From 12f08e9df847bc05617e6f74d5efed03057195ec Mon Sep 17 00:00:00 2001 From: Tobe Osakwe Date: Thu, 9 Aug 2018 10:13:17 -0400 Subject: [PATCH 01/14] Initial commit --- .gitignore | 13 +++++++++++++ LICENSE | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..7bf00e82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +.pub/ +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f8e6088a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 The Angel Framework + +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. From 7b6ccda2375283547215950edded519a0779b696 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 4 Sep 2018 16:04:53 -0400 Subject: [PATCH 02/14] Create Runner --- analysis_options.yaml | 3 + example/main.dart | 19 ++++ lib/angel_production.dart | 2 + lib/src/options.dart | 43 ++++++++ lib/src/runner.dart | 200 ++++++++++++++++++++++++++++++++++++++ pubspec.yaml | 6 ++ 6 files changed, 273 insertions(+) create mode 100644 analysis_options.yaml create mode 100644 example/main.dart create mode 100644 lib/angel_production.dart create mode 100644 lib/src/options.dart create mode 100644 lib/src/runner.dart create mode 100644 pubspec.yaml diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 00000000..eae1e42a --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,3 @@ +analyzer: + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/example/main.dart b/example/main.dart new file mode 100644 index 00000000..f7a89c3a --- /dev/null +++ b/example/main.dart @@ -0,0 +1,19 @@ +import 'dart:async'; +import 'dart:isolate'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_production/angel_production.dart'; + +main(List args) { + var runner = new Runner('example', configureServer); + return runner.run(args); +} + +Future configureServer(Angel app) async { + app.get('/', (req, res) => 'Hello, production world!'); + + app.get('/crash', (req, res) { + // We'll crash this instance deliberately, but the Runner will auto-respawn for us. + new Timer(const Duration(seconds: 3), Isolate.current.kill); + return 'Crashing in 3s...'; + }); +} diff --git a/lib/angel_production.dart b/lib/angel_production.dart new file mode 100644 index 00000000..6488127f --- /dev/null +++ b/lib/angel_production.dart @@ -0,0 +1,2 @@ +export 'src/options.dart'; +export 'src/runner.dart'; \ No newline at end of file diff --git a/lib/src/options.dart b/lib/src/options.dart new file mode 100644 index 00000000..9fefe060 --- /dev/null +++ b/lib/src/options.dart @@ -0,0 +1,43 @@ +import 'dart:io'; +import 'package:args/args.dart'; + +class RunnerOptions { + static final ArgParser argParser = new ArgParser() + ..addFlag('help', + abbr: 'h', help: 'Print this help information.', negatable: false) + ..addFlag('respawn', + help: 'Automatically respawn crashed application instances.', + defaultsTo: true, + negatable: true) + ..addFlag('use-zone', + negatable: false, help: 'Create a new Zone for each request.') + ..addOption('address', + abbr: 'a', defaultsTo: '127.0.0.1', help: 'The address to listen on.') + ..addOption('concurrency', + abbr: 'j', + defaultsTo: Platform.numberOfProcessors.toString(), + help: 'The number of isolates to spawn.') + ..addOption('port', + abbr: 'p', defaultsTo: '3000', help: 'The port to listen on.'); + + final String hostname; + final int concurrency, port; + final bool useZone, respawn; + + RunnerOptions( + {this.hostname: '127.0.0.1', + this.port: 3000, + this.concurrency: 1, + this.useZone: false, + this.respawn: true}); + + factory RunnerOptions.fromArgResults(ArgResults argResults) { + return new RunnerOptions( + hostname: argResults['address'] as String, + port: int.parse(argResults['port'] as String), + concurrency: int.parse(argResults['concurrency'] as String), + useZone: argResults['use-zone'] as bool, + respawn: argResults['respawn'] as bool, + ); + } +} diff --git a/lib/src/runner.dart b/lib/src/runner.dart new file mode 100644 index 00000000..3212d4ca --- /dev/null +++ b/lib/src/runner.dart @@ -0,0 +1,200 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:isolate'; +import 'package:angel_container/angel_container.dart'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:args/args.dart'; +import 'package:logging/logging.dart'; +import 'package:io/ansi.dart'; +import 'package:io/io.dart'; +import 'options.dart'; + +/// A command-line utility for easier running of multiple instances of an Angel application. +/// +/// Makes it easy to do things like configure SSL, log messages, and send messages between +/// all running instances. +class Runner { + final String name; + final AngelConfigurer configureServer; + final Reflector reflector; + + Runner(this.name, this.configureServer, + {this.reflector: const EmptyReflector()}); + + static const String asciiArt = ''' +____________ ________________________ +___ |__ | / /_ ____/__ ____/__ / +__ /| |_ |/ /_ / __ __ __/ __ / +_ ___ | /| / / /_/ / _ /___ _ /___ +/_/ |_/_/ |_/ \____/ /_____/ /_____/ + +'''; + + static void handleLogRecord(LogRecord record) { + var code = chooseLogColor(record.level); + + if (record.error == null) print(code.wrap(record.toString())); + + if (record.error != null) { + var err = record.error; + if (err is AngelHttpException && err.statusCode != 500) return; + print(code.wrap(record.toString() + '\n')); + print(code.wrap(err.toString())); + + if (record.stackTrace != null) { + print(code.wrap(record.stackTrace.toString())); + } + } + } + + /// Chooses a color based on the logger [level]. + static AnsiCode chooseLogColor(Level level) { + if (level == Level.SHOUT) + return backgroundRed; + else if (level == Level.SEVERE) + return red; + else if (level == Level.WARNING) + return yellow; + else if (level == Level.INFO) + return cyan; + else if (level == Level.FINER || level == Level.FINEST) return lightGray; + return resetAll; + } + + /// Spawns a new instance of the application in a separate isolate. + /// + /// If the command-line arguments permit, then the instance will be respawned on crashes. + /// + /// The returned [Future] completes when the application instance exits. + /// + /// If respawning is enabled, the [Future] will *never* complete. + Future spawnIsolate(RunnerOptions options) { + return _spawnIsolate(new Completer(), options); + } + + Future _spawnIsolate(Completer c, RunnerOptions options) { + var onLogRecord = new ReceivePort(); + var onExit = new ReceivePort(); + var onError = new ReceivePort(); + var runnerArgs = new _RunnerArgs( + name, configureServer, options, reflector, onLogRecord.sendPort); + + Isolate.spawn(isolateMain, runnerArgs, + onExit: onExit.sendPort, + onError: onError.sendPort, + errorsAreFatal: true && false) + .then((isolate) {}) + .catchError(c.completeError); + + onLogRecord.listen((msg) => handleLogRecord(msg as LogRecord)); + + onError.listen((msg) { + if (msg is List) { + var e = msg[0], st = StackTrace.fromString(msg[1].toString()); + handleLogRecord(new LogRecord( + Level.SEVERE, 'Fatal error', runnerArgs.loggerName, e, st)); + } else { + handleLogRecord(new LogRecord( + Level.SEVERE, 'Fatal error', runnerArgs.loggerName, msg)); + } + }); + + onExit.listen((_) { + if (options.respawn) { + handleLogRecord(new LogRecord( + Level.WARNING, + 'Detected a crashed instance at ${new DateTime.now()}. Respawning immediately...', + runnerArgs.loggerName)); + _spawnIsolate(c, options); + } else { + c.complete(); + } + }); + + return c.future + .whenComplete(onExit.close) + .whenComplete(onError.close) + .whenComplete(onLogRecord.close); + } + + /// Starts a number of isolates, running identical instances of an Angel application. + Future run(List args) async { + try { + var argResults = RunnerOptions.argParser.parse(args); + var options = new RunnerOptions.fromArgResults(argResults); + + print(darkGray.wrap(asciiArt.trim() + + '\n\n' + + "A batteries-included, full-featured, full-stack framework in Dart." + + '\n\n' + + 'https://angel-dart.github.io\n')); + + if (argResults['help'] == true) { + stdout..writeln('Options:')..writeln(RunnerOptions.argParser.usage); + return; + } + + print('Starting `${name}` application...'); + print('Arguments: $args...\n'); + + await Future.wait( + new List.generate(options.concurrency, (_) => spawnIsolate(options))); + } on ArgParserException catch (e) { + stderr + ..writeln(e.message) + ..writeln() + ..writeln('Options:') + ..writeln(RunnerOptions.argParser.usage); + exitCode = ExitCode.usage.code; + } catch (e) { + stderr..writeln('fatal error: $e'); + exitCode = 1; + } + } + + static void isolateMain(_RunnerArgs args) { + hierarchicalLoggingEnabled = true; + + var zone = Zone.current.fork(specification: new ZoneSpecification( + print: (self, parent, zone, msg) { + args.loggingSendPort + .send(new LogRecord(Level.INFO, msg, args.loggerName)); + }, + )); + + zone.run(() async { + var app = new Angel(reflector: args.reflector); + await app.configure(args.configureServer); + + if (app.logger == null) { + app.logger = new Logger(args.loggerName) + ..onRecord.listen(Runner.handleLogRecord); + } + + var http = + new AngelHttp.custom(app, startShared, useZone: args.options.useZone); + var server = + await http.startServer(args.options.hostname, args.options.port); + var url = new Uri( + scheme: 'http', host: server.address.address, port: server.port); + print('Listening at $url'); + }); + } +} + +class _RunnerArgs { + final String name; + + final AngelConfigurer configureServer; + + final RunnerOptions options; + + final Reflector reflector; + + final SendPort loggingSendPort; + + _RunnerArgs(this.name, this.configureServer, this.options, this.reflector, + this.loggingSendPort); + + String get loggerName => name; +} diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 00000000..4d5c9494 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,6 @@ +name: angel_production +dependencies: + angel_framework: ^2.0.0-alpha + args: ^1.0.0 + io: ^0.3.2 + logging: ^0.11.3 \ No newline at end of file From e0f0386170a6bee989ef08c15e0e5192156899b3 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 4 Sep 2018 16:13:22 -0400 Subject: [PATCH 03/14] README --- CHANGELOG.md | 2 ++ README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++ example/main.dart | 5 +---- pubspec.yaml | 7 ++++++- 4 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 README.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..1d229054 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +# 1.0.0-alpha +* Initial version. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..0283752a --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# production +Helpers for concurrency, message-passing, rotating loggers, and other production functionality in Angel. + +This will become the de-facto way to run Angel applications in deployed environments, as it +takes care of inter-isolate communication, respawning dead processes, and other housekeeping for you automatically. + +Most users will want to use the `Runner` class. + +## `Runner` +`Runner` is a utility, powered by `package:args`, that is intended to be the entry point of your application. + +Instantiate it as follows, and your file will become a command-line executable that spawns multiple instances of your +application: + +```dart +import 'dart:async'; +import 'dart:isolate'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_production/angel_production.dart'; + +main(List args) => new Runner('example', configureServer).run(args); + +Future configureServer(Angel app) async { + app.get('/', (req, res) => 'Hello, production world!'); + + app.get('/crash', (req, res) { + // We'll crash this instance deliberately, but the Runner will auto-respawn for us. + new Timer(const Duration(seconds: 3), Isolate.current.kill); + return 'Crashing in 3s...'; + }); +} +``` + +`Runner` will automatically re-spawn crashed instances, unless `--no-respawn` is passed. This can prevent +your server from entirely going down at the first error, and adds a layer of fault tolerance to your +infrastructure. + +When combined with `systemd`, deploying Angel applications on Linux can be very simple. + +## Message Passing +The `Runner` class uses [`package:pub_sub`](https://github.com/thosakwe/pub_sub) to coordinate +message passing between isolates. + +When one isolate sends a message, all other isolates will +receive the same message, except for the isolate that sent it. + +It is injected into your application's `Container` as +`pub_sub.Client`, so you can use it as follows: + +```dart +``` \ No newline at end of file diff --git a/example/main.dart b/example/main.dart index f7a89c3a..11d13736 100644 --- a/example/main.dart +++ b/example/main.dart @@ -3,10 +3,7 @@ import 'dart:isolate'; import 'package:angel_framework/angel_framework.dart'; import 'package:angel_production/angel_production.dart'; -main(List args) { - var runner = new Runner('example', configureServer); - return runner.run(args); -} +main(List args) => new Runner('example', configureServer).run(args); Future configureServer(Angel app) async { app.get('/', (req, res) => 'Hello, production world!'); diff --git a/pubspec.yaml b/pubspec.yaml index 4d5c9494..c3f215b9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,11 @@ name: angel_production +version: 1.0.0-alpha +description: Helpers for concurrency, message-passing, rotating loggers, and other production functionality in Angel. +homepage: https://github.com/angel-dart/production +environment: + sdk: ">=2.0.0-dev <3.0.0" dependencies: angel_framework: ^2.0.0-alpha args: ^1.0.0 io: ^0.3.2 - logging: ^0.11.3 \ No newline at end of file + logging: ^0.11.3 From fb1a02fa0873a899d45c3452d4f7258431804e90 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 4 Sep 2018 16:14:05 -0400 Subject: [PATCH 04/14] Update pubspec --- pubspec.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pubspec.yaml b/pubspec.yaml index c3f215b9..3a931fbd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,12 @@ name: angel_production version: 1.0.0-alpha description: Helpers for concurrency, message-passing, rotating loggers, and other production functionality in Angel. +author: Tobe O homepage: https://github.com/angel-dart/production environment: sdk: ">=2.0.0-dev <3.0.0" dependencies: + angel_container: ^1.0.0-alpha angel_framework: ^2.0.0-alpha args: ^1.0.0 io: ^0.3.2 From d85a095c109735b0d15a49661526a4e0a5d3b142 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 4 Sep 2018 16:16:01 -0400 Subject: [PATCH 05/14] Add screenshot --- README.md | 33 +++++++++++++++++++++++++++++++++ screenshot.png | Bin 0 -> 81025 bytes 2 files changed, 33 insertions(+) create mode 100644 screenshot.png diff --git a/README.md b/README.md index 0283752a..d95ad8b6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # production Helpers for concurrency, message-passing, rotating loggers, and other production functionality in Angel. +![Screenshot](screenshot.png) + This will become the de-facto way to run Angel applications in deployed environments, as it takes care of inter-isolate communication, respawning dead processes, and other housekeeping for you automatically. @@ -48,4 +50,35 @@ It is injected into your application's `Container` as `pub_sub.Client`, so you can use it as follows: ```dart +``` + +## Command-line Options +The `Runner` class supplies options like the following: + +``` +wg-dhcp201d194d221:production thosakwe$ dart example/main.dart --help +____________ ________________________ +___ |__ | / /_ ____/__ ____/__ / +__ /| |_ |/ /_ / __ __ __/ __ / +_ ___ | /| / / /_/ / _ /___ _ /___ +/_/ |_/_/ |_/ ____/ /_____/ /_____/ + +A batteries-included, full-featured, full-stack framework in Dart. + +https://angel-dart.github.io + +Options: +-h, --help Print this help information. + --[no-]respawn Automatically respawn crashed application instances. + (defaults to on) + + --use-zone Create a new Zone for each request. +-a, --address The address to listen on. + (defaults to "127.0.0.1") + +-j, --concurrency The number of isolates to spawn. + (defaults to "4") + +-p, --port The port to listen on. + (defaults to "3000") ``` \ No newline at end of file diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ece271301d6e0ead91626684c93dcb85ae6de0 GIT binary patch literal 81025 zcmdSA^;=v^vnY%Of(HvO0Rlk>2|f%E+#zU!2e-l9A%x)WK?1?uoq^!)t_iM#4K~2s z?7h!D=REh_-yiVJ(?6`$-Bn#x-6gBKCR|NL78i>G3keAcS6)u)JrWXHClV6M=yUWx zJ%@`v4@gL4g4U9fYVwkjbZX8H7S?v=NJzS&$saH@i52Tk)5p3JT*lR%(T9Zg-mof; zZzia}K#u?M6-~VhN&lHT7d<^n@K^c-#y41bX3~A)=w7JBH%~WWdmWee-?Hx-TU%R8 zTZL!Yk*KhKR9Dlby$sxpdtO@+&skL$$p$zT?Lr2NhiC$ac!5d-%ga=BJ2!B#k>7NI zjq3o$CbLHmIO5}edwY*4a$q^Z@h_57@~F)fq}*g+&maMk@$QROaaSp_;F_-~f$>pq zz8ZIP9JhsNHC7Mc@o((bG|fp?iy(Qj5{4gRBf(M(+tsr>zfv8t|A+?lj)N+y-x!0G<>d>0?H_ANqs;p$xAtpwL^pT%{tpS}J?fMaRAhR4^mG3R&!)$nNf z?UR~DPab+yYFGau;NG77g`S1qx15fdm~2PYBuM`2;1YrdCg9}wG3i8@pqS{$25?($ zg(E9oNEVs4_WKDQz5H0C#LP+v4cJCW-=3Ej^P zk1=4Yex!sFSPY((lQG^^AZYVhyc`VaI~~%k$Jknyr2k1h844jCs?jDcV}QEpoWOI$jH*Z59HrE&t7x&=tRlv^=04cc0@Qf;A7ZJnIEiqZc`LreWmy_$j9&)r?3X) zgsnKt?4&>6s~RvMbRU`k0YmhIFN{&JB{J#m9dL{LN=OiLOBb_Zel_{21GEkYkJfih z)ZU1*9MTJZxBxRNt{e7TjQ3aX2pjRWXYIvIn$)F4Fk@^)cy##5;;m@LNh2ueD-{Ak z5qo7j%25?MqB%4=T#m3oC0OSs(2JA?yk$>0h8~f2mxUb9ueUS3%6{MGxnpJ)Z{TVR z-B|kAxdMhByl}bMcuQD2P%?-t{v9sBLHuE5?oMtn=Pr{es$7y^3kkgJEt8P%Zna;5 zfv!epiN#8(CD@U{+!Ag#V+aYzE zz&EHQn-tBMr@`oFFM#M1;`n4pRq?v%XtdoxT{PPlXus&_dy#4+fN?Jvk%uH$=3a!}DE9_Y^8@z_#{yg%@b}M;C!{{kIE7dDxR}^7vzn2C< zmC|DGAmR|oiTr?1U&&OW&}48;gPr3ntSfQ))5JVU~_)j%ijE zcM^q5ndI?LC6h@2CCV8a31!1aW^rcU&oa##&W4pl7TcDUTiC zLjkR&IQMg|eQr-4M&2aedTu42Pvp{M%4DcyyyR8f?%d4c z;r|(9L2B7#5^Etgu-*?E=pOt&{%a_{+bPjBjcAv6uYLzO_@RGksHLlK%)FPR-|b6T zvTaOex?ZM8ph#?6yiZD4kZj^W4s&c#_#P^Ns0z>Fg~KZ-!@3tp1!USO*BR++;A{Ip z|A6-(|G@XafI^JIiULCMLg7HU3a1(?Rl@NL{C=kyPiqd^#T?Tw1(ICJkW+ONv25gjMd1C)+m-&yvAhtM8slHPTL!@*l#>H7nkh zu@@g#>X!q5{4D-dkx+0UMUr1y=B?Wx;U=vt&++c0aGBIi9wrWBJLGMXcK3mDZirTP zS4m7a7jqX5l^s-iNw_FQsz(0MDuo&9iLWTa6RzuH(o_P+wX!B!d0NfZL|PTSZM@ID z$L`pVuaM8=YM(l()mT}%cV?&3`TTDG+K;c(%3 zVeDw}=<(=yMuz~Y0CVPoUf0XQmn|{d?5j;~h?YV_(C8YUV8PUsF_98CU}+uGmNJ!szk0d*a=9{sQ^w0@V4-4+Q^ z%wij#n}Q`A{iF#Iz4KvOBVK#IhJF)q9K8g0rG8$3TJXwLhO!$J7;Ej>Yw@uA{c^Xvzdn&vlQ;*kCXIsekLcR@%Yc~TWPVn zu?o5Er`^|FTJOI_)K|LRUGW}>@wW2_^O*Bs^DNW>>x5%QXaK-Yub+ETI*sqITM`!& zUom62)H}1POl3ug@MYV^>tzmPrpDhe1OzK>dMZC>m_AKeb%m#9iT($#&`Sk(5`B^nd_Hq0HWPf0wr+C?bELLuwmelKNAU|{ ztBw$E&zWP35sqZNxu#Gs>4r&jqB{0m|NQs{tW89F@BM<$#Fe39hxcO^{QV6;;Ea!0 z)Yv<2O>Qb}x_OCsp?;ET9(Xf(^UHJODP^Hzyy7v|j>fGay+PE=?zXwXps3>@yg%_v zk&PiZq>+X*6%s6!qJ zT9*jxPL%{pngTiu$J?>IVQzvpo+oaZ%P01p=T)@-v^}Rj{|S!PrVO6)i}4DnrMPp1sr_y z$j*6Ccxt`lI1*X884)A)uV>co|1Ei_7b)gez34q^q{(u?2eh4+AnD zee1~ETgYYT6C0~g-u(Cp0wMXf;UG;tL;6Cqtx{vjECAP18{9#aS&xY$z9R7dtRS;u zQeQ(a=niBH3VRnaoxmFBnQ%`tMwP|bAs|VhkdkoG;QbBPnc|qty*mhY&Ryo z^1~K%c+TDetu-xyHdyJH8I&K;bS?DO8vU*7>;~)rP~#o4W7pM|<(>4SHqlG4qR+xL zss|QfX4sFSnAD0Je_98lgq$qIDbl+58%OqHmfLr7&c#M)Fk})Q2SLz-Vz058siw3m zSm~Xe+P4vjL`jPCVN8WEEh4v=wAVtfeTt;0L^Cox%7G`^-YznhyTU2ODFiU0^I-Xz2kxIlHFabV)2L)$?xP=oz>F3 zs$GM&4{LgtF!VL$J3aTN9_Y97igrDtn=?aOzspBBt_RKRTW$VizEt3-!;qEe)tlV0 z)0+1pw(#M^nxZx8*qjD;knj4W){Ma-(R$f}?6J>zUh#&dxYG+>!MB>{Jcr5GT<*=( z;ebAY83v*J!~89W*w~U-KVOfhjuSzfc8i}TpUin2Y!)QAnEN2fjkCOt8I(t{?C6rT+xh3Ya|>*ZB6PMuQyC@VYT{M*Krk7qiv9HP_7%Po^T#?RC0=N zyLPGZnA^zTv1nd!GrD^6y*c{vG8S)wze;4i4}{^D^t}B&()t9Q!Iv$;q)4}C+ zZhuf#yMDnOz-MUFysCbFfMqndUe>o@ILBq!)E@uk*pSWRhfT-n%Q@Jb=_%XW;{eC{ z^YE{*KLyqJ!=9!JU*!Rc7|kElsJnx z-Z;{oN?vYuf=>+-lpO@u@hww64zbZfkVN0u05QIGVRaraV+EfKo7R9ryX!LyM698U ze@?Jim>*^)K3w7HB~0{M_9_^WH$^x$U11)wW64&@mZR-6U&8;TY0n4+7(AMrS}lMT zIV_`?+s5srYkkaq3TUU5$f$ldCE=CLnqj5LAuFj|CkKzHOz%v1mCBtxl)9869ikN# z9d4iH_a#5JF1{?IEvo2iQy?H#Opi{BOW`Y{9o zLc{9_{qMec!EJe^gxV!~LPmWbl9ge}AH!Q0z(Tm?{lyj)+Kr7lF`bpwG!>vp1enWS z(8_hAxvO_YbI^6Pd~$Ud#d69f-Ol{en9XB%;S~SE_=MqF&_36p=h#79T?uyLh~7ek z==Z@pNbOB`XYZr;sppO1`x@EYJurZ^$^<$B!tmAdU3koRAVRH2l`wXhj5qFh;VP%M zKgE?*y@RS{M!G#(8C4x|OYniLLB!^*F!vX>U5RoZDwox>?o!F2^Kr~P%*Zf3BA3`( zrUT~4qH3A~rDr8#G0{b$s#QaS!;I!ER0GtsASY3gEi>boDVBSUSeKja@twY%BjWvR z6_F6JO!c?wKiySM+Yg`3MMe}%o9FHL2GkhjwJE7f6#tN*m)|OdH<->X*cj>?L0G&; zVAmxg9UkOI`llod_Bbyx!9KdsY_Iz)teV27FJvRef_T+*UpL7h9%Y&vz8< zxkC4`Tb{O1bHa`d*C}^>vc%{gQ|=9}q;{2#nMWKV+4%J?A(zqMGUH^VLFo&nfi1bL zXLNg<36|>^fuSf!w)9BXrAQ!cT;qHjq-QjbF8<t$y2M%{&}vS>64x#**BI`#?#l?__UuPvRwqTHF4g1n3=OxgIr|7FMD*wt-kpF;sX%}xeEjMraSv~vgccPh`ble zt}JQnP62e-YUBdco%G1R=XEOgWbq36VeZqV3mnj!V)%x(ll_C&uTmx0VsvEF&00ab z&RTVod|qhL*qOXFvsRN8^i#li+9%?aS#Ok*hNJdQ_c^-lbFJK*@`8=<|@~qmATfDUN?{^MNPH#vV`(hs+F<<|GP_u%ze8&`rSi;cB6x$uYf+uK z(3Gj_sjG#ENv5OQ1K}g`gEERYWTj-}5t`4htFvwxZ#N3$r>o;pJ_o9I*7> zAfHfxo7QUL{ZIv%n1Z2=jV6lqgs4SqL2D930BIt-ww*u|3S7G_5z~L51p&^i}7BDZ94Qnar$OgFaCP zKe2lVo(hDDHrwlRi{mQh(>JI0j?12n#wvG;{Wpq=5^M&xEJqcTV*ZtO6Jk;2{=!|j zj6qD*$RIiz;=rR^BHzI0acE}9@!#JSliwrp_S`$7`C`(@Onp~UV=1Is&0V~~qKIkL7y z`DVnV&MyG{hO|I$$!jzZYsFT@*9xhFvqPP6@XD@AtGuKitECDByM_J+s9~#Gly0|f zF0gdm(rA6XJP#sUO&$`8fmUrLMJ5{gIV4?3J9E zQe}A7P}f zLiQxyC%(V5Q#@xV8`!^wtM=r`yQ;Wm9XXwv`c4VNiJILzyWAd9mc^$x#hX$>6PeT! z6E-~{fLhl2JU*NhEsYaA758~ zskp9SsU)fNGZ6RyFfdxF-e|rig3a9R%_&>Wm|PCeKZL;tN9<{7UnFxPrA>{EL4P7` zsvuX#*R`~0x3;vXe_^C_K(fMHzT2>bmw$hjdwcTo@CB{h!wmv}KxGt}{5bul`x*%e zIon!O*Hu?pN!ZlEp3}t4;gdP1r@iB!I|d{qpr`PkM|*Qu6FN_OJFtterzrj3Glc&< z|J4nkr~7+~tF0)#uCf}Pq=U0L9UtdgPA+;779AZO(AmsF_`Q_Oe}Vsb6Q#Fub#)X5 z06aWAI6Zhd9h@xz+(JS^04^Q?4-dzm85}NNU{@1Q4zLTuKS=&B9w~DdQ)g>OS8E3_ z-CuZ3J~_C#iqg~nwa|b6{-M*{)B1l_0=xVdTYne?{51mL=HvqWH|{^6z`uHh)vP_u z?R2HA?aje1f7SqT^Kicf{tfUSL;thn{{sE+KcE8K{Qn#Be~tVXBoOcy2mgzsf5i27 z?;m-Auz-O7mOTh-C+yR2BqVVpc_|4^Pvqk)%x}bfcQ*kehU_;SVa0FWc#8M((!A+q zkYQk=;U*xA#-btMvuP)p5|_&VO(2o~yDSf#FhqTd?CtOK8x&NsS6C?YUnBKLYDNq% zL8=q8V0#CT2_@+0@$qTZ?Um--B~S}C+f-(mW?ANg#6(Dk{QrYy6^`co@%N7zpe2to zud%x-3ZwY{+s4wwe~?dbY-yOr_0tM1-PV2of+iREAC0cI}W6|r0HB%Nf zss9(#U$`fuFzW}qbQLk5>XW?qw~i7u82(L8a@;`{v^chv$lrH`tB9){+-3g_nK%j` zT805#xzMw(88iAe+Em#8N&er9K1a)teoCQA7_exD6iri&U`x{hSQ42f02got|@0*f(=IW2Wvb$X9it zpI&Mr4-xtg!vD}GK0+5a9{67PUPU$s7c{d(Q7)fsv^1|8qDm(6?`JWHEJ*WNW^F}I zQr4#CvoG&=)L0*^6^5dg+xs$(bp%h-Hq52|4nFdfuuoS&=dZicir**zt^Hcgpji zt8hm?yK*N3aJ9m}ZF(G9P(Ri+qX?MidT7!6yN#7k6^JN>&poi<)fV$I|C~FxIs6(5 z9uWRFAt7P*GQ8k-OtNazT=5!Xp5ks_=9imKlgO+#WuE5L;>Qw*?@SQFEI9?F*H|n5 z+wzmmXz!`f6zU;T$M4Ozqy^(UJC^z6=5-~~xVD(4nX;87Vf@FQeoKx2AN-3;K4&Bn zjIdl$>lkM+q&0NGo#`*j`D~t!xBi(LVAw|Ir<)Z-HoLyK=v8~|u9qVJpQ;v!_K`ox zEJQMV5o77|+`$Jd8%o!gJ&o9hGa9KwbjoQpzZ)>8;Rg@fSa0M~zpfKGE0I+}a~o&l z|7}Cw0#I-16&ePsi&2OwL@aTq`W*Bi0g(GyOVG zb=Rzyk}bW{>R+W3M~(KLd^LPQCvIJJ@AXXrd4`EwVTTC*;e(Di=8MNp!ftmiYR^4i77}pBoE|W71Of)T+cDR=QmyJ|T7ylUY$K#&& zU(7JG-qb2;7FK#MWw4+fL`7#Y+d4GivKNU2CMY2!8Vy^e%)pcy0xh`A>gkQ=wGD8d z9jTKjQI~&H+@KU$x~Z<%oUBx!-0pl|*%7(Z%I(nT(q*lHut#=OMVq~`XjV|V**#t@ zY`VoNV>OzhR@hQQ^1ZtQt#|f1#Rj@&S{P;_STcG67>qQ-@ll z-VRT4d5z!DV5P-g$>`j*(V({Rw6PQB`phihU}0ij@igW2`vq~GPO4C6;@;tw1Y5nf z4uhA;iG<0|mM9I>PWe>gMBV;X?n|n4Z{84Z`>BZl41no}u;PULcQMXF?)}3Q&s~~S z8#xVTk0i}AR{f+4)~o)g;>~74A;V^ZQjUM4p>q>^G1!&jiuHK4#U(5jbZ_O{RJj&2 zHZpR=$&<|cuO~51T#;VQ;KPTOr#9S;M|hkh-rZWEa;AdW1qIT~W-61&nOW+Za8+v# zyIiHPhjZ-FJhPSna^4S$K5mtIRWT7ji=M^8|xYW$B_6Oh}nlHB`;CRBOm%C$`y}WDBEP{;=i>U?A z+1gI(D~B3m74oY5omXT=!k1fCyyj1Gs&@c4*i807FNhtIN_g`9;rp# zAC|^>aE*EXon<6U;zrKi6b`*?s8}vS@OzB`UI*^`L`+~hkhLOth2KyZ(2UBE7O8=a3e<^|^GzIoaI;h6unA0Kg$qm!*h zrI^YmqyWi1z#~OdRtis^^Or=Qd7RaSgc($SRPtvWgYpQW3sNWTdV15E=$++Yzex0q zl`ana(iLG1{+8=9bJ1^l)MaI5ZL;*&Eowyn1UW(d^k-Tt{I?HB)I7eucW=i=hJrd( zX&1_#&zV0+N}Fbp#{6$vF?sR)4^au0@d-y45I-+6?3~GqxTAmFi?s0I%ivv;g0q4)nwP{O=#gjqIp$iTc-7atc zK6F7z1e0muu7x$Ph;A>iz0(op6dgKrN{{bF@-Iuv*r&En*{0mxj-$5RKFezpp7e~2 zb6}TJW)00LYg`Yzl^Nb>vFUI`lim&+RU=7j(8}y-86jthpq#8o6WFbx+bstxw?V&5 zM{>&aO@3GR`nI60_mVE4uV>%zQP{bmY`zA)HvYRptNzBJr{+}~*&H>|kwbTk>bc`N zuV;sG39z9&`ik^O%|pg+BWP;`&clW6M5bMnZEs&0#V*oJg89c*FnWHwf0#a?nEC}})xfZmPs zTn0Ap8Q;h3Rdyn|II{l9bsxN$^s;pNc)u)pD|^S?ygR^gdC9bN2VK1t;-r8x`XjbI zufQ{BZi$DmgkxU{TWjsq)XhYM4~7E-LUw21-WSgh({ppZT+p8-_k&Pz!-u-6qfYM1 zXH%9zRR%&+gBS_d0(Q99JB^Xv9+#bv`3@rQ#}&nfN9Wi~49Gh_W*h9?YpvCWBDy^a zo-G2xL0hpOH}ahIxL)pmMqoc(#2!?&PV{o#xm7Js8es4)fI4DFUZbxHp&pvhQV;8L2?Wu}B3kZOds{@K~7`V|C6 z|5aO16?|vsc4*sLu+)h3?p=0BM~ol^vm4D<{dCiIu~{>4|2l(KlKnvAMd>6?%EJ~X z(8!;@KL@nv6UhF@A0QeOHzao|;oogdz*ZLg37S=@W_zaa--aWNoXI<-rDL}<6M$ae z!IiA#w`d2kZ_y%#e#oS&_ed(MMjmZCTUpEw-ASpSfhjQ%cILVl@C(i+>K;pf1&+xP6 z`waOwNZBVyokN`Mk$BPLLQeZvu_p-r(Un&Hit20eg$b_>jt_9!Zvl5uX$a-GplQIU z=P^j=dLYMQ_3P;co6!(sRSW-TTOQMyl)ue*?k}`FeA<%e@4enhh;(5dkIF;OT3u4U z6Xi9wR0m`}0y2P~g4vK??HujpbIew*7}Woyy$QY+3n> zP&6UJmcuF3EQo%PbIqF5dR4w~&cXw%D%YnM%iDUBZQfuEhmmf+Lo?Xu2w&1`WAn+7 z#S6QNbXWyIbT#b|;2v;~TO%pkZrDg17JgFI_U&Mcyzj5b;ZM-_aR{y*Bh}!_pi{ZJ zSKJ19d$95$yS-bh55(ZIEvmb5>WYwP*ryk|FxNEqb};*r0K61OaiqviL=X-(J41bY z`cpfp5Xv$7RKCl1g1US8ewJ2-L%0k<3QH->oC~93$3m0tyK>`U$JP9u%sc^)zr_$c z0b7Id0>ZX}@%-nO=@GDmyi4o(>Y*(W+Tl+Ft>&JJ^JCD{J6^nl6#}gy+AwC$&gT=N z2xOUKxT&VY9bv%J0K)MhwCUGRqHF2CbXk+%`y*$Qqp{~*(miUOLb{OS=!531cpcMD zlKJxU-fu7vtriL8dGE=L>4HnG9}|D=M|-^++Nch1`el4!;*fd2V1B}Co+G78zX10{ z%ea)&xl2un6PY$Fq(?Xv;2I#ID?9SuHVUeT*~ZF`!TfI!@TqWt%= zboaCu%gvES6Zach4Gk_0u!NFTmHz&e*B`-hdV8R8DGV&zBD~hbKatK!t+l0D__mFP z%YJG~uIBA^`~FFEO_rfixj`6aB&m=xSjdL{L-u`h#vW8*`-btrpis4TN1nE}1sH&-1v&@sGP$y-Gca_9*YY??WE z%2Jp7%bI-<&sAu2)EeOjbfg#S>he`KI(|UQs(=_B5siXIgE|U`8~r<5pzyvD z5cs6|a5+Ar=DRp27|;uXEid~^@7;09=nJCEFp2FSpDjKX=WG=!%H(PIe`>NgSWS>; zBYhxhQudxDw;g2J`=xeQlk@Z18N1YRawQYw<@b_F^gj4ctr>V@fMX#>BA}&jbnGE7 z9N&14&0{OvLp%HgF6f8uxRo?;*0D}~*qnb1`X-7R@a;TJ;K8rK(0UgLT9zt= zdye+z4hSuzJfEV53@DIymG6`^WqsJw7Q0z2q=9<#xid|$97iZ}w!94SZg5-N+ph2F z>S_IzMY2 zZ_nu3bL@_93uDI{cR!hW149ha;-ALX7tB<%U`aNMen8BOQCgc<4CCqK3J zZF`rF9cafJqzY4stPRMIpN8o|E>-~z(E=M*lAV8LxWu;z zisR@yPmiaYv^(b19UNx6w6l}4_I%|h%M?2EcY2-I&Uf1Vh7}v?Op7a_1b4MJYyHpC z9DDW%f22iixW4JpAY$5V+SA#r+2fS>kw?{6w%#Y!_C(yI+D^3Q)7bN{2OijlRP;Az zGMhk8h0?rkJZlgi-NjbFa<*i0-R0R<`!<=L!F^O^VNH=viD&^=DRh3ZbLW4`=fXFp z))Wtw?;3I6aBdvz?}-Tv9l+lo_-s@P-HwP(--I5W57y~yuId50wFn)BE-xsZMgv6| zZ&O1mjz+5gD#bDMcZ=BvA|l(M^(PKu(K^~E5iCU4vUk^2j%&CcCW8}z0ay>lud>i8)8D-tCKIwb z-QZAli<^ziknkJj?nc1+&)zn0{|q5r>*G57#fLhirq##ic%XYasybPbRl=2!0%DM7`8D?#=QDMtyp`)|fP24AAd)s^Lh8x;@ur(SoqQPc=OOXjsgzLEF^`FV|?RTT8Ie1VGQ+e#qXN}E^n+7BT1m6KU-p-1~6}TJ)UU#H=Km7Q@XCMVP$6ajeY%y zN6OTPYk6Xktn031kJTuKRvC|Izl#gAhx5?r<`d)=bJtYg2is-n+2AVP1&vo`oupDG z+E~LY{S%>DrT-iGUx+y|BNepx=h}jq859{8+zV+vmdZ|ymZjoBxUp;@FWe`OB>0mzs(2Qpfs--y|c{LwlJ)M?$T zCLT(Ypb&~(Kpg2Fk@j}02K)6I|FX8>7-`2P^8>OhPJ-ntg;u+1Wir0&m+bm{SQy*d z5o7*ou4C!@tVX4U=0OX$Ism&d`GpsDg4xTPsqyv)y`+a)<9gMn-3BI84<2!9dV?$%AlqM6&7$bxLRX z`m`-;? zKLF0rh{Zg1 z=f}Kzbh3G=%TJ5E6F;$=9*HQ2Rb=B=cP)86yzOR)+HMXbICnaxigd2LlD^~|W?fz! z7u`)lb~;B5yLtx}-mMdHDQ+aZ44a*a11`ltTM$jyF$i8*V$fWJ?TWmo${pcckSTS^dWr3T)&s23J zv1ZFkf5Z+kAiZ<@h-ouSw);|YjfC$qCVZSi7;LO#hhV+O7`peHKdCy^UFWN^oz=~F zQa04miXh2JHs)Yu?1Iy|v#_QHp4vD6N(fK8*!HY<8}HUu%DKm?g!lLn;;{7&0K~$5 zzz?`sX3V=1wM3Vbb%;P)EZSZUNDHwKR6BG6vWy+@aOt*RIZ>8)9X>vHYv#Pg`%gAD zsGK1e!P|ttm5b?`-nuLEGN~-5%X4U?U$O9U(OCm;xWkpT zZbzkK`8ej{yzvv{5$O>o;}_RqC)R8Zd30I{5OaI#@u^G7;%s29QD5V4g61^@by4x&LV5t?A#n+-PaK zBA)wioNGG;Z5>ylN+HJgs4=ZuiuitdBQyHgrIB-dfw^s+$3LJxQ%Efyz>z4B2w`WzZlXzbb|9^Lbgdz0UEi1?sRF>Br1P zyqx_LorO&Y=S&NpgZEyWPc;`^e#-X+*8$Lq9)Gd*iKQ%3^XxE*fz$9Ekv|2Sh8@qF z5ZBj>C!rQU)~Yr9H4D{tKk*7IW7&4fSU6{C1W_THp~6B@nwM)-orBiViGbD@6R~ZS z(ru48VaHS4!_Ip$quJhoY(LAAwLzg&u*I+eIjKUmirX+GSEEv6zLm!3WJU+n1Yy%1b81sq(67>>TZ87XtR*!Ji1J8IrteFj$#M|6l#3Mj|JB`RF&A8vlq zY$W;Av$<~DeB?aV0?+4L(;$5NX=nUEV-)-?!asU90oR@6T%zPb;gp03de zxc2lnhf_4zuRKy!Fa^^by9V%ZfaUx@1nQGqMER(>fOYTzLH z`w~oCn{W~z2VR{ui|{QQ-!A3d$<;qm65&`GQapWKw_+tkK7oI&*cshK34go zH9iNL79+|AwA4gt3b8<}EX1|I-U21;gCVN>Npz7%G-#yfVERA{MLDxE_o_%NI(t2k zhE0Szw3Nd^Hs{j(I0}C`wZDA3I6*gax&IPc+=#Jta>AQs6?>K?sR|R&Pr6gYvT~HHH$w~uzQ(~{+mA8 zrj4A0!alNrRz>I5Jr@eHvi6BtJlkaBxF}Qa$e;F?T=xY=rJYD3B-Hm_2%h{ zPoGt!^V?pHyqH_s0F~OBc8kH-?Z*MY)Pd0LoHG94Wy1DdhDw5E=}FQWUudnuHdP0& z9;m9X&~@%I4Ka5<-ZKvQ@W7Pq=Yzo{`apK?aYQ#U|1p})?8Z>kaJo{PiJ4y8Be*IB z+?Q%AO}Zvgz%Qc6T4NB**1x_j(V0@A7k(GN<_K2xnopVYcy#s?V{NSJdAu3xvaY>6 z*^|YMqtkx<#ENj;8x=n^3O+2-njVT3nzXGBFWSdS)Xwi3pUm^-i@Ys3 zKST`D(lPi=8LksuZ0%E92plsQdFmD>KSqPg%FE|;X zj)j6Akk%r0FflHUqQ?ce{m!D8m=gi-^WfkGklG)ok?bx^bHpDI2+~_e%G>bD^Gnw` zz|#wKizoPNl-kG@4Rm`d=9$0E_DB1&Hd8;aj^h+S5;(}zg^>n4MCic*{kVUt&!jF| z>9)U2%aQ#0IQ`&)J#E6bJwJJM2e(-x?^zG9Aws0B#jTg>UG? z(7NWw=5DVO15s@;IL7N0_Zswo3DovTU5&podUD40*&O{Pde&8uIJsB3@!hEC`4ep0 zURP(0_OY!=n&7&ta_)%hX&th89jPh<`vN$FhhGHREO~8Ty@GC0|A0UsPc+^+zFhnj zX|W}=4!u+GVSBCVn-5~gp>XEa@b!RZ3Lm$TzRVeiJ`JdA{2B|2I;9ceZHash zf^oSfLDTx1JpB(yZB5Hs3avVT86qoNR89(p*PwgZMdy*6^PibMzj`G-1`vNTxOLj# zfhj!27NJT-kivpP7v9oXt?3$tQVT5pqfCr4hs%~)=%CJ%8-GgdBDG(ed{^bJzm5>} z=P9$ZAx$>dv$hSF*Vp?=Asz^Kd>X$Jq<{=326y&bk-{ep|G~}kgWJ;r`P&|n8^H-P z+t(6OYg6^gPe}EA9vJJMr~X2zH8pM+Ni06w<0|Be*+#QiwnhQZ1J;@_{JDMzq>TF@ z2dq>R=?tO5PW*r0wcgEmOu6UePf3G&T$W#Ng&p@!@vk)6_cbPr>B2X>Jm1qK1YAit z8|ZenjtnoRXlbWxRwX+8M0h`Q&jnu{_#`+M`gz^?W=%8&{fjjFq80~ zs}zl)FMj`Ap)x9oKNX!wi7U~}sv%IT+%uGf?sM*oN83xI^&HG>OjFnFl|)~Awf_0C z+QUhb+V0nOX|r2y-SKxz9@(O9zs;=N228gd2XjC`w4TS@u5f4RD^i*riEEWiK z`_M_urAQWwYC%@Gz?H~PM z4Olz9!8iCaUb|%)xqq?k&fgH}o)f|_4v~C9cftol?xz=z=bl;@dGo!06^gBIulC<$ zVn4Co(~x=HbB#V738>I|U99`9Ye9P5Jj6a@TgW5H(NKuK%kHk%f~P)TzmZ-0VlM*i zrd}}Ap1Ha8sdV>^7jU9-=^jcu+b6b$ODY9`-wNN@hs@P9O89Ff?d0Y!?hL1X?4cuM ziJM60pI`kXSx9#TQuB{LO^7B#Y}$Kj-_IBgKMdjD|FS)o_^Bzlo2s)pHsa9tdJjSe zbH6>0js1yuQipRvTSxQpPWZ2+Tmzg@DqFVS%|h(iFnat&ku!%+yDD@HiS6n3oE}8C zCQVipR=pQo1dk5eYJA$}_x+ap7NJ$CzdH9oKR?$&Vsmi(48Ub=z1Ei<`FJEWBl+LV z2$n`&9lp=QfI>$SUc#{b)@eO!5gO08Pw?#%Pm9Fkiv-v4xkN|Z4V9P<5HIWU_{IWf zh5PRv%e`Npxf4SZD)p=rKht_ucy#xrJ`iuwwxU*vqO??8rcs<8Hgy;ZyK{W4$l4zU zCmX%lI(W4Zy*ht4H(+GCGl@%R6+^f0iylj!RR{NNw9)e55W9Qu;%izF-t;w`ZOT2; zg1H~o?-4Yg1~;T_KfIC9%!kl<@8$TP0L5@CT7M102TUK#n?8+JWqaU!`R2^+@1+zF zCJ8pIUXPk%h4@|R58Z-kqoPH0MBsy|h#cvgKpBpeMovP%R}m2(N8stptv+(fYqyhH z*++#t+7-)Ns~9_?r-kRu4?lH2g&Z?MZoNd^S!Tl)P-P7T)z{e^29$NAswnwd&+gl} zG*L{K2h>T|Lwe|2#w!v&LOu2mJP%7W)c5OC#Xd3${-v3cp&kE}(lN@5H|<;D^ieJA zi?!5)6AT1$Y)U;wqDSjzRux||Hm&eC+o{sWj}zA1)Yh0AnloGu+o!jcySWr23d@-* z)M98NNjbBtB0O0f)`aUH7mlpp>pp{sV@QlwUnkrIP9Q5N(!uJJvBLQqMm*P)kfR1z zeh|iLY!6#KnR+T+J`KBwk(KiBZcwR&xFuiA%oIR>bx>oUZCsd-)4@ru1_Z! zjYfj_-noueY%HFQY#&^46Q z&@~Jl?|A%v&pCR|d7t0&uJx|xpJy$W>&BUT-}~O5y|4X=YhMHdb;E~_1;blitV8bB za4@OcgpCL;X66N_+4E)2;Kc131H8V&y2O<^$-&$*^X^WGJiXg=q-!0@ zFv)Bfm&DJDYy3r@%;m1hGDN<@X7aQYxsm9uCqYN@XG zI{2XNufM3$STEQ3!i=(WbO;Mq2qYSer_!9`<6rAl+y#vznrAo*e&n;+y>DP(^DIy% zWzL{uoR&CUVOd_$7sYTH^Hr_@{cb<4OZdu1+G zSjYI3TjjnS$>cPvMTNr&3H7I(_~!AW^o%sBAd|){l1Y-;D|YxE$7jFqCDG*HeATRB z2HnZFLoXnOGT!Zqwqrx*JDk@p)fJbPBc2~n?zP!mA`s#e>YuJK zncKU!i)TGiqu+VQyyeLT zcI-p)i&O6F-@VVSE&iMWUWc6dEGzh#T>I31qhQ~b=wod)lY^hd`{lT$X+C%l!WFDak3RQD%Cky>H>^Ijo& zoN0q`o76j?Y_uN{r87Q}{X(Q@n`kjPkR*pSK)xk*dnVpJF060Bzb9|xi{Y(I*Ry2E z`rLlzSGr=OWv?0t3ok09=TXV(9`!%Sp$7gad6xMJTOv|h9)e-~ZOv%@No8)CAZCKqY%T3|zpwXSn)3OEYKmA8$E*jq6(~nhhllzaDNvYVr zG8V#0N$?kxYM#R&FREf7_l9ARdoQwC_ly-Lw_^+0j9rSXL;GSIHeSeFbls6~O8BqE zeqlu?lcBkUQV(G!28IO9PCB`0TC14YleaQi&dQ7M!kBD$;(VEp^)`$?cS9_(mi>GR8&YeTj=H1Ex!5S*81q2f^9FV zww=N1;MyHJFfd!!Tru#ERB{yaU_q{#KHgw{C&!Mk_zN0i)c}rt?!f4F*=zz>$69ti z3)h9O(0$#C4<6sldm|#4xJxuHw(HQ)-g=7(=2YjPU1WUz@^X^3&g!_8^`Gg&k;05< zd>^5YWvx-8vu8HwGghH9m=tn8_9Q#!Y4$@xBSiEP_{jv3_4N_!5gS?`Po#mTh| zqo_x~s~ZBW@jc@P`-`eMj_5P*GD8v!EqT$48CtXCv<;W4(Q{^A)XLF01mPErCyCxD z^z)GZ$Wz~ewZSHp(B+C^nkEBDJaTjdvFsx_vzX<2gJlMn*o#1qaXAaMf>l#KtEWat zOYLj*RePh42Uu;_6ty0WeSxVOj4j^QC=rgxyyKn+VM_Nct!g5=^6WQA9Jizvov7nT z>wDOH=s?|ODlaM&@v6^e{cz|&*Y&1a=92Z3cS2S_7)z+Z6}~a`s+mggGs`1<(f#0J zqNF6hTv*M9?Cd0UvL#>4R#_AWor2^-Z|{?(YCd)CIO3YwaRrkt{C>+b{>_4Ni=K5R ztII7GY>EpH_Q^`512)Ob<7;U``?2FOxZueR03_Kk1p>g?>eFxn*O^<84k9B4JoEZy#B zmclrFo!WI_Avqx1EztBKw00wm*tL>kNh3lW@Y3XjXlwja&J)pRGvgx(?1iV4*@ECB zHrex0Z_nG6$Pq^GedikavxU@Ns0c2g$+j5DhKw`asy}y&WDHhf@Ng!fk>$RFL4L^Q zp-a+H%zCl3>QG`h=w(KpRZ}NNQXIGHI+w74eDeiNUkXiK3G!V1vWV#N+`!9)yG)U` zN^Xa7A}KcRUnA(EuFQXDP<+pK3Ez;5^O3ZAHgpnf4Nq^}nCYG*ttqvGOMv6~m3^6+ z;r(J^1HZA<^vF#uL;9FV8~AK1P9IgSKe?*>fVkei@W4*+wpJz%$k7ST_j=2-lUj!t zC55>vtKl0n;LZfWG7#9=5W@4!8XyEbHwmx7#Q+=|SgB8H$x5yuOrSG^+D?T1JbJGcJlY#zY@5t~HR}F>WK2kiCf#5DDg3 zQsw0%u*f5RF`5Lt**UYf58fYgnM+$nQuvzN%C-j1Ase?rTxK6fM-m(hPPx5ST{Z$f z`*BNj=kyXRv_w@cB#DQ-M4sikde1%75wv zBHXK4VVxgA=zt;=9_F!f2;**kPnCAx^42q;6>a+Kro4i(n7sOVf^?vl?TUR){d;vbr+Unk+ z;)#BCR7bCLb=}E4ySES8oe9(?tQs{Va)lD#ZNha`cCi9?UC|IDchcu)miiU$=&c_j zQpvGmgmMHh?idvE@(778>&T`H-pg(u7+ap?tgXZ{8SS!{nDN0KA6G)Afe(3jO|9ha zXIiaeWAhX`r=1pJcFK1Mtxa>;^?s8KQYbT#fCd&SXu>iA#3q6ZsE$npfkK83P2bSV z1p`Jk!99KSx6g0fDg*(6Mjz!uOveslLG=x~@~#ZIHWdS!(9X4Pg0km4FC=<3q zknK8A7h0uK)T9CC5iM%NFsTo|Yt>9g25SDTrsZzw?ofi>)eLNq!`JomE{G7r6MnyB zV6l`Fan$1puX6H5G_nam-l#Ras1uf)0XoQJgTXSUn6OEXm(B;5L&rr=xb$+F&L_1F zJfN%ts%nW!X)_ZFy%t}~V|+J@ThL0kb$uJ9_?mdSNIzXy;vKlX;VNIR*Ph%Uz~_;4 z(iXD>3E086j#*Yq=9FwB458eer+q{DY~LqjLf3g^0{vH32b%!y-3Y3Vr4c&0DWXjj z$yC4|w>2;9F!c3LK!78z3MtQYN4RtJX8cDSd&k&}ax%d3;5ORq@}RX!UDuE@&gHzz zW1h2~(iAfHuF`C>+DCe}JUEd{)lv)s*B6K^q9kwlURO>MJryZ@K3Cy7qVG9VSiSe< zLf0dQaj~cE4rEiK$LbQVWhTVZiKv_Izx1&9@+GTM;nVVE;MT`r*`&HY^W(lpYIVb> zQBj{s1&wXKeEIy0^*TuL0d_jxri1bF-Jvj$f!7yyr3WDIp0~t8Ss|6A&$l__QS-KV z`>nWc{bL{|9d)w~NkHE;1(1u5G{Q9Sq+LYHy=QBlX6vZ&^aUp{pinAd=550Y6F zY*f($SXIv+Khjho;dlYyRNiQ{?0|9G`i;_xaRv*O7eB^Ns(H35^=io+>;zX|3Rd15 z89N@S&_3vUw21pudAp`lAMnIdzvnG{;^|X1ICDsW=5tAD@n=eHalLNYkcMn|+CqX+pa}Yn9g{zTYpSB4} zQsKm8+7L%EI%1cMIH}Cc&}d3lpef_&ZfCsn0+Ql+xNKzQM+Oc?H;Ll@+~GPJhXD*p zblj$=thPx`h1_o7gpUX&1Xi;DH7}Onu3&l~x0zQ|SI<<>MsQbj9KuN8=|LY}dHltt z&X-+9Llenh^?`VZKb6CZR<-iCt{Ep5Op>1FX`DfU?(=I|KK(zO@BGR8Gm zMUYwMwG5SIDwG1zNMgNv4vKX>uK3QV|MBB%BGMclWws@T6ZXlBK^%1yL3>IRC#=$} zPu!51#D7R5w8Myk?_0jP&Oe3xvOPe;SDBT@$rL5<#wCK-_o$4@V%{Iemq;>Z>x-MHqal>y zMLs2NK-f9$YtC>xwP16Xkc!QjMm8K$Bwwk=%}onurCf1h-G)zCOj<0rp%Hux)7eGY z;@+K^R0np$7r@W1OCD3#s(2%(ru(Z46J^L|px){u1;e+B;pL)5IoCJOp7laLiyo@W3JHIwF`uAQ#B!;f9vEYH|ud40ZFd{ zgjR1l_+HtRkqyfLQ7xg{E|cUrzep5IcEcup}8J zMlWLdw79aIz|C>P=kowyu+hQAahD8s^|VmC$~No>;MOI(kwqyqHtd380A$%PhBJG4 zqMs|ho5gt?nhmYLd#nJyo$7&`m6pHTlsvse7$F#DxR05o;ElJ-9E%bc!qVwHa@|@T z8M^K}-|Oqieyg!{hz{7b|Jti7`_XX>Bay`roxq!Rw>yMDFRZ+~fUBcHG1z!_KJ+W; zPHV{(z{q8`BAHwVYPQ$(W!K2#)xRaNob<3RV?};ipUt%ZKU^fw& zjYl_uYk`(~UYCQO#{d@llT+?jMemnrLd6aNthMnMMHwYt7IjDjMeE4HoX6tM8Hh;k zYvT!2MEe{-pNG({%R|UaInMbD=8s-~JmzgWB?gJNb8f}P%t~GjBUV$dL$*2ZeP0_% zx-q>={l%3Yx)58&-S=sS*SgLJ*ZgIL8h;)ZMQs9cU%W7O0q3#qG2A zJ!v@H*F3SYu^%fcDpu*9KX0e@N0LJ3;L0f$wgY)_-D%452OD+cFL1^2>ZKS|7q`2G zTBKuW^j0qHII143x{Nk&S}m9&-t4=88l`n_tGPN7H9ROkk}-PfFle(;Wf{S?6Q*al zPZE08C{c%QxI=Er{cWZ&1l(Tv6tr6-U48jMW}o&s(EW6!G+@5da8*EP{gqNAlZE0u zG)D(!!&t}%8M?J{*50U`T?@}DtI+xKe#o>&Gb{sMy+fpH`HJHG%9o3aoGLX!wIO%8 zhpRC70P8Uw`Z=+6CM0Iahks_r$3KmIhdwdGJlgbfWBvUDiJXi__Ph3*8!WxK?!a zzKRfj0*L1f%WbdARj^%(mu;uiE17;u$rA(z%gmOg{l^9)qA#wajz;? zBW`d2&Q9@caX83b3G2sg3Nz~itn%E`Z_W$h?@`CW1y0KIoC&1kmfbWOE%4nQJAb(F zU2<{V@IRe=xo!fN)bPyFm}i;6~$3NNK}^&_v>lD6qHpR`FUX{8>ZA=n&)eM7aUa z4FL|wvw2>jL}!W*02mr#T*p`NfFYw$I|JCJwd?e3`AFJv){~2t5^>aOSYoz(yOdlb zjt;->b?F4NRtlGGtUYnhvW(Rp*##_@E19=y-bZr4UCUX#|7+lmqUKN$t>Iifs9I8c zcjmuZ02`gO-zH<^!q!S1+CRGn?(?AyR;&RC=W-Dun;V;iFx)k!AD$I(ZZm*erBbXt%W2Pm{ zDKD3LhEBL}+G>_;I>70~@40}N3~mCkHojNSS`)FneKT-jb-KTOF~E8YpRHPO8Hv~L zqcUAQ&>XV7i#EYG?b3dKzq|k;9D4E%*G}r#c7Fy%VdFASD7+v&T4Pi4dVtgpy1U)h zfy_7dn1aDR+3by^XT{%yx~KA>WJq;QD-EAD*N$tX?t{U})@ORGI8F7BSDBN8q^XXZ zL-Gx6=cQcnwW4kli~V1rgf6z@(;P400%CKm zTgQn(gau|{;sy)Jm*QAGP08a@p1Updv}fTBC3o3pX93LTl{52K`}3X)Adx|Ln$yjwtm8jgM6 zqD=eBv-`?TK7`=1cxUy634F_cb~f{pDq=O`DZ(&fZK`@LDVg)EJ_FQV3SV@E#F)nL z7^3$*DM|ZGAJ#Vt{{#?H4?N3Mf}hGM_q8^+4JRbQT}w}?3)v7MXO&i~NSqYfWzZXr z=YdY^p98I)=CzKb%2+qq7YTxU*CZuOn1Th5B_`r`FI2dkWaaAUcT(>Y^VsL{_cJ7W zOo+)g*>%gprwj(FhX*vZkQXZ8cbZnSr)R{bo*f?!`|CZ2OcPIwzXxlv)TIb~V+#N- zYcCJ}GO-1YC5UDonej9u)slN7S#YTrG!UyI6VLy|8RcS*uUTL>&V|5X6JWt?D8G2| z4$rV%vFoDeI-~Ag)ZB2$ak;X9rV$UtR4Se=HzMd!RZccb3oBm+yL4OUZ2m{GF-_o* ztnk=ldC-p5`+AIf5rRUwA3T*N6lam^o7t{x>gjOKN#2R@kORCmnP#%5NDb}AXKw{u z8v}0X?q2b4o<}DmY>38s{Rb2U47J}}yHz_lZ^N^8O~W0(>naEB6m*5}ekVWn#W9|e~8+{P0+%-Gco z(~+4hWMM072$~rvstAknP}vEL7GM4Dq0)pKEx!JXhpLp}`n;=S9P~X|K5JZfPX0Z* zV;m_1sK2>ep3N|xK-~$vIw0(SJFaQUQ?uJU-d=s(c>K1-cA&F)0HkrX7`JwP@`Ud4 zoH>tBX1Nj?OG)yd2^znOw5(|E7Q=fO}8 z2eT(+caDc;zQ6htT#r|Z6?*8ZyTcJ%X;t_l#@Yc?Mq09Zkz{vcRsA_Ur{a}!Q#Ybz zgEoRgah^_E+6OFsH2M}n30ziV)vR-a*$S|>lou$u061s-rz!k2iaSHkft{rZ7dKXI z)~21&GJO!?6@5>d2?5}p;{-~F44HALijE}mLMOyrT`+KWmbG-X#=4{7-GLE2@=Z3H z1S-Z5xUgE|i9Rln%XG8ufd`*2{vKR_s)=dUp|F%HoSu~WT?D&gMHj>^3O#>DP`(5y)(vz zFzHT&+|D)Rj3i4#-w(KBGmG|ej8xmj#!_jh(FIFww^u!9i_wc2VXJSpN7I?XV#v>H}A;w9P9&Roh)`7TRC&h$68)WZLlzgs= za(s3_#I8xIanlD;G@-EpzrSoScyVL;{a*Rk3B?A)9I4@M8qtCgnQ9%Ii95H>+3zFW6f9*^;{m=3r!c-3;$$>)gpJw?Q`{bEpEGc`7 ztsIl3x|%lIaIVxp23V#Ya$)1o9Zhtw;jC2XqX zq%~cnGkKGOQoOcn0i13wMVuW2%NB;c+qF^dD;AyqT5wQkrq5c8PZ~!}kIJohR905~ zdnUYR#>tS77nKaBuV53zcl2jNQW6DCvbQNfsQ(Ch|9auODohzg6r2ziRYRP^Z>hw4 z6L=(c*~57UCb6RHB$U*1iQ|s_&(a^LYKjHsNxQNYsL;v!qW$+H;z#Duz^OIm=xnyV zN6R0RQu(;7XY7^L8{+%*VWdfXT%7;!g_*6|(!-csU8nE+>DYMK%(4VHivN)>vlD+P zA}g%B|J~)ri{oKX_r)2j{qJP6zl}9&#GMQoby?ymlM)6@EDmX^oc4RBX=LkoFSAhM z0NJAI)S4L9?sZl!`SuPuGpL{@-aPGJ%4Sj@1<~*ohIC>8$I;@28;vAqzU|$rji+KE?MKP56vB*)Yt8W$OkvcjMPV1u z#tOc6@a}&!+C&xZVgmbmJItG$F6|jE3W%%^5OUr*lTX@p{ohCdhINJ?+*;sSJYy#` z<$1 z##vhf9QRF(ezc`qlQ?l}RHe9kS;V+=(Ad(5qXs>=j4??sDFFx>xYcdNr)}G-`Dfhz zv%Lcqn#r~8I)O88b)A%H)(NHdG&g{`i50T}@!Pe&#zqph8xqjeKjXBYipHp^@50bd zpJiYrYspNSA;Yd9{@B;h_~~9IPFqS~!W^T+#CFgrO4-L5mIYt}hE0{viJEivefDjP zElLdNH1+g3cm~IV0HRyjlR*w(;QdLfWOvR}ytYu@|K{HQ+gqtu!)(s5-J1C$2nm#FwRrLIqRzQa|GdS_mQ>CzaJVVM<{2ldU~dlNR6 zJv30F!49IF-@=efsYp}O>4g4}{qd{;?r#foNWOc~@2m+&O*z+-&oBHmOh;zQyAvo) z{w8B2d~i#4t8IDOzs_o6DJ(M7y1tR5019bNNQ!*?MQquNGs|{WQ%Y~D&KB+FhYX-S ztl>TcK=5?WF}DT^br@#R=j<0q@xU~YApf-l%pU1Ou3XydT-DvP4IySWwOpXT^X`U? zQlvkPXxjZ8t&kcl$Pxw>I!yqTRo$|LIsfLWU=wB86#KE&0d*kp-(+pxioKradj_m+?40R7MFG+ z{~tAdN3OX|UbcvQ%D6auX#fwFO$~SLOVNW0Q7@KtR zd9LFBY(6}H8kv{)I`7PUucGYvo-s`f9a*K!==fnjfA1ZSvuT}&*yJDPx@T7cOSa3b z&Kh^vk55nKbsqlvs7l=EZUdGv$;Tu}yu7!~ORUj7`Pp%s)#Iq2V0mRszNrjvtrU8- zrdIYew#c^b85P&PO#DH?tqWG6fO{GNXha~{Yo96C+zZ(4eu1qEzccJQUB79hb=6dY zj0TX~rP%4A!fMmNV&#{=iR&bz`5GB8T99^k@JvW}l?~Ocg%=r#q$Hg{V6|R61YT;P zoTsN91dsT>Oj_Q*E4tBwPGCWH2axj$R3o-s@X*=o9$3^9$WX-}46s{VD;HSa7rWZ_ zTcvRJ67l>1U>4avgJ5wrEeN*WHqkzqLAyrWw|%elH<3QMP#<#9(%${7PY^dF<3X7; z1tV5nPDmf>{BUwgYpCf)@@8RtmQ9ay5el_?4pZt;?r+*=`LIin*i*J=wvD-YM7s@j z6d1TL+}mLSy;cXArJ8R&egzCv?%wRiEqi-=uO~KM^pd$`s`e`G%MjV#)j^+x=ax1b z&O1z&09?5&D-`{aC2-0$&fiEPz-oS9b;+zi&(FxF1_;os2Ud)8i9ylIl- zKoNDOeYk20dwcBHgF&ty;}~>R4fMaGrNhyq>BZ`mlI=xjvKC4-AU{04`Hen|dayEE zI;#`m_&EqOSUOu|JFaehZ%tTb_}E`I0=^^>gU5wo(yxyrXE8LW`SU3I zZc#<9u*5C<9-&fE;Zfiabg z{AQfhiS;(KJ16-^&&&1J=zi|`ZNP(P_(W%DXwoaJ52t_tCPAid^(9^= z%5|&FC~=D?DdV?1pZs^b`)}oG>&am1O`s-H=9X$Zc%k(`kchKH`6%@g8-(Y)qYrzZ zriL2KO;gTFOPs#sRIHJ4pE(ugE z11QUv(9-`8h6CTX-pZav8MSuCm%oWHBm-!|cA zkpj0YsD!4Ll&1xz{=_B@L)EQFgJKan?7{cABu?!?8PFo)-nuvM5A1^)sna&9u#$l% zJkJ(2Jb^x9t2<*=-gSq4P;Y+b-B5b0v37Qv@@FLVfon#f;XaG($aT>m3Uhc_5_O)gC|3Ieb z`Ag#%%e@`|CoBGB*(Oc3@n&e>K#J~y%=*iJc;jCN z>Ve)uelB?UU@TE!Q@~WnATL{~)_{Tnj700%4rdcc7l0^CjVL_U)}B$Bo)XN?BXi!# zC23+gH}7_^mE9pr`PFA6@kg!cFcE<`LpAHpgO$y+l())LjL&9}L%p`2KD*4wU?CJw}?(&^DQ3YzVTtd;D)cZyILxn zroMf<>xSQT=!zsOxsB#EZG!BP%LE8?DpR7M<01C!8lYmihKtvO_is^Q5^Zy{`f3ta z(1V1AbAp$8+-KBC{Fraq1kUxVb4>h-*YWyEr^l0y?2MotIXJ_R^3Mwm4Nr<3wcM3D z%T5nfDhV72tvYcfu>1N_Tf!%1V44128Yb&|)FYmdpuj?O<5c0bm|W>C zjN8jV-e^<{jpsj>Enjv0YlQLr8nxVrPI}TEq8_EIJo5I#?LF6YxZvgNv z1Q^HT09j{EWzyZVG#&VVee*7w8`vJkBU4>BfPbJ%-wetnTH-i%Ue~y*pOo2}AbUI& z4No^8CyV%XYLo>D>vHnMJO{p>U}`m;w-V9S-9DtJ_oX=BifG(!5%=&r+fplQajB;S zXaHLrX8waQxbxyljIH4bXU-z#GyE|8SmF!DpEM_&hoRtsDv=a-&tI%gP&x7ftj;EV5a;B%+#M|L5;D7y~6!bGuTQ>m1%)xwo{@(d&^C5u=ca?;|d;`_d% z%1&8SP|r}!rbJN<%~*<2!gn8tpk^uGk0Q$ZY`(dJf2kM#00WdxBzohY5b_Kh^$3y%oz9yMU+JCT z;~F{BxE0uXhW8neaYFnO8Jhp?^!6H*&Tn!lcaD#QCUWtn5;$9nV`Y{&WJx? zM(ZJ}aZctA?G)ancmD3QE{iD9TB1zKEvku@GrTfD$0fF2yq&6)iLX~y2DBMX^u@?G zQ{FRdo`z-j3#A-Eol?#GOJ&2JB74rm{=LS#Deur_5To%P|7 z>-#Nd#G_2)4pNd}5r;eZG6CTAH8zxwKh5z-$bVJ%ZxLUG*bPR$J=H(ZMs{Z=z&c@u zE=V%~No`fvR-b1Zx4ysOKKNFecQrCxkW_HwOyEl^)bUVr9`QjYIT(Bo{M`LN&c+|U z2kH+*d=$rM{EOcsoi8``ueYS!)CH|FgA>Zh#ma4oFLIZoWK7yh3IHYn_P&&rPrn4lIULet1%z zFzX|0_2P_&cTjT-0?H@?{73dh}J%OO8ipl z;|nvd_h@kD0ww|YtT&^vo0o_Vx6AHvQ1k8A)V~f=r11FtF6m}`W>W1{RZiCa{!gMw zW!*?M8JDRpcCLVFGfi7rcGehF>E2Qktl1><3=br6u%)2d?z%gRa=O(}Q%2;C^WFZj)0c%7Xp{Id>u$diwCS^q0X zXev!fKJeFV>pw^#jQMh}-RUo@{HJ+8$bkBIj6s2(_Mc>(zkjv4nQ#I%jsNjSxE%Gd zdO3e#>cfBe2Fj_@x%tx*|I(BGXw=932Nm{8|Mm@R54(H+{Akp<6&cj7&e1#4BmEDS z`MtZS7w7oP<9>R`|M?e}P8(M$(1nm>N>`fmFXdJ4emjEMc9Q0^E!kOg=D*qxHr9a1 zMvP6WJ&HCwMK91$4E>T4U=3d~QC&AF05p)~PY`6xbY`iMu^&?ctZ_v$mr?Y{+$g91 z6EfrAEy&^+9ge3RTE7WnjSts58H;%gKzQjd8t{?qz69haF91hnw?6EAZRy9frw6=W zhst**JXw-z$Aar$Y3+81)ZS{yw^f@Y@SHvpnc%#QbXt%6;#hBAaH2<{>xtClKi|Uk zAQ#eF=E)c?o@*OXxCRb??J3!=Po)D2;NtIk{T9)m7(}el@PT7arrCl7)!nqQ_X;c^ zpa*YRo4ID4+O=2vs$2NQYW{&r`PCWfuz{iK%Ic+DrcIGTL?sDv^6krvkW!#59a$C=505u?0^ z)++f*O3DY{UcSq{*mFQ|if76lo+|q4$?2}MX>o(#j?;Wo<Z}BPZyxa6rOHO!%UHHyrG#`DgpgJd8B&H zcd!AS>Tvz7IoyYFp#koukN6i)>_7POpqZ9js^{-_d_~Vq3r~Ry1#a30STZV1cm-BA z&H14R$-nM;(IVvG!elR=6CCRL=|bQdkL&nFfz+C?#zQXCZypa#iJy-0$`L#d?i-_rd>hX+NKhF&vDwq#$9-MN!e4KBv*&tk z{Oq+t!dI!Q579;B@%)*iMSzbWql9LnG0Vbn!}j1?j*efx&2{!hJ~p-WA8+e(2HdP; zZ3y4D$PSTZ=VKb`v&^0)y6wmUu4}b+A|5q-wq%UFm}(HMIDXe&Cn@JE2rg~r&z-&E z9rsukn_6fMQ|N|9kLE}WNPg%G$=TM*~!D6xX5t*Z}_CLbUr!wRAhg z>6CAwkoN7}na+L23Br>IaIGD51nYj&CE6oJckPi5q$u6yL+o|7oMP0gALk8 z1{z`b^bFSmN)AC7KfyjW=M7Qk+zfamDKgPdy9p!^4fP23%x- zrHLSI8j2&S{ z4<^p?vEAdla+lOw*S|UUFgw9;wL#xQkXT2*jOx5o`_byh&oZ3PN;%*#&?(bN|3_y&?|Jr z3ot!-UxZL!y>hJmgG?+!%h|h(f(lk+nbE8Fm?{Mhy%NyB+=*(B@)R^25L*c3P9Lv# zAwV?F2aL$bao5!t@j=Gj&XP%ex3u@orV4XhynTrenCLeqBZ8Z92+PM(-x|zlVBk>L zw5;P}7&nr)4aMW6@(%}&4z07^#ns{VA}Ddf%!?xrQMp)A4IPN#PIhXW>#)^FT1Oon8w9Ce*gXu}SjvhsB zkR<#JMCZ4@xr~#%Ld@>&Zf-U8h!ZLt9b`YdBj#;%+MZJ8JBZ`@VdAfV?6O30-OxZNOv_D zKcE1Q1yxtu;C{HvD-uI`+-YV713ot&+WXq{>f2DO5BqU%_?-YD{u zn-0wSVTuWHNeJRk4%jRFl3bLdDe08^Wq!c)pomiUFd#Jeo~(F(eom^;iMA(LJD* z53*1WXS#HJ?I=2kYcd8D9$65d5H;pzdpAeyp+(KvZRdJ!fpQP|W@X43je8hoOF zH=3~hnv8o1H7Kde!Mh5mpO~CpH=l^;Pi@{K3l&t3@MqMd>w+f4rC|)E#)rs8CA@s0 zz9>CAX(!x(lvjT~6+1>tpYU57;4J)S&*H3IW`o!@JH; z;Rm)8uCgPX5nG${WR~X_4M}~OJ|vae-r;bdhVMQ1i!Fu0=Q{hvgw;UL@4cU&hX)aABQM60` z7EmtKRNQpeR}|x;dc0>egLTP@ITxh%?Ph*16Dt=3T(bhft8@MeUX;e2@CgszXYWzQKKzTNd_+xIx#oD|r%lZ^|^ZNwR=F-oobWN4XTs^j5D0Ln+2yJ}oS z6!l-c!@{TeEkI{!xe3GQDX>Mq;neWr+FJOiCRr$3Yz{2c-kGe2WQlG*?~_-U-IJ;z zG7b)<*k!nvJ?8#qx8#_ENwL9`zT^z_=rcp{K*6h-^R@X?Awj)X<@uRLU5>lt7;&@# z>pBO7Pgta_!zX{6C>bPF|9FG>XGkS}5Qr(NUe4RWUtW=(U38XPJ3MlxDxUg23(4;^ zrl2aBIR?cLP-xl!b>zR!2V!T`*4B>qRL(~X;GCAyJ>dKrNZSw~e`;Wu9UMH&cD6Jf zgcHHQrt(1T@`-$mKCNy!W7|c5mZI=X27;5X`hVH0H+E3t}^_UYj2TiH(R$y!II=6-VC@!Px)z{&5M zYTPO+Un#~;PTzlDk7a29rA`KsH+UY^CPr-Q5ogeWg`_&au@QNl3Qnmy zGn(SG7YRz5qx{U&R5?FaYq81D9!ZZ)=&N-mn#PYKMpcDWh1|57@^T6XQPz`mB;Jjq zZ%r&7c1z#S8@@@hPkjLT=bS~ev7BCsB#QO(0QaYm^{<#ur zqVYCz89zy8Za_69$X=XVBJ~uH&K}6Yn84u@&-c3)Vi^2GNbX#r4L8w2f1Z*VJ z#tqjiD?7e-FBcAKi0iCSm}8n z=yqM1Zwe~gvz&IkK+Z;h*}z*$zo`oPjg|LJoh2Wqt=CQ4`cfQV5@@w$ZOp-pbiCk{ z&LSY9Gz5(}qs_>O)|ARYWB0+!ZRSvr$tX|a(deg(Fnic3ae-xg$@19`uEjj$RagCq zb4uGiZW9zfWVBiHi2Gi9P{jK@DvMLhASQFti0T|_M=r8Jmf&874pAYuJMBpg9PHow zG+tQxB(rLBHtbWh)3Ch4rW(VqYz0&S!S|~qrPp54!*p>>ZvTk!;ttYt(k~*cCMdD@ z*NBlpJ6AqkI&WxG>R`iNdOY62C}%1P=9Kr`DXgZFj9&XKd~XAR8w+1eqLThda@W#DIikrB{xSY(r+1I1u zZRy=``yQTWT%_td?~@&!WnOUuVW>V2&envL!hKjTJM2jawx!U;y>Y9l{8%w(XI8Cx z^(Aoc>rct)g7u`96PLO%LGShx)tw*T#pe9Tb|4-c;9@O&`gm5$dwu=0)dAPDZ6Pab zjZ*Y5%yqg%PP70Qj{-YJRNBNwp`e6J$k-pLZ(4_;tzO)MbI*ixmD#Hcs`PHEpKuI3 z#;?3o;?~YNQ>$XsooHdtc~WwM;WeH&dj#yh;Llk#h1M8Z`&Xvt$&L7K<3$~(d*je3 zG}mM7yb{Ukepj~RL;cq+;6K;jL&f9=K;I`8j{VI`3IgHorZk3~-n)bGlhmO}zPmz= zw_IeUI^OXS=TZfcKTp!Zm#MP2OMLYnOm zt*&S5*(|#x%+9K0cg-GDx8aW9N$=A%b`4NXD%qiPB@i51W$eiI^5>i^$s5gmKGP0P z`A}238ZqVz@e+u*WvzfU9Uc$m$e!R@jniKr_HJ{vWgAG{N1v|Lb2#0N%Io$ZK@+hYO()^y|;{t zbM3YT6A~Z<3ldy{1$TEyaDuxQ?iQqQ2q8FupoMF2cXy|d5S+rHAh=7RUHQH~_w2KG z&b{6Jr^oHl|7sNDrK+CiebzhIoO7-9BFRIC1#1*Z`zuD+Y0BBC2_MZb8~wwC&M2{v zk0=C(AH<5&PKM~6Fv!dK+iF!?IEu2sBrM`wh`h_;o1`86vM1(dVWlJND05X%=GIBW z&#e{y$e3Su2&cJ$GYCS$YF}KD0}yc$blc~mg1W-i87u{g%HE3pM zs~{9{G>7QUa!vuq!z!pHc8HS;iduY0%!c zUT?k~@x+~#{cd=LWhv~pl;D+TXAfFH;Rp_uPtd_}{=!fDPA5cWhx^bb(jiq?HZ>DY zLGX;^88UmDY46O>t24$J1|^A3cStXOcU%q@RkxF9+lCA_UB>YGxoY9t11-5;EeP5z?e4Ep9oZA$KrXjet^XrQm zzqS_%+5SQ+InKju?h;0$QIlk{#MPaNB!8XWlpGWk;+nVg1-fv*2wDihh>u4`!O}S= z4`IfXx)eGYrwGmFBJ-VdD78tf-yM&wdofXA66mc)weRkrsATOPluHsu6gx%(d48?Dbq_fuxpL3y{YrI9jlp z9c;G33a*agw2CJv-gC?dl10=?;Tu6SAh1)CA*4ri@KI$HaIIgRbZ4YiXIf2i&KFC# z2?m6%7pZ;J7^e3*g~c4o(9jfYkW6(CDnjRfLggglC+X#1^-bhu4mTCt8I4VBC8mIs{zPqB2EU>)f`K$!(U&-(s(PVIO?qjEDhmE@f2*!`a zA9;ED3<~(iu?!HG%@SO+P)@P5jAt@O!yOpXI{)^A^U~aP2wjF{CG<6zcX)YyrE^2{ zTJuMMnbu6B3u&TbjKTtxE?F&@iJ6)`%yz{b3x%TV;d2+~0hV&cZP2$+kU*_~f_G&hz_&s~Pg57uP= z|Drbh+wfp?{3;Zs2ls!PDtYn$N2+NbYNgrSh7d+^;ce_6QcvuE0NisABq>{~2yT zf&ocMNwUYc>6)1T~6q|-|tLt{#5d$FOKCVWm%mG8Z)EAT_U6^aRK;o3*-34Tg&C2yS}$zxOcr|0jz{F}FEA1&PA z=@$IJ7+k2iMN3?6M&e*;-tC`sVBI?yfH5Y=*S=>qA$(wPt4I<6Iqh zOUTPOx)iO5w&ezuS4S1PRn@phi;Yi}l-w`uyq~&1qc}sDdb*H0@#~|Bnb%LmFv1`G z?F{h(excjC4V3HIjq3X?uZVL#c@K@&(AgQ`{PPq>ycg5VTw)a_1*rw4xgw37z12!6 z$Slr~b0<8Fgp)eW!Ei>4{^#(!qYEE5jSz-eOw$DxCDzF_*{)QIxZ?~-=5VJCH_y;$ zrS8oZknwGBpA6QMgXukGCV7kkmZe}z3;pPIlgC&w;meYyT?Hm(Pt^jCE;;ob#Ptu1 zYMy=WCgw1kMS5!uOY4SSxF@obEkf4vJ^ z{F|dcJOEdJQfB4k2QRM?Mci7pu=nVMLrYeAS?0C&g8B0Zs3r_$VeV^7GjVh0n|4A? zJIp@E4$p`*mk|9IwTOAjd{DH?_&$}hU?xUuhvz)DfX7*_IUXj}qC+@&jdr@F+5E4b zPLT_Jg5l`<4!W*ofPmR`emJYk(KW(SJrNs+=yUvD6uNC?bN9Mfcq~3WM~gOhaS}zs zfgpFXF9S6wvl&aD>@T*xYNPJ*u|yeLNlm$Ln^z6J5I7w?r#mo{N}fN~udy>Rc_B@^ z9ht5jj2j=wN3f~x^`=Bz$vCA!JO1!+KybO>;L+SV2Rrs#6naSbq&BImblYS* znOQ-!lIkUz@34RxJyLVv{y@m-Fne2*9H>c`{Eup%-$3_8K=#gcH-S)<28nFy16HAS zAYssaXp>8wsFy5d=TC#3K{@#VPT^^dTCJ#BO6hOM*!^`N z#B^xc|Gu`gLu9 zv90f~c?H(k_&RjC@bnCzIgm&@${WI-%|>i~75@h1B&q#6+Df>IZq=u5f^*n&tE8e6 ziK&OG;q@EYt$Fl_j4rz?$Q(HVatXhcB{BF9QF2xF4I4E)0@q7TO~I6%A-?d@2asPj zOJVcGWL=L_uB^0bfpNcH*j?vE$4m6b^Vgh&w>hS(A+?NzM%ih;P0hG6cz zPtsUptR^4W(HchM#^y9C~VF22Q~4m$JPnyChc2 zb=aJKNfAqj7ak6W9(K6f*}(ImKEUX{WB51!d-rKwmC?-QZ!M~kGaa->eR-I|qc=O8 z6_~{P=e3MAqw0T5MZ5a&!NF(E`7OVLy{jU!#JV;HwR`dWC@Yq@QcA1~jvJ zuG3no-0wLS0o1-!0Np6d9o=*@4`gr5cFn*({~5>NsPfbGHV4&$?pxXXa(x)%KF0SYu>stn6&(Is0w z!(J-2>DI5}6ZZpE%f1y|Rkk9?ZY({)(bKUy*4gZ)VzuVYc7}fn_wQcxewmp23u-R^ zjhdqxeoGB-p=h_zHH`xP06mM;N&pV?7nhXSmg$dT0*F%}KB1udyeUn6WAb)j?QN`? zV_Bu%xqn|hL+Q;>NaF=EX6_qdGHznfn@9Y~RnJ?IdHmgXnB)uGEH)uUFQR0cYPGVa zV0;-@c9LPeGj(7x4cQns0(i7|n>=q+P+*X3AZna29~qdOVLVh@LVaHcK6`^Bm}6Xt zGsN*vU?89J>ABb<>q|1wB$cJ*s*t0zh9~^n7rBBc#yu*wOKh!l$Kxo=n9dEywY1y{ zo$uN54^GdkDIRV$c}^91B|H&}&J#lC#3wCPr{R2%}b%@3$Mho3VZI8Wi;J>1r!G(c^X=YG{FSxdZ;$CvgvlgfS zpWpQ<_H_x4a*Vn!>0iLsMJ^m{g)h8R*z@#~0G${{?{XyWc=p?RU;*TE!FN`Uw!zYu z;m+a6tj+@y<_<#Be=qg_mtDQ_4MOB~^BW&Kp&!p<&63}e8a`787{>IY|JBv=Z@;Y5 z2@0C^fR}}HQihA-HPgPh)e!ce5Q~$k`Zhd z@jTNYytcod_T~m1Jh!?z-@e|I;M%>dwJI9a8|$yNj#E))+p4&d{c-uy$MTTV3xxgGs|6b$GabcSmY537ONTZ{P`o~)&b4D#$;TWAe+~Q|$sU^Io;#D1) zN$WIo(*#b; zT%I*Y+VXURy<^t3ftC;UEVVAbAWQs&E}ytaSh=Rys$>45D_l&y(&o;pbgmL7B0oBY z3E!dl*6#$sV>QOS5)<94!-cOTq)%xso21P_>|ri^`O>z9qn7kNII@m!{=%Cn=50VW z3UK~0j3=IzZl+)TtAVx7)g0{BrWedB8baG3^b<^hHzi4o?6>e{Fc9S*apfuY3ko(f zQh>epW2n}#@ZDKX2%9%V{#xRyk6NMM-)r~8X$y(T;QGbZk;tc;Kx8)m&k{>q4=9pn z8C_sO%*2CrlMm=Y44V6Xjhki6eoB_t0P44WUZ|twN{^NFyVSK zE{+?U=Iz%08`x@*e0!0{(g@1vjMOtk=QC{OJ6!&ho{OI|4GCYWcx}Aa&C9i|srq2x z(QxryLU6P{E_JyZ`G_aWc-mkcNmZJd=gx^tfA5~dUBm~^c6q)e;rSzV-@?%-cf4P76@~_H<;Nn?V%R&n8{I#d9HD-CawDas4C(P}B@g_*VEB zOU5~~b8O3vq~EiZ<9IeOrJ|OZLyUFo=rK~84YV5^NQ)KGo-MvE#C+~sXTp>5pFr9C zY14_UjC&pxBQxUIIa=dSX%n+%viptRMnXw#&Lco&@twjd#v<^g>4Ngc~*#vH%Dv(ycsANwVQkshVIcIw;K*Xs(M zaihMm0WQnsiEYC!Kx;6{Yt__-f6{sIceb7f7jBdwISNyWG5CK@E$@(b5o$Y)AQet* zpf6C@O*xd|=yb`9O?tD}gLSOLM-nE?SXAdSoIE{s=t!=b=G|u%nK(Kp4d5gfbY~S$ z%&u#%{ZYKqYp9}kLg!nLeR0?)W4#nXdsd^|eCiu0k#L?pIw^{J^H%guzP7$z4mXX~ zqrTqjxGje*-R5Alu!#R>pnqt!up@+6MQt{ceex&~ny<8aVbC&hzBqZUpJpAU{(7kX z>Gc@UVrE4DGraV@25(p16&-ER$gi-6O8$G+kNU(d>f! z#vqfPt0Q+Qk-MsQ^>UYer`+rAB{Vj6^@m-~ZzT1t4(}O;i_pm(?h?Lu?wIq$b-|G{ zy@L{~*p7XJ@xtK7HB|7{sM)2pXuAZ@b_FJpCM9zH8QxdXbSW0m10OID7?Ig8Z@X;@ z*%C#j%(-h;A0h+L(<_$xh@J|!yKWo)UytOMktE(v2OnM-m&ryuE8z$2D92P{KrsYQr zX>c6qxH~v#+_`i#4UQjgJ4j86U)$GFbE&>e%Ps!QQ?EK}XP3*oH_v|br-bbEjS=>Y zvnQP&g)Z6RB_l4gH-?R^>w(OpfMGl|Dpka`7k!rWeR7S=P(&gMr}w< z+QJ<-d4)MKumIQ*te0@Ro@*0h_87$RCA5!x_} zh|D?hP-IMxK0trW!s8z{R-4)C7p7O!C{227oL_n9TcWMvt0du46?RkcHAvTWU8R2% ziXA@L@oZcRZWXHmPK_YxIz9phDjd|-Q5(%N4et8o7a03i0D>b*xWDT-Nu}EOPPgfDd_prw zLlpL^;bGMnHxwtwVgq~g(S%6IaRuM0G&HxQ4V|n)jWWxXRzd~N|C_9YdSZPsBK|A70Qp+2iS-SQ$3x) z(w51v%$39bnd+f@N+!-Aw;Jhr5E-SKu8dCZ+#wOYc{alS@Vh;vBUZ8TEHu*`LXDP7 zar-4GyaP4fa0qs5$@UlC%Y$j{2c<{i+b<8HLszErI1LxV82#nRf9U2E@B}Vt5WI%C z=qpC2r3aj~4rxGl3W^JU8Uzb%v}IJ3|5gRUYpZ{F3j++MvxhHwlIp>e;O^UW(o*3m zoN~sP>LV;%3n7HCi&&_er1qX)eu$~0eI%=2K3$Xtwd6k2UPyZdmY8wT}+=tF{sSU|@hdy^3UpGdHA<&n5t9}pJ7vJs7j>hil;J*_3{NKOwea<}} zeDnG9KSA8fW!qtBvmimlBU_WlHp`qj|aG7NXB1RRd zkcRXTET0*2W$uZ2TLIcNnY6t2i@Rfm2Uwz5vIX>i_~P%Tq^L|3j%jjbcDymZ|2gMg zOvZlX7k+Bt*fH4hiUJhN5(AkC*v+2=ZKm1T3Pf^TO)QVc5m;+k46phW2&Ecce?ZM0 zsr6dE#m2X9Y2VaMxSjGI>IMoL><^dTn27uxBI=tVyq`TmWL`|uMgTc`1YJBinOY9bZCJGkE-4oTD%ur`S}m5r*?jC$1P|`PK6vD z&fwEs^8ZE^99vs52QzsciV6) z@71q*Yzra`bZVRDcK*qZgeG>r0{YOKoh0#apd;=m%I<_b^B08@P2pSS%2dxNvh@0I z7a+dWpi@J}I~2xhJbK62+>^SnIdEXw zNBBCzGvQVR$8J~5(BkDwj<^`xZ}`79IU4!cEQhIEg@ws$utwu|e^M$^a!-wcUS*~Q zO>@#_bMe2WtWscBxc;ssV<i)L1l7lVq*SbBZkCssVV(K3x{o3@%L!{ zHS6B{ZS3RTxwW>wbA~e`Xw*1c?sBg1RF!YhrZY}^pgdzh==L!GvwqbbDHWlTqp+SR!Z)Nq*f9Yy!IoiKK-k& zxV!><=G{s9f|^H_Q|!tmSJgeL@XfR$eoM8JD+)v3^S|GZXnX+<{^OtA-K>GD+;>Pb z+^+m_tIpIEYJSJ~-``RRe~G=_q_7j>L~y~rzLSn@2lTrQq-_HIGS$|tOeB_3s@(C~A7d|e#cl8xIXwRT{vMe4Hhe7kbmD`NHFc*jg2x5F!o zgV7N7wo|@EhK{P2j((nGhrKFR=^}V6L)Eq7IS;s?k$3{3*&GWoCc{)$ZZeXh{mO~H zdIS7o8_cZ2!}zz36UQF=M<05EcQ&{Ts3%V=i6HI!HMn$$^y}50O9nwjDZVErfB=ik z^baAV1u@`AZYM%e12}$yhoQeUhD4! zLSyLjn`;zzEbbOHZg&*NXffMGUa4^{)?3?1EbiwI#e*TjuAzDXyt>HZy5(gF_(Icj*C zq+)Im6sA(^o`n(@t^$yAzn#F3(2`mpV8B@#HT*KnR1w3mh0h__GS}FK$I#lYtGftM z`(rygacX>S3F^SOd)5p;5v?Vju_X{~OJh1q(boEEKuW1ir*y?Th6qAFIT7G37d|0y zASZVDMxf*>+n{Yu*%!B*M6@QIYTR^GYq*J8F=~q4Lu-E_9xs~qth^f;du{Sf6gKo+ zmCAfbpwqm-Id+tx|IjW(;yD@0ewcYdL}r1t;P}VUoeO7U3ZYs2^@TAEyEFPD3qZ)l z+yZ14q(fiRkV!2sE?OeA1F_h+8Ncy3b_MzlxzwW#M?EDPb1ZWqn8fhudd$b)W+t8F@g zVj#v|_q+(%)$bh^G2rFQSif##rp2-UI-uPC_~dYoN~H*=V#=;zvag(p$-p(;@bv+KXH#wn>i;+%qH{*z;0)-|rGkrJXJ%&=$;U?D(YDKx*aR z$h+>>ey{_-pC22g>W7c>m>PWD7oVZ&0db@M`^MZ~G z`7l)g>xf*KUKFTgl=-E81bB0yCP@C8Mv(pIbWl?im;N?URBhz*R-9kW8kDOUncwmx zI~B%>Bj&4lf3jQ0=OXt#-@Rx&&n_s|`$h{Mai*D2N{S`E!0mlV4|=D zU>gO6?U=qbaR1=B|!kP6piiJPw(>K&hB9+62Ocps^D$&G`E7zzxHpW^Mj;X$|y|>|Aa@aAtjdd zDvg%XK#l5h`N&kGkp(S}{~_MCCKA!h_oOxl*Q_63G7mFL7*@6$ynEXX!}IZ%er6ap z`mU#rmYf!msYQlhdU&k`)W~AwXwUO!?B6+#ELqU}F-&JH&yH&~yDr zT9k`}e)^u1odggJ_yS#7{4Nn0^;%pux6(xdq53no={FWd5;wlDG1k=uD)Y#IH(;i!~GlPieNYA<@~Z^suz zD=PRhk|eq;PU`#@&%_{D*~BuCjIfZMvv!Bkdj7CgX@h*Cd%V4$Co3|+7uc-3OBg(2 zbyJgpW7tZA6{(~+xC8uv^tyrZOiQ&S4uZAIw%2{@UF_s7&ww#@%8HB;9xt&m(WA}K zMmloB8p4%m?G-*dnAa`*EQCtj^D~W{bFYU7ZIoDR14^Bj@iBu-d*%Y7q+Iu+h(^yQ z;aOd7KTbre$~+x0Vmy>P_c~A)_O0u6l7;DekIVTTlc^-@zsEfSZ3MsZ!OqK%vhwa< z9+2?tecM@Ty{A(O&#VrQDI15GRtr^8LH&`VeGzZZ7c{^B<2e@gb8}7%;MVt<-2dl8)Y>QXGjcN;qN+Ei6w<$Lp*dMogt%MikT@u~i zF{kV+d;9KKz)uFYCXKgG-r%x4W3*I#Nozsw`~D$D;thAJ)Qysl6BvvJy@XZeIWLbW z(J}E9JLOGrs>-0QMmjmmb0KxosdeUsT^})fklNgSI0*Ns;v)@yw%+ zHIFkMHpV>hI?j+tj9RhZjZsLo9?Kkj-4; zmX6LDo{pAFnMwNj4Hh!%Q?lxsu5u<41GMX;{~Y`Euhi{Lz*AbbUaEEFz336A6)`a8Yj9T$XxU zs;hXnxn5rR1l-m&KcN3;;oZ8-$)A7bI6xRT_{zZR7dN4j!f-dU_odMe=%E@P3U*yM z6#_8g9oct*j3FUOB<3?62Lr@aB=E z8oT)x4OhpI7 zER6N5g(Zg`OjdC1pCF&x3JTsz-H3`9&j3`tFo1?1kvM^S!1p{Y9SoIEJJQj4%#DBL z)NCaDBW@x+jq@llTuS**)`3P_X;16oj2q56{PtQ3FqF;U?0DX2jB^@l=-#W6PESwQ zX_mKPu2`2k&l*Qd$fYG%MS}9pq;c=3^o$7jMZy$!_dlyqhQ`KU-cUppL#y#;Ma0=n zu4R}~xdadl)N2Pkd%=eAnS<O%k2$gPj!LoyfE?80u_ zceA-26D>U1$5Q$KYVADMqIrdblWXD{1uhbCsz|IVQj>K3VyKbfw`*?WnfzNxZ#yAM z(Y)GK56R$J-h=4|iILXS8e|yaC09_-*|1TshnRjG`W|5`+xi|t(5_W*YTi^(fPXQJ z!Ad0s5fg504%WpIEdPWHbx~JSv7d8z_1cg_PPhk$%(#r8u{U@yI>Ic_lt5JoS^0Vb zg_&rad2v>83^mge*OZt)0@W64N#8lA)GSAG0BDYH*V#S7nW|e)qJ&Z}n)I4vhV{alDa+X8)c|)a-9GhUEV(8e>8@|9?$mWZu;G zJRyJWy{PTE*vVEaI`85AFB&7}fW=VDpCDCf=NSnD*YGW!TUa$O!~zSlZU5d_gIlCQ z+yoB5M>HoyPz6sQz5^d;pd30FHkvbG2Dcqk8Qaqe!e5Ju9wUTOGlyz)P(p;pQz3Ua zjcq$d(N~`yeU)GP=yC8aIgX`*1fqvl4y4^v9mn|*+ zddJx$!uP-M7$uj}ijVfGca6SGyqFhis2^AN5S zX*H2^cMZ}ZpK_=ve@l+k4{Q~q1$FfW@T;Z-n^0)O)SZ|d~`o6q#T~d!!AQV|VET7F8jQv?tX9>#^8o!vV2oU7eA?l@^4h{k& z1MhAvF9zEwmCXD|_d+teriyco`D)<-%M|b}3PlOP*{%~3exI+Ww6ApdMn09eoCqEh`90ffYe|!J;*b4CFM5rt8W%(MZpioa6;B3X z0DqVl>Z1m~iE~JSQDn(B>qfJw!l}3C^9OEPxbjKQJkpc1;e8S%k-kJ!kO~HbQBHgbItc!GO`19YVk@mYS2W_*& zP%drdtb0&VyDkk3$6j!59{-iYFeeWRqqED$NxF-t`m6c-xJF7LTUj-edB=v0mV5?~1wfd@bQ`MWY=XpNfEC>Yka;d`H*S?9apHbpZ7t>I zf?8}gUQ(>~@FP3FW?MNv*+x4y;S)B+3IYB_IN-?Ly_{F3IRlUK)EU2G=@6+0ty);>711-}R)p9tcZR>e{?j zQp#5?BE3o{o2Qy-jy?Tvp}%&!PtHgS-J<%3k|pPoNdrAKxC9eG}=h%S-T*H2+E#w5*@hJxZmGhD>mP$Rzk zOJ6_dahedDU%i4CHzXyGW#(W(F%u7u>bSGeY*fc}6+c3211}rX}h zO+kaGGY#^C5_~J4kB+Q58LM=x8fSw1Zwejpt1h2NOphtz`zMnsRkW6j4V@3;)isbh z_M2)A!X5sRiSX^ZC_}aVJND`9gVzCReXph21xKuD$85j51Oa6Co-?5ge#6XN>ywSE zTyLadEuUKgbMyMF5M9g)Spj=Q23XkhO*Xy<_~f+JEmxhW>69uZWTOZ$k9x5}uXwUG zSr(ToD*TO-ii9L(wS2>J{ttA(8X~h8znV-u9b{PqG7Z4GpVY{W8#ZpOZfRq z{!?lB=R-}o*KWDGH*-O|%{>cbVhzMs1FH611_4TvEKd!+(xbMy&#(C9w&T>ZCWfri3}oV9Hk7!5X8 z+!q5h>my+kUbUbtroAt^T=UtNH$O*zy;q_smAkx_i)jOCl6|$)@>G%ziHy_Y=|B3x zGoZDRL#o*v%4uRC`FdHBh>R)i6R7{Ki5_^Tvs$993ez^4#}=#{xIq?-?zNY-AevTV4%wSVU zE&P;?1>(001r40`Q%H|<=yMB;?()0Gsd64CO%0K3JzDkO-tL-pG=6vtVL`CJtx5MP zD7;E&@_oP<^{8(clI8{a2b9_SxgW&jt5pve2>sj?HnR*g(BW$)IR2-k{!Gy*RN4o& z>R=;YETI7Xz6$`Jn~c&XXcziXfU6XKx=2IU4&KdQNHgoiKi+237)@-dTpQ;xaiWpX zW1kyuHHW#In>vnJ;~v5gu58`ziL=}tM-C(vYLJ(sIN!!lG@t*l<;X~h57N8b@A}Dl zZ_YXl+Np(l!Uff3$Y&7k>s$$*h84j}>X)J=;ytB4k*?p3B&CEbe9w!x!uw3E!xlh? z@y|o%@bx!e&mK&39rzZG2J*l{!el_1hlMuSZNt@eioNJl& zQ0Y-8{=jcW<9bC%SKZ3DZq5lyvEjd9IGN*jd6_>jw?pY&l1H0WIZR3r;!&FZ{b&OU ziW9WJb!Nouf*n$@8$Z{rAZ7hw^k>b0ROE0*RPr65WeD#2&sh%D9EzG98nU`*k)2argdCHoPO!~%JZ)up*O9W9 z9BH|^^i754-s+4K3sL~Ep4-6uH46k@em(d1=`QW~eonIAx{hYCKXVXl2lUr4dgdoc zY&YEfL(+19@$XruJ{rQ?6UDaXzxZY3D&Z!I-R<8t@qhbebjxUeo}HKctK97-PvGCi zcW?6cNo{C(4_R0|AL9f8tHMwe-Az$LC!4bmcKXyjVu8df8v28a_aqu%bJlX-&nCUc zG1@%VuFsnbt)kCDL2chDPfcvFSgY|h8^8LD(%olai~~dwX{yz03=(PJ>(bD7N|cw8 zc*^o!EYTN*)AIXB?O+O>wsdhZAEsv5#_3ELKb=gZxWba*COIL-c%7*?pAu7_lt6vr zXQaY6yG@&2yW#JXIIJo2iQB4DQh?^q%%lM(P*2Br?i`i^p(EdE?nLSTWy-%=A@}C( zTdBTZBp@~4RYPV|wSw?pFWP>$QUXt%a{R6i^xl9oKZnyr7{d0gvuAZL0|YFrTZGz} zH~_Mh(?&AAm;>vvviP&H9wGJYJ{5{ku(Og9>uv(6p;TmjfR~3GdL1QD|0(_Oc42_#$U?{XEWi_%oEv zO`8%rLlO~D2g6J$Xs-1_M^rs-OvG+s_30{7)Yc_ev9ZR#1##;8n!n8ff;-#a{JFhS zW5NHZd8j3u&f6wFJLhoIDDdqCsjrG7fH(qxj>tmmtnS13Z>ik542Kg{c>kWF!dZ`? zCsge$2{Bn@)NH*ksEcT--j7(M{EaU9m*@RnR!s84$zQ!I|K)XnxU|tPf%d7b%h%q@ z_293FnX|bECTItq^NSDq(nqYK#iIuaWG%&&X5&>6x$+$gkf7##3w5sIn%AQ?f-N1V zYl0flN$#SOo;6n$rD6M+ekeQG{E-;yyy@-K+h%%`#_>(jmwp+&GA$fxNT=eTwp^Cm zJJPHd<|rq3JsS$iMxyEsl*PWF)HSsw{0lHj79y1V-Cx-$hV|QF?r{PvL8jU0UmM^j zTnIMu8#IjfKQG$iQi;NGOFXon313LT7-}Pa-OSoI`&kg`2Lc}TH5&*+`dV*2v(O6p zeV(vG7-LRih!uzYYnpPsKWwBovib}835mRZ6!pF$Go5uK4fc-PIyMf&zTjY*L@#)%S|ItVg^no8`4yJ} zF)gcrcd$RjcLnp3%N(B5Vk*Ljfs54%SakFYRS;^ z0BdGlZufS0?|HkB=i739D6Evo+LpxI*zt=40$v1jjPtlH#8w>r>Zc*KJp{tc*Ikccfl{nhvjE z^2h^@t39`5qR_`@8;|7s`q$|h^?g08hs@+U*S`LhK6}&Fxk{JJ?uK_&39_^9&KHxm zmCaykz^GK@ z7XL**lfC+C_*`4Csi?EsRddxM&+G-MSMy@!o*3++j5q#0d28L>%4i8#Y30#szV6s; zN`D^MM+41gWMR-Nx!6+T_+(Okw|T$|5^XvQK3$twd856Xs1%vOr?XpX-SmYUzb(&a z>z)@Bt&i)EZ+vOG65tDE#T*y$ON;?8fthSs-9}<79H(~=Gs@}l`!XYvoIdEe=&pQ$ zZuLa8(qaf}`8`b6K|vL5*XQPndxGkIXRPf8%PreKe!1UFZ@{#iTZ#q%43Bpc_`?Ou zRc&e4KkT6qAaX|0D%0^_^wk$2d%}Ab(dB!Qqo%VEa8wz-8;&MOzCb&Y*QN39*71m5 zuY7r?3`PZwX7Ouk_1<14#9jcW^FnX%T!}IUEs(e>(!c(Xo%p>aX>I{|!Wb?y4K9aDPPI3@P8q%%!58Kmi#N`aSC|i}ENzAQGinPb z-8fJsKzsGwW^)=l3l&z)#k%}3H?h(^=;W~A%I(n*{-=mNp062-u)#}v=%FPU6W~{d z5bRnbhA>rB$~##Yzsdh`61pMS0XPhMzOWlH+;-GdwAhp_e@?Olc<2J`Gx(n+LWWuO z*|mV8FsG)6u%^@fTmM4+Y4oKIMDf$mN#yPOE}(VjXv@J(FME;$R2!g@m?DARpX~5Y2@dGV5{Yq2~C~?=64)quEY2DXuXlixct}{2qPw_xs zQuAMP?xQIgrp4?PG;)Jg@OG5kb!&ViRlDSHTMnx}^Nvo?bMN5OJvxk-jh6;M)J6Qa zA=2JEpK+pPuYgs1sf|XnA7w$+Fh@aPqI-0?qk_9H@7Hq2g%p=bq3sIa1#j!BtKJ4O z|K@lFN5+P8Ki&-i_?_p~NYZHK;<idj+H$bFu#=I$ zr`2OXbK0qfHDEjGEyITsBi5q%`~g9A|XrNwyvm9o8jKX z8*4`1TDI6=UhYkKTm(DnO{oV}S-LD|TT01RtU%h^NN%bQ;Lj9NdH_G({Agd)&=uU% z!CdbELe*_-=VjJkspT%X7(F*kxy;~u2t0+1lQ8<%9)wTwF7NL7kv}XQ%qD`H3+Mp? zFxmE#MQ%_$p#A>Fd9={&`~T72yT>Jc_W$F%yVu=zx7Es(Gf!J5D@~?mo~65!m8q+i zctV8QIY}kJ@ zbm}g<$|--g$}bNzyXZ?r&QW4pG87%#Su#!uq#O#95ygYM(hUnpNZwCe4`{lfhutAc z{RO>G)z+9zN*f9-S9R6lM{@7}Pqz5S8p)wwPZ7^_H8VBeC1_p@lV!`Bnm2!3qCHB%9T8hYNpEJ3lL#)8k`*HdHob2)(q%qy{ZpjCYhKH~uUN?R$D@-B$W$)H zx}${OT!xu=rLpStXH|yq7()9-T1)`FAtr>+KxpftC)*xz+F}iJv}QEolArI)=F3KE z`&8ktmP^0XHq|V>=rYc}`xvb2=5U~D?%l=vm^eP5w_YVX3uNTw5hNTbd?nQ{Y&Xl-nuu>z`Gp_Ac1Vihv`kI&6QHU^v>lahB{} z%fgIK%M5{Xj&nSK3bu+eH~kkJ_yZR>pC+d95aB2EGijMO|904TOhRl4sbT};ffb+uVWd5it zeXP$r<7G`wyDm%YoA;AIb1

ZY{ccpCwhFQxhqw6$2Y5!ZiJHbNj_lr5t=5Q<2w8 zs$x7XjpG08_phAJr!JZ2t-9UPW5!vJHm2Jq#YvnTrnKd=$WhP8fCLvw(Nd{%&~l{u z!!a^*jFy|xem&byYP#{ZpOvMp{@P%MLb7qj1|0wTm11!n+j3oKKuwi7ZKLb#EY!u|3EuJDP3TjK4k@R{lx!27BeNE9y06!ux#ZuQukWIt(rLqv zjwR0wys44?K3#J~S)ibFJ;uZgFC&KeEWZA$pQ}%ra{5311E2i~)V@zz z+g5m|7M-I+si@1Wt8{^dThc=_&uxSZ*U$w^m!Pel@PmXWw>R2C6J~jeDd1j@lvh>B zBX4=KkMBa%1%~Ai%)I<)>Lqn<+1v-(46Tk5)_n=2w3;Hu2PMQ_p%T|ygwiRP@u9{7 zbv3qr>5XvlR)5O)a-@azTv`NaB$?AM&J`pl>!*Iza03}hbtA){(sVbXIqMF_#q8YZ z>(+bt!aUT^k9pwo+>r9Lx&^o~g@+l6&a*)iTW;>gwIrvB;WjngfS5?NISijDV$2tz z@e4%7%^b5SS#OUlQ;y4Gnt^4U$$NEpTNC*@(NG{W=wLo-?YMkc{+V`T!rW?hK?*%6Jn($^{!^$E2k!POFgsDTowZbKA`3o@?J9qu;MD9IC zV8y{mT4T1<4VgbhyiBlK=Nnura8fb)_PbAc#Lv906&vH?_86YXq2K4~+E`pR?P3^a z{qR*;T0*tX!^53cU?eWuh;78YrS=Qd3@EH2(Gut3tQByp05qw4W6ZH?U@$`P51yLM zDorbx$$S_pRddv7;`t>drJ&v>3=kd?(NEILf!b%5bqG zYJo!h(^%r{IbG-sb1c?puuqS@G~{?%S_B7eA?*7-0Ia8|SU)4Gm10VbGQrbFn~k<%W;7#2v1nRRh{AYIV2o=DAo z#jkNo=bfUEnwD~887tA)x)aH7eESvIsibqdU-SlRIETwWPiGI}oJD&~K7;u$tJocp z?BPislUzl#Rx=C*2=+)`S~m`>yubM45`+`XD|MG(_$^_vK5DpvZZRF|a?yvX);Hqa zAU?z1YQbeZasP0#>>g_)fU{z|=j7YSwW|AFaH-xe?^9UXL;5vqj`tj$=>VPC=8x|* zT>mb^>h0*g3Hwus21&LEL{8M1v0$FtERW5W-U>c3lMMmuC3)zgpMdSEjNFa|&xHAv ztnDcBR%ZI5{4ldU3^7lpw)5;B2Jc=l_xL8gK^MM}!2KBK8Q`h8}1 zu!GKzJaFOCEHpMbe zG)SSl|L(C@eoB3yZBEF9pY#KlFkgRiCtT2bl3cRKlxB5{$CfE4H=k$qq#5&fn78H| z!_KGcCmLy@|tp;ZRIYwotIy8qUgG#^ijBuJeD`iS%)7y|=}ZFTQCh*eMhe8`Su8W=Ma5`ld3I z^FR#+Lhi-U8gE9Uk+G|{IVT-tzK@{c8HpE);%t(6g9AMWD^w+qr2#R6GPRy6b9iX# zl*pRP%qHsaZsgGLy{eN2*lox1S$L4>YR_qzbMPwu*tkkuH5`3_y*7t;@yB{a0+ zoiCps9Du%fg-b~MG$GCwZ-%OlF|;YmD&$FtG6EewJTt**YV>Y&t~KGHL09%z(#P69 zwkqX0eb+I#A(=G?>AD|4QrC>6sczp_R_Ws!Ftb|*oKIvlRa9%IVfi8vb{;7_sn)-i^n@1V#6NPcn_DLl zqZO~2RvdQHjE7!bNq-rY=JS(m`1@CLx@&LNzY%u_2VBU=Uqt9m z@;(0$WYgLge-mWGhr*@|GNNv&-TP*Tc^nq4f$*W8+QZN66g>)^XtCAaxp)E+(c$$4>bTk*hEg#kGmmowzWvBW6*QmdHS5)Jcgl7}WBP*tzvh(!Zu4kpSC z6vNAQG%ezYhH6Rz8K$+~9K4!QQ)5{4Of9GlaPya86_pApZg$^X`fG~f#L|_UwHS=_ zs=3&SQ2B{YB4wuNWYkZ^v(fm4*-^UMJ&-vcCVaj8kP`z+0CC)h`=Y#=%(8Wyg_4c= zbEm&5Y?!EHR+>WVl=X^8ocp=Z!6u44{&#;-w73Z8>8?#%?qr?=Mes{mvUDewKp!iF zP0&OVkhvM_>c%CYAJBmFZSN1tU z8y;wt1qtFg;qnVO_e$__?3uZQ#uyM5^P)U;DkX2~1XcR0L^5pE;a$cWa*4H=S&r9b z5QjTTljA@*{YxK#v<)#F!cU%@LcAdTQ_OD^ezPI%El+`UBHMz~3}tZsZ@Fg@;KN(+ zc}1kACox1`5xD(>+f+qvqbOu~yxX+nrWf|73zfm1cBs*dm9^#K&AgEL0!5)(6yk|E zvjn|1h)Y|ykk4{=*DVGfw@n7sRs(n60%AU2MMu-h0XoYz>^HkBT~TR9z+o$pqSSdl zL<5*j0gSmY+KYD~&V8flVl5`6&Xpc16HP&I5?K3exdpazN$CaKLqM??5Ti#L^Fg8M z)k`fo9%U6Td9VifJbfuet!tKaTiUucg!cIaKy6FH?1Y_f6mu*_MGO@c+&F>D1Jf48 z3Rwv{^28-jvM^5?{CiZ2#V{;=0u3tgi({o?W{YUihFDL%>x#8U403)e|MpML@K2R| z&s$rt;M^G~>ZXE!?U@!mPhH41<>9jvq?|1R@M0Wo{vjgJFN(e1FAtoi=}_cK5p7Lb zM>~0$puPMUcNMISP7w0-Xy8{M((nP4t9Zw7V?Ldb`V8{`tr#DJ9E*rq{$dus5Hh~3 z_rv4nmeQ$Kn=e&?_NkeYa)jiDZBIfXR%M>jWgz5bmWV21lQatFPL`4eVzeWxd4Pan4mt7$3sfd4@PQH;i+%E;%uDq z|0xbP%w;GhY`JeOLvLFVc?DpaxLlzo1-NYkYtLAH?t7fm0-%x9$)34_S#;=r!qD;y zG2V$V#iu6w%^)pJ7}m>XqtlA_8MNm7A9{#ITSE|^ffD&ZGoLobawCi>~GbGG2C_YvGboBN?(%n~k<6zd_a$kT(I zzErD@?l}+tSb=`@5`zv3J!g@2<(y`zB+hd7@p@nP-Gbp(Qrzf|Q1&ip#{_G3AW-N* zV>${{f&(;WRCKqGvY53HHTSqxXe2@{O`Sc+AdbA!39_Wl#JR~gh}RFh#Mg((dkJ%! zFK~Ir!wjGF#NK>yS@8DC^Bp)CI(4r)8S7J9MTU9s^|q2ZNsl5@gr#EUhXD3CbLqAP zIu)y_m#M?qZnmbx)UmeMTr>f+(SlB+ih6#Lu@RE|D83Ubr8hyPRa6p#IX4foEuZff z9|^YIE55p;>_b5vBL<7?P?g*Z^I#dT{hR+ke!kss%?%&y0_Gx5h0Ua>$>T^o9u&$b zU+PPyTRHm^v71T;Nn}kf2qrhxX;1Km5MEZ;rUNyx z4i09vhNd4v8?m!z5>P217gsruq0qrU#mEiJkZt#T3hLF!NGAKX$ zZs?sX&1g6`KRIVYe?pTD5K%lYT1!Z>na9YkSX&`bf~yM@gOUw-bYa>#O`rTHv7h?b zL+R1fiN!k##;0-nLCpppVy@u4xFT7$kM8AAp}$wdEp9*+Gnx`rr<%_Mn7f;fcFxZyOMz0;(+IdBp_FD0(Qgt+XrkW~s?8MtYoX0WryL0P;xE zBaArUqLZ=PZqe`*zj1&DwY~I4E3ErIt(RBKbLvG$4WUODH+IB<6RMYb8mxUqDOF@$ z+G27eEZA0BT8^0-x6-sF@I%g~YZjy&$1>g>1+{K_q@rKg@@o+2E;8 z)abn|t+A4;vdTVF(Lvfm6uJHV)4r*;>-%H#@vo z+Ha_m!p8jls`^AdAx&GU=ulR5{3_$raBg&oH^#AOIGG=bQ0Gvbs z;SzBTn3NYOSb3LMV`$xjkb3!1O(oSw?Bx_1auCXFzX5^=G|Ws#CtIiifo9ky=J~41zc5eI}{t8UrzH=a~fp8+rtKx)blboUuV zfqc+@?v2TQ>Ybzc;$)}N`zbkHe$wdBk;8B66_4j;ChrF0@sW*cqssv2E4zC*IZhDT zus@67KPCK#y)h4~FyaV$bV=bIqZd z(wUrdpk3QJuDj{v}I7&kSTB7B69TPp1rG$1epg<_%&V?(=L)?5YpuRG6Y}j-4b6<6i{R ztxkjrf|qp(@*cL4_<_JLhxyM*tLZuRZI?1eC*e_JTT~adUff`tk}}(-xDzc364oyF zD{i94cKDCo(GgOso7II>glInm@0TPJs4CV;z>%t<9z>keq|B7G-*TXta>w0y_VoIz zJ;@#(npaO4(Od_CQKV@{uri8#re>yov*msF%_3DkeuWgKln9bB&{t{dS8+1vP-BOs zE8-E|&x;Of1KVp6OHH7%@K>RU{wvC>biA z5*{SY^_?$oe418j=6t0qNz|u4+xYg8x`px+w*cnOe6Up3mi()a%+%m%DZQH^-ygG% zrtYH1)bnpAgM9PiJeLHDUnTy@B6U*Q;HxzEh1ZkGV6yBR&FoE>4Pjtm0Rg@76j8^G zE7l63*eS8tNN~?u=)PQLf?a+olj%lDUl<-_YN*yOpk=~l1M4zOw0Lbl_r*Fom=-Te z=HNHx^w#^$qA9u@x+DCY+VB8i8;EfQjBhbd|3)86*TlWGV&>$V>o(+h(<{nJ^aF;P zu^t2$CWOguW4}sfLugvRD?N4__?FfL^SH8L9h1~R z8c{C?cbF%fTW|p{cSVn`SHSki1)>$jN~lpL)lqd&>GRC+ z`=LzRzS2o1LU<nlC{^85w9O#T;AwcUBq&uqjpv}}I8s{yUcgFNUcXoYeUZmBS-6|@_oTfZNZP&?B@K?{ zIrY;fnf5Ts_q^IHEOSA+^1*KRv^@1;7QB!`%R()ABb6COR-XL)3QKnSH|ddVnc|T8 zQH!;p_X`$USFp=NpQ!!O;b;!h&x(=sFlMs!%OFcSx6J!n{c$xk1ef?ZBouRAqbd^7 zt}$AAE!dp``u!w4(~- zBj;FudW73k=fGik^83pz5U1z=d5ziXjF~^-(kJFPC1SrrOl7nwH61hAf1{bY zjsM|?DFG#ityRk{4P)5irXi627073%_dfuon zAnx1z`0n^ejDKF-rZum_zN5CQo_3%C!w&1dU>-W~tJ`V*K>^&5u3?+EA6xkIB>?b}bhGyd0! zfH)tB{-gUVocnVDmjIOQ82I74GyRGP&U3VLf;pm?-_#k^v!$v<~_Ieo?ClQe7*++?^)^hEra(hgZC|i|9`a% zLSAN&jgGKf-finSuUlgrvq5~=7gO?+`ue%QZeIJd16NE2DrJeZgaUfEi|4TU=S9~Y zp1JQf-ntyB zty->k#)DnVHK}`l_clR?3coCRrvY7j?CRrj--7#im(1bPD^tL?Bk23e-g)7N!nbQA z=+WrP!WLKWK)&ehp%`QK2On(Tck<|ezIEF6ZmadjLnTKlrA9YE*TQGcwt-H&L-Lg_ z^7_x49%p$#8oH0H?tp&r^!ZuDeqffq9^LE~eszFdERQ1jyubaOsTkjSepUgJKuaeu zr!d6NyH61lt~P_A|61K_y|DXgen(|>pR2RZ=IE`h@3gKz3Ak`}1N^MJEiwq^ zV<&Awb>HrX&9(3mwmYBie&BN(Bypd3M~%WuYjP3Ry$U-Cu}5=%@&1jG->TVs6)(W< zT`TNeJ6(JVO7^mK4CQ)ARLcEw$B)Ttjl!jJBFa3P_|@^%f=t=5{-SIr=h-A*x)A2? zZ9*RiiX6c*cQLibp9f@K?bqi{>yh>E8g<*6T*Y2wGkl9aGdrrwEs~OuzZmq%gMJZC zHSGB65%Z)RMRNULr1tgRWc$4qzItXl-LZUb_`IBVaR#~4^irZPeUb*6M!FR|9X^94 zx|L>ccz4go^OILK#qH71M+83?mrEl~L>9OqmL*g19pvZB)*fYfSo?NXNg{M9#$auW zk)OM(^l;mz)m?t!o;6CB+%kdc_=a7|y{Q^~Qd{I+sk=|sTw`Ql__4O;&059*>|fz6qmy`IK#qyer2Za{Z|aIx zhFCGfB9T8n6_wVLEg*d3&7n%kUcslB*;2GDb^LxbX^<7wTfPGyf@r7pS3zK(TP3|~ zw|myeOG0trdkvB!-R>q)eDhpvIj#-mQW&3cFp;cM zs;HzaJ5^JN6aS@s_ZhWV=uj}5KIjwN)Lq@!;ks3|yh-Z1Dl%MEp1TmVy+X!8RaJ+d ziDOJ({FW!RpVr*g1mf(O&pkus7a^EB`S)tq128Zz-{oN2MGwxBLTBS(0Z%KfmI!OX z!}^*c=FdAh%v-ISX5Dx92kT9O_w3kPch@T>;<1qU(axIT#bJ6E-;=BCzqSZ$)$hGh8^|PoSGRZ_xAUnz1d-CDkMD8FGG!C0)_+)yCPMN26ZwZWhYy^v} zscd?7dh#Lzw!ohYKT1z;UA)B3&N3}hosKwWa`KsTTmcf+Qfscl9J7(Sl&>$@99{3= zkJqE>l(*{5SEZ)sn*E#61qB@HPa9debHx zlsbMdCbCeTZlX8gP{_fl4Mwo|2i_-zePdG8r=QC)twVua#H)cxoaqR`h;rg$Kb&u7 zt`e46kj;u_dH1q>wi#tg?xlMSsm|c4#->+KL<#~Xa?(qHSJ{O7_9^=>dy%&5Y5`?( zlUNpGwIGS_?N+Mt3H!K5j_bjkVyy#PJa7(O(Kt=*^|CEX-nAJ<{q^zgOJSj%?e>k} zN^`kCtYvx!dw)fi)6ty`h}ddVRhAc>Z45(fsYDBMbeitYa>FLve-vb1=UwBCgn!;t#{dM2C1p zoMo^U9>t#ln37Y)E>>v=Ph(ow!e0S1V?IZnZV8?}Nx9{R7Nc_8#!dGc z1=`t$^>o|wZlOZX?WWa~i0h=;j%DBuXG9D%P6dxS(7th1R(jpMWzt~EjBNzAh}OWk z0np>i5Bg(Ubre)+-`FI3cRjm|4Nf=>K1eJ{OBG)7dny^&vX>h%8tr151zduAm~#B^ zMfV|1M?h9l()i*@cxM+gCA{T~6=QorJ83dAsn{*d4#c@7wjQOjTzS{M46;ZEC2T_PwoEW^oJREb$G zB_`5DuAFc-%^){DceOj$DAn$~_F>1hZ%A9@sPqPWP+QS2*o&k4v|2#HCg==ER>qF- zz=>r9*Tr+p&I%CJ4)$?3DH5Ag#W91h`&OmVtF_k823UOMjH(IvBgTUyPLyhr0~xoh zv4A%Kb{vRf0)Mdqc8U=kkvLvVGgqa%>vZreP8rFoTGSoSvE?2gjeZporX*hL3X?Za z7Mso%=c)obn%d(phE;*Bw6!29(nK<6)x4dD6$`hQsz|i&XE%{?G$>zcr`J}GX_a-W zrzBqA!cs=MOvfWVCL-wPd6Xx9sAJ6SI^cA1ixic^vDcQXBu%uLa+_k%bo@mu&+Atq z?u%a6-L1jl+&v8=Es)r^r#FAC+Jf4Rk%yiCdq#K{Lszis=p>ydx-X#qi%ZX(GD zn2Dr77>#D86z6Ga2C7Y$)>E3;7kzr$4&T*rulkTaZZXPQ&F-H~_ZUW+r~*UpRNRW! z*W~yFSxHV$<5DbKb`K$&ff$riB{?oaI?hm*|VhJ2+~9y|G)3Jz--y_J;KH%kk}P4Oem`Gg9eRnxJ7 zeTn#Yt=Wpk5~N9ewNShXci_>^^X6Psft}Mdk{+5I#3(xGia0IELA8uM;g}Usmv}tFv_+p#zY56>P@kYif%G5HpM_KAf0aK?%;eGM|t53hx?Xe}2h0eZkw0r=Y>L+tYp_gzx3Ku}rFiK$H_MAUa3{Pb zBxdQZmg_%S#mX4K>`bW1T5kTuwLO;tIJM5c6i(VQODol%X|s-9tlJ6UGkzYqjjGOX zC)qe`)l)+2q>vUsDP#A(<)xKf?H>Sqn{@77w^JVZGGP-@Ft3|V;spcyuD3`d7%*N2 z3BU?jtxGiFWxnJI7s^jK-7@+zsbFk!F%rCW*15*4vHKNw1?I{YqOYC!;20e?ac@sW z|5#hZ=IZl6Tx+A+%kxw~Ja*Y7&!3Hg3yf9nijYAWK2xP;N3Y(iY7P2XbMvHiqgEQg ztH|$xs3YmNJ8t$|j&$dI;ZPaMC47sMW-*cb>J|e=&`!8@m-? zcw*$?V#TiSaP{YpO)TVwZpz$2nCY zGD(^O?9B#t=U0`;_ed}Lvr5v=@KnVFN(?ust-f_Yd#Q`4D+}cUJGb=|YhLJ73na!l z_aKrX{2p9tT&UEB*P8291Jx4L86KtSYT?Xn$A=)`LJAwMIlSb9==vQ6WD@NgT!5LL znU(D-!Hy4PsfJB(h#;7UZ^^0}&{@5vF!NFgRpe9&Oh%{jcVizL^t%9e0~~19#z7dg zBP_lzd^!orrEIFg6%XV3XRG>@ zKa8btck-?dj2M6-gSR7N05gnlan+Y?k>WBIs>gy7T36#j@y8d1-%$pM@%jKD`}W|; z&XGK64dLa};Xqh*H6QR1<$|;)XUD{8*K(E5{c~*YrRBoi%;{{KdJ9vsk+Xh%1~ZC6 z1GD%0w`F(lgs`$y_64dC(2%Msy7W~J(|N14)UNE~{^FR%w!XA?+*q^s=hSPcWPO03 zTU%$ZT`^7%&P!y=op$0aAcb=5CET-ZS{D)tv^A3w-_pbvJ405|(}{npI8Bqyi>J38 zv&k`Yi_OMP49swuS&=4AcDVsald<5mc$t~8YQ#Iw&NCc|Ia_U--m!FveJ4SuIwM)a zp-!96{a-_#aziHZ>!=X(xPFJNaF*x(t!ese{(^2)foc&r;2|mWUm%0q7I4J`xmho$ z)=-@nxkJ9i_~(p5nx}N_&O_CARH#@+Qd>eu!6q(hr0MkKVpnuz@>jWJEqkF2yfPR&a}Fi-}0k&4n(P1TWw;RV6Av~HUWvU93!->Ih4QVunD0`AUx34GliH_1_6 zwBfi~IPJ@Y_7KuG;T&to7WlLt!ip0SKCfceO#?nYAvwdZXpNZS*!}G+4p4l(R&9B? zbR^oC$ONtg0V)I{iUndH&DkN<*T|}*y=^KW+=WB~S!pG|c}AT!$7vtAWU5MPx~ntD z=XQ7feygkgt~;?(HPHM772BpwNI1=6#j>+IFG4zTNuALi;{I*M;Y#;FZjIEHNY3e3 zg#bP|KRh-$p0Z%Q8b>H$zjXWb(P!DUCGe~+R36epXCJEWr&KrI4X$lNWV?GwM_hJm z6_e~~jZ4H?Y91w*=e$3?VKc0vSw>Z_CLO+yU8_yKwLBQC|HGe=u)bg*g~F`| zx9D?6RUVPV-(S{ zHSb9{l71ctYpQy`r#P?Dr9hmU$@#xsqyiw$8#}+=k3XZ{?~hwH>wT)$Avzx+C>Qx* zdLmM)yQ|9xfRX`?dYcU22irB=1tQq^qZS{amPt1$>I~qObvl;C@pi<1TQV}u4YnEF zBI$&5cA;duh6nlkqya38S!VdpY1penQzoi2V}KJzoa6oNs^{pt&{+?`*a^c?^3aFc{L>^DFX=HjDZAf z=c6P5i2~lnuL=j;%0?%p0^*p&mE|1sSSej+J>ak$@^BzmRl^t+pEZI}A4Fvoeo@=E zT-*y9`%xNDmoR&aix^)jhH$6U{j*;XX7A-H%c`Y4#$Ih&mH$fM1<)@w!X)mK)n(Ph znmbkjvYz`Zx!K<%%p@*fzkCw#wdg*IzdISo=WcAE5QY~jr|p0xHBQ((W?8sB1v$!* zLu(xV6*fk^=wn?@$n!F9D+8X%(tO7-zQrH%!XZuwxh{aD~}cbvbCc6V!n@OECLwR}qv z+2}u%K_Fi8DcVtc3%FS!W?N&qp_A&eZt#(TMLjpl#m?&5Z9ZyjVWRP z)_gD^@L#!ZF~?Y*82bO()TDYO#R<2=DdoWnc`k1jbG-n!by60DyUKk|+C z1^YJwn7&Ik!T8Pfe(iQ zpm-sS(yC1;0RZ-jTjqvs;_guA&lYkVe4cjNvmDDUt5$q5VsCJG5arPA#X9D-8C*Mc z#THvf2SxjoBSg>D%sG%d1ANa$yedv_26zg9DKUmaHxhw5xt6?z!~CC-$hZ+d^PZaWF5i;98hLj&JU?r6fG7v> zU1)Ww-g__J{@{{!%sBILYBwjzgABwkB9$0l(dxe)P}jEHwmvz{!n7-?07#mcJS4-B zB@%6O_|qOqP5{bl2t#6_u#N##={uQk`6HWMXL`2{<9sgj<<*fU+X4xXLt;)xGfq-m zg+M&Txkokx1I1*J@;D{`L|rHCcy!1gG)!RI+KXwGVw(i1-Jd$TgWlHYYoG=grW}s0 zj`|P&ZBy_(N~Qi&MQYAlDLdjy;{?DQuC_Xgz#!(T5CX@sPJiKlqwxoWlnLQPKZ3cI>n~Lc)NO#pZ~cG`E9y zuQja4(u?HsR|moNES%aM9uXM*>Rvh~hz`)Z1@XTIauuh;RZ9Sq7~dz^=G6vN<5D|h zTIHCO`Y!(d>RI2lu19iWig}eZUOd>X0Q{pK@cuNRKl;EEJKHhjAgoGOL}lL1C51JI#5?ZXsvYc6C2?{GIZ z)pkxAlITmBhp0UsVhtrk-EiPBSwLN9cTE2=xvPJvpUlXsiq(Bg;&0Qcgt>s(A*;f{ zKh~VQP&b~TKvpN0cI6`-)Wl>EngbfSjdvs#BD>}_IgdL#I{mMFP7Y@z6k5+2o&Iyo z(2U1JljQV>Z+EP2Mqw(R&#c*_*FH(w?a$AXD46NTf#;;O$&uTt(Y+8uKbNTVme32n zwoVAHKhvC3QVc;m#0Z>jOEA)*`~0WItJzpjuM5d{dZ&xB`A9Lf+3#+JSoG z9Lc)=jDavv;*HNAWDMu4!{aW)SY$-wW&hDLS3dV< zHEqFO%2HBoVO~mvfTs%d&M%S7qx=(yT7UQN77z}a{EhY~UWZNn>Q|vZ3ZeFybWMwa zwOF*)OvKu%`FvqBElIl6d7aZ;d)$M8vF6{ldLA0PTcrD_Y>*M^vbqqYf9PA_Stbl+ z=0~^YqCif$IOfQuh`w4g^n!haI<<@$n(l5ae}Fg ziPP**YV%;)!fDZY$Bz*ayaS7$D*a1|t96}1eBRF?45m6DA^k^xbEqw2mJRfKm-ORZ zQkP@q`jM)*;u4tJ<((0auc5Cm8)Q~VABr4wSx?k^7B+Yn^(F^Q!76>8RjIrz%Pyt& zCuBmt_x`&Ld}QRCh=IDyGoGJRu{M>wAQ-xk^qh6()53Zhg zotRqJ%j!MH)J0)kqIJuHtxk|;ZhKa)P=I@TJ5t81@?52j3qG&6tp6o9vUEP8&^lr~ z(2Ji8rG=V|Xr$=6#lDLP}>f|9<17nTf z_9Te?9w}~7qK03tZpzN>dYhX`?6G<_V)8LjQb;PAS`APv)@%(}wp#t%YI9jN@M=~6 he|+5R-%IOGJh*(SQ|OZU0r2nSG2f%4!xw)1e*ipmfsz0K literal 0 HcmV?d00001 From 2d61492ffff1671e43a0c12b8d09e897ec07d92b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 4 Sep 2018 16:34:33 -0400 Subject: [PATCH 06/14] Depend on pub_sub --- pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pubspec.yaml b/pubspec.yaml index 3a931fbd..dc12e555 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,3 +11,4 @@ dependencies: args: ^1.0.0 io: ^0.3.2 logging: ^0.11.3 + pub_sub: ^2.0.0 From 221dda89a1aa3b57cb5642f86d43d5264ba8f70c Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 4 Sep 2018 18:00:53 -0400 Subject: [PATCH 07/14] README + add pub_sub --- README.md | 22 +++++++++++++ example/main.dart | 25 ++++++++++++++ lib/angel_production.dart | 1 + lib/src/instance_info.dart | 6 ++++ lib/src/runner.dart | 67 +++++++++++++++++++++++++++++--------- 5 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 lib/src/instance_info.dart diff --git a/README.md b/README.md index d95ad8b6..50eba889 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,28 @@ It is injected into your application's `Container` as `pub_sub.Client`, so you can use it as follows: ```dart +// Use the injected `pub_sub.Client` to send messages. +var client = app.container.make(); + +// We can listen for an event to perform some behavior. +// +// Here, we use message passing to synchronize some common state. +var onGreetingChanged = await client.subscribe('user_upgraded'); +onGreetingChanged + .cast() + .listen((user) { + // Do something... + }); +``` + +## Run-time Metadata +At run-time, you may want to know information about the currently-running instance, +for example, which number instance. For this, the `InstanceInfo` class is injected +into each instance: + +```dart +var instanceInfo = app.container.make(); +print('This is instance #${instanceInfo.id}'); ``` ## Command-line Options diff --git a/example/main.dart b/example/main.dart index 11d13736..7fc28738 100644 --- a/example/main.dart +++ b/example/main.dart @@ -2,12 +2,37 @@ import 'dart:async'; import 'dart:isolate'; import 'package:angel_framework/angel_framework.dart'; import 'package:angel_production/angel_production.dart'; +import 'package:pub_sub/pub_sub.dart' as pub_sub; main(List args) => new Runner('example', configureServer).run(args); Future configureServer(Angel app) async { + // Use the injected `pub_sub.Client` to send messages. + var client = app.container.make(); + var greeting = 'Hello! This is the default greeting.'; + + // We can listen for an event to perform some behavior. + // + // Here, we use message passing to synchronize some common state. + var onGreetingChanged = await client.subscribe('greeting_changed'); + onGreetingChanged + .cast() + .listen((newGreeting) => greeting = newGreeting); + + // Add some routes... app.get('/', (req, res) => 'Hello, production world!'); + // Create some routes to demonstrate message passing. + app.get('/greeting', (req, res) => greeting); + + // This route will push a new value for `greeting`. + app.get('/change_greeting/:newGreeting', (req, res) { + greeting = req.params['newGreeting'] as String; + client.publish('greeting_changed', greeting); + return 'Changed greeting -> $greeting'; + }); + + // The `Runner` helps with fault tolerance. app.get('/crash', (req, res) { // We'll crash this instance deliberately, but the Runner will auto-respawn for us. new Timer(const Duration(seconds: 3), Isolate.current.kill); diff --git a/lib/angel_production.dart b/lib/angel_production.dart index 6488127f..1e376f25 100644 --- a/lib/angel_production.dart +++ b/lib/angel_production.dart @@ -1,2 +1,3 @@ +export 'src/instance_info.dart'; export 'src/options.dart'; export 'src/runner.dart'; \ No newline at end of file diff --git a/lib/src/instance_info.dart b/lib/src/instance_info.dart new file mode 100644 index 00000000..a19e9dfe --- /dev/null +++ b/lib/src/instance_info.dart @@ -0,0 +1,6 @@ +/// Information about the currently-running instance. +class InstanceInfo { + final int id; + + const InstanceInfo({this.id}); +} \ No newline at end of file diff --git a/lib/src/runner.dart b/lib/src/runner.dart index 3212d4ca..34c2faf8 100644 --- a/lib/src/runner.dart +++ b/lib/src/runner.dart @@ -4,9 +4,12 @@ import 'dart:isolate'; import 'package:angel_container/angel_container.dart'; import 'package:angel_framework/angel_framework.dart'; import 'package:args/args.dart'; -import 'package:logging/logging.dart'; import 'package:io/ansi.dart'; import 'package:io/io.dart'; +import 'package:logging/logging.dart'; +import 'package:pub_sub/isolate.dart' as pub_sub; +import 'package:pub_sub/pub_sub.dart' as pub_sub; +import 'instance_info.dart'; import 'options.dart'; /// A command-line utility for easier running of multiple instances of an Angel application. @@ -68,18 +71,20 @@ _ ___ | /| / / /_/ / _ /___ _ /___ /// The returned [Future] completes when the application instance exits. /// /// If respawning is enabled, the [Future] will *never* complete. - Future spawnIsolate(RunnerOptions options) { - return _spawnIsolate(new Completer(), options); + Future spawnIsolate(int id, RunnerOptions options, SendPort pubSubSendPort) { + return _spawnIsolate(id, new Completer(), options, pubSubSendPort); } - Future _spawnIsolate(Completer c, RunnerOptions options) { + Future _spawnIsolate( + int id, Completer c, RunnerOptions options, SendPort pubSubSendPort) { var onLogRecord = new ReceivePort(); var onExit = new ReceivePort(); var onError = new ReceivePort(); - var runnerArgs = new _RunnerArgs( - name, configureServer, options, reflector, onLogRecord.sendPort); + var runnerArgs = new _RunnerArgs(name, configureServer, options, reflector, + onLogRecord.sendPort, pubSubSendPort); + var argsWithId = new _RunnerArgsWithId(id, runnerArgs); - Isolate.spawn(isolateMain, runnerArgs, + Isolate.spawn(isolateMain, argsWithId, onExit: onExit.sendPort, onError: onError.sendPort, errorsAreFatal: true && false) @@ -103,9 +108,9 @@ _ ___ | /| / / /_/ / _ /___ _ /___ if (options.respawn) { handleLogRecord(new LogRecord( Level.WARNING, - 'Detected a crashed instance at ${new DateTime.now()}. Respawning immediately...', + 'Instance #$id at ${new DateTime.now()}. Respawning immediately...', runnerArgs.loggerName)); - _spawnIsolate(c, options); + _spawnIsolate(id, c, options, pubSubSendPort); } else { c.complete(); } @@ -119,6 +124,8 @@ _ ___ | /| / / /_/ / _ /___ _ /___ /// Starts a number of isolates, running identical instances of an Angel application. Future run(List args) async { + pub_sub.Server server; + try { var argResults = RunnerOptions.argParser.parse(args); var options = new RunnerOptions.fromArgResults(argResults); @@ -137,8 +144,18 @@ _ ___ | /| / / /_/ / _ /___ _ /___ print('Starting `${name}` application...'); print('Arguments: $args...\n'); - await Future.wait( - new List.generate(options.concurrency, (_) => spawnIsolate(options))); + var adapter = new pub_sub.IsolateAdapter(); + server = new pub_sub.Server([adapter]); + + // Register clients + for (int i = 0; i < Platform.numberOfProcessors; i++) { + server.registerClient(new pub_sub.ClientInfo('client$i')); + } + + server.start(); + + await Future.wait(new List.generate(options.concurrency, + (id) => spawnIsolate(id, options, adapter.receivePort.sendPort))); } on ArgParserException catch (e) { stderr ..writeln(e.message) @@ -149,10 +166,13 @@ _ ___ | /| / / /_/ / _ /___ _ /___ } catch (e) { stderr..writeln('fatal error: $e'); exitCode = 1; + } finally { + server?.close(); } } - static void isolateMain(_RunnerArgs args) { + static void isolateMain(_RunnerArgsWithId argsWithId) { + var args = argsWithId.args; hierarchicalLoggingEnabled = true; var zone = Zone.current.fork(specification: new ZoneSpecification( @@ -163,7 +183,15 @@ _ ___ | /| / / /_/ / _ /___ _ /___ )); zone.run(() async { - var app = new Angel(reflector: args.reflector); + var client = new pub_sub.IsolateClient( + 'client${argsWithId.id}', args.pubSubSendPort); + + var app = new Angel(reflector: args.reflector) + ..container.registerSingleton(client) + ..container.registerSingleton(new InstanceInfo(id: argsWithId.id)); + + app.shutdownHooks.add((_) => client.close()); + await app.configure(args.configureServer); if (app.logger == null) { @@ -177,11 +205,18 @@ _ ___ | /| / / /_/ / _ /___ _ /___ await http.startServer(args.options.hostname, args.options.port); var url = new Uri( scheme: 'http', host: server.address.address, port: server.port); - print('Listening at $url'); + print('Instance #${argsWithId.id} listening at $url'); }); } } +class _RunnerArgsWithId { + final int id; + final _RunnerArgs args; + + _RunnerArgsWithId(this.id, this.args); +} + class _RunnerArgs { final String name; @@ -191,10 +226,10 @@ class _RunnerArgs { final Reflector reflector; - final SendPort loggingSendPort; + final SendPort loggingSendPort, pubSubSendPort; _RunnerArgs(this.name, this.configureServer, this.options, this.reflector, - this.loggingSendPort); + this.loggingSendPort, this.pubSubSendPort); String get loggerName => name; } From 2c6b12a59c9a92ed619cd7bcecd514ff9e4ab748 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 6 Nov 2018 15:42:59 -0500 Subject: [PATCH 08/14] Imports --- CHANGELOG.md | 3 + example/main.dill | 183470 ++++++++++++++++++++++++++++++++++ example/main.dill.map | 1 + example/main.dill.txt | 18711 ++++ lib/angel_production.dart | 2 +- lib/src/instance_info.dart | 2 +- lib/src/runner.dart | 1 + pubspec.yaml | 2 +- 8 files changed, 202189 insertions(+), 3 deletions(-) create mode 100644 example/main.dill create mode 100644 example/main.dill.map create mode 100644 example/main.dill.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d229054..4e6a03a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,5 @@ +# 1.0.0-alpha.1 +* Import `framework/http`. + # 1.0.0-alpha * Initial version. \ No newline at end of file diff --git a/example/main.dill b/example/main.dill new file mode 100644 index 00000000..ade02195 --- /dev/null +++ b/example/main.dill @@ -0,0 +1,183470 @@ +define(['dart_sdk'], function(dart_sdk) { + 'use strict'; + const core = dart_sdk.core; + const async = dart_sdk.async; + const isolate = dart_sdk.isolate; + const _http = dart_sdk._http; + const io = dart_sdk.io; + const _interceptors = dart_sdk._interceptors; + const _js_helper = dart_sdk._js_helper; + const collection = dart_sdk.collection; + const convert = dart_sdk.convert; + const _internal = dart_sdk._internal; + const math = dart_sdk.math; + const _native_typed_data = dart_sdk._native_typed_data; + const typed_data = dart_sdk.typed_data; + const dart = dart_sdk.dart; + const dartx = dart_sdk.dartx; + const _root = Object.create(null); + const main = Object.create(_root); + const angel_framework = Object.create(_root); + const angel_production = Object.create(_root); + const pub_sub = Object.create(_root); + const src__core__core = Object.create(_root); + const src__http__http = Object.create(_root); + const src__instance_info = Object.create(_root); + const src__options = Object.create(_root); + const src__runner = Object.create(_root); + const src__protocol__protocol = Object.create(_root); + const src__core__anonymous_service = Object.create(_root); + const src__core__hooked_service = Object.create(_root); + const src__core__map_service = Object.create(_root); + const src__core__metadata = Object.create(_root); + const src__core__request_context = Object.create(_root); + const src__core__response_context = Object.create(_root); + const src__core__routable = Object.create(_root); + const src__core__server = Object.create(_root); + const src__core__service = Object.create(_root); + const src__core__typed_service = Object.create(_root); + const angel_http_exception = Object.create(_root); + const angel_model = Object.create(_root); + const angel_route = Object.create(_root); + const body_parser = Object.create(_root); + const src__http__angel_http = Object.create(_root); + const src__http__controller = Object.create(_root); + const src__http__http_request_context = Object.create(_root); + const src__http__http_response_context = Object.create(_root); + const args = Object.create(_root); + const angel_container = Object.create(_root); + const ansi = Object.create(_root); + const io$ = Object.create(_root); + const logging = Object.create(_root); + const isolate$ = Object.create(_root); + const src__protocol__client__sync_client = Object.create(_root); + const src__protocol__server__sync_server = Object.create(_root); + const src__util = Object.create(_root); + const http_parser = Object.create(_root); + const meta = Object.create(_root); + const path$ = Object.create(_root); + const file = Object.create(_root); + const mime = Object.create(_root); + const combinator = Object.create(_root); + const tuple = Object.create(_root); + const merge_map = Object.create(_root); + const convert$ = Object.create(_root); + const src__middleware_pipeline = Object.create(_root); + const src__router = Object.create(_root); + const src__routing_exception = Object.create(_root); + const src__body_parse_result = Object.create(_root); + const src__file_upload_info = Object.create(_root); + const src__parse_body = Object.create(_root); + const stack_trace = Object.create(_root); + const src__arg_parser = Object.create(_root); + const src__arg_parser_exception = Object.create(_root); + const src__arg_results = Object.create(_root); + const src__option = Object.create(_root); + const src__container = Object.create(_root); + const src__empty__empty = Object.create(_root); + const src__exception = Object.create(_root); + const src__reflector = Object.create(_root); + const src__ansi_code = Object.create(_root); + const src__copy_path = Object.create(_root); + const src__exit_code = Object.create(_root); + const src__permissions = Object.create(_root); + const src__process_manager = Object.create(_root); + const src__shared_stdin = Object.create(_root); + const src__shell_words = Object.create(_root); + const src__isolate__client = Object.create(_root); + const src__isolate__server = Object.create(_root); + const src__protocol__client__client = Object.create(_root); + const src__protocol__server__adapter = Object.create(_root); + const src__protocol__server__client = Object.create(_root); + const src__protocol__server__publish = Object.create(_root); + const src__protocol__server__server = Object.create(_root); + const src__protocol__server__subscription = Object.create(_root); + const src__authentication_challenge = Object.create(_root); + const src__case_insensitive_map = Object.create(_root); + const src__chunked_coding = Object.create(_root); + const src__http_date = Object.create(_root); + const src__media_type = Object.create(_root); + const src__context = Object.create(_root); + const src__style = Object.create(_root); + const src__path_exception = Object.create(_root); + const src__path_map = Object.create(_root); + const src__path_set = Object.create(_root); + const src__forwarding = Object.create(_root); + const src__interface = Object.create(_root); + const src__mime_multipart_transformer = Object.create(_root); + const src__mime_shared = Object.create(_root); + const src__mime_type = Object.create(_root); + const src__combinator__combinator = Object.create(_root); + const src__error = Object.create(_root); + const core$ = Object.create(_root); + const string_scanner = Object.create(_root); + const string_util = Object.create(_root); + const http_server = Object.create(_root); + const src__map_from_uri = Object.create(_root); + const src__chain = Object.create(_root); + const src__frame = Object.create(_root); + const src__trace = Object.create(_root); + const src__unparsed_frame = Object.create(_root); + const src__allow_anything_parser = Object.create(_root); + const src__parser = Object.create(_root); + const src__usage = Object.create(_root); + const collection$ = Object.create(_root); + const charcode = Object.create(_root); + const uuid = Object.create(_root); + const src__scan = Object.create(_root); + const src__utils = Object.create(_root); + const src__chunked_coding__encoder = Object.create(_root); + const src__chunked_coding__decoder = Object.create(_root); + const src__characters = Object.create(_root); + const src__internal_style = Object.create(_root); + const src__parsed_path = Object.create(_root); + const src__style__posix = Object.create(_root); + const src__style__url = Object.create(_root); + const src__style__windows = Object.create(_root); + const src__forwarding__forwarding_directory = Object.create(_root); + const src__forwarding__forwarding_file = Object.create(_root); + const src__forwarding__forwarding_file_system = Object.create(_root); + const src__forwarding__forwarding_file_system_entity = Object.create(_root); + const src__forwarding__forwarding_link = Object.create(_root); + const src__interface__directory = Object.create(_root); + const src__interface__error_codes = Object.create(_root); + const src__interface__file = Object.create(_root); + const src__interface__file_system = Object.create(_root); + const src__interface__file_system_entity = Object.create(_root); + const src__interface__link = Object.create(_root); + const src__io = Object.create(_root); + const src__bound_multipart_stream = Object.create(_root); + const src__char_code = Object.create(_root); + const src__default_extension_map = Object.create(_root); + const src__magic_number = Object.create(_root); + const code_buffer = Object.create(_root); + const matcher = Object.create(_root); + const source_span = Object.create(_root); + const src__exception$ = Object.create(_root); + const src__line_scanner = Object.create(_root); + const src__span_scanner = Object.create(_root); + const src__string_scanner = Object.create(_root); + const src__http_body = Object.create(_root); + const src__http_multipart_form_data = Object.create(_root); + const src__virtual_directory = Object.create(_root); + const src__virtual_host = Object.create(_root); + const src__get_value = Object.create(_root); + const src__lazy_chain = Object.create(_root); + const src__stack_zone_specification = Object.create(_root); + const src__utils$ = Object.create(_root); + const src__lazy_trace = Object.create(_root); + const src__vm_trace = Object.create(_root); + const src__algorithms = Object.create(_root); + const src__canonicalized_map = Object.create(_root); + const src__combined_wrappers__combined_iterable = Object.create(_root); + const src__combined_wrappers__combined_list = Object.create(_root); + const src__combined_wrappers__combined_map = Object.create(_root); + const src__comparators = Object.create(_root); + const src__equality = Object.create(_root); + const src__equality_map = Object.create(_root); + const src__equality_set = Object.create(_root); + const src__functions = Object.create(_root); + const src__iterable_zip = Object.create(_root); + const src__priority_queue = Object.create(_root); + const src__queue_list = Object.create(_root); + const src__union_set = Object.create(_root); + const src__union_set_controller = Object.create(_root); + const src__unmodifiable_wrappers = Object.create(_root); + const src__wrappers = Object.create(_root); + const ascii = Object.create(_root); + const html_entity = Object.create(_root); + const uuid_util = Object.create(_root); + const crypto = Object.create(_root); + const convert$0 = Object.create(_root); + const typed_data$ = Object.create(_root); + const src__utils$0 = Object.create(_root); + const src__interface__error_codes_dart_io = Object.create(_root); + const src__core_matchers = Object.create(_root); + const src__custom_matcher = Object.create(_root); + const src__description = Object.create(_root); + const src__equals_matcher = Object.create(_root); + const src__error_matchers = Object.create(_root); + const src__interfaces = Object.create(_root); + const src__iterable_matchers = Object.create(_root); + const src__map_matchers = Object.create(_root); + const src__numeric_matchers = Object.create(_root); + const src__operator_matchers = Object.create(_root); + const src__order_matchers = Object.create(_root); + const src__string_matchers = Object.create(_root); + const src__type_matcher = Object.create(_root); + const src__util$ = Object.create(_root); + const src__file = Object.create(_root); + const src__location = Object.create(_root); + const src__location_mixin = Object.create(_root); + const src__span = Object.create(_root); + const src__span_exception = Object.create(_root); + const src__span_mixin = Object.create(_root); + const src__span_with_context = Object.create(_root); + const src__eager_span_scanner = Object.create(_root); + const src__relative_span_scanner = Object.create(_root); + const src__utils$1 = Object.create(_root); + const src__http_body_impl = Object.create(_root); + const src__http_multipart_form_data_impl = Object.create(_root); + const src__utils$2 = Object.create(_root); + const src__empty_unmodifiable_set = Object.create(_root); + const aes = Object.create(_root); + const src__digest = Object.create(_root); + const src__hash = Object.create(_root); + const src__hmac = Object.create(_root); + const src__md5 = Object.create(_root); + const src__sha1 = Object.create(_root); + const src__sha256 = Object.create(_root); + const src__accumulator_sink = Object.create(_root); + const src__byte_accumulator_sink = Object.create(_root); + const src__hex = Object.create(_root); + const src__percent = Object.create(_root); + const src__string_accumulator_sink = Object.create(_root); + const typed_buffers = Object.create(_root); + const src__feature_matcher = Object.create(_root); + const src__pretty_print = Object.create(_root); + const src__having_matcher = Object.create(_root); + const src__colors = Object.create(_root); + const src__utils$3 = Object.create(_root); + const src__digest_sink = Object.create(_root); + const src__hash_sink = Object.create(_root); + const src__utils$4 = Object.create(_root); + const src__hex__encoder = Object.create(_root); + const src__hex__decoder = Object.create(_root); + const src__percent__encoder = Object.create(_root); + const src__percent__decoder = Object.create(_root); + const src__utils$5 = Object.create(_root); + const $_get = dartx._get; + const $toString = dartx.toString; + const $trim = dartx.trim; + const $add = dartx.add; + const $isEmpty = dartx.isEmpty; + const $first = dartx.first; + const $_equals = dartx._equals; + const $addAll = dartx.addAll; + const $clear = dartx.clear; + const $replaceAll = dartx.replaceAll; + const $_set = dartx._set; + const $fold = dartx.fold; + const $insertAll = dartx.insertAll; + const $isNotEmpty = dartx.isNotEmpty; + const $length = dartx.length; + const $removeLast = dartx.removeLast; + const $join = dartx.join; + const $putIfAbsent = dartx.putIfAbsent; + const $contains = dartx.contains; + const $keys = dartx.keys; + const $split = dartx.split; + const $where = dartx.where; + const $forEach = dartx.forEach; + const $map = dartx.map; + const $containsKey = dartx.containsKey; + const $toList = dartx.toList; + const $firstWhere = dartx.firstWhere; + const $runtimeType = dartx.runtimeType; + const $any = dartx.any; + const $remove = dartx.remove; + const $last = dartx.last; + const $values = dartx.values; + const $toLowerCase = dartx.toLowerCase; + const $toUpperCase = dartx.toUpperCase; + const $startsWith = dartx.startsWith; + const $lastIndexOf = dartx.lastIndexOf; + const $substring = dartx.substring; + const $compareTo = dartx.compareTo; + const $hashCode = dartx.hashCode; + const $take = dartx.take; + const $codeUnits = dartx.codeUnits; + const $toSet = dartx.toSet; + const $sort = dartx.sort; + const $leftShift = dartx['<<']; + const $addEntries = dartx.addEntries; + const $cast = dartx.cast; + const $entries = dartx.entries; + const $removeWhere = dartx.removeWhere; + const $update = dartx.update; + const $updateAll = dartx.updateAll; + const $containsValue = dartx.containsValue; + const $indexOf = dartx.indexOf; + const $replaceAllMapped = dartx.replaceAllMapped; + const $insert = dartx.insert; + const $removeAt = dartx.removeAt; + const $codeUnitAt = dartx.codeUnitAt; + const $endsWith = dartx.endsWith; + const $iterator = dartx.iterator; + const $setRange = dartx.setRange; + const $reduce = dartx.reduce; + const $elementAt = dartx.elementAt; + const $rightShift = dartx['>>']; + const $skip = dartx.skip; + const $single = dartx.single; + const $expand = dartx.expand; + const $padRight = dartx.padRight; + const $allMatches = dartx.allMatches; + const $skipWhile = dartx.skipWhile; + const $reversed = dartx.reversed; + const $sublist = dartx.sublist; + const $removeRange = dartx.removeRange; + const $times = dartx['*']; + const $modulo = dartx['%']; + const $toRadixString = dartx.toRadixString; + const $asUint8List = dartx.asUint8List; + const $lastWhere = dartx.lastWhere; + const $replaceFirst = dartx.replaceFirst; + const $matchAsPrefix = dartx.matchAsPrefix; + const $isNaN = dartx.isNaN; + const $every = dartx.every; + const $sign = dartx.sign; + const $followedBy = dartx.followedBy; + const $singleWhere = dartx.singleWhere; + const $takeWhile = dartx.takeWhile; + const $whereType = dartx.whereType; + const $isOdd = dartx.isOdd; + const $truncate = dartx.truncate; + const $fillRange = dartx.fillRange; + const $plus = dartx['+']; + const $asMap = dartx.asMap; + const $getRange = dartx.getRange; + const $indexWhere = dartx.indexWhere; + const $lastIndexWhere = dartx.lastIndexWhere; + const $replaceRange = dartx.replaceRange; + const $retainWhere = dartx.retainWhere; + const $setAll = dartx.setAll; + const $shuffle = dartx.shuffle; + const $floor = dartx.floor; + const $toInt = dartx.toInt; + const $runes = dartx.runes; + const $padLeft = dartx.padLeft; + const $abs = dartx.abs; + const $buffer = dartx.buffer; + const $lengthInBytes = dartx.lengthInBytes; + const $asByteData = dartx.asByteData; + const $setUint32 = dartx.setUint32; + const $getUint32 = dartx.getUint32; + const $elementSizeInBytes = dartx.elementSizeInBytes; + const $offsetInBytes = dartx.offsetInBytes; + const $isEven = dartx.isEven; + let AngelToFuture = () => (AngelToFuture = dart.constFn(dart.fnType(async.Future, [src__core__server.Angel])))(); + let StringTovoid = () => (StringTovoid = dart.constFn(dart.fnType(dart.void, [core.String])))(); + let RequestContextAndResponseContextToString = () => (RequestContextAndResponseContextToString = dart.constFn(dart.fnType(core.String, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let FutureOfHttpServer = () => (FutureOfHttpServer = dart.constFn(async.Future$(_http.HttpServer)))(); + let dynamicAndintToFutureOfHttpServer = () => (dynamicAndintToFutureOfHttpServer = dart.constFn(dart.fnType(FutureOfHttpServer(), [dart.dynamic, core.int])))(); + let _RunnerArgsWithIdTovoid = () => (_RunnerArgsWithIdTovoid = dart.constFn(dart.fnType(dart.void, [src__runner._RunnerArgsWithId])))(); + let IsolateToNull = () => (IsolateToNull = dart.constFn(dart.fnType(core.Null, [isolate.Isolate])))(); + let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.fnType(dart.void, [dart.dynamic])))(); + let dynamicToNull = () => (dynamicToNull = dart.constFn(dart.fnType(core.Null, [dart.dynamic])))(); + let JSArrayOfAdapter = () => (JSArrayOfAdapter = dart.constFn(_interceptors.JSArray$(src__protocol__server__adapter.Adapter)))(); + let ListOfFuture = () => (ListOfFuture = dart.constFn(core.List$(async.Future)))(); + let intToFuture = () => (intToFuture = dart.constFn(dart.fnType(async.Future, [core.int])))(); + let ZoneAndZoneDelegateAndZone__ToNull = () => (ZoneAndZoneDelegateAndZone__ToNull = dart.constFn(dart.fnType(core.Null, [async.Zone, async.ZoneDelegate, async.Zone, core.String])))(); + let FutureOfNull = () => (FutureOfNull = dart.constFn(async.Future$(core.Null)))(); + let LogRecordTovoid = () => (LogRecordTovoid = dart.constFn(dart.fnType(dart.void, [logging.LogRecord])))(); + let VoidToFutureOfNull = () => (VoidToFutureOfNull = dart.constFn(dart.fnType(FutureOfNull(), [])))(); + let VoidToFutureOr = () => (VoidToFutureOr = dart.constFn(dart.fnType(async.FutureOr, [])))(); + let RequestContextAndResponseContextToFutureOr = () => (RequestContextAndResponseContextToFutureOr = dart.constFn(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let JSArrayOfRequestContextAndResponseContextToFutureOr = () => (JSArrayOfRequestContextAndResponseContextToFutureOr = dart.constFn(_interceptors.JSArray$(RequestContextAndResponseContextToFutureOr())))(); + let dynamicTodynamic = () => (dynamicTodynamic = dart.constFn(dart.fnType(dart.dynamic, [dart.dynamic])))(); + let IdentityMapOfString$Providers = () => (IdentityMapOfString$Providers = dart.constFn(_js_helper.IdentityMap$(core.String, src__core__service.Providers)))(); + let ListOfRequestContextAndResponseContextToFutureOr = () => (ListOfRequestContextAndResponseContextToFutureOr = dart.constFn(core.List$(RequestContextAndResponseContextToFutureOr())))(); + let JSArrayOfMap = () => (JSArrayOfMap = dart.constFn(_interceptors.JSArray$(core.Map)))(); + let MapOfString$dynamic = () => (MapOfString$dynamic = dart.constFn(core.Map$(core.String, dart.dynamic)))(); + let MapOfString$dynamicToFuture = () => (MapOfString$dynamicToFuture = dart.constFn(dart.fnType(async.Future, [MapOfString$dynamic()])))(); + let RequestContextAndResponseContextToFuture = () => (RequestContextAndResponseContextToFuture = dart.constFn(dart.fnType(async.Future, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let MapToFuture = () => (MapToFuture = dart.constFn(dart.fnType(async.Future, [core.Map])))(); + let RequestContextAndResponseContextTobottom = () => (RequestContextAndResponseContextTobottom = dart.constFn(dart.fnType(dart.bottom, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let LinkedMapOfPattern$Service = () => (LinkedMapOfPattern$Service = dart.constFn(_js_helper.LinkedMap$(core.Pattern, src__core__service.Service)))(); + let StreamControllerOfService = () => (StreamControllerOfService = dart.constFn(async.StreamController$(src__core__service.Service)))(); + let IterableOfRequestContextAndResponseContextToFutureOr = () => (IterableOfRequestContextAndResponseContextToFutureOr = dart.constFn(core.Iterable$(RequestContextAndResponseContextToFutureOr())))(); + let MapOfPattern$Router = () => (MapOfPattern$Router = dart.constFn(core.Map$(core.Pattern, src__router.Router)))(); + let VoidToNull = () => (VoidToNull = dart.constFn(dart.fnType(core.Null, [])))(); + let RouterToNull = () => (RouterToNull = dart.constFn(dart.fnType(core.Null, [src__router.Router])))(); + let ObjectTovoid = () => (ObjectTovoid = dart.constFn(dart.fnType(dart.void, [core.Object])))(); + let JSArrayOfString = () => (JSArrayOfString = dart.constFn(_interceptors.JSArray$(core.String)))(); + let IdentityMapOfString$dynamic = () => (IdentityMapOfString$dynamic = dart.constFn(_js_helper.IdentityMap$(core.String, dart.dynamic)))(); + let BodyParseResultToMapOfString$dynamic = () => (BodyParseResultToMapOfString$dynamic = dart.constFn(dart.fnType(MapOfString$dynamic(), [src__body_parse_result.BodyParseResult])))(); + let ListOfFileUploadInfo = () => (ListOfFileUploadInfo = dart.constFn(core.List$(src__file_upload_info.FileUploadInfo)))(); + let BodyParseResultToListOfFileUploadInfo = () => (BodyParseResultToListOfFileUploadInfo = dart.constFn(dart.fnType(ListOfFileUploadInfo(), [src__body_parse_result.BodyParseResult])))(); + let ListOfint = () => (ListOfint = dart.constFn(core.List$(core.int)))(); + let BodyParseResultToListOfint = () => (BodyParseResultToListOfint = dart.constFn(dart.fnType(ListOfint(), [src__body_parse_result.BodyParseResult])))(); + let FutureOfMapOfString$dynamic = () => (FutureOfMapOfString$dynamic = dart.constFn(async.Future$(MapOfString$dynamic())))(); + let FutureOfBodyParseResult = () => (FutureOfBodyParseResult = dart.constFn(async.Future$(src__body_parse_result.BodyParseResult)))(); + let BodyParseResultToBodyParseResult = () => (BodyParseResultToBodyParseResult = dart.constFn(dart.fnType(src__body_parse_result.BodyParseResult, [src__body_parse_result.BodyParseResult])))(); + let IdentityMapOfString$String = () => (IdentityMapOfString$String = dart.constFn(_js_helper.IdentityMap$(core.String, core.String)))(); + let JSArrayOfCookie = () => (JSArrayOfCookie = dart.constFn(_interceptors.JSArray$(_http.Cookie)))(); + let ConverterOfListOfint$ListOfint = () => (ConverterOfListOfint$ListOfint = dart.constFn(convert.Converter$(ListOfint(), ListOfint())))(); + let IdentityMapOfString$ConverterOfListOfint$ListOfint = () => (IdentityMapOfString$ConverterOfListOfint$ListOfint = dart.constFn(_js_helper.IdentityMap$(core.String, ConverterOfListOfint$ListOfint())))(); + let FutureOfString = () => (FutureOfString = dart.constFn(async.Future$(core.String)))(); + let LinkedHashMapOfString$dynamic = () => (LinkedHashMapOfString$dynamic = dart.constFn(collection.LinkedHashMap$(core.String, dart.dynamic)))(); + let FutureOrOfString = () => (FutureOrOfString = dart.constFn(async.FutureOr$(core.String)))(); + let VoidToFutureOrOfString = () => (VoidToFutureOrOfString = dart.constFn(dart.fnType(FutureOrOfString(), [])))(); + let StringToNull = () => (StringToNull = dart.constFn(dart.fnType(core.Null, [core.String])))(); + let RouterToRoute = () => (RouterToRoute = dart.constFn(dart.fnType(src__router.Route, [src__router.Router])))(); + let MapOfString$dynamicAnddynamicToMapOfString$dynamic = () => (MapOfString$dynamicAnddynamicToMapOfString$dynamic = dart.constFn(dart.fnType(MapOfString$dynamic(), [MapOfString$dynamic(), dart.dynamic])))(); + let JSArrayOfint = () => (JSArrayOfint = dart.constFn(_interceptors.JSArray$(core.int)))(); + let StreamControllerOfHookedServiceEvent = () => (StreamControllerOfHookedServiceEvent = dart.constFn(async.StreamController$(src__core__hooked_service.HookedServiceEvent)))(); + let JSArrayOfStreamControllerOfHookedServiceEvent = () => (JSArrayOfStreamControllerOfHookedServiceEvent = dart.constFn(_interceptors.JSArray$(StreamControllerOfHookedServiceEvent())))(); + let dynamicTobool = () => (dynamicTobool = dart.constFn(dart.fnType(core.bool, [dart.dynamic])))(); + let MapAnddynamicToMap = () => (MapAnddynamicToMap = dart.constFn(dart.fnType(core.Map, [core.Map, dart.dynamic])))(); + let StreamControllerOfHookedServiceEventTovoid = () => (StreamControllerOfHookedServiceEventTovoid = dart.constFn(dart.fnType(dart.void, [StreamControllerOfHookedServiceEvent()])))(); + let HookedServiceEventTodynamic = () => (HookedServiceEventTodynamic = dart.constFn(dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])))(); + let JSArrayOfHookedServiceEventTodynamic = () => (JSArrayOfHookedServiceEventTodynamic = dart.constFn(_interceptors.JSArray$(HookedServiceEventTodynamic())))(); + let FunctionAndHookedServiceEventDispatcherAndboolTovoid = () => (FunctionAndHookedServiceEventDispatcherAndboolTovoid = dart.constFn(dart.fnType(dart.void, [core.Function, src__core__hooked_service.HookedServiceEventDispatcher], [core.bool])))(); + let RequestContextAndResponseContextTobool = () => (RequestContextAndResponseContextTobool = dart.constFn(dart.fnType(core.bool, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let StringToHookedServiceEventDispatcher = () => (StringToHookedServiceEventDispatcher = dart.constFn(dart.fnType(src__core__hooked_service.HookedServiceEventDispatcher, [core.String])))(); + let HookedServiceEventDispatcherTovoid = () => (HookedServiceEventDispatcherTovoid = dart.constFn(dart.fnType(dart.void, [src__core__hooked_service.HookedServiceEventDispatcher])))(); + let dynamicToFuture = () => (dynamicToFuture = dart.constFn(dart.fnType(async.Future, [dart.dynamic])))(); + let HookedServiceEventToFuture = () => (HookedServiceEventToFuture = dart.constFn(dart.fnType(async.Future, [src__core__hooked_service.HookedServiceEvent])))(); + let VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))(); + let FutureOfHookedServiceEvent = () => (FutureOfHookedServiceEvent = dart.constFn(async.Future$(src__core__hooked_service.HookedServiceEvent)))(); + let dynamicToFutureOfHookedServiceEvent = () => (dynamicToFutureOfHookedServiceEvent = dart.constFn(dart.fnType(FutureOfHookedServiceEvent(), [dart.dynamic])))(); + let dynamicToHookedServiceEvent = () => (dynamicToHookedServiceEvent = dart.constFn(dart.fnType(src__core__hooked_service.HookedServiceEvent, [dart.dynamic])))(); + let FutureOrOfHookedServiceEvent = () => (FutureOrOfHookedServiceEvent = dart.constFn(async.FutureOr$(src__core__hooked_service.HookedServiceEvent)))(); + let HookedServiceEventToFutureOrOfHookedServiceEvent = () => (HookedServiceEventToFutureOrOfHookedServiceEvent = dart.constFn(dart.fnType(FutureOrOfHookedServiceEvent(), [src__core__hooked_service.HookedServiceEvent])))(); + let JSArrayOfMapOfString$dynamic = () => (JSArrayOfMapOfString$dynamic = dart.constFn(_interceptors.JSArray$(MapOfString$dynamic())))(); + let MapTobool = () => (MapTobool = dart.constFn(dart.fnType(core.bool, [core.Map])))(); + let FutureOfList = () => (FutureOfList = dart.constFn(async.Future$(core.List)))(); + let MapOfString$dynamicTobool = () => (MapOfString$dynamicTobool = dart.constFn(dart.fnType(core.bool, [MapOfString$dynamic()])))(); + let FutureOfMap = () => (FutureOfMap = dart.constFn(async.Future$(core.Map)))(); + let VoidTobottom = () => (VoidTobottom = dart.constFn(dart.fnType(dart.bottom, [])))(); + let MapToFutureOfMap = () => (MapToFutureOfMap = dart.constFn(dart.fnType(FutureOfMap(), [core.Map])))(); + let MapToMap = () => (MapToMap = dart.constFn(dart.fnType(core.Map, [core.Map])))(); + let CookieTobool = () => (CookieTobool = dart.constFn(dart.fnType(core.bool, [_http.Cookie])))(); + let IdentityMapOfString$Type = () => (IdentityMapOfString$Type = dart.constFn(_js_helper.IdentityMap$(core.String, core.Type)))(); + let IdentityMapOfString$Parameter = () => (IdentityMapOfString$Parameter = dart.constFn(_js_helper.IdentityMap$(core.String, src__core__metadata.Parameter)))(); + let FutureOfbool = () => (FutureOfbool = dart.constFn(async.Future$(core.bool)))(); + let RequestContextAndResponseContextToFutureOfbool = () => (RequestContextAndResponseContextToFutureOfbool = dart.constFn(dart.fnType(FutureOfbool(), [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let ParameterTobool = () => (ParameterTobool = dart.constFn(dart.fnType(core.bool, [src__core__metadata.Parameter])))(); + let LinkedMapOfSymbol$dynamic = () => (LinkedMapOfSymbol$dynamic = dart.constFn(_js_helper.LinkedMap$(core.Symbol, dart.dynamic)))(); + let JSArrayOfObject = () => (JSArrayOfObject = dart.constFn(_interceptors.JSArray$(core.Object)))(); + let StringAndTypeToNull = () => (StringAndTypeToNull = dart.constFn(dart.fnType(core.Null, [core.String, core.Type])))(); + let RequestContextAndResponseContextTodynamic = () => (RequestContextAndResponseContextTodynamic = dart.constFn(dart.fnType(dart.dynamic, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let ReflectedInstanceTobool = () => (ReflectedInstanceTobool = dart.constFn(dart.fnType(core.bool, [src__reflector.ReflectedInstance])))(); + let VoidToFuture = () => (VoidToFuture = dart.constFn(dart.fnType(async.Future, [])))(); + let JSArrayOfAngel = () => (JSArrayOfAngel = dart.constFn(_interceptors.JSArray$(src__core__server.Angel)))(); + let ParseResultOfMapOfString$dynamic = () => (ParseResultOfMapOfString$dynamic = dart.constFn(src__combinator__combinator.ParseResult$(MapOfString$dynamic())))(); + let Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic = () => (Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic = dart.constFn(tuple.Tuple3$(core.List, MapOfString$dynamic(), ParseResultOfMapOfString$dynamic())))(); + let IdentityMapOfString$Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic = () => (IdentityMapOfString$Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic = dart.constFn(_js_helper.IdentityMap$(core.String, Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic())))(); + let LinkedMapOfdynamic$InjectionRequest = () => (LinkedMapOfdynamic$InjectionRequest = dart.constFn(_js_helper.LinkedMap$(dart.dynamic, src__core__request_context.InjectionRequest)))(); + let LinkedMapOfPattern$Controller = () => (LinkedMapOfPattern$Controller = dart.constFn(_js_helper.LinkedMap$(core.Pattern, src__http__controller.Controller)))(); + let AngelToFutureOr = () => (AngelToFutureOr = dart.constFn(dart.fnType(async.FutureOr, [src__core__server.Angel])))(); + let JSArrayOfAngelToFutureOr = () => (JSArrayOfAngelToFutureOr = dart.constFn(_interceptors.JSArray$(AngelToFutureOr())))(); + let AngelHttpExceptionAndRequestContextAndResponseContextToNull = () => (AngelHttpExceptionAndRequestContextAndResponseContextToNull = dart.constFn(dart.fnType(core.Null, [angel_http_exception.AngelHttpException, src__core__request_context.RequestContext, src__core__response_context.ResponseContext])))(); + let ListOfAngel = () => (ListOfAngel = dart.constFn(core.List$(src__core__server.Angel)))(); + let RouterOfRequestContextAndResponseContextToFutureOr = () => (RouterOfRequestContextAndResponseContextToFutureOr = dart.constFn(src__router.Router$(RequestContextAndResponseContextToFutureOr())))(); + let ServiceToNull = () => (ServiceToNull = dart.constFn(dart.fnType(core.Null, [src__core__service.Service])))(); + let StringAndMapToString = () => (StringAndMapToString = dart.constFn(dart.fnType(core.String, [core.String], [core.Map])))(); + let StringAndMapOfString$dynamicToFutureOrOfString = () => (StringAndMapOfString$dynamicToFutureOrOfString = dart.constFn(dart.fnType(FutureOrOfString(), [core.String], [MapOfString$dynamic()])))(); + let dynamicToString = () => (dynamicToString = dart.constFn(dart.fnType(core.String, [dart.dynamic])))(); + let dynamicAndint__ToFutureOfHttpServer = () => (dynamicAndint__ToFutureOfHttpServer = dart.constFn(dart.fnType(FutureOfHttpServer(), [dart.dynamic, core.int], {backlog: core.int, shared: core.bool, v6Only: core.bool})))(); + let ListToHttpServer = () => (ListToHttpServer = dart.constFn(dart.fnType(_http.HttpServer, [core.List])))(); + let HttpServerToFutureOfHttpServer = () => (HttpServerToFutureOfHttpServer = dart.constFn(dart.fnType(FutureOfHttpServer(), [_http.HttpServer])))(); + let dynamicToFutureOfHttpServer = () => (dynamicToFutureOfHttpServer = dart.constFn(dart.fnType(FutureOfHttpServer(), [dart.dynamic])))(); + let MapOfString$dynamicAndRoutingResultToMapOfString$dynamic = () => (MapOfString$dynamicAndRoutingResultToMapOfString$dynamic = dart.constFn(dart.fnType(MapOfString$dynamic(), [MapOfString$dynamic(), src__router.RoutingResult])))(); + let VoidToTuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic = () => (VoidToTuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic = dart.constFn(dart.fnType(Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic(), [])))(); + let VoidToFutureOfbool = () => (VoidToFutureOfbool = dart.constFn(dart.fnType(FutureOfbool(), [])))(); + let dynamicAndStackTraceToNull = () => (dynamicAndStackTraceToNull = dart.constFn(dart.fnType(core.Null, [dart.dynamic, core.StackTrace])))(); + let ObjectTobool = () => (ObjectTobool = dart.constFn(dart.fnType(core.bool, [core.Object])))(); + let dynamicAndStackTraceToFuture = () => (dynamicAndStackTraceToFuture = dart.constFn(dart.fnType(async.Future, [dart.dynamic, core.StackTrace])))(); + let ZoneAndZoneDelegateAndZone__Tovoid = () => (ZoneAndZoneDelegateAndZone__Tovoid = dart.constFn(dart.fnType(dart.void, [async.Zone, async.ZoneDelegate, async.Zone, core.Object, core.StackTrace])))(); + let ResponseContextToFutureOr = () => (ResponseContextToFutureOr = dart.constFn(dart.fnType(async.FutureOr, [src__core__response_context.ResponseContext])))(); + let HttpRequestContextToFuture = () => (HttpRequestContextToFuture = dart.constFn(dart.fnType(async.Future, [src__http__http_request_context.HttpRequestContext])))(); + let boolToFuture = () => (boolToFuture = dart.constFn(dart.fnType(async.Future, [core.bool])))(); + let dynamicToFutureOr = () => (dynamicToFutureOr = dart.constFn(dart.fnType(async.FutureOr, [dart.dynamic])))(); + let FutureAndFnToFuture = () => (FutureAndFnToFuture = dart.constFn(dart.fnType(async.Future, [async.Future, RequestContextAndResponseContextToFutureOr()])))(); + let StringToString = () => (StringToString = dart.constFn(dart.fnType(core.String, [core.String])))(); + let StringTobool = () => (StringTobool = dart.constFn(dart.fnType(core.bool, [core.String])))(); + let FutureOfResponseContext = () => (FutureOfResponseContext = dart.constFn(async.Future$(src__core__response_context.ResponseContext)))(); + let IdentityMapOfString$Route = () => (IdentityMapOfString$Route = dart.constFn(_js_helper.IdentityMap$(core.String, src__router.Route)))(); + let ReflectedInstanceToObject = () => (ReflectedInstanceToObject = dart.constFn(dart.fnType(core.Object, [src__reflector.ReflectedInstance])))(); + let ReflectedDeclarationToNull = () => (ReflectedDeclarationToNull = dart.constFn(dart.fnType(core.Null, [src__reflector.ReflectedDeclaration])))(); + let BodyParseResultToHttpRequestContext = () => (BodyParseResultToHttpRequestContext = dart.constFn(dart.fnType(src__http__http_request_context.HttpRequestContext, [src__body_parse_result.BodyParseResult])))(); + let FutureOfHttpRequestContext = () => (FutureOfHttpRequestContext = dart.constFn(async.Future$(src__http__http_request_context.HttpRequestContext)))(); + let StreamOfListOfint = () => (StreamOfListOfint = dart.constFn(async.Stream$(ListOfint())))(); + let UnmodifiableMapViewOfString$Logger = () => (UnmodifiableMapViewOfString$Logger = dart.constFn(collection.UnmodifiableMapView$(core.String, logging.Logger)))(); + let VoidToLogger = () => (VoidToLogger = dart.constFn(dart.fnType(logging.Logger, [])))(); + let LinkedMapOfString$Logger = () => (LinkedMapOfString$Logger = dart.constFn(_js_helper.LinkedMap$(core.String, logging.Logger)))(); + let StreamControllerOfLogRecord = () => (StreamControllerOfLogRecord = dart.constFn(async.StreamController$(logging.LogRecord)))(); + let IdentityMapOfString$Logger = () => (IdentityMapOfString$Logger = dart.constFn(_js_helper.IdentityMap$(core.String, logging.Logger)))(); + let ParseResultOfString = () => (ParseResultOfString = dart.constFn(src__combinator__combinator.ParseResult$(core.String)))(); + let ParseResultOfStringToString = () => (ParseResultOfStringToString = dart.constFn(dart.fnType(core.String, [ParseResultOfString()])))(); + let ParseResultOfRegExp = () => (ParseResultOfRegExp = dart.constFn(src__combinator__combinator.ParseResult$(core.RegExp)))(); + let ParseResultOfRegExpToRegExp = () => (ParseResultOfRegExpToRegExp = dart.constFn(dart.fnType(core.RegExp, [ParseResultOfRegExp()])))(); + let ParseResultOfbool = () => (ParseResultOfbool = dart.constFn(src__combinator__combinator.ParseResult$(core.bool)))(); + let ParseResultOfboolTobool = () => (ParseResultOfboolTobool = dart.constFn(dart.fnType(core.bool, [ParseResultOfbool()])))(); + let ParserOfObject = () => (ParserOfObject = dart.constFn(src__combinator__combinator.Parser$(core.Object)))(); + let JSArrayOfParserOfObject = () => (JSArrayOfParserOfObject = dart.constFn(_interceptors.JSArray$(ParserOfObject())))(); + let ListOfObject = () => (ListOfObject = dart.constFn(core.List$(core.Object)))(); + let ParseResultOfListOfObject = () => (ParseResultOfListOfObject = dart.constFn(src__combinator__combinator.ParseResult$(ListOfObject())))(); + let ParseResultOfListOfObjectToParameterSegment = () => (ParseResultOfListOfObjectToParameterSegment = dart.constFn(dart.fnType(src__router.ParameterSegment, [ParseResultOfListOfObject()])))(); + let ParseResultToString = () => (ParseResultToString = dart.constFn(dart.fnType(core.String, [src__combinator__combinator.ParseResult])))(); + let ParseResultOfListOfObjectToParsedParameterSegment = () => (ParseResultOfListOfObjectToParsedParameterSegment = dart.constFn(dart.fnType(src__router.ParsedParameterSegment, [ParseResultOfListOfObject()])))(); + let ParseResultOfWildcardSegment = () => (ParseResultOfWildcardSegment = dart.constFn(src__combinator__combinator.ParseResult$(src__router.WildcardSegment)))(); + let ParseResultOfWildcardSegmentToWildcardSegment = () => (ParseResultOfWildcardSegmentToWildcardSegment = dart.constFn(dart.fnType(src__router.WildcardSegment, [ParseResultOfWildcardSegment()])))(); + let ParseResultOfStringToConstantSegment = () => (ParseResultOfStringToConstantSegment = dart.constFn(dart.fnType(src__router.ConstantSegment, [ParseResultOfString()])))(); + let ParserOfRouteSegment = () => (ParserOfRouteSegment = dart.constFn(src__combinator__combinator.Parser$(src__router.RouteSegment)))(); + let JSArrayOfParserOfRouteSegment = () => (JSArrayOfParserOfRouteSegment = dart.constFn(_interceptors.JSArray$(ParserOfRouteSegment())))(); + let JSArrayOfRouteSegment = () => (JSArrayOfRouteSegment = dart.constFn(_interceptors.JSArray$(src__router.RouteSegment)))(); + let ListOfRouteSegment = () => (ListOfRouteSegment = dart.constFn(core.List$(src__router.RouteSegment)))(); + let ParseResultOfListOfRouteSegment = () => (ParseResultOfListOfRouteSegment = dart.constFn(src__combinator__combinator.ParseResult$(ListOfRouteSegment())))(); + let ParseResultOfListOfRouteSegmentToRouteDefinition = () => (ParseResultOfListOfRouteSegmentToRouteDefinition = dart.constFn(dart.fnType(src__router.RouteDefinition, [ParseResultOfListOfRouteSegment()])))(); + let ParseResultOfMapOfString$dynamicToMapOfString$dynamic = () => (ParseResultOfMapOfString$dynamicToMapOfString$dynamic = dart.constFn(dart.fnType(MapOfString$dynamic(), [ParseResultOfMapOfString$dynamic()])))(); + let ParseResultOfList = () => (ParseResultOfList = dart.constFn(src__combinator__combinator.ParseResult$(core.List)))(); + let ParseResultOfListToMapOfString$dynamic = () => (ParseResultOfListToMapOfString$dynamic = dart.constFn(dart.fnType(MapOfString$dynamic(), [ParseResultOfList()])))(); + let ParseResultOfStringToMapOfString$dynamic = () => (ParseResultOfStringToMapOfString$dynamic = dart.constFn(dart.fnType(MapOfString$dynamic(), [ParseResultOfString()])))(); + let IdentityMapOfString$MapOfString$dynamic = () => (IdentityMapOfString$MapOfString$dynamic = dart.constFn(_js_helper.IdentityMap$(core.String, MapOfString$dynamic())))(); + let RoutingResultTovoid = () => (RoutingResultTovoid = dart.constFn(dart.fnType(dart.void, [src__router.RoutingResult])))(); + let JSArrayOfFileUploadInfo = () => (JSArrayOfFileUploadInfo = dart.constFn(_interceptors.JSArray$(src__file_upload_info.FileUploadInfo)))(); + let BytesBuilderAndListOfintToBytesBuilder = () => (BytesBuilderAndListOfintToBytesBuilder = dart.constFn(dart.fnType(io.BytesBuilder, [io.BytesBuilder, ListOfint()])))(); + let BytesBuilderToListOfint = () => (BytesBuilderToListOfint = dart.constFn(dart.fnType(ListOfint(), [io.BytesBuilder])))(); + let FutureOfListOfint = () => (FutureOfListOfint = dart.constFn(async.Future$(ListOfint())))(); + let VoidToFutureOfListOfint = () => (VoidToFutureOfListOfint = dart.constFn(dart.fnType(FutureOfListOfint(), [])))(); + let ListOfintToString = () => (ListOfintToString = dart.constFn(dart.fnType(core.String, [ListOfint()])))(); + let VoidToFutureOfString = () => (VoidToFutureOfString = dart.constFn(dart.fnType(FutureOfString(), [])))(); + let StreamControllerOfListOfint = () => (StreamControllerOfListOfint = dart.constFn(async.StreamController$(ListOfint())))(); + let MimeMultipartToHttpMultipartFormData = () => (MimeMultipartToHttpMultipartFormData = dart.constFn(dart.fnType(src__http_multipart_form_data.HttpMultipartFormData, [src__mime_shared.MimeMultipart])))(); + let BytesBuilderAnddynamicToBytesBuilder = () => (BytesBuilderAnddynamicToBytesBuilder = dart.constFn(dart.fnType(io.BytesBuilder, [io.BytesBuilder, dart.dynamic])))(); + let UnmodifiableMapViewOfString$Option = () => (UnmodifiableMapViewOfString$Option = dart.constFn(collection.UnmodifiableMapView$(core.String, src__option.Option)))(); + let UnmodifiableMapViewOfString$ArgParser = () => (UnmodifiableMapViewOfString$ArgParser = dart.constFn(collection.UnmodifiableMapView$(core.String, src__arg_parser.ArgParser)))(); + let IdentityMapOfString$Option = () => (IdentityMapOfString$Option = dart.constFn(_js_helper.IdentityMap$(core.String, src__option.Option)))(); + let IdentityMapOfString$ArgParser = () => (IdentityMapOfString$ArgParser = dart.constFn(_js_helper.IdentityMap$(core.String, src__arg_parser.ArgParser)))(); + let ListOfString = () => (ListOfString = dart.constFn(core.List$(core.String)))(); + let OptionTobool = () => (OptionTobool = dart.constFn(dart.fnType(core.bool, [src__option.Option])))(); + let UnmodifiableListViewOfString = () => (UnmodifiableListViewOfString = dart.constFn(collection.UnmodifiableListView$(core.String)))(); + let LinkedHashSetOfString = () => (LinkedHashSetOfString = dart.constFn(collection.LinkedHashSet$(core.String)))(); + let StringAndOptionToNull = () => (StringAndOptionToNull = dart.constFn(dart.fnType(core.Null, [core.String, src__option.Option])))(); + let MapOfString$String = () => (MapOfString$String = dart.constFn(core.Map$(core.String, core.String)))(); + let LinkedMapOfType$dynamic = () => (LinkedMapOfType$dynamic = dart.constFn(_js_helper.LinkedMap$(core.Type, dart.dynamic)))(); + let ContainerTodynamic = () => (ContainerTodynamic = dart.constFn(dart.fnType(dart.dynamic, [src__container.Container])))(); + let LinkedMapOfType$ContainerTodynamic = () => (LinkedMapOfType$ContainerTodynamic = dart.constFn(_js_helper.LinkedMap$(core.Type, ContainerTodynamic())))(); + let ReflectedFunctionTobool = () => (ReflectedFunctionTobool = dart.constFn(dart.fnType(core.bool, [src__reflector.ReflectedFunction])))(); + let JSArrayOfType = () => (JSArrayOfType = dart.constFn(_interceptors.JSArray$(core.Type)))(); + let VoidToString = () => (VoidToString = dart.constFn(dart.fnType(core.String, [])))(); + let ListEqualityOfReflectedInstance = () => (ListEqualityOfReflectedInstance = dart.constFn(src__equality.ListEquality$(src__reflector.ReflectedInstance)))(); + let ListEqualityOfReflectedFunction = () => (ListEqualityOfReflectedFunction = dart.constFn(src__equality.ListEquality$(src__reflector.ReflectedFunction)))(); + let ListEqualityOfReflectedDeclaration = () => (ListEqualityOfReflectedDeclaration = dart.constFn(src__equality.ListEquality$(src__reflector.ReflectedDeclaration)))(); + let ListEqualityOfReflectedTypeParameter = () => (ListEqualityOfReflectedTypeParameter = dart.constFn(src__equality.ListEquality$(src__reflector.ReflectedTypeParameter)))(); + let ListEqualityOfReflectedParameter = () => (ListEqualityOfReflectedParameter = dart.constFn(src__equality.ListEquality$(src__reflector.ReflectedParameter)))(); + let LinkedMapOfSymbol$String = () => (LinkedMapOfSymbol$String = dart.constFn(_js_helper.LinkedMap$(core.Symbol, core.String)))(); + let LinkedMapOfObject$Object = () => (LinkedMapOfObject$Object = dart.constFn(_js_helper.LinkedMap$(core.Object, core.Object)))(); + let AnsiCodeToint = () => (AnsiCodeToint = dart.constFn(dart.fnType(core.int, [src__ansi_code.AnsiCode])))(); + let FutureOfFileStat = () => (FutureOfFileStat = dart.constFn(async.Future$(io.FileStat)))(); + let StringToFutureOfFileStat = () => (StringToFutureOfFileStat = dart.constFn(dart.fnType(FutureOfFileStat(), [core.String])))(); + let FileStatTobool = () => (FileStatTobool = dart.constFn(dart.fnType(core.bool, [io.FileStat])))(); + let _FilePermissionRoleTobool = () => (_FilePermissionRoleTobool = dart.constFn(dart.fnType(core.bool, [src__permissions._FilePermissionRole])))(); + let _EmptyStreamOfListOfint = () => (_EmptyStreamOfListOfint = dart.constFn(async._EmptyStream$(ListOfint())))(); + let intTovoid = () => (intTovoid = dart.constFn(dart.fnType(dart.void, [core.int])))(); + let ListOfintToNull = () => (ListOfintToNull = dart.constFn(dart.fnType(core.Null, [ListOfint()])))(); + let FutureOfProcess = () => (FutureOfProcess = dart.constFn(async.Future$(io.Process)))(); + let StringAndListOfString__ToFutureOfProcess = () => (StringAndListOfString__ToFutureOfProcess = dart.constFn(dart.fnType(FutureOfProcess(), [core.String, ListOfString()], {environment: MapOfString$String(), includeParentEnvironment: core.bool, mode: io.ProcessStartMode, runInShell: core.bool, workingDirectory: core.String})))(); + let CompleterOfString = () => (CompleterOfString = dart.constFn(async.Completer$(core.String)))(); + let ListQueueOfCompleterOfString = () => (ListQueueOfCompleterOfString = dart.constFn(collection.ListQueue$(CompleterOfString())))(); + let CompleterOfMap = () => (CompleterOfMap = dart.constFn(async.Completer$(core.Map)))(); + let IdentityMapOfString$CompleterOfMap = () => (IdentityMapOfString$CompleterOfMap = dart.constFn(_js_helper.IdentityMap$(core.String, CompleterOfMap())))(); + let JSArrayOf_IsolateClientSubscription = () => (JSArrayOf_IsolateClientSubscription = dart.constFn(_interceptors.JSArray$(src__isolate__client._IsolateClientSubscription)))(); + let _IsolateClientSubscriptionTobool = () => (_IsolateClientSubscriptionTobool = dart.constFn(dart.fnType(core.bool, [src__isolate__client._IsolateClientSubscription])))(); + let IdentityMapOfString$Object = () => (IdentityMapOfString$Object = dart.constFn(_js_helper.IdentityMap$(core.String, core.Object)))(); + let VoidToFutureOfMap = () => (VoidToFutureOfMap = dart.constFn(dart.fnType(FutureOfMap(), [])))(); + let MapTo_IsolateClientSubscription = () => (MapTo_IsolateClientSubscription = dart.constFn(dart.fnType(src__isolate__client._IsolateClientSubscription, [core.Map])))(); + let FutureOfClientSubscription = () => (FutureOfClientSubscription = dart.constFn(async.Future$(src__protocol__client__client.ClientSubscription)))(); + let VoidToFutureOfClientSubscription = () => (VoidToFutureOfClientSubscription = dart.constFn(dart.fnType(FutureOfClientSubscription(), [])))(); + let MapToNull = () => (MapToNull = dart.constFn(dart.fnType(core.Null, [core.Map])))(); + let IdentityMapOfString$SendPort = () => (IdentityMapOfString$SendPort = dart.constFn(_js_helper.IdentityMap$(core.String, isolate.SendPort)))(); + let StreamControllerOfPublishRequest = () => (StreamControllerOfPublishRequest = dart.constFn(async.StreamController$(src__protocol__server__publish.PublishRequest)))(); + let StreamControllerOfSubscriptionRequest = () => (StreamControllerOfSubscriptionRequest = dart.constFn(async.StreamController$(src__protocol__server__subscription.SubscriptionRequest)))(); + let StreamControllerOfUnsubscriptionRequest = () => (StreamControllerOfUnsubscriptionRequest = dart.constFn(async.StreamController$(src__protocol__server__subscription.UnsubscriptionRequest)))(); + let IdentityMapOfString$int = () => (IdentityMapOfString$int = dart.constFn(_js_helper.IdentityMap$(core.String, core.int)))(); + let JSArrayOfClientInfo = () => (JSArrayOfClientInfo = dart.constFn(_interceptors.JSArray$(src__protocol__server__client.ClientInfo)))(); + let ListOfSubscription = () => (ListOfSubscription = dart.constFn(core.List$(src__protocol__server__subscription.Subscription)))(); + let IdentityMapOfString$ListOfSubscription = () => (IdentityMapOfString$ListOfSubscription = dart.constFn(_js_helper.IdentityMap$(core.String, ListOfSubscription())))(); + let AdapterToFuture = () => (AdapterToFuture = dart.constFn(dart.fnType(async.Future, [src__protocol__server__adapter.Adapter])))(); + let ClientInfoTobool = () => (ClientInfoTobool = dart.constFn(dart.fnType(core.bool, [src__protocol__server__client.ClientInfo])))(); + let SubscriptionTobool = () => (SubscriptionTobool = dart.constFn(dart.fnType(core.bool, [src__protocol__server__subscription.Subscription])))(); + let JSArrayOfSubscription = () => (JSArrayOfSubscription = dart.constFn(_interceptors.JSArray$(src__protocol__server__subscription.Subscription)))(); + let PublishRequestToNull = () => (PublishRequestToNull = dart.constFn(dart.fnType(core.Null, [src__protocol__server__publish.PublishRequest])))(); + let VoidToListOfSubscription = () => (VoidToListOfSubscription = dart.constFn(dart.fnType(ListOfSubscription(), [])))(); + let SubscriptionRequestToFutureOfNull = () => (SubscriptionRequestToFutureOfNull = dart.constFn(dart.fnType(FutureOfNull(), [src__protocol__server__subscription.SubscriptionRequest])))(); + let UnsubscriptionRequestToNull = () => (UnsubscriptionRequestToNull = dart.constFn(dart.fnType(core.Null, [src__protocol__server__subscription.UnsubscriptionRequest])))(); + let UnmodifiableMapViewOfString$String = () => (UnmodifiableMapViewOfString$String = dart.constFn(collection.UnmodifiableMapView$(core.String, core.String)))(); + let CaseInsensitiveMapOfString = () => (CaseInsensitiveMapOfString = dart.constFn(src__case_insensitive_map.CaseInsensitiveMap$(core.String)))(); + let ListOfAuthenticationChallenge = () => (ListOfAuthenticationChallenge = dart.constFn(core.List$(src__authentication_challenge.AuthenticationChallenge)))(); + let VoidToAuthenticationChallenge = () => (VoidToAuthenticationChallenge = dart.constFn(dart.fnType(src__authentication_challenge.AuthenticationChallenge, [])))(); + let VoidToListOfAuthenticationChallenge = () => (VoidToListOfAuthenticationChallenge = dart.constFn(dart.fnType(ListOfAuthenticationChallenge(), [])))(); + let VoidTovoid = () => (VoidTovoid = dart.constFn(dart.fnType(dart.void, [])))(); + let VoidToDateTime = () => (VoidToDateTime = dart.constFn(dart.fnType(core.DateTime, [])))(); + let VoidToMediaType = () => (VoidToMediaType = dart.constFn(dart.fnType(src__media_type.MediaType, [])))(); + let LinkedHashMapOfString$String = () => (LinkedHashMapOfString$String = dart.constFn(collection.LinkedHashMap$(core.String, core.String)))(); + let MatchToString = () => (MatchToString = dart.constFn(dart.fnType(core.String, [core.Match])))(); + let StringAndStringToNull = () => (StringAndStringToNull = dart.constFn(dart.fnType(core.Null, [core.String, core.String])))(); + let StringAndStringTobool = () => (StringAndStringTobool = dart.constFn(dart.fnType(core.bool, [core.String, core.String])))(); + let StringToint = () => (StringToint = dart.constFn(dart.fnType(core.int, [core.String])))(); + let IterableOfString = () => (IterableOfString = dart.constFn(core.Iterable$(core.String)))(); + let SetOfString = () => (SetOfString = dart.constFn(core.Set$(core.String)))(); + let JSArrayOfMagicNumber = () => (JSArrayOfMagicNumber = dart.constFn(_interceptors.JSArray$(src__magic_number.MagicNumber)))(); + let JSArrayOfSyntaxError = () => (JSArrayOfSyntaxError = dart.constFn(_interceptors.JSArray$(src__error.SyntaxError)))(); + let SyntaxErrorAndSyntaxErrorTobool = () => (SyntaxErrorAndSyntaxErrorTobool = dart.constFn(dart.fnType(core.bool, [src__error.SyntaxError, src__error.SyntaxError])))(); + let JSArrayOfParser = () => (JSArrayOfParser = dart.constFn(_interceptors.JSArray$(src__combinator__combinator.Parser)))(); + let QueueOfint = () => (QueueOfint = dart.constFn(collection.Queue$(core.int)))(); + let LinkedMapOfParser$QueueOfint = () => (LinkedMapOfParser$QueueOfint = dart.constFn(_js_helper.LinkedMap$(src__combinator__combinator.Parser, QueueOfint())))(); + let Tuple2Ofint$ParseResult = () => (Tuple2Ofint$ParseResult = dart.constFn(tuple.Tuple2$(core.int, src__combinator__combinator.ParseResult)))(); + let ListOfTuple2Ofint$ParseResult = () => (ListOfTuple2Ofint$ParseResult = dart.constFn(core.List$(Tuple2Ofint$ParseResult())))(); + let LinkedMapOfParser$ListOfTuple2Ofint$ParseResult = () => (LinkedMapOfParser$ListOfTuple2Ofint$ParseResult = dart.constFn(_js_helper.LinkedMap$(src__combinator__combinator.Parser, ListOfTuple2Ofint$ParseResult())))(); + let Tuple2Ofint$ParseResultTobool = () => (Tuple2Ofint$ParseResultTobool = dart.constFn(dart.fnType(core.bool, [Tuple2Ofint$ParseResult()])))(); + let JSArrayOfTuple2Ofint$ParseResult = () => (JSArrayOfTuple2Ofint$ParseResult = dart.constFn(_interceptors.JSArray$(Tuple2Ofint$ParseResult())))(); + let VoidToListOfTuple2Ofint$ParseResult = () => (VoidToListOfTuple2Ofint$ParseResult = dart.constFn(dart.fnType(ListOfTuple2Ofint$ParseResult(), [])))(); + let ListQueueOfint = () => (ListQueueOfint = dart.constFn(collection.ListQueue$(core.int)))(); + let VoidToQueueOfint = () => (VoidToQueueOfint = dart.constFn(dart.fnType(QueueOfint(), [])))(); + let ListOfSyntaxError = () => (ListOfSyntaxError = dart.constFn(core.List$(src__error.SyntaxError)))(); + let JSArrayOfFileSpan = () => (JSArrayOfFileSpan = dart.constFn(_interceptors.JSArray$(src__file.FileSpan)))(); + let FileSpanAndFileSpanToFileSpan = () => (FileSpanAndFileSpanToFileSpan = dart.constFn(dart.fnType(src__file.FileSpan, [src__file.FileSpan, src__file.FileSpan])))(); + let SyntaxErrorTobool = () => (SyntaxErrorTobool = dart.constFn(dart.fnType(core.bool, [src__error.SyntaxError])))(); + let ListOfSyntaxErrorAndSyntaxErrorToListOfSyntaxError = () => (ListOfSyntaxErrorAndSyntaxErrorToListOfSyntaxError = dart.constFn(dart.fnType(ListOfSyntaxError(), [ListOfSyntaxError(), src__error.SyntaxError])))(); + let intAnddynamicToint = () => (intAnddynamicToint = dart.constFn(dart.fnType(core.int, [core.int, dart.dynamic])))(); + let ListOfTrace = () => (ListOfTrace = dart.constFn(core.List$(src__trace.Trace)))(); + let dynamicAnddynamicToNull = () => (dynamicAnddynamicToNull = dart.constFn(dart.fnType(core.Null, [dart.dynamic, dart.dynamic])))(); + let LinkedMapOfObject$bool = () => (LinkedMapOfObject$bool = dart.constFn(_js_helper.LinkedMap$(core.Object, core.bool)))(); + let JSArrayOfTrace = () => (JSArrayOfTrace = dart.constFn(_interceptors.JSArray$(src__trace.Trace)))(); + let VoidToChain = () => (VoidToChain = dart.constFn(dart.fnType(src__chain.Chain, [])))(); + let StringToTrace = () => (StringToTrace = dart.constFn(dart.fnType(src__trace.Trace, [core.String])))(); + let FrameTobool = () => (FrameTobool = dart.constFn(dart.fnType(core.bool, [src__frame.Frame])))(); + let TraceToTrace = () => (TraceToTrace = dart.constFn(dart.fnType(src__trace.Trace, [src__trace.Trace])))(); + let TraceTobool = () => (TraceTobool = dart.constFn(dart.fnType(core.bool, [src__trace.Trace])))(); + let ListOfFrame = () => (ListOfFrame = dart.constFn(core.List$(src__frame.Frame)))(); + let TraceToListOfFrame = () => (TraceToListOfFrame = dart.constFn(dart.fnType(ListOfFrame(), [src__trace.Trace])))(); + let FrameToint = () => (FrameToint = dart.constFn(dart.fnType(core.int, [src__frame.Frame])))(); + let TAndTToT = () => (TAndTToT = dart.constFn(dart.gFnType(T => [T, [T, T]], T => [core.num])))(); + let TraceToint = () => (TraceToint = dart.constFn(dart.fnType(core.int, [src__trace.Trace])))(); + let FrameToString = () => (FrameToString = dart.constFn(dart.fnType(core.String, [src__frame.Frame])))(); + let TraceToString = () => (TraceToString = dart.constFn(dart.fnType(core.String, [src__trace.Trace])))(); + let dynamicAndChainTovoid = () => (dynamicAndChainTovoid = dart.constFn(dart.fnType(dart.void, [dart.dynamic, src__chain.Chain])))(); + let VoidToFrame = () => (VoidToFrame = dart.constFn(dart.fnType(src__frame.Frame, [])))(); + let dynamicAnddynamicToFrame = () => (dynamicAnddynamicToFrame = dart.constFn(dart.fnType(src__frame.Frame, [dart.dynamic, dart.dynamic])))(); + let StringToFrame = () => (StringToFrame = dart.constFn(dart.fnType(src__frame.Frame, [core.String])))(); + let JSArrayOfFrame = () => (JSArrayOfFrame = dart.constFn(_interceptors.JSArray$(src__frame.Frame)))(); + let VoidToTrace = () => (VoidToTrace = dart.constFn(dart.fnType(src__trace.Trace, [])))(); + let FrameToFrame = () => (FrameToFrame = dart.constFn(dart.fnType(src__frame.Frame, [src__frame.Frame])))(); + let VoidToListOfString = () => (VoidToListOfString = dart.constFn(dart.fnType(ListOfString(), [])))(); + let intAndintToint = () => (intAndintToint = dart.constFn(dart.fnType(core.int, [core.int, core.int])))(); + let LinkedMapOfString$int = () => (LinkedMapOfString$int = dart.constFn(_js_helper.LinkedMap$(core.String, core.int)))(); + let LinkedMapOfString$dynamic = () => (LinkedMapOfString$dynamic = dart.constFn(_js_helper.LinkedMap$(core.String, dart.dynamic)))(); + let MapOfSymbol$dynamic = () => (MapOfSymbol$dynamic = dart.constFn(core.Map$(core.Symbol, dart.dynamic)))(); + let SinkOfListOfint = () => (SinkOfListOfint = dart.constFn(core.Sink$(ListOfint())))(); + let intAndStringToNull = () => (intAndStringToNull = dart.constFn(dart.fnType(core.Null, [core.int, core.String])))(); + let intToString = () => (intToString = dart.constFn(dart.fnType(core.String, [core.int])))(); + let _CodesToint = () => (_CodesToint = dart.constFn(dart.fnType(core.int, [src__interface__error_codes._Codes])))(); + let StreamControllerOfMimeMultipart = () => (StreamControllerOfMimeMultipart = dart.constFn(async.StreamController$(src__mime_shared.MimeMultipart)))(); + let LinkedMapOfString$String = () => (LinkedMapOfString$String = dart.constFn(_js_helper.LinkedMap$(core.String, core.String)))(); + let JSArrayOfCodeBufferLine = () => (JSArrayOfCodeBufferLine = dart.constFn(_interceptors.JSArray$(code_buffer.CodeBufferLine)))(); + let ListOfCodeBufferLine = () => (ListOfCodeBufferLine = dart.constFn(core.List$(code_buffer.CodeBufferLine)))(); + let LinkedMapOfSourceSpan$SourceSpan = () => (LinkedMapOfSourceSpan$SourceSpan = dart.constFn(_js_helper.LinkedMap$(src__span.SourceSpan, src__span.SourceSpan)))(); + let StreamOfHttpRequest = () => (StreamOfHttpRequest = dart.constFn(async.Stream$(_http.HttpRequest)))(); + let StringToFuture = () => (StringToFuture = dart.constFn(dart.fnType(async.Future, [core.String])))(); + let FileSystemEntityTypeToObject = () => (FileSystemEntityTypeToObject = dart.constFn(dart.fnType(core.Object, [io.FileSystemEntityType])))(); + let intToNull = () => (intToNull = dart.constFn(dart.fnType(core.Null, [core.int])))(); + let DateTimeToFuture = () => (DateTimeToFuture = dart.constFn(dart.fnType(async.Future, [core.DateTime])))(); + let StringAndStringAnddynamic__Tovoid = () => (StringAndStringAnddynamic__Tovoid = dart.constFn(dart.fnType(dart.void, [core.String, core.String, dart.dynamic, core.bool])))(); + let FileSystemEntityToNull = () => (FileSystemEntityToNull = dart.constFn(dart.fnType(core.Null, [io.FileSystemEntity])))(); + let FileStatToNull = () => (FileStatToNull = dart.constFn(dart.fnType(core.Null, [io.FileStat])))(); + let DirectoryAndHttpRequestTodynamic = () => (DirectoryAndHttpRequestTodynamic = dart.constFn(dart.fnType(dart.dynamic, [io.Directory, _http.HttpRequest])))(); + let HttpRequestTodynamic = () => (HttpRequestTodynamic = dart.constFn(dart.fnType(dart.dynamic, [_http.HttpRequest])))(); + let IdentityMapOfString$_VirtualHostDomain = () => (IdentityMapOfString$_VirtualHostDomain = dart.constFn(_js_helper.IdentityMap$(core.String, src__virtual_host._VirtualHostDomain)))(); + let StreamControllerOfHttpRequest = () => (StreamControllerOfHttpRequest = dart.constFn(async.StreamController$(_http.HttpRequest)))(); + let HttpRequestToNull = () => (HttpRequestToNull = dart.constFn(dart.fnType(core.Null, [_http.HttpRequest])))(); + let ExpandoOf_Node = () => (ExpandoOf_Node = dart.constFn(core.Expando$(src__stack_zone_specification._Node)))(); + let DefaultEqualityOfNull = () => (DefaultEqualityOfNull = dart.constFn(src__equality.DefaultEquality$(core.Null)))(); + let LinkedMapOf_MapEntry$int = () => (LinkedMapOf_MapEntry$int = dart.constFn(_js_helper.LinkedMap$(src__equality._MapEntry, core.int)))(); + let _InOfObject = () => (_InOfObject = dart.constFn(src__core_matchers._In$(core.Object)))(); + let _InOfPattern = () => (_InOfPattern = dart.constFn(src__core_matchers._In$(core.Pattern)))(); + let TypeMatcherOfMap = () => (TypeMatcherOfMap = dart.constFn(src__type_matcher.TypeMatcher$(core.Map)))(); + let TypeMatcherOfList = () => (TypeMatcherOfList = dart.constFn(src__type_matcher.TypeMatcher$(core.List)))(); + let dynamicAnddynamicAndString__ToListOfString = () => (dynamicAnddynamicAndString__ToListOfString = dart.constFn(dart.fnType(ListOfString(), [dart.dynamic, dart.dynamic, core.String, core.int])))(); + let TypeMatcherOfArgumentError = () => (TypeMatcherOfArgumentError = dart.constFn(src__type_matcher.TypeMatcher$(core.ArgumentError)))(); + let TypeMatcherOfCastError = () => (TypeMatcherOfCastError = dart.constFn(src__type_matcher.TypeMatcher$(core.CastError)))(); + let TypeMatcherOfConcurrentModificationError = () => (TypeMatcherOfConcurrentModificationError = dart.constFn(src__type_matcher.TypeMatcher$(core.ConcurrentModificationError)))(); + let TypeMatcherOfCyclicInitializationError = () => (TypeMatcherOfCyclicInitializationError = dart.constFn(src__type_matcher.TypeMatcher$(core.CyclicInitializationError)))(); + let TypeMatcherOfException = () => (TypeMatcherOfException = dart.constFn(src__type_matcher.TypeMatcher$(core.Exception)))(); + let TypeMatcherOfFormatException = () => (TypeMatcherOfFormatException = dart.constFn(src__type_matcher.TypeMatcher$(core.FormatException)))(); + let TypeMatcherOfNoSuchMethodError = () => (TypeMatcherOfNoSuchMethodError = dart.constFn(src__type_matcher.TypeMatcher$(core.NoSuchMethodError)))(); + let TypeMatcherOfNullThrownError = () => (TypeMatcherOfNullThrownError = dart.constFn(src__type_matcher.TypeMatcher$(core.NullThrownError)))(); + let TypeMatcherOfRangeError = () => (TypeMatcherOfRangeError = dart.constFn(src__type_matcher.TypeMatcher$(core.RangeError)))(); + let TypeMatcherOfStateError = () => (TypeMatcherOfStateError = dart.constFn(src__type_matcher.TypeMatcher$(core.StateError)))(); + let TypeMatcherOfUnimplementedError = () => (TypeMatcherOfUnimplementedError = dart.constFn(src__type_matcher.TypeMatcher$(core.UnimplementedError)))(); + let TypeMatcherOfUnsupportedError = () => (TypeMatcherOfUnsupportedError = dart.constFn(src__type_matcher.TypeMatcher$(core.UnsupportedError)))(); + let dynamicAndintToMatcher = () => (dynamicAndintToMatcher = dart.constFn(dart.fnType(src__interfaces.Matcher, [dart.dynamic], [core.int])))(); + let dynamicToMatcher = () => (dynamicToMatcher = dart.constFn(dart.fnType(src__interfaces.Matcher, [dart.dynamic])))(); + let ListOfListOfint = () => (ListOfListOfint = dart.constFn(core.List$(ListOfint())))(); + let intToListOfint = () => (intToListOfint = dart.constFn(dart.fnType(ListOfint(), [core.int])))(); + let intTobool = () => (intTobool = dart.constFn(dart.fnType(core.bool, [core.int])))(); + let _IdentityHashSetOfint = () => (_IdentityHashSetOfint = dart.constFn(collection._IdentityHashSet$(core.int)))(); + let NullTobool = () => (NullTobool = dart.constFn(dart.fnType(core.bool, [core.Null])))(); + let StreamOfHttpRequestBody = () => (StreamOfHttpRequestBody = dart.constFn(async.Stream$(src__http_body.HttpRequestBody)))(); + let EventSinkOfHttpRequestBody = () => (EventSinkOfHttpRequestBody = dart.constFn(async.EventSink$(src__http_body.HttpRequestBody)))(); + let EventSinkOfHttpRequestBodyTo_HttpBodyHandlerTransformerSink = () => (EventSinkOfHttpRequestBodyTo_HttpBodyHandlerTransformerSink = dart.constFn(dart.fnType(src__http_body_impl._HttpBodyHandlerTransformerSink, [EventSinkOfHttpRequestBody()])))(); + let HttpBodyTo_HttpRequestBody = () => (HttpBodyTo_HttpRequestBody = dart.constFn(dart.fnType(src__http_body_impl._HttpRequestBody, [src__http_body.HttpBody])))(); + let HttpBodyTo_HttpClientResponseBody = () => (HttpBodyTo_HttpClientResponseBody = dart.constFn(dart.fnType(src__http_body_impl._HttpClientResponseBody, [src__http_body.HttpBody])))(); + let dynamicAndListOfintTodynamic = () => (dynamicAndListOfintTodynamic = dart.constFn(dart.fnType(dart.dynamic, [dart.dynamic, ListOfint()])))(); + let dynamicTo_HttpBody = () => (dynamicTo_HttpBody = dart.constFn(dart.fnType(src__http_body_impl._HttpBody, [dart.dynamic])))(); + let FutureOfHttpBody = () => (FutureOfHttpBody = dart.constFn(async.Future$(src__http_body.HttpBody)))(); + let VoidToFutureOfHttpBody = () => (VoidToFutureOfHttpBody = dart.constFn(dart.fnType(FutureOfHttpBody(), [])))(); + let dynamicAndStringTodynamic = () => (dynamicAndStringTodynamic = dart.constFn(dart.fnType(dart.dynamic, [dart.dynamic, core.String])))(); + let EncodingToFutureOfHttpBody = () => (EncodingToFutureOfHttpBody = dart.constFn(dart.fnType(FutureOfHttpBody(), [convert.Encoding])))(); + let dynamicAnddynamicTodynamic = () => (dynamicAnddynamicTodynamic = dart.constFn(dart.fnType(dart.dynamic, [dart.dynamic, dart.dynamic])))(); + let dynamicToList = () => (dynamicToList = dart.constFn(dart.fnType(core.List, [dart.dynamic])))(); + let HttpMultipartFormDataToFutureOfList = () => (HttpMultipartFormDataToFutureOfList = dart.constFn(dart.fnType(FutureOfList(), [src__http_multipart_form_data.HttpMultipartFormData])))(); + let dynamicAndFutureOfListTodynamic = () => (dynamicAndFutureOfListTodynamic = dart.constFn(dart.fnType(dart.dynamic, [dart.dynamic, FutureOfList()])))(); + let dynamicToFutureOfList = () => (dynamicToFutureOfList = dart.constFn(dart.fnType(FutureOfList(), [dart.dynamic])))(); + let ListTo_HttpBody = () => (ListTo_HttpBody = dart.constFn(dart.fnType(src__http_body_impl._HttpBody, [core.List])))(); + let HttpBodyTo_HttpBody = () => (HttpBodyTo_HttpBody = dart.constFn(dart.fnType(src__http_body_impl._HttpBody, [src__http_body.HttpBody])))(); + let JSArrayOfListOfint = () => (JSArrayOfListOfint = dart.constFn(_interceptors.JSArray$(ListOfint())))(); + let SinkOfDigest = () => (SinkOfDigest = dart.constFn(core.Sink$(src__digest.Digest)))(); + let dynamicAndintAndSet__ToString = () => (dynamicAndintAndSet__ToString = dart.constFn(dart.fnType(core.String, [dart.dynamic, core.int, core.Set, core.bool])))(); + let JSArrayOf_FunctionMatcher = () => (JSArrayOf_FunctionMatcher = dart.constFn(_interceptors.JSArray$(src__having_matcher._FunctionMatcher)))(); + let JSArrayOfMatcher = () => (JSArrayOfMatcher = dart.constFn(_interceptors.JSArray$(src__interfaces.Matcher)))(); + let SinkOfString = () => (SinkOfString = dart.constFn(core.Sink$(core.String)))(); + let const$; + main.main = function(args) { + return new src__runner.Runner.new("example", dart.fn(main.configureServer, AngelToFuture())).run(args); + }; + main.configureServer = function(app) { + return async.async(dart.dynamic, function* configureServer() { + let client = app.container.make(src__protocol__client__client.Client); + let greeting = "Hello! This is the default greeting."; + let onGreetingChanged = (yield client.subscribe("greeting_changed")); + onGreetingChanged.cast(core.String).listen(dart.fn(newGreeting => greeting = newGreeting, StringTovoid())); + app.get("/", dart.fn((req, res) => "Hello, production world!", RequestContextAndResponseContextToString())); + app.get("/greeting", dart.fn((req, res) => greeting, RequestContextAndResponseContextToString())); + app.get("/change_greeting/:newGreeting", dart.fn((req, res) => { + greeting = core.String.as(req.params[$_get]("newGreeting")); + client.publish("greeting_changed", greeting); + return "Changed greeting -> " + dart.str(greeting); + }, RequestContextAndResponseContextToString())); + app.get("/crash", dart.fn((req, res) => { + async.Timer.new(const$ || (const$ = dart.const(new core.Duration.new({seconds: 3}))), dart.bind(isolate.Isolate.current, 'kill')); + return "Crashing in 3s..."; + }, RequestContextAndResponseContextToString())); + }); + }; + src__http__http.startShared = function(address, port) { + let t0, t0$; + return _http.HttpServer.bind((t0 = address, t0 == null ? "127.0.0.1" : t0), (t0$ = port, t0$ == null ? 0 : t0$), {shared: true}); + }; + src__http__http.startSharedSecure = function(securityContext) { + return dart.fn((address, port) => { + let t0, t0$; + return _http.HttpServer.bindSecure((t0 = address, t0 == null ? "127.0.0.1" : t0), (t0$ = port, t0$ == null ? 0 : t0$), securityContext, {shared: true}); + }, dynamicAndintToFutureOfHttpServer()); + }; + src__instance_info.InstanceInfo = class InstanceInfo extends core.Object { + get id() { + return this[id$]; + } + set id(value) { + super.id = value; + } + }; + (src__instance_info.InstanceInfo.new = function(opts) { + let id = opts && 'id' in opts ? opts.id : null; + this[id$] = id; + ; + }).prototype = src__instance_info.InstanceInfo.prototype; + dart.addTypeTests(src__instance_info.InstanceInfo); + const id$ = Symbol("InstanceInfo.id"); + dart.setFieldSignature(src__instance_info.InstanceInfo, () => ({ + __proto__: dart.getFields(src__instance_info.InstanceInfo.__proto__), + id: dart.finalFieldType(core.int) + })); + src__options.RunnerOptions = class RunnerOptions extends core.Object { + get hostname() { + return this[hostname$]; + } + set hostname(value) { + super.hostname = value; + } + get concurrency() { + return this[concurrency$]; + } + set concurrency(value) { + super.concurrency = value; + } + get port() { + return this[port$]; + } + set port(value) { + super.port = value; + } + get useZone() { + return this[useZone$]; + } + set useZone(value) { + super.useZone = value; + } + get respawn() { + return this[respawn$]; + } + set respawn(value) { + super.respawn = value; + } + static fromArgResults(argResults) { + return new src__options.RunnerOptions.new({hostname: core.String.as(argResults._get("address")), port: core.int.parse(core.String.as(argResults._get("port"))), concurrency: core.int.parse(core.String.as(argResults._get("concurrency"))), useZone: core.bool.as(argResults._get("use-zone")), respawn: core.bool.as(argResults._get("respawn"))}); + } + }; + (src__options.RunnerOptions.new = function(opts) { + let hostname = opts && 'hostname' in opts ? opts.hostname : "127.0.0.1"; + let port = opts && 'port' in opts ? opts.port : 3000; + let concurrency = opts && 'concurrency' in opts ? opts.concurrency : 1; + let useZone = opts && 'useZone' in opts ? opts.useZone : false; + let respawn = opts && 'respawn' in opts ? opts.respawn : true; + this[hostname$] = hostname; + this[port$] = port; + this[concurrency$] = concurrency; + this[useZone$] = useZone; + this[respawn$] = respawn; + ; + }).prototype = src__options.RunnerOptions.prototype; + dart.addTypeTests(src__options.RunnerOptions); + const hostname$ = Symbol("RunnerOptions.hostname"); + const concurrency$ = Symbol("RunnerOptions.concurrency"); + const port$ = Symbol("RunnerOptions.port"); + const useZone$ = Symbol("RunnerOptions.useZone"); + const respawn$ = Symbol("RunnerOptions.respawn"); + dart.setFieldSignature(src__options.RunnerOptions, () => ({ + __proto__: dart.getFields(src__options.RunnerOptions.__proto__), + hostname: dart.finalFieldType(core.String), + concurrency: dart.finalFieldType(core.int), + port: dart.finalFieldType(core.int), + useZone: dart.finalFieldType(core.bool), + respawn: dart.finalFieldType(core.bool) + })); + dart.defineLazy(src__options.RunnerOptions, { + /*src__options.RunnerOptions.argParser*/get argParser() { + let t0; + return t0 = src__arg_parser.ArgParser.new(), t0.addFlag("help", {abbr: "h", help: "Print this help information.", negatable: false}), t0.addFlag("respawn", {help: "Automatically respawn crashed application instances.", defaultsTo: true, negatable: true}), t0.addFlag("use-zone", {negatable: false, help: "Create a new Zone for each request."}), t0.addOption("address", {abbr: "a", defaultsTo: "127.0.0.1", help: "The address to listen on."}), t0.addOption("concurrency", {abbr: "j", defaultsTo: dart.toString(io.Platform.numberOfProcessors), help: "The number of isolates to spawn."}), t0.addOption("port", {abbr: "p", defaultsTo: "3000", help: "The port to listen on."}), t0; + } + }); + let const$0; + const _spawnIsolate = Symbol('_spawnIsolate'); + src__runner.Runner = class Runner extends core.Object { + get name() { + return this[name$]; + } + set name(value) { + super.name = value; + } + get configureServer() { + return this[configureServer$]; + } + set configureServer(value) { + super.configureServer = value; + } + get reflector() { + return this[reflector$]; + } + set reflector(value) { + super.reflector = value; + } + static handleLogRecord(record) { + let code = src__runner.Runner.chooseLogColor(record.level); + if (record.error == null) core.print(code.wrap(dart.toString(record))); + if (record.error != null) { + let err = record.error; + if (angel_http_exception.AngelHttpException.is(err) && err.statusCode !== 500) return; + core.print(code.wrap(dart.notNull(dart.toString(record)) + "\n")); + core.print(code.wrap(dart.toString(err))); + if (record.stackTrace != null) { + core.print(code.wrap(dart.toString(record.stackTrace))); + } + } + } + static chooseLogColor(level) { + if (dart.equals(level, logging.Level.SHOUT)) + return src__ansi_code.backgroundRed; + else if (dart.equals(level, logging.Level.SEVERE)) + return src__ansi_code.red; + else if (dart.equals(level, logging.Level.WARNING)) + return src__ansi_code.yellow; + else if (dart.equals(level, logging.Level.INFO)) + return src__ansi_code.cyan; + else if (dart.equals(level, logging.Level.FINER) || dart.equals(level, logging.Level.FINEST)) return src__ansi_code.lightGray; + return src__ansi_code.resetAll; + } + spawnIsolate(id, options, pubSubSendPort) { + return this[_spawnIsolate](id, async.Completer.new(), options, pubSubSendPort); + } + [_spawnIsolate](id, c, options, pubSubSendPort) { + let onLogRecord = new isolate._ReceivePort.new(); + let onExit = new isolate._ReceivePort.new(); + let onError = new isolate._ReceivePort.new(); + let runnerArgs = new src__runner._RunnerArgs.new(this.name, this.configureServer, options, this.reflector, onLogRecord.sendPort, pubSubSendPort); + let argsWithId = new src__runner._RunnerArgsWithId.new(id, runnerArgs); + isolate.Isolate.spawn(src__runner._RunnerArgsWithId, dart.fn(src__runner.Runner.isolateMain, _RunnerArgsWithIdTovoid()), argsWithId, {onExit: onExit.sendPort, onError: onError.sendPort, errorsAreFatal: true && false}).then(dart.dynamic, dart.fn(isolate => { + }, IsolateToNull())).catchError(dart.bind(c, 'completeError')); + onLogRecord.listen(dart.fn(msg => src__runner.Runner.handleLogRecord(logging.LogRecord.as(msg)), dynamicTovoid())); + onError.listen(dart.fn(msg => { + if (core.List.is(msg)) { + let e = msg[$_get](0); + let st = new core._StringStackTrace.new(dart.toString(msg[$_get](1))); + src__runner.Runner.handleLogRecord(new logging.LogRecord.new(logging.Level.SEVERE, "Fatal error", runnerArgs.loggerName, e, st)); + } else { + src__runner.Runner.handleLogRecord(new logging.LogRecord.new(logging.Level.SEVERE, "Fatal error", runnerArgs.loggerName, msg)); + } + }, dynamicToNull())); + onExit.listen(dart.fn(_ => { + if (dart.test(options.respawn)) { + src__runner.Runner.handleLogRecord(new logging.LogRecord.new(logging.Level.WARNING, "Instance #" + dart.str(id) + " at " + dart.str(new core.DateTime.now()) + ". Respawning immediately...", runnerArgs.loggerName)); + this[_spawnIsolate](id, c, options, pubSubSendPort); + } else { + c.complete(); + } + }, dynamicToNull())); + return c.future.whenComplete(dart.bind(onExit, 'close')).whenComplete(dart.bind(onError, 'close')).whenComplete(dart.bind(onLogRecord, 'close')); + } + run(args) { + return async.async(dart.dynamic, (function* run() { + let t0, t1, t1$, t1$0; + let server = null; + try { + let argResults = src__options.RunnerOptions.argParser.parse(args); + let options = src__options.RunnerOptions.fromArgResults(argResults); + core.print(src__ansi_code.darkGray.wrap("____________ ________________________ \n___ |__ | / /_ ____/__ ____/__ / \n__ /| |_ |/ /_ / __ __ __/ __ / \n_ ___ | /| / / /_/ / _ /___ _ /___\n/_/ |_/_/ |_/ ____/ /_____/ /_____/\n \n"[$trim]() + "\n\n" + "A batteries-included, full-featured, full-stack framework in Dart." + "\n\n" + "https://angel-dart.github.io\n")); + if (dart.equals(argResults._get("help"), true)) { + t0 = io.stdout; + t0.writeln("Options:"); + t0.writeln(src__options.RunnerOptions.argParser.usage); + t0; + return; + } + core.print("Starting `" + dart.str(this.name) + "` application..."); + core.print("Arguments: " + dart.str(args) + "...\n"); + let adapter = new src__isolate__server.IsolateAdapter.new(); + server = new src__protocol__server__server.Server.new(JSArrayOfAdapter().of([adapter])); + for (let i = 0; i < dart.notNull(io.Platform.numberOfProcessors); i = i + 1) { + server.registerClient(new src__protocol__server__client.ClientInfo.new("client" + dart.str(i))); + } + server.start(); + yield async.Future.wait(dart.dynamic, ListOfFuture().generate(options.concurrency, dart.fn(id => this.spawnIsolate(id, options, adapter.receivePort.sendPort), intToFuture()))); + } catch (e$) { + if (src__arg_parser_exception.ArgParserException.is(e$)) { + let e = e$; + t1$ = io.stderr; + t1$.writeln(e.message); + t1$.writeln(); + t1$.writeln("Options:"); + t1$.writeln(src__options.RunnerOptions.argParser.usage); + t1$; + io.exitCode = src__exit_code.ExitCode.usage.code; + } else { + let e = e$; + t1 = io.stderr; + t1.writeln("fatal error: " + dart.str(e)); + t1; + io.exitCode = 1; + } + } finally { + t1$0 = server; + t1$0 == null ? null : t1$0.close(); + } + }).bind(this)); + } + static isolateMain(argsWithId) { + let args = argsWithId.args; + logging.hierarchicalLoggingEnabled = true; + let zone = async.Zone.current.fork({specification: new async._ZoneSpecification.new({print: dart.fn((self, parent, zone, msg) => { + args.loggingSendPort.send(new logging.LogRecord.new(logging.Level.INFO, msg, args.loggerName)); + }, ZoneAndZoneDelegateAndZone__ToNull())})}); + zone.run(FutureOfNull(), dart.fn(() => async.async(core.Null, function*() { + let t1, t1$; + let client = new src__isolate__client.IsolateClient.new("client" + dart.str(argsWithId.id), args.pubSubSendPort); + let app = (t1 = new src__core__server.Angel.new({reflector: args.reflector}), t1.container.registerSingleton(src__protocol__client__client.Client, client), t1.container.registerSingleton(src__instance_info.InstanceInfo, new src__instance_info.InstanceInfo.new({id: argsWithId.id})), t1); + app.shutdownHooks[$add](dart.fn(_ => client.close(), AngelToFuture())); + yield app.configure(args.configureServer); + if (app.logger == null) { + app.logger = (t1$ = logging.Logger.new(args.loggerName), t1$.onRecord.listen(dart.fn(src__runner.Runner.handleLogRecord, LogRecordTovoid())), t1$); + } + let http = src__http__angel_http.AngelHttp.custom(app, dart.fn(src__http__http.startShared, dynamicAndintToFutureOfHttpServer()), {useZone: args.options.useZone}); + let server = (yield http.startServer(args.options.hostname, args.options.port)); + let url = core._Uri.new({scheme: "http", host: server.address.address, port: server.port}); + core.print("Instance #" + dart.str(argsWithId.id) + " listening at " + dart.str(url)); + }), VoidToFutureOfNull())); + } + }; + (src__runner.Runner.new = function(name, configureServer, opts) { + let reflector = opts && 'reflector' in opts ? opts.reflector : const$0 || (const$0 = dart.const(new src__empty__empty.EmptyReflector.new())); + this[name$] = name; + this[configureServer$] = configureServer; + this[reflector$] = reflector; + ; + }).prototype = src__runner.Runner.prototype; + dart.addTypeTests(src__runner.Runner); + const name$ = Symbol("Runner.name"); + const configureServer$ = Symbol("Runner.configureServer"); + const reflector$ = Symbol("Runner.reflector"); + dart.setMethodSignature(src__runner.Runner, () => ({ + __proto__: dart.getMethods(src__runner.Runner.__proto__), + spawnIsolate: dart.fnType(async.Future, [core.int, src__options.RunnerOptions, isolate.SendPort]), + [_spawnIsolate]: dart.fnType(async.Future, [core.int, async.Completer, src__options.RunnerOptions, isolate.SendPort]), + run: dart.fnType(async.Future, [core.List$(core.String)]) + })); + dart.setFieldSignature(src__runner.Runner, () => ({ + __proto__: dart.getFields(src__runner.Runner.__proto__), + name: dart.finalFieldType(core.String), + configureServer: dart.finalFieldType(dart.fnType(async.FutureOr, [src__core__server.Angel])), + reflector: dart.finalFieldType(src__reflector.Reflector) + })); + dart.defineLazy(src__runner.Runner, { + /*src__runner.Runner.asciiArt*/get asciiArt() { + return "____________ ________________________ \n___ |__ | / /_ ____/__ ____/__ / \n__ /| |_ |/ /_ / __ __ __/ __ / \n_ ___ | /| / / /_/ / _ /___ _ /___\n/_/ |_/_/ |_/ ____/ /_____/ /_____/\n \n"; + } + }); + src__runner._RunnerArgsWithId = class _RunnerArgsWithId extends core.Object {}; + (src__runner._RunnerArgsWithId.new = function(id, args) { + this.id = id; + this.args = args; + ; + }).prototype = src__runner._RunnerArgsWithId.prototype; + dart.addTypeTests(src__runner._RunnerArgsWithId); + dart.setFieldSignature(src__runner._RunnerArgsWithId, () => ({ + __proto__: dart.getFields(src__runner._RunnerArgsWithId.__proto__), + id: dart.finalFieldType(core.int), + args: dart.finalFieldType(src__runner._RunnerArgs) + })); + src__runner._RunnerArgs = class _RunnerArgs extends core.Object { + get loggerName() { + return this.name; + } + }; + (src__runner._RunnerArgs.new = function(name, configureServer, options, reflector, loggingSendPort, pubSubSendPort) { + this.name = name; + this.configureServer = configureServer; + this.options = options; + this.reflector = reflector; + this.loggingSendPort = loggingSendPort; + this.pubSubSendPort = pubSubSendPort; + ; + }).prototype = src__runner._RunnerArgs.prototype; + dart.addTypeTests(src__runner._RunnerArgs); + dart.setGetterSignature(src__runner._RunnerArgs, () => ({ + __proto__: dart.getGetters(src__runner._RunnerArgs.__proto__), + loggerName: core.String + })); + dart.setFieldSignature(src__runner._RunnerArgs, () => ({ + __proto__: dart.getFields(src__runner._RunnerArgs.__proto__), + name: dart.finalFieldType(core.String), + configureServer: dart.finalFieldType(dart.fnType(async.FutureOr, [src__core__server.Angel])), + options: dart.finalFieldType(src__options.RunnerOptions), + reflector: dart.finalFieldType(src__reflector.Reflector), + loggingSendPort: dart.finalFieldType(isolate.SendPort), + pubSubSendPort: dart.finalFieldType(isolate.SendPort) + })); + const _index = Symbol('_index'); + const _read = Symbol('_read'); + const _create = Symbol('_create'); + const _remove = Symbol('_remove'); + const _modify = Symbol('_modify'); + const _update = Symbol('_update'); + const _addRoutesInner = Symbol('_addRoutesInner'); + const _services = Symbol('_services'); + const _onService = Symbol('_onService'); + const _container = Symbol('_container'); + let const$1; + const _cache = Symbol('_cache'); + const _middleware = Symbol('_middleware'); + const _mounted = Symbol('_mounted'); + const _routes = Symbol('_routes'); + const _useCache = Symbol('_useCache'); + let const$2; + let const$3; + const _resolveAll = Symbol('_resolveAll'); + const _is_Router_default = Symbol('_is_Router_default'); + src__router.Router$ = dart.generic(T => { + let RoutingResultOfT = () => (RoutingResultOfT = dart.constFn(src__router.RoutingResult$(T)))(); + let IterableOfRoutingResultOfT = () => (IterableOfRoutingResultOfT = dart.constFn(core.Iterable$(RoutingResultOfT())))(); + let IdentityMapOfString$IterableOfRoutingResultOfT = () => (IdentityMapOfString$IterableOfRoutingResultOfT = dart.constFn(_js_helper.IdentityMap$(core.String, IterableOfRoutingResultOfT())))(); + let JSArrayOfT = () => (JSArrayOfT = dart.constFn(_interceptors.JSArray$(T)))(); + let RouterOfT = () => (RouterOfT = dart.constFn(src__router.Router$(T)))(); + let LinkedMapOfPattern$RouterOfT = () => (LinkedMapOfPattern$RouterOfT = dart.constFn(_js_helper.LinkedMap$(core.Pattern, RouterOfT())))(); + let RouteOfT = () => (RouteOfT = dart.constFn(src__router.Route$(T)))(); + let JSArrayOfRouteOfT = () => (JSArrayOfRouteOfT = dart.constFn(_interceptors.JSArray$(RouteOfT())))(); + let ListOfT = () => (ListOfT = dart.constFn(core.List$(T)))(); + let ListOfRouteOfT = () => (ListOfRouteOfT = dart.constFn(core.List$(RouteOfT())))(); + let SymlinkRouteOfT = () => (SymlinkRouteOfT = dart.constFn(src__router.SymlinkRoute$(T)))(); + let ListOfRouteOfTAndRouteOfTToListOfRouteOfT = () => (ListOfRouteOfTAndRouteOfTToListOfRouteOfT = dart.constFn(dart.fnType(ListOfRouteOfT(), [ListOfRouteOfT(), RouteOfT()])))(); + let IterableOfT = () => (IterableOfT = dart.constFn(core.Iterable$(T)))(); + let _ChainedRouterOfT = () => (_ChainedRouterOfT = dart.constFn(src__router._ChainedRouter$(T)))(); + let LinkedHashMapOfPattern$RouterOfT = () => (LinkedHashMapOfPattern$RouterOfT = dart.constFn(collection.LinkedHashMap$(core.Pattern, RouterOfT())))(); + let ListOfRoutingResultOfT = () => (ListOfRoutingResultOfT = dart.constFn(core.List$(RoutingResultOfT())))(); + let RouterOfTTobool = () => (RouterOfTTobool = dart.constFn(dart.fnType(core.bool, [RouterOfT()])))(); + let VoidToIterableOfRoutingResultOfT = () => (VoidToIterableOfRoutingResultOfT = dart.constFn(dart.fnType(IterableOfRoutingResultOfT(), [])))(); + let JSArrayOfRoutingResultOfT = () => (JSArrayOfRoutingResultOfT = dart.constFn(_interceptors.JSArray$(RoutingResultOfT())))(); + class Router extends core.Object { + get middleware() { + return ListOfT().unmodifiable(this[_middleware]); + } + get mounted() { + return MapOfPattern$Router().unmodifiable(this[_mounted]); + } + get routes() { + return this[_routes][$fold](ListOfRouteOfT(), JSArrayOfRouteOfT().of([]), dart.fn((out, route) => { + let t1, t1$; + if (SymlinkRouteOfT().is(route)) { + let childRoutes = route.router.routes[$fold](ListOfRouteOfT(), JSArrayOfRouteOfT().of([]), dart.fn((out, r) => { + let t1; + t1 = out; + t1[$add](route.path[$isEmpty] ? r : RouteOfT().join(route, r)); + return t1; + }, ListOfRouteOfTAndRouteOfTToListOfRouteOfT())); + t1 = out; + t1[$addAll](childRoutes); + return t1; + } else { + t1$ = out; + t1$[$add](route); + return t1$; + } + }, ListOfRouteOfTAndRouteOfTToListOfRouteOfT())); + } + enableCache() { + this[_useCache] = true; + } + addRoute(method, path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : const$2 || (const$2 = dart.constList([], core.Null)); + IterableOfT()._check(middleware); + if (dart.equals(this[_useCache], true)) dart.throw(new core.StateError.new("Cannot add routes after caching is enabled.")); + let handlers = JSArrayOfT().of([handler]); + if (middleware != null) handlers[$insertAll](0, middleware); + let route = new (RouteOfT()).new(path, {method: method, handlers: handlers}); + this[_routes][$add](route); + return route; + } + chain(middleware) { + IterableOfT()._check(middleware); + let piped = new (_ChainedRouterOfT()).new(this, middleware); + let route = new (SymlinkRouteOfT()).new("/", piped); + this[_routes][$add](route); + return piped; + } + clone() { + let t1; + let router = new (RouterOfT()).new(); + let newMounted = LinkedHashMapOfPattern$RouterOfT().from(this.mounted); + for (let route of this.routes) { + if (!SymlinkRouteOfT().is(route)) { + router[_routes][$add](route.clone()); + } else if (SymlinkRouteOfT().is(route)) { + let newRouter = route.router.clone(); + newMounted[$_set](route.path, newRouter); + let symlink = new (SymlinkRouteOfT()).new(route.path, newRouter); + router[_routes][$add](symlink); + } + } + t1 = router; + t1[_mounted][$addAll](newMounted); + return t1; + } + dumpTree(opts) { + let t1; + let callback = opts && 'callback' in opts ? opts.callback : null; + let header = opts && 'header' in opts ? opts.header : "Dumping route tree:"; + let tab = opts && 'tab' in opts ? opts.tab : " "; + let buf = new core.StringBuffer.new(); + let tabs = 0; + if (header != null && header[$isNotEmpty]) { + buf.writeln(header); + } + buf.writeln(""); + function indent() { + for (let i = 0; i < tabs; i = i + 1) + buf.write(tab); + } + dart.fn(indent, VoidToNull()); + function dumpRouter(router) { + indent(); + tabs = tabs + 1; + for (let route of router.routes) { + indent(); + buf.write("- "); + if (!src__router.SymlinkRoute.is(route)) buf.write(dart.str(route.method) + " "); + buf.write(dart.str(route.path[$isNotEmpty] ? route.path : "/")); + if (SymlinkRouteOfT().is(route)) { + buf.writeln(); + dumpRouter(route.router); + } else { + buf.writeln(" => " + dart.str(route.handlers[$length]) + " handler(s)"); + } + } + tabs = tabs - 1; + } + dart.fn(dumpRouter, RouterToNull()); + dumpRouter(this); + (t1 = callback, t1 == null ? dart.fn(core.print, ObjectTovoid()) : t1)(buf.toString()); + } + group(path, callback, opts) { + let t1, t1$; + let middleware = opts && 'middleware' in opts ? opts.middleware : const$3 || (const$3 = dart.constList([], core.Null)); + IterableOfT()._check(middleware); + let name = opts && 'name' in opts ? opts.name : null; + let router = (t1 = new (RouterOfT()).new(), t1[_middleware][$addAll](middleware), t1); + callback(router); + t1$ = this.mount(path, router); + t1$.name = name; + return t1$; + } + navigate(linkParams, opts) { + let absolute = opts && 'absolute' in opts ? opts.absolute : true; + let segments = JSArrayOfString().of([]); + let search = this; + let lastRoute = null; + for (let param of linkParams) { + let resolved = false; + if (typeof param == 'string') { + for (let route of search.routes) { + if (route.name == param) { + segments[$add](route.path[$replaceAll](src__router._straySlashes, "")); + lastRoute = route; + if (SymlinkRouteOfT().is(route)) { + search = route.router; + } + resolved = true; + break; + } + } + if (!resolved) { + let scanner = new src__span_scanner.SpanScanner.new(param[$replaceAll](src__router._straySlashes, "")); + for (let route of search.routes) { + let pos = scanner.position; + if (dart.test(route.parser.parse(scanner).successful) && dart.test(scanner.isDone)) { + segments[$add](route.path[$replaceAll](src__router._straySlashes, "")); + lastRoute = route; + if (SymlinkRouteOfT().is(route)) { + search = route.router; + } + resolved = true; + break; + } else + scanner.position = pos; + } + } + if (!resolved) { + dart.throw(src__routing_exception.RoutingException.new("Cannot resolve route for link param \"" + dart.str(param) + "\".")); + } + } else if (src__router.Route.is(param)) { + segments[$add](param.path[$replaceAll](src__router._straySlashes, "")); + } else if (MapOfString$dynamic().is(param)) { + if (lastRoute == null) { + dart.throw(src__routing_exception.RoutingException.new("Maps in link params must be preceded by a Route or String.")); + } else { + segments[$removeLast](); + segments[$add](lastRoute.makeUri(param)[$replaceAll](src__router._straySlashes, "")); + } + } else + dart.throw(src__routing_exception.RoutingException.new("Link param " + dart.str(param) + " is not Route, String, or Map.")); + } + return dart.test(absolute) ? "/" + segments[$join]("/")[$replaceAll](src__router._straySlashes, "") : segments[$join]("/"); + } + resolve(absolute, relative, out, opts) { + ListOfRoutingResultOfT()._check(out); + let method = opts && 'method' in opts ? opts.method : "GET"; + let strip = opts && 'strip' in opts ? opts.strip : true; + let cleanRelative = dart.equals(strip, false) ? relative : string_util.stripStraySlashes(relative); + let scanner = new src__span_scanner.SpanScanner.new(cleanRelative); + const crawl = (function(r) { + let success = false; + for (let route of r.routes) { + let pos = scanner.position; + if (SymlinkRouteOfT().is(route)) { + if (dart.test(route.parser.parse(scanner).successful)) { + let s = crawl(route.router); + if (dart.test(s)) success = true; + } + scanner.position = pos; + } else if (route.method === "*" || route.method == method) { + let parseResult = route.parser.parse(scanner); + if (dart.test(parseResult.successful) && dart.test(scanner.isDone)) { + let result = new (RoutingResultOfT()).new({parseResult: parseResult, params: parseResult.value, shallowRoute: route, shallowRouter: this}); + out[$add](result); + success = true; + } + scanner.position = pos; + } + } + return success; + }).bind(this); + dart.fn(crawl, RouterOfTTobool()); + return crawl(this); + } + resolveAbsolute(path, opts) { + let method = opts && 'method' in opts ? opts.method : "GET"; + let strip = opts && 'strip' in opts ? opts.strip : true; + return this.resolveAll(path, path, {method: method, strip: strip}); + } + resolveAll(absolute, relative, opts) { + let method = opts && 'method' in opts ? opts.method : "GET"; + let strip = opts && 'strip' in opts ? opts.strip : true; + if (dart.equals(this[_useCache], true)) { + return this[_cache][$putIfAbsent](dart.str(method) + dart.str(absolute), dart.fn(() => this[_resolveAll](absolute, relative, {method: method, strip: strip}), VoidToIterableOfRoutingResultOfT())); + } + return this[_resolveAll](absolute, relative, {method: method, strip: strip}); + } + [_resolveAll](absolute, relative, opts) { + let method = opts && 'method' in opts ? opts.method : "GET"; + let strip = opts && 'strip' in opts ? opts.strip : true; + let results = JSArrayOfRoutingResultOfT().of([]); + this.resolve(absolute, relative, results, {method: method, strip: strip}); + return results; + } + mount(path, router) { + RouterOfT()._check(router); + let route = new (SymlinkRouteOfT()).new(path, router); + this[_mounted][$_set](route.path, router); + this[_routes][$add](route); + return route; + } + all(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("*", path, handler, {middleware: middleware}); + } + delete(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("DELETE", path, handler, {middleware: middleware}); + } + get(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("GET", path, handler, {middleware: middleware}); + } + head(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("HEAD", path, handler, {middleware: middleware}); + } + options(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("OPTIONS", path, handler, {middleware: middleware}); + } + post(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("POST", path, handler, {middleware: middleware}); + } + patch(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("PATCH", path, handler, {middleware: middleware}); + } + put(path, handler, opts) { + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : null; + IterableOfT()._check(middleware); + return this.addRoute("PUT", path, handler, {middleware: middleware}); + } + } + (Router.new = function() { + this[_cache] = new (IdentityMapOfString$IterableOfRoutingResultOfT()).new(); + this[_middleware] = JSArrayOfT().of([]); + this[_mounted] = new (LinkedMapOfPattern$RouterOfT()).new(); + this[_routes] = JSArrayOfRouteOfT().of([]); + this[_useCache] = false; + ; + }).prototype = Router.prototype; + dart.addTypeTests(Router); + Router.prototype[_is_Router_default] = true; + dart.setMethodSignature(Router, () => ({ + __proto__: dart.getMethods(Router.__proto__), + enableCache: dart.fnType(dart.void, []), + addRoute: dart.fnType(src__router.Route$(T), [core.String, core.String, core.Object], {middleware: core.Object}), + chain: dart.fnType(src__router._ChainedRouter$(T), [core.Object]), + clone: dart.fnType(src__router.Router$(T), []), + dumpTree: dart.fnType(dart.void, [], {callback: dart.fnType(dart.dynamic, [core.String]), header: core.String, tab: core.String}), + group: dart.fnType(src__router.SymlinkRoute$(T), [core.String, dart.fnType(dart.void, [src__router.Router])], {middleware: core.Object, name: core.String}), + navigate: dart.fnType(core.String, [core.Iterable], {absolute: core.bool}), + resolve: dart.fnType(core.bool, [core.String, core.String, core.Object], {method: core.String, strip: core.bool}), + resolveAbsolute: dart.fnType(core.Iterable$(src__router.RoutingResult$(T)), [core.String], {method: core.String, strip: core.bool}), + resolveAll: dart.fnType(core.Iterable$(src__router.RoutingResult$(T)), [core.String, core.String], {method: core.String, strip: core.bool}), + [_resolveAll]: dart.fnType(core.Iterable$(src__router.RoutingResult$(T)), [core.String, core.String], {method: core.String, strip: core.bool}), + mount: dart.fnType(src__router.SymlinkRoute$(T), [core.String, core.Object]), + all: dart.fnType(src__router.Route$(T), [core.String, core.Object], {middleware: core.Object}), + delete: dart.fnType(src__router.Route$(T), [core.String, core.Object], {middleware: core.Object}), + get: dart.fnType(src__router.Route$(T), [core.String, core.Object], {middleware: core.Object}), + head: dart.fnType(src__router.Route$(T), [core.String, core.Object], {middleware: core.Object}), + options: dart.fnType(src__router.Route$(T), [core.String, core.Object], {middleware: core.Object}), + post: dart.fnType(src__router.Route$(T), [core.String, core.Object], {middleware: core.Object}), + patch: dart.fnType(src__router.Route$(T), [core.String, core.Object], {middleware: core.Object}), + put: dart.fnType(src__router.Route, [core.String, core.Object], {middleware: core.Object}) + })); + dart.setGetterSignature(Router, () => ({ + __proto__: dart.getGetters(Router.__proto__), + middleware: core.List$(T), + mounted: core.Map$(core.Pattern, src__router.Router), + routes: core.List$(src__router.Route$(T)) + })); + dart.setFieldSignature(Router, () => ({ + __proto__: dart.getFields(Router.__proto__), + [_cache]: dart.finalFieldType(core.Map$(core.String, core.Iterable$(src__router.RoutingResult$(T)))), + [_middleware]: dart.finalFieldType(core.List$(T)), + [_mounted]: dart.finalFieldType(core.Map$(core.Pattern, src__router.Router$(T))), + [_routes]: dart.finalFieldType(core.List$(src__router.Route$(T))), + [_useCache]: dart.fieldType(core.bool) + })); + return Router; + }); + src__router.Router = src__router.Router$(); + dart.addTypeTests(src__router.Router, _is_Router_default); + const _acceptHeaderCache = Symbol('_acceptHeaderCache'); + const _extensionCache = Symbol('_extensionCache'); + const _acceptsAllCache = Symbol('_acceptsAllCache'); + const _body = Symbol('_body'); + const _provisionalQuery = Symbol('_provisionalQuery'); + const _is_RequestContext_default = Symbol('_is_RequestContext_default'); + src__core__request_context.RequestContext$ = dart.generic(RawRequest => { + class RequestContext extends core.Object { + get serviceParams() { + return this[serviceParams]; + } + set serviceParams(value) { + super.serviceParams = value; + } + get app() { + return this[app]; + } + set app(value) { + this[app] = value; + } + get params() { + return this[params]; + } + set params(value) { + this[params] = value; + } + get ip() { + return this.remoteAddress.address; + } + get extension() { + let t1; + t1 = this[_extensionCache]; + return t1 == null ? this[_extensionCache] = path$.extension(this.uri.path) : t1; + } + accepts(contentType, opts) { + let t1; + let strict = opts && 'strict' in opts ? opts.strict : false; + let contentTypeString = src__media_type.MediaType.is(contentType) ? contentType.mimeType : (t1 = contentType, t1 == null ? null : dart.toString(t1)); + if (contentTypeString == null) dart.throw(new core.ArgumentError.new("RequestContext.accepts expects the `contentType` parameter to NOT be null.")); + this[_acceptHeaderCache] == null ? this[_acceptHeaderCache] = this.headers.value("accept") : null; + if (this[_acceptHeaderCache] == null) + return false; + else if (!dart.equals(strict, true) && this[_acceptHeaderCache][$contains]("*/*")) + return true; + else + return this[_acceptHeaderCache][$contains](contentTypeString); + } + get acceptsAll() { + let t1; + t1 = this[_acceptsAllCache]; + return t1 == null ? this[_acceptsAllCache] = this.accepts("*/*") : t1; + } + parseBody() { + return this.parse().then(core.Map, dart.fn(b => b.body, BodyParseResultToMapOfString$dynamic())); + } + parseUploadedFiles() { + return this.parse().then(ListOfFileUploadInfo(), dart.fn(b => b.files, BodyParseResultToListOfFileUploadInfo())); + } + parseRawRequestBuffer() { + return this.parse().then(ListOfint(), dart.fn(b => b.originalBuffer, BodyParseResultToListOfint())); + } + parseQuery(opts) { + let forceParse = opts && 'forceParse' in opts ? opts.forceParse : false; + if (this[_body] == null && !dart.equals(forceParse, true)) + return FutureOfMapOfString$dynamic().value(this.uri.queryParameters); + else + return this.parse().then(MapOfString$dynamic(), dart.fn(b => b.query, BodyParseResultToMapOfString$dynamic())); + } + parse() { + if (this[_body] != null) + return FutureOfBodyParseResult().value(this[_body]); + else + this[_provisionalQuery] = null; + return this.parseOnce().then(src__body_parse_result.BodyParseResult, dart.fn(body => this[_body] = body, BodyParseResultToBodyParseResult())); + } + close() { + let t1; + this[_body] = null; + this[_acceptsAllCache] = null; + this[_acceptHeaderCache] = null; + t1 = this[_provisionalQuery]; + t1 == null ? null : t1[$clear](); + this.serviceParams[$clear](); + this.params[$clear](); + return async.Future.value(); + } + } + (RequestContext.new = function() { + this[_acceptHeaderCache] = null; + this[_extensionCache] = null; + this[_acceptsAllCache] = null; + this[_body] = null; + this[_provisionalQuery] = null; + this[serviceParams] = new _js_helper.LinkedMap.new(); + this[app] = null; + this[params] = new (IdentityMapOfString$dynamic()).new(); + ; + }).prototype = RequestContext.prototype; + dart.addTypeTests(RequestContext); + RequestContext.prototype[_is_RequestContext_default] = true; + const serviceParams = Symbol("RequestContext.serviceParams"); + const app = Symbol("RequestContext.app"); + const params = Symbol("RequestContext.params"); + dart.setMethodSignature(RequestContext, () => ({ + __proto__: dart.getMethods(RequestContext.__proto__), + accepts: dart.fnType(core.bool, [dart.dynamic], {strict: core.bool}), + parseBody: dart.fnType(async.Future$(core.Map), []), + parseUploadedFiles: dart.fnType(async.Future$(core.List$(src__file_upload_info.FileUploadInfo)), []), + parseRawRequestBuffer: dart.fnType(async.Future$(core.List$(core.int)), []), + parseQuery: dart.fnType(async.Future$(core.Map$(core.String, dart.dynamic)), [], {forceParse: core.bool}), + parse: dart.fnType(async.Future$(src__body_parse_result.BodyParseResult), []), + close: dart.fnType(async.Future, []) + })); + dart.setGetterSignature(RequestContext, () => ({ + __proto__: dart.getGetters(RequestContext.__proto__), + ip: core.String, + extension: core.String, + acceptsAll: core.bool + })); + dart.setFieldSignature(RequestContext, () => ({ + __proto__: dart.getFields(RequestContext.__proto__), + [_acceptHeaderCache]: dart.fieldType(core.String), + [_extensionCache]: dart.fieldType(core.String), + [_acceptsAllCache]: dart.fieldType(core.bool), + [_body]: dart.fieldType(src__body_parse_result.BodyParseResult), + [_provisionalQuery]: dart.fieldType(core.Map), + serviceParams: dart.finalFieldType(core.Map), + app: dart.fieldType(src__core__server.Angel), + params: dart.fieldType(core.Map$(core.String, dart.dynamic)) + })); + return RequestContext; + }); + src__core__request_context.RequestContext = src__core__request_context.RequestContext$(); + dart.addTypeTests(src__core__request_context.RequestContext, _is_RequestContext_default); + const _headers = Symbol('_headers'); + const _done = Symbol('_done'); + const _statusCode = Symbol('_statusCode'); + const _is_ResponseContext_default = Symbol('_is_ResponseContext_default'); + src__core__response_context.ResponseContext$ = dart.generic(RawResponse => { + class ResponseContext extends core.Object { + get properties() { + return this[properties]; + } + set properties(value) { + super.properties = value; + } + get app() { + return this[app]; + } + set app(value) { + this[app] = value; + } + get chunked() { + return this[chunked]; + } + set chunked(value) { + this[chunked] = value; + } + get cookies() { + return this[cookies]; + } + set cookies(value) { + super.cookies = value; + } + get encoders() { + return this[encoders]; + } + set encoders(value) { + super.encoders = value; + } + get renderParams() { + return this[renderParams]; + } + set renderParams(value) { + super.renderParams = value; + } + get serializer() { + return this[serializer]; + } + set serializer(value) { + this[serializer] = value; + } + get contentType() { + return this[contentType]; + } + set contentType(value) { + this[contentType] = value; + } + get done() { + let t1; + return (t1 = this[_done], t1 == null ? async.Completer.new() : t1).future; + } + get headers() { + return this[_headers]; + } + get statusCode() { + return this[_statusCode]; + } + set statusCode(value) { + let t1; + if (!dart.test(this.isOpen)) + dart.throw(src__core__response_context.ResponseContext.closed()); + else + this[_statusCode] = (t1 = value, t1 == null ? 200 : t1); + } + static closed() { + return new core.StateError.new("Cannot modify a closed response."); + } + download(file, opts) { + let t1; + let filename = opts && 'filename' in opts ? opts.filename : null; + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + this.headers[$_set]("Content-Disposition", "attachment; filename=\"" + dart.str((t1 = filename, t1 == null ? file.path : t1)) + "\""); + this.contentType = src__media_type.MediaType.parse(src__mime_type.lookupMimeType(file.path)); + this.headers[$_set]("content-length", dart.toString(file.lengthSync())); + if (!dart.test(this.isBuffered)) { + file.openRead().pipe(this); + } else { + this.buffer.add(file.readAsBytesSync()); + this.close(); + } + } + close() { + let t1; + if (src__core__response_context.LockableBytesBuilder.is(this.buffer)) { + src__core__response_context.LockableBytesBuilder.as(this.buffer).lock(); + } + if (dart.equals((t1 = this[_done], t1 == null ? null : t1.isCompleted), false)) this[_done].complete(); + return async.Future.value(); + } + json(value) { + let t1; + t1 = this; + t1.contentType = new src__media_type.MediaType.new("application", "json"); + t1.serialize(value); + return t1; + } + jsonp(value, opts) { + let t1; + let callbackName = opts && 'callbackName' in opts ? opts.callbackName : "callback"; + let contentType = opts && 'contentType' in opts ? opts.contentType : null; + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + this.write(dart.str(callbackName) + "(" + dart.str(this.serializer(value)) + ")"); + this.contentType = (t1 = contentType, t1 == null ? new src__media_type.MediaType.new("application", "javascript") : t1); + this.close(); + } + render(view, data) { + if (data === void 0) data = null; + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + return FutureOfString().sync(dart.fn(() => { + let t2, t1; + return this.app.viewGenerator(view, (t1 = LinkedHashMapOfString$dynamic().from(this.renderParams), t1[$addAll]((t2 = data, t2 == null ? new (IdentityMapOfString$dynamic()).new() : t2)), t1)); + }, VoidToFutureOrOfString())).then(dart.dynamic, dart.fn(content => { + this.write(content); + this.contentType = new src__media_type.MediaType.new("text", "html"); + this.close(); + }, StringToNull())); + } + redirect(url, opts) { + let t1, t1$; + let absolute = opts && 'absolute' in opts ? opts.absolute : true; + let code = opts && 'code' in opts ? opts.code : 302; + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + t1 = this.headers; + t1[$_set]("content-type", "text/html"); + t1[$_set]("location", typeof url == 'string' ? url : this.app.navigate(core.Iterable.as(url), {absolute: absolute})); + t1; + this.statusCode = (t1$ = code, t1$ == null ? 302 : t1$); + this.write(" \n \n \n Redirecting...\n \n \n \n

Currently redirecting you...

\n
\n Click
here if you are not automatically redirected...\n \n \n \n "); + this.close(); + } + redirectTo(name, params, code) { + if (params === void 0) params = null; + if (code === void 0) code = null; + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + function _findRoute(r) { + for (let route of r.routes) { + if (src__router.SymlinkRoute.is(route)) { + let m = _findRoute(route.router); + if (m != null) return m; + } else if (route.name == name) return route; + } + return null; + } + dart.fn(_findRoute, RouterToRoute()); + let matched = _findRoute(this.app); + if (matched != null) { + this.redirect(matched.makeUri(params[$keys][$fold](MapOfString$dynamic(), new (IdentityMapOfString$dynamic()).new(), dart.fn((out, k) => { + let t1; + t1 = out; + t1[$_set](dart.toString(k), params[$_get](k)); + return t1; + }, MapOfString$dynamicAnddynamicToMapOfString$dynamic()))), {code: code}); + return; + } + dart.throw(new core.ArgumentError.notNull("Route to redirect to (" + dart.str(name) + ")")); + } + redirectToAction(action, params, code) { + if (params === void 0) params = null; + if (code === void 0) code = null; + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + let split = action[$split]("@"); + if (dart.notNull(split[$length]) < 2) dart.throw(core.Exception.new("Controller redirects must take the form of 'Controller@action'. You gave: " + dart.str(action))); + let controller = this.app.controllers[$_get](split[$_get](0)[$replaceAll](src__core__response_context._straySlashes, "")); + if (controller == null) dart.throw(core.Exception.new("Could not find a controller named '" + dart.str(split[$_get](0)) + "'")); + let matched = controller.routeMappings[$_get](split[$_get](1)); + if (matched == null) dart.throw(core.Exception.new("Controller '" + dart.str(split[$_get](0)) + "' does not contain any action named '" + dart.str(split[$_get](1)) + "'")); + let head = dart.toString(controller.findExpose(this.app.container.reflector).path)[$replaceAll](src__core__response_context._straySlashes, ""); + let tail = matched.makeUri(params[$keys][$fold](MapOfString$dynamic(), new (IdentityMapOfString$dynamic()).new(), dart.fn((out, k) => { + let t1; + t1 = out; + t1[$_set](dart.toString(k), params[$_get](k)); + return t1; + }, MapOfString$dynamicAnddynamicToMapOfString$dynamic())))[$replaceAll](src__core__response_context._straySlashes, ""); + this.redirect((head + "/" + tail)[$replaceAll](src__core__response_context._straySlashes, ""), {code: code}); + } + sendFile(file) { + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + this.contentType = src__media_type.MediaType.parse(src__mime_type.lookupMimeType(file.path)); + this.buffer.add(file.readAsBytesSync()); + this.close(); + } + serialize(value, opts) { + let t1; + let contentType = opts && 'contentType' in opts ? opts.contentType : null; + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + this.contentType = (t1 = contentType, t1 == null ? new src__media_type.MediaType.new("application", "json") : t1); + let text = this.serializer(value); + if (text[$isEmpty]) return true; + this.write(text); + this.close(); + return false; + } + streamFile(file) { + if (!dart.test(this.isOpen)) dart.throw(src__core__response_context.ResponseContext.closed()); + this.contentType = src__media_type.MediaType.parse(src__mime_type.lookupMimeType(file.path)); + return file.openRead().pipe(this); + } + addError(error, stackTrace) { + let t1; + if (stackTrace === void 0) stackTrace = null; + if (dart.equals((t1 = this[_done], t1 == null ? null : t1.isCompleted), false)) this[_done].completeError(error, stackTrace); + } + write(value, opts) { + let encoding = opts && 'encoding' in opts ? opts.encoding : null; + encoding == null ? encoding = convert.utf8 : null; + if (!dart.test(this.isOpen) && dart.test(this.isBuffered)) + dart.throw(src__core__response_context.ResponseContext.closed()); + else if (!dart.test(this.isBuffered)) { + this.add(encoding.encode(dart.toString(value))); + } else { + this.buffer.add(encoding.encode(dart.toString(value))); + } + } + writeCharCode(charCode) { + if (!dart.test(this.isOpen) && dart.test(this.isBuffered)) + dart.throw(src__core__response_context.ResponseContext.closed()); + else if (!dart.test(this.isBuffered)) + this.add(JSArrayOfint().of([charCode])); + else + this.buffer.addByte(charCode); + } + writeln(obj) { + if (obj === void 0) obj = ""; + this.write(dart.toString(obj)); + this.write("\r\n"); + } + writeAll(objects, separator) { + if (separator === void 0) separator = ""; + this.write(objects[$join](separator)); + } + } + (ResponseContext.new = function() { + this[properties] = new _js_helper.LinkedMap.new(); + this[_headers] = new (IdentityMapOfString$String()).from(["server", "angel"]); + this[_done] = null; + this[_statusCode] = 200; + this[app] = null; + this[chunked] = null; + this[cookies] = JSArrayOfCookie().of([]); + this[encoders] = new (IdentityMapOfString$ConverterOfListOfint$ListOfint()).new(); + this[renderParams] = new (IdentityMapOfString$dynamic()).new(); + this[serializer] = dart.bind(convert.json, 'encode'); + this[contentType] = new src__media_type.MediaType.new("text", "plain"); + ; + }).prototype = ResponseContext.prototype; + dart.addTypeTests(ResponseContext); + ResponseContext.prototype[_is_ResponseContext_default] = true; + const properties = Symbol("ResponseContext.properties"); + const app = Symbol("ResponseContext.app"); + const chunked = Symbol("ResponseContext.chunked"); + const cookies = Symbol("ResponseContext.cookies"); + const encoders = Symbol("ResponseContext.encoders"); + const renderParams = Symbol("ResponseContext.renderParams"); + const serializer = Symbol("ResponseContext.serializer"); + const contentType = Symbol("ResponseContext.contentType"); + ResponseContext[dart.implements] = () => [async.StreamSink$(core.List$(core.int)), core.StringSink]; + dart.setMethodSignature(ResponseContext, () => ({ + __proto__: dart.getMethods(ResponseContext.__proto__), + download: dart.fnType(dart.void, [src__interface__file.File], {filename: core.String}), + close: dart.fnType(async.Future, []), + json: dart.fnType(dart.void, [dart.dynamic]), + jsonp: dart.fnType(dart.void, [dart.dynamic], {callbackName: core.String, contentType: src__media_type.MediaType}), + render: dart.fnType(async.Future, [core.String], [core.Map$(core.String, dart.dynamic)]), + redirect: dart.fnType(dart.void, [dart.dynamic], {absolute: core.bool, code: core.int}), + redirectTo: dart.fnType(dart.void, [core.String], [core.Map, core.int]), + redirectToAction: dart.fnType(dart.void, [core.String], [core.Map, core.int]), + sendFile: dart.fnType(dart.void, [src__interface__file.File]), + serialize: dart.fnType(core.bool, [dart.dynamic], {contentType: src__media_type.MediaType}), + streamFile: dart.fnType(async.Future, [src__interface__file.File]), + addError: dart.fnType(dart.void, [core.Object], [core.StackTrace]), + write: dart.fnType(dart.void, [core.Object], {encoding: convert.Encoding}), + writeCharCode: dart.fnType(dart.void, [core.int]), + writeln: dart.fnType(dart.void, [], [core.Object]), + writeAll: dart.fnType(dart.void, [core.Iterable], [core.String]) + })); + dart.setGetterSignature(ResponseContext, () => ({ + __proto__: dart.getGetters(ResponseContext.__proto__), + done: async.Future, + headers: core.Map$(core.String, core.String), + statusCode: core.int + })); + dart.setSetterSignature(ResponseContext, () => ({ + __proto__: dart.getSetters(ResponseContext.__proto__), + statusCode: core.int + })); + dart.setFieldSignature(ResponseContext, () => ({ + __proto__: dart.getFields(ResponseContext.__proto__), + properties: dart.finalFieldType(core.Map), + [_headers]: dart.finalFieldType(core.Map$(core.String, core.String)), + [_done]: dart.fieldType(async.Completer), + [_statusCode]: dart.fieldType(core.int), + app: dart.fieldType(src__core__server.Angel), + chunked: dart.fieldType(core.bool), + cookies: dart.finalFieldType(core.List$(_http.Cookie)), + encoders: dart.finalFieldType(core.Map$(core.String, convert.Converter$(core.List$(core.int), core.List$(core.int)))), + renderParams: dart.finalFieldType(core.Map$(core.String, dart.dynamic)), + serializer: dart.fieldType(dart.fnType(core.String, [dart.dynamic])), + contentType: dart.fieldType(src__media_type.MediaType) + })); + return ResponseContext; + }); + src__core__response_context.ResponseContext = src__core__response_context.ResponseContext$(); + dart.addTypeTests(src__core__response_context.ResponseContext, _is_ResponseContext_default); + src__core__routable.Routable = class Routable extends src__router.Router$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])) { + get configuration() { + return this[configuration]; + } + set configuration(value) { + super.configuration = value; + } + get container() { + return this[_container]; + } + close() { + this[_services][$clear](); + this.configuration[$clear](); + this[_onService].close(); + } + get services() { + return this[_services]; + } + get onService() { + return this[_onService].stream; + } + service(path) { + let t1; + t1 = this[_services][$_get](path); + return t1 == null ? this[_services][$_get](dart.toString(path)[$replaceAll](src__core__routable._straySlashes, "")) : t1; + } + addRoute(method, path, handler, opts) { + let t1, t1$; + RequestContextAndResponseContextToFutureOr()._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : const$1 || (const$1 = dart.constList([], RequestContextAndResponseContextToFutureOr())); + IterableOfRequestContextAndResponseContextToFutureOr()._check(middleware); + let handlers = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]); + let middlewareDeclaration = src__core__metadata.Middleware._check(src__util.getAnnotation(handler, dart.wrapType(src__core__metadata.Middleware), (t1 = this[_container], t1 == null ? null : t1.reflector))); + if (middlewareDeclaration != null) { + handlers[$addAll](middlewareDeclaration.handlers); + } + let handlerSequence = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]); + handlerSequence[$addAll]((t1$ = middleware, t1$ == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : t1$)); + handlerSequence[$addAll](handlers); + return super.addRoute(method, dart.toString(path), handler, {middleware: handlerSequence}); + } + use(path, service) { + let hooked = new src__core__hooked_service.HookedService.new(service); + this[_services][$_set](dart.toString(path)[$trim]()[$replaceAll](core.RegExp.new("(^/+)|(/+$)"), ""), hooked); + hooked.addRoutes(); + this.mount(dart.toString(path), hooked); + service.onHooked(hooked); + this[_onService].add(hooked); + return hooked; + } + }; + (src__core__routable.Routable.new = function(reflector) { + if (reflector === void 0) reflector = null; + this[_services] = new (LinkedMapOfPattern$Service()).new(); + this[configuration] = new _js_helper.LinkedMap.new(); + this[_onService] = StreamControllerOfService().broadcast(); + this[_container] = reflector == null ? null : new src__container.Container.new(reflector); + src__core__routable.Routable.__proto__.new.call(this); + ; + }).prototype = src__core__routable.Routable.prototype; + dart.addTypeTests(src__core__routable.Routable); + const configuration = Symbol("Routable.configuration"); + dart.setMethodSignature(src__core__routable.Routable, () => ({ + __proto__: dart.getMethods(src__core__routable.Routable.__proto__), + close: dart.fnType(dart.void, []), + service: dart.fnType(src__core__service.Service, [core.Pattern]), + use: dart.fnType(src__core__hooked_service.HookedService, [core.String, src__core__service.Service]) + })); + dart.setGetterSignature(src__core__routable.Routable, () => ({ + __proto__: dart.getGetters(src__core__routable.Routable.__proto__), + container: src__container.Container, + services: core.Map$(core.Pattern, src__core__service.Service), + onService: async.Stream$(src__core__service.Service) + })); + dart.setFieldSignature(src__core__routable.Routable, () => ({ + __proto__: dart.getFields(src__core__routable.Routable.__proto__), + [_services]: dart.finalFieldType(core.Map$(core.Pattern, src__core__service.Service)), + configuration: dart.finalFieldType(core.Map), + [_container]: dart.finalFieldType(src__container.Container), + [_onService]: dart.fieldType(async.StreamController$(src__core__service.Service)) + })); + src__core__service.Service = class Service extends src__core__routable.Routable { + get app() { + return this[app]; + } + set app(value) { + this[app] = value; + } + get bootstrappers() { + return JSArrayOfRequestContextAndResponseContextToFutureOr().of([]); + } + close() { + } + findOne(params, errorMessage) { + if (params === void 0) params = null; + if (errorMessage === void 0) errorMessage = "No record was found matching the given query."; + return this.index(params).then(dart.dynamic, dart.fn(result => { + if (result == null) { + dart.throw(angel_http_exception.AngelHttpException.notFound({message: errorMessage})); + } else if (core.Iterable.is(result)) { + if (dart.test(result[$isEmpty])) { + dart.throw(angel_http_exception.AngelHttpException.notFound({message: errorMessage})); + } else { + return result[$first]; + } + } else { + return result; + } + }, dynamicTodynamic())); + } + index(params) { + if (params === void 0) params = null; + dart.throw(angel_http_exception.AngelHttpException.methodNotAllowed()); + } + read(id, params) { + if (params === void 0) params = null; + dart.throw(angel_http_exception.AngelHttpException.methodNotAllowed()); + } + create(data, params) { + if (params === void 0) params = null; + dart.throw(angel_http_exception.AngelHttpException.methodNotAllowed()); + } + modify(id, data, params) { + if (params === void 0) params = null; + dart.throw(angel_http_exception.AngelHttpException.methodNotAllowed()); + } + update(id, data, params) { + if (params === void 0) params = null; + dart.throw(angel_http_exception.AngelHttpException.methodNotAllowed()); + } + remove(id, params) { + if (params === void 0) params = null; + dart.throw(angel_http_exception.AngelHttpException.methodNotAllowed()); + } + static parseId(T, id) { + let t1; + if (dart.equals(id, "null") || id == null) + return null; + else if (dart.wrapType(T)[$_equals](dart.wrapType(core.String))) + return T.as(dart.toString(id)); + else if (dart.wrapType(T)[$_equals](dart.wrapType(core.int))) + return T.as(core.int.parse(dart.toString(id))); + else if (dart.wrapType(T)[$_equals](dart.wrapType(core.bool))) + return T.as(dart.equals(id, true) || (t1 = id, t1 == null ? null : dart.toString(t1)) === "true"); + else if (dart.wrapType(T)[$_equals](dart.wrapType(core.double))) + return T.as(core.int.parse(dart.toString(id))); + else if (dart.wrapType(T)[$_equals](dart.wrapType(core.num))) + return T.as(core.num.parse(dart.toString(id))); + else + return T.as(id); + } + addRoutes(service) { + let t1; + if (service === void 0) service = null; + this[_addRoutesInner]((t1 = service, t1 == null ? this : t1), this.bootstrappers); + } + [_addRoutesInner](service, handlerss) { + let t1, t1$, t1$0, t1$1, t1$2, t1$3, t1$4, t1$5; + let restProvider = new (IdentityMapOfString$Providers()).from(["provider", src__core__service.Providers.rest]); + let handlers = ListOfRequestContextAndResponseContextToFutureOr().from(handlerss); + let before = src__core__metadata.Middleware._check(src__util.getAnnotation(service, dart.wrapType(src__core__metadata.Middleware), this.app.container.reflector)); + if (before != null) handlers[$addAll](before.handlers); + let indexMiddleware = src__core__metadata.Middleware._check(src__util.getAnnotation(dart.bind(service, 'index'), dart.wrapType(src__core__metadata.Middleware), this.app.container.reflector)); + this.get("/", dart.fn((req, res) => req.parseQuery().then(dart.dynamic, dart.fn(query => this.index(merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))), MapOfString$dynamicToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1[$addAll](handlers), t1[$addAll](indexMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : indexMiddleware.handlers), t1)}); + let createMiddleware = src__core__metadata.Middleware._check(src__util.getAnnotation(dart.bind(service, 'create'), dart.wrapType(src__core__metadata.Middleware), this.app.container.reflector)); + this.post("/", dart.fn((req, res) => req.parseQuery().then(dart.dynamic, dart.fn(query => req.parseBody().then(dart.dynamic, dart.fn(body => this.create(body, merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))).then(dart.dynamic, dart.fn(r => { + res.statusCode = 201; + return r; + }, dynamicTodynamic())), MapToFuture())), MapOfString$dynamicToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1$ = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$[$addAll](handlers), t1$[$addAll](createMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : createMiddleware.handlers), t1$)}); + let readMiddleware = src__core__metadata.Middleware._check(src__util.getAnnotation(dart.bind(service, 'read'), dart.wrapType(src__core__metadata.Middleware), this.app.container.reflector)); + this.get("/:id", dart.fn((req, res) => req.parseQuery().then(dart.dynamic, dart.fn(query => this.read(src__core__service.Service.parseId(dart.dynamic, req.params[$_get]("id")), merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))), MapOfString$dynamicToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1$0 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$0[$addAll](handlers), t1$0[$addAll](readMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : readMiddleware.handlers), t1$0)}); + let modifyMiddleware = src__core__metadata.Middleware._check(src__util.getAnnotation(dart.bind(service, 'modify'), dart.wrapType(src__core__metadata.Middleware), this.app.container.reflector)); + this.patch("/:id", dart.fn((req, res) => req.parseBody().then(dart.dynamic, dart.fn(body => req.parseQuery().then(dart.dynamic, dart.fn(query => this.modify(src__core__service.Service.parseId(dart.dynamic, req.params[$_get]("id")), body, merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))), MapOfString$dynamicToFuture())), MapToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1$1 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$1[$addAll](handlers), t1$1[$addAll](modifyMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : modifyMiddleware.handlers), t1$1)}); + let updateMiddleware = src__core__metadata.Middleware._check(src__util.getAnnotation(dart.bind(service, 'update'), dart.wrapType(src__core__metadata.Middleware), this.app.container.reflector)); + this.post("/:id", dart.fn((req, res) => req.parseBody().then(dart.dynamic, dart.fn(body => req.parseQuery().then(dart.dynamic, dart.fn(query => this.update(src__core__service.Service.parseId(dart.dynamic, req.params[$_get]("id")), body, merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))), MapOfString$dynamicToFuture())), MapToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1$2 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$2[$addAll](handlers), t1$2[$addAll](updateMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : updateMiddleware.handlers), t1$2)}); + this.put("/:id", dart.fn((req, res) => req.parseBody().then(dart.dynamic, dart.fn(body => req.parseQuery().then(dart.dynamic, dart.fn(query => this.update(src__core__service.Service.parseId(dart.dynamic, req.params[$_get]("id")), body, merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))), MapOfString$dynamicToFuture())), MapToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1$3 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$3[$addAll](handlers), t1$3[$addAll](updateMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : updateMiddleware.handlers), t1$3)}); + let removeMiddleware = src__core__metadata.Middleware._check(src__util.getAnnotation(dart.bind(service, 'remove'), dart.wrapType(src__core__metadata.Middleware), this.app.container.reflector)); + this.delete("/", dart.fn((req, res) => req.parseQuery().then(dart.dynamic, dart.fn(query => this.remove(null, merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))), MapOfString$dynamicToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1$4 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$4[$addAll](handlers), t1$4[$addAll](removeMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : removeMiddleware.handlers), t1$4)}); + this.delete("/:id", dart.fn((req, res) => req.parseQuery().then(dart.dynamic, dart.fn(query => this.remove(src__core__service.Service.parseId(dart.dynamic, req.params[$_get]("id")), merge_map.mergeMap(dart.dynamic, dart.dynamic, JSArrayOfMap().of([new _js_helper.LinkedMap.from(["query", query]), restProvider, req.serviceParams]))), MapOfString$dynamicToFuture())), RequestContextAndResponseContextToFuture()), {middleware: (t1$5 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$5[$addAll](handlers), t1$5[$addAll](removeMiddleware == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : removeMiddleware.handlers), t1$5)}); + this.put("/", dart.fn((req, res) => dart.throw(angel_http_exception.AngelHttpException.notFound()), RequestContextAndResponseContextTobottom())); + this.patch("/", dart.fn((req, res) => dart.throw(angel_http_exception.AngelHttpException.notFound()), RequestContextAndResponseContextTobottom())); + } + onHooked(hookedService) { + } + }; + (src__core__service.Service.new = function() { + this[app] = null; + src__core__service.Service.__proto__.new.call(this); + ; + }).prototype = src__core__service.Service.prototype; + dart.addTypeTests(src__core__service.Service); + const app = Symbol("Service.app"); + dart.setMethodSignature(src__core__service.Service, () => ({ + __proto__: dart.getMethods(src__core__service.Service.__proto__), + findOne: dart.fnType(async.Future, [], [core.Map, core.String]), + index: dart.fnType(async.Future, [], [core.Map]), + read: dart.fnType(async.Future, [dart.dynamic], [core.Map]), + create: dart.fnType(async.Future, [dart.dynamic], [core.Map]), + modify: dart.fnType(async.Future, [dart.dynamic, dart.dynamic], [core.Map]), + update: dart.fnType(async.Future, [dart.dynamic, dart.dynamic], [core.Map]), + remove: dart.fnType(async.Future, [dart.dynamic], [core.Map]), + addRoutes: dart.fnType(dart.void, [], [src__core__service.Service]), + [_addRoutesInner]: dart.fnType(dart.void, [src__core__service.Service, core.Iterable$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext]))]), + onHooked: dart.fnType(dart.void, [src__core__hooked_service.HookedService]) + })); + dart.setGetterSignature(src__core__service.Service, () => ({ + __proto__: dart.getGetters(src__core__service.Service.__proto__), + bootstrappers: core.List$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])) + })); + dart.setFieldSignature(src__core__service.Service, () => ({ + __proto__: dart.getFields(src__core__service.Service.__proto__), + app: dart.fieldType(src__core__server.Angel) + })); + dart.defineLazy(src__core__service.Service, { + /*src__core__service.Service.specialQueryKeys*/get specialQueryKeys() { + return dart.constList(["$limit", "$sort", "page", "token"], core.String); + } + }); + src__core__anonymous_service.AnonymousService = class AnonymousService extends src__core__service.Service { + index(params) { + if (params === void 0) params = null; + return async.Future.sync(dart.fn(() => this[_index] != null ? this[_index](params) : super.index(params), VoidToFutureOr())); + } + read(id, params) { + if (params === void 0) params = null; + return async.Future.sync(dart.fn(() => this[_read] != null ? this[_read](id, params) : super.read(id, params), VoidToFutureOr())); + } + create(data, params) { + if (params === void 0) params = null; + return async.Future.sync(dart.fn(() => this[_create] != null ? this[_create](data, params) : super.create(data, params), VoidToFutureOr())); + } + modify(id, data, params) { + if (params === void 0) params = null; + return async.Future.sync(dart.fn(() => this[_modify] != null ? this[_modify](id, data, params) : super.modify(id, data, params), VoidToFutureOr())); + } + update(id, data, params) { + if (params === void 0) params = null; + return async.Future.sync(dart.fn(() => this[_update] != null ? this[_update](id, data, params) : super.update(id, data, params), VoidToFutureOr())); + } + remove(id, params) { + if (params === void 0) params = null; + return async.Future.sync(dart.fn(() => this[_remove] != null ? this[_remove](id, params) : super.remove(id, params), VoidToFutureOr())); + } + }; + (src__core__anonymous_service.AnonymousService.new = function(opts) { + let index = opts && 'index' in opts ? opts.index : null; + let read = opts && 'read' in opts ? opts.read : null; + let create = opts && 'create' in opts ? opts.create : null; + let modify = opts && 'modify' in opts ? opts.modify : null; + let update = opts && 'update' in opts ? opts.update : null; + let remove = opts && 'remove' in opts ? opts.remove : null; + this[_index] = null; + this[_read] = null; + this[_create] = null; + this[_remove] = null; + this[_modify] = null; + this[_update] = null; + src__core__anonymous_service.AnonymousService.__proto__.new.call(this); + this[_index] = index; + this[_read] = read; + this[_create] = create; + this[_modify] = modify; + this[_update] = update; + this[_remove] = remove; + }).prototype = src__core__anonymous_service.AnonymousService.prototype; + dart.addTypeTests(src__core__anonymous_service.AnonymousService); + dart.setFieldSignature(src__core__anonymous_service.AnonymousService, () => ({ + __proto__: dart.getFields(src__core__anonymous_service.AnonymousService.__proto__), + [_index]: dart.fieldType(dart.fnType(async.FutureOr, [], [core.Map])), + [_read]: dart.fieldType(dart.fnType(async.FutureOr, [core.Object], [core.Map])), + [_create]: dart.fieldType(dart.fnType(async.FutureOr, [core.Object], [core.Map])), + [_remove]: dart.fieldType(dart.fnType(async.FutureOr, [core.Object], [core.Map])), + [_modify]: dart.fieldType(dart.fnType(async.FutureOr, [core.Object, core.Object], [core.Map])), + [_update]: dart.fieldType(dart.fnType(async.FutureOr, [core.Object, core.Object], [core.Map])) + })); + const _ctrl = Symbol('_ctrl'); + const _getRequest = Symbol('_getRequest'); + const _getResponse = Symbol('_getResponse'); + const _stripReq = Symbol('_stripReq'); + const _close = Symbol('_close'); + const _emit = Symbol('_emit'); + const _canceled = Symbol('_canceled'); + src__core__hooked_service.HookedService = class HookedService extends src__core__service.Service { + get inner() { + return this[inner$]; + } + set inner(value) { + super.inner = value; + } + get beforeIndexed() { + return this[beforeIndexed]; + } + set beforeIndexed(value) { + super.beforeIndexed = value; + } + get beforeRead() { + return this[beforeRead]; + } + set beforeRead(value) { + super.beforeRead = value; + } + get beforeCreated() { + return this[beforeCreated]; + } + set beforeCreated(value) { + super.beforeCreated = value; + } + get beforeModified() { + return this[beforeModified]; + } + set beforeModified(value) { + super.beforeModified = value; + } + get beforeUpdated() { + return this[beforeUpdated]; + } + set beforeUpdated(value) { + super.beforeUpdated = value; + } + get beforeRemoved() { + return this[beforeRemoved]; + } + set beforeRemoved(value) { + super.beforeRemoved = value; + } + get afterIndexed() { + return this[afterIndexed]; + } + set afterIndexed(value) { + super.afterIndexed = value; + } + get afterRead() { + return this[afterRead]; + } + set afterRead(value) { + super.afterRead = value; + } + get afterCreated() { + return this[afterCreated]; + } + set afterCreated(value) { + super.afterCreated = value; + } + get afterModified() { + return this[afterModified]; + } + set afterModified(value) { + super.afterModified = value; + } + get afterUpdated() { + return this[afterUpdated]; + } + set afterUpdated(value) { + super.afterUpdated = value; + } + get afterRemoved() { + return this[afterRemoved]; + } + set afterRemoved(value) { + super.afterRemoved = value; + } + [_getRequest](params) { + if (params == null) return null; + return src__core__request_context.RequestContext.as(params[$_get]("__requestctx")); + } + [_getResponse](params) { + if (params == null) return null; + return src__core__response_context.ResponseContext.as(params[$_get]("__responsectx")); + } + [_stripReq](params) { + if (params == null) + return params; + else + return params[$keys][$where](dart.fn(key => !dart.equals(key, "__requestctx") && !dart.equals(key, "__responsectx"), dynamicTobool()))[$fold](core.Map, new _js_helper.LinkedMap.new(), dart.fn((map, key) => { + let t1; + t1 = map; + t1[$_set](key, params[$_get](key)); + return t1; + }, MapAnddynamicToMap())); + } + close() { + this[_ctrl][$forEach](dart.fn(c => c.close(), StreamControllerOfHookedServiceEventTovoid())); + this.beforeIndexed[_close](); + this.beforeRead[_close](); + this.beforeCreated[_close](); + this.beforeModified[_close](); + this.beforeUpdated[_close](); + this.beforeRemoved[_close](); + this.afterIndexed[_close](); + this.afterRead[_close](); + this.afterCreated[_close](); + this.afterModified[_close](); + this.afterUpdated[_close](); + this.afterRemoved[_close](); + this.inner.close(); + return async.Future.value(); + } + addHooks(app) { + let hooks = src__core__metadata.Hooks._check(src__util.getAnnotation(this.inner, dart.wrapType(src__core__metadata.Hooks), app.container.reflector)); + let before = JSArrayOfHookedServiceEventTodynamic().of([]); + let after = JSArrayOfHookedServiceEventTodynamic().of([]); + if (hooks != null) { + before[$addAll](hooks.before); + after[$addAll](hooks.after); + } + function applyListeners(fn, dispatcher, isAfter) { + let t1; + if (isAfter === void 0) isAfter = null; + let hooks = src__core__metadata.Hooks._check(src__util.getAnnotation(fn, dart.wrapType(src__core__metadata.Hooks), app.container.reflector)); + let listeners = (t1 = JSArrayOfHookedServiceEventTodynamic().of([]), t1[$addAll](dart.equals(isAfter, true) ? after : before), t1); + if (hooks != null) listeners[$addAll](dart.equals(isAfter, true) ? hooks.after : hooks.before); + listeners[$forEach](dart.bind(dispatcher, 'listen')); + } + dart.fn(applyListeners, FunctionAndHookedServiceEventDispatcherAndboolTovoid()); + applyListeners(dart.bind(this.inner, 'index'), this.beforeIndexed); + applyListeners(dart.bind(this.inner, 'read'), this.beforeRead); + applyListeners(dart.bind(this.inner, 'create'), this.beforeCreated); + applyListeners(dart.bind(this.inner, 'modify'), this.beforeModified); + applyListeners(dart.bind(this.inner, 'update'), this.beforeUpdated); + applyListeners(dart.bind(this.inner, 'remove'), this.beforeRemoved); + applyListeners(dart.bind(this.inner, 'index'), this.afterIndexed, true); + applyListeners(dart.bind(this.inner, 'read'), this.afterRead, true); + applyListeners(dart.bind(this.inner, 'create'), this.afterCreated, true); + applyListeners(dart.bind(this.inner, 'modify'), this.afterModified, true); + applyListeners(dart.bind(this.inner, 'update'), this.afterUpdated, true); + applyListeners(dart.bind(this.inner, 'remove'), this.afterRemoved, true); + } + get bootstrappers() { + let t1; + t1 = ListOfRequestContextAndResponseContextToFutureOr().from(super.bootstrappers); + t1[$add](dart.fn((req, res) => { + let t2; + t2 = req.serviceParams; + t2[$_set]("__requestctx", req); + t2[$_set]("__responsectx", res); + t2; + return true; + }, RequestContextAndResponseContextTobool())); + return t1; + } + addRoutes(s) { + let t1; + if (s === void 0) s = null; + super.addRoutes((t1 = s, t1 == null ? this.inner : t1)); + } + before(eventNames, listener) { + eventNames[$map](src__core__hooked_service.HookedServiceEventDispatcher, dart.fn(name => { + switch (name) { + case "indexed": + { + return this.beforeIndexed; + } + case "read": + { + return this.beforeRead; + } + case "created": + { + return this.beforeCreated; + } + case "modified": + { + return this.beforeModified; + } + case "updated": + { + return this.beforeUpdated; + } + case "removed": + { + return this.beforeRemoved; + } + default: + { + dart.throw(new core.ArgumentError.new("Invalid service method: " + dart.str(name))); + } + } + }, StringToHookedServiceEventDispatcher()))[$forEach](dart.fn(dispatcher => dispatcher.listen(listener), HookedServiceEventDispatcherTovoid())); + } + after(eventNames, listener) { + eventNames[$map](src__core__hooked_service.HookedServiceEventDispatcher, dart.fn(name => { + switch (name) { + case "indexed": + { + return this.afterIndexed; + } + case "read": + { + return this.afterRead; + } + case "created": + { + return this.afterCreated; + } + case "modified": + { + return this.afterModified; + } + case "updated": + { + return this.afterUpdated; + } + case "removed": + { + return this.afterRemoved; + } + default: + { + dart.throw(new core.ArgumentError.new("Invalid service method: " + dart.str(name))); + } + } + }, StringToHookedServiceEventDispatcher()))[$forEach](dart.fn(dispatcher => dispatcher.listen(listener), HookedServiceEventDispatcherTovoid())); + } + beforeAll(listener) { + this.beforeIndexed.listen(listener); + this.beforeRead.listen(listener); + this.beforeCreated.listen(listener); + this.beforeModified.listen(listener); + this.beforeUpdated.listen(listener); + this.beforeRemoved.listen(listener); + } + afterAll(listener) { + this.afterIndexed.listen(listener); + this.afterRead.listen(listener); + this.afterCreated.listen(listener); + this.afterModified.listen(listener); + this.afterUpdated.listen(listener); + this.afterRemoved.listen(listener); + } + beforeAllStream() { + let ctrl = StreamControllerOfHookedServiceEvent().new(); + this[_ctrl][$add](ctrl); + this.before(src__core__hooked_service.HookedServiceEvent.all, dart.bind(ctrl, 'add')); + return ctrl.stream; + } + afterAllStream() { + let ctrl = StreamControllerOfHookedServiceEvent().new(); + this[_ctrl][$add](ctrl); + this.before(src__core__hooked_service.HookedServiceEvent.all, dart.bind(ctrl, 'add')); + return ctrl.stream; + } + beforeStream(eventNames) { + let ctrl = StreamControllerOfHookedServiceEvent().new(); + this[_ctrl][$add](ctrl); + this.before(eventNames, dart.bind(ctrl, 'add')); + return ctrl.stream; + } + afterStream(eventNames) { + let ctrl = StreamControllerOfHookedServiceEvent().new(); + this[_ctrl][$add](ctrl); + this.after(eventNames, dart.bind(ctrl, 'add')); + return ctrl.stream; + } + beforeModify(listener) { + this.beforeCreated.listen(listener); + this.beforeModified.listen(listener); + this.beforeUpdated.listen(listener); + } + index(_params) { + if (_params === void 0) _params = null; + let params = this[_stripReq](_params); + return this.beforeIndexed[_emit](new src__core__hooked_service.HookedServiceEvent.new(false, this[_getRequest](_params), this[_getResponse](_params), this.inner, "indexed", {params: params})).then(dart.dynamic, dart.fn(before => { + if (dart.test(before[_canceled])) { + return this.beforeIndexed[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "indexed", {params: params, result: before.result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())); + } + return this.inner.index(params).then(dart.dynamic, dart.fn(result => this.afterIndexed[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "indexed", {params: params, result: result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())), dynamicToFuture())); + }, HookedServiceEventToFuture())); + } + read(id, _params) { + if (_params === void 0) _params = null; + let params = this[_stripReq](_params); + return this.beforeRead[_emit](new src__core__hooked_service.HookedServiceEvent.new(false, this[_getRequest](_params), this[_getResponse](_params), this.inner, "read", {id: id, params: params})).then(dart.dynamic, dart.fn(before => { + if (dart.test(before[_canceled])) { + return this.beforeRead[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "read", {id: id, params: params, result: before.result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())); + } + return this.inner.read(id, params).then(dart.dynamic, dart.fn(result => this.afterRead[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "read", {id: id, params: params, result: result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())), dynamicToFuture())); + }, HookedServiceEventToFuture())); + } + create(data, _params) { + if (_params === void 0) _params = null; + let params = this[_stripReq](_params); + return this.beforeCreated[_emit](new src__core__hooked_service.HookedServiceEvent.new(false, this[_getRequest](_params), this[_getResponse](_params), this.inner, "created", {data: data, params: params})).then(dart.dynamic, dart.fn(before => { + if (dart.test(before[_canceled])) { + return this.beforeCreated[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "created", {data: data, params: params, result: before.result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())); + } + return this.inner.create(data, params).then(dart.dynamic, dart.fn(result => this.afterCreated[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "created", {data: data, params: params, result: result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())), dynamicToFuture())); + }, HookedServiceEventToFuture())); + } + modify(id, data, _params) { + if (_params === void 0) _params = null; + let params = this[_stripReq](_params); + return this.beforeModified[_emit](new src__core__hooked_service.HookedServiceEvent.new(false, this[_getRequest](_params), this[_getResponse](_params), this.inner, "modified", {id: id, data: data, params: params})).then(dart.dynamic, dart.fn(before => { + if (dart.test(before[_canceled])) { + return this.beforeModified[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "modified", {id: id, data: data, params: params, result: before.result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())); + } + return this.inner.modify(id, data, params).then(dart.dynamic, dart.fn(result => this.afterModified[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "created", {id: id, data: data, params: params, result: result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())), dynamicToFuture())); + }, HookedServiceEventToFuture())); + } + update(id, data, _params) { + if (_params === void 0) _params = null; + let params = this[_stripReq](_params); + return this.beforeUpdated[_emit](new src__core__hooked_service.HookedServiceEvent.new(false, this[_getRequest](_params), this[_getResponse](_params), this.inner, "updated", {id: id, data: data, params: params})).then(dart.dynamic, dart.fn(before => { + if (dart.test(before[_canceled])) { + return this.beforeUpdated[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "updated", {id: id, data: data, params: params, result: before.result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())); + } + return this.inner.update(id, data, params).then(dart.dynamic, dart.fn(result => this.afterUpdated[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "updated", {id: id, data: data, params: params, result: result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())), dynamicToFuture())); + }, HookedServiceEventToFuture())); + } + remove(id, _params) { + if (_params === void 0) _params = null; + let params = this[_stripReq](_params); + return this.beforeRemoved[_emit](new src__core__hooked_service.HookedServiceEvent.new(false, this[_getRequest](_params), this[_getResponse](_params), this.inner, "removed", {id: id, params: params})).then(dart.dynamic, dart.fn(before => { + if (dart.test(before[_canceled])) { + return this.beforeRemoved[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "removed", {id: id, params: params, result: before.result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())); + } + return this.inner.remove(id, params).then(dart.dynamic, dart.fn(result => this.afterRemoved[_emit](new src__core__hooked_service.HookedServiceEvent.new(true, this[_getRequest](_params), this[_getResponse](_params), this.inner, "removed", {id: id, params: params, result: result})).then(dart.dynamic, dart.fn(after => after.result, HookedServiceEventTodynamic())), dynamicToFuture())); + }, HookedServiceEventToFuture())); + } + fire(eventName, result, callback) { + if (callback === void 0) callback = null; + let dispatcher = null; + switch (eventName) { + case "indexed": + { + dispatcher = this.afterIndexed; + break; + } + case "read": + { + dispatcher = this.afterRead; + break; + } + case "created": + { + dispatcher = this.afterCreated; + break; + } + case "modified": + { + dispatcher = this.afterModified; + break; + } + case "updated": + { + dispatcher = this.afterUpdated; + break; + } + case "removed": + { + dispatcher = this.afterRemoved; + break; + } + default: + { + dart.throw(new core.ArgumentError.new("Invalid service event name: '" + dart.str(eventName) + "'")); + } + } + let ev = new src__core__hooked_service.HookedServiceEvent.new(true, null, null, this, eventName); + return this.fireEvent(dispatcher, ev, callback); + } + fireEvent(dispatcher, event, callback) { + let t1; + if (callback === void 0) callback = null; + let f = null; + if (callback != null && !dart.equals((t1 = event, t1 == null ? null : t1[_canceled]), true)) f = async.Future.sync(dart.fn(() => callback(event), VoidTodynamic())); + f == null ? f = async.Future.value() : null; + return f.then(src__core__hooked_service.HookedServiceEvent, dart.fn(_ => dispatcher[_emit](event), dynamicToFutureOfHookedServiceEvent())); + } + }; + (src__core__hooked_service.HookedService.new = function(inner) { + this[_ctrl] = JSArrayOfStreamControllerOfHookedServiceEvent().of([]); + this[beforeIndexed] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[beforeRead] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[beforeCreated] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[beforeModified] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[beforeUpdated] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[beforeRemoved] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[afterIndexed] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[afterRead] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[afterCreated] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[afterModified] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[afterUpdated] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[afterRemoved] = new src__core__hooked_service.HookedServiceEventDispatcher.new(); + this[inner$] = inner; + src__core__hooked_service.HookedService.__proto__.new.call(this); + if (this.inner.app != null) this.app = this.inner.app; + }).prototype = src__core__hooked_service.HookedService.prototype; + dart.addTypeTests(src__core__hooked_service.HookedService); + const inner$ = Symbol("HookedService.inner"); + const beforeIndexed = Symbol("HookedService.beforeIndexed"); + const beforeRead = Symbol("HookedService.beforeRead"); + const beforeCreated = Symbol("HookedService.beforeCreated"); + const beforeModified = Symbol("HookedService.beforeModified"); + const beforeUpdated = Symbol("HookedService.beforeUpdated"); + const beforeRemoved = Symbol("HookedService.beforeRemoved"); + const afterIndexed = Symbol("HookedService.afterIndexed"); + const afterRead = Symbol("HookedService.afterRead"); + const afterCreated = Symbol("HookedService.afterCreated"); + const afterModified = Symbol("HookedService.afterModified"); + const afterUpdated = Symbol("HookedService.afterUpdated"); + const afterRemoved = Symbol("HookedService.afterRemoved"); + dart.setMethodSignature(src__core__hooked_service.HookedService, () => ({ + __proto__: dart.getMethods(src__core__hooked_service.HookedService.__proto__), + [_getRequest]: dart.fnType(src__core__request_context.RequestContext, [core.Map]), + [_getResponse]: dart.fnType(src__core__response_context.ResponseContext, [core.Map]), + [_stripReq]: dart.fnType(core.Map, [core.Map]), + close: dart.fnType(async.Future, []), + addHooks: dart.fnType(dart.void, [src__core__server.Angel]), + before: dart.fnType(dart.void, [core.Iterable$(core.String), dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]), + after: dart.fnType(dart.void, [core.Iterable$(core.String), dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]), + beforeAll: dart.fnType(dart.void, [dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]), + afterAll: dart.fnType(dart.void, [dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]), + beforeAllStream: dart.fnType(async.Stream$(src__core__hooked_service.HookedServiceEvent), []), + afterAllStream: dart.fnType(async.Stream$(src__core__hooked_service.HookedServiceEvent), []), + beforeStream: dart.fnType(async.Stream$(src__core__hooked_service.HookedServiceEvent), [core.Iterable$(core.String)]), + afterStream: dart.fnType(async.Stream$(src__core__hooked_service.HookedServiceEvent), [core.Iterable$(core.String)]), + beforeModify: dart.fnType(dart.void, [dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]), + fire: dart.fnType(async.Future$(src__core__hooked_service.HookedServiceEvent), [core.String, dart.dynamic], [dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]), + fireEvent: dart.fnType(async.Future$(src__core__hooked_service.HookedServiceEvent), [src__core__hooked_service.HookedServiceEventDispatcher, src__core__hooked_service.HookedServiceEvent], [dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]) + })); + dart.setFieldSignature(src__core__hooked_service.HookedService, () => ({ + __proto__: dart.getFields(src__core__hooked_service.HookedService.__proto__), + [_ctrl]: dart.finalFieldType(core.List$(async.StreamController$(src__core__hooked_service.HookedServiceEvent))), + inner: dart.finalFieldType(src__core__service.Service), + beforeIndexed: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + beforeRead: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + beforeCreated: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + beforeModified: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + beforeUpdated: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + beforeRemoved: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + afterIndexed: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + afterRead: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + afterCreated: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + afterModified: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + afterUpdated: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher), + afterRemoved: dart.finalFieldType(src__core__hooked_service.HookedServiceEventDispatcher) + })); + const _id = Symbol('_id'); + const _params = Symbol('_params'); + const _isAfter$ = Symbol('_isAfter'); + const _request$ = Symbol('_request'); + const _response$ = Symbol('_response'); + const _eventName$ = Symbol('_eventName'); + src__core__hooked_service.HookedServiceEvent = class HookedServiceEvent extends core.Object { + get data() { + return this[data$]; + } + set data(value) { + this[data$] = value; + } + get result() { + return this[result$]; + } + set result(value) { + this[result$] = value; + } + get service() { + return this[service$]; + } + set service(value) { + this[service$] = value; + } + cancel(result) { + let t1; + if (result === void 0) result = null; + this[_canceled] = true; + this.result = (t1 = result, t1 == null ? this.result : t1); + } + getService(path) { + return this.service.app.service(path); + } + get eventName() { + return this[_eventName$]; + } + get id() { + return this[_id]; + } + get isAfter() { + return dart.equals(this[_isAfter$], true); + } + get isBefore() { + return !dart.test(this.isAfter); + } + get params() { + return this[_params]; + } + get request() { + return this[_request$]; + } + get response() { + return this[_response$]; + } + }; + (src__core__hooked_service.HookedServiceEvent.new = function(_isAfter, _request, _response, service, _eventName, opts) { + let t1; + let id = opts && 'id' in opts ? opts.id : null; + let data = opts && 'data' in opts ? opts.data : null; + let params = opts && 'params' in opts ? opts.params : null; + let result = opts && 'result' in opts ? opts.result : null; + this[_canceled] = false; + this[_id] = null; + this[_params] = null; + this[_isAfter$] = _isAfter; + this[_request$] = _request; + this[_response$] = _response; + this[service$] = service; + this[_eventName$] = _eventName; + this[data$] = data; + this[result$] = result; + this[_id] = id; + this[_params] = (t1 = params, t1 == null ? new _js_helper.LinkedMap.new() : t1); + }).prototype = src__core__hooked_service.HookedServiceEvent.prototype; + dart.addTypeTests(src__core__hooked_service.HookedServiceEvent); + const data$ = Symbol("HookedServiceEvent.data"); + const result$ = Symbol("HookedServiceEvent.result"); + const service$ = Symbol("HookedServiceEvent.service"); + dart.setMethodSignature(src__core__hooked_service.HookedServiceEvent, () => ({ + __proto__: dart.getMethods(src__core__hooked_service.HookedServiceEvent.__proto__), + cancel: dart.fnType(dart.void, [], [dart.dynamic]), + getService: dart.fnType(src__core__service.Service, [core.Pattern]) + })); + dart.setGetterSignature(src__core__hooked_service.HookedServiceEvent, () => ({ + __proto__: dart.getGetters(src__core__hooked_service.HookedServiceEvent.__proto__), + eventName: core.String, + id: dart.dynamic, + isAfter: core.bool, + isBefore: core.bool, + params: core.Map, + request: src__core__request_context.RequestContext, + response: src__core__response_context.ResponseContext + })); + dart.setFieldSignature(src__core__hooked_service.HookedServiceEvent, () => ({ + __proto__: dart.getFields(src__core__hooked_service.HookedServiceEvent.__proto__), + [_canceled]: dart.fieldType(core.bool), + [_eventName$]: dart.fieldType(core.String), + [_id]: dart.fieldType(dart.dynamic), + [_isAfter$]: dart.fieldType(core.bool), + data: dart.fieldType(dart.dynamic), + [_params]: dart.fieldType(core.Map), + [_request$]: dart.fieldType(src__core__request_context.RequestContext), + [_response$]: dart.fieldType(src__core__response_context.ResponseContext), + result: dart.fieldType(dart.dynamic), + service: dart.fieldType(src__core__service.Service) + })); + dart.defineLazy(src__core__hooked_service.HookedServiceEvent, { + /*src__core__hooked_service.HookedServiceEvent.indexed*/get indexed() { + return "indexed"; + }, + /*src__core__hooked_service.HookedServiceEvent.read*/get read() { + return "read"; + }, + /*src__core__hooked_service.HookedServiceEvent.created*/get created() { + return "created"; + }, + /*src__core__hooked_service.HookedServiceEvent.modified*/get modified() { + return "modified"; + }, + /*src__core__hooked_service.HookedServiceEvent.updated*/get updated() { + return "updated"; + }, + /*src__core__hooked_service.HookedServiceEvent.removed*/get removed() { + return "removed"; + }, + /*src__core__hooked_service.HookedServiceEvent.all*/get all() { + return dart.constList(["indexed", "read", "created", "modified", "updated", "removed"], core.String); + } + }); + src__core__hooked_service.HookedServiceEventDispatcher = class HookedServiceEventDispatcher extends core.Object { + get listeners() { + return this[listeners]; + } + set listeners(value) { + super.listeners = value; + } + [_close]() { + this[_ctrl][$forEach](dart.fn(c => c.close(), StreamControllerOfHookedServiceEventTovoid())); + this.listeners[$clear](); + } + [_emit](event) { + let t1; + if (dart.equals((t1 = event, t1 == null ? null : t1[_canceled]), true) || event == null || dart.test(this.listeners[$isEmpty])) return FutureOfHookedServiceEvent().value(event); + let f = FutureOfHookedServiceEvent().value(event); + for (let listener of this.listeners) { + f = f.then(src__core__hooked_service.HookedServiceEvent, dart.fn(event => { + if (dart.test(event[_canceled])) return event; + return async.Future.sync(dart.fn(() => listener(event), VoidTodynamic())).then(src__core__hooked_service.HookedServiceEvent, dart.fn(_ => event, dynamicToHookedServiceEvent())); + }, HookedServiceEventToFutureOrOfHookedServiceEvent())); + } + return f; + } + asStream() { + let ctrl = StreamControllerOfHookedServiceEvent().new(); + this[_ctrl][$add](ctrl); + this.listen(dart.bind(ctrl, 'add')); + return ctrl.stream; + } + listen(listener) { + this.listeners[$add](listener); + } + }; + (src__core__hooked_service.HookedServiceEventDispatcher.new = function() { + this[_ctrl] = JSArrayOfStreamControllerOfHookedServiceEvent().of([]); + this[listeners] = JSArrayOfHookedServiceEventTodynamic().of([]); + ; + }).prototype = src__core__hooked_service.HookedServiceEventDispatcher.prototype; + dart.addTypeTests(src__core__hooked_service.HookedServiceEventDispatcher); + const listeners = Symbol("HookedServiceEventDispatcher.listeners"); + dart.setMethodSignature(src__core__hooked_service.HookedServiceEventDispatcher, () => ({ + __proto__: dart.getMethods(src__core__hooked_service.HookedServiceEventDispatcher.__proto__), + [_close]: dart.fnType(dart.void, []), + [_emit]: dart.fnType(async.Future$(src__core__hooked_service.HookedServiceEvent), [src__core__hooked_service.HookedServiceEvent]), + asStream: dart.fnType(async.Stream$(src__core__hooked_service.HookedServiceEvent), []), + listen: dart.fnType(dart.void, [dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent])]) + })); + dart.setFieldSignature(src__core__hooked_service.HookedServiceEventDispatcher, () => ({ + __proto__: dart.getFields(src__core__hooked_service.HookedServiceEventDispatcher.__proto__), + [_ctrl]: dart.finalFieldType(core.List$(async.StreamController$(src__core__hooked_service.HookedServiceEvent))), + listeners: dart.finalFieldType(core.List$(dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent]))) + })); + src__core__hooked_service.HookedServiceEventListener = dart.typedef('HookedServiceEventListener', () => HookedServiceEventTodynamic()); + const _matchesId = Symbol('_matchesId'); + const _foldStringDynamic = Symbol('_foldStringDynamic'); + src__core__map_service.MapService = class MapService extends src__core__service.Service { + get allowRemoveAll() { + return this[allowRemoveAll$]; + } + set allowRemoveAll(value) { + super.allowRemoveAll = value; + } + get allowQuery() { + return this[allowQuery$]; + } + set allowQuery(value) { + super.allowQuery = value; + } + get autoIdAndDateFields() { + return this[autoIdAndDateFields$]; + } + set autoIdAndDateFields(value) { + super.autoIdAndDateFields = value; + } + get autoSnakeCaseNames() { + return this[autoSnakeCaseNames$]; + } + set autoSnakeCaseNames(value) { + super.autoSnakeCaseNames = value; + } + get items() { + return this[items]; + } + set items(value) { + super.items = value; + } + get createdAtKey() { + return dart.equals(this.autoSnakeCaseNames, false) ? "createdAt" : "created_at"; + } + get updatedAtKey() { + return dart.equals(this.autoSnakeCaseNames, false) ? "updatedAt" : "updated_at"; + } + [_matchesId](id) { + return dart.fn(item => { + let t1; + if (item[$_get]("id") == null) + return false; + else if (!dart.equals(this.autoIdAndDateFields, false)) + return dart.equals(item[$_get]("id"), (t1 = id, t1 == null ? null : dart.toString(t1))); + else + return dart.equals(item[$_get]("id"), id); + }, MapTobool()); + } + index(params) { + if (params === void 0) params = null; + if (dart.equals(this.allowQuery, false) || params == null || !core.Map.is(params[$_get]("query"))) + return FutureOfList().value(this.items); + else { + let query = core.Map._check(params[$_get]("query")); + return FutureOfList().value(this.items[$where](dart.fn(item => { + for (let key of query[$keys]) { + if (!dart.test(item[$containsKey](key))) + return false; + else if (!dart.equals(item[$_get](key), query[$_get](key))) return false; + } + return true; + }, MapOfString$dynamicTobool()))[$toList]()); + } + } + read(id, params) { + if (params === void 0) params = null; + return FutureOfMap().value(this.items[$firstWhere](this[_matchesId](id), {orElse: dart.fn(() => dart.throw(angel_http_exception.AngelHttpException.notFound({message: "No record found for ID " + dart.str(id)})), VoidTobottom())})); + } + create(data, params) { + let t1; + if (params === void 0) params = null; + if (!core.Map.is(data)) dart.throw(angel_http_exception.AngelHttpException.badRequest({message: "MapService does not support `create` with " + dart.str(dart.runtimeType(data)) + "."})); + let now = new core.DateTime.now().toIso8601String(); + let result = core.Map.as(data); + if (dart.equals(this.autoIdAndDateFields, true)) { + t1 = result; + t1[$_set]("id", dart.toString(this.items[$length])); + t1[$_set](dart.equals(this.autoSnakeCaseNames, false) ? "createdAt" : "created_at", now); + t1[$_set](dart.equals(this.autoSnakeCaseNames, false) ? "updatedAt" : "updated_at", now); + t1; + } + this.items[$add](this[_foldStringDynamic](result)); + return FutureOfMap().value(result); + } + [_foldStringDynamic](map) { + return map == null ? null : map[$keys][$fold](MapOfString$dynamic(), new (IdentityMapOfString$dynamic()).new(), dart.fn((out, k) => { + let t1; + t1 = out; + t1[$_set](dart.toString(k), map[$_get](k)); + return t1; + }, MapOfString$dynamicAnddynamicToMapOfString$dynamic())); + } + modify(id, data, params) { + if (params === void 0) params = null; + if (!core.Map.is(data)) dart.throw(angel_http_exception.AngelHttpException.badRequest({message: "MapService does not support `modify` with " + dart.str(dart.runtimeType(data)) + "."})); + if (!dart.test(this.items[$any](this[_matchesId](id)))) return this.create(data, params); + return this.read(id).then(core.Map, dart.fn(item => { + let t1, t1$; + let result = (t1 = item, t1[$addAll](core.Map.as(data)), t1); + if (dart.equals(this.autoIdAndDateFields, true)) { + t1$ = result; + t1$[$_set](dart.equals(this.autoSnakeCaseNames, false) ? "updatedAt" : "updated_at", new core.DateTime.now().toIso8601String()); + t1$; + } + return FutureOfMap().value(result); + }, MapToFutureOfMap())); + } + update(id, data, params) { + if (params === void 0) params = null; + if (!core.Map.is(data)) dart.throw(angel_http_exception.AngelHttpException.badRequest({message: "MapService does not support `update` with " + dart.str(dart.runtimeType(data)) + "."})); + if (!dart.test(this.items[$any](this[_matchesId](id)))) return this.create(data, params); + return this.read(id).then(core.Map, dart.fn(old => { + let t2, t1; + if (!dart.test(this.items[$remove](old))) dart.throw(angel_http_exception.AngelHttpException.notFound({message: "No record found for ID " + dart.str(id)})); + let result = core.Map.as(data); + if (dart.equals(this.autoIdAndDateFields, true)) { + t1 = result; + t1[$_set]("id", (t2 = id, t2 == null ? null : dart.toString(t2))); + t1[$_set](dart.equals(this.autoSnakeCaseNames, false) ? "createdAt" : "created_at", old[$_get](dart.equals(this.autoSnakeCaseNames, false) ? "createdAt" : "created_at")); + t1[$_set](dart.equals(this.autoSnakeCaseNames, false) ? "updatedAt" : "updated_at", new core.DateTime.now().toIso8601String()); + t1; + } + this.items[$add](this[_foldStringDynamic](result)); + return FutureOfMap().value(result); + }, MapToFutureOfMap())); + } + remove(id, params) { + let t1; + if (params === void 0) params = null; + if (id == null || dart.equals(id, "null") && (dart.equals(this.allowRemoveAll, true) || !dart.equals((t1 = params, t1 == null ? null : t1[$containsKey]("provider")), true))) { + this.items[$clear](); + return FutureOfMap().value(new _js_helper.LinkedMap.new()); + } + return this.read(id, params).then(core.Map, dart.fn(result => { + if (dart.test(this.items[$remove](result))) + return result; + else + dart.throw(angel_http_exception.AngelHttpException.notFound({message: "No record found for ID " + dart.str(id)})); + }, MapToMap())); + } + }; + (src__core__map_service.MapService.new = function(opts) { + let allowRemoveAll = opts && 'allowRemoveAll' in opts ? opts.allowRemoveAll : false; + let allowQuery = opts && 'allowQuery' in opts ? opts.allowQuery : true; + let autoIdAndDateFields = opts && 'autoIdAndDateFields' in opts ? opts.autoIdAndDateFields : true; + let autoSnakeCaseNames = opts && 'autoSnakeCaseNames' in opts ? opts.autoSnakeCaseNames : true; + this[items] = JSArrayOfMapOfString$dynamic().of([]); + this[allowRemoveAll$] = allowRemoveAll; + this[allowQuery$] = allowQuery; + this[autoIdAndDateFields$] = autoIdAndDateFields; + this[autoSnakeCaseNames$] = autoSnakeCaseNames; + src__core__map_service.MapService.__proto__.new.call(this); + ; + }).prototype = src__core__map_service.MapService.prototype; + dart.addTypeTests(src__core__map_service.MapService); + const allowRemoveAll$ = Symbol("MapService.allowRemoveAll"); + const allowQuery$ = Symbol("MapService.allowQuery"); + const autoIdAndDateFields$ = Symbol("MapService.autoIdAndDateFields"); + const autoSnakeCaseNames$ = Symbol("MapService.autoSnakeCaseNames"); + const items = Symbol("MapService.items"); + dart.setMethodSignature(src__core__map_service.MapService, () => ({ + __proto__: dart.getMethods(src__core__map_service.MapService.__proto__), + [_matchesId]: dart.fnType(dart.fnType(core.bool, [core.Map]), [dart.dynamic]), + index: dart.fnType(async.Future$(core.List), [], [core.Map]), + read: dart.fnType(async.Future$(core.Map), [dart.dynamic], [core.Map]), + create: dart.fnType(async.Future$(core.Map), [dart.dynamic], [core.Map]), + [_foldStringDynamic]: dart.fnType(core.Map$(core.String, dart.dynamic), [core.Map]), + modify: dart.fnType(async.Future$(core.Map), [dart.dynamic, dart.dynamic], [core.Map]), + update: dart.fnType(async.Future$(core.Map), [dart.dynamic, dart.dynamic], [core.Map]), + remove: dart.fnType(async.Future$(core.Map), [dart.dynamic], [core.Map]) + })); + dart.setGetterSignature(src__core__map_service.MapService, () => ({ + __proto__: dart.getGetters(src__core__map_service.MapService.__proto__), + createdAtKey: core.String, + updatedAtKey: core.String + })); + dart.setFieldSignature(src__core__map_service.MapService, () => ({ + __proto__: dart.getFields(src__core__map_service.MapService.__proto__), + allowRemoveAll: dart.finalFieldType(core.bool), + allowQuery: dart.finalFieldType(core.bool), + autoIdAndDateFields: dart.finalFieldType(core.bool), + autoSnakeCaseNames: dart.finalFieldType(core.bool), + items: dart.finalFieldType(core.List$(core.Map$(core.String, dart.dynamic))) + })); + src__core__metadata.Middleware = class Middleware extends core.Object { + get handlers() { + return this[handlers$]; + } + set handlers(value) { + super.handlers = value; + } + }; + (src__core__metadata.Middleware.new = function(handlers) { + this[handlers$] = handlers; + ; + }).prototype = src__core__metadata.Middleware.prototype; + dart.addTypeTests(src__core__metadata.Middleware); + const handlers$ = Symbol("Middleware.handlers"); + dart.setFieldSignature(src__core__metadata.Middleware, () => ({ + __proto__: dart.getFields(src__core__metadata.Middleware.__proto__), + handlers: dart.finalFieldType(core.Iterable$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext]))) + })); + let const$4; + let const$5; + src__core__metadata.Hooks = class Hooks extends core.Object { + get before() { + return this[before$]; + } + set before(value) { + super.before = value; + } + get after() { + return this[after$]; + } + set after(value) { + super.after = value; + } + }; + (src__core__metadata.Hooks.new = function(opts) { + let before = opts && 'before' in opts ? opts.before : const$4 || (const$4 = dart.constList([], HookedServiceEventTodynamic())); + let after = opts && 'after' in opts ? opts.after : const$5 || (const$5 = dart.constList([], HookedServiceEventTodynamic())); + this[before$] = before; + this[after$] = after; + ; + }).prototype = src__core__metadata.Hooks.prototype; + dart.addTypeTests(src__core__metadata.Hooks); + const before$ = Symbol("Hooks.before"); + const after$ = Symbol("Hooks.after"); + dart.setFieldSignature(src__core__metadata.Hooks, () => ({ + __proto__: dart.getFields(src__core__metadata.Hooks.__proto__), + before: dart.finalFieldType(core.List$(dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent]))), + after: dart.finalFieldType(core.List$(dart.fnType(dart.dynamic, [src__core__hooked_service.HookedServiceEvent]))) + })); + let const$6; + let const$7; + src__core__metadata.Expose = class Expose extends core.Object { + get method() { + return this[method$]; + } + set method(value) { + super.method = value; + } + get path() { + return this[path$0]; + } + set path(value) { + super.path = value; + } + get middleware() { + return this[middleware$]; + } + set middleware(value) { + super.middleware = value; + } + get as() { + return this[as$]; + } + set as(value) { + super.as = value; + } + get allowNull() { + return this[allowNull$]; + } + set allowNull(value) { + super.allowNull = value; + } + }; + (src__core__metadata.Expose.new = function(path, opts) { + let method = opts && 'method' in opts ? opts.method : "GET"; + let middleware = opts && 'middleware' in opts ? opts.middleware : const$6 || (const$6 = dart.constList([], RequestContextAndResponseContextToFutureOr())); + let as = opts && 'as' in opts ? opts.as : null; + let allowNull = opts && 'allowNull' in opts ? opts.allowNull : const$7 || (const$7 = dart.constList([], core.String)); + this[path$0] = path; + this[method$] = method; + this[middleware$] = middleware; + this[as$] = as; + this[allowNull$] = allowNull; + ; + }).prototype = src__core__metadata.Expose.prototype; + dart.addTypeTests(src__core__metadata.Expose); + const method$ = Symbol("Expose.method"); + const path$0 = Symbol("Expose.path"); + const middleware$ = Symbol("Expose.middleware"); + const as$ = Symbol("Expose.as"); + const allowNull$ = Symbol("Expose.allowNull"); + dart.setFieldSignature(src__core__metadata.Expose, () => ({ + __proto__: dart.getFields(src__core__metadata.Expose.__proto__), + method: dart.finalFieldType(core.String), + path: dart.finalFieldType(core.String), + middleware: dart.finalFieldType(core.Iterable$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext]))), + as: dart.finalFieldType(core.String), + allowNull: dart.finalFieldType(core.List$(core.String)) + })); + src__core__metadata.Parameter = class Parameter extends core.Object { + get cookie() { + return this[cookie$]; + } + set cookie(value) { + super.cookie = value; + } + get header() { + return this[header$]; + } + set header(value) { + super.header = value; + } + get session() { + return this[session$]; + } + set session(value) { + super.session = value; + } + get query() { + return this[query$]; + } + set query(value) { + super.query = value; + } + get match() { + return this[match$]; + } + set match(value) { + super.match = value; + } + get defaultValue() { + return this[defaultValue$]; + } + set defaultValue(value) { + super.defaultValue = value; + } + get required() { + return this[required$]; + } + set required(value) { + super.required = value; + } + get error() { + let t1, t1$, t1$0, t1$1; + if (dart.equals((t1 = this.cookie, t1 == null ? null : t1[$isNotEmpty]), true)) return angel_http_exception.AngelHttpException.badRequest({message: "Missing required cookie \"" + dart.str(this.cookie) + "\"."}); + if (dart.equals((t1$ = this.header, t1$ == null ? null : t1$[$isNotEmpty]), true)) return angel_http_exception.AngelHttpException.badRequest({message: "Missing required header \"" + dart.str(this.header) + "\"."}); + if (dart.equals((t1$0 = this.query, t1$0 == null ? null : t1$0[$isNotEmpty]), true)) return angel_http_exception.AngelHttpException.badRequest({message: "Missing required query parameter \"" + dart.str(this.query) + "\"."}); + if (dart.equals((t1$1 = this.session, t1$1 == null ? null : t1$1[$isNotEmpty]), true)) return new core.StateError.new("Session does not contain required key \"" + dart.str(this.session) + "\"."); + } + getValue(req) { + let t1, t1$, t1$0, t1$1, t1$2, t1$3, t1$4, t1$5, t1$6; + if (dart.equals((t1 = this.cookie, t1 == null ? null : t1[$isNotEmpty]), true)) { + t1$0 = (t1$ = req.cookies[$firstWhere](dart.fn(c => c.name == this.cookie, CookieTobool())), t1$ == null ? null : t1$.value); + return t1$0 == null ? this.defaultValue : t1$0; + } + if (dart.equals((t1$1 = this.header, t1$1 == null ? null : t1$1[$isNotEmpty]), true)) { + t1$2 = req.headers.value(this.header); + return t1$2 == null ? this.defaultValue : t1$2; + } + if (dart.equals((t1$3 = this.session, t1$3 == null ? null : t1$3[$isNotEmpty]), true)) { + t1$4 = req.session[$_get](this.session); + return t1$4 == null ? this.defaultValue : t1$4; + } + if (dart.equals((t1$5 = this.query, t1$5 == null ? null : t1$5[$isNotEmpty]), true)) { + t1$6 = req.uri.queryParameters[$_get](this.query); + return t1$6 == null ? this.defaultValue : t1$6; + } + return this.defaultValue; + } + }; + (src__core__metadata.Parameter.new = function(opts) { + let cookie = opts && 'cookie' in opts ? opts.cookie : null; + let query = opts && 'query' in opts ? opts.query : null; + let header = opts && 'header' in opts ? opts.header : null; + let session = opts && 'session' in opts ? opts.session : null; + let match = opts && 'match' in opts ? opts.match : null; + let defaultValue = opts && 'defaultValue' in opts ? opts.defaultValue : null; + let required = opts && 'required' in opts ? opts.required : null; + this[cookie$] = cookie; + this[query$] = query; + this[header$] = header; + this[session$] = session; + this[match$] = match; + this[defaultValue$] = defaultValue; + this[required$] = required; + ; + }).prototype = src__core__metadata.Parameter.prototype; + dart.addTypeTests(src__core__metadata.Parameter); + const cookie$ = Symbol("Parameter.cookie"); + const header$ = Symbol("Parameter.header"); + const session$ = Symbol("Parameter.session"); + const query$ = Symbol("Parameter.query"); + const match$ = Symbol("Parameter.match"); + const defaultValue$ = Symbol("Parameter.defaultValue"); + const required$ = Symbol("Parameter.required"); + dart.setMethodSignature(src__core__metadata.Parameter, () => ({ + __proto__: dart.getMethods(src__core__metadata.Parameter.__proto__), + getValue: dart.fnType(dart.dynamic, [src__core__request_context.RequestContext]) + })); + dart.setGetterSignature(src__core__metadata.Parameter, () => ({ + __proto__: dart.getGetters(src__core__metadata.Parameter.__proto__), + error: dart.dynamic + })); + dart.setFieldSignature(src__core__metadata.Parameter, () => ({ + __proto__: dart.getFields(src__core__metadata.Parameter.__proto__), + cookie: dart.finalFieldType(core.String), + header: dart.finalFieldType(core.String), + session: dart.finalFieldType(core.String), + query: dart.finalFieldType(core.String), + match: dart.finalFieldType(dart.dynamic), + defaultValue: dart.finalFieldType(dart.dynamic), + required: dart.finalFieldType(core.bool) + })); + src__core__metadata.Header = class Header extends src__core__metadata.Parameter {}; + (src__core__metadata.Header.new = function(header, opts) { + let match = opts && 'match' in opts ? opts.match : null; + let defaultValue = opts && 'defaultValue' in opts ? opts.defaultValue : null; + let required = opts && 'required' in opts ? opts.required : true; + src__core__metadata.Header.__proto__.new.call(this, {header: header, match: match, defaultValue: defaultValue, required: required}); + ; + }).prototype = src__core__metadata.Header.prototype; + dart.addTypeTests(src__core__metadata.Header); + src__core__metadata.Session = class Session extends src__core__metadata.Parameter {}; + (src__core__metadata.Session.new = function(session, opts) { + let match = opts && 'match' in opts ? opts.match : null; + let defaultValue = opts && 'defaultValue' in opts ? opts.defaultValue : null; + let required = opts && 'required' in opts ? opts.required : true; + src__core__metadata.Session.__proto__.new.call(this, {session: session, match: match, defaultValue: defaultValue, required: required}); + ; + }).prototype = src__core__metadata.Session.prototype; + dart.addTypeTests(src__core__metadata.Session); + src__core__metadata.Query = class Query extends src__core__metadata.Parameter {}; + (src__core__metadata.Query.new = function(query, opts) { + let match = opts && 'match' in opts ? opts.match : null; + let defaultValue = opts && 'defaultValue' in opts ? opts.defaultValue : null; + let required = opts && 'required' in opts ? opts.required : true; + src__core__metadata.Query.__proto__.new.call(this, {query: query, match: match, defaultValue: defaultValue, required: required}); + ; + }).prototype = src__core__metadata.Query.prototype; + dart.addTypeTests(src__core__metadata.Query); + src__core__metadata.CookieValue = class CookieValue extends src__core__metadata.Parameter {}; + (src__core__metadata.CookieValue.new = function(cookie, opts) { + let match = opts && 'match' in opts ? opts.match : null; + let defaultValue = opts && 'defaultValue' in opts ? opts.defaultValue : null; + let required = opts && 'required' in opts ? opts.required : true; + src__core__metadata.CookieValue.__proto__.new.call(this, {cookie: cookie, match: match, defaultValue: defaultValue, required: required}); + ; + }).prototype = src__core__metadata.CookieValue.prototype; + dart.addTypeTests(src__core__metadata.CookieValue); + let const$8; + let const$9; + let const$10; + let const$11; + src__core__request_context.InjectionRequest = class InjectionRequest extends core.Object { + get named() { + return this[named$]; + } + set named(value) { + super.named = value; + } + get required() { + return this[required$0]; + } + set required(value) { + super.required = value; + } + get optional() { + return this[optional$]; + } + set optional(value) { + super.optional = value; + } + get parameters() { + return this[parameters$]; + } + set parameters(value) { + super.parameters = value; + } + }; + (src__core__request_context.InjectionRequest.constant = function(opts) { + let named = opts && 'named' in opts ? opts.named : const$8 || (const$8 = dart.constMap(core.String, core.Type, [])); + let required = opts && 'required' in opts ? opts.required : const$9 || (const$9 = dart.constList([], dart.dynamic)); + let optional = opts && 'optional' in opts ? opts.optional : const$10 || (const$10 = dart.constList([], core.String)); + let parameters = opts && 'parameters' in opts ? opts.parameters : const$11 || (const$11 = dart.constMap(core.String, src__core__metadata.Parameter, [])); + this[named$] = named; + this[required$0] = required; + this[optional$] = optional; + this[parameters$] = parameters; + ; + }).prototype = src__core__request_context.InjectionRequest.prototype; + (src__core__request_context.InjectionRequest.new = function() { + this[named$] = new (IdentityMapOfString$Type()).new(); + this[required$0] = []; + this[optional$] = JSArrayOfString().of([]); + this[parameters$] = new (IdentityMapOfString$Parameter()).new(); + ; + }).prototype = src__core__request_context.InjectionRequest.prototype; + dart.addTypeTests(src__core__request_context.InjectionRequest); + const named$ = Symbol("InjectionRequest.named"); + const required$0 = Symbol("InjectionRequest.required"); + const optional$ = Symbol("InjectionRequest.optional"); + const parameters$ = Symbol("InjectionRequest.parameters"); + dart.setFieldSignature(src__core__request_context.InjectionRequest, () => ({ + __proto__: dart.getFields(src__core__request_context.InjectionRequest.__proto__), + named: dart.finalFieldType(core.Map$(core.String, core.Type)), + required: dart.finalFieldType(core.List), + optional: dart.finalFieldType(core.List$(core.String)), + parameters: dart.finalFieldType(core.Map$(core.String, src__core__metadata.Parameter)) + })); + let const$12; + src__core__request_context.ioc = function(handler, opts) { + let optional = opts && 'optional' in opts ? opts.optional : const$12 || (const$12 = dart.constList([], core.String)); + let injection = null; + let contained = null; + return dart.fn((req, res) => { + let t1; + if (injection == null) { + injection = src__core__request_context.preInject(handler, req.app.container.reflector); + injection.optional[$addAll]((t1 = optional, t1 == null ? JSArrayOfString().of([]) : t1)); + contained = src__core__request_context.handleContained(handler, injection); + } + return req.app.executeHandler(contained, req, res); + }, RequestContextAndResponseContextToFutureOfbool()); + }; + src__core__request_context.resolveInjection = function(requirement, injection, req, res, throwOnUnresolved) { + let propFromApp = null; + if (dart.equals(requirement, dart.wrapType(src__core__request_context.RequestContext))) { + return req; + } else if (dart.equals(requirement, dart.wrapType(src__core__response_context.ResponseContext))) { + return res; + } else if (typeof requirement == 'string' && dart.test(injection.parameters[$containsKey](requirement))) { + let param = injection.parameters[$_get](requirement); + let value = param.getValue(req); + if (value == null && !dart.equals(param.required, false)) dart.throw(param.error); + return value; + } else if (typeof requirement == 'string') { + if (dart.test(req.params[$containsKey](requirement))) { + return req.params[$_get](requirement); + } else if ((propFromApp = req.app.findProperty(requirement)) != null) + return propFromApp; + else if (dart.test(injection.optional[$contains](requirement))) + return null; + else if (dart.test(throwOnUnresolved)) { + dart.throw(new core.ArgumentError.new("Cannot resolve parameter '" + dart.str(requirement) + "' within handler.")); + } + } else if (core.List.is(requirement) && requirement[$length] === 2 && typeof requirement[$first] == 'string' && core.Type.is(requirement[$last])) { + let key = core.String._check(requirement[$first]); + let type = core.Type._check(requirement[$last]); + if (dart.test(req.params[$containsKey](key)) || dart.test(req.app.configuration[$containsKey](key)) || dart.test(src__core__request_context._primitiveTypes[$contains](type))) { + return src__core__request_context.resolveInjection(key, injection, req, res, throwOnUnresolved); + } else + return src__core__request_context.resolveInjection(type, injection, req, res, throwOnUnresolved); + } else if (core.Type.is(requirement) && !dart.equals(requirement, dart.wrapType(dart.dynamic))) { + return req.app.container.make(dart.dynamic, requirement); + } else if (dart.test(throwOnUnresolved)) { + dart.throw(new core.ArgumentError.new(dart.str(requirement) + " cannot be injected into a request handler.")); + } + }; + src__core__request_context.suitableForInjection = function(req, res, injection) { + return injection.parameters[$values][$any](dart.fn(p => { + if (p.match == null) return false; + let value = p.getValue(req); + return dart.equals(value, p.match); + }, ParameterTobool())); + }; + src__core__request_context.handleContained = function(handler, injection) { + return dart.fn((req, res) => { + if (dart.test(injection.parameters[$isNotEmpty]) && dart.test(injection.parameters[$values][$any](dart.fn(p => p.match != null, ParameterTobool()))) && !dart.test(src__core__request_context.suitableForInjection(req, res, injection))) return async.Future.value(true); + let args = []; + let named = new (LinkedMapOfSymbol$dynamic()).new(); + args[$addAll](injection.required[$map](dart.dynamic, dart.fn(r => src__core__request_context.resolveInjection(r, injection, req, res, true), dynamicTodynamic()))); + injection.named[$forEach](dart.fn((k, v) => { + let name = new _internal.Symbol.new(k); + named[$_set](name, src__core__request_context.resolveInjection(JSArrayOfObject().of([k, v]), injection, req, res, false)); + }, StringAndTypeToNull())); + return core.Function.apply(handler, args, named); + }, RequestContextAndResponseContextTodynamic()); + }; + src__core__request_context.preInject = function(handler, reflector) { + let t1; + let injection = new src__core__request_context.InjectionRequest.new(); + let closureMirror = reflector.reflectFunction(handler); + if (dart.test(closureMirror.parameters[$isEmpty])) return injection; + for (let parameter of closureMirror.parameters) { + let name = parameter.name; + let type = parameter.type.reflectedType; + let _Parameter = reflector.reflectType(dart.wrapType(src__core__metadata.Parameter)); + let p = src__core__metadata.Parameter.as((t1 = parameter.annotations[$firstWhere](dart.fn(m => m.type.isAssignableTo(_Parameter), ReflectedInstanceTobool()), {orElse: dart.fn(() => null, VoidToNull())}), t1 == null ? null : t1.reflectee)); + if (p != null) { + injection.parameters[$_set](name, new src__core__metadata.Parameter.new({cookie: p.cookie, header: p.header, query: p.query, session: p.session, match: p.match, defaultValue: p.defaultValue, required: dart.test(parameter.isNamed) ? false : !dart.equals(p.required, false)})); + } + if (!dart.test(parameter.isNamed)) { + if (!dart.test(parameter.isRequired)) injection.optional[$add](name); + if (dart.equals(type, dart.wrapType(src__core__request_context.RequestContext)) || dart.equals(type, dart.wrapType(src__core__response_context.ResponseContext))) { + injection.required[$add](type); + } else if (name === "req") { + injection.required[$add](dart.wrapType(src__core__request_context.RequestContext)); + } else if (name === "res") { + injection.required[$add](dart.wrapType(src__core__response_context.ResponseContext)); + } else if (dart.equals(type, dart.wrapType(dart.dynamic))) { + injection.required[$add](name); + } else { + injection.required[$add](JSArrayOfObject().of([name, type])); + } + } else { + injection.named[$_set](name, type); + } + } + return injection; + }; + dart.defineLazy(src__core__request_context, { + /*src__core__request_context._primitiveTypes*/get _primitiveTypes() { + return dart.constList([dart.wrapType(core.String), dart.wrapType(core.int), dart.wrapType(core.num), dart.wrapType(core.double), dart.wrapType(core.Null)], core.Type); + } + }); + src__core__response_context.LockableBytesBuilder = class LockableBytesBuilder extends io.BytesBuilder { + static new() { + return new src__core__response_context._LockableBytesBuilderImpl.new(); + } + }; + dart.addTypeTests(src__core__response_context.LockableBytesBuilder); + const _buf = Symbol('_buf'); + const _closed = Symbol('_closed'); + const _deny = Symbol('_deny'); + src__core__response_context._LockableBytesBuilderImpl = class _LockableBytesBuilderImpl extends core.Object { + [_deny]() { + return new core.StateError.new("Cannot modified a closed response's buffer."); + } + lock() { + this[_closed] = true; + } + add(bytes) { + if (dart.test(this[_closed])) + dart.throw(this[_deny]()); + else + this[_buf].add(bytes); + } + addByte(byte) { + if (dart.test(this[_closed])) + dart.throw(this[_deny]()); + else + this[_buf].addByte(byte); + } + clear() { + this[_buf].clear(); + } + get isEmpty() { + return this[_buf].isEmpty; + } + get isNotEmpty() { + return this[_buf].isNotEmpty; + } + get length() { + return this[_buf].length; + } + takeBytes() { + return this[_buf].takeBytes(); + } + toBytes() { + return this[_buf].toBytes(); + } + }; + (src__core__response_context._LockableBytesBuilderImpl.new = function() { + this[_buf] = io.BytesBuilder.new({copy: false}); + this[_closed] = false; + ; + }).prototype = src__core__response_context._LockableBytesBuilderImpl.prototype; + dart.addTypeTests(src__core__response_context._LockableBytesBuilderImpl); + src__core__response_context._LockableBytesBuilderImpl[dart.implements] = () => [src__core__response_context.LockableBytesBuilder]; + dart.setMethodSignature(src__core__response_context._LockableBytesBuilderImpl, () => ({ + __proto__: dart.getMethods(src__core__response_context._LockableBytesBuilderImpl.__proto__), + [_deny]: dart.fnType(core.StateError, []), + lock: dart.fnType(dart.void, []), + add: dart.fnType(dart.void, [core.List$(core.int)]), + addByte: dart.fnType(dart.void, [core.int]), + clear: dart.fnType(dart.void, []), + takeBytes: dart.fnType(core.List$(core.int), []), + toBytes: dart.fnType(core.List$(core.int), []) + })); + dart.setGetterSignature(src__core__response_context._LockableBytesBuilderImpl, () => ({ + __proto__: dart.getGetters(src__core__response_context._LockableBytesBuilderImpl.__proto__), + isEmpty: core.bool, + isNotEmpty: core.bool, + length: core.int + })); + dart.setFieldSignature(src__core__response_context._LockableBytesBuilderImpl, () => ({ + __proto__: dart.getFields(src__core__response_context._LockableBytesBuilderImpl.__proto__), + [_buf]: dart.finalFieldType(io.BytesBuilder), + [_closed]: dart.fieldType(core.bool) + })); + dart.defineLazy(src__core__response_context, { + /*src__core__response_context._straySlashes*/get _straySlashes() { + return core.RegExp.new("(^/+)|(/+$)"); + } + }); + src__core__routable.RequestHandler = dart.typedef('RequestHandler', () => RequestContextAndResponseContextToFutureOr()); + src__core__routable.waterfall = function(handlers) { + return dart.fn((req, res) => { + let runPipeline = null; + for (let handler of handlers) { + if (handler == null) break; + if (runPipeline == null) + runPipeline = dart.fn(() => async.Future.sync(dart.fn(() => handler(req, res), VoidToFutureOr())), VoidToFuture()); + else { + let current = runPipeline; + runPipeline = dart.fn(() => current().then(dart.dynamic, dart.fn(result => !dart.test(res.isOpen) ? async.Future.value(result) : req.app.executeHandler(handler, req, res), dynamicToFuture())), VoidToFuture()); + } + } + runPipeline == null ? runPipeline = dart.fn(() => async.Future.value(), VoidToFuture()) : null; + return runPipeline(); + }, RequestContextAndResponseContextToFuture()); + }; + dart.defineLazy(src__core__routable, { + /*src__core__routable._straySlashes*/get _straySlashes() { + return core.RegExp.new("(^/+)|(/+$)"); + } + }); + let const$13; + const _children = Symbol('_children'); + const _flattened = Symbol('_flattened'); + const _http$ = Symbol('_http'); + const _isProduction = Symbol('_isProduction'); + const _parent = Symbol('_parent'); + const _preContained = Symbol('_preContained'); + const _controllers = Symbol('_controllers'); + let const$14; + src__core__server.Angel = class Angel extends src__core__routable.Routable { + get handlerCache() { + return this[handlerCache]; + } + set handlerCache(value) { + super.handlerCache = value; + } + get encoders() { + return this[encoders]; + } + set encoders(value) { + super.encoders = value; + } + get serializer() { + return this[serializer$]; + } + set serializer(value) { + this[serializer$] = value; + } + get allowMethodOverrides() { + return this[allowMethodOverrides$]; + } + set allowMethodOverrides(value) { + this[allowMethodOverrides$] = value; + } + get logger() { + return this[logger$]; + } + set logger(value) { + this[logger$] = value; + } + get startupHooks() { + return this[startupHooks]; + } + set startupHooks(value) { + super.startupHooks = value; + } + get shutdownHooks() { + return this[shutdownHooks]; + } + set shutdownHooks(value) { + super.shutdownHooks = value; + } + get responseFinalizers() { + return this[responseFinalizers]; + } + set responseFinalizers(value) { + super.responseFinalizers = value; + } + get configuration() { + return this[configuration$]; + } + set configuration(value) { + super.configuration = value; + } + get eagerParseRequestBodies() { + return this[eagerParseRequestBodies$]; + } + set eagerParseRequestBodies(value) { + this[eagerParseRequestBodies$] = value; + } + get keepRawRequestBuffers() { + return this[keepRawRequestBuffers$]; + } + set keepRawRequestBuffers(value) { + this[keepRawRequestBuffers$] = value; + } + get viewGenerator() { + return this[viewGenerator$]; + } + set viewGenerator(value) { + this[viewGenerator$] = value; + } + get errorHandler() { + return this[errorHandler]; + } + set errorHandler(value) { + this[errorHandler] = value; + } + get preContained() { + return this[_preContained]; + } + get optimizedRouter() { + let t1; + t1 = this[_flattened]; + return t1 == null ? this : t1; + } + get children() { + return ListOfAngel().unmodifiable(this[_children]); + } + get controllers() { + return this[_controllers]; + } + get isProduction() { + let t1; + t1 = this[_isProduction]; + return t1 == null ? this[_isProduction] = io.Platform.environment[$_get]("ANGEL_ENV") === "production" : t1; + } + get parent() { + return this[_parent]; + } + addRoute(method, path, handler, opts) { + let t1, t1$, t1$0; + RequestContextAndResponseContextToFutureOr()._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : const$14 || (const$14 = dart.constList([], RequestContextAndResponseContextToFutureOr())); + IterableOfRequestContextAndResponseContextToFutureOr()._check(middleware); + if (this[_flattened] != null) { + t1 = this.logger; + t1 == null ? null : t1.warning("WARNING: You added a route (" + dart.str(method) + " " + dart.str(path) + ") to the router, after it had been optimized."); + t1$ = this.logger; + t1$ == null ? null : t1$.warning("This route will be ignored, and no requests will ever reach it."); + } + return super.addRoute(method, path, handler, {middleware: (t1$0 = middleware, t1$0 == null ? JSArrayOfRequestContextAndResponseContextToFutureOr().of([]) : t1$0)}); + } + mount(path, router) { + let t1, t1$; + RouterOfRequestContextAndResponseContextToFutureOr()._check(router); + if (this[_flattened] != null) { + t1 = this.logger; + t1 == null ? null : t1.warning("WARNING: You added mounted a child router (" + dart.str(path) + ") on the router, after it had been optimized."); + t1$ = this.logger; + t1$ == null ? null : t1$.warning("This route will be ignored, and no requests will ever reach it."); + } + if (src__core__server.Angel.is(router)) { + router[_parent] = this; + this[_children][$add](router); + } + return super.mount(dart.toString(path), router); + } + bootstrapContainer() { + if (!dart.equals(this[$runtimeType], dart.wrapType(src__core__server.Angel))) { + this.container.registerSingleton(src__core__server.Angel, this); + } + this.container.registerSingleton(src__core__server.Angel, this); + this.container.registerSingleton(src__core__routable.Routable, this); + this.container.registerSingleton(src__router.Router, this); + } + close() { + let t1, t1$; + async.Future.forEach(src__core__service.Service, this.services[$values], dart.fn(service => { + service.close(); + }, ServiceToNull())); + super.close(); + this.viewGenerator = src__core__server.Angel.noViewEngineConfigured; + this[_preContained][$clear](); + this.handlerCache[$clear](); + this.encoders[$clear](); + this[_children][$clear](); + this[_parent] = null; + this.logger = null; + this.startupHooks[$clear](); + this.shutdownHooks[$clear](); + this.responseFinalizers[$clear](); + this[_flattened] = null; + t1 = this[_http$]; + t1 == null ? null : t1.close(); + return async.Future.value((t1$ = this[_http$], t1$ == null ? null : t1$.httpServer)); + } + dumpTree(opts) { + let t1, t1$, t1$0, t1$1; + let callback = opts && 'callback' in opts ? opts.callback : null; + let header = opts && 'header' in opts ? opts.header : "Dumping route tree:"; + let tab = opts && 'tab' in opts ? opts.tab : " "; + let showMatchers = opts && 'showMatchers' in opts ? opts.showMatchers : false; + if (dart.test(this.isProduction)) { + this[_flattened] == null ? this[_flattened] = src__router.flatten(dart.dynamic, this) : null; + this[_flattened].dumpTree({callback: callback, header: dart.equals((t1 = header, t1 == null ? null : t1[$isNotEmpty]), true) ? header : dart.test(this.isProduction) ? "Dumping flattened route tree:" : "Dumping route tree:", tab: (t1$ = tab, t1$ == null ? " " : t1$)}); + } else { + super.dumpTree({callback: callback, header: dart.equals((t1$0 = header, t1$0 == null ? null : t1$0[$isNotEmpty]), true) ? header : dart.test(this.isProduction) ? "Dumping flattened route tree:" : "Dumping route tree:", tab: (t1$1 = tab, t1$1 == null ? " " : t1$1)}); + } + } + getHandlerResult(handler, req, res) { + if (RequestContextAndResponseContextToFutureOr().is(handler)) { + let result = handler(req, res); + return this.getHandlerResult(result, req, res); + } + if (async.Future.is(handler)) { + return handler.then(dart.dynamic, dart.fn(result => this.getHandlerResult(result, req, res), dynamicToFuture())); + } + if (core.Function.is(handler)) { + let result = this.runContained(handler, req, res); + return this.getHandlerResult(result, req, res); + } + if (async.Stream.is(handler)) { + return this.getHandlerResult(handler.toList(), req, res); + } + return async.Future.value(handler); + } + executeHandler(handler, req, res) { + return this.getHandlerResult(handler, req, res).then(core.bool, dart.fn(result => { + if (result == null) + return false; + else if (typeof result == 'boolean') { + return result; + } else if (result != null) { + return res.serialize(result); + } else + return res.isOpen; + }, dynamicTobool())); + } + findProperty(key) { + if (dart.test(this.configuration[$containsKey](key))) return this.configuration[$_get](key); + return this.parent != null ? this.parent.findProperty(key) : null; + } + optimizeForProduction(opts) { + let t1; + let force = opts && 'force' in opts ? opts.force : false; + if (dart.equals(this.isProduction, true) || dart.equals(force, true)) { + this[_isProduction] = true; + this[_flattened] == null ? this[_flattened] = src__router.flatten(dart.dynamic, this) : null; + t1 = this.logger; + t1 == null ? null : t1.config("Angel is running in production mode."); + } + } + runContained(handler, req, res) { + return async.Future.sync(dart.fn(() => { + if (dart.test(this[_preContained][$containsKey](handler))) { + return src__core__request_context.handleContained(handler, this[_preContained][$_get](handler))(req, res); + } + return this.runReflected(handler, req, res); + }, VoidToFutureOr())); + } + runReflected(handler, req, res) { + let t3, t2, t1; + let h = src__core__request_context.handleContained(handler, (t1 = this[_preContained], t2 = handler, t3 = src__core__request_context.preInject(handler, req.app.container.reflector), t1[$_set](t2, t3), t3)); + return async.Future.sync(dart.fn(() => h(req, res), VoidToFutureOr())); + } + configure(configurer) { + return async.Future.sync(dart.fn(() => configurer(this), VoidToFutureOr())); + } + fallback(handler) { + return this.all("*", handler); + } + use(path, service) { + let t1; + service.app = this; + t1 = super.use(path, service); + t1.app = this; + return t1; + } + }; + (src__core__server.Angel.new = function(opts) { + let reflector = opts && 'reflector' in opts ? opts.reflector : const$13 || (const$13 = dart.const(new src__empty__empty.EmptyReflector.new())); + let logger = opts && 'logger' in opts ? opts.logger : null; + let eagerParseRequestBodies = opts && 'eagerParseRequestBodies' in opts ? opts.eagerParseRequestBodies : false; + let allowMethodOverrides = opts && 'allowMethodOverrides' in opts ? opts.allowMethodOverrides : true; + let keepRawRequestBuffers = opts && 'keepRawRequestBuffers' in opts ? opts.keepRawRequestBuffers : false; + let serializer = opts && 'serializer' in opts ? opts.serializer : null; + let viewGenerator = opts && 'viewGenerator' in opts ? opts.viewGenerator : null; + this[_children] = JSArrayOfAngel().of([]); + this[handlerCache] = new (IdentityMapOfString$Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic()).new(); + this[_flattened] = null; + this[_http$] = null; + this[_isProduction] = null; + this[_parent] = null; + this[encoders] = new (IdentityMapOfString$ConverterOfListOfint$ListOfint()).new(); + this[_preContained] = new (LinkedMapOfdynamic$InjectionRequest()).new(); + this[_controllers] = new (LinkedMapOfPattern$Controller()).new(); + this[startupHooks] = JSArrayOfAngelToFutureOr().of([]); + this[shutdownHooks] = JSArrayOfAngelToFutureOr().of([]); + this[responseFinalizers] = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]); + this[configuration$] = new _js_helper.LinkedMap.new(); + this[viewGenerator$] = src__core__server.Angel.noViewEngineConfigured; + this[errorHandler] = dart.fn((e, req, res) => { + if (!dart.test(req.accepts("text/html", {strict: true})) && (dart.test(req.accepts("application/json")) || dart.test(req.accepts("application/javascript")))) { + res.json(e.toJson()); + return; + } + res.contentType = new src__media_type.MediaType.new("text", "html", new (IdentityMapOfString$String()).from(["charset", "utf8"])); + res.statusCode = e.statusCode; + res.write("" + dart.str(e.message) + ""); + res.write("

" + dart.str(e.message) + "

    "); + for (let error of e.errors) { + res.write("
  • " + dart.str(error) + "
  • "); + } + res.write("
"); + res.close(); + }, AngelHttpExceptionAndRequestContextAndResponseContextToNull()); + this[logger$] = logger; + this[eagerParseRequestBodies$] = eagerParseRequestBodies; + this[allowMethodOverrides$] = allowMethodOverrides; + this[keepRawRequestBuffers$] = keepRawRequestBuffers; + this[serializer$] = serializer; + this[viewGenerator$] = viewGenerator; + src__core__server.Angel.__proto__.new.call(this, reflector); + this.bootstrapContainer(); + this.viewGenerator == null ? this.viewGenerator = src__core__server.Angel.noViewEngineConfigured : null; + this.serializer == null ? this.serializer = dart.bind(convert.json, 'encode') : null; + }).prototype = src__core__server.Angel.prototype; + dart.addTypeTests(src__core__server.Angel); + const handlerCache = Symbol("Angel.handlerCache"); + const encoders = Symbol("Angel.encoders"); + const serializer$ = Symbol("Angel.serializer"); + const allowMethodOverrides$ = Symbol("Angel.allowMethodOverrides"); + const logger$ = Symbol("Angel.logger"); + const startupHooks = Symbol("Angel.startupHooks"); + const shutdownHooks = Symbol("Angel.shutdownHooks"); + const responseFinalizers = Symbol("Angel.responseFinalizers"); + const configuration$ = Symbol("Angel.configuration"); + const eagerParseRequestBodies$ = Symbol("Angel.eagerParseRequestBodies"); + const keepRawRequestBuffers$ = Symbol("Angel.keepRawRequestBuffers"); + const viewGenerator$ = Symbol("Angel.viewGenerator"); + const errorHandler = Symbol("Angel.errorHandler"); + dart.setMethodSignature(src__core__server.Angel, () => ({ + __proto__: dart.getMethods(src__core__server.Angel.__proto__), + bootstrapContainer: dart.fnType(dart.void, []), + close: dart.fnType(async.Future, []), + dumpTree: dart.fnType(dart.void, [], {callback: dart.fnType(dart.dynamic, [core.String]), header: core.String, showMatchers: core.bool, tab: core.String}), + getHandlerResult: dart.fnType(async.Future, [dart.dynamic, src__core__request_context.RequestContext, src__core__response_context.ResponseContext]), + executeHandler: dart.fnType(async.Future$(core.bool), [dart.dynamic, src__core__request_context.RequestContext, src__core__response_context.ResponseContext]), + findProperty: dart.fnType(dart.dynamic, [dart.dynamic]), + optimizeForProduction: dart.fnType(dart.void, [], {force: core.bool}), + runContained: dart.fnType(async.Future, [core.Function, src__core__request_context.RequestContext, src__core__response_context.ResponseContext]), + runReflected: dart.fnType(async.Future, [core.Function, src__core__request_context.RequestContext, src__core__response_context.ResponseContext]), + configure: dart.fnType(async.Future, [dart.fnType(async.FutureOr, [src__core__server.Angel])]), + fallback: dart.fnType(src__router.Route$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])), [dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext])]) + })); + dart.setGetterSignature(src__core__server.Angel, () => ({ + __proto__: dart.getGetters(src__core__server.Angel.__proto__), + preContained: core.Map$(dart.dynamic, src__core__request_context.InjectionRequest), + optimizedRouter: src__router.Router, + children: core.List$(src__core__server.Angel), + controllers: core.Map$(core.Pattern, src__http__controller.Controller), + isProduction: core.bool, + parent: src__core__server.Angel + })); + dart.setFieldSignature(src__core__server.Angel, () => ({ + __proto__: dart.getFields(src__core__server.Angel.__proto__), + [_children]: dart.finalFieldType(core.List$(src__core__server.Angel)), + handlerCache: dart.finalFieldType(core.Map$(core.String, tuple.Tuple3$(core.List, core.Map$(core.String, dart.dynamic), src__combinator__combinator.ParseResult$(core.Map$(core.String, dart.dynamic))))), + [_flattened]: dart.fieldType(src__router.Router), + [_http$]: dart.fieldType(src__http__angel_http.AngelHttp), + [_isProduction]: dart.fieldType(core.bool), + [_parent]: dart.fieldType(src__core__server.Angel), + encoders: dart.finalFieldType(core.Map$(core.String, convert.Converter$(core.List$(core.int), core.List$(core.int)))), + [_preContained]: dart.finalFieldType(core.Map$(dart.dynamic, src__core__request_context.InjectionRequest)), + serializer: dart.fieldType(dart.fnType(core.String, [dart.dynamic])), + allowMethodOverrides: dart.fieldType(core.bool), + [_controllers]: dart.finalFieldType(core.Map$(core.Pattern, src__http__controller.Controller)), + logger: dart.fieldType(logging.Logger), + startupHooks: dart.finalFieldType(core.List$(dart.fnType(async.FutureOr, [src__core__server.Angel]))), + shutdownHooks: dart.finalFieldType(core.List$(dart.fnType(async.FutureOr, [src__core__server.Angel]))), + responseFinalizers: dart.finalFieldType(core.List$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext]))), + configuration: dart.finalFieldType(core.Map), + eagerParseRequestBodies: dart.fieldType(core.bool), + keepRawRequestBuffers: dart.fieldType(core.bool), + viewGenerator: dart.fieldType(dart.fnType(async.FutureOr$(core.String), [core.String], [core.Map$(core.String, dart.dynamic)])), + errorHandler: dart.fieldType(dart.fnType(dart.dynamic, [angel_http_exception.AngelHttpException, src__core__request_context.RequestContext, src__core__response_context.ResponseContext])) + })); + dart.defineLazy(src__core__server.Angel, { + /*src__core__server.Angel.noViewEngineConfigured*/get noViewEngineConfigured() { + return dart.fn((view, data) => { + if (data === void 0) data = null; + return "No view engine has been configured yet."; + }, StringAndMapToString()); + }, + set noViewEngineConfigured(_) {} + }); + src__core__server.AngelConfigurer = dart.typedef('AngelConfigurer', () => AngelToFutureOr()); + src__core__server.ViewGenerator = dart.typedef('ViewGenerator', () => StringAndMapOfString$dynamicToFutureOrOfString()); + src__core__service.Providers = class Providers extends core.Object { + get via() { + return this[via$]; + } + set via(value) { + super.via = value; + } + _equals(other) { + if (other == null) return false; + return src__core__service.Providers.is(other) && other.via == this.via; + } + toJson() { + return new (IdentityMapOfString$String()).from(["via", this.via]); + } + toString() { + return "via:" + dart.str(this.via); + } + }; + (src__core__service.Providers.new = function(via) { + this[via$] = via; + ; + }).prototype = src__core__service.Providers.prototype; + dart.addTypeTests(src__core__service.Providers); + const via$ = Symbol("Providers.via"); + dart.setMethodSignature(src__core__service.Providers, () => ({ + __proto__: dart.getMethods(src__core__service.Providers.__proto__), + toJson: dart.fnType(core.Map$(core.String, core.String), []) + })); + dart.setFieldSignature(src__core__service.Providers, () => ({ + __proto__: dart.getFields(src__core__service.Providers.__proto__), + via: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__core__service.Providers, ['_equals', 'toString']); + dart.defineLazy(src__core__service.Providers, { + /*src__core__service.Providers.viaRest*/get viaRest() { + return "rest"; + }, + /*src__core__service.Providers.viaWebsocket*/get viaWebsocket() { + return "websocket"; + }, + /*src__core__service.Providers.viaGraphQL*/get viaGraphQL() { + return "graphql"; + }, + /*src__core__service.Providers.rest*/get rest() { + return dart.const(new src__core__service.Providers.new("rest")); + }, + /*src__core__service.Providers.websocket*/get websocket() { + return dart.const(new src__core__service.Providers.new("websocket")); + }, + /*src__core__service.Providers.graphQL*/get graphQL() { + return dart.const(new src__core__service.Providers.new("graphql")); + } + }); + let const$15; + let const$16; + angel_http_exception.AngelHttpException = class AngelHttpException extends core.Object { + get error() { + return this[error$]; + } + set error(value) { + this[error$] = value; + } + get errors() { + return this[errors$]; + } + set errors(value) { + super.errors = value; + } + get message() { + return this[message$]; + } + set message(value) { + this[message$] = value; + } + get stackTrace() { + return this[stackTrace$]; + } + set stackTrace(value) { + this[stackTrace$] = value; + } + get statusCode() { + return this[statusCode$]; + } + set statusCode(value) { + this[statusCode$] = value; + } + toJson() { + return new _js_helper.LinkedMap.from(["isError", true, "status_code", this.statusCode, "message", this.message, "errors", this.errors]); + } + toMap() { + return this.toJson(); + } + toString() { + return dart.str(this.statusCode) + ": " + dart.str(this.message); + } + static fromMap(data) { + let t1, t1$; + return new angel_http_exception.AngelHttpException.new(null, {statusCode: core.int.as((t1 = data[$_get]("status_code"), t1 == null ? data[$_get]("statusCode") : t1)), message: (t1$ = data[$_get]("message"), t1$ == null ? null : dart.toString(t1$)), errors: core.Iterable.is(data[$_get]("errors")) ? core.Iterable.as(data[$_get]("errors"))[$map](core.String, dart.fn(x => dart.toString(x), dynamicToString()))[$toList]() : JSArrayOfString().of([])}); + } + static fromJson(str) { + return angel_http_exception.AngelHttpException.fromMap(core.Map.as(convert$.json.decode(str))); + } + static badRequest(opts) { + let message = opts && 'message' in opts ? opts.message : "400 Bad Request"; + let errors = opts && 'errors' in opts ? opts.errors : const$16 || (const$16 = dart.constList([], core.String)); + return new angel_http_exception.AngelHttpException.new(null, {message: message, errors: errors, statusCode: 400}); + } + static notAuthenticated(opts) { + let message = opts && 'message' in opts ? opts.message : "401 Not Authenticated"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 401}); + } + static paymentRequired(opts) { + let message = opts && 'message' in opts ? opts.message : "402 Payment Required"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 402}); + } + static forbidden(opts) { + let message = opts && 'message' in opts ? opts.message : "403 Forbidden"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 403}); + } + static notFound(opts) { + let message = opts && 'message' in opts ? opts.message : "404 Not Found"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 404}); + } + static methodNotAllowed(opts) { + let message = opts && 'message' in opts ? opts.message : "405 Method Not Allowed"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 405}); + } + static notAcceptable(opts) { + let message = opts && 'message' in opts ? opts.message : "406 Not Acceptable"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 406}); + } + static methodTimeout(opts) { + let message = opts && 'message' in opts ? opts.message : "408 Timeout"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 408}); + } + static conflict(opts) { + let message = opts && 'message' in opts ? opts.message : "409 Conflict"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 409}); + } + static notProcessable(opts) { + let message = opts && 'message' in opts ? opts.message : "422 Not Processable"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 422}); + } + static notImplemented(opts) { + let message = opts && 'message' in opts ? opts.message : "501 Not Implemented"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 501}); + } + static unavailable(opts) { + let message = opts && 'message' in opts ? opts.message : "503 Unavailable"; + return new angel_http_exception.AngelHttpException.new(null, {message: message, statusCode: 503}); + } + }; + (angel_http_exception.AngelHttpException.new = function(error, opts) { + let message = opts && 'message' in opts ? opts.message : "500 Internal Server Error"; + let stackTrace = opts && 'stackTrace' in opts ? opts.stackTrace : null; + let statusCode = opts && 'statusCode' in opts ? opts.statusCode : 500; + let errors = opts && 'errors' in opts ? opts.errors : const$15 || (const$15 = dart.constList([], core.String)); + this[errors$] = JSArrayOfString().of([]); + this[error$] = error; + this[message$] = message; + this[stackTrace$] = stackTrace; + this[statusCode$] = statusCode; + if (errors != null) { + this.errors[$addAll](errors); + } + }).prototype = angel_http_exception.AngelHttpException.prototype; + dart.addTypeTests(angel_http_exception.AngelHttpException); + const error$ = Symbol("AngelHttpException.error"); + const errors$ = Symbol("AngelHttpException.errors"); + const message$ = Symbol("AngelHttpException.message"); + const stackTrace$ = Symbol("AngelHttpException.stackTrace"); + const statusCode$ = Symbol("AngelHttpException.statusCode"); + angel_http_exception.AngelHttpException[dart.implements] = () => [core.Exception]; + dart.setMethodSignature(angel_http_exception.AngelHttpException, () => ({ + __proto__: dart.getMethods(angel_http_exception.AngelHttpException.__proto__), + toJson: dart.fnType(core.Map, []), + toMap: dart.fnType(core.Map, []) + })); + dart.setFieldSignature(angel_http_exception.AngelHttpException, () => ({ + __proto__: dart.getFields(angel_http_exception.AngelHttpException.__proto__), + error: dart.fieldType(dart.dynamic), + errors: dart.finalFieldType(core.List$(core.String)), + message: dart.fieldType(core.String), + stackTrace: dart.fieldType(core.StackTrace), + statusCode: dart.fieldType(core.int) + })); + dart.defineExtensionMethods(angel_http_exception.AngelHttpException, ['toString']); + angel_model.Model = class Model extends core.Object { + get id() { + return this[id$0]; + } + set id(value) { + this[id$0] = value; + } + get createdAt() { + return this[createdAt$]; + } + set createdAt(value) { + this[createdAt$] = value; + } + get updatedAt() { + return this[updatedAt$]; + } + set updatedAt(value) { + this[updatedAt$] = value; + } + }; + (angel_model.Model.new = function(opts) { + let id = opts && 'id' in opts ? opts.id : null; + let createdAt = opts && 'createdAt' in opts ? opts.createdAt : null; + let updatedAt = opts && 'updatedAt' in opts ? opts.updatedAt : null; + this[id$0] = id; + this[createdAt$] = createdAt; + this[updatedAt$] = updatedAt; + ; + }).prototype = angel_model.Model.prototype; + dart.addTypeTests(angel_model.Model); + const id$0 = Symbol("Model.id"); + const createdAt$ = Symbol("Model.createdAt"); + const updatedAt$ = Symbol("Model.updatedAt"); + dart.setFieldSignature(angel_model.Model, () => ({ + __proto__: dart.getFields(angel_model.Model.__proto__), + id: dart.fieldType(core.String), + createdAt: dart.fieldType(core.DateTime), + updatedAt: dart.fieldType(core.DateTime) + })); + const _closed$ = Symbol('_closed'); + const _server = Symbol('_server'); + const _serverGenerator = Symbol('_serverGenerator'); + const _sub = Symbol('_sub'); + src__http__angel_http.AngelHttp = class AngelHttp extends core.Object { + get app() { + return this[app$]; + } + set app(value) { + super.app = value; + } + get useZone() { + return this[useZone$0]; + } + set useZone(value) { + super.useZone = value; + } + get serverGenerator() { + return this[_serverGenerator]; + } + static custom(app, serverGenerator, opts) { + let t1; + let useZone = opts && 'useZone' in opts ? opts.useZone : true; + t1 = new src__http__angel_http.AngelHttp.new(app, {useZone: useZone}); + t1[_serverGenerator] = serverGenerator; + return t1; + } + static fromSecurityContext(app, context, opts) { + let useZone = opts && 'useZone' in opts ? opts.useZone : true; + let http = new src__http__angel_http.AngelHttp.new(app, {useZone: useZone}); + http[_serverGenerator] = dart.fn((address, port) => _http.HttpServer.bindSecure(address, port, context), dynamicAndintToFutureOfHttpServer()); + return http; + } + static secure(app, certificateChainPath, serverKeyPath, opts) { + let password = opts && 'password' in opts ? opts.password : null; + let useZone = opts && 'useZone' in opts ? opts.useZone : true; + let certificateChain = io.Platform.script.resolve(certificateChainPath).toFilePath(); + let serverKey = io.Platform.script.resolve(serverKeyPath).toFilePath(); + let serverContext = io.SecurityContext.new(); + serverContext.useCertificateChain(certificateChain, {password: password}); + serverContext.usePrivateKey(serverKey, {password: password}); + return src__http__angel_http.AngelHttp.fromSecurityContext(app, serverContext, {useZone: useZone}); + } + get httpServer() { + return this[_server]; + } + startServer(address, port) { + let t1, t1$; + if (address === void 0) address = null; + if (port === void 0) port = null; + let host = (t1 = address, t1 == null ? "127.0.0.1" : t1); + return this[_serverGenerator](host, (t1$ = port, t1$ == null ? 0 : t1$)).then(_http.HttpServer, dart.fn(server => { + this[_server] = server; + return async.Future.wait(dart.dynamic, this.app.startupHooks[$map](async.Future, dart.bind(this.app, 'configure'))).then(_http.HttpServer, dart.fn(_ => { + this.app.optimizeForProduction(); + this[_sub] = this[_server].listen(dart.bind(this, 'handleRequest')); + return this[_server]; + }, ListToHttpServer())); + }, HttpServerToFutureOfHttpServer())); + } + close() { + let t1; + if (dart.test(this[_closed$])) return FutureOfHttpServer().value(this[_server]); + this[_closed$] = true; + t1 = this[_sub]; + t1 == null ? null : t1.cancel(); + return this.app.close().then(_http.HttpServer, dart.fn(_ => async.Future.wait(dart.dynamic, this.app.shutdownHooks[$map](async.Future, dart.bind(this.app, 'configure'))).then(_http.HttpServer, dart.fn(_ => this[_server], ListToHttpServer())), dynamicToFutureOfHttpServer())); + } + handleRequest(request) { + return this.createRequestContext(request).then(dart.dynamic, dart.fn(req => this.createResponseContext(request.response, req).then(dart.dynamic, dart.fn(res => { + const handle = (function() { + let t1; + let path = req.path; + if (path === "/") path = ""; + const resolveTuple = (function() { + let r = this.app.optimizedRouter; + let resolved = r.resolveAbsolute(path, {method: req.method, strip: false}); + return new (Tuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic()).new(new src__middleware_pipeline.MiddlewarePipeline.new(resolved).handlers, resolved[$fold](MapOfString$dynamic(), new (IdentityMapOfString$dynamic()).new(), dart.fn((out, r) => { + let t1; + t1 = out; + t1[$addAll](r.allParams); + return t1; + }, MapOfString$dynamicAndRoutingResultToMapOfString$dynamic())), dart.test(resolved[$isEmpty]) ? null : resolved[$first].parseResult); + }).bind(this); + dart.fn(resolveTuple, VoidToTuple3OfList$MapOfString$dynamic$ParseResultOfMapOfString$dynamic()); + let cacheKey = dart.notNull(req.method) + dart.notNull(path); + let tuple = dart.test(this.app.isProduction) ? this.app.handlerCache[$putIfAbsent](cacheKey, resolveTuple) : resolveTuple(); + req.params[$addAll](tuple.item2); + req.container.registerSingleton(ParseResultOfMapOfString$dynamic(), tuple.item3); + req.container.registerSingleton(src__combinator__combinator.ParseResult, tuple.item3); + if (!dart.test(this.app.isProduction) && this.app.logger != null) { + req.container.registerSingleton(core.Stopwatch, (t1 = new core.Stopwatch.new(), t1.start(), t1)); + } + let pipeline = tuple.item1; + let runPipeline = null; + for (let handler of pipeline) { + if (handler == null) break; + if (runPipeline == null) + runPipeline = dart.fn(() => async.Future.sync(dart.fn(() => this.app.executeHandler(handler, req, res), VoidToFutureOfbool())), VoidToFuture()); + else { + let current = runPipeline; + runPipeline = dart.fn(() => current().then(dart.dynamic, dart.fn(result => !dart.test(res.isOpen) ? async.Future.value(result) : this.app.executeHandler(handler, req, res), dynamicToFuture())), VoidToFuture()); + } + } + return runPipeline == null ? this.sendResponse(request, req, res) : runPipeline().then(dart.dynamic, dart.fn(_ => this.sendResponse(request, req, res), dynamicToFuture())); + }).bind(this); + dart.fn(handle, VoidToFuture()); + if (dart.equals(this.useZone, false)) { + let f = null; + try { + f = handle(); + } catch (e) { + let st = dart.stackTrace(e); + f = async.Future.error(e, st); + } + return f.catchError(dart.fn((e, st) => { + let t1, t1$, t1$0; + if (core.FormatException.is(e)) dart.throw((t1 = angel_http_exception.AngelHttpException.badRequest({message: e.message}), t1.stackTrace = st, t1)); + dart.throw(new angel_http_exception.AngelHttpException.new(e, {stackTrace: st, statusCode: 500, message: (t1$0 = (t1$ = e, t1$ == null ? null : dart.toString(t1$)), t1$0 == null ? "500 Internal Server Error" : t1$0)})); + }, dynamicAndStackTraceToNull()), {test: dart.fn(e => !angel_http_exception.AngelHttpException.is(e), ObjectTobool())}).catchError(dart.fn((ee, st) => { + let t1, t1$, t1$0, t1$1; + let e = angel_http_exception.AngelHttpException.as(ee); + if (this.app.logger != null) { + let error = (t1 = e.error, t1 == null ? e : t1); + let trace = src__trace.Trace.from((t1$ = e.stackTrace, t1$ == null ? core.StackTrace.current : t1$)).terse; + this.app.logger.severe((t1$0 = e.message, t1$0 == null ? dart.toString(e) : t1$0), error, trace); + } + return this.handleAngelHttpException(e, (t1$1 = e.stackTrace, t1$1 == null ? st : t1$1), req, res, request); + }, dynamicAndStackTraceToFuture())); + } else { + let zoneSpec = new async._ZoneSpecification.new({print: dart.fn((self, parent, zone, line) => { + if (this.app.logger != null) + this.app.logger.info(line); + else + parent.print(zone, line); + }, ZoneAndZoneDelegateAndZone__ToNull()), handleUncaughtError: dart.fn((self, parent, zone, error, stackTrace) => { + let t1; + let trace = src__trace.Trace.from((t1 = stackTrace, t1 == null ? core.StackTrace.current : t1)).terse; + return async.Future.new(dart.fn(() => { + let t1, t1$, t1$0; + let e = null; + if (core.FormatException.is(error)) { + e = angel_http_exception.AngelHttpException.badRequest({message: error.message}); + } else if (angel_http_exception.AngelHttpException.is(error)) { + e = error; + } else { + e = new angel_http_exception.AngelHttpException.new(error, {stackTrace: stackTrace, message: (t1$ = (t1 = error, t1 == null ? null : dart.toString(t1)), t1$ == null ? "500 Internal Server Error" : t1$)}); + } + if (this.app.logger != null) { + this.app.logger.severe((t1$0 = e.message, t1$0 == null ? dart.toString(e) : t1$0), error, trace); + } + return this.handleAngelHttpException(e, trace, req, res, request); + }, VoidToFuture())).catchError(dart.fn((e, st) => { + let t1, t1$; + let trace = src__trace.Trace.from((t1 = st, t1 == null ? core.StackTrace.current : t1)).terse; + request.response.close(); + if (this.app.logger != null) { + this.app.logger.severe("Fatal error occurred when processing " + dart.str(request.uri) + ".", e, trace); + } else { + t1$ = io.stderr; + t1$.writeln("Fatal error occurred when processing " + dart.str(request.uri) + ":"); + t1$.writeln(e); + t1$.writeln(trace); + t1$; + } + }, dynamicAndStackTraceToNull())); + }, ZoneAndZoneDelegateAndZone__Tovoid())}); + let zone = async.Zone.current.fork({specification: zoneSpec}); + req.container.registerSingleton(async.Zone, zone); + req.container.registerSingleton(async.ZoneSpecification, zoneSpec); + try { + return zone.run(async.FutureOr, handle); + } catch (e) { + let st = dart.stackTrace(e); + zone.handleUncaughtError(e, st); + return async.Future.value(); + } + } + }, ResponseContextToFutureOr())), HttpRequestContextToFuture())); + } + handleAngelHttpException(e, st, req, res, request, opts) { + let t1, t1$; + let ignoreFinalizers = opts && 'ignoreFinalizers' in opts ? opts.ignoreFinalizers : false; + if (req == null || res == null) { + try { + t1 = this.app.logger; + t1 == null ? null : t1.severe(e, st); + t1$ = request.response; + t1$.statusCode = 500; + t1$.write("500 Internal Server Error"); + t1$.close(); + t1$; + } finally { + return null; + } + } + let handleError = null; + if (!dart.test(res.isOpen)) + handleError = async.Future.value(); + else { + res.statusCode = e.statusCode; + handleError = async.Future.sync(dart.fn(() => this.app.errorHandler(e, req, res), VoidTodynamic())).then(dart.dynamic, dart.fn(result => this.app.executeHandler(result, req, res).then(dart.dynamic, dart.fn(_ => res.close(), boolToFuture())), dynamicToFuture())); + } + return handleError.then(dart.dynamic, dart.fn(_ => this.sendResponse(request, req, res, {ignoreFinalizers: dart.equals(ignoreFinalizers, true)}), dynamicToFuture())); + } + sendResponse(request, req, res, opts) { + let ignoreFinalizers = opts && 'ignoreFinalizers' in opts ? opts.ignoreFinalizers : false; + const _cleanup = (function(_) { + let t1, t1$; + if (!dart.test(this.app.isProduction) && this.app.logger != null) { + let sw = req.container.make(core.Stopwatch); + this.app.logger.info(dart.str(res.statusCode) + " " + dart.str(req.method) + " " + dart.str(req.uri) + " (" + dart.str((t1$ = (t1 = sw, t1 == null ? null : t1.elapsedMilliseconds), t1$ == null ? "unknown" : t1$)) + " ms)"); + } + }).bind(this); + dart.fn(_cleanup, dynamicTovoid()); + if (!dart.test(res.isBuffered)) return res.close().then(dart.dynamic, _cleanup); + let finalizers = dart.equals(ignoreFinalizers, true) ? async.Future.value() : this.app.responseFinalizers[$fold](async.Future, async.Future.value(), dart.fn((out, f) => out.then(dart.dynamic, dart.fn(_ => f(req, res), dynamicToFutureOr())), FutureAndFnToFuture())); + return finalizers.then(dart.dynamic, dart.fn(_ => { + let t1, t1$, t1$0, t1$1, t1$2, t1$3; + if (dart.test(res.isOpen)) res.close(); + for (let key of res.headers[$keys]) { + request.response.headers.add(key, res.headers[$_get](key)); + } + request.response.contentLength = res.buffer.length; + request.response.headers.chunkedTransferEncoding = (t1 = res.chunked, t1 == null ? true : t1); + let outputBuffer = res.buffer.toBytes(); + if (dart.test(res.encoders[$isNotEmpty])) { + let allowedEncodings = (t1$2 = (t1$1 = (t1$0 = (t1$ = req.headers.value("accept-encoding"), t1$ == null ? null : t1$[$split](",")), t1$0 == null ? null : t1$0[$map](core.String, dart.fn(s => s[$trim](), StringToString()))), t1$1 == null ? null : t1$1[$where](dart.fn(s => s[$isNotEmpty], StringTobool()))), t1$2 == null ? null : t1$2[$map](core.String, dart.fn(str => { + if (!str[$contains](";")) return str; + return str[$split](";")[$_get](0); + }, StringToString()))); + if (allowedEncodings != null) { + for (let encodingName of allowedEncodings) { + let encoder = null; + let key = encodingName; + if (dart.test(res.encoders[$containsKey](encodingName))) + encoder = res.encoders[$_get](encodingName); + else if (encodingName === "*") { + encoder = res.encoders[$_get](key = res.encoders[$keys][$first]); + } + if (encoder != null) { + request.response.headers.set("content-encoding", key); + outputBuffer = res.encoders[$_get](key).convert(outputBuffer); + request.response.contentLength = outputBuffer[$length]; + break; + } + } + } + } + t1$3 = request.response; + t1$3.statusCode = res.statusCode; + t1$3.cookies[$addAll](res.cookies); + t1$3.add(outputBuffer); + t1$3; + return request.response.close().then(dart.dynamic, _cleanup); + }, dynamicToFuture())); + } + createRequestContext(request) { + let path = request.uri.path[$replaceAll](src__http__angel_http._straySlashes, ""); + if (path.length === 0) path = "/"; + return src__http__http_request_context.HttpRequestContext.from(request, this.app, path); + } + createResponseContext(response, correspondingRequest) { + let t2, t2$, t1; + if (correspondingRequest === void 0) correspondingRequest = null; + return FutureOfResponseContext().value((t1 = new src__http__http_response_context.HttpResponseContext.new(response, this.app, src__http__http_request_context.HttpRequestContext.as(correspondingRequest)), t1.serializer = (t2 = this.app.serializer, t2 == null ? dart.bind(convert.json, 'encode') : t2), t1.encoders[$addAll]((t2$ = this.app.encoders, t2$ == null ? new (IdentityMapOfString$ConverterOfListOfint$ListOfint()).new() : t2$)), t1)); + } + }; + (src__http__angel_http.AngelHttp.new = function(app, opts) { + let useZone = opts && 'useZone' in opts ? opts.useZone : false; + this[_closed$] = false; + this[_server] = null; + this[_serverGenerator] = dart.fn(_http.HttpServer.bind, dynamicAndint__ToFutureOfHttpServer()); + this[_sub] = null; + this[app$] = app; + this[useZone$0] = useZone; + ; + }).prototype = src__http__angel_http.AngelHttp.prototype; + dart.addTypeTests(src__http__angel_http.AngelHttp); + const app$ = Symbol("AngelHttp.app"); + const useZone$0 = Symbol("AngelHttp.useZone"); + dart.setMethodSignature(src__http__angel_http.AngelHttp, () => ({ + __proto__: dart.getMethods(src__http__angel_http.AngelHttp.__proto__), + startServer: dart.fnType(async.Future$(_http.HttpServer), [], [dart.dynamic, core.int]), + close: dart.fnType(async.Future$(_http.HttpServer), []), + handleRequest: dart.fnType(async.Future, [_http.HttpRequest]), + handleAngelHttpException: dart.fnType(async.Future, [angel_http_exception.AngelHttpException, core.StackTrace, src__core__request_context.RequestContext, src__core__response_context.ResponseContext, _http.HttpRequest], {ignoreFinalizers: core.bool}), + sendResponse: dart.fnType(async.Future, [_http.HttpRequest, src__core__request_context.RequestContext, src__core__response_context.ResponseContext], {ignoreFinalizers: core.bool}), + createRequestContext: dart.fnType(async.Future$(src__http__http_request_context.HttpRequestContext), [_http.HttpRequest]), + createResponseContext: dart.fnType(async.Future$(src__core__response_context.ResponseContext), [_http.HttpResponse], [src__core__request_context.RequestContext]) + })); + dart.setGetterSignature(src__http__angel_http.AngelHttp, () => ({ + __proto__: dart.getGetters(src__http__angel_http.AngelHttp.__proto__), + serverGenerator: dart.fnType(async.Future$(_http.HttpServer), [dart.dynamic, core.int]), + httpServer: _http.HttpServer + })); + dart.setFieldSignature(src__http__angel_http.AngelHttp, () => ({ + __proto__: dart.getFields(src__http__angel_http.AngelHttp.__proto__), + app: dart.finalFieldType(src__core__server.Angel), + useZone: dart.finalFieldType(core.bool), + [_closed$]: dart.fieldType(core.bool), + [_server]: dart.fieldType(_http.HttpServer), + [_serverGenerator]: dart.fieldType(dart.fnType(async.Future$(_http.HttpServer), [dart.dynamic, core.int])), + [_sub]: dart.fieldType(async.StreamSubscription$(_http.HttpRequest)) + })); + dart.defineLazy(src__http__angel_http, { + /*src__http__angel_http._straySlashes*/get _straySlashes() { + return core.RegExp.new("(^/+)|(/+$)"); + } + }); + const _app = Symbol('_app'); + const _routeBuilder = Symbol('_routeBuilder'); + src__http__controller.Controller = class Controller extends core.Object { + get injectSingleton() { + return this[injectSingleton$]; + } + set injectSingleton(value) { + super.injectSingleton = value; + } + get middleware() { + return this[middleware]; + } + set middleware(value) { + this[middleware] = value; + } + get routeMappings() { + return this[routeMappings]; + } + set routeMappings(value) { + this[routeMappings] = value; + } + get app() { + return this[_app]; + } + configureServer(app) { + let t1, t1$; + this[_app] = app; + if (!dart.equals(this.injectSingleton, false)) { + this[_app].container.registerSingleton(src__http__controller.Controller, this, {as: this[$runtimeType]}); + } + let classMirror = app.container.reflector.reflectClass(this[$runtimeType]); + let exposeDecl = this.findExpose(app.container.reflector); + if (exposeDecl == null) { + dart.throw(core.Exception.new("All controllers must carry an @Expose() declaration.")); + } + let routable = new src__core__routable.Routable.new(); + app.mount(exposeDecl.path, routable); + let typeMirror = app.container.reflector.reflectType(this[$runtimeType]); + let name = dart.equals((t1 = exposeDecl.as, t1 == null ? null : t1[$isNotEmpty]), true) ? exposeDecl.as : typeMirror.name; + app.controllers[$_set](name, this); + let instanceMirror = app.container.reflector.reflectInstance(this); + let handlers = (t1$ = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1$[$addAll](exposeDecl.middleware), t1$[$addAll](this.middleware), t1$); + let routeBuilder = this[_routeBuilder](instanceMirror, routable, handlers); + classMirror.declarations[$forEach](routeBuilder); + this.configureRoutes(routable); + return async.Future.value(); + } + [_routeBuilder](instanceMirror, routable, handlers) { + return dart.fn(decl => { + let t1, t1$, t1$0, t1$1, t1$2; + let methodName = decl.name; + if (methodName !== "toString" && methodName !== "noSuchMethod" && methodName !== "call" && methodName !== "equals" && methodName !== "==") { + let exposeDecl = src__core__metadata.Expose._check(decl.function.annotations[$map](core.Object, dart.fn(m => m.reflectee, ReflectedInstanceToObject()))[$firstWhere](dart.fn(r => src__core__metadata.Expose.is(r), ObjectTobool()), {orElse: dart.fn(() => null, VoidToNull())})); + if (exposeDecl == null) return; + let reflectedMethod = core.Function.as(instanceMirror.getField(methodName).reflectee); + let middleware = (t1 = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]), t1[$addAll](handlers), t1[$addAll](exposeDecl.middleware), t1); + let name = dart.equals((t1$ = exposeDecl.as, t1$ == null ? null : t1$[$isNotEmpty]), true) ? exposeDecl.as : methodName; + let method = decl.function; + if (method.parameters[$length] === 2 && dart.equals(method.parameters[$_get](0).type.reflectedType, dart.wrapType(src__core__request_context.RequestContext)) && dart.equals(method.parameters[$_get](1).type.reflectedType, dart.wrapType(src__core__response_context.ResponseContext))) { + this.routeMappings[$_set](name, routable.addRoute(exposeDecl.method, exposeDecl.path, dart.fn((req, res) => { + let result = dart.dcall(reflectedMethod, [req, res]); + return RequestContextAndResponseContextToFutureOr().is(result) ? result(req, res) : result; + }, RequestContextAndResponseContextTodynamic()), {middleware: middleware})); + return; + } + let injection = src__core__request_context.preInject(reflectedMethod, this.app.container.reflector); + if (dart.equals((t1$1 = (t1$0 = exposeDecl, t1$0 == null ? null : t1$0.allowNull), t1$1 == null ? null : t1$1[$isNotEmpty]), true)) { + t1$2 = injection.optional; + t1$2 == null ? null : t1$2[$addAll](exposeDecl.allowNull); + } + this.routeMappings[$_set](name, routable.addRoute(exposeDecl.method, exposeDecl.path, src__core__request_context.handleContained(reflectedMethod, injection), {middleware: middleware})); + } + }, ReflectedDeclarationToNull()); + } + configureRoutes(routable) { + } + findExpose(reflector) { + return src__core__metadata.Expose.as(reflector.reflectClass(this[$runtimeType]).annotations[$map](core.Object, dart.fn(m => m.reflectee, ReflectedInstanceToObject()))[$firstWhere](dart.fn(r => src__core__metadata.Expose.is(r), ObjectTobool()), {orElse: dart.fn(() => null, VoidToNull())})); + } + }; + (src__http__controller.Controller.new = function(opts) { + let injectSingleton = opts && 'injectSingleton' in opts ? opts.injectSingleton : true; + this[_app] = null; + this[middleware] = JSArrayOfRequestContextAndResponseContextToFutureOr().of([]); + this[routeMappings] = new (IdentityMapOfString$Route()).new(); + this[injectSingleton$] = injectSingleton; + ; + }).prototype = src__http__controller.Controller.prototype; + dart.addTypeTests(src__http__controller.Controller); + const injectSingleton$ = Symbol("Controller.injectSingleton"); + const middleware = Symbol("Controller.middleware"); + const routeMappings = Symbol("Controller.routeMappings"); + dart.setMethodSignature(src__http__controller.Controller, () => ({ + __proto__: dart.getMethods(src__http__controller.Controller.__proto__), + configureServer: dart.fnType(async.Future, [src__core__server.Angel]), + [_routeBuilder]: dart.fnType(dart.fnType(dart.void, [src__reflector.ReflectedDeclaration]), [src__reflector.ReflectedInstance, src__core__routable.Routable, core.Iterable$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext]))]), + configureRoutes: dart.fnType(dart.void, [src__core__routable.Routable]), + findExpose: dart.fnType(src__core__metadata.Expose, [src__reflector.Reflector]) + })); + dart.setGetterSignature(src__http__controller.Controller, () => ({ + __proto__: dart.getGetters(src__http__controller.Controller.__proto__), + app: src__core__server.Angel + })); + dart.setFieldSignature(src__http__controller.Controller, () => ({ + __proto__: dart.getFields(src__http__controller.Controller.__proto__), + [_app]: dart.fieldType(src__core__server.Angel), + injectSingleton: dart.finalFieldType(core.bool), + middleware: dart.fieldType(core.List$(dart.fnType(async.FutureOr, [src__core__request_context.RequestContext, src__core__response_context.ResponseContext]))), + routeMappings: dart.fieldType(core.Map$(core.String, src__router.Route)) + })); + const _container$ = Symbol('_container'); + const _contentType = Symbol('_contentType'); + const _io = Symbol('_io'); + const _override = Symbol('_override'); + const _path = Symbol('_path'); + src__http__http_request_context.HttpRequestContext = class HttpRequestContext extends src__core__request_context.RequestContext$(_http.HttpRequest) { + get container() { + return this[_container$]; + } + get contentType() { + return this[_contentType]; + } + get cookies() { + return this.rawRequest.cookies; + } + get headers() { + return this.rawRequest.headers; + } + get hostname() { + return this.rawRequest.headers.value("host"); + } + get rawRequest() { + return this[_io]; + } + get method() { + let t1; + t1 = this[_override]; + return t1 == null ? this.originalMethod : t1; + } + get originalMethod() { + return this.rawRequest.method; + } + get path() { + return this[_path]; + } + get remoteAddress() { + return this.rawRequest.connectionInfo.remoteAddress; + } + get session() { + return this.rawRequest.session; + } + get uri() { + return this.rawRequest.uri; + } + get xhr() { + let t1, t1$; + return (t1$ = (t1 = this.rawRequest.headers.value("X-Requested-With"), t1 == null ? null : t1[$trim]()), t1$ == null ? null : t1$[$toLowerCase]()) === "xmlhttprequest"; + } + static from(request, app, path) { + let t1, t1$, t1$0; + let ctx = (t1 = new src__http__http_request_context.HttpRequestContext.new(), t1[_container$] = app.container.createChild(), t1); + let override = request.method; + if (dart.equals(app.allowMethodOverrides, true)) override = (t1$0 = (t1$ = request.headers.value("x-http-method-override"), t1$ == null ? null : t1$[$toUpperCase]()), t1$0 == null ? request.method : t1$0); + ctx.app = app; + ctx[_contentType] = request.headers.contentType == null ? null : src__media_type.MediaType.parse(dart.toString(request.headers.contentType)); + ctx[_override] = override; + ctx[_path] = path; + ctx[_io] = request; + if (dart.equals(app.eagerParseRequestBodies, true)) { + return ctx.parse().then(src__http__http_request_context.HttpRequestContext, dart.fn(_ => ctx, BodyParseResultToHttpRequestContext())); + } + return FutureOfHttpRequestContext().value(ctx); + } + close() { + this[_contentType] = null; + this[_io] = null; + this[_override] = this[_path] = null; + return super.close(); + } + parseOnce() { + return src__parse_body.parseBodyFromStream(this.rawRequest, this.rawRequest.headers.contentType != null ? src__media_type.MediaType.parse(dart.toString(this.rawRequest.headers.contentType)) : null, this.rawRequest.uri, {storeOriginalBuffer: dart.equals(this.app.keepRawRequestBuffers, true)}); + } + }; + (src__http__http_request_context.HttpRequestContext.new = function() { + this[_container$] = null; + this[_contentType] = null; + this[_io] = null; + this[_override] = null; + this[_path] = null; + src__http__http_request_context.HttpRequestContext.__proto__.new.call(this); + ; + }).prototype = src__http__http_request_context.HttpRequestContext.prototype; + dart.addTypeTests(src__http__http_request_context.HttpRequestContext); + dart.setMethodSignature(src__http__http_request_context.HttpRequestContext, () => ({ + __proto__: dart.getMethods(src__http__http_request_context.HttpRequestContext.__proto__), + parseOnce: dart.fnType(async.Future$(src__body_parse_result.BodyParseResult), []) + })); + dart.setGetterSignature(src__http__http_request_context.HttpRequestContext, () => ({ + __proto__: dart.getGetters(src__http__http_request_context.HttpRequestContext.__proto__), + container: src__container.Container, + contentType: src__media_type.MediaType, + cookies: core.List$(_http.Cookie), + headers: _http.HttpHeaders, + hostname: core.String, + rawRequest: _http.HttpRequest, + method: core.String, + originalMethod: core.String, + path: core.String, + remoteAddress: io.InternetAddress, + session: _http.HttpSession, + uri: core.Uri, + xhr: core.bool + })); + dart.setFieldSignature(src__http__http_request_context.HttpRequestContext, () => ({ + __proto__: dart.getFields(src__http__http_request_context.HttpRequestContext.__proto__), + [_container$]: dart.fieldType(src__container.Container), + [_contentType]: dart.fieldType(src__media_type.MediaType), + [_io]: dart.fieldType(_http.HttpRequest), + [_override]: dart.fieldType(core.String), + [_path]: dart.fieldType(core.String) + })); + const _buffer = Symbol('_buffer'); + const _isDetached = Symbol('_isDetached'); + const _isClosed = Symbol('_isClosed'); + const _streamInitialized = Symbol('_streamInitialized'); + const __allowedEncodings = Symbol('__allowedEncodings'); + const _correspondingRequest$ = Symbol('_correspondingRequest'); + const _allowedEncodings = Symbol('_allowedEncodings'); + const _openStream = Symbol('_openStream'); + src__http__http_response_context.HttpResponseContext = class HttpResponseContext extends src__core__response_context.ResponseContext$(_http.HttpResponse) { + get rawResponse() { + return this[rawResponse$]; + } + set rawResponse(value) { + super.rawResponse = value; + } + get app() { + return this[app$0]; + } + set app(value) { + this[app$0] = value; + } + detach() { + this[_isDetached] = true; + return this.rawResponse; + } + get correspondingRequest() { + return this[_correspondingRequest$]; + } + get isOpen() { + return !dart.test(this[_isClosed]) && !dart.test(this[_isDetached]); + } + get isBuffered() { + return this[_buffer] != null; + } + get buffer() { + return this[_buffer]; + } + addError(error, stackTrace) { + if (stackTrace === void 0) stackTrace = null; + this.rawResponse.addError(error, stackTrace); + super.addError(error, stackTrace); + } + useBuffer() { + this[_buffer] = src__core__response_context.LockableBytesBuilder.new(); + } + get [_allowedEncodings]() { + let t2, t2$, t2$0, t2$1, t1; + t1 = this[__allowedEncodings]; + return t1 == null ? this[__allowedEncodings] = (t2$1 = (t2$0 = (t2$ = (t2 = this.correspondingRequest.headers.value("accept-encoding"), t2 == null ? null : t2[$split](",")), t2$ == null ? null : t2$[$map](core.String, dart.fn(s => s[$trim](), StringToString()))), t2$0 == null ? null : t2$0[$where](dart.fn(s => s[$isNotEmpty], StringTobool()))), t2$1 == null ? null : t2$1[$map](core.String, dart.fn(str => { + if (!str[$contains](";")) return str; + return str[$split](";")[$_get](0); + }, StringToString()))) : t1; + } + [_openStream]() { + let t1; + if (!dart.test(this[_streamInitialized])) { + t1 = this.rawResponse; + t1.statusCode = this.statusCode; + t1.cookies[$addAll](this.cookies); + t1; + this.headers[$forEach](dart.bind(this.rawResponse.headers, 'set')); + this.rawResponse.headers.contentType = _http.ContentType.new(this.contentType.type, this.contentType.subtype, {charset: this.contentType.parameters[$_get]("charset"), parameters: this.contentType.parameters}); + if (dart.test(this.encoders[$isNotEmpty]) && this.correspondingRequest != null) { + if (this[_allowedEncodings] != null) { + for (let encodingName of this[_allowedEncodings]) { + let encoder = null; + let key = encodingName; + if (dart.test(this.encoders[$containsKey](encodingName))) + encoder = this.encoders[$_get](encodingName); + else if (encodingName === "*") { + encoder = this.encoders[$_get](key = this.encoders[$keys][$first]); + } + if (encoder != null) { + this.rawResponse.headers.set("content-encoding", key); + break; + } + } + } + } + return this[_streamInitialized] = true; + } + return false; + } + addStream(stream) { + StreamOfListOfint()._check(stream); + if (dart.test(this[_isClosed]) && dart.test(this.isBuffered)) dart.throw(src__core__response_context.ResponseContext.closed()); + this[_openStream](); + let output = stream; + if (dart.test(this.encoders[$isNotEmpty]) && this.correspondingRequest != null) { + if (this[_allowedEncodings] != null) { + for (let encodingName of this[_allowedEncodings]) { + let encoder = null; + let key = encodingName; + if (dart.test(this.encoders[$containsKey](encodingName))) + encoder = this.encoders[$_get](encodingName); + else if (encodingName === "*") { + encoder = this.encoders[$_get](key = this.encoders[$keys][$first]); + } + if (encoder != null) { + output = this.encoders[$_get](key).bind(output); + break; + } + } + } + } + return this.rawResponse.addStream(output); + } + add(data) { + ListOfint()._check(data); + if (dart.test(this[_isClosed]) && dart.test(this.isBuffered)) + dart.throw(src__core__response_context.ResponseContext.closed()); + else if (!dart.test(this.isBuffered)) { + this[_openStream](); + if (dart.test(this.encoders[$isNotEmpty]) && this.correspondingRequest != null) { + if (this[_allowedEncodings] != null) { + for (let encodingName of this[_allowedEncodings]) { + let encoder = null; + let key = encodingName; + if (dart.test(this.encoders[$containsKey](encodingName))) + encoder = this.encoders[$_get](encodingName); + else if (encodingName === "*") { + encoder = this.encoders[$_get](key = this.encoders[$keys][$first]); + } + if (encoder != null) { + data = this.encoders[$_get](key).convert(data); + break; + } + } + } + } + this.rawResponse.add(data); + } else + this.buffer.add(data); + } + close() { + if (!dart.test(this[_isDetached])) { + if (!dart.test(this[_isClosed])) { + if (!dart.test(this.isBuffered)) { + try { + this.rawResponse.close(); + } catch (_) { + } + } else { + this[_buffer].lock(); + } + this[_isClosed] = true; + } + super.close(); + } + return async.Future.value(); + } + }; + (src__http__http_response_context.HttpResponseContext.new = function(rawResponse, app, _correspondingRequest) { + if (_correspondingRequest === void 0) _correspondingRequest = null; + this[_buffer] = null; + this[_isDetached] = false; + this[_isClosed] = false; + this[_streamInitialized] = false; + this[__allowedEncodings] = null; + this[rawResponse$] = rawResponse; + this[app$0] = app; + this[_correspondingRequest$] = _correspondingRequest; + src__http__http_response_context.HttpResponseContext.__proto__.new.call(this); + ; + }).prototype = src__http__http_response_context.HttpResponseContext.prototype; + dart.addTypeTests(src__http__http_response_context.HttpResponseContext); + const rawResponse$ = Symbol("HttpResponseContext.rawResponse"); + const app$0 = Symbol("HttpResponseContext.app"); + dart.setMethodSignature(src__http__http_response_context.HttpResponseContext, () => ({ + __proto__: dart.getMethods(src__http__http_response_context.HttpResponseContext.__proto__), + detach: dart.fnType(_http.HttpResponse, []), + useBuffer: dart.fnType(dart.void, []), + [_openStream]: dart.fnType(core.bool, []), + addStream: dart.fnType(async.Future, [core.Object]), + add: dart.fnType(dart.void, [core.Object]) + })); + dart.setGetterSignature(src__http__http_response_context.HttpResponseContext, () => ({ + __proto__: dart.getGetters(src__http__http_response_context.HttpResponseContext.__proto__), + correspondingRequest: src__core__request_context.RequestContext, + isOpen: core.bool, + isBuffered: core.bool, + buffer: io.BytesBuilder, + [_allowedEncodings]: core.Iterable$(core.String) + })); + dart.setFieldSignature(src__http__http_response_context.HttpResponseContext, () => ({ + __proto__: dart.getFields(src__http__http_response_context.HttpResponseContext.__proto__), + rawResponse: dart.finalFieldType(_http.HttpResponse), + app: dart.fieldType(src__core__server.Angel), + [_buffer]: dart.fieldType(src__core__response_context.LockableBytesBuilder), + [_correspondingRequest$]: dart.finalFieldType(src__http__http_request_context.HttpRequestContext), + [_isDetached]: dart.fieldType(core.bool), + [_isClosed]: dart.fieldType(core.bool), + [_streamInitialized]: dart.fieldType(core.bool), + [__allowedEncodings]: dart.fieldType(core.Iterable$(core.String)) + })); + let const$17; + let const$18; + let const$19; + angel_container.GenerateReflector = class GenerateReflector extends core.Object { + get types() { + return this[types$]; + } + set types(value) { + super.types = value; + } + get functions() { + return this[functions$]; + } + set functions(value) { + super.functions = value; + } + get symbols() { + return this[symbols$]; + } + set symbols(value) { + super.symbols = value; + } + get name() { + return this[name$0]; + } + set name(value) { + super.name = value; + } + }; + (angel_container.GenerateReflector.new = function(opts) { + let types = opts && 'types' in opts ? opts.types : const$17 || (const$17 = dart.constList([], core.Type)); + let functions = opts && 'functions' in opts ? opts.functions : const$18 || (const$18 = dart.constList([], core.Function)); + let symbols = opts && 'symbols' in opts ? opts.symbols : const$19 || (const$19 = dart.constList([], core.Symbol)); + let name = opts && 'name' in opts ? opts.name : null; + this[types$] = types; + this[functions$] = functions; + this[symbols$] = symbols; + this[name$0] = name; + ; + }).prototype = angel_container.GenerateReflector.prototype; + dart.addTypeTests(angel_container.GenerateReflector); + const types$ = Symbol("GenerateReflector.types"); + const functions$ = Symbol("GenerateReflector.functions"); + const symbols$ = Symbol("GenerateReflector.symbols"); + const name$0 = Symbol("GenerateReflector.name"); + dart.setFieldSignature(angel_container.GenerateReflector, () => ({ + __proto__: dart.getFields(angel_container.GenerateReflector.__proto__), + types: dart.finalFieldType(core.List$(core.Type)), + functions: dart.finalFieldType(core.List$(core.Function)), + symbols: dart.finalFieldType(core.List$(core.Symbol)), + name: dart.finalFieldType(core.String) + })); + const _level = Symbol('_level'); + const _controller = Symbol('_controller'); + const _children$ = Symbol('_children'); + const _getStream = Symbol('_getStream'); + const _publish = Symbol('_publish'); + logging.Logger = class Logger extends core.Object { + get name() { + return this[name$1]; + } + set name(value) { + super.name = value; + } + get parent() { + return this[parent$]; + } + set parent(value) { + super.parent = value; + } + get children() { + return this[children$]; + } + set children(value) { + super.children = value; + } + get fullName() { + return this.parent == null || this.parent.name === "" ? this.name : dart.str(this.parent.fullName) + "." + dart.str(this.name); + } + static new(name) { + return logging.Logger._loggers[$putIfAbsent](name, dart.fn(() => logging.Logger._named(name), VoidToLogger())); + } + static detached(name) { + return new logging.Logger._internal(name, null, new (LinkedMapOfString$Logger()).new()); + } + static _named(name) { + if (name[$startsWith](".")) { + dart.throw(new core.ArgumentError.new("name shouldn't start with a '.'")); + } + let dot = name[$lastIndexOf]("."); + let parent = null; + let thisName = null; + if (dot === -1) { + if (name !== "") parent = logging.Logger.new(""); + thisName = name; + } else { + parent = logging.Logger.new(name[$substring](0, dot)); + thisName = name[$substring](dot + 1); + } + return new logging.Logger._internal(thisName, parent, new (LinkedMapOfString$Logger()).new()); + } + get level() { + if (dart.test(logging.hierarchicalLoggingEnabled)) { + if (this[_level] != null) return this[_level]; + if (this.parent != null) return this.parent.level; + } + return logging._rootLevel; + } + set level(value) { + if (dart.test(logging.hierarchicalLoggingEnabled) && this.parent != null) { + this[_level] = value; + } else { + if (this.parent != null) { + dart.throw(new core.UnsupportedError.new("Please set \"hierarchicalLoggingEnabled\" to true if you want to " + "change the level on a non-root logger.")); + } + logging._rootLevel = value; + } + } + get onRecord() { + return this[_getStream](); + } + clearListeners() { + if (dart.test(logging.hierarchicalLoggingEnabled) || this.parent == null) { + if (this[_controller] != null) { + this[_controller].close(); + this[_controller] = null; + } + } else { + logging.Logger.root.clearListeners(); + } + } + isLoggable(value) { + return value['>='](this.level); + } + log(logLevel, message, error, stackTrace, zone) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + if (zone === void 0) zone = null; + let object = null; + if (dart.test(this.isLoggable(logLevel))) { + if (core.Function.is(message)) { + message = dart.dcall(message, []); + } + let msg = null; + if (typeof message == 'string') { + msg = message; + } else { + msg = dart.toString(message); + object = message; + } + if (stackTrace == null && dart.test(logLevel['>='](logging.recordStackTraceAtLevel))) { + stackTrace = core.StackTrace.current; + error == null ? error = "autogenerated stack trace for " + dart.str(logLevel) + " " + dart.str(msg) : null; + } + if (zone == null) zone = async.Zone.current; + let record = new logging.LogRecord.new(logLevel, msg, this.fullName, error, stackTrace, zone, object); + if (dart.test(logging.hierarchicalLoggingEnabled)) { + let target = this; + while (target != null) { + target[_publish](record); + target = target.parent; + } + } else { + logging.Logger.root[_publish](record); + } + } + } + finest(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.FINEST, message, error, stackTrace); + } + finer(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.FINER, message, error, stackTrace); + } + fine(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.FINE, message, error, stackTrace); + } + config(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.CONFIG, message, error, stackTrace); + } + info(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.INFO, message, error, stackTrace); + } + warning(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.WARNING, message, error, stackTrace); + } + severe(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.SEVERE, message, error, stackTrace); + } + shout(message, error, stackTrace) { + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + return this.log(logging.Level.SHOUT, message, error, stackTrace); + } + [_getStream]() { + if (dart.test(logging.hierarchicalLoggingEnabled) || this.parent == null) { + if (this[_controller] == null) { + this[_controller] = StreamControllerOfLogRecord().broadcast({sync: true}); + } + return this[_controller].stream; + } else { + return logging.Logger.root[_getStream](); + } + } + [_publish](record) { + if (this[_controller] != null) { + this[_controller].add(record); + } + } + }; + (logging.Logger._internal = function(name, parent, children) { + this[_level] = null; + this[_controller] = null; + this[name$1] = name; + this[parent$] = parent; + this[_children$] = children; + this[children$] = new (UnmodifiableMapViewOfString$Logger()).new(children); + if (this.parent != null) this.parent[_children$][$_set](this.name, this); + }).prototype = logging.Logger.prototype; + dart.addTypeTests(logging.Logger); + const name$1 = Symbol("Logger.name"); + const parent$ = Symbol("Logger.parent"); + const children$ = Symbol("Logger.children"); + dart.setMethodSignature(logging.Logger, () => ({ + __proto__: dart.getMethods(logging.Logger.__proto__), + clearListeners: dart.fnType(dart.void, []), + isLoggable: dart.fnType(core.bool, [logging.Level]), + log: dart.fnType(dart.void, [logging.Level, dart.dynamic], [core.Object, core.StackTrace, async.Zone]), + finest: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + finer: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + fine: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + config: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + info: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + warning: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + severe: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + shout: dart.fnType(dart.void, [dart.dynamic], [core.Object, core.StackTrace]), + [_getStream]: dart.fnType(async.Stream$(logging.LogRecord), []), + [_publish]: dart.fnType(dart.void, [logging.LogRecord]) + })); + dart.setGetterSignature(logging.Logger, () => ({ + __proto__: dart.getGetters(logging.Logger.__proto__), + fullName: core.String, + level: logging.Level, + onRecord: async.Stream$(logging.LogRecord) + })); + dart.setSetterSignature(logging.Logger, () => ({ + __proto__: dart.getSetters(logging.Logger.__proto__), + level: logging.Level + })); + dart.setFieldSignature(logging.Logger, () => ({ + __proto__: dart.getFields(logging.Logger.__proto__), + name: dart.finalFieldType(core.String), + parent: dart.finalFieldType(logging.Logger), + [_level]: dart.fieldType(logging.Level), + [_children$]: dart.finalFieldType(core.Map$(core.String, logging.Logger)), + children: dart.finalFieldType(core.Map$(core.String, logging.Logger)), + [_controller]: dart.fieldType(async.StreamController$(logging.LogRecord)) + })); + dart.defineLazy(logging.Logger, { + /*logging.Logger.root*/get root() { + return logging.Logger.new(""); + }, + /*logging.Logger._loggers*/get _loggers() { + return new (IdentityMapOfString$Logger()).new(); + } + }); + logging.Level = class Level extends core.Object { + get name() { + return this[name$2]; + } + set name(value) { + super.name = value; + } + get value() { + return this[value$]; + } + set value(value) { + super.value = value; + } + _equals(other) { + if (other == null) return false; + return logging.Level.is(other) && this.value == other.value; + } + ['<'](other) { + return dart.notNull(this.value) < dart.notNull(other.value); + } + ['<='](other) { + return dart.notNull(this.value) <= dart.notNull(other.value); + } + ['>'](other) { + return dart.notNull(this.value) > dart.notNull(other.value); + } + ['>='](other) { + return dart.notNull(this.value) >= dart.notNull(other.value); + } + compareTo(other) { + logging.Level._check(other); + return dart.notNull(this.value) - dart.notNull(other.value); + } + get hashCode() { + return this.value; + } + toString() { + return this.name; + } + }; + (logging.Level.new = function(name, value) { + this[name$2] = name; + this[value$] = value; + ; + }).prototype = logging.Level.prototype; + dart.addTypeTests(logging.Level); + const name$2 = Symbol("Level.name"); + const value$ = Symbol("Level.value"); + logging.Level[dart.implements] = () => [core.Comparable$(logging.Level)]; + dart.setMethodSignature(logging.Level, () => ({ + __proto__: dart.getMethods(logging.Level.__proto__), + _equals: dart.fnType(core.bool, [core.Object]), + [$_equals]: dart.fnType(core.bool, [core.Object]), + '<': dart.fnType(core.bool, [logging.Level]), + '<=': dart.fnType(core.bool, [logging.Level]), + '>': dart.fnType(core.bool, [logging.Level]), + '>=': dart.fnType(core.bool, [logging.Level]), + compareTo: dart.fnType(core.int, [core.Object]), + [$compareTo]: dart.fnType(core.int, [core.Object]) + })); + dart.setFieldSignature(logging.Level, () => ({ + __proto__: dart.getFields(logging.Level.__proto__), + name: dart.finalFieldType(core.String), + value: dart.finalFieldType(core.int) + })); + dart.defineExtensionMethods(logging.Level, ['_equals', 'compareTo', 'toString']); + dart.defineExtensionAccessors(logging.Level, ['hashCode']); + dart.defineLazy(logging.Level, { + /*logging.Level.ALL*/get ALL() { + return dart.const(new logging.Level.new("ALL", 0)); + }, + /*logging.Level.OFF*/get OFF() { + return dart.const(new logging.Level.new("OFF", 2000)); + }, + /*logging.Level.FINEST*/get FINEST() { + return dart.const(new logging.Level.new("FINEST", 300)); + }, + /*logging.Level.FINER*/get FINER() { + return dart.const(new logging.Level.new("FINER", 400)); + }, + /*logging.Level.FINE*/get FINE() { + return dart.const(new logging.Level.new("FINE", 500)); + }, + /*logging.Level.CONFIG*/get CONFIG() { + return dart.const(new logging.Level.new("CONFIG", 700)); + }, + /*logging.Level.INFO*/get INFO() { + return dart.const(new logging.Level.new("INFO", 800)); + }, + /*logging.Level.WARNING*/get WARNING() { + return dart.const(new logging.Level.new("WARNING", 900)); + }, + /*logging.Level.SEVERE*/get SEVERE() { + return dart.const(new logging.Level.new("SEVERE", 1000)); + }, + /*logging.Level.SHOUT*/get SHOUT() { + return dart.const(new logging.Level.new("SHOUT", 1200)); + }, + /*logging.Level.LEVELS*/get LEVELS() { + return dart.constList([logging.Level.ALL, logging.Level.FINEST, logging.Level.FINER, logging.Level.FINE, logging.Level.CONFIG, logging.Level.INFO, logging.Level.WARNING, logging.Level.SEVERE, logging.Level.SHOUT, logging.Level.OFF], logging.Level); + } + }); + logging.LogRecord = class LogRecord extends core.Object { + get level() { + return this[level$]; + } + set level(value) { + super.level = value; + } + get message() { + return this[message$0]; + } + set message(value) { + super.message = value; + } + get object() { + return this[object$]; + } + set object(value) { + super.object = value; + } + get loggerName() { + return this[loggerName$]; + } + set loggerName(value) { + super.loggerName = value; + } + get time() { + return this[time]; + } + set time(value) { + super.time = value; + } + get sequenceNumber() { + return this[sequenceNumber]; + } + set sequenceNumber(value) { + super.sequenceNumber = value; + } + get error() { + return this[error$0]; + } + set error(value) { + super.error = value; + } + get stackTrace() { + return this[stackTrace$0]; + } + set stackTrace(value) { + super.stackTrace = value; + } + get zone() { + return this[zone$]; + } + set zone(value) { + super.zone = value; + } + toString() { + return "[" + dart.str(this.level.name) + "] " + dart.str(this.loggerName) + ": " + dart.str(this.message); + } + }; + (logging.LogRecord.new = function(level, message, loggerName, error, stackTrace, zone, object) { + let t1; + if (error === void 0) error = null; + if (stackTrace === void 0) stackTrace = null; + if (zone === void 0) zone = null; + if (object === void 0) object = null; + this[level$] = level; + this[message$0] = message; + this[loggerName$] = loggerName; + this[error$0] = error; + this[stackTrace$0] = stackTrace; + this[zone$] = zone; + this[object$] = object; + this[time] = new core.DateTime.now(); + this[sequenceNumber] = (t1 = logging.LogRecord._nextNumber, logging.LogRecord._nextNumber = dart.notNull(t1) + 1, t1); + ; + }).prototype = logging.LogRecord.prototype; + dart.addTypeTests(logging.LogRecord); + const level$ = Symbol("LogRecord.level"); + const message$0 = Symbol("LogRecord.message"); + const object$ = Symbol("LogRecord.object"); + const loggerName$ = Symbol("LogRecord.loggerName"); + const time = Symbol("LogRecord.time"); + const sequenceNumber = Symbol("LogRecord.sequenceNumber"); + const error$0 = Symbol("LogRecord.error"); + const stackTrace$0 = Symbol("LogRecord.stackTrace"); + const zone$ = Symbol("LogRecord.zone"); + dart.setFieldSignature(logging.LogRecord, () => ({ + __proto__: dart.getFields(logging.LogRecord.__proto__), + level: dart.finalFieldType(logging.Level), + message: dart.finalFieldType(core.String), + object: dart.finalFieldType(core.Object), + loggerName: dart.finalFieldType(core.String), + time: dart.finalFieldType(core.DateTime), + sequenceNumber: dart.finalFieldType(core.int), + error: dart.finalFieldType(core.Object), + stackTrace: dart.finalFieldType(core.StackTrace), + zone: dart.finalFieldType(async.Zone) + })); + dart.defineExtensionMethods(logging.LogRecord, ['toString']); + dart.defineLazy(logging.LogRecord, { + /*logging.LogRecord._nextNumber*/get _nextNumber() { + return 0; + }, + set _nextNumber(_) {} + }); + logging.LoggerHandler = dart.typedef('LoggerHandler', () => LogRecordTovoid()); + dart.defineLazy(logging, { + /*logging.hierarchicalLoggingEnabled*/get hierarchicalLoggingEnabled() { + return false; + }, + set hierarchicalLoggingEnabled(_) {}, + /*logging.recordStackTraceAtLevel*/get recordStackTraceAtLevel() { + return logging.Level.OFF; + }, + set recordStackTraceAtLevel(_) {}, + /*logging._rootLevel*/get _rootLevel() { + return logging.Level.INFO; + }, + set _rootLevel(_) {} + }); + src__util.matchingAnnotation = function(metadata, T) { + for (let metaDatum of metadata) { + if (dart.equals(metaDatum.type.reflectedType, T)) { + return metaDatum.reflectee; + } + } + return null; + }; + src__util.getAnnotation = function(obj, T, reflector) { + if (reflector == null) { + return null; + } else { + if (core.Function.is(obj)) { + let methodMirror = reflector.reflectFunction(obj); + return src__util.matchingAnnotation(methodMirror.annotations, T); + } else { + let classMirror = reflector.reflectClass(dart.runtimeType(obj)); + return src__util.matchingAnnotation(classMirror.annotations, T); + } + } + }; + dart.defineLazy(src__util, { + /*src__util.straySlashes*/get straySlashes() { + return core.RegExp.new("(^/+)|(/+$)"); + } + }); + meta.Immutable = class Immutable extends core.Object { + get reason() { + return this[reason$]; + } + set reason(value) { + super.reason = value; + } + }; + (meta.Immutable.new = function(reason) { + if (reason === void 0) reason = null; + this[reason$] = reason; + ; + }).prototype = meta.Immutable.prototype; + dart.addTypeTests(meta.Immutable); + const reason$ = Symbol("Immutable.reason"); + dart.setFieldSignature(meta.Immutable, () => ({ + __proto__: dart.getFields(meta.Immutable.__proto__), + reason: dart.finalFieldType(core.String) + })); + meta.Required = class Required extends core.Object { + get reason() { + return this[reason$0]; + } + set reason(value) { + super.reason = value; + } + }; + (meta.Required.new = function(reason) { + if (reason === void 0) reason = null; + this[reason$0] = reason; + ; + }).prototype = meta.Required.prototype; + dart.addTypeTests(meta.Required); + const reason$0 = Symbol("Required.reason"); + dart.setFieldSignature(meta.Required, () => ({ + __proto__: dart.getFields(meta.Required.__proto__), + reason: dart.finalFieldType(core.String) + })); + meta._AlwaysThrows = class _AlwaysThrows extends core.Object {}; + (meta._AlwaysThrows.new = function() { + ; + }).prototype = meta._AlwaysThrows.prototype; + dart.addTypeTests(meta._AlwaysThrows); + meta._Checked = class _Checked extends core.Object {}; + (meta._Checked.new = function() { + ; + }).prototype = meta._Checked.prototype; + dart.addTypeTests(meta._Checked); + meta._Experimental = class _Experimental extends core.Object {}; + (meta._Experimental.new = function() { + ; + }).prototype = meta._Experimental.prototype; + dart.addTypeTests(meta._Experimental); + meta._Factory = class _Factory extends core.Object {}; + (meta._Factory.new = function() { + ; + }).prototype = meta._Factory.prototype; + dart.addTypeTests(meta._Factory); + meta._IsTest = class _IsTest extends core.Object {}; + (meta._IsTest.new = function() { + ; + }).prototype = meta._IsTest.prototype; + dart.addTypeTests(meta._IsTest); + meta._IsTestGroup = class _IsTestGroup extends core.Object {}; + (meta._IsTestGroup.new = function() { + ; + }).prototype = meta._IsTestGroup.prototype; + dart.addTypeTests(meta._IsTestGroup); + meta._Literal = class _Literal extends core.Object {}; + (meta._Literal.new = function() { + ; + }).prototype = meta._Literal.prototype; + dart.addTypeTests(meta._Literal); + meta._MustCallSuper = class _MustCallSuper extends core.Object {}; + (meta._MustCallSuper.new = function() { + ; + }).prototype = meta._MustCallSuper.prototype; + dart.addTypeTests(meta._MustCallSuper); + meta._OptionalTypeArgs = class _OptionalTypeArgs extends core.Object {}; + (meta._OptionalTypeArgs.new = function() { + ; + }).prototype = meta._OptionalTypeArgs.prototype; + dart.addTypeTests(meta._OptionalTypeArgs); + meta._Protected = class _Protected extends core.Object {}; + (meta._Protected.new = function() { + ; + }).prototype = meta._Protected.prototype; + dart.addTypeTests(meta._Protected); + meta._Virtual = class _Virtual extends core.Object {}; + (meta._Virtual.new = function() { + ; + }).prototype = meta._Virtual.prototype; + dart.addTypeTests(meta._Virtual); + meta._VisibleForOverriding = class _VisibleForOverriding extends core.Object {}; + (meta._VisibleForOverriding.new = function() { + ; + }).prototype = meta._VisibleForOverriding.prototype; + dart.addTypeTests(meta._VisibleForOverriding); + meta._VisibleForTesting = class _VisibleForTesting extends core.Object {}; + (meta._VisibleForTesting.new = function() { + ; + }).prototype = meta._VisibleForTesting.prototype; + dart.addTypeTests(meta._VisibleForTesting); + dart.defineLazy(meta, { + /*meta.alwaysThrows*/get alwaysThrows() { + return dart.const(new meta._AlwaysThrows.new()); + }, + /*meta.checked*/get checked() { + return dart.const(new meta._Checked.new()); + }, + /*meta.experimental*/get experimental() { + return dart.const(new meta._Experimental.new()); + }, + /*meta.factory*/get factory() { + return dart.const(new meta._Factory.new()); + }, + /*meta.immutable*/get immutable() { + return dart.const(new meta.Immutable.new()); + }, + /*meta.isTest*/get isTest() { + return dart.const(new meta._IsTest.new()); + }, + /*meta.isTestGroup*/get isTestGroup() { + return dart.const(new meta._IsTestGroup.new()); + }, + /*meta.literal*/get literal() { + return dart.const(new meta._Literal.new()); + }, + /*meta.mustCallSuper*/get mustCallSuper() { + return dart.const(new meta._MustCallSuper.new()); + }, + /*meta.optionalTypeArgs*/get optionalTypeArgs() { + return dart.const(new meta._OptionalTypeArgs.new()); + }, + /*meta.protected*/get protected() { + return dart.const(new meta._Protected.new()); + }, + /*meta.required*/get required() { + return dart.const(new meta.Required.new()); + }, + /*meta.virtual*/get virtual() { + return dart.const(new meta._Virtual.new()); + }, + /*meta.visibleForOverriding*/get visibleForOverriding() { + return dart.const(new meta._VisibleForOverriding.new()); + }, + /*meta.visibleForTesting*/get visibleForTesting() { + return dart.const(new meta._VisibleForTesting.new()); + } + }); + path$.absolute = function(part1, part2, part3, part4, part5, part6, part7) { + if (part2 === void 0) part2 = null; + if (part3 === void 0) part3 = null; + if (part4 === void 0) part4 = null; + if (part5 === void 0) part5 = null; + if (part6 === void 0) part6 = null; + if (part7 === void 0) part7 = null; + return path$.context.absolute(part1, part2, part3, part4, part5, part6, part7); + }; + path$.basename = function(path) { + return path$.context.basename(path); + }; + path$.basenameWithoutExtension = function(path) { + return path$.context.basenameWithoutExtension(path); + }; + path$.dirname = function(path) { + return path$.context.dirname(path); + }; + path$.extension = function(path) { + return path$.context.extension(path); + }; + path$.rootPrefix = function(path) { + return path$.context.rootPrefix(path); + }; + path$.isAbsolute = function(path) { + return path$.context.isAbsolute(path); + }; + path$.isRelative = function(path) { + return path$.context.isRelative(path); + }; + path$.isRootRelative = function(path) { + return path$.context.isRootRelative(path); + }; + path$.join = function(part1, part2, part3, part4, part5, part6, part7, part8) { + if (part2 === void 0) part2 = null; + if (part3 === void 0) part3 = null; + if (part4 === void 0) part4 = null; + if (part5 === void 0) part5 = null; + if (part6 === void 0) part6 = null; + if (part7 === void 0) part7 = null; + if (part8 === void 0) part8 = null; + return path$.context.join(part1, part2, part3, part4, part5, part6, part7, part8); + }; + path$.joinAll = function(parts) { + return path$.context.joinAll(parts); + }; + path$.split = function(path) { + return path$.context.split(path); + }; + path$.canonicalize = function(path) { + return path$.context.canonicalize(path); + }; + path$.normalize = function(path) { + return path$.context.normalize(path); + }; + path$.relative = function(path, opts) { + let from = opts && 'from' in opts ? opts.from : null; + return path$.context.relative(path, {from: from}); + }; + path$.isWithin = function(parent, child) { + return path$.context.isWithin(parent, child); + }; + path$.equals = function(path1, path2) { + return path$.context.equals(path1, path2); + }; + path$.hash = function(path) { + return path$.context.hash(path); + }; + path$.withoutExtension = function(path) { + return path$.context.withoutExtension(path); + }; + path$.setExtension = function(path, extension) { + return path$.context.setExtension(path, extension); + }; + path$.fromUri = function(uri) { + return path$.context.fromUri(uri); + }; + path$.toUri = function(path) { + return path$.context.toUri(path); + }; + path$.prettyUri = function(uri) { + return path$.context.prettyUri(uri); + }; + dart.copyProperties(path$, { + get style() { + return path$.context.style; + }, + get current() { + let uri = core.Uri.base; + if (dart.equals(uri, path$._currentUriBase)) return path$._current; + path$._currentUriBase = uri; + if (dart.equals(src__style.Style.platform, src__style.Style.url)) { + path$._current = dart.toString(uri.resolve(".")); + return path$._current; + } else { + let path = uri.toFilePath(); + let lastIndex = path.length - 1; + if (!(path[$_get](lastIndex) === "/" || path[$_get](lastIndex) === "\\")) dart.assertFailed(); + path$._current = lastIndex === 0 ? path : path[$substring](0, lastIndex); + return path$._current; + } + }, + get separator() { + return path$.context.separator; + } + }); + dart.defineLazy(path$, { + /*path$.posix*/get posix() { + return src__context.Context.new({style: src__style.Style.posix}); + }, + /*path$.windows*/get windows() { + return src__context.Context.new({style: src__style.Style.windows}); + }, + /*path$.url*/get url() { + return src__context.Context.new({style: src__style.Style.url}); + }, + /*path$.context*/get context() { + return src__context.createInternal(); + }, + /*path$._currentUriBase*/get _currentUriBase() { + return null; + }, + set _currentUriBase(_) {}, + /*path$._current*/get _current() { + return null; + }, + set _current(_) {} + }); + const _is_Tuple2_default = Symbol('_is_Tuple2_default'); + tuple.Tuple2$ = dart.generic((T1, T2) => { + let Tuple2OfT1$T2 = () => (Tuple2OfT1$T2 = dart.constFn(tuple.Tuple2$(T1, T2)))(); + class Tuple2 extends core.Object { + get item1() { + return this[item1$]; + } + set item1(value) { + super.item1 = value; + } + get item2() { + return this[item2$]; + } + set item2(value) { + super.item2 = value; + } + static fromList(items) { + if (items[$length] !== 2) { + dart.throw(new core.ArgumentError.new("items must have length 2")); + } + return new (tuple.Tuple2$(T1, T2)).new(T1.as(items[$_get](0)), T2.as(items[$_get](1))); + } + withItem1(v) { + T1._check(v); + return new (Tuple2OfT1$T2()).new(v, this.item2); + } + withItem2(v) { + T2._check(v); + return new (Tuple2OfT1$T2()).new(this.item1, v); + } + toList(opts) { + let growable = opts && 'growable' in opts ? opts.growable : false; + return core.List.from([this.item1, this.item2], {growable: growable}); + } + toString() { + return "[" + dart.str(this.item1) + ", " + dart.str(this.item2) + "]"; + } + _equals(o) { + if (o == null) return false; + return tuple.Tuple2.is(o) && dart.equals(o.item1, this.item1) && dart.equals(o.item2, this.item2); + } + get hashCode() { + return core$.hash2(dart.hashCode(this.item1), dart.hashCode(this.item2)); + } + } + (Tuple2.new = function(item1, item2) { + this[item1$] = item1; + this[item2$] = item2; + ; + }).prototype = Tuple2.prototype; + dart.addTypeTests(Tuple2); + Tuple2.prototype[_is_Tuple2_default] = true; + const item1$ = Symbol("Tuple2.item1"); + const item2$ = Symbol("Tuple2.item2"); + dart.setMethodSignature(Tuple2, () => ({ + __proto__: dart.getMethods(Tuple2.__proto__), + withItem1: dart.fnType(tuple.Tuple2$(T1, T2), [core.Object]), + withItem2: dart.fnType(tuple.Tuple2$(T1, T2), [core.Object]), + toList: dart.fnType(core.List, [], {growable: core.bool}) + })); + dart.setFieldSignature(Tuple2, () => ({ + __proto__: dart.getFields(Tuple2.__proto__), + item1: dart.finalFieldType(T1), + item2: dart.finalFieldType(T2) + })); + dart.defineExtensionMethods(Tuple2, ['toString', '_equals']); + dart.defineExtensionAccessors(Tuple2, ['hashCode']); + return Tuple2; + }); + tuple.Tuple2 = tuple.Tuple2$(); + dart.addTypeTests(tuple.Tuple2, _is_Tuple2_default); + const _is_Tuple3_default = Symbol('_is_Tuple3_default'); + tuple.Tuple3$ = dart.generic((T1, T2, T3) => { + let Tuple3OfT1$T2$T3 = () => (Tuple3OfT1$T2$T3 = dart.constFn(tuple.Tuple3$(T1, T2, T3)))(); + class Tuple3 extends core.Object { + get item1() { + return this[item1$]; + } + set item1(value) { + super.item1 = value; + } + get item2() { + return this[item2$]; + } + set item2(value) { + super.item2 = value; + } + get item3() { + return this[item3$]; + } + set item3(value) { + super.item3 = value; + } + static fromList(items) { + if (items[$length] !== 3) { + dart.throw(new core.ArgumentError.new("items must have length 3")); + } + return new (tuple.Tuple3$(T1, T2, T3)).new(T1.as(items[$_get](0)), T2.as(items[$_get](1)), T3.as(items[$_get](2))); + } + withItem1(v) { + T1._check(v); + return new (Tuple3OfT1$T2$T3()).new(v, this.item2, this.item3); + } + withItem2(v) { + T2._check(v); + return new (Tuple3OfT1$T2$T3()).new(this.item1, v, this.item3); + } + withItem3(v) { + T3._check(v); + return new (Tuple3OfT1$T2$T3()).new(this.item1, this.item2, v); + } + toList(opts) { + let growable = opts && 'growable' in opts ? opts.growable : false; + return core.List.from([this.item1, this.item2, this.item3], {growable: growable}); + } + toString() { + return "[" + dart.str(this.item1) + ", " + dart.str(this.item2) + ", " + dart.str(this.item3) + "]"; + } + _equals(o) { + if (o == null) return false; + return tuple.Tuple3.is(o) && dart.equals(o.item1, this.item1) && dart.equals(o.item2, this.item2) && dart.equals(o.item3, this.item3); + } + get hashCode() { + return core$.hash3(dart.hashCode(this.item1), dart.hashCode(this.item2), dart.hashCode(this.item3)); + } + } + (Tuple3.new = function(item1, item2, item3) { + this[item1$] = item1; + this[item2$] = item2; + this[item3$] = item3; + ; + }).prototype = Tuple3.prototype; + dart.addTypeTests(Tuple3); + Tuple3.prototype[_is_Tuple3_default] = true; + const item1$ = Symbol("Tuple3.item1"); + const item2$ = Symbol("Tuple3.item2"); + const item3$ = Symbol("Tuple3.item3"); + dart.setMethodSignature(Tuple3, () => ({ + __proto__: dart.getMethods(Tuple3.__proto__), + withItem1: dart.fnType(tuple.Tuple3$(T1, T2, T3), [core.Object]), + withItem2: dart.fnType(tuple.Tuple3$(T1, T2, T3), [core.Object]), + withItem3: dart.fnType(tuple.Tuple3$(T1, T2, T3), [core.Object]), + toList: dart.fnType(core.List, [], {growable: core.bool}) + })); + dart.setFieldSignature(Tuple3, () => ({ + __proto__: dart.getFields(Tuple3.__proto__), + item1: dart.finalFieldType(T1), + item2: dart.finalFieldType(T2), + item3: dart.finalFieldType(T3) + })); + dart.defineExtensionMethods(Tuple3, ['toString', '_equals']); + dart.defineExtensionAccessors(Tuple3, ['hashCode']); + return Tuple3; + }); + tuple.Tuple3 = tuple.Tuple3$(); + dart.addTypeTests(tuple.Tuple3, _is_Tuple3_default); + const _is_Tuple4_default = Symbol('_is_Tuple4_default'); + tuple.Tuple4$ = dart.generic((T1, T2, T3, T4) => { + let Tuple4OfT1$T2$T3$T4 = () => (Tuple4OfT1$T2$T3$T4 = dart.constFn(tuple.Tuple4$(T1, T2, T3, T4)))(); + class Tuple4 extends core.Object { + get item1() { + return this[item1$]; + } + set item1(value) { + super.item1 = value; + } + get item2() { + return this[item2$]; + } + set item2(value) { + super.item2 = value; + } + get item3() { + return this[item3$]; + } + set item3(value) { + super.item3 = value; + } + get item4() { + return this[item4$]; + } + set item4(value) { + super.item4 = value; + } + static fromList(items) { + if (items[$length] !== 4) { + dart.throw(new core.ArgumentError.new("items must have length 4")); + } + return new (tuple.Tuple4$(T1, T2, T3, T4)).new(T1.as(items[$_get](0)), T2.as(items[$_get](1)), T3.as(items[$_get](2)), T4.as(items[$_get](3))); + } + withItem1(v) { + T1._check(v); + return new (Tuple4OfT1$T2$T3$T4()).new(v, this.item2, this.item3, this.item4); + } + withItem2(v) { + T2._check(v); + return new (Tuple4OfT1$T2$T3$T4()).new(this.item1, v, this.item3, this.item4); + } + withItem3(v) { + T3._check(v); + return new (Tuple4OfT1$T2$T3$T4()).new(this.item1, this.item2, v, this.item4); + } + withItem4(v) { + T4._check(v); + return new (Tuple4OfT1$T2$T3$T4()).new(this.item1, this.item2, this.item3, v); + } + toList(opts) { + let growable = opts && 'growable' in opts ? opts.growable : false; + return core.List.from([this.item1, this.item2, this.item3, this.item4], {growable: growable}); + } + toString() { + return "[" + dart.str(this.item1) + ", " + dart.str(this.item2) + ", " + dart.str(this.item3) + ", " + dart.str(this.item4) + "]"; + } + _equals(o) { + if (o == null) return false; + return tuple.Tuple4.is(o) && dart.equals(o.item1, this.item1) && dart.equals(o.item2, this.item2) && dart.equals(o.item3, this.item3) && dart.equals(o.item4, this.item4); + } + get hashCode() { + return core$.hash4(dart.hashCode(this.item1), dart.hashCode(this.item2), dart.hashCode(this.item3), dart.hashCode(this.item4)); + } + } + (Tuple4.new = function(item1, item2, item3, item4) { + this[item1$] = item1; + this[item2$] = item2; + this[item3$] = item3; + this[item4$] = item4; + ; + }).prototype = Tuple4.prototype; + dart.addTypeTests(Tuple4); + Tuple4.prototype[_is_Tuple4_default] = true; + const item1$ = Symbol("Tuple4.item1"); + const item2$ = Symbol("Tuple4.item2"); + const item3$ = Symbol("Tuple4.item3"); + const item4$ = Symbol("Tuple4.item4"); + dart.setMethodSignature(Tuple4, () => ({ + __proto__: dart.getMethods(Tuple4.__proto__), + withItem1: dart.fnType(tuple.Tuple4$(T1, T2, T3, T4), [core.Object]), + withItem2: dart.fnType(tuple.Tuple4$(T1, T2, T3, T4), [core.Object]), + withItem3: dart.fnType(tuple.Tuple4$(T1, T2, T3, T4), [core.Object]), + withItem4: dart.fnType(tuple.Tuple4$(T1, T2, T3, T4), [core.Object]), + toList: dart.fnType(core.List, [], {growable: core.bool}) + })); + dart.setFieldSignature(Tuple4, () => ({ + __proto__: dart.getFields(Tuple4.__proto__), + item1: dart.finalFieldType(T1), + item2: dart.finalFieldType(T2), + item3: dart.finalFieldType(T3), + item4: dart.finalFieldType(T4) + })); + dart.defineExtensionMethods(Tuple4, ['toString', '_equals']); + dart.defineExtensionAccessors(Tuple4, ['hashCode']); + return Tuple4; + }); + tuple.Tuple4 = tuple.Tuple4$(); + dart.addTypeTests(tuple.Tuple4, _is_Tuple4_default); + const _is_Tuple5_default = Symbol('_is_Tuple5_default'); + tuple.Tuple5$ = dart.generic((T1, T2, T3, T4, T5) => { + let Tuple5OfT1$T2$T3$T4$T5 = () => (Tuple5OfT1$T2$T3$T4$T5 = dart.constFn(tuple.Tuple5$(T1, T2, T3, T4, T5)))(); + class Tuple5 extends core.Object { + get item1() { + return this[item1$]; + } + set item1(value) { + super.item1 = value; + } + get item2() { + return this[item2$]; + } + set item2(value) { + super.item2 = value; + } + get item3() { + return this[item3$]; + } + set item3(value) { + super.item3 = value; + } + get item4() { + return this[item4$]; + } + set item4(value) { + super.item4 = value; + } + get item5() { + return this[item5$]; + } + set item5(value) { + super.item5 = value; + } + static fromList(items) { + if (items[$length] !== 5) { + dart.throw(new core.ArgumentError.new("items must have length 5")); + } + return new (tuple.Tuple5$(T1, T2, T3, T4, T5)).new(T1.as(items[$_get](0)), T2.as(items[$_get](1)), T3.as(items[$_get](2)), T4.as(items[$_get](3)), T5.as(items[$_get](4))); + } + withItem1(v) { + T1._check(v); + return new (Tuple5OfT1$T2$T3$T4$T5()).new(v, this.item2, this.item3, this.item4, this.item5); + } + withItem2(v) { + T2._check(v); + return new (Tuple5OfT1$T2$T3$T4$T5()).new(this.item1, v, this.item3, this.item4, this.item5); + } + withItem3(v) { + T3._check(v); + return new (Tuple5OfT1$T2$T3$T4$T5()).new(this.item1, this.item2, v, this.item4, this.item5); + } + withItem4(v) { + T4._check(v); + return new (Tuple5OfT1$T2$T3$T4$T5()).new(this.item1, this.item2, this.item3, v, this.item5); + } + withItem5(v) { + T5._check(v); + return new (Tuple5OfT1$T2$T3$T4$T5()).new(this.item1, this.item2, this.item3, this.item4, v); + } + toList(opts) { + let growable = opts && 'growable' in opts ? opts.growable : false; + return core.List.from([this.item1, this.item2, this.item3, this.item4, this.item5], {growable: growable}); + } + toString() { + return "[" + dart.str(this.item1) + ", " + dart.str(this.item2) + ", " + dart.str(this.item3) + ", " + dart.str(this.item4) + ", " + dart.str(this.item5) + "]"; + } + _equals(o) { + if (o == null) return false; + return tuple.Tuple5.is(o) && dart.equals(o.item1, this.item1) && dart.equals(o.item2, this.item2) && dart.equals(o.item3, this.item3) && dart.equals(o.item4, this.item4) && dart.equals(o.item5, this.item5); + } + get hashCode() { + return core$.hashObjects([dart.hashCode(this.item1), dart.hashCode(this.item2), dart.hashCode(this.item3), dart.hashCode(this.item4), dart.hashCode(this.item5)]); + } + } + (Tuple5.new = function(item1, item2, item3, item4, item5) { + this[item1$] = item1; + this[item2$] = item2; + this[item3$] = item3; + this[item4$] = item4; + this[item5$] = item5; + ; + }).prototype = Tuple5.prototype; + dart.addTypeTests(Tuple5); + Tuple5.prototype[_is_Tuple5_default] = true; + const item1$ = Symbol("Tuple5.item1"); + const item2$ = Symbol("Tuple5.item2"); + const item3$ = Symbol("Tuple5.item3"); + const item4$ = Symbol("Tuple5.item4"); + const item5$ = Symbol("Tuple5.item5"); + dart.setMethodSignature(Tuple5, () => ({ + __proto__: dart.getMethods(Tuple5.__proto__), + withItem1: dart.fnType(tuple.Tuple5$(T1, T2, T3, T4, T5), [core.Object]), + withItem2: dart.fnType(tuple.Tuple5$(T1, T2, T3, T4, T5), [core.Object]), + withItem3: dart.fnType(tuple.Tuple5$(T1, T2, T3, T4, T5), [core.Object]), + withItem4: dart.fnType(tuple.Tuple5$(T1, T2, T3, T4, T5), [core.Object]), + withItem5: dart.fnType(tuple.Tuple5$(T1, T2, T3, T4, T5), [core.Object]), + toList: dart.fnType(core.List, [], {growable: core.bool}) + })); + dart.setFieldSignature(Tuple5, () => ({ + __proto__: dart.getFields(Tuple5.__proto__), + item1: dart.finalFieldType(T1), + item2: dart.finalFieldType(T2), + item3: dart.finalFieldType(T3), + item4: dart.finalFieldType(T4), + item5: dart.finalFieldType(T5) + })); + dart.defineExtensionMethods(Tuple5, ['toString', '_equals']); + dart.defineExtensionAccessors(Tuple5, ['hashCode']); + return Tuple5; + }); + tuple.Tuple5 = tuple.Tuple5$(); + dart.addTypeTests(tuple.Tuple5, _is_Tuple5_default); + const _is_Tuple6_default = Symbol('_is_Tuple6_default'); + tuple.Tuple6$ = dart.generic((T1, T2, T3, T4, T5, T6) => { + let Tuple6OfT1$T2$T3$T4$T5$T6 = () => (Tuple6OfT1$T2$T3$T4$T5$T6 = dart.constFn(tuple.Tuple6$(T1, T2, T3, T4, T5, T6)))(); + class Tuple6 extends core.Object { + get item1() { + return this[item1$]; + } + set item1(value) { + super.item1 = value; + } + get item2() { + return this[item2$]; + } + set item2(value) { + super.item2 = value; + } + get item3() { + return this[item3$]; + } + set item3(value) { + super.item3 = value; + } + get item4() { + return this[item4$]; + } + set item4(value) { + super.item4 = value; + } + get item5() { + return this[item5$]; + } + set item5(value) { + super.item5 = value; + } + get item6() { + return this[item6$]; + } + set item6(value) { + super.item6 = value; + } + static fromList(items) { + if (items[$length] !== 6) { + dart.throw(new core.ArgumentError.new("items must have length 6")); + } + return new (tuple.Tuple6$(T1, T2, T3, T4, T5, T6)).new(T1.as(items[$_get](0)), T2.as(items[$_get](1)), T3.as(items[$_get](2)), T4.as(items[$_get](3)), T5.as(items[$_get](4)), T6.as(items[$_get](5))); + } + withItem1(v) { + T1._check(v); + return new (Tuple6OfT1$T2$T3$T4$T5$T6()).new(v, this.item2, this.item3, this.item4, this.item5, this.item6); + } + withItem2(v) { + T2._check(v); + return new (Tuple6OfT1$T2$T3$T4$T5$T6()).new(this.item1, v, this.item3, this.item4, this.item5, this.item6); + } + withItem3(v) { + T3._check(v); + return new (Tuple6OfT1$T2$T3$T4$T5$T6()).new(this.item1, this.item2, v, this.item4, this.item5, this.item6); + } + withItem4(v) { + T4._check(v); + return new (Tuple6OfT1$T2$T3$T4$T5$T6()).new(this.item1, this.item2, this.item3, v, this.item5, this.item6); + } + withItem5(v) { + T5._check(v); + return new (Tuple6OfT1$T2$T3$T4$T5$T6()).new(this.item1, this.item2, this.item3, this.item4, v, this.item6); + } + withItem6(v) { + T6._check(v); + return new (Tuple6OfT1$T2$T3$T4$T5$T6()).new(this.item1, this.item2, this.item3, this.item4, this.item5, v); + } + toList(opts) { + let growable = opts && 'growable' in opts ? opts.growable : false; + return core.List.from([this.item1, this.item2, this.item3, this.item4, this.item5, this.item6], {growable: growable}); + } + toString() { + return "[" + dart.str(this.item1) + ", " + dart.str(this.item2) + ", " + dart.str(this.item3) + ", " + dart.str(this.item4) + ", " + dart.str(this.item5) + ", " + dart.str(this.item6) + "]"; + } + _equals(o) { + if (o == null) return false; + return tuple.Tuple6.is(o) && dart.equals(o.item1, this.item1) && dart.equals(o.item2, this.item2) && dart.equals(o.item3, this.item3) && dart.equals(o.item4, this.item4) && dart.equals(o.item5, this.item5) && dart.equals(o.item6, this.item6); + } + get hashCode() { + return core$.hashObjects([dart.hashCode(this.item1), dart.hashCode(this.item2), dart.hashCode(this.item3), dart.hashCode(this.item4), dart.hashCode(this.item5), dart.hashCode(this.item6)]); + } + } + (Tuple6.new = function(item1, item2, item3, item4, item5, item6) { + this[item1$] = item1; + this[item2$] = item2; + this[item3$] = item3; + this[item4$] = item4; + this[item5$] = item5; + this[item6$] = item6; + ; + }).prototype = Tuple6.prototype; + dart.addTypeTests(Tuple6); + Tuple6.prototype[_is_Tuple6_default] = true; + const item1$ = Symbol("Tuple6.item1"); + const item2$ = Symbol("Tuple6.item2"); + const item3$ = Symbol("Tuple6.item3"); + const item4$ = Symbol("Tuple6.item4"); + const item5$ = Symbol("Tuple6.item5"); + const item6$ = Symbol("Tuple6.item6"); + dart.setMethodSignature(Tuple6, () => ({ + __proto__: dart.getMethods(Tuple6.__proto__), + withItem1: dart.fnType(tuple.Tuple6$(T1, T2, T3, T4, T5, T6), [core.Object]), + withItem2: dart.fnType(tuple.Tuple6$(T1, T2, T3, T4, T5, T6), [core.Object]), + withItem3: dart.fnType(tuple.Tuple6$(T1, T2, T3, T4, T5, T6), [core.Object]), + withItem4: dart.fnType(tuple.Tuple6$(T1, T2, T3, T4, T5, T6), [core.Object]), + withItem5: dart.fnType(tuple.Tuple6$(T1, T2, T3, T4, T5, T6), [core.Object]), + withItem6: dart.fnType(tuple.Tuple6$(T1, T2, T3, T4, T5, T6), [core.Object]), + toList: dart.fnType(core.List, [], {growable: core.bool}) + })); + dart.setFieldSignature(Tuple6, () => ({ + __proto__: dart.getFields(Tuple6.__proto__), + item1: dart.finalFieldType(T1), + item2: dart.finalFieldType(T2), + item3: dart.finalFieldType(T3), + item4: dart.finalFieldType(T4), + item5: dart.finalFieldType(T5), + item6: dart.finalFieldType(T6) + })); + dart.defineExtensionMethods(Tuple6, ['toString', '_equals']); + dart.defineExtensionAccessors(Tuple6, ['hashCode']); + return Tuple6; + }); + tuple.Tuple6 = tuple.Tuple6$(); + dart.addTypeTests(tuple.Tuple6, _is_Tuple6_default); + const _is_Tuple7_default = Symbol('_is_Tuple7_default'); + tuple.Tuple7$ = dart.generic((T1, T2, T3, T4, T5, T6, T7) => { + let Tuple7OfT1$T2$T3$T4$T5$T6$T7 = () => (Tuple7OfT1$T2$T3$T4$T5$T6$T7 = dart.constFn(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7)))(); + class Tuple7 extends core.Object { + get item1() { + return this[item1$]; + } + set item1(value) { + super.item1 = value; + } + get item2() { + return this[item2$]; + } + set item2(value) { + super.item2 = value; + } + get item3() { + return this[item3$]; + } + set item3(value) { + super.item3 = value; + } + get item4() { + return this[item4$]; + } + set item4(value) { + super.item4 = value; + } + get item5() { + return this[item5$]; + } + set item5(value) { + super.item5 = value; + } + get item6() { + return this[item6$]; + } + set item6(value) { + super.item6 = value; + } + get item7() { + return this[item7$]; + } + set item7(value) { + super.item7 = value; + } + static fromList(items) { + if (items[$length] !== 7) { + dart.throw(new core.ArgumentError.new("items must have length 7")); + } + return new (tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7)).new(T1.as(items[$_get](0)), T2.as(items[$_get](1)), T3.as(items[$_get](2)), T4.as(items[$_get](3)), T5.as(items[$_get](4)), T6.as(items[$_get](5)), T7.as(items[$_get](6))); + } + withItem1(v) { + T1._check(v); + return new (Tuple7OfT1$T2$T3$T4$T5$T6$T7()).new(v, this.item2, this.item3, this.item4, this.item5, this.item6, this.item7); + } + withItem2(v) { + T2._check(v); + return new (Tuple7OfT1$T2$T3$T4$T5$T6$T7()).new(this.item1, v, this.item3, this.item4, this.item5, this.item6, this.item7); + } + withItem3(v) { + T3._check(v); + return new (Tuple7OfT1$T2$T3$T4$T5$T6$T7()).new(this.item1, this.item2, v, this.item4, this.item5, this.item6, this.item7); + } + withItem4(v) { + T4._check(v); + return new (Tuple7OfT1$T2$T3$T4$T5$T6$T7()).new(this.item1, this.item2, this.item3, v, this.item5, this.item6, this.item7); + } + withItem5(v) { + T5._check(v); + return new (Tuple7OfT1$T2$T3$T4$T5$T6$T7()).new(this.item1, this.item2, this.item3, this.item4, v, this.item6, this.item7); + } + withItem6(v) { + T6._check(v); + return new (Tuple7OfT1$T2$T3$T4$T5$T6$T7()).new(this.item1, this.item2, this.item3, this.item4, this.item5, v, this.item7); + } + withItem7(v) { + T7._check(v); + return new (Tuple7OfT1$T2$T3$T4$T5$T6$T7()).new(this.item1, this.item2, this.item3, this.item4, this.item5, this.item6, v); + } + toList(opts) { + let growable = opts && 'growable' in opts ? opts.growable : false; + return core.List.from([this.item1, this.item2, this.item3, this.item4, this.item5, this.item6, this.item7], {growable: growable}); + } + toString() { + return "[" + dart.str(this.item1) + ", " + dart.str(this.item2) + ", " + dart.str(this.item3) + ", " + dart.str(this.item4) + ", " + dart.str(this.item5) + ", " + dart.str(this.item6) + ", " + dart.str(this.item7) + "]"; + } + _equals(o) { + if (o == null) return false; + return tuple.Tuple7.is(o) && dart.equals(o.item1, this.item1) && dart.equals(o.item2, this.item2) && dart.equals(o.item3, this.item3) && dart.equals(o.item4, this.item4) && dart.equals(o.item5, this.item5) && dart.equals(o.item5, this.item6) && dart.equals(o.item6, this.item7); + } + get hashCode() { + return core$.hashObjects([dart.hashCode(this.item1), dart.hashCode(this.item2), dart.hashCode(this.item3), dart.hashCode(this.item4), dart.hashCode(this.item5), dart.hashCode(this.item6), dart.hashCode(this.item7)]); + } + } + (Tuple7.new = function(item1, item2, item3, item4, item5, item6, item7) { + this[item1$] = item1; + this[item2$] = item2; + this[item3$] = item3; + this[item4$] = item4; + this[item5$] = item5; + this[item6$] = item6; + this[item7$] = item7; + ; + }).prototype = Tuple7.prototype; + dart.addTypeTests(Tuple7); + Tuple7.prototype[_is_Tuple7_default] = true; + const item1$ = Symbol("Tuple7.item1"); + const item2$ = Symbol("Tuple7.item2"); + const item3$ = Symbol("Tuple7.item3"); + const item4$ = Symbol("Tuple7.item4"); + const item5$ = Symbol("Tuple7.item5"); + const item6$ = Symbol("Tuple7.item6"); + const item7$ = Symbol("Tuple7.item7"); + dart.setMethodSignature(Tuple7, () => ({ + __proto__: dart.getMethods(Tuple7.__proto__), + withItem1: dart.fnType(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7), [core.Object]), + withItem2: dart.fnType(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7), [core.Object]), + withItem3: dart.fnType(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7), [core.Object]), + withItem4: dart.fnType(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7), [core.Object]), + withItem5: dart.fnType(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7), [core.Object]), + withItem6: dart.fnType(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7), [core.Object]), + withItem7: dart.fnType(tuple.Tuple7$(T1, T2, T3, T4, T5, T6, T7), [core.Object]), + toList: dart.fnType(core.List, [], {growable: core.bool}) + })); + dart.setFieldSignature(Tuple7, () => ({ + __proto__: dart.getFields(Tuple7.__proto__), + item1: dart.finalFieldType(T1), + item2: dart.finalFieldType(T2), + item3: dart.finalFieldType(T3), + item4: dart.finalFieldType(T4), + item5: dart.finalFieldType(T5), + item6: dart.finalFieldType(T6), + item7: dart.finalFieldType(T7) + })); + dart.defineExtensionMethods(Tuple7, ['toString', '_equals']); + dart.defineExtensionAccessors(Tuple7, ['hashCode']); + return Tuple7; + }); + tuple.Tuple7 = tuple.Tuple7$(); + dart.addTypeTests(tuple.Tuple7, _is_Tuple7_default); + merge_map._copyValues = function(K, V, from, to, recursive, acceptNull) { + for (let key of from[$keys]) { + if (core.Map$(K, V).is(from[$_get](key)) && dart.test(recursive)) { + if (!core.Map$(K, V).is(to[$_get](key))) { + to[$_set](key, V.as(new (_js_helper.LinkedMap$(K, V)).new())); + } + merge_map._copyValues(dart.dynamic, dart.dynamic, core.Map.as(from[$_get](key)), core.Map.as(to[$_get](key)), recursive, acceptNull); + } else { + if (from[$_get](key) != null || dart.test(acceptNull)) to[$_set](key, from[$_get](key)); + } + } + }; + merge_map.mergeMap = function(K, V, maps, opts) { + let recursive = opts && 'recursive' in opts ? opts.recursive : true; + let acceptNull = opts && 'acceptNull' in opts ? opts.acceptNull : false; + let result = new (_js_helper.LinkedMap$(K, V)).new(); + maps[$forEach](dart.fn(map => { + if (map != null) merge_map._copyValues(K, V, map, result, recursive, acceptNull); + }, dart.fnType(core.Null, [core.Map$(K, V)]))); + return result; + }; + convert$.HtmlEscapeMode = class HtmlEscapeMode extends core.Object {}; + (convert$.HtmlEscapeMode.new = function() { + ; + }).prototype = convert$.HtmlEscapeMode.prototype; + dart.addTypeTests(convert$.HtmlEscapeMode); + dart.defineLazy(convert$.HtmlEscapeMode, { + /*convert$.HtmlEscapeMode.unknown*/get unknown() { + return convert.HtmlEscapeMode.unknown; + }, + /*convert$.HtmlEscapeMode.attribute*/get attribute() { + return convert.HtmlEscapeMode.attribute; + }, + /*convert$.HtmlEscapeMode.sqAttribute*/get sqAttribute() { + return convert.HtmlEscapeMode.sqAttribute; + }, + /*convert$.HtmlEscapeMode.element*/get element() { + return convert.HtmlEscapeMode.element; + } + }); + dart.defineLazy(convert$, { + /*convert$.ascii*/get ascii() { + return convert.ascii; + }, + /*convert$.base64*/get base64() { + return convert.base64; + }, + /*convert$.base64Url*/get base64Url() { + return convert.base64Url; + }, + /*convert$.htmlEscape*/get htmlEscape() { + return convert.htmlEscape; + }, + /*convert$.json*/get json() { + return convert.json; + }, + /*convert$.latin1*/get latin1() { + return convert.latin1; + }, + /*convert$.unicodeReplacementCharacterRune*/get unicodeReplacementCharacterRune() { + return 65533; + }, + /*convert$.unicodeBomCharacterRune*/get unicodeBomCharacterRune() { + return 65279; + }, + /*convert$.utf8*/get utf8() { + return convert.utf8; + } + }); + const _handlers = Symbol('_handlers'); + const _is_MiddlewarePipeline_default = Symbol('_is_MiddlewarePipeline_default'); + src__middleware_pipeline.MiddlewarePipeline$ = dart.generic(T => { + let ListOfT = () => (ListOfT = dart.constFn(core.List$(T)))(); + let JSArrayOfT = () => (JSArrayOfT = dart.constFn(_interceptors.JSArray$(T)))(); + class MiddlewarePipeline extends core.Object { + get routingResults() { + return this[routingResults$]; + } + set routingResults(value) { + super.routingResults = value; + } + get [_handlers]() { + return this[_handlers$]; + } + set [_handlers](value) { + this[_handlers$] = ListOfT()._check(value); + } + get handlers() { + if (this[_handlers] != null) return this[_handlers]; + let handlers = JSArrayOfT().of([]); + for (let result of this.routingResults) { + handlers[$addAll](result.allHandlers); + } + return this[_handlers] = handlers; + } + } + (MiddlewarePipeline.new = function(routingResults) { + this[_handlers$] = null; + this[routingResults$] = routingResults[$toList](); + ; + }).prototype = MiddlewarePipeline.prototype; + dart.addTypeTests(MiddlewarePipeline); + MiddlewarePipeline.prototype[_is_MiddlewarePipeline_default] = true; + const routingResults$ = Symbol("MiddlewarePipeline.routingResults"); + const _handlers$ = Symbol("MiddlewarePipeline._handlers"); + dart.setGetterSignature(MiddlewarePipeline, () => ({ + __proto__: dart.getGetters(MiddlewarePipeline.__proto__), + handlers: core.List$(T) + })); + dart.setFieldSignature(MiddlewarePipeline, () => ({ + __proto__: dart.getFields(MiddlewarePipeline.__proto__), + routingResults: dart.finalFieldType(core.Iterable$(src__router.RoutingResult$(T))), + [_handlers]: dart.fieldType(core.List$(T)) + })); + return MiddlewarePipeline; + }); + src__middleware_pipeline.MiddlewarePipeline = src__middleware_pipeline.MiddlewarePipeline$(); + dart.addTypeTests(src__middleware_pipeline.MiddlewarePipeline, _is_MiddlewarePipeline_default); + const _handlers$ = Symbol('_handlers'); + const _root$ = Symbol('_root'); + let const$20; + let const$21; + const _is__ChainedRouter_default = Symbol('_is__ChainedRouter_default'); + src__router._ChainedRouter$ = dart.generic(T => { + let JSArrayOfT = () => (JSArrayOfT = dart.constFn(_interceptors.JSArray$(T)))(); + let IterableOfT = () => (IterableOfT = dart.constFn(core.Iterable$(T)))(); + let _ChainedRouterOfT = () => (_ChainedRouterOfT = dart.constFn(src__router._ChainedRouter$(T)))(); + let RouterOfT = () => (RouterOfT = dart.constFn(src__router.Router$(T)))(); + let SymlinkRouteOfT = () => (SymlinkRouteOfT = dart.constFn(src__router.SymlinkRoute$(T)))(); + class _ChainedRouter extends src__router.Router$(T) { + addRoute(method, path, handler, opts) { + let t2, t1; + T._check(handler); + let middleware = opts && 'middleware' in opts ? opts.middleware : const$20 || (const$20 = dart.constList([], core.Null)); + IterableOfT()._check(middleware); + let route = super.addRoute(method, path, handler, {middleware: (t1 = JSArrayOfT().of([]), t1[$addAll](this[_handlers$]), t1[$addAll]((t2 = middleware, t2 == null ? JSArrayOfT().of([]) : t2)), t1)}); + return route; + } + group(path, callback, opts) { + let t1, t1$; + let middleware = opts && 'middleware' in opts ? opts.middleware : const$21 || (const$21 = dart.constList([], core.Null)); + IterableOfT()._check(middleware); + let name = opts && 'name' in opts ? opts.name : null; + let router = new (_ChainedRouterOfT()).new(this[_root$], (t1 = JSArrayOfT().of([]), t1[$addAll](this[_handlers$]), t1[$addAll](middleware), t1)); + callback(router); + t1$ = this.mount(path, router); + t1$.name = name; + return t1$; + } + mount(path, router) { + RouterOfT()._check(router); + let route = super.mount(path, router); + route.router[_middleware][$insertAll](0, this[_handlers$]); + return route; + } + chain(middleware) { + let t1, t1$; + IterableOfT()._check(middleware); + let piped = (t1 = new (_ChainedRouterOfT()).empty(), t1[_root$] = this[_root$], t1); + piped[_handlers$][$addAll]((t1$ = JSArrayOfT().of([]), t1$[$addAll](this[_handlers$]), t1$[$addAll](middleware), t1$)); + let route = new (SymlinkRouteOfT()).new("/", piped); + this[_routes][$add](route); + return piped; + } + } + (_ChainedRouter.empty = function() { + this[_handlers$] = JSArrayOfT().of([]); + this[_root$] = null; + _ChainedRouter.__proto__.new.call(this); + ; + }).prototype = _ChainedRouter.prototype; + (_ChainedRouter.new = function(root, middleware) { + this[_handlers$] = JSArrayOfT().of([]); + this[_root$] = null; + _ChainedRouter.__proto__.new.call(this); + this[_root$] = root; + this[_handlers$][$addAll](middleware); + }).prototype = _ChainedRouter.prototype; + dart.addTypeTests(_ChainedRouter); + _ChainedRouter.prototype[_is__ChainedRouter_default] = true; + dart.setMethodSignature(_ChainedRouter, () => ({ + __proto__: dart.getMethods(_ChainedRouter.__proto__), + group: dart.fnType(src__router.SymlinkRoute$(T), [core.String, dart.fnType(dart.void, [src__router.Router$(T)])], {middleware: core.Object, name: core.String}) + })); + dart.setFieldSignature(_ChainedRouter, () => ({ + __proto__: dart.getFields(_ChainedRouter.__proto__), + [_handlers$]: dart.finalFieldType(core.List$(T)), + [_root$]: dart.fieldType(src__router.Router) + })); + return _ChainedRouter; + }); + src__router._ChainedRouter = src__router._ChainedRouter$(); + dart.addTypeTests(src__router._ChainedRouter, _is__ChainedRouter_default); + src__router.RouteGrammar = class RouteGrammar extends core.Object {}; + (src__router.RouteGrammar.new = function() { + ; + }).prototype = src__router.RouteGrammar.prototype; + dart.addTypeTests(src__router.RouteGrammar); + dart.defineLazy(src__router.RouteGrammar, { + /*src__router.RouteGrammar.rgx*/get rgx() { + return core.RegExp.new("\\((.+)\\)"); + }, + /*src__router.RouteGrammar.notSlash*/get notSlash() { + return src__combinator__combinator.match(core.String, core.RegExp.new("[^/]+")).value(dart.fn(r => r.span.text, ParseResultOfStringToString())); + }, + /*src__router.RouteGrammar.regExp*/get regExp() { + return src__combinator__combinator.match(core.RegExp, core.RegExp.new("\\((.+)\\)")).value(dart.fn(r => core.RegExp.new(r.scanner.lastMatch._get(1)), ParseResultOfRegExpToRegExp())); + }, + /*src__router.RouteGrammar.parameterName*/get parameterName() { + return src__combinator__combinator.match(core.String, core.RegExp.new(":([A-Za-z0-9_]+)")).value(dart.fn(r => r.span.text[$substring](1), ParseResultOfStringToString())); + }, + /*src__router.RouteGrammar.parameterSegment*/get parameterSegment() { + return src__combinator__combinator.chain(core.Object, JSArrayOfParserOfObject().of([src__router.RouteGrammar.parameterName, src__combinator__combinator.match(core.bool, "?").value(dart.fn(r => true, ParseResultOfboolTobool())).opt(), src__router.RouteGrammar.regExp.opt()])).map(src__router.ParameterSegment, dart.fn(r => { + let s = new src__router.ParameterSegment.new(core.String.as(r.value[$_get](0)), core.RegExp.as(r.value[$_get](2))); + return dart.equals(r.value[$_get](1), true) ? new src__router.OptionalSegment.new(s) : s; + }, ParseResultOfListOfObjectToParameterSegment())); + }, + /*src__router.RouteGrammar.parsedParameterSegment*/get parsedParameterSegment() { + return src__combinator__combinator.chain(core.Object, JSArrayOfParserOfObject().of([src__combinator__combinator.match(dart.dynamic, core.RegExp.new("(int|num|double)"), {errorMessage: "Expected \"int\",\"double\", or \"num\"."}).map(core.String, dart.fn(r => r.span.text, ParseResultToString())), src__router.RouteGrammar.parameterSegment])).map(src__router.ParsedParameterSegment, dart.fn(r => new src__router.ParsedParameterSegment.new(core.String.as(r.value[$_get](0)), src__router.ParameterSegment.as(r.value[$_get](1))), ParseResultOfListOfObjectToParsedParameterSegment())); + }, + /*src__router.RouteGrammar.wildcardSegment*/get wildcardSegment() { + return src__combinator__combinator.match(src__router.WildcardSegment, "*").value(dart.fn(r => new src__router.WildcardSegment.new(), ParseResultOfWildcardSegmentToWildcardSegment())); + }, + /*src__router.RouteGrammar.constantSegment*/get constantSegment() { + return src__router.RouteGrammar.notSlash.map(src__router.ConstantSegment, dart.fn(r => new src__router.ConstantSegment.new(r.value), ParseResultOfStringToConstantSegment())); + }, + /*src__router.RouteGrammar.routeSegment*/get routeSegment() { + return src__combinator__combinator.any(src__router.RouteSegment, JSArrayOfParserOfRouteSegment().of([src__router.RouteGrammar.parsedParameterSegment, src__router.RouteGrammar.parameterSegment, src__router.RouteGrammar.wildcardSegment, src__router.RouteGrammar.constantSegment])); + }, + /*src__router.RouteGrammar.routeDefinition*/get routeDefinition() { + return src__router.RouteGrammar.routeSegment.separatedBy(src__combinator__combinator.match(dart.dynamic, "/")).map(src__router.RouteDefinition, dart.fn(r => { + let t1; + return new src__router.RouteDefinition.new((t1 = r.value, t1 == null ? JSArrayOfRouteSegment().of([]) : t1)); + }, ParseResultOfListOfRouteSegmentToRouteDefinition())).surroundedBy(src__combinator__combinator.match(dart.dynamic, "/").star().opt()); + } + }); + src__router.RouteDefinition = class RouteDefinition extends core.Object { + get segments() { + return this[segments$]; + } + set segments(value) { + super.segments = value; + } + compile() { + let out = null; + for (let i = 0; i < dart.notNull(this.segments[$length]); i = i + 1) { + let s = this.segments[$_get](i); + let isLast = i === dart.notNull(this.segments[$length]) - 1; + if (out == null) + out = s.compile(isLast); + else + out = s.compileNext(out.then(src__combinator__combinator.match(dart.dynamic, "/")).index(0).cast(MapOfString$dynamic()), isLast); + } + return out; + } + }; + (src__router.RouteDefinition.new = function(segments) { + this[segments$] = segments; + ; + }).prototype = src__router.RouteDefinition.prototype; + dart.addTypeTests(src__router.RouteDefinition); + const segments$ = Symbol("RouteDefinition.segments"); + dart.setMethodSignature(src__router.RouteDefinition, () => ({ + __proto__: dart.getMethods(src__router.RouteDefinition.__proto__), + compile: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), []) + })); + dart.setFieldSignature(src__router.RouteDefinition, () => ({ + __proto__: dart.getFields(src__router.RouteDefinition.__proto__), + segments: dart.finalFieldType(core.List$(src__router.RouteSegment)) + })); + src__router.RouteSegment = class RouteSegment extends core.Object {}; + (src__router.RouteSegment.new = function() { + ; + }).prototype = src__router.RouteSegment.prototype; + dart.addTypeTests(src__router.RouteSegment); + src__router.ConstantSegment = class ConstantSegment extends src__router.RouteSegment { + get text() { + return this[text$]; + } + set text(value) { + super.text = value; + } + toString() { + return "Constant: " + dart.str(this.text); + } + compile(isLast) { + return src__combinator__combinator.match(MapOfString$dynamic(), this.text).value(dart.fn(r => new (IdentityMapOfString$dynamic()).new(), ParseResultOfMapOfString$dynamicToMapOfString$dynamic())); + } + compileNext(p, isLast) { + return p.then(this.compile(isLast)).index(0).cast(MapOfString$dynamic()); + } + }; + (src__router.ConstantSegment.new = function(text) { + this[text$] = text; + ; + }).prototype = src__router.ConstantSegment.prototype; + dart.addTypeTests(src__router.ConstantSegment); + const text$ = Symbol("ConstantSegment.text"); + dart.setMethodSignature(src__router.ConstantSegment, () => ({ + __proto__: dart.getMethods(src__router.ConstantSegment.__proto__), + compile: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [core.bool]), + compileNext: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), core.bool]) + })); + dart.setFieldSignature(src__router.ConstantSegment, () => ({ + __proto__: dart.getFields(src__router.ConstantSegment.__proto__), + text: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__router.ConstantSegment, ['toString']); + const _compile = Symbol('_compile'); + src__router.WildcardSegment = class WildcardSegment extends src__router.RouteSegment { + toString() { + return "Wildcard segment"; + } + [_compile](isLast) { + if (dart.test(isLast)) return src__combinator__combinator.match(MapOfString$dynamic(), core.RegExp.new(".*")); + return src__combinator__combinator.match(MapOfString$dynamic(), core.RegExp.new("[^/]*")); + } + compile(isLast) { + return this[_compile](isLast).map(MapOfString$dynamic(), dart.fn(r => new (IdentityMapOfString$dynamic()).new(), ParseResultOfMapOfString$dynamicToMapOfString$dynamic())); + } + compileNext(p, isLast) { + return p.then(this[_compile](isLast)).index(0).cast(MapOfString$dynamic()); + } + }; + (src__router.WildcardSegment.new = function() { + ; + }).prototype = src__router.WildcardSegment.prototype; + dart.addTypeTests(src__router.WildcardSegment); + dart.setMethodSignature(src__router.WildcardSegment, () => ({ + __proto__: dart.getMethods(src__router.WildcardSegment.__proto__), + [_compile]: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [core.bool]), + compile: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [core.bool]), + compileNext: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), core.bool]) + })); + dart.defineExtensionMethods(src__router.WildcardSegment, ['toString']); + src__router.ParameterSegment = class ParameterSegment extends src__router.RouteSegment { + get name() { + return this[name$3]; + } + set name(value) { + super.name = value; + } + get regExp() { + return this[regExp$]; + } + set regExp(value) { + super.regExp = value; + } + toString() { + if (this.regExp != null) return "Param: " + dart.str(this.name) + " (" + dart.str(this.regExp.pattern) + ")"; + return "Param: " + dart.str(this.name); + } + [_compile]() { + return this.regExp != null ? src__combinator__combinator.match(core.String, this.regExp).value(dart.fn(r => r.span.text, ParseResultOfStringToString())) : src__router.RouteGrammar.notSlash; + } + compile(isLast) { + return this[_compile]().map(MapOfString$dynamic(), dart.fn(r => new (IdentityMapOfString$dynamic()).from([this.name, core.Uri.decodeComponent(r.span.text)]), ParseResultOfStringToMapOfString$dynamic())); + } + compileNext(p, isLast) { + return p.then(this[_compile]()).map(MapOfString$dynamic(), dart.fn(r => { + let t1; + t1 = MapOfString$dynamic().as(r.value[$_get](0)); + t1[$addAll](new (IdentityMapOfString$dynamic()).from([this.name, core.Uri.decodeComponent(core.String.as(r.value[$_get](1)))])); + return t1; + }, ParseResultOfListToMapOfString$dynamic())); + } + }; + (src__router.ParameterSegment.new = function(name, regExp) { + this[name$3] = name; + this[regExp$] = regExp; + ; + }).prototype = src__router.ParameterSegment.prototype; + dart.addTypeTests(src__router.ParameterSegment); + const name$3 = Symbol("ParameterSegment.name"); + const regExp$ = Symbol("ParameterSegment.regExp"); + dart.setMethodSignature(src__router.ParameterSegment, () => ({ + __proto__: dart.getMethods(src__router.ParameterSegment.__proto__), + [_compile]: dart.fnType(src__combinator__combinator.Parser$(core.String), []), + compile: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [core.bool]), + compileNext: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), core.bool]) + })); + dart.setFieldSignature(src__router.ParameterSegment, () => ({ + __proto__: dart.getFields(src__router.ParameterSegment.__proto__), + name: dart.finalFieldType(core.String), + regExp: dart.finalFieldType(core.RegExp) + })); + dart.defineExtensionMethods(src__router.ParameterSegment, ['toString']); + src__router.OptionalSegment = class OptionalSegment extends src__router.ParameterSegment { + get parameter() { + return this[parameter$]; + } + set parameter(value) { + super.parameter = value; + } + toString() { + return "Optional: " + dart.str(this.parameter); + } + compile(isLast) { + return super.compile(isLast).opt(); + } + compileNext(p, isLast) { + return p.then(this[_compile]().opt()).map(MapOfString$dynamic(), dart.fn(r => { + let t1; + if (r.value[$_get](1) == null) return MapOfString$dynamic().as(r.value[$_get](0)); + t1 = MapOfString$dynamic().as(r.value[$_get](0)); + t1[$addAll](new (IdentityMapOfString$dynamic()).from([this.name, core.Uri.decodeComponent(core.String.as(r.value[$_get](1)))])); + return t1; + }, ParseResultOfListToMapOfString$dynamic())); + } + }; + (src__router.OptionalSegment.new = function(parameter) { + this[parameter$] = parameter; + src__router.OptionalSegment.__proto__.new.call(this, parameter.name, parameter.regExp); + ; + }).prototype = src__router.OptionalSegment.prototype; + dart.addTypeTests(src__router.OptionalSegment); + const parameter$ = Symbol("OptionalSegment.parameter"); + dart.setFieldSignature(src__router.OptionalSegment, () => ({ + __proto__: dart.getFields(src__router.OptionalSegment.__proto__), + parameter: dart.finalFieldType(src__router.ParameterSegment) + })); + dart.defineExtensionMethods(src__router.OptionalSegment, ['toString']); + src__router.ParsedParameterSegment = class ParsedParameterSegment extends src__router.RouteSegment { + get type() { + return this[type$]; + } + set type(value) { + super.type = value; + } + get parameter() { + return this[parameter$0]; + } + set parameter(value) { + super.parameter = value; + } + getValue(s) { + switch (this.type) { + case "int": + { + return core.int.parse(s); + } + case "double": + { + return core.double.parse(s); + } + default: + { + return core.num.parse(s); + } + } + } + compile(isLast) { + return this.parameter[_compile]().map(MapOfString$dynamic(), dart.fn(r => new (IdentityMapOfString$dynamic()).from([this.parameter.name, this.getValue(core.Uri.decodeComponent(r.span.text))]), ParseResultOfStringToMapOfString$dynamic())); + } + compileNext(p, isLast) { + return p.then(this.parameter[_compile]()).map(MapOfString$dynamic(), dart.fn(r => { + let t1; + t1 = MapOfString$dynamic().as(r.value[$_get](0)); + t1[$addAll](new (IdentityMapOfString$dynamic()).from([this.parameter.name, this.getValue(core.Uri.decodeComponent(core.String.as(r.value[$_get](1))))])); + return t1; + }, ParseResultOfListToMapOfString$dynamic())); + } + }; + (src__router.ParsedParameterSegment.new = function(type, parameter) { + this[type$] = type; + this[parameter$0] = parameter; + ; + }).prototype = src__router.ParsedParameterSegment.prototype; + dart.addTypeTests(src__router.ParsedParameterSegment); + const type$ = Symbol("ParsedParameterSegment.type"); + const parameter$0 = Symbol("ParsedParameterSegment.parameter"); + dart.setMethodSignature(src__router.ParsedParameterSegment, () => ({ + __proto__: dart.getMethods(src__router.ParsedParameterSegment.__proto__), + getValue: dart.fnType(core.num, [core.String]), + compile: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [core.bool]), + compileNext: dart.fnType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), [src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)), core.bool]) + })); + dart.setFieldSignature(src__router.ParsedParameterSegment, () => ({ + __proto__: dart.getFields(src__router.ParsedParameterSegment.__proto__), + type: dart.finalFieldType(core.String), + parameter: dart.finalFieldType(src__router.ParameterSegment) + })); + const _parser = Symbol('_parser'); + const _routeDefinition = Symbol('_routeDefinition'); + const _is_Route_default = Symbol('_is_Route_default'); + src__router.Route$ = dart.generic(T => { + let RouteOfT = () => (RouteOfT = dart.constFn(src__router.Route$(T)))(); + class Route extends core.Object { + get method() { + return this[method$]; + } + set method(value) { + super.method = value; + } + get path() { + return this[path$]; + } + set path(value) { + super.path = value; + } + get handlers() { + return this[handlers$]; + } + set handlers(value) { + super.handlers = value; + } + get name() { + return this[name]; + } + set name(value) { + this[name] = value; + } + static join(a, b) { + let start = a.path[$replaceAll](src__router._straySlashes, ""); + let end = b.path[$replaceAll](src__router._straySlashes, ""); + return new (src__router.Route$(T)).new((start + "/" + end)[$replaceAll](src__router._straySlashes, ""), {method: b.method, handlers: b.handlers}); + } + get parser() { + let t1; + t1 = this[_parser]; + return t1 == null ? this[_parser] = this[_routeDefinition].compile() : t1; + } + toString() { + return dart.str(this.method) + " " + dart.str(this.path) + " => " + dart.str(this.handlers); + } + clone() { + let t1; + t1 = new (RouteOfT()).new(this.path, {method: this.method, handlers: this.handlers}); + t1[_cache][$addAll](this[_cache]); + return t1; + } + makeUri(params) { + let t1; + let b = new core.StringBuffer.new(); + let i = 0; + for (let seg of this[_routeDefinition].segments) { + if ((t1 = i, i = t1 + 1, t1) > 0) b.write("/"); + if (src__router.ConstantSegment.is(seg)) + b.write(seg.text); + else if (src__router.ParameterSegment.is(seg)) { + if (!dart.test(params[$containsKey](seg.name))) dart.throw(new core.ArgumentError.new("Missing parameter \"" + dart.str(seg.name) + "\".")); + b.write(params[$_get](seg.name)); + } + } + return b.toString(); + } + } + (Route.new = function(path, opts) { + let t1, t1$; + let method = opts && 'method' in opts ? opts.method : null; + let handlers = opts && 'handlers' in opts ? opts.handlers : null; + this[_cache] = new (IdentityMapOfString$MapOfString$dynamic()).new(); + this[name] = null; + this[_parser] = null; + this[path$] = path; + this[method$] = method; + this[handlers$] = handlers; + this[_routeDefinition] = src__router.RouteGrammar.routeDefinition.parse(new src__span_scanner.SpanScanner.new(path[$replaceAll](src__router._straySlashes, ""))).value; + if (!dart.equals((t1$ = (t1 = this[_routeDefinition], t1 == null ? null : t1.segments), t1$ == null ? null : t1$[$isNotEmpty]), true)) this[_parser] = src__combinator__combinator.match(MapOfString$dynamic(), "").value(dart.fn(r => new (IdentityMapOfString$dynamic()).new(), ParseResultOfMapOfString$dynamicToMapOfString$dynamic())); + }).prototype = Route.prototype; + dart.addTypeTests(Route); + Route.prototype[_is_Route_default] = true; + const method$ = Symbol("Route.method"); + const path$ = Symbol("Route.path"); + const handlers$ = Symbol("Route.handlers"); + const name = Symbol("Route.name"); + dart.setMethodSignature(Route, () => ({ + __proto__: dart.getMethods(Route.__proto__), + clone: dart.fnType(src__router.Route$(T), []), + makeUri: dart.fnType(core.String, [core.Map$(core.String, dart.dynamic)]) + })); + dart.setGetterSignature(Route, () => ({ + __proto__: dart.getGetters(Route.__proto__), + parser: src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic)) + })); + dart.setFieldSignature(Route, () => ({ + __proto__: dart.getFields(Route.__proto__), + method: dart.finalFieldType(core.String), + path: dart.finalFieldType(core.String), + handlers: dart.finalFieldType(core.List$(T)), + [_cache]: dart.finalFieldType(core.Map$(core.String, core.Map$(core.String, dart.dynamic))), + [_routeDefinition]: dart.finalFieldType(src__router.RouteDefinition), + name: dart.fieldType(core.String), + [_parser]: dart.fieldType(src__combinator__combinator.Parser$(core.Map$(core.String, dart.dynamic))) + })); + dart.defineExtensionMethods(Route, ['toString']); + return Route; + }); + src__router.Route = src__router.Route$(); + dart.addTypeTests(src__router.Route, _is_Route_default); + let const$22; + const _is_RoutingResult_default = Symbol('_is_RoutingResult_default'); + src__router.RoutingResult$ = dart.generic(T => { + let JSArrayOfT = () => (JSArrayOfT = dart.constFn(_interceptors.JSArray$(T)))(); + let RoutingResultOfT = () => (RoutingResultOfT = dart.constFn(src__router.RoutingResult$(T)))(); + let RoutingResultOfTTovoid = () => (RoutingResultOfTTovoid = dart.constFn(dart.fnType(dart.void, [RoutingResultOfT()])))(); + class RoutingResult extends core.Object { + get parseResult() { + return this[parseResult$]; + } + set parseResult(value) { + super.parseResult = value; + } + get nested() { + return this[nested$]; + } + set nested(value) { + super.nested = value; + } + get params() { + return this[params$]; + } + set params(value) { + super.params = value; + } + get shallowRoute() { + return this[shallowRoute$]; + } + set shallowRoute(value) { + super.shallowRoute = value; + } + get shallowRouter() { + return this[shallowRouter$]; + } + set shallowRouter(value) { + super.shallowRouter = value; + } + get tail() { + return this[tail$]; + } + set tail(value) { + super.tail = value; + } + get deepest() { + let t1, t1$; + let search = this; + while (dart.equals((t1$ = (t1 = search, t1 == null ? null : t1.nested), t1$ == null ? null : t1$[$isNotEmpty]), true)) + search = search.nested[$first]; + return search; + } + get route() { + return this.deepest.shallowRoute; + } + get router() { + return this.deepest.shallowRouter; + } + get handlers() { + let t1; + t1 = JSArrayOfT().of([]); + t1[$addAll](this.shallowRouter.middleware); + t1[$addAll](this.shallowRoute.handlers); + return t1; + } + get allHandlers() { + let handlers = JSArrayOfT().of([]); + function crawl(result) { + let t1; + handlers[$addAll](result.handlers); + if (dart.equals((t1 = result.nested, t1 == null ? null : t1[$isNotEmpty]), true)) { + for (let r of result.nested) + crawl(r); + } + } + dart.fn(crawl, RoutingResultOfTTovoid()); + crawl(this); + return handlers; + } + get allParams() { + let params = new (IdentityMapOfString$dynamic()).new(); + function crawl(result) { + let t1; + params[$addAll](result.params); + if (dart.equals((t1 = result.nested, t1 == null ? null : t1[$isNotEmpty]), true)) { + for (let r of result.nested) + crawl(r); + } + } + dart.fn(crawl, RoutingResultTovoid()); + crawl(this); + return params; + } + } + (RoutingResult.new = function(opts) { + let t1; + let parseResult = opts && 'parseResult' in opts ? opts.parseResult : null; + let params = opts && 'params' in opts ? opts.params : const$22 || (const$22 = dart.constMap(core.String, dart.dynamic, [])); + let nested = opts && 'nested' in opts ? opts.nested : null; + let shallowRoute = opts && 'shallowRoute' in opts ? opts.shallowRoute : null; + let shallowRouter = opts && 'shallowRouter' in opts ? opts.shallowRouter : null; + let tail = opts && 'tail' in opts ? opts.tail : null; + this[params$] = new (IdentityMapOfString$dynamic()).new(); + this[parseResult$] = parseResult; + this[nested$] = nested; + this[shallowRoute$] = shallowRoute; + this[shallowRouter$] = shallowRouter; + this[tail$] = tail; + this.params[$addAll]((t1 = params, t1 == null ? new (IdentityMapOfString$dynamic()).new() : t1)); + }).prototype = RoutingResult.prototype; + dart.addTypeTests(RoutingResult); + RoutingResult.prototype[_is_RoutingResult_default] = true; + const parseResult$ = Symbol("RoutingResult.parseResult"); + const nested$ = Symbol("RoutingResult.nested"); + const params$ = Symbol("RoutingResult.params"); + const shallowRoute$ = Symbol("RoutingResult.shallowRoute"); + const shallowRouter$ = Symbol("RoutingResult.shallowRouter"); + const tail$ = Symbol("RoutingResult.tail"); + dart.setGetterSignature(RoutingResult, () => ({ + __proto__: dart.getGetters(RoutingResult.__proto__), + deepest: src__router.RoutingResult$(T), + route: src__router.Route$(T), + router: src__router.Router$(T), + handlers: core.List$(T), + allHandlers: core.List$(T), + allParams: core.Map$(core.String, dart.dynamic) + })); + dart.setFieldSignature(RoutingResult, () => ({ + __proto__: dart.getFields(RoutingResult.__proto__), + parseResult: dart.finalFieldType(src__combinator__combinator.ParseResult$(core.Map$(core.String, dart.dynamic))), + nested: dart.finalFieldType(core.Iterable$(src__router.RoutingResult$(T))), + params: dart.finalFieldType(core.Map$(core.String, dart.dynamic)), + shallowRoute: dart.finalFieldType(src__router.Route$(T)), + shallowRouter: dart.finalFieldType(src__router.Router$(T)), + tail: dart.finalFieldType(core.String) + })); + return RoutingResult; + }); + src__router.RoutingResult = src__router.RoutingResult$(); + dart.addTypeTests(src__router.RoutingResult, _is_RoutingResult_default); + const _is_SymlinkRoute_default = Symbol('_is_SymlinkRoute_default'); + src__router.SymlinkRoute$ = dart.generic(T => { + class SymlinkRoute extends src__router.Route$(T) { + get router() { + return this[router$]; + } + set router(value) { + super.router = value; + } + } + (SymlinkRoute.new = function(path, router) { + this[router$] = router; + SymlinkRoute.__proto__.new.call(this, path, {method: null, handlers: null}); + ; + }).prototype = SymlinkRoute.prototype; + dart.addTypeTests(SymlinkRoute); + SymlinkRoute.prototype[_is_SymlinkRoute_default] = true; + const router$ = Symbol("SymlinkRoute.router"); + dart.setFieldSignature(SymlinkRoute, () => ({ + __proto__: dart.getFields(SymlinkRoute.__proto__), + router: dart.finalFieldType(src__router.Router$(T)) + })); + return SymlinkRoute; + }); + src__router.SymlinkRoute = src__router.SymlinkRoute$(); + dart.addTypeTests(src__router.SymlinkRoute, _is_SymlinkRoute_default); + src__router.flatten = function(T, router) { + let t1; + let flattened = new (src__router.Router$(T)).new(); + for (let route of router.routes) { + if (src__router.SymlinkRoute$(T).is(route)) { + let base = route.path[$replaceAll](src__router._straySlashes, ""); + let child = src__router.flatten(T, route.router); + for (let route of child.routes) { + let path = route.path[$replaceAll](src__router._straySlashes, ""); + let joined = (base + "/" + path)[$replaceAll](src__router._straySlashes, ""); + flattened.addRoute(route.method, joined[$replaceAll](src__router._straySlashes, ""), route.handlers[$last], {middleware: route.handlers[$take](dart.notNull(route.handlers[$length]) - 1)[$toList]()}); + } + } else { + flattened.addRoute(route.method, route.path, route.handlers[$last], {middleware: route.handlers[$take](dart.notNull(route.handlers[$length]) - 1)[$toList]()}); + } + } + t1 = flattened; + t1.enableCache(); + return t1; + }; + dart.defineLazy(src__router, { + /*src__router._straySlashes*/get _straySlashes() { + return core.RegExp.new("(^/+)|(/+$)"); + } + }); + src__routing_exception.RoutingException = class RoutingException extends core.Exception { + static new(message) { + return new src__routing_exception._RoutingExceptionImpl.new(message); + } + static orphan() { + return new src__routing_exception._RoutingExceptionImpl.new("Tried to resolve path '..' on a route that has no parent."); + } + static noSuchRoute(path) { + return new src__routing_exception._RoutingExceptionImpl.new("Tried to navigate to non-existent route: '" + dart.str(path) + "'."); + } + }; + dart.addTypeTests(src__routing_exception.RoutingException); + src__routing_exception._RoutingExceptionImpl = class _RoutingExceptionImpl extends core.Object { + toString() { + return this.message; + } + }; + (src__routing_exception._RoutingExceptionImpl.new = function(message) { + this.message = message; + ; + }).prototype = src__routing_exception._RoutingExceptionImpl.prototype; + dart.addTypeTests(src__routing_exception._RoutingExceptionImpl); + src__routing_exception._RoutingExceptionImpl[dart.implements] = () => [src__routing_exception.RoutingException]; + dart.setFieldSignature(src__routing_exception._RoutingExceptionImpl, () => ({ + __proto__: dart.getFields(src__routing_exception._RoutingExceptionImpl.__proto__), + message: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__routing_exception._RoutingExceptionImpl, ['toString']); + src__body_parse_result.BodyParseResult = class BodyParseResult extends core.Object {}; + (src__body_parse_result.BodyParseResult.new = function() { + ; + }).prototype = src__body_parse_result.BodyParseResult.prototype; + dart.addTypeTests(src__body_parse_result.BodyParseResult); + let const$23; + src__file_upload_info.FileUploadInfo = class FileUploadInfo extends core.Object { + get mimeType() { + return this[mimeType$]; + } + set mimeType(value) { + this[mimeType$] = value; + } + get name() { + return this[name$4]; + } + set name(value) { + this[name$4] = value; + } + get filename() { + return this[filename$]; + } + set filename(value) { + this[filename$] = value; + } + get data() { + return this[data$0]; + } + set data(value) { + this[data$0] = value; + } + }; + (src__file_upload_info.FileUploadInfo.new = function(opts) { + let mimeType = opts && 'mimeType' in opts ? opts.mimeType : null; + let name = opts && 'name' in opts ? opts.name : null; + let filename = opts && 'filename' in opts ? opts.filename : null; + let data = opts && 'data' in opts ? opts.data : const$23 || (const$23 = dart.constList([], core.int)); + this[mimeType$] = mimeType; + this[name$4] = name; + this[filename$] = filename; + this[data$0] = data; + }).prototype = src__file_upload_info.FileUploadInfo.prototype; + dart.addTypeTests(src__file_upload_info.FileUploadInfo); + const mimeType$ = Symbol("FileUploadInfo.mimeType"); + const name$4 = Symbol("FileUploadInfo.name"); + const filename$ = Symbol("FileUploadInfo.filename"); + const data$0 = Symbol("FileUploadInfo.data"); + dart.setFieldSignature(src__file_upload_info.FileUploadInfo, () => ({ + __proto__: dart.getFields(src__file_upload_info.FileUploadInfo.__proto__), + mimeType: dart.fieldType(core.String), + name: dart.fieldType(core.String), + filename: dart.fieldType(core.String), + data: dart.fieldType(core.List$(core.int)) + })); + src__parse_body._BodyParseResultImpl = class _BodyParseResultImpl extends core.Object {}; + (src__parse_body._BodyParseResultImpl.new = function() { + this.body = new (IdentityMapOfString$dynamic()).new(); + this.files = JSArrayOfFileUploadInfo().of([]); + this.originalBuffer = null; + this.query = new (IdentityMapOfString$dynamic()).new(); + this.error = null; + this.stack = null; + ; + }).prototype = src__parse_body._BodyParseResultImpl.prototype; + dart.addTypeTests(src__parse_body._BodyParseResultImpl); + src__parse_body._BodyParseResultImpl[dart.implements] = () => [src__body_parse_result.BodyParseResult]; + dart.setFieldSignature(src__parse_body._BodyParseResultImpl, () => ({ + __proto__: dart.getFields(src__parse_body._BodyParseResultImpl.__proto__), + body: dart.fieldType(core.Map$(core.String, dart.dynamic)), + files: dart.fieldType(core.List$(src__file_upload_info.FileUploadInfo)), + originalBuffer: dart.fieldType(core.List$(core.int)), + query: dart.fieldType(core.Map$(core.String, dart.dynamic)), + error: dart.fieldType(dart.dynamic), + stack: dart.fieldType(core.StackTrace) + })); + src__parse_body.parseBody = function(request, opts) { + let storeOriginalBuffer = opts && 'storeOriginalBuffer' in opts ? opts.storeOriginalBuffer : false; + return src__parse_body.parseBodyFromStream(request, request.headers.contentType != null ? src__media_type.MediaType.parse(dart.toString(request.headers.contentType)) : null, request.uri, {storeOriginalBuffer: storeOriginalBuffer}); + }; + src__parse_body.parseBodyFromStream = function(data, contentType, requestUri, opts) { + return async.async(src__body_parse_result.BodyParseResult, function* parseBodyFromStream() { + let t1, t1$; + let storeOriginalBuffer = opts && 'storeOriginalBuffer' in opts ? opts.storeOriginalBuffer : false; + let result = new src__parse_body._BodyParseResultImpl.new(); + function getBytes() { + return data.fold(io.BytesBuilder, io.BytesBuilder.new({copy: false}), dart.fn((a, b) => { + let t1; + t1 = a; + t1.add(b); + return t1; + }, BytesBuilderAndListOfintToBytesBuilder())).then(ListOfint(), dart.fn(b => b.takeBytes(), BytesBuilderToListOfint())); + } + dart.fn(getBytes, VoidToFutureOfListOfint()); + function getBody() { + if (dart.test(storeOriginalBuffer)) { + return getBytes().then(core.String, dart.fn(bytes => { + result.originalBuffer = bytes; + return convert$.utf8.decode(bytes); + }, ListOfintToString())); + } else + return data.transform(core.String, convert$.utf8.decoder).join(); + } + dart.fn(getBody, VoidToFutureOfString()); + try { + if (contentType != null) { + if (contentType.type === "multipart" && dart.test(contentType.parameters[$containsKey]("boundary"))) { + let stream = null; + if (dart.test(storeOriginalBuffer)) { + let bytes = result.originalBuffer = (yield getBytes()); + let ctrl = (t1 = StreamControllerOfListOfint().new(), t1.add(bytes), t1.close(), t1); + stream = ctrl.stream; + } else { + stream = data; + } + let parts = stream.transform(src__mime_shared.MimeMultipart, new src__mime_multipart_transformer.MimeMultipartTransformer.new(contentType.parameters[$_get]("boundary"))).map(src__http_multipart_form_data.HttpMultipartFormData, dart.fn(part => src__http_multipart_form_data.HttpMultipartFormData.parse(part, {defaultEncoding: convert$.utf8}), MimeMultipartToHttpMultipartFormData())); + let iter = async.StreamIterator.new(parts); + try { + while (yield iter.moveNext()) { + let part = iter.current; + { + if (dart.test(part.isBinary) || dart.test(part.contentDisposition.parameters[$containsKey]("filename"))) { + let builder = (yield part.fold(io.BytesBuilder, io.BytesBuilder.new({copy: false}), dart.fn((b, d) => { + let t1; + t1 = b; + t1.add(!(typeof d == 'string') ? ListOfint().as(d) : core.String.as(d)[$codeUnits]); + return t1; + }, BytesBuilderAnddynamicToBytesBuilder()))); + let upload = new src__file_upload_info.FileUploadInfo.new({mimeType: part.contentType.mimeType, name: part.contentDisposition.parameters[$_get]("name"), filename: (t1$ = part.contentDisposition.parameters[$_get]("filename"), t1$ == null ? "file" : t1$), data: builder.takeBytes()}); + result.files[$add](upload); + } else if (dart.test(part.isText)) { + let text = (yield part.join()); + src__map_from_uri.buildMapFromUri(result.body, dart.str(part.contentDisposition.parameters[$_get]("name")) + "=" + dart.str(text)); + } + } + } + } finally { + yield iter.cancel(); + } + } else if (contentType.mimeType === "application/json") { + result.body[$addAll](src__parse_body._foldToStringDynamic(core.Map.as(convert$.json.decode(yield getBody())))); + } else if (contentType.mimeType === "application/x-www-form-urlencoded") { + let body = (yield getBody()); + src__map_from_uri.buildMapFromUri(result.body, body); + } else if (dart.equals(storeOriginalBuffer, true)) { + result.originalBuffer = (yield getBytes()); + } + } else { + if (dart.test(requestUri.hasQuery)) { + src__map_from_uri.buildMapFromUri(result.query, requestUri.query); + } + if (dart.equals(storeOriginalBuffer, true)) { + result.originalBuffer = (yield getBytes()); + } + } + } catch (e) { + let st = dart.stackTrace(e); + result.error = e; + result.stack = st; + } + return result; + }); + }; + src__parse_body._foldToStringDynamic = function(map) { + return map == null ? null : map[$keys][$fold](MapOfString$dynamic(), new (IdentityMapOfString$dynamic()).new(), dart.fn((out, k) => { + let t1; + t1 = out; + t1[$_set](dart.toString(k), map[$_get](k)); + return t1; + }, MapOfString$dynamicAnddynamicToMapOfString$dynamic())); + }; + const _optionsAndSeparators = Symbol('_optionsAndSeparators'); + const _options = Symbol('_options'); + const _commands = Symbol('_commands'); + const _addOption = Symbol('_addOption'); + src__arg_parser.ArgParser = class ArgParser extends core.Object { + get options() { + return this[options$]; + } + set options(value) { + super.options = value; + } + get commands() { + return this[commands$]; + } + set commands(value) { + super.commands = value; + } + get allowTrailingOptions() { + return this[allowTrailingOptions$]; + } + set allowTrailingOptions(value) { + super.allowTrailingOptions = value; + } + get usageLineLength() { + return this[usageLineLength$]; + } + set usageLineLength(value) { + super.usageLineLength = value; + } + get allowsAnything() { + return false; + } + static new(opts) { + let allowTrailingOptions = opts && 'allowTrailingOptions' in opts ? opts.allowTrailingOptions : true; + let usageLineLength = opts && 'usageLineLength' in opts ? opts.usageLineLength : null; + return new src__arg_parser.ArgParser.__(new (IdentityMapOfString$Option()).new(), new (IdentityMapOfString$ArgParser()).new(), {allowTrailingOptions: allowTrailingOptions, usageLineLength: usageLineLength}); + } + addCommand(name, parser) { + if (parser === void 0) parser = null; + if (dart.test(this[_commands][$containsKey](name))) { + dart.throw(new core.ArgumentError.new("Duplicate command \"" + dart.str(name) + "\".")); + } + if (parser == null) parser = src__arg_parser.ArgParser.new(); + this[_commands][$_set](name, parser); + return parser; + } + addFlag(name, opts) { + let abbr = opts && 'abbr' in opts ? opts.abbr : null; + let help = opts && 'help' in opts ? opts.help : null; + let defaultsTo = opts && 'defaultsTo' in opts ? opts.defaultsTo : false; + let negatable = opts && 'negatable' in opts ? opts.negatable : true; + let callback = opts && 'callback' in opts ? opts.callback : null; + let hide = opts && 'hide' in opts ? opts.hide : false; + this[_addOption](name, abbr, help, null, null, null, defaultsTo, callback == null ? null : dart.fn(value => callback(core.bool.as(value)), dynamicTovoid()), src__option.OptionType.flag, {negatable: negatable, hide: hide}); + } + addOption(name, opts) { + let abbr = opts && 'abbr' in opts ? opts.abbr : null; + let help = opts && 'help' in opts ? opts.help : null; + let valueHelp = opts && 'valueHelp' in opts ? opts.valueHelp : null; + let allowed = opts && 'allowed' in opts ? opts.allowed : null; + let allowedHelp = opts && 'allowedHelp' in opts ? opts.allowedHelp : null; + let defaultsTo = opts && 'defaultsTo' in opts ? opts.defaultsTo : null; + let callback = opts && 'callback' in opts ? opts.callback : null; + let allowMultiple = opts && 'allowMultiple' in opts ? opts.allowMultiple : false; + let splitCommas = opts && 'splitCommas' in opts ? opts.splitCommas : null; + let hide = opts && 'hide' in opts ? opts.hide : false; + if (!dart.test(allowMultiple) && splitCommas != null) { + dart.throw(new core.ArgumentError.new("splitCommas may not be set if allowMultiple is false.")); + } + this[_addOption](name, abbr, help, valueHelp, allowed, allowedHelp, dart.test(allowMultiple) ? defaultsTo == null ? JSArrayOfString().of([]) : JSArrayOfString().of([defaultsTo]) : defaultsTo, callback, dart.test(allowMultiple) ? src__option.OptionType.multiple : src__option.OptionType.single, {splitCommas: splitCommas, hide: hide}); + } + addMultiOption(name, opts) { + let t1, t1$; + let abbr = opts && 'abbr' in opts ? opts.abbr : null; + let help = opts && 'help' in opts ? opts.help : null; + let valueHelp = opts && 'valueHelp' in opts ? opts.valueHelp : null; + let allowed = opts && 'allowed' in opts ? opts.allowed : null; + let allowedHelp = opts && 'allowedHelp' in opts ? opts.allowedHelp : null; + let defaultsTo = opts && 'defaultsTo' in opts ? opts.defaultsTo : null; + let callback = opts && 'callback' in opts ? opts.callback : null; + let splitCommas = opts && 'splitCommas' in opts ? opts.splitCommas : true; + let hide = opts && 'hide' in opts ? opts.hide : false; + this[_addOption](name, abbr, help, valueHelp, allowed, allowedHelp, (t1$ = (t1 = defaultsTo, t1 == null ? null : t1[$toList]()), t1$ == null ? JSArrayOfString().of([]) : t1$), callback == null ? null : dart.fn(value => callback(ListOfString().as(value)), dynamicTovoid()), src__option.OptionType.multiple, {splitCommas: splitCommas, hide: hide}); + } + [_addOption](name, abbr, help, valueHelp, allowed, allowedHelp, defaultsTo, callback, type, opts) { + let negatable = opts && 'negatable' in opts ? opts.negatable : false; + let splitCommas = opts && 'splitCommas' in opts ? opts.splitCommas : null; + let hide = opts && 'hide' in opts ? opts.hide : false; + if (dart.test(this[_options][$containsKey](name))) { + dart.throw(new core.ArgumentError.new("Duplicate option \"" + dart.str(name) + "\".")); + } + if (abbr != null) { + let existing = this.findByAbbreviation(abbr); + if (existing != null) { + dart.throw(new core.ArgumentError.new("Abbreviation \"" + dart.str(abbr) + "\" is already used by \"" + dart.str(existing.name) + "\".")); + } + } + let option = src__option.newOption(name, abbr, help, valueHelp, allowed, allowedHelp, defaultsTo, callback, type, {negatable: negatable, splitCommas: splitCommas, hide: hide}); + this[_options][$_set](name, option); + this[_optionsAndSeparators][$add](option); + } + addSeparator(text) { + this[_optionsAndSeparators][$add](text); + } + parse(args) { + return new src__parser.Parser.new(null, this, args[$toList]()).parse(); + } + getUsage() { + return this.usage; + } + get usage() { + return new src__usage.Usage.new(this[_optionsAndSeparators], {lineLength: this.usageLineLength}).generate(); + } + getDefault(option) { + if (!dart.test(this.options[$containsKey](option))) { + dart.throw(new core.ArgumentError.new("No option named " + dart.str(option))); + } + return this.options[$_get](option).defaultsTo; + } + findByAbbreviation(abbr) { + return this.options[$values][$firstWhere](dart.fn(option => option.abbr == abbr, OptionTobool()), {orElse: dart.fn(() => null, VoidToNull())}); + } + }; + (src__arg_parser.ArgParser.__ = function(options, commands, opts) { + let allowTrailingOptions = opts && 'allowTrailingOptions' in opts ? opts.allowTrailingOptions : true; + let usageLineLength = opts && 'usageLineLength' in opts ? opts.usageLineLength : null; + this[_optionsAndSeparators] = []; + this[usageLineLength$] = usageLineLength; + this[_options] = options; + this[options$] = new (UnmodifiableMapViewOfString$Option()).new(options); + this[_commands] = commands; + this[commands$] = new (UnmodifiableMapViewOfString$ArgParser()).new(commands); + this[allowTrailingOptions$] = allowTrailingOptions != null ? allowTrailingOptions : false; + ; + }).prototype = src__arg_parser.ArgParser.prototype; + dart.addTypeTests(src__arg_parser.ArgParser); + const options$ = Symbol("ArgParser.options"); + const commands$ = Symbol("ArgParser.commands"); + const allowTrailingOptions$ = Symbol("ArgParser.allowTrailingOptions"); + const usageLineLength$ = Symbol("ArgParser.usageLineLength"); + dart.setMethodSignature(src__arg_parser.ArgParser, () => ({ + __proto__: dart.getMethods(src__arg_parser.ArgParser.__proto__), + addCommand: dart.fnType(src__arg_parser.ArgParser, [core.String], [src__arg_parser.ArgParser]), + addFlag: dart.fnType(dart.void, [core.String], {abbr: core.String, callback: dart.fnType(dart.void, [core.bool]), defaultsTo: core.bool, help: core.String, hide: core.bool, negatable: core.bool}), + addOption: dart.fnType(dart.void, [core.String], {abbr: core.String, allowMultiple: core.bool, allowed: core.Iterable$(core.String), allowedHelp: core.Map$(core.String, core.String), callback: core.Function, defaultsTo: core.String, help: core.String, hide: core.bool, splitCommas: core.bool, valueHelp: core.String}), + addMultiOption: dart.fnType(dart.void, [core.String], {abbr: core.String, allowed: core.Iterable$(core.String), allowedHelp: core.Map$(core.String, core.String), callback: dart.fnType(dart.void, [core.List$(core.String)]), defaultsTo: core.Iterable$(core.String), help: core.String, hide: core.bool, splitCommas: core.bool, valueHelp: core.String}), + [_addOption]: dart.fnType(dart.void, [core.String, core.String, core.String, core.String, core.Iterable$(core.String), core.Map$(core.String, core.String), dart.dynamic, core.Function, src__option.OptionType], {hide: core.bool, negatable: core.bool, splitCommas: core.bool}), + addSeparator: dart.fnType(dart.void, [core.String]), + parse: dart.fnType(src__arg_results.ArgResults, [core.Iterable$(core.String)]), + getUsage: dart.fnType(core.String, []), + getDefault: dart.fnType(dart.dynamic, [core.String]), + findByAbbreviation: dart.fnType(src__option.Option, [core.String]) + })); + dart.setGetterSignature(src__arg_parser.ArgParser, () => ({ + __proto__: dart.getGetters(src__arg_parser.ArgParser.__proto__), + allowsAnything: core.bool, + usage: core.String + })); + dart.setFieldSignature(src__arg_parser.ArgParser, () => ({ + __proto__: dart.getFields(src__arg_parser.ArgParser.__proto__), + [_options]: dart.finalFieldType(core.Map$(core.String, src__option.Option)), + [_commands]: dart.finalFieldType(core.Map$(core.String, src__arg_parser.ArgParser)), + options: dart.finalFieldType(core.Map$(core.String, src__option.Option)), + commands: dart.finalFieldType(core.Map$(core.String, src__arg_parser.ArgParser)), + [_optionsAndSeparators]: dart.finalFieldType(core.List), + allowTrailingOptions: dart.finalFieldType(core.bool), + usageLineLength: dart.finalFieldType(core.int) + })); + let const$24; + src__arg_parser_exception.ArgParserException = class ArgParserException extends core.FormatException { + get commands() { + return this[commands$0]; + } + set commands(value) { + super.commands = value; + } + }; + (src__arg_parser_exception.ArgParserException.new = function(message, commands) { + if (commands === void 0) commands = null; + this[commands$0] = commands == null ? const$24 || (const$24 = dart.constList([], core.String)) : ListOfString().unmodifiable(commands); + src__arg_parser_exception.ArgParserException.__proto__.new.call(this, message); + ; + }).prototype = src__arg_parser_exception.ArgParserException.prototype; + dart.addTypeTests(src__arg_parser_exception.ArgParserException); + const commands$0 = Symbol("ArgParserException.commands"); + dart.setFieldSignature(src__arg_parser_exception.ArgParserException, () => ({ + __proto__: dart.getFields(src__arg_parser_exception.ArgParserException.__proto__), + commands: dart.finalFieldType(core.List$(core.String)) + })); + const _parser$ = Symbol('_parser'); + const _parsed$ = Symbol('_parsed'); + src__arg_results.ArgResults = class ArgResults extends core.Object { + get name() { + return this[name$5]; + } + set name(value) { + super.name = value; + } + get command() { + return this[command$]; + } + set command(value) { + super.command = value; + } + get rest() { + return this[rest$]; + } + set rest(value) { + super.rest = value; + } + get arguments() { + return this[arguments$]; + } + set arguments(value) { + super.arguments = value; + } + _get(name) { + if (!dart.test(this[_parser$].options[$containsKey](name))) { + dart.throw(new core.ArgumentError.new("Could not find an option named \"" + dart.str(name) + "\".")); + } + return this[_parser$].options[$_get](name).getOrDefault(this[_parsed$][$_get](name)); + } + get options() { + let result = LinkedHashSetOfString().from(this[_parsed$][$keys]); + this[_parser$].options[$forEach](dart.fn((name, option) => { + if (option.defaultsTo != null) result.add(name); + }, StringAndOptionToNull())); + return result; + } + wasParsed(name) { + let option = this[_parser$].options[$_get](name); + if (option == null) { + dart.throw(new core.ArgumentError.new("Could not find an option named \"" + dart.str(name) + "\".")); + } + return this[_parsed$][$containsKey](name); + } + }; + (src__arg_results.ArgResults.__ = function(_parser, _parsed, name, command, rest, arguments$0) { + this[_parser$] = _parser; + this[_parsed$] = _parsed; + this[name$5] = name; + this[command$] = command; + this[rest$] = new (UnmodifiableListViewOfString()).new(rest); + this[arguments$] = new (UnmodifiableListViewOfString()).new(arguments$0); + ; + }).prototype = src__arg_results.ArgResults.prototype; + dart.addTypeTests(src__arg_results.ArgResults); + const name$5 = Symbol("ArgResults.name"); + const command$ = Symbol("ArgResults.command"); + const rest$ = Symbol("ArgResults.rest"); + const arguments$ = Symbol("ArgResults.arguments"); + dart.setMethodSignature(src__arg_results.ArgResults, () => ({ + __proto__: dart.getMethods(src__arg_results.ArgResults.__proto__), + _get: dart.fnType(dart.dynamic, [core.String]), + wasParsed: dart.fnType(core.bool, [core.String]) + })); + dart.setGetterSignature(src__arg_results.ArgResults, () => ({ + __proto__: dart.getGetters(src__arg_results.ArgResults.__proto__), + options: core.Iterable$(core.String) + })); + dart.setFieldSignature(src__arg_results.ArgResults, () => ({ + __proto__: dart.getFields(src__arg_results.ArgResults.__proto__), + [_parser$]: dart.finalFieldType(src__arg_parser.ArgParser), + [_parsed$]: dart.finalFieldType(core.Map$(core.String, dart.dynamic)), + name: dart.finalFieldType(core.String), + command: dart.finalFieldType(src__arg_results.ArgResults), + rest: dart.finalFieldType(core.List$(core.String)), + arguments: dart.finalFieldType(core.List$(core.String)) + })); + src__arg_results.newArgResults = function(parser, parsed, name, command, rest, arguments$0) { + return new src__arg_results.ArgResults.__(parser, parsed, name, command, rest, arguments$0); + }; + src__option.Option = class Option extends core.Object { + get name() { + return this[name$6]; + } + set name(value) { + super.name = value; + } + get abbr() { + return this[abbr$]; + } + set abbr(value) { + super.abbr = value; + } + get help() { + return this[help$]; + } + set help(value) { + super.help = value; + } + get valueHelp() { + return this[valueHelp$]; + } + set valueHelp(value) { + super.valueHelp = value; + } + get allowed() { + return this[allowed$]; + } + set allowed(value) { + super.allowed = value; + } + get allowedHelp() { + return this[allowedHelp$]; + } + set allowedHelp(value) { + super.allowedHelp = value; + } + get defaultsTo() { + return this[defaultsTo$]; + } + set defaultsTo(value) { + super.defaultsTo = value; + } + get negatable() { + return this[negatable$]; + } + set negatable(value) { + super.negatable = value; + } + get callback() { + return this[callback$]; + } + set callback(value) { + super.callback = value; + } + get type() { + return this[type$0]; + } + set type(value) { + super.type = value; + } + get splitCommas() { + return this[splitCommas$]; + } + set splitCommas(value) { + super.splitCommas = value; + } + get hide() { + return this[hide$]; + } + set hide(value) { + super.hide = value; + } + get abbreviation() { + return this.abbr; + } + get defaultValue() { + return this.defaultsTo; + } + get isFlag() { + return dart.equals(this.type, src__option.OptionType.flag); + } + get isSingle() { + return dart.equals(this.type, src__option.OptionType.single); + } + get isMultiple() { + return dart.equals(this.type, src__option.OptionType.multiple); + } + getOrDefault(value) { + let t1; + if (value != null) return value; + if (dart.test(this.isMultiple)) { + t1 = this.defaultsTo; + return t1 == null ? JSArrayOfString().of([]) : t1; + } + return this.defaultsTo; + } + }; + (src__option.Option.__ = function(name, abbr, help, valueHelp, allowed, allowedHelp, defaultsTo, callback, type, opts) { + let negatable = opts && 'negatable' in opts ? opts.negatable : null; + let splitCommas = opts && 'splitCommas' in opts ? opts.splitCommas : null; + let hide = opts && 'hide' in opts ? opts.hide : false; + this[name$6] = name; + this[abbr$] = abbr; + this[help$] = help; + this[valueHelp$] = valueHelp; + this[defaultsTo$] = defaultsTo; + this[callback$] = callback; + this[negatable$] = negatable; + this[hide$] = hide; + this[allowed$] = allowed == null ? null : ListOfString().unmodifiable(allowed); + this[allowedHelp$] = allowedHelp == null ? null : MapOfString$String().unmodifiable(allowedHelp); + this[type$0] = type; + this[splitCommas$] = splitCommas == null ? dart.equals(type, src__option.OptionType.multiple) : splitCommas; + if (this.name[$isEmpty]) { + dart.throw(new core.ArgumentError.new("Name cannot be empty.")); + } else if (this.name[$startsWith]("-")) { + dart.throw(new core.ArgumentError.new("Name " + dart.str(this.name) + " cannot start with \"-\".")); + } + if (dart.test(src__option.Option._invalidChars.hasMatch(this.name))) { + dart.throw(new core.ArgumentError.new("Name \"" + dart.str(this.name) + "\" contains invalid characters.")); + } + if (this.abbr != null) { + if (this.abbr.length !== 1) { + dart.throw(new core.ArgumentError.new("Abbreviation must be null or have length 1.")); + } else if (this.abbr === "-") { + dart.throw(new core.ArgumentError.new("Abbreviation cannot be \"-\".")); + } + if (dart.test(src__option.Option._invalidChars.hasMatch(this.abbr))) { + dart.throw(new core.ArgumentError.new("Abbreviation is an invalid character.")); + } + } + }).prototype = src__option.Option.prototype; + dart.addTypeTests(src__option.Option); + const name$6 = Symbol("Option.name"); + const abbr$ = Symbol("Option.abbr"); + const help$ = Symbol("Option.help"); + const valueHelp$ = Symbol("Option.valueHelp"); + const allowed$ = Symbol("Option.allowed"); + const allowedHelp$ = Symbol("Option.allowedHelp"); + const defaultsTo$ = Symbol("Option.defaultsTo"); + const negatable$ = Symbol("Option.negatable"); + const callback$ = Symbol("Option.callback"); + const type$0 = Symbol("Option.type"); + const splitCommas$ = Symbol("Option.splitCommas"); + const hide$ = Symbol("Option.hide"); + dart.setMethodSignature(src__option.Option, () => ({ + __proto__: dart.getMethods(src__option.Option.__proto__), + getOrDefault: dart.fnType(dart.dynamic, [dart.dynamic]) + })); + dart.setGetterSignature(src__option.Option, () => ({ + __proto__: dart.getGetters(src__option.Option.__proto__), + abbreviation: core.String, + defaultValue: dart.dynamic, + isFlag: core.bool, + isSingle: core.bool, + isMultiple: core.bool + })); + dart.setFieldSignature(src__option.Option, () => ({ + __proto__: dart.getFields(src__option.Option.__proto__), + name: dart.finalFieldType(core.String), + abbr: dart.finalFieldType(core.String), + help: dart.finalFieldType(core.String), + valueHelp: dart.finalFieldType(core.String), + allowed: dart.finalFieldType(core.List$(core.String)), + allowedHelp: dart.finalFieldType(core.Map$(core.String, core.String)), + defaultsTo: dart.finalFieldType(dart.dynamic), + negatable: dart.finalFieldType(core.bool), + callback: dart.finalFieldType(core.Function), + type: dart.finalFieldType(src__option.OptionType), + splitCommas: dart.finalFieldType(core.bool), + hide: dart.finalFieldType(core.bool) + })); + dart.defineLazy(src__option.Option, { + /*src__option.Option._invalidChars*/get _invalidChars() { + return core.RegExp.new("[ \\t\\r\\n\"'\\\\/]"); + } + }); + src__option.OptionType = class OptionType extends core.Object { + get name() { + return this[name$7]; + } + set name(value) { + super.name = value; + } + }; + (src__option.OptionType.__ = function(name) { + this[name$7] = name; + ; + }).prototype = src__option.OptionType.prototype; + dart.addTypeTests(src__option.OptionType); + const name$7 = Symbol("OptionType.name"); + dart.setFieldSignature(src__option.OptionType, () => ({ + __proto__: dart.getFields(src__option.OptionType.__proto__), + name: dart.finalFieldType(core.String) + })); + dart.defineLazy(src__option.OptionType, { + /*src__option.OptionType.flag*/get flag() { + return dart.const(new src__option.OptionType.__("OptionType.flag")); + }, + /*src__option.OptionType.FLAG*/get FLAG() { + return src__option.OptionType.flag; + }, + /*src__option.OptionType.single*/get single() { + return dart.const(new src__option.OptionType.__("OptionType.single")); + }, + /*src__option.OptionType.SINGLE*/get SINGLE() { + return src__option.OptionType.single; + }, + /*src__option.OptionType.multiple*/get multiple() { + return dart.const(new src__option.OptionType.__("OptionType.multiple")); + }, + /*src__option.OptionType.MULTIPLE*/get MULTIPLE() { + return src__option.OptionType.multiple; + } + }); + src__option.newOption = function(name, abbr, help, valueHelp, allowed, allowedHelp, defaultsTo, callback, type, opts) { + let negatable = opts && 'negatable' in opts ? opts.negatable : null; + let splitCommas = opts && 'splitCommas' in opts ? opts.splitCommas : null; + let hide = opts && 'hide' in opts ? opts.hide : false; + return new src__option.Option.__(name, abbr, help, valueHelp, allowed, allowedHelp, defaultsTo, callback, type, {negatable: negatable, splitCommas: splitCommas, hide: hide}); + }; + const _singletons = Symbol('_singletons'); + const _factories = Symbol('_factories'); + const _parent$ = Symbol('_parent'); + src__container.Container = class Container extends core.Object { + get reflector() { + return this[reflector$0]; + } + set reflector(value) { + super.reflector = value; + } + get isRoot() { + return this[_parent$] == null; + } + createChild() { + return new src__container.Container._child(this); + } + has(T, t) { + if (t === void 0) t = null; + let search = this; + t == null ? t = dart.wrapType(T)[$_equals](dart.wrapType(dart.dynamic)) ? t : dart.wrapType(T) : null; + while (search != null) { + if (dart.test(search[_singletons][$containsKey](t))) { + return true; + } else if (dart.test(search[_factories][$containsKey](t))) { + return true; + } else { + search = search[_parent$]; + } + } + return false; + } + make(T, type) { + if (type === void 0) type = null; + type == null ? type = dart.wrapType(T) : null; + let search = this; + while (search != null) { + if (dart.test(search[_singletons][$containsKey](type))) { + return T.as(search[_singletons][$_get](type)); + } else if (dart.test(search[_factories][$containsKey](type))) { + return T.as(search[_factories][$_get](type)(this)); + } else { + search = search[_parent$]; + } + } + let reflectedType = this.reflector.reflectType(type); + let positional = []; + let named = new (IdentityMapOfString$dynamic()).new(); + if (src__reflector.ReflectedClass.is(reflectedType)) { + function isDefault(name) { + return name[$isEmpty] || name == reflectedType.name; + } + dart.fn(isDefault, StringTobool()); + let constructor = reflectedType.constructors[$firstWhere](dart.fn(c => isDefault(c.name), ReflectedFunctionTobool()), {orElse: dart.fn(() => dart.throw(new src__exception.ReflectionException.new(dart.str(reflectedType.name) + " has no default constructor, and therefore cannot be instantiated.")), VoidTobottom())}); + for (let param of constructor.parameters) { + let value = this.make(dart.dynamic, param.type.reflectedType); + if (dart.test(param.isNamed)) { + named[$_set](param.name, value); + } else { + positional[$add](value); + } + } + return T._check(reflectedType.newInstance(dart.test(isDefault(constructor.name)) ? "" : constructor.name, positional, named, JSArrayOfType().of([])).reflectee); + } else { + dart.throw(new src__exception.ReflectionException.new(dart.str(type) + " is not a class, and therefore cannot be instantiated.")); + } + } + registerFactory(T, f, opts) { + let as = opts && 'as' in opts ? opts.as : null; + as == null ? as = dart.wrapType(T) : null; + if (dart.test(this[_factories][$containsKey](as))) { + dart.throw(new core.StateError.new("This container already has a factory for " + dart.str(as) + ".")); + } + this[_factories][$_set](as, f); + } + registerSingleton(T, object, opts) { + let t1, t1$, t1$0; + let as = opts && 'as' in opts ? opts.as : null; + as == null ? as = dart.wrapType(T)[$_equals](dart.wrapType(dart.dynamic)) ? as : dart.wrapType(T) : null; + if (dart.test(this[_singletons][$containsKey]((t1 = as, t1 == null ? dart.runtimeType(object) : t1)))) { + dart.throw(new core.StateError.new("This container already has a singleton for " + dart.str((t1$ = as, t1$ == null ? dart.runtimeType(object) : t1$)) + ".")); + } + this[_singletons][$_set]((t1$0 = as, t1$0 == null ? dart.runtimeType(object) : t1$0), object); + } + }; + (src__container.Container.new = function(reflector) { + this[_singletons] = new (LinkedMapOfType$dynamic()).new(); + this[_factories] = new (LinkedMapOfType$ContainerTodynamic()).new(); + this[reflector$0] = reflector; + this[_parent$] = null; + ; + }).prototype = src__container.Container.prototype; + (src__container.Container._child = function(_parent) { + this[_singletons] = new (LinkedMapOfType$dynamic()).new(); + this[_factories] = new (LinkedMapOfType$ContainerTodynamic()).new(); + this[_parent$] = _parent; + this[reflector$0] = _parent.reflector; + ; + }).prototype = src__container.Container.prototype; + dart.addTypeTests(src__container.Container); + const reflector$0 = Symbol("Container.reflector"); + dart.setMethodSignature(src__container.Container, () => ({ + __proto__: dart.getMethods(src__container.Container.__proto__), + createChild: dart.fnType(src__container.Container, []), + has: dart.gFnType(T => [core.bool, [], [core.Type]], T => [core.Object]), + make: dart.gFnType(T => [T, [], [core.Type]], T => [core.Object]), + registerFactory: dart.gFnType(T => [dart.void, [dart.fnType(T, [src__container.Container])], {as: core.Type}], T => [core.Object]), + registerSingleton: dart.gFnType(T => [dart.void, [T], {as: core.Type}], T => [core.Object]) + })); + dart.setGetterSignature(src__container.Container, () => ({ + __proto__: dart.getGetters(src__container.Container.__proto__), + isRoot: core.bool + })); + dart.setFieldSignature(src__container.Container, () => ({ + __proto__: dart.getFields(src__container.Container.__proto__), + reflector: dart.finalFieldType(src__reflector.Reflector), + [_singletons]: dart.finalFieldType(core.Map$(core.Type, dart.dynamic)), + [_factories]: dart.finalFieldType(core.Map$(core.Type, dart.fnType(dart.dynamic, [src__container.Container]))), + [_parent$]: dart.finalFieldType(src__container.Container) + })); + let const$25; + let const$26; + let const$27; + let const$28; + src__empty__empty.EmptyReflector = class EmptyReflector extends core.Object { + getName(symbol) { + return src__empty__empty._symbolNames[$putIfAbsent](symbol, dart.fn(() => src__empty__empty.EmptyReflector.symbolRegex.firstMatch(dart.toString(symbol)).group(1), VoidToString())); + } + reflectClass(clazz) { + return const$25 || (const$25 = dart.const(new src__empty__empty._EmptyReflectedClass.new())); + } + reflectInstance(object) { + return const$26 || (const$26 = dart.const(new src__empty__empty._EmptyReflectedInstance.new())); + } + reflectType(type) { + return const$27 || (const$27 = dart.const(new src__empty__empty._EmptyReflectedType.new())); + } + reflectFunction(function$0) { + return const$28 || (const$28 = dart.const(new src__empty__empty._EmptyReflectedFunction.new())); + } + }; + (src__empty__empty.EmptyReflector.new = function() { + ; + }).prototype = src__empty__empty.EmptyReflector.prototype; + dart.addTypeTests(src__empty__empty.EmptyReflector); + src__empty__empty.EmptyReflector[dart.implements] = () => [src__reflector.Reflector]; + dart.setMethodSignature(src__empty__empty.EmptyReflector, () => ({ + __proto__: dart.getMethods(src__empty__empty.EmptyReflector.__proto__), + getName: dart.fnType(core.String, [core.Symbol]), + reflectClass: dart.fnType(src__reflector.ReflectedClass, [core.Type]), + reflectInstance: dart.fnType(src__reflector.ReflectedInstance, [core.Object]), + reflectType: dart.fnType(src__reflector.ReflectedType, [core.Type]), + reflectFunction: dart.fnType(src__reflector.ReflectedFunction, [core.Function]) + })); + dart.defineLazy(src__empty__empty.EmptyReflector, { + /*src__empty__empty.EmptyReflector.symbolRegex*/get symbolRegex() { + return core.RegExp.new("Symbol\\(\"([^\"]+)\"\\)"); + } + }); + let const$29; + let const$30; + let const$31; + let const$32; + let const$33; + let const$34; + let const$35; + let const$36; + src__reflector.ReflectedType = class ReflectedType extends core.Object { + get name() { + return this[name$8]; + } + set name(value) { + super.name = value; + } + get typeParameters() { + return this[typeParameters$]; + } + set typeParameters(value) { + super.typeParameters = value; + } + get reflectedType() { + return this[reflectedType$]; + } + set reflectedType(value) { + super.reflectedType = value; + } + get hashCode() { + return core$.hash3(this.name, this.typeParameters, this.reflectedType); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedType.is(other) && other.name == this.name && dart.test((const$36 || (const$36 = dart.const(new (ListEqualityOfReflectedTypeParameter()).new()))).equals(other.typeParameters, this.typeParameters)) && dart.equals(other.reflectedType, this.reflectedType); + } + }; + (src__reflector.ReflectedType.new = function(name, typeParameters, reflectedType) { + this[name$8] = name; + this[typeParameters$] = typeParameters; + this[reflectedType$] = reflectedType; + ; + }).prototype = src__reflector.ReflectedType.prototype; + dart.addTypeTests(src__reflector.ReflectedType); + const name$8 = Symbol("ReflectedType.name"); + const typeParameters$ = Symbol("ReflectedType.typeParameters"); + const reflectedType$ = Symbol("ReflectedType.reflectedType"); + dart.setFieldSignature(src__reflector.ReflectedType, () => ({ + __proto__: dart.getFields(src__reflector.ReflectedType.__proto__), + name: dart.finalFieldType(core.String), + typeParameters: dart.finalFieldType(core.List$(src__reflector.ReflectedTypeParameter)), + reflectedType: dart.finalFieldType(core.Type) + })); + dart.defineExtensionMethods(src__reflector.ReflectedType, ['_equals']); + dart.defineExtensionAccessors(src__reflector.ReflectedType, ['hashCode']); + src__reflector.ReflectedClass = class ReflectedClass extends src__reflector.ReflectedType { + get annotations() { + return this[annotations$]; + } + set annotations(value) { + super.annotations = value; + } + get constructors() { + return this[constructors$]; + } + set constructors(value) { + super.constructors = value; + } + get declarations() { + return this[declarations$]; + } + set declarations(value) { + super.declarations = value; + } + get hashCode() { + return core$.hash4(super.hashCode, this.annotations, this.constructors, this.declarations); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedClass.is(other) && super._equals(other) && dart.test((const$33 || (const$33 = dart.const(new (ListEqualityOfReflectedInstance()).new()))).equals(other.annotations, this.annotations)) && dart.test((const$34 || (const$34 = dart.const(new (ListEqualityOfReflectedFunction()).new()))).equals(other.constructors, this.constructors)) && dart.test((const$35 || (const$35 = dart.const(new (ListEqualityOfReflectedDeclaration()).new()))).equals(other.declarations, this.declarations)); + } + }; + (src__reflector.ReflectedClass.new = function(name, typeParameters, annotations, constructors, declarations, reflectedType) { + this[annotations$] = annotations; + this[constructors$] = constructors; + this[declarations$] = declarations; + src__reflector.ReflectedClass.__proto__.new.call(this, name, typeParameters, reflectedType); + ; + }).prototype = src__reflector.ReflectedClass.prototype; + dart.addTypeTests(src__reflector.ReflectedClass); + const annotations$ = Symbol("ReflectedClass.annotations"); + const constructors$ = Symbol("ReflectedClass.constructors"); + const declarations$ = Symbol("ReflectedClass.declarations"); + dart.setFieldSignature(src__reflector.ReflectedClass, () => ({ + __proto__: dart.getFields(src__reflector.ReflectedClass.__proto__), + annotations: dart.finalFieldType(core.List$(src__reflector.ReflectedInstance)), + constructors: dart.finalFieldType(core.List$(src__reflector.ReflectedFunction)), + declarations: dart.finalFieldType(core.List$(src__reflector.ReflectedDeclaration)) + })); + dart.defineExtensionMethods(src__reflector.ReflectedClass, ['_equals']); + dart.defineExtensionAccessors(src__reflector.ReflectedClass, ['hashCode']); + src__empty__empty._EmptyReflectedClass = class _EmptyReflectedClass extends src__reflector.ReflectedClass { + newInstance(constructorName, positionalArguments, namedArguments, typeArguments) { + if (namedArguments === void 0) namedArguments = null; + if (typeArguments === void 0) typeArguments = null; + dart.throw(new core.UnsupportedError.new("Classes reflected via an EmptyReflector cannot be instantiated.")); + } + isAssignableTo(other) { + return dart.equals(other, this); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedClass.is(other) && dart.hashCode(other) == this.hashCode; + } + }; + (src__empty__empty._EmptyReflectedClass.new = function() { + src__empty__empty._EmptyReflectedClass.__proto__.new.call(this, "(empty)", const$29 || (const$29 = dart.constList([], src__reflector.ReflectedTypeParameter)), const$30 || (const$30 = dart.constList([], src__reflector.ReflectedInstance)), const$31 || (const$31 = dart.constList([], src__reflector.ReflectedFunction)), const$32 || (const$32 = dart.constList([], src__reflector.ReflectedDeclaration)), dart.wrapType(dart.dynamic)); + ; + }).prototype = src__empty__empty._EmptyReflectedClass.prototype; + dart.addTypeTests(src__empty__empty._EmptyReflectedClass); + dart.setMethodSignature(src__empty__empty._EmptyReflectedClass, () => ({ + __proto__: dart.getMethods(src__empty__empty._EmptyReflectedClass.__proto__), + newInstance: dart.fnType(src__reflector.ReflectedInstance, [core.String, core.List], [core.Map$(core.String, dart.dynamic), core.List$(core.Type)]), + isAssignableTo: dart.fnType(core.bool, [src__reflector.ReflectedType]) + })); + dart.defineExtensionMethods(src__empty__empty._EmptyReflectedClass, ['_equals']); + let const$37; + src__empty__empty._EmptyReflectedType = class _EmptyReflectedType extends src__reflector.ReflectedType { + newInstance(constructorName, positionalArguments, namedArguments, typeArguments) { + if (namedArguments === void 0) namedArguments = null; + if (typeArguments === void 0) typeArguments = null; + dart.throw(new core.UnsupportedError.new("Types reflected via an EmptyReflector cannot be instantiated.")); + } + isAssignableTo(other) { + return dart.equals(other, this); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedType.is(other) && dart.hashCode(other) == this.hashCode; + } + }; + (src__empty__empty._EmptyReflectedType.new = function() { + src__empty__empty._EmptyReflectedType.__proto__.new.call(this, "(empty)", const$37 || (const$37 = dart.constList([], src__reflector.ReflectedTypeParameter)), dart.wrapType(dart.dynamic)); + ; + }).prototype = src__empty__empty._EmptyReflectedType.prototype; + dart.addTypeTests(src__empty__empty._EmptyReflectedType); + dart.setMethodSignature(src__empty__empty._EmptyReflectedType, () => ({ + __proto__: dart.getMethods(src__empty__empty._EmptyReflectedType.__proto__), + newInstance: dart.fnType(src__reflector.ReflectedInstance, [core.String, core.List], [core.Map$(core.String, dart.dynamic), core.List$(core.Type)]), + isAssignableTo: dart.fnType(core.bool, [src__reflector.ReflectedType]) + })); + dart.defineExtensionMethods(src__empty__empty._EmptyReflectedType, ['_equals']); + let const$38; + let const$39; + src__reflector.ReflectedInstance = class ReflectedInstance extends core.Object { + get type() { + return this[type$1]; + } + set type(value) { + super.type = value; + } + get clazz() { + return this[clazz$]; + } + set clazz(value) { + super.clazz = value; + } + get reflectee() { + return this[reflectee$]; + } + set reflectee(value) { + super.reflectee = value; + } + get hashCode() { + return core$.hash2(this.type, this.clazz); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedInstance.is(other) && dart.equals(other.type, this.type) && dart.equals(other.clazz, this.clazz); + } + }; + (src__reflector.ReflectedInstance.new = function(type, clazz, reflectee) { + this[type$1] = type; + this[clazz$] = clazz; + this[reflectee$] = reflectee; + ; + }).prototype = src__reflector.ReflectedInstance.prototype; + dart.addTypeTests(src__reflector.ReflectedInstance); + const type$1 = Symbol("ReflectedInstance.type"); + const clazz$ = Symbol("ReflectedInstance.clazz"); + const reflectee$ = Symbol("ReflectedInstance.reflectee"); + dart.setFieldSignature(src__reflector.ReflectedInstance, () => ({ + __proto__: dart.getFields(src__reflector.ReflectedInstance.__proto__), + type: dart.finalFieldType(src__reflector.ReflectedType), + clazz: dart.finalFieldType(src__reflector.ReflectedClass), + reflectee: dart.finalFieldType(core.Object) + })); + dart.defineExtensionMethods(src__reflector.ReflectedInstance, ['_equals']); + dart.defineExtensionAccessors(src__reflector.ReflectedInstance, ['hashCode']); + src__empty__empty._EmptyReflectedInstance = class _EmptyReflectedInstance extends src__reflector.ReflectedInstance { + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedInstance.is(other) && dart.hashCode(other) == this.hashCode; + } + getField(name) { + dart.throw(new core.UnsupportedError.new("Instances reflected via an EmptyReflector cannot call getField().")); + } + }; + (src__empty__empty._EmptyReflectedInstance.new = function() { + src__empty__empty._EmptyReflectedInstance.__proto__.new.call(this, const$38 || (const$38 = dart.const(new src__empty__empty._EmptyReflectedType.new())), const$39 || (const$39 = dart.const(new src__empty__empty._EmptyReflectedClass.new())), null); + ; + }).prototype = src__empty__empty._EmptyReflectedInstance.prototype; + dart.addTypeTests(src__empty__empty._EmptyReflectedInstance); + dart.setMethodSignature(src__empty__empty._EmptyReflectedInstance, () => ({ + __proto__: dart.getMethods(src__empty__empty._EmptyReflectedInstance.__proto__), + getField: dart.fnType(src__reflector.ReflectedInstance, [core.String]) + })); + dart.defineExtensionMethods(src__empty__empty._EmptyReflectedInstance, ['_equals']); + let const$40; + let const$41; + let const$42; + let const$43; + let const$44; + let const$45; + let const$46; + src__reflector.ReflectedFunction = class ReflectedFunction extends core.Object { + get name() { + return this[name$9]; + } + set name(value) { + super.name = value; + } + get typeParameters() { + return this[typeParameters$0]; + } + set typeParameters(value) { + super.typeParameters = value; + } + get annotations() { + return this[annotations$0]; + } + set annotations(value) { + super.annotations = value; + } + get returnType() { + return this[returnType$]; + } + set returnType(value) { + super.returnType = value; + } + get parameters() { + return this[parameters$0]; + } + set parameters(value) { + super.parameters = value; + } + get isGetter() { + return this[isGetter$]; + } + set isGetter(value) { + super.isGetter = value; + } + get isSetter() { + return this[isSetter$]; + } + set isSetter(value) { + super.isSetter = value; + } + get hashCode() { + return core$.hashObjects([this.name, this.typeParameters, this.annotations, this.returnType, this.parameters, this.isGetter, this.isSetter]); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedFunction.is(other) && other.name == this.name && dart.test((const$44 || (const$44 = dart.const(new (ListEqualityOfReflectedTypeParameter()).new()))).equals(other.typeParameters, this.typeParameters)) && dart.test((const$45 || (const$45 = dart.const(new (ListEqualityOfReflectedInstance()).new()))).equals(other.annotations, this.annotations)) && dart.equals(other.returnType, this.returnType) && dart.test((const$46 || (const$46 = dart.const(new (ListEqualityOfReflectedParameter()).new()))).equals(other.parameters, other.parameters)) && dart.equals(other.isGetter, this.isGetter) && dart.equals(other.isSetter, this.isSetter); + } + }; + (src__reflector.ReflectedFunction.new = function(name, typeParameters, annotations, returnType, parameters, isGetter, isSetter) { + this[name$9] = name; + this[typeParameters$0] = typeParameters; + this[annotations$0] = annotations; + this[returnType$] = returnType; + this[parameters$0] = parameters; + this[isGetter$] = isGetter; + this[isSetter$] = isSetter; + ; + }).prototype = src__reflector.ReflectedFunction.prototype; + dart.addTypeTests(src__reflector.ReflectedFunction); + const name$9 = Symbol("ReflectedFunction.name"); + const typeParameters$0 = Symbol("ReflectedFunction.typeParameters"); + const annotations$0 = Symbol("ReflectedFunction.annotations"); + const returnType$ = Symbol("ReflectedFunction.returnType"); + const parameters$0 = Symbol("ReflectedFunction.parameters"); + const isGetter$ = Symbol("ReflectedFunction.isGetter"); + const isSetter$ = Symbol("ReflectedFunction.isSetter"); + dart.setFieldSignature(src__reflector.ReflectedFunction, () => ({ + __proto__: dart.getFields(src__reflector.ReflectedFunction.__proto__), + name: dart.finalFieldType(core.String), + typeParameters: dart.finalFieldType(core.List$(src__reflector.ReflectedTypeParameter)), + annotations: dart.finalFieldType(core.List$(src__reflector.ReflectedInstance)), + returnType: dart.finalFieldType(src__reflector.ReflectedType), + parameters: dart.finalFieldType(core.List$(src__reflector.ReflectedParameter)), + isGetter: dart.finalFieldType(core.bool), + isSetter: dart.finalFieldType(core.bool) + })); + dart.defineExtensionMethods(src__reflector.ReflectedFunction, ['_equals']); + dart.defineExtensionAccessors(src__reflector.ReflectedFunction, ['hashCode']); + src__empty__empty._EmptyReflectedFunction = class _EmptyReflectedFunction extends src__reflector.ReflectedFunction { + invoke(invocation) { + dart.throw(new core.UnsupportedError.new("Instances reflected via an EmptyReflector cannot call invoke().")); + } + }; + (src__empty__empty._EmptyReflectedFunction.new = function() { + src__empty__empty._EmptyReflectedFunction.__proto__.new.call(this, "(empty)", const$40 || (const$40 = dart.constList([], src__reflector.ReflectedTypeParameter)), const$41 || (const$41 = dart.constList([], src__reflector.ReflectedInstance)), const$42 || (const$42 = dart.const(new src__empty__empty._EmptyReflectedType.new())), const$43 || (const$43 = dart.constList([], src__reflector.ReflectedParameter)), false, false); + ; + }).prototype = src__empty__empty._EmptyReflectedFunction.prototype; + dart.addTypeTests(src__empty__empty._EmptyReflectedFunction); + dart.setMethodSignature(src__empty__empty._EmptyReflectedFunction, () => ({ + __proto__: dart.getMethods(src__empty__empty._EmptyReflectedFunction.__proto__), + invoke: dart.fnType(src__reflector.ReflectedInstance, [core.Invocation]) + })); + dart.defineLazy(src__empty__empty, { + /*src__empty__empty._symbolNames*/get _symbolNames() { + return new (LinkedMapOfSymbol$String()).new(); + } + }); + src__exception.ReflectionException = class ReflectionException extends core.Object { + get message() { + return this[message$1]; + } + set message(value) { + super.message = value; + } + toString() { + return this.message; + } + }; + (src__exception.ReflectionException.new = function(message) { + this[message$1] = message; + ; + }).prototype = src__exception.ReflectionException.prototype; + dart.addTypeTests(src__exception.ReflectionException); + const message$1 = Symbol("ReflectionException.message"); + src__exception.ReflectionException[dart.implements] = () => [core.Exception]; + dart.setFieldSignature(src__exception.ReflectionException, () => ({ + __proto__: dart.getFields(src__exception.ReflectionException.__proto__), + message: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__exception.ReflectionException, ['toString']); + src__reflector.Reflector = class Reflector extends core.Object {}; + (src__reflector.Reflector.new = function() { + ; + }).prototype = src__reflector.Reflector.prototype; + dart.addTypeTests(src__reflector.Reflector); + src__reflector.ReflectedDeclaration = class ReflectedDeclaration extends core.Object { + get name() { + return this[name$10]; + } + set name(value) { + super.name = value; + } + get isStatic() { + return this[isStatic$]; + } + set isStatic(value) { + super.isStatic = value; + } + get function() { + return this[func]; + } + set function(value) { + super.function = value; + } + get hashCode() { + return core$.hash3(this.name, this.isStatic, this.function); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedDeclaration.is(other) && other.name == this.name && dart.equals(other.isStatic, this.isStatic) && dart.equals(other.function, this.function); + } + }; + (src__reflector.ReflectedDeclaration.new = function(name, isStatic, function$0) { + this[name$10] = name; + this[isStatic$] = isStatic; + this[func] = function$0; + ; + }).prototype = src__reflector.ReflectedDeclaration.prototype; + dart.addTypeTests(src__reflector.ReflectedDeclaration); + const name$10 = Symbol("ReflectedDeclaration.name"); + const isStatic$ = Symbol("ReflectedDeclaration.isStatic"); + const func = Symbol("ReflectedDeclaration.function"); + dart.setFieldSignature(src__reflector.ReflectedDeclaration, () => ({ + __proto__: dart.getFields(src__reflector.ReflectedDeclaration.__proto__), + name: dart.finalFieldType(core.String), + isStatic: dart.finalFieldType(core.bool), + function: dart.finalFieldType(src__reflector.ReflectedFunction) + })); + dart.defineExtensionMethods(src__reflector.ReflectedDeclaration, ['_equals']); + dart.defineExtensionAccessors(src__reflector.ReflectedDeclaration, ['hashCode']); + let const$47; + src__reflector.ReflectedParameter = class ReflectedParameter extends core.Object { + get name() { + return this[name$11]; + } + set name(value) { + super.name = value; + } + get annotations() { + return this[annotations$1]; + } + set annotations(value) { + super.annotations = value; + } + get type() { + return this[type$2]; + } + set type(value) { + super.type = value; + } + get isRequired() { + return this[isRequired$]; + } + set isRequired(value) { + super.isRequired = value; + } + get isNamed() { + return this[isNamed$]; + } + set isNamed(value) { + super.isNamed = value; + } + get hashCode() { + return core$.hashObjects([this.name, this.annotations, this.type, this.isRequired, this.isNamed]); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedParameter.is(other) && other.name == this.name && dart.test((const$47 || (const$47 = dart.const(new (ListEqualityOfReflectedInstance()).new()))).equals(other.annotations, this.annotations)) && dart.equals(other.type, this.type) && dart.equals(other.isRequired, this.isRequired) && dart.equals(other.isNamed, this.isNamed); + } + }; + (src__reflector.ReflectedParameter.new = function(name, annotations, type, isRequired, isNamed) { + this[name$11] = name; + this[annotations$1] = annotations; + this[type$2] = type; + this[isRequired$] = isRequired; + this[isNamed$] = isNamed; + ; + }).prototype = src__reflector.ReflectedParameter.prototype; + dart.addTypeTests(src__reflector.ReflectedParameter); + const name$11 = Symbol("ReflectedParameter.name"); + const annotations$1 = Symbol("ReflectedParameter.annotations"); + const type$2 = Symbol("ReflectedParameter.type"); + const isRequired$ = Symbol("ReflectedParameter.isRequired"); + const isNamed$ = Symbol("ReflectedParameter.isNamed"); + dart.setFieldSignature(src__reflector.ReflectedParameter, () => ({ + __proto__: dart.getFields(src__reflector.ReflectedParameter.__proto__), + name: dart.finalFieldType(core.String), + annotations: dart.finalFieldType(core.List$(src__reflector.ReflectedInstance)), + type: dart.finalFieldType(src__reflector.ReflectedType), + isRequired: dart.finalFieldType(core.bool), + isNamed: dart.finalFieldType(core.bool) + })); + dart.defineExtensionMethods(src__reflector.ReflectedParameter, ['_equals']); + dart.defineExtensionAccessors(src__reflector.ReflectedParameter, ['hashCode']); + src__reflector.ReflectedTypeParameter = class ReflectedTypeParameter extends core.Object { + get name() { + return this[name$12]; + } + set name(value) { + super.name = value; + } + get hashCode() { + return core$.hashObjects([this.name]); + } + _equals(other) { + if (other == null) return false; + return src__reflector.ReflectedTypeParameter.is(other) && other.name == this.name; + } + }; + (src__reflector.ReflectedTypeParameter.new = function(name) { + this[name$12] = name; + ; + }).prototype = src__reflector.ReflectedTypeParameter.prototype; + dart.addTypeTests(src__reflector.ReflectedTypeParameter); + const name$12 = Symbol("ReflectedTypeParameter.name"); + dart.setFieldSignature(src__reflector.ReflectedTypeParameter, () => ({ + __proto__: dart.getFields(src__reflector.ReflectedTypeParameter.__proto__), + name: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__reflector.ReflectedTypeParameter, ['_equals']); + dart.defineExtensionAccessors(src__reflector.ReflectedTypeParameter, ['hashCode']); + const _name$ = Symbol('_name'); + src__ansi_code.AnsiCodeType = class AnsiCodeType extends core.Object { + toString() { + return "AnsiType." + dart.str(this[_name$]); + } + }; + (src__ansi_code.AnsiCodeType.__ = function(_name) { + this[_name$] = _name; + ; + }).prototype = src__ansi_code.AnsiCodeType.prototype; + dart.addTypeTests(src__ansi_code.AnsiCodeType); + dart.setFieldSignature(src__ansi_code.AnsiCodeType, () => ({ + __proto__: dart.getFields(src__ansi_code.AnsiCodeType.__proto__), + [_name$]: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__ansi_code.AnsiCodeType, ['toString']); + dart.defineLazy(src__ansi_code.AnsiCodeType, { + /*src__ansi_code.AnsiCodeType.foreground*/get foreground() { + return dart.const(new src__ansi_code.AnsiCodeType.__("foreground")); + }, + /*src__ansi_code.AnsiCodeType.style*/get style() { + return dart.const(new src__ansi_code.AnsiCodeType.__("style")); + }, + /*src__ansi_code.AnsiCodeType.background*/get background() { + return dart.const(new src__ansi_code.AnsiCodeType.__("background")); + }, + /*src__ansi_code.AnsiCodeType.reset*/get reset() { + return dart.const(new src__ansi_code.AnsiCodeType.__("reset")); + } + }); + const _escapeValue = Symbol('_escapeValue'); + src__ansi_code.AnsiCode = class AnsiCode extends core.Object { + get code() { + return this[code$]; + } + set code(value) { + super.code = value; + } + get reset() { + return this[reset$]; + } + set reset(value) { + super.reset = value; + } + get name() { + return this[name$13]; + } + set name(value) { + super.name = value; + } + get type() { + return this[type$3]; + } + set type(value) { + super.type = value; + } + get escape() { + return dart.str("") + "[" + dart.str(this.code) + "m"; + } + get escapeForScript() { + return dart.str("\\033") + "[" + dart.str(this.code) + "m"; + } + [_escapeValue](opts) { + let forScript = opts && 'forScript' in opts ? opts.forScript : false; + forScript == null ? forScript = false : null; + return dart.test(forScript) ? this.escapeForScript : this.escape; + } + wrap(value, opts) { + let forScript = opts && 'forScript' in opts ? opts.forScript : false; + return dart.test(src__ansi_code._isNoop(dart.equals(this.type, src__ansi_code.AnsiCodeType.reset), value, forScript)) ? value : dart.str(this[_escapeValue]({forScript: forScript})) + dart.str(value) + dart.str(this.reset[_escapeValue]({forScript: forScript})); + } + toString() { + return dart.str(this.name) + " " + dart.str(this.type[_name$]) + " (" + dart.str(this.code) + ")"; + } + }; + (src__ansi_code.AnsiCode.__ = function(name, type, code, reset) { + this[name$13] = name; + this[type$3] = type; + this[code$] = code; + this[reset$] = reset; + ; + }).prototype = src__ansi_code.AnsiCode.prototype; + dart.addTypeTests(src__ansi_code.AnsiCode); + const code$ = Symbol("AnsiCode.code"); + const reset$ = Symbol("AnsiCode.reset"); + const name$13 = Symbol("AnsiCode.name"); + const type$3 = Symbol("AnsiCode.type"); + dart.setMethodSignature(src__ansi_code.AnsiCode, () => ({ + __proto__: dart.getMethods(src__ansi_code.AnsiCode.__proto__), + [_escapeValue]: dart.fnType(core.String, [], {forScript: core.bool}), + wrap: dart.fnType(core.String, [core.String], {forScript: core.bool}) + })); + dart.setGetterSignature(src__ansi_code.AnsiCode, () => ({ + __proto__: dart.getGetters(src__ansi_code.AnsiCode.__proto__), + escape: core.String, + escapeForScript: core.String + })); + dart.setFieldSignature(src__ansi_code.AnsiCode, () => ({ + __proto__: dart.getFields(src__ansi_code.AnsiCode.__proto__), + code: dart.finalFieldType(core.int), + reset: dart.finalFieldType(src__ansi_code.AnsiCode), + name: dart.finalFieldType(core.String), + type: dart.finalFieldType(src__ansi_code.AnsiCodeType) + })); + dart.defineExtensionMethods(src__ansi_code.AnsiCode, ['toString']); + src__ansi_code._isNoop = function(skip, input, forScript) { + let t1; + return dart.test(skip) || input == null || input[$isEmpty] || !(dart.test((t1 = forScript, t1 == null ? false : t1)) || dart.test(src__ansi_code.ansiOutputEnabled)); + }; + src__ansi_code.overrideAnsiOutput = function(T, enableAnsiOutput, body) { + return async.runZoned(T, body, {zoneValues: new (LinkedMapOfObject$Object()).from([dart.wrapType(src__ansi_code.AnsiCode), enableAnsiOutput])}); + }; + src__ansi_code.wrapWith = function(value, codes, opts) { + let t1; + let forScript = opts && 'forScript' in opts ? opts.forScript : false; + forScript == null ? forScript = false : null; + let myCodes = codes[$toSet](); + if (dart.test(src__ansi_code._isNoop(myCodes[$isEmpty], value, forScript))) { + return value; + } + let foreground = 0; + let background = 0; + for (let code of myCodes) { + switch (code.type) { + case src__ansi_code.AnsiCodeType.foreground: + { + foreground = foreground + 1; + if (foreground > 1) { + dart.throw(new core.ArgumentError.value(codes, "codes", "Cannot contain more than one foreground color code.")); + } + break; + } + case src__ansi_code.AnsiCodeType.background: + { + background = background + 1; + if (background > 1) { + dart.throw(new core.ArgumentError.value(codes, "codes", "Cannot contain more than one foreground color code.")); + } + break; + } + case src__ansi_code.AnsiCodeType.reset: + { + dart.throw(new core.ArgumentError.value(codes, "codes", "Cannot contain reset codes.")); + break; + } + } + } + let sortedCodes = (t1 = myCodes[$map](core.int, dart.fn(ac => ac.code, AnsiCodeToint()))[$toList](), t1[$sort](), t1); + let escapeValue = dart.test(forScript) ? "\\033" : ""; + return dart.str(escapeValue) + "[" + dart.str(sortedCodes[$join](";")) + "m" + dart.str(value) + dart.str(src__ansi_code.resetAll[_escapeValue]({forScript: forScript})); + }; + dart.copyProperties(src__ansi_code, { + get ansiOutputEnabled() { + let t1; + t1 = core.bool.as(async.Zone.current._get(dart.wrapType(src__ansi_code.AnsiCode))); + return t1 == null ? dart.test(io.stdout.supportsAnsiEscapes) && dart.test(io.stderr.supportsAnsiEscapes) : t1; + } + }); + dart.defineLazy(src__ansi_code, { + /*src__ansi_code._ansiEscapeLiteral*/get _ansiEscapeLiteral() { + return ""; + }, + /*src__ansi_code._ansiEscapeForScript*/get _ansiEscapeForScript() { + return "\\033"; + }, + /*src__ansi_code.styleBold*/get styleBold() { + return dart.const(new src__ansi_code.AnsiCode.__("bold", src__ansi_code.AnsiCodeType.style, 1, src__ansi_code.resetBold)); + }, + /*src__ansi_code.styleDim*/get styleDim() { + return dart.const(new src__ansi_code.AnsiCode.__("dim", src__ansi_code.AnsiCodeType.style, 2, src__ansi_code.resetDim)); + }, + /*src__ansi_code.styleItalic*/get styleItalic() { + return dart.const(new src__ansi_code.AnsiCode.__("italic", src__ansi_code.AnsiCodeType.style, 3, src__ansi_code.resetItalic)); + }, + /*src__ansi_code.styleUnderlined*/get styleUnderlined() { + return dart.const(new src__ansi_code.AnsiCode.__("underlined", src__ansi_code.AnsiCodeType.style, 4, src__ansi_code.resetUnderlined)); + }, + /*src__ansi_code.styleBlink*/get styleBlink() { + return dart.const(new src__ansi_code.AnsiCode.__("blink", src__ansi_code.AnsiCodeType.style, 5, src__ansi_code.resetBlink)); + }, + /*src__ansi_code.styleReverse*/get styleReverse() { + return dart.const(new src__ansi_code.AnsiCode.__("reverse", src__ansi_code.AnsiCodeType.style, 7, src__ansi_code.resetReverse)); + }, + /*src__ansi_code.styleHidden*/get styleHidden() { + return dart.const(new src__ansi_code.AnsiCode.__("hidden", src__ansi_code.AnsiCodeType.style, 8, src__ansi_code.resetHidden)); + }, + /*src__ansi_code.styleCrossedOut*/get styleCrossedOut() { + return dart.const(new src__ansi_code.AnsiCode.__("crossed out", src__ansi_code.AnsiCodeType.style, 9, src__ansi_code.resetCrossedOut)); + }, + /*src__ansi_code.resetAll*/get resetAll() { + return dart.const(new src__ansi_code.AnsiCode.__("all", src__ansi_code.AnsiCodeType.reset, 0, null)); + }, + /*src__ansi_code.resetBold*/get resetBold() { + return dart.const(new src__ansi_code.AnsiCode.__("bold", src__ansi_code.AnsiCodeType.reset, 22, null)); + }, + /*src__ansi_code.resetDim*/get resetDim() { + return dart.const(new src__ansi_code.AnsiCode.__("dim", src__ansi_code.AnsiCodeType.reset, 22, null)); + }, + /*src__ansi_code.resetItalic*/get resetItalic() { + return dart.const(new src__ansi_code.AnsiCode.__("italic", src__ansi_code.AnsiCodeType.reset, 23, null)); + }, + /*src__ansi_code.resetUnderlined*/get resetUnderlined() { + return dart.const(new src__ansi_code.AnsiCode.__("underlined", src__ansi_code.AnsiCodeType.reset, 24, null)); + }, + /*src__ansi_code.resetBlink*/get resetBlink() { + return dart.const(new src__ansi_code.AnsiCode.__("blink", src__ansi_code.AnsiCodeType.reset, 25, null)); + }, + /*src__ansi_code.resetReverse*/get resetReverse() { + return dart.const(new src__ansi_code.AnsiCode.__("reverse", src__ansi_code.AnsiCodeType.reset, 27, null)); + }, + /*src__ansi_code.resetHidden*/get resetHidden() { + return dart.const(new src__ansi_code.AnsiCode.__("hidden", src__ansi_code.AnsiCodeType.reset, 28, null)); + }, + /*src__ansi_code.resetCrossedOut*/get resetCrossedOut() { + return dart.const(new src__ansi_code.AnsiCode.__("crossed out", src__ansi_code.AnsiCodeType.reset, 29, null)); + }, + /*src__ansi_code.black*/get black() { + return dart.const(new src__ansi_code.AnsiCode.__("black", src__ansi_code.AnsiCodeType.foreground, 30, src__ansi_code.resetAll)); + }, + /*src__ansi_code.red*/get red() { + return dart.const(new src__ansi_code.AnsiCode.__("red", src__ansi_code.AnsiCodeType.foreground, 31, src__ansi_code.resetAll)); + }, + /*src__ansi_code.green*/get green() { + return dart.const(new src__ansi_code.AnsiCode.__("green", src__ansi_code.AnsiCodeType.foreground, 32, src__ansi_code.resetAll)); + }, + /*src__ansi_code.yellow*/get yellow() { + return dart.const(new src__ansi_code.AnsiCode.__("yellow", src__ansi_code.AnsiCodeType.foreground, 33, src__ansi_code.resetAll)); + }, + /*src__ansi_code.blue*/get blue() { + return dart.const(new src__ansi_code.AnsiCode.__("blue", src__ansi_code.AnsiCodeType.foreground, 34, src__ansi_code.resetAll)); + }, + /*src__ansi_code.magenta*/get magenta() { + return dart.const(new src__ansi_code.AnsiCode.__("magenta", src__ansi_code.AnsiCodeType.foreground, 35, src__ansi_code.resetAll)); + }, + /*src__ansi_code.cyan*/get cyan() { + return dart.const(new src__ansi_code.AnsiCode.__("cyan", src__ansi_code.AnsiCodeType.foreground, 36, src__ansi_code.resetAll)); + }, + /*src__ansi_code.lightGray*/get lightGray() { + return dart.const(new src__ansi_code.AnsiCode.__("light gray", src__ansi_code.AnsiCodeType.foreground, 37, src__ansi_code.resetAll)); + }, + /*src__ansi_code.defaultForeground*/get defaultForeground() { + return dart.const(new src__ansi_code.AnsiCode.__("default", src__ansi_code.AnsiCodeType.foreground, 39, src__ansi_code.resetAll)); + }, + /*src__ansi_code.darkGray*/get darkGray() { + return dart.const(new src__ansi_code.AnsiCode.__("dark gray", src__ansi_code.AnsiCodeType.foreground, 90, src__ansi_code.resetAll)); + }, + /*src__ansi_code.lightRed*/get lightRed() { + return dart.const(new src__ansi_code.AnsiCode.__("light red", src__ansi_code.AnsiCodeType.foreground, 91, src__ansi_code.resetAll)); + }, + /*src__ansi_code.lightGreen*/get lightGreen() { + return dart.const(new src__ansi_code.AnsiCode.__("light green", src__ansi_code.AnsiCodeType.foreground, 92, src__ansi_code.resetAll)); + }, + /*src__ansi_code.lightYellow*/get lightYellow() { + return dart.const(new src__ansi_code.AnsiCode.__("light yellow", src__ansi_code.AnsiCodeType.foreground, 93, src__ansi_code.resetAll)); + }, + /*src__ansi_code.lightBlue*/get lightBlue() { + return dart.const(new src__ansi_code.AnsiCode.__("light blue", src__ansi_code.AnsiCodeType.foreground, 94, src__ansi_code.resetAll)); + }, + /*src__ansi_code.lightMagenta*/get lightMagenta() { + return dart.const(new src__ansi_code.AnsiCode.__("light magenta", src__ansi_code.AnsiCodeType.foreground, 95, src__ansi_code.resetAll)); + }, + /*src__ansi_code.lightCyan*/get lightCyan() { + return dart.const(new src__ansi_code.AnsiCode.__("light cyan", src__ansi_code.AnsiCodeType.foreground, 96, src__ansi_code.resetAll)); + }, + /*src__ansi_code.white*/get white() { + return dart.const(new src__ansi_code.AnsiCode.__("white", src__ansi_code.AnsiCodeType.foreground, 97, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundBlack*/get backgroundBlack() { + return dart.const(new src__ansi_code.AnsiCode.__("black", src__ansi_code.AnsiCodeType.background, 40, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundRed*/get backgroundRed() { + return dart.const(new src__ansi_code.AnsiCode.__("red", src__ansi_code.AnsiCodeType.background, 41, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundGreen*/get backgroundGreen() { + return dart.const(new src__ansi_code.AnsiCode.__("green", src__ansi_code.AnsiCodeType.background, 42, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundYellow*/get backgroundYellow() { + return dart.const(new src__ansi_code.AnsiCode.__("yellow", src__ansi_code.AnsiCodeType.background, 43, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundBlue*/get backgroundBlue() { + return dart.const(new src__ansi_code.AnsiCode.__("blue", src__ansi_code.AnsiCodeType.background, 44, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundMagenta*/get backgroundMagenta() { + return dart.const(new src__ansi_code.AnsiCode.__("magenta", src__ansi_code.AnsiCodeType.background, 45, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundCyan*/get backgroundCyan() { + return dart.const(new src__ansi_code.AnsiCode.__("cyan", src__ansi_code.AnsiCodeType.background, 46, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundLightGray*/get backgroundLightGray() { + return dart.const(new src__ansi_code.AnsiCode.__("light gray", src__ansi_code.AnsiCodeType.background, 47, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundDefault*/get backgroundDefault() { + return dart.const(new src__ansi_code.AnsiCode.__("default", src__ansi_code.AnsiCodeType.background, 49, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundDarkGray*/get backgroundDarkGray() { + return dart.const(new src__ansi_code.AnsiCode.__("dark gray", src__ansi_code.AnsiCodeType.background, 100, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundLightRed*/get backgroundLightRed() { + return dart.const(new src__ansi_code.AnsiCode.__("light red", src__ansi_code.AnsiCodeType.background, 101, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundLightGreen*/get backgroundLightGreen() { + return dart.const(new src__ansi_code.AnsiCode.__("light green", src__ansi_code.AnsiCodeType.background, 102, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundLightYellow*/get backgroundLightYellow() { + return dart.const(new src__ansi_code.AnsiCode.__("light yellow", src__ansi_code.AnsiCodeType.background, 103, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundLightBlue*/get backgroundLightBlue() { + return dart.const(new src__ansi_code.AnsiCode.__("light blue", src__ansi_code.AnsiCodeType.background, 104, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundLightMagenta*/get backgroundLightMagenta() { + return dart.const(new src__ansi_code.AnsiCode.__("light magenta", src__ansi_code.AnsiCodeType.background, 105, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundLightCyan*/get backgroundLightCyan() { + return dart.const(new src__ansi_code.AnsiCode.__("light cyan", src__ansi_code.AnsiCodeType.background, 106, src__ansi_code.resetAll)); + }, + /*src__ansi_code.backgroundWhite*/get backgroundWhite() { + return dart.const(new src__ansi_code.AnsiCode.__("white", src__ansi_code.AnsiCodeType.background, 107, src__ansi_code.resetAll)); + }, + /*src__ansi_code.styles*/get styles() { + return dart.constList([src__ansi_code.styleBold, src__ansi_code.styleDim, src__ansi_code.styleItalic, src__ansi_code.styleUnderlined, src__ansi_code.styleBlink, src__ansi_code.styleReverse, src__ansi_code.styleHidden, src__ansi_code.styleCrossedOut], src__ansi_code.AnsiCode); + }, + /*src__ansi_code.foregroundColors*/get foregroundColors() { + return dart.constList([src__ansi_code.black, src__ansi_code.red, src__ansi_code.green, src__ansi_code.yellow, src__ansi_code.blue, src__ansi_code.magenta, src__ansi_code.cyan, src__ansi_code.lightGray, src__ansi_code.defaultForeground, src__ansi_code.darkGray, src__ansi_code.lightRed, src__ansi_code.lightGreen, src__ansi_code.lightYellow, src__ansi_code.lightBlue, src__ansi_code.lightMagenta, src__ansi_code.lightCyan, src__ansi_code.white], src__ansi_code.AnsiCode); + }, + /*src__ansi_code.backgroundColors*/get backgroundColors() { + return dart.constList([src__ansi_code.backgroundBlack, src__ansi_code.backgroundRed, src__ansi_code.backgroundGreen, src__ansi_code.backgroundYellow, src__ansi_code.backgroundBlue, src__ansi_code.backgroundMagenta, src__ansi_code.backgroundCyan, src__ansi_code.backgroundLightGray, src__ansi_code.backgroundDefault, src__ansi_code.backgroundDarkGray, src__ansi_code.backgroundLightRed, src__ansi_code.backgroundLightGreen, src__ansi_code.backgroundLightYellow, src__ansi_code.backgroundLightBlue, src__ansi_code.backgroundLightMagenta, src__ansi_code.backgroundLightCyan, src__ansi_code.backgroundWhite], src__ansi_code.AnsiCode); + } + }); + src__copy_path._doNothing = function(from, to) { + if (path$.canonicalize(from) == path$.canonicalize(to)) { + return true; + } + if (dart.test(path$.isWithin(from, to))) { + dart.throw(new core.ArgumentError.new("Cannot copy from " + dart.str(from) + " to " + dart.str(to))); + } + return false; + }; + src__copy_path.copyPath = function(from, to) { + return async.async(core.Null, function* copyPath() { + if (dart.test(src__copy_path._doNothing(from, to))) { + return; + } + yield io.Directory.new(to).create({recursive: true}); + let iter = async.StreamIterator.new(io.Directory.new(from).list({recursive: true})); + try { + while (yield iter.moveNext()) { + let file = iter.current; + { + let copyTo = path$.join(to, path$.relative(file.path, {from: from})); + if (io.Directory.is(file)) { + yield io.Directory.new(copyTo).create({recursive: true}); + } else if (io.File.is(file)) { + yield io.File.new(file.path).copy(copyTo); + } else if (io.Link.is(file)) { + yield io.Link.new(copyTo).create(yield file.target(), {recursive: true}); + } + } + } + } finally { + yield iter.cancel(); + } + }); + }; + src__copy_path.copyPathSync = function(from, to) { + if (dart.test(src__copy_path._doNothing(from, to))) { + return; + } + io.Directory.new(to).createSync({recursive: true}); + for (let file of io.Directory.new(from).listSync({recursive: true})) { + let copyTo = path$.join(to, path$.relative(file.path, {from: from})); + if (io.Directory.is(file)) { + io.Directory.new(copyTo).createSync({recursive: true}); + } else if (io.File.is(file)) { + io.File.new(file.path).copySync(copyTo); + } else if (io.Link.is(file)) { + io.Link.new(copyTo).createSync(file.targetSync(), {recursive: true}); + } + } + }; + const _name$0 = Symbol('_name'); + src__exit_code.ExitCode = class ExitCode extends core.Object { + get code() { + return this[code$0]; + } + set code(value) { + super.code = value; + } + toString() { + return dart.str(this[_name$0]) + ": " + dart.str(this.code); + } + }; + (src__exit_code.ExitCode.__ = function(code, _name) { + this[code$0] = code; + this[_name$0] = _name; + ; + }).prototype = src__exit_code.ExitCode.prototype; + dart.addTypeTests(src__exit_code.ExitCode); + const code$0 = Symbol("ExitCode.code"); + dart.setFieldSignature(src__exit_code.ExitCode, () => ({ + __proto__: dart.getFields(src__exit_code.ExitCode.__proto__), + code: dart.finalFieldType(core.int), + [_name$0]: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__exit_code.ExitCode, ['toString']); + dart.defineLazy(src__exit_code.ExitCode, { + /*src__exit_code.ExitCode.success*/get success() { + return dart.const(new src__exit_code.ExitCode.__(0, "success")); + }, + /*src__exit_code.ExitCode.usage*/get usage() { + return dart.const(new src__exit_code.ExitCode.__(64, "usage")); + }, + /*src__exit_code.ExitCode.data*/get data() { + return dart.const(new src__exit_code.ExitCode.__(65, "data")); + }, + /*src__exit_code.ExitCode.noInput*/get noInput() { + return dart.const(new src__exit_code.ExitCode.__(66, "noInput")); + }, + /*src__exit_code.ExitCode.noUser*/get noUser() { + return dart.const(new src__exit_code.ExitCode.__(67, "noUser")); + }, + /*src__exit_code.ExitCode.noHost*/get noHost() { + return dart.const(new src__exit_code.ExitCode.__(68, "noHost")); + }, + /*src__exit_code.ExitCode.unavailable*/get unavailable() { + return dart.const(new src__exit_code.ExitCode.__(69, "unavailable")); + }, + /*src__exit_code.ExitCode.software*/get software() { + return dart.const(new src__exit_code.ExitCode.__(70, "software")); + }, + /*src__exit_code.ExitCode.osError*/get osError() { + return dart.const(new src__exit_code.ExitCode.__(71, "osError")); + }, + /*src__exit_code.ExitCode.osFile*/get osFile() { + return dart.const(new src__exit_code.ExitCode.__(72, "osFile")); + }, + /*src__exit_code.ExitCode.cantCreate*/get cantCreate() { + return dart.const(new src__exit_code.ExitCode.__(73, "cantCreate")); + }, + /*src__exit_code.ExitCode.ioError*/get ioError() { + return dart.const(new src__exit_code.ExitCode.__(74, "ioError")); + }, + /*src__exit_code.ExitCode.tempFail*/get tempFail() { + return dart.const(new src__exit_code.ExitCode.__(75, "tempFail")); + }, + /*src__exit_code.ExitCode.noPerm*/get noPerm() { + return dart.const(new src__exit_code.ExitCode.__(77, "noPerm")); + }, + /*src__exit_code.ExitCode.config*/get config() { + return dart.const(new src__exit_code.ExitCode.__(78, "config")); + } + }); + const _name$1 = Symbol('_name'); + src__permissions._FilePermission = class _FilePermission extends core.Object { + toString() { + return this[_name$1]; + } + }; + (src__permissions._FilePermission.new = function(index, _name) { + this.index = index; + this[_name$1] = _name; + ; + }).prototype = src__permissions._FilePermission.prototype; + dart.addTypeTests(src__permissions._FilePermission); + dart.setFieldSignature(src__permissions._FilePermission, () => ({ + __proto__: dart.getFields(src__permissions._FilePermission.__proto__), + index: dart.finalFieldType(core.int), + [_name$1]: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__permissions._FilePermission, ['toString']); + src__permissions._FilePermission.execute = dart.const(new src__permissions._FilePermission.new(0, "_FilePermission.execute")); + src__permissions._FilePermission.write = dart.const(new src__permissions._FilePermission.new(1, "_FilePermission.write")); + src__permissions._FilePermission.read = dart.const(new src__permissions._FilePermission.new(2, "_FilePermission.read")); + src__permissions._FilePermission.setGid = dart.const(new src__permissions._FilePermission.new(3, "_FilePermission.setGid")); + src__permissions._FilePermission.setUid = dart.const(new src__permissions._FilePermission.new(4, "_FilePermission.setUid")); + src__permissions._FilePermission.sticky = dart.const(new src__permissions._FilePermission.new(5, "_FilePermission.sticky")); + src__permissions._FilePermission.values = dart.constList([src__permissions._FilePermission.execute, src__permissions._FilePermission.write, src__permissions._FilePermission.read, src__permissions._FilePermission.setGid, src__permissions._FilePermission.setUid, src__permissions._FilePermission.sticky], src__permissions._FilePermission); + src__permissions._FilePermissionRole = class _FilePermissionRole extends core.Object { + toString() { + return this[_name$1]; + } + }; + (src__permissions._FilePermissionRole.new = function(index, _name) { + this.index = index; + this[_name$1] = _name; + ; + }).prototype = src__permissions._FilePermissionRole.prototype; + dart.addTypeTests(src__permissions._FilePermissionRole); + dart.setFieldSignature(src__permissions._FilePermissionRole, () => ({ + __proto__: dart.getFields(src__permissions._FilePermissionRole.__proto__), + index: dart.finalFieldType(core.int), + [_name$1]: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__permissions._FilePermissionRole, ['toString']); + src__permissions._FilePermissionRole.world = dart.const(new src__permissions._FilePermissionRole.new(0, "_FilePermissionRole.world")); + src__permissions._FilePermissionRole.group = dart.const(new src__permissions._FilePermissionRole.new(1, "_FilePermissionRole.group")); + src__permissions._FilePermissionRole.user = dart.const(new src__permissions._FilePermissionRole.new(2, "_FilePermissionRole.user")); + src__permissions._FilePermissionRole.values = dart.constList([src__permissions._FilePermissionRole.world, src__permissions._FilePermissionRole.group, src__permissions._FilePermissionRole.user], src__permissions._FilePermissionRole); + src__permissions._hasPermission = function(stat, permission, opts) { + let role = opts && 'role' in opts ? opts.role : src__permissions._FilePermissionRole.world; + let index = src__permissions._permissionBitIndex(permission, role); + return (dart.notNull(stat.mode) & (1)[$leftShift](index)) !== 0; + }; + src__permissions._permissionBitIndex = function(permission, role) { + switch (permission) { + case src__permissions._FilePermission.setUid: + { + return 11; + } + case src__permissions._FilePermission.setGid: + { + return 10; + } + case src__permissions._FilePermission.sticky: + { + return 9; + } + default: + { + return dart.notNull(role.index) * 3 + dart.notNull(permission.index); + } + } + }; + src__permissions.isExecutable = function(path, opts) { + let t1; + let isWindows = opts && 'isWindows' in opts ? opts.isWindows : null; + let getStat = opts && 'getStat' in opts ? opts.getStat : dart.fn(io.FileStat.stat, StringToFutureOfFileStat()); + if (dart.test((t1 = isWindows, t1 == null ? io.Platform.isWindows : t1))) return true; + let stat = getStat(path); + if (io.FileStat.is(stat)) { + return src__permissions._isExecutable(stat); + } + return FutureOfFileStat().as(stat).then(core.bool, dart.fn(src__permissions._isExecutable, FileStatTobool())); + }; + src__permissions._isExecutable = function(stat) { + return dart.equals(stat.type, io.FileSystemEntityType.file) && dart.test(src__permissions._FilePermissionRole.values[$any](dart.fn(role => src__permissions._hasPermission(stat, src__permissions._FilePermission.execute, {role: role}), _FilePermissionRoleTobool()))); + }; + const _stdin$ = Symbol('_stdin'); + const _stdout$ = Symbol('_stdout'); + const _stderr$ = Symbol('_stderr'); + let const$48; + src__process_manager.ProcessManager = class ProcessManager extends core.Object { + static terminateStdIn() { + return async.async(core.Null, function* terminateStdIn() { + yield src__shared_stdin.sharedStdIn.terminate(); + }); + } + static new(opts) { + let stdin = opts && 'stdin' in opts ? opts.stdin : null; + let stdout = opts && 'stdout' in opts ? opts.stdout : null; + let stderr = opts && 'stderr' in opts ? opts.stderr : null; + let isWindows = opts && 'isWindows' in opts ? opts.isWindows : null; + stdin == null ? stdin = src__shared_stdin.sharedStdIn : null; + stdout == null ? stdout = io.stdout : null; + stderr == null ? stderr = io.stderr : null; + isWindows == null ? isWindows = io.Platform.isWindows : null; + if (dart.test(isWindows)) { + return new src__process_manager._WindowsProcessManager.new(stdin, stdout, stderr); + } + return new src__process_manager._UnixProcessManager.new(stdin, stdout, stderr); + } + spawn(executable, arguments$0, opts) { + return async.async(io.Process, (function* spawn() { + let workingDirectory = opts && 'workingDirectory' in opts ? opts.workingDirectory : null; + let environment = opts && 'environment' in opts ? opts.environment : null; + let includeParentEnvironment = opts && 'includeParentEnvironment' in opts ? opts.includeParentEnvironment : true; + let runInShell = opts && 'runInShell' in opts ? opts.runInShell : false; + let mode = opts && 'mode' in opts ? opts.mode : io.ProcessStartMode.normal; + let process = io.Process.start(executable, arguments$0[$toList](), {workingDirectory: workingDirectory, environment: environment, includeParentEnvironment: includeParentEnvironment, runInShell: runInShell, mode: mode}); + return src__process_manager._ForwardingSpawn.new(yield process, this[_stdin$], this[_stdout$], this[_stderr$]); + }).bind(this)); + } + spawnBackground(executable, arguments$0, opts) { + return async.async(io.Process, (function* spawnBackground() { + let workingDirectory = opts && 'workingDirectory' in opts ? opts.workingDirectory : null; + let environment = opts && 'environment' in opts ? opts.environment : null; + let includeParentEnvironment = opts && 'includeParentEnvironment' in opts ? opts.includeParentEnvironment : true; + let runInShell = opts && 'runInShell' in opts ? opts.runInShell : false; + let mode = opts && 'mode' in opts ? opts.mode : io.ProcessStartMode.normal; + let process = io.Process.start(executable, arguments$0[$toList](), {workingDirectory: workingDirectory, environment: environment, includeParentEnvironment: includeParentEnvironment, runInShell: runInShell, mode: mode}); + return src__process_manager._ForwardingSpawn.new(yield process, const$48 || (const$48 = dart.const(new (_EmptyStreamOfListOfint()).new())), this[_stdout$], this[_stderr$]); + }).bind(this)); + } + spawnDetached(executable, arguments$0, opts) { + return async.async(io.Process, function* spawnDetached() { + let workingDirectory = opts && 'workingDirectory' in opts ? opts.workingDirectory : null; + let environment = opts && 'environment' in opts ? opts.environment : null; + let includeParentEnvironment = opts && 'includeParentEnvironment' in opts ? opts.includeParentEnvironment : true; + let runInShell = opts && 'runInShell' in opts ? opts.runInShell : false; + let mode = opts && 'mode' in opts ? opts.mode : io.ProcessStartMode.normal; + return io.Process.start(executable, arguments$0[$toList](), {workingDirectory: workingDirectory, environment: environment, includeParentEnvironment: includeParentEnvironment, runInShell: runInShell, mode: mode}); + }); + } + }; + (src__process_manager.ProcessManager.__ = function(_stdin, _stdout, _stderr) { + this[_stdin$] = _stdin; + this[_stdout$] = _stdout; + this[_stderr$] = _stderr; + ; + }).prototype = src__process_manager.ProcessManager.prototype; + dart.addTypeTests(src__process_manager.ProcessManager); + dart.setMethodSignature(src__process_manager.ProcessManager, () => ({ + __proto__: dart.getMethods(src__process_manager.ProcessManager.__proto__), + spawn: dart.fnType(async.Future$(io.Process), [core.String, core.Iterable$(core.String)], {environment: core.Map$(core.String, core.String), includeParentEnvironment: core.bool, mode: io.ProcessStartMode, runInShell: core.bool, workingDirectory: core.String}), + spawnBackground: dart.fnType(async.Future$(io.Process), [core.String, core.Iterable$(core.String)], {environment: core.Map$(core.String, core.String), includeParentEnvironment: core.bool, mode: io.ProcessStartMode, runInShell: core.bool, workingDirectory: core.String}), + spawnDetached: dart.fnType(async.Future$(io.Process), [core.String, core.Iterable$(core.String)], {environment: core.Map$(core.String, core.String), includeParentEnvironment: core.bool, mode: io.ProcessStartMode, runInShell: core.bool, workingDirectory: core.String}) + })); + dart.setFieldSignature(src__process_manager.ProcessManager, () => ({ + __proto__: dart.getFields(src__process_manager.ProcessManager.__proto__), + [_stdin$]: dart.finalFieldType(async.Stream$(core.List$(core.int))), + [_stdout$]: dart.finalFieldType(io.IOSink), + [_stderr$]: dart.finalFieldType(io.IOSink) + })); + const _delegate$ = Symbol('_delegate'); + const _onClosed = Symbol('_onClosed'); + src__process_manager.Spawn = class Spawn extends core.Object { + [_onClosed]() { + } + kill(signal) { + if (signal === void 0) signal = io.ProcessSignal.sigterm; + return this[_delegate$].kill(signal); + } + get exitCode() { + return this[_delegate$].exitCode; + } + get pid() { + return this[_delegate$].pid; + } + get stderr() { + return this[_delegate$].stderr; + } + get stdin() { + return this[_delegate$].stdin; + } + get stdout() { + return this[_delegate$].stdout; + } + }; + (src__process_manager.Spawn.__ = function(_delegate) { + this[_delegate$] = _delegate; + this[_delegate$].exitCode.then(dart.void, dart.fn(_ => this[_onClosed](), intTovoid())); + }).prototype = src__process_manager.Spawn.prototype; + dart.addTypeTests(src__process_manager.Spawn); + src__process_manager.Spawn[dart.implements] = () => [io.Process]; + dart.setMethodSignature(src__process_manager.Spawn, () => ({ + __proto__: dart.getMethods(src__process_manager.Spawn.__proto__), + [_onClosed]: dart.fnType(dart.void, []), + kill: dart.fnType(core.bool, [], [io.ProcessSignal]) + })); + dart.setGetterSignature(src__process_manager.Spawn, () => ({ + __proto__: dart.getGetters(src__process_manager.Spawn.__proto__), + exitCode: async.Future$(core.int), + pid: core.int, + stderr: async.Stream$(core.List$(core.int)), + stdin: io.IOSink, + stdout: async.Stream$(core.List$(core.int)) + })); + dart.setFieldSignature(src__process_manager.Spawn, () => ({ + __proto__: dart.getFields(src__process_manager.Spawn.__proto__), + [_delegate$]: dart.finalFieldType(io.Process) + })); + const _stdInSub$ = Symbol('_stdInSub'); + const _stdOutSub$ = Symbol('_stdOutSub'); + const _stdErrSub$ = Symbol('_stdErrSub'); + const _stdOut$ = Symbol('_stdOut'); + const _stdErr$ = Symbol('_stdErr'); + src__process_manager._ForwardingSpawn = class _ForwardingSpawn extends src__process_manager.Spawn { + static new(delegate, stdin, stdout, stderr) { + let stdoutSelf = StreamControllerOfListOfint().new(); + let stderrSelf = StreamControllerOfListOfint().new(); + let stdInSub = stdin.listen(dart.bind(delegate.stdin, 'add')); + let stdOutSub = delegate.stdout.listen(dart.fn(event => { + stdout.add(event); + stdoutSelf.add(event); + }, ListOfintToNull())); + let stdErrSub = delegate.stderr.listen(dart.fn(event => { + stderr.add(event); + stderrSelf.add(event); + }, ListOfintToNull())); + return new src__process_manager._ForwardingSpawn._delegate(delegate, stdInSub, stdOutSub, stdErrSub, stdoutSelf, stderrSelf); + } + [_onClosed]() { + this[_stdInSub$].cancel(); + this[_stdOutSub$].cancel(); + this[_stdErrSub$].cancel(); + super[_onClosed](); + } + get stdout() { + return this[_stdOut$].stream; + } + get stderr() { + return this[_stdErr$].stream; + } + }; + (src__process_manager._ForwardingSpawn._delegate = function(delegate, _stdInSub, _stdOutSub, _stdErrSub, _stdOut, _stdErr) { + this[_stdInSub$] = _stdInSub; + this[_stdOutSub$] = _stdOutSub; + this[_stdErrSub$] = _stdErrSub; + this[_stdOut$] = _stdOut; + this[_stdErr$] = _stdErr; + src__process_manager._ForwardingSpawn.__proto__.__.call(this, delegate); + ; + }).prototype = src__process_manager._ForwardingSpawn.prototype; + dart.addTypeTests(src__process_manager._ForwardingSpawn); + dart.setFieldSignature(src__process_manager._ForwardingSpawn, () => ({ + __proto__: dart.getFields(src__process_manager._ForwardingSpawn.__proto__), + [_stdInSub$]: dart.finalFieldType(async.StreamSubscription), + [_stdOutSub$]: dart.finalFieldType(async.StreamSubscription), + [_stdErrSub$]: dart.finalFieldType(async.StreamSubscription), + [_stdOut$]: dart.finalFieldType(async.StreamController$(core.List$(core.int))), + [_stdErr$]: dart.finalFieldType(async.StreamController$(core.List$(core.int))) + })); + src__process_manager._UnixProcessManager = class _UnixProcessManager extends src__process_manager.ProcessManager {}; + (src__process_manager._UnixProcessManager.new = function(stdin, stdout, stderr) { + src__process_manager._UnixProcessManager.__proto__.__.call(this, stdin, stdout, stderr); + ; + }).prototype = src__process_manager._UnixProcessManager.prototype; + dart.addTypeTests(src__process_manager._UnixProcessManager); + src__process_manager._WindowsProcessManager = class _WindowsProcessManager extends src__process_manager.ProcessManager {}; + (src__process_manager._WindowsProcessManager.new = function(stdin, stdout, stderr) { + src__process_manager._WindowsProcessManager.__proto__.__.call(this, stdin, stdout, stderr); + ; + }).prototype = src__process_manager._WindowsProcessManager.prototype; + dart.addTypeTests(src__process_manager._WindowsProcessManager); + src__process_manager.StartProcess = dart.typedef('StartProcess', () => StringAndListOfString__ToFutureOfProcess()); + const _current = Symbol('_current'); + const _sub$ = Symbol('_sub'); + const _onInput = Symbol('_onInput'); + let const$49; + const _getCurrent = Symbol('_getCurrent'); + src__shared_stdin.SharedStdIn = class SharedStdIn extends async.Stream$(core.List$(core.int)) { + nextLine(opts) { + let encoding = opts && 'encoding' in opts ? opts.encoding : io.systemEncoding; + return this.lines({encoding: encoding}).first; + } + lines(opts) { + let encoding = opts && 'encoding' in opts ? opts.encoding : io.systemEncoding; + return this.transform(core.String, convert.utf8.decoder).transform(core.String, const$49 || (const$49 = dart.const(new convert.LineSplitter.new()))); + } + [_onInput](event) { + return this[_getCurrent]().add(event); + } + [_getCurrent]() { + if (this[_current] == null) { + this[_current] = StreamControllerOfListOfint().new({onCancel: dart.fn(() => { + this[_current] = null; + }, VoidToNull()), sync: true}); + } + return this[_current]; + } + listen(onData, opts) { + let onError = opts && 'onError' in opts ? opts.onError : null; + let onDone = opts && 'onDone' in opts ? opts.onDone : null; + let cancelOnError = opts && 'cancelOnError' in opts ? opts.cancelOnError : null; + if (this[_sub$] == null) { + dart.throw(new core.StateError.new("Stdin has already been terminated.")); + } + let controller = this[_getCurrent](); + if (dart.test(controller.hasListener)) { + dart.throw(new core.StateError.new("Subscriber already listening. The existing subscriber must cancel " + "before another may be added.")); + } + return controller.stream.listen(onData, {onDone: onDone, onError: onError, cancelOnError: cancelOnError}); + } + terminate() { + return async.async(core.Null, (function* terminate() { + let t1; + if (this[_sub$] == null) { + dart.throw(new core.StateError.new("Stdin has already been terminated.")); + } + yield this[_sub$].cancel(); + yield (t1 = this[_current], t1 == null ? null : t1.close()); + this[_sub$] = null; + }).bind(this)); + } + }; + (src__shared_stdin.SharedStdIn.new = function(stream) { + let t1; + if (stream === void 0) stream = null; + this[_current] = null; + this[_sub$] = null; + src__shared_stdin.SharedStdIn.__proto__.new.call(this); + this[_sub$] = (t1 = stream, t1 == null ? stream = io.stdin : t1).listen(dart.bind(this, _onInput)); + }).prototype = src__shared_stdin.SharedStdIn.prototype; + dart.addTypeTests(src__shared_stdin.SharedStdIn); + dart.setMethodSignature(src__shared_stdin.SharedStdIn, () => ({ + __proto__: dart.getMethods(src__shared_stdin.SharedStdIn.__proto__), + nextLine: dart.fnType(async.Future$(core.String), [], {encoding: convert.Encoding}), + lines: dart.fnType(async.Stream$(core.String), [], {encoding: convert.Encoding}), + [_onInput]: dart.fnType(dart.void, [core.List$(core.int)]), + [_getCurrent]: dart.fnType(async.StreamController$(core.List$(core.int)), []), + listen: dart.fnType(async.StreamSubscription$(core.List$(core.int)), [dart.fnType(dart.void, [core.List$(core.int)])], {cancelOnError: core.bool, onDone: dart.fnType(dart.void, []), onError: core.Function}), + terminate: dart.fnType(async.Future$(core.Null), []) + })); + dart.setFieldSignature(src__shared_stdin.SharedStdIn, () => ({ + __proto__: dart.getFields(src__shared_stdin.SharedStdIn.__proto__), + [_current]: dart.fieldType(async.StreamController$(core.List$(core.int))), + [_sub$]: dart.fieldType(async.StreamSubscription$(core.List$(core.int))) + })); + dart.defineLazy(src__shared_stdin, { + /*src__shared_stdin.sharedStdIn*/get sharedStdIn() { + return new src__shared_stdin.SharedStdIn.new(io.stdin); + } + }); + src__shell_words.shellSplit = function(command) { + let t1; + let scanner = new src__string_scanner.StringScanner.new(command); + let results = JSArrayOfString().of([]); + let token = new core.StringBuffer.new(); + let hasToken = false; + while (!dart.test(scanner.isDone)) { + let next = scanner.readChar(); + switch (next) { + case 92: + { + if (dart.test(scanner.scanChar(10))) break; + hasToken = true; + token.writeCharCode(scanner.readChar()); + break; + } + case 39: + { + hasToken = true; + let firstQuote = dart.notNull(scanner.position) - 1; + while (!dart.test(scanner.scanChar(39))) { + src__shell_words._checkUnmatchedQuote(scanner, firstQuote); + token.writeCharCode(scanner.readChar()); + } + break; + } + case 34: + { + hasToken = true; + let firstQuote = dart.notNull(scanner.position) - 1; + while (!dart.test(scanner.scanChar(34))) { + src__shell_words._checkUnmatchedQuote(scanner, firstQuote); + if (dart.test(scanner.scanChar(92))) { + src__shell_words._checkUnmatchedQuote(scanner, firstQuote); + let next = scanner.readChar(); + if (next == 10) continue; + if (next == 36 || next == 96 || next == 34 || next == 92) { + token.writeCharCode(next); + } else { + t1 = token; + t1.writeCharCode(92); + t1.writeCharCode(next); + t1; + } + } else { + token.writeCharCode(scanner.readChar()); + } + } + break; + } + case 35: + { + if (hasToken) { + token.writeCharCode(35); + break; + } + while (!dart.test(scanner.isDone) && scanner.peekChar() != 10) { + scanner.readChar(); + } + break; + } + case 32: + case 9: + case 10: + { + if (hasToken) results[$add](token.toString()); + hasToken = false; + token.clear(); + break; + } + default: + { + hasToken = true; + token.writeCharCode(next); + break; + } + } + } + if (hasToken) results[$add](token.toString()); + return results; + }; + src__shell_words._checkUnmatchedQuote = function(scanner, openingQuote) { + if (!dart.test(scanner.isDone)) return; + let type = scanner.substring(openingQuote, dart.notNull(openingQuote) + 1) === "\"" ? "double" : "single"; + scanner.error("Unmatched " + type + " quote.", {position: openingQuote, length: 1}); + }; + const _onConnect = Symbol('_onConnect'); + const _requests = Symbol('_requests'); + const _subscriptions = Symbol('_subscriptions'); + const _uuid = Symbol('_uuid'); + const _id$ = Symbol('_id'); + const _stream = Symbol('_stream'); + const _whenConnected = Symbol('_whenConnected'); + const _close$ = Symbol('_close'); + src__protocol__client__client.Client = class Client extends core.Object {}; + (src__protocol__client__client.Client.new = function() { + ; + }).prototype = src__protocol__client__client.Client.prototype; + dart.addTypeTests(src__protocol__client__client.Client); + src__isolate__client.IsolateClient = class IsolateClient extends src__protocol__client__client.Client { + get clientId() { + return this[clientId$]; + } + set clientId(value) { + super.clientId = value; + } + get serverSendPort() { + return this[serverSendPort$]; + } + set serverSendPort(value) { + super.serverSendPort = value; + } + get receivePort() { + return this[receivePort]; + } + set receivePort(value) { + super.receivePort = value; + } + [_whenConnected](T, callback) { + if (this[_id$] != null) + return async.Future$(T).sync(callback); + else { + let c = CompleterOfString().new(); + this[_onConnect].add(c); + return c.future.then(T, dart.fn(_ => callback(), dart.fnType(async.FutureOr$(T), [core.String]))); + } + } + publish(eventName, value) { + return this[_whenConnected](dart.dynamic, dart.fn(() => { + let c = CompleterOfMap().new(); + let requestId = core.String.as(this[_uuid].v4()); + this[_requests][$_set](requestId, c); + this.serverSendPort.send(new (IdentityMapOfString$Object()).from(["id", this[_id$], "request_id", requestId, "method", "publish", "params", new (IdentityMapOfString$dynamic()).from(["client_id", this.clientId, "event_name", eventName, "value", value])])); + return c.future; + }, VoidToFutureOfMap())); + } + subscribe(eventName) { + return this[_whenConnected](src__protocol__client__client.ClientSubscription, dart.fn(() => { + let c = CompleterOfMap().new(); + let requestId = core.String.as(this[_uuid].v4()); + this[_requests][$_set](requestId, c); + this.serverSendPort.send(new (IdentityMapOfString$Object()).from(["id", this[_id$], "request_id", requestId, "method", "subscribe", "params", new (IdentityMapOfString$String()).from(["client_id", this.clientId, "event_name", eventName])])); + return c.future.then(src__protocol__client__client.ClientSubscription, dart.fn(result => { + let s = new src__isolate__client._IsolateClientSubscription.new(eventName, core.String.as(result[$_get]("subscription_id")), this); + this[_subscriptions][$add](s); + return s; + }, MapTo_IsolateClientSubscription())); + }, VoidToFutureOfClientSubscription())); + } + close() { + this.receivePort.close(); + for (let c of this[_onConnect]) { + if (!dart.test(c.isCompleted)) { + c.completeError(new core.StateError.new("The client was closed before the server ever accepted the connection.")); + } + } + for (let c of this[_requests][$values]) { + if (!dart.test(c.isCompleted)) { + c.completeError(new core.StateError.new("The client was closed before the server responded to this request.")); + } + } + for (let s of this[_subscriptions]) + s[_close$](); + this[_requests][$clear](); + return async.Future.value(); + } + }; + (src__isolate__client.IsolateClient.new = function(clientId, serverSendPort) { + this[_onConnect] = new (ListQueueOfCompleterOfString()).new(); + this[_requests] = new (IdentityMapOfString$CompleterOfMap()).new(); + this[_subscriptions] = JSArrayOf_IsolateClientSubscription().of([]); + this[_uuid] = new uuid.Uuid.new(); + this[_id$] = null; + this[receivePort] = new isolate._ReceivePort.new(); + this[clientId$] = clientId; + this[serverSendPort$] = serverSendPort; + this.receivePort.listen(dart.fn(data => { + let t1, t1$; + if (core.Map.is(data) && typeof data[$_get]("request_id") == 'string') { + let requestId = core.String.as(data[$_get]("request_id")); + let c = this[_requests][$remove](requestId); + if (c != null && !dart.test(c.isCompleted)) { + if (!(typeof data[$_get]("status") == 'boolean')) { + c.completeError(new core.FormatException.new("The server sent an invalid response.")); + } else if (!dart.test(core.bool.as(data[$_get]("status")))) { + c.completeError(new src__protocol__client__client.PubSubException.new((t1$ = (t1 = data[$_get]("error_message"), t1 == null ? null : dart.toString(t1)), t1$ == null ? "The server sent a failure response, but did not provide an error message." : t1$))); + } else if (!core.Map.is(data[$_get]("result"))) { + c.completeError(new core.FormatException.new("The server sent a success response, but did not include a result.")); + } else { + c.complete(core.Map.as(data[$_get]("result"))); + } + } + } else if (core.Map.is(data) && typeof data[$_get]("id") == 'string' && this[_id$] == null) { + this[_id$] = core.String.as(data[$_get]("id")); + for (let c of this[_onConnect]) { + if (!dart.test(c.isCompleted)) c.complete(this[_id$]); + } + this[_onConnect].clear(); + } else if (core.List.is(data) && data[$length] === 2 && typeof data[$_get](0) == 'string') { + let eventName = core.String.as(data[$_get](0)); + let event = data[$_get](1); + for (let s of this[_subscriptions][$where](dart.fn(s => s.eventName == eventName, _IsolateClientSubscriptionTobool()))) { + if (!dart.test(s[_stream].isClosed)) s[_stream].add(event); + } + } + }, dynamicToNull())); + this.serverSendPort.send(this.receivePort.sendPort); + }).prototype = src__isolate__client.IsolateClient.prototype; + dart.addTypeTests(src__isolate__client.IsolateClient); + const clientId$ = Symbol("IsolateClient.clientId"); + const serverSendPort$ = Symbol("IsolateClient.serverSendPort"); + const receivePort = Symbol("IsolateClient.receivePort"); + dart.setMethodSignature(src__isolate__client.IsolateClient, () => ({ + __proto__: dart.getMethods(src__isolate__client.IsolateClient.__proto__), + [_whenConnected]: dart.gFnType(T => [async.Future$(T), [dart.fnType(async.FutureOr$(T), [])]], T => [core.Object]), + publish: dart.fnType(async.Future, [core.String, dart.dynamic]), + subscribe: dart.fnType(async.Future$(src__protocol__client__client.ClientSubscription), [core.String]), + close: dart.fnType(async.Future, []) + })); + dart.setFieldSignature(src__isolate__client.IsolateClient, () => ({ + __proto__: dart.getFields(src__isolate__client.IsolateClient.__proto__), + [_onConnect]: dart.finalFieldType(collection.Queue$(async.Completer$(core.String))), + [_requests]: dart.finalFieldType(core.Map$(core.String, async.Completer$(core.Map))), + [_subscriptions]: dart.finalFieldType(core.List$(src__isolate__client._IsolateClientSubscription)), + [_uuid]: dart.finalFieldType(uuid.Uuid), + [_id$]: dart.fieldType(core.String), + clientId: dart.finalFieldType(core.String), + serverSendPort: dart.finalFieldType(isolate.SendPort), + receivePort: dart.finalFieldType(isolate.ReceivePort) + })); + src__protocol__client__client.ClientSubscription = class ClientSubscription extends async.Stream {}; + (src__protocol__client__client.ClientSubscription.new = function() { + src__protocol__client__client.ClientSubscription.__proto__.new.call(this); + ; + }).prototype = src__protocol__client__client.ClientSubscription.prototype; + dart.addTypeTests(src__protocol__client__client.ClientSubscription); + src__isolate__client._IsolateClientSubscription = class _IsolateClientSubscription extends src__protocol__client__client.ClientSubscription { + [_close$]() { + if (!dart.test(this[_stream].isClosed)) this[_stream].close(); + } + listen(onData, opts) { + let onError = opts && 'onError' in opts ? opts.onError : null; + let onDone = opts && 'onDone' in opts ? opts.onDone : null; + let cancelOnError = opts && 'cancelOnError' in opts ? opts.cancelOnError : null; + return this[_stream].stream.listen(onData, {onError: onError, onDone: onDone, cancelOnError: cancelOnError}); + } + unsubscribe() { + return this.client[_whenConnected](dart.dynamic, dart.fn(() => { + let c = CompleterOfMap().new(); + let requestId = core.String.as(this.client[_uuid].v4()); + this.client[_requests][$_set](requestId, c); + this.client.serverSendPort.send(new (IdentityMapOfString$Object()).from(["id", this.client[_id$], "request_id", requestId, "method", "unsubscribe", "params", new (IdentityMapOfString$String()).from(["client_id", this.client.clientId, "subscription_id", this.id])])); + return c.future.then(dart.dynamic, dart.fn(_ => { + this[_close$](); + }, MapToNull())); + }, VoidToFuture())); + } + }; + (src__isolate__client._IsolateClientSubscription.new = function(eventName, id, client) { + this[_stream] = async.StreamController.new(); + this.eventName = eventName; + this.id = id; + this.client = client; + src__isolate__client._IsolateClientSubscription.__proto__.new.call(this); + ; + }).prototype = src__isolate__client._IsolateClientSubscription.prototype; + dart.addTypeTests(src__isolate__client._IsolateClientSubscription); + dart.setMethodSignature(src__isolate__client._IsolateClientSubscription, () => ({ + __proto__: dart.getMethods(src__isolate__client._IsolateClientSubscription.__proto__), + [_close$]: dart.fnType(dart.void, []), + listen: dart.fnType(async.StreamSubscription, [dart.fnType(dart.void, [dart.dynamic])], {cancelOnError: core.bool, onDone: dart.fnType(dart.void, []), onError: core.Function}), + unsubscribe: dart.fnType(async.Future, []) + })); + dart.setFieldSignature(src__isolate__client._IsolateClientSubscription, () => ({ + __proto__: dart.getFields(src__isolate__client._IsolateClientSubscription.__proto__), + [_stream]: dart.finalFieldType(async.StreamController), + eventName: dart.finalFieldType(core.String), + id: dart.finalFieldType(core.String), + client: dart.finalFieldType(src__isolate__client.IsolateClient) + })); + const _clients = Symbol('_clients'); + const _onPublish = Symbol('_onPublish'); + const _onSubscribe = Symbol('_onSubscribe'); + const _onUnsubscribe = Symbol('_onUnsubscribe'); + const _uuid$ = Symbol('_uuid'); + src__protocol__server__adapter.Adapter = class Adapter extends core.Object {}; + (src__protocol__server__adapter.Adapter.new = function() { + ; + }).prototype = src__protocol__server__adapter.Adapter.prototype; + dart.addTypeTests(src__protocol__server__adapter.Adapter); + src__isolate__server.IsolateAdapter = class IsolateAdapter extends src__protocol__server__adapter.Adapter { + get receivePort() { + return this[receivePort$]; + } + set receivePort(value) { + super.receivePort = value; + } + get onPublish() { + return this[_onPublish].stream; + } + get onSubscribe() { + return this[_onSubscribe].stream; + } + get onUnsubscribe() { + return this[_onUnsubscribe].stream; + } + close() { + this.receivePort.close(); + this[_clients][$clear](); + this[_onPublish].close(); + this[_onSubscribe].close(); + this[_onUnsubscribe].close(); + return async.Future.value(); + } + start() { + this.receivePort.listen(dart.fn(data => { + if (isolate.SendPort.is(data)) { + let id = core.String.as(this[_uuid$].v4()); + this[_clients][$_set](id, data); + data.send(new (IdentityMapOfString$Object()).from(["status", true, "id", id])); + } else if (core.Map.is(data) && typeof data[$_get]("id") == 'string' && typeof data[$_get]("request_id") == 'string' && typeof data[$_get]("method") == 'string' && core.Map.is(data[$_get]("params"))) { + let id = core.String._check(data[$_get]("id")); + let requestId = core.String._check(data[$_get]("request_id")); + let method = core.String._check(data[$_get]("method")); + let params = core.Map._check(data[$_get]("params")); + let sp = this[_clients][$_get](id); + if (sp == null) { + } else if (method === "publish") { + if (typeof params[$_get]("client_id") == 'string' && typeof params[$_get]("event_name") == 'string' && dart.test(params[$containsKey]("value"))) { + let clientId = core.String._check(params[$_get]("client_id")); + let eventName = core.String._check(params[$_get]("event_name")); + let value = params[$_get]("value"); + let rq = new src__isolate__server._IsolatePublishRequestImpl.new(requestId, clientId, eventName, value, sp); + this[_onPublish].add(rq); + } else { + sp.send(new (IdentityMapOfString$Object()).from(["status", false, "request_id", requestId, "error_message", "Expected client_id, event_name, and value."])); + } + } else if (method === "subscribe") { + if (typeof params[$_get]("client_id") == 'string' && typeof params[$_get]("event_name") == 'string') { + let clientId = core.String._check(params[$_get]("client_id")); + let eventName = core.String._check(params[$_get]("event_name")); + let rq = new src__isolate__server._IsolateSubscriptionRequestImpl.new(clientId, eventName, sp, requestId, this[_uuid$]); + this[_onSubscribe].add(rq); + } else { + sp.send(new (IdentityMapOfString$Object()).from(["status", false, "request_id", requestId, "error_message", "Expected client_id, and event_name."])); + } + } else if (method === "unsubscribe") { + if (typeof params[$_get]("client_id") == 'string' && typeof params[$_get]("subscription_id") == 'string') { + let clientId = core.String._check(params[$_get]("client_id")); + let subscriptionId = core.String._check(params[$_get]("subscription_id")); + let rq = new src__isolate__server._IsolateUnsubscriptionRequestImpl.new(clientId, subscriptionId, sp, requestId); + this[_onUnsubscribe].add(rq); + } else { + sp.send(new (IdentityMapOfString$Object()).from(["status", false, "request_id", requestId, "error_message", "Expected client_id, and subscription_id."])); + } + } else { + sp.send(new (IdentityMapOfString$Object()).from(["status", false, "request_id", requestId, "error_message", "Unrecognized method \"" + dart.str(method) + "\". Or, you omitted id, request_id, method, or params."])); + } + } + }, dynamicToNull())); + } + }; + (src__isolate__server.IsolateAdapter.new = function() { + this[_clients] = new (IdentityMapOfString$SendPort()).new(); + this[_onPublish] = StreamControllerOfPublishRequest().new(); + this[_onSubscribe] = StreamControllerOfSubscriptionRequest().new(); + this[_onUnsubscribe] = StreamControllerOfUnsubscriptionRequest().new(); + this[_uuid$] = new uuid.Uuid.new(); + this[receivePort$] = new isolate._ReceivePort.new(); + ; + }).prototype = src__isolate__server.IsolateAdapter.prototype; + dart.addTypeTests(src__isolate__server.IsolateAdapter); + const receivePort$ = Symbol("IsolateAdapter.receivePort"); + dart.setMethodSignature(src__isolate__server.IsolateAdapter, () => ({ + __proto__: dart.getMethods(src__isolate__server.IsolateAdapter.__proto__), + close: dart.fnType(async.Future, []), + start: dart.fnType(dart.void, []) + })); + dart.setGetterSignature(src__isolate__server.IsolateAdapter, () => ({ + __proto__: dart.getGetters(src__isolate__server.IsolateAdapter.__proto__), + onPublish: async.Stream$(src__protocol__server__publish.PublishRequest), + onSubscribe: async.Stream$(src__protocol__server__subscription.SubscriptionRequest), + onUnsubscribe: async.Stream$(src__protocol__server__subscription.UnsubscriptionRequest) + })); + dart.setFieldSignature(src__isolate__server.IsolateAdapter, () => ({ + __proto__: dart.getFields(src__isolate__server.IsolateAdapter.__proto__), + [_clients]: dart.finalFieldType(core.Map$(core.String, isolate.SendPort)), + [_onPublish]: dart.finalFieldType(async.StreamController$(src__protocol__server__publish.PublishRequest)), + [_onSubscribe]: dart.finalFieldType(async.StreamController$(src__protocol__server__subscription.SubscriptionRequest)), + [_onUnsubscribe]: dart.finalFieldType(async.StreamController$(src__protocol__server__subscription.UnsubscriptionRequest)), + [_uuid$]: dart.finalFieldType(uuid.Uuid), + receivePort: dart.finalFieldType(isolate.ReceivePort) + })); + src__protocol__server__publish.PublishRequest = class PublishRequest extends core.Object {}; + (src__protocol__server__publish.PublishRequest.new = function() { + ; + }).prototype = src__protocol__server__publish.PublishRequest.prototype; + dart.addTypeTests(src__protocol__server__publish.PublishRequest); + src__isolate__server._IsolatePublishRequestImpl = class _IsolatePublishRequestImpl extends src__protocol__server__publish.PublishRequest { + get clientId() { + return this[clientId$0]; + } + set clientId(value) { + super.clientId = value; + } + get eventName() { + return this[eventName$]; + } + set eventName(value) { + super.eventName = value; + } + get value() { + return this[value$0]; + } + set value(value) { + super.value = value; + } + accept(response) { + this.sendPort.send(new (IdentityMapOfString$Object()).from(["status", true, "request_id", this.requestId, "result", new (IdentityMapOfString$int()).from(["listeners", response.listeners])])); + } + reject(errorMessage) { + this.sendPort.send(new (IdentityMapOfString$Object()).from(["status", false, "request_id", this.requestId, "error_message", errorMessage])); + } + }; + (src__isolate__server._IsolatePublishRequestImpl.new = function(requestId, clientId, eventName, value, sendPort) { + this.requestId = requestId; + this[clientId$0] = clientId; + this[eventName$] = eventName; + this[value$0] = value; + this.sendPort = sendPort; + ; + }).prototype = src__isolate__server._IsolatePublishRequestImpl.prototype; + dart.addTypeTests(src__isolate__server._IsolatePublishRequestImpl); + const clientId$0 = Symbol("_IsolatePublishRequestImpl.clientId"); + const eventName$ = Symbol("_IsolatePublishRequestImpl.eventName"); + const value$0 = Symbol("_IsolatePublishRequestImpl.value"); + dart.setMethodSignature(src__isolate__server._IsolatePublishRequestImpl, () => ({ + __proto__: dart.getMethods(src__isolate__server._IsolatePublishRequestImpl.__proto__), + accept: dart.fnType(dart.void, [src__protocol__server__publish.PublishResponse]), + reject: dart.fnType(dart.void, [core.String]) + })); + dart.setFieldSignature(src__isolate__server._IsolatePublishRequestImpl, () => ({ + __proto__: dart.getFields(src__isolate__server._IsolatePublishRequestImpl.__proto__), + clientId: dart.finalFieldType(core.String), + eventName: dart.finalFieldType(core.String), + value: dart.finalFieldType(dart.dynamic), + sendPort: dart.finalFieldType(isolate.SendPort), + requestId: dart.finalFieldType(core.String) + })); + src__protocol__server__subscription.SubscriptionRequest = class SubscriptionRequest extends core.Object {}; + (src__protocol__server__subscription.SubscriptionRequest.new = function() { + ; + }).prototype = src__protocol__server__subscription.SubscriptionRequest.prototype; + dart.addTypeTests(src__protocol__server__subscription.SubscriptionRequest); + src__isolate__server._IsolateSubscriptionRequestImpl = class _IsolateSubscriptionRequestImpl extends src__protocol__server__subscription.SubscriptionRequest { + get clientId() { + return this[clientId$1]; + } + set clientId(value) { + super.clientId = value; + } + get eventName() { + return this[eventName$0]; + } + set eventName(value) { + super.eventName = value; + } + reject(errorMessage) { + this.sendPort.send(new (IdentityMapOfString$Object()).from(["status", false, "request_id", this.requestId, "error_message", errorMessage])); + } + accept() { + let id = core.String.as(this[_uuid$].v4()); + this.sendPort.send(new (IdentityMapOfString$Object()).from(["status", true, "request_id", this.requestId, "result", new (IdentityMapOfString$String()).from(["subscription_id", id])])); + return new src__isolate__server._IsolateSubscriptionImpl.new(this.clientId, id, this.eventName, this.sendPort); + } + }; + (src__isolate__server._IsolateSubscriptionRequestImpl.new = function(clientId, eventName, sendPort, requestId, _uuid) { + this[clientId$1] = clientId; + this[eventName$0] = eventName; + this.sendPort = sendPort; + this.requestId = requestId; + this[_uuid$] = _uuid; + ; + }).prototype = src__isolate__server._IsolateSubscriptionRequestImpl.prototype; + dart.addTypeTests(src__isolate__server._IsolateSubscriptionRequestImpl); + const clientId$1 = Symbol("_IsolateSubscriptionRequestImpl.clientId"); + const eventName$0 = Symbol("_IsolateSubscriptionRequestImpl.eventName"); + dart.setMethodSignature(src__isolate__server._IsolateSubscriptionRequestImpl, () => ({ + __proto__: dart.getMethods(src__isolate__server._IsolateSubscriptionRequestImpl.__proto__), + reject: dart.fnType(dart.void, [core.String]), + accept: dart.fnType(async.FutureOr$(src__protocol__server__subscription.Subscription), []) + })); + dart.setFieldSignature(src__isolate__server._IsolateSubscriptionRequestImpl, () => ({ + __proto__: dart.getFields(src__isolate__server._IsolateSubscriptionRequestImpl.__proto__), + clientId: dart.finalFieldType(core.String), + eventName: dart.finalFieldType(core.String), + sendPort: dart.finalFieldType(isolate.SendPort), + requestId: dart.finalFieldType(core.String), + [_uuid$]: dart.finalFieldType(uuid.Uuid) + })); + src__protocol__server__subscription.Subscription = class Subscription extends core.Object {}; + (src__protocol__server__subscription.Subscription.new = function() { + ; + }).prototype = src__protocol__server__subscription.Subscription.prototype; + dart.addTypeTests(src__protocol__server__subscription.Subscription); + src__isolate__server._IsolateSubscriptionImpl = class _IsolateSubscriptionImpl extends src__protocol__server__subscription.Subscription { + get clientId() { + return this[clientId$2]; + } + set clientId(value) { + super.clientId = value; + } + get id() { + return this[id$1]; + } + set id(value) { + super.id = value; + } + dispatch(event) { + this.sendPort.send([this.eventName, event]); + } + }; + (src__isolate__server._IsolateSubscriptionImpl.new = function(clientId, id, eventName, sendPort) { + this[clientId$2] = clientId; + this[id$1] = id; + this.eventName = eventName; + this.sendPort = sendPort; + ; + }).prototype = src__isolate__server._IsolateSubscriptionImpl.prototype; + dart.addTypeTests(src__isolate__server._IsolateSubscriptionImpl); + const clientId$2 = Symbol("_IsolateSubscriptionImpl.clientId"); + const id$1 = Symbol("_IsolateSubscriptionImpl.id"); + dart.setMethodSignature(src__isolate__server._IsolateSubscriptionImpl, () => ({ + __proto__: dart.getMethods(src__isolate__server._IsolateSubscriptionImpl.__proto__), + dispatch: dart.fnType(dart.void, [dart.dynamic]) + })); + dart.setFieldSignature(src__isolate__server._IsolateSubscriptionImpl, () => ({ + __proto__: dart.getFields(src__isolate__server._IsolateSubscriptionImpl.__proto__), + clientId: dart.finalFieldType(core.String), + id: dart.finalFieldType(core.String), + eventName: dart.finalFieldType(core.String), + sendPort: dart.finalFieldType(isolate.SendPort) + })); + src__protocol__server__subscription.UnsubscriptionRequest = class UnsubscriptionRequest extends core.Object {}; + (src__protocol__server__subscription.UnsubscriptionRequest.new = function() { + ; + }).prototype = src__protocol__server__subscription.UnsubscriptionRequest.prototype; + dart.addTypeTests(src__protocol__server__subscription.UnsubscriptionRequest); + src__isolate__server._IsolateUnsubscriptionRequestImpl = class _IsolateUnsubscriptionRequestImpl extends src__protocol__server__subscription.UnsubscriptionRequest { + get clientId() { + return this[clientId$3]; + } + set clientId(value) { + super.clientId = value; + } + get subscriptionId() { + return this[subscriptionId$]; + } + set subscriptionId(value) { + super.subscriptionId = value; + } + reject(errorMessage) { + this.sendPort.send(new (IdentityMapOfString$Object()).from(["status", false, "request_id", this.requestId, "error_message", errorMessage])); + } + accept() { + this.sendPort.send(new (IdentityMapOfString$Object()).from(["status", true, "request_id", this.requestId, "result", new _js_helper.LinkedMap.new()])); + } + }; + (src__isolate__server._IsolateUnsubscriptionRequestImpl.new = function(clientId, subscriptionId, sendPort, requestId) { + this[clientId$3] = clientId; + this[subscriptionId$] = subscriptionId; + this.sendPort = sendPort; + this.requestId = requestId; + ; + }).prototype = src__isolate__server._IsolateUnsubscriptionRequestImpl.prototype; + dart.addTypeTests(src__isolate__server._IsolateUnsubscriptionRequestImpl); + const clientId$3 = Symbol("_IsolateUnsubscriptionRequestImpl.clientId"); + const subscriptionId$ = Symbol("_IsolateUnsubscriptionRequestImpl.subscriptionId"); + dart.setMethodSignature(src__isolate__server._IsolateUnsubscriptionRequestImpl, () => ({ + __proto__: dart.getMethods(src__isolate__server._IsolateUnsubscriptionRequestImpl.__proto__), + reject: dart.fnType(dart.void, [core.String]), + accept: dart.fnType(async.FutureOr, []) + })); + dart.setFieldSignature(src__isolate__server._IsolateUnsubscriptionRequestImpl, () => ({ + __proto__: dart.getFields(src__isolate__server._IsolateUnsubscriptionRequestImpl.__proto__), + clientId: dart.finalFieldType(core.String), + subscriptionId: dart.finalFieldType(core.String), + sendPort: dart.finalFieldType(isolate.SendPort), + requestId: dart.finalFieldType(core.String) + })); + src__protocol__client__client.PubSubException = class PubSubException extends core.Object { + get message() { + return this[message$2]; + } + set message(value) { + super.message = value; + } + toString() { + return "`pub_sub` exception: " + dart.str(this.message); + } + }; + (src__protocol__client__client.PubSubException.new = function(message) { + this[message$2] = message; + ; + }).prototype = src__protocol__client__client.PubSubException.prototype; + dart.addTypeTests(src__protocol__client__client.PubSubException); + const message$2 = Symbol("PubSubException.message"); + src__protocol__client__client.PubSubException[dart.implements] = () => [core.Exception]; + dart.setFieldSignature(src__protocol__client__client.PubSubException, () => ({ + __proto__: dart.getFields(src__protocol__client__client.PubSubException.__proto__), + message: dart.finalFieldType(core.String) + })); + dart.defineExtensionMethods(src__protocol__client__client.PubSubException, ['toString']); + src__protocol__server__client.ClientInfo = class ClientInfo extends core.Object { + get id() { + return this[id$2]; + } + set id(value) { + super.id = value; + } + get canPublish() { + return this[canPublish$]; + } + set canPublish(value) { + super.canPublish = value; + } + get canSubscribe() { + return this[canSubscribe$]; + } + set canSubscribe(value) { + super.canSubscribe = value; + } + :J.J.HK.AKcܦ,,`:J.J.F.nb#.yn(.Yy+.F'".ynWb`cܨߨx s``>I!% ;`~J+x5;?NLVQ`~&LX;`~Ngn`wp.HKxxHKJ#(.AKxƁxAK`ܩݩs``>I!% +3`uJ+13?NHMP`~&HO.&VV3`u`~Ic%mg3`~>I".HKw3`~AK3`~HKw.AK>=0$'R.'3`~'S?>I#"3,.HKw?;53ye\UOI3ewc.AK>=0s}$'R.'Ā3'S?Jnܫ۫(s[`>I!%`uJ(!?I,!%60`~>JM"Z(]pf.7(ys7?J"".HK(HK.AK(ƀAK.7(逬7ܭEMgzVg`JY_zܮ:CkIkSs`u`u>I`!nd.7(wq*7>=0$'T.7'U'7܀*7'V?I%*`~>N(.`0h`>.HKLF*`~HKN_cy`ei`s.AKy*`~AKJ.>N˯`Ӽh`.HK*xekN y`i`.AK,("*yyekJ;FP.VI]2|P  N܁WK`7 +O܁XK`7 PAF݂#)Y`] +`݂ 7`݃M e`݃ `݃ :`݆MM[`e`i7[+x`+:`+\>IP[T>=0hr$'7'%I"!(+΂>=0$'@'%I$"!/($(+A:$>=0NX$'G$'%?&#% `: `: [`#(+`#0)$(+:C$` M݄`:>N6`#.7(+'Z.7`J$'.閘W'.:W݉ [$ 4s``>IA!OE.7(XRy7>=0ku$'T.7'U'y7'V?J.eyye\݊U`_i`Jos..'݊x + s``>I!%.7(.(p7>=0AK$'Tj.7'U'p7'V?J.eyπpe݋ދ\(\s[`J""%%`* .7(3-%`7MF.e(VP%`e݌aizr`Juu.7zW.e݌A`:J$'.$'.e'R.㖛'w[R8ݍ>D]`ݍrre`7[+`+:`+\? 7邍:z]ރ^``\? ރDOZ`:>Ndk6`#wm.7(+'Z.7`J$'.閘W'.:Wރփڄ[s``>I! .7(-7>=0)3$'TR.7'U'zt-7'V?J.ey-e\ބ΄م_`J얾..'ޅ x( s``>I5!C9.7(LF$7>=0_i$'T.7'U'$7'V?J.ey퀅$eޅ +z( z s[`J""%#`H>.7(QK`7kd.e(tn`eކz`J.7zW.eކA†`:J$'.$'.e'R.㖫'wsL2߁BQ_`] +` +߁`߁ y `߂6AEEE`:߂7`߃)17(77`߄OWaq`y``:`J9DO߅s``߆QUpx^pj s``€߈5<\C\K`:U`[+`:Àߊa`[+`:gL +Āߋ~b`ƀߋ `ǀߋ y`Ȁߋ `:ʀߋ `y`)`:\>I5!G=9.yǑ7(PJ.Ƒ7>=0cm$'T.Ƒ7'U'7.yǑ7'VI.yLJe.Ƈe>=0$H'N&.y'OA.'%IV!f_Z.ȁ(^(oi.Ɩ[x.y>=0$'c.'d.Ɩ[.y'R'e?ƀǁȂ zC}̀6I.P(+J .?J)'iW0+.PӀ8.`HϖGM=؀j``wۀT [`:P`[+\?ۂ ݀-9J6@J[JCC.˖ހ`heo`Jr#wr.P(++.PӀe`mR~[3 ?CG%kg{*l``\?  =Ea7Oa`JRXR.7em(t`Jw{w.yey.eვ$x$ s``>N`.xހɀJ#(.yx Ʉy`)49Es``>IR!`V.7(icr7>=0|$'T.7'U'7΀r7'V?N] +[, .rN(,y] +[.-7.yB<ryNPZm`#b\(j..yr`Nn`#(.y.r`IŃByxۄw>=0$-'R.'Ār'S?N?D`:UPFBWlg_wXvBy[wHGJ&`&` ҆و`:`[+`:>N `=,%$f'oE@:.閘W'paZT.:WIm!{q.7(+=$'c.7?=$'N܇a`:.a`іI +! `>=1*~=IBO?JftmAሇa`[+`:>I_()=_ə'?I܀_(*=_+?N:` .:N#`)NDq`:IR%[.`>N`:&.`ĖND`ʙ. +.I"!((+(w>=/(ց=5 +XJ(H=_ +qi +X{(H?Nr` +'XE=#Ն(ؔW + +XWH`:=h`#4+(^IHSL.((>Ja'>=.'XU=NËs`ּh`恋W.yey.e (^I!#_(+>=;4ցJAXWH=ngցt_=ցXH=ÂցЙ)=䂌ցXH>=#ց)I>!LC'XC=c\ց'X?Eu~`ćććW>IćA(>=ӂւᒈ>=ւI0!:4_(+=JCցP_?=c\ցm'ڂhoi`xyLI!_(+=ց)?JԂAG(Gs[`J""%"`%.(.("`;7.y(D>"`yLTz]`J`of`.zWu7h{w.yzᏉA`:J$ '.$'t.'.y'7.'WT@ƑP }*iou`S v`:&=`Sy`_`:jv`:\>I!.ĖnO>=0$'w.Ė'x'E?I#R'.5.Ė>JD:(+>=0cm$'y'z'{:W'|.Ė'E? |$/B7B`:J::.v.aǷnp|^ゑ)}`K` L`::JR3`:[7[+j1`+\? }71 Ȃ͂`J.K:`J.L1xM7x`yJ@D.a.1k.q.:}N`J".W(.( ÃDž-M̅-M`y\>I"!%˓`!H&-'˓`O.>=0ak$'P'Q?=܄1퀄˓1}=.K ˓~=.L#˓: +2651>5CR`\>NZfS`h.1=|1[I[wn>NąT],`.U.3Xn[H=.K.KW ̴(YI.;2̴ >=N.LVN.LWeY[ygn>=.L[y̴y>NՆT],`.U.3X[ +nHI#.N=:1͸7I?=O.KUO.KyaX͸(YIo|s͸ >=.L.Lyny[>=.L [y.3U[Fy ㈹BƉBV``>I!J*?=.W#J3) GKS`>N`jV`r=.WχJχ W %V`\>I6"D:(G"YO(\!nc.(q>=.K.KW=.L>=.L.LW̊ьGՌr``>I!GкJ*?N'T],`).U>5.R=H.KNH.KWZQ(YIfsj >=.L.LW.R܁(^>=.L.R܁(^y큏yJ)'U'`:],`>NT],`XI.N=<7I?J<Qʄʷu=_МҤ ioT~``y㍽ O` 1` ` :`RR"O`11`@`K:`\?Wbo| Y`*'ZɨV +W#^?[y=̂ҍ)``!䃙 \`P"\ `h#䇠D`u+2??R\P`u\?!}xԯw"ԯx ԯ7рԯ7 +%ow|`J.\!]."ekW.1]y."n&ۄ:`>N`.\!]%."ekW'.1]N:A:`WK.\!^wpa."ekWy.1逅յaJ#յ(."nȁy.":o`'<M<`yJ<.3.1,AElMJl\M`y\>Ii"!%sm`3!&`3O6.>=0$'P'Q?=O.1`Z1}(q~`uJ.D#)䇮Ȉ`hJ.\!."ekW.1\* :#:`uJ&/&.ݗ)_q.ab`y!c`y+`u>N6Bd`#MDo(+W.1kbo1}`Jy.\!P."ekWd1}."ekW؃[/Lr``>I!"L*H>=<.D+#JT*?=m.Dy.\!P."ekW.1."ekW.Ry[#J)0'S'`:@`+!1`+/(`+\>=>?P.3X+_9iGIw""{+(+9(+G(+=+.R?IԂ9(+>=9#+(+.1+`?I'2+G(+=;G#JD+(+Ŕb^X+yփyjd+`?NzP`u.\!P."ekW9."ekW9WG[=0] ۓ.3 Ս֪z׫ F*2 +3cie``y6 O`7 1`<||O`1`\?6ܽ7 |9 99`J(.O6\!]0.17]:=Ew:Lw`JOdXO.O6\!^n.17aJݙDcݪݬ=?>->53`:C@`N1`\(`\>Ih"!rl(+"!~ +(+!(+>=0'?I! +(+>I  +>=0-7'I~ +w(^>=0$''??I"!(+.'>=09C'?I""! +(+!(+ +Wwɀ(^>=0$''?@ +>e`yA恢f]``D @`H+1bKbQ`\?Dq 1Fgd5d ]y`]y`>J`4_;]``IJ$(UH.@DZ'IioP`]`L @`M @]`N @`O @`*U22wQwW`n]`\?LM 2Q| `\>=.@.@NWN=/ėX .@Lg\.@Mb.@Mv4<<`>=G.@OG.@NyNIY"]. @Oqh.@N(=w.@Mw?R慘S`Y`+\>=.@M;GSNw +N\>=. @)OI'4+.@N(=C:.@Mw?}VSY`\\? Xqy ``]`>JZLLL Yg`4##P$s``jJ-1nBLKb4[[\S[`>=L +V=ـL +wA=0Y 3 zB ] +`^p`]`>JZddLfqg`4щs``oJߗsdZ(/I]y],`]L`Po`]`>Ne`-eOa]`ˊ]`>J:[4- [],`[J5[5[$"쀘(g`4??x@[`dJLPi'ld8Oa`]`4`]`>N`N݊?`:Q?I!(+B=+5?=#NE(+ŏE礆R+`Jip`:礄[4‹[`:[J5[z 5[  + g`4-[`dJ i'" AO;La]`V]`>JaLzh`Q~'m`4?``J +/:]],[4PPzQ`]],[>Nqu][I>=ч[4r[[[J5[p 5[ y + g[4,r[`:J "  A>=Rx[[4r[[[J5[= 5[W F +W g[4r[[J Jg],[4l[],[>N&`:aWD:~'mI}! +(+B>= c㇏e + ?J1&[ND1'~'KmX [1[4[]],[[J5[5[ +  + g],[4[]],[JȦ[&`],][g`4],[`d>N][`:[2'`:[F7O@[H>=b_&kgc `:|x nJėi'IQ(+>J%r?AG4H<Qb'>Jrym:'>AGɃQ'>Jm(g`4!!W"s``dJ+/i'A6&QQL#s`:j'>Jmg`4s``d>Nē][`:`:&s`::N*1][[[23[[FE_N`:YU{>=wq x + +mnJi' >BB)'>AG>RFQl'>J%>BB>BJ r.F]$``_l e``斈 `:a斢 [c断e``:[\?_~`a di``f) `:g? s[iHHgQgW`:bs[\?f0g= Hljlr`d`l `nҗҘ `s`\?l i ȁȁs o"(`d`q昕 +`^s昢 +`^s`\?qX i끘ees%4ut# :Meou灘l]y[`w e`x# `yK `{{ t`|炓t`*}炮t]y[+為Ӆe```;`Z`\>=q.t{.t{}I!.y(+>=0$'O7.yK?Id""th.ew(+.ew('B.ewk('<B>=.t)|N`I"!'.ew(+!F>2.ew?(+B>=Ymw.ew??=#(+ō+`=.t.t}[䅅}?wxy{  `J.t|"6+6`J.!/.t|;X@y]@s```>N`N`N`N][`:`:2 `:`:F;`:5-#9L{>AGCK_'>=yW9LmB'>=e9L mB1F'>=gs9Lm)B>=9LmnB'I@PDs(+>=0a m'?JᗆW +se!9,DEX^da[\~a\+b`+`+][>J.t}c灊sb胋 #*jK/j7K`:`:>JC`YJ.t{LamF7TV8f`[g`[`X_X_66%_1_\? 聊`[^__~`J4__`J&y] +[x v$&`Ƈ,f`[]A_]z_ۂ\? F )~B2~`[_>=0;E'邃 +]%_J_ + Â˂(҂`J>>`[]_J!%_BGhnOhW``Jc*lq |s]``J 郩  s]_]_Jڬi_  `_J +7c6~@c`[]_JFJ_gitza_` !a_+_J鄷Äτ`[]_Jٗ_]_J g_F!F) s]_]_J37i_@JQ}]}js]`]_Jtxg_酁 s]`]_Jg_酷 K_`J̗`؅݆ ]_\J\ ! !\J\%*L0L8``JDD`PU^p ]`\J}}\醉a_`\J\醿Ćφa_`\J闔\** ]`\J""\K<sE1jSHTꀷ`],`:`7c7|7w7{77k7o7707g7+7777v7777}77Y7G77777777r77777&767?77747777q771777#77777777777'77u7 77,777n7Z77R7;777)77/77S7ѓ77 777[7j77797J7L7X777777C7M7377E777P7<777Q77@7777877777!777777 777_77D7777~7=7d7]77s7`77O77"7*777F77777^7 77727:7 +7I77$7\7777b7777y77777m777N77l7V777e7z7777x7%7.7777777t77K7777p7>77f7H777a757W7777777777i777777777U7(77777 777B7h7A77-777T77],],`:],` :+`:O`:s`:`:`7:`7:`7 :'`7@:K`7:o`7:`76\? ŀх<ׅ<],[],[],[> N +`N9C`eXQE(Y[yNM],],`1],`.`.`!.`..`E<EG`NLRhT_`_W>Npr`vtN_`=9&9`:=̗E `','W>=8@JQ=ckv}==ė= =,4?F=V^krׂN4],[.[hE΄`׆ +%ۗh +%醄 +%W>=  +%   +%9 +%9:J+2 AMY_],[],[>Nnx`N` (YN` BW7N΅],[.[ 2h oWN],[ .[E.79`@> B BM NM W>N^b],[1d[he khm 9tq {why W9 h W9 h W9=   P:E҆` Bㆆ S 2h oW S SW>=  S&.[:E5>@`GE L ML W>=_[ ` wpe sq Sy9x :I S B(>= && ],[],[Eއ`燇퇇W>=5],[ 5`4I 4I 9  S B99:I9"G= Bw7\PN SR B(>=l &ls| ],[?E`NNNW>=„  S9Nք ن Sy B9N N9J "9(B(SM],],`^`],],`>Eox|`W>E:`ЀcȃW>=ۀJ9뗲J999:JJ-DN_M],],`j`],],`>N],[.[E`W>Eʊ:`݄UU脊UW>=U + 9UW!9:E;DK:`WP \ b\ W>=zupv9{ &z 9`:Jꋺю@܎@M],],``],],`>E :`% * 0* W>N@B=],[H.[N[]r],[c.[Er{}`W>=O9 9:=l#!ƀ9 97(9 97+" 9# 9`:=HE@9I &Hmf_XTSl9[ZO9bal9ihO9poO9`:={9 &O9l9O9l9O9`:=9 &ʃO9уO9؄l9߃O9愍l9`:=9 & O9 l9O9O9! l9`:J07E\~h~M],],`],[``],],`>EŽ`τׄW>E:`Ҁe  W>=5],`% 0&95`+***I3***I9&3UA6ILHBXhWN9V`:Jnu0ꏃ],[[>E`44Á4W>=ϗ&49`9J  ],[[>N7<[I>9ER[]`dbijiW>=v׀W9:=׀:J +*2!pv`À ],`ʀʁʁЁ],`\?Àb ŀ낅(~s``J"%` Ґf[.`bȀ@z~@`J 5 &f[:.cƀ냁A~`:JU. Y /̀ B]],``Ӏ +\? ΀`Ѐ.~5@ ],``>NPZ`0`:Nv`<.: =  l=̂ wmJꁃ K5р@0:~-@; ;] +``<J:!> ? d!!g!|!~ "/=ՀDJ]],``؀ ×`ـ `ހǃDž;˅;`],`\>Is{w"5(Yw.×ԗؖ="5.×ԗ؃"5Ђ?=.ԗه +'"5(Y3"5O؀"*:"* ǰۀ@SA~Ze ],``>Nu`0:N`<.:#L=؂#b#1l=#bwmJ#LK5܀<:~R` ;] +``<Jos}#.×ԗ.ԗ# #$"߀ˆьd`<B ŗ`<퇧 Ɨ`0:Ǘ`<+L.`*bbgkgy;] +``],`\>=.Ǘ聈$ʉ:.ƗԗїN9A`G:UQ$Ձ(YEbkm`tr%>~v%(Y%>%>W>=%%>7\$%>9:=.ŗԗ‘%lE`% %(Y%%W>=-&%.%876=:$>%9:=WL.Ǘԗ䀘[%l$ʉ:$ bFl}m~ ],`\>I..ԗ=0('?=.Ǘԗ䀘&l?~],``(y`2d`\>I@D..ԗ=0OY('?={.Ǘԗ?'r'''D틱Œbw~njb\>I..ԗJ?=..)= .Ǘԗwm=%.ŗԗ‘@:).ƗԗK5l=WL.ŗԗwm&'M((!$3(( "6;OSԃڄ` ~`7hW''.p,.\? '3R:4~hv ;] +``<JV))})#)`<Y H~`Ifxx11;] +`\>=.̗9:=.̗9:=.̗9:=.̗72Tv: R*476G7~Q]>`I\> @~wq*(Y(7qN=`.̗9Nr`.̗9N_`.̗9Nԋ`.̗9Nl`N`E +`+ր7@++W>I$*(+ր7>=:+FA?+MC+qkWMJK+MgOUY+=e+Ňi+Iy}+ր7 >=+++Mk+gU+q=+7h+W7I凌+ր70>=++M+q+= +h+W77>=;+A?+qFD+MkLIJ+gNU=`+lg7hi+7N`+=++q=+q+M=+MY+MљZؙYޙY+*+Y+9*+9#$+9=0+*4.=KE.̗QYW+*`Z.̗9:=pj.̗vY|+M.̗9:=.̗Y+q.̗9:=.̗Y+.̗9:*0G`ӗ],`:#`@997 p9999999999999997^ZQ997DS9979999999999999997~997Ĉ997ߢ|99999999999999 9 +7һ9 j ],`:z`@77 7777 7777 7777 7777 7777 7777 7777 777 777 777 777 7777 +7777 +7777 +7777 +77) )0T2 "6;OSr ` ~`7hЙW p\?  p:~#p1 ;] +``<J@DV`j223 +`<A 0~`IN7; `III6R6`;] +`\>=.̘9:=.̘9:=.̘9:=.̘72Tv:=".̘9:~7P R37;L<~Vb>`I\> @|v4r(Y(7vN=`.̘9Nr`.̘9N†_`.̘9Nن`.̘9Nl`.̘9E `5[7P5[5[W>I)/-5[7>=H?.I5[SN4rT5[9:>=xo.y5[~Z.5[y9.5[y79.䆇5[y79.5[y79:N27`9Y?YEZL47S55`W.a5[9Ilrp5[7>=6YY64ʅ4k4ʇg59IІ5[7(>=6YY64ʆ459I!'%5[7<>=76>YDYJ6bXSQ4ʅU4k][4ʅ_5kge4i59>=6YY64ʆ459=555=54=4Z47=4ʁ +4=46U=71.̘=YC4LF.̘9:=\V.̘bYh4qk.̘9:={.̘Y4.̘9:=.̘Y5.̘9:=.̘љY55.̘9:4M: ` 2U3*:; "6;OS`/ ~`>7h@W"QQ[pY[\? Q`gr`Jx|":~ ;] +``<JV3 <;;=d^.̘%9:=z.̘%9:=.̘%7nr:=.̘%9:=.̘%9:=.̘%79:= .̘%77߃٫:=(".̘%79:'7@ R<7*```Jǁ>=kӁ>7 y=U+* *`!`"``J >>&>gU(>,.2j#6j;`B!`I"``JOaWRP?ST?`\Z?S^?mfd?`h?m-nr$x}``J.@*.7 @*.7@*.%``J.7@*.7 @*.7@*/<&< ``J2!.7A=*#.7/A=*75A=0@D'JO``JUudU.7aA*f.7rA*zxA҈7 +1x~x>`I\>@ƀBm(Y(7E` B7BBW>=) .'*B4/Bm5B9:ECLN`7VTC&7@\C&]\C&W>=ri.'sC&xY~Y.'.'C&y90.'C&y79Y.&.'ԁC&y79/.'聎C&y79:N "=`*$.̘%9N79r`A;.̘%9NNP_`XR.̘%9Neg`oi.̘%9N|~l`.̘%9N`.̘%79N(`.̘%79N4`.̘%79Eޏ`E 7@E E W> +N)`Y YEl.%D.+Y1. 5D8E";EG+?YKELE 9YP.'ZE 9Nkq*`sYy.$Dq-.#DqDD,=ElEG=EGE"=E"D=DřYDE +=DۃD=DD=DDq=DqY E +F =XR.̘%^YdDqmg.̘%9:=}w.̘%YD.̘%9:=.̘%YD.̘%9:=.̘%͙YD.̘%9:=.̘%YD.̘%9:= .̘%7YE"& .̘%79:=60.̘%7?3?@AABHI`+`"nӘ],`:w`@9,9-9.9/7V[909192937҃[719495969798999:77 7,o9;9<9=9>9?9@9A9B9C7cQ7))g7 +7!89D9E9F9G9H9I9J9K9L9M9N9O9P7jp7٤77l7HwL77 9Q9R9S9T9U9V9W9X9Y9Z9[;W<`IJ45}\`[`] +_8/ ]4],_1<_9.4`*B\? ;%%],_J_.]484 4\>=)!.]48 C?9>AD _\>IQU..49>=0hr('^?=.]48L(;@Ãȃw̓\>=..4)9KYKKL +LyLJLLC "D򁶁_`GG +C`Hu.C`*R\? MJ򂱂ł`J̾".+CG.+CG(KOXmam`Jdd..CHM \>= +.+CG N"- ],`\>I:>..CH>=0Q[('^?=.+CGNEO򄯄?>],``y`d`\>I..CH>=0 ('^?=TL.+CG[NbN͂iNIswN=..C)H?P򅘅w\>=..C)HMhMMN'NO]OLOOS` [#s?[ajsbbyV󂼂ƒUc]],``:\AGSpSQS\? GX`bJ + +]Y'</<`yJ22uPWPPU`V Ҙ\PPP]d +Ke~f`JPg]],``:fp]\? 鰏b􅂅`Jc􅲅Ņͅ`JЙQQQ_h`` fQ0QRg hrxi`(k +g`lw.g`*v\? *n؁3`:J.+gkAoQZoco`Jff..glq  \>=.+gk r >`:\>I+/..gl>=0BL('^?=.+gkSis?>`:`y`d`\>I..gl>=0('^?=A9.+gkMGSڃXWS炄^SHIimT=u..g)l?tw\>=..g)lRRSSKSTTR0TTwjkxSlf`[]_z7m`7|X+w],_}=w`Ȅȅ,؅,],_\?|U}&U(Y ȬWenwr`Ju&}u.+w|`19J(@J`JCC.=w}NY[``_>ImwqVV^z.(=0VV.?J.+w|VV9ͅۆUކU` K_\>IV^.(=0)V.?=B;.+w|CVLV:Zch(ihn`\>IWx.=w}>NA_.owEφ`WxWȀ.=w}W삆WW>=.+w|WȁW:I(6,Wxw@8.+w|(Y>NXp],_Ii|um.+w|(Y(>=Xm.qwWx>=Xm.rwWx= Xm .=w}".+w|O=2.+w<Xm|?=Q.=w[Wx}mrwvy K_\>I.=w}(.+w|(Y=.Řw.=w}?=.+w|5`.=w}5`.=wȁYW}YYN: K_\>=.wZ& ]_`y`+\>=Z{'I"!$ Z(+5/Z{w7Z>=0DN_ZdZ{+'y?=.swZjZ{Z~~` ]_`y`+\>=[M.' .=w}W=5F[k'I[!c_[y(+>It~x[kw[y>=0[y[k+'y?I܂[k([yJ??I4>8[M(A.=w}>=R.swZ[Zb[ki[yJu?I"[y(+%[Z],[>=[y[Z( ?I!ڃ[y(+>=.tw[M[Z [k[yJ ?Nu`.=w}NՒ`[kFK_[ZA>I]Cw>=+]C4+]CyB@?IXg\]*(rj.+w|(Y>=.Řw]*?=.+w|5`]*5`]*^W^]\:I݅]Cw>=0('v?I"!&"[y(+<1]*>[y>=0KUf[yk[kr]*'y?=ݘ.+w|[M.=w}= .+w|.=w}]*=09.+w|B[MI]*=Z.=wd]*}Jtwǖ],[`y`\>=__yC,93_;_>NLR[ZT_{[_9Nmr[zt_{{_9=_{__:=_{_` :=_Á_W=_Ђ_y%swŚ% ]_`y`+\>I%`],[=#`(+``ρ( +`?I!`(+>= .tw .=w})`ρ1`8`JD?N`FK_`>Ia^`=.a?=a܃aWIa`=0('v?v{tw` ]_`y`\>I%ҁbm],[>=#烚b(+bbm( +`I" +b~w bm( !bw*#bm( >=0<F('v?>@!b(+Nw`byb~Nɛ`.=w}Wcg=.xwc=.+w| 2,b`W4cgJB.=w}WLcgZ.+w|cb`O=wo.+w| b`b`Wcgbmb~O=.=wc}͜Ҟ؞` _\>I"d dw.=w}>=0):dD.=w}?IXd\.=w}nf.+w|(Y>=~.+w| dW.=w}W.+w|dO=.+w|dd:=.=w.=w}W}J?N p],_.rw+=>4e JdQ.+w|O=i_e xrdW}.=w}W.+w|dO=edd:=.=w.=w}W}=.+we|qvUxwUy`\>Igv.+w|(YJ?Nڟp],_.rwg=gE '.=w}0.+w|O=>.+wHgE|gorwy`],_>N`.+w|(YhI"!܀g(+g〇g>= g〢gI6D:g〇Fz>=^gjz?J.qwg oŘwo(`\>=*.+w5],_4.rw+5[OMhه [hc.+w|Oh٘|ty5 5`y` 6]_`\>ÍiXw.=w}=0iX.=w}?= .zwiKiXie'ivnsjzw|j`y` 6]_`\>I%łj1]x_>=.+w| jj$ j1]x_+w|jBO>=91.+w| BjIj$Nj1VjBO{`J.nw{¥ʦ|ئ`J.=w}h.nw{ <}<`J"/".nw}+:WAW`JDQD.nwow_2:QqwGQLB`],_UVV9VWZY.ZZL[/_[`b@dfghi-ijk kqkkll@Ve~]x`],`\? lè˨ow٨`Jm +m6z]x`[##T/T=],`[\? GMmzYdxowrx`[Ju(mm}.``\? ͘ץ:n,qw ,B``J:'ndnDn17`YYci`\? nqwB``Jͥono<櫺`n"n(`\? DN+_ozrqwB``%J+oooìs`33`\? $p,7BqqwOqTB``7J]alpzpZpv|'`ƀ`\? ƘФpĀ%qw% B``.J q,q qRǀ*0`̀TT`f`\? |qʀqwB``IJΥqqr̀鮔`Ҁ VV`\? 3=GrBЀZdqwqvB``@JrrprӀM`؀ ͯ `\? 阢]rրKqw)K.B``YJ7;]FsBs"shـPV`ހyy`\? Vs܀ǯѯqwޯB``RJVsst߀ +`11>D`\? `jvtXqwB```Jtttʰб`KK +`\? &0<u +O[qwhmB``iJvzuXu8u~]x`Gw`奟P P`\? +5VAuT`vownv`JqqzqwB``}JVv[v v;v]x`QQ`\? *4>BvUcowq`JtxtqwB``rJ>wGvw'wmU lmCmnoIopq_rrsut'tuvw~w-̈́r`[]4_\? =L!"`,][[[`JA"GLOxZUxg;d.&qqxZ_wxg _][[[`у[`][[[``>I$%-(y_>J;B.cy_iy%~y0y@?JɁy%':pp _`:][[[K``J]]yx<xxyzwz6z8 > 7&7'a[4!`+G"`+`:>OV]a[`][``:ija[v%`][``:>I%ۄz` +>N`=' z` +0{< JD$['N{<'w?I{nzJ'?={{i[1[zOa[`:S[`:J'3'z4| B;zWG{*IZ%e^z][>N`:#%z][],['Йz][W'G`:N:B],`:SKDz][`:O{Ic"!pgz(+{| +(Ywz>=| +zy| +(Y1`:'HR?N[f`:$j|b 'yq| +''I""z(+} (^Wzvz!} n'XO>J!} ?Js$||b 'W| +`:43`:`:>J ʅzWW~ G'GW'XGW zGW'GI;%F?z][[[>N],`:z][[[{`:4[`:>J${ '{z][[[ mIQ"!^Uz(+xqiC (Ywzz>=C zyC (Y1`:'HR?NIT`:$o'wbZC ''xIw""|z(+ +(^Wzvz! +n'XO>J + +?Jd q'W}C `:43`:`:>J zWW G'GW'XGW zGW'xGI'%2+z`:>N],`:z`:'XUJ'W2 `:ə$' zW'GW'G>N&,K`:@5.zAƁ'XaQ YzW'XGRNt` R'DI,0{=5 $G'@ 'w?I""""%z`%:3z`%VOz`voz(++ +>J >J$ՙz' J zz)g[) :A} H}M(``:JXu\/`:hK'R'瓟 [`:>K>I\b`(+Jk'0?I~%`J'?N`:$AJQ#]XR'pD'Vu`:[l[>J'V 6`:`:JH''Rzpzr+h-.>R`[`]4_ 3]4_' ],][==JZ]4_i`:a_6`b`]][+\?5],][1%][5[425]][;#D(+1G][]][<5[WU뀘_$_s; =VVa_6``:b`]4_J_.3%逄2Ԃ;D.[`kLgkh`r][[[`>Fʄb` +1` +.3 .>I!߂Lcp >=Fp2[['b)J<*?J\)p|[`][[[``>Nb` +&G'bm` +=l53;<&dZPG'Mm][[[lWJz<PP``J&ဆ'.3''''>.EoU[i`[` a_K[$ƈK`:a_K[b[\?  $''$' '"1g~?gL(_`JWW.`j E%'`:'(:`:')_`:' *,0;>J] +[[] +[] +[Jh#}mhExwT wTE] +[-E E] +[] +[] +[J#4$΃x. w:΁A] +[.`:`:!:``>N19 `@;d('BNMS`]UWedECn!{u(~W>ND`WU'XFWNƃ`لyI"q(6"q('6W>J5<?=QaYWiduoWEJ+%'9/0=C] +`3/`+:\? 5K`>@!./3(+ŁJ./37J[K~^f K`\>@z./3(+łz=./38w~\>@!./3(+ł̂}.s(;"#9S<΁ݕ`] +],`?J =;] +`@ ;`Ac ;`IBG;`9C;`D ;` E^.;`*R11=] +```ٽ\??@A  G`II:(:4>`I\J?P@~S^ ],`\>Ijn..;E=0y('?=.;.;CW΀(YC=.;D=.;NK w ~"\>I+/..;EJ:?=F..;)E=].;O=r.;N@.;D =.=;?.;M =.=;?w M4;4`>I.;@(J3,%.̙GމS?NKV`\:mf.̙G|N`?ޗE`Ƃ.̙G(Y؂W>=큊dhW .̙G9J&?Nq;q\>N`.;DN` .;D($.;A|E7@B`IG€K^_^W>EČ@`̓.;A(Y惌W>=.;AXO1/‚hA3.;A|WSQhUWc.;@:=..;AI=%.;DO=h_Q.;A|O{;{\> =.;D7N`.;CW7 Nߏ`.ə;z +.;A|PE,57`><ـP@yRzbcbW>=|o.;DI.;CwB>=0'?N=J`[L.;Ch]VNёe`.;D(=.;D :7N"+`A:-.;DN `%7 N4<`K>MUIYe].;@(o>=|.;@=˃W͙W<.;@>= +<%.;@=>5OHWQW_i.;@P۔ߕ ə; ```J sWy W2^2;S + SU`9VO`7W`Yف݂`!``JWUZ`djo`x``>N`7JUk̀ΙU7 y,j[׀ *|b]cY]],``:hp[\? d ],``:Jә`h쀂h(Ye W:!W/ ;] +`:`<J>BrRJi`Gl' =[] +`:r11L@LF=] +`:\?lM 1MnQVYd >],`\>=wq.=[l{`(Y on?n>],``y`d`\>= '(Y=+%.=[l/`8?F' IQU4=c].=[lw ?psxw}\>=.=[lw z]a`b h`A[],``y``:>N`:qydhN`Ny`E`dꀇqW>N`Q9=υׇk:=5`5`WЙa臈:7:=5`5` Wa*%:7:I:"E>׃^TM׃v7J\gZ|?Eԉ`dᆉ΀q醉WA>N`Q9I "^"v7B+?=09C$'#ql'y'`:'\D7'%Q=0'a;?ߙ[PUT``J_#e_7 +rlWtyWy7 +`1s *y˂ф]`:],` ps\?  {(U/U7 3`:],`>IE!XQJ=(^>=0hr'〃=À=(^?Nۃ`:=(^= +x=b.'=(^6JEL|Zo: ;] +],``J2dJ`( =s] +],`s`+=] +],`\? *?ȉ3`:`y`d`\> = +9!F-&,(^I;E?9(HF>IUYS=a.Йsh,pF?J|?N],`,bN`N`I.s(+>= +:"Fy9=/ >NV_`snfbFyh9y=:W|=.sW™܁9:=99W= =.s#x+܁69=FBI =a[.=se IquS=}.Йs,F?``<Jٙ.=sw\J.Йs|HЙsH3`:+`+\>I!.s(+>=0'ꀋe$s?==7.=sw E`G0 =s] +],`)s`+88WKWQ=] +],`\?Z 8M\ado >],`\Jyy.?(Y*O?O>],``y`d`\>= ((YI&0*(3(>I@D5=L.ЙsSZ(?Jf?N`N`I.s(+>=Υ:݂(y=ʓ>N#`72*&(y,y=CO:[W]9=sny.sW:=W=ʔ=.sx(=.=s! I-15=9.Йs@G(?TYlw^l\Jdd.ЙsאܑЙs⑤>],`+`+\>I! .s(+>=0'1'ꀑyہ?=.=sw Wuub`y xHs],`!`2`K],`\``>Nv`E`ł˃y̆W>Nܓ`N`0=;W=RG؀5`S5`Sc W yl7hnyW{:I˃yJ+?J7hЙ˃yup |8>@]],``:v|p\? | ],``:Jhπh(Yۃ>:> ;] +`:`<J!%9J`G =] +`: ?3?9=] +`:\?M  MDILW >],`\>=jd.=nw(Y a?a>],``y`d`\>=' (Y=.="+29' IDH4=VP.=w ?fkwp\>=y.=w zqe` yAy],``y``:>N̆`N`E`dqWA>Ṅ`؀Q9=脇kN#*U`17 k3I=""""""IBR^LYRRv\"ql^tzv((dž(ʒ憉(>=81FBS?=oh}=oh}7=Ն7I"^v7JA?Ehqs`ud~|LqLLWA>N`QL9I"^v7B?=0$@'# 'y'`:',&!\D7'%JQYL=0d'؍܎%ߙ%T``J#7 + W!Wy7 +`1p |:"h̓Ӆ]`:],` #p!#\? (29A 3`:],`>NSZ``Nw`ÄbÁ(^I!˂(+>=0'ꀅ.=6Á(^?JQf_XS|u(: ;] +],``Jۙ5;}`(Ł =] +],`Ɓ噲`+΁=] +],`\?ŀl *ȁƋ?΋3`:`y`d`\> = ʂ'3,(^IAKE(N>I[_=g.Йnv?J?N`N],`ЀbI.噲(>=.噲7h*5=CHCWIS]W(`>Ios={.Й?J??I!.噲(+>=ڄm.噲W=W?=*.噲7?JʂQׄVm=jd.=ŀ|unmSm( I=.Й?Ɂȋی&&``<J .=ʁ+0Cw5C\J;;.Й́{Й{3`:+`+\>I!.噲(+>=0'ꀍO W?=pj.=w sρ͍Ӕ`Gҁk =] +],`Ӂ(噲`+ہ77ZNZT=] +],`\?Ҁ 7MՁ_dgr >],`\J||.?RR(Y*ցv?v>],``y`d`\>= ‚(YI)3-(6>ICG=O.ЙV]?Ji?N`I.噲(>=.噲7hڙ=WI(>I,0=8.Й?F?JT??Io!~s.噲(+>=e.噲W=ӁW?=.噲‚τ +e=.=Ҁ0)"eSF?e( ITX=`.Йgn?ׁ{w\J.ЙفЙ >],`+ `+\>I.!=2.噲(+>=0NX'ꀔĘĬ?=.=w 4Fxf` Ι`W#'<H.<9],`H`Sy`d``>N$/`N`ŝEԗ`ŝᆗŪ醗WA> N$-`8/Ŋ99IA!RNEŊO9(U>=grġkuFB?Iw>=3L̀XŊc܆o=yŷŊ܆?=톙WI^ŪJ +?N!,`.?ŊJ=RSRWI[a_^dŪJis7hu{?N`Ŋ=Ãŷ7h{W =,;9WIGOKŪwQ>=c|̀Ŋ܂ŪIŝ(>=уŷŊ>=ŷŊ܂Ū?J/+?D\f`|],``y`\>I"H^Hv7J?Eޜ`h넜uWA>N +` U9I"+"^<3v7BE?=0S]$''D7.'}MUQ-j(ʻܘ|ށށWW],` ``>Nǃ`ۀ'9NT`򒿆>I gv7 >I#g^J)0g?>N\cU`j7 kl>Iz"~vЃvJЃyW7 +?=0$''$ >D7.'}M'%>O'̧ߘ ۢ* "=m +  " Dm !ҁqw"``\? ԁK`:J.Aց +2# '$2a[`J% .ׁ7Mv% 8'9QvRa[[J]]bX.*؁{& |''a[[JΤ.)ͪ.zہŋˌ(`\? ݁A`:J')ށ"6# '$&6'a[`J2)߁;Qg% <'9UgVa[[Jaaϭl& m''a[[JDσ*`' +a[B ,`:PP{Z{`+a[q,`:\?vЂ PA`:J.+L-L[>N.[.+Iڀ(+>==$1'/.,ߚ'0?J>EQQ1b[>Nos.[u.-I!ї(+Jї?J2[`>N.[.-I$!,( (+J5<`'3'4V[ ?J<ڐ# '$ސ[`J".2ҢҢ.)r% '9-r.[[J6#":6(+E.#JQWa.*[w& x''[[J#"Ӆ(+.#ӅӅšӅ.)[гsx[?E5`v ,`:,`:\?D A`:J.,ߚ‘ݒ# Ü'$[`J"< ..y% '92y3[[J;#"?;((+J<V(](ch(.*[~& ''[[J#"դ(+<դդКդ.)[kԝz6`\? A`:J'7It48`\? 2A$2`:J*'9ֻU[:` \?  +||A`:J';-X ɖϗJ<` =[  =[\?ר $$HA,H`:J22;.=ߛ>`\? O4:?`n ![],[@],[ |[],[1[ A`:+!!Ba``\9a``\'$'CK6'D'EԚ'F1xx<<![],[@],[|[\>=..G.%=.@.G.@%S\jy x #';AB![S],[YH[`>I["e_,(+p`'3'I>JB?=՚?N [N-a`I9C=,(+>=Tڬ1[[\h=uڶ4~~`J11[[''JIŜ`'3'K,>N@],[ ? ],['',,4=Oڬ1V[Wcic={ڶ4`J1c[''J>Nک|[@,=ڬ1[+1=?ڶ4HHw`JNN1[g1m[qJ>`ڬڶ%ìsGˬsL],[],[>N],[1[E``'3'M!$.,.W>N=A[C[''NRԂYIcg`'3'KY>=[''O.Y=ʜ[''PY>=[''Q.=.[''RBJYJbi&AASAIS`:JOO.K/-X`Sw`Jzz.(Y.T`J.(YW.@(Y'ЭЮ:U:`[>N`.(YJ # .!9/&.@20W49[(?SVe][`:`>Nry][`:`2`:`NW][ .|=[''XE``'3'M 444W>N+0K`:2`:'3'NBI4=YSʀZb`''Nq.|xnJ/K`:>I!.Aߛ (+BJ.Aߛ ?N`:'E``'3'M&c).2c02cW>I=CAcw>=RNYRNW'G?=pNwpNWz[''N.cGI`'3'Y.@>Iۜ`'3'Y.=NNW'G?=NNW'GE%.0`5`'3'MSV.@dbdW>Iqwu⭃w>=NNW'G?=NNW[''N.@G=NNW'GI`'3'Z-.|>I=A`'3'YY.=`Ng`NW'G?=vN}vNW'wGNW][ .|=[''XE`ꜣ`'3'MV VVW>I"(&Vw>=9N@9NW'G?N_n[`:py[''\.|V=NNW$'RÜ[''NVG=NNW'xG?N ]`:%.!=6N=6NW$V'^GG=\.A߀kN Jw~N)# '$[`>I`'3'_>N[[''N J`'3'`DD.?J***% '9./[C6+a`*[>I^fb(+Jov?I`'3'_>N[[''NԙIYd].(+Jmt?N`..Iw()J?I""܃w(+ `'3'b>=SD!T..Jkr??J.+ӹ& ''ڹ[[J.%\)*ܴ Oވߗ2 2c`5.([6Wda`7xe`+A([da`\>56' 9A`:>NȺf],[ӚO.I(+J +.K>?N `:'".K>W'GN6Ag`)EMVX`]_`a`'3'huW>Iw=W'G?Ni[Ü[''N遃Iꜣ`'3'j=*?=+2+W5>G=RYRW'wGJe#ly.K>`:>K`:J`:'3'.(ߛ5?ӽ9k9`>Nl`.eߛ7J# (+.e&.d673`:>Y# ?'$]^a[`Jivi.k?#{F;% '9a[[J.k?%<˽& ̜''a[[J.k?& Z^tBhnm`D K`:HK`:\?D FAɾ`:J.KDIؾSRn`L o[O< p`MQ q[N~r],`B+\@K@Ks[q[\?MlLcO@"`'3'h@6c  Q@P@g@t@s@],`B>I@y!@@}.rߛN(+J@@.rߛN?J@@.r@šC@.oߛLNS@@AuAAA f],[[>NAA&v],[A(.wA>wUNAQA]t],`BAd.tQEAuA~A`AAAAw(YAAAW>=AAAwA9AɁAA9AقAA9TAABxBBBf[`>NBB[B![''yB<.oߛLBSJBbBv#B[''zBB],[''{BB[''|BUBBDwBDBf],[],[>NCC}[C.qߛMIC.C;C2(+>JDD+/[D2.pOD??JDD],['~'yDɀDVDDFADF`:>NDD`:'NEEt],`BE!.tQNE6EA],[EC.wEYUEEkEtEv`E{E}`EE(YEEEEEEW>IE!EE(=EEEW'G?=EEƀEWEɜ`:'3'EEGNFF[FF F9IFF"`'3'F@-[FP-`>=FjFlFjW$F'FzG?=FFFWF'wWFF.xFTA&GGJFFWHHQHH,QH],[> NH9HEt],`BHL.tQNHzH~]``H~h``NII],`I.`JJ.(YNJ3J<][`B`JNJJ`BJJ.J9NKK [KKK9=K'K$OK(K6nIK?KCKMKT>=KqKiKrKw:>=KKKK:=KKKKnOKKa``KML``>IL LLL&lJL*)?NLiLrf],[LtOLIL!LL'(+JLLL'-L?IL%LԆL`I>JLM +LM M `IxMM`ItQT?IM9%M?M=`>JMZ"MnMaMqMo`!MMM`-M?JM*NMM`)CM߆M~>=M~*AFNN<N`BN6N-{>NNJNW`NaNYNbmINw!NN|N>NNN`NNONm=NԂNN5 NN.wNUN5 9:=OOO v=O7~)BOU?IP`PmPdC>=P$''P.''?JQ5Q<XQMQsRL#QN+ QY'$QwRLQx[`>IQQ`'3'_Q~>NQQ[QĜ[''NQ~QؙJQQ`'3'RRR".?JR<*YRQRgR% RR'9RkRRl[[>IRw"RR{`(+R.#R`XJRR`?JRRR`.*ZRRSP& Rќ''RSPR[[>IR"SS(+S.#SXJSS"?JS+S2S<.)OXA*z ]`` ][`B`nmLL]`B\?`a`B`n/!`n433J4p`B`nJ::x  b],`>N],`.`F `n.ߛ`|>I:!OI>p(+>=ibՀxmp;I!q(+>=Հˁq;>J+J cw(w03`@``JTT.d m %je|`B`\>=.ߛ` m tfk +k`B*`\>=QE7.ߛ`F ma !ugpu3```>I C,$ S-wOE S->Jo*?I T. T.>J*?I"!%) !`!B.ZR !pf !j>J*?E``݁ T.    W>I !.* UA 'WO Un 'j>J}*?N][`:` V(N][`:` V(F 3K`:- {>N?P`^R _ mIlp (+J*?I!.  m j>J*?J)h7?3`O``>Nhz`|J  I (+J*?N],[O N1],[3OB ER[]`db xf (Y  W>I!. h 9Ȅ  9j>J*?J)i JJ ``J))3 9&D-`` j.3,B,J3`Z``> I"% *`B .ߛ` *`Bl>=).9 *`BB 9fJT)?I"% 9`B .ߛ` 9`Bl>=+.; 9`BF *eJV)?I * 9J)?I".) 9kJ5)?I. *iJ)?IG *>N4?[XAOP *9IcgGs 9>Nhu[wO 99J. ˃ j?N-[/['3'?N-][X Jk"r. s 9j. ˁ 9j?IG 9>N[O 99N[['3' N-][& +J;"B.R *[ +Hjy. * +j?I%ƀ *`B>J"% 9`B *`B 9`B?I,%80 *`I>IX%f\ 9`I>Nzp` *`IpOI! [( 9`IpOJ*?N;A],`BMC 9`ItQN],[ *`Iw& UN:C],[OE 9`Iwe UE`׆ f [ f fW>I!. ( f9! " f9j>J5*?Jah. *`Ix T 9`Ix Tg>J*I% 9`I>J.*?Iu%y *`>I!% 9`>I" 9ݚ&-``  9&"-`` >J8)>J`*?I% 9`>J. *` 9`g??J. * 9hk16<D``JS""S] cv  &-``  c q     y nj`p`+q`+x\? t$)8@`\>IL!VP.p(+>Igku.p| >>J?I! >.p>=a >h&s-`` ??=. >pu`\>I!.q(+>I ).q>JU?Ik!pz.q )>= )䚴&-`` ??= +. )qv&hA.h`:J4$h7@.p'W`.q    Qy`{ `| ],[} ][`[~* ],`F `] "`t #`[ ],` [+ ],[+`*"`*4#`*\? ] k y{#h ys3 &2 &`|3[ /} C~#RD M(+:h`3` M[],` ΅ᅲ[][`[>I (+J +;`[?J*c`[;`[[[H \ u2K4+[[J[''N   k D?[ +['' '[['$P 'ܚ'y'z'y{'ۚ'[['' 8`)[+ +a```[@a```['' +a^````Ã`ÁK`Ø`[r^````Ã`ÁK`Ø`['' a``[Ҝa``['' a`][8a`]['' va`[a`[''̙[[''gΙ F'[u[''љ[[''ә[ۜ['' [[''י[[''ٙ[Ɯ[''ۙ[[''ݙ[([''Mߙ[Z[''[[''[Ϝ[''[ [''7[J[''u[[''[[''%[-['''[[''E[E [''Eh[Eu[''E +[Eל[''F+ [F3[''F[F[''F[G[''Gw[ 6[E['' n[|['' I[W['' b[s['' [[''7[B['')[8[''Q[e[''o Q')`z ǜ'7`=9`F` [['' [['' +[['' ],[],['' k [k[''4`I`'$)'f6'%G'O'N-]['''U'-]['v'-][''-][''-][''-][[[''-][[['Q''A1[A@[''Eu[E~['' E!][[[E"`7 +Mt[M}[''#Q$[R[''Zs%[Z[''dp&[d['''e([e['') *[:['+','-'.'/'0"sx1[#[\>=[''2 あ N3[ɜ[''4 N5[[''4 =$" #+ D=9&I 聃M S=b&r 聃v |=& 聃 =& 聃 ͙$݃6[#[\>NW][  E(13`8:`<`'3'hP (ZX L\ [a L_a LWA>NqvK`:x`:''N ( LI ('BB?=%   J %*7*[#[ K[\>N8[8 9 !_? !hIHL`'3'9l !h>Nbk[m  !V !hI! !(+>I`'3': !>=✣[''; !V !h !v?J??N29<[;[''=K !vNX_>[a[''?q !vIz!~ "L(+>I "m(+>N[['$'@'A8 !vH !VV !hf !h=s[''B !v  " !h?I!х "m(+>I너 "L(+>N[['$'C'D !v !V !h !h=[''E !vؚ  #e !h??= +  !V !h# !v&-2FAB[F#[LG[\>=V[''2i $m $-4ss[>NH['[''I $ $-NĊJ[Қ' $$ $-I $(+J $l?N$0K[2[''LM $l=_n $ℋ{ $J $KՋՌBM݌B[[J蜣[''N% %D,「4 %D;L7O7[a],[Ja],[''N %䀍 %+MkkPrsQ[R[[J['$'S &'T'U'V-['W'X &'Y &'Z2'[]'\ & '] & '^'_ &'`NГДaߔ[[J &Otb-t.[],[J;;],['~'K^ &dPwcd[],`B>JCҚ[ ']Q{e{d`2f],``>J@G`''yb 'p 'RfK[[JĚ' (יSgK[[J' + (]TOh'O(K[[J22'> (EUQQi[\K[[Jff'r (yVjK[[J' )&Wk˘K[[J֚' )iX9l 9 K[[J'" ))Y;;zmKzLK[[JVV'b )iZ||nK[[J' *2[oКK[[Jۜ[''N *u\LLpST[[J``[''q *-`À *]0r0[`>IȀ +(+J*?I圣`'3's +>J]d`'3't| +?Iɜ`'3'u +J*?IĜ`'3'v +J*?J `'3$-'w +'x-`'^wwy[K[[>N[S ,J#! ,4(+Ĝ[''N ,4 ,&+[_66zCD[JK[[>NX`{[bVm ,Iv!z ,(+>N[[''N , ,I!ȃ ,(+>Iݜ`'3'K ,>J[''z ,?J ,??Nҟ|[ۚT ,I! -|(+>N }[[''N' -|/ ,I:"!H> -(+S`'3'~o ->J['' -??J+`àá*ѡ*[[[J霣['' .N! .Wa--67[=[[JNN['' . .bZZ"q"r[wK[[>I .(+J+?I .(+= .'?NǢ[ϚR .J#! /M(+[''N /M .+[c%*p>[[\J\''2$ 2.'9 27kAF^_[b[\Joo\''2 2 2'RR[G[[>NY[Ŝ[''N 2⁦ 2J#ꜣ`'3'_ 2[''4 2⁧: 2낧@ 2M 2[(UZde[kG[qK[`>NY[' 3 3J"! 3(+`'3' 3 3lݧ[K[`J( 4. 聨 47m$_-_.[4K[`J==(H 4NꁨZ 4nafop[vK[`J( 4끨 4o[K[`J( 50љ遨 59)שܬPP[[[\>I`'3'. 5-`>=G*c 5Jq?N+[-[''IC 5IPT`'3'jg 5傫v 5>=) 5 5傫 5?N֫[✣[''4 5= 5" 6MB- C 6M*SX\s\t[\>N[[''4-`NW][1 2 6ECLN`SU`W`'3'hk 6us 7w 7#| 7z| 7WA>NK`:`:'3'N 6ꃭ 7I 7('BB?N8[  6ʅ 7=+ , 65`''CJ 7Q 7+_d[\>=* 8Z=[''? 8Z=#ZK(+K^[''y 8Z+[,!![[[> +I 8(+J%?N3;[=[''4S 8I^jb 9(+Js?I~`'3' 8-`>=+ 9J?=) + 9 8 [''N/ 98I`'3'j 8-`>=͜[''2 9 8?= [''# 8+聲7 8D=S[''i 8q遲| 8=['' 8ꁲ 8Ι=ݜ['' 8끳 8pʹK[[[>N[[''  :N'.[0[''H :=Y,i ;q :q [[>=([''r, ;Zr==NOK[U[[>=f[''|򀶋 ; ;N[[''N ;=Ϛ, ;ၶ ;s  [/][[>NDJ[L[''4b <<FktK[| =['' NJP[R[''4h <FqzK[ <>N7[NC[ =2 =/S; T =9W =Id!oh =/(+Bx?=  <`'' = =/uɼɽZZ[[>=  >3 4 >;'zvsRs[[[>=['' >q >z=I[''c >ql >zwžſڿ[[[>NEO[Q[''4g >=t[''2 >񀿢 >=['' > >xARARDA^DA_[Ae[[>IArA~Av ?(+=A ?A[''?=BW[''ÀBw ?B} ?=B[''ĀB ?C + ?C=C([''ŀC ?C ?CϚ=C؜[''ƀDj ?Dv ?Dy +QQ`\>=#[''ȀJ @z +TYpv`\>=[''ʀ @{ +؂݃((`\>=[''̀! A(| +++89K[[>IDH`'3'=m[''?=0 Ao} +66`:[>I؜`'3'=[''?=0!, A~ +99EF[[>ISW`'3'=|[''?=0 BG +RօR`+[>I`'3'=[''?=0*0D&JJ B`: +UUh[>IMQ`'3'=v[''?=0+'+++ +ꈔ[[ +a`*[>N3>[@O CN[c`:e-w C CI`'3'>=[''ڄ CJ C?I`'3'=%[''?N?ES`#G CTb Cm{ C`=0 Da- +ۙ#[[`:>NT^[`Np DIy!} D(+>N],`BP DN։`Q Dド EN `]"m0 EIFSJ Eac E;m Dc>N~],` EabI!Æ E(+>Nڊ`Q Dㆋ EJ$')2 D'GP E'' D'???J$' D'' D'dd5hi[nK[t7[[>I F(+= F?I F(+= F[''N F F?N߇[㜣[''肇 F F=4[''郈Q G%T F=\[''ꃈy G%| F=[''2 G%^\ F FJ G%88[K[[> I G(+J+?Nۊ[^\ G GI H!(+J+?N.57[7[''NF G큋K GNXZ[\[''胋p Hix G=[''鄋 H G=՜[''ꄋ H Hi=[''2 H$ H!J.5 Ȟ̍э[֜f[[>N[[''1 I@4 IINEIY[K[''i I@lz II= I] IJ I][[[JŚ IК I I*[[[[>IМ`'3' JQ JZ>J JQ?N*,[.;? JQD JZ=OY JQIa!ge J(+>Nz[\ JQI"o J Jm J JJȜ[''N JQ J?Il J JJ JQ J+?IH"!M`'3'` Jcl]x JQ>J[''N JQ J??J JQʛ JZ],`''")JJ|U|V[[[[Jeek LPp LY).[[>Nd[N LI!݁ L(+J휣['' L?J  LPP["[)K[[J338 M&= M/D M8)SS[\[a[hK[[Jvv{ M M M M*..[[K[[Ϛ[>N[; M M= MI! N#(+>N2=[?_M\U M[ N#Ic!rg Np(+>I`'3' N= Np. Np?J䜣['' M N# Np N?IS"!X`'3'k Nw] M>J[''2 M􄕰 N# N??=ǚ M M],`'' N#)J ' N/z,,`],[[`>N``'3'h ON )B],[0+ ONIm~q P P\J*?Nї`烗 Py P\N@],[ + O@I' Pw)`'3'hB PJN*?NW][N|[ O|I!˂ P(+>= Q+  PF !K[ Q+>I)!.`'3'M Q; T Q +J[*??EǙ` Q + P\ Q + Q +W>=윣['' P> Q + O Q +E(13`:8 R[ +< PF R[ +DF R[ +W>=O[''k Pv R[ +y O R[ +W P\I! Q+(+>F͚K[ Q+>=՜['' Q;  S + P S +?J)0//<=[[JHH['$'n Sx'1K[[J  ['$ ' S' + S' S' S' 2  K[`>J#`'3'F T/U`' 'x-`0 T/ T/`' 'ܚ-`1 T/`3 C-C.K[`>J8#@`'3'g Tv`' '-`0 T T㜣`' ' -`,1; T`4FFST[W[^[cf[m[s|[z[[J['$w''т U' '-`y'J U'لX U'{ U' U' U'n U' U'  U; U''! U'" U'# U'$ U' U''% U'& U''x'( U') U'* U'] U'+ U',/ U'-8 U'ل> U'. U'/ U' U'0! U'x-`I'1a U'2~ U'3 U' U'4 U'5% U'68 U'7N U' W U'8j U'9 U':/'с U'ل U'م U'; U'] U'  U'< U'=$ U']4 U'+? U',S U'-\ U'لb U'>?[[|[[J4 Xo+Μ[''@+ Xx X'zAz[f[[|[ [J334A X+J[''@\ Xf Xl X'Ba[[[J))['$'CN Ys'D Ys'd Yj'E Ys'F7 Ys' @ Ys'GW Ys' ` Ys'H Ys'I Ys'JY Ys'dc Yj'Es Ys'KC Yj'L Ys'M5}N ~'O[[a`[[>J悯 Zl皍 ZZ Zc99PCD[IK[Of[Y[_|[f[[>Iw{`'3'󀰬 Ź Z>JŚ Z͂ Zރ Z焰 Z?N[; Ź ZI& [X(+>J5<I ZN] Z&jj Z],`)?N[#! Z(+[''N Z͆ [X+[Nȱ[Ϛ\ ZN[^ \ [XJCJ4X [[ \- b Z͂g Zރq Z焲w Z~ ZQ[7[[|[[JĚ \ \+ \ \ȁ \oRo[f[7[[|[&[J99D ](I ]:Q ]1[ ]Ca ]Kh ]:rrS{|[7[[|[[J ] ] ]+ ]à ]ˁ ]T[f[7[[|[&[J99D ^;IX ^;] ^Mf ^Dp ^Vv ^^} ^MU[[[J ^'V+1[ ^+'Ҵҵ0W۵0[[K[[J _.'+1[ _7 _@+'6õ÷$Xη$[[J՜['$#'Y _'Zκ[ϡ+ ؜'$[[`>I + _(+>J!(`'3'\? `-`KFR `?J`g`'3']v _ `a '9a[[š+a`[>Iꀻ `(+J `?N [ `N)0`2< aD `IMQ`'3$'^'_ a* a* ` a `>J&- `?J8?I `N `˂T `dims``>I| a(+=7?J aþ`Ⱦ[`>I!%ڀ bC`=䚙 bC?J& bC`7aa4a\J:0:@di b [\>N`:& b`=0ġ$'c b'de[[>I%! cc(+J.+?I>B`'3'f` cce cc>=q{ cc[''-`*?J cc8@@Ag @'@A@[[>I@@ـ@ d (+=@⚀?J@A d AVAVChAdC`[`[Am ]![[> +NAAia``[Aa``[''jNBUB[`BfB] d(jNBtBx[BBz dBB dEBBB`BB eTB dB eTBB eTW>=B eBB dB eB眣`''NB dC eT=C eC"C dC# e-_NC2C9[C;[''CN e-_ICY!CdC] f)(+JCmCt f)?=C~ f)CR__C d=C[''C e-_C f)JCC f)CCDkCDCK[`>ICD`'3'lD- gD4 gD;-`>=Dl gDtDz g1D[?JDDD g9EEFMmEFME[`>JEE`'3'nF)F2 gFCFFJtoFJtF[F[+[>IFF9F h-JGG h-?NGG)p`"!G;G1 h-(+GF`'3'qGl h-NG~S[IGG hs>=G hG[''NG h-G>IGGGۚ(+=G2H[[?=H hH4H H5 h-mIHG!HQHK h(+JHZHa h?IHj!HwHn h8(+>=H hH h8>=I= hIE[''rIIbIf hs>=Ix[''2I h-II h>=III h-I hnIIJII(}wJ>=J1JJRJMJ8{v?JJfJm hJwJKs Jx'tJKJ[[>=KlKz jK[''r=K[''uK jKKKv K'wKKK[[>=Kߜ[''uK koLMLMLxLWLLX[[>NLkLqS[LsL k=L[''yL kӁL kӁL kM2M2MkYM<MkM=[[JMKMK7Ma lHOOPzO-PO.[O3[O9{[[JOEOE['$P'|Oi l'}O l'~P# l'PM l'Pe l'Pn'P l'P'P l'P l'P'RRYf Rۜ'RYfR[[JSS['$Ye'TȚ'рT m'Uw'X^ m'Xꚲ'рX m'YI m'YY m'ZZ]Z]Z [Z[[JZZޜ['$]'[ n:'['\e nE'\N-]!['с\ nE'\ n:'\ nE']]]4]]4][[J]#]#['']]]]]]K`:[J]]՜[''] o?^r^w_^}_^~[^![`>J_v_}`'3'_ o_ o_ o_'_ o__`<z_`<_[`>J_#__ p-(+œ` `'3'N` p-`'z`:`?``` `@'A`i``j[`:>I`s`{`w p(+J`'0?I`%`` p`:J`` p`:?J```:'3'` p`Ԛ'Aaab-a+ab-a[`:>Iaaa q(+Ja'0?Ia%a΀a q`:Jaa q`:?Ja&aa8a['3'b qb'A`:bnbnc bzc b{[b`[>Ibbb rl(+=bb rlb rw?Jbbۜ[''b rlb'c rwctctdcdc[c`[>Icc`'3'=cȜ[''?=0ccd s&d + s1dddg$ddgd[[>Jd&#d1d- s(+-`dB[''da s[;ffhvfhvf[fK[[>Igg`'3'g7 tFJg>gE tF?IgN"!gVgR t;(+ga`'3'vg t;g>Jgg[''g tF?Igg`'3'h- tFh3 tF>=h@[''hV tFh\ tF?Jhihp tFi<iCibiNib][JiTi[[iijiji[i#[\>FiiiK[ii u>=iњi ui uji j uɂj + u ==?@[I[[>=S[''2f vco} vlJ vc [a`[>=. +/ v84QQ[JWWc vlz vπ4K[[J v wK)J v yy[[>N ],[],['3'9 w-[JJQX` wf[''@ uu[[>G`:'3' x''a>Iڀ x'(+Jꜣ[''-`?I`'3'4! x'-`>J9@[''X x'?Npw[y[''N x'I x(+J[''˚?J x'>NQX[Z[''Ni x'nI! y:(+J y:?J['''>J휣[''-` '>J [''E x'J x'-`-`[f'>Jw~[''-`'3>J[''-`:'>J['' [`>I?C`'3'b zvh>J|`''N zv?J`''2 zvЙݛ zv Ĕ` [J݀ {#=ߛ !![.[/K[[J99[''NH {cO ɖ],[>Jל],['' +ii[`:>J*1`:'3'M` { ddK`:[>N̖[՜['' |GI  |Y(+J+?=$[''27 |Y?L |GJU\ |Y AA`:[[\>=[''֙ |炗 |=['') |灘5 |,19:[`JEE`'$U'_ }o'g'€ }o''À }o'Ā }o'ŀJ }o'ƀ }o'ǀ }o'Ȁ }o'ɀ }o'ʀ }o'ˀi }o'̀ }o'̀ }o'΀5 }o'π }o'Ѐ }o'р }o'Ҁy }o'Ӏ }o'Ԁ }o'Հ }o'րA }o'׀v }o'؀ }o'ـ }o'ڀ }o'ۀ }o'܀S }o'݀ }o'ހ }o'߀, }o'] }o'ဍ }o'‍ }o'」 }o'䀎 }o'倎? }o'怎` }o'瀎 }o'耎 }o'TYek`\>=u[''뀔 XX]w~K`)\>= <[`J`'3'К =""[\>=['7' <{{qqa[K`:[>N[[''ҙ I (+>=  $ =/[''ES Y ?Jel ttMMK`:[>N[['' HIց Z(+>= Z H=[''/ H5 Z?JAH Z>ɝݟG ʢ G`[[[a__J_'$F'' '6 ' =A'рQ ' ' A'р 'ف ' ' ' ' '# %'?JOagL],[n[],[Jzz>],[ 4],[J @66|[[[J  ['$5 'R 'рg t' t'>'с }'& t'A99KL[Q[[JYY['$ '| ' ' ' 'B11![B],[`J`'$0' u' +' >A' W u'  l'Û1 l u1[ꜣ[''J' l'CSUShVSVSQ`],`B>NUuUy`:U{`:'3'U 2NUU`UUU O@('BNUUy`UցU O#U ''`:EIUU >JVV}VQV=V"V OXV/ H'U`B4VUVUVrVV`:`BJV\V\HVkVi mzI>JV1V`BVHVVV OXV HzIVVW.VW.VK[Wa``2JWWAW ,W& 6WMWZWW`WWa![Wr],[WyH[W`JWW#W W W YYZ<YZ<Y[Y[[JZZ\Z" Z1 'ZZ[Z[[`[>I[%[[ `I>N[;[Df],`[K/`[W[R `IpO-[J[r[~[y `Ix[ T?J[[ Á[[[[[[[`J[[`''[ P[ٙ-`ā[[\\\\[\ [\K[\>I\\`'3'\+\5 \; J\D?=\O$'\f '\~ ''\ ' Ł\\_!\_\[`:J\\`:'$_'\ '"] '#]F 'x-`'$]n '%] ']'&-`''] '(]O^ ')^BN^R '*^^N-]!['+_',_ '-DaHaHhW.aZhWa[/[a`0[ae1[[Jauau['$hV1'2a '3a '4a '5a '6b '7bH'8c '9c ':c ';dP '<dĚH'=d '>eWH'?e '@e 'Ae 'Be 'Cf 'DfH'Ef 'Fg'EgF'Gh H'Hh% 'IƁiikJiki K[i$L[`>Ni[Ni`Iii✣`'3'Mj j>=j[''Nj; j?jN 0>=jc 0ji[''Njx j|=j <j`'O'j 0j Ijjǜ`'3'Pj <Jjj IlElIGlU l>JlbliFlp[''zlOl l?Jll`'3'Tl l-`Àl l-[l llGlmmWUmmWm[`Jmmm&Nm6 Bm=N-][HmZm_} Vmi} mjK[mnL[mr1[`Jmm`'$} 'm 'Wm 'XmӚFm 'YmEm 'Zn*En4 '[nOFnV '\ng 'W-[']nȚGn '^nOo '_oGo '`o@OoO 'aoH'bo 'cpGN-]['dpxH'ep 'قp 'fpH'gp 'قp 'hpG'сp 'iqpOq 'jqN-]['kqКH'рq 'lq 'mrH'рr 'nr# 'osp 'x-`'ps 'x-`'qtp 'W-`'rt 'WtҚ'st 'x-`'tu>IuR uV uZ 'uu 'x-`'vu 'x-`2'wu ' v 'xv 'x-`2'wv2 ' v8 'yvp 'x-`I'zv 'x-`I'{w '|w '}yQ '~z '{ '{šH'{ '|# ' |) '|E ' |K '|p 'x-`I'|ۚD| | | 'I}}}(})K[}-L[}11[`J}A}A`'$W'~ 'x-`'w~ '  '$ 'x-`'w@ ' F 'f 'Wn ' 'W-`' 'W-`'Y 'W-`'V 'j '*-`'Y| '*-['N'р '!N'с2 'wO'р 'O'с 'F'~'LH'~ '(I'E ' ' ' +K'р 'E 'L'р ' 'ǁ!V8V`[;_N``> +IUbY '(+>=0qw'?N[&-_` I"%ڂ `G >=0$O'H '?N\j ],[lO{ I  >=0$' '?N`J& '1 @!˄ n(+Nf],[O n@"! + (+' ́C +1J6=D 4G 1Q[Jàà3```> I-1; D JPW ?Id"ph (+{ (&-`` J+?N[N N[N I"! 5(+& 50 X>JCJ ?N{`J`''I I!ӄ (+J ?N +[ K I!!+% ?(+>=: CJY ?` Ip!{t (+J„‹ ??Nµa],[ŚL I! (+>F# [ ؀>=+ 4JJ ,Q Ic!ng (+Jw~ ??JÓ+ȁbbmn[sK[yK[[>= + Ɂ K ژ))J Ɂ6;IQ`:\>I^b`'3'=[''?=0 >ʁ`:\>I)-`'3'=R[''?=h['' ˁ88[][>NW][š  N<[  J +][''' .. Ú;;MN[SK[[>Naf8[h  I! (+J['' ?́LjNj)֋)[K[8[[Jꜣ['$(' Z', Z'' R's Z' Z' Z'  I R Z'΁,,?@[D#[JW[[>EU^``eg`i`'3'h}  * 9 * *WA>NK[[''N  *IɅ ('B?=   J  ρu'u([,#[2K[[>N@E8[_G ` 3f <Ios`'3'9 <>N[  * <I!Ʉ (+>Iޜ`'3': >= ['';" *& <, J?JA??=cU d *h JZau ˁy  gցeX=  f Q   !6 # %& %{ % & & '? ' ' (? ( ( ) )K ) ) * *W * * + , .0 . . / / 0S 0 1 1^ 1 2 2i 2 3n 4 4f 4 5 5h 6 8: 8 : ;< ; < < = >S > ?[ @| @ A + AQ A B) B C Cs D F G I" I J3 L2 L M Mg M O SX S T T U XQ X YL Z, Z \ ] + ] ^ ^ _ _{ _ ` a b% b b cE c di f g h j k9 k l! lp mW n n o op p p qg rD r s t uU u vE v w x zX { {E { { |) | }Q :    b * T L   n X ( X m ;  W + D  D߈@d~xB[ p^`:Y`: PV` K`: ` ' ` ⛹' ` ' E` O' w` ' gmyK`:\? _ m A`:J$'.K'  Ĉ`\?  8 +8 a[K[[J[''N+ )3 2 cjuva[~K[K[[J[''̀ | ^  :@` 2 K`:Á G K`ā c c`Ł x `́ RR_mK`:+~K`+c``*\?€ KÁ XĂ fŃ v Rǁ HV(XYs[`>If!%pj `J*?I".ϛ& ڛ`J. ?Jꀗ K(.KɁ  z `J.Kƒz_ʁ `:J#.ϛ'.K`: a ́ `ρ `Ё  K`ҁ ˘˘Ә`+K`+\?π HЁ V  Ӂ !`Ձ r `ց y`ׁ ][ 22c>cD`Py`Z][\?Հ ց +ׂ  2ف (`J.yփy.ځ  ]!]`J*S<+t6/.(كy(?>tBhoہ ait`Jw&wwk{.қ`݁ ][`[J.ׅٛ..(Sށ L],`>N(1L],`1B`IJUN.(كvX>=xp.݀4`[`>= Kȁ ^W.AK k;x>E `." ׀$.y) +) W..ԛ>NHP`R_ bh`f.yvk.ԛWx |.ٛI 0((>= ЛK恝 AK.ׇٛ ;>=6- :K$z'a 'Htph 0yփy'ځK 0);J  V  [ ] N` 1 K`: F a`  K`:a`\?    QW` a` ll|a`\? ] l  ` K`: :],[ ͟K`::],[\?   ( Z` ڛ[+ 0ۛ],[+ <<IJ[\>=Y.ڛg[''J=y.ۛ1[ .ڛ < [[>=.ۛр ; d%d`:`>N_`+ V=A9.ۛGE k;JX_ k iwa[`J5`.%'a5[ 'a  ңפߤ`:\>=.ڛ L &`:[>I3IC7.ڛ(+>=fZ.ڛn >=5[.ڛ 䃫 䃫W  [K[[>=ٛ.ڛ = F >>`:[>=1).ۛ5 ; CCXKX[JQQ.ۛ 8 . v  v  BH` 囇` `*  `\? u  i3i8`\>=J[  nn>tua[}c[[>=.)I" (śћ >J+?N_`:+.囇3 ; IHNL N(+BJW+?Iitm (>= N A?Ngo`5`q'P5[ '5[ʃ  N J ՛ +  PPa[c[`J$5$.囇A oI x UUsYZa[bc[[>Ntys`5`{'5[ $''''' I:%E> `>=a\ '?NL],`.囇L ́ I e(+J  ?FA.`7 e>NMP`WR %'=sp 'N[`Noz`:'I! ͛ϛ>= 5`'P5[ S# ͚ʁCa$) ͚''`:5[;9 S' S= &'?I"ݛ넲 ́K('aB   ́K('B>N=G`5`I'P5[`^ Mi & M=5`~ @ ́K5[ 'c΄ ͂c I!솳 (+>=  ?=0- < @>Nch`mj %'PI! (+>= C ?= C5`'P5[  /) ́K<6 ͂c5[QO Z & Jz Q H 1`\?  ma[c[` յܵa[`: a[` /L'/(a[],`  2 d 4:` \],`+ lly\>=.1`-3JamQYyi؜Hq15Q@k' l a[c[`:>K>I"""Ȁ (+%䀸 `% `:/ >JBPI A?Fjs`.>I m J΂  ?[l[`>=BhcS$' p' yo]J+ {{a[c[`>I (+J*?K>F9\B`O.>Iftj m{ J  ?[l[`>=$ +BhcS$^'K ~'X o]Jk* La[c[],`>K>I!ʀ (+>Fݽ`.>I  /m! ) J>OE /LX ??y[l[`>=BhcS$' Ž' —o]J1` l  JPD`'\? " v{ma[c[`J! U# BEBEa[`:>Nܾ!`:盜 åK>NyA`:$ åI ځ(^w>= @タ ڃX@ 𛓃yHW'HG?I@@@ ځn@ øO>J@@ >JAz$AA 'A ø'A[Al[>JB2B9 ø$ BJBOBjBZBjB[a[`JBf)% BoBDLBDBa[],`> +NBB[B\B GNBB]b`Bɬg`NC-C4|]`C6g`=CPCkTCz `C ŦC G)NCC]`Cg`=CěCߚUC `C C G)=DD ŃDD, Ŧ=D>D: ŃDEDT =DcDw GD ŃJDDD Ń 7 à  ( EEG` -\? '* EEFXmEFXFa[Fc[`JF"FmF& lF. w"F@F9 w(FP+ FFGFGFa[`:>JFF曜F D $. G7G=KL``5\? 0 GmGmGmGsGGta[G|c[`JG!GGG Ȥ(+1 GGGGGGa[`JG)2 GGIGIGa[`:>NGH[HHH T'II""&I:I:I3I& i(w`I[IVII i(IjI^ iIIxIk i(y>=II iIII i(y'?JI$I'II i'3 IJKJLJKJJa[],`>NJ-J6L]b`J8g`FJ\JJeK`:JmJ ʡ>NJJK`JJ ʡJ =J́J ʺJЛKJ KJK K + +)JK.K>K5 ʺ | , y ˧6 KOKUOs ``8 K +]`:`:K`:`:@\? : KKKmKKKa[Kc[`JK%KրK a`; KKLKLKa[`JL)< L +LL/LL/La[`:JL$&L$L+L$ K`:= L4LHNLLPNLQa[],`>NLLL]b`Lجg`NMM [MM)M" Ya=MGM6 ͕4MOMONMPK[MVK[`>IM!NM[M (+JN ?=N#N r&ND#N'N3 NF. &NQNQ `:NW >NjK&N~N~ `:KN [`JNNN r> NNOq NOqNK`:N`[>NNN!`:NO JOOKO8 /KOI cOe 9 ̕ 1 τA PMPSR ``H\? C P~P~PmPPPa[Pc[`>IP!PPP ('BJP*?JP!PPךP (+D QQQ#QQ#Qa[`JQ)E Q(Q/QzQ6QzQ7a[`:>JQEQLQZQn F QQRLQRQa[],`JQ1Q`QK'KQ.Q VERK'KRM VcRv Ќ . I RRWg``Q\? K RRSmRSRa[Rc[`JR%RR N][[[L SS S(SS(Sa[`JS$)M S-S4SS;SS<a[`:>NSNSR][[[&SNST ][[[JS`$SSjS| 'SS (}N SSULSUSa[],`>NTvTz][[[&TvT| Ӑ][[[NTT2]b`Tg`=TT ө4TTUxT[TK[`>NTT`T˃T KU +=UU րU-KUPUIUA ց(AKUc @x=U.U ӐU O=UU ӐU JUUU ցO VVWeVWeVa[V]`\>=VV VVK'KW2 KcWW & ҇ h # ժR WW[|``Y\? T WWX mWX Wa[Wc[`JW%XW 6][U XXXXXX a[`:>NX7X@][&X7XB ֖][K>NX^Xe(`XpXg ֫( JX~$XXX ֫'X X[Xp[>JX$XX؛X ֫V YY Y$YY$Ya[`JY )W Y)Y=[zLYE[zYFa[],`>NZ@ZIL]b`ZKg`=ZxZo ZZ&ZZZ Ɂ(`&ZZ ][L=[3[G Ɂ[O J[^[n[e   n ` ס ؤZ [[]j``a\? \ [[[m[[[a[[c[`J[%[ـ[ ,`] \K\R\x\Y\x\Za[`:J\e'^ \}\\\\\a[`J\)_ \\]hL\]h\a[],`J\1\`\K'K]. c]W  ` ٣ Tb ]]_``i\? d ]]^&m^^&^a[^ c[`J^%^^ `e ^+^2^^9^^:a[`:>N^Q^W`&^Q^Y 8`J^e$^^o^^{ M˛^'(^^^ MK^śf ^^^^^^a[`J^)g ^__L___a[],`J_"1_1`_;K'ˁK_q_j /c__K'KK_̀_ /K ڴ   ܡj ``%bf``q\? l `V`[`m`a``ba[`jc[`J`u%`|`u )`m ``a9`a9`a[`:>N```&`` ݅`N``]`:``` ݚ:`:`Ja$a5aa ݚK'Ra)a ݽ'n a>aCa^aNa^aOa[`JaZ)o acawbdLabdaa[],`>Naa`&aa ަ`NaaL],`1a`Faaa[aa ޿:>=ba ‘b Kb! +cb<;JbQbX  ] = ~ pr bbc``y\? t ccc4mc +c4c a[cc[`Jc%c%c `u c9c@ccGccHa[`:>JcV$c'chca T'Hc}czcs Tyy'v cccccca[`Jc)w cccLccca[],`Jc&cc߀c L],` , Uz ccf9``\? | d!d!dOmd'dOd(a[d0c[`Jd;%dBd; `} dTd[dzdbdzdca[`:Jdn'~ dddddda[`Jd) ebevf7Le~f7ea[],`Jef/eeee AƁ'XU`4eef&e`:`Jee˛Kee )Ze''P)  V  f<fBo ``\?  fjfjfmfpffqa[fyc[`Jfff (f ffgfgf[`:>Nffa],[fӚLf }Nff!`:gg }Ig!g&g (+>Ng;gE]`:gTgQgG 䒀`:gXJgl$ggv '!gg '>Jgg  gggggga[`Jg) ghoLhoh[],`>Nhh]b`hg`Nhh"]`hڬg`Nhi#]`ig`=iGikXi i 6i *=iiϚYi i 6i *=j'jKWja jh [jw *Ij"jj 6Cjj [C>=5]b`j 5[j݄j KjK'$)5[k'k% Kk.k= 65[kZkX Kkakp [ K?Nkk%]`kg`=l&lASlQ lX lq[''4l *&)IllƄl C>=5]b`l 5[ll 茀lK'')5[m4m2 茀m;mJ  ?Nmlmr[mtKm Im!mm (+>=mm mK'(Kn')1n3[n4 ?NnNnX*[nZ[''Inp In{"!nn (+!n]n >=nn n›K'+Ko 靂co.?Jooo  U W oopy,``\?  ooomoooa[oc[`Jo%oo ` oop"pp"pa[`:Jppp =A p'p,pHp7pHp8a[`JpC* pMpapwLpipwpja[],`Jpu1pu`  l  #)-` G !`: ` 2`: p`[+ zz!`:2`:\>=.( } z  ‚ .` /[ [  /[[\? ( 1  ` 0`7d 1`   \2`7d X3`7 4],`/.` 5` 6` 7][`:`:+F`:`: }8a[`:J`:'9' r LJڇa[],`:J#`:   !&;<a[],[JKK],['~':y  É{;։{a[]`\>= uK'`&[*\>Nz?][5][g[5[ 5'z 5N@[[''AAC"!​ (+! 䆋 r>F[(> A>NPYB`:[f N|C`:'DI R  D>=  X  (^H?I  $n% B0?NDJK`L\ d I"& ` +('B>=ܚ +뜣[''N 䇍 ?=" 퀘&K: KK +F_hK`:p A>NK` TIԅ $n TB?I%"&)) `D5= t('B>=]e tl[''N{ 䇏 T?= 퀘K TK tI! B?=  'E nF]`],`>NG],`ۀ = 󾅍4=`r``>NH`! KƒR'pDN:CI`LGE KƒR'pDIa!ne !(q LJ{# !W`?J Kƒx K =J  ޑJa[`:>NK[) I4D8 "(+>ISgW_ ('B>J~'L?J'M?Jߛ " N[`:>JȚ  Oa[c[`:>K>N`:C2囇K S I`!ld (+BJu| ?J A[l[>J$'P  ޔ|Q|[`:>NK`: A@(# R'RD#=JBNI Xb'R(^voj (^yH a[K`:`>K>Jl  [l[>J* S)1T`DK``>K>JXht  [l[>J$'P 5  ¡UСa[[J`[` p4LV`:`J'!E'7 p? (+4XXfYK[[Jbb K4sstK[`J}} p - W()a[`>N9>`:@H uIS"!\W ('aB!pk ('BJ)?I"] u2* u(+>JA)?J%逧 u`[ qhq}r Xqr ^`:Y`:>NqqY[q[''ZqǚJq#!qq m(+qꜣ^`:Y`:'3'[q m+^`:Y`: rmrmr\rr[>=r['']rr sssss[>Jss sststsK`:[>Jss嚸s  3FFUF],],`> Nt^][`:`F`:`I(Yw>N _`[ 4!(YF@gIP`S>Nv``:`:'3'a /N,],`:Ƀ 'XUN=A`:hUC ʅ`:4llm`:`:J 64`:J$'X 6t 4ڊ`:`J!䅊 R'bD!4 `:J'N&c`:(=6 =5`eJ $ 'd 'w4`J  t· .· .W UdI!((Y>F܍ +`: {>N`. / mN?Ie`UKhW UIl|vp W(MbP?d >>=  v???=֛ C=N],`:-( {=?: ۅ4KKL=`:Or`:`JUnhdU e +6mxx  +*m=N],],`1],`Fˎ`: >NՎ`쀎  +m= +1` +! +2)# +臀l;J:A + II}Z}[>=ta C 1f 1`J`'g'h 44=>[[>IGK`'g'i\Jl?Nz`W=WI(Y(>=[ +1c`'t'jI +1^(YJ??NP`[''r(< +IEOI +1(RW>=o\s +;>= +1 +: z  1  a }  5 ϡ ؽ m ܺ ߉ n p  i R N a R W , D +n + + +lk   ``~}z~[> ~`[> `:> nu`:> Әژ`:> 5 `:> 9@^Z^`:> Ț`:> `:> dk`:> `:> `:> 'SOS`:> ŝ̝`:> gn`:> ͞ԞߞK`:`:> inyK`:`> ,1Z:ZDQ`\>=RN + + #*:B=`:Lr`:`:>J`:'9' + 񁣪 +  [[>=0($'' +Q + +; + + + + + +0 +W +~ + + + + +A +h + + + +  + + + ^ + + + +9 + +|Ɯ 6"P[߈@ρHW`Ӂgmzxz\? mс̂ӃAۃ`:Jᜣ`:'9'. + + ԁmR n#K'``ہăʃЃ\? ʜց&TA+.T`:J44`:'9'.؁/z+/`J#.hh7h7)7 h7+`ف4=P$IP`JL-` + ' + i + + ܁ Zf`[`\? ށ.6<(<<`@KXMXR`_ + m + + FU_`\?  +Ї߈``"424\? "v~z`J$`J-` +] + +%+}`^d{y{\? d +CI`~\? A`:J`:'9'. +P +ۊ:`\?  88`:J`:'9'a. + +Ӑ #K'`` `-'o`'`'\? `:>N +[ ['9'.N5;@`H=&SS +`:Iake +(+Jt+?NK`: += +5` +e#ƃ +(+ɜ +e +`J#! +(+ +܂ +e`:"+`:>N8>`:F= +L.AW'XGW +L'XUM'XGJ +LݎY`J7.!A)`:>NK`:.I +)(+B>JQX`:'9'.?J$' +)' + +$ + + +- + â#K'`\?  +A`:>IPT.Jgn.?J`:'9'Ț֚.. BK(MNs[`>I[e_ +w(+Jn*?N``''.Iȁ +(+J؜`'g'. +w?J`'g'h +z +w. +w z`>N`Ȝ`''.I +W(+J + .?N2>`@`'3'.Nqv`|7h7W +Wz7J +Ƃh7W  +7+$+`J. + +Z +/ +] +dj`\? uuA}`:J'0`[J+ +9 + + +^^ _#K'`` \? Ǘ֗Y`J7.[J+ $0K)0`:J,+48b@b[JCC['9'.gnAv`:J|$'. + + + +< +r +!J #K'f`[`],_]_qHNWUW\? NI#ۂf`[[]!_>=['' +^J]!_'' +^$T\if`[j[]!_>=v['' +=['' +Jߜ]!_'' +% f`[[]!_>=*[''T +_=_['' +_=['' +_Jœ]!_'' +_'[\>=['' +(--[\>=Ӝ['' +:=[''$ +:)22>?[[>IMQ`'g'.>=0& +`:?*""[[>I͜`'g'.>=0& +`:?+'/U6U`[],_J<A5__.,Y^ad K_\>=q.'*=['7'R. +-Êš,`_>=.'*I"  + +^.(j>=0):@ +?JRY_''. +.kk,` K_\>=.'*I"뀊 + +w.(j>=0 +! +?=3['7'.Z +a +/puN~N,` ]_\>=.'*= +s.(j'I!%# +][>=H +\S +?Nq,` +( =.(.(jW +mNҌy`ހ +sW +=.  +E .(j. +sK=,. 5 +s< +EA +K0SX9^9n`,` ]_\>=.')= +ѓ.(j'F_ +>=.5` +5` +" + LW + L( + -Z1>@7J_>=S.'7*Itx.(j(=0..W?J_''.2؎ݏ``>=.'*N"(`).(jE5>@`GE +!tI +!ZQ +!tRQ +!tW>I^jf.g +!tY(m +!3>=[''. +!tJ)?J*3',7=a_`\>=T.'*=v.Μ +"))64a_`\>=.'*=.Μ +"*66 tΜta_`5`\>Nǒ],[1[Nޒy`.(jE` +#A +#' +#A +#AW>N__''N. +#AI ! +" +#( +">=3* +#7 +#;?IO!_X.(j(b +#'=0gm/.?I +#(Y( +#'J?=.(ق +#(YmN,(` + +#(YE!`(& +$* +$t2 +$32 +$W>=?[''.[ +$^ +#h +$7ya_`]_>Jq_. +%(8͕ٖ++`[a_]_]_>J +__.% +%9053;3H ]_\>N^``g.(j=s.'*Fl_ +%>@" +&(.(j0/.= +& +&W=['7'R.' +&,:8=Y BY\>=K.(m;^cjpa_\\>Ny`.(jE` +'" +' +'" +'"W>NAI[K[''N.` +'"=kj +&&ll +'l_I|!.(j( +'=0/.?<ʘ֙ܙ`[a__]_>Jf__. +(=$+ +/ +8`:'`:>NSZ(`a.(jNqv],[x.[} +(xE` +( +(x +( +(W>= +( +($. +(Y:Jܜ`:'9'҂ +( +(_>VV$`]_>J-4,_.P +)u?[gpva_K`]_>J_. +)@Ǜ˛`]_>J,_. +*+A +e~e%a_K`]_>J:A_.\ +*oBjlereu a__ __>N(`.(jIɁ +*(=0\?NK_ .YE`$" ++?& +*. ++?/. ++?W>N[[''N. ++?= ++# +*ǀ ++#& ++_I! +*(.(j=0"(/.?JU\ ++#Cjl@s@`[v _a__ __>NK_ +,N[[''N. +,= +,gʁ +,G +,g& +,_I!.(j( +,{=0/.?J07 +,gDEG' Q'Wa_K`i !a_+_>N~y`.(jE` +-̀ +- +- +-W>N7?[A[''N.V +-I`hd +-&ii +._Js&sz +._?I!.(j( +-=0/.?I!߁ +-(+J +-?=0\E,./y7/=a_`Q !a_+_>Nfm(`t.(jE` +/"y +/<^ +/< +/N*2[4[''N.I +/<IS[W +.&\\ +/_Jf&fm +/_?I|! +/"(.(j>=0/.?I!灢 +/ (+J +/ ?=0 \F46 A Ga_`[ !a_+_>Npw(`~.(jN@_+N`*Eģ`ͅ +0ڀ +0 +0؅ +0W>NX`_b_''N. +0I +0v +1$>I +0>=0ݠ]?= +0)= +0 +1$?I4!?8 +0(G.(j>=0Y_/.?I +0J +0?I! +0(+Jׁ +0?=0\GAA`_>J+6.7 +2;YHFNUeW,`qy`+],_>I}" +2 +2w.(j>=0 +2.(j'?I끦 +2(+>= +2.(j>N05+A`7 +2IB"KF +37M +2[V +37w].(j>=0o +2 +2.(j'y?I +2( +2J1_?J؝#_휣[''. +2 +2I!-5:`Ey`]_>=[k +4-r +4:|.(jJ,_. +4- +4:béɩ_>I.(jwJ.Y?=0\c"(-_>I3>7.(jwJCN.VO.(jyY?=0`{\d,,_>I.(j(J.Y?I.(j(=0\?=0]J16&A&QC,`gY,y`\>=r.'*= +6 +6.(jNѪ`な +6y +6=[''. +6 +6]K+0 8H:,`^P,y`o ]_,`\> +=.')= +6Á +6.(jN (` +6Ճy +6I' +7C(J-?=DU +6'N{],_N`I%݂ +6],_>= +7 +6],_= +7 +6>=8 +7]MD +6煀R +6*=| +7I +7W +7Cw +7(Y>=0^?I +7 + +6>E`턮 +7Cy +8^ +8 +8y>N_ +7 +7W +89=[''2.3- +6W5 +88 +9>E]fh`om +9yq +7Cy +9yzy +9yW>N_ +7 +7W +9y9=[''2.ր +6W +9y +9LHH +,`. ,y`6 _+\>=H.')=s +:N +:`.(jE` +:N +: +:` +: +:W>=[''2.1 +:4 +:rMMR]^]ug,`},y` ]_\>=.'*= +;E +;W.(jI !% +;i][>=A +;i[O +;i?Ns` +;Wy +;EN,` +;i( Iރ +;^ +<>Ni` +;y +<N*4`<6 +;EW> +<NV``ng.(jyp +=.  +<| +<. +;WK=.( +N;Ai`PC +<yR +;Njt`{.(jW +=BN` +;EW +<=.( +=lm=.  += + +=l. +;WK=,. 5 +;E< +=G +;iKNbg-jpa_``>Ny`.(jE` +>j +>P +>j +>jW>NDL[N[''N.c +>jImuq +>1&vv +>_J)?I!.(j( +>P=0/.?J*O=a_``>N"y`).(jE5>@`GE +?I +?oN +?ON +?W>Nϸ_ٜ_''N. +?I!  +?P + +?J*?I(!81.(j(; +?o=0@F/.?Js)e]_J_.PŹʺκa__=r`+\>=.')I +@(+>=*_.455W6=[9r[`J?J &RR +A ] +[&UU +A] +[>=r_.} +@Q `+\>=.' )I +A(+= +A?N (`.(jC,% +A׃w>N=A0`JC +A R +A=a +Aha +A׃yNx|_. +AY=. +A. +BYZ=. +B +BMZRлԽ۽ `,``>N(` .(jI,60 +B׃^9 +B>JIPW?I^hb +B׀>=u +Bד?E` +B +Ce +B +Ce +CeW>I. +CeY( +B>J +Ce?JWS |U| `,`+`>NQ\A+`5`^ +D'#j +DS(+yr.(jy +DS`I +D?^.(j>= +D?.(jyIႽ +D?>JW?E ` +D? +E^$ +E%$ +Ey>I1=9.: +EY(@ +D>JSZ +E?JovWTVnVs``>N(`.(jEʾ`ӂ +E逇 +E +Eނ +EW>N__''N. +EI% +F3(( +EJ/)?JF*f[o \+w`Jzz.(j(gC+`J!. fUAȿ`:J׬.V@@@,`)],_>N@*@/[@1[''.I@P!@U +GP=@_'@m +Gr?J@x@x#_@ +GrW@@@@@]_J@@i_.h@@@ +@@]%_J@@ߝ_.i@AA$zA A$`JAA .XA)ABAe(A*+ADAeAEs[`JAOAO.A_ +HjAjA}A(Ak+AA`JAA`'t'h.mAACD(ACDAA,`\>=A.'*IB?BMBC +I>=0BZBkBq +I+'?=C['7'.C6 +IYCICTDpCVDpC[`_>IC""CC +J2(+&CCC['t'C +J2^C̜['t'h.`&D D C['t'D +J2`>=0DD..D5 +J2?JDGDN_''N.Df +J2ZDuDEDED`D K_\>=D.')ID""D̀D +KK(+&DDDߜ['t'D +KK^D['t'h.`&E5E5E['t'E. +KK`>=0EBEH..Ea +KK?=Es['7'2.E +KKE +KZ[EEEEE][`_>JEEȠ_.kEEF?$EF?`JFFF[''F N-],[-_\FDFPF FZFFg s]_]_JFwFn'_.F +M:]FFFFF`[]_JFFϠO_.^FFGWGGG s],_],_>NGG&`G4G-.(jWG<G6 +M(YJGH5],_1GR_5[G]G[ +NV(Gf +NW5[GzGx +NV G.(j.O5[GG +NV G.(jG +NG +MO +NV_GGHGHGa_`G``>IHHH +O@^H!.(jJH)H0W?IH8HBH< +O@=HG +O@?EHVH_Ha`Hc +O@HlHj +OǀHs.(jH{ +OH|H{ +OW>IHHH +O)H.H +OYJHH +O?JHHW`HHIHIHa_`H`+`>IHII +P(+=I +PI$I.(jy?II-I7I1 +PJI<ICW?EIKITIV`IX +PIaI_ +QT^Ig +QTIhIg +QTy>IItI|Ix +PI.I +QTYJII +QT?JIIWnIIJIJI _\>III. f=0II.?=J.J +R,ZoJJ'JJ+JJ. _\>IJ=JF. f=0JOJ`.?=Jx.JJ~.(jyJ +RZ +5 + +6 + + +v + +B + + + +U + + +! +" +"j +" +% + +%b +% +& +& +' +(A +)W +) +* +*Q +* +, +-i +. +0X +2 +2e +4 +4 +4 +5b +5 +6 +:0 +;' +> +?2 +@P +@ +An +B +C +E +F +F +F +G- +G +H +Hd +H +I +IW +J +K# +L[ +L +M +Mv +M +O +P +R +R| +S IrLLLf`[]!_t\? q +TuLMM+f`[]r_w\? t +TxM.M4Mdf`[]r_z\? t +U9{MgMmMf`[]!_}\? q +U~MMQf`[`]%_N( ]!_NJ =N6+`NdNV+`NpX_+N}N}NNNN]!_\?N +VXNـN +VX(j N}NNO'OO_JO O .ƝOOQO#Q`>NO=ODO-+(`OPOF.Ɲ(jIP&!P2P*.=Ɲ(P5 +W>=0PEPK6Pl.Ɲ?IPPP.Ɲ^P +W>=P.+JP*?=P.PP.ƝP.ƝY=P.PP.ƝWJQ) +V +V +X.y6 z#K'```[+`$9WO4+`9Ӂ؁ށ\? ޜ?x+, r``>I'.) +X>J4;WIJS.wU +X>J`Iu~.( +X>I.(>N` +XI.( +YJ?I.JW?J"?J:IOS.ѝ>Ibhf +X>Jy?J>JWɁƃڄǡ+`J#.(. .`ʁ(N+.N`J11`'g'.ˁSgT+r`>Jx"`'g'.`'g'.́˄߅ ̡+ `J뜣`'g'.$m+-m=/,r``>JFM`''.g +[r\s+`J`''.́˅U+Ѕ`J&#.w#.픃W.```kzl+`>I".^.v>JŜ`'t'.?I휣`'g'.>J`'t'2.?=0`:'9'.ڇۡ+`J.2+2`J+.7Fh8+Kh`JQaQ.m|n+`>I.w>I;?`'g'.>Jkr`'t'.?I`'g'.>J`'t'.?=0\bs`:'9'.+`[J`[''.(+(`[J`['' .-? +.+L`[>IU^.>Jkr`['' .>J`[''.4+4`[J #..%.`[9Hq :+Mq]O, `xj,``>I +`ex +`ww>=0¡1 +`e?I .x +`eJ +`e?I'F0.x: +`wwJKR +`w?Jb.vw+`[J.+¡+``:>I" +a +aw7>=0,2 +a7'?Nmt`:v`:'9'. +aI".(.J$'y +a?J +a + &`+`:>ND`:IP!cT +b}(+>Nu+` +b}I" +bڂ +bw7>=0 +b7'?=: +bC`:'9'.m +b>= +b`:'9'.I".(.J$'y +b?J + +b+Z+>ZN@,``:>I_"mc +cŀ~t +cŃw7>=0 +cŔ7'?NԒ`:ݜ`:'9'. +cI".(&.J2$C'y< +d0?JIP +d0_qD`+~,``:>I" +d +dw7$>=0 +d7$'?N`: `:'9'.. +dNDS`7)I_!jc +e!|u +e!(^yA( +eL>J +e!?JÝ +e!+`:`:>N@],[œ],['' +eI'! +f(+>=0ms$' +e?= +e`:'3'с +f9Nߖ `ꜣ`'3'! +f9I! +f9(+>=% +e.`:'3'? +eLG +f9=X +faX +fyd`'3'h} +f9?J +eW'}h +fLGA+`:>I"".(*`'g'".>JS'#>Ju|`:'9'$.΁z+Ƙ`Jɜ`'t'%. )W+ )`J`''&..KW/+L\N,s``>Jip`''. +hy+,s``>Jڜ`'''. +ie+e. ,s``[>J;B`[''(.[ +iljhk+,s``>J`''). +iԚ^ա+^,s``>N,3`5`''.O +j$I[f_ +j>(Jl&v`?I +j>wJ& +j>`?I&Ҝ['' +j$`>J& +j>y`'' +j$`>J/&/=6 +j>W?`''N +j$`cs*d+{}+K``J`'g'+ +k +kǜߝȡ+᝭,s``>I""".*..* +k!)(, +k!85W(; +k>JJQ`'t',.q +k>J.- +k-+ʞs``>J&䜣[''(. +l`,+.>0,s``>IKUO +m,=Z2r +m,?J~.. +m,.++s``>JW#^`'g'/t +m`'t'0. +m`àۡ`ġ+ݡ`ߡ,s``>I&['' +n0`=21 +n0?J=D.1V +n0et$1f+$+s``>J#&[''.w`.2 +n圣`'t'3.# +nɃw77 +n``)8:2*+H:VJ+s``>Jc#j`'g'/ +o`'t'4.0 +o`?W@+XhZ,s``>Ju|`'t'5. +p +Ŧk+Ʀȡ,s``>Jꜣ`'t'6. +ph3+4D6,s``>JQX`'t'7.z +p+,s``>Jǜ`'g'8. +q$ Rw+ +R ,s``>J'.`'g'9.H +qWpvX+rt,s``>J`'g':. +q٨$^+ۨ$ݡ,s``>J`'g';. +r>ρ+`J .(Ё+C+1C`J4?:.(HW<I+aqc,``>J~. +s,yÁ6=+6,``>Nߩ>`씅 +syJ . +syy'.) +sс;N-?<+X-`>Nbi@`#p.|v.Wy.`NA`7 C +t\^9>= +t\ـ +t\9= +t +tW7 J  +ty" +t\2HB3+N\P+C``>J7 yĝ +uKā D+!,l`3%,``>I<B@ +u=0GX^ +u+' ?I{ +uƃv=0 +uƔ+'E?I +u(J?Nجr`.I"사 +vg +vgw +u>= +vg +vg +u?N`C#,* +uw>I9?= +u>=P +v\WU +v҂hY +vg^ +u?=o +uqo +u=~ +vg +vgh +vg +uJ +ve{Ff++`+!`+G``>Nî`I! +w>C"逮 +w̗ +wޗ>= +w  +w̉= +w +wމ=) +x +) +x hI?EC +wޒ>NZ\`^ +w=i +ẃm +w=x +wބ| +x??N` +w̗NH` +wN¯` +wNѯ=`Nدr`N߯_`N`D>C +y>= +y +yI(, +x>I<"!CA +y=!PN +yL>=f +y=hf +y=Wk +w=z +yL|z +yLy +w?= +y= +y=I! +yL>= +yL +yLy +w?= +yL +yLC +y'>= +y' +y'I(, +x>I<"!CA +y\ !PN +yk +>=f +y\ hf +y\ Wk +w=z +yk +|z +yk +y +w?= +y\  +y\ I! +yk +>= +yk + +yk +y +w?= +yk + +yk +I +y^ +y'>= +y +yy +y'I"& +x=* +y=,* +y=y/ +y\ ?=: +yL<: +yLy? +yk +>=Y +y'[Y +y'y^ +yIim +x=q +y\ sq +y\ yv +y=?= +yk + +yk +y +yL! +y(I! +wJ +x h +y'?I!͆ +y'(=0o'I?I +yk +>= + +yk +  + +yk +W +wI +yk +=# +yk +%# +yk +W( +w?I6<: +yk +w> +w>=I +yk +KI +yk +yN +wIW][ +yk +w_ +w=b +yk +db +yk +yg +w??Jt{ +yk +ŁJ+õš,``>I″ +~v=0 +~+'E?I! +~(J'?N9;`.IG"NL +YW +^\ +~=` +b` +e +~?Ilrp +(Jx?I" +(" + +~>=0o'I?J睫 +~ +)Ɓ4CK5+FVH,s``>Ngi`p.\N!` +)\I +E(J +`?I +`(J +E?I"ρ +E(ۂ +`(J?J +E +`*AWLB+`nb+``>= +<)# +<y8,2 +<9M=K +<`RP +<7333Woci +<7333= +<7 +ºQ+ƺ=`r``J؜`'t'R + +'S+.<0+``>=E +IN +QW +=c +gl +ou += + + += + + +7= +ǝ +ϝ +7J +ǁ4g+4`J`'t'T. +X +Z: +Z +Z +[E +[ +[ +\! +\ +]^ +] +] +^& +^ +_3 +_v +_ +`B +a: +ai +bZ +c +d +e +g +h +hX +h +h +iJ +i +j +k\ +k +l +m +m +n +n +od +o +pE +p +q +q_ +q +r +ry +r +s +sz +t/ +u& +u +w +~ + + + + +x + + +J?ԁU #K'9``:]`:ց9 (%+`+agqoq\? g&؁vw+,``>N!V`(.(I4">8 +怇KE +^N +>=0[lr +.'+ +?J`'t'W. +ف؃X١+,3`:. ,`]`>NFJV`SL +(^I_"ewg +vp +ǃwx +>=0 +Ǔ +?JQ. + +ځr  ,3`:4&,``>NJWX`Y`'3'hm +Iz"~ + +w +>=0 + +?NY``'3'h.I* +W +Gw, +J:+?EKTV`][ +_ +Gk +lk +W>Ix!| + +W +A(. +>J+?J + +.ہ $sW ++%s8',s`:`:>JEL`:'9'.i +܁x]y+],s`:`>NZ`Ȁ +(^N؇Y`.(I +w +J*?J&3- +(6.XK@ +yM +B݁btc+~#`,`:`:>JV. + +ށj+j #`a`@`:`:>J6B.[O + \^ +-߁o4[p+4#`\a`@`:+]a`:^`:+`:>JZ. + +% +9K:Z:+W:`#`xg,`:,``:>= +;.('J].! +' +)+ +;?Qj_@+cjs#`z, a`@`:,``:>= +.('J$^.L +R +ɂ[ +op+,r`],`:>I% +f`:>Jݝ#`:[''`. +f`:I"% +f`O3KF +f`(>Nad[fIv +f`J#`:[''`. +>J.a +f +. ,`9y`P?,`:`:>=c +t + +.(J`. + + +.a+.r`],`:>N6=],`:1G`:N`N&-(`F6?@`PH +3X.A>N}k+b` +N+c` +y= +~ކ +ۃy +I" +~(  +n( +>B?Nđy` +=け +P.X +n +\;= + +n +I&"0* +n7.(HA +~w>= +P.X + +n;?J$ +P3CR4+MVr`oa,``>Nۓ(`䜣`'t'h.I" +K&,,['t'% +Kw. +h`>=0>OU +Kd.(?Iw%{ +>`:>Ns`: +>`:NZ`Ɯ`'t'h + Nr` +KW +*I! +Tw# +hJ+*?J?LF + (O`'9'd.x +K +TB?J! +>r. +K(+ΕiXϡ+i,` +e`+`:>N '(`..(N@Ir`5`K +>#U +|(+X +V +|`Idsh +,=0x +,?I +,w +m=0 +,?I +mw +V=0  +m?J '`:'9'd.P +,\ +mn!o+`:>J`:'9'f.ʗܘ!(ˡ+!`:>J`:'9'g.%<&+IWK+``>I΀ +!7>G݀ +!7 7 +$7 77 J7 ]7 p77>J)>J*?Gۀ +!7 7 737F7Y7l77777 7 +7(7)7/7_*7=7>JM)>Jq* "h +8@3`:WI,``>Nnti`7 Nj`7 NX` +6(^ACف +C +>N` +6 +CAI ""!-$ +(0 +_!LC +(O +p!m{ +>B?= +C +CWJ +C?Uk@+lt3`:},``>Ni`7 Nj`7 AC灡 +w>N` + + +yAI'""!4+ +(7 +!SJ +(V +!t +>B?= + +yJ +VhzW+l`:> Nl`7N`:`:'3'm.N&-(`6/ +(^IBMF +(JSZ +?Njtn`}v +AN`I +I( +>= +mӝ +I +m( +J'??N09r`; +Nܥo` + +ڃyAI  +( +>=) +4L +]T +ڃy?Im"|q +m( +( +J +?J`:'9'd +ㄦ +m +Ҫp+ڪ`:>Nl`7Ni`:Ny`I`'g'q.>= +؜`:'9'r.I  +(^(J! +?N3=n`F? +AI[i_ +(l + >={ +- +?>= +.= +-.I" +-(J(/ +?I;J? +-(TM +(^J\'?Jkr`:'9's + +-L^tM+g`:>Nz~l`7N`:N+r`I`'g'u.>= +М`:'9'v.= +  +ρ(^I( +(J.5 +?NGPo`YR +φmd +݃yAIy} +d( +>= + +̂ +݃y?>= +.= + .0.(IDQH +([T +ρ(^Jcj +?Ivz +(J'?J`:'9'd +ϓ +߮h+ ,n``:>I^! +J('?I7"A; +(UN.((J[.?Il!vp +(y`'t'w +>=0 6?N`:'N!`:.AC-)>IBPLF +(=V +Za_ +kWc +ZG?=q +y`'t'x +I +(B?= +k +kW +kGJ +Z.+ +,``:'R`:>N39i`A; +XyH.(IT^X +vJd.?Ju| +jh +LW.GQ6+Q,``:'R`:>Ni` +y.(I +GvJ.?J0<.WF> +-hH +GLVoW+y],`J||.,+`dJk.͵,+Ե,֡,r`,``>I" +f*$ +fw1.(>=0ARX +fg.(?Iz%~ +T`:>JM. +T`: +f?I%ꀳ +T`>N` +T`N.4@`6LF +%.P +fJ^#lf +>(+wW| +>`?N(`.(E` +fǃ +v + +Ӄ +W>I!뀴 +Tr. +(+J  +?J&W1@gU2+Kg_M,r`mH`+`>N(`.(N`5` +# +(+ + +`I"ƃ +Ӄ +w +>=0 + +?I%% +z`:>N?Es`:G +z`:IVo`Z +Whb +k(^wq +>= + +y +k(^?J0. +k +?E` + +^ + +y>I!=& +zr.: +(+JFM +?JZaWl|wnm+w,s`,``>I"Ձ +ۀ灷 +ۃw.(>=0 +ۓ).(?J<CR.a +Ɂh +| }+`J`'3'h.(ø׸Cġ+`J!. sx+ +s , s`:`>J*#6.(9 +œ#E`'g'8.` +iW``ǹA+Ϲ`:J.z+`>N!`N.5(`7`'3'h.EV_a`hf +j +r +sr +W>= +7 +W`'3'W. += +7瀻 +W7 +7 += +`'t'y. +݀4 +=E +W7_Z +Wvn7p += +`'t'z +݀ +J7π +W7 +7 +$+`J-`:D_E+aqc,``:>I~" +H^`'t'h. +H>=0á.. +H?J`:'9'N. +H + + +z +c + + + +m + + +C +e + + + +r + + + +f + + + + +5 + + + +1 +W + +k + + + + + +& +&ȁ `ʁ##={1=2[[J:: +ˁՙ՚|`[>́C})C/`<K`:[>́EEc~YcZa[[>΁eexya[K[[> + E + + $ + + + + + + + + +o + +T: +T +T +UB +U +X? +O + + + + += +i + ~ ~읁 "Q"v߈@ ~ ~읁[=w`[`[^_K_f`[^_` `[`[^_]_>]` `:&&=/=5`:\? + &BJb(Qb`JT\T.(^fsuz``J. +7AH``:JÀ + + + +m +$i` B K`:"JPg\gbK`:\? + + P +2#"(`[`[]y_&_ ]y_-jjtz]y_\?& + j(`J.&*̂҂a_\b`+a\+`+]_>J+5].__6B__d\.&+炂y +;胂 +H5[ +e +75[ +eb +.8 +e+؂  `[]y_J-__.& + + + +@.O`[`[`]_1u ]_2 `3a_\+4u`+B]_\>=.1.;1 +  6ф؄ބ][J.17 +a_\\>=$.#=2 +(++d^.2[_ +^_[38b`\>=.1b +)I +)(+>=.+4I&%6* +)a``[>=W.wf.2[``& +)a``[a``[4>=..2[`& +)a`[49#(f.f4a\\>=PH.1W +G;kp[w[z _\>I.3(+J?N_K>= +& +_[S[`>I.4(+>=.(.2B +I +I^%ob.4a``[>=.2[`&.4a[`\ + +>=.2[&.4a[\ +J=/).2_?.3L +<`eZjs][+\>=.1Z +(=]\>=.1]@ى\`J.1\> MMf`[_+]_J-5-.1_A + +K + + +) +u + + +X + + +, CRX`[`[`[`[]__F ]__K׊׊]__\?F + קHc%c`[`[]__J15K____[.FIgr5v ]y_]y_J.F5 +__ + +d +L‹ȍ_`[`[`[`[]__O ]__U''B4B:]__\?O +b 'QGJQU __J_&|g_.O&uo +__R5 ]y_]y_J.O5 +__S ]']`[`[]__J37U____U.O + + +Z +V /`[`[]_i\? Y_ovvv]_Z{ +]%_Js__.Y + [(ƃ`J.Y( \ۃ `J.Y ] +C+`J!.YCb0X]%_sIIcUc[]%_\?m +x Ioglt`Jzz.m'q'_J&.m')_ +å + +&tB`[`[]V__w ]_~1p#1)]_\?w +ğ iy6>J`[`[W6]_]t__>Ie%pi +]_>J__ +]_?J~__ +{@@`[]_J!%y__8.w + +p +EK`[`[]t__]_ӊ6]_\? ~ +& +L66`[`[]V__]_ +Ƒ"o`[`[]__\? ip|],_)4X6X;`_JE&TLE.M +99_]kns`| K_\>=. +Ǒ& +Ǟ_:((`\>=.( +W"" K_\>=.& +D_;',2? ]_\>=UM.`y__s +Ș<  a__ `+\>=.#̀ +(++4ލ __`J +& +Q_& +\_a__`=P P&`+\>==5. E +>UZ`e`n _\>=}. +& +,_D` ]_\>=. +ʇy__ +ʔE"'-2`E ]_\>=]U.d +oy__ + +FK``J. +sG̎Ώ֏`_J&. +H_171_J&- .7I_6;FLa_`\>=kc.4wwz_`J +e& +̠_J  a_`\>=.4_`J +& +3_Kt"t'`2y`]_J@Dy___W.h +͋o +͘Ny~ `y` ]_`\>=.  + +y__ + +1O#l.l3`>y`\>=QI.] +Υd +βPqv`y` _+\>=. + +& +"_Qߑmm`y` ]_\>=,$.9 +υ@ +ϒIy__\ +ϟR + + +s + +& +z + +ɳ + +i + +U +˩ + +G + +m + +· + +g +rx `[`[]__ ],_Ȓ],_\? +д ے  `[],_J__. + +/>`[`[]V__]_g ]_ ^`[]_%%J,J2]_@^`[]_\? + + %iO]p`[]_Jvzg_`[]_J__..Ĕɔ̔ K_`J.& +_QQ ]_\>=%.0y__C +FV[aia``Jt|t. +Ө]`\>=. +..]`\>=." +Q38CIa_`\>=h`.4ttw_`J +Ԧ& +_a_`\>=.4_`J +9& +t_ U U-]``J9A9. M +Zamzs]`]_>I!.(+J. +&)?JҞ__. +&+  )s]`]_>I6!D:.(+JMT.d +*?Jw__.  ++ϙs]``]_>N ]_#.(+'g_2._]_FFcO_Z.>Nmy_&{ +_I +ׇ( +tn +=Ȃ +ע +?J +ע// s]_]_J5]_.5[" +€) +ء +49Z >Z\>=OG. _fl]_>N|]_#.(+g_._]_=ŀ +q.J +q]_J. <<`_J$&8,$.3 +<_ +/ +u + +( +ӊ + +3 +Ԉ + +ծ + +֮ +T +؃ + +C + + +wAPW`[`[`]^_\?  Ł~]^_ǁ_J&.Ňi_ȁțʛ7ԛ_J&.ń7j_Ɂ 9~9 K_\>=&.ŀ&0* +_mʁ>C{K{N K_\>=c[.Ň&rl +I_kˁ K_\>=.Œ& +ܛ_ĺŜ˜s``J.ŀ +ńRR ]_\>=&.ŀ1y__D +?o΁W\gma_`\>=.Ň4_`J +ݟ& +_pρÝȞ*Ӟ*a_`\>=.Ň4%_`J +0&  +k_qЁ/4U 9U\>=JB.Ł r +# +L +ۏ + ++ +} + +! +݁ + +ޣ + ӁZ``[`[`[`[]__ց ][__][__\?ր +ߐ ؁Ȟԟ + +`[`[][__J____.فO5!O)K``J3;3.֒5I +@kځTYdl``Jt|t.ց +lہ`_J&. +m_܁ğҠՠ _ K_\>=.ր& +?_& +J_n݁"% _, a__J;&C;.ւ&ZV +_#kb +(++4}}_J& +᷀_a_t_ށ s][__\>=.րԞ____ +du߁** +`_J&&.ր! +v_/4U 9U\>=JB.ց wZ_fla__ˁK\\>=.ր4_K_`>= +c& +_& +_xء]_Jy__.ր{*[1[]_J48y__TL.ց|`h(o`Jrzr.ց(} `J.ց ~C`J.ցCۢݣ㣫 _ a_K_ a_+_>J&#.ր&.* +a_455[9K__JC&VIC +l&PJ +__#yp +(++4_J& +倀_a_q_.7. a__ˁK_\>=.֒74)_K__J&$  +y& +_& +__r3P2X]]__>J^ume.֒2z]__4l]__]__J__& +|_&ˀ +|K_q1q 2]]__\>F3!]__* +>=B;.ր&MIC +'_&b\V +'K_nv{a__ˁK`\>=.և4_K_`Jր +言& +_& +_s +߾ +" +v + +! + +F + + + +E + +@ + + + +C +[ + + + +; `[`[]V__]__ +`[`[]__^ ]^_iirx]^_\? +@ ii`[]^_J__. +i +\ku`[]_\? ems(ss` + +=2Af`[]_\? x(``_ʃ +Ӄ]%_Jڟ9_.a_\\>N#*(`1.(E=FH`OM +xQ +^Y +xZY +xW>=lf +Gm.w +xI! +^(.(>=0/.? `J.(( ss_>I*#.((=00K\?J\c.x~_>I.((=0\?J..(y_>I .((=0*\?I;F?.(w=0Kf]?Ju|.n``>N(`.(E܆`傆 + + + +W>I . + +( +J)?I,!70 +(?.(>=0Q[/.?J* =a_``>NЇ(`.(E` + + + +W>I! +€.' +J,*?I@!KD +(S.(>=0eo/.?J) +-a_``>N(`.(E` + + + +W>I$,( +ǀ-.7 +J<)?IO!ZS +(b.(>=0t~/.?J* ȉʋF ԋFa_` !a_+_>N +(`.(E&(`/- +1 +9 +:9 +W>NHP_R.\ +Ifnj +ˀo +[Jy +[?I! +(.(>=0/.?I! +(+J +?=07\ KMyV\a_`p !a_+_>N(`.(E` +Xy +r^ +r +ry>Nϋ_. +rI +, +J +?I!! +X().(>=0;E/.?Iz!~ +B(+J +B?=0\ Ҍԏ&ߏ&a_` !a_+_>N(`.(N*0@_+NAL`*EYbd`ki +m +u +vu +W>N_. +I + +J>I +>=0]?= +)=. +߆6 +J?IM!XQ +(`.(>=0r|/.?I +J +?I!ށ +(+J +?=0\+26?`:'`:>NZa(`h.(It!y +Z `>I +s(J'?N`:$.I!遏 +s(.(>=0 /.?NKR`Xe +Es|~` +4 +s +4 +4W>= + +Z=ƃ +. +4I! +s(.(>=0 +/.?JO]V +A>N`E` +* +s +*Ƀ +*W>=ނ + . +*I! +s(.(>=0",/.?Jgun + Aa_`]_J +ϒۓ`[a__]_Jf__. +c!'* a__K__>NQX(`_.(Ikvo +(=0|\?NK_.E͓`փ +3 + +3დ +3W>= + + +. +3I!$ +(,.(>=0>H/.?J} +`[ _a__ __>NݔK_ +N(` .(E `'% +n) +T1 +n21 +nW>=> +@MF + N +@U._ +nIj!un +T(}.(>=0/.?J +@++`]_J,_. +E+0N@],_ILP +>=b +5],_1n_5[rp +с({.(W +>= +._.(EǗ`Ђ +1.( +1ۂ +1W>=큗 + +1. +1:J  +!(-]_>N=D]_Jg_EXac`jh +l.(t +ut +W>= +ဘ. +J + + + + +) + +V + +# + + + + + +~ +< + +: + + +' +v + + +q + +Sf`[]_ ]_@ H`  ʞ`,]_H``\>=.H'I!'.ʞ (+>=CT.ʞ 'yIp{t.Hw}.ʞ >=0.H.ʞ '?? m ~ #e`>N (` .( I#"4'.ʞ (+L?.ʞ wN JV] ?Jip.ʞ $`>N(`.( I.Hw .J .?J.H%(`>N (`,".( I8C<.H^F JN?I\"m`.ʞ (+x.ʞ ^ >J y.H?J.ʞ y.H'ߜ᝻Ꝼ`_>N +` .$W I%"/) @6 ^C.e#>=0V`q .'?J.  (̞О`]_>= q'N `)".HW+ qI6"!G:.ʞ (+[R ^^.ʞ >Jt_?J,_. .ʞ )CC`]_>=$ d'I9J=.ʞ (+>J[f,_y..H.HW d>N`.HW dI.ʞ  J.?J ,_.*.H2 *HPQVQ]`)],_>Nx~`.HNy`.( I"!.ʞ (+.ʞ  = .ʞ ?N(` ăy I 4=" 4?N:A],_#K 5],_[._5[fd (o 4W }._ 4],_E`  4  W>=  .ၡ W  :I.(  =0 /.?J@G  e   ~ S F q -#)jf`[`]%_0f ]_1} =`2`3X_+9]_\?0 1 ( 2 5 &9'.9_J11.37>ChKh`>NX_(`ka.0( Iw!{.=1( +;>=0/.0?I.2^ +;>=.+3J*?=.4*.0>.2 3=K.QK.2W2JY) + !:`[`[]_= ]_> О^__L;p";(]_8^__\?= > @  # `[`[0]_<a_K_]:__>IU%bY 8][>JO__ 8 I?JߟL__ 8 IB@P +Y]%_J\`[__u.= + .О>Cϧק(ާ`J.=( D `J  .= EX^zdz_Jgg.Оtj.=>F~_J.О.=>G_J.О.=>Iʨ̩թ`_J.О.=  >   V " j M `[`[]:__]_O||]_a_K_\? ӟL H Y PX`[`[]%_S"X_+T@ Ӟ]%_Ui О^__[pp~]%_^__\?T )U : p+W88`>I.ӞT'>=..О.ӞT')USJ)?=.+SJ(*Y=CV'KV_JNN.S w  .\`[`[]__< ]_`c О^__fjj|]_^__\?_ `  jb(`J._( dǬ`_J.О._ f `  H g&,f`[]_jg ]_k О^_`q]_^_`\?j 3k D mѮ  +ڮ ]%_J|_.j + .ОkoT`f`[ia__]_Jz~L__.    ;rf`[]%_u Ӟ]%_v О^_`|88%]%_5^_`\?u v  +x=BJ`>CSdZ.Ӟu'>Ix|.О.Ӟu')v>J)?J*zѯׯ'߯_J.Ӟu')   }5;$`[`[]_z ]_ О^_]_]_^_]_\? ^ o ְ" +"]%_J__ . + .О   '-`[`[`]%_o Ӟ]%_ О^_]_RXٞ]%_ l `X_+]%_^_]_\?   'Ȳ_J.زݴ`>I.ٞ(+J *?C!9'.ٞ'>=M.+Idrh.Ӟ'>=.ٞ+=%.ٞO9.ОF<.Ӟ') + >Jp*=..ٞ')J) 3 d [δԷf`[]_ ]_% ۞`p]_`\?   4<Hf`[U]_c`]_>It"!%x Y` Y>=0 Y?I%߀ H][>J_- H7 Y?JMX_j Ht Y˷ +Է]%_>J埮_. +  .۞   ]#f`[]_]_]_`\? ן  (`>N `&.( I2E6 wG.۞JSZ.۞?Jjq   u>f`[]%_ Ӟ]%_`LL]%_ +`\>@"%.#.`C8.^#G   +QV^`>=g.qg.yIy}.^>J.Ӟ'?=.ʔWJ*<'<_>I +.J+?J 1'.Ӟ') g  eAG@f`[]_ ]_ О^_`ƺ]_^_`\?   > +>]%_>J_-#. + 7.О @ CIf`[]%_ Ӟ]%_ О^_``*Áӻӻ]%_^_`\? 4 E +`>I.J)*?I;"!J@.Ӟ'!Y.Оf\.Ӟ')>=x.)J*?J)Ľ'̽_>I.J+?J.Ӟ') ! !eāwf`[]_ǁU ]_ȁl `сqqp]_`\?ǀ !ȁ ! qʁ{llf`[]_`]_>I%Ā "R][>J_ "R "c?J.9_K "RUa "ć`]_>Jҟ_..W "΁(u +1u]%_>J7B_\R.LJ + f. "* " #M #ҁzAf`[]_]_ہ@@@p@@@]_@`\? @ϟ@ $@ $"ԁ@}@@}f`[@]_@#`]_>J@0@;_@\ $@f@r $ց@@A[(@A[`>N@A(`AAA.ǁ( yA.IA+A6A/ %^JA<AC %?JAO؁A`AlAApAAu`]_>JAA_A.AA.WAϞA % $U $ % &܁BBD'f`[]%_߁B Ӟ]%_B`C C CqCCqC]%_C/`\>@"%CSCH.`ChC].^CHCl߀ & & C +CvC{CCC`>ECCC`CC 'uC.C 'uCC 'uW=CC.Ӟߑ'=C.JCCC.Ӟߑ'DD D%'DD%_JDDD.Ӟ߂') '> ( (dD*D0E)f`[]_Do ]_D О^_`DDDDDD]_D^_`\? ) ) DDDE' +DE']%_>JDD_EE . + E .О )Y )E,E2Ff`[]%_Eq Ӟ]%_E О^_`E`*EEEEEE]%_E^_`\? *w * E+EEFEF`>IF!F.>=F.)CF5FFF<.Ӟ'>IF\!Fa.ОFnFd.Ӟ')JFx)??JFFF.Ӟ'FFF'FF_JFFF.Ӟ') * + +G +GNSf`[]_GHGNG]G[G]\? GNGbGrG +G{G]%_JG~ G `GGGGGGa_\\>GGG GG`JG)GGG(GG`JGGGH4HH4_>=0H +H%\H9H?HtHDHt_>=0HJHe\HyHHHH_>=0HH\HHI HI H`_>=0HHH .3'III7nII7I&``JI2*I<IAId=IFIdILa_``JI`) IiInI-IqIIwa_``JI* +IIJ IJIa_`I !a_+_>II!IׁI /(+JIII /?=0IJ\ J$J&JyJ/JJ5a_`JI !a_+_>IJZ!JeJ^ 0+(+JJnJ{Ju 0+?=0JJ\ JJK=JK=Ja_`J !a_+_>IJ!JJ 0(+JJK K 0̀?=0KK.\ KBKIKlKMKlKV`:'`:JKj'KqK}KKKKa_`]_JK.KKKKK`[Ka__]_JKKϠ_KKL>KL>K a__K__>=0LL/\LCLELLLL`[LO _L_a__ __>JLL 2LLMLML`]_>=LL 3!'JL.M MM@~M"M@M(a_`]_JM<.MEMQMMUMMZ`]_>=MrM 3'JM.MMMMMMa_`]_JM.MMN.MN.M`)],_JN #N 41N_N$._],_N3N:NQN?NQ]_JNENIg_ ,V , , - -K - - . .j . . /I / 0 1/ 1w 1 2/ 2 2 3^ 3 4 4e 4 5#NxN~Nf`[`]%_ NNNNN\? NNNNNN`JN*NNN'NN_JN+ 5 61 6e!NNT4f`[]_$O? ]_%O[ ]_2OfOfOOxOO~]_O]_\?$ 6% 7 Of'OOPOPf`[O]_O]_]!_>IP%PP 7]_>JP7PB<_Pg 7}Pn 7]_?JPP2_P 7}P 7)PPP +PP]%_JPP٠G_P.$P.%*QQ Q1(QQ1`JQQ!QQ.$( WQ+Q#.%( +Q5Q>Qj QFQj`JQI"QPQI.$ QcQ[.% ,QnQwQCQQ`JQ"QQ.$CQQ.%C0QQR?nQR?QK``JR"RR.$nR 9R0R(.%nR9 9-RDRJRRPR_>NRZRc +]%_RlRe.$ + IRzRR~ :v'JRRR :v')?JRRR.%.RRSRS_>NRR +]%_RR.% + ISSS ;('>NS&S+_S6S- ;(')CSESUSL ;('=Sa ;uSqSh ;(')JSS ;u?JSSS.$ 7J 8 8} 8 9S 9 :F : <3T7T=Xf`[]!_]_<TTU8TU8T]_U]_\? U$2U* <U1 <5U=UIV%UMV%UR`]_>NUcUo`UxUq.$( IUUU <^U = JUUU.%UU NVPV\`VeV^.$( IVqV{Vu >$vV~ >AJVVV.$V >$?JVV<_&VV.$]_&VVV.%VV >$yW >A]_7WWWW!WW&`_>NW7WC`WLWE.$( IWXWbW\ ?YWd ?pJWqWWx.$W ?Y ?JWWW.%WW ?YyW ?p 9WWX%WX%_>IWWW.$CJWXW.$?JX XX.%:X*X0XX5X_>IX;XGX?.%CJXSXbXZ.%?JXlXzXs.$ < = ?1 @, @ A8=XXZf`[`]%_@XX]%_AXX]_GXXY_YY_Y]_Y']_\?A A@YWYQ A + XCYdYiZZYqZZ`>IYzYY~.@'JY)?IY!YY.A(+>=Y.YY.A + @=Z.+AJZZ4Z#.@'?JZJ*EZ_ZeZ'ZmZ_JZpZZp.@') B< C C]HZZ[M`[]_KZ ]`OZZ[Z[Z]`\?K C ZM[[[K +[[K]%_J[![%Y_[B[:.K + D DmP[P[V\l`[`]%_S[ ]%`Y[[[[[[]%`\?S D [U[[\E[\E`>C[[[.S'>I\%\\\.S')_J\)?J\5*W\J\P\j'\X\j_J\[&\[\c\[.S')_ E E EZ\\^``\? \]7]I]t]R]t`"J]X]\(']]]^ ]^ `"J]]('^^^^p^^v^`"J^|^('v FN F F Gaf`[`r\?  cj(j`\>=0'e   K_\>=0'fQV\a`j K_\>=0w'gvv`# ]_\>=03='h'Dž' ]_\>=0'imrx``>=0'j"-3a_`\>=0JT'k؆݇MMa_`\>=0'l \>=0'm.08=`_>=0JT'n؈ډ575_>=0'o{`y`\>=0'p49EJ`Uy`f ]_\>=0v' G{ G G HJ H H I) Is I I J6 Jm J K s;f`[`],_\? u!$)`2 K_\>=0?I'ʌ΍E(ԍE`\>=0'JNSV _\>=0eo'   _\>=0'vSX^c`s ]_\>=0'wjj K_\>=0&0'x` _\>=0'ydirw` ]_\>=0'z"'-: ]_\>=0JT'{Ցڒ@@``>=0'|a_`\>=0'}DITZa_`\>=0q{'~n +n^__~`+\>=0*4' `+\>=0'di n\>=0w'f f`_>=0'' 7 _>=0'RW _d`oy` ]_`\>=0'05@E`Py`\>=0[e'vv` y` ]_\>=0-7'š9˚9`y` _+\>=0' K K L: Lz L M MM M M N3 Ny N O Oa O O P PR P Q Qo Qf`[]_]a_\?  Rvf`[]_]s_\?  RFLE]`],[],[\? S$ ǜ(Μ`J.(YCC``>=! S.J3: S SM S SHN f`[]`_X +],_ +],_\? TJ  ĝ`_J#. T. +& T`9+_( `J. +(Y#3e:e]_J=A,_T. ++i{]`J. + `J. + ОٞC`J. +C858K``J!)!. +n2 V@N(`. +(YEޟ`炟 W_ W: W_ W_W>= W W_ +. + W_9I!! W:(,$. +(Y>=0>H/d. +? Tu T U# Uh U U V" Vv V X$ i f`[]_X]_ԠԠ]_\? X ԟ( +`J  .(  "g+g0`_J:B:._[TL.( yya Y. X Y Y  `\? `J' /GM`JY]'b(b`J!%'ϥե`J' Y Z ZM Z ZåҨ`\? 6NQ`J]a'ÁT(T`J'āǨ`J' [ [I [ [ǁׁݯ`ʁj`7 \? ́ q qf`[)=],_0a__=r`\>=I_Q \I`YW \I(Yye \Ýxxf`[=],_#``a__=r`\>I"" \ꀇ \w \ځ(Y$! \& \>=05'?=S_[ \ځ^ \gd \yl ]ρՆf`[=],_z` {`a__=r`\>I0C;5 ^y= ]vF>=i_x ]遇{ ] ^ ^>=_ ]遇 ] ^ ^Ёf`[ =],_z`{`)a__=r`\>EBKM`TO ^W[Y _.v^ ^e _.fe _.W>Nvy_|{ ^} _.9N@` _.C" _w ^ _  ^ _y9 _w>=Հ ^ _܀ ^߆ _y9:= _ _y= ^ _ _:с$:f`[J=],_Qz`[{`fa__=r`\>(@ ay `wN`  ay `W7N"`)$ `W+ aaN:A`IC ayK aaNZa `rid `Wk aN!` ay aaN"`‡ aW aaNԊ#_ۀ ` a9N$_ ` b19N +%_ ` a9N#&_&% `' b[ 9N8<'_?> `@ a9I a b + b w>N_ b += b + b = b  c?I a b  c$w>N _ b = b ! c$=, c$2 c?I?UJC aK b +P b w>Nfh_j b +=u b +{ b = b  dc?I a b  b w>N_ b = b  b = b  d?I  a b + b w>N_ b +=) b +/ b =: b @ eE?IMcXQ aY b ^ b w>Ntv_x b = b  b = b  e?I a b  c$w>N΍_ b = b  c$= c$ f'?I  a b  b w>N(*_, b =7 b = b =H b N f?I[qf_ ag b l c$w>N_ b = b  c$= c$ g ?N(_ b NЎ)_ b =dc `e ao b +:=yx `z a b := ` a c$:= ` b1 ` `9:= ` b[ ɀ ` a9:Nۏ*`灏 `WN$+`,& ayNdu,`x a gD gZ(I h>N-_ gDE "+`$ hO,* hv/ hr6 h76 hWA>NIL._ON `P h9N`e +`ng ao iVs hI i(B?I i>I! h( hO>=܀ ` h〓 ` hO9:= ` hO iV:?= hO hOW>ACc)A>=~ i a ` hr9 hI iw>= hr hryBPImvq i>= ` h ` hO9:=̀ `5` hO5` hO kW k؀ ` hr9:= `5` hr5` hr ky k iV:B>=UT `V h\[ `] hr9:=ts `5`u hr5`u hrz ly l iV:B>E&(+`* hO20 lv5 hr< l=< lW>NOR._UT `V l9Nfr/`{t a| mR gDI m{>I! l( hO>=Ѐ ` l׀ ` hO9:=쀜 ` hO mR:?= hO hOW>N6B0`KD aL mRP gZIcsg npw>AC)A>N +` a ` hr9 gZI nw>= hr hryI hr lB?B>= n a ` hr9 gDI2;6 n>={z `| l ` hO9:= `5` hO5` hO pW p ` hr9:=ŀ `5` hr5` hr py p mR:>=*) `+ l10 `2 hr9:=ML `5`N hr5`N hrS q1y q1Y mR:B?=倡 ` ` ` hOy9:= ` hOy gD:= ` a%$ `,& hrW9:=76 `>8 hrWE gZ:=_ `偣 ` hOy a=_ ` hrW a aI h>J^?Ip"yt hO{ a hrw a>C a ` hO9 gD(>= hO hOWC a ` hr9 gZ(>= hr hryE+` hO tv hr t tW>N._怨 ` t9N/`  a to gDI"2& t(>ID!JH t(M hO>=ba `c tih `j hO9:=~} ` hO to:?= hO hOW>Nȩ0`݃ a to gZI u(>AC)A>N:? +`HA aJI `K hr9S gZIjsn u(>= hr hryI hr tB?B<>= u a ` hr9 gDI u>= ` t ` hO9:=0/ `5`1 hO5`1 hO5 w3W w3<; `= hr9:=XW `5`Y hr5`Y hr^ wy wd to:>= ` tĀ ` hr9:= `5` hr5` hr xKy xK to:B?=}_ ` hO hr a>=_ ` hO hr a \ \ ] ^ ` yԁ  (``ׁB (`:؁1`:$'2'3'4'5ف6`:$'7Ӡ'8ځ9`:$'7Ѡ':ہS;`:'<܁3=`M$'>a'?o'@݁*A`D$'>Q'?_'@&M&(,M4K`:\?׀I zQ &!?B3?9(`:\?׀ z !ddCt|K`:\? z d߁(s[`J"%р {$`.(( {$`ԅ(BRcazc(la`>Nv{`}`'D'E.I! {(+J {?NςF`7 +$= {7 {h.(׃z_='[''G.G {JRY {foAo(w[J}$'H.('y``:J |(IԑK`:`:>I" | `܄ |J ' |?I1:5 |R'pD>=0$2'Ā |'J?=0?I$'ĀZ |'KuL(u0K`:`>J<"ID }Ɓ `bT݄k }M(``:Jـ ~-( { {r |^ | | } ~ + ~SN]_][]A__X_+jX_+v(`\? F `J.(( O_\>@" + XP(+5+# XQ(+ł +<IC!LG.(+>@oid.P(+łdv=.P X>=. X=ˀ XQ.=. X=.R.= .( .(Wdifqft S_\>I!.(+>@.Q(+Ń=.Q >=. = P!.=,.4 =HB.R.=Z.(`Z.(W # _\>I/!>83 ~R(.JG?=S.(YS.(yIatje ~Q(+>@ ~.=. ~P>=׀ ~QP ~PI ~P(+>@&0 ~6.&;=D.PK ~Q>=ysn ~PQ ~Q= ~P ~Q+=̀ ~R+ +]%_J _. ~ : n `  O"(T]_][`\XP_+gXQ_+XR]_+\? tyU\>I.R(+J?=.R&._ XˆȌV]_][`]%_X'_+XR]_ ܊܋))R]_\>I .R((=.R+?  .3;`>I.'(+>I.R(+J*?@70*.R(w*:=C.'SM.R=`.R+Jt)?=.'.'PJ!.'(+ 3 }W],`[:`[(?($@(Y@(@@(@(j@(.A(cA(חA(eA( _B(vH7B(mB(@0B(ļB(4&k C(7yAC(؅W4vC(NgmC(=`XC(@xD(PKD(MD Xa`:\+  +6Y6M``> @"2- N^?: Nv7-HNW^Z`70Nrt=`7aN`7fNT` N I ̓v7 J ?NՉU`䀉 Nk7 I" v   v J y" y7 +?J+2W [6`:``>@ځ Wv耊 ځ(^ԊN\`  چ AN/6]`8 MF چ^X WAJgzun 5h7W| hy h7 IB +!%BB `>=0B#B-BA ''`?=BxB 'JBB (7a7(Mf`[Vb],_],_>=p'~ :J :9c(҅9f`[d],_],_>=( J!( %e(%`:\>=$" +l + +; +U +Y + + + +7 + +U +ƚ +N +< + + + + + +J +  2   ?  L   l n  v  !v # &3 (u ) + 5 6v <* AU Cn Dz F + G2 KY R' R R S XQ Y Z [ y ~x l e &> 0 c t & f߈@.g``) h `6i `+Ej ` SS\ak`ta\\>I>Ola\‰$\>=.i +==.j = =-=D.i N`'t'my  >=0'n) S!lo lk`!a`p\\>ITX>=lN``'t'q=.i `'t'rء4`>Ns`.j WI! w>N6?t`&6YA['t'qy[ `Ilyp w| zWh >= z  ??=.j z= . >=09?'u* qys~`J.j \>I>I.i (+J?=ڡI.h >=['7'v%-.i >=N['7'wow.i =.i +>=0'xX`J! +.i (+ [y [>__ozko[>чU{~U[[\>I (+= 1`:?I%" ],[>I1!%:5 ],[],`:=L Q0`:&ee ][?I `'3'_4 >=l[''|~  ],[+>=& [ ],[>=0$N'}I Y~#Y`>J*!P1[''H(+ t   : ] "X?ǝϝ '߈@$9`[^__=r$`%]`[^_a%`&`[^_K&`*a &A`c17?=?\? 7 Wdf`[`]%_g "[hX"_+n[\?g j "'"_J."hl',4`>NCG[I[''\."g=n."y_'' HhJ`'g' H o܅f`[]A_r "a[y11R=RCa[\?r  1FuWz" X'[J."rw +]%_Jn_."r 7 x zӆپW`|`7$}`+~`+\?  " 6`:#a`:6``>IEUI ~(+=0^dt q?J ~ q,6`:`a`:6``> N[[''N@],`:],`:'' F N(4`NAJ`NWd`Imwq `(+>J5<K S %?Nr`: ` 9I (+>I! (+B>J")`'t'G ?I^!rgb `h 9(+B>JМ`'t' ?J  # %?NLR<+`T I`"jd wq w7$>=0 7$'?I" (7 +! (+B>J5<`'t'Z ?I" 7 + (+B>N`I+5/ v7 +>= +70yW >=& +D?:7ay7 +yWF @%ugb `h 9`:b~N`:`:'9'N ` Eԑ`  (^  W>N`.  + Ak7 I>PB 0 wR +>Jkr  %??JT[`'t'x  v" v6`:a`:6`[`[>I (+>=0#'E ?JXj_ k {,6`:a`:6`[`[>I!`'g$''C >JT[m u ?N``'3' Î >Nߖ`: zII"" + M('B M('B3+ M('B>JH&HO `[?Jel~ ?J& `[ ..`J`'t'q3?I\> IR!eV}(+Jn?=ǡ}7=~I`'g'J,?NJ`'g$''q`>J`'g' `:>ICG`'g'g>Jy`:'9'?J'"+L],``:>N؝`7N,y`  (YI  v# >J6=`:'9'q ?N`:'E` \  \ \W >NОP`#ބ \W   \W  `= H`:'9'z H \ J H՟w֡+w]!``:>N,.=],`15`F=bQC,`V v>Ijpn v7>=  ;I v7>= 7W΂ y77 +7;= 7W 7;>=0(.1A JW^q |}+]!``:>Fǡ͡,` >I ,=01 ,?I!'% ,w7J18M ?Jcj} ϥF+F`8 ,`0",y``:>NAK`7IV""^Z va tn (| ( ܁(?>J`:'9' ?N`:'E`   # %# W( >N?HP`#YMK WO [ db Wf r `=} `:'9'Ƅ ܅ +J5< Kd:L+v:x,``:>Iv >I ԃv7>Jڜ`:'9'Ȁ ?I' ԃv7>NBG`RI ԃy7Nim`v7k~y f7N`7k f7 +J`:'9'ʃ Ƃ ??=0  ԓ7?Mbj`:z`:`:>J ^ kɨ/֨/`:`:>J`:'9'̀ " ' 4B/Q/[``:>N[$ N8>@],[@],[''сu 2I}! M(+J& M9`:?= M!],['$''''''ׁ 2I! M(+J&Ȃ M9`:?= M],[''؁ 2I! M(+J &  M9`:?J"'4?Yc``>J&['t'ࡓ W` "9+,`UG,~`qc,|`},`,`,`ա,k`,``>N;`9NW_`ga %yNtK`I >= + ` '3'ု  7 I [ m ~>= +& ` '3'‰Z k t 7y I [ m ~I"" + + W +w >J%+?I<"F@ vTN 7dJ[bm +t { ?J +K[[[`>Nѱy[؜[''䀱 I& `>=[''僲- 3 >=N[''惲j p J`'3'烲 `[>I`'g'逳7 ^>=J['7'ꀳn ^ ^ D?J[''뀳 ^ww``>J#ހ +`'t'# 8`'t'\i `|II``>J# +˜`'t' `'t'.; `NY_i``>Jy# +`'t' `'t' ` +3=``>JM#^U +o`'t' `'t'֡ ` ``>J%#6- N+G`'t'mz N`'t' N`Ҹݹ繩``>J# +#`'t'IV k`'t' `Ⱥ``>J# |+`'t'/< |Q`'t'y |```>N̺{`# +`'t' 3`'t'P] `J *W77WɻԼ缞[`>I!% `:=0 1 ?N.4K`6`'3'P IZd^ %=0kq1 ?J %qqa[[[>I"""Ԁ (+%怼 `% `%  `:>=0"15 ?JHO[''Na i vUUa[[K[\>I""" W(+%ŀ W`%׀ W`%耽 W`:>=01 W?='['7'2> WF `K i H z ; ' S @ k @ k  0 ^ 9 EEH``FD g"`:F] "`:Fu "`:FFGYFGYFg`:F@[\? #FŁF (++F֜`:' ' +F `:#G"G (++G3`:' ' GS `: FG^GeHAGmH`:>IGvGGz."(+BJG$G' G.g"?IGGG."(+B>JG$H' H."'H.g"'?JH%$' 'H_."'Hm."'Hz.g"' HHI>`H g"`:HHHHHHg`:\? - HHHI<AII<`:JI #II .g" `'$I<'I3.g"`: Z KKNC``L"[L$"`:+L/L/LKL:LKL@[\? B L/LPLWNAAL_NA`:>ILh!LsLl."(+BJL|L."?NL`:IL"L`'g'L."L֜`'g'L.">IM%MM."`>=M8 &M8MKM@."`:>=Mo Mw`:''aM."IM"!MM (+B!MM(+>=M MM曫M ??JNN."#N(N" (+B'N8 `: k >X=XCX`X\ :`:ÁXeXkX~XrX~Xx:`:\? Xk ā[D[J[`Ɓ[c :`:ȁ[l[r[[y[[:`:\?ƀ / [r \Ɂ\\]2`ˁ] K`:́]]]0]%]0]+K`:\?ˀ ] ΁^^^5f`[`\?  ?с^^_f``Ӂ_ `:ׁ_(_(_C_5_C_;`:\?Ӏ _(Ձ_H_O_dA_W_d`:J_]_]. ؁__`4``ځ_ `:ށ__```` `:\?ڀ x _܁```2A`%`2`:J`+`+. ߁`7`=``\? `y``A```:J`' 4 k``af`a [aaa3a%a3a+[\? aa7a>adAaFad`:JaL$ad'a\. ;aab `aababa[\? b b Ëbb"bAb*b`:Jb6bK' W#!b\bT.(+blby.'!`:G ó 7dd d`\? dDdDdAdLd`:JdR'" Ĉ Ŀg-g3j1``g ("`:g #"`hhhAh!hAh'(`:h3#`\? @ O hhFhThh[hhc``:Jhnh&hvho Ů`("hhi$hih``>Ih%hЀh `Jhhh `#"?Ji+ii%i(i'ii(s[`Ji8""%i>i8 Ƌ`i^iX.("(igia Ƌ`("Bivi.#"ii Ƌ`#"iiizii`Jiii.("z_jjj/Ajj/`:Jj$j/'Hj'.("' ņ d  i ǵ=Ch%`SYfdf\? Y kq&`~\?  e ʃЃ` \?  ȳ ΄ԅ%` K`##K`\?   *(.Q'`=COMO\? C x;(`)/979\? / )`\?  +*` + K`:))$K`:\? a  ʉ.4?+`! K`:#!=0=7K`:+\?! ! $,`&ۉ\?  M' h-`[`[]__]W__]__/\? * ."+[+ &/"+&&`- +0f7f=a__ˁK\\>N_m0`o./"+F[]['1'2.."*>=Ȁ 3ɜ_''z l_''{ lI! O(./"+>=0-3/.?  0 |3`[`[]'__3 ."+[[''4 2 4""+[<[''5 /"+`F   \? /G WWQ#eQn2]![\>N[.."3N5[.4"4E```'3'h ߃ ; J ;惉 ;W>N__''N  ;N &K_(_''N7 B@ ;WINVR ή(+>=i ή+I`'g'6 ή'Ԛ>= ήD_ ή + #?=![''7 < ήA  W/ 7 Vi(W+p`Jss`'3'7.."38  +`J`'g'8.."39 ׋Cء+`J`'g'9.."3: -R2R]_J55y_.); Vfm]_Jppy_.*= +``>Iɀ 6(+>= 6+I`'g'6 6'A>Nmo[++`q 6N:[['';.4"4 ѠzI!т ѻ(+>E```'3'h ѻ    W>=. Ѡ2`''NA ѻJ IX^\ Ѡ(a 6Jf)??J*?J`'g'<.."3 6> Ԏُd5dK``>F%[ ][''=.."3>I-31 3(6 J=)?JT*? inftf s][__\>N[.."3N(``''7 ӽ=΀ ӣ4֐_K_`>I (+>= + +I#'`'g'6@ E'u>= D_ .4"4?=Ü[''.."3  #xI! (`'3'7 ӽ>=+./"QL=./"5W75?@ kvx`_>I c(+>= c+I`'g'6 cݚ' >N79%++`; cNJR:[T['';s.4"4~| ˃zI! (+>E``œ`'3'h ⃒ 7 F 7胒 7W>= `''N 惓 7I"(& (+ cJ07_''J.."3P ??Jl+?J_''.."3 cA vv _ K_\>I a(+>= a+I `'g'6% a*'X>=q awD_ a.4"4?N[.."3N(``''7 =ܜ['' a lI! (`'3'7- >=;./"a\M./"5W75?B {}kk _ a__>N[.."3I (+>= +I眣`'g'> J_''?$ ?I59`'g'6R W'>N++_ N–`ɜ`'3'@郖 ٣zN:[[''.4"4$ ټI1=5 (+>=P[''Ah.4"4q ټw >E```'3'h Ȇ ` o `Ά `W>= ٣✣_''N  `I ٣( J_''0 5 ٣?=K[''R_ h I`'g'< >J_'' ?NK_ =[''  ߃ ۤ=$./"JE6./"5W75J[b ۤC pr-x-`_>I C(+>= C+I`'g'6 Cݚ' >N79%++`; CNJO`Q`'3'@qo ܫzN:[[''.4"4 IŃ (+J+?AE```'3'h >=, ܫ0`''N? H EITZX ܫ(] C>=n Ct ܫI T(>=[''B.4"4 >=[''̓  EB?I5=; E9; EW^@ TJC+??Nsw[y.."3NK__'' q CI`'g'B q C>=./"./"5W75?J$ ކD 27 <\>NIM[O.."3IYy]`'3'7t <w>=[''C <=[''C.4"4=./"./"5W75? Ϲ  Q Н  Ӆ F C %  H ߟ`[`[]0__R L#%L.2]![\? ?GD pJ Q_bj `v K`\>=0PK  s`\J0âPL ՠڠ ߠ\J0PM )) `_J0PN -/q:qB `N a`_J]0]cPP vD"`J'E  M S!F`[`[]'__V!0 ."[7[''W!/"+`h!\? /i!!!#1:2]![\>NMQ[S.."VE]fh`mo`q`'t'h   !  W>=[''G 炃   W !/ Y!(`J`'t'7.."VZ!"+U 3U`J66`'g'8P.."V[!YbCm`Jpp`'g'9.."V\!]_Jy_.)]!̈́݅]_Jy_.*_! +YY"``>J-4`'g'<K.."VQ 9`!^c5pxK``>F[][''=.."V>I ( J)?J*a! s][__\>I  !C>N8<[>.."V=PJ !4XXY_^K_`>=o['' P 悃 x=./"./"WW7W?b!//`_>J_''!.."V' c!4B0E0H _O K_\>N`d[f.."VNt{(`}`'3'7 =['' 瑀 u I!Ѓ (Ӝ`'t'7 >=./"./"WW7W?d!57=B=E _L a__>I^b`'g'<y.."V {J_''.."V {?NK_ 膀=ɜ[''.."V { =./"./"WW7WJ-4 e!BD J R`_>N_eK_g_''z.."V I`'g'B.."V >=./"./"WW7W?J f! \>I!&??%['t'79.."Vw`>=L[''C`.."V=m./"./"WW7W?  ^  x  W ] o : j!mHf`[]_m! ."]'[[n! I"+`y!''N5N;.]'[[FI`\?m n 'p!S[p(bp`Jeje.."m(q!t} `J.."m u!p" 'Ǎp[>Nԋ]'[[.."mN +[[''J.I"n,( o."*62 o."*NES0`YU o/"+Jmt[''K ! o/"+9/U oc r!u +]%_Jn_."uv!n``J#.I"n.."m .."m5 `w!!&k-k3a_\\>FGP_.=`_ a ,  = . u Qz$L`[`[]__}J M"^`&`WWgu^__$`z^_%`M^`&`\?}   ⁁ ƁH~ӡ+H``>I!.M" }J*?J'4@ MdN~fn`_>Iy!~.M" }J+?J ǃ"~̓"`_>I!.M" `}J+?J ` Z ; '-)N`[`[]'__ ."+[['' 4"+[ [''/"ԡ+` "^__$`( O"^_%`66aCaI^__$`WO^_%`\?  6/ fy(g+`J`'t'7.." +`J`'g'8.."%C+%`J`'g'9 .."*:_?_]_JBBy_.)csz]_J}}y_.*3+3``>I%ր _>N:[['';.4".O"$ _I1!=5 (+>NT[^__$`]."Enwy`~``'t'h  3 B 3 3W>N+__''N 󰃈 3I   _J)???J#*8=5JRK``>F_h[m][''=..">I #( >J)?J*͉Ҋ4؊4 s][__\>= 4/_K_`>=. 傊# x9DFN`_>IY%a] A_>Ns{:[}['';.4".O" A_I!ȁ h(+>Nߊ^__$`."E` ` `'t'h# h/- 뀇1 4 54 W>NGI+_K_''NZ hc Iq{u | ^ A_J_''.." ^???J+ً玂ꎂ _ K_\>N 5[.4"N$`&`'3'@?.O"I NX`:[b[''u } -I e(+>=[''A  - >N^__$`."AE ```'t'h* e>NBD+_F_''NU e^ Ijtn ̀u 6x >=  6B?I  W^ >=М[''R e B?= [''6.."< A =M./"sn_./"W7$$ _ a__>N5[.4"NΎ`՜`'3'@.O" nN:[[''$ , I7C; (+>=T[''Al t z n>N^__$`."E``Ü`'t'h 冏 o ~ o놏 oW>N+__''N ܆ oI#-' D. 1 nJ7>_''Q.."W ?=i[''R} ܀ nNK_ y=[''.." n y=./"./"W7J y)+O1O9`_>ID%LH _>N^c`e`'3'@~.O" _N5[.4"N:[[''  BI (+J+?N '^__$`)."E8AC`HJ`L`'t'hb nl p s ts W>N+__''N I ـ w _>I҆ (>=朣[''B  B>=*[''̓C L Njn[p.."NK__'' # w=[''B # w=./"./"W7J 8 ??J@+TY' ^'\>Nko[q.."I{`'3'7 w>=[''C =Ȝ[''C.4"=./" ./"W7? + V ) d  $ P "<P``"I r`:"Z Q"["oR"[+"S"[+"ІЇއ6`:`*T`)\?@ Rq| R ` n* "A`:J$'U.r'"kV"ˆk[>I!.R"(+J.R"?J .R".9.rB.W"P.X")"ptY"[>I!.S"(+J.S"?JW^.S"~$.r'Z.W".X")"ƊϋW"܋`Jߜ`'g'[.Q"" RX"%R`J((`'g'\D.Q""W^]h{j,6`:`T``[>NNj`:# ''`:N`:# ''`:N(`:# '('`:NЌ^[ٜ['$'_'`'a'b'c'x'd    4I`'g'e VJ V?N`m|`:o`:'9' V=0$'f ' " +,3`:`>N],[!],['g'L.Q"[ ;Ihnl W(+Jw+?J.#`: W"ɏِ<ʡ+<,3`:`>J `'g'h".Q"1 "AHiS[3`:`:>Nms@`u. SI! j(+J j*?J+"ϐߑX,3`: ,`]`>I,"60 C= wLE (^>=0\ms } (^?J.  "ϑՓ j" 3`:``>N^`.V"=+['7'kI ܁Q Nbh@],[j],['g' ܀ I (+J+?JԢ.#`: "l"%-3`:9``>NMT^`V.Y"=r['7'k ́ N@],[],['g' ̀ I (+J+?I!  (Yy9(+J+?=5],[  ( (YyWJע.#`: "r(03`:=``>IO"YS +/f` +/woh +"(^>=0 +/ +"(^?J.l" +" +/" +m +`J.W"":n':`J**.X"   w  J    5    + +  4"?Eko``"} r`" V"],`:ȁ"28r`FV],`:\>@%x[[''pp.V"`:[@%[''q.V"`  "Ǘ͗`:JМ`:'9'p.V""  `J`'t'q.V""$,Ky0K`J393.WEA;.V"9(^ā"PWx*\xa``:Jkqk.V"r }9Ł"|``:J.* "r`J.V"(YyƁ"٘isis],`],`:>N*],`:1`:F 6)`. b>=B> F.*L ;J[b  t  _ D Ɂ"ntyt]A`́" u"`́" "`:΁" H"`ҁ")) +u``:"H`\?̀ ́ ΂  FЁ".Bw +Kw]%`JNNb.u"g."p.H"  /Ӂ"|Pv`]%`ց" w"`ׁ""`:؁"x"`ف""`+߁" LL%w`3`:Ax`\?ր ׁ ؂   ہ"Q[n'cn`Jff."݁"sxNN`>I."(+BJ*?I.x"؃v."ׁ(^>Nޛ@`.w"֟j".".x"I!  (+>=3."> ȢNQ[y`c] ȄyIpzt Ȁ( .>= . .W?=.x" .J)??=."+= ."+J>*  Q #$*kz``#6 `#L `:#b r`:#KQ\f`y`:r`:\? F S ` Q#y`J.W.r(^#ƒ҃ԃ(``:J.* #r`J#{*{{``:>I&!1* {(>=0?PV {?Jip.r#'s'|],`],`:>N],`:.`:Fׄ(` >= .* 8;J    3 ]  #}]`#] ~"`:#t "`:# "`#~`:`:`\?    - #܆5 +5]%`J.~"$.".."#:DJ`>NTZ`\My.~"."."I ^>J .~"."?=0\ j  m#`]%`#b ~"`:#y "`:#"`#"`+#~`:`:`\?    ' #`>I ."W."(^w)".~"(^>=9."+JP*?Nlr`tM.~"."."I 쀇>=.".~"(^W=."+J*?N y`(" W3*."(^=?."JV ].~"e."I y(."= y yW?=." yJ)# ' `J." d 0 c(Q`a Yc*I"[IƜ[''+` ,` 2.ɾ@ ʢ@[``>N (`&  (`I"Ł ҁ ^ />J @ '+@ /?J@v@@ '/A AB AA1BA6`AAy`AJ(``>IAVA`AZ  (+>JAoAA  '?IA"AA  AA  wA '>JAAA  A ''?IB!B +B (+>IB"B!B B#  B0B, wB2 '>JBBBTBZ B_  Bf ''y??JBBB 'y0BCC|B+CC|C [C*[C3[`JCACA`'t'Cc ׁCm Cv 1CCD- CѢCD-Ca[`>JD DD$ i2D0D5DyDLDyDMK[\>=0DXD^1Dq 3D|D|DDDDK[[>ID!%DD `=0DD1D ?JDD 4DDEDED[[>=0DDE 5EEE|E:E|E;[[>=0EJEP&EpEp `:6EEE EEEE[[>=0EE/E J7IIJJJJ[`>NJJ!S[J#J6 NJOJU`JW`''NJf Jm*IJ}!JJ (+JJJ ?=J JJ =J[''2J Jء*J JJJ 8KEKJKK^KK_[Ku`\>NKKS[KK !=K[''2K !Kǡ*K !9NNPENPEN[N][[[[>NOfOl`NOwO~(`OBO "NCOOO "qO ">NOO[OáAO "N5`O "q5`O "qO "W "NOOK[OAO "N5`P "q5`P "qP #^W #^=P!P "YP" "ԅP) #<nJP6P= "Y:PHPMPP]PPb[Ps`:`>JPP`'g'P $P $;PPQ&PQ&P[P`:[>JPP[''NQ $~Q $<QQQQQ[JQQ=ccdc%d`>Nc\cc`ce`'t'Ncc`c`'t'Jccc %5Wcc %^h9>eef|e'f|e(a[\>K>Ie>eBeP %>=eaqey %?e[el[>?ffffffK[f[\>=fʚpf &gf &q@$w|a[`J`'' &A$||!L[,`[>@>CH ' +>NJSZ[''Nm ' +t 'B$ăL[`>@ۡC '{ۂJ`'t'h '{C$LQZ_K[`>Jj%wq ']![D + 0`[<2+_A5[_>NQV`X`'3'@zv (7zN:[['' (G (XIŃ ((+>=Ԝ[''A (G (X (7J (7?E!`&(`*`'3'h> (JH )L )O )PO )W>Nik[++_m_''N| ( )I )s( (7J )s?=[''R ( (7J (7E%rtg`[_`_>J *F%pp[[[>G%ɂ[[>H%[[>I"!!_0_@^`[JKRK *Q"J"ɂɃpރp^`[>N [ +3V"=,['7'J +DJ[b +DK"Ć^``>N[ +Y"N.4@]x[<]x[''b +J  +ρ(jyL"Q`3`:``>J ,6j" ,A ,NM#+[(s[/[`>J?F`'t'c ,m ,t ,N#+[[`:>Jɜ`:'3's -! -*O# + ![+[7r[`:>JEL`:'3'di -s - -P#!+![s[[`>JM - . . ^Q#n~r`:3`:`]`>J٢ .x .k .R# +7M>+`:`X+s[k``>I{% .`:>JP . .`: /I%쁋 .`>J .`$ .X. /H>NOV`:aX .Xk /HJ|&| .X /C`S#%+Ύ%`:[`:`:>= 01`:'9' 01J✣`:'9' 0 0( 01T#(8)+L]N+`:v^``:``:>N@` 0̟j" 0 0I섎 0(+J 0?N ` 0N'+y`3- 0yJ:A`] 0g 1On 1ns 0U# x+!x"3[`:>J.5`:'9'o 1V#{v|+v+`:ġ,r`,`:`:>I% 2>`:>I+# 2>`:('B>I:G> 2,('B>JX_ 2P>N`N(`ǀ 2,(^=ރ 2ȁ 2PE` + 3  2 3  3 W>=.' 2ȁ<4 2,= 3 @=SL 2ȁY 2PJy 2A>N`:U 2>`:N[[''ă 3J"S2 2,< 3F 2PIc%og 2>`>N[J 2>`JS 2, 4I 2P>=0@'X#yơ"@``:J 4Y#ǡ"3`:`:J 4Z#ٔڡ+`:4",r`H\a`@`:i]a`:^`:`:>I 5`(+= 5`X?Iȃ 5w(+= 5wޡY?I% 5N`:>J\B 5AL 5N`:U 5`^ 5w?N~`N`Fᖺ@`ˁ 5NX 5A>= 6' 5w 5AX 6A$ 6UH=92 6'F? 5`G 6U=T 6Aga 6Uy=yr 6' 5w 5AX 6AHJ 6'A[#˗̡ۛ+`:\a`@`:7]a`:^`:`:>N`N(` 7(^NƘ`=փ 7Ձ悘 7'C 8 7A>= 7Ձ 7) 8, 7'N~Q` 7 8AI" 87g(7Ʉ 7wͅ 8W>= 8 7 8WAI3)$ 8+7g(7>=wp 7Ձ} 7 7X 8 8WH= 8 8WB??=ペ 7Ձ 7 7 8@= 8 8W= 7Ձ& 7'3 86 7'=PI 7Ձ`V 7'Jiwp 7A\#+`:r`:\a`@`:]a`:^`:`:>N(6`@8 ;(^IJ\N ;b(>Jho[ ; ;* ;A?N(`΀ ;(^N`N`AC( ;* ;>NB?= ;܁̃ ;Aր ;X ; <'H= ;܁ + ;* <'( ;2 ;=B ;XO <'WZ ;b=vo ;܁| ;A ;X ;HJ ;A]#Ȟآɡ++`:%,r`5`:F``:>IV%bZ =`:>Nw}`M = =`: =Iʄ > J =?Ny` > W =`:(^J +`- =7 > > >cC =?IW%c[ =`>J|# =(S =I =` =T = =` =Ӄ =`:?N@HL]%`sRJ =X] =g =χ + I! ?N'J =?N@` ?N')J܀ = ? ?yւ =T^#"+CK`:]r`q a`'`:``:>NL]%` @?X @2 @cχ + I! @z'J @2?N$@`.& @z')N@L`:$aXQ @LY @Jeul @2 @ހ @ބyֆ @T_#+ΤL[[`:>J윣`:'9'Ҁ A A`#--+H-U`:c`ny`z`:`:>N`:`:'3'Ѐ A큤 ANӤt`:ܜ`:'3's A킥 BJ$+ B+ B$ B\  ` K e H  x H D n ȼ 3 Ɂ  ʒ  V " ! 7  r y  <   ~ t*    6   f   v ! "& # $V $ % % &? & & '] ' ( ) *H *} * * + + , , , -b - .M . / 0 1 2 4 4 5 7m : = @ Af A B2с& ߈@,SN "& `[^_ &ŏː^``&\? &][``4J;``4#&\ \,`[>=5I.$ʀV E*'Ï`SJ&.,#`S ']lwww`SJl&ll.,#`S$'BYxdxl``4JY&YY.,+1[ F#`4!' %h%%`J&.,h#` D E EW E E FD F'&ag``+\? )&`[>=.$ʀ G F G6,&Ӑّ`'`L2\? +.'`````],`J`&``.,)],`/'a2a;aAaAaA`Ja;&a;a;.,)`0'``````J`&``.,)` G G HB H3&#f`'`=\? +5'Ĩɨ`J&.,)`6'ox`Jx&xx.,)`7'NYfff`JY&YY.,)`8'͡ء`J&.,)`9'˩ԩݩ`J&.,)`:' + + +],`$J&.,)],`$;'-555`J-&--.,)` H I6 I I J Jb J J>&io`'`F\? +@'"""`4J&.,)`4A'Û`J&.,)`D' !1(1-M`]`4J!&!!.,+1[ L)]`4B'KV___`:JV&VV.,)`: K^ K K LW LG&`'`=U\? + +I']q]]]]`4J]&]].,)`4J'\X\a\k\k\k`J\a&\a\a.,)`S'_____]`4J_&__.,+1[)]`4K']]]]]`J]&]].,)`L'[[[[[`J[&[[.,)`M'^O^j^u^u^u],`LJ^j&^j^j.,)],`LN'[[[[[`J[&[[.,)`O'^^___],`$J^&^^.,)],`$P'^^^^^`J^&^^.,)`Q'\\\\\`4J\&\\.,)`4 L MO M N Ni N O' O O P< P +V& H`'`]\? +X'` ],[ ][`[+`$J&.,+1[ Q Q, Q;)`$Y'EEEEEE`EK``$JE&EE.,+1[ Q Q)`$Z'H1H1HPH9HPHE`[JH1&H1H1.,+1[ R>)[['AAAAAA``$JA&AA.,+1[ R)`$ Q Q R R R^&KQ`V`$`& [m&ēēp֓[\?` SQ ģ]b&ɒ֒`J)c&``>IZh^.`(+Jqx-`?J&&.````f&_(_s``>J"% T:`^6@.`QK T:`^`d&dl7zu7`>J'  .`7666g&NmrK[t TN[.` U Jƣ U&h&ݕ얁` K``$>N!K[#. Uz=;K.`V U\ UJhow Ui&`],[][`[+`$>NK[ VN[%5.`@ V?+L VR[ V"g V?Jry VYj&A`:J$'.`' St S T T T U\ U V Vn&˗ј`^`-u&Hp(H)[\? WGp&M\ap],[][`[+`$>N[.` Wǣ WJ Wr'RSSSS`JS&SS.,)` Wg W XMv&;A`'``y& `& `z& -[{&ӣ``+|&Ẹ``+}&gѣ],`S+~&],`$+&][``+&fpf``)\>Nu~f],[O&.y` I Ya(+>=.ѣ:`S}>=.ѣ3`S2) Ya[466Z7[`SJ==IW Y}y Y@z# YNN& Y@` +[6=`:'9'T&dd Y@` +&͜],`$>I.~(+>N0:[<&LL.y` N`œ`''2 ZG Z=Y.#if [(+:~`$3`$&ǁ [4Ξ[`$Jգ [][],`$~?J.~&)6][``>I<N@.(+>=.ڢF``N[&"".y` N3@][`[BMRb \O=u \t4`l[`>NK`: \=. \. \ \nxI- \t ~>N]bK`:'Nwzl`|&.y` 1[N` ]O=. ]. ] ]`n?N(/|][`[1=. ^8 ^8 ^EnxNע][`[S \O= ^4 `(l[`>N:?K`:AI ^=gZ.h ^. ^߅ ^nxOa[[˥[[>I`'g'K _s>NL[ [''ㅤ4 _s=E _sL[''z[ _=m['' _ _s1[J _>Jٚ _s1[N ][`["U2 \O=ME `34UUV`^[`>={n.| `. `Ʉ _[ `nxOa[[6[[>I`'g'K# a>N:@L[B[''㇦V a=g an[''z} a5=['' a51[ aJ a5>J1[ aNCK{][`[MXVh \O={ aր4`[`>NK`: b"W'G= b"  bB +, b"=K>.L b"q. b" ` b/ nxN][`[ƣњX \O= b4k`[`>=1$.2 c? MX c? ` cL +nxNx][`[W \O= c 4ƪ,`l[`>=. c +. c + c nxN:H][`[JUYk \O=~ dP +4`[`>=. d . d  _[ d nxN$2][`[4?ZU \O=vh e 4~~`[`>=. e_ ʣ. e_  ` el nx= .c``O.?Jip.&kz** +`],[][`[+`$>N K`:  f&@"<2 fA(+QG fA ~2XI f^('B= f^'?N[&.y` Nٯ[ߜ['' f̃ f^NPY[#[`'g' f̅ f['' f f3윣['' f f3[J g&}}``$>N"'K`:)1 gJ>EM[''N\&ll.y` s g&22`K``$>NK`:ȣ hA=ݜ[''2&.y`  hc hNJ ( hN&7FLT`j],[][`[+`$>NK`: hI!̂ i(+>= h0[ h= h i;?N(/[1['' +E&UU.y` \ i"b hJmt| i& ],``>Nʴ ^],`㜣^],`'' &.y` I/ j(+>J@1G``>Nit],`v jJ& j`S4``SJ j],``&ҵ۵`J)&##`>J.y&(1VGV`JJOJ.-z(+&[p ~],`SJ.ѣ}&`S>I.-z(+>J.?I!.ӣ{(+l>J.ӣ{?=?.ӣdft[''.-z*{J.ӣ{&зต븕``>I.y(-`>J +>J-&-4KY[''Is&.y` ``&``>I!.̣|(+l>J.̣|?N[K&.y` I!+% m(+>=w.̣.|J.̣|?=.̣& m``|J.̣|&A`:J$'.y''nnnnn`Jn&nn.,)`'Ĩɨ`J&.,)`'ll!lAl/lAl;s`S`Jl!&l!l!.,+1[ o<)`'ssttt][``Js&ss.,)][``'ox`Jx&xx.,)`'NYfff`JY&YY.,)`'rFrdrsrsrs][``Jrd&rdrd.,)][``'}}}}}}s```J}&}}.,+1[ q)`'ee"e/e/e/],`wJe"&e"e".,)],`w'H1H1HPH9HPHE`[JH1&H1H1.,+1[ q)['˩ԩݩ`J&.,)`'k:k?k\kJk\kVs`S`Jk?&k?k?.,+1[ r)`'nInRnXnXnX`JnR&nRnR.,)`'-555`J-&--.,)` Z [ f g h# h i k* kT k k l l mL n6 nr n o o o p? p p qj q r: r r sS s&#`'`&p `& (`:& `S& ],`$& `&T `*&ii~p{~``],[`*\? t t t  t.3`$5][5],[^ t#k uY(++k uY[o][#x uK(+1{[ uK][ i+&aa`}[\? +ƣ uКޜ['' u],['' u>`'g'V u& +!+`J$$.&fmAu`:J{$'.(''Ĩɨ`J&.,)`' `J&., )`'ox`Jx&xx.,)`'NYfff`JY&YY.,)`'˩ԩݩ`J&.,)`'-555`J-&--.,)` vp v v w& w w x xb x&!``ā&PpP7``],[\? 79 yA yD y"&U\Ad`:Jj$'".(''`J&.,)`'Ybq#qq`Jb&bb.,#)`'A`$J&.,A)`$'CLV$VV`JL&LL.,$)` yV y y zH z zŁ&I%`'`ȁ& `Ɂ& (`:ʁ&],`+ˁ&2],`$+́&J &`́&f `΁& `*&@N@NA0'@iA0@x`v@`@[\>=A .(A& |ȁ@ {@@ {)* @N+&A5A5B)ASBAb`vAn`Av[\>=A.(B |ȁA |AA |** A5+&B B C*B<CBK`vBW`B_[\>=B.(B }WȁBx }HBB }H*) B +Ё&#`J.(Ɇ'Cс&ֿ@@`J.(ɃR'pDҁ&@)@4@I@?@I`J@B@B.Ӂ&C4C?Cp +COCp`JCR#CR.&Cb.+`ԁ&CtCC~CC],`JCC.Ձ&CCCCC],`$JCC.&CCI(CIC[\> IDDD (+>=D].:Dg`=Dw.:D`$JD?ID"!%DD `%EE ],[>=E8.EB3`$&EEEwEq 4EEEE=[`$JEEE w][=E EE >=E.:E`$=FN FV&FqFq `NFF],[&FFF ],[NFF+],[&FF΀F @],[NFF],`F.`G GG (YWGG <(YEG!G*G,`G3G1 ЀG:G5 (YGD GBGD W>NGSGX[G^GZ G_ 9NGmGv[GG~Gx G NGG`GG'GH 5&HH d],[=HH oH ЇH% :EH7H@HB`HIHG HPHK <(YHZ HXHZ W>NHiHn[HtHp <Hu 9NHH[HHH HHH (YWH NHH`I I 'II% &I,I, ],[=ICI= oIFID WIMIH (YIW :=Ii.Ix3`I o&IIIAII`:JI$I',I.('ց'w-`J&.,-)`ׁ'`J&.,)`؁'Ĩɨ`J&.,)`ف'ox`Jx&xx.,)`ځ'!`SJ&.,!)`Sہ'BKb.bb`JK&KK.,.)`܁'/`J&.,/)`݁'NYfff`JY&YY.,)`ށ'09D0DD`J9&99.,0)`߁'0;A6AA`:J;&;;.,6)`:'+4C1CC`J4&44.,1)`' 2 `J &  .,2)`'3`J&.,3)`'-555`J-&--.,)`'"`J&.,")` } ~ ~G ~ ~  e  q  ^  k  l " }  +&4`& &5[ [''6 &nn``:>I% `>J  `>J-E&TM `&qx7K[A[`J0!'8&BQy9XyY[`$>I% `>J2u4 `>JOgmi &|``S>N[& ` N̈́[ޜ['': + I)!6- M(+>JEL`S''^ M?N;`v =[''2 +أ J &!e<-e5`[J@N^ &hpg=zg`[>N>[ XI!́ k(+>J k?NK`: + XAGW_ p'>=| 'VB'>= 'B'W>= '?B '#'@>=6 $E'p@ BMJZa &jqA7[`:>@؜`'g'B n؉N `: nA@"1- R'RDNJ 'C-[J`kg X7|x (^yH&C7[`>NK`: QJ d Q&SZDmn7[`>Iz%~ `:>J `:>NK`:ǣ J  &(4E243[][`[>I=FA X(+JO2V`[?N`d][`[fF`[NF[[''G XFٌ7[& ][>N `& `:=%" & 0[''N? XE nNYhH[j['': XF7[& a][>Nʍ`ӣ =  [''N X nJ(/ &7?{K{L[[JTTbv &&~~I``[>=0!$ o'%ƣЁ |'J&K][`[[>I ($ (+J1+?NDH[J[''J=^Z 4ffn`sK[`>=[''2  U bxJ  D F GC H K! L P S W X^ t x { : 8 N 1 8  O L(m( +33`:\>I?C`'g'M>=['7'N cJ?I"`'g'O7`'g'P>=o['7'Q cJ?I`'g'R>J+?I`'g'S>=['7'T cJ?=['7'U c C E c񃆁))V`)W`:'X)AY`:'Z)l[`:'\)]`:'^)_`:'`) a`:) b`:)a`:b`:+\? D Q  )Fc`)06DBD\? 6 )@d`) K`:)&,>3>9K`:\? , H)e`)Ȇ\?  )[af` +)nt~|~\? t Q   g*i"*[h*i 'j``)\? *?hu| @'kuu`*z$`J-`*S}`(`+`>J<. < J*#,l6<}`S(`+`>Jbx. *4mŅ4}`(`+`%>J-. ) *9DnPV}`m(`+`7>J|. S a*Ȇ;oӆ;}`(`+`.>J.! 0 *@KpW]}`t(`+`I>J. *ņχBqڇB}`(`+`@>J.( j7 x *GRr^d}`{(`+`Y>=0's!*чۈStS}`(`+`R>=0'u"*Xd>vq>w}`(`+`}>Nw`&.q m#!恈 {(+ {h+``J!X2 #*COx\b}`y(`+``>J.  )$*ˉ׊NyN}`(`+`i>J).4 xC %*SaCzpCv}`(`+`r>Nw`&.x #!遊 (+ h+`#`J &@7 &*HV8{e8k}`(`+`>Nw`&.y #!ށ (+ h+`$`Jp, '*=FPV}`m(`+`>J|. 1 ?  { 5 L O Z e  p**|`]` +*}`*]a` ,*k~`+`r/*:  `>*Ȏȏۏ(`\?/ Uh @*J ;JA`\?/ A*OO p],`\>Ȅ`Ձ ܀ (Y 偏 W>Nl`  9=. / hW" `=3+. /<75 hWEC `!=VN. /_ZX hWhf `"=yq. /}{ hW `/ (Yh O +1*$`J-`r8*=EUaUr],``,>I~% !`,>J¤@ !`, />J8AF !2*Zip`Js|s. /t3*|`J. /|u4*Ò}ђ`J. /}v5**{ +*`J t6*/7U(>U`JAQJA. /(:*Zmot``>= ..(6N`[. /̀ ˂hWN`[. / ˂hWN`[. /(# ˂hWN9<`[F>. /SNH ˂hWJ]tx ? ;*` K`\>=ˤ T..(6=. /  ThW a=,$. /94. ThWF@ a!=UM. /b]W ThWoi a"=~v. / ThW a<*ii`y`+],`>= ܤ .(6J &@&II@. /WQ h`\ ΂h`  8 f 6 c +B*aa`]` C*aa`B]a` D*IO`C`}G*  `@V*ffw|(`\?G ,h fX* Әw`@\?G Y*A A.],`\>Enwy`~ 倇 ˁ(Y  W>Nl`  9=. G hW͂ 8@:=. G⁙ hW 8!@:=. G + hW 8"@:=$. G-(& hW64 8@:GGc\W ˁ(Yh  +I*FOi$[i`J^-`}P*],``D>I!%*% `D>JHaX `D G>JӤY J* `J. GK*"*Q|8Q`J;D;. G|L*V^}l`Joxo. G}M*{`JN*ȜМ(ל`J. G(YR* ``>=) .;.(NNLO`YQ. Gfa[ hW9Ntw`y. G hW9N`. G hW9Nĝ`. Gـ hW9J 䂞 + r S* .$1$6`E K`\>=Rc F.u.(N=. G FhW S@:=. G FhẂ S!@:=. G䀞 FhW S"@:=. G  FhW S@:T*)7>C`Oy`+],`>=[ ar Áy .(NJX&. Gڀ Âhた ЂhM`@ t N ( g +Z*`]`@ [*`Z]a`@ \*ΠԨ`[`_*o  `n*GG(`\?_*C< 4h p*LL pv`\?_ Lq* ],`@\>E` +  ҁ(Y  W>N*,l`@2. 3 9=E=. _NIG hWWU A@=h`. _qlj hWzx A!@_Ϥ怢 ҁ(Yh  +a* +&7],`@`\>IC%LG O`\>Jlp O`\ _>Jq Oc*(D$4D`J7-`d*IXq_q`Jbkb. _te*v~|`J. _|uf*}`J. _}vg*ޥ{`J +h*&D(-D`J0@90. _(j*I\^c``@>=p (..(hN`[. _ (hWNҦ`[. _瀦 (hWJ Y k*%(-`> K`@\>=K\ .n.(h={. _ hW (@=. _ hWƁ (!@l*Чਗ稗`y`+],`@>=  + " ,.(hJ9Tp&wwn. _ h h` 1 ! [ +r*z '``}\? t*, -'i x'`u*#0| 'k00`v*} 'ƪ`w*1as{ 2'ss`z*x}k k1`(`K`:\>I!%Ȁ `>=0  ,'>=00AG T \ ,{*pux x1`(`K`:\>I"`'g' &  ['t' w `>=F. W a Ƃi z? $ _ c~*D^f/ E'`r`'*!]/]4(``~J??HU *ѵٶ` }`(``~>=,@ H #W 0Jd#rk 0(+  #  # 0`~*޶$`J-`* "{"`J!*u|```[J.  *ݽ( 7*'^  ' 'u "'2^7`I`+`[*+û+```[J.  !($ *0d  1' I'u "'ot``+`[*+/7<`P```Joo. y ( *ξ  ' 't "'׾``+`*@@``ɽ`J.  ( *@ @7@l  @ ' @"'t "'@@@l@E`@W`+`*ABBB +BB`B#`B3`>=0B?BE'*CCD "'CDC``*EEEEEE`E`E`JEE. E XEE(E g*EF,Fb  F' F't "'F6FbF;`FM`+`*GGHLGHLG`G`H`JHH. H( ]HBH;(HE l*HQH~H  HR' Hi't "'HHH`H`+`*J+J/JJ8JJ=`JQ`Ja`>=0JmJs'*KLL! "'L +L!L``*OOP;OP;O`OK`O`O\JPP. P P #P1P*(P4 2*P@P]P  PA' "'PhPPm`P}K`P`+\*QQR}RR}R`RK`R'`R7\JRFRF. RR *R^ 9RsRl(Rv H*RRR  R' "'RRR`RK`R`+\*TTUTUT`TK`T`TϽ\JTT. T @T OU U(U ^*UU3Us  U' "'U<UsUA`UQK`U^`+\*W"W'WW/WW4`WDK`WS`Wc\JWrWr. W| VW eWW(W t*WWX  W' "'WXW`WK`W`+\*YYZKYZKY`YK`Y`Y\>=0ZZ '*[[[ "'[[[`[K`\*]]^]^]`]K`]`]ӽ\J]]. ] 4] C^^(^ R*^^9^z  ^' "'^C^z^H`^XK`^e`+\*````!``&``6K``E``U\J`d`d. `o J`{ Y``(` h*```  `' "'`````K```+\*bbc,bc,b`bK`b`bٽ\>=0bb'*ddd "'ddd`dK`\*dde@ de@d[`~Jee`~''e< **eEe[e eceed[ej[`~Jeyey`~''e ̇e ̒*eef- ef-e[e[e[`~Jee`~''f f" f(   V -  ~ 0 5 : ä ď  ť  ƻ . D ȹ ɯ " 8 ˭ ] S'*f2fAi`r][\? }*fff(ff`*ffi fif`fy`f6`f`\> +Ng g`g.(=g+. g: ΖgA '{=g]. gl Υgq 'y{Iggg Ζwg Υ=0ggg Ζg Υ?Ngg`gׁg Υyg ΖIggg =0ggh ?Nh!h.`h7h0 δ(IhCh`hThG yhV hb ό>=0hqhw('?Ih"!hh (!hȆh (h ό>=i' δi0`''ĂiK δiS ihi^ Wij ό?=i|['7'.i δi Ζ = l /*ii`]`[ e*ii`]a`[ ѓ*iil`\? *j1j9j^(j@j^`JjCjC`'t'h.*jcjsjjujjz``[>=jj O.j.(Jjj`['u'N.j O*jjktjktj`k K`\>=kk' .k9.(=kF['7'2.kc Ձkj *kyk~l klk`ky`k ]`[k`\>Ik%kk ӄ`>=l . l fl ul# ӄ`l- әJl??=lW l` flg ull ӄlv ә ( ҭ > 9*ll`]` w*ll`]a` ԥ*llo:`],`\? *mmmD(m&mD`Jm)m)`'t'h.Á*mmn.mn.m`m K`\>=mФm m.m.(=n['7'2.n mn$ |ā*n3n8o8 n@o8nE`nPy`nc ]`nx`\>In%nn `>=n. n n n `n 1Jn?=o o o o o* 1 E ǁ*o=o[s o>'``` Ɂ*oooooo(``Joo֤oߤo =ʁ*oppappap) ],`[`Jp<p<pEpW מˁ*pfpnqqpqqp`p}`p(``>=pĤp p p !Jp#q +q !(+qq% q- qFqO qW qf !`́*qvqq$qq`Jq-``ρ*qqroqroq`qy`+],`[>=q 4qդq %q 4q.(Nrr6[r[''.rC %rJ 4JrTr[rd مс*rtrr rrr[`Jrr`''̀r ҁ*rrsP rsPr[s[`Jss`''΀sE YsK dӁ*sUsns svssw[s}[s[`Jss`''πs ʁs Ղs ԁ*o[o[` K`\J H T  v / ڠ % | Ձ*ssxz sޢ'``i ׁ*tMtUttfttk(``Jtvtvtt ؁*ttutut ],`[`Jttܤtt aف*uuvu$vu7`uC}`uV(``>=udux ȁu Ղu Ju#uu (+uu ȁu uu ȁu Ղv `ہ*vvv9$v+v9`Jv.-`i݁*v>vKwvRwvW`vcy`+],`[>=vo vuv v v.(Nvv6[v[''.v v Jvvw H߁*ww-ww w5www6[`JwDwD`''Ҁws ޿*w|ww www[w[`Jww`''Ӏw w '*wxxx xxxx[x[x#[`Jx2x2`''Ԁxg ߍxm ߘxs ߣ*ss` K`\J  9 ܠ ݇ ޕ c ? *x}x}p x~'``. *xxy%xy%x(``Jyyyy *y*y2yyJyyU ],``Jyhyhyqy $*yyzyzy`y}`y(``>=yz ዁z ᘂz Jz,#z:z3 (+zLzU ዁z] zvz ዁z ᘂz `*zzz$zz`Jz-`.*zz{Fz{Fz``>=zz .{.(J{{$`'t'N.{< *{K{U|{\|{a`{my`+],`>={y ?{{ 0{ ?{.(N{{6[{[''.{ 0{ ?J{|| *||3|y |;|y|<[`J|J|J`''׀|u *|~|| |||[|[`J||`''؀| d| o*|}}n }}n}[}[}[`J},},`''ـ}] Ձ}c }i c J  : 0 *}s}` }t'``@ *}}~}~}(``J}}~~ *~ ~(~~@~~K ],``J~^~^~g~y *~~~~`~}`~(``>=~~ | 扂 J#*# (+<E |M fo |w 扂 `*$`J-`@*66``>=ݤ ..(J `'t'N., *;ELQ`]y`+],`>=i 0o ! 0.(N6[[''. ! 0J * #i +i,[`J::`''܀e *n [[`J`''݀ U `*^ ^[[ [`J`''ހM ƁS тY T ; t + ! *c~9 d'`` *(``J + * n+n6 ],``JII +Rd *s{{{`}`(``>=Τ m z J&# (+& / m7 zP Y ma zp ``*$`J-`*``>=Ƥ ..(J`'t'N. *$.5:`Fy`+],`>=R *Xi p *z.(N6[[''.  *Jۥ + { +* +N N[`J!!`''J  *Si qr[x[`J`'' O Z *7 7[[[`J`''& , ˂2 ~ E 5 n %   *<Y2 ='``7 *(`` JʥӤ *II],`` J((1C *NVXkX~`}`(`` >= g t J# (+ g t-6 g> tM ` *]f$r`Ju-`7*``>= ..(Jܜ`'t'N. * `%y`+],`>=1 7H O Y.(Njq6[s[''. J l*5 5[` J` ''1 *:R Z[[a[` Jpp` '' @ K*0 0[[[` J윣` '' % + x ? & _  *5R3 6'``I *(``Jå&̤ *JJ ],``J%%&.@ *OWYlY`}`(``>= X e tJ# t(+' X e.(7 X? eN t`!*^g$s`Jv-`I#*``>= w..(Jݜ`'t'N. w$*`&y`+],`>=2 8I P Z.(Nkr6[t[''. J& ]&*6 6[`J`''2 '*;S [\[b[`Jqq`'' 1 <(*1 1[[[`J휣`'' & , i 0  P  x )*6j 7'``% ++*(``)J5 ,*~;~F ],``)JYY5bt -*`}`(``)>= I V eJ#,% e(+>6G IO Vh7q Iy V e`)/*$`J-`%0*(`Jל`'t'h.2*qq ``>=) .;.(0JHO`'t'N.g 3*vQQ`y`+],`>= I : I.(0N6[[''.% :, IJ6=5F 5*Vt |}[`)J`)'' 6*P P[[`)J  `)''E nK y7*Us {|[[[`)J`)'' ߁ Z !  A  D : +8*(+ '`` +:*ow(``8JD ;* ],``8JD #<*!)*=*P`\}`o(``8>=} J# (+եE F   `8>*/8P$DP`JG-`?*U](d`Jgg`'t'h.A*``>= ..(?Jߜ`'t'N. B*`(y`+],`>=4 :K {R \.(?Nmt6[v[''. { JD D*4 4[`8J`8''0 RE*9P XY[_[`8Jnn`8''  F*) )[[[`8J眣`8''   +$ 6 b I S (   { +G*``I*0 `[J*B !`[K*T "`[L*f `[N*R `O* `IѥNtpr*55DL`[V!`[`"`[j`[\>IU!%[Y `=0djx ?I!% `=0 ?I!% `=0 ?I!%܃ `=0 ?I&|~R `[J&R `[K&R `[L&ۥR `[ 5s*66!`[\? +&r+ k. k1 k4 kt*::vNv\? +Xx((((u*`@\? +ۥx&R ,@`[&R ,!@`[((w*zz5 5`[!`["`[`[\?I&̥R `[J&R `[K& +R `[L&')R3 `[ zx*I )I/`[7!`[?"`[G`[\?I J K L  R*0 0[[>= N& {`J)$Nn*``G>=O @:=O !@:=(O0. "@:=B7OJH @:JQhxxsN}NNNS*NUA]`:>Jf$ 'p.I't.!J'x."K'|.L'T*tWts``>N`[.IW dN`[.!JW !dN`[."KW "dN+.`[20.LW:4 dJAXwa ˂e i Em U*W`>Jĥx.IWj.!JWj."KWj.LWjV*y"s``>N69`[=;.IyE? eNSV`[ZX.!Jyb\ !eNps`[wu."Kyy "eN`[.Ly eJw Ԃ  P W* hs``>N-0`[42.Ih<6 (fNJM`[QO.!JhYS (!fNgj`[nl."Khvp ("fN`[.Lh (fJw = {  X* +s``>N!`[%#.I-' hN;>`[B@.!JJD !hNX[`[_]."Kga "hNux`[|z.L~ hJw    \Y*s``>N `.I N(,`0..!J82 !NDH`LJ."KTN "N`d`hf.Lpj Jw#  +W`# HW`# ”W`# ДW`Z*  's``>N9=`A?.IvJD NVZ`^\.!Jvga !Nsw`{y."Kv~ "N`.Lv J# הW`# 唃W`# OW`# W`[*08/C/Ns``>N`d`hf.Iwpj N|`.!Jw !N`."Kw "N`.LwĀ Jॢ# W`# W`# W`# V$W`\*\dfvfs``>N`.I^ PN`.!J^ P!N`."K^ހ P"N`.L^ PJ#+ e1W`#9 ?W`#G MW`#U [W`]*s``>N`.I( N`.!J(ۀ !N`."K( "N`  +.L( J1#E .KW`#S kYW`#a gW`#o uW`^*s``>N`!.I(߀ ނN`!.!J( ޗ!N `!."K( ޗ"N%)`!-+.L(60 ޠJ=R#f lW`#t 1zW`# oW`# W`_*`[`>N `[ h.IfN"%`[)' h+.!JfN9<`[@> hB."KfNPS`[WU hY.LfJ`ww   ( ]`*}\}`>N`[.I\kN`[  .!J\kN `[$"."K\kN69`[=;.L\kJH_xj n "r Nv za*  ```>N  `[ N,0 +`[=2 !NKO `[\Q "Njn `[{p N `[ N`[ !N`[؁ "N`[ N`[ +.IN`[.!JN+.`[0."KN>A`[C.L=o L +#wt L +wy   L +`[= i # i w   i `[= # w   `[= # w '  '  `[= L +# L + $ $ L +`[= i #  + i  I I i `[=# #+( - n3 n9 `[=A #IF K Q W `[J_vx L + i   p*u>u`>N`ION[N[N#[N'[=4/N:.I=FANL.!J=XSN^."K=jeNp.L= #ǀ #~997= # #~997= #' #~997=2 #N@<8 #~997JY&Ymhc` #ke #kj #ko #`b*k k0``> +I" %ڀ %ڃw7>=0%+ %ړ7'0?=QLNW.I=c^Ni.!J=upN{."K=N.LN`[N %څN`[ĥNЀ %ڈN`[N %ڈN`[N*$ %ڈ7J6MxX &҂\ '` '`d 'c*%/:9:Ds`O0``>I["e` (hsn (hw7>=0 (h7'0?=N.I=ͥN.!J=ߥN."K=N.LN + `[N (hN-0`[72ND>9 (h=VQNb\ ([=niNzt ([!=N (["=N ([N`[NɁ (hN`[N (h7Jx' )`+ )/ *3 *d*kuz`[`>Jx&R +`[.!J."K.Le*` ``[`>J!8xC.I&FFRP ,`[W."KZ.Lf*`[`>J˥x.I.!J&ܥR ,`[.Lg*$.3;`[`>JG^xi.Il.!Jo."K&rrR| --`[h*s``>N`[#.I - +.I -`[N"%`[#)'.!J1+ -!5.!J?9 -!`[NMP`[#TR."K\V -"`."Kjd -"`[Nx{`[#}.L -.L -`[Jx -΂ ./ . .i*  #.s``>NBE`[#IG.IwQK /U.I_Y /`[Nmp`[#tr.!Jw|v /!.!J /!`[N`[#."Kw /"."K /"`[N`[#.LwҀ /.L /`[Jx / 0$ 0 0j*JT X `>Nhk`[mrw.IN`[r.!JN`[r."KN`[Ǽr.LJw 1 1ӂ 1 2#k*9CM`>N]``[f(?h.IhNvy`[(?.!JhN’`[˜(?š."KhN¨«`[±(?³.LhJºѥw 2 2 3 3Kl*-7 E`>NUX`[Zrh(?j.IhNy|`[~rÌ(?Î.!JhNÝà`[ârð(?ò."KhN`[Ƽr(?.LhJw 3 4" 4a + 4 Q   i   _ (      #L % (3 +a + ,y - - / 1{ 2 3 5y*IJĸ|!``{* `|* !`}* "`~* `*'R `/*ŊŊŗŜ`ţ!`Ū"`ű`\>I5"!;9 6F(C.{!%JH 6F`=0SYg 6F?Io"!us 6U(}.!|!%ƄƂ 6U`=0ƍƓơ 6U?IƩ"!Ưƭ 6d(Ʒ."}!%ƾƼ 6d`=0 6d?I"! 6s(.~!% 6s`=0 6s?{&ť 6F`|&䥃 6U`}& 6d`~& ", 6s` Ŋ* g28`@!`H"`P`\?{#d 8hW`|#ǁ 8DžW`}#Ǟ 8ǢW`~#ǻ 8ǿW`  *XXɐ pɐv`~!`Ɇ"`Ɏ`\?{ 9| 9} 9~ 9 X*FMŅ VŅW[[>=e`&ek :Y`Jr~y*S"$S/``y>NJT#`fN=zq :ȂȀ :Ղ=Ȓȉ :ȚȘ :՗!=Ȫȡ :ȲȰ :՗"=ȹ :ʀ :ՠN`& :ꁺtq`J !0, ;95 ;B> ;KG ;*ɕɜɼAɤɼ`:Jɪ$ɼ 'ɭ.{'ɱ.!|'ɵ."}'ɹ.~'*>k>s``>Jzʏʣ`'t'Rʶ.{ʿʹ <䂘@˜`'t'R.!| J&`'t'$9.{B< >@N`'t'$a.!|jd >!@v`'t'$̉."}̒̌ >"@̞`'t'$̱.~̴̺ >@*DDs``>J͕̀ͩ`'t'%ͼ.{ŀͿ ?@ќ`'t'%.!| ?!@`'t'% ."} ?"@!`'t'%4.~=7 ?@*IZύW[ύds``>Jαƥڜ`'t'&.{ @:@`'t'&!.!|*$ @:!@6`'t'&O."}XR @:"@d`'t'&}.~φπ @:@*ϒϣyϤϭs``>J#`'t''<.{E? AW@Q`'t''j.!|sm AW!@`'t''И."}СЛ AW"@Э`'t''.~π AW@*W`>J6K_`'t'(u.{с`'t'(ї.!|ѣ`'t'(ѹ."}Ŝ`'t'(.~*19>B`>NLO`bTR.{97Nqt`҇yw.!|97NҖҙ`ҬҞҜ."}97NһҾ`.~97J C>k C~k Ck C*\d kp0``> +I|"ӆӁ D쀇Ӕӏ Dw7>=0Ӥӵӻ D7'0?=ܥ.{=.!|= ."}=.~N(+`2-83 D셸NHK`RM_YT DNor`ytԆԀ{ DNԖԙ`ԠԛԭԧԢ D7JԹΥ E F# Fr F*դլקնקտs`0``>I" Gz Gzw7>=0 Gz7'0?=;6A.{=MHS.!|=_Ze."}=qlw.~Nւօ`֌և֒֍ GzN֢֥`ֳֹ֧֮֬ Gz=ƥ׀ Gm@=ޥ Gm!@= Gm"@= Gm@N*-`4/A;6 GzNQT`[Vhb] Gz7Jt׉ה Hrט Hל Iנ I*WW``>N`& J`J'<G JK.!|N."}Q.~*ءةخس!``>N`&ť KK`J쥢.{ Kb."}.~*QYٷ^ٷc"``>Nps`&pu K`Jهٜ٧.{٪.!|٭ L +ٱ.~* gg``>N #`& %/ L`J7LW.{Z.!|]."}` L*ڸ)`J!.{(*!*9*09`J3!53.!|(*ۊۓۢ+ۙۢ`Jۜ!۞ۜ."}(* , `J!.~(*U]-fl)``>N}܀`#܂ N܊W`Jܖܫܶ Nܺ.!|ܽ."}.~*݁.!݁'*``>N8;`#= O)EW`JQfq.{t O@x."}{.~*</<+``>N`# OW`J !,.{/.!|2 O6.~*ކގ0ޗޝ,``>Nޮޱ`#޳ P}޻W`Jܥ.{.!|."} P*ߺz1z2`3``>N +#`NN+34`IEO=`W QIpf Q'=w QI Q'!=ࠂ QIఀ Q'"= QIЀ Q'N5` Qa9N6` Qa9N7` Qa9N)-`6/ Qa9=I@ QIZO Q4=ja QI{p Q4!=ዂ QIᜁ Q4"=ᬂ QIὁ Q4N8`Ճ Qa9N9` Qa9N:`  Qa9N;`# Qa9N03`?86.{: R!kEBC.{gG SuNUX`d][.!|_ RLkjgh.!|gl S Nz}`."} Rwk."}g S +N`.~ Rk.~g S =ǃ Qa T! :=܃ Qa T := Qa U:= Qa U:J+xH? QIVM QId[ QIri QI :/ : @ A/ BL C D GE J{ K# K Ls M Mj M N NW O O PU P V*;<``@* `[* !`[*R `*$= `&??82tp`*RRag`[o!`[\>Ix!%~|.`=0.?I!%.!`=0.!? X0 X? R*`[\? + Y + Y +***\? + (*//j>LjW`\? +\ca Yhf Y!* `[!`[\? Z Z *A`:J$'.'.!'*oWo%s`@`@>J2ITR.W\V Zʂ@da_.!Wic Zʗ!@d*W`@>J濥.Wj.!Wj*]y]s`@`@>J 7B@.yJD [炘@eOM.!yWQ [!@e*hs`@`@>Jĥ.h׀ \@f.!h \!@f*qq's`@`@>J4KVT.^X ]<@hca.!ke ]J.h ]f.!h ]f*@J\M`@>JVmxv.\k.!\k*~ ~ `@`@`@> N `[,! ^@N:> +`[K@ ^!@NY] `[j_ ^@Nx|`[ꉁ~ ^!@N`[.N`[.!= _# _w _d _d _`[= _# _σw _ _ _`[= _# _! _' _- _`[=5 _#=: _π? _=E _=K _`[JSjs _w _*>`>N`= .=.!N*-`F840 aP#97NUX`qc_[ aP#97J|솁 ak싂 a*SS`[`@>I!% b`=0" b?J*AJ bM.!*!`[`@>I!%ŀ c8`=0 c8?J +. c8*Xbeps`@`@>J}#. c҂@. c҂@`[#.!ˀ cҗ!@.!ـ cҗ!@`[*$. 1<s`@`@>JI`#tr.w|v dǂ@. dǂ@`[#.!w dǗ!@.!鹿 dǗ!@`[*99`@>Jr$.(r2.! ZL Z [K [ \j ] ] ^R ^ a bv c c d e f*59? EF([`>IR!%]V fg`=0fl$'@ fg?J& fg`* +A  +[}[([\>I!% f`>=0 'B?I=!%OA f`>=0^d$'C f?I"! f(+!% f`>=0$'D f?*zAE A],[],[>I% g][J g?Nͱ],[.[ g(YE` h* g(Y h* h*W>= g h*'# g( h*9:J29 g*)F )``>J`'g'G h h*rH r`],[(`\>I" iW&66 ['t'/ iW^9 iw`>=0GM.` iff iW?*>I >`y`(``>I"- j1#ie j@(+~ j1w jO"" j@ j1w j@ʁ j@w jO`>=0/ j1 j@ jO?I j@(+J!( jO?J29 j@ s  @ n ќ R Ԁ Ԯ ۩ l ] N H 9 * k  5 Wf fE fG f g h i- j k¡J+"a gzy߈@)KEXe LMNOPQRSTUVWX(ā+Y^\Ł+4Z^^\\Ɓ,M[`[`[^_K]_ǁ,\^`S`ȁ, +]^[Ɂ-^^\ʁ._^\ˁ/`^\́/a^[́/ob^[΁0c`[^]-_ρ0C:d`[^_K\Ё0Cae^\с0Tgf`[^]_g\ҁ1R^[`SY\Ӂ1`[^_K`ԁ1`[`[^_K_Ձ1|h^[S`ց1`[^__=r`ׁ2i`[`[^]_4]_؁2j`[`[^_]_;\ف2k`[^``]_SY;\ځ2l`[^]_;\ہ2m`[`[^]y_`]_܁3n`[^_݁3o`[`[^__ށ3@p`[`[`[^___߁3zq^`````SY\3r^`[```a__3fs^`[`[```a____3ޡt^`[`[`[```a______3qu^`[```a_^_3v^`[`[```a__^__3w^`[`[`[```a___^___3Ax^`````SY`3y^```a\\3z^````{a\t`3{^````{a`p\|`3}^````:\3_~^````][[[`[4ɠA`[` 4X]_+4*a]_` 4K<+`*!4}n+`*"4+`*#4+`*$4,+`*%4U][+&4u`+(4a```+)4^`\+:4""a]_`\>=.! +_YEa\'3'V|a\'3'a['3'=.ꜣ`'3' +..& u)  +4\jq]y_Jtt.,4wwa```>I.¦((+>=.4S`Y``>K>=;[''P.&\ vn[ul[>=. vȁ v2(N`ƪI! v>=. v```/.¦((??JX_.¦(.4|\>I"""."?4.\S. u.$>J?=.)"N27`>IK`O.¦)(+>=q.^`\'3'./)I! wƪ>Nۭ^`\퀭 wʑ\`.¦)=.411a3`+\J<A< wʝ`Q xF] x)??=zu wʡ.¦)/4[\> =.*"=.*#=.*$N&`K>=B y=O`''c.&o y[l[`>=. y} y2=.w3J+I؜`'3' y=>=.w3J+?Ig"k.#. J+?=.)$N@FK]`H]`''Z y=N]/[I%ς z]/[>= zJ z]/[I% z][>= zJa[=3RG z][N zJ>=e zJqe[w z= zJ\.¦).,G04>CFI _`>IV![.!=m.'8?I.#=.'8?I!/$.>JD)?=f[.j {'=v..=.)#J*14Ӹغ ]y_`>I!.!=.'8?I!.J)?=.) N][. {*=9* |Cg[4>>?p[`>=J.* =p..I!."=.)#?b.,J*24S`Y`\>I("!B,.%(+!dN.%˦>=.%j | }J?Iv!{.J?=. | }34w[>I"!.%(+!0.%˦>=.%t?=.w44UYU[>@! +.! =!.)!=>..54ZZVb[>Iko.#>=..?64A_A_[>I.>J+?I@.%(+>=@!.@9[%I@@.#>=A..??JA8AUA?.%u84AdAdAAjAAr`:[JA~0A~A(A y u v we x { { | } ~ ~c ~ O  ;5`[]s_?5**~:~Y]_\? m~s %=5`J) K u@5`[]_C5`D5$`E5J`F5F`G5XP]@_+H5XQ]@_+U5ԃԄ ]_ a_\9b`Ga\V`\>=.P.Q.HG ms D S d p |K5΄Ӆ``J.¦FC( L5 %^3^\>=<.H<.¦FKCFR5clv`Jy!z.¦FD(M5\>@.¦Rʅ=..¦FkEFS5 `(``J1!\>2.¦F@E(N5چ߆\>O5fkxtx\> : 7 V5Y`[`]_]_]_]_ Y5a`Z5`[5`\5`]5`7c5(Y^\d5M^[^5|I`_5X]@_+`5X]@_+a5YX]_+b5]/[+5Y^\^[\?c [d m^Y  f5T^\>=0&'u5Ta\\>=0'g5 7V@^\>=0FP'v5GVGa\\>=0'h5n|]y_J?_.i5;]_Jƨ_.j5`J!.I¦^\(k5Ő\ΐ`J*l5":.:`J1!2.¦rn5őΒ6ޒ6`>@!.¦rJ .¦_ .¦`o5`J!.I¦^[(p5Ē͓ݓ`J!.I¦^](q566`J&.I¦^(\y5;CT]/[>I]!ma.¦b(+Jv}.¦b?J.a[br5ӓܔ`J.¦_(+z5FKLWLr g]@_\>@ P¦G =̀ 衤.I¦^ZFNGO]@_Q.¦`=h.€| `= P+G= Q RHI߁ R(+>=.€ _>=.& RP€6 G{5QVe g]@_\>@ K¨.@!ꀖ P¦G ҖN(]@_7* Q¦HN`e]@_tg P¦GI m(+>=.‚ _>= mP‚ GI (+>=Y.m m`>= Q mH= PҀ Q€ HG|55m?mEa_\^b`ra\`]_>I.j>I (+= ɦ?Jf_ ?N0=g]_CU_.l t } =.& ]@_zI.¦_.¦`>=5A.Yc?JV] }5ry <]_][>N›g]@_& ]@_I5( P¦G< JK+?I\m` ᡨ¦R>= ᡩM>=. {Ic"!h.¦ou.¦r>=.¥?J+~5ŝåѝ g]_\>53ĥ 3$ g]_\>5SY<ťg<`>Ipt.j>J('?@.¦p۞J('5AFIL _\>IX!].¦q=0kq.ť?=.ȥ 5S`Y`+\>=  I!.¦q=0.ť?N6B`QI_ f Iw!{ O(+>=  OS= Ⴀ OY?=.ɥ 5$(w)(][>I26.j>@![O.¦b(+šObJkr.¦b?I!.¦q=0.ť?=.I.I¦^k¦\^Nܡ][.y=.˥J s5-8S=S][J@@.y5X_ahas ]y_`+][>I!.¦q=0.ť?=.I.I¦^kЦ]^=._. 5` (#( (+* `aJ7N>.¦ą5 _\>=.ȥ 5ͣҤ(ͥۤ(S`Y`\>=.ɥ Q ]5-2Х8\>@H.¦pHWNnw][y.¦a=.+a=.I.I¦^]g^=Ԁ t5{ϥ{a]_g\\>IZ^.¦o>=0q{('?I.¦rJ?N!.`+$.I¦^-Z=.I.I¦^Zk[^N٧g]@_.¦_C! (+>I%6) D K>=5]@_S `` Sl`` S¦FkDF= K =Ȃ LN]@_ P¦GI0# ¦S>=P.` {?=5]@_   ¦FDgF= >=  P¦G=-.I4-.I¦^78[g^ILP.¦r>=b.¥?5W¥W\>@.¦rI".j.¦bѥ§<>=.¦bҥ+W?=>J.d - k  o *   ` t 1 + h 5\b>`[]V_]_5ܫܬ>>Ya\a\\? %+ 85 D5bkx`J{"¦q!.¦o5[ť[`>I.¦o>J('?J:Gť5`e?ȥn?q _\>I}.¦rJ?I.¦n>=.I.I¦^k٦[^Ng]@_.¦_=>1 C +=P.IWP.I¦^Zv[g^I.¦r>=.¥?J?=.ϥ4:g]_`>=) ,. +5DIɥS[S`mY`\>I.¦rJ?=.ϥ4g]_`>= ̡ͥ 5 <˥)<\>I2!7.¦r>=I.ϥ4ZZ{g]_`>= YХ>@!.¦b(+Űΰ@.¦bѥ§< =.¦bҥ+W n c + 5AG`[]V_5Ya\a\\? ަ 8 D5 ȥ), _\>E8Wdg]@_f.¦_! (+  P¦G>=؁ ե_ 5 #ɥ#$S`6Y`\>EHgtg]@_v.¦_! U(+ Û UP¦G>=肳 Uե# 4 @5(-˥6\>I?!D.¦r>EVug]@_.¦_! (+ ހ P¦G>= ե ,>@!MA.¦b(+ŵAT@pd.¦bѥ§I.¦(+>=..K_?=YP.¦] G5lq@t@w _\>I"!.j.¦o>=.إ_ _J?= _C.ץ¦>=&.¦.H5EJRZS`mY`+\>I"!.j.¦o>=.إ#  J?I!.¦=0 .ť?=#.ɥ. 5 CFM.ץ¦>=kb.¦.H5w][>I"!.j.¦o>=.إ ک,=.I.I¦^k\^J+8s?NOV][^w@!s.ץ¦r~J Z5¥\>I.ץ¦>=.¦ I=.+?=¥ g A 6( '`6 `:6 M`:6//`:*M`:+\? ~ 4f||(]`>=0$'' 6.4``m6 `:6ccx~`:\? U c6A`:J$'.¦' ~ 7#2`[`Á7p\>=0'  ,ā7~h`[`ǁ7]/`c`+ȁ7s]/`c`*ʁ7Ú˛ћ`[a]_]_>N]/_ a_=#4''`>K>=G@ \Q ݀Ti[pl[s`>= f oJ ˁ7 `[a]_]_>N6=]/_Ca_=U4gg`>K>=  ҀT[l[`>= [ dJ ́7i`[a]_]_>K>N]_ ǀI% ]_>J4; ]_IP%[T ][>Jb_ >Je_& _[S[&Y`>N>Eu]/_Ka_Njv`} I! (+>=׃  S& YY>=QJ e l YJ ́7ڥ4K4`[K]_+]_>J +b_* ΁7S+`[3S`FY`+]_>=Y ao I{!>N`ʪ 灨 I! + ?(+>= %?3 ?S=O h\ ?Y??Jd_ 灩 ρ7֬ޮ`[t`{ a]_+]_>N.5]/_;a_=QW 4aa`>K>=z +5a]_ # (++ ]_T[l[`>= + ΄ J +с71HO`[d]]_y`*a_\+]],_>Nȳ]/],_էa],_N],_N3=`NrS[NY`Oa[[`9[[`>=  yI!˄ (+>I!ꂵ ^(+>FK_ >I'!1+ r (+>=[4`>= ^ r ??= +I" ($ P>=C< R  &\\ + +`V>=   = & + +`I"䅷 (! P>= +  ̇ V?K>Fٸu]_ :>N0` = g[4  AK_`>=" +" yI9!D= (+>=a[ b +i  :I| (>=  U?>I"! ^(+!   (+>=d[4pp`>= ^  ?I"υ (! P>=  + ̇ V?bL =( 1( WICQG (>Jal],_:y`?= ._ [l[m`>I^"lb (t P>J],_  +>=  =  +J ҁ7AACH-ACH`[A]]_]_>NAA]_A_NBBa_`4BBB^BK_`>IB"!B1B' ҁ˦=BHB> tBQ !?NBhBpba[[`4BrBrBBsS[Bz[`>IB!BB ҁ˦=BB jB &BB `?FBBBu]_B >=CB g[C bC pJC-C>C4 uӁ7FFGBFGB`[F, ]_F?a_][][>NF\Fe +]%_FpFg + JF~F4FFG=]`>IF!FF Б'JF*?NFF][FفF FF Ђ')IF%FF R][JG GG R][g`G?JG+)Ձ7GGGGGGp[`JG)ց7K~KOKOKa]`][>NKK]/[Ķa[NK[=L LL`4M M OTM``>CM$M+ >NMO]`K>=Mo M~Mx FM[MS[MY`>=N!NA fNM *NT 5JNkIN%NN ]`>=NN ]`g[&NN a`][bN܁N f§VJN?=O &OO `=O>O3 f+T=OhO[ )JOtO{ fׁ7XKXUXgX\X`[Xia_K]_Xb`+]_؁7_t_~_i___b`_a`S`+]_ف7dddvddda][]_ځ7f,f6f@f>f@]y_ہ7hhhhhh`{h a]_+]_ d  | i  K  G x ܁7i@iFk``mށ7i `:߁7i t`{7iij.jj.j`:j$t`{+\?ހ ߁ i7j3j:kAjBk`:>NjRjY`:'Ijs!jjw.t(+=j $j'j.t?Ij!jj.(+B=j $jj 'j.?Jjj 7p0p?I`[`7rrsss`[]_Jss +_7|u|}|i||`[]_J||_7}C}Q}Wu}W}W]_78=ZtEZS K]_+\70j 0S`$Y`+\73<GGG` - } 0 _,+/`[`]_,f u]/_sa_\? ,t K]_+\,NjNS`Y`+\>= < <I !.uѥ§<=0'1('?Nht`{ < HI! (+>= <ҥ삃 S= H Y?=).8 I!.uѥ§<=0('?=.uҥ #W,ssS`0Y`\>=IB.u] d Y  { ,x~`[]_\? ,>t> K]_+\>I!.uѥ§<=0('?=*#.u4 RT,CHV^S`pY`\>=.u ʁ V 5 +,`[`[` +,` ,` ,( ` ,N +`7,w `, ` +, `ק +k ,` ,1`QG kS ,u` ,][[+,S ]/_, M`, `, `,,g1>]/_[^_]_m`\? »  #ނ (+` -, + +i$1]/_>`^^`S`\? e tw Á# Á(+`  +.,Ȍȍjvj]/_^[\?  +Y ,ox~`J.§8!,`J!.M +(",ǍЍݍ`J!.M (#,33`J.M($,7@oPo`JSZT.M(],t^_]_>@.!J&.^_]_,Ύێۥ`J., KK^`S`>@%.#%1J8&8?.^`S` ,Pbv^[>@.$J&.^[%,2;L`>@Y."YeJl!|s.ۥ§(+', _]_>J.§]__.§ Ǐ(,!``>I3!8.#JF)?JWd^.§``{.§ S),11`]_>@".".%ݑN`.I%끒 Ȥa``[>J&)#.§[``[ Ȥa``[uj uS| uY]_>@% Ȥa`[J&.§[`& Ȥa`[! uS]_*,6>P[>@!a."`mJt{.§[.§ e ğ A Ń - ` q W ɝ /,ca `[`]_2,|!`3,a"`4,L#`5,$`6, %`77,YI`b28, `9,&[+a,bbi\?8{ bb,']_\>=.ҥ TW8 c,**k(;k>K_J`\>=W.)a ˮJ8 ˹ *d,pp*S[Y`+\>=.  Y8 pe,AA}KN}QK_\? +_ci wu"<,ѥ`J.I§7(2=,ž+՞`J.I§7(3>,6,6`J.I§7v!3?,:Ch-Nh`JQXQ.I§7([4@,lu.`J.I§7^5A,/`J.I§7(6F,͟ҠL0ݠL6]/[\>@.,§> +=.I47=-.&€B d9[,Q[igbi`[oa_K]_b`+]_>N1`I! ֥>=  ]__ I*!6. (+>=  肢 ??J8?._Z Ё] GG,ttf`[a_K]_b`]_>N]/_ a_=..,__I Q ⁣T NJcj \,yib`a[S`+]_>Nţ]/_ҧa_I! г§8>= Ј5 ЈE> г§8IS!\W Е(+=e Еysl г§8`[ Е??=.-__ г Ј ЕNJ г],-v-$a[]_>N?F]/_La_I^!ctm ڝ§8{>=  ڝ§8[ ?=..__ ڀ NJ# ^,2@.ѥ§<=.I37I,Ϧԧ/3/\>@.+§= =.I27B,4CJ`>@W./§AW`Jg&gn.&§9`C,4]/[>@.-§?J&.&§9]/[J, ) K_\>@!1..§@0<=i.Ir57=.&€ 9K,K5KS`\>@!..§@ڨ=.I67=-.&€B `9L,PU6^fS`xY`\>=.5  KM,QV7bk6]/[\>@!..§@@ %.§@=.IÀ %I§77=.&뀪 %&§99N, (][[\>@VH? մ§(+ū?]Idh.,§>>= մ&.&§9][[=.&€ մ9>I.-§?>N6]/[.4§CI!ˁ B.§@>=끬 B մNJ ?='.74 BM?@R..§@R]=.§84`>=Z. մO,8][[\>I0>4 (+JG?ISW.,§>>N9][[&.&§9][[=.&€ 9I!ꁮ V(+>N F][[ C)!E70 צ§(+>=Z צjc צ§= צ V?>I.-§?>N6]/[.4§CI! ".§@>=Ձ "8 OJ?=.7$ "M?@B..§@BM=V b.:t Q=.§84`>=Z. P, +; + +][[>@!..§@N'][[&.&§9][[=.&+9J.: 0QQ,S:0SA][[][[>Nbg<][[+N'][[ ٘C! (+>N̳][[ۂ ¢§= ¢ ٱ= ٱ =* ƒ4 JDK ٱR,MY=lt6][c]/[\>@! ڀ.§@@!% s]/[= ڀ2HK>=IB sg[4NNOK[`>@ng ڀ+§=g=;4 ڀ3I= ڀ Tb4;S[Y[+`>@큸 ڀ+§== + ڀ ^&'' f`VD[Kl[N`>=@4RR`>=f_ ڀu ƒx VS,'3H>CHL6]/[\c]/[\>@xq K,§>qCÀ >-§?>= >瀻 >4§CI + >.§@>N/9][[B; K;P=c\ K7p >M=Z K ܶ>N̼][[&߁ K&§9][[= K0 >F=" >84 OT,MR[h K]_\>@!}..§@|I% ݑ]_>I% ݑ]_]/_>=ҧS ݑ]/_.>=R ݑ]_.>NU_][[a.;P={.)& ݑ_J=Z. &U,ȾͿ߿ K_\>@!..§@@!% ޒ]_#N;E][[G.;P=_.)i ޒJ=uZ. V,@@S`Y`+\>@!..§@N@@][[@.;P=@4.6@> 5@E AL=@VZ.@r eW,@@Cҥ@C@ K]_\>@!@..§@@@IC7%CAC; ]_>=CW.?Cd ]_XJCr?=C.2H=CC.§84CCC`>=C.&CC _UX,CCE?CED K]_\>ID%DD ]/_>ID6D@D: ]/_/§A>=D.2H=DD.§84DDE`>=DSD ]/_.>=E"SE3 ]/_.JEO?=ERE .Y,EEFEFES[EY`\>@!F..§@FF$=F,.2H=FMFG.§84F_F_F`>=Fj.Fy F "VZ,GG_@G2_G;6]/[GS][[\>CGd)A> @GG .§@GGNGGA`GG /§AIGGсG (+>IGG ->NH H`HH §B=HKH6H/ ᝜§8HjH_ SH|Hq Y?JH?CIx!III §(+>NII][[I =I II §=J J +=J+ZJA JI NJrJ{][[J} NJJ[JJ &§9NLyLB`L -NLLC[L IM""M -MÃM 䎢!M܃M 䎢$> +NMN`N N 䎝§IN"N -!N9N3N, ᝜§8DNI :>NNN`NN §B=NNʀN ᝜§8NN SOO YJO'?NOGE`IOX!O]OlOu :>=O OŪO :?OPtPyFa\PV\>@!QcQZ 䎢!QYQo@!QQ 䎢"QQNQG[K>=Q +QQ 䎢*R[Rl[R`>IR-"R1 -R=RURNRG §BSR\ >=Rp RR §B>=R RԪR R  =S )JS%ISC%SVSG +][>ISo"%SSs +][]/[SS +]/[.§@>ISSS +]/[/§A>=S TT +]/[§B=T* )?JT?NUsUH]/[U =U UU +][g[4UUUUp[]/[JUU n =U *?OV V%Ia\V8W!\>K>=VY VyVp 䎢V 'V[Vl[V`>=V V֪V M V X =V )OW,W1a\W<Y\>K>NWhWs`W|Wu §BIW"WW 䎢W (WփW 䎢%>=W XX 䎂X$ )=X? *?Xs[Xzl[X}`>IXXXXX §BSX i >=X XX §B>=Y Y)Y4 i Y7 t =YU )IYYY 䎢$>=YY g IY!Y ->IYZ Z 䎢!>=Z;Z( +?>IZfZsZj 䎢">=ZZ ?IZ![Z (+=[[ ?I[%[Ɇ[ ][>N[[J][&[[ ][N\\]/[\\ 䎀I\%\\  ]/[>I\\\  ]/[.§@>=\ ]] 8 ;P=]9]2 8 7]F  ]/[M=]b ]k  ]/[B]>=]S]  ]/[] 8 >=^R^  ^( 8 J^G??N^o^v]/[^^x 䎀=^ ^^ _;PI^!^ >=^^ _)^ J>N_'_2`&_'_4 `=_Y_R _5_i K=_ _ __,__c__c__`{_ a]_+]_>I` +`..§@J``&b_.?N`N`U]/_`[a_N`sp`I`~`` l(+>=` `` \4``a+`>=`΂` `'Ka \V>NaFaK`aR=aa laram p]_a l=a aa \4aabG`>K>=aւa aa p]_a lTb[bl[b +`>=b b b/ :b2 EV=bY.g[4b^b^bba_`>Iblbvbp ևX>=bb ց=bb b U?b4bbcGbl[b[`>Ibbb ևX>=c c ց=c$c c3 !&c6c6 +`V?[JcNcU ̞ * q ͷ D Ψ Ϸ k ѥ  ҷ A Ӎ @ Ԣ  Ք x S  q r  4 "f-L`h-B ^\i-b`f+k-jj}^\\?h j l-pv Mv(`o4N^^\\rx\? r43OO^^\\>I![''Pȡ(+>Js?I"!9[''Q1(+!iL[''Ra(+>NS[[''TΡNP[蜣[''UN,V^\OCCla[`STp[`>=aN}^\ @= @+= ?NٕW[[''X U=3[''Y_ Āi Jv4}}a\`>@ @(+Ŗ== @ =[''Z   ! +  !I*!O.[''[G(+>J`gt?Jۧus4 \'-a\\>O??la`O`>=Z=xp ?==['7']ơ t4^a\\>O..la`>o`>=I=g_ ?=|=['7'_ u4Қޛ@`@a\\>=-3 &v4:OaO(aga\\>=yo t K j  O y.`[`|.[1[~.\? . N \? ,~.͎IJَ`[]y_=5[5i_+.ǒ bؒ `[u]_]y_>Nڐ]&_& +_i)]&_= g[4mK_`>=7, Ⓙ< *J=UJ cIb4xxyS[Y[`>= ͥ & `K=΁ cIJ 7.IQdc`[x]]_]y_>N]&_& +_i)]&_N֔`Na_`43K_`>I! 7A>=ၕ 7 JI b by(= 7cI??N=Eba[[`4GGHS[O[`>I^!nc 7A>= 7ͥ <& D`KI b by(=ˁ 7cI??F×ߗu]_ >= b삗 bW= g[ rb I`jd b(=p 7wT?J 77."e"`[]_]y_>Jө_4]_J _ .xo`[|`{a`f_+]y_>Np`Nf`N]_Nv|`$9Oga\\>= {+4N_I! -(+>K>=  + -5` [5` [& W 5[<l[?`>=YN kb Se \ Js?= k Oha\˟I\>@ゞ O(+Şݞ= O 4Bp``>=7. =P ka +_i)Y4`>= {2=և T4N`>=  O= O+==7 {i3V4bbl`>@~x O(+ŠxNj`{ {j-=ą {2= O㪊 y 4``>= O+=8& =QH 4]/`>I! O(+= O?= O+JJ k.dlk`[6]y[la]_;][]y_>JѪ_[_DQ. 1wm?w`[`[J6]y_]y_J[_-__p.ͪ`J*.n Ya]_g\+Ya]_g\+]y_>J}_.CY.5KQWa_\xb`+a\+`+]_.ʸԹٹa_`]y_>J_..HRX`[[a__]y_>Js~__.v.%Co0Cf`[=a_]_]y_>Ni]_Ng]_OYa\A\>Na_\с@"%]&[%]V[8NU_p]_&U&la`]_Na``\ͥ¨=.4Aw_`>Nq]_K>=@ @@܀@@+[@2l[@5`>=@O@D@XP @[[ +J@iI@%@@ ]_>=@@Z=A@@ ]_g\@@b@vA(A]>=AWAL&A[A[ _bAAAwIAA.>=AA _YB!4B2B2Be`>=BPBCi)>=BB +_YB!T4BBC`>=CBZV4C0C0Cc`>=CNCA]4CyCyC][JCCCi)JCCɁC.GeGoLrG}Lf`[Ga_]y_]y_>NG]_NGg]_OGGYa\GJ\>@"%HH ]&[%HCH8]V[H H`NH}Hp]_&H}&HH`]_=H.H.4HHJH_`>NHs]y_K>=I II II'[I.l[I1`>=IKI@IT QIW \JIeII!II (+>=II.Z=IÍII vII.]?bJ5J+ͥ¨J~JswIJJ.>=JJ _YJD4KKKD`>=K/K".i)>=KpK +_YKDT4KKK`>=KK.ZV4LLLB`>=L-L .]4LXLXLs][JL^LkL^.i)JLLL.RRS4RS4Rb`Ra[S`+]y_>JRS_.S" S+ .VVWVW`[Va_]_]y_>JVV__.W  A.YYZCYZCY t]_][>JYZZ Y .g[4Z!Z!Z>Z"p[][JZ(Z7Z( w.\\]:\]:`[\ u]__]y_>J]],] g5..`2`<d`Bd`E a___]_>N`v`}]/_`a_N``v`*N`K_N`g][=`6`.4aab8a +_`>Iaa#>=a<_4aIaIaf_JaOaVaO ˀaW(a^m4ahahaakq_`>=a(aaa6a >=a(am=b)bbRbK §V4brbrdY`>Ib!b>K>=0cc\c[cl[c`>=cԥc cĆc>=d2d+ d<(T)Jd}d .gKgUizg\iz`[g_ _goa___]_>Ngg]/_ga_NggK_grNgg][=hh.4h$h$hh'_`>=h<_4hIhIhf_JhOhVhOhWȅh^4hhhhhhkq_`>=hȆhhhhbhh§V4iiiE`>=i*i#i4T)Jiiip.kknknk`:']`:>Nkk]/`:ka`:Nll `lNl9g][NlPlV`)=lblv.4l}l}mpl_`>Il!l>=lllq?=l*K>=lll"m[ml[m`>=m'mFׁmTm\m_b4m{m{mm|l[`>=mmmV4mmm`>=mmmӂmAT)Jnn.pprEnprEp$ `]`>Np@pGu]/`pMa`Npug][=p p.4ppqp_`>=pæ`4ppp`Jpp߃p@(p4ppqkpw``>Iqq >=q%q5 qC)?qmq qbqq§V4qqr`>=qq*T)Jr4r;.ssususa_\][>Nssu]/[sʧa[Nsg][=st.4t"t"tt%_`>=t[4ttt\Jtttt4ttttp[`>t¦ttbuu ɡ§V4u4u4ud`>=uJuCɡ+T)Juu.wwy=wywa_`]`>Nwwu]/`wa`Nx g][=x2xF.4xVxVyLxY_`>=xn`4x{x{x`JxxxKx4xxyxw``>Ix!xF>=x˦xxp*?yy+y9pbyfy_p§V4yyy`>=yyp)T)Jyyp.{| ~8-|~8|a_`]`>N|9|@u]/`|Fa`N|ng][=||.4||}|_`>=|`4|||`J||Ӏ|8|4||}^|w``>I||3>=}}(}6])?}`}w}]b}}]§V4}}~`>=}}]*T)J~'~.].'( ']`>N#u]/`)a`NAG`=U.4eefp_`>=uXzuXWb2§V4`>=׀2XT)J2.$5 =]`>NQXu]/`^a`Ng][=.4p_`>=̦b*bb§V4==m`>=SLb)T)Jb.w`[]y_J__..!1x7x]],_>NHO],_1T_Nmtu]/],_za],_=.4_`>=À〘O;b§V4C`>=' 1T)Jgn.]]_>N]_g_Nu]/]_a]_=:.4JJzM_`>=f_ ,j b Q§V4`>=ʁ Q ,T)J + Q. x f`[_+]_J.+)_!s.`]y_>J_.!.66a_`]y_>J_.-"B.`]y_>J˪_.".1;~DJa_`]y_>Jal"_.# +.ya__`+]y_>Jת-_.#r.]_>Nu]/_a_Ng][=$$8.4HHKK_`>=^n$|#$Eb#§V4~`>K>=0 \$[+l[.`>=?Z#b$Ӄe$)J#.77]_>Nu]/_a_N(/_+N@Lz`*=Y.4iilK_`>=%)=%%bЀ%^§V4`>I%>=%%^/%TJD?K>=0t\[l[`>=å%^&&)J&-%^.]kr]_>Nu]/_a_N_+Nz`*Ng][='U.4!K_`>I48'A>K>=0][l[`>= 'U' 'Ά"'J@?=^'A)=|'/'b' §V4`>Iނ'A>=' '/TJ#?K>=0Sn\[l[`>=' (Ʌ()J ' .y a_` !a_+]_>Nu]/_Чa_Ng][=).4((+K_`>=>`4KK\`JQUQ)HV)4^^dw``>I{*N>=))|)?))|b3,)|§V4SS`>Ib!mf)`(+>=_)`)|§T)|§VJ?K>=0\3[:l[=`>=Ni)|q+tt+)J)|.PZ:yc:ia_`} !a_+]_>Nu]/_a_N_+Nz`*Ng][= ,o!.411.4K_`>=G`4TTm`JZ_)(fb+g,4oouw``>I-.>=,[)=,I,? ,o,'bHA,'§V4hh`>Iw{,[>=,',ITJ?I!, (+>=_ , ,'§T*#,'§VJG?K>=0w\[l[`>=ƥ,'..)J)0,'.  a_`, !a_+]_>NHOu]/_Ua_Nip_+Nz`*Ng][=/.4K_`>=`4`J )(//4!!'w``>I>B0>>I[_/k>K>=0][l[`>=//7$0'0 JM?=s/k)=/Y/?//7b /7§V422`>IAE/k>=g`/7q/YTJ?K>I!/(+>=ڦ_//7§T/7§VJ'?=0Id\}[l[`>=/722")J/7.eox}`]_>IŠ"!%”Ž2`¥Ÿ2=0ª´2?Nu]/_a_N g][N!.{`=73$K.4[[^K_`>Iq{u2(~34>=Úê3$ø33oJ?=3434Wb(!3§V4HH`>=^W3Āđ2.'+ĭ34V)J3.'.8`{Ia]_;\+]y_> Nʂ]_Ng]_Np`N`N^\O).a_\4˫7_\>=LF5=g\4݀k5V=y5ˆˁ5|˒4˝5O˲˷ba[`\˾˿S[Y`\>=5@"% 4]&[%:/4]V[WNhrp[t4=̐̆6a ͥ̚5 ̡6 +=55|45Oa\R\>=*$5=E:4wOY^Ya\f{\>=K5WIftj4(+>=·54ΑΑ`>=ΫΠ4݁Ǧ'}4+>Nύϡ~^]_[ϴϯ5[]_4N]__+=554??`>=VN8$ =‚^4ݧ=ДЏ5]_Ф7 й8$ =8$ =+=4.56b)5:6 =I5VQ5|b4m5Oтщa][ё ][>=Ѣќ5Nѹ][σ4=4+J9 =4#!.;_]73 +g9J r_Ҙ73 +4ҢҢ5`>=5=!4Z477Ӥ`>=UH4]=k5xs5|ӄ4ӏ5Ӧ9J ]_JӵǂӼ4݀ P t $M    4 ?I#,V!@!"""#J#%*&) +.2n4:,.^m`[`\? .AHPNP][.a_\\.ݩݮbݵݿ`\.<AZGZMa\\.:?[ZD[M][+\.}]\.\`.f`[_+]_<<5E>}>>ā.T`[]y_ǁ. ]y_΁.VV]y_\?ǀ5?l KɁ.[dp`Js{s.§ǝˁ.nnnYa]_g\+a]_g\+]y_J-5-.§ǢnYQ@e@'́.sRRa_K\b`+a\+`+]_>J.§@b@)@ƅ@@է??@|A6ρ.<K:`[`\? с.y ]y_][ҁ.*18w68][AABՁ.`[`]_]_\? ׁ.w][ف.][BvBB܁.E`[`[`߁.[1[.   9I  9`[`[ Ya]y_`]_]__=5[~5i_+5_+.A`[`[a_]_;\a``]_SY;\da]_;\]__=5[v5i_+5_+.Ghm`[`[`[`[6]__]__>JK____D.5 ]y_]y_.5CAC`[`[]__C9CDE4EvE.`[`[`]__."979\? ".>Xd`[`[]__Jp____.FSF.'`[`./7E`[P]y_]_Jϩ_G%."<"I"S"Q"S]`.$7$=$D'$D$D_.'' '''][FG\GGG.'e'k(`[`]_.'=][.''''''=][\?Ho '.''('(' _\>=('.=§(H.(((m(!(m("S`(5Y`+\>=(N(H.=§(WI!(^I/.(r(w(w(|(\>=((.=§wHHIoI/w`[`]_/]y_ +/X`p`[~Ya\+Ta\+Va\+a[+i`*]_>J#Jzr_JF%JS.J`8JmPo_jJFtJS}J`Jm]&_ /̗Ԙ`[Ya\+ a\+i`*]_>J2#9K:L_nK xK-_K K-]V_/d{Y^\ /Ya\\/T^\/ǚTΚa\\/ЛV^\/V a\\/ќٜ^[/ޜa[\/dvz;zz]_/%---`/'\''`/dmxxx`/ _\/$S,S4S`GY`+\/w][/ةߪ 6]y_`+][IJJKKKLLHLrLLLMMBMgMMMNNX/ȸ׻`[`]_\? /ѹֹٹ _\/S`Y`+\/w][NO)OcO/`[`%\?  /ӻDDa_\b`'a\6`]_!/HMåYp g]_\>"/ĥ g]_\>#/ƼӼ g]_][J+OPDPxPP&/}k\`[`]_]_]_]_ )/@i`*/@`+/A1`,/A`-/C?`./D`7//E[+0/FI`F)1/G]/[+2/GY^\3/GT^\4/GV^\5/H^[V/HHHiH.HiH4Y^\HCT^\HQV^\H`^[\?2R3R4R5R H7/HHHHH]y_JHH٨~_.8/IUIgI;IlI]_JIoIs_.:/JJJGJ%JG`JJ(!JCJ0J).I¨0J2+(@/JzJJJJ`JJ!JJJ.I¨0J*(;/JJKCKKC`JKK2KK.I¨0K,(K5)A/KHKQKzKZKz`JK]!KvKeK^.I¨0Kg-(B/KKK\KK`JK#K.@KK.Q¨?¨!K.¨:`/NN3NNBN]-_>@NO.¨;NON^INe!Nj.¨<>JN&NN.¨/]-_?NNNM]_&NN.¨/]_JN&NNNW]-_F/O:OOPOcP]@_>@Os.¨;OsOIO!O.¨<>IOOO.¨/(+=O.O̩K_/?JO&OO.¨/]@_?NP(P.M]_&P(P0.¨/]_IP>PPPHPBX(+=P_PYXPmK_?JP&PPPX]@_?/QSQrR0QQR0]_>@Q.@QQIQQ.¨<>NQQ]_&QQ.¨/]_JQ&QR +RY +]_?JR&RR$.¨/]_G/RRSRS`>IRR.A>JSS('?@SR.¨<SRSaJShSs('Q/SSUmSUmS 6]y_S`+][>IT +!T.¨==0TT#.G?IT9T=.¨:JTJTUb[+?NTT]_T_.T.¨/TZ+5`TZ=#UZ(+*Z`=U.‚UZ/=U*.IU1U*.I¨0kU4.0JUJUZUQZ̨C/V_VjVVoV][JVrVr.HH/VVW,VW,][>IVVV.¨1(+>=V.#V.¨:VWa[]/[1?JWW.¨1R/W`WeWWhWWk K_\>IWx!W}.¨==0WW.G?=W.W\vJS/WWYdWYdXS`XY`+\>IX'!X,.¨==0X:X@.G?=XV\X^Xl\NXX`XXX\X]IX!XԂX]](+>=X\XYX]]S=Y]Y.Y"]]Y?=YD.ͥYN\YU]KT/[;[B[w[G[][>I[P[T.A>J[f[m.H?I[![.¨==0[[.G?=[.cIJ[[.HI/[[\c\ \\>=\.I\\.I¨0k\-0I\/\3.@>=\H.˥I\`\d.¨;>=\\}.F \,G?J/]>]C]]G]]J K_\>I]W][.@>=]p.ȥ]z_I]].¨;>=]].F]ɩ_]_G?K/]]^ͥ]^^S`^Y`\>I^)^-.@>=^B.ɥ^M`W^T`eI^l^p.¨;>=^^.F^#^`W^`eG?L/^^_Х^_\>@_.¨<__"N_L_U]_&_L_W.¨/]_=_e._y_paA/=_.I__.I¨0__.g0=__aAtM/_`c`c`a_\`-b``Aa\`P`]_>I`e!`j.¨;>=0``('?N``g]_`_.a#b a+ba4b,a<b:Nacaq]-_as.¨>=a.Iaa.I¨0ka*0Iaa.¨<>Naa]_&aa.¨/]_=b bc+bb=b3b*c+]>=bP.„b[b/=bbsbbb=bbb4bbb`>=bͥb.Y2JbbbN/c cic!ic8 g]_][>Ne?][IeKeO.¨<>Nee]_&ee.¨/]_=edeeed?=e.+/=e.If%ee.I¨0efe*kf.gkf'+0If=!fJfA.5(+>If[fff_de(+>K>=fde&fg.5][g[gl[g"`>=gde5]/[gߧa[5[ggegeheYe>=hqdehhzdevh.5?Ohhta\hi1\>Ih"!hh.¨1(+hh.¨1ѥ§<>=ii.¨1ҥ+W?Ii8!iCi<de(+>=iTdeidi]deviqfc>=iifcJiideO/iijåiji g]_\>Iii.¨<>Nj8jA]_&j8jC.¨/]_=j\jSgZ?=joj{.T3P/jjkZĥjkZj g]_\>Ijj.¨<>Nk k]_&k k.¨/]_=k-k$hP]?=kAkM.V4S(SnSTTTUYUV,VWWXY|Z[n[\N\^^_}`-`ad gMghW/k_knl`[`]&_]_d\? Z/kkkIkk`]/kklIklkM`\`/ll lAȥllAl _\>=l3l%.Q¨?l8ja/lFlKlɥlUll]S`loY`\>=ll.Q¨?ͥljuljb/lll˥ll\>=ll.Q¨?Хi}iijKjke/llnl`[`]&_l\? h/mCmHmȥmQmmT _\>=mnm`.Q¨?եm~_mki/mmnɥmnmS`mY`\>=mm.Q¨?եm#nln l)j/n n%nj˥n.nj\>=nEn7.Q¨?ե nW,kklulm/nn`[]&_]e_oY[T[V[[\? Vm$m,m4m<mkp/oOoO`[]&_]W_rY[T[V[[\? Vmmmȃmms/pps`[]_v/pXK]_~/qqq$qq$qK]_\?vnp qy/q)q?qqRqqXa_\q{b`qa\q`]_Jqqq.K¨vqnǁqnڂqnqn |/rrrzrr`Jrrrr.K¨vzɆ7252z/sss(ssss``>Is's+.s;oJsC)?IsT!%s^sXo]s[Jsu*?Nss]s[&sso]s[Jsssρsp8K¨vs.K¨vnoSop/ssu`[]_/tg K]_/twtwu&tu&tK]_ta_\tb`ta\t`\?q ttquq2uq@uqN/u+u2unu;un][>JuDuWuK.K¨.#/usuxuuu\>=uu.K¨å.!/uuuuu\>=uu.K¨ĥ."qqr>r/v9v?w`[`]_/v ][/vvvvvv][\?s + v/vvvvvv _\>=vv.¨vs_/vvwKvwKvS`wY`+\>=w,w$.¨w5sw<s/wPwWwqww\wq][Jwbwjwb.¨w/wvw}wwww 6]y_][Jwww.¨wt~/wwwww][Jwww.¨s7st +tVtu/x2x8}`[`/x ]/[/x ][/xxzyzy$]_y:6]y_yG`\?yta[yyuyyu¨b&y#yuyyuz'zuͥ¨[`zQzFuХ¨ztu x/zz{z{z][[Jz4zz{zl[z``>=zzvͥzv҂zv={zvХ/{{{HZ{${H\>={={-.Z/{M{R{}]{X{}\>={q{a.]/|a|h}W|n}W][>N|{|][||.I|||w(+>=||.̨ҥ+WJ|+?J}}}wv4}}}R`>=}7}'.̨ҥ+W/}\}a}t}i}\>=}}r.̨ҥ+Wv~w8w}wxx/}}`[]_/~[/~~~~]&_~[6]y[`\>IVeZyv\B>=w.Z?y '-yv&99y]y_Ayz'00?`[`\? 0QVbZb] _\0fkͥt|S`Y`\0Х\zyzz{0.`[`\? 0ʂςȥ؂ _\0ɥS` Y`\0!,˥*,\{c{{{0q`[`]_]_]_0p`0 `0`0`70!`70Q`7 0}`7@0`7Á0^_\+ā0ۥ`+Ł03^\+Ɓ0I `Vǁ0I`ȁ0][+Ɂ0X]-_+0͏a_\b`a\`\>=h.o}=.b}=.}#1}A` !́0otyy ]-_\>@.¨(+ŐI݀~d(+J?=.€~dI!#~d 5>=4.I;4.I¨LJk>=aX.¨ɢ.:?ہ0a_\\>I݀4(+=4?=j.zt.¨Ƒ[_4܁0b`\>I递(+=?I%'a``\>=U.ۥq`.¨Ƒ[``a``\I%΀a`\>=.ۥ.¨Ƒ[`(a`\>=0IS$''݁0||a\\>I (+=)6?=L.\V.¨Ƒ\mށ0aZa][+\>I.¨J?N˕`.¨N`.¨=Z.Ikd.I¨WmkI!Q(+=ÀQv.]?I"!w!.¨(+= +.¨ɢ;?I "!%!8.¨=E.T.¨?߁0fk]q\>Iz~.¨J?I.¨>=.¥I!.¨>I".ץ¨!.¨Ɂ 5>=E<.¨ɢ.:>@w.å¨w=.I.I¨DžgI!.¨=..¨???0 PP][>=.I.I¨DžרgI!.¨>= .ĥ?J"5][).¨#7(+Aǀ][0U_ljlf`[n_+]_>N]/_a_=.4`>=nT=.ۥ4))T*S[1Y[`>NLY][[.Ik!pz>=v4`>=ׁ&`V>=$3&::`VJ[b0`J!.I¨Dž(0˜Ԝ.ޜ`J!.I¨Dž먼(0 99`J!5".I¨Dž$(0=FƥV`JY!{aZ.I¨Džc(0`J!.I¨Dž(0ʝץ֝`J!.I¨Dž(011`J.I¨ǃ^05>eǥGe`JJQJ.I¨ǀS0irå`J"!.¨".¨(+.¨Ɂ 50Þ̟ȥ۟`J!.I¨Dž註(0 '\'`J.΅0,1ĥ8\>=A.IHA.I¨LJkKI`d.ץ¨>=y.¨ɢ;?I!.¨=.+?=..Ԩ΁0֠ۡ/¥/\>@.¨=.I.I¨ǃyρ0PUY\ _\>@!p..¨oyI.¨J?I.ǥ¨>=.ȥp>=.ե_pЁ0 ͥ"S`4Y`\>IFJ.¨JW?Icg.ǥ¨>=y.ɥ >=.եܩ# с0 Х\>@!(..¨'1I8<.¨JI?=U.I\U.I¨LJk_Irv.ǥ¨>=.˥>=.ե ,ҁ0ƤΤ\>@.¨ޤӁ0((\>@!.¨#ԁ0-4n=n][>@M.¨MXJ_+Ձ0-2xե=xL][\>Nnv]@_&nx.¨]@_I.¨(+>=.K_?=灦GI!.ץ¨>=.I.I¨LJkI5!:.¨>=XO.¨ɢ.:??ց0ȥ _\>@!.¨ħ@!.¨ާ@!.¨N`.¨=3.I:3.I¨LJk==[U.¨Ɲ_k.¨Àt =.I.I¨Džg=.ʥPׁ0ƨ˭}ɥխ}S`Y`\>@! .¨@!#.¨",@!;.¨:FNRa`c.¨Ox}a\\>I".¨!).ƥ¨J:?=H.IOH.I¨LJkRNb`.ۥ¨I%΄a``\>=.¨Ɲ``)a``\2#9/>@%md.ۥ¨a`\d=.¨Ɲ`&.ۥ¨a`\#=.I.I¨Dž٨gI.ȥ¨>=.I.I¨LJk=<.ĥIM"%_Q.¨][!w.¨>=.¨v>=>==X.ʥdt؁0˥\>@!.¨歠@!.¨ꭺ@!.¨ҭOa\7\>I!.ƥ¨J?=.I.I¨LJkkȨkب=.¨Ƣ.¨=.I.I¨Džg=>.ĥ=M.ITM.I¨LJkWIs"%w.¨][!.¨>=.¨v$>= +$ف0a\\>@!4.¨3?NKZ`\.¨=p.Iwp.I¨LJkz==.I.I¨Džg=.ʥځ0oʥ'o-`\>@!K.¨JVI]"a.ץ¨yp.¨Ɂ 5>=.I.I¨DžgI".¨.å¨>=.I.I¨Dž먽g??AC)>I.¨>=.+J?N`.¨I':+(=|BL?=Y.I`Y.I¨džcI}|>=.>=.=.I.I¨Džg=|I'"+.ץ¨!;.¨>=WN.¨ɢ.:?~D3E-,dNP6kj!0BQ`[]y_\? 0ַ!!a_\b`+&a\+5`+]_>=K[)kNg]_.s=.ХJ +0ºպa_\b`a\`]_>J,7_`Nh_qkyw0ͺҺХۺg][\>V.0ag`[]_0 ^]-_0ҥ`*0^]-_\?v 0Ѿa_\b`a\`]_>I(,.ҥ¨=05?('?=w.ҥ)J5]__ȁق僽5[:.̄:0[aB`[]-_0Xӥ]%_ 0X*X7]_\?PK + ?0]f n`Jq{q.ӥ©(+ +0BtBt $]_\>I.ӥ©(+>=0('?NAQ4`K>=Ai!A}As.ӥ©'A[Al[A`>=A.ӥ+=AŀAɥA!A,JAIA!A>=B BȥB!B.ӥ©')>=B>.ӥ+=B_BV˥ 0ByB~B BB\>IBB.6=B.;?=B.ӥ+;{@0EEE`[`0E}][+\? 0EEEEEE $]_\0F FF`[]_0FH K_0FQFQFiF]FiFcK_\?d FQ0FmFrFFyFF $]_\>=FFȥF.K0FFG][0G S[0G* Y`#0G9G9GcGFGcGLS[GXY`\?`j G9!0GgGlGGsGG $][\>=GGơɥG.SG.Y$0GGH`][,0HHH#H!H#\? H&0H'H,HkH3HkHC $][\>=H\HS˥(0HpHHHH][JH+*0HHHHHHp][\>=0HH('nJ-0I"I1P`[`00Iܥ`10Iݥ`20J`30LI`L0?\? 50LLL LL`60LLMLM`JLML.I©3(M180MM MMޥM0MM`JM3M:M3.I©3^M=1:0NN#ON+ON> $]_\>INNNR.6JN_?@!Ns. 5NrNzINN.ޥ©8>@NN.I©3(N2NN=N.INЩ13JN?=N4O O O`>NOO$`O&.I©3=O4.IO=03IOWOdO[(Og2JOx?=O.O<=O.IO13;0OOPOP\>IOO.6=O.IP23?<0PPPCP'PCP: $]_\=0PPP PP\?b@0PPTW`[]-_B0QR][+C0Q][+K\? ?E0QQR QR`JQRQ.C(+G0RR RR#RR2][\>IR?RTRC.C(+>=Re.Ry.R.CB>=R.RR.CR.CH0RRSRSS $]_\>@!S.6SS*NS?SE][SG.B=S^.SxSrBISSS.B(+>=S.+C?=SҁSSI0SSTU STU\>IST.6=T.;?=T&.T:.+CBL0TTZW`[`]_O0UJ`P0Um`Q0U`R0U `S0UI`T0U^\f0UUV1UV1U^\\>=V".\TRV U W0V6V?VdVGVd`JVJ!V`VRVK.I©SVTO(X0VhVqVV~V`JV!VVV.I©SVP(Y0VVV\VV`JVVV.I©S^VQ\0VVW?VW?\>IVV.©XJV?=WV.©RW.˥©]=W'.IW.W'.I©SkW1PS^0WDWIWjWOWjWUa_\\>_0WnWsWbWzWW`\>`0WWWWWWa\\>=W.€WTa0WWXVZWXVW][+\>=X.IXX.I©SWX +QSIX!X(X(+=X>X1vXK.]b?b0X[X`X]XfX\>IXoXs.\Y>=X.IXX.I©SyXQSIX"!X.\Y!X.©W>=X.\??c0XXY +XY +][JXXd0YYYY$Yf`[Y(_+]_>NYGYN]/_YTa_=Yf.4YpYpY`>=YY{+UTJYY]0YYZU˥YZU\>=Y.IYY.I©SYYߩPgSIYY.\YJY?=Z .IZZ .I©SkZOSIZ#!Z/Z'.©T(+=Z>Z8.©RZI.©T?-V2mh E g0ZZZ`e{`[]y_j0Z ]y_k0Z ^]_\l0Z ^]_\m0[ `n0[<XK]_+o0[aXQ]_+}0[s[s][][]y_[a]_g\[a]_g\\>=].K]Ŧ_].Х©x].©wnj,k\\[]_\=l]7]"[]_]~Tm] [sq0^^ ^^^`J^)u0^$^:`^@`^Fa_\^fb`+^ta\+^`+]_>I^"^^.K©n(+^^.K©nj>J_@_Kf__f?I_y__}.Q©o(+>=_.Q__.©j__.K©nb__.K©n` _.K©nwo?=``+)`;J`O`b`V.K©n`mu`u`~`|w0``b`b\>N```"``.K©n(+``.K©njI`!a `.©l(+>=a#a.©m\]~_a7.©laM_.?Iaa7>Ia!aa.Q©o(+>=aa.Q©o=a.Q+o??x0bb bХbb\>Ib!b2b!.©k(+>=bIbC.©m\]~_b].©kbs_.?y0bbdbd\>Iccc.Q©o(+Jc?Nc|cg][c.Q©o=c.Q+o=c.K+n=d +c z0dd dd2dd:][\>IdNd`dR.Q©o(+Jdi?=ddu.Q©oZd{0ddede\>Iddd.Q©o(+Jd?=dd.Q©o]s0eeeye%ey`>Ie+e=e/.Q©o(+JeF*?JeXeme_.Q©o\N9qi~0eei`[`]_0f) ]g[0f5f5f`fRf`fX]g[\?s f50fefjffpffva_\\>=0ff'0gggbg gg`\>=0g)g3'0ggh)gh)ga\\>=0gg'0h.h3hZh8hhA][+\>=h^hV.©hqz0hhh]hh\>=hh.©{0hhihi][>=hh.©yJhi0ii%i\\i.i\`>Ji4iCi;.©©s0iaikiivif`[iz_+]_>=0ii'GCM0jijo{`[`]_0oQ][+0q`0r`*0rrsrsr]y_\?s r0s ss}'ss}_>Is!"!s3s%.Q©(+s>.©>JsQ&sQsX.©_?Jsn+0sstst]`>Is!ss.Q©(+>Iss.©>Nssu]/`sa`=t.€t0=t#.*=tLt>.Q©]Jt^te0?=0t{t('?Jtt.0uuwguwg]`>@v u.Q©(+uvNvv'`v).©Iv9!vGv=-(+>Nvbvi]y_&vbvk-]y_=v|.Qvvlv.©bv.ۥ©v.©)Nvvu]/`va`=w.‚w"㩒Jw0w7?JwIwW0wlwsxwyx][>Nwwg]_&ww.Q©]_Nww`w.©=w.+Iw!xwm(+>=x.Q+Ix2!x7.©>NxZxau]/`&xZxc]/`=x}xv +ҥ*W?Jxxxm?Jxxئ0xxyxyx _\>@"!yy.Q©(+!y(.©yy1NyFyU]/`&yFyW.©]/`=yg.€yt=y~.)=yy)TIy"!yy.Q©(+y.©=yy.Q©Z?0yzzۥz zzS`z&Y`+\>@"!zNz@.Q©(+!zZ.©z@zcNzxz]/`&zxz.©]/`=z.Q+=z.+=zقz)zсzV0{{{{{\>@"!{-{.Q©(+!{9.©{{BN{W{f]/`&{W{h.©]/`={x.Q+={.+={{*TA;|m0||#}=`[]y_0|I|O|q|[|q\? |f0|u|~|||`J|)0||};|};|a_\|b`+|a\+|`+]_>J} +}f_}0t*ú1etG`[`[]y_1 ]y_1ϊ]y_\?, 1  `J.©1(.4a_K\Ub`+ca\+r`+]_>=)J.Ĭľ˃106a_\Ub`ca\r`]_>J__.Yjvł1@EPS _g ;]_\>=xs&&}`_1S[Y` ;]_\>=䂍iͥU]1 EE( ;]_\>=94ХUď95Ơ1`[`[]_1 ]__1:XQ]_+Ɓ1LLpipo]__}a_\b`a\`\>=.Q-.©©4.©bJ.©Å`.©ħDž ШǗǨǴ127y;y> _\>IJN..¨JY?=kpm1~ͥS`Y`\>I..¨J?=١ͥā1"'x/x\>I8J<.Q©(+JS?=m_.Q©Z1}\>I.Q©(+J?=.Q©]1ڒᓠꓠ][>I!.Q©(+>N)6g][8.Q©=M.Q+Ji}p +?J+1ܓ _\>=.©j.Á1#(45S[GY`\>=aY.©nʺu.ā1\>=.©.MȤiJʚ8ǁ1`[]__ʁ1= z^_`ρ1GGS^6]y_ka_K`\?ʁ ́1 _ ;]_\>N`K>=J.z*([/l[2`>==V5\}_̆JiI{J>=5*? +Ё1,2`[`[]__Ӂ1 ^__؁16]y_a__\?Ӂi Zց1  _1 ;]_\>N?_K>=\j.u;[l[`>=ɃJ=ɒ͞fف1EKl`[`[]__܁1 ^_]_1&œ&6]y_a_]_\?܁  ߁1+0j;j> _X ;]_\>K>FpwK_.O>=Zv[l[`>=<UZ[Ϻ^/1w`[]__1: `1Y z^[S`1ccu6]y_b`a[S`\?偞Ѓ悞Џ t1 uuS`/Y`I ;]_\>NZbL`)In!xr.z©(+>K>=.z[l[`>=ΦmvJ?I>K>=9M.©倠Y`u[|l[`>I>=ͥ>=J'>=OJͥY`҃1z`[]__1 `1ȡȢӢ6]y_`\>I!%`=0? 1Ƣܤ&&a_\b`"a\1`]_>IFQJ.©(>=tg_.©+Jf_Ӎ?JȪ_.pӁӍ ә.©1+0;> _X ;]_\>Ng]_&h]_N`}©IȃԠw>=ځh]=ԠԠy=}ƒԠI'1+Ԡ(>=hХ??P=Y1ag `[]__1 +[1*C]__Pa_\ob`}a\` +[\? սς섧1 `J&. +©`1I  I&`\>=2. +€A֩1NVl]l`J`&``. +©`1py`\>=. +€+1`J. +©1ӨܩK`\>=. +€פK։ Oׄ1l `[]__ 1f z^_`1pp6]y_a_K`\? [ ʩL 1ܩjj _ ;]_\>N`K>=5A.zGز Z[al[d`>=oؽ=ؽХJI>=.)ؽ3ز>=XSؽХؒٔ1ou `[]__1 `1Ȭ6]y_`\>I"!%`=0? 1Ȭޭa_\b`$a\3`]_>JHS_.~ژکڵ.ª1Ʈ _ ;]_\>N g]_& ;]_N(.`=0P©IISMsw>=m`P|vsyJ?=;0x1`[]__1 z^_`"1z#z.6]y_;a_K`\?_u msf1gga_\b`a\`]_>J +_.5́=݂F郰N* 1lq| _ ;]_\>Ng]_&f]_N߰`{ ©Iݞ>=f$[J7?NN`K>=iu.z{[[l[`>=f&=!{ )J5IG!L>=l_{ )=f[?ܬ;ަ#1ʲз`[]__&1`"'1B ^__`-1NN]h6]y_ua__=r`\?'K <*1Ѵ䴧a_\ b`a\&`]_>J;F_.qߦy߷Ã&+1 _ ;]_\>Ng]_&D]_N'`6)Y©IBFP|Z&>=Y€9=D9>Nص_&|_N`K>I&.ª'(+>=;TF(W9>=.퀶9'[l[`>=֦DႇJI!>=72D<9=^QY€g9?߆.2>Da`[`]_12=][72=][\?1i 32 _\>=.=ª142ہ55S`Y`+\>=.=ª1ͥ& 52:?_wD_\>=SM.=ª1ХA{82~`[`[]_;2X]_+<2eXQ]_+L2wwtt6]y_^]_]_a_\b`a\`\>Np]._Ȫ7_.=.s;=.Q1* 8.ªHbN.ªId.ªJ< ou7}HT` +?2Ȇֆ`J!.Qª<(+B2`` _\>I..¨>=0('?=RW{C2=BͥKSS`eY`\>Iw{..¨>=0('?=Сͥ⁉D2̊ыEХ׋E\>I..¨>=0('?=9ХE2ty\>I.ª?=.QªI.ª?=.Qª<]?G2 ][>I!.ª?>NKXg][Z.Qª<=o.Q+K>=.ª;[l[`>=).ͥ36CI2GLBXBYS[aY[+\>K>=.ª;H&P`[l[`>I蔀H>=.ͥH&P`C>=!.ͥ+蔃.CJ2GLW\>K>=l.Q+<=.ª;w[l[`>=.ͥ^gC[=$( +M2ُߐ`[`[]__P2< ^]_]_T2KQygym^]_]_\?P8 QR2~5 ]y_]y_J___.ªPqU2B`[`[]y_X2E ^]_]_Y2d ]y__2]y_^]_]_\?Y_Xn [2py`J.ªY]2Ւ@@a_\b`+&a\+5`+]_>=K4[)k4Ng]_L__.ªY.ªX '4J)0h`2"`[`[`]_c2 ^_]_\d2 ^``]_\e2? ^]_\f2X=]_q2qq^_]_\^``]_\^]_\=]_\>I.=ªf(+>=0)3'?cdef i2v.`J.=ªf(+l2[>=5`5[' 5[SQ'!5[Am2jj _\>I..ªi>=.l?I!.ªc(+>=.+y1.=ªfc>=RL.=ªf&[Vy_n2oth|hS`Y`+\>I..ªi>=.l?I!.ªd(+>=.)5".=ªfd>=C=.=ªfL)S5o2mr ww \>I..ªiJ?N;]_.=ªf=.=+fI!.ªe(+>=.e>= +ww[ rr2"`[`[]M__v2hh$a_]_;\+Va``]_SY;\+a]_;\+\? ΪT4Ԟg#]_]`__>Jq__,ށ8EQLt2mw5{ ]y_]y_>J5Rw2$`[`[]__z2 Х^]y_`]_~2"(VFVL^]y_`]_\?zn (|2[e5it ]y_]y_J__.Хªz2%`[`[]y_2 + Х^]y_`]_2' ]y_233iKiQ]y__^]y_`]_\? 32na_\b`+a\+`+]_>=?)?N.5]_7.ХA.ªJ?=e^sl=ysb%=s2Js8Ve"&e(`8SSt`{ a\`>I,$(4>J|DQ?J|D1)'EQ8o&0t`{?a`p\`>I\me(u>J(%?N>L)a`\[S`{J(򂋼V8q}a\\>=8\8W_cscc`8`iqXqq`4+*+(7At`{Pa\`>Nfsk`~ux+I=?Jš 4,(*t`{9a`p\`>NZgk`ri+I?=??Já!?&' .S3-``3H S`3b Y`3qq{S`Y`\?) q3A`:J$.S[3ʼnB.```3 `3 _3@&@,`7_\? 93AP/`3P[1[3Iʏ ^`````SY\^`[```a__/^`[`[```a____P^`[`[`[```a______y^`[```a_^_^`[`[```a__^__^`[`[`[```a___^___^`````SY`J^```a\\v|^````{a\t`(^````{a`p\|`^````:\^````][[[``=5[3{s#ss` ^`````SY\+^`[```a__+"^`[`[```a____+I^`[`[`[```a______+x^`[```a_^_+^`[`[```a__^__+^`[`[`[```a___^___+-^`````SY`+a^```a\\+|^````{a\t`+(^````{a`p\|`+^````:\+^````][[[`+`>J'2 5^`````SY\b#v%(+yނ몫%^`````SY\5^`[```a__#(+^`[```a__5^`[`[```a____N#=(+׀ޢ=^`[`[```a____5^`[`[`[```a______#(+ޑ类^`[`[`[```a______5^`[```a_^_,#=(+F@ޑય^`[```a_^_5^`[`[```a__^__;#(+ޑ⪰^`[`[```a__^__5^`[`[`[```a___^___#](+ޑ䪱]^`[`[`[```a___^___5^`````SY`4#BQ(+KEޑ檲Q^`````SY`5^```a\\u$ #(+ޡ^```a\\|5^````{a\t`L +#U(+̀ޢ|U^````{a\t`(5^````{a`p\|`} # (+ޣ(^````{a`p\|`5^````:\8 #> w(+GAހ w^````:\5^````][[[`\ #a (+jdހ ^````][[[`3x^`````SY\3^`[```a__3ĕؕ^`[`[```a____3^`[`[`[```a______3"222^`[```a_^_36Wlll^`[`[```a__^__3p^`[`[`[```a___^___3ŖҖ^`````SY`3֖^```a\\3*|**^````{a\t`3.M`(``^````{a`p\|`3duzzz^````:\3~^````][[[`u + +  u  D  + r  F30`` 3 ^`````SY\3 ^`[```a__3 ^`[`[```a____3 ^`[`[`[```a______3J ^`[```a_^_3 ^`[`[```a__^__3 ^`[`[`[```a___^___3 ^`````SY`3# ^```a\\Á3Q |^````{a\t`ā3 (^````{a`p\|`Ł3 ^````:\Ɓ3 ^````][[[`ȁ3ؘޚ ^`````SY\+$^`[```a__+:^`[`[```a____+U^`[`[`[```a______+q^`[```a_^_+^`[`[```a__^__+^`[`[`[```a___^___+^`````SY`+^```a\\+)|^````{a\t`+G(^````{a`p\|`+m^````:\+^````][[[`+\? UI 8 +n  gɁ3X1`\?  ˁ3P'P-`3S[EY`\́3TVn\n`[b`ja__́3rt`[`[`a____΁3`[`[`[`a______ρ3''`[`#a_^_Ё3+Cu^u`[`[d`la__^__с3y`[`[`[`a___^___ҁ3--`S`"Y``Ӂ316\G\M`Xa\\ԁ3`f|qw`t`{a\`Ձ3(`|`{a`p\`ց3  ``:\ׁ3VV `8`K][[[`4c<M ځ3e`܁3L`ҥށ3`3"p "\? 3Vfy'ny`Jqq3E'E(S[:Y`\3`iooo`3-6?!??`3D2``3AAAAAA`+A][[[+`3CCDDD`[Da__3DDDDD`[`[Da_3_D3__3EEFEF`[`[`[Ea__45_E4_E5__3G%G*GCG4GCG:a\\3GGHGH`[Ga_3\H3_\3HHIHI`[`[Ha__45\I4_I5_\3LLLLL`[La_^_3M@MXMMsM`[`[Mva__^__3N +N(NnNINn`[`[`[NSa___^___3OzOO6OO`[Oa_^_3PPQ7PQ`[`[Pa_3_^__3R+RIRRfR`[`[`[Rpa__45_^___3TTT4'T#T4T)a\a\3UUUUU`[Ua_3\a_\3WW4W8WUW`[`[Wba__45\a__\3\\]\]\S`]Y``3^^^^^^a\\3_ __B|__B_(t`{_7a\`3___(___|`{_a`p\`3bb"b4b'b4b/`:\3bbc?9bc?b``>@!bÀb#(+bb@!bb#bbbNbc`c =cހc"#Jc,c3#3ccd :cd c`\>@!cc$^(+cc=cހc$^3eeeeee`[(XR c'  S !.!j!""g""#9#s$4$$3fFfLvv;``3f <`3ffffff<`\?% f 3ffhfhf`fS[fY`\>Ngg=]^`````SY\g1g.<«ߥ«%NgQgZ>`gkg\&2Ngg^`````SY\gg&2JggŅg&g&g٦ g&g&g&h&3hhihi`[h#`h+a__>Nh:hI=]`h]hK.<««Nhmhv>`hhx'Nhh^`[```a__&hhh'^`[```a__Jhhфh'_h'hܦ h'h'lh'y 3ii +jij`[`[i`i&a__i2__>NiAiP=]`idiR.<«?«Niyi>`ii)%Nii^`[`[```a____&iiƃi)%^`[`[```a____Jiii)v__i)Si i)Sj(j(j) +3jj kTj4kT`[`[`[j:`jBa___jZ_jc__>Njsj=]`jj.<«@«Njj>`jƄj+ Njj^`[`[`[```a______&jjj+ ^`[`[`[```a______Jkkk+]___k+:k! k1+:k<*ÁkB*ЂkE*kK* 3kYkil|k|l|`[k`ka_^_>Nkk=]`kk.<««Nkk>`kk,Nll^`[```a_^_&ll.l,^`[```a_^_Jl<lJlC-I_lK-&lU le-&lp,ʁlv, 3llmlm`[`[l`la__^__>Nll=]`ll.<««Nmm$>`m5m&.Nm\md^`[`[```a__^__&m\mumf.^`[`[```a__^__Jmmm.__m.m m.m.gm.t 3mmo*no*`[`[`[n`na___^___>Nn;nJ=]`n^nL.<««Nnn>`nn0~Nnn^`[`[`[```a___^___&nn܂n0~^`[`[`[```a___^___Jnnn0π___n0o o0o0@o$0M3o/o:poGpoM`oZS`olY``>Noo=]^`````SY`oo.<««Noo>`oكo2ZIooo2oJp+?Np-p5^`````SY`pFp72ZJpTpbp[2pl2pv p2p2)p26p2D3ppqpqp`pa[\>Npp=]^```a\\qp.<«A« Nq$q->`q>q/3ـNqaqi^```a\\qzqk3ك=qq4Dq4!q q4!q3q33qqr|qrq`qt`{qa\`>Nr +r=]^````{a\t`r-r.<«*«!NrErN>`r_rP5!Nr|r^````{a\t`rr5!Jrrr5r5rr r5rr4r4r5 3rrt8(s t8s`s |`{s-a`p\`>NsGsV=]^````{a`p\|`sjsX.<«,«"Nss>`ss6Nss^````{a`p\|`ss6Jsss7s6t t6t$6Wt*6dt26s3t=tBu3tGu3tM`tZ`:\>Ntjty=]^````:\tt{.<«B«#Ntt>`tt7Ntt^````:\tt7=tt8\t89u u89u$7΁u*73u8u=vtuAvtuG`u_`ur][[[`>Nuu=]^````][[[`uu.<«C«$Nuu>`uփu9JzV"z].zm?5zz.!zz?5!:;;O;;;<#(>}>>? ?-3zz'E`03{]`+13{?]`+23{@]`+33|]`+43|B]`+53|t]`+63|]^`````SY`+73|A]^```a\\+83}%*]^````{a\t`+93}_,]^````{a`p\|`+:3}B]^````:\+;3}C]^````][[[`+<3}ߥ]^`````SY\+=3~6F`+?3~l `>3~ .][[[]3ss``.][[[\> =.#!B(+`.B.?«]`0=.?#!+"B(+B`.n`B.??«]`1=.@#!B类(+ժ`.B类.?@«]`2=-.#!aPBBય(+x`.Bય.?«]`3=.#!B⪰(+3`._QB⪰.?«]`4=.#!́B䪱(+`.3%B䪱\U.?«]`5=y.#!B檲(+^`````SY`.B檲#.?«]^`````SY`6=7.A#!m[MB(+^```a\\.́B.?A« ]^```a\\7= .*#!3'B|(+J^````{a\t`.rB|.?*«!]^````{a\t`8=.,#!ցB((+^````{a`p\|`.L>B(rk.?,«"]^````{a`p\|`9=.B#!B(+^````:\.B .?B«#]^````:\:=.C#!1,B(+H^````][[[`.wiB.?C«$]^````][[[`ګ;=.ߥ#!B몫(+ꪢ^`````SY\.5'B몫[T.?ߥ«%]^`````SY\<?B>B ,B3~~Υ~`>I!.F«=(+J%.F«=?=9.FN.=Jgn.F«=C3B!&B`J)>).ߥ«<E3GLV\a\\>K>=s.\wKQ[l[`>=.KƂKOF3NN`[a_\_\>K>=.\_L6 +LIR[l[ `>=+.?LBLOG3SXp`[`[va__\__\>K>=.\__MMM+S[l[`>=.MyMOH3 6+`[.a_^_>N=H^_J._[MTJc4jj_Jpu._yN +QI3070`[`[a__^__>N^__.__NUJ4,__J.__N(O5RJ35Sp`[`[`[za___^___>N^___.___OVJ4___J.___OPFPSSK3 '.4a\a\>NCN^\P.\aPTJi4pp\Jv{.PEL3DD`[a_\a_\>N^_\.\_QxUJ 4@_\J ._0Q<QFM3I_ 8 `[`[a__\a__\>N^__\.\__R^VJ4__\J.__RR܃RGN3%.08`[>NGN[TP..«>USUmI_"!jcSj(+zu..«>SUlJSj?I!.?(+>NK[.?SUI! T(+>=($..«>)SU0Tn?JELT?@i.(lduJ|+O3HHS[Y`\>N =]^`````SY\'.ߥ«<@!WHU +(+H^NrG` U +N^`````SY\U +JUU +Up.2T9TP3MRVj`+}][[[+`>N=]^````][[[`.C«;@!˂V|(+NG` V|N-5^````][[[`F7V|JTb[W{lV|V.VTVbQ3`[a__>N=]`.«0@! +W(+N%4G`6 UFW񀎪Nks^`[```a__&kuW^`[```a__JXe_W񀎪X7.WR3`[`[a____>N=]`.?«1@!@1Y(+1GN[jG`l |YN^`[`[```a____&Y^`[`[```a____JۄZ__YY.Yg +Y|S3w-w`[`[`[0a___H_Q__>Nap=]`w.@«2@![(+NG`ɦ [N ^`[`[`[```a______&[^`[`[`[```a______J+92[___I:[O[.e[Hh[bn[oT3|`[a_^_>N=]`.«3@!]|(+N%G`' F7]|Niq^`[```a_^_&is]|^`[```a_^_J]_]|].][U3VV`[`[a__^__>N-<=]`C.«4@!uf_-(+f|NG` _-N^`[`[```a__^__&_-^`[`[```a__^__J___-_-3_s.I_V3[y`[`[`[a___^___>N=]`.«5@!a(+N.=G`? ^OaN^`[`[`[```a___^___&a^`[`[`[```a___^___Ja___́aa`.`W3S`,Y``>NBQ=]^`````SY`X.«6@!sc(+sNH`cIcjJ+?N*G`, &<<cj`Njr^`````SY`tcJccjc.bށbX3**a\\>N=]^```a\\&.A«7@!TEd(+E[No~G` dN^```a\\܁dJe5de.$dY3/5|@Jt`{Ya\`>Nhw=]^````{a\t`~.*«8@!f(+NG`Ҧ fN^````{a\t`(fJ6D=fTEfZfi.peہzeZ3(t`{a`p\`>N=]^````{a`p\|`.,«9@!gy(+N2AG`C bSgyN^````{a`p\|`gyJh͂gyg.gOg^[3%%`:\>N /=]^````:\6.B«:@!XIh(+I_NsG` h瀎N^````:\ԁhJivh瀎iH.hJK KhLLMN{OsPQER S.TV+WY)Z](^`bdkeg'hi^3LRwI`a3J][[[[[b3 K`+3nt}\? t,(e3]`J `̥צ f3J? +J]`J `1< g3Nj@u]`J~ `h300]`J `i34Pg]`Jp v`j3::]`J `k3>fu]^`````SY`J~ ^`````SY`l3mA m]^```a\\J ^```a\\KVm3q*]^````{a\t`J ^````{a\t`եn3#,8]^````{a`p\|`JA G^````{a`p\|`|o3 B ]^````:\J ڪ^````:\p3/tC5t]^````][[[`J> D^````][[[`_jq3x#ߥ#]^`````SY\J ʪ^`````SY\ + +t3>HVOV`JR+r3.][[[J«as3.Υ8`>I>!PBb(+JY`b?Jszb.u3EN_!X_`J[.w3zYYa\\>K>IĪ>=ڀrJ?= \++.r![(l[+`>=6.JrMs x3^c^u^`[{a_\_\>K>I>=ҀsnsJ?= \_++.sns&[-l[0`>=;.Ot Rty3ch`[`[a__\__\>K>Iͥݪ>=tttJ ?=\__++.@tCtItV[]l[``>=k.uJuUz36`[a_^_>J4_J._u{3U7U`[`[a__^__>J&4--Q.__J6;.__JvVMv|3Zx`[`[`[a___^___>J4___J.___wwiwv}3Y'%Y+a\a\>J64==U\JCH.Sww~3^o`[a_\a_\>J4_\J._xkxx3s8 s`[`[a__\a__\>J44;;o<_B_\JKP.__aydy]jyjy3x—ƒ—‹`[J“+3ZZS[Y`\>= +++.DzKz!3_dh|`+Ï][[[+`>Jâé++.z~z3__`[a__>IJ'/.z?J7> _++.Yz3dft`[`[wa__ă__>IĎĒġīJķĿľ{{?JѦ __++.{{3`[`[`[a___2_;__>IGKZdJpxw|y||?JŊő___++.Ų|ŵ|Ż|3`[a_^_J}3A0A`[`[3a__^__J@@}3FdƲƅƲ`[`[`[Ɠa___^___JƱƱ~n3ƷS`Y``J+3WWa\\>=(++.Q#3\bǻ|mǻwt`{dža\`>JǑǞǫvǵ3:(:t`{a`p\`>J*43?DuIuQ`:\>=]lYjkIkklTlmmn0noxppqCqwqr,r`s;tHuvvwx8xyyzUz{p|H}R}~%~~N1(-L`f-8M`f-kN`f--O`*3ȀP`^ Ȓ'4)[Q *'R A*d`[pa[[> NS[Na``Nba``OքTa`]/[݆K`]/[>N]/[I% A]/[>=X#A]/[I5%?9A][>=RXVa[=oRA][X>=Xe[A=Xɜ]/[''׆X` +GJX=4""#K``>N4CU[E[''Yꅆ_R=kRs`''iJ#`'g'iRׄ!R`=x +4DK``>NU[[''ꅈ = Ԝ`''$J#`'g'$) 81!9 `NMR`YId!isy>=``= +ͅ`` +?NV]/_a_NW`*Oa`e`>K>=ɜ[''؀NX[[''Y+NI% +][>I% +][]/[>=S +]/[&9>=[Ro +][v9IV>=͆9_'' +U>=9ҥ+]_''7 +W>=iSz! +9[l[`>IV>=ۥ91 : +>=!A9N1 Q: +Ijs>=h=V)>=V)=hJ99,Z,;`&S`8Y`[>IH%YL ^``[>J& ^``[[&>N[^[[& ^[[J 7\]/[S[Y[\>N`#1&88$`IG!WK4(+>=fn|4S=$4Y?=ƀ &$`V7/4l]Sl\]/[dS[kY[\>N`F&P`I!Ճ`(+>=F`S=P+`Y?=D=7XF&__P`Y7^S``J5`c#߁(+`,eeg_ege;`f``>If %ffa``[>JfMfbfT[``fa``[?If%ffa`[>Jfff[`ga`[?=0g'g1gL'b$'`'a-INEb\E\>Cc!xj(+>=+N`fť=إ3iI +(+=+?==4.3h-HMc`\>=g)L>=>= ++=,*IK!]O(+>=xv?-ejd^\\>Ne`fkI(+>=#7I1!6>=[vn?>=7i=7--f-^\\>I,>0(+>=Md=sJ?N`f̧kI(+>=*#i=6F^*>=zt*ii=*i=ɥ*I*i(+>= *?-Ǐ̒mݒma\\>N1`& `I%0>=++ߥ J?N$=]`2&A« IH"LVpaqD*>=++\ J?=.&ࡔME'a /oopgopoh^[\>Ip p#pS(+Jp,?K>=pSp@Sp[[pbl[pe`>=p{pspp0CCCiCCCK`\>0DDDjD*DD2S`DEY`+\>=DcD[Dw\D~j0DDDkDD\>188lG`[Oma_[na_K[oba[`SY[[>K>= [l[`>N݁`b kI!{(+>=92:b=k>NX^S``zn{SNY`{Y=ᇂ1V[oj~g][u]/[S[Y`\>Nƃ][ _I"%][! ][,>=M@][v4ZZ\J`g`lvx}V>=lxV1˄ІBpBg][u]/[$S[6Y`\>NQ]`ldzI!(+>=фS=Y?=|&.51džևq쇒g][u]/[^[`SY\>J'4../S[AY``>=Scmqzy1 +?r?2g][Hu]/[PK[\>N_l][{nI"%9][!9][Ŧ>=9][v4\J +*T>=)"3*T1Ɩsޖ;][S[Y[\>N`-%;"&BB*`IQ!aU8(+>=p"x8S=*8Y?=΀ͥ"&*` 3eefCtefCe``>Ief ff((+Jf+?Jf%f8f1f,(Υ«& +3*/DuGDR`e`r`xS[Y`\>=4A`>Ĩ(+=?I(+=0?=! *ń1 4iv(iS`Y`\>=*8?F=Ua 3QwQ`[```a__>IҪ(EJR?N/` +EL>J%$R>=@G 3TV?xi?`[`[t```a____>I(\Jԃi~?N/`\L>Ji~>=.53BDVy]V`[`[`[c`v``a______>Iê(J݃Ʌ?N/`L>J !Ʌ'>=EL<3Yiz`[```a_^_>J3M{M`[`[ ` `-`5a__^__>JCJ3Pn|`[`[`[```a___^___>JB3n} +n`#`0`ES`WY``Jj+3qv~```a\\>I!ڥ>>N`! +D$>*I/3>=LKUP>'iK>=K>6\K=>?=K3%5;`N`[`nt`{}a\`>I!>=Ă6\?J敖3o2o8`K`X`kt`{za`p\`>I!l>=l7[`'?J8EZyd3rw````:\>=i3`:\>= 3I%I+`>`K`g`z][[[`>=* 8II[M?(+>=j? I!%?`>=0$''?NF][[[IRaVL(+>Ip%yt2`>=2`.«'>=ì[[>=[[LJ]&))2`/?>3EE`[sa_][[[+%`+b`+_>I)5- (+>JDK_X^j?NКa`\Na``\I% a``\>=% a``\I7%C; a`\>=cr a`\>=0ъє$''N;H;^`````SY\4JJ=P`c`v`|S`ҎY``>K>IҬ!ҾҰ(+>=ֆ\``  +>@!5((+(<=SLG\`\j Ӏ[Ӈl[ӊ`>Iӕәӣ Ӧ >=ӿӸ  +>= % ( IAWE(+>=fԆԭR>=㪩*RK>JIP_]coՇ[Վl[ՑY`>Iգ!յէ(+>=Ӆ>@! (+='(J8+3֑֓H֟H`[֢sa_֮][[[`_J< ' _C s   5   3 H ;=?AKBBEFHINOQi k,lmtnpru%yz0{| U_?:v’ +asҐj١޷Bp %Z:?jb+[ 9)2?\Mt=2@(u'::߈@Z" )(3FNL [ ;`[^__=r`;T`[^_a`<`[^_K`8=ģDf`[]_]_]b_= .+[[''= 4+[[''=f/X+`=}}\? }=]_J_=ʔ`[]_JЫ_=n``>I +(+>=+I26`'g'6OT'>N++`N:[˜['';.4UzI! +p(+>E%.0`57`9`'3'hMpYW[^_^W>=oUs`''NpIU(J)??J*?J뜣`'g'<..=EE%`_>I084(+JA+?IRV`'g'6ot'>NΗ++`N:[뜣[''; +.40zI&!2*K(+>EENP`UW`Y`'3'hmKyw{~~W>=0`''NKI0(JΜ_''0??J+?J _''2..8̀==JORU _`>Ndh[j..It|x(+>I`''>J*?=+Iܜ`'g'6'(>NEL5[N.4Npr^++_tN``'3'@xzN:[Ĝ[''cI(+>= [''A#c+1>ENWY`^``b`'3'hv/>//W>=x_''NĆ/Iȃx(J*?=[''RĀ I&*`''<=؀B>JP*?=h[''{؀=././W7J)=՜ڞ ]_\>N[..N(``''7.F8O?_F>IW_[(+>=r+I`'g'6'ݚ>=D_.4?=+[''>CIS!^W(a`'3'7x>=././W7?=ƞˢjѢj``>I쀞5(+>=5+I`'g'6156'd>N~++`5N``'3'@ŁzNڟ:[䜣[''.4I (+J"*?AECLN`SU`W`'3'hk>=`''N턠9I(5>=5I܅H(>=[''B.4>=5[''̓N턡W9Bq?I99W^HJ*??Nɡ[..Iݜ`'g'Be5>= +./0+./W7JC)?JZ*=otB yB\>N[..I`'3'7w>=Ü[''C=㜣[''C.4=./-(./W7?L=GMf`[]_]_]b_= .С+[眣[''=/+`=%%757\? %=J͜`''<..=SS`_>J&#`''<0..6kAk+`_=X].`.c _`>Nvz[|..I`'g'<J*?=œ[''=./ ./W7J)=38K>KK ]_\>N^b[d..Nry(`{`''7F_>=[''I!肦(뜣`'3'7>=./61"./W7?=PU[c``>Irv`'g'B..>=././W7J)?J*=  \>N$([*..I4T8`'3'7OYw>=a[''CuY=././W7?pM5Á=Ǭf`[]_Ɓ= M^``ρ=+9^__`Lz^_`[M^``\?Ƃ§ ntr|ŽɁ=]_J_..O.Mʁ=֩ݪ`[]_J_ˁ= n``>IX!].MgçJq*?Jnḉ=`_>I!.MJ+?J́=#+``>I:!?.MIwJS*?JerywCÉYЁ=xf`[]_]_]b_Ӂ=^__`ԁ= O^_`Ձ=/+`ց=p .`+[w[''ׁ= 4+[[''=> >&^__`4O^_`\?Ӏԁ ځ=CJ|Q|]_JWW_i.r.Oہ=`[]_J_܁=3n3``>I%؀_>N:[['';.4.O&_I3!?7(+>NV]^__`_.Epy{```'3'hNJǙNJNJW>N+__''NNJI__J)???J#*݁=8:@H`_>IS%[Wz_>Nmu:[w['';.4.Oz_I!ȡ(+>Nٲ^__`.E```'3'hȡ'%$)3,$-,$W>N?A+_C_''NRȡ[$Iismtɗwz_J}_''ɗ???J+ށ=ijɶ̶ _`>N޳5[.4N``'3'@.O'+N6>:[@[''S@[UIfrjʍ(+>=[''A@U+>Nƴ^__`.E```'3'hʍ /  W>N(*+_,_''N;ʍD IPZT[˓^+Jd*?=[''Rʍ+=[''..ր+=././W7J)߁= &3 ]_\>F_|=.̖=Ź``>I%_>N``'3'@.O!_N295[;.4NNV:[X[''k@sIU(+J*?N^__`.E۷``朣`'3'hUŀ  W>N+_ _''N/U8IDNH͚O8R_>Idjh(>=~[''B@>=œ[''̓U=[''B..և8=(./NI:./W7Je)??J*=v v\>N[..IΜ`'3'7hw>=[''C h=[''C+.4=;./a\M./W7?+z\ ^̼D=+f`[]_\? =3BF.4+FF[=K^l/L+ll`=q(r+`J`'3'7..=û +˻`JΜ`'g'8..=3C+3`J`'g'9...=8Hr +Qr]%_JTTn_d.=w) x')[>N]_.NǼ +[Ҝ[''=쀼3.N 0` 3/J$+[''Koـ3// 3EЂЪ"nѺ>f`[]_> ]_>؂؃6]_\? M ج> X'X`[],_J-1_NF._>\d|(k|`Jnvn.( >`_J.. yb;fu)u(`[`[`][__;u[1[=e(e`[`[a__`+za_`+Va``+]__>I ;(+>I+8/%(+>IKVO +(+>Ik"o-_-`:-_-`>Jh__?JF__?=%I-"1; M%dny +>Jh__?J__5a__` +#؃q(+qa__`%?J__5a__`$ +#+(+3a__`5a_`;%#D"(+L"a_`V;=s{`[`[]__=5[h5i_+5_+;+3#?`[`[Ds][[[]__>N[b][__h__=} 4+[[`>=(&j_&s_nxJ&(]__;&g0g`[`[;s][__]__JE5]__I__5[ZX-au-;RZ,en,`[`[x][a[_+Ka[_+]__>N][__Ƭ__=뀕٩ ٹJ&%]__;͖՗ꗄ`[`[]_ ]_]__>N!%][__+__=H^ڳcڂiړJv&v}ڳ]__luN?:Iif`[]J_\? N ?(&(]_ ?-4GEG`[]_ ?LSZ`[]_J`d__.. ?N Ns]`]_>NƂ]_. Fނ_.>I! Mnܓ=%n)ܓ?J=Dn?SZfss]`]_>N]_. F_.>IˀnL=偃'L?J'?>EgJg]_JP5]_P. 5[[Y΀.yۤ/ݠ? +(f`[`]_?[1[=#++(2f`[@a__jk`+^za_l`+xVa``+]_>I(+>Í(+>I뀉ީ(+>I"-_-`:-_-`>J=D_?Jqx_?=I"  ީ>J&_?JKR_5a__jk`oީ#v(+~a__`5a_l`#K(+Ka_`?J_5a__jk`ީ#؃(+a__`5a_l`#(+a_`= (P8Pf`[]_=5[5i_+?ӓ۔w#wf`[ ][]_>N ]__F+E6l[;>=TMŀ&XX_Jfm?ĕ̖֖f`[ ]_]_J5]__5[mNm?і +]%_{2%@f`[`]_@\?  @Zfm`[]_Js|__.!@`[a__]_J@__."@%%a_`]_J q_.##@*6fBf`[]_JHLO_.$@kw`[a_]_]_J__.%@ʃօ& & s]_]_>Nlq]_.I}%2]_>J'_2]_?J2_.&@+0n8@``>FOaVl_.>Iiom(rJ{)?J*'@a_\\>F_.=怅'A(@,, a__K__>N2; +]%_B. + IP!^U椑'>=0r\?NK_椂')Cԁ椑'>=愀椂')J#)@13:`[= _Ma__ __>N|K_F_.=獀筃J*@d=da_``>F $_.>I,!21 3CJ=*?JU)+@ipvtv}`:'`:>N +]%_. + I!́译'J'?N`I"#(+B8.('B>DG>=[T$vmd诂')译'>=$ʁ诂')C쁉译'>= =*#$E<3诂')JZhaA,@{-a_``>F_.>IȀ4WJ)?J*-@X X`)],_J.20_.؀O.@]di]_Josi_.9@<(<`>@!%.][NЋ`N]%[. + C`'>=PPWJ,3P:@AJi Ri`JU!_V. + ';@nwC`J!. :/@`]_>J_.K0@CCa_K`]_>J_.:1@HTX]`]_>Jju_.2@~a_K`]_>J՟_.C<@ +_>N]%_!. + I/!74'>=0Kf\?J}')=@uu_>N]%_. + I!π!'>=0\?N_D#>=.f:7!')SP!'Jdkf>@zUU_>N]%_. + I!ӑ'=0۠\?N_ӂ')I ӑ'=05]?JDK3@Z\/ f/la_K`~ !a_+_>F_.>IJ?I!灐(+J?=0 \4@46y?Ea_K`W !a_+_>Njq_+N`*F_.>Iŀ>>=j=x)?I xJ/6j?IB!MFT(+JVc]T?=0k\5@VVa_` !a_+_>NԒ_+N`*F_.>I'/+?0>IDHy>=0c~]?=k=y)?I݃yJk?I!U(+J$U?=0,G\6@[]fk`_>Ix!%|Z`=0'?=Z'N{`F _.>I$.(Z(1J?F?=UaUW=0oyZ.'+7@ÖA˖`:JެC.''GH fYx-}%}b !<4lA@Kf`[]_F@\? C@4>][V`:'јr`:'`:>I_>I"́n('B傘~('B>J4'?JR${[n'Hl~?N],[1[=_;L>=ͫ_>@06_?=ZH7IJr5`~n5['5[Ȅ~AD@؜][`:'ѝ8`:'`:>IUYm">J$1'HA?N`1=𫗀";L>=(!1"'>@_{i"_=7I=ăAJ탞AATGAŁ˅f`[`JA`KA)`LAJ`MAmXӫ]%_NA~I`LVA]%_\?M PAǃ2σ2`>I.IN(L=.T?J.IN(JRA79o=o_>I!.P=0('?@.IN( J(N18_D:.ӫM')=Q.TJ^eTAty~\>I.ӫM'>=.IJN>=.IKN@SWB)8(8(`[`[`][__ZB8[1[]\=ԅ܈ܡ(鈷`[`[a__`+za_`+5Va``+]W__>I]la(+>I}y(+>I^(+>I"-_-`:-_-`>Jh__?J,3F__?=XyhI" y^>Jh__?J__5a__`#^#*(+2a__`:y?JOV__5a__`v^#}+(++a__`5a_`y#v(+va_`]=ň͈`[`[]W__=5[h5i_+5_+^Bgo#`[`[s][[[]W__>N]W__\__=Հ]4ݐ+[[`>=|&_&_nxJ|_Bv~`[`[s][__]W__J5]W__\__5[āqLuq`B’ʓe䓲`[`[][a[_+Ka[_+]W__>N<@]W__F\__=i/큓J/aBYa&|&`[`[]_]_]W__>N]W__Ǭ\__=瀖 J%)3bC(f`[`]_eC[1[hg=u(uf`[a__jk`+za_l`+Va``+]b_>I(+>I#0'(+>ICNG(+>Ic"g-_-`:-_-`>J_?J۫_?= I#"'1 CZdo>J_?J_5a__jk`#ك%(+ᚧ%a__`5a_l`#p(+pa_`?J_5a__jk`4#;(+Ca__`5a_l`K#T(+\a_`fh=f`[]b_=5[5i_+iCz#Ғzf`[ ][]b_>N]b_ +g_F"B-[8>=QJꀘ&UU _JipjCRZjf`[w ]_]b_J5]b_g_5[tlC05T=k.y.t)}=.twD?? _\>= ..t!i*}xD 2]_\>=.wyD22 _`>I!̀ R(.J*?=. ~J#)D7Gs +Ps]%_JSW_.Dx(`J.=szD҉׊ ܊\>=..rWrI. J ?N _".tD.>N;A_C$=O$\V@P=oi@P}w@Q@R+!$.t=.+t=.=sD\\_>I. >=0"('?JKR.tDagl_>Irv. >=0('?J.tQDڋ猔_>I. >=0 ('?I5A9.=sw>=0NX('?J.t{D~%~+a_\\>NFX`Z.rIrv. J?N'_.tD>= +" +bI!܁ +9(.r>=0/.?=8 +bJB +bP!_i +br.tD `J.=s(}Dy~// _ e_`+\> I!ȁ j(+>=0('?=,.>,.rWr=PG jR.Ibf. >@~ _(+Ő~= jQ jP j=. jt=.=.=sWsJ?N_ _QN-7_9 _=MD jQY y=sj jP{ = yP j= Q jI" v _.t>=. jt?=".=)".=sWs~D49|@|C _\>=P.bP.rWr=vpj PQ QN_ QP P=.=.=sys=ހ R쀒 P Q+I. >=%.+tI?CM T.t>=e.n t?Ka %  + + ? hDVf]_][`]%_D R]o_D `DX_+D2XP]_D@`DRRet]o_\?rۀt* RD '_J.D#(0`>I9!P=.(YS.Rr>=0u/.?I".R "..P.R>=.+J*?=*.)=D.&DO.P_=Z.Phb.PPJs) +;IDCTf]_][`DXR]o_+DXP_+DXQ_+\? D]o_J.RDUZU`\>=oi.R&w._~DIOT_>IZ"d^.R(+oy.R.PJ+?J.PD|_>I".R(+..RJ+?J.QD̞ _\>=.R.Pi*}DAA _\>= +.R&._$)}^KEPPf`[`]_JE5Dkf`[]_\? EN\hn],[`:J}D''E+:nf`[`],_\? =E +]%_J9_.EA'A,`_J6:.;9EFR \i s]_]_Jy}'_.Ea_\\>N(`.(YE` pTppW>=+%=0.1p9I=0ak/.?E `J.(Y(ENjЋCۋ`J!. ELL_>I.(Y(=0)\?J:E.9EQZ_b K_\>Iozs.(Y(=0\?=.:EČʍ-ύ-_>I.(Y(=0\?J.%.(Yy9E2;?B K_\>IOZS.(Y(=0`{\?=..(Yy:EII_>I.(Y(=0\?I.(Yw=0 (]?J7B.9ENSXn[Xc``>Nv}(`.(YE`$$$W>I.$9(J)?I!(.(Y>=0 /.?JH*E]bf=gfma_``>N(`.(YE`///W>I!Ԁ./9J*?I!(.(Y>=0"/.?JW)Ekpq-sqya_``>N(`.(YE`99˂9W>I߀.99J)?I!(.(Y>=0",/.?Ja*Evx a_` !a_+_>N(`.(YEԑ`݃O3O胑OW>N_.O9IJ")?I8!C<3(K.(Y>=0]g/.?I!(+J?=0\Eqyqa_` !a_+_>N.5(`<.(YEHQS`\Uyca^ijiy>Nx_.9ImJ?I!ł(.(Y>=0/.?I!)"(+J2?9?=0Gb\Evxa_` !a_+_>N(`.(YNΔ@_+N`*E`  H  H HW>N(0_6.7 H9IAIEJ >I^b 5>=0z]?= 5)= ' ?I! (.(Y>=0/.?IPT 5J`g '?Ir!}v(+J?=0\Eʖїz՗z`:'`:>I.(Y(J'?N")`5`/5[?=!.N!!J^le!AEa_`]_Jq_."cEϗۘ  `[]_JO_.E["[`[%a__]_J6:f__.Y# ÁE`lu`[a_]_]_J__.#kāE+ǚ+ a__ __>N(`.(YI#(=0$?\?NRXK_^.9Egpr`yw$D{#$D$DW>=$&#Ȁ$&.$D9I!#(.(Y>=0/.?J"$&ŁE02w9w`[< _La__ __>N{K_%)N(`.(YE`ń%%h%Є%W>=%T끚%4%T.%9I!%h(.(Y>=0(2/.?Jgn%TƁE|`]_J,_.&^+ǁEɛ՜*~ޜ*a_`]_>J_.!&ȁE/;t?tD`]_JNR,_.n'ɁEya_`]_>J_.'TʁEߜ`)],_>N],_I#'>=5'5],_1A_5[EC'(N.(YW'>=i'v._~.(YE`(R.(Y(R(RW>='Ȁ(R.(R9:J'ˁE]_>N ]_g_E&/1`86)':.(YB)'CB)'W>=VO)^._)'9Jnu)́E _\>=.5`.(Y5`.(Á)WW)):́Eٞޟ ]_\>N`.(YF6!_,*N>@"QJ.(Y(T*e0Zd/.E=.(*eWW=.*e*:=*eā*eW΁E՟ڠ࠘``>E` +Z.(Y+Z+ZW>I%1-..+Z9(4+@>=L.ǫV+Z[Y+ZWJi)?J*ЁE6ǫ'6,`7y`\>NFM(`T.(Y@ivl,'gq@,',4@,4v,GNB`,4y,'Eѡ`,4܄,ꀇ,G,無,W>=.,y,. ,9:=.(,%,Gy.,WӁE;@KQa_`\>=h.ȫp-*ԁEa_`\>=.ȫ. +)сE΢Ӥȫڤa_``\>N],_1"_N.5(`<.(YEHQS`ZX.\.d.ed.W>Nu}_..9I.[/(.p>=Ƃ./;?I!탣.(.(Y>=0/.?IF!ZSJ.(Y(b.(Y>=w. .(Y.=.(.(YW?ՁEѤ֤ ۤ\>=.(WցE* *`[],_J5__.ׁE.07:_>ICNG.(Y(>=0\w\?N_..(Yy9=.(.(YyWJ0؁Eӥئ'ܦ'a__=r`+\>=_.5a__=r` 1V#1(+ҁ1a__`ҁE,7ʫBC=[Fr[`>J &1] +[&1] +[فE `+\>I 2X(+=2X,?N>E(`L.(YCXf_2w>Nw{0`}2X 2=22yN_.29=.2.29:=.2ƃ3 :ځE +GG][`_>J$/_.ہEL]'W^'g s],_],_>Nx],_5],_1_5[4(.(YW3Ё(YW4=3 .(Y.O=偨3 .(Y3(Y +3OJ3܁E,4;@`Ly`+],_>N\g`n.(YIz~4(+=4邩5?=4܁4邩5Nݩ(`ꁩ4y4N],_5],_1 _5[ 5(5fW5E$-/`645 85f@5A@5W>=SM5T5].d^4Wf59:Jt{5݁E%%`y`]_>=66.(YJ,_.66ށE*/:?`Jy`\>=`p7w7,.(YI7,w7>=.ǫ77,?߁E˫Ьy٬y`y` _+\>= 7 7*.(YE7@B`D7MK8O7T8UT8W>=e.f8k7:E~C C`y` ]_`\> =88.(YN(`8y8I(3,8(J9?=Pa8'N],_N`I%傭8],_>=9Z8],_=9l"8>=@9ZeUL8Z8*=9lI9lW8w…9Z(Y>=0^?I9l8>Ecln`wp8y~|:f^:f:fy>=.8W:f9Z9lW:f9:>E`퇯;8;;W>= +. 8W;!9Z-"9lW/;9:EHMY^`iy`z ]_\>=;ׁ;.(YI!%ւ;][>=; ;?N-:`@<;yB;NQ^`l`;( Ix|<^^<>N`;W<=. ;ׅ<ǂ;I<^w<>=-.ǫ7<ǁB;?>Ngmi`|oIˁ>R=>R?E`>R>.(Y>>W>I.>9( >EJ)0>?J=DWEOS]ca_`y``>I?\=?\?E`?\?.(Y?ς?W>I〴?G.?9J??J WEU#+ `9`+`>IG"QK@\(+b\@\^j.(Y=r@\.(Yy?E`@\@σ^@@σy>I.@9(@OJ@?J딃WEa_`$`+`>I2"<6A(+MGA^U.(Y=]Aqj.(Yy?Ez`AB^BBy>IA.B9JB?JєWEܶ` _\>=$B..(Y'IDNHB(V.(Y>=f.jBJz?Iq!%{uB`=0B?=.(.(YWW=. ʀBW.(Y.B=.BB:E vv`_>N*1_7.8C9=D.ǫNC[UCWJelCE{` ]_\>=Dp.(Y'I"!%D}]['D}.>=@D}TKD}?Nl|`~D}( =q.(xq.(YW{DWI!D}( (D>=;.(B;.(YyEDW=0\f/D}?=. DpWD.(Y.Dp=.DpD}E` ]_\>I+%8/F*],[>=I. RF_YFWjaF*( rF*>F_F*>=.5`F5`FFWFF:E!!]_J_.E&-lA5l`:J;HD.''KSQKO!"E""#B#%&@&&'6'()*0+",--.;00@01812:3r346y778};>'?)@1AaBCDREGG>Gv=Fu`[`[]__\? FFƆF][[[`:>I2H>J>'8?N]d`jL>=H;=I'wNȄ`)=ހH4慙+[[`>I!In>=I'?=5In*=SLIYI=leI'=IIx=I'x>@ܫH҅=7IJ*81IAFKR]U]V[[J\\JF Ы3?][[[M][Wa[[eKa[[\>=#{K(+Ŋ{K+a[[=#K)(+ŋK)+a[[F[K >=ɀJ͂KK߃K)KnFѫ][[[][][\>N]%[L + N+]%[4-L* + NHS`aUL?'Nv`L`'C"LL>=ҀL ߃L?')L`')n=L L?'=2LOAL`'If"jLxL>=0'?HJJKMpFQ`S`[`[`][__\? F]_F`_Fƍɍ _ K_\Fݍߍ`_F} \F`[`[][__Ji____.FЎՏ<܏<a__ˁK\\>F_.ɬ>="OD#Od,.-OdFAFLW s][__\>Fd~k_xrO€{>=.OOOm F-5-K``>Fҏ_.ɬ>I.Pd(PIJ)?J* +F24?B _I a__>I[_.kP>Jy.P?J5_P5_PՀ5\.QQ/Q/ FÑ _ a_K_ a_+_>I. Q>J5_#Q5_0*Q5.6Q5\".QބQQ?IG!TKQ(+>Je5_qQ5_xQ5\p.RaRrRr?=0Q'' FӑؒQ7Q a__ˁK_\>F _.ɬ>=).*S71R8SA.BSFVs2{]]__>J.ɬ]__4_]__J__S.S FȒԓߓ3`[4`[a__ˁK]__][__>N][__2'__F/J8_D.ɬ>NV\]__g^TDhTq.rT=TvTTKnJTvFŔH1ϔH ]]__\>F]__ UM>=%.,&Uq93UqKFMR6]6ca__ˁK`\>N.],_1_F_.ɬ>IÀUـV.V=⁔UV;?F_U>=!.(V{F;@mKmS``J[`[.ɬniVFqy(`J.ɬ( F `J.ɬ FCʕ`J.ɬCF]_J$__.F#*QA2Q`:J8@.MNNANxNNO&OP+PQoRSbTU/UVVW/WiWWXF44`[`[]__]1__\? XF@`[`[]_F .][__$F .][__\?YB F2($2`J','..(}F6?V GV`JJOJ.. ~FZcCn`Jqvq..CF_J....{m F_J....{m!F֛ܛ_J....{m"F > +>]%_J0__9..YpYYZ$Z}Z[/[u%F֜ܞq`[`[`]%_(F% ݫ]%_)F> .][__*FHX_+0F\\q|][__\?)\2(\2{ + \,FQȞQ`>I.ݫ('>=...).ݫ(')m*J)?=,.+*JA*.FV\o'do_Jgg.*\]]?1F͞ܢN`[`[`][__9\? 3FR`cf _m K_\>=0z'E4Fc c s][__\>=0#-'E5F \>=0'E6FBDJR`_>=0]g'E7FLL _ a__>=0 'E]]^D^y^_ :FW]`[`[`][__=F .][__WF][__\?=_ ?Fʣ֣`[`[][__J..=__j@F +% %`_J ..=!`ImAF)7f:f= _D K_\>=UQ..=V`]`nBFkpv s][__\>=..=`uCF \>=..= wDFѤӥޥ _ a__J..=a atEFO*O2``J:?:..=KalFFSX5emK``Jw|w..=5bCkGFa__ˁK\\>=..=bxPF `J..= ~QF+C+`J!..=CRF/7L(>L`JAFA..=(}SFP`qeq]_Jhmh..={HFuw}`_J..=cvIFA`:J..=ATFɦ٦]_J..=|UF'2']]__J ..=2zJF,1x1;xM 2]`\>=a\..=1&lld]]__pKF}3`[4`[a__ˁK]__][__J..=__e}oLFRR _ a_K_ a_+_J&+&..=2e7eIfqMFW\7eh a__ˁK_\>=..=7ftrNFa__ˁK`\>=..=fs_`,`|`a1alab%bybc cIccddUddeIefVfg XF`[`[]:__]1__gYF`[`[]X__]FGGvZve][__\? lWrh[F{`[`[][__J]__..=__jh.h^G)8Lf`[`]_aG8[1[cdecGAf`[]^_=5[ +5i_+dG܅A#f`[ ][]^_=5[5i_+eGنAf`[ ]_]^_=5[5i_+gG-=mK`[`[U6]^_]^_Jfj__zj8hG`[]^_iGGIVTV_jG7_kG16G>GA K_\lG K_\mGԍٍ܍ K_\nGK``oGRWs]sj ]_\pG((a_`\qGːa_`\rG>CJ HJ\hiFijjjjjjk k9kekkkl5lVsGOUC]s_]s[`vGX㫐_+wGX䫐_+}\? zGq嫐q _ _\>=.䫐m;w=.㫐m0vI !m0(+=,#m0䫐&,._w?IB!KFm;(+=YTm;㫐&Y._v?{Gv{AA\>I!.㫐v(+=.㫐v䫐.䫐ww?I!.䫐w(+=.䫐w㫐.㫐vv?=.䫐+w=).㫐+vmmn~GʓЖf`[]s]~_G?X_GKKoaog_\?n K}G l_\>=˭_o,嫐..䫐wzGEJQT l_\>=~a_{o嫐.㫐v.zG_>=.{J.G/O=_qa.嫐.(.䫐wzG;@HK l_\>=X_uqx.嫐.㫐v.zG_G𢡄™_J.GљUU]~_>N]_& .䫐w]_J/<6r쫐GZt]~_>N]_&.㫐v]_J̀r쫐qqAqr r0rars/Gf`[]_GBB_]_\? -3s<sGGLRU l_\>=^.fsIn!yr.(+=5]_.t,t,񫐭W?G l_\>=.tI!.(+=5]_.停tѣ停tѣ񫐭W?GCC_>=.+=".{J18.GHJP_>IY!d].(+=5]_m.ttuttu񫐭y?J.G쫐ҝ]_>J.stquuduv.G/5af`[]_Gzz]_\>=.㫐.v=.䫐.w +vGD쫐,D]~_>J5+G_>=0Ġ\G &_𢡄/__>=05P\vvw/wcGf`[]_]^_GPX]_+Ga`ЁGww\>=._. wG#3f`[= ][]_>NV[]^_a_F}l[xA>=x\&x}_lJ&x\]_Gf`[ ]_]_J5]_ۭ_5[y xy G88`[]^_J$g__.ɁG=|.y=..񫐭WG K_\>=.zR=..񫐭WG PP K_\>=(.1z==.J=.񫐭WGUZ`m ]_\>F}K_{0>=.{K=..񫐭WG橇7_>N]_&* .㫐v]_N?F_RH{ƀ=a.na.񫐭yJv}{G.._>N]_&.䫐w]_N_|i=..񫐭yJ$|G38>F``>Njp]_&j|r.䫐w]_C!}.>N`́}𢡄(}I!.}>=0>H/.?Iy}}l>=}=..񫐭yJ)?=}&ꁫ}䫐w]_J*GHȫ H&a_`<`\>Nms]_&mu.䫐w]_C!~.>NL`΀~bՂ~𢡄I!.~>=0AK/.?N]_&~䫐w]_I~w~>=~=. .񫐭y?=2~:>GMR]ca_`\>=z.ȫ)Ga_`\>=.ȫ<*ʁGQQ_>N ]_& $.䫐w]_J3E:𢡄ˁGV\a_>N]_&.㫐v]_J𢡄́Gͯӱ$ڱ$_>IX\pf.䫐w{.㫐v>N]_&.䫐w]_J耰𢡄?=0]ÁGͲ]~_>J .āG´ܵ]~_>J.́G d (d`>J.6J@.䫐wU.ŁGin s\>=|.䫐.w=.㫐.v=.񫐓ƁGZ_6k6qa]~_\\>N]_&.䫐w]_C!d.>N(0]_&(2d]_NZ_]_&Zia䫐w]_=UOIVIfj.zd>=&d䫐w]_I!.҃ؒ>=0/.?= d(΁G;] +f]_>Jlw_.ǁGA`:JʬD.'w'xxxyMyyz4z{{|C|~Bm=+m+сG@ f`[`]%_ԁGPX]_ՁGxX]_+ցGX_+܁G$$]_\?Ԁ&䫐w]_ ؁G).6`>I?CM.Y.>=m.+=.+=.+J*?N]_&.]_I !".Ԓ7*В>=0HR/xn.Ԓ?=.У𢡄=.&ˀУ䫐w]_J)ځG@'@_J.Z݁GA.A4hf`[]_]^_GA`7GAXӫ],_+GAԫ`GAի`GA` +GBoBoCBxCB~`+\>IB"BπB(+BBB>=CCIC7!C<CH>=CbCtC?@CCCC=C.ӫC._C Bo GFFH#F&Hf`[F0 ][]_>IF@%FMFD],[>NFbFi(`FtFk],[(YNFF]_F +_FFW@FFFȂF>ӫ(YwFFFEFFF`FFFGGGW>=GGG>ӫG&GG,G$],[G-9_:=GEG?>իGMJG[Gb>>NGG`GIG%GG][>=GGG][(?NHH]_H +_H(FH9HYHD[HO>=HjHc&HrHr3_JHHGIMIUIIaIf`[In ]_]_JI5]_I +_5[II׀IGIIIII`[]^_JIIg__.GIJJ3 +JJ3]%_JJJ_.GJ8J=KJDKJJa_\\>NJbJt`Jv.EJJJ`J.ԫ!JJ(J.իJJJJWJJJ.ӫ(Yy>=JڀJJJ.ӫJ9=J.KGK!K*KC K2KC`JK5K;K5.ԫ(K>.իGKHKPK(KWK`JKZKjKaK[.իyKc.ԫK{KtKm.ӫ(YyGKKKKK_>IKKK.ԫ(K.ի=0KKŠ\?JKKK.ӫK.ԫ9GKKLxKLx_>ILLL.ԫ(L.ի=0LL3\?JLDLQLK.ӫL^LYLS.իyLoLhLa.ӫ(Yy9GL}LM"LM"_>ILLL.ԫ(L.ի=0LL\?ILLL.(w=0LL]?JM +MM.ӫM.ԫ9GM'M)MM2MM7`_>=MOM_c.JMqM~Mx.ӫMMM.ԫWMcMMM.ӫ(Yy9GMMNMNM`)],_>NM],_IMM3>=NP5],_1N _5[NN~(N.(W~>=N4PN?._NG.(=NZ.뫐NgPJNrNyPGNNNNNN K_\>=N.N9GNNRNRN ]_\>IN%ON],_>NOO$],_O&],_NO:OC`OJOEā(YNO\Oc(`Oj.(IOxOOO|WO^OO.ӫ(Y>=O.۫OOWO=PP.ӫ P$P3P,WP5P?ēO=PQ.իPWPQ.իWPZ>NPP`PPP.ӫ(YyP.իIPPPP2>=Q Q.ӫ Q.իQ"Q.իWQ$Q.ēO=QB.իQHQB.իWQK>NQtQ}`QQyQ2=QQ.ӫ Q.իQQ.իWQ2QēO=QQ.ӫ Q&QĄQ2O=R.իR&=R=.ROR=.W>FRfRm_Rx=R.R,GRRSRSRK``>ERRR`R.ԫ!RԁR(R.իRRRRWRRR.ӫ(Yy>NS S_SS.ӫS9IS&S2S*@(S5>=SF.SN=SZ.SlSZ.WJSx)?JS*GSSUwSUwSa_`S`\>NST`T.NT#T%`T'.ԫCT2!T;T9`(T>.ի>NTOTW_T_TY.ӫT``9NToTv`TxT,TTT=T.TAITՅT>=T`T.T`=UAU.UU.W>=UD`UPUKUI`WUaUZUS.ӫ(YyGV9V>VVIVVOa_`\>=Vf.Vs$)GWHWMWWXWW^a_`\>=Wu.W*GWWXj WXj\>IW!WW.ԫ(W.ի>EWWW`W.ԫ!W܀W(W.իWWWWWXWW.ӫ(Yy>=XX.ӫX+:=X3.ԫX;.ի=XL.X^XL.W?GXoXvXAX~X`:JXXD.'w'xGXXXXXX K_\>=X.XGYYYYYY K_\>=Y.ԫY2Y-Y'.ԫyYCY<Y5.ӫ(Yy=YSYM.ӫYT.ԫY]:IYhYrYl.ԫ(Yu.ի=Y|.ū?=Y.YY.WGYYZYZ_>IYYY.ԫ(Y.ի=0YY\?=Y.ZY.WNZZ_Z'Z!.ӫZ(.ԫ9=Z:Z4.ӫZ;.ԫ+:=ZN.ԫZbZ]ZW.ԫWZsZlZe.ӫ(YyJZ}ZGZZ[z7Z[z_>IZZZ.ԫ(Z.ի=0ZZנ\?=Z.ZZ.W=[.ի[[[ .իy['[ [.ӫ(YyN[3[:_[B[<.ӫ[C.ի9=[U[O.ӫ[V.ի+:J[i[p?G\\ \C竐\\C\``J\'\?\/\(ׅ\9\2׃y(G\\]諐] ]]``>@]*]#]w]#]-=]4]]K]E]>]yE]T>N]i]t`]}]v]]]]yI]]](J]]]?=]]]G^^$^^6^^;`\>I^\!^z^`(^}.>=0^^/.?G__ __$__' _\>=_<_6.ӫ_=.ի_F:=_S.ի_g_b_\.իW_x_q_j.ӫ(YyI___.ԫ(_.ի=_.ū?=_.__.WGa a$d +a+d +a0e``>NaBaG0`aWaPaI.ӫ(YyNadar`aa|au1ya~.ԫaJNaa`aaa.իya1aJIaa҂aa>Nbb +`b 1Cb!b#b!J(b&.ԫ>Nb;bF`bPbKbIJybRJ=bfb`.ӫbgJbrbl.ӫbs9:=bJb=bb.ӫb.ԫ+:=b.ԫbbb.ԫWbJJbbbb1WbJ>=c.իc'c"c.իyc)JNc9c;`c=1CcK!cTcR(cW.ի>Nclcw`cc|czWcJ=cc.ӫccc.ӫcY9:=ccY=cc.ӫc.ի+:Jcc1Gd:d?eRūdDeR\>NdUd^],_dd._dzdsdl.ӫ(YhNdd`ddd.ӫ(Yyd.ԫ=dd^ dd.ӫd.ԫO=dd^ dddWd.ԫe.ӫO=e.ԫ=e".իe1e*.ӫ(Y=e=.ӫeF^GeWe[g 뫐egg ep c],_`>@eee(Y^e.(eeIeee.ԫve.ի>Nee(`ee.իye.ԫ=ee eqe.ӫf.ԫOJffq>Nf8fF`fVfOfH.ӫ(YyfX.ԫ=flfe fxf.ӫf.ԫO=ff ffʁfWf.իf.ӫOJfff.իWfGgAgFh۫gNhgS`\>@ggq^g.(gqg=ghgWhhNh$h0`h2h@Nh^hg],_hm._hu=h.իh.뫐h=h.ӫh=h.ԫrjr; +e\[!gK3Y.6  GiBiHkf`[`]%_Gi ]_Gi A`Gi `Gig`GiX_+Giijijj]_\?j j<j6իjfj`jjԫ iGjjj'jj_Jjj.Gjjkjk`>=jj.j.Ikkk .g(k.A>=k$.+Jk;*?=kS.kkkek^.ӫkl.g9=k|.gkkk.gWkkkk.ӫ(YyJk)>HRf`[`]_I\? ,H K_`HƄn΄``H`_H K``AH.6 +66]%_H;BIGI]_BHNV\(\\`CHaj r`Ju|u.(B(DHC`J!.(B( H`[]_J__.!H܅D D s]_]_J'_.> +"HIUa`[]_JgkO_.#H \>=..-%$H ć  ]_\>F_=.%Hv v2 ]`\>FBN`Y;=c.jW&H{ ]`\>N6?=]_A.FNiZ`_>=zq=.%'H[[a_`\>N݈=],[1[F_.>I=r=,#X0r;?=D.NX%(H`epva_`\>N=],[1[F_.>I!΀=⁉;?=.%)H &8s]``>FE]Q`V>Ie!j.nsJw*?J)*H s]_]_>J5]_.5[ԁ22+H +s]`]_>N%]_'.F4L;_.>IT!_Ynh=yr?J,Hb bs]`]_>N܋]_.F +_.>IKn%=6/l=?JQXl-Hgo6u6|`)],_>N],_#5],_1_5[8(.(BW8._.(B],_N`F_.= +5`5`WŃ:J%,.H;GM`[Pa__]_JgkO__.CEHtt_>I.(Bw=0ڠ]?N]%_. +AI! ɑ'=07\?NJQ_VSɂ')Jcj +/HyA`:JD.'w'x0H(a-a3a_`]_JDHq_._1Hfr{`[a_]_]_J__.2Hŏʐѐa_\\>F_.=E_3HJJ! a__K__>NPY +]%_`. +AIn!|s‘'>=0\?NĐK_Ձ‚')C‘'>=&‚')J:A4HOQX`[[ _ka__ __>NK_F_.=ہɃJ5H =a_``>F*B1_.>IJ!PO<Q_J[*?Js)6H`:'`:>N +]%_. +AI!ꁒˑ'J'?N`I3"A7(+BVL('B>De>=yr$˂')ˑ'>=ւ$聓˂')C +ˑ'>=' -=HA$cZQ˂')JxA7H-a_``>F֔_.>I怔NqJ)?J*8H)b-b2`]_>J;F_.\9Hgs|a_K`]_>J_.:H˕זۖ`]_>J_. +k;H!t~*t0a_K`]_>JEP_.kûFHy  _>N]%_. +AI!'>=0\?J')GH_>N/2]%_4. +AIB!JGė'>=0^y\?N_D>=ė')΀ė'JF*B1_.>IJRN?SoJ]do?Iw!{U(+JU?=0\=HϘњ0yښ0a_K` !a_+_>N _+N+`*F8P?_.>IX`\aK>=u)~K=7)?I7J)?I!聙(+J?=0!\>H57BHa_K`Z !a_+_>Nmt_+N`*F_.>IȀL>I݃8>=0]?=4*=L=N8)?Ivz8J*?I!(+J?=0\?HPP`_>I!%`=0$.'?=]n'N{`F_.>Iǀ(jJ~?=jjW=0#.'+?jM}&d>zv-|1i'u0¥MÝq!,JHSf`[]_N\? ILHQQ][`:J!.DC'w'xCO< `[`Q< _R<Xz]O_+S<X{]O_+U<_\?Q VI&0*.Ic(+J9@W?NQVz_X.dNio{_q.dN'_.IcN +`AC)>=.҃ڀˮQjnI섋w>I ڇzR(+B?=$+.A<4ڇzRˮQFjnIT]Xw>N]O_ڇzR=ڇz̅κ{SR=ᅌκ{ڮS=&κ_I&!ڇzR(+B/??=e_ÇzlڮR=}Ã=&ڇzR_IĄ>I߃ڇ{S(+B?=. ڇ{SˮQ jnI.72>Ngk_&gumڇ{S_=ڇ{zRS=zڮR=څI탎ڇ{S(+B??=0+ͬ{8ڮS=IͬP=a&askڇ{S_>B=ͬ{ЃڇzRS=Çzڇ{SR=ڇz .d{SR=#ڇ{2+.dzRS=<.IDڮk=YR.d{+S=rk.dz+R=. . `W`JpN'_C!ȁzR(+>Nz_&zR_=z '{SR=$'{,S=;E'JU\q<{{ __>N'_ҵC!ׁȇ{S(+>N{_&ȇ{S_=ȇ{& zRS=82z?ȮR=NȂXJipr< __>I.Ic(+J+?N” +`.ӋoI!ごӾ(J+?N_.Ic=..^y^I=LGA.IczR(+>=].I&]ke.Ic{S_k>N{_&.Ic{S_=.I.&.IczR_qk=nh.Ic{vԂS=.._W_Js<[`kq _{ +`\>=..^W^=.._W_I.Ic(+>=.I=kJ?I H>='"=z..IcR=@;={NH.Ic{SS=a[.Ic{+S>=={.IcS==z.IczRR=.Icz+R=.I=kgI .Ic(+J+?=&.I..8.IcpkJDK.IchInxr.Ic(+J+?=.I..IcqkJ.Ict<řʚК\>=.I+k=.^=. ._W_,Q̤ Jѿҕkׇ֗w<G`[`{\? yN=ۙ&_&_xJۙ<$3`[`[>s][__Ta__`+rVa[`+]}__J5]}____܉ܤ5[Ãɀu<Φ֨e`[`[][ a[_+"Ka[_+<a__`+`Va[`+]}__>N]}____݅ݠ=Ӭ€QasJ<©ʪ`[`[]_]_a__`+4Va[`+]}__>Nhl]}__r__yޔ=޷WhJ޷< _ _`J.1<Ia!f.MpߋJv+?I!.I(+>N +`.&ߋ_oIɁ(>J.IKX??J+<#`_>I.!3.M=YJC+?Nlt]V__v.&~~Y_rI!(+JKX?J+<ˬٮ+ܮ+ _ K_\>I +(+=0 +?N +`. +oIT(>=.IKXJ?=.Z__ +"Ts<02=@ _G a__> +IYa](+=0jt?N +`.oIN(>J.IKX?N`._N`. `N17K_A9 +II!_M(b._>=0~/.?I!Ą(. `>=N.o@!RMN(MV?=c.sZ__NsJ< s][__\>=ۀ܀4_K_`>=.x<'O /O`>J5C=.I(+N]%]O_ˮ_.C'>N).]V__&)60')]V__=FELG=ˮQVQ=KXJ.^< \>=.t< +ʳ +``>J".M!.&!_o(<5!)K``>N;A`*NRd`f. `Ow|a]V[[`]V[[`>C!(+>IʄKX(J)?I!(. `>=0!+/.?I`"!oid{S(+zۀ&{S]V[[J)?=&zR]V[[J*J烴ۀ.I<1 1]_J_.<6FwMw]_JPT__.<ѵӶ۶_>I.I(+J+?J.gˮQI.I(+J+?J.hˮQIckgh(+=0t~h?I.I(+J+?N +`.hoI߁ɀJ.IˮQ?N ]O_.IzRI#,'(+J5+?CF!XRM{S(+>=iup{SJˮQ<!q!.q1 __>I<D@(+=0MWe?Ioys.I(+J+?N +`.oI!wJ.IˮQ?N]O_.I{SIs(+J+?C !1,'szR(+>=BsNIszRJ^jesˮQA#n;R{YJ=b.%z6Ic6!6_PK6 ` <Ac&AcY][_]O_'_\>I@-@<@6@1΄Ic(+J@E?N@U@]`@d@_Τ@ko=@z. @@Τ `I@@@$>=A.%A%AA΄Ic{S>=AJA@.$ASAN΄Ic;+@@Σ_ <AhAnA'AvA_>IA|AA.ܫ(+JA+?JAA.(A.ܫ<AAB[%AB[A ]O_\>CB !BB(+>=B0B&.$B4;=BABMBHчzR<CCD)CDC *]O_\>@!CC.$ CC=CC.$ CICD Dr(+>=D.%D;D5.#Ic>=D\DV.#DoDcrˮQo=D{.%DDD.#Ic{S@!DD.$ DD<DDGDG`>ID!ED.(E E.#_>=0E(E2/EN.#?IF[FiF_.$ >=Fz.ܫ+JF*?IF"!FFF.# `(F. !FF.ܫ(+>=F.)G.ܫ?=G.ܫG6G,.$7I=GH.%GmG`.ܫ{SJGy)<GGG(GGG ]O__.HX<GGI+`[]_<HX#][_]O_<H%H%HFH:HFH@#][_]O_\? H%<HJHRHh(HYHh`JH\HbH\.#^<HlHuH H}H`JHHHH.#^(<HHH +HH]%_JHH_H.#<HHIHI]_>NHI]_I_&I&I&I .#e^__~`I9I3.#Mf=IMIIHI\IV.#^^=IlIhHIIxItH,II.#IcJIIHd3<IIJ-`[`[]_Ł<JX.]}__ˁ<J J J/J$J/J*.]}__\?ŀ J ǁ<J3J;JP(JBJP`JJEJJJE..ţ^ȁ<JTJ]Jx JeJx`JJhJtJmJh..ţ^(Ɂ<J|JJ +JJ]%_JJJ__J..>́<JJK.`[]__с<KKKPKKPK?][_]O_\? KFKLWρ<KTKVK(K_KKr ]O__JK{KK{ˮQҁ<KKL/`[`[]__ׁ<KKL KL K]}__\? LL MՁ<LLL(LLL/ ]O__>NLSL[0]V__&LSL]]V__JLgLvLnKX|؁<LLM1`[]_]O_݁<LLM(LM(MY][_]O_\? MM#kށ<M,M,M&MJMMsY][_]O_M{'_\? MMMہ<MMM(MMM ]O_]O_JMM4 +]߁<PP2f`[][_]O_]_<PP3f`[]_]_<PPj4f`[]_<QIXI]O_+<Qj ]O_QwU_+<Q^__~`<QM^[`<VVVVVVa__`+V3Va[`+\?5a__`Vd#Vl(+Vo_a__`5a[`V#VW(+4VVVV[`JV%VV_Wa[` Vv<XXZ#XZf`[Y ][Ya__`+Y4Va[`+]_>NYeYl]_Yr_Y"Y?FYYY[Y>NYYl_&YY_=YYaYJYYa<ZZ[[[f`[[ ]_[*a__`+[HVa[`+]_J[l5]_[p_[}K[h5[[[[8<[[\[\`[]_J[[ɯ_4[[\[=_[r_`J[[.&[[O_&[[[_\.M<\\\P\!\P`[]_J\'\+__.\H.<\T\X\\`\\c j_\i k_`J\p\p.\|E\R<\\\ +\\]%_J\\_.<\\\(\\`J\\.^<\]] ] ]`J]]].I(+<]!]*]EC]5]E`J]8!]>]8.I(+<]J]P]]V]_>I]\]g]`.^(=0]m]\?J]]].gˮQ<]]^]^_>I]]].^(=0]]\?J^^^.hˮQ<^^ ^^'^_>I^-^8^1.^(=0^>^Y\?I^j^u^n.^w=0^z^]?J^^^.IˮQ<^^_%n^_%^``>J^"^.M___ .&___o(<_*_/__2__5 _`>N_H_P`_R._YoI_g_s_k0(J_y*?=_._U___0sJ_)<__`C_`C_a``>I_!_.M`J`*?J`!!`8`(.&`0`0_r(+<`H`Ma`Sa`` ]_\>F`p``w_`>N````.`oI`!`ł`(>=`.`U_``s?<aa"aa+aa= ]`\>FaManaY`ad^>Iavaz.Ma=a.&aa_r?<aadada ]`\>Nb-b75]_b=_bM.bZ.MNbnb`b._Fbbba`b>Ib!b؂b[(b._>=0c/c9/.?Ic"c.Mccc.&cc_o(>=cځc cc.IˮQ?Id@!dUdNdD ^(dX.^>=dh.Idzdp I=d.dd ^^=d.dd._W_?<ddeedeeda`_>Id!d.Md +%Je+?Nee +`e.&e$e$ +%_oIe1!e:e5 +c(Je@+?JeQe^eX.IˮQ<ejeqfEe}fEes]`]_>Nee]_e_e.e.MFeee_.>Iefe nf  h=ff #f  h?Jf4f; #<fJfQg$ f[g$fhs]`]_>Nf|f]_f_f.f.MFfff_.>If!ff nf `=ff f `?Jgg <g)g0glg5glg= s]_]_>JgJ5]_gQ.5[g[gY gb  <gqghgh]_>Ngg]_g_g.g.M=gπg g.^^=gg Ig.,g.IJhh  <hhit,hith ]O_]O_>Ihhh](+Jh+?Ji5]O_i U_i"i]ˮQ5[i/i-zi6.,iEi@]zRR5[iSiQ{i[.,ijie]{SS<iyi~i ii\>=i.t<iiiii]_Jii.<iijAij`:JiiެD.'w'xg4_W6  +   b3P@V9],[1j[;;@^6N^O=[Rr[`JXZX(];7=[`Jƀ%z@Z:ɠZ``>E`ꁟ쫗(YW>Ih3"49J9)?JL*@>8ɯ>][],[\>Nա9`7PN+5:`N|;`N<`7dN=`N>`N(`N`N]%[ * + C"N _>I! +'J?N`:$  +')=$9(Q ;=3:3WIB=Q (^WK=Y ^Y WNp?`:N@`:N*A[+N8AB[+IK!SP +'>Ieoi v|r_W~oJ?= &97I`:= &؁97I`:>=  +')=  WI !(% +'>I<F@ vSI_W>=hb9$zn ;J?= $ = &܁97I`:=W  (^W>=/=: +')=L QL W@ C +'>= = +')=" '" WI3=7 w?>C"w낪Nyy w_>=7&7>7y&>[TGA97I(W]``=s xs y=9'H;J?= $ = $ =#WW<5& (^WP> (^W[h]NݬC`:+I w9(YW +o>={'H=070WG:WI?C"wN$9(Yw&_>=7&7>7y&>[TGA97I(W]``Ikwo{(+B>={'H=WW?I!{(+B>=9{;?= 9  ;=)#9- ;N`* I5%A98^__~`>JY`8^__~`?J9w0/eTQZSHsMXsX[]P_*gmghlnpsTvKwxɬP˓'ؼ _uLj8H + FI "<cꁗϝȁG΂ #=[ HIJKLMNOPQRST JU`[^_V \ KW^``ˁK [ KäX^[ۯ [Kw`Y^```y\LZ^\O7M []`:[:M\ [;M] [PM\epgph`[>Isw._ X>J.` YmI!%`:>J+>N[L.] ;&`:I#O2=;D.G &MM`:J?JY`RMu}(`J#._ X.` Y(}.a H(Y`SMŖΖ ֖`J.(R(TM C `J.(RwUM#(]`:>I.2._ XJ?SF.` Y{?J]dg.VM][>I._ XJ.` Y|?J؟@`:[.a H4 V[[J.!#>?M!" `:' K[\>I48._ X>=YM.` YZ!da!qnIsw.!dB>Nb[.] ;=M!̀!d!qN-[.\ :I! "!>=-M:"D!d+?>=~.c I!d!qn@M s][`:[\>=؀"4 `:K[`>=."ς"?xAM'5)'*K``>I7;._ XJH\O.` Y5j#,k?N],`:.a HE`##s(Y##W>NӚ`:݁#s#9I.#>(#,J)?J*BM,1<=``>IHL._ XJYm`.` Yy$el?I!%$e`:J*?JK.\ :&$e`:CM՛՜gg `: a[[>I.% BJ.% >?N(.K[80%=D.E% L%U?JW^%UDMllrz`[>I"!._ X!.%BJ+?J.c I%vEMC C\>I._ X>=.` Y w>I8!B<.^ <(+>=.^ < ?= +.\ .] +;:=/.^ 27[[<FMHM^T^Za`:[ˁK\\>Ivz._ XJ.` Y&x?N],`:.a HEܞ`傞'L쁞'&(Y'L'LW>N `:'&'L9NK[L.] ;'IȯO'>=',L.\ : '=/M<.] ;H'M'?=~&ڀ''I! '&.^ <>=0%+/.?XM _  `J.] ;(+YM)+` 6+][`:[>@C._ XCNJ][`:[''!.^ <HM0=a I],`:>@!Z._ XYeNqv],[&qx.^ <],[I)(+>=).^ N.\ : I,0._ XJ=D.` Y?NΤ][`:[2`:[N],`:.a HE!#`*(*1,*(Y9*:9*W>NMQ`:WS*X*9=hb*di*t.u*>nI2;6* >=QL*+;>=to* C=.\ .] +;:=.^ *d<@*._ X*5J<C*dJMRRG Zb`:[>Im!rK.\ :+J+?N[,ůL.\ :+JM.] ;+ ,/KM d  a[`:`Jܜ`'g'e,,LM$+jf 7j8a[G`:[JOO[''N^-f- MMnug a[`:K[[J[''̀-^-g-tNMΩڪ.h .a[],[J],[''i'-OM2>j LMa[`J^^`'g'k.PMl [J['m'nxf  G !F"z#$G$%&&(()M*+,,->--.J.\Mتޭo]`:_M" 3 `7gM..OAOG3`7\?_/7 .aMT\t(ct`Jfnf.3 _(RdMy  ``:>J#.3 __ X.3 _ɯU/ .3 _a H/9`:bMӭJ +ܭJ]%`:>J#.3 __ X.3 _ɯU + >/'.3 _a H + ]%`:eMnɭ``J.3 _0B/\/0701hM0p`4kM q ^``ˁK [lM = ] +`pM;; q^``ˁK [=] +`\?k1l1 $?*'nM@E.wJ.\>=Yw9Nsz`&s|.r 7`NV`:21A=21 N԰5`ޯ-2S.q k= .= l2 =#.= lw 22qN06Vs`tNa t `}NV\fmu`*\?t3; \vNK`:J'vzNȅ҆؆ 6`:`J.w3{Njqw ],`u`+`:>I4(+=4.t t?I4>J( u)03>JKz Xu*3wN`J xN̈݉TT`J#.t t u) 3u*`3c33445~N̉ҏBw]`:],`N x `N+1XFXLx`\?5 1N+5DNp}X`5ց(^=5る5񃋹6IԂ5(+=56?N(`5y5N`$:.6nE;DF`MK6O6nW6XW6W>Nhq`zs5ֆ5W6AI!7.x g(>=0'y?=667:J3:6Nڍ: ;] +],``>I"!%+&7`<>=K7VVn7?J.x &7`<N@5@# ]y`:]y],`J.4598j578L8Nz`~Nďʏ֏\? ۯ8NFL{`(N = `<N x `Nǐǐx`=`<\?9]9j Dz*N'w '\>=.= wmN,1?9A6`:M`Xy`bd`\>={9:9(^E`9:U::UɄ:UW>Nّ`뀑9:UAI!:.x g(>=0.8$'|:'%?=.= 9b9:MlI܃:>=.w?99;Nfu}]],``:N t `N x `Nߕ  t`x`\?<< 尭N4;DBDM ],`Y`hy`+`:>Nx~`<^(Y=N"'`.)<^/=9I9!SC>=QEF.x g(>Ic!h.t >=0$'=Q?J. <^N`E™`>dτ>>q>ׄ>W>NK`>Q>9I! +>  .x g(= >7?==6>K>J]kd>AN$M0::MH ;] +`:`<J:?N5 ]y],`]y`:Jȃ5@<@>1??@;Nٛߟ`Nd d'u`*\? EK@YN:%3 ;] +`:`<>NT`Id%mh@`>=@@`>=@ŲR@I.t >J$@*>JKVn@@AxN`GN `<N`<\?A MN#(Kw-K\>=@6. wmNPUXc 6],`\>=q.?zBBBB(Y*N?6],``y`d`\>=B BB(YE%.0`2B;9C =BBC CBC W>IO!m^ZTB[C 9`ag(>I}C wB=. ?BBC *D?=. :`777l= B*(C W?IAKEBMB>=dZ. ?mBuB|BBDIB>=.w?AB$BDNť`GN= ] +[N1%1+=] +[\?D MN6;Zw@Z\>=OI.= w N_d^g^r 6],`\>E`EE}(YEEW>I!E}E9¯g(>=0'?=5/.= =ZRE} Nch?p{6],``y`d`\>N(`ĀF(Y=FFFIFF>I"!'!F(!3/F(6F>=HFXQF`FgFM?={.F?IF=.w?E&E_FtGO|]],``:O `ȁODD\? 5 ɁOHNa\? w NO`J. Oϊ׊` J ÁO%/a5a= `:`JIQI.YHāOŽɝҝ6`:`y`+`:>=Ic#IU*Ic6/IH(^NMUh`7%Nkr`7=N`+N`IUN`:دN],`N,9`;WNG_`aWNmz`E`IUJo IcA>N`Jo NŐM`ӀIH5`Jo 5`Jo JWJAN`JIU^YJ(aI>It~zxJo WvIc>=J IHJo =Jo Jo WIdmhJ(pI=yJW?>=JW?Iz"vJJv7>NK`JJ9ILX^>=JILXAIJ("K(B0?IISMLX(e>IJ" >=J" D5`5`/I#7M@(++7M@(`#>M4(+M4`WPGJ yRI=kJ? +J ?=J\ J\ WI K(( IB??I0!:4LX(L>=#ibI(+ōbIq+`=I΁IHXIJ H=҅I΂J=IJo B ??=0-7'^IHfJ I{!I(+>=I΁IHXIނIcHIJ" ^>=IHJ? +IcJ" J\ I΁(>N\f`}xqjI΁(yWIO (>=0'6IH>Ic?CVg]O >=xI΁'=O O WJȀIHIUIc腚IAT?N?F(`LHIcyNIUIYj]J" ^>=xIHJ? +IcJ" J\ P >N'1`:3P IESIQC (>=0'IHIc?IQC w>=dIHtmIHIcIc#QC ('('`:T?JIHƁOӝߠz z6`:``&`8`J(`\>IX!gc\Ry(>=0u$''XRyR8RR?I'!G8+R_W:Rl(JRy>=0Zd'R8RE?IބRlw>=0'RR8dRE?H{HHI*RSpʁO١ߤo]],``:́O! `ҁO.4VAV\?* 4ӁOZ`u\?) `ρOvv ],``:>ITD J'?Nڢ`. N`!T{(TD82TD(Y)JKVZkTЁO{m:m ;] +`:`<>I%ǀU`>J  +U`*". ?J7BZU`. T&TUԁO`ׁO `:'؁O `:'فO] `ځO `ہO `7?܁OI `݁O" `:O00>D`\?#aV[k`: 0OڨT T```>@Vv'J.I:5VÅ=kKVO M``JWIO" "M``JWOgq}``J:WO],``y`d``>@瓃vX@@X@vXM @"X-(+,(XMv5/X-(Y;NFM(`SOXMyUX@Nek`my.I N~`YWXN`džY7Nխ`Y7yY`hN`(Y`hI1"5XZR?Yw>=_Y l_Y W?N4`.Y =.I ϯ. ݀X-X@XMXZZ% + .I I*Y wJ/6Z% +?J+Oůжa۶a`:],`` y`d`/4`;`LM``>N]b`do[>N`˖yͯ[>N˱`E`Z[ [ [ [ W>N `Z[ 9= [ +' [ +k*\ =6[URJD?[U7kL\ 7=[t [t yI[t (>=Ņ[&5`[15`[1\ W\ Z߆[U7A:=[&5`[15`[1"] W] 1(Z߆IB=[U7 KA:=ga[&5`h[15`h[1s^ W^ yZ߆[U7A:=[&5`[15`[1^ W^ ҀZ߆[UA:=[t =[U?I1"<5[ +^KD[ +v7>I["_[wi[t >=Z߅[&[1y[t [UJ?Jy[t [U?Nuw`yZAC` [ >N`Z` 9I"`F `F w7B?=` ` W=0Z$\'9` 'IE@ZF` 9D7O!`:54`A`R`]`\>@vpa`wpyIa`(>=aH5`aS5`aSaWaa;ʄamүA:=쁷aH5`aS5`aSbSWbSa;am A:=:4aH5`;aS5`;aSFbWbL:=f`aH5`gaS5`gaSrc;Wc;x:>@a`(=aH5`aS5`aSŅcWcԀa;儸am7 +A:=aH5` aS5` aSd@Wd@#a;:4/am<A:=VPaH5`WaS5`WaSbdWdqha;}amA:=aH5`aS5`aSe^We^:VW)WzWXZaeOѹ׼K`O`+Oںڻ`\?  f O#I/I4``>IH"XL.(+voc.(YxfO>=.:fO?J"-!.끺ޓ8fOf1fON]:`G\? MO 6],`\>=. gGˀgG(Y*Ow\>=. +)O?!,6],`8`Cy`Md`\>I[c_g(+=0lv'y?=g킽gƀgځ(Y=. gځg킽ghO8 86],``'y`1d`\g)gghhO=C@O`O = ] +`:O `O%Ͽ%=] +`:`\?imi O*/@M 3@M>6],`J`Uy`_d`\>Nw~`. i߁i򂿟ij I!j(+>NԿ3`:Zj=@ @.= @jw ?I@"@&j >=@<@6.= w ?ijO@R@XB`O@ = `<O@ ` O@@A1@A1@=`<@`\?k_AA)kl @ү +OA6A;B A?BAJ6],`AV`Aay`Akd`\>NAA`AA. AkفAkAkAl IA!AȄAl!(+>=AA.= ?Al!AAl!(YBl D?kl OCkCqG"]`:],`OCCCCC\? COEkEuFE|FE `:E`Ey`+`>=EmEEmxEmEހEmi(^IEEEmx(EmJEF:?NFF&`F,0NFLFS`F]FUnFdmiFkmxFrm,=FF|nwFmiFm-JFFn1OFFG :FG F ;] +],``>JFG;GnmAno OGsGyxu` OG `OH> `OH `HWOH `H씃WOI5 `I:OIW `I\OK ],`K,1K>`KDKHKLKPKTKXK\K`KdKhKlKpKtKxK|KKKKKKKKKKKKKKKKðKǰKҰKְKڰKްKKKKKKK7>L7>L +7?7475767778797:7;7<7=LALELILMLQLUL`77777 7 +7 7 7 777777777777LӰLװL۰L߰7?L7777777 7!7"7#7$7%7&7'7(7)7*7+7,7-7.7/70717273MaMeMiMmMqOM `7%OM `73ON `7d OQ}I `0\?  #OQQRl QRlR`R ``>@R&R s(R0R*sR2R R=JRDR`RQRLsRTkRbs$ORRS RSRM``>@R݀Rsу^RRJRRRsхR%OSFSQS S[SS`M``>@SzStt[^StS~JSSSt[S&OTTT¯ T"TT'``>@TUTEt^TETY@TwTgtv7TgT{JTTTTtWy'OU U+Uį U8UU=M``>@UWUQuUQUZJUaUoUhUiuWy(OUUUů UUUM``JUUɀUv/,OVVXwVXwV`:V`Vy``>@VvVvVV@WW vvWvW W@W)W%vvW2W,v(^W%W8IW?WC(WS.I >=Wd.I Wm+W{vWvWvW.I JW+?IWWWv(WvJWWѥ:?NWW`W)XvX vXvX.I =X&.I X/.X;vXBvXIvXNwXY.I JXfXmw-OXXYwXYX`:Xy`\>IXXX.I X&>=0Y Y'ƀYCxYJx?IYZYeY^.I w>=0YrY|'ǀYxYx?=Y.I Y& .OZZemZem[`:[ `[y`[&4`[8`[FM``> @![[([ky[Z[qN[[`7N[[`7N[[`7N[[`7N\\`\%\yN\#\)`\+$\7yN]]&`AE]/]8]:`]<y]E]Cz ]Gy]Lz ]M]Lz WA>N]]]bM`]j]dy]uz A=]z ]]z k]{PN]]Q`]]]]{P]z+9I]]]{^>=]z +^^]]z +]zk k^{7=^"z ^6^1^+z WI^C^M^Gz (>@^s^o^fyWv^}^vyׁ(Y^f^=^^y׀5`^y5`^y^}/W}/^^^z +7^zU:=^҃^y׀5`^y5`^y^}W}^^^z +7^zU:=_ _y׀5`_y5`_y_~_W~__!_z +_#zU:=_;z +?B_WI_n"_w_r{(_z__z w>I_"__z __z w_z@B_?I___z (>I_!___z +(>=0``'π`_y`fz ?=``y׀5``y5``y`W``z +7 +:=``y׀5``y5``y`W``z +:>I`!```z +7(>=0a a'πaZyaaz ?=aa{y׀5`ay5`ayabWbaaz +:Nbb`cbycz hIccc{P(c =c/c?c/W?=cMycU&ciJcc+cyccz Wcyȅcy?=0cc'Ѐcycz Id"dd z ^ddz vd"z@>Jd4d;#dQz dXz +?Nd`AEd[dT dyddT dydT ddT W>NddM`ddydT AId"eeeewez@Be ?=0e1e;'Ѐe`yegT )Of"f3i7ѯ fBi7fQ`:f\`fgy`fpM``>@ff҃^ffNff`f*fffNff(`ff߰$fWgf ygNgIgV`gfg`gYEhNgg`ggEIh"!hh (h1h$ h3>=h@hMh@Wh`hP׃y?IhohhswJhh:h?Ji(+*Ok=kHnԯ kYnka`:kl`kwy``>Nll`Nl$l*`l,Nl9l@`lBAClK"lXlR5wlZlklc!A>=lx5l}lx5yNllM`lll5AIlll(l>=l!l܃l!W=lQl5Bm?Imm*m"mՇk7 (m->Im@mJmD5(mMBmT?=mc5mhmc5y=mtmm{m5A?Immm(m>Imm˄m5(mBm?=m5mm5y=mnmn 5A?In#n,n'(n/>=nH!nOnH!W=n[Qnd5Bns?BnJnnQ+Orrxs sxss `:s`s"y`s+M``>@s?(sOs?sUIs\sfs`i(sixJsnsu?Nss`s's@sDŽs^ss@ss7ssACst +sw> Ntt M`t(t"Zt3iAItAtUtE(>Itetnti(tq>=ttty=tittiWBt?Ittt(t>=tu ty=uiu uiWIu.u8u2i(u;xBu@?=uQu^uXZuiiA>Bu?Nuv +`v Iv#v>v'w=vCvZvCy?Ivfvvj(>Iv!vv(vBv?=vivсviW=vvvyIvwvi(wxBw +?=ww&w Zw1iA?Iwd!wvwnwik7 (wyBw?=wiwwiW=wwwyIwwwi(wxBw?Iw!wwi(wx>=0ww'րx+Zx2i?JxDxK&x_rst1turvvdx|y{0l 1Oxxx~{`(4Ox = ] +],`5Ox د `y0;Oy#y#yAy5yAy;=] +],`\?4' y#*7OyFyKyyNyyV 3`:\>Iydyoyh `Jyx?Nyy`yy.د 5yyy(^,Iy!yсy(+=yy.= 4y ?8Oyyz8wyz8\>=zz.د 5w++-=z-z'.= 4w 9Oz=zB{?zJ{zR3`:z^`ziy`zsd`\>=zzz߂zzzЁ(^Izźz(zJz?Nzz`zz.د 5{Ё{ ߂{,I{!{'{ {(+={6{0.= 4{:{ ?I{G{K>={d{[.د 5w{jЂ{r-={{~.= 4w ?^FZ],`/`:y`Dd`\%rGP`<M\? FIP16J9JD >],`\JPNSZwXZ\KP_d?lw>],``y`d`\>=.MIIɃ=.wJ?PpNP`GQP = ] +],`VP++%=] +],`\?Qy MSP05d8dC >],`\>=VP.= QZ TPinws\>=|.= Qw :WPIO`GZPޯ `7[P ߯ ^],` \\P+ ],`: Z]P) `dP>>OUa],`V\\?[ >M_P >]`\>NĊ`.+ \(Yy. ]IF( w_>N7A`KC.+ \(YN]g`iazF( WhN],`:=ׄ, .+ \(Y.+ \O=.+ ,\?=&.+ \ /. ]J=. ]WRLF( ZFO=f. sf. ]W|vF( ]aP; ;``> @6w=6Ȁ6y=6Ҁ6k׀6=6「6k而6=66k6=66k +67=66k67=&6'&6WJ/66bP@EwJ\>=S.߯ e].+ \p. ]M[(eJ'9`[`] +_hJ' [1[joJWWnln\? WjJrzA`[a],_V\]e_=5[y5i_+lJkp|s|v >_\mJ+07w57\{ -pJ&`[]e_sJb ߯ ^],_ \tJ} ],_1_yJ^],_ \\?s ovJÆƆ >_\>=. t;wJ$w$\>= .߯ . tsEzJFL`[`[`]_}J ]_~J\ ] +_Jmm]__;]_\?}!~: ! mJBB" _\>=8+. ~< JGLT\S`oY`+\>=. }ՁJw\>=. ~w jPQq`[`[`Q\? Q** + __J.$Q __J.*Q4HOOO]__Qք]__QII`[ s]__]__>J$___.?Qɉ҉]__Jٰ__. XQQz`[`[`[]__Q ]__Q ]__Q||]__]__\? |Q--]__J . _%. Q1EwMw]__JP`XP. _oh. EQ`[`[]__Q ]__Q))]__\?$y Q.B[J[]__JMTM. Q_s{]__J~~. Q]__J. $\Rρވ`[`[]__R'%'\? Rm„`[`[`[`[6]__]__JU____R`brirl __R 19`[K s]__]__>JXc___.R5=:S\ ;] +_] +_>=0hr$'.R҆܇r5r ]y_]y_>J_(]400m;;][]z[[JDH[[.hRňш`[`[]__Jᰦ____.W?!Rfl`[`[`[]__R ]__R ]__R  ]__]__\? 㰭RNN __J(0(. ?8. G3RS[:qz ;] +_] +_>J. :. :xS%]`:],`S` ][`:`2`:`'%'ϯ%'%'%'%'+%'A%'V%'q%'''կ'' 'v#'4'I']'s'' ֯('(āSSYcac\? YSh]`:],`S]],``:SЂ +܂ ]y],`]`:>J8`:&.[A4QQzR[Z3`:[Je5[e5[mk5s 5g`:4[`:JASK`:SM] fnK`:`>Iz~(+BJ+?=!WJðm%YWŁT’` ȁT ( `:ɁT `ʁT_ `ˁT `́T( `́T` '))))΁T` '))**ρT` ')*)*ЁT9` O')***ՁTp (`: ````\?ȀɁʂ˃̄ ցTܑ⒞K`:'’ `*9`*W`*u`*\?Ɂ2ʂ@˃N̄\Ȁ# ҁTA`:J.( ׁTNT\]`:`:فT `T++ `"\?ـ9 ہT07>F `:`:>NVZ`:\.A esn(^J#(+B`:݁TOVA ^f`:p`{y``:>N`+E`&]3]Ą]W>Nԙ `:݀]@N`:+AG $'>=3'BTh'>Iw{.٥='?B'>I.٥='?B'>I*3..٥ =?'?B_s'w>I.٥ ='?B'>I.٥='?BI&!6*(+B>IITMJ(+=]Jj?I]w&=JX&]H?=ȃJ=&]W?I J(+J+?I*2.3w4&=B;JMHXW&^3H?JiwpJAށTZ:Z ;] +`:`>I!%؀[`>=[R[?J0;.&QQ[`c=T_e:`(T  `T = `T۞۟`=`\?'2 ۲*T ?>`:)`4y`>d`\>NPT`:^V. A gnuI(+B>=.= ?>=.= 倘lI샟=.= wm?T8w8\>=-'.= wma}K`K `Ko `K `:KTT`9`+E`:+\?.<J KY`Ah`:>Nx`:.N`:I!.(+>='>=.' Jz$'R)K!`KI*I2a`\? <BgKMTA\`:Jb'"KÎɜ#]``:K q ^``ˁK [K# $ ^[ۯ [K&,57%a``ˁK[+Z&a[a[+\?C^ ,Kf'$f%%a``ˁK[\? +P%^K%-3; 6`:D%a``ˁK[+[>Inzr (+= .q ?I (+J.D?J߱H DK K`&a[a[+`:>I#3'(+=<J.$ ?I\l`(+Ju|. ?J KӛSS`>I.$ (+J  ?J+6B.$ KXhp`?>Ivz.q (+J H?JH.q zBK (]``: KT %`: K $ ^[ۯ [K&a[a[+\? +  K)%`:&a[a[+\?    K9@GO a``:J`w~n.$ .% K̪ꬔ: ;] +`:]e`>I!%#`>=EPRjI|%`>J>`= .$  .% :?JYd/&uu`{.$ .% Kج5 ]y`]y`:J 5K29`[O s]`:_]`_>I\%f` `x>J~&~&#.% .$ []`_?JҤ_ PK=*]`],`Kw+ `7K,~`ȱK4 ],`K $ ^[ۯ [K - `#K&%`:+.&a[a[+G.`T\?{jx Kٶ./ .3`:],`>I (+BJ+?I0;4 `JDO:?A>Ey`V(^VVW>IVA^7B?JbJ(#KfpLwL a`],`> N],],`1],`O9>0a```\FEQ>`\`gy`\>It"~x w­•(Y>N(`­y =•Ѿ"••}W ?=5/E9•;=at(|. .$ .- qIE(Y(JҁE9?Nߺ(`E` E(YW>=%W1-(E.9(YNMT`Z:dEqz|`e`E(YW>N1],`E9Nϻy`܆W燻#(Y=ġ  R#O=#,RJ;Bġ KVt: ;] +],`]e`>N2`<I%р`<>=`<>=#V;JLW>u.$ . .- !K;5; ]y`]y],`>J+50ƫ +ƍ$KC 3]e`'K@4 `:(K@R $ ^[ۯ [)K@} = `*K@4 `*/K@@@@@@=`@$^[ۯ [@`:\?)Ǡ(ǭ' @o,KAABABA `\>IAA.4 *>=0AB('5?=B9.4 )*NB`Bk`BsBm.= )6=BB+BxB.$ (B. '=B܁Bxw +-KBBC +wBC +\>0KCaCgF7]e`3KC = `<4KD ],`5KD, $ ^[ۯ [6KDF - `7KDZ4 `*>KDmDmDDDD=`<D$^[ۯ [D],`D-`\?3546% Dmo:KEE +Ek8 EEkE>`E)`E4y`\>=EEE?.= 3?ENʘEUʥE\ʴ*D;KEpEuFlExFlE a`\>IEE.4 7>=0EE('5?=E.4 )7=F F&F'. 4F0.$ 5F>.- 6FK.8 :=FaF[.= 3wmIF!F.4 7>=F.4 )7=FF.= 3wm?n8?KGG"L9G"(]`:`BKGc q ^``ˁK [HKGGHGHG%a``ˁK[+\?BH G˰DKJJKJKJ `:[JJJ-K-K .q BEM10:1(GU;] +``>Jahpy.q B͊FKLSLbL5LfLLv ]y`:]y`JLL5Le$IKN[Njh:`KKN;`7LKN[`7 MKN`7 +NKO<`7 OKO@=`7 PKOd>`7"QKO?`70RKO@`7\SKOA`7bTKOB`7fUKPC`7nVKP2D`7rWKPTE`7tXKPvF`7uZKP G ],[P.[[KQJ $ ^[ۯ [nKQ[Q[QQkQQl&a[[\?[5a[[Q#Q(+Q.a[[ Q[ ^KQQQH QQ`:`KRR +R(IRR(RJ`:\aKRaRfRKRvRR~J`:R`Ry`\bKRRSSSS `\cKSBSGS^LSRS^SW`\dKSSSMSSS``JS#SSѹ7 +S70WSѹS7WWSѹ`eKTTYNT0YT8`:\>NTETLe`NT_Tf(`TjThP(^ETvTT`TTҥTyTҥTTҥWA>NTT`TTPTҥAITT҄TwTԱRBT?ITTT7 >IU UUҥwUe=U.KU-PU0eU8ҥa?=UDeUOUMҥW=U\.UjRbAGU~UUUK>=U.UƱSbBUUUL>=V.VWbBV%V;V;M>=VP.V^UbBVsVVO>=V.VTbBVVVرN>=V.WVbBW>=W=.WKXb=W`.WnQb=W.WQb=W.WdWWDŽW7b=W.WdXW7bBXIX5"XBX9(XEPXWXN(XZR>IXoXuXsҥwXwe=X.KXPXeXҥa?=XeXXҥW=X.XͱRb=X.Xb?IY YYe(>=Y%.IY1P`IY@YKYDeYMy>=Y].KYnPYqeYyya?gKZrZw[5O Z[5Za[\>EZZZ`ZZdZZ.G Z(YZdZZdW>IZZZNZZ.G ZZd9>=0ZZ[N?=[&[ .G Z[*N;hK[[\`P [\`[a[\>@!\\ .G Z \ +\@\&\6\0.G Z\<u\&\C=\P\J.G Z7IiK]]_~Q]$_~]%a[\>I]].R]"jJ]?=^.O ^"gK>N^-^8S[^:.$ ^G"[I^V!^[.R^jsj>=0^^^"^.H ^?=^.P ^"h_[_ +l[>=0___:"_S_e.H ^jK`p`ucR`c`a[`>I`%``l`>I`!``l`J`*?=`.L`l`cJ`)Ia +aal)>=a/.I'`JaJ)Iabafapl*>=a.I'`Ja)Iaaǀal(+>=a.I'0`Ja)Ib %bbl`:>=b).I'`=bA.NbTl`:e=bc.I'`Jb{)Ib%bbl],[>=b.O bl],[g=b.Tbl],[k=b.P bl],[hJb)Ic%c!cl][[[>=c1.O c=l][[[gNcc<`c.Ucl][[[l=c.P cl][[[hJccܿ>Jc*kKd d%eTd.ed4],[\>=d@.I'`IdVdfd_dZV(Yw>=ds.QddV9iEddd`ddրddV(YdddW>=d.I'`=d.QddVd9i?=e.I'`lKe6e;hUeCheH][[[`> IeSe[eW޶ ~>=el.I'J`Je)?NeeV],[e.[eee޶(}hNee`NeeW`)=fe޶4ffff [fK[`>If!%f%f!ߝ`:>=f;b*?=flf`5`fmN5`fmNfnWftߝ:=ff5`fN5`fNf_W_fߨ:xIf!fbJf*?=f.I'w`Nff`:'Efgg `gggg(Yg'g)g'W>=g7.IgC`=gU'X=gm.N&gggg9`:e=g.I'Y`=g.QgɁgg̅gW9i=g.I'x`Jg)ZЋWё($KD.ގ' oKhhnZ``IrKi[ `x\? tKikipi\iii]`\uKiikoTikoi],[\>Iiii$ >=i.I'`> =i.I'`=j.[ jj.[ rWr=j&.\j7.[ rt=jL.Qj\jX$9iEjhjqjs`jzjxꀇjj|$(YjjjW>=j.I'`=j.\j.[ rt=j.Qjj$j9i=k.I'X`=k.[ k%k.[ ryr=k/.\k@.[ rt=kU.I'`vKktkynUknk][[[`>Ikkk9 ~>=k.I'J`Jk)?NkkV],[k.[lkk9(}hNll`Nl l.W`)=l>l:94lFlFllG[lLK[`>Il[!%lcl_ `:>=ly*?=ll劀5`l5`ll{W{l :=lɁl劀5`l5`llˆWl+:xIl!lJl*?=m +.I'`=m".[ m.m".[ rWrNm=mG`:'EmQmZm\`mcma祀mrme劁(Ymzm|mzW>=m.Im`=m'=m.\m.[ rt=m.I'`=m.N&nnnn9`:e=n*.I'8`=nD.Qn\nPn_n]W9i=np.I'X`=n.[ nn.[ ryr=n.\n.[ rt=n.I'x`Jn)SyKo=oCu^`I|Ko = `Koooooo=`o$[\?| oűn&ooa[[~Kqqr\qr\qa[q&a[[q%`:`:>Nqq4`q=rr3rhr&>r3OJr@rNrGhAKrrt`_st`s a[s4`s'&a[[s>%`:\>Ns]``IIsnsysr'(+B>=s<sss>=s<sttt*'=tIt==tt.= |ttxAKuuu=Iuu=u3`:\>=u,u&.= |u2KuBuGuKuWuu_3`:uk`uvy`\>=uu.= |uuHXuWufHKuuuuuu`\>=uu.= |u P !Kv#v#a`y`oeKvvwPb`Kvr `:Kv~v~vvvv;`v&a[[v`:\? vұvŁvKvvwN\wwNw `\>Ewww!`w(w&dw*Jw1dw2w1dW=w6.IwB. "Kxpxvc`IKx .`Kx 0^```y\Kx`Kx`Kyyyyyy&a[[y+.`y<0^```y\\?y`y:y yny K{d{p}E{y}E{a`{%],`{&a[[{.`{0a```>y\\>N|``I|!!|,|%S(+>=|=|O|uh|S|y|>=||Ʊ|h|y|=}} Q}!Di=}:}.񯉬K}}~}~\>I}}}.w>=}.0}.}.?=}.+=~.K~"~-~CH ~<~C`:J~?+K~H~M~L~X~~]`\>=~k.d~~|iAK~~d~~3`:\>Et}`倇ˁ(^W>NM`ˆA@ׂJv7=.eJK +YIY3`:\>=+.K<NG(^K^cKs{3`:`y`\>EW`b`dYmkohtutWA>NM`JAIv7>=.e>I"典7(7 Wh>NGPf`YRJfdWAIv{7(7>=7Wބ典77 +W7=.g&=9:9WBJ??=r.hK;;`\>Iـ*v7>=.e*J?=.h.*K@Eh[``\>Ip}tv7>=.e7k7=.e7kӀ7?J?Iv7>=.e$7k0'7 =?.eN7ka[R77?=q.e7k7?J?=.gKg`\>@ v7 ='.e67kB97=O.e^7krkb7 7?=.e7k77?=.e7kˀ7?Ke`\>@v7I.()".(Y>=9.0B.M.=[.h:r..=.?=.5`.5`.W:~ A"v7 Ki``oK\j`Kh %],`Krr!!&a[[%],`.[0a```y\\? &  ` K&+Z\;Z@`\>NW^%],`e.%Nuk`(YI(>NM`ǁ9C߀w>=.e)= yJ!?C3@:w>=MRMyN`dy`lf.WnIv.(Y>=. .O=.>E`  W>=*.e:4;9:U28l`Ud t `U +VV"u`*\?J U[fzKkz`:Jn'U 6`:`J.U$+N1N< ],`Iu`+`:>I^ob`(+=x`.t ?I`>J u)L>J6 u*>LUSem`Jp vU`J#.t ñu) u*`."pUjpm`~U\? U/5Ln`āUu`*\? گUJ:J ;] +`:`<>N`I%U`>=$p1U`>=Jp[RuUI!.t Jp?J;p7ŁUOUo`GȁU= `ҁU=`\?ȀB MʁU̎яw֏\>=.= wm=.= +ˁU UU 6],`\>=(.?1ȓC<ȁ(Y*́UZ_p ny6],``y`d`\>=.= ȀZ&9FlIʃS=.w?ЁU?6],` +`y`d`\>=->NゑUaZЁ(YInxr({J?I!%`>=btЁ|を?=.p Ёを΁Uǒӓq 6],``y`\>N0`E#,.`097&;@&A@&W>=MRMk[U\&9Ij"sn^{v>J?=ρUr  6],`$`/y`\>Ey` 7 Z D Z ZW>NM` $ Z9I"Ȅ Ԅ w֯>=0's? $G Z?@*g  +/ӁU˜zt`ׁUGG4;`\? <B +ՁULQx?Yxd6],`p`{y`d`\>= +Ԃ + +(YEז` +䄖 . + .섖 .W>NM`  + + .9I" ~w3. ~>IBHF .wJ +=Q.p a +i +Ԅp .*?=.p :`7*= +섗 .W?I  +Ԁ +>=.p , +4 +Ԃ; +ი@ +?ISW +>=g.w? + ؁Vouu]`:`:߁VƂ\? ځVGG`:`!y`+]`:>=3 SDT E[ Sf` 8(^Nw` ENM`E` E ˀ S  WA>Nτv` =  8 AI ! (>I'!0+ (3B8?IJ[N(^>=o ~| WB??M 8X  H= ꅅ WI  + S>M# 8X- 9 SH?ہVLY`h`:],`:>N],`:1`:Ny`y(^N`NІM`E`WA>Nv`=#/*y:AID!MH(P>I_!hc(kBp?IA(>=WB??=큇yXӅ H;=&$WI5D9ӀF>=YSb]yXlӂxH;?J܁Vj:ɉj;] +`:`>I!%쀈`>=R3?JDO&aa`݁Vo~5 ]y`:]y`:>J`:J4܊;]`:`J [,VEK7w`(V = `VZx `:+Vpy `*V=`\?? *Vs?s>`:`y`d`\>=#(^IÁ^>IӃ=.w?J?I! .x (+B>@!$.y #2=;JC.x WRLX\cHG=o=(^=.x +I.y >IڀA(>=W?=.y *?=:.z DKRI\`=h.w?Vx}w\>I!.x (+B>=.= 〘.x l=.x +?=.= wmV5z 5`:`y`\>N*5`7NFKM`ET]_`ajh_l#q_rq_WA>Nv`L=L _AI!ȄL(˯>I!ㄐL(B?I(>="61/_WB@??=hb.= 〘rl X|6_Hl=6_WI6#>=.x ހ X6#H>= .y $L('dh,V:@{`]`:V ]`:VHӓHp]`:\? #R=VMRZb`qY`+\>=. 큓0L|]e`:L [1[L77MKM\? 7oLQYAza`:V\`=5[HLńA#ބ;] +`:`=5[RL^A}+^7;``=5[?LO? O(>`:3`>y`Hd`\L6IhShY``<Lo6`2sL~`L [1[Lω׊5A}5;`a\`=5[ +L{w\o L#``Lx ߯ ^\L = `L=`^\\?P] Lԋًwދ\>=.߯ LC C`\>=(".= 6LHMuRuZ`\>=ic.= o3Lz~`'\>=.= ~Lč][`:'\>=.= сdLF``LY `7L+ `L `'Lُ`\? Lgw g\>I)5-.+ C=A. %?=\O. wm Llq~`\>=.+ ZI.+ (wͲ=. %?!LSS`\>I .+ C=#. %?=>1. DBAl"LX]~dm`'\>=|.+ ~ _I.+ (w=. %?#L̐ђْ][`:'\>I .+ C=#. %?N:C +]%[ME + I[!i`!1'Ju?I `>D>=. ǂ!1')Al!1'>=!. 6.%!1')AlCIYP!1'>=o.u !=. !1')Al%L͒ғD ؓD\>NV`:.+ A=.+  =0#. 4"l< B "a"(L`+*\? 3#;+LTc``3\? -L?`:`y`d`\.Lߔw\/L22 `:\>= .?$ $(^*-0L7JTZ``<>Jp{i.$n1L6̖`>J'.###$P$$4LdjY`(7Lr `?LÖÖܖr`\?7%, ò*9Lw\>:L +!?!`:#`.y`8d`\>IF"!PJ%(!\X%(c_%(^>Es|~`%&%&&W>=.r 7%&A>=.r 7%I +%=.w9?;L&+[.[6 `:\>=MA.r 7S&J]..r 7'7=LW6W`>J;.r 7M.w9%S%u&''j'@L `4CLu ߯ ^`: \HL^`: \\?C( ?ELƚ˛ZwЛZ\>N`&.r 7`NV`:(xA=3,(x =@.߯ J(CFL_r|``<>J]..r 7)(U()7IL͜Ӟt`(LL = ] +`:RL((F:F@=] +`:\?L) (*NLKPxSx[ `:\>=lf.= Lp) OL}I?I`:`y`d`\>I"ȁ*:(Ԃ*G(ۀ*-(^>=.*-N>=. *-X*:!*GHNI26*T=>.wP?PLNSrwXr\>=ga.= Lw )*++9SLġ`<VL د `WL$ = ] +[]L..DJ=] +[\`m`\?W+V++ .FYLƠwˠ\>=.د VwI!.= W(+=.= Ww ?ZL^^& >],`\>=3.?<,LF,(Y*[[Lch ?p ],``r`d`\>=.د V,遠,- I-=.wY?,,o,-j^LD`<aL د `bL `cL? + `iLJJ]s;`~`\? +k--kLˢˣp ࣌```\?b.CaBO.N].[c.N ˰FeLw\>=.د awI.+ cC>NV`:.+ cA= .+ c =- . b?6.RF.(^)>=t. bwmfL >],`\>=.?/Ѐ/(Y*ggLB?B>],` +`r`)d`\>=@7.د aH/O0[0Ijvn.+ cC>NV`:.+ cA=. b?0w넥0w(^0!= +.+ c J?I+/0!=7.we?./z/1lW`oW `wWGG`*\?o91_ qWLWfK\f`:J_'uWss ],``+`:>I1(+=1. o?J&]1遉M1e1rWx`xJ ~sWŠ`>JӲ. o112L2|2xWqw]`:],`~W\? zW66 3`:`y`+],`> +NX`3C(^= 3P$3^)3|I<D@3^(+=M3^S3|?Nip(`vr3^yx3PI3(J:?NYa`g3hNd`43 3C3P3^@憍4^^킍3^yڍI!4^( +3^>Nʎ`3C3^yA@/4 N`43 4@!53?J +43+ %43 M{W̐ᑖ: ;] +],``>I!%5`<>==5HV`5?Jq|&5`<|Wڑ5 ]y`:]y],`J 56C3%56%6{W`Wx `W `W + ],`W  `7W11p=p\? +GVWuu.`\?7L uW+IQU0f7>N`17큖7@;68&w=6N@c^8&vf^v=.+ 5`. 5`. 8W87k8&7:=.+ 5`. 5`. ȃ9 W9 7k܂8&7 7?:=.+ 5`. 5`. 9W97k 8&77?:=6/.+ 5`7. 5`7. C:DW:DN7kVQ8&7?:Je)>=.+ 5`. 5`. :W:7k77 :=.+ 5`. 5`. ق;QW;Q7k777?:=.+ 5`. 5`. ";W;-7kA07텸7?:JP*W `:`y``>I"!Ё<(<گ/=w<zwN`I~. ^.+ (YB?=.+ 5`. 5`. ņ> W> =|:I/=|>I !. W^,$.+ (YB4?N`I\`>=m=xm=W?>N`=|I?9v>I. W^.+ (YB?=.+ 5`. 5`. &?W?17k94?97:=QJ.+ 5`R. 5`R. ^@BW@Bi7kql?97?:>@?9vI. W^.+ (YB?=.+ 5`. 5`. A%WA%7k"?97 :=;4.+ 5`<. 5`<. HAWAS7kb\W?977?:=|u.+ 5`}. 5`}. B:WB:7k?97?:J=77I!.x (>=K.?')Jk?=}.= wmWD?D`:`y`d`\>=. I"C(C!D>J?I#!.'.x (>N@M`IX!b\C(eC>=tDoCކCA>@DNԤ`. .x Do@"!eD!ztC(}CdID=CCW?=.x ?D>=C. CށC낥CN`" DC(CI)"3-C(:6CyA/VRCކaCA>It"xD. .+ (Yy>N`. CކCA@!FYԧ>=v.x CކCA=CCW?=.= ?.+ . ED=. !C뀇#CI-1D=9.w?CUCGTW!'R'(]],``:M@'د [A4@2@2A[>K>JAA[''A[Al[>JA+Wg `WRR `*\?DH.  M  )6`V`8e`py``:>I{Hv>J +?N(0[2I@LDH(+JU+?If"l(oH|xH(+>JHāH?NϷ(`⁷H(?=HHHI<I)"/(2H?;H(LBH(?>J\czHāH?JHɜ`8''āHHHM! 78[Q`8`:>IbfnJ<Jz+?JJ3J<Mǹջ\ \[`8`:>K>J`:'9'!J*J<[Cl[>JM+M x x%`8`>Nrx9`zK (?yE`KcK5KcKcW>N`рK KcAI惾K(7>N``'3'K KcWAI-@82K7(7JI)??Jh*WɭаPװP ],``y`+`:> +Nw~`:. LLLI!̃L(+B>JL?N(`L(Y=%5L<LAMINVRL(+=_LeM?N~`N`M. =톯MLLL=ML*LJ4B;MAW :  ;] +`:`<>N@`IP%YTND`>=zN_ND`>=N_RNDJN_. WQ`5dw ]y],`]y`:J5NMPq0q(x`[]`:_]],`_>J_OPM ( `:],`I`Ty``:>I؜`'g'O>Nsz`8|`8''OJOPO؃O?HVJJKLkN&NO OPk WM`W `W& r `W: `)WZ `Wl `W `WM ],`:W`h}Wr``\?QQ Wӷܸ`J. wW¸Ǹw̸\>=.W %~*~66],`+Be`+\>IQU.>In!s. >=0'RNRb?=.r &=9. =K. =e. ?WMM],``r`\> NͻK`. N`. N `. =+. =;. =S. Oima],```~],`#``>N`S7NǼ0`ίE`ST= T T= T= W>N`!S"T= 9I.!@83T :T& +(CT JIRPT= yTS?JhroT ytSOa``\a#``\>@"Uc^S*UcvS7@"Up ^S*Up v +S7='.r 1ZFSQUcWUp Nln`pS*AC)A>AI„Scw>D>IVC(S7>B?N',`7.S8VC9IF!XPKV 7(7>=oScI!. >=0$@'V D7@%S@BVC?=@`. *=@@.r @&B@>=@SJAAASJ7kAAV 7?=A1ScA>A1Scy=ANVCAOANVCWA~ApScwIAAASJvAAAAS|y9>IB"!B'. >=0BFBP$B'BBSJD7BSBBBVCyBS|y?=BScC S|=C&SJC.&?ICaCkCeSJwCm>IC!C. >=0CC$''DDSJD7DDSDnDaD_VCyDcS|y?=DSJD&?ID"!D. !DDSJ(D'>=EE .r E'SJ?=EA. *?ACEkEtErVCEvS7>NEE`EESESEVCIEEEZ w>=E. *=FF UBFVCFFVCWFZ =F4VCF6F4VCWF9Z IFMFSFQVC(FVS7BF`??NF}F`FFS5`FVC5`FVCF[ +W[ +9IHHH [ +>IHW!H\. >=0H{H$H'HHH[ +WD7HSIIVCy?=I8I,.r IF&> @II[ +wIIIIIIII[ +7(7>=ISJII[ +7=IScJS|BJ#?IJHJZJRJM[ +7(7>=JqSJJ~Jy[ +7=JScJS|BJ?IK+"K=K5K0[ +7(7KMKH[ +7>=KcSJKpKk[ +7=KScKS|BK?IK!K. >=0KL$LT'LAL<[ +D7LfSLLVCy?=LSJL&=LScLS|=L. *=M-M!.r M;SJBM[IMqMMuScw>=M. MSJ=M. MSc=M. MS|?QRR0R_N`q }N `7!O` "O` O `7=#T` $K` ͱ%Uz` U `7VW `7 +V'X `7 &W2`7'W`7(W[@`l hwWs `7W `7W `7W `7Wa `7W¯ `7Wï `7Wį `7 Wů `7 +MmƯ m[%a``ˁK[[>@!݁b((+ŇՇOa[[Fl[[>IG"K`'g'ȃcb}i`'g'Ƀb}>Jb}?Ilp`'g'ʃb}>E +`b`'t'h)b}-b.-bW>N[[''Nb}b=[''̓b}bفb(bႋbecUJb}?N`7[b}Nb[cפ] ;N֌],`:ᄌcפa HE`d; d(Yd;d;W>N*.`:40d5d;9NCK[TMb(Ud^Zbe_[''Nnb}qd=[''ͅcdd =cפ\ c:J8?cJKYRb(+d`beeb,Mpp̯ a[[>Iڀe(+J+?I@D`'g'ɀge>Jv}e?Imq`'g'̀e>J¯[e?E&(`/-f51`'t'hGePf5QPf5W>N[[''Nef5=ǜ[''̀ef5,fJe2O…],``:Jׯ!g3Ory],``:J"gd4O`jv~6`:`J!g5KƊ͋F׋Fa`&a``+`:J$%h&:h6K$,6`:<%a``ˁK`+[Jglg$shp%h~-M ԯ (&6`:.%a``ˁK[[>IU!%`Yh`:=0lr1h?N[K>=i=[''րh [l[>=0#3`:'9'MinIYe]h(+>Jt{,i=>J+i=h.KM0M8Mnׯ MKMnMTa[[JM_MfM_j>/W"د 27``JHiRIj`T(l0Wٯ ``Jj…(Я 1Woگ o` ``JK"7WD+&k$-7 +kWRk1Y.1-25;89;@TADGSUefijloo(K +BerqBt6[*M9dhFnlG +P A=<7##D$')H+N-126BBGeP_OaefgFgghRhij@jkk ܁X"%7^sG\ sݥޥY^`:][`:`:7~]`첿Z^[Z֥^][[kq``[貼][[[2[[[$ `:[겼`'[ʼn`:\?nj [։ތ`:`>N ,[8.9nmIE!UIn(+>Jf&fmn`?IԲ(}(>=0$f'M'?N`̲n=ݲnoXnJoX[.6A`>NNR/`T=e.J}onooY` Y `:Y `Y `:Y~`Y9~`KY~`Y~`.Y`7ZWY`7}WY!`57}WYz`7}WY`:\>Iw!%{.򲼲`:>=0.򲼲''?2qr++ Y::SX]`o`:\>=ݲ.󲼲I!%.`:>=0&0O.''?+qr :YUU``:>=βrIr(>J'?J<'YZasx`[>I!%s`>=0s''?I s( >J#?I5"D:s^Gh^svk>J?=0s''Y+0l8l`J>"!J?.󲼲(+!dW.(+BYō`:>I!.򲼲(+B>J.򲼲>@! .󲼲(+'@!D7.(+B7KJT`[$2g`:`'Qy.󲼲'.󲼲'2`:`:'.rrst;u/\;JJ(`\ `7@\J[1[  [ +`:`=5[ \ `:\` [$@f +@(Kf`JN[uuuvvM\Tc `\ K`:\ `:\wwK`:`:\>I ".K(' B'".Kn'O>=0>H' ?vv \|][[[wBwl\ V`\/ `[\C `[\R`[+&\rrK`:`:$`[. `[\>IZ!%b^.`[>=0v'?I!%. `[>=0'?I!.. >=0",'?=b.k.wx ;AwぇGw\\gvKmv`[Jpp.!\z~K`[\>Iy5.>=y5.IÀy5w. >=y5. ?=.y5$\w{TT][[[>N][`:`2`:`'''.$'.K'K.K'.ճ'K.K'$.' 6. JFMyxyyzf'\ `*\`[(3\K`:`:\? ѳzɁz,\K`[J.*.\#'KK,K4`[\>==.F{Q*1\PT [ ][[[>Nhl][`:`2n`:`'''.$'.K'K.K'.ճ'K.K,J{{{3{u| 4\`7\C][`:`RF`:`?\? 9\`\>I!%߀|`>=0'?I1!K=57E>|Km(+>=0\f'?=7|K|n:\(0`\>I>!%IB}g`>=0]g'?=7}gKv<\.`:`:>N%,`6.77}mI@KD}(+>J\+?Jsz$}=\Վ`:>N],[1[F3`+"7|>=C;~NG~;Nhl][`:`2n`:`'''~J$~|}I}~^9@]" `B] !`C]\ "`kD] #`H]$$#`\?D F])0 A8 `:>IA!OE.#D(+>J`$'$.!B'%."C'R'%.#D>J$'$.!B'% ."CI]u`O\? K]\&]`@>N`N*']`0`=RF4\\aM`\Jivi tH=²݀dN$(M`3=0 u=l`wJyHL]a(a)`*]`@>I!%쀉`>=0')'*?N`Nӊ']``=:49M`\J,Pt5=x:dNM`3Pu=-!:wJ:EHYM] +'0h``:>I?!%KC8`>=0`j~8'h',?J܀8-PZ^d.`SZ/`7 TZ0`7 +UZA`7 VZ4 1`WZm .`^Zttpz1`.`\?VFWS tYZt2.`+`P>J^S5`#(+`ZZ̈3Ј.``PJ^T [Zy.``PJ^ +UhJ_ZIO4`bZ5],`.`k\? dZR^6goK`:z][[[+7`P+\>I>J?I!%ʀ)`:>=0)'K'?I)!.>=~b+;J?N8`)˲ݲI%6][[[>=9)6][[[?I>%GBG`P>=^X7eG`P?=|ub;eZ͏ّW:W\>I>J?I(!b(Y(>=06@(';?N8`b7IIӀ(+>J!?=KE֦<fZym=mK`:][[[+\>I>J?I!%耑C`:>=0C'K'?IG!L>J?N>][[[I%ÁP][[[>=^[[P][[[?= &'?@CFWgZ@ K`:;^[P][[[+`7`P+[>=mdwQ̂p7L>J]>=ٳeiZTcz&gz`Jjj p%3 +lZ$(A`oZ B`pZ 5],`y1$`ywZqq}\>o qxZC6;D`\>I\!%g``>=0x'D'?oO rZ:?DLK`:W][[[+\>Iim>J?I!%A`:>=0A'K'?N8`y A.BoI-%;1N][[[>=QK9^N][[[?=zs.5p~;=HsZ̚ќkE؜kK`:][[[+\>I>J?I'!%0+V`:>=0DNbV'K'?N>][[[I%c][[[>=ެ^[[c][[[?= .Bo''?6VDUtZ<\>IƲ>J?I.5p(Y(>=0 ('F?Nv|8`y~.5p7I= uZG`>I&81*.5p(Yw>=0EO($'H'I?N̞`.BoJI#8?lyZDJ`{Z K`:'?|Z% K`:~ZX B`Z9][[[+Z p K`:B`\?| ~ Z).H4\>==N`.B~'rn.K{x.K|.9Zȡ͢B ԢB\>=ݲ .B~'l.K{!.K|'+KZzL`Z K`:'?ZE K`:Z9][[[+Z H`Z8 M`ZN`P+ZpK`:H`M`\? Z!&J<,J\>=Us.H{.M.K.K.9I!.N(+>=Բ.H.M.K.K.N1V.N.W)+?ZOXx7\xb`P\>=k.Ns$?Á[O][`:^`:][`:`:7~]`"F`:^`:][`:`:7~]`ā[P`Ł[Q`ƁZR`'Sȁ[(  `)`:+`>I׀G>=眣[''?JGɁ[IT(&I.a``>J:Aʁ[LX _X([ c`:z|`+}`+R`K`:'`+S`+Y`+\>ˁYy~7`:^`:][`:`:7~]`\>I!%π`:>=0'7'?I,!81R'UD>=0R\p'7'V?I!(+>=0$ 'W?I!%!^`:][`:`:7~]`>=0DNk''X?=́Y5:YCKZ`:Z[][[[\>Ii!%wm`:>=0'Z'?I!%聕][[[>=0'['\?NL^]`:e`$l=z΁[)e^)(3e;Z`:M[`:\>ρ[Kj_j(z7`:^`:][`:`:7~]`>J3mЁ[`(Ƅ7`:^`:][`:`:7~]`[>=Àn߁[ )a ()`Jс[އ%b(%d`\>=h+ҁ[(4c4(EOd`^)`\>=sj+Ӂ[r}d}(`>Jԁ[e(ʇ`>JՁ[f(d``:>J+ցZ}MgM][[[`:>I"(+΀(}(>J'J?J.:5$Aׁ[htht(`>J*؁[Æiá(҆`>Jف[j(`>J5`Ҳ5`Ҳ݀Wځ[)k()`>J%Wہ[ol(o`D`!m`:/K`:DK`:Qn`:\>܁[,8o8(LQ`\p`mK`:~K`:n`:\>݁[?q(̆?`p`K`:K`: `.`!n`:\>ށ[BNrN(ak`yK`:K`:n`:\>mouHvfwyz{|R' PiCFJ}* s^" +߁P' L)Β _[/6HP'L^orux &Dtuvwxyz{|}~nЁ_` ҁ_ `)`>I"*>J0;>Jfqԁ_9>RARL],`\Ձ_`\ց_],`ׁ_@JSQS],`ځ_(`ہ_؆ `܁_)2<C<<`؁_uz \ fCh ݁_0``_`7_ `:_2=`_K+`_WWkq`\?#kvۥ:k` W +_ ],`\>N,8`@:(YIL\P(Jb?Nr{B`}.=WI.+(Y9>=.ų9?@.+(Y^9I% `>=*".+ 3.=₊<9F`O>Eajl`sq!u!!W>=.+.=W!!9:=.=9_ߊ`\>I.+(Y(.=>=.ų.=?@.+(Yw.==.+.=​:=.=.=W_ ųB`\>N`ނhI>=˳>=N"p`(:2=J@Z ^V.+(Yf.+O=t.+~Z_44],`>I.=(Jų?Nٍ`".+ぺޓ.==. J#* _9CJ],`>IS_W.=(Jel?J|;".+ぺޓ.=_ێ(`J.=_  +`J  .=(_'AC2A`J5!=5.=(_FK P\>=Y.==j.+t_..``>@w=y=ʀkπ=ۀk=쀏k=k7=  k7J'%WV LI +_39i``_g=`_ ],`1`\? _],`\>N`I%တ `>=& `>=&/;B =\T.`&;=q.=yq.=W|&(Y_`\>=.5`å:5[с:;=.=.=W_],`>I.=(J">?INaZR.(Y(>Nsz`|.9=. J?N`ǥ:.=Ne`F>`.>= &=5.=W=7Q(YEQO=S=ZS=Wc]Q(Y=u. J_],`>I.=(J?N`: .=N$e`F-H6>`?.>=WPC `cohcWwqw(YwO=ccWw(YJC_Ŕ͔(Ԕ`J.=_ `J.=(_+C+`J!'.=(_05g :g\>=C.==\T. Ci +=}`3``m\? `A`:J'3q `lr5` ``䔃W `| `: `6 ```:'` \?   / ` A`:>N25`;=RO'Ii!vn. `>=5`5[؁'5[؁. I!. ( >=5`5[ځT'5[T. AT?I!-#. (0 >=5`E5[IG݁'5[^\݁nd. A?JAg\`Њ֋5``],```` 33 ],`-`\?   `djj(`\? a~(``>=0'Xbds`b`7 bQ '`7!b`7"b9 '`7#b`7$b* '`7%b`W&b '`W'bI`7 (b Z'`7 )b`7*bE '`7+b`,b '`-br`7 .b '`7 /b/`70b G'`71b`2bN '`3b`4b '`5b`6b '`7bs`8b '`9b`:bl /'`<\? =b]],`],`?bK `@b R`Abr `Bb `Cb `Dbd .`Eb\ ],`JbkktR`)`Ĵ#`/`(9D],`+a.`*x`*\>=.R@=.δA=ѳ.ϴB=.дC@CABED?* kLb"(;ҳ:;\?@X)C#A/B9D*?*E+ (Gb__`]Jj*R.R@.дC.δA(.ϴBD.ѴE.[..DHbƛ`kJӴt.дC.ѴE...D3Mb؜ުy]],`],`Obk `Pb R`Qb `Rb" `Sb$ `Tb# ],`Ub .`Zbͥͧ~֧~R`)`&#D`Y/u`9],`+.`*`)\>=.RP= #.δQ=2H.ϴR=Wo.дSPSQRTU&O4 Ͱ\bҳ\?P)S#Q/RG9U*O)T+ Wb`]J j)R8.RPQ.дSm.δQ.ϴR.ѴT...UXb w%w`kJ.2tJ.дSb.ѴT.s..U=]bݪ㸭]],`],`_bv ``b R`ab `bb- `cb/ `db. ],`eb .`jbسص㵌`* R`)4`K#i`~/`9],`+.`*\>=.R`=1.δa=@V.ϴb=e}.дc_`cabd*e> ذgb ],`],`>N,1;`7=5`<J.:a*h5[omAsl5[AwmAJ*hb:Ÿ ;] +],``<>I!%뀷`<>= V.?J?J&dd`<j.ʹ_p.R`w.дc.δa.ϴb.Ѵd..evkb@J]],`],`mb< `nb; ],`ob .`tb彊`#3],`+P.`*\>=c{.дmmn o4 尭qb ],`],`>N,1;`7=5`<J.:ar5[omڀsl5[wmJÄrbcv@H:@H ;] +],``<>I!%u`<>=uݰVu?J@@&@"@"u`<@(.дm@4.Ѵn@@..oSub@@G@(`wbA$A,BAGBAS`*AhR`Az)A`A#A`A״/A`B9B$],`+B9.`*`u>JBPBW}BwdB}tBÉBßBõBˆBxbC(C0CCKCCV`Cm#C],`+C.`*`u>JCC~CpCĆCĜzbDDDDDD],`D`Dy`\{bFF#FQbF,FQF3`)FEy`*],`}aٳ(%`5R`F`\`p`],`.``u>=0'~a۳($`:],`K.``u>=0V\';G<ő/ƚbGGIU`<bG `G޳ *\? FbGHH2HH2H >],`\>=H$H.H(CbH7H<I@?HDI@HO>],`HZ`Hey`Hod`\>IH}%HHǦ`>NHH`HǦ`=HH.H˾"H߄HށHǻHHʃyHǻ>=II.I"IǦI*ǻI1MbIEIJISwIOIS\>~bIXI^J`bIIJIJI;`<I`IR`I`I`J`J(],`J?.`\? JLJ_IJ}JVJeJsJɂJɑJɠJɵ)bJJK`bKKKK)KKD;`<KN`Kd],`Ku.`\? KKsK~KʀKʏKʤbKKQi`<bL& ȳ`ubLJ =`<bLX `*bLp᳗`)bLLLLLL=`<L`u\?˔ˡ LFbLLLLLL ],`\>=L.?LLL(Y*bLLO?MOM],`M`M&y`M0d`\>IM>MB. JMK?IMWM_M[̐(+=0MhMr'y?=MḾM̐MMl(YK>=M.᳗*NMN`NN=lNĆNJ̐=N^NV.ȳNuNfENN}ENN̐yNŃyNNEzNN*],`CN!ONNN.ȳb*{(+>=O'O!.=O+lO?[OFl[>=OQ. )=/OgIO{O̟=O.w?bOOQgwOQg\>IOO. JO?IPXP\.᳗=PlPd.ȳ:Pt`z?K>NP*],`CP!PֈP7PP.ȳby){(+>=PP.=P7lQ[Ql[>=Q. )=0Q/Q5ϳ=QB. )=Q\QV.=wmDζcU``cc{`:cǓГ`:`>N`I)Ў(+>J:EPy?JarhЎyc``>J cM``J̴ڀLcH]'e`>N}`Iѥ(+>JӴ?Jѥc"%M%%`c4D'KL[\>Njt`IA(+>=ڀ2J?=끚A&2`:cԜ`*]`chmw~`*\cŠР`>N`I *(+>J,>?JTe[*c`:+]`cMWvevn`:+`c{]`:cģ`:c$6LIt!%}x`:>=0$'?=.=.볗. V݁d--8C8N`\>I]iaֺ(+>=0z'?=.볗Ӷֺ=.,ֺ -d=HUMU`:JPP.a(`[>=0'an( n`-`[>=0<B'Áas(``[>=0'āa h (h$``:>=05;'Łam}}(``[>=0'Ɓa^(^ ` `[>=0/5'ǁacss(```[>=0'ȁa($`9`I`:[>=0X^'Ɂa(`],`c ``5`\>=0HN'dVkW'sW`>N}[I%ڦ` >=0Ե''#ڦ` ?J6A&LLڦ`:ځd\l'st[\>N`I%*`>=9$*`볗I9%B=*`>=9*<7*`IN%WR*`:>=j9*`:>=0$*''I!. >=0AK'?N[˷ԁ9I%'`=0 '`?I% '` >=04>'&*`:'` ?dM`>J .΁dދ]`>JU21C[+J.볗g`4ZZ[ +[`>Imq.O>=0.O'?JO(ρd +`>N&-[/BN.볗I]%ha` >=0|'.` ?JӀ(d`J .pЁd.4;`*]`>ITXޥ>Jk{r.g`4r`]`>IJ.?I!.(.sB>J.s)g`42p`]`>J.>JPW.>J·1[+.볗g`4ꐓ +[`>I.>=0+1.O'?J.сd`*\>IҀ[>I.J?I ! .(.sB>=3,.s)??Nfm[o.볗I%` >=0Ƶ'.` ?d c)c`J26@Wҁdhz  `:+]`>I(+B='?I.('B>=0$' ' +?N~ `:I" .'C"&*83.'C>=Q$l`.e>=$.0J@ε1 [+%2g`4EEF +[`>IX\.m>=0.' ?J&  `:Ӂd%/=F`:+`>IU`YA(+B=iA'?Iz~.('B>=0$' ' +?N7 `:I".'C"߸*.'C>= +$%.A>=:$nI.X0gAN~[ĶI%5` >=0 ' Ua5` ?Jt&5`:ʁd `*]`>J7ߵ1[+!.볗+g`4<<= +[`>IOS.d*>=0y.*'?J.ˁd`*\>N [";G.볗QIa%le` >=0'.` ?ԁd͛ߝ`:]`>J` 41E[+L.볗V+g`4eef +[`>Ix|.>=0.'?J+Ձd(Z2Z:`:`>II!%UM`:>=0is?N[.볗I%݁:` >=0' .&:` ?J9DNցd_x|`*`)]y`c>J Ƶ~.ׁ́d2k:kH`*_`)],`c>Iy"!%}N`!%\`>=0?Nڠ],`c1`c=+Ԃ?鶅%.5NH\JZa؁dpwA`:J$'.'́d +[`J"%Ѐj],[!j],[9(곚́d +[.`:[>@D.ỤD^Geumv>J泜>NU` &`:&MMEN`Js~.U>Jo'8kײVءE٤ڀ ܪݳLކ<)g#y /Jށdk(`aɇ"ɡ("``>=0'dY]igi`dnt`d`d`d`d`d)`dK`dp`d`d `d `d `d `dE]`c+dX!`*dq"`*d`*d#`+d$][ߦ[d +``(`\>=;.L +`cY.YV.V.i)  d=%=`>J #.#(++-(.#`dB_zfz]y`cJiti.d6Y6\>=1[+...g[41 +[`>I%'`>=9.#D]`=p.I%`>=.``Y=.w>=.S=.wd;@{VH{\>IQ!V.">=k.?d//][>=.!)I!.">=.w?J%.$ud49=\>IFJ.!>=\.wJk?I}".\.">J?Ní`.%I逭(+>J?= .")=k8M1`[ag[4ppq[`>=."*I%a],[>=.@a],[(Y(ѮE`ހ a],[(YW>@3/-ވ(-7AGDRLa],[5`S5`ST}W}9ll>=.:&a],[9`B۴>=. &''!a],[(9`B<TT>=wl.&a],[9`Bô>=.Sa],[9B>=,.!)JK>=.'&dױܲ33\>=.w=.$t=$.#+d8=swBs\>IKO.>J_?Iqu.">J?=.)N`.%Iڀ(+>=.>=S51H[Iv`.𳗴dx}S[\>N'[yI偳(賛>= +."I?MC(P>Nn([yNU` &ǂȳ`:&`N%/)[81y9IN\R(+>=o{(.)uI%„`>=(&y],`)u?=9..Q'*&`:/>=.'&y)?\ egv+` e,`) +e-`) eP.`) e/`) e0`)\? ZfP1(`\? aF[ȳ[(dl2`}d``\>=0'3g &f.` gt` &g4 '5`еg` &g6 '7`g` &g8 '9`g:` &g; '<` g=` &!g> '?` #g6 @`&g@FdNXd^@`\?# F'g-` )g*`' ߵ5*g)A 'B`'2)+ge`' w5,gC 'D`'е+-g E`' #5.guF ='G`'-/gH`' 50g:I 'J`'O/2go 1`5gyN1`\?2 &6g S+``c#8glt)x)`:`6>N`Iс(+>Jl?J K l9gM``6Jе8ـ:g_gw``6>JõLg`:]`6?gʫϫ٫`:`6@g,9M =ME`:]`6Aghmu}`:`6Bg (]`Cg`[g`6Dg˱]`Eg-+-`Fg +((#|`][Ggôִ|`\Hg]`IgLUgeg`Jg=DbSb]|`][Kg&&!|`\Lg`]`]MgPait``]Ngp`+y`+]y],`OgBB BNBBNB`B.B>`BH(`3PgCCC%C#C%]],`QgCCCCC],`RgDDDDDD`Dׯ(]`:SgEEEEEE`E(`:TgFFFFFF`Fί(]],`:UgGGGGGG`G(],`:VgJ-J:JJFJJQ],`Jh`JwJ`*]`6WgLLM$LM$L],`L`M +M`*\XgOOP#OP#O`:O`OO`P(P`*]`6YgRdRiRRzRR`:R`RR`R˯(R`*\\gSS%S)S)S)`:O.r +:n8] =k u*mmI#]gVGVV~6`\? _gVVVwVV]\`gWWW\WgLWeWg\agXX XMXX]`bgXXXNXX`cgYFYXYgY\YgYa`]],`dgZ)Z3ZFOZ;ZFZ@`],`eg[[\+P[\+\ +],`\`\&y`+]`fg]]^ Q]^ ]],`]`^y`+`gg^^^e^^^K`]`]hg___R___K``iga"a;avSaDavaO],`ab`aqy`+]`]jgbbbTbbb],`b`by`+\kgccd Icd c3`:c`d(]`]lgdddUddd3`:d`d(\mgesee1ee]`ngfff,Vf*f,`ogffgWggg1`]`]pggggXggg1`\qghhhhhh(`]`]rgiKiPihYi\ihia(`\sgiii(ii]`tgjwj{jjj`ugkDk]kdkbkd]`]vgkklZll\wgrrrrrr`'rҵ+r`ry`rW]`]xgyyy[yyy`'y+y`yy`y┃W\yg{{| +\{| +{`|y`|W]`]zg~~~0]~~0~`~&y`~,W\{g~~~A~~`:}g~~~~~`:O~ +rT  n   + +^ + +  E t   D   l  g:@v2``g( `:g `:g_ ` g`-`4`:'G`:'W` +\? geltAtt`:>N`=]'2I!. `>=]$'.I! .(+B>='$]$?'^9.'?IP!\T.(+>=ro]$'|.'?I!.(+>=]$'.I!.(+B>=]$ '^.'?I#!,'.(+B>=@=]$O'J.?J\fc]A,h7=_]y],` +hK]],`+h`:h``]+h g`hA`h4 a][J[hb`*hc`)h `*hd`*h&&17`:Cg`SA`\>I_mc.g(+=v.g? &he\?++ hՄۄa],`\ +b`+a\+'`+]],`>==.fJUoh\.Kvb炄胄h΄Ӆf\>=.K +],`i)YA.HV[.g4yy][>=.b)J.hhЅׇh][>I".c. >J).au?=;. )OPUa\Y\>=td.at=.Kw=.`w_i.Kv)J +.auhg(\>Inr.cJ?I.d>=.hJ?=.c)Ni`I! .A(+>=++h`/+?:.AyA.gISaW+>=p.c*I!.b>=.K$'j.A=.h=.b)?J<??=rbV.`g+cg[4wwx8],``>=.c*I.b>=.hJ?=.g.gWY(YI"!Y(Y#+"!61.A(+KA.g(N.A>=_.d)?I|"!.d!.K\>=.g?=.KYI.d>=.h?i4$$%l[([`>I3!8.b>=]Q.Kf&ii`=u.h=.b)?hHÏ\>I.g>=.K$+'k!.g=A5.Kw=`P.atJr?Ola`]\`]\>=.`=.c*=.gOma`]\*$`]\>I2@6.gw>=kTO\W`.gog\pb4l[[`>=.K&`=.c*=.h>=\O16na[[\@AS[HY[\>=h\.Kq`&xxh`=.Kw=.atI!.(+B>=(8.Lg\-BbBG>K>=zpB[l[`>=GPYk+Bhۏᔵo]],`h p`6hBq]`]+hRRekp`6{`\>=.q.pL Rhrёs`\>=.q`]~+ h!.I7IJ ]y],`]`6>Nhr]`6x`6=.qg[4t`]`>NQ[OӑS^[`\ݒnl[Y`+\>=^=/$Iw_=J@ jX[=w^4],``>=^ZK>=삒IS  (Yig[47p`][J!/!^]bBjT[[l[^Y`>={vj|4`>= t.pbj)i jJ.?5 uhN[w`]`6Jlxl.qg\4}}~t`]]\J w_g`64p\`6J.p T hL8u(`c`6h7`:+hJ볗`+hWW#\#d`:\>Ip!%yt!r`:>=0$!r'?=.!r=.볗 !r Wh((.9.D`\>IS_W"(+>=0pz'?=.볗ɶ"=. "" (:h3>KCK`:JFF.hOZvk`Jq|h&w& `],[][>=ف#"ߵ:J +##"ˁh+8J>J]`>JGNpq1|[+.볗g`4E +[]`>I#>=0߳#'x.?J/&/6#]`an~~(``[>=0'ýh::`>N[̷.볗=$'z.J)&)0$`h?HkQk`6JTX8].ṕhp}%%`*]`6>N][#%f.s)[+][Jz%g[4op[][J00Rr1^[+e.볗g`64  +[`>I&)>=0³&)'{.?J.aU(U``[>=0+1'|aZj}j(u``c`:[>=0'~a`(``#`[>=028'΁h&-`*\>IFJ'>=d].s)?N[.볗=Ƶ''{.h `*]`6>I37(.>JJ}eU_.)}g`64p`c`J.?J÷s1[+.볗g`64 +[`>I(>=0,2I('i.?J~.aeuu(``[>=0'al(l`)`[>=08>'h49BDBK`*\>Idh)>J{.볗)~?Nѡ[ڵ.볗=*6'9.ρhGTZb`:]`6>Jqxt1[+.볗*g`64ϣ +[`6>I泽*>=0 6*$b'Y*'d.?Jy8*aq(```:[>=0'a(`3`C`:[>=0RX'Ёh^c(m(u`:`6>N[.볗,1=ȵ,F$',1'.J 8,1сh-:} >}F`:]`6>JU\u1[+.볗,g`64x +[`6>Iȳ-$>=0-$$B'9,'D.?JYd8i,a(```:[>=0'ҁhܦ᧠駠`:`6>N [ *.볗4. =BO. $w'n. 'y.J8. Ӂh0ª0`ܵ]`]>I""""!.(!.(!50.(A!XS.(d!~y.( >J`]'?J f>v1H[+O.볗^Y.@#g`]4kk+l +[`>I~/>=0/'.?J1&/`.ԁh5Ap(Gp]`>JPW}1[+.볗g`4k +[]`>Iij0>=00'@.?JU&U\0]`a(&2`G`[>=0V\'Ձh«ƬoЬo`>Nݫ[ .볗=)1g'S.J^&^e1g`ցht]`>J÷~1[+.볗g`4 +[`>I 2 >=028\2 '.?JU&2 `Áa(,8`M`[>=0\b'ׁh.7G`>NTW[Yr~.볗=3'.JU&3`؁h +zz#|`][>N3:`A<3~ DJ]d1[+.볗3g[4аu +[`>I糽3>=0 *3'N.?Jc+āa%55(EQ`f`s`[>=0'فh  |`\>N` 4 DN@G[Ieq.볗{4I%4` >=0'.4` ?ځh~+~]`>J4;]1o[+v.볗g`4y +[`>I5>=0ҳ5'%.?J:EU&ii5`Ła +( +``[>=0'ہhγ״紤`>N[.볗=-:6'c.JnyU&6`܁h33|`][>Nٴ`瀴7 DJq +91N[+U.볗_7,g[4vv.w +[`>I7>=07'.?J+Ɓa ( ```[>=0'݁h|`\>N˶`ـ8U DN[*.볗48hIA%LE8` >=0`j'.8` ?ǁaɒ0ɡ(Β0```[>=0'ށh+3>`M`]>IZ""""!c^9e(o!9e(!9e(!ɀ9e(յ!9e( >=0'?Ncf.[hy.볗9e@#=:'.J۶1&:`.ȁa5II(SXs``>=0bh'Ɂh+CQVs``]>Ndg.`it:I};(>=0$':?J1;'߁h n%n+`+6y`+]y],`>JBMY._;f;hsz``(`3>I"""!̀<(ٵ!<(! <(!83<(D >=0]g'?N`.<J7<<h*@X5@X]],`>O>Pa`]]],`_.q`]]],`>N` *N]],`Ʀ],`Oa\\>==Icg[4],``>I(81,=(Yw>=SK=hW==nj=>==t=hb䃾=j==J"=uJ5C<.g],`4HH@SI`]]],`>JW@4lc^>(sg],`4qq@2r(`]],`>I?L(>J=!>?J@@@>@"?Lcv@F@A>w_h@]@gB@vB],`>N@@`]@.L>N@],`N@@(`@Ҁ@@tI@@@@U(>NACAK`AQ *DAt>=A@?AA@OAdIAAAA@?(Yw=A΃A@A@??AAA@?(Yw=B@?BB @>=B7@?BEB>@OBN@UdJBeBl@?>=BB@L`ʁhBBCBCB],`B``:>K>JBCBB CAC[Cp[>=0C(C2$C'CCzB K'C.hCCEeCEeC`CЯ(]`:>NDD`DJDDD.g`:4DDE`D],`]`:>K>JDD.EC/E BE[E#l[>JE0E;`:EHCEKBhEjEqEEEE`E(`:JEE.E.EChEEFZEFZE`F(]],`:JFF8F.F.DUg],`:FR FChF_FlFF{FF`F(],`:JFF FF.FDhFFH9GH9G ],`G"`G1G=`*]`6>JGRGjGY.GdEg`64GoGoH4Gp`]]`6>JG~HGGGESGEkGGEk(Yig`64GGHGp`]]`6>IGłGEJGGG܃GEug`64GGGGp`]`JG.?JG.vH'H"Ew_hH>HCIjHSIjH^],`Hu`HH`*\>NHH`]H.HGEL>=HHGnTHG/I +IG/(YjIIIGY=I+I$GnZv?>=IUINGnL`hIoI|JIJI`:I`II`Iگ(I`*]`6>K>JJ J.J)J HZJ0H6JAHFJNHnJ\[Jcl[>JJnJy`6JHhJJKmJKmJ`:J`J޵J`J(K`*\>=K$.K>K5IRKEI.KVI>KcIfhKrKyKAKK`:JK$K'K.'hKKL6KL6K`Kk`:K`:[>IK%KKJ0` >=0KLLJ?LJML%J0` ?"""#t$A$% %G&v&'''y( ),)~)*t+U+,,--.0 01?1223`4A45P6 6r678789F::;w;<?ABCD,DECGHIIJJ:hL;LJMLJ(`a^(^!``>=006'6hLLLLL`hLLLwLL`hLLLMLL[hLLLLLL`[hLLM PLM L],`L`My`[hMMM$eMM$MK`[hM(M(MWSM1MWM<],`MH`MSy`[hM[M[Me1McMe[hMiMiMWMtMMy1`[hMMMMMM(`[hMMM(MM[hMMMMM[hMMMMMM`M`My`[KL L;LiLLM,MfMMN)NcNNOhMM``]hN `* hNS `:hNa`*hN`+hN`+hN#`+ +hs` h|M`*1hNNONON`N`:\>=O.#OO(PC=O6.OJ .=Og. PR N"hOOOOO\>IOO. >=OηO.?hOORP +R[>IP!P>=Q-'Qx=Q'Q׷=Q)?hR!R.SJwR3SJ]\>JR<RRC.RXx1Rc[+)g\4RRSER[`>IRRRR(RW>=0RRµ'R. ?=S."S . SSR(Ŷ =S(.hSOSTT.LS]T.\>=Sf.NSS.`SS.#wISSSR(SW>=0SS'S. ?=S."S. T TR( =T.hT3T?UNMTGUN]`>JTPTTW.Tl1Tz[+g`4TTUIT +[]`>ITTTT#>=0TTʳTT#'T. ?=U!U.JU3&U3U:T#]`hUSUWV=NUcV=`>=Ul.NUU[UU.#MIU%UUT` >=0UUε'U. UT` ?=VV.JV,&V,V3T`hVBVTWVXWV]`]],`>IVj!%VtVnU`>=0VVVU?JVVV.V˷1V[+VUg],`4VVWV +[],`>IVWWVv>=0W&W,WCVv'W\. ?=WWq.&WWWWVv(`NWW],`&WWWVv],`JWWWhWWY-OWY-W`],`>=X +.IX!!%X+X%W`>=0X<XFXTW?NXjXq[XxXs.#X}WIX%XXW` >=0XX'X. XW` ?=YX.&YYYW(`JY&YY#W],`hY2Y>\1PYF\1YQ],`Y^`Ymy`+]`>IYy""!%YY~X],["!YYX(+!%YYX`"!YЂYY(+!%YYY`>=0YY?=ZYZ*Z:XZAYZMZFX(YIZZZbZ^Y(ZeX>JZtZ`?NZZ(`ZZYyZXJZZZ.ZԷ1Z[+ZZ;g`4ZZ\,Z +[`>I[ +[[Z>=0[4[:[QZ'[n. ?N[[`&[[[Z`N[[],`&[[[Z],`=[̀[X [X[[XW[[[[IO=\[.\ [J\\![h\6\:^pQ\F^p\Q],`\^`\my`+`>=\y.I\""!%\\\/],["!\\\D(+!%\́\\D`"!\\\T(+!%\\\T`>=0] ]?=]0\T]A]Q\D]X\T]d]]\/(YI]q]y]u\T(]|\D>J]?N]][]].#P]\/]\D]\TI]%]ރ]]~` >=0]]'^#. ^)]~` ?=^J^<.&^R^R]~`J^_&^_^f]~`h^u^_e^_^K`]`]>I^!%^^^u`>=0^^^^u?J^_(^._ +1_[+_ ^ug`]4_-_-__. +[`>I_@_D_U_>=0_j_p__'_. ?=__.J_.h__a8R`a8` K``>=`.I`1!%`;`5_`>=0`L`V`d_?N`z`[``.#e`_I`%```` >=0``ǵ'`. ``` ?=aa.Ja'&a'a.``ha=aVeBSa_eBaj],`a}`ay`+]`]> Ia""!%aa`],["!aaa(+!%aԁaa`"!aaa(+!%baa`>=0bb'?=bXabibyababb`(YIbbba(ba>Jbb`].?Nb`K>=cb<c c0`c8ac?acK[cRl[>Jc]ch`]cubNcc ],[c.[=ccb+:=c„cbcσcb<:=ccbccb<:=dcbd dayddayddb<:Jd)d]d0.dEdTbg`]4dbdbe=dc +[`>Idudydc>=0dddc'd. ?=dd.e +eayee ayeeb<Je+.heGeLh_TeYh_ed],`eq`ey`+\>=e.Ie""!%eed],["!éed(+!%e߁ed`"!eed(+!%f fd`>=0ff('?=fgdfxfd߂fdffdʁ(YIfffd(fd>Jf?Nff`fg dʁg(d߂g/dNg=gD[gKgF.#SgdgUfg{glfggdyggd߃yggfIg%ggfN` >=0gg޵'h. h fN` ?=h-h.h:h6dyhCh=d߃yhThEf hhdh}iaIhiah3`:h`h(]`]>Ih!%h́hg`>=0hhhg?Nii],`i#igi*gJi7i>.SiHh iViQh (Y!hifikjJUizjJi3`:i`i(\>Ii!%iih`>=0iiih?Nij],`jjhjh=j#.Tj1hj?j:h(Y"hjOj[kJ1jckJ]`>Jjljjs.jy1j[+g`4jjkEj +[]`>Ijjji>=0jj泾ji'k. ?Jk/&k/k6i]`#hkOkSlVk_l`>=kh.Nkk[kk.#1Ik%kkj` >=0kkʵ'k. kj` ?Jl +&l +lj`$hl l9mLWlDmLlI1`]`]>JlYll`.luz1l[+lkFg`]4llmGl +[`>Illlk>=0ll鳾mk'm . ?Jm5.%hmQmVn(Xmen(mj1`\>=mz.Nmm[mm.#Wml5Im%mɁml[` >=0mm絈'n. nl[` ?&hn-nFoCnNoCnS(`]`]>Jnannh.n}{1n[+nlg`]4nno>n +[`>Innnm`>=0nn㳾nm`'o. ?Jo,.'hoHoMpYoYpo^(`\>=ol.Noo[oo.#omIo%oon ` >=0ooԵ'o. pn ` ?(hpp#q (p)q ]`>Jp2pbp9.pN|1pZ[+g`4pgpgqph +[]`>Ipzp~pn>=0pppn'p. ?Jp&ppn]`)hqqqqq`>=q(.NqCqJ[qQqL.#(Iq_%qjqco` >=0q~q'q. qo` ?Jq&qqo`*hqqrqr]`]>Jrr2r +.r1r*[+g`]4r7r7rr8 +[`>IrJrNr_p>=0rtrzrp'r. ?Jr.+hrrsZrs\>=r.Nss[ss.#Is)%s4s-qY` >=0sHsR'sv. s|qY` ?htdtht̳tvtt`'`Jtttq12,httvtvt`'tӵ+t`ty`tW]`]>Iu""!%u urE`'!%u$urY`!%u5u1ri`>=0uGuQ?Iul""uwuqrYuuriuW"!uuri(uWuurY^uri>=0uu?Nuu`u.̳urEJvvIv.v1v&[+v-sv3rYv:rig`]4vNvNvvO +[`>Ivavevvt#>=0vvvt#'v. ?Jv.-hvw x\wxw`w&y`w,W]`]>Iw7"!%wBw<t`!%wSwOt`>=0wewo?Iwwwt(wt>=0ww?Jwxw.w巏1w[+w +xtx tg`]4xxxx +[`>Ix0x4xEu>=0xZx`xwu'x. ?Jx..hxxz[xzx`'x+y`yy`yW\>=y!.Iy8""!%yBy=vI`'!%yZyTv]`!%ykygvm`>=0y}y?Iy""yyv]yyvmyW"!yɂyvm(y̔Wyځyv]^yvm>=0yy?Nzz`z.̳z+vINz:zA[zHzC.#zMwzSv]zZvmIzd%zozhw` >=0zz'z. zw` ?/hzz|C]z|Cz`zy`zW\>={.I{"!%{#{x`!%{4{0x`>=0{F{P?I{k{u{ox({xx>=0{{?N{{[{{.#{ +{x{xI{%{{yH` >=0{|'|,. |2yH` ?h}z}~}%}}`J}}}.#h}}'}'} `}],[}`*][>I}}. >J}~ +[~'~>. ?I~P~T.>N~r~vk`:'J~~[~ŵ~z~. ?I~~zh>=p.) ?=.)=zV.%:JҷzGzVv4"`>=.*h,1@\>IIM.>=0gq'. ?I. >=0굈' . ?PQ$QRSTUWfX\^M_`dg|hri]jUkl lmnozpCqqrtv!xZyz{|U"2im0` +4i`2 E5i7 '`2>46iT`2 fE7i '`2˶68i`2 E9iG '`2N8:id`2 uE;i '`2ٶ:=iڳ],`2:`2 4?6c8:>i 1`EiN˄1`\?>~W Ai܄۳``2J  =~9Bi 'kA/k`:J5d:5`:''''e.1>9~~!FiDJ/J(` Ii1`Jiܳ`Kiݳ`Li޳`Mi@`Ni1K`7OiL߳`F ^bPi; `Qi `Ri `Si? `2Ti `UiM B`aiVVNhn`|```2`B`\?PqQ~RSTU Vbiƌ~ⳗ~\?P+Q+R+SQ:TU|W XaX㳗(X`!`:[>=0-3'[i`:`F>N *`8IESI(+>JdkY}?JYiƑ=峗ב=`:`F>I**>==jUqj?N[XԀjI%` J޶O?JaU&@@<AJ`]U&K`U&ˁ̶L`A&I`&M`&11-2N`\ii“i`:]`F>N`I (+>J,3Z9?JJ[Q`Zin泗`:]`F>I޸*>=y %y?J6}Ce1o[+vyg`F4 +[`F>I>JضO?N9>],[&9H@],[JS^aU&J9`U&K9`U&7738L9`hA&ttpuI9`&M9`&N9`]i×uA˗u`:J$u '.S'.P'.Q'6.R'P.^'n.BU^i%`:>N2>`E@.T7NV\],`::^`:''''''''N],[1[I!Ȁᅸ7(=ނ>';?I! ᅸ7(=>';?I-!G>2ᅸ7(=TM>';?=5],[j>5[yw}779;5[79;5[Ӄ܁通ᅸ79;J>gJYG6ciDS{!S(`fio`:+gi볗`+hiNU`N}'iik`#k7*kM'kw'`\? 1ki`:liv~M`J .kui%2:8:]`vi`wiZsy`:]`cxi `:`cyi!i5i]`:>J>Kvw1[+.볗gg`:4d +[]`:>I>=0곾'9.k?JN&NU]`:zi_f#~#`:>N[.볗g=ж:'.kJ&:`:{iʸ۸߸]`FJ\.k|i`FJ[.k}i8~>~E`*]`cJaa. t~iAjAoAAyAA`*\JAA.AyiG^GvI#G{I#G`GG`*]y`>NHH`:HH:.kNHWHa`HoIH|HH.(+>JHHHHՁH?JHHH.II ՁIiI(IAIa IHIaIO`*]`ciIeIjIIuII|`*\iIIK IK I`:I`:]`>JIJ1IᵶJ 1J[+J"rJ)g`4J6J6KJ7 +[]`>IJIJMJ^>=0JsJyJ$J'Jr'فJ''?JJ&JJ]`iMRMfN<MoN<Mw`:M`:]`>NMM`MIMMтM(+>JMM鶃MM?JN NNרN+N2miOOPpOPp`>IOO*>JPPP +.kRPhD>JPKPWPR.kR'DniQQQQQ`cpiQQRQR`:>IQQ.mJQR.k?NRR'`:R3R+IR="RIRAh'C"Rl*RRyh'C>JR$RRhR.k>JR$RRhR0R.kqiSSU7S"U7`>IS(S,.mJS8S?.볗g?NSQSY'],`SvSmSe볗g@SSSl(SS=SSl7IIS"SSSl(S'A"T*T0T+T#l(T8'A>=TYTQlT`.볗g=TTlTT(Tи0<=TTlT.볗gNU}U[UUԀUDUS=UUl'JV&VVl`iX XXX%XX-`:X;`:`>NXTX^`XlIXyXX} (+>JXXXX?JXX؂X XXriYtYZKYZK`>NYY`YŷIYYY(+>JYZ ?JZ"Z3Z)ڨ iZZ[* +Z[*Z`:`J[[&[ [ [(['d`i[/[@\I [Z\I[e``>I[n[t[r(+>J[+?I["[[فC![[[ف(>N[[`[ե:[[[ف(YW=[[V \\ف(Y\OJ\\V>J\7\>i\N\\]| \r]|\}``:>I\\\(+>J\'?N\\ `\I\\\݀\(>=\T]"]]ޓ]-]&]$(Yy?J]=]I]D(]PT)ui`%`I``M``U`:`g`)]`2>J````2`Bic/cKccScc[`:cg`)`2>Jcccccidd/dd)d5ddd=`:]`JdFdFdQd^.idid}dddd`]`Jdddd*g`4dddd`2`JddӁd(d8ie?eSe%eYeea`:]`JejeejeseO)g`4eeee`2`Jeee(e4iff.f'f9ffA`:]`JfPf~fPfYff)g`4ffff`2`Jfffv(f6ig/g;gx*gEgxgM`:`JgVgVgegrig}ggggg[`Jggg&gg>`*(g8ihJhVh&h`hhh`:`Jhwhhxhh)(h4ii&i2i(iAiiI`:`JiXiiYifis*)(i6a(```[>=0'a"22(BN```:n`:[>=0{'aɊRɡ(ފR``[>=0'illolol`:`:>Nll`lWImm*>Im"m+m&Rm6hD>=mmmm'EImmm(m딃WJmm?In "nn R'Dn+n&R'D>=nFΓ?InfnonjR'D>=nΓ?No o0`ooUo#iFIo7o?o; woA>JoRo^oYXoook WHIooo΃woW>JoooXooWH>Jo'%sipp-pTp4pT`Jp7p;pEpN.kipYpuq|pq|p`p``2>Npp[pǶpԀpp=qq'JqMqiA&qqqq`iqqrqrq`q``2>Nqq`rIr rrj(+>Jr,r3rFFrOS?Jrgrxrnjrr(rF)urSirrtsts`s$`]`2>Js7ssDso1sy[+s3s@g`24ssts +[`2>Isss>=0ss߳s't't"(t.3)u?Jt]tyA&tt`ittutut`t`]`2>Nuu`uIu+u9u/(+>JuJuQuaiujv?Juuuuu(ui)uuviuuv uvv`vk`:v `:+[>Iv-%v8v1Z` >=0vLvVvjivowvuZ` Iv%vvZ`>=0vvZ`?iwwx!w+xw3`:`:>Iwi!%wrwm0`:Jw~w0?Iww*>Cw"www0(^w"wـw0w0Cxw0'C>=x0x(x#0XxAx:x50(^yH>Cxb"xuxnxi0(^wxx|0x0C>=x0xx0Xxxˀx0(^yHJxx0iy7yE{"yb{yj`:`:>Iy!%yy`:Jyy?Iyyπy `=y'%?Iyy*>Cz"!zzz'0C!z?z:'C>=zX$zzazp0>Cz!zzz0C>=z$zzz0J{{2WEP H_: +m'{; _ ?0.1i{e{k1`i{`{i|4# |'$`|?i|`|i|% |'&`}i}~`}i}B }''`}єi~E(`~Ni~) ~W'*`~i&`E<3,k5k>kGik P'+`kkki,`Ҕi-`7i.`7i `i) `:iA '`iQQpbh`s`:~'`\?%4C Qi/`i pp"p#[)'[\? DV&^^`:&dd`iu|A`:J$'0.'1'qi2`i 3`āi0p0['[3`\? &`:&$$`i5<AD`:JP$'4i.'5.3'EŁi6`ʁitp&t'[-'[\? HZ&bb`:&hh`ǁiyA`:J$'7.'1CˁiG8`́i `:ҁi`p`[ '[`:\?͂ 6H&NN`:&TT`ρielEAtE`:>N`=$'9.'I!.(+B=$ ':.'?='J)70AahӁiJP;P(`\? ցaŻ8<š(˻8`:``]y`>=0'=؁a=V>V(b`>=0hn'?)gہj@`݁j `:ށj. .`jR`jxA`$5`$95[ހ2jB`T Dj11n@nF`:\?݀Xc 1j4?CKCC`:j,C,`[J W&D.7j"E""][`:[jքF脄][`:[J2`:['$S'N.'.c..'Kw.KjG`J5`5`W 5jH`jI`jJ`jK`j,L`jAM`[jTN`[j `:\?(( j',38`\>=E.IOE.IWR!=].Kf].KW=n.MjTYwO`w\>=i.j|`\>=.J.JW=.L.LW=.NjÈ܉E][`:[J2`:[ '.'...'K&.K'IA.I'Jd.J'K.K'L.L'M.M'N.N4jP`jL1`:'pjf [jQ][``F`` jʊʋۋ[\>=.h jR&9`[>@!WMhc.lLk={r|.ހnj S `[>@˷怋5.lˋ=5.vj8TH]][`:[>JQ\0][`:[wpf|[4{{|l`][`:[JFjȍUԍ[[]`>@K('ŌN%*][`:`2,`:`''V'KNhrW`:yt$J`jۍX][`:[>J.Ej#KY]^[h[]`>@&}d'.`}N.`&d'.`:NƎ][[[#׷lmX2[[][[[N *W`:1,$8JEP`a, +jK`:>J$.-=q jɏϗZ`j1`:'Gj0 [jH [`[j|\][`` F`` jCґC[\>=+.f jHShKXh`:J[&[c[.˷`:jmr]y\>=.jEŒ][`:[J2`:['.'...'K.K'.˷'[9.['aY.˷9'#.˷^(+'%.˷^[ju_u` [>@!6%GB.l$J=aQgb.ހmnjz`` [>@ڀg.l=g.vj 3aJ]][`:[JVZ0][`:[|ud|[4l` ][`:[J-Fjɖbܖ`: ][`:`:]`>@'{('cBDNOT][`:`2V`:`''d'|NW`:$JΦ`߳j;eP_`:}][`:`:]`>N.`q'.mN][[[#ĔlĔmE2[[][[[N!+W`:2-$9JFQ`bI¼]Fa jf`#jg`:'h$ji`:'j%j;1`:'k&jj l['jm][`` F`` 2j֘֙""l[\>= /.&: %)j'2K7`:>I=&HHA.l&n`>J]$'oxq.l&&'.l&'?Np`:'K>Nƙq[.l&cNr[ .l&r=$D's-'킚9L[Sl[>J$.l&&'.l&'+jƚStS]][`:[>J0][`:[/('|[433M4l` ][`:[J:<:F,jXmu}][`:[>N][`:[.E=`'v#&.l&w`˷#ط$`:n=`'x.l&nn=`'6.'.l&&n=F@`''XQ.l&'nIb!&fng.l&n`>K>=`'q.l&cn=р`'r.l&rn[l[>='!`'r'yn=LF`'q'yn>=~`'r'yn=`'q'yn=΀`'z.l&&KnJ`-j<{P_`:}][`:`:]`>@ʉ'.lN.`ʁʉ'.mN۞][[[#'l +'mu,2/[[][[[N;EW`:LG$SJ`k`|T.jؠ|[[]`>@˷('}Š.N9>][`:`2@`:`''~'a+NW`:$J`*/juu` [>@!;/'LG̍.l.O=aV'gb̍.ހm̍n0jz` [>@'Ҁ.l=ܷ'.vnǎ1^˙o]3kȂבH4`]],``5k`+ 7kYY c]],``((`3J8k;@hHhIS`\Y`+\?k&I/IB ]y],`][@k][Akzw][Ck7BFFF][&ZΈ$^ϚϿ DkKQ`[`]_Gk ]_Hk ][ɦ[IkX]_+Jk ][+Kk*.`*LkD`*Mk]/`*^kss]_\?G! s Pk\>I.(&ω=:>=0('?=#~'B=mf~'!B=~BTkȔ͕<Е< _\>I..K>=.PJ?=/#.K\3UkAFNOS`bY`+\>Iuy..K>=.PJ?=.K\myVk ]y_][>I.L>=0(2('?Isw./MJ.Z?=.)LNu][#.J(+.G.Jug[4""B#p[][J)1).G;][=5]_I.I#^(++^w][JށQv4 `>=.*LWk#][>I,0.L>=0BL('?I.I(+J[.?=8.)LNQXu][oZ.Ju={.IwJv4`>=.*LXkw][>I.L>=0('?IQ!V..K>=i..)KI!.I(+>=.Iw>=.Q?J .ZQky'y\>=@80.Gwg\E.Rbb.SZk~][J.HuRk!œ!K[\>I!.H˦>=.Htֺ?Sk&+=>S[PY`\>Ib!vg.H˦>=./)M=.Hj$?\kK]_>I .L>=0!+('?Idh..K>=0{('?I.I(+>=. +_i)I=.8[J=qSK.Gi].K\g[4vvwp[`>I.L>=.Jt.=.+J=:.+I>=.Qb4ۡS[Y[`>I.L>=nY.Jj|&`=.+J=.+I>=T.g&nn`S?J.ILOiSa֚|ه _k¦]D],``3bk`ck"`)nk>>Idc]],`q`\?b: ~^#ek`J.bgkUȣUK`\>I!.c>=0('?=@.LڵbikZ_dl`\>N~3`:$I+ `J?=..b+Tjk٣ޥmm][`:'\>N!* +]%[4,ۣ + IB!PGǑ'J\?Ihvl۲ `>D>=.ǂ')iłǑ'>=.ǂ')iC Ǒ'>=*.0۲i=D.SJǂ')ikkrw~~a`'\>=.i=.'Xilk¥ǦԦ`\>=.[*ifڗۅܸ [ol&(`+ql``rl`sl`tl`ul`vl `7wl.`7xl_`7yl`7zl`7 {l`7 +|l`7 }l`7 ~lD`7 ln`7l`7l`7l`7l`7l;`7lb`7l`7l`7l`7l`7l!`7lI`7lq`7l`7l`7l`7l`7l$`7 lR`7!l`7"l`7#l`7$l`7%l'`7&lS`7'l~`7(l`7)l`7*\? aŻܼ6ܡ(6 `],[][>=0 +'rm-<``cmFF`:`>N`ӷI(+>J +?J!2(Ϩ=mKScn``>JIm77M``J!*&⍂mfsyc`:`*]`m38jBjJc`:X`*\m]b{l{tc`:\mЎݎc`:]`m]`:m!(B@B`:m`:]`mۑ`:`m`mUdlcjl]`:m`:+o>l"Rum`c`m`:+m볗`+ρm + +`:\>I#!%,'``:>=0@J$an`'R'?=.`=.볗Ͷ`  +Ёm藔`\>=.볗/J=X.q 趠m`:J.mAŗ`:J$'.'mߗ]`J .볗m"'`1``J7HW.볗menw`Jz~.qmc`:`*]`>I*>=.ó'?N>E][#Ob[.s)[+][J$g[4p[][J1[+.볗g`4))* +[`>I<@.Q>=0fl.ij$'ŀ'.?J.mLL c`:`*\>I37(>=QJ.s)?Ix*>=.ó?Nϛ[޵.볗 =%'C.móc`:`:>N` $ߴ'N` .N)`/ 8NLS`:kZUe0ۨvRۂI""s(^ws@('BȄs@('B>J$'Ȅs>=0p$p'Ʉ:s'W'GǁmÞȠҠc`:\>=.~=.ȁm%y+y3c`:]`>JDTK.}g`4__t`p`c]`Jff.mÁm~D D`*]`>Ih>J"Դ.볗)}g`4''2(p`c`J..?J?Lw1[+.볗g`4? +[`>I.>=0.ij'.?J-.āmINaYa``*\>Iy}>J.볗)~?N[.볗=-:'X.Ɂmfsy`:]`>Jȷ1[+.볗4g`4 +[`>I . >=05;.ij_$'̀4'.?J4ʁm˥Цڦ`:`>N['.볗1=?L4$~'j.'πu'Jˁmc]`:>Jѵ1 [+.볗g`:4##$ +[]`:>I6:.K>=0`f.ij'.?J&]`:́m`:>N [*6.볗=ER'n.Jy&y`:́m11`k`:`:'[>I%〨 ` >=0&  ` ?Łm6;KL +[`>J\"%lc],[!w],[9(Ɓmij +[`:`:[>@. ũG  CC>Jep>NU` &Ā ų`:& `J$8A"G>Jdoo'V?ykGrutсn^mam(`\? ԁa6oӳ6(Ao`>=0GM'Ձatv(`>=0'؁aœԳš(ԓ[\>=0',qہo!`ށoDֳ`+\? oPg'o`>Ju&u5[#(+ހ[`o`\>=׷ހ_oȎnӎn`[sa_a`:`+Fa`+wa`:\+a`+Ka`:`6+1a`:]`F+Wa`:`F+a`:`:]`+a`:`:`+&a`:`]`2+da`:``2+a`:``]y`+ a`+)a`:`+^[`[`{]`+1^[`[]]`+%`+b`+_>N`θɃ,؄G녌t(=^ { + A P y*J׳_2[[q%>Qbb]o&/IDI`[Gsa_[`%`+b`+_>J_y2[[߳%b=o'1e@eH`:`JQU`o"M5M`J;Fo MM$`:\>=;ڀEo..`J$o'K'`:`6J"o11`:]`F>J"Z(/oٖ))`:`F>JY yo)6BJ`:X`:]`>Je}ow|`:`:`>JǶ,o<˛<`:`]`2>J &(%{`,o`:$``2>J7O&ggb(n`uoJbiq`:{``]y`>Jan{o `J̶o`:`Jŷo]]['`[+`{+]`>J EN؂9[QeoJi{|['`[+]]`>Jȁ؂A|P8d[]C'o`o9 Q`Qoܳa`:`oݳa`o޳a`:\o ߳a`oG೗a`:`6o泗a`:]`Fo㳗a`:`Fo᳗a`:`:]`o#ⳗa`:`:`ol㳗a`:`]`2o䳗a`:``2o峗a`:``]y`o#泗a` o[}a`:` +o糗^[`[`{]` o5賗^[`[]]`oMMy^yza`:`a`a`:\a`a`:`6)a`:]`F9a`:`Ffa`:`:]`~a`:`:`a`:`]`2a`:``2a`:``]y`a`#}a`:`H^[`[`{]`a^[`[]]`\?&:Zv  +     +  M op~p`:`>I!.ܳ(+J.ܳ*?I! .Q(+J/%.Q?*?JJWg*ouUv~U`>I!.ݳ(+J.ݳ?I!.Q(+J +.Q?J/<oZkS[~~S`:\>I!.޳(+=.޳I!.Q(+=.Q=6JoXnGY~G`>I!.߳(+J.߳?I!.Q(+J.Q?J+oVgKW~qy`:`6>I!.೗(+J.೗?I!.Q(+J.QK?JKo.K/~OW`:]`F>Ic!mg.泗(+Jv}.泗?I!.Q(+J.Q?JӅo~ `:`F>I!!.泗(+J*1.㳗;]?IF!TJ.Q(+J]nd.Qw]?J]oհ~᰺`:`:]`>I!.᳗(+J&.᳗4;*?IG!UK.Q(+J^oe.Q|*?J*oб~`:`:`>I!.ⳗ(+J").ⳗ; B ?IN!\R.Q(+Jevl.Q  ?J  oα~ `:`]`2>I'!7+.㳗(+J@G.㳗S 遲Y ?Ik!yo.Q(+J.Q 遲 ?Jè 遲 o + ~  `:+``2>I>!RB.䳗(+J[b.䳗r +ρx +?I!.Q(+J.Q +ρ +?J +ρ +o(LF)~SF[`:e`r`]y`>I!.峗(+J.峗   ?I!.Q(+J.Q   ?J"* 0 8 oK\! L~n!`>Iw!{.泗(+J.泗?I!.Q(+J.Q ?J o0A1~KS`:`>I_!oc.} (+Jx.} Y ?I!.Q(+J.Q Y?Jᨿ Yo!~./[9'`F[+^`{+]`>In!r.糗 +(+>J.糗"؂/9 +?I!.Q(+>J).Q7="؂\/t9?J"؂/9o~,-[7'`D[+]]`>IZ!r^.賗 (+>J.賗LU؂b ?I!.Q(+>J.QLU؂;b?JUbuL{U؂bct8  +   4 '5pek` "p鳗`[#p곗`:\$p볗`:]%p>쳗`:b_&p`:`'p`:׸c(pC`_N$('B)p`$('#B*p`Ƹ$('B+p`$('B,p6`P?$('B-p` +$('B>\? /p-=0>D'La}곗(`:>=0'MaL볗( L`:>=0' NaQa쳗a(x[>=0' +OaĖԗ ԡ( [>=0' Pa%5{ 5(@{[>=0IO' Qa([>=0'Ra1AA(M[>=0V\'Sa`(`],`:>=0%+'Tae||(`:>=0'Uaɘ,(,`:>=0'Va(`:>=0'WaG( G`:>=0'XaL``(g`>=0pv'Yq†Ї{ڇ{`:>N`:#F(+ W+F`:I3%>7` >=0RX?Jjq[q*9dLd`JOOK\qhz`:JL]q`:JĸM^qڈ`JX_q#5#L#`:>IRgVH(+B>N|[NI%` >=0` ?=H&`:?JH`q(:H`:>NRY[[OIq%|u` >=0` ?J&`:aq֋],`:JSbq'3][`:`:>I9O=G(+>Ndh[jRI!%d` >N`]('BNً][`:`:#`:4F`:`:][`:`:FS\[&ccd][A>It|x(+>B?N['I&&&Bw`>=?9&?D@XQB`:&?uqXBW`:n?=Gǭ]`:`:>= Gd?I7%M;G` >=0agG>J&G][`:`:cqƏΏ`:JѸVQ ICCEwpK}fqgmw`[]`:_iq .][`:_ɢF`:_\? kqސ88``J"%`:..i*&`:(Xllq=..i ƃ(X noq!#.6 `:= a__>JO[V..ikg!4(Xz!Atpq s][`:_\>=!4’`:K_\J5`:ہ!(X5_!5\.""#n"#xqqHH `_J#%"|`:(#..i3/"|`:(Xv+_rqMRp Wp\>=e`..i wsquza`:_ˁK\\>=..i#2xzqғד]`:J..i{{q  ]_J..i||q-(-`J"'"..i(}}q1:Q BQ`JEJE..i ~~qU^{Ci{`Jlql..iCq2]]`:_J..i2ztqʕ#Օ#3`[4`[a`:_ˁK]__][__J..i__%#ouq(*08 `:? a_K_S a_+_Jini..iyu%(X%%qvq7 a`:_ˁK_\>=..i7&+rwqL La`:_ˁK`\>=72..iC&sxqQXuA`u`:Jfkf..iAb / !!"^"##n##$,$h$$%|& &i&'rPV V(`\? ašכ!ס(ܛ`\>=0'"a$9#9(EJ`\>=0X^'$a%(`>=0'&aX'(X`\>=0'-'(a]q)q(u~``>=0'*aG+(G`]y`>=0',''(3(s())TrY_]-_(`\? ai.(`>=0'/a˝ 0( `>=0'1))*4rM2` r3` ߸r14 '5`:r6` r7 '8`rfP` wr9 ':`ָr^;` xr< '=`븛r @`r%KN?KE@`\?+ %r#*],`J-:-`O_urA`:J:`:'3'6'P';.@9++,GrG>(`\?  +r+333]`a>^^(ck`:],`:`:+][`:`:+`) `*8`P]`>=0_e'?a(`:],`:`:+][`:`:+6`)b`*@`A`Ƴ]`>=0'Ba )C)(08`:Q],`:j`:+][`:`:+`)`*@`-A`>`>=0U['DaE(``Ӹ`>=0'FrCIC_CeCeCe]y],`rCCCCC]y],`rD0D;D@D@D@`3rD}DDDD`rFFG FGF`G`,,-y.;./U///0#0e +rGGJG`rHA `rID [rJD [rJ `rJJJJJJ`J`J[J[\?1!101?1J J1rKLaH`<rL0I` L?'JrLzK` L'LrLM` LԹ'NrMO` M'PÁrMZQ` Mj7'RārMS` M7'TŁrMU` N7'VƁrN<W` NK7'XǁrNY` N7 'ZȁrN[` N7 +'\ɁrO]` O/7 '^ʁrOl_` O|7 '`ˁrOa` Oɹ7 'b́rPc` P7'd́rPSe` Pc7'f΁rPg` P7'hρrPi` P7'jЁrQ:k` QJ7'lсrQm` Q7'nҁrQo` Q7'pӁrR!q` R17'rԁrRns` R}7'tՁrRu` Rɹ7'vցrSw` S7'xׁrSSy` Se7'z؁rS{` S7'|فrS}` T7'~ځrT@` TP7'ہrT` T7'܁rTJ T'`U݁rUOL U'`UXށrUN Uc'`U߁rUP U'`UrVIR V +'`VSrVT V_'`VrVV V'`VrWDX W'`WMrWZ WX'`WrW\ W'`WrXA^ X'`XKrX` XW'`XrXb X'`XrY@d Y'`YJrYf YV'`YrYh Y'`YrZ?j Z'`ZIrZl ZU'`ZrZn Z'`Zr[>p Z'`[Hr[r [T'`[r[t ['`[r\:v ['`\Dr\x \P'`\r\z \'`\r]?| ]'`]Ir]~ ]U'`]r] ]'`]r^@ ^'`^Ir^^ `r^| (`:r^^^p^^^`^(`:\?:: ^r^^^A^^`:J^^.(rawaaaa]y`Jaa.:; ;Oraab``ra `:rb [ rbbbRb-bRb3`:bB[+\?;; brbWb^bAbfb`:>Nbsbwk`:'Ib!bb.(+>=b<>$b'b.?Jb$b'b.b<>< < +rbbe`` rcv `: rc ],`:rdD `:rd `rddeded`:d],`:d`:'e `\? =[ =j== dre e'eAe/e`:>Ne<e@k`:#eKeC.(+B$er'eg.et.`:Nee`:ee.̹ 'RJe$e'e> 'e.¹ 'Re>\=>s{+]y`As k`%$s݁݁pk`%\?? ݧsTv5z &['````*`*`*J],`:+i*`*]`>J1 ?S?[?g?s?"?b??*?g`4ڏ`%`J$@G s=]C]Ia`Al\vb`+a\+`+]`A>J.k`A4`N`AJϹD@@b@炐,@胐K@s'`J.k'9s"&"`;J.k&:swƑ]`J.kw3g`4p`%`J.!s))[\>=.k BE=?5@pAJAAB%Bn%sɒϪ]y`N(s k`])sLK]`N+*syQ]`++s v`-s `.s `/s ],`:,s( `*@s<<pS`k`]tv```],`:\>=.K +`Ni)YH.7Tu.6V.6.7)(Ci+Ct-C.C/C < 1s%J5N V&[c'`y```*`*`*],`:+=*`*]`%>JSs_xDWD_DwD*Dg`%4Ǣ`]`%Jݹ@E) Dk1DWD}D2sģa`N\b`+a\+`+]`N>J(B;/.K)IEbbE炣sE胣E9sأ'`J.k('b:s3Ga&Oa`;JRZR.k(&c3sQwQ]`%>=. ),J%<4,.k(w`g`%4AALBp`]`%JH.5sV[bm`\>Nr[K>=G)Gr[l[>JQ=h}G&&G)`.v+)lG'.-g.../g[4èf`N`>I. ,>=Gw>=B6.K)FGi4sstl[w[`>I!. ,>=.K)H?&HG`?6sͨҩZZ\>I.K)\>=.Q*Z>=H:.Q*]7s_d=~=\>I.K)>=.Q.k(.5b.K).K)w*>=,.w3=sBKQR[\>=t&h`.k([}ID9EnFFGF}FHIII AtӁ$(``Daap( a`N`A>=0+1'Ft[('`E`+Ya`Z`+],`:+`{+]`A>JPJJĂJ5JgJԡJg`A4`N`AJDKWGt~['``+a`Z`+4],`:+]]`A>JO +fQsKyKĂKKKg]`A4]`N]`A>N7>l]`AZSJLHlg`A4__``N`AJnrDLJ`AlLc셌LHHt   l`[+8`+La`Z`+]`A>J&&M [][g`N4[]`N>JR&$ M`g&YUJM]`MĂM"M.g`A4.`N`AJDNItǚl``],`+!`*M`*],`:+]`A>J&&N][][g`N4[]`N>J(S&D@5O`RNhg&~sO]`NtN1NiNg`A4.`N`AJDOLt1@@@`ZMt[fvvv`:Jt""`)`*`*\J6J~K~LN?OOP PVNtds``Y\? PtZy{{['``+a`Z`+],`:+!`{+]`N>=BYPށ_P***zQJPށPQ*g`N4ͨvl`]`N>JRQĂP,Q\QQt$S_`[j'``+a`Z`+],`:+]]`N>J+ RRg]`N400K]`]`N>Nu|l]`N~Rlg`N4L`]`N>JRRĂRR(0R>JU``NlRRRtaal`Cg]`+W[+s`+a`Z`+],`:+]`N>=뀱S|*= +S|*J1I#!_ZS(+łiSwpS|&G[S|'*lS|gSăSSJSStdlll``g]`+ +],`+#`*O`*],`:+]`N>=T*=ˀT*J + T&"Trā?T)lqTgTTĩTةT橭UTTt`)`*`*\Vt~`ZWt¾Ҿ`:PQS^TUUV +V/ZtIX@X(`]aկݰ0pݡ(0`Z>=0'_tſӿֿ``t@ @@@@`:at@G@U@Y@Y@Y`bt@^@i@p@p@p`:ct@t@@@@`:dt@@@@@`et@@@@@`VvVVWW2WaWWWft@@B`ht@`*itA+`)jtAy`)ktB +`*ltB5`*mtB``*ntB`*ptBBBBB\? BYqtBBX]y``N%stCC`7ttCm`7utC`7vtD`wtDC`xtDl`ytD`ztD`|tEjk`}tE ᳗]`qE`q~tEK]`+tF]y`+tFLⳗ]`tFm㳗],`tF䳗`tF &`;tF `tF`tF `tG" `tGM `tGf峗`GpstG泗`)tG糗`)tG賗`tG鳗`*tH곗`*tHU볗`*tH쳗`*tH`*tIya]`NI`NtI`fIѹptIﳗ`)tJ`*tJ'`*tJO`JctJ}`:+ʁtO"O"XO2X O?&`;OR`Ol`O`Ok`O]`O],`O`P `P.`PS],`:\> +IPmPyPq.Ĺ(+>=P.P?=P.KPШ +`i)YQ.TQE.VQl.Q.~=Q.QQ.K~=RmR_.򳗹=RRy.򳗹R.IR!RR.(+>=S R.򳗹S+.?=SXSP.k|)=S~Sv.k|*ISSS.ⳗ(+>=T$.ⳗTBT:.k|TI.bTn.T.>ITTT.ⳗ\>=TT.k|w=0TT'?NUU[U.k|IV&V#V#VV_ k`>=VB.Vb?=5]`V}.ⳗ5[VV_ V.5[VV_ bV.5[VV_ V._ K>NWW`W;WV]V +=WWq.򳗹WW.&GW.ĹW."W.W.X.X6` =XO.Xi[Xpl[Xs`>=X~.XaD XaO +\\\|\]]])]8]G O"+tEEE[E$E[E)``JE>EIE>b^ELxtJJOJO J[J` K +`+K+`+KDl`+Kug]`+K],`+K`*K`*La`Z`+LF],`:+]`q>=LaLobLubLbLbLbLc IL%LLb`;=LbM Mb?NM%M-&`;M6M/b&IMC!MLMGb(+>=M]c MwRMc &MMb`:?JMONM Mc MbMbNbN(bN<bdžNVbهNpbNbNc Nc' +᳗}utXXYXYXa`\Xb`+Y a\+Y`+]`>=Y..JYEYTYL.Y[dbYteYeYetYY]Y]Y[Y`Y`Z`Z9`Zb`\>IZz"!%ZZ~e`:!%ZZe`;>=0ZZ'?I[!%[[e`>=0['[1'?I[i"[{[meŀ[[eŃw7>=0[['?I[!%\[e`>=0\!\+'?I\n!%\\re`>=0\\'?I\"!\\f(+!%]] +f`>=0]1];' ?t]]]']]`J]]].k|'t]]]c]]`;J]]].k|ct]]^ r]^ `J]^].k|rƁt^^^V^!^V^"[\>=^D&^8^0.k|[^Mht^[^_^ +^h^`>J^q#!^^x.峗(^t^^^^.򳗹 ^v9(`t^^_Jw^_J]`N>=_._sJ_)_@_0.aut_O_T_ _k__w `+\>I_!__.a˦=__.at.?t__aг_a\> =_.)=_.쳗)I`!``.k|(+>=`@`8`0.k|wg\`E. >=`r. =`.볗)=`.곗)I`"!`.񳗹!``.򳗹(+>=aa .򳗹=a(.+?IaH!a`aL.ⳗ(+>=aaq.ⳗ?=aa.K~w=a.峗autaad;ad;a`o\>Ib"bbk(b!rb;b1k(bNs>=b\.)Ibwbb{.ӹj>=bb.k|br=b.볗)Ibb.쳗>=c.г???Ic5"cCc9k(cVqcscik(cs>=c.쳗)=c.곗)=cc.k|cqIcd.볗>=d!.г??td@dIdrd\dr`Jd_d_.泗ǁtdwdededK`\>=d.泗dmݹIdƀdm>=dߪ4ddd\Jdd.?te +ee:e%e:`Je(e(.糗ȁte?eHeeYee_K`\>=el.糗en=e.teegege(`+],`>Ie"!e׀eo(+"!%eeo`eeo>=0f +f$fn'ffo'?If{f.쳗>=0ff'?If!ff.峗(ft>Jg+?Ngg#],`gLg:g3g%.򳗹 g;v9gQo=g^.Jgug|ptggk7gk7g],`ge`+h`+`> +Ih"!hhp(+"!%h*h$p`h;h5pՀ>=0hIhS$h'hp'?Ih"!hhp(+"!%hՁhp`hhpŀ>=0hh$iY'iQp'?Iifij.>=ii.K~i'Ji?Ii!ii.峗(itJj?Ijjjp(+=j%pœ?Ij5j?j9p(+=jHpj\jUjPp(Yyj^p?Njojw`jjjj.򳗹 jw9jpjpłjpIjjՃjr҃w>=jj.*j?=k.Jk%k,rtk<kPkk`k`ZJkckqkc.򳗹¹Átkkkkk`:Jkk.󳗹tkklklk`Z`>Iklk.(+Jl*?Nl/l6[l8.lItAIl[%lfl_t~`Jlolvt~`?=0ll$l'lt~tllmvlmvm`|m``>Im"m.m&.k|(+Jm7*?JmImXmP.k|mbumju*tm{mnmnm`\>K>ImmÀmu(mպ>=m.Inn nu(n>=n/.InMnWnQu(ni>=n.?n[nl[nY`>=n.nvnvtnno(no(\>=o.=o.to-o2oqo?oq\>=oH.=o\.tovo{ooo\>Iooo.ҹi>=o.г?tooqoqol[oY`+\>Ipp p.峗(pu>Jp%Ip8p<.ﳗ>=qIq6.᳗}jqWwqZw>=qqz.K~qwqw=q.гtqqtAqtA\>Iqqq.峗(qt>Iqr.쳗Jr?=r.곗)Ir<rNr@.ҹi>=rc.쳗)=rr.K~rIrr.볗>=r.г?>=s.Is(s4s,.峗(s7s>=sP.곗)Ispsst.ҹi>=s.s'+>=t.?ttFtKu@t[u@\>K>=t~tp.򳗹=tt.*j=t.=t.=t.t[ul[uY`>=u.u(zفu+ztuEuJw+uUw+uc`)u`*u`*\>Iu!uu.峗(ut>=0vv ' ?=vrvd.򳗹v{@v{Pv{`=v.峗v۹s=vv.*j=w.tw0w5xwTx\>=w].峗wgtIw|w.ﳗ>=w.ﳗ*K>=w.ww.򳗹繒=xT4xXxXx\Jx^xqx^.᳗}t.x[xS[x`>=xx.᳗}jx|x}?txxzyz\>Iyyy.K~\>=y1.賗y<y1.賗W>=yS.賗y^yS.賗yIyhyxyl.賗(>=y.=y.?Iy"!y.곗!z.볗>Iz$z4z(.K~\>=z\zH.ⳗZ>=zz|.ⳗ]?tzz{*z{*\>Izzz.K~>?t{/{4{w{C{w\>={L.)={g.!t{|{!{\>I{{{.峗({u>J{?I{"{.𳗹!{.񳗹>={.)=|.*=p|J|3."g[4|O|On|P`f`> =|b.|r=|.*I|||.峗(|u>=||.򳗹=|.+J} ?=}/}'.k|)I}Q""}c}U.ӹj}q.!}.볗>=}.~rI~~#~.峗(~&u>J~B??I~h""~z~l.ҹi~.곗!~.쳗>I~~~.峗(~Źs>=~~.򳗹I .峗(s>=0;E'??=.?I.峗(u>J?I 2$.ѹh>=H.)Ii{m.׹n>=.?I.չl>=.?I1C5.ֹm>=l.?I.Թk>=.?I.峗(s>='.??=Y.!i{.?t#`],`>I!.㳗(+>Iw .㳗(Yy.䳗>=0MF8.㳗(YyO.䳗?Nu|],`.㳗.䳗.䳗WM=.䳗.䳗WI +.㳗(Y(.䳗>=2.㳗+?JV]eIp!u.곗>J.k|>J+t\>I.峗(uJ?N&`=6(.򳗹 >x9IT_X$o.#փw>=.*i>=.k|*t \>I.볗J-?N=D`[TF.򳗹 \y9Is~wڪ%.k|>=.k|)?t--A?A[>IH""""!M.鳗j.糗.賗(!.򳗹(+!.򳗹 ܹv9 >=.鳗)=$(.&?tFF&T[>=].鳗*I|""""!.峗(u.糗.賗(!.򳗹(+!& .򳗹 v9 >=C7.K~V=c.?t[>I""""!..泗&.賗(!D6.򳗹(+leW.򳗹 mw9'܃w>=.泗*=.K~Ӻ?tV"V]`f>N /(`!91.峗(=€%!h#W40,b19:=EA€LHhJW[WSbX9y:Jk}g`f4Q +[`f>I؃((>I>=L.l$'*+>= .+$]C;'*XP+?Oa````J&h`Oya````J&ЃӕhW`N`fp="bw9 y(oyjI=*j?=KD"m[Wb\x9 v(oviN`ւb׹w9N+`wI!-#k(70<>=OH)hIhxsl<'(>=)l?=͇<k?=<bx9=k% &xI>!LBk(VO<>=ng)hI<'(>=)m?=<k?= <by9N7?,`DAoEyI^!jbW (tm=)hI<((>=Ά)n?= =)hIć<((>=)k?= VW,+ˁt7=-`́t],`+΁t`+ρty`+Ёt B[߁t + +B[\>=..y&.BЉ`ϹЀy  ҁt. %`\>@"?9.΃wA.yVNH.WPvY.y9\=c.ic.WlIw{.΃^&.B`>=.&.΃y&.B``@.΃v.y@.΀&.B`?Ӂt/`\>@".΃v.y$.΃w*&.yW,1=8.y<8.yW?IJRN.yσ^&UU.B`>=c.y&cgc.yσy&gj.B``@}.yπ.}@.yπ&.B`?فt `J.y(.ځt(`J&#.΃w.y.BW.yy. .yσy.[`ہt$\01\`J4&4#:4.΃w<.yGB.BЃyI.UQ.yσyW.[`܁tai'n`Jq&q#wq.΃wy.y.΃y.yy.BW.y.yy[`݁t212`>I.΃w.yJ.΃y.yy?I.(J& .BЃy.yy`?J&)$.BЃy+.y`ԁt7AAEAJ`],`>IWa[(+>=rz.(>=h`.(Iŀ(J+?N],`:N 2`CWh^j>N}3`h`y.0=‡ ׂW+..O=..+=W+J07ՁtFJOZ4],`ie`u``>Ikw.'>=k.'?N`N5`׼h`k.1C*91փw>=KF.͇ T.y]Y.yW_hGs\O=./=\\W=W=ڼh`ky.1J ցt!D$0D;6a`7],``>N]e`Nrz5`|.1AC҂w>N2<4],`E>jFIV"dZ(+yo(Y(B?NV`(Y=.͇ .y.yWeO=./e=We=.1J29ׁtIN%Zel``>C)>N5`.0I(J*?N `f .&.΁-==..JIXb\ǀd>J)?:OB>T t8(`a (w((5w`>=0>D'9t#*9:`:Y`m```;`\t\t\t `:t#(5<35\t9>IO`e``\t\t`Zt=``t9&90`\t=Bcm>`\tcgq%oq`tv ],`mu EtU?``t. `:tC `:t\ ` thnz`:'` +\? +'?tp`:`:` \?, t&SA.S`:>NDG`M=daj.Iu!z. `>=$'.I!.(+>=Ӏ$'.'?I!.(+>=$.'&.?J;EBAktw@`tuu`:'-` +\? L'@d1mBwtA`tIOcl`:'` +\? 'Au`oo(`a@HH(W^B`*`>=0'Ca2D(2`>=0'E uin{`:`:+\ uRWFitG],``:+\ udiH`:`:+\uIJ],``:+\u]bu}`:`:+\u~KL],``:+\uM`:`:+\uÛȜ N O],``:+\ a7PPP(P~^`>=0dj'Qu I("6,S(+RKAS(Y(>J`k:?NU`S(YNV`E%'`.,퀇0ABAW>NRY(`hd[Se9(^Iv"z7w7v7>=W7>=0$5'W,7'IK^Oԃ^d7 >=0t~'X?N(.`4:>NWcY`Eluw`~|LLLW>N`:SL9=ღ5`95`9W(^:N `E9BD@`KI6SM(^[6\[6W>NnsM`{u6A=##k =5`95`9 +W + 7:I% #w7>J7>hS?JuZի;],`:`>O[a],``:\ \],`']`:\>N=K^],`RM(YNnrV`t(YI?w7>=0$ 'W?'?==4퀘A?;=tk{=ƀ9I!Ӂ(Y^'7 >=07A'X?J;0y3o/k3v>M_`vd``&\? vwa`>I.`(=.`5`5`€W?J.`#vb`][[[v +9c9`:J$9.d'..av>IYdYY`: v^iyeyy`:$v~fb``:>IJ$'.e ?J.e f5z,'wx~g`)wh`' ĺ:*wi`' :+wK-`' W:mW,wj v'k`')-w l 'm`'*.w]n 'o`'c+0wu `:wp`\?0Z 3wUp΄UK``'>Iꀃ(J)?I (J*?=0",$P'qJ5wK`:>G.0ϔW>J'n>J'h>J$'i>=0JT'r7wA`:J$'s.K5;w&W&(`=wӇ t `;J>>a6ZuZ( Z'vi`;>=0ou'w?w +%Cx2C`;J55@@aԤ%yԡ( 'z%`;>=0'{Aw0K_|S_`;JVVBBa*N}N( N'~X`;>=0^d'CwB]qeq`;JhhDDa( 'ȥ`;>=0'Ew5999`'Fw&`:Gw`:Hw],`Iw`Jw\eppp`KwʏՏ`Man(*n2&`:`;>=0AG'WOwA]`;Par*(*`:`'+]],`;>=0'Ra/OO(`x&`;`:`;>=0'.xd!Fq'NSwK(`\\? Uw K`:VwW_ddd`Ww͖],`;Xac(!c`>=0'-'Zah[([`*`*`'+]],`S>=0(.'N]w%4}4(`]y`e\? _a<5(<&['```**`*]`]>=0 +'bwrz~'~~`cwѣ&أ`;`w\t{wy{]`]'fwDSS(`]y`n\? ha_5(&['```**`*]`f>=0'kwz'`lwŭ٭&`;iwdyw~]`fs6\ow(`qwP`o `{rw`o {sw`o {tw? '`oIquw U'`orvw '`osxw [{w&p&[\?xq Ė|wϱմ`~w`| +wa '`|o~w`| w`| w(`| ?wn`| w [wp[\?ő Ŷw]` w,` 9wl` zw` w` wX4 '5`_w6 h'7`w '` wW '``wu `wp`\? w[A[`:>JO:`:''''P.9%zw`[`wJ l]_wj a\wxx8p8l]_+a\+\? @!̀(+źƺ @!(+ź0 xwȻͻӻ\>=.mȟwM(`]y`wH`+wV`+\?  a4VV(]^[h'`u[+`{+]`>=0'aիt(t['`+[+]]`>=0AG'wDDD +DD`wFF FFFFV`+],`wGGGGGG],`Ge`+G`+`wHHH'HH`wHjHrH|rH|H|`wHHH&HH`;wI@ITIacIaIa`;wJJJwJJ]`wKKLKLL`o\wLLMLML`|L``ɋb#O|ˬ/ wMMZMݡ(`]y],``3\?  wRRT RT R[R'`R[+R`{+]`>NRS`SISS*S .(+>JS;SISRSX؂SwS?JSSS.SS؂SSwTTV TV T[T'`T[+]]`>NUU%`U3IU@UNUD?(+>JU_UmU{ +U؂U$?JUUU?U +U؂U$a(((['`[+`{+]`>=0'a-\\(ij[t'`[+]]`>=0'wWWXXX\wXXXXXX`|X``ÁwY2Y:Y>'Y>Y>`āwYYYrYY`ŁwYZZ&ZZ`;ƁwZ_ZsZcZZ`;wZZZwZZ][ǁwZZZZZ][Lϱ'UЄа : ʁw[Z[`[`́w[w],`́w[&`;΁w['`Ёw[[[[[[],`[&`;['`\?̀́ ΂ [Uсw]]g](]y`Ӂw]`+ԁw^`+Ձw_`+ցw``+ׁwa`S+؁wb`+\? ځaX5(['``)]`>=0'wdd d'dd`wdPdddk&dkdk`;ہwdddwdd\܁we;e?exeCexeN],`ef&`;es'``݁wf1f:fCfAfC`ށwffgfgf*`;g`S+\߁wgggggg*`;g`S+\%ӈӶ jԗ#wggkB``wh4 `:whM ` whn &`;wh '`whhhhhh`:h` +h&`;+h'`+\? hwhhijhij\?'+++ hwioivk@Ai~k@`:>Nii`i=iiρ'Ii!ii. `>=iiρ$j'i.Ij!jj.(+>=j0j-ρ$jC'j:.'?IjY!jej].(+>=jyjvρ$j'j.?Ij!jj.&(+>=jjρ$j'jj.&造G?Ij!jj.'(+>=kkρ$k'k.'?Jk(k2k/A֞ذx ]y],`x ]y],`x ]y],`\? x6<Ba],`\kb`+ya\+`+]],`>J.fbـ炂ٍ胂ٚIx(`]y],`xɳ` x6p6]y],`"`\?r )/[x``*`:>NQ`7 N + O`7 +N',],`13`N`""*(̻N!.ͻI>N`AD>=)r0.NIHQLr>Bb?={r;"!r(!"r(&Iք >J+?I &>ACe)>N`.NID>I„ J+?B?I"D( D(B?=-(1D;>AC)>NȊ`.NI(B?I +(>D">=3:.NIV_Z(bBf?=;(?I>I J#+?B:?=XS\;Ju|ڿaI(I`>=0#'aN``(hn`\>=0}'a(ɷ`>=0'a[([ `\>=0/5'a`r~r(`>=0'aN(`>=0'xu~`>K>J.(N`p`>J*ڠ8v޽B߀߾! +x(`7`3 x> ɳ`xLճ`3+x]]pem;`3x`\?  K xؙ`J.ֳ.ɳ xϚ`J.س.ɳ x`J.ڳ.ɳ x.~.`J*.ɳ a9ֳ(9s``>=0 'a>KسK([`s``>=0jp'aڳ(s``>=0'at޳(-t2s``>=0<B'x $`3>I*;..ճ(+>=L.ճ_7j.ɳ ?J.ճ&g1~ x`` x `:!x ` %xK-K3`:B` +\? !! #xPWA_`:>Jh$'. #.!(+'$'.!`:S&x``(x `:)x ` -x!M/M5`:D` +\?()+ !+xRYAa`:>Jj$'.(#.)(+'$'.)`:].x/`]],`1x p[6x==s`\?1+:" 3xBIRe ]y],`][>Nw][[N<[=s4R],``>K>=.p1T[l[`>=歁=0&j>A$boejt)JՁu4x-w-][>=.p1LJ[U7x28R``3:xd =`3Kxnnv|=`3\?:; n =.=:踷5Ax/ / +a`\>=.=:$:Bx49o~@oBa`'\>=\V.=:~dK<Cxty][`:'\>=.=:陁;Dx§ǧʧ ],`\>=.=:9ExRRS`Y`+\>=3-.=:<QC]>FxW\in`\>=~.=:=Gx ]y],`][J.=:?Hx  ][J.=:@Ix/w/][J"(".=:wA=x3>PCP][JFLF.=:Cb.{3<z Lx*` Nx`L ͻ['Ox`L ['Px:`L G['Qxus`L ['sRx '`LNSx) '`L0OTxq 9'`LxPUx '`L»QVx K`:[xpK`:\?Vk Xx(A(`:J$('#.KV\xµ¡(`d\? _a$$(9>s`[>=0HN'`a(òs``>=0'aa(l``>=0'ba g (g!s`[>=0+1'bAey{`ny:@PNP\? @gyU`pKep`:Jh'kyu `:],`J.hly ],``:J.i:hy]`:],`>I!>.2('B>JT av>J ~iyمyy]],``:>I2('B>J '>JU brHoy~(]`:],`vyŅ˅\? ˰qy `:],`>N!],`#t1I=IA(+>=0Zd'?Jry^:^" ;] +],``>J.9Upta@ZZ(go3`:],`>=0}'Rwyk`(zyY =] +],`ycc~=] +],`\?z] c*|yw\>=.=zw }y 3`:\>N],`tI)!(+>=0:D'?=.=z ~yi?i6`:`y`d`\>I"!ꁉ(!((^>= X*1H?=A.E}IRV=^.w|?iVyntt(]],``:yҊ\? yي ],``:>JyPc:y ;] +`:`<>J.a(],``:>=0'\ym`Gy =] +`:y׌=] +`:\? My w \>=.=w ykk$ ],`\>=71.=S` <uzYhh(`\?  a(['``>=0'z…ƅ +υ`zφԆL݆\zQLj],``y`+`z9CVOKVP`],`z`o\z',eT9eD],`Q``y`+\z'`zr`zCW^&^^`;zcϏ`;'xJv1T !`t`` `` +`` `` ``' ``P`b`= Lb1 '`=8bv`M \b '`Mгg4 '`ڵg6 '`õg|8 L'`gc; 0'`yg6> '`S h`.7@h7o` +o^`[a_b`%`][[[_,v`x`x`xB`xf `x!`x3ó`xBij` +xRų` +x"`x#`x$`y%`e 2ny& E''`e n` +[`J"%ـ"],[!"],[9(`22xijHxI +[Z`:j`:[>@{{Gг>J$ '&&>NBFU` L&\\T]`:&`J*곝>J'Ђ3>JMXo'`FVa(xa],``y``>I"%`%ʀ`>J?N(`y!N.8p`>:HfNWY@`[Edmo`vtŀxfW>NK`9I!%`>=0$')?=Ň!:=,-,WJ7BRbQlQqRf*QRfQ`\>IQ"QQwQQQ۴!Q>=0QRR!R8RR!?bRiRnS(+RS(RR`\>IR"RR%wRRR'R>=0RRRS%S'?bS+S0T ,SET SJ`\>ISX"SsSg+wSuGSS-SG>=0SSSGS+S-?ÁbTTUg-T*UgT/`\>NTCTN.],`:TP`Tl1T3T5Tʹ7T9IUU#UU U?(U&W>=0U0U:'/?Łr([( Q`\>I*!%3.`>=0BL'0?I! +>=0'1?=!ɁrxQ`\>I!%S`>=0'0?=SˁrMU}^}`JaoƁr;@2EOt`{\>Nank`yp+I>=0'3?I! >=0'4?=́r̍ԍ؍`J鸉+āx&+57<`G`S`\>=_j=s=́xܭTT`>I(+>= +`4?JEL΁x` +>I(+>=ȳ&޻_` +?J ρx[fm` +>Iq}u(+>=&_` +?Jѳǁx@J6STa[`L>I`%kdZ`>=ZZI"Z(Z(ij>Nְ7`#瀰Z(`G"b6MM>JoN>JĻOճ>JP?I%!Z`>J7HP?IT%_XZ`>Ntv`aZ`I (+JϻQ?Gځ >J.NCC>JarO>JP?I%πZ`_>K>I%Z`_G`>J&7P?K[Rl[>?JQz.i ƻ2մ_c/J!KOR|2[~uxŊ͂=ټ|ks~'^)u*E,X01;`<>BJPVTXY +$M[)uğſLJȬhs^LؽJ)Ze knxn5z z< +h8{"<9|hn:]y[`\? |w\>|d`Jû`|֊֋܋a[\b`+a\+`+][J + +][   5 {Y_=;``m{ `:{ނރ`:\? { ;A;`:J$;'<3.(_{Z(`|=`'>{J'`{?`{ -`{q @`{ A`Ӂ{``"-`5@`+KA`+\?'3? |́'(`J`|&C&( &'B2C]`J55]`|Hhh(v]`Jyy]`ā|Ȃ䃏C(D`]`>I!(!k('CBJ6=k?JMaTwlk 'Ł|r(r`[Ea_\_F`*f`+6a`+Qb`+]`Jdd]`Ɓ|wG( M`],`:[ F`*a`+b`+/f`+N`+u][`:`:+`+`+H`*]`J]`ǁ{r} Z I`+`>=#(+ň+`=.JJɁ| +MJ(M*I`\J??\ʁ|R`]`(frI`\J\ˁ|K(L` +`+\J\́|KM("K,L`\J==\́|P^N^(lrf`\J\΁| (O`\Jл\ρ|ZP(ZL` +`+,O`7\JLL\Ё|_mQm(}'`\J\с|R(Ĉ'`\J׻\{XXZEX&Z]y[>NX=][NX\'`OXfXka[\XvYYXw[\>NXXS`:&XXX`:NXXT`:&XXՃX`:NXXS`XXυY=Y2Y'Y;5YHYB5Y=Y`Yq [i)Y4YYZ#`>=YYͻY=Y.QZZ +dЅ4Z7Z7Z`>=ZK.RZdZ_d=Z~Zyw=Z+JZZZzHzd"a-rMԁ{\-\<aW``\? ց{`-`2`C`6`C`;[\ׁ{```(```s[`ف{aEaMaUzaUaU`J܁{cciUc(`]y[߁{c[1[|:B^M^`=5[|ltVt(W``J`{ggh<gh<ga[\hb`+ha\+h-`+][{i8i=iDwiBiD\{iiidii`AG{iili(`|FNN(\ca[\+`Jww`{kkkkkkX`\{ll l'wl%l'\{lwlldll` 7c{memknY``{m `:{m Y`{mmnemnem`:mT`:\?nn>#nT m{ninpnAnxn`:Jn~n~.F}w}Z}(`|(`Jǻ`|ڋID ۢ I`[_>=0 +'[  ld|F\~o)ƍ"߈@~]`~? ^[&~~~_^[\>@!.^(+ŏ ~ ~.6e>eJ`']],[+`>Nsx[z]^Ih(+>J& +ǜ[''``?N],[0[h[J'&'. +:[''PV`~&.&aH&Ia[`>IW"""%b[d`%sld`:%d`d(+>=0'b?J& + d`~ca[`>I"!% ][[[!%0) ][>=0GM'd?J& + `~ƙe֙[[>Nf][[h[[OAa[[o[[>I(>, J l>JXp_ q m?I% ][[[>Ng[[''J=ׁ  ][[[!QnF [ ][[[{>=[''2*!Q8!E= ԀGF ][[[H!mJbi!QI% ][>Nh],[1[=ҁ  ]["6n="6 ][[ + JKR_ Jv} Ԁ ~>OQY`[>Ii"!%vm# `:!%# `>=0'i?J [''N.^# ~țٜ֜`K[\>I"!%#`:!%#`>=0-3'i?=o[''2.^###~zŜ`J~Μܝ5(ޝ5s[`J"%$o``'g'.^+%$o`^~ j[`>I-"!%:1$`:!%QH$`>=0bh'i?J`'g'$.^~fk3ky3z[\>I"!%%v`:!%%v`>=0'i?=['g'l.^&%v~NmN`'`>J`'g'4,.^7D% ~.A.`:>K>JϜ`:'9'.^[l[>J A!~줺P7[],[+[>I"!%&`:!%2+&`>=0CI'n?I!&(+=&0[&׀[?Nǣ[̜[''N.^&I`'g'o'm>=0+1C.^N&UU&`:^&2d`[?Jsz [''p'm.^&@F "#$($R$%X%&D&(/ '~q`.~))__;_<[\? N&V()~$r§$``'>J.['$'s't'u'v'w'x'x׼  (+~ ],[y[+[J .[''pY.^jw)f#)W(++0[)W[],[()9)/~HHzf`[`]_*'0~7={{f`[]/_E~\? &1[F~&&#2?s]_\? T&5],[1\[5[`^*mg*[q<*H~_[\? &+)3~H|ȫH`[>I"%䀪+i`"+i`+i`^.(A>=0'-+i`7.(A?4~MM}^c`[>Ip"%zt,`",`,`^.(AW>=0,`.(A?5~~` y`(`[>I "*$,ր71,փw9,>=0IZ`,֓j,?I}",〇,,w,>=0,〬,ւ,?6~`_>Iy"%}-`-`(-`>=.|&-``3?J&-_7~` K[\>Im"%wq.`.`(.`>=.|&.``3?=Ā..A~ܮ>(>`>N(,V[.[''hA.^I`'g'/f/f/f>J`'t'/f?=0('C~CL(RW(`\>=j'(w08~ K_\>=.P'1[0M!9~ + ]_\>N#`#&`'g'KG0\0t0[y0`=.P'&0],[!:~` _\>=.}184=.P'1[181E!;~!#+0`_>==.|I13JU&|\.P'1q[r1!_<~7_>I.(A(=0ĔW?J&.P'!_=~qq`y`\>=5*2126.(A=C.P'1X[Y2d`2yf2!>~v{ `y` ]_`\>=ɼ53/3<.(AN(`3=A.P'#\T4(+1f[1k[l4],[!+I+,-.y/>/0/0y1122}345"I~`L~ [N~[\?L5 5~#`&-- +>`~[[''~[[''~Dc]`D` ~[`J ` 'g$ '''''''''P6W6^6e6l6s6z666~Ըܺ[[>I""""7-(+% 7-`:%7-`%&$7-`1@7->JJQ7-I]%ca7-`>Jv7-`I%7-`>J7-`^I%ހ7-`>J 7-`>J ļ7-4Ӻ[`IJڼN8_~6 6 [[>N[!['$'s''x'x¼ ؼ8=[''88J&-8 ~HH[`>I""""ɀ95(+%ր95`:%值95`%95` 95>J95I(,`'3'I95>NWZ`\`'3's95J{U&9`I"%95`I!ݚ95`I>J 95`IL>J-4 +@95 +~KR]^[`Jdd q:  ~zz[`>I`'g'_:>J.:?I`'g'K3:>J=LH[T:?J^n&v: ~ؿ@@[[Ia[[`>N@ @K[@[''@(;@1;I@7@A@;;(+>=@P;@`@X;@a;=@i[''@;@;@;?J@@; ~D"D$DNDDDNg``DG__JDMDM<~EFGFGF$``>NF/F3`FOF5FP=IFVF^FZ=(+>=Fm=Fs`'$'s''u''w''xGR==GtGZGu=Gz=?JGG=(l)*05g56k7 89::;<<= O:a) QƄƅmc˅ma[[>I"!%䀄>p][[[!%>p][>=0 'd?JLSSd>pSpp eO [[>Nf][[h[[OAa[[‡[[>I⁅??5l>J??5m?I!%'%?5][[[>N=Jg[L['m'J=xg?y?5][[[~?nF[?5][[[{>=['m'̈́??炆??5][[[?mJ?I %&$?5][>N?Mh],[1O[=jY?k?5][p@n=@?5][[?J?5J?>T ..[J['m'JU11fjIсCi(+>J眣[''`C\?I`'g'K4Ci>NJX`Z`'3'hnCiG~C>J[''`C\>N[[''zCiJ!['':C\BD1U>Ndi[k[''zzCiN[[''{CiJÜ[''C\D{D>N[[''z%CiN=B[D[''{SCiNkp[r[''|CiJ[''C\D턌EE/>N[[''zCiN$[&[''{5CiNMR[T[''|cCiN{[[''CiJ[''C\EEEɆE?N],[5],[1[+5[ςFSCi<FSN[[''C\C\'FC=x['9'FJ[''`2F>P>R>A0AeAB BpBC>F [&"_ wTZ``}LJ\? y·݈ ϡ+䈟 ``>I"GуvGуw +^>=0"$\'XG?Jip`'t'Gz6Hu7+Ru`[JXX`['u'{+ʼn`J˜`'g'GHYHH~``Z[`[k(?h9f[`[(?h7f[`9&¼[+`@ü[2+`ȌȔϔ7`\>N`IIڀ>=IW?D)>%N8<`C>IڅE=TIha\IڃycJ3k^N`Iڅ=IIڃyJ^N`͂J37Nގ`J7kJ37 = +J$J3gW&J=4J3A:J텸C=RJj`Z[JgWbKW|unJywJ39=KσJ7=JꂏJ37kJ7=J3 +J3 J=J J#K=KJXTJ3h7 =eJ3rkJ텸t=JJh7 WJyJ39=KJ7=JJ37k#J7=1J351J38J=FJKFJNK=uJ~J3h7=J3J텸=JJh7WȄJyJ39ἃ=K!J7=.JC<8J37kKFJ=XJ3\XJ3_J=mJrmJuK=JJ37=KЃJ7kނJ3=JJWJ3=J3 J텸=JV5+&JW-KWF?8JyAJ39X=J.¼[h7 =.¼[ńJ텸Ǽ=.ü[ .ü[h7 WJy.¼[9 =.¼[.¼[!J3=,.ü[0,.ü[3J!KFI(NII`"hd.ü[(tp.¼[(>=.¼[7Z?=.Ǽ[=.Ǽ[=.Ǽ[=.Ǽ[ FKǼ[U\> N`9ɂh.¼[N`RUN/7`?9RUyAR~Nqw`7ah.¼[N`RЅN`ƒRЃyRN֗`愗RWR~W.ü[=.¼[SM N"`*$SMy,.¼[=5.ü[gZOE=S#WGRWQS]^i@}.¼[^}@.ü[^ +ǚɡ, ``>I"ꀘTvTw^>=0 +$J'FT?IWm`\TgcTy(>=.Ǽ[J.¼[ǀTy?N`N`D>=.Ǽ[=U.¼[=)U&)82UBT`vof`UyhUWqT^y^JUm+m`[>=.Ǽ[Nٚ`.¼[씅7y=.Ǽ[N` .¼[-&7yJ7]SF?V}hHWUVd_hrs+`>=.Ǽ[J.¼[(R/T|VAWTWÛɦN``' +[`17AAP\>N]d[f[''I!X*(+>N[[''؀X*I!X^(+>J??=0%' Aѝ֞aڼ[a`(`\>=['7'B;3.+[މSNXށUXfvg+~`>=.ڼ[J.+[˞ݡ̡+硢`[>=.ڼ[7={s.+[7?N`.+[=.+[׀Yk7N +`[).+[y(?eI4!HA8Y7(>=VZC]VZCW(<d?JZCL +L, ``>I"Zv쀡Zw^>=0$@'<Z?NQ[~`IdlhZw7>=|[h|[hWIZw7>=[h[hWIȀZw7>=[h遢[hW???= .+[N*0`4y6[hNIU`&IWk7`[h`Cp)>=.ڼ[\?[hN`.+[I#ZZy(>JQ_X\fbZy?N~`&~\Z`I\y]?WZ\c>J-4]??XY8YZ],`\?  ',`6K``>=C^9U7]X^9W_^F=k^9}7^9W7^97 +J^9^97˃ք<܄``>=_17_1W7_1=*_161_1>9_17 JJ\7d__1W{s7u_17=[r[`J&`:`&`B`˄օ*ۅ*=[r[_[[`J&``&``&##``&''``^_``aK4:```[ _h !_nty|_!_\?aa t A`:J$'.'.!'΃,(Ѓ,s[`>I!%耂bf]`J*?J" .(bf.!('!bf!19rzBr`JEU][.zig.!zOWO s]_]_>J)_&442.W<6cN_&AA?.!WICcN!_؄3y3 s]_]_>J _&.y c肘_&%%#.!y-'c!_݆@h@`]_>J _&$$".h&d_&220.!h4d_Ň`[Jȼr.h.W.!h.!")3= s]_`[>NNQ`US.y]WeNhk`om.!ywqe!J~reheWeӂheSUfp s]__>N`.yfqN`.!yfq!J&fhfWłfhf_bbIbc1cdfdejfSg8 &(`[[Æˇˡ(ч7`+`J#퀆g(+ } g`'/O/(J#$T'7.z'>.'wD.'M.́]k!(m!ns[`>I{!%j]`J*?J""".z(jŇz.(؀jŗ.{(jŇ{.9(jŘ9Ɓ&.z7`J:J\W.zzjf.zzt.{ăz.9Ńz΁#Ɖ# s]_]_>N_i_.zlzN `h`.zW.+& lzW3-lI@GDl1vJl`>NZ]__i_c.nhlN~`h`.W.lWlIlvm>Jڼ_l1l&l`yl1_&myl_??J+ρdi3s3s]``>J""".zvnzWnʀnz׃v.zW..vnWnn؃v&".W(.Ё s]_]_>NƊ{`μi`.zW.oAzWoAN 9`i`#.W*.<82oAWD>oANV[z_]h_f.zrloAzN_h_.oAJ_ppM&ρo\yp_&ނoypM_с05FV]``>Je"""ql.zv|tpz.zW.^pzWp.vӀp.W.^pWpҁhmz]``>J"""r%^.zr%v.zW.怍r%!^.r%!v .W .ǁ)U1U]_J48_F.zQ.ȁYfo]_Jrv_&.zW._.Ɂ]_Jʼ_&.zW._&.W._ʁPP]_J!%_3.z&BB>.WI._i.iQitiijjNjkkmo#prrsDst#tՁ``]_ׁ z_؁ _ف _ځ, _ށ6<EKz_V_]_f_\?׀uZ؁ue&#upupWhup`_&#ۃu{⃒u{Whu{`_ <܁ܔ`[=]_r]_]_>Nz_ h_&$vs+)vN5;_&5K=i_CAvsHFvyMv_NY]__h_ecvs!jhv!Nt{_&t}i_vs!v!yw!_J_vw!vхwVvJw߁8>``]_]_၅Xz_⁅X_䁅X[_偅X[_ڙښꚝz___ _\?xmxx#0*x7v_GxPx_#vox}v_xx_ ڼ灅`[=]_r]_]_>NϜz_ּh_܀yVၜydN_&i_yVydyy_N_h_yV! yd!N*1_&*A3i_97yV!><yd!yCz_JLW_kyqzvy}z9遅_J.[쁅   _\>IҀ{={߼v_{?=.[{ꁅ))_J"".[큅4=CF _\>IT_X{=d{mv_}{?=.[{y-zz{Y{{ ^V[`9_Ql`[(iW +@`U`[(Uk@aX`[(9B.?b`[(+eG?c`[(&{?d:`[(-DT! @e`[(;f?f`[(;f?h(+``,=_,r__JԜ_''}B}Qiq (+"q``0$,=_@4,r__JJJ_''l}o}jɄ5(+5,=`,r``[J`['' 0~13~BkօI +(+I,`, ``J  `'' =~@~lł܃ ܡ(ܡ+߃, ``[J`[''"m 7x7(7+:xJ<, ``[JVV`[''pn{(+, ``[J`[''oփ$(+$,``[J`[''"Bp'>u>(>+BuRD,``[JXX`[''sqx(+,``[J`[''rt(+,``[J`[''bs8OO(O+RbT,``[Jhh`[''t_(+,``[J`[''"v35[P``SK__>@keenJs&sz{Wh_GfHW]adgehtw| } }~ ~~Zz:Z'"#D߈@'(`\? '][``4 ( ``4>J.|4A`4`J Y(' %h%%`']lwww`S'Ï`S%JkwH'x `\?  +'ŚԠ3!``\?  'KV___`: +'Û` '"""`4 'P^g(`gas[`' !1(1-M`]`4Ty"' "``\? '͡ء`'NYfff`'Ĩɨ`'˩ԩݩ`'ox`'-555`' + + +],`$7Z'ĵHR#``#\? '` ],[ ][`[+`$'AAAAAA``$ 'EEEEEE`EK``$!'H1H1HPH9HPHE`[?{$'HHN|$``,\? &'IIIII``''KKKKK`('LLLLL[*'NcNqNz(NsNzNts[`` -'OO%V%``$3\? /'RSSSS`1'V]VlVVqVVw ],[V ][`[+`$4'WLW[Z&```<\? 6'WWWMWW`7'XY Y,Y,Y,][``:'Z^ZlZu(ZnZuZos[`8'ZZZ'ZZ],`=]0='[1[@_(``K\?  +?'[[[[[`@'[[[[[`A'\X\a\k\k\k`B'\\\\\`4C']q]]]]`4D']]]]]`E'^O^j^u^u^u],`LF'^^^^^`G'^^___],`$I'_____]`4Jw9j +L'`6`EaC)``R\? N'`````],`O'``````P'a2a;aAaAaA`FuS'aalC*``_\? U'bbbbb`V'cVc_clclcl`W'ee"e/e/e/],`wX'gSghgu gugu],`SY'hhhhh`Z'jkjzjjj`S\'k:k?k\kJk\kVs`S`]'ll!lAl/lAl;s`S`/b-i`'ll}+``S`o\?  b'mEmUm_m_m_``c'mmm mm],``d'nnnnn`e'nInRnXnXnX`f'p&pIpUpUpU][``g'rFrdrsrsrs][``h'ssttt][``i'ttttt``k'zz{Oz{Oz +`{ ],[{? ][`[+`$l'|||(|||s[`m'}}}}}}s``` <k +Bo H p'~#~2,```v\? r'~~~!~~`Ss'&~&&],`t'P`$Qw'DS-`S~\? _y'.`Sz'|`|'(s[`;'!/``S\? '0`p'CR$1``\? '!`S'0;A6AA`:'~],`'`'`'09D0DD`'+4C1CC`'w-`'"`'#`'DMZ&ZZ`' +`'/`'BKb.bb`'3`' 2 `' "("s[`Et4cN} +C't2``\? '`S'`'ajqqq`' `'(s[`3b'FU3``\? '`S'CLV$VV`'`'Ybq#qq`'A`$.['=LY`\? '`'v~:`'4`v'"(u5`' `:'W 6`:'% 7`'6<sCsI`:T6`:f7`\? <'–8 '9`': <[' :['K ;['s &['=C”N”\<[+j:[+x;[+Š&[+\? C󁆆dž̊<݊` ],``> N [&'')` N4Ad[CNXSIfwju(+>=0$'=)'>'?6' ?N +@` 6(YN(6A],[8.[=EOXZ`a_crsrW>=}&69` :Nt],`B˚PuI!(Y(>=0&,$ '=B)'BZN(Y'C'D'E'F6' ?JmtQu􁆂*G( *`J +-Cu9C(JuR``$J``kx(```>I"!%`(-[>=0$'H?NI`S'I/!%63d``>=0MS$c'H?J&&d``Z``ͅw͡(؅w` ],`+`S>I!(+>=%,>D?JZap?9I}fP2 hjìJ" K6ā؂ L`\? Ɓ9AN|NN`ȁͅ׆S}`(`+`Ɂl}`(`+`ʁIZmlr}`(`+`%ˁ1n 1}`)(`+`7́o}`(`+`.́EPp\b}`y(`+`I΁1q 1}`)(`+`@ρr}`(`+`YЁ_ittz}`(`+`Rс$Vv1V7}`N(`+`}ҁШܩx}`(`+``Ӂy}`(`+`iԁKYzhn}`(`+`rՁR{-R3}`J(`+`ց϶ط}`(`+`X}:y6u2q.فJEEEE,E<G/G3GJG:GJG?``HHHHHH`HK`\JFJJJbJRJbJW``KKLKLK`KK`\MMMMMM`M`Mн`OOOOOO`OK`O`Oν\QMQQQQZQQ_`Qs`Q`S)S.SpS7SpS<`SLK`S[`Sk\UU UAUUAU`U,`U<`VWWAWWAW `WK`W,`W<\XXXXXX`X`X`ZZZZZZ`ZK`Z`Zܽ\ \y\}\\\\`\`\` +^o^t^^|^^`^K`^`^\ `1`5`l`>`l`C``W``g` bbbXbbXb$`b4K`bC`bS\ cccccc`c`c`[g{ggggg`gK`[g`g\ii!iYi+iYi0`iD`iT`[jjjjjj`jK`[j`j\F>?KLXlll{qTl{(`],``qU`l{[1[(``=5[фم ],``=5[ppqspqsq`q}`q1(`+`>Jq@qNqGlqYqhXrsyVs(`],``ytU`s[1[ ! (``=5[:!ƈ؈ ],``=5[;"w~wx wx w`w}`w(`+`>JwwwSwx,$y9yLy^WyMy^yX s],`],``q%{{W{(`],``'U`){[1[+,+Ȇ(``%=5[+,XX' ],``%=5[,-ii`}`(`+`%>J.<5mO^<|M.-<X<(`],``0U`2<[1[4549AhJhO(``.=5[5v~ ],``.=5[6%1`D}`[(`+`.>Jjxqzo R7P_ Y_(`],``9U`;_[1[=>='' (``7=5[>5=P[ ],``7=5[?MUdp`}`(`+`7>J n&Zk@GZ(`],``B2U`D[1[FGF(``@=5[G%-n?nJ ],``@=5[H`}`(`+`@>Jq)pI[(`],``KwU`M[1[OPOBJsTsY(``I=5[P ],``I=5[Qaa`}`(`+`I>J,:3'pG4VDxRAP\P(`],``TU`7V088(AF(``R>=0TZ'uW( ],``R>=0'uX#+9E`X}`o(`+`R>J~t2 Ys-](`],``[U`7]CKK(UZ(``Y>=0hn's^0(ӊ0 ],``Y>=0's_qy`}`(`+`Y>Jۀ+r8Hl´Í`^(`],`[`b}U`d[1[fgfʁ(```=5[gNN" ],`[``=5[hgg` }`"(`+``>J1?8ĺxMǂ\ KĒi_(`],`[`kU`7m[1[opoy(``i=5[pƒփ ],`[`i=5[q&6B`U}`l(`+`i>J{JyWgś"Ƭr"`ѡ(`],``t U`7v[1[xyx (W5W:(``r=5[>yem ],``r=5[8zMUgs`}`(`+`r>J֠z|W s],`],`)iǮ8}}Fa(`],``0U`7[1[[cns(``}=5[V ],``}=5[PƇƗƣ`ƶ}`(`+`}>JɫvɸW s],`],`>Ƀ R,;ϔb;(`],`@`~U`7;[1[&& (``=5[n4<Rc ],`@`=5[aW s],`@],`@hh` +}`!(`+`>J0>7͠{Nڂ]\˥/IXYcX(`d` e`7@-f`7Mg`7mh`7؍i`7Pحj`7k`7l`7  m`7`-n`7Mo`7mp`70ٍq`7p٭r`7s`7t` u`7D,v`7Lw`7lx`7ڌy`7Tڬz`7{`7|`7$ }`7d,~`7L`7l`74ی`7t۬`7`7`7 `7H+`7K`7k`7܋`7Xܫ`7`7`7( `7h+`7K`7k`78݋`7xÁݫ`7ā`7Ł`7 Ɓ +`7Lǁ*`7ȁJ`7Ɂj`7ʁފ`7\ˁު`7́`7́`7,΁ +`7lρ*`7ЁJ`7сj`7<ҁߊ`7|Ӂߪ`7ԁ`7Ձ`ց `7Aׁ)`7؁I`7فi`7ځ`7Qہ`7܁`7݁`7!ށ `7a߁)`7I`7၇i`71⁇`7qぇ`7䁇`7假`7恇`7E灇(`7聇H`7遇h`7ꁇ`7U끇`7쁇`7큇`7%`7e(`7H`7h`75`7u`7`7`7 `7I'`7G`7g`7`7Y`7`7`7)`7i'`7G`7g`79`7y`7`7`7 `7M&`7F`7 f`7 +`7] `7 `7 `7-`7m&`7F`7f`7=`7}`7`7``7B%`7E`7e`7`7R`7`7`7"`7b%`7 E`7!e`72"`7r#`7$`7%`7&`7F'$`7(D`7)d`7*`7V+`7,`7-`7&.`7f/$`70D`71d`762`7v3`74`75`7 +6`7J7#`78C`79c`7: `7Z; +`7< `7= `7*> `7j?#`7@C`7Ac`7:B`7zC`7D`7E`7F`7NG"`7HB`7Ib`7J`7^K`7L`7M`7.N`7nO"`7PB`7Qb `7>R!`7~S"`7T#`7U$`V%`7CW!&`7XA'`7Ya(`7Z)`7S[*`7\+`7],`7#^-`7c_!.`7`A/`7aa0`73b1`7sc2`7d3`7e4`7f5`7Gg 6`7h@7`7i`8`7j9`7Wk:`7l;`7m<`7'n=`7go >`7p@?`7q`@`77rA`7wsB`7tC`7uD`7 vE`7KwF`7x?G`7y_H`7zI`7[{J`7|K`7}L`7+~M`7kN`7?O`7_P`7;Q`7{R`7S`7T`7U`7OV`7>W`7^X`7~Y`7_Z`7[`7\`7/]`7o^`7>_`7^``7?~a`7b`7c`7X[1[#ˍ`[!`["`[`[`=5[rK)K1`[`=5[sX`n`=5[t``=5[nAA`@`=5[uWs``5HKWIK`lґyҀґҋs``ҵhs``  s``>F_N_Ys``ӉӑӱӠӱӫs``s``&.Q@QKs``nvԌ{ԌԆs``ԭԵԽs``CM\R\Z`[`աիհ\ծհ` +; ; `0``Ydeee`[փ֎֏!֏֏`[ָֹ֭"ֹֹ`[`[טנר>רר`(9 /940``""s`0``nx}`[`!`[`8BQGQO"`[``[`s``^h| k|vs````=GW UW`}1rL3mJM|=y+e#'d(`d`e`7@%f`7Eg`7Áeh`7āi`7PŁj`7Ɓk`7ǁl`7 ȁm`7`Ɂ%n`7ʁEo`7ˁep`70́q`7ṕr`7΁s`7ρt`Ёu`7Dс$v`7ҁDw`7Ӂdx`7ԁy`7TՁz`7ց{`7ׁ|`7$؁}`7dف$~`7ځD`7ہd`74܁`7t݁`7ށ`7߁`7`7H၇#`7⁇C`7ぇc`7䁇`7X假`7恇`7灇`7(聇`7h遇#`7ꁇC`7끇c`78쁇`7x큇`7`7`7 `7L"`7B`7b`7`7\`7`7`7,`7l"`7B`7b`7<`7|`7`7`@ `7A@ !`7@ A`7@ a`7@ `7Q@ `7@ `7@ `7!@ +`7a@  +!`7@ + +A`7@  +a`71@  +`7q@  +`7@ +`7@ +`7@ `7E@ `7@ @`7@ ``7@ `7U@ `7@ `7@ `7%@ `7e@ `7@ @`7@ ``75@ `7u@ `7@ `7@ `7 @  `7I@! `7@" ?`7@# _`7@$ `7Y@% `7@& `7@' `7)@( `7i@)`7@*?`7@+_`79@,`7y@-`7@.`7@/`7 @0`7M@1`7@2>`7@3^`7@4~`7]@5`7@6`7@7`7-@8`7m@9`7@:>`7@;^`7=@<~`7}@=`7@>`7@?`@@`7B@A`7@B=`7@C]`7@D}`7R@E`7@F`7@G`7"@H`7b@I`7@J=`7@K]`72@L}`7r@M`7@N`7@O`7@P`7F@Q`7@R<`7@S\`7@T|`7V@U`7@V`7@W`7&@X`7f@Y`7@Z<`7@[\`76@\|`7v@]`7@^`7@_`7 +@``7J@a`7@b;`7@c[`7@d{ `7Z@e +`7@f `7@g `7*@h `7j@i`7@j;`7@k[`7:@l{`7z@m`7@n`7@o`7@p`7N@q`7@r:`7@sZ`7@tz`7^@u`7@v`7@w`7.@x`7n@y`7@z:`7@{Z `7>@|z!`7~@}"`7@~#`7@$`@%`7C@&`7@9'`7@Y(`7@y)`7S@*`7@+`7@,`7#@-`7c@.`7@9/`7@Y0`73@y1`7s@2`7@3`7@4`7@5`7G@6`7@87`7@X8`7@x9`7W@:`7@;`7@<`7'@=`7g@>`7@8?`7@X@`77@xA`7w@B`7@C`7@D`7 @E`7K@F`7@7G`7@WH`7@wI`7[@J`7@K`7@L`7+@M`7k@N`7@7O`7@WP`7;@wQ`7{@R`7@S`7@T`7@U`7O@V`7@6W`7@VX`7@vY`7_@Z`7@[`7@\`7/@]`7o@ ^`7@ 6_`7@ V``7?@ va`7@ b`7@ c`7@[1[@@@@hpw|`!`"```=5[@ÁgĎ`!`"```=5[@ā\"'\2``=5[@Ɓks``@ǁ 1A2A;s``@ȁgxys``@ɁWs``@ʁ y s``@ׁ5=>>>`@؁jrs!ss`@ف"`@ځ`@ہ>`@ˁ!!!/ !%!/!*0``@́!!"!""s`" 0``@́"\"d"p"i"p"n``@΁""""""!``@ρ## #,#%#,#*"``@Ё#v#~####``@܁###)##`@݁$2$;$@*$@$@`@ށ$$$+$$`@߁$$$,$$`@с%@%H%Y-%Q%Y%W``@ҁ%%%.%%%!``@Ӂ&&&/&&&"``@ԁ&i&q&0&z&&``@Ձ'E'O'1'U''`2`'u3``6Y =n?D  F   + +> +@(,(;.e(;(`@ぇ(;[1[@@@@@偈`[!`[`@=5[@恈ɏѐ`[`@=5[@灈>%>`@=5[@聈KS>ju``@=5[@ꁇ)M)`)rW)a)r)ls`@`@@끇)))W))`@@쁇)))y)))s`@`@@큇**!*3h*"*3*-s`@`@@*Q*d*v*e*v*ps`@`@@**+*++`[`@@+I+S+X\+V+X`@@+++ +++ `@+`@`@@,, , , , `[@,+,6,7!,7,7`[@,,,>,,`@-- -/-%-/--`[`@@-{-----!`[`@@------s`@`@@.<.F.Z .I.Z.Ts`@`@@.....`@ Z   ( k    [   Z-m@#)f``@o ^`Ayy`\?@ yA|΁`J.^@|AtSt}`(`+`J-1AIQK.^@S]Ml[Ayl}`(`+`JAP.^@lAm(.}`E(`+`%JW[AW.^@m7EADŽKnӄK}`(`+`7JA^'!.^@n4CAPZoek}`(`+`.JAe.^@o!/Aopo}`(`+`IJ&*AlKE.^@pXgAt~q}`(`+`@JAs.^@q A r!}`8(`+`YJJNAzoi.^@r|A +#t#}`(`+`RJA.^@t A (4vAG}`^(`+`}JptA.^@vjxA ˇ׈ixi}`(`+``JAD>.^@xR߁aA nz y }`(`+`iJA.^@yTbAz.4}`K(`+`rJ]aA.^@zɁAʊb{يb}`(`+`J A;5.^@{K>ZLAgpz}`(`+`JA4.^@-v`J4A &g``Af ^`A4pp`\?A pA``J.^AA!!` K`\J.DA-A&*`2`7``JFLF.^AUAejrw`K`\J.DA-A + +``ٽ`J.^A7DAmm!`1K`@`P\J__.DA-Arv```J.^AAߍ>>`K``!\J00.DA-A CGOT`h`x`J.^AӁA!  `K``\J.DA-A"yy#`7`G`JV\V.^AfrA#~`K``\J.DA-A$HH```J&,&.^A5oA| A%MRZ_`oK`~`\J.DA-A&```J.^A=J A'"|+|0`@K`O`_\Jnn.DA-A(```[J.^A  A)VV`K`[)`9\JHH.DA-A*[blq```[J.^AفA+͒ғ0ܓ0`K`[`\J"".DA-A/5=k{Pk`JSYS.^A{A0px}`J.^A}A1|`J.^A|A2ғ`JA +.^AA-!D-\>=06@'hpR OX &  !!A!!A5Tij`[k],_],[l```AB\? A8R_A9^ _J&.RA8_A: (>(/>`J282.RA8(YA@CNkPkU`_J_d_.RA8e#_9A;px{`J.^A9{A<}`J.^A9}A=ܕ|`J.^A9|A> R#R`J&*AKE.^A9""##@##$$N$ACm]`]A5```$ADn`AC`AG? R`AIHHal`\?AG|%F H%nAJo]`]A5```%AK—Șp`AJ`ANg R`APpp`\?AN% p&'AQq]`]A5``%`%&aARr`AQ`%AU R`%AWƙƚ  `%\?AU& Ƭ&AXqqs]`]A5``7`7'AYPVDt`AX`7A\ R`7A^B"B.`7\?A\>'q 'A_u]`]A5``.`.'A`rv`A_`.Ac/ R`.Ae88pQp\`.\?Acl(* 8(RAf՜w]`]A5``I`I(Agx`Af`IAjc R`IAlll`I\?Aj( l) Am y]`]A5``@`@)EAnz`Am`@Aq R`@As`@\?Aq) )At99{]`]A5``Y`Y)Au |`At`YAx R`YAzПР + +`Y\?Ax*U Ь*}A{mm}]`]A5``R`R*A|MS:~`A{`RA R`RA88$`R\?A4+ +6A]`]A5``}`}+lA}`A`}A9 R`}ABB~]~j`}\?Az+ B+A]`]A5``r`r,!AŢˣ`A`rA R`rA`r\?A,x ,ACC]`@]A5`@``,A%4`A`A R`A22`\?A.-1 -YA]`[]A5`[````-Aw}x`A``A1 R``A::vUvb``\?Ar- :.Aݦ]`[]A5`[`i`i.LA`A`iAu R`iA~~`i\?A. ~.w`hrhb â1ȖkH wQ".$$%w%&0&j&'#''([())N)***+?+u+,*,,-b-..U.6.ABp; "*AhA^`BuA\A*0B`AA[+A\?  AM]pyK[`B&JAAA0AÍP܍P[`*`B&JA+A5AC1K1 AUe~[`*`B&JAAA11A$[3[J`*b`*`B&JAAA1A22 2AoA o[>I!#A(+J,3A?JELA[AAt{A[J[''A:A(:)[[J443<AO_Ade[jK[`B&Jtt`B&''3w3A A [[[`B&Jל`B&''3ځ3ゑ3A"A-.[3[:[`B&JII`B&''n4Ms4Vz4_AÁ@A@[[[[[`B&Jǜ`B&''4 4ɂ4҃%4ۄ64001h12z233S34)45/ AƁœ ä + Ϣ'`Aȁ `:+AɁ AA`+AʁA AA`+Aˁ 6 Q' d'`+ Á][>K>J*1A[B. AAT[[l[^`>Jr}[6p6yA΁KKK[][>K>JA[.A6A[l[`>J&[3767AρPk Q'ox`+\>I7h(+>=['7'.>=Ҝ['7'.7hA؁?GpAO`A>=0Xb'AЁ "'`\Aсàȡ "'ڡ``\AӁ!1 A ' "'(1`BAԁ6>AENK[`B>N_g[ipB8J.A8AAՁݡA ¡' "'K[`B667<778988919{ Aفѣ| Ҥ + ޢ'`AA܁p A 'K p?7p@[+A߁\dpAu`A>=0~'A၊Kģ[JA.AA: :G:A⁊] ͣ ֣' *' 5 + A'`RA䁊;]l`R Tl`R'A偊j]l`R l`R'wA恊]l`R l`R'SA灊]l`B l`B'A聊H K`:+A遊  R' s'],`:+Aꁊ  ' ա'`+A쁊~K`:`:+`+`B9>Nߦ\][[[2[[I!==`YI"! =I('B!"=I('B>=0:DR=I?J.A=@=IAA`:!`:`B>I-"!61=('B!LG=('B>=0dn|=?JX_.Al=w=AA],`:`:`B>I"!ց>('B!쁫>('B>=0>?N2?],[ApIa>Jry.A?>AAvv`O`:`B>I"!?('B! ?('B>=0$.<??JMT.Aa?~m?AA򁊭{A |' "'[[`BAHpAH`A>=0#'A w "'\A󁊴 ,A>FK`:Q\][[[+`B9>Ia!me@(+>N[pH@J.A@A2A?J.A@AA􁊵JtA ' "'^t_K[e\[`B9AxA y' "'K[`B9Aɵε "'ߵK`:\A3EjMj]y`RJP[PA.lAĶ]y`RJA.lA!3Xb;X]y`RJ>I>A.lAϷ]y`BJA.l< = =>?^@@d@@AAB*BcBBC.CrBC 6 ?a' q' + '`B;KU`>J[b`'g$'''BK`:`+'a`B\+]a`R\+]`A>I|!D(+(D(+>Jæ`A'?K>NC [IR!^VD(+>=qE5{.ADDB +>=E5.ADB +I!₽D(+>= E5D?I4!B8D(+>=g]UE5nD?JA`A&E5`B[l[`>J٦`AF?FHBA $A ,K`:8a`Rl\+]`B>K>Nck `B}m.A}FB I!F(+>=F˭BF?N]`B`B=@)@@FˣnB4@0@0@_@1l`R`>=@H@>G0t.=@x@p@hFbB@@G0jJ@@@G0u@[@l[@`>J@@`B@H@HBAAB@AB@`>JA"ABA䜣`'g'..B B}BBpABB`B>=0BB'BBBBQ "'BBB`B``B BC(CKA B' "'C7CKC?K`:`B}B +CPCCA CQ' Cc' Cy' C' "'CCCK`:C`+`B}DDgFwHGHHIHIJ8BFGS Fޤ + F'`BPM Pp?`+BPd `+BPzK`:+BP `B9+BP `+ BG!G-GG2GG4[+]`>K>NGYGa `BGc.AGjK@BJGGA`GK]G[Gl[G`>JGGЦ`GKGKBGHHHHH[][>K>NH H( `BH*.VAH/L"BJH<HCA[HTL:Hd[Hkl[Hn`>JHH[HLHLBHHIunHIuH[][>K>NHH `BH.mAHLBJHIA[IMI'[I.l[I1`>JIEIP[I]MdI`MoBJJLJ)LJ2[+J@`B&+JN`:+J^`+]y`A>NJvJ[+IJ!JJM(+>IJ!JJM(+>=0JJ'?=KNK!M>=K9NKHMNK] [IKjKxKnM(+B>=KNK.AKN'B>=LNL .ALNL&MBJL<LOBX`A&LgLgN`BLpMBMM!OM.OM7[+ME`B&+MS`:+Mc`+]y`A>NM{M[+IM!MMO(+>IM!MMO(+>=0MM'?=NOրN&O>=N>OցNMONNb [INoN}NsO(+B>=NPeN.ANO'B >=O +PeO.AO#OւO1OB JOGOZBX`A&OrOrPe`BO{OB%OOPpAOP`B>=0OO'BPPPA P' "'PPP``BBPQeQ|VA P' Q' Q'Q2p? "'QiQ|Qq``BB!QQQ "'QQQ`Q`+`BB"QQQ "'QQQ`Q`+`BBQR}RmA Q'n R' R'R0p? R\' "'RRR``BBRRS1A R' R' Rˡ' R' "'SS1S`S`:+`BB S6SSA S7' SR' Sh' S~' "'SSS`S`:+`BKKLMObQ QlQRHRRST!T B&TTZ" T + T'`B(X Wp?`+B)X( `+B*Xo X7p?`+B+X `+ +B-TUUYU UYUK[`B&JU&U?AUSUB.U^UfU UyUU[U`*`B&JUUAUVUV)B/UUVs.VVsV[V`*`B&JV4VMAVgVVnVB0VxVWNVWNV[V[V`*V`*`B&JVW AW+WW2W W9WWDW&B2WWWpAWW`B&>=0WW'B4XXY X' "'XYX`X`X`+X`+`B&B5Y YY+ "'YY+Y ``B6Y0YXY Y1' "'YcYYk`Yx`+`B&B7YYY Y' "'YYYK``B&B8YYZ  Y̡'. "'YZ Z`Z`+`B&UUVeVWtWXGXXYQY +B9Z[)v  Z + [ +'`B;h `+B<hq  h"' hC'],`:+B=h hp?`+B>hK`:+B?h `B+BA[M[T\t[W\t[XK[[`[+][>K>N[| [I[![[Z(+>=[[[.A[Z[ZBJ>=[[[.A[ZBJJ[\A[&\\[`B\&[\-l[\0`>J\D\O[\\[Ã\_[BB\y\] \]][>K>J\\A[\.ABM\[\l[\`>J\\[\\i\\tBC]]]]#]]$[][>K>J]G]NA[]_. A]g\BR][]l[]`>J]][]]#]].BD]]^]^][+]`>K>N^ ^ `B^.A^]BNJ^1^8A`^I]^Y[^`l[^c`>J^w^`^^^^ BE^^_^_^K[^[+][>K>N^ [I^!^^^{(+>=_^_.A_^p_^{BU>=_8^_B.A_G^pBUJ_]_dA[&_u_u^`B_[_l[_`>J__[__H__SBF__`_`_[][>K>N`` `B`.VA`_BSJ` `'A[`8_`H[`Ol[`R`>J`f`q[`~```)BGccfLcfLd[+d`B&+d`:+d-`+]y`A>NdEdR[+Id^!dfdb`(+>Idw!dd{`(+>=0dd'?=d`Ҁd`>=e`ҁe`Nev [Ieee`(+B>=eaae.Ae`BT>=eaae.Ae`҂e`BTJffBX`A&f3f3aa`Bf<`BHfQfWgufbgufjK`:fp[f`+f`+`B>Nff\][[[2f[[If!ffb](+>=f؄fb'fb]n?If!gfbm(+>=ggb'g/bmn?JgFgM.AgZbCg`bQgibBOBagggpAgg`B9>=0gg'BJhiIjA h' i'i$AiMjiVK[if[+`B>Iir!izivd (+>Nii[ipBidNii[ipBjd Jjj.Aj!dCj*dhBK?Nj@jH[jJpBjtdJjj.AjdBLBKjkkA j' j' jǡ'jA "'kkk K[k[`BBLkkkA k ' k1' kG'k]A "'kkkK[`BBMkkkA k' "'kk`BBNkkkA kˡ' "'kkk``BBOll mAlmlK`:l*`l8\][[[+`B>IlH!lTlLf(+>Nlils[lupHlfJll.Alf݁lflg6BP?Jll.Alf݁lfBQBPm m+mXA m ' "'m9mXm:K[m@[mI\[`BBQm\m{mA m]' "'mmmK[m[`BBRmmm A m' "'mmm``BBYmmn "'mnmK`:\BSnnynVA n ' n' n0'nFp? "'n}nn``BBZnnn "'nnn`n`+`BB[nnn "'nnn`n`+`BB\oo o$n "'oo$o``BB]o)o/oH "'o4oHo<K`:`BBToMooA oN' of' o|' o' "'ooo`o`:+`BB^oop% "'op%p`p`:+`BBUp*p|qA p+' pA'pWApqpK[p[+`B>Ip!ppl@(+>Npp[ppBpl5Nqq[qpBq:l@JqFqM.AqTlvq]lBV?Nqsq{[q}pBql5Jqq. AqlBWBVqr5rNA qӡ' q' q'rA "'r;rNr<K[rC[`BBWrRrr A rS' rd' rz'rA "'rrrK[`BBXss v  +AsIv `A`AsY `Bsg`]y_>Nt#t.]_t4 +_i)=tttnvbBttn=ttπtnvnB4ttutl`R`>NttF_&t&uttnvB[_Iuu#uoA(+>=uAu6nw>=uluanupoAIu"uun()uun>=uDŽuoAA?JuuunZ\\]c^F_`^bccceeffSfgh(hhi+ijj_jjkkm4mn9p4Bbvww  v' `Bdw `+Bew `:+Bfw K`+BiwbwjwpAwww`Bb>=0ww'q)quBjxx{v  xϢ'`BmyDyLypAyVy`Bj>=0y_yi'Bnyyyyyy^`BuA\`Bj>JyyBqyr&BqyzzKAz zKz +[`BjJzz`Bj' 'zBrBszPzUzz\zzf`Azv`Bz~\][[[\>Nzz[zpHzs=z.Azrzszs,BrJzBrz{{MA z' "'{ {M{*`A{:`B{>\[\Bt{R{W{t "'{`{t{j`A\qqrhrsst=Bu|Q|u} |R'`Bw}: `A+Bx}T `+By}r `B+B|||}&pA|}&`Bu>=0|}'tuB}~Z~ ~[ + ~g'`BBC]l`R ^l`R'B]l`B l`B'B~IpAI`B}>=0$'B0BkLk]y`RJO\OB.lB]y`BJB.luvvivB  + ' `RB]l`R l`R'SB!]l`R l`R'<B2 S`N+BI "`:+B #A ' '[+B 6 '`+B! `B+BowpA`B>=0'BXdk[JnnA.#ABBk}b]y`RJB.lBn]y`RJB.lx xWxxyNB'm$ + '%`RBU]l`R nl`R'B&]l`R l`R'tB]l`R l`R'SB `A+B, S`N+BC `:+B  M' n'],`:+B2'<]`A>NFP]`AV`A=w.Bg[4p`R`>=zt.B=.bBg[4l`R`>=zj{=.Bg[4##$l`R`>Ic!rhz˦>=zj|?JˀzuB_pA'_`B>=00:'B "'\B "'K`:`B9B7InQn]y`RJT_TB.lB]y`RJB.lB4FkbNk]y`RJQ\QB.lz||} }V}}~QBH{( I + U')`RB *`:+B +`:+B , ' ѡ'`+BM - ' &'`+B c ]'c`B}+B,pA,`B>=0'B19UKUS`:^.][[[+`B>It!x(+>N/[pHJB ,?J(BBLBYsA|}[.[`BJ`B'('0Br1A$r%[`BJ44`B'('2m9k pAA3A`:'4Ay5A` AA6A` סAARR7Amn8[[>O}}9a[`ta[`>IpNCJ)?I%҂C],[>E`C],[(YW>I&%%',&C],[-9`J2)??JQ*Iy}'>=0!':?J Ah;A4h5<[[>JX_A=Aa[[>JpM>*ADdDnF?ADF`[D `B]_>NDD]_D_=EbEXEP-nB4EiEiEEjl`R`>NEuE|_&EuEE~-B_=EEHtE=EEE-bBEׁEHjJEEEHu0D5d9:CJaTYpqt^u+vyg~vlKB@NTB gp;A [ qqA<qBbw Cw DEFyGyHI)~@~Q" *%JK|}~[*BSL^`S`S`SMNB\BO^`EPB\B3Q ~^B\BR^`~B\BWS^`NSB\BT^`w4UB\BÁ襮V^],[2B\BāW^`RyB\BŁ@^`NSB\BƁE X^`SPB\Bǁc)Y^`SB\BȁqZ^`S[B\BɁI\^`]B\Bʁ^^`:B\Bˁ{_^`V`B\B́ a^],[`W2WB\B́ yRb^B\B΁ @c^][[[B\Bρ d^`Z$B\BЁ te^`B\Bс + Ef^],[`[gWB\Bҁ +Lh^`[SB\BӁ +NBi^`YB\Bԁ +rj^`:B\BՁ Gk^`^`^2WB\Bց vܮl vĤ +^`T1B\Bׁ z}m ze +^`_ISB\B؁ n^`NB\Bف >o^`aJ1B\Bځ p^`ai +B\Bہ Lq^` +B\B܁ r^],[``fsWB\B݁ ht^`]B\Bށ ݢu^],``{``p2WB\B߁ `߮v^`awB\B x^`NSB\B။ 'y^`zB\B⁋ )<{^``|}B\Bか ~^B\B䁋3 ^B\B偋N^`RB[B恋``R`R^_B[C9V :'`P`\JC `:+C \? RTC `C>=0'8C '`RCepB-e`C>=06@'Cjr00`:.][[[`C>N/[pHJ C˂C4MBVW[].[`CJoo`C''OXCŕʕ "'Օ][\n+Cؗ ٢'`]*Cs{pB`C>=0'Cӗۘ][[[+`C>I!"g(+>N7G[IpHhgJ~C?JCCB#$[`CJ66`C''C1Bɚ`CJ՜`C'' +H1tC }``RC"]l`R l`R'SC%ypB`C >=0'C'DV{b^{]y`RJalaC".lZC(Xw! Y'`b)C* `+C+ !`+C, "`+C/О؟pB`C(>=0'C0$,"9"?][[[+`C(>IU!gY0(+>N|[pH0JC3e?JC4C3&;BDE[`C(J]]`C(''C41B`C(JŜ`C(''=C5 '`R5C7]l`R l`R'C8u]l`R l`R'C9]l`R %l`R'C:]l`R l`R'C;]l`R 'l`R'C<]l`R l`R'C=`C5+C>`+C?`:+C@`+CA`:+CB`+CC`+CD#`+CEB`C{+CFV'`:+CGu`C{+CH`C5+CI`+CJ|`C5+CK`+CL`C{+CM `:+CNC`+CO-`:+CP@`:+CQX`:+CRu`C{+CSR`+CT`:+CU`+CV`+CW`+CX`:+CY`C{+CZ`:+C[*`+C\>`:+C]O`+C^c`:+C_uB`+C``:+Ca`:+Cb`+Cc`+Cd`+Ce`+Cf`+Cg`:+Ch`+Ci&`+Cj7`+CkK`:+ +Cn{pB`C5>=0'Co00`C5>J !CrCr4JBS`C5J__`C5''CsY^ "'iy`C5\Cu]y`RJC7.lCv۪88]y`RJ)C8.lCw=Oe]y`RJnnC9.lCx]y`RJC:.lCyDD]y`RJ5C;.lCzI[v]y`RJC<.lgY%i +C{ '`C}(`+CdpB,d`C{>=05?'Ciq""],`C5+`C{>I!(+>JC?JCC&@BIJ[`C{JZZ`C{''̀<C1B`C{Jɜ`C{''CGB "' G%`;`C5\CLQ "'Td`C5y`C5\C "'``C5C "'`\^k@~CԴ '`b)C `+C2:pBN`C>=0Wa'C][[[+`C>I!Ӏ|(+>N[pH|J/ICS?JoCCB[`CJ؜`C''рC :1BC`CJOO`C'']FCz {'`C`UC5`:+CI`:+C]`:+Cw`:+Cc`:+C`:+C`:+C`:+CF`:+C`:+C `:+C)`:+C=`:+CQ'`:+Ca]`:+Cu-`:+C`:+C))\? C C (opB7o`C>=0@J'Ct|OO`:+`C>Nl`C`C'' +B'=I!'"(+B=20ծ׀9C?JCJCA`:J`:'9'.`;zCA] '`R C]l`R l`R'C]l`R l`R'<C`+C)`C+C.`:+C `:+C`+C@6`+C@\ `D+C"epB-e`C>=06@'C@H]Q]r`C+`D+`C>I!(+>JC?I!(+>J C*?J=NCCarB{|[[`CJ`C''怽ȁCҽ)1B)[`CJ`C''瀾"+CÁ->oBGo`CJMM`C''Cʁľξ`Jќ`'g'Cˁ4JS]`CJ\\B`Cw[''.Ćտ@-@-]`CJB`C@[''.Cā@i@n@} "'@t@}\CŁ@@@< "'@@\CƁ@@@Z "'@@\Cǁ@@@ "'@@\Cȁ@@@A "'@@\Ć@@A@A]y`RJAAAC.lC΁A"A4A[A=A[]y`RJA@ALA@C.lZ+%\;CρB8BaC B9'`CсCK `C+CԁBBC"pBBC"`C>=0BB'CցCVCZCCkC][[[>JCtC{pGC.BCC؁CCCB C' "'CC[oCفDDJ DԢ'`CC܁ErEzEpBEE`C>=0EE'CށEEFEF`JEE`''.C灋FFF^F"F^F'K`\>=F4['7'.FTC߁F~FFFF`:JFF`:'9'.C聋FFG FG FK`:\>=Fޜ['7'.GkCG,G7GctG@Gc`JGCGC`''.C運GhGlGtGtGG|K`\>=G['7'.GC။GGH GH `:JGG뜣`:'9'.CꁋHHHXHHXH K`:\>=H-['7'.HNC⁋HxHHHH`JHH`''.C끋HHHHHHK`\>=H̜['7'.HfCかII$IHI)IH`:JI,I,`:'9'.C쁋IMIQIIUII]K`:\>=Ij['7'.IC䁋IIIII`JII͜`''.C큋IIJLJJLJ K`\>=J['7'.JBC偋JlJtJJJ`JJJ`'' .CJJJJJJK`\>=JƜ['7' +.JaJAE<@7CKLM  KӢ' `CL `+CL `:+CM t`+CM) `:+CM> `+CMX `:+CMk `+CM `+CLoLwLpBLL`C>=0LL'CNoNQ|  Np' `RCQS `:+CQo `+DNNO8pBOO8`C>=0O O'DO=OEPUOSPUO[`:Of.][[[+`C>IO|!OO(+>NOO/[OpHOJOPDP +P??JP,PBDPLDPYPoPBPxPPy[P.[`CJPP`C' 'PӁPDPPQA1BPQAP[`CJQQ`C' 'Q<L~DRWRU RX'`RD +U `+D U `+DRRS8pBSS8`D>=0S S'DS=SETmS[TmSc`:Sn.][[[+`D>IS!SS(+>NSS/[SpHSJSTDTpT ?JT<TZDTdpDTqTUBTUT[T.[`DJTT`D''UPU[DU"U@U1BUIUUJ[`DJUYUY`D''UG"DVVW V'`DW `+DW3W;WpBWNW`D>=0WWWa'_DX}XY X~'`iDYY%YzpBYBYz`D>=0YKYU'DYYY "'YYYK`:Y`\5D Z\l Z[ [[6 [@[b' [m[ [[ [¤ + [΢'`RD"]]l`R ]l`R'D#_]l`R _l`R'D$`E]l`R `dl`R' D%a]l`R al`R'SD&b!]l`R bl`R'"D'd#]l`R dl`R'$D(eJ%]l`_ efl`_'D)f&]l`R fl`R''D*g~(`D+g)`D,g*`D-g+`7D.h,`D/h'-`D0hE `+ D3\x\\pB\\`D >=0\\'D5g"g2ghg<gh`Jg?g?`'g'.D?hPhUhc "'hZhc\D@hhhmh/ "'hvh\DAhhh "'hh\D6hhi0hi]y`RJhi hD".lD7ieiwi1ii]y`RJiiiD#.lD8ijj32jj3]y`RJjj$jD$.lD9j{jjbjj]y`RJjjjD%.lD:jkk:3kk:]y`RJkk+kD&.lD;kkk4kk]y`RJkkkD'.lD<l l'lR5l2lR]y`_Jl5lCl5D(.lD=lll6ll]y`RJlllD).l\,cB=9 DBmmq7 m'7`RDDqH `:+DEqa `:+DFqv `+DGq `:+DJnQnYnpBnun`DB>=0n~n'DKnnonon`:n.][[[+`DB>In!oo(+>No$o4/[o6pHoUJokoDNoxo?JooDOoxDNoppBppp[p$.[`DBJp6p6`DB'7'8pXpcDOppq61Bpq6p[`DBJpp䜣`DB'7'9q1O*DPsqsw|: sr';`C`UDRu<`:+DSu=`:+DTu`:+DUv`:+DVv(`:+DWv7>`:+DXvHc`:+DYv`:+DZv`:+D[vF`:+D\v`:+D]v `:+D^v`:+D_v`:+D`w'`:+Daw]`:+Dbw'-`:+Dcw9`:+Dkuuuuu\? uC Dfttt`pBt(t``DP>=0t1t;'Dgtetmttxt`DPJt~t~`DP'?'tB'@DiwFwMwzAwUwz`:Jw[w[`:'9'.,xDlxWxyzA xX'B`X~Dvz~z~zzz\? zXDoxxy4pBxy4x`:+`Dl>Ix!xҀx(+B>JxxDsy?Jyy%DtDsy8yLyByUyyV[`DlJy^y^`Dl'A'Cy`Dtyyy1Byy`DlJyy`Dl'A'DDpzzzzzz`:+`DlJzzDozĜ2ŗDDw{{}E {Ƣ'E`DDy| F`+Dz} `+D}|n|v|pB||`Dw>=0||'ƸD~}~#)G }'G`DD H`+D~~pB~`D~>=0~~'WǣD+*I 'I`D J 'K`+DpB`D>=0'ND$L 'M`CD\? C D~pB`D>=0'DCC`DJ圣`D'N'4B'OiD!gP 'P`DD` M`:+DpB`D>=0'D`:'][[[`D>N7>Q[@pH_FJjD7bDNBN[[`DJ䜣`D'P'R=فIʫ$DBhpS C'S`RDl .`:+D'pB'`D>=0'D,4HP`:Z][[[`D>NjqQ[spHJD DZBZ[[`DJ`D'S'TO̗U̢ˀiDKuU L'U`DD V],`D+DApB A`D>=0'DFNfn`:x][[[`D>NQ[pHJDͺDB#$[*[`DJ33`D'U'W\gE͑.ΧDX 'X`D `k+D7?pBU`D>=0^h'NDY 'Y`DlpB4l`D>=0=G'Dqx`Z}`.`:`\][[[+][>I!(+>N[pHJ .[B)YD?J?F.\BOSDDe[B f'Z "'.[[\[][D\B 'Z "'.[[][D v v.`:]`DJ!!B`DY[''.rD{]]],`:JB],`:[''^.ϊKѭ"ҍD_ '_`RD ``+DÁ a`+Dā .`:+DŁ `:+DƁ b`+Dǁ= c`+DȁW d`+DˁQYpBv`D>=0'D́dqv]`J||B`[''e.*D΁f 'f`DDЁ +`k+DӁ+3pBP`D>=0Yc'Dԁ   `k +`k`D>JD +Dׁ$GBPQ [Z +[`DJgg`D'f'gr}ԃDսD؁h ע'h`DDځ1 V],`D+D݁nvpB`D>=0'Dށww`:][[[`D>N Q[pH3֤J>\Df֕lD။{B[[`DJ`D'h'i7BD⁋=DjLT`:][JddB[t[''k.׬ l ׂDかl~ 'l`D偋 m`+D聋T\pBe`D>=0nx'YإD運n 'n`D쁋cpB+c`D>=04>'D큋hp`D>JDD B `DJޜ`D'n'oD/p5Lq[]],`MGJ\\B],`MG[''r.-rBDs 't`CD`:+Dc`:+D\? C D XpB X`D>=0)3'D]ep`DJvv`D'u'B'?ۗDv Ţ'v`RD w`+D x`+E y`+E R`+ECKpB[`D>=0dn'4܀Ez ֢'z`REJ {],`:+E +bjpB`E>=0'E `:.][[[+`E>I +!_(+>N1A/[CpHb_JxEPݜ?JEPEB$%[+.[`EJ==`E'z'|0;E21B2[`EJ뜣`E'z'}-ީEXy~]][`:[JB[''.E][JB[眣[''.'{AߘEi '`RE^fpBy`E>=0'E`:J뜣`:'9'.Eg"g*K`:\>=7['7'.]6EDZ E'`E B`+E `:+E!pB`E>=0'E$#(^ "'-^3`+>y`+Je`:+`EE"ckpopu],[`:+`:+`E>Il"upB(+BR(+B>J&E&1`E?N[E(I!B(+B=E)'B?I!R(+B=%E).'>R?JL&LSE']1h`EE&u|B[[J[''E'1B[[[Jٜ['''2E( 2B2[J##[''JE)6=BEF[K[PK[[>=]['7'2ty~Qj5E* '`RE, `E+E- `+E0IpBI`E*>=0$'E1NV_g`:q.][[[`E*>N/[pH=JE4.YE4{B"{#[).[`E*JAA`E*''gЁmE5 '`E7 `i+E8 `:+E9 K`+E< (pBG`E5>=0PZ'E>33][JB[[''.E?8?I[K[][JkkB[{[''.oEE@ '`EB@ `+EE0pB0`E@>=0 'EGMT_][JeeB[u[''.EHP]`EJB`Eǜ[''.EIAA]`TJ + +B`T$[''.EJFMQ][JWWB[g[''.EK]`:JB`:[''. W l"EL '`C`i2 EN]l`R l`R'EOº]l`R l`R'SEP]l`R l`R'EQ#]l`R Al`R'ER^]l`R vl`R'ESǗ]l`Y Dzl`Y'ET]l`R l`R'EU ]l`R 'l`R'EVL]l`_; hl`_;'EW̍]l`R ̧l`R'EX]l`R l`R'EY5]l`d Pl`d'wEZs]l`R ύl`R'En +\? C E]HPpB]`EL>=0fp'E^϶ϾFF`ELJϜ`EL''/B'sE``yѝрѝ]l`RJуэуEN.lEab]l`RJEO.lEbb{ҡ҃ҡ]l`RJ҆ґ҆EP.lEc22]l`RJ"EQ.lEdtӍӱӔӱ]l`RJӗӡӗER.lEe@ @]l`YJ#0#ES.lEfԅԞԨ]l`RJԫԸԫET.lEg %M.M]l`RJ1=1EU.lEhՓմտ]l`_;JEV.lEi$=eFe]l`RJIUIEW.lEjjփ֫֌֫]l`RJ֏֛֏EX.lEk::]l`dJ*EY.lEl~ח׿נ׿]l`RJףׯףEZ.l.z(})+-/Eo؜ؾW ؝'`REq٥]l`Y l`Y'Er K`:+Eu'qpB9q`Eo>=0BL'EvH HK`:`Eo>J5Ey?aEyLdڴBmڴnK[`EoJ}}`Eo''ȀگEzw "'\E{ "'`\E},U6U]y`YJ9F9Eq.l8.tE~2O$ 3'`E `+E |`+EܫܳpB`E~>=0'FE"X '`CEP`+Ec`+E `T++E`:+E`:+E`:+E`+E`:+EN  + ' ''],`[+E`K`:+Ep`:+E `:+E `g\+EK`:+E `+EF2F\? =C EހވpBޗ`E>=0ޠު'Ell`EJ`E''SB'E "'`E +& "'&`E+0V "'AVIS`:\2mE_=`~ z'`dE;pB;`E>=0 'DE6 '`EpB`E>=0'EFF`:][JB[[''B.;BEKRU]`:][JqqB[恜[''<.E][JB[˜[''.E@ [\][[[+][>I$!0((+>NEO[QpHpJ.BwE?J.BwEE B ѡ'@ "'  [\[][E)AB '@ "'1A2 [][EFMQY`:][JmmB[}[''.M2[E 逢'`RE ],[+E ],[+E `:+EC `:+E apB)a`E>=02<'Efn00`:.][[[`E>N/[pHJ EE4OBXY[_.[`EJqq`E'',7EV[ "'fn][\awEi j'`YE `E+Eā jpB2j`E>=0;E'EƁ "'\jEǁ '`C`lEɁ]l`y l`y'Eʁ]l`y l`y'Eˁ`+É`+E။G3G\? >C Eρ#+rpB:r`E>=0CM'EЁU]mjmp`+{`+`E>Nl`E󜜣`E''B'I!'(+=#!P+'E?I6!A:7(+=LJPU7E?JahPEҁ "'`+`YEӁ  ' W'`:][[[+`>I!(+>N[pH3JFM.B[fE?J.BEEՁ_B ' ' +' "'lm[x[`EցFeB ' ' ' "'SeT[`E؁jo "'u^`EPB\`:`+\Eׁ B ' "' `:[+`:Eف"E "'<E`\E݁]l`yJEɯ.lEށNq]l`yJEʯ.lE߁ ^ ^`EJ`E' +' .' Eځj  k  [)[)[**[)A[)a[*`z?>N\][`:[2`:[''ԁ''''INow`y.' EI p(+>= p.' E?J& p`z?Eہ`:'`+`:J.B +( +:E W]P+fc  +}E⁋ H hk  I'`E偋   pB  `E>=0  'E灋7<i "'HiMe`\``:\ + 9 E聋 '`E끋 PpBP`E>=0!+'E큋UZ "'fn`tn\   `E\k`E\? E`E  E\ '``EE `E+E`tn+E`:+Ev  ' >'`+E `:+E!`:+E"`+E#`:+E$`+E%`:+E0&`:+FC'`:+FT(`+Ff)`+Fy*`+F+`:+F,`+F-`+F6. ̡' '`+FM/`:+F b0`:+GF \dpB~`E>=0'FsxK1K\][[[+\>I!(+>N[pH=.2BFJ?=*.3BFJAFPo2B Q'1 "'~\[\F3B '1 "'\F4 "'\F5 "'\F F6 "'F`&!`-`8`\F KP~7 "'T~V8[+n9`:+\F!$: ';$<[=`+>[+?][[[+`VF>I8"""%U=``VFwnk(+{(+у(+>N@[pF``VFJ29pEW.ABj F?I"""!k(+%``{(+(+>J'.pEW.BBj``kF?I"""%{][[[!ׁk(+% `` - (+>N B [C[ gpH {][[[J  pE .DB ``!k!zF?I!7"""%!Y!<{`!!u!lk(+!!!`(+!ʃ!(+>J!!pE".EB"`"7k"A{`F?I"k"""!""o(+%""{`!"Ӂ"k(+!""`(+>N##,C[#8pH#WJ#v#}pE#.FB#`#k#{`$F?=0$>$H'GF$$$AB $': $'; "'$$$H[[F$%)%NBB $': % +'; "'%;%N%@`%DQ[[F%R%%DB %S': %p'; "'%%%`%Q[%?[[F%& &8EB %ѡ': %'; "'&&8& [&&[&.Q`[F&<&y&FB &=': &Z'; "'&&&[&[&Q`&?[[F"&&' I "'&' &`&`&`'``EF#'''WJ "''+'W'3q`'AK`:`EF$'\'k'L "''''`'`'M`'`'`'N``EF%''(O "''('P['`P+\F&(( (; "'((;(8[+(+9`:+\F'(@(E(yQ "'(M(y(R`(Y!`(``(k`\F((~((R((][[[>J((pG(.SBFF() +)*SB ('R "')!)*[F))/)Y)T )0';)e))jU`)rV`)z`)Q``VF>J))pE).WB)L)[)j)yFF)**:WB )ۡ'T )'; "'*#*:*$U[*(V[*,[*0Q[[F*?*b*wXB *@'Y "'*n*w],`F**|**Z "'**`F+***[ "'***\[*]`*^[+*9`:+`F,**+2_ "'+ +2+ \[+]`+(!`+`F-+7+C+b` "'+N+b+V`:`e F.+g+l.Ca+x.C+H`VF+`+`+b`++c`++d`++e`+\>I+"""++d(+, +,t(+,(,(+,G,;(+>N,\,h@[,jpF,7=,.fB, ,F,UFJ,?I,"""!,,(+!-,(+!- -t(+!-:-3d(+>N-O-[@[-]pF-{7=-.gB- -F-U-d-t--FJ-?=0-. 'GF.H.g.fB .I'a "'.v..wH[.[.[\F../ gB .'a "'./ .H[.[.[.b[.c[.d[.e[\F////7h "'/%/7/-.`:\F0/</A/Xi "'/O/X\F1/]/b/rj "'/i/r\F2/w/|/k "'///l`\F3///m "'//\F4/// "'///`/!`\F5//0n "'/0/`]+\F600 0H "'00H0=`0#r`0*_`01`08l`0?`\F70M0R0no "'0X0n0a`]+\F80s0x0p "'000`0!`0`0`\F9000q "'000`:0`0!`0r`+\F:0018 "'1181 =`1r`1_`1!`1(l`1/`\F;1=1B1`s "'1K1`1P`1W!`\F1{11tB 1|' "'111`1!`1u`1v`1w`1x`\F<1120y "'1202`2 +`2z`2{`2"u`\F=252:2| "'2G22L}`2V~`2``2j`2t`2{!`\F>222 "'22\F?223, "'23,2`2!`2`2`2`2v`3w`3x`\F@31363Q "'3<3Q3A`3H!`\FA3V3[3v "'3a3v3f`3m!`\FB3{33 "'333`3`3`3!`\FC333 "'333`3!`3`3`\FD344s44s4'H`VF`VFJ4;4;`VF''.4i+:FE445>45>4`4(`4r`5=`\>=5.$5: '5++'ف5/+'ق53+'ك57+'EFF556656654`5`5`5=`\>=6.$62 '6!,Q'ف6%,_'6*,n'6/,}'EFG667 67 6`6(`6r`6=`\>=6..$7 '6-'ف6-'ق7-'ك7-.'FFH778 78 74`7`7`7=`\>=7..$8 '7-'ف7-'8-'8-'FFI889)89)8`8&!`8-u`89v`8Iw`8_x`*\>=8 [ '7'.8.b8.q8.8.9 .9.FJ9.9<99R99kq`VT9yK`:`EJ99`E''.9/69/EFK@r@wBx@Bx@6`l@]`@]`+\>I@@@/(+>=@.A/A%A/ÇzA4A+/×ABA9/ÈARAI/ëFM>=An. A/AA/ׇzA˂A/חAA/׈BA/׫BB/ÇzB5B,/×BMBD/ÈBgB^/ëFNFLFGG@ F' "'G G@G6`lG(`G3`\FMK=KYK K>' "'KhKK{6`lK`K`K`K`\FNPPQ Pס' "'Q Q Q%6`lQ7`QJ`Q]`Qt`Q`Q`Q`Q`\FSQRS= QۣQ RR* R5RW' Rd +RS=`JRR`''..FVSBTFU6 SCSe SpS SS' S̤ +TTU6TYK`\>=Tf['7$''..U3.U,3FOU;UW-Y U<U^ UiU UU' UŤ +UW-],`>IVRVV`'g'.>JVV],`''.IVVÜ`'g'.>JVV],`''.?FPW2WY& W3WU W`W WW' W +WY&W],`\>IXRXV`'g'.>=X['7'.X5IXX`'g'.>=X['7'.Y5?FQ[[\[\[`:[`[!`[r`+\>I[![[6(+>=[['7'.\'6T\-6c\06r\36>=\Q['7'.\y6T\6c\6rFT\\\\~\\`[J\(?FX+b(rjhVn_^ !y!"y""#,#r##$E$%%&&&'( (())***++v,',-.8/ /11223{4+5+6*77hGFW]]` ]΢'`[`\=`FhFY^`:+FZ^ (`+F[` `P+F\` `P+F_^v^~^pB^^`FW>=0^^'Fa^^_ "'^__`:\Fb___D "'_&_D_+e`_7`\Fc_I_N_x "'_X_x_]e`_l`:\Fd_}__ "'___e`_`_`:\Fe___ "'___e`_``:Ff` ``( "'``(``\Fg`-`2`M "'`8`M`@`\9$9p9: :`:;;c;Fhaab`Fkbb bPpBbbP`Fh>=0b!b+'FmbUbZbmb_bmbg`\Fnbrbwbb}bb`\Fobbbbb\;=0dd 'Fzddd "'ddd`d],`+\==>/F{eeh e'`F~ff&fgpBf/fg`F{>=0f8fB'Fflfsffxf][Jf~f~B[f[''.Fffffff.`:][JffB[f֜[''.f?;Fffgggg \][[[+][>Ig!g)g!?(+>Ng>gH[gJpHgi?Jgyg.Bg?F?Jgg.BFFgggB g' "'ggg\[][Fghh,B g' "'h#h,][Fh1hFhhPhhX`:]`i(JhfhfB`i(h[''.hA>o>??@G@@AbFiil i'`RFlp `L+FijjOpBjjO`F>=0j j*'FjTj\kljjkljr`:j}.][[[+`F>Ij!jjBS(+>Njj/[jpHjBSJkkFk!BDk'B?JkCkYFkcBDFkpkkBkkk[k.[`FJkk`F''πkC$kC/Fkl lX1BllXl[`FJl%l%`F''ЀlSCABBCoCFmZmvpA m['`RFp Q`+Fp! `:+Fp7 `+FmmnpBmn`F>=0mm'Fnn$o(n.o(n6`:nA.][[[+`F>InW!nin[D(+>Nn~n/[npHnDJnnFnDׂnE#?JooFoDFo,o>oBoGooH[oN.[`FJofof`F''ӀoEoEFooo1Booo[`FJooќ`F''ԀoF0DbDEFFgFqq5r5 q'5`FWFqWq_rqfrqo`:+`F>Jq|q`F''qB#qqF(+B'qF`:Fr=rErpBrNr`F>=0rWra'FGBGFssy  s'`fSFxo `:+Fssv@sv@s`:t`*t$`*tD`h+tW`:+tj`:+`F>Itytt}H@(+>=tH@tB?Nttl`F&tttBB'N`FIttp>=u^ [ '7'܆uHuHuH uH0uH@uHPuH`>=uuHBuHvH vH0vH@v"HPFJv4v;HFvEvMwepBv_wevg`:vr.][[[+`F>Iv!vvI(+>Nvv/[vpHvIJvwFwIтwJ?Jw:wRFw\IFwiwwBwww[w.[`FJww`F''ހwJwJFwx x]1Bxx]x[`FJx&x&`F''߀xXK*FxxxyB xy' "'xyx`:x`x`x`hx`:\GIJJKaKFyz9| yz' z'`CF|1`:+F{{|{|\? {C FzzzpBzz`F>=0zz'Fzz{*{{*`FJ{ &{ {{ B'N,`FF|J|Z||d|`J|g|oR'F||| |' |' "'||],`[LLMPMMF}}* }ע'`F~O~W~pB~d~`F>=0~m~w'F~~]~]~\][[[+][>I~!~Ѐ~N(+>N~~[~pHNJ '.B1NF?JGN.BFFāb}B c' "'\[][FŁB ' "'][FȁK`:K`:\][[[+][>I! P;(+>N(2[4pHSP;Jcj.BqPwP,~PwF?J.BPP,FFƁB ' "'K[K[\[][Fǁ(B ' "'(K[K[][N<NOPOOPQiQFɁ"s '`Fˁ `+F́ `+F́ `+F΁' `+Fρ= `+FЁT `+Fсl `+Fԁ~pB`F>=0'RS FՁNj= O'`Fׁ# .`:+F؁7 `:+FہpB`F>=0'SuSF܁<9 '`Fށ  '`:+F߁3 K`:+F⁋pB`F>=0'T8TFか:i '` +F恋pB`F>=0'F聋 \][[[+][>I!)!U6(+>N>H[JpHiU6Jy.BUrF?J.1BFFꁋB ' "'\[][F끋 1B ' "' ][F%,/5\][[[+][>IE!QIV(+>Nfp[rpHVJ.BVF?J.BFF쁋 B ޡ' "' \[][F큋'6B ' "'-6][F;BU][JaaB[q[''.F][JB[՜[''.F +gg`F][J00B[@[''.[XTU UV+VxW?WWX8XX +FD Eg p '`Fj `kL+F$$L``>J .BYFFaipBq`F>=0z'FQQ`J`'g'FuB v' 'M ' "'L``YYZFZ[F ע'`G  '`+G `+G `:+G +`+GKSpB^`F>=0gq'[\G  ' `G  `k+"G S[pB``G>=0is'G "'K``LG  "' K``LG2F "'4F9K``LGK_t "'btgK``LGy "'K``LG "'K``LG "'K``LG- "'- K``LG2@[. "'F[N`:`:G`t "'v{K``LG "'K``LG "'K``LG # ' "'#K``LG(<Q "'?QDK``LGVj~ "'l~qK``LG "'K``LG "'K``LG  "' K``LG ";h "');.K``LG!@Th "'Vh[K``LG"m "'K``LG# "'K``LG$o o!][[[\>N "[pH-c8=>G&RcPJeG&t#B u' "'![\G'$ "'K``LG(  "' K``LG)#/]% "'7]?`:PK`:`G*b& c'% "''`:`G+( "'K``LG,) "'K``LG-'=* "'+=0K``LG.BVl+ "'Zl_K``LG/q, "'K``L\X\\]8]]^^`^^_>__``t`aaRaab0bzbcccd/dyde*eteffRf"G0vW- w'.`GG2M`:+G5ApB A`G0>=0'gugG62T,/ 3'0`GBG8 '`:+G; pB `G6>=0'hhbG<(1 '2`GG> `G+GApB`G<>=0'hiGBZ3 ע'4`GGD 5 '6 ʡ'7],`G+GGS[pBl`GB>=0u'GI +&8 "'&`\GJ+/X9 "'9XA:`:K``izij jeGK5T`; 6'<`GGM =`+GN3 >`+GOP ?`+GRpB`GK>=0'jk<GS;ZX@ <'A`GGU `:+GV. B`Y+GWL C`LK+GZpB`GS>=0'kl G[3}cD 4'E`GG]6F`:+G^\ `G+Ga*pB*`G[>=0'lwlGb>^G ?'H`GGd 5 @'6 `'7],`G+GeK`:+Gh:pB:`Gb>=0 'GkIB "'``G[GlJ "':`:\Gm )8 "')1`:\Gn.>\K "'F\N1`:`G[mPmmn0nvnGo9ZL :'M`LXGqK`:+Gt pB `Go>=0'Gum)m1N`:`Go>J@WGxaoGxqBN[`GoJ`Go'L'Ooo%oqop3GyP ˢ'Q`LbG{R`N+G~[cpBw`Gy>=0'GR`O5\][[[+`Gy>I! +q(+>N)[+pHJqJZtG~qqP?JGqGUBUR[\[`GyJ  `Gy'P'SEqMqGYs1B|}R[`GyJ`Gy'P'Tr\ppqr.rGU 'V`G6G B`Y+G=EpBS`G>=0\f'rs@GW 'X`GG Y Y'Z`:+G `:+G SpBS`G>=0$.'stGy[ '\`LXG TpBT`G>=0%/'GYi "'l}K`G`GGS "'K``GG] "'K``GGy "'^`:`GG+L< "'.L?K`G`GGQaw "'cwk`:`GtDttu$unuvvKGTqT_ U'``GG"a`:+GM `G+GpB`G>=0'vwG/Ob 0'c`LbG(`G+GpB`G>=0'G m#m4(`G`G>JBXGbwGqB([`GJ`G'b'dxGwpwxx~Ge Т'f`LXG`G+G!`G+GT\pBn`G>=0w'G`G!`G`G>JGygyvG7B@A[D![`GJPP`G'e'gyyxy>yz,Gh 'i`LXG{ M`:+GipB1i`G>=0:D'zzG]zuj ^'k`LbGPl`G+G^`+Gh!`+GÁr"`+GƁ-pB-`G>=0'Gǁ2:4E4Fl[\!`+c"`+vl`G+`G>IÄ"""%ÙÉ{`Gúø{(+ς{(+|(+>J G{`G?I2"""%=7|`G%_]{`%us{`%ęĉ{`>JĪĽG{`{`{`|`G?=0'GGʁ8KŧBTŧUl[`GJoo`G'j'mŗ}Gˁūž;1B;l[!["[l[`GJ霣`G'j'n~ +/~2~ 5~+{o{}w}~}ǴPio Q'p`G΁ q`GρFr`7GЁns`Gсȓt`7GҁȻu`7GӁv`Gԁw`7 +GՁ/x`7GցRy`Gׁvz`7 G؁ɞ{`7Gفɼ^`:+Gځ |`G+Gہ }`LK+G܁ `+G߁ +pB +`G>=0'%qG~ '`LbG⁋ͮ`+Gか͸!`+G䁋"`+G灋v~pBˈ`G>=0ˑ˛'G聋`!`"`+`G>I""%x`%i`(+>J&6G@i`Cx`?IQ""%XV`%fdx`%tri`>J̅̕G̟i`̢x`̥`?=0̳̽'GG끋 GBG[![`GJ`G'~'BEG쁋K[ͥ1Bdͥe[h![k"[`GJww`G'~'͝b͠mͣx@4G큋ΠιL Ρ'`LbG1`G+GH`G+G#dpB,d`G>=05?'Giqxω`Gϝ`G`G>Jϧ϶GGB[[`GJ`G''(39sG--``IGD Ѣ'`G_GuB[چ[''JHW`:+HX^`:+HY (`+HZ |`G+GB ȡ'9 ݡ'*`:+GYB '9 1'`:+GB f'9 {'`:+HB 䦡'9 仡'`:+H3B '9  '`:+H}B D'9 Y'`:+H}B N'9 c'`:+HB j'9 '`:+HB 겡'9 ǡ'`:+H>B '9 '`:+HB V'9 k'`:+HB '9 '`:+H B ﺡ'9 ϡ'`:+H +B ԡ'9 '`:+H DB  '9 !'`:+H B N'9 c'`:+H B '9 '`:+HB '9 ͡'`:+H1B '9  '`:+H{B B'9 W'`:+HB '9 '`:+HB ¡'9 ס'`:+HB '9 '`:+H,B '9 '`:+HaB *'9 ?'`:+HB d'9 y'`:+HB '9 '`:+HB ġ'9 ١'`:+HB ġ'9 ١'9`:+HB ڡ'9 '`:+HB ԡ'9 ' `:+HB '9 ѡ'7`:+HB '9 '``:+HB '9 '`:+HB '9 'F`:+H  B  '9  '`:+H! +B  +'9  +'`:+H" B  '9  ˡ'`:+H# B  '9  '!`:+H$ B  '9  ɡ'`:+H%B '9 ա'`:+H&B Ρ'9 '`:+H'B '9 '`:+H(7B '9 '`:+H)1B '9 '`:+H*B '9 'z`:+H+@B  +'9 '`:+H,[B ('9 ='`:+H-lB :'9 O'`:+H.B j'9 '`:+H/B '9 ˡ'`:+H0&B '9 '`:+H1#B '9  '`:+H2EB '9 %'`:+H3_B ,'9 A'`:+H4~B J'9 _'`:+H5 B  ^'9  s'`:+H6!B !n'9 !'`:+H7"B "x'9 "'r`:+H8#B #'9 #'`:+H9$B $'9 $'`:+H:%B %'9 %'`:+H;&B &'9 &á'`:+H<( B '֡'9 ''`:+H=)3B ('9 )'`:+H>*=B * '9 *!'`:+H?+<B + '9 +!'`:+H@,fB ,0'9 ,E'`:+HA-B -T'9 -i'`:+HB.B .z'9 .'`:+HC/B /'9 /' `:+HD0 +B 0ȡ'9 0ݡ' `:+HE2@ B 2'9 2' `:+HF3B 3J'9 3_'`:+HG4gB 4^'9 4s'1`:+HH5B 5X'9 5m'`:+HI6vB 6H'9 6]'{`:+HJ7B 7\'9 7q'`:+HK8B 8p'9 8'/`:+HL9B 9'9 9'`:+HM:B :'9 :ӡ'`:+HN<B ;'9 ;'`:+HO=B <ڡ'9 <'`:+HP>B ='9 ='`:+HQ?LB ?'9 ?+' `:+HR@e!B @2'9 @G'"`:+HSA}#B AJ'9 A_'$`:+HTBpB BB'9 BW'`:+HUC%B CV'9 Ck'&`:+HVD'B DX'9 Dm'(`:+H\bjҢ}Ң`GJ҃҇H]'H]ҧү,m,m`:`G>N`GMQ_= G^.HXJ#GHa)0Ա)@ԱH*`:`:>N`j+`:l.,BԄHcJԗ5`:Ԟ#Ԩ(+'`:HcԶԽ0,B0*`:`:>J.-B ..BzHeHkHlEJ/Zb*`:`>Jv"}.0B֏Hd֨.0BֺHi$pHdHdW0BW*`:`>J$+`'g'@.Hm\alt*`:׉K`:טO`:+\>Jשװ.1B..BHeHjHe .B$,*`:`:>NGLK`:NHgYIl%up`:J؀؇`:?=ؘؑ.2BضHf=HhJHf c2B&c.*`:`:>IBF.0BXHicHd>J{ق?Nٞ٧3`:$ٳpپI.0BHd>J?JLSHgږڤ4Bڮڶ`:`:JĜ`:' 'NGHhd5B d`:!K`:\>=.['7'2EGUZHiiw܂6Bہ܂ۉ7`:`:>N۪۟8[۬['9'9J`:'9$':';sHj܇܌z1Bܞzܦ*`:ܻK`:O`:+\>I,(+B=,'?I;(+B=;'?=-['7'<.Xf,m;Hr'='`>JBsUQ_/'>HlH_dl޹pBށ޹`G>=0ފޔ'HnI? "'1I9`:`:HkNsߜ-B O') "'߄ߜߌ`:`:Hoߡߨ߾ "'߬߾߱``:Hp@ "'`:`:Hs(F*3F`:J6;.BGH΁sw*K`:\>=.B#઀4(+B'4`:GHt>I{^{`:Jaf.BGHρK`:\>=.B#(+B' `:GHu`:J.BGHЁ ``"K`:\>=/.B#HB(+B'W`:GHv`:J.BHHсGKZbK`:\>=o.B#䈀t(+B't`:HHw$/]B]`:JEJ.BHHҁK`:\>=.B#ڀ4(+B'4`:HHxz`:J.BHHӁ>>K`:\>= .B#& (+B'5`:HHy`:J.BHHԁH HK`:\>= .B#0*(+B'?`:HHz`:J.BHHՁd!d)K`:\>=6.B#LFt(+B'[t`:HH{`:J.BHHցOSdlK`:\>=y.B#ꔀ4(+B'4`:HH|4?kQk`:JTY.BHHׁK`:\>=.B#(+B'`:HH}`:J.BHH؁PPK`:\>=.B#82(+B'G`:HH~`:J.BHHف7;IQK`:\>=^.B#vpt(+B't`:HH 4 4`:J#(.BH HځcgrzK`:\>=.B#4(+B'4`:H H(3Q>Q`:JAF.BH +HہK`:\>=.B#(+B'`:H +HFQyay`:Jdi.BH H܁K`:\>=.B#(+B'`:H H`:J.BH H݁HH +K`:\>=.B#0*t(+B'?t`:H H`:J.BH Hށ15DLK`:\>=Y.B#rl4(+B'4`:H H22`:J!&.BHH߁aepxK`:\>=.B#(+B'`:HH-8bIb`:JLQ.BHHK`:\>=.B#ڀ(+B'`:HHw`:J.BHH။<<K`:\>= +.B#$t(+B'3t`:HH`:J.BHH⁋+/?GK`:\>=T.B#nh4(+B'}4`:HH6 6`:J#(.BHHかgkxK`:\>=.B#(+B'`:HH5@`L``:JOT.BHH䁋K`:\>=.B#Ȁ(+B'`:HHS^zhz`:Jkp.BHH偋K`:\>=.B#܀t(+B't`:HHit`:J.BHH恋$$K`:\>=.B# 4(+B'4`:HH`:J.BHH灋 ^^!K`:\>=..B#F@(+B'U`:HH`:J.BHH聋AES[K`:\>=h.B#z(+B'`:HH>*>`:J-2.BHH運mq|K`:\>=.B#t(+B't`:HH-8N9?N`:JBG.BHHꁋw{9K`:\>=.B#4(+B'4`:HH)4T@T`:JCH.BHH끋K`:\>=.B#(+B'`:HHBMa Sa`:JV[.BHH쁋 K`:\>=.B#(+B'`:HH/:L7?L`:JBG.BHH큋sw7{K`:\>=.B#t(+B't`:HH!5`'5`:J*/.BHH]a`fnK`:\>={.B#4(+B'4`:HH))`:J!.BHHSW^fK`:\>=s.B#~(+B'`:HH$F$`:J.BHHMQFW_K`:\>=l.B#|v(+B'`:HH  #  #`:J  .BH H O S  \  dK`:\>= q.B#  ~t(+B' t`:H H + + ++ + ++`:J + +#.BH!H +U +Y + +` + +hK`:\>= +u.B# + +4(+B' +4`:H!H +  3  3`:J # (.BH"H a e  o  wK`:\>= .B#  (+B' `:H"H  & 8! + 8`:J . 3.BH#H _ c ! g  oK`:\>= |.B#  (+B' `:H#H   1  1`:J ! &.BH$H _ c  m  uK`:\>= .B#  t(+B' t`:H$H)C2C`:J5:.BH%Hos{K`:\>=.B#4(+B'4`:H%H'2N<N`:J?D.BH&H{K`:\>=.B#(+B'`:H&H9DdPd`:JSX.BH'HK`:\>=.B#̀ô(+B'ô`:H'HXcn`:Jqv.BH(HK`:\>=.B#t(+B't`:H(Hkv}`:J.BH)HK`:\>=.B#4(+B'4`:H)H_j|zo|`:Jrw.BH*HzK`:\>=.B#΀(+B'`:H*HOZ~h~`:Jkp.BH+HK`:\>=.B#ƴ(+B'ƴ`:H+H|`:J.BH,H""K`:\>=.B# +t(+B't`:H,H`:J.BH-H44K`:\>= .B#4(+B'+4`:H-H`:J.BH.H dd'K`:\>=4.B#LF(+B'[`:H.H`:J .BH/ISWhpK`:\>=}.B#ɴ(+B'ɴ`:H/H4?cMc`:JPU.BH0IK`:\>=.B#Ҁt(+B't`:H0H]h~o~`:Jrw.BH1IK`:\>=.B#ր4(+B'4`:H1HZer`:Juz.BH2I + +K`:\>=.B#(+B'`:H2H`:J.BH3I&&K`:\>=.B#̴(+B'̴`:H3H`:J.BH4IDD +K`:\>=.B#,&t(+B';t`:H4H`:J.BH5I   X  X K`:\>= -.B# @ :4(+B' O4`:H5H     `:J  .BH6I!!!h!(!h!0K`:\>=!=.B#!P!J(+B'!_`:H6H!!!r!!`:J!!.BH7I"'"+"rr"3"r";K`:\>="H.B#"Z"Tϴ(+B'"iϴ`:H7H""#"#`:J"".BH8I #3#7##@##HK`:\>=#U.B##h#bt(+B'#wt`:H8H##$$$`:J$$ +.BH9I +$?$C$$K$$SK`:\>=$`.B#$r$l4(+B'$4`:H9H$$%%%`:J% +%.BH:I %A%E%%L%%TK`:\>=%a.B#%r%l(+B'%`:H:H%&&%&&%`:J&&.BH;I &U&Y&&e&&mK`:\>=&z.B#&&Ҵ(+B'&Ҵ`:H;H' '+'M'8'M`:J';'@.BH<I '}'''''K`:\>='.B#''t(+B''t`:H<H(H(S(u(`(u`:J(c(h.BH=I((((((K`:\>=(.B#((4(+B'(4`:H=H)k)v)))`:J)).BH>I))*)*)K`:\>=).B#))(+B')`:H>H*p*{***`:J**.BH?I**+*+*K`:\>=*.B#**մ(+B'*մ`:H?H+u++++`:J++.BH@I++,*+,*+K`:\>=+.B#,, t(+B',!t`:H@H,,,,,`:J,,.BHAI,--N- -N-K`:\>=-!.B#-6-04(+B'-E4`:HAH-----`:J--.BHBI.!.%.t.1.t.9K`:\>=.F.B#.\.V(+B'.k`:HBH../ //`:J//.BHCI/A/E/ /O//WK`:\>=/d.B#/x/rش(+B'/ش`:HCH0008 0!08`:J0$0). +BHDI0k0o0 0}00K`:\>=0. +B#00t(+B'0t`:HDH1B1M1u 1]1u`:J1`1e. BHEI112 121K`:\>=1. B#114(+B'14`:HEH22222`:J22.BHFI223D23D3K`:\>=3.B#3,3&(+B'3;`:HFH333133`:J33.gBHGI4 44X144X4!K`:\>=4..gB#4@4:۴(+B'4O۴`:HGH44444`:J44.BHHI5 55R55R5K`:\>=5*.B#5:54t(+B'5It`:HHH555{55`:J55.BHII566B{66B6K`:\>=6.B#6*6$4(+B'694`:HIH66666`:J66.BHJI77 7V77V7K`:\>=7).B#7>78(+B'7M`:HJH777/77`:J77.BHKI88!8j/8*8j82K`:\>=8?.B#8R8L޴(+B'8a޴`:HKH88989`:J89.BHLI9A9E99S99[K`:\>=9h.B#99zt(+B'9t`:HLHÁ:::;:(:;`:J:+:0.BHMI:i:m::w::K`:\>=:.B#::4(+B':4`:HMHā;-;8;\;F;\`:J;I;N.BHNI;;;;;;K`:\>=;.B#;ʀ;(+B';`:HNHŁ=<.B#<<(+B'<`:HOHƁ=9=D=d=P=d`:J=S=X.BHPI!======K`:\>==.B#=̀=t(+B'=t`:HPHǁ>[>f> >t>`:J>w>|.BHQI">>? >?>K`:\>=>.B#>>4(+B'?4`:HQHȁ???"??`:J??.!BHRI#??@,"?@,?K`:\>=@.!B#@@(+B'@#`:HRHɁ@@@$@@`:J@@.#BHSI$@@AD$AADA K`:\>=A.#B#A,A&(+B'A;`:HSHʁAAAAA`:JAA.BHTI%AAB<BB<BK`:\>=B.B#B$Bt(+B'B3t`:HTHˁBBB&BB`:JBB.%BHUI&BCCP&CCPCK`:\>=C#.%B#C8C24(+B'CG4`:HUH́CCC(CC`:JCC.'BHVI'D DDR(DDRDK`:\>=D*.'B#D:D4(+B'DI`:HVLi{ncT=/y +CJ +CJ +CJ +CJ +CJ +CJ +CJ +CJ +CJ +CJ +ƒCÊJ +ŃCƊJ +ȃCɊJ +˃C̊J +΃CϊJ +уCҊJ +ԃCՊJ +׃C؊J +ڃCۊJ +݃CފJ +CJ +CJ +CI(DDA``II)DDrB`I(I,D CB]`PI-E+DB]`G+IEVEVEEmEEsC]`P\>=E.DBEE0[E.CBI,`G4EEEEl[`GJE&EEE놃`GI-I, EV]I/EEF)FFF*`:`:JF.FfFUF..DBI-)FwHaI0FFGFFGFF*`:FK`:FO`:+\>=GF.DBI-4GGGAGl`G\JGGGG#쁁G1쐂G8HmI2GKGPHEBGWHG_*`:GtK`:\>=Go#GGo(+B'Go`:FGGG`PG.CBI,>=Gۜ['7'FGH`HoI4HLHPH*HZHHbK`:\>=Ho.EB'*H9I2I5HHIHIHK`:\>=H.EB'II2I6IQIUIIdIIlK`:\>=Iy.EB'II2I7IIJIJIK`:\>=I.EB'JVI2I8JTJXJJjJJrK`:\>=J.EB'JI2I9JJK*JK*JK`:\>=K.EB'K I2I:KSKWKK]KKeK`:\>=Kr.EB'KsI2I;KKLKLKK`:\>=K.EB'KI2I<L;L?LLPLLXK`:\>=Le.EB'L1I2I=LLMLMLK`:\>=L.EB'M I2I>MIMMMM^MMfK`:\>=Ms.EB'MI2I?MMNMNMK`:\>=M.EB'N NI2I@NFNJNNUNN]K`:\>=Nj.EB'NI2IANNNNNNK`:\>=N.EB'N I2IBO0O4O}OCO}OKK`:\>=OX.EB'OskI2ICOOOOOOK`:\>=O.EB'OI2IDP2P6PPEPPMK`:\>=PZ.EB'Pu)I2IEPPPPPPK`:\>=P.EB'PI2IFQ(Q,QwQ<QwQDK`:\>=QQ.EB'QmI2IGQQQQQQK`:\>=Q.EB'QFI2IHR0R4RRDRRLK`:\>=RY.EB'RuI2IIRRRRRRK`:\>=R.EB'RI2IJS(S,SmS7SmS?K`:\>=SL.EB'SccI2IKSSSSSSK`:\>=S.EB'SI2ILTTTYT TYT(K`:\>=T5.EB'TO!I2IMTTTTTTK`:\>=T.EB'TI2INU +UUUUUUU$K`:\>=U1.EB'UKI2IOUUUUUUK`:\>=U.EB'€U>I2IPUUV-9UV-VK`:\>=V.EB'9V#I2IQV\V`VVkVVsK`:\>=V.EB'ŀVI2IRVVW VWVK`:\>=V.EB' V[I2ISW)W-W`7W1W`W9K`:\>=WF.EB'7WVI2ITWWW`WWWK`:\>=W.EB'`WI2IUWWX(WX(WK`:\>=X .EB'׀XxI2IVXQXUXFX[XXcK`:\>=Xp.EB'FXI2IWXXXXXXK`:\>=X.EB'ӀX6I2IXY#Y'Y`Y.Y`Y6K`:\>=YC.EB'̀YVI2IYYYYYYYK`:\>=Y.EB'΀YI2IZYYZ/!ZZ/ZK`:\>=Z.EB'!Z%SI2I[Z]ZaZZkZZsK`:\>=Z.EB'рZI2I\ZZ[ Z[ ZK`:\>=Z.EB'Ӏ[I2I][8[<[y[E[y[MK`:\>=[Z.EB'Հ[opI2I^[[[[[[K`:\>=[.EB'׀[I2I_\\\^\)\^\1K`:\>=\>.EB'ـ\T.I2I`\\\\\\K`:\>=\.EB'\I2Ia\\] z\] \K`:\>=].EB'z]I2Ib]Q]U]]b]]jK`:\>=]w.EB'܀]KI2Ic]]^ ]^ ]K`:\>=].EB'ހ^I2Id^8^<^y^E^y^MK`:\>=^Z.EB'^o I2Ie^^^^^^K`:\>=^.EB'^hI2If_-_1_~_B_~_JK`:\>=_W.EB'_tI2Ig______K`:\>=_.EB'_&I2Ih`"`&`]`,`]`4K`:\>=`A.EB'`SI2Ii``````K`:\>=`.EB'`I2IjaaaEaaEaK`:\>=a%.EB'a;CI2IkataxaaaaK`:\>=a.EB'aI2Ilaab'ab'aK`:\>=b.EB'bI2ImbTbXbbabbiK`:\>=bv.EB'b`I2InbbcrbcbK`:\>=b.EB'rbI2Ioc-c1cnc:cncBK`:\>=cO.EB'cdI2IpccccccK`:\>=c.EB'c}I2Iqddd@dd@dK`:\>=d#.EB'd6I2IrdpdtddddK`:\>=d.EB'd;I2Isdde.de.dK`:\>=e .EB'e$I2Ite^ebeeneevK`:\>=e.EB'eI2IueefefeK`:\>=e.EB'fXI2Ivf9f=fvfDfvfLK`:\>=fY.EB'ȀflI2IwffffffK`:\>=f.EB'fI2Ixgg#gdg.gdg6K`:\>=gC.EB'gZuI2IyggggggK`:\>=g.EB'gI2Izh h hL hhLhK`:\>=h,.EB' hB3I2I{hhh hhhK`:\>=h.EB' hI2I|hiiK iiKiK`:\>=i&.EB' iAI2I}iiiiiiK`:\>=i.EB'i PI2I~iij61jj6j K`:\>=j.EB'1j, I2Ij_jcjjijjqK`:\>=j~.EB'j +I2Ijjj{jjjK`:\>=j.EB'{j +mI2Ik*k.kok9kokAK`:\>=kN.EB'ke +I2Ikkk/kkkK`:\>=k.EB'/k +I2IlllZl!lZl)K`:\>=l6.EB'lP I2IllllllK`:\>=l.EB'l I2IlmmEm mEmK`:\>=m".EB'm; HI2ImkmommrmmzK`:\>=m.EB'm I2ImmnmnmK`:\>=m.EB'n + I2InEnIn nVnn^K`:\>=nk.EB' n eI2Innn"nnnK`:\>=n.EB'"n I2Io,o0oo$o:oooBK`:\>=oO.EB'$oe#I2IooooooK`:\>=o.EB'oI2IoppD&ppDpK`:\>=p#.EB'&p:I2Ipnprp(pxppK`:\>=p.EB'(p@I2W2n,If$A^{9Vs1N k)Fc!>[x6Sp.K h &   +C +  `   }  ;  Xu]Irr*G`LC\? IrFrMrr)r]rrre*`:`:Irvr{rrrr*`:rK`:rO`:+\Irrs(Hss(`:Jss.)'IIJ쁋sXs\sHshsspK`:\>=s}.'IsJ'IIsstJst`:Jss.)'KIJ큋t<t@tJtJttRK`:\>=t_.'Ktz'IItttLtt`:Jtt.)'MIJuuubLu%ubu-K`:\>=u:.'MuT'IIuuuNuu`:Juu.)'NIJuuv8Nuv8vK`:\>=v.'Nv*?'IIvjvuvOvv`:Jvv.)'PIJvvw0Ovw0vK`:\>=w.'Pw"'IIwfwqwQww`:Jww.)'RIJwwx@Qwx@xK`:\>=x.'Rx2'IIxuxxSxx`:Jxx.)'TIJxxyJSyyJy K`:\>=y.'Ty<4'IIyyyUyy`:Jyy.)'VIJyzzXUzzXzK`:\>=z'.'VzJ'IIzzzWzz`:Jzz.)'XIJ{){-{W{D{{LK`:\>={Y.'X{'II{{{ {{`:J{{.)'YIJ|0|4| |A||IK`:\>=|V.'Y|t)'II||}Z|}`:J||.)'[IJ}9}=}Z}O}}WK`:\>=}d.'[}'II}}~+\}~+`:J}}.)']IJ~g~k~\~~~K`:\>=~.']~w'II~1^1`:J.)'_IJ^b^ksK`:\>=.'_'II ` `:J.)'`IJ9=`GOK`:\>=\.'`v'IIa`:J.)'bIJ ja+j3K`:\>=@.'b\l'IIc`:J.)'dIJ"zc4z<K`:\>=I.'dl'II*`:J.)'*IJ V*V!K`:\>=..'*H'II`:J.)'eIJr*r2K`:\>=?.'eda'IIf`:J.)'gIJ-1fDLK`:\>=Y.'g~'IIh`:J.)'iIJ04hBJK`:\>=W.'iv'II`:J.)'jIK,0?GK`:\>=T.'jtV'IIk`:J.)'lIK:>kQYK`:\>=f.'l'II  `:J.)'mIK@DS[K`:\>=h.'m 'IIn`:J.)'oIKBFnV^K`:\>=k.'o!K'II`:J.)'pIKNRdlK`:\>=y.'p!'II-q-`:J.)'rIKeiq|K`:\>=.'r"'IIGsG`:J.)'tIKsK`:\>=.'t#@'IIV.V`:J11.)'uIKK`:\>=.'u#'II#_v5_`:J88.)'wIKvK`:\>=.'w$'II&1mxCm`:JFF.)'yIK xK`:\>=.'y%5'II0;pzJp`:JMM.)'{IK +zK`:\>=.'{%'II*N1N`:J44.)'IK w{K`:\>=.'&'II#|#`:J.)'}IK RV|aiK`:\>=v.'}'*'II~`:J.)'IK OS~ckK`:\>=x.'''II""`:J.)'IKW[ksK`:\>=.'(x'II**`:J.)'IK_cs{K`:\>=.')'II$$`:J.)'IKTXdlK`:\>=y.')'II!!`:J.)'IKW[ltK`:\>=.'*m'II//`:J.)'IKeizK`:\>=.'+'II==`:J.)'IKswK`:\>=.'+'II ::`:J.)'IKjnzK`:\>=.',b'II7 7`:J.)'IKmqK`:\>=.'- 'II\&\`:J//.)'IKK`:\>=.'-'II;F^`:Jgg.)'IK::K`:\>=.',.W'IIp{`:J.)'IKHH +K`:\>=.':.'II~`:J.)'IKVVK`:\>=%.'H/'IIÁ`:J.)'IKN NK`:\>=!.'@0L'IIā}`:J.)'IK44K`:\>= +.'&0'IIŁalv`:Jyy.)'IKK`:\>=.'1'IIƁAL[`:J^^.)'IK + +K`:\>=.'2A'IIǁ=H~W~`:JZZ.)'IKK`:\>=.'2'IIȁ9DzSz`:JVV.)'IKK`:\>=.'3'IIɁ/:eDe`:JGG.)'IK K`:\>=.'46'IIʁ#q;q`:JDD.)'IK!K`:\>=.'4'IIˁCN}Z}`:J]].)'IK"K`:\>=.'5'IÍ0;wMw`:JPP.)'IK#K`:\>=.'6+'IÍ>I[`:J^^.)'IK$K`:\>=.'6'II΁KVg`:Jjj.)'IK%K`:\>=.'7y'IIρT_q`:Jtt.)'IK&,,K`:\>=.'8 'IIЁal}`:J.)'IK'44K`:\>=.'&8'IIсbmx`:J{{.)'IK(K`:\>=.'9n'IIҁHSc`:Jff.)'IK)K`:\>=.':'IIӁJUe`:Jhh.)'IK*K`:\>=.' +:'IIԁLWg`:Jjj.)'IK+K`:\>=.' ;c'IIՁJUb`:Jee.)'IK,K`:\>=.'< +'IIց5@oLo`:JOO.)'IK-K`:\>=.'<'IIׁ!,f=f`:J@@.)'IK.K`:\>=.'=X'II؁)4nEn`:JHH.)'IK/K`:\>=.'='IIف1<vMv`:JPP.)'IK0K`:\>=.'>'IIځ5@sNs`:JQQ.)'IK1K`:\>=.'?M'IIہ%0_<_`:J??.)'IK2K`:\>=.'?'II܁V-V`:J00.)'IK3K`:\>=.'@'II݁$^5^`:J88.)'IK4K`:\>=.'AB'IIށ!,f=f`:J@@.)'IK5K`:\>=.'A'II߁#.]:]`:J==.)'IK6K`:\>=.'B'II==`:J.)'IK7jnwK`:\>=.'€C7'II။((`:J.)'IK8[_muK`:\>=.'ÀC'II⁋55`:J  .)'IK9nrK`:\>=.'ŀD'IIか\(\`:J11.)'IK:K`:\>=.'ǀE,'II䁋+6lEl`:JHH.)'IK;Ÿ£±¹K`:\>=.'ȀE'II偋'2hAh`:JDD.)'IK<ÛßíõK`:\>=.'ɀFz'II恋*5K`:JTT.)'IK=ĹĽK`:\>=.'ˀG!'II灋KVŅbŅ`:Jee.)'IK>ŴŸK`:\>=.'̀G'II聋+6Z9=Z`:J@@.)'9IK?ƃƇ9ƍƕK`:\>=Ƣ.'9ƸHo'II運&&`:J  .)'IK@RVǚ^ǚfK`:\>=s.'΀njI'IIꁋ`:J.)'IKAQUȮgȮoK`:\>=|.'ЀȠI'II끋`:J.)'IKBJNɚZɚbK`:\>=o.'ҀɌJd'II쁋`:J.)'IKC"&h-h5K`:\>=B.'ԀZK 'II큋ʙʤʱ`:Jʴʴ.)'IKD XXK`:\>=,.'րJK'II˄ˏ˸˘˸`:J˛˛.)'IKE,,K`:\>=.'؀LY'II`ḳ{̣`:J~~.)'IKF..K`:\>=.'ڀ M'II[f͑p͑`:Jss.)'IKG;K`:\>=.'܀M'II3>eFe`:JII.)'IKHΐΔΛΣK`:\>=ΰ.'ހNN'II<<`:J.)'IKIjn϶x϶πK`:\>=ύ.'ϨN'II`:J.)'IKJFJАSА[K`:\>=h.'ЂO'IIн`:J.)'IKK $j-j5K`:\>=B.'\PC'IIљѤѰ`:Jѳѳ.)'IKLPPK`:\>=&.'BP'IIx҃ҥ ҉ҥ`:JҌҌ.)' IKM K`:\>=.' Q'II5@`7E``:JHH.)'7IKNӇӋ7ӏӗK`:\>=Ӥ.'7ӸR8'II&&`:J  .)'IKORVԚ^ԚfK`:\>=s.'ԌR'II``:J.)'`IKPX` X(K`:\>=5.'`JS'IIՍ՘թ`:Jլլ.)'IKQ ``#K`:\>=0.'RT-'IIֳ֖֡`:Jֶֶ.)'IKRn(n0K`:\>==.'`T'IIפׯ`:J.)'IKS!%|6|>K`:\>=K.'nU{'IIثض`:J.)'IKTb#b+K`:\>=8.'TV"'IIِٛ٦`:J٩٩.)'IKUBB K`:\>=.'4V'IIozڥڄڥ`:Jڇڇ.)'IKVK`:\>=.'Wp'IJJUۂ`ۂ`:Jcc.)'IKW۰۴۾K`:\>=.'X'IJ0;sKs`:JNN.)'IKXܧܫܺK`:\>=.'X'IJ2=uMu`:JPP.)'IKYݩݭݼK`:\>=.'Ye'IJ4?wOw`:JRR.)'IKZޫޯ޾K`:\>=.'Z 'IJ0;hFh`:JII.)'IK[ߖߚߤ߬K`:\>=߹.'Z'IJK(K`:J++.)'IK\z~K`:\>=.'[Z'IJ##`:J.)'IK]MQX`K`:\>=m.'\'IJ`:J.)'IK^\"\*K`:\>=7.'׀N\'IJ`:J.)'IK_ ``$K`:\>=1.'R]O'IJ `:J.)'IK`L LK`:\>=!.'>]'IJ +uF`:J.)'FIKaFK`:\>=.'F^'IJ <GqQq`:JTT.)'IKbK`:\>=.'Ӏ_D'IJ A#A`:J&&.)'IKckov~K`:\>=.'̀_'IJ `:J.)'IKdDHRZK`:\>=g.'`'IJ `:J.)' IKeT T#K`:\>=0.' Fa9'IJ{`:J.)'IKf  K`:\>=.'a'IJ9DoNo`:JQQ.)'IKgK`:\>=.'b'IJ"U 0U`:J33.)' +IKh K`:\>=.' +c.'IJ8 8`:J.)' IKidh pxK`:\>=.' c'IJ   `:J.)'IKj8< DLK`:\>=Y.'rd|'IJ`:J.)'IKk`"`*K`:\>=7.'Re#'IJ`:J.)'IKl44K`:\>= .'&e'IJ\gm`:Jpp.)'IKmK`:\>=.'fq'IJ$D!)D`:J,,.)'!IKnko!s{K`:\>=.'!g'IJ`:J.)'IKo>BLTK`:\>=a.'|g'IJ  `:J.)'IKpEI\dK`:\>=q.'hf'IJ  `:J.)'IKq<@KSK`:\>=`.'|i 'IJ`:J.)'IKr^"^*K`:\>=7.'Pi'IJ`:J.)'IKsTTK`:\>='.'Fj['IJ`:J.)'IKtFF K`:\>=.'8k'IJu`:J.)'IKu,,K`:\>=.'k'IJYdn`:Jqq.)' IKvK`:\>=.' lP'IJ 5@oLo`:JOO.)'!IKwK`:\>=.'!l'IJ!%0r"Er`:JHH.)'#IKx " K`:\>=.'#m'IJ":ErPr`:JSS.)'$IKyK`:\>=.'$nE'IJ#>%#>`:J&&.)'%IKzei%muK`:\>=.'%n'IJ$&`:J.)''IK{04x&<xDK`:\>=Q.''jo'IJ%(`:J.)')IK|#'z(6z>K`:\>=K.')lp:'IJ&*`:J.)'+IK}j*)j1K`:\>=>.'+\p'IJ',`:J.)'-IK~  Z,Z!K`:\>=..'-Lq'IJ(.`:J.)'/IK:.:K`:\>=.'/,r/'IJ)lw0`:J.)'1IK000K`:\>=.'1"r'IJ*do2`:J.)'3IK222K`:\>=.'3$s}'IJ+]h4p`:Jss.)'5IK4K`:\>=.'5t$'IJ,/:h6Eh`:JHH.)'7IK6K`:\>=.'7t'IJ- R8-R`:J00.)'9IK8K`:\>=.'9ur'IJ.@:@`:J.)';IKpt:K`:\>=.';v'IJ/=<=`:J.)'=IKsw<K`:\>=.'=v'IJ0Q>%Q`:J((.)'?IK>K`:\>=.'?wg'IJ1(b@9b`:J<<.)'AIK@K`:\>=.'Ax'IJ2$H+H`:J...)'IKqu{K`:\>=.'x'IJ3 a `:J.)'aIK A E a N  VK`:\>= c.'a |y\'IJ4   +B  +`:J  .)'CIK +> +B +B +T + +\K`:\>= +i.'C +z'IJ5 + + D + `:J + +.)'EIK > B D P  XK`:\>= e.'E z'IJ6   F  `:J  .)'FIK  # hF , h 4K`:\>= A.'F Z{Q'IJ7   G  `:J  .)'HIK   `G  ` &K`:\>= 3.'H R{'IJ8   I  `:J  .)'JIK  FIFK`:\>=.'J8|'IJ9mxz}`:J.)'zIKzK`:\>=.'z}F'IJ:/:mHm`:JKK.)'KIKK`:\>=.'K}'IJ;#.dL=d`:J@@.)'MIKLK`:\>=.'M~'IJ<$ON.O`:J11.)'OIK|NK`:\>=.'O;'IJ=)P)`:J  .)'QIKVZPckK`:\>=x.'Q'IJ>`:J.)'RIK48BJK`:\>=W.'Rr'IJ?`:J.)'SIKZZ%K`:\>=2.'SL0'IJ@`:J.)'TIKVVK`:\>=(.'TH'IJA`:J.)'UIK  dd&K`:\>=3.'UV~'IJB`:J.)'VIK ZZ K`:\>=-.'VL%'IJC`:J.)'IKK`:\>=.'ڀ'IJDOZWh`:Jkk.)'XIKWK`:\>=.'Xs'IJE@K|YX|`:J[[.)'ZIKYK`:\>=.'Z'IJF%0T7T`:J::.)'IK}K`:\>=.''IJG)[)`:J  .)'\IKX\[goK`:\>=|.'\h'IJH)])`:J.)'^IKae]xK`:\>=.'^'IJI,_,`:J  .)'`IK\`_ltK`:\>=.'`'IJJ2a2`:J.)'bIKkoaK`:\>=.'b]'IJK88`:J.)'cIKhlxK`:\>=.'c'IJL >d  >`:J  .)'eIK w { d   K`:\>= .'e 'IJM! +!!Jf!$!J`:J!'!'.)'gIK!|!!f!!!K`:\>=!.'g!R'IJN!""3h""3`:J"".)'iIK"`"d"h"m""uK`:\>=".'i"'IJO""#"#`:J"".)'jIK#>#B##L##TK`:\>=#a.'j#|'IJP#####`:J##.)'kIK$"$&$p$1$p$9K`:\>=$F.'k$bG'IJQ$$$l$$`:J$$.)'mIK%% %Vl%%V%K`:\>=%,.'m%H'IJR%%%%%`:J%%.)'nIK%%&0%&0%K`:\>=&.'n&"'IJS&f&q&o&&`:J&&.)'pIK&&'>o&'>'K`:\>=' .'p'0<'IJT'e'p'0'u'`:J'x'x.)'0IK'''0'''K`:\>='.'0''IJU('(2(dq(?(d`:J(B(B.)'rIK(((q(((K`:\>=(.'r('IJV))))hs)<)h`:J)?)?.)'tIK)))s)))K`:\>=).'t)1'IJW*6*A*u*T*`:J*W*W.)'vIK**+u*+*K`:\>=*.'v+'IJX+M+X+w+j+`:J+m+m.)'xIK++,(w+,(+K`:\>=+.'x,'IJY,`,k,y,~,`:J,,.)'zIK,,-@y,-@-K`:\>=- .'z-2&'IJZ-w--{--`:J--.)'|IK--.R{. .R.K`:\>=. .'|.D'IJ[.~..}..`:J...)'~IK../&}./&.K`:\>=..'~/t'IJ\/W/b//p/`:J/s/s.)'IK//0/0/K`:\>=/.'0 +'IJ]0E0P0{0Z0{`:J0]0].)'IK000000K`:\>=0.'0'IJ^1 1+1X161X`:J1919.)'IK111111K`:\>=1.'1i'IJ_22 2>22>`:J22.)'IK2n2r22~22K`:\>=2.'2'IJ`223/3 3/`:J3 3 .)'IK3a3e33r33zK`:\>=3.'3'IJa334%34%`:J44.)'IK4W4[44h44pK`:\>=4}.'4^'IJb44545`:J44.)'IK5>5B55L55TK`:\>=5a.'5|'IJc55555`:J55.)'IK6%6)6t646t6<K`:\>=6I.'6f'IJd66666`:J66.)'IK777^77^7&K`:\>=73.'7PS'IJe77777`:J77.)'IK77827827K`:\>=8 .'8$'IJf8e8p888`:J88.)'IK889.89.8K`:\>=9.'9 'IJg9[9f99p9`:J9s9s.)'IK99:9:9K`:\>=9.'9H'IJh:=:H::Y:`:J:\:\.)'IK::;:;:K`:\>=:.';'IJi;D;O;;_;`:J;b;b.)'IK;;<;<;K`:\>=;.'<'IJj<>=<.'<='IJk===C=$=C`:J='='.)'IK=n=r==y==K`:\>==.'='IJl==>=>`:J==.)'IKÁ>D>H>>Q>>YK`:\>=>f.'>'IJm>>?>?`:J>>.)'IKā?=?A??Q??YK`:\>=?f.'?2'IJn??@ ?@ `:J??.)'IKŁ@A@E@@T@@\K`:\>=@i.'@'IJo@@@@@`:J@@.)'IKƁA$A(AlA0AlA8K`:\>=AE.'A^'IJpAAAAA`:JAA.)'IKǁAAB:AB:BK`:\>=B.'B,''IJqBkBvBBB`:JBB.)'IKȁBBC*BC*BK`:\>=B.'C'IJrCWCbCClC`:JCoCo.)'IKɁCCDCDCK`:\>=C.'Cu'IJsD6DADvDPDv`:JDSDS.)'IKʁDDDDDDK`:\>=D.'D'IJtE&E1EWE9EW`:JE<E<.)'IKˁEEEEEEK`:\>=E.'E'IJuEEFEF`:JFF.)'IḰFCFGFFLFFTK`:\>=Fa.'Fvj'IJvFFFFF`:JFF.)'IḰGGGfG(GfG0K`:\>=G=.'GX'IJwGGGGG`:JGG.)'IK΁GGH0GH0GK`:\>=H .'H"'IJxHZHeHHmH`:JHpHp.)'IKρHHHHHHK`:\>=H.'H_'IJyI*I5IfIBIf`:JIEIE.)'IKЁIIIIIIK`:\>=I.'I'IJzJJ"JUJ0JU`:JJ3J3.)'IKсJJJJJJK`:\>=J.'J'IJ{KKKDK KD`:JK#K#.)'IKҁKtKxKKKKK`:\>=K.'KT'IJ|KKL0L L0`:JLL.)'IKӁL`LdLLpLLxK`:\>=L.'L'IJ}LLMLM`:JLL.)'IKԁM9M=MMEMMMK`:\>=MZ.'Mr'IJ~MMMMM`:JMM.)'IKՁNN NlN,NlN4K`:\>=NA.'N^I'IJNNNNN`:JNN.)'IKցNOOFO OFOK`:\>=O.'O8'IJOsO~OOO`:JOO.)'IKׁOOP OP OK`:\>=O.'P'IJPJPUP{P]P{`:JP`P`.)'IK؁PPPPPPK`:\>=P.'ȀP>'IJQQ%QVQ2QV`:JQ5Q5.)'IKفQQQQQQK`:\>=Q.'Q'IJRRRER RE`:JR#R#.)'IKځRvRzRRRRK`:\>=R.'R'IJRSS7SS7`:JSS.)'IKہShSlSSySSK`:\>=S.'S3'IJSST ST `:JTT.)'IK܁TNTRTT\TTdK`:\>=Tq.'T'IJTTUTU`:JTT.)'IK݁U2U6UUAUUIK`:\>=UV.'Ur'IJUUUUU`:JUU.)'IKށVV VlV,VlV4K`:\>=VA.'V^('IJVVVVV`:JVV.)'IK߁WW WXWWXW K`:\>=W-.'€WJ'IJWWW WW`:JWW.)'IKWWX8 WX8XK`:\>=X.'ÀX*v'IJX_XjXyXoX`:JXrXr.)'yIK။XXXyXXXK`:\>=X.'yX'IJY#Y.Yd Y=Yd`:JY@Y@.)'IK⁋YYY YYYK`:\>=Y.'ĀY'IJZ Z+Zc Z;Zc`:JZ>Z>.)'IKかZZZ ZZZK`:\>=Z.'ŀZk'IJ["[-[e[=[e`:J[@[@.)'IK䁋[[[[[[K`:\>=[.'ƀ['IJ\\)\W\5\W`:J\8\8.)'IK偋\\\\\\K`:\>=\.'ǀ\'IJ]]]M]$]M`:J]']'.)'IK恋]]]]]]K`:\>=].'ɀ]`'IJ^^^\^1^\`:J^4^4.)'IK灋^^^^^^K`:\>=^.'ˀ^'IJ_'_2_p_E_p`:J_H_H.)'IK聋__`_`_K`:\>=_.'̀_'IJ`5`@`s`N`s`:J`Q`Q.)'IK運``````K`:\>=`.'π`U'IJa!a,aT1a5aT`:Ja8a8.)'1IKꁋaaa1aaaK`:\>=a.'1a'IJabb@bb@`:Jbb.)'IK끋bubybbbbK`:\>=b.'рb'IJbcc&c c&`:Jc c .)'IK쁋cOcSccYccaK`:\>=cn.'cJ'IJccccc`:Jcc.)'IK큋dddVddVd%K`:\>=d2.'dH'IJd~dd{dd`:Jdd.)'{IKdde{dedK`:\>=d.'{e'IJeCeNe}eZe}`:Je]e].)'IKeeeeeeK`:\>=e.'Ӏe?'IJf*f5fffBff`:JfEfE.)'IKffffffK`:\>=f.'Հf'IJgg#gXg2gX`:Jg5g5.)'IKggggggK`:\>=g.'׀g'IJhh!hah5ha`:Jh8h8.)'IKhhhhhhK`:\>=h.'ـh4'IJi'i2iai>ia`:JiAiA.)'IKiiiiiiK`:\>=i.'ۀi'IJjjjJj&jJ`:Jj)j).)'IKjzj~jjjjK`:\>=j.'݀j'IJjjkBkk`:Jkk.)'BIKkCkGkBkKkkSK`:\>=k`.'Bkt)'IJkkkkk`:Jkk.)'IKkll@ll@lK`:\>=l.'ހl2'IJlflqllul`:Jlxlx.)'IKllllllK`:\>=l.'lw'IJmm(mOm0mO`:Jm3m3.)'IKmzm~mmmmK`:\>=m.'m'IJmmn)nn)`:Jn n .)'IKnXn\nngnnoK`:\>=n|.'n'IJnno#no#`:Jnn.)'IKoYo]oonoovK`:\>=o.'ol'IJoop/op`:Joo.)'IKpDpHp/pQppYK`:\>=pf.'p'IJppppp`:Jpp.)'IKq1q5qqBqqJK`:\>=qW.'qvú'IJqqqqq`:Jqq.)'IKrr rjr+rjr3K`:\>=r@.'r\a'IJrrrrr`:Jrr.)'IKsssbs sbs(K`:\>=s5.'sT'IJsssss`:Jss.)'IKtt!t|t4t|t<K`:\>=tI.'tnů'IJttttt`:Jtt.)'ILu3u7uuIuuQK`:\>=u^.'uV'IJuuvuv`:Juu.)'ILvKvOvvbvvjK`:\>=vw.'v'IJvvwAw +wA`:Jww.)'ILw~wwwwwK`:\>=w.'wǤ'IJxx!xRx.xR`:Jx1x1.)'ILxxxxxxK`:\>=x.'xK'IJyyyOy%yO`:Jy(y(.)'ILyyyyyyK`:\>=y.'y'IJzz$zfz9zf`:Jz<z<.)'ILzz{z{zK`:\>=z.'zə'IJ{6{A{}{S{}`:J{V{V.)'IL{{|{|{K`:\>={.'|@'IJ|@|K||Y|`:J|\|\.)'IL||}|}|K`:\>=|.'|'IJ}2}=}j}H}j`:J}K}K.)'IL}}}}}}K`:\>=}.'}ˎ'IJ~~~M~*~M`:J~-~-.)'IL ~|~~~~~K`:\>=~.'~5'IJX$X`:J--.)'IL +K`:\>=.''IJ-8yLy`:JOO.)'IL K`:\>=.'̓'IJLWl`:Juu.)'IL <<K`:\>=.'.*'IJv`:J.)'IL ff$K`:\>=1.'X'IJ`:J.)'ILd!d)K`:\>=6.'Vx'IJ `:J.)' +ILP PK`:\>=%.' +B'IJ `:J.)' IL^ ^ K`:\>=-.' P'IJ `:J.)'IL f !f)K`:\>=6.'Xm'IJ`:J.)'ILt.t6K`:\>=C.'f'IJ`:J.)'IL'+<DK`:\>=Q.'tһ'IJ`:J.)'IL"&t3t;K`:\>=H.'fb'IJ`:J.)'IL` `(K`:\>=5.'R 'IJ`:J.)'IL@@ +K`:\>=.'2԰'IJny`:J.)'IL  K`:\>=.'W'IJT_o`:Jrr.)'IL""K`:\>=.''IJVaq`:Jtt.)'IL$$K`:\>=.'֥'IJÁU`n`:Jqq.)'ILK`:\>=.'L'IJāMX k`:Jnn.)'!IL* *K`:\>=.'!'IJŁ`k"}`:J.)'#IL8"8K`:\>=.'#*ؚ'IJƁr}$`:J.)'%ILd$d"K`:\>=/.'%VA'IJǁ&`:J.)''ILx&1x9K`:\>=F.''j'IJȁ(`:J.)')IL/3(EMK`:\>=Z.')~ڏ'IJɁ`:J.)'IL >>K`:\>=.'06'IJʁmx*`:J.)'+IL!$*$K`:\>=.'+'IJˁYd,u`:Jxx.)'-IL",,,K`:\>=.'-܄'IJ́Xcm`:Jpp.)'IL#K`:\>=.'+'IJ́5@w.Pw`:JSS.)'/IL$.K`:\>=.'/'IJ΁5@z0Qz`:JTT.)'1IL%0K`:\>=.'1y'IJρ=H2Y`:J\\.)'3IL&2K`:\>=.'3 'IJЁEP4a`:Jdd.)'5IL'4K`:\>=.'5 +'IJсJU6d`:Jgg.)'7IL(6K`:\>=.'7n'IJҁ;0> <e p ' ͣ0`:J.)'>IL)[d> \  ' 'd/K`:\>=<.'>V'IJӁ8`:J.)'9IL* b8b'K`:\>=4.'9TR'IJԁ:`:J.)';IL+r:,r4K`:\>=A.';d'IJՁ<`:J.)'=IL,&*<<DK`:\>=Q.'=t'IJց>`:J.)'?IL-W[>s{K`:\>=.'?G'IJׁ))`:J  .)'@IL.X\goK`:\>=|.'@'IJ؁A`:J.)'BIL/BFARZK`:\>=g.'B'IJفC`:J.)'DIL0"fC*f2K`:\>=?.'DX<'IJځE`:J.)'FIL1FEFK`:\>=.'F8'IJہtG`:J.)'HIL2&G&K`:\>=.'H'IJ܁R]If`:Jii.)'JIL3IK`:\>=.'J1'IJ݁+6i Di`:JGG.)'KIL4 K`:\>=.'K'IJށ$P"/P`:J22.)'"IL5}"K`:\>=.'"'IJ߁.$ .`:J.)'LIL6\`$jrK`:\>=.'L&'IJM`:J.)'MIL7)-lM3l;K`:\>=H.'M^'IJ။`:J.)'IL8**K`:\>=.'t'IJ⁋XcNn`:Jqq.)'OIL9 +N +K`:\>=.'O'IJか7BmPLm`:JOO.)'QIL:PK`:\>=.'Q'IJ䁋M&*M`:J--.)'RIL;|&K`:\>=.'Ri'IJ偋*S +*`:J  .)'TIL<VZSbjK`:\>=w.'T'IJ恋U`:J.)'VIL=*.rU6r>K`:\>=K.'Vd'IJ灋W`:J.)'XIL> +XWX!K`:\>=..'XJ^'IJ聋Y`:J.)'ZIL?>Y>K`:\>=.'Z0'IJ運hs(z`:J}}.)'[IL@(K`:\>=.'['IJꁋ-8X\=X`:J@@.)'\ILA\K`:\>=.'\S'I;{ }$nrc +gX\MQBF7;, 0 z !!!~!"%"o"##s#$$d$% %h%&&Y&'']'((N(()R))*C**+G++,8,,-<--.-../1/{/0"001&1p122t233e34 4i455Z566^677O778S889D99:H::;9;;<=<<=.==>2>|>?#??@'@q@AAuABBfBC CjCDD[DEE_EFFPFFGTGGHEHHIIIIJ:JJK>KKL/LLM3M}MN$NNO(OrOPPvPQQgQRRkRSS\STT`TUUQUUVUVVWFWWXJXXY;YYZ?ZZ[0[[\4\~\]%]]^)^s^__w_``h`aalabb]bccacddRddeVeefGffgKggh<hhi@iij1jjk5kkl&llm*mtmnnxnooioppmpqq^qrrbrs sSsstWttuHuuvLvvw=wwxAxxy2yyz6zz{'{{|+|u|}}y}~ ~j~n_c +TXIM>B37(,vz!ko`d UYJN?C48)-w{"lpae VZKO@D59*.x|#mqb f W[LPAE6:+/y }$nrc +gX\MQBŸFÐ7Ĕ;Ņ,Ɖ0z!~%osʽd h̲YͶ]ΧNϫRМCѠGґ8ӕ<Ԇ-Պ1{"&ptپe i۳Zܷ^ݨOެSߝD6(,vz!ko`d UYJN?C48)LD] '^`GLFla`:+LG `G+LJ`pB(``LD>=01;'LKy_ z'``d>LM 5 J'6 j'7],`G+LN a`G+LO b ¡'6 '7],`G+LRDpB D`LK>=0'LTXc "'%X-d`:>`:J`+`LU]b~8 "'l~q`\LV9 "':`:`+`LWe "'`\nTLXf 'g`L[2:pBI`LX>=0R\'L]y "'`:^`:`DL^wh 'i`G6La$,upB=u`L^>=0FP'LbRyFj S'k`Ld@l`+Lg6pB6`Lb>=0'%qLh!Dm "'n`LXLjv l`+Lkĉ (`+LnpB`Lh>=0'Louu7o],`Lb+`Lh>ISkWR(+>J|•Lr?I¬%ŀ±R],`Lb>JLsR],`Lb?=01;'GLryÒBÛ`LhJçç`Lh'm'pLsf1Bfo[`LhJ`Lh'm'qRLtĔĪr "'ĺĿ``LbLus "'`N)U?Lv}t ʢ'u`LbLxN`G+Lyd!`G+Lzz"`G+L}RZƢpBjƢ`Lv>=0s}'L~ƧƯaƽa`G!`G"`G+`Lv>I""%  +Z`G%&$K`G?=i(+>JPfLpK`GsZ`G?Iǁ""%Ljdži`G%ǪǨZ`G%̀K`G>JL K`G Z`Gi`G?=0''GLe{BȄȅ[Ȉ![`LvJȔȔ`Lv't'vˁL91B9[!["[`LvJ`Lv't'w1D4O7Z"LXv1x Y'y`GL `:+L`:+L*K`+L%pB%`L>=0'L*2ˋ>ˋCK`Q`:`L>J]qL{˂LˏˣBˬ˭K[˴[`LJÜ`L'x'z ! ,2~ lL .'{  '|`LXL (`+L͙͑pBͫ`L>=0ʹ;'L%} "'%``  + +_L-2~ '`L g`L+L( `:+LϗϟpBϺ`L>=0' + L . '`GL `G+LъђpBѣ`L>=0ѬѶ' n LԎ ݢ'`GKLԉ `:+LaiӳpB{ӳ`L>=0ӄӎ'LӸ  `:`L>JL L)wB2w3[`LJAA`L''s   [  L(O0 )'`L׵׽ pB `L>=0'L$K`:1`C\][[[+\>IS!_W (+>Nt~[؀pH؟ =د.Bع ׁؿ ,LJ?=.B ׁ LJL!:fB "' "'CfDK[J[W\[\Ljك٦B k' "'ٌ٦ٍK[ٓ[\L٫ٲ "'ٵٽK`:`L..K`:][JB[[''.( a z0L6SG 7'`RLB r'[+L B ᄡ' ᘡ'[+L`:`)`)/`+`L>NPRl`L&P]TBB'N`L=܁LB܏3LI1"""%<53],[%NG3][[[%_X3`:%sl3`>K>=ݑ3ݚpB3=ׄLB#3L[p[>=,*LB=CN#+L>=~|LBޏޕޠ#+LJ޾LLÁ11[>I!.BL(+>J.BL?J&.BLL6>GpBKGS`:^.][[[+`L>It!߆x(+>Nߛ߫/[߭pHJL?J!4L>LȁK^Bgh[n.[`LJ`L''LɁ!1B![`LJ`L'' LŁ&2B:[JCCpCr.BLLʁEB ʡ' "'E`:`+#`+6`+\eCLˁ"D` #'`CLс66^J^\? UC L΁pB`L>=0'Lρ`LJ`L''pB'RLҁ;\ <'`CLԁK`:+Lف\? C LׁpB`L>=0'0LځR ̣  #E' Pr {'`CL܁I \ ' '],`[+L䁋EEp\p\? gC L߁PpBP`L>=0!+'LU]l`LJr&r{rB'N,`LL⁋`JR'*vL偋-K  .'`L灋`:+L聋`:+L運 u ' ۡ'],`SP+Lꁋ' `M+L끋D :],`:+LpB`L>=0'L;;`L>J,LL?SB\`LJbb`L''LNSt "'\te`:+\Ly6 "'`:`:L "'`:`:\L  "' q`P`!`\D!k$L + '`L G`:+L `:+LkspB`L>=0'L "'`SPM +  ' )K Vx "'`Ry-Mx  y'`Mh (`+M YpB!Y`M>=0*4'Ms "'[`:+`LM  ' "'`:`:`LM +!: ' "'(:.`SP`LM ?DR  "'IR\M Wh~ "'l~q``LM  "'`\M  ``L>Jڜ`L''N.!FA V  !!M '`iWM]l`Y l`Y'M`M"` +M7?pB[`M>=0dn'M49Gw "'>G\MLQ\e[|],`+\>I!"(+>N[pB"=.B#0"MJ ?N6@[BpBl"=z.B#MJMB ' "'[],`\M;B ' "'+;,[\M@HB A' f  "'H`B` ^`SB\+2^`NSB\+\MM N' w ƣ "'`B``j9M  ' Jl w "'`:`jsMoB ' 3 >` "'`:^`RyB\^`NSB\+\M"C\f]y`YJiviM.l"=""#$4$%N%&U' '_ +M#b c'`M%\`M&`M)FpBF`M#>=0!'M+ "'`^``|}B\+^`NSB\+\M,! "'-2`C`p^`zB\+^`NSB\+\'(9()QM- q '`M0$tpB<t`M->=0EO'M2y~ "'^``|}B\^`NSB\+\M3 o "' o ` /^`zB\+ Y^`NSB\+\))*Y*M4 +L +o s  +M'``bM6 2 `+M7 N `:+M8 g s`:+M; + + #pB + #`M4>=0 + +'+e+M< N '  O q  z  '`CM>!`+MFjj\? C MA ' / wpB ? w`M<>=0 H R'MB |    `M<J &   B'N,`M<MD`JR',c,- -RMG# '`MI ]`+MJ ],[+MK `:+MNpB`MG>=0'MO`MG>JMRMR#:}BC}`MGJOO`MG''-.-.r.MSH '`MU" ]`+MV= ],[+MY+3ypBAy`MS>=0JT'MZ~`MS>JM]M] B `MSJ圣`MS''/;//0M^#A $'`M` ]`+Ma ],[+Mb `:+MepB`M^>=0'Mf11`M^>J"MiMi5IBR`M^JXX`M^''001=1Mj '`Ml `+Mm !`+Mn "`+Mq:BpBV`Mj>=0_i'22cMr9 '`RMt `Mj+Mu `Mj+Mv `+Mw+ `M+Mz"mpB5m`Mr>=0>H'M{rz`:.][[[+`Mr>I!Ɓ3(+>N/[pH 3J";M~E3rK3?JgM3rM~#B#[.[`MrJҜ`Mr''ۀ4R4]M'@1BIJ[`MrJYY`Mr''܀423I4$45M<! '`RM!i `+M! `+M! `+M! `+MpB`M>=0'M * * `:+.][[[+`M>IA!SE6,(+>Nhx/[zpH6,JM66i?J M !6M . L B U  V[ \.[`MJ n n`M'' 6 7M  !Y1B!!Y![`MJ!!`M''!T7v5567H7M""# "'`M#s `+M# `+M# `+M###dpB#,#d`M>=0#5#?'8:8M$|$& $} + $'`CM&<`+M&L`:+M& & &2&&2\? &)C M% %%XpB% %X`M>=0%)%3'M&\&a&w "'&f&&o`:+\M&&& "'&&\M&&& "'&&\96999:6M'':L ''`RyM(()E()E(`:(`*]`Ry>J((.B):\2)[[')')6:MM)J)Z))f)`M>N))`M).BM=)?');FJ));FM******`:]`Ry>J**.B*;MM++,PK+,P+`:+`*]`Ry>J,, .B,<&\2,#[[')',A<6MM---R-%-R--`:]`Ry>J-9-@.B-I<MM---pB--`M>=0--'M-..$B -' "'..$`MM.)..0B.<0.D`:.U\][[[+.s^`RyB\+.^`NSB\+\>I.!..=(+>N..[.pH/==/.B/"=/(>@/3=߃/D=MJ/Z?I/l!//p=(+>N//[/pH/==/.B/=/>ł/=MJ0 +?I0!0(0 =(+>N0=0G[0IpH0h==0x.B0=0?AMJ0?=0.B0=MJ0M001gB 0ߡ' "'1 1g1[1\[1,^`RyB\1R^`NSB\\M1k11B 1l' "'111[1\[1^`RyB\\M112B 1ա' "'222[2 +\[\M22<2YB 2' "'2L2Y2M[\M2^23B 2_'232`:2\][[[+]`Ry>N22]`Ry2ʦ`Ry=2.B2A2A433303K`Ry`>=33At3#BB432323g33S`N`>=3L3BAj3ZBMJ3n33uAuM336%B36%3`:3\][[[+3^`RyB\+3^`NSB\+\>I4!4!4CL(+>N464@[4BpH4aC=4q.B4}C 4C4C.4CLMJ4?I4!4ۂ4C.(+>N44[4pH5C=5+.B57C 5=D5HC.MJ5`?I5r!5~5vC(+>N55[5pH5C=5.B5C 5DMJ5?=6.B6C MJ6M6*6D6B 6+' "'6O66P[6V\[6n^`RyB\6^`NSB\\M667B 6' "'676[6\[6^`RyB\\M7 7&7GB 7 ' "'717G72[78\[\M7K7e7}B 7L' "'7p7}7q[\M778B 7'787`:7\][[[+]`Ry>N77]`Ry7`Ry=7.B8G8 G4888o8K`Ry`>=8%?'8AG=8Y8OG5t8bG48q8q88rS`N`>=88G5j8GMJ888G5uM889NB 8Ρ' "'99N9^B\98^`NSB\+\M9S9y:J 9T'9:J][>N99][9[=9.B4999`>=99It499:(9S`N`>=: :Ij:IyMJ:/:@:6Iu:;;;<<=C=?@N@A'A{BEEFFvFHFHIM;';H= ;('`M;;;pB;;`M>=0;;'MÁ;<N<<]],`Ry<],`Ry=<.B4<<=)<K],[`>=<<Kft= +0`Ry=K4=+=+=`=,S`N`>==E=;Kfj=SLMJ=h=y=oKfuJWJK(LmMŁAmAC An'`CMˁCcCcCCuC\? CC MȁAAB4pBAB4`M>=0BB'MɁB9BABBKB`MJBQBQ`M''BB'SLM8MḾEE E'`[+M΁F]l`R Fl`R'MρG]l`R G5l`R'MЁHa]l`R Hl`R'MсI ]l`a Jl`a' +MҁKT ]l`R Kwl`R' MӁL6 `:+MՁLe_B LH's`C+M灋L| e`:+M聋L=`:+M運L `a+MցM B M' M(' ME' Mb' M'[+MꁋM `P+M끋M `:+M쁋N `+MׁNB B N'`U9+M큋NW C`+MNz =`N+M؁N B N'`:+MN `:+MفO B Nߡ'`:+MO8 "`:+MځOj B OH'`:+MO `v+MO`P+MO `P+MہPB O١'`:+MP* `:+MPO `N+M܁Pv B P]'`:+M݁P !B P'"`:+MށQM #B P'$ PQ QQ5`P+M߁Q %B Qk'& QQ QQߣ`+MR 'B R'( R,RN RYR{`+M။S, )B R'* RƣR RS`:+Md +`P+Md- ,`P+MdQ -`P+M⁋d .B di'/ d'0 d'1],`d>+Me 2`S+Mかe 3B e'4`+M䁋ff .B f'L f' f9'],`[+M偋f 5B fu'6`P+M恋f 7B f'8`P+{MFF!FcpBF+Fc`M>=0F4F>'MKKKKK`M>JKKNNKKL$BKL$`MJLL`M''9N/LLM +LM +`lJLLBL.BMNSGSLSg: "'SUSgS[`[`[NSlSS;B Sm'< "'SSS`S!```NSSS= "'SS`NzNSTTm>B S' "'T'TmT/?`:TL@[+`PNTrTTAB Ts'B "'TTTZ`:T`:T@[+`PNUUUDB U'C "'U+UDU3D`:`RNUIUOUcE "'UZUc``NUhUUFB Ui'G "'UUU`:`dNUUZHBUZ  U`hUc`RU`UI`V +J`VK`V"L`V6`+VC`+VPM`+Vcb`+`e>IVq!V{VuY< +(+>NVVN`RVBVXJVV.OB VXVYx VXVXЄWX߅W XWXW'Y W0YW9Y, WHY< +N?IWZ!WlW^Y, (+>NWWN`RWBWXJWW.PB + +WXWZI WXWXЄWX߅WXXXXY X!YX*Y, N?IXD!XPXHY(+>NXeXnN`RXpBXXJXX.QB XXX[ XXXXЄXX߅XXXXXY YYN ?IY!Y%YY (+>NY:YCN`RYEBYfXJYuY|.RBYXY[ YXYXЄYX߅YXYXYY N +?NYYN`RYBZXJZ#Z*.SBZBXZH\V ZRXZ^XЄZeX߅ZlXZuXN NZZ[)OB Z'T "'Z[) Z`hZc[Z[ZI[ZJ[ZK[ZL[Z[[[[ M[[b[`eN[-[L[PB [.'T "'[Z[ + + +[b`h[hc[[p[[|I[[J[[K[[L[[[[[[M[`eN [[\ZQB [Ρ'T "'[\Z \`h\c[\[\I[\#J[\*K[\9L[\B[\K[`eN +\^\}\RB \_'T "'\\\`h\c[\[\I[\J[\K[\L[\[`eN \]]bSB \'T "']]b]"`h](c[]0[]<I[]CJ[]JK[]SL[`eN ]g]]UB ]h'V "']]]W`e`eN]]]X "']]]Y`:]Z`+]K`:+`N^^ ^ [ "'^^ \N^%^*^B\ "'^9^B\N^G^W^m] "'^d^m],`CN^r^^^ ^s'_ ^'_ "'^^^``:],`[N^_U_a ^'_ _%'_ "'_f__nb`:],`[N__` +c _'_ _'_ "'_` +_d`:],`[N ```=e "'``=`$`[`0f`+`[N!`B`G`sg "'`Z`s`bY`:`N"`x`}`h "'```Y`:`N#```i "'```Y`:`N$``aj "'`aaY`:`N%aa"aLk "'a3aLa;Y`:`:N&aQaZbDlajbDar`:a}\][[[+`>Ia!aae(+>Naa[apHaeJaa.mBbe b +eWN ?Jb b'.nBb;e NN bIbobmB bJ'o "'bbb[b\[`NbbbnB b'o "'bbb[`NbchcpB b'q c +c, c7cY "'c}c\N'cccr "'cccs`:`PNdee6tB d'u "'e!e6e&`e-!``PN(e;eIeov "'eZeoe_`ef!`],`PN)iiiw "'iiix`:`PNij j5yB i'z iӡ' i' "'jj5j$x`:],`[N0jujjjj]y`RJjjjQ.lN1jk kB{kkB]y`RJkk3k#Q.lN2kkk|kk]y`RJkkkQ.lN3ll%l^}l3l^]y`RJl6lOl>Q.lN4lllll]y`RJlllQ.lN5llm"~lm"]y`RJlmmQ.lN6m'm9m~mJm~]y`RJmSmom[Q.lN7mmnmn]y`RJmmmQ.lN8n@nWnn_n]y`ZJnbnunjQ.lN9nno no ]y`ZJnooQ.lN:o_ozooo]y`FJoooQ.lN;oop'pp']y`FJpppQ.lN<pmpppp]y`RJpppQ.lN=pqq9qq9]y`ZJqq*q Q .lN>q{qqqq]y`ZJqqqQ!.lN?rrrSr*rS]y`ZJr-rDr5Q".lN@rrrrr]y`ZJrrrQ#.lNAs&s=spsHsp]y`ZJsKsasSQ$.lNBsstst]y`ZJsssQ%.lNCt?tVtt]t]y`ZJt`trthQ&.lNDttttt]y`RJtttQ'.lNEttu%tu%]y`RJuuu Q(.lNFu*u<uiuDui]y`RJuGuZuOQ).lNGuuubuu]y`RJuuuQ*.lNHv(v:vgvBvg]y`RJvEvXvMQ+.lNIvvvvv]y`RJvvvQ,.lNJw(w:wkwDwk]y`RJwGw\wOQ-.lNKwwwww]y`WJwwwQ..lNLx;xUxx`x]y`WJxcxyxkQ/.lNMxxyxy]y`WJxyxQ0.lNNyNy`yygy]y`RJyjy|yrQ1.lNOyyyyy]y`RJyyyQ2.lNPyyz5zz5]y`RJz +z&zQ3.lNQzyzzzz]y`ZJzzzQ4.lNR{ +{!{^{.{^]y`ZJ{7{O{?Q5.lNS{{{{{]y`ZJ{{{Q6.lNT|;|R||^|]y`ZJ|a|x|iQ7.lNU||}|}]y`ZJ|}|Q8.lNV}X}o}}{}]y`ZJ}~}}Q9.lNW}}~.~~.]y`ZJ~ +~~Q:.lNX~s~~~~]y`gJ~~~P.lNY"O*O]y`FJ-@5Q;.lNZTfTn]y`RJqyQ<.lN[]y`RJQ=.lN\]y`RJQ>.lN]"4wHw]y`RJQhQMέ.lN^|]y`RJMϭ.lN_]y`RJQ?.lN`bt]y`RJMЭ.lNa. .]y`RJ Q@.lNb3EtNt]y`RJQeYQA.lNc]y`RJQB.lNd7IxRx]y`RJUi]QC.lNeB B]y`aJ3Mѭ.lNfGYb]y`RJeymQD.lNg]y`RJQE.lNh#R,R]y`RJ/C7QF.lNi]y`RJMҭ.lNj-?xMx]y`RJPiXQG.lNk}]y`RJQH.lNlBB]y`RJ3'QI.lNmGYc]y`RJf{nQJ.lNn]y`RJQK.lNo5tCt]y`eJLeTQL.lNp]y`eJQM.lNqE\h]y`eJksQP.lNr**]y`eJ QQ.lNs/A|P|]y`RJSm[QR.lNt]y`RJQS.lNu!j4j]y`RJ=[EQT.lNv  ]y`RJQU.lN*bqz`P`Px`:]PI_JP_.yBRNNw:C[`>Jah`'g'.Nx~`J.NwN+$o3;`:E`g`:+\>=z.le2[['@t'N&N,  ܢ-5`:F`:+`P>J\&\#rd(+B.BN.>BN[`PNB`:[J[''.NBZ`:`:[Jʜ[''..=N-!)+B8+@Z`:U`:r`:+`P>J&#(+B.BN.AB +N[`PN0=BPVL`[k`+ `\ +`\J`\''.NBL`[4`+K `\ +`f-J]]`f-''.&5ENyW" ã  @'g`:Jjj`:'9$''....T}TUU_UUVhVW WWXXu\]^b__`]`a#aZaab>bccpcddNddef-ffg<ghhPhi"ivijjrjkknklljlmmfmnnbno +o^oppZpqqUqqrQrrsMsstIttuEuuvAvvw=wwx9xxy5yyz1zz{-{{|)|}|}%}y}~!~u~q;z\${Nz '`[`\D`]N}qB Q'],`P+N~ 3B á'4`+N/ 5B '6`P+Nr 7B G'8`P+Nmu`NzJB=NN`:`p+`p +`Nz>J$94+BsUHvсa҂{R6N`:`p+`p +`Nz>J +)v8 сW0҂q@vN.B`UlJ0!'NL],`P>I.BN}(+>=.Bq .N}?J.BN}NL%4K],`P\>N ],`PNL],`P.LN=т C=<Nz`P`Px`:]PI_JP_.yBNN)`:>N57l`M=M=QO ].)\\Joxv QNK`:\>=.NN`:`p+`p +\>=?9.[ C=L.a\SBsUpс҂R6\N(-j7j?`:\>=P.[d`\N +`:%`p+B`p +\>=].hN~#с3҂C\N SpBS`Nz>=0$.'Nxr "'s`:`PNJRxw "'_xgx`:`PN}yB ~'z ' ' "'x`:],`[L~So*tN ܢ'`N +`P+N ,`P+N -`P+N / +'0 N'1],`d>+NfnpB`N>=0'Nu "'`!``PNv "'`!`],`PN "'`b 4'N '`DNpB`N>=0'N\][[[+`N>I! (+>N(2[4pHSJc{N"?JNN4B4\[`NJ`N''݀,N8P1BY`NJee`N''qv+Nr s'`N `:+N K`:+N/pB/`N>=0 +'N4<DLK`:Z`:+`N>Ij!vn#(+B>JN#?JNNFBFK[[`NJ`N''8́>NJZ1BcdK[`NJmm`N''DzN  + '`N`:'N8`:'N{`:'N`:'N`:'NI`:'N|`:'NÁ`:'Nā`:'NŁ `:'NƁi`:'Nǁ`:'Nȁ`:'NɁ`:'NʁG`:'Nˁw`:'Ń`:'Ń`:'N΁`:'NρI `:' +NЁ `:' Nс + `:'Nҁ `:+Nԁ'2 K7 `:>NAK[M['9'.I"p=('J'?I"p̀=('J'?J&=`:NׁHPpB^`N>=0gq'NفA`:Jɜ`:'9'. +,yNځ Ƣ'`N݁JRpBe`N>=0nx'N߁  "' Z`:`:`jE`iNw "'1w@`:V`:g`:`jEN။| }' "'`:+`U}N⁋ "'` q2mNか ͢'`N恋BJpBW`N>=0`j'N聋 "'K`+`PN運դ '`O5EN쁋YpB!Y`N>=0*4'N큋^fox`+`N>I!(+>JN?JNN<B < +[`NJ`N''7N@Q‚1BZ‚`NJ```N'' O¢ª=¬`J¯¯`''!.O=K`\>=ᜣ['7'".O '/Jr1J`J44`''#.O OSÌrTÌYK`\>=f['7'$.ÂEO +ìô_ö`Jùù`''%.O!_K`\>=뜣['7'&.O 19T;T`J>>`'''.O"Y]Ė^ĖcK`\>=p['7'(.ČO Ķľl`JÜ`'').O#lK`\>=['7'*.<O ;C^E^`JHH`''+.O$cgŠhŠmK`\>=z['7',.ŖO-`JϜ`''..O%---K`\>=['7'/.#OMUt0Yt`J\\`''1.O&y}ƺ0ƀƺƅK`\>=ƒ['7'2.ư7O9`J霣`''3.O' +G9 GK`\>=['7'4.=Ogoǎ;sǎ`Jvv`''5.O(ǓǗ;ǚǟK`\>=Ǭ['7'6.O>`J`''7.O) $a>'a,K`\>=9['7'8.W2OȁȉȨ9ȍȨ`JȐȐ`'':.O*ȭȱ9ȴȹK`\>=Ɯ['7';.O5<5`J`''=.O+:>{<A{FK`\>=S['7'>.qOɛɣ?ɧ`Jɪɪ`''@.O,?K`\>=['7'A.-O(0OB4O`J77`''C.O-TXʕB[ʕ`K`\>=m['7'D.ʋOʵʽE`JĜ`''F.O."E"K`\>=['7'G.OBJiHNi`JQQ`''I.O/nr˯Hu˯zK`\>=ˇ['7'J.˥(OK`Jޜ`''L.O0<K<K`\>=['7'M.2O\d̃Nh̃`Jkk`''O.O1̈̌N̏̔K`\>=̡['7'P.̿zOQ`J`''R.O2VQV!K`\>=.['7'S.L#Ov~͝T͂͝`Jͅͅ`''U.O3ͦ͢TͩͮK`\>=ͻ['7'V.O *W*`J`''X.O4/3pW6p;K`\>=H['7'Y.fuNuΆβZ "'ΖβΣ[```NNη\ "']`i`NN +^s][[[+`N>I(!2,`(+>NGO_[QpHp`J~υNϓ?JϧϮNN +`B ǡ'^ "' +s[`NN7MaB '^ "'DM`NNR\ob "'fo`NNt~;cЊ;Аs][[[+`N>IО!ШТ(+>Nн_[pHJ.dB 8N?J&.eBNN@dсdB A'c "'sсts[`NNхѩeB ц'c "'Ѹ`NNҖfҖs][[[+`N>I!i(+>N_[pH;iJIP.gBcN?Jw~.hBNNқgB Ҝ'f "'s[`NN (hB 'f "'(`NN-7si "'JsP`+W!`+^"`+el`+`NNxӂӭj "'ӖӭӜ`+ӣ!`+`NOӲӼk "'l`+m`+n`+`NOHo "'H `+p`+%q`+2r`+`NOMWs "'`mt`+u`+ԑv`+ԣp`+Զq`+r`+`NOw "'x`:`NO"<y "'+<1U`+`NOAKez "'TeZV`+`NOjtբ{ "'ՁբՇ`+Տ|`+՗}`+`Np&svkmd h_c Z^UYPTK6I?`(iNOEO5֢M~ ր'`4O8 WpBW`O5>=0(2'O9\du~`+`O5>I׋!ה׏(+>Jץ׾O<?JO=O<pB'p([`O5J77`O5'~'kO=t؍1Bؖ`O5Jآآ`O5'~'OW=`J朣`''!.OX $r $`J`''#.OY)1L_3L`J66`''%.OZQYt[t`J^^`'''.O[yفٜlكٜ`Jنن`'').O\١٩٫`Jٮٮ`''+.O]l`Jڜ`'g'.O^0 0`J`'g'.O_5=\-A\`JDD`''..O`aiڈ0mڈ`Jpp`''1.Oaڍڕڴ9ڙڴ`Jڜڜ`''3.Obڹ;`JȜ`''5.Oc > `J`''7.Od898`J  `'':.Oe=Ed<Id`JLL`''=.Ofiqې?uې`Jxx`''@.Ogە۝ۼBۡۼ`Jۤۤ`''C.OhE`JМ`''F.OiH`J`''I.Oj!@K%@`J((`''L.OkEMlNQl`JTT`''O.OlqyܘQ}ܘ`J܀܀`''R.OmܝܥTܩ`Jܬܬ`''U.OnW`J؜`''X.OD  "' `NOE* "'!*`NOF/HtZ "'Xte[```O5OGyݒݾ\ "'ݢݾݯ]`i`O5OHޓ^ޓs][[[+`O5>I!¬(+>N!_[#pHB¬JPWO>e?JyހO?O>ޘ`B ޙ'^ "'s[`O5O?/aB '^ "'&/`O5OI4>N "'EN`NOJS]eks][[[+`N>Iy!߃}G(+>Nߘߠ_[ߢpHGJ.BĄO@?J.BOAO@3LB ' "'>L?s[`NOAPpB Q' "'{`NOKk "'l`+m`+n`+`NOL "'`+!`+"`+l`+`NOM = "'&=,`+3!`+`NONBL "'Q^t`+pu`+v`+p`+q`+r`+`NOO "'`+p`+q`+ r`+`NOP *@ "'/@5U`+`NOQEOe "'TeZV`+`NORjv "'``OS "'`iOT][[[+`Ox>I!(+>N [pH-J;B.BTQOB?Jho.BOCOBB ㌡' "'[`OxOCB ԡ' "' `OxOU!Ks "'*K0`+8|`+@}`+`Ny/|eN8"p ZD.|:‚=Õ>ŋqg-xȱɳ X4Oo(C )'`OrpB`Oo>=0'Os''`Oo>JOvOv+<mBEm`OoJKK`Oo''Owr{ "'`:`:`M\̭OxW 爢'`OO{IpBI`Ox>=0$'O|NV^d`+k!`+r"`+y`+`Ox>I!艃(+>JOŁՂ?I!т(+>JOŁՂ?I!(+>J'7OAŁD?IR!XV(+>JiyO?JOOB[!["[[`OxJ㜣`Ox'' yτϏϚO*t1B3t4[7![:"[`OxJFF`Ox''lo%r0OxB[![`OxJꛜ`Ox''ЧвO B [`OxJ蜣`Ox'' + O OB)O`OxJ//`Ox''O`J뷜`'g'O55`J`''.O:>w?wDK`\>=Q['7'.mmO`J줜`''.OK`\>=֜['7'.O$?!&?`J))`''.ODH!INK`\>=[['7'.wӿO"`J`''.O"K`\>=['7'.hO $*s][[[+`Ox>I8!B<(+>NW__[apHJO?JOOB ա' "'s[`OxO@UB ' "'LU`OxP͜KyWѨCҞGӕ>ԙTլO2T: 3'`OpB`O>=0'O $*`+1!`+8"`+?`+`O>II!OM"(+>J`xO"?I!(+>JO?I!(+>JO"?I0!64(+>JG_Oi?JwOOB[!["[[`OJٜ`O''ئرؼO 81BAB[E![H"[`OJTT`O''GR]OB[![`OJǜ`O''ԁOfB%f&[`OJ22`O''dMOjB`OJ`O''O`Jٜ`''.O`J`''.O$?!&?`J))`''.ODLg"Ng`JQQ`''.Ol88s][[[+`O>I!7(+>N_[pH7JO t?J&OO=lB >' "'xys[`OOB ' "'`OOR][[[+`Ox>I! ݗ(+>N )[+pHJݗJY`.BsO?J.BOOB ' "'R[`OxO8B ' "'/8`Ox}x٦ڄ#qۿ  m6ގO. '`O `Ox+O6 `Ox+OL `Ox+Ob `Ox+OpB`O>=0'Ohh][[[+][[[+][[[+][[[+`O>I !a(+>N(-[/pHN(N]b[dpH;N[pHNN[pHaJOÆ# ?I4!;8N(+>NPU[WpHv(N[pH;N[pHNJOኅ +ᯆ?I!!(%;(+>N=B[DpHc(Nrw[ypH;JOHm?I!ڀ((+>N[pH(J /O9?JJYOOl{B[[[[`OJ`O''ŀZep{O41B4[[[`OJ`O''ƀ)-1O8GBPQ[U[`OJ\\`O''ǀ~䈁OB[`OJ`O''ȀO B `OJ`O''Oix))s][[[+`O>I!(+>N_[pHJO?JOO.SlB /' "'^l_s[`OOpB q' "'`OOnns][[[+`O>I!(+>N_[pH!J/6OBP?JV]OOsB t' "'s[`OOB ' "'`OO "']`߳,Z8DIO$$`]]`O$$`O]mj]`,OÁ  '`O],]`]]` +OƁDpB D`O>=0'OȁIQv(Xv`J[[`'t'h.Ó{LL`]`>I`'g'ՀEEE.(O=0 E.?J$]`''N.BEO΁Q_bg`x K]`\>=0'Oҁ"y((y-K`\>=0:D'OɁ~  ]`>I.(Oȃw>J]`''z.?=0('Oʁ$]`>N.2V`9.(OIEMIpw>JZa]`''N.py?=0('Oˁ]`>NV`.(OI7(>J ]`''z.?I;C?7(=0IS('?=0r|('Oρ`]`J. +OOЁ   "'   `]`R8B +OӁ  +  '`]`OՁ + + +A + +`:>J +$ +' +.zO' +.O'w +.O' +.OOց + + ( +  +s[`>I !%  ]`J !*?J 3""" ? :.zO( H Bz \ X.O( e _ z t.O(  }  .O(  O恋   !z  !`J  jp  .zOz  .Oz  .Oz  .OzOׁ 8 B N Y s]`]`>N j m` oi` s.zO  yWzN  ` h`  .zOW .O   WzW  WI  ́ xv >N  ` i` .O  WN`h` .OW.O$ WW,&WI<C@\vF>JT_`ixm\tqyvx}zy\??J+O؁s]``>J""".zOv-("܇zW5/܈QLF܇z׃vYT.zOW[.Opl.Ov}ysܗWܫܗ؃v.OW.OOفa&a1 s]`]`>NBH{`Ji`XS.zOW_.OqlfVzWysVN9`i`.OW.OVWVNz`ټh`.zOVzN`h` .OVJ"-`7m=HBwyJmWPyYOځ]``>J""".zOvz +.zOW .O^"zW,$A=.OvLDh_[.OWa.O^wskWyOہ]``>J"""^".zO<:2vD?.zOWF.Oa_W!^d.O}{s!v.OW.OO灋]`J`.zO.OO聋  ]`J漲`.zOW.O .OO運i'i]`J04`D?.zOWK.O[W.OWb.OOꁋmw]`J`.zO.OW.OO?pB?`O>=0'ODL[a`+h!`+o`+z`+`O>I!(+>JOu?I!(+>JO"u%(?I:!@>(+>JQhOruu?I!u(+>JOu?JOO݁ +}B}[![[![`OJ,,`O''܀i)l4o?vJOށ1B[![[`OJ`O''݀ʁՂO߁cBc[ ![`OJ,,`O''ހ^WabOg~B[`OJ`O''߀O။$B$`OJ`O''O끋)1V98V`J;;`''.O쁋[cj`Jmm`''.O큋z`J`''.O{`J̜`''.O`J`''.OB%B`J((`''.OGOjQj`JTT`''.Oow!y`J||`''.O䁋__s][[[+`O>I!Ԁ(+>N_[pHJ 'O3/?JGNOO⁋dB e' "'s[`OOかB ' "'`Os-,X oL)XB,z(O`]`:O`O]mj`:O" ΢'`O]`:],`: +OpB`O>=0'OB($B`J''`'t'h.PGWY^``:>Iko`'g'Հ.(O=0.?J휣`:'9'N.P%(-`; K`:\>=0HR'P 6( 6K`\>=0 'O ; F  L `:>I R b [.(Ow>J o v`:'9'z.?=0  ('P  !k !k`:>N  V` .(OI ! (w>J!!`:'9'N.!4!0(y?=0!D!N('P!p!{"N!"N`:>N!!V`!.(OI!!!(>J!!`:'9'z.?I!!!(=0!!('?=0""'('P"S"Z"}"c"}"h``:J"r"v."w PP""" "'"""``:Rj   +4 +P ##$ #'`P $$ $fpB$.$f`P >=0$7$A'P$k$p$B "'$z$$K`:\P$$$B "'$$$K`:$K`:\P$$$ "'$$$K`:`: + + )  P%%' %Ƣ'`P& (`+P&K`:+P&@&H&pB&V&`P>=0&_&i'P&&& "'&&&`:\P&&&n "'&&&z`:`P'' +'  "''' '``:P'%'*'F "''0'F'8`:\P'K'P'}  "''W'}'_z`:'m`:\P'''% "''''z`:`P ''' "''''z`:'b`+` @    f KP!((78]`P`qP$), B`PP%)M B`UlPH)`)`)B)z))`P\?P%&)))W.BQ`UlP$)W )`P'))*n)*)``J)*).BP%n*P=**&*b *.*b`>J*4*W*D*;.BP$5BQ(+P>*g*o*(*v*`>J*|**.BP%(UqP(******``P>J*&***.BP%*Uv`PP)**+U*+U+`+K`P\>=+&+.BP$B+4+I+;.BP%+JzUv[PE+Z+^+(+d++i`\>=0++'P*+,,F,,F, K`P`P>=,#,.BP$,*o\J,6,=oP?,K,a,~ +,j,~]%`PJ,m,v,m.ʇ + P+,,-X,-X, ]`P\>I,%,,?`[>=,?,0`P,??F- -.-`P-$?>=-?-6.BP$-F\P,-]-b--f--la`P`P=r`+\>=0--'P---.4 -.4-`+\>=0-.'P..9.>..I..Oa`P`\>=.l.B.t*P1P/......a`P`\>=..B..)P1P1../B./.a`P`/`\>N/ [I/-/1>=/I/e/\/S.BP$LQ4/k/k/z/ll`P`J/r!/w/s/x%>=////.BP$LQ/F//l[&//][=/܃/P2//0M/0M0`0 y`0 `P+\>=00+05!P30R0W00c00h`0sy`0 ]`P\>=000!P4001010`0y`\>=000!P5111 1 11%`10y`1G ]`P1\`\>=01r1|!P6112121a``>I1%1ŀ1`P>N11`P1`PI1122[2.BP$>=2920.BP$B2F[J2X)??J2w*P7223232`2 `P\>I2"2Ā2ǀ2р2ǃw2.(P>>=0222Ǔ3.(P>?I33%3(3(.(P>>=3A38.BP$3H\>=3n3e.BP$3{3.3P(\P8333333`3 ]`P\>=033!P9344/ 4 4/\>=44.BP$B[P:444<44D44I``P>N4\4c`P4i.4jP(I4v!44z(+>=44.BP$B4[?J44P;445`745``P>N44`P5.PAI5 +!55(+>=5/5&.BP$B5<[?J5O5VP@5e5q55w5`P>N55`P55.BP$5BQI555V(+=055('?J55VPA66666`P>N6!6(`P636*.BP$7BQI6J6U6N(+=06^6h('?J66PB667 67 `P>I666.(P>w=066('?J67.P@PC77767%76],`[J7(7(.BP%PEJkO$Vs"r<PI78j5`P`P]_P\? MPK99999`l5P:::>:&:>:8K]`:\PL<<3<8<8<8`IPM>>>>>`lnPNAA$A/A/A/`lnPOC7CCCMCMCM`lnPPE^EjEtEtEt`lnPQEEEEE]l`RPRFF0F<{F<F<]l`RPSFFF|FF]l`RPTFGG}GG]l`RPUGLGeGkGkGk]l`RPVGpGG~GG]l`RPWGGGGG]l`RPXHHH!H!H!]l`RPYH`H~HHH]l`ZPZHHHHH]l`ZP[I3IUI[I[I[]l`FP\IIIII]l`FP]JJJ*J*J*]l`RP^LLLLL]l`ZP_NNNNN]l`ZP`PQQQQ]l`ZPaSS<SGSGSG]l`ZPbUEUcUmUmUm]l`ZPcWPWnWyWyWy]l`ZPdYaYYYY]l`ZPeYYYYY]l`RPfYYYYY]l`RPgYYYYY]l`RPhZ>ZWZ^bZ^Z^]l`RPiZZZZZ]l`RPjZ[[[[]l`RPk[][v[[[]l`RPl[[[[[]l`WPm\,\M\W\W\W]l`WPn\\\\\]l`WPo\]]]]]l`RPp] ]9]E]E]E]l`RPq]J]c]s]s]s]l`RPr]]]]]]l`ZPs^#^A^M^M^M]l`ZPt^^^^^]l`ZPu^__'_'_']l`ZPv_i____]l`ZPw_____]l`ZPx`>`\`e`e`e]l`ZPy`````]l`gPzaa4a;a;a;]l`FP{a@aYa`Ta`a`]l`RP|aea~aaa]l`RP}aaaaa]l`RP~aaaaa]l`RPbb-b4b4b4]l`RPb9bRbZbZbZ]l`RPbbbbb]l`RPbcccc]l`RPc!c:cBcBcB]l`RPcGc`cicici]l`RPccccc]l`RPdd(d5d5d5]l`RPd:dSd\d\d\]l`RPddddd]l`RPddddd]l`RPdeeee]l`RPeSeqe~e~e~]l`ePeeeee]l`ePf,fJfVfVfV]l`ePfffff]l`ePgg%g0g0g0]l`ePgtgggg]l`ePghh gh hh5 hAhc' hphhh]l`f Phhhhh]l`RPhii!i!i!]l`RPikiiii]l`RPiij j j ]l`RPjj,j3j3j3]l`g  =   !!C!t!!""P"""#,#c##$$?$v$$%%R%%%&.&e&&' '@'w''((S((()/)f))* *B*y**++U+++,1,h,,- -D-{--. .W.../3//0#0Z00MPkpkvf`P`P]_]PI_`qPk B],`[PlllBlll ],`[\>@lGl=.BP=4lMlMlflN`[`JlZ%lblZ2_l8lg$l'-_' ll.BP 4lllll`[`Jl!%ĺl3R_P2 lWPllm(lm`Jlll.BP(YPmmm2mm2m`_Jm"&m"m+m".BPm,49_Pm7mEmmHmmM`mV K_\>=0mcmm' +Pmmm(mmm`\>=0mm' +PmmnPmnPn^__~`+\>=0nn(' PnUnZn nannj`+\>=0nyn' Pnnnnn_Jn&nnn.BP_Pnnnnn_Jn&nnn.BP_Pnnooo_Jo&ooo.BP_Poo,oYo4oY`l5Jo7o;l.Po^ozooo`IJooI.PooqoqoK]`:\>=p.4ppppl_\Jppp7ʶp7QPq qqAq!qA`lnJq$q(lU.PqFqRqwq^qw`lnJqaqlqf.PQPq|qqqq`lnJqqq.PQPqqqqq`lnJqqq.PQPqqrqr],`[Jqq.BPPrFr_rrgr]l`RJrjr}rrQ B.lPrrs2{rs2]l`RJsss Q B.lPsuss|ss]l`RJsssQ B.lPtt-tr}t;tr]l`RJtDt]tLQ B.lPttttt]l`RJtttQ B.lPtuuU~u"uU]l`RJu+u@u3Q B.lPuZusuuu]l`RJuuuQ B.lPuvvRv vR]l`RJv)v=v1Q B.lPvvvvv]l`ZJvvvQ B.lPw-wKwwYw]l`ZJwbw{wjQ B.lPwwx'wx']l`FJxxxQ B.lPxdxxxx]l`FJxxxQ B.lPyyy^y'y^]l`RJy0yIy8Q B.lP{||J||J]l`ZJ|#|5|+Q B.lP~1~O~~Y~]l`ZJ~b~w~jQ! B.lP]l`ZJQ" B.lP LL]l`ZJ 7(Q# B.lPJhs]l`ZJ|Q$ B.lP]l`ZJQ% B.lP&&]l`ZJQ& B.lP+DU]l`RJ^zfQ' B.lP]l`RJQ( B.lP;;]l`RJ&Q) B.lPzb]l`RJQ* B.lPÁQ&Q]l`RJ)<1Q+ B.lPā]l`RJQ, B.lPŁ6s@s]l`RJI^QQ- B.lPƁ]l`WJQ. B.lPǁTu]l`WJQ/ B.lPȁMM]l`WJ%8-Q0 B.lPɁ]l`RJQ1 B.lPʁ66]l`RJ !Q2 B.lPˁ;Te]l`RJnvQ3 B.lṔA A]l`ZJ,Q4 B.lṔ]l`ZJQ5 B.lP΁*HU]l`ZJ^vfQ6 B.lPρ--]l`ZJ Q7 B.lPЁo]l`ZJQ8 B.lPс-n9n]l`ZJBYJQ9 B.lPҁ + +]l`ZJQ: B.lPӁNly]l`gJP B.lPԁII]l`FJ!4)Q; B.lPՁNgTo]l`RJrzQ< B.lPց]l`RJQ= B.lPׁDD]l`RJ/"Q> B.lP؁Ibo]l`RJxQ? B.lPف00]l`RJQ@ B.lPځ5NW]l`RJ`thQA B.lPہ]l`RJQB B.lP܁]v]l`RJQC B.lP݁ + +]l`RJQD B.lPށ(e2e]l`RJ;PCQE B.lP߁]l`RJQF B.lP>We]l`RJnvQG B.lP။]l`RJQH B.lP⁋7PY]l`RJbvjQI B.lPか]l`RJQJ B.lP䁋GG]l`RJ2"QK B.lP偋]l`eJQL B.lP恋1OZ]l`eJcykQM B.lP灋33]l`eJQN B.lP聋w]l`eJQO B.lP運9zEz]l`eJNeVQP B.lPꁋ]l`eJ +QQ B.lP끋f@ g  £' P]l`f JYtaP B.lP쁋]l`RJQR B.lP큋 II]l`RJ4'QS B.lP]l`RJQT B.lPD]o]l`RJxQU B.lP]l`gJQV B.l334c455~56*667!7f78D889.9{9:/::;=;; >g>??u?@)@@A7AABDBBCRCDD`DEEnEF"F|FG0GGH>HHILIJJZJKKhKLLvLM*MMN8NNOFOOPPQSQRRaWPIb J'`[`\=`T`]`FhsP]l`g mY`gRPP]l`f  qmY`f RQ B`U}+Q(B``+QSB`n+QB`p/+Q'B],`::'`:'C'''''''''''' '!'"''#'$'%'&'''(Q8 )`P+Q= ]l`R =&l`R'Q>@*]l`R >^l`R'+Q?|,]l`R ?l`R'-Q@.]l`R @l`R'/QA]l`R B l`R'QBX0]l`R Bsl`R'1QB2]l`R Bl`R'3QD4]l`R D l`R'QE;5]l`Z ETl`Z'6QFy7]l`Z Fl`Z'8QG9]l`F Gl`F' QH:]l`F Il`F';QJ5<]l`R JTl`R'=Q M?>]l`Z MWl`Z'?Q!O@]l`Z Ol`Z'AQ"QB]l`Z Rl`Z'CQ#TuD]l`Z Tl`Z'EQ$VF]l`Z Wl`Z'GQ%Y7H]l`Z YTl`Z'IQ&[J]l`Z [l`Z'KQ'[L]l`R \!l`R'MQ(\zN]l`R \l`R'OQ)\P]l`R ]l`R'QQ*^]l`R ^.l`R'SQ+_C]l`R _\l`R'Q,`q]l`R `l`R'Q-aR]l`R al`R'Q.bS]l`W bl`W'TQ/d"U]l`W d>l`W'VQ0efW]l`W el`W'XQ1f]l`R fl`R'Q2gY]l`R g l`R'ZQ3gu[]l`R gl`R'\Q4h]]l`Z hl`Z'^Q5j_]l`Z j!l`Z'`Q6kJa]l`Z khl`Z'bQ7lc]l`Z ll`Z'dQ8me]l`Z ml`Z'fQ9og]l`Z o2l`Z'hQ:pWi]l`Z prl`Z'jQ;qk]l`F ql`F'lQ<r m]l`R r"l`R'ZQ=rrn]l`R rl`R'Q>ro]l`R rl`R'pQ?sFq]l`R sdl`R'rQ@t~s]l`R tl`R'+QAt]l`R ul`R'QBv]l`R v2l`R'QCwIt]l`R wcl`R'-QDwu]l`R wl`R'vQExw]l`R x:l`R'xQFyRy]l`R yll`R'1QGzz]l`R zl`R'{QHz|]l`R {l`R'}QI|0~]l`R |Jl`R'QJ|]l`R |l`R'QK}]l`R }&l`R'QL~K]l`e ~jl`e'QM]l`e l`e'QN]l`e l`e'QO]l`e :l`e'QPb]l`e l`e'QQ]l`e l`e'QR]l`R ?l`R'QS]l`R l`R'QT- Σ ٣]l`R Ql`R'QU Z| ]l`R l`R'QVc]l`g |l`g'QW`:+QX`:+QY`+QZC`+Q[`+Q\`:+Q]i`:+Q^w`+Q_ `G+Q``+Qa`:+Qbs`+QcJ `C5+Qdo `b+Q B '`j+Qe`:+Qf `+Qg `+Qh `+Qi' `+QjD `:+Qkb `:+Qlz.`:+QB '`:+Q B 'd`:+Q  B 'Z`:+Q + B '`+Q B '`+Q B '`+Q 0 B '`+QmH`:+Qnh `d-+Qo `:+Qp `P+Qq `P+QJ 3B "'4`+Q .B b'L x' '],`[+Q 5B ֡'6`P+QE 7B '8`P+RT::^I^\? T\ Qs + + `:(`p+E`p +`P>N_h`NzxsjBsUgсg҂gR6J&߃gˑ[4l`[`J%hb`P`PQt`:`:+`PJ&RWhʁ h`PQu=`PJCQv%-\<\`PJBFQt'Qw`PJQt'Qxs{`PJQt'Qy9O$9`PJ*.DQz`PJEQ{JRsS]s`PJcgMQ|`PJQt'Q}>`PJQt'>Q~19^C^`PJIMQt'Q`PJQt'Qu}`PJQt'Q="=`PJ(,Qt'Q`PJQt'QFNsXs`PJ^bQt'Q`PJQt'QC`PJQt'CQ'N2N`PJ8<Qt'Q`PJQt'Qow1`PJQt'1QEP(E`PJ.2Qt'PQ`PJQt'QT\i`PJosQt'Q  `PJ Qt'Q`PJQt'Q=EjOj`PJUYQt'Q`PJQt'Qow`PJQt'QA#A`PJ)-Qt'QÈàë][`:`:Jîòk.QĜĜK][`:`:\>N ][`:`:'.Q=B7q wFOn[`:hbq{>=ĀvqārčĈqĎrmnQasƣL|ƣ],`PJƃPH.QƨƬdžLƴdžK],`P\>N ],`P'!r݁N9BL],`PI.LQ=`Ws) C=vms)}r<Rɓz:ɓ`P`PBx`:]PI_JVZP_v.yBɈsR+Q`l5Jl.Q K]`:\>N˲˻`l5˽.Q=Ӂt =tt}l;Q][`:`:Jl .QQ&;K][`:`:\>NNS][`:`:Z.Q=lgu wFyϘυ`:ϒόuv{>=ϤϠuϥuϱϬuvϲumnReyАИ`:][`:`:>JЩдk.vrRӍӡԇӱԇӺ`:+`G>Iv(+B>=v'?JO]VBB.uvhQEE]`J +`.Qg .Qh+.Qi8.QfQՙէeծ]`Jշջ`.Q.Q.Q.QRJO֌Y֌a`:\>=r.}dւxl\R "`:=`p+Z`p +\>=u.'Ҁוxс׮x҂xR0Rgs؁؉`:`>Nؘؚl[شRWyb+J"%߁y{`P!%y{`P`fvRx$x\>=g.R RۇیP۔\>=.R R 1@~<@\>R +EUݬcݬ],]`>NpvK],]`x.BRN[[''4 zI!z(+>=2[''ـ^z?=q?'ڀݏzJݜݣzR ~\>R  ᵣף',]][`:[![+`C>I0"!%;4{][!TM{=4ZZi[][`:[`Ja%ca|s][[[>=0u$''?N[I% +{][>=&|c?8{[CpH>=|р{N[#%Ɂ|][[[pH|][[[|[J#}I(+0.B9|RT.B]|уn}IR`CRB 䈡' "'`[+`CR,%*k:kBK`:O`:`q`:\>Qpd q'9`:J幜`:'9'.BQQ Y `:J.BQ R-A`:J.dQR.7<J\`RZ+\>Nr`)=꼜`'g'.I(R^>=%.B)R&IGUK(hR`>=}.B*R&I렁>IՀ(R_>=.B)R'>=:.BR'>=u.BR&RLB2L?l`R`:JE'RB l`R`:>Idop>J'Ip>J'?J'R/`:`:\>I`'g'.>=R.Bfm'R>=.Bd'RRB ' "'`:`:\R0-2DL`:Z`:u`p+`p +\>I%v`p>=.BGVR>=.B4GE.TVтsf҃vR6RRB ' "'`:`:\R1 `:`P`P>I+/`'g'.>=f.B}R>=.BRJRKB ' "'%K-`:<`P\RPUBhp`:|`[\>AG!W'>=.[.\B '>N'-`[#A:4.[(YwQL.[9+`[=j.w}i\B'>=.\B'>=.[.[\B0>=0NX$'jzR2Lx`:`>I`'g'.>J&-`'g'.NIei`'g'.>J`'g'.I`'g'.>J%,`'g'.XIos`'g'.>J`'g'.I`'g'.>J%,`'g'.V>=0u'R3(0x`:`>NEJ`P.DV>IajeuLr\R2J~)?=uu[!u(+J*R4:  ' +J`b>JSZ`b' ' ...QJ   +' +U`bJ^^`b''..Q=IqUq`lnJX\lL.Q   6  6`lnJ  !l].Qx`lnJle.Q% +%`lnJ lm.Q99]`J.) BMR5R5-3;D`P]`>JRaR.wcRB'`P`P]`>N` ʁN'5`"7VNGٛQo('BIe"qi(+|>I(J`?=0$''?NCP`PZRʷ)QNrtC]`~RفJ`WȀʷQօ!WʷQR6%%`:`p+-`p +`Nz> ICUG(+>Iftj(+>IQ(+>=Qn?=Q?I(>,Q(+>=QQip:>=Qсp1=QI +!(+>=0)3'?IQ(+>=QB=M'N=Q  +QENN  `D&   Q'N,`D=    B[D=!!! QU!$\?I!!!!QsU(+>=!!Qs&!!!Q'sN,`ELU?N!"%".`EL>="/"O"@QsU>="h""yQ".QoN,="""QsU&""`[\N"[I"""`F#$.BQ>=#^#RQ&#q#q`[`<=#Q##Q#`1>=##B#=#Q$$Q=NC$5!$V$K$<(+>=$r$iQ$$yI$!$$($$QsU>=$$?=% $ &%%Q`[p=%t%kB:&%~%~Q`[NJ%&%%Q`NzQ%%&RB&!&R`J&*!&+.!BQQ&&''!B&''`J&'&Qn'.QoQ))*&)*&)`:\>=*.*R7R7--.-.-`:-`p+-`p +\>=-.+[I.%..s`p>=.;.B.HSQ>=.a..h..wSс.c҂.sR6\Q.....`:J...BQQ///"//`RJ//R.R006#B060`P`>J00`'g'$6R787D7%B7j77s`P`>J77`'g'&70R778'B787[`:>N88 `:'(K>I86%8J8B8:`:>=8_&8_8p8h`:?8[8l[>J88Q88989`J8&898圣['').`Q999P9&9P`J9)&9)9I9)[''*.`Q9U9]99g9`J9j&9j99j[''+.`Q99999`J9&999['',.`Q99:9:`J9&9:9[''-.`Q::&:[:1:[`J:4&:4:T:4[''..`Q:`:d::n::sK`\>=:['7'/.::Q:::::`J:&:::ќ[''0.`Q:;;Q; ;Q;K`\>=;['7'1.;E;?pQ;V;^;;j;`J;m&;m;;m[''2.`Q;;<pB;<`P>=0;;'Q!]33]`J66`'g'4.R8 "'\R9 +6 "'\R:"0 "''0\QCN|5X|`:J[[`:'9'6.R;O7O8][[[`b>N9[pHJ&.:B6RRTy:B U'7 "'8[`bR<; "'x`:`PR=] "'],`CR>'< "''K`:`:R?,3o= "'AoIZ`:^d`:`:R@t> "'],`:RAg? h'@ 'A "']`RB ȡ' ' 'B "'],]`RB2XC ' ' "'OX],`[RC%^ '_ š'_ "' %``:],`[R*DB +'c M'_ s'_ "'d`:],`[REB ס'F "' +K`:`R<yGB 'H "'KySZ`:hd`:`RD~I "'J``REK "'J`\R*LB 'M "'*K`:\R/SNB 0'O "'emZ`:d`:\RFP "'\RGQ[+!`+\>I"{(+(+>=.RBR J(?I:"%L?{][[[YW(+>Nnx[zpH{][[[=.SB)R!J?I"!(+%{`>= .TB{`$R"J.?=0@J'GR RB ' "'\R!SB ' "'\[\R"!TB ' "'!`![\RH&+U35Q[+G!`+\>IQ"bU%(+om1(+>=.VBR#J?I"%%][[[Ɓ1(+>N[pH%][[[=.WB'R$J9?IK"!QO1(+%j]%`>={.XB%`1R%J?=0'GR#)VB 'U "' )\R$-HcWB .'U "'ScT\[\R%gXB h'U "'`![\R&B ' "'`+\R'KB 'Y "'-K4Z`+\RIPU[]_Q[+q!`+\>I{"(+(+>=.\BR(J?I"%][[[(+>N[pH0][[[=E.]BQ/R)Jc?Iu"!{y(+%`>=.^B`R*J?=0'GR($?S\B %'[ "'JS\R)Wr]B X'[ "'}~\[\R*^B '[ "'`![\RJ3_ "'3`^`awB\a`:\RK8=kb "'IkQK`:^K`:\RLpuc "'Z`:K`:K`:\RM*d "'*`^`awB\a`:\RN/4[e "'E[JJ`\RO`6f a'g   "'-6\RPPUo "'Zob`\RQty "'`\RRw "'x`:`PR+jyB 'z 2' I' "'{x`:],`[Q]l`RJQ.lQVo{|]l`RJQ.lQ)|)]l`RJ + +Q.lQn}]l`RJQ.lQ44]l`RJ$Q.lQ9R|~\|]l`RJ_l_Q.lQ]l`RJQ.lQ1Y:Y]l`RJ=I=Q.lQ]l`ZJQ.lQ!?wMw]l`ZJVgVQ.lQ]l`FJQ.lQ8Z|`|]l`FJclcQ.lQ  ]l`RJQ.lQ]l`ZJQ .lQ]l`ZJQ!.lQ 'U3U]l`ZJ6E6Q".lQb]l`ZJQ#.lQÁ]l`ZJQ$.lQā%%]l`ZJQ%.lQŁ +O2O]l`ZJ5?5Q&.lQƁTmƫ~ƫ]l`RJƇƛƇQ'.lQǁư]l`RJQ(.lQȁ77]l`RJ'Q).lQɁvǏǵbǗǵ]l`RJǚǥǚQ*.lQʁ 33]l`RJ#Q+.lQˁrȋȱȓȱ]l`RJȖȡȖQ,.lQ́ 55]l`RJ%Q-.lQ́vɗɡ]l`WJɤɱɤQ..lQ΁$P/P]l`WJ2@2Q/.lQρʏʰʸ]l`WJʻʻQ0.lQЁ-Q4Q]l`RJ7A7Q1.lQсVo˟|˟]l`RJˏQ2.lQҁˤ˽]l`RJQ3.lQӁ>\̊h̊]l`ZJkzkQ4.lQԁ""]l`ZJQ5.lQՁf̈́ͺ͑ͺ]l`ZJ͚͚ͪQ6.lQցI'I]l`ZJ*9*Q7.lQׁ΋Ωδ]l`ZJηηQ8.lQ؁6dBd]l`ZJETEQ9.lQفϥ]l`ZJQ:.lQځ1OЅ\Ѕ]l`gJeueP.lQہ  ]l`FJQ;.lQ܁*PT2P]l`RJ5@5Q<.lQ݁Unђuђ]l`RJxтxQ=.lQށїѰѺ]l`RJѽѽQ>.lQ߁((]l`RJQ?.lQgҀҦ҈Ҧ]l`RJҋҖҋQ@.lQ။ҫ]l`RJQA.lQ⁋,EmNm]l`RJQ]QQB.lQかӭ]l`RJQC.lQ䁋 44]l`RJ$QD.lQ偋9R|\|]l`RJ_l_QE.lQ恋Լ]l`RJQF.lQ灋B[ՍiՍ]l`RJl}lQG.lQ聋Ւիյ]l`RJոոQH.lQ運.V7V]l`RJ:F:QI.lQꁋ[t֞~֞]l`RJց֎ցQJ.lQ끋ּ֣]l`RJQK.lQ쁋1Oׇ]ׇ]l`eJfwfQL.lQ큋]l`eJQM.lQWuث؂ث]l`eJ؋؛؋QN.lQ CC]l`eJ#3#QO.lQن٤ٰ]l`eJٳٳQP.lQ4jAj]l`eJJZJQQ.lQڱۋ ڲԣ ߣ  /' <^ۛ]l`f Jۤ۷ۤP.lQ]l`RJ QR.lQ7aAa]l`RJDQDQS.lQܫ]l`RJQT.lQOhݨzݨ]l`RJ݃ݘ݃QU.lQݭ]l`gJQV.lghhi iciij8j|jkkKkkl lgllm<mmnnVnno+oroppGppqqlrhrsttStuLvHvwMwxBxy8yzzUz{{~~i~/v!mO2b P9&r) Rm5X{F]P+WLa\QEBWKd~-s-/13579;<>@BDFHJLN¤PæRĨTŪơMǣORUh`RY\? RWvޅiޖޞ`:ު`:[>I! A(+B>J*1['j'kg2vA?J['j'l2RZ m`R]% B[R^n`RZ Re'nR_Xo`RZ gRe'oR`p`RZ Re'pRe/5[NBN[T[\?R]͢ 5Rb__Ag`:Jm$'q.BR]Rfr   B Gi r + ~'s`CRh`:+RiK`:+Rj`:+Rk`:+Rl/`:+Rx99aMa\? XC RoJpBJ`Rf>=0%'RpOWc`RfJi&iriB'tN,`RfRr`JR'tRu9>\IB "'H\PK`:`[RvafB "'pxK`:K`[\Fϒ5ЂRyu 韢'u`R{h v`S+R| `:+R} '`+R~ %`+R K`:+ R RpBR`Ry>=0#-'RuwB ١' "'u`MK`:+9^`RyB\+_^`NSB\+\Rz {'`MK`:+]`Ry>N]`Ry`Ry=.wBҾ 4AK`Ry`>=+!t4F4CCxDS`N`>=]SjkӑRJ쐂uRxB 젡'y "'^`Z$B\^`NSB\+\RGIy 'yRI]`Z$>N_i]`Z$o`Z$=.xB4K`Z$`>=?'z=ڀԬt4'S`N`>= ԬjYRJ.?5ԬuRNj{B O'| "'t^`RyB\+^`NSB\+\R| ȡ'|]`Ry>N ]`Ry`Ry=*.{B455e6K`Ry`>=OEutXֿ4gghS`N`>=wuj +RJﴀuuR`}B ġ' "'``M K`:+$^`RyB\+J^`NSB\+\Re f'`MK`:+]`Ry>N]`RyΦ`Ry=.}B6F4,K`Ry`>= btؾ4..c/S`N`>=H>bjV RJj{qbuRB ' "'^B\^`NSB\+\R '][>N(2][8[=I.B4QQw`>=f\t4yyzS`N`>=jڎRJƀuR~ ֡' "'`:ј҆fի/\[) R=es > + J'`RR `+R$ S '`+R; `:+RR `+Rj `:+RpB`R>=0'R %`:0.][[[+`R>IF!XJܢ(+>Nm}/[pHܢJRܓ?JRܓR-B67[=.[`RJUU`R''}s~R1B[`RJ`R''jEݾ#Ry +] z'`RB`:+R`R`R`R `+R/ `+RI `+R B ' ֡' '[+R: `+RY `+Rs `+R ( B ҡ'c ' '[+R B `+R ] `:+R  `:,`)B`)`R>J[fR'.؁>قNRD`:K`:`))`)`R>NNPl`R[RBBhN=us BԂRJ R`P>I +.BR(+B>=0%/$''?N`P&.R`PNc`P&.cR`PN [D>I'2+*L:.BRR2JFM*?=[*kd*["!*(+!*([=0('R g$g],`RJ-#-`'g'.T.R1e`R],`RRltkpB{k`:.][[[+`R>I!(+>N/[pHJR)ǂ/?JKXRbRo|B[.[`RJ`R''䧁R1B[`RJ`R'' RVft`RJ}}B.BRRc`RJB.BRR f x  "'  ],`RR   B  ' "'   `: `+ `+\R   + "' + +\R + + +9 "' +0 +9\R +> +C +[ "' +R +[\yW@&]RÁ 8 U  9'`R RŁ ]l`R  l`R'SRƁ]l`Y l`Y'Rǁ8]l`R Pl`R'Rȁ`RɁ`Rʁ`Rˁ "`+Ŕ4 `:+ŔG `+ Rρ y  B  B `: [*`R>N  ][`:[2 `:[' $J  R + 09Rс ~  pB  `R>=0  'RԁwB`:][[[+`R>I!(+>N[ pH?J[nRx }U?JR RՁLBL[[`RJ  `R''38RցPc1Blm[`RJ{{`R''bRׁ[`nw "'en\Rفb]y`RJRŭ.lRځ-FoPo]y`YJS`SRƭ.lRہ]y`RJRǭ.l4"v R܁pv)`R߁ B`RRか`R\?R߀X R။''`:]y`R>Jl`R.BR߀*R䁋,2Q`RR恋`][`:`:2o`:`:''''''''''''''''''''''''''''Rꁋ`P\?  RR聋3O5O=`:]y`R>II_ZMR{nmh,!W>Ip>Jl`R.BRR,!Wm*??J!l`R9.BR߀?,*&R끋  "&  '`R l l B  \?  lR큋!! !6"!#!6`RJ!&!*R.R!;!@"!P"!X`:!l^`RB[!`+\>I"q!"~"u(+>=".B" ""8R?R""$\"$\"`:"^`RB[#`+\>I$!$$(+>=$".B$7ȁ$=ׂ$GR?R$$$pB$$`R>=0$$'R$%%aB $' "'%%a%'`:%;^`RB[%K\`+\R%f%k% "'%x%%`R`R%%& B %' "'%& %`:%^`RB[%\`+\Z*tR&' ) &'`RR'e'm'pB'~'`R>=0'''R''('('`:'.][[[+`R>I'!( '(+>N("(2/[(4pH(SJ(i(S(Â(?J((S(S(()_B()_([).[`RJ))`R''Ҁ)K)QS)c)z)1B)))[`RJ))`R''Ӏ)S))) "')))][\NuSS**, *ʢ'`RS, +p?+p@`+S,4 `:+S ,Q `:+S +,t ],`Z +S , 6 ,' ,'`+S+\+d+pB+|+`S>=0++'S--. -Ң'`S.D.L.pB.V.`S>=0._.i'S... "'..\S... "'..\bS//3 /'`S060>0pB0L0`S>=00U0_'S001010][[[+`S>I0!0׀0(+>N01[1pH1-J1I1]S1g?J11SS112*B12*1[`SJ11윣`S''2HS2.2B2y1B2K2y`SJ2Q2Q`S''S2~23 p23 2q[]],`MSJ22B],`MS2ꜣ[''r.3`OS 346 3'`F`FS"6 ]`:+S#6 1`:+S$6k  6J'`:+S%6 K`:+S(444pB44`S >=044'S)445}55}5 +][[[`S >N55![5#pH5BJ5M5hS,5rS,555B555[`S J55`S ''5 + WAS-7e7:3 7f'`RS/9u `:+S09 `+S1: `k+S4778,pB78,`S->=078'S5818988C88K`:8U.][[[`S->N8n8~/[8pH8PJ88S88A8lS8889cB99c9 [9.[`S-J9'9'`S-''9O9US;99999][J99B[9Μ[''.S9:::1 "': :1:(][\.S<;;?> ; + ;'`CS>={`+S?=  =' ='],`[+S@= `T++SA>K`:+SB> `:+SC>3 `:+SD>] `g\+SE>u `+SO=F=F=q=]=q\? =hC SH;;;pB;;`S<>=0;;'SI;;<< <`S<J<<`S<''>> "'>>`SL>>> "'>>`SM>>> "'>>>S`:\6PSP??C ?Т'`ESRB `+STC3 B B' C'[+SUCZ K`:+SVC  Cd' CC CCӣ`:+SY@3@;@ypB@A@y`SP>=0@J@T'SZ@~@A@A@],`@`:@\][[[+`SP>I@!@Ԃ@%(+>N@@[@pHA%JA$A0S]A:ADANa?JAdApS^AzAS]AAB BAB A[A[A\[`SPJAAќ`SP''AABS^BBBq1BB$BqB%[B/[`SPJBBBB`SP''B^BhS`BBBBB`JBBpJB.BSTe2SaEFI E'`RySdFmFuFpBFF`Sa>=0FF'SgFFG;B F' "'FG;F^`S[B\G%^`NSB\+\SiG@GmHu GA'GyHu]`S>NGG]`SG`S=G.B4GGHGK`S`>=Gѡ?'G=HGtH4HHHSHS`N`>=H8H.jHFBSgJHZHkHauShHzHHpB H{' "'HHH^`SPB\H^`NSB\+\SjHII H'I +I]`SP>NII!]`SPI'`SP=I>.pB4IDIDIIEK`SP`>=IT?'Ik =IIy ]tI 4IIIIS`N`>=II ]jI + +ShJIII ]uO  +\SkJJ`]`SP +SlJJ`Sk]mj`SP +SmJJP JТ'`Sl],`SP]`SP +SpKKKpBKK`Sm>=0KK'SrLLL-(LL-`JLL`'t'h.SwL2L@LLBLLG``SP>ILTLX`'g'ՀL~ L L L.(Sr=0LLL .?JLL֜`SP''N.L SxLM MwMMwM`M K`SP\>=0M-M7'S|MMN(MNMK`\>=0MM'SsNN%NN+N`SP>IN1NAN:.(Srw>JNNNU`SP''z.?=0NyN('StNNODNOD`SP>NNNV`N.(SrINN܀N w>JNN`SP''N.O O  y?=0OO'('SuOIORP#OYP#`SP>NOcOgV`On.(SrIOzOO~(>JOO`SP''z.?IOOÀO(=0OO('?=0OO('SyP(P-PPP6PPP;``SPJPEPI.PJSwSzPtPyP "'P}PP``SP " n    : \ +S}QlQ_ Qm'`R SS]l`_ Sl`_'SU%]l`_ U>l`_'SSVe]l`_ V}l`_'SW]l`_ Wl`_'SX]l`_ Y l`_'SZ;%]l`_ ZWl`_'S[%`S[C`S[b`S[ S`N+S[ "`+SQQR^QR^`>NQQ[Q͜[''.IR%RR 1`>JR&R1"R@1`?JRPRW1SRRRpBRR`S}>=0RR'SZZZZZ`S}>JZZSSZZ[BZ[`S}JZZ뜣`S}''S[[[ "'[[\S[[[ "'[[[P`E\S[\ \, [' "'\\,\ P`E\S\1\6\b  "'\@\b\FP`E\T`:+\S\\\\\]y`_J\\\S.lS]%]?]db]G]d]y`_J]J]U]JS.lS]]]]]]y`_J]]]S.lS^&^@^i +^J^i]y`_J^M^Z^MS.lS^^^ ^^]y`_J^^^S.lS_;_U_5_`_]y`_J_c_q_cS.l)zKHDS`]`b$ `^` `' `Sa K`:+Sb L`M+Saa +aNpBaaN`S>=0aa)'Saaaaa`Jaa`'g' GSd.dJp d/'`R Se]l`_ fl`_'Sg']l`R g@l`R'SShc%]l`_ hl`_'Si]l`_ il`_'Sj]l`_ k +l`_'Sl:]l`_ lXl`_'Sl`Sl`Sl`Sl S`N+Sm (`+Sm& 1`+Sm= "`+ SdddpBdd`S>=0dd'SmLmQm_ "'mVm_\Smdmim "'mmmmr1`\Smmm "'mmmB`\Smmm "'mmm`E\Snn"nGn*nG]y`_Jn-n8n-S.lSnnnbnn]y`RJnnnS.lSoooJ5o*oJ]y`_Jo-o;o-S.lSooooo]y`_JoooS.lSpp*pUp5pU]y`_Jp8pFp8S.lSÁppppp]y`_JpppS.l3j<73 Sārsv\ s'`fSSǁvH B v ' v('[+SʁsrszspBss`S>=0ss'Sˁsststs`:s.][[[+`S>Is!ttP(+>Nt%t5/[t7pHtVPJtlt~StAt?JttStAS΁ttuIBtuIt[t.[`SJu u `S''u5!u;,SρuMu_u1Buhuui[`SJuxux`S''uSсuuvuv`RJuuBu.BSl %Sҁw7wQ{{ w8'` Sԁz`:+SՁz)`:+Sցz; `:+Sׁz `:+S؁z!`:+Sفz`:+SځzA`:+Sہ{"`:+S܁{#`:+S߁wwwpBww`S>=0ww'Swxyx yx`:x 6`x-$][[[+`S>IxA!xQxE!(+>Nxfxt%[xvpHx!JxxSx!x!ăx"?JxxSy!y!Sかyy.yBy7yy8[y@6[yH$[`SJy^y^`S''&y"y"y"S䁋yyz +1Byz +y[y6[`SJyyל`S'''y#Cz#NS灋zOzdz(zkz]`SJztztB`Sz['').S偋{%{6{y{:{y]`SJ{F{FB`S{`[''*.!@!"###$LS聋|V|s+ |W'+`RSꁋ}X,]l`S }sl`S'-S끋}.]l`S ~l`S'/S쁋~v0]l`S ~l`S'1S큋~ `:+ +S||}pB|}`S>=0||'S~~ "'~`S`SSBa "'B'!`:5`:+`SGLZ  "'QZ\S_d "'jt`S`S "'^`S`S`SMNB\y`+\S "'`S`S?2 ?]y`SJ#0#S.lSDe3s]y`SJ||S.lS4]y`SJS.l%H%%&8&o&'+'u'((q +S*5 ٢'5`RS 6],`S+T]epB{`S>=0'T`:.][[[+`S>I!)t(+>N$4/[6pHU)tJkT)e)?JT)eTB  [.[`SJ$$`S'5'7s*E*PT1B[`SJƜ`S'5'8*()<***T%9 '9`T  2`S+T pB`T>=0'+T+T _: ΢':`RT `:+T0 `k+TV^pBq`T >=0z'Ttt`:.][[[`T >N/[pH#,J7PTZ,`,TxB[.[`T J`T ':';-#-.T<A] "'L]T][\, ,X,-n-T:< ;] f '  '<` T\dpBn`T>=0w'T::`T++`T>I!߀.(+>JT  +.?J+T!T >NBWX[`TJaa`T'<'=/ST!1B`TJ`T'<'>T* N*N`J--`'g'?T"SX "'^fK`:sK`:\T#@ ' "'K`:K`E`:+\T$ "'K`:\T% " "'"K`:`T&'4N "':NBK`:],`T'SXo "'[ocK`:`T(ty "'|K`:K[`:+\.G./%//0(0|0131{122s T+6A 'B`C +T-C`:+T.`:+T/`:+T0 `:+T1!D`:+T27 (`+T3I7`:+T4[K`:+T5iE`+T6c`:+TF\? C +T9 QpBQ`T+>=0",'T:V^i`T+Joo`T+'F'B'T=IB "'K`:`T? "'`T@ "'``PTA "' +`TBG05][[[\>NHRH[TpHs5=.IB5T>JT>IB 'G "'[\TC + "'\TD %4 "'+4\34G445'5q566666 +TGJ 'J` +TIN K],`+TJ L X'M '],`TV+TK N`+TL O`+TM P`:+TN .`:+TO0 `+TPG Q`:+TQe R`Ti+TRx C`+TU9pB9`TG>=0 +'8e8TV^}nS _'S`TX: `+TYQ T`+TZg K`+T]*pB*`TV>=0'929~T^IgU J'U`RT` V`TG+Tc pB `T^>=0'Td#%#-`:8.][[[+`T^>IN!`R:W(+>Nu/[pH:WJTg:H:?JTh:HTg';BDE[K.[`T^Jcc`T^'U'W;(;3Th1B[`T^JԜ`T^'U'X;9::;s;TiY 'Y`Tk Z``+Tl [``+Tm \`+Tn> ]`+To` ^``+Tp _``+Tq ``+Tr 1``+Tus{pB`Ti>=0'<=Tv`  + ¢'`` Txa(6b`+S`{+ec`{+]`T>N|\][[[2[[I!=(+>==ǀ'b=n?I!=(+>==ǀ'.&=+n?IH!WL=(+>=oh=ǀ'c=+n?N]`T`TK>=.dB4B1`T`>= >t.eB/?T{4DD}ES`_I`>=`V>jn?x=T}[l[`>=>j?Ć?J>uTyOf O.b`+K`{+]c`{+]y`T>Nt|\][[[2~[[I!@J(+>=@'b@Jn?I!@Z(+>= @'&@Z+n?I@!OD@j(+>=g`@'cx@j+n?Ng`Nr]`T=A +`Ti)Y4`>@A(+= +A.hB4##r$1`T`>=G<AK.eB[B:T{4ttuS`_I`>=AB@T4+`>@!A(+= .iBAT|J3E:AT{T`?eBo?pj[`T>K>I%ÀC`T>JC`T?[l[>JT/CT|pB`Tv>=0'T| +iB ϡ'k "' +l`\T}dB':^`T1B\i^`_ISB\+|\][[[+\>I!E +(+>N[pHE +=.mBDЁDEBT~J0?IB!TFD(+>=e.nB{DЁDTJ?=.oBDTJT~mB 'a "')<^`T1B\j^`_ISB\y\[\TnB 'a "'^`T1B\^`_ISB\\T EoB !'a "'Zm^`T1B\\T<hB<^`T1B\^`_ISB\+\][[[+`>I! G(+>N!+[-pHLGJ\c.pBtGG΃H'T?I!G(+>J.qBGGT?J.rB(GTTA`pB B'f "'p^`T1B\^`_ISB\\[`TXqB ԡ'f "'X^`T1B\C^`_ISB\`T\{rB ]'f "'^`T1B\`=_@CWCDJDFFGGHIJJq T|Vs``TTB[T[\?TK T=`FJ`F''t.BTT!)TC3T`J66`'t'uO.BTK;KKT1K+v 2'w`T =`F+T C`+TpB`T>=0'LcLTFx``R9T]l`R l`R'T6]l`R Nl`R'T0]l`R l`R'1T +2]l`R ,l`R'3T4]l`R l`R'T5]l`Z l`Z'6Th7]l`Z l`Z'8T<]l`R l`R'=TY>]l`Z ql`Z'?T@]l`Z l`Z'ATAB]l`Z ^l`Z'CTD]l`Z l`Z'ET7F]l`Z Sl`Z'GTH]l`Z l`Z'IT+J]l`Z Cl`Z'KTL]l`R l`R'MTN]l`R -l`R'OTP]l`R ˜l`R'QT]l`R l`R'STQ]l`R jl`R'Tú]l`R l`R'T#R]l`R >l`R'TĘS]l`W ijl`W'TTU]l`W 1l`W'VTŔW]l`W ŭl`W'XT]l`R l`R'TlY]l`R Ɗl`R'ZT[]l`R l`R'\T_]]l`Z |l`Z'^T_]l`Z l`Z'`TWa]l`Z ul`Z'bTc]l`Z l`Z'dTOe]l`Z kl`Z'fTg]l`Z l`Z'hTCi]l`Z ^l`Z'jTʺ]l`g l`g'yT2m]l`R Kl`R'ZT˛n]l`R ˳l`R'To]l`R l`R'pToq]l`R ̍l`R'rTs]l`R l`R'+TÁK]l`R el`R'TāͶ]l`R l`R'TŁ!u]l`R ;l`R'vTƁΌw]l`R Χl`R'xTǁy]l`R l`R'1Tȁd|]l`R l`R'}TɁ~]l`R l`R'Tʁ<]l`R Wl`R'TˁЩ]l`R l`R'T́!]l`e @l`e'T́Ѡ]l`e Ѽl`e'T΁]l`e 6l`e'TρҔ]l`e Ҳl`e'TЁ ]l`R ,l`R'TсӃ]l`R Ӟl`R'Tҁ]l`g l`g'>Tԁ$y4y<`:Ja`R[m`+\TՁ}`R`Tց`:a`R[`+\T؁ "`RUKSpBh`T>=0q{'Tف;MrUr]y`RJXcXT.lTځwԉԬԐԬ]y`RJԓԝԓT.lTہԱ~]y`RJT.lT܁::]y`RJ+T.lT݁?QxZx]y`RJ]i]T.lTށ}Քչ՜չ]y`ZJ՟ժ՟T.lT߁վ]y`ZJT.lT N+N]y`RJ.?.T.lT။Sj֍q֍]y`ZJt~tT.lT⁋ֳ֒֩]y`ZJֶֶT.lTか]y`ZJ T.lT䁋 7dCd]y`ZJFUFT.lT偋i׀׫׋׫]y`ZJ׎ל׎T.lT恋װ]y`ZJT.lT灋33]y`ZJ$T.lT聋8J؁[؁]y`RJ^r^T.lT運؆ؘآ]y`RJإزإT.lTꁋ]y`RJT.lT끋9b9]y`RJ*T.lT쁋>PuXu]y`RJ[f[T.lT큋zٌٱٔٱ]y`RJٗ٢ٗT.lTٶ]y`RJT.lT99]y`WJ*T.lT>Xڃcڃ]y`WJftfT.lTڈڢڪ]y`WJڭڸڭT.lT]y`RJT.lTG%G]y`RJ(8(T.lTL^ەoە]y`RJrۆrT.lTۚ۱۽]y`ZJT.lT))]y`ZJ + +T.lT.EtRt]y`ZJUeUT.lTyܐܽܜܽ]y`ZJܟܮܟT.lT]y`ZJT.lT  M,M]y`ZJ/>/T.lTRiݒsݒ]y`ZJv݃vT.lTݗݮݻ]y`gJݾݾT.lTT]y`RJ +T.lT0S7S]y`RJ:D:T.lTXjޓtޓ]y`RJwބwT.lUޘު޷]y`RJ޺޺T.lU]y`RJT­.lU,S5S]y`RJ8D8Tí.lUXjߑsߑ]y`RJv߂vTĭ.lUߖߨ߱]y`RJߴߴTŭ.lU]y`RJTƭ.lU&M/M]y`RJ2>2Tǭ.lURdn]y`RJq~qTȭ.lU]y`RJTɭ.lU   ]y`RJTʭ.lU +"Q/Q]y`RJ2B2T˭.lU Vm{]y`eJ~~Ṱ.lU ]y`eJTͭ.lU . .]y`eJTέ.lU3JyWy]y`eJZjZTϭ.lU~]y`RJTЭ.lU]y`RJTѭ.lUD'D]y`gJ*5*Tҭ.lWX-XmXXYKYYZGZZ[[\?\\];]]^7^^_3__`.``a*a~ab&bzbc"cvcddrdeeneffjfggfghhbhi +i^ijjZjkkVkk>U!<z "'z`b)U `+U !`+U "`+UpB`U>=0'U][[[+`U>I! m(+>N5E[GpHfmJ|U n'?JU!U <B<[`UJ + +`U'z'{.nU!@Q1BZ`UJ```U'z'|mumn{no1U"} 窢'~`CU$``:+U*\? C U'"*mpB5m`U">=0>H'U(rz`U"J艜`U"''B'oppoU+2 ף $ .P Y + e'`RU-  ޡ'`:+U.*   +'`:+U044`:`)`)`:+(`:+`U+>N;C\][`:`2E`:`'؁Zqu'قyq'q'qJǜ`U+''qepH'qU29AVpBRVZ`:e.][[[+`U+>I{!퍁r(+>N/[pHrJU5 +rr?J,CU6MrU5ZqBz{[.[`U+J`U+''sbsmU6H1BH[`U+J`U+''CsU8`Jp'q<rUs4sttYU9 .F '`CU?D0D\? ;C U<pB`U9>=0'U=ll`U9J`U9''UB'tu,uU@!: "'`UCpB`U@>=0'UDgg`+`U@>I! v9(+>J.UG8v9?JIXUHUGkzB[`U@J`U@''vUH1B`U@JԜ`U@''uvvwwXUI9 Т'`CUT  7#7\? .C ULRZpBj`UI>=0s}'UMAA`UIJƜ`UI'',B'UNFN_`UIJee`UI''B'UO`UIJ`UI''jB'UP`UIJ`UI'' B'UQ#+<`UIJBB`UI''B'UR\\`UIJᜣ`UI''GB'wx'xxy2yyz=UU-: '``l.UW (`+UX`:+UZ B e'Mxp?p@[+ +U\O$O`J''`'g'U`pB`UU>=0'U] `M`[J&&pCU.BUZUb^ "'\Uc\ "'\Ud"8 "'$8*i`+\Ue= >` k ' ȣ[*`:8`:\>NGN[PpBz}=.B}=}}(UgJUgB ' ң ! -O' \~ "'[[[\Uis5 ڣ  5' Bd5[`:`:\>N[pB~=.B~~̂!~UhJ+Uh:8B ;' Uw  ң' ߣ "'8 [&[-[\z{H{{||R|}~LJ +UjDD`]`[WUkDD`Uj]mj`[Ul5  '`Uk]`[],`[ Uo SpBS`Ul>=0$.'UqX`(g`Jjj`'t'h.UvQQ``[>I`'g'Հ.(Uq=0.?J'.`[' 'N.GUwVdgl`x K`[\>=0'U|   o(  o #K`\>=0 0 :'Ur t }   `[>I   .(Uqw>J  `[' 'z.?=0  ('Us  + + +  +`[>N + +V` + .(UqI +, +4 +0w>J +A +H`[' 'N. +e +ay?=0 +u +('Ut + + { + {`[>N + +V` +.(UqI + +ڀ +n(>J + +`[' 'z.?I   n(=0 ! +('?=0 J T('Ux      ``[J  . =UvUy    "'   ``[Uz    "'   K`:`%s:{:q U}  6 q  '`MU s`EL+U 9 Df r']l`R mY`RUU   pB  `U}>=0  'U;O< < +bg`n!```>Jw~.;BrNUu`!``P>J.tBNU +`U9J  .BMU"?/?`:J22.BMUDOf`:Jii.BMU`:J.BMU`:J.BMU88 K`:\>=.B/MU=Rm/^m],`d>Jaa..BMUr}`:J. BMUK`:\>=. BMU3[ 4V a\>=.pBNU^l^`:\][[[+`>JC5[''.M{RU@~@`:``:+\>J.o 1.N+UBPBsl`R`:>I`'g'>J'I%)`'g'\>Jh'I`'g'>J'I`'g'5>JA'?Jl'U*e  ޣ  '=e]y`RJ@V@U.lU o  o ` #`:+`p>J 6 Aox. Z7 `G=B^JQu U!L!x" !M'`UlU!!"BpB" +"B`U>=0""'U"G"L"b "'"P"b"U``[U"g"n" "'"w""K`:`SU#h#% #i'`CU%%%%%\? %C U##$:pB$$:`U>=0$ $'U$?$G$$V$`UJ$\$\`U''$B'e U&&(T &'` U'`:+U'`:+U'F`:+U'`:+U' `:+U'`:+U(`:+U('`:+U($]`:+U(8-`:+U(J`:+U')'1'pB'L'`U>=0'U'_'DU)/)V*N )0'`UlU))*pB)*`U>=0))'U**5*LB *' "'*:*L*?``PvU335} 3'`UUbA]l`R bel`R'Ue\`Uez`UÁe`Uāe`UŁe`UƁiP "`+Uȁm_ B kJ' + lBld lol ll' ḷl l'[+UɁm `:+Uʁo`:+Uˁo  o'`:+Úp  o'`M+Úq `+U΁rN `:+Uρtg`+UЁu:  u +`V+Uсv`+UӁ6M6c7Q6l7Q6t`:6`+65a`_l\+]`:>J67"6U66!57 1g`:47'7'7L74f`U`:J7<7@7<UUԁ::> :> :`:;][`:`:;`+;7`:+;_][`:`:+;z5a`_l\+]`U>N;;],[1;[=;;4;;<8;`:;K`:`>=;چ;$;;'<<(;xN=<M2<`:`:?=<Ƅ<M'4<<="`:J<'tJ=*=1U=97'E=o-==˄=M·=G5=hUՁHH9O^ H@O^HH`:H[7`:+Hn`+H`:+Hk`:+H][`:`:+H[+H5a`_l\+]`U> NII(]`UI.`UNIQIUf`UI[UIInIyIr(+B>=I';?=II0 IIpR)UII!II(+>=II0 JU?IJ$!J5J((+B>=JJJF0 JYU?IJr!JJv(+B>=JJ0 JU?IJ!J΅J(+>=JJ4JJK<J>`:JK`:`>=KK0 K% +K- Ux?IKJ!KYKN(+>=KyKnKj0 5UK?=KKK0 U4KKNKl`_`>NKK`"KKK0 U̓^7KKK0 Ù7,NKK`L LL0 U(NL=LI`LVLOLK0 U(70NMM`"MMM0 U̓w73NMM0 Ù7IN"""N N N*O N9>=N^NT tNg0 >=NN jN +=NNN0 bUNN jIN!NN(+>=O O0 OU>=O0O,0 UJOCOTOJ uU။OOP<OP<`>NOOf`UOUJP P`'g'րP4TU⁋Q8QHQQ\Q`>NQfQjf`UQpUJQQ`'g'؀QUかRR(RR=R`>NRGRKf`URQUJRdRk`'g'ڀRDU䁋SSSS+S`>NS5S9f`US?UJSRSY`'g'܀SUցTpTYTYT`:T7`:+T`:+]`:> ITTU>JTU,TUU*7U:΂U"Jg`:4U1U1UaU2f`U`:>JUAULUHʹU?NUrU|]`:U`:IUUU:(+B>=U:';?NUUf[Uۜ[''=V[''߄VUV:V&*=V0[''V`UVmEa[`4VVVVl[`>NVV +[V['9'VU=V܃Vt&VV]`:=W[''W5UWBEa[`4WYWYWWZl[`>=WsWijW=X[''XU=Xל[''XU=X[''Y#UIY.!Y;Y2J(+B>=YL[''Y`UYeJ>=Y[''YUJYYYuU偋ZZ]Z]][`:`:>N[:[BL][`:`:2[T`:`:N[`[n`:[u.UI[[[(+B>J[[?N[[],`:[['UF\\ >`:\OA>I\*\5\. `>B\H?N\e\n`\w\p'EI\\\(\W>B\?N\\`:\\Ӄ\X\H!WN]] K`:]] X]%]WHI]1]=]5ρ]I)l>=]`]Yπ]a)$]]r]k]s)m'ن]{mn>=]]π])]mnJ]]Uׁ`Y`^` "'`b``j7`:`y`:`R`+``:+``:+\Uꁋ``a@pBaa@`U>=0aa'U끋ddddd`U>JddUUفdeeFBeeF`UJee`U''U恋jAkkE + jBjd joj jj' j̣jk kE[JkkBk7.BUUځvvw  "'ww \Uہxxx x + "'xx`:U܁yyz yޤ + "'zzz K`:`:U݁{8{{ {9{[ {f{ {{ "'{{{`:\Uށ}}} "'}}}[+\U߁38j "'HjPK`:]K`:\U灋.@{S{]y`RJVlVU.lF g8}i:MU쁋X Y'`RUK]l`_ dl`_'U]l`_ l`_'SU]l`_ l`_'U1]l`_ Ll`_'U]l`_ l`_'U%]l`_ l`_'U3]l`_ Nl`_'UBpB +B`U>=0'U]y`_JU.lUVpbx]y`_J{{U.lU]y`_JU.lUo@i + p  ˣ' Ji]y`_JMZMU.lU ]y`_JU.lUS$O5 Tv  ѣ' ޣ/O]y`_J2@2U.lU]y`_JU.l%xk^V '`UVRZpBm`V>=0v' XV '`C V`:+V`+V`+V + B t' ' '[+V k`:+V `:+V K`:+V%`:+VK `P+V^`:+Vm`:+V`:+V\? C V RpBR`V>=0#-'VW_l`VJrr`V''B'V$o2o`lJ;;B\.BV + XVah b'`V: `+V *pB*`V>=0'V"IPf "']f`[_V# '`V%U `+V&j `+V)FpBF`V#>=0!'V+tyw "'~\TV,d e'`V.s `E+V1ZpB"Z`V,>=0+5'V3~ "'`V#\-yV4 '`V69 (`Y+ V9 [pB#[`V4>=0,6'V:`ht(`Y`V4>JV=V=B([`V4J휣`V4''VAC]q]`^J}}B`^['' .VBL +L]][`:[JB'['' .VCQe n]`V#JzzB`V#['' .VDWW][[[][>N[pHmJ.5.BCV>V>\{B ]' "'[][VE][[[+][>I!R(+>N[pH'RJ=D.BQV??Jmt.BV@V?B ' "'[][V@B С' "'][b$C(I VF '`VH  >' c'`%+VI `+VJ `+VMT\pBg`VF>=0pz'VN[=`Q`+`VF>I""%`%`(+>J$5VQ?`K`?I`""%ne`%z`%(+>JVR`%`?I""%`% +`%!`%>J?PVSZ`%f`p`?=0'GVQ<B<[=[`VFJ`VF'''3VR@Q1BZ[[g=[`VFJzz`VF''8CVS8B8[=[Q[`VFJ`VF''+5Y +VT  '`C`lVV<`:+VWR`:+VX t`+VY`:+VZ `:+V[#`+V\3 `+V]G `+V^c `+V_{`:+V``:+Va`:+Vb`:+Vc `:+Vd`+Vl\? C VgDLpBZ`VT>=0cm'Vh`:+`+`+`VT>Nl`VT蜣`VT'!'?B'IU!]Yj(+B=hf£njVa?Iw!{z(+=£zVd?I!Š(+=£ŠV[?J£Vj][JB[[''".@ÜVm$E# '#`Vo3 $`+VrpB`Vm>=0'Vs   %][[[+`Vm>I&!9*(+>NN_&[apHJVv?JVwVv.B78%[`VmJKK`Vm'#''łVw#1B#`VmJ圣`Vm'#'(NĚTŹ +Vx Bg) !'*`C`V`V`V`V`V`W`W`W"`W+`W4`W=`WF`WN`WW`W\`Wb`Wh`Wp`Wy`W`W1VzAm`:+V{S<`:+V|b+`:+V}|`:+V~`+V`:+V`+V,`+VA`:+V-`:+V `+VWu ' 6'],`SP+Vs `T++V`:+V`:+V`:+V`+V`:+V`+V.`+V/`+Vl  )' E'],`[+V `C+V `:+V0`+V`:+V*`+V`+VK`:+Vr`:+V`:+V%`+V7B`+VK1`:+Vf2`+V{3`+VB`+V`:+V3`:+V`:+V `:+V `g\+VK`:+V 4B y'5 '[+V6`+V1 2 '7 ƣ ],`Ry+V >'8 [} `+V`+V `+V  5!5\? ,C V`:+`Vx>Nl`Vx&B'N,`VxI:!C>P(+B>K>=iPV[p[>?JiV\pB$\`Vx>=0-7'V,t58t`JAApJc.4BVV,5,K`\>=.9BpK"VV159BERK[\>=_['7':.9V  "' `V- "'$-`V27F1 "'=F\VKPv "'aviS`:\V{€; "'Œ”`:¬`+·y`+<`:+\V#= "'#`y``:+\V(-E> "'5E;`+\VJOe? "'Ue[`+\&Rͦ fΡX3z Vzĉ@``PVÁĶ`+Vā`+VŁ.`+VƁ/`+Vǁ#K`:+VȁsK`:+V\? Vʁ],`[Vˁ,7HHH`:V́M_ggg`g\V́}ņŒŒŒ`VρŗŜūũū`VЁŰŵS`:\ <mҞ +VӁ)8ƭA``VVՁksƫƅƫ`VJƋƏV'CSӛVցZB``V +V؁@`:+VفU0`+Vځjr`:+Vہ}`:+V܁ǒ`+V݁ǤB`+VށǵB`+V߁1`:+V2`+V။3`+V\? VかǾ1\V䁋X=0X5`@y`M`:+\cV灋+9C ,N Wy Ƀɥ' ɰң``VV運l-`:+V끋 (`:``VJ@DV'-V큋xʄʈʈʈ`PV77`>J(#V'-V('-BFwVjyD``VV-`:+Vˮ˶`VJV'V`P2z׫V̖T΂E ̗̹ £ ' =``VV͈͐͟`VJͥͩV'V`PV(8΀B΀`>JHtoTV'V('B/wبVϐNшF ϑϳ ϼޣ  +' 7``VVЈАХ`VJЫЯV'GW`PW.>цHц`>JNzuZV'GV('GBٗwWԲH 5 >` jҌ' җҹ``V WP`:+Wf`+WӍ0`+WӠ`+WӴr`:+W `:+W +`+W B`+W B`+WDD`WJ%)V'IWtӀӄӄӄ`PWTd԰n԰`>JtԢԝԀV'IV('IBGܮWՀJ``VW:B~V~`WJ\`V'3W֞K``VW0 `:+W?`:+WN3`:+W[6`+W!\? W $$$`PWmrփ>zփր`+\Wֈ֍֜?֓֜֙`+\WޔW"&fL 'I' +``WW$5`+W%`+W& B`+W(לפ״`W"J׺׾V'yW*fv؀`>J؆سخؒV'yV('yB+sW+X٘M Y{' +``WW-5`+W.0`+W/BB`+W1  `W+JV'~W3ڛګڵ`>JڻV'~V('~BmW4ۡ=N ۢģ' +``WW6a5`+W7v`+W8܈B`+W:S/S`W4J59V'OW<;;`>J.) V'OV('OB^W=tP ߣ``WW?ޘ5`+W@ޭ`+WA޿B`+WCNVފfފ`W=JlpV'|WE(r2r`>J8e`DV'|V('|B6WF4tQ 5W' +``WWH`+WI$B`+WK`WFJV'RWM}`>JV'RV('RBaWNS 8 Ac h⊣``WWP%`:+WQ:`+WRLB`+WT`WNJV'WV`>JV'V('B|+WW7[T ѣ '``WWYnv`WWJV'W[ YY`>JKF)V'V('B:W\U``VW^w`+W_B`+Wa)1mEm`W\JKOV'VWb&5W``VWd`+WeB`+Wgmu`WbJV'XLWh)Y``VWjm`:+Wk`+WlB`+Wmu],`SP+Wo`h~`WhJV'+sWp-<.Z``VWr`:+Ws`:+Wt`:+Wu`+Wv"`:+Wxu}`WpJV'cWy[``V W{)<`:+W|8`:+W}N`:+W~e`:+Wy`+W`:+W`+W`:+W`+W`WyJV'qgW\``VWOWn`WJtxV'+,WK]``VW I#I`WJ)-V'aW&D^ ''^`RWpB`W>=0'W +  +`:.][[[+`W>I5!G9k(+>N\l/[npHkJW\?JW\W"B+,[2.[`WJJJ`W'^'_v<|GW1B[`WJ򻜣`W'^'`Wa \][[[\>N *[,pHK=Y.bBq-WJWbB 'a "'\[\3uWc 'c`W L`P+W% d`:+WD e],`+WFNpBd`W>=0mw'W^],[`W2WB\\][[[+`W>I! (+>N!+[-pHLJ\xW؂:?JWW|B|[ \[`WJ`W'c'fd΁tW1B[`WJ`W'c'gFWSXkh "'bk\Wpu "'|c`P\Wi "'],`WW "'c`P\c};W4_ j 5'j`W? k`O+W` l`+W m`O+W n`+W o`O+W c`P+W |`+W$pB$`W>=0'zW p 'p``bW `+W `:+W s`:+WnvpB`W>=0'IW  +q 'q`fSW r`+W `+W s`W It`W }u`WÁ v`Wā w`+WƁ xB '`+Wȁ & Q`:+WɁ : y`+Wʁ Q z`+Wˁ n `:+Wǁ {B w'r`+Ẃ `+Ẃ |`+W΁ }`+Wρ ~`+Wс   A  A + `: 0`h+ A`) ]`) y`+ `+ y`* w`* ~`* |`*`W>I * 3 .(+>= D KB?=# f ](+ ]5` j# v +(+ +`+`N  l`W&   BB'qN`W=   +B + +  ƃ ց '     & '6 WJ 5 < +Wց F K B ] + + + l`: }` ` `h `: ` y` w` ~` )|`\>I 8 <`'g'.>=  [ '7'. Ձ    / > 'M 1\ >=  [ '7'. Ձ   . > W k/ ~> M \ Wہ  `J  .BfYWӁ + + pB +  +#`: +..][[[+`W>I +D! +V +H(+>N +k +{/[ +}pH +J + +W +ւ +"?J + W Wׁ  4 B =  >[ D.[`WJ \ \`W'q'  W؁ 1B  [`WJ  М`W'q' /Wف  ) "'  ) `:`}bfW܁  &  '`WW߁   pB  `W>=0  'W      c`P ` #\`+`W>I 3! ? 7(+>J P fW p{ x ?J  W { Wか   XB  X c[ [ \[`WJ  `W'' @S H^ PiW䁋 \ r 1B {  |c[ [`WJ  `W'' ߁ R%*W偋    '`CW聋 L T pB l `W>=0 u 'W運      c`P ` \`+`W>I !   (+>J " @W J R Z?J n W  W쁋   jB  j c[ [ \[`WJ  `W'' F T̂ bW큋 n  1B   c[ [`WJ  `W'' M  +XtW    '`CW  K`+W     \? C W g o pB z `W>=0  'W   ,  ,`WJ  Μ`W'' B'2~W   z '`CW C `C+W a `T++W q`:+X   ,  ,\? #C W l t pB  `W>=0  'W   S  S`WJ  ٜ`W'' ;B':X U x  V'`CX  `T++X + s s   \? C X   %pB  %`X>=0  'X * 2  ? `XJ E E`X'' B'pX # '`C(X !) !1 !pB !K !`X >=0 !T !^'X ! ! " ! " !][[[+`X >I !! !ր !'(+>N ! ![ !pH "'J "2 "RX "\d?J "x "XX " " #JB " #J "[`X J " "眣`X '' #<X #N #n #1B #w #`X J # #`X ''nX $ $ ( $'`CX &9`:+X &`:+X '`+X '`:+X '*`:+X 'F `M+X 'X`:+X 'mB`:+X '~`:+X '`:+X ' `P+X! '`:+X" ' `d>+X# ' `P+X$ (`:+X, & & & & &\? &C X' % %% %jpB %2 %j`X>=0 %; %E'X( %o %w % % %`XJ % %`X'' %B'X* (\ (e ( (t (`>J (z (`'g'. +J + + >X- ) ) , )'``l) +X/ *  *`' *'],`:+X0 *`:+X1 *`:+X2 *F`:+X3 *`:+X4 +`:+X5 +"'`:+X6 +2]`:+X7 +F-`:+X8 +\`fL+X; * * *ZpB *" *Z`X->=0 *+ *5'X= +l +q + "' +w + +`:+\X> + + + "' + +\X? + + +  "' + + +`:\XB + + ,s + ,s`:>I + +ꜣ`'g'.>J , ,`:'9'.?J ,H$ ,o ,W.]X6' ,i.X1X@ ,x , ,A , ,`:J , ,`:'9'.    W 3XC - - 0@ -'`b)XE 0 `+XF 0- !`+XG 0= "`+XJ - . .MpB . .M`XC>=0 . .('XK .R .Z /M .f /M .l][[[+`XC>I .! . .(+>N . .[ .pH .J . /XN /?J /* />XOXN /Q /e /B /n / /o[`XCJ / /`XC'' /KXO / / 01B / 0`XCJ / /朣`XC''cXP 1 1; 3 1'`CXR 3  3=' 3_'],`[+XS 3K`:+XY 3 3 37 3# 37\? 3.C XV 1 1 1pB 1 1`XP>=0 1 1'XW 1 1 2` 1 2``XPJ 1 1`XP'' 2PB'IXZ 4~ 4 7: 4'`X] 5 5 5VpB 5 5V`XZ>=0 5' 51'X_ 5[ 5b 5 5n 5 5s][[[][>N 5 5[ 5pH 5J 5 5.B 5XaXa 6 6" 6GB 6' "' 61 6G 62[][Xc 6L 6S 6 6_ 6 6d][[[][>N 6} 6[ 6pH 6J 6 6.B 6XbXb 6 7 78B 6' "' 7" 78 7#[][bGXd 8 8< 9H 8'`Xf 9 `+Xg 9' `+Xh 9= `+Xk 8 8 8pB 8 8`Xd>=0 8 8'0|Xl :# :D ;W :$'`Xn ; `:+Xo ;! `:+Xp ;: G`:+Xq ;P `:+Xt : : :pB : :`Xl>=0 : :'`Xu <2

P <3'`RXx < < <pB < <`Xu>=0 < <'Xz = = = =. =]],`XlJ =: =:B],`Xl =l[''.X{ = = > = >][[[>J = =pG =.BX}X} > >+ >NB >' "' >E >N[UX~ ?+ ?Y H ?, + ?8'`C+X @`X A`X AH`X Ar`X A`X A`X A`X B `X B5`X Bd `w+X By`+X B `e+X B`+X B `P+X B`:+X B `:+X C`+X C&`+X C;`+X CX`+X C| t`+X C Q`+X C S`X+X C`+X C `Y+X C`+X C `+X D F`+X D)`+X DK `e+X D]`:+X Ds "`+X D p``X+X D `e+X D x`+X D `:+X D`:+X E +`Y+X E, `eh+X EP `g+X Ed`+X E  Ep' E E Eƣ E`+X F  F' F@ Fb Fm F`+X @ @ @ @ @\? @C X ? ? @pB ? @`X~>=0 ? ?'X F F G "' F G FG`: F`:+ F`:+`e1X G G" GU G + "' G- GU G5`: GC`:+`:X GZ Gf G| "' Gs G|`YX G G G "' G G\X G G GZ "' G G\X G G G G G][J G GB[ Gќ[''.X G G H^ H H^ H `Y][J H! H!B[ H1[''. HSX Hc Hj H Hs H H{`:][J H HB[ H[''. H}VS X I I L I'`RX L `+X L `:+X J# J+ JxpB J@ Jx`X>=0 JI JS'X J} J K J K J`: J.][[[+`X>I J! JӁ J (+>N J J/[ JpH K J K/ KJX KT KZ! ?J Kv KX K XÁ K K LLB K LL K[ K.[`XJ K K圣`X'' L2! L>!Xā LP Lk L1B Lt L Lu[`XJ L L`X'' L" L !s!"QXŁ M N O Mۤ + M'`Xǁ N`Xȁ N`XɁ O`Xʁ O?`Xˁ Om Q`+X́ O `:+Xρ N] Ne NpB Nq N`X>=0 Nz N'#-#yXЁ Pg P R Ph'`RXҁ R `+XӁ R `:+Xց P P QBpB Q + QB`X>=0 Q Q'Xׁ QG QO R Qc R Qk`: Qu.][[[`X>N Q Q/[ QpH Q$gJ Q QX Q$X Q$Xځ R R3 RB R< R R=[ RC.[`XJ RU RU`X'' R$ R%#$/$%EXہ S S W S֢'`RX݁ T]l`Y Tl`Y'Xށ U `+X߁ U `X+X U `:+Xか TV T^ TpB To T`X>=0 Tx T'X偋 U' U8 Uq U? Uq]\J UB UBB\ UX[''.X聋 U U Vw U V][J U UB[ U[''.X運 V V V V) V V1`: VP[][J Vc VcB[ V~[''. V'$ V'3Xꁋ V V W V W V`:][J V VB[ V['' . W'X끋 W$ W+ Wb W1 Wb][J W7 W7B[ WG['' +.X큋 Wg W WB Wh' "' W W W +[][X恋 W W W W W]y`YJ W W WXݭ.l&&M&&'}'(C((X X X Z  XТ' `X Y B`+X YT Y\ YpB Yo Y`X>=0 Yx Y'X Y Y Y "' Y Y Y [`X Y Y Z "' Y Z Z [`)^))*5X Z [ \  Z' `X [ `:+X [| [ [pB [ [`X>=0 [ ['X [ [ \H \ \H][J \ \B[ \$[''.X \M \Q \ \a \][[[>J \j \qpG \.BYY \ \ \B \' "' \ \[**+3++Y ] ] `  ]Ǣ'`Y ^; ^C ^pB ^N ^`Y>=0 ^W ^a'Y ^ ^ ^B ^' "' ^ ^ ^`:+`XY ^ ^ _a ^ _a _`Y ][J _! _!B[ _1[''. _Y,Y + _f _m ` _ ` _[][J _ _B[ _ʜ[''. _-c,!,m,-9-Y ` a b `'`Y b `:+Y ae am apB a~ a`Y >=0 a a'Y a a bF a bF a][[[`Y >N a aQ[ apH b.xJ b b1Y b;.Y bJ ba bB bj b bk[`Y J bz bz`Y '' b/..O./9Y c c e c + c'`Y d (`+Y d `:+Y d- d5 dxpB d@ dx`Y>=0 dI dS'Y d d d! "' d d d"`:\Y d d d# "' d d d"`:\Y d e e "' e + e e``:/00H00Y e f h$ e'$`Y" h~%`:+Y# h&`:+Y$ h'],[+Y% h`:+Y( fv f~ fpB f f`Y >=0 f f'Y) f f g f g f][[[+`Y >I f! g f1(+>N g g#([ g%pH gD1J gU gjY, gt20?J g gY-Y, g g hB g h g[`Y J g g圣`Y '$') h2Y- h h3 hr1B h< hr`Y J hH hH`Y '$'*1~1223:Y. i i k+ i + i'+`RY0 j4]l`R jl`R'Y1 j L`+Y2 k B`:+Y5 j j' jopB j7 jo`Y.>=0 j@ jJ'Y7 k k k<, "' k k< k,^`RB[\Y8 kA kF ks- "' kT ks kc^`RB[\Y: kx k k k k]y`RJ k k kY0.l34:4456Y; l l o. l'.`RY= o L`+Y> o B`:+YA m m mfpB m. mf`Y;>=0 m7 mA'YB mk ms n m n m`: m.][[[+`Y;>I m! m m62(+>N m m/[ mpH n62J n n8YE nB6# nH6o?J nd nYF n6#YE n n o:B n o: n[ n.[`Y;J n nӜ`Y;'.'/ o 7 o,7YF o> oY o1B ob o oc[`Y;J or or`Y;'.'0 o7|5567N7YG p p v 1 p'1`RYI q]l`R ql`R'SYJ rm]l`R r5l`R'ZYK tP 2`+YL tt k`:+YM t M`:+YN t `Y+YO t 3`+ YR q7 q? qpB qN q`YG>=0 qW qa'YS r] re s_ rr s_ r`Y r\][[[+`YG>I r! r r9U(+>N r r[ rpH r9UJ r s YV s9F s9?J s5 sJYW sT9FYV sc sx sB s s s[ s\[`YGJ s s`YG'1'4 s:% s:0YW s s tA1B s tA s[`YGJ t t`YG'1'5 t::YX t t u6 "' t u t`:`YY u + u uZ "' u u\YZ u" u' u;7 "' u2 u;\Y[ u@ uE uT] "' uK uT\Y\ uY u^ u{ "' uc u{ ui8`+\Y] u u ui "' u u\Y_ u u ub u u]y`RJ u u uYI.lY` u u v +T u v +]y`RJ u u uYJ.l899:o:;;U;;< +=0 w w'Yi w w x=; "' w x= x`: x(^B\\=~=>&Yj zH zl {\< zI'<`Yl {2 `+Ym {D `+Yn {V 3`+Yq z z {#pB z {#`Yj>=0 z z'>>Yr |7 | = |8 |Z |c |' |'=`RYt ~ >`b+Yu ~t`+Yv ~ "`:+Yw ~ ?`b+ +Yz } } }UpB } }U`Yr>=0 }& }0'Y{ }Z }b } }m }`Yr>J }v }Y~Y~ } } }B } }`YrJ } }`Yr'='@Y ~) ~9 ~j ~C ~j`J ~F ~F`'g'AY ~  $B "'  $ `:`bY ) . MC "' D M\Y R W yD "' b y kS`:+\Y ~  6 "'   `:`Y   E "'   `b\Y   F "'   ` y`\?@@I@@A1AhAAB>B +Y C G   ''G`RY H]l`R l`R'IY #J]l`R Bl`R'KY U L`+Y m .`:+Y pB `Y>=0  'Y p x   M[+`Y>I  D (+>J  Y?I %  D `Y>J  0Y :D `Y?I W% m \D ],`Y>J  Y D ],`Y?=0  'GY  & [B / [`YJ 5 5`Y'G'NY _ r 1B {  |M[`YJ  `Y'G'O EpY EB E M[`YJ  `Y'G'O 4EY t y P "'  (`Y\Y  "' `YY , CQ š'R ' "' : C],`YY H Y |S "' e | mT`:`YY U "' ],`YY  .V 'R ' "' % .],`YY 3 8 bW "' C b U(`Y\Y X ]y`RJ   Y.lY . @ qY N q]y`RJ Q b QY.lY    `J # #`'g'Z  B[h?  B[h?  B[h?  B[h?CCDEBEF FRFFG4GuGHHlHI]Y ' \ ۣ '\`RY `Y+Y pB `Y>=0  'Y   `: .][[[+`Y>I ! , J(+>N A Q/[ SpH rJJ  Y Jq J?J  Y JqY  B   [ #.[`YJ ; ;`Y'\'] oKQ uK\Y 1B  [`YJ  `Y'\'^ KY 4 D  N `J Q Xp'\IJHK#KLLHY z _ { '_`R +Y uP]l`R l`R'QY `]l`R l`R'aY b]l`R l`R'cY +d`:+Y @`+Y Y .`:+Y m G`:+Y `:+Y `+Y "`:+Y ( 0 zpB B z`Y>=0 K U'Y e  f][[[+][>I ! NQ(+>N  "g[ $pH CNQJ W ^.hB rNY?J  .iBYY hB 'e "'  f[][Y  & BiB 'e "' 9 B][YŁ G X f "' ] f`YYƁ k o j ~ ][[[>J  pG .kBYY kB ̡'j "' [Yǁ  al  a][[[>J # *pG I.mBYYÁ f mB g'l "' [Yȁ n ][[[>J  pG .oBYYā  )oB 'n "' )[YɁ . 3 @i "' 7 @\Yˁ  ]y`RJ   Y.lÝ   ;p  ;]y`RJ " , "Y.lÝ q ]y`RJ   Y.lMN'NOHOOP-PvPQQyQQRMRRY΁ r  Ƣ'r`RYЁ (`Y+YӁ L T pB k `Y>=0 t ~'Yԁ v v `: .][[[`Y>N /[ pH !TJ 5 RY \T bT4Yׁ z $B $ [ .[`YJ  `Y'r's +T TYف i y  `J  p'rSST}TU=Yځ t 't`Y܁ u`+Y݁ v`+Yށ w`+Y။ 5 = pB I `Y>=0 R \'UVY⁋  -x 'y`CY聋   +  +\? "C Y偋 q y pB `Y>=0  'Y恋 S S`YJ  ܜ`Y'z' <B'{VVW1Y運 7 c | 8 + D'|`Y끋 }`Z +Y쁋 ~`Z +Y pB `Y>=0  'Y   [ - [`Y>J 6 LYY _ u B ~ `YJ  `Y'|'WWX;XY   '`RY g B ' p? .p@[+Y  o +`:+Y `:+Y X B '6 ' )'[+Y u `:+Y 3 ;  G  O`: a`* ~`* `+ `:+ `:+ 6`h+ ],`Z : `Z `Y>I  * #Z#(+>= ;Z# DB?I V! bp>J  Ӝ +`Y +'' rYÁ Yӂ Y Y Z Z Z# Z3?N  $`Y&  / &BB'N`Y= W Q[B iYÁ oYӂ zY Y Z Z Z# Z3ZJ  [Z  [J  pC .BYY u } pB  `: .][[[+`Y>I ! Ɓ \E(+>N /[ pH \EJ " 6Z @\6 F\?J b vZ \6Z B  [ .[`YJ  ɜ`Y'' ] ]!Z ! i1B * i +[`YJ : :`Y'' d]Z 6 `RJ  B .BYZ CB C i`: ` ` ` `: `: A`R d],`Z \>N x `R B ^= .B ^H ^W ^f ^u ^ ^ ^ *^ZJ 9Z H k B I' "' ~  i[ [ [ [ [ [ [ ],`Z \Y[\ \]a]^_Y`Z  - F  + '`RZ >]l`Y Yl`Y'Z Q V  f  n`: ^`RB[ `+\>I K T O`('B>= j.HBZ?=  `ā `ӂ `RZ ?pB  ?`Z >=0  'Z w "' \Z   [ ],`+\>I ! b(+>N  [ pB ;b= K.B ZbZ ebZJ v?N [ pB b= .B bZJ Z  QB ' "' * Q +[ A],`\Z U s B V' "'  [\Z HB ' "' \Z   D % D]y`YJ ( 5 (Z .l`agaabc^ccdOZ " C  #'`CZ e`:+Z x`:+Z K`:+Z# 2 2 Y E Y\? PC Z pB `Z>=0  'Z!   `ZJ + +`Z'' jB'e&ereZ$ n z o'z`Z' B ”' ²'[+Z( B`+Z+ +pB +`Z$>=0  'Z- 0 =  N `J W WpJ y.BZ'fTffZ. Ž Ȯ  0 9 [ e Ň Ő + Ŝ'`CZ0 `+Z1 d   + !' ='],`[+Z2 s`+Z3  `+Z4 ȋ`+Z5 ȗ`+Z6 ȧK`+Z> W W  k \? vC Z9  " hpB 0 h`Z.>=0 9 C'Z: m u Ʀ Ɓ Ʀ`Z.J Ƈ& Ƈ Ɛ ƇB'N,`Z.Z<  `J  R'h~hi&imZ? ɉ ɥ ʨ Ɋ'`RZA d `Z[+ZB ʃ `Z+ZC ʚ `+ZF  LpB  L`Z?>=0  ''ijDZG ˃ ˨ ξ ˄'`RZI θ '`Z+ZL   [pB # [`ZG>=0 , 6'ZM ` h ͇ { ͇ ̃`: ̎.][[[+`ZG>I ̤! ̶ ̨k(+>N /[ pH kJ  -ZP 7k =kY?J Y tZQ ~k ZP ͋ ͦ /B ͯ / Ͱ[ Ͷ.[`ZGJ  Ȝ`ZG'' k !kZQ 3 N Τ1B W Τ X[`ZGJ g g`ZG'' Οlfjjkl8lZR ϙ ϴ K Ϛ'`ZZT []l`Zq zl`Zq'ZW  VpB  V`ZR>=0 ' 1'ZY  I I]y`ZqJ ) : )ZT.lmmdmZZ Q Q`]`:[mZ[ & D ٱ ''`ZZZ^ pB `Z[>=0  'Za   rB  r '`:][[[J 5 5pG T[''. mnZb w |  Ԃ  Ԙ s][`:[\>=0 ԥ ԯ'Zc 5  K[`J   .Zm-4   +l][[[`J   o( oqZd % V 0 V 9[`J A! O A.B& J Jp `:Za(+Ze [ h Ո j Ո s[][[[J { {.B& Մ Մp`:ZaZf Ս Ւ  ՙ  ՟a`:[ˁK\\>N 2[ ќ[''2.C )>N [ ['' &q$I 6 :`'g' OqMJ W?= f eq g`:'9' ւqM ֔pG ֳ['' qMZl O O]`:>N  +],`:1 `:= .4 $ $ 9 %+`: ([\J . 3 .r6 7ry;ZfJ @ Gr6Zm T f  m ]][[[>N y ׀],][[[1 ׇ][[[= ׏.4 ח ח ׮ ט+`: כ[\J ס ר סs& ׬ ׬sf][[[;ZfJ ׵ ׼sZn ( `J  ݜ`'t'7.Zo    `J   .(Zn(Zp  ( >C 3 >`J 6! 7. ZoZg C Q إ T إ \ `: i K[\>=0 v ؀'Zh ت ز  ؽ  `: a[[>=0  'Zi   h % h .[`:>=0 9 C'Zj m r ٯ  w ٯ\>=0 ـ ي'n+nwnoGopppqrst t]tuubuuZq ڌ ڮ ݑ ڍ'`RZs ݋ `+Zv  [pB # [`Zq>=0 , 6'Zw ` h ~ x ~ ۀ`: ۋ.][[[+`Zq>I ۡ! ۳ ۥw(+>N /[ pH wJ  'Zz 1v 7wK?J S kZ{ uvZz ܂ ܚ +B ܣ + ܤ[ ܪ.[`ZqJ  œ`Zq'' w߁ wZ{  & v1B / v 0[`ZqJ ? ?`Zq'' qxXvvwx*xZ| l ވ d m'`ZZ ,pB ,`Z|>=0  'Z 1 6 b "' : b E` PC`+\xy%yyZ l l`]`:[yZ ? ^  @'`ZZ *pB *`Z>=0  'Z / 3 B ;  C`:][[[J Q QpG p[''. zfZ   s][`:[\>=0  'Z 75  7 K[`J  ! .Z-4 % % 6 &l][[[`J , . ,{t( 1{2Z < A r L r U[`J ]! k ].B& f f{`:Z(+Z w   [][[[J  .B&  |Z`:ZZ   a`:[ˁK\\>N 2[ 휣[''2.C )>N ' -[ /['' B|I R V`'g' k}J s?= む |ǀ ボ`:'9' } pG Ϝ['' }Z  k  k]`:>N ! &],`:1 0`:= 8.4 @ @ U A+`: D[\J J O J} S~:;ZJ \ c}Z p  ]][[[>N ],][[[1 ][[[= .4   +`: [\J  Ā ~π&  '][[[;ZJ  ~Z ( `J  `'t'7.Z  6  ( 6`J + 2 +.(Z(Z ; D ZC O Z`J R! S. ZZ _ m  p  x `: K[\>=0  'Z / / `: a[[>=0  +'Z 4 ;  A  J[`:>=0 U _'Z  \>=0  'yz8z{{|1|}~~b#wZ  穢'`RZ w `:+Z .`:+Z `:+Z K`:+Z M`:+Z `:+Z  `:+Z  # epB - e`Z>=0 6 @'Z   Pw P][J & &B[ 6[''.Z U \  ` ][J f fB[ v[''.!wZ l  m'`Z ; `:+Z X `_+Z w `:+Z `:+Z )pB )`Z>=0  'nZ `]`ZZ `Z]mj`Z"Z r  s'`Z],`Z]`Z Z n v pB `Z>=0  'Z ( `J  Ԝ`'t'h.Z     ``Z>I  `'g'Հ D3 K3 R3 Y.(Z=0 h r 3.?J  `Z''N. 3Z E E ` K`Z\>=0  'ZÁ (  K`\>=0  'Z ~  ~`Z>I   .(Zw>J ( /`Z''z.?=0 W a('Z * *`Z>N V` .(ZI  Fw>J  Ҝ`Z''N. Fy?=0  ('Z / <  C `Z>N M QV` X.(ZI d l h(>J z 񁜣`Z''z.?I  (=0  ('?=0  ('Z   B ( B -``ZJ 7 ;. <ZZ j s  "' w  |``ZZ  "'  K`:`Zp +4R Zā a + '`CZƁ G`:+Zǁ W`:+Ź   ; ' ;\? 2C Zʁ  dpB , d`Z>=0 5 ?'sŹ l + 2 m'`fSZρ w`+ZЁ `+Zс L`+ZӁ  B '`+Zԁ I B +'`+Zށ a y`+Z߁  z~`[+ZՁ B '`+Zց B ͡'`+Z  |`+Zׁ . B '`+Z؁ ^ B >'`+Zف B n'I`+Zځ B 'J`+Z။ `:+Zہ + B +:' +U' +h'[+Z܁ + B +'K`+Z݁ + B +ۡ'L`+Z⁋ + ~`+Zか +?  +'~`[+Z偋   `: `h+ ` K` L` 0` F` \` r`) `) y`* w`* ~`* |`* `R+`Z>I 4 = 8(+>= N UB?N r x`Z& r  zBB'N`Z=  B  b r    &" 72 HB Y + j  z   R ZJ  Z灋 pB  `: .][[[+`Z>I ! % K(+>N : J/[ LpH kKJ  Z < ?J  Z <Zꁋ ^B  ^ [ +.[`ZJ " "`Z''݀ J P'Z끋 b t 1B }  ~[`ZJ  `Z''ހ Z +5 +5`RJ  B +".BZZ +M +R +x "' +b +x +j`:`Z쁋 +} + +:B + +: +`: +` +` +`h +` +K` +L` +&` +9` +My` +aw` +t~` +|` +` +`R\>N + +`R +B +j= +.B +1 +? +P +dń +rԅ + + + + +  +. + +=  +L  + +[  +ZJ +0Z큋 +? +` +bB +@' "' +q +b +y[ +[ +[ +`h +[ +K[ +L[ +[ +[ +y[ +w[ + ~[ +0|[ +?[ +M[\Z +g +q + +x +]`J +{ +` +.BZ +.BZZ + + +/ + + +ˣ + + +/]`J + +` +.BZ +$.BZZ +& +0 + +>e +7 + +>]`>I += +A`'g'.>N +n +p[ +r['t'.N + +![ +['t'.J + +ͼ`& + +`& + +`>I + !% + * + #.cR`P>=0 + A + K'?N + + c`P& +  + .cR`PN + + ]` +  + .Zy +  + ڀ + S?RAJ + + + + ` + + + + + +} + +, + +* + +$}!Z + +C + +M + +t + +T + +t]`J + +W + +[` + +a.BZ + +k.BZZ + +y + + + + + + + +]`J + + + +` + +.BZ + +.BZZ + + + + + +y + + + +]`J + + + +¼` + +.BZ + +.BZZ + + + + + 0 + + + 0`LJ +  + `L''.g jYKD$eZ + + +2 + ~ + '`RZ +`Z +`Z +`Z + `+Z + `:+Z + q`:+[ +7 `:+[ +P `[+[ + +( +opB +7 +o`Z>=0 +@ +J'[ +` +e +0 "' +v +0 +`: +` +` +`[ +`: +q`: + +`: +`\6[ + + +Z + +0 +9 +[ +e + +'`[ + +B][`:`; +`:`')')')')')') [ + + + h "' + + \[ + + +B + + +!c`[ +.\][[[+\>I +>! +J +B(+>N +_ +i[ +kpH += +.B + +T[J +?= +.B + [J +[ + + +9B +' "' + +9 +"c`[ +*\[\[ += +W +uB +>' "' +a +u +gc`[\[ +z + +i "' + +],`[[ + + + +) +`>J +/ +6`'g'[ +( +- + +4 + +:c`[ +N`+ +d`+ +{`+ +`+ +`+ +`+ +],`:+\> +N +: +H[ +J[O + +&a[[` + + +[ +K[`>I +! + + (+= +[ +& + + +`: + ?= +  + ' +N= +1 +) ' +@^= +Y +Q ' +kn= + + ' +~= + + ' += + + ' +I +! +) +(+>= +B +: ' +V[ +a?= +.B +> +[[ + + +B + +[J + +[''J[ + + +#B + +# +[ +`: +K[[>= +['7'2 +P +[ +j[ +( +/ +GB +9 +G +:[[J +C +C[ + + +B +' "' + + +c[ +\[\[ + + +X + +X +^],[`[gWB\`[>= +N[''}J + +`['$'' +Ea],[`[\ +6C],[`[ +Fz,"Q [ +5 +U + q +6'` [ +M  + +' +&'],`[+[ +i `:+[ + `:+[ + +`[+[! + `:+[" + `[+[# + 7  +' + '],`[+[$ + S c`[+[% + k `:+[( + + +pB + +`[>=0 + +'[) +!L +!v +#+  +!M' `[, +! +! +"9pB +" +"9`[)>=0 +" + +"'[. +"> +"E +"~' +"L +"~][J +"R +"RB[ +"b[''.[/ +" +" +") +" +"][J +" +"B[ +"[''.[0 +" +" +#) +" +#)]][`:[J +" +"B +# [''.kz[1 +$ +$! +>/ +$'`[w`[}`[`[`[q`["[3 +0 `j+[4 +0 `j+[5 +0 `[+[6 +1 `F+[7 +1. `+[8 +1L `:+[9 +1{  +1\ +`Tv+[: +1 `+[; +1 `XZ+[< +1 `Xu+[= +2 `Ya+[> +22 `Z+[? +2K `j+[@ +2e `^+[A +2 `_Z+[B +2  +2 +`:+[C +2 !`bM+[D +3 w`d+[E +3. " +3 +`:+[F +3T # +3: +`:+[G +3k $`f+[H +4 % +3s'& +3 +3 +3ţ +3`M-+[I +4 ' +4%'( +4I +4k +4v +4`M-+[J +< )`+[K +< * +< +`+[L +< +`:+[M += ,`:+[N +=/ -`:+[O +=I .`+[P +=f `:+[Q += / +=t +`:+[R += 0`:+[S += 1],`:+[T +>' 2 +> +`+[V +$ +$ +&h3 +% +&h],`TG>N +% +%4],`TG +% .5B[[N +% +%[ +%[''4 +%I +% +%́ +% (+>= +%ݜ[''ـ +& ?= +&"?'6 +&@J +&R +&Y[m +&m +&x +& +& +&`:J +& +&`:'9'7..[W +,Q +, +.8 +,R +,t +, +. +,[* +,[*]`Y>N +, +,]`Y +,צ`YN +, +-\][`:[2 +-`:[' +- 'Ɓ +-+= +-).9B[Y= +-I.:B +-WpB +-k4 +- +- +- +-`Y`>= +- +-Dt +-4 +- +- +- +-S`[`>= +- +-Dj +-A[ZJ +. +. +. +Du[Y +.# +.# +/j9B +.6 +/j[>I +.? +.C`'g';.>= +.r['7$'<'='>.....?[Z +/o +/ +0:B +/p'8 "' +/ +0 +/\[ +/<^`YB\ +/S^`[SB\\[p +0B +0J +0pB +0U +0`[1>=0 +0^ +0h'[b +4 +4 +4? "' +4 +4\[c +4 +5 +5?@ +5 + +5?][J +5 +5B[ +5 [''A.[[ +5D +5 +55B +5E'3 +5^'B +5~'C "' +5 +5],`TG[d +5 +5 +6YD +5 +6Y]``GJ +5 +5B``G +6-[''E.[e +6^ +6e +6F +6r +6][J +6x +6xB[ +6[''G.[f +6 +6 +7 H +6 + "' +6 +7  +6`: +6`: +6`:\[g +7 +7 +8I +7( +8 +77J],`:+][>I +7H! +7U +7L)(+>N +7k +7vK],[ +7xpI +7)J +7 +7.LB +7i[\?J +7 +7.MB[][\ +8 +8. +8ZLB +8'I "' +8D +8Z +8JJ],[][[] +8^ +8 +8MB +8_'I "' +8 +8][[h +8 +8 +9N +8 +9 +8\][[[+][>I +8! +8 +8(+>N +8 +9[ +9pH +9$J +94 +9;.OB +9P[^?J +9f +9m.PB[_[^ +9 +9 +9OB +9'Q "' +9 +9 +9\[][[_ +9 +: +:PB +9ۡ'Q "' +: +:][[i +:" +:) +;R +:D +; +:W`: +:lS],][[[][J +: +:B[ +:[''T. +: +:![j +; +; + +;4U "' +; +;4 +;`: +;(``[k +;9 +;@ +;V +;E +; +;K][[[+][>I +;X! +;a +;\(+>N +;v +;}[ +;pH +;J +; +;.WB +;8[`?J +; +;.XB[a[` +; +< +<WB +;'V "' +< + +< +< [][[a +< +<5 +=0 +? +?'6[w +@ +A, +BZ +A'Z`[y +B [`+[| +A +A +ApB +A +A`[w>=0 +A +A'[} +B +C +C\ +B'\`[ +C *`+[ +Cw +C +CpB +C +C`[}>=0 +C +C'(t[ +D +D +F8]`[ +E +`:+[ +E ,`:+[ +E -`:+[ +E .`+[ +E `:+[ +F /`:+[ +F- 0`:+[ +E. +E6 +E{pB +EC +E{`[>=0 +EL +EV'C[ +G +G" +H^`[ +G `:+[ +H 1],`:+[ +G +G +GpB +G +G`[>=0 +G +G'=[ +H +H +I_`[ +I 2`+[ +I^ +If +IpB +Iw +I`[>=0 +I +I'[ +J +J +K` +J'``[ +K a`:+[ +K `:+[ +K K`:+[ +K3 +K; +KpB +KT +K`[>=0 +K] +Kg'N[ +OS +Ow +QQb +OT'b`R[ +P[4]l`R +Pul`R'[ +P c`+[ +P d`+[ +P e`:+[ +P f`+[ +Q `:+[ +O +O +P.pB +O +P.`[>=0 +O +P '[ +Q +Q( +QO +Q1 +QO]y`RJ +Q4 +Q@ +Q4[.l|[ +S +S +cg]`[`q[ +Sn hB`[[ԁ +Sx +Sx +S +S +S +Sh`[\?[  +Sx[ +S +S +T8 +S +T8`[>N +S +S`[ +S`['i'j +S.hB[I +S +S +S(+=0 +S +T('?J +T' +T.[ +T= +TF +T +TK +T`[>N +TV +T]`[ +T_`['i'k +T~.hB[I +T +T +T(+=0 +T +T('?J +T +T[ +T +T +U +T +U`[>N +T +T` +U.([I +U  +U +UV(=0 +U +U"('?I +UA +UG +UEVw=0 +UL +UV('?J +U +U`['i'j +U.hB[[ +U +U +U +U +U +U K`[\>= +U +U.hB[ +U3\[ +U +U +W +U +W +V ]`[\>I +V% +V$ +Vš`[>N +VV +V``[ +Vbš`[I +Vr! +Vw +V +VϼhB[ +V.hB[>E +V +V +V` +V +VV` +V +Vρ([ +W +W4 +WG +W 4 +W +W 4W>= +W" +W.hB[ +W9 +W3 +W)ϼhB[[\?J +W^?F +Wp +W +Wz`[ +Wš>= +W +W.hB[ +W\[ +W +W +X +W +X +W` +W `[\>I +W" +W +Wt +W +Wtw +W.([>=0 +X +X +X!t +X+.([?I +X> +XH +XBt( +XK.([>= +Xa +X[.hB[ +Xhă\>= +X +X.hB[ +Xă +X. +Xt[\[ +X +X +Y~ +X +Y~ +X` +X ]`[\>I +X +X +X( +X.([>= +Y . +Y[>N +Y5 +Y:`[ +Y@. +YA[= +YU +YO.hB[l +Yeւ +Yo7[[ +Y +Y +Y +Y +Y +Y` +Y ]`[\>=0 +Y +Y'm[ +Y +Y +Z~7 +Z +Z~`[>N +Z +Z`[ +Z!.[I +Z+! +Z6 +Z/0(+>= +ZM +ZG.hB[B +ZZ0[?J +Zm +Zt0[Á +Z +Z +[ +Z +[ +Z``[>N +Z +Z`[ +Z. +Z[I +Z! +Zˁ +Z(+>= +Z +Z.hB[B +Z[?J +[ +[ [ā +[ +[ +[ +[# +[ +[+a``>I +[9!% +[D +[=ȟ`[J +[N*?N +[e +[j`[& +[e +[lȟ`[I +[x! +[} +[.hB[ +[ +[ٶ[J +[*?= +[ +[.hB[B +[[J +[)[Ɓ +[ +[ +]B +[ +] +[a`[` +\ `\>N +\ +\`[ +\ +\.hB[[C +\! +\ +\(+>N +] +]n`[ +] +]η[I +]+ +]; +]3 +]/ɠ +]4( +]>ɹ>= +]^ +]X.hB[B +]k[?= +]΃ +][ǁ +] +] +] +] +] +]a`[`\>= +].B +])[[ȁ +] +] +^/ +] +^/ +^a`[`\>= +^.B +^P*[[Ɂ +^4 +^9 +^a  +^> +^a\>= +^M +^G.hB[B[[ʁ +^f +^t +^ +^w +^ +^|` +^K`[\>= +^ +^.hB[B +^ +^. +^ +[[[ +^ +^ +^ + +^ +^]%`[J +^ +^ +^ +^.hB[o[ׇ + [ˁ +_ +_ +_ +_ +_ +_^`[`[~`+\>=0 +_ +_'p[́ +_ +_ +`R  +` +`R +` `+\>=0 +` +`"'q[́ +`t +`y +a  +` +a +`` +`y` +` ]`[ +``\>=0 +` +`'r[΁ +a +a +a +a! +a +a&` +a1y` +a< `[+\>=0 +aI +aS's[ρ +a +a +a +a +a +a` +ay`\>=0 +a +a't[ +b +b +b( +b +b`J +b +b +b +b.hB[o[ׁ(Y[ҁ +b +b +c/( +b +c/ +bK`\>=0 +b +b'u[Ё +c4 +cB +cj +cD +cj +cI``[J +cS +cc +cY +cS.hB[o[ +cd9[ +co +c~ +c +c +c],`[J +c +c +c.hB[o[s" pJŝƓǫurʿ&ˍr?͒΍Mϡp[Ձ +c +c +  +c' `R[ׁ +l o +l}' +l'],`[+[؁ +m^v`[ف +mw`[ځ +mx`7[ہ +my`7 [܁ +n z`7 [݁ +n0{`7 +[ށ +n]|`[߁ +n}`7[ +n~`7[။ +n`7 [⁋ +n`7[か +o4`[䁋 +oh  +oG'`:+[偋 +p< `[+[恋 +pV `+[灋 +q+ `[+[聋 +r  +q:' +`[+[運 +s^ `:+[ꁋ +w `+[끋 +xV `:+[쁋 +y `M+[큋 +z  +y'`P+[ +{ `[+[ +|  +{̡' `[+[ +} +|ɡ'`:+\ +c +c +dB +d +d\? +dR[ +dZ +di +d +do +d],`[>J +du +d[.[ +d +d +e +d +e +dK]`[\>N +eH +eM ],`[ +eU +eOԌ= +ec.'[F +er +e +e|`[ +eԧ>= +e. +e\[ +e +e +f +e +f\>I +fw! +f +f.[(+>N +f +f`[ +f.[= +f +f.[B.[?[ +g* +g/ +g +g: +g +g@`[`[>K>N +gh +go`[ +gv.[= +g +gB +g.[ +g[ +gl[>?J +g.[ +hb +hg +jl +hv +j +h]`[ +h`[`[>I +h% +h +hֈ`[>N +h +h`[ +hֈ`[I +i +i +i +iмhB[.>=0 +i0 +i: +iHֈ`[?E +i +i +i` +i +iV` +i +iЁ([ +i +iI +i\ +iI +iǃ +iIW>= +i. +i +i +iмhB[[ +j֝\>F +j* +jE +j3`[ +j;ֈ>= +jT. +ja +jg֝\[ +j +j +jB +j +j\>C +j! +j +j.[(+>= +j.B +j.[[[ +k. +k5 +kA +k= +k`:>N +kM +kSK`: +kU.[J +k# +k +k(+B +kAр +k`:\ +m +m + +mHpB +m +mH`[>=0 +m +m#'\ +} +( +@ +}¡' "' +. +@ +4`[`[\ +E + + +F' "' + + +f``[\ + + +n "' + + +s`[`\ + + + + + +\][[[+`[>I +! + +ڿ(+>N + +[ +pH +>ڿJ +N +U.B +d[?J +z +.B[[ + + +B +' "' + + +\[`[[ + + +B +ۡ' "' + +`[\ + + + "' + +`\ + + + "' + + +`[ + `[`[[ + +< +[B +' "' +H +[ +N`[`[[ +` + +B +a' "' + + +`[ +`[`[b#ն^MOٛKڕ]۴<ܕ\\ + + +3 + + +'` \ +l`\ +`\ +`\ +`9\ + +`7\ +3`7\ +^`7\ +`7\ +`\ +`7@\ +"`\ + + + +VpB + +V`\ >=0 +' +1';\ + +8 +% + + +'`\ +l `+\ + `[+\ + L`[+\! + `+\# +] +e + +q + +wL`[ +``\>J + + +BB + ++N\% + + +\pB +$ +\`\>=0 +- +7'\' + + + "' + +\\( + + + "' + +`[\) + + +# "' + +#`[c!\\* +1 +1`]`[\+ +1 +1`\*]mj`[\, + +( + +'`\+]`[],`[ +\/ + + +:pB + +:`\,>=0 +  +'\1 +? +G +l( +N +l`J +Q +Q`'t'h.\6 +q + +8 + +8 +``[>I + +`'g'Հ + + + +.(\1=0 + + +.?J + +`[' 'N. +.\7 += +K + +N + +S` +_ K`[\>=0 +l +v'\< + + +V( + +V + +K`\>=0 + +!'\2 +[ +d + +j +`[>I +p + +y.(\1w>J + +`[' 'z.?=0 + +('\3 + + + + +`[>N + +V` +.(\1I + + +w>J +( +/`[' 'N. +L +Hy?=0 +\ +f('\4 + + +b + +b`[>N + +V` +.(\1I + + +(>J + +֜`[' 'z.?I + + +(=0 + +('?=0 +1 +;('\8 +g +l + +u + +z``[J + +. +\6\: + + +B +' "' + + +``["n:\ +\= + + + +'`\? + `P+\@ + `P+\C +Q +Y +pB +s +`\=>=0 +| +'\D + + + +ע'`\G +a +i +pB + +`\D>=0 + +'\I + + +r "' + + +s`:`P,x\J + + + +ɢ'`\L +`:+\O +E +M +pB +\ +`\J>=0 +e +o'e\P + + + +'`R\R +H5]l`R +al`R'6\S +{]l`R +l`R'w\T +]l`R +l`R'S\U +]l`R +l`R'\V + ],[+\W + `:+\X + s`:+\Y +8  +p? +p@`+\Z +N `:+\[ +c `:+\\ +y q`:+\] + `:+\^ +`+\_ +`:+\` + `+\a + `+\b +! `+\c +9 `:+\d +K C`+\e +f `:+\f + ],`+ \h + + + + + +`: +`:+ +s`:+ +'`:+ +@`:+ +X`:+`\P>N +o +}][[[2 +[[I +! + +?(+B= + +였' +?n?I +! + +O(+B= +׆ +였's +On?I +! + +_(+B= + +였' +_n?I + ! +( +$o(+B= +> +1였' +Hon?I +Q! +Z +U(+B= +p +c였' +{n?J + +\m +/ +\j + + +QpB + +Q`\P>=0 +" +,'\m + +3 +*B +G +* +O`: +[\][[[+`\P>I +k! +w +o(+>N + +[ +pH +J + +\n + +?J + +\o + \n +/ +C +B +L + +M[ +T\[`\PJ +f +f`\P'' + +\o + + +1B + + +[`\PJ + +Ӝ`\P'' +\t +H +X + +b +`J +e +e`'g'\q + + +w "' + +\\p + + +'B +' "' + +' + ^`:B\+][\r +, +a +  +-' +r + ]`:>N + +]`: +`:= +\p4 + + + +K`:`>= +Հ +jt +J + + +ju\u +Q +c + +k +]y`RJ +n +y +n\R.l\v + + + + +]y`RJ + + +\S.l\w +G +Y +~b +a +~]y`RJ +d +o +d\T.l\x + + + + +]y`RJ + + +\U.l.zY6$TO \y + + +_ +Ԣ'`R\{ + `:+\| +: `\P+\} +X `:+\ +\ +d +pB +w +`\y>=0 + +'\ + + +z + +z +`: +.][[[`\y>N + +/[ + +pH +)J += +V\ +`w +f\ +~ + + +B + + + +[ +.[`\yJ + +`\y'' + +$Nd\ + + + +'`C\ +`+\ +`+\ +`:+\ + + + + +\? +C \ + + +LpB + +L`\>=0 + +''\ +Q +Y + +e +`\J +k +k`\'' +B'(t\ + +t +D +ɣ + + + + += +F + +R'`C \ + B +!' +<' +Y'[+\ +`:+\ + `T++\ +`:+\ +K`:+\ +`:+\ + `:+\ + `:+\ +@ `g\+\ +T`:+\ +i `+\ + + +; +' +;\? +2C \ + + +!pB + +!`\>=0 + +'\ +& +. +a +; +a`\J +A& +A +J +AB'aN,`\\ + + + + +`J + +R'a\ + + + + +`lJ + +B + .B\\ +z + +IB "' + + +K`:`[\ + + +B "' + + +K`: +K`[\\ + + + "' + +`\ + + + "' + +`\ + + +B "' +- +B +5S`:\V> Q \ + +@ +" + '`R\ +`+\ +`+ +\ + + +pB + +`\>=0 + +'\ + + +^ + +^ +` +``\>J ++ +B\ +LR +Sa\ +b +y +B + + +[ +[`\J + +`\''ƀ +́ +\ + + + + + +\][[[+][>I +'! +3 ++A(+>N +H +R[ +TpH +sAJ + +.B +}\?J + +.B\\ + + +B +ԡ' "' + + +\[][\ + +; +TB +' "' +K +T][\ +Y +` +\ +j +\ +r`: +][[[+`>I +! + +(+>N + +[ +pH +J + +.B + +\?J +7 +>.B +L\\ +a + +B +b' "' + + +[ +[`\ + + +B +' "' + + +[`\ + + +  "' + + `V#)6m(c +\ + +0 +_ +'``j\ +; `\+\Á +M`:+\ā +b`+\Ł +w `:+\Ɓ +!`:+\ǁ +"`+\ȁ +#`:+\Ɂ +$`+\ʁ +%`:+\ˁ +&`:+\́ +!`+\́ +;'`:+\΁ +L(`+\ρ +^)`+\Ё +q*`+\с ++`:+\ҁ +,`+\Ӂ +-`+\ԁ +.`+\Ձ +/`:+\ց +0`:+/\ف + + + pB + + `\>=0 + +'\ہ + + +4 "' + +\\܁ +# +( +]6 "' +1 +] +6` +=!` +D` +O`\\݁ +b +g +7 "' +k + +t`]+\\ށ + + + + +][J + +B[ +[''.\߁ + + +t: + +t +<[ +=`+ +>[+ +??][[[+`VF>I +^"""% +{ +ci`VF + +”t(+ +͂ +°(+ + +(+>N + +@[ +pF +8i`VFJ +X +_pE +}.AB +Ð\?I +é"""! +ö +ít(+% + +i` + +(+ +< +%(+>J +M +TpE +}.BB +Đi` +ĩt\?I +Ŀ"""% + +][[[! + +t(+% +) +i` +S +<(+>N +h +ŁC[ +ōpH +Ŭ][[[J + +pE +.DB +i` +-t +7\?I +]"""! +x +a(+% +Ʃ +ƌ`! +Ł +Ƽt(+! + +i(+>N + +C[ +*pH +IJ +h +opE +Ǎ.EB +ǫi +t +` + +g\?=0 +0 +:'G\။ +y +Ȗ +ȺAB +z': "' +Ȩ +Ⱥ +ȩH[[\⁋ +Ⱦ + +BB +ȿ': "' + + +` +Q[[\か + +! +^DB +': "' +3 +^ +8` +<Q[ +@?[[\䁋 +b + +EB +c': "' +ɑ + +ɒ[ +ɘ[ +ɠQ` +ɤ?[[\聋 + + +I "' + + +` +` +` +``E\運 + +$ +yJ "' +1 +y +Oq[ +cK`:`E\ꁋ +~ +ʍ +L "' +ʡ + +ʭ` +ʵ` +ʽM` +` +` +N``E\끋 + + +˙ "' + +˙  + q[ +` +!` +5`+ +L`+ +d`+ +r`+ +ˀ`+ +ˎ`+\\쁋 +˞ +ˣ + "' +˧ + +˩8[+ +9`:+\\큋 + + +Q "' + + +` +!` +` +`\\ + + +S "' +! +S +)`: +3` +:!` +Br`+\\ +X +b +T +n + +sU` +{V` +̃` +̋Q``VF>J +̕ +̜pE +̺.WB +  + & + 5 + D\\偋 + + +#WB +'T "' + +# + U[ +V[ +[ +Q[[\ +( +2 +FY "' += +F],`\ +K +P +͡[ "' +] +͡ +^\[ +m]` +v^[+ +͋9`:+`\ +ͦ +ͫ +_ "' +ͺ + +ͻ\[ +]` +!`+`\ + + +` "' + + +`:`e \ + + +a +' + +2H`VF +A` +I` +Xb`+ +dc`+ +pd`+ +΀e`+\>I +Δ""" +Ο +Θ(+ +ι +β(+ +ׅ +(+ + +(+>N + +@[ +pF +7= +I.fB +Y +f +j\J +u?I +χ"""! +ϗ +ϋ(+! +ϵ +Ϫ(+! +τ +(+! + +(+>N + + +@[ + pF +*= +<.gB +WT +d +hŃ +lԄ +t +| +Ј\J +М?=0 +Ю +и'G\恋 + + +?fB +'a "' +% +? +&H[ +1[ +5[\\灋 +C +b +ѻgB +D'a "' +q +ѻ +yH[ +ф[ +ш[ +ьb[ +єc[ +ќd[ +Ѩe[\\ + + +i "' + +\\ + + +j "' + +\\ + + +k "' + + + l`\\ + +" +/m "' +& +/\\ +4 +9 +S "' +> +S +C` +J!`\\ +X +] + "' +h + +s],`\\ +҄ +҉ + "' +ҕ + +Қ=` +ҡr` +Ҩ_` +ү` +Ҷl` +ҽ`\\ + + +o "' + + +`]+\\ + + +,p "' + +, +` + !` +` +`\\ +1 +6 +rq "' +@ +r +H`: +R` +Y!` +ar`+\\ +w +| +Ӷ "' +Ӆ +Ӷ +ӊ=` +ӑr` +Ә_` +ӟ` +Ӧl` +ӭ`\] +ӻ + +s "' + + +` +!`\] + + +Z "' + +Z +` + !` +u` + v` +0w` +Ex`\] +_ +d +Ԝy "' +i +Ԝ +n` +v` +~z` +Ԇ{` +Ԏu`\] +ԡ +Ԧ +| "' +Գ + +Ը}` +~` +` +` +` +!`\] + + + "' + +\] + + +՘ "' +# +՘ +(` +/!` +6` +C` +P` +dv` +tw` +Ճx`\] +՝ +բ +ս "' +ը +ս +խ` +մ!`\] + + + "' + + +` +!`\] + + +# "' + +# +` + +` +` +!`\] +( +- +] "' +1 +] +6` +=!` +D` +O`\.?H   +  +^ +   y  ]3}S W)uJ1'H./] + +: +_ +ٶ +;'`C] +ٛ`+] +ٯ`:+] +f +f +ّ +} +ّ\? +وC ] +׿ + +pB + +`] +>=0 + +'] + + +ص +, +ص`] +J +2 +2`] +'' +ؚB'/] +ڑ +ڴ +N +ڒ'`C] +`+] +`+] + `T++] + `+] +$`:+] +3`+] +GK`:+]) + + + + +\? +C ] + + +s + +s +`:' +K`:' + `*`]>J +8 +C]  +Su +Y+ +f] +x +ۀ +|pB +ۏ +| +۟`:+ +۬K`:+ +۸`+ +`+`]>I +! + +;(+>J + +]# + +" +)+ +:;?I +O! +c +S+(+>J +t +܉]$ +ܓ +ܙ +ܠ+?I +ܼ! +Ɓ +(+B>J + +]% + +?I +! + + (+B>J +( +=]& +G ?J +X +m]']# +݀ +ݕ +AB +ݞ +A +ݟ[ +ݥK[ +ݬ[ +ݽ[`]J + +ʜ`]''܀ + + ʂ +! Ճ +8 ]$ +E +Z +1B +c + +d[ +jK[ +q[`]J +ދ +ދ`]''݀ +޴!` +޺!k +!v]% + + +=B + += +[ +K[`]J + + + +`]''ހ +1! +7!]& +A +V +ߙB +_ +ߙ +`[`]J +o +o`]''߀ +ߔ"f]' +ߝ +߲ +B +߻ +`]J + +`]''K !2!"8""]* +) +L +Q +*'`b)], + ],`+]/ + + +pB + +`]*>=0 + +']1 + +% +O "' +3 +O +;`\#a##]2 +, + + +- +O +X +z +䄣 +䦣 +䯢'`C +]4 +&A`:+]5 +I `T++]6 +e `P+]7 +  +r + +瀡' +眡'],`[+]8 +K`:+]9 + `:+]: + `:+]; ++ `g\+]< +?K`:+]= +T `+]I +o +o + + +\? +C ]@ +/ +7 +~pB +F +~`]2>=0 +O +Y']A + + + + +`]2J +& + + +B'4N,`]2]C + + + + +`J + +R'4]E +e +j + "' +w +`]F + + + "' + +`]G + + + "' + + +S`:\%&&^&&''`]J + + + +鯢'`]L + `:+]M + `:+]N + + K`:+]Q +9 +A +pB +W +`]J>=0 +` +j']R + + + + + +`: +`:`]J>J + +]U +(i + (x]U + +8 +B +A + +B[ +N[`]JJ +Z +Z`]J'' +( +('(@().]V + + +' +'`R]X + `+][ +n +v +pB + +`]V>=0 + +']\ + + + + + +`: +.][[[+`]V>I + ! + +*(+>N +3 +C/[ +EpH +d*J +z +]_ +* +*L?J + +]` +*]_ + + +B + + +[ +.[`]VJ +0 +0`]V'' +}* +*]` + + + 1B + +  +[`]VJ + +Ϝ`]V'' ++Y))*+++]a + ++ + +'``j]c +`tn+]d ++`+]e +@ `:+]f +O"`+]g +f#`:+]h +$`+]i +%`:+]j +&`:+]k +`+]l +'`:+]m +(`+]n +)`+]o +**`+]p +@+`:+]q +T,`+]r +j-`+]s +.`+!]v + + +pB + +`]a>=0 + +']x + + +4 "' + +\]y + + +6 "' + + +` +!` +` +`\]z + + +!7 "' + +! +8[+ +9`:+\]{ +& +5 +pI "' +I +p +N` +V` +^` +f``E]| +u + +J "' + + +q[ +K`:`E]} + + +>L "' + +> + ` +` +M` +$` +,` +4N``E]~ +C +H + "' +Q +  +hq[ +s` +` +`+ +`+ +`+ +`+ +`+ +`+\] + + +0 "' + +0 +8[+ + 9`:+\] +5 +: +nQ "' +B +n +G` +N!` +U` +``\] +s +} +Y "' + +],`] + + +[ "' + + +\[ +]` +^[+ +9`:+`] + + +,_ "' + +, +\[ +]` +"!`+`] +1 +6 +Mi "' +D +M\] +R +W +gj "' +^ +g\] +l +q +k "' +w + +|l`\] + + +m "' + +\] + + + "' + + +` +!`\] + + + "' + + +],`\] + + +7 "' + +7 + =` +r` +_` + ` +'l` +.`\] +< +A +]o "' +G +] +P`]+\] +b +g +p "' +q + +v` +}!` +` +`\] + + + "' + + +=` +r` +_` +` +l` +`\] + + + s "' + +  +` +!`\] +$ +) + "' +, + +1` +8!` +?u` +Kv` +[w` +px`\] + + +y "' + + +` +` +z` +{` +u`\] + + +!| "' + +! +}` +~` +` +` + ` +!`\] +& ++ += "' +4 +=\] +B +G + "' +N + +S` +Z!` +a` +n` +{` +v` +w` +x`\] + + + "' + + +` +!`\] + + +  "' + +  +` +!`\] + + +N "' +' +N +,` +5` +>` +E!`\] +S +X + "' +\ + +a` +h!` +o` +z`\-d--.Z./$/y001!112F2233_334745 56 6b67u88=89A9: :|!] +e + +P +f'`] +4 `+] +I `+] + + +%pB + +%`]>=0 + +';f;] ++ +T +z +,'`i] ++ `+] + + +pB + +`]>=0 + +'] +@ +E +x "' +R +x +ZK`: +g`\<=0   '] 3 ;  K `]J Q Q`]'' B'C="=n=]     + '`C] K`:+] K`:+]     \? C ]   bpB * b`]>=0 3 ='] g o  { `]J  `]'' B'>x>?]   r`]  3B`+]  .B],`[+]  5B`P+]  7B`P+] < D pB P `]>=0 Y c']Á   =w + = 3x`:`P]Ł B M pyB ^ p fx`:],`[?@ @L@]Ɓ M q  N'`F`F]ȁ `+]Ɂ `:+]ʁ  `:+]ˁ `:+]́ g  F'`:+]́ K`:+]Ё +EpB + +E`]>=0 + + ']с +J +R  +d  +e[`]>I +y% + +~A][[[>N + +[ +pH +A][[[J + +] B?I % & A`T+>J ? Y] cA`T+?=0 | 'G]ԁ BB B [`]J  `]'' 5B]Ձ F ` 1B i  j[`]J  `]'' CQAxABC#C]ց a y E b'``j]ف   /pB  /`]>=0   +']ځ 4 <  B  D[+`]>I Y j ]DJ(+>J { ]?I %  DJ`]>J  ] DJ`]?I %  DJ`:>J  +] 5DJ`:?=0 N X'G]݁   B  `]J  `]'']ށ   -1B  - [`]J  `]''  E]߁ 1 ? B H  I[`]J ` ``]'' ~F]    "'   `] `tn+\]။   @ "'  @ ` !` u` v` w` +x`\]⁋ E J y "' O  T` \` dz` l{` tu`\]か   | "'   }` ~` ` ` ` !`\]䁋    "'  \]偋   ~ "'  ~ ` !` ` )` 6` Jv` Zw` ix`\]恋    "'   ` !`\]灋    "'   ` !`\]聋     "'    ` ` ` !`\]運   C "'  C ` #!` *` 5`\CD!E$EuEF?FG&GH9HpIItIJ<J]ꁋ  @ % !'` ]쁋  ],`:+]큋 $ `:+] : `:+] S `:+] v +`:+]  `:+]  `:+]  `:+]  `:+]  `:+]  `:+]   pB  `]>=0  'L&Lr]  $  '`]   pB  `]>=0  ']      ][J  B[ [''C.^ ! .  4  <`:]`J T TB` j[''B. M{^      `:]][`:[J  B [''. M^  # ~ & ~ .`:][J F FB[ V[''<. oNj^     ]],`:J  B],`: Ɯ[''.^      `:  ][[[][>N  &H[ (pH GOSJ U \.B cOD rOo^^   B ' "'   [ [][LLMQMN@NOOP"^    '`^  `]+^ + `:+^  & npB 6 n`^>=0 ? I'PP^   $N '`R^ " .`:+^ " `]+^ # `:+^ #3 `:+^      ],][[[ ][[[ \][[[+`^>N " /],[1 1[F 9 S B][[[ GQ>= h [Q lpH R ;I !  Q(+>N  H[ pH QN  [ pH %QJ 5 K^ UQ cR nR?N H[ pH QJ  ^ Q S^ ! ! !B !! ! !"[ !.[ !7\[`^J !C !C`^'' !S} !S !S^ ! ! "71B ! "7 ![ ![`^J ! !`^'' "#T "/T^ "t "| "pB " "`^>=0 " "'^ #D #K # #P #][J #V #VB[ #f[''e.^ # # # # #]`J # #B` #œ[''.^ # $ $L $ $L]`^;J $ $B`^; $3[''.QSOSTTTTUVU^ %* %O )  %+' `R^! ' `:+^" ' ],[+^# ' ],[+^$ ' !`:+^% ( `:+^& (/ `:+^' (O "`+^* % % & pB % & `^>=0 % %'^+ & & & &, & &4`: &>.][[[`^>N &W &g/[ &ipH &W4J & &^. &W% &WP^. & & 'B ' ' '[ ' +.[`^J ' '`^' '# 'iWǁ 'uW^/ (Y (n ( (x ( (`:]`i(J ( (B`i( ([''. (X<^0 ( ( ( "' ( ( ( +][\VVWXXX^1 ) * -x$ )ܢ'$`R^4 *j *r *pB * *`^1>=0 * *'^5 * * , * , *`: *.][[[+`^1>I +! +& +Y(+>N +; +K/[ +MpH +lYJ + +^8 +Y +Y?J + +^9 +Y^8 , ,( ,B ,1 , ,2[ ,8.[`^1J ,J ,J`^1'$'% ,Zr ,Z}^9 , , -D1B , -D ,[`^1J , ,`^1'$'& -?Z^: -I -N -v' "' -X -v -`(][\YYiZDZ["[h^; .S .t 0) .T')`^= /7 `+^> /P `:+^? /l *`:+^@ / +`:+^A / ,`:+^B / `:+^C / `]+^D 0 `:+^G . . /%pB . /%`^;>=0 . /'^I 0 0 0t 0% 0 0.-`:+][J 0G 0GB[ 0W[''.. 0u\\l\]'^J 1a 1 5/ 1b 1 1 1 1 1ۣ 1'/`R^L 3A 0`Y+^M 3h 1`^w+^N 3 2`+^O 3 `^+ ^R 2X 2` 2pB 2m 2`^J>=0 2v 2'^T 2 2 3+ 3 3+`J 3 3`'g'3^V 3 3 34 "' 3 3 35`:\^W 3 3 4 6 "' 3 4  37`:\^X 4 4 438 "' 4* 43\^Y 48 4O 4b9 "' 4Y 4b],`^`^Z 4g 4~ 4: "' 4 4 4K`: 4;`:],`^`^[ 4 4 4< "' 4 4 4;`:],`^`^\ 4 5 5= "' 5 5 55`:\^] 5$ 5) 5m> "' 50 5m 587`: 5L?`: 5^@`:\^^ 5r 5y 5& "' 5| 5`[^_ 5 5 5A "' 5 5 5B`\]^G^^_ _W__`F``a+aq ^` 6 6 7C 6'C`^b 7 t`+^c 7 ;`:+^d 7 K`:+^e 7 `+^h 7 7& 7ppB 78 7p`^`>=0 7A 7K'b4b^i 8 8 9D 8'D`^`^k 9 E],`d+^n 9G 9O 9pB 9j 9`^i>=0 9s 9}'bc'^o : : ;F :'F`^`^r ;7 ;? ;pB ;P ;`^o>=0 ;Y ;c'cec^s =0 = = 'cd;^w >" >U ?H ># + >/'H`^y ?(I`^z ?SJ`^{ ?zK`^| ?L`7^} ? M`+^~ ? `+^ > > ?pB > ?`^w>=0 > >'eeZ^ @ @ BN @'N`^ +^ A O`+^ A P`+^ B Q`+^ B; R`+^ BX S`+^ Bs T`+^ B M`+^ B `:+^ B U`+^ B V`+^ Ae Am ApB A A`^>=0 A A'f~f^ C C FW C͢'W`^ DU D] DpB Dr D`^>=0 D{ D'^ D D E) D E) D^`^`^2WB\`^>J D E^ Eg{^ E- EH EB EQ E ER[`^J Ee Ee`^'W'X Eg^ E E Eh "' E E\^ E E FJ E FJ E\][[[\>N E E[ EpH Fh= F%.B F0h^J F@^ FO Fi FB FP' "' Fs F Ft\[\ggRgh)h`hi<^ H I JY Hآ'Y`^ Ir Iz IpB I I`^>=0 I I'^ I I I9 "' I I],`^`^ J J JQ: "' J+ JQ J3K`: J@;`:],`^`^ JV Jm J< "' J} J J;`:],`^`iijjwj^ Ks K LaZ Kt'Z`^`^ L L L_pB L' L_`^>=0 L0 L:'kk]^ M< Mg PO[ M='[`^`^ N@ \`+^ NY ]`+^ Nt ^`+^ N _`+^ N ``+^ N a`+^ N b`+^ O + c`:+^ O) d`:+^ OG e`+^ Oa f`+^ O} g`+^ O h`+^ O i`+^ O j`+^ P k],`^+^ P' l`+^ PB m`+^ M M N1pB M N1`^>=0 N N 'm?m^ Q* QS R`n Q+'n`^ R& `:+^ R@ t`+^Á RZ K`:+^Ɓ Q Q RpB Q R`^>=0 Q Q'n nW^ǁ S; Sj Vo S< + SH'o`^Ɂ T. \`+^ʁ TG ]`+^ˁ Tb O`+^́ T| P`+^́ T Q`+^΁ T R`+^ρ T p`+^Ё U _`+^с U ``+^ҁ U@ b`+^Ӂ UY S`+^ԁ Ut T`+^Ձ U q`+^ց U e`+^ׁ U f`+^؁ U g`+^ف V h`+^ځ V i`+^ہ V6 j`+^܁ VZ U`+^݁ Vw V`+^ S S TpB S T`^>=0 S S'pp^။ Wd W Xr We'r`R^か Xf4]l`R Xl`R'^䁋 X M`:+^灋 W W X9pB X X9`^>=0 X + X'^運 X X X X X]y`RJ X X X^.lqSqq^ꁋ Y Y ]s Yע's`^큋 ZO ZW ZpB Zd Z`^>=0 Zm Zw'^ Z Z [( Z [( Z][[[][>N Z Zt[ ZpH ZrJ [ [.uB [r^^ [- [G [buB [.' "' [O [b [P[][^ [g [n [  [u [ [z][[[][>N [ [v[ [pH [sJ [ [.wB [s^^ [ \ \5wB [' "' \! \5 \"[][^ \: \S \x \] \ \h],][[[]`^J \~ \~B`^ \[''y. \ts^ \ \ ]fz \ ]f \][[[][>N ] ]t[ ]pH ]3tJ ]D ]K.{B ]Uu^^ ]k ] ]{B ]l'z "' ] ] ][][r3rs sdstItuVu^ ^ ^ _| ^'|`^ _g }],[+^ _ ~`Yj+^ _ `Yj+^ _ `:+^ _ _ _WpB _ _W`^>=0 _( _2'vdv_ ` ` bs `Ģ'`C_ bG bG bq b] bq\? bhC _ aF aN apB a^ a`_>=0 ag aq'w'ws_ cN cf d cO'`_ d `:+_ d4 `:+_ + dK (`+_ dc K`:+_ c c dpB c d`_>=0 c c'_ dl du d "' dy d d~``Z_ d d d "' d d dK`:`Zx +xVxx_ e e`]`_y%_ e e`_]mj`_yY_ e e k e'`_]`_],`_ _ f f fpB f f`_>=0 f f'_ f f g( f g`J f f眣`'t'h._ g g g g g g``_>I g+ g/`'g'Հ gUzj g\zj gczj gj.(_=0 gy g gzj.?J g g`_''N. gzj_ g g hR g hR g` g K`_\>=0 h h'_% h h h( h h hK`\>=0 h h'_ h i i i i`_>I i i" i.(_w>J i/ i6`_''z.?=0 i\ if('_ i i j+ i j+`_>N i iV` i.(_I i i i|}w>J i i՜`_''N. i i|}y?=0 j j('_ j0 j; k jB k`_>N jL jPV` jW.(_I jc jk jg}<(>J jy j`_''z.?I j j j}<(=0 j j('?=0 j j('_ k k k= k# k= k(``_J k2 k6. k7~ __! kc kj k "' kn k ks``__" k k k "' k k kK`:`__# k k k "' k k k`\yyzA{{k{|I}}~?~~ _& l l p l'`Z +_( oy `+_) o `+_* o J`+_+ o `:+_, o `+_- o `+_. p `+_/ p( `+_0 p< `+_1 pP `+_4 m% m- mspB m; ms`_&>=0 mD mN'_5 mx m n m n m`: m.][[[+`_&>I m! mǁ m(+>N m m/[ mpH n J n# n7_8 nA݂ nG)?J nc nw_9 n_8 n n o +B n o + n[ n.[`_&J n nʜ`_&'' n n_9 o o" oj1B o+ oj o,[`_&J o; o;`_&'' oe6_: pZ pm p "' p p],`_&hm_; qe r3 u qf q q q q qߣ' q r r'`R_> u B u9'M uLp? uxp@[+_A r r rpB r r`_;>=0 r r'_B r r s r s r`: s.][[[+`_;>I s! s/ s!(+>N sD sT/[ sVpH suJ s s_E s s??J s s_F s_E s t twB t tw t[ t.[`_;J t5 t5`_;'' tcӁ ti_F t{ t t1B t t t[`_;J t t`_;'' tL_H t t u4M t u4[J t tpC u).B_>~_I w x y^ wߤ + w'`_K x`_L x`_M y%`_N y? Q`+_O yU `:+_R xg xo xpB x~ x`_I>=0 x x'_S { { } {'`C_Y }y }y } } }\? }C _V { | |JpB | |J`_S>=0 | |%'_W |O |W | |a |`_SJ |g |g`_S'' |B'__Z ~| ~  ~}'`_\ ^`_+_]  `_+_` ~ ~ EpB  E`_Z>=0   'q_a q  r'`R_c 4]l`R l`R'_d K`+_g  ^pB & ^`_a>=0 / 9'_i  ]y`RJ   _c.lC_j ! T '`R_l ]l`Y /l`Y'_m g`:+_n .`:+_o M`:+_p `:+_s pB `_j>=0  '_u w "' \_v  "'  [\_w  "'  \_y  ) R 3 R]y`YJ 6 C 6_l.l3u_z / e 4 0'`R_| ( `_j+_ :pB  :`_z>=0  '_ ? G 4 k 4 s`: }.][[[`_z>N /[ pH J  _ ڂ _ 8 d B m  n[ t.[`_zJ  `_z'' | eN_  A  '`R_ `:+_ `:+_ pB `_>=0  '_    ;  C`: M.][[[`_>N f v/[ xpH J  _  _ # B ,  -[ 3.[`_J E E`_'' R ];$_  բ'`R_ ],`_j+_ k s pB `_>=0  'L_ V آ'`_ b j pB `_>=0  '_ T T]`_J  B`_ 3[''.3_ 1 V ? 2'`R_ pB `_>=0  '_    /  0[`_>I C% T H`:>J h _ `:?I % ],`:>N ],[ pI ],`:J  -_ 7]?=0 J T'G_ B  [`_J  ͜`_'' _  0 1B 9  :[`_J P P`_'' Z_ . .]`_aJ  B`_a +[''._ 3 R  [  c.`:]`_jJ p pB`_j [''. _ = =]`_jJ  B`_j #[''.u,f_  M A  + ''`FW_ " `d>+_ 9 c`:+_ pB `_>=0  'T_    ? H j t '  ã ̢'`C_  K + Y' u'],`[+_  `+_ 1`+_ K`+_  \? C _ P X pB i `_>=0 r |'_  `_J &   B'N,`__   E E`J # +R'7_  '`R_ `+_ (`+_ "`+_Á ' / vpB > v`_>=0 G Q'_ā {   `: .][[[+`_>I ! ˁ (+>N /[ pH J ' <_ Fڂ L&?J h }_ _ǁ B  [ .[`_J  ќ`_''  _ȁ  , v1B 5 v 6[`_J E E`_'' q3ej_Ɂ Z '`R_ˁ R `+_΁ # + zpB B z`_>=0 K U'_ρ  M M `: .][[[`_>N /[ pH OJ  )_ 3@ 9k_ҁ Q n B w  x[ ~.[`_J  `_''  _ԁ @  @][J  B[ &[''.-_Ձ 5 Z X 6'`F_ׁ ( `+_؁ N +`D+_ہ pB `_>=0  'F_܁ 3 N  4'`R_ށ `_+_။ pB `_>=0  '_⁋    `: .][[[+`_>I 6! H :(+>N ] m/[ opH J  _  \?J  _ _偋  |B # | $[ *.[`_J B B`_''€ h n_恋 1B  [`_J  `_''À i;_灋  ʢ'`_運 ],`:+_쁋 B J pB W `_>=0 ` j'_ F F]`_J  B`_ "[''._ K R " a " g\][[[+][>I w! {(+>N [ pH J  .B _?J  +.B__ ' K mB (' "' ] m ^\[][_ q B r' "' ][_ z z \][[[+][>I ! E(+>N [ pH 'EJ 7 >.B K_?J a h.B__  B ' "'  \[][_ B ' "' ][Qx9_  ΢'`_ N V pB g `_>=0 p z'_  "' `_ P "' `E_  "' `_  "'  `:)b_  '`` `:+` `+`  \`` ++` l t pB `_>=0  '` $ / In "' 5 I =K`:`` N [  f ]`J r rB` [''.6` +  '`` `+` `+`   opB 7 o`` +>=0 @ J'Q`  '`C` `:+`  \? C `   bpB * b``>=0 3 ='` g o  { ``J  ``'' B'+`  + Ȣ'` +` `` D`` j`` `` `+`! `[+`" `[+`# `+`$ & `[+`% C `+`'  % %``J   BEN`( * 2  A  H]```J X a XB;B& | | v,`&  ,!`N`* +pB +``>=0  '`, S d z "' q z`Nz`-   "' ```.  "'  `+\`/  "'  ` ````0  5 "'  5 `[ 'e```1 : K { "' c { k`:`Nz`2 € … œ "' “ œ\`3 ¡ ¦ µ "' ¬ µ\`4 º ¿  "'  `:\`5  "' `Nz`6  4? "' + 4]``8 9 Þ öB :' V'B u' "' í ö],]``9 û  "'  `[\`:  "'  `[ e```;   8 "' & 8 ,`[\`< = B f "' T f Z`[\`= k p Ĕ "' v Ĕ |`[ Će`\`> ę Ğ Ļ "' ĩ Ļ į`[\`?  "'  `[\`@  "'  `[ e`\`A   < "' * < 0`[\`B A F f "' T f Z`[\`C k p ŗ "' ŀ ŗ ņ`[\`D Ŝ Ŭ  ź ],]`>N K],]` .B`8N @ H[ J[''4 `I l x p(+>= Ɖ[''ـ Ƶ?= ȡ?'ڀ J  `F Dž Ǖ  Ƕ `J ǿ ǿ`'g')d][H-sT5{t`G   '``I .`:+`J `:+`K `:+`N g o ɻpB Ƀ ɻ``G>=0 Ɍ ɖ'`O   ܢ'`]*`R v ~ pB ˙ ``O>=0 ˢ ˬ'`S   ][[[+``O>I ! % (+>N : J[ LpH kJ ́ ̢`V ̬?J  `W`V  ͞B & ͞ '[``OJ 9 9``O'' ͐k`W ͢ 1B ``OJ  ؜``O''7=`X  9 '`R`Z M`:+`] v ~ pB ώ ``X>=0 ϗ ϡ'`_ U U .`+][J  B[ $[''. Q`` Z a И g И][J m mB[ }[''.`a Н Щ 7 к 7 ^` +B\]`J  B` [''. -Tf`b Y u  Z'``e pB ``b>=0  '3`f   '``i ~ Ն pB ՙ ``f>=0 բ լ'`j J J +^],[``fsWB\``f>J  3`m =0`m N g B p  q[``fJ ք ք``f'' ָ`n h "' \`o  "' \{N`p q ڑ ܏ r'``s @pB  @``p>=0  '`t E M ۰ [ ۰ s^],``{``p2WB\``p>J ۃ ۙ`w ۣ`w ۴ B  [``pJ  眣``p'' `x # ( ;h "' 2 ;\`y @ E c "' L c Uc`P\`z h m ܍ "' v ܍ c`P\^@`{  բ'``} `O+`~ c`P+` ] e ߲pB z ߲``{>=0 ߃ ߍ'P`  + Ϣ' `` `+` M U pB e ``>=0 n x'`   "' ],][[[3`  ⸢'`R` ]l`R l`R'w` ]l`R l`R'S` ]l`Y l`Y'` =]l`R Ul`R'` `:+` `+` `+` .`+` `:+`  `+` $ `+` B `+` \ `+` u ]`:+` "`:+` `+ ` B J pB Z ``>=0 c m'` w "' \`  "'  [\`  ' "'   `E\`  6 \ ' "' D \ P`\` a x  b' "'  `:\`  ꜡' "'  `\`  . S 6 S]y`RJ 9 D 9`.l` b ]y`RJ   `.l`  1 Z ; Z]y`YJ > K >`.l`  ]y`RJ   `.lJbZ®Ué ` # '`R`  ``+` 4 < pB Q ``>=0 Z d'` X X `: .][[[``>N /[ pH ĪJ  4` >ě D` \ w B  [ .[``J  ``'' = H&rň`   ' `R` !]l`` l``'"` Z # 5'$`+` v t`+` %`+` &`:+` (`Y+` { pB ``>=0  '` 9' ܡ'( "'  9 +)`: t`+ $%`+\`Á * ]y``J   `.lƀ@ǔ`ā 7+ ',`R`Ɓ 1 -`:+`Ɂ A I pB a ``>=0 j t'`ʁ n n `: .][[[``>N /[ pH uJ , J` Tf Zȑ`́ r B  [ .[``J  ``'+'.  =S`΁  q /  5 >'0``Ё ]1`:+`с o2`+`ҁ 3`:+`ԁ   ][[[``>N +[ [''4# p$ . p'5'5`:J H O``'/' q3 pB `ց  QpB  Q``>=0 " ,'ʲ`ׁ k C6 l'7``ف ^ .`:+`ہ 8B 'C[+`܁ `:+`߁ LpB  L``>=0  ''`။ e r C | `J  pJ .8B``か   W "'  ],`:`䁋 " ) A "' - A 5K`:`:ː0q̺`偋  5G9  A J':`R `灋 ;]l`Y -l`Y'<`聋 o=]l`` l``'>`運 ?]l`a* l`a*'@`ꁋ OA]l`R {l`R'B`끋 C]l`R l`R'D`쁋 E]l`Y ;l`Y'F`큋 {G]l`R l`R'H`  I`:+`  J`:+` = K`aJ+` n L`aJ+`  M`:+2` . . N][[[ O][[[+``>N  " +[ $['9'4$ | [p'PI !  (+>J  ``'9'Q 8 pB :  TpB ~>J  ``'9' 8 pB  `     `>K>= `2 [['R1  ][`:`:2 `:`:''SJ L) _[ fp[>J q*J *a   T   O][[[+]`aJ>N  ]`aJ `aJ= ".UB4 / / _ 0K[`>= I ?t& R RR]`aJ4 a a  bS`N`>= { qj Ѩ aJ   ua   V   O][[[+]`aJ>N  &]`aJ ,`aJ= T.WB4 b b  cK[`>= | rNt&  Ҙ]`aJ4    S`N`>=  Nj  -aJ   Nua   lX  l d`Y+]`ai>N  ]`ai `ai= .YB4   @ K`ai`>= * ӑt 3 BsaJ Q b Xӑua q YB r'Z "'  ^`ai +B\+ d`Y+][a +u[ + + +u +#\[][J += +=][')'] +e` + + pB + ``>=0 + +'a   ^   1` ^B\+ _^`NB\+][J : :B[ J[''`. uՉ ՘ կa      `Y O][[[+\>I !  N(+>N  /a[ 1pH PN= i.bB v? ~ևaJ ?= .cB ?aJ a   )bB ա' "'  )  `Y O[\a - I pcB .' "' U p b`Y\a u  P "'   (`Y d`Y`aDa   w "'  \a   WB   e[+ 9_^`NB\+ TO][[[+][>I m""  qu(+  ؁(+ ӂ ؟(+>J  .fBa ?I ""% (  u][[[ K ;؁(+ o ^؟(+>N  [ pH u][[[J  .gB {a +?I  ""!   ؁(+% L 1u^`aJ1B\  z؟(+>J  .hB u^`aJ1B\ ؁a ?I ""!  ؟(+! # ؁(+% R 7u^`aJ1B\>N  a[ pH ؟J  .iB u^`aJ1B\  ؁ a ?=0 = G'Ga   fB 'V "'  ][a +   gB ġ'V "'   \[][a  ( hB 'V "' 7  W^`aJ1B\ _^`NB\][a   WiB 'V "'  W ^`aJ1B\ ._^`NB\ ?O[][a \  j ]'k "'   (`Y``a   l   `: m][[[+``>I !  ݞ(+>N 1 Cn[ EpH dݞJ | .oB ݏ a ?J  .pB ݏaa ! !IoB 'l "' !* !I !+[ !2m[``a !M !{ !pB !N'l "' ! ! ![``a ! ! &;UB ! &; !e[+ !_^`NB\+ "q][[[+][>I "2"" "Q "68(+ "t "dD(+ " "b(+>J " ".rBa?I """% " "8][[[ # "D(+ #1 #!b(+>N #F #P[ #\pH #{8][[[J # #.sB #>a?I #""! #ށ #D(+% $ #8^`aJ1B\ $K $;b(+>J $\ $c.tB $r8^`aJ1B\ $Da?I $""! $ $b(+! $ $D(+% % $8^`aJ1B\>N %@ %Ru[ %TpH %sbJ % %.vB %8^`aJ1B\ %D %a?=0 % &'Ga &@ &` &wrB &A'T "' &n &w][a &{ & &sB &|'T "' & & &\[][a & & 'XtB &'T "' & 'X ' ^`aJ1B\ 'A_^`NB\][a '\ '| (vB ']'T "' ' ( '^`aJ1B\ '_^`NB\ 'q[][a ( ( (7w "' (. (7],`Ya! (< (Q (fx "' (] (f],`a<a" (k (} (y "' ( (],`Ya# ( ( (z "' ( (],`aDa$ ( ( ).Z ( ).]`aSJ ( (B`aS )[''{.a% )3 )8 )_| "' )D )_ )Q`Y\a& )d )i )W "' )t ) )2`aD\a' ) ) *A} ) *A )][[[\>N ) )[ )pH )= * .~B *!aJ *7a *F *i *~B *G'} "' *| * *}[\a * * +B * + *][[[ *^B\ +_^`NB\+][>N +$ +2[ +4pH +SJ +e +l.B + +݂ +aa + + ,kB +ơ' "' , ,k ,[ ,^B\ ,T_^`NB\][a( ,p , - ,q' , - ,][[[][>N , ,][ ,צ[= ,.B ,74 - + - + -0`>= - -St4 -2 -2 -o -3`N`>= -P -FSj -^aJ -v - -}Sua - - .B - . -][[[ -^B\ ._^`NB\+][>N .$ .2[ .4pH .SRJ .e .l.B .颁 .d .zaa . . /nB .ǡ' "' / /n /[ /!^B\ /W_^`NB\][a) /s / 0 /t' / 0 /][[[][>N / /][ /ܦ[= /.B 04 0 0 06`>= 0% 0t4 08 08 0u 09`N`>= 0V 0Lj 0dXaJ 0| 0 0u` 0 1 1. 1 1.]y`YJ 1 1 1`.l` 1} 1 1 1 1]y``J 1 1 1`.l` 2$ 2J 2 2Y 2]y`a*J 2b 2t 2b`.l` 2 2 3B 3 3B]y`RJ 3 33 3`.l` 3 3 3 3 3]y`RJ 3 3 3`.l` 4< 4Y 4 4h 4]y`YJ 4q 4 4q`.l` 4 4 5E 5 5E]y`RJ 5 56 5`.lнI7Բ_`׸GP۝{ eO޲ +`>R3yIt$SO2a* 6" 6M 9 6#'`Ra, 9 1``+a/ 6 6 7 pB 6 7 `a*>=0 6 6'a0 7 7 8J 72 8J 7:`: 7E.][[[+`a*>I 7[! 7m 7_(+>N 7 7/[ 7pH 7J 7 7a3 7 7?J 8 87a4 8Aa3 8N 8o 9B 8x 9 8y[ 8.[`a*J 8 8`a*'' 8e 8pa4 9 9) 91B 92 9 93[`a*J 9B 9B`a*'' 9\7a5 : : ; :'`a7 ; 6`+a8 ; C`+a; ; ;' ;ypB ;A ;y`a5>=0 ;J ;T'a< < < = <'`a> =n (`Y+aA = = + =RpB = =R`a<>=0 =# =-'aC =x = = "' = =],`a5*vaD > > ? >'`aF ?x (`Y+aI ? ? ?\pB ?$ ?\`aD>=0 ?- ?7'ZaJ @Z @ C @[ @} @'`aL C1`:+aM C`:+aO @ @ C6 A C6 A][[[`aJ>N A B + +[ B [''4# B@p$ B Bbp''`:J B B`aJ'' B BpB C&aQ Cr Cz CpB C C`aJ>=0 C C'aR D D`]`:[aS D D KV DƢ'`aRaV Ec Ek EpB E{ E`aS>=0 E E'aY E E FB E F E`:][[[J E EpG E[''. FaZ F F! Fy F' Fy F= s][`:[\>=0 FJ FT'a[ F~ F F5 F F FK[`J F F F.ae-4 F F F Fl][[[`J F F F( Fa\ F F F F F F[`J F! F F.B& F FN`:aY(+a] G G G- G G- G[][[[J G  G .B& G) G)`:aYa^ G2 G7 H G> H GDa`:[ˁK\\>N Gl Gt2[ Gv[''2.C G)>N G G[ G['' GRI G Gߜ`'g' G{J G?= H H +4 H `:'9' H'{ H9pG HX['' Hm{ad H H H H H]`:>N H H],`:1 H`:= H.4 H H H H+`: H[\J H H؀ Hd H;a^J H Hdae H I Ik I Ik]][[[>N I I%],][[[1 I,][[[= I4.4 I< I< IS I=+`: I@[\J IF IM IF<& IQ IQ][[[;a^J IZ Ia<af Ip Ix I( I I`J I I`'t'7.ag I I I  I I`J I I I.(af(ah I I IC I I`J I! I. aga_ I I JJ I JJ J `: J K[\>=0 J J%'a` JO JW J Jb J Jj `: Jw a[[>=0 J J'aa J J K  J K  J[`:>=0 J J'ab K K KT  K KT\>=0 K% K/'Yu$ +*9.)ai L1 LS Mn L2'`al L L MpB L M`ai>=0 L L'an M M M= "' M) M= M1K`:``ao MB M] Ml "' Mc Ml],``6wap NI Nh P NJ'`Rar Po `a<+as P d],`Y+at P (`Y+aw N N OpB N O`ap>=0 N N'ax O O O O) O O1`: O;.][[[`ap>N OT Od/[ OfpH OJ O Oa{ O} Oa{ O O PUB O PU O[ O.[`apJ P P`ap'' PA PG*Tja| Q Q T Q'` +a R B R'`+a S B R'`+a S= B S'`+a Sm B SL'`+a S `+a S `+a S`+a S `a+a S `+a T `+a Q Q R0 + Q R0]`J Q Q` Q.Ba R .Ba R.Ba R#.Baa Rl Rt RpB R| R`a|>=0 R R'ga T U W T'`Ra U4]l`R V +l`R'a V= l`+a VT `:+a Up Ux UpB U U`a>=0 U U'a V] Vd V Vh V Vp`:][J V VB[ V[''. Va V V V\ "' V V\a V V W V W]y`RJ V W Va.lTFa W X Z W'`Ca ZBR`+a ZS?`:+a Zf`:+a Z{`+a Z`:+a Z`+a Z`:+a Z`:+a Z Z Z8 Z$ Z8\? Z/C a Xr Xz XpB X X`a>=0 X X'a X X Y^ X Y^`aJ X Xᜣ`a'' YEB'!ya [ [ _ ['` a ^> `+a ^] `+a ^r `+a ^ `+a ^ `+a ^ `+a ^ `+a _ `+a _ `+a _2 `+a _J `+a _b `+a \ \$ \ipB \1 \i`a>=0 \: \D'a \n \v ]p \ ]p \][[[+`a>I \! \ \B(+>N \ \[ \pH \BJ ] ]&a ]0?J ]N ]aaa ]t ] ]B ] ] ][`aJ ] ]`a''ŀ ] a ] ] ^/1B ^ ^/`aJ ^  ^ `a''a _p _u _ "' _ _ _` _!`\a _ _ _ "' _ _\ 8   +aÁ a b d a'`DaŁ d| `:+aƁ d `P+aǁ d `+aʁ bk bs bpB b b`a>=0 b b'aˁ b b c b c b\][[[+`a>I b! b b !(+>N c c[ cpH c8 !J cH c^a ch ]?J c~ caa΁ c c dB c d c\[`aJ c cٜ`a''̀ d aρ d d) dj1B d2 dj`aJ d> d>`a'' + +   faЁ e e j e'`R aҁ ib  i>'`:+aӁ i{ `+aԁ i `:+aՁ i  i'`:+aց i `:+aׁ j `+a؁ j) `:+aف jI `:+aځ jc `:+aہ j{ s`:+a܁ j V`+a݁ j `:+a f3 f; fpB fY f`a>=0 fb fl'a။ f f g f g f`: f.][[[+`a>I f! f fc(+>N g + g/[ gpH g;cJ gQ gua gT g?J g ga gTa䁋 g h hB h h h +[ h.[`aJ h" h"`a''؀ h4 h?a偋 h h i81B h i8 h[`aJ h h֜`a''ـ i3 +a恋 k k s k'`Ca聋 m`+a運 n`+aꁋ n! `T++a끋 n|  n+ + n9' nU'],`[+a쁋 n(`+a큋 n`+a nK`:+a nB`+a n`+a nB`+a n `:+a o `:+a o: `g\+a oNK`:+a oc `+b m m m m m\? mC a l l' lnpB l6 ln`a>=0 l? lI'a ls l{ m  l m `aJ l l`a'' lB'1a ot oy oB "' o o o` o`]\a o o o "' o o o` o`\a o o o "' o o`b p p p! "' p p! p``Pb p& p4 pQ "' p= pQ pEK`:`]b pV p[ pr "' pi pr`b pw p| p "' p p pS`:\b q q, q\ q4 q],`]>N qB qJ\[ qQ.z`]'RJ q q`]& q q qŁ]`]b q q r q r],`]>I r0 r9.a>N rO rW\],`] r rf r^.\b4 rl rl r} rm`]`J rs ru rs]J r r`] rs>J r1 r`] r r.\b r.a98>y G&N b s s x sݢ'` b t `[+b t `+b t `[+b t `+b u `[+b u+ `+b uG `[+b u_ `+b uz `+b u `+b u `:+b tQ tY tpB td t`b >=0 tm tw'b u u u "' u u u``\b u u v  "' u v  u`[ ue`+\b v v v, "' v# v,\b v1 v6 vN "' vE vN\b vS vX v "' vd v vj`[ vv`+`b v v v "' v v\b v v vJ "' v v\b! v v w "' v w v`[ ve`+\b" w w w* "' w w* w```b# w/ w4 wu "' w: wu wB`: wP`: wb`:\b$ wz w w "' w w\b% w w w "' w w w``\b& w w w "' w w w`[\b' w w xW "' x xW x`[ x"` x3`[ xC`\b( x\ xa xW "' xl x xr`[ x}e`+\A_#mN]b) yi y {A yj'`Rb+ zM]l`R zfl`R'Sb, z `+b- z `+b. z C`+b1 y y z pB y z `b)>=0 y y'b3 z z z "' z z\b4 z z {i "' z {\b6 { { {?b {" {?]y`RJ {% {0 {%b+.lLYb7 | |> ~_ |'`Rb9 ~X S`N+b< | | |pB | |`b7>=0 | |'b= | | } } } }`: }.][[[`b7>N }3 }C/[ }EpH }d=J }x }b@ }. }Yb@ } } ~@B } ~@ }[ }.[`b7J } }`b7'' ~,Ё ~2 bA : Y U ;'`R`C bC M]l`R fl`R'SbD  '`:+bE M`:+bH   pB  `bA>=0  'bJ  "'  ` ],`+\bL  . Sb 6 S]y`RJ 9 D 9bC.l !!z!bM 0 X 8 1'`RbO K]l`Y fl`Y'bP `bA+bS pB `bM>=0  'bU 2 2]`brJ  B`br [''.bX 7 Y  h  q`:+]`brJ  B`br [''. #0bY   - ]],`brJ 9 9B],`br u[''.bZ u u `: \][[[+][>I ! ܁ $"(+>N [ pH $"J , 3.B ?$ D$^b\?J Z a.B m$b]b\ z B {' "'  [ \[][b] B ' "'  [][bV 6  6]y`YJ  ' bO.l"["##~#$%4%%b^  = P '`iWb` 3]l`R Ol`R' ba  +]l`R l`R'Zbb  ]l`T  7l`T ' bc  ]l`R l`R'bd ]l`Y )l`Y'be h `F{+bf `br+bi pB `b^>=0  'bk  ][J  B[ ͜[''.bm  /  /]y`RJ   b`.lbn 4 F k N k]y`RJ Q \ Qba.lbo p  ]y`T J   bb.lbp  ]y`RJ   bc.lbq % N / N]y`YJ 2 ? 2bd.l']'((T(()P)br + V  ,'`R bt 4 L`bA+bu \ `D+bv `bA+bw `[)+bx `^+by  `_+bz  `:+b{ ; i`dU+b| X `bA+ b pB `br>=0  'b d k 9 { 9 ][[[+][>I ! +?(+>N [ pH +?J  .B +|b?J  .Bbb > c B ?' "' v  w [][b B ' "' ][b   `: \][[[+][>I +!  ,(+>N + 5[ 7pH V,J f m.!B , ,b?J  ."B ,bb !B ɡ' "'  [ \[][b  @ a"B ' "' S a T[][b f s # } ]`J  B` [''$.b  ][J  B[ 朣[''%.*++,6,-l-.&.. b 2 & ߣ ' ''`Cb  \? C b pB `b>=0  'b  `bJ &   B'(N,`bb > N { X {`J [ cR'(b  ' ' "' ],`[//000w0b /    ' ' `Nz`N +b )`+b , `P+b S 6'`:+b n `:+b *`b+b +`P+b ,`P+b  -`P+b } / &'0 I'1],`d>+b +B`* +b pB `b>=0  'b u "'  ` !``Pb v "'  ` !`],`Pb   "'  `b b  ,  6 `J 9 9`'g$','-b .B  \>I ! b>= U M FBhc/'0ok= b)?b 7 1 !~ M `>= SbJ *b 1 ~  K`\>= bb  5 2 ~ G `>= MbJ *b 2 ~  K`\>= b2R223V334[455R5 +b  3 '3`b k`+b q y pB `b>=0  '66jb 4 '4`R`C b ]l`R l`R'Sb '`Z +b O W pB e `b>=0 n x'b     '`: :K`:+`b>I G! P K7w(+B>J a ub 7h 7w?J  b 7hb ?B ? [ K[`bJ  `b'4'5 /8 :8*bÁ C W 1B `  a[`bJ u u`b'4'6 8bŁ b ]y`RJ   b.l67?78i89!bƁ  7 ޢ'7`iWbȁ 8]l`R l`R'bɁ '`bʁ K`bˁ j K`:+b΁ t | pB `b>=0  'bЁ s x w "' } \bҁ  B '  ӣ ޣ "' '  ,` 6B` W^`SB\+ }^`NSB\+\bԁ . ^ ' £   "' C ^ H` RB``j9bՁ c ) d'  £ "'  ) `:`jsbӁ . :B /' \ ~  "' : `: ^`RyB\ $^`NSB\+\bׁ 9 ]y`RJ   bȭ.l9:0:f;,;<3<==b؁ : ';`Cbځ QK`:+b䁋   E 1 E\? <C b݁ ( mpB 5 m`b>=0 > H'b߁ Z e /< r / x\][[[+],`[>I ! >X(+>N [ pH >XJ  .=B >b?J  .>Bbb။ 4 Z z=B 5'< "' j z k\[],`[b⁋ ~ >B '< "' ],`[=>.>?Y?b偋 g? '?`R b灋 ]l`R l`R'b聋 ]l`R l`R'Sb運 >@`+bꁋ VA`+b끋 `w+b쁋 `e+b큋 `:+b B`+b C`e+b  D`+b ' `g+b   cpB + c`b>=0 4 >'b 7 < J "' A J\b O T xE "' ` x l`\b } F ~'E "'  `\b  "'  ` y`\b  ) )]y`RJ   b.lb . @ eb H e]y`RJ K V Kb.lA&ArAAB?BBC;b u uG`R]`bCb u uH`b]mj`bCb B d I C'I`b]`b],`b +c T \ pB n `b>=0 w 'c ( `J  `'t'h.c   ``b>I  `'g'Հ 1D΀ 8D΀ ?D F.(c=0 U _ pD.?J  `b'?'N. Dc + : : ` K`b\>=0  'c (  K`\>=0  'c   `b>I   .(cw>J ) 0`b'?'z.?=0 \ f('c 7 7`b>N V` .(cI  ǀ Fw>J  ۜ`b'?'N. Fy?=0  ('c < M & T &`b>N ^ bV` i.(cI u } yG(>J  `b'?'z.?I  ƀ G(=0  ('?=0  ('c + 8 [ A [ F``bJ P T. UHoc c  "'  ``bD DWDElEF#FGlHEHH +c #J 'K`Cc B`:+c `:+c `:+c `:+c `:+c  \? C c   WpB  W`c>=0 ( 2'c \ d  q `cJ w w`c'L' B'6IJGJc  7M 'N`Cc"   5 ! 5\? ,C c { ƒ pB  `c>=0 ™ £'c ] ]`cJ  朣`c'O' FB'PKKfKc#  1 ƝP 'P`c% Ɖ`:+c& ƕ#`+c) ŏ ŗ pB Ŧ `c#>=0 ů Ź'c* % %`c#>J  c-c- ) > }B G }`c#J S S`c#'P'QL,LxLMc. ǭ ǭR`]`c#MJc/ ǭ ǭS`c.]mj`c#M~c0 x Ǜ T y'T`c/]`c#],`c#c3 Ȑ Ș pB ȫ `c0>=0 ȴ Ⱦ'c4 2  2`c0>J + #c7c7 6 O ɖB X ɖ`c0J d d`c0'T'Uc? ɛ ɣ ( ɪ `J ɭ ɭ`'t'h.c8 ʦ ʦ ``c#>I  `'g'Հ "O% )O% 0O% 7.(c?=0 F P aO%.?J s z`c#'P'N. ʜO%c9 ʫ ʹ - ʼ - ` K`c#\>=0  'cD ˄ ˈ ( ˎ  ˓K`\>=0 ˠ ˪'c@ z z`c#>I   .(c?w>J  &`c#'P'z.?=0 S ]('cA  ̑ 0 ̖ 0`c#>N ̠ ̤V` ̫.(c?I ̷ ̿ ̻Q8w>J  Ӝ`c#'P'N. Q8y?=0  ('cB 5 G ! N !`c#>N X \V` c.(c?I o w sQ(>J ͅ ͌`c#'P'z.?I ͹ ͽQ(=0  ('?=0  ('c: & 4 W = W B``c#J L P. QRc8c; ΄ Ή κV "' Ζ κ Ξ3`: Ϋ#`+\c< ο W "'  `: #`+\c=   "'   ``c#MNN]NNOP&PzQQRRSPSScE I IX  ' + ''X`RcG Y]l`R l`R'ZcH @[]l`R ^l`R'\cI Ԁ]]l`R ԗl`R'ycJ ]l`ct l`ct'ScK !^]l`c <l`c'_cL ؀`]l`c ؚl`c'cM a]l`R l`R'bcN c]l`R /l`R'dcO We]l`R tl`R'fcP ݝg]l`R ݼl`R'hcQ i]l`R l`R'cR j`Y+cS k`+cT l`c0+cU /m`+cV I`:+cW Vn`+cZ Ы г pB `cE>=0  'c] b r  | `J  `'g'ocj j o } "' t }\ck  "' \cl i "' \c^ + 5p  5]y`RJ  & cG.lc_ q ]y`RJ   cH.lc`  >r # >]y`RJ & / &cI.lca b ]y`ctJ   cJ.lcb  = fs G f]y`cJ J W JcK.lcc t ]y`cJ   cL.lcd F X u c ]y`RJ f t fcM.lce v ]y`RJ   cN.lcf _ q w } ]y`RJ   cO.lcg 0x 0]y`RJ  ! cP.lch y y ]y`RJ   cQ.lc[ G G`cE>J  ޜ`cE'X'zWWgWWX"XYXYYUYYZPZZ[L[[\Bcm $ { % G' + V'{`co ] |`+cp y }`:+cs NpB  N`cm>=0  )']]Mct ` ~ a ꃣ' + ꒢'~`Rcv S`:+cw `:+cz  " rpB : r`ct>=0 C M'c{ w    `: ][[[+`ct>I ! Ɓ ^Q(+>N [ pH ^QJ  6c~ @^B F^?J ] {c ^Bc~ 5B 5 [ [`ctJ  ͜`ct'~' _" ,_-c 9 W 1B `  a[`ctJ p p`ct'~' _]^^_m_c    ' + '`Rc ' `M+c ? `M+c \ `+c A m' '],`c+c z pB `c>=0  'c   `: ][[[+`c>I ! & a3(+>N ; F[ HpH ga3J x c a$ ap?J  c a$c  B   [ [`cJ - -`c'' b bc 1B  [`cJ  М`c'' b}``abObc ) P У ' + '`c `+c  (`+c pB `c>=0  'c  8 N "' < N A``cmc?ccc + L  ,'`Rc F`+c `+c  `+c t 6 6],`c>N ],`c .BcI   d(Yw= ?'  d9?J % ,dc s { pB `c>=0  'c   " "'  "\c ' Y lB (' "' c l],`cc q v Z "' { \c ] "' \c  "'  `c\d\e"eneef/fffc  '`Rc `+c `+c K`:+c `c+c 9 A pB W `c>=0 ` j'g]gc F '`R c ]l`c l`c'c D]]l`c [l`c'yc ]l`R l`R'Sc ]l`c l`c'=c 'm]l`R @l`R'Zc v]l`c l`c']c i]l`c l`c'c `:+c `+c `+c `:+c 1`c+c ?`+ c t | pB `c>=0  'c % -  E  N`:+`c>I [! d _j<(+B>J u c j<?J  ccŁ   cB  c  [`cJ  `c'' ^jcƁ g  1B  `cJ  `c''cȁ     ]y`cJ   c.lcɁ 2 S tr Y t]y`cJ \ e \c.lcʁ b ]y`RJ   c.lcˁ +J +k + +r +]y`cJ +u + +uc.lć + + T + ]y`RJ +  +c.lć f V ]y`cJ   c.lc΁  Dy ' D]y`cJ * 5 *c.lijjk +k[kllVllmRm cρ ! G  "'`cс ' A 'Y`+cҁ E `:+cӁ Y `+cԁ w K`:+cՁ   '`:+c؁ pB `c>=0  'nncف    '`cہ ^ `+c܁ w `[+c݁  `+cށ  `[+c߁  `+c⁋   NpB  N`c>=0  )'oocか  `]`:`:pc䁋     + '`cc灋 v =B Y'(`+c運   t  t 3 s][`:`:\>= F @p4 N N o O+`: R`:`>= a. bp gqcxcꁋ   5   K``J   .c-4    l`:`J   q( qpBc끋   3  3 ``J ! , .B& ' 'r `:c(+Bc쁋 8 H g J g R``:J Z Z.B& c cr`:cc큋 l z  }   `:  K`:\>= .B s scc   :  :  `:  a`:`:>I ! . sc= . s  sc?J & 1. 2scc ? F  L  T``:>N e kK`: q. rt@c= |.B&  t@`:cJ  tYc      \J  .Bcc   r  r a`:`:ˁK\\>E   `) uS  uSW>N " &`: (.B -uScI 7 ? ;u(+BJ H?= X Wu, Yu b. cucc w    ]`:>N  ],`:1 `:= .4    +`: `:\J  ˀ vQ v;cJ  vQc   d  d]`:>N  ],`:1 %`:= -.4 5 5 L 6+`: 9`:\J ? F ?w* Jw|;cJ S Zw*c i q ( x `J { {.=Bcc      `J   .Bc(+Bc   C  `J ! . cd  +  SpB  S`c>=0 $ .'c   B ' "'  \c   B ' "'   `:`:c   B ' "'    ``:c  : XB ' "' E X M`:\c ] w B ^' "'   `: K`:\pqFqrtrsUttuvvwxxkxxyDyyzTzd   $)  + '`Rd " `:+d " q`:+d " `:+d # `c+d # `:+d ( 0  <  D`: V`* s`* `:+ `:+ q`:+ `:+ `c+`d>N  l`d&   BB'N`d= 8 6|uB S{ Y{ d| p| u|, |< |L |\dJ  |ud !pB ! `: .][[[+`d>I ! ! }d(+>N ! !'/[ !)pH !H}dJ !^ !rd !|}U !}?J ! !d !}Ud ! ! "EB ! "E ![ !.[`dJ " "`d'' "1~5 "7~@d "I "] "1B "f " "g[`dJ "v "v`d'' "~d #& #I $'B #'' "' #Z $' #ii`: #}` #` #`: #`: #`: #`: $`c\{}(~~~d % %$ & %'`d % % %pB % %`d>=0 % %'d % % &; % &;]][`:[J &  & B &[''.d &@ &M & &T &]`J &Z &ZB` &p[''.d & & & & &]`J & &B` &ɜ[''.>]d *b * , *c'`Cd ,`+d ,B`:+d , `d>+d ,`:+d$ ,y ,y , , ,\? ,C d! * * +/pB * +/`d>=0 + + +'d" +4 +< + +H +`dJ +N +N`d'' +B'<d% - - . -͢'`d' . `:+d* .C .K .pB .W .`d%>=0 .` .j'd, . . . "' . . .`:`7d- / / 1& /'`d5d0 0A 0I 0pB 0[ 0`d->=0 0d 0n'd2 0 0 0 "' 0 0 0`: 0K`\d3 0 0 0 "' 0 0 0`:\d4 0 0 1$ "' 0 1$ 1`: 1K`\[Kd5 2 2+ 3 2'`d8 2 2 2pB 2 2`d5>=0 2 2'd: 2 3 3 "' 3 3 3 `:`LXd; 3! 35 3S "' 3; 3S 3C`:],`LXd< 3X 3e 3{ "' 3r 3{],`:d= 3 3 3 "' 3 3 3`:`(xd> 4} 4 5 4~'`d@ 5J`+dA 5d `:+dB 5} B`Y+dC 5 `[+dD 5 }`d>+dE 5 `:+dF 5 `:+dI 4 4 5@pB 5 5@`d>>=0 5 5'<dJ 6 6 8 6̢'`RdL 8 `+dM 8 `:+dP 7D 7L 7pB 7W 7`dJ>=0 7` 7j'dQ 7 7 8& 7 8& 7`: 7][[[`dJ>N 7 7Q[ 7pH 7,J 7 8 dT 8 8HdT 8* 8; 8B 8D 8 8E[ 8K[`dJJ 8Z 8Z`dJ''ǀ 8 8 +dU 9 9 ;# 9'`dX : : :]pB :% :]`dU>=0 :. :8'dZ :b :w : :~ :]],`:J : :B],`: :[''.d[ : : ;! : ;! :`:][J : :B[ :[''. ;/Ntd\ ; <' >r ;'`Cdb >A >A >p >\ >p\? >gC d_ < < <pB < <`d\>=0 < <'d` < < = = =`d\J = =`d\'' =vB'?dc ?M ? B+ ?N'`Cde A `+df A`+dg BL`:+dh B"`+dn A A A A A\? AC dk @ @ @_pB @' @_`dc>=0 @0 @:'dl @d @l A @| A`dcJ @ @`dc'' @B'ndo C C+ Eg C'`Cdq EaP`+dw E- E- EX ED EX\? EOC dt C C CpB C C`do>=0 C C'du C C D| C D|`doJ C C`do'' DfB'Hdx FB Fd Q FC'`Cdz N?`d\+d| N B NL' N^' N'],`[+d} O B N' N͡' N'],`[+d~ O=`d+d O[`d+d M M N& N N&\? NC d F F F F F],`dJ F Fo%`d F.Bd}d F G G6 G G6],`dJ G Go%`d G0.Bd|d G; GK Gr GQ Gr`d>J GZ Ga. GkWdd Gw G G G G`d\J G G.Bdd G G G G G`dJ G G.Bdd G G H H H`dJ H H.Bdd H H4 HS H? HS`dJ HE HE.Bdd HW Hg H Hp H Hu``dJ H H.B H dd H H IsB H Is`d>I H Hœ`'g'.>J H H.Bd?N I I%`P I+Qt'= IS IJ.LQ IW;J Ic& Ic Ij`dd Ix I IB Iy' "' I I`dd I I L) I L) I`: J`p+ J$`p +`Nz>I J: JD`F>J Jn J{ Jс J҂ JR6?N K' K6`:$ KN' KA'N KX K^`P KdQs Kq с K҂ KN K K`Nz KN= K K Kr[ L L3[=0 L L'd L L MM L MM`dxJ L LӜ`dx'' M5B'd Oe O OB Of' "' O O`d\d O O OB O' "' O O`dd O P$ P9B O' "' P0 P9`dd P> PC PY "' PP PY\d P^ Pc P~ "' Pl P~ Pq`\d P P P "' P P\d P P P "' P P\d P P QB P' "' P Q P`+`d\KDc$|cNd Q R X Q'`Cd X B W' W' Wԡ'],`[+d X `+d X- `+d Wn Wn W W W\? WC d R. RI R RO R],`dcJ RX R\o%`dc R{.Bdd R R R R R`dc>J R R. RWdd R R S R S R``dcJ R& R R.B Rd`dcd S S U S& U S.`: SI`p+ Sf`p +`Nz>I S| S`F>J S S S;с SK҂ T[R6?N Ti Tr`Nz TxNN T T`[ U' U T Td T;с TK҂ U[d[N U7 U;`[ UK UE U=ّ[= Uf U` UW[ Uq Um=[=0 U U'd V# V+ V V: V`dJ V@ V@`d'' VB'd XA XF Xb "' XP Xb XU`\d Xg X XB Xh' "' X X X`+`CJYd Y Y _Y@ Y'@`Cd ^ B ^' ^' ^'],`[+d ^Q ^Q ^ ^l ^\? ^wC d Y Y Z& Y Z&],`dJ Y Zo%`d Z .Bdd Z+ Z; Zb ZA Zb`d>J ZJ ZQ. Z[Wdd Zg Zw Z Z Z Z``dJ Z& Z Z.B Zd`dd Z Z ] Z ] Z`: Z`p+ [`p +`Nz>I [ [$`F>J [N [[ [j.с [>҂ [NR6?N \ \`Nz \NN \2 \:`[ \ \ \X \@d \g.с \>҂ \Nd[= \ \ڃ \[ \ \̑[=0 ]q ]{'d ^ ^ _ "' ^ _ _`\d _ _9 _WB _' "' _C _W _I`+`C=vedÁ `4 `[ a@ `5'@`^`dŁ a/ @`:+dƁ aL @`:+dǁ ak @`:+dȁ a @`:+dɁ a  a'`:+d́ ` ` apB ` a`d>=0 ` `'Hd́ b c gz@ bѣ b b'@`Cdρ e `Nz+dف d d d d d\? dC dҁ c c cpB c c`d>=0 c c'dӁ c c d c d`dJ c& c c cB'@ N,`ddՁ e6 eF eu eP eu`J eS e[R'@ dׁ f~ f gx f gx f`: f`p+ f`p +\>= f.+[N f g`Nz g. gUс g-e҂ gGuR6= gd g\.dϣ gk\8+dځ h h j@ + h'@ +`FWd܁ i `b+d݁ i @ `:+d߁ h h iG h iG h`:`dJ h hҜ`d'@ '@  i2B iBd။ i i ipB i i`d>=0 i i'dか j jJ jpC j ' j)' "' jg jp],`[d䁋 ju jz j@ "' j j je``d|9d偋 ks k qh@ kt'@`Cd灋 m+`:+d聋 m`+d運 n@`+dꁋ nA`:+d끋 n(-`:+d쁋 n9`+d큋 nX `T++d n  nb + np' n'],`[+d n0`+d n*`+d nK`:+d n`:+d o`+d o B`+d o1`+d oA1`:+d o\2`+d oq3`+d o @`+d o `:+d o `:+d o `g\+d oK`:+d p `+d p+T`:+e m m m m m\? mC e k l lIpB l lI`d>=0 l l$'e lN lV l le l`dJ lk lk`d'@' lB'e p4 p9 pO "' pF pO`e pT pY pp "' pg pp`e pu pz p1 "' p p\e p p p "' p p pS`:\e p p q; "' p q p`: p`+ py`+ q<`:+\e + q! q& qf= "' q7 qf q<` qGy` qT`:+\#}*oJe rC ra t6@ rD'@`e r r s pB r s `e >=0 r r'e s s sQ s% sQ`e >J s. sBee sU si sB sr s`e J sx sx`e '@'@e s s t4p s t4 sq[]],`M^J s sB],`M^ t[''r. t-7 e u< uc w@ u= + uI'@`fSe wV `:+e u u v u v u`: u`* u`* u`h+ u`:+`e>I v  v v (+>= v# v*B?N vF vHl`e& vF vS vJBB'@N`e= vt vr0@B v v vă vԄ veJ v v0e v w wDpB w wD`e>=0 w w'e w_ w w@B w`'@ "' w w w`: w` w` w`h w`:\{e x x {@ x'@` e" y @`+e# y @`+e$ y @`+e% z @`+e& z( @`+e' zI @`+e( zf @ `+e) z @!`+e* z @"`+e+ z @#`+e, z @$`+e- { `+e0 y6 y> ypB yK y`e >=0 yT y^'je1 { | + w@% {'@%`Re3 }@&]l`R }l`R'@'e4 ~ @(`eT+e5 ~- @)`eT+e6 ~C .`:+e7 ~W G`:+e8 ~m `:+e9 ~ `:+e: ~`:+e= |d |l |pB |w |`e1>=0 | |'e? ~ ~ ~@* "' ~ ~ ~@+`eC\e@ ~ ~ ~@, "' ~ ~ ~@+`eC\eB 6 H u@- T u]y`RJ W f We3.leeC R p @. S'@.`ReE @/]l`R +l`R'YeF D@0]l`R \l`R'[eG @1`+eH .`:+eI @2`+eJ `+eK (`e1+eN pB `eC>=0  'eP ! 3 X@3 ; X]y`RJ > I >eE.leQ a ]y`RJ   eF.l1eR @4`]`eCeS @5`eR]mj`eCNeT K@6 '@6`eS],`eC]`eC eW pB `eT>=0  'eY   C( % C`J ( (`'t'h.e^ H ^  `  e``eC>I r v`'g'Հ c c c .(eY=0   c.?J  `eC'@.'N. ce_ $ 2  5  :` N K`eC\>=0 [ e'ee U(  U K`\>=0  'eZ Z k  q `eC>I w  .(eYw>J  `eC'@.'z.?=0  ('e[   `eC>N  V` .(eYI * 2 .zw>J ? F`eC'@.'N. k gzy?=0 { ('e\  `eC>N V` .(eYI  ;(>J  `eC'@.'z.?I ) 1 -;(=0 7 A('?=0 ` j('e`   ``eCJ  .  e^eb IB "'  ``eCec - I@7 "' 7 I ?.`:`eC:fF@ ef S S@8`R]`e19eg S S@9`ef]mj`e1oeh & E @: ''@:`eg],`e1]`e1ej uH]l`f l`f'Iek 4]l`R l`R' en & . upB = u`eh>=0 F P'ep , 4 Y( ; Y`J > >`'t'h.ew ^ q / s / x``e1>I  `'g'Հ    .(ep=0   .?J  `e1'@%'N. %ex 4 B  E  J` [ K`e1\>=0 h r'e~   \( \ K`\>=0  ''eq a o  u `e1>I {  .(epw>J  `e1'@%'z.?=0  ('er    `e1>N  V` .(epI ( 0 ,w>J = D`e1'@%'N. f by?=0 v ('es  `e1>N V` .(epI  ¾(>J  `e1'@%'z.?I  & "¾(=0 , 6('?=0 U _('ey   ``e1J  . Ïewe{ IB "'  ``e1e|  4S "' " 4 *.`:`e1et | X ]y`fJ   ej.leu  ]y`RJ   ek.l#o=ŠeZĮ e @; ڢ'@<`Ce `:+e T T { g {\? rC e V ^ pB k `e>=0 t ~'e l @= m + y'@=`e J (`+e ;pB  ;`e>=0  'e U \ qy "' _ q d``[e v }  "'  ``[rƾRe @> '@?`Ce  \? C e   apB ) a`e>=0 2 <'e f n  z `eJ  `e'@@' B'!{e @A '@A` e a B C'`+e B o'`+e b`+e `+e B ȡ'I`+e B 'J`+e 6 @BB '`+e b @CB D'`+e | `:+e M`+e B 'K`+e B С'L`+e B L'c `'@D '@D[+e  % dpB , d`e>=0 5 ?'e i q  v  {][[[`e>N [ pH !J  e =e  =B + = [`eJ  `e'@A'@E 4˫e Gc  G`RJ  B ;.Bee : B s@FB L s`J O& O l O[''@G.`e w  @HB `J &   [''@I.`e @JB `J &   ɜ[''@K.`e *@LB  *`J &  # [''@M.`e . 6 c@NB > c`J A& A \ A[''@O.`e g o @PB w `J z& z  z[''@Q.`e @RB `J &   [''@S.`e @TB `J &   [''@U.`e  % N , N]`J / 3` 9.@FBe D.@HBee S ] y b ]`J e i` o.@NBe x.@PBee  ]`J  ` .@JBe .@LBee  3    ' 3`J * *.@RBee 8  9 [ f  `J  .@TBeʬ}:̣ uGΰς_;Ѩe @V '@V`fSe j w`+e @W`e+e y`+eÁ |`+eā ~`+eŁ @X`e+eƁ  W`e+eɁ ) 1 upB = u`e>=0 F P'eʁ z   `: .][[[+`e>I ! ǁ S(+>N /[ pH SJ # 5e ?D EӐ?J a se }Dé B  [ .[`eJ  Ĝ`e'@V'@Y $ /e΁   Z1B  Z [`eJ / /`e'@V'@Z UԡeЁ  `J  p'@Vs%eс 8 8@[`]`ekeҁ 8 8@\`e]mj`eաeӁ  . @] '@]`e]`e],`e eՁ  `eJ +eׁ ; C pB N `e>=0 W a'eف  `J  蜣`'g'@^eځ   B( $ B`J ' '`'t'h.e߁ G V  X  ]``e>I j n`'g'Հ < < < .(e=0   <.?J  윣`e'@A'N. <e  #  &  +` 8 K`e\>=0 E O'e䁋 1( 1 K`\>=0  'eہ 6 @  F `e>I L \ U.(eڃw>J i p`e'@A'z.?=0  ('e܁ b b`e>N V` .(eI  Sw>J  `e'@A'N. + 'Sy?=0 ; E('e݁ g q C x C`e>N V` .(eI  (>J  `e'@A'z.?I  (=0  ('?=0  ('e။ H N q W q \``eJ f j. kee⁋  "'  ``e*v?ؓڻc e偋 3@_ '@_`e灋 @``:+e聋 @a`+e運 `:+eꁋ  `:+e끋 - `:+e +  XpB X`e>=0 ) 3'e ] e ( q ( `: `: `: @a],`: @``:+`e>I ! (+B>N @b],[ pI 7J E Ye nܻ tʂ ~م ; ?N @b],[ pI J  e ܻ ʂ م ݩe , @ B I  U[ [[ e[ l@a[ s@`[`eJ  `e'@_'@c : E P [ he  1B   [ #[ -[ 4@a[`eJ > >`e'@_'@d    Fܒ pe  0 @e '@e`e (`+e pB `e>=0  'e   C],`e+`e>I +! = /H(+>J N fe pH?J  ee /B / C[`eJ  `e'@e'@f !e 3 K 1B T `eJ ` ``e'@e'@ge  "'  ``e uf O ó@h  ͣ ֣ '  % .'@i`C f ¨@j`f @k`f `f `f /A 'Y`+f GG`:+f W`:+f k "`+f + Á`:+f Ð@l`:+f ì (`e1+f  \? C f pB `f>=0  'f  8  8`fJ &  " B'(N,`ff V f ’ p ’`J s {R'(<f Ď Ķ h@m ď + ě'@m`Rf a ( B'`+f  WpB  W`f>=0 ( 2'f \ d h n h v`: Ł.][[[+`f>I ŗ! ũ ś(+>N ž /[ pH J  f !r '?J C Uf _rf l ~ B Ƈ  ƈ[ Ǝ.[`fJ Ʀ Ʀ`f'@m'@n R ]f <1B  < [`fJ  `f'@m'@o 7I$ +f C z ː@p D'@q`Rf" F `+f# c *`:+f$ ˁ `:+f' %pB %`f >=0  'f( * 2 E A E I`: T.][[[+`f >I j! | n!(+>N ɑ ɡ/[ ɣpH !J  f+  ^?J  2f, <f+ I ` B i  j[ p.[`f J ʈ ʈ`f '@p'@r ʺ f, 71B 7 [`f J  `f '@p'@s 2oAf- k ̓  l + x'`f/ ͹*`[+f0 `\ +f1 L`[+f2  `+ f4 ̶ ̾ ' ' L`[ ``f->J   BB ꂁ +Nf6 c k ͯpB w ͯ`f->=0 ̀ ͊'f8   * "' ! *`[f9 / 4 F "' = F`[f: K P a "' X a`[f; f k  + "' v `[f< ΄ Ή Μ "' Γ Μ`[f= Ρ Φ λ "' β λ`[f>   "' `[Y*eQ f? Ϻ @t ϻ'@u`fB 3 ; ЀpB H Ѐ`f?>=0 Q ['fD Ѕ И в. "' О в Ц`:`f?fE з @v "'  `:`f?'s fF @w ʢ'@x`fI L T ҞpB f Ҟ`fF>=0 o y'fK ң һ @v "'  `:`fFQfL ӹ @y Ӻ'@z`fO 0 8 |pB D |`fL>=0 M W'fQ ԁ ԓ Ԭ "' ԙ Ԭ ԡ`:`fLfR Ա @v "'  `:`fL-yfS  @{ '@{`RfU | `+fV ڥ @|`Vm+fX \ @}B ' ' 2'[+fY ە B k' ~ +`+f[ q y ا ׀ ا ׈`: ל`h+ ׬` `) `)`fS>I  9(+>= 9 B?N 2 4l`fS& 2 ? 6BB'@{N`fS= ^ \@~B k) qY |i ؈9 ؎IfbJ ؛ آf] ج ش ٱpB ؽ ٱ `: .][[[+`fS>I ! (+>N /[ pH >J T cf` mz s?J ُ ٞfa ٨zf` ٵ "B " [ .[`fSJ  윣`fS'@{'@ Z efa & 5 m1B > m ?[`fSJ H H`fS'@{'@ hfd ڼ  `lJ  B .@}BfXfb ۠ ۾ @~B ۡ'@ "'  `: ` ` `h `\M,hfe  7@ '@`Cfk 5 ! 5\? ,C fh x ݀ pB ݎ `fe>=0 ݗ ݡ'fi \ \`feJ  圣`fe'@' GB'5fl  8 :@ '@`fo pB `fl>=0  'fq R  R `][J  B[ .[''@. Jfr W \ w@ "' n w\fs | @ "' \ft @ ][J  B[ œ[''@.fu 8 8 `][J  B[ [''@. 0-y6otfv  9 @ '@`Cf{  \? C fy pB `fv>=0  'Of| H@ 塢'@` f~ ]`:+f m`:+f }F`:+f `:+f `:+f `:+f `:+f '`:+f ]`:+f -`:+f & @`f+f >`:+f x@ x @[`:J  `:'9'@ _f } @  6`Yr`:J  œ`:'9'@ 6f   @ 5  B`Y`:J S S`:'9'@ f @  P`E`:J  ٜ`:'9'@ f # / @ >  F`:\J T T\'7'@ qf A `:J  谜`:'9'.f  QpB  Q`f|>=0 " ,' +sE?f # D n@ $'@` f pB `f>=0  'f     `+`f>I '! 0 + (+>J A Xf b ?J s ff B  [`fJ  ͜`f'@'@ f   `1B & ``fJ 2 2`f'@'@f e j  "' p  xK`: K`:\f  "'  K`:\f  "'  K`:`:f  "'  K`:],`:f +  & "'  & K`:`f + 0 U "' 3 U ;K`: HK`:\f Z _ l "' c l\u3c7 f I X @` f  `:+f 3 `:+f I F`:+f c `:+f y `:+f `:+f '`:+f ]`:+f -`:+f pB `f>=0  '\f @ '@`Rf % - ipB 1 i`f>=0 : D'f n u @  ][J  B[ 򕜣[''@.6f @ '@`f  lpB 4 l`f>=0 = G'f q } @ "'  s`f``!kf K@ '@`Rf X @`:+f r @`+fā  FpB  F`f>=0  !'fƁ U@ U \][[[+][>I ! [(+>N [ pH [J  .@B !f?J 7 >.@Bffȁ Z } @B ['@ "'  \[][fɁ @B '@ "' ][f́ @  \][[[+][>I !  (+>N 1 ;[ =pH \J l s.@B f?J  .@Bffʁ @B '@ "'  \[][fˁ + . I@B '@ "' @ I][/Xw#f́ & E N@ ''@`Rfρ F @`f+fҁ pB `f>=0  'fӁ    `: .][[[`f>N 1 A/[ CpH b J v f   6fց 2B 2 [ .[`fJ  `f'@'@  $   fׁ ) D@ *'@`Rfف + @`f+fځ @`+fہ 0@`+f܁ H O`+f݁ c `:+fށ ~ @`+f߁ @`gT+ f⁋ pB `f>=0  'f䁋 @ "'  `\f偋 4@ 4][J  B[ [''@.f恋 9 I q@ "' Y q a@`:`gf灋 v { @ "'  @`g `f聋 @ "' ],][[[f運  +@ "'  + ^`]B\`fꁋ|@$|/@],][[[][J@@B[P[''@.t Hf끋@ "'\ + =   . |    f쁋w@ x'@`fk @`+f @`+f ]`+f @`+f [pB#[`f>=0,6'f@ '@`Rf `f+f `:+f (ppB8p`f>=0AK'fu}`:.][[[+`f>I!Ɓ(+>N/[pH J"8fBƂH?JdzgfB[.[`fJϜ`f'@'@ǀg-y1B6y7[`fJFF`f'@'@Ȁt#Qx^g@ '@`gs e``+g @`+g @`+g \pB$\`g>=0-7'=g    @  '@`g  + @``+g  " @``+g  B R`g+g ] @``+g @``+g + +  +QpB + +Q`g >=0 +" +,'g +V +^ + +i +`g >J +r +gg + + +B + +`g J + +`g '@'@<g u  @  v'@`fg p v`gG+g @`+g   WpB  W`g>=0 ( 2'Pgp@ q'@`g > Z``+g!h [``+g" ^``+g# _``+g$ ``+g% 1``+g('pB'`g>=0'Zg)A@ '@`Rg+]l`R l`R'g,7]l`R Pl`R'g-|@`+g.@`+g/ @`f+g0 `+g3X`pBk`g)>=0t~'g5y][JB[[''@.g6 @)1`:<\][[[+][>IL!XP(+>Nmw[ypHJ.@B}g8?J.@B}g9g8Br@B '@ "'\r][c\[][g9v@B w'@ "'[][g;]y`RJg+.lg<?"?]y`RJ%0%g,.lQ@Vg=<N@ '@`Rg?E ?`g)+gBpB`g=>=0'gC`:.][[[`g=>N+;/[=pH\JpgFgF0B0[.[`g=J윣`g='@'@ۀ2"=ggG)H#@ *'@`gI @],`gM+gLpB`gG>=0'4gM"@ '@`gO `+gP "`+gSpB`gM>=0'gT @ ע'@`gV @``+gW @`+gX @`+g[[cpBv`gT>=0'wg\ @ '@` g^ @`+g_ @`+g` @`+ga  @`+gb / @`+gc M @`+gd i @`+ge @`+gf @`+gg @`+gh @`+gkaipBx`g\>=0'bgl!!''@ !'@`X~`lgn$`+go$*@`:+gp$? @`+gq$Y @`+gr$ @ $i'@ $$ $$ݣ`+gs% @ %'@ %-%O %Z%|`+gt%`+g~##$#$\? $Xgw"O"W"pB"e"`gl>=0"n"x'gx""#6"#6`glJ""`gl'@'#B'gz%%%@ "'%%`gg{%&p&@ %'@ &&4 &?&a "'&&\g|&''%[ &'q &&ң &ݣ& "'''%\ !A!!"E"g((()c@ ('@`g( @`+g) @`+g)0 @`+g)Q A`+g(((pB((`g>=0(('#b#g*>*Z+A *?'A`g+ .`:+g+' G`:+g+= `:+g+T `:+g+f`+g+ A`b+g**+pB*+`g>=0**'$y$g,o,.tA ,p'A`Rg-k4]l`R -l`R'g- (`+g- `+g,,->pB-->`g>=0--'g--.IB "'-.-``gg. ..4S "'.".4.*.`:`gg.9.K.r.T.r]y`RJ.W.c.Wg.l%f%&&I&g/O/o2 A /P'A`R g0K]l`R 0el`R'g0]l`R 0l`R'g1 `+g1 `+g11 `+g1I A`+g1` A`+g1v `+g1 `+g//0pB/0`g>=0//'g11111]y`RJ111g.lg112 12 ]y`RJ111g.l'(>((g4 4!6A 4 +'A`eCg5A `:+g5 5ʡ' 5ݡ'A +`+g681 6' 6'A +`+g6O`g+g6^B`+g6lA `+g6`:+g6A `:+g4y44pB44`g>=044'g44594594`4@1`4`:`g>J55g5*5'*50*g5=5K5B5T55U[5`@1[5i[`gJ5x5x`g'A'A 5+35+>5+KgÁ666A 6'A "'66`Nz***v+++gā779A 7'A`gƁ9.`:+gǁ9`+gȁ9'A`+gɁ9=A`+gʁ9V`:+gˁ9eA`+ǵ9}A`+ǵ9`+gЁ828:8}pB8E8}`g>=08N8X'gс88888`g>J88ggԁ889B89`gJ88`g'A'A,-<--gՁ?2@QA ?3?U ?^? ??' ??٣ ? + ?'A`RgׁA]l`F Al`F'wg؁B]l`R Bl`R'SgفD]l`Y D/l`Y'gځEN]l`R Efl`R'gہG`g܁GA`g݁G`gށH`g߁H$`:+gH= `+g။H] A`:+g⁋Hy ]`:+gかH "`+g䁋H `:+g灋@b@j@pB@u@`g>=0@~@'g聋EEF=EF=E`:E;`+`g>IE!EӁE0(+>JEEgE0F0?JFF+gF50g끋FAFRFBF[FF\[Fa;[`gJFuFu`g'A'AF1OF1Zg쁋FFF1BFFF[`gJFFќ`g'A'AF1gG>GNGGXG`JGaGa`'g'Ag큋HHHw "'HHHQ`+H`:+\gJJJ' "'JJ'J[\gJ,KoK J-' "'KwKK}`E\gKLL K' "'LLL`\gLN?N] L' "'NIN]NQ`:\gNbOO Nc' "'OOO`\gP +P!PFP)PF]y`FJP,P7P,g׭.lgPPPbPP]y`RJPPPgح.lgQQQCQ$QC]y`YJQ'Q4Q'g٭.lgQQQQQ]y`RJQQQgڭ.l0"0n1!122V223A334944545gRRbA R'A`ZgY@A`gYkA`gYA `gY A!B Y'`+hY A"B Yܡ'`+hZ A#`+hRRWCRWCR`:S`h+S`S&`S;A#`SPA$`Sh`S}K`SL`S`S`S`S`)T`)T$y`*T?w`*TY~`*Tu|`*T`R+`g>NTT\][`:`2T`:`'ՁT6'A$T77'T7'U7'A#U/7%'UG7I'KU`7Y'LUz7i'U7y 'U7 +'U7 'U7 'U7 'yV7'wV57'~VO7'|Vj7'V8 IVVV6(+>=V6VB?JVV`g'A'A%W 6WpHW68"hWHWPXVpBW\XVWd`:Wo.][[[+`g>IW!WW9(+>NWW/[WpHW9JWXhX9X:-?JX1XCh XM9hXZXlXBXuXXv[X|.[`gJXX`g'A'A&X:X:h XXY*1BXY*X[`gJXX`g'A'A'Y%;>h [)[1[[8[`>I[>[B`'g'A(.>J[[.A"Bh?=0[['A)h\]]] ]`>I]]`'g'A*.>J]a]m.A!Bg?=0]]'A+h]]^A$]^`>I]]ڜ`'g'A,.>J^^`'t'A-.?J^h^^^A.B^^`J^^`''A/.h^^_A0B^_`J^^㜣`''A1.h___5B__5`J__`''A2.h_:_C_A3B_\_`J_e_e`'g'A4.h +__a A5B _'A6 "'_a _`:_`` +``#`h`3``EK``XL``k``~``y``w``~``|`````RaA7`\ha%a.alA8BaAal`JaDaD`'g'A9.h apabA:B aq'A; "'abaD`:a`a`a`hb`bK`b)L`b<`bO`bb`b|`RbA<`:b`b`bA#`bA$`\69:;;y;<<=S==>S??A+hhh01"A= h'A>`R`i2`l`T`k`i!Ch A?]l`R .l`R'A@h`AA]l`Mr l`Mr'ABhAC]l`M l`M'ADh%]l`R Cl`R'h]l`R l`R'h]l`Y l`Y'h]l`R +l`R'hB]l`R \l`R'h tAE]l`R l`R'AFh!AG]l`R l`R'AHh"]l`_; l`_;'h#_%]l`R {l`R'h$]l`d l`d'wh%]l`R l`R'h&mAI  2]l`C l`C'h''AJ  ʣ]l`C Ml`C'h(AK _ ]l`C  l`C'h)`h*2`h+S AL`k+h, AM`D +h- AN`k+h.; AO`E+h/Q `+h0n AP`F+h1@ `F+h2g AQ`L+h3AR`:+h4AS`:+h5F `+h6j AT`S+h7\ AU`UU+h8K AV`+h9; AW`+h:U AX`+h;S AY`c+h<i AZ`D+h= A[`D+h>QK`:+h?I [`[1+h@N A\`+hB A]B 'A^ ġ' '[+hIt `+hJ `:+hK A_`+hL A``+hC@ AaB 'Ab`+hD AcB R'Ad`+hE AeB N' b' '[+hM  7 Bd p`^J+hN `a|+hO Af`+hP Ag`+hQ K`+hRn L`+hSf Ah`D+hFk AiB g' $' A'[+hTk Aj`c+hUw Ak`c+hV`:+hW Al`D+hX Am`d%+hY An`D+hG` AoB ' ' 6'[+hZ Ap`g+hHÙ B ' R' o'[+h['Aq]l`E (i 'Arh]k9kIkAskXk]`>Nkbkl]`kr`=k.@4kkkk|``>=kkKtkLhJkkkKuh^lllAtll`MJllԜ`M''R.hlmmRAuBm mRm [mK[`lJm!m!`l'Av'Aw.mHLmMLhmWmbmAxBmhmmi[mnK[mt\[`lJmm`l'Av'Ay.mMbmMmmMwh恋nnonon`:nK`:o\`:+`l>Ioo$oN (+B>Jo5oQoo].AuBodMoiMh>Joooo.AxBoMoMoN hh_pqqqq`X-Jq&qq.AzBha`X-irr +r5rr5rK`l)\>=r .AzBr,OAiharwrrAzBrr[Jrr['A{'A|.irrsAzBrsrK[\>=r֜['7'A}.rOh灋uuvk@uvkv^`]B\`>=v.A~BhJv5v<.ABvSC`v]PLhh聋wKwPw@wdwwi.`\>=ws.A~Bh=w.ABwPhhwwxAB w'@ "'wxx ^`]B\`hx!xHxlAB x"'@ "'x]xlxb.`\hxqxq{A~Bx{[>Ixx`'g'A..Jx?=y['7'A.hb|}d~A ||ܣ'A |}'A }%}G'A}n~`BJ}q}q`B'A'A...hc~B~N~m~V~m`oNJ~Y~aoQh運9LA]bB`nA`*]`S>J.AB#S`SwhhdRbA{`J~Oi +pB`h>=0'heetA^{`lJ~~B.A]BhBieA^%e-K`h\>=:['7'A.[ThfII`lJB=.AeBhEhg /b4b`lJ77BX.AiBhFhh`lJB.AoBhGhiDSŠZŠ`lJ]]B~.BhHhé3IB ê' ǡ'3A[`l>I%!V`>J29BU.ABbV`h?I}%ĐĂV`:>JĤīB.ABV`:h?=0'GhÁ8ŊŨAB 9'I Q' n' "'ŖŨś`[hāŬAB ŭ'I š' ' "' +K`:[hꁋ A "' `:+\h끋;A "'(;-`\h쁋@ESw "'JS\h큋).NA "'5N>`:+`hSZ Z_ p[|][[[+][>Iȉ!ȒȍY(+>NȧȮQ[ȰpHYJ.[BYZh?J .\BYhhŁ%?[[B &'Z "'G[H[O[][hƁ_yɏ\B `'Z "'Ɂɏɂ[][hFKA "'OW3`:dT`xA`ʈT`ʙA`ʩA`ʾA``hǁ@B ֡' "'@!A`P.A`:+`GhE^˦A "'q˦ˁ`Pˑ`:`d5h˫g̭A ˬ'A '6 ?'7 "'ŷ̭`P̒`:],`Gh~͈͝ "'͔͝`b h>A "')>1`:`Y.hlqЌA "'wЌ|`Ѓ!`\hȁБЪ}B В' "'бж`н!`\hɁzAB ̡'A  (J U'A "'чіK`:ѣ`:ѳ`:A`A^`~B\+`~h ӗӗ"[2A`:T],`+\>Ie!ri_(+>N҇ґ[ғpBҽ_=.B___hJ?N&[(pBR_=`.Bo`?z_hJӍhʁӜӺB ӝ' "'[A[],`\hˁKB ' "'-K.[7A[\h$ "'$\h)-9A@9U^`V`B\d\][[[+`>It!Հxa(+>NՕ՟[աpHaJ.ABaʂb#h?J.AB,ahh́>c֧AB ?'A "'y֧֎^`V`B\֘\[`h́֫ AB ֬'A "' ^`V`B\`hA "'`!`\hA "'`!`\h ~~Q[+![+&A][[[+\>I<""M@dY(+ZXde(+sedq(+>=ڄ.RBhJڗ?Iک""%ڻڮdY][[[ȁde(+dq(+>N[pH!dY][[[=6.SB@eLhJR?Id""%kide`%ۄwdY`۝ۏdq(+>=ۮ.TB۸dY`de`hJ?I""%de`%dY` dq(+>=,.AB6dY`Dde`hJN?I`""!rddq(+%܀~de`%ܙ܌dY`>NܮܾA[pHdq=.ABdY` de`fhJ(?=0:D'Gh΁݃ެ޾RB ݄' "'޵޾\hρSB á' "'\[\hЁ1OTB  ' "':O?`F!`\hсS|AB T' "'`!`\hҁAB ⟡' "'`!`A[\hZUZQ[+![+A][[[+\>I""i(+,*i(+E7i(+>=V.VBhJk?I}""%叀i][[[圁i(+嵂i(+>N[pHi][[[= +.WBjxhJ(?I:""%A?i`%ZMi`sei(+>=.XBi`i`hJ?I""%i`%ڀi`i(+>=.ABi`i`hJ(?I:""!L>i(+%ZXi`%sfi`>NA[pHi=.ABi`i`l"hJ?=0 'GhӁ_UiVB `'U "'`i\hԁmc~WB n'U "'n~o\[\hՁxXB ꃡ'U "'`!`\hցAB 띡'U "'`!`\hׁAB 췡'U "'`!`A[\hx[xQ[+![+A][[[+\>I,""=0n(+JHn(+cUn(+>=t.\BhJ?I""%נּn][[[ﺁn(+ӂn(+>N[pHn][[[=(.]B4ohJF?IX""%_]n`%xkn`n(+>=.^Bn`n`hJ?I""%߁n`%n`n(+>=".AB.n`<n`hJF?IX""!j\n(+%xvn`%n`>NA[pHn=.ABn`n` +qNhJ"?=04>'Gh؁}\B ~'[ "'\hف +]B á'[ "' +\[\hځ;[^B '[ "'F[K`R!`\hہ_AB `'[ "'`!`\h܁ AB '[ "' `!`A[\hi "'\h݁RAB ' !C "'eq`{B`^`SB\^`NSB\+\hށ<AB ء' NS`]B`]`S>Nmw]`S}`S=.ABtt4LK`S`>=ʡ?' uy=?'uyLS=6,ut?uy4NNOS`N`>=h^ujvuhJuuh߁AB ' ޣ "')1`:E^`RyB\l^`NSB\+\hA ' ݣ`:]`Ry>N%/]`Ry5`Ry=M.ABhwC4mmnK`Ry`>=}w`tw4S`N`>=w`jxhJw`uh2A "'2&A`:`:i7>VA "'BVJA`:`:hsAB t'A "'`:`+`+`h။RAB 'A "'R`:*`+:`+`h⁋WwAB X'A "'`+\hかAB 'A "'`+\h䁋4AB 'A "'4`$`+`h偋9UAB :'A "'`h`v`+`hjA]y`RJh.lhkQck]y`RJnvQ.lhl + +]y`RJQ.lhm!R~+R]y`RJ.C6Q.lhnWiz]y`RJQ.lho..]y`RJ Q.lhpl]y`ZJQ.lhq JJ]y`ZJ";*Q.lhr]y`RJQ.lhs<uAKu]y`MrJTfTh.lht %A %]y`MJ h.lhu b y   ]y`ZJ   Q .lhv   +, + +,]y`ZJ + + +Q!.lhw +n + + + +]y`ZJ + + +Q".lhx +  H  H]y`ZJ " 9 *Q#.lhy     ]y`ZJ   Q$.lhz  , a 8 a]y`ZJ ; R CQ%.lh{     ]y`ZJ   Q&.lh|   <  <]y`RJ  - Q'.lh} A S  ] ]y`RJ ` u hQ(.lh~     ]y`RJ   Q).lhEb E]y`RJ#6+Q*.lh]y`RJQ+.lhF$F]y`RJ'7'h.lh]y`RJQ,.lhFF]y`RJ"7*Q-.lh]y`WJQ..lh,_7_]y`WJ:PBQ/.lh]y`WJQ0.lh!3^:^]y`RJ=OEQ1.lhcu]y`RJQ2.lh]y`RJQ3.lh L +L]y`RJ.=.h.lh]y`YJh.lh'\3\]y`ZJ6M>Q4.lh]y`ZJQ5.lh6MZ]y`ZJc{kQ6.lh]y`ZJ Q7.lhYp{]y`ZJ~Q8.lh11]y`ZJ "Q9.lhq]y`ZJQ:.lhP P]y`gJ)A1P.lh]y`RJh.lh +C%C]y`RJ(4(h.lhA]y`RJh .lh?A?]y`RJ"0"h!.lhDVT^]y`RJatiQ<.lh]y`RJQ=.lh  ]y`RJQ>.lhNhs]y`_;Jvvh".lh5]y`RJh#.lh##]y`RJQ?.lhas{]y`RJ~Q@.lh  ]y`RJQA.lh_qz]y`RJ}QB.lh  ]y`RJQC.lh%7f@f]y`RJCWKQD.lhk}]y`RJQE.lh..]y`RJ QF.lh3EvOv]y`RJRgZQH.lh]y`dJh$.lh 7 I x R x]y`RJ U i ]QI.lh }    ]y`RJ   QJ.lh  ! !]y`RJ   QK.lh!R!i!!w!]y`eJ!!!QL.lh!""3" "3]y`eJ""$"QM.lh"u""""]y`eJ"""QP.lh###X#(#X]y`eJ#1#I#9QQ.lh#####]y`f J###P.lh$<$N$u$W$u]y`RJ$Z$f$Zh%.lh$z$$$$]y`RJ$$$QR.lh$$%$%]y`RJ$%$QS.lh%T%o%A%~%]y`CJ%%%h&.lh%&&SA&#&S]y`CJ&,&D&,h'.lh&&&A&&]y`CJ&&&h(.lh(((A((]y`RJ(((h[.lh))%)R)-)R]y`gJ)0)C)8QV.li******C]`\>=*.}B&**À*`&**Ȁ*!`hi*+m-A *ԡ'A *+ ++= +H'A+y-+K`:+`:+`:+A`+A^`~B\+`~>N+[I,,,(+=,&D,+.AB,9݁,?,H,U h=,tD,y.AB,݁,,, ,h=,ա?',DJ,&,-D`~h- --KAb- -K`J-#&-#-D-#[''A.`h-P-X-Ad-d-`J-g&-g--g[''A.`h../YA./Y`J.&.#.ܜ`'g'A./&/ [''A./O/?/6.Ath^M귰Q[`h001 A01 `J0&0#0`'g'A.00ќ[''A.110.Ath^M귲Q[`KLcLM2MNOOqOP PQ6QQRpS SKSTTjTU!UwUV#VwWX XXYYGYZzZ[5[\R\]:]u]^^_a`aagabcccd/gyghh|hi[llmAmnnqrrmrs=sstvQvxRxxynyzKz{{{|2||}.}}~*~~~*~&z"vrmie a ]YUSQMIEA=9513m/Ci 1%1+3A`o`Ei1|AB`:+i111111`R\? 1p1Si11111`:J11.ABii113132K`:\>=2 .AB2iI22`'g'A2.Ao>=2՜['7'2.Ao2?zi338A`]l`Ei3 AB`:i 333333A`:\?i 3i335353l`R4`*]y`E>N4d4k]l`E4ql`E4V4.ABi4eN44]`E4ƨ +`Ei)=5445 +5 +5k5 `E`>N55&A`i 5,i5?!=5X5Mр5\:lJ5s55zрi555A555c`R`:>J55.ABii556666l`P6`*]l`E>J66l`E6'6.ABi66i67 8 B787.l]PI`P7=`*]l`E>J77m `E77.ABi7,-i!889A`i$9N9V9pB9d9`i!>=09m9w'i&999A999A`:`:i'999A999A`:`:i=i(::<A :'A`Fpi*; A`+i+; "`:+i.;);1;wpB;?;w`i(>=0;H;R'i0;;<;<]`i(J;;B`i(;[''A.i1<<,<<4<<<`:]`i(J]]l`R >{l`R'i5>]l`Y >l`Y'i6?K]l`R ?fl`R'i7?]l`R ?l`R'i8@+]l`_; @Gl`_;'i9@]l`d @l`d'wi:A]l`R A7l`R'i===>0pB=>0`i2>=0>> 'i?A`ArAAA]y`RJAAAi4.li@AAAAA]y`YJAAAi5.liAAAB(B B(]y`RJB BB i6.liBB-B?BfBHBf]y`RJBKBWBKi7.liCBkBBBB]y`_;JBBBi8.liDBBBBB]y`dJBBBi9.liEBCC5CC5]y`RJCC&Ci:.lnb +^iFDDJA DD5 D>D` DjD' DD D¢'A`R`C iHF]l`R Fl`R'SiIG]l`Y Gl`Y'iLEJEREpBEZE`iF>=0EcEm'iMHH HRHHRH`:`iF>JH,H:iPHDiPHVHdHBHmHHn[`iFJHH`iF'A'AHiTHHIEI IE`JII`'g'AiQIJIOI "'IZIIb`Iy],`+\iRIII "'II\iUIIJbIJ]y`RJJJ JiH.liVJ[JtJJ~J]y`YJJJJiI.la'v \iWKzKSnA K{'A`R`k`i! iYMy]l`R Ml`R'SiZM `:+i[M AO`E+i\N `F+i]N A`B+i^N8 AX`+i_Nb `k+i`N [`k+iaN `:+ibN `iw+icN `iW+ifL*L2L}pBLEL}`iW>=0LNLX'ihNNOZOOO[O][[[+][>IO+!O4O/(+>NOIOPQ[ORpHOqJO~O.[BOOij?JOO.\BOikijOOO[B Oȡ'Z "'OOO[O[][ikPPP1\B P'Z "'P#P1P$[][irP6P;P\A "'PHP\PP`:\isPyPPA "'PPPA`:`:itPPPA "'PPPA`:`:ilPPQGAB Pڡ'A "'Q QGQ`:Q`+Q/`+`imQLQhQAB QM'A "'QzQQ`:Q`+Q`+`inQQRAB Q'A "'QRQ`+\ioRR$RFAB R'A "'R1RFR7`+\ipRKRhRAB RL'A "'RtRR|`R`+`iqRRRAB R'A "'RRR`R`+`ivS5SGSlbSOSl]y`RJSRS]SRiY.l4f!ib/iwTITlWhA TJ'A`RiyU7 0`Y+izUL 2`+ i}TTU!pBTU!`iw>=0TT'iU[U`U4 "'UjUUr5`:\iUUU6 "'UUU7`:\iUUU8 "'UU\iUUV +9 "'VV +],`^`iVV&V\: "'V6V\V>K`:VK;`:],`^`iVaVxV< "'VVV;`:],`^`iVVV= "'VVV5`:\iVVW> "'VWV7`:V?`:W@`:\iWW!W-& "'W$W-`[iW2W7WfA "'WRWfWWB`\(nD>y iXCXe[A XD'A`i[Q `:+iXXYpBXY`i>=0XX'iYY%ZnY5ZnYDA`:YuA],`WYA],`Y\[`i>NYY[YpBZJZZ+iZ>ZLĂZUۄZ`iZrZ[?BZ[?ZA[ZA[ZA[Z\[`iJZZӜ`i'A'A[ [#[,[7i[_[d[s "'[j[s\i[x[}[ "'[[\>a Byi\g\]DA \h'A`i\\]BpB] +]B`i>=0]]'i^c^aA^d~ ^'A`i^__NpB__N`i>=0__)'i_S_[__i_`i>J_r_ii___B__`iJ__Ɯ`i'A'Ai_``QA "'``Q`A`:`;A`i`ii`V`f`A "'`v``|A`[`ii``aA "'`a`A`:`A`[`A`i``+aA`+`i^Dib;bxczAb<~ bX'A`ibbc)pBbc)`i>=0bc'ic.c:cxA "'cBcxcHA`[cZ`+cgA`+`i,iddeAd~ d'A`ie7e?epBePe`i>=0eYec'ieeeA e'A "'eee`:`:5ifg3jAf~ g'A`igA`ihA`7ihEA`ihkA`7 ihA`ihB`7ihB`7ii)B`iiNB`iiB`7ii B`+ii B`+ii B`+ij B`+ij' B `[+ijE B +`+ije B `:+iŁgggpBgg`i>=0gg'iǁjujzjB  "'jj`[iȁjjjB  "'jjj``[aiɁkklXB k'B`Míl llVpBllV`i>=0l'l1'ímumo'Bmv~ m'B`iЁnnnWpBnnW`i>=0n(n2'iсn\ndnnqn`i>JnzniiԁnnnBnn`iJnn̜`i'B'BiՁnoo%B "'oo%oL`[`:@Œ&riցppt]B pp% p.pP pZp|p~ p'B` iفqq$qkpBq3qk`i>=0q<qF'iځqpqxqqq`i>Jqqii݁qqr +Bqr +`iJqq`i'B'Bi灋rOr_rrir`Jrlrl`'g'Biށrrr "'rr\i߁rrrB "'rrrZ`:rd`:`:irss'B "'ss's`[\i။s,s1snB "'s@snsHZ`:s]d`:\i⁋sssxs+ "'s}s\iかsssB "'sssZ`:sd`:sK`:\i䁋sst B "'st s6`[`Mi偋tt#t[B "'t6t[t<6`[tM4`M`NzIĎ2i cƚLǧ i聋u8uNvyB u9'B`[i끋v B u'd`:+i큋v) K`:+i쁋vY B v3'Z`:+ivrK`:+iuuupBuu`i>=0uu'ȔiwTwxx!B  wU'B!`iwwxpBwx`i>=0ww' lixy8zB" x'B#`iyyzpByz`i>=0yy'ɬiz{{B$ z'B%`Ri{w{{pB{{`i>=0{{':ʆi||}B& |'B'`Rj}U}]}pB}}`i>=0}}'j~~B( ~'B)`j5=pBY`j>=0bl'TˠjnnB* o'B+`j lpB4l`j>=0=G',j +Iq"B, J'B-`j  pB `j +>=0'l̸j B. 'B/`j{pB`j>=0'j4B04]`E~JB`E~[''B1.j9HB2OWB3`:]`[JkkB`[[''B4.jB5B3`:]`JB`[''B6.PDͧ$Ρj 'B7`jrzpB`j>=0'7jQB8`j +OpBO`j>=0 *'gϳj,GnB9 -'B:`Rj!pB`j>=0'j#O O]`LJB`L6[''B;.j$TcB<k]`:JwwB`:[''B=.j%  `L][JB[ꜣ[''B>./j&lB? l(`:][J77B[G[''B@.fѢAТvj'ssBA`]`G/j(ssBB`j']mj`Gej)IfL7 J'BC`j(]`G],`G +j,>FpBT`j)>=0]g'j.(`J`'t'h.j3``G>I윣`'g'Հxx x'.(j.=06@Qx.?Jcj`G'o'N.xj4` K`G\>=0'j8\`(fkK`\>=0x'j/FF`G>I.(j.w>J`G'o'z.?=0)('j0KW\`G>NfjV`q.(j.I}Ջw>J`G'o'N.Ջy?=0('j1`G>NV`.(j.I)1-J(>J?F`G'o'z.?ImuqJ(=0{('?=0('j5``GJ.j3j6,4J "'8J=``GҵOyWMח +j9'~7BD (J S'BE`j<5pB5`j9>=0' Yj=?BF 'BG`jsj@pB`j=>=0'؛jABH բ'BI`jDgopB`jA>=0''sjEBJ~ 'BK`[`FhjHpB`jE>=0'jIw@ Ǣ'BL`O]`jKcjAr`:>J{$'.zO'.O'w.j_'.j^jLy(ys[`>I!%݀]`J*?J""" +.zO( z'#.O(0*E?.j_(NHf_.j^(oijY~z`Jjp.zOz.Oz.j_z.j^zjM pp$ s]`]`>N58`:i`>.zOJDܶzNY\`^h`gb.zOWi.j_{vpܶzW}ܶI׃v>N`i`.OܶN`Ӽh`.OW.j^ܶWܶI ݻv>J*`4׃8ݻ?<yAHEyJݻ??Ja+jNs]``>J""".zOv;zW;;z׃v$.zOW&.j_;7.OvHD>;WPJ;lhb;؃vso.OWu.j^jO,, s]`]`>N {`i`#.zOW*.j_<71േzWD>ൈNT[9`]i`jf.OWq.j^yൗW൫Nz`h`.zOേzN`μh`.OൗJ`̄  փy"Qy$ jPtyVV]``>J""".zOvz.zOW.j_^zW .Ovᗒ3*&.OW,.j^^B>6ᗒWLDjQ[[]``>J"""[^.zO[v +.zOW.j_,*"[!^/.OHF>[!vOK.OWQ.j^jZ`jr]`Juy`.zO.Oj[]`J`.zOW.j_.Oj\44]`J` +.zOW.j_&".OW-.j^j]8B|M|]`JPT`_.zOnj.OWu.j^jdpB`jI>=0'je`+%!`+,`+7`+`jI>IF!QJ(+>JbrjS|ԁ?I!(+>JjTԁ?I!(+>JjUԁ?I+!1/(+>JBRjV\?JjzjWjSB[![[[`jIJŜ`jI'@'BM鈁铂鞃jTe1Be[!![$[`jIJ44`jI'@'BNY+\6_AjUiyB[![`jIJ`jI'@'BO꺁jVB[`jIJ؜`jI'@'BP5jW=B=`jIJ`jI'@'BQj^]el`Joo`''.jgK`\>=['7'BR.9j_!!`J`''.jh&*k/k4K`\>=A['7'BS.aj``J`''.jiK`\>=ʜ['7'.ja3!3`J`''.jj8<u!=uBK`\>=O['7'.k8X܌1kK_Znleijk:@`jr\? jmSS`K``>=P7PW_=P +7 PW)!7#P7 +J6B=PJEP7jnXc<in``>=zz7zW7z=zÀzˀz7 J7zW7z7jo#S(S)=[,r[`J22jn9jmAjm&LL`&PP`jpXchi=[lr[o_[r[`J~~jnjmjmjmjm&S`&]`&h`&r`&P)jsaBT 'BU`jv_pB'_`js>=00:'hjw<dBV ='BW`jsjzpB`jw>=0'Bj{sBX 'BY`j~xpB`j{>=0'j`j{>Jjj/qB8q`j{JDD`j{'BX'BZhjNw*B[ O'B\`j(pB(`j>=0'j//B]`]`TG2j//B^`j]mj`TGhj"C '6`j],`TG]`TG +jHpBH`j>=0#'jMUz(\z`J__`'t'h.jQQ``TG>I`'g'Հyyy.(j=0 y.?J&`TG'B_'N.GyjVdgl`{ K`TG\>=0'j!x('x,K`\>=09C'j}  `TG>I.(jw>J`TG'B_'z.?=0('j"`TG>N,0V`7.(jICKGw>JX_`TG'B_'N.y?=0('j`TG>NV`.(jIQ(>J +`TG'B_'z.?I=EAQ(=0KU('?=0t~('j``TGJ."jj "' ``TGP|\V +jUB`V~ p'Ba`jRpBR`j>=0#-'jWqB X' "'v{``P Yj¶ĠBb·~ Ѣ'Bc`CjmmĞĊĞ\? ĕC jemüpBÄü`j>=0Í×'=jǮBd~ 'Be`CjǀǀǬǘǬ\? ǣC j}ƅpBƗ`j>=0Ơƪ' Yj,Bf~ 'Bg`Cjʒʒʿʫʿ\? ʶC jɎɖpBɩ`j>=0ɲɼ')j:Bh~  'Bi`C`i2j\? C jpB`j>=0'j8Bj9~ S'Bk`Cj\? C j8pB8`j>=0 ' jҳBl 'Bm`jjrұpByұ`j>=0҂Ҍ'  Zjӎӳ^Bn ӏ'Bo`jŁ\pB$\`j>=0-7'  jƁ9l؊Bp :'Bq`RjɁ1pB1`j>=0 'jʁ6>(W(_Br`:v`:+`j>Iք!֎ֈ (+B>J֟j  ?J j j́,MBVWBr[f[`jJpp`j'Bp'Bs W dj΁؈1B؈Br[`jJ$$`j'Bp'Btz  ( t )  jρeٙBu f'Bv`RjҁZpB"Z`j>=0+5'jӁ_gۛځۛډ`:ڔ.][[[+`j>Iڪ!ڼڮ (+>N/[pH J:jD ւJ "?Jfۈjے jց۟WBW[.[`jJ㜣`j'Bu'Bw= I jׁ[}1B܆܇[`jJܐܐ`j'Bu'Bx 3 a    nj؁ݾޑBy ݿ'Bz`jہAIޏpBWޏ`j>=0`j'  j܁lߊ'B{ m'B|`j߁%pB%`j>=0' F jB}`]`[ j။B~`j]mj`[ j⁋.viB/~ I'B`j]`[],`[j偋CKpBZ`j>=0cm'j灋(`J⩜`'t'h.j쁋``[>I`'g'Հ  # *.(j=09CT .?Jfm`[' 'N. j큋` K`[\>=0'jSW(]bK`\>=0oy'j聋77`[>I.(jw>J윣`[' 'z.?=0('j運<EJ`[>NTXV`_.(jIkso /w>J凜`[' 'N.夀 /y?=0('jꁋ`[>NV`.(jI (>J'.`[' 'z.?IRZV (=0`j('?=0('j``[J. jj 1B "'1%K`:`ij6<xB "'JxRZ`:gd`:`ij} "'``ijB "'K`:`ijB "'Z`:d`:`ij;B "'(;/B`i`ij@FgB "'Tg[B`i`i Y   + +q + < ,   #jDJBE~ `'B`jHpBH`j>=0#'  j B  'B`j s``b+j `:+k `:+kxpB`j>=0' y k~B '`E@ k i`:+k `:+k L`U@+k  `:+k + `:+k  `:+k # `:+k = `:+k] `:+kNVpB``k>=0is'k`B][[[+`k>I! X(+>NB[pH5 XJM]kg In ?Jk Ik)B)[B[`kJ`k'B'B - 8k-=x1BFxG[`kJQQ`k'B'Br ken| "'s|`k    ~  "kB~ 'B`_kBJpBb`k>=0ku' } kwVB x'B`E@k8pB8`k>=0 'k =E[N[Ws`+a][[[+`k>In!wr (+>NQ[pH Jk#  ?I! (+>J k$* ?J;Lk%k#_pByzs[[`kJ`k'B'B  k$1Bs[`kJ眣`k'B'B + k%$TB-T`kJ33`k'B'B  W g  M k&{{B`]`c k'{{B`k&]mj`c k(1^ 2'B`k']`c],`c +k+pB`k(>=0'k- 6(6`J`'t'h.k2;\(^(c``c>Ipt`'g'Հ 1 1 1.(k-=0 1.?J`c''N. 1k3-;>C`b K`c\>=0oy'k7$((.3K`\>=0@J'k...`c>I.(k-w>JМ`c''z.?=0('k/3OT`c>N^bV`i.(k-Iu}y Dw>J`c''N. Dy?=0('k0 `c>N*.V`5.(k-IAIE (>JW^`c''z.?I (=0('?=0('k4=#=(``cJ26.7 k2k5t "'``c n    2      P +k8B`]`d> k9B`k8]mj`d> k:1 'B`k9],`d>]`d> k=pB`k:>=0'k? ( `J`'t'h.kD"$)``d>>I6:`'g'Հ` g n u.(k?=0 .?J`d>''N. kEee` K`d>\>=0%'kK(K`\>=0'k@%+`d>>I1A:.(k?w>JNU`d>''z.?=0('kAVV`d>>NV`.(k?I !w>J`d>''N. !y?=0/9('kB[jAqA`d>>N{V`.(k?I !(>J`d>''z.?I !(=0('?=0('kFFQtZt_``d>Jim.n "kDkHIB "'K`:`LKkI "'``d> 0 |    H ! "j " # #_ kL B ΢'B`kO R Z pB i `kL>=0 r |' # $kP +~ + 9B  +'B`RkS + + 7pB + 7`kP>=0  ' $U $kT  D|B  'B`kW   pB  `kT>=0  'kX    &  <B`k QB``kT>J i k[ %V %gk[  zB z B[ B[`kTJ`kT'B'BX %ԁi % $ %- % &'k\WzB X'B`k_7pB7`k\>=0'k`<DUa@`klmB``k\>Jkc & &kcxBx@[B[`k\J`k\'B'BW 'be 'o &o & '4 'kdUB V'B`Rkg5pB5`kd>=0'kh:BU]`:g.][[[`kd>N/[pH (Jkk (t (kk#B,-[3.[`kdJEE`kd'B'B ) )! ' (K ( )eklUB 'B`koSpBS`kl>=0$.' ) )kp0VuB 1'B`kspB`kp>=0'kt9B`kTHB`_`:`kp>Jpkw * * *kwsBsB[B[[`kpJ`kp'B'BB +DS +Qi +^ *9 * + +kxP~B Q'B`k{9pB9`kx>=0 +'k|>F Z b`:t`+`kx>I! ,w(+>Jk ,h ,w?Jk ,hk+B45[=[`kxJLL`kx'B'B - -)k1B[`kxJϜ`kx'B'B - + ,? , -m -kB 'B`kqypB`k>=0'kYY`k\B``k>J,k6 .E .k]rB{|[B[`kJ`k'B'B / / ." .n . /dk !$4B  Т'B`k!x!!pB!!`k>=0!!'k!!"""" `:"`+`k>I",!"5"0 00(+>J"F"mk"w 0!" 00?J""k" 0!k""#B###[# [`kJ##`k'B'B#v 0ׁ# 0k##$21B#$2#[`kJ##ɜ`k'B'B$+ 1T / / 0 1& 1k%%H(B %'B`k%%&pB%&`k>=0%%'k&&&';&E';&sB],`k&`+`k>I&!&& 2g(+>J&&k& 2P& 2g?J&'%k'/ 2Pk'?'f'B'o''pB['y[`kJ''`k'B'BĀ' 3' 3k'(%(1B(.((/B[`kJ(;(;`k'B'Bŀ( 3 1 2' 2 3_ 3k))-B )'B`k*-*5*pB*W*`k>=0*`*j'k**+*+*`:*B`+`k>I*!** 4(+>J++0k+: 4+B 4?J+[+k+ 4k++,hB+,h+[+B[`kJ++眣`k'B'Bɀ,M 5E,[ 5Pk,l,-1B,-,[`kJ,,`k'B'Bʀ- 5 4 4b 5 5 5k-.+0WB -'B`k...pB..`k>=0..'k// //+//ZB],`k`k>J/i/k/ 6k//0UB/0U/B[`kJ//霣`k'B'B̀0M 7* 6K 6 6 7gk121a45B 13'B`k112pB12`k>=011'k2#2+32@32H`:2UB`+`k>I2j!2{2n 83(+>J22k2 8$2 83?J22k2 8$k3 +3'3B30331[39B[`kJ3J3J`k'B'BЀ3 8ށ3 8k33431B3433[`kJ33`k'B'Bр4, 9] 7 7 8 9/ 9k557B`k5}55pB55`k>=055'k556AB565`:5`+6`+`k66"6eAB646e6<`:6J`+6Z`+`k6j6o6AB6}66`+\k666AB666`+\k666AB666`6`+`k667AB677`7`+` 9 : : : ;/ ;r ; <k789 B 7'B``fkā888pB88`k>=088' <{ <kŁ9:;3B 9'B`[w`[`[kȁ:::pB::`k>=0::' = =_kɁ<<1<B <'B`ḱ<<<pB<<`k>=0<<' = =ḱ==DB]`:`:kЁ> B`Pk> > >)>>)> `P\?kЀ >d > kҁ>.>3>>9>>N s][`:`:\>=>a>[ >4>i>i>>j+`:>m`:`>=>|.>} ?> ?xkӁ>>>>>`[`[][__J>>i`:`:__.kԁ>>?m5>?m>K``>F??? +`:?.k>I?$?.?( ?(?1 @ >J?>)?J?]*kՁ?r?y???? `:? a`:`:>I?!?.? @>=?.? @?݁? @?J??.? @kց@@ @J @@J\>F@@-@ `:@'.k>=@5.@< ASkׁ@O@T@@[@@aa`:`:ˁK\\>F@@@`:@.k>N@@K`:@.@ A=@@ A@ A܂@ Akہ@@B'@B']`:>NA0A;`jAFA=.BkЛBQNA[A`],`:1Aj`:EArA{A}`AAV`AA B(jAA B߀A BA BAA BW>NAAB`i&AAȀA BA Bj`iIAA.BBA C_k>=AA BAA C_Ki;?JBB Bk܁B,BACBHC]`:>NBB`jBB.BkЛBQNBB],`:1B`:EBBB`BBV`BB D:(jBB DB DB DBB DW>NC CB`i&C CC D:C Dj`iIC(C,.BBC5 Ek>=CMCF DlCVCQ EKi;?JCpCw Dlk݁CCC CC`>JCCC.((kށDXDaDwCDlDw`JDo!Dp. kkفDDDBBDDD`i` > ?O ? @^ A A BJ D E F FM F k။E'E-GB`kk쁋E\E\EEpEEy`P\? EkE GkかEEEEEE``>JEEE.BkиEB&EE Gg`:Rk䁋EEF/EF/E``:>JF +FF.Bkи<&F'F' G`:R>k偋F4FBFFEFFM `:FY K`:\>=FoFf.BkиbF| H`F HoRKk恋FFGFGF``:>NFFK`:FF.Bkи<&FF H`:R>=FF.BkиLB&FF H`:RJGG + HkꁋGVG^G(GeG`>JGkGwGr.kہ( k聋GGGBBGGG`i`JGGGG JBi(+B G= G H6 H I I JGk큋HH JB`kkHJ B`:kHYHYHHpHHy`PH`:\?k J HkH JkHHHHHH``>JHHH.BkиGBH.Bk&HH K<`:RkIII\II\I``:>JI)I9I0.Bkи=IH.Bk&ITIT K`:R?kIaIoIIrIIz `:I K`:\>=II.BkиcI.BkI LUI LdRLkIIJKIJKI``:>NIIK`:I.I Lk=JJ .BkиNBJ%.Bk&J1J1 L`:RJJ;JB LkJJJ(JJ`>JJJJ.kہ( kJJJBBJJJ`i`JJJJJ MBi(J.BkB K K L+ L M~ M NPkKmKsVB]`:`:kK B][`:`:lKKKKKK][`:`:\?k N KӬlLLLpLLpL/ s][`:`:\>=LBL< OJ4LJLJLkLK+`:LN`:`>=L].L^ OLc OlxlLuLLLL`[`[][__JLLi`:`:__.lLLM65MM6MK``JMM M.l-4M$M$M5M%`:`JM+M-M+ P(M0 P{BlM;M@M~MKM~MS``JM[MgM[.BkMs.BB&MyMy Q,`:l llMMMMMM``:JMMM.BkM.BB&MM Q`:l mlMMNMNM `:M K`:\>=MM.BkM.BBN RHl N RWnlNN"NN-NN5 `:NA a`:`:JNVNbNV.BkNn.BBNt Rl Nz RtlNNNNNN``:JNNN.BkN.BB&NN S|`:l vl NNO] NO]\>FO'O@O3`:O:.l>=OH.OO Tll +ObOgPOnPOta`:`:ˁK\\>=OO.Bk4OOPO`:OK`:`>IOO.BBO Tl >=OO TzO.BBO TlO T?xlPP.PP3P]`:>NP?PD],`:1PN`:=PbPV.Bk4PjPjPPr`:P~K`:`>IPP.BBP Ul >=PP UP.BBP Ul;?xJPP UlPPQQQ]`:>NQQ],`:1Q"`:=Q6Q*.Bk4Q>Q>QQF`:QRK`:`>IQaQe.BBQn W l >=QQ~ VQ W;?xJQQ VlQQQ(QQ`JQQQ.l( lRR R6 R(R6`JR+R2R+.(l(lR;RDRZCRORZ`JRR!RS. ll RmRtRBBRyRR`:`:JR$R'BR.BBR Xll RRRBBRRR`:`JRR̀R YR'BDlRRSBBRSR`:`:JSS.BBSS YX7HllSSUBBTUTB`:TB`*`:>NT>TG,],`:TVTI Z'yUNTjTp`#Tr Z`ETTT`T ZaTT ZTT Z-(YT ZTT ZW>NTT`:TڂT Z-T Z9ITTTT Z(^w>=UHU@ Z-UI Z$UU\UXUQ Z@(XUtUl ZXH:?JUUU Z-'lUUVBBUVUB`:`:>NVV `VEV%V.V0`V7V5 \NV>V9 \(^VF \NVGVF \NW>NVWV]`:VgVcV_ \Vd \N@!WIV|"!VVV \V \N@(V \BVV \Nw=VV \)'y?=VV \)V \JVVՁV \)A O O PQ Q Q R R SR S TP U[ V W W X1 Xu X YT Y [ ]l]9]H][B`l\?  ^Kl``nB``Rl(\? laaaaa`l)lbbbAUbb`l.l cecnctctct`l!duddA^dd`ll"f%f4f:f:f:`ll#iiiii`ll%m0m5m<wm:m<\l&n{nnnnn[nA`:n],`Z +\ ^ ^ _ _8 _k _ _ _ `Xl)nnoB`l-\? l+nooooo`:\ ` al.oo'ooB`l4\? l0o7o<oB^o@oB\l1oFoKoT\oRoT\l2oXo]omo_omod[`\ a^ a a al5pp~B`]`:lA\? l7smsrssxssK`:sB`+`l?tttBtt`l8uBuGu]nuOu]uWK``l9w{wwwww K`:`l:y*y/yCy5yCy=K``l;zzzzzz ]`:\l<|||?|$|?|6]`\l=~~~B~~~]`:~B`+\ b^ b b c# cc c c d' d}lB<BB`lnlLffu~`P\? l dlD`J.BlqQW.BBBBllET +T`J(.BlqQW*.BBCBKBllIB[\>I% fU`l>N1FB`lH fU`lIYxr] fKl΀=} fUl?=.BlqQ_ fU`lAlHI% fU`>I  fU`= fU?=2,#.BlqQ_$K> fU`'H>=0`j'BlJB[\>I%  g`l>N@TB`lV g`lIf~j h)Kl΀= gl?=.BlqQ_ g`lAlI%I% g`>I g`= g?=82).BlqQ_$OC g`'I%>=0dn'BlF z `J.Blq?RAz׃y.BB1 `:'zBllG$,0`J9^ZB9.Blq?RA؃yf.BB1`:'Bl e e f+ g iy j jlMB`lBlPEBB],`P+lUVVixB],`P\>=.BB k<lP lL k<lRLLB[\>= .BBlP4  G!l`P\J'5)' lQ> kllS26;<B[\>=YL.BBlP4aabl`P\Jhvjh lQ~ lsl k lI llV:@0B`lnl]ddst[\? l& mT`PlX`J.BlqQW.BBBBllYHH`J.BlqQW.BB7B?BllZMUzZ`Jclc.Blq?RAz׃y.BB1`:'zBll[..`J.Blq?RA؃y.BB1`:'%Bl m n n o2 ol^B`lnle77[\? )l&// p/`Pl`;CbJb`JMVM.BlqQlafnt`Jww.BlqQlbz`J.Blq?RAzlc`J.Blq?RA pb p q qe qlfB`lnlm[\? l& r&`Plhl!l`J*@3*.BlqQWB.BB[BdBllipx~`J.BlqQW.BBBBllj;z;`J.Blq?RAz׃y.BB1)`:'z3Bllk?GK`JTyu]T.Blq?RA؃y.BB1`:'Bl rY r si t tlnB`]`lqB`Pl`P\?lq u$ lsz`lt"""`lugouuu`lv`l + +B[\>=0'BlB[\>=0'BlEICBBaCvB],`:C`:`>N,3z`G>5.BlqRN[_`FiuC`: v>I:T> w(WBB>=j wS&jnj wSWul w!)$ w'y woHaKl`?Ifj w(BB>= wS& wSylȂ w!)$B'y woHaKl`?I}! w(BB>= wS& wSylނ w!)$ 'C wo'CHaKl`?J5< wSlwBJ_{P_`JSXS.zlsWZ.lvlx9`J.ltW.lulA`:>J$'.zls'.lt'w.lv'.lul(s[`>I$!%.( z]`J=*?JO"""[V.zls(d^ zՇzxt.lt({ z՗.{lw( zՇ{.9lx( z՘9ly=z=`Jjp.zlsz.ltz#.{lwz4-.9lxzlVeq s]`]`>N`i`.zls |zN`h`.zlsW.lvӀ |zW |I |v |>N +` i`.lt |N+.`0h`84.ltW:.luLHB |WTN |Idkh }vn }>J|` | } |y | }փy }??J+l"2s]``>J?"""LG.zlsvZUO zWb\ ~ys z׃v.zlsW.lv.ltv W ʀ ؃v.ltW.lul>MXh s]`]`>Ny{`i`.zlsW.lv zW N9`ɼi`.ltW.lu W N z`h`.zls% zN48`:h`C.ltNH JYd`s y ~ y  +y l ]``>J"""&!.zlsv1) zNFA.zlsWH.lv^^YQ zWh` }y.ltv .ltW.lu^ W l"/;]``>JJ"""[YQ 5^^.zlsxvn 5v{.zlsW.lv 5!^.lt 5!v.ltW.lulz]`JR`.zls +.ltl{!]*]]`J-1`FA.zlsWM.lvY.ltl|ap|]`J`.zlsW.lv.ltW.lul}]`J`.zls  .ltW.lu uS u u u v vk v yx y z2 z { |f ~ e E % 9l'-C`pUlz CB]`Pl B],`pUlpBC]`P],`pU\?l #l 8 pl* ]`P`l>J:El` v0`pU [4l`P`l5J QlC]`:>N(*]b`:0g`:=SM.Bl4[[ll`pU\Jrtr }{ CpJ l4C4]`:\>N`:ڀ d'RF l`P.CBl>= # Qelccija]`:[[>=.Bl4l`pU\J l plHHK`:B`+`J.Bl`*4G`l`pU`J""$" D+ Ӂ2 p]@ 5l &.K``J8>8.Bl`*4QQW`pl`pU`Jv"xv " pj  y J 8 nl΁C`pUl B`PlŁ  `P\?l p l$C%$]`:>N24]b`::g`:N[eC`:pg.BlQeFK`: 'RU>N`:Ȃ zII! `>= ] ?J ]l).tC:tG]`:\>=YP.Blge 'RQely(`Jll.Bll `J.(l(lÁC`J!.(l(l/  /\>=.Bl'Qel49{nA{IK``>JV]lg.Blq Yl K`:`>Jl.Bl lK``>J"% 5`:l.Bl 5`:l"}(}0K`:=B`+`>JOVl^.Blh o l ]`:\>=l.Bl Hl%%]`\>=l.Bl& ]`:l*/8J]`\>=Zlg.Blzq /n*la`:K`\>=l.Bl )lKK a`:K`\>=$l1.Bl; $*lP\C Ben`PK``>J"% `:ll  `:lB  +`PK`:`>N5:`P<lI GNC +`!l o V=l o VJ l3 B : C`PTK`:`>Nns`Pul 4N`l \ C=l \ CJ l•C B#•,`P=K`:IB``>J#-# 3(+?lN X $ilv € $‡ 3`lš¦4C B´4½`PK`:`>N`Pl J l$ * l9EC BQZ`PkK`:wB``>NÕÚ`PÜlé IHL >=_lm ǁs Jā)>=ġlIJ ǁĸ J*lţsBţ`P]`:\>N5:`P<lI }FXwdK`:m >=lō œ lŨŴmCBžm`P]`:\>N`Pl BF">+K`:4 Q>=FlW l] lr~BƊƚ`PƩa`:K`C`\>N`Pl N`C ll, C>NBG`:NI CS lPI]ja ,(qm r >=ǃlǔ Cǚ >=Ǻ lǸǺ lWlȊȞ'CBȪ'ȳl`P`PJȹȹ`P'C'C% l,7ɦCBGɦU`P`Jdd`'C'hɡ lɫɷ=CB=`PK`:`J`'C'C1 s7 lBNYCBqYʊ`PʗK`:`J`'C'CM S l^jCBw̅`P̒K`:\>=̷[''  ldCBd `PK`:\>=>[''CT Z liuCB͔͆`P͡K`:`>Jͮ͵`'g'C q lCB`P#K`:/B``>J@G`'g'C d j q  ! _ = /   i  ^ O  h C Q A i lƁkC!`lɁB`lʁ)C"B`: +lЁllϘh}Ϙσ`\?lɀ rl' llс`\?lɀ l' lҁ11Y=YC`\?lɀ ,l' 1lӁВВкОкФ`\?lɀ l' Вlԁ`\?lɀ l' lՁ[[уgуm`\?lɀ Cl' [lց`\?lɀ l' lׁ' '`\?lɀ l' l؁44\@\F`\?lɀ Zl' 4lف׎m׎C#`:\>I ('B= 'C$?I-:1 'C>=Q.C"B'l>=q.C"Bւy X֜֕֌ (^yHlIְֹ֬ n'%O>=.Bu X (^y.C"Blʁ(^Hl>=;.BHWN Xtmd (^y|v.C"Blʁ(^Hll+l+ ĺ A `:>J$.Bl.C"Bll΁MUiK[i`J^c.Bl  [lځy4C%`R`R`l݁ڵ AB`:l偋A`:\?l݀ l߁ݢݬݵl`R`*]y_Jl_ ;.ABl݁ Jlffl`P`*]l_>J"-l_H K.ABl݁W l⁋0A BPfl]PI`Pu`*]l_>Jm _ Y.ABl݁ nlか2A2c`R`:>J$.ABl  + l恋;C&`R`R`]y_l\? l聋Ld`:]y_l運9#9)a_\]_ !l쁋zC'`R`R]y_l B`Rl AB`:l C(B`lDD`R'A`:8C(`\?l l l l{!n!Ya]_g\+a]_g\+]y_J.l%.A:A`J=)l ڢ a_\-b`+;a\+J`+]_>J`km&_.Bl.ABl .C(Bl E lC)`R`R]l_]l_lKKbcc[kD[v[\? l& 4`R& ?`:& J`laLad`:]y_J.4_`JB  _4!!`"l__>=1/ iB= RJOV ilf|a_\]_Jm&_.Bl.ABl ) 8l{C*`R`R]y_]l_m C+B]`Pm C(B`m2 AB`:m AA\iC+]`P{A`:C(`\?m m m . AmKLKd`:]y_J.4_`JB  _4  J l__>= 9B' RJ9@ 9ma_\b`+a\+`+]_>N C,]m>_mJ_F4T=c`PG.C+Bm>=a\ il_y '.ABm.C(BmmFJ mD b  ̅ ۧm.5;a_\]_>NV[C,]m>_amJ_Fc`P.C+Bm>= 8l_ i.ABm)mFJ 8mD m  n1CYa]_g\+a]_g\+]y_J.m `J) u j mC-`R`R]_mB`mB`Rm AB`:m4B^`RB[mJ C(B`m&RRAjAw`RA`:a_\C(`\>=1.C.Bmm m m m#҂ (++C`R4  ) l`R\J&& [' xa`R\ R mFMS][>I\`.Bm#Jk+?=}.C/Bm=.B+m=.B+mJ+m# )B)`J".Bm(+m.3'9'?a_\\>IZ^.Bm#>=0q{('C0?=.C/Bm=.BC`R& a`R\m=.C.BmmAFebMeW`\>ma\\>mYZY][+\>I.Bm#J?=.B.BmWm=.C/BmI ! 7(+>=;. 7vH.]m?m$^g\p`Jss.Bmwm]\>I".Bm#!.\m$J?=.B.Bmym=.C.BmmqC.Bq\>I"!.Bm(+!.\m$>=5-.BmF.ABmR.Bm[.C(BmR?mv{C/B\>I!.Bm(+>=.Bm.ABm.Bm.C(BmR?m  f`[_+]_>Neo]_u_J u ^ I \ m'-C1`R`R`]y_m+\? m) _\ y m,C2`R`R]y_]m'_m/]XC3B]_+m01B`:+m8GG`:\>=.1B ]m0=.C3B _i)m/ ɧm2}}a_\b`+a\+`+]_>J# +.C3Bm/* bC T k m3<n<Ya]_g\+a]_g\+]y_J$6$.C3Bm/m6AJ]V]`JY)m4bgjm _\>Iz~ nR(.1Bm0B=.C3Bm/ n? D m9C4]m,`o]m'`om=++_D_L`:\? Tm8Z Tm;dilv `o\>I êo(.1Bm0B>= êoƸ̀ ê3BoR=.C3Bm/ ê? À ]m> C5`[`mAXKB]_+mB XB][]y_]_5F]y_]_mJPPe\>=n.KB _i).wmHmA PmD & 4 P ; P]y_J > J >.KBmAmF +R +W ' +Z ' +e ]y_\>I +s + +w.BmB + lJ +?= + +.BmB +  +ǀ +  + +.KBmAb + +.KBmA4   "\J  .  mGnmG ` e  k  v ]y_\>N  g]_  .BmB vI ! ˁ (+=  ?mH 3 8 w = \>F F v Og]_ n _.BmB|>=  ~ ǻ=  .BmB w=  .KBmAw b Ŵ DŽ =mK l rC6`R`R`]l_mN C7B[mY  C7[\?mN  mP(1>l`RG`*]y_>Jall_| &&.C7B &mN`: 5mQ<<l`P`*]l_>Jl_ .C7B) mN- mSAR Bawl]PI`P`*]l_>Jm _ k&.C7B kmN`: ʀmTPAPc`R`:>J-&-4.C7BE mN`:mWU`ABk`:Jt0t~'C8 ɡ = b ˶mZ4C9``pm]4C:B]`:Ki`:1T[d'C;'C<'C='C>''C?'C@'CA'CB'CC'CD'CE'CF''CG'CH'CI'o'CJ'CK'''CL'CM'CN'CO'CP'CQ'CR'CS'CT'CU'CV'CW'CX'CY'CZ'C['C\'C]'C^'C_'C`'Ca'Cb'Cc'Cd'Ce''Cf'Cg' '!'Ch'Ci'Cj'Ck'Cl'Cm'Cn'Co'Cp'Cq'Cr'Cs'Ct'Cu'Cv'Cw'Cx'Cy'Cz''C{'C|'C}'C~'%'C'C'C'C'C'C'C'C'l'C'C'C'C'C'C'C''_'C'C'C'(m^5CB],`::K`:'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'C'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/'D0'D1'D2'D3'D4'D5'D6'D7'D8'D9'D:'D;'D<'D='D>'D?'D@'DA'DB'DC'DD'DE'DF'DG'DH'DI'DJ'DK'DL'DM'DN'DO'DP'DQ'DR'DS'DT'DU'DV'DW'DX'DY'DZ'D['D\'D]'D^'D_'D`'Da'Db'Dc'Dd'De'Df'Dg'Dh'Di'Dj'Dk'Dl'Dm'Dn'Do'Dp'Dq'Dr'Ds'Dt'Du'Dv'Dw'Dx'Dy'Dz'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'Dm_-2DB],`::-C`: 'D'D'D'D'D'D'D'D'D'D'D'Dma.M D`pm`.~DB][`:`2.`:`mi/2/20/E0/QD`p+\>I///m` ~>F///B`:/m^>=00m`0 q0mfnF0J0k0SB`:0[m_>=00um`0 0mgn?ma#!/{/q 7(+ŀ/ 7/p`p /2mc001,D01,0`P`>J010m]n1R1 Ձmd11162D1E21N`P1^`:1tK`:`>N11`:1R1 N11`11m`$11 0'D1 mI121 Y(+>=2 Y272#m`$2K'D2= m?I2X2f2\ Y(+>J2w*?J2&222 Y2 2 2 .`mf223bDB23b2`P3 `:3)K`:3D`mZ`>J3S)mg3g3s4DB343`P3`:3K`:3`mZ`>J3433 6DmaD4 'p U ] ؄mj45=Df`[`],_m\? ml5F5V6C +5_6C]%_>J66!oA_.mn6[6`66c66f K_\>=06s6}'Dmo667676 ]_\>=066'Dmp7#7(77,772a__=r`+\>=07L7V'Dmq777 777`+\>=077'Dmr778^88^8`8 _\>=088)'Dms8c8h88q88v`8 ]_\>=088'Dmt889R89R8`9 ]_\>=099'Dmu9W9Y99a99f0`_>=09q9{'Dmv99:79:_>=099'Dmw:::}:#:}:+a``>=0:9:C'Dmx::::::a_`\>=0::'Dmy::;i;;i;a_`\>=0;%;/'Dmz;n;s< ;{<;`;y`; ]_;`\>=0;;'Dm{< +<<|<<|<`<*y`\>=0<5=0<<'Dm}= +=====`=(y`=0 _+\>=0=B=L'D I ٝ Z گ  { < ܅ = ݛ # ވ sm??exD`|m@D`m@D`m@D`7m@D`7 mAUD`7 mAyD`7 mAD`7mAD`7mAD`7mAD`7mBD`7mB4D`7mBQi`7 mBpD`7!mBD`7"mBD`7#mBD`7$mBD`7%mC D`7&mC)D`7'mCHD`7(mCfD`7!mCD`7"mCD`7#mCD`7$mDD`7%mD(D`7&mDKD`7'mDmD`7(mDD`7,mDD`7-mDD`7-mDB`7.mED`7.mE>f`70mE\D`71mEyD`72mED`73mED`74mED`75mED`76mFD`77mF-D`78mFLg`79mFjD`7;mFD`7=mG2D`7?mGYC;`7AmGtCB`7BmG)`7CmG`7DmGf`7EmGg`7FmGD`7GmHD`7HmH1Cf`7ImHLD`7JmHg`7KmHk`7LmH`7MmHj`7NmHD`7OmHCw`7PmI Cz`7QmI$`7RmÁI?`7SmāIZ`7TmŁIu_`7UmƁI`7VmǁID`7WmȁID`7XmɁID`7YmʁID`7ZmˁJ#`7[ḿJ5D`7[ḿJ[D`7\m΁JD`7]mρJD`7`mЁJD`7amсJD`7bmҁK D`7cmӁK/D`7dmԁKRD`7emՁKuD`7fmցKD`7gmׁKD`7hm؁KD`7imفLD`7jmځL)D`7kmہLLD`7mm܁LpD`7nm݁LD`7omށLD`7pm߁LD`7qmLD`7rm။MD`7sm⁋M0E`7tmかMME`7um䁋MjE`7vm偋ME`7wm恋ME`7xm灋ME`7ym聋ME`7zm運ME`7{mꁋNE`7m끋N=E `7m쁋NE +`7m큋NE `7mOjE `7mOt`7mPE `7mQE`7mQd`7mR&e`7mRE`7mSAE`7mSE`7mT^E`7mTm`7mUE`7mUE`7mUE`7mUE`7mVbE`VlWn\? mW&W2ZEW@ZWEr``>IWT"""WaWY ^WdmWtWl vWwm"WW ^WmWW vWm"ẀW ^WmW݀W vWm>JW)?IX@"XKpX_XW (>JXm)?JX""""""""""""""""""XX (XmXX (XmXՀX (XmXX (XmYY (YmY5Y- (Y8mYXYP (Y[mYxYp (Y{mYY (YmYY (YmYӀY (YmYY (YmZZ (ZmZ,Z$ (Z/mZHZ@ (ZKmZiZa (ZlmZZ (ZmZZ (ZmZրZ (Zmn\S\aevEB\yev\~r``:>G\\ &\\m>J\\n\\m>J\] n])])m>J]<]Ln!]j]jm>J]x]n%]]m>J]]n]]m>J]]n,^^m>J^ ^0n0^H^Hm>J^W^gn1^^m>J^^n^^m>J^^n6^^m>J^_n7__m>J_(_8n8_O_Om>J_[_kn9__m>J__n:__m>J__n;__m>J_`n<``m>J`'`7n=`N`Nm>J`Z`jn>``m>J``n?``m>J``n@``m>J`anAa a m>Ja.a>nVaWaWm>JagawnWaam>Jaanbaam>Jaandbbm>Jbb!nlb>b>m>JbQbanmbbm>Jbbnnbbm>Jbbnpbbm>Jc cntc<c<m>JcKc[nwcucum>Jccnyccm>Jccn}ccm>Jcd nd*d*m>Jd7dGnd_d_m>Jdkd{nddmddmddmddm>Jeen>Je.e>nJeVefn t nffjDE`ngE`nh D`nh{D`n iE`n +iE`n j6E`7n \?  nkkE`nl+E `:'E!nljE"`:'E#nlE$`:'E%nlE&`:'E'nmDE(`:'E)nmD`:'E*nmE+`:'E,nn!E-`:'E.nn]E/`:'E0nnE1`:'E2nnE3`:'E4noYE5`:'E6noE7`:'E8npE9`:'E:npcE;`:'E<npE=`:'E>n qE?`:'E@n!qVD`:'EAn"qEB`:'ECn#qED`:'EEn$r*EF`:'EGn%rvEH`:'EIn&rEJ`:'EKn'rEL`:'EMn(s<EN`:'EOn)swEP`:'EQn*sER`:'ESn+sET`:'EUn,t>D`:'EVn-tEW`:'EXn.tEY`:'EZn/u0E[`:'E\n0umD`:'E]n1vD`:'E^n2vGE_`:'E`n3vEa`:'Ebn4vEc`:'Edn5wEe`:'Efn6wQD`:'Dn7wD`:'Dn8wD`:'Dn9wD`:'Dn:x)E`:'En;x_E`:'En<xE`:'En=xE`:'En>yE`:'En?y8E`:'En@yqE`:'EnAyE`:'EnByEg`:'EgnCzEh`:'EhnDzUEi`:'EinEzEj`:'EjnFzEk`:'EknG{El`:'ElnH{9Em`:'EmnI{rEn`:'EnnJ{Eo`:'EonK{Ep`:'EpnL|Eq`:'EqnM|VEr`:'ErnN|Es`:'EtnO}Eu`:'EvnP}OEw`:'ExnQ}Ey`:'EznR~ E{`:'E|nS~lE}`:'E~nT~E`:'EnUE`:'EnVRD`:'EnWD`:'EnXE`:'EnYEE`:'EnZE`:'En[E`:'En\TE`:'En]E`:'En^OE`:'En_E`:'En`E`:'EnaoE`:'EnbD`:'EncCo`:'End#`:'EneE`:'Enf,E`:'EngE`:'EnhE`:'Eni<E`:'EnjE`:'EnkE`:'EnlME`:'EnmD`:'EnnD`:'Eno&E`:'EnpeD`:'EnqE`:'Enr6E`:'EnsE`:'EntD`:'EnuNE`:'>nvE`:'EnwD`:'Enx)E`:'EnyE`:'EnzC}`:'En{ E`:'En|]E`:'En}D`:'En~E`:'En#E`:'EncE`:'EnE`:'EnE`:'En"E`:'EnmE`:'EnD`:'EnE`:'EnXE`:'EnE`:'EnE`:'En.E`:'En|E`:'EnE`:'EnE`:'EnD`:'En-D`:'EniE`:'EnD`:'EnE`:'EnCP`:'En-E`:'EnE`:'En8E`:'EnE`:'EnE`:'EnpE`:'EnE`:'EnE`:'EnE`:'EnE`:'FnF`:'FnaF`:'FnF`:'Fn{F`:'FnF `:'F +nF `:'F nF `:'Fn\? !n%+λF]l`on FB],`o1`on 1B`:n` B`RnFB`'=b9y'C;b9nrB`m9nFB`:'FnFB][`:`;`:`'Em'EVm'Em'Em'E^m'D8m'DNm'Ddm'Dzm'Em'Em'Em'Em'Em'Em'Em'E/m'FJm'Efm'E]m'Em'Em'Emn771`:\?n! +nm='n+ %l+nnF1`:`R\>=~P:Q.Z.Bn)l.Fn=Q/.Bn)l.Fn=N  Q0*.Bn)lU.Fn=h.Bvm=.1Bnnn+n! &n! 5 ln nk00l`R`*]m'`o>N`nn.1Bn! J%! نBnnLFBL`J.FBn-4K`o`J'7/'! ro(BmnCFBC`W`>FF`o.FBn>I!9FBo(Ҁ!W>J!9ro?I""""!~W%.FBnNE?!W^^U'C;b9~uo!Wv'D鄝b9!WWn(!9FBo>J!9ro?J)8mnSWbFBkbz`W`>I!"W(>G̀!"rWm>Jmm>Jm++m>J>Mmggm>J|mm>Jmm>Jm##m>J6Em__m>Jtmm>Jmm>Jmm>J57*hhm>J|7+m>J7-m>J7.m>J.7/IQ"c[U!"rW^7Azrl!"rWv7Z>Jo|v!"rWWn?G!"rW m>Jmm>J'6mTTm>Jc7,m>J7-m>J7.m>J 7/,,m>J@7`ccm>J7[m>J7\m>J7]m>J07'JJWQ!"rWnFB`o`>I"!p! +p>J)?I4"I?p܁n'F Ob\!Ewo>Jrm!Ero?I"!Ewo!!Eyo>J*?Ix"!}!E~o"".FBnro(m.FBnro(m"p܁n'F OWOJ=.FBnro(bm>Jq*?I"""p!Eyo +!E~o"""""""""""-%!Ero(8m_WQ!Ero(jm!Ero(mЀ!Ero(m!Ero(m80*!Ero(Cme]W!Ero(pm!Ero(m!Ero(m!Ero(m!Ero(*mRJD!Ero(]m>Jt*?G!Erom>J!p  m>J-!<pJQ`muo!EronF!B +`W`>Imxp>G!7rWm>Jmm>J!mAAm>JXgmm>Jm?JՀ!7rWn +F'l`W\>I".FBn(Yw"""( .FBnro(3m!>=- .FBn C?NEK`oQo_!@=mg!F"B~.F!Bđ!no=ŐŊ!FBŢ.FBŷ!noI"".FBn(Yw!!Һro( .FBnro!!.FB5!n>=.F!@n?=.FBn!;= .Bn!m;nAF +FU +d`W\>Nuwl`o}oNj!I!,p>I:"H@>!úro(Smf^\!úro(qm>=ȂȀ!FBo>=ȰȮ!FBā!úrooIp>=>=lj!F"Bˋ}nˎˌ!F#Bomo?=˱˯!F$B.FBn-4`o`J! Bwoo=.Bn!m;n-2ιF>ιM`W\>N^`l`ofot! N̗̎=`W+F̣̬`o̳.FBn>Iу!!)ro(ށ! ro>=!! !!)?I! !! (+>=>1.FBn4JJjK`o`JW_W!!(b!! JIx͉͐|.FBn(Yw>=Ώ΂.FBn7I?=ίΧ.Bnγ! m;! ! /! !!!!!! !" neF%`n\? nÁbръїc`R]m'`oJѨѬn'V!#Pnnā'EҞLҞYc`R]m'`oJjҍnn'Xҗ!#nnŁccc`R]m'`oJ-R1n'T\!$8n!#&!#!$!$nȁ8F&``pnˁj F'B],`p1ׇ`pnہ׎׎צעצ\> ׎n܁BF(B\>=.F)n=-.F*n  ńTYF+htD`p+\>I܆ܔ܊!%(+>=ܥ!%ܵp?=.n!%nn΁uF,uD`p+\>I!&V(+>=!&V&p?==.Enf!&VnnρF-\>=.nnnЁF. `:+\>I%!'G(+B>=6!'G'h>=X!'Gjb!'G(X=.n+F/1`:$!'G'F0nnс jF)j"D`p+\>=4.<miD[!(nnҁF1\>=.onnӁ EF2E#`:=D`p+_]`:+F3]`:+\>NF4`:峀!(փ(XNF5]`:5]`:!(#!)s(++!)s`:4#K`:`:J$#!)+'D!)ʃ!W]`:N.7F6]`:5]`:9!)#Q!*>(++Q!*>`:4]]^K`:`:Jg$i!)+'D~y!*!W]`:I梁!((+>=!(p?=.n!(1`:!)+#!)X*!*#*)nnԁW\F7mu`:F8`:D`p+]`:+F3]`:+\>N F9`:!+(XN/<F4`:F>!+(XN]cF5]`:5]`:e!+#z!,z(++z!,z`:4K`:`:J$!,'D!,!W]`:NF6]`:5]`:!+#!-G(++!-G`:4"K`:`:J$"!,'D!- !W]`:I)7-!+(+>=H!+Xp?=p.xn!+1`:!,2!,!,_!-,)*nnՁF:`: D`p+B]`:+eF3]`:+\>={.F2!.D!.ɯ!.F3!.nnց F* \>=.nnnׁ`p\>= .F'Bnˀ !/;n؁ %D2;`P`>JJ]Q.F'Bnˁ-4aab`p`Jhjh!0Dx!02p nف6D6`P`:K`:`>J.F'Bnˁ-41`p`J!1\D!0!0+!1p !%!&*!&!'!'!([!(!+s!.!/N!/!0!0!1 n݁;AF;``pn߁ F<]`:g`:n F/]`:֬g`:n။ F=]`:g`:n⁋5 D`pn끋{{D`pF<]`:+F/]`:+F=]`:+\>=L<.F<n߀5]`:S!2#c!3W(+:f`:!3W]`:=u!3 5]`:!3 #!3(+:`:!3]`:=!3!5]`:!3!#؄!4(+:`:!4]`:NF>]`:!3 4  V!`:`J'!K<m_nT!4NatF?]`:v!3 4`:`Jm_n!5=.F/n!4Q=! .F=n(!3!=]H.F=nd!4n!2 n䁋CKF+ozD`p`n>Jn!6F<:`:'C;'C]F/:`:'C'C'C'C'C'C'C'C'C'C'C'C'C'C'CF=:c`:'D'Dn偋bF,bD`p`n>Jn!7F<:!`:' F/:O`: +'C'C'C'C'C'C'C'C'D'DF=:>`:'Dn恋goF-`n>Jn+F<:`:'CB'CF''CW'C^'C_'C`'Ca'Cb'Cc''Cf'Cl'Cs'Cw'C'Cn聋D`P`>J.F<n߁nR!8vn運D`P`:4K`:`>NEM`:WRd!8Irv.F=nn$!9*'D!9>J.DnD!9pI.F=nn$'D!9>J'8..DnDB!9pIUkY.F/nn$v!9*'D!9>J)I.F/nn$'D!9>J)I +.F/nn$2'!9*'F@>J=)IUkY.F/nn'FA>J)?J*!5!6!7!8J!8!;%n쁋;FB`nn FC`n FD`n33HNH`D`pF<]`:F/]`:F=]`:FC`FD`\?nYF!<()n!<"() n!;F<!;F/!;F=3!;nMRD_h`P`>Iw{.FCn>NFE`:!<߯Q'$mI!ρ!= (+B>J".F<n߁n != (X7'.F<n߁nHRU!<??Jr"y.FDn.F<n߁nR!<n9D9`P`:K`:`>I#'.D5!>Mn>IG""K.FCnyk!>\('$B.F<n߁n!>k(X>J)?JD!>M!>\!>kn?J)*!<!>!!?On>DFF`nnFGB],`::`:'5'FH'b'}'FIn FJB]`:n.\>nNi`:_n yn+F<1`:'FKF/n`:4B`:`:J$'FL !@nD+4`PD`:ZK`:`>IgqD!@!@!An>J)?I"Ӂ!@('@ B!A('B>J)?I4'!@Q'@ m('B>JCYJ.FJBnnb!@?J|*!@!BnFM``po\? o&D&`P`>I%!B`u0>J*?I]"%ia!B`u}R!B`u}('FNB>J*?I%!B`u}>J)?J*o+0D?H`PX`:nK`:`>I{"!C('$B!CR'"D>J*?J.D!Co!Bp!CS!Do +- +< FO`o +`:'-o 5FP`:'FQo FR`:'to +\? !Do  P VtFSf`[`[]_`qo RB],`[o%      R],`[\?o!EO  Ŭo 9 +9]%_Jo/_0*.RBo + o>F\(M\`JPVP.RBo(Yow| _\>=.RBo!Fd;o``J.RBo!FGo  \>=.RBo Co)F+F0`_J:&:?:.RBo@!G9_oKY\a`j K_\>=|w.RBo}!G!H:o#(`\>=.RBo(!HvWoqqa__=r`+\>=F@.RBo4KKlQ=`[Yr`[`J_f_!Hـ&gg!I)_&jj!I7_=ovz ```J.RBo&!I`[Ձ!I?oU ``+`J.RBoU&!JM`[Ձ!J\Bo$)e/e4`= _\JIOI.RBoV!J߁]!JDojlty`_J&.RBo!K_H_o# #`y` ]_`\>=.RBo !Kԁ!K !K!LOo(-t8t=`Hy`\>=YS.RBoe!Ll!LPo y~`y` ]_\>=.RBo!M!M!M%Ro!NN` +y` _+\>=*$.RBo4!M;!M@!MQoSbrjr],`[Jmm.RBo!E!E!F:!F!G !G\!G!HL!H!I!J#!J!K5!K!L^!L!Mx!N!N[o&FTf`[`[`]%_o)B]%`[o/$$]%`[\?o)!O- o+).^6^`>J?PF.Bo)'o-ci'q_Jt&t~t.Bo)')_!Ob!O!Po0bhGFU`o4\? o2EE`:a`U [``U>N `U!U=<4!Pԉ';H!PR)U=h`!PԸz!PU=!PԵU4l`R`>Iʃ!PԮ"U(U>=!P!P?=&!PԀUJ3:!P!Pn!Qo5JPFV`[`]%_o8 FWB],_o9 =B`o:gB`o;XB_+oAmmL],_\?o80!Ro:KWo9ga!Rց(Y o=rwnn`>NFX`.gBo:WI!Sp.=Bo9>=.B.FWBo8!Sp9o;=.gB!Spo:J)?=0.B+o;=E.gBQ.=Bo9o:J^*o?sy'_J.Bo;!S<!Th!ToBFY`[`]%_oE FWB],_oFgB`oG%XB_+oM22KTL],_\?oEl!UnoFW 2oI`>NFX`.gBoFWIۀ!U.FWBoE(Y>=.B.FWBoE!U9oG=.gB'!UoFJ;)?=R.B+oG=g.gBzs.FWBoE(YoFJ*oK'_J.BoG!U!W!WEoN'FZ`oQF[B`oN ononF\B\? oTCF]BC`J`'g'F^oUHW0^`YJg#g.F]BoT{`Y't'F_+`YoWMF`M``\J#.F]BoT\'7'Fa1!X́`:\J&N#&N.F]BoT&b\'7'Fz&!`+\oi&&' &' &`\J&#&.F]BoT&Ԝ\'7'F{&!a+\oj'''s''s' `\J'.#'..F]BoT'B\'7'F|'h!a+\ok'x'}'/'''`\J'#'.F]BoT'\'7'F}'!b+\!W!X8!X!Y0!Y!Z!Z![![}![!\f!\!]<!]!^&!^!_!_!`!`u!`!aa!a!bKooB{BJ +F~``porBFB[+osB'B[+otBFB[+oxBBGCGC At`MC`C'`:\> NC=CNF[CPCr!cXIC}CC!c|(+>=0CCC!cX?=C.'BCܜD!cX'osIDD(D.'Bos(+>=0D9DC$D|DS!cX'F?=EEQt'NE@ENF[EPGEs!c|IEEE!do(+>=0EEE!cX?IEEE!cg(+B>IE!F E!do('>=0F%F/$'F'F?=F.FB-`Cot>NFF`PFF!cGF!cgN,=G CG0!eMG9!cg&GEGE!do`:=G[.FBGqGi!eM$ot=G.FBG['m'4G!c|or BovGGJFGJG`P`P>IH:!HRHFH>!fE$(HU.FBot>IH"!HH.FBot(-`C!III!fE$(-`fv>=0I8IB$Iy'FIm.FBot??=IFI!fEI.FBor=I˜[''I.'BosI!fEJII!fE!f!goyKKWF``lo|L FB[oPPPPPPF[\?o|!g Po~L5LELAULML`l.JLVLioLu['B'FL.FBo|oLLMLM`l)JLLoL圣['B'A|M.FBo|oMRM[MMbM`JMeMe`'g'M|.FBo|oMMMA^MM`lJMMoM['B'FM.FBo|oMMN$MN$`lJMMoM['B'FN.FBo|oN)N8NnN<Nn`lJN?N?oNK['B'Ne.FBo|oNNNwNN\JNN\'7'N.FBo|oNNPNPN[NA`:N],[+\>IOO"O!k>(+>=O3['7'FOT.FBo|OgpBO!k"O!k->=O['7'FO.FBo|PpBPoPPQFBPQP[`l>IPPP!l;QB>JQ&QQ!l;`l>=Q_>Qt!l;JQ~QoQ!l;oQQRV"QRV`RJQ0QR'FoRRSVBRSVR`:R^`RB[R`+\JR0RS'FoSSTUSTUS`:S^`RB[S`+\JS0ST'FoTTUTUT`R`JT0TT'FoUQUVVBUjVUr`:U^`RB[U`+\JU0UU'FoVTVYWVlWVt`:V^`RB[V`+\JV0VV'F!h%!h!h!i^!i!j8!j!j!l !l!m!m!n !n}!o!ooWW"ZF``l)oX5AzB[oXXYYYYAz[\?o!p8 XoXCXGXsXKXsXS`:\JX[X[oXd.AzBoXo!poXwXXFBXXX[X[\>=X['7'FX!pX!q +oYY*YFBY5YY6[`l)>IYFYJYT!qqYeY^Bh_>JYx&YxY!qq`l)>JYYoY!qq!pe!p!qA!qoZZ +\F``l.o[FB[o[[\\ \\F[\?o!ri [o[%[*[T^[.[T\J[4[4\'7'F[K.FBoo[Y[^[\[e[\J[k[k\'7'F[.FBoo[[[[[[[`\J[[\'7'F[.FBo[!sro\\0\FB\;\\<4[`l.>I\E\I\S!s\]\VBAUh7>J\o&\o\v!s`l.>J\\o\!s!r!r!sH!s!tgobbF`o`W +ob3B`W+obF$B`+ocVFB`+ocF"B`+ogyFB`R+og @|`Vm+ohBFB[haoovS]l`ovn'TowW]l`own'Xox0U]l`oxJn'Vo܁iijfTijfi`W\>=i.3Bi!vo=i.F$Bi.FBoo=i.FBj.FBoo=j.F"Bj*.FBoo=j<.FBjUjM.3BoRo ipi!v oddd8rd'd8`Jd*d*.F"Booddddd`Jd#dd.o('VBd.FBo`oee'e>we.e>`Je1e1.F$Booeeeee`Jee.rooeef)FBff)`Jf +f +`'t'Ff!.3Boofvf~fFBff`Jff`'t'Ff.3Boofgg1FBgg1`Jgg`'g'Fg).3Booԁhhi4FBhi4[>Nhh[hڜ-`WJii Hi$!yoځjjrjr j`: j`h+j`)k `)k%r`k;`kR`kjy`*kw`*k~`*k|`*k`R+`o>Ikkk!z(+>=l !zlB?Nl+F[=m!{ mR'qn!z ؂n8!z-كnO!z==nv['7$'F'Fn!{ =o['7$'F'Fo!{ =o['7$'F'Fp/!{ NpCpQ`:pSopg!z]pq!zM=pp!{ B + +p!z p!z-p!z=p!zp!{ p!zmp!z}p!zp!z p!z +=q['7'Fq'!{ q1!zM=q?['7'Fq_!{ qi!z]=qq!{ qoNqrF`oro&rr!{ `WIr$r@r1r(!|FBo(+>=rZrQ!|FB#ryrk!z (+rBr!z `Ro?Jrr!|oŁrssFss`Jss`'g$'F'FoƁsstst`RJss.FBooՁt:tHuFBt[ut``tnr``:>It}!tt!~(tW>Ntt`:tt!~D7Ntt`t'Euuu`u"u !6u&yu,u(!~(^u4!6u5u4!6W=u<u9!'}=uQuN!uW!~Jucumuj!A>Juunu!~oǁxpx{xQxx`:Jxxx.3BoQWoȁxxxyxx`Jxxx.3BoyWoɁxxyyy`Jyyy.3BofUoʁyy#yEzy/yE`Jy2y:y2.3BozWoˁyIyTyfyXyf`:Jy[ycy[.3BoWózJzRznz[zn`Jz^zfz^.3BoWózzz|zz`Jzzz.3Bo|Wo΁{${-{I~{6{I`J{9{A{9.3Bo~Woρ{M{X{l{]{l`hJ{`&{`{h{`.3Bofd`hoց{p{u|%@~B{|%{`:{`{`{`h{`\>=0{{'Fo|*|5|uF#B|J|u`:J|M|M`:'9'F|m.3Boo|z||xB||`J||.oo|||{B||`J||.roo|||B||`J||.ooÁ||}5FB|}5`:>=0|}'Foׁ}:}?~B}Q~ + + +}``:}q`}`}`h}`:}`}y`}w`~~`~|`\>=0~,~6'Fo؁~~~~~~F`:`J~0~~!oЁ~~}~`J~0~~!oсHF'H`J*0*4!oāLX@}Bb[Je0eo!!w!wL!w!x!xF!x!y!yu!y!}!~!~Z!!!q!!!g!! !]!! !! !P!!!/!!j!!!I o݁`f&`o߁F[0['g'FoF`*o\? ![oかKQIF``Ro偋 A`Ro灋B`:+pA`R\?o! o運 `J.AoRoꁋ#,L7L`J:B:.AoRo끋QZvcv`Jfnf.Ao帋Ro쁋{`RJ.Ao帍Ro큋`J.Ao帏Ro`J.Ao帐Ro&D0D`J3;3.Ao帑RoIYqc`q`RJckc.AocRov`[J&.Ao帓R`[o`:J.Ao偐RoKBK`:`+`+\>=0 'FoPUc\>=tl.Ao帟Ro\>=.Ao帠Ro\>=.Ao帡Ro/W;W],`RJAIA.Ao帛Ro?K^Z^`P>I`nd.Bo(+B>=0$''?N#`P&*.o`PNELc`P&ES.co`PNc[Dv>I!L.BoR2J!?=!Ł!["!!(+!!(!s[=0('o],`[J&.AoR],`[oB[J.Ao希BRo%GB1G[J4<4.Ao帒BR!!f!!!V!!!F!!!A!!!U!!!!!L!p F`p\? pF`P`P!?!p#2:F`p p"p.D`p+`pJCGmiDf!p u}F`p`pJp.!Ap 7D&7/`P`p 8D8 `P`:2K`:`!!!s!!p pF`pCF`p Spp`p`p Jp:!p ) )$`[\!x!!pWF``p p757\? p<<U HUN`[\>!!pSblF`p`pJp&pPUjD^jfM`:`!!5!wp7F``pp!1 FB`CECp"g FB`X-unBh_p&\? p$5D5M`:`>=.FBp!׀!\CJ""".FBp!FC(!.FBp"FX2BLG9.FBp!'C(TO.FBp"'X5Bvh.FBp!]C(.FBp"]X6B"".FBp!FC('B.FBp!'C('B" .FBp!]C('B*!.FBp!]C('B!0!4p':@pF``pp) `pp.`p\>p)! p+iDi`P`>I!.p)D!p >=0"8RE!?JZ)p,nsnDn`P`:K`:`>I!.p)D!!!p >=0$c3R@!'K!'Fł[!'F?!!x!ip/F``p p1]`pp:jj`p\>p1! jp3 `[\>Oa`[`[\`[`[\>=.F!x!p8N `[!x[C+!7+(:!>NOn[K>=!![[l[>=.FB! !xp5=!+=4!E@!x[Ib!lf!(+=yu!Qz!!x?=!&!`[=!Q!8+p5CFBC `[`[\>I!_(+>=!P[>=' !_B4!P[p6 FB [`[\>NF`)NF5[NFE[K>=!9!=1!G?:!9'$NQ`F`jR&!`P=b!##n!)R&!`P`[l[>NF`:'FK>=#!91!AK[Rl[>K>Nl{F`:R!=.FB&!`P!!#!!q&!9][[[&!G`:p7 `>=/M\[cl[>=.FB&!`[Ձ!p5=Bhc/$'Fх!okp7FB`P`[F`7`:D`:MF5][[[[FE`:\>Ii!s*(v!>=.FB!ف!p5=Bhc/$'F҃!'wokJ?I !/%.p1D=!p >=O.FB[!فd!p5=zsBhc/$'Fӄ!'Fԁ!okJ?I!߆!:(+B>I!.p1D!'$!:p >=1.FB=!فF!p5=f^WBhc/$'F'!'Fֆ!:'okJ??N5:],[GBNK[!T!9I!.p1D!&! !`:&!&! m`:p >= Bhc/$'F'F!'RK! 'FXS!&Y! m'ok=sm!&z! v?I%!`d>N@ `d!`d=. !hdp3?p8INFZ``[k`[\>AGy!༆[[>=.FB!!p6B[[FF[aa[>B}>=.FB!!p5!! !!!!B運&FB],`:10`:''9BꁋIFB],`:1R`:'{'zB끋kDB`:'B쁋FB`:'B큋FB`:'BŊ̊`hJϜ`h'A='B-At6`U}J==`U}'F'AtB򁋋ƍFF؍F`[F[]_>N]__N#Fa[\4%%W&F[\J7A7!st&JJ!]_N_mFa[\4oopF[\J!sj!=[''F「!\͡Ea[\!Ea[\!J->4!suB󁋍F01F[]][`:[>NDN]][`:[T][`:[N~Fa[\4F[\J!tpG!NFa[\47F[\J!j*!e=<[''F』S!^Ea[\u!Ea[\!GJρ!uBuFBu`Rd`:`>Nc`R!!cRJ+#%92!=`PMF!=`Pb!$R3*`B))*bFB* +*b* F[`l>I***!(+J*%+?J*4*Po*\!B*e*q,_FB*,_*l[`R>I***!c(+>J*+?I+y+}`'g'F+!c>N++`l+o+!cI+%, +,!`R>J,",)!?J,;+J,U&,U,\!c`RB,b,n,FB,,,l[`R>I,%,,!i`oy>J,&,,,!i`oyFBo|`R>J,&,,!i`RB,,-tFB--t-[[>I-%--!`M>J-/-6!`M?J-?-FpC-p!B.O.O0 FB._0 .`[.m[[>J.~4..0 .[[>=.F.!ց.!=/[''F/!ւ/!J//ᜣ[''/!/!B000HFB00H0[[>J0,0<03!B0K0K0FB0X00Y[[>J0g0w0n!ރPB001FB010[0K[0[0q[[>J00Ԁ0!90!D0!N0!YB111FB111[[>J1%1,[''F1ءE[1!ϔB223FB232[[>J2$2+[''F2E[3!>C446\FB46\5`P5`:5*F`:\>I5="!5B`'g'F5i!5r!!"55!('@ B5`'g'F5!>=06 6'F?C6_6hAFB6~A6[6At[6`:6\][[[+`>N8z8F`:'N8`I8!88!(+>=8!&88у8!'m`:=8!&888!'@m`?N9 +9F[99?!I9H9]9L!(+>=09l9v9!?N99[9['m'49!N99[9:!'I:":2:&!(+>=0:A:K$::[!'F?=;;Qt'N;A;OF`:&;A;QG;t!`:I;;;! (+B>=0;;;!?I;;;!(+B>I;!<;! ('B>=0<<($'F'F?>N<<[<B>&B>7!>D!=>W['7'F>|! >['m'F>B>B=>Ҝ['7'F>! ? ['m'F?%B?9B=?M['7'G?z! ?['m'F?B?BN??*[?ꜣ['m'4@! +N@@%[@'['m'G@L!r @W! =@gF@! @!N@@+[@['m'G@! I@!@@!(+B>=@['m'GA!A!?JA4A;`'J'GAv!A!A!CAABJGBABJAl`P\>C$58GBA8`[Sa_\a_\>I(ªJ!'?I!'(+J+?J _-!'C;QeGBhe`[`[a__\a__\>Iު(J!?I !(+J+?J,@88__Z!Cwx`:`PJBw!N)CL[z~`P`Px`:]PI_JBz_!LN*EkV"v!2]ǰ[z9μ[Ү; +ز[ۨ܍߹Z0Ct + +  q 8;<>@ACFGLN QSSTY/[ \g-ghoijzkIllnpHrsMtvpw(xzAz~~hGqU~`  +p &  2QDc=.I!')f*+-g.0212p578:OJ(LM;@Dal˜N(5  +e 2S)b< 3lVO +y + +5h B$m(++-27)89;=%JLLloJptvuwqzb0`9e-#+Өt׼$ڌ@ީ-o<Kp9CK SZm"j#%Z)*J+-/N03S5O7=!>7?BILeS:UVV#WBX`-dxegijQlmmvDxyy+UCJ-ݭHyGry~@#$')C+; ;<=?-@CJLPKQUX[]8abc4cdHegfi]jkjmndpruvwxy.ybQYDS0^: k]Dŝǩh.g(r +6 r 0!& )/ 056w9>=b?C`CCIJKM#MSMT1\]Z_bcfgmnop!{vd I#Y%s$w!WBx?gȌBtժۜ߉#$!F\dl|H +wJAo"#$&(+-5AlFR/3"vËyʓ!˭9κD8nfـ5O} ;qf6 g  ,      l   ?    '    # $ $ &< ' )z * + - /y 1 3 6 7| 9 IpX!gJ!g?=0!g'K'Gp\/6iA>i`:>JG\N.Cp'Rp]rw}K`:B`+`>=.Gp;!1p[N˃]`:.CpN`*I !>(+=!>!!!tn*!1?I6:!>>=OM!tS!1=a!ə)>=!t!1=.C!tpJ!əp1:IBAI`JD*pn +]%`:J.Cp + p^11a`:\\>=#.Cp+!p_6={A{J`:'`:J^l^.Cpq!Kp``[a`:l_]_J.Cp_!˴pa҇ ׇ a`:`]`:J.Cp!pbf#f`[0a`:]_]_JLZL.Cp_d!̕pckp=u{a`:``J.Cp=!pd-a`:``J.Cp-!lp `J .Cp p FC+F`J.<..CpCpKSq(Zq`J]k].Cp(pev} a`:`:K`:`:>J.Cp!Μpfhh`[ _a_`: __>J1F8.Cp_N!\!!pgTYnaiK``>Iv!%z!ϔ`:J*?=.Gp;&!ϔ`:p[J.Cpn!ϔph07m=mEK``:JO&O#O.nX!0pga!0+``:pi  K`:`>=&.Gp;5!Еp[J&.4]`:`JŁ!怘!Еp`pjvvK``>=.Gp;&!I`:p[I!%쀍!I`:J*?N]`:.CpN29`=;!ўD!I=P.C]!ўpJel!pk$)/A ]`:\>=.4]`:\J!_!/`:.Gp;p[ppluz]`\>=.4]`:\J! !ppmB]`:B`+\>=!g4l`:\J.!ӭ!zp]pn s)s;]`\>=K.4RRnS]`:\JY[Y!1e!ppox}a`:K`\>=.4]`:\J!Ծ!ԋpppғה''a`:K`\>=.4" ]`:\J!K!ppq,1 <N]``Jcqc.Cp }!եprs]`]`:J.Cp!ps** s]`:]`:J.Cp$!opt/;{ E{Rs]`]`:J\j\.Cp u!p`:J.Cpp`:J.Cppԕߕ`:J.Cppu]]`)],`:J5C5.Cp؀T! pvamr]`:Jxx.Cppw`]`:J.Cp!ؾpxʖۗ$$a`:K`]`:J.Cp! py(9]=]B`]`:JHVH.Cp[!ٌpzar~{a`:K`]`:J.Cp~!p{Ƙ4 И4a`:K` !a`:+`:J.Cp !Z!-!rp|8?yHNa`:K`j !a`:+`:J~~.Cpy!!!p}&&a`:K` !a`:+`:J.Cp!Z!!rp~*1g:g?``:JIWI.Cpa! plq v\>=.4]`:\Jƀ!S pp !a]`:[[>NEG]`:I.CpN`d[gf!ܦh!=p.C}!pJ!p\huCsu]`:p"'BC3B@]`:\!A!!!V!ʄ!!+!ˉ!!j!!L!Ͳ!!:!|!!t!!u!)!!һ!E!!k!!Յ!!O!ַ!!c!ק!!P!؞!!l!!:!ں!:!ۺ!!܆!/!^!ݖ0pdsG`p],[1[pG],[1[p\?  p$(G01K[`>NBI(`RK.p(YE^gi`pn!5r!z!5{z!5W>I.p!59!J!5?=.p!;=.Gp+;J!pG `[J.Gp!#9pJG(J-`0[[>=?9.Gp@!xE!:pOO_G[_[>pGa[`pGŒ[pȌ͌G֌([],[pG[[K[\p88vIFLJ!(+JU\!?Ic%ig!`Jry!`?I%!`J!`?I%!`:J!`:?I%!`>JpK!`?I% !`>=05?!'G?I%!`SPJ!`SP?I% +!`EJ!`E?I#%)'!`SmJ6=!`Sm?I%!`VFJ!`VF?I.G!pJ!?I%တ!][[[>N`.G!][[[pN [.G#!pI0!94!(+JBI!?=U!\.Gp=n.Gx!㙂~!p=!][[[4[K[`>=.G!Ƀ!m.!vppxJ!?I%!],[>N`.G!],[pN [['G'.G!pI!!(+J!?=!.G  !],[!pJ#!?=04>!'G!p{WG Wl],[`],[>N`N(`!ہ(YNϔ ],[.G!p=.G!鄔!1pE!!!!W>=,(!1-!2.87!9!9p:JHO!1p\\G"K[[>N [.!&p=.GpJ!5!!!V!!!!9!m!!!!p p ^G#`po],[1x[pG],[1[p>`*p\? pGK[`>N (`.p(YE"+-`42!萀6!k>!?>!W>IKO.G$c].pd!9h!XpJpw!?=.p!X;=.Gp+;J!kpdi|G$v|w=[zr[`pG`[J.Gp!9pG`[[>=.Gp!!:p G% a[ a[[ˁK[[pG&([],[p˜ˢϢl[[> +I߀!(+J!?I%!`J !`?I%!`J!(!`?I/%53!`:J@G!`:?IOSpNd!>JpwpJ!?IpO!>=0!'G?I!%pS9!>JELpTm!?I|pQ!>N7<`>.GG!pNUZ [\.Ge!(pIr!{v!N(+J!N?=!N2[[=.G!(!Np=.G%!4؟[K[[J5[!N5[!5[.!p5\셟!! +!!pJ!N?I $pP6!> NFH[J['~'Z!Nhm`o.Gx!pN [['G'.G!pI!ƒ!(+J!?N(`&!튁(`=s!#z.>p.G&!*p![=.G!!pEˡ`ԅ!!*!߅!W>=!Ҁ!.!!pJ!?J!pǢǣ\G'\a[>[*[>=.>&"!n`pN49 [;.@!dpJMT!!6!a!!!U!!!B!pˣѥPG(`p`p`p `p`p5`pS`pcG)`pNN```G)``$`F`\?p!p!p!p!p!p!p! !up>DG*``VFp `%p `p `pè`%``\?p!p!p! !QpG+`pp\? ppā܆܆G[Jꜣ[''JpŁCGC[ [K[\J\'7'23!8!=! pƁGGGPQ([],[J\\],[''G,!bpǁGl[`J"%!`%€!`r!!!@!!pʁڇG-`pp\? pṕ!&jG/j0([],[J;;],[''G,c!gṕnsG&~([],[J.G!pp΁G$=[r[`J! !pρψԉG%≇a[a[[ˁK[\>FJ[][''iA!d>=XR!mY!^[''Np!dx!!E!!!B!pҁbG.`pՁ4G/p;`+pցLG0p;`+pׁaG1p;`+p؁{G2p;`+pفG3p;`:+pځG4p;`:+p\? p܁]o0y`:J||B[h?0[Rp݁߂cG5c`>I +p(+>=p0&p܁n'^O?JPWppށȄ?G6̈́?`>Ip(+>=p"!p p܁n'G7O?J/6pp߁G8`>Ip(+>=pp܁n'ZO?J +ppbrG9{`>Ip(+>=p"!pp܁n'G:O?JppၐDVG;``:>Nmt`:vpI!!/(+BJ!/?Ip>=!/'G=!/'G=Ip>=*!/'G>>=M!/'G?Jlspـ!/p⁐̇މG@`:>N`:pI!)"!(+BJ29!?IEIp>=\!'GAIw{p>=!'Ip>=!'>=!'GBJpڀ!p䁐|`GC`D`:`>K>Nl`RR!'J&%/-!`R?[Fp[>JP*!!+!!!!!!!'p灑GD]`P`qpꁑ GEp;`[p끑 GFp;],`[q EE `[\?p*%!̑[pꀃA! pф,p;ۄ,]`PJ .GFp;p4 `[`J%!j`P`P4+`[`PJ&!!`Pp0BGGp;L],`PJUY0`Pl.p;p*pppa`P\\>=bX.GGp;pj!Spu`K`P\>=.!q![q΅҆(؆`\>NV`.(pI !^!+>J)I<J@!>=0Wa'GH?=.!!+pp K`P\>=.GFp;p뀘!;paa ]`P\>F!C.`P9!*>=K.O!Gppfkns{ ``>I!%!`PJ*?N`P&!`PJ!ö[(.GEp;pp00]`PJ(.GGp;pZp5:>Da`P`P=r`+\>=0jt'GIpK K`y` ]`P`\>=0 'GJpPU^c`ny`| `P+\>=0'GKp։ۊdd`y` ]`P\>=0('GLpiny~`y`\>=0[.p;p" "y" 4܊[\J炊"p \>=~r.GFp;p Cq7`P>N`P.p;pI!׀",(+>=",[?J +",q$)`8 K`P\>IEOI"(R.(p>=b.f"p>N`P.p;p" ="[""\q` ]`P\>I+5/"(8.(p>=H.O"p>Nqy`P{.p;p" ="[l""[qII``P>N `P."^q=*#"u[J8?"uqNS1Y1a``>Ip!%|t"`PJ*?I.n"p>=&"`P[J)>J*p񁑏6>X(EX`JHRH.p;p( q\mot``PJ~~.p;p" p򁑐8Nl +Wl]%`PJZdZ.GGp;p + p󁑐q],`[J.GEp;po[! !!3!!!! +!s""[""&""""""b">""J"""/"yq +1GM`q\? q ̂ӂ=],[``r``>I"a^$""F(Y>J4;W?IIXM"a>=e"a?E`"a"耇"n""W>I"F"9("T>J"?JWq UDŽ=],[```>I" €>JW?I'6+" ƒ^;9" (Y>=K" aZX" (Yy?Epy{`}" " +Y^" +Y" +Yy>I" " +Y9(" >J" +Y?JWq//=],[` y`GN],[],[>I)3-" !=08BS" !?I_gc" .i" !=0pz" .?I" .w" (Y=0" .?E׆`" !䄆" " ." 섆" W>=" ; "  +" 9;J " ;"&" " +" qyGO`q\? q],`[" " p>rGPp;`:$'GQ'GR'GSp? GT` U]p>p@|GU` p>pBuGV,u-K[[>J8?pLm" pChGWha[[>J%pMO" >)pDSSGXxyGY[[>J p9`''GZN"@n`''G["@`''G\"@ܜ`''G]"@(`''G^J"@j`''G_"@`''G`"@pEGaGb[`VF>=[''}I%耪"L`VF>N`%"L`VFVHI`'g'Gc8">IGK`'g'Gd>=['7'Ge"=['7'Gf6"??JPW"L`VF?Jp +`%''Gg1"LI`''‮_"Lw`''怮"LpFGh#.Gi`VF[>I=%KA"`p>Jel[''Gj"`pp"`pp"`pp?J"pG~Gka[][`:[>Iɀ"`(+J+?NGl][`:[2`:[N [[''GG"`FRj][&dd"][>=tp"&tu"`:|[''N"`"nJ"pHGmGl][[[(Gna`\+[>ICLG"l(+JU+?Nhoa[q[''JI!"~(+>="~"?="l4Ƀ [K[`>=ܜ['7'2""#",xJ"pIGo҄],`:],[>J "pJ&GpBCy[`>NQbGq[d['t'}"JU&"`)pK؄؅CGrCy`[>J[''*%"[ DpLFFG"stK[[JpG""ppMG'  +a[>[*[J,Y0pG'">"ppNGsK[`J`'g'"kpOԉيGtK[`J`'g'e"pP %hGu6h7K[`JAA`'g'Kb" pQjo)Gv)K[`>N[[''Gw"^J"Ӝ`'g'Gx"q`'g'Gy!"qpR,1GzKLK[`JZZ`'g'G{~"pSG|K[`J`'g'G}"HpTbG~"b#[][>N4>][D[NW\ga[\^Ea[\4uuv[\J"t"NSa[\Ea[\4̌[\J⁌"j"BNG[[''G0"9"ǃ?"JIZP"u!!_!!!~!Z!!!P"" "  " " ""*""?"J"t""9"""I"""<""&"y"qG=RNTBp;"*/Vqq G`q\? q*<GPX`:`u}>Nqv`PBB'G"N-J&"&`u}""hqֈG + 'G`s`vq c`q+q `q+q%\? sq"KSpq]`q>=0fp'q#`qJ&q'=`q""E"q&zG + 'G` q(G`q)G`q*G`q+JG`q,yG`q- G`+q.K`+q/G`:+q0G`+q3kspqz`q&>=0'q5(G "'(G`\q6-2xG "'HxMG`[G`\""""`q7UG Vx  ϣ ؤ + 'G`qq?̎̎\? qq:jrpq`q7>=0'q;ǎՎ`q7J&q'`q7q=;KU`J^"iv '%u'`q7""@""q@Q:G  ƣ   + )'G`qqH//_K_\? VqqCÒpqْ`q@>=0'qD~2~`q@J>&>Yq'G`q@qF88`J"v 'G% u'G`q@"t""" JqIϘG 8 Ac m + 'G`qqQؗ\? qqL=0fp'qM`qIJ&q'G`qIqO1AK`JT"_v 'G%u'G`qI" "!*"!m"!qRٚG + 'G`qT G`q&+qU G`q&+qX7?pqN`qR>=0Wa'""9""wqYÜG + 'G`q[ G`+q\G`+q_#+tpq=0EO'"""#$q`yG z + 'G`qbu G`+qcG`+qffpq.f`q`>=07A'"#"#qgirG j + v'G`qiY G`+qjiG`+qmJpqJ`qg>=0%'"$@"$~qnM|_G N + Z'G`qp= G`s+qqV G`s+qtۡ+pq+`qn>=0'"$"%+qu:m`G ; + G'G`qw: G`t+qxW G`t+q{Уؤ$pq$`qu>=0'"%"%q|;jAG < + H'G`q~( G`+q8G`+qɥѦpq`q|>=0'"&G"&qOBG  + )'G`q G`t+q9 G`t+qpqΨ`q>=0'"&"'2qYpG  + *'G`qA G`t+qg G`t+qũͪ"pq"`q>=0'"'"'qKxSG L + X'G`q3 G`u+qJ G`u+qիݬ#pq#`q>=0'"(N"(q.]:G / + ;'G`q G`:+q1G`:+qĮ pqԮ `q>=0'"(")9qKJG  + "'G`q! G`v+qA G`v+qpqа`q>=0'")")q%VG & + 2'G`u}`vSqq G`u}+q G`uN+q G`uN+q//[G[\? Rv qDZϲpq`q>=0'q&~6~`qJB&B]q'N`qqG "'\qG "'e`\qͳҳG "'ܳ\qG "'e`\q1G "'(1`[q6=WG "'NW`[q\cxG "'ox`["*"*"+"+N"+"+"+",(",[", q"G + ¢'G`sq G`qn+q G`qn+q `qn+qÁ\? sqEMpq\`q>=0eo'q`qJ&q'G`q"-a"-"-qā-OG + +'G`sqƁ@ G`q`+q́! !\? sqɁpq`q>=0'qʁEE`qJ +& +%q'`q".m".".q́*V8G + + 7'G`sqӁ6"6\? -sqЁpq˽`q>=0'qс^^`qJ'&'Bq'G`q"/`"/"/qԁ?AG  + 'G`u}qځ@@AAA\? Avqׁpq`q>=0'q؁@B@B`qJ@ &@ @&q'8`q"0c"0"0qہABCG A'G`u}qCyCyCCC\? CvqށBxBBpqBB`q>=0BB'"1k"1qၓDDGG D + D'G`sqこF G`qn+q䁓F G`qn+q偓F G`qn+q恓G G`qn+q쁓FtFtFFF\? Fsq道EEEbpqE*Eb`q>=0E3E='qꁓEgEoEE}E`qJE&EEq'`q"2"2"3>q큓GHMG GH HH9 HCHe' HpH H + H'G`u}`sqKG`qKG`7qL$G`qLWG`qLG`qLG`qL G`q+qM G`q+qM. `q`+qM| `qn+qM `q+qM `qn+qM `qn+qM !`qn+rJJJJJ\? JvqIXI`IpqIpI`q>=0IyI'rIIJ IJ `qJI&IIq'G`qrK)K9KKCK`JKL"KWv 'G%KKu'G`q"5k"5"6 +"6qrNOUG NգN OO" O,ON' OYO{ O + O'G`u}`s rRG`rSG`r S[G`r +SG`r SG`r T G`q+r T) `q`+rTK `q+rT `qn+rT `q+rT `qn+rT `qn+rU !`qn+rQQQQQ\? QvrPMPUPpqPkP`r>=0PtP~'rPPQPQ`rJP&PPq'G`rrR6RFRRPR`JRY"Rdv 'G%RRu'G`r"8"8"9%"9rUV[G UV VVA VKVm' VxV V + V'G`u}`srZ9 G`q+rZ `qn+r Z `q+r!Z `qn+r"Z `qn+r#[ !`qn+r+XXY4Y Y4\? Y+vr&WxWWpqWW`r>=0WW'r'WWXMWXM`rJX&XX"q'G`rr)YyYZYZ`JY"Yv 'G%ZYu'G`r":";B";";r,[\`G [ߤ + ['G`u}`sr.]G`7r/^*G`r0^aG`r1^G`r2^G`r3_G`r4_=G`7r5_w G`q+r6_ G`q+r7_ G`q|+r8_ G`q|+r9_ G`q|+r:` G`q|+r;`& G`q`+r<`x `qn+r=` `q+r>` `qn+r?` `qn+r@` !`qn+rE]]]]]\? ]vrC\\\pq\\`r,>=0\\'">b">rFabi G aѣa ab b(bJ' bUbw b + b'G`u}`srHeG`rIf'G`rJfRG`rKfG`rLf G`q|+rMf G`q|+rNf H`q`+rOg G`q+rPg6 H`q+rQg\ H`q|+rRg H`q|+rSg H`qg+rTg H`qg+rUg H`qY+rVh H`qg+rWh? H`qg+rXh `qn+rYh `q+rZh `qn+r[h `qn+r\i + !`qn+rdddddd\? dvr_cOcWcpqcpc`rF>=0cyc'r`ccdcd`rFJc&ccq'H `rFrbeDeTee^e`Jeg"erv 'H %eeu'H `rF"A"A"B&"BreijoH + ij jj6 j@jb' jmj j + j'H `u}`s +rgn H `q|+rhnE G`q+rinb H`q|+rjn H`q|+rkn H `q|+rlo `qn+rmo. `q+rnoN `qn+room `qn+rpo !`qn+rxllmm m\? mvrskikqkpqkk`re>=0kk'rtkkl8kl8`reJk&klq'H`rervmbmrnm|n`Jm"mv 'H%mmu'H`re"D["D"D"EarypfqNvH pgp pp pp' pq q + q"'H`u}`sr{tH`r|tH`r}tH`r~u H`ru2H`ruc G`q+ru G`q+ru `q|+ru H`q`+ru H`q`+rvJ `qn+rvj `q+rv `qn+rv `qn+rv !`qn+rsgsgsss\? svrqqrApqr rA`ry>=0rr'rrFrNrrfr`ryJrr&rrrq'H`ryrsstst`Jt"tv 'H%tdt@u'H`ry"G"G"HI"Hrwx{H wwţ wΣw wx' x'xI xR + x^'H`u}r{ H`q|+r{ H`q|+rzczczzz\? zvrxxyCpqy yC`r>=0yy'ryHyPyyey`rJyq&yqyq'H`rrzz{pz{p`Jz"{v 'H%{W{6u'H`r"I"J"JZ"Jr|}oH || ||ߣ |} ' }}8 }A + }M'H`u}`sr `qn+r `q+r `qn+r `qn+r !`qn+r``v\? vr}~~Npq~~N`r>=0~~)'r~S~[~~i~`rJ~u&~u~q'H `rrQQ`J"v 'H %?%u'H `r"L"L^"L"MrH!  A Km' x + 'H"`w r\? wrIQpqa`r>=0jt'r`rJ&q'H#`rr*4`J="Hv 'H#%pu'H#`r"M"N="N"NryW$H$ z ǣ ѣ'  ) + 5'H%`w r11[G[\? Rwrpq`r>=0'r$,:`rJF&Faq'H&`rr""`J"v 'H&%u'H&`r"O"P"Po"PrH' " +M Wy'  + 'H(`w rǁ\? wrU]pqm`r>=0v'rÁ`rJ&q'H)`rrŁ&6@`JI"Tv 'H)%|u'H)`r"Q"Q"RN"Rrȁc0H*  ӣ ݣ' +, 5 + A'H+`w rЁ==gSg\? ^wrˁ+pq+`r>=0'ŕ08F`rJR&Rmq'H,`rr΁..`J"v 'H,%u'H,`r"S"S"T-"Trс H- . 7Y c'  + Ǣ'H.`u}`srӁ$ G`q+rԁA H/`q|+rՁh H0`q|+rց `qn+rׁ% `q+r؁E `qn+rفd `qn+rځ !`qn+r䁓..\? %vr݁pq`r>=0'rށLL`rJ & &q'H1`rrs + +`J"v 'H1%u'H1`rr⁓zH2 "'H/`H0`\"V0"V|"V"W6"Wr偓];eH3 ^  ף'  + 'H4`u}`s`vr灓R H5`q+r聓 `qn+r道 `q+rꁓ `qn+r끓 `qn+r쁓) !`qn+r큓_ `q+r::dPd\? [vr(pq(`r>=0'r-5C`rJO&Ojq'H6`rr++`J"v 'H6%u'H6`r"Y"Yg"Y"Z!r@H7 Ac l ' ţ + 'H8`u}`srJ `qn+rj `q+r `qn+r `qn+r !`qn+s9%9\? 0vrpq`r>=0's +^^`rJ$&$?q'H9`rs~`J"v 'H9%u'H9`r"[r"["\"\xstH: ţ Σ ' 'I R + ^'H;`u}so G`q+sTTn\? yvs +:pq:`s>=0 's ?GY`sJe&eq'H<`ss UU`J"v 'H<%?!u'H<`s"]j"]"^ "^psO2H= Pr { ɣ' ԣ + 'H>`u}`s sH?`sIH@`sHA`s G`q+s G`q`+s `q|+s" `q|+ss `qn+s `q+s `qn+s `qn+s !`qn+s"\? vs pq`s>=0'"`l"`s#HB ̣  #E' Pr { + 'HC`u}`ss% `q|+s& `q|+s' G`q+s(3 `qn+s)S `q+s*s `qn+s+ `qn+s, !`qn+s4\? vs/:BpqS`s#>=0\f's0`s#J&q'HD`s#s2)`J2"=v 'HD%fu'HD`s#"bH"b"b"cNs5nHE  ٣ ' 2 ; + G'HF`u}s7a `q|+s8| !`q|+s9 "`q|+sABBq]q\? hvs<&pq&`s5>=0's=+3F`s5JR&Rmq'HG`s5s?GG`J"v 'HG%0u'HG`s5"dl"d"e "ersBu^LHH v ã ͣ'  % + 1'HI`u}`s sD G`q+sE H`q|+sF H`q|+sG% HJ`q|+sHO HK`q|+sIy H `q|+sJ `qn+sK `q+sL `qn+sM. `qn+sNI !`qn+sV{{\? vsQSpqS`sB>=0$.'sRX`y`sBJ&q'HL`sBsT`J"#v 'HL%{Vu'HL`sB"gY"g"g"h_sW' HM (J Su ' Σ פ + 'HN`u}sY HO`q|+sZ HP`q|+s[B HQ`q|+s\e HR`q|+s]ň HK`q|+s^Ų `q|+s_ !`q|+s` "`q|+sh\? vscks¿pq‡¿`sW>=0š'sd((`sWJ&q'HS`sWsfL\f`Jo"zv 'HS%Ħu'HS`sW"i"jF"j"ksiǣaHT ǣ  @' Km v + ǂ'HU`u}`sskʗ G`q+sl `qn+sm `q+sn$ `qn+soC `qn+sp^ !`qn+sxɐɐɹɥɹ\? ɰvss19ȀpqHȀ`si>=0Q['stȅȍȚ`siJȦ&Ȧq'HV`sisv}}`J!",v 'HV%lSu'HV`si"lj"l"m "mpsy<HW =_ h̊ ̶̔'  + 'HX`u}`ss{?HY`s|pHZ`s}ПH[`s~H\`s H]`sAH^`sz H_`q|+sѢ H``q|+s Ha`qg+s 7`q|+s Hb`q`+s< `q`+sҊ `qn+sҪ `q+s `qn+s `qn+s !`qn+s$$S?S\? Jvsͳͻpq`sy>=0's s(s`syJ4&4Oq'Hc`sysϘϨ)ϲ)`Jϻ"v 'Hc%u'Hc`sy"o"p5"p"psԿ؇Hd  0 :\' gԉ Ԓ + Ԟ'He`u}`vsן Hf`q`+s `qn+s Hg`q`+s `qn+s0 `qn+sK !`qn+s؁ `q+sּּ֓֓֨\? ֳvs4<ՃpqKՃ`s>=0T^'sՈՐ՝`sJթ&թq' `ss׀׀`J$"/v ' %oVu' `s"rr"r"s"srsb}Hh c +`sl `qn+sڌ `q+sڬ `qn+s `qn+s !`qn+sRpqR`s>=0#-'"t("ttsHi Ť +`sܱ H5`q+s Hj`q+s<D܊pqR܊`s>=0[e'"t"u-swHk   : C + O'Hl`ssw `qn+s `qn+s `qn+s !`qn+sÁTTp\? {ss6pq6`s>=0's;CߣWߣ`sJc&c~q'FN`ss]]`J"v 'FN%E%u'FN`s"vE"v"v"wKsāHm Ⱔ + ⼢'Hn`ssʁ\? ssǁ5=pqG`s>=0PZ'sȁ`sJ&q'(`s"w"x%"xvsˁHo 偢'Hp`sśO Hq`q|+sׁ + +5!5\? ,ssЁYpq!Y`s>=0*4'sҁ^dHr "'ty[``tsӁHs "'`[sԁHt "'`t`sՁ_ "'`t`"y"yZ"y"y"z/"zys؁ Hu 'Hv`u}`vSsځ Hw`u}+sہ Hx`u}+s܁ `q+s݁ G`uN+sށ G`uN+s灓ww\? vsၓu}pq`s>=0'sこ*/?Hy "'6?`us䁓D_nHz E'H{ "'en`tns偓sH| t'H} "'`tn"{"{"| "|Z"|s聓N + 'H~`s`vsꁓR`:+s끓; `qn+s쁓h H5`q+s큓 `qn+s `qn+s !`qn+sH `q+s\? sspq`s>=0's77`sJ&q'q`ss][JB[[''"."}"~+"~|"~s)PH * + 6'H`sH`7s0H`s\H`sH`7sH`7tH`t H`7 +t9H`tlH`7 tH`7tH`t G`+tK`+t G`:+t #G`+t pq`s>=0't=BnG "'Yn^G`\tsxG "'G`G`\"""7"tH`]`s"tH`t]mj`s"tH + 'H`t],`st H`+tt|pq`t>=0't(`Jל`'t'h.t#%*``s>I7;`'g'Հa"6h"6o"6v.(t=0"6.?J."6t%tPP` K`s\>=0't+(K`\>=0't +`s>I .(tw>J-4`s'H'z.?=0Zd('t))`s>NV`.(tI"Dw>JӜ`s'H'N."Dy?=0 ('t.9 @ `s>NJNV`U.(tIaie"(>Jw~`s'H'z.?I"(=0('?=0('t ;!;&``sJ04.5"tt"afq "'pu`H`s\t#H "'H`s`st$  "'\t% "'``st&)H "')H`s`st'.5gH "'EgMH`sZ``st(ls "'}``st)H "'H`s``s"s"" ""0""""" +"e"""4""")"t,#H + 'H`st. `qn+t/ z`qn+t0 `qn+t1 {`qn+t7\? st419~pqF~`t,>=0OY't5`t,J&q'`t,"""Et84H  +  'H`vt:a `qn+t;} z`qn+t< `qn+t= {`qn+tCG3G\? >w t@pq`t8>=0'tAee`t8J$&$?q'H`t8"+"w"tD H  + 'H`u}`stFH`tG +H`tH;H`tIsH`tJH`tKH`tL H`qn+tM6 H`q`+tN[ H`qn+tO H`qR+tP H`q`+tQ H`qn+tR H`qn+tS H5`q+tT Hj`q+t]\? vtW7?pqN`tD>=0Wa'tX`tDJ&q'H`tDtZ H "'   l`q&\t[ " ' ?H "' 6 ?\"""o""t^ + + H  + +  +'H`u}`vSt` `qn+ta H`q`+tb  H`q`+tc 9 `qn+td X `qn+te s !`qn+tf G`uN+tg G`uN+tm     \?  vtj ( 0 upq = u`t^>=0 F P'tk z    `t^J &  q'0`t^"G""tniA  + 'H`tp=`+tqr`+tr_`+ts`+ttl`+tu`+ tx/7wpq?w`tn>=0HR'tz "'`tnt{ "'`tnt| "'`tnt}3 "'3H`tn`tnt~8?Wk "'EWJl``tnt\c "'sx`!``tnt "'H``tntH "'H`H``tnt "' l``tnt&= "'+=0l``tntBIgs "'RgW`^!``tn"""?"z"""K"""O"""< tDtH E + Q'H`u}t\? vt$pq$`t>=0'"":t ޤ + 'H`tK`+t[cpqk`t>=0t~'""tH`]`t"tH`t]mj`t"RtH  + 'H`t],`tt H`+tgopq{`t>=0't(`Jʜ`'t'h.t``t>I*.`'g'ՀT"["b"i.(t=0x".?J."ttCC` K`t\>=0't(K`\>=0'ttt`t>I .(tw>J '`t''z.?=0MW('ty`t>NV`.(tI"w>JƜ`t''N."y?=0('t!,3`t>N=AV`H.(tIT\X"M(>Jjq`t''z.?I"M(=0('?=0('t ..``tJ#'.("ttTYq "'ch`vH`t\tH "'H`t`tt  "'\t "'``ttH "' H`t`tt!(ZH "'8Z@H`tM``tt_f "'pu``ttH "'H`t``t"" "Y""|""Z"""P"""0"z""%"o"t H  + 'H`st } }   \?  st$,qpq9q`t>=0BL'tv~`tJ&q'`t"""/t!!%H ! + !'H`u}`s`v`vS t# `qn+t$ + H`q`+t$> H`q+t$m H`q`+t$ `qn+t$ `qn+t$ !`qn+t% H5`q+t%; Hj`q+t%l G`uN+t% G`uN+t% `q+tǁ#####\? #vtā"?"G"pq"W"`t>=0"`"j'tŁ"""""`tJ"&""q'r`t""6"tȁ&&' & + &Ţ'H`tʁ'`+tˁ'!`+t΁'4'<'{pq'C'{`t>=0'L'V'tЁ''' "''''R`tn`t""N"tс((*H ( + ('H`tӁ)z (`+tԁ) H`+ tׁ) )()kpq)3)k`t>=0)<)F'tځ)))q "')))`)H`t\tہ)))H "')))H`t`tt܁***  "'* *\t݁***8 "'*&*8*+``ttށ*=*C*cH "'*M*c*TH`t`tt߁*h*n*H "'*~**H`t*``tt*** "'***``ttၓ***H "'***H`t*``t""c"" "C"""8"" t⁓+, .8H +ۤ + +'H`st䁓. H`t+t偓.0 H`t+t끓-----\? -st聓,l,t,pq,,`t>=0,,'t道,,-,-`tJ,&,,q'H`t"""Vt쁓//C1wH / + / 'H`st1L H`t+t1o H`t+t1 1 171#17\? 1.st///pq//`t>=0//'t/00[00[`tJ0 &0 0;q'H`t""^"t2R26kH 2S + 2_'H`t3UH`t3H`t3H`t3H`t4H`t4RH`7 +t4H`7t4H`u5H`7 u5;H`7u5uH`u5H`7u5H`7u6#H`u6PA `+u6^H`+u +223?pq33?`t>=033'""u 7F7|:8H 7G + 7S'H`vu 9 G`qn+u9 G`qn+u9 `qn+u9 H`qn+u: H`qn+u:5 `qn+u9^9^99{9\? 9w u778>pq88>`u >=088'u8C8K88`8`u J8l&8l8q'H`u ""F"u;;8<H ; + ; 'H`u;`+u;`+u;`+u<!`+u!;;;pq;;`u>=0;;'"D"u"<= ?H < + <'H`su$? `qn+u%?' G`qn+u&?C G`qn+u'?_ `qn+u(?~ `qn+u)? !`qn+u/>>>>>\? >su,=m=u=pq==`u">=0=='u-==>=>`u"J=&==q'`u""""Au0@w@B @x + @'H`u}`vu2B`:+u3B `q+u9ByByBBB\? Bvu6AA"AipqA1Ai`u0>=0A:AD'u7AnAvAAA`u0JA&AAq'`u0""H"u:CDuGH CɣC CD D DB DK + DW'H`quBF+F+FQF=FQ\? FHqu=DDE!pqDE!`u:>=0DD'u>E&E.EzE8Ez`u:JED&EDE_q'`u:u@FFG FG `JF"Fv '%FFu'`u:"Y"""YuCGHJ.H G + G'H`u}uEJ H I'e`q|+uKIIIII\? IvuHHpHxHpqHH`uC>=0HH'uIHHIHI`uCJH&HHq'i`uC""Z"uLK?K?H`]`:"uMK?K?H`uL]mj`:"uNK K4R5H K + + K'H`uM],`:uPLo H`+uSKKL.pqKL.`uN>=0KL 'uUL3L;L`(LBL``JLELE`'t'h.uZLLM>LM>L``:>ILL`'g'ՀL"KL"KL"KL.(uU=0LLM"K.?JM M,.M4"Kuau[MCMQMMTMMY`Mg K`:\>=0MtM~'ugNN Nb(NNbNK`\>=0N#N-'uVNgNrNNxN`:>IN~NN.(uUw>JNN`:'9'z.?=0NN('uWNNOOO`:>NOOV`O.(uUIO%O-O)"Ww>JO:OA`:'9'N.O`O\"Wy?=0OpOz('uXOOPzOPz`:>NOOV`O.(uUIOO׀O"(>JOO윣`:'9'z.?IPPP"(=0P P*('?=0PIPS('u\PPPPPP``:JPP.P"uZu^PPQq "'PQP`PH`:\u_QQ Q-H "'QQ-QH`:`:u`Q2Q7QE  "'Q<QE\uaQJQQQj "'QXQjQ]``:ubQoQvQH "'QQQH`:`:ucQQQH "'QQQ`:Q``:udQQQ "'QQQ``:ueQRR3H "'RR3RH`:R&``:""""""E""#""""t"""C"""6"uhSS1U S'H`u}ujU`+ukU/B`:+ulUJ `d>+umU`:+usTTUTU\? UvupSSSpqSS`uh>=0SS'uqSST8ST8`uhJT&TTq'`uh"""EutV|VYH`pUuwV q`Pu|VVVVVV`P\?uw" VpuyVVXCWX]`:>NWWC`:W3W)W .quwQ'=mIWB%WPWF"$`q>=Wk"$W&WWx"$`qGq?NWW]`:Wg`:IWWW"$(+B>JWX"?FX X7XK`:X+X!"$'RU>NXFXN`:XUXP" zIIXc!XpXh"7 `>=XX"X"7?JXX"uzXXYCXYX][\>=XX.quwb'=XX"ڂ'RRK""".u}Y Y1`H Y + + Y'H`P`T`\J=uYHq`Y'HugU]l`R gnl`R'ug]l`R gl`R'uh%0]l`R h@l`R'1uh2]l`R hl`R'3ui 4]l`R i'l`R'ui}5]l`Z il`Z'6ui7]l`Z jl`Z'8ujj<]l`R jl`R'=uj>]l`Z jl`Z'?ukR@]l`Z kml`Z'AukB]l`Z kl`Z'CulDD]l`Z lal`Z'EulF]l`Z ll`Z'Gum8H]l`Z mUl`Z'IumJ]l`Z ml`Z'KunL]l`R nAl`R'MunN]l`R nl`R'OuoP]l`R o l`R'Quop]l`R ol`R'Suo]l`R ol`R'upB]l`R p[l`R'upR]l`R pl`R'uq S]l`W q;l`W'TuqU]l`W ql`W'VurW]l`W r5l`W'Xur]l`R rl`R'urY]l`R sl`R'Zusg[]l`R sl`R'\us]]l`Z tl`Z'^utb_]l`Z tl`Z'`uta]l`Z tl`Z'buu\c]l`Z uyl`Z'duue]l`Z ul`Z'fuvPg]l`Z vml`Z'huvi]l`Z vl`Z'juwB]l`g w`l`g'yuwm]l`R wl`R'Zux#n]l`R x;l`R'uxo]l`R xl`R'puxq]l`R yl`R'ruyjs]l`R yl`R'+uy]l`R yl`R'uz>]l`R zXl`R'uzu]l`R zl`R'vu{w]l`R {/l`R'xu{y]l`R {l`R'1u{|]l`R |l`R'}u|Y~]l`R |sl`R'u|]l`R |l`R'u}1]l`R }Ol`R'u}]l`e }l`e'u~(]l`e ~Dl`e'u~]l`e ~l`e'u]l`e :l`e'u]l`R l`R'u ]l`R &l`R'u}]l`g l`g'u8 H 'H`v+u H`u}+uM`:+voo\? RTMuYYZ YZ Y`:`u}JY&YYYBB'GZ"[N-`u}uZ$Z,\Z:\ZB`:Z\`p+Zy`p +`u}>IZ"ZZ"(+ZZ"(+>=Z"5`nZn5[ZZ"NF1n҃"N?N[[@`[-[u[8"N[F[I[Y"![c[]"ϐ(+[[}[t[n"ϐ*ۃ!W('B>=["[[BsU>=["[vN\\ [\\ "ĵ\*"с\B"҂\\"J\p&\p\\\\w"b4\\\\l[`J\%\\"`u}`u}uÁ\\\\\`l5J\\u|.uā\]])L] ])],`PJ] ]q .v].]2]L]:]]IK],`P\>N]\]eL],`P]l.Lu=]]z" C=]]"]"<uŁ]]^d5]^d`:>N]] `M]MN^^ +H`u}&^^.)\`u}=^5^,^""ҀLQ^9"ҟ;J^F^W^M"ҀQuƁ^i^t_*^~_*`:>N^^ `M^MN^^H`u}&^^.)\`u}=^^^"JLQ^^"iLu=_V._c"R7v_r_b_b_`:_`p+_`p +`Nz>I___"ԍ(+>I` `` "}(+>=`*"}5`n`:n5[`Y`W"F1n҃"?=`s"ԍ`p`"}?N```:$a'Ha"m'HNa$a-`NzaEa@a7BsUaT"Q҂ai"ԍR6NaaI`NzaNNaaL`[b ba"}[Cb!b/b$b"[(+>=bLb@"ǣbXbS"[\Jbobv"v bbc?bc?b`:b`:\>=0bb'Iv +cDcId c[d cc`:cq`:c`p+c`p +\>=0cc'Iv dddd+dd3`:dB`P`P>=0dQd['Iuȁdde.qde`Ul>=0dd'Iuʁe ee,3e$e,`Je'*v e0e5e}6e:e}\>=0eCeM'Iv ff%ff3ff;`:`>NfJfLl`u}fRufa"Jfk"%ftfr"`u}!%ff"`u}`fvuffg(pqfg(`u}>=0fg'uɁIq`qJٜ`q'G'I.v "'\v( "'(\uˁWpx]l`RJ{{u.lú]l`RJu.lú ~ ]l`RJu.lu΁%>|O|]l`RJXlXu.luρ]l`RJu.luЁ  ]l`ZJu.luс.f<f]l`ZJEVEu.luҁk]l`RJu.luӁ]l`ZJu.luԁ J*J]l`ZJ-:-u.luՁOmy]l`ZJ||u.luց]l`ZJu.luׁ;;]l`ZJ+u.lu؁@^j]l`ZJm|mu.luف]l`ZJu.luځ//]l`RJ  u.luہ4MwWw]l`RJZgZu.lu܁|]l`RJu.lu݁b]l`RJu.luށC%C]l`RJ(3(u.lu߁Hai]l`RJlwlu.lu]l`RJu.luၓ]l`WJu.lu⁓$EqPq]l`WJSaSu.luこv]l`WJu.lu䁓]l`RJu.lu偓M*M]l`RJ-=-u.lu恓Rk|]l`RJu.lu灓]l`ZJu.lu聓S*S]l`ZJ3C3u.lu道Xv]l`ZJu.luꁓ]l`ZJu.lu끓 L+L]l`ZJ.<.u.lu쁓Qo{]l`ZJ~~u.lu큓]l`ZJu.lu CC]l`gJ#3#u.luHaTi]l`RJlwlu.lu]l`RJu.lu]l`RJu.lu/_<_]l`RJ?O?u.lud}]l`RJu.lu]l`RJu.lu//]l`RJu.lu4MuVu]l`RJYeYu.luz]l`RJu.lu]l`RJu.lu!K+K]l`RJ.;.u.luPir]l`RJuuu.lu]l`RJu.lu'']l`RJu.lu,JX]l`eJarau.lu]l`eJu.lu""]l`eJu.lv'E{R{]l`eJ[k[u.lv]l`RJu.lv]l`RJu.lv8^@^]l`gJCNCu.l"1"Ψ""]"Ѩ"L"""C"ց""k""#"["آ"B"َ"""T"ڪ""V"۬""X"ܮ""Z"ݰ""\"޲""^"ߴ" +"`"" "a"" "c"""e"""g"""i"""k"""m"""o"""q"""s"""u""!"w""#"yMv;fB < + H'I`s`s`v vI `+v I +`t+v6 `qn+vV `qn+vu `qn+v !`qn+v@ H5`q+vk Hj`q+vI `+v:\? sv`v>N`u}u'=ZPM"CQ''I nJs&sz"C`vv  pq `v>=0'v"I  "'`v#I "'`u}`u`v$3I "' 3`u}'`u`v%8ZqI 9'I "'hq`q&v&vI w'I "'`sv'I 'I "'`tnv(4I 'I "'+4`tv)9[rI :'I "'ir`tv*wI x'I "'`uv+I 'I "'`vv,0bI 'I "'LbTR`tn`vv-glI  "'w\v.I! "'\v/G "'`[v0r "'s`:`Pv18wI" ' ' "'HwN`u_I#`u}],`[v2|I$ }' ' "'`uI#`u}],`[v3I% "'\v4#(JI& "'6J;`\v5OSI' "'`eI(``v6I) "'\v7I* "'I+`\v8I, "'\""""4"""7""""k"""a""""Z""X"""&"_""v;{I- | + 'I.`svAjj\? sv> Zpq"Z`v;>=0+5'v?_gt`v;J&q'I/`v;"""gvBpI0 q + }'I1`u}`svD H5`q+vE Hj`q+vKrr\? vvHbpq*b`vB>=03='vIgo|`vBJ&q'`vB"("t"vLI2  + 'I3`vvR\? vvOpq`vL>=0'vP,,`vLJ&q'I4`vL"O""vSI5  +`vU G`uN+vV G`uN+vYS[pqb`vS>=0ku'"_"vZ.I6 Ĥ + Т'I7`sv\I8`v]I9`v^ I:`v_B I;`q`+v`h @`qn+vobb|\? s +vc]epqy`vZ>=0'vew{I< "'`t`vfI= "'`[vgI> "'I?``tvh +-I@ "'-I?``uvi26OIA "'FO`vjT[IB "'lqI?``[vkIC "'I?``tvlID "'I?`IE``[vm,IF "' ,I?`IE`\"""F""""\""#W# +vp 5IG  + + 'IH`vvv\? vvspq`vp>=0'vtDD`vpJ & (q'`vp#\##vw)II  + 'IJ`vZ`v +vyIK`vzIL`v{SIM`v|IN`v}IO`v~IP`v. 7`q`+vS IQ`q`+vt `qn+v `q+v\? vovpq`vw>=0'#|#vIR  + 'IS`vZv `qu+v `qu+v k`q+v `qu+v !`qu+vCCuau\? lvov:BpqZ`v>=0cm'## v!@>  + 'IT`u}v\? vv}pq`v>=0'v((`vJ& q'`v###0v-IU ߤ + 'IV` +vIW`vIX`vIY`vLIZ`7vyI[`7vI\`vI]`v l`+v R`tn+v+ `+vbjpqu`v>=0~'v49XI^ "'BXJR`tn\v]bI_ "'kpl`{G`G`\vI` "'U`V`\vIa "'l`\vIb "'l`\v+Ic "'+`!|`\#u## #s## # Z# vDDId`]`v# vDDIe`v]mj`v# +5v6If  + 'Ig`v],`vvÀ H`+v?pq?`v>=0'vDLq(Sq`JVV`'t'h.vÒåRçRì``v>Iùý`'g'Հ# e# e# e.(v=0"# e.?J4@.H# evvWehm`~ K`v\>=0ċĕ'v΁$((.3K`\>=0@J'vńŒŘ`v>IŞŮŧ.(vw>JŻœ`v'IU'z.?=0('v%*`v>N48V`?.(vIKSO# sw>J`g`v'IU'N.Ɖƅ# sy?=0ƙƣ('vǩǩ`v>NV`.(vI#4(>J`v'IU'z.?IAIE#4(=0OY('?=0xǂ('vǮǸ``vJ.#vvÁ 8q "'8`)H`v\vā=GkH "'Qk\H`v`vvŁpuȃ  "'zȃ\vƁȈȒȦIh "'ȝȦ`vvǁȫI Ȭ'I "'R`tn`vvȁ 9 "''9,``vvɁ>HlH "'Rl]H`v`vvʁq{ɰH "'ɋɰɖH`vɣ``vvˁɵɿ "'``vv́H "'H`v ``v# +# +# <# # _# # ?###9####V###J###Nvρ!fIi  + 'Ij`vсIk`vҁIl`vӁDIm`vց{˃pqˎ`v>=0˗ˡ'#,#xvׁA\'In B +`vف! `q+v܁͹pq`v>=0'##v݁-Io  + 'Ip`s`vv߁: `qn+vZ `qn+vၓy `qn+v⁓є !`qn+vこ `q+v道   \? sv恓ϤϬpqϸ`v>=0'v灓II`vJ&.q'!`v##`#vꁓҫxIq Ҭ + Ҹ'Ir`u}`s`vv쁓 H5`q+v큓C Hj`q+vlI `+vԯԯ\? vvV^ӣpqkӣ`v>=0t~'vӨӰӻ`vJ&q'`v###-vSn׺Is T +`v+It`v[Iu`v׋Iv`v׮I `+vpq`v>=0'##vؕIw ؖ + آ'Ix`u}`vwڂIy`wڰIz`wI{`wI|`wP I}`q+wۀ I~`q`+w۬ I`q`+w `q+w @@lXl\? cvw +=EُpqWُ`v>=0`j'#m#w I Ϥ + ۢ'I`u}wޣޣ\? vw݌ݔpqݺ`w >=0'#?#wI 'I`u}`sw\? vwpq`w>=0'# #Ww%I ֢'I`u}`vw\? vwwpq`w>=0'w**`wJ& q'I`w####v""u""u"" _"!"""#1"#"$"%8"%"&"'?"'"(")F")","-"."/"0"1"3O"6"9"<">"B"Ev"H"J"M-"O "P"R"T"W"Z6"\"^"`"cc"e"ht"k"m"q"s"t"u:"w`"x"z"|"~"""""V"" ""u"G""%"[""@""" "g"""""R""n"""$""V"?""O"x"""## +###A# # +# +>######>#)###d#q#w I +oNTBp;! C]\"*&w!ބI ߢ'I`ww#I`+w$ I`+w%I`+w&I`+w'I`+w*ltpw `w!>=0'w+DžӅ`w\][[[+`w!>I!#(+>N$.[0pHO#J_sw.}#ނ# ?Jw/#w.ʅކ@w @[\[`w!J`w!'I'I/# 8# w/DX1w ab[`w!Jtt`w!'I'I# w0!&RI "':REL`\w1W\I "'q|L`\w2I "'L``\w3LJ̇I "'L``\### o# #!,#!f#!#!#"w4وD ڢ'D`w6 t`+w7 (`+w8 I`+w9 I`+w=0pz'w=33\][[[`w4>Nω[pH##Jw@%##2w@7Jw ST\[`w4Jff`w4'D'I##wAbI "'b ``1I`KI`+\wBglI "'y6``I`I`+\wCȋԋI "'I```#"#"##d###$#$j#$wD؍V=I ٣ & 0'I`wwF`w4+wG I`w+wH`+wII`+wJI`+wK `w+wNɍю pw  `wD>=0'wO%-GBGT`wb\][[[+`wD>Ir!~v#&(+>N[pH#&JwR#%#&6?J1wS;#%wRKhw qr[{\[`wDJ`wD'I'I#&#&wSp1w p[`wDJ,,`wD'I'Ih#'wT; "'; + `+I`+%I`+\#%#%#&#&#'C#'wUI ; Df p'I`wwW I`+ wZ +Ppw P`wU>=0!+'w]`J`'g'Iw_ Uw%U][J++B[;[''.w`Z^Ip][[[>JypG.Iw wbwbIw  'I "'[wd +CC][JB['[''I.w[HP\`wUJbb`wU'I'IweĖIΖ`xx>Iۜ`'g'I.>J`xx'I'I.>JU\`xx'I'I.wfI.`+I`+I`+`x>N"[$['m$'I'I..I!#*(+>Jל`x'I'I#*.!#*-#*D#*Ih!l#*(+>J`x'I'I#*.#*#*I!#*(+>J07`x'I'Il#*.|#*>J`x'I'I#*.wc Iw  'I "'(I`P^`w4UB\+{^`NSB\+][wgII`^`w4UB\+^`NSB\+]`w4>I."!B2#,(+![M#,(+>Jl&ls.Iw #,#,‚#,wc]`w4?N]`w4Ϧ`w4=.Iw #,4  9 +K`w4`>=##-st,#-4;;<S`N`>IKUO#-(+>=rh#-sj'>=#-sj#-wcJნ#-su#(#(Y#(#(#)1#)r#)#)#*#, +#,#.h whȝI ɢ'I`wwj I`+wmQYpw o`wh>=0x'#.#/wnI 'I` wp I`w+wq I`w+wr I`w+ws `w+wt `w+wu I`w+wv; I`w+wwT I`w+wxm I`w+w{'npw 6n`wn>=0?I'w}uzI "'`!`"`I`I`I`\w~ġɡW "'ԡ`!`"`\#0"#0`#0#17w͢I ΢'I`RwI`+wI`:+wI`:+w `w+w I`+w. I`+wBJpw U`w>=0^h'wBaw  C' "'ij[|4`+`+`wwh "'I[+4`+`+\w]I]`w4`#`\>=5.w >#3K#3)S#37wwbgIs`w4`\>=.w #3#3w#2#2?#2#2#3r#3wI 'I`wt A`+w `+w `+wK`+w!epw -e`w>=06@'w̧I "'ߧ``ww0I "'0``ww5@xI "'\xaK`l|``ww}I "'K`|``ww˩ I "'ک c`|`I``wwCI "''C,K`7|``wwHSI "'fq],`}|`t``w#4q#4#4#5/#5|#5#6%#6r#6wI`]`:[#7!wzI {'I`wwepw -e`w>=06@'wjnw v~`:][[[JpG[''.#7wΫӬ+٬+ s][`:[\>=0'w05r5BrKK[`JU\U.w-4``qal][[[`Jgig#8(l#8aww|[`J!.w &#8`:w(+w[][[[J.w &#9Q`:ww11a`:[ˁK\\>N&2[([''2.CI)>Nbh[j[''}#9I`'g'#9J?=#9`:'9'#9pG +[''#9w6KP]`:>N\a],`:1k`:=s.4{{|+`:[\J#:#:;wJ#:wį]][[[>NЮ],][[[1][[[=.4+`:[\J#;X&#;][[[;wJ #;Xw"*M(1M`J44`'t'7.wR[q cq`Jfmf.(w(wvC`J!. ww `: K[\>=0'w jj `:) a[[>=0;E'wov|[`:>=0'wİɱ α\>=0'#7W#7#7#8A#8#92#9#:x#;%#;#<'#=0'wò˳߳`:.][[[`w>N +/[pH;#>JOkwu#>͂{#>wÁ:w :[.[`wJќ`w'I'I倴 #?Q,#?Z#>p#>#?-#?wāw`I x'I`wwƁP]l`R l`R'QwɁbpw *b`w>=03='wˁжI ѡ' "' `+\ẃ "i "'" `+\w΁'9^A^]y`RJDODwƭ.l#@#@A#@#@#A wρ;WE <'E`wс`+wҁ! .`:+wӁ5 G`:+wԁK `:+wՁb `:+wց A`b+wفpw Ƹ`w>=0'#A#BwځkTF l'F`Rw܁g4]l`R l`R'w݁ (`+w:pw :`w>=0 'wごʻIw  "'Ի``ww䁔S "' +.`:`ww恔+R4R]y`RJ7C7wܭ.l#B~#B#B#C;#Cw灔/XI 0'I`iw達/ `+wꁔI I`+w큔ǽϾ pw  `w>=0'wX]I "'nvK`:I`\#C#D/#Dyw|BI }'I`wwB ~`w+w@@Opw @@O`w>=0@ @*'w@T@\A@lA@~`w@K`:@\][[[+`w>I@!@@#E`(+>N@@[@pH@#E`JA A#wA-#ECA6#ERA<#E?JARAjwAt#ECA}#ERwAAB3w AB3A[AK[A\[`wJAAǜ`w'I'IB#FBB#FMB+#FWwB7BOB1w BXBBY[BbK[`wJBqBq`w'I'IB#FсB#F#D#E#F#F#GwCCDI C'I`wD@DHDpw D_D`w>=0DhDr'#Gk#GwEtEOI Eu'I`RxFX `+xF `wh+xF `wn+xF I`+xF M`:+xEEFIpw FFI`w>=0FF$'x +FFGI "'FG`w!x G GG9I "'G0G9`x$x G>GJG "'GVGGbI`GxI`GI``w4x GGGI "'GG`wDxGGHI "'GHHI`+`x4xH H4HgI "'HIHgHOI`+`x=xHlHHI "'HH`xFxHHHI "'HH`xQxHHHI "'HHHI`+`x]xIII9I "'I0I9`xhxI>IGIZI "'IQIZ`xxxI_III I`'I "'IIII],`II],``xxIIJ3I "'J +J3JJ`X~`xxJ8JXJ}J "'JtJ}`xxJJJJ "'JJJJ`Y`xxJJKJ "'JK`xxK KK,J "'K#K,`xxK1K>LSJKPLSK[],`KkJ],`K|\][[[+`x>IK!KK#M(+>NKK[KpHK#MJKK.Jw L#ML #MσL#N"x?JL'L..J w LD#MLJ#MxxLXLLJw  LY'J "'LLL],`LJ],`L\[`xxLMM=J w  Lա'J "'MM=M!],`M1J],``xxMBMVMI "'MkMMx.`+MI`+MI`+`xx MMMJ + "'MM`xx!NNN,J  "'N#N,`y x"N1NEOQINTOQN`I`N^`w4UB\+N^`NSB\+]`w4JNNB`w4N[''J .O&#PǁO1#PւOB#Px#OVO]O]OcO][JOiOiB[Oy[''J .#Hn#H#H#I4#I#I#J.#J}#J#J#KF#K#K#L;#L#L#M#MQ#M#N#O3#O#P!#P^#P#Qc#Qx$PqPTJJ Pr'J`wx&Sj Cz`w+x'S I`w+x(S J`w+x)S J`w+x*S`:+x-PPQDpw Q QD`x$>=0QQ'x.QIQQR\QaR\Qs`wQ\][[[+`x$>IQ!QQ#Sa(+>NQQ[QpHQ#SaJQRx1R#SRR#S?JR.RFx2RP#SRx1R`RxRw RRR[R\[`x$JRR`x$'J'JR#T1R#T<x2RRST1w SSTS[`x$JSS`x$'J'JSL#Tx3SSTHJ "'STHSJ``TJ``T3J``\#R#S)#T#T#T#UNx4U%U[X)J U&'J`wx7UUVpw UV`x4>=0UU'x8VVW)V,W)V>`wVL\][[[+`x4>IV\!VhV`#V$(+>NV}V[VpHV#V$JVVx;V#VV#V`?JVWx<W#Vx;W-WFWw WOWWP[WY\[`x4JWkWk`x4'J'JW#VW#Vx<WWX'1w WX'W[`x4JWW뜣`x4'J'JX#Wp#U#U#V#WB#Wx=YY>\#J Y'J`wx@YYYpw YY`x=>=0YY'xAYZ[Z[Z'`wZ5\][[[+`x=>IZE!ZQZI#X}(+>NZfZp[ZrpHZ#X}JZZxDZ#XnZ#X?JZ[xE[ +#XnxD[[5[w [>[[?[[H\[`x=J[T[T`x='J'J[#YM[#YXxE[[\!1w [\![[`x=J[[ᜣ`x='J'J\#Y#W#XE#Y#Y#ZxF\]"`&J \'J`wxH` e`w+xK]]]pw ]]`xF>=0]]'xL]]_^_^`w^%\][[[+`xF>I^5!^A^9#Z(+>N^V^`[^bpH^#ZJ^^xO^#Zނ^#[)?J^^xP^#ZxO__"_w _+__,[_5\[`xFJ_G_G`xF'J'J _#[_#[xP__`1w _`_[`xFJ__ʜ`xF'J'J!`#\9#Zi#Z#[#\ #\txQaa cJ" a'J"`wxSc`w4+xTc`+xWa|aapw aa`xQ>=0aa'xXaababa`wb\][[[+`xQ>Ib!b!b#]t(+>Nb6b@[bBpHba#]tJbqbx[b#]eb#]?Jbbx\b#]ex[bbcWw bcWb[c\[`xQJcc`xQ'J"'J#cF#^DcO#^Ox\c[cpc1w cyccz[`xQJcc`xQ'J"'J$c#^#\#]<#^#^#^x]ddgwJ% dȢ'J%`wx_gl J&`w+xbe:eBepw eMe`x]>=0eVe`'xceefefe`we\][[[+`x]>Ie!eׁe#_(+>Nee[epHf#_Jf'f8xffB#_ׂfK#`"?Jfafrxgf|#_xffffw fff[f\[`x]Jffœ`x]'J%'J'f#`f#`xgfggV1w ggVg[`x]Jg*g*`x]'J%'J(gN#a2#_b#_#`#a#amxhhRhzl7J) hS'J)`wxjk J*`w+xkk J+`w+xlk J,`w+xmk J-`+xnl J.`w+xol, e`w+xrhhi7pw hi7`xh>=0ii'xsi<iDjaiZjail`wiz\][[[+`xh>Ii!ii#b(+>Nii[ipHi#bJijxvj#bĂj#c?Jj-jKxwjU#bxvjejk w jk j[j\[`xhJjj`xh'J)'J/j#ck#cxwkk.k1w k7kk8[`xhJkJkJ`xh'J)'J0k#d#bO#b#cu#c#dZxxmm:oI m'J1`wxzo J`w+x}mmmpw mm`xx>=0mm'x~mmnmnn`wn\][[[+`xx>In !n,n$#eE(+>NnAnK[nMpHnl#eEJn|nxn#e6n#e?Jnnxn#e6xnnoIw noIn[o\[`xxJoo`xx'I'J2o8#foA#f xoMo]o1w ofoog[`xxJoyoy`xx'I'J3o#f#d#e #e#fc#fxppsJ4 p'J5`wxqqqdpw q,qd`x>=0q5q?'xqiqqrq~rq`wq\][[[`x>Nqq[qpHq#gJqqxr#gr#gxr#r8rw rArrB[rK\[`xJr]r]`x'J4'J6r#h0r#h;xrrsJ "'rsrJ``rJ``rJ``\#g#gf#h#h~#hxstvJ7 s'J7`wxv J`X~+xtttpw tt`x>=0tt'xttuu uu`wu,\][[[`x>Nu?uI[uKpHuj#iJuxuxu#iu#ixuuvvw uvvu[u\[`xJvv`x'J7'J8v_#javn#jl#iK#i#j3#jxwww{SJ9 wx'J9`wx{K `Y+xxxxwpw x?xw`x>=0xHxR'xx|xyxyx`wx\][[[+`x>Ix!xx#k(+>Nxy[ypHy%#kJy5y\xyf#kyo#k?Jyyxy#kxyyzw yzy[z\[`xJz z `x'J9'J:zq#ldz#loxzz{41w z{4z[`xJzzɜ`x'J9'J;{,#l#k#k\#l6#l#mx|.|Z~J< |/'J<`wx~ J`Y+x||}pw |}`x>=0||'x}$},}}F}}X`w}e\][[[`x>N}x}[}pH}#nJ}}x}#m}#n!x}~~w ~#~~$[~-\[`xJ~9~9`x'J<'J=~#n~#n#m#m#nj#nx`J> 'J>`RxP J?`w4+x=Epw b`x>=0ku'xyy`:.][[[`x>N/[pH#oJ2Ux_#oe#ox}9w 9[.[`xJœ`x'J>'J@#p`+#pk#oI#o#p2#px;`uJA <'JA`wxw (`+xpw `x>=0'x#+>?JB[gI`+{I`+`x>I""%#q`%#q`%#q`>Jx2#q`O#q`_#q`?Iv""%{#q][[[#q(+ׂ#q(+>N[pH!#q][[[JE`xj#r?=0'Gxw JB[I[%I[`xJ::`x'JA'JC#s(#s5#sBxh1w hJB[`xJ`x'JA'JDL#sxJE]`w4JB`w4͜[''JF.xsJG 's JH`][J66B[F[''JI.f#t#q#q\#r#s#s#t_#txP{JJ Q'JK`wxāK I`w+xŁg J`w+xƁ|`:+xɁ7pw 7`x>=0'xʁ<DIRId`wr\][[[+`x>I!#v(+>N[pH#vJx#u#vA?J3x=#ux́Mcw lm[v\[`xJ`x'JJ'JL#vՁ#vx΁51w 5[`xJ`x'JJ'JM-#wQxρJN "'JO`x\#u#u#v#w##w#wxЁ6JP 'JQ`wxҁbJR`+xӁyJS`+xԁJT`+xՁJU`:+xցJV`+xׁ JW`w+x؁ JX`w+xف$ JY`w+xځ<JZ`:+xہ^ `w+x܁} `w+x݁ I`w+xށJ[`+x߁J\`+x⁔3;pw G`x>=0PZ'xご`w\][[[+`x>I!ҁ#z(+>N[pH#zJ"4x>#yG#zB?J]oxy#yx恔w [\[`xJ`x'JP'J]#zց#zx灔Y1w Y[`xJ++`x'JP'J^Q#{Rx联I "'`!`"`\x達 4W "'4`$!`+"`\#y#y#z#{$#{#{#|Wxꁔ/J_ 'J_`x큔pw `x>=0'x`w\][[[+`x>I#!/'#}/(+>NDN[PpHo#}/Jx#} #}k?Jx#} x`w `[\[`xJ##`x'J_'J`O#}X#~ +xdx1w [`xJ`x'J_'Ja#~{#|#|#}#~M#~xWI 'Jb`wxJc]l`w l`w'Jdx .`+x>Fpw [`x>=0dn'x#WJe "'3WBJf^`RB[\xUJg+U]y`wJ4F4x.l#P###Jx2T0Jh 3'Jh`wy+ Ji`w+ypw `x>=0'y +"4`wB\][[[+`x>IR!^V#1(+>Ns}[pH#1Jy#"#m?Jy#"y!9w BC[L\[`xJ^^`x'Jh'Jj## y1w [`xJۜ`x'Jh'Jk #}####O#y +Jl 'Jl`wy Jm``+y Jn`:+ypw `y >=0'y`w\][[[+`y >I#!/'#(+>NDN[PpHo#Jy##?Jy#yjw  j[\[`y J))`y 'Jl'JoY#b#yn1w [`y J`y 'Jl'Jp##6##\##A##"=#$#'#.#/,#1L#3#6#7*#>#?#A"#B#C#D#G8#G#R-#Uk#W#Z#\#_#a#ds#f#h#j#m4#n#p#u#w#|x#~#_##Z&#\yJq +[pNTBp; /I"*6yJr + 'Js`yw K`:+y B`+y `+y!epy-e`y>=06@'##7y~7Jt 'Ju`y Jv`7y# (vpy>v`y>=0GQ'y%:Jw 'Jx "':` ``#Jy`\y&?lJz @'J{ "'```e`Jy`\y'Ӈ5J| ԡ'J} "'5`&G`\###;##y(;J~  + 'J`y+py`y(>=0'#a#y,ԋJ 'J`y.  y'`E+y/ J '`\+y2+3spy;s`y,>=0DN'##Yy3Œ鍞J â'J`y6JRpyd`y3>=0mw'##y7yZJ z'J`y9xJ`7y:J`7y;J`7y<-J`7y=iJ`7y>J`7y?J`7y@J`7yAYJ`7yBJ`7yCJ`7yD +J`7yEEJ`7yFJ`7yGJ`7yHJ`7yIDJ`7yJJ`7yKJ`7yLJ`7yMVJ`7yNJ`7yOJ`7yPJ`7yQbJ`7yRJ`7ySJ`7yT+J`7yW bpy*b`y7>=03='##9yX5}J 6'J`yZNJ`7y[J`7y\J`7y_8py8`yX>=0 '##y`ޚ(J ߢ'J`ybJ`7dyepy`y`>=0'#S#yf%#J 'J` +yhJ`7pyi'J`7ryjYJ`7tykJ`7vylJ`7xym J`7qynCJ`7syo|J`7yypJ`7uyqJ`7wytpy`yf>=0'##yuJJ 'J`ywJ`7yx^J`7yyJ`7yzJ`7y} pyѡ `yu>=0'##y~*J 'J`yJ`7y9J`7yuJ`7yJ`7ypy`y~>=0'##y㧬J 'J`yJ`7MyJ`7NyBJ`7OyJ`7LyMUpyp`y>=0y'#}#yaJ + 'J`RyR J`:+y [py#[`y>=0,6'y`h^t^|`:J][[[+`y>I!#(+>NJ[pH#Jy#r#?J7KyU#rybvy[J[`yJ`y'J'J΀#,#5yߪ@1y@[`yJ  `y'J'Jπ;###S##q#y<~J ='J`yIJ`7FyJ`7Ey3py3`y>=0'#B#yzJ {'J`y\py$\`y>=0-7'yahJ "'J`|`:###8ytJ u'J`ylJ`7yVpyV`y>=0'1'##yiJ j'J`yGpyG`y>=0"'yLoJ M'J "' ],`\##C#yvJ w'J`yOJ`7yJ`7CyJ`7ByJ`7@y9py9`y>=0 +'#;#yyJ 'J`yJ`7yJ`7yÁqypy`y>=0'##%yāJ 'J`yǁs{py`y>=0'#]#yȁλJ 'J`yˁ6>pyW`y>=0`j'##ýlA1J m'J`y΁fJ`7eyρJ`7yЁJ`7dyсJ`7gyҁ3J`7fyӁbJ`7(yԁJ`7 yׁPpyP`y>=0!+'yف̿J 'J "'ٿc``|4\yځ0GJ 'J "'>G`|4yہLmJ M'J "'{`|4\y܁J 'J "'ſc`\y݁ݿ@&J ޡ'J "'@@&@ c`@K``yށ@+@Q@K @,'K "'@b@@q`|4@|K``y߁@@@K @'K "'@@@`|4`y@@A/K @ס'K "'AA/A`|4A!c`\##F###(#r##F## yၕB B9DK B 'K`yさCJ`7y䁕CGJ`7dy偕C|J`7(y恕CJ`7y違BBCpyBC`y>=0BB'y끕CCDK Cǡ'K "'CDC`z7D c`\##)#y쁕DE!EK  D'K +`yE~EEpyEE`y>=0EE'## yFFGK  F'K `yGIGQGpyGfG`y>=0GoGy'#`#yH{HJK  H|'K`yIK`7yIK`7yI3I;IpyIXI`y>=0IaIk'#&#ryJKKK J + J'K`yKmKuKpyKK`y>=0KK'## yLLNK L'K`zM)M1MpyMHM`y>=0MQM['zMMNKMNMc`MK`MK`MK`+M(`+][JNNB[N[''K.NU#N]#ЂNl#Nu#N##I##nzOeOPK Of'K`zPPP]pyP%P]`z>=0P.P8'z +PbPgP{K "'PrP{\z PPPK "'PP\###7#pz QyQRpK Qz'K`zRR!RnpyR6Rn`z >=0R?RI'##zSKSTK  SL'K!`zTaK"`7zSSTKpyTTK`z>=0TT&'#a#zUjUVPK# Uk'K$`zUVVNpyVVN`z>=0VV)'##9zW+WkX*K% W,'K&`zWWX(pyWX(`z>=0WX'#y#zYYAZ)K' Y'K(`z ZK)`7az#YYYpyYY`z>=0YY'#"#nz$[[M\K* ['K+`z'[[\py[\`z$>=0[['##z(\]-_K, \'K-`z*]K.`7z-]]]py]]`z(>=0]]'z/^$^I^K/ ^%'K0 "'^X^^nK1`|D\z0^^^K2 ^'K3 "'^^`|Dz1^__=K4 ^ݡ'K5 "'__=_*K1`|D\z2_B_e_K6 _C'K7 "'_r__K1`|D`#W###J##z3`x`aEK8 `y + `'K9`z6`aaCpya aC`z3>=0aa'#]#z7b b<bQ b!'K:`z:bbbpybb`z7>=0bb'##3z;ccdK; c + câ'K<`z>dBdJdpydXd`z;>=0dadk'#~#z?eme0H ene ee eŤ + eѢ'K=``EzAgu `E+zBg K>`+zCg K?`+zFfzffpyff`z?>=0ff'zHgg!g\g+g\`Jg.g.`'g'K@zJgghKA "'ghgKB`\zKhhhKKC "'h$hKh-KD`z3h=J`|\zLhPhUhKE "'hghhpKD`z3h}`hK`:\zMhhhKF "'hhhc`h`y(\zNhhiKG "'hihc`hKH`y\zOiiiZKI "'i,iZi1c`iFKJ`z;\zPi_idiKK "'ioiitc`iKB`|+\zQiiiKL "'iiiP`iQ`iS`i`\zRiiiKM "'iii`\zSjj jAKN "'jjAj#KO`j0KP`\zTjFjKjuKQ "'jTjujYKR`jfKS`\zUjzjjKT "'jjjKU`jKV`jKW`jKX`\zVjjkKY "'jkjc`jKZ[k`\zWkkkMK[ "'k(kMk-c`k9e`kA[\zXkRkVkK\ "'klkkqc``zYkkk  "'kkk0`\zZkkkK] "'kkkP`kQ`kS`k`\z[kkl K^ "'kl k`\z\lll-K_ "'ll-l$`\z]l2l7ltK` "'l@ltlFP`lPQ`l\S`lg`\z^lyllll][JllB[l[''.z_lllKa "'lllJ`|\z`llmmKb "'mmmmc`mR`mKc`m8`mC`mO`ma`\zamrmwmKd "'mmmc`mR`mKe`mKf`m`m`m`m`\zbnn nKg "'nnnc`n(R`n3Kc`nG`nN!`n[`nf`nr`\zcnnnKh "'nnnc`nR`nKe`nKf`n`n!`n`n`\zdoo +o "'oo`y(zeo$o0oJKi "'oAoJ`yzfoOoWomKj "'odom`z3zgorooKk "'oo`z;zhoooKl "'ooo``|zioooKm "'oo`|+zjoop Kn "'op o`\zkppp5Ko "'pp5p'`y(\zlp:p?ppKp "'pPppp]KH`y\zmpupzpKq "'pppKD`z3\znpppKr "'pppKJ`z;\zoppq Ks "'pq pJ`|\zpqqq8Kt "'q q8q)KB`|+\zqq=qBq\Ku "'qKq\qPKv`\zrqaqfqKw "'qoqqu`\zsqqqKx "'qqqKy`qKz`\ztqqqK{ "'qqqKD`z3qJ`|\zuqqr' "'qrr`\zvrrrCK| "'r1rCr6`\zwrHrMr~K} "'rWr~r\`rf`rq`\zxrrrK~ "'rrr`r`r`re`\zyrrr) "'rrr`\zzrrsK "'sss `\z{ss#s2< "'s)s2\z|s7s<sJ "'sAsJ\z}sOsTsK "'sksspc`s|K`sK`sKJ`z;\z~sst9K "'st9sc`sK`tK`tKB`|+t,R`\zt>tCt]K "'tLt]tQ`\ztbtgtK "'tuttzc`\ztttK "'tttKD`z3t``yzttu K "'tu tKD`z3u``yzuuuIK "'u1uIu:KD`z3],`|zuNuRuK "'ucuulKD`z3u|K`:`zuuuK u'D u'D "'uuuc`uK``zuv vR u'Kv4v][[[>Jv=vDpGvc.SyzzvvvSy v'R v'K "'vv[zvvwK "'vw`zw ww3K "'ww3w'K`:`zw8wwK w9'K we'K "'wwwc`wK`wK``zwyy7B w'K x'K "'y%y7y*K``zy<yCylK "'yTyly]KD`z3`:zyqyyK yr'K y'K "'yyyKD`z3yK``zyz zVK y'D z'D "'z8zVz=c`zIK``zz[zbzK "'zrzzzJ`|`:zzzzK z'K z'K "'zzzJ`|zK``z{{{cK "'{2{c{>K`{NK``|z{h{o{K "'{~{{J`|`:z{{{K "'{{],`:z{{|,K {ˡ'D {'D "'||,|c`|K``z|1}}RK |2'K |'K "'} }R})KD`z3}B`|<`z}W}g}K "'}y}}KD`z3}K`:`|<z}~~@K }'K }١'K "'~#~@~(`~3K``z~E~I~{K "'~^~{~c`~nK``z~~~ "'~~~c`~`\z~~~K "'~~~`y(`z~~~Z "'~~`z~~K "'``zHK "'(H5KH`y`zMRsK "'[sdKD`z3`zx}K "'KJ`z;`zK "'J`|`zK "'KB`|+`z +%( "'%`\z*/RK "':RCKD`z3\zW\K "'glK`w`\zK "'``\z@Ky 'K "'@`!`````2K`\zEJK "']ic`uKc```\zK "'K`K`\zK "'`!```\z QK "',Q4J`|C3`:\zV[K "'fkKv`ub`~0`\zK "'K`Kv`b`0`\zK "'0`\z3K "'3K`'0`\z8=mK "'FmKK`UK``K`\zrwK "'K`K`K`K`\zMKM  c`R`Kc`K`1K`GK[`+`+K`+\>I""!ʇ# (+!#(+%/#`>=@.Ky Y#Ӟk#ӭ|#ӻ#̄##` ## /#zJ>?IP"""%U#`VF#(+ć# (+#(+>NK[pF'#`VF=f.Kyt#Ӟ|#ӭ#ӻ#̄##c zJ?I"""%)#`VTLE#(+d_# (+~w#(+>=.Ky#Ӟ#ӭ#ӻ#̄##`VTzJY?Ik"""%p#`E׆#(+# (+ #(+>=.Ky3#ӞE#ӭV#ӻp#̄##`EzJ?I"""%>#`glaZ#(+yt# (+#(+>=.Ky#Ӟ#ӭ#ӻ#̄#/#`glzJn?I"""%ȅ#`V##(+# (+#(+>=-.KyF#ӞX#ӭi#ӻ#̄##`V#zJ?=0 'GzRoKy S'K "'| }c[R[Kc[[[`[[K`\zSKy 'K "'Sc[R[!Kc[1[9[?K[\zWtKy X'K "'c[R[Kc[[[q`VT\zOKy ա'K "'Oc[R[Kc[%[-[A`E\zSpKy T'K "'}c[R[Kc[[[`gl\zIKy ѡ'K "'Ic[ +R[Kc[![)[;`V#\zNSK "'`ec`qK`|`\zK "'c`K``\zK  c`R`Ke`"Kf`5K`PK`fK[`+K`+\>I"!ׇ#(+%"#`>=3.Ky O#ݧa#ݶr#ă#Մ###`##%zJ.?I@""%|E#`VF#(+#%(+>NK[pF#`VF=<.KyM#ݧU#ݶ\#ăe#Մn###8 zJ?I""%#`VT% #(+?8#%(+>=P.Kyl#ݧ~#ݶ#ă#Մ###`VTzJ)?I;""%@#`E#(+#%(+>=.Ky#ݧ#ݶ#ă"#Մ5#P#j#`EzJ?I""%#`gl$#(+>7#%(+>=O.Kyk#ݧ}#ݶ#ă#Մ###`glzJ(?I:""%?#`V##(+#%(+>=.Ky#ݧ#ݶ #ă#Մ2#M#g#`V#zJ?=0'Gz!Ky 'K "'1 2c[:R[AKe[JKf[S[Z[l`t[K`\z +Ky 'K "' +c[R[Ke[Kf[[[K[\z.Ky 'K "'>Fc[NR[UKe[^Kf[g[o[q`VT\zKy 'K "'c[R[Ke[Kf[[[`E\z9Ky 'K "'IQc[YR[`Ke[iKf[r[z[`gl\zKy 'K "'c[R[Ke[Kf[[[`V#\z$)ZK "'2ZC`|<Q`\zÁ_dK "'n`|<[\zāK "'`|<`\zŁK "'`|<[\zƁ +GK "'G)`|<7`>!`\zǁLQK "'[l`|<v[\zȁK "'`|<`!`\zɁK "'`|<[\zʁBK "' B`|<+`2!`9"`\zˁGLzK "'Vzg`|<q[\źK "'`|<`!`"`\źK "'`|<[\z΁KK "'K`|<-`4!`;"`B`\zρPUK "'_p`|<z[\zЁK "'`|<`!`"``\zс K "' `|<[\zҁ]K "'%]6`|<EK`PL[\zӁbgK "'w`|<K`L[\zԁK "'`|<K`L[\zՁ -K "'-KD`z3\zց27^K "'F^OKD`z3\zׁchK "'v{K``\z؁K "'K`[\zفK "'K``!`\zځ)K "')K`[\zہ.3gK "'AgFK`P`W!`^"`\z܁lqK "'K`[\z݁K "'K``!`"``\zށK "'K`[\z߁K "'-2K`<B`F`QK`gK`se`\zK "'`!```\zၕgKg`!```` `K`\>=-.Ky9#<#?#F#ńN#ԅV#\#zz⁕bTK c'KTK`K`K```[\>=.K##-#=#̈́E#܅K#zzさK 'K K`K`-K`G`R`^`j`v``\>=.K #####ą#ӆ###zz䁕K 'K!K`4K`GL`ZL`g`s`y[\>=.K##ǂ#؃### #zz偕;cL <'Ku + + +K`K`L`L````` `6`\>=B.K P#_#ɂn#ڃw### #)#8#G zz恕gL 'Lgc`-`7`\>=D.KYO#W#]#zVz灕.L 'L.c`e``\>=.K[##%#zW###!#k##-###6###L#####E###L###Q####E######`###&#n###J###(#r###p###d###g###P##!#i####w##L#ù##O#Ě#(#Ŗ##c##*#ǩ##V#ș##ɏ##h###f#ˡ##;#̉##%#s#͹##\#γ#i##9#Ю##o##0#҉##r###[##ۃ##ܫ##{##e###F####2###B###N#####b##9###T###L###b##.## #^##l#\#D#x#z##]#z聕 3_I 'L``~`~zꁕA `y,+z끕# K>`+z쁕$ K?`+&z/py/`z>=0 +'zrwL "'c``z7\zL  "'L +`\z L  "' c```y(\z%*L  "'9Ec`Q`_`y(ke`wB`\zL  "'`L`|\zL "'c`L`|8\z GK/ "'!G4L`|@\zLQL "'` + + +eL`pL`{L`L`L`L`L`L`0` `\z\L 'KY "'\ c`L`,`7L`M(`+\zaL b'K[ "'c`L`L`L`(`+\zDL  "' D`L!`*`5`\zINL" "'[``lL!`xK[L`+\zL# "'`L!`K[L`+\zAL$ "'A`L!`K[)L`+\zFJL% "'X^i`|'hL&`s``{\L' 'Kb "'\  c`R`Kc````"`,L`BL(`+\{aL) b'Kb "'c`R`Kc````L*`e`\{L+ "'1 + +6c`BR`MKc`g`r`~```L`+L(`+\{L, ۡ'L+ "' "c`4R`EKc`_`p```L*`e`\{L- Ρ'Kd "' + +c` R`+Ke`8Kf`K`V`b`t`~L`L(`+\{qL. 'Kd "'q c`R`Ke`Kf`1`<`H`TL*`ce`\{v{IL/ "'I + c`R`Ke`Kf`L0`````` L`+/L(`+\{NxaL1 O'L/ "'a c`R`Ke`Kf`L0`` ``,`>L*`Se`\{fkL2 "'|L3`L4`L5`L6`B`\{ `L7 "'` c`R` Ke`Kf`,L0`9`@!`G`R`\{ +ekL8 "'v`z7{ L9 "'`|{ L: "'`|8{ +K2 "' +`|@{3L; "'3&`z7\{8=bL< "'JbSL`|\{gl "'v|i`|'\{L= "'L`|8\{ K4 "' L`|@\{jL> "'*j/`9`D`OL?`\{otL@ "' ],`\{LA "'```e`L?`\{ lLB "'l+`5`@y`I`T`^e`\{qv‘LC "'~‘ƒc`\{–›¸LD "'¯¸\{½LE "'`L&``|'{^LF "' ^c`%K`9KB`|+FR`Q`\{cjøLG "'ÃøÌKD`z3ÙLH``:{ý#LI "'#KD`z3LH`K``{(/ăLJ "'@ăIKD`z3\LK],`pK``{ĈčLL "'ĝĢc`ĮK`K`K`+(`+\{:LM "':KD`z3.K`:`{ ?FwLN "'Yw^c`j``{!|ŃLO "'ŝŢc`ŮKc`K``{"LP "'c`K``{# CLQ "'$C+`z76K``{$HOƅLR "'bƅkL`|xK``{%ƊƑƾLS "'ơƾƧi`|'ƱK``{& LT "' KD`z3``y{'ZLU "')Z2KD`z3BLV`:`{(_i.LWz.ǃKD`z3ǙLX],`:],`>NDzLY],[pI$eJ.LZy$T${*{*3\țLZy 4'LW "'pțyKD`z3ȇLX],[],`{XȠȥL[ "'Ⱥȿc`L\],`\{Y[L] "'[ c`L\],`.`5!`B`M`\{Z`eɀL^ "'lɀs`z7`{[ɅɊɫL_ "'ɓɫɜL`|`{\ɰɵL` "'ɻi`|'`{] La "' L`|8`{^JK6 "'$J7L`|@`{_OTsLb "'js\{`x}ʘLc "'ʇʘʌ`\{aʝʺ4Ld ʞ'K "'4`!`````Le[%e`+\{b9>˭Lf "'\˭ac`mLg`ˀKc`˔`˟`\{c˲˷Lh "'\{d Li "' L`|K``\{e%*iLj "';iDL`|QK`\`\{fnsئLk~ئ + +̊c`̜R`̭Kc``````Ll[fL`+\>Ix"%}$X`$e (+>=.Lmy $߁#$4$N$ _$q$+΃$:Ε$IΥ$X`{+J?I"%P$X`VFsi$e (+>NψϏ[ϑpFϺ$X`VF=.Lny $߁$ $0$ 7$?$+Q$:Y$I_$c +{,Jn?IЀ"%Ѕ$X`VT$e (+>=.Loy "$߁4$E$_$ p$т$+є$:Ѧ$IѶ$X`VT{-J?I"%a$X`E҈~$e (+>=ҙ.Lpy ҳ$߁$$$ $$+%$:7$IG$X`E{.Jӏ?Iӡ"%Ӧ$X`gl$e (+>=).Lqy C$߁U$f$Ԁ$ ԑ$ԣ$+Ե$:$I$X`gl{/J?I1"%Ղ6$X`V#է՝$e (+>=ո.Lry $߁$$$ $2$+D$:V$If$X`V#{0J֮?I"!$e (+%.$X`>=E.Lsy + +_$߁q$ׂ$ל$ ׭$׿$+$:$I$X`>$e {1JP?=0bl'G{+ث3Lmy ج'K "'3 c[R[Kc[[[[[[%e`\{,7TٹLny 8'K "'bٹ cc[kR[rKc[ق[ى[ّ[ٟ[٧[٭[\{-ٽMLoy پ'K "'M c[R[Kc[[[[%[-[@q`VT\{.QnLpy R'K "'| }c[څR[ڌKc[ڜ[ڣ[ګ[ڹ[[`E\{/wLqy 'K "'w c[R["Kc[2[9[A[O[W[j`gl\{0{ۘ Lry |'K "'ۦ ۧc[ۯR[۶Kc[[[[[[`V#\{1,ܩLsy 'K "':ܩ + + +;c[CR[JKc[Z[a[i[w[[܏L`ܘL[\{gܮܳRLtܽR + c`R`Kc```)`:`L`^`jLu[ݵL`+\> I"%$(3 `4*$(@ +(+>=E.Lvy + +^$'p$'ށ$'ȃޛ$'لެ$'޾$'$($($($$(3 `{2JJ?I\"%߬a$(3 `VF$(@ +(+>N[pF$(3 `VF=].Lwy + +k$'s$'z$'ȃ$'ل$'$'$($($($$)I {3J?I"%1$(3 `VTWM$(@ +(+>=h.Lxy + +$'$'$'ȃ$'ل$'$'$($($($&$(3 `VT{4Jm?I"%$(3 `E$(@ +(+>=.Lyy + + $'2$'C$'ȃ]$'لn$'$'$($($($$(3 `E{5J ?I"%n#$(3 `gl$(@ +(+>=.Lzy + +$'$'$'ȃ$'ل $'$'/$(A$(S$($c$(3 `gl{6J?I"% $(3 `V#1'$(@ +(+>=B.L{y + +[$'m$'~$'ȃ$'ل$'$'$($($($$(3 `V#{7JG?IY""%^$(3 `$(3 (+6,$(@ +(+>=G.L|y + +`$'r$'$'ȃ$'ل$'$'$($($($&$(3 `{8JL?I^"!lb$(@ +(+%$(3 `>=.L}y $' $'$'ȃ8$'لI$'[$'l$(~$($($$(3 `$(@ +{9J?=0'G{2WtLvy X'Lt "' + + +c[R[Kc[[[[[[[e`\{3qLwy 'Lt "'q + + +c[R[#Kc[3[:[B[O[W[_[e[\{4u Lxy v'Lt "' + + +c[R[Kc[[[[[[[q`VT\{5,Lyy 'Lt "'9 + + +:c[BR[IKc[Y[`[h[u[}[[`E\{6ALzy 'Lt "'A + + +c[R[Kc[[[[[[![4`gl\{7EbL{y F'Lt "'o + + +pc[xR[Kc[[[[[[[`V#\{8sL|y 'Lt "' s + + + +c[R[Kc[)[0[8[E[M[U[eK`\{9wL}y x'Lt "' c[R[Kc[[[[[[[K`L[\{h }L~ "',}8c`DL`PKc`d`o`\{iL "'c`L`Kc````\{jL + +c`$R`5Ke`HKf`[`l`~``Ll[L`+\>I"%K$6Q`h^$6^ (+>=y.Ly $5ց$5$5$6$6$6$$63$6B$$6Q`{:Jl?I~"%$6Q`VF$6^ (+>N[pF9$6Q`VF=.Ly $5ց$5$5$6$6$6$$63$6B$7\ +{;J?I"%N$6Q`VTtj$6^ (+>=.Ly $5ց$5$5$6$6$6$$63 $6B0$6Q`VT{=.Ly 0$5ցB$5S$5f$6y$6$6$$63$6B$6Q`E{=J?I"%i$6Q`gl$6^ (+>=.Ly $5ց$5$5$6$6$6$)$63;$6BK$6Q`gl{>J?I"%$6Q`V#$6^ (+>=,.Ly I$5ց[$5l$5$6$6$6$$63$6B$6Q`V#{?J?I1"!?5$6^ (+%S$6Q`>=.Ly + +$5ց$5$5 $6$6-$6$?$63Q$6Ba$6Q`$6^ {@J?=0'G{:9Ly 'K "'J Kc[SR[ZKe[cKf[l[s[{[[e`\{;'Ly 'K "'' c[R[Ke[Kf[[[[[[\{<+KLy ,'K "'\ ]c[eR[lKe[uKf[~[[[[q`VT\{=QLy 'K "'Q c[R[Ke[ Kf[[[![/[C`E\{>UuLy V'K "' c[R[Ke[Kf[[[[[`gl\{? yLy 'K "'y c[#R[*Ke[3Kf[<[C[K[Y[k`V#\{@}Ly ~'K "' + + +c[R[Ke[Kf[[[[[L`L[\{k!L. :c`LR`]Ke`pKf`L0``````Lu[3L`+\> IE"%J$AM +`$AZ (+>=.Ly $@$@$@σ$@($@;$AL$A^$A o$A/$A> $AM +`{AJ?I"%:$AM +`VF]S$AZ (+>Nry[{pF$AM +`VF=.Ly $@$@ $@σ$@$@&$A-$A?$A F$A/N$A> T$Bn {BJc?Iu"%z$AM +`VT$AZ (+>=.Ly $@*$@;$@σN$@a$@t$A$A$A $A/$A> $AM +`VT{CJ?I#"%s($AM +`E$AZ (+>=.Ly $@$@$@σ$@$@#$A4$AF$A W$A/i$A> y$AM +`E{DJ?I"% "$AM +`gl H >$AZ (+>= Y.Ly  u$@ $@ $@σ $@ $@ $A $A $A  +$A/ +$A>  +'$AM +`gl{EJ +n?I +"% + +$AM +`V# + +$AZ (+>= .Ly  "$@ 4$@ E$@σ X$@ k$@ ~$A $A $A  $A/ $A>  $AM +`V#{FJ ?I -"% } 2$AM +`  $AZ (+>= .Ly  $@ $@ $@σ $@ $@ )$A :$A L$A  ]$A/ o$A>  $AM +`{GJ ?I "!  $AZ (+%E $AM +`>=\.Ly x$@$@$@σ$@$@$A$A$A $A/$A> *$AM +`t$AZ {HJ?=0'G{AxLy 'L "'x c[R[!Ke[*Kf[3L0[<[C[Q[X[`[je`\{B| Ly }'L "' c[R[Ke[Kf[L0[[[[[[[\{C1Ly 'L "'A Bc[JR[QKe[ZKf[cL0[l[s[[[[q`VT\{DULy 'L "'U c[R[Ke[Kf[L0[[[$[+[3[G`E\{EYyLy Z'L "' c[R[Ke[Kf[L0[[[[[[`gl\{FLy 'L "', -c[5R[<Ke[EKf[NL0[W[^[l[s[{[`V#\{G<Ly 'L "'< c[R[Ke[Kf[L0[[[[[[.K`\{H@`Ly A'L "'p qc[yR[Ke[Kf[L0[[[[[[K`L[\{lL KD`z31L],`:?L`\>NVaL],[cpI$N=.Ly$N$N$N{IJ{IeLy 'L "',e5KD`z3CL],[ML[\{mjL k'K "'`|<[L`L`+\{nSL 'K "' S`|<$[+L`;L`+\{oX]L "'gx`|<L`\{pL "'`|<[L`+L`+\{qfL 'K "'f-`|<7[>L`NL`+\{rkL l'K "'`|<[L`L`+\{s"L "'"`|<L` `\{t',L "'7H`|<R[ZL`+iL`+\{uL 'K "'`|<[L`L`+\{voL 'K "'%o6`|<@[GL`WL`+\{wtyL "'`|<L` ``\{xL "'`|<[L`+L`+\{y =L !'K "'HY`|<c[jL`zL`+\{z L 'K "' `|<[L`L`+\{{dL "'d.`|<<L`D `L`TL`\{|inL "'y`|<[L`+L`+\{}/L "'/KD`z3LH`L`\{~4WL 5'K "'h`|<K`L[L`L`+\{GL "'G`|< K`K[&L`+5L`+\{LQL "'ct`|<K`K[L`+L`+\{_L ǡ'K "'_`|<!K`,L[7L`ML`+\{diL "'{`|<K`K[L`+L`+\{ SL "' S `|< K` K[ 2L`+ AL`+\{ X { L  Y'K "'   `|< K` L[ L` L`+\{  !kL "'! !k!`|<!-K`!8K[!JL`+!YL`+\{!p!u!L "'!!!`|<!K`!K[!L`+!L`+\{!!"!L "'""!"`"G`\{"&"+"hL "'":"h"?`"J`"Q!`"X"`"_`\{"m"r"L "'"""`"[\{"""L "'"""`"`"!`""`"`\{""#L "'"#"`#[\{###rL "'#-#r#9`#DB`#N`#XK`#de`\{#w#|#L "'###i`|'#L&`#`\{$$ $AKA "'$-$A$2KB`\{$F$K$~KC "'$W$~$`KD`z3$pJ`|\{$$$KE "'$$$KD`z3$`$K`:\{$$%KF "'$%$c`$`y(\{%% +%EKG "'%%E%c`%2KH`y\{%J%O%KI "'%_%%dc`%yKJ`z;\{%%%KK "'%%%c`%KB`|+\{%%& +KL "'%& +%P`%Q`%S`%`\{&&&2KM "'&!&2&&`\{&7&<&tKN "'&Q&t&VKO`&cKP`\{&y&~&KQ "'&&&KR`&KS`\{&&'KT "'&'&KU`&KV`&KW`&KX`\{' ''DKY "'''D'c`'%KZ['7`\{'I'N'K[ "''[''`c`'le`'t[\{'''K\ "''''c``{'''  "''''0`\{''(K] "''('P`'Q`'S`( `\{(( (<K^ "'(*(<(/`\{(A(F(`K_ "'(R(`(W`\{(e(j(K` "'(s((yP`(Q`(S`(`\{(((((][J((B[(Ϝ[''.{(()Ka "'))) J`|\{))!)Kb "')5)):c`)FR`)QKc`)k`)v`)`)`\{))*2Kd "')*2)c`)R`)Ke`)Kf`)`*`*`*&`\{*7*<*Kg "'*J**Oc`*[R`*fKc`*z`*!`*`*`*`\{**+1Kh "'*+1*c`*R`*Ke`*Kf`+`+!`+`+#`\{+6+=+R "'+I+R`y({+W+c+}Ki "'+t+}`y{+++Kj "'++`z3{+++Kk "'++`z;{+++Kl "'+++``|{+,,Km "',,`|+{,,#,<Kn "',+,<,0`\{,A,F,hKo "',R,h,Z`y(\{,m,r,Kp "',,,KH`y\{,,,Kq "',,,KD`z3\{,,-Kr "',-,KJ`z;\{---<Ks "'-&-<-.J`|\{-A-F-kKt "'-S-k-\KB`|+\{-p-u-Ku "'-~--Kv`\{---Kw "'---`\{---Kx "'---Ky`-Kz`\{--.!K{ "'-.!.KD`z3.J`|\{.&.+.B' "'.2.B.7`\{.G.L.vK| "'.d.v.i`\{.{..K} "'...`.`.`\{...K~ "'...`.`.`.e`\{.//) "'/ //`\{//#/LK "'/:/L/?`\{/Q/V/e< "'/\/e\{/j/o/} "'/t/}\{///K "'///c`/K`/K`/KJ`z;\{/00lK "'00l0c`0)K`09K`0RKB`|+0_R`\{Á0q0v0K "'000`\{ā000K "'000c`\{Ł000K "'000KD`z30``y{Ɓ11 1@K "'11@1&KD`z313``y{ǁ1E1R1|K "'1d1|1mKD`z3],`|{ȁ111K "'111KD`z31K`:`{Ɂ111K "'111c`1K``{ʁ122aR22a][[[>J22$pG2C.Sy{J{J2f22Sy 2g'R "'22[{ˁ222K "'22`{́222K "'222K`:`{́223PK "'33P3'c`33K`3CK``{΁3U3\3zB "'3h3z3mK``{ρ333K "'333KD`z3`:{Ё333K "'333KD`z33K``{с3343K "'4434c`4&K``{ҁ484?4eK "'4O4e4WJ`|`:{Ӂ4j4q4K "'444J`|4K``{ԁ445K "'454K`4K``|{Ձ5 559K "'5#595+J`|`:{ց5>5K5jK "'5a5j],`:{ׁ5o5v5K "'555c`5K``{؁555K "'555KD`z35`|<`{ف5667K "'6676KD`z36+K`:`|<{ځ6<6C6oK "'6R6o6W`6bK``{ہ6t6x6K "'666`6K``{܁666 "'666c`6`\{݁666K "'666`y(`{ށ777Z "'77`{߁7"7'7@K "'707@75``{7E7J7wK "'7W7w7dKH`y`{ၕ7|77K "'777KD`z3`{⁕777K "'777KJ`z;`{さ778K "'787J`|`{䁕8 88/K "'88/8 KB`|+`{偕84898T( "'8B8T8G`\{恕8Y8^8K "'8i88rKD`z3\{灕888K "'888K`8`\{聕888K "'888`8`\{K89 +9oKy 8'K "'99o9`9!!`9(`93`9?`9K`9aK`\{違9t9y9K "'999c`9Kc`9`9`\{ꁕ99:K "'9:9K`9K`\{끕: ::EK "'::E:`:%!`:,`:7`\{쁕:J:O:K "':[::cJ`|:r3`:\{큕:::K "':::Kv`:b`:0`\{::;K "':;:K`:Kv`:b`:0`\{; ;;*K "';;*;0`\{;/;4;bK "';G;b;LK`;V0`\{;g;l;K "';u;;zK`;K`;K`\{;;;K "';;;K`;K`;K`;K`\{;;F|K;F|  <c`<R`<+Kc`I<""!<<$x(+!== $h(+%=^='$[`>==o.Ky =$ =$=$(=$9=$J=$[`><$h>N$x>^${LJ>m?I>"""%>>$[`VF>ۆ>$h(+>>$x(+? ?$(+>N?"?+K[?-pF?V$[`VF=?.Ky?$ ?$?$(?$9?$J?$ {MJ??I@"""%@X@$[`VT@{@t$h(+@@$x(+@@$(+>=@.Ky@$ @$@$(A$9A/$JAI$[`VT{NJA?IA"""%AA$[`EBA$h(+BB$x(+B8B1$(+>=BI.KyBb$ Bt$B$(B$9B$JB$[`E{OJC?IC%"""%CmC*$[`glCC$h(+CC$x(+CC$(+>=C.KyC$ C$D$(D)$9DD$JD^$[`gl{PJD?ID"""%DD$[`V#EE$h(+E1E,$x(+EKED$(+>=E\.KyEu$ E$E$(E$9E$JE$[`V#{QJF&?=0F8FB'G{LFFGKy F'K "'FG Fc[FR[FKc[F[F[F`F[F[GK`\{MGG3GKy G'K "'G@GGAc[GIR[GPKc[G`[Gh[GnK[\{NGGGKy G'K "'GGGc[GR[GKc[G[G[Gq`VT\{OHH H~Ky H'K "'H-H~H5c[H=R[HDKc[HT[H\[Hp`E\{PHHHKy H'K "'HHHc[HR[HKc[H[H[H`gl\{QHIIxKy I'K "'I)IxI1c[I9R[I@Kc[IP[IX[Ij`V#\{I}IIK "'IIIc`IK`I`\{IIIK "'IIIc`IK`I`\{IJT+KJT+  Jc`J-R`J>Ke`JQKf`JdK`JK`JK[J`+JK`+\>IJ"!KK$(+%KQK$u`>=Kb.Ky K~$K$#K$1K$BK$SK$dK$u`L>$LN${RJL]?ILo""%LLt$u`VFLɇL$(+LL$(+>NLMK[MpFM,$u`VF=Mk.KyM|$M$#M$1M$BM$SM$dM$ {SJM?IM""%N3M$u`VTNTNO$(+NnNg$(+>=N.KyN$N$#N$1N$BN$SN$dO$u`VT{TJOX?IOj""%OOo$u`EOԇO$(+OO$(+>=O.KyP$P-$#P>$1PQ$BPd$SP$dP$u`E{UJP?IP""%Q2P$u`glQSQN$(+QmQf$(+>=Q~.KyQ$Q$#Q$1Q$BQ$SQ$dR$u`gl{VJRW?IRi""%RRn$u`V#RчR$(+RR$(+>=R.KyS$S*$#S;$1SN$BSa$SS|$dS$u`V#{WJS?=0SS'G{RT0TPTKy T1'K "'T`T Tac[TiR[TpKe[TyKf[T[T[T`T[TK`\{STTU9Ky Tơ'K "'TU9Tc[TR[UKe[UKf[U[U[U%K[\{TU=U]UKy U>'K "'UmUUuc[U}R[UKe[UKf[U[U[Uq`VT\{UUUVDKy Uá'K "'UVDUc[UR[VKe[V Kf[V[V[V6`E\{VVHVhVKy VI'K "'VxVVc[VR[VKe[VKf[V[V[V`gl\{WVVWNKy VΡ'K "'VWNWc[W R[WKe[WKf[W&[W.[W@`V#\{WSWXWK "'WaWWr`|<W`\{WWWK "'WWW`|<W[\{WWWK "'WWW`|<W`\{XXX4K "'XX4X!`|<X+[\{X9X>XvK "'XGXvXX`|<Xf`Xm!`\{X{XXK "'XXX`|<X[\{XXXK "'XXX`|<X`X!`\{XXY(K "'YY(Y`|<Y[\{Y-Y2YqK "'Y;YqYL`|<YZ`Ya!`Yh"`\|YvY{YK "'YYY`|<Y[\|YYYK "'YYY`|<Y`Y!`Y"`\|YYZ*K "'ZZ*Z`|<Z![\|Z/Z4ZzK "'Z=ZzZN`|<Z\`Zc!`Zj"`Zq`\|ZZZK "'ZZZ`|<Z[\|ZZ[K "'Z[Z`|<Z`Z!`Z"`Z`\|[[ [:K "'[[:['`|<[1[\|[?[D[K "'[T[[e`|<[tK`[L[\|[[[K "'[[[`|<[K`[L[\| [[\0K "'[\0\ `|<\K`\#L[\| +\5\:\\K "'\D\\\MKD`z3\| \a\f\K "'\u\\~KD`z3\| \\\K "'\\\K`\`\| \\\K "'\\\K`\[\|\\]&K "']]&] K`]`]!`\|]+]0]XK "']?]X]DK`]J[\|]]]b]K "']p]]uK`]`]!`]"`\|]]]K "']]]K`][\|]]^ K "']^ ]K`]`]!`]"`^`\|^^^?K "'^&^?^+K`^1[\|^D^I^K "'^\^^aK`^kB`^u`^K`^K`^e`\|^^^K "'^^^`^!`^`^`\|^^_K___`_!`_`_ `_,`_8`_NK`\>=_\.Ky_h$_k$_n$#_u$2_}$A_$P_$_{K##O###V##3###$L$$\$$H$$*$$$$i$N$#$ $ +$ +$ _$ $ $ $ S$ $ $ +$ u$ $6$$ +$$$${$$a$$G$$-$$$S$$$l$$($$a$$[$$$A$$$$^$$$$I$$"$#8$#$$$%S$&$&$'$.$/B$/$0$1~$2>$2$3$4$5$5$;|$<3$<$=$>T$? $?$@$G$H$Il$J;$K +$K$L$Mw$NS$O"$O$P&$P$Q$Q|$R$R$R$Sg$S$Ts$T$Ua$U$Vm$V$Wl$W$Xo$X$Y$Z$Z$[&$[$\E$\$]&$]$]$^$^$_Z$_$` $`g$`$a%$a~$a$b0$b$b$cH$c$d $d$d$e2$ex$e$f5$f}$f$gI$g$h4$h$i$jL$j$j$k$k>$k$k$l$lW$l$l$m5$m$m$n$n[$n$o$oW$o$p$pz$p$q$q?$qv$q$rz$r$s +$sg$s$t$tt$t$u.$uw$u$u$vm$v$w $wh$w$x$xr$x$y$yb$y$z$zx$z${2${${$|$|Z$|$|$}D$}$}$~&$~p$~$ $$M$$$t$$U$$$b$$}$6$$\$$$$$$$$q$$$T$$L$$$I$$$h$$0$$$K$$"$$$]$$%$o$$$g$$$$$$v$$d$$&|`t`a5L `u'L`|``a3py`a3`|>=0aa'$$|bb-bL b'L`|bbbpybb`|>=0bb'$)$u|ccdL c'L`|!d `+|"d L`+|#d L`+|&d;dCdpydZd`|>=0dcdm'$$J|'eefmL e'L`|*f%f-fkpyf3fk`|'>=0f<fF'$$|+gHgfhL gI'L`|-h L`+|.hF L`+|/hl L`+|0h L`+|3gghpygh`|+>=0gg'$z$|4iij[L i'L`|7j +jjYpyj!jY`|4>=0j*j4'$$R|8k6k^lL k7'L`|;kklpykl`|8>=0kk'$$|<lmmL l'L`|?mvm~mpymm`|<>=0mm'$$j|@nnoL n'L`|Co.o6opyoIo`|@>=0oRo\'$$|Dp^pqFL p_'L`|GppqDpyq qD`|D>=0qq'$6$|HssL s'L`Q|JttL`7|KtL`7|LtL`7|MtL`76|Nu3L`7n|OujL`7m|PuL`7|QuL`7U|RuL`7|SvL`7|TvBL`7/|UvsL`7j|VvL`7|WvL`7|XwL`7|Yw>L`7|ZwaL`7|[wL`7|\wL`7|]wL`7|^x L`7 |_x6L`7=|`xiL`7 |axL`7|bxL`7|cxL`7T|dyL`7V|ey?L`7W|fygL`7X|gyL`7Y|hyL`7D|iyL`7d|jzL`7e|kz@L`7|lzcL`7|mzL`7/|nzL`7|ozL`7|p{L`7|q{;L`7|r{kL`7|s{L`7|t{M`7|u|M`7|v|;M`7|w|lM`7|x|M`7|y|M`7|z} M`7|{}<M`7||}sM`7|}}M `7|~}M +`7|~M `7|~AM `7|~wM `7|~M`7|~M`7| M`7|CM`7|sM`7|M`7|M`7|M`7|?M`7|uM`7|M`7|M`7| M`7|AM`7@|tM`7"|M`7#|M`7N|M`7|4M `7|mM!`7|M"`7|M#`7|M$`7B|*M%`76|YM&`76|M'`77|M(`77|M)`7D| M*`7E|MM+`7|{M,`7e|M-`7&|M.`7|M/`7|M0`7|GM1`7|sM2`7|M3`7|M4`7|M5`7|%M6`7V|NM7`7|M8`7s|M9`7|M:`7|M;`7|?M<`7|pM=`7t|M>`7p|M?`7|M@`7|&MA`7q|OMB`7r|}MC`7|MD`7|ME`7%|MF`7%|&MG`7&|QMH`7/|}MI`7/|MJ`70|MK`70| ML`71|9MM`71|kMN`72|ÁMO`72|āMP`73|ŁMQ`73|Ɓ'MR`74|ǁSMS`74|ȁMT`7&|ɁMU`7'|ʁMV`7'|ˁMW`7(|́=MX`7(|́nMY`7)|΁MZ`7)|ρM[`7*|ЁM\`7*|с&M]`7+|ҁQM^`7+|ӁM_`7,|ԁM``7,|ՁMa`7-|ց Mb`7-|ׁ:Mc`7.|؁eMd`7.|فMe`7|ځMf`7|ہMg`7|܁$Mh`7|݁LMi`7|ށwMj`7|߁Mk`7|Ml`7|ၕMm`7|⁕;Mn`7|さ_Mo`7|䁕Mp`7|偕Mq`7|恕Mr`7Z|灕Ms`7e|聕:Mt`7f|違eMu`7[|ꁕMv`7g|끕Mw`7h|쁕Mx`7\|큕 My`7i|8Mz`7j|cM{`7P|M|`7Q|M}`7R|M~`70| M`7|JM`7@|tM`7|M`7|M`7|7M`7|{M`7|M`7|M`7|<M`7|}M`7|M`7|M`7}HM`7}M`7}M`7}M`7}3M`7}eM`7}M`7}M`7}-M`7V} nM`7} +M`7} M`7} M`7F} M`7}EM`7 }yM`7 +}M`7}M`7}M`7}#M`7S}LM`7 }uM`7}M`7}M`7}M`7}AM`7}dM`7}M`7}M`7}M`7}M`7}>M`7} qM`7}!M`7}"M`7S}#M`7T}$M`7U}%BM`7}&mM`7}'M`9}(M`7}) M`7}*5M`7 +}+ZM`7},}M`7}-M`7}.M`7}/M`7}0M`7}1QM`}2uM`}3M`}4M`7!}5M`7}6M`7}7AM`7}8gM`7 }9M`7 +}:M`7};M`7s}<M`7}=HM`7G}>M`7}?M`7}@M`73}A9M`7M}BxM`7.}CM`71}DM`7}E/M`7$}F^M`7$}GM`7}HM`7}IM`7k}J*M`7%}KfM`7-}LM`7I}MM`7}NM`7}OPM`7}PM`7W}QM`7}RM`7r}SM`7}TMM`73}U|M`7}VM`7}WM`7}XWM`70}YM`7/}ZM`7K}[M`7}\-M`7i}]^M`7"}^M`7L}_M`7+}`M`7J}aJM`7}bM`7:}cM`7}dM`7}eM`7}f)M`7}g`M`7p}hM`7}iM`7}jM`7}kM`7}lAM`7}mf`}nM`7}oM`}pM`7}qD`}rM`7}sKM`7}tM`7}uM`7}vN`7}wN`7}xJN`7}yvN`7}zN`7}{N`7}|N`7}}-N`7}~]N`7}N `7}N +`7}N `}&N `78}ZN `77}N`7}N`7f}N`7g}N`7:}LN`7-}oN`73}N`74}N`7.}N`75}N`76} N`7)}AN`71}cN`72}N`7}N`7}N`7}N`7}7N`7}n`7}N `7R}N!`7}N"`7A} N#`7S}BN$`7}uN%`7R}N&`7T}N'`7Q}N(`7C}HN)`7D}N*`7P}N+`7}N,`7U}"N-`7B}SN.`7}zN/`7}N0`7}N1`7'}N2`7/} +N3`79}.N4`7:}SN5`70}wN6`7;}N7`7<}N8`7+}N9`77}N:`78})N;`7}QN<`7}sN=`7Y}N>`7o}N?`7}N@`7} NA`7w}3NB`7}XNC`7}}ND`7q}NE`7b}NF`7W}NG`7Q}NH`7}5NI`7}}ZNJ`7}NK`7=}ÁNL`7}āNM`7}ŁNN`7}ƁNO`7v}ǁ?NP`7}ȁeNQ`7}ɁNR`7p}ʁNS`7V}ˁNT`7X}́NU`7}́NV`7|}΁ENW`7}ρoNX`7}ЁNY`7}сNZ`7(}ҁN[`7^}ӁN\`7}ԁEN]`7}Ձ{N^`7b}ցN_`7_}ׁN``7}؁Na`7`}ف-Nb`7}ځ_Nc`7}ہNd`7}܁Ne`7}݁Nf`7}ށNg`7}߁LNh`7}Ni`7}ၕNj`7}⁕Nk`7}さNl`7O}䁕.Nm`7}偕eNn`7}恕No`7}灕Np`7}聕Nq`7}違Nr`7}ꁕ9Ns`7}끕aNt`7@}쁕Nu`7A}큕Nv`7C}Nw`7}Nx`7}'Ny`7}QNz`7}wN{`7 }N|`7}N}`7}N~`7}CN`7}~N`7}­N`7}N`7}N`7W}CN`7}xN`7}êN`7}N`7}N`7H~-N`7~cN`7~ęN`7~N`7~N`7~N`7~ON`7~yN`7~ţN`7~ N`7P~ +N`7~ &N`7~ ON`7~ xN`~ƲN`7~N`7~N`7~;N`7~bN`7~ljN`7~DZN`7~N`7~N`7~)N`7~QN`7~yN`7~ȡN`7~N`7~N`7~N`7~@N`7~hN`7~ ɐN`7~!ɸN`7~"N`7~#N`7~$0N`7~%XN`7~&ʀN`7~'ʨN`7~(N`7~)N`7~*N`7~+GN`7~,nN`7~-˕N`7~.˼N`7~/N`7~0 +N`7~11N`7~2ZN`7~3̉N`7o~4̲N`7<~5N`7i~6N`7~7KN`7j~8|N`7~9ͳN`7M~:N`7L~;N`7~<HN`7~=΂N`7~>μN`7~?N`7~@0N`7~AjN`7~BϤN`7/~CN`7~DN`7~ECN`7=~FsN`7;~GСN`7~HN`7:~IN`7r~J-N`7~KZN`7~LчN`7~MѵN`ǔW~NN`7"~ON`7$~PHN`7%~QҁN`7~RҹN`7~SN`7~T6N`7~UsN`7~VӱN`7#~WN`7~X-N`7~YgN`~ZԏN`7~[ԺN`7~\N`7<~]N`7B~^VN`7C~_ՙN`7?~`N`7@~aN`7:~b5N`7F~cN`7D~dN`7~eN`7(~f)N`74~ggN`7*~hיN`7)~iN`7>~jN`7=~k3N`7;~l`N`78~m؋N`77~nضN`7~oN`7C~p&N`7@~qXN`7n~rيN`7A~sN`7~tN`7m~u(N`7~vYN`7~wڈO`7~xڱO`7~yO`7~zO`7;~{CO`7~|sO`7h~}ۭO`7>~~O`7~O`7~VO `7~܌O +`7~O `7~O `7~$O `7~TO`7~݆O`7~ݳO`73~O`74~O`7c~PO`7~~O`7~ޣO`7~O`7~O`7~=O`7~wO`7"~߱O`7~O`7j~(O`7E~bO`7#~O`7$~O`7%~ O `71~5O!`7~\O"`7~f`~ttt^pyt&t^`|H>=0t/t9'$$-~kO# l'O$``~~6>py[`~>=0dn'$r$~mO%`~kpy3k`~>=0<F'$$:##D#-##f##F# ##"######I####2###6##-########F##{####@##~$j$$$W$$$_$$w$$$:$$G6$I~O&NTABUp;po"*~0O'^`~`~O(~\~O)^`~`~S~\~O*^`~~\~2O+^`~S~\~8-A 9[ d '`~ `:+~ Qp~Q`~>=0",'~`J`'g'O,~O- "' -`:&,`:P^`~~\+|^`~S~\+^B\+\~NO. "'ϏN^`~~\^`~S~\+6^B\+\~SX "'c{^`~~\^`~S~\+^B\+\~+O/ ')+]`~>N6@]`~F`~=g.4sstK`~`>=?'O0$ =$t$ 4ԑ S`~`>=$j$_~J!$u$$$$$ $$~"O1 'O2` +~O3`7~O4`~)O5`~L`7~pO6`7~O7`~O8`~O9`~Á Q`+~ā `:+~ǁ{p~`~>=0'$$~ȁO: 'O;`~ʁ O<`+~ˁ `~+~́ O=`+~ρt|p~`~>=0'$$~Ё--O>`]][[[$~с--O?`~]mj][[[$2~ҁO@ 'OA`~],][[[ ~ՁǗϘp~`~>=0'~ׁ!)N(0N`J33`'t'h.~܁S` +b +g`][[[>Itx`'g'Հ$$$.(~=0$.?J.$~~݁ %`0 K][[[\>=0=G'~ざʙΚ%(Ԛ%K`\>=0'~؁*28][[[>I>NG.(~׃w>J[b][[['OB'z.?=0('~فNN][[[>NȚV`.(~I瀚$҃w>J][[['OB'N.$҃y?=0'1('~ځS[+b+][[[>NlpV`w.(~I$w(>J][[['OB'z.?Iˀ$w(=0('?=0('~ށ04W=WB`][[[JLP.Q$#~~߁z~`][[[>JpG.OC~$r~~ၖҜOC~ ӡ' "'[[$v$$$$$+$$J$$R$$ ~䁖֞OD ף $a~ {'O0`~灖Ip~I`~>=0$'~ꁖNkOE~ O'OF "'v~OG`:],[+^`~`~O(~\+^`~`~S~\+\~끖0OF 'OF:BOG`:V],[+]`~>Nlv]`~|`~=.OE~%%4s`~O(`~`>=?'O;%=?'OAB8%~=YO%tb%4uuv`~S`~`>=%j%~Jς%u$$%e%$8$$$$$;$2%%~OHOI'D" 3P)h߈@  @DPVYOi NT  |@}[VYP"OJOKOLOMONOO OPOQOROSOTOUDOVOWOXOYOZO[O\O]O^O_O`OaOb~Oc`[^__=r~`~^Odf`[^`~_K" Oe`% Of~`:)ۻۻOf`:\?%%Z 'A`:J.Of~%%%*MVM\NOg`-M (~`:1MMMMMM(`:\?-%1 M/MMNAMN`:JM$N'OhM.(~-'Oi%`%2WW#\+Oj``5WkOk~`76WOl~`WW57WOm~`WWДW5yGX`2XHX;On`2XMIXuOo`2X8XOp~`2XXHWm9XOq~`2X7:YpOr~`7+;YOs~`+<YOt~`7+=YOu~`+>ZOv~`7+?Z Ow~`+@Z>Ox~`+AZYOy~`+BZ Oz~`C[ O{~`7D\9 O|~`E{O}~`:7FBO~~`B75B5wwx1p~wx1w`wO`w`7\? +wx% xRx% x!% .x*% .x6x6xO~xMxxS`xdO|`xpO{`7\?D% C% B#xx% (*x% ` x6KK`6`Iay`Na`V6`:`c`+`2>N`u`|`2`~Q`% +^`% +nI```% +(+y>=0``'O`% +^?Jaa % +MaadjO~adja6`:a``2>NaaO`70Naa`Nbb `2b GNbbO`&bbԗybb݀b% :(^`Ibc b% (=c% ?Ec+c4c6`c=c;% +cFc?% :(^cN% +cOcN% +W>=c[% ycclcgcb% yh7 +Wcucn% :c% +Ayc% bIccc% cc% W(>=c% ccƄc% hc9xWcc% yv=c% y=d % ?Id5d9% IJdEdLdM% Wm?JdYd`% NeegO~ege``>NffO`70NggO`79NggO`7aIg)"g0g-%vg3%gHg?%vgK%3JgOg_gV%yga%?=gi%grgi%k7 Ngg`ggg%yg%JW7 +Jgg%OhhlO~hlh6`:hO`h``2> NhiO`ii +5Ni#i0`i@i9i2%x(^yiB%NiTi_O`iioib%iq%nNii`7ii%NiiO`i݄i%߃yiii%yhi%Nj jO`j(j!j%b(YyNj5j7`j9%NjKjQ>`EjZjcje@`jljj%S jn%j%S jj%S W>NjjO`jNjj%x5`j% 5`j% j% W% AIjjj% ^7Jj+?=j%: +kk k%: +h7Wk% =k,k&%b5`k-%5`k-%k7% y% k=%: +:CkIkRkP% k[kT%x(^>=kk%: +Ek|kk@`kk%W k%k%W kk%W W>NkkO`kNkk%x5`k% 5`k% k% W% AIkl k% ^7Jl+?=l%%: +l8l3l-%: +h7Wl:% =lZlT%b5`l[%5`l[%le% y% lk%: +:Il|"lll%b(Y(lll%b9(JllG?Jlll%l߆l%b(Yl%bPmmoQO~moQm6`:m`m``2>Nmm`2nGNnn`2n"n+%En7n@nB`nInG%_nRnK%ށ(^nZ%_n[nZ%_W>NnknvO`nxNnn%ކn%_AInnn%ă^n%Jn+?=n%nnn%hn%1xWno%vIoo %Jo,o3o4%Wm?Jo@oG%Qp,p?v O~pHv pP6`:p]`+`2>Ipkpvpo%('BJp}+?Npp`p'OT*Npq@`qq%>q%Nq"q,O`Nq9qB`NqOq\`Nqiq|O`7Iqqq%f(+Jq+?Nqq`qqq%fq%('yBNqq`:qq%fq%NrrO`:r r%fr!%Nr7rGO`:rNrI%frO%Irirsrm%(+>Ir!rr%X (+B>JrrMs%X s%?Is.!s;s2% +(+B>JssOs% +s%?Js+?Is!%ss%`>=0stt%''`?ItH"tRtL%t_tY%w7$>=0tmt~t%7$'?It"tt%(7 +!tt%X (+B>JttMt%X t%?Iu"uu%(7"!u2u%%X (+B!uMu=% (+B>Ju_ufO5`:up%X #u}%% (+u% %% `:u%?JuuP5`:5`:u%X #u% (+u% % `:#u% (+u% +% `:u%u%RvZvevO~vovvtO`v`7`>Cv"vv%Mwvvv%^vv%My9(=v%Mvv%MyJvv%MxxxO~xx`Jxxx.O|~D(SyyzO~yzy`7y#`y`y(``7>NzzO`7zz!%Nz2z4`z9z6%yz;%EzEzNzP`zWzU%5zY%z\%5z]z\%5W>=zuzi%Հzv%5zz{%zz%Wz%59:Jzz%zz|#{ |{K``2>I{{'{!% (J{-{4G?I{>{H{B% (J{N{UH?I{^{h{b% (J{n{uI?I||&| |% \9J|5|H|W|Q% ?I|e%|o|i% `[J|z||% `[?J||&||% `||O~||K``2> +N}}`}}%!@}1}&5(7}&}6I}=}A%!>N}}O`}}9Wh9I}}}%!(}%"%>N~~`7~=~5~/%"7:J~K~^)~i%"?=~%!~~%!W?I~~~%!~6>N~~`7~ǥ=~~%#+~%!:J~ +%!Ɣ%#+?I,60%!v9>NQX`7Z=uo%#{%!7:=%#%!5:J%!ƕ%#?N`%!?N`7!E72-%$ny:5WNSU`C^!ke%!(>=y%$5`%$5`%$%%9W%%9%!7:=%!%!6J%!%$(Y%$O~K`[`2>NO`73I"%&7 %&7>=0&,$X'OR%&7?Nju`}w%&7I%&=%&7%&7Wj?=%&7%&7qI؀%&7(JG?N`EE`%#%'7*%'+*%'W>=;7%'m<%':=gZSN%'mޗ֠u%&7NO`у%'m79W%'m79N `%(@y%&P@6+5(7+;NrO`7=%) %'m97W%'m9:=ن%) %'m97W%'m9:= %) !%'m797W'#%'m9:=j[%) u7k|x%'m797:NO`2*%) NO`2%*I%(>=%*5(%*89%(WpIN[R%(w>=h%*t%*%(o?I%&J%*Wm?J%*mW`2>I.O|~D(J.?J!.Oz~B.O|~D.O{~Cn\`2J#.Oz~B.Wm.`2TXO~X``2>NO`.O|~DI&/*%-C(>J=DG?NZeO`lg%-CWn%-*N{`7.O{~CNO`7%-E`ԁ%-Cyۅ%.^%.%.y>=%-%.W%-* +%- %.9:J,..Oz~B;%-G%-U!O~/BO`7OO`Z`hO`7`>I|%/V(>J?I"%/g(%/v%/G>J%/V?N O` %/VW%/gE#%`-'%/Vy42%0@^:%0@;:%0@y>=SG%/vVT%0@WX%/gd]%/Ge%0@9:Es|~`%/gy%1 ^%1 %1 y>=%/v%1 :J%0VO~``2> +N$)O`+.O|~DI6?:%1(>JMTG?NjuO`|w%1y~%1I%2Dv>J#.Oz~B8G`2?N`7.O{~CNO`7%2DE )+`-%120%34%1:%3;:%3W>=SG%2VT%3yX%1c]%2d%39:Nx`2.Oz~B%2D%2I.Oz~B>E `%49%1%49%49W>I*!84.%25%499(>JJXQ%3׃yZHw??J{%3WO~O`7O``O`7\>@%5@wNO`%5Q5N-6O`:8%5Q<5NR`O`mb5yo%5NO`%6yNO`E`с%5@y%6 ^%6 %6 y>NT`%51%6 9= %5`'%6 W%5WG5/%7 +8%6kI%6x:=V%6xpe_%7 +g%6:s%5=%5`%5%6x:oQf|h|mO``2> I%8[>=0$'O%8[?I.O~J.?NO`(%8[+5NAJO`XL%8[Z5Ijwn%9(>J.O~%8T?NO`.O|~DW%8WNO`7%9=W .O{~C.O|~D%8[*%9J=PR.Oz~B_%9k%9X +O~ +O`7O``*O`7`> NDPO`TR%:̉W5NmvO`zx%:̈|5I%;*(>JU%:%:%:%:?NO` +%:W %:W=!W&%:/%:6%:̃9%:NPR`T%:Cepn%<-ln%<-y^>=~%:ۀ%<-:I%:%;y9(>=%;ֆ%;y?J%;YNZO~^qO`7~O``O`7\> @%=\wNO`؂%=m5NO`%=m5N$O`1&5y3%=NGOO`aTW%=yNntO`}v%=M~%=9%=N`%=\y%=yE`%?* +%> %?* +%?* +W>NT`%=M%?* +W%=W9=+%=|,%?* +VD93%? ;%>VG%> kX%>:=e%>sm%? v%==%=|%> %>:pO``2>I  %@倇>=0&,$g'O[%@?Itx.O~J.?NO`%@5NO`%@5I%A(>J.O~%AgV?N;@O`B.O|~DNS^O`e`%Byg%AgIw{%B?v>J#.Oz~B8G`2?N`7.O{~CNO`7%B?=Y%Bǃ%B%%@2%BNKR`2`b.Oz~Bo%B?{%BI.Oz~B>I!%B%Ag9%Ay(>J&%CCy(Hw?E;DF`MK%D<O%Ag[%D<\[%D<W>Ij!xtn%Bu%D<9(>J%CCyHw??J%CCZ<O~<O``>Ns`2&%E;`2J[ .O{~C.O|~D#%EVO{~C2,%EVO|~Dq +/x/ O``>N5;s`2&5=%F`2IIYM.Oz~B(b\%F,Oz~B>N{`.O~%F,ZJ#.Oz~By%F%F`?J#.Oz~B%W`[%O~% `7O`)O`7:O``>NOV`]X%Gty_%GInyr%G(>E`%Gty%H^%H%Hy>=%GĀ%Gg%H9yՂ%G%H9I!%G(J%G??J%G\O~`7O`O`7O`O`7\>@"%IE^ %Ie7-%Iew:NEKO`ET]_`fd%I쀇h%Ies%Its%IW>=%I%IW%I8%I9W%IV%I9=%Iv%IÅ%Iх7:=%I݅%Iш5E`%Ie%K(%IE%K(%K(W>=&%I,&%IW5/%I86%K(9=L@%IvM%K(XR%IхZ7:=l%Irl%Iшv5=%Iv%IE%I:]'O~.:`7FO`WO`7nO`O`7\>@"%L^%L%LwNO`E`%MG%L%MG%MGW>=%M,%M,W%L%MG9y(%L)%MG9=?3%Lр@%MGKE%M,M7:=%M,Փy߅%M,5E ` %L%N%L %N! %NW>=-%M,3-%M,W<6%L=%N9=SG%LрT%N_Y%M,a7:=%M,铃y%M,5^eqO~s`2``2> NO`.O|~DNO`ր%PO|~DI%P,%PS>J %PO~.!%P^?I8A<%P,(>@!W%PVaJjqG?I%PS(>J#.Oz~B(%P..Wm`2?NO`%P,WNO`7 +%Q=&\..O{~C7%P,C=%PO{~CL%PSW%QJj}%P%Q%Q_1=O~KXs`2d``2>@}.O~%RZ^}NO`.O|~DI%R(>@!%RJG?NO` +%RO|~DI)%ST(>J7#J>.Oz~B(M%R.a.Wm`2?NvO`7%R=].O{~C%R%RO{~C%ST%SJ%R%R%S`lxO~s`2``2>NO`.O|~DԀ%TO|~DN`7.O{~CN +O`7 %TO{~CN#0O`72=%TENWY``^%Ub%Tn%Uon%UW>={%U%U%U9%U9%U\%U9:J%T҂%T%UaGS3O~d3qs`2}``2>NO`.O|~DN`7.O{~CNO`7݀%VO{~CNO`7%WN`!&%W82%VO|~DEDMO`VT%W뀇X%W[%W\[%WW>=th%W|u%Wz%W,%W9%WO%W9g:E`%W%Xʀ%W%X‡%XW>=څ%W|%X%W,%X9:J +%V%W"%W|b,O~,s`2``2> NO`.O|~DNO`%YO|~DNO`%Y%ZN3:`7<.O{~CNMYO`7a[%YO{~CNrO`7%ZIN[N[I%Y%Z>=%Z%Y=%[ %Y>=%Z.=%[ %ZE )+`20%[ +&44%[ `7%[ +87%[ +W>=PD%Z̀Q%[ +`\V%Z}]%[ +9kmb%Zn%[ +9:NO[%ZO{~E[%[ &%\ %ZI`%\ %\ W>=҇%Z̀&%\ `&%\f +%\ `:J%Yڄ%ZI%Zc&O~&s`2``2> NO`.O|~DNO`%]O|~DN O`%]߃%^N-4`76.O{~CNGSO`7[U%]O{~CNlyO`7{%^5N[N[I%]߀%^>=%^%]=%^ %]>=%^.=%^ %^E#%`,*%_o +&..%^ `1%_o +21%_o +W>=J>%^K%_o +ZVP%^iW%_o +9g\%^h%_o +9:NzO[%^O{~E[%^ &%` %^5`%` %` W>=̇%^&%` `&%`R +%` `:J%]Ƅ %^5%^rz``O``2>Ns`2&%a`2I".O~ہ%aO~JG?I.Oz~B(%aOz~B>I#'.Oz~B>NO`2.O~H)_N18O`2@:%aO~OH)_J%b|O~%b)bO~H)^?J.O~ %a*`?NQC[NT[I[_.Oz~B>=t%ccx%a=%cn.>=%cc.=%cn%aNO[%cnO~&H*J7&7@>%ccO~R%c*`2skO``2> Ns`2&%df`2I.O~J%d?I",&%dO~J5.?IFVJ.Oz~B(_Y%dOz~B>Itx.Oz~B>NCIO`2K.O~ZH)_NryO`2Á{%dO~ÐH)_J %ePO~%e)`O~H)^?J4;.O~I%d*b?N|C[N[IĆĊ.Oz~B>=ğ%f7ģ%d=İ%fB.>=%f7.=%fB%dNVYO[][%fBO~lH)Jſ&ſɄ%fO~%f7)O~H)`2toDŽ Dž ǍO``2> Nǧǭs`2&ǧǯ%gV`2Iǻǿ.O~J%gq?I%gqO~J.?I.Oz~B(%gqOz~B>I,0.Oz~B>NțȡO`2ȣ.O~ȲH)_NO`2ف%gqO~H)_J %h@O~%hu*c?J6=.O~L%gq*c?NɍC[Nɐ[Iɗɛ.Oz~B>=ɰ%iɴ%gq=%i.>=%i.=%i %gqNdgO[ki%iO~zH)J&ւ%iO~%iv)O~H)`2u #g +#`2>I.O~J '8?I6:.Oz~B>J{̂.O~̑H*_?J.O~H)^vAVϧWWϧ_O``2>Nys`2&ý%j`2I͍͑.O~J͚͡%k?IͬͶͰ%kO~JͿ.?N`.Oz~BI%kv( +%kOz~B>Jt{.O~Ί%kΑ%kv^?I3 .O~,%kZ^>JAH.O~W%k^%kv_?Juς|%kO~.!Ϙ%kv_w+y+O``2>Ns`2&%l`2I.O~J!()%lڃWm?I4>8%lO~JG.?N\g`i.Oz~BIz!Љ~%m^(ВЌ%lOz~B>J.O~%lڂ%m^^?IѠѷѤ.O~Ѱ%lZ^>J.O~%lڂ%m^_?J%lO~.!%m^_dֆO~ֆ`!O`79`MO`7d@`k`\>Itzx%n(>JԢ?NԸԺ_`C΍%nʅ%ny^>N/`%nh%n5`%n5`%n%oW%o9NO`;$%oW7&%n8%n9W=%o3=WF%nۀ5`X%n5`X%nY%p} W%p} h_%pj7:=%o3%p6C!%o3(>N`/+%n,%n9W1%o3=K:%nۀ5`L%n5`L%nM%qW%qUS%q;W7:=i%o3om%q;r6xֿ֪hO``2> Ns`2&%r\`2NO`.O|~DNO`"%rwO|~DI-"61%r(H>%r(>JV]G?Nq|O`׃~%rWׅ%rNטן`7ס.O{~CNײ׾O`7Ɓ%rwO{~CNO`7%s=N`C%s%r>=/dB7%sC%s9G%srR%s`%sc%r=p%sqp%sWJؒ!ة؝.Oz~B(زج%rwOz~Bńؿ%s=%seZe O~o {O`7وO`ٚO`7ٱO`O`7`>NO`%uAW%uaN ` %u@6/"%ur(Y^9%u":CALJ%uHJ%uy^>=fZ%urg%u:=y%uCڄڍڋ%uڏ%ua>=ڢdڵڪ%uRڶ%u9ں%u2%ur%u%uA=%u%uWJ%ufP[ܔO~qܔ}O`ۙ`7ۥ``>Iۮۼ۸۲%we۹%wr9(ۿ%wTJ7?NO`- +%we %wr95k$%we'%%wry90%wTIEWI%w׃wY7Jel7?J|܃%wg4O~4O``2> N s`2& %x`2@*$%y +O|~Dw-I4>8.O|~DF@%y +O|~D>JU\G?=l.O~t%y +iNO`?y@N'2O`74SJ>]@k?|%yNޓޗO`2ޥ*ޮ%y׃޼%z I"!.Oz~B(%y +Oz~B%zQO|~Dw>=%zQ%zQWm?J&-%zQh߀ߌO~ߐߘO``2> N߲߸s`2&߲ߺ%{U`2@Ӂ%{pO|~DwI.O|~D%{pO|~D>J.?=.O~#%{piNO`7S>@@N$`2 *@#%|5I3D7Aw>=Q%|q[W%|q^Ap?I".Oz~Bᨃ%|qO|~Dw>=%|qƒ%|qWm?J%|qiNSO~Zgs`2\>I""".O|~D(;ր%}O|~D(= .O{~C:4D>%}O{~CM<>Jj?@.O|~D^䒀%}O|~DNO`5y伀%}O{~Cʀ%}O|~Dy9?NO`7NO`NoO`7NO`I擁%~w>=%b檥滀%}O|~DW7=%rX%}O{~C%}O|~D%~%b=%@#4..O|~DW7=@%PMX[.O{~Cd.O|~Dk%~p%@>=%b碀%}O{~C=%r翀%}O|~D=%@S.O{~C.O|~D.O|~DW= %P.O|~DN/?O`HA%bOI%ry9N]_`a%PNuw@`{y%̃y}%rNO`7إ%NO`U%b%r%% I[%@%P% %B +^>@%(%P =%@5`%P5`%P)% W% :=s]{%@%P% %B +%@>= %@5` %P5` %P% W% :N|O`7뇥똅%rW=% %r:=]% Ӆ%rW%b%r% = % + %̃yC%w>N.EO`Qfh%y%@%=%%y=d% % %@%%rI%@%9% >N]eO`gUv% %r%% =]%@%P% % %@C%@%9% % y>=*]2%@@%PL% W% `%@?=%%̃y=:.O{~C=;.O|~D=<%}O{~C==.(%}O|~D=9>M%@=_?q%P=@%r=A%~z`>Ox|a```*`K``>=%T7%TW%c=%T7%TW7%T7 +J %T%T7O15=N%`7hc%Ww7y%=%%%7 J7ɂ%W7%7I.O~J73?N/4`#6.Oz~B7F7y`Ehqs`zx%|.O|~D%%W>=%%)%.O{~C%9JɁ%Y%y(s``J"%%`2.x +%`2q(u?u`>I.O|~D(J?I.Oz~BJ$.gu??J3SE:5hNH.O|~DyWh\U.O{~Cc].O|~Dy9?zGGO``2>Ns`2&%`2I%O|~D(>=0 ?J18.O~=%g{WcltO``2>Ns`2&%`2I%O|~D(>=0 ?J.O~%h|,<q=qEs``[JO_T.ga%Uh}s``J.x%q~ @v@!s``J+<+.x5%@qvp~ws``J.x%qw^s``J.x +%q^O``2>Ns`2&%`2I%O|~D(>=0 ?N@G`2I.O~N%hIZe^%Oz~B>Iz~%Oz~B>=%%y%w>=%ۂ%W%v?J%U`>I.O|~D(J?J#.Oz~BW`%.[5[`J8">8.O|~D(WRNG.O{~C9(`J!.`J.Oz~B + ``2>I$%π>=017$o'Oۀf%?I|%(JH?N`2HN`2.C!%(>I %υ(>=/%]6/%]h9%yx?=M%VM%ψI!%(>=%y%yh%yx?J%] D O`O``2>N `2&%`2NE`2&%`2I%Oz~B>=017$k'Oނb%?Ix|%vG~>=0$'O߃%?I%O~J H?N  O` & %O|~DN 7 FO` X Jh L%WN g vO`  x%۝?I   %]vJ  H?N  "`  %N  O`7  + % N +" +0O`7 +2 +=% N +V +^O`7 +` +k%N + +O` + +%. +%+ +E + + +@` + +%R y  % ^ %  + % y>= " % #%  / (%+ + 0% 9:N B MO` O%R N ^O[E o x z`  |%]y  %~^ %~  %~y>= %k   %O % %K  % I !   %ۅ  H %~orO~>= %K  4 2%] 8% & G G%k ` T%+ + ]%R  d%>N  O`7 %N  O` %K = % % = %K &  )%k `= >%  N%= a%k  o% J   %O % %K jw3F~3`2!`2G``2>$NO`7Ӏ%O{~CNO`7%O{~CNO`  %O|~DN O`$"%O|~DN3;O`#C=%wE%M%U%`NduO`w%=%*S%*%%=%WS%W%%N O`I%>I&"1+%(FB;%W9(JMTH?I_"jd%("{t%W9%*9>=0o'I?>I%O~>=0'O'O?ICIG%O~>=0\p's'O?I""%(ƒ%*9("%(%W9(JH?C"*%!%*9(E@<5%W9(>=VY[%*d%n%*=Y%W%%W=% % WI% ^5>NO`% 5=*%0*%y3% +=M%SM%yV% +=p%xp%y{% +?I%W9(>NO`7%*NO`%=%*!%W=2%:%=I%WS% +=f%n% ?NO`7S%*%%1NO`7S%W%%1WN9<`OJF?%*9(NO`%WNO`%B WNO[NO[NO[NO[N!O`N.`N;O`NHO`IY]% >=i%s~%o=%*=%=%ɥ%o=%*?=% %o=&%*=?%IT%o=b% +*={%AC)>C%m +9(>=Y%m +%%m +I% >I "#%(>95.%(>ISW%>It"!y%%([&%`7%%W%w>=]&%`7%B  %W%&%`7>=O]W%W`%&ii%`7r%&{{%`7=%*>=\&%`7%B %W%& + +%`7I.2%>=O\&WW%`7`%B j%*s%&||%`7I"!%%([&%`7%%*%w>=]&%`7#%B -%*6%&??%`7>=l]t%*}%&%`7%&%`7=%)?=Y&%`7%B &%`7I1,(!%(>ICG%>=b\&jj%`7s%B }%*%&%`7I"!%%( [&%`7%%*%w>=]&''%`70%B :%*C%&LL%`7>=u]}%*%&%`7%&%`7=%)?=Y&%`7%B &%`7C4/+$% 9(>=DYI% R%^% Ipt% >I"%(%(>I%>I"!%%(P[&,,%`75%>%WG%w>=h]&pp%`7y%B %W%&%`7>=]%W%&%`7%&%`7= %*>= T\& \ \%`7 e%B  o%W x%&  %`7I  % +>= \&  %`7 %B  %* %&  %`7I!"!!&!!%!%(!s!@[&!O!O%`7!X%!a%*!j%w>=!]&!!%`7!%B !%*!%&!!%`7>=!]!%*!%&!!%`7"%&""%`7="'% +)?="_Y&"d"d%`7"m%B &"z"z%`7I"""""%(>I""% +>="\&""%`7"%B "%*"%&##%`7I#!"!#7#-#&%#.%(##O[&#^#^%`7#g%#p%*#y%w>=#]&##%`7#%B #%*#%&##%`7>=#]#%*#%&$$%`7$%&$$%`7=$.% +)?=$`Y&$e$e%`7$n%B &${${%`7I$$$[$%m +$%$% $%^>=$]$%m +$%$% $%%%m +I%%% >I%,%<%0%(%?%>N%^%fO`%h[&%w%w%`7%%B &%%%`7%%B I%%%%w>=%]&%%%`7%%B &%%%`7%%B &%%%`7>=&&]&&.&.%`7&7%B &&A&A%`7&J%B &&T&T%`7=&l%"!&{%!&&%(>=&\&&&%`7&%B &&&%`7&%B &&&%`7?I''-'!%('0% +>N'M'UO`'W[&'f'f%`7'o%B &'y'y%`7'%B I'''%w>=']&''%`7'%B &''%`7'%B &''%`7>=( ]&((%`7(%B &((((%`7(1%B &(;(;%`7=(Q%"!(`%!(x(p%(>=(\&((%`7(%B &((%`7(%B &((%`7>=(])% )%)%m +)"%)+% I)=)A% >I)Q)a)U%()d%>N))O`)[&))%`7)%B &))%`7)%B I)))%Nw>=)]&))%`7*%B &* * %`7*%B &**%`7>=*K]&*S*S%`7*\%B &*f*f%`7*o%B &*y*y%`7=*%"!*%!**%N(>=*\&**%`7*%B &++%`7+%B &++%`7?I+B+R+F% +(+U%>N+r+zO`+|[&++%`7+%B &++%`7+%B I+++%Tw>=+]&++%`7+%B &++%`7+%B &, , %`7>=,2]&,:,:%`7,C%B &,M,M%`7,V%B &,`,`%`7=,v% +"!,% +!,,%T(>=,\&,,%`7,%B &,,%`7,%B &,,%`7N-=-?`-A%C-P"-Z-X%.w-r-j-c%m +-m-k%.y9(=-{%.-y-{%.yI---%.(B-?I-!-%>I---% w>=-%-X-% -%-% . % ?J.!.4*.=%.F% ?N.{.}`..%yC."..%w...% .%9(=.%..%yI."!..%(!...% 9(>=0..o'I?I//% +>I/-"!/C/9/2%/:%(//W[&/f/f%`7/o%/x%*/%w>=/]&//%`7/%B /%*/%&//%`7I/"!///%/%(080[&00%`70%0&%*0/%w>=0J]&0R0R%`70[%B 0e%*0n%&0w0w%`7>=0]0%*0%&00%`70%&00%`7=0% +*>=1]1%*1#%&1,1,%`715%&1>1>%`7=1P% +*I1x"!111}%1%(11[&11%`71%1%*1%w>=1]&11%`71%B 1%*2%&22%`7I2"!242*2#%2+%(2{2H[&2W2W%`72`%2i%*2r%w>=2]&22%`72%B 2%*2%&22%`7??J22*2%&22%`7445xJ45x4!O``2>N4;4CE`2&4;4E%-`2I4Q4]4U%Hv4`G~>=04n4t$4'O4%H?I44ȁ4%H(4HyJ44G?N44`2.I4"44%Oz~B5&55 %O~5%HZ^>=55%5955%5<%H?J5O5Vj5a%H5j%)7I7U8K7X87`O``2>N7z7s`2&7z7%`2I77.O~J777%\n?I777%O~J77.\n?J77j.7%*;P;\;<;f;;k``2>J;x;.;;;H;%oy;Hwr@@BU=@BU@``2>NAB>`2B BHBB %cyoJBB>B*.B6B-%|yB8HwryBF.BH%|rwBBCOBC`>IBBB.O|~DvBFJC )?NC"C(e`C*.IC7!CMCBC<%NjJCW*?JCiCu.(CC%NjyCCDMCDM`>NCC`ECCC`CC.O|~DyC܁C%V^C%VCC%Vy>=C%=D CC%=hD6WDD.O{~CD%V9JD$#D+.Oz~BD9D:%=WDC%=`E4E;Q.ECQ.`[>NEVEcO`73NFZFlO`Fs7yFu%ɟIFF.O~JF(?NFFP`F:7NFF(`GG G5hGG.O|~DyWG.G"G.O{~CG)G#.O|~Dy9?IG=GMGHGA%.y75wGO%ɷJGbGp^?IGG.Oz~B=G˂G%77:?NH HO`H(H#H%.y75WH*%ɟ=HFH<%7HcH\HM%S7:=5`Hm%5`7HwHw%߀Hw%H{HwHw%Hw%9kHH~%S:NHHP`NHHP`NHHO`HH.O|~DyOHHPa``HLH``>CIDI\IK%I^% >NIoP`NIIP`I5IIIχI%̕>=I%; +=I%̕JI%̕y>=J"%; +J5J..O{~CJ6%̕9IJMJ\JQ%̕(JeJ_.O|~Dy=Jj%M JJ|%; +??=J%̕JJ%̕y=J%iJJԅJ%iJ%M WJ%; +=J%KJ%WK%M NKTK[`KhK]%iK}Kl%yK% =K%iKK%iyKK% +K܆K%yK% =K%KK%yK% JLL % +NLLP`LLL%77=5`L%5`7LL% +L%# LLL% +L%# 9kL% :ELLL`7LL%Й +^L%Й +LL%Й +y>=M#M%M$%Й +M1M)%7:OMAMFPa\MMN\>NNNO`AEN)N2N4`N;N9%t 7N@%t NAN@%t W>INONYNS%X (BN_?NNrNvP`NNNx%N%t 9WN%X =NN%N%t NN% 7:=N%X NN% 7INNNN%(>INOO O%9>=OPOI%3 +>IO!OÅO%i(>=PP +%3 +>AEP0P9P;`P=%̕PTPI%̕^PZ%\ P[PZ%\ y>IPm!P|PxPq.O{~CPy%\ 9(>=PP%3 +BP??JPQQPP%ޗ֠Q#RRUZARUZ`:>IR&R0R*.O|~D(JR6'}?IRFRPRJ.O|~D(>IR^Rb.Oz~BJRoRRwRRx.O{~C9WA?JRRRR.O{~C9A?NSS&P ],`:1S0`:NS<SAm`2#SC.SP.Wm.`2CSbStSnSi%՘O|~Dw>NSSP +`:SSS%՘S9{A=SрS%rS%;ISSSS%(^(=TS%r'P ;?IT#T6T/T'%(^(=TOT<%r'P ;?IT`TsTlTd%(^(=TTy%r'};?=T%՘TT%՘T9z=TրT%rTTT߁T%՘O{~C9A;ITT.Oz~B=UU %r'y;?JU-UPUGU4%rZkU_UcUP ~UsUUxT``>NUUO`70NUUO`7aIUUU%@7 +JUÚU%YWU%@?JUUUU%pWU%@y7 +WWZDW)ZW.``:> IW;WEW?%-w7$=0WKW\Wb%-7$?IWvWWz.O|~D(JW'}?IWWW.O|~D(>NWWP`:WWW.O{~C9DW%-IWW.Oz~BJWX'yWX%G?JXX %?IX8XBX<%-(7JXIXP.P~l?NXiXn`2X|X%-NXXP],`1X`NXXm`2X.\nCX!XX%O~>NXXT`YYY%Y%ڮ{=Y$%Y0Y+%Y3%ڮz=YVY?%׀YZ.P ~Yk%Bk;NYYP`:YZYY%׈ZIYY.Oz~BJYY'yWY%G?JYZ%lZZ\)P~Z(\)`:>NZ5Z;],`1ZB`EZJZSZU`Z\ZZ%ǀZdZ^.O|~DyZi%ZjZi%W>NZzZ>`ZZ.O{~CZ%9EZZZ@`ZZ%{ZZ5Z%{ZZ%{W>=ZЀZ%ܞZ.P ~ZZ%:7k;=Z%:[Z%:N[[(P`[1[*.O{~C[8[2.O|~Dy9C[B![R[I%P(>=[f[`%ܞ[j.P ~[[{%P7k;=[%P[[%PI[[.Oz~B>N[[P`7-=[[%ܞ[%L;?J[\Z\\%ܞZ% +5% +% %H%%%%%c%%!}%&%+%,%,%/%1%5%81%:|%=%@%E %E%G7%I%Lc%O%RY%T%V%Y%]%as%d<%g,%i%j%l%n~%r2%u%w$%x%{%%}f%%%O%%X%,%%%%%c%%~%%\%%%%%ij%Ũ%9%% %k%U%%%d%߬K\R\a]P`\? \\\\\\`2\P`7`\\]@]\]@\O`7\O`]O`7]O`]3O`7`]D]H]O]K]]WO`7]dO`]vO`7`]]]O]]]O`7]O``2%+%z%%\%^^eP``^\ P~`2^ P~`2^^_a^_a^P`2\?%N^^%N_ _5y_W_B_;_2%NO{~C_R_L_C%NO|~Dy9?o ^_f_ja_qa_~`2_O`7`>N_[N_O[I_"_Ā_%<Oz~B__Հ_%<O~_.P~Z^>N_``2` ` %<O~`.P~hI`!"`'`%%<Oz~B`F`@`6%O|~Dw>@`f`\%Oz~B`\`q=`|%``|%W`.P~v?@!``%Oz~B``=`%p`؄`%O|~D=`%d``%O{~C>=a%paa%<O|~D=a*%da5a3%<O{~CNaLaN[aP%pCaw&aaa%a~a%怃y^`>=aa%K&aa%`&aaa%da%`:Ja&aa%p`aab2Oab2aO`7aO``2>Jbb*b%b&%pb7b;c P~bBc bNO`7b[O``>Ibhbrbl%b}bt.P~O|~D>Jbb%?NbbP`2b.Ob%b%Nbb$`2bb%kO~b.P~hJcc.c%褀c%c%c)dOc,dc8O`7cEO`cWO`7`>Ncocqr`2c*c%Ic%:NccP`2cc%shc%sxEccc`cÅc%ဇcȄc%O|~Dc%cЅc%W>=cc%Zc%ccc%O{~Cc%9:Eddd`dd%O|~Dd d%꤀d$hd&%Id-%d.d-%W>=dFd:%ZdG%ꤓ:JdYd`.P~dh%Zdxhdz%Idde]dedO`7dO`dO`7dO`dO`7`>NdeO`eee$%뱁e-%e4%уe=%eD%JeWe^.P~ef%et% +%%D%%%%3P` `: `:\?% 1A1`:J$1'P). %%YP`ΌԌ݌\? %KQ4P` `:Á͘ә2ޙ2`:+\?5`:%#%!(+'P%!`: %bā˙љP `Ɓܙ\? %ǁP! 'P"`Ɂ K`:ʁ \`́~[1[сp~K`:\`+\?ɀ%Pʁ%\ ΁=K{IQ{YK`:g\``=5[%%ҁ&P#&(`] +`Ձ&~[1[*ׁ*B*(/B`J2>G؁FawOna(ew`JhtHف{Oo(`JIၚȔyȡ(͔6`:`+`JK% %⁚6P$6(>F6`:S`+`JdpQz%s%#K``=5[ぜڇ\`䁜W`停ӈWs``恜#2y$2,s``灜Vfuhguos``聜s``[遜ˋۋ݋s``ꁜps``끜s``쁜csuzO``큜ȑʑO``/?N@NHs``ks``2BQCQKs``񁜗9ILgJL`򁜗ys``󁜗̗ڗvܗs``􁜘(7w)71s``p~^s``X\sxesm s``ځ,4=?==`ہޝU`܁ &&&`݁R[````ށ`՟ܟ +ߟ ``D `E``ġˡJաE``Ks``4<)4.``&9=.93``߁@ISOSS`lpwuw`Y`jhj`[@GQAOQ`:ryD``:%>%u%%%L%%%"%I%|%%%%K%%%%%S%%%%%J%~%%% %4%[%%%%%R%%%%%>%e%%*g(` P%(K`:A`*`>=0jp'P&ҳz(`Jz A`:>J#.''`:%%%)%c ++IP'`[`\?  x s_` GG%=] +[3r] +[`J9;9%xE%' %%%\kP((`] +`P)`P*`P+`P,`P-`77P.`7XP/`7wP0`7P1`P2`P3`9P4`WP5`7sP6`7 P7`7!P8`7"P9`7 #P:`7 +$P;`7 %1P<`7 &SP=`7 (V ~`+ `)P>~`9*jP?~`j$'P@'PA'PBR11O9O>`O~`d|`w```PC`PD`\? +Y %,%9%G %U%c%q#%<%*SPEƙ`~`|```.`DPC`_PD`\? +~Y %%%"%0%>%L%Z%j)T&\? +ZU+PF(+ ``*\? +X&݁%&"V09PG9(\aPH``*\? +X.&s݁&X`PI~Dz```+\>I" +. D\w )"PJ3. D\(S)!}.PDO(>=0$'PJ. D?I .+(+>=0''PK?(&+& YN~(. 3`=~`H|`Q`[`m`yPC`PD``\?+#%D>&`N&`0Vjp&'`(&3&&!&.&;&H'&UG;&bWI.k&q&` ZPL~(\?+*(ݡ ".vPM~PD``>J΀&7l48HyMUPN`:`>Nps`u*N@`&I&0I!Â&_(+>OԣPOa`:`I`:`>I &(+BJ?J(39&OPPa`:`ѦL`:`>I&5(+BJ?N(`( &5(^@F?&i^?J@c\&iv7\gNw~`E`&7&&W>=&&h7 +I&ۅ&5(^>=&&W&5&A70?J7>&NY_`epk&_N~`&_N|`&_N̦`ღ&炦&_N`&&_7N$+`;-&A<&_7NRdPQ`*NwPR`&&_7NPC`& }N(PD`&I4& \}`N`*I!&_7(+B>=&)I!&_7 (+B>N=0'PU&0?J2=XQ& +_&>=0z'PV&05ʫڬP$⬋PN`:`>K>J6=4C& [`w>Jv+67E(GHs[`>IU!%a[& ~`Jo*?J".~((& ~~.+(& ~7^'^1s``>J>LE.~(TN& ~(8s``>J.~(w䀹& ~(9~PWs``>J.~((& ~(:>x > s``J ' .~(x71& Y~(CCK}zT}`JWq_X.~(ib.~(77;Ϳ@HPX@H`>I.+>J@X@.~(*?J@9.<AAAzAA`>IAA.+JA.?JAAXA.~()/ABBPY~B BB``:>NBB$PZ`B(B&&!\NB:B?U`:#BCBA&!'y'`:IBWB`B[&:^7JBi$BtBr&!?IBzBB~&:^7dJB$BB&g'}B&:?IBBB&:^7 +JB$BB&g'P B&:?JB$BB&g'P B&:0BCCP[~C CC``:>@"C$C"&C&7WC1C/&w7C"C7NCBCGPZ`CKCI&\NC]CbU`:#CfCd&'y'W`:IC{CC&^7JC$CC&BC&?JC$CC&B'}C&1CCDDP\~CDDC``:>ICCC& ^7dJC$D +D& ?IDDD& ^7 +JD$D+'}D(& ?JD1$D@'P D=& 2DIDWDP]~DaDDf``:>IDoDuDs&ڃ^7 +JD|$DD&?JD$D'}D&=FZFaH.AFiH.`:> NFyF{!`:F}/F.HNFF`:F2F.~INFF`:F2F.|JNFF4`:F2F.KNFG`:G2G.LNG#G'P^`:G)2G4.MNGHGK`:GM1GZ.PCNNGsGv`:#GGx.PDO('G1G.PDO`:IGG.+>JG$GG&r'yG&'yG&'RG&'G&!'G&M'%G&{G&'D>JG$H$H&r'yH &'yH&'RH&'H&!'H&M'%H&{H!&>KKN'LN`:> NLL!`:#"L"L.H^L%7WL3L..Hv7L>/LJ.HLR0L].H`:NLoLq`:Ls2L~.~INLL`:L2L.|JNLL4`:L2L.KNLL`:L2L.LNLLP^`:L2M.MNMM`:M!1M..PCNNMGMJ`:#MXML.PDO('Md1Mq.PDO`:IMM.+>JM$MM&'yM&'yM&'M&'M&2'M&^'%M&M&'D>JM$MM&'yM&'yM&'M&'M&2'M&^'%M&M&?z(t`{`>JX.~(Wր&+.+@~P_(~ t`{`>J0@XRK.~(y]T&+t.+A (s``{>Jk.~(y〠&~(3fP`~(f `~`*|`3`C`O`[PC`lPD`~``>J&&&&&Ä&Ѕ&"&W$.F&\&`D$ ($`J.~(E):aPH:(Qa`JT[T.~(h7FkPa(`:>I.+J'Pb?J.GߞuPc(u`{>I +.+J?J,3P.Hfww(|`J.I~(`J.Jԡ|(`J.K:(:`J!,.L?PuP(Wu`JZe.Mz(`J.NƢPCơ(Ң`J࡚.O PD (`JP 1W{1(9W`J<G.&&& +& _& & f& & 9& &&&&{&&&?&&&s&&q&&&&o&&&K&&&&3&o&&"[pu(`]Pd`[((h^Pe`[(?(h_Pf`[^Wj`1Pg`[(a]Ph`[(z\? cs``[dфW҄s``[eys``[fDT`hU`Zs``[geuv{s``[hs``[iWdqfqks``jW`[kކ\`[xˇևUڇ`[l`m`n8J7IU&#偒]&#vnP$(6`:`[>J&$[& & & &!&!S&!&!&!&"&"<&"c&"&"&"&"&#&&#M&#t&#&#&$4&${ Pi`] +`{}MPj`7~Pk`7Pl`7<Pm`7<Pn`7,Po`eJ}hg~Pp`hPq`h=Pr`fRhhPs`~hPt`h5Pu`^Jh`Pv`hPw`h +Px`)h+Q`{ ^ Py~` 'Pz`:`N`d`zk`P{`\? +b4h&'Wh&'W*h,&'WXBhZ&'Wp}h&(W&(.4ZP|~JZPPy`\?&) 4ԑ.WՑ.s`{`{>J.Py~W &)lPy~ys`{`{>J.Py~y&)Py~"4h5:``{>JHSuk.Py~hw&*[ZlqnqsP}``{>I&*(=0?J5@aW.Py~d&*ܕs`{`J.Py~&+cPy~ws`{`J.Py~wǀ&+Py~GUvWas`{`Jkzp.Py~v}&,9Py~K^K s`{`J*9/.Py~^B<&,Py~P~`J.Py~]ePm`Jpzp.Py~"*bP4b`J7A7.Py~M+P+`J +.Py~+͜`J.Py~}U]xPlx`Joo.Py~͜۝<(ݝ<s[`>I!%&.`{J*?J&.Py~(/)&.Py~AIgzRg`JU_U.Py~z(,mx5m? s`{`JISI.Py~xc]&/Py~ȣAУ`:>O٠Pa``:``:>I&08^7J +$&08?I#!&08^7J-$9'}7&08?IAGE&08^7JP$]'P [&08?Ieki&08^7dJs$'P &08?I&08^7 +J$'P&08?J$'P&08OʡPa``:ڢ``:>I&1k^7 +J$&1k?J +$'}&1kI#6'.P>JC$U'yN.W?NhxP`:z&1I&.P`NP`:Ё&1I&.P`NP`:"&0&22#.P<`JY$b.P'킣k&1'탣|&2A'%&2DMhXh`J[e[.Py~09m\I0""%;4&4`%LE&4`\+(_&4>Jo}v&4A?I%&4`:>J&4`:?J&4sP~(3`:`:>J`:'9'P&5nP~(na``:>J&$j'P=K_&6'-Y(-`J7.&4&5v&5&6B&6{AGP` ``+\?&6 ӎڎA`:J'P&7 &7<JPr`\? &7ƏP`\? &7#lP`\? ÁELjATj`:JZ'P&8%&8TƁ/P`Ɂ P~`ʁ@ [ˁ K`:́ [ԁ)͓)[+\?̀&8+*+ ՁGGKZ[K[hK`:+s[+\?ˁ&9Ĥ&9Uʀ&9?) Gց&-K`:+\?ˀ&9*'P+ ρҖݗP~`:J$'P#!.P~'P'`:Ё&=P~8=`:J;'ҁBI-AQ-`:>NalP`:'Iv!z.K(+B>=&:$'.K'?N`:#.(+'$'.`:N`:$( +.P~π&: &:I.!3.P~J>E&;IF"PJ&>R&>d^&>wf&>>=0x&>&>&>&>̄&>?ၡxP`[K`:+(`+`:+\>I&?(+=&?& &?(`?If"lwn&?~}w&?~^&?>I&?(+B=&?'?=0&?~&?&?&?&??⁡6APPU``y`i(`P`:+P`:+`:+`>I!"'w)&@82&@w:&@>IJXN&@(+B=a&@'?=0|&@&@&@΅&@?I!Ё&@(+>I"뀪&@w&@&@w&@>I &@(+B=!&@'y?=0:DU&@Z&@a&@i&@ޅr&@?J&@?J&@ち*P:?K`NK`:+[`:+\>Ikuo&Br=0z&Br+&B&B?恡ǬP~Ҭ`:J'灡rP~r`:>@.P~ɭN&2P`:'I<F@.(+>IW!_[.y(+>=r&CX$'P.y?I.y(+>=&CX$J'PD.IW_[.yڃwa.>=p&CX$'P.'.y'PI.yڀ.>=&CX'P>=$&CX$P'PJ.J\c&CX&> &>&?\&@&BP&B&C&D쁡PVHP`` [9 (``[K`:+`:+(`+\? &E8&(#!2+&E\(+=&E\PF&E8([` fl&E+z&EA#!&EN(+B&EN'P`:񁡳`J򁡴 +y`J.(y􁡴 +EP~6E`:J9'ITFP~fF`:>@s.P~ɴs|I&.ʀ`>J'P?I.((>J'P?J$B'P;.(&E&F&&Fi&F&GLflPl(`\? T]~](u}`:`\? ]A(`:JA&H&H@FLPL(` P~`:`:\?&H DA( D`:J$D'P8.P~'&H&I^dPd(` +S ~`+ m P~`+ 9~],[+ P~][`[+ P~],[+gpPp(``\? +&I &J + $&J +  ^S&J + + pb( 'Pb ``3 ],[] ][`[yP],[+\? +&J &J &J &JM&J DhA(Dh`:>Nƿ`'NP`:'I!@.9~ (+>F@@9@!3[@-.9~ >=@F@C&K@L&K=@_@\&K@k@x&K=@&K'?I@!@@.P~ (+>=@@.P~ 4@@A@`@K[`>=AA &KA&K=A'A$&KA-A=&L=AOAL&K'=AgAd&KAsA&L=A&K'x?NAA`:AA.P~ NAAP`:BB.~ +NB)B:P`:$BAB>&KIBGBbBK.P~(+>JBs$ ' B&M'P'PB&M'X'PB&M'>NCC0P`:CIC2.P~'JC[$'P'PĂC&M'P'PC&M'X'PłD &M'фD&M''PƂD@&M'хDL&Nr'&KP&O@EP` `:@ @ @`:\?&Ou @ @@CA@@C`:J@"$@C'P@;.&O&OAABP``A `:!AAB BB B`:+\?&P` AB$B+BAB3B`:JB9#!BGB?.(+B$B|'PBm.'P`:&P&Q"C\CbCP`$C `:(CCCCCC`:\?$&Qq C&CCCACC`:JC$C'PC.$&Q&Q)DDFP`+Eq P`/EEEEEEP`+\?+&R[ E-EEFAEF`:>IEEE.P+(+>JE'P?JF5$'PFzF.P+'%&R&S0FFG6P``6FFFFF\? F2FFGAFG`:JF'P4GG"G4YG-G4`JG0+&S&S&S7G9G?GP``=GgGmGGG\? Gm9GGGAGG`:JG'P;GGGYGG`JG+&To&T&T>HIJ.P`@I9 P`:DIIIIIwIbIwIiP`:+\?@&US IIBI{IJ,AIJ,`:JI#II.P@(+B'P$J,'PJ.P@'P`:&U&VEJJKPJ(`JJJJJJ\? JHLLLB~Lá(LLLS[[JL0LԀL&V&Vs&VKKuK{_P`l\? NKKKP~KKKl`[>JK"""%KK&WP`%KˀK&WP`:%KڀK&WP`KK&WP(+OKKLIP~L LILl`[>JL""%L#L!&W`%L/L-&W`:L>L<&W(+PLNLNLP~LZLLbl`[>JLk"%LtLr&X{`LL~&X{(+QLLLP~LLLl`[>JL"%LL&X`L€L&X(+RMMNGMNGMj`Mk`Mb`[>IM"!&MM.P~N&YaN`!&NN .P~N &YpN`=N,N%&Y?JN4N>N;&Ya(NA&YpSNLNLNPNUNN]j`Nhk`Nub`[>IN"!&NN.P~N&ZXN`!&NN.P~N&ZgN`=N͂N&Zv?JN!N߀N&ZX(N&ZgTOOPPOPOl`Ob`[>IO!%OۀO&[P`=OO&[^?JO!&OO&[P`UPPPPPPPj`P#k`P0b`[>IP?"!%PFPC&[`!%PUPR&[`=PfP_&\?JPn"&PuPu&[`&P{P{&[`VPPQPPQPj`Pk`Pb`[>IP"!%PŀP&\`!%PԁP&\`=PP&\ـ?JP"&PP&\`&PP&\`WQQRSPQRSRl[Rb`[>IR!!&R%R&.P~R3&]Q`=R>R7&]?JRFRMRN&]gXRXRXRPRbRRkj[Rwk[Rb`[>IR"!&RR.P~R&^9Q`!&RR.P~R&^DQ`=RƂR&^O?JRR؀R&^9R&^DYRRSmPRSmRj[Sk[Sb`[>IS "!&S$S%.P~S2&_&Q`!&S9S:.P~SG&_1Q`=SSSL&_<?JS[SeSb&_&Sg&_1ZSrSrSPS{SSj[Sk[Sb`[>IS"!&SS.P~S&`Q`!&SS.P~S&`Q`=S߂S&`)?JSSS&`kS&`[SSTPTTTj[Tk[T*b`[>IT9"!&T=T>.P~TK&aQ`!&TRTS.P~T`&a Q`=TlTe&a?JTtT~T{&aT&a \TTUPTUTj[Tk[Tb`[>IT"!&TT.P~T&aQ`!&TT.P~T&aQ`=TT&b?JUU U&a텹U&a]UUV`mUV`Uj[Uk[Ub`[>IV"!&V V .P~V&bO`!&V&V'.P~V:&bO`=VFV?&b?JVNVXVU&bWVZ&b^WvWvWPWWWl[Wb`[>IW!&WW.P~W&cP`=WW&c΀?JWWрW&căW_WWX_PWX_Wj[Wk[Xb`[>IX"!&XX.P~X$&doP`!&X+X,.P~X9&dzP`=XEX>&d?JXMXWXT&doyXY&dz`XdXdXnXiXXrj[X~k[Xb`[>IX"!&XX.P~X&eZP`!&XX.P~X&eeP`=X͂X&ep?JXX߀X&eZhX&eeaXXYmSXYmXj[Yk[Yb`[>IY "!&Y$Y%.P~Y2&fEP`!&Y9Y:.P~YG&fPP`=YSYL&f[?JY[YeYb&fEYg&fPbYrYrYPY|YYj[Yk[Yb`[>IY"!&YY.P~Y&g1P`!&YY.P~Y&g<P`=YY&gG?JYYY&g1Y&g<cZZZPZZZj[Zk[Z)b`[>IZ8"!&Z<Z=.P~ZJ&hP`!&ZQZR.P~Z_&h)P`=ZkZd&h4?JZsZ}Zz&hwZ&h)dZZ[ *Z[ Zj[Zk[Zb`[>IZ"!&ZZ.P~Z&i P`!&ZZ.P~Z&iP`=ZZ&i?JZ[[&i [&ie[[[P[[[&j[[2k[[?b`[>I[N"!&[R[S.P~[`&iP`!&[g[h.P~[u&jP`=[[z&j ?J[[[&i^[&jf[[\)P[\)[j[[k[[b`[>I["!&[[.P~[&jP`!&[[.P~\&jP`=\\&j?J\\ \&jv\#&jg\.\.\P\1\\:j[\Fk[\Sb`[>I\b"!&\f\g.P~\t&kP`!&\{\|.P~\&kP`=\\&k?J\\\&kЈ\&kh]d]d]P]o]]wj`]k`]P`]b`[>I]!%]]&l`=]]&l?J]#&]]&l`]&l̂]&l`i^d^d^P^j^^rj`^}k`^P`^b`[>I^!%^^&m`=^^&m?J^5`^&m#^΄&n(+^&m&n`j_y_y_P___l[_b`[>I_!%__&no`:=__&ny?J__Ѐ_&no(&W &W&XK&X&Y7&Z,&[$&[&\&]b&^ &^&_&`&a&b&c&dC&e0&f&g&g&h&i&j&k&l&mb&nC&nm*9P`oGOX^[+`mJkovz&o&os&op̓ӄP``mr [v ##[+\?r&p  t(/A7`:>I@LD.r(+JU'P?Jm$'P.r&p<&pwP``my `:z 6[{ e`߉##`:'6[+e`+\?y&q"z&q1{&q; }A`:>NP`:'PI"!.y(+B!'(.yB>=&q$&q' .y?N#*e`1.e{I=!%HA.6z`:>I\!g`&r(+>=z&qz&qW$'P&r'G?J&q?I"!΁&r(+"၍&r&rw&.6z(`>= &r+?IWb[&r(+>Nz6`:&z.6z`:I&s (^w7N>=&s Ȃ&s X7KHW'HG?J$ &q'X&s ?N!P`N.8D`NFXP`*Eenp`wu&s倇y&r&s&sW>NM`&.6z&s`I&t/(7 +>I"!߃&s(&s!&s>=&s&sW?=$&s20&sW=?&s*Igpk&t/(7 >=&s&sW=&s&sW=&s)?I邐&sw>=&q&qW$<'P &s'P4(!&ry*&sW'G>=Q&qXQ&qW$|'Ptm&rW'GNQ`&.6z(`AE`&r&v$&.6z(`&v$҆&v$W>NM`&.6z&v$`I" &v(7 +&v(7 >=1&u;&v$BF?Ncj(`tl&uyv&sN`&sNy`&uN`:'N֒Q`:'I&vw7N>Nio`xq&ryz&sI&w 7K>=&w>&w(W7K=&we +'HI&w>y&r7K>=&w( +&w>y7K=&wT 'H>=&w(&ry7$=&w>&rW7$=&wT &we +'H?N`:&.6zX&w(&w>`:N(Q`91*&ry3&w(WB;&wT (^JN$W&q^&wT e&x k&we +'Xz'Rh|&x L'Q&q&yٕߖxQ``m=;=\? AHvAPv`:JV'Q&y&zQ(`[`Q~`:'Q>Q~`:'Q wQ +~` K`:+Ë̡̋(ӋK`:+\?&z m~ +`:>N`:&+.=`:IV^Z&{1(+B>=o&{1$'Q 5`5`&{W&{=.&{1?J&{1+2OA:O`:J@$O'Q J.K(a`_>N*1[>J&|GRJo&o#~w&|\(++&|\.m~[_Œٍ١(܍a`K_\>N[&|'IDOH&}(+>=`&}i=&|&}?=Ρ&}.m~&|&{&{&|#&|&}(`\? ^zWQ ~W ][`[][`:[>Nъ][`:[2`:[=&~"4?`K[`>=&~G(&~3&~nxJFM&~GHXYX(]Yg`o ],[ ][`[+[>=#ˁ&(+ʼn&1[+],[I"!0!&"(+J;&"C>Nbf[h[''J=|&"4`[`>=[''2&&&xJ&&&?J,3>&A&owz`(s``&}&~&]&&+t+(`ސ摵 P%(K`: A`+`>=0SY'Qs`` k s``s``g`=J]L]QO``O``Z^Ddi `wE``HLcJVc[E``04BK7B<s```Гٓޓ`'?''`EI^<S^X``=``|W`"\ "`ǠUˠ```;?ECE`cgqoq` +`[١`[-+-`[V]omo`[?FPANP`:qxD``:ːWyˡ(АW6`:`+~ba`:6`+`>J!3<&0D&>K&L\pP$p(x6`:`+`>J&&&&P&&&&&I&&&&(&O&v&&&&,&S&z&&&&&=&d&&&& &&ˁڍQ`Á~[1[Ӂ\?  Ł˂Ӄ7䃺` ]`H ][``+`Jbf&+&&1Ɓ08LQPLX`} ]` ]` ][``+`J &&(&=&ǁA<K``=5[ȁ5=A>NV`i3``=5[ʁƈЈ`ˁ ],`J:`́_q ],[́:Sa aa][`[΁`ρ$-5"55`Ё #`сW`Qk`Jn"n."z.#&&v&&\&&&&:&h&&&& ԁύՕ9Q``ց `ׁ' ],`ف Q~],`ځ Q~][``灦萐7`:]`9]`Y|][``\?ր& x`&5],``&)#&(+:`&],`#"&<(+'!&< ~;>``ic``&<][`` 聦<`\?ր&x:`++ 遦>)/`B3`\?ր&:d`3`1[&+ ܁ϑ ],[J5],`.Q~#&y(+:`&y],`݁5i Di][`[JG5][``G.Q~#N&(+;Q``&][``ށnw`J!.Q~(+߁"`J.Q~(+ʒ#Ӓ`J"!.Q~(+.Q~(+ၦ$Q$`J.Q~(+䁦asQ~:],`],`>I&(+J:`?E֓`߁&瀓&(Y&&W>I &&9(+>=0&$y'Qv&'%?J&偦7Q~ƕ7`[ ]_],_>I&(+J+?J +3_*&&K&&S&&&H&&&2ꁙUd^1f`[`큙d~[1[  + \? "TTf`[`Qa`_+]_>I&vJ_?J)_?&F&IJf`[]_=5[5i_+򁙕m`[`[6]_]_J̞y__&  +]%_󁙜ݜ`[]_J__.􁙞' 1> s]_]_>IK%T.]_>J{'_&.]_&?JΠ2_.&`[a_l_]_JП@__.&_7CHNa_`]_Jbfq_.}&JVb`[]_JhlO_.(v1v`[>a_]_]_JUY__.t&aLQnYa``>Fpwl_.>I&(&J)?J*.3z:z@a_\\>FT[_.=ml&0n&JQSY\ a__K__>N +]%_. + I!&'>=0\?NK_&')C-$&'>=A&PI&Q&aX&')Ju|&㴓괓`[ _a__ __>N,2K_4&FFM_.=^&mf&n&u&J&z=a_``>F_.>I!ʀ&/&RJ*?J)8?ECEL`:'`:>Nox +]%_. + I!&'J'?N÷`I"&(+B&('B>D>=*#&$E<3&')`W&'>=&$&')C&'>=؂&&=&$ &')J)70&A',-/5a_``>FLdS_.>Iltp&Gu&jJ)?J*^fls`)],_>J0_.؀&+2R7R]_J=Ai_. KS(Z`>@!%l.][gN`N]%[. + Cǁ&{'>=&k&kWJ&k `J!. + '@o@x@C@@`J@!@. B +BBWBBWB`]_>JB,B7_.BM&DDDmD#DmD)a_K`]_>JD>DI_.Dd&GG)GjG-GjG2`]_>JG?GJ_.G`&VIIJ+~IJ+Ia_K`]_>JIJ_.J"&JJKKK_>NKK]%_K. + IK*!K2K/&.'>=0KFKa\?JKxKK&.')MMMM M_>NMM!]%_M#. + IM1!M9M6&Α'>=0MMMh\?NM_DM>=M&#MM&΂')MM&Α'JMM&#NNOkNOk_>NNN]%_N. + IN!NʀN&'=0NN\?NOO _OO &')IOO$O!&'=0O0OK]?JOZOa&PPQ PQPa_`P !a_+_>FPQP_.>IQQ Q&Q!&JQ+Q2&?IQE!QPQI&(+JQYQfQ`&?=0QnQ\TTUuyTUuT#a_`T7 !a_+_>NTJTQ_+NTbTp`*FT}TT_.>ITTT&}T&>=T&T&=T&)?ITU&JUU&?IU"!U-U&&(+JU6UCU=&?=0UKUf\W2W4XW?XWEa_`WY !a_+_>NWlWs_+NWW`*FWWW_.>IWWǀW&€W& >IW܃W&>=0WX]?=X3&X<& =XM&)?IXuXy&JXX&?IX!XX&(+JXXX&ڀ?=0XXߠ\ ZZ\Z\Z`_>IZ!%ZˀZ&)`=0ZZ'?=[ [&)'N[7[D{`F[M[e[T_.>I[m[w[q&)([z&J[[&?=[&[[&W=0[[[&).'+[& +^^^A^^`:J^^C.''&&u&&4&_&&4&&&6&&&o&d&&&'&&&1&&&\&&,&&&&|&c&S&&&7&"^_aQf`[]__i (`_ Q~^`~_`@`@a'`Ra'`X(``bQa`_\?&#!``&(+Ła&&aa^`~_a`_ `@a,a.aa7aa<`_>=aTad&m.Java}.Q~a&maaa~aaa``Jaa&&C&& b:bIcQQf`[`]%_$\? "c<cAcOQcMcO`&&%f`[`+\? 'ƆΆ`)ÈɈ'Ј_&&6&[,Xg^~g(f`[`]_*.r(rf`[=`&`],_>N[Iڜ`'g'Q&>=&[''>N3:(`<`'3'I&IY"e]&(+wp&>>=0$'Q&?=&㜣[''G,&>= [''Q &=5'C&JTT#_i&/tQ(tf`[,(`_`*],_>N֦]!_۝#_뜣[''G,&J=[''Q $&*&\I5!:&h=L'Z&?Jel&0<#(<f`[ ][`)],_>Nɧ]!_Ν#_ޜ[''IH%UL&/]_>Fmvl_{&/]_>=&Z&,>FϨl[&/>=ނ&Z&&_,I!&?='"&Z?J-4&Z1u}f`[ ]_`)],_J0_&e؁&w2muf`[(`Qa`_`)],_>N],_Iނ&>=&5],_1_5[&B( &W&B>=(&5._=&EPY[`b`&d&l&ml&W>=y&&&&:J&3JRR(cf`[m ][],_>N],_0_&X=(&uJ&u5=#&(+&+`=&&&ۂ&o(YN(`&y&I +&Q(Y&bW&>=0/9M&Q'c$'Q"&'Q#&b?I"!&o&Q׃&^&b>E`&Ӏ&&&W>=&Q&bW&("&o/)&W1&9:>EPY[`]&ig&~eg&~y^>=z&Q&bW&~&o&W&~9:7gsQ$`[c],_`6]_\>=&[䀢&J(Y'N`&[N`%&J(YF1M:_E&h>IU_Y&(b&>=0z&&J?=&J&&:=&؃&W83;DBD`[],_9ȦӦզ`_:lz}` K_\U7@NENH K_\V  K_\Y(`W(`\;LQ]T]W K_\INf Uf^`+\?MQtXt[ _i``@ٵݶa_```Alp~a_``+`BU _`+`C \DPUq[q``i _\E` ]_\FAyA~AAAA`A ]_\GDD DDDDK``HEEEEEE`_IFXFZFf7FdFf_JGGHGHHa_`\KIIIIIIa_`\LK'K8KHWK9KHKB s],_],_MMIMQMnMXMnM]`Miy`+],_NPPPPPP`Py`]_OUUU UUU`Uy`U ]_U`\PWWWWWW`Wy`\QYYYYYY`Yy`Y _+\R\\]\]\`\y`] ]_\S^^^^^][`_&&&&:&&(&&$&&o&&&&>&l&&&&%&P&&&&F&&&&.&o&&&<&k&&&:&&&O&&&Q&*[.OB.(`[`[`^.~[1[`abdef`w`[`[][__=5[F5i_+5_+a=EsA#Ms`[`[Rs][[[][__=5[^5i_+5_+b}A`[`[s][__][__=5[_5i_+5_+c i (i`[`[!s][[[][__>J.5]__N^__^&WdA`[`[][__=5[]5i_+5_+eAe`[`[][a[_Ka[_][__=5[`5i_+5_+fMUAf`[`[s]_]_][__=5[a5i_+5_+ilm/l`[`[3`[4`[:6][__][__JKO____e&†g19Q%H`[`[b2]]__][__Jt5][__2z__5[~|&-1&p&-j`[`[][__kej5wK``lFKbVb^``m`_nРޠ _ K_\z"?F2FF]]__oȡӡ3`[4`[a__ˁK]__][__p$)X13XM ]]__\qFF _& a_K_: a_+_rۥ7 a__ˁK_\s]bms1a__ˁK`\t   _ a__u s][__\v`_wW\c ac\x  a__ˁK\\{]_|]_}(`~LU\ \\`CƱ`&&&&&& &&:&&r&õ&&&N&ć&Ļ& &]&ů&&'&e&Ɯ&&&*&U&ǀ&ǧ&& ``[`[`I _ K_~[1[ ,p~,_&K_\?& &  ȲֳI޳`[`[_K_]__=5[5i_+5_+18^A@^`:JF$^'Q&Q.'W.K'&I&&(`Â#Q'~ׂ#`>=0'Q(؇z(`JzlsA{`:J'0&M&ʐ&&D`] +`\? ( ( s``t|z`.2Fx;F@ s``gtWuzs``ys``hs``Q^j_jds``s``[Дݔߔs`` W`)-A6A;s``n|}s``̖vΖs`` #w#s``\jw^lwqs``̗՗ڗ`nw```\`8@DUDD`OSZXZ```jnxvx`^et +rt`[ry`[`[ `[  ```04;9;` *(*`[")L8L=``:`+`:Ҷٶ``:\cmAkm`:AAByABA`:AA~ba`:`+`>NBB$`B&B/&IB;!BFB?&!(+JBOBV&!?IBbBnBf&(+=0BwBB&?JBBB&B&CtCDBP$CDBC`:`>NCC6`:CC&zIJD5`DD&#D$&J(+D.vD7&&J`DnDyDQ)~DDDp`:`JD+DDDQ*~DDDp`:`[JD+&Z&ˍ&˴&&&O&̃&̷&&&E&y&ͭ&&&I&p&Η&ξ&& &3&Z&ρ&Ϩ&&&&D&k&Ь&&&.&c&ї&ѽ&&Ӡ&&8(Á7=H=(́#!#\?Ł,Cf(C(EfFs[`JPP.`&BɁk|z|(`J .ƁA(`:J$'Pך嚲.'ǁo(o(`[>J:A.`&ʁt$(`J.&&i&ե&&?&ւ́)8Q+`\? ρBX"B*3`:7`]`Ёr3`: ``&&+&mӁwQ,`\? Ձي`ցHPSySS`ہAHX*MXR*``:܁""*``:݁ЍݍsQ-],`],`:ׁ *r**`؁mx}}}`:فƏr͏`&&&&D&w&ع&&&.Q.(`` ⁚#++(196`:Q`*iT`)`J&٤&ٲT&䁚*.(*`:`:JU%&偮Ԉڈ`:`恮X`:`]`灮7JLTL[7Lq[''r A`:&%&n&&"(Q2``a ~`:#pp`:\?&f p!A`:J.~&&$/5;Q35(`'Q4~`+(QH~`)cQ5~`9iir\>I{'(+=6? i +J`J'29>C\>IL!VP.Q5~)(+>=.H~.H~(W7y.Q5~)(=.Q5~+)?3Նچiކ\>=#.Q5~)(+.Q5~7)+`4sx+}\>=.H~5`.Q5~)#&(+7&`(, IQ6I`>J$=5`,.Q5~)#2&(+57&`y?.H~(-j`{>JP{.D..6>DR`>JXxm`.Q6,h7B@{.J+/Ԋ܋##`>J .Q6,h7.J+0gpQ7z`J}}.Q5~)(+6Q8~(\>=ҡ='}7'HPL~'(+H`J1&1F<~`&&&z&&X&&,&&&<&& :͌UA9ܡ(`] +`:`%=vQ9~[`Q:``:>NV`&&`(`Ny`"&i)&v4&I>"HB&iwSO&관U&>=b&`ni&`v&i}&?J&&`]!`>ϯQ;~`8 +`Q:``:>N*.V`:0&눁(?NJNy`[k&듂r&렃}&J&눁&듄&?үQ<~ ]``#y``:>I.82&_=0=NT&_h^&L( ?Iu"!}y&l(+&l&_>=0&l&_ʀ&L( ?N]%`&L + E `&P&_&P&PW>I&!.+&('>=0DU[&_e&P?N],`1`I&l(+>C&('=DŽ&Ӏ΃&(');>E`&_&K&l&K &KW>I!&('>=07HN&lS&_Z&K?=up&Ӏ|y&(');J&&]!`ZĬQ=ġ(ج]`` y`+`:>I%&&F]![>J:A=T&F_&Yf&g?Iv%z&F`8>J>&F`8&Y&g?J?&F&Y &g[!)Q>)(<A``:>JQcv&>\q P%(qK`:A`:+`:>=0 'Q?@BR_T_Y``:A``^(`_^fnznn`B̝(Νs``CZ_uguos`:`D1R1r`&``E$$r``+`F"KU-K6r`D`+`` `aצC`Gm}W~s`:`:HX`r`+`:I")/z-/`:Jp`:KHOZtXZ`:Lgwhx}n``:MJQ{.X{]`l`:'R`:NCJu6RuW`f`:'R`:Ons```PݺZ#``:``:Qؼ߽8_8#` a`@`:(``:R\cmv#` `:`:SCCCCCC#`C a`@`:`:TEuE|EEEE`Ey`E`:`:ULLLLLLr`],`:VOOP[OPOr`O\a`@`:+O]a`:^`:+`:bPoP}PPP],`cQQQ,QQ`dWS`SgSt!SrSt`:XU+U2U?(U=U?`:&:&b&&&&&h&&&-&T&{&&&$&f&&&&)&k&&&&&W&&&,&&&&}&&7&n&&&%dUUWQ@]`fU 3`:kUUUUUU3`:\?f& UhUUV +UV`lJUUV.3fiVVWV!W`>IV'V9V2V+.3f(^(>=0VGVQ('QA?NV{V(`VV.3f(^NVVQ`VV.3fVV&yAIV"VV&&VVV.3f(^w>NWWQB`WW.3fW+W$&yAIW7W;WL&>JWeWlW&W&&??JWW&&&2&&MlYYm1QC`] `nZF 3`:pZg~`qZQD~`r[yQE~`+[[\@[\@[3`:\?n\&pq []]^]^]3`:]`\>=^c^x&^^&(^=^.QF~^&un^&p^-&q^L& ] u__ +`!QF~_`!_#`\>I_0"""_:_4&\w_O_I&\_X_Q.3n(^_j__{.3n__&\yA___.3n_&\A>=0__$`'QG`&\?z```QH```J`#!``.g~p(`.QD~q`.g~p+`bIbRbQHbZbb_QH`\>=bzb& b.3n'QH=b.+b& v=b.wvdjdoeF+dteFdzQH`\>=dd&dd.3n(^'QH=d.QF~d&u=e.g~e .QD~e&qp=e*.QE~+r{eee'ee`Jee.QE~r|fkfsfQIff`Jfff.QD~qyf.g~p}gghJQJghJ`:>Iggg.g~p(g.QD~qJg+?Igggg.g~pW(g.QD~qJghg.3nh.g~p@?Jhh#h.3nXh-.g~ph8.QD~qHwhOhTjh\j`>=he.g~hq.QD~qpIhhh.g~p(hh.3n(^>=h.QE~+rJh*?Nhh`hh.3ni.g~pANii&FX`i2i(.g~pWIi;"i?iP'iji]'isil.3n(^>Nii`ii.3ni'AIiii'>=i.QD~j i'Wq=j.QE~j*j@'ׂjJ'rJja)??=j.QD~j'q=j.QE~j'rJj)xjjm/Qjm/`>=j.QD~k.g~pqIkkk.g~p(>=k-.QE~+rJkM*?Nkikr1`k~kt.g~pyNkk`kk.3nk'*AIk"kk']kk'*w>NklQK`l +l.3nll'*yAIl*l.l?'>=lX.g~lmld'*yp=lz.QE~ll'́l']rJl)??=l.g~l'*p=l.QE~m']rJm )&,&_&&v'K'''('' ́҅QLҡ(``QM~`:+?(?`'\?$?7'c  glQN~xy[\>=.QM~.QM~&'`:ɸ׺QO~3`:][ `:`:>N#, +]%[6.'6 + ID!RI'\'J^e')?Iqu'E `>D>=')')'\')ヹ'\'>=') ')''\')C7G>'\'>=]')fp')x'E=')')'\')J')VQP~V3`:``:>J-C' $QM' DUo(U(\o`J_i_.QM~(^PYo ao`Jdkd.((փ߃C`J!. t(`\>=.QN~$' +ŷš(ҷ`\>=.QN~[' 8))(1;][L`:'\>=c.QM~oy.QM~' ' ~(`'\>=.QN~$' 'X (\>= +.QM~'!1bA1(9b`:J?JX.QM~''' ' ' +D' +' +' ' q' ' M' ' vQQ`\? {`\  ][`:'\~`'\TYtftk`\' O' ' ' '!1@* `QR` 'WJ` '@~[1[hvI|K`:`=5[$z$$`((!("s[`''' 'O*0`\? 'RaWQSa(`a~[1[3DDE4D(DE4`>NDDM`:DID!D׀D'F(+BJDDD'F?=0DE'QT́!A! ,`:AQU`:X`:h'`{`:o]`:`:N][`:[`:`=5[ ́(0A8@QV`:RQW`:|N][`:`:`=5[ +΁RZAQXckQV`:}QW`:N][`:`:`=5[ ρA`:``=5[ ЁUA'U/`:;``=5[ сRQYR`:1k`:+J`+n~][`:`:+`*`>N`^j'k',':~'F2'_J?KF'vMxҁ+3uQZDuO],`]k['ఝ~][`:`:+Q[[*`>Nհ`^k'k '~)'Q[M')Jbni'>Mx\gmmm`:CNWQVWW`: QU`:`:'``:q|`:#+++`:o],`:N][`:`:@E@c@uQ\@u@u][`:],`:AAA(A(A(`ApAyAQ]AA`JAAA.CaAAAQ^AA`ÁCCCQ_CC`āC^CgCoCoCo`ŁCCCQ`CC`ƁDDDQaDD`ǁDtD}DQbDD`ȁEEEEE`:ԁGGGQcGGG`:`ՁRRRRRR`+`:ɁSSSSS`^ʁTHTPTXzTXTX`ցTTT(TTTs``ׁU UUAUU`:؁[["\' [)\' [9`:+[NQU`:+[e`:+[u'`+[`:+[o]`:+[`:+[N][`:[+\`:+`ف\\\Qd\\`ځ]]^]^]`:`ہ`O`S`l`]`l`b``܁bbbQebb`݁cchychdM`:d`d y`+`>=#ll'(+l'll'(^+`Ilml'^m m'W7>Nmm$Qf`m&m6'm;'ImImWmM'0(>Im"mm'wmm'mm'(^=m'mm'Xm'm'H?Jmmmqm'7+MxInnn '0(7 >Jn(nfn7qnBn>'XnRnL'W7nW'H+Mx??Noo],`o.`7=5],`p`'5[pppn'؀:5[pp~'؀ppp'y:5[pp'؀ppp'y:5[p̄p'؀p pp'y:5[pp'؀p q':5[qq'؀q +q(':5[q6q4'؀q7 qK':5[qWqU'؀qX qo':'Nq|qM`qq'q'q'qq'Ir?rIrC'^rL>=rpri'rq r':?NrrQg`rr'r9Irrυr' J^r'>=s#'s+s1's6's=' JsHsV'Isfspsj'(ss>=ss's s' J:??NuuQh`uuu'u9WNuuQi`uău'u 9NuuQj`uu'u +9Nv vQk`v!v'v" 9Nv=vKQl`vTvM'vU 9Nv`:Iwmwwq'"" +w'! =w'! w'"" +?Iw"ww'!w'!?ww'!vw' J>=w'!w'! ?Ixy x'!y '!?=y'!y"'!?@"yCy9'!?(yF'yYyO' Jvy\'!?y9ye@y}ys'!?vy'!ysy@yy' Jvy'!yy@yŇy'!vy'!yy@yy'!vy'! yy@zz'! vz'"" +zzNz,z5Qm`zPz>z7'z? 9zR'Iz^zb'$z >I{/{={3'!?w{I{?' JW>=|'$z *I|;"|I|?'!w|K'|b|^|T'!W(|e'!>=|'$z *I} +""}}'! }'"}<}1'! (}I}?'!W}f}b'R'}w'!D"}}'! w}}'!W}}'R'Qn}}'! yD>='$z *>I' J('W>Igok'R''D>='"W 'IÆ'!?v'> NWbQo`:'Ni`I!'R''!D>='' 'Qp=''7?=#'4)'' W:6'XD'!O'HG=c' Jmc' Jyp'='!?7='!7='!7='! '! W''7y'='"" +'"" +W''7y '=5'=N'XT'(^Isw'!('! >I"'('('(^>='%!'2'!='! 'T=_'! j_'! W='"" +'"" +W=''W> ='$'X''!H''X&'! 2'H=J' JTJ' JyW'=n'!?xn'!?y{'='!'!y'='!'!y'='! '! Wꔃy'='"" +'"" +Wy'=/'=J'TP'(^?I'R''D>='"W 'I""('!w*'QMC'!W(T'!uq'R'Qq'!WD>I"'('(À'(^>='''!'!'T='!)'!y=?'! J?'! y=`'"" +n`'"" +y=''y> =''X''!HW'X'! +'HG= ' J* ' Jy-'=D'!?ND'!?yQ'=h'!rh'!yu'='!'!yW'='! '! yĖW'='"" +'"" +yW'= '=$'.*'(^??Io"}s' J('W7'R'QX'D>='"W 'QXI""$'!w&'KG='!W(N'!mi'R'Qr'!WD>I"'('('(^>='܀''!'!'T='!'!y=0'! ;0'! y=O'"" +]O'"" +y=q'uq'y> =''X''!HW܀'X'!'HG=' J' Jy'=''!?1''!?y4'=I'!SI'!yV'=k'!uk'!yzW|'='! '! yW'='"" +'"" +y˗W'='=''(^???IDH'$z >IZ"d^'wok'uq'(^>=''X''H=' J' Jy'='!?ֆ'!?y'='!'!y'='!'!y'= '! + '! y.'=='"" +K='"" +yN'?Jcny'~' J'!?'!'!'! '"" +'"W ?J + +'' '' J'!?$'!7'!B'! N'"" +]'"W ށp{IP$IM`:`y`+`>K>J'6 '6 '6,`w>J4+߁kyQs`:`:>JM'6ޯ(*+9QtMU`:p`z(`:>JM'7)'79)ၸQu Qv`:`:>J+7OK'7q`'7(^y(*⁸_Qw_Qv`:`(`:>J +O'8/D3'8/(^L'8A)へ<Qx<M`:`:>JM''8,(*䁸QyM`:`:>JO'95Ѐ'95(^د(*偸)DQzT\`:s`}(][`:`:>J'9'U][`:`:2`:`:4][`:`:`:][`:`:>N`փ':b'EI':(W>I! ':b('B>='$':H(=':bP'9'n?Ix!|':(>N`:':bX':HNK`:Ճ':bX':WH=':H ';`'94I';Z'9n?Jsz':H恸Q{`:],`J' +O~Sa`:`\k`:1`\>=0$'Q}'=W'<'=eN +`:N&0Q~`N=GQ`I' l'=q'> rq'> W>NM`'<'> AI!'>k(~>I'>k70w7 >= '=1'Q''> ?>ILZP'=(>=ql'=1'Q'> ?N`р' HI'?h w7>='=1'Q>'=?=b\'=5`c'=5`c'=l'@ +W'@ +r'?h :='='> WI!'=(>=ǃ'=1'Q'=?N `"'=_Z'=1'Q'=?='='=Ї'@:J'=選 UQ*U2`:=`Ly`+],`>IX`\'A(+=i'Ato'AŁ(^?O&+S^`:[\08k`:>1[+\>=0Q[$'Q'Bk'A&'By`OQa```.`y``>I'Cy'Cw>= 'BD'QH'C?NbhK`nyt'AŃX'C'CH7I"'C'Cw7>=҃'BD'Q'C?J#'CI5E>9'AŁ(^=OJ'BD'Q?Nw}],`1`NQ`*NQ`*N +Q`'AEV_a`c'Alj'D n'As'D ts'D W>NM`'Aņ'D AI'Ee +(~>I'D ('A>='D  'D WI.!E72'AņB'D A(H~>=c^'BD'Q|'D ?='D'D ?I'D ('D>I'D>=&!'BD'QL'D ?=f'D)='DW;>='D 'BӀ +'D'D ;=,'D:8'D WILUP'Ee +(X~>=h'D)?I'D(Y(='BD'Q?NQ`'D('ANQ`'D(WI"'H !'HC +>=;6'BD'Q^'A?In!s'H >I!'D>='D'BӀ'D'A;>N],`'A'D +'A='D/*&"'I7 97k51'I7 9;=IC'DZUQM'I7 97k`\'I7 9;?Ix|'D>I'D(Yw7>='BD'Q?I! +'D(Y(7>=*%'BD'Q?N~],`:7E``'K …'D(Y'K 'K W>NK`'D'K 9I'K(W>N!Q`%7 y-''D(YE=FH@`OM'LAQ'La'LAba'LAW>=wr'J x'K3 :='J 'K3 W:='K3 'K3 W>='J 'K3 'K7:='J  +'K3 W'K7:=''K3 -''K3 WJEL'J ' ''r''T''''''''/'U'|'''')'m'''!'T'''''O''''4's''r'''%'X'5'6'6'7'8'8'9 '9' IȈȓȌ'U (+B>=Ȥ'U 'IȷŃȻ'Uw'U{>='U 5'Ul'U{'UI 'U(#'U{>=4*:'Ul?'U{'Q??NxɁQU`:'Nɒ`:Nɠ'`Iɪɸɮ'Uwɺ'U{>NQ`'UWI'WM 'U>='V +&74'Ul9'WM RH'Uy?=f'W m2w'Ul|'Uʇ'U*Iʠʲʮʤ'UWʴ'U>='W 'UlX'UW 'UHb455ˍ6p`:`>=0EO'Qo'Ul~t'UW=˘'W ˟1˩'W ˯'U ??N`:8'Ul'U̇'U+ 'U !'W (+BN.`:I9H='U݀J'U>=a'Yi:t'Ul̄y'UW̉'U+?N̰`:I̾'U'U>='Z;'Ul 'UW'U?J +]C'U K'V +U'W ['W a'Y; g'Yn'Z ͣͫNͯN Ϳ`:+QU`:+`:+'`+`:++o]`:+F`:+΅N][`:[+Σ`:+`>=δ'[%ν5'[%'[%='[57'[50'[5=@'[GG2Q'[GZn'[G*I͆'[('B='[+?='[:'['['[=5'[@;N'[[o'[='[WІ1А'[WЖ'[%NШЯ%`йв'[%('BI"҂'[G(+B""'[5Ca!'[W(+']A >='[G'?N0=Q^`!E@'[G(+B=S'[fZ8m'[fvъ'[fё'[vџ'[%ѧ'] +IѺ""ŀѾ'[% `Ղ'[G(+B!'[fR'D>NQ`"'[%Ca!,''[G(+B=;'[fBEY'[f_'^ >=Ҁ'[f҇DҚ'[fIҫ"Ҵү'[G(+BĄҿ'[fR'D>='[G'?J]'[%'[5('[G.'[W4'[f:'[A'[ +w.ӈ.ӐQV`:ӢQW`:N][`:`:+`>J&+''` '`'`%` X`QXjrQV`:ԄQW`:ԮN][`:`:+`>J&+'QX'`'`‚'``!եQV+ե`:>I1!6.Q^JD'?NWZ``=t.Q~Մ'aIJՍ՗Ք'aAժյQUվ`:J.Q~qq`:>I.Q~(+BJ'?I .Q~R'D>J*71.Q~XQJD.Q~(^yH?Jah.Q~v~'փ`>I։֓֍.Q~(+J֣֜(ְ.?Jֽ.Q~(׉Q~׉#`:`>I1<5'c('BJG7P?IVaZ'c('QXBJm7?J}׎י׮ן׮`:Jע5`:ע.Q~#ש'd(+''d`:׳׾`:J5`:.Q~#Ԁ'e +(+''e +`:RQc`:`>NQ`:.I&1*'et(+BJ:LA'e `?IY!kd]'et(^(yn'e(^J؁*?Jؚؓ)ة'etر'e)"(Q~0(8`:GM`:`>ER[]`db'fmf'f~(^u'fvu'fWA>NۆۑQ`ۚۓ'f~ۥ'fAN۳ۻQ`۽'f'fANi`'g'gGI!'g}(>I"'g}(7 >NdnQ`xp'gGkz'g}I܋"ܚ7avܝ'gܴܪ'gv7z>B??J*?J)*JVݻk~[ݻcM`:l`z`:\>=0݉ݓݣ'hƀݬ'hݱ'h+Q~`:QV`:QW`:)N][`:`:`>NDMQU`:'N[`[+Npu'[+Iނ"!ސކ'iG(+Bޥޛ'iGCa>N޽Qh`NQ`*AE`&$'j+ 2('iG(^:'j+ ;:'j+ W>NSZQ`7@Ij߆xn'iG߃'j+ A(߉'j +>=ߝ'j)=߻'iЁ'iGX'j+ H='i'j+ WB?N+3Q`5'iIF"TJ'i`V'iG(^~t'iG'iA(>AE'kT 'iG(^'kT 'kT W>I"'iG'kT A(%B5?INZR'kT (g]'iG(^>=0{'Q'iG'i?='iG 'iW'kT =*'kT 1*'kT WIZ"!f^'kT (si'iG(^!Ⓛ'iG'kT A(~>=0'Q'iG'kT ??NS[Q_`*AEjyq'kT ㅁ{'iG(^'kT 'kT W>I㰁'iG'kT A(~>NQ`:'iGX'kT WHI^mb'n Ca=y'i'n ?B?='iс'iGX'i'kT H?J 'i8QU4'i&LL'i`:'&``'i`o劂|'iX'UN'ii `:`+`>=!'p #4,'p (+DQ'p `J^&^#e'p w0'o*/'o*[`  `:`+`>=''p#:2'p(+JW'p`Jd&d#k'pu0'p)/'p)[`EOEhEQ~Eh(EsE`JEvEv,Q~AV,],`:e`[>=胀z'r4`:`>I詂'rQn'O>I'r>=0$'QƂ'rQ>=08B$t'QƂl'rQ?-\Q~\,],`:`Q`[>FJ"`:6-'s ;'sD>IR^V'sdnk'QO>Iꏁ's5>=0'Q>=0 $?'Q˃7'sd?.ah@Q~@``[>I""~v'tIԀ'tIv~"v'tI'tIv>J3?IEI'tX>=0`j'QW['tIG>=0'QW[,'tIG/ELQ~X``:kQ`[>N`:'N,],`:'u'uUI""'u'uC'uCa>='u';?IIRM'uR]'uD>J 'o'u>J o 'u0!(_Q~;_C`:NQ`[>Ieni'w0R'QD>I'w0R'QҗD>='w0€'w07'T>='w0'w0XHI""%'w0(^!K=8'w0A(N~!wid'w0A(z>=0'Q?>='w0'w0''RNMQ`:'I]"mfa'w0(^wyt'w0A(~>=.'w0A)I"݀'w0(^(!'w0A(>=0"'Q?No],`:'w0'xUI"'w?'yЁCa>= 'yЀ';?=J-n'y)J 'o'y?I܀'w0R'xD>I'w0R 'xD>NKUQj`\W'w0'EN}Q`:#'z倇'w0XH'w0X'zH`:NQ`:#'z倇' 'w0X"'zWH`:N4Ao],`:LC'{R'xU=`-'{)I"'w?ņ'{큏Ca>='{퀘';?J%0 'W'{oo'{>No],`:΀'w0'xUI"'w? '|Ca>=0#'|';?=f-'|)J 'o'|>N&o],`:-('w03'xU=?-c'})I~""'w?'}Cу'}Ca>='}';?J+6 oH'}Sdhr or `:+QU`:+`:+'`+`:+o]`:+`:+EN][`:[+c`:+`> N%3Q`*I@!KD'~}(+B>=\'~}e5q'~}|'~}(^='$ !'~}(.B>='~}.N%`'~}('BI!!'~(+B>=2'~=7K'~aX'~(^>=}'~.Q~I!'~(+>='~1'~'~}>='~.Q~I '$ >=U'~\1f'~l'~}?I!'~(+B>='~2'~'~(^*I.Q^>='~.Q~I""%'~Ca!83'~(+C' +>=S'~'?Nn{Q^`!}'~(+BI"!'~(+B!'~(+>='~8'~'~'~΀'~}' >=8'~D.IP""U' +"`' !vq'~ `!'~R'D>='~'W'~G?I"!ކ'~(+B!'~(+>= +'~:'~';'~C'~>=h'~u.Q~I!' (+B>=' ;' ' (^>=' .Q~J"]:'~}B'~L'~R'~X'~^'~e' Tw{Qd`>I!.Q` J.?J]..Q~.Q~.Q~..Q~++o8],`:>NBI],`:K.Q~I^!ib'(+Jry'?NQ`:.I"'Cá'A(~>=''XH?='#5)'('B:F`:e3`:''U[],`:=.Q~'J' N][`:`:>I"7&.Q~(+>=H.Q~i]`:`:.?J.Q~Q\][`:],`:>I %.Q~(+>N:NQ][[[PLe.Fs|['f{>='f'3`:&'f'm][n=.Q~:c`:],`:a'f?J.Q~UVQeV`>N`:9...Q^I'.J".?J3?. M'S1[fQ~ot'``:`>I"!ƀ'n(+ր'n(('|J+?J'n2   Q~   +`: + ` +y` + Q``:>I +~ + +'((+BJ ++?I + + +'7( +'FJ +'?I  '  '( '7A( *>I A! ^ J E'( Y U'FyA( a>= {* '( '7'Q?=  '(  '7W  'FyJ 3 U ? :'(X I'7 P'FH!W?I n! s'U>E   ` '7 ߄ ' 'F '  'W>I    '( 'A( ~>= ' 8'( >'7 E'FJ U$ e' _'('??J  4 '( '7 'F3  /Q~ / M``>J "  'Z7!'  +'Z9'Z7(4CQpQ~bpj`:t`y``:>N`NQ`'LN`'LN*7Q`)CDQK'S'[A>NdiM`pk'={'AI'(~> N`:<'=')I.">2'X(+BI'>=c'ic'WBy?I't(+='t?N`:'=X''HI +!'=' +%' !W?=IB'tO' Ncp`I}'X(+B>='X'=X'̅'WHI'X('B>='X'Q=$' +?=OH'tU'X=k'qk'Wt' +=''=')I3'>I""'~v')~^,'>I't(+='t?Iׄ''>='t'=X +''H=-'<'?=Y'*?=''WIA'>=*'=''> N`I"2(#'7(7KF@'WM'[>Nbg`ni'=y'WAI' 7(7>='7kԇ'77 +k' 7='i??I2=6't(+=F'tS?Nrx`:z'=X''HI!'=' ' !W?='t' ='t ='=%'+%'W.'i=D'S'Ilwp't(+J'=X'L'[H?I''[>N`:ۀ'=X''[HI!'=' '!W?=<5'tB'?JTb['tA5 Q~$,`:8`Cy``:>INXR'(['J`'?NyQ`'s'AI!P'>=*'s''Q?N1CQ`*EPY[`]'fd'mh'm'mnm'mW>N`'s'mAI!@'>=*'s'm'Q?I"&~v)'>5'σvA~>=Z'R)?='s'sX''HI'R='s؀'s!W?J6's6Q~`:`:>Ì'N('BJ'?I'N('BJ'?I'N('QXBJ+'QX?I?JC'N('CBJX'C?Jnu'N76Q~6QU`:`y``:>I؀'M(+BJ'?J> 'M'^'m#8;I"Q~R"Z`:d`oy`o]`:`:Q^``:> N%`ׄ'T('BNQ`" '~ 'cI " & !'(+B > 1'?(+J G# N'~''`:?I e"! n i'(+B!  y'?(+>=0  'Q?N [I !  '(+B>=! 'z!>!+'!1'!!8'0!=>=!h'z!!!q'?`:4!!!!`:`:J!!M!!' !(*'I!&!!!'z `>I!"'~J"'?I"""#'!&"9"A":'zR'`>="Z'z"g'W&"i"i'z`:G?="{'z"9&""'z`:"'T"'cJ"&""'z`:9##$Q~$$$`:$`:$)Q^``:>I$=""$H$A' `!$T'!$j$e'R'D>J$$E$'"$$'Ca$'?J$$D$':$% )2Q~%)2%`:%(`%3y`%pN][`:[`:>I%!%%'(+B>I%!%%'(+>=0%%'Q?J&&#>&9'&@'&G'&L?I&h&|&l'(+J&+?N&&`&N&&`:'O&&Qa`:`:\&'&`:&K`:\>='' '''='*''='H'A''R'g'I't"!'~'x'(+B'''Ca>=''''='DŽ'''''?=(('׀4(()(`:( K[`>I(/"(9(3'O(+%(J(D'O`:>=(m(_'(n'@&(s(s'O`:>N((][&(('O][F(([(' >N(K`:&((' +`:=(('('@(' xJ))$)'A;)7)E)Q~)R))Z`:)h`)sy``:>I)~))'(+BJ)+?J))>)')'͂)')<,F,T0Q~,d0,l6`:,x`,Q``:> @,,,','A(,~,,I,,,с,'W^,߀,'(^>J,'?N-)-4`-=-6'-N-H'WAN-\-h`-q-j'--|'WAN--Q`- -'GN--Q`-؞ -'I-". -'̀.$.'>J.1'?N.k.qK`...s'͂h7W.'I..Q.'d>I."".'..~v.'d..~^/'d>=/'d//'dk7 ?J/0/;[/O'd?I/a"/p/e'G^/s//'^/>J///݀/'X/'//'WH(X?J0+=005^Q~05^0M``:>@0Հ0'-v700N1],`I1$1-1('-7>=1p'm1.`=11'm1~:=11'm111؀1'-A:=11'm1122 +'-7A:>N2r2w`7N22Q`I22ހ2'-w7>=2'~7=3'I3 3)3$'-w7>=3?'=3['~7??=3'm3.`3h3'N33`C33ً3'3ʃ3'y^>N33`4433'-47h4'7?k4'~=434*'m44'W4=~:=4X4O'm4_4Y'WW4q4f44|'A:=44'm44'WW444…4'7A:=4'W4؄4'WW=4'~7J505;Z5P'm>6U6c7#Q~6x7#6`:6`6y`6Q],``:>J65`:6?6'|6'6'6'#6'(+7 +7'|X7'7'H'`:?88@O~8@8`:8`8y`9 Q],`9#Q`*`:>N9Q`N9a9nQ`9p'N99`9'C999'9'A>N9:M`::':'AI:'":0:+'X7!:g:O:C::':I:D'X9:T:]:X'X7(>=:w':|:w'W>N:`:N:`I:::'X(:~>=:'R :<;';'*I;s;;w'R (+B>=;';;'WB;?I<<'(< 'R B>=<;'R 'Q=<\'b +>=<'b +I<"!<'<A<'X>=<*='= ''>==C'b +I=_=s=i=d'X7(7>I===='W='>N==`=='=='WAI>>'>>') 7(7>=>g'b +=>'X>>7k>>>'X77 +k>>') 7???=>'R ?=?'XI?*?5?.'(+=?>'?K?=?j?c'?z?p'X?'?'H=??'?'R =?'?̇?'W?'b +=?'?'I@ @@'(+>J@)+?I@@@Q@D'@S'>=@g@`'@w@m'X@'@'H?J@@@'A@@@A8Q~@A8@ ``>J@"@@' +7!A/AAAAA' +9AA%A"' +7(AA=AIAQ~A\AAa ``>JAk"AuAr'vAx!AAAAAA'9AAA'7(B BB@BB@`JB""!B)B".('BB;B2.('BBBEBLFQ~BWFB_`:Bl`:`:>NBBQ`NBBQ`CC/C@C6'YR'RCR'D>=Ce'CnCe'W=Cz'rCCz'rWNCCR`CC'JU'FACD9"DHD@'wDYDO'rw>NDjDq`DxDs'JU'DD'yFIDDD'z>BD?NDDi`DD'yD'zIE["""EfE`'(EtEn'(EEE'JEE'zWA(E~"EE'(EÈE'JEޅE'zWA(E~>BE?=F 'F'z=F$'rF-F$'ryJF;FGFB'JFeF]'W+FzFp'YXFF'yFhF'rHTCGGH1R~GH1G`:`>IGGՀG'R'%DJG)?NGH`HH'솉'REJH!H(H"'-(H+WDI9IGKR~IYKIa`:`:>IIm!IrCI'JII'?@II'CaIINIJ4],`:1J`:NJJR`*FJ(JPJ4`:JDJ?''U>=JX'A*IJsJJw'_('B>IJJJ'C>=JJ'7IIJJ߁J' >=JJ'';??=K$'A)IKEKM'%(KP'_B>=Kc'A)>=KK'K'_;IKK'A=ḰK'';?JKKK''EN>NLRKR~NbRKNj`:NuQ``:> +@!NN'R'DNNIN!NCN'>IN!O'=O'OFO$'?JO1O8'?@OTOO'CaOOO^NOO4],`:1O`:NOOR`*FOOO`:OO''U>=O'*IPP#'(P&'B>IP9"!PEP>' !P\PWPP'('B>=PxPq'„7I=P')>=PƂP'€';IPP'%(P'B>=Q')>=Q8Q1'€Q<';IQX"QcQ\' "Q}QvQo'(Y(QQQ'9 `>JQ'R?IQ"Q'QQ҂Q'('B=QQ'€';?IQ!Q'=R R'€RFR&R '9:?JR0R>R7'‚'FRRTfR~RTfR`:`:>IR"RRȀR'’(^^RPRR'’A>AES SS`SS'S$S'’(^S,'S-S,'W>NS?SDM`SKSF'’SV'AISbSkSf'i(Sn~>JS$SSS'’XS'H'R SS'’XSS'WH?IS"SڂS'iw7T!T SSTS'i9TTT'i7(>BT4??JTWT^'’VTkToTTvTT~`:`>JTT.TT'WWTT`T`T``> NUR +`:NUU(R `:'NU9R `:NUMR `NUd`:NU{R`:IUUUU'qCa>=U'ŊU΀U'qIUUU'qQ^>=V'ŜVV'qQU=V/'ųVFV<'q=VT'#VkVa'qQ_VVu'q'+`?=V'VDVĀV'qIVV߀V'q>=V'W W'q?>=W-'ŊWA.IWOW]WS'qQ^>=Wu'ŜWW'qQU=W'ųWW'q=W'W1#WW'qQ_XW'q'+`X'Ŋ=X,'X9DXVXL'qIXeXsXi'q=X}'XX'q?>=X'ŜX.Q~=X'ųX.Q~=X'Y.Q~IYY1Y,Y"'q('B>=YD'YV.IYfYtYj'q>=Y'YY'q>=Y'Y.Q~>IZ ZZ'qQb>=Z9'ZFDZcZY'q>IZZ.Qa!>IZ!Z.Q^>I[![.Q]>=['[['q>=\7'\DD\a\W'q>=\'\D]'W]]'qG>N]X]cR`:]e.Q~]v.]]|'qBI]""].Q]].Q^].Qb">=]']D^'e>=_;'_HE_t'e"_.Q]_.Q^I___'q=_'` +`'q?N`4`=`:#`I`?'qQ``a`W'q+`:J`v`]`'Ŋ`'Ŝ`'ų`'Ņ`'׆`'`'}`aa Q]a a `Jaaa.Caa%a.aKQ^a;aK`Ja>!aDa>.Q~(+BaPaYaqQ_aaaq`Jad!ajad.Q~(+avaaaa`Ja!aa.Q~(+B aaaQ`aa`Ja!aa.Q~(+B!aaaQaaa`Jaaa. `"aab&Qbbb&`Jbbb.R'D#b+b6d)b=d)`:>IbCbNbG.('B>=0b]bg($b'R.?Ib"!bb.('B!bb.('QXB>=0bb($c6'R.?IcC"cMcG.Q~(+Bc^cX.Q~('B>=0cmcw($c'Rc.'R.?Iccc.Q~(+Jc$cc.'c.Q~?Jd$d%d.'d.Q~'d.Q~Xd.d5fld?fldF`+`:>IdV"!dadZ.('B!dqdj.('B>=0dd$d'Rd.'R?Id!dd.('B>=0de 'R?Iep!e}et.('B>=0ee'R?Iff f'Ў(+=f'Ўf?Jf/#f6'Ўf@H.f[.R~G`:GfqfxhvR~fhv`:>If"f.Q^!ff.('B>=0ff$'R'R?Ngzgo],`:g.o=g,g'Ҏ*Ngg`gIhh +.Qb"=h"h'ˁ'?=h9h2'˂hB'Ҏ'JhZhhha'AHh{hkR~hkhM``:> NhhR`*Nhh,],`:h߀h'ӊoIh""ihh'ӹ(Ywi'i ii'ӹ9(^(iQiCi?i7'ӹ9A(iT~>=id.iii}'ӹ9A*=i-i'ӹ*=i'ӣ)>=j-j3'ӹ*NjVj]`jcIjw"jj{'ӊQb!j'ӣ=jj''?IjjÀj'ӊQ^>Njj`:jj'ӊIjjj'}Ca>=kk''=k6k/'k<'}=kRkK''??=kxkq'k'ӹ'Ik"k'ӣkkk'ӹ(Y(=kɃk''?Jkkk'AkllIR~llI`>Jl"!l&l!.(+Bl6l1.R'DIlNlSm?Q~lbm?lnR`\>Ilxll|.Q~Ca>=ll'Vl.Q~=ll'V'?Il!ll.Q~(+B=ll'Vl.Q~?Il!ml.Q~(+>=mm'V'=m)m&'Vm/.Q~?$n5nAn~nFn~`^JnI#nQnJ.('Bnbl.+`^YnnnAnn`:>Jn5`:n.Q~#n'?(+Bn.Q~n.R~J'?`:JnnpR~np`:>@nn.Q~(+BnnNo o`oIo*o5o..Ca=5`oA' 5[oEoC'HoK.5[oToR'H''H?Iod"oh.Q^ooy.('B>=pp' '=p.Q~p'' I?=p9p6' p?.IpJ!pUpN.Q~(+B=5`p^' 5[pbp`'q'V5[pnpl'qpt.Q~'q?Ip!pp.Q~(+B=5`p' 5[pp' +'5[pp' +p.Q~' +?JppȀp' AZppr(prps``>Iqq.q'Jq)?Iq-%q7q1'`>NqKqOM`qQ'`Jq^"""""""""qlqe.(qsqo'Bqq.Q^(qq'Q^qq.QU(qŁq'QUBqq.(qq'Bqq.'(rr''rr.(r#r'Br>r5.(rErA'rar[.(rhrd'Brr{.Q` (rr'Q`rr.(rr'B?Jr*%rrs(zrs(`>Jr5`r.Q~#s 'i(+r.Q~ss.AYz_'i`Ks-s9sLR ~sDsL],[JsJ1sJ[LsQs\w%R!~spw%sx`:s`s(][[[>Nss][[[2s[[Nss`Nss`Nss`s锃WOssR"a```\tut`t`t!y`\>Nt5`:NtGK`:ItTt^tX'(ta'3 Jtf?Ittttx'$>=t'H +tOt'Jt't'3 t'Z)=t'X '>=t'H +tOu'Ju 'u'$u'Z)=u8'X u@OuK'Ju^uR'$Wuc'3 uh'Z)=uuu'zu'H +uKtu'X Cuũu'uԀu'J(^>NuuM`uu'Jv'AIv +vv' (v~>Iv)v9v-'=v>'vL'?Iv\vev`' (vh~>=vv~'v'ଅv'v'=v'vv'W=v'v͔W?=v'vv'W=vv'v'ଅv'w 'Jww'zMHSHjKR#~Hj(HtKHR$],`H`:H`HR%``:>IH"HH'H(HHI'>JII'?NII`I'NII],`II'쁳I'EIII`JJ'ʀJJ'十(YJ'JJ'W>NJ'J,`J3J.'J4'9IJ>"JGJB'/7!JJvJjJ\'JpJk'/9J{JJ'/7(>=JJ'kJ'/IJ"J'JJ'/(J~>=JJ'k'W>NK,K6R&`:'R'=K[KT'k'=KvKo'kKK|'pKKK'/7@=KK'kKK'pKK'/7@JKKK'kANx x+zPR(~x=zPxE`:xL0``>Nx[x``Exixrxt`x{xy'ۀx'xx'W>Nxx`xx'蚆xx'Wx'AIx"x70vx'-xڄx'-v79>=x'y xxx'‚h7Wy'-y70>=ye'-ynye'-k7 Iy"y7avy'-yy'-v7f>=y'yyyy'‚h7Wy'-y7W>=0yy'R)JzAzH'O|| R*~|*|9`:|C`|Ny`|\`|kR+``:> @|v|'||@||'v|'&||@||'&v|À|'(^||@!||'5(+||N}C}JR,`)AE}V}_}a`}c'}l}j' }n'&}s' }t}s' W>N}}`}}'}' AI}""}}'삃w7}҇}'(}~"}'B~}'(~~>=~'*B~1?N~T],`I~_~c'>I~s""~|~w((~'5~~%(~'5~~(~'5>J~~ʀ~'X~'~'&H>=~'8'X''&Hb>=A'8M.`E[df`h'qo'Ws'&x'Wyx'WW>N`''WAI'w7>=0'R-?I -$'(0~>IFPLJ'WWwWR'(^>=0mw'R.?='8N'҇'WW;='W'WWI"'B '(~>=2,'86~;>=`Z'8d';J'5'8PRR/~R``>NQ`'k7 J "#v&'=3'v@QWcR0~tyM``>J"'񧀇7!'9Ŕ΀'񧅸7('U@'Z'_'`'a5'a'b/'c*'c'd\'d'eH'fN'hz'i'o'p'q'q'r't'u'w'~R''h'7''s'>''*' 'C''''v'z''P''L'U''''''''b''G''c'̾''r'''s'c''Z'֬'&'؜''٦'ܗ'/''''j'''w'ZO^&R1`aR2~`Wb Q~`:c R3~],`d'R4~`eR5~`!f5R6~],`:G`7l77777gR7~],`h9R8~],`:H`77777755rp~>rDQ`:PR3],`hR4`\?b'Pc'ad'x 5j4`:k`:+`+~][`:`:+`*`^> N:A`GNem],`1o`paNR9`:N`:I!'(+='''?m?I' (+>I! '(+B>=3' GQ'?Irv'(+B>='' K?=#' (+Ŋ'  +`=o'('6'B'MJ'm=`X'mkd'M(;Ix|'4>='M'R:='m'M(y;=م'M' `:e'>="'M'=4rDgYP' `'j'MJ}'MA'm+kuR;u],`k['~][`:`:+Q[[*`^>N/6`<NZb],`1d`ea=uo&'`:+'Є''"='"Ą'(;I&'`>=''=rg"')'>=LE''R:=me'"xq'(y;=e:в?'Љ?'!'(Y)DJ;FWP'Ac'"+lM``^>I!Հ'4('B>=0 '4'M'R<?I=EA'4Q^>=0[e'4'M'R=?Iǀ'4Q`>=0'4'M'R>?IF!OK'4>Jahqso'4|'4?Jq$'47'4oR?~k`:R9`:=~][`:`:V`c],[\>Ir"v'(+B'('YB>=''?I"Ҁ'́ `''>='#'>NgrR@`tp'I'π>=0''k'RA?=!',MBf\S'̓Xi'Hv(*=’‹''=«¤'¶Mf'̓X'WH(*I!*'(+B>I;!G?'(+>=5],[Z'5[ca([ng'(;5[wu([ÉÂ{'(W7;([?=äÝ''RB=Ńþ'Mf'(*?=5][`:`:'#(Q(++(Q4&&+`:4K`:`>ICKG( `>=0^h''RC?IĴľĸ( `>=0''RD$:'RE4('F?IK!WO'(+=h`'sl'(;?=ʼnł''='Mf((*I)!5-'(+=F>'QJ'(;?=g`''=ƀy'ƋMƖfƧ(Ʈ(*x\p'RF~'k`:`>N&R@`(WE09;`B@(MD(ہ(^U(VU(WA>NfkM`vm(ۆȁ(AIȋ!Ȕȏ((ȗ~Bȟ?IȯȾȳ(>=((B?JWJ(s͇͖ϐy͛ϐͣM`:`^>IͮͽͶͲ(l(^^7>NQf`(lI((>J;BqI(l7+?Iftj((7 >Jq"(lX7H+??=0LV'RGυ(lx6>tMBt`> +IH!VL.R4~d(+J_f.R4~d?N|Ё`:Ѓ.Q~bNЕЛ`:+NЫжRH`и.R3~c9NRI`.Q~b'V(;WENy`.Q~b(^I'6+(q^>=D('Q>r.Q~bфy(qWщ(ѓ=ѫ(ƒѱ(q?=(>.Q~b(;W (=/.R4~?.N(T('dJ`g.R4~dy՜էikհi`:>Nպ`.R3~c9WNy`.R3~c9I( J(( J'Y?J/;OF.Q~bM( JT( Y(*z9Dک?Lک`:>NVeRJ`NrRK`ؚؓ؁.R3~c(YyIػؿ.RL{>=( +x)( +xy?E9BD`F( +bXV( +Z( +xh( +jh( +W>N|مRM`ٜ٘ه.R3~cٙ( +9WN٫ٲRN`ٴ.R3~cȂ( +W9I"߄( (( ZW7.Q~bR'?( ZD>J#/OG.Q~bUN( WkZ.R3~cnl( +W9t(*?Jڔ'RO{RL`J.R3~c(Y|ۦ۱RP۽`:J.Q~bX.R3~cWHtHR'RQ`'`> Npu`:w.Q~bN݆݌`ݥݠݎ.R3~cWIݮݲ.RL{>J˯!( ("?Nhph`7%Nހއ(`ޕގމ( (^yޗ("Eޢޫޭ`ޯ("޸޶(޿޺( (^(Ȅ(W>N`( (AI +(r( (>= (" (W=0(70(y?Nsz`߀:ߊ(Iߗߢߛ((ߪߥ( (^>=ߺ( (ڀ( b("OJ(?N`E(*`,("53(Ӏ<7( (^D(ED(WA>NU^`e`( p(AIz!~(A((>=ࣄ(5`(5`((W((A:>Iֆ(W( (^>N`  ( (WI%.)(L^>=HB(5`I(5`I(N( W( T(L:=f(hf(WBz??=0'RR( (@(( ((YJ(uRS`+`:>I((+>N ?`:.?z=G([e(Iu傀y((+>=0$'RT(??N`:.Q~bN`.R3~cWI%).RL{>N?I]`:`:ZRK!`:h_(ބJx扃(斁(X(H?JO((܁((^(*}|M~M][`:`:>N][`:`:2`:`:E`܁(T.R3~c(Y(T(TW>N `-%.R3~c(&(Ty9WN<C`VE.R3~cYW(Ty9Nimy`o.R3~c(T9N`:O.Q~b(ƒ(꾯(*NK`:O.Q~b(W(i (*=#(!$(+(nJ<C(!qRaR~gRo`:y`4``^>@"뢁((밁((7@Ɂ((7(׀(R'RUDNP`7,N17RV`7/NMWRW`7;Nmt`7=N],`1`웁(ƒyNR@`추WNM[N`(AE(= +((^(= +(= +WA>=(1  ((= +AI%".)(1 (1(u?:(1 (B(BM?IZc^(1 (f(>Iw{( >=( (= +B?=0'RA((= +?I"'( 0.(= +w2(>=0'RA((= +?AC!(1 ((u>=:2(π>(= +;=H(= +IH(= +WNWc`eWAEoxv(= +z((^(= +(= +W>=(1 ((= +AI(1 ((>I( =( (= +?I"(1 ((,'(1 (/(u>BB?Iaqe( ^>=(π( ;>NRX`(ρI""! (1 ((u!%#(= +(6((^ W7!fa(R'{(^ WD>=0'RY((= +?B=(π(= +;NRL`.'(ρ(YI9=(w >=O(]V!g(om(= +Wyt((^>NX]`:d?o(wu(= +W|((^gQ)I!(  (+B>=(((= +W((^(  T?J +5(;(ςD(rmRZ~ mR$],`5],`G`\>N`E`(!(!k(Y(!(!W>N`(!k(!9=%(!,%(!k/("I;"D?("7!sgY(!Tmh("9x|("7(>=(!(">=ւ(!~=(! '"("A=>7(!WLgb("7AI!(!7g(>E`($/(!k(Y($/Ʉ($/W>N`(!k($/9I"($ ($w7>=0&:($'R[??vryA`:J#.R3~c9(a$'RU.Q~b.Q~b`:''' +'((C(( ( +.( ( C( ((((!$(%&(%>>|R\`` ?( R]~`:?: R^~`?R R_~`?j R`~`? Ra~`? Rb~`? Rc~`@iRd~`:@}Q~`+@@AT@AT@R]`:@R^`@R_`@R``@Ra`ARb`A,Rc`AGRd`:\? ('b('s('('('('('(' @)AYAbA}Q]AlA}`JAoAzAo.R^~wAAAQ^AA`JAAA.R_~wAAAQAA`JAAA.R_~wAA.R^~WAAB$Q_AB$`JA"BA.R_~wBBB .R`~WB.Ra~B(B1BYB:BY`JB=BIB=.Rb~BK.Rc~B]BfBQ`BrB`JBuBBu.Rc~BB.R]~(^BBBRe~BB`JB"BB.R^~(BB.R]~R'DBBCRf~BC`JB"BB.R^~(CB.R]~R'DCC#CZRg~C,CZ`JC/"C:C/.R^~(7CGCB.R]~R'QXDC^CgCRh~CrC`JCu"CCu.R^~(7CC.R]~R'CDCCDFRi~CDFC`:`JD"DD.R^~(D%D(-S(^D4D/.R]~RD?(-SDDKDTDQbDdD`JDgDlDg.R]~R'D|.Ra~DDDDQaDD`JDDD.Ra~(D.Rb~DDDDD`JD"D.Q]!D.Q`DDEQcEEE `:`>IE"E%E(/*(+BE7E0(/* `JE@EREG.R^~?IE[!EmEfE_(/*(^(Ep.R^~JE|*?JEE)E(/*E.R]~EEGiEGi`:>IEEE.R^~vJE'?IE!F E.Rd~(+BJFF.Rd~?IF.F2.Rf~>=FC.Rd~'IFeFi.Rg~>=F{.Rd~'QXIFF.Re~>=F.Rd~'IFF.Rh~>=F.Rd~'C>=G.Rd~G.G).R]~XG;.R^~HJGRGY.Rd~GnGyGQVGG`:JG#GG.R_~wGG.R]~XGG.R^~WG.Ra~H'`:GGHFQUGHF`:JG#GG.R_~wHG.R^~WHH .R]~XH'H.R^~WH7H,.R_~yH'`:HJHUHHZH`:JHc#HnHc.R_~wHyHt.R]~XH.R_~H.R`~H'`:HHIK'HIK`>IHH.Q_JHHHH.R]~XHH.R`~WH.Ra~H?III .Rf~JI7P?II!I%.Rg~JI/7?JI?IPI[II`I`:JIcIhIc.R]~XIr.Ra~I~.Rb~HIIJIJ`:JI#II.Rb~I.Rc~II.R]~XII.Rb~WI.Rc~H'`:JJJlJJl`:JJ$#J4J%.Rc~J;J6.R]~(^JJJE.R]~XJcJT.Rc~WH'`:JqJ|M8JM8`:>NJJRj`J.Rf~IJJJ.R^~>=0JJ($K4'R.?IKA"!KF(7C!KQ.Rg~>=0KcKm($K'Rk.?IKKK.R_~(K.R`~>=0KK($LK'RL.'R.?ILXLgL\.R_~(LuLj.R^~W>JLLL.R]~XL.Ra~H?JLMLL.R]~XLL.R^~WHWMM.R]~XM.R_~M).Ra~HGM=MNO'oM[O'],`:>NMeMk`Mm.Ra~NMMy`M.Rb~IMMM.R]~R'M(9D=M(9MM(9W?IMMЀM(9(M(9JM:M`:?NNN],`:1N +`:ENNN`N(9N(N&(:N*(9N/(:N0N/(:W>NN@NEM`NLNG.R]~NW(:AINaNjNe(;(Nm~>=NN(:NN.R]~XN(9N(:H;=N(9NN(:W?=NӂN(:NN.R]~XN(9N(9H;JNO3`:O(:O,ODONOTO][`:`:>IOZ!O_.JOi;Op`:`:?JOO]`:`:OO.OPQwQ\PQw][`:],`:>IP!P.JP(;P/`:],`:?NPWPkQ][[[PrLP.FPPP[PP(=k{>=P؀P(=kP(=P3`:&QQQ(=kQ(=m][nJQ-Q8c`:],`:Q_(=kQ|QR+Rl~QR+Q'`:`>NQQRm`QQ.R`~WJQ"QQہQ(>WQQ(>(^(Q.Ra~RR.R]~RR(>R(>DR0R4RKQeRARK`JRG.RPRTSfQdRbSf`>IRk!Rp.Q`JR}.?JRRRR.R]~XR.Rc~HR.R^~R.R_~S.R`~S.Ra~S(.Rb~S=.Rc~SU.Rd~SkSo\ Sv\ S`:+SQU`:+S`:+S'`+S`:+So]`:+T `:+TLN][`:[+Tj`:+`> NTTQ`*IT!TT(@(+B>=T(@T5T(@ГTT(@Ё(^=T(Aw !U.Ri~U (@>=U)(@U7.NUNUU%`U_UX(@('BIUo!U|Us(@(+B>=U(@U7U(@UU(@(^IUUU.R_~w>=U(@VU.R]~XVV .R^~WV.R_~H>=V;(@'IVT!V]VX(A(+>=Vn(AVz1V(AV(@>=V(A#V.Q_V.'+`IVV(Aw >=W!(AW-1W7(AW=(@?IWX!WaW\(@(+B>=Wr(@W~2W(@WW(@(^*IWWW.R_~w>=W(@WW.R]~XW.R_~W.R`~HIX""XX (@Ca!X'X"(A(+X2(B% +>=XB(@'?NX]XjQ^`!XqXl(@(+BIX~"!XX(A(+B!XX(A!(+>=X(AX8X(AXX(AX(A!Y(@Y +(E >=Y,(AY8Y3.R]~XYB.Ra~YN.Rb~HIYb""Yg(B% +"Yr(E !YY(A `!YY(AR'D>=Y(AY'WY(AG?IY"!YY(A7(+B!Z Y(AG(+>=Z(A7Z):Z?(A7ZIZ](A7Ze(AGIZZZ.Rb~Z.Rc~>=Z(A7ZZ.R]~XZZ.Rb~WZ.Rc~H?IZ!ZZ(A^(+B>=[(A^[;[,(A^[B[9(A^(^I[V[i[Z.Rc~[p[k.R]~(^>=[(A^[[.R]~X[[.Rc~WH?J[[][(@Ё[(@[(@[(A[(A\(A7\(A^\\\i\%\i\-`:`>J\>\E.\T\Z(I\n\r]\|]\``>I\%\\(I`>J\\.Rn~.\(I`?J\\\.Ro~](I^W^[vRn~^gv^s`^b``>I^^^(JRQ]J^^(JR?I^^^(JRQ^>I^!^ڀ^(JCQ]J^^(JR?N^_Qm`)I___(JCRe~>=_/(J!_?_;(JRQaI_Z_c_^(JCRf~>=_v(J!__(JRRl~'QqI___(JCRg~>=_(J!_ρ_(JRRl~'Qr?I__(J>N` `i``!``(JCR^~WN`2`9Rp`:`g`E`@`;(JCR]~X`b`W`R(JCR^~WHW`~`y`u(JRR]~X```(JRR^~WHGJ```(L"``(JCR^~a``(JRR_~Wa +(Ka,a!a(JRR`~Wa.(KaPaEaA(JRRa~WaR(Kauaiae(JRRb~Waw(Kaaa(JRRc~Wa(Kaa(JCRd~>Jb)b?b0.Ro~bJ(JR?Ibbbjbf(JRQa>Ibbb(JR>Nbbi`bbb(JCRb~ybb(JRRb~NbbRp`:c +bbb(JCR]~Xbb(JCRb~HWc!cc(JRR]~Xc/c+(JRRb~HGJcEcPch(Ncc|(JCR^~cc(JCR_~cc(JCR`~c؀c(JCRa~dcc(JRRb~Wd(Nd(dd(JRRc~Wd*(NdBd=(JCRd~?Id_dgdc(JRQ`>Nddi`ddd(JCRc~ydd(JRRc~NddRp`:ddd΀d(JCR]~Xdd(JCRc~HWe ee(JRR]~Xee(JRRc~HGJe3e>eV(Qeoej(JCR^~ee(JCR_~ee(JCR`~eƀe(JCRa~ee(JCRb~ffe(JRRc~Wf(Pf)f$(JCRd~?JfFfRfM(JCQd?Ifnfvfr(JRQb>Nffi`fff(JCRa~yff(JRRa~NffRp`:fffՀf(JCR]~Xff(JCRa~HWg gg(JRR]~Xgg(JRRa~HGJg.g9gO(S:gfga(JCR^~gg|(JCR_~gg(JCR`~gg(JCRa~ggсg(JRRb~Wg(Rhgg(JRRc~Wh(Rhh(JCRd~?Ih4"h=h8(JCQahRhM(JCQ^>NhhQ`hh(JRRa~Ciiii (JRR]~R'Ri&(UD>=i;(UiDi;(UWNi\ibi`iitiiid(JCRa~yiv(UWNiiRp`:$iii(JCR]~Xii(JCRa~H'iiցi(JRR]~Xi(UHJijj(Uj0j+(JCR^~jKjF(JCR_~jfja(JCR`~jj|(JCRa~jjj(JRRb~Wj(Ujjj(JRRc~Wj(Ujj(JCRd~?Nm m`:mm(JCR]~Nm)m0Rq`:m6m2(JRR]~NmDmNRr`mUmP(JCRa~NmimqR`mxms(JCRb~Cmmm(WR'Rm(WD=m(Wmm(WWNmmQ`m݁m(JRRa~NmmRs`mm(JRRb~NnnQ`Co>"oRoNoE(XWvoU(Xofo_(WR'Rox(XD>=o(Xoo(XW=o(Xoo(XWNpp`:'ACqqąq(Xwq(W>=q(Xqq(XyNqqM`qq(Wr(XAIrr!r(Z +(r$~>=r6(Y 'IrLrZrP(X(Br`?=ro(Xrxro(Xy?Ir""rr(X(r(W!rr(JCQ]!rĀr(JCQb>=t(Y '=u.(Xu7u.(XyuDu:(Xh?NuXu^i`usuhu`(Xyuj(XWu|uu(Y (^NuuRp`:$uuu(JCR]~Xu(XHu(Y uuЁu(JRR]~Xu(XHJuuv([ v%v (JCR^~v>v9(JCR_~vWvR(JCR`~vpvk(JCRa~vvv(JRRb~Wv([k +vvv(JRRc~Wv([k +v΀v(JCRd~vvyKvyKv`+`:>Iw "ww.R^~^!w$.Re~>=0w5w?$w'Rw.'R?Iwww.Rb~ww.R]~(^>Iwww.Rb~w.Rc~>=0ww'R?=0xaxk'R?Ixxx(]{(+=x(]{x?Jy #y(]{yH.y:.R~`:yPyWzYR~ybzY`:>Iykyzyo.R_~y|.R`~>=0yy$'R'R?JzEzQ.z^zjzzoz`^>@!zz|.('Bz|zJz+zzzzzz`Jz5`z.Q~#zʀ(`](+z.Q~zz.R]~z_(`]`zz{y(z{yzs``>I{{ .{(`J{!)?I{2%{<{6(``J{D{P{K.R]~({Y{S(``AB?J{i*{~{|Ro~{|`>J{{]{.{.QU#{.Q^{.+`:#|.Q_|(.'+`|B.#|U.|e.+`:#|.Q`|.+`:|||A||`:J||.R]~((^((()()(*.(*(+(+(,(,(-#(-(.=(.(.(0(1(2(3p(4(5 (5(6O(7(9(R(?U(?(@(H(IU(J(]P(_(_(`%(`(a(b(b)}}}Rt`}/ ^~`^Á}9}9}}A}}G^`^}U`:}b`:\?(c }w]'+++}(c}(d+}}}}}`^J}}.^~(dI(d ~񁛌Ru` 'Rv~򁛑&` ~󁛙Rw` ~􁛢Rx~` ~Ry~`7 ~5Rz~`7%~PR{~`7&~mR|~`7+~R}~`7.~R~~`7/~R~`7:~R~`7=~R~`7A~R~`7Z(R~`7[HR~`7\eR~`7]R~`7aR~`7fR~`7zR~`:'R'|R~`R~` <R~` +R~` R~`7 FR~`7 R~`7R~`fR~`7R~`7 R~],` R~``:J#%(h`ס(h`&(h``:R~p[`J+OOOR~OOO=`Or``JO#OЀO(iHwO(iVO(iHO(iV`OOPR~OPO=`Or``JO#OO(i܀O(iO(i܁P(i`R^^(go=`yr``>J`'g'R(je(jq(je(jq R(-5a``>IALE(j(+JU?N``'D'N(j#I9B=(k(+>=Q(kX`'t'R=['7'2(j(k?Jל`'t'(k!/49Aa`\>NTY`:$d](kIhxl (+>=(k>= (kXXX>~XX>XQ``JX%X5X+X&(l|7(7XXXR~XXXQ``JXXXX(l7(7YYY{~Y(Y{Y-`Y8y``>JYAYjYP7WYcYZYT(mp77 +WYqYm(m7iy;R~;],`>NR`7N9FR`NXcR`NuR`NR`NR`7NR`7NR`7NR`7N,7R`7 NIQR`7 +Nch`7 Nz`7 N`7 NR`7NR`7NR`7N!R`7N3>R`7NP\R`7NR`N`7N_iQg`{k7NQh`7NQi` 7NQj`  +7N  "Qk` 5 $ 7N G UQl` k W 7N } Q`   7N  R`:'RN!g!qR`:'RN!!R`:$"!(q"(qN"" R],`",2`"E(nD4"Q"Q"i"Rp``J"X"\:7`O""Ra[[`"#F"M["R[`J#5`##(q &##(rz"`95[###!(r$7`&#4#4(r#`Q(r$O$$"Ra``:`\$*$$5c`$D`:$O>`\>E$a$j$l`$s$q(s&${$u(sW$(^$(s&$$(s&W>N$$M`$$(sW$$(s&A=$$(sJ#$$(s'7`$(sf%:O&B&G a``:`\&O&&Zc`&i`:&t>`\>E&&&`&&(t%A&&`&&(t%A&&(t'v&(t(&(t'&&(t'W>=&&(t$&&(t'7`&(t&:N'2r[='v(u$''z(rW!'''(n[k'(qS=''(s"&''(u$`'(q'(n[=''(s"&''(u$`'%'(o|=''(s"&''(u$`'( ((nqk((p9=(6(.(s"&(7(7(u$`'(?(n=([(S(s"&(\(\(u$`'V(j(d(oR k(l(p=(({(s"&(((u$`'(((og k((q$=((u$(((rW!((o|(ҁ((n[k((qS=(((s"&(((u$`((q((n[=))(s"&))(u$`'%)(o=)4),(s"&)5)5(u$`')H)=(nqk)J(p9=)`)X(s"&)a)a(u$`')q)i(o& +k)s(qS=))(s"&))(u$`'V))(oR k)(p=))(s"&))(u$`'))(og k)(q$=)(u$))(rW!)(o*)(n[k*(qS=**(s"&**(u$`*(q*$(n[=*=*5(s"&*>*>(u$`'*S*F(n[k*U(qS=*k*c(s"&*l*l(u$`'**t(nqk*(p9=**(s"&**(u$`'*(o =**(s"&**(u$`'V**(oR k*(p=**(s"&**(u$`'**(og k*(q$=+(u$++ +(rW!+(n[+++(n[k+-(qS=+C+;(s"&+D+D(u$`+G(q+N(n[=+g+_(s"&+h+h(u$`'+{+p(nqk+}(p9=++(s"&++(u$`'+(o& +=++(s"&++(u$`'V++(oR k+(p=++(s"&++(u$`'++(og k+(q$=+(u$,,(rW!, (nq,,(o= k,(qS=,2,*(s"&,3,3(u$`,6(q,B,=(o= k,D(p=,Z,R(s"&,[,[(u$`',s,c(nk,u(p=,,(s"&,,(u$`'%,,(ok,(p=,,(s"&,,(u$`'V,,(oR k,(p=,,(s"&,,(u$`',,(og k,(q$=-(u$-- +(rW!-(n-&-!(o= k-((qS=->-6(s"&-?-?(u$`-B(q-I(o= =-Z-R(s"&-[-[(u$`'-p-c(nk-r(ph=--(s"&--(u$`'%-(o=--(s"&--(u$`'V--(oR k-(p=--(s"&--(u$`'--(og k-(q$=-(u$.-(rW!.(n..(nk.(qS=.3.+(s"&.4.4(u$`.7(q.>(n=.V.N(tj#&.W.W(u$`'R.l.`(nk.n(qS=..|(s"&..(u$`'..(nʇk.(p=..(s"&..(u$`'.Ȅ.(nk.(ph=..(s"&..(u$`'..(nk.(qS=/ +/(s"&/ / (u$`'//(o& +k/(p=/3/+(s"&/4/4(u$`'V/B/<(oR k/D(p=/[/S(s"&/\/\(u$`'/m/d(og k/o(q$=/(u$//(rW!/(n//(nk/(qS=//(s"&//(u$`/(q/(n=//(tj#&//(u$`'R//(nk/(qS=00(s"&00(u$`'0$0(nʇk0&(p=0<04(s"&0=0=(u$`'0R0E(nk0T(ph=0j0b(s"&0k0k(u$`'0{0s(o& +k0}(p=00(s"&00(u$`'V00(oR k0(p=00(s"&00(u$`'00(og k0(q$=0(u$00(rW!0(n10(nk1(qS=11(tj#&11(u$`'R1((n=1@18(s"&1A1A(u$`'1V1I(nk1X(ph=1n1f(s"&1o1o(u$`'11w(o& +k1(p=11(s"&11(u$`'V11(oR k1(p=11(s"&11(u$`'11(og k1(q$=1(u$11(rW!1(n2 1(nk2 (qS=2!2(tj#&2"2"(u$`'R2+(n=2C2;(s"&2D2D(u$`'2Y2L(nk2[(ph=2q2i(s"&2r2r(u$`'22z(o& +k2(p=22(s"&22(u$`'V22(oR k2(p=22(s"&22(u$`'22(og k2(q$=2(u$22(rW!2(n2(n=33 +(s"&33(u$`'څ3(n=3,(u$3530(rW!36(o 3G3B(o= k3I(qS=3_3W(s"&3`3`(u$`3c(q3j(o= =3{3s(s"&3|3|(u$`'%3(o=33(s"&33(u$`'33(o& +k3(qS=33(s"&33(u$`'V33(oR k3(p=33(s"&33(u$`'43(og k4(q$=4(u$44(rW!4 (o444/(o= k46(qS=4L4D(s"&4M4M(u$`4P(q4W(o= =4h4`(s"&4i4i(u$`'%4q(o=44(s"&44(u$`'44(o& +k4(qS=44(s"&44(u$`'V44(oR k4(p=44(s"&44(u$`'44(og k4(q$=5(u$5 5(rW!5(o5#5(o= k5%(qS=5;53(s"&5<5<(u$`5?(q5F(o= =5W5O(s"&5X5X(u$`'5`(o =5w5o(s"&5x5x(u$`'V55(oR k5(p=55(s"&55(u$`'55(og k5(q$=6(u$6 6(rW!6 (o& +66(o= k6(qS=626*(s"&6363(u$`66(q6=(o= =6N6F(s"&6O6O(u$`'%6W(o=6n6f(s"&6o6o(u$`'66w(o& +k6(qS=66(s"&66(u$`'V66(oR k6(p=66(s"&66(u$`'66(og k6(q$=6(u$66(rW!6(o76(o= k7(qS=77(s"&77(u$`7(q7$(o= =757-(s"&7676(u$`'%7>(o=7V7N(s"&7W7W(u$`'7g7_(o& +k7i(qS=77w(s"&77(u$`'V77(oR k7(p=77(s"&77(u$`'77(og k7(q$=7(u$77(rW!7(o77(o= k7(qS=87(s"&88(u$`8(q8 (o= =88(s"&88(u$`'8/8'(o& +k81(qS=8G8?(s"&8H8H(u$`'V8V8P(oR k8X(p=8o8g(s"&8p8p(u$`'88x(og k8(q$=8(u$88(rW!8(o= 88(o= k8(qS=88(s"&88(u$`8(q8(o= =88(s"&88(u$`'8(o& +=88(s"&88(u$`'V9 9(oR k9 (p=9$9(s"&9%9%(u$`'969-(og k98(q$=9K(u$9T9O(rW!9U(oR 9b9\(oR k9d(qS=9z9r(s"&9{9{(u$`9~(q9(oR =99(s"&99(u$`'V9(oR =99(s"&99(u$`'99(og k9(q$=9(u$99(rW!9(og 99(og k9(qS=::(s"&::(u$`:(q:(og =:.:&(s"&:/:/(u$`'V:7(og =:(u$::(rW!:(p::(p$k:(qS=;:(tj#&;;(u$`'R;(p$=;(u$;#;(rW!;$(p$;3;,(p$k;5(qS=;K;C(tj#&;L;L(u$`'R;U(p$=;h;`(tj#&;i;i(u$`'R;r(p$=;;}(s"&;;(u$`'R;(p$J;;(q <<>R~<><M`:=`=y`=M`=(],``>N=9=@R],`=B@=_=[(Sv=f=b(5(^=[=lE=q=z=|`=~(D==(퀇=(S=(==(W>N==`==(=(b9N==M`>>=(5>(A7`I>_>h>c(w7_=>p(7?N>>>`>>(O>(9=>(b>>( 7=>Ʉ>(q>>( 7>(:J>>(b_cR~rz`:``>Ni` (ˆ(WA~h=((k0(ˆ)(A7d=@(F@(kdNI(ˆ_Y(WA7a=t(zt(k}(ˆ(WA7t=((k(ˆǁ(WA7aJ(6:uR~MuU`:`J[#^\((+Bom((^`%%%%%%%f%%k%%%p%x%m&m&$&4U&6&7I&7&7&8a&<&D&Ge&HM&I)&O"&O&Q&Q&S(&T &T&V&V&oT&o&p&y&z&}&&&Y&[&&$&&l&<&v&+& &&֟&~&W&& &&&&&&^'' ':'d''N'(&(c(dK(h`(h(i(i(j@(j(k(lN(l(mB(n((((iR)NT _[ RRRRRRRRƁR^],`\ǁkR^`Z`:`R̀'`ȁ}R^],`:;[]܁&5R`VށUR`7d߁yR`7eR`7ၺ`7⁺`7ぺR`7䁺>R`7偺bR`7恺R`7灺R`7,聺R`7-遺`7.ꁺ'R`7.끺mR`7/쁺`70큺R`71R`73`7*R`7񁺆Q`7򁺆{`7󁺆`7􁺆`7`7R`7KR`7t`7R`7R`7R`7 R`7<R`7hR`7R`7R`7R`7$R`7R`7{R`7R`7R`7R`7KR`7W R q'R` +R 'R` ^R .'R`c R j'R` R 'R`LR 'R`lR 'R`R 'R`(uR 9'R`S 'S`<S 'S`PS e'S`S 'S`GS 'S `SS + `'S `S  'S `FS 'S`[S q'S`S 'S`]S 'S`pS 'S`  '`bS $'S`w S 'S`!3S 'S`S"S s'S`# +S  'S!`$TS" "'S#`[%S$ d'S%`&S& 'S'`'uS( 2'S)`(S* 'S+`)XS, 'S-`q*S. 'S/`+\S0 'S1`q,S2 'S3`-,S4 'S5`D.S6 \'S7`/S8 'S9`0RS: 'S;`h1S< 'S=`2%S> 'S?`B3S@ ^'SA`5\? (6%F`]y`8_SB`:+9SC`+:SD`{+ <-=SSESS`P@5&["'`7`H`*\*`*]`6Ju6(((((A@SF@&['```@`*@-`*@]*`*]`6J@v@7@(.@(6@(B@(N@(\@(l@(|EAAB&SGAB&A`f`6JBBQB(BCCCwCCCb`*][=DDD'DD`>EEE&EE`;GFF"F=SHF0F=F5`\CFFFSIFF`H(E(n(((C(((((R HG@GFIoSJ`JG"`KHL`LHzSK`MIbSL`O\? ()PMaMp|'U`sRMSM`:'mSMSN`:'SOTMSP`:'UN%SQ`:'SRVN^SS`:'STWNSU`:'SVXNSW`:'YNSX`:'SYZOSZ`:'S[[OFS\`:'\OvS]`:']OS^`:'S_^OS``:'_P#Sa`:'Sb`P^Sc`:'SdaPSe`:'SfbPSg`:'cPSh`:'ydQSi`:'SjeQ?Sk`:'MfQgSl`:' gQSm`:'#hQSn`:'iQSo`:'SpjRSq`:'SrkR@Ss`:'StlRtSu`:'SvmRSw`:'SxnRSy`:'SzoSS{`:'pS@S|`:'S}qSsS~`:'P!rSS`:'SsSS`:'StTS`:'uTAS`:'SvTkS`:'SwTSB`:'xxTS`:'SyTS`:'SzUS`:'S{UKS`:'F|UuS`:'S}US`:'S~US`:'kUS`:'PVS`:'SVzE  VD'S`:VRVS V'S`:VSW8S V'S`:WJTWS Wc'S`:WUXS W'S`:XVXbS X/'S`:XhWXS Xv'S`:XXYS X'S`:YYYdS Y('S`:YtZYS Y'S`:Y[Z&S Y'S`:Z9\ZS ZS'S`:Z]ZS Z'S`:[ ^[dS [%'S`:[w_[S ['S`:[`\*S ['S`:\:a\S \Q'S`:\b\S \'S`:\c]/S \'S`:]6d]{S ]E'S`:]e]S ]'S`:]f^S ]'S`:^#g^fS ^2'S`:^mh^S ^|'S`:^i_S ^'S`:_#j_xS _='S`:_k_S _'S`:_l`3S _'S`:`Im`S `e'S`:`naS `'S`:a oaYS a'S`:ahpaS a~'S`:aqbS a'S`:b$rbS b@'S`:bsbS b'S`:btc9S c'S`:cCucS cU'S`:cvcS c'S`:cwd4S d'S`:d9xd}S dF'S`:dydS d'S`:dze?S e'S`:eI{eS e['S`:e|eS e'S`:e}f2S e'S`:f8~f}r fF'S`:ffS f'S`:fg5S`:'=g]S`:'SgS g'S`:gh +S g'S`:hh8S],`::hI`: hUZhm[hchqhyhzh{h~hiES i 'S],`:iWiwS],`::i`: +iXi\i]i^i_j`j$aj<bjSfjfnjS j'S],`:jj],`::j`: kVkWk.dk>okRrkovkwk}kkT k'T],`:ll3],`::lD`:lPRlbSl{TlUlYlelglhlim jm(km?lmRmmopmsmtmumxm|n'T m'T],`:n9ny`+oC `+o`+pX`:+p'`+qe`+q`+Ár]T`+ār`+\?  ƁsysssssK`:],`:ǁtttKtttK`:`:ȁvmvrvvuvv}K`:vK`\Ɂw#w(wFw+wFw3K`:w@K`\ʁx$x)xJx/xJx7K`:xDK`\ˁy3y8yNyAyNyIK`:\́yyz!yz!ya`:],`:K\\́{8{={ST{F{S{NK`:\΁|||% |#|%\(Ş((!(k(Ƶ((:(Lj(( с$T`Ӂ-5@IK`:'i~][`:`:+`>J|=(m(~Ձ3FzyKzSK`:hT`:'T`:+`*`>J4(T (T9(d(&؁K`:فf~~][`:`:ց"A "`:(D(((ɰ((ځ'6"V`][[[\? ܁.`:߁6;DBD\ၺa\\݁ T  `(ʉ(ʹ((!(T䁺MT +``恺.`9''?'灺T  l'T `聺`'''?'遺 Y'T `ꁺ`''?'끺T T'T`쁺`''T큺bT 2'T`knv**`:`:?`:+~][`:`:+`>JK(? (N(^(n8y8K`:`>J(D.(zk`:`:  `:9DK?KK`:(((%(V(·(θ(GT`K`:+ K`:+O `+T`+`:+2`:+~`+T`+mu{K`:+K`:+`J^(( "T;CK`:`>JP[_v(Ј4;EACE`:((\(м(`]y],`\?  OWddd` 7`: +BJMMMM`  T` vL`P J],`>G[T[[`i}`Zz?` T `:`x +`(X(щ(Ѻ(((O(҆(ҹ(((L(}(Ӯ ``3K`+V`+i`:+!T`+``{+T`+&\? L`P J],`#``][$=LsTXs_T`)]`!`x(Կ(('((('qʀT` )ʠT`7P*T ʹ'T` +)+/T`7,ˈT  J'T!`˝+-FSD`{+.͠T"`{+/θT#`+0T$`+1(0`:+36>HZ`+`'>NxԂ`ԒIԟԭԣ(א(+>JԾ(y?J(אT% (y5"<z@zO7`:^`:h'`u`:]`L6 +)T&)7`:%`]`L73Z6Z>`:H'`U`:]`L8 T'`]`L9 'O+O3`:='`J`:]`L:T( +`]`L;??#`:-'`:`:]`L<T)`]`L= 33`:!'`.`:]`L>T*`]`L?++`:'`&`:]`L@T+`]`LA`: '``:]`LBT,`]`LHT-a``:`:T.]`\CPUT/ch`tT.`:`o\IT0a``:\D4BpT1Zp_`][`:`:+`:>N`Iւ( (+>J((?J1B8( T1[(`(JtxT2a`:``:`:'T.]`\E#(T3;J`:T'`aT.`:~`o\K#'T4=Ja`Z`:`T5'`\Fchwmtb`*\(O((؀((5({(("(ڃ((*(p(((x(ܾ((x((޲((߀((L~=T6``3N-T`+O T7`+P T8`+Q `+RT`+]\? T   7  `:U   M  `VL`PW!29J99],`X *...]`^[~w]`^Y-;;;`x(>(o((((=(q(^\k":T9`]y],`n\?  `emwVww`ahs`:b`cT`dT:`e&T;&&],`k?Zbr7`:+~`+T<`+]`^fL`Pl P _ mT k m]`g   J  ],`h!z!!!!`Zi""*"8"8"8`x( (P(((((Q((((U(( o"="L"cT=`q\? (8r""#qT>`ot""#o##o#`:#)`:`rJ#<#@#\(揁#f((f(u$B$Q%T?`ow$$%$%$`:$`:`uJ$$$(4% (C( (~x%%&T@`~\? z%%%c%%`;{%%%r%%`|%%&TA&&`(((5(h&*&9'<TB`\? &&&V&&`&&&7&&`:'*'2':':':`(((((Y(^(m(TC`\? (((l((`(((TD((],`((( (()TE``( `:) M`) )):) ):)&`:)5M`+\?(( ))?)F)A)N)`:>N)[)]r`5`)c5[)s)q(:'TF5[))(:).(:I)!)).M(+>=))('$)'TG).M?J)))('A(())+TH``*; `:*_ T;],`*m*s****`:*T;],`\?(( *s***A**`:J*$*'TI*.**+M*+`J****.T;((H(TJ`TK`7=;Q`7 _O`7 +TL`7LTM`:'TN`:'mTO],`:|`WWWWWWWWWWWWWWWĕWϕWӕWוWەWߕW㕃W畃W땃WWWWWWWW WWWW"W&W*W.W2W6W:W>W7>FW7>NW7?7475767778797:7;7<7=WWWWWW77777 7 +7 7 7 777777777777WWW#W7?2W7777777 7!7"7#7$7%7&7'7(7)7*7+7,7-7.7/70717273WWWWWWĕWȕW̕WЕWԕWؕWܕWW䕃W蕃W앃WWWWWW WWWWWW#W'W+W/W3W7W;W?WCWNWRWVWZW^WbWfWjWnWrWvWzW~WWWWWWWWWWWWWWWWŕWɕW͕WѕWܕWW䕃W蕃W앃WWWWWWWW WWWW#W'W+W/W3W7W;W?WCWGWKWOWSWWW[W_WjWnWrWvWzW~WWWWWWWWWWWWWWWWŕWɕW͕WѕWՕWٕWݕWᕃW啃W镃W핃WTP`\? %6DI``>Nfm`s:}(E`((((W>=(( 7:J(TQ ],``:>N%,`2FF^O`W(>=mf(ȁ$#{v(怇7'}'`:(D7J(AӉ)TR)],` `*"TS`*`:>NGKV`SM((YI_gc((>Ju'?N`:#(`:N +`& (`N,8TT`>:(y@(+NuTU`(hW#(+w`I߂(>=((W+ (y?NEI*],`O.`Y(N@`N`N_`C(| +(X>NȌ`Ӏ(5`(| +5`(| +( W( 977k (5`(| +5`(| +(e W(e 977k(#(5`)(| +5`)(| +*( W( 9=85(A5`9(m 5`9(m :(E W(E G@(TR( 7A:=eb(A5`f(m 5`f(m g( W( tm(( 7 7?A:=(A5`(m 5`(m )f W)f (( 77?A:=(A5`(m 5`(m ) W) ߄(( 7?A:I9""=(US( QS( W(7`^(m lb(y>=~{(A5`(m 5`(m ) W) :=(A5`(m 5`(m )R W)R :=( ?I!5%(+(>NGI`PK(Q(| +9=^[(A5`_(m 5`_(m `) W) mf(zx) A:=(A5`(m 5`(m ) W) () 7?A:=(A5`(m 5`(m )$ W)$ :=(A5`(m 5`(m ) W) :I(+(>N`((| +9N+-!`4/(75(| +W9=FC(A5`G(m 5`G(m H)hW)hUN(b`) A:=ro(A5`s(m 5`s(m t)W)z() k) 7?A:=(A5`(m 5`(m )W)Ä() 7?A:=(A5`(m 5`(m )BW)B:?J Z!(A.?TVRZ`:mTW`)],`> NV`)΁(^I)(>J.`?NxTX`E`)^))^)^W>N_`̀)Ά)^A9I腒)>=)I)IWI ")(W!)>=0AK${'TYvq)w)^@??I!)y)I(>=0$7'TZ/)?NT[`AE`)y) ^) ) y>NΔT\`怔)Ά) AI  ) +I9wB"?I/C3) +I(F=K) TK) W?NfpTU`yu)y{)Ih7y) N*],`.`) +Eڕ``) z) +>NFH`ES\^@`ec) +w>Ny{_`})Ά5`) k5`) k)  W)  A9I) ^>=) ) 77k) =) +) +y?= ) <5` ) z5` ) z ) +W) +) 7:I"(&) z*) +>=B?) <5`C) z5`C) zD) +W) +SMK) 77:Icig) zk) +=yv) <5`z) z5`z) z{). +W). +) 7:??J) <(((d))xrT]` T^` T_` T`` `)],`C],`+^Ta],`+iTb`*́QQT^`T_`T``\>=..`.T^=,.Ta5.`:.T_)))1`  }}ee],`[>I.Tb>=0('Tc?=.$.W,')Á(Y=E8.L)<=W.w],`>I.Tb>J.Td?=.Tb)=.=..@YRE.(Y(E]Jdk.TdʁȜ`>J.T^h,,979[ff~Teq~|],`[Tf[![[J) W))Ɲ[[[J׀)W)y⁝)WÁ"Tg).`7``>NHRTh`ZT)7Jdqm)t)%k)7 y)%ā +Td"],`>N/6],`1=`EENP`WU) \Y.Ta(Yd) ed) W>=xq).Ti.Ta) 9@C6/*)(Yy8) ^YG.T^h[)kEs|Tl`)~.T^)~)~W> +NàTm`#.T`ހ)) 9)) W9`N Tn`#.T`&")1') W9<8)G=) W9`NWZTo`#\.T`rn)}s) W9)) W9`NTp`#.T`)Ɂ) W9Ԁ)) 9`=) ) WNB` )Ӆ77=!)&!)k8-*)</7=E)JE)k\QN)S7=h)mh)ktq)(v=.)~):ƁޢBTiBB`],`>N],`.` =;6)fGB)#K.T`7`h:=zu))#.T`77`:=)ŀ)#.T`77`:=)#)#.T`7`%:J29)ǁ  [>NV`.(YN̤Tq`.T^hI )׃^)>N17`EBWNJ)׃yP)R^Z)l)Rrl)RWu)>=.Tj.)R=.Te.=.. )R)M?ȁpp[> =.7;Nզ`.W7 NTq`'.T^h)NBR[T.])m)NTr[)y)Eŧ`΄);&)`);ބ);W>=.;N `+.h-@UH)Wk7 HaIhl.T`>=..Ti<=..Ti߄)<>= ..Ti.!)0<=OB.V.Ti<))t)J))))a))))))?)  ́Ts`ЁTt],`:`@997 p9999999999999997^ZQ997DS9979999999999999997~997Ĉ997ߢ|99999999999999 9 +7һ9 с-Tu],`:2`@77 7777 7777 7777 7777 7777 7777 7777 777 777 777 777 7777 +7777 +7777 +7777 +77ׁҩҪS֪S\>=.Ta9:= .Ta9:='%.Ta9:=?=.Ta72Tv: 7*Ӂ`>JՁTe],`\> @ʀ)##(Y(7ȯN=`.Ta9Nr`.Ta9N +_` .Ta9N`!.Ta9N/Tv[N;K[EDMO`VT)$'7@\)$']\)$'W>Iiom)$'7>=)$)#)#k)#g)#=)$)$'Iȇ)$'7 >=)$)#ⅸ)#k鄰)#g)#=)$7h)$'W7I,20)$'70>=B)$MIG)#K)#O)#=Z)$mhche)$'W77>=)$)#)#k)#g=)$7h)$'7Nر`)#=)#⃱)#=)#)#=)#&.Tf)#.Tg&##.Tf*.Tf1)#`4)$9.TfB@C)$'9HG)##&II)$`9`RPS)$'9`=_)#`c)&=vt.Ta&v|.Tf)#`.Ta9`:=.Ta&.Tf)#.Ta9`:=.Ta&.Tf)#.Ta9`:=.Ta&.Tf)#.Ta9`:)")"))؁-3Tw`ہ],`ၽtt.y.\>=.Ta9:=.Ta9:=.Ta9:=.Ta72Tv:=.Ta9:.`7P 77)݁]cn`>Jw߁Te],`\> @)+&(Y(7#N/1=`53.Ta9NBDr`HF.Ta9NUW_`[Y.Ta9Nhj`nl.Ta9N{}l`.Ta9E`),?7P),?),?W>I),?7>=.ۀ),?π)+&),?9:>N` .),?y9.),?y79  .),?y79.),?y79=.,.ۀ/),?4.Tg<),ޔ:NUW[Y.Tf`.Tfg.Tgo)+c7Åv),|z.}),?9I),?7>=)..Tf.Tf).)+)+k)+g)+9I膶),?7(>=)..Tf.Tf +).)+)+)+9I5;9),?7<>=K).O.TfV.Tf]).rhca)+e)+kmk)+o)+kwu)+y)+9>=)..Tf.Tf).)+)+)+9=),)+=)+僷)+=)+.Tg)+7=)+)+c= )+c& &$).(`=?=.Ta&?E.TfL)+cQO.Ta9`:=][.Ta&]c.Tfj)+om.Ta9`:={y.Ta&{.Tf)+.Ta9`:=.Ta&.Tf)+.Ta9`:=.Ta&.Tf),.Ta9`:)*)+)38⁾GMTx`\? 䁾9GMWy``:>NntTy],[:v['\']'^'_'`'a'bN~],[:[ 'd'e'f'g'h'i'j'k'l'm'n'oN~`)3z<)4]'R5[QO)4]\W)3e_])4+~Iy95[sq)4]'R5[)4])4+HA5[)4]#)4+Kv7 ''R`:5[τ)4]׃)4+KA5[)4]#)4+Lv7 ''`:5[)4])" )4+LA5[=;)4]#LEC)4+Mv7 ''`:5[ge)4]vom)4+MA5[)4]')4]J)4NA偾Мy՜y`:`>Ns`7 N Tz],[:['\']'^'_'`'a'bN\eT{],[:g['T|'T}'T~'T'T'T'TNT],[:[ 'd'e'f'g'h'i'j'k'l'm'n'oNT],[:['T'T'T'T'T'T'TNHZT],[:\['P)'P*'P+'P,'P-'P.'P/NT],[:[ 'T'T'U''P5'T'T'T''T'T'TNT`NݏT`N T`N`N/`:N<`OINMa`:\T\`:\>Igwpk)7(^yy)9 ): (^>=0$'T)7?Nސ`:逐)7X)9 )9 W): (^HI!):(): B>=0+5$\'TW)7?=m)9 sm)9 Wxv): (^OTa`4`>N{`N 0`)7'$)9 EI2:6);(=W>NOS0`ZU)7'Rg)9 EIw{);(W=0$'T)7?=)9 ̀)7X)9 );H=)9 );W=);y)8$)9 ?I,!80);y(;W>=K)9 T)9 +Jmt);y?>=)9 )7X)9 );H=)9 );W=);y)8$)9 ?I! );y(W>=')9 0)9JIP);y?=k);y~u)8Q)9 ?I!);y(W>=)9 )9 J);y?=0$-'T()7O;?Ta`:`JR`:`>Nim0`to)7|)>)9 EI!)>y)9 (=0$'T)7?=)9 )7X)9 )>H= )9 )>WN(.~`70)8?)9 ?IK!UO)?k(XWJ\c)?k?=0pz$'T)7OTa`:`l`:`>N0`I)@(^w>= +)@&)7)@()9 E>=G)@&RM)7(^Nos`:zu)7X)9 )@&H=)9 )@&W)@(^K>NϗK`)@J)A `wl`w>=0,6$]'TX)7OsxTa\\>I!)9 ()7(^>=0$'T)7?N{`);RN|`N+~`N:`NH`NW`Nh`Iuy)9 ()9 +>=)B)>_'RIÀ)7)9 A()8=)9 )9 W?=)B)?'R=)B+)?'=%)B98/)?'=E)BGXO)?'R=e)Bul)?'>=)9'R=)B)?#)9 ()9'R'y`:=)B)>_#)9 ()9'R'y`:=)B-$)?'R=:)B+KB)?'=X)B9kb)?'=x)BG)?'R=)9'T=)AuJS)B)BW)B)B+)B9)BG灾5ETU]y`:`> NtT],[:[ 'T'T'U''P5'T'T'T''T'T'TN9B1`OLQSa\V\>=0ak$'T)EKOTa``J)E(À)EK(^OНTa`:` `:`>NM`)FoAI)F(7 J')?I:"C>)F^7 SN)Fv7/J\)?Io"xs)F^7;)Fv7@J)?I")F^7[)Fv7`J)?I"⇞)F^7{)Fv7~J)?J*O',Ta`:`:B`:`> NQVM`ZX)G͆AIo"xs)G^)Gv7J)?I")G^7 +)Gv7J)?I")G^70)Gv79J)?I )G(7:J))?IC"LG)G^7A\W)Gv7ZJe)?I")G^7a)Gv7zJ)?I")G^7)Gv7J)?J*OTa`:`"*`:`>N9>M`B@)IAIW"`[)I w7/oj)I 7:Jw)?J*Oa`:`(~`:`>I)JR (^J㔃W?J)Eb )JR XH?O/3a`:`8@`:`>NOU`E`"mg)K qo)J +(^{)I)J +)K @)K )K W?J)J +X)K HN֢],[1[C!)E>C"! )E)FM#)EK$)E@=0)E80)EWNFL`N)EC^"!kf)Eq)G)EK)E@=)E)EW=)K +)EKX)LP )EH!W;C"!)E)FM)EK)E@=)E)EWN2T`:NFT`:N`T`:NuT`:Fz[)K +A>I&)M(`B?I""")Mj (+B&)M(^7` )I&)M`:"40+)M('"F?)I&LLG)M`:]YT)M('>=q)Mj &q{)M`:I")Mz (+B)I&)M`:>=)Mz &)M`:I")M (+B )J2&)M`:^>=%)M &%0)M`:ID"""PH)M(+B&rrke)M(^`)I&)M`:)I&)M`:>=)M&)M`:?I""")Mj (+B)Mz (+B-$)M (+BH@)M(+B>=^Y)E€?Nqv`}x)J ~)MI")P^7F)Pv7c=)P)PW7lI")P^)Pv7E=)P)PW7?I)P7A= )E€?N$T`+&)J ,)Mz I@"OD)QaV)Qw7=lg)E€?Ny~`)J2)M WNT],`:)Mj 'UI!)R(Y(=䃨)E€?N`)J )R9N`!)J *")R9N8?`FA)J OG)R9IYb])Sw7=mh)E€?Iuy)S@w7;=)E€?I)Sxw7;=)E€?JS)P)Rj)Q)S)S@)Sx)3)7)E%)TꁿAT``P +큿= ][`:],`:V T`:oT`)T],`:+T`W񁿁T`)򁿂T`*󁿂;Q`:+􁿂HQ`+\ T`,vvffT`:T`)T`+\>Im!q)V#(+>=)V#4K`:K],`:\J5][`:],`:.5`:)V|5],`:)V5\ʅ)V)V·)Vn)Vx=.T)V#T=.T>/)V#T=[.Tv)V#T=.Q)V#Q=.Q)V#Q?I.T('TB>=.T*=<.T*?)U`:],`:R)V v0kK`:],`:J.)X!WmKK`:`:>=)Yစ)Y!WN],`: +.)YmI)")Y:(+J2+?ICUNG)Y:(Yw>=0bl$'T)Y?J)Y:9Ɔˇ&·&K`:K`\>=.T=.s)Z)Z+0s7?K`:EK[\>@^Y)Z(ap)ZBYuI|%)Z][>F[)Z][>=.)Z)Z>=.)Z)Z$),4K`:AK`\>=N.T=c)[jy)[=.퀱)[vI)[(zB>=.T*?=.s )[)[ %+3K`:@K`\>=M.T=b)\bix)\b=)\n)\nN],`:.)\bmI!ۂ)\(+>N`)\ʆ&)\n`:?I!)]("W>=70)\ʈC)]PJ)]WP?Idvoh)\ʁ(Y(=|.퀱)\bv??I")\b(zBՁ)\n('>=.T*?(0K`:\>=<.T=Q)^SXg)^S={r.퀱)^Sva`:],`:K\\>=.)^xuTuK`:\>I !.T(+=*.TB.`:?=hV.Tl)_?;zT`J.T"TҏT`\>=.TI " )`(%.TJ<?IHL)`>Ij~n.T('I B>=.['w>I.T(W>=0$'T'T?=.['T>I.T('I B>=.!['w>=T.g['T=.TĀ)`Ϗ׏`J.T#`\>=+.TI@""TD.T('TBh.T)a(W>=0$'T'T?I7J;.T(M)aJ\?=h.TĀy)aI.T^>I.=.*$?=.^%)aA>=E.[^Iw{.T('I B>=.)$?Ԓݓ`J.T$5;`\>=Z.TIo"s)c.T('TB>=0'T?I <$)c(?.TJY?Iei)c>N],`:.zmI")dj(+!)dj('B>=V.Tlz'?=.W#>= .z'=M.TĀh)c`:J.Q%`:\>=.T=.QĀ)e=.T  '`J.Q&#,'05'`\>=A.T=V.QĀ^)fN=h.T `>N],`:.jmI!)f(+>K>J(4.)f9B`mVl`m>Jc+?J+'`\>=.TN:DT`:OfV)gz<=t.j)gy`>Nԙ],`:.cmI!)h&(+>K>J-=IC)h&9W`mkl`m>Jx+?J+(|y|y`\>=.TN2<T`:GSN)h߆z<=a.'yn)i~ ~`>N],`:.fmI!怛)i}(+>K>J!)i}9/`mCl`m>JP+?Jo+)o o `\>=.TNT`:$3+)j6z<=A.Rfa)j^ t*e*`>N],`:.'mI!̀)j(+>J)j9>J+*/8eCPe`\>=c.T=x.b)kmA} Ɵ}\>=.T=. w=.T W=.T)=5.T*=[.Q+=m.Q+##K`:K[\>@耟)l()lBAG)l(^>Ic()lB>=.T)l)lJ ?I%@5h(C)lB>=U.T^)ld)lJv?B7>If()lB>=.T)l)lJ?B07 +>I<]L[(`)lB>=r.T)l)lJ?B7 >Ib()lB>=.T)l)lJ0?BJ\7>Ihx^()lB>=.T)l)lJ?B7>I*z(-)lB>=?.TT)lZ)lJl?Ij()lB>=.T)l)lJ?= .T)l)l(-2T>2FK`:LK[\>IY%c])o`>=s.)o`#I%)o`:>=.)o`:#>=0$''TȀ")o7<TPXK`:^K[\>Ikuo)p('>=.)$>=.Tz)pTK`:K[\>I)%3-)q`>=H.yO)q`(Ia%ke)q`:>=~.c)q`:>=0$'TȀ)q TK`:$K[\>I1%;5)q`>=P. Z)q`)Il%vp)q`:>=.f)q`:>=0$'TȀ)q5T,54K`::K[\>IG%QK)r`>=f.x)r`'I%)r`:>=.j)r`:>=0$*'TȀ%)r:?TGOK`:UK[\>Ib%lf)s|`:>N0`)s|`:'EI)s(W>=.Q)s|`:=.Q)>I)sw>='.Q5/)s|`:XB)sH>=c.Q+I)sW()s|`:(^>=.Q)>K>=.Q )s|`:X#)sWH6`wPl`w>=a.Q+=.h)s|`:>=0$ 'TȀ)sp 6T.66K`:<K[\>NM\T[d^)uփ!Iw{)u('w>=.T*Iۂ)u('T>=.T)?=.T&)uʁ,)u;@TOWK`:]K[\>=j.{b&)v`: T K`:K`\>Nڮ],`:.)wmI)w0(+>=)w0 .`:=>6.?)wG)w0n?IY%c])w`>=x)w0)w`;I%)w`:>=˂)w0)w`:;>=)w0& +)wA`:;%*.6K`:CK`:\>@\W)x(_n)xBWsN],`:.`:=.)x)xn=̂)x怘)x;߰߱?T?[>I!.T=0'T? DDTU[>NcoT`"wq.Q(+.Q(.T=.'#)y.$.'.Q`: +ಧT벧K`:[>I")z(B"!E3.T(+!pbP.Tj)z?(sW>J*?J) T\>=.T* ܲ<T<`\>F'K`:!.{> NIAGE)|w>IX\)|>=xp){=){>=䀴){=){!=:2){>)|C=]U){o=){?=Ȁ){҂){)|9b=){ +=){/AH8AP8`:>Nfi`o=.4K`:],`:`>=5`)~5[Ã)~)~5[Ѓ)~')~N`&.T)~ +`E`)x#)~Ɂ(Y+)x,+)xW>I:@>)xw>IQU)B>=li)~'>=5`)~5[) 'X5[) )~5[) ') ?=䀷)~)~)x9=)~'XxJ *')~A =JJTWJ],`>NJ],`.`O͸Ta`:\㾌`:\>N`O a`;`J"!)u($W0*)u(53)b(^ODITa\O\>C\!hd)>Ix"!}|)b~)u@('RB!)b)u@('BJ?=)u)uWOչTa`:庹`:>N`)uAC !)>I)""6.-)b/)u@('RBIA@)bB)u@('B]UT)bV)u@('BBe?=v)u{v)uWJ)bX)σ)uHOºTa`:ӻ`:>N`)uAC!)>I""$)b)u@('RB7/.)b0)u@('BKCB)bD)u@('BBS?=d)uid)uWJ)bX))uHOMa`:`M`:`>I߄)J*?I!)b)u@( ) + BJ*?=))u.))uWJ:)CV!b^)A> =vp)I)J?NK`:)=Dž)I!)'>=)u)b')uEB?=<6)NOUK`:aW)ȀK>=})^) )b +;[p[>=)I  )J?I%!0*)'>=C)uMK)b'Z)uEBl?N],`:.mI!܂):(+>=):4+e`:\J  )D)?J8?)O]@~Tk@~s`:`:>E`)()(^)()(W>I!yӀ))(A>=0$@K'T@<@7$@C)?J@`@m@g)!W@@AT@A@K[[>I@!%@@),`:J@@),?E@@@`@@)k&@@@),(`@)k@@)kW>I@!Az&A!A!A),A,)k`>=0A;AE$A'TAA$A),?JAA),)X~)X)Y)Zf)[_)\B)^3)^)_)_)_)a)a)cp)c)eF)e)e)f/)f)gd)g)h)iS)j)j)kM)k)l~)o)p`)p)q)r)sJ)u)v)v)xx)yP)y)zz){<){y)~V))))`0-AASpT``0A`:1BT][`:`:+2B:T][`:`:+=BVBVCBbCBi`:'B~][`:`:+\>IB!BB)(+>=B.TBϬ`:`:B)1?0) BV4CCD1yCD1C'K`:C5T['CTT[+Cp[*`->NCC`-C==CքC)솫C)&CC)`:&CC)`:&DD)`7JD D'):D6DADPKDGDP`:JDJDJ.06DUDZDTDkD\>IDtDDx.T1(+>=D.TD`:`:1?;DDE~DE][`:`:>=D.T6IEE-E.T2(+>=E>.TE\]`:`:Ep.T12?JEE.T28EEFAEF`:>NEE`E=EE)LE.0IF"!FF .~;(+F3F,F!.~;(}w>=FLF@.T14FTFTFF\K`:FiK`:`>=5`Fz)L5[F~F|)9'5[FF)9F)5[FF)9'5[FF)9F))9x?JFFЀF)LA7FFSnFSnF`:GT`:GT`:G6`\> NGSGY`OGcGha`GlG`JGrGxGr)(G}G{)<(^OGGTa\GH\>CG!GG)>IG"!GGG)<G)@('RB!GGҀG)<G)@('BJG?=G)GG)WOHHTa`:H I7`:>NH/H5`H7)ACHD!HPHL)>IH^"""HkHcHb)<Hd)@('RBHHH)<H)@('BHHH)<H)@(H)\BHH̀H)<H)@(H)KBBH?=H)HH)WJIII)ICMa`:\IIIIQ`:\>IIc"IkIg)!IzIrIq)<Is)@(I}) B>=0II'T?=I)I݄I)WOIITa`:\IJ=J`:\>IJJ#JJ)<J)@(J&)e +B=J0)J5J0)W?OJDJITa\JXR\>NJgJr~]`:`:Jx`:`:=J.TJ]`:`:J) 1OJJTa`:JLF`:>NJK`K)ACK!K K)>IK0""""K=K5K4)<K6)@('RBK^KVKU)<KW)@('BKKxKw)<Ky)@('BKKK)<K)@(K)KBKKɀK)<K)@(K)\BBK?=K)KK)WJLL1LL)ILv"!LL{)LLL)<L)@('B>NLL`L=L)LL)WACM!MM)>IM%M2M*M))<M+)@('B>IMKMYMUMO)W(M^M\)<(^>=0MxM'T?IM"M)m!MMM)<MM)W@('B>=NN)NN)<N)@?=NB)NGNB)WIN^NkNcNb)<Nd)@('B>=N)NN)WBN?=NN)NƀN)<N)@=N)NN)WJNOO)A>NOUOY`:OeO[)ҀJOs#O~Oz)N('B+O)N`:CO!OO)>=OˆO)IOO߅O)JO?NOOK`:PP)l =P%P)IP1P9P5)>=PSPI) PT)+nJPl?=PP)A '=PP)IPPP)>=PP) P)+nJP?NQQK`:Q)Q)O IQ5""Q>Q9)('?B%QS.`>!QlQf)(+B>=Q)QQ)!W?=RQ) R)R )n=RR)IR*R2R.)JR6?IRRRR)<R)@(R)\BJR?=RR)sR)K=RR)=R.SR)Ҁ0=SS)ISS$S )JS(?=S?S4)A S@)K=ShSY) +))|))I)))>SsSyYT`-`AST`:'BST`:'KSSVSVS`:T`:T#?`:TF~][`:`:\>ITTT.TA(+B=T.T'A?ITTT.TB(+B=T.T'B?=U.$U&U.TA'U.TB0IU,!U;U0)(+>=UL.T6=UrUg)4UzUzVYU`:UK`:`>NUUT`:UU)!!WIUUU)I('?B>=U)0V V)0!W?=V:V/.T1V;)IVK)0nx?IVf!VrVj)(+B>=V.T6=VV.T1'?VĂV)߃!Wn?ATi)BT) T='MVVVpVV\? V=DVW YyWYWK`:`>>NW'W.`>W4M=WQWJ)WX)'+*7NWzW`WWW)0'EIW"WW)a(WWWW)a(WWWƁW)0(^y>=WW)TX XWW)0zI!WA=X)X")T'B>=XRXK)TXXXyXrXk)0XX)aHzI!WA=XX)TXXXXX)0XXقX)aWHzI!WBJXY)FYYYBkY(YB`:JY+$YBY-.G'Y:.HGYGYRYmY^Ym`:JYaYa.TAHYrY}YYY`:JYY.TBIYYY?YY`:JYYY.~;'?m))t)))])NYYjT``PYK`:QYK`:RZ `+SZ T`+TZ1`:+UZB`:+VZOT`*WZh`*^Z{Z{ZZZZK`:+ZK`:+\>=Z.T)V=Z.T[P)Q) Z{_ZZ[oT[[o[K`:\>=[P.T[e)oZQ+P+ ZZ[[dT[d[`:\>N[[`O[\a`\\`J\ \\ )(\\)(^O\$\+Ta`:\4\`:>N\C\I`\K)AC\X!\d\`)>I\r\\w\v)\x)@('BB\?=\)\\)WJ\\\\)X\)\)HzIO\\Ta`:\]`:>N]]`] )AC]!]"])>I]0]=]5]4)]6)@('BB]E?=]T)]Y]T)WJ]k]]t]r)X]~)])HzIO]]Ma`:\]^]`:\>I]]̂])=0]]$^ 'T^)'?I^!^!^^)^)@(^$)B>=0^8^B$^s'T^p)'?=^)^^)WO^^Ta\^cg\>O^^Ta`:^_`:>N^^`^)AC^!__)>I_"_!__)_)@('B_4_,_+)_-)@('BB_<?=_M)_R_M)WJ_h___q_o)X_{)_)HzI!WO__Ta`:_``:>N__`_)AC_!__)>I` ```)`)@('BB`!?=`2)`7`2)WJ`M`u`n`V`T)X``): `g)HzI!WC`!``)>N``K`:`͇`)N``K`:'I`"!``)a aa)a)@('B>=a )a%a )W=aL)f +agaT) ?Ia}aa)? (' B>=a. aa)f +RIaaa)? ('TB>=a.Tb b)f +SIb(b1b,)? ('B>=bJ.bS)f +TIbibrbm)? ('B>=b.b)f +UIbbb)? ('TB>=b.T)VIbbb)? ('B>=c .)W?Ic-!c6c2)=c:)c?c:)W?=cn.Kc~cu)|PIc"cc)ccc.KP(^(>=0cc$c'Tc)'?=c)cc)W=d.Kd.d$)Q=d6.T[IdGdOdK)JdS?=d_)ddd_)W=dd)\ddfAdf`:> Ndd`d=5`d)45[dd)Ud.KP5[dd)U'5[dd)Ue.KQ)UIe!ee. R(+6>=5`e-)45[e1e/)'T5[eFeD)eUe\. R)?Ieq!e|eu.TS(+>=5`e)45[ee)'T5[ee)e.TS)?Ie!ee.T(+B>=5`e)45[e߁e)A'T5[ee)Ae.T)A?If !ff.U(+B>=5`f&)45[f*f()ҁ'T5[f<f:)ҁfB.U)?IfSfW.W=fbf_)4'T?Ifyf}.TV=ff)4'T?Jfff)4A[ffjTfj\>NffT],`::f`:''''w''''''''''V''w'xEggg`gʁg)Pgg.KP(^g)Pgځg)PW>Ngg`hgg.KPbh)P9Ih""hh)v7 h7h.)^7hghVhK)hbh^.KPhc)P@?^>=0hwh$h'Th)'?Ehhh`hh)ii.KQ(^i)ii)W>Ni i)`i:i1i+.KQbi;)9IiE!""""iTiK)(7!"isij)^7#ii~)v7+"ii)^7-ii)v7:"iۂi)^7<ii)v7["jj)^7]j#j)v7~>=0j8jB$j'Tj)'?))))`AP_`cg``o\? fza`>I.`c(=.`5`5`ŀ)KW)Kc?J.`clb`][[[g <c<`:J$<.dh'1.afhAL\d\\`:ial|e||`:mfb``:>I)J$'.ei?J.ei)))),)W))p``sST`7tv`:u=`v+`mՄm`\?v#)v(tE:O|\)`  +xrwDzD],`\>N`);(YIƁ)T(J?N܄B`.=uW)TI.+v(Y)>=)./){?@ZSK.+v(Y^])KeIl%vp);`>=.+v .=u));`O>Eԅ`݃))T)탅)W>=.+v .=uW ));)9:=..=Ă8)uyINrUrZ`\>Ifyrj.+v(Y(|.=u>=..=u{?@81).+v(Yw:.=u)A=OH.+vP.=u[)e:=e.=le.=uWu{w|B`\>N`)hI +)s>=,)6s>=U)_|l)Np`:)=) .+v(Y.+vO=.+Ă)v}],`>I$.=u(J*1t?NEL`R"ia.+vޓt.=u=. J)~BB],`>I.=u(Jt?J;"*".+vޓ5.=uGO`(V``JYY.=uen v`Jyy.=u(C`J!.=u( \>=.=ēu=.+tv| +``>@!)w$=-)+-)y=4)64)k;9)=E)GE)kLJ)=V)XV)k][)=g)ig)knl)7=x)zx)k})7J)W))E)b)u)")õ))4){))G +1T]y],` 7 T`Z T][o[]y],`T`* L`T`*.V`+C`:+t7`:+M`+T`*L`T`]y],`\?))) T`J.TOOa],`\Db`+Ra\+a`+]],`>=w.T)J.4S[`>=0&ڄ)`:M.M)Ȋb)Ȥ炐&)ȱ胐=)ȾU][J.Tu/wÑ/SL`\>=.T)=.T)= .Tt#)).)k)Ʉ))84C/U]y],` U`U],`+ÑU`\?) ؑOJO],`>I!.U(+J .U?J").U<4.LT TeLm`Jpzp.ULT`:J.LTƒԒ`J.L-T-`J.LT))ː)))T)̖28U`` +` U`% U`U`+U`+$* +`BU`RU`%jU`\>I.LT('I B>=5`P. +L5[ㄔ)ۂ)5[ +)T+#.LTÄ)?IL!t\P.UU +(+>NU +]`:.J4Җ =``J儕)δK(X(B`:44=``:J(/()KAF=_F`:S){>=i.Ut.UU HU )KI!.U(+>=.UU B??)o)͋)͚ )|5;Aa],`\jb`+xa\+`+]],`>J.U)Lb)f炗)s胗)Ѐ )M)`J&.UM.6TC`>II[M.U(+>Npv],`:x.L'UN`:#!)s(+ɀ)s#%.Uk `A'QX'`:`:N!*U],`:3,.L'UNV`:Ib!of)(+>=)B)>=).L'I!႙)(+>=)B)>=()B$`F>2.U&FG'ZN.U'E=z.U$)ѣ')B.M?J.UӚޚ7`:J.U7 ?`>I!(.U(+>I9F=.UU>=.U+J.??J .U?Jov.U.UU H̜ۜ`xJ.U!`Z>N+2l[D4.Uk IQ%\U)`AJm{t)`A¹L?J+)-))%)n)Ӳ)Ԙ))XU``^ U` U`6ӁU`(U`6;U`\>=)M.UM9)) PV) CT;!C],`J$1$.UUCÁV̟`J.UVā`:J .UŁ1=`Z>NGNl`s]P.UU=kI%)x`AJ)x`A¹L?=0'UƁGJG],`>I!!.%.U(+J7>.U?=L.U[.`N|],`:.LI!)s(+>=Ҁ)s4ڢ'K`:`>=.U);?J4;.UǁLUT:``>If"~wj.U78(';B.U78('CB>J""".V(.V(&.V(4UJ.V(cI.U78('EB>J.V(?J*́FF(7`:+4`+>T<`+]`^>IR]V)ګ(+B>I".V(.U78('EB>=)ګ';>=")ګ8+.U78?IRZV)ڹ(+>Nr{`:}.LKoI)ۑ(+B>=0('U?=")ڹ,2)ۑ?IG!WK)()>Fhq`}.T;>I)%()ڹ>JǦ`^'U.T;??J<XC.UUl)ګt)ڹy.Ug`^4A `6]`^>=5],`)UC5[̄).T;<5[턧).VÀ)ګ)ڹ;)J$3+)wJ΁Kibobua],`\b`+a\+`+]],`>I.UT>=.UU=J],`+炪)?NAH]y],`J.UIY"i].UT$.LK\('B>=)ޮׄ)ޮ],`ᳲX?J)ޮ)b()炫9)胫P)ρgvT]`>=.UU.UU=J.UU=Tȁ*W9W`xJ<I<.UHʁ\eU~`>NڬQ],`:.LrJ""*.V(8!i_)(+|)ࣁ(Y(ˁU`>NQ],`:&.L3JO""aV.V(o!)Z(+)Z(Y(с®ݾU꾚U`]`^>OU a]`^!&]`^>JKZR.x[g`^4__`p[]`^>Jmt.UU.U78.UM9.Ug`^4 `6]`^J)wJO-:U!a],`:G],`:>JR#Y)vo.Lr.L],`:O߰U"a````>J"#))K?.UU#na.UU$?v).UU%.UM9)`OͱU&a`\㲆R`\>I)>=".UU':)>=bV.UU(u)OU)a``:][`T.`:][>Iހ)>I.UU*(+>J/:[*?NekRx`Zzm.UU$?J&.UU*)\)']܆)oA)|][>I% .UU(+>J:E[*?Jl&ls.UU.UM9)oA)|][NQ],`:)O@"!)%(+5.$)%(Y(9NMT>`-k4zq)%9T'N`)煁K:N T.`: )煁~;'T.mNorR`t)ր)I!) +(+>IZ"ha^) +(!) +O>J)&?IC"QJG) +(j")煁~;'m(+B)煁~;'m!W('B>I") +(+B) +(.$)煁~;'mB>I) +(+B>=5`) +5[ ) ()煁~;'m5[B@) '5[db) U+{qj)煁~;'U+m5[) U,) ?J )&I "!?5+$)煁~;'U-m(+Bqg]V)煁~;'U-m!W('B>=) +܇)煁~;'mJCOJ)&???I!) +(+>=@/)䯀A) +=L) ++?Ja}h)H~)) g`^4U.[]`^>I&) `>=) +.UU%.UM9)J)&>J{.)x)) )P))<)ڋ))ߍ)/)s)*)) ԁM`[`]_ׁ ]_؁ ][[ف@X]_+ځa][+ہ~.`*܁`*݁/`*ǿǿֿ]_\?׀)  @@\>=@@~'B=@Y@R~'!B=@@~@B䁻@@A(@A(@ _\>I@@..>=@.J@?=AA.K쀘A)偻A-A2AA:AA;S`ANY`+\>IAaAe..>=Ax.JA?=AA.KA)7A)E恻AADADA ]y_][>IAB.>=0BB('?=B_.)IBtBx./JBB.?OBBU/a][BCA][>JBCBB.ׁB)v4CCC:`>=C!.*ICHC`CL.(+JCiCCp)m?NCCu][CC.u=CC.wJCCC)Ag[4CCDCp[][JCCC)m灻D DEDE][>ID D$.>=0D6D@('?IDyDD}.(+JDD[.?=E,.)NEEELu][EcEN.u=EEo.wJEEE)v4EEE`>=E.*聻EEGwEG][>IEE.>=0FF ('?IFE!FJ..>=F]..)IFu!FFy.(+>=FF.w>=F.?JFF.ၻG +GGmGGm\>=G4G,G$.wg\G9.bGV.ꁻGrG}GGG][JGGG.u⁻GGHGHGK[\>IG!GG.؁˦>=GG.tH)?ほHHHH1HH2S[HDY`\>IHV!HjH[.؁˦>=H./)=HH.jH)H)?쁻HHMKHM]_>IHI.>=0II('?IIXI\..>=0IoIy('?IIII.(+>=I.I +_i)=J.J,[=JeJGJ?.ׁJ]JQ.Kg[4JjJjKJkp[`>IJxJ|.>=JJ.t.=K.+=K..+>=K.b4KKMKS[KY[`>IKK.>=LbLM.jLp)&LwLw) +`=L.+=L.+>=MH.M[)&MbMb) +`?JMM.))w) )))))))j)) MMR ]],``3N`N`)N2N2NN=NNXc]],`Ne`\?) NrNx)NNNNN`JNN.NNOINOINK`\>IN!N.>=0NN('?=O4.ĀO@)[ONOSOOXOO``\>NOrOy3`:$OO})IOOO) `JO?=O.OO.O)OOQaOQaO][O`:'\>NPP +]%[P(P ) + IP6!PDP;)'JPP?IP\PjP`) `>DP{>=P.PP)')PP)'>=P.PP)')CPQP)'>=Q.Q$)=Q8.QGQ>)')QfQkQ~QrQQ{a`'\>=Q.Q)=Q.'XQQR QR Q`\>=Q.Q[Q)))1))m))\)RRYU0`[`RU1`*RU2`)S R]`S U3`_S> L`SJSJUCS^UCScM`SoT`:SU4`_ST`+\>=UU.U3U5.u=U'.*S)S,S)T#T2T+T')('QXBTZ+T)`TT)T) TT)+ UHUPUvU^Uv`JUaUiUa.LUzUUUUU`\>=UU.LU*V# UUVTUV`JUVU.LTVV"ViTV6ViV<C`\>=VMVE.LTVd* " +VnVwVTVV`JVV.U2VVW6TVW6VT`\>IVVV.U3U6r=0VV('U7?=W.U2ĀW&* W;WHXWQX`>IWW"W[.U1WuWk.U3U6r>JWW.?NW?[IW"!WWW.Le (+!WWWW.Le ?(+B>=X +*X(XX.Le ?>=XD*'JXfXv&XX*`:XXXXXX ],`\>IXXXX*(Y(JX?=X؀X*XXYqXYqX`\>IY!Y .U1>=Y".Y.. =Y>.U1)?=YcYi*+YvY{YU8YY\ YYYU9YY`JY*)*,***?**%*u**** YYuU:]``Z`7Z7U;`:+ZUU],`+ZnU`+ ZU<`{+!ZU=`+5ZZ[Z[ZM`ZT`:ZU4`_[U>`P[SB`:\>I[![[*(+B=[[.L'x[*? [3[9*P[>*_[O*pT&[i[i*` $[[\ U9[\ `J[\[[.UUU?%\\"\|J\*\|],`>I\0\=\4.U(+=\F.U\U.`?J\i\p.U&\\\V\\`J\\.+\\];V\];\V`\>I\\\.U3U6r=0\\('U7?=].Ā]-*']@]K]x]X]x`:J][][.U@]m.V&3,]|]^]^]`:\>I]]].U3U6r=0]]('U7?=].U;Ā^ * /^!^(_^0_^5`^D`^W][>I^p^~^t.U3U6r=0^^('U7?=^.V^* +A+=^^.L'^^* +1AJ_ +_.w0_!_0bT_<b_CT`)]`>I_^_l_b.U3U6r=0_|_('UA?=_.`+-N__u]``__.UUTI`"`&* +>N`@`NUB][`d`Z.U3TUC*UD*w@``* (+``>=a +a.U3U6)r=a\.w=anai.i4ayayaazp[`>Jaa* (bbbKb-bK`xJb0b=b0.U)bPb]br`bfbr`{Jbibi.U< -bwbcn`bcnb`{\>Ib!bb.U=!(+=bb.U=!?=b.U<Āb* Ibbb.U< (+Jb?=c .U=c c&.U< 4c1c1ci`>=cYcIc<.UU!2cscxiU8ci\>Ncc`ccIcdcc.LT('I B>=d(d!*d3>=dVdO*da=d{dt*d=dd*ddd.V&Ab=d΀d*d=dd*ed.'b=ee*e*=e:e3*eLNeZeb?`eqed.UUIe"!ee*w(+!ee*wU>=eՁe*wUE*Nf(f.`*Ef=fFfH`fOfM*fYfQ.J%(Yfa*fbfa*W>Ifpffff{ft.J%f|*9K(X(fB>=5`ff.J%f*95[f̄f*Kf܁f*w.5[ff*T)5[g g *'*=g!*)?IgG!gL*>Ngagh=`gngugg*w.=gg.J%5`g*5[gg*T)5[gׄg*'*;??Ih%!h2h).U(+>=hLhC.U4hThThhU=``>=hohg.Lhh*?=hh.LT =hh.LTh* =ih*i=i#i*i5NiHiT,`&iHi]iV*`=ixin.U3UFi*ii*(Yz3iiuU@iuiV``:>Ii!ii.U;(+B>Jij.U;?Gjj&*%)jJjJ>Jj]'UGjj>Jj'UHjj>Jj'Rkk>Jk'UIk>k>>JkP'UJkyky>Jk'UKkk>Jk'ULll>Jl0'UMl^l^>Jlv'UNll>Jl'UOll>Jm +'UPm<m<>JmK'UQmqmq>Jm'URmm>Jm'USmm>Jn'UTn+n+>JnF'UUnyny>Jn'UVnn>Jn'UWnn>Jo'UXoFoF>JoY'UYoo>Jo'UZoo>Jo'U[p p >Jp#'U\pRpR>Jpw'U]pp>Jp'U^pp>Jq'U_q9q9>JqG'U`qlql>Jq'Uaqq>Jq'Ubrr>Jr#'Ucr\r\>Jrw'Udrr>Jr'Uess>Js''Ufsgsg>Js'Ugss>Js'Uhtt>Jt 'UitPtP>Jtd'Ujtt>Jt'Uktt>Jt'Ulu)u)>JuJ'Um>Ju$u'Unu*%*1**?** * p* +* +* * $* m*** 6uu#Uo]`^`L 8v, 7`:9v@ M`:vZ J],`vh.`<v U`=v U`>w# Up]`^wB`^?ws U$`Z@w]`^+AwUq`)BxUr`7Cx)U],`1x>`TxExEyxWyxfU4`_xtM`x~7`:xU$`ZxU`xU`\>Iy="yHyA.78(';By[yT.78('CB>=yn.>=yy.L)$8*!?*0<*A=*R9x* xx*'I x* Eyyzyz]`^>Iyzy.@(+>=z.z~z/[1z4][zHz5.Up>uzV)g`^4zzzz],[]`^Jz&zzz*9]`^@?Jzz.@Jzz{wz{]`^>=zwJzz.EF{ +{{/T8{{/`J{"{".UrBQ{3{<{T8{H{{MT8`\>I{a{o{e.U3U6r=0{{('Us?={.UrĀ{*:BG{{|T7{|`J{{.UqAR|||T7|||$T7`\>I|;|I|?.U3U6r=0|Y|c('Us?=|.UqĀ|* AH||}|}`xJ|||.U=L}} EUt}E}'Uu`\>N};}D +`}J}^*!.}n.U<N}u]`^I}"}.T7G}ǁ}*!*T:>I}}}}}*!*T;(Y}.T8F>=~;*!f~o~Z~D*!*x[g`^4~~~~p[]`^J~~~*!*>=~*!f ~*!*x[g`^4""#p[]`^>J2=`^b'Uv*!*T;I*!*U>=*!f *!*U)I4A8*!*U>=^*!fpg*!*U*>=*!f`^*!*=*!fg\4 `^\J.Up>t *#b3 .Up>jMJOWXS[jY`\>=|.Up>j*$l*$vNUw`:>ORYUxa`:l`:>N~`:.M9I*%% `=*%%'?I.M9>=*%%$*%%'V.M9?J *%%I&1*.U$?Uy`>JC]J*$>Itx.78('UzB>J6$VD@.M9'PL.M9'>Ios.U=U{>J*$>J.M9QdAO#(!U84!\>NJQ`Wl=*'*.78b=Ӏ*'*= *'*%.UwNb=<5*'*N=un*'*=*'*=*'*I!.J: >N$'`-ECLN`US*(_W.J:(Yg*(hg*(W>Iv|z*(w=*(v'?=5`*(v5[*)?.J:*(9K5[*)?'5[*)?.J:*(9K*)?=.L*(vA?=1).LT =aY.LTh*'* =|u*'*=*'*N,`&؀*'*`=.U3UF** +**(Yz*:*l***** * *$>*$*&*+R U{+U|`<X U}^],`\^U}^],`\\?X*+ ϰFZ## >],`\>=.U}*,kX[(-?5@>],`K`Vy``d`\>In%xr*,`>=.U}"*,`ށ*,Â*,y*,X>=.U}*,ψ*,*,y*,MX\ )w%)\>*,A*,*-*._BH8U~`]],`bU],`:`70)cKU],`:[`70{d ]``p l`qU`*r8U6`*e]+`+fl=`gU][+s`*hU`t`+iU`jU`*k&U`<+lU^],`\+mU`+n U`o*U`*uXU5][+eerxl`\?p*1A e +wsTsUC`)UD`)][>I+/.U6rJ?+?=P.U6)rNrU][N`*I%.U5u`>N +`&.U5u`I""& *28UUSC3I@.U5uT +tlc.U5uL>NU],[Ä*28ULTNU],[6/&.U5uLC\Ic""!wg*2(+*2懨[4[][J&Ň*3́'][-4[`J*4*z!('<,*39(+>=bZQ.U5uLr\'=*2)??I"*1!߄*28UUT>=*1;3&*28Ux[i4FFLGp[`>?>=j*1*I!.Uq>I*1>N`.U5uLI.U5uL>=4.)sINR*2=].)?Iy}*5^>=.*5t??I!*1(+>J*1g[42p[\J$.U5uU8??=PG.U5uU8Jd+xx ]y],`][>I.Uo>=ʀ*7[+J[.U5u?I.Uq>=;3,*7[x[i4FFLGp[`>NY`u][b.TwIx!|*8<(+>J*8IUY.UoJg?Iu~y*9Ӂ(Y(J?I.s>I.Uj>=.U݂*9l=.U*9 +.Ukl}=.U+lJ5?=O.8Y.Ukf*9Ӂ(Yt*9~=.Uĕh>I!.t(+>=.U.UiW*9Ӂ(YiI .Uiw".t>=J?*9W$'U.Ui'U.t''!Z6*9'JN??=z.8*9*9~=*8*7[*9bނ*9*9w)Ij!o.U6r>Nu][.TwI!*<(+>=A=*8ZG*<??Jbpi.lpz*9?g[4p[][>J.U5ub4S[Y[][>I .Uj=".Ukwm?=1.U)o=[L.dji*=&pp*=`I.U*=|>J.U5u>=0΄*=yw][> II.U5uL(W>=zri.U5uL*$=.U5uL#I.U5uLw>N +S`$'U'U.U5uL'%M.U5uR]=.dj*@J .U[,*@g??Iz!~.t(+>I.Ui.t>NS`$'U'R3.Ui'Ul.t'%M.U5uR]=.dj*AJ.U[*Ag??OUa][$][>I.s>I.Uj>=.U.lp9lI.Unw>=4*.UkM"h\.Umޓs.Unl?=.U+m=.Ukwm=.U+l?=.8.U.lp9~?Iame.=fw>=|.lp".+eޓ.=f9?=.++eJ.lp@g[4,p[][>=.dt.lpJ.U5ub4778S[?Y[][>=dU.djr*Ed&yy*En`I.U*Ed|>J.U5u>=0߁*EdNu][.TwI,!70*F (+>JHO.Ue^*F vr*Bg?J.U*Bg]`J.duzXUFX],`(`\>@%.=f()=0.+&0:*G/`e=D.=āN*GDf]f`j`pK`\>=}.UĀ*GjI.Uj>=.U:m@.Uk(+=.U1j):L^4ZZT[],``>I.Ul(+J?=.8.U*Hʁ(Y.Ul~=.Uĕh=2.8<*HB.Ul~hk?|ejUvwS[`J""%*I`%*I`%.U5u`}3U3>],` +a],`\\>I%!3*.U5uT +>=LI*J}M*JhJ[?Im~wq*Jh(Yw.Um(Yy.Un>=*J}".Umޓ.Un=.U :m=3.Uēn?ITe^X*Jh(Ywg>=*J}*Jh>=.Um .Un.UnW*Jh(Y*JhO=.U.UnW#*Jh(Yn~8=8FQ>],`]a],`\\>Ix!}.U5uT +>I!.+e(+>=*M(#":2.+eޓE.=f=X.++e=p.=ēf?=*M(*MJ?I*M(Yw.+e(Yy.=f>=*M(".+eޓ.=f=.+-:7e=U.=ēf?Il}vp*M(Yw>=*M(*M>=.+e .=f.=fW*M(Y*MO=.=.=fW*M(Yf#-6U96>(`],`> NR\R&],`:^`707172737475767778797A7B7C7D7E7FI0;4*PA(>IIcM.Uh(Jipb?Jc?NB`.UhNV`*PAC7B>*Q0w>=O*Q SO*Q W=]*Q0a]*Q0NvU`:*Q WI.Uh(>=܄*Q:=*Q:?N'-`/*Q C9F@*RVwH.Uh>=vg*Qy*RVwy*RVy*P`*PA79:=*PA*PA=τ*QՂ*Q W:=*Q*Q W:J#*Q*1n*71*>*F*G*G*I*J8*L*P*S +;A4U` h `:| k` U{` v` U`MQ][+ U`/U`*IU`+\`*rU`+U]`+U]`+`:k` U`"U{`*=v`+\>=.UU.kp=.Q-!.U4445Uu``>=.QZI1L5.U(+>=0_i'UM.U?I*VQV(7d>=N*VQx[g[4Lp[`>=9+.Q]i4YY-ZS[mY`+`>=.Uj&҆*W`:M.U*W=.U+>=^G.Utg*VQ=z.U+b4S[Y`+`>I!.U(+>=.Uj>&RRL*X`:M`.Un*X=.U+?4`>I!.U(+>= .Uj'UMy.U=.U+?=½.wo*U*U*U*U*Ubm  վվM`'`7`:Rx`Z`6>I#'.>=07A'UMÇ*Z?=×.UĀå*Z=.QZNU`NJU`NĈđU4`_ėĥ.kN `6T$*[e.*Z3*Z;*ZB.U.NţŨ`:ŮŪ*ZIŸż*[n'O=*[$'*['?=5`*[L5[*\[ *[%5[*\[ '*Z&5[&$*\[ 7T'*\[ IZ!tj^.U0(+B>=ƕƍƅ*[L'Sƴƨ.U0?Iԃ*ZUb>NchU`:wǕǐ($ǥǟ*Z^'ǷDZ*Z_=Ӈ*[Ls$'U *] I "!+%*ZUy`\UC7.UÚ(Yw>=i*[AȂv.UU#Ș*ZIȦ!ȵȪ*[A(+>=ӄ*[AU*[??I"! +*ZQU(+B!#*ZQU `>NɔəU`:ɨɻɶ(ƀ*ZQU=*[LY$'U*_y >=O*[ScW.UU%t*ZIʀ!ʊʄ*[S(+>=ʣʝ*[SUʭ*[?=+.UU;4*Z('CB=J.UhcZ*[eg`4uu~}``>=˺.Uצ`=ԅ6/.Uug[4;;v<Uu``>=P.U+=~ul*a +Ug[4̃̃Μ̄SL[`>I̙̦̝*a +T>=̾.UU.=.UJ ?I'+.J3?IE"""!&IJ*a `!d.U͏͇~*a +LTͽ͵*[T >= .UU.=SE.Q]>=|.IG"!VK*[A(+xm*[A(Ϙ>NϰϹU],`:ϻ*a +L'UI"!*c (+ *c (Y(>N4;>`-Z4h`*c 9T'NЗСU`:дЪУ*d ~;'UmI!*d] (+B=*[A*d] ???Iі"!Ѡњ*[S(+Ѹѱѫ*[S(>NU],`:*a +L'UI'"!4+*e+ (+OH?*e+ (Y(>Ngn>`-ҍ4қғ*e+ 9T'NU`:*e ~;'UmI!*e (+B=*[S'*e ???=XP*[Utd*a +Li4]S[`>=0'UMP*Z4eeԃfS``Jp%vp*g +`"i4ԐԐԑS[ԘY[`>=.=*[*gU +&*g_ `M=_Q.Q]Jov*a b4ՉՉեՊl[`>=Օ.Jլճ*[PTP]`>J.Ug`4 + +K p``oJ%.k:..UUUZֻaֻ\>=j.)=։}.UU.=֦֮.krwr\>=.)=.UU.=P&.U:..USDg\4UUmVp`\J\d\.kwוTUצT׮`:׸'`Rx`Za`Z`]`>N `6).2 <*j'H*jÁO*j'Uz`*jIlvp*jUb>N +U`:72($cGA*jѮ^'YS*jт_=}um*kLٍs$ٴ'Uٯ*k?JۏЄ*kwJg`A4ۍ +`^]`A>I!*ljV`(>=0$$'U'g^*ljV`'R~u*lja'?Nڡڨl`&ڴګ*lj`UU=kJ3H:*lR*ja.v}*jg`4۔۔OەU`A`>N۲۶`:&۲)*j*j`:J*mƅ *m6.*kU<)Ypܥܥ`xJ܂ܖlܝ.kܪܱUܸܾU``:'`[>J#*n$ 'U*n'*n$ *n'*n`:!&ݎU/ݎ\>I8!G<.U(+>=cX.U=s.U+?ݓݘ2Uݢ2\>@ݽݲ.U(+ݲ=.Uܪ.USD4-`>=.U+=.w*Z_*hB*i *i*j*nF*n*oJ*o*p 7=U`m `ވ Rx`Zޒޒ޾ޡ޾ާ`޸Rx`Z\?*qW*qf ޒ*q[U` + `:, `:> '`Q U`s `ߟ U]`߫` ]`` U]][!][: ]^[I +[\U`āpp`:`:'`U``\?*s9*sH*sW*se*sv p + `J"".U . .U( ;U(;`J+1+.UC@I{US{`JV"^V.Cxl.Uw\U\`>@.UN`.U=.U*u=*uU=2*.6*uJGN*uaaUn[>Iw{.C>=.i?U`\>=.*vU.E`\>@f^.no*wG^z=.*wG=.U*wG=ǀ*wGU=.UU`\>@"!?7.nH*x?!^X.Ung*x?6r=y.*x?=.U*x?=.Uwb`\>FB&][8+.U>=囁*ydlg[4[`>=巂*yǪb4l[`>=*ydI*yG>F *_` .U>=64*zLFOoX_`e].>={y*z>F_`.U>=ˁ*zwYYU`:$U`4Rx`ZG`]`>IUY.U>Nny`{.U=甃*{UJ缦`*{ɂ*{?I"!*{T#(+M?80.(WA.U^WP*{T#>Nz]`芦`=.4 `>=҄*|t.*{e*{v*{*{mJ'*|u?N=[U^`Z`:`R̀'`d]*{UOa`Z`=`Z`>Iׄ*}(+J*?J*}*~ +&*{e/*{vN[jU]][#"m.Uy*{Uy`ꟹG..'.*}..']]`=".U-".UWJ5K<*~|g`4PPT`U][]`>={n.U*NU][맇*lI!*{T"(+>=* **{T"4::`>=VI.U]*=sn*?J*g`4l[]`>=.U.Uy=* ~)N"`4J.&OO* `W*{*f.Ix"|.U!폂*{Uy`>=*b +U)J0*b +U*{e*{v*{*}g`455!6U``>=dL*{Uy*{e*{v)U*k =.U*J*k *{>=?.UL*b +=pc.Uw*J*b +*{b4LS[`>=.U.Uy= .U*=.U=08>* *s*tg*t*u5*v0*v*w*x*y*{;*P +Ł U``'ȁU`*ɁU`*ʁ< U][`:`[`:`ˁ U],`1`́ U],`1`́ v`΁U`+ρ.U*`+ЁMU`eDсU`{ 7ҁU^`Z`:`R̀'`+ԁ!T"`{+Ձ;T#`+ցZT$`)ׁ{0`:Ӂ uU][`:`: 5v`\?̀* $فSD`{J.UہSD`{\>=.UĀ*F._`&.Uʁ|>F6P?SK`IG*U>=*-U=*-U܁iT4ia`Z`:`T5'`\>=C.UĀ]*ၻn||7`:`:'``:]`L> NU`7#NU`7?N!Ql`(#*Y(^N8CQk`JE*Y(^EV_a`ohc*Y(^yvt*^|*}|*y>NM`*Y*AI*v (*v>=**=**I +*v (*>=**7*?NSY`:+Ieti*̀v*>=*>*YX*W*H=*Yփ*YX*H?NM` '+*<'7*KC*YP*>J\c.Ul*-t* ⁻T&7`:`]`LJ.U**ほFF`: '``:]`LJ)).'5*;*'A*5䁻KeT'kp`]`LJxx.U'*偻`:'``:]`LJ.'**(*6恻CT(!C&`]`LJ...U'?*灻Hbem`:w'``:]`LJ.'**+*9聻T)`]`LJ.U'*遻ii#`:-'`:`:]`LJII.'X*^*.d*<ꁻnT*`]`LJ.U'*끻$$`:'``:]`LJ.'*"*1*?쁻)ClT,JlO`]`LJWW.U'h*큻q`:'``:]`LJ.'*%*4*B'T+' `]`LJ.U'#*,1Jw6J=b`*\>=R.U)=g.UĀ|*(=.U.U@!.Uʁ|-4``J*U@"!*(!% .Uʁ|-4))D*``J0:20*[CE݁OST-_ma``:`:T.]`\>=.UĀ*;T/;`T.`:R`o\>=.Uˀ'*N,*]&33*n`;ށ@DT2Uja`:``:`:'T.]`\>=.U*Ā*rT3r`:'`T.`:!R`o\>==+.ÙEW*]*c*&jj*`;߁w{T0a`M`:\J.UĀ*SBUB7`:M`]`6> = **&*QdIALE*(+B>=0]gu*?I!*('UzB>I*π `>=0$'U݁*I"!*π('B!70,*π('QXB>=0MW$'U*π'U߁*??NU`́*π('QXBN'`*'I*(>=*#&*V<+Z)`?NU`R YI!.U(+>K>=*X&.U*`:[S[Y`>J`6**?J5y<.UOK*πU*[*f*Vg`64~~=`]`6>Oa``62``6>J**σ* *(X$*RxI*J>J .U*π***Vg`6*k?J%0,*k1*JGb +Uu +7`:M``6]`6>N3<`KG>*M9V*J`g.Up*x*0g`64 + `6`6>=5`6*5[*T7  *T7GR5[ W U*T8 o f*T8FQ*F   >`:    *L{>I     *L *c(+>= + + +*L +*c +4 +- +$*L +5*c?J +W5`6 +^*5[ +x +p +n*CL*$5[ + +*C*C + + U +  !`\>= V E 3.U Q F*ՀmU g*= x.U   @U  @ `\>=  +*UN * ;U` O =.U [ P*mI e! z i*(+>=  *U *I  Ձ * >=  .Uʀ  *v?= !.U? E J U ] \>I f j.U>= |.U .U?  IU I b`\>F  U`  .Uʁ|>=3"*jw9*MN`jUtj|`:'`U``>N`:&*** `:J.Uʂ *24e`>J(:*2?*E* K*U.vtUU`:U`U`R(U`]`>NIQU]%`Ze]S*]UV + Ota[]`4S[]`>I!*'JǦ`*?NRx`Z*')N`:#*IUy`'*;71*I\`:NGL'`#TN*IUy`_*Loi*I']`J{.U*r* *n*;*L*I.i&*JGR`4ss]`Jyy*̀'UU%``+`>N03R`J=.Uˀ`+4UUg<`mK``>NU`&*`IDŽ*U**%>I*(+J&*`?J#6/*&*M(^wFA=8*M(^[*y*`>J*J*?U#Rx`Z`+`>NLO]%`cQ.U̇ + Cq{x*F'>I*F')U**,>Jʂ*F')?J+U(R`\>N,2`A4.UˆI**?IR!\V*A(_W>=xk.Uˆ*AH?=U'=R`\>N`.Ŭ&*`?I!*(W>=$.Ŭ-*H?BP UUi Uu`][`:`:`:> OUa`:`:p`:`:>IЃ*P(+BJ+?NW]%`:, *P'U`:4*`:`:J"$"*zI + C<IC*'>NchK`:pj*')I"""*GR'D*G'C$'܀*'(*GB"*GCa*"*GC>J6'U?J_+OwwUa`:`:`:`:> I*h(+BJ+?=*hЄ*hzII*h `J+?N  0`*h'EI,40*^>=D*hTM*hXb^*WH?=v*|*h'EI*^>=*h*hX*H?I)*h'E(>N=A0`JC*hU'FId|oh*h'Ew~*=*h$*h'U?>I*h'E(ΔW=*h$*h'U?J$'U*hIUeY*(+=n*|?NU`:NU`:΁*'UmI*T(+B=*T +*'Um?I!C!*B8,*(9*T(+B>JT[*B?Ipxt*('B>NRx`:*'UmĬ*C(+B=*C*'Um?I!!*B*@*C(+B>J4;*B?IXg`\*('QXB>NRx`:*'UmI*4(+B=*4ҁ*'Um?I! *B *@ *4(+B>J  &*B??J B'U*G****l***************"**Y*'****O**** ******$  U]```*  2wU` !U`!.U`!HU` !eU` +!U][``!`` " k[ "< U`% "] U`M"pI`"y"Q][+"U`*"U][+#""*"*"k["U`%\>=#Q#E +#R.af.n=#v#j.U U&##.k ]y],`p=#.Q##.U 4##)#Uu``> =##.U U.>=$;$2$)*^Ug[4$@$@$s$ASL[`>I$T&$X$X*`=$a.?=%$.QZ=%.I%N%-%6U4`_%<&%J%J.k `N%^%g +`%m5%%*^M%%%*^LT%*S%%.U SE2&& .U SB1N&1&9 `&?&L*&V*^&`.U .=&z.U&&&*Sg[4&&)>&p``>=&&*`+-I&&&.I(& J&?I&""""'&*T '/''**T'\'S*^T!''y.U F!''.U 4>='.I'='.U*=('.U U.==((.Q]>=)".b4)I)I)i)Jp[`>=)W.=){)r*SU)))**7('CBq=))*Uą)**=)).U U)**;4***`>=*.b4*)*)***S[`>=*.o * * ##l "٬ ***V**\>=*.U)***V**`J**.U**+++\>I+ "++.I(++,+%.I(+/ J+:?=+F.I+O=+e+].k =++t.U U.<=++ ++.afv++-+T+-+]`>=+.I+ =,3,'.U U.=,, +,.afvJ,,&--.k `-*-0-G-|-V-|`xJ-Y-ml&-t-t.k `---V--`J---.I(----V--`J---.I(----U?--`J---.I(-.. .+-..+`J....I(."  .0.;.jd.L.j`:J.O'V!.n.y.e..`:J.'V..2u.2u.b`][[[>N..K`:$....k &'...k ''V/// .k c'///'.k rN/E/G][`:[2/Z`:['./h.cg'/.f/*;m'K/*W'V/*WI/π/*;>J//*?=//*'x00.U )?nK>=0.0-*'l0C0;.k )n0X[0_p[>=0k0j*'l20x`:`:'.0.cg''V 'K'V +'V'V +nAG11 .I1"1">=1413*'M'V nB1R1d1d>=1t1s*'M'V nB111>=11*'M'V nB111 >=11*'M'VnB2>=2928*'M'VnB2XJ2i2p****0*D***c**+*** *œ $22V]y```*%22O7V`$`6 (3QV][``%3`F``%13SB`:+23 SE`P3933SC`*)4U`{+*4U`++LU `+4ML`*,M V[-N V`.Nl V]o`N`/N V]o`N묇`0O*K]`+P7P7P84p7]847cV[7wV`\>=7.K7 +`i)7.wA0=7.SD 77xL=88(8.af.n,*-* 7PQ89899(SG8M9(8SV[\>=8.K8 +`i)8.wA0=8.SD 87xL=99 (9.af.n,*-* 8964+4E5T54I5T4Q&[4^'`4h`4v`4*`]`6>J454h4*Ł4*4*ݩ4**4*g`64555O5l`f`%>J5"5-P5;*{)75Y5s7KSF5}7K5&[5'`5`5`5`5`6*`]`6>J6!66;6@*݁6I*6O*6m*6*6* *6*/g`64777F7 l``%>J77$P72*)99-9@:V9[:`P>N9h9SE`9,'I =99*3e9*=99*3'V'V=:1:*3'V'V=:v:_*3'V'VJ::*3D:::SD::`{J::.U)L:;<SD; <;t`{\>I;%!;4;).U*(+>=;P;E.U*=;`.U+*?=;}.UĀ;*f)I;!;;.U)(+>=;.U;ͪ;.U)4;;<;p``>F;<$<SK`<< .V/>I<0<9<4*zV>==<<*zV*?@<<?<?<a`\=b`+='a\+=6`+]`>==Z=L.V,4=a=a>D=il``>===y*ϰ=~)N==`=#>*ϰ.=>.>.V/>2*wb4>O>O?C>PS[>WY[`>I>!%>>*N`>=?? .K0?"*N&?)?)*X`??Y?M.K0wJ?e??x?l.K0?*0b?*F?*U?*dA??Aw?A?b`*][>=@.)4N@ ][I@,"!@>@0.V,(+@I.V->=@_*р&@_@v@h.V,w][>=@*р@[=@.SD+LI@р@*Y>F@A@_`A@.V.>=AA*?@ANA;.V. A;AU?FAbAAk_`AAp.V/>=AA*Ҹ=A.:JAA*р:AABAB\>IA"""B.4B%B.V/ BKB8.V. !BvB^.U +(+>=BB.U +w=B.U ++=BB(B.afv?EBCC~'C C~`>ICC.4=0CC''V?JCa&CaCvCh.V,'`FCCD&CD`;>ICC.4=0CC'V?JC&CD +C.V,&`;MDDDlSHD,DlD1`\>=DPD@.U HSHDa*];DqDvEUDED `\>ID!D.4>=DD.K0D*>=DDD*U<EEEUE)EE:`\>=EE*uU=E.:=EEFAUEFAE`\>=FE.V.F *y=F.F.V/F2*w>FFFKFUFVFFg`\>=FFy.V/F*{y=FF.V.F*{wHFFGU FG`>IG G)G.U +(+>=G:.U GX+?JGyG.U +BGGISIGI`H>NGG`HGO=HH*ر"H1H*H.V.(WHDH3.V/(J=HcHP.V.4HkHkIH|V``>IHHH*ZV>=5`HH*رHH*ٗLHHH*ٗLKWK>@H܁H*ZU?HH=5`HH*رHH* +SLHHH* +SLMWM{=I(I.V/4I0I0IIAV``>=5`HIO*رIVIV*کSKIZIVIV*کSKLWL@IpIk*ڍVIkIw{JII*رIIIIdII`:JI'V JIIIeII`:JI'?JJLJLJ"b`][`:[> NJ1J3][`:[2JF`:['.JT.cg'Jp.fJ}*m'K$JJJ.&FG'J.'E'V$JJJ.&FG'J.'EIJJ*>JJJ*?K>=KK*'lK.K .V,)nKC[KJp[>=KVKU*'l2Kc`:`:'.Ks.cg''V 'K'V +'V'V +n=KK*''K.'En=LL*'&LL.&FGn=L(L'*'LLdLHL5.V.][[[4LLLLLbLM_`][[[JLSLULS*)n=LsLr*'SKLLL~.V/][[[4LLLL_`][[[JLLL*Ħ)n=LL*'L.4nJLL**ɛ*ʱ***:**/*&*)*ԯ*1*՚*E*ֵ*K**{*.*n*۬*JRO:O@XV!`TOlV"`:'UUOV#`:'UVX U],`ZXOOXcOXcO`:\>IPPP *D(+B>=0P*P4$Pn'V$P`*D?NPP],`:PP*D'U=PP*ࠀ4PPX^PRx`:`>=P*P߂P*zIIP!PP* `>IQ QQ*RQ TD> NQB`:NQ]`:=Q*QQQ*XQQT(^HzINRR +`RR *'EIR*!R1R.*(R4W>NRMRVV%`:RoR^RX*XRk*HzI=R*RRR*XRR*WHzINRRV&`R̆R*<'EIR""RR*(RWRR*(S S*(SSS*(^y>=0S2S<$S'V$S{*D?=S*{SSS*=0TT$U!'V$U*D?NUAUF`:UbUNUH*XU[*)HzIIUt"U}Ux*R'DUU*'C>=U*UU*XUUЇU*(^yH?NUVQ`:V"V V*XVV*)WHzINV8'`K>=VZ*# VeVk*V`wVl`w>=0VV$'V$V*D''V'W'*'=WTWL.UVW\dWc*Wi*# Wo*{Wy*;IWWWW*zI(WUB>=WW.UVWe;>=0XX +$XD'V$X6*D?VO.`Z OYXhXnXV(XX\?V:X`Z Xe Xn*ZXXZsP `\X `:]Y '`^Y `:_Y6 `:`YM Uy`dYZY`YYfYYl`:Yw'`Y`:Y`:\?\*]*^*_*`* Y`eYYZ@V(YZ@\?\+]+^+_+`) YbZEZNZqUZ^Zq`JZa!ZjZa.^(+B** fZvZ|\JV)``xhZc`;+iZr`+jZTA`+n\? lZ[\H[\H[ l``f>I[.[9[2*(+J[B+?K>N[s[x`f[~nJ[5`f[*5[[[*9c[Ȁ[*ԁch5[[[*9r[[*Ԩri5[\ \*9TA\\*'j*9\([\/l[>J\9+**o\M\SbV*]y],``r\ U]y],`s\ k`\\\\\\k`\U]y],`\?s*r* \ѧu]]!]]']]-a],`\]Vb`+]da\+]s`+]],`>J]]].Ur]*b]*2]*A]*P]^^"^^"`J^^^.ks5^'^0^k^8^k^BK`\>=^W^O.ks^b*75v^p^u^^z^^`\>=^^.ks^*:w^^^~^^^`'\>=^^.ks~^*<x^^_5^_5_`\>=__.ks_(*`=y_:_?__G__Q][_b`:'\>=__y.ks_*Ł_*;z______ ],`\>=__.ks_*F9{__`;_`;_S``Y`+\J`` `.ks`)*`0*>|`@`G``P``c ]y],`][>J`q``x.ks`*0?}`````\>=``.ks~`````][J```.ks@``aw`a][Jaa a.kswaa a4a%a4][Ja(a0a(.ksa9aAaU'aFaU`JaIaQaI.ks'aZana&ava`;Jayaay.ks&aaacaa`;Jaaa.kscaaaraa`Jaaa.ksraab^bb^b`|b"``>Jb1b@b8.ksbJ*#bR*0bcbgbbnbbtb`][[[>Jb&bb&bb.ks[b*][[[*** *l**6*****~***q***[***}* +bbeV+`b V,`bE` ccWc-V-` c;cdV.` csccccccV,`\?*I cccd~4cd~c`:`>Icddd*!W('V/BJd!d(?Id3dLd>d7*!W('BJdYd`?JdldsdddAdd`:>Idd.(dJd'V0?Idd.(dJd'?Jd'V*z*I*eeiV1`e;`eQT.`:e_O`*eV2`:+e`:+e`:+eU+`:+eU,`+eeieie`fT.`:\>Iff(f!f.(fA>NggU`&gg.`NhhV3`5`h5[h.h,*h7h2(hDh>*K5[hYhW*1h]`hh5[hzhx*hh~.T.b5[hh*1h`h5[hh*hh(hЂh*K*=h.V2hii*ww?** eii8iTi?iT`JiBiNiB.iYi^iUigiiz `L\*7**iilV4`iM`iijijiM`iT.[iU`\?*3 j j*O&jj*B`:j#j(kUj/kj4M`jO``>Ij]"!jhja*(+!jjjs.(j*Jj*?Ij!jjj*ɀ(jj.MBJj*?NjjV5`#jjj.M'(k )k&k".M'`Nk4k>V6`#kIkDk@*'(k[)kqkm*'`Ik{!kk*(k*Jk*?Jkkkk*ɁRkk.MDkklUklk `L\>Il["lrlkl_.(lll.(+B>Jl?=ll.U.l*=l.O)***lmoV7`m4`:m@'`mImImmZmm``:mk'`mqT.[mU`\?+ + mm+6&mm+)`:mmnnUmnnmRx`Zm``>Im"!nm+(+!nnn .(n!+Jn)*?Jn;"nMnHnB+\(nP.Bncn^nX+'](nf.'nsnxoUnon `L\>In"o on.(o$o4o..(+B>JoE?=ocoW.V8.ox++++_oopV9``o\? ooooo`oop;Upp;p`p3 `L\p?pDpV8pRppe`p `L\+++=+āpptV:``rƁq`:ǁq`:ρq'q'q`qBq`qH`:qW`:\?ƀ+ǁ+( q'Ɂqeqqqq`JqqˁqqsSYqs`:>Ns$s)U`:s@sSsN($sos\.'sf.Jsw$s'Us+́sstUstsp`s `L\>=ss܁s+LVsYt .SÝt"t'tV8t5ttHp`t] `L\>=t|tttl+LVtst.SY+c++I++cЁtt~KV;``uҁu7`:ӁuJ`:ہuWuWuusuuy`:u`:\?Ҁ+Ӂ+ uWՁuuuuu`Juuׁuu|SYu|u`v `6`:>Nv3v>`:vHv@+UwNNv`vgV3`5`vm5[v|vz+vvv+78b5[vv+1v`v5[vv+vЂv+Ԅb+NvvV<`:vw w+wNwU+`:Nw/V=`:NwB`:NwN[=wU+5`wb5[wjwh+ c w~wzwn+V2b5[ww+ c 1w`w+ c Iwwww+U+('UB>=w+ w߀w+U+=w+ +xx=5`x4+x@x@+ +s U,x2x@x@+ +s U,W=xR+ =xnxcxW+U,D7=x+ =xx'V>Xxx7yxx+ =(^WHWx+ =G=5`x+5[xx+ c xxx+b5[xx+ c 1y`y5[y y+ c y'y$+ =b5[y<y:+ c 1y@`yK5[y]y[+ c yhya+ +b5[y}y{+ c 1y`y5[yy+ c yyy+U+b5[yy+ c 1y`y5[yy+ c yy+b+ c >=5`z+5[z z+ z6z0z$+b5[zKzI+ 1zO`zZ5[zlzj+ ztzp+b+ Nzz +`:zzz+wNzz`5`z5[zz+ +'V?5[{{+ +${-'V@{#.'5[{7{5+ +${]'VA{U{I+T.'5[{g{e+ +${'VB{{y+'5[{{+ +${'VC{+'5[{{+ +${'VD{ހ{+'+ +I{{{+ ('UB>=5`| + +5[||+D $|1'VE|,+ '5[|=|;+D $|W'VF|O+ +'5[|c|a+D $|u'VG|q+ ='+D ?=||+ +$|'VH|+K 'J|||+ +A؁||}U|}|`} + `L\>=})}!}+LV}BY}W.SY}e+&}r}r+`6ف}}~IV8}~I}`} `L\>=}}}+GLV}s~!.SY~/+8&~<~<+G`6+@++a+ +܁~N~TVI``ށ~ V`߁~ 7`:~ `⁻~~~~V`~7`:~`\?ހ+_߁+m+| ~+ +`VJ`9VK],`:@`7H7T7T7PVL],`:`7H7T7T7P7/717.VM],`:`7H7T7T7P7/717.705VN],`:>`7H7T7T7P7/717.71{`)g`*VO],`: +`"%(+.147:=@CFILORUX[ehknqtwz}  !$'*-0369<?BEHRUX[^adgjmpsvy|  #&),/25?BEHKNQTWZ]`cfilorux{~ + ",/258;>ADGJMPSVY\? +*$VP` r`7 O`7 +Q`7 s`7 VQ`7&>E`7,]t`7-{e`7/f`70D`71h`7:VR`7;Mn`7=\? +SYUW`uVS`VT`VU`VV`%VW`NVX`7VY`7VZ`7 V[`7 +V\`7  ?V]`7 + eV^`7  V_`7 V``7 Va`7Vb`7GVc`7oVd`7Ve`7Vf`7Vg`7!Vh`7LVi`7zVj`7Vk`7`7Vl`7Vm`7*Vn`=\? +  Vo`"Vp`#VM`$VN`&\? +!2'8>Vq`)`Vp`*Vr`+Vs`-\? +!.)/9Vt`]],`1Q]],`2Vu],`3`*4`5Vv`6Vw`*D++JWQ]],`kVu],`}Vv`\?1+"2+"5+" + 8\`J.Q1\:ȒӒ`[_+]_J.Q1_+#; &][>=/.)3=G.Vu+2J_tf.Q1<a],`\\>=.VvĀ+$^5=.Q1+$^=H +Ha\\>=2$.Q19+$>MRbYc`\>=v.Q1b+%&?Z][+\>I.Vu2(+>=.Q1Z+%x>= .+ .4W4I5!F9+%x(+>=fY+%xvs.]@?@$]$\>I.Vu2(+>=.Q1]>=..4y4=.VxBB).7Vx@7\>IIM.Vw6JY?Ie!ui.4(J{?=.Vw)6=42`>=.Vw*6I".4w.3J?N ],`.Vu2=%.Vu+2=.Q1]I!.Vv5(+>=.Vv+'5?+#/+#o+#+$>+$+%+%X+&1+&+(E EI!.gG(+>=5]],`.gG5[ʄ+)х+)^5[ㄘ+)b+)x5[+)х+)+)I%.H(+>J85]],`?.gG5[MK+*y]+*y?Je5`.pD.gG.H+)^5[Ʉ+*]@+*>JP!],`1@],`A.HW+)^br+)x炚+)胚+)+)?++oMVz]y`PV{`*QD+`+RS`+Si V|`TI`+UV}`+VV~`+W`XV`Y ],`1`Z V],`12`[H J],`1W`\m K],`1|`]V`+^T`W_T`+`V`+aV`+bV`*c!V`5WdI`+eU`+f]],`+gV`)hV`*iK]`+jJV]],`+pV|`\>=+.K= +`i)Y4`>=.V*gT4`>=.V)g=.VV4e`>=+.V*g=F.V4yy`>I!.f(+>=.f?i=.VwS+. l^fV`M>J)mVѢ`M>J*o$*0a`\]b`+ka\+z`+]`>J.Ki+0b+0炥+1胥+1p U/]y],`\>=.+1.ub.Ki.vfrnn\>K>= .Vt[%l[(`>=3.ICT=R._+2Fb+2Os49yVDy`>=VM.dT*=m.T.d^I.Va=.T!W^?I"".V~V(*.T^.Va(*>=,.Tē^?IKO.V`>=k.I{T=.Tē^?=.V.T^I.V|S>=.Ue7Z.Y=2(.UeMFPZe.VZ>=.UeV.W=.UeZ.VZ=.Y C=:$.VZ CIGK.V`>=qg.UeT)=.V{*PN`.Ue=.V=.Ki+5J)?I ".T^("=0.V~V(M+Y.Vb>=r.VwN`.Ue=.V=.Ki+6IJ*I.Va>=.IT=".VēcIDXH.T^w>=e.Vy.T^c=.IT>=.IT=/.V{*P=VJ.KiZ.UeJj)tj*V&j*\>@!7.V{P6D=K.V{)PIepi.IT(z>=0'V?I.IT(>=0'V?C0"""!?7.+Q(+YR.Rc[.+Q(Y!|u.IT(!.IT(>I""! .Ue(+".Vh"G=.Ue(+R.Vg>=f.V{*PJ?N`.+Q5`.R5`.+9WR+99AG.IT>I+9{(  9>=U.V}ĔU=x.IT>I!y+9{>=0 'V?=kc.Yo+9{;I!.V|S>=0'V?=.ITB.JJ>Iu"y.V}U(Y+9{(.V}U9>=.V}&.V}UWUI;"Q?.V}U(`[(Y}x+9{(>=.V}.V}UWUI"&.V|S>=0FP'V?=.IT>E"$`+)+=]U.Ylhm+=.IT>=.Y+9{;=.V8"]IT!Y.V|S>=0{'V?=.ITB00>IQgU.V}Uyp(Y>=.V+9{.V}U9~=.V} .V}UWUI""8&.V}U(KB(Yhc+9{(u>=.V$]=.T)_=.V}.V}UWUI(">,.V}U(QH(Yni+9{({>=.V#]=.T*_= +.V} +.V}UWUI0F4.V}U(`YP(YW>=s.V{+9{~=.IT>=0@ +@'VB@R@n@n>I@@@+9{(@>=@.I@T>I@""AAA+9{9A-A(+9{(A:AUAP+9{(Ab>=0AvA'V?=AA.YA+9{;BABB>IB$B-B(+9{(B:>IBLBmBfBP.VZ(Y(>=0BB'V?=B.IBT=C.V}ēU>IC:"CCC>+9{(CPC[CV+9{(Ch>=0C|C'V?=CC.VZC+9{;BCDD>ID>DTDB.V}UDfD](Y>=D|.VD+9{DDD.V}U9~=D.V}DD.V}UWUIDDD.V}U(ED(Y>IEE'E"+9{(E4>=Ek.VE$]=E.T)_=E.V}EE.V}UWUIEEE+9{(F>=F?.VF[#]=Fq.T*_=F.V}FF.V}UWU>=0FF'V>IG5G>G9+9{(GK>=G_.IGoT>=G.VG+9{G~=G.V~G*V=H.IH TBHGHcHc>=H.VH+9{H~=H.V~H*V=H.IH TBIII>IIAIJIE+9{(IW>=Ii.IIy TIIII+9{(I>=JD.IJT +T>=J.VJJ.VXWXIJ""JJ+9{70J79J+9{JJ.VXw>=0JJ'V>=KQ.KwKpKkK_.Wh7 +WKr+9{y70WBKKK >IKKK+9{(K>=L.IL +T>ILS"L\LW+9{(LiLtLo+9{(L>=0LL'V?=ML.VZM+9{;BM!M=M= +>=M].VMe+9{Mu~=MM.V~V(M+IM"MM.W7dMM.Ww7W>=0MM'V>IN""NN.Wv7NN.W(7NN.W(70>=N.V)b?=O9.IOI TBOaO}O} >=O.O,O.dIOO΀O+9{(O>=O.IOTIPP&P!+9{(P3>=PE.IPUT=Pp.PvPp.RyR>=PP.J[P|Q +9{;=Q!.IQ1 TBQUQqQq >IQQQ+9{(Q>=Q.IQ T>IQ!QyR +9{>=0R R*'c?=R}Rp.J[R|R+9{;BRRR >IRRR+9{(S>=S.IS"TISSS\SW+9{(Si>=S{.ISTIS"!SS+9{(S!S׀S+9{(S>=T-T .K\T1+9{;=TD.ITTT?BTxTT>ITTT+9{(T>=T.ITTIUUU+9{(U+>=U=.IUMT>=UU.K\U+9{;BUUU>=U.VV+9{V~=V!.IV1TBVUVqVq>IV"VV+9{(VVV+9{(V>=V.IV T>NWW+d`:W1ZWF.J[NWhWte`:WzZW.K\IW"WW+N('SBW.VX'bX.K\}>=X0.V)a?IX[XkX_+N('B>NXX],`:X{X+NNXXV`XX.V~V(Y+NY*Y8V`"YYYM.W(YgYY.W(YEYYY`YY+PWYY+O(YY+PWYY+PWW>NZZV`Z .VZW'FbZlZhZb+OZi+PW9b}IZ""Z+P!Z+O""Z+PZ+OZ+O>=Z.V)`?=[D[;.d[I+N[\[V+O[]+PW9>=[[.d[+N[+N=[[.J[ C=\[.K\ CI\\&\!+9{(\3>=\G.I\WTI\y\\}+9{(\>=\.I\T=\.\\.RyR>=]^]Q.J[]b|]s+9{;=].I] TB]]]>=^.V^+9{^~I^'^+.Vs>J^H>B^oJ^^^>=^.V^+9{^~=^.I_TB_$_@_@>=_b.V_j+9{_z~=_.I_TB___>I___+9{(_>=` .I`TI`=`F`A+9{(`S>=`m.I`}T>N``K``.V`+9{=`.Va a`.Vch7Wa+TcBa+aGaG>Iagapak+9{(a}>=a.IaT?Baaa>=b.Vb +9{b~Ib(b>b,.Vcw>=bQ.IbaT>=b.IbTBbbb>=b.Vc+9{c~=c%.Ic5TBcUcqcq>=c.Vc+9{c~=c.Vw=c.VBcdd> =d[.dad[.RyRNdsdV`ddd.+Q(Yyd.RId"dd.Vc^dҁd+Wwd.Vc>=d+We.Vc?Nff],`f"fBf:.+Qf`fRfJ.+Q}Wfb.Rfj+W=ff.Vjf+X@If!ff.Vc(f”W>=f.Vff.Vcyff+X@(Yc?=g .gg .RWgg+X@(YRIg-gCg1.Vc(>IgW!g\.Va>=gv.Vw=g.V>=g.IgT?Bhh+h+>@*hihnBh{>@*hhBh=h.V{*PIi"!ii.+Q(+i.i'.R(i9i1.+Q(Y>=i.VxIi"!ii.IT(i!ii.IT(i>=ji.f]??uj/j4jj;jjF],`\>=jhjT.fZ@jj|.+Q(+j|j=j.+&jj+[`Q=j.ēR=j.rvjjqjq\>=k.+fIk&"k1k*.IT(k;kLkE.IT(kVJk_?Ikl!kzkp.Ue(+>Ik""!kk.IT(k!"kk.IT(k!k.V|S!""kk.IT(l!l .Val(l.T^(l+W>=lJl:.Vjld'V?=l.V)=ll.KiwJl?Im1m<m5.IT(mF>ImU!mZ.V|S>=mt.m'V?=mm.KiwJn?Innn.IT(n(>=nFn:.KiwJnU?Inhnsnl.ITn|>=n.InT=o.o''V=oo}.KiwJo?Io"!o.Vaoo.T^(oϔW>=o.IoT>=p.IpT=p.p'V=pp.Kiwq qqqq`:>Gq$q,.V]qTqT#>Jqd'Tqq$>Jq'I Jq+qqqqq`Jqq.V~VqqrTrr`Jrr.T^rr#r]Fr+r]`Jr."r..V`rKrD.IT(rUrarjrTrr`Jrr.T_rrrUrrrK`\>Irr+b=r.V)b?rrsUs s`E>=sE.IsUTJscsnLs.fs.Vsst~Vst~],`>Isss.+Q(+Js+?Ist t.R(tt .+Q(YJt+?Nt1t8],`tBt:.+QtJ.RM=tW.VxJtmtt+dwttvVtv\>Ittt.IT(tJt?=t.ItT=t.V~t)V=uu .J[ C=u2u%.K\ C=uGu?.Y C=ujuT.VZ C=ux.ēW=u.VēX=u.Vu"]=u.Tu锃W^=u.T*_=v.V*`=v4.V*a=vK.V*b=vg.Vv{Wc=v.+dxvvvVvv\>=v.++Q=v.+RyvvwLgvwLv``>Jw ""ww+gw7w$w+g7!wBw5wC+g9zwQw]wVwiwwn``>Jwz"""ww+gƒw7ww+g€7ww+g(ww΀w+g(w{wwyVxyxe`:],`:>Nx6x=],`:xC.`:Nx[xa`Nxnxt`Cx}xx+h逇xx+h(^>Ixxxx+hx+h@('B>=x؁x+hxx+hXx+hՃx+hH;=y ++hyy+hWIy*"yAy9y.+hy:+h@('RBy^yVyK+hyW+h@('B>=yq+hyvyq+hW?=y+hyy+hW=yy+hyy+hXy+hՃy+hH;Jyy+h|yy{Vz{z``>Jz#zzz׀z+jy7A77zz+jk7 z+j`}{1{6|8V{M|8{X],`{lK],``>I{y!{{{}+k(Y({{+kǁ(YJ{*?E{{{`{‚{+l/{̀{+k(Y{+l/{ւ{+l/W>I{!{{{+k{+l/9({|| |+k| +l/9J|*?J|))~|=|A|V|H||Mk`|Wl``>I|c!|l|g+m3(|o+mB>=0|}|'V?||~ V|~ |``>I|"|70v|+m||+m˃v79>J} }}+m˃y70I}1"}:7Av}=+m}J}E+m˃v7F>J}[}n}g}b+m˃y7AW7 +I}"}7av}+m}}+m˃v7f>J}}}}+m˃y7aW7 +>=0}}'V~%~*V~9~>T`\>@~e~[.Ue(+~[~l@~~z.Vj(+~z~@!~.Vh~~N~Uu[=~.V~ڨ +],`i)Y4`>I,!90+o(<.UeJG?@`.Vh`k=x.V*h=.VT4b`>I!+o(.UeJ?@! .Vh =%.V)h=C.VV4vv`>I!+o(.UeJ?@.Vh=.V*h=.V4##`>I2!?6+o(B.UeJM?I_!wc.f(+>=.f?=.V)=.Kiwj=+o.U*8.dB+odbR.Vje=o.V)h=.VVSL`*\>I.Ue(+J'?N7;`=.Ue=PL+swV+s=d.U+eIz!~.Vj(+>=.Vjw=.V+j?=.V*h=.VV-\>I6!D:.Ue(+>IU"!Z.Vh!j.V{P>=.r?>I"!.Vg!.V{P>=.r?S[ Y[+\>I!6".f(+=S?.f?=a.IqT=~.Ki+u&+u`=.Kiw+0L+0+0+1m+1+2+7+[y+\R+`+a4+a}+a+b<+b+b+cn+d+f+f+g+h[+j+k+m+m+o4+sT+t+u+vFV`` U`*0UE`)JV``V`+U `V`+P`+ .`: ^][[[[[k+k1U `G.`:\?+xC+xR]T pu|\>=.U)=.U V.=.U V..votU }\>=.VT=.U V.ӄV`J.VT  `J  .UE `)`/a\\>=A.VĀT+z1~5K``J.^5+zzkɅ``J.^+zl + +`[J.^+{-mHH [% K[\>=72.^8+{?+{nMMXY [^ a[[Jkqk.^}+{う+{t s][[[\J.^+|Hu`[J.^+|v߆ \>=.^ w CCa[[ˁK\\>=5/.^=+}8xH_w2gw]][[Jjpj.^2z|1 2]][[\>=.^1+}pЇڈ''`[`[a[[ˁK]__][__J.^__+~Qo,1u=`Z.^l+~sz`[`[][__J.^__j   [ a[K[ a[+[J.^+++qR7R a[[ˁK[\>==7.^7G+ rWdviv][Jlrl.^{z][J.^|(`J.^(}É̉ ԉ`J.^ ~C`J.^CDA#D`:J)$D'V:..'R>.^+x+y++y+y+z+zZ+z+{+{b+{+|(+|+|+}+}r+}+~+~++m++E++++Q++V`FV][`:`WV`l7h7<Á`+ā`+ŁV`+ՁЋ\?2`:`  ǁV`:>NV`7N8=`L[+{Jm+ȁU .`:`J.V+mɁҌߎDD`>N.`:.VC.V+Hl>=+H.VN׍?`5][`:`.V5`:+H5`.+H5\ꁍ++݃+n+=.V$+J29+ӁIRSH`e`\>=t.VĀ+=.V=.VʁwŎ\>=.V́TVT?`\>=.V'+9=5.VH+9́Y^Vp~?`\>I.(+>@.(+ŏ=..Ā+=.V>@! .V(+Ő @!1+.(+Ő+8=\V.ĞPĀd+={s+V.=.Ā+΁Vʒ?`\>I!+P(+>= ++PV( +V?I9!KE=+V(+>=jd\+VPzr+P?I.(+>=.+P=.V=.V?I*4..(7+>=H.XP+V?=qi+Py+V+ρV\>=.V@!.(+ŒڒN?`.=+&IU!raY+&V(+>=+&V?ЁV\>@.V(+œ̓I!.(+>N`8T .(.VAP=I.VVk}.Vƒy+ .V?сVŕ\>I!.V(+>=.VŁ=.V+?+O+++d++++++++- ց„'V`ف„N`+\? ہ„Zs'{`>J&5[#+(+ـ+[`݁…Ɇφ`\>=ـ+S߁†MVcac`[dsa_T%a``'+T1a`][`:`:M`:+&%`+Hb`+_>Nfp`~++JӀ_+2[[҅ +%3+bW+‰&FV=F`[@sa_V`z%`+b`+_>JӀ_+2[[ҁ+%+b:+ŠRT%R ``'>J/:F+NŒ!T19>`W][`:`:`:>Jj}++++3+t+~+,+x+ŒV`Œ Q`J Va``' Ua`][`:`:M`:ÍÎ֎Va``'Ua`][`:`:M`:\?++ Ž*T%~:K``'>IZ!p^.V(+Jy.V+I?I!.Q(+J.QT%+I?JT%+I)T1~AF`_][`:`:`:>Ir!v.U(+>J.U+)+6?I!.Q(+>J.QT1(+)-+6?JERT1k+)p+6+ ++Á;JV`ÁoV`7ÁV`7ÁV`7ÁV`7ÂV`7Â9V`7ÂeV`7ÂV`7ÂV`7ÂV`7ÃV`7ÃLR`7Ã{V`7ÃV 'V`Ä)V 'V`6ÄV D'V`ÄV 'V`Å@V 'V`PÅV a'V`ÆV 'V`ÆrV -'V`ÆV 'V`ÇJV 'V`\ ÇV n'V` +È2S4 'S5`J ÈV b'V` \? +É&,&V` ÊpV` ÊV 'V`Ë`V` }*Ël 'V`Ì[ V`Ì V`Í% V`Í| V`Í `Í܍⎧V`*-V`*XV`+xV`+`)\?+B+R+b+r+ Ð&@gV[gh7``k>N}`krNV`N`:I!5`+#ׄ+Y(++ׄ+Y~][`:`:(+>=+D+~m?I0!94+D(+B>IJ"ZSN+D(^^gb+DR'}D>=0'V>=+4#.V(+ +Db4**X+6`:`J6E h.V`=+e$'V񂒴+4m=ȁ++4n>=+e'm=+9 nJX_+ÓVҕ7`B``:>N`:'ID!RH+L(+>=c+p$'V󁔅+Y>I.V(+>=+p'V>=-+p$c'VO.VIs!w.V(+>=+p+pW$'V.VG?J+pØJd$Vq$7`+`k> +N`kr'I!.>J+?=+e mI0"4.V"bX+(+"!z+(++~فl>=5`k+ꂙ+Meꂙ+MemW'VGm?I$"(.V"VL+(+"!xn+(++~فl>=5`k+ނ+eނ+emW'VGm?N'V`k).VE+=5`kU+ZZ+iefZZ+iemWti+J|++$ç'@@FG@T `dVa],`:;[+V`]`&>J+)+70+S%èV ``>J+++++&éBA`]y[][ (êV`)ê`*ëSL`+ë$`,ël 4'V`y(-ë 'V`).ëA 'W` */ìI '`R+0îW`{+Có񴄴 $'W'W\?  2ò׳޳`:;]`:+1L][`:[+WV`]`&J+++V+8øGOWksl`]`:+W`+V``&>I +h(+>=0($'W'W?J,+N+Z+x+h:úDLV"VV`;û(A((`:<ü%08]88`:=üҼڼW`>ýW `:3þwQ`+`:+][4ÿSXv[vq [\5@`@g@@p@@x ]y[][6A[A`A|W +AkA|Av],`\?AAA0AA`:JAA#ABIBTB0B]BBe0`:\>=B)B+++,+++G+n++++-+m+++B DBBCWW ``FB `:JBBCCCC`:'\?F+ BHC"C)CUAC1CU`:JC7$CU'W CM.F++_K[aW `M`NT `OT`Q\? +RՂۅ W`TW`U&T `VCT`WbW`XW`YW`7ZW`7[W`7\W`7]/W`7 ^LW`7 +_jW`7 `W`7 aW`7 bW`7cW`7e\? +f\W`h7 ],`j@@ZNZT],`\?h+ @+Hk!'W`mLe`:n_`rppe`:+`+\?m+n+ ppAĆ`:J.em++,stzW]],`[]],`u8VS`vVW `wxW!`xW"`yW#`z`7{Vm`7|W$`7}4W%`7@~TW&`7 tW'`7W(`7I`uW)`*W*`*W+`WW,` WW-`*-W.`BWLW/`qW0`WW1`W2`MW` W `:'u][+ W3` W4],[.[ W5` *$W6`00xMxTW3`*nW6`+\?++ 0 }5 ]y],`]y[>J[ +D4p][`s>I/!>3.(+>=0Q[('W7?=.ā+J.֎ۏ;;S`Y`+\>=.%+,+@EiwJi\>=^S.wşȟ ],`\>N`#%+`+`;!+`N17`NDN`WP+ʁ(YIcng.I(qz>=0J'V?I.I({>=0J'V?C*""82+:+!OH.I(Rz!c\.I(f{>N{`++9I.Ivw>I.I(u>=.W)!焑+|(I! + ~k(>=0dnJ'W8?=.W++I!.W+(T>I !+}(>=5.W*)>=l.W**?I.W+vV>I.W+(T>I2.W2(KM>=0cmJ'W8?>@".W+(U .W+(V͕%I6!N:.W2(gM>=0J'W8?=.W2.W+I ".W+^+\JB.W+v^^>I!.W)=0J'W8?>=0 +J'W8=F.IOvIitm.I(wv>=.W-!+7(=.W,„+7I".W9.W,w7}>=0J'W8?IMVQ.W,(7~>=l.W,ē=.W.ĕ=.IwI.W,(7>=.W,ē=.W.7=#.I,w>@a\.W,7~\f=u.W:>@.I(w=.W,.W,7k+=.W..W.yI+.W.(>=?.W:?>I{.I(x>=.W4y5`.W/5`.W/ƅ+y++:I.W/(>=.W;?>@PI.I(SyIZNW<`żh`Ӄ+y+.W0=.W0.W0y+OIY].W->=t.W=|++O+?=.W5" +ʁނ+"+O==+C=+WF+OI_c.W9>I.W0(=.W>?>I"!.W2( N!5!.W2(NO>=0fpJ'W8?I.W0(=.W??=/+4/+y=q+vq+WW=`(``\>N͟W@`7I+ǃ^!+>Ngs`u+y+7Ny`+W+Eʠ`+׆+}+Q+}߆+}W>=5`+5`+}+΀+++9&.W45`.W15`.W1+L W+L 9`:=.+4.+W7+=J+QJ+ǃyT+Nq|WA`~+lj+I+w>Nڡ0`E`+^^+^+^y>=+K("+K7k&77*.W4NI9.W1WK+^9`NnxWB`~+K+K+K+KNWC`}Ѿ邢+ԁހ++E `+ +-!+_ (Y5+ +65+ +W>=5`}F+_ 5`R+ +QQ+ Q+ UQQ+ Q+ 9X++@:N`+h+=++W+l +=+ǁ+ǃy+l +??Ny` +W+E#%`'+0.+ 2+7+ 87+ W>=5`D+5`K+ JJ+^J+oNJJ+^J+o9&N^Q.W4q5`_.W15`_.W1n+W+9`:W:\>I.W->I!.W3>=0J'WD?=.I(x>IAE.W3>=0\fJ'WE?=.W0.W,=.WF?W;?\>= .W0".W,=,.WFDIWFV\>I.W0(>I.W9>AG .W+KK\>=^.Igz={.wB]>=.B--^>=J?.RBq=.WG>=.W?>=.Iy W?\>I%).W)>N;A],`LC.W5I_"!lc.W6(+w.W*>=+;.W6WH+;?AG.W2N>=*.3.(:+;uBMwwO>=.+;B=.W2M?=.WGW>/\>AG8@.W+gg\>=v.WNWI],`.W5I怫+(Yw>I ++(Y(>=0%/J'W8?=k.W~w+97k+9I.W(>=0J'W8?I(;4,+(Yw>=N.W a\(ph+Mu??=.Iz=.wB]>= .-$.W5BDhh^>=v..W5B=.WGW9`>J"" .W+((\A9.W+(U]me.W+(^WG\>I"!.I(z!.I({=.Iu?=.W)*=.W+ W=.W,W=".W.7W=?.W/ė=b.W0{W=.W1ē+$++T+++K+.+Ï++ƅ+=++ WJ` WI],`ӰӰWI],`+\?+˨ +XWK`& WI],`11V?VFWI],`+\?+: 1+nGrWL]``&` M K]`&e +`&i) WM^],`:;[ WN`++WM^],`:;[WN`\?+5+X 0B5F[ ]y`]y`&>=pi+ͯ4ww3x ``>= +.WM.WNg\4̳WO`&\J.K+Li#.K4==b`>=TH.KwJj}q.KVe`:],`:>N۴],`:.`:N`N`C"/)+g=1+(^>IMd\Q+]+g@('B>=}v+2+X+W+gH;=+W+gWI"ހ++g@('RB++g@('B>=+W+WW?=-+g2-+gW=G@+2WK+Xa+Wh+gH;Ju|+2ycy `WM^],`:;[V`]`&>N +`*"+ +I8!=O+>=5`+e5[+ѝV5[+ѝwA+ѝJ٦`&J'WP?O:LFa`:]`&S[]`:]`&> +=5`+e5[+TV5[ن+TL['WQ5[ +TL0{'oȆ+TNZ^`:ph`+L K'WRN`=+$+ԄbNm`:+w=4,#+eL'WSP+fI_!lc+8(+B>=+eL'WT+8?N̺WU`++e+H=%+eLJ>]NE+eT$g`&4mmnl``J,+ԃ ++8+H)+ N;],`: +L 'WTI+"!9/+(+!VD+%(+>=,+8VL+ɂ'Ji.t`:4]`:J&+%+]`:g`:4]`:`:>Iⅽ+Ɇ+?>=0J'WV?J+i4,S[`>=5`+e5[χ+YV5[+YwA+Y=0+Fg`&>+>J[ib++~DWWD ` +`V``>N@@#WX`:@5@-@%+ L K'WY=#@m@]+>(+B@]+>'+`:N@~@WZ`@@+>T'I@"@Ђ@+%@@ބ@+קK(@ B>NAA`kA*A+%VA8+ק=AUAMAD+L'WYAzAu+!emNAAV`"AAA+ק~فAlBA+%VNB,BDV`"B_BTBQ+ק~فBklBB+%VNBBWU`BVC+ؘVCP+VCC+!nVCC+!nW)JCC+J?JD+D"D.GpW[D?GpDL ``> ID[!DnDgD_+7 (';B>JD*?IDDDDD+L D[(+>JD*?NDEV`*=E=EEE+L E+[ƀ4EEEEEEMK`:`>IE\EtEfE`+!W('FB=E+ښ)?IE!E+ښJE*?NEEF`:EEۀE+L KE{IF "FF +j(+B!F6F(F +j!W('oB>JFN*?NFmFu`:FFFw+L K'W\IF"FF+(+B!FʃF+('W]B>JF*?NFF`:GGG+L K'WRIG0G8G4+(+B>JGI*?JGa)+͏+++++GuG{PW^`GV`GV`GV`GV`ÁHW`āH3`u+ŁHL`u+́HXHXIrHsIrHV`H HV`H I V`*I4V`*I_W`*\?++ ++$+6Ä+H HXȁIwI|JGW_IJG\>IIII.(+>=I.Ix#I.WI.VJ.V`.)?ɁJLJQKW`J_K\>IJhJtJl.(+>=J.Jw#J.WJ.VJ.V`.)?ʁK!K+M'WHKAM'KLk],``> +=KW.W_NKrKw],`1K~`=KK+TK+!<=KK+T:K`77<=KK.ąK+TKK+T(YzNKL],`1L `NL*],`CL'!LJL/+"L=L5.Ĥb{(+>=LbL[+Li+"=L.+?JLM ;M+ˁM,M6P}WaMLP}MWk],`],`> +=Mb.W`NM|M],`1M`NM`IM!%MM+-`>EMMM`MڃM+⸀MM+-(YM+MM+W>IM"NMM+-M+9N 7NN+-N+9>=0N#N-$'Wb'WcNzNw+-N{+9'mN+'?=N+N;N+->=N+&NN+-`=ON.ŅO +⌓OO+⌁(YzNO3*],`CO=OwOp+hO~+L=O.+?IPP%PP+h(Yw>=P2+hPBP;+hP[PTPM+h(YyM?JPlPs+h+ީ+O+++΁PPeKWd][],`][ЁQ= WO`ҁQ_]],`+ӁQWe`+܁QQQQQQWO`\>=Q.WeQQ.WOW6 +Ѐ+_ QՁQRS15RS1R ]y[]y],`>JR)R4],`RW+4RgRgS,R}p]],``>IR!RR.(+>=0RR('Wf?=R.āS +EJS.ցS6S;VS>VS? [\>ISN%SZSR+`>=Su.WgS^SS+`WIJS?IS%SˀS+`>=S.WgT]TT+`WIJT?NT:],`NTHWh`ITT!T`TX+(+>ITq%T}Tu+`:>=T+TU=T+TT(T+`:IT%TT+],`>=U+U"V=U2+U9+],`IUO%U[US+`f>=Ux+UU=U+UU+`fh>=0UUU+IU!VV.We(+>=V$+V:V+.WeWaVQ+?>=Vs+VU=V.WgV+΁V+ׁVVW!VW!VS`VY`+\>=WV.ҁW +W+؁W&W+XwW0X\>NW=WBQ`WNWD.WOWiNWhWo`:W{Wq.WOWjNW],`IW!WW+b(+>=W+W.`=WW+ŀWWW+b77;=XX+ŀXX +b7;IX!X(X!+(+B>=X@X;+ŀXLXG(XS+=YXX+UY +fY#Y.WOW3"!YGY8.We(+"YfY_+U(YzUYY+U(YV4YYYYl],``>=YY.ҀY+CځYZeIWkZeIZWh`Z0],`Z;W`ZLWl`]],`>NZcZh0`!Zk+NZZWm`#ZZ+(+œZˁZ+Ɂ(Y`NZ[Wn`#[ +7`I[[-["+3w7>=[>+|[I[>+|W7I[Z[i[^+3w7}>=[x+|[[x+|W?N[[>`[:[+|N[[`N[[Wo`\`\ \|k#\++\V}`k\r\k+\=\\+/5`\+T5`\+T\+ +W+ +\+h :N\\Wp`I]]] +3w7>=].](+/5`]/+T5`]/+T]4+ W+ 7:=]E+O +7I]a]p]e+3w7}>=]]+/5`]+T5`]+T]+2 W+2 7~:=]+O +?E]]^`^^+ ^ ++O +^+ ^^+ W>=^*^$+/5`^++T5`^++T^0+ W+ ^b^A^6+3^]^X^S^G+O +yy^Z+ h77:I^t^x+>=5`^+/5`^^+ ^+ ^^^+ ^+ 9k^7:N^^Wq`^=^އ^+/ ^+T^^+TW^+h O=_ +T__ +TWI_!_&_!+(+>N_C`I_"__+(_U%_ځ_+`>=_+ _+`>I`%`%` +`>=`A+ `L;`_+`>=`+ `:``+Ɂ(YE``````+ `́`+Ɂ(Y`+ ``+ W>I`"```+`+ 9a7aa+a+ 9>=0aa($'Wb'Wca|ax+a}+ 9'ma+ '?=aa+ a+ aa+a+ 9:NabW@`7Nbb WA`b.b'b"+ (Yb1+\ IbEbTbI+sw>Nbb0`Ebbb`bb+^b+bb+y>=b+bbb+7kbb+h b+9Nc cWB`cc!+c'+c-+c3+NcPc\WC`}cpcc+ ޓc+sEccc`cc+2cc+(Yc+2cc+2W>=5`}c+5`c+2cc+c+ccc+c+9c+@:?Ed5d>d@`dMdB+shdO+\ d]d[+4ddd_+ (Ydl+4dmdl+4W>=5`d}+ 5`d+4dd+d+ddd+d+9dd+h dd+49:=d+d+ ??@dd+T(d+|ddIddd+(+>Je1e ],`e+/>Je*1e1],`e2+/e:+++++3+)++)݁eNeTpWr`][߁e WO`e l`⁼eK][+ぼeQ][+䁼fWs`*偼f$ `*恼fAa][fW`&灼f{Wt][+ffffffWO`fl`\?߀+y+ f +ꁼffgfg\>If!ff.Q(+>=gf.Q?끼gg"gg*g\>Ig3!gEg7.Q(+>=gdgV.QZ>=g.Ws)쁼ggh%gh%\>Ig!gg.Q(+>=gg.Q]>=h.Ws*큼h*h/hh6h\>Ih?!hQhC.Q(+>Nhfhsg][hu.Q=h.Q+=hh+?hhkWuhk[>Ih!hh.K(+Jh?=i .Ki +[i)TiR.Vin.i.Nii]y],`iii.K],`ii.WO=jjj.lj,?g[4jjjdj p[`>=j+.=jJj:.atjS.WOb4jojokjpS[jY``>=j. )=j.Ij%jǁj,`>Ij!j.j,`Ƃj,>=kk.ajk,,`Ƃk3,?>=ka.=kkr.atk.WOkklklkS[+kY`+`>Ikkk.Wt(+Jk*?Il !ll , (+>=l/l$.Wtjl=, lD,>=lold.Wttlx.WO=l.Wt+Jl)llnulnul ]y[][>Ill. >=mll,+Jmm [m-.WO?=mC.Wu=m\.Wtmm[=m~.Qmm,4mmmm[`>=mm.K‘m,m.bm.)Inn.Ws>=n*n.QZ=n9.Ws*?JnYnkn`.Wtunznofwnof][>=n.WuOnnWva][no +][>Jnnnnn.lwi4nnnnp[`>g[4nnonp[`Jnn.WO=oo.KwJo*oHoAo1.aug[4oMoMoaoNp[][JoTo_oT,okopoosoot[\>Ioo. Jo?=o.Wu=oo.K‘o,oopWvop\>=o. )=o.=p .w++<++X+,,,,i,,e +p1p1Ww]y[``,pp"lWx``&pWy][``pƢF`` p`7 q%Wz`:'W{qa ]`:qK][+qQ][+q=][+q k[q W3`qW|`r(r!W}`*r=W~`+rRW`:+rkW`{+rW`+rW`+rWi`+rWj`:+ rW`+ +sW6`+ s6U`'sH3,UUWo|k[]`:V`W3`*WU`+\> =.W.&**.k`=8.=D[T.W=d.W||)=.W6Ą, +N`s.W3.W6 +=.Q&.k, 4%%j&[`>I4%=8, !`>IZ!_.W}=wm.W, !`WI?I%, !`>=.W .W(>=RF.KV, !b4uu vS[}Y[`>I!.W (+=.W ?I%І,.`w>=.>=9.P=.W~.Wi=.W.Wj=.Kw43`>I !0$.W (+=E9.W ?IUeY.W|(r)>=.W|*I!҅, W>=., W, W >==.=Y.W|q+?=.W~څ, W=.W, W =%.Kw)][=]O.QZ=j.K| +[i)Y.Q]4,`>=.Q= .Q+TM?.QZVtf.Q]=.af.n, , , UsYsrsys`:s;]`:sL][`:[sV`t]`&>Nt t$M`t*t0,It:"!tItBt>,瀟('WB!t_tXtT,瀟('WB>=0tqt{J$t'Wtt,瀟'?Ntt`tؼNuuW`u!:7Eu4u=u?`uFuD,7uL,uMuL,W>=ubuY,uc,uouh, 7:Nuu`:uu,=u,u #uuu,瀟('WB'QX'`:QUvv,QUv;v7,瀠'vSvO,'vkvg,vv,vv,緷Jvzvvv T&';v,6g`^4vvzv `L]`^>Iv"!vvv,QU(+B!www ,QU `>NwwU`:www(ww,QU=www,LVwY$x'Ux,, ?Ix(!x4x,,(+>=xOxG,4xWxWxxX`:x_K[\Jxixyxqxi,LVx}, x, +x?=5`Pxx,LV5[xx,k x['WQ5[yy,k y"{'o5[yHyF,k 'WRya,n5[yryp,k 'W'W5[yy,k 'W\'W],k Iy!yՁy,(+>=yyy,LV'WTz z,?Iz:zJz>,>=zzzez],LV'WYzz,V?Jzzz,w[g`&4zzz +`^]`&> Oz{Sa`:\{{{`:\>={R{C{:,Tlg[4{W{W{{Xl``>={s{l, =0{{J{, +I{"""!{{{,V`({|=|||,Lf|+[(+!||c|\|S,Lf|p[Ɓ-4||||K`:`J||||," +!W('FB!}}|||,LfK|{ǃ!W('oB>=}<}7, $}q'W}N,'W?N}}m`:}}},LfK'WSI}}}, +(+B>=}}, 'W?N~=~B`~H=~\~W,q ~x$~w~b,n~hԄbN~~W],`~~,q wN~~W],`~~, +I!, (Y(0!, (Y>=GB, 'W?E`,, (Y,,W>I!, ,9(, ,9>= , 'W?NYb]`:umd,LfK'WTNWU`,,J&,Tlg`&4667l``JLP,z,9,,*,PWP +`^/V``>NIYWX`:ld[,LfK'WYI,(+B>=,'?NWZ`,T'I!"1%,̪E?<, PK(H B>NiV`, P~فlNV`, P~ف +lO,0Wa`:`=E`:`>NY[`:j`], P~k,!xmIz~,!(+B>J ?J,!b4`:`J J VaT,!PbV,!PV,! V, ?JA+a[\b`+a\+`+][>J6/#.K=,"bV,# g,#~,#)W`{J.W(W`{\>I.W}J?I! .W(+=4).W?=B.WĀR,$ Iase.W(+J|?=.W.W4`>I.W}J?=.W=.W.W4++`>=U.l"`J.W|A`:J+ W`J.W~!"W "`:J.W',O/O0 [\>=B<.=F,'TYW +do],`\>I|!%,'z],`>=0,'z''W?=.=j ,'z"v*v+S`>Y`+\>=WQ.=`,(8g,(F{ ]y[][J.=,("][J.={w{Q`+`:+][>I  #,)o>=02<J$k'Wf,)o?Ix|.Wi(+>=.WiĀ,)o=.Wjā,)~?I!.K>I"!(.K!E7.Q(+>=skdX.Kx[i4~~p[][[[J2[[?I.W (+>=.W 7411N`>=y.W~.Wi=.W.WjI!.Q(+=.Q?=.Kw=1%8.afv ??Jcpj.=w#0`:J 01) 0 0`:\>= 0,,1!Q`+.`:+\>I=A.W}JO?I[m_.Wi(+>=~.WiĀ,-L=.Wjā,-[?=.W})=.WWv=.afv%&Id7I`:J:'W&MXweiw`:Jl'A|b`][`:[>NK`:$.k&'.k'N][`:[2`:['. +.cg'&.f3,.m'KG,/'V`,/Iqu,.>J,/o?K>=,/o'l.k)n[p[>=,/o'l2`:`:'..cg''V 'K'V +'V'V +nJz,/ojWjQ``>J"!ɀ,0(+""""",0ꀇ,0(*LG,0(_,0(",0w +,0ꀇ "50,0^H ^Y,0ꀇ7,[,,",#,#,%,&,&W,&,&,'N,(,(,(,)F,,w,,,-,.P,.,.,0,2/ˁW`7́W`9́W`7΁W`ρ`ЁW`7h7сW`:'Wҁ€W`Ӂ ^`[a_b`%`][[[_1ԁW`:'WՁBW`:'WցW`:'WׁW`:'W؁ W`:'WہW`:>N)1`:< args) => new Runner('example', configureServer).run(args); + +Future configureServer(Angel app) async { + // Use the injected `pub_sub.Client` to send messages. + var client = app.container.make(); + var greeting = 'Hello! This is the default greeting.'; + + // We can listen for an event to perform some behavior. + // + // Here, we use message passing to synchronize some common state. + var onGreetingChanged = await client.subscribe('greeting_changed'); + onGreetingChanged + .cast() + .listen((newGreeting) => greeting = newGreeting); + + // Add some routes... + app.get('/', (req, res) => 'Hello, production world!'); + + // Create some routes to demonstrate message passing. + app.get('/greeting', (req, res) => greeting); + + // This route will push a new value for `greeting`. + app.get('/change_greeting/:newGreeting', (req, res) { + greeting = req.params['newGreeting'] as String; + client.publish('greeting_changed', greeting); + return 'Changed greeting -> $greeting'; + }); + + // The `Runner` helps with fault tolerance. + app.get('/crash', (req, res) { + // We'll crash this instance deliberately, but the Runner will auto-respawn for us. + new Timer(const Duration(seconds: 3), Isolate.current.kill); + return 'Crashing in 3s...'; + }); +} ++792M*959:DF8:806842,.!XA pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/angel_framework.dart/// An easily-extensible web server framework in Dart. +library angel_framework; + +export 'src/core/core.dart'; +export 'src/http/http.dart'; +7Hfile:///Users/thosakwe/Source/Angel/production/lib/angel_production.dartUexport 'src/instance_info.dart'; +export 'src/options.dart'; +export 'src/runner.dart';!Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/pub_sub.dart$export 'src/protocol/protocol.dart';%nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/core.dartexport 'anonymous_service.dart'; +export 'hooked_service.dart'; +export 'map_service.dart'; +export 'metadata.dart'; +export 'request_context.dart'; +export 'response_context.dart'; +export 'routable.dart'; +export 'server.dart'; +export 'service.dart'; +export 'typed_service.dart'; + ! nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/http/http.dart/// Various libraries useful for creating highly-extensible servers. +library angel_framework.http; + +import 'dart:async'; +import 'dart:io'; +export 'package:angel_http_exception/angel_http_exception.dart'; +export 'package:angel_model/angel_model.dart'; +export 'package:angel_route/angel_route.dart'; +export 'package:body_parser/body_parser.dart' show FileUploadInfo; +export 'angel_http.dart'; +export 'controller.dart'; +export 'http_request_context.dart'; +export 'http_response_context.dart'; + +/// Boots a shared server instance. Use this if launching multiple isolates +Future startShared(address, int port) => + HttpServer.bind(address ?? '127.0.0.1', port ?? 0, shared: true); + +Future Function(dynamic, int) startSharedSecure( + SecurityContext securityContext) { + return (address, int port) => HttpServer.bindSecure( + address ?? '127.0.0.1', port ?? 0, securityContext, + shared: true); +} +EA//C$%L5F='7:Ifile:///Users/thosakwe/Source/Angel/production/lib/src/instance_info.dart~/// Information about the currently-running instance. +class InstanceInfo { + final int id; + + const InstanceInfo({this.id}); +}6!Cfile:///Users/thosakwe/Source/Angel/production/lib/src/options.dartimport 'dart:io'; +import 'package:args/args.dart'; + +class RunnerOptions { + static final ArgParser argParser = new ArgParser() + ..addFlag('help', + abbr: 'h', help: 'Print this help information.', negatable: false) + ..addFlag('respawn', + help: 'Automatically respawn crashed application instances.', + defaultsTo: true, + negatable: true) + ..addFlag('use-zone', + negatable: false, help: 'Create a new Zone for each request.') + ..addOption('address', + abbr: 'a', defaultsTo: '127.0.0.1', help: 'The address to listen on.') + ..addOption('concurrency', + abbr: 'j', + defaultsTo: Platform.numberOfProcessors.toString(), + help: 'The number of isolates to spawn.') + ..addOption('port', + abbr: 'p', defaultsTo: '3000', help: 'The port to listen on.'); + + final String hostname; + final int concurrency, port; + final bool useZone, respawn; + + RunnerOptions( + {this.hostname: '127.0.0.1', + this.port: 3000, + this.concurrency: 1, + this.useZone: false, + this.respawn: true}); + + factory RunnerOptions.fromArgResults(ArgResults argResults) { + return new RunnerOptions( + hostname: argResults['address'] as String, + port: int.parse(argResults['port'] as String), + concurrency: int.parse(argResults['concurrency'] as String), + useZone: argResults['use-zone'] as bool, + respawn: argResults['respawn'] as bool, + ); + } +} +-!5KFGO<2H#@15C/.Bfile:///Users/thosakwe/Source/Angel/production/lib/src/runner.dartimport 'dart:async'; +import 'dart:io'; +import 'dart:isolate'; +import 'package:angel_container/angel_container.dart'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:args/args.dart'; +import 'package:io/ansi.dart'; +import 'package:io/io.dart'; +import 'package:logging/logging.dart'; +import 'package:pub_sub/isolate.dart' as pub_sub; +import 'package:pub_sub/pub_sub.dart' as pub_sub; +import 'instance_info.dart'; +import 'options.dart'; + +/// A command-line utility for easier running of multiple instances of an Angel application. +/// +/// Makes it easy to do things like configure SSL, log messages, and send messages between +/// all running instances. +class Runner { + final String name; + final AngelConfigurer configureServer; + final Reflector reflector; + + Runner(this.name, this.configureServer, + {this.reflector: const EmptyReflector()}); + + static const String asciiArt = ''' +____________ ________________________ +___ |__ | / /_ ____/__ ____/__ / +__ /| |_ |/ /_ / __ __ __/ __ / +_ ___ | /| / / /_/ / _ /___ _ /___ +/_/ |_/_/ |_/ \____/ /_____/ /_____/ + +'''; + + static void handleLogRecord(LogRecord record) { + var code = chooseLogColor(record.level); + + if (record.error == null) print(code.wrap(record.toString())); + + if (record.error != null) { + var err = record.error; + if (err is AngelHttpException && err.statusCode != 500) return; + print(code.wrap(record.toString() + '\n')); + print(code.wrap(err.toString())); + + if (record.stackTrace != null) { + print(code.wrap(record.stackTrace.toString())); + } + } + } + + /// Chooses a color based on the logger [level]. + static AnsiCode chooseLogColor(Level level) { + if (level == Level.SHOUT) + return backgroundRed; + else if (level == Level.SEVERE) + return red; + else if (level == Level.WARNING) + return yellow; + else if (level == Level.INFO) + return cyan; + else if (level == Level.FINER || level == Level.FINEST) return lightGray; + return resetAll; + } + + /// Spawns a new instance of the application in a separate isolate. + /// + /// If the command-line arguments permit, then the instance will be respawned on crashes. + /// + /// The returned [Future] completes when the application instance exits. + /// + /// If respawning is enabled, the [Future] will *never* complete. + Future spawnIsolate(int id, RunnerOptions options, SendPort pubSubSendPort) { + return _spawnIsolate(id, new Completer(), options, pubSubSendPort); + } + + Future _spawnIsolate( + int id, Completer c, RunnerOptions options, SendPort pubSubSendPort) { + var onLogRecord = new ReceivePort(); + var onExit = new ReceivePort(); + var onError = new ReceivePort(); + var runnerArgs = new _RunnerArgs(name, configureServer, options, reflector, + onLogRecord.sendPort, pubSubSendPort); + var argsWithId = new _RunnerArgsWithId(id, runnerArgs); + + Isolate.spawn(isolateMain, argsWithId, + onExit: onExit.sendPort, + onError: onError.sendPort, + errorsAreFatal: true && false) + .then((isolate) {}) + .catchError(c.completeError); + + onLogRecord.listen((msg) => handleLogRecord(msg as LogRecord)); + + onError.listen((msg) { + if (msg is List) { + var e = msg[0], st = StackTrace.fromString(msg[1].toString()); + handleLogRecord(new LogRecord( + Level.SEVERE, 'Fatal error', runnerArgs.loggerName, e, st)); + } else { + handleLogRecord(new LogRecord( + Level.SEVERE, 'Fatal error', runnerArgs.loggerName, msg)); + } + }); + + onExit.listen((_) { + if (options.respawn) { + handleLogRecord(new LogRecord( + Level.WARNING, + 'Instance #$id at ${new DateTime.now()}. Respawning immediately...', + runnerArgs.loggerName)); + _spawnIsolate(id, c, options, pubSubSendPort); + } else { + c.complete(); + } + }); + + return c.future + .whenComplete(onExit.close) + .whenComplete(onError.close) + .whenComplete(onLogRecord.close); + } + + /// Starts a number of isolates, running identical instances of an Angel application. + Future run(List args) async { + pub_sub.Server server; + + try { + var argResults = RunnerOptions.argParser.parse(args); + var options = new RunnerOptions.fromArgResults(argResults); + + print(darkGray.wrap(asciiArt.trim() + + '\n\n' + + "A batteries-included, full-featured, full-stack framework in Dart." + + '\n\n' + + 'https://angel-dart.github.io\n')); + + if (argResults['help'] == true) { + stdout..writeln('Options:')..writeln(RunnerOptions.argParser.usage); + return; + } + + print('Starting `${name}` application...'); + print('Arguments: $args...\n'); + + var adapter = new pub_sub.IsolateAdapter(); + server = new pub_sub.Server([adapter]); + + // Register clients + for (int i = 0; i < Platform.numberOfProcessors; i++) { + server.registerClient(new pub_sub.ClientInfo('client$i')); + } + + server.start(); + + await Future.wait(new List.generate(options.concurrency, + (id) => spawnIsolate(id, options, adapter.receivePort.sendPort))); + } on ArgParserException catch (e) { + stderr + ..writeln(e.message) + ..writeln() + ..writeln('Options:') + ..writeln(RunnerOptions.argParser.usage); + exitCode = ExitCode.usage.code; + } catch (e) { + stderr..writeln('fatal error: $e'); + exitCode = 1; + } finally { + server?.close(); + } + } + + static void isolateMain(_RunnerArgsWithId argsWithId) { + var args = argsWithId.args; + hierarchicalLoggingEnabled = true; + + var zone = Zone.current.fork(specification: new ZoneSpecification( + print: (self, parent, zone, msg) { + args.loggingSendPort + .send(new LogRecord(Level.INFO, msg, args.loggerName)); + }, + )); + + zone.run(() async { + var client = new pub_sub.IsolateClient( + 'client${argsWithId.id}', args.pubSubSendPort); + + var app = new Angel(reflector: args.reflector) + ..container.registerSingleton(client) + ..container.registerSingleton(new InstanceInfo(id: argsWithId.id)); + + app.shutdownHooks.add((_) => client.close()); + + await app.configure(args.configureServer); + + if (app.logger == null) { + app.logger = new Logger(args.loggerName) + ..onRecord.listen(Runner.handleLogRecord); + } + + var http = + new AngelHttp.custom(app, startShared, useZone: args.options.useZone); + var server = + await http.startServer(args.options.hostname, args.options.port); + var url = new Uri( + scheme: 'http', host: server.address.address, port: server.port); + print('Instance #${argsWithId.id} listening at $url'); + }); + } +} + +class _RunnerArgsWithId { + final int id; + final _RunnerArgs args; + + _RunnerArgsWithId(this.id, this.args); +} + +class _RunnerArgs { + final String name; + + final AngelConfigurer configureServer; + + final RunnerOptions options; + + final Reflector reflector; + + final SendPort loggingSendPort, pubSubSendPort; + + _RunnerArgs(this.name, this.configureServer, this.options, this.reflector, + this.loggingSendPort, this.pubSubSendPort); + + String get loggerName => name; +} +77!'22][)*1%))))))2-C F2('830$%"NF\KDPHM)$%P/<+%'+&DG'I'G'Q%7$%*X( +C?M( 2&*: 'G)D .:5>L41 15QLL=))2M2!ffile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/protocol.dartCexport 'client/sync_client.dart'; +export 'server/sync_server.dart';""{file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/anonymous_service.dartximport 'dart:async'; +import 'service.dart'; + +/// An easy helper class to create one-off services without having to create an entire class. +/// +/// Well-suited for testing. +class AnonymousService extends Service { + FutureOr Function([Map]) _index; + FutureOr Function(Object, [Map]) _read, _create, _remove; + FutureOr Function(Object, Object, [Map]) _modify, _update; + + AnonymousService( + {FutureOr index([Map params]), + FutureOr read(id, [Map params]), + FutureOr create(data, [Map params]), + FutureOr modify(id, data, [Map params]), + FutureOr update(id, data, [Map params]), + FutureOr remove(id, [Map params])}) + : super() { + _index = index; + _read = read; + _create = create; + _modify = modify; + _update = update; + _remove = remove; + } + + @override + index([Map params]) => new Future.sync( + () => _index != null ? _index(params) : super.index(params)); + + @override + read(id, [Map params]) => new Future.sync( + () => _read != null ? _read(id, params) : super.read(id, params)); + + @override + create(data, [Map params]) => new Future.sync(() => + _create != null ? _create(data, params) : super.create(data, params)); + + @override + modify(id, data, [Map params]) => new Future.sync(() => _modify != null + ? _modify(id, data, params) + : super.modify(id, data, params)); + + @override + update(id, data, [Map params]) => new Future.sync(() => _update != null + ? _update(id, data, params) + : super.update(id, data, params)); + + @override + remove(id, [Map params]) => new Future.sync( + () => _remove != null ? _remove(id, params) : super.remove(id, params)); +} +7^)#<=%'+//* *D -I 6M J") J") /Oxfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/hooked_service.dartLlibrary angel_framework.core.hooked_service; + +import 'dart:async'; +import '../util.dart'; +import 'request_context.dart'; +import 'response_context.dart'; +import 'routable.dart'; +import 'metadata.dart'; +import 'server.dart'; +import 'service.dart'; + +/// Wraps another service in a service that broadcasts events on actions. +class HookedService extends Service { + final List> _ctrl = []; + + /// Tbe service that is proxied by this hooked one. + final Service inner; + + final HookedServiceEventDispatcher beforeIndexed = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher beforeRead = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher beforeCreated = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher beforeModified = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher beforeUpdated = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher beforeRemoved = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher afterIndexed = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher afterRead = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher afterCreated = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher afterModified = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher afterUpdated = + new HookedServiceEventDispatcher(); + final HookedServiceEventDispatcher afterRemoved = + new HookedServiceEventDispatcher(); + + HookedService(Service this.inner) { + // Clone app instance + if (inner.app != null) this.app = inner.app; + } + + RequestContext _getRequest(Map params) { + if (params == null) return null; + return params['__requestctx'] as RequestContext; + } + + ResponseContext _getResponse(Map params) { + if (params == null) return null; + return params['__responsectx'] as ResponseContext; + } + + Map _stripReq(Map params) { + if (params == null) + return params; + else + return params.keys + .where((key) => key != '__requestctx' && key != '__responsectx') + .fold({}, (map, key) => map..[key] = params[key]); + } + + /// Closes any open [StreamController]s on this instance. **Internal use only**. + @override + Future close() { + _ctrl.forEach((c) => c.close()); + beforeIndexed._close(); + beforeRead._close(); + beforeCreated._close(); + beforeModified._close(); + beforeUpdated._close(); + beforeRemoved._close(); + afterIndexed._close(); + afterRead._close(); + afterCreated._close(); + afterModified._close(); + afterUpdated._close(); + afterRemoved._close(); + inner.close(); + return new Future.value(); + } + + /// Adds hooks to this instance. + void addHooks(Angel app) { + Hooks hooks = getAnnotation(inner, Hooks, app.container.reflector); + List before = [], after = []; + + if (hooks != null) { + before.addAll(hooks.before); + after.addAll(hooks.after); + } + + void applyListeners(Function fn, HookedServiceEventDispatcher dispatcher, + [bool isAfter]) { + Hooks hooks = getAnnotation(fn, Hooks, app.container.reflector); + final listeners = [] + ..addAll(isAfter == true ? after : before); + + if (hooks != null) + listeners.addAll(isAfter == true ? hooks.after : hooks.before); + + listeners.forEach(dispatcher.listen); + } + + applyListeners(inner.index, beforeIndexed); + applyListeners(inner.read, beforeRead); + applyListeners(inner.create, beforeCreated); + applyListeners(inner.modify, beforeModified); + applyListeners(inner.update, beforeUpdated); + applyListeners(inner.remove, beforeRemoved); + applyListeners(inner.index, afterIndexed, true); + applyListeners(inner.read, afterRead, true); + applyListeners(inner.create, afterCreated, true); + applyListeners(inner.modify, afterModified, true); + applyListeners(inner.update, afterUpdated, true); + applyListeners(inner.remove, afterRemoved, true); + } + + List get bootstrappers => + new List.from(super.bootstrappers) + ..add((RequestContext req, ResponseContext res) { + req.serviceParams + ..['__requestctx'] = req + ..['__responsectx'] = res; + return true; + }); + + void addRoutes([Service s]) { + super.addRoutes(s ?? inner); + } + + /// Runs the [listener] before every service method specified. + void before( + Iterable eventNames, HookedServiceEventListener listener) { + eventNames.map((name) { + switch (name) { + case HookedServiceEvent.indexed: + return beforeIndexed; + case HookedServiceEvent.read: + return beforeRead; + case HookedServiceEvent.created: + return beforeCreated; + case HookedServiceEvent.modified: + return beforeModified; + case HookedServiceEvent.updated: + return beforeUpdated; + case HookedServiceEvent.removed: + return beforeRemoved; + default: + throw new ArgumentError('Invalid service method: ${name}'); + } + }).forEach((HookedServiceEventDispatcher dispatcher) => + dispatcher.listen(listener)); + } + + /// Runs the [listener] after every service method specified. + void after(Iterable eventNames, HookedServiceEventListener listener) { + eventNames.map((name) { + switch (name) { + case HookedServiceEvent.indexed: + return afterIndexed; + case HookedServiceEvent.read: + return afterRead; + case HookedServiceEvent.created: + return afterCreated; + case HookedServiceEvent.modified: + return afterModified; + case HookedServiceEvent.updated: + return afterUpdated; + case HookedServiceEvent.removed: + return afterRemoved; + default: + throw new ArgumentError('Invalid service method: ${name}'); + } + }).forEach((HookedServiceEventDispatcher dispatcher) => + dispatcher.listen(listener)); + } + + /// Runs the [listener] before every service method. + void beforeAll(HookedServiceEventListener listener) { + beforeIndexed.listen(listener); + beforeRead.listen(listener); + beforeCreated.listen(listener); + beforeModified.listen(listener); + beforeUpdated.listen(listener); + beforeRemoved.listen(listener); + } + + /// Runs the [listener] after every service method. + void afterAll(HookedServiceEventListener listener) { + afterIndexed.listen(listener); + afterRead.listen(listener); + afterCreated.listen(listener); + afterModified.listen(listener); + afterUpdated.listen(listener); + afterRemoved.listen(listener); + } + + /// Returns a [Stream] of all events fired before every service method. + /// + /// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee + /// that events coming out of this [Stream] will see changes you make within the [Stream] + /// callback. + Stream beforeAllStream() { + var ctrl = new StreamController(); + _ctrl.add(ctrl); + before(HookedServiceEvent.all, ctrl.add); + return ctrl.stream; + } + + /// Returns a [Stream] of all events fired after every service method. + /// + /// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee + /// that events coming out of this [Stream] will see changes you make within the [Stream] + /// callback. + Stream afterAllStream() { + var ctrl = new StreamController(); + _ctrl.add(ctrl); + before(HookedServiceEvent.all, ctrl.add); + return ctrl.stream; + } + + /// Returns a [Stream] of all events fired before every service method specified. + /// + /// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee + /// that events coming out of this [Stream] will see changes you make within the [Stream] + /// callback. + Stream beforeStream(Iterable eventNames) { + var ctrl = new StreamController(); + _ctrl.add(ctrl); + before(eventNames, ctrl.add); + return ctrl.stream; + } + + /// Returns a [Stream] of all events fired AFTER every service method specified. + /// + /// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee + /// that events coming out of this [Stream] will see changes you make within the [Stream] + /// callback. + Stream afterStream(Iterable eventNames) { + var ctrl = new StreamController(); + _ctrl.add(ctrl); + after(eventNames, ctrl.add); + return ctrl.stream; + } + + /// Runs the [listener] before [create], [modify] and [update]. + void beforeModify(HookedServiceEventListener listener) { + beforeCreated.listen(listener); + beforeModified.listen(listener); + beforeUpdated.listen(listener); + } + + @override + Future index([Map _params]) { + var params = _stripReq(_params); + return beforeIndexed + ._emit(new HookedServiceEvent(false, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.indexed, + params: params)) + .then((before) { + if (before._canceled) { + return beforeIndexed + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.indexed, + params: params, result: before.result)) + .then((after) => after.result); + } + + return inner.index(params).then((result) { + return afterIndexed + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.indexed, + params: params, result: result)) + .then((after) => after.result); + }); + }); + } + + @override + Future read(id, [Map _params]) { + var params = _stripReq(_params); + return beforeRead + ._emit(new HookedServiceEvent(false, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.read, + id: id, params: params)) + .then((before) { + if (before._canceled) { + return beforeRead + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.read, + id: id, params: params, result: before.result)) + .then((after) => after.result); + } + + return inner.read(id, params).then((result) { + return afterRead + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.read, + id: id, params: params, result: result)) + .then((after) => after.result); + }); + }); + } + + @override + Future create(data, [Map _params]) { + var params = _stripReq(_params); + return beforeCreated + ._emit(new HookedServiceEvent(false, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.created, + data: data, params: params)) + .then((before) { + if (before._canceled) { + return beforeCreated + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.created, + data: data, params: params, result: before.result)) + .then((after) => after.result); + } + + return inner.create(data, params).then((result) { + return afterCreated + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.created, + data: data, params: params, result: result)) + .then((after) => after.result); + }); + }); + } + + @override + Future modify(id, data, [Map _params]) { + var params = _stripReq(_params); + return beforeModified + ._emit(new HookedServiceEvent(false, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.modified, + id: id, data: data, params: params)) + .then((before) { + if (before._canceled) { + return beforeModified + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.modified, + id: id, data: data, params: params, result: before.result)) + .then((after) => after.result); + } + + return inner.modify(id, data, params).then((result) { + return afterModified + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.created, + id: id, data: data, params: params, result: result)) + .then((after) => after.result); + }); + }); + } + + @override + Future update(id, data, [Map _params]) { + var params = _stripReq(_params); + return beforeUpdated + ._emit(new HookedServiceEvent(false, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.updated, + id: id, data: data, params: params)) + .then((before) { + if (before._canceled) { + return beforeUpdated + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.updated, + id: id, data: data, params: params, result: before.result)) + .then((after) => after.result); + } + + return inner.update(id, data, params).then((result) { + return afterUpdated + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.updated, + id: id, data: data, params: params, result: result)) + .then((after) => after.result); + }); + }); + } + + @override + Future remove(id, [Map _params]) { + var params = _stripReq(_params); + return beforeRemoved + ._emit(new HookedServiceEvent(false, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.removed, + id: id, params: params)) + .then((before) { + if (before._canceled) { + return beforeRemoved + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.removed, + id: id, params: params, result: before.result)) + .then((after) => after.result); + } + + return inner.remove(id, params).then((result) { + return afterRemoved + ._emit(new HookedServiceEvent(true, _getRequest(_params), + _getResponse(_params), inner, HookedServiceEvent.removed, + id: id, params: params, result: result)) + .then((after) => after.result); + }); + }); + } + + /// Fires an `after` event. This will not be propagated to clients, + /// but will be broadcasted to WebSockets, etc. + Future fire(String eventName, result, + [HookedServiceEventListener callback]) { + HookedServiceEventDispatcher dispatcher; + + switch (eventName) { + case HookedServiceEvent.indexed: + dispatcher = afterIndexed; + break; + case HookedServiceEvent.read: + dispatcher = afterRead; + break; + case HookedServiceEvent.created: + dispatcher = afterCreated; + break; + case HookedServiceEvent.modified: + dispatcher = afterModified; + break; + case HookedServiceEvent.updated: + dispatcher = afterUpdated; + break; + case HookedServiceEvent.removed: + dispatcher = afterRemoved; + break; + default: + throw new ArgumentError("Invalid service event name: '$eventName'"); + } + + var ev = new HookedServiceEvent(true, null, null, this, eventName); + return fireEvent(dispatcher, ev, callback); + } + + /// Sends an arbitrary event down the hook chain. + Future fireEvent( + HookedServiceEventDispatcher dispatcher, HookedServiceEvent event, + [HookedServiceEventListener callback]) { + Future f; + if (callback != null && event?._canceled != true) + f = new Future.sync(() => callback(event)); + f ??= new Future.value(); + return f.then((_) => dispatcher._emit(event)); + } +} + +/// Fired when a hooked service is invoked. +class HookedServiceEvent { + static const String indexed = 'indexed'; + static const String read = 'read'; + static const String created = 'created'; + static const String modified = 'modified'; + static const String updated = 'updated'; + static const String removed = 'removed'; + + static const List all = const [ + indexed, + read, + created, + modified, + updated, + removed + ]; + + /// Use this to end processing of an event. + void cancel([result]) { + _canceled = true; + this.result = result ?? this.result; + } + + /// Resolves a service from the application. + /// + /// Shorthand for `e.service.app.service(...)`. + Service getService(Pattern path) => service.app.service(path); + + bool _canceled = false; + String _eventName; + var _id; + bool _isAfter; + var data; + Map _params; + RequestContext _request; + ResponseContext _response; + var result; + + String get eventName => _eventName; + + get id => _id; + + bool get isAfter => _isAfter == true; + + bool get isBefore => !isAfter; + + Map get params => _params; + + RequestContext get request => _request; + + ResponseContext get response => _response; + + /// The inner service whose method was hooked. + Service service; + + HookedServiceEvent(this._isAfter, this._request, this._response, + Service this.service, String this._eventName, + {id, this.data, Map params, this.result}) { + _id = id; + _params = params ?? {}; + } +} + +/// Triggered on a hooked service event. +typedef HookedServiceEventListener(HookedServiceEvent event); + +/// Can be listened to, but events may be canceled. +class HookedServiceEventDispatcher { + final List> _ctrl = []; + final List listeners = []; + + void _close() { + _ctrl.forEach((c) => c.close()); + listeners.clear(); + } + + /// Fires an event, and returns it once it is either canceled, or all listeners have run. + Future _emit(HookedServiceEvent event) { + if (event?._canceled == true || event == null || listeners.isEmpty) + return new Future.value(event); + + var f = new Future.value(event); + + for (var listener in listeners) { + f = f.then((event) { + if (event._canceled) return event; + return new Future.sync(() => listener(event)).then((_) => event); + }); + } + + return f; + } + + /// Returns a [Stream] containing all events fired by this dispatcher. + /// + /// *NOTE*: Callbacks on the returned [Stream] cannot be guaranteed to run before other [listeners]. + /// Use this only if you need a read-only stream of events. + Stream asStream() { + // TODO: Close StreamController + var ctrl = new StreamController(); + _ctrl.add(ctrl); + listen(ctrl.add); + return ctrl.stream; + } + + /// Registers the listener to be called whenever an event is triggered. + void listen(HookedServiceEventListener listener) { + listeners.add(listener); + } +} +<- J&?65*2*5*6*5*5*4*1*4*5*4*4*&1+%5-%7 K=S %#H>#!NG74H,0,1211516766,9:%'  !AJ) &) *!) ) F<&@Q)&)* ))F<&78$!$%$$67# #$##JW\1;.IW\0;.TW\I;"SW\H;!B;$%$ %CFFJ8,1FJ1, + #%CC%FG@,4FG9, + '%CF)FJD,8FJ=, + +%CG1FKL,<FJE, + +%CF1FJL,<FJE, + %%CF%FJ@,6FJ9, +F24%?9%\?H&9&+J +Ig>*$;J5ufile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/map_service.dartimport 'dart:async'; + +import 'package:angel_http_exception/angel_http_exception.dart'; + +import 'service.dart'; + +/// A basic service that manages an in-memory list of maps. +class MapService extends Service { + /// If set to `true`, clients can remove all items by passing a `null` `id` to `remove`. + /// + /// `false` by default. + final bool allowRemoveAll; + + /// If set to `true`, parameters in `req.query` are applied to the database query. + final bool allowQuery; + + /// If set to `true` (default), then the service will manage an `id` string and `createdAt` and `updatedAt` fields. + final bool autoIdAndDateFields; + + /// If set to `true` (default), then the keys `created_at` and `updated_at` will automatically be snake_cased. + final bool autoSnakeCaseNames; + + final List> items = []; + + MapService( + {this.allowRemoveAll: false, + this.allowQuery: true, + this.autoIdAndDateFields: true, + this.autoSnakeCaseNames: true}) + : super(); + + String get createdAtKey => + autoSnakeCaseNames == false ? 'createdAt' : 'created_at'; + + String get updatedAtKey => + autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'; + + bool Function(Map) _matchesId(id) { + return (Map item) { + if (item['id'] == null) + return false; + else if (autoIdAndDateFields != false) + return item['id'] == id?.toString(); + else + return item['id'] == id; + }; + } + + @override + Future index([Map params]) { + if (allowQuery == false || params == null || params['query'] is! Map) + return new Future.value(items); + else { + Map query = params['query']; + + return new Future.value(items.where((item) { + for (var key in query.keys) { + if (!item.containsKey(key)) + return false; + else if (item[key] != query[key]) return false; + } + + return true; + }).toList()); + } + } + + @override + Future read(id, [Map params]) { + return new Future.value(items.firstWhere(_matchesId(id), + orElse: () => throw new AngelHttpException.notFound( + message: 'No record found for ID $id'))); + } + + @override + Future create(data, [Map params]) { + if (data is! Map) + throw new AngelHttpException.badRequest( + message: + 'MapService does not support `create` with ${data.runtimeType}.'); + var now = new DateTime.now().toIso8601String(); + var result = data as Map; + + if (autoIdAndDateFields == true) { + result + ..['id'] = items.length.toString() + ..[autoSnakeCaseNames == false ? 'createdAt' : 'created_at'] = now + ..[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] = now; + } + items.add(_foldStringDynamic(result)); + return new Future.value(result); + } + + Map _foldStringDynamic(Map map) { + return map == null + ? null + : map.keys.fold>( + {}, (out, k) => out..[k.toString()] = map[k]); + } + + @override + Future modify(id, data, [Map params]) { + if (data is! Map) + throw new AngelHttpException.badRequest( + message: + 'MapService does not support `modify` with ${data.runtimeType}.'); + if (!items.any(_matchesId(id))) return create(data, params); + + return read(id).then((item) { + var result = item..addAll(data as Map); + + if (autoIdAndDateFields == true) + result + ..[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] = + new DateTime.now().toIso8601String(); + return new Future.value(result); + }); + } + + @override + Future update(id, data, [Map params]) { + if (data is! Map) + throw new AngelHttpException.badRequest( + message: + 'MapService does not support `update` with ${data.runtimeType}.'); + if (!items.any(_matchesId(id))) return create(data, params); + + return read(id).then((old) { + if (!items.remove(old)) + throw new AngelHttpException.notFound( + message: 'No record found for ID $id'); + + var result = data as Map; + if (autoIdAndDateFields == true) { + result + ..['id'] = id?.toString() + ..[autoSnakeCaseNames == false ? 'createdAt' : 'created_at'] = + old[autoSnakeCaseNames == false ? 'createdAt' : 'created_at'] + ..[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] = + new DateTime.now().toIso8601String(); + } + items.add(_foldStringDynamic(result)); + return new Future.value(result); + }); + } + + @override + Future remove(id, [Map params]) { + if (id == null || + id == 'null' && + (allowRemoveAll == true || + params?.containsKey('provider') != true)) { + items.clear(); + return new Future.value({}); + } + + return read(id, params).then((result) { + if (items.remove(result)) + return result; + else + throw new AngelHttpException.notFound( + message: 'No record found for ID $id'); + }); + } +} +A<#[Uv"q!/#&&@@&-- ! %J& #3&&: + '==6 +/Q4' +KL+%5/L //QA".'I4' //QA!/4 )$ILI4-' )'<#,  /4rfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/metadata.dartjlibrary angel_framework.http.metadata; + +import 'package:angel_http_exception/angel_http_exception.dart'; + +import 'hooked_service.dart' show HookedServiceEventListener; +import 'request_context.dart'; +import 'routable.dart'; + +/// Annotation to map middleware onto a handler. +class Middleware { + final Iterable handlers; + + const Middleware(this.handlers); +} + +/// Attaches hooks to a [HookedService]. +class Hooks { + final List before; + final List after; + + const Hooks({this.before: const [], this.after: const []}); +} + +/// Exposes a [Controller] to the Internet. +class Expose { + final String method; + final String path; + final Iterable middleware; + final String as; + final List allowNull; + + const Expose(this.path, + {this.method: "GET", + this.middleware: const [], + this.as: null, + this.allowNull: const []}); +} + +/// Used to apply special dependency injections or functionality to a function parameter. +class Parameter { + /// Inject the value of a request cookie. + final String cookie; + + /// Inject the value of a request header. + final String header; + + /// Inject the value of a key from the session. + final String session; + + /// Inject the value of a key from the query. + final String query; + + /// Only execute the handler if the value of this parameter matches the given value. + final match; + + /// Specify a default value. + final defaultValue; + + /// If `true` (default), then an error will be thrown if this parameter is not present. + final bool required; + + const Parameter( + {this.cookie, + this.query, + this.header, + this.session, + this.match, + this.defaultValue, + this.required}); + + /// Returns an error that can be thrown when the parameter is not present. + get error { + if (cookie?.isNotEmpty == true) + return new AngelHttpException.badRequest( + message: 'Missing required cookie "$cookie".'); + if (header?.isNotEmpty == true) + return new AngelHttpException.badRequest( + message: 'Missing required header "$header".'); + if (query?.isNotEmpty == true) + return new AngelHttpException.badRequest( + message: 'Missing required query parameter "$query".'); + if (session?.isNotEmpty == true) + return new StateError( + 'Session does not contain required key "$session".'); + } + + /// Obtains a value for this parameter from a [RequestContext]. + getValue(RequestContext req) { + if (cookie?.isNotEmpty == true) + return req.cookies.firstWhere((c) => c.name == cookie)?.value ?? + defaultValue; + if (header?.isNotEmpty == true) + return req.headers.value(header) ?? defaultValue; + if (session?.isNotEmpty == true) + return req.session[session] ?? defaultValue; + if (query?.isNotEmpty == true) + return req.uri.queryParameters[query] ?? defaultValue; + return defaultValue; + } +} + +/// Shortcut for declaring a request header [Parameter]. +class Header extends Parameter { + const Header(String header, {match, defaultValue, bool required: true}) + : super( + header: header, + match: match, + defaultValue: defaultValue, + required: required); +} + +/// Shortcut for declaring a request session [Parameter]. +class Session extends Parameter { + const Session(String session, {match, defaultValue, bool required: true}) + : super( + session: session, + match: match, + defaultValue: defaultValue, + required: required); +} + +/// Shortcut for declaring a request query [Parameter]. +class Query extends Parameter { + const Query(String query, {match, defaultValue, bool required: true}) + : super( + query: query, + match: match, + defaultValue: defaultValue, + required: required); +} + +/// Shortcut for declaring a request cookie [Parameter]. +class CookieValue extends Parameter { + const CookieValue(String cookie, {match, defaultValue, bool required: true}) + : super( + cookie: cookie, + match: match, + defaultValue: defaultValue, + required: required); +} +'A>1+#)10>,- !"Z,,20WZM$0:$0:#0B%@B!$G$8%3#=9!J(!:"L(!8 H(!9&O(!yfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/request_context.dartlibrary angel_framework.http.request_context; + +import 'dart:async'; +import 'dart:io' show Cookie, HttpHeaders, HttpSession, InternetAddress; + +import 'package:angel_container/angel_container.dart'; +import 'package:body_parser/body_parser.dart'; +import 'package:http_parser/http_parser.dart'; +import 'package:meta/meta.dart'; +import 'package:path/path.dart' as p; + +import 'metadata.dart'; +import 'response_context.dart'; +import 'routable.dart'; +import 'server.dart' show Angel; + +part 'injection.dart'; + +/// A convenience wrapper around an incoming [RawRequest]. +abstract class RequestContext { + String _acceptHeaderCache, _extensionCache; + bool _acceptsAllCache; + BodyParseResult _body; + Map _provisionalQuery; + + /// The underlying [RawRequest] provided by the driver. + RawRequest get rawRequest; + + /// Additional params to be passed to services. + final Map serviceParams = {}; + + /// The [Angel] instance that is responding to this request. + Angel app; + + /// Any cookies sent with this request. + List get cookies; + + /// All HTTP headers sent with this request. + HttpHeaders get headers; + + /// The requested hostname. + String get hostname; + + /// The IoC container that can be used to provide functionality to produce + /// objects of a given type. + /// + /// This is a *child* of the container found in `app`. + Container get container; + + /// The user's IP. + String get ip => remoteAddress.address; + + /// This request's HTTP method. + /// + /// This may have been processed by an override. See [originalMethod] to get the real method. + String get method; + + /// The original HTTP verb sent to the server. + String get originalMethod; + + /// The content type of an incoming request. + MediaType get contentType; + + /// The URL parameters extracted from the request URI. + Map params = {}; + + /// The requested path. + String get path; + + /// The remote address requesting this resource. + InternetAddress get remoteAddress; + + /// The user's HTTP session. + HttpSession get session; + + /// The [Uri] instance representing the path this request is responding to. + Uri get uri; + + /// Is this an **XMLHttpRequest**? + bool get xhr; + + /// Returns the file extension of the requested path, if any. + /// + /// Includes the leading `.`, if there is one. + String get extension => _extensionCache ??= p.extension(uri.path); + + /// Returns `true` if the client's `Accept` header indicates that the given [contentType] is considered a valid response. + /// + /// You cannot provide a `null` [contentType]. + /// If the `Accept` header's value is `*/*`, this method will always return `true`. + /// To ignore the wildcard (`*/*`), pass [strict] as `true`. + /// + /// [contentType] can be either of the following: + /// * A [ContentType], in which case the `Accept` header will be compared against its `mimeType` property. + /// * Any other Dart value, in which case the `Accept` header will be compared against the result of a `toString()` call. + bool accepts(contentType, {bool strict: false}) { + var contentTypeString = contentType is MediaType + ? contentType.mimeType + : contentType?.toString(); + + // Change to assert + if (contentTypeString == null) + throw new ArgumentError( + 'RequestContext.accepts expects the `contentType` parameter to NOT be null.'); + + _acceptHeaderCache ??= headers.value('accept'); + + if (_acceptHeaderCache == null) + return false; + else if (strict != true && _acceptHeaderCache.contains('*/*')) + return true; + else + return _acceptHeaderCache.contains(contentTypeString); + } + + /// Returns as `true` if the client's `Accept` header indicates that it will accept any response content type. + bool get acceptsAll => _acceptsAllCache ??= accepts('*/*'); + + /// Retrieves the request body if it has already been parsed, or lazy-parses it before returning the body. + Future parseBody() => parse().then((b) => b.body); + + /// Retrieves a list of all uploaded files if it has already been parsed, or lazy-parses it before returning the files. + Future> parseUploadedFiles() => + parse().then((b) => b.files); + + /// Retrieves the original request buffer if it has already been parsed, or lazy-parses it before returning the buffer.. + /// + /// This will return an empty `List` if you have not enabled `keepRawRequestBuffers` on your [Angel] instance. + Future> parseRawRequestBuffer() => + parse().then((b) => b.originalBuffer); + + /// Retrieves the request body if it has already been parsed, or lazy-parses it before returning the query. + /// + /// If [forceParse] is not `true`, then [uri].query will be returned, and no parsing will be performed. + Future> parseQuery({bool forceParse: false}) { + if (_body == null && forceParse != true) + return new Future.value(uri.queryParameters); + else + return parse().then((b) => b.query); + } + + /// Manually parses the request body, if it has not already been parsed. + Future parse() { + if (_body != null) + return new Future.value(_body); + else + _provisionalQuery = null; + return parseOnce().then((body) => _body = body); + } + + /// Override this method to one-time parse an incoming request. + @virtual + Future parseOnce(); + + /// Disposes of all resources. + Future close() { + _body = null; + _acceptsAllCache = null; + _acceptHeaderCache = null; + _provisionalQuery?.clear(); + serviceParams.clear(); + params.clear(); + return new Future.value(); + } +} +.I7//!& !;,.:2 ? */M9*"`1/953%N%@1E|1V?4m|45##Y4$C =q>m:z7${q/-njF-4 +K$& 5B '! sfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/injection.dartpart of angel_framework.http.request_context; + +const List _primitiveTypes = [String, int, num, double, Null]; + +/// Shortcut for calling [preInject], and then [handleContained]. +/// +/// Use this to instantly create a request handler for a DI-enabled method. +/// +/// Calling [ioc] also auto-serializes the result of a [handler]. +RequestHandler ioc(Function handler, {Iterable optional: const []}) { + InjectionRequest injection; + RequestHandler contained; + + return (req, res) { + if (injection == null) { + injection = preInject(handler, req.app.container.reflector); + injection.optional.addAll(optional ?? []); + contained = handleContained(handler, injection); + } + + return req.app.executeHandler(contained, req, res); + }; +} + +resolveInjection(requirement, InjectionRequest injection, RequestContext req, + ResponseContext res, bool throwOnUnresolved) { + var propFromApp; + + if (requirement == RequestContext) { + return req; + } else if (requirement == ResponseContext) { + return res; + } else if (requirement is String && + injection.parameters.containsKey(requirement)) { + var param = injection.parameters[requirement]; + var value = param.getValue(req); + if (value == null && param.required != false) throw param.error; + return value; + } else if (requirement is String) { + if (req.params.containsKey(requirement)) { + return req.params[requirement]; + } else if ((propFromApp = req.app.findProperty(requirement)) != null) + return propFromApp; + else if (injection.optional.contains(requirement)) + return null; + else if (throwOnUnresolved) { + throw new ArgumentError( + "Cannot resolve parameter '$requirement' within handler."); + } + } else if (requirement is List && + requirement.length == 2 && + requirement.first is String && + requirement.last is Type) { + String key = requirement.first; + Type type = requirement.last; + if (req.params.containsKey(key) || + req.app.configuration.containsKey(key) || + _primitiveTypes.contains(type)) { + return resolveInjection(key, injection, req, res, throwOnUnresolved); + } else + return resolveInjection(type, injection, req, res, throwOnUnresolved); + } else if (requirement is Type && requirement != dynamic) { + return req.app.container.make(requirement); + } else if (throwOnUnresolved) { + throw new ArgumentError( + '$requirement cannot be injected into a request handler.'); + } +} + +/// Checks if an [InjectionRequest] can be sufficiently executed within the current request/response context. +bool suitableForInjection( + RequestContext req, ResponseContext res, InjectionRequest injection) { + return injection.parameters.values.any((p) { + if (p.match == null) return false; + var value = p.getValue(req); + return value == p.match; + }); +} + +/// Handles a request with a DI-enabled handler. +RequestHandler handleContained(Function handler, InjectionRequest injection) { + return (RequestContext req, ResponseContext res) { + if (injection.parameters.isNotEmpty && + injection.parameters.values.any((p) => p.match != null) && + !suitableForInjection(req, res, injection)) + return new Future.value(true); + + List args = []; + + Map named = {}; + args.addAll(injection.required + .map((r) => resolveInjection(r, injection, req, res, true))); + + injection.named.forEach((k, v) { + var name = new Symbol(k); + named[name] = resolveInjection([k, v], injection, req, res, false); + }); + + return Function.apply(handler, args, named); + }; +} + +/// Contains a list of the data required for a DI-enabled method to run. +/// +/// This improves performance by removing the necessity to reflect a method +/// every time it is requested. +/// +/// Regular request handlers can also skip DI entirely, lowering response time +/// and memory use. +class InjectionRequest { + /// Optional, typed data that can be passed to a DI-enabled method. + final Map named; + + /// A list of the arguments required for a DI-enabled method to run. + final List required; + + /// A list of the arguments that can be null in a DI-enabled method. + final List optional; + + /// Extended parameter definitions. + final Map parameters; + + const InjectionRequest.constant( + {this.named: const {}, + this.required: const [], + this.optional: const [], + this.parameters: const {}}); + + InjectionRequest() + : named = {}, + required = [], + optional = [], + parameters = {}; +} + +/// Predetermines what needs to be injected for a handler to run. +InjectionRequest preInject(Function handler, Reflector reflector) { + var injection = new InjectionRequest(); + + var closureMirror = reflector.reflectFunction(handler); + + if (closureMirror.parameters.isEmpty) return injection; + + // Load parameters + for (var parameter in closureMirror.parameters) { + var name = parameter.name; + var type = parameter.type.reflectedType; + + var _Parameter = reflector.reflectType(Parameter); + + var p = parameter.annotations + .firstWhere((m) => m.type.isAssignableTo(_Parameter), + orElse: () => null) + ?.reflectee as Parameter; + //print(p); + if (p != null) { + injection.parameters[name] = new Parameter( + cookie: p.cookie, + header: p.header, + query: p.query, + session: p.session, + match: p.match, + defaultValue: p.defaultValue, + required: parameter.isNamed ? false : p.required != false, + ); + } + + if (!parameter.isNamed) { + if (!parameter.isRequired) injection.optional.add(name); + + if (type == RequestContext || type == ResponseContext) { + injection.required.add(type); + } else if (name == 'req') { + injection.required.add(RequestContext); + } else if (name == 'res') { + injection.required.add(ResponseContext); + } else if (type == dynamic) { + injection.required.add(name); + } else { + injection.required.add([name, type]); + } + } else { + injection.named[name] = type; + } + } + return injection; +} +.EBLBNC178N3'/&73%E&/&J7"F$!%"$"'2*L M>0"DnK/'!1O5+C4%%#F% J1IL OF!GG&+##BD*::4-7"> "2&C ??&"0"1$&. $zfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/response_context.dart library angel_framework.http.response_context; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:convert' as c show json; +import 'dart:io' show BytesBuilder, Cookie; + +import 'package:angel_route/angel_route.dart'; +import 'package:file/file.dart'; +import 'package:http_parser/http_parser.dart'; +import 'package:mime/mime.dart'; + +import '../http/http.dart'; +import 'request_context.dart'; +import 'server.dart' show Angel; + +final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); + +/// A convenience wrapper around an outgoing HTTP request. +abstract class ResponseContext + implements StreamSink>, StringSink { + final Map properties = {}; + final Map _headers = {'server': 'angel'}; + + Completer _done; + int _statusCode = 200; + + /// The [Angel] instance that is sending a response. + Angel app; + + /// Is `Transfer-Encoding` chunked? + bool chunked; + + /// Any and all cookies to be sent to the user. + final List cookies = []; + + /// A set of [Converter] objects that can be used to encode response data. + /// + /// At most one encoder will ever be used to convert data. + final Map, List>> encoders = {}; + + /// A [Map] of data to inject when `res.render` is called. + /// + /// This can be used to reduce boilerplate when using templating engines. + final Map renderParams = {}; + + /// Points to the [RequestContext] corresponding to this response. + RequestContext get correspondingRequest; + + @override + Future get done => (_done ?? new Completer()).future; + + /// Headers that will be sent to the user. + /// + /// Note that if you have already started writing to the underlying stream, headers will not persist. + Map get headers => _headers; + + /// Serializes response data into a String. + /// + /// The default is conversion into JSON via `package:json_god`. + /// + /// If you are 100% sure that your response handlers will only + /// be JSON-encodable objects (i.e. primitives, `List`s and `Map`s), + /// then consider setting [serializer] to `JSON.encode`. + /// + /// To set it globally for the whole [app], use the following helper: + /// ```dart + /// app.injectSerializer(JSON.encode); + /// ``` + String Function(dynamic) serializer = c.json.encode; + + /// This response's status code. + int get statusCode => _statusCode; + + void set statusCode(int value) { + if (!isOpen) + throw closed(); + else + _statusCode = value ?? 200; + } + + /// Returns `true` if the response is still available for processing by Angel. + /// + /// If it is `false`, then Angel will stop executing handlers, and will only run + /// response finalizers if the response [isBuffered]. + bool get isOpen; + + /// Returns `true` if response data is being written to a buffer, rather than to the underlying stream. + bool get isBuffered; + + /// A set of UTF-8 encoded bytes that will be written to the response. + BytesBuilder get buffer; + + /// The underlying [RawResponse] under this instance. + RawResponse get rawResponse; + + /// Signals Angel that the response is being held alive deliberately, and that the framework should not automatically close it. + /// + /// This is mostly used in situations like WebSocket handlers, where the connection should remain + /// open indefinitely. + FutureOr detach(); + + /// Gets or sets the content type to send back to a client. + MediaType contentType = new MediaType('text', 'plain'); + + static StateError closed() => + new StateError('Cannot modify a closed response.'); + + /// Sends a download as a response. + void download(File file, {String filename}) { + if (!isOpen) throw closed(); + + headers["Content-Disposition"] = + 'attachment; filename="${filename ?? file.path}"'; + contentType = MediaType.parse(lookupMimeType(file.path)); + headers['content-length'] = file.lengthSync().toString(); + + if (!isBuffered) { + file.openRead().pipe(this); + } else { + buffer.add(file.readAsBytesSync()); + close(); + } + } + + /// Prevents more data from being written to the response, and locks it entire from further editing. + /// + /// This method should be overwritten, setting [streaming] to `false`, **after** a `super` call. + Future close() { + if (buffer is LockableBytesBuilder) { + (buffer as LockableBytesBuilder).lock(); + } + + if (_done?.isCompleted == false) _done.complete(); + return new Future.value(); + } + + /// Serializes JSON to the response. + void json(value) => this + ..contentType = MediaType('application', 'json') + ..serialize(value); + + /// Returns a JSONP response. + /// + /// You can override the [contentType] sent; by default it is `application/javascript`. + void jsonp(value, {String callbackName: "callback", MediaType contentType}) { + if (!isOpen) throw closed(); + write("$callbackName(${serializer(value)})"); + this.contentType = + contentType ?? new MediaType('application', 'javascript'); + close(); + } + + /// Renders a view to the response stream, and closes the response. + Future render(String view, [Map data]) { + if (!isOpen) throw closed(); + return Future.sync(() => app.viewGenerator( + view, + new Map.from(renderParams) + ..addAll(data ?? {}))).then((content) { + write(content); + contentType = new MediaType('text', 'html'); + close(); + }); + } + + /// Redirects to user to the given URL. + /// + /// [url] can be a `String`, or a `List`. + /// If it is a `List`, a URI will be constructed + /// based on the provided params. + /// + /// See [Router]#navigate for more. :) + void redirect(url, {bool absolute: true, int code: 302}) { + if (!isOpen) throw closed(); + headers + ..['content-type'] = 'text/html' + ..['location'] = url is String + ? url + : app.navigate(url as Iterable, absolute: absolute); + statusCode = code ?? 302; + write(''' + + + + Redirecting... + + + +

Currently redirecting you...

+
+ Click here if you are not automatically redirected... + + + + '''); + close(); + } + + /// Redirects to the given named [Route]. + void redirectTo(String name, [Map params, int code]) { + if (!isOpen) throw closed(); + Route _findRoute(Router r) { + for (Route route in r.routes) { + if (route is SymlinkRoute) { + final m = _findRoute(route.router); + + if (m != null) return m; + } else if (route.name == name) return route; + } + + return null; + } + + Route matched = _findRoute(app); + + if (matched != null) { + redirect( + matched.makeUri(params.keys.fold>({}, (out, k) { + return out..[k.toString()] = params[k]; + })), + code: code); + return; + } + + throw new ArgumentError.notNull('Route to redirect to ($name)'); + } + + /// Redirects to the given [Controller] action. + void redirectToAction(String action, [Map params, int code]) { + if (!isOpen) throw closed(); + // UserController@show + List split = action.split("@"); + + if (split.length < 2) + throw new Exception( + "Controller redirects must take the form of 'Controller@action'. You gave: $action"); + + Controller controller = + app.controllers[split[0].replaceAll(_straySlashes, '')]; + + if (controller == null) + throw new Exception("Could not find a controller named '${split[0]}'"); + + Route matched = controller.routeMappings[split[1]]; + + if (matched == null) + throw new Exception( + "Controller '${split[0]}' does not contain any action named '${split[1]}'"); + + final head = controller + .findExpose(app.container.reflector) + .path + .toString() + .replaceAll(_straySlashes, ''); + final tail = matched + .makeUri(params.keys.fold>({}, (out, k) { + return out..[k.toString()] = params[k]; + })) + .replaceAll(_straySlashes, ''); + + redirect('$head/$tail'.replaceAll(_straySlashes, ''), code: code); + } + + /// Copies a file's contents into the response buffer. + void sendFile(File file) { + if (!isOpen) throw closed(); + + contentType = MediaType.parse(lookupMimeType(file.path)); + buffer.add(file.readAsBytesSync()); + close(); + } + + /// Serializes data to the response. + bool serialize(value, {MediaType contentType}) { + if (!isOpen) throw closed(); + this.contentType = contentType ?? new MediaType('application', 'json'); + var text = serializer(value); + if (text.isEmpty) return true; + write(text); + close(); + return false; + } + + /// Streams a file to this response. + Future streamFile(File file) { + if (!isOpen) throw closed(); + contentType = MediaType.parse(lookupMimeType(file.path)); + return file.openRead().pipe(this); + } + + /// Configure the response to write to an intermediate response buffer, rather than to the stream directly. + void useBuffer(); + + /// Adds a stream directly the underlying response. + /// + /// This will also set [willCloseItself] to `true`, thus canceling out response finalizers. + /// + /// If this instance has access to a [correspondingRequest], then it will attempt to transform + /// the content using at most one of the response [encoders]. + @override + Future addStream(Stream> stream); + + @override + void addError(Object error, [StackTrace stackTrace]) { + if (_done?.isCompleted == false) _done.completeError(error, stackTrace); + } + + /// Writes data to the response. + void write(value, {Encoding encoding}) { + encoding ??= utf8; + + if (!isOpen && isBuffered) + throw closed(); + else if (!isBuffered) { + add(encoding.encode(value.toString())); + } else { + buffer.add(encoding.encode(value.toString())); + } + } + + @override + void writeCharCode(int charCode) { + if (!isOpen && isBuffered) + throw closed(); + else if (!isBuffered) + add([charCode]); + else + buffer.addByte(charCode); + } + + @override + void writeln([Object obj = ""]) { + write(obj.toString()); + write('\r\n'); + } + + @override + void writeAll(Iterable objects, [String separator = ""]) { + write(objects.join(separator)); + } +} + +abstract class LockableBytesBuilder extends BytesBuilder { + factory LockableBytesBuilder() { + return new _LockableBytesBuilderImpl(); + } + + void lock(); +} + +class _LockableBytesBuilderImpl implements LockableBytesBuilder { + final BytesBuilder _buf = new BytesBuilder(copy: false); + bool _closed = false; + + StateError _deny() => + new StateError('Cannot modified a closed response\'s buffer.'); + + @override + void lock() { + _closed = true; + } + + @override + void add(List bytes) { + if (_closed) + throw _deny(); + else + _buf.add(bytes); + } + + @override + void addByte(int byte) { + if (_closed) + throw _deny(); + else + _buf.addByte(byte); + } + + @override + void clear() { + _buf.clear(); + } + + @override + bool get isEmpty => _buf.isEmpty; + + @override + bool get isNotEmpty => _buf.isNotEmpty; + + @override + int get length => _buf.length; + + @override + List takeBytes() { + return _buf.takeBytes(); + } + + @override + List toBytes() { + return _buf.toBytes(); + } +} +/&,/!/!!9;,3<7 &2#M=D=L0E+ 8-h/.BAG;H) +7#%# "QS8jI8d">: :&0!%;>>" *gc*/7'5 ZP!2C F( '3!L"# '!!>'n6^a@ . 9M#+. 5 %  $ =$;#,B;F       $ * !  rfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/routable.dartlibrary angel_framework.http.routable; + +import 'dart:async'; + +import 'package:angel_container/angel_container.dart'; +import 'package:angel_route/angel_route.dart'; + +import '../util.dart'; +import 'hooked_service.dart'; +import 'metadata.dart'; +import 'request_context.dart'; +import 'response_context.dart'; +import 'service.dart'; + +final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); + +/// A function that receives an incoming [RequestContext] and responds to it. +typedef FutureOr RequestHandler(RequestContext req, ResponseContext res); + +/// Sequentially runs a list of [handlers] of middleware, and returns early if any does not +/// return `true`. Works well with [Router].chain. +RequestHandler waterfall(Iterable handlers) { + return (req, res) { + Future Function() runPipeline; + + for (var handler in handlers) { + if (handler == null) break; + + if (runPipeline == null) + runPipeline = () => Future.sync(() => handler(req, res)); + else { + var current = runPipeline; + runPipeline = () => current().then((result) => !res.isOpen + ? new Future.value(result) + : req.app.executeHandler(handler, req, res)); + } + } + + runPipeline ??= () => new Future.value(); + return runPipeline(); + }; +} + +/// A routable server that can handle dynamic requests. +class Routable extends Router { + final Map _services = {}; + final Map configuration = {}; + + final Container _container; + + Routable([Reflector reflector]) + : _container = reflector == null ? null : new Container(reflector), + super(); + + /// A [Container] used to inject dependencies. + Container get container => _container; + + void close() { + _services.clear(); + configuration.clear(); + _onService.close(); + } + + /// A set of [Service] objects that have been mapped into routes. + Map get services => _services; + + StreamController _onService = + new StreamController.broadcast(); + + /// Fired whenever a service is added to this instance. + /// + /// **NOTE**: This is a broadcast stream. + Stream get onService => _onService.stream; + + /// Retrieves the service assigned to the given path. + Service service(Pattern path) => + _services[path] ?? + _services[path.toString().replaceAll(_straySlashes, '')]; + + @override + Route addRoute( + String method, String path, RequestHandler handler, + {Iterable middleware: const []}) { + final handlers = []; + // Merge @Middleware declaration, if any + Middleware middlewareDeclaration = + getAnnotation(handler, Middleware, _container?.reflector); + if (middlewareDeclaration != null) { + handlers.addAll(middlewareDeclaration.handlers); + } + + final handlerSequence = []; + handlerSequence.addAll(middleware ?? []); + handlerSequence.addAll(handlers); + + return super.addRoute(method, path.toString(), handler, + middleware: handlerSequence); + } + + /// Mounts a [service] at the given [path]. + /// + /// Returns a [HookedService] that can be used to hook into + /// events dispatched by this service. + HookedService use(String path, Service service) { + var hooked = new HookedService(service); + _services[path + .toString() + .trim() + .replaceAll(new RegExp(r'(^/+)|(/+$)'), '')] = hooked; + hooked.addRoutes(); + mount(path.toString(), hooked); + service.onHooked(hooked); + _onService.add(hooked); + return hooked; + } +} +v'7/ 9NJ\3>#$"B #C':.80. "J1)D3)1:,68#@ ":I)-'C)70.&<&.>)4-?$pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/server.dartnlibrary angel_framework.http.server; + +import 'dart:async'; +import 'dart:collection' show HashMap; +import 'dart:convert'; +import 'dart:io'; + +import 'package:angel_container/angel_container.dart'; +import 'package:angel_http_exception/angel_http_exception.dart'; +import 'package:angel_route/angel_route.dart'; +import 'package:combinator/combinator.dart'; +import 'package:http_parser/http_parser.dart'; +import 'package:logging/logging.dart'; +import 'package:tuple/tuple.dart'; + +import '../http/http.dart'; +import 'hooked_service.dart'; +import 'request_context.dart'; +import 'response_context.dart'; +import 'routable.dart'; +import 'service.dart'; + +//final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); + +/// A function that configures an [Angel] server in some way. +typedef FutureOr AngelConfigurer(Angel app); + +/// A function that asynchronously generates a view from the given path and data. +typedef FutureOr ViewGenerator(String path, + [Map data]); + +/// A powerful real-time/REST/MVC server class. +class Angel extends Routable { + static ViewGenerator noViewEngineConfigured = + (String view, [Map data]) => 'No view engine has been configured yet.'; + + final List _children = []; + final Map, ParseResult>>> + handlerCache = new HashMap(); + + Router _flattened; + AngelHttp _http; + bool _isProduction; + Angel _parent; + + /// A global Map of converters that can transform responses bodies. + final Map, List>> encoders = {}; + + final Map _preContained = {}; + + /// A middleware to inject a serialize on every request. + String Function(dynamic) serializer; + + /// A [Map] of dependency data obtained via reflection. + /// + /// You may modify this [Map] yourself if you intend to avoid reflection entirely. + Map get preContained => _preContained; + + /// Returns the [flatten]ed version of this router in production. + Router get optimizedRouter => _flattened ?? this; + + /// Determines whether to allow HTTP request method overrides. + bool allowMethodOverrides = true; + + /// All child application mounted on this instance. + List get children => new List.unmodifiable(_children); + + final Map _controllers = {}; + + /// A set of [Controller] objects that have been loaded into the application. + Map get controllers => _controllers; + + /// Indicates whether the application is running in a production environment. + /// + /// The criteria for this is the `ANGEL_ENV` environment variable being set to + /// `'production'`. + /// + /// This value is memoized the first time you call it, so do not change environment + /// configuration at runtime! + bool get isProduction { + return _isProduction ??= + (Platform.environment['ANGEL_ENV'] == 'production'); + } + + /// Returns the parent instance of this application, if any. + Angel get parent => _parent; + + /// Outputs diagnostics and debug messages. + Logger logger; + + /// Plug-ins to be called right before server startup. + /// + /// If the server is never started, they will never be called. + final List startupHooks = []; + + /// Plug-ins to be called right before server shutdown. + /// + /// If the server is never [close]d, they will never be called. + final List shutdownHooks = []; + + /// Always run before responses are sent. + /// + /// These will only not run if a response's `willCloseItself` is set to `true`. + final List responseFinalizers = []; + + /// A [Map] of application-specific data that can be accessed by any + /// piece of code that can see this [Angel] instance. + /// + /// Packages like `package:angel_configuration` populate this map + /// for you. + final Map configuration = {}; + + /// When set to `true` (default: `false`), the request body will be parsed + /// automatically; otherwise, you must call [RequestContext].parseBody() manually, + /// or use `lazyBody()`. + bool eagerParseRequestBodies = false; + + /// When set to `true`, the original body bytes will be stored + /// on requests. `false` by default. + bool keepRawRequestBuffers = false; + + /// A function that renders views. + /// + /// Called by [ResponseContext]@`render`. + ViewGenerator viewGenerator = noViewEngineConfigured; + + /// The handler currently configured to run on [AngelHttpException]s. + Function(AngelHttpException e, RequestContext req, ResponseContext res) + errorHandler = + (AngelHttpException e, RequestContext req, ResponseContext res) { + if (!req.accepts('text/html', strict: true) && + (req.accepts('application/json') || + req.accepts('application/javascript'))) { + res.json(e.toJson()); + return; + } + + res.contentType = new MediaType('text', 'html', {'charset': 'utf8'}); + res.statusCode = e.statusCode; + res.write("${e.message}"); + res.write("

${e.message}

    "); + + for (String error in e.errors) { + res.write("
  • $error
  • "); + } + + res.write("
"); + res.close(); + }; + + @override + Route addRoute( + String method, String path, RequestHandler handler, + {Iterable middleware: const []}) { + if (_flattened != null) { + logger?.warning( + 'WARNING: You added a route ($method $path) to the router, after it had been optimized.'); + logger?.warning( + 'This route will be ignored, and no requests will ever reach it.'); + } + + return super.addRoute(method, path, handler, middleware: middleware ?? []); + } + + @override + mount(String path, Router router) { + if (_flattened != null) { + logger?.warning( + 'WARNING: You added mounted a child router ($path) on the router, after it had been optimized.'); + logger?.warning( + 'This route will be ignored, and no requests will ever reach it.'); + } + + if (router is Angel) { + router._parent = this; + _children.add(router); + } + + return super.mount(path.toString(), router); + } + + /// Loads some base dependencies into the service container. + void bootstrapContainer() { + if (runtimeType != Angel) { + container.registerSingleton(this); + } + + container.registerSingleton(this); + container.registerSingleton(this); + container.registerSingleton(this); + } + + /// Shuts down the server, and closes any open [StreamController]s. + /// + /// The server will be **COMPLETELY DEFUNCT** after this operation! + Future close() { + Future.forEach(services.values, (Service service) { + service.close(); + }); + + super.close(); + viewGenerator = noViewEngineConfigured; + _preContained.clear(); + handlerCache.clear(); + encoders.clear(); + //_serializer = json.encode; + _children.clear(); + _parent = null; + logger = null; + startupHooks.clear(); + shutdownHooks.clear(); + responseFinalizers.clear(); + _flattened = null; + _http?.close(); + return new Future.value(_http?.httpServer); + } + + @override + void dumpTree( + {callback(String tree), + String header: 'Dumping route tree:', + String tab: ' ', + bool showMatchers: false}) { + if (isProduction) { + _flattened ??= flatten(this); + + _flattened.dumpTree( + callback: callback, + header: header?.isNotEmpty == true + ? header + : (isProduction + ? 'Dumping flattened route tree:' + : 'Dumping route tree:'), + tab: tab ?? ' '); + } else { + super.dumpTree( + callback: callback, + header: header?.isNotEmpty == true + ? header + : (isProduction + ? 'Dumping flattened route tree:' + : 'Dumping route tree:'), + tab: tab ?? ' '); + } + } + + Future getHandlerResult(handler, RequestContext req, ResponseContext res) { + if (handler is RequestHandler) { + var result = handler(req, res); + return getHandlerResult(result, req, res); + } + + if (handler is Future) { + return handler.then((result) => getHandlerResult(result, req, res)); + } + + if (handler is Function) { + var result = runContained(handler, req, res); + return getHandlerResult(result, req, res); + } + + if (handler is Stream) { + return getHandlerResult(handler.toList(), req, res); + } + + return new Future.value(handler); + } + + /// Runs some [handler]. Returns `true` if request execution should continue. + Future executeHandler( + handler, RequestContext req, ResponseContext res) { + return getHandlerResult(handler, req, res).then((result) { + if (result == null) + return false; + else if (result is bool) { + return result; + } else if (result != null) { + return res.serialize(result); + } else + return res.isOpen; + }); + } + + /// Attempts to find a property by the given name within this application. + findProperty(key) { + if (configuration.containsKey(key)) return configuration[key]; + return parent != null ? parent.findProperty(key) : null; + } + + /// Runs several optimizations, *if* [isProduction] is `true`. + /// + /// * Preprocesses all dependency injection, and eliminates the burden of reflecting handlers + /// at run-time. + /// * [flatten]s the route tree into a linear one. + /// + /// You may [force] the optimization to run, if you are not running in production. + void optimizeForProduction({bool force: false}) { + if (isProduction == true || force == true) { + _isProduction = true; + _flattened ??= flatten(this); + logger?.config('Angel is running in production mode.'); + } + } + + /// Run a function after injecting from service container. + /// If this function has been reflected before, then + /// the execution will be faster, as the injection requirements were stored beforehand. + Future runContained( + Function handler, RequestContext req, ResponseContext res) { + return new Future.sync(() { + if (_preContained.containsKey(handler)) { + return handleContained(handler, _preContained[handler])(req, res); + } + + return runReflected(handler, req, res); + }); + } + + /// Runs with DI, and *always* reflects. Prefer [runContained]. + Future runReflected( + Function handler, RequestContext req, ResponseContext res) { + var h = handleContained( + handler, + _preContained[handler] = + preInject(handler, req.app.container.reflector)); + return new Future.sync(() => h(req, res)); + // return closureMirror.apply(args).reflectee; + } + + /// Applies an [AngelConfigurer] to this instance. + Future configure(AngelConfigurer configurer) { + return new Future.sync(() => configurer(this)); + } + + /// Shorthand for calling `all('*', handler)`. + Route fallback(RequestHandler handler) { + return all('*', handler); + } + + @override + HookedService use(String path, Service service) { + service.app = this; + return super.use(path, service)..app = this; + } + + Angel( + {Reflector reflector: const EmptyReflector(), + this.logger, + this.eagerParseRequestBodies: false, + this.allowMethodOverrides: true, + this.keepRawRequestBuffers: false, + this.serializer, + this.viewGenerator}) + : super(reflector) { + bootstrapContainer(); + viewGenerator ??= noViewEngineConfigured; + serializer ??= json.encode; + } +} +j%'7A/-/'# ;>-R4"00N$Q$FD;;':UDD4A$6G4P<PQV =?.9A1:B2,R6G8D MU(A'&%,8HJH3,6J#I9%$& ":IeNP 6lN1? ).1/FF8,! 0 ,#$-4, -4,N%&1K41;&P:?!#& MC=A`5U41$>=7ZC 0K.BC!>/55141; 41 4+'). qfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/service.dart=library angel_framework.http.service; + +import 'dart:async'; + +import 'package:angel_http_exception/angel_http_exception.dart'; +import 'package:merge_map/merge_map.dart'; + +import '../util.dart'; +import 'hooked_service.dart' show HookedService; +import 'metadata.dart'; +import 'response_context.dart'; +import 'routable.dart'; +import 'server.dart'; + +/// Indicates how the service was accessed. +/// +/// This will be passed to the `params` object in a service method. +/// When requested on the server side, this will be null. +class Providers { + /// The transport through which the client is accessing this service. + final String via; + + const Providers(String this.via); + + static const String viaRest = "rest"; + static const String viaWebsocket = "websocket"; + static const String viaGraphQL = "graphql"; + + /// Represents a request via REST. + static const Providers rest = Providers(viaRest); + + /// Represents a request over WebSockets. + static const Providers websocket = Providers(viaWebsocket); + + /// Represents a request parsed from GraphQL. + static const Providers graphQL = Providers(viaGraphQL); + + @override + bool operator ==(other) => other is Providers && other.via == via; + + Map toJson() { + return {'via': via}; + } + + @override + String toString() { + return 'via:$via'; + } +} + +/// A front-facing interface that can present data to and operate on data on behalf of the user. +/// +/// Heavily inspired by FeathersJS. <3 +class Service extends Routable { + /// A [List] of keys that services should ignore, should they see them in the query. + static const List specialQueryKeys = [ + r'$limit', + r'$sort', + 'page', + 'token' + ]; + + /// Handlers that must run to ensure this service's functionality. + List get bootstrappers => []; + + /// The [Angel] app powering this service. + Angel app; + + /// Closes this service, including any database connections or stream controllers. + void close() {} + + /// Retrieves the first object from the result of calling [index] with the given [params]. + /// + /// If the result of [index] is `null`, OR an empty [Iterable], a 404 `AngelHttpException` will be thrown. + /// + /// If the result is both non-null and NOT an [Iterable], it will be returned as-is. + /// + /// If the result is a non-empty [Iterable], [findOne] will return `it.first`, where `it` is the aforementioned [Iterable]. + /// + /// A custom [errorMessage] may be provided. + Future findOne( + [Map params, + String errorMessage = 'No record was found matching the given query.']) { + return index(params).then((result) { + if (result == null) { + throw new AngelHttpException.notFound(message: errorMessage); + } else if (result is Iterable) { + if (result.isEmpty) { + throw new AngelHttpException.notFound(message: errorMessage); + } else { + return result.first; + } + } else { + return result; + } + }); + } + + /// Retrieves all resources. + Future index([Map params]) { + throw new AngelHttpException.methodNotAllowed(); + } + + /// Retrieves the desired resource. + Future read(id, [Map params]) { + throw new AngelHttpException.methodNotAllowed(); + } + + /// Creates a resource. + Future create(data, [Map params]) { + throw new AngelHttpException.methodNotAllowed(); + } + + /// Modifies a resource. + Future modify(id, data, [Map params]) { + throw new AngelHttpException.methodNotAllowed(); + } + + /// Overwrites a resource. + Future update(id, data, [Map params]) { + throw new AngelHttpException.methodNotAllowed(); + } + + /// Removes the given resource. + Future remove(id, [Map params]) { + throw new AngelHttpException.methodNotAllowed(); + } + + /// Transforms an [id] (whether it is a String, num, etc.) into one acceptable by a service. + /// + /// The single type argument, [T], is used to determine how to parse the [id]. + /// + /// For example, `parseId` attempts to parse the value as a [bool]. + static T parseId(id) { + if (id == 'null' || id == null) + return null; + else if (T == String) + return id.toString() as T; + else if (T == int) + return int.parse(id.toString()) as T; + else if (T == bool) + return (id == true || id?.toString() == 'true') as T; + else if (T == double) + return int.parse(id.toString()) as T; + else if (T == num) + return num.parse(id.toString()) as T; + else + return id as T; + } + + /// Generates RESTful routes pointing to this class's methods. + void addRoutes([Service service]) { + _addRoutesInner(service ?? this, bootstrappers); + } + + void _addRoutesInner(Service service, Iterable handlerss) { + var restProvider = {'provider': Providers.rest}; + var handlers = new List.from(handlerss); + + // Add global middleware if declared on the instance itself + Middleware before = + getAnnotation(service, Middleware, app.container.reflector); + + if (before != null) handlers.addAll(before.handlers); + + Middleware indexMiddleware = + getAnnotation(service.index, Middleware, app.container.reflector); + get('/', (req, res) { + return req.parseQuery().then((query) { + return this.index(mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])); + }); + }, + middleware: [] + ..addAll(handlers) + ..addAll((indexMiddleware == null) ? [] : indexMiddleware.handlers)); + + Middleware createMiddleware = + getAnnotation(service.create, Middleware, app.container.reflector); + post('/', (req, ResponseContext res) { + return req.parseQuery().then((query) { + return req.parseBody().then((body) { + return this + .create( + body, + mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])) + .then((r) { + res.statusCode = 201; + return r; + }); + }); + }); + }, + middleware: [] + ..addAll(handlers) + ..addAll( + (createMiddleware == null) ? [] : createMiddleware.handlers)); + + Middleware readMiddleware = + getAnnotation(service.read, Middleware, app.container.reflector); + + get('/:id', (req, res) { + return req.parseQuery().then((query) { + return this.read( + parseId(req.params['id']), + mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])); + }); + }, + middleware: [] + ..addAll(handlers) + ..addAll((readMiddleware == null) ? [] : readMiddleware.handlers)); + + Middleware modifyMiddleware = + getAnnotation(service.modify, Middleware, app.container.reflector); + patch( + '/:id', + (req, res) => req.parseBody().then((body) { + return req.parseQuery().then((query) { + return this.modify( + parseId(req.params['id']), + body, + mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])); + }); + }), + middleware: [] + ..addAll(handlers) + ..addAll( + (modifyMiddleware == null) ? [] : modifyMiddleware.handlers)); + + Middleware updateMiddleware = + getAnnotation(service.update, Middleware, app.container.reflector); + post( + '/:id', + (req, res) => req.parseBody().then((body) { + return req.parseQuery().then((query) { + return this.update( + parseId(req.params['id']), + body, + mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])); + }); + }), + middleware: [] + ..addAll(handlers) + ..addAll( + (updateMiddleware == null) ? [] : updateMiddleware.handlers)); + put( + '/:id', + (req, res) => req.parseBody().then((body) { + return req.parseQuery().then((query) { + return this.update( + parseId(req.params['id']), + body, + mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])); + }); + }), + middleware: [] + ..addAll(handlers) + ..addAll( + (updateMiddleware == null) ? [] : updateMiddleware.handlers)); + + Middleware removeMiddleware = + getAnnotation(service.remove, Middleware, app.container.reflector); + delete('/', (req, res) { + return req.parseQuery().then((query) { + return this.remove( + null, + mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])); + }); + }, + middleware: [] + ..addAll(handlers) + ..addAll( + (removeMiddleware == null) ? [] : removeMiddleware.handlers)); + delete('/:id', (req, res) { + return req.parseQuery().then((query) { + return this.remove( + parseId(req.params['id']), + mergeMap([ + {'query': query}, + restProvider, + req.serviceParams + ])); + }); + }, + middleware: [] + ..addAll(handlers) + ..addAll( + (removeMiddleware == null) ? [] : removeMiddleware.handlers)); + + // REST compliance + put('/', (req, res) => throw new AngelHttpException.notFound()); + patch('/', (req, res) => throw new AngelHttpException.notFound()); + } + + /// Invoked when this service is wrapped within a [HookedService]. + void onHooked(HookedService hookedService) {} +} +F&A+1 ,D:H$(2.%4,>0: E! a'!W9 E0- U]mW~/P)F'H +5&"5&5*5*5"$5_QL$!,<,, A&5N5=@E:!K-% +'P"L+--&"&" +M J-'   +N"L 45$/($(M"L +45$/($(M 45$/($(M"L-   +M -'   +MEGE0wfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/core/typed_service.dart +tfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_http_exception-1.0.0+3/lib/angel_http_exception.dartlibrary angel_http_exception; + +import 'package:dart2_constant/convert.dart'; + +/// Basically the same as +/// [feathers-errors](https://github.com/feathersjs/feathers-errors). +class AngelHttpException implements Exception { + var error; + + /// A list of errors that occurred when this exception was thrown. + final List errors = []; + + /// The cause of this exception. + String message; + + /// The [StackTrace] associated with this error. + StackTrace stackTrace; + + /// An HTTP status code this exception will throw. + int statusCode; + + AngelHttpException(this.error, + {this.message: '500 Internal Server Error', + this.stackTrace, + this.statusCode: 500, + List errors: const []}) { + if (errors != null) { + this.errors.addAll(errors); + } + } + + Map toJson() { + return { + 'isError': true, + 'status_code': statusCode, + 'message': message, + 'errors': errors + }; + } + + Map toMap() => toJson(); + + @override + String toString() { + return "$statusCode: $message"; + } + + factory AngelHttpException.fromMap(Map data) { + return new AngelHttpException( + null, + statusCode: (data['status_code'] ?? data['statusCode']) as int, + message: data['message']?.toString(), + errors: data['errors'] is Iterable + ? ((data['errors'] as Iterable).map((x) => x.toString()).toList()) + : [], + ); + } + + factory AngelHttpException.fromJson(String str) => + new AngelHttpException.fromMap(json.decode(str) as Map); + + /// Throws a 400 Bad Request error, including an optional arrray of (validation?) + /// errors you specify. + factory AngelHttpException.badRequest( + {String message: '400 Bad Request', List errors: const []}) => + new AngelHttpException(null, + message: message, errors: errors, statusCode: 400); + + /// Throws a 401 Not Authenticated error. + factory AngelHttpException.notAuthenticated( + {String message: '401 Not Authenticated'}) => + new AngelHttpException(null, message: message, statusCode: 401); + + /// Throws a 402 Payment Required error. + factory AngelHttpException.paymentRequired( + {String message: '402 Payment Required'}) => + new AngelHttpException(null, message: message, statusCode: 402); + + /// Throws a 403 Forbidden error. + factory AngelHttpException.forbidden({String message: '403 Forbidden'}) => + new AngelHttpException(null, message: message, statusCode: 403); + + /// Throws a 404 Not Found error. + factory AngelHttpException.notFound({String message: '404 Not Found'}) => + new AngelHttpException(null, message: message, statusCode: 404); + + /// Throws a 405 Method Not Allowed error. + factory AngelHttpException.methodNotAllowed( + {String message: '405 Method Not Allowed'}) => + new AngelHttpException(null, message: message, statusCode: 405); + + /// Throws a 406 Not Acceptable error. + factory AngelHttpException.notAcceptable( + {String message: '406 Not Acceptable'}) => + new AngelHttpException(null, message: message, statusCode: 406); + + /// Throws a 408 Timeout error. + factory AngelHttpException.methodTimeout({String message: '408 Timeout'}) => + new AngelHttpException(null, message: message, statusCode: 408); + + /// Throws a 409 Conflict error. + factory AngelHttpException.conflict({String message: '409 Conflict'}) => + new AngelHttpException(null, message: message, statusCode: 409); + + /// Throws a 422 Not Processable error. + factory AngelHttpException.notProcessable( + {String message: '422 Not Processable'}) => + new AngelHttpException(null, message: message, statusCode: 422); + + /// Throws a 501 Not Implemented error. + factory AngelHttpException.notImplemented( + {String message: '501 Not Implemented'}) => + new AngelHttpException(null, message: message, statusCode: 501); + + /// Throws a 503 Unavailable error. + factory AngelHttpException.unavailable({String message: '503 Unavailable'}) => + new AngelHttpException(null, message: message, statusCode: 503); +} +x.F0 E"#35!2(" ! $1# F,)M5?T)Q#>,/8G+.7G$MG$LG-/9G),5G"OG#KG*-6G*-6G&QGbfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_model-1.0.0+1/lib/angel_model.dart/// Represents arbitrary data, with an associated ID and timestamps. +class Model { + String id; + DateTime createdAt; + DateTime updatedAt; + + Model({this.id, this.createdAt, this.updatedAt}); +} E 4`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/angel_route.dart|library angel_route; + +export 'src/middleware_pipeline.dart'; +export 'src/router.dart'; +export 'src/routing_exception.dart'; +'%`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/body_parser-1.1.1/lib/body_parser.dart/// A library for parsing HTTP request bodies and queries. +library body_parser; + +export 'src/body_parse_result.dart'; +export 'src/file_upload_info.dart'; +export 'src/parse_body.dart'; +;%$tfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/http/angel_http.dart:import 'dart:async'; +import 'dart:convert'; +import 'dart:io' + show + stderr, + HttpRequest, + HttpResponse, + HttpServer, + Platform, + SecurityContext; + +import 'package:angel_http_exception/angel_http_exception.dart'; +import 'package:angel_route/angel_route.dart'; +import 'package:combinator/combinator.dart'; +import 'package:stack_trace/stack_trace.dart'; +import 'package:tuple/tuple.dart'; + +import '../core/core.dart'; +import 'http_request_context.dart'; +import 'http_response_context.dart'; + +final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); + +/// Adapts `dart:io`'s [HttpServer] to serve Angel. +class AngelHttp { + final Angel app; + final bool useZone; + bool _closed = false; + HttpServer _server; + Future Function(dynamic, int) _serverGenerator = HttpServer.bind; + StreamSubscription _sub; + + AngelHttp(this.app, {this.useZone: false}); + + /// The function used to bind this instance to an HTTP server. + Future Function(dynamic, int) get serverGenerator => + _serverGenerator; + + /// An instance mounted on a server started by the [serverGenerator]. + factory AngelHttp.custom( + Angel app, Future Function(dynamic, int) serverGenerator, + {bool useZone: true}) { + return new AngelHttp(app, useZone: useZone) + .._serverGenerator = serverGenerator; + } + + factory AngelHttp.fromSecurityContext(Angel app, SecurityContext context, + {bool useZone: true}) { + var http = new AngelHttp(app, useZone: useZone); + + http._serverGenerator = (address, int port) { + return HttpServer.bindSecure(address, port, context); + }; + + return http; + } + + /// Creates an HTTPS server. + /// + /// Provide paths to a certificate chain and server key (both .pem). + /// If no password is provided, a random one will be generated upon running + /// the server. + factory AngelHttp.secure( + Angel app, String certificateChainPath, String serverKeyPath, + {String password, bool useZone: true}) { + var certificateChain = + Platform.script.resolve(certificateChainPath).toFilePath(); + var serverKey = Platform.script.resolve(serverKeyPath).toFilePath(); + var serverContext = new SecurityContext(); + serverContext.useCertificateChain(certificateChain, password: password); + serverContext.usePrivateKey(serverKey, password: password); + + return new AngelHttp.fromSecurityContext(app, serverContext, + useZone: useZone); + } + + /// The native HttpServer running this instance. + HttpServer get httpServer => _server; + + /// Starts the server. + /// + /// Returns false on failure; otherwise, returns the HttpServer. + Future startServer([address, int port]) { + var host = address ?? '127.0.0.1'; + return _serverGenerator(host, port ?? 0).then((server) { + _server = server; + return Future.wait(app.startupHooks.map(app.configure)).then((_) { + app.optimizeForProduction(); + _sub = _server.listen(handleRequest); + return _server; + }); + }); + } + + /// Shuts down the underlying server. + Future close() { + if (_closed) return new Future.value(_server); + _closed = true; + _sub?.cancel(); + return app.close().then((_) => + Future.wait(app.shutdownHooks.map(app.configure)).then((_) => _server)); + } + + /// Handles a single request. + Future handleRequest(HttpRequest request) { + return createRequestContext(request).then((req) { + return createResponseContext(request.response, req).then((res) { + handle() { + var path = req.path; + if (path == '/') path = ''; + + Tuple3, ParseResult>> + resolveTuple() { + Router r = app.optimizedRouter; + var resolved = + r.resolveAbsolute(path, method: req.method, strip: false); + + return new Tuple3( + new MiddlewarePipeline(resolved).handlers, + resolved.fold>( + {}, (out, r) => out..addAll(r.allParams)), + resolved.isEmpty ? null : resolved.first.parseResult, + ); + } + + var cacheKey = req.method + path; + var tuple = app.isProduction + ? app.handlerCache.putIfAbsent(cacheKey, resolveTuple) + : resolveTuple(); + + req.params.addAll(tuple.item2); + + req.container.registerSingleton>>( + tuple.item3); + req.container.registerSingleton(tuple.item3); + + if (!app.isProduction && app.logger != null) { + req.container + .registerSingleton(new Stopwatch()..start()); + } + + var pipeline = tuple.item1; + + Future Function() runPipeline; + + for (var handler in pipeline) { + if (handler == null) break; + + if (runPipeline == null) + runPipeline = () => + Future.sync(() => app.executeHandler(handler, req, res)); + else { + var current = runPipeline; + runPipeline = () => current().then((result) => !res.isOpen + ? new Future.value(result) + : app.executeHandler(handler, req, res)); + } + } + + return runPipeline == null + ? sendResponse(request, req, res) + : runPipeline().then((_) => sendResponse(request, req, res)); + } + + if (useZone == false) { + Future f; + + try { + f = handle(); + } catch (e, st) { + f = Future.error(e, st); + } + + return f.catchError((e, StackTrace st) { + if (e is FormatException) + throw new AngelHttpException.badRequest(message: e.message) + ..stackTrace = st; + throw new AngelHttpException(e, + stackTrace: st, + statusCode: 500, + message: e?.toString() ?? '500 Internal Server Error'); + }, test: (e) => e is! AngelHttpException).catchError( + (ee, StackTrace st) { + var e = ee as AngelHttpException; + + if (app.logger != null) { + var error = e.error ?? e; + var trace = + new Trace.from(e.stackTrace ?? StackTrace.current).terse; + app.logger.severe(e.message ?? e.toString(), error, trace); + } + + return handleAngelHttpException( + e, e.stackTrace ?? st, req, res, request); + }); + } else { + var zoneSpec = new ZoneSpecification( + print: (self, parent, zone, line) { + if (app.logger != null) + app.logger.info(line); + else + parent.print(zone, line); + }, + handleUncaughtError: (self, parent, zone, error, stackTrace) { + var trace = + new Trace.from(stackTrace ?? StackTrace.current).terse; + + return new Future(() { + AngelHttpException e; + + if (error is FormatException) { + e = new AngelHttpException.badRequest(message: error.message); + } else if (error is AngelHttpException) { + e = error; + } else { + e = new AngelHttpException(error, + stackTrace: stackTrace, + message: + error?.toString() ?? '500 Internal Server Error'); + } + + if (app.logger != null) { + app.logger.severe(e.message ?? e.toString(), error, trace); + } + + return handleAngelHttpException(e, trace, req, res, request); + }).catchError((e, StackTrace st) { + var trace = new Trace.from(st ?? StackTrace.current).terse; + request.response.close(); + // Ideally, we won't be in a position where an absolutely fatal error occurs, + // but if so, we'll need to log it. + if (app.logger != null) { + app.logger.severe( + 'Fatal error occurred when processing ${request.uri}.', + e, + trace); + } else { + stderr + ..writeln('Fatal error occurred when processing ' + '${request.uri}:') + ..writeln(e) + ..writeln(trace); + } + }); + }, + ); + + var zone = Zone.current.fork(specification: zoneSpec); + req.container.registerSingleton(zone); + req.container.registerSingleton(zoneSpec); + + // If a synchronous error is thrown, it's not caught by `zone.run`, + // so use a try/catch, and recover when need be. + + try { + return zone.run(handle); + } catch (e, st) { + zone.handleUncaughtError(e, st); + return Future.value(); + } + } + }); + }); + } + + /// Handles an [AngelHttpException]. + Future handleAngelHttpException(AngelHttpException e, StackTrace st, + RequestContext req, ResponseContext res, HttpRequest request, + {bool ignoreFinalizers: false}) { + if (req == null || res == null) { + try { + app.logger?.severe(e, st); + request.response + ..statusCode = 500 + ..write('500 Internal Server Error') + ..close(); + } finally { + return null; + } + } + + Future handleError; + + if (!res.isOpen) + handleError = new Future.value(); + else { + res.statusCode = e.statusCode; + handleError = + new Future.sync(() => app.errorHandler(e, req, res)).then((result) { + return app.executeHandler(result, req, res).then((_) => res.close()); + }); + } + + return handleError.then((_) => sendResponse(request, req, res, + ignoreFinalizers: ignoreFinalizers == true)); + } + + /// Sends a response. + Future sendResponse( + HttpRequest request, RequestContext req, ResponseContext res, + {bool ignoreFinalizers: false}) { + void _cleanup(_) { + if (!app.isProduction && app.logger != null) { + var sw = req.container.make(); + app.logger.info( + "${res.statusCode} ${req.method} ${req.uri} (${sw?.elapsedMilliseconds ?? 'unknown'} ms)"); + } + } + + if (!res.isBuffered) return res.close().then(_cleanup); + + Future finalizers = ignoreFinalizers == true + ? new Future.value() + : app.responseFinalizers.fold( + new Future.value(), (out, f) => out.then((_) => f(req, res))); + + return finalizers.then((_) { + if (res.isOpen) res.close(); + + for (var key in res.headers.keys) { + request.response.headers.add(key, res.headers[key]); + } + + request.response.contentLength = res.buffer.length; + request.response.headers.chunkedTransferEncoding = res.chunked ?? true; + + List outputBuffer = res.buffer.toBytes(); + + if (res.encoders.isNotEmpty) { + var allowedEncodings = req.headers + .value('accept-encoding') + ?.split(',') + ?.map((s) => s.trim()) + ?.where((s) => s.isNotEmpty) + ?.map((str) { + // Ignore quality specifications in accept-encoding + // ex. gzip;q=0.8 + if (!str.contains(';')) return str; + return str.split(';')[0]; + }); + + if (allowedEncodings != null) { + for (var encodingName in allowedEncodings) { + Converter, List> encoder; + String key = encodingName; + + if (res.encoders.containsKey(encodingName)) + encoder = res.encoders[encodingName]; + else if (encodingName == '*') { + encoder = res.encoders[key = res.encoders.keys.first]; + } + + if (encoder != null) { + request.response.headers.set('content-encoding', key); + outputBuffer = res.encoders[key].convert(outputBuffer); + request.response.contentLength = outputBuffer.length; + break; + } + } + } + } + + request.response + ..statusCode = res.statusCode + ..cookies.addAll(res.cookies) + ..add(outputBuffer); + + return request.response.close().then(_cleanup); + }); + } + + Future createRequestContext(HttpRequest request) { + var path = request.uri.path.replaceAll(_straySlashes, ''); + if (path.length == 0) path = '/'; + return HttpRequestContext.from(request, app, path); + } + + Future createResponseContext(HttpResponse response, + [RequestContext correspondingRequest]) => + new Future.value(new HttpResponseContext( + response, app, correspondingRequest as HttpRequestContext) + ..serializer = (app.serializer ?? json.encode) + ..encoders.addAll(app.encoders ?? {})); +} + A/-/#$%94P(.ACHL0,L52<GND/DI/M@A3(C8'=I%. +(3#Q .6G&P,K93ND ,'E *NE9I &)*(%"L)I-< %0L + % 3&J#, !H@$.&(LJ-;00&'*KJ%&0Q:4.M*NN1L*^4*%NF+!& A7HN;%-# + +'GD(& #/( %ON +C6D(52h<1/K!#*=:N5%+&#)>.$ (75'84,E#EFD +&&6I?&8G4AE70tfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/http/controller.dartlibrary angel_framework.http.controller; + +import 'dart:async'; +import 'package:angel_container/angel_container.dart'; +import 'package:angel_route/angel_route.dart'; +import 'package:meta/meta.dart'; + +import '../core/core.dart'; + +/// Supports grouping routes with shared functionality. +class Controller { + Angel _app; + + /// The [Angel] application powering this controller. + Angel get app => _app; + + /// If `true` (default), this class will inject itself as a singleton into the [app]'s container when bootstrapped. + final bool injectSingleton; + + /// Middleware to run before all handlers in this class. + List middleware = []; + + /// A mapping of route paths to routes, produced from the [Expose] annotations on this class. + Map routeMappings = {}; + + Controller({this.injectSingleton: true}); + + @mustCallSuper + Future configureServer(Angel app) { + _app = app; + + if (injectSingleton != false) { + _app.container.registerSingleton(this, as: runtimeType); + } + + // Load global expose decl + var classMirror = app.container.reflector.reflectClass(this.runtimeType); + Expose exposeDecl = findExpose(app.container.reflector); + + if (exposeDecl == null) { + throw new Exception( + "All controllers must carry an @Expose() declaration."); + } + + var routable = new Routable(); + app.mount(exposeDecl.path, routable); + var typeMirror = app.container.reflector.reflectType(this.runtimeType); + String name = + exposeDecl.as?.isNotEmpty == true ? exposeDecl.as : typeMirror.name; + + app.controllers[name] = this; + + // Pre-reflect methods + var instanceMirror = app.container.reflector.reflectInstance(this); + final handlers = [] + ..addAll(exposeDecl.middleware) + ..addAll(middleware); + final routeBuilder = _routeBuilder(instanceMirror, routable, handlers); + classMirror.declarations.forEach(routeBuilder); + configureRoutes(routable); + return new Future.value(); + } + + void Function(ReflectedDeclaration) _routeBuilder( + ReflectedInstance instanceMirror, + Routable routable, + Iterable handlers) { + return (ReflectedDeclaration decl) { + var methodName = decl.name; + + if (methodName != 'toString' && + methodName != 'noSuchMethod' && + methodName != 'call' && + methodName != 'equals' && + methodName != '==') { + Expose exposeDecl = decl.function.annotations + .map((m) => m.reflectee) + .firstWhere((r) => r is Expose, orElse: () => null); + + if (exposeDecl == null) return; + + var reflectedMethod = + instanceMirror.getField(methodName).reflectee as Function; + var middleware = [] + ..addAll(handlers) + ..addAll(exposeDecl.middleware); + String name = + exposeDecl.as?.isNotEmpty == true ? exposeDecl.as : methodName; + + // Check if normal + var method = decl.function; + if (method.parameters.length == 2 && + method.parameters[0].type.reflectedType == RequestContext && + method.parameters[1].type.reflectedType == ResponseContext) { + // Create a regular route + routeMappings[name] = routable + .addRoute(exposeDecl.method, exposeDecl.path, + (RequestContext req, ResponseContext res) { + var result = reflectedMethod(req, res); + return result is RequestHandler ? result(req, res) : result; + }, middleware: middleware); + return; + } + + var injection = preInject(reflectedMethod, app.container.reflector); + + if (exposeDecl?.allowNull?.isNotEmpty == true) + injection.optional?.addAll(exposeDecl.allowNull); + + routeMappings[name] = routable.addRoute(exposeDecl.method, + exposeDecl.path, handleContained(reflectedMethod, injection), + middleware: middleware); + } + }; + } + + /// Used to add additional routes to the router from within a [Controller]. + void configureRoutes(Routable routable) {} + + /// Finds the [Expose] declaration for this class. + Expose findExpose(Reflector reflector) => reflector + .reflectClass(runtimeType) + .annotations + .map((m) => m.reflectee) + .firstWhere((r) => r is Expose, orElse: () => null) as Expose; +} +)7/!88v;(`),&$?N=C#*LM"H(&L45(+)"&*"$ 6%A(G,+L$-IJ$)<>4I& +M7<CJ%N-56!E~file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/http/http_request_context.dartimport 'dart:async'; +import 'dart:io'; + +import 'package:angel_container/angel_container.dart'; +import 'package:body_parser/body_parser.dart'; +import 'package:http_parser/http_parser.dart'; + +import '../core/core.dart'; + +/// An implementation of [RequestContext] that wraps a [HttpRequest]. +class HttpRequestContext extends RequestContext { + Container _container; + MediaType _contentType; + HttpRequest _io; + String _override, _path; + + @override + Container get container => _container; + + @override + MediaType get contentType { + return _contentType; + } + + @override + List get cookies { + return rawRequest.cookies; + } + + @override + HttpHeaders get headers { + return rawRequest.headers; + } + + @override + String get hostname { + return rawRequest.headers.value('host'); + } + + /// The underlying [HttpRequest] instance underneath this context. + HttpRequest get rawRequest => _io; + + @override + String get method { + return _override ?? originalMethod; + } + + @override + String get originalMethod { + return rawRequest.method; + } + + @override + String get path { + return _path; + } + + @override + InternetAddress get remoteAddress { + return rawRequest.connectionInfo.remoteAddress; + } + + @override + HttpSession get session { + return rawRequest.session; + } + + @override + Uri get uri { + return rawRequest.uri; + } + + @override + bool get xhr { + return rawRequest.headers + .value("X-Requested-With") + ?.trim() + ?.toLowerCase() == + 'xmlhttprequest'; + } + + /// Magically transforms an [HttpRequest] into a [RequestContext]. + static Future from( + HttpRequest request, Angel app, String path) { + HttpRequestContext ctx = new HttpRequestContext() + .._container = app.container.createChild(); + + String override = request.method; + + if (app.allowMethodOverrides == true) + override = + request.headers.value('x-http-method-override')?.toUpperCase() ?? + request.method; + + ctx.app = app; + ctx._contentType = request.headers.contentType == null + ? null + : MediaType.parse(request.headers.contentType.toString()); + ctx._override = override; + + /* + // Faster way to get path + List _path = []; + + // Go up until we reach a ? + for (int ch in request.uri.toString().codeUnits) { + if (ch != $question) + _path.add(ch); + else + break; + } + + // Remove trailing slashes + int lastSlash = -1; + + for (int i = _path.length - 1; i >= 0; i--) { + if (_path[i] == $slash) + lastSlash = i; + else + break; + } + + if (lastSlash > -1) + ctx._path = new String.fromCharCodes(_path.take(lastSlash)); + else + ctx._path = new String.fromCharCodes(_path); + */ + + ctx._path = path; + ctx._io = request; + + if (app.eagerParseRequestBodies == true) { + return ctx.parse().then((_) => ctx); + } + + return new Future.value(ctx); + } + + @override + Future close() { + _contentType = null; + _io = null; + _override = _path = null; + return super.close(); + } + + @override + Future parseOnce() { + return parseBodyFromStream( + rawRequest, + rawRequest.headers.contentType != null + ? new MediaType.parse(rawRequest.headers.contentType.toString()) + : null, + rawRequest.uri, + storeOriginalBuffer: app.keepRawRequestBuffers == true); + } +} +7//F? )    -E% (   &4   'E*562&*L;C 7 2 C 3 /+"  ( /MAfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/http/http_response_context.dartimport 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import '../core/core.dart'; +import 'http_request_context.dart'; + +/// An implementation of [ResponseContext] that abstracts over an [HttpResponse]. +class HttpResponseContext extends ResponseContext { + /// The underlying [HttpResponse] under this instance. + @override + final HttpResponse rawResponse; + Angel app; + + LockableBytesBuilder _buffer; + + final HttpRequestContext _correspondingRequest; + bool _isDetached = false, _isClosed = false, _streamInitialized = false; + + HttpResponseContext(this.rawResponse, this.app, [this._correspondingRequest]); + + @override + HttpResponse detach() { + _isDetached = true; + return rawResponse; + } + + @override + RequestContext get correspondingRequest { + return _correspondingRequest; + } + + @override + bool get isOpen { + return !_isClosed && !_isDetached; + } + + @override + bool get isBuffered => _buffer != null; + + @override + BytesBuilder get buffer => _buffer; + + @override + void addError(Object error, [StackTrace stackTrace]) { + rawResponse.addError(error, stackTrace); + super.addError(error, stackTrace); + } + + @override + void useBuffer() { + _buffer = new LockableBytesBuilder(); + } + + Iterable __allowedEncodings; + + Iterable get _allowedEncodings { + return __allowedEncodings ??= correspondingRequest.headers + .value('accept-encoding') + ?.split(',') + ?.map((s) => s.trim()) + ?.where((s) => s.isNotEmpty) + ?.map((str) { + // Ignore quality specifications in accept-encoding + // ex. gzip;q=0.8 + if (!str.contains(';')) return str; + return str.split(';')[0]; + }); + } + + bool _openStream() { + if (!_streamInitialized) { + // If this is the first stream added to this response, + // then add headers, status code, etc. + rawResponse + ..statusCode = statusCode + ..cookies.addAll(cookies); + headers.forEach(rawResponse.headers.set); + rawResponse.headers.contentType = new ContentType( + contentType.type, contentType.subtype, + charset: contentType.parameters['charset'], + parameters: contentType.parameters); + + if (encoders.isNotEmpty && correspondingRequest != null) { + if (_allowedEncodings != null) { + for (var encodingName in _allowedEncodings) { + Converter, List> encoder; + String key = encodingName; + + if (encoders.containsKey(encodingName)) + encoder = encoders[encodingName]; + else if (encodingName == '*') { + encoder = encoders[key = encoders.keys.first]; + } + + if (encoder != null) { + rawResponse.headers.set('content-encoding', key); + break; + } + } + } + } + + //_isClosed = true; + return _streamInitialized = true; + } + + return false; + } + + @override + Future addStream(Stream> stream) { + if (_isClosed && isBuffered) throw ResponseContext.closed(); + _openStream(); + + Stream> output = stream; + + if (encoders.isNotEmpty && correspondingRequest != null) { + if (_allowedEncodings != null) { + for (var encodingName in _allowedEncodings) { + Converter, List> encoder; + String key = encodingName; + + if (encoders.containsKey(encodingName)) + encoder = encoders[encodingName]; + else if (encodingName == '*') { + encoder = encoders[key = encoders.keys.first]; + } + + if (encoder != null) { + output = encoders[key].bind(output); + break; + } + } + } + } + + return rawResponse.addStream(output); + } + + @override + void add(List data) { + if (_isClosed && isBuffered) + throw ResponseContext.closed(); + else if (!isBuffered) { + _openStream(); + + if (encoders.isNotEmpty && correspondingRequest != null) { + if (_allowedEncodings != null) { + for (var encodingName in _allowedEncodings) { + Converter, List> encoder; + String key = encodingName; + + if (encoders.containsKey(encodingName)) + encoder = encoders[encodingName]; + else if (encodingName == '*') { + encoder = encoders[key = encoders.keys.first]; + } + + if (encoder != null) { + data = encoders[key].convert(data); + break; + } + } + } + } + + rawResponse.add(data); + } else + buffer.add(data); + } + + @override + Future close() { + if (!_isDetached) { + if (!_isClosed) { + if (!isBuffered) { + try { + rawResponse.close(); + } catch (_) { + // This only seems to occur on `MockHttpRequest`, but + // this try/catch prevents a crash. + } + } else { + _buffer.lock(); + } + + _isClosed = true; + } + + super.close(); + } + return new Future.value(); + } +} +$RB9 "  2KQ  ," ' * & 9-' *'+?"%:* =-"#0916/A)85'40,=#@ +( /A'?'63%2.*; !1 +* !&A)85'40,=#2 +  !B0  +Rfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/args.dartz// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/arg_parser.dart'; +export 'src/arg_parser_exception.dart'; +export 'src/arg_results.dart' hide newArgResults; +export 'src/option.dart' hide newOption; + +NN<(2)pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_container-1.0.0-alpha.9/lib/angel_container.dartHlibrary angel_container; + +export 'src/container.dart'; +export 'src/empty/empty.dart'; +export 'src/exception.dart'; +export 'src/reflector.dart'; + +/// An annotation used by `package:angel_container_generator` to generate reflection metadata for types chosen by the user. +/// +/// When attached to a library, it generates a class that implements the `Reflector` interface. +/// +/// When attached to a class, it can be used to customize the output of the generator. +class GenerateReflector { + /// The list of types that should have reflection metadata generated for them. + final List types; + + /// The list of top-level functions that should have reflection metadata generated for them. + final List functions; + + /// The list of symbols within this class that should have reflection metadata generated for them. + /// + /// If omitted, then all symbols will be included. + final List symbols; + + /// An explicit name for the generated reflector. + /// + /// By default, a class with the library's name in PascalCase is created, + /// with the text "Reflector" appended. + /// + /// Ex. `my_cool_library` becomes `const MyCoolLibraryReflector()`. + final String name; + + const GenerateReflector( + {this.types: const [], + this.functions: const [], + this.symbols: const [], + this.name}); +} +(|`WQ_"e54L*F#*&Pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/ansi.dart// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/ansi_code.dart'; +JN<Nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/io.dart#// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/copy_path.dart' show copyPath, copyPathSync; +export 'src/exit_code.dart' show ExitCode; +export 'src/permissions.dart' show isExecutable; +export 'src/process_manager.dart' show ProcessManager, Spawn, StartProcess; +export 'src/shared_stdin.dart' show SharedStdIn, sharedStdIn; +export 'src/shell_words.dart' show shellSplit; + JN<9+1L>/[file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/logging-0.11.3+2/lib/logging.dartZ// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library logging; + +import 'dart:async'; +import 'dart:collection'; + +/// Whether to allow fine-grain logging and configuration of loggers in a +/// hierarchy. +/// +/// When false, all logging is merged in the root logger. +bool hierarchicalLoggingEnabled = false; + +/// Automatically record stack traces for any message of this level or above. +/// +/// Because this is expensive, this is off by default. +Level recordStackTraceAtLevel = Level.OFF; + +/// Level for the root-logger. +/// +/// This will be the level of all loggers if [hierarchicalLoggingEnabled] is +/// false. +Level _rootLevel = Level.INFO; + +/// Use a [Logger] to log debug messages. +/// +/// [Logger]s are named using a hierarchical dot-separated name convention. +class Logger { + /// Simple name of this logger. + final String name; + + /// The full name of this logger, which includes the parent's full name. + String get fullName => + (parent == null || parent.name == '') ? name : '${parent.fullName}.$name'; + + /// Parent of this logger in the hierarchy of loggers. + final Logger parent; + + /// Logging [Level] used for entries generated on this logger. + Level _level; + + final Map _children; + + /// Children in the hierarchy of loggers, indexed by their simple names. + final Map children; + + /// Controller used to notify when log entries are added to this logger. + StreamController _controller; + + /// Singleton constructor. Calling `new Logger(name)` will return the same + /// actual instance whenever it is called with the same string name. + factory Logger(String name) { + return _loggers.putIfAbsent(name, () => new Logger._named(name)); + } + + /// Creates a new detached [Logger]. + /// + /// Returns a new [Logger] instance (unlike `new Logger`, which returns a + /// [Logger] singleton), which doesn't have any parent or children, + /// and is not a part of the global hierarchical loggers structure. + /// + /// It can be useful when you just need a local short-living logger, + /// which you'd like to be garbage-collected later. + factory Logger.detached(String name) { + return new Logger._internal(name, null, new Map()); + } + + factory Logger._named(String name) { + if (name.startsWith('.')) { + throw new ArgumentError("name shouldn't start with a '.'"); + } + // Split hierarchical names (separated with '.'). + int dot = name.lastIndexOf('.'); + Logger parent; + String thisName; + if (dot == -1) { + if (name != '') parent = new Logger(''); + thisName = name; + } else { + parent = new Logger(name.substring(0, dot)); + thisName = name.substring(dot + 1); + } + return new Logger._internal(thisName, parent, new Map()); + } + + Logger._internal(this.name, this.parent, Map children) + : this._children = children, + this.children = new UnmodifiableMapView(children) { + if (parent != null) parent._children[name] = this; + } + + /// Effective level considering the levels established in this logger's + /// parents (when [hierarchicalLoggingEnabled] is true). + Level get level { + if (hierarchicalLoggingEnabled) { + if (_level != null) return _level; + if (parent != null) return parent.level; + } + return _rootLevel; + } + + /// Override the level for this particular [Logger] and its children. + set level(Level value) { + if (hierarchicalLoggingEnabled && parent != null) { + _level = value; + } else { + if (parent != null) { + throw new UnsupportedError( + 'Please set "hierarchicalLoggingEnabled" to true if you want to ' + 'change the level on a non-root logger.'); + } + _rootLevel = value; + } + } + + /// Returns a stream of messages added to this [Logger]. + /// + /// You can listen for messages using the standard stream APIs, for instance: + /// + /// ```dart + /// logger.onRecord.listen((record) { ... }); + /// ``` + Stream get onRecord => _getStream(); + + void clearListeners() { + if (hierarchicalLoggingEnabled || parent == null) { + if (_controller != null) { + _controller.close(); + _controller = null; + } + } else { + root.clearListeners(); + } + } + + /// Whether a message for [value]'s level is loggable in this logger. + bool isLoggable(Level value) => (value >= level); + + /// Adds a log record for a [message] at a particular [logLevel] if + /// `isLoggable(logLevel)` is true. + /// + /// Use this method to create log entries for user-defined levels. To record a + /// message at a predefined level (e.g. [Level.INFO], [Level.WARNING], etc) + /// you can use their specialized methods instead (e.g. [info], [warning], + /// etc). + /// + /// If [message] is a [Function], it will be lazy evaluated. Additionally, if + /// [message] or its evaluated value is not a [String], then 'toString()' will + /// be called on the object and the result will be logged. The log record will + /// contain a field holding the original object. + /// + /// The log record will also contain a field for the zone in which this call + /// was made. This can be advantageous if a log listener wants to handler + /// records of different zones differently (e.g. group log records by HTTP + /// request if each HTTP request handler runs in it's own zone). + void log(Level logLevel, message, + [Object error, StackTrace stackTrace, Zone zone]) { + Object object; + if (isLoggable(logLevel)) { + if (message is Function) { + message = message(); + } + + String msg; + if (message is String) { + msg = message; + } else { + msg = message.toString(); + object = message; + } + + if (stackTrace == null && logLevel >= recordStackTraceAtLevel) { + stackTrace = StackTrace.current; + error ??= 'autogenerated stack trace for $logLevel $msg'; + } + if (zone == null) zone = Zone.current; + + var record = new LogRecord( + logLevel, msg, fullName, error, stackTrace, zone, object); + + if (hierarchicalLoggingEnabled) { + var target = this; + while (target != null) { + target._publish(record); + target = target.parent; + } + } else { + root._publish(record); + } + } + } + + /// Log message at level [Level.FINEST]. + void finest(message, [Object error, StackTrace stackTrace]) => + log(Level.FINEST, message, error, stackTrace); + + /// Log message at level [Level.FINER]. + void finer(message, [Object error, StackTrace stackTrace]) => + log(Level.FINER, message, error, stackTrace); + + /// Log message at level [Level.FINE]. + void fine(message, [Object error, StackTrace stackTrace]) => + log(Level.FINE, message, error, stackTrace); + + /// Log message at level [Level.CONFIG]. + void config(message, [Object error, StackTrace stackTrace]) => + log(Level.CONFIG, message, error, stackTrace); + + /// Log message at level [Level.INFO]. + void info(message, [Object error, StackTrace stackTrace]) => + log(Level.INFO, message, error, stackTrace); + + /// Log message at level [Level.WARNING]. + void warning(message, [Object error, StackTrace stackTrace]) => + log(Level.WARNING, message, error, stackTrace); + + /// Log message at level [Level.SEVERE]. + void severe(message, [Object error, StackTrace stackTrace]) => + log(Level.SEVERE, message, error, stackTrace); + + /// Log message at level [Level.SHOUT]. + void shout(message, [Object error, StackTrace stackTrace]) => + log(Level.SHOUT, message, error, stackTrace); + + Stream _getStream() { + if (hierarchicalLoggingEnabled || parent == null) { + if (_controller == null) { + _controller = new StreamController.broadcast(sync: true); + } + return _controller.stream; + } else { + return root._getStream(); + } + } + + void _publish(LogRecord record) { + if (_controller != null) { + _controller.add(record); + } + } + + /// Top-level root [Logger]. + static final Logger root = new Logger(''); + + /// All [Logger]s in the system. + static final Map _loggers = {}; +} + +/// Handler callback to process log entries as they are added to a [Logger]. +typedef void LoggerHandler(LogRecord record); + +/// [Level]s to control logging output. Logging can be enabled to include all +/// levels above certain [Level]. [Level]s are ordered using an integer +/// value [Level.value]. The predefined [Level] constants below are sorted as +/// follows (in descending order): [Level.SHOUT], [Level.SEVERE], +/// [Level.WARNING], [Level.INFO], [Level.CONFIG], [Level.FINE], [Level.FINER], +/// [Level.FINEST], and [Level.ALL]. +/// +/// We recommend using one of the predefined logging levels. If you define your +/// own level, make sure you use a value between those used in [Level.ALL] and +/// [Level.OFF]. +class Level implements Comparable { + final String name; + + /// Unique value for this level. Used to order levels, so filtering can + /// exclude messages whose level is under certain value. + final int value; + + const Level(this.name, this.value); + + /// Special key to turn on logging for all levels ([value] = 0). + static const Level ALL = const Level('ALL', 0); + + /// Special key to turn off all logging ([value] = 2000). + static const Level OFF = const Level('OFF', 2000); + + /// Key for highly detailed tracing ([value] = 300). + static const Level FINEST = const Level('FINEST', 300); + + /// Key for fairly detailed tracing ([value] = 400). + static const Level FINER = const Level('FINER', 400); + + /// Key for tracing information ([value] = 500). + static const Level FINE = const Level('FINE', 500); + + /// Key for static configuration messages ([value] = 700). + static const Level CONFIG = const Level('CONFIG', 700); + + /// Key for informational messages ([value] = 800). + static const Level INFO = const Level('INFO', 800); + + /// Key for potential problems ([value] = 900). + static const Level WARNING = const Level('WARNING', 900); + + /// Key for serious failures ([value] = 1000). + static const Level SEVERE = const Level('SEVERE', 1000); + + /// Key for extra debugging loudness ([value] = 1200). + static const Level SHOUT = const Level('SHOUT', 1200); + + static const List LEVELS = const [ + ALL, + FINEST, + FINER, + FINE, + CONFIG, + INFO, + WARNING, + SEVERE, + SHOUT, + OFF + ]; + + @override + bool operator ==(Object other) => other is Level && value == other.value; + bool operator <(Level other) => value < other.value; + bool operator <=(Level other) => value <= other.value; + bool operator >(Level other) => value > other.value; + bool operator >=(Level other) => value >= other.value; + + @override + int compareTo(Level other) => value - other.value; + + @override + int get hashCode => value; + + @override + String toString() => name; +} + +/// A log entry representation used to propagate information from [Logger] to +/// individual handlers. +class LogRecord { + final Level level; + final String message; + + /// Non-string message passed to Logger. + final Object object; + + /// Logger where this record is stored. + final String loggerName; + + /// Time when this record was created. + final DateTime time; + + /// Unique sequence number greater than all log records created before it. + final int sequenceNumber; + + static int _nextNumber = 0; + + /// Associated error (if any) when recording errors messages. + final Object error; + + /// Associated stackTrace (if any) when recording errors messages. + final StackTrace stackTrace; + + /// Zone of the calling code which resulted in this LogRecord. + final Zone zone; + + LogRecord(this.level, this.message, this.loggerName, + [this.error, this.stackTrace, this.zone, this.object]) + : time = new DateTime.now(), + sequenceNumber = LogRecord._nextNumber++; + + @override + String toString() => '[${level.name}] $loggerName: $message'; +} +sNN<J:)N7+M *L"KQ9A'K&K+MG F'LFFG6)H' B6%/ 3*NI#<7J;&)/H8 $N7;P0 +28! H4F&QNM PQQ3OLMC$: !"G)B-"E(!#" ++A5*@4)?3+A5)?3,B6+A5*@4#8!M! $-#BM.NHNBP%PO+J;&C2<57:7836=:662<1;99, + +  L7979 5  N+*)M@EA7=#2 @Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/isolate.dartCexport 'src/isolate/client.dart'; +export 'src/isolate/server.dart';""pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/client/sync_client.dartexport 'client.dart';pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/server/sync_server.dartuexport 'adapter.dart'; +export 'client.dart'; +export 'publish.dart'; +export 'server.dart'; +export 'subscription.dart';ifile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_framework-2.0.0-alpha.2/lib/src/util.dartimport 'package:angel_container/angel_container.dart'; + +final RegExp straySlashes = new RegExp(r'(^/+)|(/+$)'); + +matchingAnnotation(List metadata, Type T) { + for (ReflectedInstance metaDatum in metadata) { + if (metaDatum.type.reflectedType == T) { + return metaDatum.reflectee; + } + } + + return null; +} + +getAnnotation(obj, Type T, Reflector reflector) { + if (reflector == null) { + return null; + } else { + if (obj is Function) { + var methodMirror = reflector.reflectFunction(obj); + return matchingAnnotation(methodMirror.annotations, T); + } else { + var classMirror = reflector.reflectClass(obj.runtimeType as Type); + return matchingAnnotation(classMirror.annotations, T); + } + } +} +78?2-"2 9> I=`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/http_parser.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/authentication_challenge.dart'; +export 'src/case_insensitive_map.dart'; +export 'src/chunked_coding.dart'; +export 'src/http_date.dart'; +export 'src/media_type.dart'; + NN<,("Rfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/meta-1.1.6/lib/meta.dart#// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Constants for use in metadata annotations. +/// +/// See also `@deprecated` and `@override` in the `dart:core` library. +/// +/// Annotations provide semantic information that tools can use to provide a +/// better user experience. For example, an IDE might not autocomplete the name +/// of a function that's been marked `@deprecated`, or it might display the +/// function's name differently. +/// +/// For information on installing and importing this library, see the +/// [meta package on pub.dartlang.org] (http://pub.dartlang.org/packages/meta). +/// For examples of using annotations, see +/// [Metadata](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#metadata) +/// in the language tour. +library meta; + +/// Used to annotate a function `f`. Indicates that `f` always throws an +/// exception. Any functions that override `f`, in class inheritence, are also +/// expected to conform to this contract. +/// +/// Tools, such as the analyzer, can use this to understand whether a block of +/// code "exits". For example: +/// +/// ```dart +/// @alwaysThrows toss() { throw 'Thrown'; } +/// +/// int fn(bool b) { +/// if (b) { +/// return 0; +/// } else { +/// toss(); +/// print("Hello."); +/// } +/// } +/// ``` +/// +/// Without the annotation on `toss`, it would look as though `fn` doesn't +/// always return a value. The annotation shows that `fn` does always exit. In +/// addition, the annotation reveals that any statements following a call to +/// `toss` (like the `print` call) are dead code. +/// +/// Tools, such as the analyzer, can also expect this contract to be enforced; +/// that is, tools may emit warnings if a function with this annotation +/// _doesn't_ always throw. +const _AlwaysThrows alwaysThrows = const _AlwaysThrows(); + +/// Used to annotate a parameter of an instance method that overrides another +/// method. +/// +/// Indicates that this parameter may have a tighter type than the parameter on +/// its superclass. The actual argument will be checked at runtime to ensure it +/// is a subtype of the overridden parameter type. +/// +/// DEPRECATED: Use the `covariant` modifier instead. +@deprecated +const _Checked checked = const _Checked(); + +/// Used to annotate a library, or any declaration that is part of the public +/// interface of a library (such as top-level members, class members, and +/// function parameters) to indicate that the annotated API is experimental and +/// may be removed or changed at any-time without updating the version of the +/// containing package, despite the fact that it would otherwise be a breaking +/// change. +/// +/// If the annotation is applied to a library then it is equivalent to applying +/// the annotation to all of the top-level members of the library. Applying the +/// annotation to a class does *not* apply the annotation to subclasses, but +/// does apply the annotation to members of the class. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with a declaration that is not part of the +/// public interface of a library (such as a local variable or a declaration +/// that is private) or a directive other than the first directive in the +/// library, or +/// * the declaration is referenced by a package that has not explicitly +/// indicated its intention to use experimental APIs (details TBD). +const _Experimental experimental = const _Experimental(); + +/// Used to annotate an instance or static method `m`. Indicates that `m` must +/// either be abstract or must return a newly allocated object or `null`. In +/// addition, every method that either implements or overrides `m` is implicitly +/// annotated with this same annotation. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a method, or +/// * the annotation is associated with a method that has this annotation that +/// can return anything other than a newly allocated object or `null`. +const _Factory factory = const _Factory(); + +/// Used to annotate a class `C`. Indicates that `C` and all subtypes of `C` +/// must be immutable. +/// +/// A class is immutable if all of the instance fields of the class, whether +/// defined directly or inherited, are `final`. +/// +/// Tools, such as the analyzer, can provide feedback if +/// * the annotation is associated with anything other than a class, or +/// * a class that has this annotation or extends, implements or mixes in a +/// class that has this annotation is not immutable. +const Immutable immutable = const Immutable(); + +/// Used to annotate a test framework function that runs a single test. +/// +/// Tools, such as IDEs, can show invocations of such function in a file +/// structure view to help the user navigating in large test files. +/// +/// The first parameter of the function must be the description of the test. +const _IsTest isTest = const _IsTest(); + +/// Used to annotate a test framework function that runs a group of tests. +/// +/// Tools, such as IDEs, can show invocations of such function in a file +/// structure view to help the user navigating in large test files. +/// +/// The first parameter of the function must be the description of the group. +const _IsTestGroup isTestGroup = const _IsTestGroup(); + +/// Used to annotate a const constructor `c`. Indicates that any invocation of +/// the constructor must use the keyword `const` unless one or more of the +/// arguments to the constructor is not a compile-time constant. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a const constructor, +/// or +/// * an invocation of a constructor that has this annotation is not invoked +/// using the `const` keyword unless one or more of the arguments to the +/// constructor is not a compile-time constant. +const _Literal literal = const _Literal(); + +/// Used to annotate an instance method `m`. Indicates that every invocation of +/// a method that overrides `m` must also invoke `m`. In addition, every method +/// that overrides `m` is implicitly annotated with this same annotation. +/// +/// Note that private methods with this annotation cannot be validly overridden +/// outside of the library that defines the annotated method. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than an instance method, +/// or +/// * a method that overrides a method that has this annotation can return +/// without invoking the overridden method. +const _MustCallSuper mustCallSuper = const _MustCallSuper(); + +/// Used to annotate a class declaration `C`. Indicates that any type arguments +/// declared on `C` are to be treated as optional. Tools such as the analyzer +/// and linter can use this information to suppress warnings that would +/// otherwise require type arguments to be provided for instances of `C`. +const _OptionalTypeArgs optionalTypeArgs = const _OptionalTypeArgs(); + +/// Used to annotate an instance member (method, getter, setter, operator, or +/// field) `m` in a class `C`. If the annotation is on a field it applies to the +/// getter, and setter if appropriate, that are induced by the field. Indicates +/// that `m` should only be invoked from instance methods of `C` or classes that +/// extend, implement or mix in `C`, either directly or indirectly. Additionally +/// indicates that `m` should only be invoked on `this`, whether explicitly or +/// implicitly. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than an instance member, +/// or +/// * an invocation of a member that has this annotation is used outside of an +/// instance member defined on a class that extends or mixes in the class in +/// which the protected member is defined, or that uses a receiver other than +/// `this`. +const _Protected protected = const _Protected(); + +/// Used to annotate a named parameter `p` in a method or function `f`. +/// Indicates that every invocation of `f` must include an argument +/// corresponding to `p`, despite the fact that `p` would otherwise be an +/// optional parameter. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a named parameter, +/// * the annotation is associated with a named parameter in a method `m1` that +/// overrides a method `m0` and `m0` defines a named parameter with the same +/// name that does not have this annotation, or +/// * an invocation of a method or function does not include an argument +/// corresponding to a named parameter that has this annotation. +const Required required = const Required(); + +/// Used to annotate a field that is allowed to be overridden in Strong Mode. +const _Virtual virtual = const _Virtual(); + +/// Used to annotate an instance member that was made public so that it could be +/// overridden but that is not intended to be referenced from outside the +/// defining library. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with a declaration other than a public +/// instance member in a class, or +/// * the member is referenced outside of the defining library. +const _VisibleForOverriding visibleForOverriding = + const _VisibleForOverriding(); + +/// Used to annotate a declaration was made public, so that it is more visible +/// than otherwise necessary, to make code testable. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with a declaration not in the `lib` folder +/// of a package, or +/// * the declaration is referenced outside of its the defining library or a +/// library which is in the `test` folder of the defining package. +const _VisibleForTesting visibleForTesting = const _VisibleForTesting(); + +/// Used to annotate a class. +/// +/// See [immutable] for more details. +class Immutable { + /// A human-readable explanation of the reason why the class is immutable. + final String reason; + + /// Initialize a newly created instance to have the given [reason]. + const Immutable([this.reason]); +} + +/// Used to annotate a named parameter `p` in a method or function `f`. +/// +/// See [required] for more details. +class Required { + /// A human-readable explanation of the reason why the annotated parameter is + /// required. For example, the annotation might look like: + /// + /// ButtonWidget({ + /// Function onHover, + /// @Required('Buttons must do something when pressed') + /// Function onPressed, + /// ... + /// }) ... + final String reason; + + /// Initialize a newly created instance to have the given [reason]. + const Required([this.reason]); +} + +class _AlwaysThrows { + const _AlwaysThrows(); +} + +class _Checked { + const _Checked(); +} + +class _Experimental { + const _Experimental(); +} + +class _Factory { + const _Factory(); +} + +class _IsTest { + const _IsTest(); +} + +class _IsTestGroup { + const _IsTestGroup(); +} + +class _Literal { + const _Literal(); +} + +class _MustCallSuper { + const _MustCallSuper(); +} + +class _OptionalTypeArgs { + const _OptionalTypeArgs(); +} + +class _Protected { + const _Protected(); +} + +class _Virtual { + const _Virtual(); +} + +class _VisibleForOverriding { + const _VisibleForOverriding(); +} + +class _VisibleForTesting { + const _VisibleForTesting(); +} ++NN</GMPL!FP+UIO*O -KOM2OH:N PP36 +NJPNO PPM79NOLIF:OMQ)9IOI+MM09HL7/HIDM(KIDN7OKA9Q MK2+PPJP>9P K.=POHJFNQPQQO9P OOP1HDJ9OPO2IC,N+QJ9J%@3#O59NMEI&MF"H%P= B"F!!Rfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/path.dartBv// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A comprehensive, cross-platform path manipulation library. +/// +/// ## Installing ## +/// +/// Use [pub][] to install this package. Add the following to your +/// `pubspec.yaml` file. +/// +/// dependencies: +/// path: any +/// +/// Then run `pub install`. +/// +/// For more information, see the [path package on pub.dartlang.org][pkg]. +/// +/// [pub]: http://pub.dartlang.org +/// [pkg]: http://pub.dartlang.org/packages/path +/// +/// ## Usage ## +/// +/// The path library was designed to be imported with a prefix, though you don't +/// have to if you don't want to: +/// +/// import 'package:path/path.dart' as p; +/// +/// The most common way to use the library is through the top-level functions. +/// These manipulate path strings based on your current working directory and +/// the path style (POSIX, Windows, or URLs) of the host platform. For example: +/// +/// p.join("directory", "file.txt"); +/// +/// This calls the top-level [join] function to join "directory" and "file.txt" +/// using the current platform's directory separator. +/// +/// If you want to work with paths for a specific platform regardless of the +/// underlying platform that the program is running on, you can create a +/// [Context] and give it an explicit [Style]: +/// +/// var context = new p.Context(style: Style.windows); +/// context.join("directory", "file.txt"); +/// +/// This will join "directory" and "file.txt" using the Windows path separator, +/// even when the program is run on a POSIX machine. +import 'src/context.dart'; +import 'src/style.dart'; + +export 'src/context.dart' hide createInternal; +export 'src/path_exception.dart'; +export 'src/path_map.dart'; +export 'src/path_set.dart'; +export 'src/style.dart'; + +/// A default context for manipulating POSIX paths. +final Context posix = new Context(style: Style.posix); + +/// A default context for manipulating Windows paths. +final Context windows = new Context(style: Style.windows); + +/// A default context for manipulating URLs. +/// +/// URL path equality is undefined for paths that differ only in their +/// percent-encoding or only in the case of their host segment. +final Context url = new Context(style: Style.url); + +/// The system path context. +/// +/// This differs from a context created with [new Context] in that its +/// [Context.current] is always the current working directory, rather than being +/// set once when the context is created. +final Context context = createInternal(); + +/// Returns the [Style] of the current context. +/// +/// This is the style that all top-level path functions will use. +Style get style => context.style; + +/// Gets the path to the current working directory. +/// +/// In the browser, this means the current URL, without the last file segment. +String get current { + var uri = Uri.base; + + // Converting the base URI to a file path is pretty slow, and the base URI + // rarely changes in practice, so we cache the result here. + if (uri == _currentUriBase) return _current; + _currentUriBase = uri; + + if (Style.platform == Style.url) { + _current = uri.resolve('.').toString(); + return _current; + } else { + var path = uri.toFilePath(); + // Remove trailing '/' or '\' unless it is the only thing left + // (for instance the root on Linux). + var lastIndex = path.length - 1; + assert(path[lastIndex] == '/' || path[lastIndex] == '\\'); + _current = lastIndex == 0 ? path : path.substring(0, lastIndex); + return _current; + } +} + +/// The last value returned by [Uri.base]. +/// +/// This is used to cache the current working directory. +Uri _currentUriBase; + +/// The last known value of the current working directory. +/// +/// This is cached because [current] is called frequently but rarely actually +/// changes. +String _current; + +/// Gets the path separator for the current platform. This is `\` on Windows +/// and `/` on other platforms (including the browser). +String get separator => context.separator; + +/// Creates a new path by appending the given path parts to [current]. +/// Equivalent to [join()] with [current] as the first argument. Example: +/// +/// p.absolute('path', 'to/foo'); // -> '/your/current/dir/path/to/foo' +String absolute(String part1, + [String part2, + String part3, + String part4, + String part5, + String part6, + String part7]) => + context.absolute(part1, part2, part3, part4, part5, part6, part7); + +/// Gets the part of [path] after the last separator. +/// +/// p.basename('path/to/foo.dart'); // -> 'foo.dart' +/// p.basename('path/to'); // -> 'to' +/// +/// Trailing separators are ignored. +/// +/// p.basename('path/to/'); // -> 'to' +String basename(String path) => context.basename(path); + +/// Gets the part of [path] after the last separator, and without any trailing +/// file extension. +/// +/// p.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' +/// +/// Trailing separators are ignored. +/// +/// p.basenameWithoutExtension('path/to/foo.dart/'); // -> 'foo' +String basenameWithoutExtension(String path) => + context.basenameWithoutExtension(path); + +/// Gets the part of [path] before the last separator. +/// +/// p.dirname('path/to/foo.dart'); // -> 'path/to' +/// p.dirname('path/to'); // -> 'path' +/// +/// Trailing separators are ignored. +/// +/// p.dirname('path/to/'); // -> 'path' +/// +/// If an absolute path contains no directories, only a root, then the root +/// is returned. +/// +/// p.dirname('/'); // -> '/' (posix) +/// p.dirname('c:\'); // -> 'c:\' (windows) +/// +/// If a relative path has no directories, then '.' is returned. +/// +/// p.dirname('foo'); // -> '.' +/// p.dirname(''); // -> '.' +String dirname(String path) => context.dirname(path); + +/// Gets the file extension of [path]: the portion of [basename] from the last +/// `.` to the end (including the `.` itself). +/// +/// p.extension('path/to/foo.dart'); // -> '.dart' +/// p.extension('path/to/foo'); // -> '' +/// p.extension('path.to/foo'); // -> '' +/// p.extension('path/to/foo.dart.js'); // -> '.js' +/// +/// If the file name starts with a `.`, then that is not considered the +/// extension: +/// +/// p.extension('~/.bashrc'); // -> '' +/// p.extension('~/.notes.txt'); // -> '.txt' +String extension(String path) => context.extension(path); + +// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. +/// Returns the root of [path], if it's absolute, or the empty string if it's +/// relative. +/// +/// // Unix +/// p.rootPrefix('path/to/foo'); // -> '' +/// p.rootPrefix('/path/to/foo'); // -> '/' +/// +/// // Windows +/// p.rootPrefix(r'path\to\foo'); // -> '' +/// p.rootPrefix(r'C:\path\to\foo'); // -> r'C:\' +/// +/// // URL +/// p.rootPrefix('path/to/foo'); // -> '' +/// p.rootPrefix('http://dartlang.org/path/to/foo'); +/// // -> 'http://dartlang.org' +String rootPrefix(String path) => context.rootPrefix(path); + +/// Returns `true` if [path] is an absolute path and `false` if it is a +/// relative path. +/// +/// On POSIX systems, absolute paths start with a `/` (forward slash). On +/// Windows, an absolute path starts with `\\`, or a drive letter followed by +/// `:/` or `:\`. For URLs, absolute paths either start with a protocol and +/// optional hostname (e.g. `http://dartlang.org`, `file://`) or with a `/`. +/// +/// URLs that start with `/` are known as "root-relative", since they're +/// relative to the root of the current URL. Since root-relative paths are still +/// absolute in every other sense, [isAbsolute] will return true for them. They +/// can be detected using [isRootRelative]. +bool isAbsolute(String path) => context.isAbsolute(path); + +/// Returns `true` if [path] is a relative path and `false` if it is absolute. +/// On POSIX systems, absolute paths start with a `/` (forward slash). On +/// Windows, an absolute path starts with `\\`, or a drive letter followed by +/// `:/` or `:\`. +bool isRelative(String path) => context.isRelative(path); + +/// Returns `true` if [path] is a root-relative path and `false` if it's not. +/// +/// URLs that start with `/` are known as "root-relative", since they're +/// relative to the root of the current URL. Since root-relative paths are still +/// absolute in every other sense, [isAbsolute] will return true for them. They +/// can be detected using [isRootRelative]. +/// +/// No POSIX and Windows paths are root-relative. +bool isRootRelative(String path) => context.isRootRelative(path); + +/// Joins the given path parts into a single path using the current platform's +/// [separator]. Example: +/// +/// p.join('path', 'to', 'foo'); // -> 'path/to/foo' +/// +/// If any part ends in a path separator, then a redundant separator will not +/// be added: +/// +/// p.join('path/', 'to', 'foo'); // -> 'path/to/foo +/// +/// If a part is an absolute path, then anything before that will be ignored: +/// +/// p.join('path', '/to', 'foo'); // -> '/to/foo' +String join(String part1, + [String part2, + String part3, + String part4, + String part5, + String part6, + String part7, + String part8]) => + context.join(part1, part2, part3, part4, part5, part6, part7, part8); + +/// Joins the given path parts into a single path using the current platform's +/// [separator]. Example: +/// +/// p.joinAll(['path', 'to', 'foo']); // -> 'path/to/foo' +/// +/// If any part ends in a path separator, then a redundant separator will not +/// be added: +/// +/// p.joinAll(['path/', 'to', 'foo']); // -> 'path/to/foo +/// +/// If a part is an absolute path, then anything before that will be ignored: +/// +/// p.joinAll(['path', '/to', 'foo']); // -> '/to/foo' +/// +/// For a fixed number of parts, [join] is usually terser. +String joinAll(Iterable parts) => context.joinAll(parts); + +// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. +/// Splits [path] into its components using the current platform's [separator]. +/// +/// p.split('path/to/foo'); // -> ['path', 'to', 'foo'] +/// +/// The path will *not* be normalized before splitting. +/// +/// p.split('path/../foo'); // -> ['path', '..', 'foo'] +/// +/// If [path] is absolute, the root directory will be the first element in the +/// array. Example: +/// +/// // Unix +/// p.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo'] +/// +/// // Windows +/// p.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo'] +/// +/// // Browser +/// p.split('http://dartlang.org/path/to/foo'); +/// // -> ['http://dartlang.org', 'path', 'to', 'foo'] +List split(String path) => context.split(path); + +/// Canonicalizes [path]. +/// +/// This is guaranteed to return the same path for two different input paths +/// if and only if both input paths point to the same location. Unlike +/// [normalize], it returns absolute paths when possible and canonicalizes +/// ASCII case on Windows. +/// +/// Note that this does not resolve symlinks. +/// +/// If you want a map that uses path keys, it's probably more efficient to +/// pass [equals] and [hash] to [new HashMap] than it is to canonicalize every +/// key. +String canonicalize(String path) => context.canonicalize(path); + +/// Normalizes [path], simplifying it by handling `..`, and `.`, and +/// removing redundant path separators whenever possible. +/// +/// Note that this is *not* guaranteed to return the same result for two +/// equivalent input paths. For that, see [canonicalize]. Or, if you're using +/// paths as map keys, pass [equals] and [hash] to [new HashMap]. +/// +/// p.normalize('path/./to/..//file.text'); // -> 'path/file.txt' +String normalize(String path) => context.normalize(path); + +/// Attempts to convert [path] to an equivalent relative path from the current +/// directory. +/// +/// // Given current directory is /root/path: +/// p.relative('/root/path/a/b.dart'); // -> 'a/b.dart' +/// p.relative('/root/other.dart'); // -> '../other.dart' +/// +/// If the [from] argument is passed, [path] is made relative to that instead. +/// +/// p.relative('/root/path/a/b.dart', from: '/root/path'); // -> 'a/b.dart' +/// p.relative('/root/other.dart', from: '/root/path'); +/// // -> '../other.dart' +/// +/// If [path] and/or [from] are relative paths, they are assumed to be relative +/// to the current directory. +/// +/// Since there is no relative path from one drive letter to another on Windows, +/// or from one hostname to another for URLs, this will return an absolute path +/// in those cases. +/// +/// // Windows +/// p.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other' +/// +/// // URL +/// p.relative('http://dartlang.org', from: 'http://pub.dartlang.org'); +/// // -> 'http://dartlang.org' +String relative(String path, {String from}) => + context.relative(path, from: from); + +/// Returns `true` if [child] is a path beneath `parent`, and `false` otherwise. +/// +/// p.isWithin('/root/path', '/root/path/a'); // -> true +/// p.isWithin('/root/path', '/root/other'); // -> false +/// p.isWithin('/root/path', '/root/path') // -> false +bool isWithin(String parent, String child) => context.isWithin(parent, child); + +/// Returns `true` if [path1] points to the same location as [path2], and +/// `false` otherwise. +/// +/// The [hash] function returns a hash code that matches these equality +/// semantics. +bool equals(String path1, String path2) => context.equals(path1, path2); + +/// Returns a hash code for [path] such that, if [equals] returns `true` for two +/// paths, their hash codes are the same. +/// +/// Note that the same path may have different hash codes on different platforms +/// or with different [current] directories. +int hash(String path) => context.hash(path); + +/// Removes a trailing extension from the last part of [path]. +/// +/// p.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' +String withoutExtension(String path) => context.withoutExtension(path); + +/// Returns [path] with the trailing extension set to [extension]. +/// +/// If [path] doesn't have a trailing extension, this just adds [extension] to +/// the end. +/// +/// p.setExtension('path/to/foo.dart', '.js') // -> 'path/to/foo.js' +/// p.setExtension('path/to/foo.dart.js', '.map') +/// // -> 'path/to/foo.dart.map' +/// p.setExtension('path/to/foo', '.js') // -> 'path/to/foo.js' +String setExtension(String path, String extension) => + context.setExtension(path, extension); + +/// Returns the path represented by [uri], which may be a [String] or a [Uri]. +/// +/// For POSIX and Windows styles, [uri] must be a `file:` URI. For the URL +/// style, this will just convert [uri] to a string. +/// +/// // POSIX +/// p.fromUri('file:///path/to/foo') // -> '/path/to/foo' +/// +/// // Windows +/// p.fromUri('file:///C:/path/to/foo') // -> r'C:\path\to\foo' +/// +/// // URL +/// p.fromUri('http://dartlang.org/path/to/foo') +/// // -> 'http://dartlang.org/path/to/foo' +/// +/// If [uri] is relative, a relative path will be returned. +/// +/// p.fromUri('path/to/foo'); // -> 'path/to/foo' +String fromUri(uri) => context.fromUri(uri); + +/// Returns the URI that represents [path]. +/// +/// For POSIX and Windows styles, this will return a `file:` URI. For the URL +/// style, this will just convert [path] to a [Uri]. +/// +/// // POSIX +/// p.toUri('/path/to/foo') +/// // -> Uri.parse('file:///path/to/foo') +/// +/// // Windows +/// p.toUri(r'C:\path\to\foo') +/// // -> Uri.parse('file:///C:/path/to/foo') +/// +/// // URL +/// p.toUri('http://dartlang.org/path/to/foo') +/// // -> Uri.parse('http://dartlang.org/path/to/foo') +/// +/// If [path] is relative, a relative URI will be returned. +/// +/// p.toUri('path/to/foo') // -> Uri.parse('path/to/foo') +Uri toUri(String path) => context.toUri(path); + +/// Returns a terse, human-readable representation of [uri]. +/// +/// [uri] can be a [String] or a [Uri]. If it can be made relative to the +/// current working directory, that's done. Otherwise, it's returned as-is. This +/// gracefully handles non-`file:` URIs for [Style.posix] and [Style.windows]. +/// +/// The returned value is meant for human consumption, and may be either URI- +/// or path-formatted. +/// +/// // POSIX at "/root/path" +/// p.prettyUri('file:///root/path/a/b.dart'); // -> 'a/b.dart' +/// p.prettyUri('http://dartlang.org/'); // -> 'http://dartlang.org' +/// +/// // Windows at "C:\root\path" +/// p.prettyUri('file:///C:/root/path/a/b.dart'); // -> r'a\b.dart' +/// p.prettyUri('http://dartlang.org/'); // -> 'http://dartlang.org' +/// +/// // URL at "http://dartlang.org/root/path" +/// p.prettyUri('http://dartlang.org/root/path/a/b.dart'); // -> r'a/b.dart' +/// p.prettyUri('file:///root/path'); // -> 'file:///root/path' +String prettyUri(uri) => context.prettyUri(uri); +NN<?CK#1Q".ONP)P6MI/;/P5/"476;-G@3GQ**0B"4OM>/%, !C)%?E+9;N M8+GJLG693%+8OD%E0,774%,L+1A%"6O/:558H.2:HN.0/6.9&<HJNLMIQP,:OJN:NIQP,2BO9N9N6JO>N>N;;BHP<8<OBH4=8MGK.KO @E:INBF:O2<>OP< PQPDL&/(Q==;OJHIQ*Q--?DHCO I6'D6+OK5>D52<6-,N5 1#43=<>/=JQON!DI%HI2QD1Rfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/file.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Core interfaces containing the abstract `FileSystem` interface definition +/// and all associated types used by `FileSystem`. +export 'src/forwarding.dart'; +export 'src/interface.dart'; + +NN<N3Tfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/mime-0.9.6+2/lib/mime.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Help for working with file format identifiers + * such as `text/html` and `image/png`. + * + * More details, including a list of types, are in the Wikipedia article + * [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). + * For information on installing and importing this library, see the + * [mime package on pub.dartlang.org] + * (http://pub.dartlang.org/packages/mime). + */ +library mime; + +export 'src/mime_multipart_transformer.dart'; +export 'src/mime_shared.dart'; +export 'src/mime_type.dart'; +NN<1(ILE&,.`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/combinator.dartBexport 'src/combinator/combinator.dart'; +export 'src/error.dart'; +)Tfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/tuple-1.0.2/lib/tuple.dart// Copyright (c) 2014, the tuple project authors. Please see the AUTHORS +// file for details. All rights reserved. Use of this source code is governed +// by a BSD-style license that can be found in the LICENSE file. + +/// # Tuple data structure +/// +/// - [Tuple2], [Tuple3]... +/// +/// ## Usage example +/// +/// ```dart +/// const t = const Tuple2('a', 10); +/// +/// print(t.item1); // prints 'a' +/// print(t.item2); // prints '10' +/// ``` +/// +/// ```dart +/// const t1 = const Tuple2('a', 10); +/// final t2 = t1.withItem1('c'); +/// // t2 is a new [Tuple2] object with item1 is 'c' and item2 is 10. +/// ``` +library tuple; + +import 'package:quiver/core.dart'; + +part 'package:tuple/src/tuple.dart'; +INA 2"# 3"F#%Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/tuple-1.0.2/lib/src/tuple.dart1// Copyright (c) 2014, the tuple project authors. Please see the AUTHORS +// file for details. All rights reserved. Use of this source code is governed +// by a BSD-style license that can be found in the LICENSE file. + +part of tuple; + +/// Represents a 2-tuple, or pair. +class Tuple2 { + /// Returns the first item of the tuple + final T1 item1; + + /// Returns the second item of the tuple + final T2 item2; + + /// Creates a new tuple value with the specified items. + const Tuple2(this.item1, this.item2); + + /// Create a new tuple value with the specified list [items]. + factory Tuple2.fromList(List items) { + if (items.length != 2) { + throw new ArgumentError('items must have length 2'); + } + + return new Tuple2(items[0] as T1, items[1] as T2); + } + + /// Returns a tuple with the first item set to the specified value. + Tuple2 withItem1(T1 v) { + return new Tuple2(v, item2); + } + + /// Returns a tuple with the second item set to the specified value. + Tuple2 withItem2(T2 v) { + return new Tuple2(item1, v); + } + + /// Creates a [List] containing the items of this [Tuple2]. + /// + /// The elements are in item order. The list is variable-length + /// if [growable] is true. + List toList({bool growable: false}) => + new List.from([item1, item2], growable: growable); + + @override + String toString() => '[$item1, $item2]'; + + @override + bool operator ==(o) => o is Tuple2 && o.item1 == item1 && o.item2 == item2; + + @override + int get hashCode => hash2(item1.hashCode, item2.hashCode); +} + +/// Represents a 3-tuple, or triple. +class Tuple3 { + /// Returns the first item of the tuple + final T1 item1; + + /// Returns the second item of the tuple + final T2 item2; + + /// Returns the third item of the tuple + final T3 item3; + + /// Creates a new tuple value with the specified items. + const Tuple3(this.item1, this.item2, this.item3); + + /// Create a new tuple value with the specified list [items]. + factory Tuple3.fromList(List items) { + if (items.length != 3) { + throw new ArgumentError('items must have length 3'); + } + + return new Tuple3( + items[0] as T1, items[1] as T2, items[2] as T3); + } + + /// Returns a tuple with the first item set to the specified value. + Tuple3 withItem1(T1 v) { + return new Tuple3(v, item2, item3); + } + + /// Returns a tuple with the second item set to the specified value. + Tuple3 withItem2(T2 v) { + return new Tuple3(item1, v, item3); + } + + /// Returns a tuple with the third item set to the specified value. + Tuple3 withItem3(T3 v) { + return new Tuple3(item1, item2, v); + } + + /// Creates a [List] containing the items of this [Tuple3]. + /// + /// The elements are in item order. The list is variable-length + /// if [growable] is true. + List toList({bool growable: false}) => + new List.from([item1, item2, item3], growable: growable); + + @override + String toString() => '[$item1, $item2, $item3]'; + + @override + bool operator ==(o) => + o is Tuple3 && o.item1 == item1 && o.item2 == item2 && o.item3 == item3; + + @override + int get hashCode => hash3(item1.hashCode, item2.hashCode, item3.hashCode); +} + +/// Represents a 4-tuple, or quadruple. +class Tuple4 { + /// Returns the first item of the tuple + final T1 item1; + + /// Returns the second item of the tuple + final T2 item2; + + /// Returns the third item of the tuple + final T3 item3; + + /// Returns the fourth item of the tuple + final T4 item4; + + /// Creates a new tuple value with the specified items. + const Tuple4(this.item1, this.item2, this.item3, this.item4); + + /// Create a new tuple value with the specified list [items]. + factory Tuple4.fromList(List items) { + if (items.length != 4) { + throw new ArgumentError('items must have length 4'); + } + + return new Tuple4( + items[0] as T1, items[1] as T2, items[2] as T3, items[3] as T4); + } + + /// Returns a tuple with the first item set to the specified value. + Tuple4 withItem1(T1 v) { + return new Tuple4(v, item2, item3, item4); + } + + /// Returns a tuple with the second item set to the specified value. + Tuple4 withItem2(T2 v) { + return new Tuple4(item1, v, item3, item4); + } + + /// Returns a tuple with the third item set to the specified value. + Tuple4 withItem3(T3 v) { + return new Tuple4(item1, item2, v, item4); + } + + /// Returns a tuple with the fourth item set to the specified value. + Tuple4 withItem4(T4 v) { + return new Tuple4(item1, item2, item3, v); + } + + /// Creates a [List] containing the items of this [Tuple4]. + /// + /// The elements are in item order. The list is variable-length + /// if [growable] is true. + List toList({bool growable: false}) => + new List.from([item1, item2, item3, item4], growable: growable); + + @override + String toString() => '[$item1, $item2, $item3, $item4]'; + + @override + bool operator ==(o) => + o is Tuple4 && + o.item1 == item1 && + o.item2 == item2 && + o.item3 == item3 && + o.item4 == item4; + + @override + int get hashCode => + hash4(item1.hashCode, item2.hashCode, item3.hashCode, item4.hashCode); +} + +/// Represents a 5-tuple, or quintuple. +class Tuple5 { + /// Returns the first item of the tuple + final T1 item1; + + /// Returns the second item of the tuple + final T2 item2; + + /// Returns the third item of the tuple + final T3 item3; + + /// Returns the fourth item of the tuple + final T4 item4; + + /// Returns the fifth item of the tuple + final T5 item5; + + /// Creates a new tuple value with the specified items. + const Tuple5(this.item1, this.item2, this.item3, this.item4, this.item5); + + /// Create a new tuple value with the specified list [items]. + factory Tuple5.fromList(List items) { + if (items.length != 5) { + throw new ArgumentError('items must have length 5'); + } + + return new Tuple5(items[0] as T1, items[1] as T2, + items[2] as T3, items[3] as T4, items[4] as T5); + } + + /// Returns a tuple with the first item set to the specified value. + Tuple5 withItem1(T1 v) { + return new Tuple5(v, item2, item3, item4, item5); + } + + /// Returns a tuple with the second item set to the specified value. + Tuple5 withItem2(T2 v) { + return new Tuple5(item1, v, item3, item4, item5); + } + + /// Returns a tuple with the third item set to the specified value. + Tuple5 withItem3(T3 v) { + return new Tuple5(item1, item2, v, item4, item5); + } + + /// Returns a tuple with the fourth item set to the specified value. + Tuple5 withItem4(T4 v) { + return new Tuple5(item1, item2, item3, v, item5); + } + + /// Returns a tuple with the fifth item set to the specified value. + Tuple5 withItem5(T5 v) { + return new Tuple5(item1, item2, item3, item4, v); + } + + /// Creates a [List] containing the items of this [Tuple5]. + /// + /// The elements are in item order. The list is variable-length + /// if [growable] is true. + List toList({bool growable: false}) => + new List.from([item1, item2, item3, item4, item5], growable: growable); + + @override + String toString() => '[$item1, $item2, $item3, $item4, $item5]'; + + @override + bool operator ==(o) => + o is Tuple5 && + o.item1 == item1 && + o.item2 == item2 && + o.item3 == item3 && + o.item4 == item4 && + o.item5 == item5; + + @override + int get hashCode => hashObjects([ + item1.hashCode, + item2.hashCode, + item3.hashCode, + item4.hashCode, + item5.hashCode + ]); +} + +/// Represents a 6-tuple, or sextuple. +class Tuple6 { + /// Returns the first item of the tuple + final T1 item1; + + /// Returns the second item of the tuple + final T2 item2; + + /// Returns the third item of the tuple + final T3 item3; + + /// Returns the fourth item of the tuple + final T4 item4; + + /// Returns the fifth item of the tuple + final T5 item5; + + /// Returns the sixth item of the tuple + final T6 item6; + + /// Creates a new tuple value with the specified items. + const Tuple6( + this.item1, this.item2, this.item3, this.item4, this.item5, this.item6); + + /// Create a new tuple value with the specified list [items]. + factory Tuple6.fromList(List items) { + if (items.length != 6) { + throw new ArgumentError('items must have length 6'); + } + + return new Tuple6(items[0] as T1, items[1] as T2, + items[2] as T3, items[3] as T4, items[4] as T5, items[5] as T6); + } + + /// Returns a tuple with the first item set to the specified value. + Tuple6 withItem1(T1 v) { + return new Tuple6( + v, item2, item3, item4, item5, item6); + } + + /// Returns a tuple with the second item set to the specified value. + Tuple6 withItem2(T2 v) { + return new Tuple6( + item1, v, item3, item4, item5, item6); + } + + /// Returns a tuple with the third item set to the specified value. + Tuple6 withItem3(T3 v) { + return new Tuple6( + item1, item2, v, item4, item5, item6); + } + + /// Returns a tuple with the fourth item set to the specified value. + Tuple6 withItem4(T4 v) { + return new Tuple6( + item1, item2, item3, v, item5, item6); + } + + /// Returns a tuple with the fifth item set to the specified value. + Tuple6 withItem5(T5 v) { + return new Tuple6( + item1, item2, item3, item4, v, item6); + } + + /// Returns a tuple with the sixth item set to the specified value. + Tuple6 withItem6(T6 v) { + return new Tuple6( + item1, item2, item3, item4, item5, v); + } + + /// Creates a [List] containing the items of this [Tuple5]. + /// + /// The elements are in item order. The list is variable-length + /// if [growable] is true. + List toList({bool growable: false}) => + new List.from([item1, item2, item3, item4, item5, item6], + growable: growable); + + @override + String toString() => '[$item1, $item2, $item3, $item4, $item5, $item6]'; + + @override + bool operator ==(o) => + o is Tuple6 && + o.item1 == item1 && + o.item2 == item2 && + o.item3 == item3 && + o.item4 == item4 && + o.item5 == item5 && + o.item6 == item6; + + @override + int get hashCode => hashObjects([ + item1.hashCode, + item2.hashCode, + item3.hashCode, + item4.hashCode, + item5.hashCode, + item6.hashCode + ]); +} + +/// Represents a 7-tuple, or septuple. +class Tuple7 { + /// Returns the first item of the tuple + final T1 item1; + + /// Returns the second item of the tuple + final T2 item2; + + /// Returns the third item of the tuple + final T3 item3; + + /// Returns the fourth item of the tuple + final T4 item4; + + /// Returns the fifth item of the tuple + final T5 item5; + + /// Returns the sixth item of the tuple + final T6 item6; + + /// Returns the seventh item of the tuple + final T7 item7; + + /// Creates a new tuple value with the specified items. + const Tuple7(this.item1, this.item2, this.item3, this.item4, this.item5, + this.item6, this.item7); + + /// Create a new tuple value with the specified list [items]. + factory Tuple7.fromList(List items) { + if (items.length != 7) { + throw new ArgumentError('items must have length 7'); + } + + return new Tuple7( + items[0] as T1, + items[1] as T2, + items[2] as T3, + items[3] as T4, + items[4] as T5, + items[5] as T6, + items[6] as T7); + } + + /// Returns a tuple with the first item set to the specified value. + Tuple7 withItem1(T1 v) { + return new Tuple7( + v, item2, item3, item4, item5, item6, item7); + } + + /// Returns a tuple with the second item set to the specified value. + Tuple7 withItem2(T2 v) { + return new Tuple7( + item1, v, item3, item4, item5, item6, item7); + } + + /// Returns a tuple with the third item set to the specified value. + Tuple7 withItem3(T3 v) { + return new Tuple7( + item1, item2, v, item4, item5, item6, item7); + } + + /// Returns a tuple with the fourth item set to the specified value. + Tuple7 withItem4(T4 v) { + return new Tuple7( + item1, item2, item3, v, item5, item6, item7); + } + + /// Returns a tuple with the fifth item set to the specified value. + Tuple7 withItem5(T5 v) { + return new Tuple7( + item1, item2, item3, item4, v, item6, item7); + } + + /// Returns a tuple with the sixth item set to the specified value. + Tuple7 withItem6(T6 v) { + return new Tuple7( + item1, item2, item3, item4, item5, v, item7); + } + + /// Returns a tuple with the seventh item set to the specified value. + Tuple7 withItem7(T7 v) { + return new Tuple7( + item1, item2, item3, item4, item5, item6, v); + } + + /// Creates a [List] containing the items of this [Tuple5]. + /// + /// The elements are in item order. The list is variable-length + /// if [growable] is true. + List toList({bool growable: false}) => + new List.from([item1, item2, item3, item4, item5, item6, item7], + growable: growable); + + @override + String toString() => + '[$item1, $item2, $item3, $item4, $item5, $item6, $item7]'; + + @override + bool operator ==(o) => + o is Tuple7 && + o.item1 == item1 && + o.item2 == item2 && + o.item3 == item3 && + o.item4 == item4 && + o.item5 == item5 && + o.item5 == item6 && + o.item6 == item7; + + @override + int get hashCode => hashObjects([ + item1.hashCode, + item2.hashCode, + item3.hashCode, + item4.hashCode, + item5.hashCode, + item6.hashCode, + item7.hashCode + ]); +} +INA#*+:(@(;?F#)G#)>B)9 + N =%*+*:4@(;#9F'4G'4F'4>B)@ 3 O M(*+*+:@@(;'IF+?G+?F+?G+?>B)G ;  M(#*+*+*:L@(;J9F/JG/JF/JG/JF/J>B)N C  $ +''*+*+**:O@(;NIF3//G3//F3//G3//F3//F3//>B)@ K  $ +'+*+*+**,:K@(;3F736G736F736G736F736F736H736>B)G B  $ +\file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/merge_map-1.0.1/lib/merge_map.dartn/// Exposes the [mergeMap] function, which... merges Maps. +library merge_map; + +_copyValues( + Map from, Map to, bool recursive, bool acceptNull) { + for (var key in from.keys) { + if (from[key] is Map && recursive) { + if (!(to[key] is Map)) { + to[key] = {} as V; + } + _copyValues(from[key] as Map, to[key] as Map, recursive, acceptNull); + } else { + if (from[key] != null || acceptNull) to[key] = from[key]; + } + } +} + +/// Merges the values of the given maps together. +/// +/// `recursive` is set to `true` by default. If set to `true`, +/// then nested maps will also be merged. Otherwise, nested maps +/// will overwrite others. +/// +/// `acceptNull` is set to `false` by default. If set to `false`, +/// then if the value on a map is `null`, it will be ignored, and +/// that `null` will not be copied. +Map mergeMap(Iterable> maps, + {bool recursive: true, bool acceptNull: false}) { + Map result = {}; + maps.forEach((Map map) { + if (map != null) _copyValues(map, result, recursive, acceptNull); + }); + return result; +} +$;E/%!L @2?ABB$36!Fefile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/dart2_constant-1.0.2+dart2/lib/convert.dart// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' as convert; + +const ascii = convert.ascii; +const base64 = convert.base64; +const base64Url = convert.base64Url; +const htmlEscape = convert.htmlEscape; + +abstract class HtmlEscapeMode { + static const unknown = convert.HtmlEscapeMode.unknown; + static const attribute = convert.HtmlEscapeMode.attribute; + static const sqAttribute = convert.HtmlEscapeMode.sqAttribute; + static const element = convert.HtmlEscapeMode.element; +} + +const json = convert.json; +const latin1 = convert.latin1; +const unicodeReplacementCharacterRune = convert.unicodeReplacementCharacterRune; +const unicodeBomCharacterRune = convert.unicodeBomCharacterRune; +const utf8 = convert.utf8; +NN<"%' 9=A9QAlfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/src/middleware_pipeline.dartimport 'router.dart'; + +/// A chain of arbitrary handlers obtained by routing a path. +class MiddlewarePipeline { + /// All the possible routes that matched the given path. + final Iterable> routingResults; + List _handlers; + + /// An ordered list of every handler delegated to handle this request. + List get handlers { + if (_handlers != null) return _handlers; + final handlers = []; + + for (var result in routingResults) { + handlers.addAll(result.allHandlers); + } + + return _handlers = handlers; + } + + MiddlewarePipeline(Iterable> routingResults) + : this.routingResults = routingResults.toList(); +} +>;3I-)+!@7_file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/src/router.dart!library angel_route.src.router; + +import 'package:combinator/combinator.dart'; +import 'package:meta/meta.dart'; +import 'package:string_scanner/string_scanner.dart'; + +import '../string_util.dart'; +import 'routing_exception.dart'; + +part 'grammar.dart'; + +part 'route.dart'; + +part 'routing_result.dart'; + +part 'symlink_route.dart'; + +//final RegExp _param = new RegExp(r':([A-Za-z0-9_]+)(\((.+)\))?'); +//final RegExp _rgxEnd = new RegExp(r'\$+$'); +//final RegExp _rgxStart = new RegExp(r'^\^+'); +//final RegExp _rgxStraySlashes = +// new RegExp(r'(^((\\+/)|(/))+)|(((\\+/)|(/))+$)'); +//final RegExp _slashDollar = new RegExp(r'/+\$'); +final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); + +/// An abstraction over complex [Route] trees. Use this instead of the raw API. :) +class Router { + final Map>> _cache = {}; + + //final List<_ChainedRouter> _chained = []; + final List _middleware = []; + final Map> _mounted = {}; + final List> _routes = []; + bool _useCache = false; + + List get middleware => new List.unmodifiable(_middleware); + + Map get mounted => + new Map.unmodifiable(_mounted); + + List> get routes { + return _routes.fold>>([], (out, route) { + if (route is SymlinkRoute) { + var childRoutes = + route.router.routes.fold>>([], (out, r) { + return out + ..add( + route.path.isEmpty ? r : new Route.join(route, r), + ); + }); + + return out..addAll(childRoutes); + } else { + return out..add(route); + } + }); + } + + /// Provide a `root` to make this Router revolve around a pre-defined route. + /// Not recommended. + Router(); + + /// Enables the use of a cache to eliminate the overhead of consecutive resolutions of the same path. + void enableCache() { + _useCache = true; + } + + /// Adds a route that responds to the given path + /// for requests with the given method (case-insensitive). + /// Provide '*' as the method to respond to all methods. + Route addRoute(String method, String path, T handler, + {Iterable middleware: const []}) { + if (_useCache == true) + throw new StateError('Cannot add routes after caching is enabled.'); + + // Check if any mounted routers can match this + final handlers = [handler]; + + if (middleware != null) handlers.insertAll(0, middleware); + + final route = new Route(path, method: method, handlers: handlers); + _routes.add(route); + return route; + } + + /// Prepends the given [middleware] to any routes created + /// by the resulting router. + /// + /// The resulting router can be chained, too. + _ChainedRouter chain(Iterable middleware) { + var piped = new _ChainedRouter(this, middleware); + var route = new SymlinkRoute('/', piped); + _routes.add(route); + return piped; + } + + /// Returns a [Router] with a duplicated version of this tree. + Router clone() { + final router = new Router(); + final newMounted = new Map>.from(mounted); + + for (var route in routes) { + if (route is! SymlinkRoute) { + router._routes.add(route.clone()); + } else if (route is SymlinkRoute) { + final newRouter = route.router.clone(); + newMounted[route.path] = newRouter; + final symlink = new SymlinkRoute(route.path, newRouter); + router._routes.add(symlink); + } + } + + return router.._mounted.addAll(newMounted); + } + + /// Creates a visual representation of the route hierarchy and + /// passes it to a callback. If none is provided, `print` is called. + void dumpTree( + {callback(String tree), + String header: 'Dumping route tree:', + String tab: ' '}) { + final buf = new StringBuffer(); + int tabs = 0; + + if (header != null && header.isNotEmpty) { + buf.writeln(header); + } + + buf.writeln(''); + + indent() { + for (int i = 0; i < tabs; i++) buf.write(tab); + } + + dumpRouter(Router router) { + indent(); + tabs++; + + for (Route route in router.routes) { + indent(); + buf.write('- '); + if (route is! SymlinkRoute) buf.write('${route.method} '); + buf.write('${route.path.isNotEmpty ? route.path : '/'}'); + + if (route is SymlinkRoute) { + buf.writeln(); + dumpRouter(route.router); + } else { + buf.writeln(' => ${route.handlers.length} handler(s)'); + } + } + + tabs--; + } + + dumpRouter(this); + + (callback ?? print)(buf.toString()); + } + + /// Creates a route, and allows you to add child routes to it + /// via a [Router] instance. + /// + /// Returns the created route. + /// You can also register middleware within the router. + SymlinkRoute group(String path, void callback(Router router), + {Iterable middleware: const [], String name: null}) { + final router = new Router().._middleware.addAll(middleware); + callback(router); + return mount(path, router)..name = name; + } + + /// Generates a URI string based on the given input. + /// Handy when you have named routes. + /// + /// Each item in `linkParams` should be a [Route], + /// `String` or `Map`. + /// + /// Strings should be route names, namespaces, or paths. + /// Maps should be parameters, which will be filled + /// into the previous route. + /// + /// Paths and segments should correspond to the way + /// you declared them. + /// + /// For example, if you declared a route group on + /// `'users/:id'`, it would not be resolved if you + /// passed `'users'` in [linkParams]. + /// + /// Leading and trailing slashes are automatically + /// removed. + /// + /// Set [absolute] to `true` to insert a forward slash + /// before the generated path. + /// + /// Example: + /// ```dart + /// router.navigate(['users/:id', {'id': '1337'}, 'profile']); + /// ``` + String navigate(Iterable linkParams, {bool absolute: true}) { + final List segments = []; + Router search = this; + Route lastRoute; + + for (final param in linkParams) { + bool resolved = false; + + if (param is String) { + // Search by name + for (Route route in search.routes) { + if (route.name == param) { + segments.add(route.path.replaceAll(_straySlashes, '')); + lastRoute = route; + + if (route is SymlinkRoute) { + search = route.router; + } + + resolved = true; + break; + } + } + + // Search by path + if (!resolved) { + var scanner = new SpanScanner(param.replaceAll(_straySlashes, '')); + for (Route route in search.routes) { + int pos = scanner.position; + if (route.parser.parse(scanner).successful && scanner.isDone) { + segments.add(route.path.replaceAll(_straySlashes, '')); + lastRoute = route; + + if (route is SymlinkRoute) { + search = route.router; + } + + resolved = true; + break; + } else + scanner.position = pos; + } + } + + if (!resolved) { + throw new RoutingException( + 'Cannot resolve route for link param "$param".'); + } + } else if (param is Route) { + segments.add(param.path.replaceAll(_straySlashes, '')); + } else if (param is Map) { + if (lastRoute == null) { + throw new RoutingException( + 'Maps in link params must be preceded by a Route or String.'); + } else { + segments.removeLast(); + segments.add(lastRoute.makeUri(param).replaceAll(_straySlashes, '')); + } + } else + throw new RoutingException( + 'Link param $param is not Route, String, or Map.'); + } + + return absolute + ? '/${segments.join('/').replaceAll(_straySlashes, '')}' + : segments.join('/'); + } + + /// Finds the first [Route] that matches the given path, + /// with the given method. + bool resolve(String absolute, String relative, List> out, + {String method: 'GET', bool strip: true}) { + final cleanRelative = + strip == false ? relative : stripStraySlashes(relative); + var scanner = new SpanScanner(cleanRelative); + + bool crawl(Router r) { + bool success = false; + + for (var route in r.routes) { + int pos = scanner.position; + + if (route is SymlinkRoute) { + if (route.parser.parse(scanner).successful) { + var s = crawl(route.router); + if (s) success = true; + } + + scanner.position = pos; + } else if (route.method == '*' || route.method == method) { + var parseResult = route.parser.parse(scanner); + + if (parseResult.successful && scanner.isDone) { + var result = new RoutingResult( + parseResult: parseResult, + params: parseResult.value, + shallowRoute: route, + shallowRouter: this); + out.add(result); + success = true; + } + + scanner.position = pos; + } + } + + return success; + } + + return crawl(this); + } + + /// Returns the result of [resolve] with [path] passed as + /// both `absolute` and `relative`. + Iterable> resolveAbsolute(String path, + {String method: 'GET', bool strip: true}) => + resolveAll(path, path, method: method, strip: strip); + + /// Finds every possible [Route] that matches the given path, + /// with the given method. + Iterable> resolveAll(String absolute, String relative, + {String method: 'GET', bool strip: true}) { + if (_useCache == true) { + return _cache.putIfAbsent('$method$absolute', + () => _resolveAll(absolute, relative, method: method, strip: strip)); + } + + return _resolveAll(absolute, relative, method: method, strip: strip); + } + + Iterable> _resolveAll(String absolute, String relative, + {String method: 'GET', bool strip: true}) { + var results = >[]; + resolve(absolute, relative, results, method: method, strip: strip); + + // _printDebug( + // 'Results of $method "/${absolute.replaceAll(_straySlashes, '')}": ${results.map((r) => r.route).toList()}'); + return results; + } + + /// Incorporates another [Router]'s routes into this one's. + SymlinkRoute mount(String path, Router router) { + final route = new SymlinkRoute(path, router); + _mounted[route.path] = router; + _routes.add(route); + //route._head = new RegExp(route.matcher.pattern.replaceAll(_rgxEnd, '')); + + return route; + } + + /// Adds a route that responds to any request matching the given path. + Route all(String path, T handler, {Iterable middleware}) { + return addRoute('*', path, handler, middleware: middleware); + } + + /// Adds a route that responds to a DELETE request. + Route delete(String path, T handler, {Iterable middleware}) { + return addRoute('DELETE', path, handler, middleware: middleware); + } + + /// Adds a route that responds to a GET request. + Route get(String path, T handler, {Iterable middleware}) { + return addRoute('GET', path, handler, middleware: middleware); + } + + /// Adds a route that responds to a HEAD request. + Route head(String path, T handler, {Iterable middleware}) { + return addRoute('HEAD', path, handler, middleware: middleware); + } + + /// Adds a route that responds to a OPTIONS request. + Route options(String path, T handler, {Iterable middleware}) { + return addRoute('OPTIONS', path, handler, middleware: middleware); + } + + /// Adds a route that responds to a POST request. + Route post(String path, T handler, {Iterable middleware}) { + return addRoute('POST', path, handler, middleware: middleware); + } + + /// Adds a route that responds to a PATCH request. + Route patch(String path, T handler, {Iterable middleware}) { + return addRoute('PATCH', path, handler, middleware: middleware); + } + + /// Adds a route that responds to a PUT request. + Route put(String path, T handler, {Iterable middleware}) { + return addRoute('PUT', path, handler, middleware: middleware); + } +} + +class _ChainedRouter extends Router { + final List _handlers = []; + Router _root; + + _ChainedRouter.empty(); + + _ChainedRouter(Router root, Iterable middleware) { + this._root = root; + _handlers.addAll(middleware); + } + + @override + Route addRoute(String method, String path, handler, + {Iterable middleware: const []}) { + var route = super.addRoute(method, path, handler, + middleware: []..addAll(_handlers)..addAll(middleware ?? [])); + //_root._routes.add(route); + return route; + } + + SymlinkRoute group(String path, void callback(Router router), + {Iterable middleware: const [], String name: null}) { + final router = + new _ChainedRouter(_root, []..addAll(_handlers)..addAll(middleware)); + callback(router); + return mount(path, router)..name = name; + } + + @override + SymlinkRoute mount(String path, Router router) { + final route = super.mount(path, router); + route.router._middleware.insertAll(0, _handlers); + //_root._routes.add(route); + return route; + } + + @override + _ChainedRouter chain(Iterable middleware) { + final piped = new _ChainedRouter.empty().._root = _root; + piped._handlers.addAll([]..addAll(_handlers)..addAll(middleware)); + var route = new SymlinkRoute('/', piped); + _routes.add(route); + return piped; + } +} + +/// Optimizes a router by condensing all its routes into one level. +Router flatten(Router router) { + var flattened = new Router(); + + for (var route in router.routes) { + if (route is SymlinkRoute) { + var base = route.path.replaceAll(_straySlashes, ''); + var child = flatten(route.router); + + for (var route in child.routes) { + var path = route.path.replaceAll(_straySlashes, ''); + var joined = '$base/$path'.replaceAll(_straySlashes, ''); + flattened.addRoute(route.method, joined.replaceAll(_straySlashes, ''), + route.handlers.last, + middleware: + route.handlers.take(route.handlers.length - 1).toList()); + } + } else { + flattened.addRoute(route.method, route.path, route.handlers.last, + middleware: route.handlers.take(route.handlers.length - 1).toList()); + } + } + + return flattened..enableCache(); +} + -!5!D.0"839S=."/%C&7;&DA ) O h3=;;,K3#?J<0491A$B '+-0,D%0AG,$/5 +CB($B +)@!:C?D-7(5*;6645(59!A +@&&-%D,% +N/(LF!.'& +&@ +#@2!&M!P + $QA;M2A2$$(8)# "D9:/*+%& " +<&:7<@J24PJK2(Hw>95#OICA6FF3CC4DD7GG4DD5EE3@C,#8" 9,6F F?Q- 9-6  4@G1D)#%$;)(=BO!J HP#`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/src/grammar.dartpart of angel_route.src.router; + +class RouteGrammar { + static final RegExp rgx = new RegExp(r'\((.+)\)'); + static final Parser notSlash = + match(new RegExp(r'[^/]+')).value((r) => r.span.text); + + static final Parser regExp = match(new RegExp(r'\((.+)\)')) + .value((r) => new RegExp(r.scanner.lastMatch[1])); + + static final Parser parameterName = + match(new RegExp(r':([A-Za-z0-9_]+)')) + .value((r) => r.span.text.substring(1)); + + static final Parser parameterSegment = chain([ + parameterName, + match('?').value((r) => true).opt(), + regExp.opt(), + ]).map((r) { + var s = new ParameterSegment(r.value[0] as String, r.value[2] as RegExp); + return r.value[1] == true ? new OptionalSegment(s) : s; + }); + + static final Parser parsedParameterSegment = chain([ + match(new RegExp(r'(int|num|double)'), + errorMessage: 'Expected "int","double", or "num".') + .map((r) => r.span.text), + parameterSegment, + ]).map((r) { + return new ParsedParameterSegment( + r.value[0] as String, r.value[1] as ParameterSegment); + }); + + static final Parser wildcardSegment = + match('*').value((r) => new WildcardSegment()); + + static final Parser constantSegment = + notSlash.map((r) => new ConstantSegment(r.value)); + + static final Parser routeSegment = any([ + parsedParameterSegment, + parameterSegment, + wildcardSegment, + constantSegment + ]); + + static final Parser routeDefinition = routeSegment + .separatedBy(match('/')) + .map((r) => new RouteDefinition(r.value ?? [])) + .surroundedBy(match('/').star().opt()); +} + +class RouteDefinition { + final List segments; + + RouteDefinition(this.segments); + + Parser> compile() { + Parser> out; + + for (int i = 0; i < segments.length; i++) { + var s = segments[i]; + bool isLast = i == segments.length - 1; + if (out == null) + out = s.compile(isLast); + else + out = s.compileNext( + out.then(match('/')).index(0).cast>(), isLast); + } + + return out; + } +} + +abstract class RouteSegment { + Parser> compile(bool isLast); + + Parser> compileNext( + Parser> p, bool isLast); +} + +class ConstantSegment extends RouteSegment { + final String text; + + ConstantSegment(this.text); + + @override + String toString() { + return 'Constant: $text'; + } + + @override + Parser> compile(bool isLast) { + return match>(text).value((r) => {}); + } + + @override + Parser> compileNext( + Parser> p, bool isLast) { + return p.then(compile(isLast)).index(0).cast>(); + } +} + +class WildcardSegment extends RouteSegment { + @override + String toString() { + return 'Wildcard segment'; + } + + Parser> _compile(bool isLast) { + if (isLast) return match(new RegExp(r'.*')); + return match(new RegExp(r'[^/]*')); + } + + @override + Parser> compile(bool isLast) { + return _compile(isLast).map((r) => {}); + } + + @override + Parser> compileNext( + Parser> p, bool isLast) { + return p.then(_compile(isLast)).index(0).cast>(); + } +} + +class OptionalSegment extends ParameterSegment { + final ParameterSegment parameter; + + OptionalSegment(this.parameter) : super(parameter.name, parameter.regExp); + + @override + String toString() { + return 'Optional: $parameter'; + } + + @override + Parser> compile(bool isLast) { + return super.compile(isLast).opt(); + } + + @override + Parser> compileNext( + Parser> p, bool isLast) { + return p.then(_compile().opt()).map((r) { + if (r.value[1] == null) return r.value[0] as Map; + return (r.value[0] as Map) + ..addAll({name: Uri.decodeComponent(r.value[1] as String)}); + }); + } +} + +class ParameterSegment extends RouteSegment { + final String name; + final RegExp regExp; + + ParameterSegment(this.name, this.regExp); + + @override + String toString() { + if (regExp != null) return 'Param: $name (${regExp.pattern})'; + return 'Param: $name'; + } + + Parser _compile() { + return regExp != null + ? match(regExp).value((r) => r.span.text) + : RouteGrammar.notSlash; + } + + @override + Parser> compile(bool isLast) { + return _compile().map>( + (r) => {name: Uri.decodeComponent(r.span.text)}); + } + + @override + Parser> compileNext( + Parser> p, bool isLast) { + return p.then(_compile()).map((r) { + return (r.value[0] as Map) + ..addAll({name: Uri.decodeComponent(r.value[1] as String)}); + }); + } +} + +class ParsedParameterSegment extends RouteSegment { + final String type; + final ParameterSegment parameter; + + ParsedParameterSegment(this.type, this.parameter); + + num getValue(String s) { + switch (type) { + case 'int': + return int.parse(s); + case 'double': + return double.parse(s); + default: + return num.parse(s); + } + } + + @override + Parser> compile(bool isLast) { + return parameter._compile().map( + (r) => {parameter.name: getValue(Uri.decodeComponent(r.span.text))}); + } + + @override + Parser> compileNext( + Parser> p, bool isLast) { + return p.then(parameter._compile()).map((r) { + return (r.value[0] as Map) + ..addAll({ + parameter.name: getValue(Uri.decodeComponent(r.value[1] as String)) + }); + }); + } +} + 5)EN9.53C/N<O+@"'?9G9JGFG.%"+&0.! Q5,4-  6P ,5J- 71( 6, ,5K1$M # 6( ,5.I2E., C:! 61: ,5(2E4$5  6%N ,522N ^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/src/route.dartpart of angel_route.src.router; + +/// Represents a virtual location within an application. +class Route { + final String method; + final String path; + final List handlers; + final Map> _cache = {}; + final RouteDefinition _routeDefinition; + String name; + Parser> _parser; + + Route(this.path, {@required this.method, @required this.handlers}) + : _routeDefinition = RouteGrammar.routeDefinition + .parse(new SpanScanner(path.replaceAll(_straySlashes, ''))) + .value { + if (_routeDefinition?.segments?.isNotEmpty != true) + _parser = + match>('').value((r) => {}); + } + + factory Route.join(Route a, Route b) { + var start = a.path.replaceAll(_straySlashes, ''); + var end = b.path.replaceAll(_straySlashes, ''); + return new Route('$start/$end'.replaceAll(_straySlashes, ''), + method: b.method, handlers: b.handlers); + } + + Parser> get parser => + _parser ??= _routeDefinition.compile(); + + @override + String toString() { + return '$method $path => $handlers'; + } + + Route clone() { + return new Route(path, method: method, handlers: handlers) + .._cache.addAll(_cache); + } + + String makeUri(Map params) { + var b = new StringBuffer(); + int i = 0; + + for (var seg in _routeDefinition.segments) { + if (i++ > 0) b.write('/'); + if (seg is ConstantSegment) + b.write(seg.text); + else if (seg is ParameterSegment) { + if (!params.containsKey(seg.name)) + throw new ArgumentError('Missing parameter "${seg.name}".'); + b.write(params[seg.name]); + } + } + + return b.toString(); + } +} += 97*(E8H8M/64B1-. )B0 1!"*+G#gfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/src/routing_result.dartpart of angel_route.src.router; + +/// Represents a complex result of navigating to a path. +class RoutingResult { + /// The parse result that matched the given sub-path. + final ParseResult> parseResult; + + /// A nested instance, if a sub-path was matched. + final Iterable> nested; + + /// All route params matching this route on the current sub-path. + final Map params = {}; + + /// The [Route] that answered this sub-path. + /// + /// This is mostly for internal use, and useless in production. + final Route shallowRoute; + + /// The [Router] that answered this sub-path. + /// + /// Only really for internal use. + final Router shallowRouter; + + /// The remainder of the full path that was not matched, and was passed to [nested] routes. + final String tail; + + /// The [RoutingResult] that matched the most specific sub-path. + RoutingResult get deepest { + var search = this; + + while (search?.nested?.isNotEmpty == true) search = search.nested.first; + + return search; + } + + /// The most specific route. + Route get route => deepest.shallowRoute; + + /// The most specific router. + Router get router => deepest.shallowRouter; + + /// The handlers at this sub-path. + List get handlers { + return [] + ..addAll(shallowRouter.middleware) + ..addAll(shallowRoute.handlers); + } + + /// All handlers on this sub-path and its children. + List get allHandlers { + final handlers = []; + + void crawl(RoutingResult result) { + handlers.addAll(result.handlers); + + if (result.nested?.isNotEmpty == true) { + for (var r in result.nested) crawl(r); + } + } + + crawl(this); + + return handlers; + } + + /// All parameters on this sub-path and its children. + Map get allParams { + final Map params = {}; + + void crawl(RoutingResult result) { + params.addAll(result.params); + + if (result.nested?.isNotEmpty == true) { + for (var r in result.nested) crawl(r); + } + } + + crawl(this); + return params; + } + + RoutingResult( + {this.parseResult, + Map params: const {}, + this.nested, + this.shallowRoute, + this.shallowRouter, + this.tail}) { + this.params.addAll(params ?? {}); + } +} +] 9874+D*/B0$!^C!M. 1%)'6*(//8','$//-&ffile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/src/symlink_route.dartpart of angel_route.src.router; + +/// Placeholder [Route] to serve as a symbolic link +/// to a mounted [Router]. +class SymlinkRoute extends Route { + final Router router; + SymlinkRoute(String path, this.router) + : super(path, method: null, handlers: null); +} + 4))3jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/src/routing_exception.dart-/// Represents an error in route configuration or navigation. +abstract class RoutingException extends Exception { + factory RoutingException(String message) => + new _RoutingExceptionImpl(message); + + /// Occurs when trying to resolve the parent of a [Route] without a parent. + factory RoutingException.orphan() => new _RoutingExceptionImpl( + "Tried to resolve path '..' on a route that has no parent."); + + /// Occurs when the user attempts to navigate to a non-existent route. + factory RoutingException.noSuchRoute(String path) => + new _RoutingExceptionImpl( + "Tried to navigate to non-existent route: '$path'."); +} + +class _RoutingExceptionImpl implements RoutingException { + final String message; + + _RoutingExceptionImpl(this.message); + + @override + String toString() => message; +} +>4.*NBDI7!@:' jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/body_parser-1.1.1/lib/src/body_parse_result.dart +import 'file_upload_info.dart'; + +/// A representation of data from an incoming request. +abstract class BodyParseResult { + /// The parsed body. + Map get body; + + /// The parsed query string. + Map get query; + + /// All files uploaded within this request. + List get files; + + /// The original body bytes sent with this request. + /// + /// You must set [storeOriginalBuffer] to `true` to see this. + List get originalBuffer; + + /// If an error was encountered while parsing the body, it will appear here. + /// + /// Otherwise, this is `null`. + dynamic get error; + + /// If an error was encountered while parsing the body, the call stack will appear here. + /// + /// Otherwise, this is `null`. + StackTrace get stack; +} + 7!!"."6@ O![!ifile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/body_parser-1.1.1/lib/src/file_upload_info.dart/// Represents a file uploaded to the server. +class FileUploadInfo { + /// The MIME type of the uploaded file. + String mimeType; + + /// The name of the file field from the request. + String name; + + /// The filename of the file. + String filename; + + /// The bytes that make up this file. + List data; + + FileUploadInfo( + {this.mimeType, this.name, this.filename, this.data: const []}) {} +} +.*3 (Icfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/body_parser-1.1.1/lib/src/parse_body.dartQimport 'dart:async'; +import 'dart:io'; + +import 'package:dart2_constant/convert.dart'; +import 'package:http_parser/http_parser.dart'; +import 'package:http_server/http_server.dart'; +import 'package:mime/mime.dart'; + +import 'body_parse_result.dart'; +import 'file_upload_info.dart'; +import 'map_from_uri.dart'; + +/// Forwards to [parseBodyFromStream]. +@deprecated +Future parseBody(HttpRequest request, + {bool storeOriginalBuffer: false}) { + return parseBodyFromStream( + request, + request.headers.contentType != null + ? new MediaType.parse(request.headers.contentType.toString()) + : null, + request.uri, + storeOriginalBuffer: storeOriginalBuffer); +} + +/// Grabs data from an incoming request. +/// +/// Supports URL-encoded and JSON, as well as multipart/* forms. +/// On a file upload request, only fields with the name **'file'** are processed +/// as files. Anything else is put in the body. You can change the upload file name +/// via the *fileUploadName* parameter. :) +/// +/// Use [storeOriginalBuffer] to add the original request bytes to the result. +Future parseBodyFromStream( + Stream> data, MediaType contentType, Uri requestUri, + {bool storeOriginalBuffer: false}) async { + var result = new _BodyParseResultImpl(); + + Future> getBytes() { + return data + .fold(new BytesBuilder(copy: false), (a, b) => a..add(b)) + .then((b) => b.takeBytes()); + } + + Future getBody() { + if (storeOriginalBuffer) { + return getBytes().then((bytes) { + result.originalBuffer = bytes; + return utf8.decode(bytes); + }); + } else + return data.transform(utf8.decoder).join(); + } + + try { + if (contentType != null) { + if (contentType.type == 'multipart' && + contentType.parameters.containsKey('boundary')) { + Stream> stream; + + if (storeOriginalBuffer) { + var bytes = result.originalBuffer = await getBytes(); + var ctrl = new StreamController>() + ..add(bytes) + ..close(); + stream = ctrl.stream; + } else { + stream = data; + } + + var parts = stream + .transform(new MimeMultipartTransformer( + contentType.parameters['boundary'])) + .map((part) => + HttpMultipartFormData.parse(part, defaultEncoding: utf8)); + + await for (HttpMultipartFormData part in parts) { + if (part.isBinary || + part.contentDisposition.parameters.containsKey("filename")) { + BytesBuilder builder = await part.fold( + new BytesBuilder(copy: false), + (BytesBuilder b, d) => b + ..add(d is! String + ? (d as List) + : (d as String).codeUnits)); + var upload = new FileUploadInfo( + mimeType: part.contentType.mimeType, + name: part.contentDisposition.parameters['name'], + filename: + part.contentDisposition.parameters['filename'] ?? 'file', + data: builder.takeBytes()); + result.files.add(upload); + } else if (part.isText) { + var text = await part.join(); + buildMapFromUri(result.body, + '${part.contentDisposition.parameters["name"]}=$text'); + } + } + } else if (contentType.mimeType == 'application/json') { + result.body + .addAll(_foldToStringDynamic(json.decode(await getBody()) as Map)); + } else if (contentType.mimeType == 'application/x-www-form-urlencoded') { + String body = await getBody(); + buildMapFromUri(result.body, body); + } else if (storeOriginalBuffer == true) { + result.originalBuffer = await getBytes(); + } + } else { + if (requestUri.hasQuery) { + buildMapFromUri(result.query, requestUri.query); + } + + if (storeOriginalBuffer == true) { + result.originalBuffer = await getBytes(); + } + } + } catch (e, st) { + result.error = e; + result.stack = st; + } + + return result; +} + +class _BodyParseResultImpl implements BodyParseResult { + @override + Map body = {}; + + @override + List files = []; + + @override + List originalBuffer; + + @override + Map query = {}; + + @override + var error = null; + + @override + StackTrace stack = null; +} + +Map _foldToStringDynamic(Map map) { + return map == null + ? null + : map.keys.fold>( + {}, (out, k) => out..[k.toString()] = map[k]); +} +.//!! ' 7)*H1)AQT+P-C/+!P%''# + 2-<"#@7  +55K:L4/)%)3-5BN,&$*)H +?PP',02 !9)28 " #  #  5 -J`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/stack_trace.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Stack trace generation and parsing. + * + * ## Installing ## + * + * Use [pub][] to install this package. Add the following to your `pubspec.yaml` + * file. + * + * dependencies: + * stack_trace: any + * + * Then run `pub install`. + * + * For more information, see the + * [stack_trace package on pub.dartlang.org][pkg]. + * + * [pub]: http://pub.dartlang.org + * [pkg]: http://pub.dartlang.org/packages/stack_trace + */ +export 'src/chain.dart'; +export 'src/frame.dart'; +export 'src/trace.dart'; +export 'src/unparsed_frame.dart'; +NN<'Q !3"7"\file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/src/arg_parser.dartf// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'allow_anything_parser.dart'; +import 'arg_results.dart'; +import 'option.dart'; +import 'parser.dart'; +import 'usage.dart'; + +/// A class for taking a list of raw command line arguments and parsing out +/// options and flags from them. +class ArgParser { + final Map _options; + final Map _commands; + + /// The options that have been defined for this parser. + final Map options; + + /// The commands that have been defined for this parser. + final Map commands; + + /// A list of the [Option]s in [options] intermingled with [String] + /// separators. + final _optionsAndSeparators = []; + + /// Whether or not this parser parses options that appear after non-option + /// arguments. + final bool allowTrailingOptions; + + /// An optional maximum line length for [usage] messages. + /// + /// If specified, then help messages in the usage are wrapped at the given + /// column, after taking into account the width of the options. Will refuse to + /// wrap help text to less than 10 characters of help text per line if there + /// isn't enough space on the line. It preserves embedded newlines, and + /// attempts to wrap at whitespace breaks (although it will split words if + /// there is no whitespace at which to split). + /// + /// If null (the default), help messages are not wrapped. + final int usageLineLength; + + /// Whether or not this parser treats unrecognized options as non-option + /// arguments. + bool get allowsAnything => false; + + /// Creates a new ArgParser. + /// + /// If [allowTrailingOptions] is `true` (the default), the parser will parse + /// flags and options that appear after positional arguments. If it's `false`, + /// the parser stops parsing as soon as it finds an argument that is neither + /// an option nor a command. + factory ArgParser({bool allowTrailingOptions: true, int usageLineLength}) => + new ArgParser._({}, {}, + allowTrailingOptions: allowTrailingOptions, + usageLineLength: usageLineLength); + + /// Creates a new ArgParser that treats *all input* as non-option arguments. + /// + /// This is intended to allow arguments to be passed through to child + /// processes without needing to be redefined in the parent. + /// + /// Options may not be defined for this parser. + factory ArgParser.allowAnything() = AllowAnythingParser; + + ArgParser._(Map options, Map commands, + {bool allowTrailingOptions: true, this.usageLineLength}) + : this._options = options, + this.options = new UnmodifiableMapView(options), + this._commands = commands, + this.commands = new UnmodifiableMapView(commands), + this.allowTrailingOptions = + allowTrailingOptions != null ? allowTrailingOptions : false; + + /// Defines a command. + /// + /// A command is a named argument which may in turn define its own options and + /// subcommands using the given parser. If [parser] is omitted, implicitly + /// creates a new one. Returns the parser for the command. + ArgParser addCommand(String name, [ArgParser parser]) { + // Make sure the name isn't in use. + if (_commands.containsKey(name)) { + throw new ArgumentError('Duplicate command "$name".'); + } + + if (parser == null) parser = new ArgParser(); + _commands[name] = parser; + return parser; + } + + /// Defines a boolean flag. + /// + /// This adds an [Option] with the given properties to [options]. + /// + /// The [abbr] argument is a single-character string that can be used as a + /// shorthand for this flag. For example, `abbr: "a"` will allow the user to + /// pass `-a` to enable the flag. + /// + /// The [help] argument is used by [usage] to describe this flag. + /// + /// The [defaultsTo] argument indicates the value this flag will have if the + /// user doesn't explicitly pass it in. + /// + /// The [negatable] argument indicates whether this flag's value can be set to + /// `false`. For example, if [name] is `flag`, the user can pass `--no-flag` + /// to set its value to `false`. + /// + /// The [callback] argument is invoked with the flag's value when the flag + /// is parsed. Note that this makes argument parsing order-dependent in ways + /// that are often surprising, and its use is discouraged in favor of reading + /// values from the [ArgResult]. + /// + /// If [hide] is `true`, this option won't be included in [usage]. + /// + /// Throws an [ArgumentError] if: + /// + /// * There is already an option named [name]. + /// * There is already an option using abbreviation [abbr]. + void addFlag(String name, + {String abbr, + String help, + bool defaultsTo: false, + bool negatable: true, + void callback(bool value), + bool hide: false}) { + _addOption( + name, + abbr, + help, + null, + null, + null, + defaultsTo, + callback == null ? null : (value) => callback(value as bool), + OptionType.flag, + negatable: negatable, + hide: hide); + } + + /// Defines an option that takes a value. + /// + /// This adds an [Option] with the given properties to [options]. + /// + /// The [abbr] argument is a single-character string that can be used as a + /// shorthand for this option. For example, `abbr: "a"` will allow the user to + /// pass `-a value` or `-avalue`. + /// + /// The [help] argument is used by [usage] to describe this option. + /// + /// The [valueHelp] argument is used by [usage] as a name for the value this + /// option takes. For example, `valueHelp: "FOO"` will include + /// `--option=` rather than just `--option` in the usage string. + /// + /// The [allowed] argument is a list of valid values for this option. If + /// it's non-`null` and the user passes a value that's not included in the + /// list, [parse] will throw a [FormatException]. The allowed values will also + /// be included in [usage]. + /// + /// The [allowedHelp] argument is a map from values in [allowed] to + /// documentation for those values that will be included in [usage]. + /// + /// The [defaultsTo] argument indicates the value this option will have if the + /// user doesn't explicitly pass it in (or `null` by default). + /// + /// The [callback] argument is invoked with the option's value when the option + /// is parsed. Note that this makes argument parsing order-dependent in ways + /// that are often surprising, and its use is discouraged in favor of reading + /// values from the [ArgResult]. + /// + /// The [allowMultiple] and [splitCommas] options are deprecated; the + /// [addMultiOption] method should be used instead. + /// + /// If [hide] is `true`, this option won't be included in [usage]. + /// + /// Throws an [ArgumentError] if: + /// + /// * There is already an option with name [name]. + /// * There is already an option using abbreviation [abbr]. + /// * [splitCommas] is passed but [allowMultiple] is `false`. + void addOption(String name, + {String abbr, + String help, + String valueHelp, + Iterable allowed, + Map allowedHelp, + String defaultsTo, + Function callback, + @Deprecated("Use addMultiOption() instead.") bool allowMultiple: false, + @Deprecated("Use addMultiOption() instead.") bool splitCommas, + bool hide: false}) { + if (!allowMultiple && splitCommas != null) { + throw new ArgumentError( + 'splitCommas may not be set if allowMultiple is false.'); + } + + _addOption( + name, + abbr, + help, + valueHelp, + allowed, + allowedHelp, + allowMultiple + ? (defaultsTo == null ? [] : [defaultsTo]) + : defaultsTo, + callback, + allowMultiple ? OptionType.multiple : OptionType.single, + splitCommas: splitCommas, + hide: hide); + } + + /// Defines an option that takes multiple values. + /// + /// The [abbr] argument is a single-character string that can be used as a + /// shorthand for this option. For example, `abbr: "a"` will allow the user to + /// pass `-a value` or `-avalue`. + /// + /// The [help] argument is used by [usage] to describe this option. + /// + /// The [valueHelp] argument is used by [usage] as a name for the value this + /// argument takes. For example, `valueHelp: "FOO"` will include + /// `--option=` rather than just `--option` in the usage string. + /// + /// The [allowed] argument is a list of valid values for this argument. If + /// it's non-`null` and the user passes a value that's not included in the + /// list, [parse] will throw a [FormatException]. The allowed values will also + /// be included in [usage]. + /// + /// The [allowedHelp] argument is a map from values in [allowed] to + /// documentation for those values that will be included in [usage]. + /// + /// The [defaultsTo] argument indicates the values this option will have if + /// the user doesn't explicitly pass it in (or `[]` by default). + /// + /// The [callback] argument is invoked with the option's value when the option + /// is parsed. Note that this makes argument parsing order-dependent in ways + /// that are often surprising, and its use is discouraged in favor of reading + /// values from the [ArgResult]. + /// + /// If [splitCommas] is `true` (the default), multiple options may be passed + /// by writing `--option a,b` in addition to `--option a --option b`. + /// + /// If [hide] is `true`, this option won't be included in [usage]. + /// + /// Throws an [ArgumentError] if: + /// + /// * There is already an option with name [name]. + /// * There is already an option using abbreviation [abbr]. + void addMultiOption(String name, + {String abbr, + String help, + String valueHelp, + Iterable allowed, + Map allowedHelp, + Iterable defaultsTo, + void callback(List values), + bool splitCommas: true, + bool hide: false}) { + _addOption( + name, + abbr, + help, + valueHelp, + allowed, + allowedHelp, + defaultsTo?.toList() ?? [], + callback == null ? null : (value) => callback(value as List), + OptionType.multiple, + splitCommas: splitCommas, + hide: hide); + } + + void _addOption( + String name, + String abbr, + String help, + String valueHelp, + Iterable allowed, + Map allowedHelp, + defaultsTo, + Function callback, + OptionType type, + {bool negatable: false, + bool splitCommas, + bool hide: false}) { + // Make sure the name isn't in use. + if (_options.containsKey(name)) { + throw new ArgumentError('Duplicate option "$name".'); + } + + // Make sure the abbreviation isn't too long or in use. + if (abbr != null) { + var existing = findByAbbreviation(abbr); + if (existing != null) { + throw new ArgumentError( + 'Abbreviation "$abbr" is already used by "${existing.name}".'); + } + } + + var option = newOption(name, abbr, help, valueHelp, allowed, allowedHelp, + defaultsTo, callback, type, + negatable: negatable, splitCommas: splitCommas, hide: hide); + _options[name] = option; + _optionsAndSeparators.add(option); + } + + /// Adds a separator line to the usage. + /// + /// In the usage text for the parser, this will appear between any options + /// added before this call and ones added after it. + void addSeparator(String text) { + _optionsAndSeparators.add(text); + } + + /// Parses [args], a list of command-line arguments, matches them against the + /// flags and options defined by this parser, and returns the result. + ArgResults parse(Iterable args) => + new Parser(null, this, args.toList()).parse(); + + /// Generates a string displaying usage information for the defined options. + /// + /// This is basically the help text shown on the command line. + @Deprecated("Replaced with get usage. getUsage() will be removed in args 1.0") + String getUsage() => usage; + + /// Generates a string displaying usage information for the defined options. + /// + /// This is basically the help text shown on the command line. + String get usage { + return new Usage(_optionsAndSeparators, lineLength: usageLineLength) + .generate(); + } + + /// Get the default value for an option. Useful after parsing to test if the + /// user specified something other than the default. + getDefault(String option) { + if (!options.containsKey(option)) { + throw new ArgumentError('No option named $option'); + } + return options[option].defaultsTo; + } + + /// Finds the option whose abbreviation is [abbr], or `null` if no option has + /// that abbreviation. + Option findByAbbreviation(String abbr) { + return options.values + .firstWhere((option) => option.abbr == abbr, orElse: () => null); + } +} +aNN<%L!&*:%;)F$M#<MQOJM1<K$OQOOA6-OH?2;L?!9#;$IQM=:('=2DMO$DO*QO#MOP#E$1>!F,DMQ$FOAHKMQFGQAQOP#H6E$5>@ 'NE1D?A"4MQ$FOCHMMQFGNCQOP#OHE$5># '#*,N" '(&<</!LN$E'*M6#%PH-5OAQOAIO7(:'P+Jffile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/src/arg_parser_exception.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// An exception thrown by `ArgParser`. +class ArgParserException extends FormatException { + /// The command(s) that were parsed before discovering the error. + /// + /// This will be empty if the error was on the root parser. + final List commands; + + ArgParserException(String message, [Iterable commands]) + : commands = + commands == null ? const [] : new List.unmodifiable(commands), + super(message); +} +NN<(3D>BK]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/src/arg_results.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'arg_parser.dart'; + +/// Creates a new [ArgResults]. +/// +/// Since [ArgResults] doesn't have a public constructor, this lets [ArgParser] +/// get to it. This function isn't exported to the public API of the package. +ArgResults newArgResults( + ArgParser parser, + Map parsed, + String name, + ArgResults command, + List rest, + List arguments) { + return new ArgResults._(parser, parsed, name, command, rest, arguments); +} + +/// The results of parsing a series of command line arguments using +/// [ArgParser.parse()]. +/// +/// Includes the parsed options and any remaining unparsed command line +/// arguments. +class ArgResults { + /// The [ArgParser] whose options were parsed for these results. + final ArgParser _parser; + + /// The option values that were parsed from arguments. + final Map _parsed; + + /// If these are the results for parsing a command's options, this will be the + /// name of the command. For top-level results, this returns `null`. + final String name; + + /// The command that was selected, or `null` if none was. + /// + /// This will contain the options that were selected for that command. + final ArgResults command; + + /// The remaining command-line arguments that were not parsed as options or + /// flags. + /// + /// If `--` was used to separate the options from the remaining arguments, + /// it will not be included in this list unless parsing stopped before the + /// `--` was reached. + final List rest; + + /// The original list of arguments that were parsed. + final List arguments; + + /// Creates a new [ArgResults]. + ArgResults._(this._parser, this._parsed, this.name, this.command, + List rest, List arguments) + : this.rest = new UnmodifiableListView(rest), + this.arguments = new UnmodifiableListView(arguments); + + /// Gets the parsed command-line option named [name]. + operator [](String name) { + if (!_parser.options.containsKey(name)) { + throw new ArgumentError('Could not find an option named "$name".'); + } + + return _parser.options[name].getOrDefault(_parsed[name]); + } + + /// Get the names of the available options as an [Iterable]. + /// + /// This includes the options whose values were parsed or that have defaults. + /// Options that weren't present and have no default will be omitted. + Iterable get options { + var result = new Set.from(_parsed.keys); + + // Include the options that have defaults. + _parser.options.forEach((name, option) { + if (option.defaultsTo != null) result.add(name); + }); + + return result; + } + + /// Returns `true` if the option with [name] was parsed from an actual + /// argument. + /// + /// Returns `false` if it wasn't provided and the default value or no default + /// value would be used instead. + bool wasParsed(String name) { + var option = _parser.options[name]; + if (option == null) { + throw new ArgumentError('Could not find an option named "$name".'); + } + + return _parsed.containsKey(name); + } +} +dNN< PN!KDHC9&QG<IN MM7 "D14>8.J>?PH!5/-7IP# (J&Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/src/option.dartO// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Creates a new [Option]. +/// +/// Since [Option] doesn't have a public constructor, this lets `ArgParser` +/// get to it. This function isn't exported to the public API of the package. +Option newOption( + String name, + String abbr, + String help, + String valueHelp, + Iterable allowed, + Map allowedHelp, + defaultsTo, + Function callback, + OptionType type, + {bool negatable, + bool splitCommas, + bool hide: false}) { + return new Option._(name, abbr, help, valueHelp, allowed, allowedHelp, + defaultsTo, callback, type, + negatable: negatable, splitCommas: splitCommas, hide: hide); +} + +/// A command-line option. +/// +/// This represents both boolean flags and options which take a value. +class Option { + /// The name of the option that the user passes as an argument. + final String name; + + /// A single-character string that can be used as a shorthand for this option. + /// + /// For example, `abbr: "a"` will allow the user to pass `-a value` or + /// `-avalue`. + final String abbr; + + @Deprecated("Use abbr instead.") + String get abbreviation => abbr; + + /// A description of this option. + final String help; + + /// A name for the value this option takes. + final String valueHelp; + + /// A list of valid values for this option. + final List allowed; + + /// A map from values in [allowed] to documentation for those values. + final Map allowedHelp; + + /// The value this option will have if the user doesn't explicitly pass it in + final defaultsTo; + + @Deprecated("Use defaultsTo instead.") + get defaultValue => defaultsTo; + + /// Whether this flag's value can be set to `false`. + /// + /// For example, if [name] is `flag`, the user can pass `--no-flag` to set its + /// value to `false`. + /// + /// This is `null` unless [type] is [OptionType.flag]. + final bool negatable; + + /// The callback to invoke with the option's value when the option is parsed. + final Function callback; + + /// Whether this is a flag, a single value option, or a multi-value option. + final OptionType type; + + /// Whether multiple values may be passed by writing `--option a,b` in + /// addition to `--option a --option b`. + final bool splitCommas; + + /// Whether this option should be hidden from usage documentation. + final bool hide; + + /// Whether the option is boolean-valued flag. + bool get isFlag => type == OptionType.flag; + + /// Whether the option takes a single value. + bool get isSingle => type == OptionType.single; + + /// Whether the option allows multiple values. + bool get isMultiple => type == OptionType.multiple; + + Option._( + this.name, + this.abbr, + this.help, + this.valueHelp, + Iterable allowed, + Map allowedHelp, + this.defaultsTo, + this.callback, + OptionType type, + {this.negatable, + bool splitCommas, + this.hide: false}) + : this.allowed = allowed == null ? null : new List.unmodifiable(allowed), + this.allowedHelp = + allowedHelp == null ? null : new Map.unmodifiable(allowedHelp), + this.type = type, + // If the user doesn't specify [splitCommas], it defaults to true for + // multiple options. + this.splitCommas = + splitCommas == null ? type == OptionType.multiple : splitCommas { + if (name.isEmpty) { + throw new ArgumentError('Name cannot be empty.'); + } else if (name.startsWith('-')) { + throw new ArgumentError('Name $name cannot start with "-".'); + } + + // Ensure name does not contain any invalid characters. + if (_invalidChars.hasMatch(name)) { + throw new ArgumentError('Name "$name" contains invalid characters.'); + } + + if (abbr != null) { + if (abbr.length != 1) { + throw new ArgumentError('Abbreviation must be null or have length 1.'); + } else if (abbr == '-') { + throw new ArgumentError('Abbreviation cannot be "-".'); + } + + if (_invalidChars.hasMatch(abbr)) { + throw new ArgumentError('Abbreviation is an invalid character.'); + } + } + } + + /// Returns [value] if non-`null`, otherwise returns the default value for + /// this option. + /// + /// For single-valued options, it will be [defaultsTo] if set or `null` + /// otherwise. For multiple-valued options, it will be an empty list or a + /// list containing [defaultsTo] if set. + dynamic getOrDefault(value) { + if (value != null) return value; + if (isMultiple) return defaultsTo ?? []; + return defaultsTo; + } + + static final _invalidChars = new RegExp(r'''[ \t\r\n"'\\/]'''); +} + +/// What kinds of values an option accepts. +class OptionType { + /// An option that can only be `true` or `false`. + /// + /// The presence of the option name itself in the argument list means `true`. + static const flag = const OptionType._("OptionType.flag"); + + @Deprecated("Use OptionType.flag instead.") + static const FLAG = flag; + + /// An option that takes a single value. + /// + /// Examples: + /// + /// --mode debug + /// -mdebug + /// --mode=debug + /// + /// If the option is passed more than once, the last one wins. + static const single = const OptionType._("OptionType.single"); + + @Deprecated("Use OptionType.single instead.") + static const SINGLE = single; + + /// An option that allows multiple values. + /// + /// Example: + /// + /// --output text --output xml + /// + /// In the parsed `ArgResults`, a multiple-valued option will always return + /// a list, even if one or no values were passed. + static const multiple = const OptionType._("OptionType.multiple"); + + @Deprecated("Use OptionType.multiple instead.") + static const MULTIPLE = multiple; + + final String name; + + const OptionType._(this.name); +} +NN<LN%I"CGBQI##$..H)P)"7Q9PNI+E1./216  'PLNN8'D<(LP @*JMJL+ %5B,4P=.+AA0 -%N4E2$!nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_container-1.0.0-alpha.9/lib/src/container.dartHimport 'exception.dart'; +import 'reflector.dart'; + +class Container { + final Reflector reflector; + final Map _singletons = {}; + final Map _factories = {}; + final Container _parent; + + Container(this.reflector) : _parent = null; + + Container._child(this._parent) : reflector = _parent.reflector; + + bool get isRoot => _parent == null; + + /// Creates a child [Container] that can define its own singletons and factories. + /// + /// Use this to create children of a global "scope." + Container createChild() { + return new Container._child(this); + } + + bool has([Type t]) { + var search = this; + t ??= T == dynamic ? t : T; + + while (search != null) { + if (search._singletons.containsKey(t)) { + return true; + } else if (search._factories.containsKey(t)) { + return true; + } else { + search = search._parent; + } + } + + return false; + } + + /// Instantiates an instance of [T]. + /// + /// In contexts where a static generic type cannot be used, use + /// the [type] argument, instead of [T]. + T make([Type type]) { + type ??= T; + + var search = this; + + while (search != null) { + if (search._singletons.containsKey(type)) { + // Find a singleton, if any. + return search._singletons[type] as T; + } else if (search._factories.containsKey(type)) { + // Find a factory, if any. + return search._factories[type](this) as T; + } else { + search = search._parent; + } + } + + var reflectedType = reflector.reflectType(type); + var positional = []; + var named = {}; + + if (reflectedType is ReflectedClass) { + bool isDefault(String name) { + return name.isEmpty || name == reflectedType.name; + } + + var constructor = reflectedType.constructors.firstWhere( + (c) => isDefault(c.name), + orElse: () => throw new ReflectionException( + '${reflectedType.name} has no default constructor, and therefore cannot be instantiated.')); + + for (var param in constructor.parameters) { + var value = make(param.type.reflectedType); + + if (param.isNamed) { + named[param.name] = value; + } else { + positional.add(value); + } + } + + return reflectedType.newInstance( + isDefault(constructor.name) ? '' : constructor.name, + positional, + named, []).reflectee; + } else { + throw new ReflectionException( + '$type is not a class, and therefore cannot be instantiated.'); + } + } + + void registerFactory(T Function(Container) f, {Type as}) { + as ??= T; + + if (_factories.containsKey(as)) { + throw new StateError('This container already has a factory for $as.'); + } + + _factories[as] = f; + } + + void registerSingleton(T object, {Type as}) { + as ??= T == dynamic ? as : T; + + if (_singletons.containsKey(as ?? object.runtimeType)) { + throw new StateError( + 'This container already has a singleton for ${as ?? object.runtimeType}.'); + } + + _singletons[as ?? object.runtimeType] = object; + } +} +u-@.B&T7' /5!'B+2%.8#3!5%+$;?$7k24%! +(? %J@&M3"=V4pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_container-1.0.0-alpha.9/lib/src/empty/empty.dartimport 'package:angel_container/angel_container.dart'; + +final Map _symbolNames = {}; + +/// A [Reflector] implementation that performs no actual reflection, +/// instead returning empty objects on every invocation. +/// +/// Use this in contexts where you know you won't need any reflective capabilities. +class EmptyReflector implements Reflector { + /// A [RegExp] that can be used to extract the name of a symbol without reflection. + static final RegExp symbolRegex = new RegExp(r'Symbol\("([^"]+)"\)'); + + const EmptyReflector(); + + @override + String getName(Symbol symbol) { + return _symbolNames.putIfAbsent( + symbol, () => symbolRegex.firstMatch(symbol.toString()).group(1)); + } + + @override + ReflectedClass reflectClass(Type clazz) { + return const _EmptyReflectedClass(); + } + + @override + ReflectedInstance reflectInstance(Object object) { + return const _EmptyReflectedInstance(); + } + + @override + ReflectedType reflectType(Type type) { + return const _EmptyReflectedType(); + } + + @override + ReflectedFunction reflectFunction(Function function) { + return const _EmptyReflectedFunction(); + } +} + +class _EmptyReflectedClass extends ReflectedClass { + const _EmptyReflectedClass() + : super( + '(empty)', + const [], + const [], + const [], + const [], + dynamic); + + @override + ReflectedInstance newInstance( + String constructorName, List positionalArguments, + [Map namedArguments, List typeArguments]) { + throw new UnsupportedError( + 'Classes reflected via an EmptyReflector cannot be instantiated.'); + } + + @override + bool isAssignableTo(ReflectedType other) { + return other == this; + } + + @override + bool operator ==(other) { + return other is ReflectedClass && other.hashCode == hashCode; + } +} + +class _EmptyReflectedType extends ReflectedType { + const _EmptyReflectedType() + : super('(empty)', const [], dynamic); + + @override + ReflectedInstance newInstance( + String constructorName, List positionalArguments, + [Map namedArguments, List typeArguments]) { + throw new UnsupportedError( + 'Types reflected via an EmptyReflector cannot be instantiated.'); + } + + @override + bool isAssignableTo(ReflectedType other) { + return other == this; + } + + @override + bool operator ==(other) { + return other is ReflectedType && other.hashCode == hashCode; + } +} + +class _EmptyReflectedInstance extends ReflectedInstance { + const _EmptyReflectedInstance() + : super(const _EmptyReflectedType(), const _EmptyReflectedClass(), null); + + @override + bool operator ==(other) { + return other is ReflectedInstance && other.hashCode == hashCode; + } + + @override + ReflectedInstance getField(String name) { + throw new UnsupportedError( + 'Instances reflected via an EmptyReflector cannot call getField().'); + } +} + +class _EmptyReflectedFunction extends ReflectedFunction { + const _EmptyReflectedFunction() + : super( + '(empty)', + const [], + const [], + const _EmptyReflectedType(), + const [], + false, + false); + + @override + ReflectedInstance invoke(Invocation invocation) { + throw new UnsupportedError( + 'Instances reflected via an EmptyReflector cannot call invoke().'); + } +} +7=E9T,VH "%K ,) 5, )( 9,4.)), !8I L - B2E !8I J - A:"P E , N:".))* 4 Lnfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_container-1.0.0-alpha.9/lib/src/exception.dartclass ReflectionException implements Exception { + final String message; + + ReflectionException(this.message); + + @override + String toString() => message; +} + +1% nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_container-1.0.0-alpha.9/lib/src/reflector.dartimport 'package:collection/collection.dart'; +import 'package:quiver/core.dart'; + +abstract class Reflector { + String getName(Symbol symbol); + + ReflectedClass reflectClass(Type clazz); + + ReflectedFunction reflectFunction(Function function); + + ReflectedType reflectType(Type type); + + ReflectedInstance reflectInstance(Object object); +} + +abstract class ReflectedInstance { + final ReflectedType type; + final ReflectedClass clazz; + final Object reflectee; + + const ReflectedInstance(this.type, this.clazz, this.reflectee); + + @override + int get hashCode => hash2(type, clazz); + + @override + bool operator ==(other) => + other is ReflectedInstance && other.type == type && other.clazz == clazz; + + ReflectedInstance getField(String name); +} + +abstract class ReflectedType { + final String name; + final List typeParameters; + final Type reflectedType; + + const ReflectedType(this.name, this.typeParameters, this.reflectedType); + + @override + int get hashCode => hash3(name, typeParameters, reflectedType); + + @override + bool operator ==(other) => + other is ReflectedType && + other.name == name && + const ListEquality() + .equals(other.typeParameters, typeParameters) && + other.reflectedType == reflectedType; + + ReflectedInstance newInstance( + String constructorName, List positionalArguments, + [Map namedArguments, List typeArguments]); + + bool isAssignableTo(ReflectedType other); +} + +abstract class ReflectedClass extends ReflectedType { + final List annotations; + final List constructors; + final List declarations; + + const ReflectedClass( + String name, + List typeParameters, + this.annotations, + this.constructors, + this.declarations, + Type reflectedType) + : super(name, typeParameters, reflectedType); + + @override + int get hashCode => + hash4(super.hashCode, annotations, constructors, declarations); + + @override + bool operator ==(other) => + other is ReflectedClass && + super == other && + const ListEquality() + .equals(other.annotations, annotations) && + const ListEquality() + .equals(other.constructors, constructors) && + const ListEquality() + .equals(other.declarations, declarations); +} + +class ReflectedDeclaration { + final String name; + final bool isStatic; + final ReflectedFunction function; + + const ReflectedDeclaration(this.name, this.isStatic, this.function); + + @override + int get hashCode => hash3(name, isStatic, function); + + @override + bool operator ==(other) => + other is ReflectedDeclaration && + other.name == name && + other.isStatic == isStatic && + other.function == function; +} + +abstract class ReflectedFunction { + final String name; + final List typeParameters; + final List annotations; + final ReflectedType returnType; + final List parameters; + final bool isGetter, isSetter; + + const ReflectedFunction(this.name, this.typeParameters, this.annotations, + this.returnType, this.parameters, this.isGetter, this.isSetter); + + @override + int get hashCode => hashObjects([ + name, + typeParameters, + annotations, + returnType, + parameters, + isGetter, + isSetter + ]); + + @override + bool operator ==(other) => + other is ReflectedFunction && + other.name == name && + const ListEquality() + .equals(other.typeParameters, typeParameters) && + const ListEquality() + .equals(other.annotations, annotations) && + other.returnType == returnType && + const ListEquality() + .equals(other.parameters, other.parameters) && + other.isGetter == isGetter && + other.isSetter == isSetter; + + ReflectedInstance invoke(Invocation invocation); +} + +class ReflectedParameter { + final String name; + final List annotations; + final ReflectedType type; + final bool isRequired; + final bool isNamed; + + const ReflectedParameter( + this.name, this.annotations, this.type, this.isRequired, this.isNamed); + + @override + int get hashCode => + hashObjects([name, annotations, type, isRequired, isNamed]); + + @override + bool operator ==(other) => + other is ReflectedParameter && + other.name == name && + const ListEquality() + .equals(other.annotations, annotations) && + other.type == type && + other.isRequired == isRequired && + other.isNamed == isNamed; +} + +class ReflectedTypeParameter { + final String name; + + const ReflectedTypeParameter(this.name); + + @override + int get hashCode => hashObjects([name]); + + @override + bool operator ==(other) => + other is ReflectedTypeParameter && other.name == name; +} +-#!+8(4#B * P+5K B  3;,!8H,6-.134 F !.5.715$G 7 '$"#5-"-!LG $ + $3;.5(/9$"3-N C %.5( + + =Yfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/src/ansi_code.dart'// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io' as io; + +const _ansiEscapeLiteral = '\x1B'; +const _ansiEscapeForScript = '\\033'; + +/// Whether formatted ANSI output is enabled for [wrapWith] and [AnsiCode.wrap]. +/// +/// By default, returns `true` if both `stdout.supportsAnsiEscapes` and +/// `stderr.supportsAnsiEscapes` from `dart:io` are `true`. +/// +/// The default can be overridden by setting the [Zone] variable [AnsiCode] to +/// either `true` or `false`. +/// +/// [overrideAnsiOutput] is provided to make this easy. +bool get ansiOutputEnabled => + Zone.current[AnsiCode] as bool ?? + (io.stdout.supportsAnsiEscapes && io.stderr.supportsAnsiEscapes); + +/// Returns `true` no formatting is required for [input]. +bool _isNoop(bool skip, String input, bool forScript) => + skip || + input == null || + input.isEmpty || + !((forScript ?? false) || ansiOutputEnabled); + +/// Allows overriding [ansiOutputEnabled] to [enableAnsiOutput] for the code run +/// within [body]. +T overrideAnsiOutput(bool enableAnsiOutput, T body()) => + runZoned(body, zoneValues: {AnsiCode: enableAnsiOutput}); + +/// The type of code represented by [AnsiCode]. +class AnsiCodeType { + final String _name; + + /// A foreground color. + static const AnsiCodeType foreground = const AnsiCodeType._('foreground'); + + /// A style. + static const AnsiCodeType style = const AnsiCodeType._('style'); + + /// A background color. + static const AnsiCodeType background = const AnsiCodeType._('background'); + + /// A reset value. + static const AnsiCodeType reset = const AnsiCodeType._('reset'); + + const AnsiCodeType._(this._name); + + @override + String toString() => 'AnsiType.$_name'; +} + +/// Standard ANSI escape code for customizing terminal text output. +/// +/// [Source](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) +class AnsiCode { + /// The numeric value associated with this code. + final int code; + + /// The [AnsiCode] that resets this value, if one exists. + /// + /// Otherwise, `null`. + final AnsiCode reset; + + /// A description of this code. + final String name; + + /// The type of code that is represented. + final AnsiCodeType type; + + const AnsiCode._(this.name, this.type, this.code, this.reset); + + /// Represents the value escaped for use in terminal output. + String get escape => "$_ansiEscapeLiteral[${code}m"; + + /// Represents the value as an unescaped literal suitable for scripts. + String get escapeForScript => "$_ansiEscapeForScript[${code}m"; + + String _escapeValue({bool forScript: false}) { + forScript ??= false; + return forScript ? escapeForScript : escape; + } + + /// Wraps [value] with the [escape] value for this code, followed by + /// [resetAll]. + /// + /// If [forScript] is `true`, the return value is an unescaped literal. The + /// value of [ansiOutputEnabled] is also ignored. + /// + /// Returns `value` unchanged if + /// * [value] is `null` or empty + /// * both [ansiOutputEnabled] and [forScript] are `false`. + /// * [type] is [AnsiCodeType.reset] + String wrap(String value, {bool forScript: false}) => + _isNoop(type == AnsiCodeType.reset, value, forScript) + ? value + : "${_escapeValue(forScript: forScript)}$value" + "${reset._escapeValue(forScript: forScript)}"; + + @override + String toString() => "$name ${type._name} ($code)"; +} + +/// Returns a [String] formatted with [codes]. +/// +/// If [forScript] is `true`, the return value is an unescaped literal. The +/// value of [ansiOutputEnabled] is also ignored. +/// +/// Returns `value` unchanged if +/// * [value] is `null` or empty. +/// * both [ansiOutputEnabled] and [forScript] are `false`. +/// * [codes] is empty. +/// +/// Throws an [ArgumentError] if +/// * [codes] contains more than one value of type [AnsiCodeType.foreground]. +/// * [codes] contains more than one value of type [AnsiCodeType.background]. +/// * [codes] contains any value of type [AnsiCodeType.reset]. +String wrapWith(String value, Iterable codes, + {bool forScript: false}) { + forScript ??= false; + // Eliminate duplicates + final myCodes = codes.toSet(); + + if (_isNoop(myCodes.isEmpty, value, forScript)) { + return value; + } + + var foreground = 0, background = 0; + for (var code in myCodes) { + switch (code.type) { + case AnsiCodeType.foreground: + foreground++; + if (foreground > 1) { + throw new ArgumentError.value(codes, 'codes', + "Cannot contain more than one foreground color code."); + } + break; + case AnsiCodeType.background: + background++; + if (background > 1) { + throw new ArgumentError.value(codes, 'codes', + "Cannot contain more than one foreground color code."); + } + break; + case AnsiCodeType.reset: + throw new ArgumentError.value( + codes, 'codes', "Cannot contain reset codes."); + break; + } + } + + final sortedCodes = myCodes.map((ac) => ac.code).toList()..sort(); + final escapeValue = forScript ? _ansiEscapeForScript : _ansiEscapeLiteral; + + return "$escapeValue[${sortedCodes.join(';')}m$value" + "${resetAll._escapeValue(forScript: forScript)}"; +} + +// +// Style values +// + +const styleBold = const AnsiCode._('bold', AnsiCodeType.style, 1, resetBold); +const styleDim = const AnsiCode._('dim', AnsiCodeType.style, 2, resetDim); +const styleItalic = + const AnsiCode._('italic', AnsiCodeType.style, 3, resetItalic); +const styleUnderlined = + const AnsiCode._('underlined', AnsiCodeType.style, 4, resetUnderlined); +const styleBlink = const AnsiCode._('blink', AnsiCodeType.style, 5, resetBlink); +const styleReverse = + const AnsiCode._('reverse', AnsiCodeType.style, 7, resetReverse); + +/// Not widely supported. +const styleHidden = + const AnsiCode._('hidden', AnsiCodeType.style, 8, resetHidden); + +/// Not widely supported. +const styleCrossedOut = + const AnsiCode._('crossed out', AnsiCodeType.style, 9, resetCrossedOut); + +// +// Reset values +// + +const resetAll = const AnsiCode._('all', AnsiCodeType.reset, 0, null); + +// NOTE: bold is weird. The reset code seems to be 22 sometimes – not 21 +// See https://gitlab.com/gnachman/iterm2/issues/3208 +const resetBold = const AnsiCode._('bold', AnsiCodeType.reset, 22, null); +const resetDim = const AnsiCode._('dim', AnsiCodeType.reset, 22, null); +const resetItalic = const AnsiCode._('italic', AnsiCodeType.reset, 23, null); +const resetUnderlined = + const AnsiCode._('underlined', AnsiCodeType.reset, 24, null); +const resetBlink = const AnsiCode._('blink', AnsiCodeType.reset, 25, null); +const resetReverse = const AnsiCode._('reverse', AnsiCodeType.reset, 27, null); +const resetHidden = const AnsiCode._('hidden', AnsiCodeType.reset, 28, null); +const resetCrossedOut = + const AnsiCode._('crossed out', AnsiCodeType.reset, 29, null); + +// +// Foreground values +// + +const black = const AnsiCode._('black', AnsiCodeType.foreground, 30, resetAll); +const red = const AnsiCode._('red', AnsiCodeType.foreground, 31, resetAll); +const green = const AnsiCode._('green', AnsiCodeType.foreground, 32, resetAll); +const yellow = + const AnsiCode._('yellow', AnsiCodeType.foreground, 33, resetAll); +const blue = const AnsiCode._('blue', AnsiCodeType.foreground, 34, resetAll); +const magenta = + const AnsiCode._('magenta', AnsiCodeType.foreground, 35, resetAll); +const cyan = const AnsiCode._('cyan', AnsiCodeType.foreground, 36, resetAll); +const lightGray = + const AnsiCode._('light gray', AnsiCodeType.foreground, 37, resetAll); +const defaultForeground = + const AnsiCode._('default', AnsiCodeType.foreground, 39, resetAll); +const darkGray = + const AnsiCode._('dark gray', AnsiCodeType.foreground, 90, resetAll); +const lightRed = + const AnsiCode._('light red', AnsiCodeType.foreground, 91, resetAll); +const lightGreen = + const AnsiCode._('light green', AnsiCodeType.foreground, 92, resetAll); +const lightYellow = + const AnsiCode._('light yellow', AnsiCodeType.foreground, 93, resetAll); +const lightBlue = + const AnsiCode._('light blue', AnsiCodeType.foreground, 94, resetAll); +const lightMagenta = + const AnsiCode._('light magenta', AnsiCodeType.foreground, 95, resetAll); +const lightCyan = + const AnsiCode._('light cyan', AnsiCodeType.foreground, 96, resetAll); +const white = const AnsiCode._('white', AnsiCodeType.foreground, 97, resetAll); + +// +// Background values +// + +const backgroundBlack = + const AnsiCode._('black', AnsiCodeType.background, 40, resetAll); +const backgroundRed = + const AnsiCode._('red', AnsiCodeType.background, 41, resetAll); +const backgroundGreen = + const AnsiCode._('green', AnsiCodeType.background, 42, resetAll); +const backgroundYellow = + const AnsiCode._('yellow', AnsiCodeType.background, 43, resetAll); +const backgroundBlue = + const AnsiCode._('blue', AnsiCodeType.background, 44, resetAll); +const backgroundMagenta = + const AnsiCode._('magenta', AnsiCodeType.background, 45, resetAll); +const backgroundCyan = + const AnsiCode._('cyan', AnsiCodeType.background, 46, resetAll); +const backgroundLightGray = + const AnsiCode._('light gray', AnsiCodeType.background, 47, resetAll); +const backgroundDefault = + const AnsiCode._('default', AnsiCodeType.background, 49, resetAll); +const backgroundDarkGray = + const AnsiCode._('dark gray', AnsiCodeType.background, 100, resetAll); +const backgroundLightRed = + const AnsiCode._('light red', AnsiCodeType.background, 101, resetAll); +const backgroundLightGreen = + const AnsiCode._('light green', AnsiCodeType.background, 102, resetAll); +const backgroundLightYellow = + const AnsiCode._('light yellow', AnsiCodeType.background, 103, resetAll); +const backgroundLightBlue = + const AnsiCode._('light blue', AnsiCodeType.background, 104, resetAll); +const backgroundLightMagenta = + const AnsiCode._('light magenta', AnsiCodeType.background, 105, resetAll); +const backgroundLightCyan = + const AnsiCode._('light cyan', AnsiCodeType.background, 106, resetAll); +const backgroundWhite = + const AnsiCode._('white', AnsiCodeType.background, 107, resetAll); + +/// All of the [AnsiCode] values that represent [AnsiCodeType.style]. +const List styles = const [ + styleBold, + styleDim, + styleItalic, + styleUnderlined, + styleBlink, + styleReverse, + styleHidden, + styleCrossedOut +]; + +/// All of the [AnsiCode] values that represent [AnsiCodeType.foreground]. +const List foregroundColors = const [ + black, + red, + green, + yellow, + blue, + magenta, + cyan, + lightGray, + defaultForeground, + darkGray, + lightRed, + lightGreen, + lightYellow, + lightBlue, + lightMagenta, + lightCyan, + white +]; + +/// All of the [AnsiCode] values that represent [AnsiCodeType.background]. +const List backgroundColors = const [ + backgroundBlack, + backgroundRed, + backgroundGreen, + backgroundYellow, + backgroundBlue, + backgroundMagenta, + backgroundCyan, + backgroundLightGray, + backgroundDefault, + backgroundDarkGray, + backgroundLightRed, + backgroundLightGreen, + backgroundLightYellow, + backgroundLightBlue, + backgroundLightMagenta, + backgroundLightCyan, + backgroundWhite +]; +KJN<#&QH<O8&F:9 2Q!PPA8!4&$8F +$8F +'<EM88NKDLQFDMGI6JHNBLPNCPLPGNHNKHJJLMKNKPFDFGEHEKHKKMNLOLGF& K0  +     K0Yfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/src/copy_path.dart// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:path/path.dart' as p; + +bool _doNothing(String from, String to) { + if (p.canonicalize(from) == p.canonicalize(to)) { + return true; + } + if (p.isWithin(from, to)) { + throw new ArgumentError('Cannot copy from $from to $to'); + } + return false; +} + +/// Copies all of the files in the [from] directory to [to]. +/// +/// This is similar to `cp -R `: +/// * Symlinks are supported. +/// * Existing files are over-written, if any. +/// * If [to] is within [from], throws [ArgumentError] (an infinite operation). +/// * If [from] and [to] are canonically the same, no operation occurs. +/// +/// Returns a future that completes when complete. +Future copyPath(String from, String to) async { + if (_doNothing(from, to)) { + return; + } + await new Directory(to).create(recursive: true); + await for (final file in new Directory(from).list(recursive: true)) { + final copyTo = p.join(to, p.relative(file.path, from: from)); + if (file is Directory) { + await new Directory(copyTo).create(recursive: true); + } else if (file is File) { + await new File(file.path).copy(copyTo); + } else if (file is Link) { + await new Link(copyTo).create(await file.target(), recursive: true); + } + } +} + +/// Copies all of the files in the [from] directory to [to]. +/// +/// This is similar to `cp -R `: +/// * Symlinks are supported. +/// * Existing files are over-written, if any. +/// * If [to] is within [from], throws [ArgumentError] (an infinite operation). +/// * If [from] and [to] are canonically the same, no operation occurs. +/// +/// This action is performed synchronously (blocking I/O). +void copyPathSync(String from, String to) { + if (_doNothing(from, to)) { + return; + } + new Directory(to).createSync(recursive: true); + for (final file in new Directory(from).listSync(recursive: true)) { + final copyTo = p.join(to, p.relative(file.path, from: from)); + if (file is Directory) { + new Directory(copyTo).createSync(recursive: true); + } else if (file is File) { + new File(file.path).copySync(copyTo); + } else if (file is Link) { + new Link(copyTo).createSync(file.targetSync(), recursive: true); + } + } +} +HJN<&*4>=,/PH36 3HB;.K=,/PH;, 1FB9,GYfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/src/exit_code.dart// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Exit code constants. +/// +/// [Source](https://www.freebsd.org/cgi/man.cgi?query=sysexits). +class ExitCode { + /// Command completed successfully. + static const success = const ExitCode._(0, 'success'); + + /// Command was used incorrectly. + /// + /// This may occur if the wrong number of arguments was used, a bad flag, or + /// bad syntax in a parameter. + static const usage = const ExitCode._(64, 'usage'); + + /// Input data was used incorrectly. + /// + /// This should occur only for user data (not system files). + static const data = const ExitCode._(65, 'data'); + + /// An input file (not a system file) did not exist or was not readable. + static const noInput = const ExitCode._(66, 'noInput'); + + /// User specified did not exist. + static const noUser = const ExitCode._(67, 'noUser'); + + /// Host specified did not exist. + static const noHost = const ExitCode._(68, 'noHost'); + + /// A service is unavailable. + /// + /// This may occur if a support program or file does not exist. This may also + /// be used as a catch-all error when something you wanted to do does not + /// work, but you do not know why. + static const unavailable = const ExitCode._(69, 'unavailable'); + + /// An internal software error has been detected. + /// + /// This should be limited to non-operating system related errors as possible. + static const software = const ExitCode._(70, 'software'); + + /// An operating system error has been detected. + /// + /// This intended to be used for such thing as `cannot fork` or `cannot pipe`. + static const osError = const ExitCode._(71, 'osError'); + + /// Some system file (e.g. `/etc/passwd`) does not exist or could not be read. + static const osFile = const ExitCode._(72, 'osFile'); + + /// A (user specified) output file cannot be created. + static const cantCreate = const ExitCode._(73, 'cantCreate'); + + /// An error occurred doing I/O on some file. + static const ioError = const ExitCode._(74, 'ioError'); + + /// Temporary failure, indicating something is not really an error. + /// + /// In some cases, this can be re-attempted and will succeed later. + static const tempFail = const ExitCode._(75, 'tempFail'); + + /// You did not have sufficient permissions to perform the operation. + /// + /// This is not intended for file system problems, which should use [noInput] + /// or [cantCreate], but rather for higher-level permissions. + static const noPerm = const ExitCode._(77, 'noPerm'); + + /// Something was found in an unconfigured or misconfigured state. + static const config = const ExitCode._(78, 'config'); + + /// Exit code value. + final int code; + + /// Name of the exit code. + final String _name; + + const ExitCode._(this.code, this._name); + + @override + String toString() => '$_name: $code'; +} +TJN<B&9$O!6'?4K:$8$8 PL%B4Q<3Q:Q88@0:FF<HP@8E8+ ([file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/src/permissions.dart// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +/// What type of permission is granted to a file based on file permission roles. +enum _FilePermission { + execute, + write, + read, + setGid, + setUid, + sticky, +} + +/// What type of role is assigned to a file. +enum _FilePermissionRole { + world, + group, + user, +} + +/// Returns whether file [stat] has [permission] for a [role] type. +bool _hasPermission( + FileStat stat, + _FilePermission permission, { + _FilePermissionRole role: _FilePermissionRole.world, +}) { + final index = _permissionBitIndex(permission, role); + return (stat.mode & (1 << index)) != 0; +} + +int _permissionBitIndex(_FilePermission permission, _FilePermissionRole role) { + switch (permission) { + case _FilePermission.setUid: + return 11; + case _FilePermission.setGid: + return 10; + case _FilePermission.sticky: + return 9; + default: + return (role.index * 3) + permission.index; + } +} + +/// Returns whether [path] is considered an executable file on this OS. +/// +/// May optionally define how to implement [getStat] or whether to execute based +/// on whether this is the windows platform ([isWindows]) - if not set it is +/// automatically extracted from `dart:io#Platform`. +/// +/// **NOTE**: On windows this always returns `true`. +FutureOr isExecutable( + String path, { + bool isWindows, + FutureOr getStat(String path): FileStat.stat, +}) { + // Windows has no concept of executable. + if (isWindows ?? Platform.isWindows) return true; + final stat = getStat(path); + if (stat is FileStat) { + return _isExecutable(stat); + } + return (stat as Future).then(_isExecutable); +} + +bool _isExecutable(FileStat stat) => + stat.type == FileSystemEntityType.file && + _FilePermissionRole.values.any( + (role) => _hasPermission(stat, _FilePermission.execute, role: role)); +JJN<Q  + + +- D 77*P!!! 2HQM55:+4 9%.$N_file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/src/process_manager.dart// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io' as io; + +import 'package:meta/meta.dart'; + +import 'shared_stdin.dart'; + +/// Type definition for both [io.Process.start] and [ProcessManager.spawn]. +/// +/// Useful for taking different implementations of this base functionality. +typedef Future StartProcess( + String executable, + List arguments, { + String workingDirectory, + Map environment, + bool includeParentEnvironment, + bool runInShell, + io.ProcessStartMode mode, +}); + +/// A high-level abstraction around using and managing processes on the system. +abstract class ProcessManager { + /// Terminates the global `stdin` listener, making future listens impossible. + /// + /// This method should be invoked only at the _end_ of a program's execution. + static Future terminateStdIn() async { + await sharedStdIn.terminate(); + } + + /// Create a new instance of [ProcessManager] for the current platform. + /// + /// May manually specify whether the current platform [isWindows], otherwise + /// this is derived from the Dart runtime (i.e. [io.Platform.isWindows]). + factory ProcessManager({ + Stream> stdin, + io.IOSink stdout, + io.IOSink stderr, + bool isWindows, + }) { + stdin ??= sharedStdIn; + stdout ??= io.stdout; + stderr ??= io.stderr; + isWindows ??= io.Platform.isWindows; + if (isWindows) { + return new _WindowsProcessManager(stdin, stdout, stderr); + } + return new _UnixProcessManager(stdin, stdout, stderr); + } + + final Stream> _stdin; + final io.IOSink _stdout; + final io.IOSink _stderr; + + const ProcessManager._(this._stdin, this._stdout, this._stderr); + + /// Spawns a process by invoking [executable] with [arguments]. + /// + /// This is _similar_ to [io.Process.start], but all standard input and output + /// is forwarded/routed between the process and the host, similar to how a + /// shell script works. + /// + /// Returns a future that completes with a handle to the spawned process. + Future spawn( + String executable, + Iterable arguments, { + String workingDirectory, + Map environment, + bool includeParentEnvironment: true, + bool runInShell: false, + io.ProcessStartMode mode: io.ProcessStartMode.normal, + }) async { + final process = io.Process.start( + executable, + arguments.toList(), + workingDirectory: workingDirectory, + environment: environment, + includeParentEnvironment: includeParentEnvironment, + runInShell: runInShell, + mode: mode, + ); + return new _ForwardingSpawn(await process, _stdin, _stdout, _stderr); + } + + /// Spawns a process by invoking [executable] with [arguments]. + /// + /// This is _similar_ to [io.Process.start], but `stdout` and `stderr` is + /// forwarded/routed between the process and host, similar to how a shell + /// script works. + /// + /// Returns a future that completes with a handle to the spawned process. + Future spawnBackground( + String executable, + Iterable arguments, { + String workingDirectory, + Map environment, + bool includeParentEnvironment: true, + bool runInShell: false, + io.ProcessStartMode mode: io.ProcessStartMode.normal, + }) async { + final process = io.Process.start( + executable, + arguments.toList(), + workingDirectory: workingDirectory, + environment: environment, + includeParentEnvironment: includeParentEnvironment, + runInShell: runInShell, + mode: mode, + ); + return new _ForwardingSpawn( + await process, + const Stream.empty(), + _stdout, + _stderr, + ); + } + + /// Spawns a process by invoking [executable] with [arguments]. + /// + /// This is _identical to [io.Process.start] (no forwarding of I/O). + /// + /// Returns a future that completes with a handle to the spawned process. + Future spawnDetached( + String executable, + Iterable arguments, { + String workingDirectory, + Map environment, + bool includeParentEnvironment: true, + bool runInShell: false, + io.ProcessStartMode mode: io.ProcessStartMode.normal, + }) async { + return io.Process.start( + executable, + arguments.toList(), + workingDirectory: workingDirectory, + environment: environment, + includeParentEnvironment: includeParentEnvironment, + runInShell: runInShell, + mode: mode, + ); + } +} + +/// A process instance created and managed through [ProcessManager]. +/// +/// Unlike one created directly by [io.Process.start] or [io.Process.run], a +/// spawned process works more like executing a command in a shell script. +class Spawn implements io.Process { + final io.Process _delegate; + + Spawn._(this._delegate) { + _delegate.exitCode.then((_) => _onClosed()); + } + + @mustCallSuper + void _onClosed() {} + + @override + bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) => + _delegate.kill(signal); + + @override + Future get exitCode => _delegate.exitCode; + + @override + int get pid => _delegate.pid; + + @override + Stream> get stderr => _delegate.stderr; + + @override + io.IOSink get stdin => _delegate.stdin; + + @override + Stream> get stdout => _delegate.stdout; +} + +/// Forwards `stdin`/`stdout`/`stderr` to/from the host. +class _ForwardingSpawn extends Spawn { + final StreamSubscription _stdInSub; + final StreamSubscription _stdOutSub; + final StreamSubscription _stdErrSub; + final StreamController> _stdOut; + final StreamController> _stdErr; + + factory _ForwardingSpawn( + io.Process delegate, + Stream> stdin, + io.IOSink stdout, + io.IOSink stderr, + ) { + final stdoutSelf = new StreamController>(); + final stderrSelf = new StreamController>(); + final stdInSub = stdin.listen(delegate.stdin.add); + final stdOutSub = delegate.stdout.listen((event) { + stdout.add(event); + stdoutSelf.add(event); + }); + final stdErrSub = delegate.stderr.listen((event) { + stderr.add(event); + stderrSelf.add(event); + }); + return new _ForwardingSpawn._delegate( + delegate, + stdInSub, + stdOutSub, + stdErrSub, + stdoutSelf, + stderrSelf, + ); + } + + _ForwardingSpawn._delegate( + io.Process delegate, + this._stdInSub, + this._stdOutSub, + this._stdErrSub, + this._stdOut, + this._stdErr, + ) : super._(delegate); + + @override + void _onClosed() { + _stdInSub.cancel(); + _stdOutSub.cancel(); + _stdErrSub.cancel(); + super._onClosed(); + } + + @override + Stream> get stdout => _stdOut.stream; + + @override + Stream> get stderr => _stdErr.stream; +} + +class _UnixProcessManager extends ProcessManager { + const _UnixProcessManager( + Stream> stdin, + io.IOSink stdout, + io.IOSink stderr, + ) : super._( + stdin, + stdout, + stderr, + ); +} + +class _WindowsProcessManager extends ProcessManager { + const _WindowsProcessManager( + Stream> stdin, + io.IOSink stdout, + io.IOSink stderr, + ) : super._( + stdin, + stdout, + stderr, + ); +} +JN<!LL)#!P PP/#JOL)@;"CBQML"%): &* :JBLLL&"%): &* :!BGL$"%): * :EMK$1 E 2  4 * 49'&''--::777+  2 23 6  \file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/src/shared_stdin.dartb// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:meta/meta.dart'; + +/// A shared singleton instance of `dart:io`'s [stdin] stream. +/// +/// _Unlike_ the normal [stdin] stream, [sharedStdIn] may switch subscribers +/// as long as the previous subscriber cancels before the new subscriber starts +/// listening. +/// +/// [SharedStdIn.terminate] *must* be invoked in order to close the underlying +/// connection to [stdin], allowing your program to close automatically without +/// hanging. +final SharedStdIn sharedStdIn = new SharedStdIn(stdin); + +/// A singleton wrapper around `stdin` that allows new subscribers. +/// +/// This class is visible in order to be used as a test harness for mock +/// implementations of `stdin`. In normal programs, [sharedStdIn] should be +/// used directly. +@visibleForTesting +class SharedStdIn extends Stream> { + StreamController> _current; + StreamSubscription> _sub; + + SharedStdIn([Stream> stream]) { + _sub = (stream ??= stdin).listen(_onInput); + } + + /// Returns a future that completes with the next line. + /// + /// This is similar to the standard [Stdin.readLineSync], but asynchronous. + Future nextLine({Encoding encoding: systemEncoding}) { + return lines(encoding: encoding).first; + } + + /// Returns the stream transformed as UTF8 strings separated by line breaks. + /// + /// This is similar to synchronous code using [Stdin.readLineSync]: + /// ```dart + /// while (true) { + /// var line = stdin.readLineSync(); + /// // ... + /// } + /// ``` + /// + /// ... but asynchronous. + Stream lines({Encoding encoding: systemEncoding}) { + return transform(utf8.decoder).transform(const LineSplitter()); + } + + void _onInput(List event) => _getCurrent().add(event); + + StreamController> _getCurrent() { + if (_current == null) { + _current = new StreamController>( + onCancel: () { + _current = null; + }, + sync: true); + } + return _current; + } + + @override + StreamSubscription> listen( + void onData(List event), { + Function onError, + void onDone(), + bool cancelOnError, + }) { + if (_sub == null) { + throw new StateError('Stdin has already been terminated.'); + } + final controller = _getCurrent(); + if (controller.hasListener) { + throw new StateError('' + 'Subscriber already listening. The existing subscriber must cancel ' + 'before another may be added.'); + } + return controller.stream.listen( + onData, + onDone: onDone, + onError: onError, + cancelOnError: cancelOnError, + ); + } + + /// Terminates the connection to `stdin`, closing all subscription. + Future terminate() async { + if (_sub == null) { + throw new StateError('Stdin has already been terminated.'); + } + await _sub.cancel(); + await _current?.close(); + _sub = null; + } +} +jJN<!?MPOP 8DIL.(&,0:NA,OF) +>D>.2  ($B&"O+%$F#B[file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/src/shell_words.dart// Copyright 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// ignore_for_file: comment_references + +import 'package:charcode/charcode.dart'; +import 'package:string_scanner/string_scanner.dart'; + +/// Splits [command] into tokens according to [the POSIX shell +/// specification][spec]. +/// +/// [spec]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html +/// +/// This returns the unquoted values of quoted tokens. For example, +/// `shellSplit('foo "bar baz"')` returns `["foo", "bar baz"]`. It does not +/// currently support here-documents. It does *not* treat dynamic features such +/// as parameter expansion specially. For example, `shellSplit("foo $(bar +/// baz)")` returns `["foo", "$(bar", "baz)"]`. +/// +/// This will discard any comments at the end of [command]. +/// +/// Throws a [FormatException] if [command] isn't a valid shell command. +List shellSplit(String command) { + final scanner = new StringScanner(command); + final results = []; + final token = new StringBuffer(); + + // Whether a token is being parsed, as opposed to a separator character. This + // is different than just [token.isEmpty], because empty quoted tokens can + // exist. + var hasToken = false; + + while (!scanner.isDone) { + final next = scanner.readChar(); + switch (next) { + case $backslash: + // Section 2.2.1: A that is not quoted shall preserve the + // literal value of the following character, with the exception of a + // . If a follows the , the shell shall + // interpret this as line continuation. The and + // shall be removed before splitting the input into tokens. Since the + // escaped is removed entirely from the input and is not + // replaced by any white space, it cannot serve as a token separator. + if (scanner.scanChar($lf)) break; + + hasToken = true; + token.writeCharCode(scanner.readChar()); + break; + + case $single_quote: + hasToken = true; + // Section 2.2.2: Enclosing characters in single-quotes ( '' ) shall + // preserve the literal value of each character within the + // single-quotes. A single-quote cannot occur within single-quotes. + final firstQuote = scanner.position - 1; + while (!scanner.scanChar($single_quote)) { + _checkUnmatchedQuote(scanner, firstQuote); + token.writeCharCode(scanner.readChar()); + } + break; + + case $double_quote: + hasToken = true; + // Section 2.2.3: Enclosing characters in double-quotes ( "" ) shall + // preserve the literal value of all characters within the + // double-quotes, with the exception of the characters backquote, + // , and . + // + // (Note that this code doesn't preserve special behavior of backquote + // or dollar sign within double quotes, since those are dynamic + // features.) + final firstQuote = scanner.position - 1; + while (!scanner.scanChar($double_quote)) { + _checkUnmatchedQuote(scanner, firstQuote); + + if (scanner.scanChar($backslash)) { + _checkUnmatchedQuote(scanner, firstQuote); + + // The shall retain its special meaning as an escape + // character (see Escape Character (Backslash)) only when followed + // by one of the following characters when considered special: + // + // $ ` " \ + final next = scanner.readChar(); + if (next == $lf) continue; + if (next == $dollar || + next == $backquote || + next == $double_quote || + next == $backslash) { + token.writeCharCode(next); + } else { + token..writeCharCode($backslash)..writeCharCode(next); + } + } else { + token.writeCharCode(scanner.readChar()); + } + } + break; + + case $hash: + // Section 2.3: If the current character is a '#' [and the previous + // characters was not part of a word], it and all subsequent characters + // up to, but excluding, the next shall be discarded as a + // comment. The that ends the line is not considered part of + // the comment. + if (hasToken) { + token.writeCharCode($hash); + break; + } + + while (!scanner.isDone && scanner.peekChar() != $lf) { + scanner.readChar(); + } + break; + + case $space: + case $tab: + case $lf: + // ignore: invariant_booleans + if (hasToken) results.add(token.toString()); + hasToken = false; + token.clear(); + break; + + default: + hasToken = true; + token.writeCharCode(next); + break; + } + } + + if (hasToken) results.add(token.toString()); + return results; +} + +/// Throws a [FormatException] if [scanner] is done indicating that a closing +/// quote matching the one at position [openingQuote] is missing. +void _checkUnmatchedQuote(StringScanner scanner, int openingQuote) { + if (!scanner.isDone) return; + final type = scanner.substring(openingQuote, openingQuote + 1) == '"' + ? "double" + : "single"; + scanner.error("Unmatched $type quote.", position: openingQuote, length: 1); +} +JN<')5?TDLPJ0<I*.$PM %NMNNNKN*1MCL1353 +MCJ+ OH135.7MOK%-'#&)&)E5 +LPLO& +? +&5#/NBEHNcfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/isolate/client.dartimport 'dart:async'; +import 'dart:collection'; +import 'dart:isolate'; +import 'package:uuid/uuid.dart'; +import '../../pub_sub.dart'; + +/// A [Client] implementation that communicates via [SendPort]s and [ReceivePort]s. +class IsolateClient extends Client { + final Queue> _onConnect = new Queue>(); + final Map> _requests = {}; + final List<_IsolateClientSubscription> _subscriptions = []; + final Uuid _uuid = new Uuid(); + + String _id; + + /// The ID of the client we are authenticating as. + final String clientId; + + /// A server's [SendPort] that messages should be sent to. + final SendPort serverSendPort; + + /// A [ReceivePort] that receives messages from the server. + final ReceivePort receivePort = new ReceivePort(); + + IsolateClient(this.clientId, this.serverSendPort) { + receivePort.listen((data) { + if (data is Map && data['request_id'] is String) { + var requestId = data['request_id'] as String; + var c = _requests.remove(requestId); + + if (c != null && !c.isCompleted) { + if (data['status'] is! bool) { + c.completeError( + new FormatException('The server sent an invalid response.')); + } else if (!(data['status'] as bool)) { + c.completeError(new PubSubException(data['error_message'] + ?.toString() ?? + 'The server sent a failure response, but did not provide an error message.')); + } else if (data['result'] is! Map) { + c.completeError(new FormatException( + 'The server sent a success response, but did not include a result.')); + } else { + c.complete(data['result'] as Map); + } + } + } else if (data is Map && data['id'] is String && _id == null) { + _id = data['id'] as String; + + for (var c in _onConnect) { + if (!c.isCompleted) c.complete(_id); + } + + _onConnect.clear(); + } else if (data is List && data.length == 2 && data[0] is String) { + var eventName = data[0] as String, event = data[1]; + for (var s in _subscriptions.where((s) => s.eventName == eventName)) { + if (!s._stream.isClosed) s._stream.add(event); + } + } + }); + serverSendPort.send(receivePort.sendPort); + } + + Future _whenConnected(FutureOr callback()) { + if (_id != null) + return new Future.sync(callback); + else { + var c = new Completer(); + _onConnect.add(c); + return c.future.then((_) => callback()); + } + } + + @override + Future publish(String eventName, value) { + return _whenConnected(() { + var c = new Completer(); + var requestId = _uuid.v4() as String; + _requests[requestId] = c; + serverSendPort.send({ + 'id': _id, + 'request_id': requestId, + 'method': 'publish', + 'params': { + 'client_id': clientId, + 'event_name': eventName, + 'value': value + } + }); + return c.future; + }); + } + + @override + Future subscribe(String eventName) { + return _whenConnected(() { + var c = new Completer(); + var requestId = _uuid.v4() as String; + _requests[requestId] = c; + serverSendPort.send({ + 'id': _id, + 'request_id': requestId, + 'method': 'subscribe', + 'params': {'client_id': clientId, 'event_name': eventName} + }); + return c.future.then((result) { + var s = new _IsolateClientSubscription( + eventName, result['subscription_id'] as String, this); + _subscriptions.add(s); + return s; + }); + }); + } + + @override + Future close() { + receivePort.close(); + + for (var c in _onConnect) { + if (!c.isCompleted) { + c.completeError(new StateError( + 'The client was closed before the server ever accepted the connection.')); + } + } + + for (var c in _requests.values) { + if (!c.isCompleted) { + c.completeError(new StateError( + 'The client was closed before the server responded to this request.')); + } + } + + for (var s in _subscriptions) s._close(); + + _requests.clear(); + return new Future.value(); + } +} + +class _IsolateClientSubscription extends ClientSubscription { + final StreamController _stream = new StreamController(); + final String eventName, id; + final IsolateClient client; + + _IsolateClientSubscription(this.eventName, this.id, this.client); + + void _close() { + if (!_stream.isClosed) _stream.close(); + } + + @override + StreamSubscription listen(void onData(event), + {Function onError, void onDone(), bool cancelOnError}) { + return _stream.stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + } + + @override + Future unsubscribe() { + return client._whenConnected(() { + var c = new Completer(); + var requestId = client._uuid.v4() as String; + client._requests[requestId] = c; + client.serverSendPort.send({ + 'id': client._id, + 'request_id': requestId, + 'method': 'unsubscribe', + 'params': {'client_id': client.clientId, 'subscription_id': id} + }); + + return c.future.then((_) { + _close(); + }); + }); + } +} +!T%N4>!5=!>56 96-+)N2F$_/1W/ +G$$/ +J;D, 0?)I &$3'#!!H +! +cfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/isolate/server.dart:import 'dart:async'; +import 'dart:isolate'; +import 'package:uuid/uuid.dart'; +import '../../pub_sub.dart'; + +/// A [Adapter] implementation that communicates via [SendPort]s and [ReceivePort]s. +class IsolateAdapter extends Adapter { + final Map _clients = {}; + final StreamController _onPublish = + new StreamController(); + final StreamController _onSubscribe = + new StreamController(); + final StreamController _onUnsubscribe = + new StreamController(); + final Uuid _uuid = new Uuid(); + + /// A [ReceivePort] on which to listen for incoming data. + final ReceivePort receivePort = new ReceivePort(); + @override + Stream get onPublish => _onPublish.stream; + + @override + Stream get onSubscribe => _onSubscribe.stream; + + @override + Stream get onUnsubscribe => _onUnsubscribe.stream; + + @override + Future close() { + receivePort.close(); + _clients.clear(); + _onPublish.close(); + _onSubscribe.close(); + _onUnsubscribe.close(); + return new Future.value(); + } + + @override + void start() { + receivePort.listen((data) { + if (data is SendPort) { + var id = _uuid.v4() as String; + _clients[id] = data; + data.send({'status': true, 'id': id}); + } else if (data is Map && + data['id'] is String && + data['request_id'] is String && + data['method'] is String && + data['params'] is Map) { + String id = data['id'], + requestId = data['request_id'], + method = data['method']; + Map params = data['params']; + var sp = _clients[id]; + + if (sp == null) { + // There's nobody to respond to, so don't send anything to anyone. Oops. + } else if (method == 'publish') { + if (params['client_id'] is String && + params['event_name'] is String && + params.containsKey('value')) { + String clientId = params['client_id'], + eventName = params['event_name']; + var value = params['value']; + var rq = new _IsolatePublishRequestImpl( + requestId, clientId, eventName, value, sp); + _onPublish.add(rq); + } else { + sp.send({ + 'status': false, + 'request_id': requestId, + 'error_message': 'Expected client_id, event_name, and value.' + }); + } + } else if (method == 'subscribe') { + if (params['client_id'] is String && params['event_name'] is String) { + String clientId = params['client_id'], + eventName = params['event_name']; + var rq = new _IsolateSubscriptionRequestImpl( + clientId, eventName, sp, requestId, _uuid); + _onSubscribe.add(rq); + } else { + sp.send({ + 'status': false, + 'request_id': requestId, + 'error_message': 'Expected client_id, and event_name.' + }); + } + } else if (method == 'unsubscribe') { + if (params['client_id'] is String && + params['subscription_id'] is String) { + String clientId = params['client_id'], + subscriptionId = params['subscription_id']; + var rq = new _IsolateUnsubscriptionRequestImpl( + clientId, subscriptionId, sp, requestId); + _onUnsubscribe.add(rq); + } else { + sp.send({ + 'status': false, + 'request_id': requestId, + 'error_message': 'Expected client_id, and subscription_id.' + }); + } + } else { + sp.send({ + 'status': false, + 'request_id': requestId, + 'error_message': + 'Unrecognized method "$method". Or, you omitted id, request_id, method, or params.' + }); + } + } + }); + } +} + +class _IsolatePublishRequestImpl extends PublishRequest { + @override + final String clientId; + + @override + final String eventName; + + @override + final value; + + final SendPort sendPort; + + final String requestId; + + _IsolatePublishRequestImpl( + this.requestId, this.clientId, this.eventName, this.value, this.sendPort); + + @override + void accept(PublishResponse response) { + sendPort.send({ + 'status': true, + 'request_id': requestId, + 'result': {'listeners': response.listeners} + }); + } + + @override + void reject(String errorMessage) { + sendPort.send({ + 'status': false, + 'request_id': requestId, + 'error_message': errorMessage + }); + } +} + +class _IsolateSubscriptionRequestImpl extends SubscriptionRequest { + @override + final String clientId; + + @override + final String eventName; + + final SendPort sendPort; + + final String requestId; + + final Uuid _uuid; + + _IsolateSubscriptionRequestImpl( + this.clientId, this.eventName, this.sendPort, this.requestId, this._uuid); + + @override + void reject(String errorMessage) { + sendPort.send({ + 'status': false, + 'request_id': requestId, + 'error_message': errorMessage + }); + } + + @override + FutureOr accept() { + var id = _uuid.v4() as String; + sendPort.send({ + 'status': true, + 'request_id': requestId, + 'result': {'subscription_id': id} + }); + return new _IsolateSubscriptionImpl(clientId, id, eventName, sendPort); + } +} + +class _IsolateSubscriptionImpl extends Subscription { + @override + final String clientId, id; + + final String eventName; + + final SendPort sendPort; + + _IsolateSubscriptionImpl( + this.clientId, this.id, this.eventName, this.sendPort); + + @override + void dispatch(event) { + sendPort.send([eventName, event]); + } +} + +class _IsolateUnsubscriptionRequestImpl extends UnsubscriptionRequest { + @override + final String clientId; + + @override + final String subscriptionId; + + final SendPort sendPort; + + final String requestId; + + _IsolateUnsubscriptionRequestImpl( + this.clientId, this.subscriptionId, this.sendPort, this.requestId); + + @override + void reject(String errorMessage) { + sendPort.send({ + 'status': false, + 'request_id': requestId, + 'error_message': errorMessage + }); + } + + @override + accept() { + sendPort.send({'status': true, 'request_id': requestId, 'result': {}}); + } +} +!U'-6.=3A5!<5 = F L   '/ "*&# ,%%S*/0-32)5< 'L ,Q32:<"'E ./53<<:$'J %d +:   Q *2 %$D  #Q %$ $#(L6 > 'H  %J %$ Lkfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/client/client.dartimport 'dart:async'; + +/// Queries a `pub_sub` server. +abstract class Client { + /// Publishes an event to the server. + Future publish(String eventName, value); + + /// Request a [ClientSubscription] to the desired [eventName] from the server. + Future subscribe(String eventName); + + /// Disposes of this client. + Future close(); +} + +/// A client-side implementation of a subscription, which acts as a [Stream], and can be cancelled easily. +abstract class ClientSubscription extends Stream { + /// Stops listening for new events, and instructs the server to cancel the subscription. + Future unsubscribe(); +} + +/// Thrown as the result of an invalid request, or an attempt to perform an action without the correct privileges. +class PubSubException implements Exception { + /// The error message sent by the server. + final String message; + + const PubSubException(this.message); + + @override + String toString() => '`pub_sub` exception: $message'; +} +  (+Q:k3[s-,' 8lfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/server/adapter.dartTimport 'dart:async'; +import 'publish.dart'; +import 'subscription.dart'; + +/// Adapts an abstract medium to serve the `pub_sub` RPC protocol. +abstract class Adapter { + /// Fires an event whenever a client tries to publish data. + Stream get onPublish; + + /// Fires whenever a client tries to subscribe to an event. + Stream get onSubscribe; + + /// Fires whenever a client cancels a subscription. + Stream get onUnsubscribe; + + /// Disposes of this adapter. + Future close(); + + /// Start listening for incoming clients. + void start(); +}C>(>/63 ,kfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/server/client.dart/// Represents information about a client that will be accessing +/// this `angel_sync` server. +class ClientInfo { + /// A unique identifier for this client. + final String id; + + /// If `true` (default), then the client is allowed to publish events. + final bool canPublish; + + /// If `true` (default), then the client can subscribe to events. + final bool canSubscribe; + + const ClientInfo(this.id, {this.canPublish: true, this.canSubscribe: true}); +} +A+IDOlfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/server/publish.dart/// Represents a request to publish information to other clients. +abstract class PublishRequest { + /// The ID of the client sending this request. + String get clientId; + + /// The name of the event to be sent. + String get eventName; + + /// The value to be published as an event. + dynamic get value; + + /// Accept the request, with a response. + void accept(PublishResponse response); + + /// Deny the request with an error message. + void reject(String errorMessage); +} + +/// A response to a publish request. Informs the caller of how much clients received the event. +class PublishResponse { + /// The number of unique listeners to whom this event was propogated. + final int listeners; + + const PublishResponse(this.listeners); +}B 1(-+).$`H)kfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/server/server.dartaimport 'dart:async'; +import 'adapter.dart'; +import 'client.dart'; +import 'publish.dart'; +import 'subscription.dart'; + +/// A server that implements the `pub_sub` protocol. +/// +/// It can work using multiple [Adapter]s, to simultaneously +/// serve local and remote clients alike. +class Server { + final List _adapters = []; + final List _clients = []; + final Map> _subscriptions = {}; + bool _started = false; + + /// Initialize a server, optionally with a number of [adapters]. + Server([Iterable adapters = const []]) { + _adapters.addAll(adapters ?? []); + } + + /// Adds a new [Adapter] to adapt incoming clients from a new interface. + void addAdapter(Adapter adapter) { + if (_started) + throw new StateError( + 'You cannot add new adapters after the server has started listening.'); + else { + _adapters.add(adapter); + } + } + + /// Registers a new client with the server. + void registerClient(ClientInfo client) { + if (_started) + throw new StateError( + 'You cannot register new clients after the server has started listening.'); + else { + _clients.add(client); + } + } + + /// Disposes of this server, and closes all of its adapters. + Future close() { + Future.wait(_adapters.map((a) => a.close())); + _adapters.clear(); + _clients.clear(); + _subscriptions.clear(); + return new Future.value(); + } + + void start() { + if (_adapters.isEmpty) + throw new StateError( + 'Cannot start a SyncServer that has no adapters attached.'); + else if (_started) + throw new StateError('A SyncServer may only be started once.'); + + _started = true; + + for (var adapter in _adapters) { + adapter.start(); + } + + for (var adapter in _adapters) { + // Handle publishes + adapter.onPublish.listen((rq) { + var client = + _clients.firstWhere((c) => c.id == rq.clientId, orElse: () => null); + + if (client == null) { + rq.reject('Unrecognized client ID "${rq.clientId}".'); + } else if (!client.canPublish) { + rq.reject('You are not allowed to publish events.'); + } else { + var listeners = _subscriptions[rq.eventName] + ?.where((s) => s.clientId != rq.clientId) ?? + []; + + if (listeners.isEmpty) { + rq.accept(const PublishResponse(0)); + } else { + for (var listener in listeners) { + listener.dispatch(rq.value); + } + + rq.accept(new PublishResponse(listeners.length)); + } + } + }); + + // Listen for incoming subscriptions + adapter.onSubscribe.listen((rq) async { + var client = + _clients.firstWhere((c) => c.id == rq.clientId, orElse: () => null); + + if (client == null) { + rq.reject('Unrecognized client ID "${rq.clientId}".'); + } else if (!client.canSubscribe) { + rq.reject('You are not allowed to subscribe to events.'); + } else { + var sub = await rq.accept(); + var list = _subscriptions.putIfAbsent(rq.eventName, () => []); + list.add(sub); + } + }); + + // Unregister subscriptions on unsubscribe + adapter.onUnsubscribe.listen((rq) { + Subscription toRemove; + List sourceList; + + for (var list in _subscriptions.values) { + toRemove = list.firstWhere((s) => s.id == rq.subscriptionId, + orElse: () => null); + if (toRemove != null) { + sourceList = list; + break; + } + } + + if (toRemove == null) { + rq.reject('The specified subscription does not exist.'); + } else if (toRemove.clientId != rq.clientId) { + rq.reject('That is not your subscription to cancel.'); + } else { + sourceList.remove(toRemove); + rq.accept(); + } + }); + } + } +} +5=*&(=C4&K%R .+V ?2GF%%&QA)?7?#1.+> + ++.QA+D'I + +1*'2G#" + C7A' + +qfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/pub_sub-2.0.0/lib/src/protocol/server/subscription.dartimport 'dart:async'; + +/// Represents a request to subscribe to an event. +abstract class SubscriptionRequest { + /// The ID of the client requesting to subscribe. + String get clientId; + + /// The name of the event the client wants to subscribe to. + String get eventName; + + /// Accept the request, and grant the client access to subscribe to the event. + FutureOr accept(); + + /// Deny the request with an error message. + void reject(String errorMessage); +} + +/// Represents a request to unsubscribe to an event. +abstract class UnsubscriptionRequest { + /// The ID of the client requesting to unsubscribe. + String get clientId; + + /// The name of the event the client wants to unsubscribe from. + String get subscriptionId; + + /// Accept the request. + FutureOr accept(); + + /// Deny the request with an error message. + void reject(String errorMessage); +} + +/// Represents a client's subscription to an event. +/// +/// Also provides a means to fire an event. +abstract class Subscription { + /// A unique identifier for this subscription. + String get id; + + /// The ID of the client who requested this subscription. + String get clientId; + + /// Alerts a client of an event. + void dispatch(event); +}.3%4>Q#.$5'6B.$4,1<#qfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/authentication_challenge.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'package:string_scanner/string_scanner.dart'; + +import 'case_insensitive_map.dart'; +import 'scan.dart'; +import 'utils.dart'; + +/// A single challenge in a WWW-Authenticate header, parsed as per [RFC 2617][]. +/// +/// [RFC 2617]: http://tools.ietf.org/html/rfc2617 +/// +/// Each WWW-Authenticate header contains one or more challenges, representing +/// valid ways to authenticate with the server. +class AuthenticationChallenge { + /// The scheme describing the type of authentication that's required, for + /// example "basic" or "digest". + /// + /// This is normalized to always be lower-case. + final String scheme; + + /// The parameters describing how to authenticate. + /// + /// The semantics of these parameters are scheme-specific. The keys of this + /// map are case-insensitive. + final Map parameters; + + /// Parses a WWW-Authenticate header, which should contain one or more + /// challenges. + /// + /// Throws a [FormatException] if the header is invalid. + static List parseHeader(String header) { + return wrapFormatException("authentication header", header, () { + var scanner = new StringScanner(header); + scanner.scan(whitespace); + var challenges = parseList(scanner, () { + var scheme = _scanScheme(scanner, whitespaceName: '" " or "="'); + + // Manually parse the inner list. We need to do some lookahead to + // disambiguate between an auth param and another challenge. + var params = {}; + + // Consume initial empty values. + while (scanner.scan(",")) { + scanner.scan(whitespace); + } + + _scanAuthParam(scanner, params); + + var beforeComma = scanner.position; + while (scanner.scan(",")) { + scanner.scan(whitespace); + + // Empty elements are allowed, but excluded from the results. + if (scanner.matches(",") || scanner.isDone) continue; + + scanner.expect(token, name: "a token"); + var name = scanner.lastMatch[0]; + scanner.scan(whitespace); + + // If there's no "=", then this is another challenge rather than a + // parameter for the current challenge. + if (!scanner.scan('=')) { + scanner.position = beforeComma; + break; + } + + scanner.scan(whitespace); + + if (scanner.scan(token)) { + params[name] = scanner.lastMatch[0]; + } else { + params[name] = + expectQuotedString(scanner, name: "a token or a quoted string"); + } + + scanner.scan(whitespace); + beforeComma = scanner.position; + } + + return new AuthenticationChallenge(scheme, params); + }); + + scanner.expectDone(); + return challenges; + }); + } + + /// Parses a single WWW-Authenticate challenge value. + /// + /// Throws a [FormatException] if the challenge is invalid. + factory AuthenticationChallenge.parse(String challenge) { + return wrapFormatException("authentication challenge", challenge, () { + var scanner = new StringScanner(challenge); + scanner.scan(whitespace); + var scheme = _scanScheme(scanner); + + var params = {}; + parseList(scanner, () => _scanAuthParam(scanner, params)); + + scanner.expectDone(); + return new AuthenticationChallenge(scheme, params); + }); + } + + /// Scans a single scheme name and asserts that it's followed by a space. + /// + /// If [whitespaceName] is passed, it's used as the name for exceptions thrown + /// due to invalid trailing whitespace. + static String _scanScheme(StringScanner scanner, {String whitespaceName}) { + scanner.expect(token, name: "a token"); + var scheme = scanner.lastMatch[0].toLowerCase(); + + scanner.scan(whitespace); + + // The spec specifically requires a space between the scheme and its + // params. + if (scanner.lastMatch == null || !scanner.lastMatch[0].contains(" ")) { + scanner.expect(" ", name: whitespaceName); + } + + return scheme; + } + + /// Scans a single authentication parameter and stores its result in [params]. + static void _scanAuthParam(StringScanner scanner, Map params) { + scanner.expect(token, name: "a token"); + var name = scanner.lastMatch[0]; + scanner.scan(whitespace); + scanner.expect('='); + scanner.scan(whitespace); + + if (scanner.scan(token)) { + params[name] = scanner.lastMatch[0]; + } else { + params[name] = + expectQuotedString(scanner, name: "a token or a quoted string"); + } + + scanner.scan(whitespace); + } + + /// Creates a new challenge value with [scheme] and [parameters]. + AuthenticationChallenge(this.scheme, Map parameters) + : parameters = + new UnmodifiableMapView(new CaseInsensitiveMap.from(parameters)); +} +NN<5$Q3O0 L#25N (I;DE/ /IJE))$$ +),$$H@2+$M2$, $%1Q $* +< +8> extends CanonicalizedMap { + CaseInsensitiveMap() + : super((key) => key.toLowerCase(), isValidKey: (key) => key != null); + + CaseInsensitiveMap.from(Map other) + : super.from(other, (key) => key.toLowerCase(), + isValidKey: (key) => key != null); +} +NN<-3MJM06/gfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/chunked_coding.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'chunked_coding/encoder.dart'; +import 'chunked_coding/decoder.dart'; + +export 'chunked_coding/encoder.dart' hide chunkedCodingEncoder; +export 'chunked_coding/decoder.dart' hide chunkedCodingDecoder; + +/// The canonical instance of [ChunkedCodingCodec]. +const chunkedCoding = const ChunkedCodingCodec._(); + +/// A codec that encodes and decodes the [chunked transfer coding][]. +/// +/// [chunked transfer coding]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1 +/// +/// The [encoder] creates a *single* chunked message for each call to +/// [ChunkedCodingEncoder.convert] or +/// [ChunkedCodingEncoder.startChunkedConversion]. This means that it will +/// always add an end-of-message footer once conversion has finished. It doesn't +/// support generating chunk extensions or trailing headers. +/// +/// Similarly, the [decoder] decodes a *single* chunked message into a stream of +/// byte arrays that must be concatenated to get the full list (like most Dart +/// byte streams). It doesn't support decoding a stream that contains multiple +/// chunked messages, nor does it support a stream that contains chunked data +/// mixed with other types of data. +/// +/// Currently, [decoder] will fail to parse chunk extensions and trailing +/// headers. It may be updated to silently ignore them in the future. +class ChunkedCodingCodec extends Codec, List> { + ChunkedCodingEncoder get encoder => chunkedCodingEncoder; + ChunkedCodingDecoder get decoder => chunkedCodingDecoder; + + const ChunkedCodingCodec._(); +} +)NN<&&@@44F_F&KQ=QOON$JF?<< bfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/http_date.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:string_scanner/string_scanner.dart'; + +import 'utils.dart'; + +const _WEEKDAYS = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; +const _MONTHS = const [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" +]; + +final _shortWeekdayRegExp = new RegExp(r"Mon|Tue|Wed|Thu|Fri|Sat|Sun"); +final _longWeekdayRegExp = + new RegExp(r"Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday"); +final _monthRegExp = + new RegExp(r"Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"); +final _digitRegExp = new RegExp(r"\d+"); + +/// Return a HTTP-formatted string representation of [date]. +/// +/// This follows [RFC 822](http://tools.ietf.org/html/rfc822) as updated by [RFC +/// 1123](http://tools.ietf.org/html/rfc1123). +String formatHttpDate(DateTime date) { + date = date.toUtc(); + var buffer = new StringBuffer() + ..write(_WEEKDAYS[date.weekday - 1]) + ..write(", ") + ..write(date.day <= 9 ? "0" : "") + ..write(date.day.toString()) + ..write(" ") + ..write(_MONTHS[date.month - 1]) + ..write(" ") + ..write(date.year.toString()) + ..write(date.hour <= 9 ? " 0" : " ") + ..write(date.hour.toString()) + ..write(date.minute <= 9 ? ":0" : ":") + ..write(date.minute.toString()) + ..write(date.second <= 9 ? ":0" : ":") + ..write(date.second.toString()) + ..write(" GMT"); + return buffer.toString(); +} + +/// Parses an HTTP-formatted date into a UTC [DateTime]. +/// +/// This follows [RFC +/// 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3). It will +/// throw a [FormatException] if [date] is invalid. +DateTime parseHttpDate(String date) { + return wrapFormatException("HTTP date", date, () { + var scanner = new StringScanner(date); + + if (scanner.scan(_longWeekdayRegExp)) { + // RFC 850 starts with a long weekday. + scanner.expect(", "); + var day = _parseInt(scanner, 2); + scanner.expect("-"); + var month = _parseMonth(scanner); + scanner.expect("-"); + var year = 1900 + _parseInt(scanner, 2); + scanner.expect(" "); + var time = _parseTime(scanner); + scanner.expect(" GMT"); + scanner.expectDone(); + + return _makeDateTime(year, month, day, time); + } + + // RFC 1123 and asctime both start with a short weekday. + scanner.expect(_shortWeekdayRegExp); + if (scanner.scan(", ")) { + // RFC 1123 follows the weekday with a comma. + var day = _parseInt(scanner, 2); + scanner.expect(" "); + var month = _parseMonth(scanner); + scanner.expect(" "); + var year = _parseInt(scanner, 4); + scanner.expect(" "); + var time = _parseTime(scanner); + scanner.expect(" GMT"); + scanner.expectDone(); + + return _makeDateTime(year, month, day, time); + } + + // asctime follows the weekday with a space. + scanner.expect(" "); + var month = _parseMonth(scanner); + scanner.expect(" "); + var day = scanner.scan(" ") ? _parseInt(scanner, 1) : _parseInt(scanner, 2); + scanner.expect(" "); + var time = _parseTime(scanner); + scanner.expect(" "); + var year = _parseInt(scanner, 4); + scanner.expectDone(); + + return _makeDateTime(year, month, day, time); + }); +} + +/// Parses a short-form month name to a form accepted by [DateTime]. +int _parseMonth(StringScanner scanner) { + scanner.expect(_monthRegExp); + // DateTime uses 1-indexed months. + return _MONTHS.indexOf(scanner.lastMatch[0]) + 1; +} + +/// Parses an int an enforces that it has exactly [digits] digits. +int _parseInt(StringScanner scanner, int digits) { + scanner.expect(_digitRegExp); + if (scanner.lastMatch[0].length != digits) { + scanner.error("expected a $digits-digit number."); + } + + return int.parse(scanner.lastMatch[0]); +} + +/// Parses an timestamp of the form "HH:MM:SS" on a 24-hour clock. +DateTime _parseTime(StringScanner scanner) { + var hours = _parseInt(scanner, 2); + if (hours >= 24) scanner.error("hours may not be greater than 24."); + scanner.expect(':'); + + var minutes = _parseInt(scanner, 2); + if (minutes >= 60) scanner.error("minutes may not be greater than 60."); + scanner.expect(':'); + + var seconds = _parseInt(scanner, 2); + if (seconds >= 60) scanner.error("seconds may not be greater than 60."); + + return new DateTime(1, 1, 1, hours, minutes, seconds); +} + +/// Returns a UTC [DateTime] from the given components. +/// +/// Validates that [day] is a valid day for [month]. If it's not, throws a +/// [FormatException]. +DateTime _makeDateTime(int year, int month, int day, DateTime time) { + var dateTime = + new DateTime.utc(year, month, day, time.hour, time.minute, time.second); + + // If [day] was too large, it will cause [month] to overflow. + if (dateTime.month != month) { + throw new FormatException("invalid day '$day' for month '$month'."); + } + return dateTime; +} +NN<5K HMD)=Q/'")&!%")"+$+$9Q4&5+,-'(/&4=)4'((&41&Q$&2E) %4C3 /7*C-%G'K'K98KFO@!Icfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/media_type.darte// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:collection/collection.dart'; +import 'package:string_scanner/string_scanner.dart'; + +import 'case_insensitive_map.dart'; +import 'scan.dart'; +import 'utils.dart'; + +/// A regular expression matching a character that needs to be backslash-escaped +/// in a quoted string. +final _escapedChar = new RegExp(r'["\x00-\x1F\x7F]'); + +/// A class representing an HTTP media type, as used in Accept and Content-Type +/// headers. +/// +/// This is immutable; new instances can be created based on an old instance by +/// calling [change]. +class MediaType { + /// The primary identifier of the MIME type. + /// + /// This is always lowercase. + final String type; + + /// The secondary identifier of the MIME type. + /// + /// This is always lowercase. + final String subtype; + + /// The parameters to the media type. + /// + /// This map is immutable and the keys are case-insensitive. + final Map parameters; + + /// The media type's MIME type. + String get mimeType => "$type/$subtype"; + + /// Parses a media type. + /// + /// This will throw a FormatError if the media type is invalid. + factory MediaType.parse(String mediaType) { + // This parsing is based on sections 3.6 and 3.7 of the HTTP spec: + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html. + return wrapFormatException("media type", mediaType, () { + var scanner = new StringScanner(mediaType); + scanner.scan(whitespace); + scanner.expect(token); + var type = scanner.lastMatch[0]; + scanner.expect('/'); + scanner.expect(token); + var subtype = scanner.lastMatch[0]; + scanner.scan(whitespace); + + var parameters = {}; + while (scanner.scan(';')) { + scanner.scan(whitespace); + scanner.expect(token); + var attribute = scanner.lastMatch[0]; + scanner.expect('='); + + String value; + if (scanner.scan(token)) { + value = scanner.lastMatch[0]; + } else { + value = expectQuotedString(scanner); + } + + scanner.scan(whitespace); + parameters[attribute] = value; + } + + scanner.expectDone(); + return new MediaType(type, subtype, parameters); + }); + } + + MediaType(String type, String subtype, [Map parameters]) + : type = type.toLowerCase(), + subtype = subtype.toLowerCase(), + parameters = new UnmodifiableMapView( + parameters == null ? {} : new CaseInsensitiveMap.from(parameters)); + + /// Returns a copy of this [MediaType] with some fields altered. + /// + /// [type] and [subtype] alter the corresponding fields. [mimeType] is parsed + /// and alters both the [type] and [subtype] fields; it cannot be passed along + /// with [type] or [subtype]. + /// + /// [parameters] overwrites and adds to the corresponding field. If + /// [clearParameters] is passed, it replaces the corresponding field entirely + /// instead. + MediaType change( + {String type, + String subtype, + String mimeType, + Map parameters, + bool clearParameters: false}) { + if (mimeType != null) { + if (type != null) { + throw new ArgumentError("You may not pass both [type] and [mimeType]."); + } else if (subtype != null) { + throw new ArgumentError("You may not pass both [subtype] and " + "[mimeType]."); + } + + var segments = mimeType.split('/'); + if (segments.length != 2) { + throw new FormatException('Invalid mime type "$mimeType".'); + } + + type = segments[0]; + subtype = segments[1]; + } + + if (type == null) type = this.type; + if (subtype == null) subtype = this.subtype; + if (parameters == null) parameters = {}; + + if (!clearParameters) { + var newParameters = parameters; + parameters = new Map.from(this.parameters); + parameters.addAll(newParameters); + } + + return new MediaType(type, subtype, parameters); + } + + /// Converts the media type to a string. + /// + /// This will produce a valid HTTP media type. + String toString() { + var buffer = new StringBuffer()..write(type)..write("/")..write(subtype); + + parameters.forEach((attribute, value) { + buffer.write("; $attribute="); + if (nonToken.hasMatch(value)) { + buffer + ..write('"') + ..write( + value.replaceAllMapped(_escapedChar, (match) => "\\" + match[0])) + ..write('"'); + } else { + buffer.write(value); + } + }); + + return buffer.toString(); + } +} +NN<-5$Q6P P/ 1 (?("+B.G>=2 '* +"".#(/ +"'7K#).PCPQ FP&&Q$G*"E(1-&2(5+1N,%&PYfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/context.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:math' as math; + +import 'characters.dart' as chars; +import 'internal_style.dart'; +import 'style.dart'; +import 'parsed_path.dart'; +import 'path_exception.dart'; +import '../path.dart' as p; + +Context createInternal() => new Context._internal(); + +/// An instantiable class for manipulating paths. Unlike the top-level +/// functions, this lets you explicitly select what platform the paths will use. +class Context { + /// Creates a new path context for the given style and current directory. + /// + /// If [style] is omitted, it uses the host operating system's path style. If + /// only [current] is omitted, it defaults ".". If *both* [style] and + /// [current] are omitted, [current] defaults to the real current working + /// directory. + /// + /// On the browser, [style] defaults to [Style.url] and [current] defaults to + /// the current URL. + factory Context({Style style, String current}) { + if (current == null) { + if (style == null) { + current = p.current; + } else { + current = "."; + } + } + + if (style == null) { + style = Style.platform; + } else if (style is! InternalStyle) { + throw new ArgumentError("Only styles defined by the path package are " + "allowed."); + } + + return new Context._(style as InternalStyle, current); + } + + /// Create a [Context] to be used internally within path. + Context._internal() + : style = Style.platform as InternalStyle, + _current = null; + + Context._(this.style, this._current); + + /// The style of path that this context works with. + final InternalStyle style; + + /// The current directory given when Context was created. If null, current + /// directory is evaluated from 'p.current'. + final String _current; + + /// The current directory that relative paths are relative to. + String get current => _current != null ? _current : p.current; + + /// Gets the path separator for the context's [style]. On Mac and Linux, + /// this is `/`. On Windows, it's `\`. + String get separator => style.separator; + + /// Creates a new path by appending the given path parts to [current]. + /// Equivalent to [join()] with [current] as the first argument. Example: + /// + /// var context = new Context(current: '/root'); + /// context.absolute('path', 'to', 'foo'); // -> '/root/path/to/foo' + /// + /// If [current] isn't absolute, this won't return an absolute path. + String absolute(String part1, + [String part2, + String part3, + String part4, + String part5, + String part6, + String part7]) { + _validateArgList( + "absolute", [part1, part2, part3, part4, part5, part6, part7]); + + // If there's a single absolute path, just return it. This is a lot faster + // for the common case of `p.absolute(path)`. + if (part2 == null && isAbsolute(part1) && !isRootRelative(part1)) { + return part1; + } + + return join(current, part1, part2, part3, part4, part5, part6, part7); + } + + /// Gets the part of [path] after the last separator on the context's + /// platform. + /// + /// context.basename('path/to/foo.dart'); // -> 'foo.dart' + /// context.basename('path/to'); // -> 'to' + /// + /// Trailing separators are ignored. + /// + /// context.basename('path/to/'); // -> 'to' + String basename(String path) => _parse(path).basename; + + /// Gets the part of [path] after the last separator on the context's + /// platform, and without any trailing file extension. + /// + /// context.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' + /// + /// Trailing separators are ignored. + /// + /// context.basenameWithoutExtension('path/to/foo.dart/'); // -> 'foo' + String basenameWithoutExtension(String path) => + _parse(path).basenameWithoutExtension; + + /// Gets the part of [path] before the last separator. + /// + /// context.dirname('path/to/foo.dart'); // -> 'path/to' + /// context.dirname('path/to'); // -> 'path' + /// + /// Trailing separators are ignored. + /// + /// context.dirname('path/to/'); // -> 'path' + String dirname(String path) { + var parsed = _parse(path); + parsed.removeTrailingSeparators(); + if (parsed.parts.isEmpty) return parsed.root == null ? '.' : parsed.root; + if (parsed.parts.length == 1) { + return parsed.root == null ? '.' : parsed.root; + } + parsed.parts.removeLast(); + parsed.separators.removeLast(); + parsed.removeTrailingSeparators(); + return parsed.toString(); + } + + /// Gets the file extension of [path]: the portion of [basename] from the last + /// `.` to the end (including the `.` itself). + /// + /// context.extension('path/to/foo.dart'); // -> '.dart' + /// context.extension('path/to/foo'); // -> '' + /// context.extension('path.to/foo'); // -> '' + /// context.extension('path/to/foo.dart.js'); // -> '.js' + /// + /// If the file name starts with a `.`, then it is not considered an + /// extension: + /// + /// context.extension('~/.bashrc'); // -> '' + /// context.extension('~/.notes.txt'); // -> '.txt' + String extension(String path) => _parse(path).extension; + + // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. + /// Returns the root of [path] if it's absolute, or an empty string if it's + /// relative. + /// + /// // Unix + /// context.rootPrefix('path/to/foo'); // -> '' + /// context.rootPrefix('/path/to/foo'); // -> '/' + /// + /// // Windows + /// context.rootPrefix(r'path\to\foo'); // -> '' + /// context.rootPrefix(r'C:\path\to\foo'); // -> r'C:\' + /// + /// // URL + /// context.rootPrefix('path/to/foo'); // -> '' + /// context.rootPrefix('http://dartlang.org/path/to/foo'); + /// // -> 'http://dartlang.org' + String rootPrefix(String path) => path.substring(0, style.rootLength(path)); + + /// Returns `true` if [path] is an absolute path and `false` if it is a + /// relative path. + /// + /// On POSIX systems, absolute paths start with a `/` (forward slash). On + /// Windows, an absolute path starts with `\\`, or a drive letter followed by + /// `:/` or `:\`. For URLs, absolute paths either start with a protocol and + /// optional hostname (e.g. `http://dartlang.org`, `file://`) or with a `/`. + /// + /// URLs that start with `/` are known as "root-relative", since they're + /// relative to the root of the current URL. Since root-relative paths are + /// still absolute in every other sense, [isAbsolute] will return true for + /// them. They can be detected using [isRootRelative]. + bool isAbsolute(String path) => style.rootLength(path) > 0; + + /// Returns `true` if [path] is a relative path and `false` if it is absolute. + /// On POSIX systems, absolute paths start with a `/` (forward slash). On + /// Windows, an absolute path starts with `\\`, or a drive letter followed by + /// `:/` or `:\`. + bool isRelative(String path) => !this.isAbsolute(path); + + /// Returns `true` if [path] is a root-relative path and `false` if it's not. + /// + /// URLs that start with `/` are known as "root-relative", since they're + /// relative to the root of the current URL. Since root-relative paths are + /// still absolute in every other sense, [isAbsolute] will return true for + /// them. They can be detected using [isRootRelative]. + /// + /// No POSIX and Windows paths are root-relative. + bool isRootRelative(String path) => style.isRootRelative(path); + + /// Joins the given path parts into a single path. Example: + /// + /// context.join('path', 'to', 'foo'); // -> 'path/to/foo' + /// + /// If any part ends in a path separator, then a redundant separator will not + /// be added: + /// + /// context.join('path/', 'to', 'foo'); // -> 'path/to/foo + /// + /// If a part is an absolute path, then anything before that will be ignored: + /// + /// context.join('path', '/to', 'foo'); // -> '/to/foo' + /// + String join(String part1, + [String part2, + String part3, + String part4, + String part5, + String part6, + String part7, + String part8]) { + var parts = [ + part1, + part2, + part3, + part4, + part5, + part6, + part7, + part8 + ]; + _validateArgList("join", parts); + return joinAll(parts.where((part) => part != null)); + } + + /// Joins the given path parts into a single path. Example: + /// + /// context.joinAll(['path', 'to', 'foo']); // -> 'path/to/foo' + /// + /// If any part ends in a path separator, then a redundant separator will not + /// be added: + /// + /// context.joinAll(['path/', 'to', 'foo']); // -> 'path/to/foo + /// + /// If a part is an absolute path, then anything before that will be ignored: + /// + /// context.joinAll(['path', '/to', 'foo']); // -> '/to/foo' + /// + /// For a fixed number of parts, [join] is usually terser. + String joinAll(Iterable parts) { + var buffer = new StringBuffer(); + var needsSeparator = false; + var isAbsoluteAndNotRootRelative = false; + + for (var part in parts.where((part) => part != '')) { + if (this.isRootRelative(part) && isAbsoluteAndNotRootRelative) { + // If the new part is root-relative, it preserves the previous root but + // replaces the path after it. + var parsed = _parse(part); + var path = buffer.toString(); + parsed.root = + path.substring(0, style.rootLength(path, withDrive: true)); + if (style.needsSeparator(parsed.root)) { + parsed.separators[0] = style.separator; + } + buffer.clear(); + buffer.write(parsed.toString()); + } else if (this.isAbsolute(part)) { + isAbsoluteAndNotRootRelative = !this.isRootRelative(part); + // An absolute path discards everything before it. + buffer.clear(); + buffer.write(part); + } else { + if (part.length > 0 && style.containsSeparator(part[0])) { + // The part starts with a separator, so we don't need to add one. + } else if (needsSeparator) { + buffer.write(separator); + } + + buffer.write(part); + } + + // Unless this part ends with a separator, we'll need to add one before + // the next part. + needsSeparator = style.needsSeparator(part); + } + + return buffer.toString(); + } + + // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. + /// Splits [path] into its components using the current platform's + /// [separator]. Example: + /// + /// context.split('path/to/foo'); // -> ['path', 'to', 'foo'] + /// + /// The path will *not* be normalized before splitting. + /// + /// context.split('path/../foo'); // -> ['path', '..', 'foo'] + /// + /// If [path] is absolute, the root directory will be the first element in the + /// array. Example: + /// + /// // Unix + /// context.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo'] + /// + /// // Windows + /// context.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo'] + List split(String path) { + var parsed = _parse(path); + // Filter out empty parts that exist due to multiple separators in a row. + parsed.parts = parsed.parts.where((part) => !part.isEmpty).toList(); + if (parsed.root != null) parsed.parts.insert(0, parsed.root); + return parsed.parts; + } + + /// Canonicalizes [path]. + /// + /// This is guaranteed to return the same path for two different input paths + /// if and only if both input paths point to the same location. Unlike + /// [normalize], it returns absolute paths when possible and canonicalizes + /// ASCII case on Windows. + /// + /// Note that this does not resolve symlinks. + /// + /// If you want a map that uses path keys, it's probably more efficient to + /// pass [equals] and [hash] to [new HashMap] than it is to canonicalize every + /// key. + String canonicalize(String path) { + path = absolute(path); + if (style != Style.windows && !_needsNormalization(path)) return path; + + var parsed = _parse(path); + parsed.normalize(canonicalize: true); + return parsed.toString(); + } + + /// Normalizes [path], simplifying it by handling `..`, and `.`, and + /// removing redundant path separators whenever possible. + /// + /// Note that this is *not* guaranteed to return the same result for two + /// equivalent input paths. For that, see [canonicalize]. Or, if you're using + /// paths as map keys, pass [equals] and [hash] to [new HashMap]. + /// + /// context.normalize('path/./to/..//file.text'); // -> 'path/file.txt' + String normalize(String path) { + if (!_needsNormalization(path)) return path; + + var parsed = _parse(path); + parsed.normalize(); + return parsed.toString(); + } + + /// Returns whether [path] needs to be normalized. + bool _needsNormalization(String path) { + var start = 0; + var codeUnits = path.codeUnits; + int previousPrevious; + int previous; + + // Skip past the root before we start looking for snippets that need + // normalization. We want to normalize "//", but not when it's part of + // "http://". + var root = style.rootLength(path); + if (root != 0) { + start = root; + previous = chars.SLASH; + + // On Windows, the root still needs to be normalized if it contains a + // forward slash. + if (style == Style.windows) { + for (var i = 0; i < root; i++) { + if (codeUnits[i] == chars.SLASH) return true; + } + } + } + + for (var i = start; i < codeUnits.length; i++) { + var codeUnit = codeUnits[i]; + if (style.isSeparator(codeUnit)) { + // Forward slashes in Windows paths are normalized to backslashes. + if (style == Style.windows && codeUnit == chars.SLASH) return true; + + // Multiple separators are normalized to single separators. + if (previous != null && style.isSeparator(previous)) return true; + + // Single dots and double dots are normalized to directory traversals. + // + // This can return false positives for ".../", but that's unlikely + // enough that it's probably not going to cause performance issues. + if (previous == chars.PERIOD && + (previousPrevious == null || + previousPrevious == chars.PERIOD || + style.isSeparator(previousPrevious))) { + return true; + } + } + + previousPrevious = previous; + previous = codeUnit; + } + + // Empty paths are normalized to ".". + if (previous == null) return true; + + // Trailing separators are removed. + if (style.isSeparator(previous)) return true; + + // Single dots and double dots are normalized to directory traversals. + if (previous == chars.PERIOD && + (previousPrevious == null || + style.isSeparator(previousPrevious) || + previousPrevious == chars.PERIOD)) { + return true; + } + + return false; + } + + /// Attempts to convert [path] to an equivalent relative path relative to + /// [root]. + /// + /// var context = new Context(current: '/root/path'); + /// context.relative('/root/path/a/b.dart'); // -> 'a/b.dart' + /// context.relative('/root/other.dart'); // -> '../other.dart' + /// + /// If the [from] argument is passed, [path] is made relative to that instead. + /// + /// context.relative('/root/path/a/b.dart', + /// from: '/root/path'); // -> 'a/b.dart' + /// context.relative('/root/other.dart', + /// from: '/root/path'); // -> '../other.dart' + /// + /// If [path] and/or [from] are relative paths, they are assumed to be + /// relative to [current]. + /// + /// Since there is no relative path from one drive letter to another on + /// Windows, this will return an absolute path in that case. + /// + /// context.relative(r'D:\other', from: r'C:\other'); // -> 'D:\other' + /// + /// This will also return an absolute path if an absolute [path] is passed to + /// a context with a relative path for [current]. + /// + /// var context = new Context(r'some/relative/path'); + /// context.relative(r'/absolute/path'); // -> '/absolute/path' + /// + /// If [root] is relative, it may be impossible to determine a path from + /// [from] to [path]. For example, if [root] and [path] are "." and [from] is + /// "/", no path can be determined. In this case, a [PathException] will be + /// thrown. + String relative(String path, {String from}) { + // Avoid expensive computation if the path is already relative. + if (from == null && this.isRelative(path)) return this.normalize(path); + + from = from == null ? current : absolute(from); + + // We can't determine the path from a relative path to an absolute path. + if (this.isRelative(from) && this.isAbsolute(path)) { + return this.normalize(path); + } + + // If the given path is relative, resolve it relative to the context's + // current directory. + if (this.isRelative(path) || this.isRootRelative(path)) { + path = this.absolute(path); + } + + // If the path is still relative and `from` is absolute, we're unable to + // find a path from `from` to `path`. + if (this.isRelative(path) && this.isAbsolute(from)) { + throw new PathException('Unable to find a path to "$path" from "$from".'); + } + + var fromParsed = _parse(from)..normalize(); + var pathParsed = _parse(path)..normalize(); + + if (fromParsed.parts.length > 0 && fromParsed.parts[0] == '.') { + return pathParsed.toString(); + } + + // If the root prefixes don't match (for example, different drive letters + // on Windows), then there is no relative path, so just return the absolute + // one. In Windows, drive letters are case-insenstive and we allow + // calculation of relative paths, even if a path has not been normalized. + if (fromParsed.root != pathParsed.root && + ((fromParsed.root == null || pathParsed.root == null) || + !style.pathsEqual(fromParsed.root, pathParsed.root))) { + return pathParsed.toString(); + } + + // Strip off their common prefix. + while (fromParsed.parts.length > 0 && + pathParsed.parts.length > 0 && + style.pathsEqual(fromParsed.parts[0], pathParsed.parts[0])) { + fromParsed.parts.removeAt(0); + fromParsed.separators.removeAt(1); + pathParsed.parts.removeAt(0); + pathParsed.separators.removeAt(1); + } + + // If there are any directories left in the from path, we need to walk up + // out of them. If a directory left in the from path is '..', it cannot + // be cancelled by adding a '..'. + if (fromParsed.parts.length > 0 && fromParsed.parts[0] == '..') { + throw new PathException('Unable to find a path to "$path" from "$from".'); + } + pathParsed.parts + .insertAll(0, new List.filled(fromParsed.parts.length, '..')); + pathParsed.separators[0] = ''; + pathParsed.separators.insertAll( + 1, new List.filled(fromParsed.parts.length, style.separator)); + + // Corner case: the paths completely collapsed. + if (pathParsed.parts.length == 0) return '.'; + + // Corner case: path was '.' and some '..' directories were added in front. + // Don't add a final '/.' in that case. + if (pathParsed.parts.length > 1 && pathParsed.parts.last == '.') { + pathParsed.parts.removeLast(); + pathParsed.separators + ..removeLast() + ..removeLast() + ..add(''); + } + + // Make it relative. + pathParsed.root = ''; + pathParsed.removeTrailingSeparators(); + + return pathParsed.toString(); + } + + /// Returns `true` if [child] is a path beneath `parent`, and `false` + /// otherwise. + /// + /// path.isWithin('/root/path', '/root/path/a'); // -> true + /// path.isWithin('/root/path', '/root/other'); // -> false + /// path.isWithin('/root/path', '/root/path'); // -> false + bool isWithin(String parent, String child) => + _isWithinOrEquals(parent, child) == _PathRelation.within; + + /// Returns `true` if [path1] points to the same location as [path2], and + /// `false` otherwise. + /// + /// The [hash] function returns a hash code that matches these equality + /// semantics. + bool equals(String path1, String path2) => + _isWithinOrEquals(path1, path2) == _PathRelation.equal; + + /// Compares two paths and returns an enum value indicating their relationship + /// to one another. + /// + /// This never returns [_PathRelation.inconclusive]. + _PathRelation _isWithinOrEquals(String parent, String child) { + // Make both paths the same level of relative. We're only able to do the + // quick comparison if both paths are in the same format, and making a path + // absolute is faster than making it relative. + var parentIsAbsolute = isAbsolute(parent); + var childIsAbsolute = isAbsolute(child); + if (parentIsAbsolute && !childIsAbsolute) { + child = absolute(child); + if (style.isRootRelative(parent)) parent = absolute(parent); + } else if (childIsAbsolute && !parentIsAbsolute) { + parent = absolute(parent); + if (style.isRootRelative(child)) child = absolute(child); + } else if (childIsAbsolute && parentIsAbsolute) { + var childIsRootRelative = style.isRootRelative(child); + var parentIsRootRelative = style.isRootRelative(parent); + + if (childIsRootRelative && !parentIsRootRelative) { + child = absolute(child); + } else if (parentIsRootRelative && !childIsRootRelative) { + parent = absolute(parent); + } + } + + var result = _isWithinOrEqualsFast(parent, child); + if (result != _PathRelation.inconclusive) return result; + + String relative; + try { + relative = this.relative(child, from: parent); + } on PathException catch (_) { + // If no relative path from [parent] to [child] is found, [child] + // definitely isn't a child of [parent]. + return _PathRelation.different; + } + + if (!this.isRelative(relative)) return _PathRelation.different; + if (relative == '.') return _PathRelation.equal; + if (relative == '..') return _PathRelation.different; + return (relative.length >= 3 && + relative.startsWith('..') && + style.isSeparator(relative.codeUnitAt(2))) + ? _PathRelation.different + : _PathRelation.within; + } + + /// An optimized implementation of [_isWithinOrEquals] that doesn't handle a + /// few complex cases. + _PathRelation _isWithinOrEqualsFast(String parent, String child) { + // Normally we just bail when we see "." path components, but we can handle + // a single dot easily enough. + if (parent == '.') parent = ''; + + var parentRootLength = style.rootLength(parent); + var childRootLength = style.rootLength(child); + + // If the roots aren't the same length, we know both paths are absolute or + // both are root-relative, and thus that the roots are meaningfully + // different. + // + // isWithin("C:/bar", "//foo/bar/baz") //=> false + // isWithin("http://example.com/", "http://google.com/bar") //=> false + if (parentRootLength != childRootLength) return _PathRelation.different; + + // Make sure that the roots are textually the same as well. + // + // isWithin("C:/bar", "D:/bar/baz") //=> false + // isWithin("http://example.com/", "http://example.org/bar") //=> false + for (var i = 0; i < parentRootLength; i++) { + var parentCodeUnit = parent.codeUnitAt(i); + var childCodeUnit = child.codeUnitAt(i); + if (!style.codeUnitsEqual(parentCodeUnit, childCodeUnit)) { + return _PathRelation.different; + } + } + + // Start by considering the last code unit as a separator, since + // semantically we're starting at a new path component even if we're + // comparing relative paths. + var lastCodeUnit = chars.SLASH; + + /// The index of the last separator in [parent]. + int lastParentSeparator; + + // Iterate through both paths as long as they're semantically identical. + var parentIndex = parentRootLength; + var childIndex = childRootLength; + while (parentIndex < parent.length && childIndex < child.length) { + var parentCodeUnit = parent.codeUnitAt(parentIndex); + var childCodeUnit = child.codeUnitAt(childIndex); + if (style.codeUnitsEqual(parentCodeUnit, childCodeUnit)) { + if (style.isSeparator(parentCodeUnit)) { + lastParentSeparator = parentIndex; + } + + lastCodeUnit = parentCodeUnit; + parentIndex++; + childIndex++; + continue; + } + + // Ignore multiple separators in a row. + if (style.isSeparator(parentCodeUnit) && + style.isSeparator(lastCodeUnit)) { + lastParentSeparator = parentIndex; + parentIndex++; + continue; + } else if (style.isSeparator(childCodeUnit) && + style.isSeparator(lastCodeUnit)) { + childIndex++; + continue; + } + + // If a dot comes after a separator, it may be a directory traversal + // operator. To check that, we need to know if it's followed by either + // "/" or "./". Otherwise, it's just a normal non-matching character. + // + // isWithin("foo/./bar", "foo/bar/baz") //=> true + // isWithin("foo/bar/../baz", "foo/bar/.foo") //=> false + if (parentCodeUnit == chars.PERIOD && style.isSeparator(lastCodeUnit)) { + parentIndex++; + + // We've hit "/." at the end of the parent path, which we can ignore, + // since the paths were equivalent up to this point. + if (parentIndex == parent.length) break; + parentCodeUnit = parent.codeUnitAt(parentIndex); + + // We've hit "/./", which we can ignore. + if (style.isSeparator(parentCodeUnit)) { + lastParentSeparator = parentIndex; + parentIndex++; + continue; + } + + // We've hit "/..", which may be a directory traversal operator that + // we can't handle on the fast track. + if (parentCodeUnit == chars.PERIOD) { + parentIndex++; + if (parentIndex == parent.length || + style.isSeparator(parent.codeUnitAt(parentIndex))) { + return _PathRelation.inconclusive; + } + } + + // If this isn't a directory traversal, fall through so we hit the + // normal handling for mismatched paths. + } + + // This is the same logic as above, but for the child path instead of the + // parent. + if (childCodeUnit == chars.PERIOD && style.isSeparator(lastCodeUnit)) { + childIndex++; + if (childIndex == child.length) break; + childCodeUnit = child.codeUnitAt(childIndex); + + if (style.isSeparator(childCodeUnit)) { + childIndex++; + continue; + } + + if (childCodeUnit == chars.PERIOD) { + childIndex++; + if (childIndex == child.length || + style.isSeparator(child.codeUnitAt(childIndex))) { + return _PathRelation.inconclusive; + } + } + } + + // If we're here, we've hit two non-matching, non-significant characters. + // As long as the remainders of the two paths don't have any unresolved + // ".." components, we can be confident that [child] is not within + // [parent]. + var childDirection = _pathDirection(child, childIndex); + if (childDirection != _PathDirection.belowRoot) { + return _PathRelation.inconclusive; + } + + var parentDirection = _pathDirection(parent, parentIndex); + if (parentDirection != _PathDirection.belowRoot) { + return _PathRelation.inconclusive; + } + + return _PathRelation.different; + } + + // If the child is shorter than the parent, it's probably not within the + // parent. The only exception is if the parent has some weird ".." stuff + // going on, in which case we do the slow check. + // + // isWithin("foo/bar/baz", "foo/bar") //=> false + // isWithin("foo/bar/baz/../..", "foo/bar") //=> true + if (childIndex == child.length) { + if (parentIndex == parent.length || + style.isSeparator(parent.codeUnitAt(parentIndex))) { + lastParentSeparator = parentIndex; + } else { + lastParentSeparator ??= math.max(0, parentRootLength - 1); + } + + var direction = + _pathDirection(parent, lastParentSeparator ?? parentRootLength - 1); + if (direction == _PathDirection.atRoot) return _PathRelation.equal; + return direction == _PathDirection.aboveRoot + ? _PathRelation.inconclusive + : _PathRelation.different; + } + + // We've reached the end of the parent path, which means it's time to make a + // decision. Before we do, though, we'll check the rest of the child to see + // what that tells us. + var direction = _pathDirection(child, childIndex); + + // If there are no more components in the child, then it's the same as + // the parent. + // + // isWithin("foo/bar", "foo/bar") //=> false + // isWithin("foo/bar", "foo/bar//") //=> false + // equals("foo/bar", "foo/bar") //=> true + // equals("foo/bar", "foo/bar//") //=> true + if (direction == _PathDirection.atRoot) return _PathRelation.equal; + + // If there are unresolved ".." components in the child, no decision we make + // will be valid. We'll abort and do the slow check instead. + // + // isWithin("foo/bar", "foo/bar/..") //=> false + // isWithin("foo/bar", "foo/bar/baz/bang/../../..") //=> false + // isWithin("foo/bar", "foo/bar/baz/bang/../../../bar/baz") //=> true + if (direction == _PathDirection.aboveRoot) { + return _PathRelation.inconclusive; + } + + // The child is within the parent if and only if we're on a separator + // boundary. + // + // isWithin("foo/bar", "foo/bar/baz") //=> true + // isWithin("foo/bar/", "foo/bar/baz") //=> true + // isWithin("foo/bar", "foo/barbaz") //=> false + return (style.isSeparator(child.codeUnitAt(childIndex)) || + style.isSeparator(lastCodeUnit)) + ? _PathRelation.within + : _PathRelation.different; + } + + // Returns a [_PathDirection] describing the path represented by [codeUnits] + // starting at [index]. + // + // This ignores leading separators. + // + // pathDirection("foo") //=> below root + // pathDirection("foo/bar/../baz") //=> below root + // pathDirection("//foo/bar/baz") //=> below root + // pathDirection("/") //=> at root + // pathDirection("foo/..") //=> at root + // pathDirection("foo/../baz") //=> reaches root + // pathDirection("foo/../..") //=> above root + // pathDirection("foo/../../foo/bar/baz") //=> above root + _PathDirection _pathDirection(String path, int index) { + var depth = 0; + var reachedRoot = false; + var i = index; + while (i < path.length) { + // Ignore initial separators or doubled separators. + while (i < path.length && style.isSeparator(path.codeUnitAt(i))) { + i++; + } + + // If we're at the end, stop. + if (i == path.length) break; + + // Move through the path component to the next separator. + var start = i; + while (i < path.length && !style.isSeparator(path.codeUnitAt(i))) { + i++; + } + + // See if the path component is ".", "..", or a name. + if (i - start == 1 && path.codeUnitAt(start) == chars.PERIOD) { + // Don't change the depth. + } else if (i - start == 2 && + path.codeUnitAt(start) == chars.PERIOD && + path.codeUnitAt(start + 1) == chars.PERIOD) { + // ".." backs out a directory. + depth--; + + // If we work back beyond the root, stop. + if (depth < 0) break; + + // Record that we reached the root so we don't return + // [_PathDirection.belowRoot]. + if (depth == 0) reachedRoot = true; + } else { + // Step inside a directory. + depth++; + } + + // If we're at the end, stop. + if (i == path.length) break; + + // Move past the separator. + i++; + } + + if (depth < 0) return _PathDirection.aboveRoot; + if (depth == 0) return _PathDirection.atRoot; + if (reachedRoot) return _PathDirection.reachesRoot; + return _PathDirection.belowRoot; + } + + /// Returns a hash code for [path] that matches the semantics of [equals]. + /// + /// Note that the same path may have different hash codes in different + /// [Context]s. + int hash(String path) { + // Make [path] absolute to ensure that equivalent relative and absolute + // paths have the same hash code. + path = absolute(path); + + var result = _hashFast(path); + if (result != null) return result; + + var parsed = _parse(path); + parsed.normalize(); + return _hashFast(parsed.toString()); + } + + /// An optimized implementation of [hash] that doesn't handle internal `..` + /// components. + /// + /// This will handle `..` components that appear at the beginning of the path. + int _hashFast(String path) { + var hash = 4603; + var beginning = true; + var wasSeparator = true; + for (var i = 0; i < path.length; i++) { + var codeUnit = style.canonicalizeCodeUnit(path.codeUnitAt(i)); + + // Take advantage of the fact that collisions are allowed to ignore + // separators entirely. This lets us avoid worrying about cases like + // multiple trailing slashes. + if (style.isSeparator(codeUnit)) { + wasSeparator = true; + continue; + } + + if (codeUnit == chars.PERIOD && wasSeparator) { + // If a dot comes after a separator, it may be a directory traversal + // operator. To check that, we need to know if it's followed by either + // "/" or "./". Otherwise, it's just a normal character. + // + // hash("foo/./bar") == hash("foo/bar") + + // We've hit "/." at the end of the path, which we can ignore. + if (i + 1 == path.length) break; + + var next = path.codeUnitAt(i + 1); + + // We can just ignore "/./", since they don't affect the semantics of + // the path. + if (style.isSeparator(next)) continue; + + // If the path ends with "/.." or contains "/../", we need to + // canonicalize it before we can hash it. We make an exception for ".."s + // at the beginning of the path, since those may appear even in a + // canonicalized path. + if (!beginning && + next == chars.PERIOD && + (i + 2 == path.length || + style.isSeparator(path.codeUnitAt(i + 2)))) { + return null; + } + } + + // Make sure [hash] stays under 32 bits even after multiplication. + hash &= 0x3FFFFFF; + hash *= 33; + hash ^= codeUnit; + wasSeparator = false; + beginning = false; + } + return hash; + } + + /// Removes a trailing extension from the last part of [path]. + /// + /// context.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' + String withoutExtension(String path) { + var parsed = _parse(path); + + for (var i = parsed.parts.length - 1; i >= 0; i--) { + if (!parsed.parts[i].isEmpty) { + parsed.parts[i] = parsed.basenameWithoutExtension; + break; + } + } + + return parsed.toString(); + } + + /// Returns [path] with the trailing extension set to [extension]. + /// + /// If [path] doesn't have a trailing extension, this just adds [extension] to + /// the end. + /// + /// context.setExtension('path/to/foo.dart', '.js') + /// // -> 'path/to/foo.js' + /// context.setExtension('path/to/foo.dart.js', '.map') + /// // -> 'path/to/foo.dart.map' + /// context.setExtension('path/to/foo', '.js') + /// // -> 'path/to/foo.js' + String setExtension(String path, String extension) => + withoutExtension(path) + extension; + + /// Returns the path represented by [uri], which may be a [String] or a [Uri]. + /// + /// For POSIX and Windows styles, [uri] must be a `file:` URI. For the URL + /// style, this will just convert [uri] to a string. + /// + /// // POSIX + /// context.fromUri('file:///path/to/foo') + /// // -> '/path/to/foo' + /// + /// // Windows + /// context.fromUri('file:///C:/path/to/foo') + /// // -> r'C:\path\to\foo' + /// + /// // URL + /// context.fromUri('http://dartlang.org/path/to/foo') + /// // -> 'http://dartlang.org/path/to/foo' + /// + /// If [uri] is relative, a relative path will be returned. + /// + /// path.fromUri('path/to/foo'); // -> 'path/to/foo' + String fromUri(uri) => style.pathFromUri(_parseUri(uri)); + + /// Returns the URI that represents [path]. + /// + /// For POSIX and Windows styles, this will return a `file:` URI. For the URL + /// style, this will just convert [path] to a [Uri]. + /// + /// // POSIX + /// context.toUri('/path/to/foo') + /// // -> Uri.parse('file:///path/to/foo') + /// + /// // Windows + /// context.toUri(r'C:\path\to\foo') + /// // -> Uri.parse('file:///C:/path/to/foo') + /// + /// // URL + /// context.toUri('http://dartlang.org/path/to/foo') + /// // -> Uri.parse('http://dartlang.org/path/to/foo') + Uri toUri(String path) { + if (isRelative(path)) { + return style.relativePathToUri(path); + } else { + return style.absolutePathToUri(join(current, path)); + } + } + + /// Returns a terse, human-readable representation of [uri]. + /// + /// [uri] can be a [String] or a [Uri]. If it can be made relative to the + /// current working directory, that's done. Otherwise, it's returned as-is. + /// This gracefully handles non-`file:` URIs for [Style.posix] and + /// [Style.windows]. + /// + /// The returned value is meant for human consumption, and may be either URI- + /// or path-formatted. + /// + /// // POSIX + /// var context = new Context(current: '/root/path'); + /// context.prettyUri('file:///root/path/a/b.dart'); // -> 'a/b.dart' + /// context.prettyUri('http://dartlang.org/'); // -> 'http://dartlang.org' + /// + /// // Windows + /// var context = new Context(current: r'C:\root\path'); + /// context.prettyUri('file:///C:/root/path/a/b.dart'); // -> r'a\b.dart' + /// context.prettyUri('http://dartlang.org/'); // -> 'http://dartlang.org' + /// + /// // URL + /// var context = new Context(current: 'http://dartlang.org/root/path'); + /// context.prettyUri('http://dartlang.org/root/path/a/b.dart'); + /// // -> r'a/b.dart' + /// context.prettyUri('file:///root/path'); // -> 'file:///root/path' + String prettyUri(uri) { + var typedUri = _parseUri(uri); + if (typedUri.scheme == 'file' && style == Style.url) { + return typedUri.toString(); + } else if (typedUri.scheme != 'file' && + typedUri.scheme != '' && + style != Style.url) { + return typedUri.toString(); + } + + var path = normalize(fromUri(typedUri)); + var rel = relative(path); + + // Only return a relative path if it's actually shorter than the absolute + // path. This avoids ugly things like long "../" chains to get to the root + // and then go back down. + return split(rel).length > split(path).length ? path : rel; + } + + ParsedPath _parse(String path) => new ParsedPath.parse(path, style); +} + +/// Parses argument if it's a [String] or returns it intact if it's a [Uri]. +/// +/// Throws an [ArgumentError] otherwise. +Uri _parseUri(uri) { + if (uri is String) return Uri.parse(uri); + if (uri is Uri) return uri; + throw new ArgumentError.value(uri, 'uri', 'Value must be a String or a Uri'); +} + +/// Validates that there are no non-null arguments following a null one and +/// throws an appropriate [ArgumentError] on failure. +void _validateArgList(String method, List args) { + for (var i = 1; i < args.length; i++) { + // Ignore nulls hanging off the end. + if (args[i] == null || args[i - 1] != null) continue; + + int numArgs; + for (numArgs = args.length; numArgs >= 1; numArgs--) { + if (args[numArgs - 1] != null) break; + } + + // Show the arguments. + var message = new StringBuffer(); + message.write("$method("); + message.write(args + .take(numArgs) + .map((arg) => arg == null ? "null" : '"$arg"') + .join(", ")); + message.write("): part ${i - 1} was null, but part $i was not."); + throw new ArgumentError(message.toString()); + } +} + +/// An enum of possible return values for [Context._pathDirection]. +class _PathDirection { + /// The path contains enough ".." components that at some point it reaches + /// above its original root. + /// + /// Note that this applies even if the path ends beneath its original root. It + /// takes precendence over any other return values that may apple. + static const aboveRoot = const _PathDirection("above root"); + + /// The path contains enough ".." components that it ends at its original + /// root. + static const atRoot = const _PathDirection("at root"); + + /// The path contains enough ".." components that at some point it reaches its + /// original root, but it ends beneath that root. + static const reachesRoot = const _PathDirection("reaches root"); + + /// The path never reaches to or above its original root. + static const belowRoot = const _PathDirection("below root"); + + final String name; + + const _PathDirection(this.name); + + String toString() => name; +} + +/// An enum of possible return values for [Context._isWithinOrEquals]. +class _PathRelation { + /// The first path is a proper parent of the second. + /// + /// For example, `foo` is a proper parent of `foo/bar`, but not of `foo`. + static const within = const _PathRelation("within"); + + /// The two paths are equivalent. + /// + /// For example, `foo//bar` is equivalent to `foo/bar`. + static const equal = const _PathRelation("equal"); + + /// The first path is neither a parent of nor equal to the second. + static const different = const _PathRelation("different"); + + /// We couldn't quickly determine any information about the paths' + /// relationship to each other. + /// + /// Only returned by [Context._isWithinOrEqualsFast]. + static const inconclusive = const _PathRelation("inconclusive"); + + final String name; + + const _PathRelation(this.name); + + String toString() => name; +} +{NN<#5GQLPHLP3*M;<1(6M/AAK)+IL7KG HO2HKHA;'39H9L'M2-9?<'4 'N$6$'Q1?55@G6:;JN687>6A(OJLPNOKMM9>QLP:PKMM94B>APAP> %9>FPFPC=+% .:GP'#&H12 +)*C;CL%# +N3JED:DQJP$NIBOIM0MQ %K*G<KPDN"15*$IK'L$)8 +5#)KLDJO KL()48 +#*'(2K$%31L"M*:Q00E$NPGN.AD$&*'F$)$)NL&FQG#%G42P,G%+"HBBA0@LJ->Q7AMP3/-0C7!@6=?:!A#7= +5#H/&D5:$)7" OEP#$53OH:OM@7P11/B(EI!$5M(&G;8A1- +'./-+5-KML 8+A9+&MM59>&*?+COJ3'%QP7K5724HQA8GN1)J898?-#O&.98).74@::I $#@J ',$$#" 428%MIL&"')NQ,EJK$)6MOA 4G)+N/FQJ$%> +IAL)9&;EQ:#>)5#8*QM71!4$=4>;<.P7(3+6;?, ;?LNEP new Context(style: this); + + @Deprecated("Most Style members will be removed in path 2.0.") + String get separator; + + @Deprecated("Most Style members will be removed in path 2.0.") + Pattern get separatorPattern; + + @Deprecated("Most Style members will be removed in path 2.0.") + Pattern get needsSeparatorPattern; + + @Deprecated("Most Style members will be removed in path 2.0.") + Pattern get rootPattern; + + @Deprecated("Most Style members will be removed in path 2.0.") + Pattern get relativeRootPattern; + + @Deprecated("Most style members will be removed in path 2.0.") + String getRoot(String path); + + @Deprecated("Most style members will be removed in path 2.0.") + String getRelativeRoot(String path); + + @Deprecated("Most style members will be removed in path 2.0.") + String pathFromUri(Uri uri); + + @Deprecated("Most style members will be removed in path 2.0.") + Uri relativePathToUri(String path); + + @Deprecated("Most style members will be removed in path 2.0.") + Uri absolutePathToUri(String path); + + String toString() => name; +} +XNN<0NA/QLP3O+NI+&PF5*%GLM58KA(3AA A%AA#AA'AA&A&`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/path_exception.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// An exception class that's thrown when a path operation is unable to be +/// computed accurately. +class PathException implements Exception { + String message; + + PathException(this.message); + + String toString() => "PathException: $message"; +} +NN<K+2Zfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/path_map.dart// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import '../path.dart' as p; + +/// A map whose keys are paths, compared using [equals] and [hash]. +class PathMap extends MapView { + /// Creates an empty [PathMap] whose keys are compared using `context.equals` + /// and `context.hash`. + /// + /// The [context] defaults to the current path context. + PathMap({p.Context context}) : super(_create(context)); + + /// Creates a [PathMap] with the same keys and values as [other] whose keys + /// are compared using `context.equals` and `context.hash`. + /// + /// The [context] defaults to the current path context. If multiple keys in + /// [other] represent the same logical path, the last key's value will be + /// used. + PathMap.of(Map other, {p.Context context}) + : super(_create(context)..addAll(other)); + + /// Creates a map that uses [context] for equality and hashing. + static Map _create(p.Context context) { + context ??= p.context; + return new LinkedHashMap( + equals: (path1, path2) { + if (path1 == null) return path2 == null; + if (path2 == null) return false; + return context.equals(path1, path2); + }, + hashCode: (path) => path == null ? 0 : context.hash(path), + isValidKey: (path) => path is String || path == null); + } +} +(NN<D.P::N>NL 80B8!3+/ C?Zfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/path_set.dart// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import '../path.dart' as p; + +/// A set containing paths, compared using [equals] and [hash]. +class PathSet extends IterableBase implements Set { + /// The set to which we forward implementation methods. + final Set _inner; + + /// Creates an empty [PathSet] whose contents are compared using + /// `context.equals` and `context.hash`. + /// + /// The [context] defaults to the current path context. + PathSet({p.Context context}) : _inner = _create(context); + + /// Creates a [PathSet] with the same contents as [other] whose elements are + /// compared using `context.equals` and `context.hash`. + /// + /// The [context] defaults to the current path context. If multiple elements + /// in [other] represent the same logical path, the first value will be + /// used. + PathSet.of(Iterable other, {p.Context context}) + : _inner = _create(context)..addAll(other); + + /// Creates a set that uses [context] for equality and hashing. + static Set _create(p.Context context) { + context ??= p.context; + return new LinkedHashSet( + equals: (path1, path2) { + if (path1 == null) return path2 == null; + if (path2 == null) return false; + return context.equals(path1, path2); + }, + hashCode: (path) => path == null ? 0 : context.hash(path), + isValidKey: (path) => path is String || path == null); + } + + // Normally we'd use DelegatingSetView from the collection package to + // implement these, but we want to avoid adding dependencies from path because + // it's so widely used that even brief version skew can be very painful. + + Iterator get iterator => _inner.iterator; + + int get length => _inner.length; + + bool add(String value) => _inner.add(value); + + void addAll(Iterable elements) => _inner.addAll(elements); + + Set cast() => _inner.cast(); + + void clear() => _inner.clear(); + + bool contains(Object other) => _inner.contains(other); + + bool containsAll(Iterable other) => _inner.containsAll(other); + + Set difference(Set other) => _inner.difference(other); + + Set intersection(Set other) => _inner.intersection(other); + + String lookup(Object element) => _inner.lookup(element); + + bool remove(Object value) => _inner.remove(value); + + void removeAll(Iterable elements) => _inner.removeAll(elements); + + void removeWhere(bool test(String element)) => _inner.removeWhere(test); + + void retainAll(Iterable elements) => _inner.retainAll(elements); + + void retainWhere(bool test(String element)) => _inner.retainWhere(test); + + Set union(Set other) => _inner.union(other); + + Set toSet() => _inner.toSet(); +} +SNN<@D:C+:<O:OJ :2B2!3+/ C?HQK4#/E("9IIM;5KKKK?)\file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/forwarding.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'forwarding/forwarding_directory.dart'; +export 'forwarding/forwarding_file.dart'; +export 'forwarding/forwarding_file_system.dart'; +export 'forwarding/forwarding_file_system_entity.dart'; +export 'forwarding/forwarding_link.dart'; + NN</*18*[file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/interface.dart +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library file.src.interface; + +export 'interface/directory.dart'; +export 'interface/error_codes.dart'; +export 'interface/file.dart'; +export 'interface/file_system.dart'; +export 'interface/file_system_entity.dart'; +export 'interface/link.dart'; +export 'io.dart' hide Directory, File, FileSystemEntity, Link; +NN<#%%,?nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/mime-0.9.6+2/lib/src/mime_multipart_transformer.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +library mime.multipart_transformer; + +import 'dart:async'; +import 'dart:typed_data'; + +import 'bound_multipart_stream.dart'; +import 'char_code.dart'; +import 'mime_shared.dart'; + +Uint8List _getBoundary(String boundary) { + var charCodes = boundary.codeUnits; + + var boundaryList = new Uint8List(4 + charCodes.length); + // Set-up the matching boundary preceding it with CRLF and two + // dashes. + boundaryList[0] = CharCode.CR; + boundaryList[1] = CharCode.LF; + boundaryList[2] = CharCode.DASH; + boundaryList[3] = CharCode.DASH; + boundaryList.setRange(4, 4 + charCodes.length, charCodes); + return boundaryList; +} + +/** + * Parser for MIME multipart types of data as described in RFC 2046 + * section 5.1.1. The data is transformed into [MimeMultipart] objects, each + * of them streaming the multipart data. + */ +class MimeMultipartTransformer + extends StreamTransformerBase, MimeMultipart> { + final List _boundary; + + /** + * Construct a new MIME multipart parser with the boundary + * [boundary]. The boundary should be as specified in the content + * type parameter, that is without the -- prefix. + */ + MimeMultipartTransformer(String boundary) + : _boundary = _getBoundary(boundary); + + Stream bind(Stream> stream) { + return new BoundMultipartStream(_boundary, stream).stream; + } +} +1NN<$&*&:A !!##=DM)>=D4,,9?_file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/mime-0.9.6+2/lib/src/mime_shared.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +library mime.shared; + +import 'dart:async'; + +class MimeMultipartException implements Exception { + final String message; + + const MimeMultipartException([this.message = ""]); + + String toString() => "MimeMultipartException: $message"; +} + +/** + * A Mime Multipart class representing each part parsed by + * [MimeMultipartTransformer]. The data is streamed in as it become available. + */ +abstract class MimeMultipart extends Stream> { + Map get headers; +} +NN<45;;O9#]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/mime-0.9.6+2/lib/src/mime_type.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library mime.mime_type; + +import 'default_extension_map.dart'; +import 'magic_number.dart'; + +final MimeTypeResolver _globalResolver = new MimeTypeResolver(); + +/** + * The maximum number of bytes needed, to match all default magic-numbers. + */ +int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; + +/** + * Extract the extension from [path] and use that for MIME-type lookup, using + * the default extension map. + * + * If no matching MIME-type was found, `null` is returned. + * + * If [headerBytes] is present, a match for known magic-numbers will be + * performed first. This allows the correct mime-type to be found, even though + * a file have been saved using the wrong file-name extension. If less than + * [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't + * be matched against. + */ +String lookupMimeType(String path, {List headerBytes}) => + _globalResolver.lookup(path, headerBytes: headerBytes); + +/** + * MIME-type resolver class, used to customize the lookup of mime-types. + */ +class MimeTypeResolver { + final Map _extensionMap = {}; + final List _magicNumbers = []; + final bool _useDefault; + int _magicNumbersMaxLength; + + /** + * Create a new empty [MimeTypeResolver]. + */ + MimeTypeResolver.empty() + : _useDefault = false, + _magicNumbersMaxLength = 0; + + /** + * Create a new [MimeTypeResolver] containing the default scope. + */ + MimeTypeResolver() + : _useDefault = true, + _magicNumbersMaxLength = DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; + + /** + * Get the maximum number of bytes required to match all magic numbers, when + * performing [lookup] with headerBytes present. + */ + int get magicNumbersMaxLength => _magicNumbersMaxLength; + + /** + * Extract the extension from [path] and use that for MIME-type lookup. + * + * If no matching MIME-type was found, `null` is returned. + * + * If [headerBytes] is present, a match for known magic-numbers will be + * performed first. This allows the correct mime-type to be found, even though + * a file have been saved using the wrong file-name extension. If less than + * [magicNumbersMaxLength] bytes was provided, some magic-numbers won't + * be matched against. + */ + String lookup(String path, {List headerBytes}) { + String result; + if (headerBytes != null) { + result = _matchMagic(headerBytes, _magicNumbers); + if (result != null) return result; + if (_useDefault) { + result = _matchMagic(headerBytes, DEFAULT_MAGIC_NUMBERS); + if (result != null) return result; + } + } + var ext = _ext(path); + result = _extensionMap[ext]; + if (result != null) return result; + if (_useDefault) { + result = defaultExtensionMap[ext]; + if (result != null) return result; + } + return null; + } + + /** + * Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] + * is already present in the [MimeTypeResolver], it'll be overwritten. + */ + void addExtension(String extension, String mimeType) { + _extensionMap[extension] = mimeType; + } + + /** + * Add a new magic-number mapping to the [MimeTypeResolver]. + * + * If [mask] is present,the [mask] is used to only perform matching on + * selective bits. The [mask] must have the same length as [bytes]. + */ + void addMagicNumber(List bytes, String mimeType, {List mask}) { + if (mask != null && bytes.length != mask.length) { + throw new ArgumentError('Bytes and mask are of different lengths'); + } + if (bytes.length > _magicNumbersMaxLength) { + _magicNumbersMaxLength = bytes.length; + } + _magicNumbers.add(new MagicNumber(mimeType, bytes, mask: mask)); + } + + static String _matchMagic( + List headerBytes, List magicNumbers) { + for (var mn in magicNumbers) { + if (mn.matches(headerBytes)) return mn.mimeType; + } + return null; + } + + static String _ext(String path) { + int index = path.lastIndexOf('.'); + if (index < 0 || index + 1 >= path.length) return path; + return path.substring(index + 1).toLowerCase(); + } +} +NN<%AKON;HOLO?<I0.,$CCO3;J=JQNJ88)B+!'))OI9)?IFL7J1-E?#7$'<4ofile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/combinator.dartlibrary lex.src.combinator; + +import 'dart:collection'; + +import 'package:code_buffer/code_buffer.dart'; +import 'package:matcher/matcher.dart'; +import 'package:source_span/source_span.dart'; +import 'package:string_scanner/string_scanner.dart'; +import 'package:tuple/tuple.dart'; +import '../error.dart'; + +part 'any.dart'; + +part 'advance.dart'; + +part 'cache.dart'; + +part 'cast.dart'; + +part 'chain.dart'; + +part 'check.dart'; + +part 'compare.dart'; + +part 'fold_errors.dart'; + +part 'index.dart'; + +part 'longest.dart'; + +part 'map.dart'; + +part 'match.dart'; + +part 'max_depth.dart'; + +part 'negate.dart'; + +part 'opt.dart'; + +part 'recursion.dart'; + +part 'reduce.dart'; + +part 'reference.dart'; + +part 'repeat.dart'; + +part 'safe.dart'; + +part 'to_list.dart'; + +part 'util.dart'; + +part 'value.dart'; + +class ParseArgs { + final Trampoline trampoline; + final SpanScanner scanner; + final int depth; + + ParseArgs(this.trampoline, this.scanner, this.depth); + + ParseArgs increaseDepth() => new ParseArgs(trampoline, scanner, depth + 1); +} + +/// A parser combinator, which can parse very complicated grammars in a manageable manner. +abstract class Parser { + ParseResult __parse(ParseArgs args); + + ParseResult _parse(ParseArgs args) { + var pos = args.scanner.position; + + if (args.trampoline.hasMemoized(this, pos)) + return args.trampoline.getMemoized(this, pos); + + if (args.trampoline.isActive(this, pos)) + return new ParseResult(args.trampoline, args.scanner, this, false, []); + + args.trampoline.enter(this, pos); + var result = __parse(args); + args.trampoline.memoize(this, pos, result); + args.trampoline.exit(this); + return result; + } + + /// Parses text from a [SpanScanner]. + ParseResult parse(SpanScanner scanner, [int depth = 1]) { + var args = new ParseArgs(new Trampoline(), scanner, depth); + return _parse(args); + } + + /// Skips forward a certain amount of steps after parsing, if it was successful. + Parser forward(int amount) => new _Advance(this, amount); + + /// Moves backward a certain amount of steps after parsing, if it was successful. + Parser back(int amount) => new _Advance(this, amount * -1); + + /// Casts this parser to produce [U] objects. + Parser cast() => new _Cast(this); + + /// Casts this parser to produce [dynamic] objects. + Parser castDynamic() => new _CastDynamic(this); + + /// Runs the given function, which changes the returned [ParseResult] into one relating to a [U] object. + Parser change(ParseResult Function(ParseResult) f) { + return new _Change(this, f); + } + + /// Validates the parse result against a [Matcher]. + /// + /// You can provide a custom [errorMessage]. + Parser check(Matcher matcher, + {String errorMessage, SyntaxErrorSeverity severity}) => + new _Check( + this, matcher, errorMessage, severity ?? SyntaxErrorSeverity.error); + + /// Binds an [errorMessage] to a copy of this parser. + Parser error({String errorMessage, SyntaxErrorSeverity severity}) => + new _Alt(this, errorMessage, severity ?? SyntaxErrorSeverity.error); + + /// Removes multiple errors that occur in the same spot; this can reduce noise in parser output. + Parser foldErrors({bool equal(SyntaxError a, SyntaxError b)}) { + equal ??= (b, e) => b.span.start.offset == e.span.start.offset; + return new _FoldErrors(this, equal); + } + + /// Transforms the parse result using a unary function. + Parser map(U Function(ParseResult) f) { + return new _Map(this, f); + } + + /// Prevents recursion past a certain [depth], preventing stack overflow errors. + Parser maxDepth(int depth) => new _MaxDepth(this, depth); + + Parser operator ~() => negate(); + + /// Ensures this pattern is not matched. + /// + /// You can provide an [errorMessage]. + Parser negate({String errorMessage, SyntaxErrorSeverity severity}) => + new _Negate(this, errorMessage, severity ?? SyntaxErrorSeverity.error); + + /// Caches the results of parse attempts at various locations within the source text. + /// + /// Use this to prevent excessive recursion. + Parser cache() => new _Cache(this); + + Parser operator &(Parser other) => and(other); + + /// Consumes `this` and another parser, but only considers the result of `this` parser. + Parser and(Parser other) => then(other).change((r) { + return new ParseResult( + r.trampoline, + r.scanner, + this, + r.successful, + r.errors, + span: r.span, + value: (r.value != null ? r.value[0] : r.value) as T, + ); + }); + + Parser operator |(Parser other) => or(other); + + /// Shortcut for [or]-ing two parsers. + Parser or(Parser other) => any([this, other]); + + /// Parses this sequence one or more times. + ListParser plus() => times(1, exact: false); + + /// Safely escapes this parser when an error occurs. + /// + /// The generated parser only runs once; repeated uses always exit eagerly. + Parser safe( + {bool backtrack: true, + String errorMessage, + SyntaxErrorSeverity severity}) => + new _Safe( + this, backtrack, errorMessage, severity ?? SyntaxErrorSeverity.error); + + Parser> separatedByComma() => separatedBy(match>(',').space()); + + /// Expects to see an infinite amounts of the pattern, separated by the [other] pattern. + /// + /// Use this as a shortcut to parse arrays, parameter lists, etc. + Parser> separatedBy(Parser other) { + var suffix = other.then(this).index(1).cast(); + return this.then(suffix.star()).map((r) { + var preceding = + r.value.isEmpty ? [] : (r.value[0] == null ? [] : [r.value[0]]); + var out = new List.from(preceding); + if (r.value[1] != null) out.addAll(r.value[1] as Iterable); + return out; + }); + } + + Parser surroundedByCurlyBraces({T defaultValue}) => opt() + .surroundedBy(match('{').space(), match('}').space()) + .map((r) => r.value ?? defaultValue); + + Parser surroundedBySquareBrackets({T defaultValue}) => opt() + .surroundedBy(match('[').space(), match(']').space()) + .map((r) => r.value ?? defaultValue); + + /// Expects to see the pattern, surrounded by the others. + /// + /// If no [right] is provided, it expects to see the same pattern on both sides. + /// Use this parse things like parenthesized expressions, arrays, etc. + Parser surroundedBy(Parser left, [Parser right]) { + return chain([ + left, + this, + right ?? left, + ]).index(1).castDynamic().cast(); + } + + /// Parses `this`, either as-is or wrapped in parentheses. + Parser maybeParenthesized() { + return any([parenthesized(), this]); + } + + /// Parses `this`, wrapped in parentheses. + Parser parenthesized() => + surroundedBy(match('(').space(), match(')').space()); + + /// Consumes any trailing whitespace. + Parser space() => trail(new RegExp(r'[ \n\r\t]+')); + + /// Consumes 0 or more instance(s) of this parser. + ListParser star({bool backtrack: true}) => + times(1, exact: false, backtrack: backtrack).opt(); + + /// Shortcut for [chain]-ing two parsers together. + ListParser then(Parser other) => chain([this, other]); + + /// Casts this instance into a [ListParser]. + ListParser toList() => new _ToList(this); + + /// Consumes and ignores any trailing occurrences of [pattern]. + Parser trail(Pattern pattern) => + then(match(pattern).opt()).first().cast(); + + /// Expect this pattern a certain number of times. + /// + /// If [exact] is `false` (default: `true`), then the generated parser will accept + /// an infinite amount of occurrences after the specified [count]. + /// + /// You can provide custom error messages for when there are [tooFew] or [tooMany] occurrences. + ListParser times(int count, + {bool exact: true, + String tooFew, + String tooMany, + bool backtrack: true, + SyntaxErrorSeverity severity}) { + return new _Repeat(this, count, exact, tooFew, tooMany, backtrack, + severity ?? SyntaxErrorSeverity.error); + } + + /// Produces an optional copy of this parser. + /// + /// If [backtrack] is `true` (default), then a failed parse will not + /// modify the scanner state. + Parser opt({bool backtrack: true}) => new _Opt(this, backtrack); + + /// Sets the value of the [ParseResult]. + Parser value(T Function(ParseResult) f) { + return new _Value(this, f); + } + + /// Prints a representation of this parser, ideally without causing a stack overflow. + void stringify(CodeBuffer buffer); + + @override + String toString() { + return super.toString(); + var b = new CodeBuffer(); + stringify(b); + return b.toString(); + } +} + +/// A [Parser] that produces [List]s of a type [T]. +abstract class ListParser extends Parser> { + /// Shortcut for calling [index] with `0`. + Parser first() => index(0); + + /// Modifies this parser to only return the value at the given index [i]. + Parser index(int i) => new _Index(this, i); + + /// Shortcut for calling [index] with the greatest-possible index. + Parser last() => index(-1); + + /// Modifies this parser to call `List.reduce` on the parsed values. + Parser reduce(T Function(T, T) combine) => new _Reduce(this, combine); + + /// Sorts the parsed values, using the given [Comparator]. + ListParser sort(Comparator compare) => new _Compare(this, compare); + + @override + ListParser opt({bool backtrack: true}) => new _ListOpt(this, backtrack); + + /// Modifies this parser, returning only the values that match a predicate. + Parser> where(bool Function(T) f) => + map>((r) => r.value.where(f).toList()); + + /// Condenses a [ListParser] into having a value of the combined span's text. + Parser flatten() => map((r) => r.span.text); +} + +/// Prevents stack overflow in recursive parsers. +class Trampoline { + final Map> _active = {}; + final Map>> _memo = {}; + + bool hasMemoized(Parser parser, int position) { + var list = _memo[parser]; + return list?.any((t) => t.item1 == position) == true; + } + + ParseResult getMemoized(Parser parser, int position) { + return _memo[parser].firstWhere((t) => t.item1 == position).item2 as ParseResult; + } + + void memoize(Parser parser, int position, ParseResult result) { + if (result != null) { + var list = _memo.putIfAbsent(parser, () => []); + var tuple = new Tuple2(position, result); + if (!list.contains(tuple)) list.add(tuple); + } + } + + bool isActive(Parser parser, int position) { + if (!_active.containsKey(parser)) return false; + var q = _active[parser]; + if (q.isEmpty) return false; + //return q.contains(position); + return q.first == position; + } + + void enter(Parser parser, int position) { + _active.putIfAbsent(parser, () => new Queue()).addFirst(position); + } + + void exit(Parser parser) { + if (_active.containsKey(parser)) _active[parser].removeFirst(); + } +} + +/// The result generated by a [Parser]. +class ParseResult { + final Parser parser; + final bool successful; + final Iterable errors; + final FileSpan span; + final T value; + final SpanScanner scanner; + final Trampoline trampoline; + + ParseResult( + this.trampoline, this.scanner, this.parser, this.successful, this.errors, + {this.span, this.value}); + + ParseResult change( + {Parser parser, + bool successful, + Iterable errors, + FileSpan span, + T value}) { + return new ParseResult( + trampoline, + scanner, + parser ?? this.parser, + successful ?? this.successful, + errors ?? this.errors, + span: span ?? this.span, + value: value ?? this.value, + ); + } + + ParseResult addErrors(Iterable errors) { + return change( + errors: new List.from(this.errors)..addAll(errors), + ); + } +} +/'/5#8N[**%08-N& 0 (?@SBTD0:6>kC'6/#BO8JNcED,:3$SB&+)KQX/,7Z= @ +6)=.27N!,QR[D.6.K-E?<,B<,<SI8 )=#)-<(950:5K/2B&45UEb!'J00G F+2#X% 47-!L4E!GO=L NN/6P?2.@2:?YB602/4!# ,GD(&P $%";Ghfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/any.dartnpart of lex.src.combinator; + +/// Matches any one of the given [parsers]. +/// +/// If [backtrack] is `true` (default), a failed parse will not modify the scanner state. +/// +/// You can provide a custom [errorMessage]. You can set it to `false` to not +/// generate any error at all. +Parser any(Iterable> parsers, + {bool backtrack: true, errorMessage, SyntaxErrorSeverity severity}) { + return new _Any(parsers, backtrack != false, errorMessage, + severity ?? SyntaxErrorSeverity.error); +} + +class _Any extends Parser { + final Iterable> parsers; + final bool backtrack; + final errorMessage; + final SyntaxErrorSeverity severity; + + _Any(this.parsers, this.backtrack, this.errorMessage, this.severity); + + @override + ParseResult _parse(ParseArgs args) { + var inactive = parsers + .where((p) => !args.trampoline.isActive(p, args.scanner.position)); + + if (inactive.isEmpty) { + return new ParseResult(args.trampoline, args.scanner, this, false, []); + } + + var errors = []; + int replay = args.scanner.position; + + for (var parser in inactive) { + var result = parser._parse(args.increaseDepth()); + + if (result.successful) + return result; + else { + if (backtrack) args.scanner.position = replay; + if (parser is _Alt) errors.addAll(result.errors); + } + } + + if (errorMessage != false) { + errors.add( + new SyntaxError( + severity, + errorMessage?.toString() ?? 'No match found for ${parsers.length} alternative(s)', + args.scanner.emptySpan, + ), + ); + } + + return new ParseResult(args.trampoline, args.scanner, this, false, errors); + } + + @override + ParseResult __parse(ParseArgs args) { + // Never called + return null; + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('any(${parsers.length}) (') + ..indent(); + int i = 1; + + for (var parser in parsers) { + buffer + ..writeln('#${i++}:') + ..indent(); + parser.stringify(buffer); + buffer.outdent(); + } + + buffer + ..outdent() + ..writeln(')'); + } +} +V,ZN.J=."%&H *LN"(#8 7:!]" P + & ,"   lfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/advance.dart;part of lex.src.combinator; + +class _Advance extends Parser { + final Parser parser; + final int amount; + + _Advance(this.parser, this.amount); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()).change(parser: this); + if (result.successful) args.scanner.position += amount; + return result; + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('advance($amount) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +&& +K< & & jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/cache.dart:part of lex.src.combinator; + +class _Cache extends Parser { + final Map> _cache = {}; + final Parser parser; + + _Cache(this.parser); + + @override + ParseResult __parse(ParseArgs args) { + return _cache.putIfAbsent(args.scanner.position, () { + return parser._parse(args.increaseDepth()); + }).change(parser: this); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('cache(${_cache.length}) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +$. +:2 & - ifile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/cast.dartpart of lex.src.combinator; + +class _Cast extends Parser { + final Parser parser; + + _Cast(this.parser); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + return new ParseResult( + args.trampoline, + args.scanner, + this, + result.successful, + result.errors, + span: result.span, + value: result.value as U, + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('cast<$U> (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} + +class _CastDynamic extends Parser { + final Parser parser; + + _CastDynamic(this.parser); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + return new ParseResult( + args.trampoline, + args.scanner, + this, + result.successful, + result.errors, + span: result.span, + value: result.value, + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('cast (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +A0 +6   &  0 16%  & # jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/chain.dartpart of lex.src.combinator; + +/// Expects to parse a sequence of [parsers]. +/// +/// If [failFast] is `true` (default), then the first failure to parse will abort the parse. +ListParser chain(Iterable> parsers, + {bool failFast: true, SyntaxErrorSeverity severity}) { + return new _Chain( + parsers, failFast != false, severity ?? SyntaxErrorSeverity.error); +} + +class _Alt extends Parser { + final Parser parser; + final String errorMessage; + final SyntaxErrorSeverity severity; + + _Alt(this.parser, this.errorMessage, this.severity); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + return result.successful + ? result + : result.addErrors([ + new SyntaxError(severity ?? SyntaxErrorSeverity.error, errorMessage, + result.span ?? args.scanner.emptySpan), + ]); + } + + @override + void stringify(CodeBuffer buffer) { + parser.stringify(buffer); + } +} + +class _Chain extends ListParser { + final Iterable> parsers; + final bool failFast; + final SyntaxErrorSeverity severity; + + _Chain(this.parsers, this.failFast, this.severity); + + @override + ParseResult> __parse(ParseArgs args) { + var errors = []; + var results = []; + var spans = []; + bool successful = true; + + for (var parser in parsers) { + var result = parser._parse(args.increaseDepth()); + + if (!result.successful) { + if (parser is _Alt) errors.addAll(result.errors); + + if (failFast) { + return new ParseResult( + args.trampoline, args.scanner, this, false, result.errors); + } + + successful = false; + } + + results.add(result.value); + + if (result.span != null) spans.add(result.span); + } + + FileSpan span; + + if (spans.isNotEmpty) { + span = spans.reduce((a, b) => a.expand(b)); + } + + return new ParseResult>( + args.trampoline, + args.scanner, + this, + successful, + errors, + span: span, + value: new List.unmodifiable(results), + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('chain(${parsers.length}) (') + ..indent(); + int i = 1; + + for (var parser in parsers) { + buffer + ..writeln('#${i++}:') + ..indent(); + parser.stringify(buffer); + buffer.outdent(); + } + + buffer + ..outdent() + ..writeln(')'); + } +} +k.]4;J"&7 +6Q8 &(%&6 1""8 :"J +!72% 0 & ."   jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/check.dart extends Parser { + final Parser parser; + final Matcher matcher; + final String errorMessage; + final SyntaxErrorSeverity severity; + + _Check(this.parser, this.matcher, this.errorMessage, this.severity); + + @override + ParseResult __parse(ParseArgs args) { + var matchState = {}; + var result = parser._parse(args.increaseDepth()).change(parser: this); + if (!result.successful) + return result; + else if (!matcher.matches(result.value, matchState)) { + return result.change(successful: false).addErrors([ + new SyntaxError( + severity, + errorMessage ?? + matcher.describe(new StringDescription('Expected ')).toString() + + '.', + result.span, + ), + ]); + } else + return result; + } + + @override + void stringify(CodeBuffer buffer) { + var d = matcher.describe(new StringDescription()); + buffer + ..writeln('check($d) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +,$&G +K;:P +  &7  lfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/compare.dart|part of lex.src.combinator; + +class _Compare extends ListParser { + final ListParser parser; + final Comparator compare; + + _Compare(this.parser, this.compare); + + @override + ParseResult> __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + if (!result.successful) return result; + + result = result.change( + value: result.value?.isNotEmpty == true ? result.value : []); + result = result.change(value: new List.from(result.value)); + return new ParseResult>( + args.trampoline, + args.scanner, + this, + true, + [], + span: result.span, + value: result.value..sort(compare), + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('sort($compare) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +(*' 16+FC% +* & $ pfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/fold_errors.dartpart of lex.src.combinator; + +class _FoldErrors extends Parser { + final Parser parser; + final bool Function(SyntaxError, SyntaxError) equal; + + _FoldErrors(this.parser, this.equal); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()).change(parser: this); + var errors = result.errors.fold>([], (out, e) { + if (!out.any((b) => equal(e, b))) out.add(e); + return out; + }); + return result.change(errors: errors); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('fold errors (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +)7( +KF4* & ! jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/index.dart part of lex.src.combinator; + +class _Index extends Parser { + final ListParser parser; + final int index; + + _Index(this.parser, this.index); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + Object value; + + if (result.successful) + value = index == -1 ? result.value.last : result.value.elementAt(index); + + return new ParseResult( + args.trampoline, + args.scanner, + this, + result.successful, + result.errors, + span: result.span, + value: value as T, + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('index($index) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +($# +6O  & # lfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/longest.dartpart of lex.src.combinator; + +/// Matches any one of the given [parsers]. +/// +/// You can provide a custom [errorMessage]. +Parser longest(Iterable> parsers, + {Object errorMessage, SyntaxErrorSeverity severity}) { + return new _Longest( + parsers, errorMessage, severity ?? SyntaxErrorSeverity.error); +} + +class _Longest extends Parser { + final Iterable> parsers; + final Object errorMessage; + final SyntaxErrorSeverity severity; + + _Longest(this.parsers, this.errorMessage, this.severity); + + @override + ParseResult _parse(ParseArgs args) { + var inactive = parsers + .toList() + .where((p) => !args.trampoline.isActive(p, args.scanner.position)); + + if (inactive.isEmpty) { + return new ParseResult(args.trampoline, args.scanner, this, false, []); + } + + int replay = args.scanner.position; + var errors = []; + var results = >[]; + + for (var parser in inactive) { + var result = parser._parse(args.increaseDepth()); + + if (result.successful && result.span != null) + results.add(result); + else if (parser is _Alt) errors.addAll(result.errors); + + args.scanner.position = replay; + } + + if (results.isNotEmpty) { + results.sort((a, b) => b.span.length.compareTo(a.span.length)); + args.scanner.scan(results.first.span.text); + return results.first; + } + + if (errorMessage != false) + errors.add( + new SyntaxError( + severity, + errorMessage?.toString() ?? 'No match found for ${parsers.length} alternative(s)', + args.scanner.emptySpan, + ), + ); + + return new ParseResult(args.trampoline, args.scanner, this, false, errors); + } + + @override + ParseResult __parse(ParseArgs args) { + int replay = args.scanner.position; + var errors = []; + var results = >[]; + + for (var parser in parsers) { + var result = parser._parse(args.increaseDepth()); + + if (result.successful) + results.add(result); + else if (parser is _Alt) errors.addAll(result.errors); + + args.scanner.position = replay; + } + + if (results.isNotEmpty) { + results.sort((a, b) => b.span.length.compareTo(a.span.length)); + args.scanner.scan(results.first.span.text); + return results.first; + } + + errors.add( + new SyntaxError( + severity, + errorMessage?.toString() ?? 'No match found for ${parsers.length} alternative(s)', + args.scanner.emptySpan, + ), + ); + + return new ParseResult(args.trampoline, args.scanner, this, false, errors); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('longest(${parsers.length}) (') + ..indent(); + int i = 1; + + for (var parser in parsers) { + buffer + ..writeln('#${i++}:') + ..indent(); + parser.stringify(buffer); + buffer.outdent(); + } + + buffer + ..outdent() + ..writeln(')'); + } +} +s,-2;E&%&< *LN("&#84=&F2]" P +("&"8=&F2[ P & 0"   hfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/map.dartpart of lex.src.combinator; + +class _Map extends Parser { + final Parser parser; + final U Function(ParseResult) f; + + _Map(this.parser, this.f); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + return new ParseResult( + args.trampoline, + args.scanner, + this, + result.successful, + result.errors, + span: result.span, + value: result.successful ? f(result) : null, + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('map<$U> (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} + +class _Change extends Parser { + final Parser parser; + final ParseResult Function(ParseResult) f; + + _Change(this.parser, this.f); + + @override + ParseResult __parse(ParseArgs args) { + return f(parser._parse(args.increaseDepth())).change(parser: this); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('change($f) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +:%& +6 3 &  (3  +H &  jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/match.dart4part of lex.src.combinator; + +/// Expects to match a given [pattern]. If it is not matched, you can provide a custom [errorMessage]. +Parser match(Pattern pattern, + {String errorMessage, SyntaxErrorSeverity severity}) => + new _Match(pattern, errorMessage, severity ?? SyntaxErrorSeverity.error); + +class _Match extends Parser { + final Pattern pattern; + final String errorMessage; + final SyntaxErrorSeverity severity; + + _Match(this.pattern, this.errorMessage, this.severity); + + @override + ParseResult __parse(ParseArgs args) { + var scanner = args.scanner; + if (!scanner.scan(pattern)) + return new ParseResult(args.trampoline, scanner, this, false, [ + new SyntaxError( + severity, + errorMessage ?? 'Expected "$pattern".', + scanner.emptySpan, + ), + ]); + return new ParseResult( + args.trampoline, + scanner, + this, + true, + [], + span: scanner.lastSpan, + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer.writeln('match($pattern)'); + } +} +*g$@Q$&: + F2 + + &'nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/max_depth.dart@part of lex.src.combinator; + +class _MaxDepth extends Parser { + final Parser parser; + final int cap; + + _MaxDepth(this.parser, this.cap); + + @override + ParseResult __parse(ParseArgs args) { + if (args.depth > cap) { + return new ParseResult(args.trampoline, args.scanner, this, false, []); + } + + return parser._parse(args.increaseDepth()); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('max depth($cap) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +'$ +Q0 & % kfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/negate.dart3part of lex.src.combinator; + +class _Negate extends Parser { + final Parser parser; + final String errorMessage; + final SyntaxErrorSeverity severity; + + _Negate(this.parser, this.errorMessage, this.severity); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()).change(parser: this); + + if (!result.successful) { + return new ParseResult( + args.trampoline, + args.scanner, + this, + true, + [], + span: result.span ?? args.scanner.lastSpan ?? args.scanner.emptySpan, + value: result.value, + ); + } + + result = result.change(successful: false); + + if (errorMessage != null) { + result = result.addErrors([ + new SyntaxError( + severity, + errorMessage, + result.span, + ), + ]); + } + + return result; + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('negate (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +5%&: +K! N / " + &  hfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/opt.dartpart of lex.src.combinator; + +class _Opt extends Parser { + final Parser parser; + final bool backtrack; + + _Opt(this.parser, this.backtrack); + + @override + ParseResult __parse(ParseArgs args) { + var replay = args.scanner.position; + var result = parser._parse(args.increaseDepth()); + + if (!result.successful) args.scanner.position = replay; + + return result.change(parser: this, successful: true); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('optional (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} + +class _ListOpt extends ListParser { + final ListParser parser; + final bool backtrack; + + _ListOpt(this.parser, this.backtrack); + + @override + ParseResult> __parse(ParseArgs args) { + var replay = args.scanner.position; + var result = parser._parse(args.increaseDepth()); + + if (!result.successful) args.scanner.position = replay; + + return result.change(parser: this, successful: true); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('optional (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +;"% +(6<: &  *) 1(6<: &  kfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/reduce.dartpart of lex.src.combinator; + +class _Reduce extends Parser { + final ListParser parser; + final T Function(T, T) combine; + + _Reduce(this.parser, this.combine); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + + if (!result.successful) + return new ParseResult( + args.trampoline, + args.scanner, + this, + false, + result.errors, + ); + + result = result.change( + value: result.value?.isNotEmpty == true ? result.value : []); + return new ParseResult( + args.trampoline, + args.scanner, + this, + result.successful, + [], + span: result.span, + value: result.value.isEmpty ? null : result.value.reduce(combine), + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('reduce($combine) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +/%"& +6! F  +I & & nfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/reference.dartpart of lex.src.combinator; + +Reference reference() => new Reference._(); + +class Reference extends Parser { + Parser _parser; + bool printed = false; + + Reference._(); + + void set parser(Parser value) { + if (_parser != null) + throw new StateError( + 'There is already a parser assigned to this reference.'); + _parser = value; + } + + @override + ParseResult __parse(ParseArgs args) { + if (_parser == null) + throw new StateError('There is no parser assigned to this reference.'); + return _parser._parse(args); + } + + @override + ParseResult _parse(ParseArgs args) { + return _parser._parse(args); + } + + @override + void stringify(CodeBuffer buffer) { + if (_parser == null) + buffer.writeln('(undefined reference <$T>)'); + else if (!printed) _parser.stringify(buffer); + printed = true; + buffer.writeln('(previously printed reference)'); + } +} +(5'%D +N! *! &426kfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/repeat.dartpart of lex.src.combinator; + +class _Repeat extends ListParser { + final Parser parser; + final int count; + final bool exact, backtrack; + final String tooFew, tooMany; + final SyntaxErrorSeverity severity; + + _Repeat(this.parser, this.count, this.exact, this.tooFew, this.tooMany, + this.backtrack, this.severity); + + @override + ParseResult> __parse(ParseArgs args) { + var errors = []; + var results = []; + var spans = []; + int success = 0, replay = args.scanner.position; + ParseResult result; + + do { + result = parser._parse(args.increaseDepth()); + if (result.successful) { + success++; + results.add(result.value); + replay = args.scanner.position; + } else if (backtrack) args.scanner.position = replay; + + if (result.span != null) spans.add(result.span); + } while (result.successful); + + if (success < count) { + errors.addAll(result.errors); + errors.add( + new SyntaxError( + severity, + tooFew ?? 'Expected at least $count occurence(s).', + result.span ?? args.scanner.emptySpan, + ), + ); + + if (backtrack) args.scanner.position = replay; + + return new ParseResult>( + args.trampoline, args.scanner, this, false, errors); + } else if (success > count && exact) { + if (backtrack) args.scanner.position = replay; + + return new ParseResult>( + args.trampoline, args.scanner, this, false, [ + new SyntaxError( + severity, + tooMany ?? 'Expected no more than $count occurence(s).', + result.span ?? args.scanner.emptySpan, + ), + ]); + } + + var span = spans.reduce((a, b) => a.expand(b)); + return new ParseResult>( + args.trampoline, + args.scanner, + this, + true, + [], + span: span, + value: results, + ); + } + + @override + void stringify(CodeBuffer buffer) { + var r = new StringBuffer('{$count'); + if (!exact) r.write(','); + r.write('}'); + buffer + ..writeln('repeat($r) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +V) &J& 1"5 4#(<7!$>1 5'?+5'8C1 +4% + &)  ifile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/safe.dartpart of lex.src.combinator; + +class _Safe extends Parser { + final Parser parser; + final bool backtrack; + final String errorMessage; + final SyntaxErrorSeverity severity; + bool _triggered = false; + + _Safe(this.parser, this.backtrack, this.errorMessage, this.severity); + + @override + ParseResult __parse(ParseArgs args) { + var replay = args.scanner.position; + + try { + if (_triggered) throw null; + return parser._parse(args.increaseDepth()); + } catch (_) { + _triggered = true; + if (backtrack) args.scanner.position = replay; + var errors = []; + + if (errorMessage != null) { + // TODO: Custom severity for all errors? + errors.add( + new SyntaxError( + severity, + errorMessage, + args.scanner.lastSpan ?? args.scanner.emptySpan, + ), + ); + } + + return new ParseResult( + args.trampoline, args.scanner, this, false, errors); + } + } + + @override + void stringify(CodeBuffer buffer) { + var t = _triggered ? 'triggered' : 'not triggered'; + buffer + ..writeln('safe($t) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +5#&H +( +"25$"1= !? &8  lfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/to_list.dartpart of lex.src.combinator; + +class _ToList extends ListParser { + final Parser parser; + + _ToList(this.parser); + + @override + ParseResult> __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()); + + if (result.value is List) { + return (result as ParseResult>).change(parser: this); + } + + return new ParseResult( + args.trampoline, + args.scanner, + this, + result.successful, + result.errors, + span: result.span, + value: [result.value], + ); + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('to list (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +') 16 D  &  jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/combinator/value.dart;part of lex.src.combinator; + +class _Value extends Parser { + final Parser parser; + final T Function(ParseResult) f; + + _Value(this.parser, this.f); + + @override + ParseResult __parse(ParseArgs args) { + var result = parser._parse(args.increaseDepth()).change(parser: this); + return result.successful ? result.change(value: f(result)) : result; + } + + @override + void stringify(CodeBuffer buffer) { + buffer + ..writeln('set value($f) (') + ..indent(); + parser.stringify(buffer); + buffer + ..outdent() + ..writeln(')'); + } +} +$& +KI & # _file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/combinator-1.0.0+3/lib/src/error.dart$import 'package:source_span/source_span.dart'; + +class SyntaxError implements Exception { + final SyntaxErrorSeverity severity; + final String message; + final FileSpan span; + String _toolString; + + SyntaxError(this.severity, this.message, this.span); + + String get toolString { + if (_toolString != null) return _toolString; + var type = severity == SyntaxErrorSeverity.warning ? 'warning' : 'error'; + return _toolString = '$type: ${span.start.toolString}: $message'; + } +} + +enum SyntaxErrorSeverity { + warning, + error, + info, + hint, +} +/)&71NF Vfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/quiver-2.0.0+1/lib/core.dartw// 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. + +/// Simple code with broad use cases. +library quiver.core; + +import 'dart:collection'; + +part 'src/core/hash.dart'; +part 'src/core/optional.dart'; + +/// Returns the first non-null argument. If all arguments are null, throws an +/// [ArgumentError]. +/// +/// Note: if [o1] is an [Optional], this can be accomplished with `o1.or(o2)`. +firstNonNull(o1, o2, [o3, o4]) { + if (o1 != null) return o1; + if (o2 != null) return o2; + if (o3 != null) return o3; + if (o4 != null) return o4; + throw new ArgumentError('All arguments were null'); +} +#3CD+2GELG"&NO!6cfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/quiver-2.0.0+1/lib/src/core/optional.dart// 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. + +part of quiver.core; + +/// A value that might be absent. +/// +/// Use Optional as an alternative to allowing fields, parameters or return +/// values to be null. It signals that a value is not required and provides +/// convenience methods for dealing with the absent case. +class Optional extends IterableBase { + final T _value; + + /// Constructs an empty Optional. + const Optional.absent() : _value = null; + + /// Constructs an Optional of the given [value]. + /// + /// Throws [ArgumentError] if [value] is null. + Optional.of(T value) : this._value = value { + if (this._value == null) throw new ArgumentError('Must not be null.'); + } + + /// Constructs an Optional of the given [value]. + /// + /// If [value] is null, returns [absent()]. + const Optional.fromNullable(T value) : this._value = value; + + /// Whether the Optional contains a value. + bool get isPresent => _value != null; + + /// Gets the Optional value. + /// + /// Throws [StateError] if [value] is null. + T get value { + if (this._value == null) { + throw new StateError('value called on absent Optional.'); + } + return _value; + } + + /// Executes a function if the Optional value is present. + void ifPresent(void ifPresent(T value)) { + if (isPresent) { + ifPresent(_value); + } + } + + /// Execution a function if the Optional value is absent. + void ifAbsent(void ifAbsent()) { + if (!isPresent) { + ifAbsent(); + } + } + + /// Gets the Optional value with a default. + /// + /// The default is returned if the Optional is [absent()]. + /// + /// Throws [ArgumentError] if [defaultValue] is null. + T or(T defaultValue) { + if (defaultValue == null) { + throw new ArgumentError('defaultValue must not be null.'); + } + return _value == null ? defaultValue : _value; + } + + /// Gets the Optional value, or [null] if there is none. + T get orNull => _value; + + /// Transforms the Optional value. + /// + /// If the Optional is [absent()], returns [absent()] without applying the transformer. + /// + /// The transformer must not return [null]. If it does, an [ArgumentError] is thrown. + Optional transform(S transformer(T value)) { + return _value == null + ? new Optional.absent() + : new Optional.of(transformer(_value)); + } + + @override + Iterator get iterator => + isPresent ? [_value].iterator : new Iterable.empty().iterator; + + /// Delegates to the underlying [value] hashCode. + int get hashCode => _value.hashCode; + + /// Delegates to the underlying [value] operator==. + bool operator ==(o) => o is Optional && o._value == _value; + + String toString() { + return _value == null + ? 'Optional { absent }' + : 'Optional { value: ${_value} }'; + } +} +n3CD+2GELG""LL:,$+31/K3.>-(.@<,<#.=8 A3;%ZX5 0 K4'6A +_file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/quiver-2.0.0+1/lib/src/core/hash.dartB// 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. + +part of quiver.core; + +/// Generates a hash code for multiple [objects]. +int hashObjects(Iterable objects) => + _finish(objects.fold(0, (h, i) => _combine(h, i.hashCode))); + +/// Generates a hash code for two objects. +int hash2(a, b) => _finish(_combine(_combine(0, a.hashCode), b.hashCode)); + +/// Generates a hash code for three objects. +int hash3(a, b, c) => _finish( + _combine(_combine(_combine(0, a.hashCode), b.hashCode), c.hashCode)); + +/// Generates a hash code for four objects. +int hash4(a, b, c, d) => _finish(_combine( + _combine(_combine(_combine(0, a.hashCode), b.hashCode), c.hashCode), + d.hashCode)); + +// Jenkins hash functions + +int _combine(int hash, int value) { + hash = 0x1fffffff & (hash + value); + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); +} + +int _finish(int hash) { + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); +} +/3CD+2GELG"2%A+K-J,+I$&<;<ffile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/string_scanner.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A library for parsing strings using a sequence of patterns. +export 'src/exception.dart'; +export 'src/line_scanner.dart'; +export 'src/span_scanner.dart'; +export 'src/string_scanner.dart'; + NN<@ "`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/angel_route-3.0.0/lib/string_util.dart/// Helper functions to performantly transform strings, without `RegExp`. +library angel_route.string_util; + +/// Removes leading and trailing occurrences of a pattern from a string. +String stripStray(String haystack, String needle) { + int firstSlash; + + if (haystack.startsWith(needle)) { + firstSlash = haystack.indexOf(needle); + if (firstSlash == -1) return haystack; + } else { + firstSlash = -1; + } + + if (firstSlash == haystack.length - 1) + return haystack.length == 1 ? '' : haystack.substring(0, firstSlash); + + // Find last leading index of slash + for (int i = firstSlash + 1; i < haystack.length; i++) { + if (haystack[i] != needle) { + var sub = haystack.substring(i); + + if (!sub.endsWith(needle)) return sub; + + var lastSlash = sub.lastIndexOf(needle); + + for (int j = lastSlash - 1; j >= 0; j--) { + if (sub[j] != needle) { + return sub.substring(0, j + 1); + } + } + + return lastSlash == -1 ? sub : sub.substring(0, lastSlash); + } + } + + return haystack.substring(0, firstSlash); +} + +String stripStraySlashes(String str) => stripStray(str, '/'); + +String stripRegexStraySlashes(String str) => stripStray(str, '\\/'); +,J!I4%++ )J&;!'-/1 * +B,>E`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_server-0.9.8/lib/http_server.dart_// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * A library for serving HTTP requests and resources. + * + * ## Installing ## + * + * Use [pub][] to install this package. Add the following to your + * `pubspec.yaml` file. + * + * dependencies: + * http_server: any + * + * Then run `pub install`. + * + * For more information, see the + * [http_server package on pub.dartlang.org][pub]. + * + * ## Basic usage + * + * Here is a short example of how to serve all files from the current + * directory. + * + * import 'dart:io'; + * import 'dart:async'; + * import 'package:http_server/http_server.dart'; + * + * void main() { + * var staticFiles = new VirtualDirectory('.') + * ..allowDirectoryListing = true; + * + * runZoned(() { + * HttpServer.bind('0.0.0.0', 7777).then((server) { + * print('Server running'); + * server.listen(staticFiles.serveRequest); + * }); + * }, + * onError: (e, stackTrace) => print('Oh noes! $e $stackTrace')); + * } + * + * ## Virtual directory + * + * The [VirtualDirectory] class makes it easy to serve static content + * from the file system. It supports: + * + * * Range-based requests. + * * If-Modified-Since based caching. + * * Automatic GZip-compression of content. + * * Following symlinks, either throughout the system or inside + * a jailed root. + * * Directory listing. + * + * See [VirtualDirectory] for more information. + * + * ## Virtual host + * + * The [VirtualHost] class helps to serve multiple hosts on the same + * address, by using the `Host` field of the incoming requests. It also + * works with wildcards for sub-domains. + * + * var virtualHost = new VirtualHost(server); + * // Filter out on a specific host + * var stream1 = virtualServer.addHost('static.myserver.com'); + * // Wildcard for any other sub-domains. + * var stream2 = virtualServer.addHost('*.myserver.com'); + * // Requets not matching any hosts. + * var stream3 = virtualServer.unhandled; + * + * See [VirtualHost] for more information. + * + * [pub]: http://pub.dartlang.org/packages/http_server + */ +library http_server; + +export 'src/http_body.dart'; +export 'src/http_multipart_form_data.dart'; +export 'src/virtual_directory.dart'; +export 'src/virtual_host.dart'; +RNN<6B!3F32(9#3 E F&(.B0EH)2(C.>*.+7,% efile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/body_parser-1.1.1/lib/src/map_from_uri.dartimport 'get_value.dart'; + +/// Parses a URI-encoded string into real data! **Wow!** +/// +/// Whichever map you provide will be automatically populated from the urlencoded body string you provide. +buildMapFromUri(Map map, String body) { + RegExp parseArrayRgx = new RegExp(r'^(.+)\[\]$'); + + for (String keyValuePair in body.split('&')) { + if (keyValuePair.contains('=')) { + var equals = keyValuePair.indexOf('='); + String key = Uri.decodeQueryComponent(keyValuePair.substring(0, equals)); + String value = + Uri.decodeQueryComponent(keyValuePair.substring(equals + 1)); + + if (parseArrayRgx.hasMatch(key)) { + Match queryMatch = parseArrayRgx.firstMatch(key); + key = queryMatch.group(1); + if (!(map[key] is List)) { + map[key] = []; + } + + map[key].add(getValue(value)); + } else if (key.contains('.')) { + // i.e. map.foo.bar => [map, foo, bar] + List keys = key.split('.'); + + Map targetMap = map[keys[0]] ?? {}; + map[keys[0]] = targetMap; + for (int i = 1; i < keys.length; i++) { + if (i < keys.length - 1) { + targetMap[keys[i]] = targetMap[keys[i]] ?? {}; + targetMap = targetMap[keys[i]] as Map; + } else { + targetMap[keys[i]] = getValue(value); + } + } + } else + map[key] = getValue(value); + } else + map[Uri.decodeQueryComponent(keyValuePair)] = true; + } +} +-9k(41&.PH):## +'&/,,"0%;32 + $ :^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/chain.dart // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:math' as math; + +import 'frame.dart'; +import 'lazy_chain.dart'; +import 'stack_zone_specification.dart'; +import 'trace.dart'; +import 'utils.dart'; + +/// A function that handles errors in the zone wrapped by [Chain.capture]. +@Deprecated("Will be removed in stack_trace 2.0.0.") +typedef void ChainHandler(error, Chain chain); + +/// An opaque key used to track the current [StackZoneSpecification]. +final _specKey = new Object(); + +/// A chain of stack traces. +/// +/// A stack chain is a collection of one or more stack traces that collectively +/// represent the path from [main] through nested function calls to a particular +/// code location, usually where an error was thrown. Multiple stack traces are +/// necessary when using asynchronous functions, since the program's stack is +/// reset before each asynchronous callback is run. +/// +/// Stack chains can be automatically tracked using [Chain.capture]. This sets +/// up a new [Zone] in which the current stack chain is tracked and can be +/// accessed using [new Chain.current]. Any errors that would be top-leveled in +/// the zone can be handled, along with their associated chains, with the +/// `onError` callback. For example: +/// +/// Chain.capture(() { +/// // ... +/// }, onError: (error, stackChain) { +/// print("Caught error $error\n" +/// "$stackChain"); +/// }); +class Chain implements StackTrace { + /// The stack traces that make up this chain. + /// + /// Like the frames in a stack trace, the traces are ordered from most local + /// to least local. The first one is the trace where the actual exception was + /// raised, the second one is where that callback was scheduled, and so on. + final List traces; + + /// The [StackZoneSpecification] for the current zone. + static StackZoneSpecification get _currentSpec => Zone.current[_specKey]; + + /// If [when] is `true`, runs [callback] in a [Zone] in which the current + /// stack chain is tracked and automatically associated with (most) errors. + /// + /// If [when] is `false`, this does not track stack chains. Instead, it's + /// identical to [runZoned], except that it wraps any errors in [new + /// Chain.forTrace]—which will only wrap the trace unless there's a different + /// [Chain.capture] active. This makes it easy for the caller to only capture + /// stack chains in debug mode or during development. + /// + /// If [onError] is passed, any error in the zone that would otherwise go + /// unhandled is passed to it, along with the [Chain] associated with that + /// error. Note that if [callback] produces multiple unhandled errors, + /// [onError] may be called more than once. If [onError] isn't passed, the + /// parent Zone's `unhandledErrorHandler` will be called with the error and + /// its chain. + /// + /// If [errorZone] is `true`, the zone this creates will be an error zone, + /// even if [onError] isn't passed. This means that any errors that would + /// cross the zone boundary are considered unhandled. If [errorZone] is + /// `false`, [onError] must be `null`. + /// + /// If [callback] returns a value, it will be returned by [capture] as well. + static T capture(T callback(), + {void onError(error, Chain chain), + bool when: true, + bool errorZone: true}) { + if (!errorZone && onError != null) { + throw new ArgumentError.value( + onError, "onError", "must be null if errorZone is false"); + } + + if (!when) { + var newOnError; + if (onError != null) { + newOnError = (error, stackTrace) { + onError( + error, + stackTrace == null + ? new Chain.current() + : new Chain.forTrace(stackTrace)); + }; + } + + return runZoned(callback, onError: newOnError); + } + + var spec = new StackZoneSpecification(onError, errorZone: errorZone); + return runZoned(() { + try { + return callback(); + } catch (error, stackTrace) { + // TODO(nweiz): Don't special-case this when issue 19566 is fixed. + Zone.current.handleUncaughtError(error, stackTrace); + return null; + } + }, + zoneSpecification: spec.toSpec(), + zoneValues: {_specKey: spec, StackZoneSpecification.disableKey: false}); + } + + /// If [when] is `true` and this is called within a [Chain.capture] zone, runs + /// [callback] in a [Zone] in which chain capturing is disabled. + /// + /// If [callback] returns a value, it will be returned by [disable] as well. + static T disable(T callback(), {bool when: true}) { + var zoneValues = + when ? {_specKey: null, StackZoneSpecification.disableKey: true} : null; + + return runZoned(callback, zoneValues: zoneValues); + } + + /// Returns [futureOrStream] unmodified. + /// + /// Prior to Dart 1.7, this was necessary to ensure that stack traces for + /// exceptions reported with [Completer.completeError] and + /// [StreamController.addError] were tracked correctly. + @Deprecated("Chain.track is not necessary in Dart 1.7+.") + static track(futureOrStream) => futureOrStream; + + /// Returns the current stack chain. + /// + /// By default, the first frame of the first trace will be the line where + /// [Chain.current] is called. If [level] is passed, the first trace will + /// start that many frames up instead. + /// + /// If this is called outside of a [capture] zone, it just returns a + /// single-trace chain. + factory Chain.current([int level = 0]) { + if (_currentSpec != null) return _currentSpec.currentChain(level + 1); + + var chain = new Chain.forTrace(StackTrace.current); + return new LazyChain(() { + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + var first = new Trace( + chain.traces.first.frames.skip(level + (inJS ? 2 : 1)), + original: chain.traces.first.original.toString()); + return new Chain([first]..addAll(chain.traces.skip(1))); + }); + } + + /// Returns the stack chain associated with [trace]. + /// + /// The first stack trace in the returned chain will always be [trace] + /// (converted to a [Trace] if necessary). If there is no chain associated + /// with [trace] or if this is called outside of a [capture] zone, this just + /// returns a single-trace chain containing [trace]. + /// + /// If [trace] is already a [Chain], it will be returned as-is. + factory Chain.forTrace(StackTrace trace) { + if (trace is Chain) return trace; + if (_currentSpec != null) return _currentSpec.chainFor(trace); + if (trace is Trace) return new Chain([trace]); + return new LazyChain(() => new Chain.parse(trace.toString())); + } + + /// Parses a string representation of a stack chain. + /// + /// If [chain] is the output of a call to [Chain.toString], it will be parsed + /// as a full stack chain. Otherwise, it will be parsed as in [Trace.parse] + /// and returned as a single-trace chain. + factory Chain.parse(String chain) { + if (chain.isEmpty) return new Chain([]); + if (chain.contains(vmChainGap)) { + return new Chain( + chain.split(vmChainGap).map((trace) => new Trace.parseVM(trace))); + } + if (!chain.contains(chainGap)) return new Chain([new Trace.parse(chain)]); + + return new Chain( + chain.split(chainGap).map((trace) => new Trace.parseFriendly(trace))); + } + + /// Returns a new [Chain] comprised of [traces]. + Chain(Iterable traces) : traces = new List.unmodifiable(traces); + + /// Returns a terser version of [this]. + /// + /// This calls [Trace.terse] on every trace in [traces], and discards any + /// trace that contain only internal frames. + /// + /// This won't do anything with a raw JavaScript trace, since there's no way + /// to determine which frames come from which Dart libraries. However, the + /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to + /// convert JavaScript traces into Dart-style traces. + /// + /// [source_map_stack_trace]: https://pub.dartlang.org/packages/source_map_stack_trace + Chain get terse => foldFrames((_) => false, terse: true); + + /// Returns a new [Chain] based on [this] where multiple stack frames matching + /// [predicate] are folded together. + /// + /// This means that whenever there are multiple frames in a row that match + /// [predicate], only the last one is kept. In addition, traces that are + /// composed entirely of frames matching [predicate] are omitted. + /// + /// This is useful for limiting the amount of library code that appears in a + /// stack trace by only showing user code and code that's called by user code. + /// + /// If [terse] is true, this will also fold together frames from the core + /// library or from this package, and simplify core library frames as in + /// [Trace.terse]. + Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) { + var foldedTraces = + traces.map((trace) => trace.foldFrames(predicate, terse: terse)); + var nonEmptyTraces = foldedTraces.where((trace) { + // Ignore traces that contain only folded frames. + if (trace.frames.length > 1) return true; + if (trace.frames.isEmpty) return false; + + // In terse mode, the trace may have removed an outer folded frame, + // leaving a single non-folded frame. We can detect a folded frame because + // it has no line information. + if (!terse) return false; + return trace.frames.single.line != null; + }); + + // If all the traces contain only internal processing, preserve the last + // (top-most) one so that the chain isn't empty. + if (nonEmptyTraces.isEmpty && foldedTraces.isNotEmpty) { + return new Chain([foldedTraces.last]); + } + + return new Chain(nonEmptyTraces); + } + + /// Converts [this] to a [Trace]. + /// + /// The trace version of a chain is just the concatenation of all the traces + /// in the chain. + Trace toTrace() => new Trace(traces.expand((trace) => trace.frames)); + + String toString() { + // Figure out the longest path so we know how much to pad. + var longest = traces.map((trace) { + return trace.frames + .map((frame) => frame.location.length) + .fold(0, math.max); + }).fold(0, math.max); + + // Don't call out to [Trace.toString] here because that doesn't ensure that + // padding is consistent across all traces. + return traces.map((trace) { + return trace.frames.map((frame) { + return '${frame.location.padRight(longest)} ${frame.member}\n'; + }).join(); + }).join(chainGap); + } +} +NN<(K5/FPQPN4OKPJ%*( $0OPN9LLNLGPP8LMIMNMLJ)O$))%E+!(5 6J $K=*QQCO9Q7+L=:<2'LL)G+K8L=B=?7IMO7B-&C3C7PN,&-&MOO3Q*L/OMP8Y<Q'MKDOQLKGJ680.JQ% /M5=-&$OH?'1P0 (I^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/frame.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:path/path.dart' as path; + +import 'trace.dart'; +import 'unparsed_frame.dart'; + +// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) +// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42) +// #1 Foo._bar (file:///home/nweiz/code/stuff.dart) +final _vmFrame = new RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); + +// at Object.stringify (native) +// at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) +// at VW.call$0 (eval as fn +// (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28) +// at http://pub.dartlang.org/stuff.dart.js:560:28 +final _v8Frame = + new RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); + +// http://pub.dartlang.org/stuff.dart.js:560:28 +final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)|native$'); + +// eval as function (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28 +// eval as function (http://pub.dartlang.org/stuff.dart.js:560:28) +// eval as function (eval as otherFunction +// (http://pub.dartlang.org/stuff.dart.js:560:28)) +final _v8EvalLocation = + new RegExp(r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); + +// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560:36 +// http://pub.dartlang.org/stuff.dart.js:560 +final _firefoxSafariFrame = new RegExp(r'^' + r'(?:' // Member description. Not present in some Safari frames. + r'([^@(/]*)' // The actual name of the member. + r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox. + r'((?:/[^/]*)*)' // Extra characters indicating a nested closure. + r'(?:\(.*\))?' // Arguments to the closure. + r'@' + r')?' + r'(.*?)' // The frame's URL. + r':' + r'(\d*)' // The line number. Empty in Safari if it's unknown. + r'(?::(\d*))?' // The column number. Not present in older browsers and + // empty in Safari if it's unknown. + r'$'); + +// foo/bar.dart 10:11 Foo._bar +// foo/bar.dart 10:11 (anonymous function).dart.fn +// http://dartlang.org/foo/bar.dart Foo._bar +// data:... 10:11 Foo._bar +final _friendlyFrame = new RegExp(r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); + +/// A regular expression that matches asynchronous member names generated by the +/// VM. +final _asyncBody = new RegExp(r'<(|[^>]+)_async_body>'); + +final _initialDot = new RegExp(r"^\."); + +/// A single stack frame. Each frame points to a precise location in Dart code. +class Frame { + /// The URI of the file in which the code is located. + /// + /// This URI will usually have the scheme `dart`, `file`, `http`, or `https`. + final Uri uri; + + /// The line number on which the code location is located. + /// + /// This can be null, indicating that the line number is unknown or + /// unimportant. + final int line; + + /// The column number of the code location. + /// + /// This can be null, indicating that the column number is unknown or + /// unimportant. + final int column; + + /// The name of the member in which the code location occurs. + /// + /// Anonymous closures are represented as `` in this member string. + final String member; + + /// Whether this stack frame comes from the Dart core libraries. + bool get isCore => uri.scheme == 'dart'; + + /// Returns a human-friendly description of the library that this stack frame + /// comes from. + /// + /// This will usually be the string form of [uri], but a relative URI will be + /// used if possible. Data URIs will be truncated. + String get library { + if (uri.scheme == 'data') return "data:..."; + return path.prettyUri(uri); + } + + /// Returns the name of the package this stack frame comes from, or `null` if + /// this stack frame doesn't come from a `package:` URL. + String get package { + if (uri.scheme != 'package') return null; + return uri.path.split('/').first; + } + + /// A human-friendly description of the code location. + String get location { + if (line == null) return library; + if (column == null) return '$library $line'; + return '$library $line:$column'; + } + + /// Returns a single frame of the current stack. + /// + /// By default, this will return the frame above the current method. If + /// [level] is `0`, it will return the current method's frame; if [level] is + /// higher than `1`, it will return higher frames. + factory Frame.caller([int level = 1]) { + if (level < 0) { + throw new ArgumentError("Argument [level] must be greater than or equal " + "to 0."); + } + + return new Trace.current(level + 1).frames.first; + } + + /// Parses a string representation of a Dart VM stack frame. + factory Frame.parseVM(String frame) => _catchFormatException(frame, () { + // The VM sometimes folds multiple stack frames together and replaces them + // with "...". + if (frame == '...') { + return new Frame(new Uri(), null, null, '...'); + } + + var match = _vmFrame.firstMatch(frame); + if (match == null) return new UnparsedFrame(frame); + + // Get the pieces out of the regexp match. Function, URI and line should + // always be found. The column is optional. + var member = match[1] + .replaceAll(_asyncBody, "") + .replaceAll("", ""); + var uri = Uri.parse(match[2]); + + var lineAndColumn = match[3].split(':'); + var line = + lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null; + var column = + lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null; + return new Frame(uri, line, column, member); + }); + + /// Parses a string representation of a Chrome/V8 stack frame. + factory Frame.parseV8(String frame) => _catchFormatException(frame, () { + var match = _v8Frame.firstMatch(frame); + if (match == null) return new UnparsedFrame(frame); + + // v8 location strings can be arbitrarily-nested, since it adds a layer of + // nesting for each eval performed on that line. + parseLocation(location, member) { + var evalMatch = _v8EvalLocation.firstMatch(location); + while (evalMatch != null) { + location = evalMatch[1]; + evalMatch = _v8EvalLocation.firstMatch(location); + } + + if (location == 'native') { + return new Frame(Uri.parse('native'), null, null, member); + } + + var urlMatch = _v8UrlLocation.firstMatch(location); + if (urlMatch == null) return new UnparsedFrame(frame); + + return new Frame(_uriOrPathToUri(urlMatch[1]), int.parse(urlMatch[2]), + int.parse(urlMatch[3]), member); + } + + // V8 stack frames can be in two forms. + if (match[2] != null) { + // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists + // anonymous functions within eval as "", while IE10 lists them + // as "Anonymous function". + return parseLocation( + match[2], + match[1] + .replaceAll("", "") + .replaceAll("Anonymous function", "") + .replaceAll("(anonymous function)", "")); + } else { + // The second form looks like " at LOCATION", and is used for anonymous + // functions. + return parseLocation(match[3], ""); + } + }); + + /// Parses a string representation of a JavaScriptCore stack trace. + factory Frame.parseJSCore(String frame) => new Frame.parseV8(frame); + + /// Parses a string representation of an IE stack frame. + /// + /// IE10+ frames look just like V8 frames. Prior to IE10, stack traces can't + /// be retrieved. + factory Frame.parseIE(String frame) => new Frame.parseV8(frame); + + /// Parses a string representation of a Firefox stack frame. + factory Frame.parseFirefox(String frame) => _catchFormatException(frame, () { + var match = _firefoxSafariFrame.firstMatch(frame); + if (match == null) return new UnparsedFrame(frame); + + // Normally this is a URI, but in a jsshell trace it can be a path. + var uri = _uriOrPathToUri(match[3]); + + var member; + if (match[1] != null) { + member = match[1]; + member += + new List.filled('/'.allMatches(match[2]).length, ".").join(); + if (member == '') member = ''; + + // Some Firefox members have initial dots. We remove them for consistency + // with other platforms. + member = member.replaceFirst(_initialDot, ''); + } else { + member = ''; + } + + var line = match[4] == '' ? null : int.parse(match[4]); + var column = + match[5] == null || match[5] == '' ? null : int.parse(match[5]); + return new Frame(uri, line, column, member); + }); + + /// Parses a string representation of a Safari 6.0 stack frame. + @Deprecated("Use Frame.parseSafari instead.") + factory Frame.parseSafari6_0(String frame) => new Frame.parseFirefox(frame); + + /// Parses a string representation of a Safari 6.1+ stack frame. + @Deprecated("Use Frame.parseSafari instead.") + factory Frame.parseSafari6_1(String frame) => new Frame.parseFirefox(frame); + + /// Parses a string representation of a Safari stack frame. + factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame); + + /// Parses this package's string representation of a stack frame. + factory Frame.parseFriendly(String frame) => _catchFormatException(frame, () { + var match = _friendlyFrame.firstMatch(frame); + if (match == null) { + throw new FormatException( + "Couldn't parse package:stack_trace stack trace line '$frame'."); + } + // Fake truncated data urls generated by the friendly stack trace format + // cause Uri.parse to throw an exception so we have to special case them. + var uri = match[1] == 'data:...' + ? new Uri.dataFromString('') + : Uri.parse(match[1]); + // If there's no scheme, this is a relative URI. We should interpret it as + // relative to the current working directory. + if (uri.scheme == '') { + uri = path.toUri(path.absolute(path.fromUri(uri))); + } + + var line = match[2] == null ? null : int.parse(match[2]); + var column = match[3] == null ? null : int.parse(match[3]); + return new Frame(uri, line, column, match[4]); + }); + + /// A regular expression matching an absolute URI. + static final _uriRegExp = new RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://'); + + /// A regular expression matching a Windows path. + static final _windowsRegExp = new RegExp(r'^([a-zA-Z]:[\\/]|\\\\)'); + + /// Converts [uriOrPath], which can be a URI, a Windows path, or a Posix path, + /// to a URI (absolute if possible). + static Uri _uriOrPathToUri(String uriOrPath) { + if (uriOrPath.contains(_uriRegExp)) { + return Uri.parse(uriOrPath); + } else if (uriOrPath.contains(_windowsRegExp)) { + return new Uri.file(uriOrPath, windows: true); + } else if (uriOrPath.startsWith('/')) { + return new Uri.file(uriOrPath, windows: false); + } + + // As far as I've seen, Firefox and V8 both always report absolute paths in + // their stack frames. However, if we do get a relative path, we should + // handle it gracefully. + if (uriOrPath.contains('\\')) return path.windows.toUri(uriOrPath); + return Uri.parse(uriOrPath); + } + + /// Runs [body] and returns its result. + /// + /// If [body] throws a [FormatException], returns an [UnparsedFrame] with + /// [text] instead. + static Frame _catchFormatException(String text, Frame body()) { + try { + return body(); + } on FormatException catch (_) { + return new UnparsedFrame(text); + } + } + + Frame(this.uri, this.line, this.column, this.member); + + String toString() => '$location in $member'; +} +7NN<)?<9J$C E7I0AMC+7C8?>;-,E3NF0 +! BK( 3-QQL(P8P=F.H@JC+PP51 P;.&9&1%3JO5*P6?KS: +0<Q4/8'1KK5 +AK0<S9*@&%> &G >AQ/ +0 RU& 5<@R2 + +FG;OC?P;<L- P-T#9 +@M5 +B0OC0O>LDQ6%P +QR))#S6 > +BD7 +5G4GQ'1*#55,6PLH!*LB +%&8/^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/trace.dart8// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:math' as math; + +import 'chain.dart'; +import 'frame.dart'; +import 'lazy_trace.dart'; +import 'unparsed_frame.dart'; +import 'utils.dart'; +import 'vm_trace.dart'; + +final _terseRegExp = new RegExp(r"(-patch)?([/\\].*)?$"); + +/// A RegExp to match V8's stack traces. +/// +/// V8's traces start with a line that's either just "Error" or else is a +/// description of the exception that occurred. That description can be multiple +/// lines, so we just look for any line other than the first that begins with +/// three or four spaces and "at". +final _v8Trace = new RegExp(r"\n ?at "); + +/// A RegExp to match indidual lines of V8's stack traces. +/// +/// This is intended to filter out the leading exception details of the trace +/// though it is possible for the message to match this as well. +final _v8TraceLine = new RegExp(r" ?at "); + +/// A RegExp to match Firefox and Safari's stack traces. +/// +/// Firefox and Safari have very similar stack trace formats, so we use the same +/// logic for parsing them. +/// +/// Firefox's trace frames start with the name of the function in which the +/// error occurred, possibly including its parameters inside `()`. For example, +/// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. +/// +/// Safari traces occasionally don't include the initial method name followed by +/// "@", and they always have both the line and column number (or just a +/// trailing colon if no column number is available). They can also contain +/// empty lines or lines consisting only of `[native code]`. +final _firefoxSafariTrace = new RegExp( + r"^" + r"(" // Member description. Not present in some Safari frames. + r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments. + r"@" + r")?" + r"[^\s]*" // Frame URL. + r":\d*" // Line or column number. Some older frames only have a line number. + r"$", + multiLine: true); + +/// A RegExp to match this package's stack traces. +final _friendlyTrace = + new RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", multiLine: true); + +/// A stack trace, comprised of a list of stack frames. +class Trace implements StackTrace { + /// The stack frames that comprise this stack trace. + final List frames; + + /// The original stack trace from which this trace was parsed. + final StackTrace original; + + /// Returns a human-readable representation of [stackTrace]. If [terse] is + /// set, this folds together multiple stack frames from the Dart core + /// libraries, so that only the core library method directly called from user + /// code is visible (see [Trace.terse]). + static String format(StackTrace stackTrace, {bool terse: true}) { + var trace = new Trace.from(stackTrace); + if (terse) trace = trace.terse; + return trace.toString(); + } + + /// Returns the current stack trace. + /// + /// By default, the first frame of this trace will be the line where + /// [Trace.current] is called. If [level] is passed, the trace will start that + /// many frames up instead. + factory Trace.current([int level = 0]) { + if (level < 0) { + throw new ArgumentError("Argument [level] must be greater than or equal " + "to 0."); + } + + var trace = new Trace.from(StackTrace.current); + return new LazyTrace(() { + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), + original: trace.original.toString()); + }); + } + + /// Returns a new stack trace containing the same data as [trace]. + /// + /// If [trace] is a native [StackTrace], its data will be parsed out; if it's + /// a [Trace], it will be returned as-is. + factory Trace.from(StackTrace trace) { + // Normally explicitly validating null arguments is bad Dart style, but here + // the natural failure will only occur when the LazyTrace is materialized, + // and we want to provide an error that's more local to the actual problem. + if (trace == null) { + throw new ArgumentError("Cannot create a Trace from null."); + } + + if (trace is Trace) return trace; + if (trace is Chain) return trace.toTrace(); + return new LazyTrace(() => new Trace.parse(trace.toString())); + } + + /// Parses a string representation of a stack trace. + /// + /// [trace] should be formatted in the same way as a Dart VM or browser stack + /// trace. If it's formatted as a stack chain, this will return the equivalent + /// of [Chain.toTrace]. + factory Trace.parse(String trace) { + try { + if (trace.isEmpty) return new Trace([]); + if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); + if (trace.contains("\tat ")) return new Trace.parseJSCore(trace); + if (trace.contains(_firefoxSafariTrace)) { + return new Trace.parseFirefox(trace); + } + if (trace.contains(chainGap)) return new Chain.parse(trace).toTrace(); + if (trace.contains(_friendlyTrace)) { + return new Trace.parseFriendly(trace); + } + + // Default to parsing the stack trace as a VM trace. This is also hit on + // IE and Safari, where the stack trace is just an empty string (issue + // 11257). + return new Trace.parseVM(trace); + } on FormatException catch (error) { + throw new FormatException('${error.message}\nStack trace:\n$trace'); + } + } + + /// Parses a string representation of a Dart VM stack trace. + Trace.parseVM(String trace) : this(_parseVM(trace), original: trace); + + static List _parseVM(String trace) { + // Ignore [vmChainGap]. This matches the behavior of + // `Chain.parse().toTrace()`. + var lines = trace.trim().replaceAll(vmChainGap, '').split("\n"); + var frames = lines + .take(lines.length - 1) + .map((line) => new Frame.parseVM(line)) + .toList(); + + // TODO(nweiz): Remove this when issue 23614 is fixed. + if (!lines.last.endsWith(".da")) { + frames.add(new Frame.parseVM(lines.last)); + } + + return frames; + } + + /// Parses a string representation of a Chrome/V8 stack trace. + Trace.parseV8(String trace) + : this( + trace + .split("\n") + .skip(1) + // It's possible that an Exception's description contains a line that + // looks like a V8 trace line, which will screw this up. + // Unfortunately, that's impossible to detect. + .skipWhile((line) => !line.startsWith(_v8TraceLine)) + .map((line) => new Frame.parseV8(line)), + original: trace); + + /// Parses a string representation of a JavaScriptCore stack trace. + Trace.parseJSCore(String trace) + : this( + trace + .split("\n") + .where((line) => line != "\tat ") + .map((line) => new Frame.parseV8(line)), + original: trace); + + /// Parses a string representation of an Internet Explorer stack trace. + /// + /// IE10+ traces look just like V8 traces. Prior to IE10, stack traces can't + /// be retrieved. + Trace.parseIE(String trace) : this.parseV8(trace); + + /// Parses a string representation of a Firefox stack trace. + Trace.parseFirefox(String trace) + : this( + trace + .trim() + .split("\n") + .where((line) => line.isNotEmpty && line != '[native code]') + .map((line) => new Frame.parseFirefox(line)), + original: trace); + + /// Parses a string representation of a Safari stack trace. + Trace.parseSafari(String trace) : this.parseFirefox(trace); + + /// Parses a string representation of a Safari 6.1+ stack trace. + @Deprecated("Use Trace.parseSafari instead.") + Trace.parseSafari6_1(String trace) : this.parseSafari(trace); + + /// Parses a string representation of a Safari 6.0 stack trace. + @Deprecated("Use Trace.parseSafari instead.") + Trace.parseSafari6_0(String trace) + : this( + trace + .trim() + .split("\n") + .where((line) => line != '[native code]') + .map((line) => new Frame.parseFirefox(line)), + original: trace); + + /// Parses this package's string representation of a stack trace. + /// + /// This also parses string representations of [Chain]s. They parse to the + /// same trace that [Chain.toTrace] would return. + Trace.parseFriendly(String trace) + : this( + trace.isEmpty + ? [] + : trace + .trim() + .split("\n") + // Filter out asynchronous gaps from [Chain]s. + .where((line) => !line.startsWith('=====')) + .map((line) => new Frame.parseFriendly(line)), + original: trace); + + /// Returns a new [Trace] comprised of [frames]. + Trace(Iterable frames, {String original}) + : frames = new List.unmodifiable(frames), + original = new StackTrace.fromString(original); + + /// Returns a VM-style [StackTrace] object. + /// + /// The return value's [toString] method will always return a string + /// representation in the Dart VM's stack trace format, regardless of what + /// platform is being used. + StackTrace get vmTrace => new VMTrace(frames); + + /// Returns a terser version of [this]. + /// + /// This is accomplished by folding together multiple stack frames from the + /// core library or from this package, as in [foldFrames]. Remaining core + /// library frames have their libraries, "-patch" suffixes, and line numbers + /// removed. If the outermost frame of the stack trace is a core library + /// frame, it's removed entirely. + /// + /// This won't do anything with a raw JavaScript trace, since there's no way + /// to determine which frames come from which Dart libraries. However, the + /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to + /// convert JavaScript traces into Dart-style traces. + /// + /// [source_map_stack_trace]: https://pub.dartlang.org/packages/source_map_stack_trace + /// + /// For custom folding, see [foldFrames]. + Trace get terse => foldFrames((_) => false, terse: true); + + /// Returns a new [Trace] based on [this] where multiple stack frames matching + /// [predicate] are folded together. + /// + /// This means that whenever there are multiple frames in a row that match + /// [predicate], only the last one is kept. This is useful for limiting the + /// amount of library code that appears in a stack trace by only showing user + /// code and code that's called by user code. + /// + /// If [terse] is true, this will also fold together frames from the core + /// library or from this package, simplify core library frames, and + /// potentially remove the outermost frame as in [Trace.terse]. + Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) { + if (terse) { + var oldPredicate = predicate; + predicate = (frame) { + if (oldPredicate(frame)) return true; + + if (frame.isCore) return true; + if (frame.package == 'stack_trace') return true; + + // Ignore async stack frames without any line or column information. + // These come from the VM's async/await implementation and represent + // internal frames. They only ever show up in stack chains and are + // always surrounded by other traces that are actually useful, so we can + // just get rid of them. + // TODO(nweiz): Get rid of this logic some time after issue 22009 is + // fixed. + if (!frame.member.contains('')) return false; + return frame.line == null; + }; + } + + var newFrames = []; + for (var frame in frames.reversed) { + if (frame is UnparsedFrame || !predicate(frame)) { + newFrames.add(frame); + } else if (newFrames.isEmpty || !predicate(newFrames.last)) { + newFrames + .add(new Frame(frame.uri, frame.line, frame.column, frame.member)); + } + } + + if (terse) { + newFrames = newFrames.map((frame) { + if (frame is UnparsedFrame || !predicate(frame)) return frame; + var library = frame.library.replaceAll(_terseRegExp, ''); + return new Frame(Uri.parse(library), null, null, frame.member); + }).toList(); + + if (newFrames.length > 1 && predicate(newFrames.first)) { + newFrames.removeAt(0); + } + } + + return new Trace(newFrames.reversed, original: this.original.toString()); + } + + /// Returns a human-readable string representation of [this]. + String toString() { + // Figure out the longest path so we know how much to pad. + var longest = + frames.map((frame) => frame.location.length).fold(0, math.max); + + // Print out the stack trace nicely formatted. + return frames.map((frame) { + if (frame is UnparsedFrame) return "$frame\n"; + return '${frame.location.padRight(longest)} ${frame.member}\n'; + }).join(); + } +} +MNN<:)JQN#,;NA.9QLPCQIL=( C@ +Q +3N8$7AMHP+D,$'GQ+P4L=B0EP,)QOPC&0C7PQ& +6EH1.M,/OM')K?H.9"E 0;'1AVI?E9F"29JO5?#M>>>C0@B0%:>DM4$!C@C3378.GM1*NLOK$OMP8Y,<Q'MNP0LFBG$.'9MMKQ!M=# )9DP*GBH@N@?H3 5Ggfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/unparsed_frame.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'frame.dart'; + +/// A frame that failed to parse. +/// +/// The [member] property contains the original frame's contents. +class UnparsedFrame implements Frame { + final Uri uri = new Uri(path: "unparsed"); + final int line = null; + final int column = null; + final bool isCore = false; + final String library = "unparsed"; + final String package = null; + final String location = "unparsed"; + + final String member; + + UnparsedFrame(this.member); + + String toString() => member; +} +NN<"B'-%&gfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/src/allow_anything_parser.dart,// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'arg_parser.dart'; +import 'arg_results.dart'; +import 'option.dart'; +import 'parser.dart'; + +/// An ArgParser that treats *all input* as non-option arguments. +class AllowAnythingParser implements ArgParser { + Map get options => const {}; + Map get commands => const {}; + bool get allowTrailingOptions => false; + bool get allowsAnything => true; + int get usageLineLength => null; + + ArgParser addCommand(String name, [ArgParser parser]) { + throw new UnsupportedError( + "ArgParser.allowAnything().addCommands() isn't supported."); + } + + void addFlag(String name, + {String abbr, + String help, + bool defaultsTo: false, + bool negatable: true, + void callback(bool value), + bool hide: false}) { + throw new UnsupportedError( + "ArgParser.allowAnything().addFlag() isn't supported."); + } + + void addOption(String name, + {String abbr, + String help, + String valueHelp, + Iterable allowed, + Map allowedHelp, + String defaultsTo, + Function callback, + bool allowMultiple: false, + bool splitCommas, + bool hide: false}) { + throw new UnsupportedError( + "ArgParser.allowAnything().addOption() isn't supported."); + } + + void addMultiOption(String name, + {String abbr, + String help, + String valueHelp, + Iterable allowed, + Map allowedHelp, + Iterable defaultsTo, + void callback(List values), + bool splitCommas: true, + bool hide: false}) { + throw new UnsupportedError( + "ArgParser.allowAnything().addMultiOption() isn't supported."); + } + + void addSeparator(String text) { + throw new UnsupportedError( + "ArgParser.allowAnything().addSeparator() isn't supported."); + } + + ArgResults parse(Iterable args) => + new Parser(null, this, args.toList()).parse(); + + String getUsage() => usage; + + String get usage => ""; + + getDefault(String option) { + throw new ArgumentError('No option named $option'); + } + + Option findByAbbreviation(String abbr) => null; +} +RNN<B1/3*##: E! A '! C# '#* H# F-582Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/src/parser.dartn// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'arg_parser.dart'; +import 'arg_parser_exception.dart'; +import 'arg_results.dart'; +import 'option.dart'; + +final _soloOpt = new RegExp(r'^-([a-zA-Z0-9])$'); +final _abbrOpt = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$'); +final _longOpt = new RegExp(r'^--([a-zA-Z\-_0-9]+)(=(.*))?$'); + +/// The actual argument parsing class. +/// +/// Unlike [ArgParser] which is really more an "arg grammar", this is the class +/// that does the parsing and holds the mutable state required during a parse. +class Parser { + /// If parser is parsing a command's options, this will be the name of the + /// command. For top-level results, this returns `null`. + final String commandName; + + /// The parser for the supercommand of this command parser, or `null` if this + /// is the top-level parser. + final Parser parent; + + /// The grammar being parsed. + final ArgParser grammar; + + /// The arguments being parsed. + final List args; + + /// The remaining non-option, non-command arguments. + final rest = []; + + /// The accumulated parsed options. + final Map results = {}; + + Parser(this.commandName, this.grammar, this.args, + [this.parent, List rest]) { + if (rest != null) this.rest.addAll(rest); + } + + /// The current argument being parsed. + String get current => args[0]; + + /// Parses the arguments. This can only be called once. + ArgResults parse() { + var arguments = args.toList(); + if (grammar.allowsAnything) { + return newArgResults( + grammar, const {}, commandName, null, arguments, arguments); + } + + ArgResults commandResults; + + // Parse the args. + while (args.length > 0) { + if (current == '--') { + // Reached the argument terminator, so stop here. + args.removeAt(0); + break; + } + + // Try to parse the current argument as a command. This happens before + // options so that commands can have option-like names. + var command = grammar.commands[current]; + if (command != null) { + validate(rest.isEmpty, 'Cannot specify arguments before a command.'); + var commandName = args.removeAt(0); + var commandParser = new Parser(commandName, command, args, this, rest); + + try { + commandResults = commandParser.parse(); + } on ArgParserException catch (error) { + if (commandName == null) rethrow; + throw new ArgParserException( + error.message, [commandName]..addAll(error.commands)); + } + + // All remaining arguments were passed to command so clear them here. + rest.clear(); + break; + } + + // Try to parse the current argument as an option. Note that the order + // here matters. + if (parseSoloOption()) continue; + if (parseAbbreviation(this)) continue; + if (parseLongOption()) continue; + + // This argument is neither option nor command, so stop parsing unless + // the [allowTrailingOptions] option is set. + if (!grammar.allowTrailingOptions) break; + rest.add(args.removeAt(0)); + } + + // Invoke the callbacks. + grammar.options.forEach((name, option) { + if (option.callback == null) return; + option.callback(option.getOrDefault(results[name])); + }); + + // Add in the leftover arguments we didn't parse to the innermost command. + rest.addAll(args); + args.clear(); + return newArgResults( + grammar, results, commandName, commandResults, rest, arguments); + } + + /// Pulls the value for [option] from the second argument in [args]. + /// + /// Validates that there is a valid value there. + void readNextArgAsValue(Option option) { + // Take the option argument from the next command line arg. + validate(args.length > 0, 'Missing argument for "${option.name}".'); + + setOption(results, option, current); + args.removeAt(0); + } + + /// Tries to parse the current argument as a "solo" option, which is a single + /// hyphen followed by a single letter. + /// + /// We treat this differently than collapsed abbreviations (like "-abc") to + /// handle the possible value that may follow it. + bool parseSoloOption() { + var soloOpt = _soloOpt.firstMatch(current); + if (soloOpt == null) return false; + + var option = grammar.findByAbbreviation(soloOpt[1]); + if (option == null) { + // Walk up to the parent command if possible. + validate( + parent != null, 'Could not find an option or flag "-${soloOpt[1]}".'); + return parent.parseSoloOption(); + } + + args.removeAt(0); + + if (option.isFlag) { + setFlag(results, option, true); + } else { + readNextArgAsValue(option); + } + + return true; + } + + /// Tries to parse the current argument as a series of collapsed abbreviations + /// (like "-abc") or a single abbreviation with the value directly attached + /// to it (like "-mrelease"). + bool parseAbbreviation(Parser innermostCommand) { + var abbrOpt = _abbrOpt.firstMatch(current); + if (abbrOpt == null) return false; + + // If the first character is the abbreviation for a non-flag option, then + // the rest is the value. + var c = abbrOpt[1].substring(0, 1); + var first = grammar.findByAbbreviation(c); + if (first == null) { + // Walk up to the parent command if possible. + validate( + parent != null, 'Could not find an option with short name "-$c".'); + return parent.parseAbbreviation(innermostCommand); + } else if (!first.isFlag) { + // The first character is a non-flag option, so the rest must be the + // value. + var value = '${abbrOpt[1].substring(1)}${abbrOpt[2]}'; + setOption(results, first, value); + } else { + // If we got some non-flag characters, then it must be a value, but + // if we got here, it's a flag, which is wrong. + validate( + abbrOpt[2] == '', + 'Option "-$c" is a flag and cannot handle value ' + '"${abbrOpt[1].substring(1)}${abbrOpt[2]}".'); + + // Not an option, so all characters should be flags. + // We use "innermostCommand" here so that if a parent command parses the + // *first* letter, subcommands can still be found to parse the other + // letters. + for (var i = 0; i < abbrOpt[1].length; i++) { + var c = abbrOpt[1].substring(i, i + 1); + innermostCommand.parseShortFlag(c); + } + } + + args.removeAt(0); + return true; + } + + void parseShortFlag(String c) { + var option = grammar.findByAbbreviation(c); + if (option == null) { + // Walk up to the parent command if possible. + validate( + parent != null, 'Could not find an option with short name "-$c".'); + parent.parseShortFlag(c); + return; + } + + // In a list of short options, only the first can be a non-flag. If + // we get here we've checked that already. + validate( + option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".'); + + setFlag(results, option, true); + } + + /// Tries to parse the current argument as a long-form named option, which + /// may include a value like "--mode=release" or "--mode release". + bool parseLongOption() { + var longOpt = _longOpt.firstMatch(current); + if (longOpt == null) return false; + + var name = longOpt[1]; + var option = grammar.options[name]; + if (option != null) { + args.removeAt(0); + if (option.isFlag) { + validate(longOpt[3] == null, + 'Flag option "$name" should not be given a value.'); + + setFlag(results, option, true); + } else if (longOpt[3] != null) { + // We have a value like --foo=bar. + setOption(results, option, longOpt[3]); + } else { + // Option like --foo, so look for the value as the next arg. + readNextArgAsValue(option); + } + } else if (name.startsWith('no-')) { + // See if it's a negated flag. + name = name.substring('no-'.length); + option = grammar.options[name]; + if (option == null) { + // Walk up to the parent command if possible. + validate(parent != null, 'Could not find an option named "$name".'); + return parent.parseLongOption(); + } + + args.removeAt(0); + validate(option.isFlag, 'Cannot negate non-flag option "$name".'); + validate(option.negatable, 'Cannot negate option "$name".'); + + setFlag(results, option, false); + } else { + // Walk up to the parent command if possible. + validate(parent != null, 'Could not find an option named "$name".'); + return parent.parseLongOption(); + } + + return true; + } + + /// Called during parsing to validate the arguments. + /// + /// Throws an [ArgParserException] if [condition] is `false`. + void validate(bool condition, String message) { + if (!condition) throw new ArgParserException(message); + } + + /// Validates and stores [value] as the value for [option], which must not be + /// a flag. + void setOption(Map results, Option option, String value) { + assert(!option.isFlag); + + if (!option.isMultiple) { + _validateAllowed(option, value); + results[option.name] = value; + return; + } + + var list = results.putIfAbsent(option.name, () => []); + + if (option.splitCommas) { + for (var element in value.split(",")) { + _validateAllowed(option, element); + list.add(element); + } + } else { + _validateAllowed(option, value); + list.add(value); + } + } + + /// Validates and stores [value] as the value for [option], which must be a + /// flag. + void setFlag(Map results, Option option, bool value) { + assert(option.isFlag); + results[option.name] = value; + } + + /// Validates that [value] is allowed as a value of [option]. + void _validateAllowed(Option option, String value) { + if (option.allowed == null) return; + + validate(option.allowed.contains(value), + '"$value" is not an allowed value for option "${option.name}".'); + } +} +0NN<$27?'POM;P "7&<4*.)!:#"G:M>/N,P20,(E +NM'-'M30"-+;OIG3+@I)P*N40'94Q'& "QN 40'N(/4N9 K=( J6<9;OK40,"04N H/Q$ME0'(%A('+0E$)%+&6M)IC' 4K'7@2;P='$C.+ 'N 9"@7(-JWfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/args-1.5.0/lib/src/usage.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:math' as math; + +import '../args.dart'; + +/// Takes an [ArgParser] and generates a string of usage (i.e. help) text for +/// its defined options. +/// +/// Internally, it works like a tabular printer. The output is divided into +/// three horizontal columns, like so: +/// +/// -h, --help Prints the usage information +/// | | | | +/// +/// It builds the usage text up one column at a time and handles padding with +/// spaces and wrapping to the next line to keep the cells correctly lined up. +class Usage { + /// Abbreviation, long name, help. + static const _columnCount = 3; + + /// A list of the [Option]s intermingled with [String] separators. + final List optionsAndSeparators; + + /// The working buffer for the generated usage text. + StringBuffer buffer; + + /// The column that the "cursor" is currently on. + /// + /// If the next call to [write()] is not for this column, it will correctly + /// handle advancing to the next column (and possibly the next row). + int currentColumn = 0; + + /// The width in characters of each column. + List columnWidths; + + /// The number of sequential lines of text that have been written to the last + /// column (which shows help info). + /// + /// We track this so that help text that spans multiple lines can be padded + /// with a blank line after it for separation. Meanwhile, sequential options + /// with single-line help will be compacted next to each other. + int numHelpLines = 0; + + /// How many newlines need to be rendered before the next bit of text can be + /// written. + /// + /// We do this lazily so that the last bit of usage doesn't have dangling + /// newlines. We only write newlines right *before* we write some real + /// content. + int newlinesNeeded = 0; + + /// The horizontal character position at which help text is wrapped. Help that + /// extends past this column will be wrapped at the nearest whitespace (or + /// truncated if there is no available whitespace). + final int lineLength; + + Usage(this.optionsAndSeparators, {this.lineLength}); + + /// Generates a string displaying usage information for the defined options. + /// This is basically the help text shown on the command line. + String generate() { + buffer = new StringBuffer(); + + calculateColumnWidths(); + + for (var optionOrSeparator in optionsAndSeparators) { + if (optionOrSeparator is String) { + // Ensure that there's always a blank line before a separator. + if (buffer.isNotEmpty) buffer.write("\n\n"); + buffer.write(optionOrSeparator); + newlinesNeeded = 1; + continue; + } + + var option = optionOrSeparator as Option; + if (option.hide) continue; + + write(0, getAbbreviation(option)); + write(1, getLongOption(option)); + + if (option.help != null) write(2, option.help); + + if (option.allowedHelp != null) { + var allowedNames = option.allowedHelp.keys.toList(growable: false); + allowedNames.sort(); + newline(); + for (var name in allowedNames) { + write(1, getAllowedTitle(option, name)); + write(2, option.allowedHelp[name]); + } + newline(); + } else if (option.allowed != null) { + write(2, buildAllowedList(option)); + } else if (option.isFlag) { + if (option.defaultsTo == true) { + write(2, '(defaults to on)'); + } + } else if (option.isMultiple) { + if (option.defaultsTo != null && option.defaultsTo.isNotEmpty) { + write( + 2, + '(defaults to ' + + option.defaultsTo.map((value) => '"$value"').join(', ') + + ')'); + } + } else { + if (option.defaultsTo != null) { + write(2, '(defaults to "${option.defaultsTo}")'); + } + } + + // If any given option displays more than one line of text on the right + // column (i.e. help, default value, allowed options, etc.) then put a + // blank line after it. This gives space where it's useful while still + // keeping simple one-line options clumped together. + if (numHelpLines > 1) newline(); + } + + return buffer.toString(); + } + + String getAbbreviation(Option option) => + option.abbr == null ? '' : '-${option.abbr}, '; + + String getLongOption(Option option) { + var result; + if (option.negatable) { + result = '--[no-]${option.name}'; + } else { + result = '--${option.name}'; + } + + if (option.valueHelp != null) result += "=<${option.valueHelp}>"; + + return result; + } + + String getAllowedTitle(Option option, String allowed) { + var isDefault = option.defaultsTo is List + ? option.defaultsTo.contains(allowed) + : option.defaultsTo == allowed; + return ' [$allowed]' + (isDefault ? ' (default)' : ''); + } + + void calculateColumnWidths() { + var abbr = 0; + var title = 0; + for (var option in optionsAndSeparators) { + if (option is! Option) continue; + if (option.hide) continue; + + // Make room in the first column if there are abbreviations. + abbr = math.max(abbr, getAbbreviation(option).length); + + // Make room for the option. + title = math.max(title, getLongOption(option).length); + + // Make room for the allowed help. + if (option.allowedHelp != null) { + for (var allowed in option.allowedHelp.keys) { + title = math.max(title, getAllowedTitle(option, allowed).length); + } + } + } + + // Leave a gutter between the columns. + title += 4; + columnWidths = [abbr, title]; + } + + void newline() { + newlinesNeeded++; + currentColumn = 0; + numHelpLines = 0; + } + + /// Wraps a single line of text into lines no longer than [lineLength], + /// starting at the [start] column. + /// + /// Tries to split at whitespace, but if that's not good enough to keep it + /// under the limit, then splits in the middle of a word. + List _wrap(String text, int start) { + assert(lineLength != null, "Should wrap when given a length."); + assert(start >= 0); + + text = text.trim(); + + var length = math.max(lineLength - start, 10); + if (text.length <= length) return [text]; + + var result = []; + var currentLineStart = 0; + int lastWhitespace; + for (var i = 0; i < text.length; ++i) { + if (_isWhitespace(text, i)) lastWhitespace = i; + + if (i - currentLineStart >= length) { + // Back up to the last whitespace, unless there wasn't any, in which + // case we just split where we are. + if (lastWhitespace != null) i = lastWhitespace; + + result.add(text.substring(currentLineStart, i)); + + // Skip any intervening whitespace. + while (_isWhitespace(text, i) && i < text.length) i++; + + currentLineStart = i; + lastWhitespace = null; + } + } + + result.add(text.substring(currentLineStart)); + return result; + } + + void write(int column, String text) { + var lines = text.split('\n'); + // If we are writing the last column, word wrap it to fit. + if (column == columnWidths.length && lineLength != null) { + var wrappedLines = []; + var start = columnWidths + .sublist(0, column) + .reduce((start, width) => start += width); + + for (var line in lines) { + wrappedLines.addAll(_wrap(line, start)); + } + + lines = wrappedLines; + } + + // Strip leading and trailing empty lines. + while (lines.length > 0 && lines[0].trim() == '') { + lines.removeRange(0, 1); + } + + while (lines.length > 0 && lines[lines.length - 1].trim() == '') { + lines.removeLast(); + } + + for (var line in lines) { + writeLine(column, line); + } + } + + void writeLine(int column, String text) { + // Write any pending newlines. + while (newlinesNeeded > 0) { + buffer.write('\n'); + newlinesNeeded--; + } + + // Advance until we are at the right column (which may mean wrapping around + // to the next line. + while (currentColumn != column) { + if (currentColumn < _columnCount - 1) { + buffer.write(' ' * columnWidths[currentColumn]); + } else { + buffer.write('\n'); + } + currentColumn = (currentColumn + 1) % _columnCount; + } + + if (column < columnWidths.length) { + // Fixed-size column, so pad it. + buffer.write(text.padRight(columnWidths[column])); + } else { + // The last column, so just write it. + buffer.write(text); + } + + // Advance to the next column. + currentColumn = (currentColumn + 1) % _columnCount; + + // If we reached the last column, we need to wrap to the next line. + if (column == _columnCount - 1) newlinesNeeded++; + + // Keep track of how many consecutive lines we've written in the last + // column. + if (column == _columnCount - 1) { + numHelpLines++; + } else { + numHelpLines = 0; + } + } + + String buildAllowedList(Option option) { + var isDefault = option.defaultsTo is List + ? option.defaultsTo.contains + : (value) => value == option.defaultsTo; + + var allowedBuffer = new StringBuffer(); + allowedBuffer.write('['); + var first = true; + for (var allowed in option.allowed) { + if (!first) allowedBuffer.write(', '); + allowedBuffer.write(allowed); + if (isDefault(allowed)) { + allowedBuffer.write(' (default)'); + } + first = false; + } + allowedBuffer.write(']'); + return allowedBuffer.toString(); + } +} + +/// Returns true if the code unit at [index] in [text] is a whitespace +/// character. +/// +/// Based on: https://en.wikipedia.org/wiki/Whitespace_character#Unicode +bool _isWhitespace(String text, int index) { + var rune = text.codeUnitAt(index); + return rune >= 0x0009 && rune <= 0x000D || + rune == 0x0020 || + rune == 0x0085 || + rune == 0x1680 || + rune == 0x180E || + rune >= 0x2000 && rune <= 0x200A || + rune == 0x2028 || + rune == 0x2029 || + rune == 0x202F || + rune == 0x205F || + rune == 0x3000 || + rune == 0xFEFF; +} +KNN<NL'18NO%!E#74NG.P&NOBOLIQM67OA!:)G5)0!)'6(L)3. ++,")( +&I L +)< +NMM;'+6(( #F:..(A!/'!C=#=)(7L ++"J&M _byteToHex; + Map _hexToByte; + + Uuid() { + _byteToHex = new List(256); + _hexToByte = new Map(); + + // Easy number <-> hex conversion + for (var i = 0; i < 256; i++) { + var hex = new List(); + hex.add(i); + _byteToHex[i] = convert.hex.encode(hex); + _hexToByte[_byteToHex[i]] = i; + } + + // Sets initial seedBytes, node, and clock seq based on MathRNG. + _seedBytes = UuidUtil.mathRNG(); + + // Per 4.5, create a 48-bit node id (47 random bits + multicast bit = 1) + _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], + _seedBytes[2], + _seedBytes[3], + _seedBytes[4], + _seedBytes[5] + ]; + + // Per 4.2.2, randomize (14 bit) clockseq + _clockSeq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3ffff; + } + + /** + * Parses the provided [uuid] into a list of byte values. + * Can optionally be provided a [buffer] to write into and + * a positional [offset] for where to start inputting into the buffer. + */ + List parse(String uuid, {List buffer, int offset: 0}) { + var i = offset, ii = 0; + + // Create a 16 item buffer if one hasn't been provided. + buffer = (buffer != null) ? buffer : new List(16); + + // Convert to lowercase and replace all hex with bytes then + // string.replaceAll() does a lot of work that I don't need, and a manual + // regex gives me more control. + final RegExp regex = new RegExp('[0-9a-f]{2}'); + for (Match match in regex.allMatches(uuid.toLowerCase())) { + if (ii < 16) { + var hex = uuid.toLowerCase().substring(match.start, match.end); + buffer[i + ii++] = _hexToByte[hex]; + } + } + + // Zero out any left over bytes if the string was too short. + while (ii < 16) { + buffer[i + ii++] = 0; + } + + return buffer; + } + + /** + * Unparses a [buffer] of bytes and outputs a proper UUID string. + * An optional [offset] is allowed if you want to start at a different point + * in the buffer. + */ + String unparse(List buffer, {int offset: 0}) { + var i = offset; + return '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}' + '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}-' + '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}-' + '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}-' + '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}-' + '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}' + '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}' + '${_byteToHex[buffer[i++]]}${_byteToHex[buffer[i++]]}'; + } + + /** + * v1() Generates a time-based version 1 UUID + * + * By default it will generate a string based off current time, and will + * return a string. + * + * If an optional [buffer] list is provided, it will put the byte data into + * that buffer and return a buffer. + * + * Optionally an [offset] can be provided with a start position in the buffer. + * + * The first argument is an options map that takes various configuration + * options detailed in the readme. + * + * http://tools.ietf.org/html/rfc4122.html#section-4.2.2 + */ + v1({Map options: null, List buffer: null, int offset: 0}) { + var i = offset; + var buf = (buffer != null) ? buffer : new List(16); + options = (options != null) ? options : new Map(); + + var clockSeq = + (options['clockSeq'] != null) ? options['clockSeq'] : _clockSeq; + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). Time is handled internally as 'msecs' (integer + // milliseconds) and 'nsecs' (100-nanoseconds offset from msecs) since unix + // epoch, 1970-01-01 00:00. + var mSecs = (options['mSecs'] != null) + ? options['mSecs'] + : (new DateTime.now()).millisecondsSinceEpoch; + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nSecs = (options['nSecs'] != null) ? options['nSecs'] : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (mSecs - _lastMSecs) + (nSecs - _lastNSecs) / 10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options['clockSeq'] == null) { + clockSeq = clockSeq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || mSecs > _lastMSecs) && options['nSecs'] == null) { + nSecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nSecs >= 10000) { + throw new Exception('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = mSecs; + _lastNSecs = nSecs; + _clockSeq = clockSeq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + mSecs += 12219292800000; + + // time Low + var tl = ((mSecs & 0xfffffff) * 10000 + nSecs) % 0x100000000; + buf[i++] = tl >> 24 & 0xff; + buf[i++] = tl >> 16 & 0xff; + buf[i++] = tl >> 8 & 0xff; + buf[i++] = tl & 0xff; + + // time mid + var tmh = (mSecs ~/ 0x100000000 * 10000) & 0xfffffff; + buf[i++] = tmh >> 8 & 0xff; + buf[i++] = tmh & 0xff; + + // time high and version + buf[i++] = tmh >> 24 & 0xf | 0x10; // include version + buf[i++] = tmh >> 16 & 0xff; + + // clockSeq high and reserved (Per 4.2.2 - include variant) + buf[i++] = clockSeq >> 8 | 0x80; + + // clockSeq low + buf[i++] = clockSeq & 0xff; + + // node + var node = (options['node'] != null) ? options['node'] : _nodeId; + for (var n = 0; n < 6; n++) { + buf[i + n] = node[n]; + } + + return (buffer != null) ? buffer : unparse(buf); + } + + /** + * v4() Generates a time-based version 4 UUID + * + * By default it will generate a string based AES-based RNG, and will return + * a string. + * + * If an optional [buffer] list is provided, it will put the byte data into + * that buffer and return a buffer. + * + * Optionally an [offset] can be provided with a start position in the buffer. + * + * The first argument is an options map that takes various configuration + * options detailed in the readme. + * + * http://tools.ietf.org/html/rfc4122.html#section-4.4 + */ + v4({Map options: null, List buffer: null, int offset: 0}) { + var i = offset; + options = (options != null) ? options : new Map(); + + // Use the built-in RNG or a custom provided RNG + var positionalArgs = + (options['positionalArgs'] != null) ? options['positionalArgs'] : []; + var namedArgs = (options['namedArgs'] != null) + ? options['namedArgs'] as Map + : const {}; + var rng = (options['rng'] != null) + ? Function.apply(options['rng'], positionalArgs, namedArgs) + : UuidUtil.mathRNG(); + + // Use provided values over RNG + var rnds = (options['random'] != null) ? options['random'] : rng; + + // per 4.4, set bits for version and clockSeq high and reserved + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy the bytes to the buffer if one is provided. + if (buffer != null) { + for (var j = 0; j < 16; j++) { + buffer[i + j] = rnds[j]; + } + } + + return (buffer != null) ? buffer : unparse(rnds); + } + + /** + * v5() Generates a namspace & name-based version 5 UUID + * + * By default it will generate a string based on a provided uuid namespace and + * name, and will return a string. + * + * If an optional [buffer] list is provided, it will put the byte data into + * that buffer and return a buffer. + * + * Optionally an [offset] can be provided with a start position in the buffer. + * + * The first argument is an options map that takes various configuration + * options detailed in the readme. + * + * http://tools.ietf.org/html/rfc4122.html#section-4.4 + */ + v5(String namespace, String name, + {Map options: null, List buffer: null, int offset: 0}) { + var i = offset; + options = (options != null) ? options : new Map(); + + // Check if user wants a random namespace generated by v4() or a NIL namespace. + var useRandom = (options['randomNamespace'] != null) + ? options['randomNamespace'] + : true; + + // If useRandom is true, generate UUIDv4, else use NIL + var blankNS = useRandom ? v4() : NAMESPACE_NIL; + + // Use provided namespace, or use whatever is decided by options. + namespace = (namespace != null) ? namespace : blankNS; + + // Use provided name, + name = (name != null) ? name : ''; + + // Convert namespace UUID to Byte List + var bytes = parse(namespace); + + // Convert name to a list of bytes + var nameBytes = new List(); + for (var singleChar in name.codeUnits) { + nameBytes.add(singleChar); + } + + // Generate SHA1 using namespace concatenated with name + List hashBytes = + sha1.convert(new List.from(bytes)..addAll(nameBytes)).bytes; + + // per 4.4, set bits for version and clockSeq high and reserved + hashBytes[6] = (hashBytes[6] & 0x0f) | 0x50; + hashBytes[8] = (hashBytes[8] & 0x3f) | 0x80; + + // Copy the bytes to the buffer if one is provided. + if (buffer != null) { + for (var j = 0; j < 16; j++) { + buffer[i + j] = hashBytes[j]; + } + } + + return (buffer != null) ? buffer : unparse(hashBytes); + } +} +5%2' * EGGGHGF ()&$!/%E%M.@<=JD<<@N$4@H,ADO1B@@@@??@0KN&QK%;>87ILJP +7K1P0B61(OF?O>B : :!@%  F"50ON&QK%9OH5N37%'D$FD''8%!6;Q%N&QK%9$?7T9%;4F;'+"'%-!<ED118%&;]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/scan.dartT// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A library for broadly-useful functions and regular expressions for scanning +/// HTTP entities. +/// +/// Many of the regular expressions come from [section 2.2 of the HTTP +/// spec][spec]. +/// +/// [spec]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html +import 'package:string_scanner/string_scanner.dart'; + +/// HTTP entities. +/// +/// Many of the regular expressions come from [section 2.2 of the HTTP +/// spec][spec]. +/// +/// [spec]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html + +/// An HTTP token. +final token = new RegExp(r'[^()<>@,;:"\\/[\]?={} \t\x00-\x1F\x7F]+'); + +/// Linear whitespace. +final _lws = new RegExp(r"(?:\r\n)?[ \t]+"); + +/// A quoted string. +final _quotedString = new RegExp(r'"(?:[^"\x00-\x1F\x7F]|\\.)*"'); + +/// A quoted pair. +final _quotedPair = new RegExp(r'\\(.)'); + +/// A character that is *not* a valid HTTP token. +final nonToken = new RegExp(r'[()<>@,;:"\\/\[\]?={} \t\x00-\x1F\x7F]'); + +/// A regular expression matching any number of [_lws] productions in a row. +final whitespace = new RegExp("(?:${_lws.pattern})*"); + +/// Parses a list of elements, as in `1#element` in the HTTP spec. +/// +/// [scanner] is used to parse the elements, and [parseElement] is used to parse +/// each one individually. The values returned by [parseElement] are collected +/// in a list and returned. +/// +/// Once this is finished, [scanner] will be at the next non-LWS character in +/// the string, or the end of the string. +List parseList(StringScanner scanner, T parseElement()) { + var result = []; + + // Consume initial empty values. + while (scanner.scan(",")) { + scanner.scan(whitespace); + } + + result.add(parseElement()); + scanner.scan(whitespace); + + while (scanner.scan(",")) { + scanner.scan(whitespace); + + // Empty elements are allowed, but excluded from the results. + if (scanner.matches(",") || scanner.isDone) continue; + + result.add(parseElement()); + scanner.scan(whitespace); + } + + return result; +} + +/// Parses a single quoted string, and returns its contents. +/// +/// If [name] is passed, it's used to describe the expected value if it's not +/// found. +String expectQuotedString(StringScanner scanner, {String name}) { + if (name == null) name = "quoted string"; + scanner.expect(_quotedString, name: name); + var string = scanner.lastMatch[0]; + return string + .substring(1, string.length - 1) + .replaceAllMapped(_quotedPair, (match) => match[1]); +} +TNN<PGB5GBF-C*2HM7CQON*@#B: =N B,-%';^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/utils.dartI// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +/// Runs [body] and wraps any format exceptions it produces. +/// +/// [name] should describe the type of thing being parsed, and [value] should be +/// its actual value. +T wrapFormatException(String name, String value, T body()) { + try { + return body(); + } on SourceSpanFormatException catch (error) { + throw new SourceSpanFormatException( + 'Invalid $name: ${error.message}', error.span, error.source); + } on FormatException catch (error) { + throw new FormatException( + 'Invalid $name "$value": ${error.message}', error.source, error.offset); + } +} +NN</=Q@1)F'Qofile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/chunked_coding/encoder.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:charcode/ascii.dart'; + +/// The canonical instance of [ChunkedCodingEncoder]. +const chunkedCodingEncoder = const ChunkedCodingEncoder._(); + +/// The chunk indicating that the chunked message has finished. +final _doneChunk = new Uint8List.fromList([$0, $cr, $lf, $cr, $lf]); + +/// A converter that encodes byte arrays into chunks with size tags. +class ChunkedCodingEncoder extends Converter, List> { + const ChunkedCodingEncoder._(); + + List convert(List bytes) => + _convert(bytes, 0, bytes.length, isLast: true); + + ByteConversionSink startChunkedConversion(Sink> sink) => + new _Sink(sink); +} + +/// A conversion sink for the chunked transfer encoding. +class _Sink extends ByteConversionSinkBase { + /// The underlying sink to which encoded byte arrays will be passed. + final Sink> _sink; + + _Sink(this._sink); + + void add(List chunk) { + _sink.add(_convert(chunk, 0, chunk.length)); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + _sink.add(_convert(chunk, start, end, isLast: isLast)); + if (isLast) _sink.close(); + } + + void close() { + _sink.add(_doneChunk); + _sink.close(); + } +} + +/// Returns a new list a chunked transfer encoding header followed by the slice +/// of [bytes] from [start] to [end]. +/// +/// If [isLast] is `true`, this adds the footer that indicates that the chunked +/// message is complete. +List _convert(List bytes, int start, int end, {bool isLast: false}) { + if (end == start) return isLast ? _doneChunk : const []; + + var size = end - start; + var sizeInHex = size.toRadixString(16); + var footerSize = isLast ? _doneChunk.length : 0; + + // Add 4 for the CRLF sequences that follow the size header and the bytes. + var list = new Uint8List(sizeInHex.length + 4 + size + footerSize); + list.setRange(0, sizeInHex.length, sizeInHex.codeUnits); + + var cursor = sizeInHex.length; + list[cursor++] = $cr; + list[cursor++] = $lf; + list.setRange(cursor, cursor + end - start, bytes, start); + cursor += end - start; + list[cursor++] = $cr; + list[cursor++] = $lf; + + if (isLast) { + list.setRange(list.length - footerSize, list.length, _doneChunk); + } + return list; +} +PNN<&6=@EEE"(6E9-G1D:<P&PP;*3MF;!=Fofile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/src/chunked_coding/decoder.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:math' as math; +import 'dart:typed_data'; + +import 'package:charcode/ascii.dart'; +import 'package:typed_data/typed_data.dart'; + +/// The canonical instance of [ChunkedCodingDecoder]. +const chunkedCodingDecoder = const ChunkedCodingDecoder._(); + +/// A converter that decodes byte arrays into chunks with size tags. +class ChunkedCodingDecoder extends Converter, List> { + const ChunkedCodingDecoder._(); + + List convert(List bytes) { + var sink = new _Sink(null); + var output = sink._decode(bytes, 0, bytes.length); + if (sink._state == _State.end) return output; + + throw new FormatException("Input ended unexpectedly.", bytes, bytes.length); + } + + ByteConversionSink startChunkedConversion(Sink> sink) => + new _Sink(sink); +} + +/// A conversion sink for the chunked transfer encoding. +class _Sink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The current state of the sink's parsing. + var _state = _State.boundary; + + /// The size of the chunk being parsed, or `null` if the size hasn't been + /// parsed yet. + int _size; + + _Sink(this._sink); + + void add(List chunk) => addSlice(chunk, 0, chunk.length, false); + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + var output = _decode(chunk, start, end); + if (output.isNotEmpty) _sink.add(output); + if (isLast) _close(chunk, end); + } + + void close() => _close(); + + /// Like [close], but includes [chunk] and [index] in the [FormatException] if + /// one is thrown. + void _close([List chunk, int index]) { + if (_state != _State.end) { + throw new FormatException("Input ended unexpectedly.", chunk, index); + } + + _sink.close(); + } + + /// Decodes the data in [bytes] from [start] to [end]. + Uint8List _decode(List bytes, int start, int end) { + /// Throws a [FormatException] if `bytes[start] != $char`. Uses [name] to + /// describe the character in the exception text. + assertCurrentChar(int char, String name) { + if (bytes[start] != char) { + throw new FormatException("Expected $name.", bytes, start); + } + } + + var buffer = new Uint8Buffer(); + while (start != end) { + switch (_state) { + case _State.boundary: + _size = _digitForByte(bytes, start); + _state = _State.size; + start++; + break; + + case _State.size: + if (bytes[start] == $cr) { + _state = _State.sizeBeforeLF; + } else { + // Shift four bits left since a single hex digit contains four bits + // of information. + _size = (_size << 4) + _digitForByte(bytes, start); + } + start++; + break; + + case _State.sizeBeforeLF: + assertCurrentChar($lf, "LF"); + _state = _size == 0 ? _State.endBeforeCR : _State.body; + start++; + break; + + case _State.body: + var chunkEnd = math.min(end, start + _size); + buffer.addAll(bytes, start, chunkEnd); + _size -= chunkEnd - start; + start = chunkEnd; + if (_size == 0) _state = _State.bodyBeforeCR; + break; + + case _State.bodyBeforeCR: + assertCurrentChar($cr, "CR"); + _state = _State.bodyBeforeLF; + start++; + break; + + case _State.bodyBeforeLF: + assertCurrentChar($lf, "LF"); + _state = _State.boundary; + start++; + break; + + case _State.endBeforeCR: + assertCurrentChar($cr, "CR"); + _state = _State.endBeforeLF; + start++; + break; + + case _State.endBeforeLF: + assertCurrentChar($lf, "LF"); + _state = _State.end; + start++; + break; + + case _State.end: + throw new FormatException("Expected no more data.", bytes, start); + } + } + return buffer.buffer.asUint8List(0, buffer.length); + } + + /// Returns the hex digit (0 through 15) corresponding to the byte at index + /// [index] in [bytes]. + /// + /// If the given byte isn't a hexadecimal ASCII character, throws a + /// [FormatException]. + int _digitForByte(List bytes, int index) { + // If the byte is a numeral, get its value. XOR works because 0 in ASCII is + // `0b110000` and the other numerals come after it in ascending order and + // take up at most four bits. + // + // We check for digits first because it ensures there's only a single branch + // for 10 out of 16 of the expected cases. We don't count the `digit >= 0` + // check because branch prediction will always work on it for valid data. + var byte = bytes[index]; + var digit = $0 ^ byte; + if (digit <= 9) { + if (digit >= 0) return digit; + } else { + // If the byte is an uppercase letter, convert it to lowercase. This works + // because uppercase letters in ASCII are exactly `0b100000 = 0x20` less + // than lowercase letters, so if we ensure that that bit is 1 we ensure that + // the letter is lowercase. + var letter = 0x20 | byte; + if ($a <= letter && letter <= $f) return letter - $a + 10; + } + + throw new FormatException( + "Invalid hexadecimal byte 0x${byte.toRadixString(16).toUpperCase()}.", + bytes, + index); + } +} + +/// An enumeration of states that [_Sink] can exist in when decoded a chunked +/// message. +class _State { + /// The parser has fully parsed one chunk and is expecting the header for the + /// next chunk. + /// + /// Transitions to [size]. + static const boundary = const _State._("boundary"); + + /// The parser has parsed at least one digit of the chunk size header, but has + /// not yet parsed the `CR LF` sequence that indicates the end of that header. + /// + /// Transitions to [sizeBeforeLF]. + static const size = const _State._("size"); + + /// The parser has parsed the chunk size header and the CR character after it, + /// but not the LF. + /// + /// Transitions to [body] or [bodyBeforeCR]. + static const sizeBeforeLF = const _State._("size before LF"); + + /// The parser has parsed a chunk header and possibly some of the body, but + /// still needs to consume more bytes. + /// + /// Transitions to [bodyBeforeCR]. + static const body = const _State._("body"); + + // The parser has parsed all the bytes in a chunk body but not the CR LF + // sequence that follows it. + // + // Transitions to [bodyBeforeLF]. + static const bodyBeforeCR = const _State._("body before CR"); + + // The parser has parsed all the bytes in a chunk body and the CR that follows + // it, but not the LF after that. + // + // Transitions to [bounday]. + static const bodyBeforeLF = const _State._("body before LF"); + + /// The parser has parsed the final empty chunk but not the CR LF sequence + /// that follows it. + /// + /// Transitions to [endBeforeLF]. + static const endBeforeCR = const _State._("end before CR"); + + /// The parser has parsed the final empty chunk and the CR that follows it, + /// but not the LF after that. + /// + /// Transitions to [end]. + static const endBeforeLF = const _State._("end before LF"); + + /// The parser has parsed the final empty chunk as well as the CR LF that + /// follows, and expects no more data. + static const end = const _State._("end"); + + final String _name; + + const _State._(this._name); + + String toString() => _name; +} +NN<&-6=EE"' 72QE9-G/ L HD:-.$Q. L9;N6/"D$/ %*P@ "(B71%8"(("($!('!(M8NF2PN"QON$ QOS" AON P6QQ%.Q/@N)%.K$@Q$@M$>N!>L),\file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/characters.dart // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This library contains character-code definitions. +const PLUS = 0x2b; +const MINUS = 0x2d; +const PERIOD = 0x2e; +const SLASH = 0x2f; +const ZERO = 0x30; +const NINE = 0x39; +const COLON = 0x3a; +const UPPER_A = 0x41; +const UPPER_Z = 0x5a; +const LOWER_A = 0x61; +const LOWER_Z = 0x7a; +const BACKSLASH = 0x5c; +NN<6`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/internal_style.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'context.dart'; +import 'style.dart'; + +/// The internal interface for the [Style] type. +/// +/// Users should be able to pass around instances of [Style] like an enum, but +/// the members that [Context] uses should be hidden from them. Those members +/// are defined on this class instead. +abstract class InternalStyle extends Style { + /// The default path separator for this style. + /// + /// On POSIX, this is `/`. On Windows, it's `\`. + String get separator; + + /// Returns whether [path] contains a separator. + bool containsSeparator(String path); + + /// Returns whether [codeUnit] is the character code of a separator. + bool isSeparator(int codeUnit); + + /// Returns whether this path component needs a separator after it. + /// + /// Windows and POSIX styles just need separators when the previous component + /// doesn't already end in a separator, but the URL always needs to place a + /// separator between the root and the first component, even if the root + /// already ends in a separator character. For example, to join "file://" and + /// "usr", an additional "/" is needed (making "file:///usr"). + bool needsSeparator(String path); + + /// Returns the number of characters of the root part. + /// + /// Returns 0 if the path is relative and 1 if the path is root-relative. + /// + /// If [withDrive] is `true`, this should include the drive letter for `file:` + /// URLs. Non-URL styles may ignore the parameter. + int rootLength(String path, {bool withDrive: false}); + + /// Gets the root prefix of [path] if path is absolute. If [path] is relative, + /// returns `null`. + String getRoot(String path) { + var length = rootLength(path); + if (length > 0) return path.substring(0, length); + return isRootRelative(path) ? path[0] : null; + } + + /// Returns whether [path] is root-relative. + /// + /// If [path] is relative or absolute and not root-relative, returns `false`. + bool isRootRelative(String path); + + /// Returns the path represented by [uri] in this style. + String pathFromUri(Uri uri); + + /// Returns the URI that represents the relative path made of [parts]. + Uri relativePathToUri(String path) { + var segments = context.split(path); + + // Ensure that a trailing slash in the path produces a trailing slash in the + // URL. + if (isSeparator(path.codeUnitAt(path.length - 1))) segments.add(''); + return new Uri(pathSegments: segments); + } + + /// Returns the URI that represents [path], which is assumed to be absolute. + Uri absolutePathToUri(String path); + + /// Returns whether [codeUnit1] and [codeUnit2] are considered equivalent for + /// this style. + bool codeUnitsEqual(int codeUnit1, int codeUnit2) => codeUnit1 == codeUnit2; + + /// Returns whether [path1] and [path2] are equivalent. + /// + /// This only needs to handle character-by-character comparison; it can assume + /// the paths are normalized and contain no `..` components. + bool pathsEqual(String path1, String path2) => path1 == path2; + + int canonicalizeCodeUnit(int codeUnit) => codeUnit; + + String canonicalizePart(String part) => part; +} +VNN<1ON'-133'G"FPNKPA$9LQ58Q #62/P$;I'(Q I,O&PO:Q?A60]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/parsed_path.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'internal_style.dart'; +import 'style.dart'; + +class ParsedPath { + /// The [InternalStyle] that was used to parse this path. + InternalStyle style; + + /// The absolute root portion of the path, or `null` if the path is relative. + /// On POSIX systems, this will be `null` or "/". On Windows, it can be + /// `null`, "//" for a UNC path, or something like "C:\" for paths with drive + /// letters. + String root; + + /// Whether this path is root-relative. + /// + /// See [Context.isRootRelative]. + bool isRootRelative; + + /// The path-separated parts of the path. All but the last will be + /// directories. + List parts; + + /// The path separators preceding each part. + /// + /// The first one will be an empty string unless the root requires a separator + /// between it and the path. The last one will be an empty string unless the + /// path ends with a trailing separator. + List separators; + + /// The file extension of the last non-empty part, or "" if it doesn't have + /// one. + String get extension => _splitExtension()[1]; + + /// `true` if this is an absolute path. + bool get isAbsolute => root != null; + + factory ParsedPath.parse(String path, InternalStyle style) { + // Remove the root prefix, if any. + var root = style.getRoot(path); + var isRootRelative = style.isRootRelative(path); + if (root != null) path = path.substring(root.length); + + // Split the parts on path separators. + var parts = []; + var separators = []; + + var start = 0; + + if (path.isNotEmpty && style.isSeparator(path.codeUnitAt(0))) { + separators.add(path[0]); + start = 1; + } else { + separators.add(''); + } + + for (var i = start; i < path.length; i++) { + if (style.isSeparator(path.codeUnitAt(i))) { + parts.add(path.substring(start, i)); + separators.add(path[i]); + start = i + 1; + } + } + + // Add the final part, if any. + if (start < path.length) { + parts.add(path.substring(start)); + separators.add(''); + } + + return new ParsedPath._(style, root, isRootRelative, parts, separators); + } + + ParsedPath._( + this.style, this.root, this.isRootRelative, this.parts, this.separators); + + String get basename { + var copy = this.clone(); + copy.removeTrailingSeparators(); + if (copy.parts.isEmpty) return root == null ? '' : root; + return copy.parts.last; + } + + String get basenameWithoutExtension => _splitExtension()[0]; + + bool get hasTrailingSeparator => + !parts.isEmpty && (parts.last == '' || separators.last != ''); + + void removeTrailingSeparators() { + while (!parts.isEmpty && parts.last == '') { + parts.removeLast(); + separators.removeLast(); + } + if (separators.length > 0) separators[separators.length - 1] = ''; + } + + void normalize({bool canonicalize: false}) { + // Handle '.', '..', and empty parts. + var leadingDoubles = 0; + var newParts = []; + for (var part in parts) { + if (part == '.' || part == '') { + // Do nothing. Ignore it. + } else if (part == '..') { + // Pop the last part off. + if (newParts.length > 0) { + newParts.removeLast(); + } else { + // Backed out past the beginning, so preserve the "..". + leadingDoubles++; + } + } else { + newParts.add(canonicalize ? style.canonicalizePart(part) : part); + } + } + + // A relative path can back out from the start directory. + if (!isAbsolute) { + newParts.insertAll(0, new List.filled(leadingDoubles, '..')); + } + + // If we collapsed down to nothing, do ".". + if (newParts.length == 0 && !isAbsolute) { + newParts.add('.'); + } + + // Canonicalize separators. + var newSeparators = new List.generate( + newParts.length, (_) => style.separator, + growable: true); + newSeparators.insert( + 0, + isAbsolute && newParts.length > 0 && style.needsSeparator(root) + ? style.separator + : ''); + + parts = newParts; + separators = newSeparators; + + // Normalize the Windows root if needed. + if (root != null && style == Style.windows) { + if (canonicalize) root = root.toLowerCase(); + root = root.replaceAll('/', '\\'); + } + removeTrailingSeparators(); + } + + String toString() { + var builder = new StringBuffer(); + if (root != null) builder.write(root); + for (var i = 0; i < parts.length; i++) { + builder.write(separators[i]); + builder.write(parts[i]); + } + builder.write(separators.last); + + return builder.toString(); + } + + /// Splits the last non-empty part of the path into a `[basename, extension`] + /// pair. + /// + /// Returns a two-element list. The first is the name of the file without any + /// extension. The second is the extension or "" if it has none. + List _splitExtension() { + var file = parts.lastWhere((p) => p != '', orElse: () => null); + + if (file == null) return ['', '']; + if (file == '..') return ['..', '']; + + var lastDot = file.lastIndexOf('.'); + + // If there is no dot, or it's the first character, like '.bashrc', it + // doesn't count. + if (lastDot <= 0) return [file, '']; + + return [file.substring(0, lastDot), file.substring(lastDot)]; + } + + ParsedPath clone() => new ParsedPath._(style, root, isRootRelative, + new List.from(parts), new List.from(separators)); +} +NN<<PJP*$E/QO+N 0*'?'$5:+!D 03-!#(MP%=?#E$1G/*'"!"#!B +J>D0/ 31 H -23) &+-$$P PC#D'))K)BF8]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/style/posix.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../characters.dart' as chars; +import '../parsed_path.dart'; +import '../internal_style.dart'; + +/// The style for POSIX paths. +class PosixStyle extends InternalStyle { + PosixStyle(); + + final name = 'posix'; + final separator = '/'; + final separators = const ['/']; + + // Deprecated properties. + + final separatorPattern = new RegExp(r'/'); + final needsSeparatorPattern = new RegExp(r'[^/]$'); + final rootPattern = new RegExp(r'^/'); + final relativeRootPattern = null; + + bool containsSeparator(String path) => path.contains('/'); + + bool isSeparator(int codeUnit) => codeUnit == chars.SLASH; + + bool needsSeparator(String path) => + path.isNotEmpty && !isSeparator(path.codeUnitAt(path.length - 1)); + + int rootLength(String path, {bool withDrive: false}) { + if (path.isNotEmpty && isSeparator(path.codeUnitAt(0))) return 1; + return 0; + } + + bool isRootRelative(String path) => false; + + String getRelativeRoot(String path) => null; + + String pathFromUri(Uri uri) { + if (uri.scheme == '' || uri.scheme == 'file') { + return Uri.decodeComponent(uri.path); + } + throw new ArgumentError("Uri $uri must have scheme 'file:'."); + } + + Uri absolutePathToUri(String path) { + var parsed = new ParsedPath.parse(path, this); + if (parsed.parts.isEmpty) { + // If the path is a bare root (e.g. "/"), [components] will + // currently be empty. We add two empty components so the URL constructor + // produces "file:///", with a trailing slash. + parsed.parts.addAll(["", ""]); + } else if (parsed.hasTrailingSeparator) { + // If the path has a trailing slash, add a single empty component so the + // URI has a trailing slash as well. + parsed.parts.add(""); + } + + return new Uri(scheme: 'file', pathSegments: parsed.parts); + } +} +@NN<&!)"-6)$==&I9F-/ 4,C'3 BP5%.O+@[file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/style/url.dartN// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../characters.dart' as chars; +import '../internal_style.dart'; +import '../utils.dart'; + +/// The style for URL paths. +class UrlStyle extends InternalStyle { + UrlStyle(); + + final name = 'url'; + final separator = '/'; + final separators = const ['/']; + + // Deprecated properties. + + final separatorPattern = new RegExp(r'/'); + final needsSeparatorPattern = + new RegExp(r"(^[a-zA-Z][-+.a-zA-Z\d]*://|[^/])$"); + final rootPattern = new RegExp(r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*"); + final relativeRootPattern = new RegExp(r"^/"); + + bool containsSeparator(String path) => path.contains('/'); + + bool isSeparator(int codeUnit) => codeUnit == chars.SLASH; + + bool needsSeparator(String path) { + if (path.isEmpty) return false; + + // A URL that doesn't end in "/" always needs a separator. + if (!isSeparator(path.codeUnitAt(path.length - 1))) return true; + + // A URI that's just "scheme://" needs an extra separator, despite ending + // with "/". + return path.endsWith("://") && rootLength(path) == path.length; + } + + int rootLength(String path, {bool withDrive: false}) { + if (path.isEmpty) return 0; + if (isSeparator(path.codeUnitAt(0))) return 1; + + for (var i = 0; i < path.length; i++) { + var codeUnit = path.codeUnitAt(i); + if (isSeparator(codeUnit)) return 0; + if (codeUnit == chars.COLON) { + if (i == 0) return 0; + + // The root part is up until the next '/', or the full path. Skip ':' + // (and '//' if it exists) and search for '/' after that. + if (path.startsWith('//', i + 1)) i += 3; + var index = path.indexOf('/', i); + if (index <= 0) return path.length; + + // file: URLs sometimes consider Windows drive letters part of the root. + // See https://url.spec.whatwg.org/#file-slash-state. + if (!withDrive || path.length < index + 3) return index; + if (!path.startsWith('file://')) return index; + if (!isDriveLetter(path, index + 1)) return index; + return path.length == index + 3 ? index + 3 : index + 4; + } + } + + return 0; + } + + bool isRootRelative(String path) => + path.isNotEmpty && isSeparator(path.codeUnitAt(0)); + + String getRelativeRoot(String path) => isRootRelative(path) ? '/' : null; + + String pathFromUri(Uri uri) => uri.toString(); + + Uri relativePathToUri(String path) => Uri.parse(path); + Uri absolutePathToUri(String path) => Uri.parse(path); +} +ONN<&!'"- 9E1==%$?END9 3,)+%NB2*,Q>A7;A&:L199_file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/style/windows.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../characters.dart' as chars; +import '../internal_style.dart'; +import '../parsed_path.dart'; +import '../utils.dart'; + +// `0b100000` can be bitwise-ORed with uppercase ASCII letters to get their +// lowercase equivalents. +const _asciiCaseBit = 0x20; + +/// The style for Windows paths. +class WindowsStyle extends InternalStyle { + WindowsStyle(); + + final name = 'windows'; + final separator = '\\'; + final separators = const ['/', '\\']; + + // Deprecated properties. + + final separatorPattern = new RegExp(r'[/\\]'); + final needsSeparatorPattern = new RegExp(r'[^/\\]$'); + final rootPattern = new RegExp(r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'); + final relativeRootPattern = new RegExp(r"^[/\\](?![/\\])"); + + bool containsSeparator(String path) => path.contains('/'); + + bool isSeparator(int codeUnit) => + codeUnit == chars.SLASH || codeUnit == chars.BACKSLASH; + + bool needsSeparator(String path) { + if (path.isEmpty) return false; + return !isSeparator(path.codeUnitAt(path.length - 1)); + } + + int rootLength(String path, {bool withDrive: false}) { + if (path.isEmpty) return 0; + if (path.codeUnitAt(0) == chars.SLASH) return 1; + if (path.codeUnitAt(0) == chars.BACKSLASH) { + if (path.length < 2 || path.codeUnitAt(1) != chars.BACKSLASH) return 1; + // The path is a network share. Search for up to two '\'s, as they are + // the server and share - and part of the root part. + var index = path.indexOf('\\', 2); + if (index > 0) { + index = path.indexOf('\\', index + 1); + if (index > 0) return index; + } + return path.length; + } + // If the path is of the form 'C:/' or 'C:\', with C being any letter, it's + // a root part. + if (path.length < 3) return 0; + // Check for the letter. + if (!isAlphabetic(path.codeUnitAt(0))) return 0; + // Check for the ':'. + if (path.codeUnitAt(1) != chars.COLON) return 0; + // Check for either '/' or '\'. + if (!isSeparator(path.codeUnitAt(2))) return 0; + return 3; + } + + bool isRootRelative(String path) => rootLength(path) == 1; + + String getRelativeRoot(String path) { + var length = rootLength(path); + if (length == 1) return path[0]; + return null; + } + + String pathFromUri(Uri uri) { + if (uri.scheme != '' && uri.scheme != 'file') { + throw new ArgumentError("Uri $uri must have scheme 'file:'."); + } + + var path = uri.path; + if (uri.host == '') { + // Drive-letter paths look like "file:///C:/path/to/file". The + // replaceFirst removes the extra initial slash. Otherwise, leave the + // slash to match IE's interpretation of "/foo" as a root-relative path. + if (path.length >= 3 && path.startsWith('/') && isDriveLetter(path, 1)) { + path = path.replaceFirst("/", ""); + } + } else { + // Network paths look like "file://hostname/path/to/file". + path = '\\\\${uri.host}$path'; + } + return Uri.decodeComponent(path.replaceAll("/", "\\")); + } + + Uri absolutePathToUri(String path) { + var parsed = new ParsedPath.parse(path, this); + if (parsed.root.startsWith(r'\\')) { + // Network paths become "file://server/share/path/to/file". + + // The root is of the form "\\server\share". We want "server" to be the + // URI host, and "share" to be the first element of the path. + var rootParts = parsed.root.split('\\').where((part) => part != ''); + parsed.parts.insert(0, rootParts.last); + + if (parsed.hasTrailingSeparator) { + // If the path has a trailing slash, add a single empty component so the + // URI has a trailing slash as well. + parsed.parts.add(""); + } + + return new Uri( + scheme: 'file', host: rootParts.first, pathSegments: parsed.parts); + } else { + // Drive-letter paths become "file:///C:/path/to/file". + + // If the path is a bare root (e.g. "C:\"), [parsed.parts] will currently + // be empty. We add an empty component so the URL constructor produces + // "file:///C:/", with a trailing slash. We also add an empty component if + // the URL otherwise has a trailing slash. + if (parsed.parts.length == 0 || parsed.hasTrailingSeparator) { + parsed.parts.add(""); + } + + // Get rid of the trailing "\" in "C:\" because the URI constructor will + // add a separator on its own. + parsed.parts + .insert(0, parsed.root.replaceAll("/", "").replaceAll("\\", "")); + + return new Uri(scheme: 'file', pathSegments: parsed.parts); + } + } + + bool codeUnitsEqual(int codeUnit1, int codeUnit2) { + if (codeUnit1 == codeUnit2) return true; + + /// Forward slashes and backslashes are equivalent on Windows. + if (codeUnit1 == chars.SLASH) return codeUnit2 == chars.BACKSLASH; + if (codeUnit1 == chars.BACKSLASH) return codeUnit2 == chars.SLASH; + + // If this check fails, the code units are definitely different. If it + // succeeds *and* either codeUnit is an ASCII letter, they're equivalent. + if (codeUnit1 ^ codeUnit2 != _asciiCaseBit) return false; + + // Now we just need to verify that one of the code units is an ASCII letter. + var upperCase1 = codeUnit1 | _asciiCaseBit; + return upperCase1 >= chars.LOWER_A && upperCase1 <= chars.LOWER_Z; + } + + bool pathsEqual(String path1, String path2) { + if (identical(path1, path2)) return true; + if (path1.length != path2.length) return false; + for (var i = 0; i < path1.length; i++) { + if (!codeUnitsEqual(path1.codeUnitAt(i), path2.codeUnitAt(i))) { + return false; + } + } + return true; + } + + int canonicalizeCodeUnit(int codeUnit) { + if (codeUnit == chars.SLASH) return chars.BACKSLASH; + if (codeUnit < chars.UPPER_A) return codeUnit; + if (codeUnit > chars.UPPER_Z) return codeUnit; + return codeUnit | _asciiCaseBit; + } + + String canonicalizePart(String part) => part.toLowerCase(); +} +NN<&!L!+(18L>=$>%$;9 51NM;)/%P#55$4=(#% 4EELOP+ A%<'3)BNDK.)Q-N >PMQ1EO%LB6-CGGKN>Q0G0.4-G+933%>qfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/forwarding/forwarding_directory.dart'// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; + +/// A directory that forwards all methods and properties to a delegate. +abstract class ForwardingDirectory + extends ForwardingFileSystemEntity implements Directory { + @override + T wrap(io.Directory delegate) => wrapDirectory(delegate); + + @override + Future create({bool recursive: false}) async => + wrap(await delegate.create(recursive: recursive)); + + @override + void createSync({bool recursive: false}) => + delegate.createSync(recursive: recursive); + + @override + Future createTemp([String prefix]) async => + wrap(await delegate.createTemp(prefix)); + + @override + Directory createTempSync([String prefix]) => + wrap(delegate.createTempSync(prefix)); + + @override + Stream list({ + bool recursive: false, + bool followLinks: true, + }) => + delegate.list(recursive: recursive, followLinks: followLinks).map(_wrap); + + @override + List listSync({ + bool recursive: false, + bool followLinks: true, + }) => + delegate + .listSync(recursive: recursive, followLinks: followLinks) + .map(_wrap) + .toList(); + + FileSystemEntity _wrap(io.FileSystemEntity entity) { + if (entity is io.File) { + return wrapFile(entity); + } else if (entity is io.Directory) { + return wrapDirectory(entity); + } else if (entity is io.Link) { + return wrapLink(entity); + } + throw new FileSystemException('Unsupported type: $entity', entity.path); + } +} +=NN<)!H8O < =9 .1 9/ /- "P $D7)$$Mlfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/forwarding/forwarding_file.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; + +/// A file that forwards all methods and properties to a delegate. +abstract class ForwardingFile extends ForwardingFileSystemEntity + implements File { + @override + ForwardingFile wrap(io.File delegate) => wrapFile(delegate); + + @override + Future create({bool recursive: false}) async => + wrap(await delegate.create(recursive: recursive)); + + @override + void createSync({bool recursive: false}) => + delegate.createSync(recursive: recursive); + + @override + Future copy(String newPath) async => wrap(await delegate.copy(newPath)); + + @override + File copySync(String newPath) => wrap(delegate.copySync(newPath)); + + @override + Future length() => delegate.length(); + + @override + int lengthSync() => delegate.lengthSync(); + + @override + Future lastAccessed() => delegate.lastAccessed(); + + @override + DateTime lastAccessedSync() => delegate.lastAccessedSync(); + + @override + Future setLastAccessed(DateTime time) => + delegate.setLastAccessed(time); + + @override + void setLastAccessedSync(DateTime time) => delegate.setLastAccessedSync(time); + + @override + Future lastModified() => delegate.lastModified(); + + @override + DateTime lastModifiedSync() => delegate.lastModifiedSync(); + + @override + Future setLastModified(DateTime time) => + delegate.setLastModified(time); + + @override + void setLastModifiedSync(DateTime time) => delegate.setLastModifiedSync(time); + + @override + Future open({ + FileMode mode: FileMode.read, + }) async => + delegate.open(mode: mode); + + @override + RandomAccessFile openSync({FileMode mode: FileMode.read}) => + delegate.openSync(mode: mode); + + @override + Stream> openRead([int start, int end]) => + delegate.openRead(start, end); + + @override + IOSink openWrite({ + FileMode mode: FileMode.write, + Encoding encoding: utf8, + }) => + delegate.openWrite(mode: mode, encoding: encoding); + + @override + Future> readAsBytes() => delegate.readAsBytes(); + + @override + List readAsBytesSync() => delegate.readAsBytesSync(); + + @override + Future readAsString({Encoding encoding: utf8}) => + delegate.readAsString(encoding: encoding); + + @override + String readAsStringSync({Encoding encoding: utf8}) => + delegate.readAsStringSync(encoding: encoding); + + @override + Future> readAsLines({Encoding encoding: utf8}) => + delegate.readAsLines(encoding: encoding); + + @override + List readAsLinesSync({Encoding encoding: utf8}) => + delegate.readAsLinesSync(encoding: encoding); + + @override + Future writeAsBytes( + List bytes, { + FileMode mode: FileMode.write, + bool flush: false, + }) async => + wrap(await delegate.writeAsBytes( + bytes, + mode: mode, + flush: flush, + )); + + @override + void writeAsBytesSync( + List bytes, { + FileMode mode: FileMode.write, + bool flush: false, + }) => + delegate.writeAsBytesSync(bytes, mode: mode, flush: flush); + + @override + Future writeAsString( + String contents, { + FileMode mode: FileMode.write, + Encoding encoding: utf8, + bool flush: false, + }) async => + wrap(await delegate.writeAsString( + contents, + mode: mode, + encoding: encoding, + flush: flush, + )); + + @override + void writeAsStringSync( + String contents, { + FileMode mode: FileMode.write, + Encoding encoding: utf8, + bool flush: false, + }) => + delegate.writeAsStringSync( + contents, + mode: mode, + encoding: encoding, + flush: flush, + ); +} +NN<)!CP ? 89 .1 Q E - - > > 4& Q > > 4& Q ""! ?% 6% #: = = <1 85 A0 =4 #( + #B #) + #" sfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/forwarding/forwarding_file_system.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; +import 'package:meta/meta.dart'; +import 'package:path/path.dart' as p; + +/// A file system that forwards all methods and properties to a delegate. +abstract class ForwardingFileSystem extends FileSystem { + /// The file system to which this file system will forward all activity. + @protected + final FileSystem delegate; + + /// Creates a new [ForwardingFileSystem] that forwards all methods and + /// properties to the specified [delegate]. + ForwardingFileSystem(this.delegate); + + @override + Directory directory(dynamic path) => delegate.directory(path); + + @override + File file(dynamic path) => delegate.file(path); + + @override + Link link(dynamic path) => delegate.link(path); + + @override + p.Context get path => delegate.path; + + @override + Directory get systemTempDirectory => delegate.systemTempDirectory; + + @override + Directory get currentDirectory => delegate.currentDirectory; + + @override + set currentDirectory(dynamic path) => delegate.currentDirectory = path; + + @override + Future stat(String path) => delegate.stat(path); + + @override + io.FileStat statSync(String path) => delegate.statSync(path); + + @override + Future identical(String path1, String path2) => + delegate.identical(path1, path2); + + @override + bool identicalSync(String path1, String path2) => + delegate.identicalSync(path1, path2); + + @override + bool get isWatchSupported => delegate.isWatchSupported; + + @override + Future type(String path, {bool followLinks: true}) => + delegate.type(path, followLinks: followLinks); + + @override + io.FileSystemEntityType typeSync(String path, {bool followLinks: true}) => + delegate.typeSync(path, followLinks: followLinks); +} +ENN<)!!&J9K I.' A 2 2 ' E ? J @ @ 8( 4, : Q5 M9zfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/forwarding/forwarding_file_system_entity.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; +import 'package:meta/meta.dart'; + +/// A file system entity that forwards all methods and properties to a delegate. +abstract class ForwardingFileSystemEntity implements FileSystemEntity { + /// The entity to which this entity will forward all methods and properties. + @protected + D get delegate; + + /// Creates a new entity with the same file system and same type as this + /// entity but backed by the specified delegate. + @protected + T wrap(D delegate); + + /// Creates a new directory with the same file system as this entity and + /// backed by the specified delegate. + @protected + Directory wrapDirectory(io.Directory delegate); + + /// Creates a new file with the same file system as this entity and + /// backed by the specified delegate. + @protected + File wrapFile(io.File delegate); + + /// Creates a new link with the same file system as this entity and + /// backed by the specified delegate. + @protected + Link wrapLink(io.Link delegate); + + @override + Uri get uri => delegate.uri; + + @override + Future exists() => delegate.exists(); + + @override + bool existsSync() => delegate.existsSync(); + + @override + Future rename(String newPath) async => + wrap(await delegate.rename(newPath) as D); + + @override + T renameSync(String newPath) => wrap(delegate.renameSync(newPath) as D); + + @override + Future resolveSymbolicLinks() => delegate.resolveSymbolicLinks(); + + @override + String resolveSymbolicLinksSync() => delegate.resolveSymbolicLinksSync(); + + @override + Future stat() => delegate.stat(); + + @override + io.FileStat statSync() => delegate.statSync(); + + @override + Future delete({bool recursive: false}) async => + wrap(await delegate.delete(recursive: recursive) as D); + + @override + void deleteSync({bool recursive: false}) => + delegate.deleteSync(recursive: recursive); + + @override + Stream watch({ + int events: FileSystemEvent.all, + bool recursive: false, + }) => + delegate.watch(events: events, recursive: recursive); + + @override + bool get isAbsolute => delegate.isAbsolute; + + @override + T get absolute => wrap(delegate.absolute as D); + + @override + Directory get parent => wrapDirectory(delegate.parent); + + @override + String get path => delegate.path; + + @override + String get basename => fileSystem.path.basename(path); + + @override + String get dirname => fileSystem.path.dirname(path); +} +dNN<)!!QFAO K3 K( 2F( #F( #  . . ,1 K L L 1 1 5> .1 "%< . 2 : $ 9 7lfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/forwarding/forwarding_link.dartv// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; + +/// A link that forwards all methods and properties to a delegate. +abstract class ForwardingLink extends ForwardingFileSystemEntity + implements Link { + @override + ForwardingLink wrap(io.Link delegate) => wrapLink(delegate); + + @override + Future create(String target, {bool recursive: false}) async => + wrap(await delegate.create(target, recursive: recursive)); + + @override + void createSync(String target, {bool recursive: false}) => + delegate.createSync(target, recursive: recursive); + + @override + Future update(String target) async => + wrap(await delegate.update(target)); + + @override + void updateSync(String target) => delegate.updateSync(target); + + @override + Future target() => delegate.target(); + + @override + String targetSync() => delegate.targetSync(); +} +&NN<)!CP ? GA =9 .+ A 0 0efile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/interface/directory.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'file.dart'; +import 'file_system_entity.dart'; +import 'link.dart'; +import '../io.dart' as io; + +/// A reference to a directory on the file system. +abstract class Directory implements FileSystemEntity, io.Directory { + // Override method definitions to codify the return type covariance. + @override + Future create({bool recursive: false}); + + @override + Future createTemp([String prefix]); + + @override + Directory createTempSync([String prefix]); + + @override + Future rename(String newPath); + + @override + Directory renameSync(String newPath); + + @override + Directory get absolute; + + @override + Stream list( + {bool recursive: false, bool followLinks: true}); + + @override + List listSync( + {bool recursive: false, bool followLinks: true}); + + /// Returns a reference to a [Directory] that exists as a child of this + /// directory and has the specified [basename]. + Directory childDirectory(String basename); + + /// Returns a reference to a [File] that exists as a child of this directory + /// and has the specified [basename]. + File childFile(String basename); + + /// Returns a reference to a [Link] that exists as a child of this directory + /// and has the specified [basename]. + Link childLink(String basename); +} +6NN<"3EG 5 1 - , (  !8 #8J2-O(#O(#gfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/interface/error_codes.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'error_codes_internal.dart' + if (dart.library.io) 'error_codes_dart_io.dart'; + +/// Operating system error codes. +// TODO(tvolkert): Remove (https://github.com/dart-lang/sdk/issues/28860) +class ErrorCodes { + ErrorCodes._(); + + /// Argument list too long + // ignore: non_constant_identifier_names + static int get E2BIG => _platform((_Codes codes) => codes.e2big); + + /// Permission denied + // ignore: non_constant_identifier_names + static int get EACCES => _platform((_Codes codes) => codes.eacces); + + /// Try again + // ignore: non_constant_identifier_names + static int get EAGAIN => _platform((_Codes codes) => codes.eagain); + + /// Bad file number + // ignore: non_constant_identifier_names + static int get EBADF => _platform((_Codes codes) => codes.ebadf); + + /// Device or resource busy + // ignore: non_constant_identifier_names + static int get EBUSY => _platform((_Codes codes) => codes.ebusy); + + /// No child processes + // ignore: non_constant_identifier_names + static int get ECHILD => _platform((_Codes codes) => codes.echild); + + /// Resource deadlock would occur + // ignore: non_constant_identifier_names + static int get EDEADLK => _platform((_Codes codes) => codes.edeadlk); + + /// Math argument out of domain of func + // ignore: non_constant_identifier_names + static int get EDOM => _platform((_Codes codes) => codes.edom); + + /// File exists + // ignore: non_constant_identifier_names + static int get EEXIST => _platform((_Codes codes) => codes.eexist); + + /// Bad address + // ignore: non_constant_identifier_names + static int get EFAULT => _platform((_Codes codes) => codes.efault); + + /// File too large + // ignore: non_constant_identifier_names + static int get EFBIG => _platform((_Codes codes) => codes.efbig); + + /// Illegal byte sequence + // ignore: non_constant_identifier_names + static int get EILSEQ => _platform((_Codes codes) => codes.eilseq); + + /// Interrupted system call + // ignore: non_constant_identifier_names + static int get EINTR => _platform((_Codes codes) => codes.eintr); + + /// Invalid argument + // ignore: non_constant_identifier_names + static int get EINVAL => _platform((_Codes codes) => codes.einval); + + /// I/O error + // ignore: non_constant_identifier_names + static int get EIO => _platform((_Codes codes) => codes.eio); + + /// Is a directory + // ignore: non_constant_identifier_names + static int get EISDIR => _platform((_Codes codes) => codes.eisdir); + + /// Too many levels of symbolic links + // ignore: non_constant_identifier_names + static int get ELOOP => _platform((_Codes codes) => codes.eloop); + + /// Too many open files + // ignore: non_constant_identifier_names + static int get EMFILE => _platform((_Codes codes) => codes.emfile); + + /// Too many links + // ignore: non_constant_identifier_names + static int get EMLINK => _platform((_Codes codes) => codes.emlink); + + /// File name too long + // ignore: non_constant_identifier_names + static int get ENAMETOOLONG => + _platform((_Codes codes) => codes.enametoolong); + + /// File table overflow + // ignore: non_constant_identifier_names + static int get ENFILE => _platform((_Codes codes) => codes.enfile); + + /// No such device + // ignore: non_constant_identifier_names + static int get ENODEV => _platform((_Codes codes) => codes.enodev); + + /// No such file or directory + // ignore: non_constant_identifier_names + static int get ENOENT => _platform((_Codes codes) => codes.enoent); + + /// Exec format error + // ignore: non_constant_identifier_names + static int get ENOEXEC => _platform((_Codes codes) => codes.enoexec); + + /// No record locks available + // ignore: non_constant_identifier_names + static int get ENOLCK => _platform((_Codes codes) => codes.enolck); + + /// Out of memory + // ignore: non_constant_identifier_names + static int get ENOMEM => _platform((_Codes codes) => codes.enomem); + + /// No space left on device + // ignore: non_constant_identifier_names + static int get ENOSPC => _platform((_Codes codes) => codes.enospc); + + /// Function not implemented + // ignore: non_constant_identifier_names + static int get ENOSYS => _platform((_Codes codes) => codes.enosys); + + /// Not a directory + // ignore: non_constant_identifier_names + static int get ENOTDIR => _platform((_Codes codes) => codes.enotdir); + + /// Directory not empty + // ignore: non_constant_identifier_names + static int get ENOTEMPTY => _platform((_Codes codes) => codes.enotempty); + + /// Not a typewriter + // ignore: non_constant_identifier_names + static int get ENOTTY => _platform((_Codes codes) => codes.enotty); + + /// No such device or address + // ignore: non_constant_identifier_names + static int get ENXIO => _platform((_Codes codes) => codes.enxio); + + /// Operation not permitted + // ignore: non_constant_identifier_names + static int get EPERM => _platform((_Codes codes) => codes.eperm); + + /// Broken pipe + // ignore: non_constant_identifier_names + static int get EPIPE => _platform((_Codes codes) => codes.epipe); + + /// Math result not representable + // ignore: non_constant_identifier_names + static int get ERANGE => _platform((_Codes codes) => codes.erange); + + /// Read-only file system + // ignore: non_constant_identifier_names + static int get EROFS => _platform((_Codes codes) => codes.erofs); + + /// Illegal seek + // ignore: non_constant_identifier_names + static int get ESPIPE => _platform((_Codes codes) => codes.espipe); + + /// No such process + // ignore: non_constant_identifier_names + static int get ESRCH => _platform((_Codes codes) => codes.esrch); + + /// Cross-device link + // ignore: non_constant_identifier_names + static int get EXDEV => _platform((_Codes codes) => codes.exdev); + + static int _platform(int getCode(_Codes codes)) { + _Codes codes = _platforms[operatingSystem] ?? _platforms['linux']; + return getCode(codes); + } +} + +const Map _platforms = const { + 'linux': const _LinuxCodes(), + 'macos': const _MacOSCodes(), + 'windows': const _WindowsCodes(), +}; + +abstract class _Codes { + int get e2big; + int get eacces; + int get eagain; + int get ebadf; + int get ebusy; + int get echild; + int get edeadlk; + int get edom; + int get eexist; + int get efault; + int get efbig; + int get eilseq; + int get eintr; + int get einval; + int get eio; + int get eisdir; + int get eloop; + int get emfile; + int get emlink; + int get enametoolong; + int get enfile; + int get enodev; + int get enoent; + int get enoexec; + int get enolck; + int get enomem; + int get enospc; + int get enosys; + int get enotdir; + int get enotempty; + int get enotty; + int get enxio; + int get eperm; + int get epipe; + int get erange; + int get erofs; + int get espipe; + int get esrch; + int get exdev; +} + +class _LinuxCodes implements _Codes { + const _LinuxCodes(); + + @override + final int e2big = 7; + + @override + final int eacces = 13; + + @override + final int eagain = 11; + + @override + final int ebadf = 9; + + @override + final int ebusy = 16; + + @override + final int echild = 10; + + @override + final int edeadlk = 35; + + @override + final int edom = 33; + + @override + final int eexist = 17; + + @override + final int efault = 14; + + @override + final int efbig = 27; + + @override + final int eilseq = 84; + + @override + final int eintr = 4; + + @override + final int einval = 22; + + @override + final int eio = 5; + + @override + final int eisdir = 21; + + @override + final int eloop = 40; + + @override + final int emfile = 24; + + @override + final int emlink = 31; + + @override + final int enametoolong = 36; + + @override + final int enfile = 23; + + @override + final int enodev = 19; + + @override + final int enoent = 2; + + @override + final int enoexec = 8; + + @override + final int enolck = 37; + + @override + final int enomem = 12; + + @override + final int enospc = 28; + + @override + final int enosys = 38; + + @override + final int enotdir = 20; + + @override + final int enotempty = 39; + + @override + final int enotty = 25; + + @override + final int enxio = 6; + + @override + final int eperm = 1; + + @override + final int epipe = 32; + + @override + final int erange = 34; + + @override + final int erofs = 30; + + @override + final int espipe = 29; + + @override + final int esrch = 3; + + @override + final int exdev = 18; +} + +class _MacOSCodes implements _Codes { + const _MacOSCodes(); + + @override + final int e2big = 7; + + @override + final int eacces = 13; + + @override + final int eagain = 35; + + @override + final int ebadf = 9; + + @override + final int ebusy = 16; + + @override + final int echild = 10; + + @override + final int edeadlk = 11; + + @override + final int edom = 33; + + @override + final int eexist = 17; + + @override + final int efault = 14; + + @override + final int efbig = 27; + + @override + final int eilseq = 92; + + @override + final int eintr = 4; + + @override + final int einval = 22; + + @override + final int eio = 5; + + @override + final int eisdir = 21; + + @override + final int eloop = 62; + + @override + final int emfile = 24; + + @override + final int emlink = 31; + + @override + final int enametoolong = 63; + + @override + final int enfile = 23; + + @override + final int enodev = 19; + + @override + final int enoent = 2; + + @override + final int enoexec = 8; + + @override + final int enolck = 77; + + @override + final int enomem = 12; + + @override + final int enospc = 28; + + @override + final int enosys = 78; + + @override + final int enotdir = 20; + + @override + final int enotempty = 66; + + @override + final int enotty = 25; + + @override + final int enxio = 6; + + @override + final int eperm = 1; + + @override + final int epipe = 32; + + @override + final int erange = 34; + + @override + final int erofs = 30; + + @override + final int espipe = 29; + + @override + final int esrch = 3; + + @override + final int exdev = 18; +} + +class _WindowsCodes implements _Codes { + const _WindowsCodes(); + + @override + final int e2big = 7; + + @override + final int eacces = 13; + + @override + final int eagain = 11; + + @override + final int ebadf = 9; + + @override + final int ebusy = 16; + + @override + final int echild = 10; + + @override + final int edeadlk = 36; + + @override + final int edom = 33; + + @override + final int eexist = 17; + + @override + final int efault = 14; + + @override + final int efbig = 27; + + @override + final int eilseq = 42; + + @override + final int eintr = 4; + + @override + final int einval = 22; + + @override + final int eio = 5; + + @override + final int eisdir = 21; + + @override + final int eloop = -1; + + @override + final int emfile = 24; + + @override + final int emlink = 31; + + @override + final int enametoolong = 38; + + @override + final int enfile = 23; + + @override + final int enodev = 19; + + @override + final int enoent = 2; + + @override + final int enoexec = 8; + + @override + final int enolck = 39; + + @override + final int enomem = 12; + + @override + final int enospc = 28; + + @override + final int enosys = 40; + + @override + final int enotdir = 20; + + @override + final int enotempty = 41; + + @override + final int enotty = 25; + + @override + final int enxio = 6; + + @override + final int eperm = 1; + + @override + final int epipe = 32; + + @override + final int erange = 34; + + @override + final int erofs = 30; + + @override + final int espipe = 29; + + @override + final int esrch = 3; + + @override + final int exdev = 18; +} +KNN<#5"J+D+F+F+D+D+F$+H*+B+F+F+D+F+D+F+@+F(+D+F+F+!7+F+F +F+H +F+F+F+F+H+L+F +D+D+D$+F+D+F+D+D4G? $&                                       &                                       (                                       `file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/interface/file.dart4// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'file_system_entity.dart'; +import '../io.dart' as io; + +/// A reference to a file on the file system. +abstract class File implements FileSystemEntity, io.File { + // Override method definitions to codify the return type covariance. + @override + Future create({bool recursive: false}); + + @override + Future rename(String newPath); + + @override + File renameSync(String newPath); + + @override + Future copy(String newPath); + + @override + File copySync(String newPath); + + @override + File get absolute; + + @override + Future writeAsBytes(List bytes, + {io.FileMode mode: io.FileMode.write, bool flush: false}); + + @override + Future writeAsString(String contents, + {io.FileMode mode: io.FileMode.write, + Encoding encoding: utf8, + bool flush: false}); +} ++NN<".;G 0 ' # % !  -A .,gfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/interface/file_system.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:meta/meta.dart'; +import 'package:path/path.dart' as p; + +import 'directory.dart'; +import 'file.dart'; +import 'file_system_entity.dart'; +import 'link.dart'; +import '../io.dart' as io; + +/// A generic representation of a file system. +/// +/// Note that this class uses `dart:io` only inasmuch as it deals in the types +/// exposed by the `dart:io` library. Subclasses should document their level of +/// dependence on the library (and the associated implications of using that +/// implementation in the browser). +abstract class FileSystem { + /// Creates a new `FileSystem`. + const FileSystem(); + + /// Returns a reference to a [Directory] at [path]. + /// + /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`]. + Directory directory(dynamic path); + + /// Returns a reference to a [File] at [path]. + /// + /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`]. + File file(dynamic path); + + /// Returns a reference to a [Link] at [path]. + /// + /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`]. + Link link(dynamic path); + + /// An object for manipulating paths in this file system. + p.Context get path; + + /// Gets the system temp directory. + /// + /// It is left to file system implementations to decide how to define the + /// "system temp directory". + Directory get systemTempDirectory; + + /// Creates a directory object pointing to the current working directory. + Directory get currentDirectory; + + /// Sets the current working directory to the specified [path]. + /// + /// The new value set can be either a [Directory] or a [String]. + /// + /// Relative paths will be resolved by the underlying file system + /// implementation (meaning it is up to the underlying implementation to + /// decide whether to support relative paths). + set currentDirectory(dynamic path); + + /// Asynchronously calls the operating system's stat() function on [path]. + /// Returns a Future which completes with a [FileStat] object containing + /// the data returned by stat(). + /// If the call fails, completes the future with a [FileStat] object with + /// .type set to FileSystemEntityType.NOT_FOUND and the other fields invalid. + Future stat(String path); + + /// Calls the operating system's stat() function on [path]. + /// Returns a [FileStat] object containing the data returned by stat(). + /// If the call fails, returns a [FileStat] object with .type set to + /// FileSystemEntityType.NOT_FOUND and the other fields invalid. + io.FileStat statSync(String path); + + /// Checks whether two paths refer to the same object in the + /// file system. Returns a [Future] that completes with the result. + /// + /// Comparing a link to its target returns false, as does comparing two links + /// that point to the same target. To check the target of a link, use + /// Link.target explicitly to fetch it. Directory links appearing + /// inside a path are followed, though, to find the file system object. + /// + /// Completes the returned Future with an error if one of the paths points + /// to an object that does not exist. + Future identical(String path1, String path2); + + /// Synchronously checks whether two paths refer to the same object in the + /// file system. + /// + /// Comparing a link to its target returns false, as does comparing two links + /// that point to the same target. To check the target of a link, use + /// Link.target explicitly to fetch it. Directory links appearing + /// inside a path are followed, though, to find the file system object. + /// + /// Throws an error if one of the paths points to an object that does not + /// exist. + bool identicalSync(String path1, String path2); + + /// Tests if [FileSystemEntity.watch] is supported on the current system. + bool get isWatchSupported; + + /// Finds the type of file system object that a [path] points to. Returns + /// a Future that completes with the result. + /// + /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is + /// `false`, and [path] points to a link + /// + /// If the [path] does not point to a file system object or an error occurs + /// then [io.FileSystemEntityType.NOT_FOUND] is returned. + Future type(String path, {bool followLinks: true}); + + /// Syncronously finds the type of file system object that a [path] points + /// to. Returns a [FileSystemEntityType]. + /// + /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is + /// `false`, and [path] points to a link + /// + /// If the [path] does not point to a file system object or an error occurs + /// then [io.FileSystemEntityType.NOT_FOUND] is returned. + io.FileSystemEntityType typeSync(String path, {bool followLinks: true}); + + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.FILE]. + Future isFile(String path) async => + await type(path) == io.FileSystemEntityType.file; + + /// Synchronously checks if [`type(path)`](type) returns + /// [io.FileSystemEntityType.FILE]. + bool isFileSync(String path) => + typeSync(path) == io.FileSystemEntityType.file; + + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.DIRECTORY]. + Future isDirectory(String path) async => + await type(path) == io.FileSystemEntityType.directory; + + /// Synchronously checks if [`type(path)`](type) returns + /// [io.FileSystemEntityType.DIRECTORY]. + bool isDirectorySync(String path) => + typeSync(path) == io.FileSystemEntityType.directory; + + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.LINK]. + Future isLink(String path) async => + await type(path) == io.FileSystemEntityType.link; + + /// Synchronously checks if [`type(path)`](type) returns + /// [io.FileSystemEntityType.LINK]. + bool isLinkSync(String path) => + typeSync(path) == io.FileSystemEntityType.link; + + /// Gets the string path represented by the specified generic [path]. + /// + /// [path] may be a [io.FileSystemEntity], a [String], or a [Uri]. + @protected + String getPath(dynamic path) { + if (path is io.FileSystemEntity) { + return path.path; + } else if (path is String) { + return path; + } else if (path is Uri) { + return this.path.fromUri(path); + } else { + throw new ArgumentError('Invalid type for "path": ${path?.runtimeType}'); + } + } +} +NN<!&"/OPM$"6O%1O1O<&L%L"BCDK1&MK#LP)>JGC%?LPIEJM(6MPIEJL 2LLEO+N 'foo.dart' + /// context.basename('path/to'); // -> 'to' + /// + /// Trailing separators are ignored. + /// + /// context.basename('path/to/'); // -> 'to' + String get basename; + + /// Gets the part of this entity's path before the last separator. + /// + /// context.dirname('path/to/foo.dart'); // -> 'path/to' + /// context.dirname('path/to'); // -> 'path' + /// context.dirname('foo.dart'); // -> '.' + /// + /// Trailing separators are ignored. + /// + /// context.dirname('path/to/'); // -> 'path' + String get dirname; + + // Override method definitions to codify the return type covariance. + @override + Future delete({bool recursive: false}); + + @override + Directory get parent; +} +-NN<HA;DA;'3E?<9'4G < `file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/interface/link.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'file_system_entity.dart'; +import '../io.dart' as io; + +/// A reference to a symbolic link on the file system. +abstract class Link implements FileSystemEntity, io.Link { + // Override method definitions to codify the return type covariance. + @override + Future create(String target, {bool recursive: false}); + + @override + Future update(String target); + + @override + Future rename(String newPath); + + @override + Link renameSync(String newPath); + + @override + Link get absolute; +} +NN<"7;G ? & ' # Tfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/io.dartg// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// For internal use only! +/// +/// This exposes the subset of the `dart:io` interfaces that are required by +/// the `file` package. The `file` package re-exports these interfaces (or in +/// some cases, implementations of these interfaces by the same name), so this +/// file need not be exposes publicly and exists for internal use only. +export 'dart:io' + show + Directory, + File, + FileLock, + FileMode, + FileStat, + FileSystemEntity, + FileSystemEntityType, + FileSystemEvent, + FileSystemException, + IOException, + IOSink, + Link, + OSError, + RandomAccessFile; +NN<MNOH jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/mime-0.9.6+2/lib/src/bound_multipart_stream.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +library mime.bound_multipart_stream; + +import 'dart:async'; +import 'dart:convert'; + +import 'char_code.dart'; +import 'mime_shared.dart'; + +// Bytes for '()<>@,;:\\"/[]?={} \t'. +const _SEPARATORS = const [ + 40, + 41, + 60, + 62, + 64, + 44, + 59, + 58, + 92, + 34, + 47, + 91, + 93, + 63, + 61, + 123, + 125, + 32, + 9 +]; + +bool _isTokenChar(int byte) { + return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1; +} + +int _toLowerCase(int byte) { + const delta = CharCode.LOWER_A - CharCode.UPPER_A; + return (CharCode.UPPER_A <= byte && byte <= CharCode.UPPER_Z) + ? byte + delta + : byte; +} + +void _expectByteValue(int val1, int val2) { + if (val1 != val2) { + throw new MimeMultipartException("Failed to parse multipart mime 1"); + } +} + +void _expectWhitespace(int byte) { + if (byte != CharCode.SP && byte != CharCode.HT) { + throw new MimeMultipartException("Failed to parse multipart mime 2"); + } +} + +class _MimeMultipart extends MimeMultipart { + final Map headers; + final Stream> _stream; + + _MimeMultipart(this.headers, this._stream); + + StreamSubscription> listen(void onData(List data), + {void onDone(), Function onError, bool cancelOnError}) { + return _stream.listen(onData, + onDone: onDone, onError: onError, cancelOnError: cancelOnError); + } +} + +class BoundMultipartStream { + static const int _START = 0; + static const int _BOUNDARY_ENDING = 1; + static const int _BOUNDARY_END = 2; + static const int _HEADER_START = 3; + static const int _HEADER_FIELD = 4; + static const int _HEADER_VALUE_START = 5; + static const int _HEADER_VALUE = 6; + static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; + static const int _HEADER_VALUE_FOLD_OR_END = 8; + static const int _HEADER_ENDING = 9; + static const int _CONTENT = 10; + static const int _LAST_BOUNDARY_DASH2 = 11; + static const int _LAST_BOUNDARY_ENDING = 12; + static const int _LAST_BOUNDARY_END = 13; + static const int _DONE = 14; + static const int _FAIL = 15; + + final List _boundary; + final List _headerField = []; + final List _headerValue = []; + + // The following states belong to `_controller`, state changes will not be + // immediately acted upon but rather only after the current + // `_multipartController` is done. + static const int _CONTROLLER_STATE_IDLE = 0; + static const int _CONTROLLER_STATE_ACTIVE = 1; + static const int _CONTROLLER_STATE_PAUSED = 2; + static const int _CONTROLLER_STATE_CANCELED = 3; + + int _controllerState = _CONTROLLER_STATE_IDLE; + + StreamController _controller; + + Stream get stream => _controller.stream; + + StreamSubscription _subscription; + + StreamController> _multipartController; + Map _headers; + + int _state = _START; + int _boundaryIndex = 2; + + // Current index in the data buffer. If index is negative then it + // is the index into the artificial prefix of the boundary string. + int _index; + List _buffer; + + BoundMultipartStream(this._boundary, Stream> stream) { + _controller = new StreamController( + sync: true, + onPause: _pauseStream, + onResume: _resumeStream, + onCancel: () { + _controllerState = _CONTROLLER_STATE_CANCELED; + _tryPropagateControllerState(); + }, + onListen: () { + _controllerState = _CONTROLLER_STATE_ACTIVE; + _subscription = stream.listen((data) { + assert(_buffer == null); + _subscription.pause(); + _buffer = data; + _index = 0; + _parse(); + }, onDone: () { + if (_state != _DONE) { + _controller + .addError(new MimeMultipartException("Bad multipart ending")); + } + _controller.close(); + }, onError: _controller.addError); + }); + } + + void _resumeStream() { + assert(_controllerState == _CONTROLLER_STATE_PAUSED); + _controllerState = _CONTROLLER_STATE_ACTIVE; + _tryPropagateControllerState(); + } + + void _pauseStream() { + _controllerState = _CONTROLLER_STATE_PAUSED; + _tryPropagateControllerState(); + } + + void _tryPropagateControllerState() { + if (_multipartController == null) { + switch (_controllerState) { + case _CONTROLLER_STATE_ACTIVE: + if (_subscription.isPaused) _subscription.resume(); + break; + case _CONTROLLER_STATE_PAUSED: + if (!_subscription.isPaused) _subscription.pause(); + break; + case _CONTROLLER_STATE_CANCELED: + _subscription.cancel(); + break; + default: + throw new StateError("This code should never be reached."); + } + } + } + + void _parse() { + // Number of boundary bytes to artificially place before the supplied data. + int boundaryPrefix = 0; + // Position where content starts. Will be null if no known content + // start exists. Will be negative of the content starts in the + // boundary prefix. Will be zero or position if the content starts + // in the current buffer. + int contentStartIndex; + + // Function to report content data for the current part. The data + // reported is from the current content start index up til the + // current index. As the data can be artificially prefixed with a + // prefix of the boundary both the content start index and index + // can be negative. + void reportData() { + if (contentStartIndex < 0) { + var contentLength = boundaryPrefix + _index - _boundaryIndex; + if (contentLength <= boundaryPrefix) { + _multipartController.add(_boundary.sublist(0, contentLength)); + } else { + _multipartController.add(_boundary.sublist(0, boundaryPrefix)); + _multipartController + .add(_buffer.sublist(0, contentLength - boundaryPrefix)); + } + } else { + var contentEndIndex = _index - _boundaryIndex; + _multipartController + .add(_buffer.sublist(contentStartIndex, contentEndIndex)); + } + } + + if (_state == _CONTENT && _boundaryIndex == 0) { + contentStartIndex = 0; + } else { + contentStartIndex = null; + } + // The data to parse might be "artificially" prefixed with a + // partial match of the boundary. + boundaryPrefix = _boundaryIndex; + + while ((_index < _buffer.length) && _state != _FAIL && _state != _DONE) { + int byte; + if (_index < 0) { + byte = _boundary[boundaryPrefix + _index]; + } else { + byte = _buffer[_index]; + } + switch (_state) { + case _START: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + _state = _BOUNDARY_ENDING; + _boundaryIndex = 0; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + _boundaryIndex = 0; + } + break; + + case _BOUNDARY_ENDING: + if (byte == CharCode.CR) { + _state = _BOUNDARY_END; + } else if (byte == CharCode.DASH) { + _state = _LAST_BOUNDARY_DASH2; + } else { + _expectWhitespace(byte); + } + break; + + case _BOUNDARY_END: + _expectByteValue(byte, CharCode.LF); + if (_multipartController != null) { + _multipartController.close(); + _multipartController = null; + _tryPropagateControllerState(); + } + _state = _HEADER_START; + break; + + case _HEADER_START: + _headers = new Map(); + if (byte == CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + break; + + case _HEADER_FIELD: + if (byte == CharCode.COLON) { + _state = _HEADER_VALUE_START; + } else { + if (!_isTokenChar(byte)) { + throw new MimeMultipartException("Invalid header field name"); + } + _headerField.add(_toLowerCase(byte)); + } + break; + + case _HEADER_VALUE_START: + if (byte == CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else if (byte != CharCode.SP && byte != CharCode.HT) { + // Start of new header value. + _headerValue.add(byte); + _state = _HEADER_VALUE; + } + break; + + case _HEADER_VALUE: + if (byte == CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else { + _headerValue.add(byte); + } + break; + + case _HEADER_VALUE_FOLDING_OR_ENDING: + _expectByteValue(byte, CharCode.LF); + _state = _HEADER_VALUE_FOLD_OR_END; + break; + + case _HEADER_VALUE_FOLD_OR_END: + if (byte == CharCode.SP || byte == CharCode.HT) { + _state = _HEADER_VALUE_START; + } else { + String headerField = utf8.decode(_headerField); + String headerValue = utf8.decode(_headerValue); + _headers[headerField.toLowerCase()] = headerValue; + _headerField.clear(); + _headerValue.clear(); + if (byte == CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + } + break; + + case _HEADER_ENDING: + _expectByteValue(byte, CharCode.LF); + _multipartController = new StreamController( + sync: true, + onListen: () { + if (_subscription.isPaused) _subscription.resume(); + }, + onPause: _subscription.pause, + onResume: _subscription.resume); + _controller + .add(new _MimeMultipart(_headers, _multipartController.stream)); + _headers = null; + _state = _CONTENT; + contentStartIndex = _index + 1; + break; + + case _CONTENT: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + if (contentStartIndex != null) { + _index++; + reportData(); + _index--; + } + _multipartController.close(); + _multipartController = null; + _tryPropagateControllerState(); + _boundaryIndex = 0; + _state = _BOUNDARY_ENDING; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + if (contentStartIndex == null) contentStartIndex = _index; + _boundaryIndex = 0; + } + break; + + case _LAST_BOUNDARY_DASH2: + _expectByteValue(byte, CharCode.DASH); + _state = _LAST_BOUNDARY_ENDING; + break; + + case _LAST_BOUNDARY_ENDING: + if (byte == CharCode.CR) { + _state = _LAST_BOUNDARY_END; + } else { + _expectWhitespace(byte); + } + break; + + case _LAST_BOUNDARY_END: + _expectByteValue(byte, CharCode.LF); + if (_multipartController != null) { + _multipartController.close(); + _multipartController = null; + _tryPropagateControllerState(); + } + _state = _DONE; + break; + + default: + // Should be unreachable. + assert(false); + break; + } + + // Move to the next byte. + _index++; + } + + // Report any known content. + if (_state == _CONTENT && contentStartIndex != null) { + reportData(); + } + + // Resume if at end. + if (_index == _buffer.length) { + _buffer = null; + _index = null; + _subscription.resume(); + } + } +} +NN<%&E5@,J#4J-%#.D?"I)&&&,&82'"./,%%M>%/1131/:$4 DEC(!9* 71%##Q!- :1$1$(("'>'>)"FPGCGFCFE#F/IJH +7G5 A&%N3 36)"1. %$.+% /.*), "0%%*2$ (*'M2 "%6C*$$ %6$ ./.(<*< defaultExtensionMap = { + '123': 'application/vnd.lotus-1-2-3', + '3dml': 'text/vnd.in3d.3dml', + '3ds': 'image/x-3ds', + '3g2': 'video/3gpp2', + '3gp': 'video/3gpp', + '7z': 'application/x-7z-compressed', + 'aab': 'application/x-authorware-bin', + 'aac': 'audio/x-aac', + 'aam': 'application/x-authorware-map', + 'aas': 'application/x-authorware-seg', + 'abw': 'application/x-abiword', + 'ac': 'application/pkix-attr-cert', + 'acc': 'application/vnd.americandynamics.acc', + 'ace': 'application/x-ace-compressed', + 'acu': 'application/vnd.acucobol', + 'acutc': 'application/vnd.acucorp', + 'adp': 'audio/adpcm', + 'aep': 'application/vnd.audiograph', + 'afm': 'application/x-font-type1', + 'afp': 'application/vnd.ibm.modcap', + 'ahead': 'application/vnd.ahead.space', + 'ai': 'application/postscript', + 'aif': 'audio/x-aiff', + 'aifc': 'audio/x-aiff', + 'aiff': 'audio/x-aiff', + 'air': 'application/vnd.adobe.air-application-installer-package+zip', + 'ait': 'application/vnd.dvb.ait', + 'ami': 'application/vnd.amiga.ami', + 'apk': 'application/vnd.android.package-archive', + 'appcache': 'text/cache-manifest', + 'application': 'application/x-ms-application', + 'apr': 'application/vnd.lotus-approach', + 'arc': 'application/x-freearc', + 'asc': 'application/pgp-signature', + 'asf': 'video/x-ms-asf', + 'asm': 'text/x-asm', + 'aso': 'application/vnd.accpac.simply.aso', + 'asx': 'video/x-ms-asf', + 'atc': 'application/vnd.acucorp', + 'atom': 'application/atom+xml', + 'atomcat': 'application/atomcat+xml', + 'atomsvc': 'application/atomsvc+xml', + 'atx': 'application/vnd.antix.game-component', + 'au': 'audio/basic', + 'avi': 'video/x-msvideo', + 'aw': 'application/applixware', + 'azf': 'application/vnd.airzip.filesecure.azf', + 'azs': 'application/vnd.airzip.filesecure.azs', + 'azw': 'application/vnd.amazon.ebook', + 'bat': 'application/x-msdownload', + 'bcpio': 'application/x-bcpio', + 'bdf': 'application/x-font-bdf', + 'bdm': 'application/vnd.syncml.dm+wbxml', + 'bed': 'application/vnd.realvnc.bed', + 'bh2': 'application/vnd.fujitsu.oasysprs', + 'bin': 'application/octet-stream', + 'blb': 'application/x-blorb', + 'blorb': 'application/x-blorb', + 'bmi': 'application/vnd.bmi', + 'bmp': 'image/bmp', + 'book': 'application/vnd.framemaker', + 'box': 'application/vnd.previewsystems.box', + 'boz': 'application/x-bzip2', + 'bpk': 'application/octet-stream', + 'btif': 'image/prs.btif', + 'bz': 'application/x-bzip', + 'bz2': 'application/x-bzip2', + 'c': 'text/x-c', + 'c11amc': 'application/vnd.cluetrust.cartomobile-config', + 'c11amz': 'application/vnd.cluetrust.cartomobile-config-pkg', + 'c4d': 'application/vnd.clonk.c4group', + 'c4f': 'application/vnd.clonk.c4group', + 'c4g': 'application/vnd.clonk.c4group', + 'c4p': 'application/vnd.clonk.c4group', + 'c4u': 'application/vnd.clonk.c4group', + 'cab': 'application/vnd.ms-cab-compressed', + 'caf': 'audio/x-caf', + 'cap': 'application/vnd.tcpdump.pcap', + 'car': 'application/vnd.curl.car', + 'cat': 'application/vnd.ms-pki.seccat', + 'cb7': 'application/x-cbr', + 'cba': 'application/x-cbr', + 'cbr': 'application/x-cbr', + 'cbt': 'application/x-cbr', + 'cbz': 'application/x-cbr', + 'cc': 'text/x-c', + 'cct': 'application/x-director', + 'ccxml': 'application/ccxml+xml', + 'cdbcmsg': 'application/vnd.contact.cmsg', + 'cdf': 'application/x-netcdf', + 'cdkey': 'application/vnd.mediastation.cdkey', + 'cdmia': 'application/cdmi-capability', + 'cdmic': 'application/cdmi-container', + 'cdmid': 'application/cdmi-domain', + 'cdmio': 'application/cdmi-object', + 'cdmiq': 'application/cdmi-queue', + 'cdx': 'chemical/x-cdx', + 'cdxml': 'application/vnd.chemdraw+xml', + 'cdy': 'application/vnd.cinderella', + 'cer': 'application/pkix-cert', + 'cfs': 'application/x-cfs-compressed', + 'cgm': 'image/cgm', + 'chat': 'application/x-chat', + 'chm': 'application/vnd.ms-htmlhelp', + 'chrt': 'application/vnd.kde.kchart', + 'cif': 'chemical/x-cif', + 'cii': 'application/vnd.anser-web-certificate-issue-initiation', + 'cil': 'application/vnd.ms-artgalry', + 'cla': 'application/vnd.claymore', + 'class': 'application/java-vm', + 'clkk': 'application/vnd.crick.clicker.keyboard', + 'clkp': 'application/vnd.crick.clicker.palette', + 'clkt': 'application/vnd.crick.clicker.template', + 'clkw': 'application/vnd.crick.clicker.wordbank', + 'clkx': 'application/vnd.crick.clicker', + 'clp': 'application/x-msclip', + 'cmc': 'application/vnd.cosmocaller', + 'cmdf': 'chemical/x-cmdf', + 'cml': 'chemical/x-cml', + 'cmp': 'application/vnd.yellowriver-custom-menu', + 'cmx': 'image/x-cmx', + 'cod': 'application/vnd.rim.cod', + 'com': 'application/x-msdownload', + 'conf': 'text/plain', + 'cpio': 'application/x-cpio', + 'cpp': 'text/x-c', + 'cpt': 'application/mac-compactpro', + 'crd': 'application/x-mscardfile', + 'crl': 'application/pkix-crl', + 'crt': 'application/x-x509-ca-cert', + 'cryptonote': 'application/vnd.rig.cryptonote', + 'csh': 'application/x-csh', + 'csml': 'chemical/x-csml', + 'csp': 'application/vnd.commonspace', + 'css': 'text/css', + 'cst': 'application/x-director', + 'csv': 'text/csv', + 'cu': 'application/cu-seeme', + 'curl': 'text/vnd.curl', + 'cww': 'application/prs.cww', + 'cxt': 'application/x-director', + 'cxx': 'text/x-c', + 'dae': 'model/vnd.collada+xml', + 'daf': 'application/vnd.mobius.daf', + 'dart': 'application/dart', + 'dataless': 'application/vnd.fdsn.seed', + 'davmount': 'application/davmount+xml', + 'dbk': 'application/docbook+xml', + 'dcr': 'application/x-director', + 'dcurl': 'text/vnd.curl.dcurl', + 'dd2': 'application/vnd.oma.dd2+xml', + 'ddd': 'application/vnd.fujixerox.ddd', + 'deb': 'application/x-debian-package', + 'def': 'text/plain', + 'deploy': 'application/octet-stream', + 'der': 'application/x-x509-ca-cert', + 'dfac': 'application/vnd.dreamfactory', + 'dgc': 'application/x-dgc-compressed', + 'dic': 'text/x-c', + 'dir': 'application/x-director', + 'dis': 'application/vnd.mobius.dis', + 'dist': 'application/octet-stream', + 'distz': 'application/octet-stream', + 'djv': 'image/vnd.djvu', + 'djvu': 'image/vnd.djvu', + 'dll': 'application/x-msdownload', + 'dmg': 'application/x-apple-diskimage', + 'dmp': 'application/vnd.tcpdump.pcap', + 'dms': 'application/octet-stream', + 'dna': 'application/vnd.dna', + 'doc': 'application/msword', + 'docm': 'application/vnd.ms-word.document.macroenabled.12', + 'docx': + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot': 'application/msword', + 'dotm': 'application/vnd.ms-word.template.macroenabled.12', + 'dotx': + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dp': 'application/vnd.osgi.dp', + 'dpg': 'application/vnd.dpgraph', + 'dra': 'audio/vnd.dra', + 'dsc': 'text/prs.lines.tag', + 'dssc': 'application/dssc+der', + 'dtb': 'application/x-dtbook+xml', + 'dtd': 'application/xml-dtd', + 'dts': 'audio/vnd.dts', + 'dtshd': 'audio/vnd.dts.hd', + 'dump': 'application/octet-stream', + 'dvb': 'video/vnd.dvb.file', + 'dvi': 'application/x-dvi', + 'dwf': 'model/vnd.dwf', + 'dwg': 'image/vnd.dwg', + 'dxf': 'image/vnd.dxf', + 'dxp': 'application/vnd.spotfire.dxp', + 'dxr': 'application/x-director', + 'ecelp4800': 'audio/vnd.nuera.ecelp4800', + 'ecelp7470': 'audio/vnd.nuera.ecelp7470', + 'ecelp9600': 'audio/vnd.nuera.ecelp9600', + 'ecma': 'application/ecmascript', + 'edm': 'application/vnd.novadigm.edm', + 'edx': 'application/vnd.novadigm.edx', + 'efif': 'application/vnd.picsel', + 'ei6': 'application/vnd.pg.osasli', + 'elc': 'application/octet-stream', + 'emf': 'application/x-msmetafile', + 'eml': 'message/rfc822', + 'emma': 'application/emma+xml', + 'emz': 'application/x-msmetafile', + 'eol': 'audio/vnd.digital-winds', + 'eot': 'application/vnd.ms-fontobject', + 'eps': 'application/postscript', + 'epub': 'application/epub+zip', + 'es3': 'application/vnd.eszigno3+xml', + 'esa': 'application/vnd.osgi.subsystem', + 'esf': 'application/vnd.epson.esf', + 'et3': 'application/vnd.eszigno3+xml', + 'etx': 'text/x-setext', + 'eva': 'application/x-eva', + 'evy': 'application/x-envoy', + 'exe': 'application/x-msdownload', + 'exi': 'application/exi', + 'ext': 'application/vnd.novadigm.ext', + 'ez': 'application/andrew-inset', + 'ez2': 'application/vnd.ezpix-album', + 'ez3': 'application/vnd.ezpix-package', + 'f': 'text/x-fortran', + 'f4v': 'video/x-f4v', + 'f77': 'text/x-fortran', + 'f90': 'text/x-fortran', + 'fbs': 'image/vnd.fastbidsheet', + 'fcdt': 'application/vnd.adobe.formscentral.fcdt', + 'fcs': 'application/vnd.isac.fcs', + 'fdf': 'application/vnd.fdf', + 'fe_launch': 'application/vnd.denovo.fcselayout-link', + 'fg5': 'application/vnd.fujitsu.oasysgp', + 'fgd': 'application/x-director', + 'fh': 'image/x-freehand', + 'fh4': 'image/x-freehand', + 'fh5': 'image/x-freehand', + 'fh7': 'image/x-freehand', + 'fhc': 'image/x-freehand', + 'fig': 'application/x-xfig', + 'flac': 'audio/x-flac', + 'fli': 'video/x-fli', + 'flo': 'application/vnd.micrografx.flo', + 'flv': 'video/x-flv', + 'flw': 'application/vnd.kde.kivio', + 'flx': 'text/vnd.fmi.flexstor', + 'fly': 'text/vnd.fly', + 'fm': 'application/vnd.framemaker', + 'fnc': 'application/vnd.frogans.fnc', + 'for': 'text/x-fortran', + 'fpx': 'image/vnd.fpx', + 'frame': 'application/vnd.framemaker', + 'fsc': 'application/vnd.fsc.weblaunch', + 'fst': 'image/vnd.fst', + 'ftc': 'application/vnd.fluxtime.clip', + 'fti': 'application/vnd.anser-web-funds-transfer-initiation', + 'fvt': 'video/vnd.fvt', + 'fxp': 'application/vnd.adobe.fxp', + 'fxpl': 'application/vnd.adobe.fxp', + 'fzs': 'application/vnd.fuzzysheet', + 'g2w': 'application/vnd.geoplan', + 'g3': 'image/g3fax', + 'g3w': 'application/vnd.geospace', + 'gac': 'application/vnd.groove-account', + 'gam': 'application/x-tads', + 'gbr': 'application/rpki-ghostbusters', + 'gca': 'application/x-gca-compressed', + 'gdl': 'model/vnd.gdl', + 'geo': 'application/vnd.dynageo', + 'gex': 'application/vnd.geometry-explorer', + 'ggb': 'application/vnd.geogebra.file', + 'ggt': 'application/vnd.geogebra.tool', + 'ghf': 'application/vnd.groove-help', + 'gif': 'image/gif', + 'gim': 'application/vnd.groove-identity-message', + 'glb': 'model/gltf-binary', + 'gltf': 'model/gltf+json', + 'gml': 'application/gml+xml', + 'gmx': 'application/vnd.gmx', + 'gnumeric': 'application/x-gnumeric', + 'gph': 'application/vnd.flographit', + 'gpx': 'application/gpx+xml', + 'gqf': 'application/vnd.grafeq', + 'gqs': 'application/vnd.grafeq', + 'gram': 'application/srgs', + 'gramps': 'application/x-gramps-xml', + 'gre': 'application/vnd.geometry-explorer', + 'grv': 'application/vnd.groove-injector', + 'grxml': 'application/srgs+xml', + 'gsf': 'application/x-font-ghostscript', + 'gtar': 'application/x-gtar', + 'gtm': 'application/vnd.groove-tool-message', + 'gtw': 'model/vnd.gtw', + 'gv': 'text/vnd.graphviz', + 'gxf': 'application/gxf', + 'gxt': 'application/vnd.geonext', + 'h': 'text/x-c', + 'h261': 'video/h261', + 'h263': 'video/h263', + 'h264': 'video/h264', + 'hal': 'application/vnd.hal+xml', + 'hbci': 'application/vnd.hbci', + 'hdf': 'application/x-hdf', + 'hh': 'text/x-c', + 'hlp': 'application/winhlp', + 'hpgl': 'application/vnd.hp-hpgl', + 'hpid': 'application/vnd.hp-hpid', + 'hps': 'application/vnd.hp-hps', + 'hqx': 'application/mac-binhex40', + 'htke': 'application/vnd.kenameaapp', + 'htm': 'text/html', + 'html': 'text/html', + 'hvd': 'application/vnd.yamaha.hv-dic', + 'hvp': 'application/vnd.yamaha.hv-voice', + 'hvs': 'application/vnd.yamaha.hv-script', + 'i2g': 'application/vnd.intergeo', + 'icc': 'application/vnd.iccprofile', + 'ice': 'x-conference/x-cooltalk', + 'icm': 'application/vnd.iccprofile', + 'ico': 'image/x-icon', + 'ics': 'text/calendar', + 'ief': 'image/ief', + 'ifb': 'text/calendar', + 'ifm': 'application/vnd.shana.informed.formdata', + 'iges': 'model/iges', + 'igl': 'application/vnd.igloader', + 'igm': 'application/vnd.insors.igm', + 'igs': 'model/iges', + 'igx': 'application/vnd.micrografx.igx', + 'iif': 'application/vnd.shana.informed.interchange', + 'imp': 'application/vnd.accpac.simply.imp', + 'ims': 'application/vnd.ms-ims', + 'in': 'text/plain', + 'ink': 'application/inkml+xml', + 'inkml': 'application/inkml+xml', + 'install': 'application/x-install-instructions', + 'iota': 'application/vnd.astraea-software.iota', + 'ipfix': 'application/ipfix', + 'ipk': 'application/vnd.shana.informed.package', + 'irm': 'application/vnd.ibm.rights-management', + 'irp': 'application/vnd.irepository.package+xml', + 'iso': 'application/x-iso9660-image', + 'itp': 'application/vnd.shana.informed.formtemplate', + 'ivp': 'application/vnd.immervision-ivp', + 'ivu': 'application/vnd.immervision-ivu', + 'jad': 'text/vnd.sun.j2me.app-descriptor', + 'jam': 'application/vnd.jam', + 'jar': 'application/java-archive', + 'java': 'text/x-java-source', + 'jisp': 'application/vnd.jisp', + 'jlt': 'application/vnd.hp-jlyt', + 'jnlp': 'application/x-java-jnlp-file', + 'joda': 'application/vnd.joost.joda-archive', + 'jpe': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'jpg': 'image/jpeg', + 'jpgm': 'video/jpm', + 'jpgv': 'video/jpeg', + 'jpm': 'video/jpm', + 'js': 'application/javascript', + 'json': 'application/json', + 'jsonml': 'application/jsonml+json', + 'kar': 'audio/midi', + 'karbon': 'application/vnd.kde.karbon', + 'kfo': 'application/vnd.kde.kformula', + 'kia': 'application/vnd.kidspiration', + 'kml': 'application/vnd.google-earth.kml+xml', + 'kmz': 'application/vnd.google-earth.kmz', + 'kne': 'application/vnd.kinar', + 'knp': 'application/vnd.kinar', + 'kon': 'application/vnd.kde.kontour', + 'kpr': 'application/vnd.kde.kpresenter', + 'kpt': 'application/vnd.kde.kpresenter', + 'kpxx': 'application/vnd.ds-keypoint', + 'ksp': 'application/vnd.kde.kspread', + 'ktr': 'application/vnd.kahootz', + 'ktx': 'image/ktx', + 'ktz': 'application/vnd.kahootz', + 'kwd': 'application/vnd.kde.kword', + 'kwt': 'application/vnd.kde.kword', + 'lasxml': 'application/vnd.las.las+xml', + 'latex': 'application/x-latex', + 'lbd': 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe': 'application/vnd.llamagraphics.life-balance.exchange+xml', + 'les': 'application/vnd.hhe.lesson-player', + 'lha': 'application/x-lzh-compressed', + 'link66': 'application/vnd.route66.link66+xml', + 'list': 'text/plain', + 'list3820': 'application/vnd.ibm.modcap', + 'listafp': 'application/vnd.ibm.modcap', + 'lnk': 'application/x-ms-shortcut', + 'log': 'text/plain', + 'lostxml': 'application/lost+xml', + 'lrf': 'application/octet-stream', + 'lrm': 'application/vnd.ms-lrm', + 'ltf': 'application/vnd.frogans.ltf', + 'lvp': 'audio/vnd.lucent.voice', + 'lwp': 'application/vnd.lotus-wordpro', + 'lzh': 'application/x-lzh-compressed', + 'm13': 'application/x-msmediaview', + 'm14': 'application/x-msmediaview', + 'm1v': 'video/mpeg', + 'm21': 'application/mp21', + 'm2a': 'audio/mpeg', + 'm2v': 'video/mpeg', + 'm3a': 'audio/mpeg', + 'm3u': 'audio/x-mpegurl', + 'm3u8': 'application/vnd.apple.mpegurl', + 'm4u': 'video/vnd.mpegurl', + 'm4v': 'video/x-m4v', + 'ma': 'application/mathematica', + 'mads': 'application/mads+xml', + 'mag': 'application/vnd.ecowin.chart', + 'maker': 'application/vnd.framemaker', + 'man': 'text/troff', + 'mar': 'application/octet-stream', + 'mathml': 'application/mathml+xml', + 'mb': 'application/mathematica', + 'mbk': 'application/vnd.mobius.mbk', + 'mbox': 'application/mbox', + 'mc1': 'application/vnd.medcalcdata', + 'mcd': 'application/vnd.mcd', + 'mcurl': 'text/vnd.curl.mcurl', + 'mdb': 'application/x-msaccess', + 'mdi': 'image/vnd.ms-modi', + 'me': 'text/troff', + 'mesh': 'model/mesh', + 'meta4': 'application/metalink4+xml', + 'metalink': 'application/metalink+xml', + 'mets': 'application/mets+xml', + 'mfm': 'application/vnd.mfmp', + 'mft': 'application/rpki-manifest', + 'mgp': 'application/vnd.osgeo.mapguide.package', + 'mgz': 'application/vnd.proteus.magazine', + 'mid': 'audio/midi', + 'midi': 'audio/midi', + 'mie': 'application/x-mie', + 'mif': 'application/vnd.mif', + 'mime': 'message/rfc822', + 'mj2': 'video/mj2', + 'mjp2': 'video/mj2', + 'mk3d': 'video/x-matroska', + 'mka': 'audio/x-matroska', + 'mks': 'video/x-matroska', + 'mkv': 'video/x-matroska', + 'mlp': 'application/vnd.dolby.mlp', + 'mmd': 'application/vnd.chipnuts.karaoke-mmd', + 'mmf': 'application/vnd.smaf', + 'mmr': 'image/vnd.fujixerox.edmics-mmr', + 'mng': 'video/x-mng', + 'mny': 'application/x-msmoney', + 'mobi': 'application/x-mobipocket-ebook', + 'mods': 'application/mods+xml', + 'mov': 'video/quicktime', + 'movie': 'video/x-sgi-movie', + 'mp2': 'audio/mpeg', + 'mp21': 'application/mp21', + 'mp2a': 'audio/mpeg', + 'mp3': 'audio/mpeg', + 'mp4': 'video/mp4', + 'mp4a': 'audio/mp4', + 'mp4s': 'application/mp4', + 'mp4v': 'video/mp4', + 'mpc': 'application/vnd.mophun.certificate', + 'mpe': 'video/mpeg', + 'mpeg': 'video/mpeg', + 'mpg': 'video/mpeg', + 'mpg4': 'video/mp4', + 'mpga': 'audio/mpeg', + 'mpkg': 'application/vnd.apple.installer+xml', + 'mpm': 'application/vnd.blueice.multipass', + 'mpn': 'application/vnd.mophun.application', + 'mpp': 'application/vnd.ms-project', + 'mpt': 'application/vnd.ms-project', + 'mpy': 'application/vnd.ibm.minipay', + 'mqy': 'application/vnd.mobius.mqy', + 'mrc': 'application/marc', + 'mrcx': 'application/marcxml+xml', + 'ms': 'text/troff', + 'mscml': 'application/mediaservercontrol+xml', + 'mseed': 'application/vnd.fdsn.mseed', + 'mseq': 'application/vnd.mseq', + 'msf': 'application/vnd.epson.msf', + 'msh': 'model/mesh', + 'msi': 'application/x-msdownload', + 'msl': 'application/vnd.mobius.msl', + 'msty': 'application/vnd.muvee.style', + 'mts': 'model/vnd.mts', + 'mus': 'application/vnd.musician', + 'musicxml': 'application/vnd.recordare.musicxml+xml', + 'mvb': 'application/x-msmediaview', + 'mwf': 'application/vnd.mfer', + 'mxf': 'application/mxf', + 'mxl': 'application/vnd.recordare.musicxml', + 'mxml': 'application/xv+xml', + 'mxs': 'application/vnd.triscape.mxs', + 'mxu': 'video/vnd.mpegurl', + 'n-gage': 'application/vnd.nokia.n-gage.symbian.install', + 'n3': 'text/n3', + 'nb': 'application/mathematica', + 'nbp': 'application/vnd.wolfram.player', + 'nc': 'application/x-netcdf', + 'ncx': 'application/x-dtbncx+xml', + 'nfo': 'text/x-nfo', + 'ngdat': 'application/vnd.nokia.n-gage.data', + 'nitf': 'application/vnd.nitf', + 'nlu': 'application/vnd.neurolanguage.nlu', + 'nml': 'application/vnd.enliven', + 'nnd': 'application/vnd.noblenet-directory', + 'nns': 'application/vnd.noblenet-sealer', + 'nnw': 'application/vnd.noblenet-web', + 'npx': 'image/vnd.net-fpx', + 'nsc': 'application/x-conference', + 'nsf': 'application/vnd.lotus-notes', + 'ntf': 'application/vnd.nitf', + 'nzb': 'application/x-nzb', + 'oa2': 'application/vnd.fujitsu.oasys2', + 'oa3': 'application/vnd.fujitsu.oasys3', + 'oas': 'application/vnd.fujitsu.oasys', + 'obd': 'application/x-msbinder', + 'obj': 'application/x-tgif', + 'oda': 'application/oda', + 'odb': 'application/vnd.oasis.opendocument.database', + 'odc': 'application/vnd.oasis.opendocument.chart', + 'odf': 'application/vnd.oasis.opendocument.formula', + 'odft': 'application/vnd.oasis.opendocument.formula-template', + 'odg': 'application/vnd.oasis.opendocument.graphics', + 'odi': 'application/vnd.oasis.opendocument.image', + 'odm': 'application/vnd.oasis.opendocument.text-master', + 'odp': 'application/vnd.oasis.opendocument.presentation', + 'ods': 'application/vnd.oasis.opendocument.spreadsheet', + 'odt': 'application/vnd.oasis.opendocument.text', + 'oga': 'audio/ogg', + 'ogg': 'audio/ogg', + 'ogv': 'video/ogg', + 'ogx': 'application/ogg', + 'omdoc': 'application/omdoc+xml', + 'onepkg': 'application/onenote', + 'onetmp': 'application/onenote', + 'onetoc': 'application/onenote', + 'onetoc2': 'application/onenote', + 'opf': 'application/oebps-package+xml', + 'opml': 'text/x-opml', + 'oprc': 'application/vnd.palm', + 'org': 'application/vnd.lotus-organizer', + 'osf': 'application/vnd.yamaha.openscoreformat', + 'osfpvg': 'application/vnd.yamaha.openscoreformat.osfpvg+xml', + 'otc': 'application/vnd.oasis.opendocument.chart-template', + 'otf': 'application/x-font-otf', + 'otg': 'application/vnd.oasis.opendocument.graphics-template', + 'oth': 'application/vnd.oasis.opendocument.text-web', + 'oti': 'application/vnd.oasis.opendocument.image-template', + 'otp': 'application/vnd.oasis.opendocument.presentation-template', + 'ots': 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott': 'application/vnd.oasis.opendocument.text-template', + 'oxps': 'application/oxps', + 'oxt': 'application/vnd.openofficeorg.extension', + 'p': 'text/x-pascal', + 'p10': 'application/pkcs10', + 'p12': 'application/x-pkcs12', + 'p7b': 'application/x-pkcs7-certificates', + 'p7c': 'application/pkcs7-mime', + 'p7m': 'application/pkcs7-mime', + 'p7r': 'application/x-pkcs7-certreqresp', + 'p7s': 'application/pkcs7-signature', + 'p8': 'application/pkcs8', + 'pas': 'text/x-pascal', + 'paw': 'application/vnd.pawaafile', + 'pbd': 'application/vnd.powerbuilder6', + 'pbm': 'image/x-portable-bitmap', + 'pcap': 'application/vnd.tcpdump.pcap', + 'pcf': 'application/x-font-pcf', + 'pcl': 'application/vnd.hp-pcl', + 'pclxl': 'application/vnd.hp-pclxl', + 'pct': 'image/x-pict', + 'pcurl': 'application/vnd.curl.pcurl', + 'pcx': 'image/x-pcx', + 'pdb': 'application/vnd.palm', + 'pdf': 'application/pdf', + 'pfa': 'application/x-font-type1', + 'pfb': 'application/x-font-type1', + 'pfm': 'application/x-font-type1', + 'pfr': 'application/font-tdpfr', + 'pfx': 'application/x-pkcs12', + 'pgm': 'image/x-portable-graymap', + 'pgn': 'application/x-chess-pgn', + 'pgp': 'application/pgp-encrypted', + 'pic': 'image/x-pict', + 'pkg': 'application/octet-stream', + 'pki': 'application/pkixcmp', + 'pkipath': 'application/pkix-pkipath', + 'plb': 'application/vnd.3gpp.pic-bw-large', + 'plc': 'application/vnd.mobius.plc', + 'plf': 'application/vnd.pocketlearn', + 'pls': 'application/pls+xml', + 'pml': 'application/vnd.ctc-posml', + 'png': 'image/png', + 'pnm': 'image/x-portable-anymap', + 'portpkg': 'application/vnd.macports.portpkg', + 'pot': 'application/vnd.ms-powerpoint', + 'potm': 'application/vnd.ms-powerpoint.template.macroenabled.12', + 'potx': + 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppam': 'application/vnd.ms-powerpoint.addin.macroenabled.12', + 'ppd': 'application/vnd.cups-ppd', + 'ppm': 'image/x-portable-pixmap', + 'pps': 'application/vnd.ms-powerpoint', + 'ppsm': 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', + 'ppsx': + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppt': 'application/vnd.ms-powerpoint', + 'pptm': 'application/vnd.ms-powerpoint.presentation.macroenabled.12', + 'pptx': + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pqa': 'application/vnd.palm', + 'prc': 'application/x-mobipocket-ebook', + 'pre': 'application/vnd.lotus-freelance', + 'prf': 'application/pics-rules', + 'ps': 'application/postscript', + 'psb': 'application/vnd.3gpp.pic-bw-small', + 'psd': 'image/vnd.adobe.photoshop', + 'psf': 'application/x-font-linux-psf', + 'pskcxml': 'application/pskc+xml', + 'ptid': 'application/vnd.pvi.ptid1', + 'pub': 'application/x-mspublisher', + 'pvb': 'application/vnd.3gpp.pic-bw-var', + 'pwn': 'application/vnd.3m.post-it-notes', + 'pya': 'audio/vnd.ms-playready.media.pya', + 'pyv': 'video/vnd.ms-playready.media.pyv', + 'qam': 'application/vnd.epson.quickanime', + 'qbo': 'application/vnd.intu.qbo', + 'qfx': 'application/vnd.intu.qfx', + 'qps': 'application/vnd.publishare-delta-tree', + 'qt': 'video/quicktime', + 'qwd': 'application/vnd.quark.quarkxpress', + 'qwt': 'application/vnd.quark.quarkxpress', + 'qxb': 'application/vnd.quark.quarkxpress', + 'qxd': 'application/vnd.quark.quarkxpress', + 'qxl': 'application/vnd.quark.quarkxpress', + 'qxt': 'application/vnd.quark.quarkxpress', + 'ra': 'audio/x-pn-realaudio', + 'ram': 'audio/x-pn-realaudio', + 'rar': 'application/x-rar-compressed', + 'ras': 'image/x-cmu-raster', + 'rcprofile': 'application/vnd.ipunplugged.rcprofile', + 'rdf': 'application/rdf+xml', + 'rdz': 'application/vnd.data-vision.rdz', + 'rep': 'application/vnd.businessobjects', + 'res': 'application/x-dtbresource+xml', + 'rgb': 'image/x-rgb', + 'rif': 'application/reginfo+xml', + 'rip': 'audio/vnd.rip', + 'ris': 'application/x-research-info-systems', + 'rl': 'application/resource-lists+xml', + 'rlc': 'image/vnd.fujixerox.edmics-rlc', + 'rld': 'application/resource-lists-diff+xml', + 'rm': 'application/vnd.rn-realmedia', + 'rmi': 'audio/midi', + 'rmp': 'audio/x-pn-realaudio-plugin', + 'rms': 'application/vnd.jcp.javame.midlet-rms', + 'rmvb': 'application/vnd.rn-realmedia-vbr', + 'rnc': 'application/relax-ng-compact-syntax', + 'roa': 'application/rpki-roa', + 'roff': 'text/troff', + 'rp9': 'application/vnd.cloanto.rp9', + 'rpss': 'application/vnd.nokia.radio-presets', + 'rpst': 'application/vnd.nokia.radio-preset', + 'rq': 'application/sparql-query', + 'rs': 'application/rls-services+xml', + 'rsd': 'application/rsd+xml', + 'rss': 'application/rss+xml', + 'rtf': 'application/rtf', + 'rtx': 'text/richtext', + 's': 'text/x-asm', + 's3m': 'audio/s3m', + 'saf': 'application/vnd.yamaha.smaf-audio', + 'sbml': 'application/sbml+xml', + 'sc': 'application/vnd.ibm.secure-container', + 'scd': 'application/x-msschedule', + 'scm': 'application/vnd.lotus-screencam', + 'scq': 'application/scvp-cv-request', + 'scs': 'application/scvp-cv-response', + 'scurl': 'text/vnd.curl.scurl', + 'sda': 'application/vnd.stardivision.draw', + 'sdc': 'application/vnd.stardivision.calc', + 'sdd': 'application/vnd.stardivision.impress', + 'sdkd': 'application/vnd.solent.sdkm+xml', + 'sdkm': 'application/vnd.solent.sdkm+xml', + 'sdp': 'application/sdp', + 'sdw': 'application/vnd.stardivision.writer', + 'see': 'application/vnd.seemail', + 'seed': 'application/vnd.fdsn.seed', + 'sema': 'application/vnd.sema', + 'semd': 'application/vnd.semd', + 'semf': 'application/vnd.semf', + 'ser': 'application/java-serialized-object', + 'setpay': 'application/set-payment-initiation', + 'setreg': 'application/set-registration-initiation', + 'sfd-hdstx': 'application/vnd.hydrostatix.sof-data', + 'sfs': 'application/vnd.spotfire.sfs', + 'sfv': 'text/x-sfv', + 'sgi': 'image/sgi', + 'sgl': 'application/vnd.stardivision.writer-global', + 'sgm': 'text/sgml', + 'sgml': 'text/sgml', + 'sh': 'application/x-sh', + 'shar': 'application/x-shar', + 'shf': 'application/shf+xml', + 'sid': 'image/x-mrsid-image', + 'sig': 'application/pgp-signature', + 'sil': 'audio/silk', + 'silo': 'model/mesh', + 'sis': 'application/vnd.symbian.install', + 'sisx': 'application/vnd.symbian.install', + 'sit': 'application/x-stuffit', + 'sitx': 'application/x-stuffitx', + 'skd': 'application/vnd.koan', + 'skm': 'application/vnd.koan', + 'skp': 'application/vnd.koan', + 'skt': 'application/vnd.koan', + 'sldm': 'application/vnd.ms-powerpoint.slide.macroenabled.12', + 'sldx': 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'slt': 'application/vnd.epson.salt', + 'sm': 'application/vnd.stepmania.stepchart', + 'smf': 'application/vnd.stardivision.math', + 'smi': 'application/smil+xml', + 'smil': 'application/smil+xml', + 'smv': 'video/x-smv', + 'smzip': 'application/vnd.stepmania.package', + 'snd': 'audio/basic', + 'snf': 'application/x-font-snf', + 'so': 'application/octet-stream', + 'spc': 'application/x-pkcs7-certificates', + 'spf': 'application/vnd.yamaha.smaf-phrase', + 'spl': 'application/x-futuresplash', + 'spot': 'text/vnd.in3d.spot', + 'spp': 'application/scvp-vp-response', + 'spq': 'application/scvp-vp-request', + 'spx': 'audio/ogg', + 'sql': 'application/x-sql', + 'src': 'application/x-wais-source', + 'srt': 'application/x-subrip', + 'sru': 'application/sru+xml', + 'srx': 'application/sparql-results+xml', + 'ssdl': 'application/ssdl+xml', + 'sse': 'application/vnd.kodak-descriptor', + 'ssf': 'application/vnd.epson.ssf', + 'ssml': 'application/ssml+xml', + 'st': 'application/vnd.sailingtracker.track', + 'stc': 'application/vnd.sun.xml.calc.template', + 'std': 'application/vnd.sun.xml.draw.template', + 'stf': 'application/vnd.wt.stf', + 'sti': 'application/vnd.sun.xml.impress.template', + 'stk': 'application/hyperstudio', + 'stl': 'application/vnd.ms-pki.stl', + 'str': 'application/vnd.pg.format', + 'stw': 'application/vnd.sun.xml.writer.template', + 'sub': 'text/vnd.dvb.subtitle', + 'sus': 'application/vnd.sus-calendar', + 'susp': 'application/vnd.sus-calendar', + 'sv4cpio': 'application/x-sv4cpio', + 'sv4crc': 'application/x-sv4crc', + 'svc': 'application/vnd.dvb.service', + 'svd': 'application/vnd.svd', + 'svg': 'image/svg+xml', + 'svgz': 'image/svg+xml', + 'swa': 'application/x-director', + 'swf': 'application/x-shockwave-flash', + 'swi': 'application/vnd.aristanetworks.swi', + 'sxc': 'application/vnd.sun.xml.calc', + 'sxd': 'application/vnd.sun.xml.draw', + 'sxg': 'application/vnd.sun.xml.writer.global', + 'sxi': 'application/vnd.sun.xml.impress', + 'sxm': 'application/vnd.sun.xml.math', + 'sxw': 'application/vnd.sun.xml.writer', + 't': 'text/troff', + 't3': 'application/x-t3vm-image', + 'taglet': 'application/vnd.mynfc', + 'tao': 'application/vnd.tao.intent-module-archive', + 'tar': 'application/x-tar', + 'tcap': 'application/vnd.3gpp2.tcap', + 'tcl': 'application/x-tcl', + 'teacher': 'application/vnd.smart.teacher', + 'tei': 'application/tei+xml', + 'teicorpus': 'application/tei+xml', + 'tex': 'application/x-tex', + 'texi': 'application/x-texinfo', + 'texinfo': 'application/x-texinfo', + 'text': 'text/plain', + 'tfi': 'application/thraud+xml', + 'tfm': 'application/x-tex-tfm', + 'tga': 'image/x-tga', + 'thmx': 'application/vnd.ms-officetheme', + 'tif': 'image/tiff', + 'tiff': 'image/tiff', + 'tmo': 'application/vnd.tmobile-livetv', + 'torrent': 'application/x-bittorrent', + 'tpl': 'application/vnd.groove-tool-template', + 'tpt': 'application/vnd.trid.tpt', + 'tr': 'text/troff', + 'tra': 'application/vnd.trueapp', + 'trm': 'application/x-msterminal', + 'tsd': 'application/timestamped-data', + 'tsv': 'text/tab-separated-values', + 'ttc': 'application/x-font-ttf', + 'ttf': 'application/x-font-ttf', + 'ttl': 'text/turtle', + 'twd': 'application/vnd.simtech-mindmapper', + 'twds': 'application/vnd.simtech-mindmapper', + 'txd': 'application/vnd.genomatix.tuxedo', + 'txf': 'application/vnd.mobius.txf', + 'txt': 'text/plain', + 'u32': 'application/x-authorware-bin', + 'udeb': 'application/x-debian-package', + 'ufd': 'application/vnd.ufdl', + 'ufdl': 'application/vnd.ufdl', + 'ulx': 'application/x-glulx', + 'umj': 'application/vnd.umajin', + 'unityweb': 'application/vnd.unity', + 'uoml': 'application/vnd.uoml+xml', + 'uri': 'text/uri-list', + 'uris': 'text/uri-list', + 'urls': 'text/uri-list', + 'ustar': 'application/x-ustar', + 'utz': 'application/vnd.uiq.theme', + 'uu': 'text/x-uuencode', + 'uva': 'audio/vnd.dece.audio', + 'uvd': 'application/vnd.dece.data', + 'uvf': 'application/vnd.dece.data', + 'uvg': 'image/vnd.dece.graphic', + 'uvh': 'video/vnd.dece.hd', + 'uvi': 'image/vnd.dece.graphic', + 'uvm': 'video/vnd.dece.mobile', + 'uvp': 'video/vnd.dece.pd', + 'uvs': 'video/vnd.dece.sd', + 'uvt': 'application/vnd.dece.ttml+xml', + 'uvu': 'video/vnd.uvvu.mp4', + 'uvv': 'video/vnd.dece.video', + 'uvva': 'audio/vnd.dece.audio', + 'uvvd': 'application/vnd.dece.data', + 'uvvf': 'application/vnd.dece.data', + 'uvvg': 'image/vnd.dece.graphic', + 'uvvh': 'video/vnd.dece.hd', + 'uvvi': 'image/vnd.dece.graphic', + 'uvvm': 'video/vnd.dece.mobile', + 'uvvp': 'video/vnd.dece.pd', + 'uvvs': 'video/vnd.dece.sd', + 'uvvt': 'application/vnd.dece.ttml+xml', + 'uvvu': 'video/vnd.uvvu.mp4', + 'uvvv': 'video/vnd.dece.video', + 'uvvx': 'application/vnd.dece.unspecified', + 'uvvz': 'application/vnd.dece.zip', + 'uvx': 'application/vnd.dece.unspecified', + 'uvz': 'application/vnd.dece.zip', + 'vcard': 'text/vcard', + 'vcd': 'application/x-cdlink', + 'vcf': 'text/x-vcard', + 'vcg': 'application/vnd.groove-vcard', + 'vcs': 'text/x-vcalendar', + 'vcx': 'application/vnd.vcx', + 'vis': 'application/vnd.visionary', + 'viv': 'video/vnd.vivo', + 'vob': 'video/x-ms-vob', + 'vor': 'application/vnd.stardivision.writer', + 'vox': 'application/x-authorware-bin', + 'vrml': 'model/vrml', + 'vsd': 'application/vnd.visio', + 'vsf': 'application/vnd.vsf', + 'vss': 'application/vnd.visio', + 'vst': 'application/vnd.visio', + 'vsw': 'application/vnd.visio', + 'vtu': 'model/vnd.vtu', + 'vxml': 'application/voicexml+xml', + 'w3d': 'application/x-director', + 'wad': 'application/x-doom', + 'wasm': 'application/wasm', + 'wav': 'audio/x-wav', + 'wax': 'audio/x-ms-wax', + 'wbmp': 'image/vnd.wap.wbmp', + 'wbs': 'application/vnd.criticaltools.wbs+xml', + 'wbxml': 'application/vnd.wap.wbxml', + 'wcm': 'application/vnd.ms-works', + 'wdb': 'application/vnd.ms-works', + 'wdp': 'image/vnd.ms-photo', + 'weba': 'audio/webm', + 'webm': 'video/webm', + 'webp': 'image/webp', + 'wg': 'application/vnd.pmi.widget', + 'wgt': 'application/widget', + 'wks': 'application/vnd.ms-works', + 'wm': 'video/x-ms-wm', + 'wma': 'audio/x-ms-wma', + 'wmd': 'application/x-ms-wmd', + 'wmf': 'application/x-msmetafile', + 'wml': 'text/vnd.wap.wml', + 'wmlc': 'application/vnd.wap.wmlc', + 'wmls': 'text/vnd.wap.wmlscript', + 'wmlsc': 'application/vnd.wap.wmlscriptc', + 'wmv': 'video/x-ms-wmv', + 'wmx': 'video/x-ms-wmx', + 'wmz': 'application/x-ms-wmz', + 'woff': 'application/x-font-woff', + 'wpd': 'application/vnd.wordperfect', + 'wpl': 'application/vnd.ms-wpl', + 'wps': 'application/vnd.ms-works', + 'wqd': 'application/vnd.wqd', + 'wri': 'application/x-mswrite', + 'wrl': 'model/vrml', + 'wsdl': 'application/wsdl+xml', + 'wspolicy': 'application/wspolicy+xml', + 'wtb': 'application/vnd.webturbo', + 'wvx': 'video/x-ms-wvx', + 'x32': 'application/x-authorware-bin', + 'x3d': 'model/x3d+xml', + 'x3db': 'model/x3d+binary', + 'x3dbz': 'model/x3d+binary', + 'x3dv': 'model/x3d+vrml', + 'x3dvz': 'model/x3d+vrml', + 'x3dz': 'model/x3d+xml', + 'xaml': 'application/xaml+xml', + 'xap': 'application/x-silverlight-app', + 'xar': 'application/vnd.xara', + 'xbap': 'application/x-ms-xbap', + 'xbd': 'application/vnd.fujixerox.docuworks.binder', + 'xbm': 'image/x-xbitmap', + 'xdf': 'application/xcap-diff+xml', + 'xdm': 'application/vnd.syncml.dm+xml', + 'xdp': 'application/vnd.adobe.xdp+xml', + 'xdssc': 'application/dssc+xml', + 'xdw': 'application/vnd.fujixerox.docuworks', + 'xenc': 'application/xenc+xml', + 'xer': 'application/patch-ops-error+xml', + 'xfdf': 'application/vnd.adobe.xfdf', + 'xfdl': 'application/vnd.xfdl', + 'xht': 'application/xhtml+xml', + 'xhtml': 'application/xhtml+xml', + 'xhvml': 'application/xv+xml', + 'xif': 'image/vnd.xiff', + 'xla': 'application/vnd.ms-excel', + 'xlam': 'application/vnd.ms-excel.addin.macroenabled.12', + 'xlc': 'application/vnd.ms-excel', + 'xlf': 'application/x-xliff+xml', + 'xlm': 'application/vnd.ms-excel', + 'xls': 'application/vnd.ms-excel', + 'xlsb': 'application/vnd.ms-excel.sheet.binary.macroenabled.12', + 'xlsm': 'application/vnd.ms-excel.sheet.macroenabled.12', + 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlt': 'application/vnd.ms-excel', + 'xltm': 'application/vnd.ms-excel.template.macroenabled.12', + 'xltx': + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlw': 'application/vnd.ms-excel', + 'xm': 'audio/xm', + 'xml': 'application/xml', + 'xo': 'application/vnd.olpc-sugar', + 'xop': 'application/xop+xml', + 'xpi': 'application/x-xpinstall', + 'xpl': 'application/xproc+xml', + 'xpm': 'image/x-xpixmap', + 'xpr': 'application/vnd.is-xpr', + 'xps': 'application/vnd.ms-xpsdocument', + 'xpw': 'application/vnd.intercon.formnet', + 'xpx': 'application/vnd.intercon.formnet', + 'xsl': 'application/xml', + 'xslt': 'application/xslt+xml', + 'xsm': 'application/vnd.syncml+xml', + 'xspf': 'application/xspf+xml', + 'xul': 'application/vnd.mozilla.xul+xml', + 'xvm': 'application/xv+xml', + 'xvml': 'application/xv+xml', + 'xwd': 'image/x-xwindowdump', + 'xyz': 'chemical/x-xyz', + 'xz': 'application/x-xz', + 'yang': 'application/yang', + 'yin': 'application/yin+xml', + 'z1': 'application/x-zmachine', + 'z2': 'application/x-zmachine', + 'z3': 'application/x-zmachine', + 'z4': 'application/x-zmachine', + 'z5': 'application/x-zmachine', + 'z6': 'application/x-zmachine', + 'z7': 'application/x-zmachine', + 'z8': 'application/x-zmachine', + 'zaz': 'application/vnd.zzazz.deck+xml', + 'zip': 'application/zip', + 'zir': 'application/vnd.zul', + 'zirz': 'application/vnd.zul', + 'zmm': 'application/vnd.handheld-entertainment+xml', +}; +NN<;B( ')))"&1)%&'%'*"H$&4%1+"&.$"((1"22)%"#,(-% " (/ % <@*****.)%*#$-!1*)&&%+'") ((C(%"4344+!(4$% '%!'2(#  #"'+*$#"(*)('*)#'&'%*)% > +Q> +Q#$"% &)#,,,$))$&%%"%$*#")+&) %)$(*#5% 9,#+&"&()**@&''$%+*)$.**(4 (' ##(.,#+ 0$$"%%#%(*,-%'$'4%'+7.#"$33 324(8,,- % "$*0"'*))1-""(++)($$&&+"?D.)2,+&%%#(#*)&&+#"))%&#'( "#(*"!&3- &1!+"," /1./''('%1)"&%')%8&!/ )<#+ %0".$/,)%(!++*#857A85;<;4$###$*",3A>#A8>ED=4!-##,(&*$*##')!%%%#!%$&% ).'( &$1*D +OA%$*E +P*H +S!+,#".&)%'&,----%%2...... !)8 ,,*$0*+0((2.0!(10$( ."0%,()"..1--0$'"""/277)7 &,-"$!!!!AP'/.!"0#$-/' )(&! +"-&"022#5$'&4")*&$( #*/))2,)+$%6(. &#&#",+)1%$%)&##/0-')*!" #'&"&!&&##"*!"''$$#+ ".&-%!) &0)" """&# 2(%%&%!%&$-!%(#% ""*%)"*!#7&**#0",(""$!%<%$%%C numbers; + final List mask; + + const MagicNumber(this.mimeType, this.numbers, {this.mask}); + + bool matches(List header) { + if (header.length < numbers.length) return false; + + for (int i = 0; i < numbers.length; i++) { + if (mask != null) { + if ((mask[i] & numbers[i]) != (mask[i] & header[i])) return false; + } else { + if (numbers[i] != header[i]) return false; + } + } + + return true; + } +} + +const int DEFAULT_MAGIC_NUMBERS_MAX_LENGTH = 12; + +const List DEFAULT_MAGIC_NUMBERS = const [ + const MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), + const MagicNumber('application/postscript', const [0x25, 0x51]), + const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), + const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), + const MagicNumber('image/jpeg', const [0xFF, 0xD8]), + const MagicNumber( + 'image/png', const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), + const MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), + const MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), + const MagicNumber('video/mp4', const [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x33, + 0x67, + 0x70, + 0x35 + ], mask: const [ + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + const MagicNumber('model/gltf-binary', const [0x46, 0x54, 0x6C, 0x67]), +]; +GNN<?#6/K318HCNN7LCC) + + + + + + + + + + +  + + + + + + + + + + + J`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/code_buffer-1.0.1/lib/code_buffer.dartimport 'package:source_span/source_span.dart'; + +/// An advanced StringBuffer geared toward generating code, and source maps. +class CodeBuffer implements StringBuffer { + /// The character sequence used to represent a line break. + final String newline; + + /// The character sequence used to represent a space/tab. + final String space; + + /// The source URL to be applied to all generated [SourceSpan] instances. + final sourceUrl; + + /// If `true` (default: `false`), then an additional [newline] will be inserted at the end of the generated string. + final bool trailingNewline; + + final List _lines = []; + CodeBufferLine _currentLine, _lastLine; + int _indentationLevel = 0; + int _length = 0; + + CodeBuffer( + {this.space: ' ', + this.newline: '\n', + this.trailingNewline: false, + this.sourceUrl}); + + /// Creates a [CodeBuffer] that does not emit additional whitespace. + factory CodeBuffer.noWhitespace({sourceUrl}) => new CodeBuffer( + space: '', newline: '', trailingNewline: false, sourceUrl: sourceUrl); + + /// The last line created within this buffer. + CodeBufferLine get lastLine => _lastLine; + + /// Returns an immutable collection of the [CodeBufferLine]s within this instance. + List get lines => + new List.unmodifiable(_lines); + + @override + bool get isEmpty => _lines.isEmpty; + + @override + bool get isNotEmpty => _lines.isNotEmpty; + + @override + int get length => _length; + + CodeBufferLine _createLine() { + var start = new SourceLocation( + _length, + sourceUrl: sourceUrl, + line: _lines.length, + column: _indentationLevel * space.length, + ); + var line = new CodeBufferLine._(_indentationLevel, start).._end = start; + _lines.add(_lastLine = line); + return line; + } + + /// Increments the indentation level. + void indent() { + _indentationLevel++; + } + + /// Decrements the indentation level, if it is greater than `0`. + void outdent() { + if (_indentationLevel > 0) _indentationLevel--; + } + + /// Copies the contents of this [CodeBuffer] into another, preserving indentation and source mapping information. + void copyInto(CodeBuffer other) { + if (_lines.isEmpty) return; + int i = 0; + + for (var line in _lines) { + // To compute offset: + // 1. Find current length of other + // 2. Add length of its newline + // 3. Add indentation + var column = (other._indentationLevel + line.indentationLevel) * + other.space.length; + var offset = other._length + other.newline.length + column; + + // Re-compute start + end + var start = new SourceLocation( + offset, + sourceUrl: other.sourceUrl, + line: other._lines.length + i, + column: column, + ); + + var end = new SourceLocation( + offset + line.span.length, + sourceUrl: other.sourceUrl, + line: start.line, + column: column + line._buf.length, + ); + + var clone = new CodeBufferLine._( + line.indentationLevel + other._indentationLevel, start) + .._end = end + .._buf.write(line._buf.toString()); + + // Adjust lastSpan + if (line._lastSpan != null) { + var s = line._lastSpan.start; + var lastSpanColumn = + ((line.indentationLevel + other._indentationLevel) * + other.space.length) + + line.text.indexOf(line._lastSpan.text); + clone._lastSpan = new SourceSpan( + new SourceLocation( + offset + s.offset, + sourceUrl: other.sourceUrl, + line: clone.span.start.line, + column: lastSpanColumn, + ), + new SourceLocation( + offset + s.offset + line._lastSpan.length, + sourceUrl: other.sourceUrl, + line: clone.span.end.line, + column: lastSpanColumn + line._lastSpan.length, + ), + line._lastSpan.text, + ); + } + + other._lines.add(other._currentLine = other._lastLine = clone); + + // Adjust length accordingly... + other._length = offset + clone.span.length; + i++; + } + + other.writeln(); + } + + @override + void clear() { + _lines.clear(); + _length = _indentationLevel = 0; + _currentLine = null; + } + + @override + void writeCharCode(int charCode) { + _currentLine ??= _createLine(); + _currentLine._buf.writeCharCode(charCode); + var end = _currentLine._end; + _currentLine._end = new SourceLocation( + end.offset + 1, + sourceUrl: end.sourceUrl, + line: end.line, + column: end.column + 1, + ); + _length++; + _currentLine._lastSpan = new SourceSpan( + end, _currentLine._end, new String.fromCharCode(charCode)); + } + + @override + void write(Object obj) { + var msg = obj.toString(); + _currentLine ??= _createLine(); + _currentLine._buf.write(msg); + var end = _currentLine._end; + _currentLine._end = new SourceLocation( + end.offset + msg.length, + sourceUrl: end.sourceUrl, + line: end.line, + column: end.column + msg.length, + ); + _length += msg.length; + _currentLine._lastSpan = new SourceSpan(end, _currentLine._end, msg); + } + + @override + void writeln([Object obj = ""]) { + if (obj != null && obj != '') write(obj); + _currentLine = null; + _length++; + } + + @override + void writeAll(Iterable objects, [String separator = ""]) { + write(objects.join(separator)); + } + + @override + String toString() { + var buf = new StringBuffer(); + int i = 0; + + for (var line in lines) { + if (i++ > 0) buf.write(newline); + for (int j = 0; j < line.indentationLevel; j++) buf.write(space); + buf.write(line._buf.toString()); + } + + if (trailingNewline == true) buf.write(newline); + + return buf.toString(); + } +} + +/// Represents a line of text within a [CodeBuffer]. +class CodeBufferLine { + /// Mappings from one [SourceSpan] to another, to aid with generating dynamic source maps. + final Map sourceMappings = {}; + + /// The level of indentation preceding this line. + final int indentationLevel; + + final SourceLocation _start; + final StringBuffer _buf = new StringBuffer(); + SourceLocation _end; + SourceSpan _lastSpan; + + CodeBufferLine._(this.indentationLevel, this._start); + + /// The [SourceSpan] corresponding to the last text written to this line. + SourceSpan get lastSpan => _lastSpan; + + /// The [SourceSpan] corresponding to this entire line. + SourceSpan get span => new SourceSpan(_start, _end, _buf.toString()); + + /// The text within this line. + String get text => _buf.toString(); +} +/M+=<Lv**#GBM0,U$5 & , !$0M"(C4t$ +(GB &$' $#$+ (B,$&A*8*()$ 7('<  F&2  % %$/!, -D $"!, 'J $. =$ "'H'55]9408L(:H!&Yfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/matcher.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Support for specifying test expectations, such as for unit tests. +export 'src/core_matchers.dart'; +export 'src/custom_matcher.dart'; +export 'src/description.dart'; +export 'src/equals_matcher.dart'; +export 'src/error_matchers.dart'; +export 'src/interfaces.dart'; +export 'src/iterable_matchers.dart'; +export 'src/map_matchers.dart'; +export 'src/numeric_matchers.dart'; +export 'src/operator_matchers.dart'; +export 'src/order_matchers.dart'; +export 'src/string_matchers.dart'; +export 'src/type_matcher.dart'; +export 'src/util.dart'; +NN<F!"""% $%"# `file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/source_span.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export "src/file.dart"; +export "src/location.dart"; +export "src/location_mixin.dart"; +export "src/span.dart"; +export "src/span_exception.dart"; +export "src/span_mixin.dart"; +export "src/span_with_context.dart"; + NN<""%efile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/src/exception.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +/// An exception thrown by a [StringScanner] that failed to parse a string. +class StringScannerException extends SourceSpanFormatException { + String get source => super.source; + + /// The URL of the source file being parsed. + /// + /// This may be `null`, indicating that the source URL is unknown. + Uri get sourceUrl => span.sourceUrl; + + StringScannerException(String message, SourceSpan span, String source) + : super(message, span, source); +} +NN</LA%/E'I&hfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/src/line_scanner.dartQ// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:charcode/ascii.dart'; + +import 'string_scanner.dart'; + +// Note that much of this code is duplicated in eager_span_scanner.dart. + +/// A regular expression matching newlines across platforms. +final _newlineRegExp = new RegExp(r"\r\n?|\n"); + +/// A subclass of [StringScanner] that tracks line and column information. +class LineScanner extends StringScanner { + /// The scanner's current (zero-based) line number. + int get line => _line; + int _line = 0; + + /// The scanner's current (zero-based) column number. + int get column => _column; + int _column = 0; + + /// The scanner's state, including line and column information. + /// + /// This can be used to efficiently save and restore the state of the scanner + /// when backtracking. A given [LineScannerState] is only valid for the + /// [LineScanner] that created it. + /// + /// This does not include the scanner's match information. + LineScannerState get state => + new LineScannerState._(this, position, line, column); + + /// Whether the current position is between a CR character and an LF + /// charactet. + bool get _betweenCRLF => peekChar(-1) == $cr && peekChar() == $lf; + + set state(LineScannerState state) { + if (!identical(state._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + super.position = state.position; + _line = state.line; + _column = state.column; + } + + set position(int newPosition) { + var oldPosition = position; + super.position = newPosition; + + if (newPosition > oldPosition) { + var newlines = _newlinesIn(string.substring(oldPosition, newPosition)); + _line += newlines.length; + if (newlines.isEmpty) { + _column += newPosition - oldPosition; + } else { + _column = newPosition - newlines.last.end; + } + } else { + var newlines = _newlinesIn(string.substring(newPosition, oldPosition)); + if (_betweenCRLF) newlines.removeLast(); + + _line -= newlines.length; + if (newlines.isEmpty) { + _column -= oldPosition - newPosition; + } else { + _column = + newPosition - string.lastIndexOf(_newlineRegExp, newPosition) - 1; + } + } + } + + LineScanner(String string, {sourceUrl, int position}) + : super(string, sourceUrl: sourceUrl, position: position); + + bool scanChar(int character) { + if (!super.scanChar(character)) return false; + _adjustLineAndColumn(character); + return true; + } + + int readChar() { + var character = super.readChar(); + _adjustLineAndColumn(character); + return character; + } + + /// Adjusts [_line] and [_column] after having consumed [character]. + void _adjustLineAndColumn(int character) { + if (character == $lf || (character == $cr && peekChar() != $lf)) { + _line += 1; + _column = 0; + } else { + _column += 1; + } + } + + bool scan(Pattern pattern) { + if (!super.scan(pattern)) return false; + + var newlines = _newlinesIn(lastMatch[0]); + _line += newlines.length; + if (newlines.isEmpty) { + _column += lastMatch[0].length; + } else { + _column = lastMatch[0].length - newlines.last.end; + } + + return true; + } + + /// Returns a list of [Match]es describing all the newlines in [text], which + /// is assumed to end at [position]. + List _newlinesIn(String text) { + var newlines = _newlineRegExp.allMatches(text).toList(); + if (_betweenCRLF) newlines.removeLast(); + return newlines; + } +} + +/// A class representing the state of a [LineScanner]. +class LineScannerState { + /// The [LineScanner] that created this. + final LineScanner _scanner; + + /// The position of the scanner in this state. + final int position; + + /// The zero-based line number of the scanner in this state. + final int line; + + /// The zero-based column number of the scanner in this state. + final int column; + + LineScannerState._(this._scanner, this.position, this.line, this.column); +} +NN<&I=0K*68BPJ%= <GE&,P %" "%N .3 N/ .O8A!2%&%G-G ,.& 9O')=-7+1?ALhfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/src/span_scanner.dart~// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +import 'eager_span_scanner.dart'; +import 'exception.dart'; +import 'line_scanner.dart'; +import 'relative_span_scanner.dart'; +import 'string_scanner.dart'; +import 'utils.dart'; + +/// A subclass of [LineScanner] that exposes matched ranges as source map +/// [Span]s. +class SpanScanner extends StringScanner implements LineScanner { + /// The source of the scanner. + /// + /// This caches line break information and is used to generate [Span]s. + final SourceFile _sourceFile; + + int get line => _sourceFile.getLine(position); + int get column => _sourceFile.getColumn(position); + + LineScannerState get state => new _SpanScannerState(this, position); + + set state(LineScannerState state) { + if (state is! _SpanScannerState || + !identical((state as _SpanScannerState)._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + this.position = state.position; + } + + /// The [FileSpan] for [lastMatch]. + /// + /// This is the span for the entire match. There's no way to get spans for + /// subgroups since [Match] exposes no information about their positions. + FileSpan get lastSpan { + if (lastMatch == null) _lastSpan = null; + return _lastSpan; + } + + FileSpan _lastSpan; + + /// The current location of the scanner. + FileLocation get location => _sourceFile.location(position); + + /// Returns an empty span at the current location. + FileSpan get emptySpan => location.pointSpan(); + + /// Creates a new [SpanScanner] that starts scanning from [position]. + /// + /// [sourceUrl] is used as [SourceLocation.sourceUrl] for the returned + /// [FileSpan]s as well as for error reporting. It can be a [String], a + /// [Uri], or `null`. + SpanScanner(String string, {sourceUrl, int position}) + : _sourceFile = new SourceFile.fromString(string, url: sourceUrl), + super(string, sourceUrl: sourceUrl, position: position); + + /// Creates a new [SpanScanner] that eagerly computes line and column numbers. + /// + /// In general [new SpanScanner] will be more efficient, since it avoids extra + /// computation on every scan. However, eager scanning can be useful for + /// situations where the normal course of parsing frequently involves + /// accessing the current line and column numbers. + /// + /// Note that *only* the `line` and `column` fields on the `SpanScanner` + /// itself and its `LineScannerState` are eagerly computed. To limit their + /// memory footprint, returned spans and locations will still lazily compute + /// their line and column numbers. + factory SpanScanner.eager(String string, {sourceUrl, int position}) = + EagerSpanScanner; + + /// Creates a new [SpanScanner] that scans within [span]. + /// + /// This scans through [span.text], but emits new spans from [span.file] in + /// their appropriate relative positions. The [string] field contains only + /// [span.text], and [position], [line], and [column] are all relative to the + /// span. + factory SpanScanner.within(FileSpan span) = RelativeSpanScanner; + + /// Creates a [FileSpan] representing the source range between [startState] + /// and the current position. + FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { + var endPosition = endState == null ? position : endState.position; + return _sourceFile.span(startState.position, endPosition); + } + + bool matches(Pattern pattern) { + if (!super.matches(pattern)) { + _lastSpan = null; + return false; + } + + _lastSpan = _sourceFile.span(position, lastMatch.end); + return true; + } + + void error(String message, {Match match, int position, int length}) { + validateErrorArgs(string, match, position, length); + + if (match == null && position == null && length == null) match = lastMatch; + if (position == null) { + position = match == null ? this.position : match.start; + } + if (length == null) length = match == null ? 0 : match.end - match.start; + + var span = _sourceFile.span(position, position + length); + throw new StringScannerException(message, span, string); + } +} + +/// A class representing the state of a [SpanScanner]. +class _SpanScannerState implements LineScannerState { + /// The [SpanScanner] that created this. + final SpanScanner _scanner; + + final int position; + int get line => _scanner._sourceFile.getLine(position); + int get column => _scanner._sourceFile.getColumn(position); + + _SpanScannerState(this._scanner, this.position); +} +NN</"%J A!J 15G&'CP $&ML-+?52HIJ8IAQQKH5KMO%H<NMP CN PG?"#;H8P>N>=76+:>3jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/src/string_scanner.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:charcode/charcode.dart'; +import 'package:meta/meta.dart'; +import 'package:source_span/source_span.dart'; + +import 'exception.dart'; +import 'utils.dart'; + +/// When compiled to JS, forward slashes are always escaped in [RegExp.pattern]. +/// +/// See issue 17998. +final _slashAutoEscape = new RegExp("/").pattern == "\\/"; + +/// A class that scans through a string using [Pattern]s. +class StringScanner { + /// The URL of the source of the string being scanned. + /// + /// This is used for error reporting. It may be `null`, indicating that the + /// source URL is unknown or unavailable. + final Uri sourceUrl; + + /// The string being scanned through. + final String string; + + /// The current position of the scanner in the string, in characters. + int get position => _position; + set position(int position) { + if (position < 0 || position > string.length) { + throw new ArgumentError("Invalid position $position"); + } + + _position = position; + _lastMatch = null; + } + + int _position = 0; + + /// The data about the previous match made by the scanner. + /// + /// If the last match failed, this will be `null`. + Match get lastMatch { + // Lazily unset [_lastMatch] so that we avoid extra assignments in + // character-by-character methods that are used in core loops. + if (_position != _lastMatchPosition) _lastMatch = null; + return _lastMatch; + } + + Match _lastMatch; + int _lastMatchPosition; + + /// The portion of the string that hasn't yet been scanned. + String get rest => string.substring(position); + + /// Whether the scanner has completely consumed [string]. + bool get isDone => position == string.length; + + /// Creates a new [StringScanner] that starts scanning from [position]. + /// + /// [position] defaults to 0, the beginning of the string. [sourceUrl] is the + /// URL of the source of the string being scanned, if available. It can be + /// a [String], a [Uri], or `null`. + StringScanner(this.string, {sourceUrl, int position}) + : sourceUrl = sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl { + if (position != null) this.position = position; + } + + /// Consumes a single character and returns its character code. + /// + /// This throws a [FormatException] if the string has been fully consumed. It + /// doesn't affect [lastMatch]. + int readChar() { + if (isDone) _fail("more input"); + return string.codeUnitAt(_position++); + } + + /// Returns the character code of the character [offset] away from [position]. + /// + /// [offset] defaults to zero, and may be negative to inspect already-consumed + /// characters. + /// + /// This returns `null` if [offset] points outside the string. It doesn't + /// affect [lastMatch]. + int peekChar([int offset]) { + if (offset == null) offset = 0; + var index = position + offset; + if (index < 0 || index >= string.length) return null; + return string.codeUnitAt(index); + } + + /// If the next character in the string is [character], consumes it. + /// + /// Returns whether or not [character] was consumed. + bool scanChar(int character) { + if (isDone) return false; + if (string.codeUnitAt(_position) != character) return false; + _position++; + return true; + } + + /// If the next character in the string is [character], consumes it. + /// + /// If [character] could not be consumed, throws a [FormatException] + /// describing the position of the failure. [name] is used in this error as + /// the expected name of the character being matched; if it's `null`, the + /// character itself is used instead. + void expectChar(int character, {String name}) { + if (scanChar(character)) return; + + if (name == null) { + if (character == $backslash) { + name = r'"\"'; + } else if (character == $double_quote) { + name = r'"\""'; + } else { + name = '"${new String.fromCharCode(character)}"'; + } + } + + _fail(name); + } + + /// If [pattern] matches at the current position of the string, scans forward + /// until the end of the match. + /// + /// Returns whether or not [pattern] matched. + bool scan(Pattern pattern) { + var success = matches(pattern); + if (success) { + _position = _lastMatch.end; + _lastMatchPosition = _position; + } + return success; + } + + /// If [pattern] matches at the current position of the string, scans forward + /// until the end of the match. + /// + /// If [pattern] did not match, throws a [FormatException] describing the + /// position of the failure. [name] is used in this error as the expected name + /// of the pattern being matched; if it's `null`, the pattern itself is used + /// instead. + void expect(Pattern pattern, {String name}) { + if (scan(pattern)) return; + + if (name == null) { + if (pattern is RegExp) { + var source = pattern.pattern; + if (!_slashAutoEscape) source = source.replaceAll("/", "\\/"); + name = "/$source/"; + } else { + name = + pattern.toString().replaceAll("\\", "\\\\").replaceAll('"', '\\"'); + name = '"$name"'; + } + } + _fail(name); + } + + /// If the string has not been fully consumed, this throws a + /// [FormatException]. + void expectDone() { + if (isDone) return; + _fail("no more input"); + } + + /// Returns whether or not [pattern] matches at the current position of the + /// string. + /// + /// This doesn't move the scan pointer forward. + bool matches(Pattern pattern) { + _lastMatch = pattern.matchAsPrefix(string, position); + _lastMatchPosition = _position; + return _lastMatch != null; + } + + /// Returns the substring of [string] between [start] and [end]. + /// + /// Unlike [String.substring], [end] defaults to [position] rather than the + /// end of the string. + String substring(int start, [int end]) { + if (end == null) end = position; + return string.substring(start, end); + } + + /// Throws a [FormatException] with [message] as well as a detailed + /// description of the location of the error in the string. + /// + /// [match] is the match information for the span of the string with which the + /// error is associated. This should be a match returned by this scanner's + /// [lastMatch] property. By default, the error is associated with the last + /// match. + /// + /// If [position] and/or [length] are passed, they are used as the error span + /// instead. If only [length] is passed, [position] defaults to the current + /// position; if only [position] is passed, [length] defaults to 0. + /// + /// It's an error to pass [match] at the same time as [position] or [length]. + @alwaysThrows + void error(String message, {Match match, int position, int length}) { + validateErrorArgs(string, match, position, length); + + if (match == null && position == null && length == null) match = lastMatch; + if (position == null) { + position = match == null ? this.position : match.start; + } + if (length == null) length = match == null ? 0 : match.end - match.start; + + var sourceFile = new SourceFile.fromString(string, url: sourceUrl); + var span = sourceFile.span(position, position + length); + throw new StringScannerException(message, span, string); + } + + // TODO(nweiz): Make this handle long lines more gracefully. + /// Throws a [FormatException] describing that [name] is expected at the + /// current position in the string. + void _fail(String name) { + error("expected $name.", position: this.position, length: 0); + } +} +NN<)!/Q;:9N,(H!4==5GC<>1<0JPM&8M4BP"%+QQL$#:%G7!AGGNL(2%%/:P"0$"&P"LQO0&GP?N2":$CN+%)F>QMN PNFPH8P>NH==?K&Bbfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_server-0.9.8/lib/src/http_body.dart\// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library http_server.http_body; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'http_body_impl.dart'; + +/** + * [HttpBodyHandler] is a helper class for processing and collecting + * HTTP message data in an easy-to-use [HttpBody] object. The content + * body is parsed, depending on the `Content-Type` header field. When + * the full body is read and parsed the body content is made + * available. The class can be used to process both server requests + * and client responses. + * + * The following content types are recognized: + * + * text/ * + * application/json + * application/x-www-form-urlencoded + * multipart/form-data + * + * For content type `text/\*` the body is decoded into a string. The + * 'charset' parameter of the content type specifies the encoding + * used for decoding. If no 'charset' is present the default encoding + * of ISO-8859-1 is used. + * + * For content type `application/json` the body is decoded into a + * string which is then parsed as JSON. The resulting body is a + * [Map]. The 'charset' parameter of the content type specifies the + * encoding used for decoding. If no 'charset' is present the default + * encoding of UTF-8 is used. + * + * For content type `application/x-www-form-urlencoded` the body is a + * query string which is then split according to the rules for + * splitting a query string. The resulting body is a `Map`. If the same name is present several times in the query + * string, then the last value seen for this name will be in the + * resulting map. The encoding US-ASCII is always used for decoding + * the body. + * + * For content type `multipart/form-data` the body is parsed into + * it's different fields. The resulting body is a `Map`, where the value is a [String] for normal fields and a + * [HttpBodyFileUpload] instance for file upload fields. If the same + * name is present several times, then the last value seen for this + * name will be in the resulting map. + * + * When using content type `multipart/form-data` the encoding of + * fields with [String] values is determined by the browser sending + * the HTTP request with the form data. The encoding is specified + * either by the attribute `accept-charset` on the HTML form, or by + * the content type of the web page containing the form. If the HTML + * form has an `accept-charset` attribute the browser will use the + * encoding specified there. If the HTML form has no `accept-charset` + * attribute the browser determines the encoding from the content + * type of the web page containing the form. Using a content type of + * `text/html; charset=utf-8` for the page and setting + * `accept-charset` on the HTML form to `utf-8` is recommended as the + * default for [HttpBodyHandler] is UTF-8. It is important to get + * these encoding values right, as the actual `multipart/form-data` + * HTTP request sent by the browser does _not_ contain any + * information on the encoding. If something else than UTF-8 is used + * `defaultEncoding` needs to be set in the [HttpBodyHandler] + * constructor and calls to [processRequest] and [processResponse]. + * + * For all other content types the body will be treated as + * uninterpreted binary data. The resulting body will be of type + * `List`. + * + * To use with the [HttpServer] for request messages, [HttpBodyHandler] can be + * used as either a [StreamTransformer] or as a per-request handler (see + * [processRequest]). + * + * HttpServer server = ... + * server.transform(new HttpBodyHandler()) + * .listen((HttpRequestBody body) { + * ... + * }); + * + * To use with the [HttpClient] for response messages, [HttpBodyHandler] can be + * used as a per-request handler (see [processResponse]). + * + * HttpClient client = ... + * client.get(...) + * .then((HttpClientRequest response) => response.close()) + * .then(HttpBodyHandler.processResponse) + * .then((HttpClientResponseBody body) { + * ... + * }); + * + */ +class HttpBodyHandler + extends StreamTransformerBase { + HttpBodyHandlerTransformer _transformer; + + /** + * Create a new [HttpBodyHandler] to be used with a [Stream]<[HttpRequest]>, + * e.g. a [HttpServer]. + * + * If the page is served using different encoding than UTF-8, set + * [defaultEncoding] accordingly. This is required for parsing + * `multipart/form-data` content correctly. See the class comment + * for more information on `multipart/form-data`. + */ + HttpBodyHandler({Encoding defaultEncoding: utf8}) + : _transformer = new HttpBodyHandlerTransformer(defaultEncoding); + + /** + * Process and parse an incoming [HttpRequest]. The returned [HttpRequestBody] + * contains a `response` field for accessing the [HttpResponse]. + * + * See [HttpBodyHandler] constructor for more info on [defaultEncoding]. + */ + static Future processRequest(HttpRequest request, + {Encoding defaultEncoding: utf8}) { + return HttpBodyHandlerImpl.processRequest(request, defaultEncoding); + } + + /** + * Process and parse an incoming [HttpClientResponse]. + * + * See [HttpBodyHandler] constructor for more info on [defaultEncoding]. + */ + static Future processResponse( + HttpClientResponse response, + {Encoding defaultEncoding: utf8}) { + return HttpBodyHandlerImpl.processResponse(response, defaultEncoding); + } + + Stream bind(Stream stream) { + return _transformer.bind(stream); + } +} + +/** + * A HTTP content body produced by [HttpBodyHandler] for either [HttpRequest] + * or [HttpClientResponse]. + */ +abstract class HttpBody { + /** + * A high-level type value, that reflects how the body was parsed, e.g. + * "text", "binary" and "json". + */ + String get type; + + /** + * The actual body. The type depends on [type]. + */ + dynamic get body; +} + +/** + * The [HttpBody] of a [HttpClientResponse] will be of type + * [HttpClientResponseBody]. It contains the [HttpClientResponse] object + * for access to the headers. + */ +abstract class HttpClientResponseBody extends HttpBody { + /** + * The [HttpClientResponse] from which the [HttpClientResponseBody] was + * created. + */ + HttpClientResponse get response; +} + +/** + * The [HttpBody] of a [HttpRequest] will be of type [HttpRequestBody]. It + * provides access to the request, for reading all request header information + * and responding to the client. + */ +abstract class HttpRequestBody extends HttpBody { + /** + * The [HttpRequest] from which the [HttpRequestBody] was created. + * + * Note that the [HttpRequest] is already drained at this point, so the + * `Stream` methods cannot be used. + */ + HttpRequest get request; +} + +/** + * A [HttpBodyFileUpload] object wraps a file upload, presenting a way for + * extracting filename, contentType and the data of the uploaded file. + */ +abstract class HttpBodyFileUpload { + /** + * The filename of the uploaded file. + */ + String get filename; + + /** + * The [ContentType] of the uploaded file. For 'text/\*' and + * 'application/json' the [content] field will a String. + */ + ContentType get contentType; + + /** + * The content of the file. Either a [String] or a [List]. + */ + dynamic get content; +} +NN<EFF=D/)FCGCAFGG@CFBEC@EFE'BECEFDGCF8GCE + HttpMultipartFormDataImpl.parse(multipart, defaultEncoding); +} +YNN<.!-MLM>-31JM9J&QLK&/Cjfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_server-0.9.8/lib/src/virtual_directory.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library http_server.virtual_directory; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:mime/mime.dart'; +import 'package:path/path.dart'; + +// Used for signal a directory redirecting, where a tailing slash is missing. +class _DirectoryRedirect { + const _DirectoryRedirect(); +} + +typedef dynamic _DirCallback(Directory dir, HttpRequest request); +typedef dynamic _ErrorCallback(HttpRequest request); + +/** + * A [VirtualDirectory] can serve files and directory-listing from a root path, + * to [HttpRequest]s. + * + * The [VirtualDirectory] providing secure handling of request uris and + * file-system links, correct mime-types and custom error pages. + */ +class VirtualDirectory { + final String root; + + /** + * Set or get if the [VirtualDirectory] should list the content of + * directories. + */ + bool allowDirectoryListing = false; + + /** + * Set or get if the [VirtualDirectory] should follow links, that point + * to other resources within the [root] directory. + */ + bool followLinks = true; + + /** + * Set or get if the [VirtualDirectory] should jail the root. When the root is + * not jailed, links can be followed to outside the [root] directory. + */ + bool jailRoot = true; + + final List _pathPrefixSegments; + + final RegExp _invalidPathRegExp = new RegExp("[\\\/\x00]"); + + _ErrorCallback _errorCallback; + _DirCallback _dirCallback; + + static List _parsePathPrefix(String pathPrefix) { + if (pathPrefix == null) return []; + return new Uri(path: pathPrefix) + .pathSegments + .where((segment) => segment.isNotEmpty) + .toList(); + } + + /* + * Create a new [VirtualDirectory] for serving static file content of + * the path [root]. + * + * The [root] is not required to exist. If the [root] doesn't exist at time of + * a request, a 404 response is generated. + * + * If [pathPrefix] is set, [pathPrefix] will indicate the expected path prefix + * of incoming requests. When locating the resource on disk, the prefix will + * be trimmed from the requests uri, before locating the actual resource. + * If the requests uri doesn't start with [pathPrefix], a 404 response is + * generated. + */ + VirtualDirectory(this.root, {String pathPrefix}) + : _pathPrefixSegments = _parsePathPrefix(pathPrefix); + + /** + * Serve a [Stream] of [HttpRequest]s, in this [VirtualDirectory]. + */ + StreamSubscription serve(Stream requests) => + requests.listen(serveRequest); + + /** + * Serve a single [HttpRequest], in this [VirtualDirectory]. + */ + Future serveRequest(HttpRequest request) { + var iterator = request.uri.pathSegments.iterator; + for (var segment in _pathPrefixSegments) { + if (!iterator.moveNext() || iterator.current != segment) { + _serveErrorPage(HttpStatus.notFound, request); + return request.response.done; + } + } + return _locateResource('.', iterator..moveNext()).then((entity) { + if (entity is File) { + serveFile(entity, request); + } else if (entity is Directory) { + if (allowDirectoryListing) { + _serveDirectory(entity, request); + } else { + _serveErrorPage(HttpStatus.notFound, request); + } + } else if (entity is _DirectoryRedirect) { + // TODO(ajohnsen): Use HttpRequest.requestedUri once 1.2 is out. + request.response.redirect(Uri.parse('${request.uri}/'), + status: HttpStatus.movedPermanently); + } else { + assert(entity == null); + _serveErrorPage(HttpStatus.notFound, request); + } + return request.response.done; + }); + } + + /** + * Set the [callback] to override the default directory listing. The + * [callback] will be called with the [Directory] to be listed and the + * [HttpRequest]. + */ + set directoryHandler(void callback(Directory dir, HttpRequest request)) { + _dirCallback = callback; + } + + /** + * Set the [callback] to override the error page handler. When [callback] is + * invoked, the `statusCode` property of the response is set. + */ + set errorPageHandler(void callback(HttpRequest request)) { + _errorCallback = callback; + } + + Future _locateResource(String path, Iterator segments) { + // Don't allow navigating up paths. + if (segments.current == "..") return new Future.value(null); + path = normalize(path); + // If we jail to root, the relative path can never go up. + if (jailRoot && split(path).first == "..") return new Future.value(null); + String fullPath() => join(root, path); + return FileSystemEntity.type(fullPath(), followLinks: false).then((type) { + switch (type) { + case FileSystemEntityType.file: + if (segments.current == null) { + return new File(fullPath()); + } + break; + + case FileSystemEntityType.directory: + String dirFullPath() => '${fullPath()}$separator'; + var current = segments.current; + if (current == null) { + if (path == '.') return new Directory(dirFullPath()); + return const _DirectoryRedirect(); + } + var hasNext = segments.moveNext(); + if (!hasNext && current == "") { + return new Directory(dirFullPath()); + } else { + if (_invalidPathRegExp.hasMatch(current)) break; + return _locateResource(join(path, current), segments); + } + break; + + case FileSystemEntityType.link: + if (followLinks) { + return new Link(fullPath()).target().then((target) { + var targetPath = normalize(target); + if (isAbsolute(targetPath)) { + // If we jail to root, the path can never be absolute. + if (jailRoot) return null; + return _locateResource(targetPath, segments); + } else { + targetPath = join(dirname(path), targetPath); + return _locateResource(targetPath, segments); + } + }); + } + break; + } + // Return `null` on fall-through, to indicate NOT_FOUND. + return null; + }); + } + + /** + * Serve the content of [file] to [request]. + * + * This is usefull when e.g. overriding [directoryHandler] to redirect to + * some index file. + * + * In the request contains the [HttpStatus.ifModifiedSince] header, + * [serveFile] will send a [HttpStatus.notModified] response if the file + * was not changed. + * + * Note that if it was unabled to read from [file], the [request]s response + * is closed with error-code [HttpStatus.notFound]. + */ + void serveFile(File file, HttpRequest request) { + var response = request.response; + // TODO(ajohnsen): Set up Zone support for these errors. + file.lastModified().then((lastModified) { + if (request.headers.ifModifiedSince != null && + !lastModified.isAfter(request.headers.ifModifiedSince)) { + response.statusCode = HttpStatus.notModified; + response.close(); + return null; + } + + response.headers.set(HttpHeaders.lastModifiedHeader, lastModified); + response.headers.set(HttpHeaders.acceptRangesHeader, "bytes"); + + return file.length().then((length) { + var range = request.headers.value(HttpHeaders.rangeHeader); + if (range != null) { + // We only support one range, where the standard support several. + var matches = new RegExp(r"^bytes=(\d*)\-(\d*)$").firstMatch(range); + // If the range header have the right format, handle it. + if (matches != null && + (matches[1].isNotEmpty || matches[2].isNotEmpty)) { + // Serve sub-range. + int start; // First byte position - inclusive. + int end; // Last byte position - inclusive. + if (matches[1].isEmpty) { + start = length - int.parse(matches[2]); + if (start < 0) start = 0; + end = length - 1; + } else { + start = int.parse(matches[1]); + end = matches[2].isEmpty ? length - 1 : int.parse(matches[2]); + } + // If the range is syntactically invalid the Range header + // MUST be ignored (RFC 2616 section 14.35.1). + if (start <= end) { + if (end >= length) { + end = length - 1; + } + + if (start >= length) { + response + ..statusCode = HttpStatus.requestedRangeNotSatisfiable + ..close(); + return; + } + + // Override Content-Length with the actual bytes sent. + response.headers + .set(HttpHeaders.contentLengthHeader, end - start + 1); + + // Set 'Partial Content' status code. + response + ..statusCode = HttpStatus.partialContent + ..headers.set(HttpHeaders.contentRangeHeader, + 'bytes $start-$end/$length'); + + // Pipe the 'range' of the file. + if (request.method == 'HEAD') { + response.close(); + } else { + file + .openRead(start, end + 1) + .pipe(new _VirtualDirectoryFileStream(response, file.path)) + .catchError((_) { + // TODO(kevmoo): log errors + }); + } + return; + } + } + } + + response.headers.set(HttpHeaders.contentLengthHeader, length); + if (request.method == 'HEAD') { + response.close(); + } else { + file + .openRead() + .pipe(new _VirtualDirectoryFileStream(response, file.path)) + .catchError((_) { + // TODO(kevmoo): log errors + }); + } + }); + }).catchError((_) { + response.statusCode = HttpStatus.notFound; + response.close(); + }); + } + + void _serveDirectory(Directory dir, HttpRequest request) { + if (_dirCallback != null) { + _dirCallback(dir, request); + return; + } + var response = request.response; + dir.stat().then((stats) { + if (request.headers.ifModifiedSince != null && + !stats.modified.isAfter(request.headers.ifModifiedSince)) { + response.statusCode = HttpStatus.notModified; + response.close(); + return; + } + + response.headers.contentType = + new ContentType('text', 'html', parameters: {'charset': 'utf-8'}); + response.headers.set(HttpHeaders.lastModifiedHeader, stats.modified); + var path = Uri.decodeComponent(request.uri.path); + var encodedPath = const HtmlEscape().convert(path); + var header = + ''' + + +Index of $encodedPath + + +

Index of $encodedPath

+ + + + + + +'''; + var server = response.headers.value(HttpHeaders.serverHeader); + server ??= ""; + var footer = '''
NameLast modifiedSize
+$server + + +'''; + + response.write(header); + + void add(String name, String modified, var size, bool folder) { + size ??= "-"; + modified ??= ""; + var encodedSize = const HtmlEscape().convert(size.toString()); + var encodedModified = const HtmlEscape().convert(modified); + var encodedLink = const HtmlEscape(HtmlEscapeMode.attribute) + .convert(Uri.encodeComponent(name)); + if (folder) { + encodedLink += '/'; + name += '/'; + } + var encodedName = const HtmlEscape().convert(name); + + var entry = ''' + $encodedName + $encodedModified + $encodedSize + '''; + response.write(entry); + } + + if (path != '/') { + add('..', null, null, true); + } + + dir.list(followLinks: true).listen((entity) { + var name = basename(entity.path); + var stat = entity.statSync(); + if (entity is File) { + add(name, stat.modified.toString(), stat.size, false); + } else if (entity is Directory) { + add(name, stat.modified.toString(), null, true); + } + }, onError: (e) { + // TODO(kevmoo): log error + }, onDone: () { + response.write(footer); + response.close(); + }); + }, onError: (e) { + // TODO(kevmoo): log error + response.close(); + }); + } + + void _serveErrorPage(int error, HttpRequest request) { + var response = request.response; + response.statusCode = error; + if (_errorCallback != null) { + _errorCallback(request); + return; + } + response.headers.contentType = + new ContentType('text', 'html', parameters: {'charset': 'utf-8'}); + // Default error page. + var path = Uri.decodeComponent(request.uri.path); + var encodedPath = const HtmlEscape().convert(path); + var encodedReason = const HtmlEscape().convert(response.reasonPhrase); + var encodedError = const HtmlEscape().convert(error.toString()); + + var server = response.headers.value(HttpHeaders.serverHeader); + server ??= ""; + var page = ''' + + +$encodedReason: $encodedPath + + +

Error $encodedError at \'$encodedPath\': $encodedReason

+$server + +'''; + response.write(page); + response.close(); + } +} + +class _VirtualDirectoryFileStream extends StreamConsumer> { + final HttpResponse response; + final String path; + List buffer = []; + + _VirtualDirectoryFileStream(this.response, this.path); + + Future addStream(Stream> stream) { + stream.listen((data) { + if (buffer == null) { + response.add(data); + return; + } + if (buffer.isEmpty) { + if (data.length >= defaultMagicNumbersMaxLength) { + setMimeType(data); + response.add(data); + buffer = null; + } else { + buffer.addAll(data); + } + } else { + buffer.addAll(data); + if (buffer.length >= defaultMagicNumbersMaxLength) { + setMimeType(buffer); + response.add(buffer); + buffer = null; + } + } + }, onDone: () { + if (buffer != null) { + if (buffer.isEmpty) { + setMimeType(null); + } else { + setMimeType(buffer); + response.add(buffer); + } + } + response.close(); + }, onError: response.addError); + return response.done; + } + + Future close() => new Future.value(); + + void setMimeType(List bytes) { + var mimeType = lookupMimeType(path, headerBytes: bytes); + if (mimeType != null) { + response.headers.contentType = ContentType.parse(mimeType); + } + } +} +NN<'!!NB5PHAE&J5QH*>!N+O(*) -=*!B/ -+1=C (A2,G+>>> ?/LFKN63%=.5D6JE+DLOC!B ;8&6( -MF; #"%IEJ49>2/.".P&. +G(J ( + +1= "%5F6%ML8:L:,%EFGDE1 +<54 %4*&A*; +#  +!9%!"#K68KECQ:,,A F9/; +=  + +$(&=Befile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_server-0.9.8/lib/src/virtual_host.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library http_server.virtual_host; + +import 'dart:async'; +import 'dart:io'; + +/** + * The [VirtualHost] class is a utility class for handling multiple hosts on + * multiple sources, by using a named-based approach. + */ +abstract class VirtualHost { + /** + * Get the [Stream] of [HttpRequest]s, not matching any hosts. If unused, the + * default implementation will result in a [HttpHeaders.FORBIDDEN] response. + */ + Stream get unhandled; + + /** + * Construct a new [VirtualHost]. + * + * The optional [source] is a shortcut for calling [addSource]. + * + * Example of usage: + * + * HttpServer.bind(..., 80).then((server) { + * var virtualHost = new VirtualHost(server); + * virtualServer.addHost('static.myserver.com') + * .listen(...); + * virtualServer.addHost('cache.myserver.com') + * .listen(...); + * }) + */ + factory VirtualHost([Stream source]) => new _VirtualHost(source); + + /** + * Provide another source of [HttpRequest]s in the form of a [Stream]. + */ + void addSource(Stream source); + + /** + * Add a host to the [VirtualHost] instance. The host can be either a specific + * domain (`my.domain.name`) or a wildcard-based domain name + * (`*.domain.name`). The former will only match the specific domain name + * while the latter will match any series of sub-domains. + * + * If both `my.domain.name` and `*.domain.name` is specified, the most + * qualified will take precedence, `my.domain.name` in this case. + */ + Stream addHost(String host); +} + +class _VirtualHostDomain { + StreamController any; + StreamController exact; + Map subDomains = {}; +} + +class _VirtualHost implements VirtualHost { + final _VirtualHostDomain _topDomain = new _VirtualHostDomain(); + StreamController _unhandledController; + + Stream get unhandled { + _unhandledController ??= new StreamController(); + + return _unhandledController.stream; + } + + _VirtualHost([Stream source]) { + if (source != null) addSource(source); + } + + void addSource(Stream source) { + source.listen((request) { + var host = request.headers.host; + if (host == null) { + _unhandled(request); + return; + } + var domains = host.split('.'); + var current = _topDomain; + StreamController any; + for (var i = domains.length - 1; i >= 0; i--) { + if (current.any != null) any = current.any; + if (i == 0) { + var last = current.subDomains[domains[i]]; + if (last != null && last.exact != null) { + last.exact.add(request); + return; + } + } else { + if (!current.subDomains.containsKey(domains[i])) { + break; + } + current = current.subDomains[domains[i]]; + } + } + if (any != null) { + any.add(request); + return; + } + _unhandled(request); + }); + } + + Stream addHost(String host) { + if (host.lastIndexOf('*') > 0) { + throw new ArgumentError( + 'Wildcards are only allowed in the beginning of a host'); + } + var controller = new StreamController(); + var domains = host.split('.'); + var current = _topDomain; + for (var i = domains.length - 1; i >= 0; i--) { + if (domains[i] == '*') { + if (current.any != null) { + throw new ArgumentError('Host is already provided'); + } + current.any = controller; + } else { + if (!current.subDomains.containsKey(domains[i])) { + current.subDomains[domains[i]] = new _VirtualHostDomain(); + } + if (i > 0) { + current = current.subDomains[domains[i]]; + } else { + if (current.subDomains[domains[i]].exact != null) { + throw new ArgumentError('Host is already provided'); + } + current.subDomains[domains[i]].exact = controller; + } + } + } + return controller.stream; + } + + void _unhandled(HttpRequest request) { + if (_unhandledController != null) { + _unhandledController.add(request); + return; + } + request.response.statusCode = HttpStatus.forbidden; + request.response.close(); + } +} +NN<"M6PO%$B0465 +QI.Q?L<ID,%'3,B6&B(/+/'% 6454% = 4 +-%D:#4#? +";E +4>A = +)()8bfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/body_parser-1.1.1/lib/src/get_value.dartimport 'package:dart2_constant/convert.dart'; + +getValue(String value) { + try { + num numValue = num.parse(value); + if (!numValue.isNaN) + return numValue; + else + return value; + } on FormatException { + if (value.startsWith('[') && value.endsWith(']')) + return json.decode(value); + else if (value.startsWith('{') && value.endsWith('}')) + return json.decode(value); + else if (value.trim().toLowerCase() == 'null') + return null; + else + return value; + } +} +.% 6!;!3 cfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/lazy_chain.dart/// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'chain.dart'; +import 'frame.dart'; +import 'lazy_trace.dart'; +import 'trace.dart'; + +/// A thunk for lazily constructing a [Chain]. +typedef Chain ChainThunk(); + +/// A wrapper around a [ChainThunk]. This works around issue 9579 by avoiding +/// the conversion of native [StackTrace]s to strings until it's absolutely +/// necessary. +class LazyChain implements Chain { + final ChainThunk _thunk; + Chain _inner; + + LazyChain(this._thunk); + + Chain get _chain { + if (_inner == null) _inner = _thunk(); + return _inner; + } + + List get traces => _chain.traces; + Chain get terse => _chain.terse; + Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) => + new LazyChain(() => _chain.foldFrames(predicate, terse: terse)); + Trace toTrace() => new LazyTrace(() => _chain.toTrace()); + String toString() => _chain.toString(); +} +#NN</NL#++#HG<*qfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/stack_zone_specification.dartd// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'chain.dart'; +import 'lazy_chain.dart'; +import 'lazy_trace.dart'; +import 'trace.dart'; +import 'utils.dart'; + +/// A function that handles errors in the zone wrapped by [Chain.capture]. +typedef void _ChainHandler(error, Chain chain); + +/// A class encapsulating the zone specification for a [Chain.capture] zone. +/// +/// Until they're materialized and exposed to the user, stack chains are tracked +/// as linked lists of [Trace]s using the [_Node] class. These nodes are stored +/// in three distinct ways: +/// +/// * When a callback is registered, a node is created and stored as a captured +/// local variable until the callback is run. +/// +/// * When a callback is run, its captured node is set as the [_currentNode] so +/// it can be available to [Chain.current] and to be linked into additional +/// chains when more callbacks are scheduled. +/// +/// * When a callback throws an error or a Future or Stream emits an error, the +/// current node is associated with that error's stack trace using the +/// [_chains] expando. +/// +/// Since [ZoneSpecification] can't be extended or even implemented, in order to +/// get a real [ZoneSpecification] instance it's necessary to call [toSpec]. +class StackZoneSpecification { + /// An opaque object used as a zone value to disable chain tracking in a given + /// zone. + /// + /// If `Zone.current[disableKey]` is `true`, no stack chains will be tracked. + static final disableKey = new Object(); + + /// Whether chain-tracking is disabled in the current zone. + bool get _disabled => Zone.current[disableKey] == true; + + /// The expando that associates stack chains with [StackTrace]s. + /// + /// The chains are associated with stack traces rather than errors themselves + /// because it's a common practice to throw strings as errors, which can't be + /// used with expandos. + /// + /// The chain associated with a given stack trace doesn't contain a node for + /// that stack trace. + final _chains = new Expando<_Node>("stack chains"); + + /// The error handler for the zone. + /// + /// If this is null, that indicates that any unhandled errors should be passed + /// to the parent zone. + final _ChainHandler _onError; + + /// The most recent node of the current stack chain. + _Node _currentNode; + + /// Whether this is an error zone. + final bool _errorZone; + + StackZoneSpecification(this._onError, {bool errorZone: true}) + : _errorZone = errorZone; + + /// Converts [this] to a real [ZoneSpecification]. + ZoneSpecification toSpec() { + return new ZoneSpecification( + handleUncaughtError: _errorZone ? _handleUncaughtError : null, + registerCallback: _registerCallback, + registerUnaryCallback: _registerUnaryCallback, + registerBinaryCallback: _registerBinaryCallback, + errorCallback: _errorCallback); + } + + /// Returns the current stack chain. + /// + /// By default, the first frame of the first trace will be the line where + /// [currentChain] is called. If [level] is passed, the first trace will start + /// that many frames up instead. + Chain currentChain([int level = 0]) => _createNode(level + 1).toChain(); + + /// Returns the stack chain associated with [trace], if one exists. + /// + /// The first stack trace in the returned chain will always be [trace] + /// (converted to a [Trace] if necessary). If there is no chain associated + /// with [trace], this just returns a single-trace chain containing [trace]. + Chain chainFor(StackTrace trace) { + if (trace is Chain) return trace; + trace ??= StackTrace.current; + + var previous = _chains[trace] ?? _currentNode; + if (previous == null) { + // If there's no [_currentNode], we're running synchronously beneath + // [Chain.capture] and we should fall back to the VM's stack chaining. We + // can't use [Chain.from] here because it'll just call [chainFor] again. + if (trace is Trace) return new Chain([trace]); + return new LazyChain(() => new Chain.parse(trace.toString())); + } else { + if (trace is! Trace) { + var original = trace; + trace = new LazyTrace(() => new Trace.parse(_trimVMChain(original))); + } + + return new _Node(trace, previous).toChain(); + } + } + + /// Tracks the current stack chain so it can be set to [_currentChain] when + /// [f] is run. + ZoneCallback _registerCallback( + Zone self, ZoneDelegate parent, Zone zone, R f()) { + if (f == null || _disabled) return parent.registerCallback(zone, f); + var node = _createNode(1); + return parent.registerCallback(zone, () => _run(f, node)); + } + + /// Tracks the current stack chain so it can be set to [_currentChain] when + /// [f] is run. + ZoneUnaryCallback _registerUnaryCallback( + Zone self, ZoneDelegate parent, Zone zone, R f(T arg)) { + if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); + var node = _createNode(1); + return parent.registerUnaryCallback(zone, (arg) { + return _run(() => f(arg), node); + }); + } + + /// Tracks the current stack chain so it can be set to [_currentChain] when + /// [f] is run. + ZoneBinaryCallback _registerBinaryCallback( + Zone self, ZoneDelegate parent, Zone zone, Function f) { + if (f == null || _disabled) return parent.registerBinaryCallback(zone, f); + + var node = _createNode(1); + return parent.registerBinaryCallback(zone, (arg1, arg2) { + return _run(() => f(arg1, arg2), node); + }); + } + + /// Looks up the chain associated with [stackTrace] and passes it either to + /// [_onError] or [parent]'s error handler. + void _handleUncaughtError( + Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { + if (_disabled) { + parent.handleUncaughtError(zone, error, stackTrace); + return; + } + + var stackChain = chainFor(stackTrace); + if (_onError == null) { + parent.handleUncaughtError(zone, error, stackChain); + return; + } + + // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just + // allow [runBinary] to throw instead once issue 18134 is fixed. + try { + self.parent.runBinary(_onError, error, stackChain); + } catch (newError, newStackTrace) { + if (identical(newError, error)) { + parent.handleUncaughtError(zone, error, stackChain); + } else { + parent.handleUncaughtError(zone, newError, newStackTrace); + } + } + } + + /// Attaches the current stack chain to [stackTrace], replacing it if + /// necessary. + AsyncError _errorCallback(Zone self, ZoneDelegate parent, Zone zone, + Object error, StackTrace stackTrace) { + if (_disabled) return parent.errorCallback(zone, error, stackTrace); + + // Go up two levels to get through [_CustomZone.errorCallback]. + if (stackTrace == null) { + stackTrace = _createNode(2).toChain(); + } else { + if (_chains[stackTrace] == null) _chains[stackTrace] = _createNode(2); + } + + var asyncError = parent.errorCallback(zone, error, stackTrace); + return asyncError == null ? new AsyncError(error, stackTrace) : asyncError; + } + + /// Creates a [_Node] with the current stack trace and linked to + /// [_currentNode]. + /// + /// By default, the first frame of the first trace will be the line where + /// [_createNode] is called. If [level] is passed, the first trace will start + /// that many frames up instead. + _Node _createNode([int level = 0]) => + new _Node(_currentTrace(level + 1), _currentNode); + + // TODO(nweiz): use a more robust way of detecting and tracking errors when + // issue 15105 is fixed. + /// Runs [f] with [_currentNode] set to [node]. + /// + /// If [f] throws an error, this associates [node] with that error's stack + /// trace. + T _run(T f(), _Node node) { + var previousNode = _currentNode; + _currentNode = node; + try { + return f(); + } catch (e, stackTrace) { + // We can see the same stack trace multiple times if it's rethrown through + // guarded callbacks. The innermost chain will have the most + // information so it should take precedence. + _chains[stackTrace] ??= node; + rethrow; + } finally { + _currentNode = previousNode; + } + } + + /// Like [new Trace.current], but if the current stack trace has VM chaining + /// enabled, this only returns the innermost sub-trace. + Trace _currentTrace([int level]) { + level ??= 0; + var stackTrace = StackTrace.current; + return new LazyTrace(() { + var text = _trimVMChain(stackTrace); + var trace = new Trace.parse(text); + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), + original: text); + }); + } + + /// Removes the VM's stack chains from the native [trace], since we're + /// generating our own and we don't want duplicate frames. + String _trimVMChain(StackTrace trace) { + var text = trace.toString(); + var index = text.indexOf(vmChainGap); + return index == -1 ? text : text.substring(0, index); + } +} + +/// A linked list node representing a single entry in a stack chain. +class _Node { + /// The stack trace for this link of the chain. + final Trace trace; + + /// The previous node in the chain. + final _Node previous; + + _Node(StackTrace trace, [this.previous]) : trace = new Trace.from(trace); + + /// Converts this to a [Chain]. + Chain toChain() { + var nodes = []; + var node = this; + while (node != null) { + nodes.add(node.trace); + node = node.previous; + } + return new Chain(nodes); + } +} + NN<K0MQPP0PN0PIQMQ P*>:CPPO6&Q 7%@ 5"G-79('LQ#KFIMO%&"3KPO5E N3N(:I?N8?N6'ND?O>.N.Q;+;OE +:((=CHG-ID- MDPCLP#(9N2M !% +QD3$#O:%)+)L=BI=*!*:E2&L"^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/utils.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// The line used in the string representation of stack chains to represent +/// the gap between traces. +const chainGap = '===== asynchronous gap ===========================\n'; + +/// The line used in the string representation of VM stack chains to represent +/// the gap between traces. +const vmChainGap = '\n'; + +// TODO(nweiz): When cross-platform imports work, use them to set this. +/// Whether we're running in a JS context. +final bool inJS = 0.0 is int; +NN<LIO2H+cfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/lazy_trace.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'frame.dart'; +import 'trace.dart'; + +/// A thunk for lazily constructing a [Trace]. +typedef Trace TraceThunk(); + +/// A wrapper around a [TraceThunk]. This works around issue 9579 by avoiding +/// the conversion of native [StackTrace]s to strings until it's absolutely +/// necessary. +class LazyTrace implements Trace { + final TraceThunk _thunk; + Trace _inner; + + LazyTrace(this._thunk); + + Trace get _trace { + if (_inner == null) _inner = _thunk(); + return _inner; + } + + List get frames => _trace.frames; + StackTrace get original => _trace.original; + StackTrace get vmTrace => _trace.vmTrace; + Trace get terse => new LazyTrace(() => _trace.terse); + Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) => + new LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); + String toString() => _trace.toString(); + + // Work around issue 14075. + set frames(_) => throw new UnimplementedError(); +} +%NN</NL#++.,8HG*3afile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/vm_trace.dartU// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'frame.dart'; + +/// An implementation of [StackTrace] that emulates the behavior of the VM's +/// implementation. +/// +/// In particular, when [toString] is called, this returns a string in the VM's +/// stack trace format. +class VMTrace implements StackTrace { + /// The stack frames that comprise this stack trace. + final List frames; + + VMTrace(this.frames); + + String toString() { + var i = 1; + return frames.map((frame) { + var number = "#${i++}".padRight(8); + var member = frame.member + .replaceAllMapped(new RegExp(r"[^.]+\."), + (match) => "${match[1]}.<${match[1]}_async_body>") + .replaceAll("", ""); + var line = frame.line == null ? 0 : frame.line; + var column = frame.column == null ? 0 : frame.column; + return "$number$member (${frame.uri}:$line:$column)\n"; + }).join(); + } +} +!NN<MP&7 * ;A66<>dfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/algorithms.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:math" as math; + +import "utils.dart"; + +/// Returns a position of the [value] in [sortedList], if it is there. +/// +/// If the list isn't sorted according to the [compare] function, the result +/// is unpredictable. +/// +/// If [compare] is omitted, this defaults to calling [Comparable.compareTo] on +/// the objects. If any object is not [Comparable], this throws a [CastError]. +/// +/// Returns -1 if [value] is not in the list by default. +int binarySearch(List sortedList, T value, {int compare(T a, T b)}) { + compare ??= defaultCompare(); + int min = 0; + int max = sortedList.length; + while (min < max) { + int mid = min + ((max - min) >> 1); + var element = sortedList[mid]; + int comp = compare(element, value); + if (comp == 0) return mid; + if (comp < 0) { + min = mid + 1; + } else { + max = mid; + } + } + return -1; +} + +/// Returns the first position in [sortedList] that does not compare less than +/// [value]. +/// +/// If the list isn't sorted according to the [compare] function, the result +/// is unpredictable. +/// +/// If [compare] is omitted, this defaults to calling [Comparable.compareTo] on +/// the objects. If any object is not [Comparable], this throws a [CastError]. +/// +/// Returns [sortedList.length] if all the items in [sortedList] compare less +/// than [value]. +int lowerBound(List sortedList, T value, {int compare(T a, T b)}) { + compare ??= defaultCompare(); + int min = 0; + int max = sortedList.length; + while (min < max) { + int mid = min + ((max - min) >> 1); + var element = sortedList[mid]; + int comp = compare(element, value); + if (comp < 0) { + min = mid + 1; + } else { + max = mid; + } + } + return min; +} + +/// Shuffles a list randomly. +/// +/// A sub-range of a list can be shuffled by providing [start] and [end]. +void shuffle(List list, [int start = 0, int end]) { + var random = new math.Random(); + if (end == null) end = list.length; + int length = end - start; + while (length > 1) { + int pos = random.nextInt(length); + length--; + var tmp1 = list[start + pos]; + list[start + pos] = list[start + length]; + list[start + length] = tmp1; + } +} + +/// Reverses a list, or a part of a list, in-place. +void reverse(List list, [int start = 0, int end]) { + if (end == null) end = list.length; + _reverse(list, start, end); +} + +/// Internal helper function that assumes valid arguments. +void _reverse(List list, int start, int end) { + for (int i = start, j = end - 1; i < j; i++, j--) { + var tmp = list[i]; + list[i] = list[j]; + list[j] = tmp; + } +} + +/// Sort a list between [start] (inclusive) and [end] (exclusive) using +/// insertion sort. +/// +/// If [compare] is omitted, this defaults to calling [Comparable.compareTo] on +/// the objects. If any object is not [Comparable], this throws a [CastError]. +/// +/// Insertion sort is a simple sorting algorithm. For `n` elements it does on +/// the order of `n * log(n)` comparisons but up to `n` squared moves. The +/// sorting is performed in-place, without using extra memory. +/// +/// For short lists the many moves have less impact than the simple algorithm, +/// and it is often the favored sorting algorithm for short lists. +/// +/// This insertion sort is stable: Equal elements end up in the same order +/// as they started in. +void insertionSort(List list, + {int compare(T a, T b), int start: 0, int end}) { + // If the same method could have both positional and named optional + // parameters, this should be (list, [start, end], {compare}). + compare ??= defaultCompare(); + end ??= list.length; + + for (int pos = start + 1; pos < end; pos++) { + int min = start; + int max = pos; + var element = list[pos]; + while (min < max) { + int mid = min + ((max - min) >> 1); + int comparison = compare(element, list[mid]); + if (comparison < 0) { + max = mid; + } else { + min = mid + 1; + } + } + list.setRange(min + 1, pos + 1, list, min); + list[min] = element; + } +} + +/// Limit below which merge sort defaults to insertion sort. +const int _MERGE_SORT_LIMIT = 32; + +/// Sorts a list between [start] (inclusive) and [end] (exclusive) using the +/// merge sort algorithm. +/// +/// If [compare] is omitted, this defaults to calling [Comparable.compareTo] on +/// the objects. If any object is not [Comparable], this throws a [CastError]. +/// +/// Merge-sorting works by splitting the job into two parts, sorting each +/// recursively, and then merging the two sorted parts. +/// +/// This takes on the order of `n * log(n)` comparisons and moves to sort +/// `n` elements, but requires extra space of about the same size as the list +/// being sorted. +/// +/// This merge sort is stable: Equal elements end up in the same order +/// as they started in. +void mergeSort(List list, + {int start: 0, int end, int compare(T a, T b)}) { + end ??= list.length; + compare ??= defaultCompare(); + + int length = end - start; + if (length < 2) return; + if (length < _MERGE_SORT_LIMIT) { + insertionSort(list, compare: compare, start: start, end: end); + return; + } + // Special case the first split instead of directly calling + // _mergeSort, because the _mergeSort requires its target to + // be different from its source, and it requires extra space + // of the same size as the list to sort. + // This split allows us to have only half as much extra space, + // and it ends up in the original place. + int middle = start + ((end - start) >> 1); + int firstLength = middle - start; + int secondLength = end - middle; + // secondLength is always the same as firstLength, or one greater. + var scratchSpace = new List(secondLength); + _mergeSort(list, compare, middle, end, scratchSpace, 0); + int firstTarget = end - firstLength; + _mergeSort(list, compare, start, middle, list, firstTarget); + _merge(compare, list, firstTarget, end, scratchSpace, 0, secondLength, list, + start); +} + +/// Performs an insertion sort into a potentially different list than the +/// one containing the original values. +/// +/// It will work in-place as well. +void _movingInsertionSort(List list, int compare(T a, T b), int start, + int end, List target, int targetOffset) { + int length = end - start; + if (length == 0) return; + target[targetOffset] = list[start]; + for (int i = 1; i < length; i++) { + var element = list[start + i]; + int min = targetOffset; + int max = targetOffset + i; + while (min < max) { + int mid = min + ((max - min) >> 1); + if (compare(element, target[mid]) < 0) { + max = mid; + } else { + min = mid + 1; + } + } + target.setRange(min + 1, targetOffset + i + 1, target, min); + target[min] = element; + } +} + +/// Sorts [list] from [start] to [end] into [target] at [targetOffset]. +/// +/// The `target` list must be able to contain the range from `start` to `end` +/// after `targetOffset`. +/// +/// Allows target to be the same list as [list], as long as it's not +/// overlapping the `start..end` range. +void _mergeSort(List list, int compare(T a, T b), int start, int end, + List target, int targetOffset) { + int length = end - start; + if (length < _MERGE_SORT_LIMIT) { + _movingInsertionSort(list, compare, start, end, target, targetOffset); + return; + } + int middle = start + (length >> 1); + int firstLength = middle - start; + int secondLength = end - middle; + // Here secondLength >= firstLength (differs by at most one). + int targetMiddle = targetOffset + firstLength; + // Sort the second half into the end of the target area. + _mergeSort(list, compare, middle, end, target, targetMiddle); + // Sort the first half into the end of the source area. + _mergeSort(list, compare, start, middle, list, middle); + // Merge the two parts into the target area. + _merge(compare, list, middle, middle + firstLength, target, targetMiddle, + targetMiddle + secondLength, target, targetOffset); +} + +/// Merges two lists into a target list. +/// +/// One of the input lists may be positioned at the end of the target +/// list. +/// +/// For equal object, elements from [firstList] are always preferred. +/// This allows the merge to be stable if the first list contains elements +/// that started out earlier than the ones in [secondList] +void _merge( + int compare(T a, T b), + List firstList, + int firstStart, + int firstEnd, + List secondList, + int secondStart, + int secondEnd, + List target, + int targetOffset) { + // No empty lists reaches here. + assert(firstStart < firstEnd); + assert(secondStart < secondEnd); + int cursor1 = firstStart; + int cursor2 = secondStart; + var firstElement = firstList[cursor1++]; + var secondElement = secondList[cursor2++]; + while (true) { + if (compare(firstElement, secondElement) <= 0) { + target[targetOffset++] = firstElement; + if (cursor1 == firstEnd) break; // Flushing second list after loop. + firstElement = firstList[cursor1++]; + } else { + target[targetOffset++] = secondElement; + if (cursor2 != secondEnd) { + secondElement = secondList[cursor2++]; + continue; + } + // Second list empties first. Flushing first list here. + target[targetOffset++] = firstElement; + target.setRange(targetOffset, targetOffset + (firstEnd - cursor1), + firstList, cursor1); + return; + } + } + // First list empties first. Reached by break above. + target[targetOffset++] = secondElement; + target.setRange( + targetOffset, targetOffset + (secondEnd - cursor2), secondList, cursor2); +} +NN<GMPO9L#(#(  O MPONJ#(#( J4"&&".!44&;/6HPONK?OCK$6FA#0*40="MPOJ8JNG 6#$C >??+A+-$#E0;'?OJ(#M1&%# */AHNE(L($K &$#@1;@::/L:)F +FK;"!#+-5-J+ ."/>-I7*Pkfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/canonicalized_map.dartY// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'utils.dart'; + +typedef C _Canonicalize(K key); + +typedef bool _IsValidKey(Object key); + +/// A map whose keys are converted to canonical values of type `C`. +/// +/// This is useful for using case-insensitive String keys, for example. It's +/// more efficient than a [LinkedHashMap] with a custom equality operator +/// because it only canonicalizes each key once, rather than doing so for each +/// comparison. +/// +/// By default, `null` is allowed as a key. It can be forbidden via the +/// `isValidKey` parameter. +class CanonicalizedMap implements Map { + final _Canonicalize _canonicalize; + + final _IsValidKey _isValidKeyFn; + + final _base = new Map>(); + + /// Creates an empty canonicalized map. + /// + /// The [canonicalize] function should return the canonical value for the + /// given key. Keys with the same canonical value are considered equivalent. + /// + /// The [isValidKey] function is called before calling [canonicalize] for + /// methods that take arbitrary objects. It can be used to filter out keys + /// that can't be canonicalized. + CanonicalizedMap(C canonicalize(K key), {bool isValidKey(Object key)}) + : _canonicalize = canonicalize, + _isValidKeyFn = isValidKey; + + /// Creates a canonicalized map that is initialized with the key/value pairs + /// of [other]. + /// + /// The [canonicalize] function should return the canonical value for the + /// given key. Keys with the same canonical value are considered equivalent. + /// + /// The [isValidKey] function is called before calling [canonicalize] for + /// methods that take arbitrary objects. It can be used to filter out keys + /// that can't be canonicalized. + CanonicalizedMap.from(Map other, C canonicalize(K key), + {bool isValidKey(Object key)}) + : _canonicalize = canonicalize, + _isValidKeyFn = isValidKey { + addAll(other); + } + + V operator [](Object key) { + if (!_isValidKey(key)) return null; + var pair = _base[_canonicalize(key as K)]; + return pair == null ? null : pair.last; + } + + void operator []=(K key, V value) { + if (!_isValidKey(key)) return; + _base[_canonicalize(key)] = new Pair(key, value); + } + + void addAll(Map other) { + other.forEach((key, value) => this[key] = value); + } + + void addEntries(Iterable> entries) => + _base.addEntries(entries.map( + (e) => new MapEntry(_canonicalize(e.key), new Pair(e.key, e.value)))); + + Map cast() => _base.cast(); + + void clear() { + _base.clear(); + } + + bool containsKey(Object key) { + if (!_isValidKey(key)) return false; + return _base.containsKey(_canonicalize(key as K)); + } + + bool containsValue(Object value) => + _base.values.any((pair) => pair.last == value); + + Iterable> get entries => + _base.entries.map((e) => new MapEntry(e.value.first, e.value.last)); + + void forEach(void f(K key, V value)) { + _base.forEach((key, pair) => f(pair.first, pair.last)); + } + + bool get isEmpty => _base.isEmpty; + + bool get isNotEmpty => _base.isNotEmpty; + + Iterable get keys => _base.values.map((pair) => pair.first); + + int get length => _base.length; + + Map map(MapEntry transform(K key, V value)) => + _base.map((_, pair) => transform(pair.first, pair.last)); + + V putIfAbsent(K key, V ifAbsent()) { + return _base + .putIfAbsent(_canonicalize(key), () => new Pair(key, ifAbsent())) + .last; + } + + V remove(Object key) { + if (!_isValidKey(key)) return null; + var pair = _base.remove(_canonicalize(key as K)); + return pair == null ? null : pair.last; + } + + void removeWhere(bool test(K key, V value)) => + _base.removeWhere((_, pair) => test(pair.first, pair.last)); + + @deprecated + Map retype() => cast(); + + V update(K key, V update(V value), {V ifAbsent()}) => _base + .update(_canonicalize(key), (pair) => new Pair(key, update(pair.last)), + ifAbsent: ifAbsent == null ? null : () => new Pair(key, ifAbsent())) + .last; + + void updateAll(V update(K key, V value)) => _base.updateAll( + (_, pair) => new Pair(pair.first, update(pair.first, pair.last))); + + Iterable get values => _base.values.map((pair) => pair.last); + + String toString() { + // Detect toString() cycles. + if (_isToStringVisiting(this)) { + return '{...}'; + } + + var result = new StringBuffer(); + try { + _toStringVisiting.add(this); + result.write('{'); + bool first = true; + forEach((k, v) { + if (!first) { + result.write(', '); + } + first = false; + result.write('$k: $v'); + }); + result.write('}'); + } finally { + assert(identical(_toStringVisiting.last, this)); + _toStringVisiting.removeLast(); + } + + return result.toString(); + } + + bool _isValidKey(Object key) => + (key == null || key is K) && + (_isValidKeyFn == null || _isValidKeyFn(key)); +} + +/// A collection used to identify cyclic maps during toString() calls. +final List _toStringVisiting = []; + +/// Check if we are currently visiting `o` in a toString() call. +bool _isToStringVisiting(o) => _toStringVisiting.any((e) => identical(o, e)); +NN<&&DMJOH7+#**LOLM#I&$OLOLM#@%&%(/,!67$Q6!)7&6*K)<%+B"I@'J(6,1C2>NO ?IC!%% +# + +7&"#5G#AN}file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/combined_wrappers/combined_iterable.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +/// A view of several iterables combined sequentially into a single iterable. +/// +/// All methods and accessors treat the [CombinedIterableView] as if it were a +/// single concatenated iterable, but the underlying implementation is based on +/// lazily accessing individual iterable instances. This means that if the +/// underlying iterables change, the [CombinedIterableView] will reflect those +/// changes. +class CombinedIterableView extends IterableBase { + /// The iterables that this combines. + final Iterable> _iterables; + + /// Creates a combined view of [iterables]. + const CombinedIterableView(this._iterables); + + Iterator get iterator => + new _CombinedIterator(_iterables.map((i) => i.iterator).iterator); + + // Special cased contains/isEmpty/length since many iterables have an + // efficient implementation instead of running through the entire iterator. + + bool contains(Object element) => _iterables.any((i) => i.contains(element)); + + bool get isEmpty => _iterables.every((i) => i.isEmpty); + + int get length => _iterables.fold(0, (length, i) => length + i.length); +} + +/// The iterator for [CombinedIterableView]. +/// +/// This moves through each iterable's iterators in sequence. +class _CombinedIterator implements Iterator { + /// The iterators that this combines. + /// + /// Because this comes from a call to [Iterable.map], it's lazy and will + /// avoid instantiating unnecessary iterators. + final Iterator> _iterators; + + _CombinedIterator(this._iterators); + + T get current => _iterators.current?.current; + + bool moveNext() { + var current = _iterators.current; + if (current != null && current.moveNext()) { + return true; + } + return _iterators.moveNext() && moveNext(); + } +} +9NN<NOPKO 8(*./LHNO:J->4(K1*&0&10yfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/combined_wrappers/combined_list.dart)// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +/// A view of several lists combined into a single list. +/// +/// All methods and accessors treat the [CombinedListView] list as if it were a +/// single concatenated list, but the underlying implementation is based on +/// lazily accessing individual list instances. This means that if the +/// underlying lists change, the [CombinedListView] will reflect those changes. +/// +/// The index operator (`[]`) and [length] property of a [CombinedListView] are +/// both `O(lists)` rather than `O(1)`. A [CombinedListView] is unmodifiable. +class CombinedListView extends ListBase + implements UnmodifiableListView { + static void _throw() { + throw new UnsupportedError('Cannot modify an unmodifiable List'); + } + + /// The lists that this combines. + final List> _lists; + + /// Creates a combined view of [lists]. + CombinedListView(this._lists); + + set length(int length) { + _throw(); + } + + int get length => _lists.fold(0, (length, list) => length + list.length); + + T operator [](int index) { + var initialIndex = index; + for (var i = 0; i < _lists.length; i++) { + var list = _lists[i]; + if (index < list.length) { + return list[index]; + } + index -= list.length; + } + throw new RangeError.index(initialIndex, this, 'index', null, length); + } + + void operator []=(int index, T value) { + _throw(); + } + + void clear() { + _throw(); + } + + bool remove(Object element) { + _throw(); + return null; + } + + void removeWhere(bool test(T element)) { + _throw(); + } + + void retainWhere(bool test(T element)) { + _throw(); + } +} +DNN<9PLGPPN.)F$*!L.!K* ++xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/combined_wrappers/combined_map.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'combined_iterable.dart'; + +/// Returns a new map that represents maps flattened into a single map. +/// +/// All methods and accessors treat the new map as-if it were a single +/// concatenated map, but the underlying implementation is based on lazily +/// accessing individual map instances. In the occasion where a key occurs in +/// multiple maps the first value is returned. +/// +/// The resulting map has an index operator (`[]`) and `length` property that +/// are both `O(maps)`, rather than `O(1)`, and the map is unmodifiable - but +/// underlying changes to these maps are still accessible from the resulting +/// map. +class CombinedMapView extends UnmodifiableMapBase { + final Iterable> _maps; + + /// Create a new combined view into multiple maps. + /// + /// The iterable is accessed lazily so it should be collection type like + /// [List] or [Set] rather than a lazy iterable produced by `map()` et al. + CombinedMapView(this._maps); + + V operator [](Object key) { + for (var map in _maps) { + // Avoid two hash lookups on a positive hit. + var value = map[key]; + if (value != null || map.containsKey(value)) { + return value; + } + } + return null; + } + + /// The keys of [this]. + /// + /// The returned iterable has efficient `length` and `contains` operations, + /// based on [length] and [containsKey] of the individual maps. + /// + /// The order of iteration is defined by the individual `Map` implementations, + /// but must be consistent between changes to the maps. + /// + /// Unlike most [Map] implementations, modifying an individual map while + /// iterating the keys will _sometimes_ throw. This behavior may change in + /// the future. + Iterable get keys => new CombinedIterableView(_maps.map((m) => m.keys)); +} +6NN<!HGKN/NNM @#5KM35NBQ:KMQefile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/comparators.dartq// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Character constants. +const int _zero = 0x30; +const int _upperCaseA = 0x41; +const int _upperCaseZ = 0x5a; +const int _lowerCaseA = 0x61; +const int _lowerCaseZ = 0x7a; +const int _asciiCaseBit = 0x20; + +/// Checks if strings [a] and [b] differ only on the case of ASCII letters. +/// +/// Strings are equal if they have the same length, and the characters at +/// each index are the same, or they are ASCII letters where one is upper-case +/// and the other is the lower-case version of the same letter. +/// +/// The comparison does not ignore the case of non-ASCII letters, so +/// an upper-case ae-ligature (Æ) is different from +/// a lower case ae-ligature (æ). +/// +/// Ignoring non-ASCII letters is not generally a good idea, but it makes sense +/// for situations where the strings are known to be ASCII. Examples could +/// be Dart identifiers, base-64 or hex encoded strings, GUIDs or similar +/// strings with a known structure. +bool equalsIgnoreAsciiCase(String a, String b) { + if (a.length != b.length) return false; + for (int i = 0; i < a.length; i++) { + var aChar = a.codeUnitAt(i); + var bChar = b.codeUnitAt(i); + if (aChar == bChar) continue; + // Quick-check for whether this may be different cases of the same letter. + if (aChar ^ bChar != _asciiCaseBit) return false; + // If it's possible, then check if either character is actually an ASCII + // letter. + int aCharLowerCase = aChar | _asciiCaseBit; + if (_lowerCaseA <= aCharLowerCase && aCharLowerCase <= _lowerCaseZ) { + continue; + } + return false; + } + return true; +} + +/// Hash code for a string which is compatible with [equalsIgnoreAsciiCase]. +/// +/// The hash code is unaffected by changing the case of ASCII letters, but +/// the case of non-ASCII letters do affect the result. +int hashIgnoreAsciiCase(String string) { + // Jenkins hash code ( http://en.wikipedia.org/wiki/Jenkins_hash_function). + // adapted to smi values. + // Same hash used by dart2js for strings, modified to ignore ASCII letter + // case. + int hash = 0; + for (int i = 0; i < string.length; i++) { + int char = string.codeUnitAt(i); + // Convert lower-case ASCII letters to upper case.upper + // This ensures that strings that differ only in case will have the + // same hash code. + if (_lowerCaseA <= char && char <= _lowerCaseZ) char -= _asciiCaseBit; + hash = 0x1fffffff & (hash + char); + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + hash >>= 6; + } + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + hash >>= 11; + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); +} + +/// Compares [a] and [b] lexically, converting ASCII letters to upper case. +/// +/// Comparison treats all lower-case ASCII letters as upper-case letters, +/// but does no case conversion for non-ASCII letters. +/// +/// If two strings differ only on the case of ASCII letters, the one with the +/// capital letter at the first difference will compare as less than the other +/// string. This tie-breaking ensures that the comparison is a total ordering +/// on strings and is compatible with equality. +/// +/// Ignoring non-ASCII letters is not generally a good idea, but it makes sense +/// for situations where the strings are known to be ASCII. Examples could +/// be Dart identifiers, base-64 or hex encoded strings, GUIDs or similar +/// strings with a known structure. +int compareAsciiUpperCase(String a, String b) { + int defaultResult = 0; // Returned if no difference found. + for (int i = 0; i < a.length; i++) { + if (i >= b.length) return 1; + var aChar = a.codeUnitAt(i); + var bChar = b.codeUnitAt(i); + if (aChar == bChar) continue; + // Upper-case if letters. + int aUpperCase = aChar; + int bUpperCase = bChar; + if (_lowerCaseA <= aChar && aChar <= _lowerCaseZ) { + aUpperCase -= _asciiCaseBit; + } + if (_lowerCaseA <= bChar && bChar <= _lowerCaseZ) { + bUpperCase -= _asciiCaseBit; + } + if (aUpperCase != bUpperCase) return (aUpperCase - bUpperCase).sign; + if (defaultResult == 0) defaultResult = (aChar - bChar); + } + if (b.length > a.length) return -1; + return defaultResult.sign; +} + +/// Compares [a] and [b] lexically, converting ASCII letters to lower case. +/// +/// Comparison treats all upper-case ASCII letters as lower-case letters, +/// but does no case conversion for non-ASCII letters. +/// +/// If two strings differ only on the case of ASCII letters, the one with the +/// capital letter at the first difference will compare as less than the other +/// string. This tie-breaking ensures that the comparison is a total ordering +/// on strings. +/// +/// Ignoring non-ASCII letters is not generally a good idea, but it makes sense +/// for situations where the strings are known to be ASCII. Examples could +/// be Dart identifiers, base-64 or hex encoded strings, GUIDs or similar +/// strings with a known structure. +int compareAsciiLowerCase(String a, String b) { + int defaultResult = 0; + for (int i = 0; i < a.length; i++) { + if (i >= b.length) return 1; + var aChar = a.codeUnitAt(i); + var bChar = b.codeUnitAt(i); + if (aChar == bChar) continue; + int aLowerCase = aChar; + int bLowerCase = bChar; + // Upper case if ASCII letters. + if (_upperCaseA <= bChar && bChar <= _upperCaseZ) { + bLowerCase += _asciiCaseBit; + } + if (_upperCaseA <= aChar && aChar <= _upperCaseZ) { + aLowerCase += _asciiCaseBit; + } + if (aLowerCase != bLowerCase) return (aLowerCase - bLowerCase).sign; + if (defaultResult == 0) defaultResult = aChar - bChar; + } + if (b.length > a.length) return -1; + return defaultResult.sign; +} + +/// Compares strings [a] and [b] according to [natural sort ordering][]. +/// +/// A natural sort ordering is a lexical ordering where embedded +/// numerals (digit sequences) are treated as a single unit and ordered by +/// numerical value. +/// This means that `"a10b"` will be ordered after `"a7b"` in natural +/// ordering, where lexical ordering would put the `1` before the `7`, ignoring +/// that the `1` is part of a larger number. +/// +/// Example: +/// The following strings are in the order they would be sorted by using this +/// comparison function: +/// +/// "a", "a0", "a0b", "a1", "a01", "a9", "a10", "a100", "a100b", "aa" +/// +/// [natural sort ordering]: https://en.wikipedia.org/wiki/Natural_sort_order +int compareNatural(String a, String b) { + for (int i = 0; i < a.length; i++) { + if (i >= b.length) return 1; + var aChar = a.codeUnitAt(i); + var bChar = b.codeUnitAt(i); + if (aChar != bChar) { + return _compareNaturally(a, b, i, aChar, bChar); + } + } + if (b.length > a.length) return -1; + return 0; +} + +/// Compares strings [a] and [b] according to lower-case +/// [natural sort ordering][]. +/// +/// ASCII letters are converted to lower case before being compared, like +/// for [compareAsciiLowerCase], then the result is compared like for +/// [compareNatural]. +/// +/// If two strings differ only on the case of ASCII letters, the one with the +/// capital letter at the first difference will compare as less than the other +/// string. This tie-breaking ensures that the comparison is a total ordering +/// on strings. +/// +/// [natural sort ordering]: https://en.wikipedia.org/wiki/Natural_sort_order +int compareAsciiLowerCaseNatural(String a, String b) { + int defaultResult = 0; // Returned if no difference found. + for (int i = 0; i < a.length; i++) { + if (i >= b.length) return 1; + var aChar = a.codeUnitAt(i); + var bChar = b.codeUnitAt(i); + if (aChar == bChar) continue; + int aLowerCase = aChar; + int bLowerCase = bChar; + if (_upperCaseA <= aChar && aChar <= _upperCaseZ) { + aLowerCase += _asciiCaseBit; + } + if (_upperCaseA <= bChar && bChar <= _upperCaseZ) { + bLowerCase += _asciiCaseBit; + } + if (aLowerCase != bLowerCase) { + return _compareNaturally(a, b, i, aLowerCase, bLowerCase); + } + if (defaultResult == 0) defaultResult = aChar - bChar; + } + if (b.length > a.length) return -1; + return defaultResult.sign; +} + +/// Compares strings [a] and [b] according to upper-case +/// [natural sort ordering][]. +/// +/// ASCII letters are converted to upper case before being compared, like +/// for [compareAsciiUpperCase], then the result is compared like for +/// [compareNatural]. +/// +/// If two strings differ only on the case of ASCII letters, the one with the +/// capital letter at the first difference will compare as less than the other +/// string. This tie-breaking ensures that the comparison is a total ordering +/// on strings +/// +/// [natural sort ordering]: https://en.wikipedia.org/wiki/Natural_sort_order +int compareAsciiUpperCaseNatural(String a, String b) { + int defaultResult = 0; + for (int i = 0; i < a.length; i++) { + if (i >= b.length) return 1; + var aChar = a.codeUnitAt(i); + var bChar = b.codeUnitAt(i); + if (aChar == bChar) continue; + int aUpperCase = aChar; + int bUpperCase = bChar; + if (_lowerCaseA <= aChar && aChar <= _lowerCaseZ) { + aUpperCase -= _asciiCaseBit; + } + if (_lowerCaseA <= bChar && bChar <= _lowerCaseZ) { + bUpperCase -= _asciiCaseBit; + } + if (aUpperCase != bUpperCase) { + return _compareNaturally(a, b, i, aUpperCase, bUpperCase); + } + if (defaultResult == 0) defaultResult = aChar - bChar; + } + if (b.length > a.length) return -1; + return defaultResult.sign; +} + +/// Check for numbers overlapping the current mismatched characters. +/// +/// If both [aChar] and [bChar] are digits, use numerical comparison. +/// Check if the previous characters is a non-zero number, and if not, +/// skip - but count - leading zeros before comparing numbers. +/// +/// If one is a digit and the other isn't, check if the previous character +/// is a digit, and if so, the the one with the digit is the greater number. +/// +/// Otherwise just returns the difference between [aChar] and [bChar]. +int _compareNaturally(String a, String b, int index, int aChar, int bChar) { + assert(aChar != bChar); + var aIsDigit = _isDigit(aChar); + var bIsDigit = _isDigit(bChar); + if (aIsDigit) { + if (bIsDigit) { + return _compareNumerically(a, b, aChar, bChar, index); + } else if (index > 0 && _isDigit(a.codeUnitAt(index - 1))) { + // aChar is the continuation of a longer number. + return 1; + } + } else if (bIsDigit && index > 0 && _isDigit(b.codeUnitAt(index - 1))) { + // bChar is the continuation of a longer number. + return -1; + } + // Characters are both non-digits, or not continuation of earlier number. + return (aChar - bChar).sign; +} + +/// Compare numbers overlapping [aChar] and [bChar] numerically. +/// +/// If the numbers have the same numerical value, but one has more leading +/// zeros, the longer number is considered greater than the shorter one. +/// +/// This ensures a total ordering on strings compatible with equality. +int _compareNumerically(String a, String b, int aChar, int bChar, int index) { + // Both are digits. Find the first significant different digit, then find + // the length of the numbers. + if (_isNonZeroNumberSuffix(a, index)) { + // Part of a longer number, differs at this index, just count the length. + int result = _compareDigitCount(a, b, index, index); + if (result != 0) return result; + // If same length, the current character is the most significant differing + // digit. + return (aChar - bChar).sign; + } + // Not part of larger (non-zero) number, so skip leading zeros before + // comparing numbers. + int aIndex = index; + int bIndex = index; + if (aChar == _zero) { + do { + aIndex++; + if (aIndex == a.length) return -1; // number in a is zero, b is not. + aChar = a.codeUnitAt(aIndex); + } while (aChar == _zero); + if (!_isDigit(aChar)) return -1; + } else if (bChar == _zero) { + do { + bIndex++; + if (bIndex == b.length) return 1; // number in b is zero, a is not. + bChar = b.codeUnitAt(bIndex); + } while (bChar == _zero); + if (!_isDigit(bChar)) return 1; + } + if (aChar != bChar) { + int result = _compareDigitCount(a, b, aIndex, bIndex); + if (result != 0) return result; + return (aChar - bChar).sign; + } + // Same leading digit, one had more leading zeros. + // Compare digits until reaching a difference. + while (true) { + var aIsDigit = false; + var bIsDigit = false; + aChar = 0; + bChar = 0; + if (++aIndex < a.length) { + aChar = a.codeUnitAt(aIndex); + aIsDigit = _isDigit(aChar); + } + if (++bIndex < b.length) { + bChar = b.codeUnitAt(bIndex); + bIsDigit = _isDigit(bChar); + } + if (aIsDigit) { + if (bIsDigit) { + if (aChar == bChar) continue; + // First different digit found. + break; + } + // bChar is non-digit, so a has longer number. + return 1; + } else if (bIsDigit) { + return -1; // b has longer number. + } else { + // Neither is digit, so numbers had same numerical value. + // Fall back on number of leading zeros + // (reflected by difference in indices). + return (aIndex - bIndex).sign; + } + } + // At first differing digits. + int result = _compareDigitCount(a, b, aIndex, bIndex); + if (result != 0) return result; + return (aChar - bChar).sign; +} + +/// Checks which of [a] and [b] has the longest sequence of digits. +/// +/// Starts counting from `i + 1` and `j + 1` (assumes that `a[i]` and `b[j]` are +/// both already known to be digits). +int _compareDigitCount(String a, String b, int i, int j) { + while (++i < a.length) { + bool aIsDigit = _isDigit(a.codeUnitAt(i)); + if (++j == b.length) return aIsDigit ? 1 : 0; + bool bIsDigit = _isDigit(b.codeUnitAt(j)); + if (aIsDigit) { + if (bIsDigit) continue; + return 1; + } else if (bIsDigit) { + return -1; + } else { + return 0; + } + } + if (++j < b.length && _isDigit(b.codeUnitAt(j))) { + return -1; + } + return 0; +} + +bool _isDigit(int charCode) => (charCode ^ _zero) <= 9; + +/// Check if the digit at [index] is continuing a non-zero number. +/// +/// If there is no non-zero digits before, then leading zeros at [index] +/// are also ignored when comparing numerically. If there is a non-zero digit +/// before, then zeros at [index] are significant. +bool _isNonZeroNumberSuffix(String string, int index) { + while (--index >= 0) { + int char = string.codeUnitAt(index); + if (char != _zero) return _isDigit(char); + } + return false; +} +OO=!MKPAF5#QLK%2+(""#P7N1KNL9*OM -&=IL(?<=MK8OPO1QLK%1>("""#9$9$J>'MK8OPOQLK%1("""#%9$9$J<'JBLGQ.OKO*("""8' : KGOPOO8>("""#9$9$%B<': KGOPOO8("""#9$9$%B<'FGH@LNHN##>B8L6M BLJHPM!+O:%P"I +L%& +K%%<%"62 %# %#') 6*A/0&!:# ER'<0306 9DJO49*/bfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/equality.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:collection"; + +import "comparators.dart"; + +const int _HASH_MASK = 0x7fffffff; + +/// A generic equality relation on objects. +abstract class Equality { + const factory Equality() = DefaultEquality; + + /// Compare two elements for being equal. + /// + /// This should be a proper equality relation. + bool equals(E e1, E e2); + + /// Get a hashcode of an element. + /// + /// The hashcode should be compatible with [equals], so that if + /// `equals(a, b)` then `hash(a) == hash(b)`. + int hash(E e); + + /// Test whether an object is a valid argument to [equals] and [hash]. + /// + /// Some implementations may be restricted to only work on specific types + /// of objects. + bool isValidKey(Object o); +} + +typedef F _GetKey(E object); + +/// Equality of objects based on derived values. +/// +/// For example, given the class: +/// ```dart +/// abstract class Employee { +/// int get employmentId; +/// } +/// ``` +/// +/// The following [Equality] considers employees with the same IDs to be equal: +/// ```dart +/// new EqualityBy((Employee e) => e.employmentId); +/// ``` +/// +/// It's also possible to pass an additional equality instance that should be +/// used to compare the value itself. +class EqualityBy implements Equality { + // Returns a derived value F from an object E. + final _GetKey _getKey; + + // Determines equality between two values of F. + final Equality _inner; + + EqualityBy(F getKey(E object), [Equality inner = const DefaultEquality()]) + : _getKey = getKey, + _inner = inner; + + bool equals(E e1, E e2) => _inner.equals(_getKey(e1), _getKey(e2)); + + int hash(E e) => _inner.hash(_getKey(e)); + + bool isValidKey(Object o) { + if (o is E) { + final value = _getKey(o); + return value is F && _inner.isValidKey(value); + } + return false; + } +} + +/// Equality of objects that compares only the natural equality of the objects. +/// +/// This equality uses the objects' own [Object.==] and [Object.hashCode] for +/// the equality. +/// +/// Note that [equals] and [hash] take `Object`s rather than `E`s. This allows +/// `E` to be inferred as `Null` in const contexts where `E` wouldn't be a +/// compile-time constant, while still allowing the class to be used at runtime. +class DefaultEquality implements Equality { + const DefaultEquality(); + bool equals(Object e1, Object e2) => e1 == e2; + int hash(Object e) => e.hashCode; + bool isValidKey(Object o) => true; +} + +/// Equality of objects that compares only the identity of the objects. +class IdentityEquality implements Equality { + const IdentityEquality(); + bool equals(E e1, E e2) => identical(e1, e2); + int hash(E e) => identityHashCode(e); + bool isValidKey(Object o) => true; +} + +/// Equality on iterables. +/// +/// Two iterables are equal if they have the same elements in the same order. +/// +/// The [equals] and [hash] methods accepts `null` values, +/// even if the [isValidKey] returns `false` for `null`. +/// The [hash] of `null` is `null.hashCode`. +class IterableEquality implements Equality> { + final Equality _elementEquality; + const IterableEquality( + [Equality elementEquality = const DefaultEquality()]) + : _elementEquality = elementEquality; + + bool equals(Iterable elements1, Iterable elements2) { + if (identical(elements1, elements2)) return true; + if (elements1 == null || elements2 == null) return false; + var it1 = elements1.iterator; + var it2 = elements2.iterator; + while (true) { + bool hasNext = it1.moveNext(); + if (hasNext != it2.moveNext()) return false; + if (!hasNext) return true; + if (!_elementEquality.equals(it1.current, it2.current)) return false; + } + } + + int hash(Iterable elements) { + if (elements == null) return null.hashCode; + // Jenkins's one-at-a-time hash function. + int hash = 0; + for (E element in elements) { + int c = _elementEquality.hash(element); + hash = (hash + c) & _HASH_MASK; + hash = (hash + (hash << 10)) & _HASH_MASK; + hash ^= (hash >> 6); + } + hash = (hash + (hash << 3)) & _HASH_MASK; + hash ^= (hash >> 11); + hash = (hash + (hash << 15)) & _HASH_MASK; + return hash; + } + + bool isValidKey(Object o) => o is Iterable; +} + +/// Equality on lists. +/// +/// Two lists are equal if they have the same length and their elements +/// at each index are equal. +/// +/// This is effectively the same as [IterableEquality] except that it +/// accesses elements by index instead of through iteration. +/// +/// The [equals] and [hash] methods accepts `null` values, +/// even if the [isValidKey] returns `false` for `null`. +/// The [hash] of `null` is `null.hashCode`. +class ListEquality implements Equality> { + final Equality _elementEquality; + const ListEquality([Equality elementEquality = const DefaultEquality()]) + : _elementEquality = elementEquality; + + bool equals(List list1, List list2) { + if (identical(list1, list2)) return true; + if (list1 == null || list2 == null) return false; + int length = list1.length; + if (length != list2.length) return false; + for (int i = 0; i < length; i++) { + if (!_elementEquality.equals(list1[i], list2[i])) return false; + } + return true; + } + + int hash(List list) { + if (list == null) return null.hashCode; + // Jenkins's one-at-a-time hash function. + // This code is almost identical to the one in IterableEquality, except + // that it uses indexing instead of iterating to get the elements. + int hash = 0; + for (int i = 0; i < list.length; i++) { + int c = _elementEquality.hash(list[i]); + hash = (hash + c) & _HASH_MASK; + hash = (hash + (hash << 10)) & _HASH_MASK; + hash ^= (hash >> 6); + } + hash = (hash + (hash << 3)) & _HASH_MASK; + hash ^= (hash >> 11); + hash = (hash + (hash << 15)) & _HASH_MASK; + return hash; + } + + bool isValidKey(Object o) => o is List; +} + +abstract class _UnorderedEquality> + implements Equality { + final Equality _elementEquality; + + const _UnorderedEquality(this._elementEquality); + + bool equals(T elements1, T elements2) { + if (identical(elements1, elements2)) return true; + if (elements1 == null || elements2 == null) return false; + HashMap counts = new HashMap( + equals: _elementEquality.equals, + hashCode: _elementEquality.hash, + isValidKey: _elementEquality.isValidKey); + int length = 0; + for (var e in elements1) { + int count = counts[e]; + if (count == null) count = 0; + counts[e] = count + 1; + length++; + } + for (var e in elements2) { + int count = counts[e]; + if (count == null || count == 0) return false; + counts[e] = count - 1; + length--; + } + return length == 0; + } + + int hash(T elements) { + if (elements == null) return null.hashCode; + int hash = 0; + for (E element in elements) { + int c = _elementEquality.hash(element); + hash = (hash + c) & _HASH_MASK; + } + hash = (hash + (hash << 3)) & _HASH_MASK; + hash ^= (hash >> 11); + hash = (hash + (hash << 15)) & _HASH_MASK; + return hash; + } +} + +/// Equality of the elements of two iterables without considering order. +/// +/// Two iterables are considered equal if they have the same number of elements, +/// and the elements of one set can be paired with the elements +/// of the other iterable, so that each pair are equal. +class UnorderedIterableEquality extends _UnorderedEquality> { + const UnorderedIterableEquality( + [Equality elementEquality = const DefaultEquality()]) + : super(elementEquality); + + bool isValidKey(Object o) => o is Iterable; +} + +/// Equality of sets. +/// +/// Two sets are considered equal if they have the same number of elements, +/// and the elements of one set can be paired with the elements +/// of the other set, so that each pair are equal. +/// +/// This equality behaves the same as [UnorderedIterableEquality] except that +/// it expects sets instead of iterables as arguments. +/// +/// The [equals] and [hash] methods accepts `null` values, +/// even if the [isValidKey] returns `false` for `null`. +/// The [hash] of `null` is `null.hashCode`. +class SetEquality extends _UnorderedEquality> { + const SetEquality([Equality elementEquality = const DefaultEquality()]) + : super(elementEquality); + + bool isValidKey(Object o) => o is Set; +} + +/// Internal class used by [MapEquality]. +/// +/// The class represents a map entry as a single object, +/// using a combined hashCode and equality of the key and value. +class _MapEntry { + final MapEquality equality; + final key; + final value; + _MapEntry(this.equality, this.key, this.value); + + int get hashCode => + (3 * equality._keyEquality.hash(key) + + 7 * equality._valueEquality.hash(value)) & + _HASH_MASK; + + bool operator ==(Object other) => + other is _MapEntry && + equality._keyEquality.equals(key, other.key) && + equality._valueEquality.equals(value, other.value); +} + +/// Equality on maps. +/// +/// Two maps are equal if they have the same number of entries, and if the +/// entries of the two maps are pairwise equal on both key and value. +/// +/// The [equals] and [hash] methods accepts `null` values, +/// even if the [isValidKey] returns `false` for `null`. +/// The [hash] of `null` is `null.hashCode`. +class MapEquality implements Equality> { + final Equality _keyEquality; + final Equality _valueEquality; + const MapEquality( + {Equality keys: const DefaultEquality(), + Equality values: const DefaultEquality()}) + : _keyEquality = keys, + _valueEquality = values; + + bool equals(Map map1, Map map2) { + if (identical(map1, map2)) return true; + if (map1 == null || map2 == null) return false; + int length = map1.length; + if (length != map2.length) return false; + Map<_MapEntry, int> equalElementCounts = new HashMap(); + for (K key in map1.keys) { + _MapEntry entry = new _MapEntry(this, key, map1[key]); + int count = equalElementCounts[entry]; + if (count == null) count = 0; + equalElementCounts[entry] = count + 1; + } + for (K key in map2.keys) { + _MapEntry entry = new _MapEntry(this, key, map2[key]); + int count = equalElementCounts[entry]; + if (count == null || count == 0) return false; + equalElementCounts[entry] = count - 1; + } + return true; + } + + int hash(Map map) { + if (map == null) return null.hashCode; + int hash = 0; + for (K key in map.keys) { + int keyHash = _keyEquality.hash(key); + int valueHash = _valueEquality.hash(map[key]); + hash = (hash + 3 * keyHash + 7 * valueHash) & _HASH_MASK; + } + hash = (hash + (hash << 3)) & _HASH_MASK; + hash ^= (hash >> 11); + hash = (hash + (hash << 15)) & _HASH_MASK; + return hash; + } + + bool isValidKey(Object o) => o is Map; +} + +/// Combines several equalities into a single equality. +/// +/// Tries each equality in order, using [Equality.isValidKey], and returns +/// the result of the first equality that applies to the argument or arguments. +/// +/// For `equals`, the first equality that matches the first argument is used, +/// and if the second argument of `equals` is not valid for that equality, +/// it returns false. +/// +/// Because the equalities are tried in order, they should generally work on +/// disjoint types. Otherwise the multi-equality may give inconsistent results +/// for `equals(e1, e2)` and `equals(e2, e1)`. This can happen if one equality +/// considers only `e1` a valid key, and not `e2`, but an equality which is +/// checked later, allows both. +class MultiEquality implements Equality { + final Iterable> _equalities; + + const MultiEquality(Iterable> equalities) + : _equalities = equalities; + + bool equals(E e1, E e2) { + for (Equality eq in _equalities) { + if (eq.isValidKey(e1)) return eq.isValidKey(e2) && eq.equals(e1, e2); + } + return false; + } + + int hash(E e) { + for (Equality eq in _equalities) { + if (eq.isValidKey(e)) return eq.hash(e); + } + return 0; + } + + bool isValidKey(Object o) { + for (Equality eq in _equalities) { + if (eq.isValidKey(o)) return true; + } + return false; + } +} + +/// Deep equality on collections. +/// +/// Recognizes lists, sets, iterables and maps and compares their elements using +/// deep equality as well. +/// +/// Non-iterable/map objects are compared using a configurable base equality. +/// +/// Works in one of two modes: ordered or unordered. +/// +/// In ordered mode, lists and iterables are required to have equal elements +/// in the same order. In unordered mode, the order of elements in iterables +/// and lists are not important. +/// +/// A list is only equal to another list, likewise for sets and maps. All other +/// iterables are compared as iterables only. +class DeepCollectionEquality implements Equality { + final Equality _base; + final bool _unordered; + const DeepCollectionEquality([Equality base = const DefaultEquality()]) + : _base = base, + _unordered = false; + + /// Creates a deep equality on collections where the order of lists and + /// iterables are not considered important. That is, lists and iterables are + /// treated as unordered iterables. + const DeepCollectionEquality.unordered( + [Equality base = const DefaultEquality()]) + : _base = base, + _unordered = true; + + bool equals(e1, e2) { + if (e1 is Set) { + return e2 is Set && new SetEquality(this).equals(e1, e2); + } + if (e1 is Map) { + return e2 is Map && + new MapEquality(keys: this, values: this).equals(e1, e2); + } + if (!_unordered) { + if (e1 is List) { + return e2 is List && new ListEquality(this).equals(e1, e2); + } + if (e1 is Iterable) { + return e2 is Iterable && new IterableEquality(this).equals(e1, e2); + } + } else if (e1 is Iterable) { + if (e1 is List != e2 is List) return false; + return e2 is Iterable && + new UnorderedIterableEquality(this).equals(e1, e2); + } + return _base.equals(e1, e2); + } + + int hash(Object o) { + if (o is Set) return new SetEquality(this).hash(o); + if (o is Map) return new MapEquality(keys: this, values: this).hash(o); + if (!_unordered) { + if (o is List) return new ListEquality(this).hash(o); + if (o is Iterable) return new IterableEquality(this).hash(o); + } else if (o is Iterable) { + return new UnorderedIterableEquality(this).hash(o); + } + return _base.hash(o); + } + + bool isValidKey(Object o) => o is Iterable || o is Map || _base.isValidKey(o); +} + +/// String equality that's insensitive to differences in ASCII case. +/// +/// Non-ASCII characters are compared as-is, with no conversion. +class CaseInsensitiveEquality implements Equality { + const CaseInsensitiveEquality(); + + bool equals(String string1, String string2) => + equalsIgnoreAsciiCase(string1, string2); + + int hash(String string) => hashIgnoreAsciiCase(string); + + bool isValidKey(Object object) => object is String; +} +NN<#,1,1$B0IL#1" P 4N&012PF, 5PNOKQ21$%H30(%N;9-=&?,>6>""%3!L#0.".&1./1HF=;9-5&N,..6.'F,.LG,.&1./-<&3*6>*))2$50".&./IQ@8P#? 1L@3N7;9-=M ,*9A 2-5$6:KF;9-9"$24!0,4-<=-$-=-5-+,5@.//8KPNKMOOL 0+8"*L*/*)"QN5MM!P.3JJO&*1@DDL!2>!8L extends DelegatingMap { + /// Creates a map with equality based on [equality]. + EqualityMap(Equality equality) + : super(new LinkedHashMap( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)); + + /// Creates a map with equality based on [equality] that contains all + /// key-value pairs of [other]. + /// + /// If [other] has multiple keys that are equivalent according to [equality], + /// the last one reached during iteration takes precedence. + EqualityMap.from(Equality equality, Map other) + : super(new LinkedHashMap( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)) { + addAll(other); + } +} +!NN<F67$!%%/H"P>:!%%0ffile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/equality_set.dart{// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'equality.dart'; +import 'wrappers.dart'; + +/// A [Map] whose key equality is determined by an [Equality] object. +class EqualitySet extends DelegatingSet { + /// Creates a set with equality based on [equality]. + EqualitySet(Equality equality) + : super(new LinkedHashSet( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)); + + /// Creates a set with equality based on [equality] that contains all + /// elements in [other]. + /// + /// If [other] has multiple values that are equivalent according to + /// [equality], the first one reached during iteration takes precedence. + EqualitySet.from(Equality equality, Iterable other) + : super(new LinkedHashSet( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)) { + addAll(other); + } +} +!NN<F07$!%%/HFK mapMap(Map map, + {K2 key(K1 key, V1 value), V2 value(K1 key, V1 value)}) { + key ??= (mapKey, _) => mapKey as K2; + value ??= (_, mapValue) => mapValue as V2; + + var result = {}; + map.forEach((mapKey, mapValue) { + result[key(mapKey, mapValue)] = value(mapKey, mapValue); + }); + return result; +} + +/// Returns a new map with all key/value pairs in both [map1] and [map2]. +/// +/// If there are keys that occur in both maps, the [value] function is used to +/// select the value that goes into the resulting map based on the two original +/// values. If [value] is omitted, the value from [map2] is used. +Map mergeMaps(Map map1, Map map2, + {V value(V value1, V value2)}) { + var result = new Map.from(map1); + if (value == null) return result..addAll(map2); + + map2.forEach((key, mapValue) { + result[key] = + result.containsKey(key) ? value(result[key], mapValue) : mapValue; + }); + return result; +} + +/// Groups the elements in [values] by the value returned by [key]. +/// +/// Returns a map from keys computed by [key] to a list of all values for which +/// [key] returns that key. The values appear in the list in the same relative +/// order as in [values]. +Map> groupBy(Iterable values, T key(S element)) { + var map = >{}; + for (var element in values) { + var list = map.putIfAbsent(key(element), () => []); + list.add(element); + } + return map; +} + +/// Returns the element of [values] for which [orderBy] returns the minimum +/// value. +/// +/// The values returned by [orderBy] are compared using the [compare] function. +/// If [compare] is omitted, values must implement [Comparable] and they are +/// compared using their [Comparable.compareTo]. +S minBy(Iterable values, T orderBy(S element), + {int compare(T value1, T value2)}) { + compare ??= defaultCompare(); + + S minValue; + T minOrderBy; + for (var element in values) { + var elementOrderBy = orderBy(element); + if (minOrderBy == null || compare(elementOrderBy, minOrderBy) < 0) { + minValue = element; + minOrderBy = elementOrderBy; + } + } + return minValue; +} + +/// Returns the element of [values] for which [orderBy] returns the maximum +/// value. +/// +/// The values returned by [orderBy] are compared using the [compare] function. +/// If [compare] is omitted, values must implement [Comparable] and they are +/// compared using their [Comparable.compareTo]. +S maxBy(Iterable values, T orderBy(S element), + {int compare(T value1, T value2)}) { + compare ??= defaultCompare(); + + S maxValue; + T maxOrderBy; + for (var element in values) { + var elementOrderBy = orderBy(element); + if (maxOrderBy == null || compare(elementOrderBy, maxOrderBy) > 0) { + maxValue = element; + maxOrderBy = elementOrderBy; + } + } + return maxValue; +} + +/// Returns the [transitive closure][] of [graph]. +/// +/// [transitive closure]: https://en.wikipedia.org/wiki/Transitive_closure +/// +/// Interprets [graph] as a directed graph with a vertex for each key and edges +/// from each key to the values that the key maps to. +/// +/// Assumes that every vertex in the graph has a key to represent it, even if +/// that vertex has no outgoing edges. This isn't checked, but if it's not +/// satisfied, the function may crash or provide unexpected output. For example, +/// `{"a": ["b"]}` is not valid, but `{"a": ["b"], "b": []}` is. +Map> transitiveClosure(Map> graph) { + // This uses [Warshall's algorithm][], modified not to add a vertex from each + // node to itself. + // + // [Warshall's algorithm]: https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm#Applications_and_generalizations. + var result = >{}; + graph.forEach((vertex, edges) { + result[vertex] = new Set.from(edges); + }); + + // Lists are faster to iterate than maps, so we create a list since we're + // iterating repeatedly. + var keys = graph.keys.toList(); + for (var vertex1 in keys) { + for (var vertex2 in keys) { + for (var vertex3 in keys) { + if (result[vertex2].contains(vertex1) && + result[vertex1].contains(vertex3)) { + result[vertex2].add(vertex3); + } + } + } + } + + return result; +} + +/// Returns the [strongly connected components][] of [graph], in topological +/// order. +/// +/// [strongly connected components]: https://en.wikipedia.org/wiki/Strongly_connected_component +/// +/// Interprets [graph] as a directed graph with a vertex for each key and edges +/// from each key to the values that the key maps to. +/// +/// Assumes that every vertex in the graph has a key to represent it, even if +/// that vertex has no outgoing edges. This isn't checked, but if it's not +/// satisfied, the function may crash or provide unexpected output. For example, +/// `{"a": ["b"]}` is not valid, but `{"a": ["b"], "b": []}` is. +List> stronglyConnectedComponents(Map> graph) { + // This uses [Tarjan's algorithm][]. + // + // [Tarjan's algorithm]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + var index = 0; + var stack = []; + var result = >[]; + + // The order of these doesn't matter, so we use un-linked implementations to + // avoid unnecessary overhead. + var indices = new HashMap(); + var lowLinks = new HashMap(); + var onStack = new HashSet(); + + strongConnect(T vertex) { + indices[vertex] = index; + lowLinks[vertex] = index; + index++; + + stack.add(vertex); + onStack.add(vertex); + + for (var successor in graph[vertex]) { + if (!indices.containsKey(successor)) { + strongConnect(successor); + lowLinks[vertex] = math.min(lowLinks[vertex], lowLinks[successor]); + } else if (onStack.contains(successor)) { + lowLinks[vertex] = math.min(lowLinks[vertex], lowLinks[successor]); + } + } + + if (lowLinks[vertex] == indices[vertex]) { + var component = new Set(); + T neighbor; + do { + neighbor = stack.removeLast(); + onStack.remove(neighbor); + component.add(neighbor); + } while (neighbor != vertex); + result.add(component); + } + } + + for (var vertex in graph.keys) { + if (!indices.containsKey(vertex)) strongConnect(vertex); + } + + // Tarjan's algorithm produces a reverse-topological sort, so we reverse it to + // get a normal topological sort. + return result.reversed.toList(); +} +NN<OK;M44>'-#=JOPB:%)2!KDPOF 8L PP18)# +I#L PP18)# +I#3KP6NKQAAP~"-L" "11( +M `P6NKQAI'lO!'(" +-"L0L/$ '"!$#=Q$#ffile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/iterable_zip.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:collection"; + +/// Iterable that iterates over lists of values from other iterables. +/// +/// When [iterator] is read, an [Iterator] is created for each [Iterable] in +/// the [Iterable] passed to the constructor. +/// +/// As long as all these iterators have a next value, those next values are +/// combined into a single list, which becomes the next value of this +/// [Iterable]'s [Iterator]. As soon as any of the iterators run out, +/// the zipped iterator also stops. +class IterableZip extends IterableBase> { + final Iterable> _iterables; + + IterableZip(Iterable> iterables) : this._iterables = iterables; + + /// Returns an iterator that combines values of the iterables' iterators + /// as long as they all have values. + Iterator> get iterator { + var iterators = _iterables.map((x) => x.iterator).toList(growable: false); + // TODO(lrn): Return an empty iterator directly if iterators is empty? + return new _IteratorZip(iterators); + } +} + +class _IteratorZip implements Iterator> { + final List> _iterators; + List _current; + + _IteratorZip(List> iterators) : _iterators = iterators; + + bool moveNext() { + if (_iterators.isEmpty) return false; + for (int i = 0; i < _iterators.length; i++) { + if (!_iterators[i].moveNext()) { + _current = null; + return false; + } + } + _current = new List(_iterators.length); + for (int i = 0; i < _iterators.length; i++) { + _current[i] = _iterators[i].current; + } + return true; + } + + List get current => _current; +} +6NN<FM.LFF$5*NK'#OK+5&F*2',2+#hfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/priority_queue.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:collection"; + +import "utils.dart"; + +/// A priority queue is a priority based work-list of elements. +/// +/// The queue allows adding elements, and removing them again in priority order. +abstract class PriorityQueue { + /// Creates an empty [PriorityQueue]. + /// + /// The created [PriorityQueue] is a plain [HeapPriorityQueue]. + /// + /// The [comparison] is a [Comparator] used to compare the priority of + /// elements. An element that compares as less than another element has + /// a higher priority. + /// + /// If [comparison] is omitted, it defaults to [Comparable.compare]. If this + /// is the case, `E` must implement [Comparable], and this is checked at + /// runtime for every comparison. + factory PriorityQueue([int comparison(E e1, E e2)]) = HeapPriorityQueue; + + /// Number of elements in the queue. + int get length; + + /// Whether the queue is empty. + bool get isEmpty; + + /// Whether the queue has any elements. + bool get isNotEmpty; + + /// Checks if [object] is in the queue. + /// + /// Returns true if the element is found. + bool contains(E object); + + /// Adds element to the queue. + /// + /// The element will become the next to be removed by [removeFirst] + /// when all elements with higher priority have been removed. + void add(E element); + + /// Adds all [elements] to the queue. + void addAll(Iterable elements); + + /// Returns the next element that will be returned by [removeFirst]. + /// + /// The element is not removed from the queue. + /// + /// The queue must not be empty when this method is called. + E get first; + + /// Removes and returns the element with the highest priority. + /// + /// Repeatedly calling this method, without adding element in between, + /// is guaranteed to return elements in non-decreasing order as, specified by + /// [comparison]. + /// + /// The queue must not be empty when this method is called. + E removeFirst(); + + /// Removes an element that compares equal to [element] in the queue. + /// + /// Returns true if an element is found and removed, + /// and false if no equal element is found. + bool remove(E element); + + /// Removes all the elements from this queue and returns them. + /// + /// The returned iterable has no specified order. + Iterable removeAll(); + + /// Removes all the elements from this queue. + void clear(); + + /// Returns a list of the elements of this queue in priority order. + /// + /// The queue is not modified. + /// + /// The order is the order that the elements would be in if they were + /// removed from this queue using [removeFirst]. + List toList(); + + /// Return a comparator based set using the comparator of this queue. + /// + /// The queue is not modified. + /// + /// The returned [Set] is currently a [SplayTreeSet], + /// but this may change as other ordered sets are implemented. + /// + /// The set contains all the elements of this queue. + /// If an element occurs more than once in the queue, + /// the set will contain it only once. + Set toSet(); +} + +/// Heap based priority queue. +/// +/// The elements are kept in a heap structure, +/// where the element with the highest priority is immediately accessible, +/// and modifying a single element takes +/// logarithmic time in the number of elements on average. +/// +/// * The [add] and [removeFirst] operations take amortized logarithmic time, +/// O(log(n)), but may occasionally take linear time when growing the capacity +/// of the heap. +/// * The [addAll] operation works as doing repeated [add] operations. +/// * The [first] getter takes constant time, O(1). +/// * The [clear] and [removeAll] methods also take constant time, O(1). +/// * The [contains] and [remove] operations may need to search the entire +/// queue for the elements, taking O(n) time. +/// * The [toList] operation effectively sorts the elements, taking O(n*log(n)) +/// time. +/// * The [toSet] operation effectively adds each element to the new set, taking +/// an expected O(n*log(n)) time. +class HeapPriorityQueue implements PriorityQueue { + /// Initial capacity of a queue when created, or when added to after a + /// [clear]. + /// + /// Number can be any positive value. Picking a size that gives a whole + /// number of "tree levels" in the heap is only done for aesthetic reasons. + static const int _INITIAL_CAPACITY = 7; + + /// The comparison being used to compare the priority of elements. + final Comparator comparison; + + /// List implementation of a heap. + List _queue = new List(_INITIAL_CAPACITY); + + /// Number of elements in queue. + /// + /// The heap is implemented in the first [_length] entries of [_queue]. + int _length = 0; + + /// Create a new priority queue. + /// + /// The [comparison] is a [Comparator] used to compare the priority of + /// elements. An element that compares as less than another element has + /// a higher priority. + /// + /// If [comparison] is omitted, it defaults to [Comparable.compare]. If this + /// is the case, `E` must implement [Comparable], and this is checked at + /// runtime for every comparison. + HeapPriorityQueue([int comparison(E e1, E e2)]) + : comparison = comparison ?? defaultCompare(); + + void add(E element) { + _add(element); + } + + void addAll(Iterable elements) { + for (E element in elements) { + _add(element); + } + } + + void clear() { + _queue = const []; + _length = 0; + } + + bool contains(E object) { + return _locate(object) >= 0; + } + + E get first { + if (_length == 0) throw new StateError("No such element"); + return _queue[0]; + } + + bool get isEmpty => _length == 0; + + bool get isNotEmpty => _length != 0; + + int get length => _length; + + bool remove(E element) { + int index = _locate(element); + if (index < 0) return false; + E last = _removeLast(); + if (index < _length) { + int comp = comparison(last, element); + if (comp <= 0) { + _bubbleUp(last, index); + } else { + _bubbleDown(last, index); + } + } + return true; + } + + Iterable removeAll() { + List result = _queue; + int length = _length; + _queue = const []; + _length = 0; + return result.take(length); + } + + E removeFirst() { + if (_length == 0) throw new StateError("No such element"); + E result = _queue[0]; + E last = _removeLast(); + if (_length > 0) { + _bubbleDown(last, 0); + } + return result; + } + + List toList() { + List list = new List()..length = _length; + list.setRange(0, _length, _queue); + list.sort(comparison); + return list; + } + + Set toSet() { + Set set = new SplayTreeSet(comparison); + for (int i = 0; i < _length; i++) { + set.add(_queue[i]); + } + return set; + } + + /// Returns some representation of the queue. + /// + /// The format isn't significant, and may change in the future. + String toString() { + return _queue.take(_length).toString(); + } + + /// Add element to the queue. + /// + /// Grows the capacity if the backing list is full. + void _add(E element) { + if (_length == _queue.length) _grow(); + _bubbleUp(element, _length++); + } + + /// Find the index of an object in the heap. + /// + /// Returns -1 if the object is not found. + int _locate(E object) { + if (_length == 0) return -1; + // Count positions from one instead of zero. This gives the numbers + // some nice properties. For example, all right children are odd, + // their left sibling is even, and the parent is found by shifting + // right by one. + // Valid range for position is [1.._length], inclusive. + int position = 1; + // Pre-order depth first search, omit child nodes if the current + // node has lower priority than [object], because all nodes lower + // in the heap will also have lower priority. + do { + int index = position - 1; + E element = _queue[index]; + int comp = comparison(element, object); + if (comp == 0) return index; + if (comp < 0) { + // Element may be in subtree. + // Continue with the left child, if it is there. + int leftChildPosition = position * 2; + if (leftChildPosition <= _length) { + position = leftChildPosition; + continue; + } + } + // Find the next right sibling or right ancestor sibling. + do { + while (position.isOdd) { + // While position is a right child, go to the parent. + position >>= 1; + } + // Then go to the right sibling of the left-child. + position += 1; + } while (position > _length); // Happens if last element is a left child. + } while (position != 1); // At root again. Happens for right-most element. + return -1; + } + + E _removeLast() { + int newLength = _length - 1; + E last = _queue[newLength]; + _queue[newLength] = null; + _length = newLength; + return last; + } + + /// Place [element] in heap at [index] or above. + /// + /// Put element into the empty cell at `index`. + /// While the `element` has higher priority than the + /// parent, swap it with the parent. + void _bubbleUp(E element, int index) { + while (index > 0) { + int parentIndex = (index - 1) ~/ 2; + E parent = _queue[parentIndex]; + if (comparison(element, parent) > 0) break; + _queue[index] = parent; + index = parentIndex; + } + _queue[index] = element; + } + + /// Place [element] in heap at [index] or above. + /// + /// Put element into the empty cell at `index`. + /// While the `element` has lower priority than either child, + /// swap it with the highest priority child. + void _bubbleDown(E element, int index) { + int rightChildIndex = index * 2 + 2; + while (rightChildIndex < _length) { + int leftChildIndex = rightChildIndex - 1; + E leftChild = _queue[leftChildIndex]; + E rightChild = _queue[rightChildIndex]; + int comp = comparison(leftChild, rightChild); + int minChildIndex; + E minChild; + if (comp < 0) { + minChild = leftChild; + minChildIndex = leftChildIndex; + } else { + minChild = rightChild; + minChildIndex = rightChildIndex; + } + comp = comparison(element, minChild); + if (comp <= 0) { + _queue[index] = element; + return; + } + _queue[index] = minChild; + index = minChildIndex; + rightChildIndex = index * 2 + 2; + } + int leftChildIndex = rightChildIndex - 1; + if (leftChildIndex < _length) { + E child = _queue[leftChildIndex]; + int comp = comparison(element, child); + if (comp > 0) { + _queue[index] = child; + index = leftChildIndex; + } + } + _queue[index] = element; + } + + /// Grows the capacity of the list holding the heap. + /// + /// Called when the list is full. + void _grow() { + int newCapacity = _queue.length * 2 + 1; + if (newCapacity < _INITIAL_CAPACITY) newCapacity = _INITIAL_CAPACITY; + List newQueue = new List(newCapacity); + newQueue.setRange(0, _length, _queue); + _queue = newQueue; + } +} +jNN<@Q"(BIJOK$N'"**,!F@(%G1>AIP>H7.A40F!H3H!8A78)/K);NQG4IK0P Q$9IJN*E"%3#J#IJOK$28&"!?$'"!, " ?4'2(0B, 6+#/-!HFG<EF2 !.#&9.,( +@ !@ +;PO! 327')*&232@/+)(0,.4(),! '.$(- 7$-J1+dfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/queue_list.dartQ// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +/// A class that efficiently implements both [Queue] and [List]. +// TODO(nweiz): Currently this code is copied almost verbatim from +// dart:collection. The only changes are to implement List and to remove methods +// that are redundant with ListMixin. Remove or simplify it when issue 21330 is +// fixed. +class QueueList extends Object with ListMixin implements Queue { + /// Adapts [source] to be a `QueueList`. + /// + /// Any time the class would produce an element that is not a [T], the element + /// access will throw. + /// + /// Any time a [T] value is attempted stored into the adapted class, the store + /// will throw unless the value is also an instance of [S]. + /// + /// If all accessed elements of [source] are actually instances of [T] and if + /// all elements stored in the returned are actually instance of [S], + /// then the returned instance can be used as a `QueueList`. + static QueueList _castFrom(QueueList source) { + return new _CastQueueList(source); + } + + static const int _INITIAL_CAPACITY = 8; + List _table; + int _head; + int _tail; + + /// Create an empty queue. + /// + /// If [initialCapacity] is given, prepare the queue for at least that many + /// elements. + QueueList([int initialCapacity]) + : _head = 0, + _tail = 0 { + if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) { + initialCapacity = _INITIAL_CAPACITY; + } else if (!_isPowerOf2(initialCapacity)) { + initialCapacity = _nextPowerOf2(initialCapacity); + } + assert(_isPowerOf2(initialCapacity)); + _table = new List(initialCapacity); + } + + // An internal constructor for use by _CastQueueList. + QueueList._(); + + /// Create a queue initially containing the elements of [source]. + factory QueueList.from(Iterable source) { + if (source is List) { + int length = source.length; + QueueList queue = new QueueList(length + 1); + assert(queue._table.length > length); + var sourceList = source; + queue._table.setRange(0, length, sourceList, 0); + queue._tail = length; + return queue; + } else { + return new QueueList()..addAll(source); + } + } + + // Collection interface. + + void add(E element) { + _add(element); + } + + void addAll(Iterable iterable) { + if (iterable is List) { + var list = iterable; + int addCount = list.length; + int length = this.length; + if (length + addCount >= _table.length) { + _preGrow(length + addCount); + // After preGrow, all elements are at the start of the list. + _table.setRange(length, length + addCount, list, 0); + _tail += addCount; + } else { + // Adding addCount elements won't reach _head. + int endSpace = _table.length - _tail; + if (addCount < endSpace) { + _table.setRange(_tail, _tail + addCount, list, 0); + _tail += addCount; + } else { + int preSpace = addCount - endSpace; + _table.setRange(_tail, _tail + endSpace, list, 0); + _table.setRange(0, preSpace, list, endSpace); + _tail = preSpace; + } + } + } else { + for (E element in iterable) _add(element); + } + } + + QueueList cast() => QueueList._castFrom(this); + + @deprecated + QueueList retype() => cast(); + + String toString() => IterableBase.iterableToFullString(this, "{", "}"); + + // Queue interface. + + void addLast(E element) { + _add(element); + } + + void addFirst(E element) { + _head = (_head - 1) & (_table.length - 1); + _table[_head] = element; + if (_head == _tail) _grow(); + } + + E removeFirst() { + if (_head == _tail) throw new StateError("No element"); + E result = _table[_head]; + _table[_head] = null; + _head = (_head + 1) & (_table.length - 1); + return result; + } + + E removeLast() { + if (_head == _tail) throw new StateError("No element"); + _tail = (_tail - 1) & (_table.length - 1); + E result = _table[_tail]; + _table[_tail] = null; + return result; + } + + // List interface. + + int get length => (_tail - _head) & (_table.length - 1); + + set length(int value) { + if (value < 0) throw new RangeError("Length $value may not be negative."); + + int delta = value - length; + if (delta >= 0) { + if (_table.length <= value) { + _preGrow(value); + } + _tail = (_tail + delta) & (_table.length - 1); + return; + } + + int newTail = _tail + delta; // [delta] is negative. + if (newTail >= 0) { + _table.fillRange(newTail, _tail, null); + } else { + newTail += _table.length; + _table.fillRange(0, _tail, null); + _table.fillRange(newTail, _table.length, null); + } + _tail = newTail; + } + + E operator [](int index) { + if (index < 0 || index >= length) { + throw new RangeError("Index $index must be in the range [0..$length)."); + } + + return _table[(_head + index) & (_table.length - 1)]; + } + + void operator []=(int index, E value) { + if (index < 0 || index >= length) { + throw new RangeError("Index $index must be in the range [0..$length)."); + } + + _table[(_head + index) & (_table.length - 1)] = value; + } + + // Internal helper functions. + + /// Whether [number] is a power of two. + /// + /// Only works for positive numbers. + static bool _isPowerOf2(int number) => (number & (number - 1)) == 0; + + /// Rounds [number] up to the nearest power of 2. + /// + /// If [number] is a power of 2 already, it is returned. + /// + /// Only works for positive numbers. + static int _nextPowerOf2(int number) { + assert(number > 0); + number = (number << 1) - 1; + for (;;) { + int nextNumber = number & (number - 1); + if (nextNumber == 0) return number; + number = nextNumber; + } + } + + /// Adds element at end of queue. Used by both [add] and [addAll]. + void _add(E element) { + _table[_tail] = element; + _tail = (_tail + 1) & (_table.length - 1); + if (_head == _tail) _grow(); + } + + /// Grow the table when full. + void _grow() { + List newTable = new List(_table.length * 2); + int split = _table.length - _head; + newTable.setRange(0, split, _table, _head); + newTable.setRange(split, split + _head, _table, 0); + _head = 0; + _tail = _table.length; + _table = newTable; + } + + int _writeToList(List target) { + assert(target.length >= length); + if (_head <= _tail) { + int length = _tail - _head; + target.setRange(0, length, _table, _head); + return length; + } else { + int firstPartSize = _table.length - _head; + target.setRange(0, firstPartSize, _table, _head); + target.setRange(firstPartSize, firstPartSize + _tail, _table, 0); + return _tail + firstPartSize; + } + } + + /// Grows the table even if it is not full. + void _preGrow(int newElementCount) { + assert(newElementCount >= length); + + // Add 1.5x extra room to ensure that there's room for more elements after + // expansion. + newElementCount += newElementCount >> 1; + int newCapacity = _nextPowerOf2(newElementCount); + List newTable = new List(newCapacity); + _tail = _writeToList(newTable); + _table = newTable; + _head = 0; + } +} + +class _CastQueueList extends QueueList { + final QueueList _delegate; + + _CastQueueList(this._delegate) : super._() { + _table = _delegate._table.cast(); + } + + int get _head => _delegate._head; + set _head(int value) => _delegate._head = value; + + int get _tail => _delegate._tail; + set _tail(int value) => _delegate._tail = value; +} +NN<ACQP +J.QQ>PIB=-* N#J+08*+8D/"6,7 1&" 0%E=7.#=.=8 + 1=)J/!</ extends SetBase with UnmodifiableSetMixin { + /// The set of sets that this provides a view of. + final Set> _sets; + + /// Whether the sets in [_sets] are guaranteed to be disjoint. + final bool _disjoint; + + /// Creates a new set that's a view of the union of all sets in [sets]. + /// + /// If any sets in [sets] change, this [UnionSet] reflects that change. If a + /// new set is added to [sets], this [UnionSet] reflects that as well. + /// + /// If [disjoint] is `true`, then all component sets must be disjoint. That + /// is, that they contain no elements in common. This makes many operations + /// including [length] more efficient. If the component sets turn out not to + /// be disjoint, some operations may behave inconsistently. + UnionSet(this._sets, {bool disjoint: false}) : _disjoint = disjoint; + + /// Creates a new set that's a view of the union of all sets in [sets]. + /// + /// If any sets in [sets] change, this [UnionSet] reflects that change. + /// However, unlike [new UnionSet], this creates a copy of its parameter, so + /// changes in [sets] aren't reflected in this [UnionSet]. + /// + /// If [disjoint] is `true`, then all component sets must be disjoint. That + /// is, that they contain no elements in common. This makes many operations + /// including [length] more efficient. If the component sets turn out not to + /// be disjoint, some operations may behave inconsistently. + UnionSet.from(Iterable> sets, {bool disjoint: false}) + : this(sets.toSet(), disjoint: disjoint); + + int get length => _disjoint + ? _sets.fold(0, (length, set) => length + set.length) + : _iterable.length; + + Iterator get iterator => _iterable.iterator; + + /// Returns an iterable over the contents of all the sets in [this]. + Iterable get _iterable => + _disjoint ? _sets.expand((set) => set) : _dedupIterable; + + /// Returns an iterable over the contents of all the sets in [this] that + /// de-duplicates elements. + /// + /// If the sets aren't guaranteed to be disjoint, this keeps track of the + /// elements we've already emitted so that we can de-duplicate them. + Iterable get _dedupIterable { + var seen = new Set(); + return _sets.expand((set) => set).where((element) { + if (seen.contains(element)) return false; + seen.add(element); + return true; + }); + } + + bool contains(Object element) => _sets.any((set) => set.contains(element)); + + E lookup(Object element) { + if (element == null) return null; + + return _sets + .map((set) => set.lookup(element)) + .firstWhere((result) => result != null, orElse: () => null); + } + + Set toSet() { + var result = new Set(); + for (var set in _sets) { + result.addAll(set); + } + return result; + } +} +ZNN<%GOPN&D4AJOINNO>GJJO=NNO>?0<2G?KLG#80N&+Enfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/union_set_controller.dartP// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'union_set.dart'; + +/// A controller that exposes a view of the union of a collection of sets. +/// +/// This is a convenience class for creating a [UnionSet] whose contents change +/// over the lifetime of a class. For example: +/// +/// ```dart +/// class Engine { +/// Set get activeTests => _activeTestsGroup.set; +/// final _activeTestsGroup = new UnionSetController(); +/// +/// void addSuite(Suite suite) { +/// _activeTestsGroup.add(suite.tests); +/// _runSuite(suite); +/// _activeTestsGroup.remove(suite.tests); +/// } +/// } +/// ``` +class UnionSetController { + /// The [UnionSet] that provides a view of the union of sets in [this]. + UnionSet get set => _set; + UnionSet _set; + + /// The sets whose union is exposed through [set]. + final _sets = new Set>(); + + /// Creates a set of sets that provides a view of the union of those sets. + /// + /// If [disjoint] is `true`, this assumes that all component sets are + /// disjoint—that is, that they contain no elements in common. This makes + /// many operations including [length] more efficient. + UnionSetController({bool disjoint: false}) { + _set = new UnionSet(_sets, disjoint: disjoint); + } + + /// Adds the contents of [component] to [set]. + /// + /// If the contents of [component] change over time, [set] will change + /// accordingly. + void add(Set component) { + _sets.add(component); + } + + /// Removes the contents of [component] to [set]. + /// + /// If another set in [this] has overlapping elements with [component], those + /// elements will remain in [set]. + bool remove(Set component) => _sets.remove(component); +} +8NN<KP/ :@#,/J5#MHL9/71I4P%<ofile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/unmodifiable_wrappers.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'empty_unmodifiable_set.dart'; +import 'wrappers.dart'; + +export "dart:collection" show UnmodifiableListView, UnmodifiableMapView; + +/// A fixed-length list. +/// +/// A `NonGrowableListView` contains a [List] object and ensures that +/// its length does not change. +/// Methods that would change the length of the list, +/// such as [add] and [remove], throw an [UnsupportedError]. +/// All other methods work directly on the underlying list. +/// +/// This class _does_ allow changes to the contents of the wrapped list. +/// You can, for example, [sort] the list. +/// Permitted operations defer to the wrapped list. +class NonGrowableListView extends DelegatingList + with NonGrowableListMixin { + NonGrowableListView(List listBase) : super(listBase); +} + +/// Mixin class that implements a throwing version of all list operations that +/// change the List's length. +abstract class NonGrowableListMixin implements List { + static T _throw() { + throw new UnsupportedError( + "Cannot change the length of a fixed-length list"); + } + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + set length(int newLength) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + bool add(E value) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void addAll(Iterable iterable) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void insert(int index, E element) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void insertAll(int index, Iterable iterable) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + bool remove(Object value) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + E removeAt(int index) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + E removeLast() => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void removeWhere(bool test(E element)) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void retainWhere(bool test(E element)) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void removeRange(int start, int end) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void replaceRange(int start, int end, Iterable iterable) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the length of the list are disallowed. + void clear() => _throw(); +} + +/// An unmodifiable set. +/// +/// An UnmodifiableSetView contains a [Set] object and ensures +/// that it does not change. +/// Methods that would change the set, +/// such as [add] and [remove], throw an [UnsupportedError]. +/// Permitted operations defer to the wrapped set. +class UnmodifiableSetView extends DelegatingSet + with UnmodifiableSetMixin { + UnmodifiableSetView(Set setBase) : super(setBase); + + /// An unmodifiable empty set. + /// + /// This is the same as `new UnmodifiableSetView(new Set())`, except that it + /// can be used in const contexts. + const factory UnmodifiableSetView.empty() = EmptyUnmodifiableSet; +} + +/// Mixin class that implements a throwing version of all set operations that +/// change the Set. +abstract class UnmodifiableSetMixin implements Set { + static T _throw() { + throw new UnsupportedError("Cannot modify an unmodifiable Set"); + } + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + bool add(E value) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + void addAll(Iterable elements) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + bool remove(Object value) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + void removeAll(Iterable elements) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + void retainAll(Iterable elements) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + void removeWhere(bool test(E element)) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + void retainWhere(bool test(E element)) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the set are disallowed. + void clear() => _throw(); +} + +/// Mixin class that implements a throwing version of all map operations that +/// change the Map. +abstract class UnmodifiableMapMixin implements Map { + static T _throw() { + throw new UnsupportedError("Cannot modify an unmodifiable Map"); + } + + /// Throws an [UnsupportedError]; + /// operations that change the map are disallowed. + void operator []=(K key, V value) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the map are disallowed. + V putIfAbsent(K key, V ifAbsent()) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the map are disallowed. + void addAll(Map other) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the map are disallowed. + V remove(Object key) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the map are disallowed. + void clear() => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the map are disallowed. + set first(_) => _throw(); + + /// Throws an [UnsupportedError]; + /// operations that change the map are disallowed. + set last(_) => _throw(); +} +NN<&IF 6=<I+47#;O< <$D)$D!$D1$D1$D?$D)$D%$D$D6$D6$D4$DK$D?'=36#8!O%GN;E$5!$51$5)$51$51$56$56$5NAE$51$52$5,$5$$5$5$5bfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/wrappers.dartS// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:collection"; +import "dart:math" as math; + +import "unmodifiable_wrappers.dart"; + +typedef K _KeyForValue(V value); + +/// A base class for delegating iterables. +/// +/// Subclasses can provide a [_base] that should be delegated to. Unlike +/// [DelegatingIterable], this allows the base to be created on demand. +abstract class _DelegatingIterableBase implements Iterable { + Iterable get _base; + + const _DelegatingIterableBase(); + + bool any(bool test(E element)) => _base.any(test); + + Iterable cast() => _base.cast(); + + bool contains(Object element) => _base.contains(element); + + E elementAt(int index) => _base.elementAt(index); + + bool every(bool test(E element)) => _base.every(test); + + Iterable expand(Iterable f(E element)) => _base.expand(f); + + E get first => _base.first; + + E firstWhere(bool test(E element), {E orElse()}) => + _base.firstWhere(test, orElse: orElse); + + T fold(T initialValue, T combine(T previousValue, E element)) => + _base.fold(initialValue, combine); + + Iterable followedBy(Iterable other) => _base.followedBy(other); + + void forEach(void f(E element)) => _base.forEach(f); + + bool get isEmpty => _base.isEmpty; + + bool get isNotEmpty => _base.isNotEmpty; + + Iterator get iterator => _base.iterator; + + String join([String separator = ""]) => _base.join(separator); + + E get last => _base.last; + + E lastWhere(bool test(E element), {E orElse()}) => + _base.lastWhere(test, orElse: orElse); + + int get length => _base.length; + + Iterable map(T f(E element)) => _base.map(f); + + E reduce(E combine(E value, E element)) => _base.reduce(combine); + + @deprecated + Iterable retype() => cast(); + + E get single => _base.single; + + E singleWhere(bool test(E element), {E orElse()}) { + return _base.singleWhere(test, orElse: orElse); + } + + Iterable skip(int n) => _base.skip(n); + + Iterable skipWhile(bool test(E value)) => _base.skipWhile(test); + + Iterable take(int n) => _base.take(n); + + Iterable takeWhile(bool test(E value)) => _base.takeWhile(test); + + List toList({bool growable: true}) => _base.toList(growable: growable); + + Set toSet() => _base.toSet(); + + Iterable where(bool test(E element)) => _base.where(test); + + Iterable whereType() => _base.whereType(); + + String toString() => _base.toString(); +} + +/// An [Iterable] that delegates all operations to a base iterable. +/// +/// This class can be used to hide non-`Iterable` methods of an iterable object, +/// or it can be extended to add extra functionality on top of an existing +/// iterable object. +class DelegatingIterable extends _DelegatingIterableBase { + final Iterable _base; + + /// Creates a wrapper that forwards operations to [base]. + const DelegatingIterable(Iterable base) : _base = base; + + /// Creates a wrapper that asserts the types of values in [base]. + /// + /// This soundly converts an [Iterable] without a generic type to an + /// `Iterable` by asserting that its elements are instances of `E` whenever + /// they're accessed. If they're not, it throws a [CastError]. + /// + /// This forwards all operations to [base], so any changes in [base] will be + /// reflected in [this]. If [base] is already an `Iterable`, it's returned + /// unmodified. + @Deprecated('Use iterable.cast instead.') + static Iterable typed(Iterable base) => base.cast(); +} + +/// A [List] that delegates all operations to a base list. +/// +/// This class can be used to hide non-`List` methods of a list object, or it +/// can be extended to add extra functionality on top of an existing list +/// object. +class DelegatingList extends DelegatingIterable implements List { + const DelegatingList(List base) : super(base); + + /// Creates a wrapper that asserts the types of values in [base]. + /// + /// This soundly converts a [List] without a generic type to a `List` by + /// asserting that its elements are instances of `E` whenever they're + /// accessed. If they're not, it throws a [CastError]. Note that even if an + /// operation throws a [CastError], it may still mutate the underlying + /// collection. + /// + /// This forwards all operations to [base], so any changes in [base] will be + /// reflected in [this]. If [base] is already a `List`, it's returned + /// unmodified. + @Deprecated('Use list.cast instead.') + static List typed(List base) => base.cast(); + + List get _listBase => _base; + + E operator [](int index) => _listBase[index]; + + void operator []=(int index, E value) { + _listBase[index] = value; + } + + List operator +(List other) => _listBase + other; + + void add(E value) { + _listBase.add(value); + } + + void addAll(Iterable iterable) { + _listBase.addAll(iterable); + } + + Map asMap() => _listBase.asMap(); + + List cast() => _listBase.cast(); + + void clear() { + _listBase.clear(); + } + + void fillRange(int start, int end, [E fillValue]) { + _listBase.fillRange(start, end, fillValue); + } + + set first(E value) { + if (this.isEmpty) throw new RangeError.index(0, this); + this[0] = value; + } + + Iterable getRange(int start, int end) => _listBase.getRange(start, end); + + int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start); + + int indexWhere(bool test(E element), [int start = 0]) => + _listBase.indexWhere(test, start); + + void insert(int index, E element) { + _listBase.insert(index, element); + } + + insertAll(int index, Iterable iterable) { + _listBase.insertAll(index, iterable); + } + + set last(E value) { + if (this.isEmpty) throw new RangeError.index(0, this); + this[this.length - 1] = value; + } + + int lastIndexOf(E element, [int start]) => + _listBase.lastIndexOf(element, start); + + int lastIndexWhere(bool test(E element), [int start]) => + _listBase.lastIndexWhere(test, start); + + set length(int newLength) { + _listBase.length = newLength; + } + + bool remove(Object value) => _listBase.remove(value); + + E removeAt(int index) => _listBase.removeAt(index); + + E removeLast() => _listBase.removeLast(); + + void removeRange(int start, int end) { + _listBase.removeRange(start, end); + } + + void removeWhere(bool test(E element)) { + _listBase.removeWhere(test); + } + + void replaceRange(int start, int end, Iterable iterable) { + _listBase.replaceRange(start, end, iterable); + } + + void retainWhere(bool test(E element)) { + _listBase.retainWhere(test); + } + + @deprecated + List retype() => cast(); + + Iterable get reversed => _listBase.reversed; + + void setAll(int index, Iterable iterable) { + _listBase.setAll(index, iterable); + } + + void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { + _listBase.setRange(start, end, iterable, skipCount); + } + + void shuffle([math.Random random]) { + _listBase.shuffle(random); + } + + void sort([int compare(E a, E b)]) { + _listBase.sort(compare); + } + + List sublist(int start, [int end]) => _listBase.sublist(start, end); +} + +/// A [Set] that delegates all operations to a base set. +/// +/// This class can be used to hide non-`Set` methods of a set object, or it can +/// be extended to add extra functionality on top of an existing set object. +class DelegatingSet extends DelegatingIterable implements Set { + const DelegatingSet(Set base) : super(base); + + /// Creates a wrapper that asserts the types of values in [base]. + /// + /// This soundly converts a [Set] without a generic type to a `Set` by + /// asserting that its elements are instances of `E` whenever they're + /// accessed. If they're not, it throws a [CastError]. Note that even if an + /// operation throws a [CastError], it may still mutate the underlying + /// collection. + /// + /// This forwards all operations to [base], so any changes in [base] will be + /// reflected in [this]. If [base] is already a `Set`, it's returned + /// unmodified. + @Deprecated('Use set.cast instead.') + static Set typed(Set base) => base.cast(); + + Set get _setBase => _base; + + bool add(E value) => _setBase.add(value); + + void addAll(Iterable elements) { + _setBase.addAll(elements); + } + + Set cast() => _setBase.cast(); + + void clear() { + _setBase.clear(); + } + + bool containsAll(Iterable other) => _setBase.containsAll(other); + + Set difference(Set other) => _setBase.difference(other); + + Set intersection(Set other) => _setBase.intersection(other); + + E lookup(Object element) => _setBase.lookup(element); + + bool remove(Object value) => _setBase.remove(value); + + void removeAll(Iterable elements) { + _setBase.removeAll(elements); + } + + void removeWhere(bool test(E element)) { + _setBase.removeWhere(test); + } + + void retainAll(Iterable elements) { + _setBase.retainAll(elements); + } + + @deprecated + Set retype() => cast(); + + void retainWhere(bool test(E element)) { + _setBase.retainWhere(test); + } + + Set union(Set other) => _setBase.union(other); + + Set toSet() => new DelegatingSet(_setBase.toSet()); +} + +/// A [Queue] that delegates all operations to a base queue. +/// +/// This class can be used to hide non-`Queue` methods of a queue object, or it +/// can be extended to add extra functionality on top of an existing queue +/// object. +class DelegatingQueue extends DelegatingIterable implements Queue { + const DelegatingQueue(Queue queue) : super(queue); + + /// Creates a wrapper that asserts the types of values in [base]. + /// + /// This soundly converts a [Queue] without a generic type to a `Queue` by + /// asserting that its elements are instances of `E` whenever they're + /// accessed. If they're not, it throws a [CastError]. Note that even if an + /// operation throws a [CastError], it may still mutate the underlying + /// collection. + /// + /// This forwards all operations to [base], so any changes in [base] will be + /// reflected in [this]. If [base] is already a `Queue`, it's returned + /// unmodified. + @Deprecated('Use queue.cast instead.') + static Queue typed(Queue base) => base.cast(); + + Queue get _baseQueue => _base; + + void add(E value) { + _baseQueue.add(value); + } + + void addAll(Iterable iterable) { + _baseQueue.addAll(iterable); + } + + void addFirst(E value) { + _baseQueue.addFirst(value); + } + + void addLast(E value) { + _baseQueue.addLast(value); + } + + Queue cast() => _baseQueue.cast(); + + void clear() { + _baseQueue.clear(); + } + + bool remove(Object object) => _baseQueue.remove(object); + + void removeWhere(bool test(E element)) { + _baseQueue.removeWhere(test); + } + + void retainWhere(bool test(E element)) { + _baseQueue.retainWhere(test); + } + + @deprecated + Queue retype() => cast(); + + E removeFirst() => _baseQueue.removeFirst(); + + E removeLast() => _baseQueue.removeLast(); +} + +/// A [Map] that delegates all operations to a base map. +/// +/// This class can be used to hide non-`Map` methods of an object that extends +/// `Map`, or it can be extended to add extra functionality on top of an +/// existing map object. +class DelegatingMap implements Map { + final Map _base; + + const DelegatingMap(Map base) : _base = base; + + /// Creates a wrapper that asserts the types of keys and values in [base]. + /// + /// This soundly converts a [Map] without generic types to a `Map` by + /// asserting that its keys are instances of `E` and its values are instances + /// of `V` whenever they're accessed. If they're not, it throws a [CastError]. + /// Note that even if an operation throws a [CastError], it may still mutate + /// the underlying collection. + /// + /// This forwards all operations to [base], so any changes in [base] will be + /// reflected in [this]. If [base] is already a `Map`, it's returned + /// unmodified. + @Deprecated('Use map.cast instead.') + static Map typed(Map base) => base.cast(); + + V operator [](Object key) => _base[key]; + + void operator []=(K key, V value) { + _base[key] = value; + } + + void addAll(Map other) { + _base.addAll(other); + } + + void addEntries(Iterable> entries) { + _base.addEntries(entries); + } + + void clear() { + _base.clear(); + } + + Map cast() => _base.cast(); + + bool containsKey(Object key) => _base.containsKey(key); + + bool containsValue(Object value) => _base.containsValue(value); + + Iterable> get entries => _base.entries; + + void forEach(void f(K key, V value)) { + _base.forEach(f); + } + + bool get isEmpty => _base.isEmpty; + + bool get isNotEmpty => _base.isNotEmpty; + + Iterable get keys => _base.keys; + + int get length => _base.length; + + Map map(MapEntry transform(K key, V value)) => + _base.map(transform); + + V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent); + + V remove(Object key) => _base.remove(key); + + void removeWhere(bool test(K key, V value)) => _base.removeWhere(test); + + @deprecated + Map retype() => cast(); + + Iterable get values => _base.values; + + String toString() => _base.toString(); + + V update(K key, V update(V value), {V ifAbsent()}) => + _base.update(key, update, ifAbsent: ifAbsent); + + void updateAll(V update(K key, V value)) => _base.updateAll(update); +} + +/// An unmodifiable [Set] view of the keys of a [Map]. +/// +/// The set delegates all operations to the underlying map. +/// +/// A `Map` can only contain each key once, so its keys can always +/// be viewed as a `Set` without any loss, even if the [Map.keys] +/// getter only shows an [Iterable] view of the keys. +/// +/// Note that [lookup] is not supported for this set. +class MapKeySet extends _DelegatingIterableBase + with UnmodifiableSetMixin { + final Map _baseMap; + + MapKeySet(Map base) : _baseMap = base; + + Iterable get _base => _baseMap.keys; + + Set cast() { + if (this is MapKeySet) { + return this as MapKeySet; + } + return Set.castFrom(this); + } + + bool contains(Object element) => _baseMap.containsKey(element); + + bool get isEmpty => _baseMap.isEmpty; + + bool get isNotEmpty => _baseMap.isNotEmpty; + + int get length => _baseMap.length; + + String toString() => "{${_base.join(', ')}}"; + + bool containsAll(Iterable other) => other.every(contains); + + /// Returns a new set with the the elements of [this] that are not in [other]. + /// + /// That is, the returned set contains all the elements of this [Set] that are + /// not elements of [other] according to `other.contains`. + /// + /// Note that the returned set will use the default equality operation, which + /// may be different than the equality operation [this] uses. + Set difference(Set other) => + where((element) => !other.contains(element)).toSet(); + + /// Returns a new set which is the intersection between [this] and [other]. + /// + /// That is, the returned set contains all the elements of this [Set] that are + /// also elements of [other] according to `other.contains`. + /// + /// Note that the returned set will use the default equality operation, which + /// may be different than the equality operation [this] uses. + Set intersection(Set other) => where(other.contains).toSet(); + + /// Throws an [UnsupportedError] since there's no corresponding method for + /// [Map]s. + E lookup(Object element) => + throw new UnsupportedError("MapKeySet doesn't support lookup()."); + + @deprecated + Set retype() => Set.castFrom(this); + + /// Returns a new set which contains all the elements of [this] and [other]. + /// + /// That is, the returned set contains all the elements of this [Set] and all + /// the elements of [other]. + /// + /// Note that the returned set will use the default equality operation, which + /// may be different than the equality operation [this] uses. + Set union(Set other) => toSet()..addAll(other); +} + +/// Creates a modifiable [Set] view of the values of a [Map]. +/// +/// The `Set` view assumes that the keys of the `Map` can be uniquely determined +/// from the values. The `keyForValue` function passed to the constructor finds +/// the key for a single value. The `keyForValue` function should be consistent +/// with equality. If `value1 == value2` then `keyForValue(value1)` and +/// `keyForValue(value2)` should be considered equal keys by the underlying map, +/// and vice versa. +/// +/// Modifying the set will modify the underlying map based on the key returned +/// by `keyForValue`. +/// +/// If the `Map` contents are not compatible with the `keyForValue` function, +/// the set will not work consistently, and may give meaningless responses or do +/// inconsistent updates. +/// +/// This set can, for example, be used on a map from database record IDs to the +/// records. It exposes the records as a set, and allows for writing both +/// `recordSet.add(databaseRecord)` and `recordMap[id]`. +/// +/// Effectively, the map will act as a kind of index for the set. +class MapValueSet extends _DelegatingIterableBase implements Set { + final Map _baseMap; + final _KeyForValue _keyForValue; + + /// Creates a new [MapValueSet] based on [base]. + /// + /// [keyForValue] returns the key in the map that should be associated with + /// the given value. The set's notion of equality is identical to the equality + /// of the return values of [keyForValue]. + MapValueSet(Map base, K keyForValue(V value)) + : _baseMap = base, + _keyForValue = keyForValue; + + Iterable get _base => _baseMap.values; + + Set cast() { + if (this is Set) { + return this as Set; + } + return Set.castFrom(this); + } + + bool contains(Object element) { + if (element != null && element is! V) return false; + var key = _keyForValue(element as V); + + return _baseMap.containsKey(key); + } + + bool get isEmpty => _baseMap.isEmpty; + + bool get isNotEmpty => _baseMap.isNotEmpty; + + int get length => _baseMap.length; + + String toString() => toSet().toString(); + + bool add(V value) { + K key = _keyForValue(value); + bool result = false; + _baseMap.putIfAbsent(key, () { + result = true; + return value; + }); + return result; + } + + void addAll(Iterable elements) => elements.forEach(add); + + void clear() => _baseMap.clear(); + + bool containsAll(Iterable other) => other.every(contains); + + /// Returns a new set with the the elements of [this] that are not in [other]. + /// + /// That is, the returned set contains all the elements of this [Set] that are + /// not elements of [other] according to `other.contains`. + /// + /// Note that the returned set will use the default equality operation, which + /// may be different than the equality operation [this] uses. + Set difference(Set other) => + where((element) => !other.contains(element)).toSet(); + + /// Returns a new set which is the intersection between [this] and [other]. + /// + /// That is, the returned set contains all the elements of this [Set] that are + /// also elements of [other] according to `other.contains`. + /// + /// Note that the returned set will use the default equality operation, which + /// may be different than the equality operation [this] uses. + Set intersection(Set other) => where(other.contains).toSet(); + + V lookup(Object element) { + if (element != null && element is! V) return null; + var key = _keyForValue(element as V); + + return _baseMap[key]; + } + + bool remove(Object element) { + if (element != null && element is! V) return false; + var key = _keyForValue(element as V); + + if (!_baseMap.containsKey(key)) return false; + _baseMap.remove(key); + return true; + } + + void removeAll(Iterable elements) => elements.forEach(remove); + + void removeWhere(bool test(V element)) { + var toRemove = []; + _baseMap.forEach((key, value) { + if (test(value)) toRemove.add(key); + }); + toRemove.forEach(_baseMap.remove); + } + + void retainAll(Iterable elements) { + var valuesToRetain = new Set.identity(); + for (var element in elements) { + if (element != null && element is! V) continue; + var key = _keyForValue(element as V); + + if (!_baseMap.containsKey(key)) continue; + valuesToRetain.add(_baseMap[key]); + } + + var keysToRemove = []; + _baseMap.forEach((k, v) { + if (!valuesToRetain.contains(v)) keysToRemove.add(k); + }); + keysToRemove.forEach(_baseMap.remove); + } + + void retainWhere(bool test(V element)) => + removeWhere((element) => !test(element)); + + @deprecated + Set retype() => Set.castFrom(this); + + /// Returns a new set which contains all the elements of [this] and [other]. + /// + /// That is, the returned set contains all the elements of this [Set] and all + /// the elements of [other]. + /// + /// Note that the returned set will use the default equality operation, which + /// may be different than the equality operation [this] uses. + Set union(Set other) => toSet()..addAll(other); +} +NN<%'+IHC#5,<49F6.F)H7%+.A5-"6D( 64,F,FM#@6)DQKA<=DGQAOP/@;NJ K4DNHNIOK+8"0*:& ,,60;NP;)&&/*;#--;-"86,)'+!@2+!$21'Q9''J9PMI2DLHNIOJ*6 ,&*KFJ87."+ ."#+ 7<=PK M8DPHNIOL,:$&! .;+"+"%/-9OI16MNPQO!OM-?+&!66:B9)%+&"IJ-J2*)85G7<CB666#"5* #%B(.%0EQQ=P@*<NQ>P@KMI2OPP@8>QPPHQONQPJ9BO)3NQ-6$,%"8*&(.%+!#>$EQQ=P@*<NQ>P@K7* 8*2I+$*'.0$6,0)<+,02OPP@8Wfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.2/lib/ascii.dart)// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Declare integer constants for each ASCII character. +/// +/// The constants all start with "$" to avoid conflicting with other constants. +/// +/// For characters that are valid in an identifier, the character itself +/// follows the "$". For other characters, a symbolic name is used. +/// In some cases, multiple alternative symbolic names are provided. +/// Please stick to using one name per character in your code. +/// +/// The symbolic names are, where applicable, the name of the symbol without +/// any "mark", "symbol" "sign" or "accent" suffix. +/// Examples: [$exclamation], [$pipe], [$dollar] and [$grave]. +/// For less common symbols, a selection of common names are used. +/// +/// For parenthetical markers, there is both a short name, [$lparen]/[$rparen], +/// and a long name, [$open_paren]/ [$close_paren]. +/// +/// For common HTML entities, the entity names are also usable as symbolic +/// names: [$apos], [$quot], [$lt], [$gt], and [$amp]. +library charcode.ascii.dollar_lowercase; + +// Control characters. + +/// "Null character" control character. +const int $nul = 0x00; + +/// "Start of Header" control character. +const int $soh = 0x01; + +/// "Start of Text" control character. +const int $stx = 0x02; + +/// "End of Text" control character. +const int $etx = 0x03; + +/// "End of Transmission" control character. +const int $eot = 0x04; + +/// "Enquiry" control character. +const int $enq = 0x05; + +/// "Acknowledgment" control character. +const int $ack = 0x06; + +/// "Bell" control character. +const int $bel = 0x07; + +/// "Backspace" control character. +const int $bs = 0x08; + +/// "Horizontal Tab" control character. +const int $ht = 0x09; + +/// "Horizontal Tab" control character, common name. +const int $tab = 0x09; + +/// "Line feed" control character. +const int $lf = 0x0A; + +/// "Vertical Tab" control character. +const int $vt = 0x0B; + +/// "Form feed" control character. +const int $ff = 0x0C; + +/// "Carriage return" control character. +const int $cr = 0x0D; + +/// "Shift Out" control character. +const int $so = 0x0E; + +/// "Shift In" control character. +const int $si = 0x0F; + +/// "Data Link Escape" control character. +const int $dle = 0x10; + +/// "Device Control 1" control character (oft. XON). +const int $dc1 = 0x11; + +/// "Device Control 2" control character. +const int $dc2 = 0x12; + +/// "Device Control 3" control character (oft. XOFF). +const int $dc3 = 0x13; + +/// "Device Control 4" control character. +const int $dc4 = 0x14; + +/// "Negative Acknowledgment" control character. +const int $nak = 0x15; + +/// "Synchronous idle" control character. +const int $syn = 0x16; + +/// "End of Transmission Block" control character. +const int $etb = 0x17; + +/// "Cancel" control character. +const int $can = 0x18; + +/// "End of Medium" control character. +const int $em = 0x19; + +/// "Substitute" control character. +const int $sub = 0x1A; + +/// "Escape" control character. +const int $esc = 0x1B; + +/// "File Separator" control character. +const int $fs = 0x1C; + +/// "Group Separator" control character. +const int $gs = 0x1D; + +/// "Record Separator" control character. +const int $rs = 0x1E; + +/// "Unit Separator" control character. +const int $us = 0x1F; + +/// "Delete" control character. +const int $del = 0x7F; + +// Visible characters. + +/// Space character. +const int $space = 0x20; + +/// Character '!'. +const int $exclamation = 0x21; + +/// Character '"', short name. +const int $quot = 0x22; + +/// Character '"'. +const int $quote = 0x22; + +/// Character '"'. +const int $double_quote = 0x22; + +/// Character '"'. +const int $quotation = 0x22; + +/// Character '#'. +const int $hash = 0x23; + +/// Character '$'. +const int $$ = 0x24; + +/// Character '$'. +const int $dollar = 0x24; + +/// Character '%'. +const int $percent = 0x25; + +/// Character '&', short name. +const int $amp = 0x26; + +/// Character '&'. +const int $ampersand = 0x26; + +/// Character "'". +const int $apos = 0x27; + +/// Character '''. +const int $apostrophe = 0x27; + +/// Character '''. +const int $single_quote = 0x27; + +/// Character '('. +const int $lparen = 0x28; + +/// Character '('. +const int $open_paren = 0x28; + +/// Character '('. +const int $open_parenthesis = 0x28; + +/// Character ')'. +const int $rparen = 0x29; + +/// Character ')'. +const int $close_paren = 0x29; + +/// Character ')'. +const int $close_parenthesis = 0x29; + +/// Character '*'. +const int $asterisk = 0x2A; + +/// Character '+'. +const int $plus = 0x2B; + +/// Character ','. +const int $comma = 0x2C; + +/// Character '-'. +const int $minus = 0x2D; + +/// Character '-'. +const int $dash = 0x2D; + +/// Character '.'. +const int $dot = 0x2E; + +/// Character '.'. +const int $fullstop = 0x2E; + +/// Character '/'. +const int $slash = 0x2F; + +/// Character '/'. +const int $solidus = 0x2F; + +/// Character '/'. +const int $division = 0x2F; + +/// Character '0'. +const int $0 = 0x30; + +/// Character '1'. +const int $1 = 0x31; + +/// Character '2'. +const int $2 = 0x32; + +/// Character '3'. +const int $3 = 0x33; + +/// Character '4'. +const int $4 = 0x34; + +/// Character '5'. +const int $5 = 0x35; + +/// Character '6'. +const int $6 = 0x36; + +/// Character '7'. +const int $7 = 0x37; + +/// Character '8'. +const int $8 = 0x38; + +/// Character '9'. +const int $9 = 0x39; + +/// Character ':'. +const int $colon = 0x3A; + +/// Character ';'. +const int $semicolon = 0x3B; + +/// Character '<'. +const int $lt = 0x3C; + +/// Character '<'. +const int $less_than = 0x3C; + +/// Character '<'. +const int $langle = 0x3C; + +/// Character '<'. +const int $open_angle = 0x3C; + +/// Character '='. +const int $equal = 0x3D; + +/// Character '>'. +const int $gt = 0x3E; + +/// Character '>'. +const int $greater_than = 0x3E; + +/// Character '>'. +const int $rangle = 0x3E; + +/// Character '>'. +const int $close_angle = 0x3E; + +/// Character '?'. +const int $question = 0x3F; + +/// Character '@'. +const int $at = 0x40; + +/// Character 'A'. +const int $A = 0x41; + +/// Character 'B'. +const int $B = 0x42; + +/// Character 'C'. +const int $C = 0x43; + +/// Character 'D'. +const int $D = 0x44; + +/// Character 'E'. +const int $E = 0x45; + +/// Character 'F'. +const int $F = 0x46; + +/// Character 'G'. +const int $G = 0x47; + +/// Character 'H'. +const int $H = 0x48; + +/// Character 'I'. +const int $I = 0x49; + +/// Character 'J'. +const int $J = 0x4A; + +/// Character 'K'. +const int $K = 0x4B; + +/// Character 'L'. +const int $L = 0x4C; + +/// Character 'M'. +const int $M = 0x4D; + +/// Character 'N'. +const int $N = 0x4E; + +/// Character 'O'. +const int $O = 0x4F; + +/// Character 'P'. +const int $P = 0x50; + +/// Character 'Q'. +const int $Q = 0x51; + +/// Character 'R'. +const int $R = 0x52; + +/// Character 'S'. +const int $S = 0x53; + +/// Character 'T'. +const int $T = 0x54; + +/// Character 'U'. +const int $U = 0x55; + +/// Character 'V'. +const int $V = 0x56; + +/// Character 'W'. +const int $W = 0x57; + +/// Character 'X'. +const int $X = 0x58; + +/// Character 'Y'. +const int $Y = 0x59; + +/// Character 'Z'. +const int $Z = 0x5A; + +/// Character '['. +const int $lbracket = 0x5B; + +/// Character '['. +const int $open_bracket = 0x5B; + +/// Character '\'. +const int $backslash = 0x5C; + +/// Character ']'. +const int $rbracket = 0x5D; + +/// Character ']'. +const int $close_bracket = 0x5D; + +/// Character '^'. +const int $circumflex = 0x5E; + +/// Character '^'. +const int $caret = 0x5E; + +/// Character '^'. +const int $hat = 0x5E; + +/// Character '_'. +const int $_ = 0x5F; + +/// Character '_'. +const int $underscore = 0x5F; + +/// Character '_'. +const int $underline = 0x5F; + +/// Character '`'. +const int $backquote = 0x60; + +/// Character '`'. +const int $grave = 0x60; + +/// Character 'a'. +const int $a = 0x61; + +/// Character 'b'. +const int $b = 0x62; + +/// Character 'c'. +const int $c = 0x63; + +/// Character 'd'. +const int $d = 0x64; + +/// Character 'e'. +const int $e = 0x65; + +/// Character 'f'. +const int $f = 0x66; + +/// Character 'g'. +const int $g = 0x67; + +/// Character 'h'. +const int $h = 0x68; + +/// Character 'i'. +const int $i = 0x69; + +/// Character 'j'. +const int $j = 0x6A; + +/// Character 'k'. +const int $k = 0x6B; + +/// Character 'l'. +const int $l = 0x6C; + +/// Character 'm'. +const int $m = 0x6D; + +/// Character 'n'. +const int $n = 0x6E; + +/// Character 'o'. +const int $o = 0x6F; + +/// Character 'p'. +const int $p = 0x70; + +/// Character 'q'. +const int $q = 0x71; + +/// Character 'r'. +const int $r = 0x72; + +/// Character 's'. +const int $s = 0x73; + +/// Character 't'. +const int $t = 0x74; + +/// Character 'u'. +const int $u = 0x75; + +/// Character 'v'. +const int $v = 0x76; + +/// Character 'w'. +const int $w = 0x77; + +/// Character 'x'. +const int $x = 0x78; + +/// Character 'y'. +const int $y = 0x79; + +/// Character 'z'. +const int $z = 0x7A; + +/// Character '{'. +const int $lbrace = 0x7B; + +/// Character '{'. +const int $open_brace = 0x7B; + +/// Character '|'. +const int $pipe = 0x7C; + +/// Character '|'. +const int $bar = 0x7C; + +/// Character '}'. +const int $rbrace = 0x7D; + +/// Character '}'. +const int $close_brace = 0x7D; + +/// Character '~'. +const int $tilde = 0x7E; +NI<8PIDE?M4?CP4K7)()'%-!(#(5#&#)#"*5*6*1*3 '$ ()*(   $%  !]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.2/lib/html_entity.dartE// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Character codes based on HTML 4.01 character entity names. +/// +/// For each entity name, e.g., `nbsp`, +/// a constant with that name prefixed by `$` is defined +/// for that entity's code point. +/// +/// The HTML entities include the non-ASCII Latin-1 characters and +/// symbols, mathematical symbols and Greek litters. +/// +/// The five characters that are ASCII +/// are exported from the `ascii.dart` library. +/// +/// Three names conflict with `ascii.dart`: `$minus`, `$sub` and `$tilde`. +/// If importing both libraries, these three should be hidden from one of the +/// libraries. +library charcode.htmlentity.dollar_lowercase; + +export "ascii.dart" show $quot, $amp, $apos, $lt, $gt; + +/// no-break space (non-breaking space) +const int $nbsp = 0x00A0; + +/// inverted exclamation mark ('¡') +const int $iexcl = 0x00A1; + +/// cent sign ('¢') +const int $cent = 0x00A2; + +/// pound sign ('£') +const int $pound = 0x00A3; + +/// currency sign ('¤') +const int $curren = 0x00A4; + +/// yen sign (yuan sign) ('¥') +const int $yen = 0x00A5; + +/// broken bar (broken vertical bar) ('¦') +const int $brvbar = 0x00A6; + +/// section sign ('§') +const int $sect = 0x00A7; + +/// diaeresis (spacing diaeresis); see Germanic umlaut ('¨') +const int $uml = 0x00A8; + +/// copyright symbol ('©') +const int $copy = 0x00A9; + +/// feminine ordinal indicator ('ª') +const int $ordf = 0x00AA; + +/// left-pointing double angle quotation mark (left pointing guillemet) ('«') +const int $laquo = 0x00AB; + +/// not sign ('¬') +const int $not = 0x00AC; + +/// soft hyphen (discretionary hyphen) +const int $shy = 0x00AD; + +/// registered sign (registered trademark symbol) ('®') +const int $reg = 0x00AE; + +/// macron (spacing macron, overline, APL overbar) ('¯') +const int $macr = 0x00AF; + +/// degree symbol ('°') +const int $deg = 0x00B0; + +/// plus-minus sign (plus-or-minus sign) ('±') +const int $plusmn = 0x00B1; + +/// superscript two (superscript digit two, squared) ('²') +const int $sup2 = 0x00B2; + +/// superscript three (superscript digit three, cubed) ('³') +const int $sup3 = 0x00B3; + +/// acute accent (spacing acute) ('´') +const int $acute = 0x00B4; + +/// micro sign ('µ') +const int $micro = 0x00B5; + +/// pilcrow sign (paragraph sign) ('¶') +const int $para = 0x00B6; + +/// middle dot (Georgian comma, Greek middle dot) ('·') +const int $middot = 0x00B7; + +/// cedilla (spacing cedilla) ('¸') +const int $cedil = 0x00B8; + +/// superscript one (superscript digit one) ('¹') +const int $sup1 = 0x00B9; + +/// masculine ordinal indicator ('º') +const int $ordm = 0x00BA; + +/// right-pointing double angle quotation mark (right pointing guillemet) ('»') +const int $raquo = 0x00BB; + +/// vulgar fraction one quarter (fraction one quarter) ('¼') +const int $frac14 = 0x00BC; + +/// vulgar fraction one half (fraction one half) ('½') +const int $frac12 = 0x00BD; + +/// vulgar fraction three quarters (fraction three quarters) ('¾') +const int $frac34 = 0x00BE; + +/// inverted question mark (turned question mark) ('¿') +const int $iquest = 0x00BF; + +/// Latin capital letter A with grave accent (Latin capital letter A grave) ('À') +const int $Agrave = 0x00C0; + +/// Latin capital letter A with acute accent ('Á') +const int $Aacute = 0x00C1; + +/// Latin capital letter A with circumflex ('Â') +const int $Acirc = 0x00C2; + +/// Latin capital letter A with tilde ('Ã') +const int $Atilde = 0x00C3; + +/// Latin capital letter A with diaeresis ('Ä') +const int $Auml = 0x00C4; + +/// Latin capital letter A with ring above (Latin capital letter A ring) ('Å') +const int $Aring = 0x00C5; + +/// Latin capital letter AE (Latin capital ligature AE) ('Æ') +const int $AElig = 0x00C6; + +/// Latin capital letter C with cedilla ('Ç') +const int $Ccedil = 0x00C7; + +/// Latin capital letter E with grave accent ('È') +const int $Egrave = 0x00C8; + +/// Latin capital letter E with acute accent ('É') +const int $Eacute = 0x00C9; + +/// Latin capital letter E with circumflex ('Ê') +const int $Ecirc = 0x00CA; + +/// Latin capital letter E with diaeresis ('Ë') +const int $Euml = 0x00CB; + +/// Latin capital letter I with grave accent ('Ì') +const int $Igrave = 0x00CC; + +/// Latin capital letter I with acute accent ('Í') +const int $Iacute = 0x00CD; + +/// Latin capital letter I with circumflex ('Î') +const int $Icirc = 0x00CE; + +/// Latin capital letter I with diaeresis ('Ï') +const int $Iuml = 0x00CF; + +/// Latin capital letter Eth ('Ð') +const int $ETH = 0x00D0; + +/// Latin capital letter N with tilde ('Ñ') +const int $Ntilde = 0x00D1; + +/// Latin capital letter O with grave accent ('Ò') +const int $Ograve = 0x00D2; + +/// Latin capital letter O with acute accent ('Ó') +const int $Oacute = 0x00D3; + +/// Latin capital letter O with circumflex ('Ô') +const int $Ocirc = 0x00D4; + +/// Latin capital letter O with tilde ('Õ') +const int $Otilde = 0x00D5; + +/// Latin capital letter O with diaeresis ('Ö') +const int $Ouml = 0x00D6; + +/// multiplication sign ('×') +const int $times = 0x00D7; + +/// Latin capital letter O with stroke (Latin capital letter O slash) ('Ø') +const int $Oslash = 0x00D8; + +/// Latin capital letter U with grave accent ('Ù') +const int $Ugrave = 0x00D9; + +/// Latin capital letter U with acute accent ('Ú') +const int $Uacute = 0x00DA; + +/// Latin capital letter U with circumflex ('Û') +const int $Ucirc = 0x00DB; + +/// Latin capital letter U with diaeresis ('Ü') +const int $Uuml = 0x00DC; + +/// Latin capital letter Y with acute accent ('Ý') +const int $Yacute = 0x00DD; + +/// Latin capital letter THORN ('Þ') +const int $THORN = 0x00DE; + +/// Latin small letter sharp s (ess-zed); see German Eszett ('ß') +const int $szlig = 0x00DF; + +/// Latin small letter a with grave accent ('à') +const int $agrave = 0x00E0; + +/// Latin small letter a with acute accent ('á') +const int $aacute = 0x00E1; + +/// Latin small letter a with circumflex ('â') +const int $acirc = 0x00E2; + +/// Latin small letter a with tilde ('ã') +const int $atilde = 0x00E3; + +/// Latin small letter a with diaeresis ('ä') +const int $auml = 0x00E4; + +/// Latin small letter a with ring above ('å') +const int $aring = 0x00E5; + +/// Latin small letter ae (Latin small ligature ae) ('æ') +const int $aelig = 0x00E6; + +/// Latin small letter c with cedilla ('ç') +const int $ccedil = 0x00E7; + +/// Latin small letter e with grave accent ('è') +const int $egrave = 0x00E8; + +/// Latin small letter e with acute accent ('é') +const int $eacute = 0x00E9; + +/// Latin small letter e with circumflex ('ê') +const int $ecirc = 0x00EA; + +/// Latin small letter e with diaeresis ('ë') +const int $euml = 0x00EB; + +/// Latin small letter i with grave accent ('ì') +const int $igrave = 0x00EC; + +/// Latin small letter i with acute accent ('í') +const int $iacute = 0x00ED; + +/// Latin small letter i with circumflex ('î') +const int $icirc = 0x00EE; + +/// Latin small letter i with diaeresis ('ï') +const int $iuml = 0x00EF; + +/// Latin small letter eth ('ð') +const int $eth = 0x00F0; + +/// Latin small letter n with tilde ('ñ') +const int $ntilde = 0x00F1; + +/// Latin small letter o with grave accent ('ò') +const int $ograve = 0x00F2; + +/// Latin small letter o with acute accent ('ó') +const int $oacute = 0x00F3; + +/// Latin small letter o with circumflex ('ô') +const int $ocirc = 0x00F4; + +/// Latin small letter o with tilde ('õ') +const int $otilde = 0x00F5; + +/// Latin small letter o with diaeresis ('ö') +const int $ouml = 0x00F6; + +/// division sign (obelus) ('÷') +const int $divide = 0x00F7; + +/// Latin small letter o with stroke (Latin small letter o slash) ('ø') +const int $oslash = 0x00F8; + +/// Latin small letter u with grave accent ('ù') +const int $ugrave = 0x00F9; + +/// Latin small letter u with acute accent ('ú') +const int $uacute = 0x00FA; + +/// Latin small letter u with circumflex ('û') +const int $ucirc = 0x00FB; + +/// Latin small letter u with diaeresis ('ü') +const int $uuml = 0x00FC; + +/// Latin small letter y with acute accent ('ý') +const int $yacute = 0x00FD; + +/// Latin small letter thorn ('þ') +const int $thorn = 0x00FE; + +/// Latin small letter y with diaeresis ('ÿ') +const int $yuml = 0x00FF; + +/// Latin capital ligature oe ('Œ') +const int $OElig = 0x0152; + +/// Latin small ligature oe ('œ') +const int $oelig = 0x0153; + +/// Latin capital letter s with caron ('Š') +const int $Scaron = 0x0160; + +/// Latin small letter s with caron ('š') +const int $scaron = 0x0161; + +/// Latin capital letter y with diaeresis ('Ÿ') +const int $Yuml = 0x0178; + +/// Latin small letter f with hook (function, florin) ('ƒ') +const int $fnof = 0x0192; + +/// modifier letter circumflex accent ('ˆ') +const int $circ = 0x02C6; + +/// small tilde ('˜') +const int $tilde = 0x02DC; + +/// Greek capital letter Alpha ('Α') +const int $Alpha = 0x0391; + +/// Greek capital letter Beta ('Β') +const int $Beta = 0x0392; + +/// Greek capital letter Gamma ('Γ') +const int $Gamma = 0x0393; + +/// Greek capital letter Delta ('Δ') +const int $Delta = 0x0394; + +/// Greek capital letter Epsilon ('Ε') +const int $Epsilon = 0x0395; + +/// Greek capital letter Zeta ('Ζ') +const int $Zeta = 0x0396; + +/// Greek capital letter Eta ('Η') +const int $Eta = 0x0397; + +/// Greek capital letter Theta ('Θ') +const int $Theta = 0x0398; + +/// Greek capital letter Iota ('Ι') +const int $Iota = 0x0399; + +/// Greek capital letter Kappa ('Κ') +const int $Kappa = 0x039A; + +/// Greek capital letter Lambda ('Λ') +const int $Lambda = 0x039B; + +/// Greek capital letter Mu ('Μ') +const int $Mu = 0x039C; + +/// Greek capital letter Nu ('Ν') +const int $Nu = 0x039D; + +/// Greek capital letter Xi ('Ξ') +const int $Xi = 0x039E; + +/// Greek capital letter Omicron ('Ο') +const int $Omicron = 0x039F; + +/// Greek capital letter Pi ('Π') +const int $Pi = 0x03A0; + +/// Greek capital letter Rho ('Ρ') +const int $Rho = 0x03A1; + +/// Greek capital letter Sigma ('Σ') +const int $Sigma = 0x03A3; + +/// Greek capital letter Tau ('Τ') +const int $Tau = 0x03A4; + +/// Greek capital letter Upsilon ('Υ') +const int $Upsilon = 0x03A5; + +/// Greek capital letter Phi ('Φ') +const int $Phi = 0x03A6; + +/// Greek capital letter Chi ('Χ') +const int $Chi = 0x03A7; + +/// Greek capital letter Psi ('Ψ') +const int $Psi = 0x03A8; + +/// Greek capital letter Omega ('Ω') +const int $Omega = 0x03A9; + +/// Greek small letter alpha ('α') +const int $alpha = 0x03B1; + +/// Greek small letter beta ('β') +const int $beta = 0x03B2; + +/// Greek small letter gamma ('γ') +const int $gamma = 0x03B3; + +/// Greek small letter delta ('δ') +const int $delta = 0x03B4; + +/// Greek small letter epsilon ('ε') +const int $epsilon = 0x03B5; + +/// Greek small letter zeta ('ζ') +const int $zeta = 0x03B6; + +/// Greek small letter eta ('η') +const int $eta = 0x03B7; + +/// Greek small letter theta ('θ') +const int $theta = 0x03B8; + +/// Greek small letter iota ('ι') +const int $iota = 0x03B9; + +/// Greek small letter kappa ('κ') +const int $kappa = 0x03BA; + +/// Greek small letter lambda ('λ') +const int $lambda = 0x03BB; + +/// Greek small letter mu ('μ') +const int $mu = 0x03BC; + +/// Greek small letter nu ('ν') +const int $nu = 0x03BD; + +/// Greek small letter xi ('ξ') +const int $xi = 0x03BE; + +/// Greek small letter omicron ('ο') +const int $omicron = 0x03BF; + +/// Greek small letter pi ('π') +const int $pi = 0x03C0; + +/// Greek small letter rho ('ρ') +const int $rho = 0x03C1; + +/// Greek small letter final sigma ('ς') +const int $sigmaf = 0x03C2; + +/// Greek small letter sigma ('σ') +const int $sigma = 0x03C3; + +/// Greek small letter tau ('τ') +const int $tau = 0x03C4; + +/// Greek small letter upsilon ('υ') +const int $upsilon = 0x03C5; + +/// Greek small letter phi ('φ') +const int $phi = 0x03C6; + +/// Greek small letter chi ('χ') +const int $chi = 0x03C7; + +/// Greek small letter psi ('ψ') +const int $psi = 0x03C8; + +/// Greek small letter omega ('ω') +const int $omega = 0x03C9; + +/// Greek theta symbol ('ϑ') +const int $thetasym = 0x03D1; + +/// Greek Upsilon with hook symbol ('ϒ') +const int $upsih = 0x03D2; + +/// Greek pi symbol ('ϖ') +const int $piv = 0x03D6; + +/// en space +const int $ensp = 0x2002; + +/// em space +const int $emsp = 0x2003; + +/// thin space +const int $thinsp = 0x2009; + +/// zero-width non-joiner +const int $zwnj = 0x200C; + +/// zero-width joiner +const int $zwj = 0x200D; + +/// left-to-right mark +const int $lrm = 0x200E; + +/// right-to-left mark +const int $rlm = 0x200F; + +/// en dash ('–') +const int $ndash = 0x2013; + +/// em dash ('—') +const int $mdash = 0x2014; + +/// left single quotation mark ('‘') +const int $lsquo = 0x2018; + +/// right single quotation mark ('’') +const int $rsquo = 0x2019; + +/// single low-9 quotation mark ('‚') +const int $sbquo = 0x201A; + +/// left double quotation mark ('“') +const int $ldquo = 0x201C; + +/// right double quotation mark ('”') +const int $rdquo = 0x201D; + +/// double low-9 quotation mark ('„') +const int $bdquo = 0x201E; + +/// dagger, obelisk ('†') +const int $dagger = 0x2020; + +/// double dagger, double obelisk ('‡') +const int $Dagger = 0x2021; + +/// bullet (black small circle) ('•') +const int $bull = 0x2022; + +/// horizontal ellipsis (three dot leader) ('…') +const int $hellip = 0x2026; + +/// per mille sign ('‰') +const int $permil = 0x2030; + +/// prime (minutes, feet) ('′') +const int $prime = 0x2032; + +/// double prime (seconds, inches) ('″') +const int $Prime = 0x2033; + +/// single left-pointing angle quotation mark ('‹') +const int $lsaquo = 0x2039; + +/// single right-pointing angle quotation mark ('›') +const int $rsaquo = 0x203A; + +/// overline (spacing overscore) ('‾') +const int $oline = 0x203E; + +/// fraction slash (solidus) ('⁄') +const int $frasl = 0x2044; + +/// euro sign ('€') +const int $euro = 0x20AC; + +/// black-letter capital I (imaginary part) ('ℑ') +const int $image = 0x2111; + +/// script capital P (power set, Weierstrass p) ('℘') +const int $weierp = 0x2118; + +/// black-letter capital R (real part symbol) ('ℜ') +const int $real = 0x211C; + +/// trademark symbol ('™') +const int $trade = 0x2122; + +/// alef symbol (first transfinite cardinal) ('ℵ') +const int $alefsym = 0x2135; + +/// leftwards arrow ('←') +const int $larr = 0x2190; + +/// upwards arrow ('↑') +const int $uarr = 0x2191; + +/// rightwards arrow ('→') +const int $rarr = 0x2192; + +/// downwards arrow ('↓') +const int $darr = 0x2193; + +/// left right arrow ('↔') +const int $harr = 0x2194; + +/// downwards arrow with corner leftwards (carriage return) ('↵') +const int $crarr = 0x21B5; + +/// leftwards double arrow ('⇐') +const int $lArr = 0x21D0; + +/// upwards double arrow ('⇑') +const int $uArr = 0x21D1; + +/// rightwards double arrow ('⇒') +const int $rArr = 0x21D2; + +/// downwards double arrow ('⇓') +const int $dArr = 0x21D3; + +/// left right double arrow ('⇔') +const int $hArr = 0x21D4; + +/// for all ('∀') +const int $forall = 0x2200; + +/// partial differential ('∂') +const int $part = 0x2202; + +/// there exists ('∃') +const int $exist = 0x2203; + +/// empty set (null set); see also U+8960, ⌀ ('∅') +const int $empty = 0x2205; + +/// del or nabla (vector differential operator) ('∇') +const int $nabla = 0x2207; + +/// element of ('∈') +const int $isin = 0x2208; + +/// not an element of ('∉') +const int $notin = 0x2209; + +/// contains as member ('∋') +const int $ni = 0x220B; + +/// n-ary product (product sign) ('∏') +const int $prod = 0x220F; + +/// n-ary summation ('∑') +const int $sum = 0x2211; + +/// minus sign ('−') +const int $minus = 0x2212; + +/// asterisk operator ('∗') +const int $lowast = 0x2217; + +/// square root (radical sign) ('√') +const int $radic = 0x221A; + +/// proportional to ('∝') +const int $prop = 0x221D; + +/// infinity ('∞') +const int $infin = 0x221E; + +/// angle ('∠') +const int $ang = 0x2220; + +/// logical and (wedge) ('∧') +const int $and = 0x2227; + +/// logical or (vee) ('∨') +const int $or = 0x2228; + +/// intersection (cap) ('∩') +const int $cap = 0x2229; + +/// union (cup) ('∪') +const int $cup = 0x222A; + +/// integral ('∫') +const int $int = 0x222B; + +/// therefore sign ('∴') +const int $there4 = 0x2234; + +/// tilde operator (varies with, similar to) ('∼') +const int $sim = 0x223C; + +/// congruent to ('≅') +const int $cong = 0x2245; + +/// almost equal to (asymptotic to) ('≈') +const int $asymp = 0x2248; + +/// not equal to ('≠') +const int $ne = 0x2260; + +/// identical to; sometimes used for 'equivalent to' ('≡') +const int $equiv = 0x2261; + +/// less-than or equal to ('≤') +const int $le = 0x2264; + +/// greater-than or equal to ('≥') +const int $ge = 0x2265; + +/// subset of ('⊂') +const int $sub = 0x2282; + +/// superset of ('⊃') +const int $sup = 0x2283; + +/// not a subset of ('⊄') +const int $nsub = 0x2284; + +/// subset of or equal to ('⊆') +const int $sube = 0x2286; + +/// superset of or equal to ('⊇') +const int $supe = 0x2287; + +/// circled plus (direct sum) ('⊕') +const int $oplus = 0x2295; + +/// circled times (vector product) ('⊗') +const int $otimes = 0x2297; + +/// up tack (orthogonal to, perpendicular) ('⊥') +const int $perp = 0x22A5; + +/// dot operator ('⋅') +const int $sdot = 0x22C5; + +/// vertical ellipsis ('⋮') +const int $vellip = 0x22EE; + +/// left ceiling (APL upstile) ('⌈') +const int $lceil = 0x2308; + +/// right ceiling ('⌉') +const int $rceil = 0x2309; + +/// left floor (APL downstile) ('⌊') +const int $lfloor = 0x230A; + +/// right floor ('⌋') +const int $rfloor = 0x230B; + +/// left-pointing angle bracket (bra) ('〈') +const int $lang = 0x2329; + +/// right-pointing angle bracket (ket) ('〉') +const int $rang = 0x232A; + +/// lozenge ('◊') +const int $loz = 0x25CA; + +/// black spade suit ('♠') +const int $spades = 0x2660; + +/// black club suit (shamrock) ('♣') +const int $clubs = 0x2663; + +/// black heart suit (valentine) ('♥') +const int $hearts = 0x2665; + +/// black diamond suit ('♦') +const int $diams = 0x2666; +NI<?(9"C5'0KN.7($+=%N'89/;='(8$2&P=7C8R31,0O>.33103310#,331,0L33103%B11/*./:,11/.11/.!*11/*.!H11/.1#.$",*0<,%$%%'$#%$%&"""'"#%#'###%#"##%"!#"#$   % !)#!%!!!#)  %&&%&&(&1 )45'#2643B!"!"36'%3*; # "$)1%%,-%'Wfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/uuid-1.0.3/lib/uuid_util.dartlibrary UuidUtil; + +import 'dart:math'; +import 'package:crypto/crypto.dart'; +import 'aes.dart'; + +class UuidUtil { + /** + * Math.Random()-based RNG. All platforms, fast, not cryptographically strong. Optional Seed passable. + */ + static List mathRNG({int seed: null}) { + var rand, b = new List(16); + + var _rand = (seed == null) ? new Random() : new Random(seed); + for (var i = 0; i < 16; i++) { + if ((i & 0x03) == 0) { + rand = (_rand.nextDouble() * 0x100000000).floor().toInt(); + } + b[i] = rand >> ((i & 0x03) << 3) & 0xff; + } + + return b; + } + + /** + * AES-based RNG. All platforms, unknown speed, cryptographically strong (theoretically) + */ + static List cryptoRNG() { + int nBytes = 32; + var pwBytes = new List(nBytes); + + var bytes = mathRNG(); + pwBytes = sha256.convert(bytes).bytes.sublist(0, nBytes); + + return AES.cipher(pwBytes, AES.keyExpansion(pwBytes)); + } +} +'%i/%B#C/[$>;Vfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/crypto.dartl// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/digest.dart'; +export 'src/hash.dart'; +export 'src/hmac.dart'; +export 'src/md5.dart'; +export 'src/sha1.dart'; +export 'src/sha256.dart'; + NN<Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/convert.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert; + +export 'src/accumulator_sink.dart'; +export 'src/byte_accumulator_sink.dart'; +export 'src/hex.dart'; +export 'src/percent.dart'; +export 'src/string_accumulator_sink.dart'; + NN<$)+^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/typed_data-1.1.6/lib/typed_data.darth// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Utilities and functionality related to the "dart:typed_data" library. +library typed_data; + +export "package:typed_data/typed_buffers.dart"; + +NN<J0Wfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/src/utils.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'characters.dart' as chars; + +/// Returns whether [char] is the code for an ASCII letter (uppercase or +/// lowercase). +bool isAlphabetic(int char) => + (char >= chars.UPPER_A && char <= chars.UPPER_Z) || + (char >= chars.LOWER_A && char <= chars.LOWER_Z); + +/// Returns whether [char] is the code for an ASCII digit. +bool isNumeric(int char) => char >= chars.ZERO && char <= chars.NINE; + +/// Returns whether [path] has a URL-formatted Windows drive letter beginning at +/// [index]. +bool isDriveLetter(String path, int index) { + if (path.length < index + 2) return false; + if (!isAlphabetic(path.codeUnitAt(index))) return false; + if (path.codeUnitAt(index + 1) != chars.COLON) return false; + if (path.length == index + 2) return true; + return path.codeUnitAt(index + 2) == chars.SLASH; +} +NN<#I86;FQ --;?-4ofile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/file-5.0.6/lib/src/interface/error_codes_dart_io.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' show Platform; + +/// If we have `dart:io` available, we pull the current operating system from +/// the [Platform] class, so we'll get errno values that match our current +/// operating system. +final String operatingSystem = Platform.operatingSystem; + NN< NK9cfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/core_matchers.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'feature_matcher.dart'; +import 'interfaces.dart'; +import 'type_matcher.dart'; +import 'util.dart'; + +/// Returns a matcher that matches the isEmpty property. +const Matcher isEmpty = const _Empty(); + +class _Empty extends Matcher { + const _Empty(); + + bool matches(item, Map matchState) => item.isEmpty; + + Description describe(Description description) => description.add('empty'); +} + +/// Returns a matcher that matches the isNotEmpty property. +const Matcher isNotEmpty = const _NotEmpty(); + +class _NotEmpty extends Matcher { + const _NotEmpty(); + + bool matches(item, Map matchState) => item.isNotEmpty; + + Description describe(Description description) => description.add('non-empty'); +} + +/// A matcher that matches any null value. +const Matcher isNull = const _IsNull(); + +/// A matcher that matches any non-null value. +const Matcher isNotNull = const _IsNotNull(); + +class _IsNull extends Matcher { + const _IsNull(); + bool matches(item, Map matchState) => item == null; + Description describe(Description description) => description.add('null'); +} + +class _IsNotNull extends Matcher { + const _IsNotNull(); + bool matches(item, Map matchState) => item != null; + Description describe(Description description) => description.add('not null'); +} + +/// A matcher that matches the Boolean value true. +const Matcher isTrue = const _IsTrue(); + +/// A matcher that matches anything except the Boolean value true. +const Matcher isFalse = const _IsFalse(); + +class _IsTrue extends Matcher { + const _IsTrue(); + bool matches(item, Map matchState) => item == true; + Description describe(Description description) => description.add('true'); +} + +class _IsFalse extends Matcher { + const _IsFalse(); + bool matches(item, Map matchState) => item == false; + Description describe(Description description) => description.add('false'); +} + +/// A matcher that matches the numeric value NaN. +const Matcher isNaN = const _IsNaN(); + +/// A matcher that matches any non-NaN value. +const Matcher isNotNaN = const _IsNotNaN(); + +class _IsNaN extends FeatureMatcher { + const _IsNaN(); + bool typedMatches(num item, Map matchState) => + double.nan.compareTo(item) == 0; + Description describe(Description description) => description.add('NaN'); +} + +class _IsNotNaN extends FeatureMatcher { + const _IsNotNaN(); + bool typedMatches(num item, Map matchState) => + double.nan.compareTo(item) != 0; + Description describe(Description description) => description.add('not NaN'); +} + +/// Returns a matches that matches if the value is the same instance +/// as [expected], using [identical]. +Matcher same(expected) => new _IsSameAs(expected); + +class _IsSameAs extends Matcher { + final Object _expected; + const _IsSameAs(this._expected); + bool matches(item, Map matchState) => identical(item, _expected); + // If all types were hashable we could show a hash here. + Description describe(Description description) => + description.add('same instance as ').addDescriptionOf(_expected); +} + +/// A matcher that matches any value. +const Matcher anything = const _IsAnything(); + +class _IsAnything extends Matcher { + const _IsAnything(); + bool matches(item, Map matchState) => true; + Description describe(Description description) => description.add('anything'); +} + +/// **DEPRECATED** Use [TypeMatcher] instead. +/// +/// Returns a matcher that matches if an object is an instance +/// of [T] (or a subtype). +@Deprecated('Use `const TypeMatcher()` instead.') +// ignore: camel_case_types +class isInstanceOf extends TypeMatcher { + const isInstanceOf(); +} + +/// A matcher that matches a function call against no exception. +/// +/// The function will be called once. Any exceptions will be silently swallowed. +/// The value passed to expect() should be a reference to the function. +/// Note that the function cannot take arguments; to handle this +/// a wrapper will have to be created. +const Matcher returnsNormally = const _ReturnsNormally(); + +class _ReturnsNormally extends FeatureMatcher { + const _ReturnsNormally(); + + bool typedMatches(Function f, Map matchState) { + try { + f(); + return true; + } catch (e, s) { + addStateInfo(matchState, {'exception': e, 'stack': s}); + return false; + } + } + + Description describe(Description description) => + description.add("return normally"); + + Description describeTypedMismatch(Function item, + Description mismatchDescription, Map matchState, bool verbose) { + mismatchDescription.add('threw ').addDescriptionOf(matchState['exception']); + if (verbose) { + mismatchDescription.add(' at ').add(matchState['stack'].toString()); + } + return mismatchDescription; + } +} + +/// A matcher for [Map]. +const isMap = const TypeMatcher(); + +/// A matcher for [List]. +const isList = const TypeMatcher(); + +/// Returns a matcher that matches if an object has a length property +/// that matches [matcher]. +Matcher hasLength(matcher) => new _HasLength(wrapMatcher(matcher)); + +class _HasLength extends Matcher { + final Matcher _matcher; + const _HasLength([Matcher matcher]) : this._matcher = matcher; + + bool matches(item, Map matchState) { + try { + // This is harmless code that will throw if no length property + // but subtle enough that an optimizer shouldn't strip it out. + if (item.length * item.length >= 0) { + return _matcher.matches(item.length, matchState); + } + } catch (e) { + return false; + } + throw new UnsupportedError('Should never get here'); + } + + Description describe(Description description) => + description.add('an object with length of ').addDescriptionOf(_matcher); + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + try { + // We want to generate a different description if there is no length + // property; we use the same trick as in matches(). + if (item.length * item.length >= 0) { + return mismatchDescription + .add('has length of ') + .addDescriptionOf(item.length); + } + } catch (e) { + return mismatchDescription.add('has no length property'); + } + throw new UnsupportedError('Should never get here'); + } +} + +/// Returns a matcher that matches if the match argument contains the expected +/// value. +/// +/// For [String]s this means substring matching; +/// for [Map]s it means the map has the key, and for [Iterable]s +/// it means the iterable has a matching element. In the case of iterables, +/// [expected] can itself be a matcher. +Matcher contains(expected) => new _Contains(expected); + +class _Contains extends Matcher { + final Object _expected; + + const _Contains(this._expected); + + bool matches(item, Map matchState) { + var expected = _expected; + if (item is String) { + return expected is Pattern && item.contains(expected); + } else if (item is Iterable) { + if (expected is Matcher) { + return item.any((e) => expected.matches(e, matchState)); + } else { + return item.contains(_expected); + } + } else if (item is Map) { + return item.containsKey(_expected); + } + return false; + } + + Description describe(Description description) => + description.add('contains ').addDescriptionOf(_expected); + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + if (item is String || item is Iterable || item is Map) { + return super + .describeMismatch(item, mismatchDescription, matchState, verbose); + } else { + return mismatchDescription.add('is not a string, map or iterable'); + } + } +} + +/// Returns a matcher that matches if the match argument is in +/// the expected value. This is the converse of [contains]. +Matcher isIn(expected) { + if (expected is Iterable) { + return new _In(expected, expected.contains); + } else if (expected is String) { + return new _In(expected, expected.contains); + } else if (expected is Map) { + return new _In(expected, expected.containsKey); + } + + throw new ArgumentError.value( + expected, 'expected', 'Only Iterable, Map, and String are supported.'); +} + +class _In extends FeatureMatcher { + final Object _source; + final bool Function(T) _containsFunction; + + const _In(this._source, this._containsFunction); + + bool typedMatches(T item, Map matchState) => _containsFunction(item); + + Description describe(Description description) => + description.add('is in ').addDescriptionOf(_source); +} + +/// Returns a matcher that uses an arbitrary function that returns +/// true or false for the actual value. +/// +/// For example: +/// +/// expect(v, predicate((x) => ((x % 2) == 0), "is even")) +Matcher predicate(bool f(T value), + [String description = 'satisfies function']) => + new _Predicate(f, description); + +typedef bool _PredicateFunction(T value); + +class _Predicate extends FeatureMatcher { + final _PredicateFunction _matcher; + final String _description; + + _Predicate(this._matcher, this._description); + + bool typedMatches(T item, Map matchState) => _matcher(item); + + Description describe(Description description) => + description.add(_description); +} +(NN<9(6M<."9Q+(/. 6L#6P3(C* 6L!7M2&.,+1'K.1'OE&3"#D;3H&.$.P.?:/AQHA'::2 + >3*3GQK (*FD#A' +EE,:93O M +K:,##,@9O 1AL(7"#'=#!A)*3@ M=M J?<1#: 4!N),3H3;C(?&8$-0(0?3%dfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/custom_matcher.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:stack_trace/stack_trace.dart'; + +import 'description.dart'; +import 'interfaces.dart'; +import 'util.dart'; + +/// A useful utility class for implementing other matchers through inheritance. +/// Derived classes should call the base constructor with a feature name and +/// description, and an instance matcher, and should implement the +/// [featureValueOf] abstract method. +/// +/// The feature description will typically describe the item and the feature, +/// while the feature name will just name the feature. For example, we may +/// have a Widget class where each Widget has a price; we could make a +/// [CustomMatcher] that can make assertions about prices with: +/// +/// ```dart +/// class HasPrice extends CustomMatcher { +/// HasPrice(matcher) : super("Widget with price that is", "price", matcher); +/// featureValueOf(actual) => actual.price; +/// } +/// ``` +/// +/// and then use this for example like: +/// +/// ```dart +/// expect(inventoryItem, new HasPrice(greaterThan(0))); +/// ``` +class CustomMatcher extends Matcher { + final String _featureDescription; + final String _featureName; + final Matcher _matcher; + + CustomMatcher(this._featureDescription, this._featureName, matcher) + : this._matcher = wrapMatcher(matcher); + + /// Override this to extract the interesting feature. + Object featureValueOf(actual) => actual; + + bool matches(item, Map matchState) { + try { + var f = featureValueOf(item); + if (_matcher.matches(f, matchState)) return true; + addStateInfo(matchState, {'custom.feature': f}); + } catch (exception, stack) { + addStateInfo(matchState, { + 'custom.exception': exception.toString(), + 'custom.stack': new Chain.forTrace(stack) + .foldFrames( + (frame) => + frame.package == 'test' || + frame.package == 'stream_channel' || + frame.package == 'matcher', + terse: true) + .toString() + }); + } + return false; + } + + Description describe(Description description) => + description.add(_featureDescription).add(' ').addDescriptionOf(_matcher); + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + if (matchState['custom.exception'] != null) { + mismatchDescription + .add('threw ') + .addDescriptionOf(matchState['custom.exception']) + .add('\n') + .add(matchState['custom.stack'].toString()); + return mismatchDescription; + } + + mismatchDescription + .add('has ') + .add(_featureName) + .add(' with value ') + .addDescriptionOf(matchState['custom.feature']); + var innerDescription = new StringDescription(); + + _matcher.describeMismatch(matchState['custom.feature'], innerDescription, + matchState['state'] as Map, verbose); + + if (innerDescription.length > 0) { + mismatchDescription.add(' which ').add(innerDescription.toString()); + } + return mismatchDescription; + } +} +`NN</PMC&NKG@ +P.( 9&$F.8+' +$87!!22/90 +3P M2<7"94N.'K afile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/description.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'interfaces.dart'; +import 'pretty_print.dart'; + +/// The default implementation of [Description]. This should rarely need +/// substitution, although conceivably it is a place where other languages +/// could be supported. +class StringDescription implements Description { + final StringBuffer _out = new StringBuffer(); + + /// Initialize the description with initial contents [init]. + StringDescription([String init = '']) { + _out.write(init); + } + + int get length => _out.length; + + /// Get the description as a string. + String toString() => _out.toString(); + + /// Append [text] to the description. + Description add(String text) { + _out.write(text); + return this; + } + + /// Change the value of the description. + Description replace(String text) { + _out.clear(); + return add(text); + } + + /// Appends a description of [value]. If it is an IMatcher use its + /// describe method; if it is a string use its literal value after + /// escaping any embedded control characters; otherwise use its + /// toString() value and wrap it in angular "quotes". + Description addDescriptionOf(value) { + if (value is Matcher) { + value.describe(this); + } else { + add(prettyPrint(value, maxLineLength: 80, maxItems: 25)); + } + return this; + } + + /// Append an [Iterable] [list] of objects to the description, using the + /// specified [separator] and framing the list with [start] + /// and [end]. + Description addAll( + String start, String separator, String end, Iterable list) { + var separate = false; + add(start); + for (var item in list) { + if (separate) { + add(separator); + } + addDescriptionOf(item); + separate = true; + } + add(end); + return this; + } +} +DNN<IK10?*!'((!+%EEB8( @K>Cdfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/equals_matcher.dart)// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'description.dart'; +import 'feature_matcher.dart'; +import 'interfaces.dart'; +import 'util.dart'; + +/// Returns a matcher that matches if the value is structurally equal to +/// [expected]. +/// +/// If [expected] is a [Matcher], then it matches using that. Otherwise it tests +/// for equality using `==` on the expected value. +/// +/// For [Iterable]s and [Map]s, this will recursively match the elements. To +/// handle cyclic structures a recursion depth [limit] can be provided. The +/// default limit is 100. [Set]s will be compared order-independently. +Matcher equals(expected, [int limit = 100]) => expected is String + ? new _StringEqualsMatcher(expected) + : new _DeepMatcher(expected, limit); + +typedef _RecursiveMatcher = List Function( + dynamic, dynamic, String, int); + +/// A special equality matcher for strings. +class _StringEqualsMatcher extends FeatureMatcher { + final String _value; + + _StringEqualsMatcher(this._value); + + bool typedMatches(String item, Map matchState) => _value == item; + + Description describe(Description description) => + description.addDescriptionOf(_value); + + Description describeTypedMismatch(String item, + Description mismatchDescription, Map matchState, bool verbose) { + var buff = new StringBuffer(); + buff.write('is different.'); + var escapedItem = escape(item); + var escapedValue = escape(_value); + var minLength = escapedItem.length < escapedValue.length + ? escapedItem.length + : escapedValue.length; + var start = 0; + for (; start < minLength; start++) { + if (escapedValue.codeUnitAt(start) != escapedItem.codeUnitAt(start)) { + break; + } + } + if (start == minLength) { + if (escapedValue.length < escapedItem.length) { + buff.write(' Both strings start the same, but the actual value also' + ' has the following trailing characters: '); + _writeTrailing(buff, escapedItem, escapedValue.length); + } else { + buff.write(' Both strings start the same, but the actual value is' + ' missing the following trailing characters: '); + _writeTrailing(buff, escapedValue, escapedItem.length); + } + } else { + buff.write('\nExpected: '); + _writeLeading(buff, escapedValue, start); + _writeTrailing(buff, escapedValue, start); + buff.write('\n Actual: '); + _writeLeading(buff, escapedItem, start); + _writeTrailing(buff, escapedItem, start); + buff.write('\n '); + for (var i = (start > 10 ? 14 : start); i > 0; i--) buff.write(' '); + buff.write('^\n Differ at offset $start'); + } + + return mismatchDescription.add(buff.toString()); + } + + static void _writeLeading(StringBuffer buff, String s, int start) { + if (start > 10) { + buff.write('... '); + buff.write(s.substring(start - 10, start)); + } else { + buff.write(s.substring(0, start)); + } + } + + static void _writeTrailing(StringBuffer buff, String s, int start) { + if (start + 10 > s.length) { + buff.write(s.substring(start)); + } else { + buff.write(s.substring(start, start + 10)); + buff.write(' ...'); + } + } +} + +class _DeepMatcher extends Matcher { + final Object _expected; + final int _limit; + + _DeepMatcher(this._expected, [int limit = 1000]) : this._limit = limit; + + // Returns a pair (reason, location) + List _compareIterables(Iterable expected, Object actual, + _RecursiveMatcher matcher, int depth, String location) { + if (actual is Iterable) { + var expectedIterator = expected.iterator; + var actualIterator = actual.iterator; + for (var index = 0;; index++) { + // Advance in lockstep. + var expectedNext = expectedIterator.moveNext(); + var actualNext = actualIterator.moveNext(); + + // If we reached the end of both, we succeeded. + if (!expectedNext && !actualNext) return null; + + // Fail if their lengths are different. + var newLocation = '$location[$index]'; + if (!expectedNext) return ['longer than expected', newLocation]; + if (!actualNext) return ['shorter than expected', newLocation]; + + // Match the elements. + var rp = matcher(expectedIterator.current, actualIterator.current, + newLocation, depth); + if (rp != null) return rp; + } + } else { + return ['is not Iterable', location]; + } + } + + List _compareSets(Set expected, Object actual, + _RecursiveMatcher matcher, int depth, String location) { + if (actual is Iterable) { + var other = actual.toSet(); + + for (var expectedElement in expected) { + if (other.every((actualElement) => + matcher(expectedElement, actualElement, location, depth) != null)) { + return ['does not contain $expectedElement', location]; + } + } + + if (other.length > expected.length) { + return ['larger than expected', location]; + } else if (other.length < expected.length) { + return ['smaller than expected', location]; + } else { + return null; + } + } else { + return ['is not Iterable', location]; + } + } + + List _recursiveMatch( + Object expected, Object actual, String location, int depth) { + // If the expected value is a matcher, try to match it. + if (expected is Matcher) { + var matchState = {}; + if (expected.matches(actual, matchState)) return null; + + var description = new StringDescription(); + expected.describe(description); + return ['does not match $description', location]; + } else { + // Otherwise, test for equality. + try { + if (expected == actual) return null; + } catch (e) { + // TODO(gram): Add a test for this case. + return ['== threw "$e"', location]; + } + } + + if (depth > _limit) return ['recursion depth limit exceeded', location]; + + // If _limit is 1 we can only recurse one level into object. + if (depth == 0 || _limit > 1) { + if (expected is Set) { + return _compareSets( + expected, actual, _recursiveMatch, depth + 1, location); + } else if (expected is Iterable) { + return _compareIterables( + expected, actual, _recursiveMatch, depth + 1, location); + } else if (expected is Map) { + if (actual is! Map) return ['expected a map', location]; + var map = (actual as Map); + var err = + (expected.length == map.length) ? '' : 'has different length and '; + for (var key in expected.keys) { + if (!map.containsKey(key)) { + return ["${err}is missing map key '$key'", location]; + } + } + + for (var key in map.keys) { + if (!expected.containsKey(key)) { + return ["${err}has extra map key '$key'", location]; + } + } + + for (var key in expected.keys) { + var rp = _recursiveMatch( + expected[key], map[key], "$location['$key']", depth + 1); + if (rp != null) return rp; + } + + return null; + } + } + + var description = new StringDescription(); + + // If we have recursed, show the expected value too; if not, expect() will + // show it for us. + if (depth > 0) { + description + .add('was ') + .addDescriptionOf(actual) + .add(' instead of ') + .addDescriptionOf(expected); + return [description.toString(), location]; + } + + // We're not adding any value to the actual value. + return ["", location]; + } + + String _match(expected, actual, Map matchState) { + var rp = _recursiveMatch(expected, actual, '', 0); + if (rp == null) return null; + String reason; + if (rp[0].isNotEmpty) { + if (rp[1].isNotEmpty) { + reason = "${rp[0]} at location ${rp[1]}"; + } else { + reason = rp[0]; + } + } else { + reason = ''; + } + // Cache the failure reason in the matchState. + addStateInfo(matchState, {'reason': reason}); + return reason; + } + + bool matches(item, Map matchState) => + _match(_expected, item, matchState) == null; + + Description describe(Description description) => + description.addDescriptionOf(_expected); + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + var reason = matchState['reason'] as String ?? ''; + // If we didn't get a good reason, that would normally be a + // simple 'is ' message. We only add that if the mismatch + // description is non empty (so we are supplementing the mismatch + // description). + if (reason.isEmpty && mismatchDescription.length > 0) { + mismatchDescription.add('is ').addDescriptionOf(item); + } else { + mismatchDescription.add(reason); + } + return mismatchDescription; + } +} + NN<IQ3MLGB))3$,<%D3,1G#!$'=)M6M9@K=@ "01"/0"K15F2 )G!& 2%J'C?0,& 84870/IHK!# ,9?".+QB +,334 , D<=1&8 ' -1,MA$E)"E$A#P)'B +$,A +)$H% +/O$'1747!2 32(33/ M7@EF<= ' dfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/error_matchers.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'type_matcher.dart'; + +/// A matcher for [ArgumentError]. +const isArgumentError = const TypeMatcher(); + +/// A matcher for [CastError]. +const isCastError = const TypeMatcher(); + +/// A matcher for [ConcurrentModificationError]. +const isConcurrentModificationError = + const TypeMatcher(); + +/// A matcher for [CyclicInitializationError]. +const isCyclicInitializationError = + const TypeMatcher(); + +/// A matcher for [Exception]. +const isException = const TypeMatcher(); + +/// A matcher for [FormatException]. +const isFormatException = const TypeMatcher(); + +/// A matcher for [NoSuchMethodError]. +const isNoSuchMethodError = const TypeMatcher(); + +/// A matcher for [NullThrownError]. +const isNullThrownError = const TypeMatcher(); + +/// A matcher for [RangeError]. +const isRangeError = const TypeMatcher(); + +/// A matcher for [StateError]. +const isStateError = const TypeMatcher(); + +/// A matcher for [UnimplementedError]. +const isUnimplementedError = const TypeMatcher(); + +/// A matcher for [UnsupportedError]. +const isUnsupportedError = const TypeMatcher(); +-NN<#<41&6/$44%@'D%@ 6 6(F&B`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/interfaces.dartf// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Matchers build up their error messages by appending to Description objects. +/// +/// This interface is implemented by StringDescription. +/// +/// This interface is unlikely to need other implementations, but could be +/// useful to replace in some cases - e.g. language conversion. +abstract class Description { + int get length; + + /// Change the value of the description. + Description replace(String text); + + /// This is used to add arbitrary text to the description. + Description add(String text); + + /// This is used to add a meaningful description of a value. + Description addDescriptionOf(value); + + /// This is used to add a description of an [Iterable] [list], + /// with appropriate [start] and [end] markers and inter-element [separator]. + Description addAll(String start, String separator, String end, Iterable list); +} + +/// The base class for all matchers. +/// +/// [matches] and [describe] must be implemented by subclasses. +/// +/// Subclasses can override [describeMismatch] if a more specific description is +/// required when the matcher fails. +abstract class Matcher { + const Matcher(); + + /// Does the matching of the actual vs expected values. + /// + /// [item] is the actual value. [matchState] can be supplied + /// and may be used to add details about the mismatch that are too + /// costly to determine in [describeMismatch]. + bool matches(item, Map matchState); + + /// Builds a textual description of the matcher. + Description describe(Description description); + + /// Builds a textual description of a specific mismatch. + /// + /// [item] is the value that was tested by [matches]; [matchState] is + /// the [Map] that was passed to and supplemented by [matches] + /// with additional information about the mismatch, and [mismatchDescription] + /// is the [Description] that is being built to describe the mismatch. + /// + /// A few matchers make use of the [verbose] flag to provide detailed + /// information that is not typically included but can be of help in + /// diagnosing failures, such as stack traces. + Description describeMismatch(item, Description mismatchDescription, + Map matchState, bool verbose) => + mismatchDescription; +} +>NN<P8K@+$= ?'APQ%@Q%:?E1&31;HAPIHG1F+gfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/iterable_matchers.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'description.dart'; +import 'equals_matcher.dart'; +import 'feature_matcher.dart'; +import 'interfaces.dart'; +import 'util.dart'; + +/// Returns a matcher which matches [Iterable]s in which all elements +/// match the given [matcher]. +Matcher everyElement(matcher) => new _EveryElement(wrapMatcher(matcher)); + +class _EveryElement extends _IterableMatcher { + final Matcher _matcher; + + _EveryElement(this._matcher); + + bool typedMatches(Iterable item, Map matchState) { + var i = 0; + for (var element in item) { + if (!_matcher.matches(element, matchState)) { + addStateInfo(matchState, {'index': i, 'element': element}); + return false; + } + ++i; + } + return true; + } + + Description describe(Description description) => + description.add('every element(').addDescriptionOf(_matcher).add(')'); + + Description describeTypedMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + if (matchState['index'] != null) { + var index = matchState['index']; + var element = matchState['element']; + mismatchDescription + .add('has value ') + .addDescriptionOf(element) + .add(' which '); + var subDescription = new StringDescription(); + _matcher.describeMismatch( + element, subDescription, matchState['state'] as Map, verbose); + if (subDescription.length > 0) { + mismatchDescription.add(subDescription.toString()); + } else { + mismatchDescription.add("doesn't match "); + _matcher.describe(mismatchDescription); + } + mismatchDescription.add(' at index $index'); + return mismatchDescription; + } + return super + .describeMismatch(item, mismatchDescription, matchState, verbose); + } +} + +/// Returns a matcher which matches [Iterable]s in which at least one +/// element matches the given [matcher]. +Matcher anyElement(matcher) => new _AnyElement(wrapMatcher(matcher)); + +class _AnyElement extends _IterableMatcher { + final Matcher _matcher; + + _AnyElement(this._matcher); + + bool typedMatches(Iterable item, Map matchState) => + item.any((e) => _matcher.matches(e, matchState)); + + Description describe(Description description) => + description.add('some element ').addDescriptionOf(_matcher); +} + +/// Returns a matcher which matches [Iterable]s that have the same +/// length and the same elements as [expected], in the same order. +/// +/// This is equivalent to [equals] but does not recurse. +Matcher orderedEquals(Iterable expected) => new _OrderedEquals(expected); + +class _OrderedEquals extends _IterableMatcher { + final Iterable _expected; + final Matcher _matcher; + + _OrderedEquals(this._expected) : _matcher = equals(_expected, 1); + + bool typedMatches(Iterable item, Map matchState) => + _matcher.matches(item, matchState); + + Description describe(Description description) => + description.add('equals ').addDescriptionOf(_expected).add(' ordered'); + + Description describeTypedMismatch(Iterable item, + Description mismatchDescription, Map matchState, bool verbose) { + return _matcher.describeMismatch( + item, mismatchDescription, matchState, verbose); + } +} + +/// Returns a matcher which matches [Iterable]s that have the same length and +/// the same elements as [expected], but not necessarily in the same order. +/// +/// Note that this is worst case O(n^2) runtime and memory usage so it should +/// only be used on small iterables. +Matcher unorderedEquals(Iterable expected) => new _UnorderedEquals(expected); + +class _UnorderedEquals extends _UnorderedMatches { + final List _expectedValues; + + _UnorderedEquals(Iterable expected) + : _expectedValues = expected.toList(), + super(expected.map(equals)); + + Description describe(Description description) => description + .add('equals ') + .addDescriptionOf(_expectedValues) + .add(' unordered'); +} + +/// Iterable matchers match against [Iterable]s. We add this intermediate +/// class to give better mismatch error messages than the base Matcher class. +abstract class _IterableMatcher extends FeatureMatcher { + const _IterableMatcher(); +} + +/// Returns a matcher which matches [Iterable]s whose elements match the +/// matchers in [expected], but not necessarily in the same order. +/// +/// Note that this is worst case O(n^2) runtime and memory usage so it should +/// only be used on small iterables. +Matcher unorderedMatches(Iterable expected) => new _UnorderedMatches(expected); + +class _UnorderedMatches extends _IterableMatcher { + final List _expected; + final bool _allowUnmatchedValues; + + _UnorderedMatches(Iterable expected, {bool allowUnmatchedValues}) + : _expected = expected.map(wrapMatcher).toList(), + _allowUnmatchedValues = allowUnmatchedValues ?? false; + + String _test(List values) { + // Check the lengths are the same. + if (_expected.length > values.length) { + return 'has too few elements (${values.length} < ${_expected.length})'; + } else if (!_allowUnmatchedValues && _expected.length < values.length) { + return 'has too many elements (${values.length} > ${_expected.length})'; + } + + var edges = + new List.generate(values.length, (_) => [], growable: false); + for (var v = 0; v < values.length; v++) { + for (var m = 0; m < _expected.length; m++) { + if (_expected[m].matches(values[v], {})) { + edges[v].add(m); + } + } + } + // The index into `values` matched with each matcher or `null` if no value + // has been matched yet. + var matched = new List(_expected.length); + for (var valueIndex = 0; valueIndex < values.length; valueIndex++) { + _findPairing(edges, valueIndex, matched); + } + for (var matcherIndex = 0; + matcherIndex < _expected.length; + matcherIndex++) { + if (matched[matcherIndex] == null) { + final description = new StringDescription() + .add('has no match for ') + .addDescriptionOf(_expected[matcherIndex]) + .add(' at index $matcherIndex'); + final remainingUnmatched = + matched.sublist(matcherIndex + 1).where((m) => m == null).length; + return remainingUnmatched == 0 + ? description.toString() + : description + .add(' along with $remainingUnmatched other unmatched') + .toString(); + } + } + return null; + } + + bool typedMatches(Iterable item, Map mismatchState) => + _test(item.toList()) == null; + + Description describe(Description description) => description + .add('matches ') + .addAll('[', ', ', ']', _expected) + .add(' unordered'); + + Description describeTypedMismatch(item, Description mismatchDescription, + Map matchState, bool verbose) => + mismatchDescription.add(_test(item.toList())); + + /// Returns `true` if the value at [valueIndex] can be paired with some + /// unmatched matcher and updates the state of [matched]. + /// + /// If there is a conflict where multiple values may match the same matcher + /// recursively looks for a new place to match the old value. [reserved] + /// tracks the matchers that have been used _during_ this search. + bool _findPairing(List> edges, int valueIndex, List matched, + [Set reserved]) { + reserved ??= new Set(); + final possiblePairings = + edges[valueIndex].where((m) => !reserved.contains(m)); + for (final matcherIndex in possiblePairings) { + reserved.add(matcherIndex); + final previouslyMatched = matched[matcherIndex]; + if (previouslyMatched == null || + // If the matcher isn't already free, check whether the existing value + // occupying the matcher can be bumped to another one. + _findPairing(edges, matched[matcherIndex], matched, reserved)) { + matched[matcherIndex] = valueIndex; + return true; + } + } + return false; + } +} + +/// A pairwise matcher for [Iterable]s. +/// +/// The [comparator] function, taking an expected and an actual argument, and +/// returning whether they match, will be applied to each pair in order. +/// [description] should be a meaningful name for the comparator. +Matcher pairwiseCompare( + Iterable expected, bool comparator(S a, T b), String description) => + new _PairwiseCompare(expected, comparator, description); + +typedef bool _Comparator(S a, T b); + +class _PairwiseCompare extends _IterableMatcher { + final Iterable _expected; + final _Comparator _comparator; + final String _description; + + _PairwiseCompare(this._expected, this._comparator, this._description); + + bool typedMatches(Iterable item, Map matchState) { + if (item.length != _expected.length) return false; + var iterator = item.iterator; + var i = 0; + for (var e in _expected) { + iterator.moveNext(); + if (!_comparator(e, iterator.current as T)) { + addStateInfo(matchState, + {'index': i, 'expected': e, 'actual': iterator.current}); + return false; + } + i++; + } + return true; + } + + Description describe(Description description) => + description.add('pairwise $_description ').addDescriptionOf(_expected); + + Description describeTypedMismatch(Iterable item, + Description mismatchDescription, Map matchState, bool verbose) { + if (item.length != _expected.length) { + return mismatchDescription + .add('has length ${item.length} instead of ${_expected.length}'); + } else { + return mismatchDescription + .add('has ') + .addDescriptionOf(matchState["actual"]) + .add(' which is not $_description ') + .addDescriptionOf(matchState["expected"]) + .add(' at index ${matchState["index"]}'); + } + } +} + +/// Matches [Iterable]s which contain an element matching every value in +/// [expected] in any order, and may contain additional values. +/// +/// For example: `[0, 1, 0, 2, 0]` matches `containsAll([1, 2])` and +/// `containsAll([2, 1])` but not `containsAll([1, 2, 3])`. +/// +/// Will only match values which implement [Iterable]. +/// +/// Each element in the value will only be considered a match for a single +/// matcher in [expected] even if it could satisfy more than one. For instance +/// `containsAll([greaterThan(1), greaterThan(2)])` will not be satisfied by +/// `[3]`. To check that all matchers are satisfied within an iterable and allow +/// the same element to satisfy multiple matchers use +/// `allOf(matchers.map(contains))`. +/// +/// Note that this is worst case O(n^2) runtime and memory usage so it should +/// only be used on small iterables. +Matcher containsAll(Iterable expected) => new _ContainsAll(expected); + +class _ContainsAll extends _UnorderedMatches { + final Iterable _unwrappedExpected; + + _ContainsAll(Iterable expected) + : _unwrappedExpected = expected, + super(expected.map(wrapMatcher), allowUnmatchedValues: true); + @override + Description describe(Description description) => + description.add('contains all of ').addDescriptionOf(_unwrappedExpected); +} + +/// Matches [Iterable]s which contain an element matching every value in +/// [expected] in the same order, but may contain additional values interleaved +/// throughout. +/// +/// For example: `[0, 1, 0, 2, 0]` matches `containsAllInOrder([1, 2])` but not +/// `containsAllInOrder([2, 1])` or `containsAllInOrder([1, 2, 3])`. +/// +/// Will only match values which implement [Iterable]. +Matcher containsAllInOrder(Iterable expected) => + new _ContainsAllInOrder(expected); + +class _ContainsAllInOrder extends _IterableMatcher { + final Iterable _expected; + + _ContainsAllInOrder(this._expected); + + String _test(Iterable item, Map matchState) { + var matchers = _expected.map(wrapMatcher).toList(); + var matcherIndex = 0; + for (var value in item) { + if (matchers[matcherIndex].matches(value, matchState)) matcherIndex++; + if (matcherIndex == matchers.length) return null; + } + return new StringDescription() + .add('did not find a value matching ') + .addDescriptionOf(matchers[matcherIndex]) + .add(' following expected prior values') + .toString(); + } + + @override + bool typedMatches(Iterable item, Map matchState) => + _test(item, matchState) == null; + + @override + Description describe(Description description) => description + .add('contains in order(') + .addDescriptionOf(_expected) + .add(')'); + + @override + Description describeTypedMismatch(Iterable item, + Description mismatchDescription, Map matchState, bool verbose) => + mismatchDescription.add(_test(item, matchState)); +} +aNN<FJ/ 5 4D 3M%M''+%4!I'<303"KF)F-683CCC9J0D6*3N3G&9NLN%N3&-%?)JNCICN%P3!$D8?',NMOK.33 +O3I0)+4&7-#N'%H9$?)K+5J<NKDN!?3"7'QAK,(NIBP=*8'I57"4!F 3N3G+!L !2/44I@E<7KOMQ6%N%F/%"'F 3PIPPE71'5'08M8#/21 6' ?!# 3L8bfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/map_matchers.dartb// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'interfaces.dart'; +import 'util.dart'; + +/// Returns a matcher which matches maps containing the given [value]. +Matcher containsValue(value) => new _ContainsValue(value); + +class _ContainsValue extends Matcher { + final Object _value; + + const _ContainsValue(this._value); + + bool matches(item, Map matchState) => item.containsValue(_value); + Description describe(Description description) => + description.add('contains value ').addDescriptionOf(_value); +} + +/// Returns a matcher which matches maps containing the key-value pair +/// with [key] => [value]. +Matcher containsPair(key, value) => + new _ContainsMapping(key, wrapMatcher(value)); + +class _ContainsMapping extends Matcher { + final Object _key; + final Matcher _valueMatcher; + + const _ContainsMapping(this._key, this._valueMatcher); + + bool matches(item, Map matchState) => + item.containsKey(_key) && _valueMatcher.matches(item[_key], matchState); + + Description describe(Description description) { + return description + .add('contains pair ') + .addDescriptionOf(_key) + .add(' => ') + .addDescriptionOf(_valueMatcher); + } + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + if (!item.containsKey(_key)) { + return mismatchDescription + .add(" doesn't contain key ") + .addDescriptionOf(_key); + } else { + mismatchDescription + .add(' contains key ') + .addDescriptionOf(_key) + .add(' but with value '); + _valueMatcher.describeMismatch( + item[_key], mismatchDescription, matchState, verbose); + return mismatchDescription; + } + } +} +=NN<G;'%D3CG$3)9(O2 * M#!(# !"$&A"ffile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/numeric_matchers.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'feature_matcher.dart'; +import 'interfaces.dart'; + +/// Returns a matcher which matches if the match argument is within [delta] +/// of some [value]. +/// +/// In other words, this matches if the match argument is greater than +/// than or equal [value]-[delta] and less than or equal to [value]+[delta]. +Matcher closeTo(num value, num delta) => new _IsCloseTo(value, delta); + +class _IsCloseTo extends FeatureMatcher { + final num _value, _delta; + + const _IsCloseTo(this._value, this._delta); + + bool typedMatches(item, Map matchState) { + var diff = item - _value; + if (diff < 0) diff = -diff; + return (diff <= _delta); + } + + Description describe(Description description) => description + .add('a numeric value within ') + .addDescriptionOf(_delta) + .add(' of ') + .addDescriptionOf(_value); + + Description describeTypedMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + var diff = item - _value; + if (diff < 0) diff = -diff; + return mismatchDescription.add(' differs by ').addDescriptionOf(diff); + } +} + +/// Returns a matcher which matches if the match argument is greater +/// than or equal to [low] and less than or equal to [high]. +Matcher inInclusiveRange(num low, num high) => + new _InRange(low, high, true, true); + +/// Returns a matcher which matches if the match argument is greater +/// than [low] and less than [high]. +Matcher inExclusiveRange(num low, num high) => + new _InRange(low, high, false, false); + +/// Returns a matcher which matches if the match argument is greater +/// than [low] and less than or equal to [high]. +Matcher inOpenClosedRange(num low, num high) => + new _InRange(low, high, false, true); + +/// Returns a matcher which matches if the match argument is greater +/// than or equal to a [low] and less than [high]. +Matcher inClosedOpenRange(num low, num high) => + new _InRange(low, high, true, false); + +class _InRange extends FeatureMatcher { + final num _low, _high; + final bool _lowMatchValue, _highMatchValue; + + const _InRange( + this._low, this._high, this._lowMatchValue, this._highMatchValue); + + bool typedMatches(value, Map matchState) { + if (value < _low || value > _high) { + return false; + } + if (value == _low) { + return _lowMatchValue; + } + if (value == _high) { + return _highMatchValue; + } + return true; + } + + Description describe(Description description) => + description.add("be in range from " + "$_low (${_lowMatchValue ? 'inclusive' : 'exclusive'}) to " + "$_high (${_highMatchValue ? 'inclusive' : 'exclusive'})"); +} +VNN<LGMG/., ?& !%M KE=/)E%/+E10*E30*-.I-)3*FFgfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/operator_matchers.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'interfaces.dart'; +import 'util.dart'; + +/// This returns a matcher that inverts [matcher] to its logical negation. +Matcher isNot(matcher) => new _IsNot(wrapMatcher(matcher)); + +class _IsNot extends Matcher { + final Matcher _matcher; + + const _IsNot(this._matcher); + + bool matches(item, Map matchState) => !_matcher.matches(item, matchState); + + Description describe(Description description) => + description.add('not ').addDescriptionOf(_matcher); +} + +/// This returns a matcher that matches if all of the matchers passed as +/// arguments (up to 7) match. +/// +/// Instead of passing the matchers separately they can be passed as a single +/// List argument. Any argument that is not a matcher is implicitly wrapped in a +/// Matcher to check for equality. +Matcher allOf(arg0, [arg1, arg2, arg3, arg4, arg5, arg6]) { + return new _AllOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6)); +} + +class _AllOf extends Matcher { + final List _matchers; + + const _AllOf(this._matchers); + + bool matches(item, Map matchState) { + for (var matcher in _matchers) { + if (!matcher.matches(item, matchState)) { + addStateInfo(matchState, {'matcher': matcher}); + return false; + } + } + return true; + } + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + var matcher = matchState['matcher']; + matcher.describeMismatch( + item, mismatchDescription, matchState['state'], verbose); + return mismatchDescription; + } + + Description describe(Description description) => + description.addAll('(', ' and ', ')', _matchers); +} + +/// Matches if any of the given matchers evaluate to true. +/// +/// The arguments can be a set of matchers as separate parameters +/// (up to 7), or a List of matchers. +/// +/// The matchers are evaluated from left to right using short-circuit +/// evaluation, so evaluation stops as soon as a matcher returns true. +/// +/// Any argument that is not a matcher is implicitly wrapped in a +/// Matcher to check for equality. +Matcher anyOf(arg0, [arg1, arg2, arg3, arg4, arg5, arg6]) { + return new _AnyOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6)); +} + +class _AnyOf extends Matcher { + final List _matchers; + + const _AnyOf(this._matchers); + + bool matches(item, Map matchState) { + for (var matcher in _matchers) { + if (matcher.matches(item, matchState)) { + return true; + } + } + return false; + } + + Description describe(Description description) => + description.addAll('(', ' or ', ')', _matchers); +} + +List _wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + Iterable args; + if (arg0 is List) { + if (arg1 != null || + arg2 != null || + arg3 != null || + arg4 != null || + arg5 != null || + arg6 != null) { + throw new ArgumentError('If arg0 is a List, all other arguments must be' + ' null.'); + } + + args = arg0; + } else { + args = [arg0, arg1, arg2, arg3, arg4, arg5, arg6].where((e) => e != null); + } + + return args.map(wrapMatcher).toList(); +} +pNN<K<M3:INQ# + new _OrderingMatcher(value, false, false, true, 'a value greater than'); + +/// Returns a matcher which matches if the match argument is greater +/// than or equal to the given [value]. +Matcher greaterThanOrEqualTo(value) => new _OrderingMatcher( + value, true, false, true, 'a value greater than or equal to'); + +/// Returns a matcher which matches if the match argument is less +/// than the given [value]. +Matcher lessThan(value) => + new _OrderingMatcher(value, false, true, false, 'a value less than'); + +/// Returns a matcher which matches if the match argument is less +/// than or equal to the given [value]. +Matcher lessThanOrEqualTo(value) => new _OrderingMatcher( + value, true, true, false, 'a value less than or equal to'); + +/// A matcher which matches if the match argument is zero. +const Matcher isZero = + const _OrderingMatcher(0, true, false, false, 'a value equal to'); + +/// A matcher which matches if the match argument is non-zero. +const Matcher isNonZero = + const _OrderingMatcher(0, false, true, true, 'a value not equal to'); + +/// A matcher which matches if the match argument is positive. +const Matcher isPositive = + const _OrderingMatcher(0, false, false, true, 'a positive value', false); + +/// A matcher which matches if the match argument is zero or negative. +const Matcher isNonPositive = + const _OrderingMatcher(0, true, true, false, 'a non-positive value', false); + +/// A matcher which matches if the match argument is negative. +const Matcher isNegative = + const _OrderingMatcher(0, false, true, false, 'a negative value', false); + +/// A matcher which matches if the match argument is zero or positive. +const Matcher isNonNegative = + const _OrderingMatcher(0, true, false, true, 'a non-negative value', false); + +// TODO(kevmoo) Note that matchers that use _OrderingComparison only use +// `==` and `<` operators to evaluate the match. Or change the matcher. +class _OrderingMatcher extends Matcher { + /// Expected value. + final Object _value; + + /// What to return if actual == expected + final bool _equalValue; + + /// What to return if actual < expected + final bool _lessThanValue; + + /// What to return if actual > expected + final bool _greaterThanValue; + + /// Textual name of the inequality + final String _comparisonDescription; + + /// Whether to include the expected value in the description + final bool _valueInDescription; + + const _OrderingMatcher(this._value, this._equalValue, this._lessThanValue, + this._greaterThanValue, this._comparisonDescription, + [bool valueInDescription = true]) + : this._valueInDescription = valueInDescription; + + bool matches(item, Map matchState) { + if (item == _value) { + return _equalValue; + } else if (item < _value) { + return _lessThanValue; + } else { + return _greaterThanValue; + } + } + + Description describe(Description description) { + if (_valueInDescription) { + return description + .add(_comparisonDescription) + .add(' ') + .addDescriptionOf(_value); + } else { + return description.add(_comparisonDescription); + } + } + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + mismatchDescription.add('is not '); + return describe(mismatchDescription); + } +} +iNN<EME(=CBJB(:@;G?J?NGQ?NGQIH)+** %'?"M;(7'  2'% 6 M(*efile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/string_matchers.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'feature_matcher.dart'; +import 'interfaces.dart'; + +/// Returns a matcher which matches if the match argument is a string and +/// is equal to [value] when compared case-insensitively. +Matcher equalsIgnoringCase(String value) => new _IsEqualIgnoringCase(value); + +class _IsEqualIgnoringCase extends FeatureMatcher { + final String _value; + final String _matchValue; + + _IsEqualIgnoringCase(String value) + : _value = value, + _matchValue = value.toLowerCase(); + + bool typedMatches(String item, Map matchState) => + _matchValue == item.toLowerCase(); + + Description describe(Description description) => + description.addDescriptionOf(_value).add(' ignoring case'); +} + +/// Returns a matcher which matches if the match argument is a string and +/// is equal to [value], ignoring whitespace. +/// +/// In this matcher, "ignoring whitespace" means comparing with all runs of +/// whitespace collapsed to single space characters and leading and trailing +/// whitespace removed. +/// +/// For example, the following will all match successfully: +/// +/// expect("hello world", equalsIgnoringWhitespace("hello world")); +/// expect(" hello world", equalsIgnoringWhitespace("hello world")); +/// expect("hello world ", equalsIgnoringWhitespace("hello world")); +/// +/// The following will not match: +/// +/// expect("helloworld", equalsIgnoringWhitespace("hello world")); +/// expect("he llo world", equalsIgnoringWhitespace("hello world")); +Matcher equalsIgnoringWhitespace(String value) => + new _IsEqualIgnoringWhitespace(value); + +class _IsEqualIgnoringWhitespace extends FeatureMatcher { + final String _value; + final String _matchValue; + + _IsEqualIgnoringWhitespace(String value) + : _value = value, + _matchValue = collapseWhitespace(value); + + bool typedMatches(String item, Map matchState) => + _matchValue == collapseWhitespace(item); + + Description describe(Description description) => + description.addDescriptionOf(_matchValue).add(' ignoring whitespace'); + + Description describeTypedMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + return mismatchDescription + .add('is ') + .addDescriptionOf(collapseWhitespace(item)) + .add(' with whitespace compressed'); + } +} + +/// Returns a matcher that matches if the match argument is a string and +/// starts with [prefixString]. +Matcher startsWith(String prefixString) => new _StringStartsWith(prefixString); + +class _StringStartsWith extends FeatureMatcher { + final String _prefix; + + const _StringStartsWith(this._prefix); + + bool typedMatches(item, Map matchState) => item.startsWith(_prefix); + + Description describe(Description description) => + description.add('a string starting with ').addDescriptionOf(_prefix); +} + +/// Returns a matcher that matches if the match argument is a string and +/// ends with [suffixString]. +Matcher endsWith(String suffixString) => new _StringEndsWith(suffixString); + +class _StringEndsWith extends FeatureMatcher { + final String _suffix; + + const _StringEndsWith(this._suffix); + + bool typedMatches(item, Map matchState) => item.endsWith(_suffix); + + Description describe(Description description) => + description.add('a string ending with ').addDescriptionOf(_suffix); +} + +/// Returns a matcher that matches if the match argument is a string and +/// contains a given list of [substrings] in relative order. +/// +/// For example, `stringContainsInOrder(["a", "e", "i", "o", "u"])` will match +/// "abcdefghijklmnopqrstuvwxyz". + +Matcher stringContainsInOrder(List substrings) => + new _StringContainsInOrder(substrings); + +class _StringContainsInOrder extends FeatureMatcher { + final List _substrings; + + const _StringContainsInOrder(this._substrings); + + bool typedMatches(item, Map matchState) { + var fromIndex = 0; + for (var s in _substrings) { + fromIndex = item.indexOf(s, fromIndex); + if (fromIndex < 0) return false; + } + return true; + } + + Description describe(Description description) => description.addAll( + 'a string containing ', ', ', ' in order', _substrings); +} + +/// Returns a matcher that matches if the match argument is a string and +/// matches the regular expression given by [re]. +/// +/// [re] can be a [RegExp] instance or a [String]; in the latter case it will be +/// used to create a RegExp instance. +Matcher matches(re) => new _MatchesRegExp(re); + +class _MatchesRegExp extends FeatureMatcher { + RegExp _regexp; + + _MatchesRegExp(re) { + if (re is String) { + _regexp = new RegExp(re); + } else if (re is RegExp) { + _regexp = re; + } else { + throw new ArgumentError('matches requires a regexp or string'); + } + } + + bool typedMatches(item, Map matchState) => _regexp.hasMatch(item); + + Description describe(Description description) => + description.add("match '${_regexp.pattern}'"); +} + +/// Utility function to collapse whitespace runs to single spaces +/// and strip leading/trailing whitespace. +String collapseWhitespace(String string) { + var result = new StringBuffer(); + var skipSpace = true; + for (var i = 0; i < string.length; i++) { + var character = string[i]; + if (_isWhitespace(character)) { + if (!skipSpace) { + result.write(' '); + skipSpace = true; + } + } else { + result.write(character); + skipSpace = false; + } + } + return result.toString().trim(); +} + +bool _isWhitespace(String ch) => + ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; +NN<J:M<%+4)3BJ.LM<JJJ"GI2+B+14/3M%M4-I P9)G3LIL7'E3JI=O":,>"2,!.'G?I2Q&/6  FE35B++#,$ #!9bfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/type_matcher.dart// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'having_matcher.dart'; +import 'interfaces.dart'; + +/// A [Matcher] subclass that supports validating the [Type] of the target +/// object. +/// +/// ```dart +/// expect(shouldBeDuration, new TypeMatcher()); +/// ``` +/// +/// If you want to further validate attributes of the specified [Type], use the +/// [having] function. +/// +/// ```dart +/// void shouldThrowRangeError(int value) { +/// throw new RangeError.range(value, 10, 20); +/// } +/// +/// expect( +/// () => shouldThrowRangeError(5), +/// throwsA(const TypeMatcher() +/// .having((e) => e.start, 'start', greaterThanOrEqualTo(10)) +/// .having((e) => e.end, 'end', lessThanOrEqualTo(20)))); +/// ``` +/// +/// Notice that you can chain multiple calls to [having] to verify multiple +/// aspects of an object. +/// +/// Note: All of the top-level `isType` matchers exposed by this package are +/// instances of [TypeMatcher], so you can use the [having] function without +/// creating your own instance. +/// +/// ```dart +/// expect( +/// () => shouldThrowRangeError(5), +/// throwsA(isRangeError +/// .having((e) => e.start, 'start', greaterThanOrEqualTo(10)) +/// .having((e) => e.end, 'end', lessThanOrEqualTo(20)))); +/// ``` +class TypeMatcher extends Matcher { + final String _name; + const TypeMatcher( + [@Deprecated('Provide a type argument to TypeMatcher and omit the name. ' + 'This argument will be removed in the next release.') + String name]) + : this._name = + // ignore: deprecated_member_use + name; + + /// Returns a new [TypeMatcher] that validates the existing type as well as + /// a specific [feature] of the object with the provided [matcher]. + /// + /// Provides a human-readable [description] of the [feature] to make debugging + /// failures easier. + /// + /// ```dart + /// /// Validates that the object is a [RangeError] with a message containing + /// /// the string 'details' and `start` and `end` properties that are `null`. + /// final _rangeMatcher = isRangeError + /// .having((e) => e.message, 'message', contains('details')) + /// .having((e) => e.start, 'start', isNull) + /// .having((e) => e.end, 'end', isNull); + /// ``` + TypeMatcher having( + Object feature(T source), String description, Object matcher) => + new HavingMatcher(this, description, feature, matcher); + + Description describe(Description description) { + var name = _name ?? _stripDynamic(T); + return description.add(""); + } + + bool matches(Object item, Map matchState) => item is T; +} + +final _dart2DynamicArgs = new RegExp(''); + +/// With this expression `{}.runtimeType.toString`, +/// Dart 1: " +/// Dart 2: ">" +/// +/// This functions returns the Dart 1 output, when Dart 2 runtime semantics +/// are enabled. +String _stripDynamic(Type type) => + type.toString().replaceAll(_dart2DynamicArgs, ''); +[NN<K  ;P ,1 (0GCLMM  (GC'P@-NFQPQ)C2/ +K>2*5:?42L#7Zfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/util.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'core_matchers.dart'; +import 'equals_matcher.dart'; +import 'interfaces.dart'; + +typedef bool _Predicate(T value); + +/// A [Map] between whitespace characters and their escape sequences. +const _escapeMap = const { + '\n': r'\n', + '\r': r'\r', + '\f': r'\f', + '\b': r'\b', + '\t': r'\t', + '\v': r'\v', + '\x7F': r'\x7F', // delete +}; + +/// A [RegExp] that matches whitespace characters that should be escaped. +final _escapeRegExp = new RegExp( + "[\\x00-\\x07\\x0E-\\x1F${_escapeMap.keys.map(_getHexLiteral).join()}]"); + +/// Useful utility for nesting match states. +void addStateInfo(Map matchState, Map values) { + var innerState = new Map.from(matchState); + matchState.clear(); + matchState['state'] = innerState; + matchState.addAll(values); +} + +/// Takes an argument and returns an equivalent [Matcher]. +/// +/// If the argument is already a matcher this does nothing, +/// else if the argument is a function, it generates a predicate +/// function matcher, else it generates an equals matcher. +Matcher wrapMatcher(x) { + if (x is Matcher) { + return x; + } else if (x is _Predicate) { + // x is already a predicate that can handle anything + return predicate(x); + } else if (x is _Predicate) { + // x is a unary predicate, but expects a specific type + // so wrap it. + // ignore: unnecessary_lambdas + return predicate((a) => (x as dynamic)(a)); + } else { + return equals(x); + } +} + +/// Returns [str] with all whitespace characters represented as their escape +/// sequences. +/// +/// Backslash characters are escaped as `\\` +String escape(String str) { + str = str.replaceAll('\\', r'\\'); + return str.replaceAllMapped(_escapeRegExp, (match) { + var mapped = _escapeMap[match[0]]; + if (mapped != null) return mapped; + return _getHexLiteral(match[0]); + }); +} + +/// Given single-character string, return the hex-escaped equivalent. +String _getHexLiteral(String input) { + var rune = input.runes.single; + return r'\x' + rune.toRadixString(16).toUpperCase().padLeft(2, '0'); +} +JNN<%FJ"N-0-$;[0]; + + /// The code points of the characters in the file. + final Uint32List _decodedChars; + + /// The length of the file in characters. + int get length => _decodedChars.length; + + /// The number of lines in the file. + int get lines => _lineStarts.length; + + /// The line that the offset fell on the last time [getLine] was called. + /// + /// In many cases, sequential calls to getLine() are for nearby, usually + /// increasing offsets. In that case, we can find the line for an offset + /// quickly by first checking to see if the offset is on the same line as the + /// previous result. + int _cachedLine; + + /// This constructor is deprecated. + /// + /// Use [new SourceFile.fromString] instead. + @Deprecated("Will be removed in 2.0.0") + SourceFile(String text, {url}) : this.decoded(text.runes, url: url); + + /// Creates a new source file from [text]. + /// + /// [url] may be either a [String], a [Uri], or `null`. + SourceFile.fromString(String text, {url}) + : this.decoded(text.codeUnits, url: url); + + /// Creates a new source file from a list of decoded code units. + /// + /// [url] may be either a [String], a [Uri], or `null`. + /// + /// Currently, if [decodedChars] contains characters larger than `0xFFFF`, + /// they'll be treated as single characters rather than being split into + /// surrogate pairs. **This behavior is deprecated**. For + /// forwards-compatibility, callers should only pass in characters less than + /// or equal to `0xFFFF`. + SourceFile.decoded(Iterable decodedChars, {url}) + : url = url is String ? Uri.parse(url) : url, + _decodedChars = new Uint32List.fromList(decodedChars.toList()) { + for (var i = 0; i < _decodedChars.length; i++) { + var c = _decodedChars[i]; + if (c == _CR) { + // Return not followed by newline is treated as a newline + var j = i + 1; + if (j >= _decodedChars.length || _decodedChars[j] != _LF) c = _LF; + } + if (c == _LF) _lineStarts.add(i + 1); + } + } + + /// Returns a span in [this] from [start] to [end] (exclusive). + /// + /// If [end] isn't passed, it defaults to the end of the file. + FileSpan span(int start, [int end]) { + if (end == null) end = length - 1; + return new _FileSpan(this, start, end); + } + + /// Returns a location in [this] at [offset]. + FileLocation location(int offset) => new FileLocation._(this, offset); + + /// Gets the 0-based line corresponding to [offset]. + int getLine(int offset) { + if (offset < 0) { + throw new RangeError("Offset may not be negative, was $offset."); + } else if (offset > length) { + throw new RangeError("Offset $offset must not be greater than the number " + "of characters in the file, $length."); + } + + if (offset < _lineStarts.first) return -1; + if (offset >= _lineStarts.last) return _lineStarts.length - 1; + + if (_isNearCachedLine(offset)) return _cachedLine; + + _cachedLine = _binarySearch(offset) - 1; + return _cachedLine; + } + + /// Returns `true` if [offset] is near [_cachedLine]. + /// + /// Checks on [_cachedLine] and the next line. If it's on the next line, it + /// updates [_cachedLine] to point to that. + bool _isNearCachedLine(int offset) { + if (_cachedLine == null) return false; + + // See if it's before the cached line. + if (offset < _lineStarts[_cachedLine]) return false; + + // See if it's on the cached line. + if (_cachedLine >= _lineStarts.length - 1 || + offset < _lineStarts[_cachedLine + 1]) { + return true; + } + + // See if it's on the next line. + if (_cachedLine >= _lineStarts.length - 2 || + offset < _lineStarts[_cachedLine + 2]) { + _cachedLine++; + return true; + } + + return false; + } + + /// Binary search through [_lineStarts] to find the line containing [offset]. + /// + /// Returns the index of the line in [_lineStarts]. + int _binarySearch(int offset) { + int min = 0; + int max = _lineStarts.length - 1; + while (min < max) { + var half = min + ((max - min) ~/ 2); + if (_lineStarts[half] > offset) { + max = half; + } else { + min = half + 1; + } + } + + return max; + } + + /// Gets the 0-based column corresponding to [offset]. + /// + /// If [line] is passed, it's assumed to be the line containing [offset] and + /// is used to more efficiently compute the column. + int getColumn(int offset, {int line}) { + if (offset < 0) { + throw new RangeError("Offset may not be negative, was $offset."); + } else if (offset > length) { + throw new RangeError("Offset $offset must be not be greater than the " + "number of characters in the file, $length."); + } + + if (line == null) { + line = getLine(offset); + } else if (line < 0) { + throw new RangeError("Line may not be negative, was $line."); + } else if (line >= lines) { + throw new RangeError("Line $line must be less than the number of " + "lines in the file, $lines."); + } + + var lineStart = _lineStarts[line]; + if (lineStart > offset) { + throw new RangeError("Line $line comes after offset $offset."); + } + + return offset - lineStart; + } + + /// Gets the offset for a [line] and [column]. + /// + /// [column] defaults to 0. + int getOffset(int line, [int column]) { + if (column == null) column = 0; + + if (line < 0) { + throw new RangeError("Line may not be negative, was $line."); + } else if (line >= lines) { + throw new RangeError("Line $line must be less than the number of " + "lines in the file, $lines."); + } else if (column < 0) { + throw new RangeError("Column may not be negative, was $column."); + } + + var result = _lineStarts[line] + column; + if (result > length || + (line + 1 < lines && result >= _lineStarts[line + 1])) { + throw new RangeError("Line $line doesn't have $column columns."); + } + + return result; + } + + /// Returns the text of the file from [start] to [end] (exclusive). + /// + /// If [end] isn't passed, it defaults to the end of the file. + String getText(int start, [int end]) => + new String.fromCharCodes(_decodedChars.sublist(start, end)); +} + +/// A [SourceLocation] within a [SourceFile]. +/// +/// Unlike the base [SourceLocation], [FileLocation] lazily computes its line +/// and column values based on its offset and the contents of [file]. +/// +/// A [FileLocation] can be created using [SourceFile.location]. +class FileLocation extends SourceLocationMixin implements SourceLocation { + /// The [file] that [this] belongs to. + final SourceFile file; + + final int offset; + Uri get sourceUrl => file.url; + int get line => file.getLine(offset); + int get column => file.getColumn(offset); + + FileLocation._(this.file, this.offset) { + if (offset < 0) { + throw new RangeError("Offset may not be negative, was $offset."); + } else if (offset > file.length) { + throw new RangeError("Offset $offset must not be greater than the number " + "of characters in the file, ${file.length}."); + } + } + + FileSpan pointSpan() => new _FileSpan(file, offset, offset); +} + +/// A [SourceSpan] within a [SourceFile]. +/// +/// Unlike the base [SourceSpan], [FileSpan] lazily computes its line and column +/// values based on its offset and the contents of [file]. [FileSpan.message] is +/// also able to provide more context then [SourceSpan.message], and +/// [FileSpan.union] will return a [FileSpan] if possible. +/// +/// A [FileSpan] can be created using [SourceFile.span]. +abstract class FileSpan implements SourceSpanWithContext { + /// The [file] that [this] belongs to. + SourceFile get file; + + FileLocation get start; + FileLocation get end; + + /// Returns a new span that covers both [this] and [other]. + /// + /// Unlike [union], [other] may be disjoint from [this]. If it is, the text + /// between the two will be covered by the returned span. + FileSpan expand(FileSpan other); +} + +/// The implementation of [FileSpan]. +/// +/// This is split into a separate class so that `is _FileSpan` checks can be run +/// to make certain operations more efficient. If we used `is FileSpan`, that +/// would break if external classes implemented the interface. +class _FileSpan extends SourceSpanMixin implements FileSpan { + final SourceFile file; + + /// The offset of the beginning of the span. + /// + /// [start] is lazily generated from this to avoid allocating unnecessary + /// objects. + final int _start; + + /// The offset of the end of the span. + /// + /// [end] is lazily generated from this to avoid allocating unnecessary + /// objects. + final int _end; + + Uri get sourceUrl => file.url; + int get length => _end - _start; + FileLocation get start => new FileLocation._(file, _start); + FileLocation get end => new FileLocation._(file, _end); + String get text => file.getText(_start, _end); + String get context => file.getText(file.getOffset(start.line), + end.line == file.lines - 1 ? null : file.getOffset(end.line + 1)); + + _FileSpan(this.file, this._start, this._end) { + if (_end < _start) { + throw new ArgumentError('End $_end must come after start $_start.'); + } else if (_end > file.length) { + throw new RangeError("End $_end must not be greater than the number " + "of characters in the file, ${file.length}."); + } else if (_start < 0) { + throw new RangeError("Start may not be negative, was $_start."); + } + } + + int compareTo(SourceSpan other) { + if (other is! _FileSpan) return super.compareTo(other); + + _FileSpan otherFile = other; + var result = _start.compareTo(otherFile._start); + return result == 0 ? _end.compareTo(otherFile._end) : result; + } + + SourceSpan union(SourceSpan other) { + if (other is! FileSpan) return super.union(other); + + _FileSpan span = expand(other); + + if (other is _FileSpan) { + if (this._start > other._end || other._start > this._end) { + throw new ArgumentError("Spans $this and $other are disjoint."); + } + } else { + if (this._start > other.end.offset || other.start.offset > this._end) { + throw new ArgumentError("Spans $this and $other are disjoint."); + } + } + + return span; + } + + bool operator ==(other) { + if (other is! FileSpan) return super == other; + if (other is! _FileSpan) { + return super == other && sourceUrl == other.sourceUrl; + } + + return _start == other._start && + _end == other._end && + sourceUrl == other.sourceUrl; + } + + // Eliminates dart2js warning about overriding `==`, but not `hashCode` + int get hashCode => super.hashCode; + + /// Returns a new span that covers both [this] and [other]. + /// + /// Unlike [union], [other] may be disjoint from [this]. If it is, the text + /// between the two will be covered by the returned span. + FileSpan expand(FileSpan other) { + if (sourceUrl != other.sourceUrl) { + throw new ArgumentError("Source URLs \"${sourceUrl}\" and " + " \"${other.sourceUrl}\" don't match."); + } + + if (other is _FileSpan) { + var start = math.min(this._start, other._start); + var end = math.max(this._end, other._end); + return new _FileSpan(file, start, end); + } else { + var start = math.min(this._start, other.start.offset); + var end = math.max(this._end, other.end.offset); + return new _FileSpan(file, start, end); + } + } +} +rNN<!((P30K?LP 5",*''KKKP&/*G-:,0C:MKN<#&QN?>/L)J!#>:1AI1K%L9G$<!5B'7$BI NI3=%&J&>N<$(B371. =7.afile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/src/location.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'span.dart'; + +// TODO(nweiz): Use SourceLocationMixin once we decide to cut a release with +// breaking changes. See SourceLocationMixin for details. + +/// A class that describes a single location within a source file. +/// +/// This class should not be extended. Instead, [SourceLocationBase] should be +/// extended instead. +class SourceLocation implements Comparable { + /// URL of the source containing this location. + /// + /// This may be null, indicating that the source URL is unknown or + /// unavailable. + final Uri sourceUrl; + + /// The 0-based offset of this location in the source. + final int offset; + + /// The 0-based line of this location in the source. + final int line; + + /// The 0-based column of this location in the source + final int column; + + /// Returns a representation of this location in the `source:line:column` + /// format used by text editors. + /// + /// This prints 1-based lines and columns. + String get toolString { + var source = sourceUrl == null ? 'unknown source' : sourceUrl; + return '$source:${line + 1}:${column + 1}'; + } + + /// Creates a new location indicating [offset] within [sourceUrl]. + /// + /// [line] and [column] default to assuming the source is a single line. This + /// means that [line] defaults to 0 and [column] defaults to [offset]. + /// + /// [sourceUrl] may be either a [String], a [Uri], or `null`. + SourceLocation(int offset, {sourceUrl, int line, int column}) + : sourceUrl = sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl, + offset = offset, + line = line == null ? 0 : line, + column = column == null ? offset : column { + if (offset < 0) { + throw new RangeError("Offset may not be negative, was $offset."); + } else if (line != null && line < 0) { + throw new RangeError("Line may not be negative, was $line."); + } else if (column != null && column < 0) { + throw new RangeError("Column may not be negative, was $column."); + } + } + + /// Returns the distance in characters between [this] and [other]. + /// + /// This always returns a non-negative value. + int distance(SourceLocation other) { + if (sourceUrl != other.sourceUrl) { + throw new ArgumentError("Source URLs \"${sourceUrl}\" and " + "\"${other.sourceUrl}\" don't match."); + } + return (offset - other.offset).abs(); + } + + /// Returns a span that covers only a single point: this location. + SourceSpan pointSpan() => new SourceSpan(this, this, ""); + + /// Compares two locations. + /// + /// [other] must have the same source URL as [this]. + int compareTo(SourceLocation other) { + if (sourceUrl != other.sourceUrl) { + throw new ArgumentError("Source URLs \"${sourceUrl}\" and " + "\"${other.sourceUrl}\" don't match."); + } + return offset - other.offset; + } + + bool operator ==(other) => + other is SourceLocation && + sourceUrl == other.sourceUrl && + offset == other.offset; + + int get hashCode => sourceUrl.hashCode + offset; + + String toString() => '<$runtimeType: $offset $toolString>'; +} + +/// A base class for source locations with [offset], [line], and [column] known +/// at construction time. +class SourceLocationBase extends SourceLocation { + SourceLocationBase(int offset, {sourceUrl, int line, int column}) + : super(offset, sourceUrl: sourceUrl, line: line, column: column); +} +eNN<M:CO=2E978L#-C0EPI@@L(4H+D/HE0'(B2*E<7((B2"!&3>P2DIgfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/src/location_mixin.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'location.dart'; +import 'span.dart'; + +// Note: this class duplicates a lot of functionality of [SourceLocation]. This +// is because in order for SourceLocation to use SourceLocationMixin, +// SourceLocationMixin couldn't implement SourceLocation. In SourceSpan we +// handle this by making the class itself non-extensible, but that would be a +// breaking change for SourceLocation. So until we want to endure the pain of +// cutting a release with breaking changes, we duplicate the code here. + +/// A mixin for easily implementing [SourceLocation]. +abstract class SourceLocationMixin implements SourceLocation { + String get toolString { + var source = sourceUrl == null ? 'unknown source' : sourceUrl; + return '$source:${line + 1}:${column + 1}'; + } + + int distance(SourceLocation other) { + if (sourceUrl != other.sourceUrl) { + throw new ArgumentError("Source URLs \"${sourceUrl}\" and " + "\"${other.sourceUrl}\" don't match."); + } + return (offset - other.offset).abs(); + } + + SourceSpan pointSpan() => new SourceSpan(this, this, ""); + + int compareTo(SourceLocation other) { + if (sourceUrl != other.sourceUrl) { + throw new ArgumentError("Source URLs \"${sourceUrl}\" and " + "\"${other.sourceUrl}\" don't match."); + } + return offset - other.offset; + } + + bool operator ==(other) => + other is SourceLocation && + sourceUrl == other.sourceUrl && + offset == other.offset; + + int get hashCode => sourceUrl.hashCode + offset; + + String toString() => '<$runtimeType: $offset $toolString>'; +} +2NN<PFKNNH6?C0'(B2*<((B2"!&3>]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/src/span.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'location.dart'; +import 'span_mixin.dart'; + +/// A class that describes a segment of source text. +abstract class SourceSpan implements Comparable { + /// The start location of this span. + SourceLocation get start; + + /// The end location of this span, exclusive. + SourceLocation get end; + + /// The source text for this span. + String get text; + + /// The URL of the source (typically a file) of this span. + /// + /// This may be null, indicating that the source URL is unknown or + /// unavailable. + Uri get sourceUrl; + + /// The length of this span, in characters. + int get length; + + /// Creates a new span from [start] to [end] (exclusive) containing [text]. + /// + /// [start] and [end] must have the same source URL and [start] must come + /// before [end]. [text] must have a number of characters equal to the + /// distance between [start] and [end]. + factory SourceSpan(SourceLocation start, SourceLocation end, String text) => + new SourceSpanBase(start, end, text); + + /// Creates a new span that's the union of [this] and [other]. + /// + /// The two spans must have the same source URL and may not be disjoint. + /// [text] is computed by combining [this.text] and [other.text]. + SourceSpan union(SourceSpan other); + + /// Compares two spans. + /// + /// [other] must have the same source URL as [this]. This orders spans by + /// [start] then [length]. + int compareTo(SourceSpan other); + + /// Formats [message] in a human-friendly way associated with this span. + /// + /// [color] may either be a [String], a [bool], or `null`. If it's a string, + /// it indicates an ANSII terminal color escape that should be used to + /// highlight the span's text. If it's `true`, it indicates that the text + /// should be highlighted using the default color. If it's `false` or `null`, + /// it indicates that the text shouldn't be highlighted. + String message(String message, {color}); + + /// Prints the text associated with this span in a user-friendly way. + /// + /// This is identical to [message], except that it doesn't print the file + /// name, line number, column number, or message. If [length] is 0 and this + /// isn't a [SourceSpanWithContext], returns an empty string. + /// + /// [color] may either be a [String], a [bool], or `null`. If it's a string, + /// it indicates an ANSII terminal color escape that should be used to + /// highlight the span's text. If it's `true`, it indicates that the text + /// should be highlighted using the default color. If it's `false` or `null`, + /// it indicates that the text shouldn't be highlighted. + String highlight({color}); +} + +/// A base class for source spans with [start], [end], and [text] known at +/// construction time. +class SourceSpanBase extends SourceSpanMixin { + final SourceLocation start; + final SourceLocation end; + final String text; + + SourceSpanBase(this.start, this.end, this.text) { + if (end.sourceUrl != start.sourceUrl) { + throw new ArgumentError("Source URLs \"${start.sourceUrl}\" and " + " \"${end.sourceUrl}\" don't match."); + } else if (end.offset < start.offset) { + throw new ArgumentError('End $end must come after start $start.'); + } else if (text.length != start.distance(end)) { + throw new ArgumentError('Text "$text" must be ${start.distance(end)} ' + 'characters long.'); + } + } +} +[NN<5>'0%=E.NLI*O,AKD&L#KOILP;+HLN@OILP;K/4,H1,I5Mgfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/src/span_exception.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'span.dart'; + +/// A class for exceptions that have source span information attached. +class SourceSpanException implements Exception { + // This is a getter so that subclasses can override it. + /// A message describing the exception. + String get message => _message; + final String _message; + + // This is a getter so that subclasses can override it. + /// The span associated with this exception. + /// + /// This may be `null` if the source location can't be determined. + SourceSpan get span => _span; + final SourceSpan _span; + + SourceSpanException(this._message, this._span); + + /// Returns a string representation of [this]. + /// + /// [color] may either be a [String], a [bool], or `null`. If it's a string, + /// it indicates an ANSII terminal color escape that should be used to + /// highlight the span's text. If it's `true`, it indicates that the text + /// should be highlighted using the default color. If it's `false` or `null`, + /// it indicates that the text shouldn't be highlighted. + String toString({color}) { + if (span == null) return message; + return "Error on " + span.message(message, color: color); + } +} + +/// A [SourceSpanException] that's also a [FormatException]. +class SourceSpanFormatException extends SourceSpanException + implements FormatException { + // This is a getter so that subclasses can override it. + dynamic get source => _source; + final _source; + + int get offset => span == null ? null : span.start.offset; + + SourceSpanFormatException(String message, SourceSpan span, [this._source]) + : super(message, span); +} +1NN<G1:*":/E 21OILP;&>= start.sourceUrl; + int get length => end.offset - start.offset; + + int compareTo(SourceSpan other) { + var result = start.compareTo(other.start); + return result == 0 ? end.compareTo(other.end) : result; + } + + SourceSpan union(SourceSpan other) { + if (sourceUrl != other.sourceUrl) { + throw new ArgumentError("Source URLs \"${sourceUrl}\" and " + " \"${other.sourceUrl}\" don't match."); + } + + var start = min(this.start, other.start); + var end = max(this.end, other.end); + var beginSpan = start == this.start ? this : other; + var endSpan = end == this.end ? this : other; + + if (beginSpan.end.compareTo(endSpan.start) < 0) { + throw new ArgumentError("Spans $this and $other are disjoint."); + } + + var text = beginSpan.text + + endSpan.text.substring(beginSpan.end.distance(endSpan.start)); + return new SourceSpan(start, end, text); + } + + String message(String message, {color}) { + var buffer = new StringBuffer(); + buffer.write('line ${start.line + 1}, column ${start.column + 1}'); + if (sourceUrl != null) buffer.write(' of ${p.prettyUri(sourceUrl)}'); + buffer.write(': $message'); + + var highlight = this.highlight(color: color); + if (!highlight.isEmpty) { + buffer.writeln(); + buffer.write(highlight); + } + + return buffer.toString(); + } + + String highlight({color}) { + if (color == true) color = colors.RED; + if (color == false) color = null; + + var column = start.column; + var buffer = new StringBuffer(); + String textLine; + if (this is SourceSpanWithContext) { + var context = (this as SourceSpanWithContext).context; + var lineStart = findLineStart(context, text, column); + if (lineStart != null && lineStart > 0) { + buffer.write(context.substring(0, lineStart)); + context = context.substring(lineStart); + } + var endIndex = context.indexOf('\n'); + textLine = endIndex == -1 ? context : context.substring(0, endIndex + 1); + column = math.min(column, textLine.length); + } else if (length == 0) { + return ""; + } else { + textLine = text.split("\n").first; + column = 0; + } + + var toColumn = + math.min(column + end.offset - start.offset, textLine.length); + if (color != null) { + buffer.write(textLine.substring(0, column)); + buffer.write(color); + buffer.write(textLine.substring(column, toColumn)); + buffer.write(colors.NONE); + buffer.write(textLine.substring(toColumn)); + } else { + buffer.write(textLine); + } + if (!textLine.endsWith('\n')) buffer.write('\n'); + + for (var i = 0; i < column; i++) { + if (textLine.codeUnitAt(i) == $tab) { + buffer.writeCharCode($tab); + } else { + buffer.writeCharCode($space); + } + } + + if (color != null) buffer.write(color); + buffer.write('^' * math.max(toColumn - column, 1)); + if (color != null) buffer.write(colors.NONE); + return buffer.toString(); + } + + bool operator ==(other) => + other is SourceSpan && start == other.start && end == other.end; + + int get hashCode => start.hashCode + (31 * end.hashCode); + + String toString() => '<$runtimeType: from $start to $end "$text">'; +} +|NN<)& !2MOQ/7(/$/<'(B3.(826G G-,%HJ 2+&%)=<070,P2 )G3:!2 6',$&,82G<Fjfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/src/span_with_context.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'location.dart'; +import 'span.dart'; +import 'utils.dart'; + +/// A class that describes a segment of source text with additional context. +class SourceSpanWithContext extends SourceSpanBase { + // This is a getter so that subclasses can override it. + /// Text around the span, which includes the line containing this span. + String get context => _context; + final String _context; + + /// Creates a new span from [start] to [end] (exclusive) containing [text], in + /// the given [context]. + /// + /// [start] and [end] must have the same source URL and [start] must come + /// before [end]. [text] must have a number of characters equal to the + /// distance between [start] and [end]. [context] must contain [text], and + /// [text] should start at `start.column` from the beginning of a line in + /// [context]. + SourceSpanWithContext( + SourceLocation start, SourceLocation end, String text, this._context) + : super(start, end, text) { + if (!context.contains(text)) { + throw new ArgumentError( + 'The context line "$context" must contain "$text".'); + } + + if (findLineStart(context, text, start.column) == null) { + throw new ArgumentError('The span text "$text" must start at ' + 'column ${start.column + 1} in a line within "$context".'); + } + } +} +'NN<M5:J"QLIMLL"#@>EFnfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/src/eager_span_scanner.dartU// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:charcode/ascii.dart'; + +import 'line_scanner.dart'; +import 'span_scanner.dart'; + +// TODO(nweiz): Currently this duplicates code in line_scanner.dart. Once +// sdk#23770 is fully complete, we should move the shared code into a mixin. + +/// A regular expression matching newlines across platforms. +final _newlineRegExp = new RegExp(r"\r\n?|\n"); + +/// A [SpanScanner] that tracks the line and column eagerly, like [LineScanner]. +class EagerSpanScanner extends SpanScanner { + int get line => _line; + int _line = 0; + + int get column => _column; + int _column = 0; + + LineScannerState get state => + new _EagerSpanScannerState(this, position, line, column); + + bool get _betweenCRLF => peekChar(-1) == $cr && peekChar() == $lf; + + set state(LineScannerState state) { + if (state is! _EagerSpanScannerState || + !identical((state as _EagerSpanScannerState)._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + super.position = state.position; + _line = state.line; + _column = state.column; + } + + set position(int newPosition) { + var oldPosition = position; + super.position = newPosition; + + if (newPosition > oldPosition) { + var newlines = _newlinesIn(string.substring(oldPosition, newPosition)); + _line += newlines.length; + if (newlines.isEmpty) { + _column += newPosition - oldPosition; + } else { + _column = newPosition - newlines.last.end; + } + } else { + var newlines = _newlinesIn(string.substring(newPosition, oldPosition)); + if (_betweenCRLF) newlines.removeLast(); + + _line -= newlines.length; + if (newlines.isEmpty) { + _column -= oldPosition - newPosition; + } else { + _column = + newPosition - string.lastIndexOf(_newlineRegExp, newPosition) - 1; + } + } + } + + EagerSpanScanner(String string, {sourceUrl, int position}) + : super(string, sourceUrl: sourceUrl, position: position); + + bool scanChar(int character) { + if (!super.scanChar(character)) return false; + _adjustLineAndColumn(character); + return true; + } + + int readChar() { + var character = super.readChar(); + _adjustLineAndColumn(character); + return character; + } + + /// Adjusts [_line] and [_column] after having consumed [character]. + void _adjustLineAndColumn(int character) { + if (character == $lf || (character == $cr && peekChar() != $lf)) { + _line += 1; + _column = 0; + } else { + _column += 1; + } + } + + bool scan(Pattern pattern) { + if (!super.scan(pattern)) return false; + + var newlines = _newlinesIn(lastMatch[0]); + _line += newlines.length; + if (newlines.isEmpty) { + _column += lastMatch[0].length; + } else { + _column = lastMatch[0].length - newlines.last.end; + } + + return true; + } + + /// Returns a list of [Match]es describing all the newlines in [text], which + /// is assumed to end at [position]. + List _newlinesIn(String text) { + var newlines = _newlineRegExp.allMatches(text).toList(); + if (_betweenCRLF) newlines.removeLast(); + return newlines; + } +} + +/// A class representing the state of an [EagerSpanScanner]. +class _EagerSpanScannerState implements LineScannerState { + final EagerSpanScanner _scanner; + final int position; + final int line; + final int column; + + _EagerSpanScannerState(this._scanner, this.position, this.line, this.column); +} +}NN<&JM=0Q- @E&,HP %" "%N .3 N/ .O=A!2%&%G-G ,.& 9O')=-=;#Pqfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/src/relative_span_scanner.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +import 'exception.dart'; +import 'line_scanner.dart'; +import 'span_scanner.dart'; +import 'string_scanner.dart'; +import 'utils.dart'; + +/// A [SpanScanner] that scans within an existing [FileSpan]. +/// +/// This re-implements chunks of [SpanScanner] rather than using a dummy span or +/// inheritance because scanning is often a performance-critical operation, so +/// it's important to avoid adding extra overhead when relative scanning isn't +/// needed. +class RelativeSpanScanner extends StringScanner implements SpanScanner { + /// The source of the scanner. + /// + /// This caches line break information and is used to generate [Span]s. + final SourceFile _sourceFile; + + /// The start location of the span within which this scanner is scanning. + /// + /// This is used to convert between span-relative and file-relative fields. + final FileLocation _startLocation; + + int get line => + _sourceFile.getLine(_startLocation.offset + position) - + _startLocation.line; + + int get column { + var line = _sourceFile.getLine(_startLocation.offset + position); + var column = + _sourceFile.getColumn(_startLocation.offset + position, line: line); + return line == _startLocation.line + ? column - _startLocation.column + : column; + } + + LineScannerState get state => new _SpanScannerState(this, position); + + set state(LineScannerState state) { + if (state is! _SpanScannerState || + !identical((state as _SpanScannerState)._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + this.position = state.position; + } + + FileSpan get lastSpan => _lastSpan; + FileSpan _lastSpan; + + FileLocation get location => + _sourceFile.location(_startLocation.offset + position); + + FileSpan get emptySpan => location.pointSpan(); + + RelativeSpanScanner(FileSpan span) + : _sourceFile = span.file, + _startLocation = span.start, + super(span.text, sourceUrl: span.sourceUrl); + + FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { + var endPosition = endState == null ? position : endState.position; + return _sourceFile.span(_startLocation.offset + startState.position, + _startLocation.offset + endPosition); + } + + bool matches(Pattern pattern) { + if (!super.matches(pattern)) { + _lastSpan = null; + return false; + } + + _lastSpan = _sourceFile.span(_startLocation.offset + position, + _startLocation.offset + lastMatch.end); + return true; + } + + void error(String message, {Match match, int position, int length}) { + validateErrorArgs(string, match, position, length); + + if (match == null && position == null && length == null) match = lastMatch; + if (position == null) { + position = match == null ? this.position : match.start; + } + if (length == null) length = match == null ? 1 : match.end - match.start; + + var span = _sourceFile.span(_startLocation.offset + position, + _startLocation.offset + position + length); + throw new StringScannerException(message, span, string); + } +} + +/// A class representing the state of a [SpanScanner]. +class _SpanScannerState implements LineScannerState { + /// The [SpanScanner] that created this. + final RelativeSpanScanner _scanner; + + final int position; + int get line => _scanner._sourceFile.getLine(position); + int get column => _scanner._sourceFile.getColumn(position); + + _SpanScannerState(this._scanner, this.position); +} +pNN</>QOO I!J LN%>FM')G&'CP $&>2%!%5PGI."#C0H8P>NB4=76+&:>3afile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/src/utils.dart?// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Validates the arguments passed to [StringScanner.error]. +void validateErrorArgs(String string, Match match, int position, int length) { + if (match != null && (position != null || length != null)) { + throw new ArgumentError("Can't pass both match and position/length."); + } + + if (position != null) { + if (position < 0) { + throw new RangeError("position must be greater than or equal to 0."); + } else if (position > string.length) { + throw new RangeError("position must be less than or equal to the " + "string length."); + } + } + + if (length != null && length < 0) { + throw new RangeError("length must be greater than or equal to 0."); + } + + if (position != null && length != null && position + length > string.length) { + throw new RangeError("position plus length must not go beyond the end of " + "the string."); + } +} +NN<=O?KL+I&HQOgfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_server-0.9.8/lib/src/http_body_impl.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library http_server.http_body_impl; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:mime/mime.dart'; + +import 'http_body.dart'; +import 'http_multipart_form_data.dart'; + +class HttpBodyHandlerTransformer + extends StreamTransformerBase { + final Encoding _defaultEncoding; + + const HttpBodyHandlerTransformer(this._defaultEncoding); + + Stream bind(Stream stream) { + return new Stream.eventTransformed( + stream, + (EventSink sink) => + new _HttpBodyHandlerTransformerSink(_defaultEncoding, sink)); + } +} + +class _HttpBodyHandlerTransformerSink implements EventSink { + final Encoding _defaultEncoding; + final EventSink _outSink; + int _pending = 0; + bool _closed = false; + + _HttpBodyHandlerTransformerSink(this._defaultEncoding, this._outSink); + + void add(HttpRequest request) { + _pending++; + HttpBodyHandlerImpl.processRequest(request, _defaultEncoding) + .then(_outSink.add, onError: _outSink.addError) + .whenComplete(() { + _pending--; + if (_closed && _pending == 0) _outSink.close(); + }); + } + + void addError(Object error, [StackTrace stackTrace]) { + _outSink.addError(error, stackTrace); + } + + void close() { + _closed = true; + if (_pending == 0) _outSink.close(); + } +} + +class HttpBodyHandlerImpl { + static Future processRequest( + HttpRequest request, Encoding defaultEncoding) { + return process(request, request.headers, defaultEncoding) + .then((body) => new _HttpRequestBody(request, body), onError: (error) { + // Try to send BAD_REQUEST response. + request.response.statusCode = HttpStatus.badRequest; + request.response.close(); + throw error; + }); + } + + static Future processResponse( + HttpClientResponse response, Encoding defaultEncoding) { + return process(response, response.headers, defaultEncoding) + .then((body) => new _HttpClientResponseBody(response, body)); + } + + static Future process( + Stream> stream, HttpHeaders headers, Encoding defaultEncoding) { + var contentType = headers.contentType; + + Future asBinary() { + return stream + .fold(new BytesBuilder(), (builder, data) => builder..add(data)) + .then((builder) => new _HttpBody("binary", builder.takeBytes())); + } + + Future asText(Encoding defaultEncoding) { + Encoding encoding; + var charset = contentType.charset; + if (charset != null) encoding = Encoding.getByName(charset); + encoding ??= defaultEncoding; + return stream + .transform(encoding.decoder) + .fold(new StringBuffer(), (buffer, data) => buffer..write(data)) + .then((buffer) => new _HttpBody("text", buffer.toString())); + } + + Future asFormData() { + return stream + .transform( + new MimeMultipartTransformer(contentType.parameters['boundary'])) + .map((part) => HttpMultipartFormData.parse(part, + defaultEncoding: defaultEncoding)) + .map((multipart) { + Future future; + if (multipart.isText) { + future = multipart + .fold(new StringBuffer(), (b, s) => b..write(s)) + .then((b) => b.toString()); + } else { + future = multipart + .fold(new BytesBuilder(), (b, d) => b..add(d)) + .then((b) => b.takeBytes()); + } + return future.then((data) { + var filename = + multipart.contentDisposition.parameters['filename']; + if (filename != null) { + data = new _HttpBodyFileUpload( + multipart.contentType, filename, data); + } + return [multipart.contentDisposition.parameters['name'], data]; + }); + }) + .fold([], (l, f) => l..add(f)) + .then((values) => Future.wait(values as List)) + .then((parts) { + var map = {}; + for (var part in parts) { + map[part[0] as String] = part[1]; // Override existing entries. + } + return new _HttpBody('form', map); + }); + } + + if (contentType == null) { + return asBinary(); + } + + switch (contentType.primaryType) { + case "text": + return asText(defaultEncoding); + + case "application": + switch (contentType.subType) { + case "json": + return asText(utf8) + .then((body) => new _HttpBody("json", jsonDecode(body.body))); + + case "x-www-form-urlencoded": + return asText(ascii).then((body) { + var map = + Uri.splitQueryString(body.body, encoding: defaultEncoding); + var result = {}; + for (var key in map.keys) { + result[key] = map[key]; + } + return new _HttpBody("form", result); + }); + + default: + break; + } + break; + + case "multipart": + switch (contentType.subType) { + case "form-data": + return asFormData(); + + default: + break; + } + break; + + default: + break; + } + + return asBinary(); + } +} + +class _HttpBodyFileUpload implements HttpBodyFileUpload { + final ContentType contentType; + final String filename; + final dynamic content; + _HttpBodyFileUpload(this.contentType, this.filename, this.content); +} + +class _HttpBody implements HttpBody { + final String type; + final dynamic body; + + _HttpBody(this.type, this.body); +} + +class _HttpRequestBody extends _HttpBody implements HttpRequestBody { + final HttpRequest request; + + _HttpRequestBody(this.request, HttpBody body) : super(body.type, body.body); +} + +class _HttpClientResponseBody extends _HttpBody + implements HttpClientResponseBody { + final HttpClientResponse response; + + _HttpClientResponseBody(this.response, HttpBody body) + : super(body.type, body.body); +} +NN<$!(!B#;=9-JJ#-I"B869*)17>P+; 9?@F#Q+"KL8)C$'KG$P;1$!C.!A/(G&0<N )A+&N/'(' O(/N*(4 +'! +:!F&#FO0(%8%vfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/http_server-0.9.8/lib/src/http_multipart_form_data_impl.dartm// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library http_server.http_multipart_form_data_impl; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:mime/mime.dart'; + +import 'http_multipart_form_data.dart'; + +class HttpMultipartFormDataImpl extends Stream + implements HttpMultipartFormData { + final ContentType contentType; + final HeaderValue contentDisposition; + final HeaderValue contentTransferEncoding; + + final MimeMultipart _mimeMultipart; + + bool _isText = false; + + Stream _stream; + + HttpMultipartFormDataImpl( + this.contentType, + this.contentDisposition, + this.contentTransferEncoding, + this._mimeMultipart, + Encoding defaultEncoding) { + _stream = _mimeMultipart; + if (contentTransferEncoding != null) { + // TODO(ajohnsen): Support BASE64, etc. + throw new HttpException("Unsupported contentTransferEncoding: " + "${contentTransferEncoding.value}"); + } + + if (contentType == null || + contentType.primaryType == 'text' || + contentType.mimeType == 'application/json') { + _isText = true; + Encoding encoding; + if (contentType != null && contentType.charset != null) { + encoding = Encoding.getByName(contentType.charset); + } + encoding ??= defaultEncoding; + _stream = _stream.transform(encoding.decoder); + } + } + + bool get isText => _isText; + bool get isBinary => !_isText; + + static HttpMultipartFormData parse( + MimeMultipart multipart, Encoding defaultEncoding) { + ContentType type; + HeaderValue encoding; + HeaderValue disposition; + var remaining = {}; + for (var key in multipart.headers.keys) { + switch (key) { + case 'content-type': + type = ContentType.parse(multipart.headers[key]); + break; + + case 'content-transfer-encoding': + encoding = HeaderValue.parse(multipart.headers[key]); + break; + + case 'content-disposition': + disposition = HeaderValue.parse(multipart.headers[key], + preserveBackslash: true); + break; + + default: + remaining[key] = multipart.headers[key]; + break; + } + } + if (disposition == null) { + throw const HttpException( + "Mime Multipart doesn't contain a Content-Disposition header value"); + } + return new HttpMultipartFormDataImpl( + type, disposition, encoding, multipart, defaultEncoding); + } + + StreamSubscription listen(void onData(data), + {void onDone(), Function onError, bool cancelOnError}) { + return _stream.listen(onData, + onDone: onDone, onError: onError, cancelOnError: cancelOnError); + } + + String value(String name) { + return _mimeMultipart.headers[name]; + } +} +eNN<3!(/'!(-&$"+.F/-6@<$5!&;(.<*@$B(3!P*B/?"I)_file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/utils.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A pair of values. +class Pair { + E first; + F last; + + Pair(this.first, this.last); +} + +/// Returns a [Comparator] that asserts that its first argument is comparable. +Comparator defaultCompare() => + (value1, value2) => (value1 as Comparable).compareTo(value2); +NN< +O%Bpfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/src/empty_unmodifiable_set.dart-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'unmodifiable_wrappers.dart'; + +// Unfortunately, we can't use UnmodifiableSetMixin here, since const classes +// can't use mixins. +/// An unmodifiable, empty set that can have a const constructor. +class EmptyUnmodifiableSet extends IterableBase + implements UnmodifiableSetView { + static T _throw() { + throw new UnsupportedError("Cannot modify an unmodifiable Set"); + } + + Iterator get iterator => new Iterable.empty().iterator; + int get length => 0; + + const EmptyUnmodifiableSet(); + + EmptyUnmodifiableSet cast() => new EmptyUnmodifiableSet(); + bool contains(Object element) => false; + bool containsAll(Iterable other) => other.isEmpty; + Iterable followedBy(Iterable other) => new Set.from(other); + E lookup(Object element) => null; + @deprecated + EmptyUnmodifiableSet retype() => new EmptyUnmodifiableSet(); + E singleWhere(bool test(E element), {E orElse()}) => super.singleWhere(test); + Iterable whereType() => new EmptyUnmodifiableSet(); + Set toSet() => new Set(); + Set union(Set other) => new Set.from(other); + Set intersection(Set other) => new Set(); + Set difference(Set other) => new Set(); + + bool add(E value) => _throw(); + void addAll(Iterable elements) => _throw(); + void clear() => _throw(); + bool remove(Object element) => _throw(); + void removeAll(Iterable elements) => _throw(); + void removeWhere(bool test(E element)) => _throw(); + void retainWhere(bool test(E element)) => _throw(); + void retainAll(Iterable elements) => _throw(); +} +/NN<%NB6(E@ F*=D$HP?575!1+9669Qfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/uuid-1.0.3/lib/aes.dartlibrary AES; + +/** + * AES for Dart + * + * Copyright (c) 2012 Yulian Kuncheff + * + * Released under MIT License. + * + * Based on AES implementation in JavaScript by Chris Veness + */ + +class AES { + static List cipher(List input, List keySchedule) { + int blockSize = 4; //block size - fixed at 4 for AES + int numRounds = keySchedule.length ~/ blockSize - + 1; // number of rounds (10/12/14 for 128/192/256-bit keys) + + // Initialize 4xNb byte-array 'state' with input [§3.4] + var state = >[new List(4), new List(4), new List(4), new List(4)]; + for (int i = 0; i < 4 * blockSize; i++) { + int r = i % 4; + int c = (i ~/ 4).floor(); + state[r][c] = input[i]; + } + + state = _addRoundKey(state, keySchedule, 0, blockSize); + for (int round = 1; round < numRounds; round++) { + state = _subBytes(state, blockSize); + state = _shiftRows(state, blockSize); + state = _mixColumns(state, blockSize); + state = _addRoundKey(state, keySchedule, round, blockSize); + } + + state = _subBytes(state, blockSize); + state = _shiftRows(state, blockSize); + state = _addRoundKey(state, keySchedule, numRounds, blockSize); + + var output = new List(4 * blockSize); + for (int i = 0; i < 4 * blockSize; i++) { + output[i] = state[i % 4][(i ~/ 4).floor()]; + } + return output; + } + + static List keyExpansion(List key) { + int blockSize = 4; + int keyLength = key.length ~/ 4; + int numRounds = keyLength + 6; + + var keySchedule = new List((blockSize * (numRounds + 1)).toInt()); + var temp = new List(4); + + for (int i = 0; i < keyLength; i++) { + var row = [key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]]; + keySchedule[i] = row; + } + + for (int i = keyLength; i < (blockSize * (numRounds + 1)); i++) { + keySchedule[i] = new List(4); + for (int t = 0; t < 4; t++) { + temp[t] = keySchedule[i - 1][t]; + } + if (i % keyLength == 0) { + temp = _subWord(_rotWord(temp)); + for (int t = 0; t < 4; t++) { + temp[t] ^= _rCon[i ~/ keyLength][t]; + } + } else if (keyLength > 6 && i % keyLength == 4) { + temp = _subWord(temp); + } + for (int t = 0; t < 4; t++) { + keySchedule[i][t] = keySchedule[i - keyLength][t] ^ temp[t]; + } + } + + return keySchedule; + } + + static List> _subBytes(List> state, int blockSize) { + for (int row = 0; row < 4; row++) { + for (int column = 0; column < blockSize; column++) { + state[row][column] = _sBox[state[row][column]]; + } + } + return state; + } + + static List> _shiftRows(List> state, int blockSize) { + var temp = new List(4); + for (int row = 1; row < 4; row++) { + for (int column = 0; column < 4; column++) { + temp[column] = state[row][(column + row) % blockSize]; + } + for (int column = 0; column < 4; column++) { + state[row][column] = temp[column]; + } + } + return state; + } + + static List> _mixColumns(List> state, int blockSize) { + for (int column = 0; column < 4; column++) { + var a = new List(4); + var b = new List(4); + for (int i = 0; i < 4; i++) { + a[i] = state[i][column]; + b[i] = (state[i][column] & 0x80) != 0 + ? state[i][column] << 1 ^ 0x011b + : state[i][column] << 1; + } + + state[0][column] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; + state[1][column] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; + state[2][column] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; + state[3][column] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; + } + return state; + } + + static List> _addRoundKey( + List> state, List keySchedule, int round, int blockSize) { + for (int row = 0; row < 4; row++) { + for (int column = 0; column < blockSize; column++) { + state[row][column] ^= keySchedule[round * 4 + column][row]; + } + } + return state; + } + + static _subWord(List keySchedule) { + for (int i = 0; i < 4; i++) { + _sBox[keySchedule[i]]; + } + return keySchedule; + } + + static _rotWord(List keySchedule) { + var temp = keySchedule[0]; + for (int i = 0; i < 3; i++) { + keySchedule[i] = keySchedule[i + 1]; + } + keySchedule[3] = temp; + return keySchedule; + } + + static const _sBox = const [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, + 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, + 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, + 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, + 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, + 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, + 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, + 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, + 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, + 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, + 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, + 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, + 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, + 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, + 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, + 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16]; + + static const _rCon = const [ + const [0x00, 0x00, 0x00, 0x00], + const [0x01, 0x00, 0x00, 0x00], + const [0x02, 0x00, 0x00, 0x00], + const [0x04, 0x00, 0x00, 0x00], + const [0x08, 0x00, 0x00, 0x00], + const [0x10, 0x00, 0x00, 0x00], + const [0x20, 0x00, 0x00, 0x00], + const [0x40, 0x00, 0x00, 0x00], + const [0x80, 0x00, 0x00, 0x00], + const [0x1b, 0x00, 0x00, 0x00], + const [0x36, 0x00, 0x00, 0x00] + ]; +} + ' > 596C bytes; + + Digest(this.bytes); + + /// Returns whether this is equal to another digest. + /// + /// This should be used instead of manual comparisons to avoid leaking + /// information via timing. + @override + bool operator ==(Object other) => + other is Digest && const ListEquality().equals(bytes, other.bytes); + + @override + int get hashCode => const ListEquality().hash(bytes); + + /// The message digest as a string of hexadecimal digits. + @override + String toString() => hex.encode(bytes); +} +NN<-'A/7I $J 8< *Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/hash.dartC// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'digest.dart'; +import 'digest_sink.dart'; + +/// An interface for cryptographic hash functions. +/// +/// Every hash is a converter that takes a list of ints and returns a single +/// digest. When used in chunked mode, it will only ever add one digest to the +/// inner [Sink]. +abstract class Hash extends Converter, Digest> { + /// The internal block size of the hash in bytes. + /// + /// This is exposed for use by the `Hmac` class, which needs to know the block + /// size for the [Hash] it uses. + int get blockSize; + + const Hash(); + + @override + Digest convert(List data) { + var innerSink = new DigestSink(); + var outerSink = startChunkedConversion(innerSink); + outerSink.add(data); + outerSink.close(); + return innerSink.value; + } + + @override + ByteConversionSink startChunkedConversion(Sink sink); +} +%NN<3MO;4Q# #&7 @Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/hmac.darte// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'digest.dart'; +import 'digest_sink.dart'; +import 'hash.dart'; + +/// An implementation of [keyed-hash method authentication codes][rfc]. +/// +/// [rfc]: https://tools.ietf.org/html/rfc2104 +/// +/// HMAC allows messages to be cryptographically authenticated using any +/// iterated cryptographic hash function. +class Hmac extends Converter, Digest> { + /// The hash function used to compute the authentication digest. + final Hash _hash; + + /// The secret key shared by the sender and the receiver. + final Uint8List _key; + + /// Create an [Hmac] object from a [Hash] and a binary key. + /// + /// The key should be a secret shared between the sender and receiver of the + /// message. + Hmac(Hash hash, List key) + : _hash = hash, + _key = new Uint8List(hash.blockSize) { + // Hash the key if it's longer than the block size of the hash. + if (key.length > _hash.blockSize) key = _hash.convert(key).bytes; + + // If [key] is shorter than the block size, the rest of [_key] will be + // 0-padded. + _key.setRange(0, key.length, key); + } + + @override + Digest convert(List data) { + var innerSink = new DigestSink(); + var outerSink = startChunkedConversion(innerSink); + outerSink.add(data); + outerSink.close(); + return innerSink.value; + } + + @override + ByteConversionSink startChunkedConversion(Sink sink) => + new _HmacSink(sink, _hash, _key); +} + +/// The concrete implementation of the HMAC algorithm. +class _HmacSink extends ByteConversionSink { + /// The sink for the outer hash computation. + final ByteConversionSink _outerSink; + + /// The sink that [_innerSink]'s result will be added to when it's available. + final _innerResultSink = new DigestSink(); + + /// The sink for the inner hash computation. + ByteConversionSink _innerSink; + + /// Whether [close] has been called. + bool _isClosed = false; + + _HmacSink(Sink sink, Hash hash, List key) + : _outerSink = hash.startChunkedConversion(sink) { + _innerSink = hash.startChunkedConversion(_innerResultSink); + + // Compute outer padding. + var padding = new Uint8List(key.length); + for (var i = 0; i < padding.length; i++) { + padding[i] = 0x5c ^ key[i]; + } + _outerSink.add(padding); + + // Compute inner padding. + for (var i = 0; i < padding.length; i++) { + padding[i] = 0x36 ^ key[i]; + } + _innerSink.add(padding); + } + + @override + void add(List data) { + if (_isClosed) throw new StateError('HMAC is closed'); + _innerSink.add(data); + } + + @override + void addSlice(List data, int start, int end, bool isLast) { + if (_isClosed) throw new StateError('HMAC is closed'); + _innerSink.addSlice(data, start, end, isLast); + } + + @override + void close() { + if (_isClosed) return; + _isClosed = true; + + _innerSink.close(); + _outerSink.add(_innerResultSink.value.bytes); + _outerSink.close(); + } +} +mNN<H/I*2C<>O!/DFK' #&7 B(7-/'P-/!'99@-/"/" ; C;3 2Wfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/md5.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'digest.dart'; +import 'hash.dart'; +import 'hash_sink.dart'; +import 'utils.dart'; + +/// An instance of [MD5]. +/// +/// This instance provides convenient access to the [MD5][rfc] hash function. +/// +/// [rfc]: https://tools.ietf.org/html/rfc1321 +/// +/// **Warning**: MD5 has known collisions and should only be used when required +/// for backwards compatibility. +final md5 = new MD5._(); + +/// An implementation of the [MD5][rfc] hash function. +/// +/// [rfc]: https://tools.ietf.org/html/rfc1321 +/// +/// **Warning**: MD5 has known collisions and should only be used when required +/// for backwards compatibility. +/// +/// Note that it's almost always easier to use [md5] rather than creating a new +/// instance. +class MD5 extends Hash { + @override + final int blockSize = 16 * bytesPerWord; + + MD5._(); + + @override + ByteConversionSink startChunkedConversion(Sink sink) => + new ByteConversionSink.from(new _MD5Sink(sink)); +} + +/// Data from a non-linear mathematical function that functions as +/// reproducible noise. +const _noise = const [ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, // + 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, + 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, + 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, + 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, + 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +]; + +/// Per-round shift amounts. +const _shiftAmounts = const [ + 07, 12, 17, 22, 07, 12, 17, 22, 07, 12, 17, 22, 07, 12, 17, 22, 05, 09, 14, // + 20, 05, 09, 14, 20, 05, 09, 14, 20, 05, 09, 14, 20, 04, 11, 16, 23, 04, 11, + 16, 23, 04, 11, 16, 23, 04, 11, 16, 23, 06, 10, 15, 21, 06, 10, 15, 21, 06, + 10, 15, 21, 06, 10, 15, 21 +]; + +/// The concrete implementation of [MD5]. +/// +/// This is separate so that it can extend [HashSink] without leaking additional +/// public members. +class _MD5Sink extends HashSink { + @override + final digest = new Uint32List(4); + + _MD5Sink(Sink sink) : super(sink, 16, endian: Endian.little) { + digest[0] = 0x67452301; + digest[1] = 0xefcdab89; + digest[2] = 0x98badcfe; + digest[3] = 0x10325476; + } + + @override + void updateHash(Uint32List chunk) { + assert(chunk.length == 16); + + var a = digest[0]; + var b = digest[1]; + var c = digest[2]; + var d = digest[3]; + + int e; + int f; + + for (var i = 0; i < 64; i++) { + if (i < 16) { + e = (b & c) | ((~b & mask32) & d); + f = i; + } else if (i < 32) { + e = (d & b) | ((~d & mask32) & c); + f = ((5 * i) + 1) % 16; + } else if (i < 48) { + e = b ^ c ^ d; + f = ((3 * i) + 5) % 16; + } else { + e = c ^ (b | (~d & mask32)); + f = (7 * i) % 16; + } + + var temp = d; + d = c; + c = b; + b = add32( + b, + rotl32(add32(add32(a, e), add32(_noise[i], chunk[f])), + _shiftAmounts[i])); + a = temp; + } + + digest[0] = add32(a, digest[0]); + digest[1] = add32(b, digest[1]); + digest[2] = add32(c, digest[2]); + digest[3] = add32(d, digest[3]); + } +} +~NN<N/P!7/P!P +  B7CMJJJJJJJJJ1QNN*Q" $I &  #++  %  A"%%%%Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/sha1.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'digest.dart'; +import 'hash.dart'; +import 'hash_sink.dart'; +import 'utils.dart'; + +/// An instance of [Sha1]. +/// +/// This instance provides convenient access to the [SHA-1][rfc] hash function. +/// +/// [rfc]: http://tools.ietf.org/html/rfc3174 +final sha1 = new Sha1._(); + +/// An implementation of the [SHA-1][rfc] hash function. +/// +/// [rfc]: http://tools.ietf.org/html/rfc3174 +class Sha1 extends Hash { + @override + final int blockSize = 16 * bytesPerWord; + + Sha1._(); + + @override + ByteConversionSink startChunkedConversion(Sink sink) => + new ByteConversionSink.from(new _Sha1Sink(sink)); +} + +/// The concrete implementation of [Sha1]. +/// +/// This is separate so that it can extend [HashSink] without leaking additional +/// public memebers. +class _Sha1Sink extends HashSink { + @override + final digest = new Uint32List(5); + + /// The sixteen words from the original chunk, extended to 80 words. + /// + /// This is an instance variable to avoid re-allocating, but its data isn't + /// used across invocations of [updateHash]. + final Uint32List _extended; + + _Sha1Sink(Sink sink) + : _extended = new Uint32List(80), + super(sink, 16) { + digest[0] = 0x67452301; + digest[1] = 0xEFCDAB89; + digest[2] = 0x98BADCFE; + digest[3] = 0x10325476; + digest[4] = 0xC3D2E1F0; + } + + @override + void updateHash(Uint32List chunk) { + assert(chunk.length == 16); + + var a = digest[0]; + var b = digest[1]; + var c = digest[2]; + var d = digest[3]; + var e = digest[4]; + + for (var i = 0; i < 80; i++) { + if (i < 16) { + _extended[i] = chunk[i]; + } else { + _extended[i] = rotl32( + _extended[i - 3] ^ + _extended[i - 8] ^ + _extended[i - 14] ^ + _extended[i - 16], + 1); + } + + var newA = add32(add32(rotl32(a, 5), e), _extended[i]); + if (i < 20) { + newA = add32(add32(newA, (b & c) | (~b & d)), 0x5A827999); + } else if (i < 40) { + newA = add32(add32(newA, (b ^ c ^ d)), 0x6ED9EBA1); + } else if (i < 60) { + newA = add32(add32(newA, (b & c) | (b & d) | (c & d)), 0x8F1BBCDC); + } else { + newA = add32(add32(newA, b ^ c ^ d), 0xCA62C1D6); + } + + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = newA & mask32; + } + + digest[0] = add32(a, digest[0]); + digest[1] = add32(b, digest[1]); + digest[2] = add32(c, digest[2]); + digest[3] = add32(d, digest[3]); + digest[4] = add32(e, digest[4]); + } +} +jNN<P.9. +  B8+Q# $GN/( & #!#$#>C<L:  %%%%%Zfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/sha256.dart{// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'digest.dart'; +import 'hash.dart'; +import 'hash_sink.dart'; +import 'utils.dart'; + +/// An instance of [Sha256]. +/// +/// This instance provides convenient access to the [Sha256][rfc] hash function. +/// +/// [rfc]: http://tools.ietf.org/html/rfc6234 +final sha256 = new Sha256._(); + +/// An implementation of the [SHA-256][rfc] hash function. +/// +/// [rfc]: http://tools.ietf.org/html/rfc6234 +/// +/// Note that it's almost always easier to use [sha256] rather than creating a +/// new instance. +class Sha256 extends Hash { + @override + final int blockSize = 16 * bytesPerWord; + + Sha256._(); + + Sha256 newInstance() => new Sha256._(); + + @override + ByteConversionSink startChunkedConversion(Sink sink) => + new ByteConversionSink.from(new _Sha256Sink(sink)); +} + +/// Data from a non-linear function that functions as reproducible noise. +const List _noise = const [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, // + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +]; + +/// The concrete implementation of [Sha256]. +/// +/// This is separate so that it can extend [HashSink] without leaking additional +/// public members. +class _Sha256Sink extends HashSink { + @override + final digest = new Uint32List(8); + + /// The sixteen words from the original chunk, extended to 64 words. + /// + /// This is an instance variable to avoid re-allocating, but its data isn't + /// used across invocations of [updateHash]. + final Uint32List _extended; + + _Sha256Sink(Sink sink) + : _extended = new Uint32List(64), + super(sink, 16) { + // Initial value of the hash parts. First 32 bits of the fractional parts + // of the square roots of the first 8 prime numbers. + digest[0] = 0x6a09e667; + digest[1] = 0xbb67ae85; + digest[2] = 0x3c6ef372; + digest[3] = 0xa54ff53a; + digest[4] = 0x510e527f; + digest[5] = 0x9b05688c; + digest[6] = 0x1f83d9ab; + digest[7] = 0x5be0cd19; + } + + // The following helper functions are taken directly from + // http://tools.ietf.org/html/rfc6234. + + int _rotr32(int n, int x) => (x >> n) | ((x << (32 - n)) & mask32); + int _ch(int x, int y, int z) => (x & y) ^ ((~x & mask32) & z); + int _maj(int x, int y, int z) => (x & y) ^ (x & z) ^ (y & z); + int _bsig0(int x) => _rotr32(2, x) ^ _rotr32(13, x) ^ _rotr32(22, x); + int _bsig1(int x) => _rotr32(6, x) ^ _rotr32(11, x) ^ _rotr32(25, x); + int _ssig0(int x) => _rotr32(7, x) ^ _rotr32(18, x) ^ (x >> 3); + int _ssig1(int x) => _rotr32(17, x) ^ _rotr32(19, x) ^ (x >> 10); + + @override + void updateHash(Uint32List chunk) { + assert(chunk.length == 16); + + // Prepare message schedule. + for (var i = 0; i < 16; i++) { + _extended[i] = chunk[i]; + } + for (var i = 16; i < 64; i++) { + _extended[i] = add32(add32(_ssig1(_extended[i - 2]), _extended[i - 7]), + add32(_ssig0(_extended[i - 15]), _extended[i - 16])); + } + + // Shuffle around the bits. + var a = digest[0]; + var b = digest[1]; + var c = digest[2]; + var d = digest[3]; + var e = digest[4]; + var f = digest[5]; + var g = digest[6]; + var h = digest[7]; + + for (var i = 0; i < 64; i++) { + var temp1 = add32(add32(h, _bsig1(e)), + add32(_ch(e, f, g), add32(_noise[i], _extended[i]))); + var temp2 = add32(_bsig0(a), _maj(a, b, c)); + h = g; + g = f; + f = e; + e = add32(d, temp1); + d = c; + c = b; + b = a; + a = add32(temp1, temp2); + } + + // Update hash values after iteration. + digest[0] = add32(a, digest[0]); + digest[1] = add32(b, digest[1]); + digest[2] = add32(c, digest[2]); + digest[3] = add32(d, digest[3]); + digest[4] = add32(e, digest[4]); + digest[5] = add32(f, digest[5]); + digest[6] = add32(g, digest[6]); + digest[7] = add32(h, digest[7]); + } +} +NN<Q.;.O +* B:J!MJJJJJJJJJ1-Q% $GN/!(N9<)FA@HHBD & !#$N@ #-@3  +%%%%%%%%efile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/accumulator_sink.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +/// A sink that provides access to all the [events] that have been passed to it. +/// +/// See also [ChunkedConversionSink.withCallback]. +class AccumulatorSink implements Sink { + /// An unmodifiable list of events passed to this sink so far. + List get events => new UnmodifiableListView(_events); + final _events = []; + + /// Whether [close] has been called. + bool get isClosed => _isClosed; + var _isClosed = false; + + /// Removes all events from [events]. + /// + /// This can be used to avoid double-processing events. + void clear() { + _events.clear(); + } + + void add(T event) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _events.add(event); + } + + void close() { + _isClosed = true; + } +} +'NN<Q3.A;'"(:;jfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/byte_accumulator_sink.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:typed_data/typed_data.dart'; + +/// A sink that provides access to the concatenated bytes passed to it. +/// +/// See also [ByteConversionSink.withCallback]. +class ByteAccumulatorSink extends ByteConversionSinkBase { + /// The bytes accumulated so far. + /// + /// The returned [Uint8List] is viewing a shared buffer, so it should not be + /// changed and any bytes outside the view should not be accessed. + Uint8List get bytes => new Uint8List.view(_buffer.buffer, 0, _buffer.length); + + final _buffer = new Uint8Buffer(); + + /// Whether [close] has been called. + bool get isClosed => _isClosed; + var _isClosed = false; + + /// Removes all bytes from [bytes]. + /// + /// This can be used to avoid double-processing data. + void clear() { + _buffer.clear(); + } + + void add(List bytes) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.addAll(bytes); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.addAll(chunk, start, end); + if (isLast) _isClosed = true; + } + + void close() { + _isClosed = true; + } +} +7NN<-H0;$OEP%'"&8;D;'"Xfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/hex.dartV// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert.hex; + +import 'dart:convert'; + +import 'hex/encoder.dart'; +import 'hex/decoder.dart'; + +export 'hex/encoder.dart' hide hexEncoder; +export 'hex/decoder.dart' hide hexDecoder; + +/// The canonical instance of [HexCodec]. +const hex = const HexCodec._(); + +/// A codec that converts byte arrays to and from hexadecimal strings, following +/// [the Base16 spec][rfc]. +/// +/// [rfc]: https://tools.ietf.org/html/rfc4648#section-8 +/// +/// This should be used via the [hex] field. +class HexCodec extends Codec, String> { + HexEncoder get encoder => hexEncoder; + HexDecoder get decoder => hexDecoder; + + const HexCodec._(); +} +NN<++* Q9-2((\file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/percent.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert.percent; + +import 'dart:convert'; + +import 'percent/encoder.dart'; +import 'percent/decoder.dart'; + +export 'percent/encoder.dart' hide percentEncoder; +export 'percent/decoder.dart' hide percentDecoder; + +/// The canonical instance of [PercentCodec]. +const percent = const PercentCodec._(); + +// TODO(nweiz): Add flags to support generating and interpreting "+" as a space +// character. Also add an option for custom sets of unreserved characters. +/// A codec that converts byte arrays to and from percent-encoded (also known as +/// URL-encoded) strings according to [RFC 3986][rfc]. +/// +/// [rfc]: https://tools.ietf.org/html/rfc3986#section-2.1 +/// +/// [encoder] encodes all bytes other than ASCII letters, decimal digits, or one +/// of `-._~`. This matches the behavior of [Uri.encodeQueryComponent] except +/// that it doesn't encode `0x20` bytes to the `+` character. +/// +/// To be maximally flexible, [decoder] will decode any percent-encoded byte and +/// will allow any non-percent-encoded byte other than `%`. By default, it +/// interprets `+` as `0x2B` rather than `0x20` as emitted by +/// [Uri.encodeQueryComponent]. +class PercentCodec extends Codec, String> { + PercentEncoder get encoder => percentEncoder; + PercentDecoder get decoder => percentDecoder; + + const PercentCodec._(); +} +(NN<33.(PKQ7;QN>QK> 600lfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/string_accumulator_sink.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +/// A sink that provides access to the concatenated strings passed to it. +/// +/// See also [StringConversionSink.withCallback]. +class StringAccumulatorSink extends StringConversionSinkBase { + /// The string accumulated so far. + String get string => _buffer.toString(); + final _buffer = new StringBuffer(); + + /// Whether [close] has been called. + bool get isClosed => _isClosed; + var _isClosed = false; + + /// Empties [string]. + /// + /// This can be used to avoid double-processing data. + void clear() { + _buffer.clear(); + } + + void add(String chunk) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.write(chunk); + } + + void addSlice(String chunk, int start, int end, bool isLast) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.write(chunk.substring(start, end)); + if (isLast) _isClosed = true; + } + + void close() { + _isClosed = true; + } +} +0NN<J2?%+&'"8;A;0"afile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/typed_data-1.1.6/lib/typed_buffers.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Growable typed-data lists. +/// +/// These lists works just as a typed-data list, except that they are growable. +/// They use an underlying buffer, and when that buffer becomes too small, it +/// is replaced by a new buffer. +/// +/// That means that using the [TypedDataView.buffer] getter is not guaranteed +/// to return the same result each time it is used, and that the buffer may +/// be larger than what the list is using. +library typed_data.typed_buffers; + +import "dart:collection" show ListBase; +import "dart:typed_data"; + +abstract class _TypedDataBuffer extends ListBase { + static const int INITIAL_LENGTH = 8; + + /// The underlying data buffer. + /// + /// This is always both a List and a TypedData, which we don't have a type + /// for here. For example, for a `Uint8Buffer`, this is a `Uint8List`. + List _buffer; + + /// Returns a view of [_buffer] as a [TypedData]. + TypedData get _typedBuffer => _buffer as TypedData; + + /// The length of the list being built. + int _length; + + _TypedDataBuffer(List buffer) + : this._buffer = buffer, + this._length = buffer.length; + + int get length => _length; + E operator [](int index) { + if (index >= length) throw new RangeError.index(index, this); + return _buffer[index]; + } + + void operator []=(int index, E value) { + if (index >= length) throw new RangeError.index(index, this); + _buffer[index] = value; + } + + void set length(int newLength) { + if (newLength < _length) { + E defaultValue = _defaultValue; + for (int i = newLength; i < _length; i++) { + _buffer[i] = defaultValue; + } + } else if (newLength > _buffer.length) { + List newBuffer; + if (_buffer.length == 0) { + newBuffer = _createBuffer(newLength); + } else { + newBuffer = _createBiggerBuffer(newLength); + } + newBuffer.setRange(0, _length, _buffer); + _buffer = newBuffer; + } + _length = newLength; + } + + void _add(E value) { + if (_length == _buffer.length) _grow(_length); + _buffer[_length++] = value; + } + + // We override the default implementation of `add` because it grows the list + // by setting the length in increments of one. We want to grow by doubling + // capacity in most cases. + void add(E value) { + _add(value); + } + + /// Appends all objects of [values] to the end of this buffer. + /// + /// This adds values from [start] (inclusive) to [end] (exclusive) in + /// [values]. If [end] is omitted, it defaults to adding all elements of + /// [values] after [start]. + /// + /// The [start] value must be non-negative. The [values] iterable must have at + /// least [start] elements, and if [end] is specified, it must be greater than + /// or equal to [start] and [values] must have at least [end] elements. + void addAll(Iterable values, [int start = 0, int end]) { + RangeError.checkNotNegative(start, "start"); + if (end != null && start > end) { + throw new RangeError.range(end, start, null, "end"); + } + + _addAll(values, start, end); + } + + /// Inserts all objects of [values] at position [index] in this list. + /// + /// This adds values from [start] (inclusive) to [end] (exclusive) in + /// [values]. If [end] is omitted, it defaults to adding all elements of + /// [values] after [start]. + /// + /// The [start] value must be non-negative. The [values] iterable must have at + /// least [start] elements, and if [end] is specified, it must be greater than + /// or equal to [start] and [values] must have at least [end] elements. + void insertAll(int index, Iterable values, [int start = 0, int end]) { + RangeError.checkValidIndex(index, this, "index", _length + 1); + RangeError.checkNotNegative(start, "start"); + if (end != null) { + if (start > end) { + throw new RangeError.range(end, start, null, "end"); + } + if (start == end) return; + } + + // If we're adding to the end of the list anyway, use [_addAll]. This lets + // us avoid converting [values] into a list even if [end] is null, since we + // can add values iteratively to the end of the list. We can't do so in the + // center because copying the trailing elements every time is non-linear. + if (index == _length) { + _addAll(values, start, end); + return; + } + + if (end == null && values is List) { + end = values.length; + } + if (end != null) { + _insertKnownLength(index, values, start, end); + return; + } + + // Add elements at end, growing as appropriate, then put them back at + // position [index] using flip-by-double-reverse. + var writeIndex = _length; + var skipCount = start; + for (var value in values) { + if (skipCount > 0) { + skipCount--; + continue; + } + if (writeIndex == _buffer.length) { + _grow(writeIndex); + } + _buffer[writeIndex++] = value; + } + + if (skipCount > 0) { + throw new StateError("Too few elements"); + } + if (end != null && writeIndex < end) { + throw new RangeError.range(end, start, writeIndex, "end"); + } + + // Swap [index.._length) and [_length..writeIndex) by double-reversing. + _reverse(_buffer, index, _length); + _reverse(_buffer, _length, writeIndex); + _reverse(_buffer, index, writeIndex); + _length = writeIndex; + return; + } + + // Reverses the range [start..end) of buffer. + static void _reverse(List buffer, int start, int end) { + end--; // Point to last element, not after last element. + while (start < end) { + var first = buffer[start]; + var last = buffer[end]; + buffer[end] = first; + buffer[start] = last; + start++; + end--; + } + } + + /// Does the same thing as [addAll]. + /// + /// This allows [addAll] and [insertAll] to share implementation without a + /// subclass unexpectedly overriding both when it intended to only override + /// [addAll]. + void _addAll(Iterable values, [int start = 0, int end]) { + if (values is List) end ??= values.length; + + // If we know the length of the segment to add, do so with [addRange]. This + // way we know how much to grow the buffer in advance, and it may be even + // more efficient for typed data input. + if (end != null) { + _insertKnownLength(_length, values, start, end); + return; + } + + // Otherwise, just add values one at a time. + var i = 0; + for (var value in values) { + if (i >= start) add(value); + i++; + } + if (i < start) throw new StateError("Too few elements"); + } + + /// Like [insertAll], but with a guaranteed non-`null` [start] and [end]. + void _insertKnownLength(int index, Iterable values, int start, int end) { + if (values is List) { + end ??= values.length; + if (start > values.length || end > values.length) { + throw new StateError("Too few elements"); + } + } else { + assert(end != null); + } + + var valuesLength = end - start; + var newLength = _length + valuesLength; + _ensureCapacity(newLength); + + _buffer.setRange( + index + valuesLength, _length + valuesLength, _buffer, index); + _buffer.setRange(index, index + valuesLength, values, start); + _length = newLength; + } + + void insert(int index, E element) { + if (index < 0 || index > _length) { + throw new RangeError.range(index, 0, _length); + } + if (_length < _buffer.length) { + _buffer.setRange(index + 1, _length + 1, _buffer, index); + _buffer[index] = element; + _length++; + return; + } + List newBuffer = _createBiggerBuffer(null); + newBuffer.setRange(0, index, _buffer); + newBuffer.setRange(index + 1, _length + 1, _buffer, index); + newBuffer[index] = element; + _length++; + _buffer = newBuffer; + } + + /// Ensures that [_buffer] is at least [requiredCapacity] long, + /// + /// Grows the buffer if necessary, preserving existing data. + void _ensureCapacity(int requiredCapacity) { + if (requiredCapacity <= _buffer.length) return; + var newBuffer = _createBiggerBuffer(requiredCapacity); + newBuffer.setRange(0, _length, _buffer); + _buffer = newBuffer; + } + + /// Create a bigger buffer. + /// + /// This method determines how much bigger a bigger buffer should + /// be. If [requiredCapacity] is not null, it will be at least that + /// size. It will always have at least have double the capacity of + /// the current buffer. + List _createBiggerBuffer(int requiredCapacity) { + int newLength = _buffer.length * 2; + if (requiredCapacity != null && newLength < requiredCapacity) { + newLength = requiredCapacity; + } else if (newLength < INITIAL_LENGTH) { + newLength = INITIAL_LENGTH; + } + return _createBuffer(newLength); + } + + /// Grows the buffer. + /// + /// This copies the first [length] elements into the new buffer. + void _grow(int length) { + _buffer = _createBiggerBuffer(null)..setRange(0, length, _buffer); + } + + void setRange(int start, int end, Iterable source, [int skipCount = 0]) { + if (end > _length) throw new RangeError.range(end, 0, _length); + _setRange(start, end, source, skipCount); + } + + /// Like [setRange], but with no bounds checking. + void _setRange(int start, int end, Iterable source, int skipCount) { + if (source is _TypedDataBuffer) { + _buffer.setRange(start, end, source._buffer, skipCount); + } else { + _buffer.setRange(start, end, source, skipCount); + } + } + + // TypedData. + + int get elementSizeInBytes => _typedBuffer.elementSizeInBytes; + + int get lengthInBytes => _length * _typedBuffer.elementSizeInBytes; + + int get offsetInBytes => _typedBuffer.offsetInBytes; + + /// Returns the underlying [ByteBuffer]. + /// + /// The returned buffer may be replaced by operations that change the [length] + /// of this list. + /// + /// The buffer may be larger than [lengthInBytes] bytes, but never smaller. + ByteBuffer get buffer => _typedBuffer.buffer; + + // Specialization for the specific type. + + // Return zero for integers, 0.0 for floats, etc. + // Used to fill buffer when changing length. + E get _defaultValue; + + // Create a new typed list to use as buffer. + List _createBuffer(int size); +} + +abstract class _IntBuffer extends _TypedDataBuffer { + _IntBuffer(List buffer) : super(buffer); + + int get _defaultValue => 0; +} + +abstract class _FloatBuffer extends _TypedDataBuffer { + _FloatBuffer(List buffer) : super(buffer); + + double get _defaultValue => 0.0; +} + +class Uint8Buffer extends _IntBuffer { + Uint8Buffer([int initialLength = 0]) : super(new Uint8List(initialLength)); + Uint8List _createBuffer(int size) => new Uint8List(size); +} + +class Int8Buffer extends _IntBuffer { + Int8Buffer([int initialLength = 0]) : super(new Int8List(initialLength)); + Int8List _createBuffer(int size) => new Int8List(size); +} + +class Uint8ClampedBuffer extends _IntBuffer { + Uint8ClampedBuffer([int initialLength = 0]) + : super(new Uint8ClampedList(initialLength)); + Uint8ClampedList _createBuffer(int size) => new Uint8ClampedList(size); +} + +class Uint16Buffer extends _IntBuffer { + Uint16Buffer([int initialLength = 0]) : super(new Uint16List(initialLength)); + Uint16List _createBuffer(int size) => new Uint16List(size); +} + +class Int16Buffer extends _IntBuffer { + Int16Buffer([int initialLength = 0]) : super(new Int16List(initialLength)); + Int16List _createBuffer(int size) => new Int16List(size); +} + +class Uint32Buffer extends _IntBuffer { + Uint32Buffer([int initialLength = 0]) : super(new Uint32List(initialLength)); + Uint32List _createBuffer(int size) => new Uint32List(size); +} + +class Int32Buffer extends _IntBuffer { + Int32Buffer([int initialLength = 0]) : super(new Int32List(initialLength)); + Int32List _createBuffer(int size) => new Int32List(size); +} + +class Uint64Buffer extends _IntBuffer { + Uint64Buffer([int initialLength = 0]) : super(new Uint64List(initialLength)); + Uint64List _createBuffer(int size) => new Uint64List(size); +} + +class Int64Buffer extends _IntBuffer { + Int64Buffer([int initialLength = 0]) : super(new Int64List(initialLength)); + Int64List _createBuffer(int size) => new Int64List(size); +} + +class Float32Buffer extends _FloatBuffer { + Float32Buffer([int initialLength = 0]) + : super(new Float32List(initialLength)); + Float32List _createBuffer(int size) => new Float32List(size); +} + +class Float64Buffer extends _FloatBuffer { + Float64Buffer([int initialLength = 0]) + : super(new Float64List(initialLength)); + Float64List _createBuffer(int size) => new Float64List(size); +} + +class Int32x4Buffer extends _TypedDataBuffer { + static Int32x4 _zero = new Int32x4(0, 0, 0, 0); + Int32x4Buffer([int initialLength = 0]) + : super(new Int32x4List(initialLength)); + Int32x4 get _defaultValue => _zero; + Int32x4List _createBuffer(int size) => new Int32x4List(size); +} + +class Float32x4Buffer extends _TypedDataBuffer { + Float32x4Buffer([int initialLength = 0]) + : super(new Float32x4List(initialLength)); + Float32x4 get _defaultValue => new Float32x4.zero(); + Float32x4List _createBuffer(int size) => new Float32x4List(size); +} +NN<PN!NL+"(9'"PI46*#&B*B#&2#-!.4/3 OMAHKQQJ>1&;!HHKQQJLC1= OPPN#)5J6 *%0+AL',* 0:=! 'MN?/PN,71 " =LO:2 $, GB&(5$@ 3+@ B?/4;-DFE6(D$-"%CGOD.4J)? 7AF7+QN0+4//#:0?5#'N<&L:..4J(P>'N<(P>'N<(P>'N<+)/@+)/@82)/&@<+17Defile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/feature_matcher.darts// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'interfaces.dart'; +import 'type_matcher.dart'; + +/// A package-private [TypeMatcher] implementation that makes it easy for +/// subclasses to validate aspects of specific types while providing consistent +/// type checking. +abstract class FeatureMatcher extends TypeMatcher { + const FeatureMatcher(); + + bool matches(item, Map matchState) => + super.matches(item, matchState) && typedMatches(item, matchState); + + bool typedMatches(T item, Map matchState); + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + if (item is T) { + return describeTypedMismatch( + item, mismatchDescription, matchState, verbose); + } + + return super.describe(mismatchDescription.add('not an ')); + } + + Description describeTypedMismatch(T item, Description mismatchDescription, + Map matchState, bool verbose) => + mismatchDescription; +} +"NN<JP:(I- M$;?M+bfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/pretty_print.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'description.dart'; +import 'interfaces.dart'; +import 'util.dart'; + +/// Returns a pretty-printed representation of [object]. +/// +/// If [maxLineLength] is passed, this will attempt to ensure that each line is +/// no longer than [maxLineLength] characters long. This isn't guaranteed, since +/// individual objects may have string representations that are too long, but +/// most lines will be less than [maxLineLength] long. +/// +/// If [maxItems] is passed, [Iterable]s and [Map]s will only print their first +/// [maxItems] members or key/value pairs, respectively. +String prettyPrint(object, {int maxLineLength, int maxItems}) { + String _prettyPrint(object, int indent, Set seen, bool top) { + // If the object is a matcher, use its description. + if (object is Matcher) { + var description = new StringDescription(); + object.describe(description); + return "<$description>"; + } + + // Avoid looping infinitely on recursively-nested data structures. + if (seen.contains(object)) return "(recursive)"; + seen = seen.union(new Set.from([object])); + String pp(child) => _prettyPrint(child, indent + 2, seen, false); + + if (object is Iterable) { + // Print the type name for non-List iterables. + var type = object is List ? "" : _typeName(object) + ":"; + + // Truncate the list of strings if it's longer than [maxItems]. + var strings = object.map(pp).toList(); + if (maxItems != null && strings.length > maxItems) { + strings.replaceRange(maxItems - 1, strings.length, ['...']); + } + + // If the printed string is short and doesn't contain a newline, print it + // as a single line. + var singleLine = "$type[${strings.join(', ')}]"; + if ((maxLineLength == null || + singleLine.length + indent <= maxLineLength) && + !singleLine.contains("\n")) { + return singleLine; + } + + // Otherwise, print each member on its own line. + return "$type[\n" + + strings.map((string) { + return _indent(indent + 2) + string; + }).join(",\n") + + "\n" + + _indent(indent) + + "]"; + } else if (object is Map) { + // Convert the contents of the map to string representations. + var strings = object.keys.map((key) { + return '${pp(key)}: ${pp(object[key])}'; + }).toList(); + + // Truncate the list of strings if it's longer than [maxItems]. + if (maxItems != null && strings.length > maxItems) { + strings.replaceRange(maxItems - 1, strings.length, ['...']); + } + + // If the printed string is short and doesn't contain a newline, print it + // as a single line. + var singleLine = "{${strings.join(", ")}}"; + if ((maxLineLength == null || + singleLine.length + indent <= maxLineLength) && + !singleLine.contains("\n")) { + return singleLine; + } + + // Otherwise, print each key/value pair on its own line. + return "{\n" + + strings.map((string) { + return _indent(indent + 2) + string; + }).join(",\n") + + "\n" + + _indent(indent) + + "}"; + } else if (object is String) { + // Escape strings and print each line on its own line. + var lines = object.split("\n"); + return "'" + + lines.map(_escapeString).join("\\n'\n${_indent(indent + 2)}'") + + "'"; + } else { + var value = object.toString().replaceAll("\n", _indent(indent) + "\n"); + var defaultToString = value.startsWith("Instance of "); + + // If this is the top-level call to [prettyPrint], wrap the value on angle + // brackets to set it apart visually. + if (top) value = "<$value>"; + + // Print the type of objects with custom [toString] methods. Primitive + // objects and objects that don't implement a custom [toString] don't need + // to have their types printed. + if (object is num || + object is bool || + object is Function || + object == null || + defaultToString) { + return value; + } else { + return "${_typeName(object)}:$value"; + } + } + } + + return _prettyPrint(object, 0, new Set(), true); +} + +String _indent(int length) => new List.filled(length, ' ').join(''); + +/// Returns the name of the type of [x], or "Unknown" if the type name can't be +/// determined. +String _typeName(x) { + // dart2js blows up on some objects (e.g. window.navigator). + // So we play safe here. + try { + if (x == null) return "null"; + if (x is Type) return "Type"; + var type = x.runtimeType.toString(); + // TODO(nweiz): if the object's type is private, find a public superclass to + // display once there's a portable API to do that. + return type.startsWith("_") ? "?" : type; + } catch (e) { + return "?"; + } +} + +/// Returns [source] with any control characters replaced by their escape +/// sequences. +/// +/// This doesn't add quotes to the string, but it does escape single quote +/// characters so that single quotes can be applied externally. +String _escapeString(String source) => escape(source).replaceAll("'", r"\'"); +NN<9PQN7P9@@81$G5/F5@F-;EP7$>(7!1 D,1F;EP2$>(?!1#=&K N>Q,#MQ& .3EP?"")Q7.JK@Ndfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.4/lib/src/having_matcher.dartj// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'custom_matcher.dart'; +import 'interfaces.dart'; +import 'type_matcher.dart'; +import 'util.dart'; + +/// A package-private [TypeMatcher] implementation that handles is returned +/// by calls to [TypeMatcher.having]. +class HavingMatcher implements TypeMatcher { + final TypeMatcher _parent; + final List<_FunctionMatcher> _functionMatchers; + + HavingMatcher(TypeMatcher parent, String description, + Object feature(T source), Object matcher, + [Iterable<_FunctionMatcher> existing]) + : this._parent = parent, + this._functionMatchers = <_FunctionMatcher>[] + ..addAll(existing ?? []) + ..add(new _FunctionMatcher(description, feature, matcher)); + + TypeMatcher having( + Object feature(T source), String description, Object matcher) => + new HavingMatcher( + _parent, description, feature, matcher, _functionMatchers); + + bool matches(item, Map matchState) { + for (var matcher in [_parent].followedBy(_functionMatchers)) { + if (!matcher.matches(item, matchState)) { + addStateInfo(matchState, {'matcher': matcher}); + return false; + } + } + return true; + } + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + var matcher = matchState['matcher'] as Matcher; + matcher.describeMismatch( + item, mismatchDescription, matchState['state'] as Map, verbose); + return mismatchDescription; + } + + Description describe(Description description) => description + .add('') + .addDescriptionOf(_parent) + .add(' with ') + .addAll('', ' and ', '', _functionMatchers); +} + +class _FunctionMatcher extends CustomMatcher { + final dynamic Function(T value) _feature; + + _FunctionMatcher(String name, this._feature, matcher) + : super('`$name`:', '`$name`', matcher); + + @override + Object featureValueOf(covariant T actual) => _feature(actual); +} +@NN<L&3 2;0-6#IKF'L08 M4I ?!32,8/ A_file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/src/colors.dartr// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Color constants used for generating messages. +const String RED = '\u001b[31m'; + +const String YELLOW = '\u001b[33m'; + +const String NONE = '\u001b[0m'; + NN<1!$!^file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/source_span-1.4.1/lib/src/utils.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Returns the minimum of [obj1] and [obj2] according to +/// [Comparable.compareTo]. +Comparable min(Comparable obj1, Comparable obj2) => + obj1.compareTo(obj2) > 0 ? obj2 : obj1; + +/// Returns the maximum of [obj1] and [obj2] according to +/// [Comparable.compareTo]. +Comparable max(Comparable obj1, Comparable obj2) => + obj1.compareTo(obj2) > 0 ? obj1 : obj2; + +/// Finds a line in [context] containing [text] at the specified [column]. +/// +/// Returns the index in [context] where that line begins, or null if none +/// exists. +int findLineStart(String context, String text, int column) { + var isEmpty = text == ''; + var index = context.indexOf(text); + while (index != -1) { + var lineStart = context.lastIndexOf('\n', index) + 1; + var textColumn = index - lineStart; + if (column == textColumn || (isEmpty && column == textColumn + 1)) { + return lineStart; + } + index = context.indexOf(text, index + 1); + } + return null; +} +!NN<:4,:4,KK =%:(I._file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/digest_sink.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'digest.dart'; + +/// A sink used to get a digest value out of `Hash.startChunkedConversion`. +class DigestSink extends Sink { + /// The value added to the sink, if any. + Digest get value { + assert(_value != null); + return _value; + } + + Digest _value; + + /// Adds [value] to the sink. + /// + /// Unlike most sinks, this may only be called once. + @override + void add(Digest value) { + assert(_value == null); + _value = value; + } + + @override + void close() { + assert(_value != null); + } +} + NN<L(+ 7  ]file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/hash_sink.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:typed_data/typed_data.dart'; + +import 'digest.dart'; +import 'utils.dart'; + +/// A base class for [Sink] implementations for hash algorithms. +/// +/// Subclasses should override [updateHash] and [digest]. +abstract class HashSink implements Sink> { + /// The inner sink that this should forward to. + final Sink _sink; + + /// Whether the hash function operates on big-endian words. + final Endian _endian; + + /// The words in the current chunk. + /// + /// This is an instance variable to avoid re-allocating, but its data isn't + /// used across invocations of [_iterate]. + final Uint32List _currentChunk; + + /// Messages with more than 2^53-1 bits are not supported. (This is the + /// largest value that is representable on both JS and the Dart VM.) + /// So the maximum length in bytes is (2^53-1)/8. + static const _maxMessageLengthInBytes = 0x0003ffffffffffff; + + /// The length of the input data so far, in bytes. + int _lengthInBytes = 0; + + /// Data that has yet to be processed by the hash function. + final _pendingData = new Uint8Buffer(); + + /// Whether [close] has been called. + bool _isClosed = false; + + /// The words in the current digest. + /// + /// This should be updated each time [updateHash] is called. + Uint32List get digest; + + /// Creates a new hash. + /// + /// [chunkSizeInWords] represents the size of the input chunks processed by + /// the algorithm, in terms of 32-bit words. + HashSink(this._sink, int chunkSizeInWords, {Endian endian: Endian.big}) + : _endian = endian, + _currentChunk = new Uint32List(chunkSizeInWords); + + /// Runs a single iteration of the hash computation, updating [digest] with + /// the result. + /// + /// [chunk] is the current chunk, whose size is given by the + /// `chunkSizeInWords` parameter passed to the constructor. + void updateHash(Uint32List chunk); + + @override + void add(List data) { + if (_isClosed) throw new StateError('Hash.add() called after close().'); + _lengthInBytes += data.length; + _pendingData.addAll(data); + _iterate(); + } + + @override + void close() { + if (_isClosed) return; + _isClosed = true; + + _finalizeData(); + _iterate(); + assert(_pendingData.isEmpty); + _sink.add(new Digest(_byteDigest())); + _sink.close(); + } + + Uint8List _byteDigest() { + if (_endian == Endian.host) return digest.buffer.asUint8List(); + + var byteDigest = new Uint8List(digest.lengthInBytes); + var byteData = byteDigest.buffer.asByteData(); + for (var i = 0; i < digest.length; i++) { + byteData.setUint32(i * bytesPerWord, digest[i]); + } + return byteDigest; + } + + /// Iterates through [_pendingData], updating the hash computation for each + /// chunk. + void _iterate() { + var pendingDataBytes = _pendingData.buffer.asByteData(); + var pendingDataChunks = _pendingData.length ~/ _currentChunk.lengthInBytes; + for (var i = 0; i < pendingDataChunks; i++) { + // Copy words from the pending data buffer into the current chunk buffer. + for (var j = 0; j < _currentChunk.length; j++) { + _currentChunk[j] = pendingDataBytes.getUint32( + i * _currentChunk.lengthInBytes + j * bytesPerWord, _endian); + } + + // Run the hash function on the current chunk. + updateHash(_currentChunk); + } + + // Remove all pending data up to the last clean chunk break. + _pendingData.removeRange( + 0, pendingDataChunks * _currentChunk.lengthInBytes); + } + + /// Finalizes [_pendingData]. + /// + /// This adds a 1 bit to the end of the message, and expands it with 0 bits to + /// pad it out. + void _finalizeData() { + // Pad out the data with 0x80, eight 0s, and as many more 0s as we need to + // land cleanly on a chunk boundary. + _pendingData.add(0x80); + var contentsLength = _lengthInBytes + 9; + var finalizedLength = _roundUp(contentsLength, _currentChunk.lengthInBytes); + for (var i = 0; i < finalizedLength - contentsLength; i++) { + _pendingData.add(0); + } + + if (_lengthInBytes > _maxMessageLengthInBytes) { + throw new UnsupportedError( + 'Hashing is unsupported for messages with more than 2^53 bits.'); + } + + var lengthInBits = _lengthInBytes * bitsPerByte; + + // Add the full length of the input data as a 64-bit value at the end of the + // hash. + var offset = _pendingData.length; + _pendingData.addAll(new Uint8List(8)); + var byteData = _pendingData.buffer.asByteData(); + + // We're essentially doing byteData.setUint64(offset, lengthInBits, _endian) + // here, but that method isn't supported on dart2js so we implement it + // manually instead. + var highBits = lengthInBits >> 32; + var lowBits = lengthInBits & mask32; + if (_endian == Endian.big) { + byteData.setUint32(offset, highBits, _endian); + byteData.setUint32(offset + bytesPerWord, lowBits, _endian); + } else { + byteData.setUint32(offset, lowBits, _endian); + byteData.setUint32(offset + bytesPerWord, highBits, _endian); + } + } + + /// Rounds [val] up to the next multiple of [n], as long as [n] is a power of + /// two. + int _roundUp(int val, int n) => (val + n - 1) & -n; +} +NN<-A:52>&N-"JG4>5>*''?N/J:N?>% M# "*D:3.7N =P2P77J5!A= QO)-QA5"L5Q &+5QK')!5C 4DP 6Yfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/src/utils.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A bitmask that limits an integer to 32 bits. +const mask32 = 0xFFFFFFFF; + +/// The number of bits in a byte. +const bitsPerByte = 8; + +/// The number of bytes in a 32-bit word. +const bytesPerWord = 4; + +/// Adds [x] and [y] with 32-bit overflow semantics. +int add32(int x, int y) => (x + y) & mask32; + +/// Bitwise rotates [val] to the left by [shift], obeying 32-bit overflow +/// semantics. +int rotl32(int val, int shift) { + var modShift = shift & 31; + return ((val << modShift) & mask32) | ((val & mask32) >> (32 - modShift)); +} +NN<1"*5-J!M`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/hex/encoder.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert.hex.encoder; + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:charcode/ascii.dart'; + +/// The canonical instance of [HexEncoder]. +const hexEncoder = const HexEncoder._(); + +/// A converter that encodes byte arrays into hexadecimal strings. +/// +/// This will throw a [RangeError] if the byte array has any digits that don't +/// fit in the gamut of a byte. +class HexEncoder extends Converter, String> { + const HexEncoder._(); + + String convert(List bytes) => _convert(bytes, 0, bytes.length); + + ByteConversionSink startChunkedConversion(Sink sink) => + new _HexEncoderSink(sink); +} + +/// A conversion sink for chunked hexadecimal encoding. +class _HexEncoderSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink _sink; + + _HexEncoderSink(this._sink); + + void add(List chunk) { + _sink.add(_convert(chunk, 0, chunk.length)); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + _sink.add(_convert(chunk, start, end)); + if (isLast) _sink.close(); + } + + void close() { + _sink.close(); + } +} + +String _convert(List bytes, int start, int end) { + // A Uint8List is more efficient than a StringBuffer given that we know that + // we're only emitting ASCII-compatible characters, and that we know the + // length ahead of time. + var buffer = new Uint8List((end - start) * 2); + var bufferIndex = 0; + + // A bitwise OR of all bytes in [bytes]. This allows us to check for + // out-of-range bytes without adding more branches than necessary to the + // core loop. + var byteOr = 0; + for (var i = start; i < end; i++) { + var byte = bytes[i]; + byteOr |= byte; + + // The bitwise arithmetic here is equivalent to `byte ~/ 16` and `byte % 16` + // for valid byte values, but is easier for dart2js to optimize given that + // it can't prove that [byte] will always be positive. + buffer[bufferIndex++] = _codeUnitForDigit((byte & 0xF0) >> 4); + buffer[bufferIndex++] = _codeUnitForDigit(byte & 0x0F); + } + + if (byteOr >= 0 && byteOr <= 255) return new String.fromCharCodes(buffer); + + // If there was an invalid byte, find it and throw an exception. + for (var i = start; i < end; i++) { + var byte = bytes[i]; + if (byte >= 0 && byte <= 0xff) continue; + throw new FormatException( + "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", + bytes, + i); + } + + throw 'unreachable'; +} + +/// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit +/// [digit]. +int _codeUnitForDigit(int digit) => digit < 10 ? digit + $0 : digit + $a - 10; +[NN<&,)CO 8GB!87G1D:,7OK1GK&QO;C<MC&-Q O O`file:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/hex/decoder.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert.hex.decoder; + +import 'dart:convert'; +import 'dart:typed_data'; + +import '../utils.dart'; + +/// The canonical instance of [HexDecoder]. +const hexDecoder = const HexDecoder._(); + +/// A converter that decodes hexadecimal strings into byte arrays. +/// +/// Because two hexadecimal digits correspond to a single byte, this will throw +/// a [FormatException] if given an odd-length string. It will also throw a +/// [FormatException] if given a string containing non-hexadecimal code units. +class HexDecoder extends Converter> { + const HexDecoder._(); + + List convert(String string) { + if (!string.length.isEven) { + throw new FormatException( + "Invalid input length, must be even.", string, string.length); + } + + var bytes = new Uint8List(string.length ~/ 2); + _decode(string.codeUnits, 0, string.length, bytes, 0); + return bytes; + } + + StringConversionSink startChunkedConversion(Sink> sink) => + new _HexDecoderSink(sink); +} + +/// A conversion sink for chunked hexadecimal decoding. +class _HexDecoderSink extends StringConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This will be non-`null` if the most recent string had an odd number of + /// hexadecimal digits. Since it's the most significant digit, it's always a + /// multiple of 16. + int _lastDigit; + + _HexDecoderSink(this._sink); + + void addSlice(String string, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, string.length); + + if (start == end) { + if (isLast) _close(string, end); + return; + } + + var codeUnits = string.codeUnits; + Uint8List bytes; + int bytesStart; + if (_lastDigit == null) { + bytes = new Uint8List((end - start) ~/ 2); + bytesStart = 0; + } else { + var hexPairs = (end - start - 1) ~/ 2; + bytes = new Uint8List(1 + hexPairs); + bytes[0] = _lastDigit + digitForCodeUnit(codeUnits, start); + start++; + bytesStart = 1; + } + + _lastDigit = _decode(codeUnits, start, end, bytes, bytesStart); + + _sink.add(bytes); + if (isLast) _close(string, end); + } + + ByteConversionSink asUtf8Sink(bool allowMalformed) => + new _HexDecoderByteSink(_sink); + + void close() => _close(); + + /// Like [close], but includes [string] and [index] in the [FormatException] + /// if one is thrown. + void _close([String string, int index]) { + if (_lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", string, index); + } + + _sink.close(); + } +} + +/// A conversion sink for chunked hexadecimal decoding from UTF-8 bytes. +class _HexDecoderByteSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This will be non-`null` if the most recent string had an odd number of + /// hexadecimal digits. Since it's the most significant digit, it's always a + /// multiple of 16. + int _lastDigit; + + _HexDecoderByteSink(this._sink); + + void add(List chunk) => addSlice(chunk, 0, chunk.length, false); + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + + if (start == end) { + if (isLast) _close(chunk, end); + return; + } + + Uint8List bytes; + int bytesStart; + if (_lastDigit == null) { + bytes = new Uint8List((end - start) ~/ 2); + bytesStart = 0; + } else { + var hexPairs = (end - start - 1) ~/ 2; + bytes = new Uint8List(1 + hexPairs); + bytes[0] = _lastDigit + digitForCodeUnit(chunk, start); + start++; + bytesStart = 1; + } + + _lastDigit = _decode(chunk, start, end, bytes, bytesStart); + + _sink.add(bytes); + if (isLast) _close(chunk, end); + } + + void close() => _close(); + + /// Like [close], but includes [chunk] and [index] in the [FormatException] + /// if one is thrown. + void _close([List chunk, int index]) { + if (_lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", chunk, index); + } + + _sink.close(); + } +} + +/// Decodes [codeUnits] and writes the result into [destination]. +/// +/// This reads from [codeUnits] between [sourceStart] and [sourceEnd]. It writes +/// the result into [destination] starting at [destinationStart]. +/// +/// If there's a leftover digit at the end of the decoding, this returns that +/// digit. Otherwise it returns `null`. +int _decode(List codeUnits, int sourceStart, int sourceEnd, + List destination, int destinationStart) { + var destinationIndex = destinationStart; + for (var i = sourceStart; i < sourceEnd - 1; i += 2) { + var firstDigit = digitForCodeUnit(codeUnits, i); + var secondDigit = digitForCodeUnit(codeUnits, i + 1); + destination[destinationIndex++] = 16 * firstDigit + secondDigit; + } + + if ((sourceEnd - sourceStart).isEven) return null; + return 16 * digitForCodeUnit(codeUnits, sourceEnd - 1); +} +NN<,)CPLO8%!!I3;G!89G3MOB;'&1 -+BD%8&O,!GI;G3MO#HD:&1 -+>@$N.!FBQBN(A3+95:E5:dfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/percent/encoder.dart&// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert.percent.encoder; + +import 'dart:convert'; + +import 'package:charcode/ascii.dart'; + +/// The canonical instance of [PercentEncoder]. +const percentEncoder = const PercentEncoder._(); + +/// A converter that encodes byte arrays into percent-encoded strings. +/// +/// [encoder] encodes all bytes other than ASCII letters, decimal digits, or one +/// of `-._~`. This matches the behavior of [Uri.encodeQueryComponent] except +/// that it doesn't encode `0x20` bytes to the `+` character. +/// +/// This will throw a [RangeError] if the byte array has any digits that don't +/// fit in the gamut of a byte. +class PercentEncoder extends Converter, String> { + const PercentEncoder._(); + + String convert(List bytes) => _convert(bytes, 0, bytes.length); + + ByteConversionSink startChunkedConversion(Sink sink) => + new _PercentEncoderSink(sink); +} + +/// A conversion sink for chunked percentadecimal encoding. +class _PercentEncoderSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink _sink; + + _PercentEncoderSink(this._sink); + + void add(List chunk) { + _sink.add(_convert(chunk, 0, chunk.length)); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + _sink.add(_convert(chunk, start, end)); + if (isLast) _sink.close(); + } + + void close() { + _sink.close(); + } +} + +String _convert(List bytes, int start, int end) { + var buffer = new StringBuffer(); + + // A bitwise OR of all bytes in [bytes]. This allows us to check for + // out-of-range bytes without adding more branches than necessary to the + // core loop. + var byteOr = 0; + for (var i = start; i < end; i++) { + var byte = bytes[i]; + byteOr |= byte; + + // If the byte is an uppercase letter, convert it to lowercase to check if + // it's unreserved. This works because uppercase letters in ASCII are + // exactly `0b100000 = 0x20` less than lowercase letters, so if we ensure + // that that bit is 1 we ensure that the letter is lowercase. + var letter = 0x20 | byte; + if ((letter >= $a && letter <= $z) || + (byte >= $0 && byte <= $9) || + byte == $dash || + byte == $dot || + byte == $underscore || + byte == $tilde) { + // Unreserved characters are safe to write as-is. + buffer.writeCharCode(byte); + continue; + } + + buffer.writeCharCode($percent); + + // The bitwise arithmetic here is equivalent to `byte ~/ 16` and `byte % 16` + // for valid byte values, but is easier for dart2js to optimize given that + // it can't prove that [byte] will always be positive. + buffer.writeCharCode(_codeUnitForDigit((byte & 0xF0) >> 4)); + buffer.writeCharCode(_codeUnitForDigit(byte & 0x0F)); + } + + if (byteOr >= 0 && byteOr <= 255) return buffer.toString(); + + // If there was an invalid byte, find it and throw an exception. + for (var i = start; i < end; i++) { + var byte = bytes[i]; + if (byte >= 0 && byte <= 0xff) continue; + throw new FormatException( + "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", + bytes, + i); + } + + throw 'unreachable'; +} + +/// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit +/// [digit]. +int _codeUnitForDigit(int digit) => digit < 10 ? digit + $0 : digit + $A - 10; +lNN<!&01GQN>O <GB%<;G#1D:,7#GK&OJNB*&8"$QO;A:>C&-Q O Odfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/percent/decoder.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert.percent.decoder; + +import 'dart:convert'; + +import 'package:charcode/ascii.dart'; +import 'package:typed_data/typed_data.dart'; + +import '../utils.dart'; + +/// The canonical instance of [PercentDecoder]. +const percentDecoder = const PercentDecoder._(); + +const _lastPercent = -1; + +/// A converter that decodes percent-encoded strings into byte arrays. +/// +/// To be maximally flexible, this will decode any percent-encoded byte and +/// will allow any non-percent-encoded byte other than `%`. By default, it +/// interprets `+` as `0x2B` rather than `0x20` as emitted by +/// [Uri.encodeQueryComponent]. +/// +/// This will throw a [FormatException] if the input string has an incomplete +/// percent-encoding, or if it contains non-ASCII code units. +class PercentDecoder extends Converter> { + const PercentDecoder._(); + + List convert(String string) { + var buffer = new Uint8Buffer(); + var lastDigit = _decode(string.codeUnits, 0, string.length, buffer); + + if (lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", string, string.length); + } + + return buffer.buffer.asUint8List(0, buffer.length); + } + + StringConversionSink startChunkedConversion(Sink> sink) => + new _PercentDecoderSink(sink); +} + +/// A conversion sink for chunked percent-encoded decoding. +class _PercentDecoderSink extends StringConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This is `null` if the previous string ended with a complete + /// percent-encoded byte or a literal character. It's [_lastPercent] if the + /// most recent string ended with `%`. Otherwise, the most recent string ended + /// with a `%` followed by a hexadecimal digit, and this is that digit. Since + /// it's the most significant digit, it's always a multiple of 16. + int _lastDigit; + + _PercentDecoderSink(this._sink); + + void addSlice(String string, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, string.length); + + if (start == end) { + if (isLast) _close(string, end); + return; + } + + var buffer = new Uint8Buffer(); + var codeUnits = string.codeUnits; + if (_lastDigit == _lastPercent) { + _lastDigit = 16 * digitForCodeUnit(codeUnits, start); + start++; + + if (start == end) { + if (isLast) _close(string, end); + return; + } + } + + if (_lastDigit != null) { + buffer.add(_lastDigit + digitForCodeUnit(codeUnits, start)); + start++; + } + + _lastDigit = _decode(codeUnits, start, end, buffer); + + _sink.add(buffer.buffer.asUint8List(0, buffer.length)); + if (isLast) _close(string, end); + } + + ByteConversionSink asUtf8Sink(bool allowMalformed) => + new _PercentDecoderByteSink(_sink); + + void close() => _close(); + + /// Like [close], but includes [string] and [index] in the [FormatException] + /// if one is thrown. + void _close([String string, int index]) { + if (_lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", string, index); + } + + _sink.close(); + } +} + +/// A conversion sink for chunked percent-encoded decoding from UTF-8 bytes. +class _PercentDecoderByteSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This is `null` if the previous string ended with a complete + /// percent-encoded byte or a literal character. It's [_lastPercent] if the + /// most recent string ended with `%`. Otherwise, the most recent string ended + /// with a `%` followed by a hexadecimal digit, and this is that digit. Since + /// it's the most significant digit, it's always a multiple of 16. + int _lastDigit; + + _PercentDecoderByteSink(this._sink); + + void add(List chunk) => addSlice(chunk, 0, chunk.length, false); + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + + if (start == end) { + if (isLast) _close(chunk, end); + return; + } + + var buffer = new Uint8Buffer(); + if (_lastDigit == _lastPercent) { + _lastDigit = 16 * digitForCodeUnit(chunk, start); + start++; + + if (start == end) { + if (isLast) _close(chunk, end); + return; + } + } + + if (_lastDigit != null) { + buffer.add(_lastDigit + digitForCodeUnit(chunk, start)); + start++; + } + + _lastDigit = _decode(chunk, start, end, buffer); + + _sink.add(buffer.buffer.asUint8List(0, buffer.length)); + if (isLast) _close(chunk, end); + } + + void close() => _close(); + + /// Like [close], but includes [chunk] and [index] in the [FormatException] + /// if one is thrown. + void _close([List chunk, int index]) { + if (_lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", chunk, index); + } + + _sink.close(); + } +} + +/// Decodes [codeUnits] and writes the result into [destination]. +/// +/// This reads from [codeUnits] between [sourceStart] and [sourceEnd]. It writes +/// the result into [destination] starting at [destinationStart]. +/// +/// If there's a leftover digit at the end of the decoding, this returns that +/// digit. Otherwise it returns `null`. +int _decode(List codeUnits, int start, int end, Uint8Buffer buffer) { + // A bitwise OR of all code units in [codeUnits]. This allows us to check for + // out-of-range code units without adding more branches than necessary to the + // core loop. + var codeUnitOr = 0; + + // The beginning of the current slice of adjacent non-% characters. We can add + // all of these to the buffer at once. + var sliceStart = start; + for (var i = start; i < end; i++) { + // First, loop through non-% characters. + var codeUnit = codeUnits[i]; + if (codeUnits[i] != $percent) { + codeUnitOr |= codeUnit; + continue; + } + + // We found a %. The slice from `sliceStart` to `i` represents characters + // than can be copied to the buffer as-is. + if (i > sliceStart) { + _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, i); + buffer.addAll(codeUnits, sliceStart, i); + } + + // Now decode the percent-encoded byte and add it as well. + i++; + if (i >= end) return _lastPercent; + + var firstDigit = digitForCodeUnit(codeUnits, i); + i++; + if (i >= end) return 16 * firstDigit; + + var secondDigit = digitForCodeUnit(codeUnits, i); + buffer.add(16 * firstDigit + secondDigit); + + // The next iteration will look for non-% characters again. + sliceStart = i + 1; + } + + if (end > sliceStart) { + _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, end); + if (start == sliceStart) { + buffer.addAll(codeUnits); + } else { + buffer.addAll(codeUnits, sliceStart, end); + } + } + + return null; +} + +void _checkForInvalidCodeUnit( + int codeUnitOr, List codeUnits, int start, int end) { + if (codeUnitOr >= 0 && codeUnitOr <= 0x7f) return; + + for (var i = start; i < end; i++) { + var codeUnit = codeUnits[i]; + if (codeUnit >= 0 && codeUnit <= 0x7f) continue; + throw new FormatException( + "Non-ASCII code unit " + "U+${codeUnit.toRadixString(16).padLeft(4, '0')}", + codeUnits, + i); + } +} +NN<!&-01GLK> N><%$I!O8G%<=G3BNQPE#B;'$&&<)C9<%8*O,!GM?G3BNQPE'HD:&$&8(?5<$N.!FBQBN(KPPQ)&-!$N/F/? '5 *6/@F 1?5&!5; Zfile:///Users/thosakwe/.pub-cache/hosted/pub.dartlang.org/convert-2.0.2/lib/src/utils.dartX// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library convert.utils; + +import 'package:charcode/ascii.dart'; + +/// Returns the digit (0 through 15) corresponding to the hexadecimal code unit +/// at index [i] in [codeUnits]. +/// +/// If the given code unit isn't valid hexadecimal, throws a [FormatException]. +int digitForCodeUnit(List codeUnits, int index) { + // If the code unit is a numeral, get its value. XOR works because 0 in ASCII + // is `0b110000` and the other numerals come after it in ascending order and + // take up at most four bits. + // + // We check for digits first because it ensures there's only a single branch + // for 10 out of 16 of the expected cases. We don't count the `digit >= 0` + // check because branch prediction will always work on it for valid data. + var codeUnit = codeUnits[index]; + var digit = $0 ^ codeUnit; + if (digit <= 9) { + if (digit >= 0) return digit; + } else { + // If the code unit is an uppercase letter, convert it to lowercase. This + // works because uppercase letters in ASCII are exactly `0b100000 = 0x20` + // less than lowercase letters, so if we ensure that that bit is 1 we ensure + // that the letter is lowercase. + var letter = 0x20 | codeUnit; + if ($a <= letter && letter <= $f) return letter - $a + 10; + } + + throw new FormatException( + "Invalid hexadecimal code unit " + "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", + codeUnits, + index); +} +)NN<&P!P7PO OML#" NNQ%"?':tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@ReifyFunctionTypes(false) +library dart._runtime; + +import 'dart:async'; +import 'dart:collection'; + +import 'dart:_foreign_helper' show JS, JSExportName, rest, spread; +import 'dart:_interceptors' show JSArray, jsNull, JSFunction; +import 'dart:_internal' as internal show Symbol; +import 'dart:_js_helper' + show + AssertionErrorImpl, + BooleanConversionAssertionError, + CastErrorImpl, + DartIterator, + getTraceFromException, + TypeErrorImpl, + JsLinkedHashMap, + ImmutableMap, + PrivateSymbol, + ReifyFunctionTypes, + NoReifyGeneric, + notNull; +import 'dart:_debugger' show trackCall; + +export 'dart:_debugger' show getDynamicStats, clearDynamicStats, trackCall; + +part 'utils.dart'; +part 'classes.dart'; +part 'rtti.dart'; +part 'types.dart'; +part 'errors.dart'; +part 'operations.dart'; + +// TODO(vsm): Move polyfill code to dart:html. +// Note, native extensions are registered onto types in dart.global. +// This polyfill needs to run before the corresponding dart:html code is run. +final _polyfilled = JS('', 'Symbol("_polyfilled")'); + +bool polyfill(window) => JS('', '''(() => { + if ($window[$_polyfilled]) return false; + $window[$_polyfilled] = true; + + if (typeof $window.NodeList !== "undefined") { + // TODO(vsm): Do we still need these? + $window.NodeList.prototype.get = function(i) { return this[i]; }; + $window.NamedNodeMap.prototype.get = function(i) { return this[i]; }; + $window.DOMTokenList.prototype.get = function(i) { return this[i]; }; + $window.HTMLCollection.prototype.get = function(i) { return this[i]; }; + + // Expose constructors for DOM types dart:html needs to assume are + // available on window. + if (typeof $window.PannerNode == "undefined") { + let audioContext; + if (typeof $window.AudioContext == "undefined" && + (typeof $window.webkitAudioContext != "undefined")) { + audioContext = new $window.webkitAudioContext(); + } else { + audioContext = new $window.AudioContext(); + $window.StereoPannerNode = + audioContext.createStereoPanner().constructor; + } + $window.PannerNode = audioContext.createPanner().constructor; + } + if (typeof $window.AudioSourceNode == "undefined") { + $window.AudioSourceNode = MediaElementAudioSourceNode.__proto__; + } + if (typeof $window.FontFaceSet == "undefined") { + // CSS Font Loading is not supported on Edge. + if (typeof $window.document.fonts != "undefined") { + $window.FontFaceSet = $window.document.fonts.__proto__.constructor; + } + } + if (typeof $window.MemoryInfo == "undefined") { + if (typeof $window.performance.memory != "undefined") { + $window.MemoryInfo = $window.performance.memory.constructor; + } + } + if (typeof $window.Geolocation == "undefined") { + $window.Geolocation == $window.navigator.geolocation.constructor; + } + if (typeof $window.Animation == "undefined") { + let d = $window.document.createElement('div'); + if (typeof d.animate != "undefined") { + $window.Animation = d.animate(d).constructor; + } + } + if (typeof $window.SourceBufferList == "undefined") { + $window.SourceBufferList = + new $window.MediaSource().sourceBuffers.constructor; + } + if (typeof $window.SpeechRecognition == "undefined") { + $window.SpeechRecognition = $window.webkitSpeechRecognition; + $window.SpeechRecognitionError = $window.webkitSpeechRecognitionError; + $window.SpeechRecognitionEvent = $window.webkitSpeechRecognitionEvent; + } + } + return true; +})()'''); + +@JSExportName('global') +final global_ = JS('', ''' + function () { + // Find global object. + var globalState = (typeof window != "undefined") ? window + : (typeof global != "undefined") ? global + : (typeof self != "undefined") ? self : null; + if (!globalState) { + // Some platforms (e.g., d8) do not define any of the above. The + // following is a non-CSP safe way to access the global object: + globalState = new Function('return this;')(); + } + + $polyfill(globalState); + + // By default, stack traces cutoff at 10. Set the limit to Infinity for + // better debugging. + if (globalState.Error) { + globalState.Error.stackTraceLimit = Infinity; + } + + // These settings must be configured before the application starts so that + // user code runs with the correct configuration. + let settings = 'ddcSettings' in globalState ? globalState.ddcSettings : {}; + $trapRuntimeErrors( + 'trapRuntimeErrors' in settings ? settings.trapRuntimeErrors : false); + $ignoreWhitelistedErrors( + 'ignoreWhitelistedErrors' in settings ? + settings.ignoreWhitelistedErrors : false); + + $ignoreAllErrors( + 'ignoreAllErrors' in settings ? settings.ignoreAllErrors : false); + + $trackProfile( + 'trackProfile' in settings ? settings.trackProfile : false); + + return globalState; + }() +'''); + +void trackProfile(bool flag) { + JS('', 'dart.__trackProfile = #', flag); +} + +final JsSymbol = JS('', 'Symbol'); + +// TODO(vsm): Remove once this flag we've removed the ability to +// whitelist / fallback on the old behavior. +bool startAsyncSynchronously = true; +void setStartAsyncSynchronously([bool value = true]) { + startAsyncSynchronously = value; +} +NN<C>1 )(L/EN5,+ 1*FJJLG48@93#;D9G54:L4>E5H35-6:!=;CMM +>04HF4M4O6PO07KE+#A-%7#rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dartá// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This library defines the representation of runtime types. +part of "runtime.dart"; + +final metadata = JS('', 'Symbol("metadata")'); + +/// Types in dart are represented internally at runtime as follows. +/// +/// - Normal nominal types, produced from classes, are represented +/// at runtime by the JS class of which they are an instance. +/// If the type is the result of instantiating a generic class, +/// then the "classes" module manages the association between the +/// instantiated class and the original class declaration +/// and the type arguments with which it was instantiated. This +/// association can be queried via the "classes" module". +/// +/// - All other types are represented as instances of class TypeRep, +/// defined in this module. +/// - Dynamic, Void, and Bottom are singleton instances of sentinal +/// classes. +/// - Function types are instances of subclasses of AbstractFunctionType. +/// +/// Function types are represented in one of two ways: +/// - As an instance of FunctionType. These are eagerly computed. +/// - As an instance of TypeDef. The TypeDef representation lazily +/// computes an instance of FunctionType, and delegates to that instance. +/// +/// These above "runtime types" are what is used for implementing DDC's +/// internal type checks. These objects are distinct from the objects exposed +/// to user code by class literals and calling `Object.runtimeType`. In DDC, +/// the latter are represented by instances of WrappedType which contain a +/// real runtime type internally. This ensures that the returned object only +/// exposes the API that Type defines: +/// +/// get String name; +/// String toString(); +/// +/// These "runtime types" have methods for performing type checks. The methods +/// have the following JavaScript names which are designed to not collide with +/// static methods, which are also placed 'on' the class constructor function. +/// +/// T.is(o): Implements 'o is T'. +/// T.as(o): Implements 'o as T'. +/// T._check(o): Implements the type assertion of 'T x = o;' +/// +/// By convention, we used named JavaScript functions for these methods with the +/// name 'is_X', 'as_X' and 'check_X' for various X to indicate the type or the +/// implementation strategy for the test (e.g 'is_String', 'is_G' for generic +/// types, etc.) +// TODO(jmesserly): we shouldn't implement Type here. It should be moved down +// to AbstractFunctionType. +class TypeRep implements Type { + String get name => this.toString(); + + // TODO(jmesserly): these should never be reached. + @JSExportName('is') + bool is_T(object) => instanceOf(object, this); + + @JSExportName('as') + as_T(object) => cast(object, this, false); + + @JSExportName('_check') + check_T(object) => cast(object, this, true); +} + +class DynamicType extends TypeRep { + toString() => 'dynamic'; + + @JSExportName('is') + bool is_T(object) => true; + + @JSExportName('as') + as_T(object) => object; + + @JSExportName('_check') + check_T(object) => object; +} + +bool _isJsObject(obj) => JS('!', '# === #', getReifiedType(obj), jsobject); + +class LazyJSType extends TypeRep { + final Function() _rawJSType; + final String _dartName; + + LazyJSType(this._rawJSType, this._dartName); + + toString() => typeName(_rawJSType()); + + _raw() { + var raw = _rawJSType(); + if (raw == null) { + _warn('Cannot find native JavaScript type ($_dartName) for type check'); + } + return raw; + } + + rawJSTypeForCheck() { + var raw = _raw(); + if (raw != null) return raw; + // Treat as anonymous: return true for any JS object. + return jsobject; + } + + bool isRawType(obj) { + var raw = _raw(); + if (raw != null) return JS('!', '# instanceof #', obj, raw); + // Treat as anonymous: return true for any JS object. + return _isJsObject(obj); + } + + @JSExportName('is') + bool is_T(obj) => isRawType(obj) || instanceOf(obj, this); + + @JSExportName('as') + as_T(obj) => obj == null || is_T(obj) ? obj : castError(obj, this, false); + + @JSExportName('_check') + check_T(obj) => obj == null || is_T(obj) ? obj : castError(obj, this, true); +} + +/// An anonymous JS type +/// +/// For the purposes of subtype checks, these match any JS type. +class AnonymousJSType extends TypeRep { + final String _dartName; + AnonymousJSType(this._dartName); + toString() => _dartName; + + @JSExportName('is') + bool is_T(obj) => _isJsObject(obj) || instanceOf(obj, this); + + @JSExportName('as') + as_T(obj) => obj == null || _isJsObject(obj) ? obj : cast(obj, this, false); + + @JSExportName('_check') + check_T(obj) => obj == null || _isJsObject(obj) ? obj : cast(obj, this, true); +} + +void _warn(arg) { + JS('void', 'console.warn(#)', arg); +} + +var _lazyJSTypes = JS('', 'new Map()'); +var _anonymousJSTypes = JS('', 'new Map()'); + +lazyJSType(Function() getJSTypeCallback, String name) { + var ret = JS('', '#.get(#)', _lazyJSTypes, name); + if (ret == null) { + ret = LazyJSType(getJSTypeCallback, name); + JS('', '#.set(#, #)', _lazyJSTypes, name, ret); + } + return ret; +} + +anonymousJSType(String name) { + var ret = JS('', '#.get(#)', _anonymousJSTypes, name); + if (ret == null) { + ret = AnonymousJSType(name); + JS('', '#.set(#, #)', _anonymousJSTypes, name, ret); + } + return ret; +} + +@JSExportName('dynamic') +final _dynamic = DynamicType(); + +class VoidType extends TypeRep { + toString() => 'void'; +} + +@JSExportName('void') +final void_ = VoidType(); + +class BottomType extends TypeRep { + toString() => 'bottom'; +} + +final bottom = BottomType(); + +class JSObjectType extends TypeRep { + toString() => 'NativeJavaScriptObject'; +} + +final jsobject = JSObjectType(); + +class WrappedType extends Type { + final _wrappedType; + WrappedType(this._wrappedType); + toString() => typeName(_wrappedType); +} + +// Marker class for generic functions, typedefs, and non-generic functions. +abstract class AbstractFunctionType extends TypeRep {} + +/// Memo table for named argument groups. A named argument packet +/// {name1 : type1, ..., namen : typen} corresponds to the path +/// n, name1, type1, ...., namen, typen. The element of the map +/// reached via this path (if any) is the canonical representative +/// for this packet. +final _fnTypeNamedArgMap = JS('', 'new Map()'); + +/// Memo table for positional argument groups. A positional argument +/// packet [type1, ..., typen] (required or optional) corresponds to +/// the path n, type1, ...., typen. The element reached via +/// this path (if any) is the canonical representative for this +/// packet. Note that required and optional parameters packages +/// may have the same canonical representation. +final _fnTypeArrayArgMap = JS('', 'new Map()'); + +/// Memo table for function types. The index path consists of the +/// path length - 1, the returnType, the canonical positional argument +/// packet, and if present, the canonical optional or named argument +/// packet. A level of indirection could be avoided here if desired. +final _fnTypeTypeMap = JS('', 'new Map()'); + +/// Memo table for small function types with no optional or named +/// arguments and less than a fixed n (currently 3) number of +/// required arguments. Indexing into this table by the number +/// of required arguments yields a map which is indexed by the +/// argument types themselves. The element reached via this +/// index path (if present) is the canonical function type. +final List _fnTypeSmallMap = JS('', '[new Map(), new Map(), new Map()]'); + +@NoReifyGeneric() +T _memoizeArray(map, arr, T create()) => JS('', '''(() => { + let len = $arr.length; + $map = $_lookupNonTerminal($map, len); + for (var i = 0; i < len-1; ++i) { + $map = $_lookupNonTerminal($map, $arr[i]); + } + let result = $map.get($arr[len-1]); + if (result !== void 0) return result; + $map.set($arr[len-1], result = $create()); + return result; +})()'''); + +List _canonicalizeArray(List array, map) => + _memoizeArray(map, array, () => array); + +// TODO(leafp): This only canonicalizes of the names are +// emitted in a consistent order. +_canonicalizeNamed(named, map) => JS('', '''(() => { + let key = []; + let names = $getOwnPropertyNames($named); + for (var i = 0; i < names.length; ++i) { + let name = names[i]; + let type = $named[name]; + key.push(name); + key.push(type); + } + return $_memoizeArray($map, key, () => $named); +})()'''); + +_lookupNonTerminal(map, key) => JS('', '''(() => { + let result = $map.get($key); + if (result !== void 0) return result; + $map.set($key, result = new Map()); + return result; +})()'''); + +// TODO(leafp): This handles some low hanging fruit, but +// really we should make all of this faster, and also +// handle more cases here. +FunctionType _createSmall(returnType, List required) => JS('', '''(() => { + let count = $required.length; + let map = $_fnTypeSmallMap[count]; + for (var i = 0; i < count; ++i) { + map = $_lookupNonTerminal(map, $required[i]); + } + let result = map.get($returnType); + if (result !== void 0) return result; + result = ${new FunctionType(returnType, required, [], JS('', '{}'))}; + map.set($returnType, result); + return result; +})()'''); + +class FunctionType extends AbstractFunctionType { + final returnType; + List args; + List optionals; + final named; + // TODO(vsm): This is just parameter metadata for now. + List metadata = []; + String _stringValue; + + /** + * Construct a function type. + * + * We eagerly normalize the argument types to avoid having to deal with + * this logic in multiple places. + * + * This code does best effort canonicalization. It does not guarantee + * that all instances will share. + * + */ + static FunctionType create(returnType, List args, extra) { + // Note that if extra is ever passed as an empty array + // or an empty map, we can end up with semantically + // identical function types that don't canonicalize + // to the same object since we won't fall into this + // fast path. + if (extra == null && JS('!', '#.length < 3', args)) { + return _createSmall(returnType, args); + } + args = _canonicalizeArray(args, _fnTypeArrayArgMap); + var keys; + FunctionType Function() create; + if (extra == null) { + keys = [returnType, args]; + create = () => FunctionType(returnType, args, [], JS('', '{}')); + } else if (JS('!', '# instanceof Array', extra)) { + var optionals = + _canonicalizeArray(JS('', '#', extra), _fnTypeArrayArgMap); + keys = [returnType, args, optionals]; + create = () => FunctionType(returnType, args, optionals, JS('', '{}')); + } else { + var named = _canonicalizeNamed(extra, _fnTypeNamedArgMap); + keys = [returnType, args, named]; + create = () => FunctionType(returnType, args, [], named); + } + return _memoizeArray(_fnTypeTypeMap, keys, create); + } + + List _process(List array) { + var result = []; + for (var i = 0; JS('!', '# < #.length', i, array); ++i) { + var arg = JS('', '#[#]', array, i); + if (JS('!', '# instanceof Array', arg)) { + JS('', '#.push(#.slice(1))', metadata, arg); + JS('', '#.push(#[0])', result, arg); + } else { + JS('', '#.push([])', metadata); + JS('', '#.push(#)', result, arg); + } + } + return result; + } + + FunctionType(this.returnType, this.args, this.optionals, this.named) { + this.args = _process(this.args); + this.optionals = _process(this.optionals); + // TODO(vsm): Add named arguments. + } + + toString() => name; + + int get requiredParameterCount => args.length; + int get positionalParameterCount => args.length + optionals.length; + + getPositionalParameter(int i) { + int n = args.length; + return i < n ? args[i] : optionals[i + n]; + } + + Map getNamedParameters() { + var result = {}; + var names = getOwnPropertyNames(named); + JS('', '#.sort()', names); + for (var i = 0; JS('!', '# < #.length', i, names); ++i) { + String name = JS('!', '#[#]', names, i); + result[name] = JS('', '#[#]', named, name); + } + return result; + } + + get name { + if (_stringValue != null) return _stringValue; + + var buffer = '('; + for (var i = 0; JS('!', '# < #.length', i, args); ++i) { + if (i > 0) { + buffer += ', '; + } + buffer += typeName(JS('', '#[#]', args, i)); + } + if (JS('!', '#.length > 0', optionals)) { + if (JS('!', '#.length > 0', args)) buffer += ', '; + buffer += '['; + for (var i = 0; JS('!', '# < #.length', i, optionals); ++i) { + if (i > 0) { + buffer += ', '; + } + buffer += typeName(JS('', '#[#]', optionals, i)); + } + buffer += ']'; + } else if (JS('!', 'Object.keys(#).length > 0', named)) { + if (JS('!', '#.length > 0', args)) buffer += ', '; + buffer += '{'; + var names = getOwnPropertyNames(named); + JS('', '#.sort()', names); + for (var i = 0; JS('!', '# < #.length', i, names); ++i) { + if (i > 0) { + buffer += ', '; + } + var typeNameString = typeName(JS('', '#[#[#]]', named, names, i)); + buffer += '$typeNameString ${JS('', '#[#]', names, i)}'; + } + buffer += '}'; + } + + var returnTypeName = typeName(returnType); + buffer += ') => $returnTypeName'; + _stringValue = buffer; + return buffer; + } + + @JSExportName('is') + bool is_T(obj) { + if (JS('!', 'typeof # == "function"', obj)) { + var actual = JS('', '#[#]', obj, _runtimeType); + // If there's no actual type, it's a JS function. + // Allow them to subtype all Dart function types. + return JS('!', '# == null || !!#', actual, isSubtype(actual, this)); + } + return false; + } + + static final void Function(Object, Object) _logIgnoredCast = + JS('', '''(() => $_ignoreMemo((actual, expected) => { + console.warn('Ignoring cast fail from ' + $typeName(actual) + + ' to ' + $typeName(expected)); + return null; + }))()'''); + + @JSExportName('as') + as_T(obj, [@notNull bool isImplicit = false]) { + if (obj == null) return obj; + if (JS('!', 'typeof # == "function"', obj)) { + var actual = JS('', '#[#]', obj, _runtimeType); + // If there's no actual type, it's a JS function. + // Allow them to subtype all Dart function types. + if (actual == null) return obj; + var result = isSubtype(actual, this); + if (result == true) return obj; + if (result == null && + isImplicit && + JS('!', 'dart.__ignoreWhitelistedErrors')) { + _logIgnoredCast(actual, this); + return obj; + } + } + return castError(obj, this, isImplicit); + } + + @JSExportName('_check') + check_T(obj) => as_T(obj, true); +} + +class Typedef extends AbstractFunctionType { + dynamic _name; + AbstractFunctionType Function() _closure; + AbstractFunctionType _functionType; + + Typedef(this._name, this._closure) {} + + toString() { + var typeArgs = getGenericArgs(this); + if (typeArgs == null) return name; + + var result = name + '<'; + var allDynamic = true; + for (int i = 0, n = JS('!', '#.length', typeArgs); i < n; ++i) { + if (i > 0) result += ', '; + var typeArg = JS('', '#[#]', typeArgs, i); + if (JS('!', '# !== #', typeArg, _dynamic)) allDynamic = false; + result += typeName(typeArg); + } + result += '>'; + return allDynamic ? name : result; + } + + String get name => JS('!', '#', _name); + + AbstractFunctionType get functionType { + var ft = _functionType; + return ft == null ? _functionType = _closure() : ft; + } + + @JSExportName('is') + bool is_T(object) => functionType.is_T(object); + + @JSExportName('as') + as_T(object) => functionType.as_T(object); + + @JSExportName('_check') + check_T(object) => functionType.check_T(object); +} + +/// A type variable, used by [GenericFunctionType] to represent a type formal. +class TypeVariable extends TypeRep { + final String name; + + TypeVariable(this.name); + + toString() => name; +} + +class GenericFunctionType extends AbstractFunctionType { + final _instantiateTypeParts; + final int formalCount; + final _instantiateTypeBounds; + List _typeFormals; + + GenericFunctionType(instantiateTypeParts, this._instantiateTypeBounds) + : _instantiateTypeParts = instantiateTypeParts, + formalCount = JS('!', '#.length', instantiateTypeParts); + + List get typeFormals { + if (_typeFormals != null) return _typeFormals; + return _typeFormals = _typeFormalsFromFunction(_instantiateTypeParts); + } + + checkBounds(List typeArgs) { + var bounds = instantiateTypeBounds(typeArgs); + var typeFormals = this.typeFormals; + for (var i = 0; i < typeArgs.length; i++) { + checkTypeBound(typeArgs[i], bounds[i], typeFormals[i]); + } + } + + FunctionType instantiate(typeArgs) { + var parts = JS('', '#.apply(null, #)', _instantiateTypeParts, typeArgs); + return FunctionType.create( + JS('', '#[0]', parts), JS('', '#[1]', parts), JS('', '#[2]', parts)); + } + + List instantiateTypeBounds(List typeArgs) { + var boundsFn = _instantiateTypeBounds; + if (boundsFn == null) { + // The Dart 1 spec says omitted type parameters have an upper bound of + // Object. However strong mode assumes `dynamic` for all purposes + // (such as instantiate to bounds) so we use that here. + return List.filled(formalCount, _dynamic); + } + // If bounds are recursive, we need to apply type formals and return them. + return JS('List', '#.apply(null, #)', boundsFn, typeArgs); + } + + toString() { + String s = "<"; + var typeFormals = this.typeFormals; + var typeBounds = instantiateTypeBounds(typeFormals); + for (int i = 0, n = typeFormals.length; i < n; i++) { + if (i != 0) s += ", "; + s += JS('!', '#[#].name', typeFormals, i); + var bound = typeBounds[i]; + if (JS('!', '# !== # && # !== #', bound, dynamic, bound, Object)) { + s += " extends $bound"; + } + } + s += ">" + instantiate(typeFormals).toString(); + return s; + } + + /// Given a [DartType] [type], if [type] is an uninstantiated + /// parameterized type then instantiate the parameters to their + /// bounds and return those type arguments. + /// + /// See the issue for the algorithm description: + /// + List instantiateDefaultBounds() { + var typeFormals = this.typeFormals; + + // All type formals + var all = HashMap.identity(); + // ground types, by index. + // + // For each index, this will be a ground type for the corresponding type + // formal if known, or it will be the original TypeVariable if we are still + // solving for it. This array is passed to `instantiateToBounds` as we are + // progressively solving for type variables. + var defaults = List(typeFormals.length); + // not ground + var partials = Map.identity(); + + var typeBounds = this.instantiateTypeBounds(typeFormals); + for (var i = 0; i < typeFormals.length; i++) { + var typeFormal = typeFormals[i]; + var bound = typeBounds[i]; + all[typeFormal] = i; + if (identical(bound, _dynamic)) { + defaults[i] = bound; + } else { + defaults[i] = typeFormal; + partials[typeFormal] = bound; + } + } + + bool hasFreeFormal(Object t) { + if (partials.containsKey(t)) return true; + + // Generic classes and typedefs. + var typeArgs = getGenericArgs(t); + if (typeArgs != null) return typeArgs.any(hasFreeFormal); + + if (t is GenericFunctionType) { + return hasFreeFormal(t.instantiate(t.typeFormals)); + } + + if (t is FunctionType) { + return hasFreeFormal(t.returnType) || t.args.any(hasFreeFormal); + } + + return false; + } + + var hasProgress = true; + while (hasProgress) { + hasProgress = false; + for (var typeFormal in partials.keys) { + var partialBound = partials[typeFormal]; + if (!hasFreeFormal(partialBound)) { + int index = all[typeFormal]; + defaults[index] = instantiateTypeBounds(defaults)[index]; + partials.remove(typeFormal); + hasProgress = true; + break; + } + } + } + + // If we stopped making progress, and not all types are ground, + // then the whole type is malbounded and an error should be reported + // if errors are requested, and a partially completed type should + // be returned. + if (partials.isNotEmpty) { + throwTypeError('Instantiate to bounds failed for type with ' + 'recursive generic bounds: ${typeName(this)}. ' + 'Try passing explicit type arguments.'); + } + return defaults; + } + + @notNull + @JSExportName('is') + bool is_T(obj) { + if (JS('!', 'typeof # == "function"', obj)) { + var actual = JS('', '#[#]', obj, _runtimeType); + return JS('!', '# != null && !!#', actual, isSubtype(actual, this)); + } + return false; + } + + @JSExportName('as') + as_T(obj) { + if (obj == null || is_T(obj)) return obj; + return castError(obj, this, false); + } + + @JSExportName('_check') + check_T(obj) { + if (obj == null || is_T(obj)) return obj; + return castError(obj, this, true); + } +} + +List _typeFormalsFromFunction(Object typeConstructor) { + // Extract parameter names from the function parameters. + // + // This is not robust in general for user-defined JS functions, but it + // should handle the functions generated by our compiler. + // + // TODO(jmesserly): names of TypeVariables are only used for display + // purposes, such as when an error happens or if someone calls + // `Type.toString()`. So we could recover them lazily rather than eagerly. + // Alternatively we could synthesize new names. + String str = JS('!', '#.toString()', typeConstructor); + var hasParens = str[0] == '('; + var end = str.indexOf(hasParens ? ')' : '=>'); + if (hasParens) { + return str + .substring(1, end) + .split(',') + .map((n) => TypeVariable(n.trim())) + .toList(); + } else { + return [TypeVariable(str.substring(0, end).trim())]; + } +} + +Typedef typedef(name, AbstractFunctionType Function() closure) => + Typedef(name, closure); + +/// Create a function type. +FunctionType fnType(returnType, List args, [extra = undefined]) => + FunctionType.create(returnType, args, extra); + +/// Creates a generic function type. +/// +/// A function type consists of two things: an instantiate function, and an +/// function that returns a list of upper bound constraints for each +/// the type formals. Both functions accept the type parameters, allowing us +/// to substitute values. The upper bound constraints can be omitted if all +/// of the type parameters use the default upper bound. +/// +/// For example given the type >(T) -> T, we can declare +/// this type with `gFnType(T => [T, [T]], T => [Iterable$(T)])`.\ +gFnType(instantiateFn, typeBounds) => + GenericFunctionType(instantiateFn, typeBounds); + +/// TODO(vsm): Remove when mirrors is deprecated. +/// This is a temporary workaround to support dart:mirrors, which doesn't +/// understand generic methods. +getFunctionTypeMirror(AbstractFunctionType type) { + if (type is GenericFunctionType) { + var typeArgs = List.filled(type.formalCount, dynamic); + return type.instantiate(typeArgs); + } + return type; +} + +bool isType(obj) => JS('', '#[#] === #', obj, _runtimeType, Type); + +void checkTypeBound(type, bound, name) { + if (JS('!', '#', isSubtype(type, bound))) return; + + throwTypeError('type `$type` does not extend `$bound`' + ' of `$name`.'); +} + +String typeName(type) => JS('', '''(() => { + if ($type === void 0) return "undefined type"; + if ($type === null) return "null type"; + // Non-instance types + if ($type instanceof $TypeRep) { + return $type.toString(); + } + + // Instance types + let tag = $type[$_runtimeType]; + if (tag === $Type) { + let name = $type.name; + let args = ${getGenericArgs(type)}; + if (args == null) return name; + + if (${getGenericClass(type)} == ${getGenericClass(JSArray)}) name = 'List'; + + let result = name; + result += '<'; + for (let i = 0; i < args.length; ++i) { + if (i > 0) result += ', '; + result += $typeName(args[i]); + } + result += '>'; + return result; + } + if (tag) return "Not a type: " + tag.name; + return "JSObject<" + $type.name + ">"; +})()'''); + +/// Returns true if [ft1] <: [ft2]. +/// Returns false if [ft1] JS('', '''(() => { + let ret1 = $ft1.returnType; + let ret2 = $ft2.returnType; + + let args1 = $ft1.args; + let args2 = $ft2.args; + + if (args1.length > args2.length) { + // If we're in a covariant position, then Dart's arity rules + // agree with strong mode, otherwise we can't be sure. + return ($isCovariant) ? false : null; + } + + for (let i = 0; i < args1.length; ++i) { + if (!$_isSubtype(args2[i], args1[i], !$isCovariant)) { + // Even if isSubtype returns false, assignability + // means that we can't be definitive + return null; + } + } + + let optionals1 = $ft1.optionals; + let optionals2 = $ft2.optionals; + + if (args1.length + optionals1.length < args2.length + optionals2.length) { + return ($isCovariant) ? false : null; + } + + let j = 0; + for (let i = args1.length; i < args2.length; ++i, ++j) { + if (!$_isSubtype(args2[i], optionals1[j], !$isCovariant)) { + return null; + } + } + + for (let i = 0; i < optionals2.length; ++i, ++j) { + if (!$_isSubtype(optionals2[i], optionals1[j], !$isCovariant)) { + return null; + } + } + + let named1 = $ft1.named; + let named2 = $ft2.named; + + let names = $getOwnPropertyNames(named2); + for (let i = 0; i < names.length; ++i) { + let name = names[i]; + let n1 = named1[name]; + let n2 = named2[name]; + if (n1 === void 0) { + return ($isCovariant) ? false : null; + } + if (!$_isSubtype(n2, n1, !$isCovariant)) { + return null; + } + } + + // Check return type last, so that arity mismatched functions can be + // definitively rejected. + + // For `void` we will give the same answer as the VM, so don't return null. + if (ret1 === $void_) return $_isTop(ret2); + + if (!$_isSubtype(ret1, ret2, $isCovariant)) return null; + return true; +})()'''); + +/// Returns true if [t1] <: [t2]. +/// Returns false if [t1] JS('!', '# == # || # == #', type, bottom, type, Null); + +@notNull +bool _isTop(type) { + if (_isFutureOr(type)) { + return _isTop(JS('', '#[0]', getGenericArgs(type))); + } + return JS('!', '# == # || # == # || # == #', type, Object, type, dynamic, + type, void_); +} + +bool _isFutureOr(type) => + identical(getGenericClass(type), getGenericClass(FutureOr)); + +bool _isSubtype(t1, t2, isCovariant) => JS('', '''(() => { + if ($t1 === $t2) return true; + + // Trivially true. + if (${_isTop(t2)} || ${_isBottom(t1)}) { + return true; + } + + // Trivially false. + if (${_isBottom(t2)}) return null; + if (${_isTop(t1)}) { + if ($t1 === $dynamic) return null; + return false; + } + + // Handle FutureOr union type. + if (${_isFutureOr(t1)}) { + let t1TypeArg = ${getGenericArgs(t1)}[0]; + if (${_isFutureOr(t2)}) { + let t2TypeArg = ${getGenericArgs(t2)}[0]; + // FutureOr <: FutureOr iff A <: B + return $_isSubtype(t1TypeArg, t2TypeArg, $isCovariant); + } + + // given t1 is Future | A, then: + // (Future | A) <: t2 iff Future <: t2 and A <: t2. + let t1Future = ${getGenericClass(Future)}(t1TypeArg); + return $_isSubtype(t1Future, $t2, $isCovariant) && + $_isSubtype(t1TypeArg, $t2, $isCovariant); + } + + if ($_isFutureOr($t2)) { + // given t2 is Future | A, then: + // t1 <: (Future | A) iff t1 <: Future or t1 <: A + let t2TypeArg = ${getGenericArgs(t2)}[0]; + let t2Future = ${getGenericClass(Future)}(t2TypeArg); + let s1 = $_isSubtype($t1, t2Future, $isCovariant); + let s2 = $_isSubtype($t1, t2TypeArg, $isCovariant); + if (s1 === true || s2 === true) return true; + if (s1 === null || s2 === null) return null; + return false; + } + + // "Traditional" name-based subtype check. Avoid passing + // function types to the class subtype checks, since we don't + // currently distinguish between generic typedefs and classes. + if (!($t2 instanceof $AbstractFunctionType)) { + // t2 is an interface type. + + if ($t1 instanceof $AbstractFunctionType) { + // Function types are only subtypes of interface types `Function` (and top + // types, handled already above). + return $t2 === $Function; + } + + // All JS types are subtypes of anonymous JS types. + if ($t1 === $jsobject && $t2 instanceof $AnonymousJSType) return true; + + // Compare two interface types: + return ${_isInterfaceSubtype(t1, t2, isCovariant)}; + } + + // Function subtyping. + if (!($t1 instanceof $AbstractFunctionType)) return false; + + // Unwrap typedefs. + if ($t1 instanceof $Typedef) $t1 = $t1.functionType; + if ($t2 instanceof $Typedef) $t2 = $t2.functionType; + + // Handle generic functions. + if ($t1 instanceof $GenericFunctionType) { + if (!($t2 instanceof $GenericFunctionType)) return false; + + // Given generic functions g1 and g2, g1 <: g2 iff: + // + // g1 <: g2 + // + // where TFresh is a list of fresh type variables that both g1 and g2 will + // be instantiated with. + let formalCount = $t1.formalCount; + if (formalCount !== $t2.formalCount) return false; + + // Using either function's type formals will work as long as they're both + // instantiated with the same ones. The instantiate operation is guaranteed + // to avoid capture because it does not depend on its TypeVariable objects, + // rather it uses JS function parameters to ensure correct binding. + let fresh = $t2.typeFormals; + + // Check the bounds of the type parameters of g1 and g2. + // given a type parameter `T1 extends U1` from g1, and a type parameter + // `T2 extends U2` from g2, we must ensure that: + // + // U2 <: U1 + // + // (Note the reversal of direction -- type formal bounds are contravariant, + // similar to the function's formal parameter types). + // + let t1Bounds = $t1.instantiateTypeBounds(fresh); + let t2Bounds = $t2.instantiateTypeBounds(fresh); + // TODO(jmesserly): we could optimize for the common case of no bounds. + for (let i = 0; i < formalCount; i++) { + if (!$_isSubtype(t2Bounds[i], t1Bounds[i], !$isCovariant)) { + return false; + } + } + + $t1 = $t1.instantiate(fresh); + $t2 = $t2.instantiate(fresh); + } else if ($t2 instanceof $GenericFunctionType) { + return false; + } + + // Handle non-generic functions. + return ${_isFunctionSubtype(t1, t2, isCovariant)}; +})()'''); + +bool _isInterfaceSubtype(t1, t2, isCovariant) => JS('', '''(() => { + // We support Dart's covariant generics with the caveat that we do not + // substitute bottom for dynamic in subtyping rules. + // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow: + // - S !<: S + // - S !<: S + + // If we have lazy JS types, unwrap them. This will effectively + // reduce to a prototype check below. + if ($t1 instanceof $LazyJSType) $t1 = $t1.rawJSTypeForCheck(); + if ($t2 instanceof $LazyJSType) $t2 = $t2.rawJSTypeForCheck(); + + if ($t1 === $t2) return true; + if ($t1 === $Object) return false; + + // Classes cannot subtype `Function` or vice versa. + if ($t1 === $Function || $t2 === $Function) return false; + + // If t1 is a JS Object, we may not hit core.Object. + if ($t1 == null) return $t2 == $Object || $t2 == $dynamic; + + // Check if t1 and t2 have the same raw type. If so, check covariance on + // type parameters. + let raw1 = $getGenericClass($t1); + let raw2 = $getGenericClass($t2); + if (raw1 != null && raw1 == raw2) { + let typeArguments1 = $getGenericArgs($t1); + let typeArguments2 = $getGenericArgs($t2); + let length = typeArguments1.length; + if (typeArguments2.length == 0) { + // t2 is the raw form of t1 + return true; + } else if (length == 0) { + // t1 is raw, but t2 is not + if (typeArguments2.every($_isTop)) return true; + return null; + } + if (length != typeArguments2.length) $assertFailed(); + for (let i = 0; i < length; ++i) { + let result = + $_isSubtype(typeArguments1[i], typeArguments2[i], $isCovariant); + if (!result) { + return result; + } + } + return true; + } + + let indefinite = false; + function definitive(t1, t2) { + let result = $_isInterfaceSubtype(t1, t2, $isCovariant); + if (result == null) { + indefinite = true; + return false; + } + return result; + } + + if (definitive($t1.__proto__, $t2)) return true; + + // Check mixin. + let m1 = $getMixin($t1); + if (m1 != null) { + if (definitive(m1, $t2)) return true; + } + + // Check interfaces. + let getInterfaces = $getImplements($t1); + if (getInterfaces) { + for (let i1 of getInterfaces()) { + if (definitive(i1, $t2)) return true; + } + } + + // We found no definite supertypes, and at least one indefinite supertype + // so the answer is indefinite. + if (indefinite) return null; + // We found no definite supertypes and no indefinite supertypes, so we + // can return false. + return false; +})()'''); + +Object extractTypeArguments(T instance, Function f) { + if (instance == null) { + throw ArgumentError('Cannot extract type of null instance.'); + } + var type = unwrapType(T); + if (type is AbstractFunctionType || _isFutureOr(type)) { + throw ArgumentError('Cannot extract from non-class type ($type).'); + } + var typeArguments = getGenericArgs(type); + if (typeArguments.isEmpty) { + throw ArgumentError('Cannot extract from non-generic type ($type).'); + } + var supertype = _getMatchingSupertype(getReifiedType(instance), type); + // The signature of this method guarantees that instance is a T, so we + // should have a valid non-empty list at this point. + assert(supertype != null); + var typeArgs = getGenericArgs(supertype); + assert(typeArgs != null && typeArgs.isNotEmpty); + return dgcall(f, typeArgs, []); +} + +/// Infers type variables based on a series of [trySubtypeMatch] calls, followed +/// by [getInferredTypes] to return the type. +class _TypeInferrer { + final Map _typeVariables; + + /// Creates a [TypeConstraintGatherer] which is prepared to gather type + /// constraints for the given type parameters. + _TypeInferrer(Iterable typeVariables) + : _typeVariables = Map.fromIterables( + typeVariables, typeVariables.map((_) => TypeConstraint())); + + /// Returns the inferred types based on the current constraints. + List getInferredTypes() { + var result = List(); + for (var constraint in _typeVariables.values) { + // Prefer the known bound, if any. + if (constraint.lower != null) { + result.add(constraint.lower); + } else if (constraint.upper != null) { + result.add(constraint.upper); + } else { + return null; + } + } + return result; + } + + /// Tries to match [subtype] against [supertype]. + /// + /// If the match succeeds, the resulting type constraints are recorded for + /// later use by [computeConstraints]. If the match fails, the set of type + /// constraints is unchanged. + bool trySubtypeMatch(Object subtype, Object supertype) => + _isSubtypeMatch(subtype, supertype); + + void _constrainLower(TypeVariable parameter, Object lower) { + _typeVariables[parameter]._constrainLower(lower); + } + + void _constrainUpper(TypeVariable parameter, Object upper) { + _typeVariables[parameter]._constrainUpper(upper); + } + + bool _isFunctionSubtypeMatch(FunctionType subtype, FunctionType supertype) { + // A function type `(M0,..., Mn, [M{n+1}, ..., Mm]) -> R0` is a subtype + // match for a function type `(N0,..., Nk, [N{k+1}, ..., Nr]) -> R1` with + // respect to `L` under constraints `C0 + ... + Cr + C` + // - If `R0` is a subtype match for a type `R1` with respect to `L` under + // constraints `C`: + // - If `n <= k` and `r <= m`. + // - And for `i` in `0...r`, `Ni` is a subtype match for `Mi` with respect + // to `L` under constraints `Ci`. + // Function types with named parameters are treated analogously to the + // positional parameter case above. + // A generic function type `F0` is a + // subtype match for a generic function type `F1` with respect to `L` under constraints `Cl`: + // - If `F0[Z0/T0, ..., Zn/Tn]` is a subtype match for `F0[Z0/S0, ..., + // Zn/Sn]` with respect to `L` under constraints `C`, where each `Zi` is a + // fresh type variable with bound `Bi`. + // - And `Cl` is `C` with each constraint replaced with its closure with + // respect to `[Z0, ..., Zn]`. + if (subtype.requiredParameterCount > supertype.requiredParameterCount) { + return false; + } + if (subtype.positionalParameterCount < supertype.positionalParameterCount) { + return false; + } + // Test the return types. + if (supertype.returnType is! VoidType && + !_isSubtypeMatch(subtype.returnType, supertype.returnType)) { + return false; + } + + // Test the parameter types. + for (int i = 0, n = supertype.positionalParameterCount; i < n; ++i) { + if (!_isSubtypeMatch(supertype.getPositionalParameter(i), + subtype.getPositionalParameter(i))) { + return false; + } + } + var supertypeNamed = supertype.getNamedParameters(); + var subtypeNamed = supertype.getNamedParameters(); + for (var name in supertypeNamed.keys) { + var subtypeParamType = subtypeNamed[name]; + if (subtypeParamType == null) return false; + if (!_isSubtypeMatch(supertypeNamed[name], subtypeParamType)) { + return false; + } + } + return true; + } + + bool _isInterfaceSubtypeMatch(Object subtype, Object supertype) { + // A type `P` is a subtype match for `P` with + // respect to `L` under constraints `C0 + ... + Ck`: + // - If `Mi` is a subtype match for `Ni` with respect to `L` under + // constraints `Ci`. + // A type `P` is a subtype match for `Q` with + // respect to `L` under constraints `C`: + // - If `R` is the superclass of `P` and `R` is a subtype match for `Q` with respect to `L` + // under constraints `C`. + // - Or `R` is one of the interfaces implemented by `P` (considered in lexical order) and `R` is a subtype + // match for `Q` with respect to `L` under constraints `C`. + // - Or `R` is a mixin into `P` (considered in + // lexical order) and `R` is a subtype match for `Q` with respect to `L` under constraints `C`. + + // Note that since kernel requires that no class may only appear in the set + // of supertypes of a given type more than once, the order of the checks + // above is irrelevant; we just need to find the matched superclass, + // substitute, and then iterate through type variables. + var matchingSupertype = _getMatchingSupertype(subtype, supertype); + if (matchingSupertype == null) return false; + + var matchingTypeArgs = getGenericArgs(matchingSupertype); + var supertypeTypeArgs = getGenericArgs(supertype); + for (int i = 0; i < supertypeTypeArgs.length; i++) { + if (!_isSubtypeMatch(matchingTypeArgs[i], supertypeTypeArgs[i])) { + return false; + } + } + return true; + } + + bool _isNull(Object type) => identical(type, unwrapType(Null)); + + /// Attempts to match [subtype] as a subtype of [supertype], gathering any + /// constraints discovered in the process. + /// + /// If a set of constraints was found, `true` is returned and the caller + /// may proceed to call [computeConstraints]. Otherwise, `false` is returned. + /// + /// In the case where `false` is returned, some bogus constraints may have + /// been added to [_protoConstraints]. It is the caller's responsibility to + /// discard them if necessary. + bool _isSubtypeMatch(Object subtype, Object supertype) { + // A type variable `T` in `L` is a subtype match for any type schema `Q`: + // - Under constraint `T <: Q`. + if (subtype is TypeVariable && _typeVariables.containsKey(subtype)) { + _constrainUpper(subtype, supertype); + return true; + } + // A type schema `Q` is a subtype match for a type variable `T` in `L`: + // - Under constraint `Q <: T`. + if (supertype is TypeVariable && _typeVariables.containsKey(supertype)) { + _constrainLower(supertype, subtype); + return true; + } + // Any two equal types `P` and `Q` are subtype matches under no constraints. + // Note: to avoid making the algorithm quadratic, we just check for + // identical(). If P and Q are equal but not identical, recursing through + // the types will give the proper result. + if (identical(subtype, supertype)) return true; + // Any type `P` is a subtype match for `dynamic`, `Object`, or `void` under + // no constraints. + if (_isTop(supertype)) return true; + // `Null` is a subtype match for any type `Q` under no constraints. + // Note that nullable types will change this. + if (_isNull(subtype)) return true; + + // Handle FutureOr union type. + if (_isFutureOr(subtype)) { + var subtypeArg = getGenericArgs(subtype)[0]; + if (_isFutureOr(supertype)) { + // `FutureOr

` is a subtype match for `FutureOr` with respect to `L` + // under constraints `C`: + // - If `P` is a subtype match for `Q` with respect to `L` under constraints + // `C`. + var supertypeArg = getGenericArgs(supertype)[0]; + return _isSubtypeMatch(subtypeArg, supertypeArg); + } + + // `FutureOr

` is a subtype match for `Q` with respect to `L` under + // constraints `C0 + C1`: + // - If `Future

` is a subtype match for `Q` with respect to `L` under + // constraints `C0`. + // - And `P` is a subtype match for `Q` with respect to `L` under + // constraints `C1`. + var subtypeFuture = JS('!', '#(#)', getGenericClass(Future), subtypeArg); + return _isSubtypeMatch(subtypeFuture, supertype) && + _isSubtypeMatch(subtypeArg, supertype); + } + + if (_isFutureOr(supertype)) { + // `P` is a subtype match for `FutureOr` with respect to `L` under + // constraints `C`: + // - If `P` is a subtype match for `Future` with respect to `L` under + // constraints `C`. + // - Or `P` is not a subtype match for `Future` with respect to `L` under + // constraints `C` + // - And `P` is a subtype match for `Q` with respect to `L` under + // constraints `C` + var supertypeArg = getGenericArgs(supertype)[0]; + var supertypeFuture = + JS('!', '#(#)', getGenericClass(Future), supertypeArg); + return _isSubtypeMatch(subtype, supertypeFuture) || + _isSubtypeMatch(subtype, supertypeArg); + } + + // A type variable `T` not in `L` with bound `P` is a subtype match for the + // same type variable `T` with bound `Q` with respect to `L` under + // constraints `C`: + // - If `P` is a subtype match for `Q` with respect to `L` under constraints + // `C`. + if (subtype is TypeVariable) { + return supertype is TypeVariable && identical(subtype, supertype); + } + if (subtype is GenericFunctionType) { + if (supertype is GenericFunctionType) { + // Given generic functions g1 and g2, g1 <: g2 iff: + // + // g1 <: g2 + // + // where TFresh is a list of fresh type variables that both g1 and g2 will + // be instantiated with. + var formalCount = subtype.formalCount; + if (formalCount != supertype.formalCount) return false; + + // Using either function's type formals will work as long as they're + // both instantiated with the same ones. The instantiate operation is + // guaranteed to avoid capture because it does not depend on its + // TypeVariable objects, rather it uses JS function parameters to ensure + // correct binding. + var fresh = supertype.typeFormals; + + // Check the bounds of the type parameters of g1 and g2. + // given a type parameter `T1 extends U1` from g1, and a type parameter + // `T2 extends U2` from g2, we must ensure that: + // + // U2 <: U1 + // + // (Note the reversal of direction -- type formal bounds are + // contravariant, similar to the function's formal parameter types). + // + var t1Bounds = subtype.instantiateTypeBounds(fresh); + var t2Bounds = supertype.instantiateTypeBounds(fresh); + // TODO(jmesserly): we could optimize for the common case of no bounds. + for (var i = 0; i < formalCount; i++) { + if (!_isSubtypeMatch(t2Bounds[i], t1Bounds[i])) { + return false; + } + } + return _isFunctionSubtypeMatch( + subtype.instantiate(fresh), supertype.instantiate(fresh)); + } else { + return false; + } + } else if (supertype is GenericFunctionType) { + return false; + } + + // A type `P` is a subtype match for `Function` with respect to `L` under no + // constraints: + // - If `P` implements a call method. + // - Or if `P` is a function type. + // TODO(paulberry): implement this case. + // A type `P` is a subtype match for a type `Q` with respect to `L` under + // constraints `C`: + // - If `P` is an interface type which implements a call method of type `F`, + // and `F` is a subtype match for a type `Q` with respect to `L` under + // constraints `C`. + // TODO(paulberry): implement this case. + if (subtype is FunctionType) { + if (supertype is! FunctionType) { + if (identical(supertype, unwrapType(Function)) || + identical(supertype, unwrapType(Object))) { + return true; + } else { + return false; + } + } + if (supertype is FunctionType) { + return _isFunctionSubtypeMatch(subtype, supertype); + } + } + return _isInterfaceSubtypeMatch(subtype, supertype); + } + + bool _isTop(Object type) => + identical(type, _dynamic) || + identical(type, void_) || + identical(type, unwrapType(Object)); +} + +/// A constraint on a type parameter that we're inferring. +class TypeConstraint { + /// The lower bound of the type being constrained. This bound must be a + /// subtype of the type being constrained. + Object lower; + + /// The upper bound of the type being constrained. The type being constrained + /// must be a subtype of this bound. + Object upper; + + void _constrainLower(Object type) { + if (lower != null) { + if (isSubtype(lower, type)) { + // nothing to do, existing lower bound is lower than the new one. + return; + } + if (!isSubtype(type, lower)) { + // Neither bound is lower and we don't have GLB, so use bottom type. + type = unwrapType(Null); + } + } + lower = type; + } + + void _constrainUpper(Object type) { + if (upper != null) { + if (isSubtype(type, upper)) { + // nothing to do, existing upper bound is higher than the new one. + return; + } + if (!isSubtype(upper, type)) { + // Neither bound is higher and we don't have LUB, so use top type. + type = unwrapType(Object); + } + } + upper = type; + } + + String toString() => '${typeName(lower)} <: <: ${typeName(upper)}'; +} + +/// Finds a supertype of [subtype] that matches the class [supertype], but may +/// contain different generic type arguments. +Object _getMatchingSupertype(Object subtype, Object supertype) { + if (identical(subtype, supertype)) return supertype; + if (subtype == null || subtype == unwrapType(Object)) return null; + + var subclass = getGenericClass(subtype); + var superclass = getGenericClass(supertype); + if (subclass != null && identical(subclass, superclass)) { + return subtype; // matching supertype found! + } + + var result = _getMatchingSupertype(JS('', '#.__proto__', subtype), supertype); + if (result != null) return result; + + // Check mixin. + var mixin = getMixin(subtype); + if (mixin != null) { + result = _getMatchingSupertype(mixin, supertype); + if (result != null) return result; + } + + // Check interfaces. + var getInterfaces = getImplements(subtype); + if (getInterfaces != null) { + for (var iface in getInterfaces()) { + result = _getMatchingSupertype(iface, supertype); + if (result != null) return result; + } + } + + return null; +} +NN<>/DEBDF>E>G HN7EFNHNMKM'OOO&&AQPNN &51-/$L#/( O!:A:=MOA(#?OQ&(-84/49!9 !#%*!!"(L7B@AC0EE=@@00BGEF,B>@?=9.!F +KA/&2688K?'M N.+MH>1O?(9:9!J 4@B.3M$(/MPO159>3'!("&#0'(@&<I.1,'D' +DIFC:3 26K.(.'F;I<GAM29!1, 9BC2%LEML8OC&42J 3%;'C)49,1*#"(#P,!$-) +$BBLFJ@%A;*+;8+##M* ;@5E,+,/GN-; +"@@;;" << -38 O*9 O 9LA; +%'$.0/>(>:73(<.:7811<@A1 0Q( 8K$8=77->8$O'7NPPH!=L5P:55L,C""4#5 +DI7K3C(AA %6<7=L$$&//(&""6:'K =3*+&,L"I +9B;H,JII7,3"Q.:J16,HC$!4)&&-&4MN <+?6?6OLN79IBM-KQMO!;N$J+L$N+QHO.4P(H2'& 3$R"U9:L OHP:2"LOSJ7B:2PGQ#I*.< ( S!/@MNIQ+AP9  EM =?P0< +(G3Q*'-NQM-#(:8 +'<9# +;K-Q'&$J%M!&$K%K#MO.A7E+/=1Q%!6'.)8)wfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dartj// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This library defines runtime operations on objects used by the code +/// generator. +part of "runtime.dart"; + +// TODO(jmesserly): remove this in favor of _Invocation. +class InvocationImpl extends Invocation { + final Symbol memberName; + final List positionalArguments; + final Map namedArguments; + final List typeArguments; + final bool isMethod; + final bool isGetter; + final bool isSetter; + + InvocationImpl(memberName, List positionalArguments, + {namedArguments, + List typeArguments, + this.isMethod = false, + this.isGetter = false, + this.isSetter = false}) + : memberName = + isSetter ? _setterSymbol(memberName) : _dartSymbol(memberName), + positionalArguments = List.unmodifiable(positionalArguments), + namedArguments = _namedArgsToSymbols(namedArguments), + typeArguments = typeArguments == null + ? const [] + : List.unmodifiable(typeArguments.map(wrapType)); + + static Map _namedArgsToSymbols(namedArgs) { + if (namedArgs == null) return const {}; + return Map.unmodifiable(Map.fromIterable(getOwnPropertyNames(namedArgs), + key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k))); + } +} + +/// Given an object and a method name, tear off the method. +/// Sets the runtime type of the torn off method appropriately, +/// and also binds the object. +/// +/// If the optional `f` argument is passed in, it will be used as the method. +/// This supports cases like `super.foo` where we need to tear off the method +/// from the superclass, not from the `obj` directly. +// TODO(leafp): Consider caching the tearoff on the object? +bind(obj, name, method) { + if (obj == null) obj = jsNull; + if (method == null) method = JS('', '#[#]', obj, name); + var f = JS('', '#.bind(#)', method, obj); + // TODO(jmesserly): canonicalize tearoffs. + JS('', '#._boundObject = #', f, obj); + JS('', '#._boundMethod = #', f, method); + JS('', '#[#] = #', f, _runtimeType, getMethodType(getType(obj), name)); + return f; +} + +/// Binds the `call` method of an interface type, handling null. +/// +/// Essentially this works like `obj?.call`. It also handles the needs of +/// [dsend]/[dcall], returning `null` if no method was found with the given +/// canonical member [name]. +/// +/// [name] is typically `"call"` but it could be the [extensionSymbol] for +/// `call`, if we define it on a native type, and [obj] is known statially to be +/// a native type/interface with `call`. +bindCall(obj, name) { + if (obj == null) return null; + var ftype = getMethodType(getType(obj), name); + if (ftype == null) return null; + var method = JS('', '#[#]', obj, name); + var f = JS('', '#.bind(#)', method, obj); + // TODO(jmesserly): canonicalize tearoffs. + JS('', '#._boundObject = #', f, obj); + JS('', '#._boundMethod = #', f, method); + JS('', '#[#] = #', f, _runtimeType, ftype); + return f; +} + +/// Instantiate a generic method. +/// +/// We need to apply the type arguments both to the function, as well as its +/// associated function type. +gbind(f, @rest typeArgs) { + var result = + JS('', '(...args) => #.apply(null, #.concat(args))', f, typeArgs); + var sig = JS('', '#[#].instantiate(#)', f, _runtimeType, typeArgs); + fn(result, sig); + return result; +} + +dloadRepl(obj, field) => dload(obj, replNameLookup(obj, field), false); + +// Warning: dload, dput, and dsend assume they are never called on methods +// implemented by the Object base class as those methods can always be +// statically resolved. +dload(obj, field, [mirrors = undefined]) { + if (JS('!', 'typeof # == "function" && # == "call"', obj, field)) { + return obj; + } + var f = _canonicalMember(obj, field); + + trackCall(obj); + if (f != null) { + var type = getType(obj); + + if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f); + if (hasMethod(type, f)) return bind(obj, f, null); + + // Always allow for JS interop objects. + if (!JS('!', '#', mirrors) && isJsInterop(obj)) { + return JS('', '#[#]', obj, f); + } + } + return noSuchMethod(obj, InvocationImpl(field, JS('', '[]'), isGetter: true)); +} + +// Version of dload that matches legacy mirrors behavior for JS types. +dloadMirror(obj, field) => dload(obj, field, true); + +_stripGenericArguments(type) { + var genericClass = getGenericClass(type); + if (genericClass != null) return JS('', '#()', genericClass); + return type; +} + +// Version of dput that matches legacy Dart 1 type check rules and mirrors +// behavior for JS types. +// TODO(jacobr): remove the type checking rules workaround when mirrors based +// PageLoader code can generate the correct reified generic types. +dputMirror(obj, field, value) => dput(obj, field, value, true); + +dputRepl(obj, field, value) => + dput(obj, replNameLookup(obj, field), value, false); + +dput(obj, field, value, [mirrors = undefined]) { + var f = _canonicalMember(obj, field); + trackCall(obj); + if (f != null) { + var setterType = getSetterType(getType(obj), f); + if (setterType != null) { + if (JS('!', '#', mirrors)) + setterType = _stripGenericArguments(setterType); + return JS('', '#[#] = #._check(#)', obj, f, setterType, value); + } + // Always allow for JS interop objects. + if (!JS('!', '#', mirrors) && isJsInterop(obj)) { + return JS('', '#[#] = #', obj, f, value); + } + } + noSuchMethod( + obj, InvocationImpl(field, JS('', '[#]', value), isSetter: true)); + return value; +} + +/// Check that a function of a given type can be applied to +/// actuals. +bool _checkApply(FunctionType type, List actuals, namedActuals) { + // Check for too few required arguments. + int actualsCount = JS('!', '#.length', actuals); + var required = type.args; + int requiredCount = JS('!', '#.length', required); + if (actualsCount < requiredCount) return false; + + // Check for too many postional arguments. + var extras = actualsCount - requiredCount; + var optionals = type.optionals; + if (extras > JS('!', '#.length', optionals)) return false; + + // Check if we have invalid named arguments. + Iterable names; + var named = type.named; + if (namedActuals != null) { + names = getOwnPropertyNames(namedActuals); + for (var name in names) { + if (!JS('!', '#.hasOwnProperty(#)', named, name)) return false; + } + } + // Now that we know the signature matches, we can perform type checks. + for (var i = 0; i < requiredCount; ++i) { + JS('', '#[#]._check(#[#])', required, i, actuals, i); + } + for (var i = 0; i < extras; ++i) { + JS('', '#[#]._check(#[#])', optionals, i, actuals, i + requiredCount); + } + if (names != null) { + for (var name in names) { + JS('', '#[#]._check(#[#])', named, name, namedActuals, name); + } + } + return true; +} + +_toSymbolName(symbol) => JS('', '''(() => { + let str = $symbol.toString(); + // Strip leading 'Symbol(' and trailing ')' + return str.substring(7, str.length-1); + })()'''); + +_toDisplayName(name) => JS('', '''(() => { + // Names starting with _ are escaped names used to disambiguate Dart and + // JS names. + if ($name[0] === '_') { + // Inverse of + switch($name) { + case '_get': + return '[]'; + case '_set': + return '[]='; + case '_negate': + return 'unary-'; + case '_constructor': + case '_prototype': + return $name.substring(1); + } + } + return $name; + })()'''); + +Symbol _dartSymbol(name) { + return (JS('!', 'typeof # === "symbol"', name)) + ? JS('Symbol', '#(new #.new(#, #))', const_, PrivateSymbol, + _toSymbolName(name), name) + : JS('Symbol', '#(new #.new(#))', const_, internal.Symbol, + _toDisplayName(name)); +} + +Symbol _setterSymbol(name) { + return (JS('!', 'typeof # === "symbol"', name)) + ? JS('Symbol', '#(new #.new(# + "=", #))', const_, PrivateSymbol, + _toSymbolName(name), name) + : JS('Symbol', '#(new #.new(# + "="))', const_, internal.Symbol, + _toDisplayName(name)); +} + +_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) => + JS('', '''(() => { + $trackCall($obj); + + let originalTarget = obj === void 0 ? f : obj; + + function callNSM() { + return $noSuchMethod(originalTarget, new $InvocationImpl.new( + $displayName, $args, { + namedArguments: $named, + typeArguments: $typeArgs, + isMethod: true + })); + } + if (!($f instanceof Function)) { + // We're not a function (and hence not a method either) + // Grab the `call` method if it's not a function. + if ($f != null) { + $f = ${bindCall(f, _canonicalMember(f, 'call'))}; + $ftype = null; + } + if ($f == null) return callNSM(); + } + // If f is a function, but not a method (no method type) + // then it should have been a function valued field, so + // get the type from the function. + if ($ftype == null) $ftype = $f[$_runtimeType]; + + if ($ftype == null) { + // TODO(leafp): Allow JS objects to go through? + if ($typeArgs != null) { + // TODO(jmesserly): is there a sensible way to handle these? + $throwTypeError('call to JS object `' + $obj + + '` with type arguments <' + $typeArgs + '> is not supported.'); + } + + if ($named != null) $args.push($named); + return $f.apply($obj, $args); + } + + // TODO(vsm): Remove when we no longer need mirrors metadata. + // An array is used to encode annotations attached to the type. + if ($ftype instanceof Array) $ftype = $ftype[0]; + + // Apply type arguments + if ($ftype instanceof $GenericFunctionType) { + let formalCount = $ftype.formalCount; + + if ($typeArgs == null) { + $typeArgs = $ftype.instantiateDefaultBounds(); + } else if ($typeArgs.length != formalCount) { + return callNSM(); + } else { + $ftype.checkBounds($typeArgs); + } + $ftype = $ftype.instantiate($typeArgs); + } else if ($typeArgs != null) { + return callNSM(); + } + + if ($_checkApply($ftype, $args, $named)) { + if ($typeArgs != null) $args = $typeArgs.concat($args); + if ($named != null) $args.push($named); + return $f.apply($obj, $args); + } + return callNSM(); +})()'''); + +dcall(f, args, [named = undefined]) => + _checkAndCall(f, null, JS('', 'void 0'), null, args, named, 'call'); + +dgcall(f, typeArgs, args, [named = undefined]) => + _checkAndCall(f, null, JS('', 'void 0'), typeArgs, args, named, 'call'); + +/// Helper for REPL dynamic invocation variants that make a best effort to +/// enable accessing private members across library boundaries. +replNameLookup(object, field) => JS('', '''(() => { + let rawField = $field; + if (typeof(field) == 'symbol') { + // test if the specified field exists in which case it is safe to use it. + if ($field in $object) return $field; + + // Symbol is from a different library. Make a best effort to + $field = $field.toString(); + $field = $field.substring('Symbol('.length, field.length - 1); + + } else if ($field.charAt(0) != '_') { + // Not a private member so default call path is safe. + return $field; + } + + // If the exact field name is present, invoke callback with it. + if ($field in $object) return $field; + + // TODO(jacobr): warn if there are multiple private members with the same + // name which could happen if super classes in different libraries have + // the same private member name. + let proto = $object; + while (proto !== null) { + // Private field (indicated with "_"). + let symbols = Object.getOwnPropertySymbols(proto); + let target = 'Symbol(' + $field + ')'; + + for (let s = 0; s < symbols.length; s++) { + let sym = symbols[s]; + if (target == sym.toString()) return sym; + } + proto = proto.__proto__; + } + // We didn't find a plausible alternate private symbol so just fall back + // to the regular field. + return rawField; +})()'''); + +// TODO(jmesserly): the debugger extension hardcodes a call to this private +// function. Fix that. +@Deprecated('use replNameLookup') +_dhelperRepl(obj, field, Function(Object) callback) { + return callback(replNameLookup(obj, field)); +} + +/// Shared code for dsend, dindex, and dsetindex. +callMethod(obj, name, typeArgs, args, named, displayName) { + if (JS('!', 'typeof # == "function" && # == "call"', obj, name)) { + return dgcall(obj, typeArgs, args, named); + } + var symbol = _canonicalMember(obj, name); + if (symbol == null) { + return noSuchMethod(obj, InvocationImpl(displayName, args, isMethod: true)); + } + var f = obj != null ? JS('', '#[#]', obj, symbol) : null; + var type = getType(obj); + var ftype = getMethodType(type, symbol); + // No such method if dart object and ftype is missing. + return _checkAndCall(f, ftype, obj, typeArgs, args, named, displayName); +} + +dsend(obj, method, args, [named = undefined]) => + callMethod(obj, method, null, args, named, method); + +dgsend(obj, typeArgs, method, args, [named = undefined]) => + callMethod(obj, method, typeArgs, args, named, method); + +dsendRepl(obj, method, args, [named = undefined]) => + callMethod(obj, replNameLookup(obj, method), null, args, named, method); + +dgsendRepl(obj, typeArgs, method, args, [named = undefined]) => + callMethod(obj, replNameLookup(obj, method), typeArgs, args, named, method); + +dindex(obj, index) => callMethod(obj, '_get', null, [index], null, '[]'); + +dsetindex(obj, index, value) => + callMethod(obj, '_set', null, [index, value], null, '[]='); + +/// TODO(leafp): This duplicates code in types.dart. +/// I haven't found a way to factor it out that makes the +/// code generator happy though. +_ignoreMemo(f) => JS('', '''(() => { + let memo = new Map(); + return (t1, t2) => { + let map = memo.get(t1); + let result; + if (map) { + result = map.get(t2); + if (result !== void 0) return result; + } else { + memo.set(t1, map = new Map()); + } + result = $f(t1, t2); + map.set(t2, result); + return result; + }; +})()'''); + +final Object _ignoreTypeFailure = JS('', '''(() => { + return $_ignoreMemo((actual, type) => { + // TODO(vsm): Remove this hack ... + // This is primarily due to the lack of generic methods, + // but we need to triage all the types. + if ($_isFutureOr(type)) { + // Ignore if we would ignore either side of union. + let typeArg = $getGenericArgs(type)[0]; + let typeFuture = ${getGenericClass(Future)}(typeArg); + return $_ignoreTypeFailure(actual, typeFuture) || + $_ignoreTypeFailure(actual, typeArg); + } + + if (!!$isSubtype(type, $Iterable) && !!$isSubtype(actual, $Iterable) || + !!$isSubtype(type, $Future) && !!$isSubtype(actual, $Future) || + !!$isSubtype(type, $Map) && !!$isSubtype(actual, $Map)) { + console.warn('Ignoring cast fail from ' + $typeName(actual) + + ' to ' + $typeName(type)); + return true; + } + return false; + }); +})()'''); + +@notNull +@JSExportName('is') +bool instanceOf(obj, type) { + if (obj == null) { + return JS('!', '# == # || #', type, Null, _isTop(type)); + } + return JS('!', '!!#', isSubtype(getReifiedType(obj), type)); +} + +@JSExportName('as') +cast(obj, type, @notNull bool isImplicit) { + if (obj == null) return obj; + var actual = getReifiedType(obj); + var result = isSubtype(actual, type); + if (JS( + '!', + '# === true || # === null && # && ' + 'dart.__ignoreWhitelistedErrors && #(#, #)', + result, + result, + isImplicit, + _ignoreTypeFailure, + actual, + type)) { + return obj; + } + return castError(obj, type, isImplicit); +} + +bool test(bool obj) { + if (obj == null) _throwBooleanConversionError(); + return obj; +} + +bool dtest(obj) { + if (obj is! bool) booleanConversionFailed(obj); + return obj; +} + +void _throwBooleanConversionError() => throw BooleanConversionAssertionError(); + +void booleanConversionFailed(obj) { + var actual = typeName(getReifiedType(test(obj))); + throw TypeErrorImpl("type '$actual' is not a 'bool' in boolean expression"); +} + +asInt(obj) { + if (obj == null) return null; + + if (JS('!', 'Math.floor(#) != #', obj, obj)) { + castError(obj, JS('', '#', int), false); + } + return obj; +} + +/// Checks that `x` is not null or undefined. +// +// TODO(jmesserly): inline this, either by generating it as a function into +// the module, or via some other pattern such as: +// +// || nullErr() +// (t0 = ) != null ? t0 : nullErr() +@JSExportName('notNull') +_notNull(x) { + if (x == null) throwNullValueError(); + return x; +} + +/// The global constant map table. +final constantMaps = JS('', 'new Map()'); + +constMap(JSArray elements) { + Function(Object, Object) lookupNonTerminal = JS('', '''function(map, key) { + let result = map.get(key); + if (result != null) return result; + map.set(key, result = new Map()); + return result; + }'''); + var count = elements.length; + var map = lookupNonTerminal(constantMaps, count); + for (var i = 0; i < count; i++) { + map = lookupNonTerminal(map, JS('', '#[#]', elements, i)); + } + map = lookupNonTerminal(map, K); + var result = JS('', '#.get(#)', map, V); + if (result != null) return result; + result = ImmutableMap.from(elements); + JS('', '#.set(#, #)', map, V, result); + return result; +} + +bool dassert(value) { + if (JS('!', '# != null && #[#] instanceof #', value, value, _runtimeType, + AbstractFunctionType)) { + value = dcall(value, []); + } + return dtest(value); +} + +/// Store a JS error for an exception. For non-primitives, we store as an +/// expando. For primitive, we use a side cache. To limit memory leakage, we +/// only keep the last [_maxTraceCache] entries. +final _error = JS('', 'Symbol("_error")'); +Map _primitiveErrorCache; +const _maxErrorCache = 10; + +bool _isJsError(exception) { + return JS('!', '#.Error != null && # instanceof #.Error', global_, exception, + global_); +} + +// Record/return the JS error for an exception. If an error was already +// recorded, prefer that to [newError]. +recordJsError(exception, [newError]) { + if (_isJsError(exception)) return exception; + + var useExpando = + exception != null && JS('!', 'typeof # == "object"', exception); + var error; + if (useExpando) { + error = JS('', '#[#]', exception, _error); + } else { + if (_primitiveErrorCache == null) _primitiveErrorCache = {}; + error = _primitiveErrorCache[exception]; + } + if (error != null) return error; + if (newError != null) { + error = newError; + } else { + // We should only hit this path when a non-Error was thrown from JS. In + // case, there is no stack trace on the exception, so we create one: + error = JS('', 'new Error()'); + } + if (useExpando) { + JS('', '#[#] = #', exception, _error, error); + } else { + _primitiveErrorCache[exception] = error; + if (_primitiveErrorCache.length > _maxErrorCache) { + _primitiveErrorCache.remove(_primitiveErrorCache.keys.first); + } + } + return error; +} + +@JSExportName('throw') +throw_(obj) { + // Note, we create the error here to avoid the extra frame. + // package:stack_trace and tests appear to assume this. We could fix use + // cases instead, but we're already on the exceptional path here. + recordJsError(obj, JS('', 'new Error()')); + JS('', 'throw #', obj); +} + +@JSExportName('rethrow') +rethrow_(obj) { + JS('', 'throw #', obj); +} + +// This is a utility function: it is only intended to be called from dev +// tools. +stackPrint(exception) { + var error = recordJsError(exception); + JS('', 'console.log(#.stack ? #.stack : "No stack trace for: " + #)', error, + error, error); +} + +// Forward to dart:_js_helper to create a _StackTrace object. +stackTrace(exception) => getTraceFromException(exception); + +final _value = JS('', 'Symbol("_value")'); + +/// +/// Looks up a sequence of [keys] in [map], recursively, and +/// returns the result. If the value is not found, [valueFn] will be called to +/// add it. For example: +/// +/// let map = new Map(); +/// putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world'); +/// +/// ... will create a Map with a structure like: +/// +/// { 1: { 2: { 'hi ': { 'there ': 'world' } } } } +/// +multiKeyPutIfAbsent(map, keys, valueFn) => JS('', '''(() => { + for (let k of $keys) { + let value = $map.get(k); + if (!value) { + // TODO(jmesserly): most of these maps are very small (e.g. 1 item), + // so it may be worth optimizing for that. + $map.set(k, value = new Map()); + } + $map = value; + } + if ($map.has($_value)) return $map.get($_value); + let value = $valueFn(); + $map.set($_value, value); + return value; +})()'''); + +/// The global constant table. +/// This maps the number of names in the object (n) +/// to a path of length 2*n of maps indexed by the name and +/// and value of the field. The final map is +/// indexed by runtime type, and contains the canonical +/// version of the object. +final constants = JS('', 'new Map()'); + +/// +/// Canonicalize a constant object. +/// +/// Preconditions: +/// - `obj` is an objects or array, not a primitive. +/// - nested values of the object are themselves already canonicalized. +/// +@JSExportName('const') +const_(obj) => JS('', '''(() => { + // TODO(leafp): This table gets quite large in apps. + // Keeping the paths is probably expensive. It would probably + // be more space efficient to just use a direct hash table with + // an appropriately defined structural equality function. + function lookupNonTerminal(map, key) { + let result = map.get(key); + if (result !== void 0) return result; + map.set(key, result = new Map()); + return result; + }; + let names = $getOwnNamesAndSymbols($obj); + let count = names.length; + // Index by count. All of the paths through this map + // will have 2*count length. + let map = lookupNonTerminal($constants, count); + // TODO(jmesserly): there's no guarantee in JS that names/symbols are + // returned in the same order. + // + // We could probably get the same order if we're judicious about + // initializing fields in a consistent order across all const constructors. + // Alternatively we need a way to sort them to make consistent. + // + // Right now we use the (name,value) pairs in sequence, which prevents + // an object with incorrect field values being returned, but won't + // canonicalize correctly if key order is different. + // + // See issue https://github.com/dart-lang/sdk/issues/30876 + for (let i = 0; i < count; i++) { + let name = names[i]; + map = lookupNonTerminal(map, name); + map = lookupNonTerminal(map, $obj[name]); + } + // TODO(leafp): It may be the case that the reified type + // is always one of the keys already used above? + let type = $getReifiedType($obj); + let value = map.get(type); + if (value) return value; + map.set(type, $obj); + return $obj; +})()'''); + +/// The global constant list table. +/// This maps the number of elements in the list (n) +/// to a path of length n of maps indexed by the value +/// of the field. The final map is indexed by the element +/// type and contains the canonical version of the list. +final constantLists = JS('', 'new Map()'); + +/// Canonicalize a constant list +constList(elements, elementType) => JS('', '''(() => { + function lookupNonTerminal(map, key) { + let result = map.get(key); + if (result !== void 0) return result; + map.set(key, result = new Map()); + return result; + }; + let count = $elements.length; + let map = lookupNonTerminal($constantLists, count); + for (let i = 0; i < count; i++) { + map = lookupNonTerminal(map, elements[i]); + } + let value = map.get($elementType); + if (value) return value; + + ${getGenericClass(JSArray)}($elementType).unmodifiable($elements); + map.set($elementType, elements); + return elements; +})()'''); + +constFn(x) => JS('', '() => x'); + +/// Gets the extension symbol given a member [name]. +/// +/// This is inlined by the compiler when used with a literal string. +extensionSymbol(String name) => JS('', 'dartx[#]', name); + +// The following are helpers for Object methods when the receiver +// may be null. These should only be generated by the compiler. +bool equals(x, y) { + // We handle `y == null` inside our generated operator methods, to keep this + // function minimal. + // This pattern resulted from performance testing; it found that dispatching + // was the fastest solution, even for primitive types. + return JS('!', '# == null ? # == null : #[#](#)', x, y, x, + extensionSymbol('_equals'), y); +} + +int hashCode(obj) { + return obj == null ? 0 : JS('!', '#[#]', obj, extensionSymbol('hashCode')); +} + +@JSExportName('toString') +String _toString(obj) { + if (obj == null) return "null"; + if (obj is String) return obj; + return JS('!', '#[#]()', obj, extensionSymbol('toString')); +} + +/// Converts to a non-null [String], equivalent to +/// `dart.notNull(dart.toString(obj))`. +/// +/// This is commonly used in string interpolation. +@notNull +String str(obj) { + if (obj == null) return "null"; + if (obj is String) return obj; + return _notNull(JS('!', '#[#]()', obj, extensionSymbol('toString'))); +} + +// TODO(jmesserly): is the argument type verified statically? +noSuchMethod(obj, Invocation invocation) { + if (obj == null) defaultNoSuchMethod(obj, invocation); + return JS('', '#[#](#)', obj, extensionSymbol('noSuchMethod'), invocation); +} + +/// The default implementation of `noSuchMethod` to match `Object.noSuchMethod`. +defaultNoSuchMethod(obj, Invocation i) { + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + throw NoSuchMethodError.withInvocation(obj, i); +} + +runtimeType(obj) { + return obj == null ? Null : JS('', '#[dartx.runtimeType]', obj); +} + +final identityHashCode_ = JS('', 'Symbol("_identityHashCode")'); + +/// Adapts a Dart `get iterator` into a JS `[Symbol.iterator]`. +// TODO(jmesserly): instead of an adaptor, we could compile Dart iterators +// natively implementing the JS iterator protocol. This would allow us to +// optimize them a bit. +final JsIterator = JS('', ''' + class JsIterator { + constructor(dartIterator) { + this.dartIterator = dartIterator; + } + next() { + let i = this.dartIterator; + let done = !i.moveNext(); + return { done: done, value: done ? void 0 : i.current }; + } + } +'''); + +_canonicalMember(obj, name) { + // Private names are symbols and are already canonical. + if (JS('!', 'typeof # === "symbol"', name)) return name; + + if (obj != null && JS('!', '#[#] != null', obj, _extensionType)) { + return JS('', 'dartx.#', name); + } + + // Check for certain names that we can't use in JS + if (JS('!', '# == "constructor" || # == "prototype"', name, name)) { + JS('', '# = "+" + #', name, name); + } + return name; +} + +/// Emulates the implicit "loadLibrary" function provided by a deferred library. +/// +/// Libraries are not actually deferred in DDC, so this just returns a future +/// that completes immediately. +Future loadLibrary() => Future.value(); + +/// Defines lazy statics. +void defineLazy(to, from) { + for (var name in getOwnNamesAndSymbols(from)) { + defineLazyField(to, name, getOwnPropertyDescriptor(from, name)); + } +} +7NN<H9*"-"?LF>.>?,MH<@NN6<!:,-(+J AJLKQ) 1"*,-(+. "MIFHKG+F(P7,<%QG4,@KNC@91(5!9F,<0I< B+352--"B//FI,:%KD,&4/+O' + 8B%A!8H%G!D1B"$ #<68&;:%24C5J,"@B30*52 %,"-<," +'I2MK@4#N*A C(:B(LJ#+7+/0K +L"6/2LD-I +(O>;+=OB17>K1&3 +4<.8'$5H"7AB<)*&,82H!CNBIE7=$(.;3$ +$57;9+!7)*& 6$/%E# +!5E:B@OO9=&N"!>3(3 "!H>+9NQ)?2CA@KJ ( ! ?:;K$5G'QN (2Erfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +part of "runtime.dart"; + +/// This library defines a set of general javascript utilities for us +/// by the Dart runtime. +// TODO(ochafik): Rewrite some of these in Dart when possible. + +/// The JavaScript undefined constant. +/// +/// This is initialized by DDC to JS `void 0`. +const undefined = null; + +final Function(Object, Object, Object) defineProperty = + JS('', 'Object.defineProperty'); + +defineValue(obj, name, value) { + defineAccessor(obj, name, value: value, configurable: true, writable: true); + return value; +} + +final Function(Object, Object, + {Object get, + Object set, + Object value, + bool configurable, + bool writable}) defineAccessor = JS('', 'Object.defineProperty'); + +final Function(Object, Object) getOwnPropertyDescriptor = + JS('', 'Object.getOwnPropertyDescriptor'); + +final Iterable Function(Object) getOwnPropertyNames = + JS('', 'Object.getOwnPropertyNames'); + +final Function(Object) getOwnPropertySymbols = + JS('', 'Object.getOwnPropertySymbols'); + +/// This error indicates a strong mode specific failure, other than a type +/// assertion failure (TypeError) or CastError. +void throwTypeError(String message) { + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + throw TypeErrorImpl(message); +} + +/// This error indicates a bug in the runtime or the compiler. +void throwInternalError(String message) { + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + JS('', 'throw Error(#)', message); +} + +Iterable getOwnNamesAndSymbols(obj) { + var names = getOwnPropertyNames(obj); + var symbols = getOwnPropertySymbols(obj); + return JS('', '#.concat(#)', names, symbols); +} + +safeGetOwnProperty(obj, name) { + var desc = getOwnPropertyDescriptor(obj, name); + if (desc != null) return JS('', '#.value', desc); +} + +/// Defines a lazy static field. +/// After initial get or set, it will replace itself with a value property. +// TODO(jmesserly): reusing descriptor objects has been shown to improve +// performance in other projects (e.g. webcomponents.js ShadowDOM polyfill). +defineLazyField(to, name, desc) => JS('', '''(() => { + let init = $desc.get; + let value = null; + $desc.get = function() { + if (init == null) return value; + let f = init; + init = $throwCyclicInitializationError; + if (f === init) f($name); // throw cycle error + try { + value = f(); + init = null; + return value; + } catch (e) { + init = null; + value = null; + throw e; + } + }; + $desc.configurable = true; + if ($desc.set != null) { + $desc.set = function(x) { + init = null; + value = x; + }; + } + return ${defineProperty(to, name, desc)}; +})()'''); + +copyTheseProperties(to, from, names) { + for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) { + var name = JS('', '#[#]', names, i); + if (name == 'constructor') continue; + copyProperty(to, from, name); + } + return to; +} + +copyProperty(to, from, name) { + var desc = getOwnPropertyDescriptor(from, name); + if (JS('!', '# == Symbol.iterator', name)) { + // On native types, Symbol.iterator may already be present. + // TODO(jmesserly): investigate if we still need this. + // If so, we need to find a better solution. + // See https://github.com/dart-lang/sdk/issues/28324 + var existing = getOwnPropertyDescriptor(to, name); + if (existing != null) { + if (JS('!', '#.writable', existing)) { + JS('', '#[#] = #.value', to, name, desc); + } + return; + } + } + defineProperty(to, name, desc); +} + +@JSExportName('export') +exportProperty(to, from, name) => copyProperty(to, from, name); + +/// Copy properties from source to destination object. +/// This operation is commonly called `mixin` in JS. +copyProperties(to, from) { + return copyTheseProperties(to, from, getOwnNamesAndSymbols(from)); +} +NN<F?'/8% OF:/6*/,K0&? ?*?%&(,0 24!LIM6$,3 +, +'@))" 3/@;197-2"@75Etfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dartG// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This library defines the operations that define and manipulate Dart +/// classes. Included in this are: +/// - Generics +/// - Class metadata +/// - Extension methods +/// + +// TODO(leafp): Consider splitting some of this out. +part of "runtime.dart"; + +/// Returns a new type that mixes members from base and the mixin. +/// +/// The mixin must be non-generic; generic mixins are handled by [genericMixin]. +void mixinMembers(to, from) { + JS('', '#[#] = #', to, _mixin, from); + var toProto = JS('', '#.prototype', to); + var fromProto = JS('', '#.prototype', from); + _copyMembers(toProto, fromProto); + _mixinSignature(to, from, _methodSig); + _mixinSignature(to, from, _fieldSig); + _mixinSignature(to, from, _getterSig); + _mixinSignature(to, from, _setterSig); +} + +void _copyMembers(to, from) { + var names = getOwnNamesAndSymbols(from); + for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) { + String name = JS('', '#[#]', names, i); + if (name == 'constructor') continue; + _copyMember(to, from, name); + } + return to; +} + +void _copyMember(to, from, name) { + var desc = getOwnPropertyDescriptor(from, name); + if (JS('!', '# == Symbol.iterator', name)) { + // On native types, Symbol.iterator may already be present. + // TODO(jmesserly): investigate if we still need this. + // If so, we need to find a better solution. + // See https://github.com/dart-lang/sdk/issues/28324 + var existing = getOwnPropertyDescriptor(to, name); + if (existing != null) { + if (JS('!', '#.writable', existing)) { + JS('', '#[#] = #.value', to, name, desc); + } + return; + } + } + var getter = JS('', '#.get', desc); + var setter = JS('', '#.set', desc); + if (getter != null) { + if (setter == null) { + var obj = JS( + '', + '#.set = { __proto__: #.__proto__, ' + 'set [#](x) { return super[#] = x; } }', + desc, + to, + name, + name); + JS('', '#.set = #.set', desc, getOwnPropertyDescriptor(obj, name)); + } + } else if (setter != null) { + if (getter == null) { + var obj = JS( + '', + '#.get = { __proto__: #.__proto__, ' + 'get [#]() { return super[#]; } }', + desc, + to, + name, + name); + JS('', '#.get = #.get', desc, getOwnPropertyDescriptor(obj, name)); + } + } + defineProperty(to, name, desc); +} + +void _mixinSignature(to, from, kind) { + JS('', '#[#] = #', to, kind, () { + var baseMembers = _getMembers(JS('', '#.__proto__', to), kind); + var fromMembers = _getMembers(from, kind); + if (fromMembers == null) return baseMembers; + var toSignature = JS('', '{ __proto__: # }', baseMembers); + copyProperties(toSignature, fromMembers); + return toSignature; + }); +} + +final _mixin = JS('', 'Symbol("mixin")'); + +getMixin(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', + clazz, _mixin, clazz, _mixin); + +@JSExportName('implements') +final _implements = JS('', 'Symbol("implements")'); + +List Function() getImplements(clazz) => JS( + '', + 'Object.hasOwnProperty.call(#, #) ? #[#] : null', + clazz, + _implements, + clazz, + _implements); + +/// The Symbol for storing type arguments on a specialized generic type. +final _typeArguments = JS('', 'Symbol("typeArguments")'); + +final _originalDeclaration = JS('', 'Symbol("originalDeclaration")'); + +final mixinNew = JS('', 'Symbol("dart.mixinNew")'); + +/// Memoize a generic type constructor function. +generic(typeConstructor, setBaseClass) => JS('', '''(() => { + let length = $typeConstructor.length; + if (length < 1) { + $throwInternalError('must have at least one generic type argument'); + } + let resultMap = new Map(); + function makeGenericType(...args) { + if (args.length != length && args.length != 0) { + $throwInternalError('requires ' + length + ' or 0 type arguments'); + } + while (args.length < length) args.push($dynamic); + + let value = resultMap; + for (let i = 0; i < length; i++) { + let arg = args[i]; + if (arg == null) { + $throwInternalError('type arguments should not be null: ' + + $typeConstructor); + } + let map = value; + value = map.get(arg); + if (value === void 0) { + if (i + 1 == length) { + value = $typeConstructor.apply(null, args); + // Save the type constructor and arguments for reflection. + if (value) { + value[$_typeArguments] = args; + value[$_originalDeclaration] = makeGenericType; + } + map.set(arg, value); + if ($setBaseClass != null) $setBaseClass.apply(null, args); + } else { + value = new Map(); + map.set(arg, value); + } + } + } + return value; + } + makeGenericType[$_genericTypeCtor] = $typeConstructor; + return makeGenericType; +})()'''); + +getGenericClass(type) => safeGetOwnProperty(type, _originalDeclaration); + +List getGenericArgs(type) => + JS('List', '#', safeGetOwnProperty(type, _typeArguments)); + +List getGenericTypeFormals(genericClass) { + return _typeFormalsFromFunction(getGenericTypeCtor(genericClass)); +} + +Object instantiateClass(Object genericClass, List typeArgs) { + return JS('', '#.apply(null, #)', genericClass, typeArgs); +} + +final _constructorSig = JS('', 'Symbol("sigCtor")'); +final _methodSig = JS('', 'Symbol("sigMethod")'); +final _fieldSig = JS('', 'Symbol("sigField")'); +final _getterSig = JS('', 'Symbol("sigGetter")'); +final _setterSig = JS('', 'Symbol("sigSetter")'); +final _staticMethodSig = JS('', 'Symbol("sigStaticMethod")'); +final _staticFieldSig = JS('', 'Symbol("sigStaticField")'); +final _staticGetterSig = JS('', 'Symbol("sigStaticGetter")'); +final _staticSetterSig = JS('', 'Symbol("sigStaticSetter")'); +final _genericTypeCtor = JS('', 'Symbol("genericType")'); + +getConstructors(value) => _getMembers(value, _constructorSig); +getMethods(value) => _getMembers(value, _methodSig); +getFields(value) => _getMembers(value, _fieldSig); +getGetters(value) => _getMembers(value, _getterSig); +getSetters(value) => _getMembers(value, _setterSig); +getStaticMethods(value) => _getMembers(value, _staticMethodSig); +getStaticFields(value) => _getMembers(value, _staticFieldSig); +getStaticGetters(value) => _getMembers(value, _staticGetterSig); +getStaticSetters(value) => _getMembers(value, _staticSetterSig); + +getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor); + +/// Get the type of a method from an object using the stored signature +getType(obj) => + JS('', '# == null ? # : #.__proto__.constructor', obj, Object, obj); + +bool isJsInterop(obj) { + if (obj == null) return false; + if (JS('!', 'typeof # === "function"', obj)) { + // A function is a Dart function if it has runtime type information. + return JS('!', '#[#] == null', obj, _runtimeType); + } + // Primitive types are not JS interop types. + if (JS('!', 'typeof # !== "object"', obj)) return false; + + // Extension types are not considered JS interop types. + // Note that it is still possible to call typed JS interop methods on + // extension types but the calls must be statically typed. + if (JS('!', '#[#] != null', obj, _extensionType)) return false; + return JS('!', '!($obj instanceof $Object)'); +} + +/// Get the type of a method from a type using the stored signature +getMethodType(type, name) { + var m = getMethods(type); + return m != null ? JS('', '#[#]', m, name) : null; +} + +/// Gets the type of the corresponding setter (this includes writable fields). +getSetterType(type, name) { + var setters = getSetters(type); + if (setters != null) { + var type = JS('', '#[#]', setters, name); + if (type != null) { + if (JS('!', '# instanceof Array', type)) { + // The type has metadata attached. Pull out just the type. + // TODO(jmesserly): remove when we remove mirrors + return JS('', '#[0]', type); + } + return type; + } + } + var fields = getFields(type); + if (fields != null) { + var fieldInfo = JS('', '#[#]', fields, name); + if (fieldInfo != null && JS('!', '!#.isFinal', fieldInfo)) { + return JS('', '#.type', fieldInfo); + } + } + return null; +} + +finalFieldType(type, metadata) => + JS('', '{ type: #, isFinal: true, metadata: # }', type, metadata); + +fieldType(type, metadata) => + JS('', '{ type: #, isFinal: false, metadata: # }', type, metadata); + +/// Get the type of a constructor from a class using the stored signature +/// If name is undefined, returns the type of the default constructor +/// Returns undefined if the constructor is not found. +classGetConstructorType(cls, name) { + if (cls == null) return null; + if (name == null) name = 'new'; + var ctors = getConstructors(cls); + return ctors != null ? JS('', '#[#]', ctors, name) : null; +} + +void setMethodSignature(f, sigF) => JS('', '#[#] = #', f, _methodSig, sigF); +void setFieldSignature(f, sigF) => JS('', '#[#] = #', f, _fieldSig, sigF); +void setGetterSignature(f, sigF) => JS('', '#[#] = #', f, _getterSig, sigF); +void setSetterSignature(f, sigF) => JS('', '#[#] = #', f, _setterSig, sigF); + +// Set up the constructor signature field on the constructor +void setConstructorSignature(f, sigF) => + JS('', '#[#] = #', f, _constructorSig, sigF); + +// Set up the static signature field on the constructor +void setStaticMethodSignature(f, sigF) => + JS('', '#[#] = #', f, _staticMethodSig, sigF); + +void setStaticFieldSignature(f, sigF) => + JS('', '#[#] = #', f, _staticFieldSig, sigF); + +void setStaticGetterSignature(f, sigF) => + JS('', '#[#] = #', f, _staticGetterSig, sigF); + +void setStaticSetterSignature(f, sigF) => + JS('', '#[#] = #', f, _staticSetterSig, sigF); + +_getMembers(type, kind) { + var sig = JS('', '#[#]', type, kind); + return JS('!', 'typeof # == "function"', sig) + ? JS('', '#[#] = #()', type, kind, sig) + : sig; +} + +bool _hasMember(type, kind, name) { + var sig = _getMembers(type, kind); + return sig != null && JS('!', '# in #', name, sig); +} + +bool hasMethod(type, name) => _hasMember(type, _methodSig, name); +bool hasGetter(type, name) => _hasMember(type, _getterSig, name); +bool hasSetter(type, name) => _hasMember(type, _setterSig, name); +bool hasField(type, name) => _hasMember(type, _fieldSig, name); + +final _extensionType = JS('', 'Symbol("extensionType")'); + +final dartx = JS('', 'dartx'); + +/// Install properties in prototype-first order. Properties / descriptors from +/// more specific types should overwrite ones from less specific types. +void _installProperties(jsProto, dartType, installedParent) { + if (JS('!', '# === #', dartType, Object)) { + _installPropertiesForObject(jsProto); + return; + } + // If the extension methods of the parent have been installed on the parent + // of [jsProto], the methods will be available via prototype inheritance. + var dartSupertype = JS('', '#.__proto__', dartType); + if (JS('!', '# !== #', dartSupertype, installedParent)) { + _installProperties(jsProto, dartSupertype, installedParent); + } + + var dartProto = JS('', '#.prototype', dartType); + copyTheseProperties(jsProto, dartProto, getOwnPropertySymbols(dartProto)); +} + +void _installPropertiesForObject(jsProto) { + // core.Object members need to be copied from the non-symbol name to the + // symbol name. + var coreObjProto = JS('', '#.prototype', Object); + var names = getOwnPropertyNames(coreObjProto); + for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) { + var name = JS('!', '#[#]', names, i); + if (name == 'constructor') continue; + var desc = getOwnPropertyDescriptor(coreObjProto, name); + defineProperty(jsProto, JS('', '#.#', dartx, name), desc); + } +} + +void _installPropertiesForGlobalObject(jsProto) { + _installPropertiesForObject(jsProto); + // Use JS toString for JS objects, rather than the Dart one. + JS('', '#[dartx.toString] = function() { return this.toString(); }', jsProto); + identityEquals ??= JS('', '#[dartx._equals]', jsProto); +} + +final _extensionMap = JS('', 'new Map()'); + +_applyExtension(jsType, dartExtType) { + // TODO(vsm): Not all registered js types are real. + if (jsType == null) return; + var jsProto = JS('', '#.prototype', jsType); + if (jsProto == null) return; + + if (JS('!', '# === #', dartExtType, Object)) { + _installPropertiesForGlobalObject(jsProto); + return; + } + + _installProperties( + jsProto, dartExtType, JS('', '#[#]', jsProto, _extensionType)); + + // Mark the JS type's instances so we can easily check for extensions. + if (JS('!', '# !== #', dartExtType, JSFunction)) { + JS('', '#[#] = #', jsProto, _extensionType, dartExtType); + } + JS('', '#[#] = #[#]', jsType, _methodSig, dartExtType, _methodSig); + JS('', '#[#] = #[#]', jsType, _fieldSig, dartExtType, _fieldSig); + JS('', '#[#] = #[#]', jsType, _getterSig, dartExtType, _getterSig); + JS('', '#[#] = #[#]', jsType, _setterSig, dartExtType, _setterSig); +} + +/// Apply the previously registered extension to the type of [nativeObject]. +/// This is intended for types that are not available to polyfill at startup. +applyExtension(name, nativeObject) { + var dartExtType = JS('', '#.get(#)', _extensionMap, name); + var jsType = JS('', '#.constructor', nativeObject); + _applyExtension(jsType, dartExtType); +} + +/// Apply all registered extensions to a window. This is intended for +/// different frames, where registrations need to be reapplied. +applyAllExtensions(global) { + JS('', '#.forEach((dartExtType, name) => #(#[name], dartExtType))', + _extensionMap, _applyExtension, global); +} + +/// Copy symbols from the prototype of the source to destination. +/// These are the only properties safe to copy onto an existing public +/// JavaScript class. +registerExtension(name, dartExtType) { + JS('', '#.set(#, #)', _extensionMap, name, dartExtType); + var jsType = JS('', '#[#]', global_, name); + _applyExtension(jsType, dartExtType); +} + +/// +/// Mark a concrete type as implementing extension methods. +/// For example: `class MyIter implements Iterable`. +/// +/// This takes a list of names, which are the extension methods implemented. +/// It will add a forwarder, so the extension method name redirects to the +/// normal Dart method name. For example: +/// +/// defineExtensionMembers(MyType, ['add', 'remove']); +/// +/// Results in: +/// +/// MyType.prototype[dartx.add] = MyType.prototype.add; +/// MyType.prototype[dartx.remove] = MyType.prototype.remove; +/// +// TODO(jmesserly): essentially this gives two names to the same method. +// This benefit is roughly equivalent call performance either way, but the +// cost is we need to call defineExtensionMembers any time a subclass +// overrides one of these methods. +defineExtensionMethods(type, Iterable memberNames) { + var proto = JS('', '#.prototype', type); + for (var name in memberNames) { + JS('', '#[dartx.#] = #[#]', proto, name, proto, name); + } +} + +/// Like [defineExtensionMethods], but for getter/setter pairs. +defineExtensionAccessors(type, Iterable memberNames) { + var proto = JS('', '#.prototype', type); + for (var name in memberNames) { + // Find the member. It should always exist (or we have a compiler bug). + var member; + var p = proto; + for (;; p = JS('', '#.__proto__', p)) { + member = getOwnPropertyDescriptor(p, name); + if (member != null) break; + } + defineProperty(proto, JS('', 'dartx[#]', name), member); + } +} + +definePrimitiveHashCode(proto) { + defineProperty(proto, identityHashCode_, + getOwnPropertyDescriptor(proto, extensionSymbol('hashCode'))); +} + +/// Link the extension to the type it's extending as a base class. +setBaseClass(derived, base) { + JS('', '#.prototype.__proto__ = #.prototype', derived, base); + // We use __proto__ to track the superclass hierarchy (see isSubtype). + JS('', '#.__proto__ = #', derived, base); +} + +/// Like [setBaseClass], but for generic extension types such as `JSArray`. +setExtensionBaseClass(dartType, jsType) { + // Mark the generic type as an extension type and link the prototype objects. + var dartProto = JS('', '#.prototype', dartType); + JS('', '#[#] = #', dartProto, _extensionType, dartType); + JS('', '#.__proto__ = #.prototype', dartProto, jsType); +} + +/// Adds type test predicates to a class/interface type [ctor], using the +/// provided [isClass] JS Symbol. +/// +/// This will operate quickly for non-generic types, native extension types, +/// as well as matching exact generic type arguments: +/// +/// class C {} +/// class D extends C {} +/// main() { dynamic d = new D(); d as C; } +/// +addTypeTests(ctor, isClass) { + if (isClass == null) isClass = JS('', 'Symbol("_is_" + ctor.name)'); + // TODO(jmesserly): since we know we're dealing with class/interface types, + // we can optimize this rather than go through the generic `dart.is` helpers. + JS('', '#.prototype[#] = true', ctor, isClass); + JS( + '', + '''#.is = function is_C(obj) { + return obj != null && (obj[#] || #(obj, this)); + }''', + ctor, + isClass, + instanceOf); + JS( + '', + '''#.as = function as_C(obj) { + if (obj == null || obj[#]) return obj; + return #(obj, this, false); + }''', + ctor, + isClass, + cast); + JS( + '', + '''#._check = function check_C(obj) { + if (obj == null || obj[#]) return obj; + return #(obj, this, true); + }''', + ctor, + isClass, + cast); +} + +// TODO(jmesserly): should we do this for all interfaces? + +/// The well known symbol for testing `is Future` +final isFuture = JS('', 'Symbol("_is_Future")'); + +/// The well known symbol for testing `is Iterable` +final isIterable = JS('', 'Symbol("_is_Iterable")'); + +/// The well known symbol for testing `is List` +final isList = JS('', 'Symbol("_is_List")'); + +/// The well known symbol for testing `is Map` +final isMap = JS('', 'Symbol("_is_Map")'); + +/// The well known symbol for testing `is Stream` +final isStream = JS('', 'Symbol("_is_Stream")'); + +/// The well known symbol for testing `is StreamSubscription` +final isStreamSubscription = JS('', 'Symbol("_is_StreamSubscription")'); + +/// The default `operator ==` that calls [identical]. +var identityEquals; + +NN<H$5CQ(+/$)())+@,)! #3/@;197-2&&/3J/.J"'$D/1?.*L#4,6  I:F41=(I&5J6'B/6E+< F +9 +I?9EF=52022><>>:?5355A?AAFGI!1I7/;:H=B0D5O".1D:% 2G*"GHJF7% "$=MKMM=)28*3)2*3*3(6. $%<BBB@:PH>.* NL7FDFFMN%=6(G@F/BG';.(<5MK*;I6qfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dartB// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This library defines the association between runtime objects and +/// runtime types. +part of "runtime.dart"; + +/// Runtime type information. This module defines the mapping from +/// runtime objects to their runtime type information. See the types +/// module for the definition of how type information is represented. +/// +/// There are two kinds of objects that represent "types" at runtime. A +/// "runtime type" contains all of the data needed to implement the runtime +/// type checking inserted by the compiler. These objects fall into four +/// categories: +/// +/// - Things represented by javascript primitives, such as +/// null, numbers, booleans, strings, and symbols. For these +/// we map directly from the javascript type (given by typeof) +/// to the appropriate class type from core, which serves as their +/// rtti. +/// +/// - Functions, which are represented by javascript functions. +/// Representations of Dart functions always have a +/// _runtimeType property attached to them with the appropriate +/// rtti. +/// +/// - Objects (instances) which are represented by instances of +/// javascript (ES6) classes. Their types are given by their +/// classes, and the rtti is accessed by projecting out their +/// constructor field. +/// +/// - Types objects, which are represented as described in the types +/// module. Types always have a _runtimeType property attached to +/// them with the appropriate rtti. The rtti for these is always +/// core.Type. TODO(leafp): consider the possibility that we can +/// reliably recognize type objects and map directly to core.Type +/// rather than attaching this property everywhere. +/// +/// The other kind of object representing a "type" is the instances of the +/// dart:core Type class. These are the user visible objects you get by calling +/// "runtimeType" on an object or using a class literal expression. These are +/// different from the above objects, and are created by calling `wrapType()` +/// on a runtime type. + +/// Tag a closure with a type. +/// +/// `dart.fn(closure, type)` marks [closure] with the provided runtime [type]. +fn(closure, type) { + JS('', '#[#] = #', closure, _runtimeType, type); + return closure; +} + +/// Tag a closure with a type that's computed lazily. +/// +/// `dart.fn(closure, type)` marks [closure] with a getter that uses +/// [computeType] to return the runtime type. +/// +/// The getter/setter replaces the property with a value property, so the +/// resulting function is compatible with [fn] and the type can be set again +/// safely. +lazyFn(closure, Object Function() computeType) { + defineAccessor(closure, _runtimeType, + get: () => defineValue(closure, _runtimeType, computeType()), + set: (value) => defineValue(closure, _runtimeType, value), + configurable: true); + return closure; +} + +// TODO(vsm): How should we encode the runtime type? +final _runtimeType = JS('', 'Symbol("_runtimeType")'); + +final _moduleName = JS('', 'Symbol("_moduleName")'); + +getFunctionType(obj) { + // TODO(vsm): Encode this properly on the function for Dart-generated code. + var args = JS('!', 'Array(#.length).fill(#)', obj, dynamic); + return fnType(bottom, args, JS('', 'void 0')); +} + +/// Returns the runtime representation of the type of obj. +/// +/// The resulting object is used internally for runtime type checking. This is +/// different from the user-visible Type object returned by calling +/// `runtimeType` on some Dart object. +getReifiedType(obj) { + switch (JS('!', 'typeof #', obj)) { + case "object": + if (obj == null) return JS('', '#', Null); + if (JS('!', '# instanceof #', obj, Object)) { + return JS('', '#.constructor', obj); + } + var result = JS('', '#[#]', obj, _extensionType); + if (result == null) return JS('', '#', jsobject); + return result; + case "function": + // All Dart functions and callable classes must set _runtimeType + var result = JS('', '#[#]', obj, _runtimeType); + if (result != null) return result; + return JS('', '#', jsobject); + case "undefined": + return JS('', '#', Null); + case "number": + return JS('', 'Math.floor(#) == # ? # : #', obj, obj, int, double); + case "boolean": + return JS('', '#', bool); + case "string": + return JS('', '#', String); + case "symbol": + default: + return JS('', '#', jsobject); + } +} + +/// Given an internal runtime type object, wraps it in a `WrappedType` object +/// that implements the dart:core Type interface. +Type wrapType(type) { + // If we've already wrapped this type once, use the previous wrapper. This + // way, multiple references to the same type return an identical Type. + if (JS('!', '#.hasOwnProperty(#)', type, _typeObject)) { + return JS('', '#[#]', type, _typeObject); + } + return JS('Type', '#[#] = #', type, _typeObject, WrappedType(type)); +} + +/// The symbol used to store the cached `Type` object associated with a class. +final _typeObject = JS('', 'Symbol("typeObject")'); + +/// Given a WrappedType, return the internal runtime type object. +unwrapType(WrappedType obj) => obj._wrappedType; + +/// Return the module name for a raw library object. +getModuleName(value) => JS('', '#[#]', value, _moduleName); + +var _loadedModules = JS('', 'new Map()'); +var _loadedSourceMaps = JS('', 'new Map()'); + +List getModuleNames() { + return JS('', 'Array.from(#.keys())', _loadedModules); +} + +String getSourceMap(module) { + return JS('!', '#.get(#)', _loadedSourceMaps, module); +} + +/// Return all library objects in the specified module. +getModuleLibraries(String name) { + var module = JS('', '#.get(#)', _loadedModules, name); + if (module == null) return null; + JS('', '#[#] = #', module, _moduleName, name); + return module; +} + +/// Track all libraries +void trackLibraries(String moduleName, libraries, sourceMap) { + JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap); + JS('', '#.set(#, #)', _loadedModules, moduleName, libraries); +} +NN<EDFFHLI=BCGB8DBBBGGFFF8KPNNO36E.JM 1(DA575NE1;OD'.14-88G6)$ J " $N2MI;.GO4B15<*-9A8"9#1?C@sfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +part of "runtime.dart"; + +// We need to set these properties while the sdk is only partially initialized +// so we cannot use regular Dart fields. +// The default values for these properties are set when the global_ final field +// in runtime.dart is initialized. + +// Override, e.g., for testing +void trapRuntimeErrors(bool flag) { + JS('', 'dart.__trapRuntimeErrors = #', flag); +} + +void ignoreWhitelistedErrors(bool flag) { + JS('', 'dart.__ignoreWhitelistedErrors = #', flag); +} + +// TODO(jmesserly): remove this? +void ignoreAllErrors(bool flag) { + JS('', 'dart.__ignoreAllErrors = #', flag); +} + +argumentError(value) { + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + throw ArgumentError.value(value); +} + +throwUnimplementedError(String message) { + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + throw UnimplementedError(message); +} + +assertFailed(message) { + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + throw AssertionErrorImpl(message); +} + +throwCyclicInitializationError([Object field]) { + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + throw CyclicInitializationError(field); +} + +throwNullValueError() { + // TODO(vsm): Per spec, we should throw an NSM here. Technically, we ought + // to thread through method info, but that uglifies the code and can't + // actually be queried ... it only affects how the error is printed. + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + throw NoSuchMethodError( + null, Symbol(''), null, null, null); +} + +castError(obj, expectedType, [@notNull bool isImplicit = false]) { + var actualType = getReifiedType(obj); + var message = _castErrorMessage(actualType, expectedType); + if (JS('!', 'dart.__ignoreAllErrors')) { + JS('', 'console.error(#)', message); + return obj; + } + if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); + var error = isImplicit ? TypeErrorImpl(message) : CastErrorImpl(message); + throw error; +} + +String _castErrorMessage(from, to) { + // If both types are generic classes, see if we can infer generic type + // arguments for `from` that would allow the subtype relation to work. + var fromClass = getGenericClass(from); + if (fromClass != null) { + var fromTypeFormals = getGenericTypeFormals(fromClass); + var fromType = instantiateClass(fromClass, fromTypeFormals); + var inferrer = _TypeInferrer(fromTypeFormals); + if (inferrer.trySubtypeMatch(fromType, to)) { + var inferredTypes = inferrer.getInferredTypes(); + if (inferredTypes != null) { + var inferred = instantiateClass(fromClass, inferredTypes); + return "Type '${typeName(from)}' should be '${typeName(inferred)}' " + "to implement expected type '${typeName(to)}'."; + } + } + } + return "Type '${typeName(from)}' is not a subtype of " + "expected type '${typeName(to)}'."; +} +WNN<O)P#$0*6!".?$*?%?%1?*NIG?BC(=+)?L%II) "JsonMLConfig($name)"; +} + +int _maxSpanLength = 100; +var _devtoolsFormatter = JsonMLFormatter(DartFormatter()); + +/// We truncate a toString() longer than [maxStringLength]. +int maxFormatterStringLength = 100; + +String _typeof(object) => JS('String', 'typeof #', object); + +List getOwnPropertyNames(object) => + JSArray.of(dart.getOwnPropertyNames(object)); + +List getOwnPropertySymbols(object) => + JS('List', 'Object.getOwnPropertySymbols(#)', object); + +// TODO(jacobr): move this to dart:js and fully implement. +class JSNative { + // Name may be a String or a Symbol. + static getProperty(object, name) => JS('', '#[#]', object, name); + // Name may be a String or a Symbol. + static setProperty(object, name, value) => + JS('', '#[#]=#', object, name, value); +} + +void addMetadataChildren(object, Set ret) { + ret.add(NameValuePair( + name: "[[class]]", + value: dart.getReifiedType(object), + config: JsonMLConfig.asClass)); +} + +/// Add properties from a signature definition [sig] for [object]. +/// Walk the prototype chain if [walkProtypeChain] is set. +/// Tag types on function typed properties of [object] if [tagTypes] is set. +/// +void addPropertiesFromSignature( + sig, Set properties, object, bool walkPrototypeChain, + {tagTypes = false}) { + // Including these property names doesn't add any value and just clutters + // the debugger output. + // TODO(jacobr): consider adding runtimeType to this list. + var skippedNames = Set()..add('hashCode'); + var objectPrototype = JS('', 'Object.prototype'); + while (sig != null && !identical(sig, objectPrototype)) { + for (var symbol in getOwnPropertySymbols(sig)) { + var dartName = symbolName(symbol); + String dartXPrefix = 'dartx.'; + if (dartName.startsWith(dartXPrefix)) { + dartName = dartName.substring(dartXPrefix.length); + } + if (skippedNames.contains(dartName)) continue; + var value = safeGetProperty(object, symbol); + // Tag the function with its runtime type. + if (tagTypes && _typeof(value) == 'function') { + dart.fn(value, JS('', '#[#]', sig, symbol)); + } + properties.add(NameValuePair(name: dartName, value: value)); + } + + for (var name in getOwnPropertyNames(sig)) { + var value = safeGetProperty(object, name); + if (skippedNames.contains(name)) continue; + // Tag the function with its runtime type. + if (tagTypes && _typeof(value) == 'function') { + dart.fn(value, JS('', '#[#]', sig, name)); + } + properties.add(NameValuePair(name: name, value: value)); + } + + if (!walkPrototypeChain) break; + + sig = safeGetProperty(sig, '__proto__'); + } +} + +/// Sort properties sorting public names before private names. +List sortProperties(Iterable properties) { + var sortedProperties = properties.toList(); + + sortedProperties.sort((a, b) { + var aPrivate = a.name.startsWith('_'); + var bPrivate = b.name.startsWith('_'); + if (aPrivate != bPrivate) return aPrivate ? 1 : -1; + return a.name.compareTo(b.name); + }); + return sortedProperties; +} + +String getObjectTypeName(object) { + var reifiedType = dart.getReifiedType(object); + if (reifiedType == null) { + if (_typeof(object) == 'function') { + return '[[Raw JavaScript Function]]'; + } + return ''; + } + return getTypeName(reifiedType); +} + +String getTypeName(type) { + // TODO(jacobr): it would be nice if there was a way we could distinguish + // between a List created from Dart and an Array passed in from + // JavaScript. + return dart.typeName(type); +} + +String safePreview(object, config) { + try { + var preview = _devtoolsFormatter._simpleFormatter.preview(object, config); + if (preview != null) return preview; + return object.toString(); + } catch (e) { + return ' $e'; + } +} + +String symbolName(symbol) { + var name = symbol.toString(); + assert(name.startsWith('Symbol(')); + return name.substring('Symbol('.length, name.length - 1); +} + +bool hasMethod(object, String name) { + try { + return dart.hasMethod(object, name); + } catch (e) { + return false; + } +} + +/// [JsonMLFormatter] consumes [NameValuePair] objects and +class NameValuePair { + NameValuePair( + {this.name, + this.value, + this.config = JsonMLConfig.none, + this.hideName = false}); + + // Define equality and hashCode so that NameValuePair can be used + // in a Set to dedupe entries with duplicate names. + bool operator ==(other) { + if (other is! NameValuePair) return false; + if (this.hideName || other.hideName) return identical(this, other); + return other.name == name; + } + + int get hashCode => name.hashCode; + + final String name; + final Object value; + final JsonMLConfig config; + final bool hideName; + + String get displayName => hideName ? '' : name; +} + +class MapEntry { + MapEntry({this.key, this.value}); + + final Object key; + final Object value; +} + +class IterableSpan { + IterableSpan(this.start, this.end, this.iterable); + + final int start; + final int end; + final Iterable iterable; + int get length => end - start; + + /// Using length - .5, a list of length 10000 results in a + /// maxPowerOfSubsetSize of 1, so the list will be broken up into 100, + /// 100-length subsets. A list of length 10001 results in a + /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1 + /// 10000-length subset and 1 1-length subset. + int get maxPowerOfSubsetSize => + (log(length - .5) / log(_maxSpanLength)).truncate(); + int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize); + + Map asMap() => + iterable.skip(start).take(length).toList().asMap(); + + List children() { + var children = []; + if (length <= _maxSpanLength) { + asMap().forEach((i, element) { + children + .add(NameValuePair(name: (i + start).toString(), value: element)); + }); + } else { + for (var i = start; i < end; i += subsetSize) { + var subSpan = IterableSpan(i, min(end, subsetSize + i), iterable); + if (subSpan.length == 1) { + children.add( + NameValuePair(name: i.toString(), value: iterable.elementAt(i))); + } else { + children.add(NameValuePair( + name: '[${i}...${subSpan.end - 1}]', + value: subSpan, + hideName: true)); + } + } + } + return children; + } +} + +class Library { + Library(this.name, this.object); + + final String name; + final Object object; +} + +class NamedConstructor { + NamedConstructor(this.object); + + final Object object; +} + +class HeritageClause { + HeritageClause(this.name, this.types); + + final String name; + final List types; +} + +Object safeGetProperty(Object protoChain, Object name) { + try { + return JSNative.getProperty(protoChain, name); + } catch (e) { + return ' $e'; + } +} + +safeProperties(object) => Map.fromIterable( + getOwnPropertyNames(object) + .where((each) => safeGetProperty(object, each) != null), + key: (name) => name, + value: (name) => safeGetProperty(object, name)); + +/// Class to simplify building the JsonML objects expected by the +/// Devtools Formatter API. +class JsonMLElement { + dynamic _attributes; + List _jsonML; + + JsonMLElement(tagName) { + _attributes = JS('', '{}'); + _jsonML = [tagName, _attributes]; + } + + appendChild(element) { + _jsonML.add(element.toJsonML()); + } + + JsonMLElement createChild(String tagName) { + var c = JsonMLElement(tagName); + _jsonML.add(c.toJsonML()); + return c; + } + + JsonMLElement createObjectTag(object) => + createChild('object')..addAttribute('object', object); + + void setStyle(String style) { + _attributes.style = style; + } + + addStyle(String style) { + if (_attributes.style == null) { + _attributes.style = style; + } else { + _attributes.style += style; + } + } + + addAttribute(key, value) { + JSNative.setProperty(_attributes, key, value); + } + + createTextChild(String text) { + _jsonML.add(text); + } + + toJsonML() => _jsonML; +} + +/// Whether an object is a native JavaScript type where we should display the +/// JavaScript view of the object instead of the custom Dart specific render +/// of properties. +bool isNativeJavaScriptObject(object) { + var type = _typeof(object); + if (type != 'object' && type != 'function') return true; + + // Consider all regular JS objects that do not represent Dart modules native + // JavaScript objects. + if (dart.isJsInterop(object) && dart.getModuleName(object) == null) { + return true; + } + + // Treat Node objects as a native JavaScript type as the regular DOM render + // in devtools is superior to the dart specific view. + return object is html.Node; +} + +/// Class implementing the Devtools Formatter API described by: +/// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335T3U +/// Specifically, a formatter implements a header, hasBody, and body method. +/// This class renders the simple structured format objects [_simpleFormatter] +/// provides as JsonML. +class JsonMLFormatter { + // TODO(jacobr): define a SimpleFormatter base class that DartFormatter + // implements if we decide to use this class elsewhere. We specify that the + // type is DartFormatter here purely to get type checking benefits not because + // this class is really intended to only support instances of type + // DartFormatter. + DartFormatter _simpleFormatter; + + bool customFormattersOn = false; + + JsonMLFormatter(this._simpleFormatter); + + void setMaxSpanLengthForTestingOnly(int spanLength) { + _maxSpanLength = spanLength; + } + + header(object, config) { + customFormattersOn = true; + if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) { + return null; + } + var c = _simpleFormatter.preview(object, config); + if (c == null) return null; + + if (config == JsonMLConfig.keyToString) { + c = object.toString(); + } + + // Indicate this is a Dart Object by using a Dart background color. + // This is stylistically a bit ugly but it eases distinguishing Dart and + // JS objects. + var element = JsonMLElement('span') + ..setStyle('background-color: #d9edf7;color: black') + ..createTextChild(c); + return element.toJsonML(); + } + + bool hasBody(object, config) => _simpleFormatter.hasChildren(object, config); + + body(object, config) { + var body = JsonMLElement('ol') + ..setStyle('list-style-type: none;' + 'padding-left: 0px;' + 'margin-top: 0px;' + 'margin-bottom: 0px;' + 'margin-left: 12px;'); + if (object is StackTrace) { + body.addStyle('background-color: thistle;color: rgb(196, 26, 22);'); + } + var children = _simpleFormatter.children(object, config); + if (children == null) return body.toJsonML(); + for (NameValuePair child in children) { + var li = body.createChild('li'); + li.setStyle("padding-left: 13px;"); + + // The value is indented when it is on a different line from the name + // by setting right padding of the name to -13px and the padding of the + // value to 13px. + JsonMLElement nameSpan; + var valueStyle = ''; + if (!child.hideName) { + nameSpan = JsonMLElement('span') + ..createTextChild( + child.displayName.isNotEmpty ? '${child.displayName}: ' : '') + ..setStyle( + 'background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px'); + valueStyle = 'margin-left: 13px'; + } + + if (_typeof(child.value) == 'object' || + _typeof(child.value) == 'function') { + var valueSpan = JsonMLElement('span')..setStyle(valueStyle); + valueSpan.createObjectTag(child.value) + ..addAttribute('config', child.config); + if (nameSpan != null) { + li.appendChild(nameSpan); + } + li.appendChild(valueSpan); + } else { + var line = li.createChild('span'); + if (nameSpan != null) { + line.appendChild(nameSpan); + } + line.appendChild(JsonMLElement('span') + ..createTextChild(safePreview(child.value, child.config)) + ..setStyle(valueStyle)); + } + } + return body.toJsonML(); + } +} + +abstract class Formatter { + bool accept(object, config); + String preview(object); + bool hasChildren(object); + List children(object); +} + +class DartFormatter { + List _formatters; + + DartFormatter() { + // The order of formatters matters as formatters earlier in the list take + // precedence. + _formatters = [ + ObjectInternalsFormatter(), + ClassFormatter(), + TypeFormatter(), + NamedConstructorFormatter(), + MapFormatter(), + IterableFormatter(), + IterableSpanFormatter(), + MapEntryFormatter(), + StackTraceFormatter(), + FunctionFormatter(), + HeritageClauseFormatter(), + LibraryModuleFormatter(), + LibraryFormatter(), + ObjectFormatter(), + ]; + } + + String preview(object, config) { + try { + if (object == null || + object is num || + object is String || + isNativeJavaScriptObject(object)) { + return object.toString(); + } + for (var formatter in _formatters) { + if (formatter.accept(object, config)) return formatter.preview(object); + } + } catch (e, trace) { + // Log formatter internal errors as unfortunately the devtools cannot + // be used to debug formatter errors. + html.window.console.error("Caught exception $e\n trace:\n$trace"); + } + + return null; + } + + bool hasChildren(object, config) { + if (object == null) return false; + try { + for (var formatter in _formatters) { + if (formatter.accept(object, config)) + return formatter.hasChildren(object); + } + } catch (e, trace) { + // See comment for preview. + html.window.console + .error("[hasChildren] Caught exception $e\n trace:\n$trace"); + } + return false; + } + + List children(object, config) { + try { + if (object != null) { + for (var formatter in _formatters) { + if (formatter.accept(object, config)) + return formatter.children(object); + } + } + } catch (e, trace) { + // See comment for preview. + html.window.console.error("Caught exception $e\n trace:\n$trace"); + } + return []; + } +} + +/// Default formatter for Dart Objects. +class ObjectFormatter extends Formatter { + bool accept(object, config) => !isNativeJavaScriptObject(object); + + String preview(object) { + var typeName = getObjectTypeName(object); + try { + // An explicit toString() call might not actually be a string. This way + // we're sure. + var toString = "$object"; + if (toString.length > maxFormatterStringLength) { + toString = toString.substring(0, maxFormatterStringLength - 3) + "..."; + } + // The default toString() will be "Instance of 'Foo'", in which case we + // don't need any further indication of the class. + if (toString.contains(typeName)) { + return toString; + } else { + // If there's no class indication, e.g. an Int64 that just prints as a + // number, then add the class name. + return "$toString ($typeName)"; + } + } catch (e) {} + // We will only get here if there was an error getting the toString, in + // which case we just use the type name. + return typeName; + } + + bool hasChildren(object) => true; + + List children(object) { + var type = dart.getType(object); + var ret = LinkedHashSet(); + // We use a Set rather than a List to avoid duplicates. + var fields = Set(); + addPropertiesFromSignature(dart.getFields(type), fields, object, true); + var getters = Set(); + addPropertiesFromSignature(dart.getGetters(type), getters, object, true); + ret.addAll(sortProperties(fields)); + ret.addAll(sortProperties(getters)); + addMetadataChildren(object, ret); + return ret.toList(); + } +} + +/// Show the object instance members and a reduced preview. +/// +/// Used as a sub-entry to show the internals of objects that have a different +/// primary format. For example, a Map shows the key-value pairs, but this makes +/// the internals of the map visible for debugging. +class ObjectInternalsFormatter extends ObjectFormatter { + bool accept(object, config) => + super.accept(object, config) && config == JsonMLConfig.asObject; + + // A minimal preview because we expect a full preview is already shown in a + // parent formatter. + String preview(object) { + return getObjectTypeName(object); + } +} + +/// Formatter for module Dart Library objects. +class LibraryModuleFormatter implements Formatter { + accept(object, config) => dart.getModuleName(object) != null; + + bool hasChildren(object) => true; + + String preview(object) { + var libraryNames = dart.getModuleName(object).split('/'); + // Library names are received with a repeat directory name, so strip the + // last directory entry here to make the path cleaner. For example, the + // library "third_party/dart/utf/utf" shoud display as + // "third_party/dart/utf/". + if (libraryNames.length > 1 && + libraryNames.last == libraryNames[libraryNames.length - 2]) { + libraryNames[libraryNames.length - 1] = ''; + } + return 'Library Module: ${libraryNames.join('/')}'; + } + + List children(object) { + var children = LinkedHashSet(); + for (var name in getOwnPropertyNames(object)) { + var value = safeGetProperty(object, name); + children.add(NameValuePair( + name: name, value: Library(name, value), hideName: true)); + } + return children.toList(); + } +} + +class LibraryFormatter implements Formatter { + var genericParameters = HashMap(); + + accept(object, config) => object is Library; + + bool hasChildren(object) => true; + + String preview(object) => object.name; + + List children(object) { + // Maintain library member order rather than sorting members as is the + // case for class members. + var children = LinkedHashSet(); + var objectProperties = safeProperties(object.object); + objectProperties.forEach((name, value) { + // Skip the generic constructors for each class as users are only + // interested in seeing the actual classes. + if (dart.getGenericTypeCtor(value) != null) return; + + children.add(dart.isType(value) + ? classChild(name, value) + : NameValuePair(name: name, value: value)); + }); + return children.toList(); + } + + classChild(String name, Object child) { + var typeName = getTypeName(child); + return NameValuePair( + name: typeName, value: child, config: JsonMLConfig.asClass); + } +} + +/// Formatter for Dart Function objects. +/// Dart functions happen to be regular JavaScript Function objects but +/// we can distinguish them based on whether they have been tagged with +/// runtime type information. +class FunctionFormatter implements Formatter { + accept(object, config) { + if (_typeof(object) != 'function') return false; + return dart.getReifiedType(object) != null; + } + + bool hasChildren(object) => true; + + String preview(object) { + return dart.typeName(dart.getReifiedType(object)); + } + + List children(object) => [ + NameValuePair(name: 'signature', value: preview(object)), + NameValuePair( + name: 'JavaScript Function', + value: object, + config: JsonMLConfig.skipDart) + ]; +} + +/// Formatter for Dart Map objects. +class MapFormatter implements Formatter { + accept(object, config) => object is Map; + + bool hasChildren(object) => true; + + String preview(object) { + Map map = object; + return '${getObjectTypeName(map)} length ${map.length}'; + } + + List children(object) { + // TODO(jacobr): be lazier about enumerating contents of Maps that are not + // the build in LinkedHashMap class. + // TODO(jacobr): handle large Maps better. + Map map = object; + var entries = LinkedHashSet(); + map.forEach((key, value) { + var entryWrapper = MapEntry(key: key, value: value); + entries.add( + NameValuePair(name: entries.length.toString(), value: entryWrapper)); + }); + addInstanceMembers(object, entries); + addMetadataChildren(object, entries); + return entries.toList(); + } + + // We've formatted as a Map, but we may want to see the internals + // of the Map, particularly for domain objects that implement Map. + // Add an ObjectFormatter view underneath. + void addInstanceMembers(object, Set ret) { + ret.add(NameValuePair( + name: "[[instance members]]", + value: object, + config: JsonMLConfig.asObject)); + } +} + +/// Formatter for Dart Iterable objects including List and Set. +class IterableFormatter implements Formatter { + bool accept(object, config) => object is Iterable; + + String preview(object) { + Iterable iterable = object; + try { + var length = iterable.length; + return '${getObjectTypeName(iterable)} length $length'; + } catch (_) { + return '${getObjectTypeName(iterable)}'; + } + } + + bool hasChildren(object) => true; + + List children(object) { + // TODO(jacobr): be lazier about enumerating contents of Iterables that + // are not the built in Set or List types. + // TODO(jacobr): handle large Iterables better. + // TODO(jacobr): consider only using numeric indices + var children = LinkedHashSet(); + children.addAll(IterableSpan(0, object.length, object).children()); + // TODO(jacobr): provide a link to show regular class properties here. + // required for subclasses of iterable, etc. + addMetadataChildren(object, children); + return children.toList(); + } +} + +class NamedConstructorFormatter implements Formatter { + accept(object, config) => object is NamedConstructor; + + // TODO(bmilligan): Display the signature of the named constructor as the + // preview. + String preview(object) => 'Named Constructor'; + + bool hasChildren(object) => true; + + List children(object) => [ + NameValuePair( + name: 'JavaScript Function', + value: object, + config: JsonMLConfig.skipDart) + ]; +} + +/// Formatter for synthetic MapEntry objects used to display contents of a Map +/// cleanly. +class MapEntryFormatter implements Formatter { + accept(object, config) => object is MapEntry; + + String preview(object) { + MapEntry entry = object; + return '${safePreview(entry.key, JsonMLConfig.none)} => ${safePreview(entry.value, JsonMLConfig.none)}'; + } + + bool hasChildren(object) => true; + + List children(object) => [ + NameValuePair( + name: 'key', value: object.key, config: JsonMLConfig.keyToString), + NameValuePair(name: 'value', value: object.value) + ]; +} + +/// Formatter for Dart Iterable objects including List and Set. +class HeritageClauseFormatter implements Formatter { + bool accept(object, config) => object is HeritageClause; + + String preview(object) { + HeritageClause clause = object; + var typeNames = clause.types.map(getTypeName); + return '${clause.name} ${typeNames.join(", ")}'; + } + + bool hasChildren(object) => true; + + List children(object) { + HeritageClause clause = object; + var children = []; + for (var type in clause.types) { + children.add(NameValuePair(value: type, config: JsonMLConfig.asClass)); + } + return children; + } +} + +/// Formatter for synthetic IterableSpan objects used to display contents of +/// an Iterable cleanly. +class IterableSpanFormatter implements Formatter { + accept(object, config) => object is IterableSpan; + + String preview(object) { + return '[${object.start}...${object.end-1}]'; + } + + bool hasChildren(object) => true; + + List children(object) => object.children(); +} + +class StackTraceFormatter implements Formatter { + accept(object, config) => object is StackTrace; + + String preview(object) => 'StackTrace'; + + bool hasChildren(object) => true; + + // Using the stack_trace formatting would be ideal, but adding the + // dependency or re-writing the code is too messy, so each line of the + // StackTrace will be added as its own child. + List children(object) => object + .toString() + .split('\n') + .map((line) => NameValuePair( + value: line.replaceFirst(RegExp(r'^\s+at\s'), ''), hideName: true)) + .toList(); +} + +class ClassFormatter implements Formatter { + accept(object, config) => config == JsonMLConfig.asClass; + + String preview(type) { + var implements = dart.getImplements(type); + var typeName = getTypeName(type); + if (implements != null) { + var typeNames = implements().map(getTypeName); + return '${typeName} implements ${typeNames.join(", ")}'; + } else { + return typeName; + } + } + + bool hasChildren(object) => true; + + List children(type) { + // TODO(jacobr): add other entries describing the class such as + // implemented interfaces, and methods. + var ret = LinkedHashSet(); + + var staticProperties = Set(); + var staticMethods = Set(); + // Static fields and properties. + addPropertiesFromSignature( + dart.getStaticFields(type), staticProperties, type, false); + addPropertiesFromSignature( + dart.getStaticGetters(type), staticProperties, type, false); + // static methods. + addPropertiesFromSignature( + dart.getStaticMethods(type), staticMethods, type, false); + + if (staticProperties.isNotEmpty || staticMethods.isNotEmpty) { + ret + ..add(NameValuePair(value: '[[Static members]]', hideName: true)) + ..addAll(sortProperties(staticProperties)) + ..addAll(sortProperties(staticMethods)); + } + + // instance methods. + var instanceMethods = Set(); + // Instance methods are defined on the prototype not the constructor object. + addPropertiesFromSignature(dart.getMethods(type), instanceMethods, + JS('', '#.prototype', type), false, + tagTypes: true); + if (instanceMethods.isNotEmpty) { + ret + ..add(NameValuePair(value: '[[Instance Methods]]', hideName: true)) + ..addAll(sortProperties(instanceMethods)); + } + + var mixin = dart.getMixin(type); + if (mixin != null) { + // TODO(jmesserly): this can only be one value. + ret.add(NameValuePair( + name: '[[Mixins]]', value: HeritageClause('mixins', [mixin]))); + } + + var baseProto = JS('', '#.__proto__', type); + if (baseProto != null && !dart.isJsInterop(baseProto)) { + ret.add(NameValuePair( + name: "[[base class]]", + value: baseProto, + config: JsonMLConfig.asClass)); + } + + // TODO(jacobr): add back fields for named constructors. + return ret.toList(); + } +} + +class TypeFormatter implements Formatter { + accept(object, config) => object is Type; + + String preview(object) => object.toString(); + + bool hasChildren(object) => false; + + List children(object) => []; +} + +typedef String StackTraceMapper(String stackTrace); + +/// Hook for other parts of the SDK To use to map JS stack traces to Dart +/// stack traces. +/// +/// Raw JS stack traces are used if $dartStackTraceUtility has not been +/// specified. +StackTraceMapper get stackTraceMapper { + var _util = JS('', r'#.$dartStackTraceUtility', dart.global_); + return _util != null ? JS('!', '#.mapper', _util) : null; +} + +/// This entry point is automatically invoked by the code generated by +/// Dart Dev Compiler +registerDevtoolsFormatter() { + JS('', '#.devtoolsFormatters = [#]', dart.global_, _devtoolsFormatter); +} + +// Expose these methods here to facilitate writing debugger tests. +// If export worked for private SDK libraries we could just export +// these methods from dart:_runtime. + +getModuleNames() { + return dart.getModuleNames(); +} + +getModuleLibraries(String name) { + return dart.getModuleLibraries(name); +} +NN<'* LJBLONJP!,4:24';<$<,:&;;'D'--;*&C;M!IL=-4<5)%.;53165C111163?$-?I.!++8%#1),(#LK%O)$ &<&);'D6/H%2$5!=I>F1";C:#&$%O + 6K#P&3 +#!)93$, A5B &%.$+= %! "3!NM(;OHN8@TMOJNQE"#*8!O6 .HM(;P#* ! K>2,'*LN)L[*.0E/2 $ +#+ & +/D#(N"#! # +."+PL,I%& ++.0"H1 +-0/ +"I(*D. +N 8PN9)O,(L-$)%.<'L(N()&<OQ49!GN&/4@$>ML; #F28)341"E.5/$))K3:-H2:&$6*'E)HH/50$7;B)+ $*+$=)O)/2;P)*DE-<&)@/5 +$>/$)L/493HK1+78L1$;)+ O /0m$;O: @5;$35$)$&%NM342$=12*$EI01$N,</&5? $'D,.1.% D E BC +J310QG,& +L3%6J1="*=+,/%.4JH(A<GJCC% "(hfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/profile.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. 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 supports profiling dynamic calls. +part of dart._debugger; + +class _MethodStats { + final String typeName; + final String frame; + double count; + + _MethodStats(this.typeName, this.frame) { + count = 0.0; + } +} + +class _CallMethodRecord { + var jsError; + var type; + + _CallMethodRecord(this.jsError, this.type); +} + +/// Size for the random sample of dynamic calls. +int _callRecordSampleSize = 5000; + +/// If the number of dynamic calls exceeds [_callRecordSampleSize] this list +/// will represent a random sample of the dynamic calls made. +List<_CallMethodRecord> _callMethodRecords = List(); + +/// If the number of dynamic calls exceeds [_callRecordSampleSize] this value +/// will be greater than [_callMethodRecords.length]. +int _totalCallRecords = 0; + +/// Minimum number of samples to consider a profile entry relevant. +/// This could be set a lot higher. We set this value so users are not +/// confused into thinking that a dynamic call that occurred once but was +/// randomly included in the sample is relevant. +num _minCount = 2; + +/// Cache mapping from raw stack frames to source mapped stack frames to +/// speedup lookup of source map frames when running the profiler. +/// The number of source map entries looked up makes caching more important +/// in this case than for typical source map use cases. +Map _frameMappingCache = Map(); + +List> getDynamicStats() { + // Process the accumulated method stats. This may be quite slow as processing + // stack traces is expensive. If there are performance blockers, we should + // switch to a sampling approach that caps the number of _callMethodRecords + // and uses random sampling to decide whether to add each additional record + // to the sample. Main change required is that we need to still show the total + // raw number of dynamic calls so that the magnitude of the dynamic call + // performance hit is clear to users. + + Map callMethodStats = Map(); + if (_callMethodRecords.length > 0) { + // Ratio between total record count and sampled records count. + var recordRatio = _totalCallRecords / _callMethodRecords.length; + for (var record in _callMethodRecords) { + String stackStr = JS('!', '#.stack', record.jsError); + var frames = stackStr.split('\n'); + // Skip first two lines as the first couple frames are from the dart + // runtime. + var src = frames + .skip(2) + .map((f) => + _frameMappingCache.putIfAbsent(f, () => stackTraceMapper('\n$f'))) + .firstWhere((f) => !f.startsWith('dart:'), orElse: () => ''); + + var actualTypeName = dart.typeName(record.type); + callMethodStats + .putIfAbsent( + "$actualTypeName <$src>", () => _MethodStats(actualTypeName, src)) + .count += recordRatio; + } + + // filter out all calls that did not occur at least _minCount times in the + // random sample if we are dealing with a random sample instead of a + // complete profile. + if (_totalCallRecords != _callMethodRecords.length) { + for (var k in callMethodStats.keys.toList()) { + var stats = callMethodStats[k]; + var threshold = _minCount * recordRatio; + if (stats.count + 0.001 < threshold) { + callMethodStats.remove(k); + } + } + } + } + _callMethodRecords.clear(); + _totalCallRecords = 0; + var keys = callMethodStats.keys.toList(); + + keys.sort( + (a, b) => callMethodStats[b].count.compareTo(callMethodStats[a].count)); + List> ret = []; + for (var key in keys) { + var stats = callMethodStats[key]; + ret.add([stats.typeName, stats.frame, stats.count.round()]); + } + return ret; +} + +clearDynamicStats() { + _callMethodRecords.clear(); +} + +// We need to set this property while the sdk is only partially initialized +// so we cannot use a regular Dart field. +bool get _trackProfile => JS('bool', 'dart.__trackProfile'); + +trackCall(obj) { + if (JS('bool', '!#', _trackProfile)) return; + int index = -1; + _totalCallRecords++; + if (_callMethodRecords.length == _callRecordSampleSize) { + // Ensure that each sample has an equal + // _callRecordSampleSize / _totalCallRecords chance of inclusion + // by choosing to include the new record in the sample the with the + // appropriate probability randomly evicting one of the existing records. + // Unfortunately we can't use the excellent Random.nextInt method defined + // by Dart from within this library. + index = JS('int', 'Math.floor(Math.random() * #)', _totalCallRecords); + if (index >= _callMethodRecords.length) return; // don't sample + } + var record = + _CallMethodRecord(JS('', 'new Error()'), dart.getReifiedType(obj)); + if (index == -1) { + _callMethodRecords.add(record); + } else { + _callMethodRecords[index] = record; + } +} +NN<0, .1"M>5N6DGJ1ICL80'PMNNQK(5'CE-D)KQH7Q!OI:5(1/% +, O&AL*=/<,EHNN)KDJ$ (ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/foreign_helper.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart._foreign_helper; + +/** + * Emits a JavaScript code fragment parameterized by arguments. + * + * Hash characters `#` in the [codeTemplate] are replaced in left-to-right order + * with expressions that contain the values of, or evaluate to, the arguments. + * The number of hash marks must match the number or arguments. Although + * declared with arguments [arg0] through [arg2], the form actually has no limit + * on the number of arguments. + * + * The [typeDescription] argument is interpreted as a description of the + * behavior of the JavaScript code. Currently it describes the types that may + * be returned by the expression, with the additional behavior that the returned + * values may be fresh instances of the types. The type information must be + * correct as it is trusted by the compiler in optimizations, and it must be + * precise as possible since it is used for native live type analysis to + * tree-shake large parts of the DOM libraries. If poorly written, the + * [typeDescription] will cause unnecessarily bloated programs. (You can check + * for this by compiling with `--verbose`; there is an info message describing + * the number of native (DOM) types that can be removed, which usually should be + * greater than zero.) + * + * The [typeDescription] is a [String] which contains a union of types separated + * by vertical bar `|` symbols, e.g. `"num|String"` describes the union of + * numbers and Strings. There is no type in Dart that is this precise. The + * Dart alternative would be `Object` or `dynamic`, but these types imply that + * the JS-code might also be creating instances of all the DOM types. If `null` + * is possible, it must be specified explicitly, e.g. `"String|Null"`. + * [typeDescription] has several extensions to help describe the behavior more + * accurately. In addition to the union type already described: + * + * + `=Object` is a plain JavaScript object. Some DOM methods return instances + * that have no corresponding Dart type (e.g. cross-frame documents), + * `=Object` can be used to describe these untyped' values. + * + * + `var` (or empty string). If the entire [typeDescription] is `var` (or + * empty string) then the type is `dynamic` but the code is known to not + * create any instances. + * + * Examples: + * + * // Parent window might be an opaque cross-frame window. + * var thing = JS('=Object|Window', '#.parent', myWindow); + * + * Guidelines: + * + * + Do not use any parameter, local, method or field names in the + * [codeTemplate]. These names are all subject to arbitrary renaming by the + * compiler. Pass the values in via `#` substition, and test with the + * `--minify` dart2js command-line option. + * + * + The substituted expressions are values, not locations. + * + * JS('void', '# += "x"', this.field); + * + * `this.field` might not be a substituted as a reference to the field. The + * generated code might accidentally work as intended, but it also might be + * + * var t1 = this.field; + * t1 += "x"; + * + * or + * + * this.get$field() += "x"; + * + * The remedy in this case is to expand the `+=` operator, leaving all + * references to the Dart field as Dart code: + * + * this.field = JS('String', '# + "x"', this.field); + * + * + Never use `#` in function bodies. + * + * This is a variation on the previous guideline. Since `#` is replaced with + * an *expression* and the expression is only valid in the immediate context, + * `#` should never appear in a function body. Doing so might defer the + * evaluation of the expression, and its side effects, until the function is + * called. + * + * For example, + * + * var value = foo(); + * var f = JS('', 'function(){return #}', value) + * + * might result in no immediate call to `foo` and a call to `foo` on every + * call to the JavaScript function bound to `f`. This is better: + * + * var f = JS('', + * '(function(val) { return function(){return val}; })(#)', value); + * + * Since `#` occurs in the immediately evaluated expression, the expression + * is immediately evaluated and bound to `val` in the immediate call. + * + * + * Additional notes. + * + * In the future we may extend [typeDescription] to include other aspects of the + * behavior, for example, separating the returned types from the instantiated + * types, or including effects to allow the compiler to perform more + * optimizations around the code. This might be an extension of [JS] or a new + * function similar to [JS] with additional arguments for the new information. + */ +// Add additional optional arguments if needed. The method is treated internally +// as a variable argument method. +T JS(String typeDescription, String codeTemplate, + [arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19]) {} + +/// Annotates the compiled Js name for fields and methods. +/// Similar behaviour to `JS` from `package:js/js.dart` (but usable from runtime +/// files), and not to be confused with `JSName` from `js_helper` (which deals +/// with names of externs). +class JSExportName { + final String name; + const JSExportName(this.name); +} + +/** + * Returns the JavaScript constructor function for Dart's Object class. + * This can be used for type tests, as in + * + * if (JS('bool', '# instanceof #', obj, JS_DART_OBJECT_CONSTRUCTOR())) + * ... + */ +JS_DART_OBJECT_CONSTRUCTOR() {} + +/** + * Returns the interceptor for class [type]. The interceptor is the type's + * constructor's `prototype` property. [type] will typically be the class, not + * an interface, e.g. `JS_INTERCEPTOR_CONSTANT(JSInt)`, not + * `JS_INTERCEPTOR_CONSTANT(int)`. + */ +JS_INTERCEPTOR_CONSTANT(Type type) {} + +/** + * Returns the prefix used for generated is checks on classes. + */ +String JS_OPERATOR_IS_PREFIX() {} + +/** + * Returns the prefix used for generated type argument substitutions on classes. + */ +String JS_OPERATOR_AS_PREFIX() {} + +/// Returns the name of the class `Object` in the generated code. +String JS_OBJECT_CLASS_NAME() {} + +/// Returns the name of the class `Null` in the generated code. +String JS_NULL_CLASS_NAME() {} + +/// Returns the name of the class `Function` in the generated code. +String JS_FUNCTION_CLASS_NAME() {} + +/** + * Returns the field name used for determining if an object or its + * interceptor has JavaScript indexing behavior. + */ +String JS_IS_INDEXABLE_FIELD_NAME() {} + +/// Returns the name used for generated function types on classes and methods. +String JS_SIGNATURE_NAME() {} + +/// Returns the name used to tag typedefs. +String JS_TYPEDEF_TAG() {} + +/// Returns the name used to tag function type representations in JavaScript. +String JS_FUNCTION_TYPE_TAG() {} + +/** + * Returns the name used to tag void return in function type representations + * in JavaScript. + */ +String JS_FUNCTION_TYPE_VOID_RETURN_TAG() {} + +/** + * Returns the name used to tag return types in function type representations + * in JavaScript. + */ +String JS_FUNCTION_TYPE_RETURN_TYPE_TAG() {} + +/** + * Returns the name used to tag required parameters in function type + * representations in JavaScript. + */ +String JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG() {} + +/** + * Returns the name used to tag optional parameters in function type + * representations in JavaScript. + */ +String JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG() {} + +/** + * Returns the name used to tag named parameters in function type + * representations in JavaScript. + */ +String JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG() {} + +/// Returns the JS name for [name] from the Namer. +String JS_GET_NAME(String name) {} + +/// Returns the state of a flag that is determined by the state of the compiler +/// when the program has been analyzed. +bool JS_GET_FLAG(String name) {} + +/** + * Pretend [code] is executed. Generates no executable code. This is used to + * model effects at some other point in external code. For example, the + * following models an assignment to foo with an unknown value. + * + * var foo; + * + * main() { + * JS_EFFECT((_){ foo = _; }) + * } + * + * TODO(sra): Replace this hack with something to mark the volatile or + * externally initialized elements. + */ +void JS_EFFECT(Function code) { + code(null); +} + +/** + * Use this class for creating constants that hold JavaScript code. + * For example: + * + * const constant = JS_CONST('typeof window != "undefined"); + * + * This code will generate: + * $.JS_CONST_1 = typeof window != "undefined"; + */ +class JS_CONST { + final String code; + const JS_CONST(this.code); +} + +/** + * JavaScript string concatenation. Inputs must be Strings. Corresponds to the + * HStringConcat SSA instruction and may be constant-folded. + */ +String JS_STRING_CONCAT(String a, String b) { + // This body is unused, only here for type analysis. + return JS('String', '# + #', a, b); +} + +/// Same `@rest` annotation and `spread` function as in +/// `package:js/src/varargs.dart`. +/// +/// Runtime files cannot import packages, which is why we have an ad-hoc copy. + +class _Rest { + const _Rest(); +} + +const _Rest rest = _Rest(); + +dynamic spread(args) { + throw StateError('The spread function cannot be called, ' + 'it should be compiled away.'); +} +NN<@QOJQIOQMMIHPOQQLMOQGOAQJ@ML ??DPJ.=.PO #J1<(QQLP8NEOOIQNEOOQ"5 + + + + + + + + + ;QO!H*L  LP<#&?"Q"B!@D#C1'O+N!M-N-E"5E"5B"23#P(!OI@$ G$ D=0P=.7&8#O<&mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart._interceptors; + +import 'dart:collection'; +import 'dart:_internal' hide Symbol; +import 'dart:_js_helper'; +import 'dart:_foreign_helper' show JS, JSExportName; +import 'dart:math' show Random; +import 'dart:_runtime' as dart; + +part 'js_array.dart'; +part 'js_number.dart'; +part 'js_string.dart'; + +// TODO(jmesserly): remove, this doesn't do anything for us. +abstract class Interceptor { + const Interceptor(); + + // Use native JS toString method instead of standard Dart Object.toString. + String toString() => JS('String', '#.toString()', this); +} + +// TODO(jmesserly): remove +getInterceptor(obj) => obj; + +/** + * The interceptor class for [bool]. + */ +@JsPeerInterface(name: 'Boolean') +class JSBool extends Interceptor implements bool { + const JSBool(); + + // Note: if you change this, also change the function [S]. + @notNull + String toString() => JS('String', r'String(#)', this); + + // The values here are SMIs, co-prime and differ about half of the bit + // positions, including the low bit, so they are different mod 2^k. + @notNull + int get hashCode => this ? (2 * 3 * 23 * 3761) : (269 * 811); + + Type get runtimeType => bool; +} + +/** + * The supertype for JSString and JSArray. Used by the backend as to + * have a type mask that contains the objects that we can use the + * native JS [] operator and length on. + */ +abstract class JSIndexable { + int get length; + E operator [](int index); +} + +/** + * The interface implemented by JavaScript objects. These are methods in + * addition to the regular Dart Object methods like [Object.hashCode]. + * + * This is the type that should be exported by a JavaScript interop library. + */ +abstract class JSObject {} + +/** + * Interceptor base class for JavaScript objects not recognized as some more + * specific native type. + */ +abstract class JavaScriptObject extends Interceptor implements JSObject { + const JavaScriptObject(); + + // It would be impolite to stash a property on the object. + int get hashCode => 0; + + Type get runtimeType => JSObject; +} + +/** + * Interceptor for plain JavaScript objects created as JavaScript object + * literals or `new Object()`. + */ +class PlainJavaScriptObject extends JavaScriptObject { + const PlainJavaScriptObject(); +} + +/** + * Interceptor for unclassified JavaScript objects, typically objects with a + * non-trivial prototype chain. + * + * This class also serves as a fallback for unknown JavaScript exceptions. + */ +class UnknownJavaScriptObject extends JavaScriptObject { + const UnknownJavaScriptObject(); + + String toString() => JS('String', 'String(#)', this); +} + +class NativeError extends Interceptor { + String dartStack() => JS('String', '#.stack', this); +} + +// Note that this needs to be in interceptors.dart in order for +// it to be picked up as an extension type. +@JsPeerInterface(name: 'TypeError') +class NullError extends NativeError implements NoSuchMethodError { + static RegExp _nullError = RegExp(r"^Cannot read property '(.+)' of null$"); + static RegExp _extensionName = RegExp(r"^Symbol\(dartx\.(.+)\)$"); + static RegExp _privateName = RegExp(r"^Symbol\((_.+)\)$"); + + String _fieldName() { + var message = JS('String', '#.message', this); + var match = _nullError.firstMatch(message); + if (match == null) return null; + var name = match[1]; + match = _extensionName.firstMatch(name) ?? _privateName.firstMatch(name); + return match != null ? match[1] : name; + } + + String dartStack() { + var stack = super.dartStack(); + // Strip TypeError from first line. + stack = toString() + '\n' + stack.split('\n').sublist(1).join('\n'); + return stack; + } + + StackTrace get stackTrace => getTraceFromException(this); + + String toString() { + // TODO(vsm): Distinguish between null reference errors and other + // TypeErrors. We should not get non-null TypeErrors from DDC code, + // but we may from native JavaScript. + var name = _fieldName(); + if (name == null) { + // Not a Null NSM error: fallback to JS. + return JS('String', '#.toString()', this); + } + return "NullError: invalid member on null: '$name'"; + } +} + +@JsPeerInterface(name: 'Function') +class JSFunction extends Interceptor { + toString() { + // If the function is a Type object, we should just display the type name. + // + // Regular Dart code should typically get wrapped type objects instead of + // raw type (aka JS constructor) objects, however raw type objects can be + // exposed to Dart code via JS interop or debugging tools. + if (dart.isType(this)) return dart.typeName(this); + + return JS('String', r'"Closure: " + # + " from: " + #', + dart.typeName(dart.getReifiedType(this)), this); + } + + // TODO(jmesserly): remove these once we canonicalize tearoffs. + operator ==(other) { + if (other == null) return false; + var boundObj = JS('', '#._boundObject', this); + if (boundObj == null) return JS('bool', '# === #', this, other); + return JS( + 'bool', + '# === #._boundObject && #._boundMethod === #._boundMethod', + boundObj, + other, + this, + other); + } + + get hashCode { + var boundObj = JS('', '#._boundObject', this); + if (boundObj == null) return identityHashCode(this); + + var boundMethod = JS('!', '#._boundMethod', this); + int hash = (17 * 31 + boundObj.hashCode) & 0x1fffffff; + return (hash * 31 + identityHashCode(boundMethod)) & 0x1fffffff; + } + + get runtimeType => dart.wrapType(dart.getReifiedType(this)); +} + +/// A class used for implementing `null` tear-offs. +class JSNull { + toString() => 'null'; + noSuchMethod(Invocation i) => dart.defaultNoSuchMethod(null, i); +} + +final Object jsNull = JSNull(); + +// Note that this needs to be in interceptors.dart in order for +// it to be picked up as an extension type. +@JsPeerInterface(name: 'RangeError') +class JSRangeError extends Interceptor implements ArgumentError { + StackTrace get stackTrace => getTraceFromException(this); + + get invalidValue => null; + get name => null; + get message => JS('String', '#.message', this); + + String toString() => "Invalid argument: $message"; +} + +// Obsolete in dart dev compiler. Added only so that the same version of +// dart:html can be used in dart2js an dev compiler. +// Warning: calls to these methods need to be removed before custom elements +// and cross-frame dom objects behave correctly in ddc. +// See https://github.com/dart-lang/sdk/issues/28326 +findInterceptorConstructorForType(Type type) {} +findConstructorForNativeSubclassType(Type type, String name) {} +getNativeInterceptor(object) {} +setDispatchProperty(object, value) {} +NN<%5 =M;%"3= 9IF @ EB( JGMMJ=$I7!M K9#8(7@,$COE=30$N,#(I<FI*/19#'ONN?7<9B%;EE;9?;E?4C @,%B<25I5M850@ &ifile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/js_array.dartQ// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._interceptors; + +/** + * The interceptor class for [List]. The compiler recognizes this + * class as an interceptor, and changes references to [:this:] to + * actually use the receiver of the method, which is generated as an extra + * argument added to each member. + */ +@JsPeerInterface(name: 'Array') +class JSArray implements List, JSIndexable { + const JSArray(); + + /** + * Constructor for adding type parameters to an existing JavaScript + * Array. Used for creating literal lists. + */ + factory JSArray.of(list) { + // TODO(sra): Move this to core.List for better readability. + // + // TODO(jmesserly): this uses special compiler magic to close over the + // parameterized ES6 'JSArray' class. + JS('', '#.__proto__ = JSArray.prototype', list); + return JS('-dynamic', '#', list); + } + + // TODO(jmesserly): consider a fixed array subclass instead. + factory JSArray.fixed(list) { + JS('', '#.__proto__ = JSArray.prototype', list); + JS('', r'#.fixed$length = Array', list); + return JS('-dynamic', '#', list); + } + + factory JSArray.unmodifiable(list) { + JS('', '#.__proto__ = JSArray.prototype', list); + JS('', r'#.fixed$length = Array', list); + JS('', r'#.immutable$list = Array', list); + return JS('-dynamic', '#', list); + } + + static void markFixedList(list) { + // Functions are stored in the hidden class and not as properties in + // the object. We never actually look at the value, but only want + // to know if the property exists. + JS('', r'#.fixed$length = Array', list); + } + + static void markUnmodifiableList(list) { + // Functions are stored in the hidden class and not as properties in + // the object. We never actually look at the value, but only want + // to know if the property exists. + JS('', r'#.fixed$length = Array', list); + JS('', r'#.immutable$list = Array', list); + } + + checkMutable(reason) { + if (JS('bool', r'#.immutable$list', this)) { + throw UnsupportedError(reason); + } + } + + checkGrowable(reason) { + if (JS('bool', r'#.fixed$length', this)) { + throw UnsupportedError(reason); + } + } + + List cast() => List.castFrom(this); + void add(E value) { + checkGrowable('add'); + JS('void', r'#.push(#)', this, value); + } + + E removeAt(@nullCheck int index) { + checkGrowable('removeAt'); + if (index < 0 || index >= length) { + throw RangeError.value(index); + } + return JS('-dynamic', r'#.splice(#, 1)[0]', this, index); + } + + void insert(@nullCheck int index, E value) { + checkGrowable('insert'); + if (index < 0 || index > length) { + throw RangeError.value(index); + } + JS('void', r'#.splice(#, 0, #)', this, index, value); + } + + void insertAll(@nullCheck int index, Iterable iterable) { + checkGrowable('insertAll'); + RangeError.checkValueInInterval(index, 0, this.length, "index"); + if (iterable is! EfficientLengthIterable) { + iterable = iterable.toList(); + } + @nullCheck + int insertionLength = iterable.length; + this.length += insertionLength; + int end = index + insertionLength; + this.setRange(end, this.length, this, index); + this.setRange(index, end, iterable); + } + + void setAll(@nullCheck int index, Iterable iterable) { + checkMutable('setAll'); + RangeError.checkValueInInterval(index, 0, this.length, "index"); + for (var element in iterable) { + this[index++] = element; + } + } + + E removeLast() { + checkGrowable('removeLast'); + if (length == 0) throw diagnoseIndexError(this, -1); + return JS('var', r'#.pop()', this); + } + + bool remove(Object element) { + checkGrowable('remove'); + var length = this.length; + for (int i = 0; i < length; i++) { + if (this[i] == element) { + JS('var', r'#.splice(#, 1)', this, i); + return true; + } + } + return false; + } + + /** + * Removes elements matching [test] from [this] List. + */ + void removeWhere(bool test(E element)) { + checkGrowable('removeWhere'); + _removeWhere(test, true); + } + + void retainWhere(bool test(E element)) { + checkGrowable('retainWhere'); + _removeWhere(test, false); + } + + void _removeWhere(bool test(E element), bool removeMatching) { + // Performed in two steps, to avoid exposing an inconsistent state + // to the [test] function. First the elements to retain are found, and then + // the original list is updated to contain those elements. + + // TODO(sra): Replace this algorithm with one that retains a list of ranges + // to be removed. Most real uses remove 0, 1 or a few clustered elements. + + List retained = []; + int end = this.length; + for (int i = 0; i < end; i++) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + E element = JS('-dynamic', '#[#]', this, i); + // !test() ensures bool conversion in checked mode. + if (!test(element) == removeMatching) { + retained.add(element); + } + if (this.length != end) throw ConcurrentModificationError(this); + } + if (retained.length == end) return; + this.length = retained.length; + @nullCheck + var length = retained.length; + for (int i = 0; i < length; i++) { + JS('', '#[#] = #[#]', this, i, retained, i); + } + } + + Iterable where(bool f(E element)) { + return WhereIterable(this, f); + } + + Iterable expand(Iterable f(E element)) { + return ExpandIterable(this, f); + } + + void addAll(Iterable collection) { + int i = this.length; + checkGrowable('addAll'); + for (E e in collection) { + assert(i == this.length || (throw ConcurrentModificationError(this))); + i++; + JS('void', r'#.push(#)', this, e); + } + } + + void clear() { + length = 0; + } + + void forEach(void f(E element)) { + int end = this.length; + for (int i = 0; i < end; i++) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + var/*=E*/ element = JS('', '#[#]', this, i); + f(element); + if (this.length != end) throw ConcurrentModificationError(this); + } + } + + Iterable map(T f(E element)) { + return MappedListIterable(this, f); + } + + String join([String separator = ""]) { + var length = this.length; + var list = List(length); + for (int i = 0; i < length; i++) { + list[i] = "${this[i]}"; + } + return JS('String', "#.join(#)", list, separator); + } + + Iterable take(int n) { + return SubListIterable(this, 0, n); + } + + Iterable takeWhile(bool test(E value)) { + return TakeWhileIterable(this, test); + } + + Iterable skip(int n) { + return SubListIterable(this, n, null); + } + + Iterable skipWhile(bool test(E value)) { + return SkipWhileIterable(this, test); + } + + E reduce(E combine(E previousValue, E element)) { + int length = this.length; + if (length == 0) throw IterableElementError.noElement(); + E value = this[0]; + for (int i = 1; i < length; i++) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + var/*=E*/ element = JS('', '#[#]', this, i); + value = combine(value, element); + if (length != this.length) throw ConcurrentModificationError(this); + } + return value; + } + + T fold(T initialValue, T combine(T previousValue, E element)) { + var value = initialValue; + int length = this.length; + for (int i = 0; i < length; i++) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + var/*=E*/ element = JS('', '#[#]', this, i); + value = combine(value, element); + if (this.length != length) throw ConcurrentModificationError(this); + } + return value; + } + + E firstWhere(bool test(E value), {E orElse()}) { + int end = this.length; + for (int i = 0; i < end; ++i) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + var/*=E*/ element = JS('', '#[#]', this, i); + if (test(element)) return element; + if (this.length != end) throw ConcurrentModificationError(this); + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E lastWhere(bool test(E element), {E orElse()}) { + int length = this.length; + for (int i = length - 1; i >= 0; i--) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + var/*=E*/ element = JS('', '#[#]', this, i); + if (test(element)) return element; + if (length != this.length) { + throw ConcurrentModificationError(this); + } + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E singleWhere(bool test(E element), {E orElse()}) { + int length = this.length; + E match = null; + bool matchFound = false; + for (int i = 0; i < length; i++) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + E element = JS('-dynamic', '#[#]', this, i); + if (test(element)) { + if (matchFound) { + throw IterableElementError.tooMany(); + } + matchFound = true; + match = element; + } + if (length != this.length) { + throw ConcurrentModificationError(this); + } + } + if (matchFound) return match; + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E elementAt(int index) { + return this[index]; + } + + List sublist(@nullCheck int start, [int end]) { + if (start < 0 || start > length) { + throw RangeError.range(start, 0, length, "start"); + } + if (end == null) { + end = length; + } else { + @notNull + var _end = end; + if (_end < start || _end > length) { + throw RangeError.range(end, start, length, "end"); + } + } + if (start == end) return []; + return JSArray.of(JS('', r'#.slice(#, #)', this, start, end)); + } + + Iterable getRange(int start, int end) { + RangeError.checkValidRange(start, end, this.length); + return SubListIterable(this, start, end); + } + + E get first { + if (length > 0) return this[0]; + throw IterableElementError.noElement(); + } + + E get last { + if (length > 0) return this[length - 1]; + throw IterableElementError.noElement(); + } + + E get single { + if (length == 1) return this[0]; + if (length == 0) throw IterableElementError.noElement(); + throw IterableElementError.tooMany(); + } + + void removeRange(@nullCheck int start, @nullCheck int end) { + checkGrowable('removeRange'); + RangeError.checkValidRange(start, end, this.length); + int deleteCount = end - start; + JS('', '#.splice(#, #)', this, start, deleteCount); + } + + void setRange(@nullCheck int start, @nullCheck int end, Iterable iterable, + [@nullCheck int skipCount = 0]) { + checkMutable('set range'); + + RangeError.checkValidRange(start, end, this.length); + int length = end - start; + if (length == 0) return; + RangeError.checkNotNegative(skipCount, "skipCount"); + + List otherList; + int otherStart = 0; + // TODO(floitsch): Make this accept more. + if (iterable is List) { + otherList = iterable; + otherStart = skipCount; + } else { + otherList = iterable.skip(skipCount).toList(growable: false); + otherStart = 0; + } + if (otherStart + length > otherList.length) { + throw IterableElementError.tooFew(); + } + if (otherStart < start) { + // Copy backwards to ensure correct copy if [from] is this. + // TODO(sra): If [from] is the same Array as [this], we can copy without + // type annotation checks on the stores. + for (int i = length - 1; i >= 0; i--) { + // Use JS to avoid bounds check (the bounds check elimination + // optimzation is too weak). The 'E' type annotation is a store type + // check - we can't rely on iterable, it could be List. + E element = otherList[otherStart + i]; + JS('', '#[#] = #', this, start + i, element); + } + } else { + for (int i = 0; i < length; i++) { + E element = otherList[otherStart + i]; + JS('', '#[#] = #', this, start + i, element); + } + } + } + + void fillRange(@nullCheck int start, @nullCheck int end, [E fillValue]) { + checkMutable('fill range'); + RangeError.checkValidRange(start, end, this.length); + for (int i = start; i < end; i++) { + // Store is safe since [fillValue] type has been checked as parameter. + JS('', '#[#] = #', this, i, fillValue); + } + } + + void replaceRange( + @nullCheck int start, @nullCheck int end, Iterable replacement) { + checkGrowable('replace range'); + RangeError.checkValidRange(start, end, this.length); + if (replacement is! EfficientLengthIterable) { + replacement = replacement.toList(); + } + int removeLength = end - start; + @nullCheck + int insertLength = replacement.length; + if (removeLength >= insertLength) { + int delta = removeLength - insertLength; + int insertEnd = start + insertLength; + int newLength = this.length - delta; + this.setRange(start, insertEnd, replacement); + if (delta != 0) { + this.setRange(insertEnd, newLength, this, end); + this.length = newLength; + } + } else { + int delta = insertLength - removeLength; + int newLength = this.length + delta; + int insertEnd = start + insertLength; // aka. end + delta. + this.length = newLength; + this.setRange(insertEnd, newLength, this, end); + this.setRange(start, insertEnd, replacement); + } + } + + bool any(bool test(E element)) { + int end = this.length; + for (int i = 0; i < end; i++) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + var/*=E*/ element = JS('', '#[#]', this, i); + if (test(element)) return true; + if (this.length != end) throw ConcurrentModificationError(this); + } + return false; + } + + bool every(bool test(E element)) { + int end = this.length; + for (int i = 0; i < end; i++) { + // TODO(22407): Improve bounds check elimination to allow this JS code to + // be replaced by indexing. + E element = JS('-dynamic', '#[#]', this, i); + if (!test(element)) return false; + if (this.length != end) throw ConcurrentModificationError(this); + } + return true; + } + + Iterable get reversed => ReversedListIterable(this); + + void sort([int compare(E a, E b)]) { + checkMutable('sort'); + if (compare == null) { + Sort.sort(this, (a, b) => Comparable.compare(a, b)); + } else { + Sort.sort(this, compare); + } + } + + void shuffle([Random random]) { + checkMutable('shuffle'); + if (random == null) random = Random(); + int length = this.length; + while (length > 1) { + int pos = random.nextInt(length); + length -= 1; + var tmp = this[length]; + this[length] = this[pos]; + this[pos] = tmp; + } + } + + int indexOf(Object element, [@nullCheck int start = 0]) { + int length = this.length; + if (start >= length) { + return -1; + } + if (start < 0) { + start = 0; + } + for (int i = start; i < length; i++) { + if (this[i] == element) { + return i; + } + } + return -1; + } + + int lastIndexOf(Object element, [int _startIndex]) { + @notNull + int startIndex = _startIndex ?? this.length - 1; + if (startIndex >= this.length) { + startIndex = this.length - 1; + } else if (startIndex < 0) { + return -1; + } + for (int i = startIndex; i >= 0; i--) { + if (this[i] == element) { + return i; + } + } + return -1; + } + + bool contains(Object other) { + var length = this.length; + for (int i = 0; i < length; i++) { + E element = JS('Null', '#[#]', this, i); + if (element == other) return true; + } + return false; + } + + @notNull + bool get isEmpty => length == 0; + + @notNull + bool get isNotEmpty => !isEmpty; + + String toString() => ListBase.listToString(this); + + List toList({@nullCheck bool growable = true}) { + var list = JS('', '#.slice()', this); + if (!growable) markFixedList(list); + return JSArray.of(list); + } + + Set toSet() => Set.from(this); + + Iterator get iterator => ArrayIterator(this); + + int get hashCode => identityHashCode(this); + + @notNull + bool operator ==(other) => identical(this, other); + + @notNull + int get length => JS('int', r'#.length', this); + + void set length(@nullCheck int newLength) { + checkGrowable('set length'); + // TODO(sra): Remove this test and let JavaScript throw an error. + if (newLength < 0) { + throw RangeError.range(newLength, 0, null, 'newLength'); + } + // JavaScript with throw a RangeError for numbers that are too big. The + // message does not contain the value. + JS('void', r'#.length = #', this, newLength); + } + + E operator [](int index) { + // Suppress redundant null checks via JS. + if (index == null || + JS('int', '#', index) >= JS('int', '#.length', this) || + JS('int', '#', index) < 0) { + throw diagnoseIndexError(this, index); + } + return JS('var', '#[#]', this, index); + } + + void operator []=(int index, E value) { + checkMutable('indexed set'); + if (index == null || + JS('int', '#', index) >= JS('int', '#.length', this) || + JS('int', '#', index) < 0) { + throw diagnoseIndexError(this, index); + } + JS('void', r'#[#] = #', this, index, value); + } + + Map asMap() { + return ListMapView(this); + } + + Type get runtimeType => + dart.wrapType(JS('', '#(#)', dart.getGenericClass(List), E)); + + Iterable followedBy(Iterable other) => + FollowedByIterable.firstEfficient(this, other); + + Iterable whereType() => new WhereTypeIterable(this); + + List operator +(List other) { + int totalLength = this.length + other.length; + return [] + ..length = totalLength + ..setRange(0, this.length, this) + ..setRange(this.length, totalLength, other); + } + + int indexWhere(bool test(E element), [int start = 0]) { + if (start >= this.length) return -1; + if (start < 0) start = 0; + for (int i = start; i < this.length; i++) { + if (test(this[i])) return i; + } + return -1; + } + + int lastIndexWhere(bool test(E element), [int start]) { + if (start == null) start = this.length - 1; + if (start < 0) return -1; + for (int i = start; i >= 0; i--) { + if (test(this[i])) return i; + } + return -1; + } + + void set first(E element) { + if (this.isEmpty) throw RangeError.index(0, this); + this[0] = element; + } + + void set last(E element) { + if (this.isEmpty) throw RangeError.index(0, this); + this[this.length - 1] = element; + } +} + +/** + * Dummy subclasses that allow the backend to track more precise + * information about arrays through their type. The CPA type inference + * relies on the fact that these classes do not override [] nor []=. + * + * These classes are really a fiction, and can have no methods, since + * getInterceptor always returns JSArray. We should consider pushing the + * 'isGrowable' and 'isMutable' checks into the getInterceptor implementation so + * these classes can have specialized implementations. Doing so will challenge + * many assumptions in the JS backend. + */ +class JSMutableArray extends JSArray {} + +class JSFixedArray extends JSMutableArray {} + +class JSExtendableArray extends JSMutableArray {} + +class JSUnmodifiableArray extends JSArray {} // Already is JSIndexable. + +/// An [Iterator] that iterates a JSArray. +/// +class ArrayIterator implements Iterator { + final JSArray _iterable; + @notNull + final int _length; + @notNull + int _index; + E _current; + + ArrayIterator(JSArray iterable) + : _iterable = iterable, + _length = iterable.length, + _index = 0; + + E get current => _current; + + bool moveNext() { + @notNull + int length = _iterable.length; + + // We have to do the length check even on fixed length Arrays. If we can + // inline moveNext() we might be able to GVN the length and eliminate this + // check on known fixed length JSArray. + if (_length != length) { + throw throwConcurrentModificationError(_iterable); + } + + if (_index >= length) { + _current = null; + return false; + } + _current = _iterable[_index]; + _index++; + return true; + } +} +NN<BBK" 6F-AK*5&? 5-&'5-/&$IF'-+IF'-/1&/&2+%(%>/'%:? E0$+$'2)<E$!9( ' /8+"+"AGP?PO$P"3:.G(#"'3)&4*(M )$$P"3G'.)'7+.-..-4='P"3'JE'P"3'J3$P"3)G),4,P"3)#1),6'P"30 +#1"),5'9 +;$F-91$,-,%=*?"9#8P(99. D2+BO/.FMI/6 )/6L 9(M.K$93*$+(/,+48! /+A64#$P"3&G%$P"3(G='; "+( <+ 7 5%$!,  '/) # #46*( '6. 5 2.!F?L+2.@%-+*!@%-1!D/9@&2'3:)0#:0'#77%AGEFJQO'.38N+0  %# #NO,9"jfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/js_number.dart7// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._interceptors; + +/** + * The implementation of Dart's int & double methods. + * These are made available as extension methods on `Number` in JS. + */ +@JsPeerInterface(name: 'Number') +class JSNumber extends Interceptor implements int, double { + const JSNumber(); + + @notNull + int compareTo(@nullCheck num b) { + if (this < b) { + return -1; + } else if (this > b) { + return 1; + } else if (this == b) { + if (this == 0) { + bool bIsNegative = b.isNegative; + if (isNegative == bIsNegative) return 0; + if (isNegative) return -1; + return 1; + } + return 0; + } else if (isNaN) { + if (b.isNaN) { + return 0; + } + return 1; + } else { + return -1; + } + } + + @notNull + bool get isNegative => (this == 0) ? (1 / this) < 0 : this < 0; + + @notNull + bool get isNaN => JS('bool', r'isNaN(#)', this); + + @notNull + bool get isInfinite { + return JS('bool', r'# == (1/0)', this) || JS('bool', r'# == (-1/0)', this); + } + + @notNull + bool get isFinite => JS('bool', r'isFinite(#)', this); + + @notNull + JSNumber remainder(@nullCheck num b) { + return JS('num', r'# % #', this, b); + } + + @notNull + JSNumber abs() => JS('num', r'Math.abs(#)', this); + + @notNull + JSNumber get sign => this > 0 ? 1 : this < 0 ? -1 : this; + + @notNull + static const int _MIN_INT32 = -0x80000000; + @notNull + static const int _MAX_INT32 = 0x7FFFFFFF; + + @notNull + int toInt() { + if (this >= _MIN_INT32 && this <= _MAX_INT32) { + return JS('int', '# | 0', this); + } + if (JS('bool', r'isFinite(#)', this)) { + return JS('int', r'# + 0', truncateToDouble()); // Converts -0.0 to +0.0. + } + // This is either NaN, Infinity or -Infinity. + throw UnsupportedError(JS("String", '"" + #', this)); + } + + @notNull + int truncate() => toInt(); + + @notNull + int ceil() => ceilToDouble().toInt(); + + @notNull + int floor() => floorToDouble().toInt(); + + @notNull + int round() { + if (this > 0) { + // This path excludes the special cases -0.0, NaN and -Infinity, leaving + // only +Infinity, for which a direct test is faster than [isFinite]. + if (JS('bool', r'# !== (1/0)', this)) { + return JS('int', r'Math.round(#)', this); + } + } else if (JS('bool', '# > (-1/0)', this)) { + // This test excludes NaN and -Infinity, leaving only -0.0. + // + // Subtraction from zero rather than negation forces -0.0 to 0.0 so code + // inside Math.round and code to handle result never sees -0.0, which on + // some JavaScript VMs can be a slow path. + return JS('int', r'0 - Math.round(0 - #)', this); + } + // This is either NaN, Infinity or -Infinity. + throw UnsupportedError(JS("String", '"" + #', this)); + } + + @notNull + double ceilToDouble() => JS('num', r'Math.ceil(#)', this); + + @notNull + double floorToDouble() => JS('num', r'Math.floor(#)', this); + + @notNull + double roundToDouble() { + if (this < 0) { + return JS('num', r'-Math.round(-#)', this); + } else { + return JS('num', r'Math.round(#)', this); + } + } + + @notNull + double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble(); + + @notNull + num clamp(@nullCheck num lowerLimit, @nullCheck num upperLimit) { + if (lowerLimit.compareTo(upperLimit) > 0) { + throw argumentErrorValue(lowerLimit); + } + if (this.compareTo(lowerLimit) < 0) return lowerLimit; + if (this.compareTo(upperLimit) > 0) return upperLimit; + return this; + } + + @notNull + double toDouble() => this; + + @notNull + String toStringAsFixed(@notNull int fractionDigits) { + if (fractionDigits < 0 || fractionDigits > 20) { + throw RangeError.range(fractionDigits, 0, 20, "fractionDigits"); + } + String result = JS('String', r'#.toFixed(#)', this, fractionDigits); + if (this == 0 && isNegative) return "-$result"; + return result; + } + + @notNull + String toStringAsExponential([int fractionDigits]) { + String result; + if (fractionDigits != null) { + @notNull + var _fractionDigits = fractionDigits; + if (_fractionDigits < 0 || _fractionDigits > 20) { + throw RangeError.range(_fractionDigits, 0, 20, "fractionDigits"); + } + result = JS('String', r'#.toExponential(#)', this, _fractionDigits); + } else { + result = JS('String', r'#.toExponential()', this); + } + if (this == 0 && isNegative) return "-$result"; + return result; + } + + @notNull + String toStringAsPrecision(@nullCheck int precision) { + if (precision < 1 || precision > 21) { + throw RangeError.range(precision, 1, 21, "precision"); + } + String result = JS('String', r'#.toPrecision(#)', this, precision); + if (this == 0 && isNegative) return "-$result"; + return result; + } + + @notNull + String toRadixString(@nullCheck int radix) { + if (radix < 2 || radix > 36) { + throw RangeError.range(radix, 2, 36, "radix"); + } + String result = JS('String', r'#.toString(#)', this, radix); + const int rightParenCode = 0x29; + if (result.codeUnitAt(result.length - 1) != rightParenCode) { + return result; + } + return _handleIEtoString(result); + } + + @notNull + static String _handleIEtoString(String result) { + // Result is probably IE's untraditional format for large numbers, + // e.g., "8.0000000000008(e+15)" for 0x8000000000000800.toString(16). + var match = JS( + '', r'/^([\da-z]+)(?:\.([\da-z]+))?\(e\+(\d+)\)$/.exec(#)', result); + if (match == null) { + // Then we don't know how to handle it at all. + throw UnsupportedError("Unexpected toString result: $result"); + } + result = JS('!', '#', match[1]); + int exponent = JS("!", "+#", match[3]); + if (match[2] != null) { + result = JS('!', '# + #', result, match[2]); + exponent -= JS('!', '#.length', match[2]); + } + return result + "0" * exponent; + } + + // Note: if you change this, also change the function [S]. + @notNull + String toString() { + if (this == 0 && JS('bool', '(1 / #) < 0', this)) { + return '-0.0'; + } else { + return JS('String', r'"" + (#)', this); + } + } + + @notNull + int get hashCode => JS('int', '# & 0x1FFFFFFF', this); + + @notNull + JSNumber operator -() => JS('num', r'-#', this); + + @notNull + JSNumber operator +(@nullCheck num other) { + return JS('num', '# + #', this, other); + } + + @notNull + JSNumber operator -(@nullCheck num other) { + return JS('num', '# - #', this, other); + } + + @notNull + double operator /(@nullCheck num other) { + return JS('num', '# / #', this, other); + } + + @notNull + JSNumber operator *(@nullCheck num other) { + return JS('num', '# * #', this, other); + } + + @notNull + JSNumber operator %(@nullCheck num other) { + // Euclidean Modulo. + num result = JS('num', r'# % #', this, other); + if (result == 0) return (0 as JSNumber); // Make sure we don't return -0.0. + if (result > 0) return result; + if (JS('num', '#', other) < 0) { + return result - JS('num', '#', other); + } else { + return result + JS('num', '#', other); + } + } + + @notNull + bool _isInt32(@notNull num value) => + JS('bool', '(# | 0) === #', value, value); + + @notNull + int operator ~/(@nullCheck num other) { + if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) { + return JS('int', r'(# / #) | 0', this, other); + } else { + return _tdivSlow(other); + } + } + + @notNull + int _tdivSlow(num other) { + return (JS('num', r'# / #', this, other)).toInt(); + } + + // TODO(ngeoffray): Move the bit operations below to [JSInt] and + // make them take an int. Because this will make operations slower, + // we define these methods on number for now but we need to decide + // the grain at which we do the type checks. + + @notNull + int operator <<(@nullCheck num other) { + if (other < 0) throwArgumentErrorValue(other); + return _shlPositive(other); + } + + @notNull + int _shlPositive(@notNull num other) { + // JavaScript only looks at the last 5 bits of the shift-amount. Shifting + // by 33 is hence equivalent to a shift by 1. + return JS('bool', r'# > 31', other) + ? 0 + : JS('int', r'(# << #) >>> 0', this, other); + } + + @notNull + int operator >>(@nullCheck num other) { + if (JS('num', '#', other) < 0) throwArgumentErrorValue(other); + return _shrOtherPositive(other); + } + + @notNull + int _shrOtherPositive(@notNull num other) { + return JS('num', '#', this) > 0 + ? _shrBothPositive(other) + // For negative numbers we just clamp the shift-by amount. + // `this` could be negative but not have its 31st bit set. + // The ">>" would then shift in 0s instead of 1s. Therefore + // we cannot simply return 0xFFFFFFFF. + : JS('int', r'(# >> #) >>> 0', this, other > 31 ? 31 : other); + } + + @notNull + int _shrBothPositive(@notNull num other) { + return JS('bool', r'# > 31', other) + // JavaScript only looks at the last 5 bits of the shift-amount. In JS + // shifting by 33 is hence equivalent to a shift by 1. Shortcut the + // computation when that happens. + ? 0 + // Given that `this` is positive we must not use '>>'. Otherwise a + // number that has the 31st bit set would be treated as negative and + // shift in ones. + : JS('int', r'# >>> #', this, other); + } + + @notNull + int operator &(@nullCheck num other) { + return JS('int', r'(# & #) >>> 0', this, other); + } + + @notNull + int operator |(@nullCheck num other) { + return JS('int', r'(# | #) >>> 0', this, other); + } + + @notNull + int operator ^(@nullCheck num other) { + return JS('int', r'(# ^ #) >>> 0', this, other); + } + + @notNull + bool operator <(@nullCheck num other) { + return JS('bool', '# < #', this, other); + } + + @notNull + bool operator >(@nullCheck num other) { + return JS('bool', '# > #', this, other); + } + + @notNull + bool operator <=(@nullCheck num other) { + return JS('bool', '# <= #', this, other); + } + + @notNull + bool operator >=(@nullCheck num other) { + return JS('bool', '# >= #', this, other); + } + + // int members. + // TODO(jmesserly): all numbers will have these in dynamic dispatch. + // We can fix by checking it at dispatch time but we'd need to structure them + // differently. + + @notNull + bool get isEven => (this & 1) == 0; + + @notNull + bool get isOdd => (this & 1) == 1; + + @notNull + int toUnsigned(@nullCheck int width) { + return this & ((1 << width) - 1); + } + + @notNull + int toSigned(@nullCheck int width) { + int signMask = 1 << (width - 1); + return (this & (signMask - 1)) - (this & signMask); + } + + @notNull + int get bitLength { + int nonneg = this < 0 ? -this - 1 : this; + int wordBits = 32; + while (nonneg >= 0x100000000) { + nonneg = nonneg ~/ 0x100000000; + wordBits += 32; + } + return wordBits - _clz32(nonneg); + } + + @notNull + static int _clz32(@notNull int uint32) { + // TODO(sra): Use `Math.clz32(uint32)` (not available on IE11). + return 32 - _bitCount(_spread(uint32)); + } + + // Returns pow(this, e) % m. + @notNull + int modPow(@nullCheck int e, @nullCheck int m) { + if (e < 0) throw RangeError.range(e, 0, null, "exponent"); + if (m <= 0) throw RangeError.range(m, 1, null, "modulus"); + if (e == 0) return 1; + int b = this; + if (b < 0 || b > m) { + b %= m; + } + int r = 1; + while (e > 0) { + if (e.isOdd) { + r = (r * b) % m; + } + e ~/= 2; + b = (b * b) % m; + } + return r; + } + + // If inv is false, returns gcd(x, y). + // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1. + // If inv is true and gcd(x, y) != 1, throws Exception("Not coprime"). + @notNull + static int _binaryGcd(@notNull int x, @notNull int y, @notNull bool inv) { + int s = 1; + if (!inv) { + while (x.isEven && y.isEven) { + x ~/= 2; + y ~/= 2; + s *= 2; + } + if (y.isOdd) { + var t = x; + x = y; + y = t; + } + } + final bool ac = x.isEven; + int u = x; + int v = y; + int a = 1, b = 0, c = 0, d = 1; + do { + while (u.isEven) { + u ~/= 2; + if (ac) { + if (!a.isEven || !b.isEven) { + a += y; + b -= x; + } + a ~/= 2; + } else if (!b.isEven) { + b -= x; + } + b ~/= 2; + } + while (v.isEven) { + v ~/= 2; + if (ac) { + if (!c.isEven || !d.isEven) { + c += y; + d -= x; + } + c ~/= 2; + } else if (!d.isEven) { + d -= x; + } + d ~/= 2; + } + if (u >= v) { + u -= v; + if (ac) a -= c; + b -= d; + } else { + v -= u; + if (ac) c -= a; + d -= b; + } + } while (u != 0); + if (!inv) return s * v; + if (v != 1) throw Exception("Not coprime"); + if (d < 0) { + d += x; + if (d < 0) d += x; + } else if (d > x) { + d -= x; + if (d > x) d -= x; + } + return d; + } + + // Returns 1/this % m, with m > 0. + @notNull + int modInverse(@nullCheck int m) { + if (m <= 0) throw RangeError.range(m, 1, null, "modulus"); + if (m == 1) return 0; + int t = this; + if ((t < 0) || (t >= m)) t %= m; + if (t == 1) return 1; + if ((t == 0) || (t.isEven && m.isEven)) { + throw Exception("Not coprime"); + } + return _binaryGcd(m, t, true); + } + + // Returns gcd of abs(this) and abs(other). + @notNull + int gcd(@nullCheck int other) { + int x = this.abs(); + int y = other.abs(); + if (x == 0) return y; + if (y == 0) return x; + if ((x == 1) || (y == 1)) return 1; + return _binaryGcd(x, y, false); + } + + // Assumes i is <= 32-bit and unsigned. + @notNull + static int _bitCount(@notNull int i) { + // See "Hacker's Delight", section 5-1, "Counting 1-Bits". + + // The basic strategy is to use "divide and conquer" to + // add pairs (then quads, etc.) of bits together to obtain + // sub-counts. + // + // A straightforward approach would look like: + // + // i = (i & 0x55555555) + ((i >> 1) & 0x55555555); + // i = (i & 0x33333333) + ((i >> 2) & 0x33333333); + // i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F); + // i = (i & 0x00FF00FF) + ((i >> 8) & 0x00FF00FF); + // i = (i & 0x0000FFFF) + ((i >> 16) & 0x0000FFFF); + // + // The code below removes unnecessary &'s and uses a + // trick to remove one instruction in the first line. + + i = _shru(i, 0) - (_shru(i, 1) & 0x55555555); + i = (i & 0x33333333) + (_shru(i, 2) & 0x33333333); + i = 0x0F0F0F0F & (i + _shru(i, 4)); + i += _shru(i, 8); + i += _shru(i, 16); + return (i & 0x0000003F); + } + + @notNull + static int _shru(int value, int shift) => JS('int', '# >>> #', value, shift); + @notNull + static int _shrs(int value, int shift) => JS('int', '# >> #', value, shift); + @notNull + static int _ors(int a, int b) => JS('int', '# | #', a, b); + + // Assumes i is <= 32-bit + @notNull + static int _spread(@notNull int i) { + i = _ors(i, _shrs(i, 1)); + i = _ors(i, _shrs(i, 2)); + i = _ors(i, _shrs(i, 4)); + i = _ors(i, _shrs(i, 8)); + i = _shru(_ors(i, _shrs(i, 16)), 0); + return i; + } + + @notNull + int operator ~() => JS('int', r'(~#) >>> 0', this); +} +8NN<6D!< $)1#  B 3 P 9 )) 5 < - , 4',P2:  ( * OL.21B OO182: = ? 2 0 L D0,;;  85GI4 7",9JK 94 9+=H4 /#5A%B& 3GJM5E%,36$= 8 . 9 3 ., ., ,, ., .3P#%- - '1 *J5  7CFE/ *3  )N2( 5 *C% .$"CCD/G -(OL* KM. )5 )5 )5 *- *- +. +.GP & % )& '%8 .$&& +D, 3??)II M%$ (   +(   +0% %?%.&#. "($* )? { + const JSString(); + + @notNull + int codeUnitAt(@nullCheck int index) { + // Suppress 2nd null check on index and null check on length + // (JS String.length cannot be null). + final len = this.length; + if (index < 0 || index >= len) { + throw RangeError.index(index, this, 'index', null, len); + } + return JS('int', r'#.charCodeAt(#)', this, index); + } + + @notNull + Iterable allMatches(@nullCheck String string, + [@nullCheck int start = 0]) { + final len = string.length; + if (0 > start || start > len) { + throw RangeError.range(start, 0, len); + } + return allMatchesInStringUnchecked(this, string, start); + } + + Match matchAsPrefix(@nullCheck String string, [@nullCheck int start = 0]) { + int stringLength = JS('!', '#.length', string); + if (start < 0 || start > stringLength) { + throw RangeError.range(start, 0, stringLength); + } + int thisLength = JS('!', '#.length', this); + if (start + thisLength > stringLength) return null; + for (int i = 0; i < thisLength; i++) { + if (string.codeUnitAt(start + i) != this.codeUnitAt(i)) { + return null; + } + } + return StringMatch(start, string, this); + } + + @notNull + String operator +(@nullCheck String other) { + return JS('String', r'# + #', this, other); + } + + @notNull + bool endsWith(@nullCheck String other) { + var otherLength = other.length; + var thisLength = this.length; + if (otherLength > thisLength) return false; + return other == substring(thisLength - otherLength); + } + + @notNull + String replaceAll(Pattern from, @nullCheck String to) { + return stringReplaceAllUnchecked(this, from, to); + } + + @notNull + String replaceAllMapped(Pattern from, String convert(Match match)) { + return this.splitMapJoin(from, onMatch: convert); + } + + @notNull + String splitMapJoin(Pattern from, + {String onMatch(Match match), String onNonMatch(String nonMatch)}) { + return stringReplaceAllFuncUnchecked(this, from, onMatch, onNonMatch); + } + + @notNull + String replaceFirst(Pattern from, @nullCheck String to, + [@nullCheck int startIndex = 0]) { + RangeError.checkValueInInterval(startIndex, 0, this.length, "startIndex"); + return stringReplaceFirstUnchecked(this, from, to, startIndex); + } + + @notNull + String replaceFirstMapped( + Pattern from, @nullCheck String replace(Match match), + [@nullCheck int startIndex = 0]) { + RangeError.checkValueInInterval(startIndex, 0, this.length, "startIndex"); + return stringReplaceFirstMappedUnchecked(this, from, replace, startIndex); + } + + @notNull + List split(@nullCheck Pattern pattern) { + if (pattern is String) { + return JSArray.of(JS('', r'#.split(#)', this, pattern)); + } else if (pattern is JSSyntaxRegExp && regExpCaptureCount(pattern) == 0) { + var re = regExpGetNative(pattern); + return JSArray.of(JS('', r'#.split(#)', this, re)); + } else { + return _defaultSplit(pattern); + } + } + + @notNull + String replaceRange( + @nullCheck int start, int end, @nullCheck String replacement) { + end = RangeError.checkValidRange(start, end, this.length); + return stringReplaceRangeUnchecked(this, start, end, replacement); + } + + @notNull + List _defaultSplit(Pattern pattern) { + List result = []; + // End of most recent match. That is, start of next part to add to result. + int start = 0; + // Length of most recent match. + // Set >0, so no match on the empty string causes the result to be [""]. + int length = 1; + for (var match in pattern.allMatches(this)) { + @notNull + int matchStart = match.start; + @notNull + int matchEnd = match.end; + length = matchEnd - matchStart; + if (length == 0 && start == matchStart) { + // An empty match right after another match is ignored. + // This includes an empty match at the start of the string. + continue; + } + int end = matchStart; + result.add(this.substring(start, end)); + start = matchEnd; + } + if (start < this.length || length > 0) { + // An empty match at the end of the string does not cause a "" at the end. + // A non-empty match ending at the end of the string does add a "". + result.add(this.substring(start)); + } + return result; + } + + @notNull + bool startsWith(Pattern pattern, [@nullCheck int index = 0]) { + // Suppress null check on length and all but the first + // reference to index. + int length = JS('int', '#.length', this); + if (index < 0 || JS('int', '#', index) > length) { + throw RangeError.range(index, 0, this.length); + } + if (pattern is String) { + String other = pattern; + int otherLength = JS('int', '#.length', other); + int endIndex = index + otherLength; + if (endIndex > length) return false; + return other == JS('String', r'#.substring(#, #)', this, index, endIndex); + } + return pattern.matchAsPrefix(this, index) != null; + } + + @notNull + String substring(@nullCheck int startIndex, [int _endIndex]) { + var length = this.length; + final endIndex = _endIndex ?? length; + if (startIndex < 0) throw RangeError.value(startIndex); + if (startIndex > endIndex) throw RangeError.value(startIndex); + if (endIndex > length) throw RangeError.value(endIndex); + return JS('String', r'#.substring(#, #)', this, startIndex, endIndex); + } + + @notNull + String toLowerCase() { + return JS('String', r'#.toLowerCase()', this); + } + + @notNull + String toUpperCase() { + return JS('String', r'#.toUpperCase()', this); + } + + // Characters with Whitespace property (Unicode 6.3). + // 0009..000D ; White_Space # Cc .. + // 0020 ; White_Space # Zs SPACE + // 0085 ; White_Space # Cc + // 00A0 ; White_Space # Zs NO-BREAK SPACE + // 1680 ; White_Space # Zs OGHAM SPACE MARK + // 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE + // 2028 ; White_Space # Zl LINE SEPARATOR + // 2029 ; White_Space # Zp PARAGRAPH SEPARATOR + // 202F ; White_Space # Zs NARROW NO-BREAK SPACE + // 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE + // 3000 ; White_Space # Zs IDEOGRAPHIC SPACE + // + // BOM: 0xFEFF + @notNull + static bool _isWhitespace(@notNull int codeUnit) { + // Most codeUnits should be less than 256. Special case with a smaller + // switch. + if (codeUnit < 256) { + switch (codeUnit) { + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x20: + case 0x85: + case 0xA0: + return true; + default: + return false; + } + } + switch (codeUnit) { + case 0x1680: + case 0x2000: + case 0x2001: + case 0x2002: + case 0x2003: + case 0x2004: + case 0x2005: + case 0x2006: + case 0x2007: + case 0x2008: + case 0x2009: + case 0x200A: + case 0x2028: + case 0x2029: + case 0x202F: + case 0x205F: + case 0x3000: + case 0xFEFF: + return true; + default: + return false; + } + } + + /// Finds the index of the first non-whitespace character, or the + /// end of the string. Start looking at position [index]. + @notNull + static int _skipLeadingWhitespace(String string, @nullCheck int index) { + const int SPACE = 0x20; + const int CARRIAGE_RETURN = 0x0D; + var stringLength = string.length; + while (index < stringLength) { + int codeUnit = string.codeUnitAt(index); + if (codeUnit != SPACE && + codeUnit != CARRIAGE_RETURN && + !_isWhitespace(codeUnit)) { + break; + } + index++; + } + return index; + } + + /// Finds the index after the last non-whitespace character, or 0. + /// Start looking at position [index - 1]. + @notNull + static int _skipTrailingWhitespace(String string, @nullCheck int index) { + const int SPACE = 0x20; + const int CARRIAGE_RETURN = 0x0D; + while (index > 0) { + int codeUnit = string.codeUnitAt(index - 1); + if (codeUnit != SPACE && + codeUnit != CARRIAGE_RETURN && + !_isWhitespace(codeUnit)) { + break; + } + index--; + } + return index; + } + + // Dart2js can't use JavaScript trim directly, + // because JavaScript does not trim + // the NEXT LINE (NEL) character (0x85). + @notNull + String trim() { + const int NEL = 0x85; + + // Start by doing JS trim. Then check if it leaves a NEL at + // either end of the string. + String result = JS('!', '#.trim()', this); + final length = result.length; + if (length == 0) return result; + int firstCode = result.codeUnitAt(0); + int startIndex = 0; + if (firstCode == NEL) { + startIndex = _skipLeadingWhitespace(result, 1); + if (startIndex == length) return ""; + } + + int endIndex = length; + // We know that there is at least one character that is non-whitespace. + // Therefore we don't need to verify that endIndex > startIndex. + int lastCode = result.codeUnitAt(endIndex - 1); + if (lastCode == NEL) { + endIndex = _skipTrailingWhitespace(result, endIndex - 1); + } + if (startIndex == 0 && endIndex == length) return result; + return JS('String', r'#.substring(#, #)', result, startIndex, endIndex); + } + + // Dart2js can't use JavaScript trimLeft directly, + // because it is not in ES5, so not every browser implements it, + // and because those that do will not trim the NEXT LINE character (0x85). + @notNull + String trimLeft() { + const int NEL = 0x85; + + // Start by doing JS trim. Then check if it leaves a NEL at + // the beginning of the string. + String result; + int startIndex = 0; + if (JS('bool', 'typeof #.trimLeft != "undefined"', this)) { + result = JS('String', '#.trimLeft()', this); + if (result.length == 0) return result; + int firstCode = result.codeUnitAt(0); + if (firstCode == NEL) { + startIndex = _skipLeadingWhitespace(result, 1); + } + } else { + result = this; + startIndex = _skipLeadingWhitespace(this, 0); + } + if (startIndex == 0) return result; + if (startIndex == result.length) return ""; + return JS('String', r'#.substring(#)', result, startIndex); + } + + // Dart2js can't use JavaScript trimRight directly, + // because it is not in ES5 and because JavaScript does not trim + // the NEXT LINE character (0x85). + @notNull + String trimRight() { + const int NEL = 0x85; + + // Start by doing JS trim. Then check if it leaves a NEL or BOM at + // the end of the string. + String result; + @notNull + int endIndex = 0; + // trimRight is implemented by Firefox and Chrome/Blink, + // so use it if it is there. + if (JS('bool', 'typeof #.trimRight != "undefined"', this)) { + result = JS('String', '#.trimRight()', this); + endIndex = result.length; + if (endIndex == 0) return result; + int lastCode = result.codeUnitAt(endIndex - 1); + if (lastCode == NEL) { + endIndex = _skipTrailingWhitespace(result, endIndex - 1); + } + } else { + result = this; + endIndex = _skipTrailingWhitespace(this, this.length); + } + + if (endIndex == result.length) return result; + if (endIndex == 0) return ""; + return JS('String', r'#.substring(#, #)', result, 0, endIndex); + } + + @notNull + String operator *(@nullCheck int times) { + if (0 >= times) return ''; + if (times == 1 || this.length == 0) return this; + if (times != JS('int', '# >>> 0', times)) { + // times >= 2^32. We can't create a string that big. + throw const OutOfMemoryError(); + } + var result = ''; + String s = this; + while (true) { + if (times & 1 == 1) result = s + result; + times = JS('int', '# >>> 1', times); + if (times == 0) break; + s += s; + } + return result; + } + + @notNull + String padLeft(@nullCheck int width, [String padding = ' ']) { + int delta = width - this.length; + if (delta <= 0) return this; + return padding * delta + this; + } + + @notNull + String padRight(@nullCheck int width, [String padding = ' ']) { + int delta = width - this.length; + if (delta <= 0) return this; + return this + padding * delta; + } + + @notNull + List get codeUnits => CodeUnits(this); + + @notNull + Runes get runes => Runes(this); + + @notNull + int indexOf(@nullCheck Pattern pattern, [@nullCheck int start = 0]) { + if (start < 0 || start > this.length) { + throw RangeError.range(start, 0, this.length); + } + if (pattern is String) { + return stringIndexOfStringUnchecked(this, pattern, start); + } + if (pattern is JSSyntaxRegExp) { + JSSyntaxRegExp re = pattern; + Match match = firstMatchAfter(re, this, start); + return (match == null) ? -1 : match.start; + } + var length = this.length; + for (int i = start; i <= length; i++) { + if (pattern.matchAsPrefix(this, i) != null) return i; + } + return -1; + } + + @notNull + int lastIndexOf(@nullCheck Pattern pattern, [int _start]) { + var length = this.length; + var start = _start ?? length; + if (start < 0 || start > length) { + throw RangeError.range(start, 0, length); + } + if (pattern is String) { + String other = pattern; + if (start + other.length > length) { + start = length - other.length; + } + return stringLastIndexOfUnchecked(this, other, start); + } + for (int i = start; i >= 0; i--) { + if (pattern.matchAsPrefix(this, i) != null) return i; + } + return -1; + } + + @notNull + bool contains(@nullCheck Pattern other, [@nullCheck int startIndex = 0]) { + if (startIndex < 0 || startIndex > this.length) { + throw RangeError.range(startIndex, 0, this.length); + } + return stringContainsUnchecked(this, other, startIndex); + } + + @notNull + bool get isEmpty => JS('!', '#.length', this) == 0; + + @notNull + bool get isNotEmpty => !isEmpty; + + @notNull + int compareTo(@nullCheck String other) { + return this == other ? 0 : JS('bool', r'# < #', this, other) ? -1 : 1; + } + + // Note: if you change this, also change the function [S]. + @notNull + String toString() => this; + + /** + * This is the [Jenkins hash function][1] but using masking to keep + * values in SMI range. + * + * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function + */ + @notNull + int get hashCode { + // TODO(ahe): This method shouldn't have to use JS. Update when our + // optimizations are smarter. + int hash = 0; + int length = JS('!', '#.length', this); + for (int i = 0; i < length; i++) { + hash = 0x1fffffff & (hash + JS('!', r'#.charCodeAt(#)', this, i)); + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + hash = JS('int', '# ^ (# >> 6)', hash, hash); + } + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + hash = JS('int', '# ^ (# >> 11)', hash, hash); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } + + @notNull + Type get runtimeType => String; + + @notNull + final int length; + + @notNull + String operator [](@nullCheck int index) { + if (index >= JS('int', '#.length', this) || index < 0) { + throw diagnoseIndexError(this, index); + } + return JS('String', '#[#]', this, index); + } +} +NN<DBK"!L )A*%?7 7$$-=N4-608+@- /0 +$"09 :6 G6 $KK :)OD <)OO 3?P): % F?G 0&O$M2$ &0@D.-QJ) A;.756*+Q7 A* 5KD< K&&#/)&E- L&3)&1&+ @!/"$*6+LE4@>M5CM @$@3-,8 4(0@6C% G =!A4 (6B =2"D ,50;&/+ A%!# B%!# . " H,5A%#61,< >"'0+'='< M6:= ; # +K= F= H",'N@4=3> "  -=-.Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/internal.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart._internal; + +import 'dart:collection'; + +import 'dart:async' + show + Future, + Stream, + StreamSubscription, + StreamTransformer, + StreamTransformerBase, + Zone; +import 'dart:convert' show Converter; +import 'dart:core' hide Symbol; +import 'dart:core' as core; +import 'dart:math' show Random; + +part 'async_cast.dart'; +part 'cast.dart'; +part 'iterable.dart'; +part 'list.dart'; +part 'print.dart'; +part 'sort.dart'; +part 'symbol.dart'; +part 'linked_list.dart'; + +// Powers of 10 up to 10^22 are representable as doubles. +// Powers of 10 above that are only approximate due to lack of precission. +// Used by double-parsing. +const POWERS_OF_TEN = const [ + 1.0, // 0 + 10.0, + 100.0, + 1000.0, + 10000.0, + 100000.0, // 5 + 1000000.0, + 10000000.0, + 100000000.0, + 1000000000.0, + 10000000000.0, // 10 + 100000000000.0, + 1000000000000.0, + 10000000000000.0, + 100000000000000.0, + 1000000000000000.0, // 15 + 10000000000000000.0, + 100000000000000000.0, + 1000000000000000000.0, + 10000000000000000000.0, + 100000000000000000000.0, // 20 + 1000000000000000000000.0, + 10000000000000000000000.0, +]; + +/** + * An [Iterable] of the UTF-16 code units of a [String] in index order. + */ +class CodeUnits extends UnmodifiableListBase { + /** The string that this is the code units of. */ + final String _string; + + CodeUnits(this._string); + + int get length => _string.length; + int operator [](int i) => _string.codeUnitAt(i); + + static String stringOf(CodeUnits u) => u._string; +} + +/// Marks a function or library as having an external implementation ("native" +/// in the Dart VM). +/// +/// On a function, this provides a backend-specific String that can be used to +/// identify the function's implementation. +/// +/// On a library, it provides a Uri that can be used to locate the native +/// library's implementation. +class ExternalName { + final String name; + const ExternalName(this.name); +} + +// Shared hex-parsing utilities. + +/// Parses a single hex-digit as code unit. +/// +/// Returns a negative value if the character is not a valid hex-digit. +int hexDigitValue(int char) { + assert(char >= 0 && char <= 0xFFFF); + const int digit0 = 0x30; + const int a = 0x61; + const int f = 0x66; + int digit = char ^ digit0; + if (digit <= 9) return digit; + int letter = (char | 0x20); + if (a <= letter && letter <= f) return letter - (a - 10); + return -1; +} + +/// Parses two hex digits in a string. +/// +/// Returns a negative value if either digit isn't valid. +int parseHexByte(String source, int index) { + assert(index + 2 <= source.length); + int digit1 = hexDigitValue(source.codeUnitAt(index)); + int digit2 = hexDigitValue(source.codeUnitAt(index + 1)); + return digit1 * 16 + digit2 - (digit2 & 256); +} + +/// Given an [instance] of some generic type [T], and [extract], a first-class +/// generic function that takes the same number of type parameters as [T], +/// invokes the function with the same type arguments that were passed to T +/// when [instance] was constructed. +/// +/// Example: +/// +/// ```dart +/// class Two {} +/// +/// print(extractTypeArguments([], () => new Set())); +/// // Prints: Instance of 'Set'. +/// +/// print(extractTypeArguments({}, +/// () => new Two)); +/// // Prints: Instance of 'Two'. +/// ``` +/// +/// The type argument T is important to choose which specific type parameter +/// list in [instance]'s type hierarchy is being extracted. Consider: +/// +/// ```dart +/// class A {} +/// class B {} +/// +/// class C implements A, B {} +/// +/// main() { +/// var c = new C(); +/// print(extractTypeArguments(c, () => [])); +/// // Prints: Instance of 'List'. +/// +/// print(extractTypeArguments(c, () => [])); +/// // Prints: Instance of 'List'. +/// } +/// ``` +/// +/// A caller must not: +/// +/// * Pass `null` for [instance]. +/// * Use a non-class type (i.e. a function type) for [T]. +/// * Use a non-generic type for [T]. +/// * Pass an instance of a generic type and a function that don't both take +/// the same number of type arguments: +/// +/// ```dart +/// extractTypeArguments([], () => null); +/// ``` +/// +/// See this issue for more context: +/// https://github.com/dart-lang/sdk/issues/31371 +external Object extractTypeArguments(T instance, Function extract); +NN< &  :K  +  !H44$34OO,J!!,H' < ':-&8<0OKL%  G'6%0MF , 9*9-$=(O+? %2GRfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/iterable.dart^// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +/** + * Marker interface for [Iterable] subclasses that have an efficient + * [length] implementation. + */ +abstract class EfficientLengthIterable extends Iterable { + const EfficientLengthIterable(); + /** + * Returns the number of elements in the iterable. + * + * This is an efficient operation that doesn't require iterating through + * the elements. + */ + int get length; +} + +/** + * An [Iterable] for classes that have efficient [length] and [elementAt]. + * + * All other methods are implemented in terms of [length] and [elementAt], + * including [iterator]. + */ +abstract class ListIterable extends EfficientLengthIterable { + int get length; + E elementAt(int i); + + const ListIterable(); + + Iterator get iterator => new ListIterator(this); + + void forEach(void action(E element)) { + int length = this.length; + for (int i = 0; i < length; i++) { + action(elementAt(i)); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + } + + bool get isEmpty => length == 0; + + E get first { + if (length == 0) throw IterableElementError.noElement(); + return elementAt(0); + } + + E get last { + if (length == 0) throw IterableElementError.noElement(); + return elementAt(length - 1); + } + + E get single { + if (length == 0) throw IterableElementError.noElement(); + if (length > 1) throw IterableElementError.tooMany(); + return elementAt(0); + } + + bool contains(Object element) { + int length = this.length; + for (int i = 0; i < length; i++) { + if (elementAt(i) == element) return true; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return false; + } + + bool every(bool test(E element)) { + int length = this.length; + for (int i = 0; i < length; i++) { + if (!test(elementAt(i))) return false; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return true; + } + + bool any(bool test(E element)) { + int length = this.length; + for (int i = 0; i < length; i++) { + if (test(elementAt(i))) return true; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return false; + } + + E firstWhere(bool test(E element), {E orElse()}) { + int length = this.length; + for (int i = 0; i < length; i++) { + E element = elementAt(i); + if (test(element)) return element; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E lastWhere(bool test(E element), {E orElse()}) { + int length = this.length; + for (int i = length - 1; i >= 0; i--) { + E element = elementAt(i); + if (test(element)) return element; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E singleWhere(bool test(E element), {E orElse()}) { + int length = this.length; + E match = null; + bool matchFound = false; + for (int i = 0; i < length; i++) { + E element = elementAt(i); + if (test(element)) { + if (matchFound) { + throw IterableElementError.tooMany(); + } + matchFound = true; + match = element; + } + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + if (matchFound) return match; + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + String join([String separator = ""]) { + int length = this.length; + if (!separator.isEmpty) { + if (length == 0) return ""; + String first = "${elementAt(0)}"; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + StringBuffer buffer = new StringBuffer(first); + for (int i = 1; i < length; i++) { + buffer.write(separator); + buffer.write(elementAt(i)); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return buffer.toString(); + } else { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + buffer.write(elementAt(i)); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return buffer.toString(); + } + } + + Iterable where(bool test(E element)) => super.where(test); + + Iterable map(T f(E element)) => new MappedListIterable(this, f); + + E reduce(E combine(E value, E element)) { + int length = this.length; + if (length == 0) throw IterableElementError.noElement(); + E value = elementAt(0); + for (int i = 1; i < length; i++) { + value = combine(value, elementAt(i)); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return value; + } + + T fold(T initialValue, T combine(T previousValue, E element)) { + var value = initialValue; + int length = this.length; + for (int i = 0; i < length; i++) { + value = combine(value, elementAt(i)); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return value; + } + + Iterable skip(int count) => new SubListIterable(this, count, null); + + Iterable skipWhile(bool test(E element)) => super.skipWhile(test); + + Iterable take(int count) => new SubListIterable(this, 0, count); + + Iterable takeWhile(bool test(E element)) => super.takeWhile(test); + + List toList({bool growable: true}) { + List result; + if (growable) { + result = []..length = length; + } else { + result = new List(length); + } + for (int i = 0; i < length; i++) { + result[i] = elementAt(i); + } + return result; + } + + Set toSet() { + Set result = new Set(); + for (int i = 0; i < length; i++) { + result.add(elementAt(i)); + } + return result; + } +} + +class SubListIterable extends ListIterable { + final Iterable _iterable; // Has efficient length and elementAt. + final int _start; + /** If null, represents the length of the iterable. */ + final int _endOrLength; + + SubListIterable(this._iterable, this._start, this._endOrLength) { + RangeError.checkNotNegative(_start, "start"); + if (_endOrLength != null) { + RangeError.checkNotNegative(_endOrLength, "end"); + if (_start > _endOrLength) { + throw new RangeError.range(_start, 0, _endOrLength, "start"); + } + } + } + + int get _endIndex { + int length = _iterable.length; + if (_endOrLength == null || _endOrLength > length) return length; + return _endOrLength; + } + + int get _startIndex { + int length = _iterable.length; + if (_start > length) return length; + return _start; + } + + int get length { + int length = _iterable.length; + if (_start >= length) return 0; + if (_endOrLength == null || _endOrLength >= length) { + return length - _start; + } + return _endOrLength - _start; + } + + E elementAt(int index) { + int realIndex = _startIndex + index; + if (index < 0 || realIndex >= _endIndex) { + throw new RangeError.index(index, this, "index"); + } + return _iterable.elementAt(realIndex); + } + + Iterable skip(int count) { + RangeError.checkNotNegative(count, "count"); + int newStart = _start + count; + if (_endOrLength != null && newStart >= _endOrLength) { + return new EmptyIterable(); + } + return new SubListIterable(_iterable, newStart, _endOrLength); + } + + Iterable take(int count) { + RangeError.checkNotNegative(count, "count"); + if (_endOrLength == null) { + return new SubListIterable(_iterable, _start, _start + count); + } else { + int newEnd = _start + count; + if (_endOrLength < newEnd) return this; + return new SubListIterable(_iterable, _start, newEnd); + } + } + + List toList({bool growable: true}) { + int start = _start; + int end = _iterable.length; + if (_endOrLength != null && _endOrLength < end) end = _endOrLength; + int length = end - start; + if (length < 0) length = 0; + List result = + growable ? (new List()..length = length) : new List(length); + for (int i = 0; i < length; i++) { + result[i] = _iterable.elementAt(start + i); + if (_iterable.length < end) throw new ConcurrentModificationError(this); + } + return result; + } +} + +/** + * An [Iterator] that iterates a list-like [Iterable]. + * + * All iterations is done in terms of [Iterable.length] and + * [Iterable.elementAt]. These operations are fast for list-like + * iterables. + */ +class ListIterator implements Iterator { + final Iterable _iterable; + final int _length; + int _index; + E _current; + + ListIterator(Iterable iterable) + : _iterable = iterable, + _length = iterable.length, + _index = 0; + + E get current => _current; + + bool moveNext() { + int length = _iterable.length; + if (_length != length) { + throw new ConcurrentModificationError(_iterable); + } + if (_index >= length) { + _current = null; + return false; + } + _current = _iterable.elementAt(_index); + _index++; + return true; + } +} + +typedef T _Transformation(S value); + +class MappedIterable extends Iterable { + final Iterable _iterable; + final _Transformation _f; + + factory MappedIterable(Iterable iterable, T function(S value)) { + if (iterable is EfficientLengthIterable) { + return new EfficientLengthMappedIterable(iterable, function); + } + return new MappedIterable._(iterable, function); + } + + MappedIterable._(this._iterable, this._f); + + Iterator get iterator => new MappedIterator(_iterable.iterator, _f); + + // Length related functions are independent of the mapping. + int get length => _iterable.length; + bool get isEmpty => _iterable.isEmpty; + + // Index based lookup can be done before transforming. + T get first => _f(_iterable.first); + T get last => _f(_iterable.last); + T get single => _f(_iterable.single); + T elementAt(int index) => _f(_iterable.elementAt(index)); +} + +class EfficientLengthMappedIterable extends MappedIterable + implements EfficientLengthIterable { + EfficientLengthMappedIterable(Iterable iterable, T function(S value)) + : super._(iterable, function); +} + +class MappedIterator extends Iterator { + T _current; + final Iterator _iterator; + final _Transformation _f; + + MappedIterator(this._iterator, this._f); + + bool moveNext() { + if (_iterator.moveNext()) { + _current = _f(_iterator.current); + return true; + } + _current = null; + return false; + } + + T get current => _current; +} + +/** + * Specialized alternative to [MappedIterable] for mapped [List]s. + * + * Expects efficient `length` and `elementAt` on the source iterable. + */ +class MappedListIterable extends ListIterable { + final Iterable _source; + final _Transformation _f; + + MappedListIterable(this._source, this._f); + + int get length => _source.length; + T elementAt(int index) => _f(_source.elementAt(index)); +} + +typedef bool _ElementPredicate(E element); + +class WhereIterable extends Iterable { + final Iterable _iterable; + final _ElementPredicate _f; + + WhereIterable(this._iterable, this._f); + + Iterator get iterator => new WhereIterator(_iterable.iterator, _f); + + // Specialization of [Iterable.map] to non-EfficientLengthIterable. + Iterable map(T f(E element)) => new MappedIterable._(this, f); +} + +class WhereIterator extends Iterator { + final Iterator _iterator; + final _ElementPredicate _f; + + WhereIterator(this._iterator, this._f); + + bool moveNext() { + while (_iterator.moveNext()) { + if (_f(_iterator.current)) { + return true; + } + } + return false; + } + + E get current => _iterator.current; +} + +typedef Iterable _ExpandFunction(S sourceElement); + +class ExpandIterable extends Iterable { + final Iterable _iterable; + final _ExpandFunction _f; + + ExpandIterable(this._iterable, this._f); + + Iterator get iterator => new ExpandIterator(_iterable.iterator, _f); +} + +class ExpandIterator implements Iterator { + final Iterator _iterator; + final _ExpandFunction _f; + // Initialize _currentExpansion to an empty iterable. A null value + // marks the end of iteration, and we don't want to call _f before + // the first moveNext call. + Iterator _currentExpansion = const EmptyIterator(); + T _current; + + ExpandIterator(this._iterator, this._f); + + T get current => _current; + + bool moveNext() { + if (_currentExpansion == null) return false; + while (!_currentExpansion.moveNext()) { + _current = null; + if (_iterator.moveNext()) { + // If _f throws, this ends iteration. Otherwise _currentExpansion and + // _current will be set again below. + _currentExpansion = null; + _currentExpansion = _f(_iterator.current).iterator; + } else { + return false; + } + } + _current = _currentExpansion.current; + return true; + } +} + +class TakeIterable extends Iterable { + final Iterable _iterable; + final int _takeCount; + + factory TakeIterable(Iterable iterable, int takeCount) { + if (takeCount is! int || takeCount < 0) { + throw new ArgumentError(takeCount); + } + if (iterable is EfficientLengthIterable) { + return new EfficientLengthTakeIterable(iterable, takeCount); + } + return new TakeIterable._(iterable, takeCount); + } + + TakeIterable._(this._iterable, this._takeCount); + + Iterator get iterator { + return new TakeIterator(_iterable.iterator, _takeCount); + } +} + +class EfficientLengthTakeIterable extends TakeIterable + implements EfficientLengthIterable { + EfficientLengthTakeIterable(Iterable iterable, int takeCount) + : super._(iterable, takeCount); + + int get length { + int iterableLength = _iterable.length; + if (iterableLength > _takeCount) return _takeCount; + return iterableLength; + } +} + +class TakeIterator extends Iterator { + final Iterator _iterator; + int _remaining; + + TakeIterator(this._iterator, this._remaining) { + assert(_remaining is int && _remaining >= 0); + } + + bool moveNext() { + _remaining--; + if (_remaining >= 0) { + return _iterator.moveNext(); + } + _remaining = -1; + return false; + } + + E get current { + if (_remaining < 0) return null; + return _iterator.current; + } +} + +class TakeWhileIterable extends Iterable { + final Iterable _iterable; + final _ElementPredicate _f; + + TakeWhileIterable(this._iterable, this._f); + + Iterator get iterator { + return new TakeWhileIterator(_iterable.iterator, _f); + } +} + +class TakeWhileIterator extends Iterator { + final Iterator _iterator; + final _ElementPredicate _f; + bool _isFinished = false; + + TakeWhileIterator(this._iterator, this._f); + + bool moveNext() { + if (_isFinished) return false; + if (!_iterator.moveNext() || !_f(_iterator.current)) { + _isFinished = true; + return false; + } + return true; + } + + E get current { + if (_isFinished) return null; + return _iterator.current; + } +} + +class SkipIterable extends Iterable { + final Iterable _iterable; + final int _skipCount; + + factory SkipIterable(Iterable iterable, int count) { + if (iterable is EfficientLengthIterable) { + return new EfficientLengthSkipIterable(iterable, count); + } + return new SkipIterable._(iterable, _checkCount(count)); + } + + SkipIterable._(this._iterable, this._skipCount); + + Iterable skip(int count) { + return new SkipIterable._(_iterable, _skipCount + _checkCount(count)); + } + + Iterator get iterator { + return new SkipIterator(_iterable.iterator, _skipCount); + } +} + +class EfficientLengthSkipIterable extends SkipIterable + implements EfficientLengthIterable { + factory EfficientLengthSkipIterable(Iterable iterable, int count) { + return new EfficientLengthSkipIterable._(iterable, _checkCount(count)); + } + + EfficientLengthSkipIterable._(Iterable iterable, int count) + : super._(iterable, count); + + int get length { + int length = _iterable.length - _skipCount; + if (length >= 0) return length; + return 0; + } + + Iterable skip(int count) { + return new EfficientLengthSkipIterable._( + _iterable, _skipCount + _checkCount(count)); + } +} + +int _checkCount(int count) { + if (count is! int) { + throw new ArgumentError.value(count, "count", "is not an integer"); + } + RangeError.checkNotNegative(count, "count"); + return count; +} + +class SkipIterator extends Iterator { + final Iterator _iterator; + int _skipCount; + + SkipIterator(this._iterator, this._skipCount) { + assert(_skipCount is int && _skipCount >= 0); + } + + bool moveNext() { + for (int i = 0; i < _skipCount; i++) _iterator.moveNext(); + _skipCount = 0; + return _iterator.moveNext(); + } + + E get current => _iterator.current; +} + +class SkipWhileIterable extends Iterable { + final Iterable _iterable; + final _ElementPredicate _f; + + SkipWhileIterable(this._iterable, this._f); + + Iterator get iterator { + return new SkipWhileIterator(_iterable.iterator, _f); + } +} + +class SkipWhileIterator extends Iterator { + final Iterator _iterator; + final _ElementPredicate _f; + bool _hasSkipped = false; + + SkipWhileIterator(this._iterator, this._f); + + bool moveNext() { + if (!_hasSkipped) { + _hasSkipped = true; + while (_iterator.moveNext()) { + if (!_f(_iterator.current)) return true; + } + } + return _iterator.moveNext(); + } + + E get current => _iterator.current; +} + +/** + * The always empty [Iterable]. + */ +class EmptyIterable extends EfficientLengthIterable { + const EmptyIterable(); + + Iterator get iterator => const EmptyIterator(); + + void forEach(void action(E element)) {} + + bool get isEmpty => true; + + int get length => 0; + + E get first { + throw IterableElementError.noElement(); + } + + E get last { + throw IterableElementError.noElement(); + } + + E get single { + throw IterableElementError.noElement(); + } + + E elementAt(int index) { + throw new RangeError.range(index, 0, 0, "index"); + } + + bool contains(Object element) => false; + + bool every(bool test(E element)) => true; + + bool any(bool test(E element)) => false; + + E firstWhere(bool test(E element), {E orElse()}) { + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E lastWhere(bool test(E element), {E orElse()}) { + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E singleWhere(bool test(E element), {E orElse()}) { + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + String join([String separator = ""]) => ""; + + Iterable where(bool test(E element)) => this; + + Iterable map(T f(E element)) => new EmptyIterable(); + + E reduce(E combine(E value, E element)) { + throw IterableElementError.noElement(); + } + + T fold(T initialValue, T combine(T previousValue, E element)) { + return initialValue; + } + + Iterable skip(int count) { + RangeError.checkNotNegative(count, "count"); + return this; + } + + Iterable skipWhile(bool test(E element)) => this; + + Iterable take(int count) { + RangeError.checkNotNegative(count, "count"); + return this; + } + + Iterable takeWhile(bool test(E element)) => this; + + List toList({bool growable: true}) => growable ? [] : new List(0); + + Set toSet() => new Set(); +} + +/** The always empty iterator. */ +class EmptyIterator implements Iterator { + const EmptyIterator(); + bool moveNext() => false; + E get current => null; +} + +class FollowedByIterable extends Iterable { + final Iterable _first; + final Iterable _second; + FollowedByIterable(this._first, this._second); + + factory FollowedByIterable.firstEfficient( + EfficientLengthIterable first, Iterable second) { + if (second is EfficientLengthIterable) { + return new EfficientLengthFollowedByIterable(first, second); + } + return new FollowedByIterable(first, second); + } + + Iterator get iterator => new FollowedByIterator(_first, _second); + + int get length => _first.length + _second.length; + bool get isEmpty => _first.isEmpty && _second.isEmpty; + bool get isNotEmpty => _first.isNotEmpty || _second.isNotEmpty; + + // May be more efficient if either iterable is a Set. + bool contains(Object value) => + _first.contains(value) || _second.contains(value); + + E get first { + var iterator = _first.iterator; + if (iterator.moveNext()) return iterator.current; + return _second.first; + } + + E get last { + var iterator = _second.iterator; + if (iterator.moveNext()) { + E last = iterator.current; + while (iterator.moveNext()) last = iterator.current; + return last; + } + return _first.last; + } + + // If linear sequences of `followedBy` becomes an issue, we can flatten + // into a list of iterables instead of a tree or spine. +} + +class EfficientLengthFollowedByIterable extends FollowedByIterable + implements EfficientLengthIterable { + EfficientLengthFollowedByIterable( + EfficientLengthIterable first, EfficientLengthIterable second) + : super(first, second); + + Iterable skip(int count) { + int firstLength = _first.length; + if (count >= firstLength) return _second.skip(count - firstLength); + return new EfficientLengthFollowedByIterable( + _first.skip(count), _second); + } + + Iterable take(int count) { + int firstLength = _first.length; + if (count <= firstLength) return _first.take(count); + return new EfficientLengthFollowedByIterable( + _first, _second.take(count - firstLength)); + } + + E elementAt(int index) { + int firstLength = _first.length; + if (index < firstLength) return _first.elementAt(index); + return _second.elementAt(index - firstLength); + } + + E get first { + if (_first.isNotEmpty) return _first.first; + return _second.first; + } + + E get last { + if (_second.isNotEmpty) return _second.last; + return _first.last; + } +} + +class FollowedByIterator implements Iterator { + Iterator _currentIterator; + Iterable _nextIterable; + + FollowedByIterator(Iterable first, this._nextIterable) + : _currentIterator = first.iterator; + + bool moveNext() { + if (_currentIterator.moveNext()) return true; + if (_nextIterable != null) { + _currentIterator = _nextIterable.iterator; + _nextIterable = null; + return _currentIterator.moveNext(); + } + return false; + } + + E get current => _currentIterator.current; +} + +class WhereTypeIterable extends Iterable { + final Iterable _source; + WhereTypeIterable(this._source); + Iterator get iterator => new WhereTypeIterator(_source.iterator); +} + +class WhereTypeIterator implements Iterator { + final Iterator _source; + WhereTypeIterator(this._source); + bool moveNext() { + while (_source.moveNext()) { + if (_source.current is T) return true; + } + return false; + } + + T get current => _source.current; +} + +/** + * Creates errors throw by [Iterable] when the element count is wrong. + */ +abstract class IterableElementError { + /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ + static StateError noElement() => new StateError("No element"); + /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ + static StateError tooMany() => new StateError("Too many elements"); + /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ + static StateError tooFew() => new StateError("Too few elements"); +} +NN<E@#5KKKD9)'#5#=="=:"'0#5%'-#5#'+#55' )#5),4, )#5),6' 0 +#5"),)"(#55)!$%7 + 0)$%7 + @O,=',#5E',#5LHIH*' $' "' 3F9D2 8#F#F#(#$:")/8+ 1#<%F 1 H #.@* H K'2O7&)9&$(<G,K%1"+ (CF9"-$:.-!*LFM-!*##&<1"+P4"EE9+1,"N-"<*,>.*/F73@=,C&+8,22#%1!.=1!.#;",:/B@3 N@=,IOA"0$ 15H/,22?!&1!.=1!.%1!& <5*,,,6*,+5),4),6),.3@,,E 17 17N""021->0F5G49B8!9$6%!;J:I,%K %H5& %954%=3015 <+2!1*-1"#J4"#!-$G&QAQFODTfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/async_cast.dart`// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +// Casting wrappers for asynchronous classes. + +class CastStream extends Stream { + final Stream _source; + CastStream(this._source); + bool get isBroadcast => _source.isBroadcast; + + StreamSubscription listen(void onData(T data), + {Function onError, void onDone(), bool cancelOnError}) { + return new CastStreamSubscription( + _source.listen(null, onDone: onDone, cancelOnError: cancelOnError)) + ..onData(onData) + ..onError(onError); + } + + Stream cast() => new CastStream(_source); +} + +class CastStreamSubscription implements StreamSubscription { + final StreamSubscription _source; + + /// Zone where listen was called. + final Zone _zone = Zone.current; + + /// User's data handler. May be null. + void Function(T) _handleData; + + /// Copy of _source's handleError so we can report errors in onData. + /// May be null. + Function _handleError; + + CastStreamSubscription(this._source) { + _source.onData(_onData); + } + + Future cancel() => _source.cancel(); + + void onData(void handleData(T data)) { + _handleData = handleData == null + ? null + : _zone.registerUnaryCallback(handleData); + } + + void onError(Function handleError) { + _source.onError(handleError); + if (handleError == null) { + _handleError = null; + } else if (handleError is Function(Null, Null)) { + _handleError = _zone + .registerBinaryCallback(handleError); + } else { + _handleError = _zone.registerUnaryCallback(handleError); + } + } + + void onDone(void handleDone()) { + _source.onDone(handleDone); + } + + void _onData(S data) { + if (_handleData == null) return; + T targetData; + try { + targetData = data as T; + } catch (error, stack) { + if (_handleError == null) { + _zone.handleUncaughtError(error, stack); + } else if (_handleError is Function(Null, Null)) { + _zone.runBinaryGuarded(_handleError, error, stack); + } else { + _zone.runUnaryGuarded(_handleError, error); + } + return; + } + _zone.runUnaryGuarded(_handleData, targetData); + } + + void pause([Future resumeSignal]) { + _source.pause(resumeSignal); + } + + void resume() { + _source.resume(); + } + + bool get isPaused => _source.isPaused; + + Future asFuture([E futureValue]) => _source.asFuture(futureValue); +} + +class CastStreamTransformer + extends StreamTransformerBase { + final StreamTransformer _source; + CastStreamTransformer(this._source); + + StreamTransformer cast() => + new CastStreamTransformer(_source); + Stream bind(Stream stream) => + _source.bind(stream.cast()).cast(); +} + +class CastConverter extends Converter { + final Converter _source; + CastConverter(this._source); + + TT convert(TS input) => _source.convert(input as SS) as TT; + + // cast is inherited from Converter. + + Stream bind(Stream stream) => + _source.bind(stream.cast()).cast(); + + Converter cast() => + new CastConverter(_source); +} +{NN<.+/4?-L8F'$#( G)')%?'"6M P# % +"19<44&!)N,,+'.:(2@#>'(2&2Nfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/cast.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +// Casting wrappers for collection classes. + +abstract class _CastIterableBase extends Iterable { + Iterable get _source; + + Iterator get iterator => new CastIterator(_source.iterator); + + // The following members use the default implementation on the + // throwing iterator. These are all operations that have no more efficient + // implementation than visiting every element in order, + // or that has no more efficient way to get the correct type (toList, toSet). + // + // * map + // * where + // * expand + // * forEach + // * reduce + // * fold + // * every + // * any + // * join + // * toList + // * toSet + // * skipWhile + // * takeWhile + // * firstWhere + // * singleWhere + + int get length => _source.length; + bool get isEmpty => _source.isEmpty; + bool get isNotEmpty => _source.isNotEmpty; + + Iterable skip(int count) => new CastIterable(_source.skip(count)); + Iterable take(int count) => new CastIterable(_source.take(count)); + + T elementAt(int index) => _source.elementAt(index) as T; + T get first => _source.first as T; + T get last => _source.last as T; + T get single => _source.single as T; + + bool contains(Object other) => _source.contains(other); + + // Might be implemented by testing backwards from the end, + // so use the _source's implementation. + T lastWhere(bool test(T element), {T orElse()}) => + _source.lastWhere((S element) => test(element as T), + orElse: (orElse == null) ? null : () => orElse() as S) as T; + + String toString() => _source.toString(); +} + +class CastIterator implements Iterator { + Iterator _source; + CastIterator(this._source); + bool moveNext() => _source.moveNext(); + T get current => _source.current as T; +} + +class CastIterable extends _CastIterableBase { + final Iterable _source; + + CastIterable._(this._source); + + factory CastIterable(Iterable source) { + if (source is EfficientLengthIterable) { + return new _EfficientLengthCastIterable(source); + } + return new CastIterable._(source); + } + + Iterable cast() => new CastIterable(_source); +} + +class _EfficientLengthCastIterable extends CastIterable + implements EfficientLengthIterable { + _EfficientLengthCastIterable(EfficientLengthIterable source) + : super._(source); +} + +abstract class _CastListBase extends _CastIterableBase + with ListMixin { + List get _source; + + // Using the default implementation from ListMixin: + // * reversed + // * shuffle + // * indexOf + // * lastIndexOf + // * clear + // * sublist + // * asMap + + T operator [](int index) => _source[index] as T; + + void operator []=(int index, T value) { + _source[index] = value as S; + } + + void set length(int length) { + _source.length = length; + } + + void add(T value) { + _source.add(value as S); + } + + void addAll(Iterable values) { + _source.addAll(new CastIterable(values)); + } + + void sort([int compare(T v1, T v2)]) { + _source.sort( + compare == null ? null : (S v1, S v2) => compare(v1 as T, v2 as T)); + } + + void shuffle([Random random]) { + _source.shuffle(random); + } + + void insert(int index, T element) { + _source.insert(index, element as S); + } + + void insertAll(int index, Iterable elements) { + _source.insertAll(index, new CastIterable(elements)); + } + + void setAll(int index, Iterable elements) { + _source.setAll(index, new CastIterable(elements)); + } + + bool remove(Object value) => _source.remove(value); + + T removeAt(int index) => _source.removeAt(index) as T; + + T removeLast() => _source.removeLast() as T; + + void removeWhere(bool test(T element)) { + _source.removeWhere((S element) => test(element as T)); + } + + void retainWhere(bool test(T element)) { + _source.retainWhere((S element) => test(element as T)); + } + + Iterable getRange(int start, int end) => + new CastIterable(_source.getRange(start, end)); + + void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { + _source.setRange(start, end, new CastIterable(iterable), skipCount); + } + + void removeRange(int start, int end) { + _source.removeRange(start, end); + } + + void fillRange(int start, int end, [T fillValue]) { + _source.fillRange(start, end, fillValue as S); + } + + void replaceRange(int start, int end, Iterable replacement) { + _source.replaceRange(start, end, new CastIterable(replacement)); + } +} + +class CastList extends _CastListBase { + final List _source; + CastList(this._source); + + List cast() => new CastList(_source); +} + +class CastSet extends _CastIterableBase implements Set { + final Set _source; + + /// Creates a new empty set of the same *kind* as [_source], + /// but with `` as type argument. + /// Used by [toSet] and [union]. + final Set Function() _emptySet; + + CastSet(this._source, this._emptySet); + + static Set _defaultEmptySet() => new Set(); + + Set cast() => new CastSet(_source, _emptySet); + bool add(T value) => _source.add(value as S); + + void addAll(Iterable elements) { + _source.addAll(new CastIterable(elements)); + } + + bool remove(Object object) => _source.remove(object); + + void removeAll(Iterable objects) { + _source.removeAll(objects); + } + + void retainAll(Iterable objects) { + _source.retainAll(objects); + } + + void removeWhere(bool test(T element)) { + _source.removeWhere((S element) => test(element as T)); + } + + void retainWhere(bool test(T element)) { + _source.retainWhere((S element) => test(element as T)); + } + + bool containsAll(Iterable objects) => _source.containsAll(objects); + + Set intersection(Set other) { + if (_emptySet != null) return _conditionalAdd(other, true); + return new CastSet(_source.intersection(other), null); + } + + Set difference(Set other) { + if (_emptySet != null) return _conditionalAdd(other, false); + return new CastSet(_source.difference(other), null); + } + + Set _conditionalAdd(Set other, bool otherContains) { + Set result = (_emptySet == null) ? new Set() : _emptySet(); + for (var element in _source) { + T castElement = element as T; + if (otherContains == other.contains(castElement)) result.add(castElement); + } + return result; + } + + Set union(Set other) => _clone()..addAll(other); + + void clear() { + _source.clear(); + } + + Set _clone() { + Set result = (_emptySet == null) ? new Set() : _emptySet(); + result.addAll(this); + return result; + } + + Set toSet() => _clone(); + + T lookup(Object key) => _source.lookup(key) as T; +} + +abstract class _CastQueueMixin implements Queue { + Queue get _source; + + T removeFirst() => _source.removeFirst() as T; + T removeLast() => _source.removeLast() as T; + + @deprecated + void add(T value) { + _source.add(value as S); + } + + void addFirst(T value) { + _source.addFirst(value as S); + } + + void addLast(T value) { + _source.addLast(value as S); + } + + bool remove(Object other) => _source.remove(other); + void addAll(Iterable elements) { + _source.addAll(new CastIterable(elements)); + } + + void removeWhere(bool test(T element)) { + _source.removeWhere((S element) => test(element as T)); + } + + void retainWhere(bool test(T element)) { + _source.retainWhere((S element) => test(element as T)); + } + + void clear() { + _source.clear(); + } +} + +class CastMap extends MapBase { + final Map _source; + + CastMap(this._source); + + Map cast() => new CastMap(_source); + + bool containsValue(Object value) => _source.containsValue(value); + + bool containsKey(Object key) => _source.containsKey(key); + + V operator [](Object key) => _source[key] as V; + + void operator []=(K key, V value) { + _source[key as SK] = value as SV; + } + + V putIfAbsent(K key, V ifAbsent()) => _source.putIfAbsent( + key as SK, (ifAbsent == null) ? null : () => ifAbsent() as SV) as V; + + void addAll(Map other) { + _source.addAll(new CastMap(other)); + } + + V remove(Object key) => _source.remove(key) as V; + + void clear() { + _source.clear(); + } + + void forEach(void f(K key, V value)) { + _source.forEach((SK key, SV value) { + f(key as K, value as V); + }); + } + + Iterable get keys => new CastIterable(_source.keys); + + Iterable get values => new CastIterable(_source.values); + + int get length => _source.length; + + bool get isEmpty => _source.isEmpty; + + bool get isNotEmpty => _source.isNotEmpty; + + V update(K key, V update(V value), {V ifAbsent()}) { + return _source.update(key as SK, (SV value) => update(value as V) as SV, + ifAbsent: (ifAbsent == null) ? null : () => ifAbsent() as SV) as V; + } + + void updateAll(V update(K key, V value)) { + _source.updateAll((SK key, SV value) => update(key as K, value as V) as SV); + } + + Iterable> get entries { + return _source.entries.map>( + (MapEntry e) => new MapEntry(e.key as K, e.value as V)); + } + + void addEntries(Iterable> entries) { + for (var entry in entries) { + _source[entry.key as SK] = entry.value as SV; + } + } + + void removeWhere(bool test(K key, V value)) { + _source.removeWhere((SK key, SV value) => test(key as K, value as V)); + } +} + +class CastQueue extends _CastIterableBase + with _CastQueueMixin { + final Queue _source; + CastQueue(this._source); + Queue cast() => new CastQueue(_source); +} + +// TODO(lrn): Use when ListQueue implements List. +// class CastListQueue +// extends _CastListBase with _CastQueueMixin +// implements ListQueue { +// final ListQueue _source; +// CastListQueue(this._source); +// ListQueue cast() => new CastListQueue(_source); +// } +zNN<,=HAM:P   $'-NN;%#':=*5;G+2)); -0=-<D,BC6  3*! $4)M"&)4@1=69/+<+<.<QO)%63CK34H?'#()7=0&68- - +<+<N+@A)A?BI#$Q9I4;1/"!6&6+<+<4FD<2&&=K!64))AE$'-7ML-Q)0O6!40K6!62>!!"ANfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/list.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +/** + * Mixin that throws on the length changing operations of [List]. + * + * Intended to mix-in on top of [ListMixin] for fixed-length lists. + */ +abstract class FixedLengthListMixin { + /** This operation is not supported by a fixed length list. */ + set length(int newLength) { + throw new UnsupportedError( + "Cannot change the length of a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void add(E value) { + throw new UnsupportedError("Cannot add to a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void insert(int index, E value) { + throw new UnsupportedError("Cannot add to a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void insertAll(int at, Iterable iterable) { + throw new UnsupportedError("Cannot add to a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void addAll(Iterable iterable) { + throw new UnsupportedError("Cannot add to a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + bool remove(Object element) { + throw new UnsupportedError("Cannot remove from a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void removeWhere(bool test(E element)) { + throw new UnsupportedError("Cannot remove from a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void retainWhere(bool test(E element)) { + throw new UnsupportedError("Cannot remove from a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void clear() { + throw new UnsupportedError("Cannot clear a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + E removeAt(int index) { + throw new UnsupportedError("Cannot remove from a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + E removeLast() { + throw new UnsupportedError("Cannot remove from a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void removeRange(int start, int end) { + throw new UnsupportedError("Cannot remove from a fixed-length list"); + } + + /** This operation is not supported by a fixed length list. */ + void replaceRange(int start, int end, Iterable iterable) { + throw new UnsupportedError("Cannot remove from a fixed-length list"); + } +} + +/** + * Mixin for an unmodifiable [List] class. + * + * This overrides all mutating methods with methods that throw. + * This mixin is intended to be mixed in on top of [ListMixin] on + * unmodifiable lists. + */ +abstract class UnmodifiableListMixin implements List { + /** This operation is not supported by an unmodifiable list. */ + void operator []=(int index, E value) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + set length(int newLength) { + throw new UnsupportedError( + "Cannot change the length of an unmodifiable list"); + } + + set first(E element) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } + + set last(E element) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void setAll(int at, Iterable iterable) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void add(E value) { + throw new UnsupportedError("Cannot add to an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void insert(int index, E element) { + throw new UnsupportedError("Cannot add to an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void insertAll(int at, Iterable iterable) { + throw new UnsupportedError("Cannot add to an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void addAll(Iterable iterable) { + throw new UnsupportedError("Cannot add to an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + bool remove(Object element) { + throw new UnsupportedError("Cannot remove from an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void removeWhere(bool test(E element)) { + throw new UnsupportedError("Cannot remove from an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void retainWhere(bool test(E element)) { + throw new UnsupportedError("Cannot remove from an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void sort([Comparator compare]) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void shuffle([Random random]) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void clear() { + throw new UnsupportedError("Cannot clear an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + E removeAt(int index) { + throw new UnsupportedError("Cannot remove from an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + E removeLast() { + throw new UnsupportedError("Cannot remove from an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void removeRange(int start, int end) { + throw new UnsupportedError("Cannot remove from an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void replaceRange(int start, int end, Iterable iterable) { + throw new UnsupportedError("Cannot remove from an unmodifiable list"); + } + + /** This operation is not supported by an unmodifiable list. */ + void fillRange(int start, int end, [E fillValue]) { + throw new UnsupportedError("Cannot modify an unmodifiable list"); + } +} + +/** + * Abstract implementation of a fixed-length list. + * + * All operations are defined in terms of `length`, `operator[]` and + * `operator[]=`, which need to be implemented. + */ +abstract class FixedLengthListBase = ListBase + with FixedLengthListMixin; + +/** + * Abstract implementation of an unmodifiable list. + * + * All operations are defined in terms of `length` and `operator[]`, + * which need to be implemented. + */ +abstract class UnmodifiableListBase = ListBase + with UnmodifiableListMixin; + +class _ListIndicesIterable extends ListIterable { + List _backedList; + + _ListIndicesIterable(this._backedList); + + int get length => _backedList.length; + int elementAt(int index) { + RangeError.checkValidIndex(index, this); + return index; + } +} + +class ListMapView extends UnmodifiableMapBase { + List _values; + + ListMapView(this._values); + + E operator [](Object key) => containsKey(key) ? _values[key] : null; + int get length => _values.length; + + Iterable get values => new SubListIterable(_values, 0, null); + Iterable get keys => new _ListIndicesIterable(_values); + + bool get isEmpty => _values.isEmpty; + bool get isNotEmpty => _values.isNotEmpty; + bool containsValue(Object value) => _values.contains(value); + bool containsKey(Object key) => key is int && key >= 0 && key < length; + + void forEach(void f(int key, E value)) { + int length = _values.length; + for (int i = 0; i < length; i++) { + f(i, _values[i]); + if (length != _values.length) { + throw new ConcurrentModificationError(_values); + } + } + } +} + +class ReversedListIterable extends ListIterable { + Iterable _source; + ReversedListIterable(this._source); + + int get length => _source.length; + + E elementAt(int index) => _source.elementAt(_source.length - 1 - index); +} + +/** + * Creates errors thrown by unmodifiable lists when they are attempted modified. + * + * This class creates [UnsupportedError]s with specialized messages. + */ +abstract class UnmodifiableListError { + /** Error thrown when trying to add elements to an unmodifiable list. */ + static UnsupportedError add() => + new UnsupportedError("Cannot add to unmodifiable List"); + + /** Error thrown when trying to add elements to an unmodifiable list. */ + static UnsupportedError change() => + new UnsupportedError("Cannot change the content of an unmodifiable List"); + + /** Error thrown when trying to change the length of an unmodifiable list. */ + static UnsupportedError length() => + new UnsupportedError("Cannot change length of unmodifiable List"); + + /** Error thrown when trying to remove elements from an unmodifiable list. */ + static UnsupportedError remove() => + new UnsupportedError("Cannot remove from unmodifiable List"); +} + +/** + * Creates errors thrown by non-growable lists when they are attempted modified. + * + * This class creates [UnsupportedError]s with specialized messages. + */ +abstract class NonGrowableListError { + /** Error thrown when trying to add elements to an non-growable list. */ + static UnsupportedError add() => + new UnsupportedError("Cannot add to non-growable List"); + + /** Error thrown when trying to change the length of an non-growable list. */ + static UnsupportedError length() => + new UnsupportedError("Cannot change length of non-growable List"); + + /** Error thrown when trying to remove elements from an non-growable list. */ + static UnsupportedError remove() => + new UnsupportedError("Cannot remove from non-growable List"); +} + +/** + * Converts a growable list to a fixed length list with the same elements. + * + * For internal use only. + * Only works on growable lists as created by `[]` or `new List()`. + * May throw on any other list. + * + * The operation is efficient. It doesn't copy the elements, but converts + * the existing list directly to a fixed length list. + * That means that it is a destructive conversion. + * The original list should not be used afterwards. + * + * The returned list may be the same list as the original, + * or it may be a different list (according to [identical]). + * The original list may have changed type to be a fixed list, + * or become empty or been otherwise modified. + * It will still be a valid object, so references to it will not, e.g., crash + * the runtime if accessed, but no promises are made wrt. its contents. + * + * This unspecified behavior is the reason the function is not exposed to + * users. We allow the underlying implementation to make the most efficient + * conversion, at the cost of leaving the original list in an unspecified + * state. + */ +external List makeListFixedLength(List growableList); + +/** + * Converts a fixed-length list to an unmodifiable list. + * + * For internal use only. + * Only works for core fixed-length lists as created by `new List(length)`, + * or as returned by [makeListFixedLength]. + * + * The operation is efficient. It doesn't copy the elements, but converts + * the existing list directly to a fixed length list. + * That means that it is a destructive conversion. + * The original list should not be used afterwards. + * + * The unmodifiable list type is similar to the one used by const lists. + */ +external List makeFixedListUnmodifiable(List fixedLengthList); +WNN<BD)A <AEA$EA1EA&EA JA+JA+JADAJAJA)JA@J+@B=B*FB =FFB.FBFB&FB1FB&FB KB+KB+KB'FB"FBEBKBKBQFB)KB@KB6F3E04"4E!5#7*(-;G$F?'-?J+!'&88&$KQE'K#?K&QP&IP&DQE&K#?P&IP&DKD J634;=?/NHJLJ +?9L,J634IHNfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/sort.dart// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +/** + * Dual-Pivot Quicksort algorithm. + * + * This class implements the dual-pivot quicksort algorithm as presented in + * Vladimir Yaroslavskiy's paper. + * + * Some improvements have been copied from Android's implementation. + */ +class Sort { + // When a list has less then [:_INSERTION_SORT_THRESHOLD:] elements it will + // be sorted by an insertion sort. + static const int _INSERTION_SORT_THRESHOLD = 32; + + /** + * Sorts all elements of the given list [:a:] according to the given + * [:compare:] function. + * + * The [:compare:] function takes two arguments [:x:] and [:y:] and returns + * -1 if [:x < y:], + * 0 if [:x == y:], and + * 1 if [:x > y:]. + * + * The function's behavior must be consistent. It must not return different + * results for the same values. + */ + static void sort(List a, int compare(E a, E b)) { + _doSort(a, 0, a.length - 1, compare); + } + + /** + * Sorts all elements in the range [:from:] (inclusive) to [:to:] (exclusive) + * of the given list [:a:]. + * + * If the given range is invalid an "OutOfRange" error is raised. + * TODO(floitsch): do we want an error? + * + * See [:sort:] for requirements of the [:compare:] function. + */ + static void sortRange(List a, int from, int to, int compare(E a, E b)) { + if ((from < 0) || (to > a.length) || (to < from)) { + throw "OutOfRange"; + } + _doSort(a, from, to - 1, compare); + } + + /** + * Sorts the list in the interval [:left:] to [:right:] (both inclusive). + */ + static void _doSort( + List a, int left, int right, int compare(E a, E b)) { + if ((right - left) <= _INSERTION_SORT_THRESHOLD) { + _insertionSort(a, left, right, compare); + } else { + _dualPivotQuicksort(a, left, right, compare); + } + } + + static void _insertionSort( + List a, int left, int right, int compare(E a, E b)) { + for (int i = left + 1; i <= right; i++) { + var el = a[i]; + int j = i; + while ((j > left) && (compare(a[j - 1], el) > 0)) { + a[j] = a[j - 1]; + j--; + } + a[j] = el; + } + } + + static void _dualPivotQuicksort( + List a, int left, int right, int compare(E a, E b)) { + assert(right - left > _INSERTION_SORT_THRESHOLD); + + // Compute the two pivots by looking at 5 elements. + int sixth = (right - left + 1) ~/ 6; + int index1 = left + sixth; + int index5 = right - sixth; + int index3 = (left + right) ~/ 2; // The midpoint. + int index2 = index3 - sixth; + int index4 = index3 + sixth; + + var el1 = a[index1]; + var el2 = a[index2]; + var el3 = a[index3]; + var el4 = a[index4]; + var el5 = a[index5]; + + // Sort the selected 5 elements using a sorting network. + if (compare(el1, el2) > 0) { + var t = el1; + el1 = el2; + el2 = t; + } + if (compare(el4, el5) > 0) { + var t = el4; + el4 = el5; + el5 = t; + } + if (compare(el1, el3) > 0) { + var t = el1; + el1 = el3; + el3 = t; + } + if (compare(el2, el3) > 0) { + var t = el2; + el2 = el3; + el3 = t; + } + if (compare(el1, el4) > 0) { + var t = el1; + el1 = el4; + el4 = t; + } + if (compare(el3, el4) > 0) { + var t = el3; + el3 = el4; + el4 = t; + } + if (compare(el2, el5) > 0) { + var t = el2; + el2 = el5; + el5 = t; + } + if (compare(el2, el3) > 0) { + var t = el2; + el2 = el3; + el3 = t; + } + if (compare(el4, el5) > 0) { + var t = el4; + el4 = el5; + el5 = t; + } + + var pivot1 = el2; + var pivot2 = el4; + + // el2 and el4 have been saved in the pivot variables. They will be written + // back, once the partitioning is finished. + a[index1] = el1; + a[index3] = el3; + a[index5] = el5; + + a[index2] = a[left]; + a[index4] = a[right]; + + int less = left + 1; // First element in the middle partition. + int great = right - 1; // Last element in the middle partition. + + bool pivots_are_equal = (compare(pivot1, pivot2) == 0); + if (pivots_are_equal) { + var pivot = pivot1; + // Degenerated case where the partitioning becomes a Dutch national flag + // problem. + // + // [ | < pivot | == pivot | unpartitioned | > pivot | ] + // ^ ^ ^ ^ ^ + // left less k great right + // + // a[left] and a[right] are undefined and are filled after the + // partitioning. + // + // Invariants: + // 1) for x in ]left, less[ : x < pivot. + // 2) for x in [less, k[ : x == pivot. + // 3) for x in ]great, right[ : x > pivot. + for (int k = less; k <= great; k++) { + var ak = a[k]; + int comp = compare(ak, pivot); + if (comp == 0) continue; + if (comp < 0) { + if (k != less) { + a[k] = a[less]; + a[less] = ak; + } + less++; + } else { + // comp > 0. + // + // Find the first element <= pivot in the range [k - 1, great] and + // put [:ak:] there. We know that such an element must exist: + // When k == less, then el3 (which is equal to pivot) lies in the + // interval. Otherwise a[k - 1] == pivot and the search stops at k-1. + // Note that in the latter case invariant 2 will be violated for a + // short amount of time. The invariant will be restored when the + // pivots are put into their final positions. + while (true) { + comp = compare(a[great], pivot); + if (comp > 0) { + great--; + // This is the only location in the while-loop where a new + // iteration is started. + continue; + } else if (comp < 0) { + // Triple exchange. + a[k] = a[less]; + a[less++] = a[great]; + a[great--] = ak; + break; + } else { + // comp == 0; + a[k] = a[great]; + a[great--] = ak; + // Note: if great < k then we will exit the outer loop and fix + // invariant 2 (which we just violated). + break; + } + } + } + } + } else { + // We partition the list into three parts: + // 1. < pivot1 + // 2. >= pivot1 && <= pivot2 + // 3. > pivot2 + // + // During the loop we have: + // [ | < pivot1 | >= pivot1 && <= pivot2 | unpartitioned | > pivot2 | ] + // ^ ^ ^ ^ ^ + // left less k great right + // + // a[left] and a[right] are undefined and are filled after the + // partitioning. + // + // Invariants: + // 1. for x in ]left, less[ : x < pivot1 + // 2. for x in [less, k[ : pivot1 <= x && x <= pivot2 + // 3. for x in ]great, right[ : x > pivot2 + for (int k = less; k <= great; k++) { + var ak = a[k]; + int comp_pivot1 = compare(ak, pivot1); + if (comp_pivot1 < 0) { + if (k != less) { + a[k] = a[less]; + a[less] = ak; + } + less++; + } else { + int comp_pivot2 = compare(ak, pivot2); + if (comp_pivot2 > 0) { + while (true) { + int comp = compare(a[great], pivot2); + if (comp > 0) { + great--; + if (great < k) break; + // This is the only location inside the loop where a new + // iteration is started. + continue; + } else { + // a[great] <= pivot2. + comp = compare(a[great], pivot1); + if (comp < 0) { + // Triple exchange. + a[k] = a[less]; + a[less++] = a[great]; + a[great--] = ak; + } else { + // a[great] >= pivot1. + a[k] = a[great]; + a[great--] = ak; + } + break; + } + } + } + } + } + } + + // Move pivots into their final positions. + // We shrunk the list from both sides (a[left] and a[right] have + // meaningless values in them) and now we move elements from the first + // and third partition into these locations so that we can store the + // pivots. + a[left] = a[less - 1]; + a[less - 1] = pivot1; + a[right] = a[great + 1]; + a[great + 1] = pivot2; + + // The list is now partitioned into three partitions: + // [ < pivot1 | >= pivot1 && <= pivot2 | > pivot2 ] + // ^ ^ ^ ^ + // left less great right + + // Recursive descent. (Don't include the pivot values.) + _doSort(a, left, less - 2, compare); + _doSort(a, great + 2, right, compare); + + if (pivots_are_equal) { + // All elements in the second partition are equal to the pivot. No + // need to sort them. + return; + } + + // In theory it should be enough to call _doSort recursively on the second + // partition. + // The Android source however removes the pivot elements from the recursive + // call if the second partition is too large (more than 2/3 of the list). + if (less < index1 && great > index5) { + while (compare(a[less], pivot1) == 0) { + less++; + } + while (compare(a[great], pivot2) == 0) { + great--; + } + + // Copy paste of the previous 3-way partitioning with adaptions. + // + // We partition the list into three parts: + // 1. == pivot1 + // 2. > pivot1 && < pivot2 + // 3. == pivot2 + // + // During the loop we have: + // [ == pivot1 | > pivot1 && < pivot2 | unpartitioned | == pivot2 ] + // ^ ^ ^ + // less k great + // + // Invariants: + // 1. for x in [ *, less[ : x == pivot1 + // 2. for x in [less, k[ : pivot1 < x && x < pivot2 + // 3. for x in ]great, * ] : x == pivot2 + for (int k = less; k <= great; k++) { + var ak = a[k]; + int comp_pivot1 = compare(ak, pivot1); + if (comp_pivot1 == 0) { + if (k != less) { + a[k] = a[less]; + a[less] = ak; + } + less++; + } else { + int comp_pivot2 = compare(ak, pivot2); + if (comp_pivot2 == 0) { + while (true) { + int comp = compare(a[great], pivot2); + if (comp == 0) { + great--; + if (great < k) break; + // This is the only location inside the loop where a new + // iteration is started. + continue; + } else { + // a[great] < pivot2. + comp = compare(a[great], pivot1); + if (comp < 0) { + // Triple exchange. + a[k] = a[less]; + a[less++] = a[great]; + a[great--] = ak; + } else { + // a[great] == pivot1. + a[k] = a[great]; + a[great--] = ak; + } + break; + } + } + } + } + } + // The second partition has now been cleared of pivot elements and looks + // as follows: + // [ * | > pivot1 && < pivot2 | * ] + // ^ ^ + // less great + // Sort the second partition using recursive descent. + _doSort(a, less, great, compare); + } else { + // The second partition looks as follows: + // [ * | >= pivot1 && <= pivot2 | * ] + // ^ ^ + // less great + // Simply sort it by recursive descent. + _doSort(a, less, great, compare); + } + } +} +NN<#L"E N%3GNN":*PD*@Q8'L?7/ 4!?.: &?68) 7!!=!!!!!!!!!P0CD<O A@C E 1/3,'!  MHLPMK8-I'#"$M7 + 1$ "POQ E 1>3,/ 1!4&I)'2 &"(#)## +/EKI:?>@<)+IOPN+./G 1" "K>B 0<1,/  1"4&I)&2 &"(#)## +O.)+<( 00+-.(Pfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/symbol.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +/** + * Implementation of [core.Symbol]. This class uses the same name as + * a core class so a user can't tell the difference. + * + * The purpose of this class is to hide [_name] from user code, but + * make it accessible to Dart platform code via the static method + * [getName]. + */ +class Symbol implements core.Symbol { + final String _name; + + /** + * Source of RegExp matching Dart reserved words. + * + * Reserved words are not allowed as identifiers. + */ + static const String reservedWordRE = + r'(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|' + r'e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|' + r'ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|' + r'v(?:ar|oid)|w(?:hile|ith))'; + /** + * Source of RegExp matching any public identifier. + * + * A public identifier is a valid identifier (not a reserved word) + * that doesn't start with '_'. + */ + static const String publicIdentifierRE = + r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$][\w$]*'; + /** + * Source of RegExp matching any identifier. + * + * It matches identifiers but not reserved words. The identifiers + * may start with '_'. + */ + static const String identifierRE = + r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$_][\w$]*'; + /** + * Source of RegExp matching a declarable operator names. + * + * The operators that can be declared using `operator` declarations are + * also the only ones allowed as symbols. The name of the operators is + * the same as the operator itself except for unary minus, where the name + * is "unary-". + */ + static const String operatorRE = + r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>[>=]?|unary-)'; + + // Grammar if symbols: + // symbol ::= qualifiedName | + // qualifiedName ::= publicIdentifier '.' qualifiedName | name + // name ::= publicIdentifier + // | publicIdentifier '=' + // | operator + // where publicIdentifier is any valid identifier (not a reserved word) + // that isn't private (doesn't start with '_'). + // + // Railroad diagram of the accepted grammar: + // + // /----------------\ + // | | + // | /-[.]-/ /-[=]-\ + // \ / / \ + // -------[id]-------------------------> + // \ / + // \------[operator]---/ + // \ / + // \------------/ + // + + /** + * RegExp that validates a non-empty non-private symbol. + * + * The empty symbol is handled before this regexp is used, and is not + * accepted. + */ + static final RegExp publicSymbolPattern = new RegExp( + '^(?:$operatorRE\$|$publicIdentifierRE(?:=?\$|[.](?!\$)))+?\$'); + + // The grammar of symbols that may be private is the same as for public + // symbols, except that "publicIdentifier" is replaced by "identifier", + // which matches any identifier. + + /** + * RegExp that validates a non-empty symbol. + * + * Private symbols are accepted. + * + * The empty symbol is handled before this regexp is used, and is not + * accepted. + */ + static final RegExp symbolPattern = + new RegExp('^(?:$operatorRE\$|$identifierRE(?:=?\$|[.](?!\$)))+?\$'); + + external const Symbol(String name); + + /** + * Platform-private method used by the mirror system to create + * otherwise invalid names. + */ + const Symbol.unvalidated(this._name); + + // This is called by dart2js. + Symbol.validated(String name) : this._name = validatePublicSymbol(name); + + bool operator ==(other) => other is Symbol && _name == other._name; + + external int get hashCode; + + external toString(); + + /// Platform-private accessor which cannot be called from user libraries. + static String getName(Symbol symbol) => symbol._name; + + static String validatePublicSymbol(String name) { + if (name.isEmpty || publicSymbolPattern.hasMatch(name)) return name; + if (name.startsWith('_')) { + // There may be other private parts in a qualified name than the first + // one, but this is a common case that deserves a specific error + // message. + throw new ArgumentError('"$name" is a private identifier'); + } + throw new ArgumentError('"$name" is not a valid (qualified) symbol name'); + } + + /** + * Checks whether name is a valid symbol name. + * + * This test allows both private and non-private symbols. + */ + static bool isValidSymbol(String name) { + return (name.isEmpty || symbolPattern.hasMatch(name)); + } + + external static String computeUnmangledName(Symbol symbol); +} +NN<F5DB&44'MJE%6E"+</D%=<JIL#=+D"&J2/'(,#"! ;H8GJJ#/#H&L&A( KFL84I MGBO1<+;>mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/internal_patch.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:core' hide Symbol; +import 'dart:core' as core show Symbol; +import 'dart:_js_primitives' show printString; +import 'dart:_js_helper' show patch; +import 'dart:_interceptors' show JSArray; +import 'dart:_foreign_helper' show JS; +import 'dart:_runtime' as dart; + +@patch +class Symbol implements core.Symbol { + @patch + const Symbol(String name) : this._name = name; + + @patch + int get hashCode { + int hash = JS('int|Null', '#._hashCode', this); + if (hash != null) return hash; + const arbitraryPrime = 664597; + hash = 0x1fffffff & (arbitraryPrime * _name.hashCode); + JS('', '#._hashCode = #', this, hash); + return hash; + } + + @patch + toString() => 'Symbol("$_name")'; + + @patch + static String computeUnmangledName(Symbol symbol) => symbol._name; +} + +@patch +void printToConsole(String line) { + printString('$line'); +} + +@patch +List makeListFixedLength(List growableList) { + JSArray.markFixedList(growableList); + return growableList; +} + +@patch +List makeFixedListUnmodifiable(List fixedLengthList) { + JSArray.markUnmodifiableList(fixedLengthList); + return fixedLengthList; +} + +@patch +Object extractTypeArguments(T instance, Function extract) => + dart.extractTypeArguments(instance, extract); +8NN< (/%*' & 1 4##;+ $ E#7'@1@5Ufile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/linked_list.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +/// A rudimentary linked list. +class LinkedList> extends IterableBase { + T first; + T last; + int length = 0; + + bool get isEmpty => length == 0; + + /** + * Adds [newLast] to the end of this linked list. + */ + void add(T newLast) { + assert(newLast._next == null && newLast._previous == null); + if (last != null) { + assert(last._next == null); + last._next = newLast; + } else { + first = newLast; + } + newLast._previous = last; + last = newLast; + last._list = this; + length++; + } + + /** + * Adds [newFirst] to the beginning of this linked list. + */ + void addFirst(T newFirst) { + if (first != null) { + assert(first._previous == null); + first._previous = newFirst; + } else { + last = newFirst; + } + newFirst._next = first; + first = newFirst; + first._list = this; + length++; + } + + /** + * Removes the given [node] from this list. + * + * If the entry is not in this linked list nothing happens. + * + * Also see [LinkedListEntry.unlink]. + */ + void remove(T node) { + if (node._list != this) return; + length--; + if (node._previous == null) { + assert(identical(node, first)); + first = node._next; + } else { + node._previous._next = node._next; + } + if (node._next == null) { + assert(identical(node, last)); + last = node._previous; + } else { + node._next._previous = node._previous; + } + node._next = node._previous = null; + node._list = null; + } + + Iterator get iterator => new _LinkedListIterator(this); +} + +class LinkedListEntry> { + T _next; + T _previous; + LinkedList _list; + + /** + * Unlinks the element from its linked list. + * + * If the entry is not in a linked list, does nothing. Otherwise, this + * is equivalent to calling [LinkedList.remove] on the list this entry + * is currently in. + */ + void unlink() { + if (_list == null) return; + _list.remove(this); + } +} + +class _LinkedListIterator> implements Iterator { + /// The current element of the iterator. + // This field is writeable, but should only read by users of this class. + T current; + + /// The list the iterator iterates over. + /// + /// Set to [null] if the provided list was empty (indicating that there were + /// no entries to iterate over). + /// + /// Set to [null] as soon as [moveNext] was invoked (indicating that the + /// iterator has to work with [current] from now on. + LinkedList _list; + + _LinkedListIterator(this._list) { + if (_list.length == 0) _list = null; + } + + bool moveNext() { + // current is null if the iterator hasn't started iterating, or if the + // iteration is finished. In the first case, the [_list] field is not null. + if (current == null) { + if (_list == null) return false; + assert(_list.length > 0); + current = _list.first; + _list = null; + return true; + } + current = current._next; + return current != null; + } +} +NN<I +#4@" ;'" .>($"& )% -(@6 /IIQ+K +O#K7$)KP' Ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/internal/print.dart5// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._internal; + +/** + * This function is set by the first allocation of a Zone. + * + * Once the function is set the core `print` function calls this closure instead + * of [printToConsole]. + * + * This decouples the core library from the async library. + */ +void Function(String) printToZone = null; + +external void printToConsole(String line); +NN<;Q;*+ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dartZ// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart._isolate_helper; + +import 'dart:_runtime' as dart; +import 'dart:async'; +import 'dart:_foreign_helper' show JS; + +/// Marks entering a JavaScript async operation to keep the worker alive. +/// +/// To be called by library code before starting an async operation controlled +/// by the JavaScript event handler. +/// +/// Also call [leaveJsAsync] in all callback handlers marking the end of that +/// async operation (also error handlers) so the worker can be released. +/// +/// These functions only has to be called for code that can be run from a +/// worker-isolate (so not for general dom operations). +/// +// TODO(jmesserly): we could potentially use this to track when all async +// operations have completed, for example, to run a bunch of test `main()` +// methods in batch mode the same V8 process. +enterJsAsync() {} + +/// Marks leaving a javascript async operation. +/// +/// See [enterJsAsync]. +leaveJsAsync() {} + +/// Deprecated way of initializing `main()` in DDC, typically called from JS. +@deprecated +void startRootIsolate(main, args) { + if (args == null) args = []; + if (args is List) { + if (args is! List) args = List.from(args); + // DDC attaches signatures only when torn off, and the typical way of + // getting `main` via the JS ABI won't do this. So use JS to invoke main. + if (JS('!', 'typeof # == "function"', main)) { + // JS will ignore extra arguments. + JS('', '#(#, #)', main, args, null); + } else { + // Not a function. Use a dynamic call to throw an error. + (main as dynamic)(args); + } + } else { + throw ArgumentError("Arguments to main must be a List: $args"); + } +} + +// TODO(vsm): Other libraries import global from here. Consider replacing +// those uses to just refer to the one in dart:runtime. +final global = dart.global_; + +class TimerImpl implements Timer { + final bool _once; + int _handle; + int _tick = 0; + + TimerImpl(int milliseconds, void callback()) : _once = true { + if (hasTimer()) { + void internalCallback() { + _handle = null; + leaveJsAsync(); + _tick = 1; + callback(); + } + + enterJsAsync(); + + _handle = JS( + 'int', '#.setTimeout(#, #)', global, internalCallback, milliseconds); + } else { + throw UnsupportedError("`setTimeout()` not found."); + } + } + + TimerImpl.periodic(int milliseconds, void callback(Timer timer)) + : _once = false { + if (hasTimer()) { + enterJsAsync(); + int start = JS('int', 'Date.now()'); + _handle = JS('int', '#.setInterval(#, #)', global, () { + int tick = this._tick + 1; + if (milliseconds > 0) { + int duration = JS('int', 'Date.now()') - start; + if (duration > (tick + 1) * milliseconds) { + tick = duration ~/ milliseconds; + } + } + this._tick = tick; + callback(this); + }, milliseconds); + } else { + throw UnsupportedError("Periodic timer."); + } + } + + int get tick => _tick; + + void cancel() { + if (hasTimer()) { + if (_handle == null) return; + leaveJsAsync(); + if (_once) { + JS('void', '#.clearTimeout(#)', global, _handle); + } else { + JS('void', '#.clearInterval(#)', global, _handle); + } + _handle = null; + } else { + throw UnsupportedError("Canceling a timer."); + } + } + + bool get isActive => _handle != null; +} + +bool hasTimer() { + return JS('', '#.setTimeout', global) != null; +} +|NN< 'JO%NIJ8JK.0N $'?JN9)+ ? DK8#@ P ;C+># :6- + 1#:; 4(1jfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/js_helper.dartj2// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart._js_helper; + +import 'dart:collection'; + +import 'dart:_debugger' show stackTraceMapper; + +import 'dart:_foreign_helper' show JS, JS_STRING_CONCAT, JSExportName; + +import 'dart:_interceptors'; +import 'dart:_internal' + show EfficientLengthIterable, MappedIterable, IterableElementError; + +import 'dart:_native_typed_data'; +import 'dart:_runtime' as dart; + +part 'annotations.dart'; +part 'linked_hash_map.dart'; +part 'identity_hash_map.dart'; +part 'custom_hash_map.dart'; +part 'native_helper.dart'; +part 'regexp_helper.dart'; +part 'string_helper.dart'; +part 'js_rti.dart'; + +class _Patch { + const _Patch(); +} + +const _Patch patch = _Patch(); + +/// Adapts a JS `[Symbol.iterator]` to a Dart `get iterator`. +/// +/// This is the inverse of `JsIterator`, for classes where we can more +/// efficiently obtain a JS iterator instead of a Dart one. +/// +// TODO(jmesserly): this adapter is to work around +// https://github.com/dart-lang/sdk/issues/28320 +class DartIterator implements Iterator { + final _jsIterator; + E _current; + + DartIterator(this._jsIterator); + + E get current => _current; + + bool moveNext() { + final ret = JS('', '#.next()', _jsIterator); + _current = JS('', '#.value', ret); + return JS('bool', '!#.done', ret); + } +} + +/// Used to compile `sync*`. +class SyncIterable extends IterableBase { + final Function() _initGenerator; + SyncIterable(this._initGenerator); + + @JSExportName('Symbol.iterator') + _jsIterator() => _initGenerator(); + + get iterator => DartIterator(_initGenerator()); +} + +class Primitives { + @NoInline() + static int _parseIntError(String source, int handleError(String source)) { + if (handleError == null) throw FormatException(source); + return handleError(source); + } + + static int parseInt( + @nullCheck String source, int _radix, int handleError(String source)) { + var re = JS('', r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i'); + // TODO(jmesserly): this isn't reified List, but it's safe to use as + // long as we use it locally and don't expose it to user code. + List match = JS('', '#.exec(#)', re, source); + int digitsIndex = 1; + int hexIndex = 2; + int decimalIndex = 3; + if (match == null) { + // TODO(sra): It might be that the match failed due to unrecognized U+0085 + // spaces. We could replace them with U+0020 spaces and try matching + // again. + return _parseIntError(source, handleError); + } + String decimalMatch = match[decimalIndex]; + if (_radix == null) { + if (decimalMatch != null) { + // Cannot fail because we know that the digits are all decimal. + return JS('int', r'parseInt(#, 10)', source); + } + if (match[hexIndex] != null) { + // Cannot fail because we know that the digits are all hex. + return JS('int', r'parseInt(#, 16)', source); + } + return _parseIntError(source, handleError); + } + @notNull + var radix = _radix; + if (radix < 2 || radix > 36) { + throw RangeError.range(radix, 2, 36, 'radix'); + } + if (radix == 10 && decimalMatch != null) { + // Cannot fail because we know that the digits are all decimal. + return JS('int', r'parseInt(#, 10)', source); + } + // If radix >= 10 and we have only decimal digits the string is safe. + // Otherwise we need to check the digits. + if (radix < 10 || decimalMatch == null) { + // We know that the characters must be ASCII as otherwise the + // regexp wouldn't have matched. Lowercasing by doing `| 0x20` is thus + // guaranteed to be a safe operation, since it preserves digits + // and lower-cases ASCII letters. + int maxCharCode; + if (radix <= 10) { + // Allow all digits less than the radix. For example 0, 1, 2 for + // radix 3. + // "0".codeUnitAt(0) + radix - 1; + maxCharCode = (0x30 - 1) + radix; + } else { + // Letters are located after the digits in ASCII. Therefore we + // only check for the character code. The regexp above made already + // sure that the string does not contain anything but digits or + // letters. + // "a".codeUnitAt(0) + (radix - 10) - 1; + maxCharCode = (0x61 - 10 - 1) + radix; + } + assert(match[digitsIndex] is String); + String digitsPart = JS('String', '#[#]', match, digitsIndex); + for (int i = 0; i < digitsPart.length; i++) { + int characterCode = digitsPart.codeUnitAt(i) | 0x20; + if (characterCode > maxCharCode) { + return _parseIntError(source, handleError); + } + } + } + // The above matching and checks ensures the source has at least one digits + // and all digits are suitable for the radix, so parseInt cannot return NaN. + return JS('int', r'parseInt(#, #)', source, radix); + } + + @NoInline() + static double _parseDoubleError( + String source, double handleError(String source)) { + if (handleError == null) { + throw FormatException('Invalid double', source); + } + return handleError(source); + } + + static double parseDouble( + @nullCheck String source, double handleError(String source)) { + // Notice that JS parseFloat accepts garbage at the end of the string. + // Accept only: + // - [+/-]NaN + // - [+/-]Infinity + // - a Dart double literal + // We do allow leading or trailing whitespace. + if (!JS( + 'bool', + r'/^\s*[+-]?(?:Infinity|NaN|' + r'(?:\.\d+|\d+(?:\.\d*)?)(?:[eE][+-]?\d+)?)\s*$/.test(#)', + source)) { + return _parseDoubleError(source, handleError); + } + num result = JS('!', r'parseFloat(#)', source); + if (result.isNaN) { + var trimmed = source.trim(); + if (trimmed == 'NaN' || trimmed == '+NaN' || trimmed == '-NaN') { + return result; + } + return _parseDoubleError(source, handleError); + } + return result; + } + + /** `r"$".codeUnitAt(0)` */ + static const int DOLLAR_CHAR_VALUE = 36; + + static int dateNow() => JS('int', r'Date.now()'); + + static void initTicker() { + if (timerFrequency != null) return; + // Start with low-resolution. We overwrite the fields if we find better. + timerFrequency = 1000; + timerTicks = dateNow; + if (JS('bool', 'typeof window == "undefined"')) return; + var jsWindow = JS('var', 'window'); + if (jsWindow == null) return; + var performance = JS('var', '#.performance', jsWindow); + if (performance == null) return; + if (JS('bool', 'typeof #.now != "function"', performance)) return; + timerFrequency = 1000000; + timerTicks = () => (1000 * JS('!', '#.now()', performance)).floor(); + } + + static int timerFrequency; + static Function timerTicks; + + static bool get isD8 { + return JS( + 'bool', + 'typeof version == "function"' + ' && typeof os == "object" && "system" in os'); + } + + static bool get isJsshell { + return JS( + 'bool', 'typeof version == "function" && typeof system == "function"'); + } + + static String currentUri() { + // In a browser return self.location.href. + if (JS('bool', '!!#.location', dart.global_)) { + return JS('String', '#.location.href', dart.global_); + } + + // TODO(vsm): Consider supporting properly in non-browser settings. + return ''; + } + + // This is to avoid stack overflows due to very large argument arrays in + // apply(). It fixes http://dartbug.com/6919 + @notNull + static String _fromCharCodeApply(List array) { + const kMaxApply = 500; + @nullCheck + int end = array.length; + if (end <= kMaxApply) { + return JS('String', r'String.fromCharCode.apply(null, #)', array); + } + String result = ''; + for (int i = 0; i < end; i += kMaxApply) { + int chunkEnd = (i + kMaxApply < end) ? i + kMaxApply : end; + result = JS( + 'String', + r'# + String.fromCharCode.apply(null, #.slice(#, #))', + result, + array, + i, + chunkEnd); + } + return result; + } + + @notNull + static String stringFromCodePoints(JSArray codePoints) { + List a = []; + for (@nullCheck var i in codePoints) { + if (i <= 0xffff) { + a.add(i); + } else if (i <= 0x10ffff) { + a.add(0xd800 + ((((i - 0x10000) >> 10) & 0x3ff))); + a.add(0xdc00 + (i & 0x3ff)); + } else { + throw argumentErrorValue(i); + } + } + return _fromCharCodeApply(a); + } + + @notNull + static String stringFromCharCodes(JSArray charCodes) { + for (@nullCheck var i in charCodes) { + if (i < 0) throw argumentErrorValue(i); + if (i > 0xffff) return stringFromCodePoints(charCodes); + } + return _fromCharCodeApply(charCodes); + } + + // [start] and [end] are validated. + @notNull + static String stringFromNativeUint8List( + NativeUint8List charCodes, @nullCheck int start, @nullCheck int end) { + const kMaxApply = 500; + if (end <= kMaxApply && start == 0 && end == charCodes.length) { + return JS('String', r'String.fromCharCode.apply(null, #)', charCodes); + } + String result = ''; + for (int i = start; i < end; i += kMaxApply) { + int chunkEnd = (i + kMaxApply < end) ? i + kMaxApply : end; + result = JS( + 'String', + r'# + String.fromCharCode.apply(null, #.subarray(#, #))', + result, + charCodes, + i, + chunkEnd); + } + return result; + } + + @notNull + static String stringFromCharCode(@nullCheck int charCode) { + if (0 <= charCode) { + if (charCode <= 0xffff) { + return JS('String', 'String.fromCharCode(#)', charCode); + } + if (charCode <= 0x10ffff) { + var bits = charCode - 0x10000; + var low = 0xDC00 | (bits & 0x3ff); + var high = 0xD800 | (bits >> 10); + return JS('String', 'String.fromCharCode(#, #)', high, low); + } + } + throw RangeError.range(charCode, 0, 0x10ffff); + } + + static String stringConcatUnchecked(String string1, String string2) { + return JS_STRING_CONCAT(string1, string2); + } + + static String flattenString(String str) { + return JS('String', "#.charCodeAt(0) == 0 ? # : #", str, str, str); + } + + static String getTimeZoneName(DateTime receiver) { + // Firefox and Chrome emit the timezone in parenthesis. + // Example: "Wed May 16 2012 21:13:00 GMT+0200 (CEST)". + // We extract this name using a regexp. + var d = lazyAsJsDate(receiver); + List match = JS('JSArray|Null', r'/\((.*)\)/.exec(#.toString())', d); + if (match != null) return match[1]; + + // Internet Explorer 10+ emits the zone name without parenthesis: + // Example: Thu Oct 31 14:07:44 PDT 2013 + match = JS( + 'JSArray|Null', + // Thu followed by a space. + r'/^[A-Z,a-z]{3}\s' + // Oct 31 followed by space. + r'[A-Z,a-z]{3}\s\d+\s' + // Time followed by a space. + r'\d{2}:\d{2}:\d{2}\s' + // The time zone name followed by a space. + r'([A-Z]{3,5})\s' + // The year. + r'\d{4}$/' + '.exec(#.toString())', + d); + if (match != null) return match[1]; + + // IE 9 and Opera don't provide the zone name. We fall back to emitting the + // UTC/GMT offset. + // Example (IE9): Wed Nov 20 09:51:00 UTC+0100 2013 + // (Opera): Wed Nov 20 2013 11:03:38 GMT+0100 + match = JS('JSArray|Null', r'/(?:GMT|UTC)[+-]\d{4}/.exec(#.toString())', d); + if (match != null) return match[0]; + return ""; + } + + static int getTimeZoneOffsetInMinutes(DateTime receiver) { + // Note that JS and Dart disagree on the sign of the offset. + return -JS('int', r'#.getTimezoneOffset()', lazyAsJsDate(receiver)); + } + + static num valueFromDecomposedDate( + @nullCheck int years, + @nullCheck int month, + @nullCheck int day, + @nullCheck int hours, + @nullCheck int minutes, + @nullCheck int seconds, + @nullCheck int milliseconds, + @nullCheck bool isUtc) { + final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000; + var jsMonth = month - 1; + num value; + if (isUtc) { + value = JS('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day, + hours, minutes, seconds, milliseconds); + } else { + value = JS('!', r'new Date(#, #, #, #, #, #, #).valueOf()', years, + jsMonth, day, hours, minutes, seconds, milliseconds); + } + if (value.isNaN || + value < -MAX_MILLISECONDS_SINCE_EPOCH || + value > MAX_MILLISECONDS_SINCE_EPOCH) { + return null; + } + if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc); + return value; + } + + static num patchUpY2K(value, years, isUtc) { + var date = JS('', r'new Date(#)', value); + if (isUtc) { + JS('', r'#.setUTCFullYear(#)', date, years); + } else { + JS('', r'#.setFullYear(#)', date, years); + } + return JS('!', r'#.valueOf()', date); + } + + // Lazily keep a JS Date stored in the JS object. + static lazyAsJsDate(DateTime receiver) { + if (JS('bool', r'#.date === (void 0)', receiver)) { + JS('void', r'#.date = new Date(#)', receiver, + receiver.millisecondsSinceEpoch); + } + return JS('var', r'#.date', receiver); + } + + // The getters for date and time parts below add a positive integer to ensure + // that the result is really an integer, because the JavaScript implementation + // may return -0.0 instead of 0. + + static int getYear(DateTime receiver) { + return (receiver.isUtc) + ? JS('int', r'(#.getUTCFullYear() + 0)', lazyAsJsDate(receiver)) + : JS('int', r'(#.getFullYear() + 0)', lazyAsJsDate(receiver)); + } + + static int getMonth(DateTime receiver) { + return (receiver.isUtc) + ? JS('int', r'#.getUTCMonth() + 1', lazyAsJsDate(receiver)) + : JS('int', r'#.getMonth() + 1', lazyAsJsDate(receiver)); + } + + static int getDay(DateTime receiver) { + return (receiver.isUtc) + ? JS('int', r'(#.getUTCDate() + 0)', lazyAsJsDate(receiver)) + : JS('int', r'(#.getDate() + 0)', lazyAsJsDate(receiver)); + } + + static int getHours(DateTime receiver) { + return (receiver.isUtc) + ? JS('int', r'(#.getUTCHours() + 0)', lazyAsJsDate(receiver)) + : JS('int', r'(#.getHours() + 0)', lazyAsJsDate(receiver)); + } + + static int getMinutes(DateTime receiver) { + return (receiver.isUtc) + ? JS('int', r'(#.getUTCMinutes() + 0)', lazyAsJsDate(receiver)) + : JS('int', r'(#.getMinutes() + 0)', lazyAsJsDate(receiver)); + } + + static int getSeconds(DateTime receiver) { + return (receiver.isUtc) + ? JS('int', r'(#.getUTCSeconds() + 0)', lazyAsJsDate(receiver)) + : JS('int', r'(#.getSeconds() + 0)', lazyAsJsDate(receiver)); + } + + static int getMilliseconds(DateTime receiver) { + return (receiver.isUtc) + ? JS('int', r'(#.getUTCMilliseconds() + 0)', lazyAsJsDate(receiver)) + : JS('int', r'(#.getMilliseconds() + 0)', lazyAsJsDate(receiver)); + } + + static int getWeekday(DateTime receiver) { + int weekday = (receiver.isUtc) + ? JS('int', r'#.getUTCDay() + 0', lazyAsJsDate(receiver)) + : JS('int', r'#.getDay() + 0', lazyAsJsDate(receiver)); + // Adjust by one because JS weeks start on Sunday. + return (weekday + 6) % 7 + 1; + } + + static num valueFromDateString(str) { + if (str is! String) throw argumentErrorValue(str); + num value = JS('!', r'Date.parse(#)', str); + if (value.isNaN) throw argumentErrorValue(str); + return value; + } + + static getProperty(object, key) { + if (object == null || object is bool || object is num || object is String) { + throw argumentErrorValue(object); + } + return JS('var', '#[#]', object, key); + } + + static void setProperty(object, key, value) { + if (object == null || object is bool || object is num || object is String) { + throw argumentErrorValue(object); + } + JS('void', '#[#] = #', object, key, value); + } +} + +/** + * Diagnoses an indexing error. Returns the ArgumentError or RangeError that + * describes the problem. + */ +@NoInline() +Error diagnoseIndexError(indexable, int index) { + int length = indexable.length; + // The following returns the same error that would be thrown by calling + // [RangeError.checkValidIndex] with no optional parameters provided. + if (index < 0 || index >= length) { + return RangeError.index(index, indexable, 'index', null, length); + } + // The above should always match, but if it does not, use the following. + return RangeError.value(index, 'index'); +} + +/** + * Diagnoses a range error. Returns the ArgumentError or RangeError that + * describes the problem. + */ +@NoInline() +Error diagnoseRangeError(int start, int end, int length) { + if (start == null) { + return ArgumentError.value(start, 'start'); + } + if (start < 0 || start > length) { + return RangeError.range(start, 0, length, 'start'); + } + if (end != null) { + if (end < start || end > length) { + return RangeError.range(end, start, length, 'end'); + } + } + // The above should always match, but if it does not, use the following. + return ArgumentError.value(end, "end"); +} + +@notNull +int stringLastIndexOfUnchecked(receiver, element, start) => + JS('int', r'#.lastIndexOf(#, #)', receiver, element, start); + +/// 'factory' for constructing ArgumentError.value to keep the call sites small. +@NoInline() +ArgumentError argumentErrorValue(object) { + return ArgumentError.value(object); +} + +void throwArgumentErrorValue(value) { + throw argumentErrorValue(value); +} + +checkInt(value) { + if (value is! int) throw argumentErrorValue(value); + return value; +} + +throwRuntimeError(message) { + throw RuntimeError(message); +} + +throwAbstractClassInstantiationError(className) { + throw AbstractClassInstantiationError(className); +} + +@NoInline() +throwConcurrentModificationError(collection) { + throw ConcurrentModificationError(collection); +} + +class JsNoSuchMethodError extends Error implements NoSuchMethodError { + final String _message; + final String _method; + final String _receiver; + + JsNoSuchMethodError(this._message, match) + : _method = match == null ? null : JS('String|Null', '#.method', match), + _receiver = + match == null ? null : JS('String|Null', '#.receiver', match); + + String toString() { + if (_method == null) return 'NoSuchMethodError: $_message'; + if (_receiver == null) { + return "NoSuchMethodError: method not found: '$_method' ($_message)"; + } + return "NoSuchMethodError: " + "method not found: '$_method' on '$_receiver' ($_message)"; + } +} + +class UnknownJsTypeError extends Error { + final String _message; + + UnknownJsTypeError(this._message); + + String toString() => _message.isEmpty ? 'Error' : 'Error: $_message'; +} + +/** + * Called by generated code to fetch the stack trace from a Dart + * exception. Should never return null. + */ +final _stackTrace = JS('', 'Symbol("_stackTrace")'); +StackTrace getTraceFromException(exception) { + var error = dart.recordJsError(exception); + StackTrace trace = JS('', '#[#]', error, _stackTrace); + if (trace != null) return trace; + trace = _StackTrace(error); + JS('', '#[#] = #', error, _stackTrace, trace); + return trace; +} + +/** + * Called on rethrow to (potentially) set a different trace. + */ +void setTraceForException(exception, StackTrace trace) { + var error = dart.recordJsError(exception); + JS('', '#[#] = #', error, _stackTrace, trace); +} + +class _StackTrace implements StackTrace { + var _exception; + String _trace; + + _StackTrace(this._exception); + + String toString() { + if (_trace != null) return _trace; + + String trace; + if (JS('bool', '# !== null', _exception) && + JS('bool', 'typeof # === "object"', _exception)) { + if (_exception is NativeError) { + trace = _exception.dartStack(); + } else { + trace = JS("", r"#.stack", _exception); + } + if (trace != null && stackTraceMapper != null) { + trace = stackTraceMapper(trace); + } + } + return _trace = (trace == null) ? '' : trace; + } +} + +/** + * Called by generated code to build a map literal. [keyValuePairs] is + * a list of key, value, key, value, ..., etc. + */ +fillLiteralMap(keyValuePairs, Map result) { + // TODO(johnniwinther): Use JSArray to optimize this code instead of calling + // [getLength] and [getIndex]. + int index = 0; + int length = getLength(keyValuePairs); + while (index < length) { + var key = getIndex(keyValuePairs, index++); + var value = getIndex(keyValuePairs, index++); + result[key] = value; + } + return result; +} + +bool jsHasOwnProperty(var jsObject, String property) { + return JS('bool', r'#.hasOwnProperty(#)', jsObject, property); +} + +jsPropertyAccess(var jsObject, String property) { + return JS('var', r'#[#]', jsObject, property); +} + +/** + * Called at the end of unaborted switch cases to get the singleton + * FallThroughError exception that will be thrown. + */ +getFallThroughError() => FallThroughErrorImplementation(); + +/** + * A metadata annotation describing the types instantiated by a native element. + * + * The annotation is valid on a native method and a field of a native class. + * + * By default, a field of a native class is seen as an instantiation point for + * all native classes that are a subtype of the field's type, and a native + * method is seen as an instantiation point fo all native classes that are a + * subtype of the method's return type, or the argument types of the declared + * type of the method's callback parameter. + * + * An @[Creates] annotation overrides the default set of instantiated types. If + * one or more @[Creates] annotations are present, the type of the native + * element is ignored, and the union of @[Creates] annotations is used instead. + * The names in the strings are resolved and the program will fail to compile + * with dart2js if they do not name types. + * + * The argument to [Creates] is a string. The string is parsed as the names of + * one or more types, separated by vertical bars `|`. There are some special + * names: + * + * * `=Object`. This means 'exactly Object', which is a plain JavaScript object + * with properties and none of the subtypes of Object. + * + * Example: we may know that a method always returns a specific implementation: + * + * @Creates('_NodeList') + * List getElementsByTagName(String tag) native; + * + * Useful trick: A method can be marked as not instantiating any native classes + * with the annotation `@Creates('Null')`. This is useful for fields on native + * classes that are used only in Dart code. + * + * @Creates('Null') + * var _cachedFoo; + */ +class Creates { + final String types; + const Creates(this.types); +} + +/** + * A metadata annotation describing the types returned or yielded by a native + * element. + * + * The annotation is valid on a native method and a field of a native class. + * + * By default, a native method or field is seen as returning or yielding all + * subtypes if the method return type or field type. This annotation allows a + * more precise set of types to be specified. + * + * See [Creates] for the syntax of the argument. + * + * Example: IndexedDB keys are numbers, strings and JavaScript Arrays of keys. + * + * @Returns('String|num|JSExtendableArray') + * dynamic key; + * + * // Equivalent: + * @Returns('String') @Returns('num') @Returns('JSExtendableArray') + * dynamic key; + */ +class Returns { + final String types; + const Returns(this.types); +} + +/** + * A metadata annotation placed on native methods and fields of native classes + * to specify the JavaScript name. + * + * This example declares a Dart field + getter + setter called `$dom_title` that + * corresponds to the JavaScript property `title`. + * + * class Document native "*Foo" { + * @JSName('title') + * String $dom_title; + * } + */ +class JSName { + final String name; + const JSName(this.name); +} + +/** + * Special interface recognized by the compiler and implemented by DOM + * objects that support integer indexing. This interface is not + * visible to anyone, and is only injected into special libraries. + */ +abstract class JavaScriptIndexingBehavior {} + +// TODO(lrn): These exceptions should be implemented in core. +// When they are, remove the 'Implementation' here. + +/// Thrown by type assertions that fail. +class TypeErrorImpl extends Error implements TypeError { + final String message; + + TypeErrorImpl(this.message); + + String toString() => message; +} + +/// Thrown by the 'as' operator if the cast isn't valid. +class CastErrorImpl extends Error implements CastError { + final String message; + + CastErrorImpl(this.message); + + String toString() => message; +} + +class FallThroughErrorImplementation extends FallThroughError { + String toString() => "Switch case fall-through."; +} + +/** + * Error thrown when a runtime error occurs. + */ +class RuntimeError extends Error { + final message; + RuntimeError(this.message); + String toString() => "RuntimeError: $message"; +} + +/// Error thrown by DDC when an `assert()` fails (with or without a message). +class AssertionErrorImpl extends AssertionError { + AssertionErrorImpl(message) : super(message); + String toString() => + "Assertion failed: " + + (message != null ? Error.safeToString(message) : "is not true"); +} + +/** + * Creates a random number with 64 bits of randomness. + * + * This will be truncated to the 53 bits available in a double. + */ +int random64() { + // TODO(lrn): Use a secure random source. + int int32a = JS("int", "(Math.random() * 0x100000000) >>> 0"); + int int32b = JS("int", "(Math.random() * 0x100000000) >>> 0"); + return int32a + int32b * 0x100000000; +} + +class BooleanConversionAssertionError extends AssertionError { + toString() => 'Failed assertion: boolean expression must not be null'; +} + +// Hook to register new global object. This is invoked from dart:html +// whenever a new window is accessed for the first time. +void registerGlobalObject(object) { + try { + if (dart.polyfill(object)) { + dart.applyAllExtensions(object); + } + } catch (e) { + // This may fail due to cross-origin errors. In that case, we shouldn't + // need to polyfill as we can't get objects from that frame. + + // TODO(vsm): Detect this more robustly - ideally before we try to polyfill. + } +} + +/// Expose browser JS classes. +void applyExtension(name, nativeObject) { + dart.applyExtension(name, nativeObject); +} + +/// Used internally by DDC to map ES6 symbols to Dart. +class PrivateSymbol implements Symbol { + // TODO(jmesserly): could also get this off the native symbol instead of + // storing it. Mirrors already does this conversion. + final String _name; + final Object _nativeSymbol; + + const PrivateSymbol(this._name, this._nativeSymbol); + + static String getName(Symbol symbol) => (symbol as PrivateSymbol)._name; + + static Object getNativeSymbol(Symbol symbol) { + if (symbol is PrivateSymbol) return symbol._nativeSymbol; + return null; + } + + bool operator ==(other) => + other is PrivateSymbol && + _name == other._name && + identical(_nativeSymbol, other._nativeSymbol); + + get hashCode => _name.hashCode; + + // TODO(jmesserly): is this equivalent to _nativeSymbol toString? + toString() => 'Symbol("$_name")'; +} +WNN</GH" >G<31/"1''0#%#%2M< NKQC:QL2/"H6%D62 #5/F4J..DMF(I**GLH1/,D4=+6 +PQ8#:7 EK3 &C54#H5+4(M<("<%GN'8P/4<HK0 6I/BA  @+";%%" >*.>*& +MEM3BD  > A"'+*E3H/,H5<<,$J(F-$%%3 (P88Q(=AI&#?M2 I@10K/.3 0*4+84,+PQ#*IG+DB)EC+FD-HF-HF2MK-#B@7"(704$Q(+0Q(0M 1!JH&FK+I ;0%8':K* 4)9 99 @4-#1N20G7@,AA(?IG9$!'MAQ*+7(K77K1> 5"D$pfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/custom_hash_map.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._js_helper; + +class CustomKeyHashMap extends CustomHashMap { + final _Predicate _validKey; + CustomKeyHashMap(_Equality equals, _Hasher hashCode, this._validKey) + : super(equals, hashCode); + + @override + @notNull + bool containsKey(Object key) { + if (!_validKey(key)) return false; + return super.containsKey(key); + } + + @override + V operator [](Object key) { + if (!_validKey(key)) return null; + return super[key]; + } + + @override + V remove(Object key) { + if (!_validKey(key)) return null; + return super.remove(key); + } +} + +class CustomHashMap extends InternalMap { + /// The backing store for this map. + @notNull + final _map = JS('', 'new Map()'); + + /// Our map used to map keys onto the canonical key that is stored in [_map]. + @notNull + final _keyMap = JS('', 'new Map()'); + + // We track the number of modifications done to the key set of the + // hash map to be able to throw when the map is modified while being + // iterated over. + // + // Value cycles after 2^30 modifications so that modification counts are + // always unboxed (Smi) values. Modification detection will be missed if you + // make exactly some multiple of 2^30 modifications between advances of an + // iterator. + @notNull + int _modifications = 0; + + final _Equality _equals; + final _Hasher _hashCode; + + CustomHashMap(this._equals, this._hashCode); + + @notNull + int get length => JS('int', '#.size', _map); + + @notNull + bool get isEmpty => JS('bool', '#.size == 0', _map); + + @notNull + bool get isNotEmpty => JS('bool', '#.size != 0', _map); + + Iterable get keys => _JSMapIterable(this, true); + Iterable get values => _JSMapIterable(this, false); + + @notNull + bool containsKey(Object key) { + if (key is K) { + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key)); + if (buckets != null) { + var equals = _equals; + for (int i = 0, n = JS('int', '#.length', buckets); i < n; i++) { + K k = JS('', '#[#]', buckets, i); + if (equals(k, key)) return true; + } + } + } + return false; + } + + bool containsValue(Object value) { + for (var v in JS('', '#.values()', _map)) { + if (value == v) return true; + } + return false; + } + + void addAll(Map other) { + other.forEach((K key, V value) { + this[key] = value; + }); + } + + V operator [](Object key) { + if (key is K) { + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key)); + if (buckets != null) { + var equals = _equals; + for (int i = 0, n = JS('int', '#.length', buckets); i < n; i++) { + K k = JS('', '#[#]', buckets, i); + if (equals(k, key)) return JS('', '#.get(#)', _map, k); + } + } + } + return null; + } + + void operator []=(K key, V value) { + var keyMap = _keyMap; + int hash = JS('!', '# & 0x3ffffff', _hashCode(key)); + var buckets = JS('', '#.get(#)', keyMap, hash); + if (buckets == null) { + JS('', '#.set(#, [#])', keyMap, hash, key); + } else { + var equals = _equals; + for (int i = 0, n = JS('int', '#.length', buckets);;) { + K k = JS('', '#[#]', buckets, i); + if (equals(k, key)) { + key = k; + break; + } + if (++i >= n) { + JS('', '#.push(#)', buckets, key); + break; + } + } + } + JS('', '#.set(#, #)', _map, key, value); + _modifications = (_modifications + 1) & 0x3ffffff; + } + + V putIfAbsent(K key, V ifAbsent()) { + var keyMap = _keyMap; + int hash = JS('!', '# & 0x3ffffff', _hashCode(key)); + var buckets = JS('', '#.get(#)', keyMap, hash); + if (buckets == null) { + JS('', '#.set(#, [#])', keyMap, hash, key); + } else { + var equals = _equals; + for (int i = 0, n = JS('int', '#.length', buckets); i < n; i++) { + K k = JS('', '#[#]', buckets, i); + if (equals(k, key)) return JS('', '#.get(#)', _map, k); + } + JS('', '#.push(#)', buckets, key); + } + V value = ifAbsent(); + JS('', '#.set(#, #)', _map, key, value); + _modifications = (_modifications + 1) & 0x3ffffff; + return value; + } + + V remove(Object key) { + if (key is K) { + int hash = JS('!', '# & 0x3ffffff', _hashCode(key)); + var keyMap = _keyMap; + var buckets = JS('', '#.get(#)', keyMap, hash); + if (buckets == null) return null; // not found + var equals = _equals; + for (int i = 0, n = JS('int', '#.length', buckets); i < n; i++) { + K k = JS('', '#[#]', buckets, i); + if (equals(k, key)) { + if (n == 1) { + JS('', '#.delete(#)', keyMap, hash); + } else { + JS('', '#.splice(#, 1)', buckets, i); + } + var map = _map; + V value = JS('', '#.get(#)', map, k); + JS('', '#.delete(#)', map, k); + _modifications = (_modifications + 1) & 0x3ffffff; + return value; + } + } + } + return null; + } + + void clear() { + var map = _map; + if (JS('!', '#.size', map) > 0) { + JS('', '#.clear()', map); + JS('', '#.clear()', _keyMap); + _modifications = (_modifications + 1) & 0x3ffffff; + } + } +} + +typedef bool _Equality(K a, K b); +typedef int _Hasher(K object); +typedef bool _Predicate(T value); +NN<;&M! !'# & &6& $P 'EGKOM / / 7 :9< !MJ,+ +%0#!%MJ,B +&942 >* +- +-7'942 H*@)-7;65H*12 0)= ++ $9%"%lfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/annotations.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._js_helper; + +/// Tells the optimizing compiler to always inline the annotated method. +class ForceInline { + const ForceInline(); +} + +class _NotNull { + const _NotNull(); +} + +/// Marks a variable or API to be non-nullable. +/// ****CAUTION****** +/// This is currently unchecked, and hence should never be used +/// on any public interface where user code could subclass, implement, +/// or otherwise cause the contract to be violated. +/// TODO(leafp): Consider adding static checking and exposing +/// this to user code. +const notNull = _NotNull(); + +/// Marks a generic function or static method API to be not reified. +/// ****CAUTION****** +/// This is currently unchecked, and hence should be used very carefully for +/// internal SDK APIs only. +class NoReifyGeneric { + const NoReifyGeneric(); +} + +/// Enables/disables reificiation of functions within the body of this function. +/// ****CAUTION****** +/// This is currently unchecked, and hence should be used very carefully for +/// internal SDK APIs only. +class ReifyFunctionTypes { + final bool value; + const ReifyFunctionTypes(this.value); +} + +class _NullCheck { + const _NullCheck(); +} + +/// Tells the development compiler to check a variable for null at its +/// declaration point, and then to assume that the variable is non-null +/// from that point forward. +/// ****CAUTION****** +/// This is currently unchecked, and hence will not catch re-assignments +/// of a variable with null +const nullCheck = _NullCheck(); + +/// Tells the optimizing compiler that the annotated method cannot throw. +/// Requires @NoInline() to function correctly. +class NoThrows { + const NoThrows(); +} + +/// Tells the optimizing compiler to not inline the annotated method. +class NoInline { + const NoInline(); +} + +/// Marks a class as native and defines its JavaScript name(s). +class Native { + final String name; + const Native(this.name); +} + +class JsPeerInterface { + /// The JavaScript type that we should match the API of. + /// Used for classes where Dart subclasses should be callable from JavaScript + /// matching the JavaScript calling conventions. + final String name; + const JsPeerInterface({this.name}); +} + +/// A Dart interface may only be implemented by a native JavaScript object +/// if it is marked with this annotation. +class SupportJsExtensionMethods { + const SupportJsExtensionMethods(); +} +UNN<I0@G4>EMQM(GHI J0F@;P3&K*"%pfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/linked_hash_map.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Efficient JavaScript based implementation of a linked hash map used as a +// backing map for constant maps and the [LinkedHashMap] patch + +part of dart._js_helper; + +abstract class InternalMap extends MapBase + implements LinkedHashMap, HashMap { + @notNull + get _map; + + @notNull + int get _modifications; + + void forEach(void action(K key, V value)) { + int modifications = _modifications; + for (var entry in JS('Iterable', '#.entries()', _map)) { + action(JS('', '#[0]', entry), JS('', '#[1]', entry)); + if (modifications != _modifications) { + throw ConcurrentModificationError(this); + } + } + } +} + +/// A linked hash map implementation based on ES6 Map. +/// +/// Items that can use identity semantics are stored directly in the backing +/// map. +/// +/// Items that have a custom equality/hashCode are first canonicalized by +/// looking up the canonical key by its hashCode. +class LinkedMap extends InternalMap { + /// The backing store for this map. + /// + /// Keys that use identity equality are stored directly. For other types of + /// keys, we first look them up (by hashCode) in the [_keyMap] map, then + /// we lookup the key in this map. + @notNull + final _map = JS('', 'new Map()'); + + /// Items that use custom equality semantics. + /// + /// This maps from the item's hashCode to the canonical key, which is then + /// used to lookup the item in [_map]. Keeping the data in our primary backing + /// map gives us the ordering semantics requred by [LinkedHashMap], while + /// also providing convenient access to keys/values. + @notNull + final _keyMap = JS('', 'new Map()'); + + // We track the number of modifications done to the key set of the + // hash map to be able to throw when the map is modified while being + // iterated over. + // + // Value cycles after 2^30 modifications so that modification counts are + // always unboxed (Smi) values. Modification detection will be missed if you + // make exactly some multiple of 2^30 modifications between advances of an + // iterator. + @notNull + int _modifications = 0; + + LinkedMap(); + + /// Called by generated code for a map literal. + LinkedMap.from(JSArray entries) { + var map = _map; + var keyMap = _keyMap; + for (int i = 0, n = JS('!', '#.length', entries); i < n; i += 2) { + K key = JS('', '#[#]', entries, i); + V value = JS('', '#[#]', entries, i + 1); + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + key = putLinkedMapKey(key, keyMap); + } + JS('', '#.set(#, #)', map, key, value); + } + } + + @notNull + int get length => JS('!', '#.size', _map); + + @notNull + bool get isEmpty => JS('bool', '#.size == 0', _map); + + @notNull + bool get isNotEmpty => JS('bool', '#.size != 0', _map); + + Iterable get keys => _JSMapIterable(this, true); + Iterable get values => _JSMapIterable(this, false); + + @notNull + bool containsKey(Object key) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + @notNull + var k = key; + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode); + if (buckets != null) { + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + k = JS('', '#[#]', buckets, i); + if (k == key) return true; + } + } + return false; + } + return JS('bool', '#.has(#)', _map, key); + } + + bool containsValue(Object value) { + for (var v in JS('', '#.values()', _map)) { + if (v == value) return true; + } + return false; + } + + void addAll(Map other) { + var map = _map; + int length = JS('', '#.size', map); + other.forEach((K key, V value) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + key = putLinkedMapKey(key, _keyMap); + } + JS('', '#.set(#, #)', _map, key, value); + }); + if (length != JS('!', '#.size', map)) { + _modifications = (_modifications + 1) & 0x3ffffff; + } + } + + V operator [](Object key) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + @notNull + var k = key; + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode); + if (buckets != null) { + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + k = JS('', '#[#]', buckets, i); + if (k == key) return JS('', '#.get(#)', _map, k); + } + } + return null; + } + return JS('', '#.get(#)', _map, key); + } + + void operator []=(K key, V value) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + key = putLinkedMapKey(key, _keyMap); + } + var map = _map; + int length = JS('', '#.size', map); + JS('', '#.set(#, #)', map, key, value); + if (length != JS('!', '#.size', map)) { + _modifications = (_modifications + 1) & 0x3ffffff; + } + } + + V putIfAbsent(K key, V ifAbsent()) { + var map = _map; + if (key == null) { + key = null; + if (JS('bool', '#.has(null)', map)) return JS('', '#.get(null)', map); + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + @notNull + K k = key; + var hash = JS('!', '# & 0x3ffffff', k.hashCode); + var buckets = JS('', '#.get(#)', _keyMap, hash); + if (buckets == null) { + JS('', '#.set(#, [#])', _keyMap, hash, key); + } else { + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + k = JS('', '#[#]', buckets, i); + if (k == key) return JS('', '#.get(#)', map, k); + } + JS('', '#.push(#)', buckets, key); + } + } else if (JS('bool', '#.has(#)', map, key)) { + return JS('', '#.get(#)', map, key); + } + V value = ifAbsent(); + JS('', '#.set(#, #)', map, key, value); + _modifications = (_modifications + 1) & 0x3ffffff; + return value; + } + + V remove(Object key) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + @notNull + var k = key; + var hash = JS('!', '# & 0x3ffffff', k.hashCode); + var buckets = JS('', '#.get(#)', _keyMap, hash); + if (buckets == null) return null; // not found + for (int i = 0, n = JS('!', '#.length', buckets);;) { + k = JS('', '#[#]', buckets, i); + if (k == key) { + key = k; + if (n == 1) { + JS('', '#.delete(#)', _keyMap, hash); + } else { + JS('', '#.splice(#, 1)', buckets, i); + } + break; + } + if (++i >= n) return null; // not found + } + } + var map = _map; + V value = JS('', '#.get(#)', map, key); + if (JS('bool', '#.delete(#)', map, key)) { + _modifications = (_modifications + 1) & 0x3ffffff; + } + return value; + } + + void clear() { + var map = _map; + if (JS('!', '#.size', map) > 0) { + JS('', '#.clear()', map); + JS('', '#.clear()', _keyMap); + _modifications = (_modifications + 1) & 0x3ffffff; + } + } +} + +@NoReifyGeneric() +K putLinkedMapKey(@notNull K key, keyMap) { + var hash = JS('!', '# & 0x3ffffff', key.hashCode); + var buckets = JS('', '#.get(#)', keyMap, hash); + if (buckets == null) { + JS('', '#.set(#, [#])', keyMap, hash, key); + return key; + } + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + @notNull + K k = JS('', '#[#]', buckets, i); + if (k == key) return k; + } + JS('', '#.push(#)', buckets, key); + return key; +} + +class ImmutableMap extends LinkedMap { + ImmutableMap.from(JSArray entries) : super.from(entries); + + void operator []=(Object key, Object value) { + throw _unsupported(); + } + + void addAll(Object other) => throw _unsupported(); + void clear() => throw _unsupported(); + V remove(Object key) => throw _unsupported(); + V putIfAbsent(Object key, Object ifAbsent()) => throw _unsupported(); + + static Error _unsupported() => + UnsupportedError("Cannot modify unmodifiable map"); +} +NN<L?74  .(=<-17M J22&NK% $0MQL7 'EGKOM 2$G*0P",. 2 7 :9< !N IH*% +.%0#!(%P"-/19N IH*< +*&N +(,19'MN <75H*; ++3+,7N <75<(22  +0,/9+ $9/:20B &%3<05(0H!:rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/identity_hash_map.dartn// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._js_helper; + +class IdentityMap extends InternalMap { + final _map = JS('', 'new Map()'); + + // We track the number of modifications done to the key set of the + // hash map to be able to throw when the map is modified while being + // iterated over. + // + // Value cycles after 2^30 modifications so that modification counts are + // always unboxed (Smi) values. Modification detection will be missed if you + // make exactly some multiple of 2^30 modifications between advances of an + // iterator. + @notNull + int _modifications = 0; + + IdentityMap(); + IdentityMap.from(JSArray entries) { + var map = _map; + for (int i = 0, n = JS('int', '#.length', entries); i < n; i += 2) { + JS('', '#.set(#[#], #[#])', map, entries, i, entries, i + 1); + } + } + + int get length => JS('int', '#.size', _map); + bool get isEmpty => JS('bool', '#.size == 0', _map); + bool get isNotEmpty => JS('bool', '#.size != 0', _map); + + Iterable get keys => _JSMapIterable(this, true); + Iterable get values => _JSMapIterable(this, false); + + bool containsKey(Object key) { + return JS('bool', '#.has(#)', _map, key); + } + + bool containsValue(Object value) { + for (var v in JS('', '#.values()', _map)) { + if (v == value) return true; + } + return false; + } + + void addAll(Map other) { + if (other.isNotEmpty) { + var map = _map; + other.forEach((key, value) { + JS('', '#.set(#, #)', map, key, value); + }); + _modifications = (_modifications + 1) & 0x3ffffff; + } + } + + V operator [](Object key) { + return JS('', '#.get(#)', _map, key); + } + + void operator []=(K key, V value) { + var map = _map; + int length = JS('!', '#.size', map); + JS('', '#.set(#, #)', map, key, value); + if (length != JS('int', '#.size', map)) { + _modifications = (_modifications + 1) & 0x3ffffff; + } + } + + V putIfAbsent(K key, V ifAbsent()) { + if (JS('bool', '#.has(#)', _map, key)) return JS('', '#.get(#)', _map, key); + V value = ifAbsent(); + JS('', '#.set(#, #)', _map, key, value); + _modifications = (_modifications + 1) & 0x3ffffff; + return value; + } + + V remove(Object key) { + V value = JS('', '#.get(#)', _map, key); + if (JS('bool', '#.delete(#)', _map, key)) { + _modifications = (_modifications + 1) & 0x3ffffff; + } + return value; + } + + void clear() { + if (JS('int', '#.size', _map) > 0) { + JS('', '#.clear()', _map); + _modifications = (_modifications + 1) & 0x3ffffff; + } + } +} + +class _JSMapIterable extends EfficientLengthIterable { + final InternalMap _map; + @notNull + final bool _isKeys; + _JSMapIterable(this._map, this._isKeys); + + int get length => _map.length; + bool get isEmpty => _map.isEmpty; + + @JSExportName('Symbol.iterator') + _jsIterator() { + var map = _map; + var iterator = + JS('', '# ? #.keys() : #.values()', _isKeys, map._map, map._map); + int modifications = map._modifications; + return JS( + '', + '''{ + next() { + if (# != #) { + throw #; + } + return #.next(); + } + }''', + modifications, + map._modifications, + ConcurrentModificationError(map), + iterator); + } + + Iterator get iterator => DartIterator(_jsIterator()); + + bool contains(Object element) => + _isKeys ? _map.containsKey(element) : _map.containsValue(element); + + void forEach(void f(E element)) { + for (var entry in this) f(entry); + } +} +NN<4$EGKOM &ID/7:9<!.%0#!#0 +9*&),.9'Q-7-09)!9= +!$#J,  + +*>#I$&nfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._js_helper; + +// Helper method used by internal libraries. +regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp; + +/** + * Returns a native version of the RegExp with the global flag set. + * + * The RegExp's `lastIndex` property is zero when it is returned. + * + * The returned regexp is shared, and its `lastIndex` property may be + * modified by other uses, so the returned regexp must be used immediately + * when it's returned, with no user-provided code run in between. + */ +regExpGetGlobalNative(JSSyntaxRegExp regexp) { + var nativeRegexp = regexp._nativeGlobalVersion; + JS("void", "#.lastIndex = 0", nativeRegexp); + return nativeRegexp; +} + +/** + * Computes the number of captures in a regexp. + * + * This currently involves creating a new RegExp object with a different + * source and running it against the empty string (the last part is usually + * fast). + * + * The JSSyntaxRegExp could cache the result, and set the cache any time + * it finds a match. + */ +int regExpCaptureCount(JSSyntaxRegExp regexp) { + var nativeAnchoredRegExp = regexp._nativeAnchoredVersion; + JSExtendableArray match = + JS('JSExtendableArray', "#.exec('')", nativeAnchoredRegExp); + // The native-anchored regexp always have one capture more than the original, + // and always matches the empty string. + return match.length - 2; +} + +class JSSyntaxRegExp implements RegExp { + final String pattern; + final _nativeRegExp; + var _nativeGlobalRegExp; + var _nativeAnchoredRegExp; + + String toString() => "RegExp/$pattern/"; + + JSSyntaxRegExp(String source, + {bool multiLine = false, bool caseSensitive = true}) + : this.pattern = source, + this._nativeRegExp = + makeNative(source, multiLine, caseSensitive, false); + + get _nativeGlobalVersion { + if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp; + return _nativeGlobalRegExp = + makeNative(pattern, _isMultiLine, _isCaseSensitive, true); + } + + get _nativeAnchoredVersion { + if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp; + // An "anchored version" of a regexp is created by adding "|()" to the + // source. This means that the regexp always matches at the first position + // that it tries, and you can see if the original regexp matched, or it + // was the added zero-width match that matched, by looking at the last + // capture. If it is a String, the match participated, otherwise it didn't. + return _nativeAnchoredRegExp = + makeNative("$pattern|()", _isMultiLine, _isCaseSensitive, true); + } + + bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp); + bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp); + + static makeNative(@nullCheck String source, bool multiLine, + bool caseSensitive, bool global) { + String m = multiLine ? 'm' : ''; + String i = caseSensitive ? '' : 'i'; + String g = global ? 'g' : ''; + // We're using the JavaScript's try catch instead of the Dart one + // to avoid dragging in Dart runtime support just because of using + // RegExp. + var regexp = JS( + '', + '(function() {' + 'try {' + 'return new RegExp(#, # + # + #);' + '} catch (e) {' + 'return e;' + '}' + '})()', + source, + m, + i, + g); + if (JS('bool', '# instanceof RegExp', regexp)) return regexp; + // The returned value is the JavaScript exception. Turn it into a + // Dart exception. + String errorMessage = JS('String', r'String(#)', regexp); + throw FormatException("Illegal RegExp pattern: $source, $errorMessage"); + } + + Match firstMatch(@nullCheck String string) { + List m = JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp, string); + if (m == null) return null; + return _MatchImplementation(this, JSArray.of(m)); + } + + @notNull + bool hasMatch(@nullCheck String string) { + return JS('bool', r'#.test(#)', _nativeRegExp, string); + } + + String stringMatch(String string) { + var match = firstMatch(string); + if (match != null) return match.group(0); + return null; + } + + Iterable allMatches(@nullCheck String string, + [@nullCheck int start = 0]) { + if (start < 0 || start > string.length) { + throw RangeError.range(start, 0, string.length); + } + return _AllMatchesIterable(this, string, start); + } + + Match _execGlobal(String string, int start) { + Object regexp = _nativeGlobalVersion; + JS("void", "#.lastIndex = #", regexp, start); + List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string); + if (match == null) return null; + return _MatchImplementation(this, JSArray.of(match)); + } + + Match _execAnchored(String string, int start) { + Object regexp = _nativeAnchoredVersion; + JS("void", "#.lastIndex = #", regexp, start); + List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string); + if (match == null) return null; + // If the last capture group participated, the original regexp did not + // match at the start position. + if (match[match.length - 1] != null) return null; + match.length -= 1; + return _MatchImplementation(this, JSArray.of(match)); + } + + Match matchAsPrefix(String string, [int start = 0]) { + if (start < 0 || start > string.length) { + throw RangeError.range(start, 0, string.length); + } + return _execAnchored(string, start); + } + + bool get isMultiLine => _isMultiLine; + bool get isCaseSensitive => _isCaseSensitive; +} + +class _MatchImplementation implements Match { + final Pattern pattern; + // Contains a JS RegExp match object. + // It is an Array of String values with extra "index" and "input" properties. + final List _match; + + _MatchImplementation(this.pattern, this._match) { + assert(JS("var", "#.input", _match) is String); + assert(JS("var", "#.index", _match) is int); + } + + String get input => JS("String", "#.input", _match); + int get start => JS("int", "#.index", _match); + int get end => start + _match[0].length; + + String group(int index) => _match[index]; + String operator [](int index) => group(index); + int get groupCount => _match.length - 1; + + List groups(List groups) { + List out = []; + for (int i in groups) { + out.add(group(i)); + } + return out; + } +} + +class _AllMatchesIterable extends IterableBase { + final JSSyntaxRegExp _re; + final String _string; + final int _start; + + _AllMatchesIterable(this._re, this._string, this._start); + + Iterator get iterator => _AllMatchesIterator(_re, _string, _start); +} + +class _AllMatchesIterator implements Iterator { + final JSSyntaxRegExp _regExp; + String _string; + int _nextIndex; + Match _current; + + _AllMatchesIterator(this._regExp, this._string, this._nextIndex); + + Match get current => _current; + + bool moveNext() { + if (_string == null) return false; + if (_nextIndex <= _string.length) { + var match = _regExp._execGlobal(_string, _nextIndex); + if (match != null) { + _current = match; + int nextIndex = match.end; + if (match.start == nextIndex) { + nextIndex++; + } + _nextIndex = nextIndex; + return true; + } + } + _current = null; + _string = null; // Marks iteration as ended. + return false; + } +} + +/** Find the first match of [regExp] in [string] at or after [start]. */ +Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) { + return regExp._execGlobal(string, start); +} +NN<-@DBFKB/2/0IL +I0<CP*)+ ;AA!CEKOLKP#IEK>)%)"FG +  BF>M/P > ,<&$.7$.750*2L$B2,2L$K$6B8.7)(0.(P44171+,1+*8<M7 D!'(<#( + 1II,nfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart.// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._js_helper; + +@notNull +int stringIndexOfStringUnchecked(receiver, other, startIndex) { + return JS('int', '#.indexOf(#, #)', receiver, other, startIndex); +} + +@notNull +String substring1Unchecked(receiver, startIndex) { + return JS('!', '#.substring(#)', receiver, startIndex); +} + +@notNull +String substring2Unchecked(receiver, startIndex, endIndex) { + return JS('!', '#.substring(#, #)', receiver, startIndex, endIndex); +} + +@notNull +bool stringContainsStringUnchecked(receiver, other, startIndex) { + return stringIndexOfStringUnchecked(receiver, other, startIndex) >= 0; +} + +class StringMatch implements Match { + const StringMatch(int this.start, String this.input, String this.pattern); + + int get end => start + pattern.length; + String operator [](int g) => group(g); + int get groupCount => 0; + + String group(int group_) { + if (group_ != 0) { + throw RangeError.value(group_); + } + return pattern; + } + + List groups(List groups_) { + List result = List(); + for (int g in groups_) { + result.add(group(g)); + } + return result; + } + + final int start; + final String input; + final String pattern; +} + +Iterable allMatchesInStringUnchecked( + String pattern, String string, int startIndex) { + return _StringAllMatchesIterable(string, pattern, startIndex); +} + +class _StringAllMatchesIterable extends Iterable { + final String _input; + final String _pattern; + final int _index; + + _StringAllMatchesIterable(this._input, this._pattern, this._index); + + Iterator get iterator => + _StringAllMatchesIterator(_input, _pattern, _index); + + Match get first { + int index = stringIndexOfStringUnchecked(_input, _pattern, _index); + if (index >= 0) { + return StringMatch(index, _input, _pattern); + } + throw IterableElementError.noElement(); + } +} + +class _StringAllMatchesIterator implements Iterator { + final String _input; + final String _pattern; + int _index; + Match _current; + + _StringAllMatchesIterator(this._input, this._pattern, this._index); + + bool moveNext() { + if (_index + _pattern.length > _input.length) { + _current = null; + return false; + } + var index = stringIndexOfStringUnchecked(_input, _pattern, _index); + if (index < 0) { + _index = _input.length + 1; + _current = null; + return false; + } + int end = index + _pattern.length; + _current = StringMatch(index, _input, _pattern); + // Empty match, don't start at same location again. + if (end == _index) end++; + _index = end; + return true; + } + + Match get current => _current; +} + +@notNull +bool stringContainsUnchecked( + @notNull String receiver, @notNull other, int startIndex) { + if (other is String) { + return stringContainsStringUnchecked(receiver, other, startIndex); + } else if (other is JSSyntaxRegExp) { + return other.hasMatch(receiver.substring(startIndex)); + } else { + var substr = receiver.substring(startIndex); + return other.allMatches(substr).isNotEmpty; + } +} + +@notNull +String stringReplaceJS(String receiver, replacer, String replacement) { + // The JavaScript String.replace method recognizes replacement + // patterns in the replacement string. Dart does not have that + // behavior. + replacement = JS('String', r'#.replace(/\$/g, "$$$$")', replacement); + return JS('String', r'#.replace(#, #)', receiver, replacer, replacement); +} + +@notNull +String stringReplaceFirstRE(@notNull String receiver, JSSyntaxRegExp regexp, + String replacement, int startIndex) { + var match = regexp._execGlobal(receiver, startIndex); + if (match == null) return receiver; + var start = match.start; + var end = match.end; + return stringReplaceRangeUnchecked(receiver, start, end, replacement); +} + +/// Returns a string for a RegExp pattern that matches [string]. This is done by +/// escaping all RegExp metacharacters. +@notNull +String quoteStringForRegExp(string) { + return JS('String', r'#.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&")', string); +} + +@notNull +String stringReplaceAllUnchecked(@notNull String receiver, + @nullCheck Pattern pattern, @nullCheck String replacement) { + if (pattern is String) { + if (pattern == "") { + if (receiver == "") { + return replacement; + } else { + StringBuffer result = StringBuffer(); + int length = receiver.length; + result.write(replacement); + for (int i = 0; i < length; i++) { + result.write(receiver[i]); + result.write(replacement); + } + return result.toString(); + } + } else { + var quoted = quoteStringForRegExp(pattern); + var replacer = JS('', "new RegExp(#, 'g')", quoted); + return stringReplaceJS(receiver, replacer, replacement); + } + } else if (pattern is JSSyntaxRegExp) { + var re = regExpGetGlobalNative(pattern); + return stringReplaceJS(receiver, re, replacement); + } else { + // TODO(floitsch): implement generic String.replace (with patterns). + throw "String.replaceAll(Pattern) UNIMPLEMENTED"; + } +} + +String _matchString(Match match) => match[0]; +String _stringIdentity(String string) => string; + +@notNull +String stringReplaceAllFuncUnchecked( + String receiver, + @nullCheck Pattern pattern, + String onMatch(Match match), + String onNonMatch(String nonMatch)) { + if (onMatch == null) onMatch = _matchString; + if (onNonMatch == null) onNonMatch = _stringIdentity; + if (pattern is String) { + return stringReplaceAllStringFuncUnchecked( + receiver, pattern, onMatch, onNonMatch); + } + StringBuffer buffer = StringBuffer(); + int startIndex = 0; + for (Match match in pattern.allMatches(receiver)) { + buffer.write(onNonMatch(receiver.substring(startIndex, match.start))); + buffer.write(onMatch(match)); + startIndex = match.end; + } + buffer.write(onNonMatch(receiver.substring(startIndex))); + return buffer.toString(); +} + +@notNull +String stringReplaceAllEmptyFuncUnchecked(String receiver, + String onMatch(Match match), String onNonMatch(String nonMatch)) { + // Pattern is the empty string. + StringBuffer buffer = StringBuffer(); + int length = receiver.length; + int i = 0; + buffer.write(onNonMatch("")); + while (i < length) { + buffer.write(onMatch(StringMatch(i, receiver, ""))); + // Special case to avoid splitting a surrogate pair. + int code = receiver.codeUnitAt(i); + if ((code & ~0x3FF) == 0xD800 && length > i + 1) { + // Leading surrogate; + code = receiver.codeUnitAt(i + 1); + if ((code & ~0x3FF) == 0xDC00) { + // Matching trailing surrogate. + buffer.write(onNonMatch(receiver.substring(i, i + 2))); + i += 2; + continue; + } + } + buffer.write(onNonMatch(receiver[i])); + i++; + } + buffer.write(onMatch(StringMatch(i, receiver, ""))); + buffer.write(onNonMatch("")); + return buffer.toString(); +} + +@notNull +String stringReplaceAllStringFuncUnchecked(String receiver, String pattern, + String onMatch(Match match), String onNonMatch(String nonMatch)) { + int patternLength = pattern.length; + if (patternLength == 0) { + return stringReplaceAllEmptyFuncUnchecked(receiver, onMatch, onNonMatch); + } + int length = receiver.length; + StringBuffer buffer = StringBuffer(); + int startIndex = 0; + while (startIndex < length) { + int position = stringIndexOfStringUnchecked(receiver, pattern, startIndex); + if (position == -1) { + break; + } + buffer.write(onNonMatch(receiver.substring(startIndex, position))); + buffer.write(onMatch(StringMatch(position, receiver, pattern))); + startIndex = position + patternLength; + } + buffer.write(onNonMatch(receiver.substring(startIndex))); + return buffer.toString(); +} + +@notNull +String stringReplaceFirstUnchecked(@notNull String receiver, + @nullCheck Pattern pattern, String replacement, int startIndex) { + if (pattern is String) { + int index = stringIndexOfStringUnchecked(receiver, pattern, startIndex); + if (index < 0) return receiver; + int end = index + pattern.length; + return stringReplaceRangeUnchecked(receiver, index, end, replacement); + } + if (pattern is JSSyntaxRegExp) { + return startIndex == 0 + ? stringReplaceJS(receiver, regExpGetNative(pattern), replacement) + : stringReplaceFirstRE(receiver, pattern, replacement, startIndex); + } + Iterator matches = pattern.allMatches(receiver, startIndex).iterator; + if (!matches.moveNext()) return receiver; + Match match = matches.current; + return receiver.replaceRange(match.start, match.end, replacement); +} + +@notNull +String stringReplaceFirstMappedUnchecked(String receiver, Pattern pattern, + String replace(Match current), int startIndex) { + Iterator matches = pattern.allMatches(receiver, startIndex).iterator; + if (!matches.moveNext()) return receiver; + Match match = matches.current; + String replacement = "${replace(match)}"; + return receiver.replaceRange(match.start, match.end, replacement); +} + +@notNull +String stringJoinUnchecked(array, separator) { + return JS('String', r'#.join(#)', array, separator); +} + +@notNull +String stringReplaceRangeUnchecked( + String receiver, int start, int end, String replacement) { + String prefix = JS('!', '#.substring(0, #)', receiver, start); + String suffix = JS('!', '#.substring(#)', receiver, end); + return "$prefix$replacement$suffix"; +} +,NN< @D 3: =G BI%M))&+*-5A:F";H3,=F4H"'58! @G(; 10 HAAHL M*8&IQ( &L ;A.&#+%% +" 2;?*-7 I6.1 & !*/801(6K"< ;G"( 99'7)'(@+ 7  LG&N ( P HE+< =FM$&K#KLO,!E K5O,!,E /7 $?A<'gfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/js_rti.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._js_helper; + +// TODO(leafp): Maybe get rid of this? Currently used by the interceptors +// library, but that should probably be culled as well. +Type getRuntimeType(var object) => + JS('Type|null', 'dart.getReifiedType(#)', object); + +/// Returns the property [index] of the JavaScript array [array]. +getIndex(var array, int index) { + assert(isJsArray(array)); + return JS('var', r'#[#]', array, index); +} + +/// Returns the length of the JavaScript array [array]. +int getLength(var array) { + assert(isJsArray(array)); + return JS('int', r'#.length', array); +} + +/// Returns whether [value] is a JavaScript array. +bool isJsArray(var value) { + return value is JSArray; +} +NN<K8#7B!+8(3nfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/native_helper.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart._js_helper; + +// Obsolete in dart dev compiler. Added only so that the same version of +// dart:html can be used in dart2js an dev compiler. +F convertDartClosureToJS(F closure, int arity) { + return closure; +} + +// Warning: calls to these methods need to be removed before custom elements +// and cross-frame dom objects behave correctly in ddc +// https://github.com/dart-lang/sdk/issues/28326 +setNativeSubclassDispatchRecord(proto, interceptor) {} +findDispatchTagForInterceptorClass(interceptorClassConstructor) {} +makeLeafDispatchRecord(interceptor) {} +NN<I54M717C'kfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dartI// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart._js_mirrors; + +import 'dart:mirrors'; +import 'dart:_runtime' as dart; +import 'dart:_foreign_helper' show JS; +import 'dart:_internal' as _internal show Symbol; +import 'dart:_js_helper' show PrivateSymbol; + +String getName(Symbol symbol) { + if (symbol is PrivateSymbol) { + return PrivateSymbol.getName(symbol); + } else { + return _internal.Symbol.getName(symbol as _internal.Symbol); + } +} + +Symbol getSymbol(name, library) => + throw UnimplementedError("MirrorSystem.getSymbol unimplemented"); + +final currentJsMirrorSystem = JsMirrorSystem(); + +final _typeMirror = JS('', 'Symbol("_typeMirror")'); + +InstanceMirror reflect(reflectee) { + // TODO(vsm): Consider caching the mirror here. Unlike the type below, + // reflectee may be a primitive - i.e., we can't just add an expando. + if (reflectee is Function) { + return JsClosureMirror._(reflectee); + } else { + return JsInstanceMirror._(reflectee); + } +} + +TypeMirror reflectType(Type key) { + var unwrapped = dart.unwrapType(key); + var property = + JS('', 'Object.getOwnPropertyDescriptor(#, #)', unwrapped, _typeMirror); + if (property != null) { + return JS('', '#.value', property); + } + // TODO(vsm): Might not be a class. + var mirror = JsClassMirror._(key); + JS('', '#[#] = #', unwrapped, _typeMirror, mirror); + return mirror; +} + +typedef T _Lazy(); + +dynamic _getESSymbol(Symbol symbol) => PrivateSymbol.getNativeSymbol(symbol); + +dynamic _getMember(Symbol symbol) { + var privateSymbol = _getESSymbol(symbol); + if (privateSymbol != null) { + return privateSymbol; + } + var name = getName(symbol); + // TODO(jacobr): this code is duplicated in code_generator.dart + switch (name) { + case '[]': + name = '_get'; + break; + case '[]=': + name = '_set'; + break; + case 'unary-': + name = '_negate'; + break; + case 'constructor': + case 'prototype': + name = '_$name'; + break; + } + return name; +} + +String _getNameForESSymbol(member) { + // Convert private JS symbol "Symbol(_foo)" to string "_foo". + assert(JS('bool', 'typeof # == "symbol"', member)); + var str = member.toString(); + assert(str.startsWith('Symbol(') && str.endsWith(')')); + return str.substring(7, str.length - 1); +} + +Symbol _getSymbolForESSymbol(member) { + var name = _getNameForESSymbol(member); + return PrivateSymbol(name, member); +} + +// The [member] must be either a string (public) or an ES6 symbol (private). +Symbol _getSymbolForMember(member) { + if (member is String) { + return Symbol(member); + } else { + var name = _getNameForESSymbol(member); + return PrivateSymbol(name, member); + } +} + +Map _toDartMap(data) { + if (data == null) return {}; + var map = Map(); + // Note: we recorded a map from fields/methods to their type and metadata. + // The key is a string name for public members but an ES6 symbol for private + // ones. That's works nicely for dynamic operations, but dart:mirrors expects + // Dart symbols, so we convert here. + var publicMembers = JS('', 'Object.getOwnPropertyNames(#)', data); + for (var member in publicMembers) { + var symbol = Symbol(member); + map[symbol] = JS('', '#[#]', data, member); + } + + var privateMembers = JS('', 'Object.getOwnPropertySymbols(#)', data); + for (var member in privateMembers) { + var symbol = _getSymbolForESSymbol(member); + map[symbol] = JS('', '#[#]', data, member); + } + return map; +} + +dynamic _runtimeType(obj) => dart.wrapType(dart.getReifiedType(obj)); + +_unimplemented(Type t, Invocation i) { + throw UnimplementedError('$t.${getName(i.memberName)} unimplemented'); +} + +dynamic _toJsMap(Map map) { + if (map == null) return null; + var obj = JS('', '{}'); + map.forEach((Symbol key, value) { + JS('', '#[#] = #', obj, getName(key), value); + }); + return obj; +} + +class JsMirrorSystem implements MirrorSystem { + get libraries => const {}; + + noSuchMethod(Invocation i) { + _unimplemented(this.runtimeType, i); + } +} + +class JsMirror implements Mirror { + noSuchMethod(Invocation i) { + _unimplemented(this.runtimeType, i); + } +} + +class JsCombinatorMirror extends JsMirror implements CombinatorMirror {} + +class JsDeclarationMirror extends JsMirror implements DeclarationMirror {} + +class JsIsolateMirror extends JsMirror implements IsolateMirror {} + +class JsLibraryDependencyMirror extends JsMirror + implements LibraryDependencyMirror {} + +class JsObjectMirror extends JsMirror implements ObjectMirror {} + +class JsInstanceMirror extends JsObjectMirror implements InstanceMirror { + // Reflected object + final reflectee; + bool get hasReflectee => true; + + ClassMirror get type { + // The spec guarantees that `null` is the singleton instance of the `Null` + // class. + if (reflectee == null) return reflectClass(Null); + return reflectType(_runtimeType(reflectee)); + } + + JsInstanceMirror._(this.reflectee); + + bool operator ==(Object other) { + return (other is JsInstanceMirror) && identical(reflectee, other.reflectee); + } + + int get hashCode { + // Avoid hash collisions with the reflectee. This constant is in Smi range + // and happens to be the inner padding from RFC 2104. + return identityHashCode(reflectee) ^ 0x36363636; + } + + InstanceMirror getField(Symbol symbol) { + var name = _getMember(symbol); + var field = dart.dloadMirror(reflectee, name); + return reflect(field); + } + + InstanceMirror setField(Symbol symbol, Object value) { + var name = _getMember(symbol); + dart.dputMirror(reflectee, name, value); + return reflect(value); + } + + InstanceMirror invoke(Symbol symbol, List args, + [Map namedArgs]) { + var name = _getMember(symbol); + var result = + dart.callMethod(reflectee, name, null, args, _toJsMap(namedArgs), name); + return reflect(result); + } + + String toString() => "InstanceMirror on '$reflectee'"; +} + +class JsClosureMirror extends JsInstanceMirror implements ClosureMirror { + JsClosureMirror._(reflectee) : super._(reflectee); + + InstanceMirror apply(List args, [Map namedArgs]) { + var result = dart.dcall(reflectee, args, _toJsMap(namedArgs)); + return reflect(result); + } +} + +// For generic classes, mirrors uses the same representation, [ClassMirror], +// for the instantiated and uninstantiated type. Somewhat awkwardly, most APIs +// (e.g., [newInstance]) treat the uninstantiated type as if instantiated +// with all dynamic. The representation below is correspondingly a bit wonky. +// For an uninstantiated generic class, [_cls] is the instantiated type (with +// dynamic) and [_raw] is null. For an instantiated generic class, [_cls] is +// the instantiated type (with the corresponding type parameters), and [_raw] +// is the generic factory. +class JsClassMirror extends JsMirror implements ClassMirror { + final Type _cls; + final Symbol simpleName; + // Generic class factory for instantiated types. + final dynamic _raw; + + ClassMirror _originalDeclaration; + + // TODO(vsm): Do this properly + ClassMirror _mixin = null; + List _typeArguments; + + List _metadata; + Map _declarations; + + List get metadata { + if (_metadata == null) { + // Load metadata. + var unwrapped = dart.unwrapType(_cls); + // Only get metadata directly embedded on this class, not its + // superclasses. + Function fn = JS( + '', + 'Object.hasOwnProperty.call(#, dart.metadata) ? #[dart.metadata] : null', + unwrapped, + unwrapped); + _metadata = (fn == null) + ? const [] + : List.unmodifiable(fn().map((i) => reflect(i))); + } + return _metadata; + } + + Map get declarations { + if (_declarations == null) { + // Load declarations. + // TODO(vsm): This is only populating the default constructor right now. + _declarations = Map(); + var unwrapped = dart.unwrapType(_cls); + var constructors = _toDartMap(dart.getConstructors(unwrapped)); + constructors.forEach((symbol, ft) { + var name = getName(symbol); + _declarations[symbol] = JsMethodMirror._constructor(this, symbol, ft); + }); + if (constructors.isEmpty) { + // Add a default + var name = 'new'; + var ft = dart.fnType(dart.unwrapType(_cls), []); + var symbol = Symbol(name); + _declarations[symbol] = JsMethodMirror._constructor(this, symbol, ft); + } + var fields = _toDartMap(dart.getFields(unwrapped)); + fields.forEach((symbol, t) { + _declarations[symbol] = JsVariableMirror._fromField(symbol, t); + }); + var methods = _toDartMap(dart.getMethods(unwrapped)); + methods.forEach((symbol, ft) { + var name = getName(symbol); + _declarations[symbol] = + JsMethodMirror._instanceMethod(this, symbol, ft); + }); + + getterType(type) { + if (JS('bool', '# instanceof Array', type)) { + var array = JS('', '#.slice()', type); + type = JS('', '#[0]', array); + JS('', '#[0] = #', array, dart.fnType(type, [])); + return array; + } else { + return dart.fnType(type, []); + } + } + + var getters = _toDartMap(dart.getGetters(unwrapped)); + getters.forEach((symbol, type) { + _declarations[symbol] = + JsMethodMirror._instanceMethod(this, symbol, getterType(type)); + }); + + setterType(type) { + if (JS('bool', '# instanceof Array', type)) { + var array = JS('', '#.slice()', type); + type = JS('', '#[0]', array); + JS('', '#[0] = #', array, dart.fnType(dart.void_, [type])); + return array; + } else { + return dart.fnType(dart.void_, [type]); + } + } + + var setters = _toDartMap(dart.getSetters(unwrapped)); + setters.forEach((symbol, type) { + var name = getName(symbol) + '='; + // Create a separate symbol for the setter. + symbol = PrivateSymbol(name, _getESSymbol(symbol)); + _declarations[symbol] = + JsMethodMirror._instanceMethod(this, symbol, setterType(type)); + }); + + var staticFields = _toDartMap(dart.getStaticFields(unwrapped)); + staticFields.forEach((symbol, t) { + _declarations[symbol] = JsVariableMirror._fromField(symbol, t); + }); + var statics = _toDartMap(dart.getStaticMethods(unwrapped)); + statics.forEach((symbol, ft) { + _declarations[symbol] = JsMethodMirror._staticMethod(this, symbol, ft); + }); + + var staticGetters = _toDartMap(dart.getStaticGetters(unwrapped)); + staticGetters.forEach((symbol, type) { + _declarations[symbol] = + JsMethodMirror._staticMethod(this, symbol, getterType(type)); + }); + + var staticSetters = _toDartMap(dart.getStaticSetters(unwrapped)); + staticSetters.forEach((symbol, type) { + _declarations[symbol] = + JsMethodMirror._staticMethod(this, symbol, setterType(type)); + }); + _declarations = + Map.unmodifiable(_declarations); + } + return _declarations; + } + + JsClassMirror._(Type cls, {bool instantiated = true}) + : _cls = cls, + _raw = instantiated ? dart.getGenericClass(dart.unwrapType(cls)) : null, + simpleName = Symbol(JS('String', '#.name', dart.unwrapType(cls))) { + var typeArgs = dart.getGenericArgs(dart.unwrapType(_cls)); + if (typeArgs == null) { + _typeArguments = const []; + } else { + _typeArguments = + List.unmodifiable(typeArgs.map((t) => reflectType(dart.wrapType(t)))); + } + } + + InstanceMirror newInstance(Symbol constructorName, List args, + [Map namedArgs]) { + // TODO(vsm): Support named arguments. + var name = getName(constructorName); + assert(namedArgs == null || namedArgs.isEmpty); + // Default constructors are mapped to new. + if (name == '') name = 'new'; + var cls = dart.unwrapType(_cls); + var ctr = JS('', '#.#', cls, name); + // Only generative Dart constructors are wired up as real JS constructors. + var instance = JS('bool', '#.prototype == #.prototype', cls, ctr) + // Generative + ? JS('', 'new #(...#)', ctr, args) + // Factory + : JS('', '#(...#)', ctr, args); + return reflect(instance); + } + + // TODO(vsm): Need to check for NSM, types on accessors below. Unlike the + // InstanceMirror case, there is no dynamic helper to delegate to - we never + // need a dload, etc. on a static. + + InstanceMirror getField(Symbol symbol) { + var name = getName(symbol); + return reflect(JS('', '#[#]', dart.unwrapType(_cls), name)); + } + + InstanceMirror setField(Symbol symbol, Object value) { + var name = getName(symbol); + JS('', '#[#] = #', dart.unwrapType(_cls), name, value); + return reflect(value); + } + + InstanceMirror invoke(Symbol symbol, List args, + [Map namedArgs]) { + var name = getName(symbol); + if (namedArgs != null) { + args = List.from(args); + args.add(_toJsMap(namedArgs)); + } + var result = JS('', '#.#(...#)', dart.unwrapType(_cls), name, args); + return reflect(result); + } + + List get superinterfaces { + _Lazy> interfaceThunk = + JS('', '#[dart.implements]', dart.unwrapType(_cls)); + if (interfaceThunk == null) { + return []; + } else { + List interfaces = interfaceThunk(); + return interfaces.map((t) => reflectType(t)).toList(); + } + } + + bool get hasReflectedType => true; + Type get reflectedType { + return _cls; + } + + bool get isOriginalDeclaration => _raw == null; + + List get typeArguments => _typeArguments; + + TypeMirror get originalDeclaration { + if (_raw == null) { + return this; + } + if (_originalDeclaration != null) { + return _originalDeclaration; + } + _originalDeclaration = JsClassMirror._(dart.wrapType(JS('', '#()', _raw)), + instantiated: false); + return _originalDeclaration; + } + + ClassMirror get superclass { + if (_cls == Object) { + return null; + } else { + return reflectType( + dart.wrapType(JS('Type', '#.__proto__', dart.unwrapType(_cls)))); + } + } + + ClassMirror get mixin { + if (_mixin != null) { + return _mixin; + } + var mixin = dart.getMixin(dart.unwrapType(_cls)); + if (mixin == null) { + // If there is no mixin, return this mirror per API. + _mixin = this; + return _mixin; + } + _mixin = reflectType(dart.wrapType(mixin)); + return _mixin; + } + + String toString() => "ClassMirror on '$_cls'"; +} + +class JsVariableMirror extends JsMirror implements VariableMirror { + final Symbol _symbol; + final String _name; + final TypeMirror type; + final List metadata; + final bool isFinal; + + // TODO(vsm): Refactor this out. + Symbol get simpleName => _symbol; + + // TODO(vsm): Fix this + final bool isStatic = false; + + JsVariableMirror._(Symbol symbol, Type t, List annotations, + {this.isFinal = false}) + : _symbol = symbol, + _name = getName(symbol), + type = reflectType(t), + metadata = + List.unmodifiable(annotations?.map(reflect) ?? []); + + JsVariableMirror._fromField(Symbol symbol, fieldInfo) + : this._(symbol, dart.wrapType(JS('', '#.type', fieldInfo)), + JS('', '#.metadata', fieldInfo), + isFinal: JS('bool', '#.isFinal', fieldInfo)); + + String toString() => "VariableMirror on '$_name'"; +} + +class JsParameterMirror extends JsVariableMirror implements ParameterMirror { + JsParameterMirror._(Symbol member, Type t, List annotations) + : super._(member, t, annotations); + + String toString() => "ParameterMirror on '$_name'"; +} + +class JsMethodMirror extends JsMirror implements MethodMirror { + final Symbol _symbol; + final String _name; + List _params; + List _metadata; + final bool isConstructor; + final bool isStatic; + + // TODO(vsm): Fix this + final bool isFinal = false; + bool get isSetter => _name.endsWith('='); + bool get isPrivate => _name.startsWith('_'); + + // TODO(vsm): Refactor this out. + Symbol get simpleName => _symbol; + + JsMethodMirror._constructor(JsClassMirror cls, Symbol symbol, ftype) + : _symbol = symbol, + _name = getName(symbol), + isConstructor = true, + isStatic = false { + _createParameterMirrorList(ftype); + } + + JsMethodMirror._instanceMethod(JsClassMirror cls, Symbol symbol, ftype) + : _symbol = symbol, + _name = getName(symbol), + isConstructor = false, + isStatic = false { + _createParameterMirrorList(ftype); + } + + JsMethodMirror._staticMethod(JsClassMirror cls, Symbol symbol, ftype) + : _symbol = symbol, + _name = getName(symbol), + isConstructor = false, + isStatic = true { + _createParameterMirrorList(ftype); + } + + // TODO(vsm): Support named constructors. + Symbol get constructorName => isConstructor ? _symbol : null; + List get parameters => _params; + List get metadata => _metadata; + + void _createParameterMirrorList(ftype) { + if (ftype == null) { + // TODO(vsm): No explicit constructor. Verify this. + _params = const []; + _metadata = const []; + return; + } + + // TODO(vsm): Why does generic function type trigger true for List? + if (ftype is! Function && ftype is List) { + // Record metadata + _metadata = List.unmodifiable( + ftype.skip(1).map((a) => reflect(a))); + ftype = ftype[0]; + } else { + _metadata = const []; + } + + // TODO(vsm): Handle generic function types properly. Or deprecate mirrors + // before we need to! + ftype = dart.getFunctionTypeMirror(ftype); + + // TODO(vsm): Add named args. + List args = ftype.args; + List opts = ftype.optionals; + var params = List(args.length + opts.length); + + for (var i = 0; i < args.length; ++i) { + var type = args[i]; + var metadata = ftype.metadata[i]; + // TODO(vsm): Recover the param name. + var param = + JsParameterMirror._(Symbol(''), dart.wrapType(type), metadata); + params[i] = param; + } + + for (var i = 0; i < opts.length; ++i) { + var type = opts[i]; + var metadata = ftype.metadata[args.length + i]; + // TODO(vsm): Recover the param name. + var param = + JsParameterMirror._(Symbol(''), dart.wrapType(type), metadata); + params[i + args.length] = param; + } + + _params = List.unmodifiable(params); + } + + String toString() => "MethodMirror on '$_name'"; +} +XNN< '2- !* A#F05$JH) *#(O(&%6N$,B    %@6:+'*&M% ,(($MOQ'E&!0H'00F'I- $2/)#)IKC1*AJ!O61&#QO:5+#39#-;*#Q9J5OCMPJONNN>3$!#"0&-DT%L4!O8-F*$O +"9#O:#H +<%$ > +61(<( +<' L +61(F2 +<'*4< L +F)H +B%P +H- J +H- J +F8QL?! Q@*+)4/"%(OF+(MO%+ A9 <;* %I*'=" 0=%28'(#O! L6;01D'#$>!P8C-:5N?)6@!",/#$G!'J!'H!',@32+;H/51 P/"!C,(,J,6,J')3Pfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/mirrors/mirrors.dart—// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// For the purposes of the mirrors library, we adopt a naming +// convention with respect to getters and setters. Specifically, for +// some variable or field... +// +// var myField; +// +// ...the getter is named 'myField' and the setter is named +// 'myField='. This allows us to assign unique names to getters and +// setters for the purposes of member lookup. + +/** + * Basic reflection in Dart, + * with support for introspection and dynamic invocation. + * + * *Introspection* is that subset of reflection by which a running + * program can examine its own structure. For example, a function + * that prints out the names of all the members of an arbitrary object. + * + * *Dynamic invocation* refers the ability to evaluate code that + * has not been literally specified at compile time, such as calling a method + * whose name is provided as an argument (because it is looked up + * in a database, or provided interactively by the user). + * + * ## How to interpret this library's documentation + * + * As a rule, the names of Dart declarations are represented using + * instances of class [Symbol]. Whenever the doc speaks of an object *s* + * of class [Symbol] denoting a name, it means the string that + * was used to construct *s*. + * + * The documentation frequently abuses notation with + * Dart pseudo-code such as [:o.x(a):], where + * o and a are defined to be objects; what is actually meant in these + * cases is [:o'.x(a'):] where *o'* and *a'* are Dart variables + * bound to *o* and *a* respectively. Furthermore, *o'* and *a'* + * are assumed to be fresh variables (meaning that they are + * distinct from any other variables in the program). + * + * Sometimes the documentation refers to *serializable* objects. + * An object is serializable across isolates if and only if it is an instance of + * num, bool, String, a list of objects that are serializable + * across isolates, or a map with keys and values that are all serializable across + * isolates. + * + * ## Status: Unstable + * + * The dart:mirrors library is unstable and its API might change slightly as a + * result of user feedback. This library is platform dependent and therefore it + * has implementations for both dart2js and the Dart VM. Both are under + * development and may not support all operations yet. + * + * {@category VM} + */ +library dart.mirrors; + +import 'dart:async' show Future; + +/** + * A [MirrorSystem] is the main interface used to reflect on a set of + * associated libraries. + * + * At runtime each running isolate has a distinct [MirrorSystem]. + * + * It is also possible to have a [MirrorSystem] which represents a set + * of libraries which are not running -- perhaps at compile-time. In + * this case, all available reflective functionality would be + * supported, but runtime functionality (such as invoking a function + * or inspecting the contents of a variable) would fail dynamically. + */ +abstract class MirrorSystem { + /** + * All libraries known to the mirror system, indexed by their URI. + * + * Returns an unmodifiable map of the libraries with [LibraryMirror.uri] as + * keys. + * + * For a runtime mirror system, only libraries which are currently loaded + * are included, and repeated calls of this method may return different maps + * as libraries are loaded. + */ + Map get libraries; + + /** + * Returns the unique library named [libraryName] if it exists. + * + * If no unique library exists, an error is thrown. + */ + external LibraryMirror findLibrary(Symbol libraryName); + + /** + * A mirror on the isolate associated with this [MirrorSystem]. + * + * This may be null if this mirror system is not running. + */ + IsolateMirror get isolate; + + /** + * A mirror on the [:dynamic:] type. + */ + TypeMirror get dynamicType; + + /** + * A mirror on the [:void:] type. + */ + TypeMirror get voidType; + + /** + * Returns the name of [symbol]. + * + * The following text is non-normative: + * + * Using this method may result in larger output. If possible, use + * [MirrorsUsed] to specify which symbols must be retained in clear text. + */ + external static String getName(Symbol symbol); + + /** + * Returns a symbol for [name]. + * + * If [library] is not a [LibraryMirror] or if [name] is a private identifier + * and [library] is `null`, throws an [ArgumentError]. If [name] is a private + * identifier, the symbol returned is with respect to [library]. + * + * The following text is non-normative: + * + * Using this method may result in larger output. If possible, use + * the const constructor of [Symbol] or symbol literals. + */ + external static Symbol getSymbol(String name, [LibraryMirror library]); +} + +/** + * Returns a [MirrorSystem] for the current isolate. + */ +external MirrorSystem currentMirrorSystem(); + +/** + * Reflects an instance. + * + * Returns an [InstanceMirror] reflecting [reflectee]. If [reflectee] is a + * function or an instance of a class that has a [:call:] method, the returned + * instance mirror will be a [ClosureMirror]. + * + * Note that since one cannot obtain an object from another isolate, this + * function can only be used to obtain mirrors on objects of the current + * isolate. + */ +external InstanceMirror reflect(Object reflectee); + +/** + * Reflects a class declaration. + * + * Let *C* be the original class declaration of the class represented by [key]. + * This function returns a [ClassMirror] reflecting *C*. + * + * If [key] is not an instance of [Type], then this function throws an + * [ArgumentError]. If [key] is the Type for dynamic or a function typedef, + * throws an [ArgumentError]. + * + * Note that since one cannot obtain a [Type] object from another isolate, this + * function can only be used to obtain class mirrors on classes of the current + * isolate. + */ +external ClassMirror reflectClass(Type key); + +/** + * Reflects the type represented by [key]. + * + * If [key] is not an instance of [Type], then this function throws an + * [ArgumentError]. + * + * Optionally takes a list of [typeArguments] for generic classes. If the list + * is provided, then the [key] must be a generic class type, and the number of + * the provided type arguments must be equal to the number of type variables + * declared by the class. + * + * Note that since one cannot obtain a [Type] object from another isolate, this + * function can only be used to obtain type mirrors on types of the current + * isolate. + */ +external TypeMirror reflectType(Type key, [List typeArguments]); + +/** + * A [Mirror] reflects some Dart language entity. + * + * Every [Mirror] originates from some [MirrorSystem]. + */ +abstract class Mirror {} + +/** + * An [IsolateMirror] reflects an isolate. + */ +abstract class IsolateMirror implements Mirror { + /** + * A unique name used to refer to the isolate in debugging messages. + */ + String get debugName; + + /** + * Whether this mirror reflects the currently running isolate. + */ + bool get isCurrent; + + /** + * The root library for the reflected isolate. + */ + LibraryMirror get rootLibrary; + + /** + * Whether [other] is an [IsolateMirror] on the same isolate as this mirror. + * + * The equality holds if and only if + * + * 1. [other] is a mirror of the same kind, and + * 2. the isolate being reflected by this mirror is the same isolate being + * reflected by [other]. + */ + bool operator ==(other); + + /** + * Loads the library at the given uri into this isolate. + * + * WARNING: You are strongly encouraged to use Isolate.spawnUri instead when + * possible. IsolateMirror.loadUri should only be used when synchronous + * communication or shared state with dynamically loaded code is needed. + * + * If a library with the same canonicalized uri has already been loaded, + * the existing library will be returned. (The isolate will not load a new + * copy of the library.) + * + * This behavior is similar to the behavior of an import statement that + * appears in the root library, except that the import scope of the root + * library is not changed. + */ + Future loadUri(Uri uri); +} + +/** + * A [DeclarationMirror] reflects some entity declared in a Dart program. + */ +abstract class DeclarationMirror implements Mirror { + /** + * The simple name for this Dart language entity. + * + * The simple name is in most cases the identifier name of the entity, + * such as 'myMethod' for a method, [:void myMethod() {...}:] or 'mylibrary' + * for a [:library 'mylibrary';:] declaration. + */ + Symbol get simpleName; + + /** + * The fully-qualified name for this Dart language entity. + * + * This name is qualified by the name of the owner. For instance, + * the qualified name of a method 'method' in class 'Class' in + * library 'library' is 'library.Class.method'. + * + * Returns a [Symbol] constructed from a string representing the + * fully qualified name of the reflectee. + * Let *o* be the [owner] of this mirror, let *r* be the reflectee of + * this mirror, let *p* be the fully qualified + * name of the reflectee of *o*, and let *s* be the simple name of *r* + * computed by [simpleName]. + * The fully qualified name of *r* is the + * concatenation of *p*, '.', and *s*. + * + * Because an isolate can contain more than one library with the same name (at + * different URIs), a fully-qualified name does not uniquely identify any + * language entity. + */ + Symbol get qualifiedName; + + /** + * A mirror on the owner of this Dart language entity. + * + * The owner is the declaration immediately surrounding the reflectee: + * + * * For a library, the owner is [:null:]. + * * For a class declaration, typedef or top level function or variable, the + * owner is the enclosing library. + * * For a mixin application `S with M`, the owner is the owner of `M`. + * * For a constructor, the owner is the immediately enclosing class. + * * For a method, instance variable or a static variable, the owner is the + * immediately enclosing class, unless the class is a mixin application + * `S with M`, in which case the owner is `M`. Note that `M` may be an + * invocation of a generic. + * * For a parameter, local variable or local function the owner is the + * immediately enclosing function. + */ + DeclarationMirror get owner; + + /** + * Whether this declaration is library private. + * + * Always returns `false` for a library declaration, + * otherwise returns `true` if the declaration's name starts with an + * underscore character (`_`), and `false` if it doesn't. + */ + bool get isPrivate; + + /** + * Whether this declaration is top-level. + * + * A declaration is considered top-level if its [owner] is a [LibraryMirror]. + */ + bool get isTopLevel; + + /** + * The source location of this Dart language entity, or [:null:] if the + * entity is synthetic. + * + * If the reflectee is a variable, the returned location gives the position + * of the variable name at its point of declaration. + * + * If the reflectee is a library, class, typedef, function or type variable + * with associated metadata, the returned location gives the position of the + * first metadata declaration associated with the reflectee. + * + * Otherwise: + * + * If the reflectee is a library, the returned location gives the position of + * the keyword 'library' at the reflectee's point of declaration, if the + * reflectee is a named library, or the first character of the first line in + * the compilation unit defining the reflectee if the reflectee is anonymous. + * + * If the reflectee is an abstract class, the returned location gives the + * position of the keyword 'abstract' at the reflectee's point of declaration. + * Otherwise, if the reflectee is a class, the returned location gives the + * position of the keyword 'class' at the reflectee's point of declaration. + * + * If the reflectee is a typedef the returned location gives the position of + * the of the keyword 'typedef' at the reflectee's point of declaration. + * + * If the reflectee is a function with a declared return type, the returned + * location gives the position of the function's return type at the + * reflectee's point of declaration. Otherwise. the returned location gives + * the position of the function's name at the reflectee's point of + * declaration. + * + * This operation is optional and may throw an [UnsupportedError]. + */ + SourceLocation get location; + + /** + * A list of the metadata associated with this declaration. + * + * Let *D* be the declaration this mirror reflects. + * If *D* is decorated with annotations *A1, ..., An* + * where *n > 0*, then for each annotation *Ai* associated + * with *D, 1 <= i <= n*, let *ci* be the constant object + * specified by *Ai*. Then this method returns a list whose + * members are instance mirrors on *c1, ..., cn*. + * If no annotations are associated with *D*, then + * an empty list is returned. + * + * If evaluating any of *c1, ..., cn* would cause a + * compilation error + * the effect is the same as if a non-reflective compilation error + * had been encountered. + */ + List get metadata; +} + +/** + * An [ObjectMirror] is a common superinterface of [InstanceMirror], + * [ClassMirror], and [LibraryMirror] that represents their shared + * functionality. + * + * For the purposes of the mirrors library, these types are all + * object-like, in that they support method invocation and field + * access. Real Dart objects are represented by the [InstanceMirror] + * type. + * + * See [InstanceMirror], [ClassMirror], and [LibraryMirror]. + */ +abstract class ObjectMirror implements Mirror { + /** + * Invokes the named function and returns a mirror on the result. + * + * Let *o* be the object reflected by this mirror, let *f* be the simple name + * of the member denoted by [memberName], let *a1, ..., an* be the elements + * of [positionalArguments], let *k1, ..., km* be the identifiers denoted by + * the elements of [namedArguments.keys], and let *v1, ..., vm* be the + * elements of [namedArguments.values]. Then this method will perform the + * method invocation *o.f(a1, ..., an, k1: v1, ..., km: vm)* in a scope that + * has access to the private members of *o* (if *o* is a class or library) or + * the private members of the class of *o* (otherwise). + * + * If the invocation returns a result *r*, this method returns the result of + * calling [reflect]\(*r*\). + * + * If the invocation causes a compilation error the effect is the same as if + * a non-reflective compilation error had been encountered. + * + * If the invocation throws an exception *e* (that it does not catch), this + * method throws *e*. + */ + /* + * TODO(turnidge): Handle ambiguous names. + * TODO(turnidge): Handle optional & named arguments. + */ + InstanceMirror invoke(Symbol memberName, List positionalArguments, + [Map namedArguments]); + + /** + * Invokes a getter and returns a mirror on the result. + * + * The getter can be the implicit getter for a field or a user-defined getter + * method. + * + * Let *o* be the object reflected by this mirror, + * let *f* be the simple name of the getter denoted by [fieldName]. + * + * Then this method will perform the getter invocation *o.f* in a scope that + * has access to the private members of *o* (if *o* is a class or library) or + * the private members of the class of *o* (otherwise). + * + * If this mirror is an [InstanceMirror], and [fieldName] denotes an instance + * method on its reflectee, the result of the invocation is an instance + * mirror on a closure corresponding to that method. + * + * If this mirror is a [LibraryMirror], and [fieldName] denotes a top-level + * method in the corresponding library, the result of the invocation is an + * instance mirror on a closure corresponding to that method. + * + * If this mirror is a [ClassMirror], and [fieldName] denotes a static method + * in the corresponding class, the result of the invocation is an instance + * mirror on a closure corresponding to that method. + * + * If the invocation returns a result *r*, this method returns the result of + * calling [reflect]\(*r*\). + * + * If the invocation causes a compilation error, the effect is the same as if + * a non-reflective compilation error had been encountered. + * + * If the invocation throws an exception *e* (that it does not catch), this + * method throws *e*. + */ + // TODO(ahe): Remove stuff about scope and private members. [fieldName] is a + // capability giving access to private members. + InstanceMirror getField(Symbol fieldName); + + /** + * Invokes a setter and returns a mirror on the result. + * + * The setter may be either the implicit setter for a non-final field or a + * user-defined setter method. + * + * Let *o* be the object reflected by this mirror, + * let *f* be the simple name of the getter denoted by [fieldName], + * and let *a* be the object bound to [value]. + * + * Then this method will perform the setter invocation *o.f = a* in a scope + * that has access to the private members of *o* (if *o* is a class or + * library) or the private members of the class of *o* (otherwise). + * + * If the invocation returns a result *r*, this method returns the result of + * calling [reflect]\([value]\). + * + * If the invocation causes a compilation error, the effect is the same as if + * a non-reflective compilation error had been encountered. + * + * If the invocation throws an exception *e* (that it does not catch) this + * method throws *e*. + */ + /* TODO(turnidge): Handle ambiguous names.*/ + InstanceMirror setField(Symbol fieldName, Object value); + + /** + * Performs [invocation] on the reflectee of this [ObjectMirror]. + * + * Equivalent to + * + * if (invocation.isGetter) { + * return this.getField(invocation.memberName).reflectee; + * } else if (invocation.isSetter) { + * return this.setField(invocation.memberName, + * invocation.positionalArguments[0]).reflectee; + * } else { + * return this.invoke(invocation.memberName, + * invocation.positionalArguments, + * invocation.namedArguments).reflectee; + * } + */ + delegate(Invocation invocation); +} + +/** + * An [InstanceMirror] reflects an instance of a Dart language object. + */ +abstract class InstanceMirror implements ObjectMirror { + /** + * A mirror on the type of the reflectee. + * + * Returns a mirror on the actual class of the reflectee. + * The class of the reflectee may differ from + * the object returned by invoking [runtimeType] on + * the reflectee. + */ + ClassMirror get type; + + /** + * Whether [reflectee] will return the instance reflected by this mirror. + * + * This will always be true in the local case (reflecting instances in the + * same isolate), but only true in the remote case if this mirror reflects a + * simple value. + * + * A value is simple if one of the following holds: + * + * * the value is [:null:] + * * the value is of type [num] + * * the value is of type [bool] + * * the value is of type [String] + */ + bool get hasReflectee; + + /** + * If the [InstanceMirror] reflects an instance it is meaningful to + * have a local reference to, we provide access to the actual + * instance here. + * + * If you access [reflectee] when [hasReflectee] is false, an + * exception is thrown. + */ + get reflectee; + + /** + * Whether this mirror is equal to [other]. + * + * The equality holds if and only if + * + * 1. [other] is a mirror of the same kind, and + * 2. either + * + * a. [hasReflectee] is true and so is + * [:identical(reflectee, other.reflectee):], or + * + * b. the remote objects reflected by this mirror and by [other] are + * identical. + */ + bool operator ==(other); +} + +/** + * A [ClosureMirror] reflects a closure. + * + * A [ClosureMirror] provides the ability to execute its reflectee and + * introspect its function. + */ +abstract class ClosureMirror implements InstanceMirror { + /** + * A mirror on the function associated with this closure. + * + * The function associated with an implicit closure of a function is that + * function. + * + * The function associated with an instance of a class that has a [:call:] + * method is that [:call:] method. + * + * A Dart implementation might choose to create a class for each closure + * expression, in which case [:function:] would be the same as + * [:type.declarations[#call]:]. But the Dart language model does not require + * this. A more typical implementation involves a single closure class for + * each type signature, where the call method dispatches to a function held + * in the closure rather the call method + * directly implementing the closure body. So one cannot rely on closures from + * distinct closure expressions having distinct classes ([:type:]), but one + * can rely on them having distinct functions ([:function:]). + */ + MethodMirror get function; + + /** + * Executes the closure and returns a mirror on the result. + * + * Let *f* be the closure reflected by this mirror, + * let *a1, ..., an* be the elements of [positionalArguments], + * let *k1, ..., km* be the identifiers denoted by the elements of + * [namedArguments.keys], + * and let *v1, ..., vm* be the elements of [namedArguments.values]. + * + * Then this method will perform the method invocation + * *f(a1, ..., an, k1: v1, ..., km: vm)*. + * + * If the invocation returns a result *r*, this method returns the result of + * calling [reflect]\(*r*\). + * + * If the invocation causes a compilation error, the effect is the same as if + * a non-reflective compilation error had been encountered. + * + * If the invocation throws an exception *e* (that it does not catch), this + * method throws *e*. + */ + InstanceMirror apply(List positionalArguments, + [Map namedArguments]); +} + +/** + * A [LibraryMirror] reflects a Dart language library, providing + * access to the variables, functions, and classes of the + * library. + */ +abstract class LibraryMirror implements DeclarationMirror, ObjectMirror { + /** + * The absolute uri of the library. + */ + Uri get uri; + + /** + * Returns an immutable map of the declarations actually given in the library. + * + * This map includes all regular methods, getters, setters, fields, classes + * and typedefs actually declared in the library. The map is keyed by the + * simple names of the declarations. + */ + Map get declarations; + + /** + * Whether this mirror is equal to [other]. + * + * The equality holds if and only if + * + * 1. [other] is a mirror of the same kind, and + * 2. The library being reflected by this mirror and the library being + * reflected by [other] are the same library in the same isolate. + */ + bool operator ==(other); + + /** + * Returns a list of the imports and exports in this library; + */ + List get libraryDependencies; +} + +/// A mirror on an import or export declaration. +abstract class LibraryDependencyMirror implements Mirror { + /// Is `true` if this dependency is an import. + bool get isImport; + + /// Is `true` if this dependency is an export. + bool get isExport; + + /// Returns true iff this dependency is a deferred import. Otherwise returns + /// false. + bool get isDeferred; + + /// Returns the library mirror of the library that imports or exports the + /// [targetLibrary]. + LibraryMirror get sourceLibrary; + + /// Returns the library mirror of the library that is imported or exported, + /// or null if the library is not loaded. + LibraryMirror get targetLibrary; + + /// Returns the prefix if this is a prefixed import and `null` otherwise. + Symbol get prefix; + + /// Returns the list of show/hide combinators on the import/export + /// declaration. + List get combinators; + + /// Returns the source location for this import/export declaration. + SourceLocation get location; + + List get metadata; + + /// Returns a future that completes with a library mirror on the library being + /// imported or exported when it is loaded, and initiates a load of that + /// library if it is not loaded. + Future loadLibrary(); +} + +/// A mirror on a show/hide combinator declared on a library dependency. +abstract class CombinatorMirror implements Mirror { + /// The list of identifiers on the combinator. + List get identifiers; + + /// Is `true` if this is a 'show' combinator. + bool get isShow; + + /// Is `true` if this is a 'hide' combinator. + bool get isHide; +} + +/** + * A [TypeMirror] reflects a Dart language class, typedef, + * function type or type variable. + */ +abstract class TypeMirror implements DeclarationMirror { + /** + * Returns true if this mirror reflects dynamic, a non-generic class or + * typedef, or an instantiated generic class or typedef in the current + * isolate. Otherwise, returns false. + */ + bool get hasReflectedType; + + /** + * If [:hasReflectedType:] returns true, returns the corresponding [Type]. + * Otherwise, an [UnsupportedError] is thrown. + */ + Type get reflectedType; + + /** + * An immutable list with mirrors for all type variables for this type. + * + * If this type is a generic declaration or an invocation of a generic + * declaration, the returned list contains mirrors on the type variables + * declared in the original declaration. + * Otherwise, the returned list is empty. + * + * This list preserves the order of declaration of the type variables. + */ + List get typeVariables; + + /** + * An immutable list with mirrors for all type arguments for + * this type. + * + * If the reflectee is an invocation of a generic class, + * the type arguments are the bindings of its type parameters. + * If the reflectee is the original declaration of a generic, + * it has no type arguments and this method returns an empty list. + * If the reflectee is not generic, then + * it has no type arguments and this method returns an empty list. + * + * This list preserves the order of declaration of the type variables. + */ + List get typeArguments; + + /** + * Is this the original declaration of this type? + * + * For most classes, they are their own original declaration. For + * generic classes, however, there is a distinction between the + * original class declaration, which has unbound type variables, and + * the instantiations of generic classes, which have bound type + * variables. + */ + bool get isOriginalDeclaration; + + /** + * A mirror on the original declaration of this type. + * + * For most classes, they are their own original declaration. For + * generic classes, however, there is a distinction between the + * original class declaration, which has unbound type variables, and + * the instantiations of generic classes, which have bound type + * variables. + */ + TypeMirror get originalDeclaration; + + /** + * Checks the subtype relationship, denoted by `<:` in the language + * specification. + * + * This is the type relationship used in `is` test checks. + */ + bool isSubtypeOf(TypeMirror other); + + /** + * Checks the assignability relationship, denoted by `<=>` in the language + * specification. + * + * This is the type relationship tested on assignment in checked mode. + */ + bool isAssignableTo(TypeMirror other); +} + +/** + * A [ClassMirror] reflects a Dart language class. + */ +abstract class ClassMirror implements TypeMirror, ObjectMirror { + /** + * A mirror on the superclass on the reflectee. + * + * If this type is [:Object:], the superclass will be null. + */ + ClassMirror get superclass; + + /** + * A list of mirrors on the superinterfaces of the reflectee. + */ + List get superinterfaces; + + /** + * Is the reflectee abstract? + */ + bool get isAbstract; + + /** + * Is the reflectee an enum? + */ + bool get isEnum; + + /** + * Returns an immutable map of the declarations actually given in the class + * declaration. + * + * This map includes all regular methods, getters, setters, fields, + * constructors and type variables actually declared in the class. Both + * static and instance members are included, but no inherited members are + * included. The map is keyed by the simple names of the declarations. + * + * This does not include inherited members. + */ + Map get declarations; + + /** + * Returns a map of the methods, getters and setters of an instance of the + * class. + * + * The intent is to capture those members that constitute the API of an + * instance. Hence fields are not included, but the getters and setters + * implicitly introduced by fields are included. The map includes methods, + * getters and setters that are inherited as well as those introduced by the + * class itself. + * + * The map is keyed by the simple names of the members. + */ + Map get instanceMembers; + + /** + * Returns a map of the static methods, getters and setters of the class. + * + * The intent is to capture those members that constitute the API of a class. + * Hence fields are not included, but the getters and setters implicitly + * introduced by fields are included. + * + * The map is keyed by the simple names of the members. + */ + Map get staticMembers; + + /** + * The mixin of this class. + * + * If this class is the result of a mixin application of the form S with M, + * returns a class mirror on M. Otherwise returns a class mirror on + * the reflectee. + */ + ClassMirror get mixin; + + // TODO(ahe): What about: + // /// Finds the instance member named [name] declared or inherited in the + // /// reflected class. + // DeclarationMirror instanceLookup(Symbol name); + + /** + * Invokes the named constructor and returns a mirror on the result. + * + * Let *c* be the class reflected by this mirror, + * let *a1, ..., an* be the elements of [positionalArguments], + * let *k1, ..., km* be the identifiers denoted by the elements of + * [namedArguments.keys], + * and let *v1, ..., vm* be the elements of [namedArguments.values]. + * + * If [constructorName] was created from the empty string, then this method + * will execute the instance creation expression + * *new c(a1, ..., an, k1: v1, ..., km: vm)* in a scope that has access to + * the private members of *c*. + * + * Otherwise, let *f* be the simple name of the constructor denoted by + * [constructorName]. Then this method will execute the instance creation + * expression *new c.f(a1, ..., an, k1: v1, ..., km: vm)* in a scope that has + * access to the private members of *c*. + * + * In either case: + * + * * If the expression evaluates to a result *r*, this method returns the + * result of calling [reflect]\(*r*\). + * * If evaluating the expression causes a compilation error, the effect is + * the same as if a non-reflective compilation error had been encountered. + * * If evaluating the expression throws an exception *e* (that it does not + * catch), this method throws *e*. + */ + InstanceMirror newInstance(Symbol constructorName, List positionalArguments, + [Map namedArguments]); + + /** + * Whether this mirror is equal to [other]. + * + * The equality holds if and only if + * + * 1. [other] is a mirror of the same kind, and + * 2. This mirror and [other] reflect the same class. + * + * Note that if the reflected class is an invocation of a generic class, 2. + * implies that the reflected class and [other] have equal type arguments. + */ + bool operator ==(other); + + /** + * Returns whether the class denoted by the receiver is a subclass of the + * class denoted by the argument. + * + * Note that the subclass relationship is reflexive. + */ + bool isSubclassOf(ClassMirror other); +} + +/** + * A [FunctionTypeMirror] represents the type of a function in the + * Dart language. + */ +abstract class FunctionTypeMirror implements ClassMirror { + /** + * Returns the return type of the reflectee. + */ + TypeMirror get returnType; + + /** + * Returns a list of the parameter types of the reflectee. + */ + List get parameters; + + /** + * A mirror on the [:call:] method for the reflectee. + */ + // This is only here because in the past the VM did not implement a call + // method on closures. + MethodMirror get callMethod; +} + +/** + * A [TypeVariableMirror] represents a type parameter of a generic type. + */ +abstract class TypeVariableMirror extends TypeMirror { + /** + * A mirror on the type that is the upper bound of this type variable. + */ + TypeMirror get upperBound; + + /** + * Is the reflectee static? + * + * For the purposes of the mirrors library, type variables are considered + * non-static. + */ + bool get isStatic; + + /** + * Whether [other] is a [TypeVariableMirror] on the same type variable as this + * mirror. + * + * The equality holds if and only if + * + * 1. [other] is a mirror of the same kind, and + * 2. [:simpleName == other.simpleName:] and [:owner == other.owner:]. + */ + bool operator ==(other); +} + +/** + * A [TypedefMirror] represents a typedef in a Dart language program. + */ +abstract class TypedefMirror implements TypeMirror { + /** + * The defining type for this typedef. + * + * If the type referred to by the reflectee is a function type *F*, the + * result will be [:FunctionTypeMirror:] reflecting *F* which is abstract + * and has an abstract method [:call:] whose signature corresponds to *F*. + * For instance [:void f(int):] is the referent for [:typedef void f(int):]. + */ + FunctionTypeMirror get referent; +} + +/** + * A [MethodMirror] reflects a Dart language function, method, + * constructor, getter, or setter. + */ +abstract class MethodMirror implements DeclarationMirror { + /** + * A mirror on the return type for the reflectee. + */ + TypeMirror get returnType; + + /** + * The source code for the reflectee, if available. Otherwise null. + */ + String get source; + + /** + * A list of mirrors on the parameters for the reflectee. + */ + List get parameters; + + /** + * A function is considered non-static iff it is permited to refer to 'this'. + * + * Note that generative constructors are considered non-static, whereas + * factory constructors are considered static. + */ + bool get isStatic; + + /** + * Is the reflectee abstract? + */ + bool get isAbstract; + + /** + * Returns true if the reflectee is synthetic, and returns false otherwise. + * + * A reflectee is synthetic if it is a getter or setter implicitly introduced + * for a field or Type, or if it is a constructor that was implicitly + * introduced as a default constructor or as part of a mixin application. + */ + bool get isSynthetic; + + /** + * Is the reflectee a regular function or method? + * + * A function or method is regular if it is not a getter, setter, or + * constructor. Note that operators, by this definition, are + * regular methods. + */ + bool get isRegularMethod; + + /** + * Is the reflectee an operator? + */ + bool get isOperator; + + /** + * Is the reflectee a getter? + */ + bool get isGetter; + + /** + * Is the reflectee a setter? + */ + bool get isSetter; + + /** + * Is the reflectee a constructor? + */ + bool get isConstructor; + + /** + * The constructor name for named constructors and factory methods. + * + * For unnamed constructors, this is the empty string. For + * non-constructors, this is the empty string. + * + * For example, [:'bar':] is the constructor name for constructor + * [:Foo.bar:] of type [:Foo:]. + */ + Symbol get constructorName; + + /** + * Is the reflectee a const constructor? + */ + bool get isConstConstructor; + + /** + * Is the reflectee a generative constructor? + */ + bool get isGenerativeConstructor; + + /** + * Is the reflectee a redirecting constructor? + */ + bool get isRedirectingConstructor; + + /** + * Is the reflectee a factory constructor? + */ + bool get isFactoryConstructor; + + /** + * Whether this mirror is equal to [other]. + * + * The equality holds if and only if + * + * 1. [other] is a mirror of the same kind, and + * 2. [:simpleName == other.simpleName:] and [:owner == other.owner:]. + */ + bool operator ==(other); +} + +/** + * A [VariableMirror] reflects a Dart language variable declaration. + */ +abstract class VariableMirror implements DeclarationMirror { + /** + * Returns a mirror on the type of the reflectee. + */ + TypeMirror get type; + + /** + * Returns [:true:] if the reflectee is a static variable. + * Otherwise returns [:false:]. + * + * For the purposes of the mirror library, top-level variables are + * implicitly declared static. + */ + bool get isStatic; + + /** + * Returns [:true:] if the reflectee is a final variable. + * Otherwise returns [:false:]. + */ + bool get isFinal; + + /** + * Returns [:true:] if the reflectee is declared [:const:]. + * Otherwise returns [:false:]. + */ + bool get isConst; + + /** + * Whether this mirror is equal to [other]. + * + * The equality holds if and only if + * + * 1. [other] is a mirror of the same kind, and + * 2. [:simpleName == other.simpleName:] and [:owner == other.owner:]. + */ + bool operator ==(other); +} + +/** + * A [ParameterMirror] reflects a Dart formal parameter declaration. + */ +abstract class ParameterMirror implements VariableMirror { + /** + * A mirror on the type of this parameter. + */ + TypeMirror get type; + + /** + * Returns [:true:] if the reflectee is an optional parameter. + * Otherwise returns [:false:]. + */ + bool get isOptional; + + /** + * Returns [:true:] if the reflectee is a named parameter. + * Otherwise returns [:false:]. + */ + bool get isNamed; + + /** + * Returns [:true:] if the reflectee has explicitly declared a default value. + * Otherwise returns [:false:]. + */ + bool get hasDefaultValue; + + /** + * Returns the default value of an optional parameter. + * + * Returns an [InstanceMirror] on the (compile-time constant) + * default value for an optional parameter. + * If no default value is declared, it defaults to `null` + * and a mirror of `null` is returned. + * + * Returns `null` for a required parameter. + */ + InstanceMirror get defaultValue; +} + +/** + * A [SourceLocation] describes the span of an entity in Dart source code. + */ +abstract class SourceLocation { + /** + * The 1-based line number for this source location. + * + * A value of 0 means that the line number is unknown. + */ + int get line; + + /** + * The 1-based column number for this source location. + * + * A value of 0 means that the column number is unknown. + */ + int get column; + + /** + * Returns the URI where the source originated. + */ + Uri get sourceUri; +} + +/** + * Class used for encoding comments as metadata annotations. + */ +class Comment { + /** + * The comment text as written in the source text. + */ + final String text; + + /** + * The comment text without the start, end, and padding text. + * + * For example, if [text] is [: /** Comment text. */ :] then the [trimmedText] + * is [: Comment text. :]. + */ + final String trimmedText; + + /** + * Is [:true:] if this comment is a documentation comment. + * + * That is, that the comment is either enclosed in [: /** ... */ :] or starts + * with [: /// :]. + */ + final bool isDocComment; + + const Comment(this.text, this.trimmedText, this.isDocComment); +} + +/** + * Annotation describing how "dart:mirrors" is used (EXPERIMENTAL). + * + * When used as metadata on an import of "dart:mirrors" in library *L*, this + * class describes how "dart:mirrors" is used by library *L* unless overridden. + * See [override]. + * + * The following text is non-normative: + * + * In some scenarios, for example, when minifying Dart code, or when generating + * JavaScript code from a Dart program, the size and performance of the output + * can suffer from use of reflection. In those cases, telling the compiler + * what is used, can have a significant impact. + * + * Example usage: + * + * @MirrorsUsed(symbols: 'foo') + * import 'dart:mirrors'; + * + * class Foo { + * noSuchMethod(Invocation invocation) { + * print(MirrorSystem.getName(invocation.memberName)); + * } + * } + * + * main() { + * new Foo().foo(); // Prints "foo". + * new Foo().bar(); // Might print an arbitrary (mangled) name, "bar". + * } + * + * For a detailed description of the parameters to the [MirrorsUsed] constructor + * see the comments for [symbols], [targets], [metaTargets] and [override]. + * + * An import of `dart:mirrors` may have multiple [MirrorsUsed] annotations. This + * is particularly helpful to specify overrides for specific libraries. For + * example: + * + * @MirrorsUsed(targets: 'foo.Bar', override: 'foo') + * @MirrorsUsed(targets: 'Bar') + * import 'dart:mirrors'; + * + * will ensure that the target `Bar` from the current library and from library + * `foo` is available for reflection. See also [override]. + */ +@Deprecated("No longer has any effect. Will be removed in a later release.") +class MirrorsUsed { + // Note: the fields of this class are untyped. This is because the most + // convenient way to specify symbols today is using a single string. In + // some cases, a const list of classes might be convenient. Some + // might prefer to use a const list of symbols. + + /** + * The list of strings passed to new [Symbol], and symbols that might be + * passed to [MirrorSystem.getName]. + * + * Combined with the names of [targets], [metaTargets] and their members, + * this forms the complete list of strings passed to new [Symbol], and + * symbols that might be passed to [MirrorSystem.getName] by the library to + * which this metadata applies. + * + * The following text is non-normative: + * + * Dart2js currently supports the following formats to specify symbols: + * + * * A constant [List] of [String] constants representing symbol names, + * e.g., `const ['foo', 'bar']`. + * * A single [String] constant whose value is a comma-separated list of + * symbol names, e.g., `"foo, bar"`. + * + * Specifying the `symbols` field turns off the following warnings emitted by + * dart2js: + * + * * Using "MirrorSystem.getName" may result in larger output. + * * Using "new Symbol" may result in larger output. + * + * For example, if you're using [noSuchMethod] to interact with a database, + * extract all the possible column names and include them in this list. + * Similarly, if you're using [noSuchMethod] to interact with another + * language (JavaScript, for example) extract all the identifiers from the + * API you use and include them in this list. + * + * Note that specifying a symbol only ensures that the symbol will be + * available under that name at runtime. It does not mark targets with + * that name as available for reflection. See [targets] and [metaTargets] + * for that purpose. + */ + final symbols; + + /** + * A list of reflective targets. + * + * Combined with [metaTargets], this provides the complete list of reflective + * targets used by the library to which this metadata applies. + * + * The following text is non-normative: + * + * For now, there is no formal description of what a reflective target is. + * Informally, a target is a library, a class, a method or a field. + * + * Dart2js currently supports the following formats to specify targets: + * + * * A constant [List] containing [String] constants representing (qualified) + * names of targets and Dart types. + * * A single [String] constant whose value is a comma-separated list of + * (qualified) names. + * * A single Dart type. + * + * A (qualified) name is resolved to a target as follows: + * + * 1. If the qualified name matches a library name, the matching library is + * the target. + * 2. Else, find the longest prefix of the name such that the prefix ends + * just before a `.` and is a library name. + * 3. Use that library as current scope. If no matching prefix was found, use + * the current library, i.e., the library where the [MirrorsUsed] + * annotation was placed. + * 4. Split the remaining suffix (the entire name if no library name was + * found in step 3) into a list of [String] using `.` as a + * separator. + * 5. Select all targets in the current scope whose name matches a [String] + * from the list. + * + * For example: + * + * library my.library.one; + * + * class A { + * var aField; + * } + * + * library main; + * + * @MirrorsUsed(targets: "my.library.one.A.aField") + * import "dart:mirrors"; + * + * The [MirrorsUsed] annotation specifies `A` and `aField` from library + * `my.library.one` as targets. This will mark the class `A` as a reflective + * target. The target specification for `aField` has no effect, as there is + * no target in `my.library.one` with that name. + * + * Note that everything within a target also is available for reflection. + * So, if a library is specified as target, all classes in that library + * become targets for reflection. Likewise, if a class is a target, all + * its methods and fields become targets for reflection. As a consequence, + * `aField` in the above example is also a reflective target. + * + */ + final targets; + + /** + * A list of classes that when used as metadata indicates a reflective + * target. See also [targets]. + * + * The following text is non-normative: + * + * The format for specifying the list of classes is the same as used for + * specifying [targets]. However, as a library cannot be used as a metadata + * annotation in Dart, adding a library to the list of [metaTargets] has no + * effect. In particular, adding a library to [metaTargets] does not make + * the library's classes valid metadata annotations to enable reflection. + * + * If an instance of a class specified in [metaTargets] is used as + * metadata annotation on a library, class, field or method, that library, + * class, field or method is added to the set of targets for reflection. + * + * Example usage: + * + * library example; + * @MirrorsUsed(metaTargets: "example.Reflectable") + * import "dart:mirrors"; + * + * class Reflectable { + * const Reflectable(); + * } + * + * class Foo { + * @Reflectable() + * reflectableMethod() { ... } + * + * nonReflectableMethod() { ... } + * } + * + * In the above example. `reflectableMethod` is marked as reflectable by + * using the `Reflectable` class, which in turn is specified in the + * [metaTargets] annotation. + * + * The method `nonReflectableMethod` lacks a metadata annotation and thus + * will not be reflectable at runtime. + */ + final metaTargets; + + /** + * A list of library names or "*". + * + * When used as metadata on an import of "dart:mirrors", this metadata does + * not apply to the library in which the annotation is used, but instead + * applies to the other libraries (all libraries if "*" is used). + * + * The following text is non-normative: + * + * Dart2js currently supports the following formats to specify libraries: + * + * * A constant [List] containing [String] constants representing names of + * libraries. + * * A single [String] constant whose value is a comma-separated list of + * library names. + * + * Conceptually, a [MirrorsUsed] annotation with [override] has the same + * effect as placing the annotation directly on the import of `dart:mirrors` + * in each of the referenced libraries. Thus, if the library had no + * [MirrorsUsed] annotation before, its unconditional import of + * `dart:mirrors` is overridden by an annotated import. + * + * Note that, like multiple explicit [MirrorsUsed] annotations, using + * override on a library with an existing [MirrorsUsed] annotation is + * additive. That is, the overall set of reflective targets is the union + * of the reflective targets that arise from the original and the + * overriding [MirrorsUsed] annotations. + * + * The use of [override] is only meaningful for libraries that have an + * import of `dart:mirrors` without annotation because otherwise it would + * work exactly the same way without the [override] parameter. + * + * While the annotation will apply to the given target libraries, the + * [symbols], [targets] and [metaTargets] are still evaluated in the + * scope of the annotation. Thus, to select a target from library `foo`, + * a qualified name has to be used or, if the target is visible in the + * current scope, its type may be referenced. + * + * For example, the following code marks all targets in the library `foo` + * as reflectable that have a metadata annotation using the `Reflectable` + * class from the same library. + * + * @MirrorsUsed(metaTargets: "foo.Reflectable", override: "foo") + * + * However, the following code would require the use of the `Reflectable` + * class from the current library, instead. + * + * @MirrorsUsed(metaTargets: "Reflectable", override: "foo") + * + */ + final override; + + /** + * See the documentation for [MirrorsUsed.symbols], [MirrorsUsed.targets], + * [MirrorsUsed.metaTargets] and [MirrorsUsed.override] for documentation + * of the parameters. + */ + const MirrorsUsed( + {this.symbols, this.targets, this.metaTargets, this.override}); +} +NN<>FS OPH7!FBGF>EEEN LO)B6:B<'$#*FL1"PPC*F;J5-KO.JJ 3!P9GLPO -+GOOMPL G27+1GA1!O'2M;OJKKMJK*J54IO1=DA2C,H1I,)QL9I-O'JHNLK J'27G<,PJN7NO?PKOPLQMNOKNFNEE>68=<>45 6E%EC@AF =0DPNOILOP:OO>N-8E.:P 5FOP:PJ7NM@PM7OP>NO2-:M!5F1NIFO#P>M/;D$B+7N5>D #G8,<06LMO6"#%F@@.'2,6J)G9<LM%KAPMN+QN@>6AEG9,OP>N1.A: J&QNL'3.'2IG@91;11O L#N,#LE*F%QK#'I41 00;#9JI(M1JIK+,I.?;A@E+EI&4EBGB"8EBGB&F=&MI)3A2>@) NFJLI.3M JJMO:1LPK(:/NFM4G4AEGN3M!ILP+L+NON'O..'28NML$7(C;/=(8KI7ILQ '2IF5)JLMO#?#;4F<(PJ1 NPHL4G@#  %F>1D"+0$1%-!.'2IE=4="E!<">".'2IE;-A"="P"9@.<).#K 799;2=5@Q=PADMP(POL0$/? +M QLQL 9$O;MKJC2K'LIN"*JJ%K)PA7NJHM0HIL#PA*MFJP(K<NL1PGK@N! : JON3LJJM@I!*KNNLLEML:  '* KFL)%NKD*LMKKOFB:HHKD+ILAHGKI0LL"GL.CMLFnfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/js_primitives.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// dart2js "primitives", that is, features that cannot be implemented without +/// access to JavaScript features. +library dart2js._js_primitives; + +import 'dart:_foreign_helper' show JS; + +/** + * This is the low-level method that is used to implement [print]. It is + * possible to override this function from JavaScript by defining a function in + * JavaScript called "dartPrint". + * + * Notice that it is also possible to intercept calls to [print] from within a + * Dart program using zones. This means that there is no guarantee that a call + * to print ends in this method. + */ +void printString(String string) { + if (JS('bool', r'typeof dartPrint == "function"')) { + // Support overriding print from JavaScript. + JS('void', r'dartPrint(#)', string); + return; + } + + // Inside browser or nodejs. + if (JS('bool', r'typeof console == "object"') && + JS('bool', r'typeof console.log != "undefined"')) { + JS('void', r'console.log(#)', string); + return; + } + + // Don't throw inside IE, the console is only defined if dev tools is open. + if (JS('bool', r'typeof window == "object"')) { + return; + } + + // Running in d8, the V8 developer shell, or in Firefox' js-shell. + if (JS('bool', r'typeof print == "function"')) { + JS('void', r'print(#)', string); + return; + } + + // This is somewhat nasty, but we don't want to drag in a bunch of + // dependencies to handle a situation that cannot happen. So we + // avoid using Dart [:throw:] and Dart [toString]. + JS('void', 'throw "Unable to print message: " + String(#)', string); +} +3NN<O# 'JP"OO!"71) 3:+ N2 E3% EB5GZfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/html/html_common/metadata.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library metadata; + +/** + * An annotation used to mark a feature as only being supported by a subset + * of the browsers that Dart supports by default. + * + * If an API is not annotated with [SupportedBrowser] then it is assumed to + * work on all browsers Dart supports. + */ +class SupportedBrowser { + static const String CHROME = "Chrome"; + static const String FIREFOX = "Firefox"; + static const String IE = "Internet Explorer"; + static const String OPERA = "Opera"; + static const String SAFARI = "Safari"; + + /// The name of the browser. + final String browserName; + + /// The minimum version of the browser that supports the feature, or null + /// if supported on all versions. + final String minimumVersion; + + const SupportedBrowser(this.browserName, [this.minimumVersion]); +} + +/** + * An annotation used to mark an API as being experimental. + * + * An API is considered to be experimental if it is still going through the + * process of stabilizing and is subject to change or removal. + * + * See also: + * + * * [W3C recommendation](http://en.wikipedia.org/wiki/W3C_recommendation) + */ +class Experimental { + const Experimental(); +} + +/** + * Annotation that specifies that a member is editable through generate files. + * + * This is used for API generation. + * + * [name] should be formatted as `interface.member`. + */ +class DomName { + final String name; + const DomName(this.name); +} + +/** + * Metadata that specifies that that member is editable through generated + * files. + */ +class DocsEditable { + const DocsEditable(); +} + +/** + * Annotation that indicates that an API is not expected to change but has + * not undergone enough testing to be considered stable. + */ +class Unstable { + const Unstable(); +} +INN<L2L')+0')L$C<L? KO$5J +K9rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/private/native_typed_data.dart?// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Specialized integers and floating point numbers, + * with SIMD support and efficient lists. + */ +library dart.typed_data.implementation; + +import 'dart:collection'; +import 'dart:_internal'; +import 'dart:_interceptors' show JSIndexable; +import 'dart:_js_helper' + show + Creates, + JavaScriptIndexingBehavior, + JSName, + Native, + Null, + Returns, + diagnoseIndexError, + diagnoseRangeError; +import 'dart:_foreign_helper' show JS; +import 'dart:math' as Math; + +import 'dart:typed_data'; + +@Native("ArrayBuffer") +class NativeByteBuffer implements ByteBuffer { + @JSName('byteLength') + external int get lengthInBytes; + + Type get runtimeType => ByteBuffer; + + Uint8List asUint8List([int offsetInBytes = 0, int length]) { + return NativeUint8List.view(this, offsetInBytes, length); + } + + Int8List asInt8List([int offsetInBytes = 0, int length]) { + return NativeInt8List.view(this, offsetInBytes, length); + } + + Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) { + return NativeUint8ClampedList.view(this, offsetInBytes, length); + } + + Uint16List asUint16List([int offsetInBytes = 0, int length]) { + return NativeUint16List.view(this, offsetInBytes, length); + } + + Int16List asInt16List([int offsetInBytes = 0, int length]) { + return NativeInt16List.view(this, offsetInBytes, length); + } + + Uint32List asUint32List([int offsetInBytes = 0, int length]) { + return NativeUint32List.view(this, offsetInBytes, length); + } + + Int32List asInt32List([int offsetInBytes = 0, int length]) { + return NativeInt32List.view(this, offsetInBytes, length); + } + + Uint64List asUint64List([int offsetInBytes = 0, int length]) { + throw UnsupportedError("Uint64List not supported by dart2js."); + } + + Int64List asInt64List([int offsetInBytes = 0, int length]) { + throw UnsupportedError("Int64List not supported by dart2js."); + } + + Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) { + NativeInt32List storage = + this.asInt32List(offsetInBytes, length != null ? length * 4 : null); + return NativeInt32x4List._externalStorage(storage); + } + + Float32List asFloat32List([int offsetInBytes = 0, int length]) { + return NativeFloat32List.view(this, offsetInBytes, length); + } + + Float64List asFloat64List([int offsetInBytes = 0, int length]) { + return NativeFloat64List.view(this, offsetInBytes, length); + } + + Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) { + NativeFloat32List storage = + this.asFloat32List(offsetInBytes, length != null ? length * 4 : null); + return NativeFloat32x4List._externalStorage(storage); + } + + Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) { + NativeFloat64List storage = + this.asFloat64List(offsetInBytes, length != null ? length * 2 : null); + return NativeFloat64x2List._externalStorage(storage); + } + + ByteData asByteData([int offsetInBytes = 0, int length]) { + return NativeByteData.view(this, offsetInBytes, length); + } +} + +/** + * A fixed-length list of Float32x4 numbers that is viewable as a + * [TypedData]. For long lists, this implementation will be considerably more + * space- and time-efficient than the default [List] implementation. + */ +class NativeFloat32x4List extends Object + with ListMixin, FixedLengthListMixin + implements Float32x4List { + final NativeFloat32List _storage; + + /** + * Creates a [Float32x4List] of the specified length (in elements), + * all of whose elements are initially zero. + */ + NativeFloat32x4List(int length) : _storage = NativeFloat32List(length * 4); + + NativeFloat32x4List._externalStorage(this._storage); + + NativeFloat32x4List._slowFromList(List list) + : _storage = NativeFloat32List(list.length * 4) { + for (int i = 0; i < list.length; i++) { + var e = list[i]; + _storage[(i * 4) + 0] = e.x; + _storage[(i * 4) + 1] = e.y; + _storage[(i * 4) + 2] = e.z; + _storage[(i * 4) + 3] = e.w; + } + } + + Type get runtimeType => Float32x4List; + + /** + * Creates a [Float32x4List] with the same size as the [elements] list + * and copies over the elements. + */ + factory NativeFloat32x4List.fromList(List list) { + if (list is NativeFloat32x4List) { + return NativeFloat32x4List._externalStorage( + NativeFloat32List.fromList(list._storage)); + } else { + return NativeFloat32x4List._slowFromList(list); + } + } + + ByteBuffer get buffer => _storage.buffer; + + int get lengthInBytes => _storage.lengthInBytes; + + int get offsetInBytes => _storage.offsetInBytes; + + int get elementSizeInBytes => Float32x4List.bytesPerElement; + + int get length => _storage.length ~/ 4; + + Float32x4 operator [](int index) { + _checkValidIndex(index, this, this.length); + double _x = _storage[(index * 4) + 0]; + double _y = _storage[(index * 4) + 1]; + double _z = _storage[(index * 4) + 2]; + double _w = _storage[(index * 4) + 3]; + return NativeFloat32x4._truncated(_x, _y, _z, _w); + } + + void operator []=(int index, Float32x4 value) { + _checkValidIndex(index, this, this.length); + _storage[(index * 4) + 0] = value.x; + _storage[(index * 4) + 1] = value.y; + _storage[(index * 4) + 2] = value.z; + _storage[(index * 4) + 3] = value.w; + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + return NativeFloat32x4List._externalStorage( + _storage.sublist(start * 4, end * 4)); + } +} + +/** + * A fixed-length list of Int32x4 numbers that is viewable as a + * [TypedData]. For long lists, this implementation will be considerably more + * space- and time-efficient than the default [List] implementation. + */ +class NativeInt32x4List extends Object + with ListMixin, FixedLengthListMixin + implements Int32x4List { + final Int32List _storage; + + /** + * Creates a [Int32x4List] of the specified length (in elements), + * all of whose elements are initially zero. + */ + NativeInt32x4List(int length) : _storage = NativeInt32List(length * 4); + + NativeInt32x4List._externalStorage(Int32List storage) : _storage = storage; + + NativeInt32x4List._slowFromList(List list) + : _storage = NativeInt32List(list.length * 4) { + for (int i = 0; i < list.length; i++) { + var e = list[i]; + _storage[(i * 4) + 0] = e.x; + _storage[(i * 4) + 1] = e.y; + _storage[(i * 4) + 2] = e.z; + _storage[(i * 4) + 3] = e.w; + } + } + + Type get runtimeType => Int32x4List; + + /** + * Creates a [Int32x4List] with the same size as the [elements] list + * and copies over the elements. + */ + factory NativeInt32x4List.fromList(List list) { + if (list is NativeInt32x4List) { + return NativeInt32x4List._externalStorage( + NativeInt32List.fromList(list._storage)); + } else { + return NativeInt32x4List._slowFromList(list); + } + } + + ByteBuffer get buffer => _storage.buffer; + + int get lengthInBytes => _storage.lengthInBytes; + + int get offsetInBytes => _storage.offsetInBytes; + + int get elementSizeInBytes => Int32x4List.bytesPerElement; + + int get length => _storage.length ~/ 4; + + Int32x4 operator [](int index) { + _checkValidIndex(index, this, this.length); + int _x = _storage[(index * 4) + 0]; + int _y = _storage[(index * 4) + 1]; + int _z = _storage[(index * 4) + 2]; + int _w = _storage[(index * 4) + 3]; + return NativeInt32x4._truncated(_x, _y, _z, _w); + } + + void operator []=(int index, Int32x4 value) { + _checkValidIndex(index, this, this.length); + _storage[(index * 4) + 0] = value.x; + _storage[(index * 4) + 1] = value.y; + _storage[(index * 4) + 2] = value.z; + _storage[(index * 4) + 3] = value.w; + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + return NativeInt32x4List._externalStorage( + _storage.sublist(start * 4, end * 4)); + } +} + +/** + * A fixed-length list of Float64x2 numbers that is viewable as a + * [TypedData]. For long lists, this implementation will be considerably more + * space- and time-efficient than the default [List] implementation. + */ +class NativeFloat64x2List extends Object + with ListMixin, FixedLengthListMixin + implements Float64x2List { + final NativeFloat64List _storage; + + /** + * Creates a [Float64x2List] of the specified length (in elements), + * all of whose elements are initially zero. + */ + NativeFloat64x2List(int length) : _storage = NativeFloat64List(length * 2); + + NativeFloat64x2List._externalStorage(this._storage); + + NativeFloat64x2List._slowFromList(List list) + : _storage = NativeFloat64List(list.length * 2) { + for (int i = 0; i < list.length; i++) { + var e = list[i]; + _storage[(i * 2) + 0] = e.x; + _storage[(i * 2) + 1] = e.y; + } + } + + /** + * Creates a [Float64x2List] with the same size as the [elements] list + * and copies over the elements. + */ + factory NativeFloat64x2List.fromList(List list) { + if (list is NativeFloat64x2List) { + return NativeFloat64x2List._externalStorage( + NativeFloat64List.fromList(list._storage)); + } else { + return NativeFloat64x2List._slowFromList(list); + } + } + + Type get runtimeType => Float64x2List; + + ByteBuffer get buffer => _storage.buffer; + + int get lengthInBytes => _storage.lengthInBytes; + + int get offsetInBytes => _storage.offsetInBytes; + + int get elementSizeInBytes => Float64x2List.bytesPerElement; + + int get length => _storage.length ~/ 2; + + Float64x2 operator [](int index) { + _checkValidIndex(index, this, this.length); + double _x = _storage[(index * 2) + 0]; + double _y = _storage[(index * 2) + 1]; + return Float64x2(_x, _y); + } + + void operator []=(int index, Float64x2 value) { + _checkValidIndex(index, this, this.length); + _storage[(index * 2) + 0] = value.x; + _storage[(index * 2) + 1] = value.y; + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + return NativeFloat64x2List._externalStorage( + _storage.sublist(start * 2, end * 2)); + } +} + +@Native("ArrayBufferView") +class NativeTypedData implements TypedData { + /** + * Returns the byte buffer associated with this object. + */ + @Creates('NativeByteBuffer') + // May be Null for IE's CanvasPixelArray. + @Returns('NativeByteBuffer|Null') + external ByteBuffer get buffer; + + /** + * Returns the length of this view, in bytes. + */ + @JSName('byteLength') + external int get lengthInBytes; + + /** + * Returns the offset in bytes into the underlying byte buffer of this view. + */ + @JSName('byteOffset') + external int get offsetInBytes; + + /** + * Returns the number of bytes in the representation of each element in this + * list. + */ + @JSName('BYTES_PER_ELEMENT') + external int get elementSizeInBytes; + + void _invalidPosition(int position, int length, String name) { + if (position is! int) { + throw ArgumentError.value(position, name, 'Invalid list position'); + } else { + throw RangeError.range(position, 0, length, name); + } + } + + void _checkPosition(int position, int length, String name) { + if (JS('bool', '(# >>> 0) !== #', position, position) || + JS('int', '#', position) > length) { + // 'int' guaranteed by above test. + _invalidPosition(position, length, name); + } + } +} + +// Validates the unnamed constructor length argument. Checking is necessary +// because passing unvalidated values to the native constructors can cause +// conversions or create views. +int _checkLength(length) { + if (length is! int) throw ArgumentError('Invalid length $length'); + return length; +} + +// Validates `.view` constructor arguments. Checking is necessary because +// passing unvalidated values to the native constructors can cause conversions +// (e.g. String arguments) or create typed data objects that are not actually +// views of the input. +void _checkViewArguments(buffer, offsetInBytes, length) { + if (buffer is! NativeByteBuffer) { + throw ArgumentError('Invalid view buffer'); + } + if (offsetInBytes is! int) { + throw ArgumentError('Invalid view offsetInBytes $offsetInBytes'); + } + if (length != null && length is! int) { + throw ArgumentError('Invalid view length $length'); + } +} + +// Ensures that [list] is a JavaScript Array or a typed array. If necessary, +// returns a copy of the list. +List _ensureNativeList(List list) { + if (list is JSIndexable) return list; + List result = List(list.length); + for (int i = 0; i < list.length; i++) { + result[i] = list[i]; + } + return result; +} + +@Native("DataView") +class NativeByteData extends NativeTypedData implements ByteData { + /** + * Creates a [ByteData] of the specified length (in elements), all of + * whose elements are initially zero. + */ + factory NativeByteData(int length) => _create1(_checkLength(length)); + + /** + * Creates an [ByteData] _view_ of the specified region in the specified + * byte buffer. Changes in the [ByteData] will be visible in the byte + * buffer and vice versa. If the [offsetInBytes] index of the region is not + * specified, it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to null, which indicates + * that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + */ + factory NativeByteData.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => ByteData; + + int get elementSizeInBytes => 1; + + /** + * Returns the floating point number represented by the four bytes at + * the specified [byteOffset] in this object, in IEEE 754 + * single-precision binary floating-point format (binary32). + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + double getFloat32(int byteOffset, [Endian endian = Endian.big]) => + _getFloat32(byteOffset, Endian.little == endian); + + @JSName('getFloat32') + @Returns('double') + double _getFloat32(int byteOffset, [bool littleEndian]) native; + + /** + * Returns the floating point number represented by the eight bytes at + * the specified [byteOffset] in this object, in IEEE 754 + * double-precision binary floating-point format (binary64). + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + double getFloat64(int byteOffset, [Endian endian = Endian.big]) => + _getFloat64(byteOffset, Endian.little == endian); + + @JSName('getFloat64') + @Returns('double') + double _getFloat64(int byteOffset, [bool littleEndian]) native; + + /** + * Returns the (possibly negative) integer represented by the two bytes at + * the specified [byteOffset] in this object, in two's complement binary + * form. + * The return value will be between 215 and 215 - 1, + * inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + int getInt16(int byteOffset, [Endian endian = Endian.big]) => + _getInt16(byteOffset, Endian.little == endian); + + @JSName('getInt16') + @Returns('int') + int _getInt16(int byteOffset, [bool littleEndian]) native; + + /** + * Returns the (possibly negative) integer represented by the four bytes at + * the specified [byteOffset] in this object, in two's complement binary + * form. + * The return value will be between 231 and 231 - 1, + * inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + int getInt32(int byteOffset, [Endian endian = Endian.big]) => + _getInt32(byteOffset, Endian.little == endian); + + @JSName('getInt32') + @Returns('int') + int _getInt32(int byteOffset, [bool littleEndian]) native; + + /** + * Returns the (possibly negative) integer represented by the eight bytes at + * the specified [byteOffset] in this object, in two's complement binary + * form. + * The return value will be between 263 and 263 - 1, + * inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + int getInt64(int byteOffset, [Endian endian = Endian.big]) { + throw UnsupportedError('Int64 accessor not supported by dart2js.'); + } + + /** + * Returns the (possibly negative) integer represented by the byte at the + * specified [byteOffset] in this object, in two's complement binary + * representation. The return value will be between -128 and 127, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * greater than or equal to the length of this object. + */ + int getInt8(int byteOffset) native; + + /** + * Returns the positive integer represented by the two bytes starting + * at the specified [byteOffset] in this object, in unsigned binary + * form. + * The return value will be between 0 and 216 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + int getUint16(int byteOffset, [Endian endian = Endian.big]) => + _getUint16(byteOffset, Endian.little == endian); + + @JSName('getUint16') + @Returns('int') + int _getUint16(int byteOffset, [bool littleEndian]) native; + + /** + * Returns the positive integer represented by the four bytes starting + * at the specified [byteOffset] in this object, in unsigned binary + * form. + * The return value will be between 0 and 232 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + int getUint32(int byteOffset, [Endian endian = Endian.big]) => + _getUint32(byteOffset, Endian.little == endian); + + @JSName('getUint32') + @Returns('int') + int _getUint32(int byteOffset, [bool littleEndian]) native; + + /** + * Returns the positive integer represented by the eight bytes starting + * at the specified [byteOffset] in this object, in unsigned binary + * form. + * The return value will be between 0 and 264 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + int getUint64(int byteOffset, [Endian endian = Endian.big]) { + throw UnsupportedError('Uint64 accessor not supported by dart2js.'); + } + + /** + * Returns the positive integer represented by the byte at the specified + * [byteOffset] in this object, in unsigned binary form. The + * return value will be between 0 and 255, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * greater than or equal to the length of this object. + */ + int getUint8(int byteOffset) native; + + /** + * Sets the four bytes starting at the specified [byteOffset] in this + * object to the IEEE 754 single-precision binary floating-point + * (binary32) representation of the specified [value]. + * + * **Note that this method can lose precision.** The input [value] is + * a 64-bit floating point value, which will be converted to 32-bit + * floating point value by IEEE 754 rounding rules before it is stored. + * If [value] cannot be represented exactly as a binary32, it will be + * converted to the nearest binary32 value. If two binary32 values are + * equally close, the one whose least significant bit is zero will be used. + * Note that finite (but large) values can be converted to infinity, and + * small non-zero values can be converted to zero. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + void setFloat32(int byteOffset, num value, [Endian endian = Endian.big]) => + _setFloat32(byteOffset, value, Endian.little == endian); + + @JSName('setFloat32') + void _setFloat32(int byteOffset, num value, [bool littleEndian]) native; + + /** + * Sets the eight bytes starting at the specified [byteOffset] in this + * object to the IEEE 754 double-precision binary floating-point + * (binary64) representation of the specified [value]. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + void setFloat64(int byteOffset, num value, [Endian endian = Endian.big]) => + _setFloat64(byteOffset, value, Endian.little == endian); + + @JSName('setFloat64') + void _setFloat64(int byteOffset, num value, [bool littleEndian]) native; + + /** + * Sets the two bytes starting at the specified [byteOffset] in this + * object to the two's complement binary representation of the specified + * [value], which must fit in two bytes. In other words, [value] must lie + * between 215 and 215 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + void setInt16(int byteOffset, int value, [Endian endian = Endian.big]) => + _setInt16(byteOffset, value, Endian.little == endian); + + @JSName('setInt16') + void _setInt16(int byteOffset, int value, [bool littleEndian]) native; + + /** + * Sets the four bytes starting at the specified [byteOffset] in this + * object to the two's complement binary representation of the specified + * [value], which must fit in four bytes. In other words, [value] must lie + * between 231 and 231 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + void setInt32(int byteOffset, int value, [Endian endian = Endian.big]) => + _setInt32(byteOffset, value, Endian.little == endian); + + @JSName('setInt32') + void _setInt32(int byteOffset, int value, [bool littleEndian]) native; + + /** + * Sets the eight bytes starting at the specified [byteOffset] in this + * object to the two's complement binary representation of the specified + * [value], which must fit in eight bytes. In other words, [value] must lie + * between 263 and 263 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + void setInt64(int byteOffset, int value, [Endian endian = Endian.big]) { + throw UnsupportedError('Int64 accessor not supported by dart2js.'); + } + + /** + * Sets the byte at the specified [byteOffset] in this object to the + * two's complement binary representation of the specified [value], which + * must fit in a single byte. In other words, [value] must be between + * -128 and 127, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * greater than or equal to the length of this object. + */ + void setInt8(int byteOffset, int value) native; + + /** + * Sets the two bytes starting at the specified [byteOffset] in this object + * to the unsigned binary representation of the specified [value], + * which must fit in two bytes. in other words, [value] must be between + * 0 and 216 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + void setUint16(int byteOffset, int value, [Endian endian = Endian.big]) => + _setUint16(byteOffset, value, Endian.little == endian); + + @JSName('setUint16') + void _setUint16(int byteOffset, int value, [bool littleEndian]) native; + + /** + * Sets the four bytes starting at the specified [byteOffset] in this object + * to the unsigned binary representation of the specified [value], + * which must fit in four bytes. in other words, [value] must be between + * 0 and 232 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + void setUint32(int byteOffset, int value, [Endian endian = Endian.big]) => + _setUint32(byteOffset, value, Endian.little == endian); + + @JSName('setUint32') + void _setUint32(int byteOffset, int value, [bool littleEndian]) native; + + /** + * Sets the eight bytes starting at the specified [byteOffset] in this object + * to the unsigned binary representation of the specified [value], + * which must fit in eight bytes. in other words, [value] must be between + * 0 and 264 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + void setUint64(int byteOffset, int value, [Endian endian = Endian.big]) { + throw UnsupportedError('Uint64 accessor not supported by dart2js.'); + } + + /** + * Sets the byte at the specified [byteOffset] in this object to the + * unsigned binary representation of the specified [value], which must fit + * in a single byte. in other words, [value] must be between 0 and 255, + * inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, + * or greater than or equal to the length of this object. + */ + void setUint8(int byteOffset, int value) native; + + static NativeByteData _create1(arg) => + JS('NativeByteData', 'new DataView(new ArrayBuffer(#))', arg); + + static NativeByteData _create2(arg1, arg2) => + JS('NativeByteData', 'new DataView(#, #)', arg1, arg2); + + static NativeByteData _create3(arg1, arg2, arg3) => + JS('NativeByteData', 'new DataView(#, #, #)', arg1, arg2, arg3); +} + +abstract class NativeTypedArray extends NativeTypedData + implements JavaScriptIndexingBehavior { + int get length; + + void _setRangeFast( + int start, int end, NativeTypedArray source, int skipCount) { + int targetLength = this.length; + _checkPosition(start, targetLength, "start"); + _checkPosition(end, targetLength, "end"); + if (start > end) throw RangeError.range(start, 0, end); + int count = end - start; + + if (skipCount < 0) throw ArgumentError(skipCount); + + int sourceLength = source.length; + if (sourceLength - skipCount < count) { + throw StateError('Not enough elements'); + } + + if (skipCount != 0 || sourceLength != count) { + // Create a view of the exact subrange that is copied from the source. + source = JS('', '#.subarray(#, #)', source, skipCount, skipCount + count); + } + JS('void', '#.set(#, #)', this, source, start); + } +} + +abstract class NativeTypedArrayOfDouble extends NativeTypedArray + with ListMixin, FixedLengthListMixin { + int get length => JS('int', '#.length', this); + + double operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('double', '#[#]', this, index); + } + + void operator []=(int index, num value) { + _checkValidIndex(index, this, this.length); + JS('void', '#[#] = #', this, index, value); + } + + void setRange(int start, int end, Iterable iterable, + [int skipCount = 0]) { + if (iterable is NativeTypedArrayOfDouble) { + _setRangeFast(start, end, iterable, skipCount); + return; + } + super.setRange(start, end, iterable, skipCount); + } +} + +abstract class NativeTypedArrayOfInt extends NativeTypedArray + with ListMixin, FixedLengthListMixin + implements List { + int get length => JS('int', '#.length', this); + + // operator[]() is not here since different versions have different return + // types + + void operator []=(int index, int value) { + _checkValidIndex(index, this, this.length); + JS('void', '#[#] = #', this, index, value); + } + + void setRange(int start, int end, Iterable iterable, + [int skipCount = 0]) { + if (iterable is NativeTypedArrayOfInt) { + _setRangeFast(start, end, iterable, skipCount); + return; + } + super.setRange(start, end, iterable, skipCount); + } +} + +@Native("Float32Array") +class NativeFloat32List extends NativeTypedArrayOfDouble + implements Float32List { + factory NativeFloat32List(int length) => _create1(_checkLength(length)); + + factory NativeFloat32List.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeFloat32List.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Float32List; + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeFloat32List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeFloat32List _create1(arg) => + JS('NativeFloat32List', 'new Float32Array(#)', arg); + + static NativeFloat32List _create2(arg1, arg2) => + JS('NativeFloat32List', 'new Float32Array(#, #)', arg1, arg2); + + static NativeFloat32List _create3(arg1, arg2, arg3) => + JS('NativeFloat32List', 'new Float32Array(#, #, #)', arg1, arg2, arg3); +} + +@Native("Float64Array") +class NativeFloat64List extends NativeTypedArrayOfDouble + implements Float64List { + factory NativeFloat64List(int length) => _create1(_checkLength(length)); + + factory NativeFloat64List.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeFloat64List.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Float64List; + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeFloat64List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeFloat64List _create1(arg) => + JS('NativeFloat64List', 'new Float64Array(#)', arg); + + static NativeFloat64List _create2(arg1, arg2) => + JS('NativeFloat64List', 'new Float64Array(#, #)', arg1, arg2); + + static NativeFloat64List _create3(arg1, arg2, arg3) => + JS('NativeFloat64List', 'new Float64Array(#, #, #)', arg1, arg2, arg3); +} + +@Native("Int16Array") +class NativeInt16List extends NativeTypedArrayOfInt implements Int16List { + factory NativeInt16List(int length) => _create1(_checkLength(length)); + + factory NativeInt16List.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeInt16List.view( + NativeByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Int16List; + + int operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('int', '#[#]', this, index); + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeInt16List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeInt16List _create1(arg) => + JS('NativeInt16List', 'new Int16Array(#)', arg); + + static NativeInt16List _create2(arg1, arg2) => + JS('NativeInt16List', 'new Int16Array(#, #)', arg1, arg2); + + static NativeInt16List _create3(arg1, arg2, arg3) => + JS('NativeInt16List', 'new Int16Array(#, #, #)', arg1, arg2, arg3); +} + +@Native("Int32Array") +class NativeInt32List extends NativeTypedArrayOfInt implements Int32List { + factory NativeInt32List(int length) => _create1(_checkLength(length)); + + factory NativeInt32List.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeInt32List.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Int32List; + + int operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('int', '#[#]', this, index); + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeInt32List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeInt32List _create1(arg) => + JS('NativeInt32List', 'new Int32Array(#)', arg); + + static NativeInt32List _create2(arg1, arg2) => + JS('NativeInt32List', 'new Int32Array(#, #)', arg1, arg2); + + static NativeInt32List _create3(arg1, arg2, arg3) => + JS('NativeInt32List', 'new Int32Array(#, #, #)', arg1, arg2, arg3); +} + +@Native("Int8Array") +class NativeInt8List extends NativeTypedArrayOfInt implements Int8List { + factory NativeInt8List(int length) => _create1(_checkLength(length)); + + factory NativeInt8List.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeInt8List.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Int8List; + + int operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('int', '#[#]', this, index); + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeInt8List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeInt8List _create1(arg) => + JS('NativeInt8List', 'new Int8Array(#)', arg); + + static NativeInt8List _create2(arg1, arg2) => + JS('NativeInt8List', 'new Int8Array(#, #)', arg1, arg2); + + static Int8List _create3(arg1, arg2, arg3) => + JS('NativeInt8List', 'new Int8Array(#, #, #)', arg1, arg2, arg3); +} + +@Native("Uint16Array") +class NativeUint16List extends NativeTypedArrayOfInt implements Uint16List { + factory NativeUint16List(int length) => _create1(_checkLength(length)); + + factory NativeUint16List.fromList(List list) => + _create1(_ensureNativeList(list)); + + factory NativeUint16List.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Uint16List; + + int operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('int', '#[#]', this, index); + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeUint16List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeUint16List _create1(arg) => + JS('NativeUint16List', 'new Uint16Array(#)', arg); + + static NativeUint16List _create2(arg1, arg2) => + JS('NativeUint16List', 'new Uint16Array(#, #)', arg1, arg2); + + static NativeUint16List _create3(arg1, arg2, arg3) => + JS('NativeUint16List', 'new Uint16Array(#, #, #)', arg1, arg2, arg3); +} + +@Native("Uint32Array") +class NativeUint32List extends NativeTypedArrayOfInt implements Uint32List { + factory NativeUint32List(int length) => _create1(_checkLength(length)); + + factory NativeUint32List.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeUint32List.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Uint32List; + + int operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('int', '#[#]', this, index); + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeUint32List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeUint32List _create1(arg) => + JS('NativeUint32List', 'new Uint32Array(#)', arg); + + static NativeUint32List _create2(arg1, arg2) => + JS('NativeUint32List', 'new Uint32Array(#, #)', arg1, arg2); + + static NativeUint32List _create3(arg1, arg2, arg3) => + JS('NativeUint32List', 'new Uint32Array(#, #, #)', arg1, arg2, arg3); +} + +@Native("Uint8ClampedArray,CanvasPixelArray") +class NativeUint8ClampedList extends NativeTypedArrayOfInt + implements Uint8ClampedList { + factory NativeUint8ClampedList(int length) => _create1(_checkLength(length)); + + factory NativeUint8ClampedList.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeUint8ClampedList.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Uint8ClampedList; + + int get length => JS('int', '#.length', this); + + int operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('int', '#[#]', this, index); + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = + JS('NativeUint8ClampedList', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeUint8ClampedList _create1(arg) => + JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#)', arg); + + static NativeUint8ClampedList _create2(arg1, arg2) => + JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#, #)', arg1, arg2); + + static NativeUint8ClampedList _create3(arg1, arg2, arg3) => JS( + 'NativeUint8ClampedList', + 'new Uint8ClampedArray(#, #, #)', + arg1, + arg2, + arg3); +} + +// On some browsers Uint8ClampedArray is a subtype of Uint8Array. Marking +// Uint8List as !nonleaf ensures that the native dispatch correctly handles +// the potential for Uint8ClampedArray to 'accidentally' pick up the +// dispatch record for Uint8List. +@Native("Uint8Array,!nonleaf") +class NativeUint8List extends NativeTypedArrayOfInt implements Uint8List { + factory NativeUint8List(int length) => _create1(_checkLength(length)); + + factory NativeUint8List.fromList(List elements) => + _create1(_ensureNativeList(elements)); + + factory NativeUint8List.view( + ByteBuffer buffer, int offsetInBytes, int length) { + _checkViewArguments(buffer, offsetInBytes, length); + return length == null + ? _create2(buffer, offsetInBytes) + : _create3(buffer, offsetInBytes, length); + } + + Type get runtimeType => Uint8List; + + int get length => JS('int', '#.length', this); + + int operator [](int index) { + _checkValidIndex(index, this, this.length); + return JS('int', '#[#]', this, index); + } + + List sublist(int start, [int end]) { + end = _checkValidRange(start, end, this.length); + var source = JS('NativeUint8List', '#.subarray(#, #)', this, start, end); + return _create1(source); + } + + static NativeUint8List _create1(arg) => + JS('NativeUint8List', 'new Uint8Array(#)', arg); + + static NativeUint8List _create2(arg1, arg2) => + JS('NativeUint8List', 'new Uint8Array(#, #)', arg1, arg2); + + static NativeUint8List _create3(arg1, arg2, arg3) => + JS('NativeUint8List', 'new Uint8Array(#, #, #)', arg1, arg2, arg3); +} + +/** + * Implementation of Dart Float32x4 immutable value type and operations. + * Float32x4 stores 4 32-bit floating point values in "lanes". + * The lanes are "x", "y", "z", and "w" respectively. + */ +class NativeFloat32x4 implements Float32x4 { + final double x; + final double y; + final double z; + final double w; + + static final NativeFloat32List _list = NativeFloat32List(4); + static final Uint32List _uint32view = _list.buffer.asUint32List(); + + static _truncate(x) { + _list[0] = x; + return _list[0]; + } + + NativeFloat32x4(double x, double y, double z, double w) + : this.x = _truncate(x), + this.y = _truncate(y), + this.z = _truncate(z), + this.w = _truncate(w) { + // We would prefer to check for `double` but in dart2js we can't see the + // difference anyway. + if (x is! num) throw ArgumentError(x); + if (y is! num) throw ArgumentError(y); + if (z is! num) throw ArgumentError(z); + if (w is! num) throw ArgumentError(w); + } + + NativeFloat32x4.splat(double v) : this(v, v, v, v); + NativeFloat32x4.zero() : this._truncated(0.0, 0.0, 0.0, 0.0); + + /// Returns a bit-wise copy of [i] as a Float32x4. + factory NativeFloat32x4.fromInt32x4Bits(Int32x4 i) { + _uint32view[0] = i.x; + _uint32view[1] = i.y; + _uint32view[2] = i.z; + _uint32view[3] = i.w; + return NativeFloat32x4._truncated(_list[0], _list[1], _list[2], _list[3]); + } + + NativeFloat32x4.fromFloat64x2(Float64x2 v) + : this._truncated(_truncate(v.x), _truncate(v.y), 0.0, 0.0); + + /// Creates a new NativeFloat32x4. + /// + /// Does not verify if the given arguments are non-null. + NativeFloat32x4._doubles(double x, double y, double z, double w) + : this.x = _truncate(x), + this.y = _truncate(y), + this.z = _truncate(z), + this.w = _truncate(w); + + /// Creates a new NativeFloat32x4. + /// + /// The constructor does not truncate the arguments. They must already be in + /// the correct range. It does not verify the type of the given arguments, + /// either. + NativeFloat32x4._truncated(this.x, this.y, this.z, this.w); + + String toString() { + return '[$x, $y, $z, $w]'; + } + + /// Addition operator. + Float32x4 operator +(Float32x4 other) { + double _x = x + other.x; + double _y = y + other.y; + double _z = z + other.z; + double _w = w + other.w; + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } + + /// Negate operator. + Float32x4 operator -() { + return NativeFloat32x4._truncated(-x, -y, -z, -w); + } + + /// Subtraction operator. + Float32x4 operator -(Float32x4 other) { + double _x = x - other.x; + double _y = y - other.y; + double _z = z - other.z; + double _w = w - other.w; + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } + + /// Multiplication operator. + Float32x4 operator *(Float32x4 other) { + double _x = x * other.x; + double _y = y * other.y; + double _z = z * other.z; + double _w = w * other.w; + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } + + /// Division operator. + Float32x4 operator /(Float32x4 other) { + double _x = x / other.x; + double _y = y / other.y; + double _z = z / other.z; + double _w = w / other.w; + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } + + /// Relational less than. + Int32x4 lessThan(Float32x4 other) { + bool _cx = x < other.x; + bool _cy = y < other.y; + bool _cz = z < other.z; + bool _cw = w < other.w; + return NativeInt32x4._truncated( + _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + } + + /// Relational less than or equal. + Int32x4 lessThanOrEqual(Float32x4 other) { + bool _cx = x <= other.x; + bool _cy = y <= other.y; + bool _cz = z <= other.z; + bool _cw = w <= other.w; + return NativeInt32x4._truncated( + _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + } + + /// Relational greater than. + Int32x4 greaterThan(Float32x4 other) { + bool _cx = x > other.x; + bool _cy = y > other.y; + bool _cz = z > other.z; + bool _cw = w > other.w; + return NativeInt32x4._truncated( + _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + } + + /// Relational greater than or equal. + Int32x4 greaterThanOrEqual(Float32x4 other) { + bool _cx = x >= other.x; + bool _cy = y >= other.y; + bool _cz = z >= other.z; + bool _cw = w >= other.w; + return NativeInt32x4._truncated( + _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + } + + /// Relational equal. + Int32x4 equal(Float32x4 other) { + bool _cx = x == other.x; + bool _cy = y == other.y; + bool _cz = z == other.z; + bool _cw = w == other.w; + return NativeInt32x4._truncated( + _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + } + + /// Relational not-equal. + Int32x4 notEqual(Float32x4 other) { + bool _cx = x != other.x; + bool _cy = y != other.y; + bool _cz = z != other.z; + bool _cw = w != other.w; + return NativeInt32x4._truncated( + _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + } + + /// Returns a copy of [this] each lane being scaled by [s]. + Float32x4 scale(double s) { + double _x = s * x; + double _y = s * y; + double _z = s * z; + double _w = s * w; + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } + + /// Returns the absolute value of this [Float32x4]. + Float32x4 abs() { + double _x = x.abs(); + double _y = y.abs(); + double _z = z.abs(); + double _w = w.abs(); + return NativeFloat32x4._truncated(_x, _y, _z, _w); + } + + /// Clamps [this] to be in the range [lowerLimit]-[upperLimit]. + Float32x4 clamp(Float32x4 lowerLimit, Float32x4 upperLimit) { + double _lx = lowerLimit.x; + double _ly = lowerLimit.y; + double _lz = lowerLimit.z; + double _lw = lowerLimit.w; + double _ux = upperLimit.x; + double _uy = upperLimit.y; + double _uz = upperLimit.z; + double _uw = upperLimit.w; + double _x = x; + double _y = y; + double _z = z; + double _w = w; + // MAX(MIN(self, upper), lower). + _x = _x > _ux ? _ux : _x; + _y = _y > _uy ? _uy : _y; + _z = _z > _uz ? _uz : _z; + _w = _w > _uw ? _uw : _w; + _x = _x < _lx ? _lx : _x; + _y = _y < _ly ? _ly : _y; + _z = _z < _lz ? _lz : _z; + _w = _w < _lw ? _lw : _w; + return NativeFloat32x4._truncated(_x, _y, _z, _w); + } + + /// Extract the sign bit from each lane return them in the first 4 bits. + int get signMask { + var view = _uint32view; + var mx, my, mz, mw; + _list[0] = x; + _list[1] = y; + _list[2] = z; + _list[3] = w; + // This is correct because dart2js uses the unsigned right shift. + mx = (view[0] & 0x80000000) >> 31; + my = (view[1] & 0x80000000) >> 30; + mz = (view[2] & 0x80000000) >> 29; + mw = (view[3] & 0x80000000) >> 28; + return mx | my | mz | mw; + } + + /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. + Float32x4 shuffle(int mask) { + if ((mask < 0) || (mask > 255)) { + throw RangeError.range(mask, 0, 255, "mask"); + } + _list[0] = x; + _list[1] = y; + _list[2] = z; + _list[3] = w; + + double _x = _list[mask & 0x3]; + double _y = _list[(mask >> 2) & 0x3]; + double _z = _list[(mask >> 4) & 0x3]; + double _w = _list[(mask >> 6) & 0x3]; + return NativeFloat32x4._truncated(_x, _y, _z, _w); + } + + /// Shuffle the lane values in [this] and [other]. The returned + /// Float32x4 will have XY lanes from [this] and ZW lanes from [other]. + /// Uses the same [mask] as [shuffle]. + Float32x4 shuffleMix(Float32x4 other, int mask) { + if ((mask < 0) || (mask > 255)) { + throw RangeError.range(mask, 0, 255, "mask"); + } + _list[0] = x; + _list[1] = y; + _list[2] = z; + _list[3] = w; + double _x = _list[mask & 0x3]; + double _y = _list[(mask >> 2) & 0x3]; + + _list[0] = other.x; + _list[1] = other.y; + _list[2] = other.z; + _list[3] = other.w; + double _z = _list[(mask >> 4) & 0x3]; + double _w = _list[(mask >> 6) & 0x3]; + return NativeFloat32x4._truncated(_x, _y, _z, _w); + } + + /// Copy [this] and replace the [x] lane. + Float32x4 withX(double newX) { + return NativeFloat32x4._truncated(_truncate(newX), y, z, w); + } + + /// Copy [this] and replace the [y] lane. + Float32x4 withY(double newY) { + return NativeFloat32x4._truncated(x, _truncate(newY), z, w); + } + + /// Copy [this] and replace the [z] lane. + Float32x4 withZ(double newZ) { + return NativeFloat32x4._truncated(x, y, _truncate(newZ), w); + } + + /// Copy [this] and replace the [w] lane. + Float32x4 withW(double newW) { + return NativeFloat32x4._truncated(x, y, z, _truncate(newW)); + } + + /// Returns the lane-wise minimum value in [this] or [other]. + Float32x4 min(Float32x4 other) { + double _x = x < other.x ? x : other.x; + double _y = y < other.y ? y : other.y; + double _z = z < other.z ? z : other.z; + double _w = w < other.w ? w : other.w; + return NativeFloat32x4._truncated(_x, _y, _z, _w); + } + + /// Returns the lane-wise maximum value in [this] or [other]. + Float32x4 max(Float32x4 other) { + double _x = x > other.x ? x : other.x; + double _y = y > other.y ? y : other.y; + double _z = z > other.z ? z : other.z; + double _w = w > other.w ? w : other.w; + return NativeFloat32x4._truncated(_x, _y, _z, _w); + } + + /// Returns the square root of [this]. + Float32x4 sqrt() { + double _x = Math.sqrt(x); + double _y = Math.sqrt(y); + double _z = Math.sqrt(z); + double _w = Math.sqrt(w); + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } + + /// Returns the reciprocal of [this]. + Float32x4 reciprocal() { + double _x = 1.0 / x; + double _y = 1.0 / y; + double _z = 1.0 / z; + double _w = 1.0 / w; + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } + + /// Returns the square root of the reciprocal of [this]. + Float32x4 reciprocalSqrt() { + double _x = Math.sqrt(1.0 / x); + double _y = Math.sqrt(1.0 / y); + double _z = Math.sqrt(1.0 / z); + double _w = Math.sqrt(1.0 / w); + return NativeFloat32x4._doubles(_x, _y, _z, _w); + } +} + +/** + * Interface of Dart Int32x4 and operations. + * Int32x4 stores 4 32-bit bit-masks in "lanes". + * The lanes are "x", "y", "z", and "w" respectively. + */ +class NativeInt32x4 implements Int32x4 { + final int x; + final int y; + final int z; + final int w; + + static final _list = NativeInt32List(4); + + static _truncate(x) { + _list[0] = x; + return _list[0]; + } + + NativeInt32x4(int x, int y, int z, int w) + : this.x = _truncate(x), + this.y = _truncate(y), + this.z = _truncate(z), + this.w = _truncate(w) { + if (x != this.x && x is! int) throw ArgumentError(x); + if (y != this.y && y is! int) throw ArgumentError(y); + if (z != this.z && z is! int) throw ArgumentError(z); + if (w != this.w && w is! int) throw ArgumentError(w); + } + + NativeInt32x4.bool(bool x, bool y, bool z, bool w) + : this.x = x ? -1 : 0, + this.y = y ? -1 : 0, + this.z = z ? -1 : 0, + this.w = w ? -1 : 0; + + /// Returns a bit-wise copy of [f] as a Int32x4. + factory NativeInt32x4.fromFloat32x4Bits(Float32x4 f) { + NativeFloat32List floatList = NativeFloat32x4._list; + floatList[0] = f.x; + floatList[1] = f.y; + floatList[2] = f.z; + floatList[3] = f.w; + NativeInt32List view = floatList.buffer.asInt32List(); + return NativeInt32x4._truncated(view[0], view[1], view[2], view[3]); + } + + NativeInt32x4._truncated(this.x, this.y, this.z, this.w); + + String toString() => '[$x, $y, $z, $w]'; + + /// The bit-wise or operator. + Int32x4 operator |(Int32x4 other) { + // Dart2js uses unsigned results for bit-operations. + // We use "JS" to fall back to the signed versions. + return NativeInt32x4._truncated( + JS("int", "# | #", x, other.x), + JS("int", "# | #", y, other.y), + JS("int", "# | #", z, other.z), + JS("int", "# | #", w, other.w)); + } + + /// The bit-wise and operator. + Int32x4 operator &(Int32x4 other) { + // Dart2js uses unsigned results for bit-operations. + // We use "JS" to fall back to the signed versions. + return NativeInt32x4._truncated( + JS("int", "# & #", x, other.x), + JS("int", "# & #", y, other.y), + JS("int", "# & #", z, other.z), + JS("int", "# & #", w, other.w)); + } + + /// The bit-wise xor operator. + Int32x4 operator ^(Int32x4 other) { + // Dart2js uses unsigned results for bit-operations. + // We use "JS" to fall back to the signed versions. + return NativeInt32x4._truncated( + JS("int", "# ^ #", x, other.x), + JS("int", "# ^ #", y, other.y), + JS("int", "# ^ #", z, other.z), + JS("int", "# ^ #", w, other.w)); + } + + Int32x4 operator +(Int32x4 other) { + // Avoid going through the typed array by "| 0" the result. + return NativeInt32x4._truncated( + JS("int", "(# + #) | 0", x, other.x), + JS("int", "(# + #) | 0", y, other.y), + JS("int", "(# + #) | 0", z, other.z), + JS("int", "(# + #) | 0", w, other.w)); + } + + Int32x4 operator -(Int32x4 other) { + // Avoid going through the typed array by "| 0" the result. + return NativeInt32x4._truncated( + JS("int", "(# - #) | 0", x, other.x), + JS("int", "(# - #) | 0", y, other.y), + JS("int", "(# - #) | 0", z, other.z), + JS("int", "(# - #) | 0", w, other.w)); + } + + Int32x4 operator -() { + // Avoid going through the typed array by "| 0" the result. + return NativeInt32x4._truncated( + JS("int", "(-#) | 0", x), + JS("int", "(-#) | 0", y), + JS("int", "(-#) | 0", z), + JS("int", "(-#) | 0", w)); + } + + /// Extract the top bit from each lane return them in the first 4 bits. + int get signMask { + int mx = (x & 0x80000000) >> 31; + int my = (y & 0x80000000) >> 31; + int mz = (z & 0x80000000) >> 31; + int mw = (w & 0x80000000) >> 31; + return mx | my << 1 | mz << 2 | mw << 3; + } + + /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. + Int32x4 shuffle(int mask) { + if ((mask < 0) || (mask > 255)) { + throw RangeError.range(mask, 0, 255, "mask"); + } + _list[0] = x; + _list[1] = y; + _list[2] = z; + _list[3] = w; + int _x = _list[mask & 0x3]; + int _y = _list[(mask >> 2) & 0x3]; + int _z = _list[(mask >> 4) & 0x3]; + int _w = _list[(mask >> 6) & 0x3]; + return NativeInt32x4._truncated(_x, _y, _z, _w); + } + + /// Shuffle the lane values in [this] and [other]. The returned + /// Int32x4 will have XY lanes from [this] and ZW lanes from [other]. + /// Uses the same [mask] as [shuffle]. + Int32x4 shuffleMix(Int32x4 other, int mask) { + if ((mask < 0) || (mask > 255)) { + throw RangeError.range(mask, 0, 255, "mask"); + } + _list[0] = x; + _list[1] = y; + _list[2] = z; + _list[3] = w; + int _x = _list[mask & 0x3]; + int _y = _list[(mask >> 2) & 0x3]; + + _list[0] = other.x; + _list[1] = other.y; + _list[2] = other.z; + _list[3] = other.w; + int _z = _list[(mask >> 4) & 0x3]; + int _w = _list[(mask >> 6) & 0x3]; + return NativeInt32x4._truncated(_x, _y, _z, _w); + } + + /// Returns a new [Int32x4] copied from [this] with a new x value. + Int32x4 withX(int x) { + int _x = _truncate(x); + return NativeInt32x4._truncated(_x, y, z, w); + } + + /// Returns a new [Int32x4] copied from [this] with a new y value. + Int32x4 withY(int y) { + int _y = _truncate(y); + return NativeInt32x4._truncated(x, _y, z, w); + } + + /// Returns a new [Int32x4] copied from [this] with a new z value. + Int32x4 withZ(int z) { + int _z = _truncate(z); + return NativeInt32x4._truncated(x, y, _z, w); + } + + /// Returns a new [Int32x4] copied from [this] with a new w value. + Int32x4 withW(int w) { + int _w = _truncate(w); + return NativeInt32x4._truncated(x, y, z, _w); + } + + /// Extracted x value. Returns `false` for 0, `true` for any other value. + bool get flagX => x != 0; + + /// Extracted y value. Returns `false` for 0, `true` for any other value. + bool get flagY => y != 0; + + /// Extracted z value. Returns `false` for 0, `true` for any other value. + bool get flagZ => z != 0; + + /// Extracted w value. Returns `false` for 0, `true` for any other value. + bool get flagW => w != 0; + + /// Returns a new [Int32x4] copied from [this] with a new x value. + Int32x4 withFlagX(bool flagX) { + int _x = flagX ? -1 : 0; + return NativeInt32x4._truncated(_x, y, z, w); + } + + /// Returns a new [Int32x4] copied from [this] with a new y value. + Int32x4 withFlagY(bool flagY) { + int _y = flagY ? -1 : 0; + return NativeInt32x4._truncated(x, _y, z, w); + } + + /// Returns a new [Int32x4] copied from [this] with a new z value. + Int32x4 withFlagZ(bool flagZ) { + int _z = flagZ ? -1 : 0; + return NativeInt32x4._truncated(x, y, _z, w); + } + + /// Returns a new [Int32x4] copied from [this] with a new w value. + Int32x4 withFlagW(bool flagW) { + int _w = flagW ? -1 : 0; + return NativeInt32x4._truncated(x, y, z, _w); + } + + /// Merge [trueValue] and [falseValue] based on [this]' bit mask: + /// Select bit from [trueValue] when bit in [this] is on. + /// Select bit from [falseValue] when bit in [this] is off. + Float32x4 select(Float32x4 trueValue, Float32x4 falseValue) { + var floatList = NativeFloat32x4._list; + var intView = NativeFloat32x4._uint32view; + + floatList[0] = trueValue.x; + floatList[1] = trueValue.y; + floatList[2] = trueValue.z; + floatList[3] = trueValue.w; + int stx = intView[0]; + int sty = intView[1]; + int stz = intView[2]; + int stw = intView[3]; + + floatList[0] = falseValue.x; + floatList[1] = falseValue.y; + floatList[2] = falseValue.z; + floatList[3] = falseValue.w; + int sfx = intView[0]; + int sfy = intView[1]; + int sfz = intView[2]; + int sfw = intView[3]; + int _x = (x & stx) | (~x & sfx); + int _y = (y & sty) | (~y & sfy); + int _z = (z & stz) | (~z & sfz); + int _w = (w & stw) | (~w & sfw); + intView[0] = _x; + intView[1] = _y; + intView[2] = _z; + intView[3] = _w; + return NativeFloat32x4._truncated( + floatList[0], floatList[1], floatList[2], floatList[3]); + } +} + +class NativeFloat64x2 implements Float64x2 { + final double x; + final double y; + + static NativeFloat64List _list = NativeFloat64List(2); + static NativeUint32List _uint32View = _list.buffer.asUint32List(); + + NativeFloat64x2(this.x, this.y) { + if (x is! num) throw ArgumentError(x); + if (y is! num) throw ArgumentError(y); + } + + NativeFloat64x2.splat(double v) : this(v, v); + + NativeFloat64x2.zero() : this.splat(0.0); + + NativeFloat64x2.fromFloat32x4(Float32x4 v) : this(v.x, v.y); + + /// Arguments [x] and [y] must be doubles. + NativeFloat64x2._doubles(this.x, this.y); + + String toString() => '[$x, $y]'; + + /// Addition operator. + Float64x2 operator +(Float64x2 other) { + return NativeFloat64x2._doubles(x + other.x, y + other.y); + } + + /// Negate operator. + Float64x2 operator -() { + return NativeFloat64x2._doubles(-x, -y); + } + + /// Subtraction operator. + Float64x2 operator -(Float64x2 other) { + return NativeFloat64x2._doubles(x - other.x, y - other.y); + } + + /// Multiplication operator. + Float64x2 operator *(Float64x2 other) { + return NativeFloat64x2._doubles(x * other.x, y * other.y); + } + + /// Division operator. + Float64x2 operator /(Float64x2 other) { + return NativeFloat64x2._doubles(x / other.x, y / other.y); + } + + /// Returns a copy of [this] each lane being scaled by [s]. + Float64x2 scale(double s) { + return NativeFloat64x2._doubles(x * s, y * s); + } + + /// Returns the absolute value of this [Float64x2]. + Float64x2 abs() { + return NativeFloat64x2._doubles(x.abs(), y.abs()); + } + + /// Clamps [this] to be in the range [lowerLimit]-[upperLimit]. + Float64x2 clamp(Float64x2 lowerLimit, Float64x2 upperLimit) { + double _lx = lowerLimit.x; + double _ly = lowerLimit.y; + double _ux = upperLimit.x; + double _uy = upperLimit.y; + double _x = x; + double _y = y; + // MAX(MIN(self, upper), lower). + _x = _x > _ux ? _ux : _x; + _y = _y > _uy ? _uy : _y; + _x = _x < _lx ? _lx : _x; + _y = _y < _ly ? _ly : _y; + return NativeFloat64x2._doubles(_x, _y); + } + + /// Extract the sign bits from each lane return them in the first 2 bits. + int get signMask { + var view = _uint32View; + _list[0] = x; + _list[1] = y; + var mx = (view[1] & 0x80000000) >> 31; + var my = (view[3] & 0x80000000) >> 31; + return mx | my << 1; + } + + /// Returns a new [Float64x2] copied from [this] with a new x value. + Float64x2 withX(double x) { + if (x is! num) throw ArgumentError(x); + return NativeFloat64x2._doubles(x, y); + } + + /// Returns a new [Float64x2] copied from [this] with a new y value. + Float64x2 withY(double y) { + if (y is! num) throw ArgumentError(y); + return NativeFloat64x2._doubles(x, y); + } + + /// Returns the lane-wise minimum value in [this] or [other]. + Float64x2 min(Float64x2 other) { + return NativeFloat64x2._doubles( + x < other.x ? x : other.x, y < other.y ? y : other.y); + } + + /// Returns the lane-wise maximum value in [this] or [other]. + Float64x2 max(Float64x2 other) { + return NativeFloat64x2._doubles( + x > other.x ? x : other.x, y > other.y ? y : other.y); + } + + /// Returns the lane-wise square root of [this]. + Float64x2 sqrt() { + return NativeFloat64x2._doubles(Math.sqrt(x), Math.sqrt(y)); + } +} + +/// Checks that the value is a Uint32. If not, it's not valid as an array +/// index or offset. Also ensures that the value is non-negative. +bool _isInvalidArrayIndex(int index) { + return (JS('bool', '(# >>> 0 !== #)', index, index)); +} + +/// Checks that [index] is a valid index into [list] which has length [length]. +/// +/// That is, [index] is an integer in the range `0..length - 1`. +void _checkValidIndex(int index, List list, int length) { + if (_isInvalidArrayIndex(index) || JS('int', '#', index) >= length) { + throw diagnoseIndexError(list, index); + } +} + +/// Checks that [start] and [end] form a range of a list of length [length]. +/// +/// That is: `start` and `end` are integers with `0 <= start <= end <= length`. +/// If `end` is `null` in which case it is considered to be `length` +/// +/// Returns the actual value of `end`, which is `length` if `end` is `null`, and +/// the original value of `end` otherwise. +int _checkValidRange(int start, int end, int length) { + if (_isInvalidArrayIndex(start) || // Ensures start is non-negative int. + ((end == null) + ? start > length + : (_isInvalidArrayIndex(end) || start > end || end > length))) { + throw diagnoseRangeError(start, end, length); + } + if (end == null) return length; + return end; +} +lNN<4*(. $'/"&?>==MEA??>A??>AD?CCM8C@C@G O:G O:==BNE)?$F/N7:8,####)I#?'36 6,33?*%0++++720))))251/@NE';D/JN66,####'G#;%14 4,33=*#0((((500))))05//BNE)?$F/N7:8,##I#?'36 6),33?*%0++20))251/-:,$"0"O"O 'AJ 9?=-)0MK EKON:%0F*8N$(#*CH(HKHNIJ:IJ:8*3$#HIF L9AA7>JF L9A@IK?899'HC9HFJHJNK59AN?KIC99AN?KGKL?9AL=IHKM?9AL=IIKN?9AKHGLH992NEJ*9AM>JOEK*9AM>JPEL*9ALIGMJ6<3)E0>6G8,D$2.<7&,/3MQ4A;1"0.,00?065>31M ,00<-659K?-":8*3'/5P,;3E9N9K?-":8*3'/5P,;3E9NKI:- @8*3%0+,5N*71A7JKI:- :8*3%0+,5N*71A7JIH9-:8*3$0+,5M)50?0HMJ7)!:8*3&0+,5O+92C8LMJ;-!:8*3&0+,5O+92C8L.;"PA-':8*3,10+,5L1E8OB ( KLE"KI:- :8*3%10+,5N*71A7JI?6-?E: M++++6@57O-C%;C%OM>*57*5*5*5&%A%-%A)%A(0%A#%A&%A>567B@%7KF''''P &4#***7BJ)4&4#***7,!A,!A,!A,!A@#++++7@#++++7)5(5;$$$$5-16)+, ::::5399;I<+ &98%((()!&98%((()!&98%((()&@%.../&@%.../@%"""#J%%%%-P&4 '''5BH)0&4 '''5E2E2E2E2LLLLE"2E"2E"2E"2D<>@+/ !!!!%%%%'A-9E$++0,?-,#*?-*?*?*?>367B@%-L++G++G++@#%?@#%?3AJB'8PA:H+MPEQ+7KK2"Lfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/async.dart9// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Support for asynchronous programming, + * with classes such as Future and Stream. + * + * Understanding [Future]s and [Stream]s is a prerequisite for + * writing just about any Dart program. + * + * To use this library in your code: + * + * import 'dart:async'; + * + * ## Future + * + * A Future object represents a computation whose return value + * might not yet be available. + * The Future returns the value of the computation + * when it completes at some time in the future. + * Futures are often used for potentially lengthy computations + * such as I/O and interaction with users. + * + * Many methods in the Dart libraries return Futures when + * performing tasks. For example, when binding an HttpServer + * to a host and port, the `bind()` method returns a Future. + * + * HttpServer.bind('127.0.0.1', 4444) + * .then((server) => print('${server.isBroadcast}')) + * .catchError(print); + * + * [Future.then] registers a callback function that runs + * when the Future's operation, in this case the `bind()` method, + * completes successfully. + * The value returned by the operation + * is passed into the callback function. + * In this example, the `bind()` method returns the HttpServer + * object. The callback function prints one of its properties. + * [Future.catchError] registers a callback function that + * runs if an error occurs within the Future. + * + * ## Stream + * + * A Stream provides an asynchronous sequence of data. + * Examples of data sequences include individual events, like mouse clicks, + * or sequential chunks of larger data, like multiple byte lists with the + * contents of a file + * such as mouse clicks, and a stream of byte lists read from a file. + * The following example opens a file for reading. + * [Stream.listen] registers a callback function that runs + * each time more data is available. + * + * Stream> stream = new File('quotes.txt').openRead(); + * stream.transform(utf8.decoder).listen(print); + * + * The stream emits a sequence of a list of bytes. + * The program must interpret the bytes or handle the raw byte data. + * Here, the code uses a UTF-8 decoder (provided in the `dart:convert` library) + * to convert the sequence of bytes into a sequence + * of Dart strings. + * + * Another common use of streams is for user-generated events + * in a web app: The following code listens for mouse clicks on a button. + * + * querySelector('#myButton').onClick.listen((_) => print('Click.')); + * + * ## Other resources + * + * * The [dart:async section of the library tour][asynchronous-programming]: + * A brief overview of asynchronous programming. + * + * * [Use Future-Based APIs][futures-tutorial]: A closer look at Futures and + * how to use them to write asynchronous Dart code. + * + * * [Futures and Error Handling][futures-error-handling]: Everything you + * wanted to know about handling errors and exceptions when working with + * Futures (but were afraid to ask). + * + * * [The Event Loop and Dart](https://www.dartlang.org/articles/event-loop/): + * Learn how Dart handles the event queue and microtask queue, so you can + * write better asynchronous code with fewer surprises. + * + * * [test package: Asynchronous Tests][test-readme]: How to test asynchronous + * code. + * + * [asynchronous-programming]: https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartasync---asynchronous-programming + * [futures-tutorial]: https://www.dartlang.org/docs/tutorials/futures/ + * [futures-error-handling]: https://www.dartlang.org/articles/futures-and-error-handling/ + * [test-readme]: https://pub.dartlang.org/packages/test + * + * {@category Core} + */ +library dart.async; + +import "dart:collection" show HashMap, IterableBase; +import "dart:_internal" + show + CastStream, + CastStreamTransformer, + printToZone, + printToConsole, + IterableElementError; + +part 'async_error.dart'; +part 'broadcast_stream_controller.dart'; +part 'deferred_load.dart'; +part 'future.dart'; +part 'future_impl.dart'; +part 'schedule_microtask.dart'; +part 'stream.dart'; +part 'stream_controller.dart'; +part 'stream_impl.dart'; +part 'stream_pipe.dart'; +part 'stream_transformers.dart'; +part 'timer.dart'; +part 'zone.dart'; +wNN<)+?(% ?31?+:==+> 9B')??:. 7LJF3;%E53EP4>JJM3M6JK'OL:O H[95 ) !Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/future_impl.dartg// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +/** The onValue and onError handlers return either a value or a future */ +typedef FutureOr _FutureOnValue(S value); +/** Test used by [Future.catchError] to handle skip some errors. */ +typedef bool _FutureErrorTest(Object error); +/** Used by [WhenFuture]. */ +typedef dynamic _FutureAction(); + +abstract class _Completer implements Completer { + final _Future future = new _Future(); + + void complete([FutureOr value]); + + void completeError(Object error, [StackTrace stackTrace]) { + error = _nonNullError(error); + if (!future._mayComplete) throw new StateError("Future already completed"); + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + _completeError(error, stackTrace); + } + + void _completeError(Object error, StackTrace stackTrace); + + // The future's _isComplete doesn't take into account pending completions. + // We therefore use _mayComplete. + bool get isCompleted => !future._mayComplete; +} + +class _AsyncCompleter extends _Completer { + void complete([FutureOr value]) { + if (!future._mayComplete) throw new StateError("Future already completed"); + future._asyncComplete(value); + } + + void _completeError(Object error, StackTrace stackTrace) { + future._asyncCompleteError(error, stackTrace); + } +} + +class _SyncCompleter extends _Completer { + void complete([FutureOr value]) { + if (!future._mayComplete) throw new StateError("Future already completed"); + future._complete(value); + } + + void _completeError(Object error, StackTrace stackTrace) { + future._completeError(error, stackTrace); + } +} + +class _FutureListener { + static const int maskValue = 1; + static const int maskError = 2; + static const int maskTestError = 4; + static const int maskWhencomplete = 8; + static const int stateChain = 0; + static const int stateThen = maskValue; + static const int stateThenOnerror = maskValue | maskError; + static const int stateCatcherror = maskError; + static const int stateCatcherrorTest = maskError | maskTestError; + static const int stateWhencomplete = maskWhencomplete; + // Listeners on the same future are linked through this link. + _FutureListener _nextListener = null; + // The future to complete when this listener is activated. + final _Future result; + // Which fields means what. + final int state; + // Used for then/whenDone callback and error test + final Function callback; + // Used for error callbacks. + final Function errorCallback; + + _FutureListener.then( + this.result, _FutureOnValue onValue, Function errorCallback) + : callback = onValue, + errorCallback = errorCallback, + state = (errorCallback == null) ? stateThen : stateThenOnerror; + + _FutureListener.catchError( + this.result, this.errorCallback, _FutureErrorTest test) + : callback = test, + state = (test == null) ? stateCatcherror : stateCatcherrorTest; + + _FutureListener.whenComplete(this.result, _FutureAction onComplete) + : callback = onComplete, + errorCallback = null, + state = stateWhencomplete; + + Zone get _zone => result._zone; + + bool get handlesValue => (state & maskValue != 0); + bool get handlesError => (state & maskError != 0); + bool get hasErrorTest => (state == stateCatcherrorTest); + bool get handlesComplete => (state == stateWhencomplete); + + _FutureOnValue get _onValue { + assert(handlesValue); + return callback; + } + + Function get _onError => errorCallback; + _FutureErrorTest get _errorTest { + assert(hasErrorTest); + return callback; + } + + _FutureAction get _whenCompleteAction { + assert(handlesComplete); + return callback; + } + + /// Whether this listener has an error callback. + /// + /// This function must only be called if the listener [handlesError]. + bool get hasErrorCallback { + assert(handlesError); + return _onError != null; + } + + FutureOr handleValue(S sourceResult) { + return _zone.runUnary, S>(_onValue, sourceResult); + } + + bool matchesErrorTest(AsyncError asyncError) { + if (!hasErrorTest) return true; + return _zone.runUnary(_errorTest, asyncError.error); + } + + FutureOr handleError(AsyncError asyncError) { + assert(handlesError && hasErrorCallback); + var errorCallback = this.errorCallback; // To enable promotion. + // If the errorCallback returns something which is not a FutureOr, + // this return statement throws, and the caller handles the error. + if (errorCallback is dynamic Function(Object, StackTrace)) { + return _zone.runBinary( + errorCallback, asyncError.error, asyncError.stackTrace); + } else { + assert(errorCallback is dynamic Function(Object)); + return _zone.runUnary(errorCallback, asyncError.error); + } + } + + dynamic handleWhenComplete() { + assert(!handlesError); + return _zone.run(_whenCompleteAction); + } +} + +class _Future implements Future { + /// Initial state, waiting for a result. In this state, the + /// [resultOrListeners] field holds a single-linked list of + /// [_FutureListener] listeners. + static const int _stateIncomplete = 0; + + /// Pending completion. Set when completed using [_asyncComplete] or + /// [_asyncCompleteError]. It is an error to try to complete it again. + /// [resultOrListeners] holds listeners. + static const int _statePendingComplete = 1; + + /// The future has been chained to another future. The result of that + /// other future becomes the result of this future as well. + /// [resultOrListeners] contains the source future. + static const int _stateChained = 2; + + /// The future has been completed with a value result. + static const int _stateValue = 4; + + /// The future has been completed with an error result. + static const int _stateError = 8; + + /** Whether the future is complete, and as what. */ + int _state = _stateIncomplete; + + /** + * Zone that the future was completed from. + * This is the zone that an error result belongs to. + * + * Until the future is completed, the field may hold the zone that + * listener callbacks used to create this future should be run in. + */ + final Zone _zone; + + /** + * Either the result, a list of listeners or another future. + * + * The result of the future is either a value or an error. + * A result is only stored when the future has completed. + * + * The listeners is an internally linked list of [_FutureListener]s. + * Listeners are only remembered while the future is not yet complete, + * and it is not chained to another future. + * + * The future is another future that his future is chained to. This future + * is waiting for the other future to complete, and when it does, this future + * will complete with the same result. + * All listeners are forwarded to the other future. + */ + var _resultOrListeners; + + // This constructor is used by async/await. + _Future() : _zone = Zone.current; + + _Future.immediate(FutureOr result) : _zone = Zone.current { + _asyncComplete(result); + } + + /** Creates a future with the value and the specified zone. */ + _Future.zoneValue(T value, this._zone) { + _setValue(value); + } + + _Future.immediateError(var error, [StackTrace stackTrace]) + : _zone = Zone.current { + _asyncCompleteError(error, stackTrace); + } + + /** Creates a future that is already completed with the value. */ + _Future.value(T value) : this.zoneValue(value, Zone.current); + + bool get _mayComplete => _state == _stateIncomplete; + bool get _isPendingComplete => _state == _statePendingComplete; + bool get _mayAddListener => _state <= _statePendingComplete; + bool get _isChained => _state == _stateChained; + bool get _isComplete => _state >= _stateValue; + bool get _hasError => _state == _stateError; + + void _setChained(_Future source) { + assert(_mayAddListener); + _state = _stateChained; + _resultOrListeners = source; + } + + Future then(FutureOr f(T value), {Function onError}) { + Zone currentZone = Zone.current; + if (!identical(currentZone, _rootZone)) { + f = currentZone.registerUnaryCallback, T>(f); + if (onError != null) { + // In checked mode, this checks that onError is assignable to one of: + // dynamic Function(Object) + // dynamic Function(Object, StackTrace) + onError = _registerErrorHandler(onError, currentZone); + } + } + return _thenNoZoneRegistration(f, onError); + } + + // This method is used by async/await. + Future _thenNoZoneRegistration( + FutureOr f(T value), Function onError) { + _Future result = new _Future(); + _addListener(new _FutureListener.then(result, f, onError)); + return result; + } + + Future catchError(Function onError, {bool test(error)}) { + _Future result = new _Future(); + if (!identical(result._zone, _rootZone)) { + onError = _registerErrorHandler(onError, result._zone); + if (test != null) test = result._zone.registerUnaryCallback(test); + } + _addListener(new _FutureListener.catchError(result, onError, test)); + return result; + } + + Future whenComplete(dynamic action()) { + _Future result = new _Future(); + if (!identical(result._zone, _rootZone)) { + action = result._zone.registerCallback(action); + } + _addListener(new _FutureListener.whenComplete(result, action)); + return result; + } + + Stream asStream() => new Stream.fromFuture(this); + + void _setPendingComplete() { + assert(_mayComplete); + _state = _statePendingComplete; + } + + void _clearPendingComplete() { + assert(_isPendingComplete); + _state = _stateIncomplete; + } + + AsyncError get _error { + assert(_hasError); + return _resultOrListeners; + } + + _Future get _chainSource { + assert(_isChained); + return _resultOrListeners; + } + + // This method is used by async/await. + void _setValue(T value) { + assert(!_isComplete); // But may have a completion pending. + _state = _stateValue; + _resultOrListeners = value; + } + + void _setErrorObject(AsyncError error) { + assert(!_isComplete); // But may have a completion pending. + _state = _stateError; + _resultOrListeners = error; + } + + void _setError(Object error, StackTrace stackTrace) { + _setErrorObject(new AsyncError(error, stackTrace)); + } + + /// Copy the completion result of [source] into this future. + /// + /// Used when a chained future notices that its source is completed. + void _cloneResult(_Future source) { + assert(!_isComplete); + assert(source._isComplete); + _state = source._state; + _resultOrListeners = source._resultOrListeners; + } + + void _addListener(_FutureListener listener) { + assert(listener._nextListener == null); + if (_mayAddListener) { + listener._nextListener = _resultOrListeners; + _resultOrListeners = listener; + } else { + if (_isChained) { + // Delegate listeners to chained source future. + // If the source is complete, instead copy its values and + // drop the chaining. + _Future source = _chainSource; + if (!source._isComplete) { + source._addListener(listener); + return; + } + _cloneResult(source); + } + assert(_isComplete); + // Handle late listeners asynchronously. + _zone.scheduleMicrotask(() { + _propagateToListeners(this, listener); + }); + } + } + + void _prependListeners(_FutureListener listeners) { + if (listeners == null) return; + if (_mayAddListener) { + _FutureListener existingListeners = _resultOrListeners; + _resultOrListeners = listeners; + if (existingListeners != null) { + _FutureListener cursor = listeners; + while (cursor._nextListener != null) { + cursor = cursor._nextListener; + } + cursor._nextListener = existingListeners; + } + } else { + if (_isChained) { + // Delegate listeners to chained source future. + // If the source is complete, instead copy its values and + // drop the chaining. + _Future source = _chainSource; + if (!source._isComplete) { + source._prependListeners(listeners); + return; + } + _cloneResult(source); + } + assert(_isComplete); + listeners = _reverseListeners(listeners); + _zone.scheduleMicrotask(() { + _propagateToListeners(this, listeners); + }); + } + } + + _FutureListener _removeListeners() { + // Reverse listeners before returning them, so the resulting list is in + // subscription order. + assert(!_isComplete); + _FutureListener current = _resultOrListeners; + _resultOrListeners = null; + return _reverseListeners(current); + } + + _FutureListener _reverseListeners(_FutureListener listeners) { + _FutureListener prev = null; + _FutureListener current = listeners; + while (current != null) { + _FutureListener next = current._nextListener; + current._nextListener = prev; + prev = current; + current = next; + } + return prev; + } + + // Take the value (when completed) of source and complete target with that + // value (or error). This function could chain all Futures, but is slower + // for _Future than _chainCoreFuture, so you must use _chainCoreFuture + // in that case. + static void _chainForeignFuture(Future source, _Future target) { + assert(!target._isComplete); + assert(source is! _Future); + + // Mark the target as chained (and as such half-completed). + target._setPendingComplete(); + try { + source.then((value) { + assert(target._isPendingComplete); + // The "value" may be another future if the foreign future + // implementation is mis-behaving, + // so use _complete instead of _completeWithValue. + target._clearPendingComplete(); // Clear this first, it's set again. + target._complete(value); + }, + // TODO(floitsch): eventually we would like to make this non-optional + // and dependent on the listeners of the target future. If none of + // the target future's listeners want to have the stack trace we don't + // need a trace. + onError: (error, [stackTrace]) { + assert(target._isPendingComplete); + target._completeError(error, stackTrace); + }); + } catch (e, s) { + // This only happens if the `then` call threw synchronously when given + // valid arguments. + // That requires a non-conforming implementation of the Future interface, + // which should, hopefully, never happen. + scheduleMicrotask(() { + target._completeError(e, s); + }); + } + } + + // Take the value (when completed) of source and complete target with that + // value (or error). This function expects that source is a _Future. + static void _chainCoreFuture(_Future source, _Future target) { + assert(target._mayAddListener); // Not completed, not already chained. + while (source._isChained) { + source = source._chainSource; + } + if (source._isComplete) { + _FutureListener listeners = target._removeListeners(); + target._cloneResult(source); + _propagateToListeners(target, listeners); + } else { + _FutureListener listeners = target._resultOrListeners; + target._setChained(source); + source._prependListeners(listeners); + } + } + + void _complete(FutureOr value) { + assert(!_isComplete); + if (value is Future) { + if (value is _Future) { + _chainCoreFuture(value, this); + } else { + _chainForeignFuture(value, this); + } + } else { + _FutureListener listeners = _removeListeners(); + _setValue(value); + _propagateToListeners(this, listeners); + } + } + + void _completeWithValue(T value) { + assert(!_isComplete); + assert(value is! Future); + + _FutureListener listeners = _removeListeners(); + _setValue(value); + _propagateToListeners(this, listeners); + } + + void _completeError(Object error, [StackTrace stackTrace]) { + assert(!_isComplete); + + _FutureListener listeners = _removeListeners(); + _setError(error, stackTrace); + _propagateToListeners(this, listeners); + } + + void _asyncComplete(FutureOr value) { + assert(!_isComplete); + // Two corner cases if the value is a future: + // 1. the future is already completed and an error. + // 2. the future is not yet completed but might become an error. + // The first case means that we must not immediately complete the Future, + // as our code would immediately start propagating the error without + // giving the time to install error-handlers. + // However the second case requires us to deal with the value immediately. + // Otherwise the value could complete with an error and report an + // unhandled error, even though we know we are already going to listen to + // it. + + if (value is Future) { + _chainFuture(value); + return; + } + _setPendingComplete(); + _zone.scheduleMicrotask(() { + _completeWithValue(value); + }); + } + + void _chainFuture(Future value) { + if (value is _Future) { + if (value._hasError) { + // Delay completion to allow the user to register callbacks. + _setPendingComplete(); + _zone.scheduleMicrotask(() { + _chainCoreFuture(value, this); + }); + } else { + _chainCoreFuture(value, this); + } + return; + } + // Just listen on the foreign future. This guarantees an async delay. + _chainForeignFuture(value, this); + } + + void _asyncCompleteError(error, StackTrace stackTrace) { + assert(!_isComplete); + + _setPendingComplete(); + _zone.scheduleMicrotask(() { + _completeError(error, stackTrace); + }); + } + + /** + * Propagates the value/error of [source] to its [listeners], executing the + * listeners' callbacks. + */ + static void _propagateToListeners(_Future source, _FutureListener listeners) { + while (true) { + assert(source._isComplete); + bool hasError = source._hasError; + if (listeners == null) { + if (hasError) { + AsyncError asyncError = source._error; + source._zone + .handleUncaughtError(asyncError.error, asyncError.stackTrace); + } + return; + } + // Usually futures only have one listener. If they have several, we + // call handle them separately in recursive calls, continuing + // here only when there is only one listener left. + while (listeners._nextListener != null) { + _FutureListener listener = listeners; + listeners = listener._nextListener; + listener._nextListener = null; + _propagateToListeners(source, listener); + } + _FutureListener listener = listeners; + final sourceResult = source._resultOrListeners; + // Do the actual propagation. + // Set initial state of listenerHasError and listenerValueOrError. These + // variables are updated with the outcome of potential callbacks. + // Non-error results, including futures, are stored in + // listenerValueOrError and listenerHasError is set to false. Errors + // are stored in listenerValueOrError as an [AsyncError] and + // listenerHasError is set to true. + bool listenerHasError = hasError; + var listenerValueOrError = sourceResult; + + // Only if we either have an error or callbacks, go into this, somewhat + // expensive, branch. Here we'll enter/leave the zone. Many futures + // don't have callbacks, so this is a significant optimization. + if (hasError || listener.handlesValue || listener.handlesComplete) { + Zone zone = listener._zone; + if (hasError && !source._zone.inSameErrorZone(zone)) { + // Don't cross zone boundaries with errors. + AsyncError asyncError = source._error; + source._zone + .handleUncaughtError(asyncError.error, asyncError.stackTrace); + return; + } + + Zone oldZone; + if (!identical(Zone.current, zone)) { + // Change zone if it's not current. + oldZone = Zone._enter(zone); + } + + // These callbacks are abstracted to isolate the try/catch blocks + // from the rest of the code to work around a V8 glass jaw. + void handleWhenCompleteCallback() { + // The whenComplete-handler is not combined with normal value/error + // handling. This means at most one handleX method is called per + // listener. + assert(!listener.handlesValue); + assert(!listener.handlesError); + var completeResult; + try { + completeResult = listener.handleWhenComplete(); + } catch (e, s) { + if (hasError && identical(source._error.error, e)) { + listenerValueOrError = source._error; + } else { + listenerValueOrError = new AsyncError(e, s); + } + listenerHasError = true; + return; + } + if (completeResult is Future) { + if (completeResult is _Future && completeResult._isComplete) { + if (completeResult._hasError) { + listenerValueOrError = completeResult._error; + listenerHasError = true; + } + // Otherwise use the existing result of source. + return; + } + // We have to wait for the completeResult future to complete + // before knowing if it's an error or we should use the result + // of source. + var originalSource = source; + listenerValueOrError = completeResult.then((_) => originalSource); + listenerHasError = false; + } + } + + void handleValueCallback() { + try { + listenerValueOrError = listener.handleValue(sourceResult); + } catch (e, s) { + listenerValueOrError = new AsyncError(e, s); + listenerHasError = true; + } + } + + void handleError() { + try { + AsyncError asyncError = source._error; + if (listener.matchesErrorTest(asyncError) && + listener.hasErrorCallback) { + listenerValueOrError = listener.handleError(asyncError); + listenerHasError = false; + } + } catch (e, s) { + if (identical(source._error.error, e)) { + listenerValueOrError = source._error; + } else { + listenerValueOrError = new AsyncError(e, s); + } + listenerHasError = true; + } + } + + if (listener.handlesComplete) { + handleWhenCompleteCallback(); + } else if (!hasError) { + if (listener.handlesValue) { + handleValueCallback(); + } + } else { + if (listener.handlesError) { + handleError(); + } + } + + // If we changed zone, oldZone will not be null. + if (oldZone != null) Zone._leave(oldZone); + + // If the listener's value is a future we need to chain it. Note that + // this can only happen if there is a callback. + if (listenerValueOrError is Future) { + Future chainSource = listenerValueOrError; + // Shortcut if the chain-source is already completed. Just continue + // the loop. + _Future result = listener.result; + if (chainSource is _Future) { + if (chainSource._isComplete) { + listeners = result._removeListeners(); + result._cloneResult(chainSource); + source = chainSource; + continue; + } else { + _chainCoreFuture(chainSource, result); + } + } else { + _chainForeignFuture(chainSource, result); + } + return; + } + } + _Future result = listener.result; + listeners = result._removeListeners(); + if (!listenerHasError) { + result._setValue(listenerValueOrError); + } else { + AsyncError asyncError = listenerValueOrError; + result._setErrorObject(asyncError); + } + // Prepare for next round. + source = result; + } + } + + Future timeout(Duration timeLimit, {FutureOr onTimeout()}) { + if (_isComplete) return new _Future.immediate(this); + _Future result = new _Future(); + Timer timer; + if (onTimeout == null) { + timer = new Timer(timeLimit, () { + result._completeError( + new TimeoutException("Future not completed", timeLimit)); + }); + } else { + Zone zone = Zone.current; + onTimeout = zone.registerCallback(onTimeout); + timer = new Timer(timeLimit, () { + try { + result._complete(zone.run(onTimeout)); + } catch (e, s) { + result._completeError(e, s); + } + }); + } + this.then((T v) { + if (timer.isActive) { + timer.cancel(); + result._completeWithValue(v); + } + }, onError: (e, s) { + if (timer.isActive) { + timer.cancel(); + result._completeError(e, s); + } + }); + return result; + } +} + +/// Registers errorHandler in zone if it has the correct type. +/// +/// Checks that the function accepts either an [Object] and a [StackTrace] +/// or just one [Object]. Does not check the return type. +/// The actually returned value must be `FutureOr` where `R` is the +/// value type of the future that the call will complete (either returned +/// by [Future.then] or [Future.catchError]). We check the returned value +/// dynamically because the functions are passed as arguments in positions +/// without inference, so a function expression won't infer the return type. +/// +/// Throws if the type is not valid. +Function _registerErrorHandler(Function errorHandler, Zone zone) { + if (errorHandler is dynamic Function(Object, StackTrace)) { + return zone + .registerBinaryCallback(errorHandler); + } + if (errorHandler is dynamic Function(Object)) { + return zone.registerUnaryCallback(errorHandler); + } + throw new ArgumentError.value( + errorHandler, + "onError", + "Error handler must accept one Object or one Object and a StackTrace" + " as arguments, and return a a valid result"); +} + +NN<J3D-!7.&>"PL0+'<M$01'P"=30'P=.""&)#*=0D9@(=4 I'H>HF#"55;<&*$*3H,C1$G3.DJGA;C 9O!+(>>#)GI+.H>6&9$:$6!.7EE?=<GI.MP)6.$AA+=,D@7B?21/%!B%.@N&2?3)(2*F?*/>IO-*/?J:$! )@ +@ 88?G& 40,3% 8B'#) +/#/ +6#>&',/) +2 8B'#/ +0#0 +'L2'A!)4$MLIC! @" ++C+;M! PMQ++2 +MP0% +MGAK $=#0 ="+&!'* 6.%!4,?4",+2:GNI2OFN !!'E%) 'J&;!)NQ"(1M +JD90.,'1,6$OH=KC*(/NJFK$?61M +..' +JD,NK**<A4;% *K.>)>IK)O& +%G9% +39-G(54;% +(( '# ' +93N8.5N,(+50$56  +(-06,!E9*(F + 4(1' + +&%?K:GJJKM%C>L2F!L5Yfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/schedule_microtask.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +typedef void _AsyncCallback(); + +class _AsyncCallbackEntry { + final _AsyncCallback callback; + _AsyncCallbackEntry next; + _AsyncCallbackEntry(this.callback); +} + +/** Head of single linked list of pending callbacks. */ +_AsyncCallbackEntry _nextCallback; +/** Tail of single linked list of pending callbacks. */ +_AsyncCallbackEntry _lastCallback; +/** + * Tail of priority callbacks added by the currently executing callback. + * + * Priority callbacks are put at the beginning of the + * callback queue, so that if one callback schedules more than one + * priority callback, they are still enqueued in scheduling order. + */ +_AsyncCallbackEntry _lastPriorityCallback; +/** + * Whether we are currently inside the callback loop. + * + * If we are inside the loop, we never need to schedule the loop, + * even if adding a first element. + */ +bool _isInCallbackLoop = false; + +void _microtaskLoop() { + while (_nextCallback != null) { + _lastPriorityCallback = null; + _AsyncCallbackEntry entry = _nextCallback; + _nextCallback = entry.next; + if (_nextCallback == null) _lastCallback = null; + (entry.callback)(); + } +} + +void _startMicrotaskLoop() { + _isInCallbackLoop = true; + try { + // Moved to separate function because try-finally prevents + // good optimization. + _microtaskLoop(); + } finally { + _lastPriorityCallback = null; + _isInCallbackLoop = false; + if (_nextCallback != null) { + _AsyncRun._scheduleImmediate(_startMicrotaskLoop); + } + } +} + +/** + * Schedules a callback to be called as a microtask. + * + * The microtask is called after all other currently scheduled + * microtasks, but as part of the current system event. + */ +void _scheduleAsyncCallback(_AsyncCallback callback) { + _AsyncCallbackEntry newEntry = new _AsyncCallbackEntry(callback); + if (_nextCallback == null) { + _nextCallback = _lastCallback = newEntry; + if (!_isInCallbackLoop) { + _AsyncRun._scheduleImmediate(_startMicrotaskLoop); + } + } else { + _lastCallback.next = newEntry; + _lastCallback = newEntry; + } +} + +/** + * Schedules a callback to be called before all other currently scheduled ones. + * + * This callback takes priority over existing scheduled callbacks. + * It is only used internally to give higher priority to error reporting. + * + * Is always run in the root zone. + */ +void _schedulePriorityAsyncCallback(_AsyncCallback callback) { + if (_nextCallback == null) { + _scheduleAsyncCallback(callback); + _lastPriorityCallback = _lastCallback; + return; + } + _AsyncCallbackEntry entry = new _AsyncCallbackEntry(callback); + if (_lastPriorityCallback == null) { + entry.next = _nextCallback; + _nextCallback = _lastPriorityCallback = entry; + } else { + entry.next = _lastPriorityCallback.next; + _lastPriorityCallback.next = entry; + _lastPriorityCallback = entry; + if (entry.next == null) { + _lastCallback = entry; + } + } +} + +/** + * Runs a function asynchronously. + * + * Callbacks registered through this function are always executed in order and + * are guaranteed to run before other asynchronous events (like [Timer] events, + * or DOM events). + * + * **Warning:** it is possible to starve the DOM by registering asynchronous + * callbacks through this method. For example the following program runs + * the callbacks without ever giving the Timer callback a chance to execute: + * + * main() { + * Timer.run(() { print("executed"); }); // Will never be executed. + * foo() { + * scheduleMicrotask(foo); // Schedules [foo] in front of other events. + * } + * foo(); + * } + * + * ## Other resources + * + * * [The Event Loop and Dart](https://www.dartlang.org/articles/event-loop/): + * Learn how Dart handles the event queue and microtask queue, so you can write + * better asynchronous code with fewer surprises. + */ +void scheduleMicrotask(void callback()) { + _Zone currentZone = Zone.current; + if (identical(_rootZone, currentZone)) { + // No need to bind the callback. We know that the root's scheduleMicrotask + // will be invoked in the root zone. + _rootScheduleMicrotask(null, null, _rootZone, callback); + return; + } + _ZoneFunction implementation = currentZone._scheduleMicrotask; + if (identical(_rootZone, implementation.zone) && + _rootZone.inSameErrorZone(currentZone)) { + _rootScheduleMicrotask( + null, null, currentZone, currentZone.registerCallback(callback)); + return; + } + Zone.current.scheduleMicrotask(Zone.current.bindCallbackGuarded(callback)); +} + +class _AsyncRun { + /** Schedule the given callback before any other event in the event-loop. */ + external static void _scheduleImmediate(void callback()); +} +NN<!&8#8#I6CC+6B# ""/ 5?"!95?87D.9 #PCJ#?&+ A' 3 -(##OPMIMKQ  OP2*$+O)= A30J NO<Mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/stream.dart(// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +// ------------------------------------------------------------------- +// Core Stream types +// ------------------------------------------------------------------- + +typedef void _TimerCallback(); + +/** + * A source of asynchronous data events. + * + * A Stream provides a way to receive a sequence of events. + * Each event is either a data event, also called an *element* of the stream, + * or an error event, which is a notification that something has failed. + * When a stream has emitted all its event, + * a single "done" event will notify the listener that the end has been reached. + * + * You [listen] on a stream to make it start generating events, + * and to set up listeners that receive the events. + * When you listen, you receive a [StreamSubscription] object + * which is the active object providing the events, + * and which can be used to stop listening again, + * or to temporarily pause events from the subscription. + * + * There are two kinds of streams: "Single-subscription" streams and + * "broadcast" streams. + * + * *A single-subscription stream* allows only a single listener during the whole + * lifetime of the stream. + * It doesn't start generating events until it has a listener, + * and it stops sending events when the listener is unsubscribed, + * even if the source of events could still provide more. + * + * Listening twice on a single-subscription stream is not allowed, even after + * the first subscription has been canceled. + * + * Single-subscription streams are generally used for streaming chunks of + * larger contiguous data like file I/O. + * + * *A broadcast stream* allows any number of listeners, and it fires + * its events when they are ready, whether there are listeners or not. + * + * Broadcast streams are used for independent events/observers. + * + * If several listeners want to listen to a single subscription stream, + * use [asBroadcastStream] to create a broadcast stream on top of the + * non-broadcast stream. + * + * On either kind of stream, stream transformations, such as [where] and + * [skip], return the same type of stream as the one the method was called on, + * unless otherwise noted. + * + * When an event is fired, the listener(s) at that time will receive the event. + * If a listener is added to a broadcast stream while an event is being fired, + * that listener will not receive the event currently being fired. + * If a listener is canceled, it immediately stops receiving events. + * + * When the "done" event is fired, subscribers are unsubscribed before + * receiving the event. After the event has been sent, the stream has no + * subscribers. Adding new subscribers to a broadcast stream after this point + * is allowed, but they will just receive a new "done" event as soon + * as possible. + * + * Stream subscriptions always respect "pause" requests. If necessary they need + * to buffer their input, but often, and preferably, they can simply request + * their input to pause too. + * + * The default implementation of [isBroadcast] returns false. + * A broadcast stream inheriting from [Stream] must override [isBroadcast] + * to return `true`. + */ +abstract class Stream { + Stream(); + + /** + * Internal use only. We do not want to promise that Stream stays const. + * + * If mixins become compatible with const constructors, we may use a + * stream mixin instead of extending Stream from a const class. + */ + const Stream._internal(); + + /** + * Creates an empty broadcast stream. + * + * This is a stream which does nothing except sending a done event + * when it's listened to. + */ + const factory Stream.empty() = _EmptyStream; + + /** + * Creates a new single-subscription stream from the future. + * + * When the future completes, the stream will fire one event, either + * data or error, and then close with a done-event. + */ + factory Stream.fromFuture(Future future) { + // Use the controller's buffering to fill in the value even before + // the stream has a listener. For a single value, it's not worth it + // to wait for a listener before doing the `then` on the future. + _StreamController controller = new StreamController(sync: true); + future.then((value) { + controller._add(value); + controller._closeUnchecked(); + }, onError: (error, stackTrace) { + controller._addError(error, stackTrace); + controller._closeUnchecked(); + }); + return controller.stream; + } + + /** + * Create a stream from a group of futures. + * + * The stream reports the results of the futures on the stream in the order + * in which the futures complete. + * Each future provides either a data event or an error event, + * depending on how the future completes. + * + * If some futures have already completed when `Stream.fromFutures` is called, + * their results will be emitted in some unspecified order. + * + * When all futures have completed, the stream is closed. + * + * If [futures] is empty, the stream closes as soon as possible. + */ + factory Stream.fromFutures(Iterable> futures) { + _StreamController controller = new StreamController(sync: true); + int count = 0; + // Declare these as variables holding closures instead of as + // function declarations. + // This avoids creating a new closure from the functions for each future. + var onValue = (T value) { + if (!controller.isClosed) { + controller._add(value); + if (--count == 0) controller._closeUnchecked(); + } + }; + var onError = (error, stack) { + if (!controller.isClosed) { + controller._addError(error, stack); + if (--count == 0) controller._closeUnchecked(); + } + }; + // The futures are already running, so start listening to them immediately + // (instead of waiting for the stream to be listened on). + // If we wait, we might not catch errors in the futures in time. + for (var future in futures) { + count++; + future.then(onValue, onError: onError); + } + // Use schedule microtask since controller is sync. + if (count == 0) scheduleMicrotask(controller.close); + return controller.stream; + } + + /** + * Creates a single-subscription stream that gets its data from [data]. + * + * The iterable is iterated when the stream receives a listener, and stops + * iterating if the listener cancels the subscription. + * + * If iterating [data] throws an error, the stream ends immediately with + * that error. No done event will be sent (iteration is not complete), but no + * further data events will be generated either, since iteration cannot + * continue. + */ + factory Stream.fromIterable(Iterable data) { + return new _GeneratedStreamImpl( + () => new _IterablePendingEvents(data)); + } + + /** + * Creates a stream that repeatedly emits events at [period] intervals. + * + * The event values are computed by invoking [computation]. The argument to + * this callback is an integer that starts with 0 and is incremented for + * every event. + * + * If [computation] is omitted the event values will all be `null`. + */ + factory Stream.periodic(Duration period, + [T computation(int computationCount)]) { + Timer timer; + int computationCount = 0; + StreamController controller; + // Counts the time that the Stream was running (and not paused). + Stopwatch watch = new Stopwatch(); + + void sendEvent() { + watch.reset(); + T data; + if (computation != null) { + try { + data = computation(computationCount++); + } catch (e, s) { + controller.addError(e, s); + return; + } + } + controller.add(data); + } + + void startPeriodicTimer() { + assert(timer == null); + timer = new Timer.periodic(period, (Timer timer) { + sendEvent(); + }); + } + + controller = new StreamController( + sync: true, + onListen: () { + watch.start(); + startPeriodicTimer(); + }, + onPause: () { + timer.cancel(); + timer = null; + watch.stop(); + }, + onResume: () { + assert(timer == null); + Duration elapsed = watch.elapsed; + watch.start(); + timer = new Timer(period - elapsed, () { + timer = null; + startPeriodicTimer(); + sendEvent(); + }); + }, + onCancel: () { + if (timer != null) timer.cancel(); + timer = null; + return Future._nullFuture; + }); + return controller.stream; + } + + /** + * Creates a stream where all events of an existing stream are piped through + * a sink-transformation. + * + * The given [mapSink] closure is invoked when the returned stream is + * listened to. All events from the [source] are added into the event sink + * that is returned from the invocation. The transformation puts all + * transformed events into the sink the [mapSink] closure received during + * its invocation. Conceptually the [mapSink] creates a transformation pipe + * with the input sink being the returned [EventSink] and the output sink + * being the sink it received. + * + * This constructor is frequently used to build transformers. + * + * Example use for a duplicating transformer: + * + * class DuplicationSink implements EventSink { + * final EventSink _outputSink; + * DuplicationSink(this._outputSink); + * + * void add(String data) { + * _outputSink.add(data); + * _outputSink.add(data); + * } + * + * void addError(e, [st]) { _outputSink.addError(e, st); } + * void close() { _outputSink.close(); } + * } + * + * class DuplicationTransformer extends StreamTransformerBase { + * // Some generic types omitted for brevity. + * Stream bind(Stream stream) => new Stream.eventTransformed( + * stream, + * (EventSink sink) => new DuplicationSink(sink)); + * } + * + * stringStream.transform(new DuplicationTransformer()); + * + * The resulting stream is a broadcast stream if [source] is. + */ + factory Stream.eventTransformed( + Stream source, EventSink mapSink(EventSink sink)) { + return new _BoundSinkStream(source, mapSink); + } + + /** + * Adapts [source] to be a `Stream`. + * + * This allows [source] to be used at the new type, but at run-time it + * must satisfy the requirements of both the new type and its original type. + * + * Data events created by the source stream must also be instances of [T]. + */ + static Stream castFrom(Stream source) => + new CastStream(source); + + /** + * Whether this stream is a broadcast stream. + */ + bool get isBroadcast => false; + + /** + * Returns a multi-subscription stream that produces the same events as this. + * + * The returned stream will subscribe to this stream when its first + * subscriber is added, and will stay subscribed until this stream ends, + * or a callback cancels the subscription. + * + * If [onListen] is provided, it is called with a subscription-like object + * that represents the underlying subscription to this stream. It is + * possible to pause, resume or cancel the subscription during the call + * to [onListen]. It is not possible to change the event handlers, including + * using [StreamSubscription.asFuture]. + * + * If [onCancel] is provided, it is called in a similar way to [onListen] + * when the returned stream stops having listener. If it later gets + * a new listener, the [onListen] function is called again. + * + * Use the callbacks, for example, for pausing the underlying subscription + * while having no subscribers to prevent losing events, or canceling the + * subscription when there are no listeners. + */ + Stream asBroadcastStream( + {void onListen(StreamSubscription subscription), + void onCancel(StreamSubscription subscription)}) { + return new _AsBroadcastStream(this, onListen, onCancel); + } + + /** + * Adds a subscription to this stream. + * + * Returns a [StreamSubscription] which handles events from the stream using + * the provided [onData], [onError] and [onDone] handlers. + * The handlers can be changed on the subscription, but they start out + * as the provided functions. + * + * On each data event from this stream, the subscriber's [onData] handler + * is called. If [onData] is `null`, nothing happens. + * + * On errors from this stream, the [onError] handler is called with the + * error object and possibly a stack trace. + * + * The [onError] callback must be of type `void onError(error)` or + * `void onError(error, StackTrace stackTrace)`. If [onError] accepts + * two arguments it is called with the error object and the stack trace + * (which could be `null` if the stream itself received an error without + * stack trace). + * Otherwise it is called with just the error object. + * If [onError] is omitted, any errors on the stream are considered unhandled, + * and will be passed to the current [Zone]'s error handler. + * By default unhandled async errors are treated + * as if they were uncaught top-level errors. + * + * If this stream closes and sends a done event, the [onDone] handler is + * called. If [onDone] is `null`, nothing happens. + * + * If [cancelOnError] is true, the subscription is automatically canceled + * when the first error event is delivered. The default is `false`. + * + * While a subscription is paused, or when it has been canceled, + * the subscription doesn't receive events and none of the + * event handler functions are called. + */ + StreamSubscription listen(void onData(T event), + {Function onError, void onDone(), bool cancelOnError}); + + /** + * Creates a new stream from this stream that discards some elements. + * + * The new stream sends the same error and done events as this stream, + * but it only sends the data events that satisfy the [test]. + * + * If the [test] function throws, the data event is dropped and the + * error is emitted on the returned stream instead. + * + * The returned stream is a broadcast stream if this stream is. + * If a broadcast stream is listened to more than once, each subscription + * will individually perform the `test`. + */ + Stream where(bool test(T event)) { + return new _WhereStream(this, test); + } + + /** + * Transforms each element of this stream into a new stream event. + * + * Creates a new stream that converts each element of this stream + * to a new value using the [convert] function, and emits the result. + * + * For each data event, `o`, in this stream, the returned stream + * provides a data event with the value `convert(o)`. + * If [convert] throws, the returned stream reports it as an error + * event instead. + * + * Error and done events are passed through unchanged to the returned stream. + * + * The returned stream is a broadcast stream if this stream is. + * The [convert] function is called once per data event per listener. + * If a broadcast stream is listened to more than once, each subscription + * will individually call [convert] on each data event. + */ + Stream map(S convert(T event)) { + return new _MapStream(this, convert); + } + + /** + * Creates a new stream with each data event of this stream asynchronously + * mapped to a new event. + * + * This acts like [map], except that [convert] may return a [Future], + * and in that case, the stream waits for that future to complete before + * continuing with its result. + * + * The returned stream is a broadcast stream if this stream is. + */ + Stream asyncMap(FutureOr convert(T event)) { + StreamController controller; + StreamSubscription subscription; + + void onListen() { + final add = controller.add; + assert(controller is _StreamController || + controller is _BroadcastStreamController); + final _EventSink eventSink = controller as Object; + final addError = eventSink._addError; + subscription = this.listen((T event) { + FutureOr newValue; + try { + newValue = convert(event); + } catch (e, s) { + controller.addError(e, s); + return; + } + if (newValue is Future) { + subscription.pause(); + newValue + .then(add, onError: addError) + .whenComplete(subscription.resume); + } else { + controller.add(newValue); + } + }, onError: addError, onDone: controller.close); + } + + if (this.isBroadcast) { + controller = new StreamController.broadcast( + onListen: onListen, + onCancel: () { + subscription.cancel(); + }, + sync: true); + } else { + controller = new StreamController( + onListen: onListen, + onPause: () { + subscription.pause(); + }, + onResume: () { + subscription.resume(); + }, + onCancel: () => subscription.cancel(), + sync: true); + } + return controller.stream; + } + + /** + * Transforms each element into a sequence of asynchronous events. + * + * Returns a new stream and for each event of this stream, do the following: + * + * * If the event is an error event or a done event, it is emitted directly + * by the returned stream. + * * Otherwise it is an element. Then the [convert] function is called + * with the element as argument to produce a convert-stream for the element. + * * If that call throws, the error is emitted on the returned stream. + * * If the call returns `null`, no further action is taken for the elements. + * * Otherwise, this stream is paused and convert-stream is listened to. + * Every data and error event of the convert-stream is emitted on the returned + * stream in the order it is produced. + * When the convert-stream ends, this stream is resumed. + * + * The returned stream is a broadcast stream if this stream is. + */ + Stream asyncExpand(Stream convert(T event)) { + StreamController controller; + StreamSubscription subscription; + void onListen() { + assert(controller is _StreamController || + controller is _BroadcastStreamController); + final _EventSink eventSink = controller as Object; + subscription = this.listen((T event) { + Stream newStream; + try { + newStream = convert(event); + } catch (e, s) { + controller.addError(e, s); + return; + } + if (newStream != null) { + subscription.pause(); + controller.addStream(newStream).whenComplete(subscription.resume); + } + }, + onError: eventSink._addError, // Avoid Zone error replacement. + onDone: controller.close); + } + + if (this.isBroadcast) { + controller = new StreamController.broadcast( + onListen: onListen, + onCancel: () { + subscription.cancel(); + }, + sync: true); + } else { + controller = new StreamController( + onListen: onListen, + onPause: () { + subscription.pause(); + }, + onResume: () { + subscription.resume(); + }, + onCancel: () => subscription.cancel(), + sync: true); + } + return controller.stream; + } + + /** + * Creates a wrapper Stream that intercepts some errors from this stream. + * + * If this stream sends an error that matches [test], then it is intercepted + * by the [onError] function. + * + * The [onError] callback must be of type `void onError(error)` or + * `void onError(error, StackTrace stackTrace)`. Depending on the function + * type the stream either invokes [onError] with or without a stack + * trace. The stack trace argument might be `null` if the stream itself + * received an error without stack trace. + * + * An asynchronous error `error` is matched by a test function if + *`test(error)` returns true. If [test] is omitted, every error is considered + * matching. + * + * If the error is intercepted, the [onError] function can decide what to do + * with it. It can throw if it wants to raise a new (or the same) error, + * or simply return to make the stream forget the error. + * If the received `error` value is thrown again by the [onError] function, + * it acts like a `rethrow` and it is emitted along with its original + * stack trace, not the stack trace of the `throw` inside [onError]. + * + * If you need to transform an error into a data event, use the more generic + * [Stream.transform] to handle the event by writing a data event to + * the output sink. + * + * The returned stream is a broadcast stream if this stream is. + * If a broadcast stream is listened to more than once, each subscription + * will individually perform the `test` and handle the error. + */ + Stream handleError(Function onError, {bool test(error)}) { + return new _HandleErrorStream(this, onError, test); + } + + /** + * Transforms each element of this stream into a sequence of elements. + * + * Returns a new stream where each element of this stream is replaced + * by zero or more data events. + * The event values are provided as an [Iterable] by a call to [convert] + * with the element as argument, and the elements of that iterable is + * emitted in iteration order. + * If calling [convert] throws, or if the iteration of the returned values + * throws, the error is emitted on the returned stream and iteration ends + * for that element of this stream. + * + * Error events and the done event of this stream are forwarded directly + * to the returned stream. + * + * The returned stream is a broadcast stream if this stream is. + * If a broadcast stream is listened to more than once, each subscription + * will individually call `convert` and expand the events. + */ + Stream expand(Iterable convert(T element)) { + return new _ExpandStream(this, convert); + } + + /** + * Pipes the events of this stream into [streamConsumer]. + * + * All events of this stream are added to `streamConsumer` using + * [StreamConsumer.addStream]. + * The `streamConsumer` is closed when this stream has been successfully added + * to it - when the future returned by `addStream` completes without an error. + * + * Returns a future which completes when the stream has been consumed + * and the consumer has been closed. + * + * The returned future completes with the same result as the future returned + * by [StreamConsumer.close]. + * If the call to [StreamConsumer.addStream] fails in some way, this + * method fails in the same way. + */ + Future pipe(StreamConsumer streamConsumer) { + return streamConsumer.addStream(this).then((_) => streamConsumer.close()); + } + + /** + * Applies a [StreamTransformer] to the current stream. + * + * Returns the result of the stream transformation, + * that is, the result of `streamTransformer.bind(this)`. + * This method simply allows writing the call to `streamTransformer.bind` + * in a chained fashion, like + * ``` + * stream.map(mapping).transform(transformation).toList() + * ``` + * which can be more convenient than calling `bind` directly. + * + * The [streamTransformer] can return any stream. + * Whether the returned stream is a broadcast stream or not, + * and which elements it will contain, + * is entirely up to the transformation. + */ + Stream transform(StreamTransformer streamTransformer) { + return streamTransformer.bind(this); + } + + /** + * Combines a sequence of values by repeatedly applying [combine]. + * + * Similar to [Iterable.reduce], this function maintains a value, + * starting with the first element of the stream + * and updated for each further element of this stream. + * For each element after the first, + * the value is updated to the result of calling [combine] + * with the previous value and the element. + * + * When this stream is done, the returned future is completed with + * the value at that time. + * + * If the stream is empty, the returned future is completed with + * an error. + * If this stream emits an error, or the call to [combine] throws, + * the returned future is completed with that error, + * and processing is stopped. + */ + Future reduce(T combine(T previous, T element)) { + _Future result = new _Future(); + bool seenFirst = false; + T value; + StreamSubscription subscription; + subscription = this.listen( + (T element) { + if (seenFirst) { + _runUserCode(() => combine(value, element), (T newValue) { + value = newValue; + }, _cancelAndErrorClosure(subscription, result)); + } else { + value = element; + seenFirst = true; + } + }, + onError: result._completeError, + onDone: () { + if (!seenFirst) { + try { + // Throw and recatch, instead of just doing + // _completeWithErrorCallback, e, theError, StackTrace.current), + // to ensure that the stackTrace is set on the error. + throw IterableElementError.noElement(); + } catch (e, s) { + _completeWithErrorCallback(result, e, s); + } + } else { + result._complete(value); + } + }, + cancelOnError: true); + return result; + } + + /** + * Combines a sequence of values by repeatedly applying [combine]. + * + * Similar to [Iterable.fold], this function maintains a value, + * starting with [initialValue] and updated for each element of + * this stream. + * For each element, the value is updated to the result of calling + * [combine] with the previous value and the element. + * + * When this stream is done, the returned future is completed with + * the value at that time. + * For an empty stream, the future is completed with [initialValue]. + * + * If this stream emits an error, or the call to [combine] throws, + * the returned future is completed with that error, + * and processing is stopped. + */ + Future fold(S initialValue, S combine(S previous, T element)) { + _Future result = new _Future(); + S value = initialValue; + StreamSubscription subscription; + subscription = this.listen( + (T element) { + _runUserCode(() => combine(value, element), (S newValue) { + value = newValue; + }, _cancelAndErrorClosure(subscription, result)); + }, + onError: result._completeError, + onDone: () { + result._complete(value); + }, + cancelOnError: true); + return result; + } + + /** + * Combines the string representation of elements into a single string. + * + * Each element is converted to a string using its [Object.toString] method. + * If [separator] is provided, it is inserted between element string + * representations. + * + * The returned future is completed with the combined string when the stream + * is done. + * + * If the stream contains an error, or if the call to [Object.toString] + * throws, the returned future is completed with that error, + * and processing stops. + */ + Future join([String separator = ""]) { + _Future result = new _Future(); + StringBuffer buffer = new StringBuffer(); + StreamSubscription subscription; + bool first = true; + subscription = this.listen((T element) { + if (!first) { + buffer.write(separator); + } + first = false; + try { + buffer.write(element); + } catch (e, s) { + _cancelAndErrorWithReplacement(subscription, result, e, s); + } + }, onError: (e) { + result._completeError(e); + }, onDone: () { + result._complete(buffer.toString()); + }, cancelOnError: true); + return result; + } + + /** + * Returns whether [needle] occurs in the elements provided by this stream. + * + * Compares each element of this stream to [needle] using [Object.==]. + * If an equal element is found, the returned future is completed with `true`. + * If the stream ends without finding a match, the future is completed with + * `false`. + * + * If the stream contains an error, or the call to `Object.==` throws, + * the returned future is completed with that error, and processing stops. + */ + Future contains(Object needle) { + _Future future = new _Future(); + StreamSubscription subscription; + subscription = this.listen( + (T element) { + _runUserCode(() => (element == needle), (bool isMatch) { + if (isMatch) { + _cancelAndValue(subscription, future, true); + } + }, _cancelAndErrorClosure(subscription, future)); + }, + onError: future._completeError, + onDone: () { + future._complete(false); + }, + cancelOnError: true); + return future; + } + + /** + * Executes [action] on each element of the stream. + * + * Completes the returned [Future] when all elements of the stream + * have been processed. + * + * If the stream contains an error, or if the call to [action] throws, + * the returned future completes with that error, and processing stops. + */ + Future forEach(void action(T element)) { + _Future future = new _Future(); + StreamSubscription subscription; + subscription = this.listen( + (T element) { + // TODO(floitsch): the type should be 'void' and inferred. + _runUserCode(() => action(element), (_) {}, + _cancelAndErrorClosure(subscription, future)); + }, + onError: future._completeError, + onDone: () { + future._complete(null); + }, + cancelOnError: true); + return future; + } + + /** + * Checks whether [test] accepts all elements provided by this stream. + * + * Calls [test] on each element of the stream. + * If the call returns `false`, the returned future is completed with `false` + * and processing stops. + * + * If the stream ends without finding an element that [test] rejects, + * the returned future is completed with `true`. + * + * If this stream contains an error, or if the call to [test] throws, + * the returned future is completed with that error, and processing stops. + */ + Future every(bool test(T element)) { + _Future future = new _Future(); + StreamSubscription subscription; + subscription = this.listen( + (T element) { + _runUserCode(() => test(element), (bool isMatch) { + if (!isMatch) { + _cancelAndValue(subscription, future, false); + } + }, _cancelAndErrorClosure(subscription, future)); + }, + onError: future._completeError, + onDone: () { + future._complete(true); + }, + cancelOnError: true); + return future; + } + + /** + * Checks whether [test] accepts any element provided by this stream. + * + * Calls [test] on each element of the stream. + * If the call returns `true`, the returned future is completed with `true` + * and processing stops. + * + * If the stream ends without finding an element that [test] accepts, + * the returned future is completed with `false`. + * + * If this stream contains an error, or if the call to [test] throws, + * the returned future is completed with that error, and processing stops. + */ + Future any(bool test(T element)) { + _Future future = new _Future(); + StreamSubscription subscription; + subscription = this.listen( + (T element) { + _runUserCode(() => test(element), (bool isMatch) { + if (isMatch) { + _cancelAndValue(subscription, future, true); + } + }, _cancelAndErrorClosure(subscription, future)); + }, + onError: future._completeError, + onDone: () { + future._complete(false); + }, + cancelOnError: true); + return future; + } + + /** + * The number of elements in this stream. + * + * Waits for all elements of this stream. When the stream ends, + * the returned future is completed with the number of elements. + * + * If the stream contains an error, the returned future is completed with + * that error, and processing stops. + * + * This operation listens to the stream, and a non-broadcast stream cannot + * be reused after finding its length. + */ + Future get length { + _Future future = new _Future(); + int count = 0; + this.listen( + (_) { + count++; + }, + onError: future._completeError, + onDone: () { + future._complete(count); + }, + cancelOnError: true); + return future; + } + + /** + * Whether this stream contains any elements. + * + * Waits for the first element of this stream, then completes the returned + * future with `true`. + * If the stream ends without emitting any elements, the returned future is + * completed with `false`. + * + * If the first event is an error, the returned future is completed with that + * error. + * + * This operation listens to the stream, and a non-broadcast stream cannot + * be reused after checking whether it is empty. + */ + Future get isEmpty { + _Future future = new _Future(); + StreamSubscription subscription; + subscription = this.listen( + (_) { + _cancelAndValue(subscription, future, false); + }, + onError: future._completeError, + onDone: () { + future._complete(true); + }, + cancelOnError: true); + return future; + } + + /** + * Adapt this stream to be a `Stream`. + * + * This stream is wrapped as a `Stream` which checks at run-time that + * each data event emitted by this stream is also an instance of [R]. + */ + Stream cast() => Stream.castFrom(this); + /** + * Collects all elements of this stream in a [List]. + * + * Creates a `List` and adds all elements of the stream to the list + * in the order they arrive. + * When the stream ends, the returned future is completed with that list. + * + * If the stream contains an error, the returned future is completed + * with that error, and processing stops. + */ + Future> toList() { + List result = []; + _Future> future = new _Future>(); + this.listen( + (T data) { + result.add(data); + }, + onError: future._completeError, + onDone: () { + future._complete(result); + }, + cancelOnError: true); + return future; + } + + /** + * Collects the data of this stream in a [Set]. + * + * The returned set is the same type as returned by `new Set()`. + * If another type of set is needed, either use [forEach] to add each + * element to the set, or use + * `toList().then((list) => new SomeOtherSet.from(list))` + * to create the set. + */ + Future> toSet() { + Set result = new Set(); + _Future> future = new _Future>(); + this.listen( + (T data) { + result.add(data); + }, + onError: future._completeError, + onDone: () { + future._complete(result); + }, + cancelOnError: true); + return future; + } + + /** + * Discards all data on the stream, but signals when it's done or an error + * occurred. + * + * When subscribing using [drain], cancelOnError will be true. This means + * that the future will complete with the first error on the stream and then + * cancel the subscription. + * + * In case of a `done` event the future completes with the given + * [futureValue]. + */ + Future drain([E futureValue]) => + listen(null, cancelOnError: true).asFuture(futureValue); + + /** + * Provides at most the first [count] data events of this stream. + * + * Returns a stream that emits the same events that this stream would + * if listened to at the same time, + * until either this stream ends or it has emitted [count] data events, + * at which point the returned stream is done. + * + * If this stream produces fewer than [count] data events before it's done, + * so will the returned stream. + * + * Starts listening to this stream when the returned stream is listened to + * and stops listening when the first [count] data events have been received. + * + * This means that if this is a single-subscription (non-broadcast) streams + * it cannot be reused after the returned stream has been listened to. + * + * If this is a broadcast stream, the returned stream is a broadcast stream. + * In that case, the events are only counted from the time + * the returned stream is listened to. + */ + Stream take(int count) { + return new _TakeStream(this, count); + } + + /** + * Forwards data events while [test] is successful. + * + * Returns a stream that provides the same events as this stream + * until [test] fails for a data event. + * The returned stream is done when either this stream is done, + * or when this stream first emits a data event that fails [test]. + * + * The `test` call is considered failing if it returns a non-`true` value + * or if it throws. If the `test` call throws, the error is emitted as the + * last event on the returned streams. + * + * Stops listening to this stream after the accepted elements. + * + * Internally the method cancels its subscription after these elements. This + * means that single-subscription (non-broadcast) streams are closed and + * cannot be reused after a call to this method. + * + * The returned stream is a broadcast stream if this stream is. + * For a broadcast stream, the events are only tested from the time + * the returned stream is listened to. + */ + Stream takeWhile(bool test(T element)) { + return new _TakeWhileStream(this, test); + } + + /** + * Skips the first [count] data events from this stream. + * + * Returns a stream that emits the same events as this stream would + * if listened to at the same time, except that the first [count] + * data events are not emitted. + * The returned stream is done when this stream is. + * + * If this stream emits fewer than [count] data events + * before being done, the returned stream emits no data events. + * + * The returned stream is a broadcast stream if this stream is. + * For a broadcast stream, the events are only counted from the time + * the returned stream is listened to. + */ + Stream skip(int count) { + return new _SkipStream(this, count); + } + + /** + * Skip data events from this stream while they are matched by [test]. + * + * Returns a stream that emits the same events as this stream, + * except that data events are not emitted until a data event fails `test`. + * The test fails when called with a data event + * if it returns a non-`true` value or if the call to `test` throws. + * If the call throws, the error is emitted as an error event + * on the returned stream instead of the data event, + * otherwise the event that made `test` return non-true is emitted as the + * first data event. + * + * Error and done events are provided by the returned stream unmodified. + * + * The returned stream is a broadcast stream if this stream is. + * For a broadcast stream, the events are only tested from the time + * the returned stream is listened to. + */ + Stream skipWhile(bool test(T element)) { + return new _SkipWhileStream(this, test); + } + + /** + * Skips data events if they are equal to the previous data event. + * + * The returned stream provides the same events as this stream, except + * that it never provides two consecutive data events that are equal. + * That is, errors are passed through to the returned stream, and + * data events are passed through if they are distinct from the most + * recently emitted data event. + * + * Equality is determined by the provided [equals] method. If that is + * omitted, the '==' operator on the last provided data element is used. + * + * If [equals] throws, the data event is replaced by an error event + * containing the thrown error. The behavior is equivalent to the + * original stream emitting the error event, and it doesn't change + * the what the most recently emitted data event is. + * + * The returned stream is a broadcast stream if this stream is. + * If a broadcast stream is listened to more than once, each subscription + * will individually perform the `equals` test. + */ + Stream distinct([bool equals(T previous, T next)]) { + return new _DistinctStream(this, equals); + } + + /** + * The first element of the stream. + * + * Stops listening to the stream after the first element has been received. + * + * Internally the method cancels its subscription after the first element. + * This means that single-subscription (non-broadcast) streams are closed + * and cannot be reused after a call to this getter. + * + * If an error event occurs before the first data event, the returned future + * is completed with that error. + * + * If this stream is empty (a done event occurs before the first data event), + * the returned future completes with an error. + * + * Except for the type of the error, this method is equivalent to + * `this.elementAt(0)`. + */ + Future get first { + _Future future = new _Future(); + StreamSubscription subscription; + subscription = this.listen( + (T value) { + _cancelAndValue(subscription, future, value); + }, + onError: future._completeError, + onDone: () { + try { + throw IterableElementError.noElement(); + } catch (e, s) { + _completeWithErrorCallback(future, e, s); + } + }, + cancelOnError: true); + return future; + } + + /** + * The last element of this stream. + * + * If this stream emits an error event, + * the returned future is completed with that error + * and processing stops. + * + * If this stream is empty (the done event is the first event), + * the returned future completes with an error. + */ + Future get last { + _Future future = new _Future(); + T result = null; + bool foundResult = false; + listen( + (T value) { + foundResult = true; + result = value; + }, + onError: future._completeError, + onDone: () { + if (foundResult) { + future._complete(result); + return; + } + try { + throw IterableElementError.noElement(); + } catch (e, s) { + _completeWithErrorCallback(future, e, s); + } + }, + cancelOnError: true); + return future; + } + + /** + * The single element of this stream. + * + * If this stream emits an error event, + * the returned future is completed with that error + * and processing stops. + * + * If [this] is empty or has more than one element, + * the returned future completes with an error. + */ + Future get single { + _Future future = new _Future(); + T result = null; + bool foundResult = false; + StreamSubscription subscription; + subscription = this.listen( + (T value) { + if (foundResult) { + // This is the second element we get. + try { + throw IterableElementError.tooMany(); + } catch (e, s) { + _cancelAndErrorWithReplacement(subscription, future, e, s); + } + return; + } + foundResult = true; + result = value; + }, + onError: future._completeError, + onDone: () { + if (foundResult) { + future._complete(result); + return; + } + try { + throw IterableElementError.noElement(); + } catch (e, s) { + _completeWithErrorCallback(future, e, s); + } + }, + cancelOnError: true); + return future; + } + + /** + * Finds the first element of this stream matching [test]. + * + * Returns a future that is completed with the first element of this stream + * that [test] returns `true` for. + * + * If no such element is found before this stream is done, and a + * [orElse] function is provided, the result of calling [orElse] + * becomes the value of the future. If [orElse] throws, the returned + * future is completed with that error. + * + * If this stream emits an error before the first matching element, + * the returned future is completed with that error, and processing stops. + * + * Stops listening to the stream after the first matching element or error + * has been received. + * + * Internally the method cancels its subscription after the first element that + * matches the predicate. This means that single-subscription (non-broadcast) + * streams are closed and cannot be reused after a call to this method. + * + * If an error occurs, or if this stream ends without finding a match and + * with no [orElse] function provided, + * the returned future is completed with an error. + */ + Future firstWhere(bool test(T element), {T orElse()}) { + _Future future = new _Future(); + StreamSubscription subscription; + subscription = this.listen( + (T value) { + _runUserCode(() => test(value), (bool isMatch) { + if (isMatch) { + _cancelAndValue(subscription, future, value); + } + }, _cancelAndErrorClosure(subscription, future)); + }, + onError: future._completeError, + onDone: () { + if (orElse != null) { + _runUserCode(orElse, future._complete, future._completeError); + return; + } + try { + throw IterableElementError.noElement(); + } catch (e, s) { + _completeWithErrorCallback(future, e, s); + } + }, + cancelOnError: true); + return future; + } + + /** + * Finds the last element in this stream matching [test]. + * + * If this stream emits an error, the returned future is completed with that + * error, and processing stops. + * + * Otherwise as [firstWhere], except that the last matching element is found + * instead of the first. + * That means that a non-error result cannot be provided before this stream + * is done. + */ + Future lastWhere(bool test(T element), {T orElse()}) { + _Future future = new _Future(); + T result = null; + bool foundResult = false; + StreamSubscription subscription; + subscription = this.listen( + (T value) { + _runUserCode(() => true == test(value), (bool isMatch) { + if (isMatch) { + foundResult = true; + result = value; + } + }, _cancelAndErrorClosure(subscription, future)); + }, + onError: future._completeError, + onDone: () { + if (foundResult) { + future._complete(result); + return; + } + if (orElse != null) { + _runUserCode(orElse, future._complete, future._completeError); + return; + } + try { + throw IterableElementError.noElement(); + } catch (e, s) { + _completeWithErrorCallback(future, e, s); + } + }, + cancelOnError: true); + return future; + } + + /** + * Finds the single element in this stream matching [test]. + * + * Like [lastWhere], except that it is an error if more than one + * matching element occurs in the stream. + */ + Future singleWhere(bool test(T element), {T orElse()}) { + _Future future = new _Future(); + T result = null; + bool foundResult = false; + StreamSubscription subscription; + subscription = this.listen( + (T value) { + _runUserCode(() => true == test(value), (bool isMatch) { + if (isMatch) { + if (foundResult) { + try { + throw IterableElementError.tooMany(); + } catch (e, s) { + _cancelAndErrorWithReplacement(subscription, future, e, s); + } + return; + } + foundResult = true; + result = value; + } + }, _cancelAndErrorClosure(subscription, future)); + }, + onError: future._completeError, + onDone: () { + if (foundResult) { + future._complete(result); + return; + } + try { + if (orElse != null) { + _runUserCode(orElse, future._complete, future._completeError); + return; + } + throw IterableElementError.noElement(); + } catch (e, s) { + _completeWithErrorCallback(future, e, s); + } + }, + cancelOnError: true); + return future; + } + + /** + * Returns the value of the [index]th data event of this stream. + * + * Stops listening to the stream after the [index]th data event has been + * received. + * + * Internally the method cancels its subscription after these elements. This + * means that single-subscription (non-broadcast) streams are closed and + * cannot be reused after a call to this method. + * + * If an error event occurs before the value is found, the future completes + * with this error. + * + * If a done event occurs before the value is found, the future completes + * with a [RangeError]. + */ + Future elementAt(int index) { + if (index is! int || index < 0) throw new ArgumentError(index); + _Future future = new _Future(); + StreamSubscription subscription; + int elementIndex = 0; + subscription = this.listen( + (T value) { + if (index == elementIndex) { + _cancelAndValue(subscription, future, value); + return; + } + elementIndex += 1; + }, + onError: future._completeError, + onDone: () { + future._completeError( + new RangeError.index(index, this, "index", null, elementIndex)); + }, + cancelOnError: true); + return future; + } + + /** + * Creates a new stream with the same events as this stream. + * + * Whenever more than [timeLimit] passes between two events from this stream, + * the [onTimeout] function is called, which can emit further events on + * the returned stream. + * + * The countdown doesn't start until the returned stream is listened to. + * The countdown is reset every time an event is forwarded from this stream, + * or when the stream is paused and resumed. + * + * The [onTimeout] function is called with one argument: an + * [EventSink] that allows putting events into the returned stream. + * This `EventSink` is only valid during the call to [onTimeout]. + * Calling [EventSink.close] on the sink passed to [onTimeout] closes the + * returned stream, and no futher events are processed. + * + * If [onTimeout] is omitted, a timeout will just put a [TimeoutException] + * into the error channel of the returned stream. + * If the call to [onTimeout] throws, the error is emitted on the returned + * stream. + * + * The returned stream is a broadcast stream if this stream is. + * If a broadcast stream is listened to more than once, each subscription + * will have its individually timer that starts counting on listen, + * and the subscriptions' timers can be paused individually. + */ + Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) { + StreamController controller; + // The following variables are set on listen. + StreamSubscription subscription; + Timer timer; + Zone zone; + _TimerCallback timeout; + + void onData(T event) { + timer.cancel(); + controller.add(event); + timer = zone.createTimer(timeLimit, timeout); + } + + void onError(error, StackTrace stackTrace) { + timer.cancel(); + assert(controller is _StreamController || + controller is _BroadcastStreamController); + dynamic eventSink = controller; + eventSink._addError(error, stackTrace); // Avoid Zone error replacement. + timer = zone.createTimer(timeLimit, timeout); + } + + void onDone() { + timer.cancel(); + controller.close(); + } + + void onListen() { + // This is the onListen callback for of controller. + // It runs in the same zone that the subscription was created in. + // Use that zone for creating timers and running the onTimeout + // callback. + zone = Zone.current; + if (onTimeout == null) { + timeout = () { + controller.addError( + new TimeoutException("No stream event", timeLimit), null); + }; + } else { + // TODO(floitsch): the return type should be 'void', and the type + // should be inferred. + var registeredOnTimeout = + zone.registerUnaryCallback>(onTimeout); + var wrapper = new _ControllerEventSinkWrapper(null); + timeout = () { + wrapper._sink = controller; // Only valid during call. + zone.runUnaryGuarded(registeredOnTimeout, wrapper); + wrapper._sink = null; + }; + } + + subscription = this.listen(onData, onError: onError, onDone: onDone); + timer = zone.createTimer(timeLimit, timeout); + } + + Future onCancel() { + timer.cancel(); + Future result = subscription.cancel(); + subscription = null; + return result; + } + + controller = isBroadcast + ? new _SyncBroadcastStreamController(onListen, onCancel) + : new _SyncStreamController(onListen, () { + // Don't null the timer, onCancel may call cancel again. + timer.cancel(); + subscription.pause(); + }, () { + subscription.resume(); + timer = zone.createTimer(timeLimit, timeout); + }, onCancel); + return controller.stream; + } +} + +/** + * A subscription on events from a [Stream]. + * + * When you listen on a [Stream] using [Stream.listen], + * a [StreamSubscription] object is returned. + * + * The subscription provides events to the listener, + * and holds the callbacks used to handle the events. + * The subscription can also be used to unsubscribe from the events, + * or to temporarily pause the events from the stream. + */ +abstract class StreamSubscription { + /** + * Cancels this subscription. + * + * After this call, the subscription no longer receives events. + * + * The stream may need to shut down the source of events and clean up after + * the subscription is canceled. + * + * Returns a future that is completed once the stream has finished + * its cleanup. + * + * For historical reasons, may also return `null` if no cleanup was necessary. + * Returning `null` is deprecated and should be avoided. + * + * Typically, futures are returned when the stream needs to release resources. + * For example, a stream might need to close an open file (as an asynchronous + * operation). If the listener wants to delete the file after having + * canceled the subscription, it must wait for the cleanup future to complete. + * + * A returned future completes with a `null` value. + * If the cleanup throws, which it really shouldn't, the returned future + * completes with that error. + */ + Future cancel(); + + /** + * Replaces the data event handler of this subscription. + * + * The [handleData] function is called for each element of the stream + * after this function is called. + * If [handleData] is `null`, further elements are ignored. + * + * This method replaces the current handler set by the invocation of + * [Stream.listen] or by a previous call to [onData]. + */ + void onData(void handleData(T data)); + + /** + * Replaces the error event handler of this subscription. + * + * The [handleError] function must be able to be called with either + * one positional argument, or with two positional arguments + * where the seconds is always a [StackTrace]. + * + * The [handleError] argument may be `null`, in which case further + * error events are considered unhandled, and will be reported to + * [Zone.handleUncaughtError]. + * + * The provided function is called for all error events from the + * stream subscription. + * + * This method replaces the current handler set by the invocation of + * [Stream.listen], by calling [asFuture], or by a previous call to [onError]. + */ + void onError(Function handleError); + + /** + * Replaces the done event handler of this subscription. + * + * The [handleDone] function is called when the stream closes. + * The value may be `null`, in which case no function is called. + * + * This method replaces the current handler set by the invocation of + * [Stream.listen], by calling [asFuture], or by a previous call to [onDone]. + */ + void onDone(void handleDone()); + + /** + * Request that the stream pauses events until further notice. + * + * While paused, the subscription will not fire any events. + * If it receives events from its source, they will be buffered until + * the subscription is resumed. + * For non-broadcast streams, the underlying source is usually informed + * about the pause, + * so it can stop generating events until the subscription is resumed. + * + * To avoid buffering events on a broadcast stream, it is better to + * cancel this subscription, and start to listen again when events + * are needed, if the intermediate events are not important. + * + * If [resumeSignal] is provided, the stream subscription will undo the pause + * when the future completes, as if by a call to [resume]. + * If the future completes with an error, + * the stream will still resume, but the error will be considered unhandled + * and is passed to [Zone.handleUncaughtError]. + * + * A call to [resume] will also undo a pause. + * + * If the subscription is paused more than once, an equal number + * of resumes must be performed to resume the stream. + * + * Currently DOM streams silently drop events when the stream is paused. This + * is a bug and will be fixed. + */ + void pause([Future resumeSignal]); + + /** + * Resume after a pause. + * + * This undoes one previous call to [pause]. + * When all previously calls to [pause] have been matched by a calls to + * [resume], possibly through a `resumeSignal` passed to [pause], + * the stream subscription may emit events again. + */ + void resume(); + + /** + * Whether the [StreamSubscription] is currently paused. + * + * If there have been more calls to [pause] than to [resume] on this + * stream subscription, the subscription is paused, and this getter + * returns `true`. + * + * Returns `false` if the stream can currently emit events, or if + * the subscription has completed or been cancelled. + */ + bool get isPaused; + + /** + * Returns a future that handles the [onDone] and [onError] callbacks. + * + * This method *overwrites* the existing [onDone] and [onError] callbacks + * with new ones that complete the returned future. + * + * In case of an error the subscription will automatically cancel (even + * when it was listening with `cancelOnError` set to `false`). + * + * In case of a `done` event the future completes with the given + * [futureValue]. + */ + Future asFuture([E futureValue]); +} + +/** + * A [Sink] that supports adding errors. + * + * This makes it suitable for capturing the results of asynchronous + * computations, which can complete with a value or an error. + * + * The [EventSink] has been designed to handle asynchronous events from + * [Stream]s. See, for example, [Stream.eventTransformed] which uses + * `EventSink`s to transform events. + */ +abstract class EventSink implements Sink { + /** + * Adds a data [event] to the sink. + * + * Must not be called on a closed sink. + */ + void add(T event); + + /** + * Adds an [error] to the sink. + * + * Must not be called on a closed sink. + */ + void addError(Object error, [StackTrace stackTrace]); + + /** + * Closes the sink. + * + * Calling this method more than once is allowed, but does nothing. + * + * Neither [add] nor [addError] must be called after this method. + */ + void close(); +} + +/** [Stream] wrapper that only exposes the [Stream] interface. */ +class StreamView extends Stream { + final Stream _stream; + + const StreamView(Stream stream) + : _stream = stream, + super._internal(); + + bool get isBroadcast => _stream.isBroadcast; + + Stream asBroadcastStream( + {void onListen(StreamSubscription subscription), + void onCancel(StreamSubscription subscription)}) => + _stream.asBroadcastStream(onListen: onListen, onCancel: onCancel); + + StreamSubscription listen(void onData(T value), + {Function onError, void onDone(), bool cancelOnError}) { + return _stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + } +} + +/** + * Abstract interface for a "sink" accepting multiple entire streams. + * + * A consumer can accept a number of consecutive streams using [addStream], + * and when no further data need to be added, the [close] method tells the + * consumer to complete its work and shut down. + * + * The [Stream.pipe] accepts a `StreamConsumer` and will pass the stream + * to the consumer's [addStream] method. When that completes, it will + * call [close] and then complete its own returned future. + */ +abstract class StreamConsumer { + /** + * Consumes the elements of [stream]. + * + * Listens on [stream] and does something for each event. + * + * Returns a future which is completed when the stream is done being added, + * and the consumer is ready to accept a new stream. + * No further calls to [addStream] or [close] should happen before the + * returned future has completed. + * + * The consumer may stop listening to the stream after an error, + * it may consume all the errors and only stop at a done event, + * or it may be canceled early if the receiver don't want any further events. + * + * If the consumer stops listening because of some error preventing it + * from continuing, it may report this error in the returned future, + * otherwise it will just complete the future with `null`. + */ + Future addStream(Stream stream); + + /** + * Tells the consumer that no further streams will be added. + * + * This allows the consumer to complete any remaining work and release + * resources that are no longer needed + * + * Returns a future which is completed when the consumer has shut down. + * If cleaning up can fail, the error may be reported in the returned future, + * otherwise it completes with `null`. + */ + Future close(); +} + +/** + * A object that accepts stream events both synchronously and asynchronously. + * + * A [StreamSink] combines the methods from [StreamConsumer] and [EventSink]. + * + * The [EventSink] methods can't be used while the [addStream] is called. + * As soon as the [addStream]'s [Future] completes with a value, the + * [EventSink] methods can be used again. + * + * If [addStream] is called after any of the [EventSink] methods, it'll + * be delayed until the underlying system has consumed the data added by the + * [EventSink] methods. + * + * When [EventSink] methods are used, the [done] [Future] can be used to + * catch any errors. + * + * When [close] is called, it will return the [done] [Future]. + */ +abstract class StreamSink implements EventSink, StreamConsumer { + /** + * Tells the stream sink that no further streams will be added. + * + * This allows the stream sink to complete any remaining work and release + * resources that are no longer needed + * + * Returns a future which is completed when the stream sink has shut down. + * If cleaning up can fail, the error may be reported in the returned future, + * otherwise it completes with `null`. + * + * Returns the same future as [done]. + * + * The stream sink may close before the [close] method is called, either due + * to an error or because it is itself providing events to someone who has + * stopped listening. In that case, the [done] future is completed first, + * and the `close` method will return the `done` future when called. + * + * Unifies [StreamConsumer.close] and [EventSink.close] which both mark their + * object as not expecting any further events. + */ + Future close(); + + /** + * Return a future which is completed when the [StreamSink] is finished. + * + * If the `StreamSink` fails with an error, + * perhaps in response to adding events using [add], [addError] or [close], + * the [done] future will complete with that error. + * + * Otherwise, the returned future will complete when either: + * + * * all events have been processed and the sink has been closed, or + * * the sink has otherwise been stopped from handling more events + * (for example by canceling a stream subscription). + */ + Future get done; +} + +/** + * Transforms a Stream. + * + * When a stream's [Stream.transform] method is invoked with a + * [StreamTransformer], the stream calls the [bind] method on the provided + * transformer. The resulting stream is then returned from the + * [Stream.transform] method. + * + * Conceptually, a transformer is simply a function from [Stream] to [Stream] + * that is encapsulated into a class. + * + * It is good practice to write transformers that can be used multiple times. + * + * All other transforming methods on [Stream], such as [Stream.map], + * [Stream.where] or [Stream.expand] can be implemented using + * [Stream.transform]. A [StreamTransformer] is thus very powerful but often + * also a bit more complicated to use. + */ +abstract class StreamTransformer { + /** + * Creates a [StreamTransformer] based on the given [onListen] callback. + * + * The returned stream transformer uses the provided [onListen] callback + * when a transformed stream is listened to. At that time, the callback + * receives the input stream (the one passed to [bind]) and a + * boolean flag `cancelOnError` to create a [StreamSubscription]. + * + * The [onListen] callback does *not* receive the handlers that were passed + * to [Stream.listen]. These are automatically set after the call to the + * [onListen] callback (using [StreamSubscription.onData], + * [StreamSubscription.onError] and [StreamSubscription.onDone]). + * + * Most commonly, an [onListen] callback will first call [Stream.listen] on + * the provided stream (with the corresponding `cancelOnError` flag), and then + * return a new [StreamSubscription]. + * + * There are two common ways to create a StreamSubscription: + * + * 1. by allocating a [StreamController] and to return the result of + * listening to its stream. It's important to forward pause, resume and + * cancel events (unless the transformer intentionally wants to change + * this behavior). + * 2. by creating a new class that implements [StreamSubscription]. + * Note that the subscription should run callbacks in the [Zone] the + * stream was listened to (see [Zone] and [Zone.bindCallback]). + * + * Example: + * + * ``` + * /// Starts listening to [input] and duplicates all non-error events. + * StreamSubscription _onListen(Stream input, bool cancelOnError) { + * StreamSubscription subscription; + * // Create controller that forwards pause, resume and cancel events. + * var controller = new StreamController( + * onPause: () { + * subscription.pause(); + * }, + * onResume: () { + * subscription.resume(); + * }, + * onCancel: () => subscription.cancel(), + * sync: true); // "sync" is correct here, since events are forwarded. + * + * // Listen to the provided stream using `cancelOnError`. + * subscription = input.listen((data) { + * // Duplicate the data. + * controller.add(data); + * controller.add(data); + * }, + * onError: controller.addError, + * onDone: controller.close, + * cancelOnError: cancelOnError); + * + * // Return a new [StreamSubscription] by listening to the controller's + * // stream. + * return controller.stream.listen(null); + * } + * + * // Instantiate a transformer: + * var duplicator = const StreamTransformer(_onListen); + * + * // Use as follows: + * intStream.transform(duplicator); + * ``` + */ + const factory StreamTransformer( + StreamSubscription onListen( + Stream stream, bool cancelOnError)) = + _StreamSubscriptionTransformer; + + /** + * Creates a [StreamTransformer] that delegates events to the given functions. + * + * Example use of a duplicating transformer: + * + * ``` + * stringStream.transform(new StreamTransformer.fromHandlers( + * handleData: (String value, EventSink sink) { + * sink.add(value); + * sink.add(value); // Duplicate the incoming events. + * })); + * ``` + * + * Transformers that are constructed this way cannot use captured state if + * they are used in streams that can be listened to multiple times. + * ``` + * StreamController controller; + * controller = new StreamController.broadcast(onListen: () { + * scheduleMicrotask(() { + * controller.addError("Bad"); + * controller.addError("Worse"); + * controller.addError("Worst"); + * }); + * }); + * var sharedState = 0; + * var transformedStream = controller.stream.transform( + * new StreamTransformer.fromHandlers( + * handleError: (error, stackTrace, sink) { + * sharedState++; // Increment shared error-counter. + * sink.add("Error $sharedState: $error"); + * })); + * + * transformedStream.listen(print); + * transformedStream.listen(print); // Listen twice. + * // Listening twice to the same stream makes the transformer share the same + * // state. Instead of having "Error 1: Bad", "Error 2: Worse", + * // "Error 3: Worst" as output (each twice for the separate subscriptions), + * // this program emits: + * // Error 1: Bad + * // Error 2: Bad + * // Error 3: Worse + * // Error 4: Worse + * // Error 5: Worst + * // Error 6: Worst + * ``` + */ + factory StreamTransformer.fromHandlers( + {void handleData(S data, EventSink sink), + void handleError(Object error, StackTrace stackTrace, EventSink sink), + void handleDone(EventSink sink)}) = _StreamHandlerTransformer; + + /** + * Adapts [source] to be a `StreamTransfomer`. + * + * This allows [source] to be used at the new type, but at run-time it + * must satisfy the requirements of both the new type and its original type. + * + * Data events passed into the returned transformer must also be instances + * of [SS], and data events produced by [source] for those events must + * also be instances of [TT]. + */ + static StreamTransformer castFrom( + StreamTransformer source) { + return new CastStreamTransformer(source); + } + + /** + * Transforms the provided [stream]. + * + * Returns a new stream with events that are computed from events of the + * provided [stream]. + * + * Implementors of the [StreamTransformer] interface should document + * differences from the following expected behavior: + * + * * When the returned stream is listened to, it starts listening to the + * input [stream]. + * * Subscriptions of the returned stream forward (in a reasonable time) + * a [StreamSubscription.pause] call to the subscription of the input + * [stream]. + * * Similarly, canceling a subscription of the returned stream eventually + * (in reasonable time) cancels the subscription of the input [stream]. + * + * "Reasonable time" depends on the transformer and stream. Some transformers, + * like a "timeout" transformer, might make these operations depend on a + * duration. Others might not delay them at all, or just by a microtask. + */ + Stream bind(Stream stream); + + /** + * Provides a `StreamTrasformer` view of this stream transformer. + * + * The resulting transformer will check at run-time that all data events + * of the stream it transforms are actually instances of [S], + * and it will check that all data events produced by this transformer + * are acually instances of [RT]. + */ + StreamTransformer cast(); +} + +/** + * Base class for implementing [StreamTransformer]. + * + * Contains default implementations of every method except [bind]. + */ +abstract class StreamTransformerBase implements StreamTransformer { + const StreamTransformerBase(); + + StreamTransformer cast() => + StreamTransformer.castFrom(this); +} + +/** + * An [Iterator] like interface for the values of a [Stream]. + * + * This wraps a [Stream] and a subscription on the stream. It listens + * on the stream, and completes the future returned by [moveNext] when the + * next value becomes available. + * + * The stream may be paused between calls to [moveNext]. + */ +abstract class StreamIterator { + /** Create a [StreamIterator] on [stream]. */ + factory StreamIterator(Stream stream) + // TODO(lrn): use redirecting factory constructor when type + // arguments are supported. + => + new _StreamIterator(stream); + + /** + * Wait for the next stream value to be available. + * + * Returns a future which will complete with either `true` or `false`. + * Completing with `true` means that another event has been received and + * can be read as [current]. + * Completing with `false` means that the stream iteration is done and + * no further events will ever be available. + * The future may complete with an error, if the stream produces an error, + * which also ends iteration. + * + * The function must not be called again until the future returned by a + * previous call is completed. + */ + Future moveNext(); + + /** + * The current value of the stream. + * + * Is `null` before the first call to [moveNext] and after a call to + * `moveNext` completes with a `false` result or an error. + * + * When a `moveNext` call completes with `true`, the `current` field holds + * the most recent event of the stream, and it stays like that until the next + * call to `moveNext`. + * Between a call to `moveNext` and when its returned future completes, + * the value is unspecified. + */ + T get current; + + /** + * Cancels the stream iterator (and the underlying stream subscription) early. + * + * The stream iterator is automatically canceled if the [moveNext] future + * completes with either `false` or an error. + * + * If you need to stop listening for values before the stream iterator is + * automatically closed, you must call [cancel] to ensure that the stream + * is properly closed. + * + * If [moveNext] has been called when the iterator is canceled, + * its returned future will complete with `false` as value, + * as will all further calls to [moveNext]. + * + * Returns a future if the cancel-operation is not completed synchronously. + * Otherwise returns `null`. + */ + Future cancel(); +} + +/** + * Wraps an [_EventSink] so it exposes only the [EventSink] interface. + */ +class _ControllerEventSinkWrapper implements EventSink { + EventSink _sink; + _ControllerEventSinkWrapper(this._sink); + + void add(T data) { + _sink.add(data); + } + + void addError(error, [StackTrace stackTrace]) { + _sink.addError(error, stackTrace); + } + + void close() { + _sink.close(); + } +} +HNN<GG)429EQ?B:N-J)EG@HFIOPOCEGINEPM>K KGB(E2?G60GHEK$&/$.N$A,Q><CE".89JM9KPJ2(4JNKF+/$E'!2% + 9 +*  !,3" -% OHMGLNL!@0>0.#$$ C1 V6N? ?@#=2*IOM7$0!PFK-MGJO*LF>ML/:<@)O=I L8J.EHJK8Q?30K5LFC=)5>HI@F6BL+(,EDHC8EPBHL:)0MHK!B8$("05<,-%% +% ,2$ +76#  ," # 1EONIOIPKQ);B9$(05<-&% +! M + I%6#  ," # 1LO EMFJ,DPOK;NHGOGBL@@;IH"KH!ML&KBL=83<C!QQH'O G#2O:6 (:PD68% EBBE8EGE7 H*% E< (# JOGOJ?14.%-! D +NIQNIM)0% C;< (# 6EIJ+$% E?= (" I1PH3HM-0% =<< (" H1NH4HM+0% =;< (# ,BCL'M). (# 0MNP M30% 8 (" ,KH67ILG,6 ($ 2FH <"4 ($ MLOC)BDH&J1N"MPNIO=),6C*BELM)AOK3BF).0;FD"69BBG),IAN2G@7LKBF).0EIHDG"HKFDE7BL2:1&NML7O#P2D*% 8 (46 &*6B2*  (& 46 (*662*% 24J  (& 46 =N%CCG*FMMQPJL)5='% ;<< ( K 46 <O"ON<'% C"< (& K 46 >C,>*% C!8!N"< (& "M46 CKOK3NL#D*% ':  (!O ?PJKO/>FDL:M4M BLF?O$2(4105&O4:HEI J"J@A> L4-D6E"#:-8.56E7' BN#EQ;QPGQ6K ;H$>G8(<F?1ED!CGQ&;ACGP"A>H"JIFE?P=,N20C8P!%/JD4;GFD7IL6JAC*)D>HE%1&*"*8FDB(%/>AI5?"IFLK0IF;#(<N7I$CBPIG=&?I)JP)NNJE*HMI?JBL)MP)(OMLGP1K.N6?GE9?K?N&NE>M')KKJ@DNK=DNQ(?GMLFJE JP0K6#$2O?,  +)%*M.#D& #*7,Q/ P>? MF *@%'' :569/ +&7PCP *3PN9IOMI =*>'KG7KKJMLQKK$LK@I$,4CP!.6>FK!9#0+B" &5IKI/M J!&G=MPJQL0LLB>.NG?+2'Xfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/stream_controller.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +// ------------------------------------------------------------------- +// Controller for creating and adding events to a stream. +// ------------------------------------------------------------------- + +/** + * Type of a stream controller's `onListen`, `onPause` and `onResume` callbacks. + */ +typedef void ControllerCallback(); + +/** + * Type of stream controller `onCancel` callbacks. + * + * The callback may return either `void` or a future. + */ +typedef ControllerCancelCallback(); + +/** + * A controller with the stream it controls. + * + * This controller allows sending data, error and done events on + * its [stream]. + * This class can be used to create a simple stream that others + * can listen on, and to push events to that stream. + * + * It's possible to check whether the stream is paused or not, and whether + * it has subscribers or not, as well as getting a callback when either of + * these change. + */ +abstract class StreamController implements StreamSink { + /** The stream that this controller is controlling. */ + Stream get stream; + + /** + * A controller with a [stream] that supports only one single subscriber. + * + * If [sync] is true, the returned stream controller is a + * [SynchronousStreamController], and must be used with the care + * and attention necessary to not break the [Stream] contract. If in doubt, + * use the non-sync version. + * + * Using an asynchronous controller will never give the wrong + * behavior, but using a synchronous controller incorrectly can cause + * otherwise correct programs to break. + * + * A synchronous controller is only intended for optimizing event + * propagation when one asynchronous event immediately triggers another. + * It should not be used unless the calls to [add] or [addError] + * are guaranteed to occur in places where it won't break `Stream` invariants. + * + * Use synchronous controllers only to forward (potentially transformed) + * events from another stream or a future. + * + * A Stream should be inert until a subscriber starts listening on it (using + * the [onListen] callback to start producing events). Streams should not + * leak resources (like websockets) when no user ever listens on the stream. + * + * The controller buffers all incoming events until a subscriber is + * registered, but this feature should only be used in rare circumstances. + * + * The [onPause] function is called when the stream becomes + * paused. [onResume] is called when the stream resumed. + * + * The [onListen] callback is called when the stream + * receives its listener and [onCancel] when the listener ends + * its subscription. If [onCancel] needs to perform an asynchronous operation, + * [onCancel] should return a future that completes when the cancel operation + * is done. + * + * If the stream is canceled before the controller needs new data the + * [onResume] call might not be executed. + */ + factory StreamController( + {void onListen(), + void onPause(), + void onResume(), + onCancel(), + bool sync: false}) { + return sync + ? new _SyncStreamController(onListen, onPause, onResume, onCancel) + : new _AsyncStreamController(onListen, onPause, onResume, onCancel); + } + + /** + * A controller where [stream] can be listened to more than once. + * + * The [Stream] returned by [stream] is a broadcast stream. + * It can be listened to more than once. + * + * A Stream should be inert until a subscriber starts listening on it (using + * the [onListen] callback to start producing events). Streams should not + * leak resources (like websockets) when no user ever listens on the stream. + * + * Broadcast streams do not buffer events when there is no listener. + * + * The controller distributes any events to all currently subscribed + * listeners at the time when [add], [addError] or [close] is called. + * It is not allowed to call `add`, `addError`, or `close` before a previous + * call has returned. The controller does not have any internal queue of + * events, and if there are no listeners at the time the event is added, + * it will just be dropped, or, if it is an error, be reported as uncaught. + * + * Each listener subscription is handled independently, + * and if one pauses, only the pausing listener is affected. + * A paused listener will buffer events internally until unpaused or canceled. + * + * If [sync] is true, events may be fired directly by the stream's + * subscriptions during an [add], [addError] or [close] call. + * The returned stream controller is a [SynchronousStreamController], + * and must be used with the care and attention necessary to not break + * the [Stream] contract. + * See [Completer.sync] for some explanations on when a synchronous + * dispatching can be used. + * If in doubt, keep the controller non-sync. + * + * If [sync] is false, the event will always be fired at a later time, + * after the code adding the event has completed. + * In that case, no guarantees are given with regard to when + * multiple listeners get the events, except that each listener will get + * all events in the correct order. Each subscription handles the events + * individually. + * If two events are sent on an async controller with two listeners, + * one of the listeners may get both events + * before the other listener gets any. + * A listener must be subscribed both when the event is initiated + * (that is, when [add] is called) + * and when the event is later delivered, + * in order to receive the event. + * + * The [onListen] callback is called when the first listener is subscribed, + * and the [onCancel] is called when there are no longer any active listeners. + * If a listener is added again later, after the [onCancel] was called, + * the [onListen] will be called again. + */ + factory StreamController.broadcast( + {void onListen(), void onCancel(), bool sync: false}) { + return sync + ? new _SyncBroadcastStreamController(onListen, onCancel) + : new _AsyncBroadcastStreamController(onListen, onCancel); + } + + /** + * The callback which is called when the stream is listened to. + * + * May be set to `null`, in which case no callback will happen. + */ + ControllerCallback get onListen; + + void set onListen(void onListenHandler()); + + /** + * The callback which is called when the stream is paused. + * + * May be set to `null`, in which case no callback will happen. + * + * Pause related callbacks are not supported on broadcast stream controllers. + */ + ControllerCallback get onPause; + + void set onPause(void onPauseHandler()); + + /** + * The callback which is called when the stream is resumed. + * + * May be set to `null`, in which case no callback will happen. + * + * Pause related callbacks are not supported on broadcast stream controllers. + */ + ControllerCallback get onResume; + + void set onResume(void onResumeHandler()); + + /** + * The callback which is called when the stream is canceled. + * + * May be set to `null`, in which case no callback will happen. + */ + ControllerCancelCallback get onCancel; + + void set onCancel(onCancelHandler()); + + /** + * Returns a view of this object that only exposes the [StreamSink] interface. + */ + StreamSink get sink; + + /** + * Whether the stream controller is closed for adding more events. + * + * The controller becomes closed by calling the [close] method. + * New events cannot be added, by calling [add] or [addError], + * to a closed controller. + * + * If the controller is closed, + * the "done" event might not have been delivered yet, + * but it has been scheduled, and it is too late to add more events. + */ + bool get isClosed; + + /** + * Whether the subscription would need to buffer events. + * + * This is the case if the controller's stream has a listener and it is + * paused, or if it has not received a listener yet. In that case, the + * controller is considered paused as well. + * + * A broadcast stream controller is never considered paused. It always + * forwards its events to all uncanceled subscriptions, if any, + * and let the subscriptions handle their own pausing and buffering. + */ + bool get isPaused; + + /** Whether there is a subscriber on the [Stream]. */ + bool get hasListener; + + /** + * Sends a data [event]. + * + * Listeners receive this event in a later microtask. + * + * Note that a synchronous controller (created by passing true to the `sync` + * parameter of the `StreamController` constructor) delivers events + * immediately. Since this behavior violates the contract mentioned here, + * synchronous controllers should only be used as described in the + * documentation to ensure that the delivered events always *appear* as if + * they were delivered in a separate microtask. + */ + void add(T event); + + /** + * Sends or enqueues an error event. + * + * If [error] is `null`, it is replaced by a [NullThrownError]. + * + * Listeners receive this event at a later microtask. This behavior can be + * overridden by using `sync` controllers. Note, however, that sync + * controllers have to satisfy the preconditions mentioned in the + * documentation of the constructors. + */ + void addError(Object error, [StackTrace stackTrace]); + + /** + * Closes the stream. + * + * Listeners receive the done event at a later microtask. This behavior can be + * overridden by using `sync` controllers. Note, however, that sync + * controllers have to satisfy the preconditions mentioned in the + * documentation of the constructors. + */ + Future close(); + + /** + * Receives events from [source] and puts them into this controller's stream. + * + * Returns a future which completes when the source stream is done. + * + * Events must not be added directly to this controller using [add], + * [addError], [close] or [addStream], until the returned future + * is complete. + * + * Data and error events are forwarded to this controller's stream. A done + * event on the source will end the `addStream` operation and complete the + * returned future. + * + * If [cancelOnError] is true, only the first error on [source] is + * forwarded to the controller's stream, and the `addStream` ends + * after this. If [cancelOnError] is false, all errors are forwarded + * and only a done event will end the `addStream`. + * If [cancelOnError] is omitted, it defaults to false. + */ + Future addStream(Stream source, {bool cancelOnError}); +} + +/** + * A stream controller that delivers its events synchronously. + * + * A synchronous stream controller is intended for cases where + * an already asynchronous event triggers an event on a stream. + * + * Instead of adding the event to the stream in a later microtask, + * causing extra latency, the event is instead fired immediately by the + * synchronous stream controller, as if the stream event was + * the current event or microtask. + * + * The synchronous stream controller can be used to break the contract + * on [Stream], and it must be used carefully to avoid doing so. + * + * The only advantage to using a [SynchronousStreamController] over a + * normal [StreamController] is the improved latency. + * Only use the synchronous version if the improvement is significant, + * and if its use is safe. Otherwise just use a normal stream controller, + * which will always have the correct behavior for a [Stream], and won't + * accidentally break other code. + * + * Adding events to a synchronous controller should only happen as the + * very last part of the handling of the original event. + * At that point, adding an event to the stream is equivalent to + * returning to the event loop and adding the event in the next microtask. + * + * Each listener callback will be run as if it was a top-level event + * or microtask. This means that if it throws, the error will be reported as + * uncaught as soon as possible. + * This is one reason to add the event as the last thing in the original event + * handler - any action done after adding the event will delay the report of + * errors in the event listener callbacks. + * + * If an event is added in a setting that isn't known to be another event, + * it may cause the stream's listener to get that event before the listener + * is ready to handle it. We promise that after calling [Stream.listen], + * you won't get any events until the code doing the listen has completed. + * Calling [add] in response to a function call of unknown origin may break + * that promise. + * + * An [onListen] callback from the controller is *not* an asynchronous event, + * and adding events to the controller in the `onListen` callback is always + * wrong. The events will be delivered before the listener has even received + * the subscription yet. + * + * The synchronous broadcast stream controller also has a restrictions that a + * normal stream controller does not: + * The [add], [addError], [close] and [addStream] methods *must not* be + * called while an event is being delivered. + * That is, if a callback on a subscription on the controller's stream causes + * a call to any of the functions above, the call will fail. + * A broadcast stream may have more than one listener, and if an + * event is added synchronously while another is being also in the process + * of being added, the latter event might reach some listeners before + * the former. To prevent that, an event cannot be added while a previous + * event is being fired. + * This guarantees that an event is fully delivered when the + * first [add], [addError] or [close] returns, + * and further events will be delivered in the correct order. + * + * This still only guarantees that the event is delivered to the subscription. + * If the subscription is paused, the actual callback may still happen later, + * and the event will instead be buffered by the subscription. + * Barring pausing, and the following buffered events that haven't been + * delivered yet, callbacks will be called synchronously when an event is added. + * + * Adding an event to a synchronous non-broadcast stream controller while + * another event is in progress may cause the second event to be delayed + * and not be delivered synchronously, and until that event is delivered, + * the controller will not act synchronously. + */ +abstract class SynchronousStreamController implements StreamController { + /** + * Adds event to the controller's stream. + * + * As [StreamController.add], but must not be called while an event is + * being added by [add], [addError] or [close]. + */ + void add(T data); + + /** + * Adds error to the controller's stream. + * + * As [StreamController.addError], but must not be called while an event is + * being added by [add], [addError] or [close]. + */ + void addError(Object error, [StackTrace stackTrace]); + + /** + * Closes the controller's stream. + * + * As [StreamController.close], but must not be called while an event is + * being added by [add], [addError] or [close]. + */ + Future close(); +} + +abstract class _StreamControllerLifecycle { + StreamSubscription _subscribe( + void onData(T data), Function onError, void onDone(), bool cancelOnError); + void _recordPause(StreamSubscription subscription) {} + void _recordResume(StreamSubscription subscription) {} + Future _recordCancel(StreamSubscription subscription) => null; +} + +/** + * Default implementation of [StreamController]. + * + * Controls a stream that only supports a single controller. + */ +abstract class _StreamController + implements + StreamController, + _StreamControllerLifecycle, + _EventSink, + _EventDispatch { + // The states are bit-flags. More than one can be set at a time. + // + // The "subscription state" goes through the states: + // initial -> subscribed -> canceled. + // These are mutually exclusive. + // The "closed" state records whether the [close] method has been called + // on the controller. This can be done at any time. If done before + // subscription, the done event is queued. If done after cancel, the done + // event is ignored (just as any other event after a cancel). + + /** The controller is in its initial state with no subscription. */ + static const int _STATE_INITIAL = 0; + /** The controller has a subscription, but hasn't been closed or canceled. */ + static const int _STATE_SUBSCRIBED = 1; + /** The subscription is canceled. */ + static const int _STATE_CANCELED = 2; + /** Mask for the subscription state. */ + static const int _STATE_SUBSCRIPTION_MASK = 3; + + // The following state relate to the controller, not the subscription. + // If closed, adding more events is not allowed. + // If executing an [addStream], new events are not allowed either, but will + // be added by the stream. + + /** + * The controller is closed due to calling [close]. + * + * When the stream is closed, you can neither add new events nor add new + * listeners. + */ + static const int _STATE_CLOSED = 4; + /** + * The controller is in the middle of an [addStream] operation. + * + * While adding events from a stream, no new events can be added directly + * on the controller. + */ + static const int _STATE_ADDSTREAM = 8; + + /** + * Field containing different data depending on the current subscription + * state. + * + * If [_state] is [_STATE_INITIAL], the field may contain a [_PendingEvents] + * for events added to the controller before a subscription. + * + * While [_state] is [_STATE_SUBSCRIBED], the field contains the subscription. + * + * When [_state] is [_STATE_CANCELED] the field is currently not used. + */ + var _varData; + + /** Current state of the controller. */ + int _state = _STATE_INITIAL; + + /** + * Future completed when the stream sends its last event. + * + * This is also the future returned by [close]. + */ + // TODO(lrn): Could this be stored in the varData field too, if it's not + // accessed until the call to "close"? Then we need to special case if it's + // accessed earlier, or if close is called before subscribing. + _Future _doneFuture; + + ControllerCallback onListen; + ControllerCallback onPause; + ControllerCallback onResume; + ControllerCancelCallback onCancel; + + _StreamController(this.onListen, this.onPause, this.onResume, this.onCancel); + + // Return a new stream every time. The streams are equal, but not identical. + Stream get stream => new _ControllerStream(this); + + /** + * Returns a view of this object that only exposes the [StreamSink] interface. + */ + StreamSink get sink => new _StreamSinkWrapper(this); + + /** + * Whether a listener has existed and been canceled. + * + * After this, adding more events will be ignored. + */ + bool get _isCanceled => (_state & _STATE_CANCELED) != 0; + + /** Whether there is an active listener. */ + bool get hasListener => (_state & _STATE_SUBSCRIBED) != 0; + + /** Whether there has not been a listener yet. */ + bool get _isInitialState => + (_state & _STATE_SUBSCRIPTION_MASK) == _STATE_INITIAL; + + bool get isClosed => (_state & _STATE_CLOSED) != 0; + + bool get isPaused => + hasListener ? _subscription._isInputPaused : !_isCanceled; + + bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0; + + /** New events may not be added after close, or during addStream. */ + bool get _mayAddEvent => (_state < _STATE_CLOSED); + + // Returns the pending events. + // Pending events are events added before a subscription exists. + // They are added to the subscription when it is created. + // Pending events, if any, are kept in the _varData field until the + // stream is listened to. + // While adding a stream, pending events are moved into the + // state object to allow the state object to use the _varData field. + _PendingEvents get _pendingEvents { + assert(_isInitialState); + if (!_isAddingStream) { + return _varData; + } + _StreamControllerAddStreamState state = _varData; + return state.varData; + } + + // Returns the pending events, and creates the object if necessary. + _StreamImplEvents _ensurePendingEvents() { + assert(_isInitialState); + if (!_isAddingStream) { + if (_varData == null) _varData = new _StreamImplEvents(); + return _varData; + } + _StreamControllerAddStreamState state = _varData; + if (state.varData == null) state.varData = new _StreamImplEvents(); + return state.varData; + } + + // Get the current subscription. + // If we are adding a stream, the subscription is moved into the state + // object to allow the state object to use the _varData field. + _ControllerSubscription get _subscription { + assert(hasListener); + if (_isAddingStream) { + _StreamControllerAddStreamState addState = _varData; + return addState.varData; + } + return _varData; + } + + /** + * Creates an error describing why an event cannot be added. + * + * The reason, and therefore the error message, depends on the current state. + */ + Error _badEventState() { + if (isClosed) { + return new StateError("Cannot add event after closing"); + } + assert(_isAddingStream); + return new StateError("Cannot add event while adding a stream"); + } + + // StreamSink interface. + Future addStream(Stream source, {bool cancelOnError}) { + if (!_mayAddEvent) throw _badEventState(); + if (_isCanceled) return new _Future.immediate(null); + _StreamControllerAddStreamState addState = + new _StreamControllerAddStreamState( + this, _varData, source, cancelOnError ?? false); + _varData = addState; + _state |= _STATE_ADDSTREAM; + return addState.addStreamFuture; + } + + /** + * Returns a future that is completed when the stream is done + * processing events. + * + * This happens either when the done event has been sent, or if the + * subscriber of a single-subscription stream is cancelled. + */ + Future get done => _ensureDoneFuture(); + + Future _ensureDoneFuture() { + if (_doneFuture == null) { + _doneFuture = _isCanceled ? Future._nullFuture : new _Future(); + } + return _doneFuture; + } + + /** + * Send or enqueue a data event. + */ + void add(T value) { + if (!_mayAddEvent) throw _badEventState(); + _add(value); + } + + /** + * Send or enqueue an error event. + */ + void addError(Object error, [StackTrace stackTrace]) { + if (!_mayAddEvent) throw _badEventState(); + error = _nonNullError(error); + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + _addError(error, stackTrace); + } + + /** + * Closes this controller and sends a done event on the stream. + * + * The first time a controller is closed, a "done" event is added to its + * stream. + * + * You are allowed to close the controller more than once, but only the first + * call has any effect. + * + * After closing, no further events may be added using [add], [addError] + * or [addStream]. + * + * The returned future is completed when the done event has been delivered. + */ + Future close() { + if (isClosed) { + return _ensureDoneFuture(); + } + if (!_mayAddEvent) throw _badEventState(); + _closeUnchecked(); + return _ensureDoneFuture(); + } + + void _closeUnchecked() { + _state |= _STATE_CLOSED; + if (hasListener) { + _sendDone(); + } else if (_isInitialState) { + _ensurePendingEvents().add(const _DelayedDone()); + } + } + + // EventSink interface. Used by the [addStream] events. + + // Add data event, used both by the [addStream] events and by [add]. + void _add(T value) { + if (hasListener) { + _sendData(value); + } else if (_isInitialState) { + _ensurePendingEvents().add(new _DelayedData(value)); + } + } + + void _addError(Object error, StackTrace stackTrace) { + if (hasListener) { + _sendError(error, stackTrace); + } else if (_isInitialState) { + _ensurePendingEvents().add(new _DelayedError(error, stackTrace)); + } + } + + void _close() { + // End of addStream stream. + assert(_isAddingStream); + _StreamControllerAddStreamState addState = _varData; + _varData = addState.varData; + _state &= ~_STATE_ADDSTREAM; + addState.complete(); + } + + // _StreamControllerLifeCycle interface + + StreamSubscription _subscribe(void onData(T data), Function onError, + void onDone(), bool cancelOnError) { + if (!_isInitialState) { + throw new StateError("Stream has already been listened to."); + } + _ControllerSubscription subscription = new _ControllerSubscription( + this, onData, onError, onDone, cancelOnError); + + _PendingEvents pendingEvents = _pendingEvents; + _state |= _STATE_SUBSCRIBED; + if (_isAddingStream) { + _StreamControllerAddStreamState addState = _varData; + addState.varData = subscription; + addState.resume(); + } else { + _varData = subscription; + } + subscription._setPendingEvents(pendingEvents); + subscription._guardCallback(() { + _runGuarded(onListen); + }); + + return subscription; + } + + Future _recordCancel(StreamSubscription subscription) { + // When we cancel, we first cancel any stream being added, + // Then we call `onCancel`, and finally the _doneFuture is completed. + // If either of addStream's cancel or `onCancel` returns a future, + // we wait for it before continuing. + // Any error during this process ends up in the returned future. + // If more errors happen, we act as if it happens inside nested try/finallys + // or whenComplete calls, and only the last error ends up in the + // returned future. + Future result; + if (_isAddingStream) { + _StreamControllerAddStreamState addState = _varData; + result = addState.cancel(); + } + _varData = null; + _state = + (_state & ~(_STATE_SUBSCRIBED | _STATE_ADDSTREAM)) | _STATE_CANCELED; + + if (onCancel != null) { + if (result == null) { + // Only introduce a future if one is needed. + // If _onCancel returns null, no future is needed. + try { + result = onCancel(); + } catch (e, s) { + // Return the error in the returned future. + // Complete it asynchronously, so there is time for a listener + // to handle the error. + result = new _Future().._asyncCompleteError(e, s); + } + } else { + // Simpler case when we already know that we will return a future. + result = result.whenComplete(onCancel); + } + } + + void complete() { + if (_doneFuture != null && _doneFuture._mayComplete) { + _doneFuture._asyncComplete(null); + } + } + + if (result != null) { + result = result.whenComplete(complete); + } else { + complete(); + } + + return result; + } + + void _recordPause(StreamSubscription subscription) { + if (_isAddingStream) { + _StreamControllerAddStreamState addState = _varData; + addState.pause(); + } + _runGuarded(onPause); + } + + void _recordResume(StreamSubscription subscription) { + if (_isAddingStream) { + _StreamControllerAddStreamState addState = _varData; + addState.resume(); + } + _runGuarded(onResume); + } +} + +abstract class _SyncStreamControllerDispatch + implements _StreamController, SynchronousStreamController { + int get _state; + void set _state(int state); + + void _sendData(T data) { + _subscription._add(data); + } + + void _sendError(Object error, StackTrace stackTrace) { + _subscription._addError(error, stackTrace); + } + + void _sendDone() { + _subscription._close(); + } +} + +abstract class _AsyncStreamControllerDispatch + implements _StreamController { + void _sendData(T data) { + _subscription._addPending(new _DelayedData(data)); + } + + void _sendError(Object error, StackTrace stackTrace) { + _subscription._addPending(new _DelayedError(error, stackTrace)); + } + + void _sendDone() { + _subscription._addPending(const _DelayedDone()); + } +} + +// TODO(lrn): Use common superclass for callback-controllers when VM supports +// constructors in mixin superclasses. + +class _AsyncStreamController = _StreamController + with _AsyncStreamControllerDispatch; + +class _SyncStreamController = _StreamController + with _SyncStreamControllerDispatch; + +typedef _NotificationHandler(); + +void _runGuarded(_NotificationHandler notificationHandler) { + if (notificationHandler == null) return; + try { + notificationHandler(); + } catch (e, s) { + Zone.current.handleUncaughtError(e, s); + } +} + +class _ControllerStream extends _StreamImpl { + _StreamControllerLifecycle _controller; + + _ControllerStream(this._controller); + + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) => + _controller._subscribe(onData, onError, onDone, cancelOnError); + + // Override == and hashCode so that new streams returned by the same + // controller are considered equal. The controller returns a new stream + // each time it's queried, but doesn't have to cache the result. + + int get hashCode => _controller.hashCode ^ 0x35323532; + + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other is! _ControllerStream) return false; + _ControllerStream otherStream = other; + return identical(otherStream._controller, this._controller); + } +} + +class _ControllerSubscription extends _BufferingStreamSubscription { + final _StreamControllerLifecycle _controller; + + _ControllerSubscription(this._controller, void onData(T data), + Function onError, void onDone(), bool cancelOnError) + : super(onData, onError, onDone, cancelOnError); + + Future _onCancel() { + return _controller._recordCancel(this); + } + + void _onPause() { + _controller._recordPause(this); + } + + void _onResume() { + _controller._recordResume(this); + } +} + +/** A class that exposes only the [StreamSink] interface of an object. */ +class _StreamSinkWrapper implements StreamSink { + final StreamController _target; + _StreamSinkWrapper(this._target); + void add(T data) { + _target.add(data); + } + + void addError(Object error, [StackTrace stackTrace]) { + _target.addError(error, stackTrace); + } + + Future close() => _target.close(); + + Future addStream(Stream source) => _target.addStream(source); + + Future get done => _target.done; +} + +/** + * Object containing the state used to handle [StreamController.addStream]. + */ +class _AddStreamState { + // [_Future] returned by call to addStream. + final _Future addStreamFuture; + + // Subscription on stream argument to addStream. + final StreamSubscription addSubscription; + + _AddStreamState( + _EventSink controller, Stream source, bool cancelOnError) + : addStreamFuture = new _Future(), + addSubscription = source.listen(controller._add, + onError: cancelOnError + ? makeErrorHandler(controller) + : controller._addError, + onDone: controller._close, + cancelOnError: cancelOnError); + + static makeErrorHandler(_EventSink controller) => (e, StackTrace s) { + controller._addError(e, s); + controller._close(); + }; + + void pause() { + addSubscription.pause(); + } + + void resume() { + addSubscription.resume(); + } + + /** + * Stop adding the stream. + * + * Complete the future returned by `StreamController.addStream` when + * the cancel is complete. + * + * Return a future if the cancel takes time, otherwise return `null`. + */ + Future cancel() { + var cancel = addSubscription.cancel(); + if (cancel == null) { + addStreamFuture._asyncComplete(null); + return null; + } + return cancel.whenComplete(() { + addStreamFuture._asyncComplete(null); + }); + } + + void complete() { + addStreamFuture._asyncComplete(null); + } +} + +class _StreamControllerAddStreamState extends _AddStreamState { + // The subscription or pending data of a _StreamController. + // Stored here because we reuse the `_varData` field in the _StreamController + // to store this state object. + var varData; + + _StreamControllerAddStreamState(_StreamController controller, this.varData, + Stream source, bool cancelOnError) + : super(controller, source, cancelOnError) { + if (controller.isPaused) { + addSubscription.pause(); + } + } +} +NN<G:GQ#36$-A@5KK>9L;7AQPH,NPD>+OLOGGHOKKN:?QE@HIF0I4?KKG.)D%,$NQJ*&>DFBB#-=BP"+>BP#-?B)(QEBA"9G;JI.IBG88OFLEM2'BMFD(8QFD(PFGCMMEDG5:<??@CH=#GAF6GJI"G9AKEM!OM+KLIKLNLMN&H-N=AKFJ=/>ON?HQJIJ.O,I2,N28%K2/$Q;G)9F0C9K#IA1>?P?E=/920= %@F>*F#/%9/"L0+"BK PKN"/ "8:G">8%"H ' 3%=?JG)EQE>" N5;6I"= +K0=*. :>;>0F901&:9E5N'7,6+ =+,4-'ABFGJC9#-3+AK3A;7,$%J7"$9)%C#L.!3,F)9#/('+H$ GH+,$,*F>Q!Q)3Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/stream_impl.dart}>// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +/** Abstract and private interface for a place to put events. */ +abstract class _EventSink { + void _add(T data); + void _addError(Object error, StackTrace stackTrace); + void _close(); +} + +/** + * Abstract and private interface for a place to send events. + * + * Used by event buffering to finally dispatch the pending event, where + * [_EventSink] is where the event first enters the stream subscription, + * and may yet be buffered. + */ +abstract class _EventDispatch { + void _sendData(T data); + void _sendError(Object error, StackTrace stackTrace); + void _sendDone(); +} + +/** + * Default implementation of stream subscription of buffering events. + * + * The only public methods are those of [StreamSubscription], so instances of + * [_BufferingStreamSubscription] can be returned directly as a + * [StreamSubscription] without exposing internal functionality. + * + * The [StreamController] is a public facing version of [Stream] and this class, + * with some methods made public. + * + * The user interface of [_BufferingStreamSubscription] are the following + * methods: + * + * * [_add]: Add a data event to the stream. + * * [_addError]: Add an error event to the stream. + * * [_close]: Request to close the stream. + * * [_onCancel]: Called when the subscription will provide no more events, + * either due to being actively canceled, or after sending a done event. + * * [_onPause]: Called when the subscription wants the event source to pause. + * * [_onResume]: Called when allowing new events after a pause. + * + * The user should not add new events when the subscription requests a paused, + * but if it happens anyway, the subscription will enqueue the events just as + * when new events arrive while still firing an old event. + */ +class _BufferingStreamSubscription + implements StreamSubscription, _EventSink, _EventDispatch { + /** The `cancelOnError` flag from the `listen` call. */ + static const int _STATE_CANCEL_ON_ERROR = 1; + /** + * Whether the "done" event has been received. + * No further events are accepted after this. + */ + static const int _STATE_CLOSED = 2; + /** + * Set if the input has been asked not to send events. + * + * This is not the same as being paused, since the input will remain paused + * after a call to [resume] if there are pending events. + */ + static const int _STATE_INPUT_PAUSED = 4; + /** + * Whether the subscription has been canceled. + * + * Set by calling [cancel], or by handling a "done" event, or an "error" event + * when `cancelOnError` is true. + */ + static const int _STATE_CANCELED = 8; + /** + * Set when either: + * + * * an error is sent, and [cancelOnError] is true, or + * * a done event is sent. + * + * If the subscription is canceled while _STATE_WAIT_FOR_CANCEL is set, the + * state is unset, and no further events must be delivered. + */ + static const int _STATE_WAIT_FOR_CANCEL = 16; + static const int _STATE_IN_CALLBACK = 32; + static const int _STATE_HAS_PENDING = 64; + static const int _STATE_PAUSE_COUNT = 128; + + /* Event handlers provided in constructor. */ + _DataHandler _onData; + Function _onError; + _DoneHandler _onDone; + final Zone _zone = Zone.current; + + /** Bit vector based on state-constants above. */ + int _state; + + // TODO(floitsch): reuse another field + /** The future [_onCancel] may return. */ + Future _cancelFuture; + + /** + * Queue of pending events. + * + * Is created when necessary, or set in constructor for preconfigured events. + */ + _PendingEvents _pending; + + _BufferingStreamSubscription( + void onData(T data), Function onError, void onDone(), bool cancelOnError) + : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0) { + this.onData(onData); + this.onError(onError); + this.onDone(onDone); + } + + /** + * Sets the subscription's pending events object. + * + * This can only be done once. The pending events object is used for the + * rest of the subscription's life cycle. + */ + void _setPendingEvents(_PendingEvents pendingEvents) { + assert(_pending == null); + if (pendingEvents == null) return; + _pending = pendingEvents; + if (!pendingEvents.isEmpty) { + _state |= _STATE_HAS_PENDING; + _pending.schedule(this); + } + } + + // StreamSubscription interface. + + void onData(void handleData(T event)) { + if (handleData == null) handleData = _nullDataHandler; + // TODO(floitsch): the return type should be 'void', and the type + // should be inferred. + _onData = _zone.registerUnaryCallback(handleData); + } + + void onError(Function handleError) { + if (handleError == null) handleError = _nullErrorHandler; + if (handleError is void Function(Object, StackTrace)) { + _onError = _zone + .registerBinaryCallback(handleError); + } else if (handleError is void Function(Object)) { + _onError = _zone.registerUnaryCallback(handleError); + } else { + throw new ArgumentError("handleError callback must take either an Object " + "(the error), or both an Object (the error) and a StackTrace."); + } + } + + void onDone(void handleDone()) { + if (handleDone == null) handleDone = _nullDoneHandler; + _onDone = _zone.registerCallback(handleDone); + } + + void pause([Future resumeSignal]) { + if (_isCanceled) return; + bool wasPaused = _isPaused; + bool wasInputPaused = _isInputPaused; + // Increment pause count and mark input paused (if it isn't already). + _state = (_state + _STATE_PAUSE_COUNT) | _STATE_INPUT_PAUSED; + if (resumeSignal != null) resumeSignal.whenComplete(resume); + if (!wasPaused && _pending != null) _pending.cancelSchedule(); + if (!wasInputPaused && !_inCallback) _guardCallback(_onPause); + } + + void resume() { + if (_isCanceled) return; + if (_isPaused) { + _decrementPauseCount(); + if (!_isPaused) { + if (_hasPending && !_pending.isEmpty) { + // Input is still paused. + _pending.schedule(this); + } else { + assert(_mayResumeInput); + _state &= ~_STATE_INPUT_PAUSED; + if (!_inCallback) _guardCallback(_onResume); + } + } + } + } + + Future cancel() { + // The user doesn't want to receive any further events. If there is an + // error or done event pending (waiting for the cancel to be done) discard + // that event. + _state &= ~_STATE_WAIT_FOR_CANCEL; + if (!_isCanceled) { + _cancel(); + } + return _cancelFuture ?? Future._nullFuture; + } + + Future asFuture([E futureValue]) { + _Future result = new _Future(); + + // Overwrite the onDone and onError handlers. + _onDone = () { + result._complete(futureValue); + }; + _onError = (error, stackTrace) { + Future cancelFuture = cancel(); + if (!identical(cancelFuture, Future._nullFuture)) { + cancelFuture.whenComplete(() { + result._completeError(error, stackTrace); + }); + } else { + result._completeError(error, stackTrace); + } + }; + + return result; + } + + // State management. + + bool get _isInputPaused => (_state & _STATE_INPUT_PAUSED) != 0; + bool get _isClosed => (_state & _STATE_CLOSED) != 0; + bool get _isCanceled => (_state & _STATE_CANCELED) != 0; + bool get _waitsForCancel => (_state & _STATE_WAIT_FOR_CANCEL) != 0; + bool get _inCallback => (_state & _STATE_IN_CALLBACK) != 0; + bool get _hasPending => (_state & _STATE_HAS_PENDING) != 0; + bool get _isPaused => _state >= _STATE_PAUSE_COUNT; + bool get _canFire => _state < _STATE_IN_CALLBACK; + bool get _mayResumeInput => + !_isPaused && (_pending == null || _pending.isEmpty); + bool get _cancelOnError => (_state & _STATE_CANCEL_ON_ERROR) != 0; + + bool get isPaused => _isPaused; + + void _cancel() { + _state |= _STATE_CANCELED; + if (_hasPending) { + _pending.cancelSchedule(); + } + if (!_inCallback) _pending = null; + _cancelFuture = _onCancel(); + } + + /** + * Decrements the pause count. + * + * Does not automatically unpause the input (call [_onResume]) when + * the pause count reaches zero. This is handled elsewhere, and only + * if there are no pending events buffered. + */ + void _decrementPauseCount() { + assert(_isPaused); + _state -= _STATE_PAUSE_COUNT; + } + + // _EventSink interface. + + void _add(T data) { + assert(!_isClosed); + if (_isCanceled) return; + if (_canFire) { + _sendData(data); + } else { + _addPending(new _DelayedData(data)); + } + } + + void _addError(Object error, StackTrace stackTrace) { + if (_isCanceled) return; + if (_canFire) { + _sendError(error, stackTrace); // Reports cancel after sending. + } else { + _addPending(new _DelayedError(error, stackTrace)); + } + } + + void _close() { + assert(!_isClosed); + if (_isCanceled) return; + _state |= _STATE_CLOSED; + if (_canFire) { + _sendDone(); + } else { + _addPending(const _DelayedDone()); + } + } + + // Hooks called when the input is paused, unpaused or canceled. + // These must not throw. If overwritten to call user code, include suitable + // try/catch wrapping and send any errors to + // [_Zone.current.handleUncaughtError]. + void _onPause() { + assert(_isInputPaused); + } + + void _onResume() { + assert(!_isInputPaused); + } + + Future _onCancel() { + assert(_isCanceled); + return null; + } + + // Handle pending events. + + /** + * Add a pending event. + * + * If the subscription is not paused, this also schedules a firing + * of pending events later (if necessary). + */ + void _addPending(_DelayedEvent event) { + _StreamImplEvents pending = _pending; + if (_pending == null) { + pending = _pending = new _StreamImplEvents(); + } + pending.add(event); + if (!_hasPending) { + _state |= _STATE_HAS_PENDING; + if (!_isPaused) { + _pending.schedule(this); + } + } + } + + /* _EventDispatch interface. */ + + void _sendData(T data) { + assert(!_isCanceled); + assert(!_isPaused); + assert(!_inCallback); + bool wasInputPaused = _isInputPaused; + _state |= _STATE_IN_CALLBACK; + _zone.runUnaryGuarded(_onData, data); + _state &= ~_STATE_IN_CALLBACK; + _checkState(wasInputPaused); + } + + void _sendError(Object error, StackTrace stackTrace) { + assert(!_isCanceled); + assert(!_isPaused); + assert(!_inCallback); + bool wasInputPaused = _isInputPaused; + + void sendError() { + // If the subscription has been canceled while waiting for the cancel + // future to finish we must not report the error. + if (_isCanceled && !_waitsForCancel) return; + _state |= _STATE_IN_CALLBACK; + // TODO(floitsch): this dynamic should be 'void'. + var onError = _onError; + if (onError is void Function(Object, StackTrace)) { + _zone.runBinaryGuarded(onError, error, stackTrace); + } else { + assert(_onError is void Function(Object)); + _zone.runUnaryGuarded(_onError, error); + } + _state &= ~_STATE_IN_CALLBACK; + } + + if (_cancelOnError) { + _state |= _STATE_WAIT_FOR_CANCEL; + _cancel(); + if (_cancelFuture is Future && + !identical(_cancelFuture, Future._nullFuture)) { + _cancelFuture.whenComplete(sendError); + } else { + sendError(); + } + } else { + sendError(); + // Only check state if not cancelOnError. + _checkState(wasInputPaused); + } + } + + void _sendDone() { + assert(!_isCanceled); + assert(!_isPaused); + assert(!_inCallback); + + void sendDone() { + // If the subscription has been canceled while waiting for the cancel + // future to finish we must not report the done event. + if (!_waitsForCancel) return; + _state |= (_STATE_CANCELED | _STATE_CLOSED | _STATE_IN_CALLBACK); + _zone.runGuarded(_onDone); + _state &= ~_STATE_IN_CALLBACK; + } + + _cancel(); + _state |= _STATE_WAIT_FOR_CANCEL; + if (_cancelFuture is Future && + !identical(_cancelFuture, Future._nullFuture)) { + _cancelFuture.whenComplete(sendDone); + } else { + sendDone(); + } + } + + /** + * Call a hook function. + * + * The call is properly wrapped in code to avoid other callbacks + * during the call, and it checks for state changes after the call + * that should cause further callbacks. + */ + void _guardCallback(void callback()) { + assert(!_inCallback); + bool wasInputPaused = _isInputPaused; + _state |= _STATE_IN_CALLBACK; + callback(); + _state &= ~_STATE_IN_CALLBACK; + _checkState(wasInputPaused); + } + + /** + * Check if the input needs to be informed of state changes. + * + * State changes are pausing, resuming and canceling. + * + * After canceling, no further callbacks will happen. + * + * The cancel callback is called after a user cancel, or after + * the final done event is sent. + */ + void _checkState(bool wasInputPaused) { + assert(!_inCallback); + if (_hasPending && _pending.isEmpty) { + _state &= ~_STATE_HAS_PENDING; + if (_isInputPaused && _mayResumeInput) { + _state &= ~_STATE_INPUT_PAUSED; + } + } + // If the state changes during a callback, we immediately + // make a new state-change callback. Loop until the state didn't change. + while (true) { + if (_isCanceled) { + _pending = null; + return; + } + bool isInputPaused = _isInputPaused; + if (wasInputPaused == isInputPaused) break; + _state ^= _STATE_IN_CALLBACK; + if (isInputPaused) { + _onPause(); + } else { + _onResume(); + } + _state &= ~_STATE_IN_CALLBACK; + wasInputPaused = isInputPaused; + } + if (_hasPending && !_isPaused) { + _pending.schedule(this); + } + } +} + +// ------------------------------------------------------------------- +// Common base class for single and multi-subscription streams. +// ------------------------------------------------------------------- +abstract class _StreamImpl extends Stream { + // ------------------------------------------------------------------ + // Stream interface. + + StreamSubscription listen(void onData(T data), + {Function onError, void onDone(), bool cancelOnError}) { + cancelOnError = identical(true, cancelOnError); + StreamSubscription subscription = + _createSubscription(onData, onError, onDone, cancelOnError); + _onListen(subscription); + return subscription; + } + + // ------------------------------------------------------------------- + /** Create a subscription object. Called by [subcribe]. */ + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) { + return new _BufferingStreamSubscription( + onData, onError, onDone, cancelOnError); + } + + /** Hook called when the subscription has been created. */ + void _onListen(StreamSubscription subscription) {} +} + +typedef _PendingEvents _EventGenerator(); + +/** Stream that generates its own events. */ +class _GeneratedStreamImpl extends _StreamImpl { + final _EventGenerator _pending; + bool _isUsed = false; + /** + * Initializes the stream to have only the events provided by a + * [_PendingEvents]. + * + * A new [_PendingEvents] must be generated for each listen. + */ + _GeneratedStreamImpl(this._pending); + + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) { + if (_isUsed) throw new StateError("Stream has already been listened to."); + _isUsed = true; + return new _BufferingStreamSubscription( + onData, onError, onDone, cancelOnError) + .._setPendingEvents(_pending()); + } +} + +/** Pending events object that gets its events from an [Iterable]. */ +class _IterablePendingEvents extends _PendingEvents { + // The iterator providing data for data events. + // Set to null when iteration has completed. + Iterator _iterator; + + _IterablePendingEvents(Iterable data) : _iterator = data.iterator; + + bool get isEmpty => _iterator == null; + + void handleNext(_EventDispatch dispatch) { + if (_iterator == null) { + throw new StateError("No events pending."); + } + // Send one event per call to moveNext. + // If moveNext returns true, send the current element as data. + // If moveNext returns false, send a done event and clear the _iterator. + // If moveNext throws an error, send an error and clear the _iterator. + // After an error, no further events will be sent. + bool isDone; + try { + isDone = !_iterator.moveNext(); + } catch (e, s) { + _iterator = null; + dispatch._sendError(e, s); + return; + } + if (!isDone) { + dispatch._sendData(_iterator.current); + } else { + _iterator = null; + dispatch._sendDone(); + } + } + + void clear() { + if (isScheduled) cancelSchedule(); + _iterator = null; + } +} + +// Internal helpers. + +// Types of the different handlers on a stream. Types used to type fields. +typedef void _DataHandler(T value); +typedef void _DoneHandler(); + +/** Default data handler, does nothing. */ +void _nullDataHandler(Object value) {} + +/** Default error handler, reports the error to the current zone's handler. */ +void _nullErrorHandler(Object error, [StackTrace stackTrace]) { + Zone.current.handleUncaughtError(error, stackTrace); +} + +/** Default done handler, does nothing. */ +void _nullDoneHandler() {} + +/** A delayed event on a buffering stream subscription. */ +abstract class _DelayedEvent { + /** Added as a linked list on the [StreamController]. */ + _DelayedEvent next; + /** Execute the delayed event on the [StreamController]. */ + void perform(_EventDispatch dispatch); +} + +/** A delayed data event. */ +class _DelayedData extends _DelayedEvent { + final T value; + _DelayedData(this.value); + void perform(_EventDispatch dispatch) { + dispatch._sendData(value); + } +} + +/** A delayed error event. */ +class _DelayedError extends _DelayedEvent { + final error; + final StackTrace stackTrace; + + _DelayedError(this.error, this.stackTrace); + void perform(_EventDispatch dispatch) { + dispatch._sendError(error, stackTrace); + } +} + +/** A delayed done event. */ +class _DelayedDone implements _DelayedEvent { + const _DelayedDone(); + void perform(_EventDispatch dispatch) { + dispatch._sendDone(); + } + + _DelayedEvent get next => null; + + void set next(_DelayedEvent _) { + throw new StateError("No events after a done."); + } +} + +/** Superclass for provider of pending events. */ +abstract class _PendingEvents { + // No async event has been scheduled. + static const int _STATE_UNSCHEDULED = 0; + // An async event has been scheduled to run a function. + static const int _STATE_SCHEDULED = 1; + // An async event has been scheduled, but it will do nothing when it runs. + // Async events can't be preempted. + static const int _STATE_CANCELED = 3; + + /** + * State of being scheduled. + * + * Set to [_STATE_SCHEDULED] when pending events are scheduled for + * async dispatch. Since we can't cancel a [scheduleMicrotask] call, if + * scheduling is "canceled", the _state is simply set to [_STATE_CANCELED] + * which will make the async code do nothing except resetting [_state]. + * + * If events are scheduled while the state is [_STATE_CANCELED], it is + * merely switched back to [_STATE_SCHEDULED], but no new call to + * [scheduleMicrotask] is performed. + */ + int _state = _STATE_UNSCHEDULED; + + bool get isEmpty; + + bool get isScheduled => _state == _STATE_SCHEDULED; + bool get _eventScheduled => _state >= _STATE_SCHEDULED; + + /** + * Schedule an event to run later. + * + * If called more than once, it should be called with the same dispatch as + * argument each time. It may reuse an earlier argument in some cases. + */ + void schedule(_EventDispatch dispatch) { + if (isScheduled) return; + assert(!isEmpty); + if (_eventScheduled) { + assert(_state == _STATE_CANCELED); + _state = _STATE_SCHEDULED; + return; + } + scheduleMicrotask(() { + int oldState = _state; + _state = _STATE_UNSCHEDULED; + if (oldState == _STATE_CANCELED) return; + handleNext(dispatch); + }); + _state = _STATE_SCHEDULED; + } + + void cancelSchedule() { + if (isScheduled) _state = _STATE_CANCELED; + } + + void handleNext(_EventDispatch dispatch); + + /** Throw away any pending events and cancel scheduled events. */ + void clear(); +} + +/** Class holding pending events for a [_StreamImpl]. */ +class _StreamImplEvents extends _PendingEvents { + /// Single linked list of [_DelayedEvent] objects. + _DelayedEvent firstPendingEvent = null; + + /// Last element in the list of pending events. New events are added after it. + _DelayedEvent lastPendingEvent = null; + + bool get isEmpty => lastPendingEvent == null; + + void add(_DelayedEvent event) { + if (lastPendingEvent == null) { + firstPendingEvent = lastPendingEvent = event; + } else { + lastPendingEvent = lastPendingEvent.next = event; + } + } + + void handleNext(_EventDispatch dispatch) { + assert(!isScheduled); + _DelayedEvent event = firstPendingEvent; + firstPendingEvent = event.next; + if (firstPendingEvent == null) { + lastPendingEvent = null; + } + event.perform(dispatch); + } + + void clear() { + if (isScheduled) cancelSchedule(); + firstPendingEvent = lastPendingEvent = null; + } +} + +typedef void _BroadcastCallback(StreamSubscription subscription); + +/** + * Done subscription that will send one done event as soon as possible. + */ +class _DoneStreamSubscription implements StreamSubscription { + static const int _DONE_SENT = 1; + static const int _SCHEDULED = 2; + static const int _PAUSED = 4; + + final Zone _zone; + int _state = 0; + _DoneHandler _onDone; + + _DoneStreamSubscription(this._onDone) : _zone = Zone.current { + _schedule(); + } + + bool get _isSent => (_state & _DONE_SENT) != 0; + bool get _isScheduled => (_state & _SCHEDULED) != 0; + bool get isPaused => _state >= _PAUSED; + + void _schedule() { + if (_isScheduled) return; + _zone.scheduleMicrotask(_sendDone); + _state |= _SCHEDULED; + } + + void onData(void handleData(T data)) {} + void onError(Function handleError) {} + void onDone(void handleDone()) { + _onDone = handleDone; + } + + void pause([Future resumeSignal]) { + _state += _PAUSED; + if (resumeSignal != null) resumeSignal.whenComplete(resume); + } + + void resume() { + if (isPaused) { + _state -= _PAUSED; + if (!isPaused && !_isSent) { + _schedule(); + } + } + } + + Future cancel() => Future._nullFuture; + + Future asFuture([E futureValue]) { + _Future result = new _Future(); + _onDone = () { + result._completeWithValue(null); + }; + return result; + } + + void _sendDone() { + _state &= ~_SCHEDULED; + if (isPaused) return; + _state |= _DONE_SENT; + if (_onDone != null) _zone.runGuarded(_onDone); + } +} + +class _AsBroadcastStream extends Stream { + final Stream _source; + final _BroadcastCallback _onListenHandler; + final _BroadcastCallback _onCancelHandler; + final Zone _zone; + + _AsBroadcastStreamController _controller; + StreamSubscription _subscription; + + _AsBroadcastStream( + this._source, + void onListenHandler(StreamSubscription subscription), + void onCancelHandler(StreamSubscription subscription)) + // TODO(floitsch): the return type should be void and should be + // inferred. + : _onListenHandler = Zone.current + .registerUnaryCallback>( + onListenHandler), + _onCancelHandler = Zone.current + .registerUnaryCallback>( + onCancelHandler), + _zone = Zone.current { + _controller = new _AsBroadcastStreamController(_onListen, _onCancel); + } + + bool get isBroadcast => true; + + StreamSubscription listen(void onData(T data), + {Function onError, void onDone(), bool cancelOnError}) { + if (_controller == null || _controller.isClosed) { + // Return a dummy subscription backed by nothing, since + // it will only ever send one done event. + return new _DoneStreamSubscription(onDone); + } + if (_subscription == null) { + _subscription = _source.listen(_controller.add, + onError: _controller.addError, onDone: _controller.close); + } + cancelOnError = identical(true, cancelOnError); + return _controller._subscribe(onData, onError, onDone, cancelOnError); + } + + void _onCancel() { + bool shutdown = (_controller == null) || _controller.isClosed; + if (_onCancelHandler != null) { + _zone.runUnary( + _onCancelHandler, new _BroadcastSubscriptionWrapper(this)); + } + if (shutdown) { + if (_subscription != null) { + _subscription.cancel(); + _subscription = null; + } + } + } + + void _onListen() { + if (_onListenHandler != null) { + _zone.runUnary( + _onListenHandler, new _BroadcastSubscriptionWrapper(this)); + } + } + + // Methods called from _BroadcastSubscriptionWrapper. + void _cancelSubscription() { + if (_subscription == null) return; + // Called by [_controller] when it has no subscribers left. + StreamSubscription subscription = _subscription; + _subscription = null; + _controller = null; // Marks the stream as no longer listenable. + subscription.cancel(); + } + + void _pauseSubscription(Future resumeSignal) { + if (_subscription == null) return; + _subscription.pause(resumeSignal); + } + + void _resumeSubscription() { + if (_subscription == null) return; + _subscription.resume(); + } + + bool get _isSubscriptionPaused { + if (_subscription == null) return false; + return _subscription.isPaused; + } +} + +/** + * Wrapper for subscription that disallows changing handlers. + */ +class _BroadcastSubscriptionWrapper implements StreamSubscription { + final _AsBroadcastStream _stream; + + _BroadcastSubscriptionWrapper(this._stream); + + void onData(void handleData(T data)) { + throw new UnsupportedError( + "Cannot change handlers of asBroadcastStream source subscription."); + } + + void onError(Function handleError) { + throw new UnsupportedError( + "Cannot change handlers of asBroadcastStream source subscription."); + } + + void onDone(void handleDone()) { + throw new UnsupportedError( + "Cannot change handlers of asBroadcastStream source subscription."); + } + + void pause([Future resumeSignal]) { + _stream._pauseSubscription(resumeSignal); + } + + void resume() { + _stream._resumeSubscription(); + } + + Future cancel() { + _stream._cancelSubscription(); + return Future._nullFuture; + } + + bool get isPaused { + return _stream._isSubscriptionPaused; + } + + Future asFuture([E futureValue]) { + throw new UnsupportedError( + "Cannot change handlers of asBroadcastStream source subscription."); + } +} + +/** + * Simple implementation of [StreamIterator]. + * + * Pauses the stream between calls to [moveNext]. + */ +class _StreamIterator implements StreamIterator { + // The stream iterator is always in one of four states. + // The value of the [_stateData] field depends on the state. + // + // When `_subscription == null` and `_stateData != null`: + // The stream iterator has been created, but [moveNext] has not been called + // yet. The [_stateData] field contains the stream to listen to on the first + // call to [moveNext] and [current] returns `null`. + // + // When `_subscription != null` and `!_isPaused`: + // The user has called [moveNext] and the iterator is waiting for the next + // event. The [_stateData] field contains the [_Future] returned by the + // [_moveNext] call and [current] returns `null.` + // + // When `_subscription != null` and `_isPaused`: + // The most recent call to [moveNext] has completed with a `true` value + // and [current] provides the value of the data event. + // The [_stateData] field contains the [current] value. + // + // When `_subscription == null` and `_stateData == null`: + // The stream has completed or been canceled using [cancel]. + // The stream completes on either a done event or an error event. + // The last call to [moveNext] has completed with `false` and [current] + // returns `null`. + + /// Subscription being listened to. + /// + /// Set to `null` when the stream subscription is done or canceled. + StreamSubscription _subscription; + + /// Data value depending on the current state. + /// + /// Before first call to [moveNext]: The stream to listen to. + /// + /// After calling [moveNext] but before the returned future completes: + /// The returned future. + /// + /// After calling [moveNext] and the returned future has completed + /// with `true`: The value of [current]. + /// + /// After calling [moveNext] and the returned future has completed + /// with `false`, or after calling [cancel]: `null`. + Object _stateData; + + /// Whether the iterator is between calls to `moveNext`. + /// This will usually cause the [_subscription] to be paused, but as an + /// optimization, we only pause after the [moveNext] future has been + /// completed. + bool _isPaused = false; + + _StreamIterator(final Stream stream) : _stateData = stream; + + T get current { + if (_subscription != null && _isPaused) { + return _stateData; + } + return null; + } + + Future moveNext() { + if (_subscription != null) { + if (_isPaused) { + var future = new _Future(); + _stateData = future; + _isPaused = false; + _subscription.resume(); + return future; + } + throw new StateError("Already waiting for next."); + } + return _initializeOrDone(); + } + + /// Called if there is no active subscription when [moveNext] is called. + /// + /// Either starts listening on the stream if this is the first call to + /// [moveNext], or returns a `false` future because the stream has already + /// ended. + Future _initializeOrDone() { + assert(_subscription == null); + var stateData = _stateData; + if (stateData != null) { + Stream stream = stateData; + _subscription = stream.listen(_onData, + onError: _onError, onDone: _onDone, cancelOnError: true); + var future = new _Future(); + _stateData = future; + return future; + } + return Future._falseFuture; + } + + Future cancel() { + StreamSubscription subscription = _subscription; + Object stateData = _stateData; + _stateData = null; + if (subscription != null) { + _subscription = null; + if (!_isPaused) { + _Future future = stateData; + future._asyncComplete(false); + } + return subscription.cancel(); + } + return Future._nullFuture; + } + + void _onData(T data) { + assert(_subscription != null && !_isPaused); + _Future moveNextFuture = _stateData; + _stateData = data; + _isPaused = true; + moveNextFuture._complete(true); + if (_subscription != null && _isPaused) _subscription.pause(); + } + + void _onError(Object error, [StackTrace stackTrace]) { + assert(_subscription != null && !_isPaused); + _Future moveNextFuture = _stateData; + _subscription = null; + _stateData = null; + moveNextFuture._completeError(error, stackTrace); + } + + void _onDone() { + assert(_subscription != null && !_isPaused); + _Future moveNextFuture = _stateData; + _subscription = null; + _stateData = null; + moveNextFuture._complete(false); + } +} + +/** An empty broadcast stream, sending a done event as soon as possible. */ +class _EmptyStream extends Stream { + const _EmptyStream() : super._internal(); + bool get isBroadcast => true; + StreamSubscription listen(void onData(T data), + {Function onError, void onDone(), bool cancelOnError}) { + return new _DoneStreamSubscription(onDone); + } +} +"NN<A7>HI#8FN@AQ"J -4,LMOAON;&I:/10&9N;,1Q#(;N>0,,-0#4),P P@4K,<'"$#*;FC'><M7L QK#;2& *JBACC0$##*7 +KO'0+*2%%&:'4 2B7;F>>64M+2$%&%G@G2H4?4)EI=A=01=50-7%B?'A=O00'F<2/H)02,CMK7 +&!- 'K'+'O@7+;";>,1-,.*,.*"#52#(+:)M&(EJMJID'#6:%MI.)!#///D975*Q)0"$4 80-$%'1HHD## A27*(*(#&A#)+*'4000/'@@F(D"(D"M 4?7>05!6E4KC$I# $I8'@5E1'''#-#>J$/) M' M# M&.##*+ M.28:?( + T userCode(), onSuccess(T value), onError(error, StackTrace stackTrace)) { + try { + onSuccess(userCode()); + } catch (e, s) { + AsyncError replacement = Zone.current.errorCallback(e, s); + if (replacement == null) { + onError(e, s); + } else { + var error = _nonNullError(replacement.error); + var stackTrace = replacement.stackTrace; + onError(error, stackTrace); + } + } +} + +/** Helper function to cancel a subscription and wait for the potential future, + before completing with an error. */ +void _cancelAndError(StreamSubscription subscription, _Future future, error, + StackTrace stackTrace) { + var cancelFuture = subscription.cancel(); + if (cancelFuture is Future && !identical(cancelFuture, Future._nullFuture)) { + cancelFuture.whenComplete(() => future._completeError(error, stackTrace)); + } else { + future._completeError(error, stackTrace); + } +} + +void _cancelAndErrorWithReplacement(StreamSubscription subscription, + _Future future, error, StackTrace stackTrace) { + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + _cancelAndError(subscription, future, error, stackTrace); +} + +typedef void _ErrorCallback(error, StackTrace stackTrace); + +/** Helper function to make an onError argument to [_runUserCode]. */ +_ErrorCallback _cancelAndErrorClosure( + StreamSubscription subscription, _Future future) { + return (error, StackTrace stackTrace) { + _cancelAndError(subscription, future, error, stackTrace); + }; +} + +/** Helper function to cancel a subscription and wait for the potential future, + before completing with a value. */ +void _cancelAndValue(StreamSubscription subscription, _Future future, value) { + var cancelFuture = subscription.cancel(); + if (cancelFuture is Future && !identical(cancelFuture, Future._nullFuture)) { + cancelFuture.whenComplete(() => future._complete(value)); + } else { + future._complete(value); + } +} + +/** + * A [Stream] that forwards subscriptions to another stream. + * + * This stream implements [Stream], but forwards all subscriptions + * to an underlying stream, and wraps the returned subscription to + * modify the events on the way. + * + * This class is intended for internal use only. + */ +abstract class _ForwardingStream extends Stream { + final Stream _source; + + _ForwardingStream(this._source); + + bool get isBroadcast => _source.isBroadcast; + + StreamSubscription listen(void onData(T value), + {Function onError, void onDone(), bool cancelOnError}) { + cancelOnError = identical(true, cancelOnError); + return _createSubscription(onData, onError, onDone, cancelOnError); + } + + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) { + return new _ForwardingStreamSubscription( + this, onData, onError, onDone, cancelOnError); + } + + // Override the following methods in subclasses to change the behavior. + + void _handleData(S data, _EventSink sink) { + sink._add(data as Object); + } + + void _handleError(error, StackTrace stackTrace, _EventSink sink) { + sink._addError(error, stackTrace); + } + + void _handleDone(_EventSink sink) { + sink._close(); + } +} + +/** + * Abstract superclass for subscriptions that forward to other subscriptions. + */ +class _ForwardingStreamSubscription + extends _BufferingStreamSubscription { + final _ForwardingStream _stream; + + StreamSubscription _subscription; + + _ForwardingStreamSubscription(this._stream, void onData(T data), + Function onError, void onDone(), bool cancelOnError) + : super(onData, onError, onDone, cancelOnError) { + _subscription = _stream._source + .listen(_handleData, onError: _handleError, onDone: _handleDone); + } + + // _StreamSink interface. + // Transformers sending more than one event have no way to know if the stream + // is canceled or closed after the first, so we just ignore remaining events. + + void _add(T data) { + if (_isClosed) return; + super._add(data); + } + + void _addError(Object error, StackTrace stackTrace) { + if (_isClosed) return; + super._addError(error, stackTrace); + } + + // StreamSubscription callbacks. + + void _onPause() { + if (_subscription == null) return; + _subscription.pause(); + } + + void _onResume() { + if (_subscription == null) return; + _subscription.resume(); + } + + Future _onCancel() { + if (_subscription != null) { + StreamSubscription subscription = _subscription; + _subscription = null; + return subscription.cancel(); + } + return null; + } + + // Methods used as listener on source subscription. + + void _handleData(S data) { + _stream._handleData(data, this); + } + + void _handleError(error, StackTrace stackTrace) { + _stream._handleError(error, stackTrace, this); + } + + void _handleDone() { + _stream._handleDone(this); + } +} + +// ------------------------------------------------------------------- +// Stream transformers used by the default Stream implementation. +// ------------------------------------------------------------------- + +typedef bool _Predicate(T value); + +void _addErrorWithReplacement(_EventSink sink, error, stackTrace) { + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + sink._addError(error, stackTrace); +} + +class _WhereStream extends _ForwardingStream { + final _Predicate _test; + + _WhereStream(Stream source, bool test(T value)) + : _test = test, + super(source); + + void _handleData(T inputEvent, _EventSink sink) { + bool satisfies; + try { + satisfies = _test(inputEvent); + } catch (e, s) { + _addErrorWithReplacement(sink, e, s); + return; + } + if (satisfies) { + sink._add(inputEvent); + } + } +} + +typedef T _Transformation(S value); + +/** + * A stream pipe that converts data events before passing them on. + */ +class _MapStream extends _ForwardingStream { + final _Transformation _transform; + + _MapStream(Stream source, T transform(S event)) + : this._transform = transform, + super(source); + + void _handleData(S inputEvent, _EventSink sink) { + T outputEvent; + try { + outputEvent = _transform(inputEvent); + } catch (e, s) { + _addErrorWithReplacement(sink, e, s); + return; + } + sink._add(outputEvent); + } +} + +/** + * A stream pipe that converts data events before passing them on. + */ +class _ExpandStream extends _ForwardingStream { + final _Transformation> _expand; + + _ExpandStream(Stream source, Iterable expand(S event)) + : this._expand = expand, + super(source); + + void _handleData(S inputEvent, _EventSink sink) { + try { + for (T value in _expand(inputEvent)) { + sink._add(value); + } + } catch (e, s) { + // If either _expand or iterating the generated iterator throws, + // we abort the iteration. + _addErrorWithReplacement(sink, e, s); + } + } +} + +typedef bool _ErrorTest(error); + +/** + * A stream pipe that converts or disposes error events + * before passing them on. + */ +class _HandleErrorStream extends _ForwardingStream { + final Function _transform; + final _ErrorTest _test; + + _HandleErrorStream(Stream source, Function onError, bool test(error)) + : this._transform = onError, + this._test = test, + super(source); + + void _handleError(Object error, StackTrace stackTrace, _EventSink sink) { + bool matches = true; + if (_test != null) { + try { + matches = _test(error); + } catch (e, s) { + _addErrorWithReplacement(sink, e, s); + return; + } + } + if (matches) { + try { + _invokeErrorHandler(_transform, error, stackTrace); + } catch (e, s) { + if (identical(e, error)) { + sink._addError(error, stackTrace); + } else { + _addErrorWithReplacement(sink, e, s); + } + return; + } + } else { + sink._addError(error, stackTrace); + } + } +} + +class _TakeStream extends _ForwardingStream { + final int _count; + + _TakeStream(Stream source, int count) + : this._count = count, + super(source) { + // This test is done early to avoid handling an async error + // in the _handleData method. + if (count is! int) throw new ArgumentError(count); + } + + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) { + if (_count == 0) { + _source.listen(null).cancel(); + return new _DoneStreamSubscription(onDone); + } + return new _StateStreamSubscription( + this, onData, onError, onDone, cancelOnError, _count); + } + + void _handleData(T inputEvent, _EventSink sink) { + _StateStreamSubscription subscription = sink; + int count = subscription._count; + if (count > 0) { + sink._add(inputEvent); + count -= 1; + subscription._count = count; + if (count == 0) { + // Closing also unsubscribes all subscribers, which unsubscribes + // this from source. + sink._close(); + } + } + } +} + +/** + * A [_ForwardingStreamSubscription] with one extra state field. + * + * Use by several different classes, storing an integer, bool or general. + */ +class _StateStreamSubscription extends _ForwardingStreamSubscription { + // Raw state field. Typed access provided by getters and setters below. + var _sharedState; + + _StateStreamSubscription(_ForwardingStream stream, void onData(T data), + Function onError, void onDone(), bool cancelOnError, this._sharedState) + : super(stream, onData, onError, onDone, cancelOnError); + + bool get _flag => _sharedState; + void set _flag(bool flag) { + _sharedState = flag; + } + + int get _count => _sharedState; + void set _count(int count) { + _sharedState = count; + } + + Object get _value => _sharedState; + void set _value(Object value) { + _sharedState = value; + } +} + +class _TakeWhileStream extends _ForwardingStream { + final _Predicate _test; + + _TakeWhileStream(Stream source, bool test(T value)) + : this._test = test, + super(source); + + void _handleData(T inputEvent, _EventSink sink) { + bool satisfies; + try { + satisfies = _test(inputEvent); + } catch (e, s) { + _addErrorWithReplacement(sink, e, s); + // The test didn't say true. Didn't say false either, but we stop anyway. + sink._close(); + return; + } + if (satisfies) { + sink._add(inputEvent); + } else { + sink._close(); + } + } +} + +class _SkipStream extends _ForwardingStream { + final int _count; + + _SkipStream(Stream source, int count) + : this._count = count, + super(source) { + // This test is done early to avoid handling an async error + // in the _handleData method. + if (count is! int || count < 0) throw new ArgumentError(count); + } + + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) { + return new _StateStreamSubscription( + this, onData, onError, onDone, cancelOnError, _count); + } + + void _handleData(T inputEvent, _EventSink sink) { + _StateStreamSubscription subscription = sink; + int count = subscription._count; + if (count > 0) { + subscription._count = count - 1; + return; + } + sink._add(inputEvent); + } +} + +class _SkipWhileStream extends _ForwardingStream { + final _Predicate _test; + + _SkipWhileStream(Stream source, bool test(T value)) + : this._test = test, + super(source); + + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) { + return new _StateStreamSubscription( + this, onData, onError, onDone, cancelOnError, false); + } + + void _handleData(T inputEvent, _EventSink sink) { + _StateStreamSubscription subscription = sink; + bool hasFailed = subscription._flag; + if (hasFailed) { + sink._add(inputEvent); + return; + } + bool satisfies; + try { + satisfies = _test(inputEvent); + } catch (e, s) { + _addErrorWithReplacement(sink, e, s); + // A failure to return a boolean is considered "not matching". + subscription._flag = true; + return; + } + if (!satisfies) { + subscription._flag = true; + sink._add(inputEvent); + } + } +} + +typedef bool _Equality(T a, T b); + +class _DistinctStream extends _ForwardingStream { + static var _SENTINEL = new Object(); + + final _Equality _equals; + + _DistinctStream(Stream source, bool equals(T a, T b)) + : _equals = equals, + super(source); + + StreamSubscription _createSubscription(void onData(T data), + Function onError, void onDone(), bool cancelOnError) { + return new _StateStreamSubscription( + this, onData, onError, onDone, cancelOnError, _SENTINEL); + } + + void _handleData(T inputEvent, _EventSink sink) { + _StateStreamSubscription subscription = sink; + var previous = subscription._value; + if (identical(previous, _SENTINEL)) { + // First event. + subscription._value = inputEvent; + sink._add(inputEvent); + } else { + T previousEvent = previous; + bool isEqual; + try { + if (_equals == null) { + isEqual = (previousEvent == inputEvent); + } else { + isEqual = _equals(previousEvent, inputEvent); + } + } catch (e, s) { + _addErrorWithReplacement(sink, e, s); + return; + } + if (!isEqual) { + sink._add(inputEvent); + subscription._value = inputEvent; + } + } + } +} +NN<IO? 4/"P&M,PO .E4J.)<;F'7*>P%O,P> =CC!1;#/5?4HA=47J1H')N*.)'C;8$JPP8(#''!7$6%43GBG%DJ.)%857 +%,*C9*5%7 +,,C<1?7 +-G!, 8>K#O . <#-0 + )7+@"7A=%5,?75%#IAJPJPN?""%"<97 +%,P 7+@"DA=,?75%'<9A=,>75) +%,E!!%;';A=,B75(*( " 38 +.*Zfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/stream_transformers.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +/** + * Wraps an [_EventSink] so it exposes only the [EventSink] interface. + */ +class _EventSinkWrapper implements EventSink { + _EventSink _sink; + _EventSinkWrapper(this._sink); + + void add(T data) { + _sink._add(data); + } + + void addError(error, [StackTrace stackTrace]) { + _sink._addError(error, stackTrace); + } + + void close() { + _sink._close(); + } +} + +/** + * A StreamSubscription that pipes data through a sink. + * + * The constructor of this class takes a [_SinkMapper] which maps from + * [EventSink] to [EventSink]. The input to the mapper is the output of + * the transformation. The returned sink is the transformation's input. + */ +class _SinkTransformerStreamSubscription + extends _BufferingStreamSubscription { + /// The transformer's input sink. + EventSink _transformerSink; + + /// The subscription to the input stream. + StreamSubscription _subscription; + + _SinkTransformerStreamSubscription(Stream source, _SinkMapper mapper, + void onData(T data), Function onError, void onDone(), bool cancelOnError) + // We set the adapter's target only when the user is allowed to send data. + : super(onData, onError, onDone, cancelOnError) { + _EventSinkWrapper eventSink = new _EventSinkWrapper(this); + _transformerSink = mapper(eventSink); + _subscription = + source.listen(_handleData, onError: _handleError, onDone: _handleDone); + } + + /** Whether this subscription is still subscribed to its source. */ + bool get _isSubscribed => _subscription != null; + + // _EventSink interface. + + /** + * Adds an event to this subscriptions. + * + * Contrary to normal [_BufferingStreamSubscription]s we may receive + * events when the stream is already closed. Report them as state + * error. + */ + void _add(T data) { + if (_isClosed) { + throw new StateError("Stream is already closed"); + } + super._add(data); + } + + /** + * Adds an error event to this subscriptions. + * + * Contrary to normal [_BufferingStreamSubscription]s we may receive + * events when the stream is already closed. Report them as state + * error. + */ + void _addError(Object error, StackTrace stackTrace) { + if (_isClosed) { + throw new StateError("Stream is already closed"); + } + super._addError(error, stackTrace); + } + + /** + * Adds a close event to this subscriptions. + * + * Contrary to normal [_BufferingStreamSubscription]s we may receive + * events when the stream is already closed. Report them as state + * error. + */ + void _close() { + if (_isClosed) { + throw new StateError("Stream is already closed"); + } + super._close(); + } + + // _BufferingStreamSubscription hooks. + + void _onPause() { + if (_isSubscribed) _subscription.pause(); + } + + void _onResume() { + if (_isSubscribed) _subscription.resume(); + } + + Future _onCancel() { + if (_isSubscribed) { + StreamSubscription subscription = _subscription; + _subscription = null; + return subscription.cancel(); + } + return null; + } + + void _handleData(S data) { + try { + _transformerSink.add(data); + } catch (e, s) { + _addError(e, s); + } + } + + void _handleError(error, [stackTrace]) { + try { + _transformerSink.addError(error, stackTrace); + } catch (e, s) { + if (identical(e, error)) { + _addError(error, stackTrace); + } else { + _addError(e, s); + } + } + } + + void _handleDone() { + try { + _subscription = null; + _transformerSink.close(); + } catch (e, s) { + _addError(e, s); + } + } +} + +typedef EventSink _SinkMapper(EventSink output); + +/** + * A StreamTransformer for Sink-mappers. + * + * A Sink-mapper takes an [EventSink] (its output) and returns another + * EventSink (its input). + * + * Note that this class can be `const`. + */ +class _StreamSinkTransformer extends StreamTransformerBase { + final _SinkMapper _sinkMapper; + const _StreamSinkTransformer(this._sinkMapper); + + Stream bind(Stream stream) => + new _BoundSinkStream(stream, _sinkMapper); +} + +/** + * The result of binding a StreamTransformer for Sink-mappers. + * + * It contains the bound Stream and the sink-mapper. Only when the user starts + * listening to this stream is the sink-mapper invoked. The result is used + * to create a StreamSubscription that transforms events. + */ +class _BoundSinkStream extends Stream { + final _SinkMapper _sinkMapper; + final Stream _stream; + + bool get isBroadcast => _stream.isBroadcast; + + _BoundSinkStream(this._stream, this._sinkMapper); + + StreamSubscription listen(void onData(T event), + {Function onError, void onDone(), bool cancelOnError}) { + cancelOnError = identical(true, cancelOnError); + StreamSubscription subscription = + new _SinkTransformerStreamSubscription( + _stream, _sinkMapper, onData, onError, onDone, cancelOnError); + return subscription; + } +} + +/// Data-handler coming from [StreamTransformer.fromHandlers]. +typedef void _TransformDataHandler(S data, EventSink sink); + +/// Error-handler coming from [StreamTransformer.fromHandlers]. +typedef void _TransformErrorHandler( + Object error, StackTrace stackTrace, EventSink sink); + +/// Done-handler coming from [StreamTransformer.fromHandlers]. +typedef void _TransformDoneHandler(EventSink sink); + +/** + * Wraps handlers (from [StreamTransformer.fromHandlers]) into an `EventSink`. + * + * This way we can reuse the code from [_StreamSinkTransformer]. + */ +class _HandlerEventSink implements EventSink { + final _TransformDataHandler _handleData; + final _TransformErrorHandler _handleError; + final _TransformDoneHandler _handleDone; + + /// The output sink where the handlers should send their data into. + EventSink _sink; + + _HandlerEventSink( + this._handleData, this._handleError, this._handleDone, this._sink) { + if (_sink == null) { + throw new ArgumentError("The provided sink must not be null."); + } + } + + bool get _isClosed => _sink == null; + + _reportClosedSink() { + // TODO(29554): throw a StateError, and don't just report the problem. + Zone.root + ..print("Sink is closed and adding to it is an error.") + ..print(" See http://dartbug.com/29554.") + ..print(StackTrace.current.toString()); + } + + void add(S data) { + if (_isClosed) { + _reportClosedSink(); + } + if (_handleData != null) { + _handleData(data, _sink); + } else { + _sink.add(data as T); + } + } + + void addError(Object error, [StackTrace stackTrace]) { + if (_isClosed) { + _reportClosedSink(); + } + if (_handleError != null) { + _handleError(error, stackTrace, _sink); + } else { + _sink.addError(error, stackTrace); + } + } + + void close() { + if (_isClosed) return; + var sink = _sink; + _sink = null; + if (_handleDone != null) { + _handleDone(sink); + } else { + sink.close(); + } + } +} + +/** + * A StreamTransformer that transformers events with the given handlers. + * + * Note that this transformer can only be used once. + */ +class _StreamHandlerTransformer extends _StreamSinkTransformer { + _StreamHandlerTransformer( + {void handleData(S data, EventSink sink), + void handleError(Object error, StackTrace stackTrace, EventSink sink), + void handleDone(EventSink sink)}) + : super((EventSink outputSink) { + return new _HandlerEventSink( + handleData, handleError, handleDone, outputSink); + }); + + Stream bind(Stream stream) { + return super.bind(stream); + } +} + +/// A closure mapping a stream and cancelOnError to a StreamSubscription. +typedef StreamSubscription _SubscriptionTransformer( + Stream stream, bool cancelOnError); + +/** + * A [StreamTransformer] that minimizes the number of additional classes. + * + * Instead of implementing three classes: a [StreamTransformer], a [Stream] + * (as the result of a `bind` call) and a [StreamSubscription] (which does the + * actual work), this class only requires a function that is invoked when the + * last bit (the subscription) of the transformer-workflow is needed. + * + * The given transformer function maps from Stream and cancelOnError to a + * `StreamSubscription`. As such it can also act on `cancel` events, making it + * fully general. + */ +class _StreamSubscriptionTransformer extends StreamTransformerBase { + final _SubscriptionTransformer _onListen; + + const _StreamSubscriptionTransformer(this._onListen); + + Stream bind(Stream stream) => + new _BoundSubscriptionStream(stream, _onListen); +} + +/** + * A stream transformed by a [_StreamSubscriptionTransformer]. + * + * When this stream is listened to it invokes the [_onListen] function with + * the stored [_stream]. Usually the transformer starts listening at this + * moment. + */ +class _BoundSubscriptionStream extends Stream { + final _SubscriptionTransformer _onListen; + final Stream _stream; + + _BoundSubscriptionStream(this._stream, this._onListen); + + StreamSubscription listen(void onData(T event), + {Function onError, void onDone(), bool cancelOnError}) { + cancelOnError = identical(true, cancelOnError); + StreamSubscription result = _onListen(_stream, cancelOnError); + result.onData(onData); + result.onError(onError); + result.onDone(onDone); + return result; + } +} +NNN<G5!2(8GHH/.$!,'QPQ8E*PF3*GD 80GD 88(/GD 8)./7$ +"+ +4!& + =)G(I'2&7?OK:1'/45?4)6K?E@(=?:OA810.FKF'K>1. 9 . ) I5M3P+*.@ %J>+JLONFJOQ28&=?LJ 92:5?4FKfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/zone.dartI// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +typedef R ZoneCallback(); +typedef R ZoneUnaryCallback(T arg); +typedef R ZoneBinaryCallback(T1 arg1, T2 arg2); + +typedef HandleUncaughtErrorHandler = void Function(Zone self, + ZoneDelegate parent, Zone zone, Object error, StackTrace stackTrace); +typedef RunHandler = R Function( + Zone self, ZoneDelegate parent, Zone zone, R Function() f); +typedef RunUnaryHandler = R Function( + Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f, T arg); +typedef RunBinaryHandler = R Function(Zone self, ZoneDelegate parent, + Zone zone, R Function(T1 arg1, T2 arg2) f, T1 arg1, T2 arg2); +typedef RegisterCallbackHandler = ZoneCallback Function( + Zone self, ZoneDelegate parent, Zone zone, R Function() f); +typedef RegisterUnaryCallbackHandler = ZoneUnaryCallback Function( + Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f); +typedef RegisterBinaryCallbackHandler + = ZoneBinaryCallback Function(Zone self, + ZoneDelegate parent, Zone zone, R Function(T1 arg1, T2 arg2) f); +typedef AsyncError ErrorCallbackHandler(Zone self, ZoneDelegate parent, + Zone zone, Object error, StackTrace stackTrace); +typedef void ScheduleMicrotaskHandler( + Zone self, ZoneDelegate parent, Zone zone, void f()); +typedef Timer CreateTimerHandler( + Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f()); +typedef Timer CreatePeriodicTimerHandler(Zone self, ZoneDelegate parent, + Zone zone, Duration period, void f(Timer timer)); +typedef void PrintHandler( + Zone self, ZoneDelegate parent, Zone zone, String line); +typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone, + ZoneSpecification specification, Map zoneValues); + +/** Pair of error and stack trace. Returned by [Zone.errorCallback]. */ +class AsyncError implements Error { + final Object error; + final StackTrace stackTrace; + + AsyncError(this.error, this.stackTrace); + + String toString() => '$error'; +} + +class _ZoneFunction { + final _Zone zone; + final T function; + const _ZoneFunction(this.zone, this.function); +} + +/** + * This class provides the specification for a forked zone. + * + * When forking a new zone (see [Zone.fork]) one can override the default + * behavior of the zone by providing callbacks. These callbacks must be + * given in an instance of this class. + * + * Handlers have the same signature as the same-named methods on [Zone] but + * receive three additional arguments: + * + * 1. the zone the handlers are attached to (the "self" zone). + * 2. a [ZoneDelegate] to the parent zone. + * 3. the zone that first received the request (before the request was + * bubbled up). + * + * Handlers can either stop propagation the request (by simply not calling the + * parent handler), or forward to the parent zone, potentially modifying the + * arguments on the way. + */ +abstract class ZoneSpecification { + /** + * Creates a specification with the provided handlers. + */ + const factory ZoneSpecification( + {HandleUncaughtErrorHandler handleUncaughtError, + RunHandler run, + RunUnaryHandler runUnary, + RunBinaryHandler runBinary, + RegisterCallbackHandler registerCallback, + RegisterUnaryCallbackHandler registerUnaryCallback, + RegisterBinaryCallbackHandler registerBinaryCallback, + ErrorCallbackHandler errorCallback, + ScheduleMicrotaskHandler scheduleMicrotask, + CreateTimerHandler createTimer, + CreatePeriodicTimerHandler createPeriodicTimer, + PrintHandler print, + ForkHandler fork}) = _ZoneSpecification; + + /** + * Creates a specification from [other] with the provided handlers overriding + * the ones in [other]. + */ + factory ZoneSpecification.from(ZoneSpecification other, + {HandleUncaughtErrorHandler handleUncaughtError: null, + RunHandler run: null, + RunUnaryHandler runUnary: null, + RunBinaryHandler runBinary: null, + RegisterCallbackHandler registerCallback: null, + RegisterUnaryCallbackHandler registerUnaryCallback: null, + RegisterBinaryCallbackHandler registerBinaryCallback: null, + ErrorCallbackHandler errorCallback: null, + ScheduleMicrotaskHandler scheduleMicrotask: null, + CreateTimerHandler createTimer: null, + CreatePeriodicTimerHandler createPeriodicTimer: null, + PrintHandler print: null, + ForkHandler fork: null}) { + return new ZoneSpecification( + handleUncaughtError: handleUncaughtError ?? other.handleUncaughtError, + run: run ?? other.run, + runUnary: runUnary ?? other.runUnary, + runBinary: runBinary ?? other.runBinary, + registerCallback: registerCallback ?? other.registerCallback, + registerUnaryCallback: + registerUnaryCallback ?? other.registerUnaryCallback, + registerBinaryCallback: + registerBinaryCallback ?? other.registerBinaryCallback, + errorCallback: errorCallback ?? other.errorCallback, + scheduleMicrotask: scheduleMicrotask ?? other.scheduleMicrotask, + createTimer: createTimer ?? other.createTimer, + createPeriodicTimer: createPeriodicTimer ?? other.createPeriodicTimer, + print: print ?? other.print, + fork: fork ?? other.fork); + } + + HandleUncaughtErrorHandler get handleUncaughtError; + RunHandler get run; + RunUnaryHandler get runUnary; + RunBinaryHandler get runBinary; + RegisterCallbackHandler get registerCallback; + RegisterUnaryCallbackHandler get registerUnaryCallback; + RegisterBinaryCallbackHandler get registerBinaryCallback; + ErrorCallbackHandler get errorCallback; + ScheduleMicrotaskHandler get scheduleMicrotask; + CreateTimerHandler get createTimer; + CreatePeriodicTimerHandler get createPeriodicTimer; + PrintHandler get print; + ForkHandler get fork; +} + +/** + * Internal [ZoneSpecification] class. + * + * The implementation wants to rely on the fact that the getters cannot change + * dynamically. We thus require users to go through the redirecting + * [ZoneSpecification] constructor which instantiates this class. + */ +class _ZoneSpecification implements ZoneSpecification { + const _ZoneSpecification( + {this.handleUncaughtError: null, + this.run: null, + this.runUnary: null, + this.runBinary: null, + this.registerCallback: null, + this.registerUnaryCallback: null, + this.registerBinaryCallback: null, + this.errorCallback: null, + this.scheduleMicrotask: null, + this.createTimer: null, + this.createPeriodicTimer: null, + this.print: null, + this.fork: null}); + + final HandleUncaughtErrorHandler handleUncaughtError; + final RunHandler run; + final RunUnaryHandler runUnary; + final RunBinaryHandler runBinary; + final RegisterCallbackHandler registerCallback; + final RegisterUnaryCallbackHandler registerUnaryCallback; + final RegisterBinaryCallbackHandler registerBinaryCallback; + final ErrorCallbackHandler errorCallback; + final ScheduleMicrotaskHandler scheduleMicrotask; + final CreateTimerHandler createTimer; + final CreatePeriodicTimerHandler createPeriodicTimer; + final PrintHandler print; + final ForkHandler fork; +} + +/** + * An adapted view of the parent zone. + * + * This class allows the implementation of a zone method to invoke methods on + * the parent zone while retaining knowledge of the originating zone. + * + * Custom zones (created through [Zone.fork] or [runZoned]) can provide + * implementations of most methods of zones. This is similar to overriding + * methods on [Zone], except that this mechanism doesn't require subclassing. + * + * A custom zone function (provided through a [ZoneSpecification]) typically + * records or wraps its parameters and then delegates the operation to its + * parent zone using the provided [ZoneDelegate]. + * + * While zones have access to their parent zone (through [Zone.parent]) it is + * recommended to call the methods on the provided parent delegate for two + * reasons: + * 1. the delegate methods take an additional `zone` argument which is the + * zone the action has been initiated in. + * 2. delegate calls are more efficient, since the implementation knows how + * to skip zones that would just delegate to their parents. + */ +abstract class ZoneDelegate { + void handleUncaughtError(Zone zone, error, StackTrace stackTrace); + R run(Zone zone, R f()); + R runUnary(Zone zone, R f(T arg), T arg); + R runBinary(Zone zone, R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2); + ZoneCallback registerCallback(Zone zone, R f()); + ZoneUnaryCallback registerUnaryCallback(Zone zone, R f(T arg)); + ZoneBinaryCallback registerBinaryCallback( + Zone zone, R f(T1 arg1, T2 arg2)); + AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace); + void scheduleMicrotask(Zone zone, void f()); + Timer createTimer(Zone zone, Duration duration, void f()); + Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)); + void print(Zone zone, String line); + Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues); +} + +/** + * A zone represents an environment that remains stable across asynchronous + * calls. + * + * Code is always executed in the context of a zone, available as + * [Zone.current]. The initial `main` function runs in the context of the + * default zone ([Zone.root]). Code can be run in a different zone using either + * [runZoned], to create a new zone, or [Zone.run] to run code in the context of + * an existing zone likely created using [Zone.fork]. + * + * Developers can create a new zone that overrides some of the functionality of + * an existing zone. For example, custom zones can replace of modify the + * behavior of `print`, timers, microtasks or how uncaught errors are handled. + * + * The [Zone] class is not subclassable, but users can provide custom zones by + * forking an existing zone (usually [Zone.current]) with a [ZoneSpecification]. + * This is similar to creating a new class that extends the base `Zone` class + * and that overrides some methods, except without actually creating a new + * class. Instead the overriding methods are provided as functions that + * explicitly take the equivalent of their own class, the "super" class and the + * `this` object as parameters. + * + * Asynchronous callbacks always run in the context of the zone where they were + * scheduled. This is implemented using two steps: + * 1. the callback is first registered using one of [registerCallback], + * [registerUnaryCallback], or [registerBinaryCallback]. This allows the zone + * to record that a callback exists and potentially modify it (by returning a + * different callback). The code doing the registration (e.g., `Future.then`) + * also remembers the current zone so that it can later run the callback in + * that zone. + * 2. At a later point the registered callback is run in the remembered zone. + * + * This is all handled internally by the platform code and most users don't need + * to worry about it. However, developers of new asynchronous operations, + * provided by the underlying system or through native extensions, must follow + * the protocol to be zone compatible. + * + * For convenience, zones provide [bindCallback] (and the corresponding + * [bindUnaryCallback] and [bindBinaryCallback]) to make it easier to respect + * the zone contract: these functions first invoke the corresponding `register` + * functions and then wrap the returned function so that it runs in the current + * zone when it is later asynchronously invoked. + * + * Similarly, zones provide [bindCallbackGuarded] (and the corresponding + * [bindUnaryCallbackGuarded] and [bindBinaryCallbackGuarded]), when the + * callback should be invoked through [Zone.runGuarded]. + */ +abstract class Zone { + // Private constructor so that it is not possible instantiate a Zone class. + Zone._(); + + /** + * The root zone. + * + * All isolate entry functions (`main` or spawned functions) start running in + * the root zone (that is, [Zone.current] is identical to [Zone.root] when the + * entry function is called). If no custom zone is created, the rest of the + * program always runs in the root zone. + * + * The root zone implements the default behavior of all zone operations. + * Many methods, like [registerCallback] do the bare minimum required of the + * function, and are only provided as a hook for custom zones. Others, like + * [scheduleMicrotask], interact with the underlying system to implement the + * desired behavior. + */ + static const Zone root = _rootZone; + + /** The currently running zone. */ + static Zone _current = _rootZone; + + /** The zone that is currently active. */ + static Zone get current => _current; + + /** + * Handles uncaught asynchronous errors. + * + * There are two kind of asynchronous errors that are handled by this + * function: + * 1. Uncaught errors that were thrown in asynchronous callbacks, for example, + * a `throw` in the function passed to [Timer.run]. + * 2. Asynchronous errors that are pushed through [Future] and [Stream] + * chains, but for which no child registered an error handler. + * Most asynchronous classes, like [Future] or [Stream] push errors to their + * listeners. Errors are propagated this way until either a listener handles + * the error (for example with [Future.catchError]), or no listener is + * available anymore. In the latter case, futures and streams invoke the + * zone's [handleUncaughtError]. + * + * By default, when handled by the root zone, uncaught asynchronous errors are + * treated like uncaught synchronous exceptions. + */ + void handleUncaughtError(error, StackTrace stackTrace); + + /** + * The parent zone of the this zone. + * + * Is `null` if `this` is the [root] zone. + * + * Zones are created by [fork] on an existing zone, or by [runZoned] which + * forks the [current] zone. The new zone's parent zone is the zone it was + * forked from. + */ + Zone get parent; + + /** + * The error zone is the one that is responsible for dealing with uncaught + * errors. + * + * This is the closest parent zone of this zone that provides a + * [handleUncaughtError] method. + * + * Asynchronous errors never cross zone boundaries between zones with + * different error handlers. + * + * Example: + * ``` + * import 'dart:async'; + * + * main() { + * var future; + * runZoned(() { + * // The asynchronous error is caught by the custom zone which prints + * // 'asynchronous error'. + * future = new Future.error("asynchronous error"); + * }, onError: (e) { print(e); }); // Creates a zone with an error handler. + * // The following `catchError` handler is never invoked, because the + * // custom zone created by the call to `runZoned` provides an + * // error handler. + * future.catchError((e) { throw "is never reached"; }); + * } + * ``` + * + * Note that errors cannot enter a child zone with a different error handler + * either: + * ``` + * import 'dart:async'; + * + * main() { + * runZoned(() { + * // The following asynchronous error is *not* caught by the `catchError` + * // in the nested zone, since errors are not to cross zone boundaries + * // with different error handlers. + * // Instead the error is handled by the current error handler, + * // printing "Caught by outer zone: asynchronous error". + * var future = new Future.error("asynchronous error"); + * runZoned(() { + * future.catchError((e) { throw "is never reached"; }); + * }, onError: (e) { throw "is never reached"; }); + * }, onError: (e) { print("Caught by outer zone: $e"); }); + * } + * ``` + */ + Zone get errorZone; + + /** + * Returns true if `this` and [otherZone] are in the same error zone. + * + * Two zones are in the same error zone if they have the same [errorZone]. + */ + bool inSameErrorZone(Zone otherZone); + + /** + * Creates a new zone as a child of `this`. + * + * The new zone uses the closures in the given [specification] to override + * the current's zone behavior. All specification entries that are `null` + * inherit the behavior from the parent zone (`this`). + * + * The new zone inherits the stored values (accessed through [operator []]) + * of this zone and updates them with values from [zoneValues], which either + * adds new values or overrides existing ones. + * + * Note that the fork operation is interceptible. A zone can thus change + * the zone specification (or zone values), giving the forking zone full + * control over the child zone. + */ + Zone fork({ZoneSpecification specification, Map zoneValues}); + + /** + * Executes [action] in this zone. + * + * By default (as implemented in the [root] zone), runs [action] + * with [current] set to this zone. + * + * If [action] throws, the synchronous exception is not caught by the zone's + * error handler. Use [runGuarded] to achieve that. + * + * Since the root zone is the only zone that can modify the value of + * [current], custom zones intercepting run should always delegate to their + * parent zone. They may take actions before and after the call. + */ + R run(R action()); + + /** + * Executes the given [action] with [argument] in this zone. + * + * As [run] except that [action] is called with one [argument] instead of + * none. + */ + R runUnary(R action(T argument), T argument); + + /** + * Executes the given [action] with [argument1] and [argument2] in this + * zone. + * + * As [run] except that [action] is called with two arguments instead of none. + */ + R runBinary( + R action(T1 argument1, T2 argument2), T1 argument1, T2 argument2); + + /** + * Executes the given [action] in this zone and catches synchronous + * errors. + * + * This function is equivalent to: + * ``` + * try { + * this.run(action); + * } catch (e, s) { + * this.handleUncaughtError(e, s); + * } + * ``` + * + * See [run]. + */ + void runGuarded(void action()); + + /** + * Executes the given [action] with [argument] in this zone and + * catches synchronous errors. + * + * See [runGuarded]. + */ + void runUnaryGuarded(void action(T argument), T argument); + + /** + * Executes the given [action] with [argument1] and [argument2] in this + * zone and catches synchronous errors. + * + * See [runGuarded]. + */ + void runBinaryGuarded( + void action(T1 argument1, T2 argument2), T1 argument1, T2 argument2); + + /** + * Registers the given callback in this zone. + * + * When implementing an asynchronous primitive that uses callbacks, the + * callback must be registered using [registerCallback] at the point where the + * user provides the callback. This allows zones to record other information + * that they need at the same time, perhaps even wrapping the callback, so + * that the callback is prepared when it is later run in the same zones + * (using [run]). For example, a zone may decide + * to store the stack trace (at the time of the registration) with the + * callback. + * + * Returns the callback that should be used in place of the provided + * [callback]. Frequently zones simply return the original callback. + * + * Custom zones may intercept this operation. The default implementation in + * [Zone.root] returns the original callback unchanged. + */ + ZoneCallback registerCallback(R callback()); + + /** + * Registers the given callback in this zone. + * + * Similar to [registerCallback] but with a unary callback. + */ + ZoneUnaryCallback registerUnaryCallback(R callback(T arg)); + + /** + * Registers the given callback in this zone. + * + * Similar to [registerCallback] but with a unary callback. + */ + ZoneBinaryCallback registerBinaryCallback( + R callback(T1 arg1, T2 arg2)); + + /** + * Registers the provided [callback] and returns a function that will + * execute in this zone. + * + * Equivalent to: + * + * ZoneCallback registered = this.registerCallback(callback); + * return () => this.run(registered); + * + */ + ZoneCallback bindCallback(R callback()); + + /** + * Registers the provided [callback] and returns a function that will + * execute in this zone. + * + * Equivalent to: + * + * ZoneCallback registered = this.registerUnaryCallback(callback); + * return (arg) => thin.runUnary(registered, arg); + */ + ZoneUnaryCallback bindUnaryCallback(R callback(T argument)); + + /** + * Registers the provided [callback] and returns a function that will + * execute in this zone. + * + * Equivalent to: + * + * ZoneCallback registered = registerBinaryCallback(callback); + * return (arg1, arg2) => thin.runBinary(registered, arg1, arg2); + */ + ZoneBinaryCallback bindBinaryCallback( + R callback(T1 argument1, T2 argument2)); + + /** + * Registers the provided [callback] and returns a function that will + * execute in this zone. + * + * When the function executes, errors are caught and treated as uncaught + * errors. + * + * Equivalent to: + * + * ZoneCallback registered = this.registerCallback(callback); + * return () => this.runGuarded(registered); + * + */ + void Function() bindCallbackGuarded(void callback()); + + /** + * Registers the provided [callback] and returns a function that will + * execute in this zone. + * + * When the function executes, errors are caught and treated as uncaught + * errors. + * + * Equivalent to: + * + * ZoneCallback registered = this.registerUnaryCallback(callback); + * return (arg) => this.runUnaryGuarded(registered, arg); + */ + void Function(T) bindUnaryCallbackGuarded(void callback(T argument)); + + /** + * Registers the provided [callback] and returns a function that will + * execute in this zone. + * + * Equivalent to: + * + * ZoneCallback registered = registerBinaryCallback(callback); + * return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2); + */ + void Function(T1, T2) bindBinaryCallbackGuarded( + void callback(T1 argument1, T2 argument2)); + + /** + * Intercepts errors when added programmatically to a `Future` or `Stream`. + * + * When calling [Completer.completeError], [StreamController.addError], + * or some [Future] constructors, the current zone is allowed to intercept + * and replace the error. + * + * Future constructors invoke this function when the error is received + * directly, for example with [Future.error], or when the error is caught + * synchronously, for example with [Future.sync]. + * + * There is no guarantee that an error is only sent through [errorCallback] + * once. Libraries that use intermediate controllers or completers might + * end up invoking [errorCallback] multiple times. + * + * Returns `null` if no replacement is desired. Otherwise returns an instance + * of [AsyncError] holding the new pair of error and stack trace. + * + * Although not recommended, the returned instance may have its `error` member + * ([AsyncError.error]) be equal to `null` in which case the error should be + * replaced by a [NullThrownError]. + * + * Custom zones may intercept this operation. + * + * Implementations of a new asynchronous primitive that converts synchronous + * errors to asynchronous errors rarely need to invoke [errorCallback], since + * errors are usually reported through future completers or stream + * controllers. + */ + AsyncError errorCallback(Object error, StackTrace stackTrace); + + /** + * Runs [callback] asynchronously in this zone. + * + * The global `scheduleMicrotask` delegates to the current zone's + * [scheduleMicrotask]. The root zone's implementation interacts with the + * underlying system to schedule the given callback as a microtask. + * + * Custom zones may intercept this operation (for example to wrap the given + * [callback]). + */ + void scheduleMicrotask(void callback()); + + /** + * Creates a Timer where the callback is executed in this zone. + */ + Timer createTimer(Duration duration, void callback()); + + /** + * Creates a periodic Timer where the callback is executed in this zone. + */ + Timer createPeriodicTimer(Duration period, void callback(Timer timer)); + + /** + * Prints the given [line]. + * + * The global `print` function delegates to the current zone's [print] + * function which makes it possible to intercept printing. + * + * Example: + * ``` + * import 'dart:async'; + * + * main() { + * runZoned(() { + * // Ends up printing: "Intercepted: in zone". + * print("in zone"); + * }, zoneSpecification: new ZoneSpecification( + * print: (Zone self, ZoneDelegate parent, Zone zone, String line) { + * parent.print(zone, "Intercepted: $line"); + * })); + * } + * ``` + */ + void print(String line); + + /** + * Call to enter the Zone. + * + * The previous current zone is returned. + */ + static Zone _enter(Zone zone) { + assert(zone != null); + assert(!identical(zone, _current)); + Zone previous = _current; + _current = zone; + return previous; + } + + /** + * Call to leave the Zone. + * + * The previous Zone must be provided as `previous`. + */ + static void _leave(Zone previous) { + assert(previous != null); + Zone._current = previous; + } + + /** + * Retrieves the zone-value associated with [key]. + * + * If this zone does not contain the value looks up the same key in the + * parent zone. If the [key] is not found returns `null`. + * + * Any object can be used as key, as long as it has compatible `operator ==` + * and `hashCode` implementations. + * By controlling access to the key, a zone can grant or deny access to the + * zone value. + */ + operator [](Object key); +} + +ZoneDelegate _parentDelegate(_Zone zone) { + if (zone.parent == null) return null; + return zone.parent._delegate; +} + +class _ZoneDelegate implements ZoneDelegate { + final _Zone _delegationTarget; + + _ZoneDelegate(this._delegationTarget); + + void handleUncaughtError(Zone zone, error, StackTrace stackTrace) { + var implementation = _delegationTarget._handleUncaughtError; + _Zone implZone = implementation.zone; + HandleUncaughtErrorHandler handler = implementation.function; + return handler( + implZone, _parentDelegate(implZone), zone, error, stackTrace); + } + + R run(Zone zone, R f()) { + var implementation = _delegationTarget._run; + _Zone implZone = implementation.zone; + RunHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, f); + } + + R runUnary(Zone zone, R f(T arg), T arg) { + var implementation = _delegationTarget._runUnary; + _Zone implZone = implementation.zone; + RunUnaryHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, f, arg); + } + + R runBinary(Zone zone, R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) { + var implementation = _delegationTarget._runBinary; + _Zone implZone = implementation.zone; + RunBinaryHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, f, arg1, arg2); + } + + ZoneCallback registerCallback(Zone zone, R f()) { + var implementation = _delegationTarget._registerCallback; + _Zone implZone = implementation.zone; + RegisterCallbackHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, f); + } + + ZoneUnaryCallback registerUnaryCallback(Zone zone, R f(T arg)) { + var implementation = _delegationTarget._registerUnaryCallback; + _Zone implZone = implementation.zone; + RegisterUnaryCallbackHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, f); + } + + ZoneBinaryCallback registerBinaryCallback( + Zone zone, R f(T1 arg1, T2 arg2)) { + var implementation = _delegationTarget._registerBinaryCallback; + _Zone implZone = implementation.zone; + RegisterBinaryCallbackHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, f); + } + + AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace) { + var implementation = _delegationTarget._errorCallback; + _Zone implZone = implementation.zone; + if (identical(implZone, _rootZone)) return null; + ErrorCallbackHandler handler = implementation.function; + return handler( + implZone, _parentDelegate(implZone), zone, error, stackTrace); + } + + void scheduleMicrotask(Zone zone, f()) { + var implementation = _delegationTarget._scheduleMicrotask; + _Zone implZone = implementation.zone; + ScheduleMicrotaskHandler handler = implementation.function; + handler(implZone, _parentDelegate(implZone), zone, f); + } + + Timer createTimer(Zone zone, Duration duration, void f()) { + var implementation = _delegationTarget._createTimer; + _Zone implZone = implementation.zone; + CreateTimerHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, duration, f); + } + + Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)) { + var implementation = _delegationTarget._createPeriodicTimer; + _Zone implZone = implementation.zone; + CreatePeriodicTimerHandler handler = implementation.function; + return handler(implZone, _parentDelegate(implZone), zone, period, f); + } + + void print(Zone zone, String line) { + var implementation = _delegationTarget._print; + _Zone implZone = implementation.zone; + PrintHandler handler = implementation.function; + handler(implZone, _parentDelegate(implZone), zone, line); + } + + Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues) { + var implementation = _delegationTarget._fork; + _Zone implZone = implementation.zone; + ForkHandler handler = implementation.function; + return handler( + implZone, _parentDelegate(implZone), zone, specification, zoneValues); + } +} + +/** + * Base class for Zone implementations. + */ +abstract class _Zone implements Zone { + const _Zone(); + + // TODO(floitsch): the types of the `_ZoneFunction`s should have a type for + // all fields. + _ZoneFunction get _run; + _ZoneFunction get _runUnary; + _ZoneFunction get _runBinary; + _ZoneFunction get _registerCallback; + _ZoneFunction get _registerUnaryCallback; + _ZoneFunction get _registerBinaryCallback; + _ZoneFunction get _errorCallback; + _ZoneFunction get _scheduleMicrotask; + _ZoneFunction get _createTimer; + _ZoneFunction get _createPeriodicTimer; + _ZoneFunction get _print; + _ZoneFunction get _fork; + _ZoneFunction get _handleUncaughtError; + _Zone get parent; + ZoneDelegate get _delegate; + Map get _map; + + bool inSameErrorZone(Zone otherZone) { + return identical(this, otherZone) || + identical(errorZone, otherZone.errorZone); + } +} + +class _CustomZone extends _Zone { + // The actual zone and implementation of each of these + // inheritable zone functions. + // TODO(floitsch): the types of the `_ZoneFunction`s should have a type for + // all fields. + _ZoneFunction _run; + _ZoneFunction _runUnary; + _ZoneFunction _runBinary; + _ZoneFunction _registerCallback; + _ZoneFunction _registerUnaryCallback; + _ZoneFunction _registerBinaryCallback; + _ZoneFunction _errorCallback; + _ZoneFunction _scheduleMicrotask; + _ZoneFunction _createTimer; + _ZoneFunction _createPeriodicTimer; + _ZoneFunction _print; + _ZoneFunction _fork; + _ZoneFunction _handleUncaughtError; + + // A cached delegate to this zone. + ZoneDelegate _delegateCache; + + /// The parent zone. + final _Zone parent; + + /// The zone's scoped value declaration map. + /// + /// This is always a [HashMap]. + final Map _map; + + ZoneDelegate get _delegate { + if (_delegateCache != null) return _delegateCache; + _delegateCache = new _ZoneDelegate(this); + return _delegateCache; + } + + _CustomZone(this.parent, ZoneSpecification specification, this._map) { + // The root zone will have implementations of all parts of the + // specification, so it will never try to access the (null) parent. + // All other zones have a non-null parent. + _run = (specification.run != null) + ? new _ZoneFunction(this, specification.run) + : parent._run; + _runUnary = (specification.runUnary != null) + ? new _ZoneFunction(this, specification.runUnary) + : parent._runUnary; + _runBinary = (specification.runBinary != null) + ? new _ZoneFunction(this, specification.runBinary) + : parent._runBinary; + _registerCallback = (specification.registerCallback != null) + ? new _ZoneFunction(this, specification.registerCallback) + : parent._registerCallback; + _registerUnaryCallback = (specification.registerUnaryCallback != null) + ? new _ZoneFunction(this, specification.registerUnaryCallback) + : parent._registerUnaryCallback; + _registerBinaryCallback = (specification.registerBinaryCallback != null) + ? new _ZoneFunction( + this, specification.registerBinaryCallback) + : parent._registerBinaryCallback; + _errorCallback = (specification.errorCallback != null) + ? new _ZoneFunction( + this, specification.errorCallback) + : parent._errorCallback; + _scheduleMicrotask = (specification.scheduleMicrotask != null) + ? new _ZoneFunction( + this, specification.scheduleMicrotask) + : parent._scheduleMicrotask; + _createTimer = (specification.createTimer != null) + ? new _ZoneFunction(this, specification.createTimer) + : parent._createTimer; + _createPeriodicTimer = (specification.createPeriodicTimer != null) + ? new _ZoneFunction( + this, specification.createPeriodicTimer) + : parent._createPeriodicTimer; + _print = (specification.print != null) + ? new _ZoneFunction(this, specification.print) + : parent._print; + _fork = (specification.fork != null) + ? new _ZoneFunction(this, specification.fork) + : parent._fork; + _handleUncaughtError = (specification.handleUncaughtError != null) + ? new _ZoneFunction( + this, specification.handleUncaughtError) + : parent._handleUncaughtError; + } + + /** + * The closest error-handling zone. + * + * Returns `this` if `this` has an error-handler. Otherwise returns the + * parent's error-zone. + */ + Zone get errorZone => _handleUncaughtError.zone; + + void runGuarded(void f()) { + try { + run(f); + } catch (e, s) { + handleUncaughtError(e, s); + } + } + + void runUnaryGuarded(void f(T arg), T arg) { + try { + runUnary(f, arg); + } catch (e, s) { + handleUncaughtError(e, s); + } + } + + void runBinaryGuarded(void f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) { + try { + runBinary(f, arg1, arg2); + } catch (e, s) { + handleUncaughtError(e, s); + } + } + + ZoneCallback bindCallback(R f()) { + var registered = registerCallback(f); + return () => this.run(registered); + } + + ZoneUnaryCallback bindUnaryCallback(R f(T arg)) { + var registered = registerUnaryCallback(f); + return (arg) => this.runUnary(registered, arg); + } + + ZoneBinaryCallback bindBinaryCallback( + R f(T1 arg1, T2 arg2)) { + var registered = registerBinaryCallback(f); + return (arg1, arg2) => this.runBinary(registered, arg1, arg2); + } + + void Function() bindCallbackGuarded(void f()) { + var registered = registerCallback(f); + return () => this.runGuarded(registered); + } + + void Function(T) bindUnaryCallbackGuarded(void f(T arg)) { + var registered = registerUnaryCallback(f); + return (arg) => this.runUnaryGuarded(registered, arg); + } + + void Function(T1, T2) bindBinaryCallbackGuarded( + void f(T1 arg1, T2 arg2)) { + var registered = registerBinaryCallback(f); + return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2); + } + + operator [](Object key) { + var result = _map[key]; + if (result != null || _map.containsKey(key)) return result; + // If we are not the root zone, look up in the parent zone. + if (parent != null) { + // We do not optimize for repeatedly looking up a key which isn't + // there. That would require storing the key and keeping it alive. + // Copying the key/value from the parent does not keep any new values + // alive. + var value = parent[key]; + if (value != null) { + _map[key] = value; + } + return value; + } + assert(this == _rootZone); + return null; + } + + // Methods that can be customized by the zone specification. + + void handleUncaughtError(error, StackTrace stackTrace) { + var implementation = this._handleUncaughtError; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + HandleUncaughtErrorHandler handler = implementation.function; + return handler( + implementation.zone, parentDelegate, this, error, stackTrace); + } + + Zone fork({ZoneSpecification specification, Map zoneValues}) { + var implementation = this._fork; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + ForkHandler handler = implementation.function; + return handler( + implementation.zone, parentDelegate, this, specification, zoneValues); + } + + R run(R f()) { + var implementation = this._run; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + RunHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, f); + } + + R runUnary(R f(T arg), T arg) { + var implementation = this._runUnary; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + RunUnaryHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, f, arg); + } + + R runBinary(R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) { + var implementation = this._runBinary; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + RunBinaryHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, f, arg1, arg2); + } + + ZoneCallback registerCallback(R callback()) { + var implementation = this._registerCallback; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + RegisterCallbackHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, callback); + } + + ZoneUnaryCallback registerUnaryCallback(R callback(T arg)) { + var implementation = this._registerUnaryCallback; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + RegisterUnaryCallbackHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, callback); + } + + ZoneBinaryCallback registerBinaryCallback( + R callback(T1 arg1, T2 arg2)) { + var implementation = this._registerBinaryCallback; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + RegisterBinaryCallbackHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, callback); + } + + AsyncError errorCallback(Object error, StackTrace stackTrace) { + var implementation = this._errorCallback; + assert(implementation != null); + final Zone implementationZone = implementation.zone; + if (identical(implementationZone, _rootZone)) return null; + final ZoneDelegate parentDelegate = _parentDelegate(implementationZone); + ErrorCallbackHandler handler = implementation.function; + return handler(implementationZone, parentDelegate, this, error, stackTrace); + } + + void scheduleMicrotask(void f()) { + var implementation = this._scheduleMicrotask; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + ScheduleMicrotaskHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, f); + } + + Timer createTimer(Duration duration, void f()) { + var implementation = this._createTimer; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + CreateTimerHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, duration, f); + } + + Timer createPeriodicTimer(Duration duration, void f(Timer timer)) { + var implementation = this._createPeriodicTimer; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + CreatePeriodicTimerHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, duration, f); + } + + void print(String line) { + var implementation = this._print; + assert(implementation != null); + ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); + PrintHandler handler = implementation.function; + return handler(implementation.zone, parentDelegate, this, line); + } +} + +void _rootHandleUncaughtError( + Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { + _schedulePriorityAsyncCallback(() { + if (error == null) error = new NullThrownError(); + if (stackTrace == null) throw error; + _rethrow(error, stackTrace); + }); +} + +external void _rethrow(Object error, StackTrace stackTrace); + +R _rootRun(Zone self, ZoneDelegate parent, Zone zone, R f()) { + if (Zone._current == zone) return f(); + + Zone old = Zone._enter(zone); + try { + return f(); + } finally { + Zone._leave(old); + } +} + +R _rootRunUnary( + Zone self, ZoneDelegate parent, Zone zone, R f(T arg), T arg) { + if (Zone._current == zone) return f(arg); + + Zone old = Zone._enter(zone); + try { + return f(arg); + } finally { + Zone._leave(old); + } +} + +R _rootRunBinary(Zone self, ZoneDelegate parent, Zone zone, + R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) { + if (Zone._current == zone) return f(arg1, arg2); + + Zone old = Zone._enter(zone); + try { + return f(arg1, arg2); + } finally { + Zone._leave(old); + } +} + +ZoneCallback _rootRegisterCallback( + Zone self, ZoneDelegate parent, Zone zone, R f()) { + return f; +} + +ZoneUnaryCallback _rootRegisterUnaryCallback( + Zone self, ZoneDelegate parent, Zone zone, R f(T arg)) { + return f; +} + +ZoneBinaryCallback _rootRegisterBinaryCallback( + Zone self, ZoneDelegate parent, Zone zone, R f(T1 arg1, T2 arg2)) { + return f; +} + +AsyncError _rootErrorCallback(Zone self, ZoneDelegate parent, Zone zone, + Object error, StackTrace stackTrace) => + null; + +void _rootScheduleMicrotask( + Zone self, ZoneDelegate parent, Zone zone, void f()) { + if (!identical(_rootZone, zone)) { + bool hasErrorHandler = !_rootZone.inSameErrorZone(zone); + if (hasErrorHandler) { + f = zone.bindCallbackGuarded(f); + } else { + f = zone.bindCallback(f); + } + // Use root zone as event zone if the function is already bound. + zone = _rootZone; + } + _scheduleAsyncCallback(f); +} + +Timer _rootCreateTimer(Zone self, ZoneDelegate parent, Zone zone, + Duration duration, void callback()) { + if (!identical(_rootZone, zone)) { + callback = zone.bindCallback(callback); + } + return Timer._createTimer(duration, callback); +} + +Timer _rootCreatePeriodicTimer(Zone self, ZoneDelegate parent, Zone zone, + Duration duration, void callback(Timer timer)) { + if (!identical(_rootZone, zone)) { + // TODO(floitsch): the return type should be 'void'. + callback = zone.bindUnaryCallback(callback); + } + return Timer._createPeriodicTimer(duration, callback); +} + +void _rootPrint(Zone self, ZoneDelegate parent, Zone zone, String line) { + printToConsole(line); +} + +void _printToZone(String line) { + Zone.current.print(line); +} + +Zone _rootFork(Zone self, ZoneDelegate parent, Zone zone, + ZoneSpecification specification, Map zoneValues) { + // TODO(floitsch): it would be nice if we could get rid of this hack. + // Change the static zoneOrDirectPrint function to go through zones + // from now on. + printToZone = _printToZone; + + if (specification == null) { + specification = const ZoneSpecification(); + } else if (specification is! _ZoneSpecification) { + throw new ArgumentError("ZoneSpecifications must be instantiated" + " with the provided constructor."); + } + Map valueMap; + if (zoneValues == null) { + if (zone is _Zone) { + valueMap = zone._map; + } else { + valueMap = new HashMap(); + } + } else { + valueMap = new HashMap.from(zoneValues); + } + return new _CustomZone(zone, specification, valueMap); +} + +class _RootZone extends _Zone { + const _RootZone(); + + _ZoneFunction get _run => + const _ZoneFunction(_rootZone, _rootRun); + _ZoneFunction get _runUnary => + const _ZoneFunction(_rootZone, _rootRunUnary); + _ZoneFunction get _runBinary => + const _ZoneFunction(_rootZone, _rootRunBinary); + _ZoneFunction get _registerCallback => + const _ZoneFunction(_rootZone, _rootRegisterCallback); + _ZoneFunction get _registerUnaryCallback => + const _ZoneFunction(_rootZone, _rootRegisterUnaryCallback); + _ZoneFunction get _registerBinaryCallback => + const _ZoneFunction(_rootZone, _rootRegisterBinaryCallback); + _ZoneFunction get _errorCallback => + const _ZoneFunction(_rootZone, _rootErrorCallback); + _ZoneFunction get _scheduleMicrotask => + const _ZoneFunction( + _rootZone, _rootScheduleMicrotask); + _ZoneFunction get _createTimer => + const _ZoneFunction(_rootZone, _rootCreateTimer); + _ZoneFunction get _createPeriodicTimer => + const _ZoneFunction( + _rootZone, _rootCreatePeriodicTimer); + _ZoneFunction get _print => + const _ZoneFunction(_rootZone, _rootPrint); + _ZoneFunction get _fork => + const _ZoneFunction(_rootZone, _rootFork); + _ZoneFunction get _handleUncaughtError => + const _ZoneFunction( + _rootZone, _rootHandleUncaughtError); + + // The parent zone. + _Zone get parent => null; + + /// The zone's scoped value declaration map. + /// + /// This is always a [HashMap]. + Map get _map => _rootMap; + + static Map _rootMap = new HashMap(); + + static ZoneDelegate _rootDelegate; + + ZoneDelegate get _delegate { + if (_rootDelegate != null) return _rootDelegate; + return _rootDelegate = new _ZoneDelegate(this); + } + + /** + * The closest error-handling zone. + * + * Returns `this` if `this` has an error-handler. Otherwise returns the + * parent's error-zone. + */ + Zone get errorZone => this; + + // Zone interface. + + void runGuarded(void f()) { + try { + if (identical(_rootZone, Zone._current)) { + f(); + return; + } + _rootRun(null, null, this, f); + } catch (e, s) { + handleUncaughtError(e, s); + } + } + + void runUnaryGuarded(void f(T arg), T arg) { + try { + if (identical(_rootZone, Zone._current)) { + f(arg); + return; + } + _rootRunUnary(null, null, this, f, arg); + } catch (e, s) { + handleUncaughtError(e, s); + } + } + + void runBinaryGuarded(void f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) { + try { + if (identical(_rootZone, Zone._current)) { + f(arg1, arg2); + return; + } + _rootRunBinary(null, null, this, f, arg1, arg2); + } catch (e, s) { + handleUncaughtError(e, s); + } + } + + ZoneCallback bindCallback(R f()) { + return () => this.run(f); + } + + ZoneUnaryCallback bindUnaryCallback(R f(T arg)) { + return (arg) => this.runUnary(f, arg); + } + + ZoneBinaryCallback bindBinaryCallback( + R f(T1 arg1, T2 arg2)) { + return (arg1, arg2) => this.runBinary(f, arg1, arg2); + } + + void Function() bindCallbackGuarded(void f()) { + return () => this.runGuarded(f); + } + + void Function(T) bindUnaryCallbackGuarded(void f(T arg)) { + return (arg) => this.runUnaryGuarded(f, arg); + } + + void Function(T1, T2) bindBinaryCallbackGuarded( + void f(T1 arg1, T2 arg2)) { + return (arg1, arg2) => this.runBinaryGuarded(f, arg1, arg2); + } + + operator [](Object key) => null; + + // Methods that can be customized by the zone specification. + + void handleUncaughtError(error, StackTrace stackTrace) { + _rootHandleUncaughtError(null, null, this, error, stackTrace); + } + + Zone fork({ZoneSpecification specification, Map zoneValues}) { + return _rootFork(null, null, this, specification, zoneValues); + } + + R run(R f()) { + if (identical(Zone._current, _rootZone)) return f(); + return _rootRun(null, null, this, f); + } + + R runUnary(R f(T arg), T arg) { + if (identical(Zone._current, _rootZone)) return f(arg); + return _rootRunUnary(null, null, this, f, arg); + } + + R runBinary(R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) { + if (identical(Zone._current, _rootZone)) return f(arg1, arg2); + return _rootRunBinary(null, null, this, f, arg1, arg2); + } + + ZoneCallback registerCallback(R f()) => f; + + ZoneUnaryCallback registerUnaryCallback(R f(T arg)) => f; + + ZoneBinaryCallback registerBinaryCallback( + R f(T1 arg1, T2 arg2)) => + f; + + AsyncError errorCallback(Object error, StackTrace stackTrace) => null; + + void scheduleMicrotask(void f()) { + _rootScheduleMicrotask(null, null, this, f); + } + + Timer createTimer(Duration duration, void f()) { + return Timer._createTimer(duration, f); + } + + Timer createPeriodicTimer(Duration duration, void f(Timer timer)) { + return Timer._createPeriodicTimer(duration, f); + } + + void print(String line) { + printToConsole(line); + } +} + +const _rootZone = const _RootZone(); + +/** + * Runs [body] in its own zone. + * + * Creates a new zone using [Zone.fork] based on [zoneSpecification] and + * [zoneValues], then runs [body] in that zone and returns the result. + * + * If [onError] is provided, it must have one of the types + * * `void Function(Object)` + * * `void Function(Object, StackTrace)` + * and the [onError] handler is used *both* to handle asynchronous errors + * by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification], + * if any, *and* to handle errors thrown synchronously by the call to [body]. + * + * If an error occurs synchronously in [body], + * then throwing in the [onError] handler + * makes the call to `runZone` throw that error, + * and otherwise the call to `runZoned` returns `null`. + * + * If the zone specification has a `handleUncaughtError` value or the [onError] + * parameter is provided, the zone becomes an error-zone. + * + * Errors will never cross error-zone boundaries by themselves. + * Errors that try to cross error-zone boundaries are considered uncaught in + * their originating error zone. + * + * var future = new Future.value(499); + * runZoned(() { + * var future2 = future.then((_) { throw "error in first error-zone"; }); + * runZoned(() { + * var future3 = future2.catchError((e) { print("Never reached!"); }); + * }, onError: (e) { print("unused error handler"); }); + * }, onError: (e) { print("catches error of first error-zone."); }); + * + * Example: + * + * runZoned(() { + * new Future(() { throw "asynchronous error"; }); + * }, onError: print); // Will print "asynchronous error". + * + * It is possible to manually pass an error from one error zone to another + * by re-throwing it in the new zone. If [onError] throws, that error will + * occur in the original zone where [runZoned] was called. + */ +R runZoned(R body(), + {Map zoneValues, ZoneSpecification zoneSpecification, Function onError}) { + if (onError == null) { + return _runZoned(body, zoneValues, zoneSpecification); + } + void Function(Object) unaryOnError; + void Function(Object, StackTrace) binaryOnError; + if (onError is void Function(Object, StackTrace)) { + binaryOnError = onError; + } else if (onError is void Function(Object)) { + unaryOnError = onError; + } else { + throw new ArgumentError("onError callback must take either an Object " + "(the error), or both an Object (the error) and a StackTrace."); + } + HandleUncaughtErrorHandler errorHandler = (Zone self, ZoneDelegate parent, + Zone zone, error, StackTrace stackTrace) { + try { + if (binaryOnError != null) { + self.parent.runBinary(binaryOnError, error, stackTrace); + } else { + assert(unaryOnError != null); + self.parent.runUnary(unaryOnError, error); + } + } catch (e, s) { + if (identical(e, error)) { + parent.handleUncaughtError(zone, error, stackTrace); + } else { + parent.handleUncaughtError(zone, e, s); + } + } + }; + if (zoneSpecification == null) { + zoneSpecification = + new ZoneSpecification(handleUncaughtError: errorHandler); + } else { + zoneSpecification = new ZoneSpecification.from(zoneSpecification, + handleUncaughtError: errorHandler); + } + try { + return _runZoned(body, zoneValues, zoneSpecification); + } catch (e, stackTrace) { + if (binaryOnError != null) { + binaryOnError(e, stackTrace); + } else { + assert(unaryOnError != null); + unaryOnError(e); + } + } + return null; +} + +/// Runs [body] in a new zone based on [zoneValues] and [specification]. +R _runZoned(R body(), Map zoneValues, ZoneSpecification specification) => + Zone.current + .fork(specification: specification, zoneValues: zoneValues) + .run(body); +NN<*;>J$@,LQB?@OE&CIH5':"MI6=D6H$+!*1<JH'L'A-IOM#9#7 "0:<*2&6/P:=&(6@B08,< !"O.1FB D=I7O%#6 "0:<*2&6'ODB8'#() $&8"$2<>,4(8'NFHKNMK2NK K,L>E2N9NC)L/=N&IL +BJPQ6PIOOQNKHP P3HPPPNNQJO'HNPP1II9N PQN+KONO&%$,'+HQ8JCQQKM%Q3:'-MMM B#H M":QKD= O QN+GA>A9@ HM(.ML9NO1KK"@%C&O6GNC?L 6J QIF % ' "B!@J*!L0JQOMJ3IGGN:50>J0>C%IE-1IJ:KIFI?/HK D38HK I@KIFP;2NJMIL4NK5PDQO&0OPEA2DLFN+B9KJI= 64M3  ,"(7&5J<O%N+( .!)FA*BG1*2B36*7GO7*8N:>*?BOC*DBC*D*EBM;*5<G+?*@;>9*:LOA*BJ'3*4>J2*3O('N$)*167:B6F*(F))3"9!N %&-236>2B&$B%/"7.ICH/'?1D3EAL$KQ)M'8*;3/!C73%7QG95'+E)CG95'&J3 +!2 +!N + !+*'@/4?0C2*.@/;;"0J@@HIL?;4$HBGA%$H3O$$H2B()$H7GD*$H8N61$H?IK6$HDIC&7$HEIB.$9?MH70/"'%54&J +1 %!2 +1/!N +17!+!@1?E2%@2;"A#?;CAC9*(<4DC<3HC$ I%13,F4% IG;)JQN/*18P:@M!+PO>J 9@KK;O>&361 KIM1 +#A&3!=0#B F,>!$ $IMDjfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dartA// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Patch file for the dart:async library. + +import 'dart:_js_helper' + show notNull, patch, setTraceForException, ReifyFunctionTypes; +import 'dart:_isolate_helper' + show TimerImpl, global, leaveJsAsync, enterJsAsync; +import 'dart:_foreign_helper' show JS, JSExportName; +import 'dart:_runtime' as dart; + +typedef void _Callback(); +typedef void _TakeCallback(_Callback callback); + +/// This function adapts ES6 generators to implement Dart's async/await. +/// +/// It's designed to interact with Dart's Future and follow Dart async/await +/// semantics. +/// +/// See https://github.com/dart-lang/sdk/issues/27315 for ideas on reconciling +/// Dart's Future and ES6 Promise. At that point we should use native JS +/// async/await. +/// +/// Inspired by `co`: https://github.com/tj/co/blob/master/index.js, which is a +/// stepping stone for ES async/await. +@JSExportName('async') +@ReifyFunctionTypes(false) +_async(Function() initGenerator) { + var iter; + Object Function(Object) onValue; + Object Function(Object) onError; + + onAwait(Object value) { + _Future f; + if (value is _Future) { + f = value; + } else if (value is Future) { + f = _Future(); + _Future._chainForeignFuture(value, f); + } else { + f = _Future.value(value); + } + f = JS('', '#', f._thenNoZoneRegistration(onValue, onError)); + return f; + } + + onValue = (value) { + var iteratorResult = JS('', '#.next(#)', iter, value); + value = JS('', '#.value', iteratorResult); + return JS('bool', '#.done', iteratorResult) ? value : onAwait(value); + }; + + // If the awaited Future throws, we want to convert this to an exception + // thrown from the `yield` point, as if it was thrown there. + // + // If the exception is not caught inside `gen`, it will emerge here, which + // will send it to anyone listening on this async function's Future. + // + // In essence, we are giving the code inside the generator a chance to + // use try-catch-finally. + onError = (value) { + var iteratorResult = JS('', '#.throw(#)', iter, value); + value = JS('', '#.value', iteratorResult); + return JS('bool', '#.done', iteratorResult) ? value : onAwait(value); + }; + + var zone = Zone.current; + if (!identical(zone, _rootZone)) { + onValue = zone.registerUnaryCallback(onValue); + onError = zone.registerUnaryCallback(onError); + } + + var asyncFuture = _Future(); + + // This will be set to true once we've yielded to the event loop. + // + // Before we've done that, we need to complete the future asynchronously to + // match dart2js/VM. See https://github.com/dart-lang/sdk/issues/33330 + // + // Once we've yielded to the event loop we can complete synchronously. + // Other implementations call this `isSync` to indicate that. + bool isRunningAsEvent = false; + runBody() { + try { + iter = JS('', '#[Symbol.iterator]()', initGenerator()); + var iteratorValue = JS('', '#.next(null)', iter); + var value = JS('', '#.value', iteratorValue); + if (JS('bool', '#.done', iteratorValue)) { + // TODO(jmesserly): this is a workaround for ignored cast failures. + // Remove it once we've fixed those. We should be able to call: + // + // if (isRunningAsEvent) { + // asyncFuture._complete(value); + // } else { + // asyncFuture._asyncComplete(value); + // } + // + // But if the user code returns `Future` instead of + // `Future`, that function won't recognize it as a future and will + // instead treat it as a completed value. + if (value is Future) { + if (value is _Future) { + _Future._chainCoreFuture(value, asyncFuture); + } else { + _Future._chainForeignFuture(value, asyncFuture); + } + } else if (isRunningAsEvent) { + asyncFuture._completeWithValue(JS('', '#', value)); + } else { + asyncFuture._asyncComplete(JS('', '#', value)); + } + } else { + _Future._chainCoreFuture(onAwait(value), asyncFuture); + } + } catch (e, s) { + if (isRunningAsEvent) { + _completeWithErrorCallback(asyncFuture, e, s); + } else { + _asyncCompleteWithErrorCallback(asyncFuture, e, s); + } + } + } + + if (dart.startAsyncSynchronously) { + runBody(); + isRunningAsEvent = true; + } else { + isRunningAsEvent = true; + scheduleMicrotask(runBody); + } + return asyncFuture; +} + +@patch +class _AsyncRun { + @patch + static void _scheduleImmediate(void callback()) { + _scheduleImmediateClosure(callback); + } + + // Lazily initialized. + static final _TakeCallback _scheduleImmediateClosure = + _initializeScheduleImmediate(); + + static _TakeCallback _initializeScheduleImmediate() { + // TODO(rnystrom): Not needed by dev_compiler. + // requiresPreamble(); + if (JS('', '#.scheduleImmediate', global) != null) { + return _scheduleImmediateJsOverride; + } + if (JS('', '#.MutationObserver', global) != null && + JS('', '#.document', global) != null) { + // Use mutationObservers. + var div = JS('', '#.document.createElement("div")', global); + var span = JS('', '#.document.createElement("span")', global); + _Callback storedCallback; + + internalCallback(_) { + leaveJsAsync(); + var f = storedCallback; + storedCallback = null; + f(); + } + + ; + + var observer = + JS('', 'new #.MutationObserver(#)', global, internalCallback); + JS('', '#.observe(#, { childList: true })', observer, div); + + return (void callback()) { + assert(storedCallback == null); + enterJsAsync(); + storedCallback = callback; + // Because of a broken shadow-dom polyfill we have to change the + // children instead a cheap property. + // See https://github.com/Polymer/ShadowDOM/issues/468 + JS('', '#.firstChild ? #.removeChild(#): #.appendChild(#)', div, div, + span, div, span); + }; + } else if (JS('', '#.setImmediate', global) != null) { + return _scheduleImmediateWithSetImmediate; + } + // TODO(20055): We should use DOM promises when available. + return _scheduleImmediateWithTimer; + } + + static void _scheduleImmediateJsOverride(void callback()) { + internalCallback() { + leaveJsAsync(); + callback(); + } + + ; + enterJsAsync(); + JS('void', '#.scheduleImmediate(#)', global, internalCallback); + } + + static void _scheduleImmediateWithSetImmediate(void callback()) { + internalCallback() { + leaveJsAsync(); + callback(); + } + + ; + enterJsAsync(); + JS('void', '#.setImmediate(#)', global, internalCallback); + } + + static void _scheduleImmediateWithTimer(void callback()) { + Timer._createTimer(Duration.zero, callback); + } +} + +@patch +class DeferredLibrary { + @patch + Future load() { + throw 'DeferredLibrary not supported. ' + 'please use the `import "lib.dart" deferred as lib` syntax.'; + } +} + +@patch +class Timer { + @patch + static Timer _createTimer(Duration duration, void callback()) { + int milliseconds = duration.inMilliseconds; + if (milliseconds < 0) milliseconds = 0; + return TimerImpl(milliseconds, callback); + } + + @patch + static Timer _createPeriodicTimer( + Duration duration, void callback(Timer timer)) { + int milliseconds = duration.inMilliseconds; + if (milliseconds < 0) milliseconds = 0; + return TimerImpl.periodic(milliseconds, callback); + } +} + +@patch +void _rethrow(Object error, StackTrace stackTrace) { + setTraceForException(error, stackTrace); + dart.throw_(error); +} + +/// Used by the compiler to implement `async*` functions. +/// +/// This is inspired by _AsyncStarStreamController in dart-lang/sdk's +/// runtime/lib/core_patch.dart +/// +/// Given input like: +/// +/// foo() async* { +/// yield 1; +/// yield* bar(); +/// print(await baz()); +/// } +/// +/// This compiles to: +/// +/// function foo() { +/// return new (AsyncStarImplOfT()).new(function*(stream) { +/// if (stream.add(1)) return; +/// yield; +/// if (stream.addStream(bar()) return; +/// yield; +/// print(yield baz()); +/// }); +/// } +/// +class _AsyncStarImpl { + StreamController controller; + Object Function(_AsyncStarImpl) initGenerator; + @notNull + bool isSuspendedAtYieldStar = false; + @notNull + bool onListenReceived = false; + @notNull + bool isScheduled = false; + @notNull + bool isSuspendedAtYield = false; + + /// Whether we're suspended at an `await`. + @notNull + bool isSuspendedAtAwait = false; + + Completer cancellationCompleter; + Object jsIterator; + + Null Function(Object, StackTrace) _handleErrorCallback; + void Function([Object]) _runBodyCallback; + + _AsyncStarImpl(this.initGenerator) { + controller = StreamController( + onListen: JS('!', 'this.onListen.bind(this)'), + onResume: JS('!', 'this.onResume.bind(this)'), + onCancel: JS('!', 'this.onCancel.bind(this)')); + jsIterator = JS('!', '#[Symbol.iterator]()', initGenerator(this)); + } + + /// The stream produced by this `async*` function. + Stream get stream => controller.stream; + + /// Returns the callback used for error handling. + /// + /// This callback throws the error back into the user code, at the appropriate + /// location (e.g. `await` `yield` or `yield*`). This gives user code a chance + /// to handle it try-catch. If they do not handle, the error gets routed to + /// the [stream] as an error via [addError]. + /// + /// As a performance optimization, this callback is only bound once to the + /// current [Zone]. This works because a single subscription stream should + /// always be running in its original zone. An `async*` method will always + /// save/restore the zone that was active when `listen()` was first called, + /// similar to a stream. This follows from section 16.14 of the Dart 4th + /// edition spec: + /// + /// > If `f` is marked `async*` (9), then a fresh instance `s` implementing + /// > the built-in class `Stream` is associated with the invocation and + /// > immediately returned. When `s` is listened to, execution of the body of + /// > `f` will begin. + /// + Null Function(Object, StackTrace) get handleError { + if (_handleErrorCallback == null) { + _handleErrorCallback = (error, StackTrace stackTrace) { + try { + JS('', '#.throw(#)', jsIterator, error); + } catch (e) { + addError(e, stackTrace); + } + }; + var zone = Zone.current; + if (!identical(zone, Zone.root)) { + _handleErrorCallback = zone.bindBinaryCallback(_handleErrorCallback); + } + } + return _handleErrorCallback; + } + + void scheduleGenerator() { + // TODO(jmesserly): is this isPaused check in the right place? Assuming the + // async* Stream yields, then is paused (by other code), the body will + // already be scheduled. This will cause at least one more iteration to + // run (adding another data item to the Stream) before actually pausing. + // It could be fixed by moving the `isPaused` check inside `runBody`. + if (isScheduled || + controller.isPaused || + isSuspendedAtYieldStar || + isSuspendedAtAwait) { + return; + } + isScheduled = true; + // Capture the current zone. See comment on [handleError] for more + // information about this optimization. + var zone = Zone.current; + if (_runBodyCallback == null) { + _runBodyCallback = JS('!', '#.bind(this)', runBody); + if (!identical(zone, Zone.root)) { + var registered = zone.registerUnaryCallback(_runBodyCallback); + _runBodyCallback = ([arg]) => zone.runUnaryGuarded(registered, arg); + } + } + zone.scheduleMicrotask(_runBodyCallback); + } + + void runBody(awaitValue) { + isScheduled = false; + isSuspendedAtYield = false; + isSuspendedAtAwait = false; + + Object iterResult; + try { + iterResult = JS('', '#.next(#)', jsIterator, awaitValue); + } catch (e, s) { + addError(e, s); + close(); + return null; + } + + if (JS('!', '#.done', iterResult)) { + close(); + return null; + } + + // If we're suspended at a yield/yield*, we're done for now. + if (isSuspendedAtYield || isSuspendedAtYieldStar) return null; + + // Handle `await`: if we get a value passed to `yield` it means we are + // waiting on this Future. Make sure to prevent scheduling, and pass the + // value back as the result of the `yield`. + // + // TODO(jmesserly): is the timing here correct? The assumption here is + // that we should schedule `await` in `async*` the same as in `async`. + isSuspendedAtAwait = true; + FutureOr value = JS('', '#.value', iterResult); + + // TODO(jmesserly): this logic was copied from `async` function impl. + _Future f; + if (value is _Future) { + f = value; + } else if (value is Future) { + f = _Future(); + _Future._chainForeignFuture(value, f); + } else { + f = _Future.value(value); + } + f._thenNoZoneRegistration(_runBodyCallback, handleError); + } + + /// Adds element to [stream] and returns true if the caller should terminate + /// execution of the generator. + /// + /// This is called from generated code like this: + /// + /// if (controller.add(1)) return; + /// yield; + // + // TODO(hausner): Per spec, the generator should be suspended before exiting + // when the stream is closed. We could add a getter like this: + // + // get isCancelled => controller.hasListener; + // + // The generator would translate a 'yield e' statement to + // + // controller.add(1); + // suspend; // this is `yield` in JS. + // if (controller.isCancelled) return; + bool add(T event) { + if (!onListenReceived) _fatal("yield before stream is listened to"); + if (isSuspendedAtYield) _fatal("unexpected yield"); + // If stream is cancelled, tell caller to exit the async generator. + if (!controller.hasListener) { + return true; + } + controller.add(event); + scheduleGenerator(); + isSuspendedAtYield = true; + return false; + } + + /// Adds the elements of [stream] into this [controller]'s stream, and returns + /// true if the caller should terminate execution of the generator. + /// + /// The generator will be scheduled again when all of the elements of the + /// added stream have been consumed. + bool addStream(Stream stream) { + if (!onListenReceived) _fatal("yield* before stream is listened to"); + // If stream is cancelled, tell caller to exit the async generator. + if (!controller.hasListener) return true; + isSuspendedAtYieldStar = true; + var whenDoneAdding = controller.addStream(stream, cancelOnError: false); + whenDoneAdding.then((_) { + isSuspendedAtYieldStar = false; + scheduleGenerator(); + if (!isScheduled) isSuspendedAtYield = true; + }, onError: handleError); + return false; + } + + void addError(Object error, StackTrace stackTrace) { + if (cancellationCompleter != null && !cancellationCompleter.isCompleted) { + // If the stream has been cancelled, complete the cancellation future + // with the error. + cancellationCompleter.completeError(error, stackTrace); + return; + } + // If stream is cancelled, tell caller to exit the async generator. + if (!controller.hasListener) return; + controller.addError(error, stackTrace); + // No need to schedule the generator body here. This code is only + // called from the catch clause of the implicit try-catch-finally + // around the generator body. That is, we are on the error path out + // of the generator and do not need to run the generator again. + } + + close() { + if (cancellationCompleter != null && !cancellationCompleter.isCompleted) { + // If the stream has been cancelled, complete the cancellation future + // with the error. + cancellationCompleter.complete(); + } + controller.close(); + } + + onListen() { + assert(!onListenReceived); + onListenReceived = true; + scheduleGenerator(); + } + + onResume() { + if (isSuspendedAtYield) { + scheduleGenerator(); + } + } + + onCancel() { + if (controller.isClosed) { + return null; + } + if (cancellationCompleter == null) { + cancellationCompleter = Completer(); + // Only resume the generator if it is suspended at a yield. + // Cancellation does not affect an async generator that is + // suspended at an await. + if (isSuspendedAtYield) { + scheduleGenerator(); + } + } + return cancellationCompleter.future; + } + + _fatal(String message) => throw StateError(message); +} +NN<*C85 0IMOIP'& ##"- B;/JK?MJI841LH '/4 EN2":= '>: +?7<&   4)9&839+80 CE   IB!(#I.?N ;1?(>DD?=1 ,F B0,. %70,75+:F  +B'0 +"4 ' !  #- ##:,'#778G5-4QQN/MMMNKNJP6(>3# + )N!PKLMJ"G,$;)GM.  +@)ACKM0KK<J"- >O"4)OA4<,-I8H#QFL'%JH.#M&37OL>H),FFHD OL()+BA )7bfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/broadcast_stream_controller.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +class _BroadcastStream extends _ControllerStream { + _BroadcastStream(_StreamControllerLifecycle controller) + : super(controller); + + bool get isBroadcast => true; +} + +class _BroadcastSubscription extends _ControllerSubscription { + static const int _STATE_EVENT_ID = 1; + static const int _STATE_FIRING = 2; + static const int _STATE_REMOVE_AFTER_FIRING = 4; + // TODO(lrn): Use the _state field on _ControllerSubscription to + // also store this state. Requires that the subscription implementation + // does not assume that it's use of the state integer is the only use. + int _eventState = 0; // Initialized to help dart2js type inference. + + _BroadcastSubscription _next; + _BroadcastSubscription _previous; + + _BroadcastSubscription(_StreamControllerLifecycle controller, + void onData(T data), Function onError, void onDone(), bool cancelOnError) + : super(controller, onData, onError, onDone, cancelOnError) { + _next = _previous = this; + } + + bool _expectsEvent(int eventId) => (_eventState & _STATE_EVENT_ID) == eventId; + + void _toggleEventId() { + _eventState ^= _STATE_EVENT_ID; + } + + bool get _isFiring => (_eventState & _STATE_FIRING) != 0; + + void _setRemoveAfterFiring() { + assert(_isFiring); + _eventState |= _STATE_REMOVE_AFTER_FIRING; + } + + bool get _removeAfterFiring => + (_eventState & _STATE_REMOVE_AFTER_FIRING) != 0; + + // The controller._recordPause doesn't do anything for a broadcast controller, + // so we don't bother calling it. + void _onPause() {} + + // The controller._recordResume doesn't do anything for a broadcast + // controller, so we don't bother calling it. + void _onResume() {} + + // _onCancel is inherited. +} + +abstract class _BroadcastStreamController + implements + StreamController, + _StreamControllerLifecycle, + _EventSink, + _EventDispatch { + static const int _STATE_INITIAL = 0; + static const int _STATE_EVENT_ID = 1; + static const int _STATE_FIRING = 2; + static const int _STATE_CLOSED = 4; + static const int _STATE_ADDSTREAM = 8; + + ControllerCallback onListen; + ControllerCancelCallback onCancel; + + // State of the controller. + int _state; + + // Double-linked list of active listeners. + _BroadcastSubscription _firstSubscription; + _BroadcastSubscription _lastSubscription; + + // Extra state used during an [addStream] call. + _AddStreamState _addStreamState; + + /** + * Future returned by [close] and [done]. + * + * The future is completed whenever the done event has been sent to all + * relevant listeners. + * The relevant listeners are the ones that were listening when [close] was + * called. When all of these have been canceled (sending the done event makes + * them cancel, but they can also be canceled before sending the event), + * this future completes. + * + * Any attempt to listen after calling [close] will throw, so there won't + * be any further listeners. + */ + _Future _doneFuture; + + _BroadcastStreamController(this.onListen, this.onCancel) + : _state = _STATE_INITIAL; + + ControllerCallback get onPause { + throw new UnsupportedError( + "Broadcast stream controllers do not support pause callbacks"); + } + + void set onPause(void onPauseHandler()) { + throw new UnsupportedError( + "Broadcast stream controllers do not support pause callbacks"); + } + + ControllerCallback get onResume { + throw new UnsupportedError( + "Broadcast stream controllers do not support pause callbacks"); + } + + void set onResume(void onResumeHandler()) { + throw new UnsupportedError( + "Broadcast stream controllers do not support pause callbacks"); + } + + // StreamController interface. + + Stream get stream => new _BroadcastStream(this); + + StreamSink get sink => new _StreamSinkWrapper(this); + + bool get isClosed => (_state & _STATE_CLOSED) != 0; + + /** + * A broadcast controller is never paused. + * + * Each receiving stream may be paused individually, and they handle their + * own buffering. + */ + bool get isPaused => false; + + /** Whether there are currently one or more subscribers. */ + bool get hasListener => !_isEmpty; + + /** + * Test whether the stream has exactly one listener. + * + * Assumes that the stream has a listener (not [_isEmpty]). + */ + bool get _hasOneListener { + assert(!_isEmpty); + return identical(_firstSubscription, _lastSubscription); + } + + /** Whether an event is being fired (sent to some, but not all, listeners). */ + bool get _isFiring => (_state & _STATE_FIRING) != 0; + + bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0; + + bool get _mayAddEvent => (_state < _STATE_CLOSED); + + _Future _ensureDoneFuture() { + if (_doneFuture != null) return _doneFuture; + return _doneFuture = new _Future(); + } + + // Linked list helpers + + bool get _isEmpty => _firstSubscription == null; + + /** Adds subscription to linked list of active listeners. */ + void _addListener(_BroadcastSubscription subscription) { + assert(identical(subscription._next, subscription)); + subscription._eventState = (_state & _STATE_EVENT_ID); + // Insert in linked list as last subscription. + _BroadcastSubscription oldLast = _lastSubscription; + _lastSubscription = subscription; + subscription._next = null; + subscription._previous = oldLast; + if (oldLast == null) { + _firstSubscription = subscription; + } else { + oldLast._next = subscription; + } + } + + void _removeListener(_BroadcastSubscription subscription) { + assert(identical(subscription._controller, this)); + assert(!identical(subscription._next, subscription)); + _BroadcastSubscription previous = subscription._previous; + _BroadcastSubscription next = subscription._next; + if (previous == null) { + // This was the first subscription. + _firstSubscription = next; + } else { + previous._next = next; + } + if (next == null) { + // This was the last subscription. + _lastSubscription = previous; + } else { + next._previous = previous; + } + + subscription._next = subscription._previous = subscription; + } + + // _StreamControllerLifecycle interface. + + StreamSubscription _subscribe(void onData(T data), Function onError, + void onDone(), bool cancelOnError) { + if (isClosed) { + if (onDone == null) onDone = _nullDoneHandler; + return new _DoneStreamSubscription(onDone); + } + StreamSubscription subscription = new _BroadcastSubscription( + this, onData, onError, onDone, cancelOnError); + _addListener(subscription); + if (identical(_firstSubscription, _lastSubscription)) { + // Only one listener, so it must be the first listener. + _runGuarded(onListen); + } + return subscription; + } + + Future _recordCancel(StreamSubscription sub) { + _BroadcastSubscription subscription = sub; + // If already removed by the stream, don't remove it again. + if (identical(subscription._next, subscription)) return null; + if (subscription._isFiring) { + subscription._setRemoveAfterFiring(); + } else { + _removeListener(subscription); + // If we are currently firing an event, the empty-check is performed at + // the end of the listener loop instead of here. + if (!_isFiring && _isEmpty) { + _callOnCancel(); + } + } + return null; + } + + void _recordPause(StreamSubscription subscription) {} + void _recordResume(StreamSubscription subscription) {} + + // EventSink interface. + + Error _addEventError() { + if (isClosed) { + return new StateError("Cannot add new events after calling close"); + } + assert(_isAddingStream); + return new StateError("Cannot add new events while doing an addStream"); + } + + void add(T data) { + if (!_mayAddEvent) throw _addEventError(); + _sendData(data); + } + + void addError(Object error, [StackTrace stackTrace]) { + error = _nonNullError(error); + if (!_mayAddEvent) throw _addEventError(); + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + _sendError(error, stackTrace); + } + + Future close() { + if (isClosed) { + assert(_doneFuture != null); + return _doneFuture; + } + if (!_mayAddEvent) throw _addEventError(); + _state |= _STATE_CLOSED; + Future doneFuture = _ensureDoneFuture(); + _sendDone(); + return doneFuture; + } + + Future get done => _ensureDoneFuture(); + + Future addStream(Stream stream, {bool cancelOnError}) { + if (!_mayAddEvent) throw _addEventError(); + _state |= _STATE_ADDSTREAM; + _addStreamState = new _AddStreamState(this, stream, cancelOnError ?? false); + return _addStreamState.addStreamFuture; + } + + // _EventSink interface, called from AddStreamState. + void _add(T data) { + _sendData(data); + } + + void _addError(Object error, StackTrace stackTrace) { + _sendError(error, stackTrace); + } + + void _close() { + assert(_isAddingStream); + _AddStreamState addState = _addStreamState; + _addStreamState = null; + _state &= ~_STATE_ADDSTREAM; + addState.complete(); + } + + // Event handling. + void _forEachListener( + void action(_BufferingStreamSubscription subscription)) { + if (_isFiring) { + throw new StateError( + "Cannot fire new event. Controller is already firing an event"); + } + if (_isEmpty) return; + + // Get event id of this event. + int id = (_state & _STATE_EVENT_ID); + // Start firing (set the _STATE_FIRING bit). We don't do [onCancel] + // callbacks while firing, and we prevent reentrancy of this function. + // + // Set [_state]'s event id to the next event's id. + // Any listeners added while firing this event will expect the next event, + // not this one, and won't get notified. + _state ^= _STATE_EVENT_ID | _STATE_FIRING; + _BroadcastSubscription subscription = _firstSubscription; + while (subscription != null) { + if (subscription._expectsEvent(id)) { + subscription._eventState |= _BroadcastSubscription._STATE_FIRING; + action(subscription); + subscription._toggleEventId(); + _BroadcastSubscription next = subscription._next; + if (subscription._removeAfterFiring) { + _removeListener(subscription); + } + subscription._eventState &= ~_BroadcastSubscription._STATE_FIRING; + subscription = next; + } else { + subscription = subscription._next; + } + } + _state &= ~_STATE_FIRING; + + if (_isEmpty) { + _callOnCancel(); + } + } + + void _callOnCancel() { + assert(_isEmpty); + if (isClosed && _doneFuture._mayComplete) { + // When closed, _doneFuture is not null. + _doneFuture._asyncComplete(null); + } + _runGuarded(onCancel); + } +} + +class _SyncBroadcastStreamController extends _BroadcastStreamController + implements SynchronousStreamController { + _SyncBroadcastStreamController(void onListen(), void onCancel()) + : super(onListen, onCancel); + + // EventDispatch interface. + + bool get _mayAddEvent => super._mayAddEvent && !_isFiring; + + _addEventError() { + if (_isFiring) { + return new StateError( + "Cannot fire new event. Controller is already firing an event"); + } + return super._addEventError(); + } + + void _sendData(T data) { + if (_isEmpty) return; + if (_hasOneListener) { + _state |= _BroadcastStreamController._STATE_FIRING; + _BroadcastSubscription subscription = _firstSubscription; + subscription._add(data); + _state &= ~_BroadcastStreamController._STATE_FIRING; + if (_isEmpty) { + _callOnCancel(); + } + return; + } + _forEachListener((_BufferingStreamSubscription subscription) { + subscription._add(data); + }); + } + + void _sendError(Object error, StackTrace stackTrace) { + if (_isEmpty) return; + _forEachListener((_BufferingStreamSubscription subscription) { + subscription._addError(error, stackTrace); + }); + } + + void _sendDone() { + if (!_isEmpty) { + _forEachListener((_BufferingStreamSubscription subscription) { + subscription._close(); + }); + } else { + assert(_doneFuture != null); + assert(_doneFuture._mayComplete); + _doneFuture._asyncComplete(null); + } + } +} + +class _AsyncBroadcastStreamController extends _BroadcastStreamController { + _AsyncBroadcastStreamController(void onListen(), void onCancel()) + : super(onListen, onCancel); + + // EventDispatch interface. + + void _sendData(T data) { + for (_BroadcastSubscription subscription = _firstSubscription; + subscription != null; + subscription = subscription._next) { + subscription._addPending(new _DelayedData(data)); + } + } + + void _sendError(Object error, StackTrace stackTrace) { + for (_BroadcastSubscription subscription = _firstSubscription; + subscription != null; + subscription = subscription._next) { + subscription._addPending(new _DelayedError(error, stackTrace)); + } + } + + void _sendDone() { + if (!_isEmpty) { + for (_BroadcastSubscription subscription = _firstSubscription; + subscription != null; + subscription = subscription._next) { + subscription._addPending(const _DelayedDone()); + } + } else { + assert(_doneFuture != null); + assert(_doneFuture._mayComplete); + _doneFuture._asyncComplete(null); + } + } +} + +/** + * Stream controller that is used by [Stream.asBroadcastStream]. + * + * This stream controller allows incoming events while it is firing + * other events. This is handled by delaying the events until the + * current event is done firing, and then fire the pending events. + * + * This class extends [_SyncBroadcastStreamController]. Events of + * an "asBroadcastStream" stream are always initiated by events + * on another stream, and it is fine to forward them synchronously. + */ +class _AsBroadcastStreamController extends _SyncBroadcastStreamController + implements _EventDispatch { + _StreamImplEvents _pending; + + _AsBroadcastStreamController(void onListen(), void onCancel()) + : super(onListen, onCancel); + + bool get _hasPending => _pending != null && !_pending.isEmpty; + + void _addPendingEvent(_DelayedEvent event) { + if (_pending == null) { + _pending = new _StreamImplEvents(); + } + _pending.add(event); + } + + void add(T data) { + if (!isClosed && _isFiring) { + _addPendingEvent(new _DelayedData(data)); + return; + } + super.add(data); + while (_hasPending) { + _pending.handleNext(this); + } + } + + void addError(Object error, [StackTrace stackTrace]) { + if (!isClosed && _isFiring) { + _addPendingEvent(new _DelayedError(error, stackTrace)); + return; + } + if (!_mayAddEvent) throw _addEventError(); + _sendError(error, stackTrace); + while (_hasPending) { + _pending.handleNext(this); + } + } + + Future close() { + if (!isClosed && _isFiring) { + _addPendingEvent(const _DelayedDone()); + _state |= _BroadcastStreamController._STATE_CLOSED; + return super.done; + } + Future result = super.close(); + assert(!_hasPending); + return result; + } + + void _callOnCancel() { + if (_hasPending) { + _pending.clear(); + _pending = null; + } + super._callOnCancel(); + } +} +NN<9= E(&3CJIF#'CPDQ$<!/!7Q$F0-''(&&)%-0/2&,JNPKL;!# H, H$ H. H!9=6-M>%7>=Q7@5 1(3?>9;3;&&) $A7:A9*! )$ !@+J+55H7 <>42@B", %N7$;<JM/9"/L0+##/-*=/ Q,78#0!CK#)HK7O-/A#,J'=/) +K+0/(N0C#=K#:C;F9F1H + #((QD#F-;9F-FH /8 #((ADBCB@DP#!A#A/-"3!9">/#!".:#Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/deferred_load.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +/** + * Indicates that loading of [libraryName] is deferred. + * + * This class is obsolete. Instead use the syntax: + * import "library.dart" deferred as prefix; + */ +@Deprecated("Dart sdk v. 1.8") +class DeferredLibrary { + final String libraryName; + final String uri; + + const DeferredLibrary(this.libraryName, {this.uri}); + + /** + * Ensure that [libraryName] has been loaded. + * + * If the library fails to load, the Future will complete with a + * DeferredLoadException. + */ + external Future load(); +} + +/** + * Thrown when a deferred library fails to load. + */ +class DeferredLoadException implements Exception { + DeferredLoadException(this._s); + String toString() => "DeferredLoadException: '$_s'"; + final String _s; +} +&NN<83-70C 13"7Mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/future.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +/// A type representing values that are either `Future` or `T`. +/// +/// This class declaration is a public stand-in for an internal +/// future-or-value generic type. References to this class are resolved to the +/// internal type. +/// +/// It is a compile-time error for any class to extend, mix in or implement +/// `FutureOr`. +/// +/// Note: the `FutureOr` type is interpreted as `dynamic` in non strong-mode. +/// +/// # Examples +/// ``` dart +/// // The `Future.then` function takes a callback [f] that returns either +/// // an `S` or a `Future`. +/// Future then(FutureOr f(T x), ...); +/// +/// // `Completer.complete` takes either a `T` or `Future`. +/// void complete(FutureOr value); +/// ``` +/// +/// # Advanced +/// The `FutureOr` type is actually the "type union" of the types `int` and +/// `Future`. This type union is defined in such a way that +/// `FutureOr` is both a super- and sub-type of `Object` (sub-type +/// because `Object` is one of the types of the union, super-type because +/// `Object` is a super-type of both of the types of the union). Together it +/// means that `FutureOr` is equivalent to `Object`. +/// +/// As a corollary, `FutureOr` is equivalent to +/// `FutureOr>`, `FutureOr>` is equivalent to +/// `Future`. +abstract class FutureOr { + // Private generative constructor, so that it is not subclassable, mixable, or + // instantiable. + FutureOr._() { + throw new UnsupportedError("FutureOr can't be instantiated"); + } +} + +/** + * An object representing a delayed computation. + * + * A [Future] is used to represent a potential value, or error, + * that will be available at some time in the future. + * Receivers of a [Future] can register callbacks + * that handle the value or error once it is available. + * For example: + * + * Future future = getFuture(); + * future.then((value) => handleValue(value)) + * .catchError((error) => handleError(error)); + * + * A [Future] can be completed in two ways: + * with a value ("the future succeeds") + * or with an error ("the future fails"). + * Users can install callbacks for each case. + * + * In some cases we say that a future is completed with another future. + * This is a short way of stating that the future is completed in the same way, + * with the same value or error, + * as the other future once that completes. + * Whenever a function in the core library may complete a future + * (for example [Completer.complete] or [new Future.value]), + * then it also accepts another future and does this work for the developer. + * + * The result of registering a pair of callbacks is a new Future (the + * "successor") which in turn is completed with the result of invoking the + * corresponding callback. + * The successor is completed with an error if the invoked callback throws. + * For example: + * ``` + * Future successor = future.then((int value) { + * // Invoked when the future is completed with a value. + * return 42; // The successor is completed with the value 42. + * }, + * onError: (e) { + * // Invoked when the future is completed with an error. + * if (canHandle(e)) { + * return 499; // The successor is completed with the value 499. + * } else { + * throw e; // The successor is completed with the error e. + * } + * }); + * ``` + * + * If a future does not have a successor when it completes with an error, + * it forwards the error message to the global error-handler. + * This behavior makes sure that no error is silently dropped. + * However, it also means that error handlers should be installed early, + * so that they are present as soon as a future is completed with an error. + * The following example demonstrates this potential bug: + * ``` + * var future = getFuture(); + * new Timer(new Duration(milliseconds: 5), () { + * // The error-handler is not attached until 5 ms after the future has + * // been received. If the future fails before that, the error is + * // forwarded to the global error-handler, even though there is code + * // (just below) to eventually handle the error. + * future.then((value) { useValue(value); }, + * onError: (e) { handleError(e); }); + * }); + * ``` + * + * When registering callbacks, it's often more readable to register the two + * callbacks separately, by first using [then] with one argument + * (the value handler) and using a second [catchError] for handling errors. + * Each of these will forward the result that they don't handle + * to their successors, and together they handle both value and error result. + * It also has the additional benefit of the [catchError] handling errors in the + * [then] value callback too. + * Using sequential handlers instead of parallel ones often leads to code that + * is easier to reason about. + * It also makes asynchronous code very similar to synchronous code: + * ``` + * // Synchronous code. + * try { + * int value = foo(); + * return bar(value); + * } catch (e) { + * return 499; + * } + * ``` + * + * Equivalent asynchronous code, based on futures: + * ``` + * Future future = new Future(foo); // Result of foo() as a future. + * future.then((int value) => bar(value)) + * .catchError((e) => 499); + * ``` + * + * Similar to the synchronous code, the error handler (registered with + * [catchError]) is handling any errors thrown by either `foo` or `bar`. + * If the error-handler had been registered as the `onError` parameter of + * the `then` call, it would not catch errors from the `bar` call. + * + * Futures can have more than one callback-pair registered. Each successor is + * treated independently and is handled as if it was the only successor. + * + * A future may also fail to ever complete. In that case, no callbacks are + * called. + */ +abstract class Future { + /// A `Future` completed with `null`. + static final _Future _nullFuture = + new _Future.zoneValue(null, Zone.root); + + /// A `Future` completed with `false`. + static final _Future _falseFuture = + new _Future.zoneValue(false, Zone.root); + + /** + * Creates a future containing the result of calling [computation] + * asynchronously with [Timer.run]. + * + * If the result of executing [computation] throws, the returned future is + * completed with the error. + * + * If the returned value is itself a [Future], completion of + * the created future will wait until the returned future completes, + * and will then complete with the same result. + * + * If a non-future value is returned, the returned future is completed + * with that value. + */ + factory Future(FutureOr computation()) { + _Future result = new _Future(); + Timer.run(() { + try { + result._complete(computation()); + } catch (e, s) { + _completeWithErrorCallback(result, e, s); + } + }); + return result; + } + + /** + * Creates a future containing the result of calling [computation] + * asynchronously with [scheduleMicrotask]. + * + * If executing [computation] throws, + * the returned future is completed with the thrown error. + * + * If calling [computation] returns a [Future], completion of + * the created future will wait until the returned future completes, + * and will then complete with the same result. + * + * If calling [computation] returns a non-future value, + * the returned future is completed with that value. + */ + factory Future.microtask(FutureOr computation()) { + _Future result = new _Future(); + scheduleMicrotask(() { + try { + result._complete(computation()); + } catch (e, s) { + _completeWithErrorCallback(result, e, s); + } + }); + return result; + } + + /** + * Returns a future containing the result of immediately calling + * [computation]. + * + * If calling [computation] throws, the returned future is completed with the + * error. + * + * If calling [computation] returns a `Future`, that future is returned. + * + * If calling [computation] returns a non-future value, + * a future is returned which has been completed with that value. + */ + factory Future.sync(FutureOr computation()) { + try { + var result = computation(); + if (result is Future) { + return result; + } else if (result is Future) { + // TODO(lrn): Remove this case for Dart 2.0. + return new _Future.immediate(result); + } else { + return new _Future.value(result); + } + } catch (error, stackTrace) { + var future = new _Future(); + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + future._asyncCompleteError( + _nonNullError(replacement.error), replacement.stackTrace); + } else { + future._asyncCompleteError(error, stackTrace); + } + return future; + } + } + + /** + * Creates a future completed with [value]. + * + * If [value] is a future, the created future waits for the + * [value] future to complete, and then completes with the same result. + * Since a [value] future can complete with an error, so can the future + * created by [Future.value], even if the name suggests otherwise. + * + * If [value] is not a [Future], the created future is completed + * with the [value] value, + * equivalently to `new Future.sync(() => value)`. + * + * Use [Completer] to create a future and complete it later. + */ + factory Future.value([FutureOr value]) { + return new _Future.immediate(value); + } + + /** + * Creates a future that completes with an error. + * + * The created future will be completed with an error in a future microtask. + * This allows enough time for someone to add an error handler on the future. + * If an error handler isn't added before the future completes, the error + * will be considered unhandled. + * + * If [error] is `null`, it is replaced by a [NullThrownError]. + * + * Use [Completer] to create a future and complete it later. + */ + factory Future.error(Object error, [StackTrace stackTrace]) { + error = _nonNullError(error); + if (!identical(Zone.current, _rootZone)) { + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + } + return new _Future.immediateError(error, stackTrace); + } + + /** + * Creates a future that runs its computation after a delay. + * + * The [computation] will be executed after the given [duration] has passed, + * and the future is completed with the result of the computation, + * + * If the duration is 0 or less, + * it completes no sooner than in the next event-loop iteration, + * after all microtasks have run. + * + * If [computation] is omitted, + * it will be treated as if [computation] was `() => null`, + * and the future will eventually complete with the `null` value. + * + * If calling [computation] throws, the created future will complete with the + * error. + * + * See also [Completer] for a way to create and complete a future at a + * later time that isn't necessarily after a known fixed duration. + */ + factory Future.delayed(Duration duration, [FutureOr computation()]) { + _Future result = new _Future(); + new Timer(duration, () { + try { + result._complete(computation?.call()); + } catch (e, s) { + _completeWithErrorCallback(result, e, s); + } + }); + return result; + } + + /** + * Waits for multiple futures to complete and collects their results. + * + * Returns a future which will complete once all the provided futures + * have completed, either with their results, or with an error if either + * of the provided futures fail. + * + * The value of the returned future will be a list of all the values that + * were produced. + * + * If any future completes with an error, + * then the returned future completes with that error. + * If further futures also complete with errors, those errors are discarded. + * + * If `eagerError` is true, the returned future completes with an error + * immediately on the first error from one of the futures. Otherwise all + * futures must complete before the returned future is completed (still with + * the first error; the remaining errors are silently dropped). + * + * In the case of an error, [cleanUp] (if provided), is invoked on any + * non-null result of successful futures. + * This makes it possible to `cleanUp` resources that would otherwise be + * lost (since the returned future does not provide access to these values). + * The [cleanUp] function is unused if there is no error. + * + * The call to [cleanUp] should not throw. If it does, the error will be an + * uncaught asynchronous error. + */ + static Future> wait(Iterable> futures, + {bool eagerError: false, void cleanUp(T successValue)}) { + final _Future> result = new _Future>(); + List values; // Collects the values. Set to null on error. + int remaining = 0; // How many futures are we waiting for. + var error; // The first error from a future. + StackTrace stackTrace; // The stackTrace that came with the error. + + // Handle an error from any of the futures. + // TODO(jmesserly): use `void` return type once it can be inferred for the + // `then` call below. + handleError(theError, theStackTrace) { + remaining--; + if (values != null) { + if (cleanUp != null) { + for (var value in values) { + if (value != null) { + // Ensure errors from cleanUp are uncaught. + new Future.sync(() { + cleanUp(value); + }); + } + } + } + values = null; + if (remaining == 0 || eagerError) { + result._completeError(theError, theStackTrace); + } else { + error = theError; + stackTrace = theStackTrace; + } + } else if (remaining == 0 && !eagerError) { + result._completeError(error, stackTrace); + } + } + + try { + // As each future completes, put its value into the corresponding + // position in the list of values. + for (var future in futures) { + int pos = remaining; + future.then((T value) { + remaining--; + if (values != null) { + values[pos] = value; + if (remaining == 0) { + result._completeWithValue(values); + } + } else { + if (cleanUp != null && value != null) { + // Ensure errors from cleanUp are uncaught. + new Future.sync(() { + cleanUp(value); + }); + } + if (remaining == 0 && !eagerError) { + result._completeError(error, stackTrace); + } + } + }, onError: handleError); + // Increment the 'remaining' after the call to 'then'. + // If that call throws, we don't expect any future callback from + // the future, and we also don't increment remaining. + remaining++; + } + if (remaining == 0) { + return new Future.value(const []); + } + values = new List(remaining); + } catch (e, st) { + // The error must have been thrown while iterating over the futures + // list, or while installing a callback handler on the future. + if (remaining == 0 || eagerError) { + // Throw a new Future.error. + // Don't just call `result._completeError` since that would propagate + // the error too eagerly, not giving the callers time to install + // error handlers. + // Also, don't use `_asyncCompleteError` since that one doesn't give + // zones the chance to intercept the error. + return new Future.error(e, st); + } else { + // Don't allocate a list for values, thus indicating that there was an + // error. + // Set error to the caught exception. + error = e; + stackTrace = st; + } + } + return result; + } + + /** + * Returns the result of the first future in [futures] to complete. + * + * The returned future is completed with the result of the first + * future in [futures] to report that it is complete, + * whether it's with a value or an error. + * The results of all the other futures are discarded. + * + * If [futures] is empty, or if none of its futures complete, + * the returned future never completes. + */ + static Future any(Iterable> futures) { + var completer = new Completer.sync(); + var onValue = (T value) { + if (!completer.isCompleted) completer.complete(value); + }; + var onError = (error, stack) { + if (!completer.isCompleted) completer.completeError(error, stack); + }; + for (var future in futures) { + future.then(onValue, onError: onError); + } + return completer.future; + } + + /** + * Performs an action for each element of the iterable, in turn. + * + * The [action] may be either synchronous or asynchronous. + * + * Calls [action] with each element in [elements] in order. + * If the call to [action] returns a `Future`, the iteration waits + * until the future is completed before continuing with the next element. + * + * Returns a [Future] that completes with `null` when all elements have been + * processed. + * + * Non-[Future] return values, and completion-values of returned [Future]s, + * are discarded. + * + * Any error from [action], synchronous or asynchronous, + * will stop the iteration and be reported in the returned [Future]. + */ + static Future forEach(Iterable elements, FutureOr action(T element)) { + var iterator = elements.iterator; + return doWhile(() { + if (!iterator.moveNext()) return false; + var result = action(iterator.current); + if (result is Future) return result.then(_kTrue); + return true; + }); + } + + // Constant `true` function, used as callback by [forEach]. + static bool _kTrue(_) => true; + + /** + * Performs an operation repeatedly until it returns `false`. + * + * The operation, [action], may be either synchronous or asynchronous. + * + * The operation is called repeatedly as long as it returns either the [bool] + * value `true` or a `Future` which completes with the value `true`. + * + * If a call to [action] returns `false` or a [Future] that completes to + * `false`, iteration ends and the future returned by [doWhile] is completed + * with a `null` value. + * + * If a call to [action] throws or a future returned by [action] completes + * with an error, iteration ends and the future returned by [doWhile] + * completes with the same error. + * + * Calls to [action] may happen at any time, + * including immediately after calling `doWhile`. + * The only restriction is a new call to [action] won't happen before + * the previous call has returned, and if it returned a `Future`, not + * until that future has completed. + */ + static Future doWhile(FutureOr action()) { + _Future doneSignal = new _Future(); + var nextIteration; + // Bind this callback explicitly so that each iteration isn't bound in the + // context of all the previous iterations' callbacks. + // This avoids, e.g., deeply nested stack traces from the stack trace + // package. + nextIteration = Zone.current.bindUnaryCallbackGuarded((bool keepGoing) { + while (keepGoing) { + FutureOr result; + try { + result = action(); + } catch (error, stackTrace) { + // Cannot use _completeWithErrorCallback because it completes + // the future synchronously. + _asyncCompleteWithErrorCallback(doneSignal, error, stackTrace); + return; + } + if (result is Future) { + result.then(nextIteration, onError: doneSignal._completeError); + return; + } + keepGoing = result; + } + doneSignal._complete(null); + }); + nextIteration(true); + return doneSignal; + } + + /** + * Register callbacks to be called when this future completes. + * + * When this future completes with a value, + * the [onValue] callback will be called with that value. + * If this future is already completed, the callback will not be called + * immediately, but will be scheduled in a later microtask. + * + * If [onError] is provided, and this future completes with an error, + * the `onError` callback is called with that error and its stack trace. + * The `onError` callback must accept either one argument or two arguments + * where the latter is a [StackTrace]. + * If `onError` accepts two arguments, + * it is called with both the error and the stack trace, + * otherwise it is called with just the error object. + * The `onError` callback must return a value or future that can be used + * to complete the returned future, so it must be something assignable to + * `FutureOr`. + * + * Returns a new [Future] + * which is completed with the result of the call to `onValue` + * (if this future completes with a value) + * or to `onError` (if this future completes with an error). + * + * If the invoked callback throws, + * the returned future is completed with the thrown error + * and a stack trace for the error. + * In the case of `onError`, + * if the exception thrown is `identical` to the error argument to `onError`, + * the throw is considered a rethrow, + * and the original stack trace is used instead. + * + * If the callback returns a [Future], + * the future returned by `then` will be completed with + * the same result as the future returned by the callback. + * + * If [onError] is not given, and this future completes with an error, + * the error is forwarded directly to the returned future. + * + * In most cases, it is more readable to use [catchError] separately, possibly + * with a `test` parameter, instead of handling both value and error in a + * single [then] call. + * + * Note that futures don't delay reporting of errors until listeners are + * added. If the first `then` or `catchError` call happens after this future + * has completed with an error then the error is reported as unhandled error. + * See the description on [Future]. + */ + Future then(FutureOr onValue(T value), {Function onError}); + + /** + * Handles errors emitted by this [Future]. + * + * This is the asynchronous equivalent of a "catch" block. + * + * Returns a new [Future] that will be completed with either the result of + * this future or the result of calling the `onError` callback. + * + * If this future completes with a value, + * the returned future completes with the same value. + * + * If this future completes with an error, + * then [test] is first called with the error value. + * + * If `test` returns false, the exception is not handled by this `catchError`, + * and the returned future completes with the same error and stack trace + * as this future. + * + * If `test` returns `true`, + * [onError] is called with the error and possibly stack trace, + * and the returned future is completed with the result of this call + * in exactly the same way as for [then]'s `onError`. + * + * If `test` is omitted, it defaults to a function that always returns true. + * The `test` function should not throw, but if it does, it is handled as + * if the `onError` function had thrown. + * + * Note that futures don't delay reporting of errors until listeners are + * added. If the first `catchError` (or `then`) call happens after this future + * has completed with an error then the error is reported as unhandled error. + * See the description on [Future]. + */ + // The `Function` below stands for one of two types: + // - (dynamic) -> FutureOr + // - (dynamic, StackTrace) -> FutureOr + // Given that there is a `test` function that is usually used to do an + // `isCheck` we should also expect functions that take a specific argument. + // Note: making `catchError` return a `Future` in non-strong mode could be + // a breaking change. + Future catchError(Function onError, {bool test(Object error)}); + + /** + * Registers a function to be called when this future completes. + * + * The [action] function is called when this future completes, whether it + * does so with a value or with an error. + * + * This is the asynchronous equivalent of a "finally" block. + * + * The future returned by this call, `f`, will complete the same way + * as this future unless an error occurs in the [action] call, or in + * a [Future] returned by the [action] call. If the call to [action] + * does not return a future, its return value is ignored. + * + * If the call to [action] throws, then `f` is completed with the + * thrown error. + * + * If the call to [action] returns a [Future], `f2`, then completion of + * `f` is delayed until `f2` completes. If `f2` completes with + * an error, that will be the result of `f` too. The value of `f2` is always + * ignored. + * + * This method is equivalent to: + * + * Future whenComplete(action()) { + * return this.then((v) { + * var f2 = action(); + * if (f2 is Future) return f2.then((_) => v); + * return v + * }, onError: (e) { + * var f2 = action(); + * if (f2 is Future) return f2.then((_) { throw e; }); + * throw e; + * }); + * } + */ + Future whenComplete(FutureOr action()); + + /** + * Creates a [Stream] containing the result of this future. + * + * The stream will produce single data or error event containing the + * completion result of this future, and then it will close with a + * done event. + * + * If the future never completes, the stream will not produce any events. + */ + Stream asStream(); + + /** + * Time-out the future computation after [timeLimit] has passed. + * + * Returns a new future that completes with the same value as this future, + * if this future completes in time. + * + * If this future does not complete before `timeLimit` has passed, + * the [onTimeout] action is executed instead, and its result (whether it + * returns or throws) is used as the result of the returned future. + * The [onTimeout] function must return a [T] or a `Future`. + * + * If `onTimeout` is omitted, a timeout will cause the returned future to + * complete with a [TimeoutException]. + */ + Future timeout(Duration timeLimit, {FutureOr onTimeout()}); +} + +/** + * Thrown when a scheduled timeout happens while waiting for an async result. + */ +class TimeoutException implements Exception { + /** Description of the cause of the timeout. */ + final String message; + /** The duration that was exceeded. */ + final Duration duration; + + TimeoutException(this.message, [this.duration]); + + String toString() { + String result = "TimeoutException"; + if (duration != null) result = "TimeoutException after $duration"; + if (message != null) result = "$result: $message"; + return result; + } +} + +/** + * A way to produce Future objects and to complete them later + * with a value or error. + * + * Most of the time, the simplest way to create a future is to just use + * one of the [Future] constructors to capture the result of a single + * asynchronous computation: + * ``` + * new Future(() { doSomething(); return result; }); + * ``` + * or, if the future represents the result of a sequence of asynchronous + * computations, they can be chained using [Future.then] or similar functions + * on [Future]: + * ``` + * Future doStuff(){ + * return someAsyncOperation().then((result) { + * return someOtherAsyncOperation(result); + * }); + * } + * ``` + * If you do need to create a Future from scratch — for example, + * when you're converting a callback-based API into a Future-based + * one — you can use a Completer as follows: + * ``` + * class AsyncOperation { + * Completer _completer = new Completer(); + * + * Future doOperation() { + * _startOperation(); + * return _completer.future; // Send future object back to client. + * } + * + * // Something calls this when the value is ready. + * void _finishOperation(T result) { + * _completer.complete(result); + * } + * + * // If something goes wrong, call this. + * void _errorHappened(error) { + * _completer.completeError(error); + * } + * } + * ``` + */ +abstract class Completer { + /** + * Creates a new completer. + * + * The general workflow for creating a new future is to 1) create a + * new completer, 2) hand out its future, and, at a later point, 3) invoke + * either [complete] or [completeError]. + * + * The completer completes the future asynchronously. That means that + * callbacks registered on the future are not called immediately when + * [complete] or [completeError] is called. Instead the callbacks are + * delayed until a later microtask. + * + * Example: + * ``` + * var completer = new Completer(); + * handOut(completer.future); + * later: { + * completer.complete('completion value'); + * } + * ``` + */ + factory Completer() => new _AsyncCompleter(); + + /** + * Completes the future synchronously. + * + * This constructor should be avoided unless the completion of the future is + * known to be the final result of another asynchronous operation. If in doubt + * use the default [Completer] constructor. + * + * Using an normal, asynchronous, completer will never give the wrong + * behavior, but using a synchronous completer incorrectly can cause + * otherwise correct programs to break. + * + * A synchronous completer is only intended for optimizing event + * propagation when one asynchronous event immediately triggers another. + * It should not be used unless the calls to [complete] and [completeError] + * are guaranteed to occur in places where it won't break `Future` invariants. + * + * Completing synchronously means that the completer's future will be + * completed immediately when calling the [complete] or [completeError] + * method on a synchronous completer, which also calls any callbacks + * registered on that future. + * + * Completing synchronously must not break the rule that when you add a + * callback on a future, that callback must not be called until the code + * that added the callback has completed. + * For that reason, a synchronous completion must only occur at the very end + * (in "tail position") of another synchronous event, + * because at that point, completing the future immediately is be equivalent + * to returning to the event loop and completing the future in the next + * microtask. + * + * Example: + * + * var completer = new Completer.sync(); + * // The completion is the result of the asynchronous onDone event. + * // No other operation is performed after the completion. It is safe + * // to use the Completer.sync constructor. + * stream.listen(print, onDone: () { completer.complete("done"); }); + * + * Bad example. Do not use this code. Only for illustrative purposes: + * + * var completer = new Completer.sync(); + * completer.future.then((_) { bar(); }); + * // The completion is the result of the asynchronous onDone event. + * // However, there is still code executed after the completion. This + * // operation is *not* safe. + * stream.listen(print, onDone: () { + * completer.complete("done"); + * foo(); // In this case, foo() runs after bar(). + * }); + */ + factory Completer.sync() => new _SyncCompleter(); + + /** + * The future that is completed by this completer. + * + * The future that is completed when [complete] or [completeError] is called. + */ + Future get future; + + /** + * Completes [future] with the supplied values. + * + * The value must be either a value of type [T] + * or a future of type `Future`. + * + * If the value is itself a future, the completer will wait for that future + * to complete, and complete with the same result, whether it is a success + * or an error. + * + * Calling [complete] or [completeError] must be done at most once. + * + * All listeners on the future are informed about the value. + */ + void complete([FutureOr value]); + + /** + * Complete [future] with an error. + * + * Calling [complete] or [completeError] must be done at most once. + * + * Completing a future with an error indicates that an exception was thrown + * while trying to produce a value. + * + * If [error] is `null`, it is replaced by a [NullThrownError]. + * + * If `error` is a `Future`, the future itself is used as the error value. + * If you want to complete with the result of the future, you can use: + * ``` + * thisCompleter.complete(theFuture) + * ``` + * or if you only want to handle an error from the future: + * ``` + * theFuture.catchError(thisCompleter.completeError); + * ``` + */ + void completeError(Object error, [StackTrace stackTrace]); + + /** + * Whether the [future] has been completed. + * + * Reflects whether [complete] or [completeError] has been called. + * A `true` value doesn't necessarily mean that listeners of this future + * have been invoked yet, either because the completer usually waits until + * a later microtask to propagate the result, or because [complete] + * was called with a future that hasn't completed yet. + * + * When this value is `true`, [complete] and [completeError] must not be + * called again. + */ + bool get isCompleted; +} + +// Helper function completing a _Future with error, but checking the zone +// for error replacement first. +void _completeWithErrorCallback(_Future result, error, stackTrace) { + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + result._completeError(error, stackTrace); +} + +// Like [_completeWithErrorCallback] but completes asynchronously. +void _asyncCompleteWithErrorCallback(_Future result, error, stackTrace) { + AsyncError replacement = Zone.current.errorCallback(error, stackTrace); + if (replacement != null) { + error = _nonNullError(replacement.error); + stackTrace = replacement.stackTrace; + } + result._asyncCompleteError(error, stackTrace); +} + +/** Helper function that converts `null` to a [NullThrownError]. */ +Object _nonNullError(Object error) => error ?? new NullThrownError(); +NN<C@OLQ N 0B&QAKJM=8NQB1@628)29,(*.HP!,A=MFKL5=D>HC J>?IL:1JEI5/4LAL@NQOE 3J*"GIJCNIK .+4/,5E&M?G2I.* )2E.(=@G2:78* )2CP N:D3 +"!%51-"%N!$G7.>JJEC8?.,4OPL#B?@"/N!2-=?OE#C$">DP IEK* /2HHK#L,9OJKOBI,KO<N">@+'JE*%NIM4(O.FC8,9@*9-=#I".C=>HLON;GO&.-8>!@IPMKOMH$/4HN&3(O:JM&H'J +&J +"A.HKM));8KLA-?%<&P(3):=I=QLKOP&G.=MB,8-7QKBG8OL+KQP&7 ,INPECL,?GGG<DJAO#," 9 A ->GELCM'ELFBL)DN.2)3(G7>HF5IN1/ AC--G6'$,"(FM+HHH& & / 3)OQ.HG*CKNQHJG JK,O8OJ/KM3KH/0KM%+'< 75P22&NMF?&&FN&BMI ' = 8 =.EKMF9KJ EJ.),CJJ.)1DFLfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/timer.dart#// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +/** + * A count-down timer that can be configured to fire once or repeatedly. + * + * The timer counts down from the specified duration to 0. + * When the timer reaches 0, the timer invokes the specified callback function. + * Use a periodic timer to repeatedly count down the same interval. + * + * A negative duration is treated the same as a duration of 0. + * If the duration is statically known to be 0, consider using [run]. + * + * Frequently the duration is either a constant or computed as in the + * following example (taking advantage of the multiplication operator of + * the [Duration] class): + * ```dart + * const timeout = const Duration(seconds: 3); + * const ms = const Duration(milliseconds: 1); + * + * startTimeout([int milliseconds]) { + * var duration = milliseconds == null ? timeout : ms * milliseconds; + * return new Timer(duration, handleTimeout); + * } + * ... + * void handleTimeout() { // callback function + * ... + * } + * ``` + * Note: If Dart code using Timer is compiled to JavaScript, the finest + * granularity available in the browser is 4 milliseconds. + * + * See [Stopwatch] for measuring elapsed time. + */ +abstract class Timer { + /** + * Creates a new timer. + * + * The [callback] function is invoked after the given [duration]. + * + */ + factory Timer(Duration duration, void callback()) { + if (Zone.current == Zone.root) { + // No need to bind the callback. We know that the root's timer will + // be invoked in the root zone. + return Zone.current.createTimer(duration, callback); + } + return Zone.current + .createTimer(duration, Zone.current.bindCallbackGuarded(callback)); + } + + /** + * Creates a new repeating timer. + * + * The [callback] is invoked repeatedly with [duration] intervals until + * canceled with the [cancel] function. + * + * The exact timing depends on the underlying timer implementation. + * No more than `n` callbacks will be made in `duration * n` time, + * but the time between two consecutive callbacks + * can be shorter and longer than `duration`. + * + * In particular, an implementation may schedule the next callback, e.g., + * a `duration` after either when the previous callback ended, + * when the previous callback started, or when the previous callback was + * scheduled for - even if the actual callback was delayed. + */ + factory Timer.periodic(Duration duration, void callback(Timer timer)) { + if (Zone.current == Zone.root) { + // No need to bind the callback. We know that the root's timer will + // be invoked in the root zone. + return Zone.current.createPeriodicTimer(duration, callback); + } + var boundCallback = Zone.current.bindUnaryCallbackGuarded(callback); + return Zone.current.createPeriodicTimer(duration, boundCallback); + } + + /** + * Runs the given [callback] asynchronously as soon as possible. + * + * This function is equivalent to `new Timer(Duration.zero, callback)`. + */ + static void run(void callback()) { + new Timer(Duration.zero, callback); + } + + /** + * Cancels the timer. + */ + void cancel(); + + /** + * The number of durations preceding the most recent timer event. + * + * The value starts at zero and is incremented each time a timer event + * occurs, so each callback will see a larger value than the previous one. + * + * If a periodic timer with a non-zero duration is delayed too much, + * so more than one tick should have happened, + * all but the last tick in the past are considered "missed", + * and no callback is invoked for them. + * The [tick] count reflects the number of durations that have passed and + * not the number of callback invocations that have happened. + */ + int get tick; + + /** + * Returns whether the timer is still active. + * + * A non-periodic timer is active if the callback has not been executed, + * and the timer has not been canceled. + * + * A periodic timer is active if it has not been canceled. + */ + bool get isActive; + + external static Timer _createTimer(Duration duration, void callback()); + external static Timer _createPeriodicTimer( + Duration duration, void callback(Timer timer)); +} +}NN<I;PD?FFI //&H00 H;/D6%J&;L$J*FE40LAK>J%J&CPFCJ%(DIMG1@*L@0K*=J.6Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/async/async_error.dart-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.async; + +_invokeErrorHandler( + Function errorHandler, Object error, StackTrace stackTrace) { + if (errorHandler is ZoneBinaryCallback) { + return (errorHandler as dynamic)(error, stackTrace); + } else { + ZoneUnaryCallback unaryErrorHandler = errorHandler; + return unaryErrorHandler(error); + } +} +NN<BA9 8%Vfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/collection.dart4// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Classes and utilities that supplement the collection support in dart:core. + * + * To use this library in your code: + * + * import 'dart:collection'; + * + * {@category Core} + */ +library dart.collection; + +import 'dart:_internal' hide Symbol; +import 'dart:math' show Random; // Used by ListMixin.shuffle. + +part 'collections.dart'; +part 'hash_map.dart'; +part 'hash_set.dart'; +part 'iterable.dart'; +part 'iterator.dart'; +part 'linked_hash_map.dart'; +part 'linked_hash_set.dart'; +part 'linked_list.dart'; +part 'list.dart'; +part 'maps.dart'; +part 'queue.dart'; +part 'set.dart'; +part 'splay_tree.dart'; +!NN<N%!%>Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/hash_map.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** Default function for equality comparison in customized HashMaps */ +bool _defaultEquals(a, b) => a == b; +/** Default function for hash-code computation in customized HashMaps */ +int _defaultHashCode(a) => a.hashCode; + +/** Type of custom equality function */ +typedef bool _Equality(K a, K b); +/** Type of custom hash code function. */ +typedef int _Hasher(K object); + +/** + * A hash-table based implementation of [Map]. + * + * The keys of a `HashMap` must have consistent [Object.==] + * and [Object.hashCode] implementations. This means that the `==` operator + * must define a stable equivalence relation on the keys (reflexive, + * symmetric, transitive, and consistent over time), and that `hashCode` + * must be the same for objects that are considered equal by `==`. + * + * The map allows `null` as a key. + * + * Iterating the map's keys, values or entries (through [forEach]) + * may happen in any order. + * The iteration order only changes when the map is modified. + * Values are iterated in the same order as their associated keys, + * so iterating the [keys] and [values] in parallel + * will give matching key and value pairs. + */ +abstract class HashMap implements Map { + /** + * Creates an unordered hash-table based [Map]. + * + * The created map is not ordered in any way. When iterating the keys or + * values, the iteration order is unspecified except that it will stay the + * same as long as the map isn't changed. + * + * If [equals] is provided, it is used to compare the keys in the table with + * new keys. If [equals] is omitted, the key's own [Object.==] is used + * instead. + * + * Similar, if [hashCode] is provided, it is used to produce a hash value + * for keys in order to place them in the hash table. If it is omitted, the + * key's own [Object.hashCode] is used. + * + * If using methods like [operator []], [remove] and [containsKey] together + * with a custom equality and hashcode, an extra `isValidKey` function + * can be supplied. This function is called before calling [equals] or + * [hashCode] with an argument that may not be a [K] instance, and if the + * call returns false, the key is assumed to not be in the set. + * The [isValidKey] function defaults to just testing if the object is a + * [K] instance. + * + * Example: + * + * new HashMap(equals: (int a, int b) => (b - a) % 5 == 0, + * hashCode: (int e) => e % 5) + * + * This example map does not need an `isValidKey` function to be passed. + * The default function accepts only `int` values, which can safely be + * passed to both the `equals` and `hashCode` functions. + * + * If neither `equals`, `hashCode`, nor `isValidKey` is provided, + * the default `isValidKey` instead accepts all keys. + * The default equality and hashcode operations are assumed to work on all + * objects. + * + * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode] + * and `isValidKey` is omitted, the resulting map is identity based, + * and the `isValidKey` defaults to accepting all keys. + * Such a map can be created directly using [HashMap.identity]. + * + * The used `equals` and `hashCode` method should always be consistent, + * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash + * of an object, or what it compares equal to, should not change while the + * object is a key in the map. If it does change, the result is unpredictable. + * + * If you supply one of [equals] and [hashCode], + * you should generally also to supply the other. + */ + external factory HashMap( + {bool equals(K key1, K key2), + int hashCode(K key), + bool isValidKey(potentialKey)}); + + /** + * Creates an unordered identity-based map. + * + * Effectively a shorthand for: + * + * new HashMap(equals: identical, + * hashCode: identityHashCode) + */ + external factory HashMap.identity(); + + /** + * Creates a [HashMap] that contains all key/value pairs of [other]. + * + * The keys must all be instances of [K] and the values of [V]. + * The [other] map itself can have any type. + */ + factory HashMap.from(Map other) { + Map result = new HashMap(); + other.forEach((k, v) { + result[k] = v; + }); + return result; + } + + /** + * Creates a [HashMap] that contains all key/value pairs of [other]. + */ + factory HashMap.of(Map other) => new HashMap()..addAll(other); + + /** + * Creates a [HashMap] where the keys and values are computed from the + * [iterable]. + * + * For each element of the [iterable] this constructor computes a key/value + * pair, by applying [key] and [value] respectively. + * + * The keys of the key/value pairs do not need to be unique. The last + * occurrence of a key will simply overwrite any previous value. + * + * If no values are specified for [key] and [value] the default is the + * identity function. + */ + factory HashMap.fromIterable(Iterable iterable, + {K key(element), V value(element)}) { + Map map = new HashMap(); + MapBase._fillMapWithMappedIterable(map, iterable, key, value); + return map; + } + + /** + * Creates a [HashMap] associating the given [keys] to [values]. + * + * This constructor iterates over [keys] and [values] and maps each element of + * [keys] to the corresponding element of [values]. + * + * If [keys] contains the same object multiple times, the last occurrence + * overwrites the previous value. + * + * It is an error if the two [Iterable]s don't have the same length. + */ + factory HashMap.fromIterables(Iterable keys, Iterable values) { + Map map = new HashMap(); + MapBase._fillMapWithIterables(map, keys, values); + return map; + } +} +NN<G%I'(%*"/C4+42KM,OILN*NIILBKJ:KI;D8MLG:BJKMQ34$'.".7'GB/$,GMIN7HCI2,)CCQ6L$GH)6Vfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/splay_tree.dartj// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +typedef bool _Predicate(T value); + +/** + * A node in a splay tree. It holds the sorting key and the left + * and right children in the tree. + */ +class _SplayTreeNode { + final K key; + _SplayTreeNode left; + _SplayTreeNode right; + + _SplayTreeNode(this.key); +} + +/** + * A node in a splay tree based map. + * + * A [_SplayTreeNode] that also contains a value + */ +class _SplayTreeMapNode extends _SplayTreeNode { + V value; + _SplayTreeMapNode(K key, this.value) : super(key); +} + +/** + * A splay tree is a self-balancing binary search tree. + * + * It has 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. + */ +abstract class _SplayTree> { + // The root node of the splay tree. It will contain either the last + // element inserted or the last element looked up. + Node get _root; + set _root(Node newValue); + + // The dummy node used when performing a splay on the tree. Reusing it + // avoids allocating a node each time a splay is performed. + Node get _dummy; + + // Number of elements in the splay tree. + int _count = 0; + + /** + * Counter incremented whenever the keys in the map changes. + * + * Used to detect concurrent modifications. + */ + int _modificationCount = 0; + + /** + * Counter incremented whenever the tree structure changes. + * + * Used to detect that an in-place traversal cannot use + * cached information that relies on the tree structure. + */ + int _splayCount = 0; + + /** The comparator that is used for this splay tree. */ + Comparator get _comparator; + + /** The predicate to determine that a given object is a valid key. */ + _Predicate get _validKey; + + /** Comparison used to compare keys. */ + int _compare(K key1, K key2); + + /** + * 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. + * + * Returns the result of comparing the new root of the tree to [key]. + * Returns -1 if the table is empty. + */ + int _splay(K key) { + if (_root == null) return -1; + + // 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. + Node left = _dummy; + Node right = _dummy; + Node current = _root; + int comp; + while (true) { + comp = _compare(current.key, key); + if (comp > 0) { + if (current.left == null) break; + comp = _compare(current.left.key, key); + if (comp > 0) { + // Rotate right. + _SplayTreeNode tmp = current.left; + current.left = tmp.right; + tmp.right = current; + current = tmp; + if (current.left == null) break; + } + // Link right. + right.left = current; + right = current; + current = current.left; + } else if (comp < 0) { + if (current.right == null) break; + comp = _compare(current.right.key, key); + if (comp < 0) { + // Rotate left. + Node tmp = current.right; + current.right = tmp.left; + tmp.left = current; + current = tmp; + if (current.right == null) 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; + _root = current; + + _dummy.right = null; + _dummy.left = null; + _splayCount++; + return comp; + } + + // Emulates splaying with a key that is smaller than any in the subtree + // anchored at [node]. + // and that node is returned. It should replace the reference to [node] + // in any parent tree or root pointer. + Node _splayMin(Node node) { + Node current = node; + while (current.left != null) { + Node left = current.left; + current.left = left.right; + left.right = current; + current = left; + } + return current; + } + + // Emulates splaying with a key that is greater than any in the subtree + // anchored at [node]. + // After this, the largest element in the tree is the root of the subtree, + // and that node is returned. It should replace the reference to [node] + // in any parent tree or root pointer. + Node _splayMax(Node node) { + Node current = node; + while (current.right != null) { + Node right = current.right; + current.right = right.left; + right.left = current; + current = right; + } + return current; + } + + Node _remove(K key) { + if (_root == null) return null; + int comp = _splay(key); + if (comp != 0) return null; + Node result = _root; + _count--; + // assert(_count >= 0); + if (_root.left == null) { + _root = _root.right; + } else { + Node right = _root.right; + // Splay to make sure that the new root has an empty right child. + _root = _splayMax(_root.left); + // Insert the original right child as the right child of the new + // root. + _root.right = right; + } + _modificationCount++; + return result; + } + + /** + * Adds a new root node with the given [key] or [value]. + * + * The [comp] value is the result of comparing the existing root's key + * with key. + */ + void _addNewRoot(Node node, int comp) { + _count++; + _modificationCount++; + if (_root == null) { + _root = node; + return; + } + // assert(_count >= 0); + if (comp < 0) { + node.left = _root; + node.right = _root.right; + _root.right = null; + } else { + node.right = _root; + node.left = _root.left; + _root.left = null; + } + _root = node; + } + + Node get _first { + if (_root == null) return null; + _root = _splayMin(_root); + return _root; + } + + Node get _last { + if (_root == null) return null; + _root = _splayMax(_root); + return _root; + } + + void _clear() { + _root = null; + _count = 0; + _modificationCount++; + } +} + +class _TypeTest { + bool test(v) => v is T; +} + +int _dynamicCompare(dynamic a, dynamic b) => Comparable.compare(a, b); + +Comparator _defaultCompare() { + // If K <: Comparable, then we can just use Comparable.compare + // with no casts. + Object compare = Comparable.compare; + if (compare is Comparator) { + return compare; + } + // Otherwise wrap and cast the arguments on each call. + return _dynamicCompare; +} + +/** + * A [Map] of objects that can be ordered relative to each other. + * + * The map is based on a self-balancing binary tree. It allows most operations + * in amortized logarithmic time. + * + * Keys of the map are compared using the `compare` function passed in + * the constructor, both for ordering and for equality. + * If the map contains only the key `a`, then `map.containsKey(b)` + * will return `true` if and only if `compare(a, b) == 0`, + * and the value of `a == b` is not even checked. + * If the compare function is omitted, the objects are assumed to be + * [Comparable], and are compared using their [Comparable.compareTo] method. + * Non-comparable objects (including `null`) will not work as keys + * in that case. + * + * To allow calling [operator []], [remove] or [containsKey] with objects + * that are not supported by the `compare` function, an extra `isValidKey` + * predicate function can be supplied. This function is tested before + * using the `compare` function on an argument value that may not be a [K] + * value. If omitted, the `isValidKey` function defaults to testing if the + * value is a [K]. + */ +class SplayTreeMap extends _SplayTree> + with MapMixin { + _SplayTreeMapNode _root; + final _SplayTreeMapNode _dummy = + new _SplayTreeMapNode(null, null); + + Comparator _comparator; + _Predicate _validKey; + + SplayTreeMap([int compare(K key1, K key2), bool isValidKey(potentialKey)]) + : _comparator = compare ?? _defaultCompare(), + _validKey = isValidKey ?? ((v) => v is K); + + /** + * Creates a [SplayTreeMap] that contains all key/value pairs of [other]. + * + * The keys must all be instances of [K] and the values of [V]. + * The [other] map itself can have any type. + */ + factory SplayTreeMap.from(Map other, + [int compare(K key1, K key2), bool isValidKey(potentialKey)]) { + SplayTreeMap result = new SplayTreeMap(compare, isValidKey); + other.forEach((k, v) { + result[k] = v; + }); + return result; + } + + /** + * Creates a [SplayTreeMap] that contains all key/value pairs of [other]. + */ + factory SplayTreeMap.of(Map other, + [int compare(K key1, K key2), bool isValidKey(potentialKey)]) => + new SplayTreeMap(compare, isValidKey)..addAll(other); + + /** + * Creates a [SplayTreeMap] where the keys and values are computed from the + * [iterable]. + * + * For each element of the [iterable] this constructor computes a key/value + * pair, by applying [key] and [value] respectively. + * + * The keys of the key/value pairs do not need to be unique. The last + * occurrence of a key will simply overwrite any previous value. + * + * If no functions are specified for [key] and [value] the default is to + * use the iterable value itself. + */ + factory SplayTreeMap.fromIterable(Iterable iterable, + {K key(element), + V value(element), + int compare(K key1, K key2), + bool isValidKey(potentialKey)}) { + SplayTreeMap map = new SplayTreeMap(compare, isValidKey); + MapBase._fillMapWithMappedIterable(map, iterable, key, value); + return map; + } + + /** + * Creates a [SplayTreeMap] associating the given [keys] to [values]. + * + * This constructor iterates over [keys] and [values] and maps each element of + * [keys] to the corresponding element of [values]. + * + * If [keys] contains the same object multiple times, the last occurrence + * overwrites the previous value. + * + * It is an error if the two [Iterable]s don't have the same length. + */ + factory SplayTreeMap.fromIterables(Iterable keys, Iterable values, + [int compare(K key1, K key2), bool isValidKey(potentialKey)]) { + SplayTreeMap map = new SplayTreeMap(compare, isValidKey); + MapBase._fillMapWithIterables(map, keys, values); + return map; + } + + int _compare(K key1, K key2) => _comparator(key1, key2); + + SplayTreeMap._internal(); + + V operator [](Object key) { + if (!_validKey(key)) return null; + if (_root != null) { + int comp = _splay(key); + if (comp == 0) { + return _root.value; + } + } + return null; + } + + V remove(Object key) { + if (!_validKey(key)) return null; + _SplayTreeMapNode mapRoot = _remove(key); + if (mapRoot != null) return mapRoot.value; + return null; + } + + void operator []=(K key, V value) { + if (key == null) throw new ArgumentError(key); + // Splay on the key to move the last node on the search path for + // the key to the root of the tree. + int comp = _splay(key); + if (comp == 0) { + _root.value = value; + return; + } + _addNewRoot(new _SplayTreeMapNode(key, value), comp); + } + + V putIfAbsent(K key, V ifAbsent()) { + if (key == null) throw new ArgumentError(key); + int comp = _splay(key); + if (comp == 0) { + return _root.value; + } + int modificationCount = _modificationCount; + int splayCount = _splayCount; + V value = ifAbsent(); + if (modificationCount != _modificationCount) { + throw new ConcurrentModificationError(this); + } + if (splayCount != _splayCount) { + comp = _splay(key); + // Key is still not there, otherwise _modificationCount would be changed. + assert(comp != 0); + } + _addNewRoot(new _SplayTreeMapNode(key, value), comp); + return value; + } + + void addAll(Map other) { + other.forEach((K key, V value) { + this[key] = value; + }); + } + + bool get isEmpty { + return (_root == null); + } + + bool get isNotEmpty => !isEmpty; + + void forEach(void f(K key, V value)) { + Iterator<_SplayTreeNode> nodes = new _SplayTreeNodeIterator(this); + while (nodes.moveNext()) { + _SplayTreeMapNode node = nodes.current; + f(node.key, node.value); + } + } + + int get length { + return _count; + } + + void clear() { + _clear(); + } + + bool containsKey(Object key) { + return _validKey(key) && _splay(key) == 0; + } + + bool containsValue(Object value) { + bool found = false; + int initialSplayCount = _splayCount; + bool visit(_SplayTreeMapNode node) { + while (node != null) { + if (node.value == value) return true; + if (initialSplayCount != _splayCount) { + throw new ConcurrentModificationError(this); + } + if (node.right != null && visit(node.right)) return true; + node = node.left; + } + return false; + } + + return visit(_root); + } + + Iterable get keys => new _SplayTreeKeyIterable(this); + + Iterable get values => new _SplayTreeValueIterable(this); + + /** + * Get the first key in the map. Returns [:null:] if the map is empty. + */ + K firstKey() { + if (_root == null) return null; + return _first.key; + } + + /** + * Get the last key in the map. Returns [:null:] if the map is empty. + */ + K lastKey() { + if (_root == null) return null; + return _last.key; + } + + /** + * Get the last key in the map that is strictly smaller than [key]. Returns + * [:null:] if no key was not found. + */ + K lastKeyBefore(K key) { + if (key == null) throw new ArgumentError(key); + if (_root == null) return null; + int comp = _splay(key); + if (comp < 0) return _root.key; + _SplayTreeNode node = _root.left; + if (node == null) return null; + while (node.right != null) { + node = node.right; + } + return node.key; + } + + /** + * Get the first key in the map that is strictly larger than [key]. Returns + * [:null:] if no key was not found. + */ + K firstKeyAfter(K key) { + if (key == null) throw new ArgumentError(key); + if (_root == null) return null; + int comp = _splay(key); + if (comp > 0) return _root.key; + _SplayTreeNode node = _root.right; + if (node == null) return null; + while (node.left != null) { + node = node.left; + } + return node.key; + } +} + +abstract class _SplayTreeIterator implements Iterator { + final _SplayTree> _tree; + /** + * Worklist of nodes to visit. + * + * These nodes have been passed over on the way down in a + * depth-first left-to-right traversal. Visiting each node, + * and their right subtrees will visit the remainder of + * the nodes of a full traversal. + * + * Only valid as long as the original tree isn't reordered. + */ + final List<_SplayTreeNode> _workList = <_SplayTreeNode>[]; + + /** + * Original modification counter of [_tree]. + * + * Incremented on [_tree] when a key is added or removed. + * If it changes, iteration is aborted. + * + * Not final because some iterators may modify the tree knowingly, + * and they update the modification count in that case. + */ + int _modificationCount; + + /** + * Count of splay operations on [_tree] when [_workList] was built. + * + * If the splay count on [_tree] increases, [_workList] becomes invalid. + */ + int _splayCount; + + /** Current node. */ + _SplayTreeNode _currentNode; + + _SplayTreeIterator(_SplayTree> tree) + : _tree = tree, + _modificationCount = tree._modificationCount, + _splayCount = tree._splayCount { + _findLeftMostDescendent(tree._root); + } + + _SplayTreeIterator.startAt(_SplayTree> tree, K startKey) + : _tree = tree, + _modificationCount = tree._modificationCount { + if (tree._root == null) return; + int compare = tree._splay(startKey); + _splayCount = tree._splayCount; + if (compare < 0) { + // Don't include the root, start at the next element after the root. + _findLeftMostDescendent(tree._root.right); + } else { + _workList.add(tree._root); + } + } + + T get current { + if (_currentNode == null) return null; + return _getValue(_currentNode); + } + + void _findLeftMostDescendent(_SplayTreeNode node) { + while (node != null) { + _workList.add(node); + node = node.left; + } + } + + /** + * Called when the tree structure of the tree has changed. + * + * This can be caused by a splay operation. + * If the key-set changes, iteration is aborted before getting + * here, so we know that the keys are the same as before, it's + * only the tree that has been reordered. + */ + void _rebuildWorkList(_SplayTreeNode currentNode) { + assert(!_workList.isEmpty); + _workList.clear(); + if (currentNode == null) { + _findLeftMostDescendent(_tree._root); + } else { + _tree._splay(currentNode.key); + _findLeftMostDescendent(_tree._root.right); + assert(!_workList.isEmpty); + } + } + + bool moveNext() { + if (_modificationCount != _tree._modificationCount) { + throw new ConcurrentModificationError(_tree); + } + // Picks the next element in the worklist as current. + // Updates the worklist with the left-most path of the current node's + // right-hand child. + // If the worklist is no longer valid (after a splay), it is rebuild + // from scratch. + if (_workList.isEmpty) { + _currentNode = null; + return false; + } + if (_tree._splayCount != _splayCount && _currentNode != null) { + _rebuildWorkList(_currentNode); + } + _currentNode = _workList.removeLast(); + _findLeftMostDescendent(_currentNode.right); + return true; + } + + T _getValue(_SplayTreeNode node); +} + +class _SplayTreeKeyIterable extends EfficientLengthIterable { + _SplayTree> _tree; + _SplayTreeKeyIterable(this._tree); + int get length => _tree._count; + bool get isEmpty => _tree._count == 0; + Iterator get iterator => new _SplayTreeKeyIterator(_tree); + + Set toSet() { + SplayTreeSet set = + new SplayTreeSet(_tree._comparator, _tree._validKey); + set._count = _tree._count; + set._root = set._copyNode(_tree._root); + return set; + } +} + +class _SplayTreeValueIterable extends EfficientLengthIterable { + SplayTreeMap _map; + _SplayTreeValueIterable(this._map); + int get length => _map._count; + bool get isEmpty => _map._count == 0; + Iterator get iterator => new _SplayTreeValueIterator(_map); +} + +class _SplayTreeKeyIterator extends _SplayTreeIterator { + _SplayTreeKeyIterator(_SplayTree> map) : super(map); + K _getValue(_SplayTreeNode node) => node.key; +} + +class _SplayTreeValueIterator extends _SplayTreeIterator { + _SplayTreeValueIterator(SplayTreeMap map) : super(map); + V _getValue(_SplayTreeNode node) { + _SplayTreeMapNode mapNode = node; + return mapNode.value; + } +} + +class _SplayTreeNodeIterator + extends _SplayTreeIterator> { + _SplayTreeNodeIterator(_SplayTree> tree) : super(tree); + _SplayTreeNodeIterator.startAt( + _SplayTree> tree, K startKey) + : super.startAt(tree, startKey); + _SplayTreeNode _getValue(_SplayTreeNode node) => node; +} + +/** + * A [Set] of objects that can be ordered relative to each other. + * + * The set is based on a self-balancing binary tree. It allows most operations + * in amortized logarithmic time. + * + * Elements of the set are compared using the `compare` function passed in + * the constructor, both for ordering and for equality. + * If the set contains only an object `a`, then `set.contains(b)` + * will return `true` if and only if `compare(a, b) == 0`, + * and the value of `a == b` is not even checked. + * If the compare function is omitted, the objects are assumed to be + * [Comparable], and are compared using their [Comparable.compareTo] method. + * Non-comparable objects (including `null`) will not work as an element + * in that case. + */ +class SplayTreeSet extends _SplayTree> + with IterableMixin, SetMixin { + _SplayTreeNode _root; + final _SplayTreeNode _dummy = new _SplayTreeNode(null); + + Comparator _comparator; + _Predicate _validKey; + + /** + * Create a new [SplayTreeSet] with the given compare function. + * + * If the [compare] function is omitted, it defaults to [Comparable.compare], + * and the elements must be comparable. + * + * A provided `compare` function may not work on all objects. It may not even + * work on all `E` instances. + * + * For operations that add elements to the set, the user is supposed to not + * pass in objects that doesn't work with the compare function. + * + * The methods [contains], [remove], [lookup], [removeAll] or [retainAll] + * are typed to accept any object(s), and the [isValidKey] test can used to + * filter those objects before handing them to the `compare` function. + * + * If [isValidKey] is provided, only values satisfying `isValidKey(other)` + * are compared using the `compare` method in the methods mentioned above. + * If the `isValidKey` function returns false for an object, it is assumed to + * not be in the set. + * + * If omitted, the `isValidKey` function defaults to checking against the + * type parameter: `other is E`. + */ + SplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)]) + : _comparator = compare ?? _defaultCompare(), + _validKey = isValidKey ?? ((v) => v is E); + + /** + * Creates a [SplayTreeSet] that contains all [elements]. + * + * The set works as if created by `new SplayTreeSet(compare, isValidKey)`. + * + * All the [elements] should be instances of [E] and valid arguments to + * [compare]. + * The `elements` iterable itself may have any element type, so this + * constructor can be used to down-cast a `Set`, for example as: + * ```dart + * Set superSet = ...; + * Set subSet = + * new SplayTreeSet.from(superSet.whereType()); + * ``` + */ + factory SplayTreeSet.from(Iterable elements, + [int compare(E key1, E key2), bool isValidKey(potentialKey)]) { + SplayTreeSet result = new SplayTreeSet(compare, isValidKey); + for (final element in elements) { + E e = element; + result.add(e); + } + return result; + } + + /** + * Creates a [SplayTreeSet] from [elements]. + * + * The set works as if created by `new SplayTreeSet(compare, isValidKey)`. + * + * All the [elements] should be valid as arguments to the [compare] function. + */ + factory SplayTreeSet.of(Iterable elements, + [int compare(E key1, E key2), bool isValidKey(potentialKey)]) => + new SplayTreeSet(compare, isValidKey)..addAll(elements); + + Set _newSet() => + new SplayTreeSet((T a, T b) => _comparator(a as E, b as E), _validKey); + + Set cast() => Set.castFrom(this, newSet: _newSet); + int _compare(E e1, E e2) => _comparator(e1, e2); + + // From Iterable. + + Iterator get iterator => new _SplayTreeKeyIterator(this); + + int get length => _count; + bool get isEmpty => _root == null; + bool get isNotEmpty => _root != null; + + E get first { + if (_count == 0) throw IterableElementError.noElement(); + return _first.key; + } + + E get last { + if (_count == 0) throw IterableElementError.noElement(); + return _last.key; + } + + E get single { + if (_count == 0) throw IterableElementError.noElement(); + if (_count > 1) throw IterableElementError.tooMany(); + return _root.key; + } + + // From Set. + bool contains(Object element) { + return _validKey(element) && _splay(element) == 0; + } + + bool add(E element) { + int compare = _splay(element); + if (compare == 0) return false; + _addNewRoot(new _SplayTreeNode(element), compare); + return true; + } + + bool remove(Object object) { + if (!_validKey(object)) return false; + return _remove(object) != null; + } + + void addAll(Iterable elements) { + for (E element in elements) { + int compare = _splay(element); + if (compare != 0) { + _addNewRoot(new _SplayTreeNode(element), compare); + } + } + } + + void removeAll(Iterable elements) { + for (Object element in elements) { + if (_validKey(element)) _remove(element); + } + } + + void retainAll(Iterable elements) { + // Build a set with the same sense of equality as this set. + SplayTreeSet retainSet = new SplayTreeSet(_comparator, _validKey); + int modificationCount = _modificationCount; + for (Object object in elements) { + if (modificationCount != _modificationCount) { + // The iterator should not have side effects. + throw new ConcurrentModificationError(this); + } + // Equivalent to this.contains(object). + if (_validKey(object) && _splay(object) == 0) { + retainSet.add(_root.key); + } + } + // Take over the elements from the retained set, if it differs. + if (retainSet._count != _count) { + _root = retainSet._root; + _count = retainSet._count; + _modificationCount++; + } + } + + E lookup(Object object) { + if (!_validKey(object)) return null; + int comp = _splay(object); + if (comp != 0) return null; + return _root.key; + } + + Set intersection(Set other) { + Set result = new SplayTreeSet(_comparator, _validKey); + for (E element in this) { + if (other.contains(element)) result.add(element); + } + return result; + } + + Set difference(Set other) { + Set result = new SplayTreeSet(_comparator, _validKey); + for (E element in this) { + if (!other.contains(element)) result.add(element); + } + return result; + } + + Set union(Set other) { + return _clone()..addAll(other); + } + + SplayTreeSet _clone() { + var set = new SplayTreeSet(_comparator, _validKey); + set._count = _count; + set._root = _copyNode(_root); + return set; + } + + // Copies the structure of a SplayTree into a new similar structure. + // Works on _SplayTreeMapNode as well, but only copies the keys, + _SplayTreeNode _copyNode(_SplayTreeNode node) { + if (node == null) return null; + return new _SplayTreeNode(node.key) + ..left = _copyNode(node.left) + ..right = _copyNode(node.right); + } + + void clear() { + _clear(); + } + + Set toSet() => _clone(); + + String toString() => IterableBase.iterableToFullString(this, '{', '}'); +} +NN<%A#%1: 58B?)?F5I>+?.>:;:!H* HEFDAH'"3FHB))00$+ + *1$$, +! !!JJ)# !JMJ)$""$  H%G;I*  $$G%A'"9BO"G8C;2EMCJKFKKH!)/M73LB/'FML+KBNN7HCK$7#(JCHQ6L$GKFJ6;&&4/&3E(:'30"33%P:!%#)M4!/%)).07 +B>EI$H$N'3$$)#!N'3$$*# A0!<>:$>C/<*E:FK"<6))P7$)$K1 !+$9=.AA,9 , %2":4:JID&+1'D*%")CA,I&!(GBL3G@(, 7O"9'?BO"K8B;2EMI?)@BP*P NBLNIMMPL#M73<PJGC $H /FG&/PP0K?QA3B%(===:"7#$7*$&"%;.'0.@M0&565.6"D&!) +A8)A9$;"GC8#+$'Jofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart,// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Patch file for dart:collection classes. +import 'dart:_foreign_helper' show JS, JSExportName; +import 'dart:_runtime' as dart; +import 'dart:_js_helper' + show + NoInline, + NoSideEffects, + NoThrows, + patch, + LinkedMap, + IdentityMap, + CustomHashMap, + CustomKeyHashMap, + DartIterator, + notNull, + putLinkedMapKey; + +@patch +class HashMap { + @patch + factory HashMap( + {bool equals(K key1, K key2), + int hashCode(K key), + bool isValidKey(Object potentialKey)}) { + if (isValidKey == null) { + if (hashCode == null) { + if (equals == null) { + if (identical(K, String) || identical(K, int)) { + return IdentityMap(); + } + return LinkedMap(); + } + hashCode = dart.hashCode; + } else if (identical(identityHashCode, hashCode) && + identical(identical, equals)) { + return IdentityMap(); + } + return CustomHashMap(equals ?? dart.equals, hashCode); + } + return CustomKeyHashMap( + equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey); + } + + @patch + factory HashMap.identity() = IdentityMap; +} + +@patch +class LinkedHashMap { + @patch + factory LinkedHashMap( + {bool equals(K key1, K key2), + int hashCode(K key), + bool isValidKey(Object potentialKey)}) { + if (isValidKey == null) { + if (hashCode == null) { + if (equals == null) { + if (identical(K, String) || identical(K, int)) { + return IdentityMap(); + } + return LinkedMap(); + } + hashCode = dart.hashCode; + } else if (identical(identityHashCode, hashCode) && + identical(identical, equals)) { + return IdentityMap(); + } + return CustomHashMap(equals ?? dart.equals, hashCode); + } + return CustomKeyHashMap( + equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey); + } + + @patch + factory LinkedHashMap.identity() = IdentityMap; +} + +@patch +class HashSet { + @patch + factory HashSet( + {bool equals(E e1, E e2), + int hashCode(E e), + bool isValidKey(Object potentialKey)}) { + if (isValidKey == null) { + if (hashCode == null) { + if (equals == null) { + if (identical(E, String) || identical(E, int)) { + return _IdentityHashSet(); + } + return _HashSet(); + } + hashCode = dart.hashCode; + } else if (identical(identityHashCode, hashCode) && + identical(identical, equals)) { + return _IdentityHashSet(); + } + return _CustomHashSet( + equals ?? dart.equals, hashCode ?? dart.hashCode); + } + return _CustomKeyHashSet( + equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey); + } + + @patch + factory HashSet.identity() = _IdentityHashSet; +} + +@patch +class LinkedHashSet { + @patch + factory LinkedHashSet( + {bool equals(E e1, E e2), + int hashCode(E e), + bool isValidKey(Object potentialKey)}) { + if (isValidKey == null) { + if (hashCode == null) { + if (equals == null) { + if (identical(E, String) || identical(E, int)) { + return _IdentityHashSet(); + } + return _HashSet(); + } + hashCode = dart.hashCode; + } else if (identical(identityHashCode, hashCode) && + identical(identical, equals)) { + return _IdentityHashSet(); + } + return _CustomHashSet( + equals ?? dart.equals, hashCode ?? dart.hashCode); + } + return _CustomKeyHashSet( + equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey); + } + + @patch + factory LinkedHashSet.identity() = _IdentityHashSet; +} + +class _HashSet extends _InternalSet + implements HashSet, LinkedHashSet { + /// The backing store for this set. + /// + /// Keys that use identity equality are stored directly. For other types of + /// keys, we first look them up (by hashCode) in the [_keyMap] map, then + /// we lookup the key in this map. + @notNull + final _map = JS('', 'new Set()'); + + /// Items that use custom equality semantics. + /// + /// This maps from the item's hashCode to the canonical key, which is then + /// used to lookup the item in [_map]. Keeping the data in our primary backing + /// map gives us the ordering semantics requred by [LinkedHashMap], while + /// also providing convenient access to keys/values. + @notNull + final _keyMap = JS('', 'new Map()'); + + // We track the number of modifications done to the key set of the + // hash map to be able to throw when the map is modified while being + // iterated over. + // + // Value cycles after 2^30 modifications so that modification counts are + // always unboxed (Smi) values. Modification detection will be missed if you + // make exactly some multiple of 2^30 modifications between advances of an + // iterator. + @notNull + int _modifications = 0; + + _HashSet(); + + Set _newSet() => _HashSet(); + + Set _newSimilarSet() => _HashSet(); + + bool contains(Object key) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + @notNull + var k = key; + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode); + if (buckets != null) { + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + k = JS('', '#[#]', buckets, i); + if (k == key) return true; + } + } + return false; + } + return JS('bool', '#.has(#)', _map, key); + } + + E lookup(Object key) { + if (key == null) return null; + if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + @notNull + var k = key; + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode); + if (buckets != null) { + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + k = JS('', '#[#]', buckets, i); + if (k == key) return JS('', '#', k); + } + } + return null; + } + return JS('', '#.has(#) ? # : null', _map, key, key); + } + + bool add(E key) { + var map = _map; + if (key == null) { + if (JS('', '#.has(null)', map)) return false; + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + var keyMap = _keyMap; + @notNull + var k = key; + int hash = JS('!', '# & 0x3ffffff', k.hashCode); + var buckets = JS('', '#.get(#)', keyMap, hash); + if (buckets == null) { + JS('', '#.set(#, [#])', keyMap, hash, key); + } else { + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + k = JS('', '#[#]', buckets, i); + if (k == key) return false; + } + JS('', '#.push(#)', buckets, key); + } + } else if (JS('', '#.has(#)', map, key)) { + return false; + } + JS('', '#.add(#)', map, key); + _modifications = (_modifications + 1) & 0x3ffffff; + return true; + } + + void addAll(Iterable objects) { + var map = _map; + int length = JS('', '#.size', map); + for (E key in objects) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + key = putLinkedMapKey(key, _keyMap); + } + JS('', '#.add(#)', map, key); + } + if (length != JS('!', '#.size', map)) { + _modifications = (_modifications + 1) & 0x3ffffff; + } + } + + bool remove(Object key) { + if (key == null) { + key = null; + } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'), + dart.identityEquals)) { + @notNull + var k = key; + int hash = JS('!', '# & 0x3ffffff', k.hashCode); + var buckets = JS('', '#.get(#)', _keyMap, hash); + if (buckets == null) return false; // not found + for (int i = 0, n = JS('!', '#.length', buckets);;) { + k = JS('', '#[#]', buckets, i); + if (k == key) { + key = k; + if (n == 1) { + JS('', '#.delete(#)', _keyMap, hash); + } else { + JS('', '#.splice(#, 1)', buckets, i); + } + break; + } + if (++i >= n) return false; // not found + } + } + var map = _map; + if (JS('bool', '#.delete(#)', map, key)) { + _modifications = (_modifications + 1) & 0x3ffffff; + return true; + } + return false; + } + + void clear() { + var map = _map; + if (JS('!', '#.size', map) > 0) { + JS('', '#.clear()', map); + JS('', '#.clear()', _keyMap); + _modifications = (_modifications + 1) & 0x3ffffff; + } + } +} + +class _IdentityHashSet extends _InternalSet + implements HashSet, LinkedHashSet { + /// The backing store for this set. + @notNull + final _map = JS('', 'new Set()'); + + @notNull + int _modifications = 0; + + _IdentityHashSet(); + + Set _newSet() => _IdentityHashSet(); + + Set _newSimilarSet() => _IdentityHashSet(); + + bool contains(Object element) { + return JS('', '#.has(#)', _map, element); + } + + E lookup(Object element) { + return JS('', '#.has(#)', _map, element) ? element : null; + } + + bool add(E element) { + var map = _map; + if (JS('bool', '#.has(#)', map, element)) return false; + JS('', '#.add(#)', map, element); + _modifications = (_modifications + 1) & 0x3ffffff; + return true; + } + + void addAll(Iterable objects) { + var map = _map; + int length = JS('', '#.size', map); + for (E key in objects) { + JS('', '#.add(#)', map, key); + } + if (length != JS('!', '#.size', map)) { + _modifications = (_modifications + 1) & 0x3ffffff; + } + } + + bool remove(Object element) { + if (JS('bool', '#.delete(#)', _map, element)) { + _modifications = (_modifications + 1) & 0x3ffffff; + return true; + } + return false; + } + + void clear() { + var map = _map; + if (JS('!', '#.size', map) > 0) { + JS('', '#.clear()', map); + _modifications = (_modifications + 1) & 0x3ffffff; + } + } +} + +class _CustomKeyHashSet extends _CustomHashSet { + _Predicate _validKey; + _CustomKeyHashSet(_Equality equals, _Hasher hashCode, this._validKey) + : super(equals, hashCode); + + Set _newSet() => _CustomKeyHashSet(_equals, _hashCode, _validKey); + + Set _newSimilarSet() => _HashSet(); + + bool contains(Object element) { + // TODO(jmesserly): there is a subtle difference here compared to Dart 1. + // See the comment on CustomKeyHashMap.containsKey for more information. + // Treatment of `null` is different due to strong mode's requirement to + // perform an `element is E` check before calling equals/hashCode. + if (!_validKey(element)) return false; + return super.contains(element); + } + + E lookup(Object element) { + if (!_validKey(element)) return null; + return super.lookup(element); + } + + bool remove(Object element) { + if (!_validKey(element)) return false; + return super.remove(element); + } +} + +class _CustomHashSet extends _InternalSet + implements HashSet, LinkedHashSet { + _Equality _equals; + _Hasher _hashCode; + + // We track the number of modifications done to the key set of the + // hash map to be able to throw when the map is modified while being + // iterated over. + // + // Value cycles after 2^30 modifications so that modification counts are + // always unboxed (Smi) values. Modification detection will be missed if you + // make exactly some multiple of 2^30 modifications between advances of an + // iterator. + @notNull + int _modifications = 0; + + /// The backing store for this set, used to handle ordering. + // TODO(jmesserly): a non-linked custom hash set could skip this. + @notNull + final _map = JS('', 'new Set()'); + + /// Our map used to map keys onto the canonical key that is stored in [_map]. + @notNull + final _keyMap = JS('', 'new Map()'); + + _CustomHashSet(this._equals, this._hashCode); + + Set _newSet() => _CustomHashSet(_equals, _hashCode); + Set _newSimilarSet() => _HashSet(); + + bool contains(Object key) { + if (key is E) { + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key)); + if (buckets != null) { + var equals = _equals; + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + E k = JS('', '#[#]', buckets, i); + if (equals(k, key)) return true; + } + } + } + return false; + } + + E lookup(Object key) { + if (key is E) { + var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key)); + if (buckets != null) { + var equals = _equals; + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + E k = JS('', '#[#]', buckets, i); + if (equals(k, key)) return JS('', '#', k); + } + } + } + return null; + } + + bool add(E key) { + var keyMap = _keyMap; + var hash = JS('!', '# & 0x3ffffff', _hashCode(key)); + var buckets = JS('', '#.get(#)', keyMap, hash); + if (buckets == null) { + JS('', '#.set(#, [#])', keyMap, hash, key); + } else { + var equals = _equals; + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + E k = JS('', '#[#]', buckets, i); + if (equals(k, key)) return false; + } + JS('', '#.push(#)', buckets, key); + } + JS('', '#.add(#)', _map, key); + _modifications = (_modifications + 1) & 0x3ffffff; + return true; + } + + void addAll(Iterable objects) { + // TODO(jmesserly): it'd be nice to skip the covariance check here. + for (E element in objects) add(element); + } + + bool remove(Object key) { + if (key is E) { + var hash = JS('!', '# & 0x3ffffff', _hashCode(key)); + var keyMap = _keyMap; + var buckets = JS('', '#.get(#)', keyMap, hash); + if (buckets == null) return false; // not found + var equals = _equals; + for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) { + E k = JS('', '#[#]', buckets, i); + if (equals(k, key)) { + if (n == 1) { + JS('', '#.delete(#)', keyMap, hash); + } else { + JS('', '#.splice(#, 1)', buckets, i); + } + JS('', '#.delete(#)', _map, k); + _modifications = (_modifications + 1) & 0x3ffffff; + return true; + } + } + } + return false; + } + + void clear() { + var map = _map; + if (JS('!', '#.size', map) > 0) { + JS('', '#.clear()', map); + JS('', '#.clear()', _keyMap); + _modifications = (_modifications + 1) & 0x3ffffff; + } + } +} + +/// Base class for our internal [LinkedHashSet]/[HashSet] implementations. +/// +/// This implements the common functionality. +abstract class _InternalSet extends _HashSetBase { + @notNull + get _map; + + @notNull + int get _modifications; + + @notNull + int get length => JS('!', '#.size', _map); + + @notNull + bool get isEmpty => JS('bool', '#.size == 0', _map); + + @notNull + bool get isNotEmpty => JS('bool', '#.size != 0', _map); + + Iterator get iterator => DartIterator(_jsIterator()); + + @JSExportName('Symbol.iterator') + _jsIterator() { + var self = this; + var iterator = JS('', '#.values()', self._map); + int modifications = self._modifications; + return JS( + '', + '''{ + next() { + if (# != #) { + throw #; + } + return #.next(); + } + }''', + modifications, + self._modifications, + ConcurrentModificationError(self), + iterator); + } +} +(NN<+5   $/;( $ +":*$C#G 2 $/;( $ +":*$C#G 8  /;* +":*& =!G 4  /;* +":*& =!G :*.&NK% $0MQL7 'EGKOM %/N IH*% +."G IH*/ +:4N 764H*& ++/"7%(P"-$19N 776<(22  +1/9+ $92.& $ -7".?<&7%($19 49+ 97 N!K/"NMLG+$*" +"0.EGKOM ?D $P '0=/MH,+ +MH,5 +>42 F**)#7%H-@66F*12 *= ++ $9K.9   2 7 :>#4-  + ++Wfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/collections.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * An unmodifiable [List] view of another List. + * + * The source of the elements may be a [List] or any [Iterable] with + * efficient [Iterable.length] and [Iterable.elementAt]. + */ +class UnmodifiableListView extends UnmodifiableListBase { + final Iterable _source; + + /** + * Creates an unmodifiable list backed by [source]. + * + * The [source] of the elements may be a [List] or any [Iterable] with + * efficient [Iterable.length] and [Iterable.elementAt]. + */ + UnmodifiableListView(Iterable source) : _source = source; + + List cast() => new UnmodifiableListView(_source.cast()); + int get length => _source.length; + + E operator [](int index) => _source.elementAt(index); +} +NN<0E9@6I;?D$8Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/hash_set.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** Common parts of [HashSet] and [LinkedHashSet] implementations. */ +abstract class _HashSetBase extends SetBase { + // The following two methods override the ones in SetBase. + // It's possible to be more efficient if we have a way to create an empty + // set of the correct type. + + Set _newSet(); + + Set _newSimilarSet(); + + Set cast() => Set.castFrom(this, newSet: _newSimilarSet); + Set difference(Set other) { + Set result = _newSet(); + for (var element in this) { + if (!other.contains(element)) result.add(element); + } + return result; + } + + Set intersection(Set other) { + Set result = _newSet(); + for (var element in this) { + if (other.contains(element)) result.add(element); + } + return result; + } + + // Subclasses can optimize this further. + Set toSet() => _newSet()..addAll(this); +} + +/** + * An unordered hash-table based [Set] implementation. + * + * The elements of a `HashSet` must have consistent equality + * and hashCode implementations. This means that the equals operation + * must define a stable equivalence relation on the elements (reflexive, + * symmetric, transitive, and consistent over time), and that the hashCode + * must consistent with equality, so that the same for objects that are + * considered equal. + * + * The set allows `null` as an element. + * + * Most simple operations on `HashSet` are done in (potentially amortized) + * constant time: [add], [contains], [remove], and [length], provided the hash + * codes of objects are well distributed. + * + * The iteration order of the set is not specified and depends on + * the hashcodes of the provided elements. However, the order is stable: + * multiple iterations over the same set produce the same order, as long as + * the set is not modified. + */ +abstract class HashSet implements Set { + /** + * Create a hash set using the provided [equals] as equality. + * + * The provided [equals] must define a stable equivalence relation, and + * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode] + * methods won't work on all objects, but only on some instances of E, the + * [isValidKey] predicate can be used to restrict the keys that the functions + * are applied to. + * Any key for which [isValidKey] returns false is automatically assumed + * to not be in the set when asking `contains`. + * + * If [equals] or [hashCode] are omitted, the set uses + * the elements' intrinsic [Object.==] and [Object.hashCode]. + * + * If you supply one of [equals] and [hashCode], + * you should generally also to supply the other. + * + * If the supplied `equals` or `hashCode` functions won't work on all [E] + * objects, and the map will be used in a setting where a non-`E` object + * is passed to, e.g., `contains`, then the [isValidKey] function should + * also be supplied. + * + * If [isValidKey] is omitted, it defaults to testing if the object is an + * [E] instance. That means that: + * + * new HashSet(equals: (int e1, int e2) => (e1 - e2) % 5 == 0, + * hashCode: (int e) => e % 5) + * + * does not need an `isValidKey` argument, because it defaults to only + * accepting `int` values which are accepted by both `equals` and `hashCode`. + * + * If neither `equals`, `hashCode`, nor `isValidKey` is provided, + * the default `isValidKey` instead accepts all values. + * The default equality and hashcode operations are assumed to work on all + * objects. + * + * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode] + * and `isValidKey` is omitted, the resulting set is identity based, + * and the `isValidKey` defaults to accepting all keys. + * Such a map can be created directly using [HashSet.identity]. + */ + external factory HashSet( + {bool equals(E e1, E e2), + int hashCode(E e), + bool isValidKey(potentialKey)}); + + /** + * Creates an unordered identity-based set. + * + * Effectively a shorthand for: + * + * new HashSet(equals: identical, + * hashCode: identityHashCode) + */ + external factory HashSet.identity(); + + /** + * Create a hash set containing all [elements]. + * + * Creates a hash set as by `new HashSet()` and adds all given [elements] + * to the set. The elements are added in order. If [elements] contains + * two entries that are equal, but not identical, then the first one is + * the one in the resulting set. + * + * All the [elements] should be instances of [E]. + * The `elements` iterable itself may have any element type, so this + * constructor can be used to down-cast a `Set`, for example as: + * ```dart + * Set superSet = ...; + * Set subSet = + * new HashSet.from(superSet.whereType()); + * ``` + */ + factory HashSet.from(Iterable elements) { + HashSet result = new HashSet(); + for (final e in elements) { + result.add(e); + } + return result; + } + + /** + * Create a hash set containing all [elements]. + * + * Creates a hash set as by `new HashSet()` and adds all given [elements] + * to the set. The elements are added in order. If [elements] contains + * two entries that are equal, but not identical, then the first one is + * the one in the resulting set. + */ + factory HashSet.of(Iterable elements) => + new HashSet()..addAll(elements); + + /** + * Provides an iterator that iterates over the elements of this set. + * + * The order of iteration is unspecified, + * but consistent between changes to the set. + */ + Iterator get iterator; +} +NN<F4=LH) 9+ 8+-7=FIKH(KO*BIL.@JPMPK29@34LKKL$J6IPD:MLG:B '."+4'2OIJ#4GC $C ,* 2OIJ#.*G,0Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/iterable.dart?// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * This [Iterable] mixin implements all [Iterable] members except `iterator`. + * + * All other methods are implemented in terms of `iterator`. + */ +abstract class IterableMixin implements Iterable { + // This class has methods copied verbatim into: + // - IterableBase + // - SetMixin + // If changing a method here, also change the other copies. + + Iterable cast() => Iterable.castFrom(this); + Iterable map(T f(E element)) => new MappedIterable(this, f); + + Iterable where(bool f(E element)) => new WhereIterable(this, f); + + Iterable whereType() => new WhereTypeIterable(this); + + Iterable expand(Iterable f(E element)) => + new ExpandIterable(this, f); + + Iterable followedBy(Iterable other) { + // Type workaround because IterableMixin doesn't promote + // to EfficientLengthIterable. + Iterable self = this; + if (self is EfficientLengthIterable) { + return new FollowedByIterable.firstEfficient(self, other); + } + return new FollowedByIterable(this, other); + } + + bool contains(Object element) { + for (E e in this) { + if (e == element) return true; + } + return false; + } + + void forEach(void f(E element)) { + for (E element in this) f(element); + } + + E reduce(E combine(E value, E element)) { + Iterator iterator = this.iterator; + if (!iterator.moveNext()) { + throw IterableElementError.noElement(); + } + E value = iterator.current; + while (iterator.moveNext()) { + value = combine(value, iterator.current); + } + return value; + } + + T fold(T initialValue, T combine(T previousValue, E element)) { + var value = initialValue; + for (E element in this) value = combine(value, element); + return value; + } + + bool every(bool f(E element)) { + for (E element in this) { + if (!f(element)) return false; + } + return true; + } + + String join([String separator = ""]) { + Iterator iterator = this.iterator; + if (!iterator.moveNext()) return ""; + StringBuffer buffer = new StringBuffer(); + if (separator == null || separator == "") { + do { + buffer.write("${iterator.current}"); + } while (iterator.moveNext()); + } else { + buffer.write("${iterator.current}"); + while (iterator.moveNext()) { + buffer.write(separator); + buffer.write("${iterator.current}"); + } + } + return buffer.toString(); + } + + bool any(bool test(E element)) { + for (E element in this) { + if (test(element)) return true; + } + return false; + } + + List toList({bool growable: true}) => + new List.from(this, growable: growable); + + Set toSet() => new Set.from(this); + + int get length { + assert(this is! EfficientLengthIterable); + int count = 0; + Iterator it = iterator; + while (it.moveNext()) { + count++; + } + return count; + } + + bool get isEmpty => !iterator.moveNext(); + + bool get isNotEmpty => !isEmpty; + + Iterable take(int count) { + return new TakeIterable(this, count); + } + + Iterable takeWhile(bool test(E value)) { + return new TakeWhileIterable(this, test); + } + + Iterable skip(int count) { + return new SkipIterable(this, count); + } + + Iterable skipWhile(bool test(E value)) { + return new SkipWhileIterable(this, test); + } + + E get first { + Iterator it = iterator; + if (!it.moveNext()) { + throw IterableElementError.noElement(); + } + return it.current; + } + + E get last { + Iterator it = iterator; + if (!it.moveNext()) { + throw IterableElementError.noElement(); + } + E result; + do { + result = it.current; + } while (it.moveNext()); + return result; + } + + E get single { + Iterator it = iterator; + if (!it.moveNext()) throw IterableElementError.noElement(); + E result = it.current; + if (it.moveNext()) throw IterableElementError.tooMany(); + return result; + } + + E firstWhere(bool test(E value), {E orElse()}) { + for (E element in this) { + if (test(element)) return element; + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E lastWhere(bool test(E value), {E orElse()}) { + E result = null; + bool foundMatching = false; + for (E element in this) { + if (test(element)) { + result = element; + foundMatching = true; + } + } + if (foundMatching) return result; + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E singleWhere(bool test(E element), {E orElse()}) { + E result = null; + bool foundMatching = false; + for (E element in this) { + if (test(element)) { + if (foundMatching) { + throw IterableElementError.tooMany(); + } + result = element; + foundMatching = true; + } + } + if (foundMatching) return result; + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E elementAt(int index) { + if (index is! int) throw new ArgumentError.notNull("index"); + RangeError.checkNotNegative(index, "index"); + int elementIndex = 0; + for (E element in this) { + if (index == elementIndex) return element; + elementIndex++; + } + throw new RangeError.index(index, this, "index", null, elementIndex); + } + + String toString() => IterableBase.iterableToShortString(this, '(', ')'); +} + +/** + * Base class for implementing [Iterable]. + * + * This class implements all methods of [Iterable], except [Iterable.iterator], + * in terms of `iterator`. + */ +abstract class IterableBase extends Iterable { + const IterableBase(); + + /** + * Convert an `Iterable` to a string like [IterableBase.toString]. + * + * Allows using other delimiters than '(' and ')'. + * + * Handles circular references where converting one of the elements + * to a string ends up converting [iterable] to a string again. + */ + static String iterableToShortString(Iterable iterable, + [String leftDelimiter = '(', String rightDelimiter = ')']) { + if (_isToStringVisiting(iterable)) { + if (leftDelimiter == "(" && rightDelimiter == ")") { + // Avoid creating a new string in the "common" case. + return "(...)"; + } + return "$leftDelimiter...$rightDelimiter"; + } + List parts = []; + _toStringVisiting.add(iterable); + try { + _iterablePartsToStrings(iterable, parts); + } finally { + assert(identical(_toStringVisiting.last, iterable)); + _toStringVisiting.removeLast(); + } + return (new StringBuffer(leftDelimiter) + ..writeAll(parts, ", ") + ..write(rightDelimiter)) + .toString(); + } + + /** + * Converts an `Iterable` to a string. + * + * Converts each elements to a string, and separates the results by ", ". + * Then wraps the result in [leftDelimiter] and [rightDelimiter]. + * + * Unlike [iterableToShortString], this conversion doesn't omit any + * elements or puts any limit on the size of the result. + * + * Handles circular references where converting one of the elements + * to a string ends up converting [iterable] to a string again. + */ + static String iterableToFullString(Iterable iterable, + [String leftDelimiter = '(', String rightDelimiter = ')']) { + if (_isToStringVisiting(iterable)) { + return "$leftDelimiter...$rightDelimiter"; + } + StringBuffer buffer = new StringBuffer(leftDelimiter); + _toStringVisiting.add(iterable); + try { + buffer.writeAll(iterable, ", "); + } finally { + assert(identical(_toStringVisiting.last, iterable)); + _toStringVisiting.removeLast(); + } + buffer.write(rightDelimiter); + return buffer.toString(); + } +} + +/** A collection used to identify cyclic lists during toString() calls. */ +final List _toStringVisiting = []; + +/** Check if we are currently visiting `o` in a toString call. */ +bool _isToStringVisiting(Object o) { + for (int i = 0; i < _toStringVisiting.length; i++) { + if (identical(o, _toStringVisiting[i])) return true; + } + return false; +} + +/** + * Convert elements of [iterable] to strings and store them in [parts]. + */ +void _iterablePartsToStrings(Iterable iterable, List parts) { + /* + * This is the complicated part of [iterableToShortString]. + * It is extracted as a separate function to avoid having too much code + * inside the try/finally. + */ + /// Try to stay below this many characters. + const int lengthLimit = 80; + + /// Always at least this many elements at the start. + const int headCount = 3; + + /// Always at least this many elements at the end. + const int tailCount = 2; + + /// Stop iterating after this many elements. Iterables can be infinite. + const int maxCount = 100; + // Per entry length overhead. It's for ", " for all after the first entry, + // and for "(" and ")" for the initial entry. By pure luck, that's the same + // number. + const int overhead = 2; + const int ellipsisSize = 3; // "...".length. + + int length = 0; + int count = 0; + Iterator it = iterable.iterator; + // Initial run of elements, at least headCount, and then continue until + // passing at most lengthLimit characters. + while (length < lengthLimit || count < headCount) { + if (!it.moveNext()) return; + String next = "${it.current}"; + parts.add(next); + length += next.length + overhead; + count++; + } + + String penultimateString; + String ultimateString; + + // Find last two elements. One or more of them may already be in the + // parts array. Include their length in `length`. + var penultimate = null; + var ultimate = null; + if (!it.moveNext()) { + if (count <= headCount + tailCount) return; + ultimateString = parts.removeLast(); + penultimateString = parts.removeLast(); + } else { + penultimate = it.current; + count++; + if (!it.moveNext()) { + if (count <= headCount + 1) { + parts.add("$penultimate"); + return; + } + ultimateString = "$penultimate"; + penultimateString = parts.removeLast(); + length += ultimateString.length + overhead; + } else { + ultimate = it.current; + count++; + // Then keep looping, keeping the last two elements in variables. + assert(count < maxCount); + while (it.moveNext()) { + penultimate = ultimate; + ultimate = it.current; + count++; + if (count > maxCount) { + // If we haven't found the end before maxCount, give up. + // This cannot happen in the code above because each entry + // increases length by at least two, so there is no way to + // visit more than ~40 elements before this loop. + + // Remove any surplus elements until length, including ", ...)", + // is at most lengthLimit. + while (length > lengthLimit - ellipsisSize - overhead && + count > headCount) { + length -= parts.removeLast().length + overhead; + count--; + } + parts.add("..."); + return; + } + } + penultimateString = "$penultimate"; + ultimateString = "$ultimate"; + length += ultimateString.length + penultimateString.length + 2 * overhead; + } + } + + // If there is a gap between the initial run and the last two, + // prepare to add an ellipsis. + String elision = null; + if (count > parts.length + tailCount) { + elision = "..."; + length += ellipsisSize + overhead; + } + + // If the last two elements were very long, and we have more than + // headCount elements in the initial run, drop some to make room for + // the last two. + while (length > lengthLimit && parts.length > headCount) { + length -= parts.removeLast().length + overhead; + if (elision == null) { + elision = "..."; + length += ellipsisSize + overhead; + } + } + if (elision != null) { + parts.add(elision); + } + parts.add(penultimateString); + parts.add(ultimateString); +} +NN<N=92>:KI@5).@&.D3"%$(,* . "0E="%)*).0 -% +$!-#&+2+.,# -.1 -.1.. @=3)),2 &),6 0 +&),A11JK+P5E5FB9C);=1% +0;&,"#)LDF;FB8C)1;% +';&"K#B%79H>>J.75JMN /#J-6 #& G40),  $#'.2 H   CEE<K%C#<  +*$QA!*'DG=4) Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/iterator.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * The [HasNextIterator] class wraps an [Iterator] and provides methods to + * iterate over an object using `hasNext` and `next`. + * + * An [HasNextIterator] does not implement the [Iterator] interface. + */ +class HasNextIterator { + static const int _HAS_NEXT_AND_NEXT_IN_CURRENT = 0; + static const int _NO_NEXT = 1; + static const int _NOT_MOVED_YET = 2; + + Iterator _iterator; + int _state = _NOT_MOVED_YET; + + HasNextIterator(this._iterator); + + bool get hasNext { + if (_state == _NOT_MOVED_YET) _move(); + return _state == _HAS_NEXT_AND_NEXT_IN_CURRENT; + } + + E next() { + // Call to hasNext is necessary to make sure we are positioned at the first + // element when we start iterating. + if (!hasNext) throw new StateError("No more elements"); + assert(_state == _HAS_NEXT_AND_NEXT_IN_CURRENT); + E result = _iterator.current; + _move(); + return result; + } + + void _move() { + if (_iterator.moveNext()) { + _state = _HAS_NEXT_AND_NEXT_IN_CURRENT; + } else { + _state = _NO_NEXT; + } + } +} +/NN<K6E6!'#+4 P(<5"  . [file:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/linked_hash_map.dart)// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * A hash-table based implementation of [Map]. + * + * The insertion order of keys is remembered, + * and keys are iterated in the order they were inserted into the map. + * Values are iterated in their corresponding key's order. + * Changing a key's value, when the key is already in the map, + * does not change the iteration order, + * but removing the key and adding it again + * will make it be last in the iteration order. + * + * The keys of a `LinkedHashMap` must have consistent [Object.==] + * and [Object.hashCode] implementations. This means that the `==` operator + * must define a stable equivalence relation on the keys (reflexive, + * symmetric, transitive, and consistent over time), and that `hashCode` + * must be the same for objects that are considered equal by `==`. + * + * The map allows `null` as a key. + */ +abstract class LinkedHashMap implements Map { + /** + * Creates an insertion-ordered hash-table based [Map]. + * + * If [equals] is provided, it is used to compare the keys in the table with + * new keys. If [equals] is omitted, the key's own [Object.==] is used + * instead. + * + * Similar, if [hashCode] is provided, it is used to produce a hash value + * for keys in order to place them in the hash table. If it is omitted, the + * key's own [Object.hashCode] is used. + * + * If using methods like [operator []], [remove] and [containsKey] together + * with a custom equality and hashcode, an extra `isValidKey` function + * can be supplied. This function is called before calling [equals] or + * [hashCode] with an argument that may not be a [K] instance, and if the + * call returns false, the key is assumed to not be in the set. + * The [isValidKey] function defaults to just testing if the object is a + * [K] instance. + * + * Example: + * + * new LinkedHashMap(equals: (int a, int b) => (b - a) % 5 == 0, + * hashCode: (int e) => e % 5) + * + * This example map does not need an `isValidKey` function to be passed. + * The default function accepts only `int` values, which can safely be + * passed to both the `equals` and `hashCode` functions. + * + * If neither `equals`, `hashCode`, nor `isValidKey` is provided, + * the default `isValidKey` instead accepts all keys. + * The default equality and hashcode operations are assumed to work on all + * objects. + * + * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode] + * and `isValidKey` is omitted, the resulting map is identity based, + * and the `isValidKey` defaults to accepting all keys. + * Such a map can be created directly using [LinkedHashMap.identity]. + * + * The used `equals` and `hashCode` method should always be consistent, + * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash + * of an object, or what it compares equal to, should not change while the + * object is in the table. If it does change, the result is unpredictable. + * + * If you supply one of [equals] and [hashCode], + * you should generally also to supply the other. + */ + external factory LinkedHashMap( + {bool equals(K key1, K key2), + int hashCode(K key), + bool isValidKey(potentialKey)}); + + /** + * Creates an insertion-ordered identity-based map. + * + * Effectively a shorthand for: + * + * new LinkedHashMap(equals: identical, + * hashCode: identityHashCode) + */ + external factory LinkedHashMap.identity(); + + /** + * Creates a [LinkedHashMap] that contains all key value pairs of [other]. + * + * The keys must all be instances of [K] and the values to [V]. + * The [other] map itself can have any type. + */ + factory LinkedHashMap.from(Map other) { + LinkedHashMap result = new LinkedHashMap(); + other.forEach((k, v) { + result[k] = v; + }); + return result; + } + + /** + * Creates a [LinkedHashMap] that contains all key value pairs of [other]. + */ + factory LinkedHashMap.of(Map other) => + new LinkedHashMap()..addAll(other); + + /** + * Creates a [LinkedHashMap] where the keys and values are computed from the + * [iterable]. + * + * For each element of the [iterable] this constructor computes a key/value + * pair, by applying [key] and [value] respectively. + * + * The keys of the key/value pairs do not need to be unique. The last + * occurrence of a key will simply overwrite any previous value. + * + * If no values are specified for [key] and [value] the default is the + * identity function. + */ + factory LinkedHashMap.fromIterable(Iterable iterable, + {K key(element), V value(element)}) { + LinkedHashMap map = new LinkedHashMap(); + MapBase._fillMapWithMappedIterable(map, iterable, key, value); + return map; + } + + /** + * Creates a [LinkedHashMap] associating the given [keys] to [values]. + * + * This constructor iterates over [keys] and [values] and maps each element of + * [keys] to the corresponding element of [values]. + * + * If [keys] contains the same object multiple times, the last occurrence + * overwrites the previous value. + * + * It is an error if the two [Iterable]s don't have the same length. + */ + factory LinkedHashMap.fromIterables(Iterable keys, Iterable values) { + LinkedHashMap map = new LinkedHashMap(); + MapBase._fillMapWithIterables(map, keys, values); + return map; + } +} +NN</.G;?(,0BLEIC#::OILN*NIILBKP@KI;D8MLG:HJKMM34"$'6"4=-MB/*<M/0ON7HCI8,9CIQ6L$GN96[file:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/linked_hash_set.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * A [LinkedHashSet] is a hash-table based [Set] implementation. + * + * The `LinkedHashSet` also keep track of the order that elements were inserted + * in, and iteration happens in first-to-last insertion order. + * + * The elements of a `LinkedHashSet` must have consistent [Object.==] + * and [Object.hashCode] implementations. This means that the `==` operator + * must define a stable equivalence relation on the elements (reflexive, + * symmetric, transitive, and consistent over time), and that `hashCode` + * must be the same for objects that are considered equal by `==`. + * + * The set allows `null` as an element. + * + * Iteration of elements is done in element insertion order. + * An element that was added after another will occur later in the iteration. + * Adding an element that is already in the set + * does not change its position in the iteration order, + * but removing an element and adding it again, + * will make it the last element of an iteration. + * + * Most simple operations on `HashSet` are done in (potentially amortized) + * constant time: [add], [contains], [remove], and [length], provided the hash + * codes of objects are well distributed.. + */ +abstract class LinkedHashSet implements Set { + /** + * Create an insertion-ordered hash set using the provided + * [equals] and [hashCode]. + * + * The provided [equals] must define a stable equivalence relation, and + * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode] + * methods won't work on all objects, but only on some instances of E, the + * [isValidKey] predicate can be used to restrict the keys that the functions + * are applied to. + * Any key for which [isValidKey] returns false is automatically assumed + * to not be in the set when asking `contains`. + * + * If [equals] or [hashCode] are omitted, the set uses + * the elements' intrinsic [Object.==] and [Object.hashCode], + * and [isValidKey] is ignored since these operations are assumed + * to work on all objects. + * + * If you supply one of [equals] and [hashCode], + * you should generally also to supply the other. + * + * If the supplied `equals` or `hashCode` functions won't work on all [E] + * objects, and the map will be used in a setting where a non-`E` object + * is passed to, e.g., `contains`, then the [isValidKey] function should + * also be supplied. + * + * If [isValidKey] is omitted, it defaults to testing if the object is an + * [E] instance. That means that: + * + * new LinkedHashSet(equals: (int e1, int e2) => (e1 - e2) % 5 == 0, + * hashCode: (int e) => e % 5) + * + * does not need an `isValidKey` argument, because it defaults to only + * accepting `int` values which are accepted by both `equals` and `hashCode`. + * + * If neither `equals`, `hashCode`, nor `isValidKey` is provided, + * the default `isValidKey` instead accepts all values. + * The default equality and hashcode operations are assumed to work on all + * objects. + * + * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode] + * and `isValidKey` is omitted, the resulting set is identity based, + * and the `isValidKey` defaults to accepting all keys. + * Such a map can be created directly using [LinkedHashSet.identity]. + */ + external factory LinkedHashSet( + {bool equals(E e1, E e2), + int hashCode(E e), + bool isValidKey(potentialKey)}); + + /** + * Creates an insertion-ordered identity-based set. + * + * Effectively a shorthand for: + * + * new LinkedHashSet(equals: identical, + * hashCode: identityHashCode) + */ + external factory LinkedHashSet.identity(); + + /** + * Create a linked hash set containing all [elements]. + * + * Creates a linked hash set as by `new LinkedHashSet()` and adds each + * element of `elements` to this set in the order they are iterated. + * + * All the [elements] should be instances of [E]. + * The `elements` iterable itself may have any element type, + * so this constructor can be used to down-cast a `Set`, for example as: + * + * Set superSet = ...; + * Iterable tmp = superSet.where((e) => e is SubType); + * Set subSet = new LinkedHashSet.from(tmp); + */ + factory LinkedHashSet.from(Iterable elements) { + LinkedHashSet result = new LinkedHashSet(); + for (final element in elements) { + result.add(element); + } + return result; + } + + /** + * Create a linked hash set from [elements]. + * + * Creates a linked hash set as by `new LinkedHashSet()` and adds each + * element of `elements` to this set in the order they are iterated. + */ + factory LinkedHashSet.of(Iterable elements) => + new LinkedHashSet()..addAll(elements); + + /** + * Executes a function on each element of the set. + * + * The elements are iterated in insertion order. + */ + void forEach(void action(E element)); + + /** + * Provides an iterator that iterates over the elements in insertion order. + */ + Iterator get iterator; +} +NN<AP?FLIIC(=N0802KO+4=JPMPK29@D34LKKL$P<IPD:MLG:H" '6"1:-9LG4?K(HE26&/LG4053(NWfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/linked_list.dartD// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * A specialized double-linked list of elements that extends [LinkedListEntry]. + * + * This is not a generic data structure. It only accepts elements that extend + * the [LinkedListEntry] class. See the [Queue] implementations for + * generic collections that allow constant time adding and removing at the ends. + * + * This is not a [List] implementation. Despite its name, this class does not + * implement the [List] interface. It does not allow constant time lookup by + * index. + * + * Because the elements themselves contain the links of this linked list, + * each element can be in only one list at a time. To add an element to another + * list, it must first be removed from its current list (if any). + * + * In return, each element knows its own place in the linked list, as well as + * which list it is in. This allows constant time [LinkedListEntry.insertAfter], + * [LinkedListEntry.insertBefore] and [LinkedListEntry.unlink] operations + * when all you have is the element. + * + * A `LinkedList` also allows constant time adding and removing at either end, + * and a constant time length getter. + */ +class LinkedList> extends Iterable { + int _modificationCount = 0; + int _length = 0; + E _first; + + /** + * Construct a new empty linked list. + */ + LinkedList(); + + /** + * Add [entry] to the beginning of the linked list. + */ + void addFirst(E entry) { + _insertBefore(_first, entry, updateFirst: true); + _first = entry; + } + + /** + * Add [entry] to the end of the linked list. + */ + void add(E entry) { + _insertBefore(_first, entry, updateFirst: false); + } + + /** + * Add [entries] to the end of the linked list. + */ + void addAll(Iterable entries) { + entries.forEach(add); + } + + /** + * Remove [entry] from the linked list. + * + * Returns false and does nothing if [entry] is not in this linked list. + * + * This is equivalent to calling `entry.unlink()` if the entry is in this + * list. + */ + bool remove(E entry) { + if (entry._list != this) return false; + _unlink(entry); // Unlink will decrement length. + return true; + } + + Iterator get iterator => new _LinkedListIterator(this); + + int get length => _length; + + /** + * Remove all elements from this linked list. + */ + void clear() { + _modificationCount++; + if (isEmpty) return; + + E next = _first; + do { + E entry = next; + next = entry._next; + entry._next = entry._previous = entry._list = null; + } while (!identical(next, _first)); + + _first = null; + _length = 0; + } + + E get first { + if (isEmpty) { + throw new StateError('No such element'); + } + return _first; + } + + E get last { + if (isEmpty) { + throw new StateError('No such element'); + } + return _first._previous; + } + + E get single { + if (isEmpty) { + throw new StateError('No such element'); + } + if (_length > 1) { + throw new StateError('Too many elements'); + } + return _first; + } + + /** + * Call [action] with each entry in this linked list. + * + * It's an error if [action] modify the linked list. + */ + void forEach(void action(E entry)) { + int modificationCount = _modificationCount; + if (isEmpty) return; + + E current = _first; + do { + action(current); + if (modificationCount != _modificationCount) { + throw new ConcurrentModificationError(this); + } + current = current._next; + } while (!identical(current, _first)); + } + + bool get isEmpty => _length == 0; + + /// Inserts [newEntry] as last entry of the list. + /// + /// If [updateFirst] is true and [entry] is the first entry in the list, + /// updates the [_first] field to point to the [newEntry] as first entry. + void _insertBefore(E entry, E newEntry, {bool updateFirst}) { + if (newEntry.list != null) { + throw new StateError('LinkedListEntry is already in a LinkedList'); + } + _modificationCount++; + + newEntry._list = this; + if (isEmpty) { + assert(entry == null); + newEntry._previous = newEntry._next = newEntry; + _first = newEntry; + _length++; + return; + } + E predecessor = entry._previous; + E successor = entry; + newEntry._previous = predecessor; + newEntry._next = successor; + predecessor._next = newEntry; + successor._previous = newEntry; + if (updateFirst && identical(entry, _first)) { + _first = newEntry; + } + _length++; + } + + void _unlink(E entry) { + _modificationCount++; + entry._next._previous = entry._previous; + E next = entry._previous._next = entry._next; + _length--; + entry._list = entry._next = entry._previous = null; + if (isEmpty) { + _first = null; + } else if (identical(entry, _first)) { + _first = next; + } + } +} + +class _LinkedListIterator> implements Iterator { + final LinkedList _list; + final int _modificationCount; + E _current; + LinkedListEntry _next; + bool _visitedFirst; + + _LinkedListIterator(LinkedList list) + : _list = list, + _modificationCount = list._modificationCount, + _next = list._first, + _visitedFirst = false; + + E get current => _current; + + bool moveNext() { + if (_modificationCount != _list._modificationCount) { + throw new ConcurrentModificationError(this); + } + if (_list.isEmpty || (_visitedFirst && identical(_next, _list.first))) { + _current = null; + return false; + } + _visitedFirst = true; + _current = _next; + _next = _next._next; + return true; + } +} + +/** + * An object that can be an element in a [LinkedList]. + * + * All elements of a `LinkedList` must extend this class. + * The class provides the internal links that link elements together + * in the `LinkedList`, and a reference to the linked list itself + * that an element is currently part of. + * + * An entry can be in at most one linked list at a time. + * While an entry is in a linked list, the [list] property points to that + * linked list, and otherwise the `list` property is `null`. + * + * When created, an entry is not in any linked list. + */ +abstract class LinkedListEntry> { + LinkedList _list; + E _next; + E _previous; + + /** + * Get the linked list containing this element. + * + * Returns `null` if this entry is not currently in any list. + */ + LinkedList get list => _list; + + /** + * Unlink the element from its linked list. + * + * The entry must currently be in a linked list when this method is called. + */ + void unlink() { + _list._unlink(this); + } + + /** + * Return the successor of this element in its linked list. + * + * Returns `null` if there is no successor in the linked list, or if this + * entry is not currently in any list. + */ + E get next { + if (_list == null || identical(_list.first, _next)) return null; + return _next; + } + + /** + * Return the predecessor of this element in its linked list. + * + * Returns `null` if there is no predecessor in the linked list, or if this + * entry is not currently in any list. + */ + E get previous { + if (_list == null || identical(this, _list.first)) return null; + return _previous; + } + + /** + * Insert an element after this element in this element's linked list. + * + * This entry must be in a linked list when this method is called. + * The [entry] must not be in a linked list. + */ + void insertAfter(E entry) { + _list._insertBefore(_next, entry, updateFirst: false); + } + + /** + * Insert an element before this element in this element's linked list. + * + * This entry must be in a linked list when this method is called. + * The [entry] must not be in a linked list. + */ + void insertBefore(E entry) { + _list._insertBefore(this, entry, updateFirst: true); + } +} +'NN<PNDQNM +JPBNQJ%O&E (65062%*KL +5@0 :(///187'0 55+$4KL@!J6%& "$3-28+Q *6:3M7:EB)9J=5? 2@#.N>L)E@N)DIE/;JE/9Pfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/list.darto// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * Abstract implementation of a list. + * + * `ListBase` can be used as a base class for implementing the `List` interface. + * + * All operations are defined in terms of `length`, `operator[]`, + * `operator[]=` and `length=`, which need to be implemented. + * + * *NOTICE*: Forwarding just these four operations to a normal growable [List] + * (as created by `new List()`) will give very bad performance for `add` and + * `addAll` operations of `ListBase`. These operations are implemented by + * increasing the length of the list by one for each `add` operation, and + * repeatedly increasing the length of a growable list is not efficient. + * To avoid this, either override 'add' and 'addAll' to also forward directly + * to the growable list, or, preferably, use `DelegatingList` from + * "package:collection/wrappers.dart" instead. + */ +abstract class ListBase extends Object with ListMixin { + /** + * Convert a `List` to a string as `[each, element, as, string]`. + * + * Handles circular references where converting one of the elements + * to a string ends up converting [list] to a string again. + */ + static String listToString(List list) => + IterableBase.iterableToFullString(list, '[', ']'); +} + +/** + * Base implementation of a [List] class. + * + * `ListMixin` can be used as a mixin to make a class implement + * the `List` interface. + * + * This implements all read operations using only the `length` and + * `operator[]` members. It implements write operations using those and + * `length=` and `operator[]=` + * + * *NOTICE*: Forwarding just these four operations to a normal growable [List] + * (as created by `new List()`) will give very bad performance for `add` and + * `addAll` operations of `ListBase`. These operations are implemented by + * increasing the length of the list by one for each `add` operation, and + * repeatedly increasing the length of a growable list is not efficient. + * To avoid this, either override 'add' and 'addAll' to also forward directly + * to the growable list, or, if possible, use `DelegatingList` from + * "package:collection/wrappers.dart" instead. + */ +abstract class ListMixin implements List { + // Iterable interface. + // TODO(lrn): When we get composable mixins, reuse IterableMixin instead + // of redaclating everything. + Iterator get iterator => new ListIterator(this); + + E elementAt(int index) => this[index]; + + Iterable followedBy(Iterable other) => + new FollowedByIterable.firstEfficient(this, other); + + void forEach(void action(E element)) { + int length = this.length; + for (int i = 0; i < length; i++) { + action(this[i]); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + } + + bool get isEmpty => length == 0; + + bool get isNotEmpty => !isEmpty; + + E get first { + if (length == 0) throw IterableElementError.noElement(); + return this[0]; + } + + void set first(E value) { + if (length == 0) throw IterableElementError.noElement(); + this[0] = value; + } + + E get last { + if (length == 0) throw IterableElementError.noElement(); + return this[length - 1]; + } + + void set last(E value) { + if (length == 0) throw IterableElementError.noElement(); + this[length - 1] = value; + } + + E get single { + if (length == 0) throw IterableElementError.noElement(); + if (length > 1) throw IterableElementError.tooMany(); + return this[0]; + } + + bool contains(Object element) { + int length = this.length; + for (int i = 0; i < length; i++) { + if (this[i] == element) return true; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return false; + } + + bool every(bool test(E element)) { + int length = this.length; + for (int i = 0; i < length; i++) { + if (!test(this[i])) return false; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return true; + } + + bool any(bool test(E element)) { + int length = this.length; + for (int i = 0; i < length; i++) { + if (test(this[i])) return true; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return false; + } + + E firstWhere(bool test(E element), {E orElse()}) { + int length = this.length; + for (int i = 0; i < length; i++) { + E element = this[i]; + if (test(element)) return element; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E lastWhere(bool test(E element), {E orElse()}) { + int length = this.length; + for (int i = length - 1; i >= 0; i--) { + E element = this[i]; + if (test(element)) return element; + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E singleWhere(bool test(E element), {E orElse()}) { + int length = this.length; + E match = null; + bool matchFound = false; + for (int i = 0; i < length; i++) { + E element = this[i]; + if (test(element)) { + if (matchFound) { + throw IterableElementError.tooMany(); + } + matchFound = true; + match = element; + } + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + if (matchFound) return match; + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + String join([String separator = ""]) { + if (length == 0) return ""; + StringBuffer buffer = new StringBuffer()..writeAll(this, separator); + return buffer.toString(); + } + + Iterable where(bool test(E element)) => new WhereIterable(this, test); + + Iterable whereType() => new WhereTypeIterable(this); + + Iterable map(T f(E element)) => new MappedListIterable(this, f); + + Iterable expand(Iterable f(E element)) => + new ExpandIterable(this, f); + + E reduce(E combine(E previousValue, E element)) { + int length = this.length; + if (length == 0) throw IterableElementError.noElement(); + E value = this[0]; + for (int i = 1; i < length; i++) { + value = combine(value, this[i]); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return value; + } + + T fold(T initialValue, T combine(T previousValue, E element)) { + var value = initialValue; + int length = this.length; + for (int i = 0; i < length; i++) { + value = combine(value, this[i]); + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + return value; + } + + Iterable skip(int count) => new SubListIterable(this, count, null); + + Iterable skipWhile(bool test(E element)) { + return new SkipWhileIterable(this, test); + } + + Iterable take(int count) => new SubListIterable(this, 0, count); + + Iterable takeWhile(bool test(E element)) { + return new TakeWhileIterable(this, test); + } + + List toList({bool growable: true}) { + List result; + if (growable) { + result = []..length = length; + } else { + result = new List(length); + } + for (int i = 0; i < length; i++) { + result[i] = this[i]; + } + return result; + } + + Set toSet() { + Set result = new Set(); + for (int i = 0; i < length; i++) { + result.add(this[i]); + } + return result; + } + + // List interface. + void add(E element) { + this[this.length++] = element; + } + + void addAll(Iterable iterable) { + int i = this.length; + for (E element in iterable) { + assert(this.length == i || (throw new ConcurrentModificationError(this))); + this.length = i + 1; + this[i] = element; + i++; + } + } + + bool remove(Object element) { + for (int i = 0; i < this.length; i++) { + if (this[i] == element) { + this._closeGap(i, i + 1); + return true; + } + } + return false; + } + + /// Removes elements from the list starting at [start] up to but not including + /// [end]. Arguments are pre-validated. + void _closeGap(int start, int end) { + int length = this.length; + assert(0 <= start); + assert(start < end); + assert(end <= length); + int size = end - start; + for (int i = end; i < length; i++) { + this[i - size] = this[i]; + } + this.length = length - size; + } + + void removeWhere(bool test(E element)) { + _filter(test, false); + } + + void retainWhere(bool test(E element)) { + _filter(test, true); + } + + void _filter(bool test(E element), bool retainMatching) { + List retained = []; + int length = this.length; + for (int i = 0; i < length; i++) { + var element = this[i]; + if (test(element) == retainMatching) { + retained.add(element); + } + if (length != this.length) { + throw new ConcurrentModificationError(this); + } + } + if (retained.length != this.length) { + this.setRange(0, retained.length, retained); + this.length = retained.length; + } + } + + void clear() { + this.length = 0; + } + + List cast() => List.castFrom(this); + E removeLast() { + if (length == 0) { + throw IterableElementError.noElement(); + } + E result = this[length - 1]; + length--; + return result; + } + + void sort([int compare(E a, E b)]) { + Sort.sort(this, compare ?? _compareAny); + } + + static int _compareAny(a, b) { + // In strong mode Comparable.compare requires an implicit cast to ensure + // `a` and `b` are Comparable. + return Comparable.compare(a, b); + } + + void shuffle([Random random]) { + if (random == null) random = new Random(); + int length = this.length; + while (length > 1) { + int pos = random.nextInt(length); + length -= 1; + var tmp = this[length]; + this[length] = this[pos]; + this[pos] = tmp; + } + } + + Map asMap() { + return new ListMapView(this); + } + + List operator +(List other) { + var result = []..length = (this.length + other.length); + result.setRange(0, this.length, this); + result.setRange(this.length, result.length, other); + return result; + } + + List sublist(int start, [int end]) { + int listLength = this.length; + if (end == null) end = listLength; + RangeError.checkValidRange(start, end, listLength); + int length = end - start; + List result = []..length = length; + for (int i = 0; i < length; i++) { + result[i] = this[start + i]; + } + return result; + } + + Iterable getRange(int start, int end) { + RangeError.checkValidRange(start, end, this.length); + return new SubListIterable(this, start, end); + } + + void removeRange(int start, int end) { + RangeError.checkValidRange(start, end, this.length); + if (end > start) { + _closeGap(start, end); + } + } + + void fillRange(int start, int end, [E fill]) { + RangeError.checkValidRange(start, end, this.length); + for (int i = start; i < end; i++) { + this[i] = fill; + } + } + + void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { + RangeError.checkValidRange(start, end, this.length); + int length = end - start; + if (length == 0) return; + RangeError.checkNotNegative(skipCount, "skipCount"); + + List otherList; + int otherStart; + // TODO(floitsch): Make this accept more. + if (iterable is List) { + otherList = iterable; + otherStart = skipCount; + } else { + otherList = iterable.skip(skipCount).toList(growable: false); + otherStart = 0; + } + if (otherStart + length > otherList.length) { + throw IterableElementError.tooFew(); + } + if (otherStart < start) { + // Copy backwards to ensure correct copy if [from] is this. + for (int i = length - 1; i >= 0; i--) { + this[start + i] = otherList[otherStart + i]; + } + } else { + for (int i = 0; i < length; i++) { + this[start + i] = otherList[otherStart + i]; + } + } + } + + void replaceRange(int start, int end, Iterable newContents) { + RangeError.checkValidRange(start, end, this.length); + if (newContents is! EfficientLengthIterable) { + newContents = newContents.toList(); + } + int removeLength = end - start; + int insertLength = newContents.length; + if (removeLength >= insertLength) { + int insertEnd = start + insertLength; + this.setRange(start, insertEnd, newContents); + if (removeLength > insertLength) { + _closeGap(insertEnd, end); + } + } else { + int delta = insertLength - removeLength; + int newLength = this.length + delta; + int insertEnd = start + insertLength; // aka. end + delta. + this.length = newLength; + this.setRange(insertEnd, newLength, this, end); + this.setRange(start, insertEnd, newContents); + } + } + + int indexOf(Object element, [int start = 0]) { + if (start < 0) start = 0; + for (int i = start; i < this.length; i++) { + if (this[i] == element) return i; + } + return -1; + } + + int indexWhere(bool test(E element), [int start = 0]) { + if (start < 0) start = 0; + for (int i = start; i < this.length; i++) { + if (test(this[i])) return i; + } + return -1; + } + + int lastIndexOf(Object element, [int start]) { + if (start == null || start >= this.length) start = this.length - 1; + for (int i = start; i >= 0; i--) { + if (this[i] == element) return i; + } + return -1; + } + + int lastIndexWhere(bool test(E element), [int start]) { + if (start == null || start >= this.length) start = this.length - 1; + for (int i = start; i >= 0; i--) { + if (test(this[i])) return i; + } + return -1; + } + + void insert(int index, E element) { + RangeError.checkValueInInterval(index, 0, length, "index"); + if (index == this.length) { + add(element); + return; + } + // We are modifying the length just below the is-check. Without the check + // Array.copy could throw an exception, leaving the list in a bad state + // (with a length that has been increased, but without a new element). + if (index is! int) throw new ArgumentError(index); + this.length++; + setRange(index + 1, this.length, this, index); + this[index] = element; + } + + E removeAt(int index) { + E result = this[index]; + _closeGap(index, index + 1); + return result; + } + + void insertAll(int index, Iterable iterable) { + RangeError.checkValueInInterval(index, 0, length, "index"); + if (iterable is! EfficientLengthIterable || identical(iterable, this)) { + iterable = iterable.toList(); + } + int insertionLength = iterable.length; + // There might be errors after the length change, in which case the list + // will end up being modified but the operation not complete. Unless we + // always go through a "toList" we can't really avoid that. + this.length += insertionLength; + if (iterable.length != insertionLength) { + // If the iterable's length is linked to this list's length somehow, + // we can't insert one in the other. + this.length -= insertionLength; + throw new ConcurrentModificationError(iterable); + } + setRange(index + insertionLength, this.length, this, index); + setAll(index, iterable); + } + + void setAll(int index, Iterable iterable) { + if (iterable is List) { + setRange(index, index + iterable.length, iterable); + } else { + for (E element in iterable) { + this[index++] = element; + } + } + } + + Iterable get reversed => new ReversedListIterable(this); + + String toString() => IterableBase.iterableToFullString(this, '[', ']'); +} + NN<&QB>OMJJINC/>DF>+9*@CHOMJJIND/1K 9)/=)'#5##=====:"'+#5%'(#5#'5')#5),4,)#5),6'0 +#5"),) IO@O5)4=''#5E''#5L01I01*' $'"'#&"Q  , "Q+') !++<'-#5*3%2.!'-!M#%"/( %&?+8*"'8-'#-95)919(Q99. D2+B.5 )5C93*$+(,4)# /+A6410(:0#1H'(:H'#&@ NLK73!4@M$+ML@$.K+&7A1: $!AJPfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/maps.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.collection; + +/** + * Base class for implementing a [Map]. + * + * This class has a basic implementation of all but five of the members of + * [Map]. + * A basic `Map` class can be implemented by extending this class and + * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. + * The remaining operations are implemented in terms of these five. + * + * The `keys` iterable should have efficient [Iterable.length] and + * [Iterable.contains] operations, and it should catch concurrent modifications + * of the keys while iterating. + * + * A more efficient implementation is usually possible by overriding + * some of the other members as well. + */ +abstract class MapBase extends MapMixin { + static String mapToString(Map m) { + // Reuses the list in IterableBase for detecting toString cycles. + if (_isToStringVisiting(m)) { + return '{...}'; + } + + var result = new StringBuffer(); + try { + _toStringVisiting.add(m); + result.write('{'); + bool first = true; + m.forEach((k, v) { + if (!first) { + result.write(', '); + } + first = false; + result.write(k); + result.write(': '); + result.write(v); + }); + result.write('}'); + } finally { + assert(identical(_toStringVisiting.last, m)); + _toStringVisiting.removeLast(); + } + + return result.toString(); + } + + static _id(x) => x; + + /** + * Fills a [Map] with key/value pairs computed from [iterable]. + * + * This method is used by [Map] classes in the named constructor + * `fromIterable`. + */ + static void _fillMapWithMappedIterable( + Map map, Iterable iterable, key(element), value(element)) { + key ??= _id; + value ??= _id; + + for (var element in iterable) { + map[key(element)] = value(element); + } + } + + /** + * Fills a map by associating the [keys] to [values]. + * + * This method is used by [Map] classes in the named constructor + * `fromIterables`. + */ + static void _fillMapWithIterables(Map map, Iterable keys, Iterable values) { + Iterator keyIterator = keys.iterator; + Iterator valueIterator = values.iterator; + + bool hasNextKey = keyIterator.moveNext(); + bool hasNextValue = valueIterator.moveNext(); + + while (hasNextKey && hasNextValue) { + map[keyIterator.current] = valueIterator.current; + hasNextKey = keyIterator.moveNext(); + hasNextValue = valueIterator.moveNext(); + } + + if (hasNextKey || hasNextValue) { + throw new ArgumentError("Iterables do not have same length."); + } + } +} + +/** + * Mixin implementing a [Map]. + * + * This mixin has a basic implementation of all but five of the members of + * [Map]. + * A basic `Map` class can be implemented by mixin in this class and + * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. + * The remaining operations are implemented in terms of these five. + * + * The `keys` iterable should have efficient [Iterable.length] and + * [Iterable.contains] operations, and it should catch concurrent modifications + * of the keys while iterating. + * + * A more efficient implementation is usually possible by overriding + * some of the other members as well. + */ +abstract class MapMixin implements Map { + Iterable get keys; + V operator [](Object key); + operator []=(K key, V value); + V remove(Object key); + // The `clear` operation should not be based on `remove`. + // It should clear the map even if some keys are not equal to themselves. + void clear(); + + Map cast() => Map.castFrom(this); + void forEach(void action(K key, V value)) { + for (K key in keys) { + action(key, this[key]); + } + } + + void addAll(Map other) { + for (K key in other.keys) { + this[key] = other[key]; + } + } + + bool containsValue(Object value) { + for (K key in keys) { + if (this[key] == value) return true; + } + return false; + } + + V putIfAbsent(K key, V ifAbsent()) { + if (containsKey(key)) { + return this[key]; + } + return this[key] = ifAbsent(); + } + + V update(K key, V update(V value), {V ifAbsent()}) { + if (this.containsKey(key)) { + return this[key] = update(this[key]); + } + if (ifAbsent != null) { + return this[key] = ifAbsent(); + } + throw new ArgumentError.value(key, "key", "Key not in map."); + } + + void updateAll(V update(K key, V value)) { + for (var key in this.keys) { + this[key] = update(key, this[key]); + } + } + + Iterable> get entries { + return keys.map((K key) => new MapEntry(key, this[key])); + } + + Map map(MapEntry transform(K key, V value)) { + var result = {}; + for (var key in this.keys) { + var entry = transform(key, this[key]); + result[entry.key] = entry.value; + } + return result; + } + + void addEntries(Iterable> newEntries) { + for (var entry in newEntries) { + this[entry.key] = entry.value; + } + } + + void removeWhere(bool test(K key, V value)) { + var keysToRemove = []; + for (var key in keys) { + if (test(key, this[key])) keysToRemove.add(key); + } + for (var key in keysToRemove) { + this.remove(key); + } + } + + bool containsKey(Object key) => keys.contains(key); + int get length => keys.length; + bool get isEmpty => keys.isEmpty; + bool get isNotEmpty => keys.isNotEmpty; + Iterable get values => new _MapBaseValueIterable(this); + String toString() => MapBase.mapToString(this); +} + +/** + * Basic implementation of an unmodifiable [Map]. + * + * This class has a basic implementation of all but two of the members of + * an umodifiable [Map]. + * A simple unmodifiable `Map` class can be implemented by extending this + * class and implementing `keys` and `operator[]`. + * + * Modifying operations throw when used. + * The remaining non-modifying operations are implemented in terms of `keys` + * and `operator[]`. + * + * The `keys` iterable should have efficient [Iterable.length] and + * [Iterable.contains] operations, and it should catch concurrent modifications + * of the keys while iterating. + * + * A more efficient implementation is usually possible by overriding + * some of the other members as well. + */ +abstract class UnmodifiableMapBase = MapBase + with _UnmodifiableMapMixin; + +/** + * Implementation of [Map.values] based on the map and its [Map.keys] iterable. + * + * Iterable that iterates over the values of a `Map`. + * It accesses the values by iterating over the keys of the map, and using the + * map's `operator[]` to lookup the keys. + */ +class _MapBaseValueIterable extends EfficientLengthIterable { + final Map _map; + _MapBaseValueIterable(this._map); + + int get length => _map.length; + bool get isEmpty => _map.isEmpty; + bool get isNotEmpty => _map.isNotEmpty; + V get first => _map[_map.keys.first]; + V get single => _map[_map.keys.single]; + V get last => _map[_map.keys.last]; + + Iterator get iterator => new _MapBaseValueIterator(_map); +} + +/** + * Iterator created by [_MapBaseValueIterable]. + * + * Iterates over the values of a map by iterating its keys and lookup up the + * values. + */ +class _MapBaseValueIterator implements Iterator { + final Iterator _keys; + final Map _map; + V _current = null; + + _MapBaseValueIterator(Map map) + : _map = map, + _keys = map.keys.iterator; + + bool moveNext() { + if (_keys.moveNext()) { + _current = _map[_keys.current]; + return true; + } + _current = null; + return false; + } + + V get current => _current; +} + +/** + * Mixin that overrides mutating map operations with implementations that throw. + */ +abstract class _UnmodifiableMapMixin implements Map { + /** This operation is not supported by an unmodifiable map. */ + void operator []=(K key, V value) { + throw new UnsupportedError("Cannot modify unmodifiable map"); + } + + /** This operation is not supported by an unmodifiable map. */ + void addAll(Map other) { + throw new UnsupportedError("Cannot modify unmodifiable map"); + } + + /** This operation is not supported by an unmodifiable map. */ + void clear() { + throw new UnsupportedError("Cannot modify unmodifiable map"); + } + + /** This operation is not supported by an unmodifiable map. */ + V remove(Object key) { + throw new UnsupportedError("Cannot modify unmodifiable map"); + } + + /** This operation is not supported by an unmodifiable map. */ + V putIfAbsent(K key, V ifAbsent()) { + throw new UnsupportedError("Cannot modify unmodifiable map"); + } +} + +/** + * Wrapper around a class that implements [Map] that only exposes `Map` members. + * + * A simple wrapper that delegates all `Map` members to the map provided in the + * constructor. + * + * Base for delegating map implementations like [UnmodifiableMapView]. + */ +class MapView implements Map { + final Map _map; + const MapView(Map map) : _map = map; + + Map cast() => _map.cast(); + V operator [](Object key) => _map[key]; + void operator []=(K key, V value) { + _map[key] = value; + } + + void addAll(Map other) { + _map.addAll(other); + } + + void clear() { + _map.clear(); + } + + V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent); + bool containsKey(Object key) => _map.containsKey(key); + bool containsValue(Object value) => _map.containsValue(value); + void forEach(void action(K key, V value)) { + _map.forEach(action); + } + + bool get isEmpty => _map.isEmpty; + bool get isNotEmpty => _map.isNotEmpty; + int get length => _map.length; + Iterable get keys => _map.keys; + V remove(Object key) => _map.remove(key); + String toString() => _map.toString(); + Iterable get values => _map.values; + + Iterable> get entries => _map.entries; + + void addEntries(Iterable entries) { + _map.addEntries(entries); + } + + Map map(MapEntry transform(K key, V value)) => + _map.map(transform); + + V update(K key, V update(V value), {V ifAbsent()}) => + _map.update(key, update, ifAbsent: ifAbsent); + + void updateAll(V update(K key, V value)) { + _map.updateAll(update); + } + + void removeWhere(bool test(K key, V value)) { + _map.removeWhere(test); + } +} + +/** + * View of a [Map] that disallow modifying the map. + * + * A wrapper around a `Map` that forwards all members to the map provided in + * the constructor, except for operations that modify the map. + * Modifying operations throw instead. + */ +class UnmodifiableMapView extends MapView + with _UnmodifiableMapMixin { + UnmodifiableMapView(Map map) : super(map); + + Map cast() => + new UnmodifiableMapView(_map.cast()); +} +zNN<(K +FKDCP E&6%F"% +  + +4&BC*B$*8CO*..2)8+/&EK +EKDCP E&5  implements EfficientLengthIterable { + /** + * Creates a queue. + */ + factory Queue() = ListQueue; + + /** + * Creates a queue containing all [elements]. + * + * The element order in the queue is as if the elements were added using + * [addLast] in the order provided by [elements.iterator]. + * + * All the [elements] should be instances of [E]. + * The `elements` iterable itself may have any element type, so this + * constructor can be used to down-cast a `Queue`, for example as: + * ```dart + * Queue superQueue = ...; + * Queue subQueue = + * new Queue.from(superSet.whereType()); + * ``` + */ + factory Queue.from(Iterable elements) = ListQueue.from; + + /** + * Creates a queue from [elements]. + * + * The element order in the queue is as if the elements were added using + * [addLast] in the order provided by [elements.iterator]. + */ + factory Queue.of(Iterable elements) = ListQueue.of; + + /** + * Adapts [source] to be a `Queue`. + * + * Any time the queue would produce an element that is not a [T], + * the element access will throw. + * + * Any time a [T] value is attempted stored into the adapted queue, + * the store will throw unless the value is also an instance of [S]. + * + * If all accessed elements of [source] are actually instances of [T], + * and if all elements stored into the returned queue are actually instance + * of [S], + * then the returned queue can be used as a `Queue`. + */ + static Queue castFrom(Queue source) => + new CastQueue(source); + + /** + * Provides a view of this queue as a queue of [R] instances, if necessary. + * + * If this queue contains only instances of [R], all read operations + * will work correctly. If any operation tries to access an element + * that is not an instance of [R], the access will throw instead. + * + * Elements added to the queue (e.g., by using [addFirst] or [addAll]) + * must be instance of [R] to be valid arguments to the adding function, + * and they must be instances of [E] as well to be accepted by + * this queue as well. + */ + Queue cast(); + /** + * Removes and returns the first element of this queue. + * + * The queue must not be empty when this method is called. + */ + E removeFirst(); + + /** + * Removes and returns the last element of the queue. + * + * The queue must not be empty when this method is called. + */ + E removeLast(); + + /** + * Adds [value] at the beginning of the queue. + */ + void addFirst(E value); + + /** + * Adds [value] at the end of the queue. + */ + void addLast(E value); + + /** + * Adds [value] at the end of the queue. + */ + void add(E value); + + /** + * Remove a single instance of [value] from the queue. + * + * Returns `true` if a value was removed, or `false` if the queue + * contained no element equal to [value]. + */ + bool remove(Object value); + + /** + * Adds all elements of [iterable] at the end of the queue. The + * length of the queue is extended by the length of [iterable]. + */ + void addAll(Iterable iterable); + + /** + * Removes all elements matched by [test] from the queue. + * + * The `test` function must not throw or modify the queue. + */ + void removeWhere(bool test(E element)); + + /** + * Removes all elements not matched by [test] from the queue. + * + * The `test` function must not throw or modify the queue. + */ + void retainWhere(bool test(E element)); + + /** + * Removes all elements in the queue. The size of the queue becomes zero. + */ + void clear(); +} + +class _DoubleLink> { + Link _previousLink; + Link _nextLink; + + void _link(Link previous, Link next) { + _nextLink = next; + _previousLink = previous; + if (previous != null) previous._nextLink = this; + if (next != null) next._previousLink = this; + } + + void _unlink() { + if (_previousLink != null) _previousLink._nextLink = _nextLink; + if (_nextLink != null) _nextLink._previousLink = _previousLink; + _nextLink = null; + _previousLink = null; + } +} + +/** + * An entry in a doubly linked list. It contains a pointer to the next + * entry, the previous entry, and the boxed element. + */ +class DoubleLinkedQueueEntry extends _DoubleLink> { + /// The element in the queue. + E element; + + DoubleLinkedQueueEntry(this.element); + + /// Appends the given [e] as entry just after this entry. + void append(E e) { + new DoubleLinkedQueueEntry(e)._link(this, _nextLink); + } + + /// Prepends the given [e] as entry just before this entry. + void prepend(E e) { + new DoubleLinkedQueueEntry(e)._link(_previousLink, this); + } + + E remove() { + _unlink(); + return element; + } + + /// Returns the previous entry or `null` if there is none. + DoubleLinkedQueueEntry previousEntry() => _previousLink; + + /// Returns the next entry or `null` if there is none. + DoubleLinkedQueueEntry nextEntry() => _nextLink; +} + +/** + * Interface for the link classes used by [DoubleLinkedQueue]. + * + * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] + * implement this interface. + * The entry contains a link back to the queue, so calling `append` + * or `prepend` can correctly update the element count. + */ +abstract class _DoubleLinkedQueueEntry extends DoubleLinkedQueueEntry { + DoubleLinkedQueue _queue; + _DoubleLinkedQueueEntry(E element, this._queue) : super(element); + + DoubleLinkedQueueEntry _asNonSentinelEntry(); + + void _append(E e) { + new _DoubleLinkedQueueElement(e, _queue)._link(this, _nextLink); + } + + void _prepend(E e) { + new _DoubleLinkedQueueElement(e, _queue)._link(_previousLink, this); + } + + E _remove(); + + E get _element => element; + + DoubleLinkedQueueEntry nextEntry() { + _DoubleLinkedQueueEntry entry = _nextLink; + return entry._asNonSentinelEntry(); + } + + DoubleLinkedQueueEntry previousEntry() { + _DoubleLinkedQueueEntry entry = _previousLink; + return entry._asNonSentinelEntry(); + } +} + +/** + * The actual entry type used by the [DoubleLinkedQueue]. + * + * The entry contains a reference to the queue, allowing + * [append]/[prepend] to update the list length. + */ +class _DoubleLinkedQueueElement extends _DoubleLinkedQueueEntry { + _DoubleLinkedQueueElement(E element, DoubleLinkedQueue queue) + : super(element, queue); + + void append(E e) { + _append(e); + if (_queue != null) _queue._elementCount++; + } + + void prepend(E e) { + _prepend(e); + if (_queue != null) _queue._elementCount++; + } + + E _remove() { + _queue = null; + _unlink(); + return element; + } + + E remove() { + if (_queue != null) _queue._elementCount--; + return _remove(); + } + + _DoubleLinkedQueueElement _asNonSentinelEntry() { + return this; + } +} + +/** + * A sentinel in a double linked list is used to manipulate the list + * at both ends. + * A double linked list has exactly one sentinel, + * which is the only entry when the list is constructed. + * Initially, a sentinel has its next and previous entry point to itself. + * A sentinel does not box any user element. + */ +class _DoubleLinkedQueueSentinel extends _DoubleLinkedQueueEntry { + _DoubleLinkedQueueSentinel(DoubleLinkedQueue queue) : super(null, queue) { + _previousLink = this; + _nextLink = this; + } + + DoubleLinkedQueueEntry _asNonSentinelEntry() { + return null; + } + + /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ + E _remove() { + throw IterableElementError.noElement(); + } + + /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ + E get _element { + throw IterableElementError.noElement(); + } +} + +/** + * A [Queue] implementation based on a double-linked list. + * + * Allows constant time add, remove-at-ends and peek operations. + */ +class DoubleLinkedQueue extends Iterable implements Queue { + _DoubleLinkedQueueSentinel _sentinel; + int _elementCount = 0; + + DoubleLinkedQueue() { + _sentinel = new _DoubleLinkedQueueSentinel(this); + } + + /** + * Creates a double-linked queue containing all [elements]. + * + * The element order in the queue is as if the elements were added using + * [addLast] in the order provided by [elements.iterator]. + * + * All the [elements] should be instances of [E]. + * The `elements` iterable itself may have any element type, so this + * constructor can be used to down-cast a `Queue`, for example as: + * ```dart + * Queue superQueue = ...; + * Queue subQueue = + * new DoubleLinkedQueue.from(superQueue.whereType()); + * ``` + */ + factory DoubleLinkedQueue.from(Iterable elements) { + Queue list = new DoubleLinkedQueue(); + for (final e in elements) { + list.addLast(e); + } + return list; + } + + /** + * Creates a double-linked queue from [elements]. + * + * The element order in the queue is as if the elements were added using + * [addLast] in the order provided by [elements.iterator]. + */ + factory DoubleLinkedQueue.of(Iterable elements) => + new DoubleLinkedQueue()..addAll(elements); + + Queue cast() => Queue.castFrom(this); + int get length => _elementCount; + + void addLast(E value) { + _sentinel._prepend(value); + _elementCount++; + } + + void addFirst(E value) { + _sentinel._append(value); + _elementCount++; + } + + void add(E value) { + _sentinel._prepend(value); + _elementCount++; + } + + void addAll(Iterable iterable) { + for (final E value in iterable) { + _sentinel._prepend(value); + _elementCount++; + } + } + + E removeLast() { + _DoubleLinkedQueueEntry lastEntry = _sentinel._previousLink; + E result = lastEntry._remove(); + _elementCount--; + return result; + } + + E removeFirst() { + _DoubleLinkedQueueEntry firstEntry = _sentinel._nextLink; + E result = firstEntry._remove(); + _elementCount--; + return result; + } + + bool remove(Object o) { + _DoubleLinkedQueueEntry entry = _sentinel._nextLink; + while (!identical(entry, _sentinel)) { + bool equals = (entry._element == o); + if (!identical(this, entry._queue)) { + // Entry must still be in the queue. + throw new ConcurrentModificationError(this); + } + if (equals) { + entry._remove(); + _elementCount--; + return true; + } + entry = entry._nextLink; + } + return false; + } + + void _filter(bool test(E element), bool removeMatching) { + _DoubleLinkedQueueEntry entry = _sentinel._nextLink; + while (!identical(entry, _sentinel)) { + bool matches = test(entry._element); + if (!identical(this, entry._queue)) { + // Entry must still be in the queue. + throw new ConcurrentModificationError(this); + } + _DoubleLinkedQueueEntry next = entry._nextLink; // Cannot be null. + if (identical(removeMatching, matches)) { + entry._remove(); + _elementCount--; + } + entry = next; + } + } + + void removeWhere(bool test(E element)) { + _filter(test, true); + } + + void retainWhere(bool test(E element)) { + _filter(test, false); + } + + E get first { + _DoubleLinkedQueueEntry firstEntry = _sentinel._nextLink; + return firstEntry._element; + } + + E get last { + _DoubleLinkedQueueEntry lastEntry = _sentinel._previousLink; + return lastEntry._element; + } + + E get single { + // Note that this throws correctly if the queue is empty + // because reading the element of the sentinel throws. + if (identical(_sentinel._nextLink, _sentinel._previousLink)) { + _DoubleLinkedQueueEntry entry = _sentinel._nextLink; + return entry._element; + } + throw IterableElementError.tooMany(); + } + + /** + * The entry object of the first element in the queue. + * + * Each element of the queue has an associated [DoubleLinkedQueueEntry]. + * Returns the entry object corresponding to the first element of the queue. + * + * The entry objects can also be accessed using [lastEntry], + * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and + * [DoubleLinkedQueueEntry.previousEntry()]. + */ + DoubleLinkedQueueEntry firstEntry() { + return _sentinel.nextEntry(); + } + + /** + * The entry object of the last element in the queue. + * + * Each element of the queue has an associated [DoubleLinkedQueueEntry]. + * Returns the entry object corresponding to the last element of the queue. + * + * The entry objects can also be accessed using [firstEntry], + * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and + * [DoubleLinkedQueueEntry.previousEntry()]. + */ + DoubleLinkedQueueEntry lastEntry() { + return _sentinel.previousEntry(); + } + + bool get isEmpty { + return (identical(_sentinel._nextLink, _sentinel)); + } + + void clear() { + _sentinel._nextLink = _sentinel; + _sentinel._previousLink = _sentinel; + _elementCount = 0; + } + + /** + * Calls [action] for each entry object of this double-linked queue. + * + * Each element of the queue has an associated [DoubleLinkedQueueEntry]. + * This method iterates the entry objects from first to last and calls + * [action] with each object in turn. + * + * The entry objects can also be accessed using [firstEntry] and [lastEntry], + * and iterated using [DoubleLinkedQueueEntry.nextEntry()] and + * [DoubleLinkedQueueEntry.previousEntry()]. + * + * The [action] function can use methods on [DoubleLinkedQueueEntry] to remove + * the entry or it can insert elements before or after then entry. + * If the current entry is removed, iteration continues with the entry that + * was following the current entry when [action] was called. Any elements + * inserted after the current element before it is removed will not be + * visited by the iteration. + */ + void forEachEntry(void action(DoubleLinkedQueueEntry element)) { + _DoubleLinkedQueueEntry entry = _sentinel._nextLink; + while (!identical(entry, _sentinel)) { + _DoubleLinkedQueueElement element = entry; + _DoubleLinkedQueueEntry next = element._nextLink; + // Remember both entry and entry._nextLink. + // If someone calls `element.remove()` we continue from `next`. + // Otherwise we use the value of entry._nextLink which may have been + // updated. + action(element); + if (identical(this, entry._queue)) { + next = entry._nextLink; + } else if (!identical(this, next._queue)) { + throw new ConcurrentModificationError(this); + } + entry = next; + } + } + + _DoubleLinkedQueueIterator get iterator { + return new _DoubleLinkedQueueIterator(_sentinel); + } + + String toString() => IterableBase.iterableToFullString(this, '{', '}'); +} + +class _DoubleLinkedQueueIterator implements Iterator { + _DoubleLinkedQueueSentinel _sentinel; + _DoubleLinkedQueueEntry _nextEntry = null; + E _current; + + _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel sentinel) + : _sentinel = sentinel, + _nextEntry = sentinel._nextLink; + + bool moveNext() { + if (identical(_nextEntry, _sentinel)) { + _current = null; + _nextEntry = null; + _sentinel = null; + return false; + } + _DoubleLinkedQueueElement elementEntry = _nextEntry; + if (!identical(_sentinel._queue, elementEntry._queue)) { + throw new ConcurrentModificationError(_sentinel._queue); + } + _current = elementEntry._element; + _nextEntry = elementEntry._nextLink; + return true; + } + + E get current => _current; +} + +/** + * List based [Queue]. + * + * Keeps a cyclic buffer of elements, and grows to a larger buffer when + * it fills up. This guarantees constant time peek and remove operations, and + * amortized constant time add operations. + * + * The structure is efficient for any queue or stack usage. + */ +class ListQueue extends ListIterable implements Queue { + static const int _INITIAL_CAPACITY = 8; + List _table; + int _head; + int _tail; + int _modificationCount = 0; + + /** + * Create an empty queue. + * + * If [initialCapacity] is given, prepare the queue for at least that many + * elements. + */ + ListQueue([int initialCapacity]) + : _head = 0, + _tail = 0 { + if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) { + initialCapacity = _INITIAL_CAPACITY; + } else if (!_isPowerOf2(initialCapacity)) { + initialCapacity = _nextPowerOf2(initialCapacity); + } + assert(_isPowerOf2(initialCapacity)); + _table = new List(initialCapacity); + } + + /** + * Create a `ListQueue` containing all [elements]. + * + * The elements are added to the queue, as by [addLast], in the order given by + * `elements.iterator`. + * + * All the [elements] should be instances of [E]. + * The `elements` iterable itself may have any element type, so this + * constructor can be used to down-cast a `Queue`, for example as: + * ```dart + * Queue superQueue = ...; + * Queue subQueue = + * new ListQueue.from(superQueue.whereType()); + * ``` + */ + factory ListQueue.from(Iterable elements) { + if (elements is List) { + int length = elements.length; + ListQueue queue = new ListQueue(length + 1); + assert(queue._table.length > length); + for (int i = 0; i < length; i++) { + queue._table[i] = elements[i]; + } + queue._tail = length; + return queue; + } else { + int capacity = _INITIAL_CAPACITY; + if (elements is EfficientLengthIterable) { + capacity = elements.length; + } + ListQueue result = new ListQueue(capacity); + for (final element in elements) { + result.addLast(element); + } + return result; + } + } + + /** + * Create a `ListQueue` from [elements]. + * + * The elements are added to the queue, as by [addLast], in the order given by + * `elements.iterator`. + */ + factory ListQueue.of(Iterable elements) => + new ListQueue()..addAll(elements); + + // Iterable interface. + + Queue cast() => Queue.castFrom(this); + Iterator get iterator => new _ListQueueIterator(this); + + void forEach(void f(E element)) { + int modificationCount = _modificationCount; + for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { + f(_table[i]); + _checkModification(modificationCount); + } + } + + bool get isEmpty => _head == _tail; + + int get length => (_tail - _head) & (_table.length - 1); + + E get first { + if (_head == _tail) throw IterableElementError.noElement(); + return _table[_head]; + } + + E get last { + if (_head == _tail) throw IterableElementError.noElement(); + return _table[(_tail - 1) & (_table.length - 1)]; + } + + E get single { + if (_head == _tail) throw IterableElementError.noElement(); + if (length > 1) throw IterableElementError.tooMany(); + return _table[_head]; + } + + E elementAt(int index) { + RangeError.checkValidIndex(index, this); + return _table[(_head + index) & (_table.length - 1)]; + } + + List toList({bool growable: true}) { + List list; + if (growable) { + list = []..length = length; + } else { + list = new List(length); + } + _writeToList(list); + return list; + } + + // Collection interface. + + void add(E value) { + _add(value); + } + + void addAll(Iterable elements) { + if (elements is List) { + List list = elements; + int addCount = list.length; + int length = this.length; + if (length + addCount >= _table.length) { + _preGrow(length + addCount); + // After preGrow, all elements are at the start of the list. + _table.setRange(length, length + addCount, list, 0); + _tail += addCount; + } else { + // Adding addCount elements won't reach _head. + int endSpace = _table.length - _tail; + if (addCount < endSpace) { + _table.setRange(_tail, _tail + addCount, list, 0); + _tail += addCount; + } else { + int preSpace = addCount - endSpace; + _table.setRange(_tail, _tail + endSpace, list, 0); + _table.setRange(0, preSpace, list, endSpace); + _tail = preSpace; + } + } + _modificationCount++; + } else { + for (E element in elements) _add(element); + } + } + + bool remove(Object value) { + for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { + E element = _table[i]; + if (element == value) { + _remove(i); + _modificationCount++; + return true; + } + } + return false; + } + + void _filterWhere(bool test(E element), bool removeMatching) { + int modificationCount = _modificationCount; + int i = _head; + while (i != _tail) { + E element = _table[i]; + bool remove = identical(removeMatching, test(element)); + _checkModification(modificationCount); + if (remove) { + i = _remove(i); + modificationCount = ++_modificationCount; + } else { + i = (i + 1) & (_table.length - 1); + } + } + } + + /** + * Remove all elements matched by [test]. + * + * This method is inefficient since it works by repeatedly removing single + * elements, each of which can take linear time. + */ + void removeWhere(bool test(E element)) { + _filterWhere(test, true); + } + + /** + * Remove all elements not matched by [test]. + * + * This method is inefficient since it works by repeatedly removing single + * elements, each of which can take linear time. + */ + void retainWhere(bool test(E element)) { + _filterWhere(test, false); + } + + void clear() { + if (_head != _tail) { + for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { + _table[i] = null; + } + _head = _tail = 0; + _modificationCount++; + } + } + + String toString() => IterableBase.iterableToFullString(this, "{", "}"); + + // Queue interface. + + void addLast(E value) { + _add(value); + } + + void addFirst(E value) { + _head = (_head - 1) & (_table.length - 1); + _table[_head] = value; + if (_head == _tail) _grow(); + _modificationCount++; + } + + E removeFirst() { + if (_head == _tail) throw IterableElementError.noElement(); + _modificationCount++; + E result = _table[_head]; + _table[_head] = null; + _head = (_head + 1) & (_table.length - 1); + return result; + } + + E removeLast() { + if (_head == _tail) throw IterableElementError.noElement(); + _modificationCount++; + _tail = (_tail - 1) & (_table.length - 1); + E result = _table[_tail]; + _table[_tail] = null; + return result; + } + + // Internal helper functions. + + /** + * Whether [number] is a power of two. + * + * Only works for positive numbers. + */ + static bool _isPowerOf2(int number) => (number & (number - 1)) == 0; + + /** + * Rounds [number] up to the nearest power of 2. + * + * If [number] is a power of 2 already, it is returned. + * + * Only works for positive numbers. + */ + static int _nextPowerOf2(int number) { + assert(number > 0); + number = (number << 1) - 1; + for (;;) { + int nextNumber = number & (number - 1); + if (nextNumber == 0) return number; + number = nextNumber; + } + } + + /** Check if the queue has been modified during iteration. */ + void _checkModification(int expectedModificationCount) { + if (expectedModificationCount != _modificationCount) { + throw new ConcurrentModificationError(this); + } + } + + /** Adds element at end of queue. Used by both [add] and [addAll]. */ + void _add(E element) { + _table[_tail] = element; + _tail = (_tail + 1) & (_table.length - 1); + if (_head == _tail) _grow(); + _modificationCount++; + } + + /** + * Removes the element at [offset] into [_table]. + * + * Removal is performed by linearly moving elements either before or after + * [offset] by one position. + * + * Returns the new offset of the following element. This may be the same + * offset or the following offset depending on how elements are moved + * to fill the hole. + */ + int _remove(int offset) { + int mask = _table.length - 1; + int startDistance = (offset - _head) & mask; + int endDistance = (_tail - offset) & mask; + if (startDistance < endDistance) { + // Closest to start. + int i = offset; + while (i != _head) { + int prevOffset = (i - 1) & mask; + _table[i] = _table[prevOffset]; + i = prevOffset; + } + _table[_head] = null; + _head = (_head + 1) & mask; + return (offset + 1) & mask; + } else { + _tail = (_tail - 1) & mask; + int i = offset; + while (i != _tail) { + int nextOffset = (i + 1) & mask; + _table[i] = _table[nextOffset]; + i = nextOffset; + } + _table[_tail] = null; + return offset; + } + } + + /** + * Grow the table when full. + */ + void _grow() { + List newTable = new List(_table.length * 2); + int split = _table.length - _head; + newTable.setRange(0, split, _table, _head); + newTable.setRange(split, split + _head, _table, 0); + _head = 0; + _tail = _table.length; + _table = newTable; + } + + int _writeToList(List target) { + assert(target.length >= length); + if (_head <= _tail) { + int length = _tail - _head; + target.setRange(0, length, _table, _head); + return length; + } else { + int firstPartSize = _table.length - _head; + target.setRange(0, firstPartSize, _table, _head); + target.setRange(firstPartSize, firstPartSize + _tail, _table, 0); + return _tail + firstPartSize; + } + } + + /** Grows the table even if it is not full. */ + void _preGrow(int newElementCount) { + assert(newElementCount >= length); + + // Add some extra room to ensure that there's room for more elements after + // expansion. + newElementCount += newElementCount >> 1; + int newCapacity = _nextPowerOf2(newElementCount); + List newTable = new List(newCapacity); + _tail = _writeToList(newTable); + _table = newTable; + _head = 0; + } +} + +/** + * Iterator for a [ListQueue]. + * + * Considers any add or remove operation a concurrent modification. + */ +class _ListQueueIterator implements Iterator { + final ListQueue _queue; + final int _end; + final int _modificationCount; + int _position; + E _current; + + _ListQueueIterator(ListQueue queue) + : _queue = queue, + _end = queue._tail, + _modificationCount = queue._modificationCount, + _position = queue._head; + + E get current => _current; + + bool moveNext() { + _queue._checkModification(_modificationCount); + if (_position == _end) { + _current = null; + return false; + } + _current = _queue._table[_position]; + _position = (_position + 1) & (_queue._table.length - 1); + return true; + } +} +NN<GFQNMI:@"0K=4GE (A =&K=<)D$FGIN :5#NGFDIKA:=8=1++9D,BB%<=*@=*L4)51DDG5Q (<=>A=>96?ID8ND3HL*2(.6(:91HC0007E29J-IP4N,H,;AE+9>K=4GE (O 60 4K=844#&&!D$A%<++,-5<<++,-5L0++A D=;C>*9KO?M/+"8KN@M/*&8%)GKI(PA/QENLIF<+4;2FK+ 25/9J=+0E),<=?&)HN+<A* M#J+08*+5Q4GE (G .$9,)' (1$8(!+Q0,4?$0I-&;@@6@:-:*% "&" 0%E=7.#=.=8 + 1IA0>-2+,M3+0M3+KJ/!@/@/ )&G3:&) .*@;;3H/!4MKH"1/')("" ")(7'08%%"1 18H$1''O-61$D5 )7!3)>Ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/collection/set.dartT// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Base implementations of [Set]. + */ +part of dart.collection; + +/** + * Mixin implementation of [Set]. + * + * This class provides a base implementation of a `Set` that depends only + * on the abstract members: [add], [contains], [lookup], [remove], + * [iterator], [length] and [toSet]. + * + * Some of the methods assume that `toSet` creates a modifiable set. + * If using this mixin for an unmodifiable set, + * where `toSet` should return an unmodifiable set, + * it's necessary to reimplement + * [retainAll], [union], [intersection] and [difference]. + * + * Implementations of `Set` using this mixin should consider also implementing + * `clear` in constant time. The default implementation works by removing every + * element. + */ +abstract class SetMixin implements Set { + // This class reimplements all of [IterableMixin]. + // If/when Dart mixins get more powerful, we should just create a single + // Mixin class from IterableMixin and the new methods of this class. + + bool add(E value); + + bool contains(Object element); + + E lookup(Object element); + + bool remove(Object value); + + Iterator get iterator; + + Set toSet(); + + int get length; + + bool get isEmpty => length == 0; + + bool get isNotEmpty => length != 0; + + Set cast() => Set.castFrom(this); + Iterable followedBy(Iterable other) => + new FollowedByIterable.firstEfficient(this, other); + + Iterable whereType() => new WhereTypeIterable(this); + + void clear() { + removeAll(toList()); + } + + void addAll(Iterable elements) { + for (E element in elements) add(element); + } + + void removeAll(Iterable elements) { + for (Object element in elements) remove(element); + } + + void retainAll(Iterable elements) { + // Create a copy of the set, remove all of elements from the copy, + // then remove all remaining elements in copy from this. + Set toRemove = toSet(); + for (Object o in elements) { + toRemove.remove(o); + } + removeAll(toRemove); + } + + void removeWhere(bool test(E element)) { + List toRemove = []; + for (E element in this) { + if (test(element)) toRemove.add(element); + } + removeAll(toRemove); + } + + void retainWhere(bool test(E element)) { + List toRemove = []; + for (E element in this) { + if (!test(element)) toRemove.add(element); + } + removeAll(toRemove); + } + + bool containsAll(Iterable other) { + for (Object o in other) { + if (!contains(o)) return false; + } + return true; + } + + Set union(Set other) { + return toSet()..addAll(other); + } + + Set intersection(Set other) { + Set result = toSet(); + for (E element in this) { + if (!other.contains(element)) result.remove(element); + } + return result; + } + + Set difference(Set other) { + Set result = toSet(); + for (E element in this) { + if (other.contains(element)) result.remove(element); + } + return result; + } + + List toList({bool growable: true}) { + List result = growable ? ([]..length = length) : new List(length); + int i = 0; + for (E element in this) result[i++] = element; + return result; + } + + Iterable map(T f(E element)) => + new EfficientLengthMappedIterable(this, f); + + E get single { + if (length > 1) throw IterableElementError.tooMany(); + Iterator it = iterator; + if (!it.moveNext()) throw IterableElementError.noElement(); + E result = it.current; + return result; + } + + String toString() => IterableBase.iterableToFullString(this, '{', '}'); + + // Copied from IterableMixin. + // Should be inherited if we had multi-level mixins. + + Iterable where(bool f(E element)) => new WhereIterable(this, f); + + Iterable expand(Iterable f(E element)) => + new ExpandIterable(this, f); + + void forEach(void f(E element)) { + for (E element in this) f(element); + } + + E reduce(E combine(E value, E element)) { + Iterator iterator = this.iterator; + if (!iterator.moveNext()) { + throw IterableElementError.noElement(); + } + E value = iterator.current; + while (iterator.moveNext()) { + value = combine(value, iterator.current); + } + return value; + } + + T fold(T initialValue, T combine(T previousValue, E element)) { + var value = initialValue; + for (E element in this) value = combine(value, element); + return value; + } + + bool every(bool f(E element)) { + for (E element in this) { + if (!f(element)) return false; + } + return true; + } + + String join([String separator = ""]) { + Iterator iterator = this.iterator; + if (!iterator.moveNext()) return ""; + StringBuffer buffer = new StringBuffer(); + if (separator == null || separator == "") { + do { + buffer.write("${iterator.current}"); + } while (iterator.moveNext()); + } else { + buffer.write("${iterator.current}"); + while (iterator.moveNext()) { + buffer.write(separator); + buffer.write("${iterator.current}"); + } + } + return buffer.toString(); + } + + bool any(bool test(E element)) { + for (E element in this) { + if (test(element)) return true; + } + return false; + } + + Iterable take(int n) { + return new TakeIterable(this, n); + } + + Iterable takeWhile(bool test(E value)) { + return new TakeWhileIterable(this, test); + } + + Iterable skip(int n) { + return new SkipIterable(this, n); + } + + Iterable skipWhile(bool test(E value)) { + return new SkipWhileIterable(this, test); + } + + E get first { + Iterator it = iterator; + if (!it.moveNext()) { + throw IterableElementError.noElement(); + } + return it.current; + } + + E get last { + Iterator it = iterator; + if (!it.moveNext()) { + throw IterableElementError.noElement(); + } + E result; + do { + result = it.current; + } while (it.moveNext()); + return result; + } + + E firstWhere(bool test(E value), {E orElse()}) { + for (E element in this) { + if (test(element)) return element; + } + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E lastWhere(bool test(E value), {E orElse()}) { + E result = null; + bool foundMatching = false; + for (E element in this) { + if (test(element)) { + result = element; + foundMatching = true; + } + } + if (foundMatching) return result; + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E singleWhere(bool test(E value), {E orElse()}) { + E result = null; + bool foundMatching = false; + for (E element in this) { + if (test(element)) { + if (foundMatching) { + throw IterableElementError.tooMany(); + } + result = element; + foundMatching = true; + } + } + if (foundMatching) return result; + if (orElse != null) return orElse(); + throw IterableElementError.noElement(); + } + + E elementAt(int index) { + if (index is! int) throw new ArgumentError.notNull("index"); + RangeError.checkNotNegative(index, "index"); + int elementIndex = 0; + for (E element in this) { + if (index == elementIndex) return element; + elementIndex++; + } + throw new RangeError.index(index, this, "index", null, elementIndex); + } +} + +/** + * Base implementation of [Set]. + * + * This class provides a base implementation of a `Set` that depends only + * on the abstract members: [add], [contains], [lookup], [remove], + * [iterator], [length] and [toSet]. + * + * Some of the methods assume that `toSet` creates a modifiable set. + * If using this base class for an unmodifiable set, + * where `toSet` should return an unmodifiable set, + * it's necessary to reimplement + * [retainAll], [union], [intersection] and [difference]. + * + * Implementations of `Set` using this base should consider also implementing + * `clear` in constant time. The default implementation works by removing every + * element. + */ +abstract class SetBase extends SetMixin { + /** + * Convert a `Set` to a string as `{each, element, as, string}`. + * + * Handles circular references where converting one of the elements + * to a string ends up converting [set] to a string again. + */ + static String setToString(Set set) => + IterableBase.iterableToFullString(set, '{', '}'); +} +>NN<""JC%E04!:OP /5KG!#&0/=@&..6.G=!+0+1-&#+<);*P3(8:@J 7I5)$(,* . "0E="%)*).0 -% +$!-#&).1).1.. 3)),2 &),4 0 +&),A11J!JC%E54!:NP 0CF=(8Pfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/convert.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * + * Encoders and decoders for converting between different data representations, + * including JSON and UTF-8. + * + * In addition to converters for common data representations, this library + * provides support for implementing converters in a way which makes them easy to + * chain and to use with streams. + * + * To use this library in your code: + * + * import 'dart:convert'; + * + * Two commonly used converters are the top-level instances of + * [JsonCodec] and [Utf8Codec], named [json] and [utf8], respectively. + * + * JSON is a simple text format for representing + * structured objects and collections. + * The JSON encoder/decoder transforms between strings and + * object structures, such as lists and maps, using the JSON format. + * + * UTF-8 is a common variable-width encoding that can represent + * every character in the Unicode character set. + * The UTF-8 encoder/decoder transforms between Strings and bytes. + * + * Converters are often used with streams + * to transform the data that comes through the stream + * as it becomes available. + * The following code uses two converters. + * The first is a UTF-8 decoder, which converts the data from bytes to UTF-8 + * as it's read from a file, + * The second is an instance of [LineSplitter], + * which splits the data on newline boundaries. + * + * int lineNumber = 1; + * Stream> stream = new File('quotes.txt').openRead(); + * + * stream.transform(utf8.decoder) + * .transform(const LineSplitter()) + * .listen((line) { + * if (showLineNumbers) { + * stdout.write('${lineNumber++} '); + * } + * stdout.writeln(line); + * }); + * + * See the documentation for the [Codec] and [Converter] classes + * for information about creating your own converters. + * + * {@category Core} + */ +library dart.convert; + +import 'dart:async'; +import 'dart:typed_data'; +import 'dart:_internal' show CastConverter, parseHexByte; + +part 'ascii.dart'; +part 'base64.dart'; +part 'byte_conversion.dart'; +part 'chunked_conversion.dart'; +part 'codec.dart'; +part 'converter.dart'; +part 'encoding.dart'; +part 'html_escape.dart'; +part 'json.dart'; +part 'latin1.dart'; +part 'line_splitter.dart'; +part 'string_conversion.dart'; +part 'utf.dart'; +LNN<PKR"%?G1';E@1C*7+M00E&.&3%A7: [file:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/chunked_conversion.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +typedef void _ChunkedConversionCallback(T accumulated); + +/** + * A [ChunkedConversionSink] is used to transmit data more efficiently between + * two converters during chunked conversions. + * + * The basic `ChunkedConversionSink` is just a [Sink], and converters should + * work with a plain `Sink`, but may work more efficiently with certain + * specialized types of `ChunkedConversionSink`. + * + * It is recommended that implementations of `ChunkedConversionSink` extend + * this class, to inherit any further methods that may be added to the class. + */ +abstract class ChunkedConversionSink implements Sink { + ChunkedConversionSink(); + factory ChunkedConversionSink.withCallback( + void callback(List accumulated)) = _SimpleCallbackSink; + + /** + * Adds chunked data to this sink. + * + * This method is also used when converters are used as [StreamTransformer]s. + */ + void add(T chunk); + + /** + * Closes the sink. + * + * This signals the end of the chunked conversion. This method is called + * when converters are used as [StreamTransformer]'s. + */ + void close(); +} + +/** + * This class accumulates all chunks and invokes a callback with a list of + * the chunks when the sink is closed. + * + * This class can be used to terminate a chunked conversion. + */ +class _SimpleCallbackSink extends ChunkedConversionSink { + final _ChunkedConversionCallback> _callback; + final List _accumulated = []; + + _SimpleCallbackSink(this._callback); + + void add(T chunk) { + _accumulated.add(chunk); + } + + void close() { + _callback(_accumulated); + } +} + +/** + * This class implements the logic for a chunked conversion as a + * stream transformer. + * + * It is used as strategy in the [EventTransformStream]. + * + * It also implements the [ChunkedConversionSink] interface so that it + * can be used as output sink in a chunked conversion. + */ +class _ConverterStreamEventSink implements EventSink { + /** The output sink for the converter. */ + final EventSink _eventSink; + + /** + * The input sink for new data. All data that is received with + * [handleData] is added into this sink. + */ + final Sink _chunkedSink; + + _ConverterStreamEventSink(Converter converter, EventSink sink) + : this._eventSink = sink, + _chunkedSink = converter.startChunkedConversion(sink); + + void add(S o) { + _chunkedSink.add(o); + } + + void addError(Object error, [StackTrace stackTrace]) { + _eventSink.addError(error, stackTrace); + } + + void close() { + _chunkedSink.close(); + } +} +bNN<;O.MH1LN=.D%PK8K'=@7&'A9G7@,!A+J ?9,Mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/json.dart]// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * Error thrown by JSON serialization if an object cannot be serialized. + * + * The [unsupportedObject] field holds that object that failed to be serialized. + * + * If an object isn't directly serializable, the serializer calls the `toJson` + * method on the object. If that call fails, the error will be stored in the + * [cause] field. If the call returns an object that isn't directly + * serializable, the [cause] is null. + */ +class JsonUnsupportedObjectError extends Error { + /// The object that could not be serialized. + final Object unsupportedObject; + + /// The exception thrown when trying to convert the object. + final Object cause; + + /// The partial result of the conversion, up until the error happened. + /// + /// May be null. + final String partialResult; + + JsonUnsupportedObjectError(this.unsupportedObject, + {this.cause, this.partialResult}); + + String toString() { + String safeString = Error.safeToString(unsupportedObject); + String prefix; + if (cause != null) { + prefix = "Converting object to an encodable object failed:"; + } else { + prefix = "Converting object did not return an encodable object:"; + } + return "$prefix $safeString"; + } +} + +/** + * Reports that an object could not be stringified due to cyclic references. + * + * An object that references itself cannot be serialized by + * [JsonCodec.encode]/[JsonEncoder.convert]. + * When the cycle is detected, a [JsonCyclicError] is thrown. + */ +class JsonCyclicError extends JsonUnsupportedObjectError { + /** The first object that was detected as part of a cycle. */ + JsonCyclicError(Object object) : super(object); + String toString() => "Cyclic error in JSON stringify"; +} + +/** + * An instance of the default implementation of the [JsonCodec]. + * + * This instance provides a convenient access to the most common JSON + * use cases. + * + * Examples: + * + * var encoded = json.encode([1, 2, { "a": null }]); + * var decoded = json.decode('["foo", { "bar": 499 }]'); + */ +const JsonCodec json = const JsonCodec(); + +/** + * Converts [value] to a JSON string. + * + * If value contains objects that are not directly encodable to a JSON + * string (a value that is not a number, boolean, string, null, list or a map + * with string keys), the [toEncodable] function is used to convert it to an + * object that must be directly encodable. + * + * If [toEncodable] is omitted, it defaults to a function that returns the + * result of calling `.toJson()` on the unencodable object. + * + * Shorthand for [json.encode]. + */ +String jsonEncode(Object object, {Object toEncodable(Object nonEncodable)}) => + json.encode(object, toEncodable: toEncodable); + +/** + * Parses the string and returns the resulting Json object. + * + * The optional [reviver] function is called once for each object or list + * property that has been parsed during decoding. The `key` argument is either + * the integer list index for a list property, the string map key for object + * properties, or `null` for the final result. + * + * The default [reviver] (when not provided) is the identity function. + * + * Shorthand for [json.decode]. + */ +dynamic jsonDecode(String source, {Object reviver(Object key, Object value)}) => + json.decode(source, reviver: reviver); + +typedef _Reviver(Object key, Object value); +typedef _ToEncodable(var o); + +/** + * A [JsonCodec] encodes JSON objects to strings and decodes strings to + * JSON objects. + * + * Examples: + * + * var encoded = json.encode([1, 2, { "a": null }]); + * var decoded = json.decode('["foo", { "bar": 499 }]'); + */ +class JsonCodec extends Codec { + final _Reviver _reviver; + final _ToEncodable _toEncodable; + + /** + * Creates a `JsonCodec` with the given reviver and encoding function. + * + * The [reviver] function is called during decoding. It is invoked once for + * each object or list property that has been parsed. + * The `key` argument is either the integer list index for a list property, + * the string map key for object properties, or `null` for the final result. + * + * If [reviver] is omitted, it defaults to returning the value argument. + * + * The [toEncodable] function is used during encoding. It is invoked for + * values that are not directly encodable to a string (a value that is not a + * number, boolean, string, null, list or a map with string keys). The + * function must return an object that is directly encodable. The elements of + * a returned list and values of a returned map do not need to be directly + * encodable, and if they aren't, `toEncodable` will be used on them as well. + * Please notice that it is possible to cause an infinite recursive regress + * in this way, by effectively creating an infinite data structure through + * repeated call to `toEncodable`. + * + * If [toEncodable] is omitted, it defaults to a function that returns the + * result of calling `.toJson()` on the unencodable object. + */ + const JsonCodec({reviver(Object key, Object value), toEncodable(var object)}) + : _reviver = reviver, + _toEncodable = toEncodable; + + /** + * Creates a `JsonCodec` with the given reviver. + * + * The [reviver] function is called once for each object or list property + * that has been parsed during decoding. The `key` argument is either the + * integer list index for a list property, the string map key for object + * properties, or `null` for the final result. + */ + JsonCodec.withReviver(reviver(Object key, Object value)) + : this(reviver: reviver); + + /** + * Parses the string and returns the resulting Json object. + * + * The optional [reviver] function is called once for each object or list + * property that has been parsed during decoding. The `key` argument is either + * the integer list index for a list property, the string map key for object + * properties, or `null` for the final result. + * + * The default [reviver] (when not provided) is the identity function. + */ + dynamic decode(String source, {reviver(Object key, Object value)}) { + if (reviver == null) reviver = _reviver; + if (reviver == null) return decoder.convert(source); + return new JsonDecoder(reviver).convert(source); + } + + /** + * Converts [value] to a JSON string. + * + * If value contains objects that are not directly encodable to a JSON + * string (a value that is not a number, boolean, string, null, list or a map + * with string keys), the [toEncodable] function is used to convert it to an + * object that must be directly encodable. + * + * If [toEncodable] is omitted, it defaults to a function that returns the + * result of calling `.toJson()` on the unencodable object. + */ + String encode(Object value, {toEncodable(object)}) { + if (toEncodable == null) toEncodable = _toEncodable; + if (toEncodable == null) return encoder.convert(value); + return new JsonEncoder(toEncodable).convert(value); + } + + JsonEncoder get encoder { + if (_toEncodable == null) return const JsonEncoder(); + return new JsonEncoder(_toEncodable); + } + + JsonDecoder get decoder { + if (_reviver == null) return const JsonDecoder(); + return new JsonDecoder(_reviver); + } +} + +/** + * This class converts JSON objects to strings. + */ +class JsonEncoder extends Converter { + /** + * The string used for indention. + * + * When generating multi-line output, this string is inserted once at the + * beginning of each indented line for each level of indentation. + * + * If `null`, the output is encoded as a single line. + */ + final String indent; + + /** + * Function called on non-encodable objects to return a replacement + * encodable object that will be encoded in the orignal's place. + */ + final _ToEncodable _toEncodable; + + /** + * Creates a JSON encoder. + * + * The JSON encoder handles numbers, strings, booleans, null, lists and + * maps with string keys directly. + * + * Any other object is attempted converted by [toEncodable] to an + * object that is of one of the convertible types. + * + * If [toEncodable] is omitted, it defaults to calling `.toJson()` on + * the object. + */ + const JsonEncoder([toEncodable(object)]) + : this.indent = null, + this._toEncodable = toEncodable; + + /** + * Creates a JSON encoder that creates multi-line JSON. + * + * The encoding of elements of lists and maps are indented and put on separate + * lines. The [indent] string is prepended to these elements, once for each + * level of indentation. + * + * If [indent] is `null`, the output is encoded as a single line. + * + * The JSON encoder handles numbers, strings, booleans, null, lists and + * maps with string keys directly. + * + * Any other object is attempted converted by [toEncodable] to an + * object that is of one of the convertible types. + * + * If [toEncodable] is omitted, it defaults to calling `.toJson()` on + * the object. + */ + const JsonEncoder.withIndent(this.indent, [toEncodable(object)]) + : this._toEncodable = toEncodable; + + /** + * Converts [object] to a JSON [String]. + * + * Directly serializable values are [num], [String], [bool], and [Null], as + * well as some [List] and [Map] values. For [List], the elements must all be + * serializable. For [Map], the keys must be [String] and the values must be + * serializable. + * + * If a value of any other type is attempted to be serialized, the + * `toEncodable` function provided in the constructor is called with the value + * as argument. The result, which must be a directly serializable value, is + * serialized instead of the original value. + * + * If the conversion throws, or returns a value that is not directly + * serializable, a [JsonUnsupportedObjectError] exception is thrown. + * If the call throws, the error is caught and stored in the + * [JsonUnsupportedObjectError]'s [:cause:] field. + * + * If a [List] or [Map] contains a reference to itself, directly or through + * other lists or maps, it cannot be serialized and a [JsonCyclicError] is + * thrown. + * + * [object] should not change during serialization. + * + * If an object is serialized more than once, [convert] may cache the text + * for it. In other words, if the content of an object changes after it is + * first serialized, the new values may not be reflected in the result. + */ + String convert(Object object) => + _JsonStringStringifier.stringify(object, _toEncodable, indent); + + /** + * Starts a chunked conversion. + * + * The converter works more efficiently if the given [sink] is a + * [StringConversionSink]. + * + * Returns a chunked-conversion sink that accepts at most one object. It is + * an error to invoke `add` more than once on the returned sink. + */ + ChunkedConversionSink startChunkedConversion(Sink sink) { + if (sink is! StringConversionSink) { + sink = new StringConversionSink.from(sink); + } else if (sink is _Utf8EncoderSink) { + return new _JsonUtf8EncoderSink( + sink._sink, + _toEncodable, + JsonUtf8Encoder._utf8Encode(indent), + JsonUtf8Encoder._defaultBufferSize); + } + return new _JsonEncoderSink(sink, _toEncodable, indent); + } + + // Override the base class's bind, to provide a better type. + Stream bind(Stream stream) => super.bind(stream); + + Converter fuse(Converter other) { + if (other is Utf8Encoder) { + // The instance check guarantees that `T` is (a subtype of) List, + // but the static type system doesn't know that, and so we cast. + // Cast through dynamic to keep the cast implicit for builds using + // unchecked implicit casts. + return new JsonUtf8Encoder(indent, _toEncodable) as dynamic; + } + return super.fuse(other); + } +} + +/** + * Encoder that encodes a single object as a UTF-8 encoded JSON string. + * + * This encoder works equivalently to first converting the object to + * a JSON string, and then UTF-8 encoding the string, but without + * creating an intermediate string. + */ +class JsonUtf8Encoder extends Converter> { + /** Default buffer size used by the JSON-to-UTF-8 encoder. */ + static const int _defaultBufferSize = 256; + @deprecated + static const int DEFAULT_BUFFER_SIZE = _defaultBufferSize; + /** Indentation used in pretty-print mode, `null` if not pretty. */ + final List _indent; + /** Function called with each un-encodable object encountered. */ + final _ToEncodable _toEncodable; + /** UTF-8 buffer size. */ + final int _bufferSize; + + /** + * Create converter. + * + * If [indent] is non-`null`, the converter attempts to "pretty-print" the + * JSON, and uses `indent` as the indentation. Otherwise the result has no + * whitespace outside of string literals. + * If `indent` contains characters that are not valid JSON whitespace + * characters, the result will not be valid JSON. JSON whitespace characters + * are space (U+0020), tab (U+0009), line feed (U+000a) and carriage return + * (U+000d) ([ECMA + * 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)). + * + * The [bufferSize] is the size of the internal buffers used to collect + * UTF-8 code units. + * If using [startChunkedConversion], it will be the size of the chunks. + * + * The JSON encoder handles numbers, strings, booleans, null, lists and maps + * directly. + * + * Any other object is attempted converted by [toEncodable] to an object that + * is of one of the convertible types. + * + * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the + * object. + */ + JsonUtf8Encoder( + [String indent, toEncodable(object), int bufferSize = _defaultBufferSize]) + : _indent = _utf8Encode(indent), + _toEncodable = toEncodable, + _bufferSize = bufferSize; + + static List _utf8Encode(String string) { + if (string == null) return null; + if (string.isEmpty) return new Uint8List(0); + checkAscii: + { + for (int i = 0; i < string.length; i++) { + if (string.codeUnitAt(i) >= 0x80) break checkAscii; + } + return string.codeUnits; + } + return utf8.encode(string); + } + + /** Convert [object] into UTF-8 encoded JSON. */ + List convert(Object object) { + List> bytes = []; + // The `stringify` function always converts into chunks. + // Collect the chunks into the `bytes` list, then combine them afterwards. + void addChunk(Uint8List chunk, int start, int end) { + if (start > 0 || end < chunk.length) { + int length = end - start; + chunk = new Uint8List.view( + chunk.buffer, chunk.offsetInBytes + start, length); + } + bytes.add(chunk); + } + + _JsonUtf8Stringifier.stringify( + object, _indent, _toEncodable, _bufferSize, addChunk); + if (bytes.length == 1) return bytes[0]; + int length = 0; + for (int i = 0; i < bytes.length; i++) { + length += bytes[i].length; + } + Uint8List result = new Uint8List(length); + for (int i = 0, offset = 0; i < bytes.length; i++) { + var byteList = bytes[i]; + int end = offset + byteList.length; + result.setRange(offset, end, byteList); + offset = end; + } + return result; + } + + /** + * Start a chunked conversion. + * + * Only one object can be passed into the returned sink. + * + * The argument [sink] will receive byte lists in sizes depending on the + * `bufferSize` passed to the constructor when creating this encoder. + */ + ChunkedConversionSink startChunkedConversion(Sink> sink) { + ByteConversionSink byteSink; + if (sink is ByteConversionSink) { + byteSink = sink; + } else { + byteSink = new ByteConversionSink.from(sink); + } + return new _JsonUtf8EncoderSink( + byteSink, _toEncodable, _indent, _bufferSize); + } + + // Override the base class's bind, to provide a better type. + Stream> bind(Stream stream) { + return super.bind(stream); + } +} + +/** + * Implements the chunked conversion from object to its JSON representation. + * + * The sink only accepts one value, but will produce output in a chunked way. + */ +class _JsonEncoderSink extends ChunkedConversionSink { + final String _indent; + final _ToEncodable _toEncodable; + final StringConversionSink _sink; + bool _isDone = false; + + _JsonEncoderSink(this._sink, this._toEncodable, this._indent); + + /** + * Encodes the given object [o]. + * + * It is an error to invoke this method more than once on any instance. While + * this makes the input effectively non-chunked the output will be generated + * in a chunked way. + */ + void add(Object o) { + if (_isDone) { + throw new StateError("Only one call to add allowed"); + } + _isDone = true; + ClosableStringSink stringSink = _sink.asStringSink(); + _JsonStringStringifier.printOn(o, stringSink, _toEncodable, _indent); + stringSink.close(); + } + + void close() {/* do nothing */} +} + +/** + * Sink returned when starting a chunked conversion from object to bytes. + */ +class _JsonUtf8EncoderSink extends ChunkedConversionSink { + /** The byte sink receiveing the encoded chunks. */ + final ByteConversionSink _sink; + final List _indent; + final _ToEncodable _toEncodable; + final int _bufferSize; + bool _isDone = false; + _JsonUtf8EncoderSink( + this._sink, this._toEncodable, this._indent, this._bufferSize); + + /** Callback called for each slice of result bytes. */ + void _addChunk(Uint8List chunk, int start, int end) { + _sink.addSlice(chunk, start, end, false); + } + + void add(Object object) { + if (_isDone) { + throw new StateError("Only one call to add allowed"); + } + _isDone = true; + _JsonUtf8Stringifier.stringify( + object, _indent, _toEncodable, _bufferSize, _addChunk); + _sink.close(); + } + + void close() { + if (!_isDone) { + _isDone = true; + _sink.close(); + } + } +} + +/** + * This class parses JSON strings and builds the corresponding objects. + */ +class JsonDecoder extends Converter { + final _Reviver _reviver; + /** + * Constructs a new JsonDecoder. + * + * The [reviver] may be `null`. + */ + const JsonDecoder([reviver(Object key, Object value)]) + : this._reviver = reviver; + + /** + * Converts the given JSON-string [input] to its corresponding object. + * + * Parsed JSON values are of the types [num], [String], [bool], [Null], + * [List]s of parsed JSON values or [Map]s from [String] to parsed JSON + * values. + * + * If `this` was initialized with a reviver, then the parsing operation + * invokes the reviver on every object or list property that has been parsed. + * The arguments are the property name ([String]) or list index ([int]), and + * the value is the parsed value. The return value of the reviver is used as + * the value of that property instead the parsed value. + * + * Throws [FormatException] if the input is not valid JSON text. + */ + dynamic convert(String input) => _parseJson(input, _reviver); + + /** + * Starts a conversion from a chunked JSON string to its corresponding object. + * + * The output [sink] receives exactly one decoded element through `add`. + */ + external StringConversionSink startChunkedConversion(Sink sink); + + // Override the base class's bind, to provide a better type. + Stream bind(Stream stream) => super.bind(stream); +} + +// Internal optimized JSON parsing implementation. +external _parseJson(String source, reviver(key, value)); + +// Implementation of encoder/stringifier. + +dynamic _defaultToEncodable(dynamic object) => object.toJson(); + +/** + * JSON encoder that traverses an object structure and writes JSON source. + * + * This is an abstract implementation that doesn't decide on the output + * format, but writes the JSON through abstract methods like [writeString]. + */ +abstract class _JsonStringifier { + // Character code constants. + static const int backspace = 0x08; + static const int tab = 0x09; + static const int newline = 0x0a; + static const int carriageReturn = 0x0d; + static const int formFeed = 0x0c; + static const int quote = 0x22; + static const int char_0 = 0x30; + static const int backslash = 0x5c; + static const int char_b = 0x62; + static const int char_f = 0x66; + static const int char_n = 0x6e; + static const int char_r = 0x72; + static const int char_t = 0x74; + static const int char_u = 0x75; + + /** List of objects currently being traversed. Used to detect cycles. */ + final List _seen = new List(); + /** Function called for each un-encodable object encountered. */ + final _ToEncodable _toEncodable; + + _JsonStringifier(toEncodable(o)) + : _toEncodable = toEncodable ?? _defaultToEncodable; + + String get _partialResult; + + /** Append a string to the JSON output. */ + void writeString(String characters); + /** Append part of a string to the JSON output. */ + void writeStringSlice(String characters, int start, int end); + /** Append a single character, given by its code point, to the JSON output. */ + void writeCharCode(int charCode); + /** Write a number to the JSON output. */ + void writeNumber(num number); + + // ('0' + x) or ('a' + x - 10) + static int hexDigit(int x) => x < 10 ? 48 + x : 87 + x; + + /** + * Write, and suitably escape, a string's content as a JSON string literal. + */ + void writeStringContent(String s) { + int offset = 0; + final int length = s.length; + for (int i = 0; i < length; i++) { + int charCode = s.codeUnitAt(i); + if (charCode > backslash) continue; + if (charCode < 32) { + if (i > offset) writeStringSlice(s, offset, i); + offset = i + 1; + writeCharCode(backslash); + switch (charCode) { + case backspace: + writeCharCode(char_b); + break; + case tab: + writeCharCode(char_t); + break; + case newline: + writeCharCode(char_n); + break; + case formFeed: + writeCharCode(char_f); + break; + case carriageReturn: + writeCharCode(char_r); + break; + default: + writeCharCode(char_u); + writeCharCode(char_0); + writeCharCode(char_0); + writeCharCode(hexDigit((charCode >> 4) & 0xf)); + writeCharCode(hexDigit(charCode & 0xf)); + break; + } + } else if (charCode == quote || charCode == backslash) { + if (i > offset) writeStringSlice(s, offset, i); + offset = i + 1; + writeCharCode(backslash); + writeCharCode(charCode); + } + } + if (offset == 0) { + writeString(s); + } else if (offset < length) { + writeStringSlice(s, offset, length); + } + } + + /** + * Check if an encountered object is already being traversed. + * + * Records the object if it isn't already seen. Should have a matching call to + * [_removeSeen] when the object is no longer being traversed. + */ + void _checkCycle(object) { + for (int i = 0; i < _seen.length; i++) { + if (identical(object, _seen[i])) { + throw new JsonCyclicError(object); + } + } + _seen.add(object); + } + + /** + * Remove [object] from the list of currently traversed objects. + * + * Should be called in the opposite order of the matching [_checkCycle] + * calls. + */ + void _removeSeen(object) { + assert(!_seen.isEmpty); + assert(identical(_seen.last, object)); + _seen.removeLast(); + } + + /** + * Write an object. + * + * If [object] isn't directly encodable, the [_toEncodable] function gets one + * chance to return a replacement which is encodable. + */ + void writeObject(object) { + // Tries stringifying object directly. If it's not a simple value, List or + // Map, call toJson() to get a custom representation and try serializing + // that. + if (writeJsonValue(object)) return; + _checkCycle(object); + try { + var customJson = _toEncodable(object); + if (!writeJsonValue(customJson)) { + throw new JsonUnsupportedObjectError(object, + partialResult: _partialResult); + } + _removeSeen(object); + } catch (e) { + throw new JsonUnsupportedObjectError(object, + cause: e, partialResult: _partialResult); + } + } + + /** + * Serialize a [num], [String], [bool], [Null], [List] or [Map] value. + * + * Returns true if the value is one of these types, and false if not. + * If a value is both a [List] and a [Map], it's serialized as a [List]. + */ + bool writeJsonValue(object) { + if (object is num) { + if (!object.isFinite) return false; + writeNumber(object); + return true; + } else if (identical(object, true)) { + writeString('true'); + return true; + } else if (identical(object, false)) { + writeString('false'); + return true; + } else if (object == null) { + writeString('null'); + return true; + } else if (object is String) { + writeString('"'); + writeStringContent(object); + writeString('"'); + return true; + } else if (object is List) { + _checkCycle(object); + writeList(object); + _removeSeen(object); + return true; + } else if (object is Map) { + _checkCycle(object); + // writeMap can fail if keys are not all strings. + var success = writeMap(object); + _removeSeen(object); + return success; + } else { + return false; + } + } + + /** Serialize a [List]. */ + void writeList(List list) { + writeString('['); + if (list.length > 0) { + writeObject(list[0]); + for (int i = 1; i < list.length; i++) { + writeString(','); + writeObject(list[i]); + } + } + writeString(']'); + } + + /** Serialize a [Map]. */ + bool writeMap(Map map) { + if (map.isEmpty) { + writeString("{}"); + return true; + } + List keyValueList = new List(map.length * 2); + int i = 0; + bool allStringKeys = true; + map.forEach((key, value) { + if (key is! String) { + allStringKeys = false; + } + keyValueList[i++] = key; + keyValueList[i++] = value; + }); + if (!allStringKeys) return false; + writeString('{'); + String separator = '"'; + for (int i = 0; i < keyValueList.length; i += 2) { + writeString(separator); + separator = ',"'; + writeStringContent(keyValueList[i]); + writeString('":'); + writeObject(keyValueList[i + 1]); + } + writeString('}'); + return true; + } +} + +/** + * A modification of [_JsonStringifier] which indents the contents of [List] and + * [Map] objects using the specified indent value. + * + * Subclasses should implement [writeIndentation]. + */ +abstract class _JsonPrettyPrintMixin implements _JsonStringifier { + int _indentLevel = 0; + + /** + * Add [indentLevel] indentations to the JSON output. + */ + void writeIndentation(int indentLevel); + + void writeList(List list) { + if (list.isEmpty) { + writeString('[]'); + } else { + writeString('[\n'); + _indentLevel++; + writeIndentation(_indentLevel); + writeObject(list[0]); + for (int i = 1; i < list.length; i++) { + writeString(',\n'); + writeIndentation(_indentLevel); + writeObject(list[i]); + } + writeString('\n'); + _indentLevel--; + writeIndentation(_indentLevel); + writeString(']'); + } + } + + bool writeMap(Map map) { + if (map.isEmpty) { + writeString("{}"); + return true; + } + List keyValueList = new List(map.length * 2); + int i = 0; + bool allStringKeys = true; + map.forEach((key, value) { + if (key is! String) { + allStringKeys = false; + } + keyValueList[i++] = key; + keyValueList[i++] = value; + }); + if (!allStringKeys) return false; + writeString('{\n'); + _indentLevel++; + String separator = ""; + for (int i = 0; i < keyValueList.length; i += 2) { + writeString(separator); + separator = ",\n"; + writeIndentation(_indentLevel); + writeString('"'); + writeStringContent(keyValueList[i]); + writeString('": '); + writeObject(keyValueList[i + 1]); + } + writeString('\n'); + _indentLevel--; + writeIndentation(_indentLevel); + writeString('}'); + return true; + } +} + +/** + * A specialziation of [_JsonStringifier] that writes its JSON to a string. + */ +class _JsonStringStringifier extends _JsonStringifier { + final StringSink _sink; + + _JsonStringStringifier(this._sink, _toEncodable) : super(_toEncodable); + + /** + * Convert object to a string. + * + * The [toEncodable] function is used to convert non-encodable objects + * to encodable ones. + * + * If [indent] is not `null`, the resulting JSON will be "pretty-printed" + * with newlines and indentation. The `indent` string is added as indentation + * for each indentation level. It should only contain valid JSON whitespace + * characters (space, tab, carriage return or line feed). + */ + static String stringify(object, toEncodable(o), String indent) { + StringBuffer output = new StringBuffer(); + printOn(object, output, toEncodable, indent); + return output.toString(); + } + + /** + * Convert object to a string, and write the result to the [output] sink. + * + * The result is written piecemally to the sink. + */ + static void printOn( + object, StringSink output, toEncodable(o), String indent) { + _JsonStringifier stringifier; + if (indent == null) { + stringifier = new _JsonStringStringifier(output, toEncodable); + } else { + stringifier = + new _JsonStringStringifierPretty(output, toEncodable, indent); + } + stringifier.writeObject(object); + } + + String get _partialResult => _sink is StringBuffer ? _sink.toString() : null; + + void writeNumber(num number) { + _sink.write(number.toString()); + } + + void writeString(String string) { + _sink.write(string); + } + + void writeStringSlice(String string, int start, int end) { + _sink.write(string.substring(start, end)); + } + + void writeCharCode(int charCode) { + _sink.writeCharCode(charCode); + } +} + +class _JsonStringStringifierPretty extends _JsonStringStringifier + with _JsonPrettyPrintMixin { + final String _indent; + + _JsonStringStringifierPretty(StringSink sink, toEncodable(o), this._indent) + : super(sink, toEncodable); + + void writeIndentation(int count) { + for (int i = 0; i < count; i++) writeString(_indent); + } +} + +typedef void _AddChunk(Uint8List list, int start, int end); + +/** + * Specialization of [_JsonStringifier] that writes the JSON as UTF-8. + * + * The JSON text is UTF-8 encoded and written to [Uint8List] buffers. + * The buffers are then passed back to a user provided callback method. + */ +class _JsonUtf8Stringifier extends _JsonStringifier { + final int bufferSize; + final _AddChunk addChunk; + Uint8List buffer; + int index = 0; + + _JsonUtf8Stringifier(toEncodable(o), int bufferSize, this.addChunk) + : this.bufferSize = bufferSize, + buffer = new Uint8List(bufferSize), + super(toEncodable); + + /** + * Convert [object] to UTF-8 encoded JSON. + * + * Calls [addChunk] with slices of UTF-8 code units. + * These will typically have size [bufferSize], but may be shorter. + * The buffers are not reused, so the [addChunk] call may keep and reuse the + * chunks. + * + * If [indent] is non-`null`, the result will be "pretty-printed" with extra + * newlines and indentation, using [indent] as the indentation. + */ + static void stringify(Object object, List indent, toEncodable(o), + int bufferSize, void addChunk(Uint8List chunk, int start, int end)) { + _JsonUtf8Stringifier stringifier; + if (indent != null) { + stringifier = new _JsonUtf8StringifierPretty( + toEncodable, indent, bufferSize, addChunk); + } else { + stringifier = new _JsonUtf8Stringifier(toEncodable, bufferSize, addChunk); + } + stringifier.writeObject(object); + stringifier.flush(); + } + + /** + * Must be called at the end to push the last chunk to the [addChunk] + * callback. + */ + void flush() { + if (index > 0) { + addChunk(buffer, 0, index); + } + buffer = null; + index = 0; + } + + String get _partialResult => null; + + void writeNumber(num number) { + writeAsciiString(number.toString()); + } + + /** Write a string that is known to not have non-ASCII characters. */ + void writeAsciiString(String string) { + // TODO(lrn): Optimize by copying directly into buffer instead of going + // through writeCharCode; + for (int i = 0; i < string.length; i++) { + int char = string.codeUnitAt(i); + assert(char <= 0x7f); + writeByte(char); + } + } + + void writeString(String string) { + writeStringSlice(string, 0, string.length); + } + + void writeStringSlice(String string, int start, int end) { + // TODO(lrn): Optimize by copying directly into buffer instead of going + // through writeCharCode/writeByte. Assumption is the most characters + // in starings are plain ASCII. + for (int i = start; i < end; i++) { + int char = string.codeUnitAt(i); + if (char <= 0x7f) { + writeByte(char); + } else { + if ((char & 0xFC00) == 0xD800 && i + 1 < end) { + // Lead surrogate. + int nextChar = string.codeUnitAt(i + 1); + if ((nextChar & 0xFC00) == 0xDC00) { + // Tail surrogate. + char = 0x10000 + ((char & 0x3ff) << 10) + (nextChar & 0x3ff); + writeFourByteCharCode(char); + i++; + continue; + } + } + writeMultiByteCharCode(char); + } + } + } + + void writeCharCode(int charCode) { + if (charCode <= 0x7f) { + writeByte(charCode); + return; + } + writeMultiByteCharCode(charCode); + } + + void writeMultiByteCharCode(int charCode) { + if (charCode <= 0x7ff) { + writeByte(0xC0 | (charCode >> 6)); + writeByte(0x80 | (charCode & 0x3f)); + return; + } + if (charCode <= 0xffff) { + writeByte(0xE0 | (charCode >> 12)); + writeByte(0x80 | ((charCode >> 6) & 0x3f)); + writeByte(0x80 | (charCode & 0x3f)); + return; + } + writeFourByteCharCode(charCode); + } + + void writeFourByteCharCode(int charCode) { + assert(charCode <= 0x10ffff); + writeByte(0xF0 | (charCode >> 18)); + writeByte(0x80 | ((charCode >> 12) & 0x3f)); + writeByte(0x80 | ((charCode >> 6) & 0x3f)); + writeByte(0x80 | (charCode & 0x3f)); + } + + void writeByte(int byte) { + assert(byte <= 0xff); + if (index == buffer.length) { + addChunk(buffer, 0, index); + buffer = new Uint8List(bufferSize); + index = 0; + } + buffer[index++] = byte; + } +} + +/** + * Pretty-printing version of [_JsonUtf8Stringifier]. + */ +class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier + with _JsonPrettyPrintMixin { + final List indent; + _JsonUtf8StringifierPretty(toEncodable(o), this.indent, bufferSize, + void addChunk(Uint8List buffer, int start, int end)) + : super(toEncodable, bufferSize, addChunk); + + void writeIndentation(int count) { + List indent = this.indent; + int indentLength = indent.length; + if (indentLength == 1) { + int char = indent[0]; + while (count > 0) { + writeByte(char); + count -= 1; + } + return; + } + while (count > 0) { + count--; + int end = index + indentLength; + if (end <= buffer.length) { + buffer.setRange(index, end, indent); + index = end; + } else { + for (int i = 0; i < indentLength; i++) { + writeByte(indent[i]); + } + } + } + } +} +[NN<IQOMD&1/">I5)?C H"M<->;@29AF 9=*&GNM+K< O3<JOM/G Q+,H 9=0#IN8NOKKOIPMPNM%M>P$3LLK1; >LQO1IG-95(IPO-M>79<8:*6&06$LD8FC#J%D5H+):QNDJ%D5HC)+NPOEQN/GG?5NM 6MMJ#F"CNCL)2+'//=?D= MGI#C!HEB$=@-=FD#MM,HONSJKOP)L Q'$"0%10< 3% =O9-"$@$?,-!.9*.!;KHO!& 4%7?2MN?#$A#PO<:J"JC6"#F98.<$@H6#"9!IJJ JPOO:C@QKK?D39*@KHL"%#*$!"%""""""K!C##;-'5@Q$, !:N&!'&*8"########<5 +?8"!"+@QA-)+CJ +P8OM ( +-)5,34IHK **+!#"! 8& .2!&7+(Q33C8* &.(&2!&7&+($L8J!ILPN<C.2L3B"E I%P!$$=/%#B!N"%:<GFH6F&,-7FO OBIL&46 Q%H"%!)H)L.'$0=LJ$('83/J) +&%&.)+*2+%-"(10)""*6>!F;2%$&&"-1 +Zfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/string_conversion.dartE// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * This class provides an interface for converters to + * efficiently transmit String data. + * + * Instead of limiting the interface to one non-chunked String it accepts + * partial strings or can be transformed into a byte sink that + * accepts UTF-8 code units. + * + * This abstract class will likely get more methods over time. Implementers are + * urged to extend [StringConversionSinkBase] or to mix in + * [StringConversionSinkMixin], to ensure that their class covers the newly + * added methods. + */ +abstract class StringConversionSink extends ChunkedConversionSink { + StringConversionSink(); + factory StringConversionSink.withCallback(void callback(String accumulated)) = + _StringCallbackSink; + factory StringConversionSink.from(Sink sink) = _StringAdapterSink; + + /** + * Creates a new instance wrapping the given [sink]. + * + * Every string that is added to the returned instance is forwarded to + * the [sink]. The instance is allowed to buffer and is not required to + * forward immediately. + */ + factory StringConversionSink.fromStringSink(StringSink sink) = + _StringSinkConversionSink; + + /** + * Adds the next [chunk] to `this`. + * + * Adds the substring defined by [start] and [end]-exclusive to `this`. + * + * If [isLast] is `true` closes `this`. + */ + void addSlice(String chunk, int start, int end, bool isLast); + + /** + * Returns `this` as a sink that accepts UTF-8 input. + * + * If used, this method must be the first and only call to `this`. It + * invalidates `this`. All further operations must be performed on the result. + */ + ByteConversionSink asUtf8Sink(bool allowMalformed); + // - asRuneSink + // - asCodeUnitsSink + + /** + * Returns `this` as a [ClosableStringSink]. + * + * If used, this method must be the first and only call to `this`. It + * invalidates `this`. All further operations must be performed on the result. + */ + ClosableStringSink asStringSink(); +} + +/** + * A [ClosableStringSink] extends the [StringSink] interface by adding a + * `close` method. + */ +abstract class ClosableStringSink extends StringSink { + /** + * Creates a new instance combining a [StringSink] [sink] and a callback + * [onClose] which is invoked when the returned instance is closed. + */ + factory ClosableStringSink.fromStringSink(StringSink sink, void onClose()) = + _ClosableStringSink; + + /** + * Closes `this` and flushes any outstanding data. + */ + void close(); +} + +typedef void _StringSinkCloseCallback(); + +/** + * This class wraps an existing [StringSink] and invokes a + * closure when [close] is invoked. + */ +class _ClosableStringSink implements ClosableStringSink { + final _StringSinkCloseCallback _callback; + final StringSink _sink; + + _ClosableStringSink(this._sink, this._callback); + + void close() { + _callback(); + } + + void writeCharCode(int charCode) { + _sink.writeCharCode(charCode); + } + + void write(Object o) { + _sink.write(o); + } + + void writeln([Object o = ""]) { + _sink.writeln(o); + } + + void writeAll(Iterable objects, [String separator = ""]) { + _sink.writeAll(objects, separator); + } +} + +/** + * This class wraps an existing [StringConversionSink] and exposes a + * [ClosableStringSink] interface. The wrapped sink only needs to implement + * `add` and `close`. + */ +// TODO(floitsch): make this class public? +class _StringConversionSinkAsStringSinkAdapter implements ClosableStringSink { + static const _MIN_STRING_SIZE = 16; + + StringBuffer _buffer; + StringConversionSink _chunkedSink; + + _StringConversionSinkAsStringSinkAdapter(this._chunkedSink) + : _buffer = new StringBuffer(); + + void close() { + if (_buffer.isNotEmpty) _flush(); + _chunkedSink.close(); + } + + void writeCharCode(int charCode) { + _buffer.writeCharCode(charCode); + if (_buffer.length > _MIN_STRING_SIZE) _flush(); + } + + void write(Object o) { + if (_buffer.isNotEmpty) _flush(); + _chunkedSink.add(o.toString()); + } + + void writeln([Object o = ""]) { + _buffer.writeln(o); + if (_buffer.length > _MIN_STRING_SIZE) _flush(); + } + + void writeAll(Iterable objects, [String separator = ""]) { + if (_buffer.isNotEmpty) _flush(); + Iterator iterator = objects.iterator; + if (!iterator.moveNext()) return; + if (separator.isEmpty) { + do { + _chunkedSink.add(iterator.current.toString()); + } while (iterator.moveNext()); + } else { + _chunkedSink.add(iterator.current.toString()); + while (iterator.moveNext()) { + write(separator); + _chunkedSink.add(iterator.current.toString()); + } + } + } + + void _flush() { + String accumulated = _buffer.toString(); + _buffer.clear(); + _chunkedSink.add(accumulated); + } +} + +/** + * This class provides a base-class for converters that need to accept String + * inputs. + */ +abstract class StringConversionSinkBase extends StringConversionSinkMixin {} + +/** + * This class provides a mixin for converters that need to accept String + * inputs. + */ +abstract class StringConversionSinkMixin implements StringConversionSink { + void addSlice(String str, int start, int end, bool isLast); + void close(); + + void add(String str) { + addSlice(str, 0, str.length, false); + } + + ByteConversionSink asUtf8Sink(bool allowMalformed) { + return new _Utf8ConversionSink(this, allowMalformed); + } + + ClosableStringSink asStringSink() { + return new _StringConversionSinkAsStringSinkAdapter(this); + } +} + +/** + * This class is a [StringConversionSink] that wraps a [StringSink]. + */ +class _StringSinkConversionSink extends StringConversionSinkBase { + StringSink _stringSink; + _StringSinkConversionSink(this._stringSink); + + void close() {} + void addSlice(String str, int start, int end, bool isLast) { + if (start != 0 || end != str.length) { + for (int i = start; i < end; i++) { + _stringSink.writeCharCode(str.codeUnitAt(i)); + } + } else { + _stringSink.write(str); + } + if (isLast) close(); + } + + void add(String str) { + _stringSink.write(str); + } + + ByteConversionSink asUtf8Sink(bool allowMalformed) { + return new _Utf8StringSinkAdapter(this, _stringSink, allowMalformed); + } + + ClosableStringSink asStringSink() { + return new ClosableStringSink.fromStringSink(_stringSink, this.close); + } +} + +/** + * This class accumulates all chunks into one string + * and invokes a callback when the sink is closed. + * + * This class can be used to terminate a chunked conversion. + */ +class _StringCallbackSink extends _StringSinkConversionSink { + final _ChunkedConversionCallback _callback; + _StringCallbackSink(this._callback) : super(new StringBuffer()); + + void close() { + StringBuffer buffer = _stringSink; + String accumulated = buffer.toString(); + buffer.clear(); + _callback(accumulated); + } + + ByteConversionSink asUtf8Sink(bool allowMalformed) { + return new _Utf8StringSinkAdapter(this, _stringSink, allowMalformed); + } +} + +/** + * This class adapts a simple [ChunkedConversionSink] to a + * [StringConversionSink]. + * + * All additional methods of the [StringConversionSink] (compared to the + * ChunkedConversionSink) are redirected to the `add` method. + */ +class _StringAdapterSink extends StringConversionSinkBase { + final Sink _sink; + + _StringAdapterSink(this._sink); + + void add(String str) { + _sink.add(str); + } + + void addSlice(String str, int start, int end, bool isLast) { + if (start == 0 && end == str.length) { + add(str); + } else { + add(str.substring(start, end)); + } + if (isLast) close(); + } + + void close() { + _sink.close(); + } +} + +/** + * Decodes UTF-8 code units and stores them in a [StringSink]. + */ +class _Utf8StringSinkAdapter extends ByteConversionSink { + final _Utf8Decoder _decoder; + final Sink _sink; + + _Utf8StringSinkAdapter(this._sink, StringSink stringSink, bool allowMalformed) + : _decoder = new _Utf8Decoder(stringSink, allowMalformed); + + void close() { + _decoder.close(); + if (_sink != null) _sink.close(); + } + + void add(List chunk) { + addSlice(chunk, 0, chunk.length, false); + } + + void addSlice( + List codeUnits, int startIndex, int endIndex, bool isLast) { + _decoder.convert(codeUnits, startIndex, endIndex); + if (isLast) close(); + } +} + +/** + * Decodes UTF-8 code units. + * + * Forwards the decoded strings to the given [StringConversionSink]. + */ +// TODO(floitsch): make this class public? +class _Utf8ConversionSink extends ByteConversionSink { + final _Utf8Decoder _decoder; + final StringConversionSink _chunkedSink; + final StringBuffer _buffer; + _Utf8ConversionSink(StringConversionSink sink, bool allowMalformed) + : this._(sink, new StringBuffer(), allowMalformed); + + _Utf8ConversionSink._( + this._chunkedSink, StringBuffer stringBuffer, bool allowMalformed) + : _decoder = new _Utf8Decoder(stringBuffer, allowMalformed), + _buffer = stringBuffer; + + void close() { + _decoder.close(); + if (_buffer.isNotEmpty) { + String accumulated = _buffer.toString(); + _buffer.clear(); + _chunkedSink.addSlice(accumulated, 0, accumulated.length, true); + } else { + _chunkedSink.close(); + } + } + + void add(List chunk) { + addSlice(chunk, 0, chunk.length, false); + } + + void addSlice(List chunk, int startIndex, int endIndex, bool isLast) { + _decoder.convert(chunk, startIndex, endIndex); + if (_buffer.isNotEmpty) { + String accumulated = _buffer.toString(); + _chunkedSink.addSlice(accumulated, 0, accumulated.length, isLast); + _buffer.clear(); + return; + } + if (isLast) close(); + } +} +dNN<6%J?P;LLQM7IJA!&J*@8HQ6/HQ%I7KFO5);$:,3%#"=(EL+O&%>&&%%5&$"5=&*& 7% 5$7-#N MI K>)7:&?EC/?+*6 7J&K53=>6C',7J;I><"?+ &?:QA&-H7E+7+F:IC /G -N3/Ilfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dartB// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Patch file for dart:convert library. + +import 'dart:_js_helper' show argumentErrorValue, patch; +import 'dart:_foreign_helper' show JS; +import 'dart:_interceptors' show JSExtendableArray; +import 'dart:_internal' show MappedIterable, ListIterable; +import 'dart:collection' show Maps, LinkedHashMap, MapBase; +import 'dart:_native_typed_data' show NativeUint8List; + +/** + * Parses [json] and builds the corresponding parsed JSON value. + * + * Parsed JSON values Nare of the types [num], [String], [bool], [Null], + * [List]s of parsed JSON values or [Map]s from [String] to parsed + * JSON values. + * + * The optional [reviver] function, if provided, is called once for each object + * or list property parsed. The arguments are the property name ([String]) or + * list index ([int]), and the value is the parsed value. The return value of + * the reviver will be used as the value of that property instead of the parsed + * value. The top level value is passed to the reviver with the empty string as + * a key. + * + * Throws [FormatException] if the input is not valid JSON text. + */ +@patch +_parseJson(String source, reviver(Object key, Object value)) { + if (source is! String) throw argumentErrorValue(source); + + var parsed; + try { + parsed = JS('=Object|JSExtendableArray|Null|bool|num|String', + 'JSON.parse(#)', source); + } catch (e) { + throw FormatException(JS('String', 'String(#)', e)); + } + + if (reviver == null) { + return _convertJsonToDartLazy(parsed); + } else { + return _convertJsonToDart(parsed, reviver); + } +} + +/** + * Walks the raw JavaScript value [json], replacing JavaScript Objects with + * Maps. [json] is expected to be freshly allocated so elements can be replaced + * in-place. + */ +_convertJsonToDart(json, reviver(Object key, Object value)) { + assert(reviver != null); + walk(e) { + // JavaScript null, string, number, bool are in the correct representation. + if (JS('bool', '# == null', e) || JS('bool', 'typeof # != "object"', e)) { + return e; + } + + // This test is needed to avoid identifying '{"__proto__":[]}' as an Array. + // TODO(sra): Replace this test with cheaper '#.constructor === Array' when + // bug 621 below is fixed. + if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) { + // In-place update of the elements since JS Array is a Dart List. + for (int i = 0; i < JS('int', '#.length', e); i++) { + // Use JS indexing to avoid range checks. We know this is the only + // reference to the list, but the compiler will likely never be able to + // tell that this instance of the list cannot have its length changed by + // the reviver even though it later will be passed to the reviver at the + // outer level. + var item = JS('', '#[#]', e, i); + JS('', '#[#]=#', e, i, reviver(i, walk(item))); + } + return e; + } + + // Otherwise it is a plain object, so copy to a JSON map, so we process + // and revive all entries recursively. + _JsonMap map = _JsonMap(e); + var processed = map._processed; + List keys = map._computeKeys(); + for (int i = 0; i < keys.length; i++) { + String key = keys[i]; + var revived = reviver(key, walk(JS('', '#[#]', e, key))); + JS('', '#[#]=#', processed, key, revived); + } + + // Update the JSON map structure so future access is cheaper. + map._original = processed; // Don't keep two objects around. + return map; + } + + return reviver(null, walk(json)); +} + +_convertJsonToDartLazy(object) { + // JavaScript null and undefined are represented as null. + if (object == null) return null; + + // JavaScript string, number, bool already has the correct representation. + if (JS('bool', 'typeof # != "object"', object)) { + return object; + } + + // This test is needed to avoid identifying '{"__proto__":[]}' as an array. + // TODO(sra): Replace this test with cheaper '#.constructor === Array' when + // bug https://code.google.com/p/v8/issues/detail?id=621 is fixed. + if (JS('bool', 'Object.getPrototypeOf(#) !== Array.prototype', object)) { + return _JsonMap(object); + } + + // Update the elements in place since JS arrays are Dart lists. + for (int i = 0; i < JS('int', '#.length', object); i++) { + // Use JS indexing to avoid range checks. We know this is the only + // reference to the list, but the compiler will likely never be able to + // tell that this instance of the list cannot have its length changed by + // the reviver even though it later will be passed to the reviver at the + // outer level. + var item = JS('', '#[#]', object, i); + JS('', '#[#]=#', object, i, _convertJsonToDartLazy(item)); + } + return object; +} + +class _JsonMap extends MapBase { + // The original JavaScript object remains unchanged until + // the map is eventually upgraded, in which case we null it + // out to reclaim the memory used by it. + var _original; + + // We keep track of the map entries that we have already + // processed by adding them to a separate JavaScript object. + var _processed = _newJavaScriptObject(); + + // If the data slot isn't null, it represents either the list + // of keys (for non-upgraded JSON maps) or the upgraded map. + var _data = null; + + _JsonMap(this._original); + + operator [](key) { + if (_isUpgraded) { + return _upgradedMap[key]; + } else if (key is! String) { + return null; + } else { + var result = _getProperty(_processed, key); + if (_isUnprocessed(result)) result = _process(key); + return result; + } + } + + int get length => _isUpgraded ? _upgradedMap.length : _computeKeys().length; + + bool get isEmpty => length == 0; + bool get isNotEmpty => length > 0; + + Iterable get keys { + if (_isUpgraded) return _upgradedMap.keys; + return _JsonMapKeyIterable(this); + } + + Iterable get values { + if (_isUpgraded) return _upgradedMap.values; + return MappedIterable(_computeKeys(), (each) => this[each]); + } + + operator []=(key, value) { + if (_isUpgraded) { + _upgradedMap[key] = value; + } else if (containsKey(key)) { + var processed = _processed; + _setProperty(processed, key, value); + var original = _original; + if (!identical(original, processed)) { + _setProperty(original, key, null); // Reclaim memory. + } + } else { + _upgrade()[key] = value; + } + } + + void addAll(Map other) { + other.forEach((key, value) { + this[key] = value; + }); + } + + bool containsValue(value) { + if (_isUpgraded) return _upgradedMap.containsValue(value); + List keys = _computeKeys(); + for (int i = 0; i < keys.length; i++) { + String key = keys[i]; + if (this[key] == value) return true; + } + return false; + } + + bool containsKey(key) { + if (_isUpgraded) return _upgradedMap.containsKey(key); + if (key is! String) return false; + return _hasProperty(_original, key); + } + + putIfAbsent(key, ifAbsent()) { + if (containsKey(key)) return this[key]; + var value = ifAbsent(); + this[key] = value; + return value; + } + + remove(Object key) { + if (!_isUpgraded && !containsKey(key)) return null; + return _upgrade().remove(key); + } + + void clear() { + if (_isUpgraded) { + _upgradedMap.clear(); + } else { + if (_data != null) { + // Clear the list of keys to make sure we force + // a concurrent modification error if anyone is + // currently iterating over it. + _data.clear(); + } + _original = _processed = null; + _data = {}; + } + } + + void forEach(void f(String key, value)) { + if (_isUpgraded) return _upgradedMap.forEach(f); + List keys = _computeKeys(); + for (int i = 0; i < keys.length; i++) { + String key = keys[i]; + + // Compute the value under the assumption that the property + // is present but potentially not processed. + var value = _getProperty(_processed, key); + if (_isUnprocessed(value)) { + value = _convertJsonToDartLazy(_getProperty(_original, key)); + _setProperty(_processed, key, value); + } + + // Do the callback. + f(key, value); + + // Check if invoking the callback function changed + // the key set. If so, throw an exception. + if (!identical(keys, _data)) { + throw ConcurrentModificationError(this); + } + } + } + + // ------------------------------------------ + // Private helper methods. + // ------------------------------------------ + + bool get _isUpgraded => _processed == null; + + Map get _upgradedMap { + assert(_isUpgraded); + // 'cast' the union type to LinkedHashMap. It would be even better if we + // could 'cast' to the implementation type, since LinkedHashMap includes + // _JsonMap. + return JS('LinkedHashMap', '#', _data); + } + + List _computeKeys() { + assert(!_isUpgraded); + List keys = _data; + if (keys == null) { + keys = _data = _getPropertyNames(_original); + } + return JS('JSExtendableArray', '#', keys); + } + + Map _upgrade() { + if (_isUpgraded) return _upgradedMap; + + // Copy all the (key, value) pairs to a freshly allocated + // linked hash map thus preserving the ordering. + var result = {}; + List keys = _computeKeys(); + for (int i = 0; i < keys.length; i++) { + String key = keys[i]; + result[key] = this[key]; + } + + // We only upgrade when we need to extend the map, so we can + // safely force a concurrent modification error in case + // someone is iterating over the map here. + if (keys.isEmpty) { + keys.add(null); + } else { + keys.clear(); + } + + // Clear out the associated JavaScript objects and mark the + // map as having been upgraded. + _original = _processed = null; + _data = result; + assert(_isUpgraded); + return result; + } + + _process(String key) { + if (!_hasProperty(_original, key)) return null; + var result = _convertJsonToDartLazy(_getProperty(_original, key)); + return _setProperty(_processed, key, result); + } + + // ------------------------------------------ + // Private JavaScript helper methods. + // ------------------------------------------ + + static bool _hasProperty(object, String key) => + JS('bool', 'Object.prototype.hasOwnProperty.call(#,#)', object, key); + static _getProperty(object, String key) => JS('', '#[#]', object, key); + static _setProperty(object, String key, value) => + JS('', '#[#]=#', object, key, value); + static List _getPropertyNames(object) => + JS('JSExtendableArray', 'Object.keys(#)', object); + static bool _isUnprocessed(object) => + JS('bool', 'typeof(#)=="undefined"', object); + static _newJavaScriptObject() => JS('=Object', 'Object.create(null)'); +} + +class _JsonMapKeyIterable extends ListIterable { + final _JsonMap _parent; + + _JsonMapKeyIterable(this._parent); + + int get length => _parent.length; + + String elementAt(int index) { + return _parent._isUpgraded + ? _parent.keys.elementAt(index) + : _parent._computeKeys()[index]; + } + + /// Although [ListIterable] defines its own iterator, we return the iterator + /// of the underlying list [_keys] in order to propagate + /// [ConcurrentModificationError]s. + Iterator get iterator { + return _parent._isUpgraded + ? _parent.keys.iterator + : _parent._computeKeys().iterator; + } + + /// Delegate to [parent.containsKey] to ensure the performance expected + /// from [Map.keys.containsKey]. + bool contains(Object key) => _parent.containsKey(key); +} + +@patch +class JsonDecoder { + @patch + StringConversionSink startChunkedConversion(Sink sink) { + return _JsonDecoderSink(_reviver, sink); + } +} + +/** + * Implements the chunked conversion from a JSON string to its corresponding + * object. + * + * The sink only creates one object, but its input can be chunked. + */ +// TODO(floitsch): don't accumulate everything before starting to decode. +class _JsonDecoderSink extends _StringSinkConversionSink { + final _Reviver _reviver; + final Sink _sink; + + _JsonDecoderSink(this._reviver, this._sink) : super(StringBuffer('')); + + void close() { + super.close(); + StringBuffer buffer = _stringSink; + String accumulated = buffer.toString(); + buffer.clear(); + Object decoded = _parseJson(accumulated, _reviver); + _sink.add(decoded); + _sink.close(); + } +} + +@patch +class Utf8Decoder { + @patch + Converter, T> fuse(Converter next) { + return super.fuse(next); + } + + // Currently not intercepting UTF8 decoding. + @patch + static String _convertIntercepted( + bool allowMalformed, List codeUnits, int start, int end) { + // Test `codeUnits is NativeUint8List`. Dart's NativeUint8List is + // implemented by JavaScript's Uint8Array. + if (JS('bool', '# instanceof Uint8Array', codeUnits)) { + // JS 'cast' to avoid a downcast equivalent to the is-check we hand-coded. + NativeUint8List casted = JS('NativeUint8List', '#', codeUnits); + return _convertInterceptedUint8List(allowMalformed, casted, start, end); + } + } + + static String _convertInterceptedUint8List( + bool allowMalformed, NativeUint8List codeUnits, int start, int end) { + if (allowMalformed) { + // TextDecoder with option {fatal: false} does not produce the same result + // as [Utf8Decoder]. It disagrees on the number of `U+FFFD` (REPLACEMENT + // CHARACTER) generated for some malformed sequences. We could use + // TextDecoder with option {fatal: true}, catch the error, and re-try + // without acceleration. That turns out to be extremely slow (the Error + // captures a stack trace). + // TODO(31370): Bring Utf8Decoder into alignment with TextDecoder. + // TODO(sra): If we can't do that, can we detect valid input fast enough + // to use a check like the [_unsafe] check below? + return null; + } + + var decoder = _decoder; + if (decoder == null) return null; + if (0 == start && end == null) { + return _useTextDecoderChecked(decoder, codeUnits); + } + + int length = codeUnits.length; + end = RangeError.checkValidRange(start, end, length); + + if (0 == start && end == codeUnits.length) { + return _useTextDecoderChecked(decoder, codeUnits); + } + + return _useTextDecoderChecked(decoder, + JS('NativeUint8List', '#.subarray(#, #)', codeUnits, start, end)); + } + + static String _useTextDecoderChecked(decoder, NativeUint8List codeUnits) { + if (_unsafe(codeUnits)) return null; + return _useTextDecoderUnchecked(decoder, codeUnits); + } + + static String _useTextDecoderUnchecked(decoder, NativeUint8List codeUnits) { + // If the input is malformed, catch the exception and return `null` to fall + // back on unintercepted decoder. The fallback will either succeed in + // decoding, or report the problem better than TextDecoder. + try { + return JS('String', '#.decode(#)', decoder, codeUnits); + } catch (e) {} + return null; + } + + /// Returns `true` if [codeUnits] contains problematic encodings. + /// + /// TextDecoder behaves differently to [Utf8Encoder] when the input encodes a + /// surrogate (U+D800 through U+DFFF). TextDecoder considers the surrogate to + /// be an encoding error and, depending on the `fatal` option, either throws + /// and Error or encodes the surrogate as U+FFFD. [Utf8Decoder] does not + /// consider the surrogate to be an error and returns the code unit encoded by + /// the surrogate. + /// + /// Throwing an `Error` captures the stack, whoch makes it so expensive that + /// it is worth checking the input for surrogates and avoiding TextDecoder in + /// this case. + static bool _unsafe(NativeUint8List codeUnits) { + // Surrogates encode as (hex) ED Ax xx or ED Bx xx. + int limit = codeUnits.length - 2; + for (int i = 0; i < limit; i++) { + int unit1 = codeUnits[i]; + if (unit1 == 0xED) { + int unit2 = JS('!', '#', codeUnits[i + 1]); + if ((unit2 & 0xE0) == 0xA0) return true; + } + } + return false; + } + + //// TextDecoder is not defined on some browsers and on the stand-alone d8 and + /// jsshell engines. Use a lazy initializer to do feature detection once. + static final _decoder = () { + try { + // Use `{fatal: true}`. 'fatal' does not correspond exactly to + // `!allowMalformed`: TextDecoder rejects unpaired surrogates which + // [Utf8Decoder] accepts. In non-fatal mode, TextDecoder translates + // unpaired surrogates to REPLACEMENT CHARACTER (U+FFFD) whereas + // [Utf8Decoder] leaves the surrogate intact. + return JS('', 'new TextDecoder("utf-8", {fatal: true})'); + } catch (e) {} + return null; + }(); +} +NN<(9'4;<7AICPNOPQ +A?;B"9+ 0LP > POPPIH;LPQQ)8L+ $,,@1BA$!<#M4NNELB+;?+@? ! 2:O#%/&1A!#"+ -> ,!?(,+;&)!,8# 88(%,5(,B31#F.91%100.*NM, 3/$*>5&(,ADPPOKQOP38&& 41QL +EJKG4@Nfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/ascii.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * An instance of the default implementation of the [AsciiCodec]. + * + * This instance provides a convenient access to the most common ASCII + * use cases. + * + * Examples: + * ```dart + * var encoded = ascii.encode("This is ASCII!"); + * var decoded = ascii.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, + * 0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]); + * ``` + */ +const AsciiCodec ascii = const AsciiCodec(); + +const int _asciiMask = 0x7F; + +/** + * An [AsciiCodec] allows encoding strings as ASCII bytes + * and decoding ASCII bytes to strings. + */ +class AsciiCodec extends Encoding { + final bool _allowInvalid; + /** + * Instantiates a new [AsciiCodec]. + * + * If [allowInvalid] is true, the [decode] method and the converter + * returned by [decoder] will default to allowing invalid values. + * If allowing invalid values, the values will be decoded into the Unicode + * Replacement character (U+FFFD). If not, an exception will be thrown. + * Calls to the [decode] method can choose to override this default. + * + * Encoders will not accept invalid (non Latin-1) characters. + */ + const AsciiCodec({bool allowInvalid: false}) : _allowInvalid = allowInvalid; + + String get name => "us-ascii"; + + Uint8List encode(String source) => encoder.convert(source); + + /** + * Decodes the ASCII [bytes] (a list of unsigned 7-bit integers) to the + * corresponding string. + * + * If [bytes] contains values that are not in the range 0 .. 127, the decoder + * will eventually throw a [FormatException]. + * + * If [allowInvalid] is not provided, it defaults to the value used to create + * this [AsciiCodec]. + */ + String decode(List bytes, {bool allowInvalid}) { + if (allowInvalid == null) allowInvalid = _allowInvalid; + if (allowInvalid) { + return const AsciiDecoder(allowInvalid: true).convert(bytes); + } else { + return const AsciiDecoder(allowInvalid: false).convert(bytes); + } + } + + AsciiEncoder get encoder => const AsciiEncoder(); + + AsciiDecoder get decoder => _allowInvalid + ? const AsciiDecoder(allowInvalid: true) + : const AsciiDecoder(allowInvalid: false); +} + +// Superclass for [AsciiEncoder] and [Latin1Encoder]. +// Generalizes common operations that only differ by a mask; +class _UnicodeSubsetEncoder extends Converter> { + final int _subsetMask; + + const _UnicodeSubsetEncoder(this._subsetMask); + + /** + * Converts the [String] into a list of its code units. + * + * If [start] and [end] are provided, only the substring + * `string.substring(start, end)` is used as input to the conversion. + */ + Uint8List convert(String string, [int start = 0, int end]) { + int stringLength = string.length; + RangeError.checkValidRange(start, end, stringLength); + if (end == null) end = stringLength; + int length = end - start; + var result = new Uint8List(length); + for (int i = 0; i < length; i++) { + var codeUnit = string.codeUnitAt(start + i); + if ((codeUnit & ~_subsetMask) != 0) { + throw new ArgumentError("String contains invalid characters."); + } + result[i] = codeUnit; + } + return result; + } + + /** + * Starts a chunked conversion. + * + * The converter works more efficiently if the given [sink] is a + * [ByteConversionSink]. + */ + StringConversionSink startChunkedConversion(Sink> sink) { + if (sink is! ByteConversionSink) { + sink = new ByteConversionSink.from(sink); + } + return new _UnicodeSubsetEncoderSink(_subsetMask, sink); + } + + // Override the base-class' bind, to provide a better type. + Stream> bind(Stream stream) => super.bind(stream); +} + +/** + * This class converts strings of only ASCII characters to bytes. + */ +class AsciiEncoder extends _UnicodeSubsetEncoder { + const AsciiEncoder() : super(_asciiMask); +} + +/** + * This class encodes chunked strings to bytes (unsigned 8-bit + * integers). + */ +class _UnicodeSubsetEncoderSink extends StringConversionSinkBase { + final ByteConversionSink _sink; + final int _subsetMask; + + _UnicodeSubsetEncoderSink(this._subsetMask, this._sink); + + void close() { + _sink.close(); + } + + void addSlice(String source, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, source.length); + for (int i = start; i < end; i++) { + int codeUnit = source.codeUnitAt(i); + if ((codeUnit & ~_subsetMask) != 0) { + throw new ArgumentError( + "Source contains invalid character with code point: $codeUnit."); + } + } + _sink.add(source.codeUnits.sublist(start, end)); + if (isLast) { + close(); + } + } +} + +/** + * This class converts Latin-1 bytes (lists of unsigned 8-bit integers) + * to a string. + */ +abstract class _UnicodeSubsetDecoder extends Converter, String> { + final bool _allowInvalid; + final int _subsetMask; + + /** + * Instantiates a new decoder. + * + * The [_allowInvalid] argument defines how [convert] deals + * with invalid bytes. + * + * The [_subsetMask] argument is a bit mask used to define the subset + * of Unicode being decoded. Use [_LATIN1_MASK] for Latin-1 (8-bit) or + * [_asciiMask] for ASCII (7-bit). + * + * If [_allowInvalid] is `true`, [convert] replaces invalid bytes with the + * Unicode Replacement character `U+FFFD` (�). + * Otherwise it throws a [FormatException]. + */ + const _UnicodeSubsetDecoder(this._allowInvalid, this._subsetMask); + + /** + * Converts the [bytes] (a list of unsigned 7- or 8-bit integers) to the + * corresponding string. + * + * If [start] and [end] are provided, only the sub-list of bytes from + * `start` to `end` (`end` not inclusive) is used as input to the conversion. + */ + String convert(List bytes, [int start = 0, int end]) { + int byteCount = bytes.length; + RangeError.checkValidRange(start, end, byteCount); + if (end == null) end = byteCount; + + for (int i = start; i < end; i++) { + int byte = bytes[i]; + if ((byte & ~_subsetMask) != 0) { + if (!_allowInvalid) { + throw new FormatException("Invalid value in input: $byte"); + } + return _convertInvalid(bytes, start, end); + } + } + return new String.fromCharCodes(bytes, start, end); + } + + String _convertInvalid(List bytes, int start, int end) { + StringBuffer buffer = new StringBuffer(); + for (int i = start; i < end; i++) { + int value = bytes[i]; + if ((value & ~_subsetMask) != 0) value = 0xFFFD; + buffer.writeCharCode(value); + } + return buffer.toString(); + } + + /** + * Starts a chunked conversion. + * + * The converter works more efficiently if the given [sink] is a + * [StringConversionSink]. + */ + ByteConversionSink startChunkedConversion(Sink sink); + + // Override the base-class's bind, to provide a better type. + Stream bind(Stream> stream) => super.bind(stream); +} + +class AsciiDecoder extends _UnicodeSubsetDecoder { + const AsciiDecoder({bool allowInvalid: false}) + : super(allowInvalid, _asciiMask); + + /** + * Starts a chunked conversion. + * + * The converter works more efficiently if the given [sink] is a + * [StringConversionSink]. + */ + ByteConversionSink startChunkedConversion(Sink sink) { + StringConversionSink stringSink; + if (sink is StringConversionSink) { + stringSink = sink; + } else { + stringSink = new StringConversionSink.from(sink); + } + // TODO(lrn): Use asUtf16Sink when it becomes available. It + // works just as well, is likely to have less decoding overhead, + // and make adding U+FFFD easier. + // At that time, merge this with _Latin1DecoderSink; + if (_allowInvalid) { + return new _ErrorHandlingAsciiDecoderSink(stringSink.asUtf8Sink(false)); + } else { + return new _SimpleAsciiDecoderSink(stringSink); + } + } +} + +class _ErrorHandlingAsciiDecoderSink extends ByteConversionSinkBase { + ByteConversionSink _utf8Sink; + _ErrorHandlingAsciiDecoderSink(this._utf8Sink); + + void close() { + _utf8Sink.close(); + } + + void add(List source) { + addSlice(source, 0, source.length, false); + } + + void addSlice(List source, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, source.length); + for (int i = start; i < end; i++) { + if ((source[i] & ~_asciiMask) != 0) { + if (i > start) _utf8Sink.addSlice(source, start, i, false); + // Add UTF-8 encoding of U+FFFD. + _utf8Sink.add(const [0xEF, 0xBF, 0xBD]); + start = i + 1; + } + } + if (start < end) { + _utf8Sink.addSlice(source, start, end, isLast); + } else if (isLast) { + close(); + } + } +} + +class _SimpleAsciiDecoderSink extends ByteConversionSinkBase { + Sink _sink; + _SimpleAsciiDecoderSink(this._sink); + + void close() { + _sink.close(); + } + + void add(List source) { + for (int i = 0; i < source.length; i++) { + if ((source[i] & ~_asciiMask) != 0) { + throw new FormatException("Source contains non-ASCII bytes."); + } + } + _sink.add(new String.fromCharCodes(source)); + } + + void addSlice(List source, int start, int end, bool isLast) { + final int length = source.length; + RangeError.checkValidRange(start, end, length); + if (start < end) { + if (start != 0 || end != length) { + source = source.sublist(start, end); + } + add(source); + } + if (isLast) close(); + } +} +;NN<BG 1IK-:($&FDMJG@O!>JP0P8<D E4,/16=C1:;H?&:)('3,H"CF'0=>GB3,?C";B;(+,!N5HL!>HI%M1.EKHP>"7&((F +38@.(7#"C@?G31)"CA%( 8@E&9O 6F 2/E;(,D)66?'.,G1E&4)-Ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/base64.dart{// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder. + * + * It encodes using the default base64 alphabet, + * decodes using both the base64 and base64url alphabets, + * does not allow invalid characters and requires padding. + * + * Examples: + * + * var encoded = base64.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6, + * 0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]); + * var decoded = base64.decode("YmzDpWLDpnJncsO4ZAo="); + */ +const Base64Codec base64 = const Base64Codec(); + +/** + * A [base64url](https://tools.ietf.org/html/rfc4648) encoder and decoder. + * + * It encodes and decodes using the base64url alphabet, + * decodes using both the base64 and base64url alphabets, + * does not allow invalid characters and requires padding. + * + * Examples: + * + * var encoded = base64Url.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6, + * 0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]); + * var decoded = base64Url.decode("YmzDpWLDpnJncsO4ZAo="); + */ +const Base64Codec base64Url = const Base64Codec.urlSafe(); + +/** + * Encodes [bytes] using [base64](https://tools.ietf.org/html/rfc4648) encoding. + * + * Shorthand for [base64.encode]. + */ +String base64Encode(List bytes) => base64.encode(bytes); + +/** + * Encodes [bytes] using [base64url](https://tools.ietf.org/html/rfc4648) encoding. + * + * Shorthand for [base64url.encode]. + */ +String base64UrlEncode(List bytes) => base64Url.encode(bytes); + +/** + * Decodes [base64](https://tools.ietf.org/html/rfc4648) or [base64url](https://tools.ietf.org/html/rfc4648) encoded bytes. + * + * Shorthand for [base64.decode]. + */ +Uint8List base64Decode(String source) => base64.decode(source); + +// Constants used in more than one class. +const int _paddingChar = 0x3d; // '='. + +/** + * A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder. + * + * A [Base64Codec] allows base64 encoding bytes into ASCII strings and + * decoding valid encodings back to bytes. + * + * This implementation only handles the simplest RFC 4648 base64 and base64url + * encodings. + * It does not allow invalid characters when decoding and it requires, + * and generates, padding so that the input is always a multiple of four + * characters. + */ +class Base64Codec extends Codec, String> { + final Base64Encoder _encoder; + const Base64Codec() : _encoder = const Base64Encoder(); + const Base64Codec.urlSafe() : _encoder = const Base64Encoder.urlSafe(); + + Base64Encoder get encoder => _encoder; + + Base64Decoder get decoder => const Base64Decoder(); + + /** + * Decodes [encoded]. + * + * The input is decoded as if by `decoder.convert`. + * + * The returned [Uint8List] contains exactly the decoded bytes, + * so the [Uint8List.length] is precisely the number of decoded bytes. + * The [Uint8List.buffer] may be larger than the decoded bytes. + */ + Uint8List decode(String encoded) => decoder.convert(encoded); + + /** + * Validates and normalizes the base64 encoded data in [source]. + * + * Only acts on the substring from [start] to [end], with [end] + * defaulting to the end of the string. + * + * Normalization will: + * * Unescape any `%`-escapes. + * * Only allow valid characters (`A`-`Z`, `a`-`z`, `0`-`9`, `/` and `+`). + * * Normalize a `_` or `-` character to `/` or `+`. + * * Validate that existing padding (trailing `=` characters) is correct. + * * If no padding exists, add correct padding if necessary and possible. + * * Validate that the length is correct (a multiple of four). + */ + String normalize(String source, [int start = 0, int end]) { + end = RangeError.checkValidRange(start, end, source.length); + const int percent = 0x25; + const int equals = 0x3d; + StringBuffer buffer = null; + int sliceStart = start; + var alphabet = _Base64Encoder._base64Alphabet; + var inverseAlphabet = _Base64Decoder._inverseAlphabet; + int firstPadding = -1; + int firstPaddingSourceIndex = -1; + int paddingCount = 0; + for (int i = start; i < end;) { + int sliceEnd = i; + int char = source.codeUnitAt(i++); + int originalChar = char; + // Normalize char, keep originalChar to see if it matches the source. + if (char == percent) { + if (i + 2 <= end) { + char = parseHexByte(source, i); // May be negative. + i += 2; + // We know that %25 isn't valid, but our table considers it + // a potential padding start, so skip the checks. + if (char == percent) char = -1; + } else { + // An invalid HEX escape (too short). + // Just skip past the handling and reach the throw below. + char = -1; + } + } + // If char is negative here, hex-decoding failed in some way. + if (0 <= char && char <= 127) { + int value = inverseAlphabet[char]; + if (value >= 0) { + char = alphabet.codeUnitAt(value); + if (char == originalChar) continue; + } else if (value == _Base64Decoder._padding) { + // We have ruled out percent, so char is '='. + if (firstPadding < 0) { + // Mark position in normalized output where padding occurs. + firstPadding = (buffer?.length ?? 0) + (sliceEnd - sliceStart); + firstPaddingSourceIndex = sliceEnd; + } + paddingCount++; + // It could have been an escaped equals (%3D). + if (originalChar == equals) continue; + } + if (value != _Base64Decoder._invalid) { + buffer ??= new StringBuffer(); + buffer.write(source.substring(sliceStart, sliceEnd)); + buffer.writeCharCode(char); + sliceStart = i; + continue; + } + } + throw new FormatException("Invalid base64 data", source, sliceEnd); + } + if (buffer != null) { + buffer.write(source.substring(sliceStart, end)); + if (firstPadding >= 0) { + // There was padding in the source. Check that it is valid: + // * result length a multiple of four + // * one or two padding characters at the end. + _checkPadding(source, firstPaddingSourceIndex, end, firstPadding, + paddingCount, buffer.length); + } else { + // Length of last chunk (1-4 chars) in the encoding. + int endLength = ((buffer.length - 1) % 4) + 1; + if (endLength == 1) { + // The data must have length 0, 2 or 3 modulo 4. + throw new FormatException( + "Invalid base64 encoding length ", source, end); + } + while (endLength < 4) { + buffer.write("="); + endLength++; + } + } + return source.replaceRange(start, end, buffer.toString()); + } + // Original was already normalized, only check padding. + int length = end - start; + if (firstPadding >= 0) { + _checkPadding(source, firstPaddingSourceIndex, end, firstPadding, + paddingCount, length); + } else { + // No padding given, so add some if needed it. + int endLength = length % 4; + if (endLength == 1) { + // The data must have length 0, 2 or 3 modulo 4. + throw new FormatException( + "Invalid base64 encoding length ", source, end); + } + if (endLength > 1) { + // There is no "insertAt" on String, but this works as well. + source = source.replaceRange(end, end, (endLength == 2) ? "==" : "="); + } + } + return source; + } + + static void _checkPadding(String source, int sourceIndex, int sourceEnd, + int firstPadding, int paddingCount, int length) { + if (length % 4 != 0) { + throw new FormatException( + "Invalid base64 padding, padded length must be multiple of four, " + "is $length", + source, + sourceEnd); + } + if (firstPadding + paddingCount != length) { + throw new FormatException( + "Invalid base64 padding, '=' not at the end", source, sourceIndex); + } + if (paddingCount > 2) { + throw new FormatException( + "Invalid base64 padding, more than two '=' characters", + source, + sourceIndex); + } + } +} + +// ------------------------------------------------------------------------ +// Encoder +// ------------------------------------------------------------------------ + +/** + * Base64 and base64url encoding converter. + * + * Encodes lists of bytes using base64 or base64url encoding. + * + * The results are ASCII strings using a restricted alphabet. + */ +class Base64Encoder extends Converter, String> { + final bool _urlSafe; + + const Base64Encoder() : _urlSafe = false; + const Base64Encoder.urlSafe() : _urlSafe = true; + + String convert(List input) { + if (input.isEmpty) return ""; + var encoder = new _Base64Encoder(_urlSafe); + Uint8List buffer = encoder.encode(input, 0, input.length, true); + return new String.fromCharCodes(buffer); + } + + ByteConversionSink startChunkedConversion(Sink sink) { + if (sink is StringConversionSink) { + return new _Utf8Base64EncoderSink(sink.asUtf8Sink(false), _urlSafe); + } + return new _AsciiBase64EncoderSink(sink, _urlSafe); + } +} + +/** + * Helper class for encoding bytes to base64. + */ +class _Base64Encoder { + /** The RFC 4648 base64 encoding alphabet. */ + static const String _base64Alphabet = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + /** The RFC 4648 base64url encoding alphabet. */ + static const String _base64UrlAlphabet = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + + /** Shift-count to extract the values stored in [_state]. */ + static const int _valueShift = 2; + + /** Mask to extract the count value stored in [_state]. */ + static const int _countMask = 3; + + static const int _sixBitMask = 0x3F; + + /** + * Intermediate state between chunks. + * + * Encoding handles three bytes at a time. + * If fewer than three bytes has been seen, this value encodes + * the number of bytes seen (0, 1 or 2) and their values. + */ + int _state = 0; + + /** Alphabet used for encoding. */ + final String _alphabet; + + _Base64Encoder(bool urlSafe) + : _alphabet = urlSafe ? _base64UrlAlphabet : _base64Alphabet; + + /** Encode count and bits into a value to be stored in [_state]. */ + static int _encodeState(int count, int bits) { + assert(count <= _countMask); + return bits << _valueShift | count; + } + + /** Extract bits from encoded state. */ + static int _stateBits(int state) => state >> _valueShift; + + /** Extract count from encoded state. */ + static int _stateCount(int state) => state & _countMask; + + /** + * Create a [Uint8List] with the provided length. + */ + Uint8List createBuffer(int bufferLength) => new Uint8List(bufferLength); + + /** + * Encode [bytes] from [start] to [end] and the bits in [_state]. + * + * Returns a [Uint8List] of the ASCII codes of the encoded data. + * + * If the input, including left over [_state] from earlier encodings, + * are not a multiple of three bytes, then the partial state is stored + * back into [_state]. + * If [isLast] is true, partial state is encoded in the output instead, + * with the necessary padding. + * + * Returns `null` if there is no output. + */ + Uint8List encode(List bytes, int start, int end, bool isLast) { + assert(0 <= start); + assert(start <= end); + assert(bytes == null || end <= bytes.length); + int length = end - start; + + int count = _stateCount(_state); + int byteCount = (count + length); + int fullChunks = byteCount ~/ 3; + int partialChunkLength = byteCount - fullChunks * 3; + int bufferLength = fullChunks * 4; + if (isLast && partialChunkLength > 0) { + bufferLength += 4; // Room for padding. + } + var output = createBuffer(bufferLength); + _state = + encodeChunk(_alphabet, bytes, start, end, isLast, output, 0, _state); + if (bufferLength > 0) return output; + // If the input plus the data in state is still less than three bytes, + // there may not be any output. + return null; + } + + static int encodeChunk(String alphabet, List bytes, int start, int end, + bool isLast, Uint8List output, int outputIndex, int state) { + int bits = _stateBits(state); + // Count number of missing bytes in three-byte chunk. + int expectedChars = 3 - _stateCount(state); + + // The input must be a list of bytes (integers in the range 0..255). + // The value of `byteOr` will be the bitwise or of all the values in + // `bytes` and a later check will validate that they were all valid bytes. + int byteOr = 0; + for (int i = start; i < end; i++) { + int byte = bytes[i]; + byteOr |= byte; + bits = ((bits << 8) | byte) & 0xFFFFFF; // Never store more than 24 bits. + expectedChars--; + if (expectedChars == 0) { + output[outputIndex++] = alphabet.codeUnitAt((bits >> 18) & _sixBitMask); + output[outputIndex++] = alphabet.codeUnitAt((bits >> 12) & _sixBitMask); + output[outputIndex++] = alphabet.codeUnitAt((bits >> 6) & _sixBitMask); + output[outputIndex++] = alphabet.codeUnitAt(bits & _sixBitMask); + expectedChars = 3; + bits = 0; + } + } + if (byteOr >= 0 && byteOr <= 255) { + if (isLast && expectedChars < 3) { + writeFinalChunk(alphabet, output, outputIndex, 3 - expectedChars, bits); + return 0; + } + return _encodeState(3 - expectedChars, bits); + } + + // There was an invalid byte value somewhere in the input - find it! + int i = start; + while (i < end) { + int byte = bytes[i]; + if (byte < 0 || byte > 255) break; + i++; + } + throw new ArgumentError.value( + bytes, "Not a byte value at index $i: 0x${bytes[i].toRadixString(16)}"); + } + + /** + * Writes a final encoded four-character chunk. + * + * Only used when the [_state] contains a partial (1 or 2 byte) + * input. + */ + static void writeFinalChunk( + String alphabet, Uint8List output, int outputIndex, int count, int bits) { + assert(count > 0); + if (count == 1) { + output[outputIndex++] = alphabet.codeUnitAt((bits >> 2) & _sixBitMask); + output[outputIndex++] = alphabet.codeUnitAt((bits << 4) & _sixBitMask); + output[outputIndex++] = _paddingChar; + output[outputIndex++] = _paddingChar; + } else { + assert(count == 2); + output[outputIndex++] = alphabet.codeUnitAt((bits >> 10) & _sixBitMask); + output[outputIndex++] = alphabet.codeUnitAt((bits >> 4) & _sixBitMask); + output[outputIndex++] = alphabet.codeUnitAt((bits << 2) & _sixBitMask); + output[outputIndex++] = _paddingChar; + } + } +} + +class _BufferCachingBase64Encoder extends _Base64Encoder { + /** + * Reused buffer. + * + * When the buffer isn't released to the sink, only used to create another + * value (a string), the buffer can be reused between chunks. + */ + Uint8List bufferCache; + + _BufferCachingBase64Encoder(bool urlSafe) : super(urlSafe); + + Uint8List createBuffer(int bufferLength) { + if (bufferCache == null || bufferCache.length < bufferLength) { + bufferCache = new Uint8List(bufferLength); + } + // Return a view of the buffer, so it has the requested length. + return new Uint8List.view(bufferCache.buffer, 0, bufferLength); + } +} + +abstract class _Base64EncoderSink extends ByteConversionSinkBase { + void add(List source) { + _add(source, 0, source.length, false); + } + + void close() { + _add(null, 0, 0, true); + } + + void addSlice(List source, int start, int end, bool isLast) { + if (end == null) throw new ArgumentError.notNull("end"); + RangeError.checkValidRange(start, end, source.length); + _add(source, start, end, isLast); + } + + void _add(List source, int start, int end, bool isLast); +} + +class _AsciiBase64EncoderSink extends _Base64EncoderSink { + final Sink _sink; + final _Base64Encoder _encoder; + + _AsciiBase64EncoderSink(this._sink, bool urlSafe) + : _encoder = new _BufferCachingBase64Encoder(urlSafe); + + void _add(List source, int start, int end, bool isLast) { + Uint8List buffer = _encoder.encode(source, start, end, isLast); + if (buffer != null) { + String string = new String.fromCharCodes(buffer); + _sink.add(string); + } + if (isLast) { + _sink.close(); + } + } +} + +class _Utf8Base64EncoderSink extends _Base64EncoderSink { + final ByteConversionSink _sink; + final _Base64Encoder _encoder; + + _Utf8Base64EncoderSink(this._sink, bool urlSafe) + : _encoder = new _Base64Encoder(urlSafe); + + void _add(List source, int start, int end, bool isLast) { + Uint8List buffer = _encoder.encode(source, start, end, isLast); + if (buffer != null) { + _sink.addSlice(buffer, 0, buffer.length, isLast); + } + } +} + +// ------------------------------------------------------------------------ +// Decoder +// ------------------------------------------------------------------------ + +/** + * Decoder for base64 encoded data. + * + * This decoder accepts both base64 and base64url ("url-safe") encodings. + * + * The encoding is required to be properly padded. + */ +class Base64Decoder extends Converter> { + const Base64Decoder(); + + /** + * Decodes the characters of [input] from [start] to [end] as base64. + * + * If [start] is omitted, it defaults to the start of [input]. + * If [end] is omitted, it defaults to the end of [input]. + * + * The returned [Uint8List] contains exactly the decoded bytes, + * so the [Uint8List.length] is precisely the number of decoded bytes. + * The [Uint8List.buffer] may be larger than the decoded bytes. + */ + Uint8List convert(String input, [int start = 0, int end]) { + end = RangeError.checkValidRange(start, end, input.length); + if (start == end) return new Uint8List(0); + var decoder = new _Base64Decoder(); + Uint8List buffer = decoder.decode(input, start, end); + decoder.close(input, end); + return buffer; + } + + StringConversionSink startChunkedConversion(Sink> sink) { + return new _Base64DecoderSink(sink); + } +} + +/** + * Helper class implementing base64 decoding with intermediate state. + */ +class _Base64Decoder { + /** Shift-count to extract the values stored in [_state]. */ + static const int _valueShift = 2; + + /** Mask to extract the count value stored in [_state]. */ + static const int _countMask = 3; + + /** Invalid character in decoding table. */ + static const int _invalid = -2; + + /** Padding character in decoding table. */ + static const int _padding = -1; + + // Shorthands to make the table more readable. + static const int __ = _invalid; + static const int _p = _padding; + + /** + * Mapping from ASCII characters to their index in the base64 alphabet. + * + * Uses [_invalid] for invalid indices and [_padding] for the padding + * character. + * + * Accepts the "URL-safe" alphabet as well (`-` and `_` are the + * 62nd and 63rd alphabet characters), and considers `%` a padding + * character, which must then be followed by `3D`, the percent-escape + * for `=`. + */ + static final List _inverseAlphabet = new Int8List.fromList([ + __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // + __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // + __, __, __, __, __, _p, __, __, __, __, __, 62, __, 62, __, 63, // + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, __, __, __, _p, __, __, // + __, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, // + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, __, __, __, __, 63, // + __, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, __, __, __, __, __, // + ]); + + // Character constants. + static const int _char_percent = 0x25; // '%'. + static const int _char_3 = 0x33; // '3'. + static const int _char_d = 0x64; // 'd'. + + /** + * Maintains the intermediate state of a partly-decoded input. + * + * Base64 is decoded in chunks of four characters. If a chunk does not + * contain a full block, the decoded bits (six per character) of the + * available characters are stored in [_state] until the next call to + * [_decode] or [_close]. + * + * If no padding has been seen, the value is + * `numberOfCharactersSeen | (decodedBits << 2)` + * where `numberOfCharactersSeen` is between 0 and 3 and decoded bits + * contains six bits per seen character. + * + * If padding has been seen the value is negative. It's the bitwise negation + * of the number of remaining allowed padding characters (always ~0 or ~1). + * + * A state of `0` or `~0` are valid places to end decoding, all other values + * mean that a four-character block has not been completed. + */ + int _state = 0; + + /** + * Encodes [count] and [bits] as a value to be stored in [_state]. + */ + static int _encodeCharacterState(int count, int bits) { + assert(count == (count & _countMask)); + return (bits << _valueShift | count); + } + + /** + * Extracts count from a [_state] value. + */ + static int _stateCount(int state) { + assert(state >= 0); + return state & _countMask; + } + + /** + * Extracts value bits from a [_state] value. + */ + static int _stateBits(int state) { + assert(state >= 0); + return state >> _valueShift; + } + + /** + * Encodes a number of expected padding characters to be stored in [_state]. + */ + static int _encodePaddingState(int expectedPadding) { + assert(expectedPadding >= 0); + assert(expectedPadding <= 5); + return -expectedPadding - 1; // ~expectedPadding adapted to dart2js. + } + + /** + * Extracts expected padding character count from a [_state] value. + */ + static int _statePadding(int state) { + assert(state < 0); + return -state - 1; // ~state adapted to dart2js. + } + + static bool _hasSeenPadding(int state) => state < 0; + + /** + * Decodes [input] from [start] to [end]. + * + * Returns a [Uint8List] with the decoded bytes. + * If a previous call had an incomplete four-character block, the bits from + * those are included in decoding + */ + Uint8List decode(String input, int start, int end) { + assert(0 <= start); + assert(start <= end); + assert(end <= input.length); + if (_hasSeenPadding(_state)) { + _state = _checkPadding(input, start, end, _state); + return null; + } + if (start == end) return new Uint8List(0); + Uint8List buffer = _allocateBuffer(input, start, end, _state); + _state = decodeChunk(input, start, end, buffer, 0, _state); + return buffer; + } + + /** Checks that [_state] represents a valid decoding. */ + void close(String input, int end) { + if (_state < _encodePaddingState(0)) { + throw new FormatException("Missing padding character", input, end); + } + if (_state > 0) { + throw new FormatException( + "Invalid length, must be multiple of four", input, end); + } + _state = _encodePaddingState(0); + } + + /** + * Decodes [input] from [start] to [end]. + * + * Includes the state returned by a previous call in the decoding. + * Writes the decoding to [output] at [outIndex], and there must + * be room in the output. + */ + static int decodeChunk(String input, int start, int end, Uint8List output, + int outIndex, int state) { + assert(!_hasSeenPadding(state)); + const int asciiMask = 127; + const int asciiMax = 127; + const int eightBitMask = 0xFF; + const int bitsPerCharacter = 6; + + int bits = _stateBits(state); + int count = _stateCount(state); + // String contents should be all ASCII. + // Instead of checking for each character, we collect the bitwise-or of + // all the characters in `charOr` and later validate that all characters + // were ASCII. + int charOr = 0; + for (int i = start; i < end; i++) { + var char = input.codeUnitAt(i); + charOr |= char; + int code = _inverseAlphabet[char & asciiMask]; + if (code >= 0) { + bits = ((bits << bitsPerCharacter) | code) & 0xFFFFFF; + count = (count + 1) & 3; + if (count == 0) { + assert(outIndex + 3 <= output.length); + output[outIndex++] = (bits >> 16) & eightBitMask; + output[outIndex++] = (bits >> 8) & eightBitMask; + output[outIndex++] = bits & eightBitMask; + bits = 0; + } + continue; + } else if (code == _padding && count > 1) { + if (charOr < 0 || charOr > asciiMax) break; + if (count == 3) { + if ((bits & 0x03) != 0) { + throw new FormatException( + "Invalid encoding before padding", input, i); + } + output[outIndex++] = bits >> 10; + output[outIndex++] = bits >> 2; + } else { + if ((bits & 0x0F) != 0) { + throw new FormatException( + "Invalid encoding before padding", input, i); + } + output[outIndex++] = bits >> 4; + } + // Expected padding is the number of expected padding characters, + // where `=` counts as three and `%3D` counts as one per character. + // + // Expect either zero or one padding depending on count (2 or 3), + // plus two more characters if the code was `%` (a partial padding). + int expectedPadding = (3 - count) * 3; + if (char == _char_percent) expectedPadding += 2; + state = _encodePaddingState(expectedPadding); + return _checkPadding(input, i + 1, end, state); + } + throw new FormatException("Invalid character", input, i); + } + if (charOr >= 0 && charOr <= asciiMax) { + return _encodeCharacterState(count, bits); + } + // There is an invalid (non-ASCII) character in the input. + int i; + for (i = start; i < end; i++) { + int char = input.codeUnitAt(i); + if (char < 0 || char > asciiMax) break; + } + throw new FormatException("Invalid character", input, i); + } + + /** + * Allocates a buffer with room for the decoding of a substring of [input]. + * + * Includes room for the characters in [state], and handles padding correctly. + */ + static Uint8List _allocateBuffer( + String input, int start, int end, int state) { + assert(state >= 0); + int paddingStart = _trimPaddingChars(input, start, end); + int length = _stateCount(state) + (paddingStart - start); + // Three bytes per full four bytes in the input. + int bufferLength = (length >> 2) * 3; + // If padding was seen, then this is the last chunk, and the final partial + // chunk should be decoded too. + int remainderLength = length & 3; + if (remainderLength != 0 && paddingStart < end) { + bufferLength += remainderLength - 1; + } + if (bufferLength > 0) return new Uint8List(bufferLength); + // If the input plus state is less than four characters, and it's not + // at the end of input, no buffer is needed. + return null; + } + + /** + * Returns the position of the start of padding at the end of the input. + * + * Returns the end of input if there is no padding. + * + * This is used to ensure that the decoding buffer has the exact size + * it needs when input is valid, and at least enough bytes to reach the error + * when input is invalid. + * + * Never count more than two padding sequences since any more than that + * will raise an error anyway, and we only care about being precise for + * successful conversions. + */ + static int _trimPaddingChars(String input, int start, int end) { + // This may count '%=' as two paddings. That's ok, it will err later, + // but the buffer will be large enough to reach the error. + int padding = 0; + int index = end; + int newEnd = end; + while (index > start && padding < 2) { + index--; + int char = input.codeUnitAt(index); + if (char == _paddingChar) { + padding++; + newEnd = index; + continue; + } + if ((char | 0x20) == _char_d) { + if (index == start) break; + index--; + char = input.codeUnitAt(index); + } + if (char == _char_3) { + if (index == start) break; + index--; + char = input.codeUnitAt(index); + } + if (char == _char_percent) { + padding++; + newEnd = index; + continue; + } + break; + } + return newEnd; + } + + /** + * Check that the remainder of the string is valid padding. + * + * Valid padding is a correct number (0, 1 or 2) of `=` characters + * or `%3D` sequences depending on the number of preceding base64 characters. + * The [state] parameter encodes which padding continuations are allowed + * as the number of expected characters. That number is the number of + * expected padding characters times 3 minus the number of padding characters + * seen so far, where `=` counts as 3 counts as three characters, + * and the padding sequence `%3D` counts as one character per character. + * + * The number of missing characters is always between 0 and 5 because we + * only call this function after having seen at least one `=` or `%` + * character. + * If the number of missing characters is not 3 or 0, we have seen (at least) + * a `%` character and expects the rest of the `%3D` sequence, and a `=` is + * not allowed. When missing 3 characters, either `=` or `%` is allowed. + * + * When the value is 0, no more padding (or any other character) is allowed. + */ + static int _checkPadding(String input, int start, int end, int state) { + assert(_hasSeenPadding(state)); + if (start == end) return state; + int expectedPadding = _statePadding(state); + assert(expectedPadding >= 0); + assert(expectedPadding < 6); + while (expectedPadding > 0) { + int char = input.codeUnitAt(start); + if (expectedPadding == 3) { + if (char == _paddingChar) { + expectedPadding -= 3; + start++; + break; + } + if (char == _char_percent) { + expectedPadding--; + start++; + if (start == end) break; + char = input.codeUnitAt(start); + } else { + break; + } + } + // Partial padding means we have seen part of a "%3D" escape. + int expectedPartialPadding = expectedPadding; + if (expectedPartialPadding > 3) expectedPartialPadding -= 3; + if (expectedPartialPadding == 2) { + // Expects '3' + if (char != _char_3) break; + start++; + expectedPadding--; + if (start == end) break; + char = input.codeUnitAt(start); + } + // Expects 'D' or 'd'. + if ((char | 0x20) != _char_d) break; + start++; + expectedPadding--; + if (start == end) break; + } + if (start != end) { + throw new FormatException("Invalid padding character", input, start); + } + return _encodePaddingState(expectedPadding); + } +} + +class _Base64DecoderSink extends StringConversionSinkBase { + /** Output sink */ + final Sink> _sink; + final _Base64Decoder _decoder = new _Base64Decoder(); + + _Base64DecoderSink(this._sink); + + void add(String string) { + if (string.isEmpty) return; + Uint8List buffer = _decoder.decode(string, 0, string.length); + if (buffer != null) _sink.add(buffer); + } + + void close() { + _decoder.close(null, null); + _sink.close(); + } + + void addSlice(String string, int start, int end, bool isLast) { + end = RangeError.checkValidRange(start, end, string.length); + if (start == end) return; + Uint8List buffer = _decoder.decode(string, start, end); + if (buffer != null) _sink.add(buffer); + if (isLast) { + _decoder.close(string, end); + _sink.close(); + } + } +} +NN<H1:; NJ<0K8:; QM?;Q">T%D|"@*'HG+OGI5 :J)66BIB@CB*!M7LLA>A 3;&$)L>F<*0D +D&+-.78"HL0 90 +0)@& +J7D.7J*=7;%? +  +A<H! 5"9#=EOK8!M1!N!BL L,>>;,3$"0E-A(K8.0(J3+J?$=#'(-A<%DF1!(*<+;4KDCHIJ!+G2%&%9',.- N)K$OC":0IIO(P QQPI()Q4I) #Q2B QNN,, ONN,;M@>-D1DDC+E=;&@;!4=AD8:"!30AD8L L$J3;HA=BIB>@/(:F)F?$=#."."1""JHBEHDGGGGGGGG1++AIGH/5H+ONO>E:+*+&0%!O8""IF(57,3N$7!#9/C@;&+J!C%,ECM!%#$"$,LM(&5?!1<;4 +24$'> +*$'> * +JL JM/968@-1? $&.>NQ$5=>5*O$&6+>J1K6HPJJCJ?+*"&#(#(# >EPKHPDKKGPNKOJ$$0"!"*"$  +%#* +D4C)$!(+L1<8" B+ BA<+#Xfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/byte_conversion.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * The [ByteConversionSink] provides an interface for converters to + * efficiently transmit byte data. + * + * Instead of limiting the interface to one non-chunked list of bytes it + * accepts its input in chunks (themselves being lists of bytes). + * + * This abstract class will likely get more methods over time. Implementers are + * urged to extend or mix in [ByteConversionSinkBase] to ensure that their + * class covers the newly added methods. + */ +abstract class ByteConversionSink extends ChunkedConversionSink> { + ByteConversionSink(); + factory ByteConversionSink.withCallback( + void callback(List accumulated)) = _ByteCallbackSink; + factory ByteConversionSink.from(Sink> sink) = _ByteAdapterSink; + + /** + * Adds the next [chunk] to `this`. + * + * Adds the bytes defined by [start] and [end]-exclusive to `this`. + * + * If [isLast] is `true` closes `this`. + * + * Contrary to `add` the given [chunk] must not be held onto. Once the method + * returns, it is safe to overwrite the data in it. + */ + void addSlice(List chunk, int start, int end, bool isLast); + + // TODO(floitsch): add more methods: + // - iterateBytes. +} + +/** + * This class provides a base-class for converters that need to accept byte + * inputs. + */ +abstract class ByteConversionSinkBase extends ByteConversionSink { + void add(List chunk); + void close(); + + void addSlice(List chunk, int start, int end, bool isLast) { + add(chunk.sublist(start, end)); + if (isLast) close(); + } +} + +/** + * This class adapts a simple [Sink] to a [ByteConversionSink]. + * + * All additional methods of the [ByteConversionSink] (compared to the + * ChunkedConversionSink) are redirected to the `add` method. + */ +class _ByteAdapterSink extends ByteConversionSinkBase { + final Sink> _sink; + + _ByteAdapterSink(this._sink); + + void add(List chunk) { + _sink.add(chunk); + } + + void close() { + _sink.close(); + } +} + +/** + * This class accumulates all chunks into one list of bytes + * and invokes a callback when the sink is closed. + * + * This class can be used to terminate a chunked conversion. + */ +class _ByteCallbackSink extends ByteConversionSinkBase { + static const _INITIAL_BUFFER_SIZE = 1024; + + final _ChunkedConversionCallback> _callback; + List _buffer = new Uint8List(_INITIAL_BUFFER_SIZE); + int _bufferIndex = 0; + + _ByteCallbackSink(void callback(List accumulated)) + : this._callback = callback; + + void add(Iterable chunk) { + int freeCount = _buffer.length - _bufferIndex; + if (chunk.length > freeCount) { + // Grow the buffer. + int oldLength = _buffer.length; + int newLength = _roundToPowerOf2(chunk.length + oldLength) * 2; + List grown = new Uint8List(newLength); + grown.setRange(0, _buffer.length, _buffer); + _buffer = grown; + } + _buffer.setRange(_bufferIndex, _bufferIndex + chunk.length, chunk); + _bufferIndex += chunk.length; + } + + static int _roundToPowerOf2(int v) { + assert(v > 0); + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; + } + + void close() { + _callback(_buffer.sublist(0, _bufferIndex)); + } +} +yNN<D#IBPK)M+AL&F*P6C'L CD$@G>8 <3=9,9;:#"3$&F22H"'  1Nfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/codec.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * A [Codec] encodes and (if supported) decodes data. + * + * Codecs can be fused. For example fusing [json] and [utf8] produces + * an encoder that can convert Json objects directly to bytes, or can decode + * bytes directly to json objects. + * + * Fused codecs generally attempt to optimize the operations and can be faster + * than executing each step of an encoding separately. + */ +abstract class Codec { + const Codec(); + + /** + * Encodes [input]. + * + * The input is encoded as if by `encoder.convert`. + */ + T encode(S input) => encoder.convert(input); + + /** + * Decodes [encoded] data. + * + * The input is decoded as if by `decoder.convert`. + */ + S decode(T encoded) => decoder.convert(encoded); + + /** + * Returns the encoder from [S] to [T]. + * + * It may be stateful and should not be reused. + */ + Converter get encoder; + /** + * Returns the decoder of `this`, converting from [T] to [S]. + * + * It may be stateful and should not be reused. + */ + Converter get decoder; + + /** + * Fuses `this` with `other`. + * + * When encoding, the resulting codec encodes with `this` before + * encoding with [other]. + * + * When decoding, the resulting codec decodes with [other] before decoding + * with `this`. + * + * In some cases one needs to use the [inverted] codecs to be able to fuse + * them correctly. That is, the output type of `this` ([T]) must match the + * input type of the second codec [other]. + * + * Examples: + * ```dart + * final jsonToBytes = json.fuse(utf8); + * List bytes = jsonToBytes.encode(["json-object"]); + * var decoded = jsonToBytes.decode(bytes); + * assert(decoded is List && decoded[0] == "json-object"); + * + * var inverted = json.inverted; + * var jsonIdentity = json.fuse(inverted); + * var jsonObject = jsonIdentity.encode(["1", 2]); + * assert(jsonObject is List && jsonObject[0] == "1" && jsonObject[1] == 2); + * ``` + */ + // TODO(floitsch): use better example with line-splitter once that one is + // in this library. + Codec fuse(Codec other) { + return new _FusedCodec(this, other); + } + + /** + * Inverts `this`. + * + * The [encoder] and [decoder] of the resulting codec are swapped. + */ + Codec get inverted => new _InvertedCodec(this); +} + +/** + * Fuses the given codecs. + * + * In the non-chunked conversion simply invokes the non-chunked conversions in + * sequence. + */ +class _FusedCodec extends Codec { + final Codec _first; + final Codec _second; + + Converter get encoder => _first.encoder.fuse(_second.encoder); + Converter get decoder => _second.decoder.fuse(_first.decoder); + + _FusedCodec(this._first, this._second); +} + +class _InvertedCodec extends Codec { + final Codec _codec; + + _InvertedCodec(Codec codec) : _codec = codec; + + Converter get encoder => _codec.decoder; + Converter get decoder => _codec.encoder; + + Codec get inverted => _codec; +} +rNN<6FM#O76/63*2@2 CMMM- *<.=#-5O L+2E>O 1JJ*1611&Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/converter.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * A [Converter] converts data from one representation into another. + * + * It is recommended that implementations of `Converter` extend this class, + * to inherit any further methods that may be added to the class. + */ +abstract class Converter extends StreamTransformerBase { + const Converter(); + + /** + * Adapts [source] to be a `Converter`. + * + * This allows [source] to be used at the new type, but at run-time it + * must satisfy the requirements of both the new type and its original type. + * + * Conversion input must be both [SS] and [TS] and the output created by + * [source] for those input must be both [ST] and [TT]. + */ + static Converter castFrom(Converter source) => + new CastConverter(source); + + /** + * Converts [input] and returns the result of the conversion. + */ + T convert(S input); + + /** + * Fuses `this` with [other]. + * + * Encoding with the resulting converter is equivalent to converting with + * `this` before converting with `other`. + */ + Converter fuse(Converter other) { + return new _FusedConverter(this, other); + } + + /** + * Starts a chunked conversion. + * + * The returned sink serves as input for the long-running conversion. The + * given [sink] serves as output. + */ + Sink startChunkedConversion(Sink sink) { + throw new UnsupportedError( + "This converter does not support chunked conversions: $this"); + } + + Stream bind(Stream stream) { + return new Stream.eventTransformed( + stream, (EventSink sink) => new _ConverterStreamEventSink(this, sink)); + } + + /** + * Provides a `Converter` view of this stream transformer. + * + * The resulting transformer will check at run-time that all conversion + * inputs are actually instances of [S], + * and it will check that all conversion output produced by this converter + * are acually instances of [RT]. + */ + Converter cast() => Converter.castFrom(this); +} + +/** + * Fuses two converters. + * + * For a non-chunked conversion converts the input in sequence. + */ +class _FusedConverter extends Converter { + final Converter _first; + final Converter _second; + + _FusedConverter(this._first, this._second); + + T convert(S input) => _second.convert(_first.convert(input)); + + Sink startChunkedConversion(Sink sink) { + return _first.startChunkedConversion(_second.startChunkedConversion(sink)); + } +} +XNN<ELBE2IOK:Q1@ L,67"L$1 G%+PEJ+M$N@9 !.@1PQfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/encoding.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * Open-ended Encoding enum. + */ +abstract class Encoding extends Codec> { + const Encoding(); + + Converter> get encoder; + Converter, String> get decoder; + + Future decodeStream(Stream> byteStream) { + return byteStream + .transform(decoder) + .fold(new StringBuffer(), (buffer, string) => buffer..write(string)) + .then((buffer) => buffer.toString()); + } + + /** + * Name of the encoding. + * + * If the encoding is standardized, this is the lower-case version of one of + * the IANA official names for the character set (see + * http://www.iana.org/assignments/character-sets/character-sets.xml) + */ + String get name; + + // All aliases (in lowercase) of supported encoding from + // http://www.iana.org/assignments/character-sets/character-sets.xml. + static Map _nameToEncoding = { + // ISO_8859-1:1987. + "iso_8859-1:1987": latin1, + "iso-ir-100": latin1, + "iso_8859-1": latin1, + "iso-8859-1": latin1, + "latin1": latin1, + "l1": latin1, + "ibm819": latin1, + "cp819": latin1, + "csisolatin1": latin1, + + // US-ASCII. + "iso-ir-6": ascii, + "ansi_x3.4-1968": ascii, + "ansi_x3.4-1986": ascii, + "iso_646.irv:1991": ascii, + "iso646-us": ascii, + "us-ascii": ascii, + "us": ascii, + "ibm367": ascii, + "cp367": ascii, + "csascii": ascii, + "ascii": ascii, // This is not in the IANA official names. + + // UTF-8. + "csutf8": utf8, + "utf-8": utf8 + }; + + /** + * Gets an [Encoding] object from the name of the character set + * name. The names used are the IANA official names for the + * character set (see + * http://www.iana.org/assignments/character-sets/character-sets.xml). + * + * The [name] passed is case insensitive. + * + * If character set is not supported [:null:] is returned. + */ + static Encoding getByName(String name) { + if (name == null) return null; + name = name.toLowerCase(); + return _nameToEncoding[name]; + } +} +QNN<;,,>M.O8H;HE?A=H+<+#"Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/html_escape.dart;// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * A `String` converter that converts characters to HTML entities. + * + * This is intended to sanitize text before inserting the text into an HTML + * document. Characters that are meaningful in HTML are converted to + * HTML entities (like `&` for `&`). + * + * The general converter escapes all characters that are meaningful in HTML + * attributes or normal element context. Elements with special content types + * (like CSS or JavaScript) may need a more specialized escaping that + * understands that content type. + * + * If the context where the text will be inserted is known in more detail, + * it's possible to omit escaping some characters (like quotes when not + * inside an attribute value). + * + * The escaped text should only be used inside quoted HTML attributes values + * or as text content of a normal element. Using the escaped text inside a + * tag, but not inside a quoted attribute value, is still dangerous. + */ +const HtmlEscape htmlEscape = const HtmlEscape(); + +/** + * HTML escape modes. + * + * Allows specifying a mode for HTML escaping that depend on the context + * where the escaped result is going to be used. + * The relevant contexts are: + * + * * as text content of an HTML element. + * * as value of a (single- or double-) quoted attribute value. + * + * All modes require escaping of `&` (ampersand) characters, and may + * enable escaping of more characters. + * + * Custom escape modes can be created using the [HtmlEscapeMode.HtmlEscapeMode] + * constructor. + */ +class HtmlEscapeMode { + final String _name; + /** Whether to escape '<' and '>'. */ + final bool escapeLtGt; + /** Whether to escape '"' (quote). */ + final bool escapeQuot; + /** Whether to escape "'" (apostrophe). */ + final bool escapeApos; + /** + * Whether to escape "/" (forward slash, solidus). + * + * Escaping a slash is recommended to avoid cross-site scripting attacks by + * [the Open Web Application Security Project](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content) + */ + final bool escapeSlash; + + /** + * Default escaping mode which escape all characters. + * + * The result of such an escaping is usable both in element content and + * in any attribute value. + * + * The escaping only works for elements with normal HTML content, + * and not for, for example, script or style element content, + * which require escapes matching their particular content syntax. + */ + static const HtmlEscapeMode unknown = + const HtmlEscapeMode._('unknown', true, true, true, true); + + /** + * Escaping mode for text going into double-quoted HTML attribute values. + * + * The result should not be used as the content of an unquoted + * or single-quoted attribute value. + * + * Escapes double quotes (`"`) but not single quotes (`'`), + * and escapes `<` and `>` characters because they are not allowed + * in strict XHTML attributes + */ + static const HtmlEscapeMode attribute = + const HtmlEscapeMode._('attribute', true, true, false, false); + + /** + * Escaping mode for text going into single-quoted HTML attribute values. + * + * The result should not be used as the content of an unquoted + * or double-quoted attribute value. + * + * Escapes single quotes (`'`) but not double quotes (`"`), + * and escapes `<` and `>` characters because they are not allowed + * in strict XHTML attributes + */ + static const HtmlEscapeMode sqAttribute = + const HtmlEscapeMode._('attribute', true, false, true, false); + + /** + * Escaping mode for text going into HTML element content. + * + * The escaping only works for elements with normal HTML content, + * and not for, for example, script or style element content, + * which require escapes matching their particular content syntax. + * + * Escapes `<` and `>` characters. + */ + static const HtmlEscapeMode element = + const HtmlEscapeMode._('element', true, false, false, false); + + const HtmlEscapeMode._(this._name, this.escapeLtGt, this.escapeQuot, + this.escapeApos, this.escapeSlash); + + /** + * Create a custom escaping mode. + * + * All modes escape `&`. + * The mode can further be set to escape `<` and `>` ([escapeLtGt]), + * `"` ([escapeQuot]), `'` ([escapeApos]), and/or `/` ([escapeSlash]). + */ + const HtmlEscapeMode( + {String name: "custom", + this.escapeLtGt: false, + this.escapeQuot: false, + this.escapeApos: false, + this.escapeSlash: false}) + : _name = name; + + String toString() => _name; +} + +/** + * Converter which escapes characters with special meaning in HTML. + * + * The converter finds characters that are significant in HTML source and + * replaces them with corresponding HTML entities. + * + * The characters that need escaping in HTML are: + * + * * `&` (ampersand) always need to be escaped. + * * `<` (less than) and '>' (greater than) when inside an element. + * * `"` (quote) when inside a double-quoted attribute value. + * * `'` (apostrophe) when inside a single-quoted attribute value. + * Apostrophe is escaped as `'` instead of `'` since + * not all browsers understand `'`. + * * `/` (slash) is recommended to be escaped because it may be used + * to terminate an element in some HTML dialects. + * + * Escaping `>` (greater than) isn't necessary, but the result is often + * found to be easier to read if greater-than is also escaped whenever + * less-than is. + */ +class HtmlEscape extends Converter { + /** The [HtmlEscapeMode] used by the converter. */ + final HtmlEscapeMode mode; + + /** + * Create converter that escapes HTML characters. + * + * If [mode] is provided as either [HtmlEscapeMode.attribute] or + * [HtmlEscapeMode.element], only the corresponding subset of HTML + * characters are escaped. + * The default is to escape all HTML characters. + */ + const HtmlEscape([this.mode = HtmlEscapeMode.unknown]); + + String convert(String text) { + var val = _convert(text, 0, text.length); + return val == null ? text : val; + } + + /** + * Converts the substring of text from start to end. + * + * Returns `null` if no changes were necessary, otherwise returns + * the converted string. + */ + String _convert(String text, int start, int end) { + StringBuffer result = null; + for (int i = start; i < end; i++) { + var ch = text[i]; + String replacement = null; + switch (ch) { + case '&': + replacement = '&'; + break; + case '"': + if (mode.escapeQuot) replacement = '"'; + break; + case "'": + if (mode.escapeApos) replacement = '''; + break; + case '<': + if (mode.escapeLtGt) replacement = '<'; + break; + case '>': + if (mode.escapeLtGt) replacement = '>'; + break; + case '/': + if (mode.escapeSlash) replacement = '/'; + break; + } + if (replacement != null) { + if (result == null) result = new StringBuffer(); + if (i > start) result.write(text.substring(start, i)); + result.write(replacement); + start = i + 1; + } + } + if (result == null) return null; + if (end > start) result.write(text.substring(start, end)); + return result.toString(); + } + + StringConversionSink startChunkedConversion(Sink sink) { + if (sink is! StringConversionSink) { + sink = new StringConversionSink.from(sink); + } + return new _HtmlEscapeSink(this, sink); + } +} + +class _HtmlEscapeSink extends StringConversionSinkBase { + final HtmlEscape _escape; + final StringConversionSink _sink; + + _HtmlEscapeSink(this._escape, this._sink); + + void addSlice(String chunk, int start, int end, bool isLast) { + var val = _escape._convert(chunk, start, end); + if (val == null) { + _sink.addSlice(chunk, start, end, isLast); + } else { + _sink.add(val); + if (isLast) _sink.close(); + } + } + + void close() { + _sink.close(); + } +} +NN<CLE)LMF"KHMKE2I1)@E'P((-5N8JD@E(ALA'>E *ELA'>E ,E=D@E%(DG*$GI DJ320D>CD/E8HG554CE3: .%7D5 (!!76557!9?#%?C)2,9$-A31 !Ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/latin1.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** + * An instance of the default implementation of the [Latin1Codec]. + * + * This instance provides a convenient access to the most common ISO Latin 1 + * use cases. + * + * Examples: + * ```dart + * var encoded = latin1.encode("blåbærgrød"); + * var decoded = latin1.decode([0x62, 0x6c, 0xe5, 0x62, 0xe6, + * 0x72, 0x67, 0x72, 0xf8, 0x64]); + * ``` + */ +const Latin1Codec latin1 = const Latin1Codec(); + +const int _latin1Mask = 0xFF; + +/** + * A [Latin1Codec] encodes strings to ISO Latin-1 (aka ISO-8859-1) bytes + * and decodes Latin-1 bytes to strings. + */ +class Latin1Codec extends Encoding { + final bool _allowInvalid; + /** + * Instantiates a new [Latin1Codec]. + * + * If [allowInvalid] is true, the [decode] method and the converter + * returned by [decoder] will default to allowing invalid values. Invalid + * values are decoded into the Unicode Replacement character (U+FFFD). + * Calls to the [decode] method can override this default. + * + * Encoders will not accept invalid (non Latin-1) characters. + */ + const Latin1Codec({bool allowInvalid: false}) : _allowInvalid = allowInvalid; + + String get name => "iso-8859-1"; + + Uint8List encode(String source) => encoder.convert(source); + + /** + * Decodes the Latin-1 [bytes] (a list of unsigned 8-bit integers) to the + * corresponding string. + * + * If [bytes] contains values that are not in the range 0 .. 255, the decoder + * will eventually throw a [FormatException]. + * + * If [allowInvalid] is not provided, it defaults to the value used to create + * this [Latin1Codec]. + */ + String decode(List bytes, {bool allowInvalid}) { + if (allowInvalid == null) allowInvalid = _allowInvalid; + if (allowInvalid) { + return const Latin1Decoder(allowInvalid: true).convert(bytes); + } else { + return const Latin1Decoder(allowInvalid: false).convert(bytes); + } + } + + Latin1Encoder get encoder => const Latin1Encoder(); + + Latin1Decoder get decoder => _allowInvalid + ? const Latin1Decoder(allowInvalid: true) + : const Latin1Decoder(allowInvalid: false); +} + +/** + * This class converts strings of only ISO Latin-1 characters to bytes. + */ +class Latin1Encoder extends _UnicodeSubsetEncoder { + const Latin1Encoder() : super(_latin1Mask); +} + +/** + * This class converts Latin-1 bytes (lists of unsigned 8-bit integers) + * to a string. + */ +class Latin1Decoder extends _UnicodeSubsetDecoder { + /** + * Instantiates a new [Latin1Decoder]. + * + * The optional [allowInvalid] argument defines how [convert] deals + * with invalid bytes. + * + * If it is `true`, [convert] replaces invalid bytes with the Unicode + * Replacement character `U+FFFD` (�). + * Otherwise it throws a [FormatException]. + */ + const Latin1Decoder({bool allowInvalid: false}) + : super(allowInvalid, _latin1Mask); + + /** + * Starts a chunked conversion. + * + * The converter works more efficiently if the given [sink] is a + * [StringConversionSink]. + */ + ByteConversionSink startChunkedConversion(Sink sink) { + StringConversionSink stringSink; + if (sink is StringConversionSink) { + stringSink = sink; + } else { + stringSink = new StringConversionSink.from(sink); + } + // TODO(lrn): Use stringSink.asUtf16Sink() if it becomes available. + if (!_allowInvalid) return new _Latin1DecoderSink(stringSink); + return new _Latin1AllowInvalidDecoderSink(stringSink); + } +} + +class _Latin1DecoderSink extends ByteConversionSinkBase { + StringConversionSink _sink; + _Latin1DecoderSink(this._sink); + + void close() { + _sink.close(); + _sink = null; + } + + void add(List source) { + addSlice(source, 0, source.length, false); + } + + void _addSliceToSink(List source, int start, int end, bool isLast) { + // If _sink was a UTF-16 conversion sink, just add the slice directly with + // _sink.addSlice(source, start, end, isLast). + // The code below is an moderately stupid workaround until a real + // solution can be made. + _sink.add(new String.fromCharCodes(source, start, end)); + if (isLast) close(); + } + + void addSlice(List source, int start, int end, bool isLast) { + end = RangeError.checkValidRange(start, end, source.length); + if (start == end) return; + if (source is! Uint8List) { + // List may contain value outside of the 0..255 range. If so, throw. + // Technically, we could excuse Uint8ClampedList as well, but it unlikely + // to be relevant. + _checkValidLatin1(source, start, end); + } + _addSliceToSink(source, start, end, isLast); + } + + static void _checkValidLatin1(List source, int start, int end) { + int mask = 0; + for (int i = start; i < end; i++) { + mask |= source[i]; + } + if (mask >= 0 && mask <= _latin1Mask) { + return; + } + _reportInvalidLatin1(source, start, end); // Always throws. + } + + static void _reportInvalidLatin1(List source, int start, int end) { + // Find the index of the first non-Latin-1 character code. + for (int i = start; i < end; i++) { + int char = source[i]; + if (char < 0 || char > _latin1Mask) { + throw new FormatException( + "Source contains non-Latin-1 characters.", source, i); + } + } + // Unreachable - we only call the function if the loop above throws. + assert(false); + } +} + +class _Latin1AllowInvalidDecoderSink extends _Latin1DecoderSink { + _Latin1AllowInvalidDecoderSink(StringConversionSink sink) : super(sink); + + void addSlice(List source, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, source.length); + for (int i = start; i < end; i++) { + int char = source[i]; + if (char > _latin1Mask || char < 0) { + if (i > start) _addSliceToSink(source, start, i, false); + // Add UTF-8 encoding of U+FFFD. + _addSliceToSink(const [0xFFFD], 0, 1, false); + start = i + 1; + } + } + if (start < end) { + _addSliceToSink(source, start, end, isLast); + } + if (isLast) { + close(); + } + } +} +NN<CM .>@0I)%'FLI=@P#>LP0P8<E F6-02H4.H4)FH).2*"CA%( 8HC;:"/LO3F=EA KP-1H(,@K?(,#CIBKE;(,A)63Vfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/line_splitter.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +// Character constants. +const int _LF = 10; +const int _CR = 13; + +/** + * A [StreamTransformer] that splits a [String] into individual lines. + * + * A line is terminated by either a CR (U+000D), a LF (U+000A), a + * CR+LF sequence (DOS line ending), + * and a final non-empty line can be ended by the end of the string. + * + * The returned lines do not contain the line terminators. + */ + +class LineSplitter extends StreamTransformerBase { + const LineSplitter(); + + /// Split [lines] into individual lines. + /// + /// If [start] and [end] are provided, only split the contents of + /// `lines.substring(start, end)`. The [start] and [end] values must + /// specify a valid sub-range of [lines] + /// (`0 <= start <= end <= lines.length`). + static Iterable split(String lines, [int start = 0, int end]) sync* { + end = RangeError.checkValidRange(start, end, lines.length); + int sliceStart = start; + int char = 0; + for (int i = start; i < end; i++) { + int previousChar = char; + char = lines.codeUnitAt(i); + if (char != _CR) { + if (char != _LF) continue; + if (previousChar == _CR) { + sliceStart = i + 1; + continue; + } + } + yield lines.substring(sliceStart, i); + sliceStart = i + 1; + } + if (sliceStart < end) { + yield lines.substring(sliceStart, end); + } + } + + List convert(String data) { + List lines = []; + int end = data.length; + int sliceStart = 0; + int char = 0; + for (int i = 0; i < end; i++) { + int previousChar = char; + char = data.codeUnitAt(i); + if (char != _CR) { + if (char != _LF) continue; + if (previousChar == _CR) { + sliceStart = i + 1; + continue; + } + } + lines.add(data.substring(sliceStart, i)); + sliceStart = i + 1; + } + if (sliceStart < end) { + lines.add(data.substring(sliceStart, end)); + } + return lines; + } + + StringConversionSink startChunkedConversion(Sink sink) { + if (sink is! StringConversionSink) { + sink = new StringConversionSink.from(sink); + } + return new _LineSplitterSink(sink); + } + + Stream bind(Stream stream) { + return new Stream.eventTransformed( + stream, (EventSink sink) => new _LineSplitterEventSink(sink)); + } +} + +// TODO(floitsch): deal with utf8. +class _LineSplitterSink extends StringConversionSinkBase { + final StringConversionSink _sink; + + /// The carry-over from the previous chunk. + /// + /// If the previous slice ended in a line without a line terminator, + /// then the next slice may continue the line. + String _carry; + + /// Whether to skip a leading LF character from the next slice. + /// + /// If the previous slice ended on a CR character, a following LF + /// would be part of the same line termination, and should be ignored. + /// + /// Only `true` when [_carry] is `null`. + bool _skipLeadingLF = false; + + _LineSplitterSink(this._sink); + + void addSlice(String chunk, int start, int end, bool isLast) { + end = RangeError.checkValidRange(start, end, chunk.length); + // If the chunk is empty, it's probably because it's the last one. + // Handle that here, so we know the range is non-empty below. + if (start >= end) { + if (isLast) close(); + return; + } + if (_carry != null) { + assert(!_skipLeadingLF); + chunk = _carry + chunk.substring(start, end); + start = 0; + end = chunk.length; + _carry = null; + } else if (_skipLeadingLF) { + if (chunk.codeUnitAt(start) == _LF) { + start += 1; + } + _skipLeadingLF = false; + } + _addLines(chunk, start, end); + if (isLast) close(); + } + + void close() { + if (_carry != null) { + _sink.add(_carry); + _carry = null; + } + _sink.close(); + } + + void _addLines(String lines, int start, int end) { + int sliceStart = start; + int char = 0; + for (int i = start; i < end; i++) { + int previousChar = char; + char = lines.codeUnitAt(i); + if (char != _CR) { + if (char != _LF) continue; + if (previousChar == _CR) { + sliceStart = i + 1; + continue; + } + } + _sink.add(lines.substring(sliceStart, i)); + sliceStart = i + 1; + } + if (sliceStart < end) { + _carry = lines.substring(sliceStart, end); + } else { + _skipLeadingLF = (char == _CR); + } + } +} + +class _LineSplitterEventSink extends _LineSplitterSink + implements EventSink { + final EventSink _eventSink; + + _LineSplitterEventSink(EventSink eventSink) + : _eventSink = eventSink, + super(new StringConversionSink.from(eventSink)); + + void addError(Object o, [StackTrace stackTrace]) { + _eventSink.addError(o, stackTrace); + } +} +NN<GB%E;C+DG+-P@("## +,.&%$!## +02C)2(/0O#;$.G1BDI+!A@GB4!,"5("## +11 &7#&6 95(Lfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/convert/utf.dartN // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.convert; + +/** The Unicode Replacement character `U+FFFD` (�). */ +const int unicodeReplacementCharacterRune = 0xFFFD; + +/** The Unicode Byte Order Marker (BOM) character `U+FEFF`. */ +const int unicodeBomCharacterRune = 0xFEFF; + +/** + * An instance of the default implementation of the [Utf8Codec]. + * + * This instance provides a convenient access to the most common UTF-8 + * use cases. + * + * Examples: + * + * var encoded = utf8.encode("Îñţérñåţîöñåļîžåţîờñ"); + * var decoded = utf8.decode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6, + * 0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]); + */ +const Utf8Codec utf8 = const Utf8Codec(); + +/** + * A [Utf8Codec] encodes strings to utf-8 code units (bytes) and decodes + * UTF-8 code units to strings. + */ +class Utf8Codec extends Encoding { + final bool _allowMalformed; + + /** + * Instantiates a new [Utf8Codec]. + * + * The optional [allowMalformed] argument defines how [decoder] (and [decode]) + * deal with invalid or unterminated character sequences. + * + * If it is `true` (and not overridden at the method invocation) [decode] and + * the [decoder] replace invalid (or unterminated) octet + * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise + * they throw a [FormatException]. + */ + const Utf8Codec({bool allowMalformed: false}) + : _allowMalformed = allowMalformed; + + String get name => "utf-8"; + + /** + * Decodes the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the + * corresponding string. + * + * If the [codeUnits] start with the encoding of a + * [unicodeBomCharacterRune], that character is discarded. + * + * If [allowMalformed] is `true` the decoder replaces invalid (or + * unterminated) character sequences with the Unicode Replacement character + * `U+FFFD` (�). Otherwise it throws a [FormatException]. + * + * If [allowMalformed] is not given, it defaults to the `allowMalformed` that + * was used to instantiate `this`. + */ + String decode(List codeUnits, {bool allowMalformed}) { + if (allowMalformed == null) allowMalformed = _allowMalformed; + return new Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits); + } + + Utf8Encoder get encoder => const Utf8Encoder(); + Utf8Decoder get decoder { + return new Utf8Decoder(allowMalformed: _allowMalformed); + } +} + +/** + * This class converts strings to their UTF-8 code units (a list of + * unsigned 8-bit integers). + */ +class Utf8Encoder extends Converter> { + const Utf8Encoder(); + + /** + * Converts [string] to its UTF-8 code units (a list of + * unsigned 8-bit integers). + * + * If [start] and [end] are provided, only the substring + * `string.substring(start, end)` is converted. + */ + List convert(String string, [int start = 0, int end]) { + int stringLength = string.length; + RangeError.checkValidRange(start, end, stringLength); + if (end == null) end = stringLength; + int length = end - start; + if (length == 0) return new Uint8List(0); + // Create a new encoder with a length that is guaranteed to be big enough. + // A single code unit uses at most 3 bytes, a surrogate pair at most 4. + _Utf8Encoder encoder = new _Utf8Encoder.withBufferSize(length * 3); + int endPosition = encoder._fillBuffer(string, start, end); + assert(endPosition >= end - 1); + if (endPosition != end) { + // Encoding skipped the last code unit. + // That can only happen if the last code unit is a leadsurrogate. + // Force encoding of the lead surrogate by itself. + int lastCodeUnit = string.codeUnitAt(end - 1); + assert(_isLeadSurrogate(lastCodeUnit)); + // We use a non-surrogate as `nextUnit` so that _writeSurrogate just + // writes the lead-surrogate. + bool wasCombined = encoder._writeSurrogate(lastCodeUnit, 0); + assert(!wasCombined); + } + return encoder._buffer.sublist(0, encoder._bufferIndex); + } + + /** + * Starts a chunked conversion. + * + * The converter works more efficiently if the given [sink] is a + * [ByteConversionSink]. + */ + StringConversionSink startChunkedConversion(Sink> sink) { + if (sink is! ByteConversionSink) { + sink = new ByteConversionSink.from(sink); + } + return new _Utf8EncoderSink(sink); + } + + // Override the base-classes bind, to provide a better type. + Stream> bind(Stream stream) => super.bind(stream); +} + +/** + * This class encodes Strings to UTF-8 code units (unsigned 8 bit integers). + */ +// TODO(floitsch): make this class public. +class _Utf8Encoder { + int _carry = 0; + int _bufferIndex = 0; + final List _buffer; + + static const _DEFAULT_BYTE_BUFFER_SIZE = 1024; + + _Utf8Encoder() : this.withBufferSize(_DEFAULT_BYTE_BUFFER_SIZE); + + _Utf8Encoder.withBufferSize(int bufferSize) + : _buffer = _createBuffer(bufferSize); + + /** + * Allow an implementation to pick the most efficient way of storing bytes. + */ + static List _createBuffer(int size) => new Uint8List(size); + + /** + * Tries to combine the given [leadingSurrogate] with the [nextCodeUnit] and + * writes it to [_buffer]. + * + * Returns true if the [nextCodeUnit] was combined with the + * [leadingSurrogate]. If it wasn't then nextCodeUnit was not a trailing + * surrogate and has not been written yet. + * + * It is safe to pass 0 for [nextCodeUnit] in which case only the leading + * surrogate is written. + */ + bool _writeSurrogate(int leadingSurrogate, int nextCodeUnit) { + if (_isTailSurrogate(nextCodeUnit)) { + int rune = _combineSurrogatePair(leadingSurrogate, nextCodeUnit); + // If the rune is encoded with 2 code-units then it must be encoded + // with 4 bytes in UTF-8. + assert(rune > _THREE_BYTE_LIMIT); + assert(rune <= _FOUR_BYTE_LIMIT); + _buffer[_bufferIndex++] = 0xF0 | (rune >> 18); + _buffer[_bufferIndex++] = 0x80 | ((rune >> 12) & 0x3f); + _buffer[_bufferIndex++] = 0x80 | ((rune >> 6) & 0x3f); + _buffer[_bufferIndex++] = 0x80 | (rune & 0x3f); + return true; + } else { + // TODO(floitsch): allow to throw on malformed strings. + // Encode the half-surrogate directly into UTF-8. This yields + // invalid UTF-8, but we started out with invalid UTF-16. + + // Surrogates are always encoded in 3 bytes in UTF-8. + _buffer[_bufferIndex++] = 0xE0 | (leadingSurrogate >> 12); + _buffer[_bufferIndex++] = 0x80 | ((leadingSurrogate >> 6) & 0x3f); + _buffer[_bufferIndex++] = 0x80 | (leadingSurrogate & 0x3f); + return false; + } + } + + /** + * Fills the [_buffer] with as many characters as possible. + * + * Does not encode any trailing lead-surrogate. This must be done by the + * caller. + * + * Returns the position in the string. The returned index points to the + * first code unit that hasn't been encoded. + */ + int _fillBuffer(String str, int start, int end) { + if (start != end && _isLeadSurrogate(str.codeUnitAt(end - 1))) { + // Don't handle a trailing lead-surrogate in this loop. The caller has + // to deal with those. + end--; + } + int stringIndex; + for (stringIndex = start; stringIndex < end; stringIndex++) { + int codeUnit = str.codeUnitAt(stringIndex); + // ASCII has the same representation in UTF-8 and UTF-16. + if (codeUnit <= _ONE_BYTE_LIMIT) { + if (_bufferIndex >= _buffer.length) break; + _buffer[_bufferIndex++] = codeUnit; + } else if (_isLeadSurrogate(codeUnit)) { + if (_bufferIndex + 3 >= _buffer.length) break; + // Note that it is safe to read the next code unit. We decremented + // [end] above when the last valid code unit was a leading surrogate. + int nextCodeUnit = str.codeUnitAt(stringIndex + 1); + bool wasCombined = _writeSurrogate(codeUnit, nextCodeUnit); + if (wasCombined) stringIndex++; + } else { + int rune = codeUnit; + if (rune <= _TWO_BYTE_LIMIT) { + if (_bufferIndex + 1 >= _buffer.length) break; + _buffer[_bufferIndex++] = 0xC0 | (rune >> 6); + _buffer[_bufferIndex++] = 0x80 | (rune & 0x3f); + } else { + assert(rune <= _THREE_BYTE_LIMIT); + if (_bufferIndex + 2 >= _buffer.length) break; + _buffer[_bufferIndex++] = 0xE0 | (rune >> 12); + _buffer[_bufferIndex++] = 0x80 | ((rune >> 6) & 0x3f); + _buffer[_bufferIndex++] = 0x80 | (rune & 0x3f); + } + } + } + return stringIndex; + } +} + +/** + * This class encodes chunked strings to UTF-8 code units (unsigned 8-bit + * integers). + */ +class _Utf8EncoderSink extends _Utf8Encoder with StringConversionSinkMixin { + final ByteConversionSink _sink; + + _Utf8EncoderSink(this._sink); + + void close() { + if (_carry != 0) { + // addSlice will call close again, but then the carry must be equal to 0. + addSlice("", 0, 0, true); + return; + } + _sink.close(); + } + + void addSlice(String str, int start, int end, bool isLast) { + _bufferIndex = 0; + + if (start == end && !isLast) { + return; + } + + if (_carry != 0) { + int nextCodeUnit = 0; + if (start != end) { + nextCodeUnit = str.codeUnitAt(start); + } else { + assert(isLast); + } + bool wasCombined = _writeSurrogate(_carry, nextCodeUnit); + // Either we got a non-empty string, or we must not have been combined. + assert(!wasCombined || start != end); + if (wasCombined) start++; + _carry = 0; + } + do { + start = _fillBuffer(str, start, end); + bool isLastSlice = isLast && (start == end); + if (start == end - 1 && _isLeadSurrogate(str.codeUnitAt(start))) { + if (isLast && _bufferIndex < _buffer.length - 3) { + // There is still space for the last incomplete surrogate. + // We use a non-surrogate as second argument. This way the + // function will just add the surrogate-half to the buffer. + bool hasBeenCombined = _writeSurrogate(str.codeUnitAt(start), 0); + assert(!hasBeenCombined); + } else { + // Otherwise store it in the carry. If isLast is true, then + // close will flush the last carry. + _carry = str.codeUnitAt(start); + } + start++; + } + _sink.addSlice(_buffer, 0, _bufferIndex, isLastSlice); + _bufferIndex = 0; + } while (start < end); + if (isLast) close(); + } + + // TODO(floitsch): implement asUtf8Sink. Sligthly complicated because it + // needs to deal with malformed input. +} + +/** + * This class converts UTF-8 code units (lists of unsigned 8-bit integers) + * to a string. + */ +class Utf8Decoder extends Converter, String> { + final bool _allowMalformed; + + /** + * Instantiates a new [Utf8Decoder]. + * + * The optional [allowMalformed] argument defines how [convert] deals + * with invalid or unterminated character sequences. + * + * If it is `true` [convert] replaces invalid (or unterminated) character + * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise + * it throws a [FormatException]. + */ + const Utf8Decoder({bool allowMalformed: false}) + : this._allowMalformed = allowMalformed; + + /** + * Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the + * corresponding string. + * + * Uses the code units from [start] to, but no including, [end]. + * If [end] is omitted, it defaults to `codeUnits.length`. + * + * If the [codeUnits] start with the encoding of a + * [unicodeBomCharacterRune], that character is discarded. + */ + String convert(List codeUnits, [int start = 0, int end]) { + // Allow the implementation to intercept and specialize based on the type + // of codeUnits. + String result = _convertIntercepted(_allowMalformed, codeUnits, start, end); + if (result != null) { + return result; + } + + int length = codeUnits.length; + RangeError.checkValidRange(start, end, length); + if (end == null) end = length; + StringBuffer buffer = new StringBuffer(); + _Utf8Decoder decoder = new _Utf8Decoder(buffer, _allowMalformed); + decoder.convert(codeUnits, start, end); + decoder.flush(codeUnits, end); + return buffer.toString(); + } + + /** + * Starts a chunked conversion. + * + * The converter works more efficiently if the given [sink] is a + * [StringConversionSink]. + */ + ByteConversionSink startChunkedConversion(Sink sink) { + StringConversionSink stringSink; + if (sink is StringConversionSink) { + stringSink = sink; + } else { + stringSink = new StringConversionSink.from(sink); + } + return stringSink.asUtf8Sink(_allowMalformed); + } + + // Override the base-classes bind, to provide a better type. + Stream bind(Stream> stream) => super.bind(stream); + + external Converter, T> fuse(Converter next); + + external static String _convertIntercepted( + bool allowMalformed, List codeUnits, int start, int end); +} + +// UTF-8 constants. +const int _ONE_BYTE_LIMIT = 0x7f; // 7 bits +const int _TWO_BYTE_LIMIT = 0x7ff; // 11 bits +const int _THREE_BYTE_LIMIT = 0xffff; // 16 bits +const int _FOUR_BYTE_LIMIT = 0x10ffff; // 21 bits, truncated to Unicode max. + +// UTF-16 constants. +const int _SURROGATE_MASK = 0xF800; +const int _SURROGATE_TAG_MASK = 0xFC00; +const int _SURROGATE_VALUE_MASK = 0x3FF; +const int _LEAD_SURROGATE_MIN = 0xD800; +const int _TAIL_SURROGATE_MIN = 0xDC00; + +bool _isLeadSurrogate(int codeUnit) => + (codeUnit & _SURROGATE_TAG_MASK) == _LEAD_SURROGATE_MIN; +bool _isTailSurrogate(int codeUnit) => + (codeUnit & _SURROGATE_TAG_MASK) == _TAIL_SURROGATE_MIN; +int _combineSurrogatePair(int lead, int tail) => + 0x10000 + ((lead & _SURROGATE_VALUE_MASK) << 10) | + (tail & _SURROGATE_VALUE_MASK); + +/** + * Decodes UTF-8. + * + * The decoder handles chunked input. + */ +// TODO(floitsch): make this class public. +class _Utf8Decoder { + final bool _allowMalformed; + final StringSink _stringSink; + bool _isFirstCharacter = true; + int _value = 0; + int _expectedUnits = 0; + int _extraUnits = 0; + + _Utf8Decoder(this._stringSink, this._allowMalformed); + + bool get hasPartialInput => _expectedUnits > 0; + + // Limits of one through four byte encodings. + static const List _LIMITS = const [ + _ONE_BYTE_LIMIT, + _TWO_BYTE_LIMIT, + _THREE_BYTE_LIMIT, + _FOUR_BYTE_LIMIT + ]; + + void close() { + flush(); + } + + /** + * Flushes this decoder as if closed. + * + * This method throws if the input was partial and the decoder was + * constructed with `allowMalformed` set to `false`. + * + * The [source] and [offset] of the current position may be provided, + * and are included in the exception if one is thrown. + */ + void flush([List source, int offset]) { + if (hasPartialInput) { + if (!_allowMalformed) { + throw new FormatException( + "Unfinished UTF-8 octet sequence", source, offset); + } + _stringSink.writeCharCode(unicodeReplacementCharacterRune); + _value = 0; + _expectedUnits = 0; + _extraUnits = 0; + } + } + + void convert(List codeUnits, int startIndex, int endIndex) { + int value = _value; + int expectedUnits = _expectedUnits; + int extraUnits = _extraUnits; + _value = 0; + _expectedUnits = 0; + _extraUnits = 0; + + int scanOneByteCharacters(List units, int from) { + final to = endIndex; + final mask = _ONE_BYTE_LIMIT; + for (var i = from; i < to; i++) { + final unit = units[i]; + if ((unit & mask) != unit) return i - from; + } + return to - from; + } + + void addSingleBytes(int from, int to) { + assert(from >= startIndex && from <= endIndex); + assert(to >= startIndex && to <= endIndex); + _stringSink.write(new String.fromCharCodes(codeUnits, from, to)); + } + + int i = startIndex; + loop: + while (true) { + multibyte: + if (expectedUnits > 0) { + do { + if (i == endIndex) { + break loop; + } + int unit = codeUnits[i]; + if ((unit & 0xC0) != 0x80) { + expectedUnits = 0; + if (!_allowMalformed) { + throw new FormatException( + "Bad UTF-8 encoding 0x${unit.toRadixString(16)}", + codeUnits, + i); + } + _isFirstCharacter = false; + _stringSink.writeCharCode(unicodeReplacementCharacterRune); + break multibyte; + } else { + value = (value << 6) | (unit & 0x3f); + expectedUnits--; + i++; + } + } while (expectedUnits > 0); + if (value <= _LIMITS[extraUnits - 1]) { + // Overly long encoding. The value could be encoded with a shorter + // encoding. + if (!_allowMalformed) { + throw new FormatException( + "Overlong encoding of 0x${value.toRadixString(16)}", + codeUnits, + i - extraUnits - 1); + } + expectedUnits = extraUnits = 0; + value = unicodeReplacementCharacterRune; + } + if (value > _FOUR_BYTE_LIMIT) { + if (!_allowMalformed) { + throw new FormatException( + "Character outside valid Unicode range: " + "0x${value.toRadixString(16)}", + codeUnits, + i - extraUnits - 1); + } + value = unicodeReplacementCharacterRune; + } + if (!_isFirstCharacter || value != unicodeBomCharacterRune) { + _stringSink.writeCharCode(value); + } + _isFirstCharacter = false; + } + + while (i < endIndex) { + int oneBytes = scanOneByteCharacters(codeUnits, i); + if (oneBytes > 0) { + _isFirstCharacter = false; + addSingleBytes(i, i + oneBytes); + i += oneBytes; + if (i == endIndex) break; + } + int unit = codeUnits[i++]; + // TODO(floitsch): the way we test we could potentially allow + // units that are too large, if they happen to have the + // right bit-pattern. (Same is true for the multibyte loop above). + // TODO(floitsch): optimize this loop. See: + // https://codereview.chromium.org/22929022/diff/1/sdk/lib/convert/utf.dart?column_width=80 + if (unit < 0) { + // TODO(floitsch): should this be unit <= 0 ? + if (!_allowMalformed) { + throw new FormatException( + "Negative UTF-8 code unit: -0x${(-unit).toRadixString(16)}", + codeUnits, + i - 1); + } + _stringSink.writeCharCode(unicodeReplacementCharacterRune); + } else { + assert(unit > _ONE_BYTE_LIMIT); + if ((unit & 0xE0) == 0xC0) { + value = unit & 0x1F; + expectedUnits = extraUnits = 1; + continue loop; + } + if ((unit & 0xF0) == 0xE0) { + value = unit & 0x0F; + expectedUnits = extraUnits = 2; + continue loop; + } + // 0xF5, 0xF6 ... 0xFF never appear in valid UTF-8 sequences. + if ((unit & 0xF8) == 0xF0 && unit < 0xF5) { + value = unit & 0x07; + expectedUnits = extraUnits = 3; + continue loop; + } + if (!_allowMalformed) { + throw new FormatException( + "Bad UTF-8 encoding 0x${unit.toRadixString(16)}", + codeUnits, + i - 1); + } + value = unicodeReplacementCharacterRune; + expectedUnits = extraUnits = 0; + _isFirstCharacter = false; + _stringSink.writeCharCode(value); + } + } + break loop; + } + if (expectedUnits > 0) { + _value = value; + _expectedUnits = expectedUnits; + _extraUnits = extraUnits; + } + } +} +MNN<74?,AG :LH*I #%Q<P;N%0*N5=DN<P%>BO2=D9:;2?&:).OLH?$.H95.K$C="CF'0'?GM+1C.-NCO>K-LA*HJ ((5>=6 >D@K J/4EM B2@)3,/7KNKGEOKK;<I(I$#)PQQE;HK Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/developer/extension.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.developer; + +/// A response to a service protocol extension RPC. +/// +/// If the RPC was successful, use [ServiceExtensionResponse.result], otherwise +/// use [ServiceExtensionResponse.error]. +class ServiceExtensionResponse { + final String _result; + final int _errorCode; + final String _errorDetail; + + /// Creates a successful response to a service protocol extension RPC. + /// + /// Requires [result] to be a JSON object encoded as a string. When forming + /// the JSON-RPC message [result] will be inlined directly. + ServiceExtensionResponse.result(String result) + : _result = result, + _errorCode = null, + _errorDetail = null { + if (_result is! String) { + throw new ArgumentError.value(_result, "result", "Must be a String"); + } + } + + /// Creates an error response to a service protocol extension RPC. + /// + /// Requires [errorCode] to be [invalidParams] or between [extensionErrorMin] + /// and [extensionErrorMax]. Requires [errorDetail] to be a JSON object + /// encoded as a string. When forming the JSON-RPC message [errorDetail] will + /// be inlined directly. + ServiceExtensionResponse.error(int errorCode, String errorDetail) + : _result = null, + _errorCode = errorCode, + _errorDetail = errorDetail { + _validateErrorCode(_errorCode); + if (_errorDetail is! String) { + throw new ArgumentError.value( + _errorDetail, "errorDetail", "Must be a String"); + } + } + + /// Invalid method parameter(s) error code. + @deprecated + static const kInvalidParams = invalidParams; + + /// Generic extension error code. + @deprecated + static const kExtensionError = extensionError; + + /// Maximum extension provided error code. + @deprecated + static const kExtensionErrorMax = extensionErrorMax; + + /// Minimum extension provided error code. + @deprecated + static const kExtensionErrorMin = extensionErrorMin; + + /// Invalid method parameter(s) error code. + static const invalidParams = -32602; + + /// Generic extension error code. + static const extensionError = -32000; + + /// Maximum extension provided error code. + static const extensionErrorMax = -32000; + + /// Minimum extension provided error code. + static const extensionErrorMin = -32016; + + static String _errorCodeMessage(int errorCode) { + _validateErrorCode(errorCode); + if (errorCode == invalidParams) { + return "Invalid params"; + } + return "Server error"; + } + + static _validateErrorCode(int errorCode) { + if (errorCode is! int) { + throw new ArgumentError.value(errorCode, "errorCode", "Must be an int"); + } + if (errorCode == invalidParams) { + return; + } + if ((errorCode >= extensionErrorMin) && (errorCode <= extensionErrorMax)) { + return; + } + throw new ArgumentError.value(errorCode, "errorCode", "Out of range"); + } + + // ignore: unused_element, called from runtime/lib/developer.dart + bool _isError() => (_errorCode != null) && (_errorDetail != null); + + // ignore: unused_element, called from runtime/lib/developer.dart + String _toString() { + if (_result != null) { + return _result; + } else { + assert(_errorCode != null); + assert(_errorDetail != null); + return json.encode({ + 'code': _errorCode, + 'message': _errorCodeMessage(_errorCode), + 'data': {'details': _errorDetail} + }); + } + } +} + +/// A service protocol extension handler. Registered with [registerExtension]. +/// +/// Must complete to a [ServiceExtensionResponse]. [method] is the method name +/// of the service protocol request, and [parameters] is a map holding the +/// parameters to the service protocol request. +/// +/// *NOTE*: all parameter names and values are encoded as strings. +typedef Future ServiceExtensionHandler( + String method, Map parameters); + +/// Register a [ServiceExtensionHandler] that will be invoked in this isolate +/// for [method]. *NOTE*: Service protocol extensions must be registered +/// in each isolate. +/// +/// *NOTE*: [method] must begin with 'ext.' and you should use the following +/// structure to avoid conflicts with other packages: 'ext.package.command'. +/// That is, immediately following the 'ext.' prefix, should be the registering +/// package name followed by another period ('.') and then the command name. +/// For example: 'ext.dart.io.getOpenFiles'. +/// +/// Because service extensions are isolate specific, clients using extensions +/// must always include an 'isolateId' parameter with each RPC. +void registerExtension(String method, ServiceExtensionHandler handler) { + if (method is! String) { + throw new ArgumentError.value(method, 'method', 'Must be a String'); + } + if (!method.startsWith('ext.')) { + throw new ArgumentError.value(method, 'method', 'Must begin with ext.'); + } + if (_lookupExtension(method) != null) { + throw new ArgumentError('Extension already registered: $method'); + } + if (handler is! ServiceExtensionHandler) { + throw new ArgumentError.value( + handler, 'handler', 'Must be a ServiceExtensionHandler'); + } + _registerExtension(method, handler); +} + +/// Post an event of [eventKind] with payload of [eventData] to the `Extension` +/// event stream. +void postEvent(String eventKind, Map eventData) { + if (eventKind is! String) { + throw new ArgumentError.value(eventKind, 'eventKind', 'Must be a String'); + } + if (eventData is! Map) { + throw new ArgumentError.value(eventData, 'eventData', 'Must be a Map'); + } + String eventDataAsString = json.encode(eventData); + _postEvent(eventKind, eventDataAsString); +} + +external void _postEvent(String eventKind, String eventData); + +// Both of these functions are written inside C++ to avoid updating the data +// structures in Dart, getting an OOB, and observing stale state. Do not move +// these into Dart code unless you can ensure that the operations will can be +// done atomically. Native code lives in vm/isolate.cc- +// LookupServiceExtensionHandler and RegisterServiceExtensionHandler. +external ServiceExtensionHandler _lookupExtension(String method); +external _registerExtension(String method, ServiceExtensionHandler handler); +NN<4P*!IN>1LEPJPD %$#%<./$1-7-7.'$(-+-+3#&-O&PKDED "$2* +OOK0CB4NIMMPM-N@II$M*F-#B'P2OL5,>MNN8FBMSfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/developer/timeline.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.developer; + +const bool _isProduct = const bool.fromEnvironment("dart.vm.product"); + +/// A typedef for the function argument to [Timeline.timeSync]. +typedef dynamic TimelineSyncFunction(); + +// TODO: This typedef is not used. +typedef Future TimelineAsyncFunction(); + +/// A class to represent Flow events. +/// +/// [Flow] objects are used to thread flow events between timeline slices, +/// for example, those created with the [Timeline] class below. Adding +/// [Flow] objects cause arrows to be drawn between slices in Chrome's trace +/// viewer. The arrows start at e.g [Timeline] events that are passed a +/// [Flow.begin] object, go through [Timeline] events that are passed a +/// [Flow.step] object, and end at [Timeline] events that are passed a +/// [Flow.end] object, all having the same [Flow.id]. For example: +/// +/// ```dart +/// var flow = Flow.begin(); +/// Timeline.timeSync('flow_test', () { +/// doSomething(); +/// }, flow: flow); +/// +/// Timeline.timeSync('flow_test', () { +/// doSomething(); +/// }, flow: Flow.step(flow.id)); +/// +/// Timeline.timeSync('flow_test', () { +/// doSomething(); +/// }, flow: Flow.end(flow.id)); +/// ``` +class Flow { + // These values must be kept in sync with the enum "EventType" in + // runtime/vm/timeline.h. + static const int _begin = 9; + static const int _step = 10; + static const int _end = 11; + + final int _type; + + /// The flow id of the flow event. + final int id; + + Flow._(this._type, this.id); + + /// A "begin" Flow event. + /// + /// When passed to a [Timeline] method, generates a "begin" Flow event. + /// If [id] is not provided, an id that conflicts with no other Dart-generated + /// flow id's will be generated. + static Flow begin({int id}) { + return new Flow._(_begin, id ?? _getNextAsyncId()); + } + + /// A "step" Flow event. + /// + /// When passed to a [Timeline] method, generates a "step" Flow event. + /// The [id] argument is required. It can come either from another [Flow] + /// event, or some id that comes from the environment. + static Flow step(int id) => new Flow._(_step, id); + + /// An "end" Flow event. + /// + /// When passed to a [Timeline] method, generates a "end" Flow event. + /// The [id] argument is required. It can come either from another [Flow] + /// event, or some id that comes from the environment. + static Flow end(int id) => new Flow._(_end, id); +} + +/// Add to the timeline. +/// +/// [Timeline]'s methods add synchronous events to the timeline. When +/// generating a timeline in Chrome's tracing format, using [Timeline] generates +/// "Complete" events. [Timeline]'s [startSync] and [finishSync] can be used +/// explicitly, or implicitly by wrapping a closure in [timeSync]. For example: +/// +/// ```dart +/// Timeline.startSync("Doing Something"); +/// doSomething(); +/// Timeline.finishSync(); +/// ``` +/// +/// Or: +/// +/// ```dart +/// Timeline.timeSync("Doing Something", () { +/// doSomething(); +/// }); +/// ``` +class Timeline { + /// Start a synchronous operation labeled [name]. Optionally takes + /// a [Map] of [arguments]. This slice may also optionally be associated with + /// a [Flow] event. This operation must be finished before + /// returning to the event queue. + static void startSync(String name, {Map arguments, Flow flow}) { + if (_isProduct) { + return; + } + if (name is! String) { + throw new ArgumentError.value(name, 'name', 'Must be a String'); + } + if (!_isDartStreamEnabled()) { + // Push a null onto the stack and return. + _stack.add(null); + return; + } + var block = new _SyncBlock._(name, _getTraceClock(), _getThreadCpuClock()); + if (arguments is Map) { + block._arguments = arguments; + } + if (flow is Flow) { + block.flow = flow; + } + _stack.add(block); + } + + /// Finish the last synchronous operation that was started. + static void finishSync() { + if (_isProduct) { + return; + } + if (_stack.length == 0) { + throw new StateError('Uneven calls to startSync and finishSync'); + } + // Pop top item off of stack. + var block = _stack.removeLast(); + if (block == null) { + // Dart stream was disabled when startSync was called. + return; + } + // Finish it. + block.finish(); + } + + /// Emit an instant event. + static void instantSync(String name, {Map arguments}) { + if (_isProduct) { + return; + } + if (name is! String) { + throw new ArgumentError.value(name, 'name', 'Must be a String'); + } + if (!_isDartStreamEnabled()) { + // Stream is disabled. + return; + } + Map instantArguments; + if (arguments is Map) { + instantArguments = new Map.from(arguments); + } + _reportInstantEvent( + _getTraceClock(), 'Dart', name, _argumentsAsJson(instantArguments)); + } + + /// A utility method to time a synchronous [function]. Internally calls + /// [function] bracketed by calls to [startSync] and [finishSync]. + static dynamic timeSync(String name, TimelineSyncFunction function, + {Map arguments, Flow flow}) { + startSync(name, arguments: arguments, flow: flow); + try { + return function(); + } finally { + finishSync(); + } + } + + /// The current time stamp from the clock used by the timeline. Units are + /// microseconds. + static int get now => _getTraceClock(); + static final List<_SyncBlock> _stack = new List<_SyncBlock>(); +} + +/// An asynchronous task on the timeline. An asynchronous task can have many +/// (nested) synchronous operations. Synchronous operations can live longer than +/// the current isolate event. To pass a [TimelineTask] to another isolate, +/// you must first call [pass] to get the task id and then construct a new +/// [TimelineTask] in the other isolate. +class TimelineTask { + /// Create a task. The task ID will be set by the system. + TimelineTask() : _taskId = _getNextAsyncId() {} + + /// Create a task with an explicit [taskId]. This is useful if you are + /// passing a task from one isolate to another. + TimelineTask.withTaskId(int taskId) : _taskId = taskId { + if (taskId is! int) { + throw new ArgumentError.value(taskId, 'taskId', 'Must be an int'); + } + } + + /// Start a synchronous operation within this task named [name]. + /// Optionally takes a [Map] of [arguments]. + void start(String name, {Map arguments}) { + if (_isProduct) { + return; + } + if (name is! String) { + throw new ArgumentError.value(name, 'name', 'Must be a String'); + } + var block = new _AsyncBlock._(name, _taskId); + if (arguments is Map) { + block._arguments = arguments; + } + _stack.add(block); + block._start(); + } + + /// Emit an instant event for this task. + void instant(String name, {Map arguments}) { + if (_isProduct) { + return; + } + if (name is! String) { + throw new ArgumentError.value(name, 'name', 'Must be a String'); + } + Map instantArguments; + if (arguments is Map) { + instantArguments = new Map.from(arguments); + } + _reportTaskEvent(_getTraceClock(), _taskId, 'n', 'Dart', name, + _argumentsAsJson(instantArguments)); + } + + /// Finish the last synchronous operation that was started. + void finish() { + if (_isProduct) { + return; + } + if (_stack.length == 0) { + throw new StateError('Uneven calls to start and finish'); + } + // Pop top item off of stack. + var block = _stack.removeLast(); + block._finish(); + } + + /// Retrieve the [TimelineTask]'s task id. Will throw an exception if the + /// stack is not empty. + int pass() { + if (_stack.length > 0) { + throw new StateError( + 'You cannot pass a TimelineTask without finishing all started ' + 'operations'); + } + int r = _taskId; + return r; + } + + final int _taskId; + final List<_AsyncBlock> _stack = []; +} + +/// An asynchronous block of time on the timeline. This block can be kept +/// open across isolate messages. +class _AsyncBlock { + /// The category this block belongs to. + final String category = 'Dart'; + + /// The name of this block. + final String name; + + /// The asynchronous task id. + final int _taskId; + + /// An (optional) set of arguments which will be serialized to JSON and + /// associated with this block. + Map _arguments; + + _AsyncBlock._(this.name, this._taskId); + + // Emit the start event. + void _start() { + _reportTaskEvent(_getTraceClock(), _taskId, 'b', category, name, + _argumentsAsJson(_arguments)); + } + + // Emit the finish event. + void _finish() { + _reportTaskEvent( + _getTraceClock(), _taskId, 'e', category, name, _argumentsAsJson(null)); + } +} + +/// A synchronous block of time on the timeline. This block should not be +/// kept open across isolate messages. +class _SyncBlock { + /// The category this block belongs to. + final String category = 'Dart'; + + /// The name of this block. + final String name; + + /// An (optional) set of arguments which will be serialized to JSON and + /// associated with this block. + Map _arguments; + // The start time stamp. + final int _start; + // The start time stamp of the thread cpu clock. + final int _startCpu; + + /// An (optional) flow event associated with this block. + Flow _flow; + + _SyncBlock._(this.name, this._start, this._startCpu); + + /// Finish this block of time. At this point, this block can no longer be + /// used. + void finish() { + // Report event to runtime. + _reportCompleteEvent( + _start, _startCpu, category, name, _argumentsAsJson(_arguments)); + if (_flow != null) { + _reportFlowEvent(_start, _startCpu, category, name, _flow._type, _flow.id, + _argumentsAsJson(null)); + } + } + + void set flow(Flow f) { + _flow = f; + } +} + +String _argumentsAsJson(Map arguments) { + if ((arguments == null) || (arguments.length == 0)) { + // Fast path no arguments. Avoid calling jsonEncode. + return '{}'; + } + return json.encode(arguments); +} + +/// Returns true if the Dart Timeline stream is enabled. +external bool _isDartStreamEnabled(); + +/// Returns the next async task id. +external int _getNextAsyncId(); + +/// Returns the current value from the trace clock. +external int _getTraceClock(); + +/// Returns the current value from the thread CPU usage clock. +external int _getThreadCpuClock(); + +/// Reports an event for a task. +external void _reportTaskEvent(int start, int taskId, String phase, + String category, String name, String argumentsAsJson); + +/// Reports a complete synchronous event. +external void _reportCompleteEvent(int start, int startCpu, String category, + String name, String argumentsAsJson); + +/// Reports a flow event. +external void _reportFlowEvent(int start, int startCpu, String category, + String name, int type, int id, String argumentsAsJson); + +/// Reports an instant event. +external void _reportInstantEvent( + int start, String category, String name, String argumentsAsJson); +mNN<G@(#(&KGMHHGC (("(! D%JQ# 8IL95HL93FQMP + .EP=$CG#0P$>H"%=:G#2MJEF$7 +L*AMQLK)<2I2;IC/-G2$+/G2C->@"%LJ'J"*" J"*E'QJ'*"J"3;8L  JQ#)89!9&$ 4?#!D;*M*I<#Fnfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/developer_patch.dart*// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Patch file for dart:developer library. + +import 'dart:_js_helper' show patch, ForceInline; +import 'dart:_foreign_helper' show JS; +import 'dart:async'; +import 'dart:isolate'; + +@patch +@ForceInline() +bool debugger({bool when = true, String message}) { + if (when) { + JS('', 'debugger'); + } + return when; +} + +@patch +Object inspect(Object object) { + return object; +} + +@patch +void log(String message, + {DateTime time, + int sequenceNumber, + int level = 0, + String name = '', + Zone zone, + Object error, + StackTrace stackTrace}) { + // TODO. +} + +final _extensions = Map(); + +@patch +ServiceExtensionHandler _lookupExtension(String method) { + return _extensions[method]; +} + +@patch +_registerExtension(String method, ServiceExtensionHandler handler) { + _extensions[method] = handler; +} + +@patch +void _postEvent(String eventKind, String eventData) { + // TODO. +} + +@patch +bool _isDartStreamEnabled() { + return false; +} + +@patch +int _getTraceClock() { + // TODO. + return _clockValue++; +} + +int _clockValue = 0; + +@patch +int _getThreadCpuClock() { + return -1; +} + +@patch +void _reportCompleteEvent(int start, int startCpu, String category, String name, + String argumentsAsJson) { + // TODO. +} + +@patch +void _reportFlowEvent(int start, int startCpu, String category, String name, + int type, int id, String argumentsAsJson) { + // TODO. +} + +@patch +void _reportInstantEvent( + int start, String category, String name, String argumentsAsJson) { + // TODO. +} + +@patch +int _getNextAsyncId() { + return 0; +} + +@patch +void _reportTaskEvent(int start, int taskId, String phase, String category, + String name, String argumentsAsJson) { + // TODO. +} + +@patch +int _getServiceMajorVersion() { + return 0; +} + +@patch +int _getServiceMinorVersion() { + return 0; +} + +@patch +void _getServerInfo(SendPort sendPort) { + sendPort.send(null); +} + +@patch +void _webServerControl(SendPort sendPort, bool enable) { + sendPort.send(null); +} + +@patch +String _getIsolateIDFromSendPort(SendPort sendPort) { + return null; +} + +@patch +class UserTag { + @patch + factory UserTag(String label) = _FakeUserTag; + + @patch + static UserTag get defaultTag => _FakeUserTag._defaultTag; +} + +class _FakeUserTag implements UserTag { + static Map _instances = {}; + + _FakeUserTag.real(this.label); + + factory _FakeUserTag(String label) { + // Canonicalize by name. + var existingTag = _instances[label]; + if (existingTag != null) { + return existingTag; + } + // Throw an exception if we've reached the maximum number of user tags. + if (_instances.length == UserTag.MAX_USER_TAGS) { + throw UnsupportedError( + 'UserTag instance limit (${UserTag.MAX_USER_TAGS}) reached.'); + } + // Create a new instance and add it to the instance map. + var instance = _FakeUserTag.real(label); + _instances[label] = instance; + return instance; + } + + final String label; + + UserTag makeCurrent() { + var old = _currentTag; + _currentTag = this; + return old; + } + + static final UserTag _defaultTag = _FakeUserTag('Default'); +} + +var _currentTag = _FakeUserTag._defaultTag; + +@patch +UserTag getCurrentTag() => _currentTag; +NN<*2'4  <:E!6   Q M0 G  L+   )96 0 =(!')L6I=-">,(Sfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/developer/profiler.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.developer; + +/// A UserTag can be used to group samples in the Observatory profiler. +abstract class UserTag { + /// The maximum number of UserTag instances that can be created by a program. + static const MAX_USER_TAGS = 64; + + external factory UserTag(String label); + + /// Label of [this]. + String get label; + + /// Make [this] the current tag for the isolate. Returns the current tag + /// before setting. + UserTag makeCurrent(); + + /// The default [UserTag] with label 'Default'. + external static UserTag get defaultTag; +} + +/// Returns the current [UserTag] for the isolate. +external UserTag getCurrentTag(); + +/// Abstract [Metric] class. Metric names must be unique, are hierarchical, +/// and use periods as separators. For example, 'a.b.c'. Uniqueness is only +/// enforced when a Metric is registered. The name of a metric cannot contain +/// the slash ('/') character. +abstract class Metric { + /// [name] of this metric. + final String name; + + /// [description] of this metric. + final String description; + + Metric(this.name, this.description) { + if ((name == 'vm') || name.contains('/')) { + throw new ArgumentError('Invalid Metric name.'); + } + } + + Map _toJSON(); +} + +/// A measured value with a min and max. Initial value is min. Value will +/// be clamped to the interval [min, max]. +class Gauge extends Metric { + final double min; + final double max; + + double _value; + double get value => _value; + set value(double v) { + if (v < min) { + v = min; + } else if (v > max) { + v = max; + } + _value = v; + } + + Gauge(String name, String description, this.min, this.max) + : super(name, description) { + if (min is! double) { + throw new ArgumentError('min must be a double'); + } + if (max is! double) { + throw new ArgumentError('max must be a double'); + } + if (!(min < max)) { + throw new ArgumentError('min must be less than max'); + } + _value = min; + } + + Map _toJSON() { + var map = { + 'type': 'Gauge', + 'id': 'metrics/$name', + 'name': name, + 'description': description, + 'value': value, + 'min': min, + 'max': max, + }; + return map; + } +} + +/// A changing value. Initial value is 0.0. +class Counter extends Metric { + Counter(String name, String description) : super(name, description); + + double _value = 0.0; + double get value => _value; + set value(double v) { + _value = v; + } + + Map _toJSON() { + var map = { + 'type': 'Counter', + 'id': 'metrics/$name', + 'name': name, + 'description': description, + 'value': value, + }; + return map; + } +} + +class Metrics { + static final Map _metrics = new Map(); + + /// Register [Metric]s to make them visible to Observatory. + static void register(Metric metric) { + if (metric is! Metric) { + throw new ArgumentError('metric must be a Metric'); + } + if (_metrics[metric.name] != null) { + throw new ArgumentError('Registered metrics have unique names'); + } + _metrics[metric.name] = metric; + } + + /// Deregister [Metric]s to make them not visible to Observatory. + static void deregister(Metric metric) { + if (metric is! Metric) { + throw new ArgumentError('metric must be a Metric'); + } + _metrics.remove(metric.name); + } + + // ignore: unused_element, called from native code + static String _printMetric(String id) { + var metric = _metrics[id]; + if (metric == null) { + return null; + } + return json.encode(metric._toJSON()); + } + + // ignore: unused_element, called from native code + static String _printMetrics() { + var metrics = []; + for (var metric in _metrics.values) { + metrics.add(metric._toJSON()); + } + var map = { + 'type': 'MetricList', + 'metrics': metrics, + }; + return json.encode(map); + } +} +NN<HP#*K2*3"LLN$(07J+=#77<",G"I>(:)G$D*:"5**5"*%Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/developer/service.dart// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.developer; + +/// Service protocol is the protocol that a client like the Observatory +/// could use to access the services provided by the Dart VM for +/// debugging and inspecting Dart programs. This class encapsulates the +/// version number and Uri for accessing this service. +class ServiceProtocolInfo { + /// The major version of the protocol. If the running Dart environment does + /// not support the service protocol, this is 0. + final int majorVersion = _getServiceMajorVersion(); + + /// The minor version of the protocol. If the running Dart environment does + /// not support the service protocol, this is 0. + final int minorVersion = _getServiceMinorVersion(); + + /// The Uri to access the service. If the web server is not running, this + /// will be null. + final Uri serverUri; + + ServiceProtocolInfo(this.serverUri); + + String toString() { + if (serverUri != null) { + return 'Dart VM Service Protocol v$majorVersion.$minorVersion ' + 'listening on $serverUri'; + } else { + return 'Dart VM Service Protocol v$majorVersion.$minorVersion'; + } + } +} + +/// Access information about the service protocol and control the web server +/// that provides access to the services provided by the Dart VM for +/// debugging and inspecting Dart programs. +class Service { + /// Get information about the service protocol (version number and + /// Uri to access the service). + static Future getInfo() async { + // Port to receive response from service isolate. + final RawReceivePort receivePort = new RawReceivePort(); + final Completer uriCompleter = new Completer(); + receivePort.handler = (Uri uri) => uriCompleter.complete(uri); + // Request the information from the service isolate. + _getServerInfo(receivePort.sendPort); + // Await the response from the service isolate. + Uri uri = await uriCompleter.future; + // Close the port. + receivePort.close(); + return new ServiceProtocolInfo(uri); + } + + /// Control the web server that the service protocol is accessed through. + /// The [enable] argument must be a boolean and is used as a toggle to + /// enable (true) or disable (false) the web server servicing requests. + static Future controlWebServer( + {bool enable: false}) async { + if (enable is! bool) { + throw new ArgumentError.value(enable, 'enable', 'Must be a bool'); + } + // Port to receive response from service isolate. + final RawReceivePort receivePort = new RawReceivePort(); + final Completer uriCompleter = new Completer(); + receivePort.handler = (Uri uri) => uriCompleter.complete(uri); + // Request the information from the service isolate. + _webServerControl(receivePort.sendPort, enable); + // Await the response from the service isolate. + Uri uri = await uriCompleter.future; + // Close the port. + receivePort.close(); + return new ServiceProtocolInfo(uri); + } + + /// Returns a [String] token representing the ID of [isolate]. + /// + /// Returns null if the running Dart environment does not support the service + /// protocol. + static String getIsolateID(Isolate isolate) { + if (isolate is! Isolate) { + throw new ArgumentError.value(isolate, 'isolate', 'Must be an Isolate'); + } + return _getIsolateIDFromSendPort(isolate.controlPort); + } +} + +/// [sendPort] will receive a Uri or null. +external void _getServerInfo(SendPort sendPort); + +/// [sendPort] will receive a Uri or null. +external void _webServerControl(SendPort sendPort, bool enable); + +/// Returns the major version of the service protocol. +external int _getServiceMajorVersion(); + +/// Returns the minor version of the service protocol. +external int _getServiceMinorVersion(); + +/// Returns the service id for the isolate that owns [sendPort]. +external String _getIsolateIDFromSendPort(SendPort sendPort); +hNN<HAH7N36N36L'F% FME,E"76=>C9*4))LIJ7$I6=>C954))AP0O;+1+A7(7(A>Ffile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/io.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * File, socket, HTTP, and other I/O support for non-web applications. + * + * **Important:** Browser-based applications can't use this library. + * Only servers, command-line scripts, and Flutter mobile apps can import + * and use dart:io. + * + * This library allows you to work with files, directories, + * sockets, processes, HTTP servers and clients, and more. + * Many operations related to input and output are asynchronous + * and are handled using [Future]s or [Stream]s, both of which + * are defined in the [dart:async + * library](../dart-async/dart-async-library.html). + * + * To use the dart:io library in your code: + * + * import 'dart:io'; + * + * For an introduction to I/O in Dart, see the [dart:io library + * tour](https://www.dartlang.org/dart-vm/io-library-tour). + * + * ## File, Directory, and Link + * + * An instance of [File], [Directory], or [Link] represents a file, + * directory, or link, respectively, in the native file system. + * + * You can manipulate the file system through objects of these types. + * For example, you can rename a file or directory: + * + * File myFile = new File('myFile.txt'); + * myFile.rename('yourFile.txt').then((_) => print('file renamed')); + * + * Many methods provided by the File, Directory, and Link classes + * run asynchronously and return a Future. + * + * ## FileSystemEntity + * + * File, Directory, and Link all extend [FileSystemEntity]. + * In addition to being the superclass for these classes, + * FileSystemEntity has a number of static methods for working with paths. + * + * To get information about a path, + * you can use the FileSystemEntity static methods + * such as 'isDirectory', 'isFile', and 'exists'. + * Because file system access involves I/O, these methods + * are asynchronous and return a Future. + * + * FileSystemEntity.isDirectory(myPath).then((isDir) { + * if (isDir) { + * print('$myPath is a directory'); + * } else { + * print('$myPath is not a directory'); + * } + * }); + * + * ## HttpServer and HttpClient + * + * The classes [HttpServer] and [HttpClient] + * provide HTTP server and HTTP client functionality. + * + * The [HttpServer] class provides the basic functionality for + * implementing an HTTP server. + * For some higher-level building-blocks, we recommend that you try + * the [shelf](https://pub.dartlang.org/packages/shelf) + * pub package, which contains + * a set of high-level classes that, together with the [HttpServer] class + * in this library, make it easier to implement HTTP servers. + * + * ## Process + * + * The [Process] class provides a way to run a process on + * the native machine. + * For example, the following code spawns a process that recursively lists + * the files under `web`. + * + * Process.start('ls', ['-R', 'web']).then((process) { + * stdout.addStream(process.stdout); + * stderr.addStream(process.stderr); + * process.exitCode.then(print); + * }); + * + * Using `start()` returns a Future, which completes with a [Process] object + * when the process has started. This [Process] object allows you to interact + * with the process while it is running. Using `run()` returns a Future, which + * completes with a [ProcessResult] object when the spawned process has + * terminated. This [ProcessResult] object collects the output and exit code + * from the process. + * + * When using `start()`, + * you need to read all data coming on the stdout and stderr streams otherwise + * the system resources will not be freed. + * + * ## WebSocket + * + * The [WebSocket] class provides support for the web socket protocol. This + * allows full-duplex communications between client and server applications. + * + * A web socket server uses a normal HTTP server for accepting web socket + * connections. The initial handshake is a HTTP request which is then upgraded to a + * web socket connection. + * The server upgrades the request using [WebSocketTransformer] + * and listens for the data on the returned web socket. + * For example, here's a mini server that listens for 'ws' data + * on a WebSocket: + * + * runZoned(() async { + * var server = await HttpServer.bind('127.0.0.1', 4040); + * server.listen((HttpRequest req) async { + * if (req.uri.path == '/ws') { + * var socket = await WebSocketTransformer.upgrade(req); + * socket.listen(handleMsg); + * } + * }); + * }, onError: (e) => print("An error occurred.")); + * + * The client connects to the WebSocket using the `connect()` method + * and a URI that uses the Web Socket protocol. + * The client can write to the WebSocket with the `add()` method. + * For example, + * + * var socket = await WebSocket.connect('ws://127.0.0.1:4040/ws'); + * socket.add('Hello, World!'); + * + * Check out the + * [websocket_sample](https://github.com/dart-lang/dart-samples/tree/master/html5/web/websockets/basics) + * app, which uses WebSockets to communicate with a server. + * + * ## Socket and ServerSocket + * + * Clients and servers use [Socket]s to communicate using the TCP protocol. + * Use [ServerSocket] on the server side and [Socket] on the client. + * The server creates a listening socket using the `bind()` method and + * then listens for incoming connections on the socket. For example: + * + * ServerSocket.bind('127.0.0.1', 4041) + * .then((serverSocket) { + * serverSocket.listen((socket) { + * socket.transform(utf8.decoder).listen(print); + * }); + * }); + * + * A client connects a Socket using the `connect()` method, + * which returns a Future. + * Using `write()`, `writeln()`, or `writeAll()` are the easiest ways to + * send data over the socket. + * For example: + * + * Socket.connect('127.0.0.1', 4041).then((socket) { + * socket.write('Hello, World!'); + * }); + * + * Besides [Socket] and [ServerSocket], the [RawSocket] and + * [RawServerSocket] classes are available for lower-level access + * to async socket IO. + * + * ## Standard output, error, and input streams + * + * This library provides the standard output, error, and input + * streams, named 'stdout', 'stderr', and 'stdin', respectively. + * + * The stdout and stderr streams are both [IOSink]s and have the same set + * of methods and properties. + * + * To write a string to 'stdout': + * + * stdout.writeln('Hello, World!'); + * + * To write a list of objects to 'stderr': + * + * stderr.writeAll([ 'That ', 'is ', 'an ', 'error.', '\n']); + * + * The standard input stream is a true [Stream], so it inherits + * properties and methods from the Stream class. + * + * To read text synchronously from the command line + * (the program blocks waiting for user to type information): + * + * String inputText = stdin.readLineSync(); + * + * {@category VM} + */ +library dart.io; + +import 'dart:async'; +import 'dart:_internal' hide Symbol; +import 'dart:collection' + show HashMap, HashSet, Queue, ListQueue, MapBase, UnmodifiableMapView; +import 'dart:convert'; +import 'dart:developer' hide log; +import 'dart:isolate'; +import 'dart:math'; +import 'dart:typed_data'; + +export 'dart:_http'; + +part 'bytes_builder.dart'; +part 'common.dart'; +part 'data_transformer.dart'; +part 'directory.dart'; +part 'directory_impl.dart'; +part 'embedder_config.dart'; +part 'eventhandler.dart'; +part 'file.dart'; +part 'file_impl.dart'; +part 'file_system_entity.dart'; +part 'io_resource_info.dart'; +part 'io_sink.dart'; +part 'io_service.dart'; +part 'link.dart'; +part 'namespace_impl.dart'; +part 'overrides.dart'; +part 'platform.dart'; +part 'platform_impl.dart'; +part 'process.dart'; +part 'secure_server_socket.dart'; +part 'secure_socket.dart'; +part 'security_context.dart'; +part 'service_object.dart'; +part 'socket.dart'; +part 'stdio.dart'; +part 'string_transformer.dart'; +part 'sync_socket.dart'; +NN<GEJ<;@?"4,@< D@F4-IB+<:K$32:);,0  -6? D8J>:K;++' MNOHMO+LMJT@8@@1(C' 8E0BG$i<LEGE, *; <I9( 1%K" " Qfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/bytes_builder.dartj// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * Builds a list of bytes, allowing bytes and lists of bytes to be added at the + * end. + * + * Used to efficiently collect bytes and lists of bytes. + */ +abstract class BytesBuilder { + /** + * Construct a new empty [BytesBuilder]. + * + * If [copy] is true, the data is always copied when added to the list. If + * it [copy] is false, the data is only copied if needed. That means that if + * the lists are changed after added to the [BytesBuilder], it may effect the + * output. Default is `true`. + */ + factory BytesBuilder({bool copy: true}) { + if (copy) { + return new _CopyingBytesBuilder(); + } else { + return new _BytesBuilder(); + } + } + + /** + * Appends [bytes] to the current contents of the builder. + * + * Each value of [bytes] will be bit-representation truncated to the range + * 0 .. 255. + */ + void add(List bytes); + + /** + * Append [byte] to the current contents of the builder. + * + * The [byte] will be bit-representation truncated to the range 0 .. 255. + */ + void addByte(int byte); + + /** + * Returns the contents of `this` and clears `this`. + * + * The list returned is a view of the internal buffer, limited to the + * [length]. + */ + List takeBytes(); + + /** + * Returns a copy of the current contents of the builder. + * + * Leaves the contents of the builder intact. + */ + List toBytes(); + + /** + * The number of bytes in the builder. + */ + int get length; + + /** + * Returns `true` if the buffer is empty. + */ + bool get isEmpty; + + /** + * Returns `true` if the buffer is not empty. + */ + bool get isNotEmpty; + + /** + * Clear the contents of the builder. + */ + void clear(); +} + +class _CopyingBytesBuilder implements BytesBuilder { + // Start with 1024 bytes. + static const int _initSize = 1024; + + static final _emptyList = new Uint8List(0); + + int _length = 0; + Uint8List _buffer; + + _CopyingBytesBuilder([int initialCapacity = 0]) + : _buffer = (initialCapacity <= 0) + ? _emptyList + : new Uint8List(_pow2roundup(initialCapacity)); + + void add(List bytes) { + int bytesLength = bytes.length; + if (bytesLength == 0) return; + int required = _length + bytesLength; + if (_buffer.length < required) { + _grow(required); + } + assert(_buffer.length >= required); + if (bytes is Uint8List) { + _buffer.setRange(_length, required, bytes); + } else { + for (int i = 0; i < bytesLength; i++) { + _buffer[_length + i] = bytes[i]; + } + } + _length = required; + } + + void addByte(int byte) { + if (_buffer.length == _length) { + // The grow algorithm always at least doubles. + // If we added one to _length it would quadruple unnecessarily. + _grow(_length); + } + assert(_buffer.length > _length); + _buffer[_length] = byte; + _length++; + } + + void _grow(int required) { + // We will create a list in the range of 2-4 times larger than + // required. + int newSize = required * 2; + if (newSize < _initSize) { + newSize = _initSize; + } else { + newSize = _pow2roundup(newSize); + } + var newBuffer = new Uint8List(newSize); + newBuffer.setRange(0, _buffer.length, _buffer); + _buffer = newBuffer; + } + + List takeBytes() { + if (_length == 0) return _emptyList; + var buffer = new Uint8List.view(_buffer.buffer, 0, _length); + clear(); + return buffer; + } + + List toBytes() { + if (_length == 0) return _emptyList; + return new Uint8List.fromList( + new Uint8List.view(_buffer.buffer, 0, _length)); + } + + int get length => _length; + + bool get isEmpty => _length == 0; + + bool get isNotEmpty => _length != 0; + + void clear() { + _length = 0; + _buffer = _emptyList; + } + + static int _pow2roundup(int x) { + assert(x > 0); + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; + } +} + +class _BytesBuilder implements BytesBuilder { + int _length = 0; + final List _chunks = []; + + void add(List bytes) { + Uint8List typedBytes; + if (bytes is Uint8List) { + typedBytes = bytes; + } else { + typedBytes = new Uint8List.fromList(bytes); + } + _chunks.add(typedBytes); + _length += typedBytes.length; + } + + void addByte(int byte) { + _chunks.add(new Uint8List(1)..[0] = byte); + _length++; + } + + List takeBytes() { + if (_length == 0) return _CopyingBytesBuilder._emptyList; + if (_chunks.length == 1) { + var buffer = _chunks[0]; + clear(); + return buffer; + } + var buffer = new Uint8List(_length); + int offset = 0; + for (var chunk in _chunks) { + buffer.setRange(offset, offset + chunk.length, chunk); + offset += chunk.length; + } + clear(); + return buffer; + } + + List toBytes() { + if (_length == 0) return _CopyingBytesBuilder._emptyList; + var buffer = new Uint8List(_length); + int offset = 0; + for (var chunk in _chunks) { + buffer.setRange(offset, offset + chunk.length, chunk); + offset += chunk.length; + } + return buffer; + } + + int get length => _length; + + bool get isEmpty => _length == 0; + + bool get isNotEmpty => _length != 0; + + void clear() { + _length = 0; + _chunks.clear(); + } +} +NN<P9+MOP ,) "=M;L7H<0),0(5%.2)<$"*%(2 .)%5F&C  ',4)A )#9$'# .& 2"/>)!= >)!=$'Jfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/common.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +// Constants used when working with native ports. +// These must match the constants in runtime/bin/dartutils.h class CObject. +const int _successResponse = 0; +const int _illegalArgumentResponse = 1; +const int _osErrorResponse = 2; +const int _fileClosedResponse = 3; + +const int _errorResponseErrorType = 0; +const int _osErrorResponseErrorCode = 1; +const int _osErrorResponseMessage = 2; + +// Functions used to receive exceptions from native ports. +bool _isErrorResponse(response) => + response is List && response[0] != _successResponse; + +/** + * Returns an Exception or an Error + */ +_exceptionFromResponse(response, String message, String path) { + assert(_isErrorResponse(response)); + switch (response[_errorResponseErrorType]) { + case _illegalArgumentResponse: + return new ArgumentError("$message: $path"); + case _osErrorResponse: + var err = new OSError(response[_osErrorResponseMessage], + response[_osErrorResponseErrorCode]); + return new FileSystemException(message, path, err); + case _fileClosedResponse: + return new FileSystemException("File closed", path); + default: + return new Exception("Unknown error"); + } +} + +/** + * Base class for all IO related exceptions. + */ +abstract class IOException implements Exception { + String toString() => "IOException"; +} + +/** + * An [OSError] object holds information about an error from the + * operating system. + */ +class OSError { + /** Constant used to indicate that no OS error code is available. */ + static const int noErrorCode = -1; + + /// Error message supplied by the operating system. This may be `null` or + /// empty if no message is associated with the error. + final String message; + + /// Error code supplied by the operating system. + /// + /// Will have the value [OSError.noErrorCode] if there is no error code + /// associated with the error. + final int errorCode; + + /** Creates an OSError object from a message and an errorCode. */ + const OSError([this.message = "", this.errorCode = noErrorCode]); + + /** Converts an OSError object to a string representation. */ + String toString() { + StringBuffer sb = new StringBuffer(); + sb.write("OS Error"); + if (!message.isEmpty) { + sb..write(": ")..write(message); + if (errorCode != noErrorCode) { + sb..write(", errno = ")..write(errorCode.toString()); + } + } else if (errorCode != noErrorCode) { + sb..write(": errno = ")..write(errorCode.toString()); + } + return sb.toString(); + } +} + +// Object for holding a buffer and an offset. +class _BufferAndStart { + List buffer; + int start; + _BufferAndStart(this.buffer, this.start); +} + +// Ensure that the input List can be serialized through a native port. +// Only Int8List and Uint8List Lists are serialized directly. +// All other lists are first copied into a Uint8List. This has the added +// benefit that it is faster to access from the C code as well. +_BufferAndStart _ensureFastAndSerializableByteData( + List buffer, int start, int end) { + if (buffer is Uint8List || buffer is Int8List) { + return new _BufferAndStart(buffer, start); + } + int length = end - start; + var newBuffer = new Uint8List(length); + int j = start; + for (int i = 0; i < length; i++) { + int value = buffer[j]; + if (value is! int) { + throw new ArgumentError("List element is not an integer at index $j"); + } + newBuffer[i] = value; + j++; + } + return new _BufferAndStart(newBuffer, 0); +} + +class _IOCrypto { + external static Uint8List getRandomBytes(int count); +} +wNN<2L ( #')';#9$@&/#3?0:; --2&BG%L83J!DD@*'&>+<. ,G>I@4,3/)%M ,7gfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart9// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:_js_helper' show patch; +import 'dart:async'; +import 'dart:convert'; +import 'dart:isolate' show SendPort; +import 'dart:typed_data'; + +@patch +class _Directory { + @patch + static _current(_Namespace namespace) { + throw UnsupportedError("Directory._current"); + } + + @patch + static _setCurrent(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("Directory_SetCurrent"); + } + + @patch + static _createTemp(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("Directory._createTemp"); + } + + @patch + static String _systemTemp(_Namespace namespace) { + throw UnsupportedError("Directory._systemTemp"); + } + + @patch + static _exists(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("Directory._exists"); + } + + @patch + static _create(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("Directory._create"); + } + + @patch + static _deleteNative( + _Namespace namespace, Uint8List rawPath, bool recursive) { + throw UnsupportedError("Directory._deleteNative"); + } + + @patch + static _rename(_Namespace namespace, Uint8List rawPath, String newPath) { + throw UnsupportedError("Directory._rename"); + } + + @patch + static void _fillWithDirectoryListing( + _Namespace namespace, + List list, + Uint8List rawPath, + bool recursive, + bool followLinks) { + throw UnsupportedError("Directory._fillWithDirectoryListing"); + } +} + +@patch +class _AsyncDirectoryListerOps { + @patch + factory _AsyncDirectoryListerOps(int pointer) { + throw UnsupportedError("Directory._list"); + } +} + +@patch +class _EventHandler { + @patch + static void _sendData(Object sender, SendPort sendPort, int data) { + throw UnsupportedError("EventHandler._sendData"); + } +} + +@patch +class FileStat { + @patch + static _statSync(_Namespace namespace, String path) { + throw UnsupportedError("FileStat.stat"); + } +} + +@patch +class FileSystemEntity { + @patch + static _getTypeNative( + _Namespace namespace, Uint8List rawPath, bool followLinks) { + throw UnsupportedError("FileSystemEntity._getType"); + } + + @patch + static _identicalNative(_Namespace namespace, String path1, String path2) { + throw UnsupportedError("FileSystemEntity._identical"); + } + + @patch + static _resolveSymbolicLinks(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("FileSystemEntity._resolveSymbolicLinks"); + } +} + +@patch +class _File { + @patch + static _exists(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._exists"); + } + + @patch + static _create(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._create"); + } + + @patch + static _createLink(_Namespace namespace, Uint8List rawPath, String target) { + throw UnsupportedError("File._createLink"); + } + + @patch + static _linkTarget(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._linkTarget"); + } + + @patch + static _deleteNative(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._deleteNative"); + } + + @patch + static _deleteLinkNative(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._deleteLinkNative"); + } + + @patch + static _rename(_Namespace namespace, Uint8List oldPath, String newPath) { + throw UnsupportedError("File._rename"); + } + + @patch + static _renameLink(_Namespace namespace, Uint8List oldPath, String newPath) { + throw UnsupportedError("File._renameLink"); + } + + @patch + static _copy(_Namespace namespace, Uint8List oldPath, String newPath) { + throw UnsupportedError("File._copy"); + } + + @patch + static _lengthFromPath(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._lengthFromPath"); + } + + @patch + static _lastModified(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._lastModified"); + } + + @patch + static _lastAccessed(_Namespace namespace, Uint8List rawPath) { + throw UnsupportedError("File._lastAccessed"); + } + + @patch + static _setLastModified(_Namespace namespace, Uint8List rawPath, int millis) { + throw UnsupportedError("File._setLastModified"); + } + + @patch + static _setLastAccessed(_Namespace namespace, Uint8List rawPath, int millis) { + throw UnsupportedError("File._setLastAccessed"); + } + + @patch + static _open(_Namespace namespace, Uint8List rawPath, int mode) { + throw UnsupportedError("File._open"); + } + + @patch + static int _openStdio(int fd) { + throw UnsupportedError("File._openStdio"); + } +} + +@patch +class _Namespace { + @patch + static void _setupNamespace(var namespace) { + throw UnsupportedError("_Namespace"); + } + + @patch + static _Namespace get _namespace { + throw UnsupportedError("_Namespace"); + } + + @patch + static int get _namespacePointer { + throw UnsupportedError("_Namespace"); + } +} + +@patch +class _RandomAccessFileOps { + @patch + factory _RandomAccessFileOps(int pointer) { + throw UnsupportedError("RandomAccessFile"); + } +} + +@patch +class _IOCrypto { + @patch + static Uint8List getRandomBytes(int count) { + throw UnsupportedError("_IOCrypto.getRandomBytes"); + } +} + +@patch +class _Platform { + @patch + static int _numberOfProcessors() { + throw UnsupportedError("Platform._numberOfProcessors"); + } + + @patch + static String _pathSeparator() { + throw UnsupportedError("Platform._pathSeparator"); + } + + @patch + static String _operatingSystem() { + throw UnsupportedError("Platform._operatingSystem"); + } + + @patch + static _operatingSystemVersion() { + throw UnsupportedError("Platform._operatingSystemVersion"); + } + + @patch + static _localHostname() { + throw UnsupportedError("Platform._localHostname"); + } + + @patch + static _executable() { + throw UnsupportedError("Platform._executable"); + } + + @patch + static _resolvedExecutable() { + throw UnsupportedError("Platform._resolvedExecutable"); + } + + @patch + static List _executableArguments() { + throw UnsupportedError("Platform._executableArguments"); + } + + @patch + static String _packageRoot() { + throw UnsupportedError("Platform._packageRoot"); + } + + @patch + static String _packageConfig() { + throw UnsupportedError("Platform._packageConfig"); + } + + @patch + static _environment() { + throw UnsupportedError("Platform._environment"); + } + + @patch + static String _version() { + throw UnsupportedError("Platform._version"); + } + + @patch + static String _localeName() { + throw UnsupportedError("Platform._localeName"); + } + + @patch + static Uri _script() { + throw UnsupportedError("Platform._script"); + } +} + +@patch +class _ProcessUtils { + @patch + static void _exit(int status) { + throw UnsupportedError("ProcessUtils._exit"); + } + + @patch + static void _setExitCode(int status) { + throw UnsupportedError("ProcessUtils._setExitCode"); + } + + @patch + static int _getExitCode() { + throw UnsupportedError("ProcessUtils._getExitCode"); + } + + @patch + static void _sleep(int millis) { + throw UnsupportedError("ProcessUtils._sleep"); + } + + @patch + static int _pid(Process process) { + throw UnsupportedError("ProcessUtils._pid"); + } + + @patch + static Stream _watchSignal(ProcessSignal signal) { + throw UnsupportedError("ProcessUtils._watchSignal"); + } +} + +@patch +class ProcessInfo { + @patch + static int get currentRss { + throw UnsupportedError("ProcessInfo.currentRss"); + } + + @patch + static int get maxRss { + throw UnsupportedError("ProcessInfo.maxRss"); + } +} + +@patch +class Process { + @patch + static Future start(String executable, List arguments, + {String workingDirectory, + Map environment, + bool includeParentEnvironment = true, + bool runInShell = false, + ProcessStartMode mode = ProcessStartMode.normal}) { + throw UnsupportedError("Process.start"); + } + + @patch + static Future run(String executable, List arguments, + {String workingDirectory, + Map environment, + bool includeParentEnvironment = true, + bool runInShell = false, + Encoding stdoutEncoding = systemEncoding, + Encoding stderrEncoding = systemEncoding}) { + throw UnsupportedError("Process.run"); + } + + @patch + static ProcessResult runSync(String executable, List arguments, + {String workingDirectory, + Map environment, + bool includeParentEnvironment = true, + bool runInShell = false, + Encoding stdoutEncoding = systemEncoding, + Encoding stderrEncoding = systemEncoding}) { + throw UnsupportedError("Process.runSync"); + } + + @patch + static bool killPid(int pid, [ProcessSignal signal = ProcessSignal.sigterm]) { + throw UnsupportedError("Process.killPid"); + } +} + +@patch +class InternetAddress { + @patch + static InternetAddress get LOOPBACK_IP_V4 { + throw UnsupportedError("InternetAddress.LOOPBACK_IP_V4"); + } + + @patch + static InternetAddress get LOOPBACK_IP_V6 { + throw UnsupportedError("InternetAddress.LOOPBACK_IP_V6"); + } + + @patch + static InternetAddress get ANY_IP_V4 { + throw UnsupportedError("InternetAddress.ANY_IP_V4"); + } + + @patch + static InternetAddress get ANY_IP_V6 { + throw UnsupportedError("InternetAddress.ANY_IP_V6"); + } + + @patch + factory InternetAddress(String address) { + throw UnsupportedError("InternetAddress"); + } + @patch + static Future> lookup(String host, + {InternetAddressType type = InternetAddressType.any}) { + throw UnsupportedError("InternetAddress.lookup"); + } + + @patch + static InternetAddress _cloneWithNewHost( + InternetAddress address, String host) { + throw UnsupportedError("InternetAddress._cloneWithNewHost"); + } +} + +@patch +class NetworkInterface { + @patch + static bool get listSupported { + throw UnsupportedError("NetworkInterface.listSupported"); + } + + @patch + static Future> list( + {bool includeLoopback = false, + bool includeLinkLocal = false, + InternetAddressType type = InternetAddressType.any}) { + throw UnsupportedError("NetworkInterface.list"); + } +} + +@patch +class RawServerSocket { + @patch + static Future bind(address, int port, + {int backlog = 0, bool v6Only = false, bool shared = false}) { + throw UnsupportedError("RawServerSocket.bind"); + } +} + +@patch +class ServerSocket { + @patch + static Future bind(address, int port, + {int backlog = 0, bool v6Only = false, bool shared = false}) { + throw UnsupportedError("ServerSocket.bind"); + } +} + +@patch +class RawSocket { + @patch + static Future connect(host, int port, + {sourceAddress, Duration timeout}) { + throw UnsupportedError("RawSocket constructor"); + } + + @patch + static Future> startConnect(host, int port, + {sourceAddress}) { + throw UnsupportedError("RawSocket constructor"); + } +} + +@patch +class Socket { + @patch + static Future _connect(host, int port, + {sourceAddress, Duration timeout}) { + throw UnsupportedError("Socket constructor"); + } + + @patch + static Future> _startConnect(host, int port, + {sourceAddress}) { + throw UnsupportedError("Socket constructor"); + } +} + +@patch +class SecureSocket { + @patch + factory SecureSocket._(RawSecureSocket rawSocket) { + throw UnsupportedError("SecureSocket constructor"); + } +} + +@patch +class RawSynchronousSocket { + @patch + static RawSynchronousSocket connectSync(host, int port) { + throw UnsupportedError("RawSynchronousSocket.connectSync"); + } +} + +@patch +class SecurityContext { + @patch + factory SecurityContext({bool withTrustedRoots = false}) { + throw UnsupportedError("SecurityContext constructor"); + } + + @patch + static SecurityContext get defaultContext { + throw UnsupportedError("default SecurityContext getter"); + } + + @patch + static bool get alpnSupported { + throw UnsupportedError("SecurityContext alpnSupported getter"); + } +} + +@patch +class X509Certificate { + @patch + factory X509Certificate._() { + throw UnsupportedError("X509Certificate constructor"); + } +} + +@patch +class RawDatagramSocket { + @patch + static Future bind(host, int port, + {bool reuseAddress = true}) { + throw UnsupportedError("RawDatagramSocket.bind"); + } +} + +@patch +class _SecureFilter { + @patch + factory _SecureFilter() { + throw UnsupportedError("_SecureFilter._SecureFilter"); + } +} + +@patch +class _StdIOUtils { + @patch + static Stdin _getStdioInputStream(int fd) { + throw UnsupportedError("StdIOUtils._getStdioInputStream"); + } + + @patch + static _getStdioOutputStream(int fd) { + throw UnsupportedError("StdIOUtils._getStdioOutputStream"); + } + + @patch + static int _socketType(Socket socket) { + throw UnsupportedError("StdIOUtils._socketType"); + } + + @patch + static _getStdioHandleType(int fd) { + throw UnsupportedError("StdIOUtils._getStdioHandleType"); + } +} + +@patch +class _WindowsCodePageDecoder { + @patch + static String _decodeBytes(List bytes) { + throw UnsupportedError("_WindowsCodePageDecoder._decodeBytes"); + } +} + +@patch +class _WindowsCodePageEncoder { + @patch + static List _encodeString(String string) { + throw UnsupportedError("_WindowsCodePageEncoder._encodeString"); + } +} + +@patch +class RawZLibFilter { + @patch + static RawZLibFilter _makeZLibDeflateFilter( + bool gzip, + int level, + int windowBits, + int memLevel, + int strategy, + List dictionary, + bool raw) { + throw UnsupportedError("_newZLibDeflateFilter"); + } + + @patch + static RawZLibFilter _makeZLibInflateFilter( + int windowBits, List dictionary, bool raw) { + throw UnsupportedError("_newZLibInflateFilter"); + } +} + +@patch +class Stdin { + @patch + int readByteSync() { + throw UnsupportedError("Stdin.readByteSync"); + } + + @patch + bool get echoMode { + throw UnsupportedError("Stdin.echoMode"); + } + + @patch + void set echoMode(bool enabled) { + throw UnsupportedError("Stdin.echoMode"); + } + + @patch + bool get lineMode { + throw UnsupportedError("Stdin.lineMode"); + } + + @patch + void set lineMode(bool enabled) { + throw UnsupportedError("Stdin.lineMode"); + } + + @patch + bool get supportsAnsiEscapes { + throw UnsupportedError("Stdin.supportsAnsiEscapes"); + } +} + +@patch +class Stdout { + @patch + bool _hasTerminal(int fd) { + throw UnsupportedError("Stdout.hasTerminal"); + } + + @patch + int _terminalColumns(int fd) { + throw UnsupportedError("Stdout.terminalColumns"); + } + + @patch + int _terminalLines(int fd) { + throw UnsupportedError("Stdout.terminalLines"); + } + + @patch + static bool _supportsAnsiEscapes(int fd) { + throw UnsupportedError("Stdout.supportsAnsiEscapes"); + } +} + +@patch +class _FileSystemWatcher { + @patch + static Stream _watch( + String path, int events, bool recursive) { + throw UnsupportedError("_FileSystemWatcher.watch"); + } + + @patch + static bool get isSupported { + throw UnsupportedError("_FileSystemWatcher.isSupported"); + } +} + +@patch +class _IOService { + @patch + static Future _dispatch(int request, List data) { + throw UnsupportedError("_IOService._dispatch"); + } +} +NN<%% *2 @4 @5 45 <1 <1 A7 L1 )#C! 2/ F6 8- C9 N; JF <, <, O0 @0 B2 F6 L, P0 J* D4 B2 B2 Q5 Q5 D* "/ /* %* %* .0 /8 %< #7 %9 %@ 7 4 !< /= !5 #7 5 1 4 0 "2 )9 9 #3 %1 D9 6 2 J ',:- N ',03+ J ',03/ Q/ .> .> )9 )9 ,/ ;>6 ,.A "> .%%=5 9E4 6E1 3+5 H5 1+2 F2 68 <@ =; .> "D ; 8$6 ; .? )@ *6 '> 0D 2E /5 /85 2 . $. . $. !9 2 !6 4 -: )18 > 44Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/data_transformer.dartUh// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * Exposes ZLib options for input parameters. + * + * See http://www.zlib.net/manual.html for more documentation. + */ +abstract class ZLibOption { + /// Minimal value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits] + /// and [ZLibDecoder.windowBits]. + static const int minWindowBits = 8; + @Deprecated("Use minWindowBits instead") + static const int MIN_WINDOW_BITS = 8; + + /// Maximal value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits] + /// and [ZLibDecoder.windowBits]. + static const int maxWindowBits = 15; + @Deprecated("Use maxWindowBits instead") + static const int MAX_WINDOW_BITS = 15; + + /// Default value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits] + /// and [ZLibDecoder.windowBits]. + static const int defaultWindowBits = 15; + @Deprecated("Use defaultWindowBits instead") + static const int DEFAULT_WINDOW_BITS = 15; + + /// Minimal value for [ZLibCodec.level] and [ZLibEncoder.level]. + static const int minLevel = -1; + @Deprecated("Use minLevel instead") + static const int MIN_LEVEL = -1; + + /// Maximal value for [ZLibCodec.level] and [ZLibEncoder.level] + static const int maxLevel = 9; + @Deprecated("Use maxLevel instead") + static const int MAX_LEVEL = 9; + + /// Default value for [ZLibCodec.level] and [ZLibEncoder.level]. + static const int defaultLevel = 6; + @Deprecated("Use defaultLevel instead") + static const int DEFAULT_LEVEL = 6; + + /// Minimal value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel]. + static const int minMemLevel = 1; + @Deprecated("Use minMemLevel instead") + static const int MIN_MEM_LEVEL = 1; + + /// Maximal value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel]. + static const int maxMemLevel = 9; + @Deprecated("Use maxMemLevel instead") + static const int MAX_MEM_LEVEL = 9; + + /// Default value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel]. + static const int defaultMemLevel = 8; + @Deprecated("Use defaultMemLevel instead") + static const int DEFAULT_MEM_LEVEL = 8; + + /// Recommended strategy for data produced by a filter (or predictor) + static const int strategyFiltered = 1; + @Deprecated("Use strategyFiltered instead") + static const int STRATEGY_FILTERED = 1; + + /// Use this strategy to force Huffman encoding only (no string match) + static const int strategyHuffmanOnly = 2; + @Deprecated("Use strategyHuffmanOnly instead") + static const int STRATEGY_HUFFMAN_ONLY = 2; + + /// Use this strategy to limit match distances to one (run-length encoding) + static const int strategyRle = 3; + @Deprecated("Use strategyRle instead") + static const int STRATEGY_RLE = 3; + + /// This strategy prevents the use of dynamic Huffman codes, allowing for a + /// simpler decoder + static const int strategyFixed = 4; + @Deprecated("Use strategyFixed instead") + static const int STRATEGY_FIXED = 4; + + /// Recommended strategy for normal data + static const int strategyDefault = 0; + @Deprecated("Use strategyDefault instead") + static const int STRATEGY_DEFAULT = 0; +} + +/** + * An instance of the default implementation of the [ZLibCodec]. + */ +const ZLibCodec zlib = const ZLibCodec._default(); +@Deprecated("Use zlib instead") +const ZLibCodec ZLIB = zlib; + +/** + * The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib + * compressed bytes to raw bytes. + */ +class ZLibCodec extends Codec, List> { + /** + * When true, `GZip` frames will be added to the compressed data. + */ + final bool gzip; + + /** + * The compression-[level] can be set in the range of `-1..9`, with `6` being + * the default compression level. Levels above `6` will have higher + * compression rates at the cost of more CPU and memory usage. Levels below + * `6` will use less CPU and memory at the cost of lower compression rates. + */ + final int level; + + /** + * Specifies how much memory should be allocated for the internal compression + * state. `1` uses minimum memory but is slow and reduces compression ratio; + * `9` uses maximum memory for optimal speed. The default value is `8`. + * + * The memory requirements for deflate are (in bytes): + * + * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) + * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) + */ + final int memLevel; + + /** + * Tunes the compression algorithm. Use the value strategyDefault for normal + * data, strategyFiltered for data produced by a filter (or predictor), + * strategyHuffmanOnly to force Huffman encoding only (no string match), or + * strategyRle to limit match distances to one (run-length encoding). + */ + final int strategy; + + /** + * Base two logarithm of the window size (the size of the history buffer). It + * should be in the range 8..15. Larger values result in better compression at + * the expense of memory usage. The default value is 15 + */ + final int windowBits; + + /** + * When true, deflate generates raw data with no zlib header or trailer, and + * will not compute an adler32 check value + */ + final bool raw; + + /** + * Initial compression dictionary. + * + * It should consist of strings (byte sequences) that are likely to be + * encountered later in the data to be compressed, with the most commonly used + * strings preferably put towards the end of the dictionary. Using a + * dictionary is most useful when the data to be compressed is short and can + * be predicted with good accuracy; the data can then be compressed better + * than with the default empty dictionary. + */ + final List dictionary; + + ZLibCodec( + {this.level: ZLibOption.defaultLevel, + this.windowBits: ZLibOption.defaultWindowBits, + this.memLevel: ZLibOption.defaultMemLevel, + this.strategy: ZLibOption.strategyDefault, + this.dictionary: null, + this.raw: false, + this.gzip: false}) { + _validateZLibeLevel(level); + _validateZLibMemLevel(memLevel); + _validateZLibStrategy(strategy); + _validateZLibWindowBits(windowBits); + } + + const ZLibCodec._default() + : level = ZLibOption.defaultLevel, + windowBits = ZLibOption.defaultWindowBits, + memLevel = ZLibOption.defaultMemLevel, + strategy = ZLibOption.strategyDefault, + raw = false, + gzip = false, + dictionary = null; + + /** + * Get a [ZLibEncoder] for encoding to `ZLib` compressed data. + */ + ZLibEncoder get encoder => new ZLibEncoder( + gzip: false, + level: level, + windowBits: windowBits, + memLevel: memLevel, + strategy: strategy, + dictionary: dictionary, + raw: raw); + + /** + * Get a [ZLibDecoder] for decoding `ZLib` compressed data. + */ + ZLibDecoder get decoder => + new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw); +} + +/** + * An instance of the default implementation of the [GZipCodec]. + */ +const GZipCodec gzip = const GZipCodec._default(); +@Deprecated("Use gzip instead") +const GZipCodec GZIP = gzip; + +/** + * The [GZipCodec] encodes raw bytes to GZip compressed bytes and decodes GZip + * compressed bytes to raw bytes. + * + * The difference between [ZLibCodec] and [GZipCodec] is that the [GZipCodec] + * wraps the `ZLib` compressed bytes in `GZip` frames. + */ +class GZipCodec extends Codec, List> { + /** + * When true, `GZip` frames will be added to the compressed data. + */ + final bool gzip; + + /** + * The compression-[level] can be set in the range of `-1..9`, with `6` being + * the default compression level. Levels above `6` will have higher + * compression rates at the cost of more CPU and memory usage. Levels below + * `6` will use less CPU and memory at the cost of lower compression rates. + */ + final int level; + + /** + * Specifies how much memory should be allocated for the internal compression + * state. `1` uses minimum memory but is slow and reduces compression ratio; + * `9` uses maximum memory for optimal speed. The default value is `8`. + * + * The memory requirements for deflate are (in bytes): + * + * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) + * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) + */ + final int memLevel; + + /** + * Tunes the compression algorithm. Use the value + * [ZLibOption.strategyDefault] for normal data, + * [ZLibOption.strategyFiltered] for data produced by a filter + * (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman + * encoding only (no string match), or [ZLibOption.strategyRle] to limit + * match distances to one (run-length encoding). + */ + final int strategy; + + /** + * Base two logarithm of the window size (the size of the history buffer). It + * should be in the range `8..15`. Larger values result in better compression + * at the expense of memory usage. The default value is `15` + */ + final int windowBits; + + /** + * Initial compression dictionary. + * + * It should consist of strings (byte sequences) that are likely to be + * encountered later in the data to be compressed, with the most commonly used + * strings preferably put towards the end of the dictionary. Using a + * dictionary is most useful when the data to be compressed is short and can + * be predicted with good accuracy; the data can then be compressed better + * than with the default empty dictionary. + */ + final List dictionary; + + /** + * When true, deflate generates raw data with no zlib header or trailer, and + * will not compute an adler32 check value + */ + final bool raw; + + GZipCodec( + {this.level: ZLibOption.defaultLevel, + this.windowBits: ZLibOption.defaultWindowBits, + this.memLevel: ZLibOption.defaultMemLevel, + this.strategy: ZLibOption.strategyDefault, + this.dictionary: null, + this.raw: false, + this.gzip: true}) { + _validateZLibeLevel(level); + _validateZLibMemLevel(memLevel); + _validateZLibStrategy(strategy); + _validateZLibWindowBits(windowBits); + } + + const GZipCodec._default() + : level = ZLibOption.defaultLevel, + windowBits = ZLibOption.defaultWindowBits, + memLevel = ZLibOption.defaultMemLevel, + strategy = ZLibOption.strategyDefault, + raw = false, + gzip = true, + dictionary = null; + + /** + * Get a [ZLibEncoder] for encoding to `GZip` compressed data. + */ + ZLibEncoder get encoder => new ZLibEncoder( + gzip: true, + level: level, + windowBits: windowBits, + memLevel: memLevel, + strategy: strategy, + dictionary: dictionary, + raw: raw); + + /** + * Get a [ZLibDecoder] for decoding `GZip` compressed data. + */ + ZLibDecoder get decoder => + new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw); +} + +/** + * The [ZLibEncoder] encoder is used by [ZLibCodec] and [GZipCodec] to compress + * data. + */ +class ZLibEncoder extends Converter, List> { + /** + * When true, `GZip` frames will be added to the compressed data. + */ + final bool gzip; + + /** + * The compression-[level] can be set in the range of `-1..9`, with `6` being + * the default compression level. Levels above `6` will have higher + * compression rates at the cost of more CPU and memory usage. Levels below + * `6` will use less CPU and memory at the cost of lower compression rates. + */ + final int level; + + /** + * Specifies how much memory should be allocated for the internal compression + * state. `1` uses minimum memory but is slow and reduces compression ratio; + * `9` uses maximum memory for optimal speed. The default value is `8`. + * + * The memory requirements for deflate are (in bytes): + * + * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) + * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) + */ + final int memLevel; + + /** + * Tunes the compression algorithm. Use the value + * [ZLibOption.strategyDefault] for normal data, + * [ZLibOption.strategyFiltered] for data produced by a filter + * (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman + * encoding only (no string match), or [ZLibOption.strategyRle] to limit + * match distances to one (run-length encoding). + */ + final int strategy; + + /** + * Base two logarithm of the window size (the size of the history buffer). It + * should be in the range `8..15`. Larger values result in better compression + * at the expense of memory usage. The default value is `15` + */ + final int windowBits; + + /** + * Initial compression dictionary. + * + * It should consist of strings (byte sequences) that are likely to be + * encountered later in the data to be compressed, with the most commonly used + * strings preferably put towards the end of the dictionary. Using a + * dictionary is most useful when the data to be compressed is short and can + * be predicted with good accuracy; the data can then be compressed better + * than with the default empty dictionary. + */ + final List dictionary; + + /** + * When true, deflate generates raw data with no zlib header or trailer, and + * will not compute an adler32 check value + */ + final bool raw; + + ZLibEncoder( + {this.gzip: false, + this.level: ZLibOption.defaultLevel, + this.windowBits: ZLibOption.defaultWindowBits, + this.memLevel: ZLibOption.defaultMemLevel, + this.strategy: ZLibOption.strategyDefault, + this.dictionary: null, + this.raw: false}) { + _validateZLibeLevel(level); + _validateZLibMemLevel(memLevel); + _validateZLibStrategy(strategy); + _validateZLibWindowBits(windowBits); + } + + /** + * Convert a list of bytes using the options given to the ZLibEncoder + * constructor. + */ + List convert(List bytes) { + _BufferSink sink = new _BufferSink(); + startChunkedConversion(sink) + ..add(bytes) + ..close(); + return sink.builder.takeBytes(); + } + + /** + * Start a chunked conversion using the options given to the [ZLibEncoder] + * constructor. While it accepts any [Sink] taking [List]'s, + * the optimal sink to be passed as [sink] is a [ByteConversionSink]. + */ + ByteConversionSink startChunkedConversion(Sink> sink) { + if (sink is! ByteConversionSink) { + sink = new ByteConversionSink.from(sink); + } + return new _ZLibEncoderSink( + sink, gzip, level, windowBits, memLevel, strategy, dictionary, raw); + } +} + +/** + * The [ZLibDecoder] is used by [ZLibCodec] and [GZipCodec] to decompress data. + */ +class ZLibDecoder extends Converter, List> { + /** + * Base two logarithm of the window size (the size of the history buffer). It + * should be in the range `8..15`. Larger values result in better compression + * at the expense of memory usage. The default value is `15`. + */ + final int windowBits; + + /** + * Initial compression dictionary. + * + * It should consist of strings (byte sequences) that are likely to be + * encountered later in the data to be compressed, with the most commonly used + * strings preferably put towards the end of the dictionary. Using a + * dictionary is most useful when the data to be compressed is short and can + * be predicted with good accuracy; the data can then be compressed better + * than with the default empty dictionary. + */ + final List dictionary; + + /** + * When true, deflate generates raw data with no zlib header or trailer, and + * will not compute an adler32 check value + */ + final bool raw; + + ZLibDecoder( + {this.windowBits: ZLibOption.defaultWindowBits, + this.dictionary: null, + this.raw: false}) { + _validateZLibWindowBits(windowBits); + } + + /** + * Convert a list of bytes using the options given to the [ZLibDecoder] + * constructor. + */ + List convert(List bytes) { + _BufferSink sink = new _BufferSink(); + startChunkedConversion(sink) + ..add(bytes) + ..close(); + return sink.builder.takeBytes(); + } + + /** + * Start a chunked conversion. While it accepts any [Sink] + * taking [List]'s, the optimal sink to be passed as [sink] is a + * [ByteConversionSink]. + */ + ByteConversionSink startChunkedConversion(Sink> sink) { + if (sink is! ByteConversionSink) { + sink = new ByteConversionSink.from(sink); + } + return new _ZLibDecoderSink(sink, windowBits, dictionary, raw); + } +} + +/** + * The [RawZLibFilter] class provides a low-level interface to zlib. + */ +abstract class RawZLibFilter { + /** + * Returns a a [RawZLibFilter] whose [process] and [processed] methods + * compress data. + */ + factory RawZLibFilter.deflateFilter({ + bool gzip: false, + int level: ZLibOption.defaultLevel, + int windowBits: ZLibOption.defaultWindowBits, + int memLevel: ZLibOption.defaultMemLevel, + int strategy: ZLibOption.strategyDefault, + List dictionary, + bool raw: false, + }) { + return _makeZLibDeflateFilter( + gzip, level, windowBits, memLevel, strategy, dictionary, raw); + } + + /** + * Returns a a [RawZLibFilter] whose [process] and [processed] methods + * decompress data. + */ + factory RawZLibFilter.inflateFilter({ + int windowBits: ZLibOption.defaultWindowBits, + List dictionary, + bool raw: false, + }) { + return _makeZLibInflateFilter(windowBits, dictionary, raw); + } + + /** + * Call to process a chunk of data. A call to [process] should only be made + * when [processed] returns [:null:]. + */ + void process(List data, int start, int end); + + /** + * Get a chunk of processed data. When there are no more data available, + * [processed] will return [:null:]. Set [flush] to [:false:] for non-final + * calls to improve performance of some filters. + * + * The last call to [processed] should have [end] set to [:true:]. This will + * make sure an 'end' packet is written on the stream. + */ + List processed({bool flush: true, bool end: false}); + + external static RawZLibFilter _makeZLibDeflateFilter( + bool gzip, + int level, + int windowBits, + int memLevel, + int strategy, + List dictionary, + bool raw); + + external static RawZLibFilter _makeZLibInflateFilter( + int windowBits, List dictionary, bool raw); +} + +class _BufferSink extends ByteConversionSink { + final BytesBuilder builder = new BytesBuilder(copy: false); + + void add(List chunk) { + builder.add(chunk); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + if (chunk is Uint8List) { + Uint8List list = chunk; + builder.add(new Uint8List.view(list.buffer, start, end - start)); + } else { + builder.add(chunk.sublist(start, end)); + } + } + + void close() {} +} + +class _ZLibEncoderSink extends _FilterSink { + _ZLibEncoderSink( + ByteConversionSink sink, + bool gzip, + int level, + int windowBits, + int memLevel, + int strategy, + List dictionary, + bool raw) + : super( + sink, + RawZLibFilter._makeZLibDeflateFilter( + gzip, level, windowBits, memLevel, strategy, dictionary, raw)); +} + +class _ZLibDecoderSink extends _FilterSink { + _ZLibDecoderSink( + ByteConversionSink sink, int windowBits, List dictionary, bool raw) + : super(sink, + RawZLibFilter._makeZLibInflateFilter(windowBits, dictionary, raw)); +} + +class _FilterSink extends ByteConversionSink { + final RawZLibFilter _filter; + final ByteConversionSink _sink; + bool _closed = false; + bool _empty = true; + + _FilterSink(this._sink, this._filter); + + void add(List data) { + addSlice(data, 0, data.length, false); + } + + void addSlice(List data, int start, int end, bool isLast) { + if (_closed) return; + if (end == null) throw new ArgumentError.notNull("end"); + RangeError.checkValidRange(start, end, data.length); + try { + _empty = false; + _BufferAndStart bufferAndStart = + _ensureFastAndSerializableByteData(data, start, end); + _filter.process(bufferAndStart.buffer, bufferAndStart.start, + end - (start - bufferAndStart.start)); + List out; + while ((out = _filter.processed(flush: false)) != null) { + _sink.add(out); + } + } catch (e) { + _closed = true; + rethrow; + } + + if (isLast) close(); + } + + void close() { + if (_closed) return; + // Be sure to send process an empty chunk of data. Without this, the empty + // message would not have a GZip frame (if compressed with GZip). + if (_empty) _filter.process(const [], 0, 0); + try { + List out; + while ((out = _filter.processed(end: true)) != null) { + _sink.add(out); + } + } catch (e) { + _closed = true; + throw e; + } + _closed = true; + _sink.close(); + } +} + +void _validateZLibWindowBits(int windowBits) { + if (ZLibOption.minWindowBits > windowBits || + ZLibOption.maxWindowBits < windowBits) { + throw new RangeError.range( + windowBits, ZLibOption.minWindowBits, ZLibOption.maxWindowBits); + } +} + +void _validateZLibeLevel(int level) { + if (ZLibOption.minLevel > level || ZLibOption.maxLevel < level) { + throw new RangeError.range(level, ZLibOption.minLevel, ZLibOption.maxLevel); + } +} + +void _validateZLibMemLevel(int memLevel) { + if (ZLibOption.minMemLevel > memLevel || ZLibOption.maxMemLevel < memLevel) { + throw new RangeError.range( + memLevel, ZLibOption.minMemLevel, ZLibOption.maxMemLevel); + } +} + +void _validateZLibStrategy(int strategy) { + const strategies = const [ + ZLibOption.strategyFiltered, + ZLibOption.strategyHuffmanOnly, + ZLibOption.strategyRle, + ZLibOption.strategyFixed, + ZLibOption.strategyDefault + ]; + if (strategies.indexOf(strategy) == -1) { + throw new ArgumentError("Unsupported 'strategy'"); + } +} +NN<.?I$&+(I$'+)I$+/-C"&#B!&"C%*&I$)&I$)&I(-*H).*I,1.N$)%N&+'+(-)A3 O"6DPFNNPOJ9:POJNHPQ:O-%IQGOM- ,511 %%))3//A.>QA3 O"N76DPFNNPOJ9:P43AGK3PP?%IQGOM-O- ,511 %%))3//A.>QP <DPFNNPOJ9:P43AGK3PP?%IQGOM-O-+511 %%)H'*!%MDHD'0!MP<PP@%IQGOM-O-6)J'*!%=HD'0DEI((2..#GI(2@N(4KN3O9<887/>DH .-2P-OP/")+C=9 +'@C1@OF1 +=/// I&DQ+P C+"!$,7Mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/directory.dartV// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * A reference to a directory (or _folder_) on the file system. + * + * A Directory instance is an object holding a [path] on which operations can + * be performed. The path to the directory can be [absolute] or relative. + * You can get the parent directory using the getter [parent], + * a property inherited from [FileSystemEntity]. + * + * In addition to being used as an instance to access the file system, + * Directory has a number of static properties, such as [systemTemp], + * which gets the system's temporary directory, and the getter and setter + * [current], which you can use to access or change the current directory. + * + * Create a new Directory object with a pathname to access the specified + * directory on the file system from your program. + * + * var myDir = new Directory('myDir'); + * + * Most methods in this class occur in synchronous and asynchronous pairs, + * for example, [create] and [createSync]. + * Unless you have a specific reason for using the synchronous version + * of a method, prefer the asynchronous version to avoid blocking your program. + * + * ## Create a directory + * + * The following code sample creates a directory using the [create] method. + * By setting the `recursive` parameter to true, you can create the + * named directory and all its necessary parent directories, + * if they do not already exist. + * + * import 'dart:io'; + * + * void main() { + * // Creates dir/ and dir/subdir/. + * new Directory('dir/subdir').create(recursive: true) + * // The created directory is returned as a Future. + * .then((Directory directory) { + * print(directory.path); + * }); + * } + * + * ## List a directory + * + * Use the [list] or [listSync] methods to get the files and directories + * contained by a directory. + * Set `recursive` to true to recursively list all subdirectories. + * Set `followLinks` to true to follow symbolic links. + * The list method returns a [Stream] that provides FileSystemEntity + * objects. Use the listen callback function to process each object + * as it become available. + * + * import 'dart:io'; + * + * void main() { + * // Get the system temp directory. + * var systemTempDir = Directory.systemTemp; + * + * // List directory contents, recursing into sub-directories, + * // but not following symbolic links. + * systemTempDir.list(recursive: true, followLinks: false) + * .listen((FileSystemEntity entity) { + * print(entity.path); + * }); + * } + * + * ## The use of Futures + * + * I/O operations can block a program for some period of time while it waits for + * the operation to complete. To avoid this, all + * methods involving I/O have an asynchronous variant which returns a [Future]. + * This future completes when the I/O operation finishes. While the I/O + * operation is in progress, the Dart program is not blocked, + * and can perform other operations. + * + * For example, + * the [exists] method, which determines whether the directory exists, + * returns a boolean value using a Future. + * Use `then` to register a callback function, which is called when + * the value is ready. + * + * import 'dart:io'; + * + * main() { + * final myDir = new Directory('dir'); + * myDir.exists().then((isThere) { + * isThere ? print('exists') : print('non-existent'); + * }); + * } + * + * + * In addition to exists, the [stat], [rename], and + * other methods, return Futures. + * + * ## Other resources + * + * * [Dart by Example](https://www.dartlang.org/dart-by-example/#files-directories-and-symlinks) + * provides additional task-oriented code samples that show how to use + * various API from the Directory class and the related [File] class. + * + * * [I/O for Command-Line + * Apps](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartio---io-for-command-line-apps) + * a section from _A Tour of the Dart Libraries_ covers files and directories. + * + * * [Write Command-Line Apps](https://www.dartlang.org/docs/tutorials/cmdline/), + * a tutorial about writing command-line apps, includes information about + * files and directories. + */ +abstract class Directory implements FileSystemEntity { + /** + * Gets the path of this directory. + */ + String get path; + + /** + * Creates a [Directory] object. + * + * If [path] is a relative path, it will be interpreted relative to the + * current working directory (see [Directory.current]), when used. + * + * If [path] is an absolute path, it will be immune to changes to the + * current working directory. + */ + factory Directory(String path) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return new _Directory(path); + } + return overrides.createDirectory(path); + } + + factory Directory.fromRawPath(Uint8List path) { + // TODO(bkonyi): Handle overrides. + return new _Directory.fromRawPath(path); + } + + /** + * Create a Directory object from a URI. + * + * If [uri] cannot reference a directory this throws [UnsupportedError]. + */ + factory Directory.fromUri(Uri uri) => new Directory(uri.toFilePath()); + + /** + * Creates a directory object pointing to the current working + * directory. + */ + static Directory get current { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _Directory.current; + } + return overrides.getCurrentDirectory(); + } + + /** + * Returns a [Uri] representing the directory's location. + * + * The returned URI's scheme is always "file" if the entity's [path] is + * absolute, otherwise the scheme will be empty. + * The returned URI's path always ends in a slash ('/'). + */ + Uri get uri; + + /** + * Sets the current working directory of the Dart process including + * all running isolates. The new value set can be either a [Directory] + * or a [String]. + * + * The new value is passed to the OS's system call unchanged, so a + * relative path passed as the new working directory will be + * resolved by the OS. + * + * Note that setting the current working directory is a synchronous + * operation and that it changes the working directory of *all* + * isolates. + * + * Use this with care - especially when working with asynchronous + * operations and multiple isolates. Changing the working directory, + * while asynchronous operations are pending or when other isolates + * are working with the file system, can lead to unexpected results. + */ + static void set current(path) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + _Directory.current = path; + return; + } + overrides.setCurrentDirectory(path); + } + + /** + * Creates the directory with this name. + * + * If [recursive] is false, only the last directory in the path is + * created. If [recursive] is true, all non-existing path components + * are created. If the directory already exists nothing is done. + * + * Returns a [:Future:] that completes with this + * directory once it has been created. If the directory cannot be + * created the future completes with an exception. + */ + Future create({bool recursive: false}); + + /** + * Synchronously creates the directory with this name. + * + * If [recursive] is false, only the last directory in the path is + * created. If [recursive] is true, all non-existing path components + * are created. If the directory already exists nothing is done. + * + * If the directory cannot be created an exception is thrown. + */ + void createSync({bool recursive: false}); + + /** + * Gets the system temp directory. + * + * Gets the directory provided by the operating system for creating + * temporary files and directories in. + * The location of the system temp directory is platform-dependent, + * and may be set by an environment variable. + */ + static Directory get systemTemp { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _Directory.systemTemp; + } + return overrides.getSystemTempDirectory(); + } + + /** + * Creates a temporary directory in this directory. Additional random + * characters are appended to [prefix] to produce a unique directory + * name. If [prefix] is missing or null, the empty string is used + * for [prefix]. + * + * Returns a [:Future:] that completes with the newly + * created temporary directory. + */ + Future createTemp([String prefix]); + + /** + * Synchronously creates a temporary directory in this directory. + * Additional random characters are appended to [prefix] to produce + * a unique directory name. If [prefix] is missing or null, the empty + * string is used for [prefix]. + * + * Returns the newly created temporary directory. + */ + Directory createTempSync([String prefix]); + + Future resolveSymbolicLinks(); + + String resolveSymbolicLinksSync(); + + /** + * Renames this directory. Returns a [:Future:] that completes + * with a [Directory] instance for the renamed directory. + * + * If newPath identifies an existing directory, that directory is + * replaced. If newPath identifies an existing file, the operation + * fails and the future completes with an exception. + */ + Future rename(String newPath); + + /** + * Synchronously renames this directory. Returns a [Directory] + * instance for the renamed directory. + * + * If newPath identifies an existing directory, that directory is + * replaced. If newPath identifies an existing file the operation + * fails and an exception is thrown. + */ + Directory renameSync(String newPath); + + /** + * Returns a [Directory] instance whose path is the absolute path to [this]. + * + * The absolute path is computed by prefixing + * a relative path with the current working directory, and returning + * an absolute path unchanged. + */ + Directory get absolute; + + /** + * Lists the sub-directories and files of this [Directory]. + * Optionally recurses into sub-directories. + * + * If [followLinks] is false, then any symbolic links found + * are reported as [Link] objects, rather than as directories or files, + * and are not recursed into. + * + * If [followLinks] is true, then working links are reported as + * directories or files, depending on + * their type, and links to directories are recursed into. + * Broken links are reported as [Link] objects. + * If a symbolic link makes a loop in the file system, then a recursive + * listing will not follow a link twice in the + * same recursive descent, but will report it as a [Link] + * the second time it is seen. + * + * The result is a stream of [FileSystemEntity] objects + * for the directories, files, and links. + */ + Stream list( + {bool recursive: false, bool followLinks: true}); + + /** + * Lists the sub-directories and files of this [Directory]. + * Optionally recurses into sub-directories. + * + * If [followLinks] is false, then any symbolic links found + * are reported as [Link] objects, rather than as directories or files, + * and are not recursed into. + * + * If [followLinks] is true, then working links are reported as + * directories or files, depending on + * their type, and links to directories are recursed into. + * Broken links are reported as [Link] objects. + * If a link makes a loop in the file system, then a recursive + * listing will not follow a link twice in the + * same recursive descent, but will report it as a [Link] + * the second time it is seen. + * + * Returns a [List] containing [FileSystemEntity] objects for the + * directories, files, and links. + */ + List listSync( + {bool recursive: false, bool followLinks: true}); + + /** + * Returns a human readable string for this Directory instance. + */ + String toString(); +} +WNN<@NJ?1GFJKI3+K+GPLD=!*==)$ IC7ED+3E.A/! Q1PH>%G+D-)> 4"aIHjQRL7&#JEH #7#,2'-+KI@!7!,<J3;FIE?FBDGFG"7!)+EGC>D559EGC@,%F)F0$7$/HGDC"1DFH"4-)%L<DE7,A)DD'(O0G!>/>J B(=2J1/>J B(=2A1 _path; + + external static _current(_Namespace namespace); + external static _setCurrent(_Namespace namespace, Uint8List rawPath); + external static _createTemp(_Namespace namespace, Uint8List rawPath); + external static String _systemTemp(_Namespace namespace); + external static _exists(_Namespace namespace, Uint8List rawPath); + external static _create(_Namespace namespace, Uint8List rawPath); + external static _deleteNative( + _Namespace namespace, Uint8List rawPath, bool recursive); + external static _rename( + _Namespace namespace, Uint8List rawPath, String newPath); + external static void _fillWithDirectoryListing( + _Namespace namespace, + List list, + Uint8List rawPath, + bool recursive, + bool followLinks); + + static Directory get current { + var result = _current(_Namespace._namespace); + if (result is OSError) { + throw new FileSystemException( + "Getting current working directory failed", "", result); + } + return new _Directory(result); + } + + static void set current(path) { + Uint8List _rawPath; + if (path is _Directory) { + // For our internal Directory implementation, go ahead and use the raw + // path. + _rawPath = path._rawPath; + } else if (path is Directory) { + // FIXME(bkonyi): package:file passes in instances of classes which do + // not have _path defined, so we will fallback to using the existing + // path String for now. + _rawPath = FileSystemEntity._toUtf8Array(path.path); + } else if (path is String) { + _rawPath = FileSystemEntity._toUtf8Array(path); + } else { + throw new ArgumentError('${Error.safeToString(path)} is not a String or' + ' Directory'); + } + if (!_EmbedderConfig._mayChdir) { + throw new UnsupportedError( + "This embedder disallows setting Directory.current"); + } + var result = _setCurrent(_Namespace._namespace, _rawPath); + if (result is ArgumentError) throw result; + if (result is OSError) { + throw new FileSystemException( + "Setting current working directory failed", path, result); + } + } + + Uri get uri { + return new Uri.directory(path); + } + + Future exists() { + return _File._dispatchWithNamespace( + _IOService.directoryExists, [null, _rawPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionOrErrorFromResponse(response, "Exists failed"); + } + return response == 1; + }); + } + + bool existsSync() { + var result = _exists(_Namespace._namespace, _rawPath); + if (result is OSError) { + throw new FileSystemException("Exists failed", path, result); + } + return (result == 1); + } + + Directory get absolute => new Directory(_absolutePath); + + Future create({bool recursive: false}) { + if (recursive) { + return exists().then((exists) { + if (exists) return this; + if (path != parent.path) { + return parent.create(recursive: true).then((_) { + return create(); + }); + } else { + return create(); + } + }); + } else { + return _File._dispatchWithNamespace( + _IOService.directoryCreate, [null, _rawPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionOrErrorFromResponse(response, "Creation failed"); + } + return this; + }); + } + } + + void createSync({bool recursive: false}) { + if (recursive) { + if (existsSync()) return; + if (path != parent.path) { + parent.createSync(recursive: true); + } + } + var result = _create(_Namespace._namespace, _rawPath); + if (result is OSError) { + throw new FileSystemException("Creation failed", path, result); + } + } + + static Directory get systemTemp => + new Directory(_systemTemp(_Namespace._namespace)); + + Future createTemp([String prefix]) { + if (prefix == null) prefix = ''; + if (path == '') { + throw new ArgumentError("Directory.createTemp called with an empty path. " + "To use the system temp directory, use Directory.systemTemp"); + } + String fullPrefix; + // FIXME(bkonyi): here we're using `path` directly, which might cause + // issues if it is not UTF-8 encoded. + if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) { + fullPrefix = "$path$prefix"; + } else { + fullPrefix = "$path${Platform.pathSeparator}$prefix"; + } + return _File._dispatchWithNamespace(_IOService.directoryCreateTemp, + [null, FileSystemEntity._toUtf8Array(fullPrefix)]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionOrErrorFromResponse( + response, "Creation of temporary directory failed"); + } + return new Directory(response); + }); + } + + Directory createTempSync([String prefix]) { + if (prefix == null) prefix = ''; + if (path == '') { + throw new ArgumentError("Directory.createTemp called with an empty path. " + "To use the system temp directory, use Directory.systemTemp"); + } + String fullPrefix; + // FIXME(bkonyi): here we're using `path` directly, which might cause + // issues if it is not UTF-8 encoded. + if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) { + fullPrefix = "$path$prefix"; + } else { + fullPrefix = "$path${Platform.pathSeparator}$prefix"; + } + var result = _createTemp( + _Namespace._namespace, FileSystemEntity._toUtf8Array(fullPrefix)); + if (result is OSError) { + throw new FileSystemException( + "Creation of temporary directory failed", fullPrefix, result); + } + return new Directory(result); + } + + Future _delete({bool recursive: false}) { + return _File._dispatchWithNamespace(_IOService.directoryDelete, + [null, _rawPath, recursive]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionOrErrorFromResponse(response, "Deletion failed"); + } + return this; + }); + } + + void _deleteSync({bool recursive: false}) { + var result = _deleteNative(_Namespace._namespace, _rawPath, recursive); + if (result is OSError) { + throw new FileSystemException("Deletion failed", path, result); + } + } + + Future rename(String newPath) { + return _File._dispatchWithNamespace( + _IOService.directoryRename, [null, _rawPath, newPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionOrErrorFromResponse(response, "Rename failed"); + } + return new Directory(newPath); + }); + } + + Directory renameSync(String newPath) { + if (newPath is! String) { + throw new ArgumentError(); + } + var result = _rename(_Namespace._namespace, _rawPath, newPath); + if (result is OSError) { + throw new FileSystemException("Rename failed", path, result); + } + return new Directory(newPath); + } + + Stream list( + {bool recursive: false, bool followLinks: true}) { + return new _AsyncDirectoryLister( + // FIXME(bkonyi): here we're using `path` directly, which might cause issues + // if it is not UTF-8 encoded. + FileSystemEntity._toUtf8Array( + FileSystemEntity._ensureTrailingPathSeparators(path)), + recursive, + followLinks) + .stream; + } + + List listSync( + {bool recursive: false, bool followLinks: true}) { + if (recursive is! bool || followLinks is! bool) { + throw new ArgumentError(); + } + var result = []; + _fillWithDirectoryListing( + _Namespace._namespace, + result, + // FIXME(bkonyi): here we're using `path` directly, which might cause issues + // if it is not UTF-8 encoded. + FileSystemEntity + ._toUtf8Array(FileSystemEntity._ensureTrailingPathSeparators(path)), + recursive, + followLinks); + return result; + } + + String toString() => "Directory: '$path'"; + + bool _isErrorResponse(response) => + response is List && response[0] != _successResponse; + + _exceptionOrErrorFromResponse(response, String message) { + assert(_isErrorResponse(response)); + switch (response[_errorResponseErrorType]) { + case _illegalArgumentResponse: + return new ArgumentError(); + case _osErrorResponse: + var err = new OSError(response[_osErrorResponseMessage], + response[_osErrorResponseErrorCode]); + return new FileSystemException(message, path, err); + default: + return new Exception("Unknown error"); + } + } +} + +abstract class _AsyncDirectoryListerOps { + external factory _AsyncDirectoryListerOps(int pointer); + + int getPointer(); +} + +class _AsyncDirectoryLister { + static const int listFile = 0; + static const int listDirectory = 1; + static const int listLink = 2; + static const int listError = 3; + static const int listDone = 4; + + static const int responseType = 0; + static const int responsePath = 1; + static const int responseComplete = 1; + static const int responseError = 2; + + final Uint8List rawPath; + final bool recursive; + final bool followLinks; + + StreamController controller; + bool canceled = false; + bool nextRunning = false; + bool closed = false; + _AsyncDirectoryListerOps _ops; + Completer closeCompleter = new Completer(); + + _AsyncDirectoryLister(this.rawPath, this.recursive, this.followLinks) { + controller = new StreamController( + onListen: onListen, onResume: onResume, onCancel: onCancel, sync: true); + } + + // WARNING: + // Calling this function will increase the reference count on the native + // object that implements the async directory lister operations. It should + // only be called to pass the pointer to the IO Service, which will decrement + // the reference count when it is finished with it. + int _pointer() { + return (_ops == null) ? null : _ops.getPointer(); + } + + Stream get stream => controller.stream; + + void onListen() { + _File._dispatchWithNamespace(_IOService.directoryListStart, + [null, rawPath, recursive, followLinks]).then((response) { + if (response is int) { + _ops = new _AsyncDirectoryListerOps(response); + next(); + } else if (response is Error) { + controller.addError(response, response.stackTrace); + close(); + } else { + error(response); + close(); + } + }); + } + + void onResume() { + if (!nextRunning) { + next(); + } + } + + Future onCancel() { + canceled = true; + // If we are active, but not requesting, close. + if (!nextRunning) { + close(); + } + + return closeCompleter.future; + } + + void next() { + if (canceled) { + close(); + return; + } + if (controller.isPaused || nextRunning) { + return; + } + var pointer = _pointer(); + if (pointer == null) { + return; + } + nextRunning = true; + _IOService + ._dispatch(_IOService.directoryListNext, [pointer]).then((result) { + nextRunning = false; + if (result is List) { + next(); + assert(result.length % 2 == 0); + for (int i = 0; i < result.length; i++) { + assert(i % 2 == 0); + switch (result[i++]) { + case listFile: + controller.add(new File.fromRawPath(result[i])); + break; + case listDirectory: + controller.add(new Directory.fromRawPath(result[i])); + break; + case listLink: + controller.add(new Link.fromRawPath(result[i])); + break; + case listError: + error(result[i]); + break; + case listDone: + canceled = true; + return; + } + } + } else { + controller.addError(new FileSystemException("Internal error")); + } + }); + } + + void _cleanup() { + controller.close(); + closeCompleter.complete(); + _ops = null; + } + + void close() { + if (closed) { + return; + } + if (nextRunning) { + return; + } + closed = true; + + var pointer = _pointer(); + if (pointer == null) { + _cleanup(); + } else { + _IOService._dispatch( + _IOService.directoryListStop, [pointer]).whenComplete(_cleanup); + } + } + + void error(message) { + var errorType = message[responseError][_errorResponseErrorType]; + if (errorType == _illegalArgumentResponse) { + controller.addError(new ArgumentError()); + } else if (errorType == _osErrorResponse) { + var responseErrorInfo = message[responseError]; + var err = new OSError(responseErrorInfo[_osErrorResponseMessage], + responseErrorInfo[_osErrorResponseErrorCode]); + var errorPath = message[responsePath]; + if (errorPath == null) { + errorPath = utf8.decode(rawPath, allowMalformed: true); + } else if (errorPath is Uint8List) { + errorPath = utf8.decode(message[responsePath], allowMalformed: true); + } + controller.addError( + new FileSystemException("Directory listing failed", errorPath, err)); + } else { + controller.addError(new FileSystemException("Internal error")); + } + } +} +NN<AN5.9E>2HH> inputStream = file.openRead(); + * + * inputStream + * .transform(utf8.decoder) // Decode bytes to UTF-8. + * .transform(new LineSplitter()) // Convert stream to individual lines. + * .listen((String line) { // Process results. + * print('$line: ${line.length} bytes'); + * }, + * onDone: () { print('File is now closed.'); }, + * onError: (e) { print(e.toString()); }); + * } + * + * ## Write to a file + * + * To write a string to a file, use the [writeAsString] method: + * + * import 'dart:io'; + * + * void main() { + * final filename = 'file.txt'; + * new File(filename).writeAsString('some content') + * .then((File file) { + * // Do something with the file. + * }); + * } + * + * You can also write to a file using a [Stream]. Open the file with + * [openWrite], which returns an [IOSink] to which you can write data. + * Be sure to close the sink with the [IOSink.close] method. + * + * import 'dart:io'; + * + * void main() { + * var file = new File('file.txt'); + * var sink = file.openWrite(); + * sink.write('FILE ACCESSED ${new DateTime.now()}\n'); + * + * // Close the IOSink to free system resources. + * sink.close(); + * } + * + * ## The use of Futures + * + * To avoid unintentional blocking of the program, + * several methods use a [Future] to return a value. For example, + * the [length] method, which gets the length of a file, returns a Future. + * Use `then` to register a callback function, which is called when + * the value is ready. + * + * import 'dart:io'; + * + * main() { + * final file = new File('file.txt'); + * + * file.length().then((len) { + * print(len); + * }); + * } + * + * In addition to length, the [exists], [lastModified], [stat], and + * other methods, return Futures. + * + * ## Other resources + * + * * [Dart by Example](https://www.dartlang.org/dart-by-example/#files-directories-and-symlinks) + * provides additional task-oriented code samples that show how to use + * various API from the Directory class and the related [File] class. + * + * * [I/O for Command-Line + * Apps](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartio---io-for-command-line-apps) + * a section from _A Tour of the Dart Libraries_ covers files and directories. + * + * * [Write Command-Line Apps](https://www.dartlang.org/docs/tutorials/cmdline/), + * a tutorial about writing command-line apps, includes information about + * files and directories. + */ +abstract class File implements FileSystemEntity { + /** + * Creates a [File] object. + * + * If [path] is a relative path, it will be interpreted relative to the + * current working directory (see [Directory.current]), when used. + * + * If [path] is an absolute path, it will be immune to changes to the + * current working directory. + */ + factory File(String path) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return new _File(path); + } + return overrides.createFile(path); + } + + /** + * Create a File object from a URI. + * + * If [uri] cannot reference a file this throws [UnsupportedError]. + */ + factory File.fromUri(Uri uri) => new File(uri.toFilePath()); + + /** + * Creates a File object from a raw path, that is, a sequence of bytes + * as represented by the OS. + */ + factory File.fromRawPath(Uint8List rawPath) { + // TODO(bkonyi): Handle overrides. + return new _File.fromRawPath(rawPath); + } + + /** + * Create the file. Returns a `Future` that completes with + * the file when it has been created. + * + * If [recursive] is false, the default, the file is created only if + * all directories in the path exist. If [recursive] is true, all + * non-existing path components are created. + * + * Existing files are left untouched by [create]. Calling [create] on an + * existing file might fail if there are restrictive permissions on + * the file. + * + * Completes the future with a [FileSystemException] if the operation fails. + */ + Future create({bool recursive: false}); + + /** + * Synchronously create the file. Existing files are left untouched + * by [createSync]. Calling [createSync] on an existing file might fail + * if there are restrictive permissions on the file. + * + * If [recursive] is false, the default, the file is created + * only if all directories in the path exist. + * If [recursive] is true, all non-existing path components are created. + * + * Throws a [FileSystemException] if the operation fails. + */ + void createSync({bool recursive: false}); + + /** + * Renames this file. Returns a `Future` that completes + * with a [File] instance for the renamed file. + * + * If [newPath] identifies an existing file, that file is + * replaced. If [newPath] identifies an existing directory, the + * operation fails and the future completes with an exception. + */ + Future rename(String newPath); + + /** + * Synchronously renames this file. Returns a [File] + * instance for the renamed file. + * + * If [newPath] identifies an existing file, that file is + * replaced. If [newPath] identifies an existing directory the + * operation fails and an exception is thrown. + */ + File renameSync(String newPath); + + /** + * Copy this file. Returns a `Future` that completes + * with a [File] instance for the copied file. + * + * If [newPath] identifies an existing file, that file is + * replaced. If [newPath] identifies an existing directory, the + * operation fails and the future completes with an exception. + */ + Future copy(String newPath); + + /** + * Synchronously copy this file. Returns a [File] + * instance for the copied file. + * + * If [newPath] identifies an existing file, that file is + * replaced. If [newPath] identifies an existing directory the + * operation fails and an exception is thrown. + */ + File copySync(String newPath); + + /** + * Get the length of the file. Returns a `Future` that + * completes with the length in bytes. + */ + Future length(); + + /** + * Synchronously get the length of the file. + * + * Throws a [FileSystemException] if the operation fails. + */ + int lengthSync(); + + /** + * Returns a [File] instance whose path is the absolute path to [this]. + * + * The absolute path is computed by prefixing + * a relative path with the current working directory, and returning + * an absolute path unchanged. + */ + File get absolute; + +/** + * Get the last-accessed time of the file. + * + * Returns a `Future` that completes with the date and time when the + * file was last accessed, if the information is available. + * + * Throws a [FileSystemException] if the operation fails. + */ + Future lastAccessed(); + +/** + * Get the last-accessed time of the file. + * + * Returns the date and time when the file was last accessed, + * if the information is available. Blocks until the information can be returned + * or it is determined that the information is not available. + * + * Throws a [FileSystemException] if the operation fails. + */ + DateTime lastAccessedSync(); + + /** + * Modifies the time the file was last accessed. + * + * Returns a [Future] that completes once the operation has completed. + * + * Throws a [FileSystemException] if the time cannot be set. + */ + Future setLastAccessed(DateTime time); + + /** + * Synchronously modifies the time the file was last accessed. + * + * Throws a [FileSystemException] if the time cannot be set. + */ + void setLastAccessedSync(DateTime time); + +/** + * Get the last-modified time of the file. + * + * Returns a `Future` that completes with the date and time when the + * file was last modified, if the information is available. + * + * Throws a [FileSystemException] if the operation fails. + */ + Future lastModified(); + +/** + * Get the last-modified time of the file. + * + * Returns the date and time when the file was last modified, + * if the information is available. Blocks until the information can be returned + * or it is determined that the information is not available. + * + * Throws a [FileSystemException] if the operation fails. + */ + DateTime lastModifiedSync(); + + /** + * Modifies the time the file was last modified. + * + * Returns a [Future] that completes once the operation has completed. + * + * Throws a [FileSystemException] if the time cannot be set. + */ + Future setLastModified(DateTime time); + + /** + * Synchronously modifies the time the file was last modified. + * + * If the attributes cannot be set, throws a [FileSystemException]. + */ + void setLastModifiedSync(DateTime time); + + /** + * Open the file for random access operations. Returns a + * `Future` that completes with the opened + * random access file. [RandomAccessFile]s must be closed using the + * [RandomAccessFile.close] method. + * + * Files can be opened in three modes: + * + * [FileMode.read]: open the file for reading. + * + * [FileMode.write]: open the file for both reading and writing and + * truncate the file to length zero. If the file does not exist the + * file is created. + * + * [FileMode.append]: same as [FileMode.write] except that the file is + * not truncated. + */ + Future open({FileMode mode: FileMode.read}); + + /** + * Synchronously open the file for random access operations. The + * result is a [RandomAccessFile] on which random access operations + * can be performed. Opened [RandomAccessFile]s must be closed using + * the [RandomAccessFile.close] method. + * + * See [open] for information on the [mode] argument. + * + * Throws a [FileSystemException] if the operation fails. + */ + RandomAccessFile openSync({FileMode mode: FileMode.read}); + + /** + * Create a new independent [Stream] for the contents of this file. + * + * If [start] is present, the file will be read from byte-offset [start]. + * Otherwise from the beginning (index 0). + * + * If [end] is present, only up to byte-index [end] will be read. Otherwise, + * until end of file. + * + * In order to make sure that system resources are freed, the stream + * must be read to completion or the subscription on the stream must + * be cancelled. + */ + Stream> openRead([int start, int end]); + + /** + * Creates a new independent [IOSink] for the file. The + * [IOSink] must be closed when no longer used, to free + * system resources. + * + * An [IOSink] for a file can be opened in two modes: + * + * * [FileMode.write]: truncates the file to length zero. + * * [FileMode.append]: sets the initial write position to the end + * of the file. + * + * When writing strings through the returned [IOSink] the encoding + * specified using [encoding] will be used. The returned [IOSink] + * has an `encoding` property which can be changed after the + * [IOSink] has been created. + */ + IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}); + + /** + * Read the entire file contents as a list of bytes. Returns a + * `Future>` that completes with the list of bytes that + * is the contents of the file. + */ + Future> readAsBytes(); + + /** + * Synchronously read the entire file contents as a list of bytes. + * + * Throws a [FileSystemException] if the operation fails. + */ + List readAsBytesSync(); + + /** + * Read the entire file contents as a string using the given + * [Encoding]. + * + * Returns a `Future` that completes with the string once + * the file contents has been read. + */ + Future readAsString({Encoding encoding: utf8}); + + /** + * Synchronously read the entire file contents as a string using the + * given [Encoding]. + * + * Throws a [FileSystemException] if the operation fails. + */ + String readAsStringSync({Encoding encoding: utf8}); + + /** + * Read the entire file contents as lines of text using the given + * [Encoding]. + * + * Returns a `Future>` that completes with the lines + * once the file contents has been read. + */ + Future> readAsLines({Encoding encoding: utf8}); + + /** + * Synchronously read the entire file contents as lines of text + * using the given [Encoding]. + * + * Throws a [FileSystemException] if the operation fails. + */ + List readAsLinesSync({Encoding encoding: utf8}); + + /** + * Write a list of bytes to a file. + * + * Opens the file, writes the list of bytes to it, and closes the file. + * Returns a `Future` that completes with this [File] object once + * the entire operation has completed. + * + * By default [writeAsBytes] creates the file for writing and truncates the + * file if it already exists. In order to append the bytes to an existing + * file, pass [FileMode.append] as the optional mode parameter. + * + * If the argument [flush] is set to `true`, the data written will be + * flushed to the file system before the returned future completes. + */ + Future writeAsBytes(List bytes, + {FileMode mode: FileMode.write, bool flush: false}); + + /** + * Synchronously write a list of bytes to a file. + * + * Opens the file, writes the list of bytes to it and closes the file. + * + * By default [writeAsBytesSync] creates the file for writing and truncates + * the file if it already exists. In order to append the bytes to an existing + * file, pass [FileMode.append] as the optional mode parameter. + * + * If the [flush] argument is set to `true` data written will be + * flushed to the file system before returning. + * + * Throws a [FileSystemException] if the operation fails. + */ + void writeAsBytesSync(List bytes, + {FileMode mode: FileMode.write, bool flush: false}); + + /** + * Write a string to a file. + * + * Opens the file, writes the string in the given encoding, and closes the + * file. Returns a `Future` that completes with this [File] object + * once the entire operation has completed. + * + * By default [writeAsString] creates the file for writing and truncates the + * file if it already exists. In order to append the bytes to an existing + * file, pass [FileMode.append] as the optional mode parameter. + * + * If the argument [flush] is set to `true`, the data written will be + * flushed to the file system before the returned future completes. + * + */ + Future writeAsString(String contents, + {FileMode mode: FileMode.write, + Encoding encoding: utf8, + bool flush: false}); + + /** + * Synchronously write a string to a file. + * + * Opens the file, writes the string in the given encoding, and closes the + * file. + * + * By default [writeAsStringSync] creates the file for writing and + * truncates the file if it already exists. In order to append the bytes + * to an existing file, pass [FileMode.append] as the optional mode + * parameter. + * + * If the [flush] argument is set to `true` data written will be + * flushed to the file system before returning. + * + * Throws a [FileSystemException] if the operation fails. + */ + void writeAsStringSync(String contents, + {FileMode mode: FileMode.write, + Encoding encoding: utf8, + bool flush: false}); + + /** + * Get the path of the file. + */ + String get path; +} + +/** + * `RandomAccessFile` provides random access to the data in a + * file. + * + * `RandomAccessFile` objects are obtained by calling the + * `open` method on a [File] object. + * + * A `RandomAccessFile` have both asynchronous and synchronous + * methods. The asynchronous methods all return a `Future` + * whereas the synchronous methods will return the result directly, + * and block the current isolate until the result is ready. + * + * At most one asynchronous method can be pending on a given `RandomAccessFile` + * instance at the time. If an asynchronous method is called when one is + * already in progress a [FileSystemException] is thrown. + * + * If an asynchronous method is pending it is also not possible to call any + * synchronous methods. This will also throw a [FileSystemException]. + */ +abstract class RandomAccessFile { + /** + * Closes the file. Returns a `Future` that + * completes when it has been closed. + */ + Future close(); + + /** + * Synchronously closes the file. + * + * Throws a [FileSystemException] if the operation fails. + */ + void closeSync(); + + /** + * Reads a byte from the file. Returns a `Future` that + * completes with the byte, or with -1 if end-of-file has been reached. + */ + Future readByte(); + + /** + * Synchronously reads a single byte from the file. If end-of-file + * has been reached -1 is returned. + * + * Throws a [FileSystemException] if the operation fails. + */ + int readByteSync(); + + /** + * Reads [bytes] bytes from a file and returns the result as a list of bytes. + */ + Future> read(int bytes); + + /** + * Synchronously reads a maximum of [bytes] bytes from a file and + * returns the result in a list of bytes. + * + * Throws a [FileSystemException] if the operation fails. + */ + List readSync(int bytes); + + /** + * Reads into an existing [List] from the file. If [start] is present, + * the bytes will be filled into [buffer] from at index [start], otherwise + * index 0. If [end] is present, the [end] - [start] bytes will be read into + * [buffer], otherwise up to [buffer.length]. If [end] == [start] nothing + * happens. + * + * Returns a `Future` that completes with the number of bytes read. + */ + Future readInto(List buffer, [int start = 0, int end]); + + /** + * Synchronously reads into an existing [List] from the file. If [start] + * is present, the bytes will be filled into [buffer] from at index [start], + * otherwise index 0. If [end] is present, the [end] - [start] bytes will be + * read into [buffer], otherwise up to [buffer.length]. If [end] == [start] + * nothing happens. + * + * Throws a [FileSystemException] if the operation fails. + */ + int readIntoSync(List buffer, [int start = 0, int end]); + + /** + * Writes a single byte to the file. Returns a + * `Future` that completes with this + * RandomAccessFile when the write completes. + */ + Future writeByte(int value); + + /** + * Synchronously writes a single byte to the file. Returns the + * number of bytes successfully written. + * + * Throws a [FileSystemException] if the operation fails. + */ + int writeByteSync(int value); + + /** + * Writes from a [List] to the file. It will read the buffer from index + * [start] to index [end]. If [start] is omitted, it'll start from index 0. + * If [end] is omitted, it will write to end of [buffer]. + * + * Returns a `Future` that completes with this + * [RandomAccessFile] when the write completes. + */ + Future writeFrom(List buffer, + [int start = 0, int end]); + + /** + * Synchronously writes from a [List] to the file. It will read the + * buffer from index [start] to index [end]. If [start] is omitted, it'll + * start from index 0. If [end] is omitted, it will write to the end of + * [buffer]. + * + * Throws a [FileSystemException] if the operation fails. + */ + void writeFromSync(List buffer, [int start = 0, int end]); + + /** + * Writes a string to the file using the given [Encoding]. Returns a + * `Future` that completes with this + * RandomAccessFile when the write completes. + */ + Future writeString(String string, + {Encoding encoding: utf8}); + + /** + * Synchronously writes a single string to the file using the given + * [Encoding]. + * + * Throws a [FileSystemException] if the operation fails. + */ + void writeStringSync(String string, {Encoding encoding: utf8}); + + /** + * Gets the current byte position in the file. Returns a + * `Future` that completes with the position. + */ + Future position(); + + /** + * Synchronously gets the current byte position in the file. + * + * Throws a [FileSystemException] if the operation fails. + */ + int positionSync(); + + /** + * Sets the byte position in the file. Returns a + * `Future` that completes with this + * RandomAccessFile when the position has been set. + */ + Future setPosition(int position); + + /** + * Synchronously sets the byte position in the file. + * + * Throws a [FileSystemException] if the operation fails. + */ + void setPositionSync(int position); + + /** + * Truncates (or extends) the file to [length] bytes. Returns a + * `Future` that completes with this + * RandomAccessFile when the truncation has been performed. + */ + Future truncate(int length); + + /** + * Synchronously truncates (or extends) the file to [length] bytes. + * + * Throws a [FileSystemException] if the operation fails. + */ + void truncateSync(int length); + + /** + * Gets the length of the file. Returns a `Future` that + * completes with the length in bytes. + */ + Future length(); + + /** + * Synchronously gets the length of the file. + * + * Throws a [FileSystemException] if the operation fails. + */ + int lengthSync(); + + /** + * Flushes the contents of the file to disk. Returns a + * `Future` that completes with this + * RandomAccessFile when the flush operation completes. + */ + Future flush(); + + /** + * Synchronously flushes the contents of the file to disk. + * + * Throws a [FileSystemException] if the operation fails. + */ + void flushSync(); + + /** + * Locks the file or part of the file. + * + * By default an exclusive lock will be obtained, but that can be overridden + * by the [mode] argument. + * + * Locks the byte range from [start] to [end] of the file, with the + * byte at position `end` not included. If no arguments are + * specified, the full file is locked, If only `start` is specified + * the file is locked from byte position `start` to the end of the + * file, no matter how large it grows. It is possible to specify an + * explicit value of `end` which is past the current length of the file. + * + * To obtain an exclusive lock on a file it must be opened for writing. + * + * If [mode] is [FileLock.exclusive] or [FileLock.shared], an error is + * signaled if the lock cannot be obtained. If [mode] is + * [FileLock.blockingExclusive] or [FileLock.blockingShared], the + * returned [Future] is resolved only when the lock has been obtained. + * + * *NOTE* file locking does have slight differences in behavior across + * platforms: + * + * On Linux and OS X this uses advisory locks, which have the + * surprising semantics that all locks associated with a given file + * are removed when *any* file descriptor for that file is closed by + * the process. Note that this does not actually lock the file for + * access. Also note that advisory locks are on a process + * level. This means that several isolates in the same process can + * obtain an exclusive lock on the same file. + * + * On Windows the regions used for lock and unlock needs to match. If that + * is not the case unlocking will result in the OS error "The segment is + * already unlocked". + */ + Future lock( + [FileLock mode = FileLock.exclusive, int start = 0, int end = -1]); + + /** + * Synchronously locks the file or part of the file. + * + * By default an exclusive lock will be obtained, but that can be overridden + * by the [mode] argument. + * + * Locks the byte range from [start] to [end] of the file ,with the + * byte at position `end` not included. If no arguments are + * specified, the full file is locked, If only `start` is specified + * the file is locked from byte position `start` to the end of the + * file, no matter how large it grows. It is possible to specify an + * explicit value of `end` which is past the current length of the file. + * + * To obtain an exclusive lock on a file it must be opened for writing. + * + * If [mode] is [FileLock.exclusive] or [FileLock.shared], an exception is + * thrown if the lock cannot be obtained. If [mode] is + * [FileLock.blockingExclusive] or [FileLock.blockingShared], the + * call returns only after the lock has been obtained. + * + * *NOTE* file locking does have slight differences in behavior across + * platforms: + * + * On Linux and OS X this uses advisory locks, which have the + * surprising semantics that all locks associated with a given file + * are removed when *any* file descriptor for that file is closed by + * the process. Note that this does not actually lock the file for + * access. Also note that advisory locks are on a process + * level. This means that several isolates in the same process can + * obtain an exclusive lock on the same file. + * + * On Windows the regions used for lock and unlock needs to match. If that + * is not the case unlocking will result in the OS error "The segment is + * already unlocked". + * + */ + void lockSync( + [FileLock mode = FileLock.exclusive, int start = 0, int end = -1]); + + /** + * Unlocks the file or part of the file. + * + * Unlocks the byte range from [start] to [end] of the file, with + * the byte at position `end` not included. If no arguments are + * specified, the full file is unlocked, If only `start` is + * specified the file is unlocked from byte position `start` to the + * end of the file. + * + * *NOTE* file locking does have slight differences in behavior across + * platforms: + * + * See [lock] for more details. + */ + Future unlock([int start = 0, int end = -1]); + + /** + * Synchronously unlocks the file or part of the file. + * + * Unlocks the byte range from [start] to [end] of the file, with + * the byte at position `end` not included. If no arguments are + * specified, the full file is unlocked, If only `start` is + * specified the file is unlocked from byte position `start` to the + * end of the file. + * + * *NOTE* file locking does have slight differences in behavior across + * platforms: + * + * See [lockSync] for more details. + */ + void unlockSync([int start = 0, int end = -1]); + + /** + * Returns a human-readable string for this RandomAccessFile instance. + */ + String toString(); + + /** + * Gets the path of the file underlying this RandomAccessFile. + */ + String get path; +} + +/** + * Exception thrown when a file operation fails. + */ +class FileSystemException implements IOException { + /** + * Message describing the error. This does not include any detailed + * information form the underlying OS error. Check [osError] for + * that information. + */ + final String message; + + /** + * The file system path on which the error occurred. Can be `null` + * if the exception does not relate directly to a file system path. + */ + final String path; + + /** + * The underlying OS error. Can be `null` if the exception is not + * raised due to an OS error. + */ + final OSError osError; + + /** + * Creates a new FileSystemException with an optional error message + * [message], optional file system path [path] and optional OS error + * [osError]. + */ + const FileSystemException([this.message = "", this.path = "", this.osError]); + + String toString() { + StringBuffer sb = new StringBuffer(); + sb.write("FileSystemException"); + if (!message.isEmpty) { + sb.write(": $message"); + if (path != null) { + sb.write(", path = '$path'"); + } + if (osError != null) { + sb.write(" ($osError)"); + } + } else if (osError != null) { + sb.write(": $osError"); + if (path != null) { + sb.write(", path = '$path'"); + } + } else if (path != null) { + sb.write(": $path"); + } + return sb.toString(); + } +} +NN<,43"CK4#=C5$ >K8''8C>-4(2)EI*?A+ 58D>7-@,:DQ>5;5 @&:, EG=*&>7 3BKD,$ D"aIHjQRL2JEH 7'&F?I0'+C(GD/KFO0FJ7?0K<,@2)/<J0G!+O<:#+>Q>:3I?)A?++O<:#+>Q>:3I?)AF+;?F&)1FFIACFG*8<=FL-OGG4::8 :%?;D<PI:LF".($<>JE&<P%D,<!NMOLKDPOPN<@1901A+< ON<C27!KLJ<BG906"F<B;5?<39667<&B9>1F<!?)0<99:$=<)OF>FEFKJI;DII@FGEFEFKJM9D9I@FGEFI"B9DB>FI&2IA13FCEFD FGP*%&!"&Mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/file_impl.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +// Read the file in blocks of size 64k. +const int _blockSize = 64 * 1024; + +class _FileStream extends Stream> { + // Stream controller. + StreamController> _controller; + + // Information about the underlying file. + String _path; + RandomAccessFile _openedFile; + int _position; + int _end; + final Completer _closeCompleter = new Completer(); + + // Has the stream been paused or unsubscribed? + bool _unsubscribed = false; + + // Is there a read currently in progress? + bool _readInProgress = true; + bool _closed = false; + + bool _atEnd = false; + + _FileStream(this._path, this._position, this._end) { + if (_position == null) _position = 0; + } + + _FileStream.forStdin() : _position = 0; + + StreamSubscription> listen(void onData(List event), + {Function onError, void onDone(), bool cancelOnError}) { + _setupController(); + return _controller.stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + } + + void _setupController() { + _controller = new StreamController>( + sync: true, + onListen: _start, + onResume: _readBlock, + onCancel: () { + _unsubscribed = true; + return _closeFile(); + }); + } + + Future _closeFile() { + if (_readInProgress || _closed) { + return _closeCompleter.future; + } + _closed = true; + + void done() { + _closeCompleter.complete(); + _controller.close(); + } + + _openedFile.close().catchError(_controller.addError).whenComplete(done); + return _closeCompleter.future; + } + + void _readBlock() { + // Don't start a new read if one is already in progress. + if (_readInProgress) return; + if (_atEnd) { + _closeFile(); + return; + } + _readInProgress = true; + int readBytes = _blockSize; + if (_end != null) { + readBytes = min(readBytes, _end - _position); + if (readBytes < 0) { + _readInProgress = false; + if (!_unsubscribed) { + _controller.addError(new RangeError("Bad end position: $_end")); + _closeFile(); + _unsubscribed = true; + } + return; + } + } + _openedFile.read(readBytes).then((block) { + _readInProgress = false; + if (_unsubscribed) { + _closeFile(); + return; + } + _position += block.length; + if (block.length < readBytes || (_end != null && _position == _end)) { + _atEnd = true; + } + if (!_atEnd && !_controller.isPaused) { + _readBlock(); + } + _controller.add(block); + if (_atEnd) { + _closeFile(); + } + }).catchError((e, s) { + if (!_unsubscribed) { + _controller.addError(e, s); + _closeFile(); + _unsubscribed = true; + } + }); + } + + void _start() { + if (_position < 0) { + _controller.addError(new RangeError("Bad start position: $_position")); + _controller.close(); + _closeCompleter.complete(); + return; + } + + void onReady(RandomAccessFile file) { + _openedFile = file; + _readInProgress = false; + _readBlock(); + } + + void onOpenFile(RandomAccessFile file) { + if (_position > 0) { + file.setPosition(_position).then(onReady, onError: (e, s) { + _controller.addError(e, s); + _readInProgress = false; + _closeFile(); + }); + } else { + onReady(file); + } + } + + void openFailed(error, stackTrace) { + _controller.addError(error, stackTrace); + _controller.close(); + _closeCompleter.complete(); + } + + if (_path != null) { + new File(_path) + .open(mode: FileMode.read) + .then(onOpenFile, onError: openFailed); + } else { + try { + onOpenFile(_File._openStdioSync(0)); + } catch (e, s) { + openFailed(e, s); + } + } + } +} + +class _FileStreamConsumer extends StreamConsumer> { + File _file; + Future _openFuture; + + _FileStreamConsumer(this._file, FileMode mode) { + _openFuture = _file.open(mode: mode); + } + + _FileStreamConsumer.fromStdio(int fd) { + _openFuture = new Future.value(_File._openStdioSync(fd)); + } + + Future addStream(Stream> stream) { + Completer completer = new Completer.sync(); + _openFuture.then((openedFile) { + var _subscription; + void error(e, [StackTrace stackTrace]) { + _subscription.cancel(); + openedFile.close(); + completer.completeError(e, stackTrace); + } + + _subscription = stream.listen((d) { + _subscription.pause(); + try { + openedFile + .writeFrom(d, 0, d.length) + .then((_) => _subscription.resume(), onError: error); + } catch (e, stackTrace) { + error(e, stackTrace); + } + }, onDone: () { + completer.complete(_file); + }, onError: error, cancelOnError: true); + }).catchError(completer.completeError); + return completer.future; + } + + Future close() => + _openFuture.then((openedFile) => openedFile.close()).then((_) => _file); +} + +// Class for encapsulating the native implementation of files. +class _File extends FileSystemEntity implements File { + String _path; + Uint8List _rawPath; + + _File(String path) { + if (path is! String) { + throw new ArgumentError('${Error.safeToString(path)} is not a String'); + } + _path = path; + _rawPath = FileSystemEntity._toUtf8Array(path); + } + + _File.fromRawPath(Uint8List rawPath) { + if (rawPath == null) { + throw new ArgumentError('rawPath cannot be null'); + } + _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(rawPath); + _path = FileSystemEntity._toStringFromUtf8Array(rawPath); + } + + String get path => _path; + + // WARNING: + // Calling this function will increase the reference count on the native + // namespace object. It should only be called to pass the pointer to the + // IOService, which will decrement the reference count when it is finished + // with it. + static int _namespacePointer() => _Namespace._namespacePointer; + + static Future _dispatchWithNamespace(int request, List data) { + data[0] = _namespacePointer(); + return _IOService._dispatch(request, data); + } + + Future exists() { + return _dispatchWithNamespace(_IOService.fileExists, [null, _rawPath]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "Cannot check existence", path); + } + return response; + }); + } + + external static _exists(_Namespace namespace, Uint8List rawPath); + + bool existsSync() { + var result = _exists(_Namespace._namespace, _rawPath); + throwIfError(result, "Cannot check existence of file", path); + return result; + } + + File get absolute => new File(_absolutePath); + + Future create({bool recursive: false}) { + var result = + recursive ? parent.create(recursive: true) : new Future.value(null); + return result + .then((_) => + _dispatchWithNamespace(_IOService.fileCreate, [null, _rawPath])) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "Cannot create file", path); + } + return this; + }); + } + + external static _create(_Namespace namespace, Uint8List rawPath); + + external static _createLink( + _Namespace namespace, Uint8List rawPath, String target); + + external static _linkTarget(_Namespace namespace, Uint8List rawPath); + + void createSync({bool recursive: false}) { + if (recursive) { + parent.createSync(recursive: true); + } + var result = _create(_Namespace._namespace, _rawPath); + throwIfError(result, "Cannot create file", path); + } + + Future _delete({bool recursive: false}) { + if (recursive) { + return new Directory(path).delete(recursive: true).then((_) => this); + } + return _dispatchWithNamespace(_IOService.fileDelete, [null, _rawPath]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "Cannot delete file", path); + } + return this; + }); + } + + external static _deleteNative(_Namespace namespace, Uint8List rawPath); + + external static _deleteLinkNative(_Namespace namespace, Uint8List rawPath); + + void _deleteSync({bool recursive: false}) { + if (recursive) { + return new Directory.fromRawPath(_rawPath).deleteSync(recursive: true); + } + var result = _deleteNative(_Namespace._namespace, _rawPath); + throwIfError(result, "Cannot delete file", path); + } + + Future rename(String newPath) { + return _dispatchWithNamespace( + _IOService.fileRename, [null, _rawPath, newPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot rename file to '$newPath'", path); + } + return new File(newPath); + }); + } + + external static _rename( + _Namespace namespace, Uint8List oldPath, String newPath); + + external static _renameLink( + _Namespace namespace, Uint8List oldPath, String newPath); + + File renameSync(String newPath) { + var result = _rename(_Namespace._namespace, _rawPath, newPath); + throwIfError(result, "Cannot rename file to '$newPath'", path); + return new File(newPath); + } + + Future copy(String newPath) { + return _dispatchWithNamespace( + _IOService.fileCopy, [null, _rawPath, newPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot copy file to '$newPath'", path); + } + return new File(newPath); + }); + } + + external static _copy( + _Namespace namespace, Uint8List oldPath, String newPath); + + File copySync(String newPath) { + var result = _copy(_Namespace._namespace, _rawPath, newPath); + throwIfError(result, "Cannot copy file to '$newPath'", path); + return new File(newPath); + } + + Future open({FileMode mode: FileMode.read}) { + if (mode != FileMode.read && + mode != FileMode.write && + mode != FileMode.append && + mode != FileMode.writeOnly && + mode != FileMode.writeOnlyAppend) { + return new Future.error( + new ArgumentError('Invalid file mode for this operation')); + } + return _dispatchWithNamespace( + _IOService.fileOpen, [null, _rawPath, mode._mode]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "Cannot open file", path); + } + return new _RandomAccessFile(response, path); + }); + } + + Future length() { + return _dispatchWithNamespace( + _IOService.fileLengthFromPath, [null, _rawPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot retrieve length of file", path); + } + return response; + }); + } + + external static _lengthFromPath(_Namespace namespace, Uint8List rawPath); + + int lengthSync() { + var result = _lengthFromPath(_Namespace._namespace, _rawPath); + throwIfError(result, "Cannot retrieve length of file", path); + return result; + } + + Future lastAccessed() { + return _dispatchWithNamespace(_IOService.fileLastAccessed, [null, _rawPath]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot retrieve access time", path); + } + return new DateTime.fromMillisecondsSinceEpoch(response); + }); + } + + external static _lastAccessed(_Namespace namespace, Uint8List rawPath); + + DateTime lastAccessedSync() { + var ms = _lastAccessed(_Namespace._namespace, _rawPath); + throwIfError(ms, "Cannot retrieve access time", path); + return new DateTime.fromMillisecondsSinceEpoch(ms); + } + + Future setLastAccessed(DateTime time) { + int millis = time.millisecondsSinceEpoch; + return _dispatchWithNamespace( + _IOService.fileSetLastAccessed, [null, _rawPath, millis]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "Cannot set access time", path); + } + return null; + }); + } + + external static _setLastAccessed( + _Namespace namespace, Uint8List rawPath, int millis); + + void setLastAccessedSync(DateTime time) { + int millis = time.millisecondsSinceEpoch; + var result = _setLastAccessed(_Namespace._namespace, _rawPath, millis); + if (result is OSError) { + throw new FileSystemException( + "Failed to set file access time", path, result); + } + } + + Future lastModified() { + return _dispatchWithNamespace(_IOService.fileLastModified, [null, _rawPath]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot retrieve modification time", path); + } + return new DateTime.fromMillisecondsSinceEpoch(response); + }); + } + + external static _lastModified(_Namespace namespace, Uint8List rawPath); + + DateTime lastModifiedSync() { + var ms = _lastModified(_Namespace._namespace, _rawPath); + throwIfError(ms, "Cannot retrieve modification time", path); + return new DateTime.fromMillisecondsSinceEpoch(ms); + } + + Future setLastModified(DateTime time) { + int millis = time.millisecondsSinceEpoch; + return _dispatchWithNamespace( + _IOService.fileSetLastModified, [null, _rawPath, millis]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot set modification time", path); + } + return null; + }); + } + + external static _setLastModified( + _Namespace namespace, Uint8List rawPath, int millis); + + void setLastModifiedSync(DateTime time) { + int millis = time.millisecondsSinceEpoch; + var result = _setLastModified(_Namespace._namespace, _rawPath, millis); + if (result is OSError) { + throw new FileSystemException( + "Failed to set file modification time", path, result); + } + } + + external static _open(_Namespace namespace, Uint8List rawPath, int mode); + + RandomAccessFile openSync({FileMode mode: FileMode.read}) { + if (mode != FileMode.read && + mode != FileMode.write && + mode != FileMode.append && + mode != FileMode.writeOnly && + mode != FileMode.writeOnlyAppend) { + throw new ArgumentError('Invalid file mode for this operation'); + } + var id = _open(_Namespace._namespace, _rawPath, mode._mode); + throwIfError(id, "Cannot open file", path); + return new _RandomAccessFile(id, _path); + } + + external static int _openStdio(int fd); + + static RandomAccessFile _openStdioSync(int fd) { + var id = _openStdio(fd); + if (id == 0) { + throw new FileSystemException("Cannot open stdio file for: $fd"); + } + return new _RandomAccessFile(id, ""); + } + + Stream> openRead([int start, int end]) { + return new _FileStream(path, start, end); + } + + IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}) { + if (mode != FileMode.write && + mode != FileMode.append && + mode != FileMode.writeOnly && + mode != FileMode.writeOnlyAppend) { + throw new ArgumentError('Invalid file mode for this operation'); + } + var consumer = new _FileStreamConsumer(this, mode); + return new IOSink(consumer, encoding: encoding); + } + + Future> readAsBytes() { + Future> readDataChunked(RandomAccessFile file) { + var builder = new BytesBuilder(copy: false); + var completer = new Completer>(); + void read() { + file.read(_blockSize).then((data) { + if (data.length > 0) { + builder.add(data); + read(); + } else { + completer.complete(builder.takeBytes()); + } + }, onError: completer.completeError); + } + + read(); + return completer.future; + } + + return open().then((file) { + return file.length().then((length) { + if (length == 0) { + // May be character device, try to read it in chunks. + return readDataChunked(file); + } + return file.read(length); + }).whenComplete(file.close); + }); + } + + List readAsBytesSync() { + var opened = openSync(); + try { + List data; + var length = opened.lengthSync(); + if (length == 0) { + // May be character device, try to read it in chunks. + var builder = new BytesBuilder(copy: false); + do { + data = opened.readSync(_blockSize); + if (data.length > 0) builder.add(data); + } while (data.length > 0); + data = builder.takeBytes(); + } else { + data = opened.readSync(length); + } + return data; + } finally { + opened.closeSync(); + } + } + + String _tryDecode(List bytes, Encoding encoding) { + try { + return encoding.decode(bytes); + } catch (_) { + throw new FileSystemException( + "Failed to decode data using encoding '${encoding.name}'", path); + } + } + + Future readAsString({Encoding encoding: utf8}) { + // TODO(dart:io): If the change in async semantics to run synchronously + // until await lands, this is as efficient as + // return _tryDecode(await readAsBytes(), encoding); + var stack = StackTrace.current; + return readAsBytes().then((bytes) { + try { + return _tryDecode(bytes, encoding); + } catch (e) { + return new Future.error(e, stack); + } + }); + } + + String readAsStringSync({Encoding encoding: utf8}) => + _tryDecode(readAsBytesSync(), encoding); + + Future> readAsLines({Encoding encoding: utf8}) => + readAsString(encoding: encoding).then(const LineSplitter().convert); + + List readAsLinesSync({Encoding encoding: utf8}) => + const LineSplitter().convert(readAsStringSync(encoding: encoding)); + + Future writeAsBytes(List bytes, + {FileMode mode: FileMode.write, bool flush: false}) { + return open(mode: mode).then((file) { + return file.writeFrom(bytes, 0, bytes.length).then((_) { + if (flush) return file.flush().then((_) => this); + return this; + }).whenComplete(file.close); + }); + } + + void writeAsBytesSync(List bytes, + {FileMode mode: FileMode.write, bool flush: false}) { + RandomAccessFile opened = openSync(mode: mode); + try { + opened.writeFromSync(bytes, 0, bytes.length); + if (flush) opened.flushSync(); + } finally { + opened.closeSync(); + } + } + + Future writeAsString(String contents, + {FileMode mode: FileMode.write, + Encoding encoding: utf8, + bool flush: false}) { + try { + return writeAsBytes(encoding.encode(contents), mode: mode, flush: flush); + } catch (e) { + return new Future.error(e); + } + } + + void writeAsStringSync(String contents, + {FileMode mode: FileMode.write, + Encoding encoding: utf8, + bool flush: false}) { + writeAsBytesSync(encoding.encode(contents), mode: mode, flush: flush); + } + + String toString() => "File: '$path'"; + + static throwIfError(Object result, String msg, String path) { + if (result is OSError) { + throw new FileSystemException(msg, path, result); + } + } +} + +abstract class _RandomAccessFileOps { + external factory _RandomAccessFileOps(int pointer); + + int getPointer(); + int close(); + readByte(); + read(int bytes); + readInto(List buffer, int start, int end); + writeByte(int value); + writeFrom(List buffer, int start, int end); + position(); + setPosition(int position); + truncate(int length); + length(); + flush(); + lock(int lock, int start, int end); +} + +class _RandomAccessFile implements RandomAccessFile { + static bool _connectedResourceHandler = false; + + final String path; + + bool _asyncDispatched = false; + SendPort _fileService; + + _FileResourceInfo _resourceInfo; + _RandomAccessFileOps _ops; + + _RandomAccessFile(int pointer, this.path) { + _ops = new _RandomAccessFileOps(pointer); + _resourceInfo = new _FileResourceInfo(this); + _maybeConnectHandler(); + } + + void _maybePerformCleanup() { + if (closed) { + _FileResourceInfo.FileClosed(_resourceInfo); + } + } + + _maybeConnectHandler() { + if (!_connectedResourceHandler) { + // TODO(ricow): We probably need to set these in some initialization code. + // We need to make sure that these are always available from the + // observatory even if no files (or sockets for the socket ones) are + // open. + registerExtension( + 'ext.dart.io.getOpenFiles', _FileResourceInfo.getOpenFiles); + registerExtension( + 'ext.dart.io.getFileByID', _FileResourceInfo.getFileInfoMapByID); + _connectedResourceHandler = true; + } + } + + Future close() { + return _dispatch(_IOService.fileClose, [null], markClosed: true) + .then((result) { + if (result == -1) { + throw new FileSystemException("Cannot close file", path); + } + closed = closed || (result == 0); + _maybePerformCleanup(); + }); + } + + void closeSync() { + _checkAvailable(); + var id = _ops.close(); + if (id == -1) { + throw new FileSystemException("Cannot close file", path); + } + closed = closed || (id == 0); + _maybePerformCleanup(); + } + + Future readByte() { + return _dispatch(_IOService.fileReadByte, [null]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "readByte failed", path); + } + _resourceInfo.addRead(1); + return response; + }); + } + + int readByteSync() { + _checkAvailable(); + var result = _ops.readByte(); + if (result is OSError) { + throw new FileSystemException("readByte failed", path, result); + } + _resourceInfo.addRead(1); + return result; + } + + Future> read(int bytes) { + if (bytes is! int) { + throw new ArgumentError(bytes); + } + return _dispatch(_IOService.fileRead, [null, bytes]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "read failed", path); + } + _resourceInfo.addRead(response[1].length); + List result = response[1]; + return result; + }); + } + + List readSync(int bytes) { + _checkAvailable(); + if (bytes is! int) { + throw new ArgumentError(bytes); + } + var result = _ops.read(bytes); + if (result is OSError) { + throw new FileSystemException("readSync failed", path, result); + } + _resourceInfo.addRead(result.length); + return result; + } + + Future readInto(List buffer, [int start = 0, int end]) { + if ((buffer is! List) || + ((start != null) && (start is! int)) || + ((end != null) && (end is! int))) { + throw new ArgumentError(); + } + end = RangeError.checkValidRange(start, end, buffer.length); + if (end == start) { + return new Future.value(0); + } + int length = end - start; + return _dispatch(_IOService.fileReadInto, [null, length]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "readInto failed", path); + } + int read = response[1]; + List data = response[2]; + buffer.setRange(start, start + read, data); + _resourceInfo.addRead(read); + return read; + }); + } + + int readIntoSync(List buffer, [int start = 0, int end]) { + _checkAvailable(); + if ((buffer is! List) || + ((start != null) && (start is! int)) || + ((end != null) && (end is! int))) { + throw new ArgumentError(); + } + end = RangeError.checkValidRange(start, end, buffer.length); + if (end == start) { + return 0; + } + var result = _ops.readInto(buffer, start, end); + if (result is OSError) { + throw new FileSystemException("readInto failed", path, result); + } + _resourceInfo.addRead(result); + return result; + } + + Future writeByte(int value) { + if (value is! int) { + throw new ArgumentError(value); + } + return _dispatch(_IOService.fileWriteByte, [null, value]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "writeByte failed", path); + } + _resourceInfo.addWrite(1); + return this; + }); + } + + int writeByteSync(int value) { + _checkAvailable(); + if (value is! int) { + throw new ArgumentError(value); + } + var result = _ops.writeByte(value); + if (result is OSError) { + throw new FileSystemException("writeByte failed", path, result); + } + _resourceInfo.addWrite(1); + return result; + } + + Future writeFrom(List buffer, + [int start = 0, int end]) { + if ((buffer is! List) || + ((start != null) && (start is! int)) || + ((end != null) && (end is! int))) { + throw new ArgumentError("Invalid arguments to writeFrom"); + } + end = RangeError.checkValidRange(start, end, buffer.length); + if (end == start) { + return new Future.value(this); + } + _BufferAndStart result; + try { + result = _ensureFastAndSerializableByteData(buffer, start, end); + } catch (e) { + return new Future.error(e); + } + + List request = new List(4); + request[0] = null; + request[1] = result.buffer; + request[2] = result.start; + request[3] = end - (start - result.start); + return _dispatch(_IOService.fileWriteFrom, request).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "writeFrom failed", path); + } + _resourceInfo.addWrite(end - (start - result.start)); + return this; + }); + } + + void writeFromSync(List buffer, [int start = 0, int end]) { + _checkAvailable(); + if ((buffer is! List) || + ((start != null) && (start is! int)) || + ((end != null) && (end is! int))) { + throw new ArgumentError("Invalid arguments to writeFromSync"); + } + end = RangeError.checkValidRange(start, end, buffer.length); + if (end == start) { + return; + } + _BufferAndStart bufferAndStart = + _ensureFastAndSerializableByteData(buffer, start, end); + var result = _ops.writeFrom(bufferAndStart.buffer, bufferAndStart.start, + end - (start - bufferAndStart.start)); + if (result is OSError) { + throw new FileSystemException("writeFrom failed", path, result); + } + _resourceInfo.addWrite(end - (start - bufferAndStart.start)); + } + + Future writeString(String string, + {Encoding encoding: utf8}) { + if (encoding is! Encoding) { + throw new ArgumentError(encoding); + } + var data = encoding.encode(string); + return writeFrom(data, 0, data.length); + } + + void writeStringSync(String string, {Encoding encoding: utf8}) { + if (encoding is! Encoding) { + throw new ArgumentError(encoding); + } + var data = encoding.encode(string); + writeFromSync(data, 0, data.length); + } + + Future position() { + return _dispatch(_IOService.filePosition, [null]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "position failed", path); + } + return response; + }); + } + + int positionSync() { + _checkAvailable(); + var result = _ops.position(); + if (result is OSError) { + throw new FileSystemException("position failed", path, result); + } + return result; + } + + Future setPosition(int position) { + return _dispatch(_IOService.fileSetPosition, [null, position]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "setPosition failed", path); + } + return this; + }); + } + + void setPositionSync(int position) { + _checkAvailable(); + var result = _ops.setPosition(position); + if (result is OSError) { + throw new FileSystemException("setPosition failed", path, result); + } + } + + Future truncate(int length) { + return _dispatch(_IOService.fileTruncate, [null, length]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "truncate failed", path); + } + return this; + }); + } + + void truncateSync(int length) { + _checkAvailable(); + var result = _ops.truncate(length); + if (result is OSError) { + throw new FileSystemException("truncate failed", path, result); + } + } + + Future length() { + return _dispatch(_IOService.fileLength, [null]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "length failed", path); + } + return response; + }); + } + + int lengthSync() { + _checkAvailable(); + var result = _ops.length(); + if (result is OSError) { + throw new FileSystemException("length failed", path, result); + } + return result; + } + + Future flush() { + return _dispatch(_IOService.fileFlush, [null]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "flush failed", path); + } + return this; + }); + } + + void flushSync() { + _checkAvailable(); + var result = _ops.flush(); + if (result is OSError) { + throw new FileSystemException("flush failed", path, result); + } + } + + static const int lockUnlock = 0; + // static const int lockShared = 1; + // static const int lockExclusive = 2; + // static const int lockBlockingShared = 3; + // static const int lockBlockingExclusive = 4; + + int _fileLockValue(FileLock fl) => fl._type; + + Future lock( + [FileLock mode = FileLock.exclusive, int start = 0, int end = -1]) { + if ((mode is! FileLock) || (start is! int) || (end is! int)) { + throw new ArgumentError(); + } + if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) { + throw new ArgumentError(); + } + int lock = _fileLockValue(mode); + return _dispatch(_IOService.fileLock, [null, lock, start, end]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, 'lock failed', path); + } + return this; + }); + } + + Future unlock([int start = 0, int end = -1]) { + if ((start is! int) || (end is! int)) { + throw new ArgumentError(); + } + if (start == end) { + throw new ArgumentError(); + } + return _dispatch(_IOService.fileLock, [null, lockUnlock, start, end]) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, 'unlock failed', path); + } + return this; + }); + } + + void lockSync( + [FileLock mode = FileLock.exclusive, int start = 0, int end = -1]) { + _checkAvailable(); + if ((mode is! FileLock) || (start is! int) || (end is! int)) { + throw new ArgumentError(); + } + if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) { + throw new ArgumentError(); + } + int lock = _fileLockValue(mode); + var result = _ops.lock(lock, start, end); + if (result is OSError) { + throw new FileSystemException('lock failed', path, result); + } + } + + void unlockSync([int start = 0, int end = -1]) { + _checkAvailable(); + if ((start is! int) || (end is! int)) { + throw new ArgumentError(); + } + if (start == end) { + throw new ArgumentError(); + } + var result = _ops.lock(lockUnlock, start, end); + if (result is OSError) { + throw new FileSystemException('unlock failed', path, result); + } + } + + bool closed = false; + + // WARNING: + // Calling this function will increase the reference count on the native + // object that implements the file operations. It should only be called to + // pass the pointer to the IO Service, which will decrement the reference + // count when it is finished with it. + int _pointer() => _ops.getPointer(); + + Future _dispatch(int request, List data, {bool markClosed: false}) { + if (closed) { + return new Future.error(new FileSystemException("File closed", path)); + } + if (_asyncDispatched) { + var msg = "An async operation is currently pending"; + return new Future.error(new FileSystemException(msg, path)); + } + if (markClosed) { + // Set closed to true to ensure that no more async requests can be issued + // for this file. + closed = true; + } + _asyncDispatched = true; + data[0] = _pointer(); + return _IOService._dispatch(request, data).whenComplete(() { + _asyncDispatched = false; + }); + } + + void _checkAvailable() { + if (_asyncDispatched) { + throw new FileSystemException( + "An async operation is currently pending", path); + } + if (closed) { + throw new FileSystemException("File closed", path); + } + } +} +YNN<(".+,  51,7**E?-I3  &%"M#=! 4!K +/!M.$N"*-D&# )/"%2 ->(3**>5<$/ 0*)D" +#/,O?7N4)9E>KKMBA#0K(PD;B01MM(LD?H-*;62LK(LJN.NA6(#L(&A @@$DD&#J(&? @"BBB!"#&,F#M(J4#K(&?LCB$Q(&<@J =;8*.#F(P$<,.L%;$Q(&B@J =A8*.#F(&=$<,.L%AL>!"#&,GA0-*3H*5.O"#&,G85$?32,!5 . +@( +"#  +(>5 .2#$(: +%%L;L29$( ,+8/AK=J-<*E:#)<4 +4%.& +P"*&K(@8&623 &61!#..1 3&QGKGL(EB(@"H(I "F&&K(E1&"&#F*E0,!A"P(I$2#A0,!A4F#2&P(J!!&(G7"0,AA% +G"  /J(J<C0,EA%@M/GB6#!)(,C!)()H(I"F7C(L'-I2P(I"(FF(G D%E(FC#&).1/!KC!H!%D(EC,!!J(GKC!H!%.B3,!!4DKML('GM;CPA %<:Vfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/file_system_entity.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * The type of an entity on the file system, such as a file, directory, or link. + * + * These constants are used by the [FileSystemEntity] class + * to indicate the object's type. + * + */ + +class FileSystemEntityType { + static const file = const FileSystemEntityType._internal(0); + @Deprecated("Use file instead") + static const FILE = file; + + static const directory = const FileSystemEntityType._internal(1); + @Deprecated("Use directory instead") + static const DIRECTORY = directory; + + static const link = const FileSystemEntityType._internal(2); + @Deprecated("Use link instead") + static const LINK = link; + + static const notFound = const FileSystemEntityType._internal(3); + @Deprecated("Use notFound instead") + static const NOT_FOUND = notFound; + + static const _typeList = const [ + FileSystemEntityType.file, + FileSystemEntityType.directory, + FileSystemEntityType.link, + FileSystemEntityType.notFound, + ]; + final int _type; + + const FileSystemEntityType._internal(this._type); + + static FileSystemEntityType _lookup(int type) => _typeList[type]; + String toString() => const ['file', 'directory', 'link', 'notFound'][_type]; +} + +/** + * A FileStat object represents the result of calling the POSIX stat() function + * on a file system object. It is an immutable object, representing the + * snapshotted values returned by the stat() call. + */ +class FileStat { + // These must agree with enum FileStat in file.h. + static const _type = 0; + static const _changedTime = 1; + static const _modifiedTime = 2; + static const _accessedTime = 3; + static const _mode = 4; + static const _size = 5; + + static const _notFound = const FileStat._internalNotFound(); + + /** + * The time of the last change to the data or metadata of the file system + * object. + * + * On Windows platforms, this is instead the file creation time. + */ + final DateTime changed; + + /** + * The time of the last change to the data of the file system object. + */ + final DateTime modified; + + /** + * The time of the last access to the data of the file system object. + * + * On Windows platforms, this may have 1 day granularity, and be + * out of date by an hour. + */ + final DateTime accessed; + + /** + * The type of the object (file, directory, or link). + * + * If the call to stat() fails, the type of the returned object is notFound. + */ + final FileSystemEntityType type; + + /** + * The mode of the file system object. + * + * Permissions are encoded in the lower 16 bits of this number, and can be + * decoded using the [modeString] getter. + */ + final int mode; + + /** + * The size of the file system object. + */ + final int size; + + FileStat._internal(this.changed, this.modified, this.accessed, this.type, + this.mode, this.size); + + const FileStat._internalNotFound() + : changed = null, + modified = null, + accessed = null, + type = FileSystemEntityType.notFound, + mode = 0, + size = -1; + + external static _statSync(_Namespace namespace, String path); + + /** + * Calls the operating system's stat() function on [path]. + * + * Returns a [FileStat] object containing the data returned by stat(). + * If the call fails, returns a [FileStat] object with .type set to + * FileSystemEntityType.notFound and the other fields invalid. + */ + static FileStat statSync(String path) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _statSyncInternal(path); + } + return overrides.statSync(path); + } + + static FileStat _statSyncInternal(String path) { + // Trailing path is not supported on Windows. + if (Platform.isWindows) { + path = FileSystemEntity._trimTrailingPathSeparators(path); + } + var data = _statSync(_Namespace._namespace, path); + if (data is OSError) return FileStat._notFound; + return new FileStat._internal( + new DateTime.fromMillisecondsSinceEpoch(data[_changedTime]), + new DateTime.fromMillisecondsSinceEpoch(data[_modifiedTime]), + new DateTime.fromMillisecondsSinceEpoch(data[_accessedTime]), + FileSystemEntityType._lookup(data[_type]), + data[_mode], + data[_size]); + } + + /** + * Asynchronously calls the operating system's stat() function on [path]. + * + * Returns a Future which completes with a [FileStat] object containing + * the data returned by stat(). If the call fails, completes the future with a + * [FileStat] object with `.type` set to FileSystemEntityType.notFound and + * the other fields invalid. + */ + static Future stat(String path) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _stat(path); + } + return overrides.stat(path); + } + + static Future _stat(String path) { + // Trailing path is not supported on Windows. + if (Platform.isWindows) { + path = FileSystemEntity._trimTrailingPathSeparators(path); + } + return _File._dispatchWithNamespace(_IOService.fileStat, [null, path]).then( + (response) { + if (_isErrorResponse(response)) { + return FileStat._notFound; + } + // Unwrap the real list from the "I'm not an error" wrapper. + List data = response[1]; + return new FileStat._internal( + new DateTime.fromMillisecondsSinceEpoch(data[_changedTime]), + new DateTime.fromMillisecondsSinceEpoch(data[_modifiedTime]), + new DateTime.fromMillisecondsSinceEpoch(data[_accessedTime]), + FileSystemEntityType._lookup(data[_type]), + data[_mode], + data[_size]); + }); + } + + String toString() => """ +FileStat: type $type + changed $changed + modified $modified + accessed $accessed + mode ${modeString()} + size $size"""; + + /** + * Returns the mode value as a human-readable string. + * + * The string is in the format "rwxrwxrwx", reflecting the user, group, and + * world permissions to read, write, and execute the file system object, with + * "-" replacing the letter for missing permissions. Extra permission bits + * may be represented by prepending "(suid)", "(guid)", and/or "(sticky)" to + * the mode string. + */ + String modeString() { + var permissions = mode & 0xFFF; + var codes = const ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx']; + var result = []; + if ((permissions & 0x800) != 0) result.add("(suid) "); + if ((permissions & 0x400) != 0) result.add("(guid) "); + if ((permissions & 0x200) != 0) result.add("(sticky) "); + result + ..add(codes[(permissions >> 6) & 0x7]) + ..add(codes[(permissions >> 3) & 0x7]) + ..add(codes[permissions & 0x7]); + return result.join(); + } +} + +/** + * The common super class for [File], [Directory], and [Link] objects. + * + * [FileSystemEntity] objects are returned from directory listing + * operations. To determine if a FileSystemEntity is a [File], a + * [Directory], or a [Link] perform a type check: + * + * if (entity is File) (entity as File).readAsStringSync(); + * + * You can also use the [type] or [typeSync] methods to determine + * the type of a file system object. + * + * Most methods in this class occur in synchronous and asynchronous pairs, + * for example, [exists] and [existsSync]. + * Unless you have a specific reason for using the synchronous version + * of a method, prefer the asynchronous version to avoid blocking your program. + * + * Here's the exists method in action: + * + * entity.exists().then((isThere) { + * isThere ? print('exists') : print('non-existent'); + * }); + * + * + * ## Other resources + * + * * [Dart by + * Example](https://www.dartlang.org/dart-by-example/#files-directories-and-symlinks) + * provides additional task-oriented code samples that show how to use various + * API from the [Directory] class and the [File] class, both subclasses of + * FileSystemEntity. + * + * * [I/O for Command-Line + * Apps](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartio---io-for-command-line-apps), + * a section from _A Tour of the Dart Libraries_ covers files and directories. + * + * * [Write Command-Line Apps](https://www.dartlang.org/docs/tutorials/cmdline/), + * a tutorial about writing command-line apps, includes information about + * files and directories. + */ +abstract class FileSystemEntity { + String _path; + Uint8List _rawPath; + + String get path; + + /** + * Returns a [Uri] representing the file system entity's location. + * + * The returned URI's scheme is always "file" if the entity's [path] is + * absolute, otherwise the scheme will be empty. + */ + Uri get uri => new Uri.file(path); + + /** + * Checks whether the file system entity with this path exists. Returns + * a [:Future:] that completes with the result. + * + * Since FileSystemEntity is abstract, every FileSystemEntity object + * is actually an instance of one of the subclasses [File], + * [Directory], and [Link]. Calling [exists] on an instance of one + * of these subclasses checks whether the object exists in the file + * system object exists and is of the correct type (file, directory, + * or link). To check whether a path points to an object on the + * file system, regardless of the object's type, use the [type] + * static method. + * + */ + Future exists(); + + /** + * Synchronously checks whether the file system entity with this path + * exists. + * + * Since FileSystemEntity is abstract, every FileSystemEntity object + * is actually an instance of one of the subclasses [File], + * [Directory], and [Link]. Calling [existsSync] on an instance of + * one of these subclasses checks whether the object exists in the + * file system object exists and is of the correct type (file, + * directory, or link). To check whether a path points to an object + * on the file system, regardless of the object's type, use the + * [typeSync] static method. + */ + bool existsSync(); + + /** + * Renames this file system entity. + * + * Returns a `Future` that completes with a + * [FileSystemEntity] instance for the renamed file system entity. + * + * If [newPath] identifies an existing entity of the same type, that entity + * is replaced. If [newPath] identifies an existing entity of a different + * type, the operation fails and the future completes with an exception. + */ + Future rename(String newPath); + + /** + * Synchronously renames this file system entity. + * + * Returns a [FileSystemEntity] instance for the renamed entity. + * + * If [newPath] identifies an existing entity of the same type, that entity + * is replaced. If [newPath] identifies an existing entity of a different + * type, the operation fails and an exception is thrown. + */ + FileSystemEntity renameSync(String newPath); + + /** + * Resolves the path of a file system object relative to the + * current working directory. + * + * Resolves all symbolic links on the path and resolves all `..` and `.` path + * segments. + * + * [resolveSymbolicLinks] uses the operating system's native + * file system API to resolve the path, using the `realpath` function + * on linux and OS X, and the `GetFinalPathNameByHandle` function on + * Windows. If the path does not point to an existing file system object, + * `resolveSymbolicLinks` throws a `FileSystemException`. + * + * On Windows the `..` segments are resolved _before_ resolving the symbolic + * link, and on other platforms the symbolic links are _resolved to their + * target_ before applying a `..` that follows. + * + * To ensure the same behavior on all platforms resolve `..` segments before + * calling `resolveSymbolicLinks`. One way of doing this is with the `Uri` + * class: + * + * var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath(); + * if (path == '') path = '.'; + * new File(path).resolveSymbolicLinks().then((resolved) { + * print(resolved); + * }); + * + * since `Uri.resolve` removes `..` segments. This will result in the Windows + * behavior. + */ + Future resolveSymbolicLinks() { + return _File._dispatchWithNamespace( + _IOService.fileResolveSymbolicLinks, [null, _rawPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot resolve symbolic links", path); + } + return response; + }); + } + + /** + * Resolves the path of a file system object relative to the + * current working directory. + * + * Resolves all symbolic links on the path and resolves all `..` and `.` path + * segments. + * + * [resolveSymbolicLinksSync] uses the operating system's native + * file system API to resolve the path, using the `realpath` function + * on linux and OS X, and the `GetFinalPathNameByHandle` function on + * Windows. If the path does not point to an existing file system object, + * `resolveSymbolicLinksSync` throws a `FileSystemException`. + * + * On Windows the `..` segments are resolved _before_ resolving the symbolic + * link, and on other platforms the symbolic links are _resolved to their + * target_ before applying a `..` that follows. + * + * To ensure the same behavior on all platforms resolve `..` segments before + * calling `resolveSymbolicLinksSync`. One way of doing this is with the `Uri` + * class: + * + * var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath(); + * if (path == '') path = '.'; + * var resolved = new File(path).resolveSymbolicLinksSync(); + * print(resolved); + * + * since `Uri.resolve` removes `..` segments. This will result in the Windows + * behavior. + */ + String resolveSymbolicLinksSync() { + var result = _resolveSymbolicLinks(_Namespace._namespace, _rawPath); + _throwIfError(result, "Cannot resolve symbolic links", path); + return result; + } + + /** + * Calls the operating system's stat() function on the [path] of this + * [FileSystemEntity]. + * + * Identical to [:FileStat.stat(this.path):]. + * + * Returns a [:Future:] object containing the data returned by + * stat(). + * + * If the call fails, completes the future with a [FileStat] object + * with .type set to + * FileSystemEntityType.notFound and the other fields invalid. + */ + Future stat() => FileStat.stat(path); + + /** + * Synchronously calls the operating system's stat() function on the + * [path] of this [FileSystemEntity]. + * + * Identical to [:FileStat.statSync(this.path):]. + * + * Returns a [FileStat] object containing the data returned by stat(). + * + * If the call fails, returns a [FileStat] object with .type set to + * FileSystemEntityType.notFound and the other fields invalid. + */ + FileStat statSync() => FileStat.statSync(path); + + /** + * Deletes this [FileSystemEntity]. + * + * If the [FileSystemEntity] is a directory, and if [recursive] is false, + * the directory must be empty. Otherwise, if [recursive] is true, the + * directory and all sub-directories and files in the directories are + * deleted. Links are not followed when deleting recursively. Only the link + * is deleted, not its target. + * + * If [recursive] is true, the [FileSystemEntity] is deleted even if the type + * of the [FileSystemEntity] doesn't match the content of the file system. + * This behavior allows [delete] to be used to unconditionally delete any file + * system object. + * + * Returns a [:Future:] that completes with this + * [FileSystemEntity] when the deletion is done. If the [FileSystemEntity] + * cannot be deleted, the future completes with an exception. + */ + Future delete({bool recursive: false}) => + _delete(recursive: recursive); + + /** + * Synchronously deletes this [FileSystemEntity]. + * + * If the [FileSystemEntity] is a directory, and if [recursive] is false, + * the directory must be empty. Otherwise, if [recursive] is true, the + * directory and all sub-directories and files in the directories are + * deleted. Links are not followed when deleting recursively. Only the link + * is deleted, not its target. + * + * If [recursive] is true, the [FileSystemEntity] is deleted even if the type + * of the [FileSystemEntity] doesn't match the content of the file system. + * This behavior allows [deleteSync] to be used to unconditionally delete any + * file system object. + * + * Throws an exception if the [FileSystemEntity] cannot be deleted. + */ + void deleteSync({bool recursive: false}) => _deleteSync(recursive: recursive); + + /** + * Start watching the [FileSystemEntity] for changes. + * + * The implementation uses platform-dependent event-based APIs for receiving + * file-system notifications, thus behavior depends on the platform. + * + * * `Windows`: Uses `ReadDirectoryChangesW`. The implementation only + * supports watching directories. Recursive watching is supported. + * * `Linux`: Uses `inotify`. The implementation supports watching both + * files and directories. Recursive watching is not supported. + * Note: When watching files directly, delete events might not happen + * as expected. + * * `OS X`: Uses `FSEvents`. The implementation supports watching both + * files and directories. Recursive watching is supported. + * + * The system will start listening for events once the returned [Stream] is + * being listened to, not when the call to [watch] is issued. + * + * The returned value is an endless broadcast [Stream], that only stops when + * one of the following happens: + * + * * The [Stream] is canceled, e.g. by calling `cancel` on the + * [StreamSubscription]. + * * The [FileSystemEntity] being watches, is deleted. + * + * Use `events` to specify what events to listen for. The constants in + * [FileSystemEvent] can be or'ed together to mix events. Default is + * [FileSystemEvent.ALL]. + * + * A move event may be reported as seperate delete and create events. + */ + Stream watch( + {int events: FileSystemEvent.all, bool recursive: false}) { + // FIXME(bkonyi): find a way to do this using the raw path. + final String trimmedPath = _trimTrailingPathSeparators(path); + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _FileSystemWatcher._watch(trimmedPath, events, recursive); + } + return overrides.fsWatch(trimmedPath, events, recursive); + } + + Future _delete({bool recursive: false}); + void _deleteSync({bool recursive: false}); + + static Future _identical(String path1, String path2) { + return _File._dispatchWithNamespace( + _IOService.fileIdentical, [null, path1, path2]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, + "Error in FileSystemEntity.identical($path1, $path2)", ""); + } + return response; + }); + } + + /** + * Checks whether two paths refer to the same object in the + * file system. + * + * Returns a [:Future:] that completes with the result. + * + * Comparing a link to its target returns false, as does comparing two links + * that point to the same target. To check the target of a link, use + * Link.target explicitly to fetch it. Directory links appearing + * inside a path are followed, though, to find the file system object. + * + * Completes the returned Future with an error if one of the paths points + * to an object that does not exist. + */ + static Future identical(String path1, String path2) { + IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _identical(path1, path2); + } + return overrides.fseIdentical(path1, path2); + } + + static final RegExp _absoluteWindowsPathPattern = + new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])'); + + /** + * Returns a [bool] indicating whether this object's path is absolute. + * + * On Windows, a path is absolute if it starts with \\\\ or a drive letter + * between a and z (upper or lower case) followed by :\\ or :/. + * On non-Windows, a path is absolute if it starts with /. + */ + bool get isAbsolute { + if (Platform.isWindows) { + return path.startsWith(_absoluteWindowsPathPattern); + } else { + return path.startsWith('/'); + } + } + + /** + * Returns a [FileSystemEntity] whose path is the absolute path to [this]. + * + * The type of the returned instance is the type of [this]. + * + * The absolute path is computed by prefixing + * a relative path with the current working directory, and returning + * an absolute path unchanged. + */ + FileSystemEntity get absolute; + + String get _absolutePath { + if (isAbsolute) return path; + String current = Directory.current.path; + if (current.endsWith('/') || + (Platform.isWindows && current.endsWith('\\'))) { + return '$current$path'; + } else { + return '$current${Platform.pathSeparator}$path'; + } + } + + Uint8List get _rawAbsolutePath { + if (isAbsolute) return _rawPath; + var current = Directory.current._rawPath.toList(); + assert(current.last == 0); + current.removeLast(); // Remove null terminator. + if ((current.last == '/'.codeUnitAt(0)) || + (Platform.isWindows && (current.last == '\\'.codeUnitAt(0)))) { + current.addAll(_rawPath); + return new Uint8List.fromList(current); + } else { + current.addAll(utf8.encode(Platform.pathSeparator)); + current.addAll(_rawPath); + return new Uint8List.fromList(current); + } + } + + static bool _identicalSync(String path1, String path2) { + var result = _identicalNative(_Namespace._namespace, path1, path2); + _throwIfError(result, 'Error in FileSystemEntity.identicalSync'); + return result; + } + + /** + * Synchronously checks whether two paths refer to the same object in the + * file system. + * + * Comparing a link to its target returns false, as does comparing two links + * that point to the same target. To check the target of a link, use + * Link.target explicitly to fetch it. Directory links appearing + * inside a path are followed, though, to find the file system object. + * + * Throws an error if one of the paths points to an object that does not + * exist. + */ + static bool identicalSync(String path1, String path2) { + IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _identicalSync(path1, path2); + } + return overrides.fseIdenticalSync(path1, path2); + } + + /** + * Test if [watch] is supported on the current system. + * + * OS X 10.6 and below is not supported. + */ + static bool get isWatchSupported { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _FileSystemWatcher.isSupported; + } + return overrides.fsWatchIsSupported(); + } + + // The native methods which determine type of the FileSystemEntity require + // that the buffer provided is null terminated. + static Uint8List _toUtf8Array(String s) => + _toNullTerminatedUtf8Array(utf8.encode(s)); + + static Uint8List _toNullTerminatedUtf8Array(Uint8List l) { + if (l == null) { + return null; + } + if (l.isNotEmpty && l.last != 0) { + final tmp = new Uint8List(l.length + 1); + tmp.setRange(0, l.length, l); + return tmp; + } else { + return l; + } + } + + static String _toStringFromUtf8Array(Uint8List l) { + if (l == null) { + return ''; + } + Uint8List nonNullTerminated = l; + if (l.last == 0) { + nonNullTerminated = new Uint8List.view(l.buffer, 0, l.length - 1); + } + return utf8.decode(nonNullTerminated, allowMalformed: true); + } + + /** + * Finds the type of file system object that a path points to. + * + * Returns a [:Future:] that completes with the result. + * + * [FileSystemEntityType] has the constant instances file, directory, + * link, and notFound. [type] will return link only if the optional + * named argument [followLinks] is false, and [path] points to a link. + * If the path does not point to a file system object, or any other error + * occurs in looking up the path, notFound is returned. The only + * error or exception that may be put on the returned future is ArgumentError, + * caused by passing the wrong type of arguments to the function. + */ + static Future type(String path, + {bool followLinks: true}) { + return _getType(_toUtf8Array(path), followLinks); + } + + /** + * Synchronously finds the type of file system object that a path points to. + * + * Returns a [FileSystemEntityType]. + * + * [FileSystemEntityType] has the constant instances file, directory, + * link, and notFound. [type] will return link only if the optional + * named argument [followLinks] is false, and [path] points to a link. + * If the path does not point to a file system object, or any other error + * occurs in looking up the path, notFound is returned. The only + * error or exception that may be thrown is ArgumentError, + * caused by passing the wrong type of arguments to the function. + */ + static FileSystemEntityType typeSync(String path, {bool followLinks: true}) { + return _getTypeSync(_toUtf8Array(path), followLinks); + } + + /** + * Checks if type(path, followLinks: false) returns FileSystemEntityType.link. + */ + static Future isLink(String path) => _isLinkRaw(_toUtf8Array(path)); + + static Future _isLinkRaw(Uint8List rawPath) => _getType(rawPath, false) + .then((type) => (type == FileSystemEntityType.link)); + + /** + * Checks if type(path) returns FileSystemEntityType.file. + */ + static Future isFile(String path) => _getType(_toUtf8Array(path), true) + .then((type) => (type == FileSystemEntityType.file)); + + /** + * Checks if type(path) returns FileSystemEntityType.directory. + */ + static Future isDirectory(String path) => + _getType(_toUtf8Array(path), true) + .then((type) => (type == FileSystemEntityType.directory)); + + /** + * Synchronously checks if typeSync(path, followLinks: false) returns + * FileSystemEntityType.link. + */ + static bool isLinkSync(String path) => _isLinkRawSync(_toUtf8Array(path)); + + static bool _isLinkRawSync(rawPath) => + (_getTypeSync(rawPath, false) == FileSystemEntityType.link); + + /** + * Synchronously checks if typeSync(path) returns + * FileSystemEntityType.file. + */ + static bool isFileSync(String path) => + (_getTypeSync(_toUtf8Array(path), true) == FileSystemEntityType.file); + + /** + * Synchronously checks if typeSync(path) returns + * FileSystemEntityType.directory. + */ + static bool isDirectorySync(String path) => + (_getTypeSync(_toUtf8Array(path), true) == + FileSystemEntityType.directory); + + external static _getTypeNative( + _Namespace namespace, Uint8List rawPath, bool followLinks); + external static _identicalNative( + _Namespace namespace, String path1, String path2); + external static _resolveSymbolicLinks(_Namespace namespace, Uint8List path); + + // Finds the next-to-last component when dividing at path separators. + static final RegExp _parentRegExp = Platform.isWindows + ? new RegExp(r'[^/\\][/\\]+[^/\\]') + : new RegExp(r'[^/]/+[^/]'); + + /** + * Removes the final path component of a path, using the platform's + * path separator to split the path. + * + * Will not remove the root component of a Windows path, like "C:\\" or + * "\\\\server_name\\". Ignores trailing path separators, and leaves no + * trailing path separators. + */ + static String parentOf(String path) { + int rootEnd = -1; + if (Platform.isWindows) { + if (path.startsWith(_absoluteWindowsPathPattern)) { + // Root ends at first / or \ after the first two characters. + rootEnd = path.indexOf(new RegExp(r'[/\\]'), 2); + if (rootEnd == -1) return path; + } else if (path.startsWith('\\') || path.startsWith('/')) { + rootEnd = 0; + } + } else if (path.startsWith('/')) { + rootEnd = 0; + } + // Ignore trailing slashes. + // All non-trivial cases have separators between two non-separators. + int pos = path.lastIndexOf(_parentRegExp); + if (pos > rootEnd) { + return path.substring(0, pos + 1); + } else if (rootEnd > -1) { + return path.substring(0, rootEnd + 1); + } else { + return '.'; + } + } + + /** + * The directory containing [this]. + */ + Directory get parent => new Directory(parentOf(path)); + + static FileSystemEntityType _getTypeSyncHelper( + Uint8List rawPath, bool followLinks) { + var result = _getTypeNative(_Namespace._namespace, rawPath, followLinks); + _throwIfError(result, 'Error getting type of FileSystemEntity'); + return FileSystemEntityType._lookup(result); + } + + static FileSystemEntityType _getTypeSync( + Uint8List rawPath, bool followLinks) { + IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _getTypeSyncHelper(rawPath, followLinks); + } + return overrides.fseGetTypeSync( + utf8.decode(rawPath, allowMalformed: true), followLinks); + } + + static Future _getTypeRequest( + Uint8List rawPath, bool followLinks) { + return _File._dispatchWithNamespace( + _IOService.fileType, [null, rawPath, followLinks]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "Error getting type", + utf8.decode(rawPath, allowMalformed: true)); + } + return FileSystemEntityType._lookup(response); + }); + } + + static Future _getType( + Uint8List rawPath, bool followLinks) { + IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return _getTypeRequest(rawPath, followLinks); + } + return overrides.fseGetType( + utf8.decode(rawPath, allowMalformed: true), followLinks); + } + + static _throwIfError(Object result, String msg, [String path]) { + if (result is OSError) { + throw new FileSystemException(msg, path, result); + } else if (result is ArgumentError) { + throw result; + } + } + + // TODO(bkonyi): find a way to do this with raw paths. + static String _trimTrailingPathSeparators(String path) { + // Don't handle argument errors here. + if (path is! String) return path; + if (Platform.isWindows) { + while (path.length > 1 && + (path.endsWith(Platform.pathSeparator) || path.endsWith('/'))) { + path = path.substring(0, path.length - 1); + } + } else { + while (path.length > 1 && path.endsWith(Platform.pathSeparator)) { + path = path.substring(0, path.length - 1); + } + } + return path; + } + + // TODO(bkonyi): find a way to do this with raw paths. + static String _ensureTrailingPathSeparators(String path) { + // Don't handle argument errors here. + if (path is! String) return path; + if (path.isEmpty) path = '.'; + if (Platform.isWindows) { + while (!path.endsWith(Platform.pathSeparator) && !path.endsWith('/')) { + path = "$path${Platform.pathSeparator}"; + } + } else { + while (!path.endsWith(Platform.pathSeparator)) { + path = "$path${Platform.pathSeparator}"; + } + } + return path; + } +} + +/** + * Base event class emitted by [FileSystemEntity.watch]. + */ +class FileSystemEvent { + /** + * Bitfield for [FileSystemEntity.watch], to enable [FileSystemCreateEvent]s. + */ + static const int create = 1 << 0; + @Deprecated("Use create instead") + static const int CREATE = 1 << 0; + + /** + * Bitfield for [FileSystemEntity.watch], to enable [FileSystemModifyEvent]s. + */ + static const int modify = 1 << 1; + @Deprecated("Use modify instead") + static const int MODIFY = 1 << 1; + + /** + * Bitfield for [FileSystemEntity.watch], to enable [FileSystemDeleteEvent]s. + */ + static const int delete = 1 << 2; + @Deprecated("Use delete instead") + static const int DELETE = 1 << 2; + + /** + * Bitfield for [FileSystemEntity.watch], to enable [FileSystemMoveEvent]s. + */ + static const int move = 1 << 3; + @Deprecated("Use move instead") + static const int MOVE = 1 << 3; + + /** + * Bitfield for [FileSystemEntity.watch], for enabling all of [create], + * [modify], [delete] and [move]. + */ + static const int all = create | modify | delete | move; + @Deprecated("Use all instead") + static const int ALL = create | modify | delete | move; + + static const int _modifyAttributes = 1 << 4; + static const int _deleteSelf = 1 << 5; + static const int _isDir = 1 << 6; + + /** + * The type of event. See [FileSystemEvent] for a list of events. + */ + final int type; + + /** + * The path that triggered the event. + * + * Depending on the platform and the FileSystemEntity, the path may be + * relative. + */ + final String path; + + /** + * Is `true` if the event target was a directory. + * + * Note that if the file has been deleted by the time the event has arrived, + * this will always be `false` on Windows. In particular, it will always be + * `false` for `delete` events. + */ + final bool isDirectory; + + FileSystemEvent._(this.type, this.path, this.isDirectory); +} + +/** + * File system event for newly created file system objects. + */ +class FileSystemCreateEvent extends FileSystemEvent { + FileSystemCreateEvent._(path, isDirectory) + : super._(FileSystemEvent.create, path, isDirectory); + + String toString() => "FileSystemCreateEvent('$path')"; +} + +/** + * File system event for modifications of file system objects. + */ +class FileSystemModifyEvent extends FileSystemEvent { + /** + * If the content was changed and not only the attributes, [contentChanged] + * is `true`. + */ + final bool contentChanged; + + FileSystemModifyEvent._(path, isDirectory, this.contentChanged) + : super._(FileSystemEvent.modify, path, isDirectory); + + String toString() => + "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; +} + +/** + * File system event for deletion of file system objects. + */ +class FileSystemDeleteEvent extends FileSystemEvent { + FileSystemDeleteEvent._(path, isDirectory) + : super._(FileSystemEvent.delete, path, isDirectory); + + String toString() => "FileSystemDeleteEvent('$path')"; +} + +/** + * File system event for moving of file system objects. + */ +class FileSystemMoveEvent extends FileSystemEvent { + /** + * If the underlying implementation is able to identify the destination of + * the moved file, [destination] will be set. Otherwise, it will be `null`. + */ + final String destination; + + FileSystemMoveEvent._(path, isDirectory, this.destination) + : super._(FileSystemEvent.move, path, isDirectory); + + String toString() { + var buffer = new StringBuffer(); + buffer.write("FileSystemMoveEvent('$path'"); + if (destination != null) buffer.write(", '$destination'"); + buffer.write(')'); + return buffer.toString(); + } +} + +class _FileSystemWatcher { + external static Stream _watch( + String path, int events, bool recursive); + external static bool get isSupported; +} +NN<Q<"?"D'&?"C&%#$#4DOPI34!""?L CHHC8O#)M,)L%.@=IFA*7&%32A74#EFF3LJQM.7!/2AQ(#C%GHH58NPNO$P;;= --'GBA2@B%K+GP'(< XQMkQRL"EJ3%J8G>FFGCBH G>FEAGB&@ENLK34CNL;/? P?HGL<OL2OM Q%A P*)Q(&>? PCHGL@OL2OQ Q%CP&IBH0K FA2G(4IFA2&LIHN!PMQEM@>%4LIHN!PMPFQ8OGJILELLAN@O#C ;IGH!B@B7H>=-?)J(/H>@OHDIL'>1'14-IMB=; #M>0G!!!-!: 7#%75/H . ; .;HFLOHDIK :1+59+%7-+M2-2='/$ 6%IAAPHGILDQD8"6O'HGILD=DP:QMP<=P<B2)EH M)C4 )M4%.1+"B$9OH9*#F'JJ(:E9(B' I/)- &92-NE1,-17%B7-)M(E950-14!BC8*9;*& K3 I39=*&"N1 719P$$$P$$$P$$$N"""J$:!:/)$D(I4ON"=<6-<9?6NB<H:6-<984MN=:%1?20(Tfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/io_resource_info.dart// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +abstract class _IOResourceInfo { + final String type; + final int id; + String get name; + static int _count = 0; + + static final Stopwatch _sw = new Stopwatch()..start(); + static final _startTime = new DateTime.now().millisecondsSinceEpoch; + + static double get timestamp => _startTime + _sw.elapsedMicroseconds / 1000; + + _IOResourceInfo(this.type) : id = _IOResourceInfo.getNextID(); + + /// Get the full set of values for a specific implementation. This is normally + /// looked up based on an id from a referenceValueMap. + Map get fullValueMap; + + /// The reference map, used to return a list of values, e.g., getting + /// all open sockets. The structure of this is shared among all subclasses. + Map get referenceValueMap => { + // The type for a reference object is prefixed with @ in observatory. + 'type': '@$type', + 'id': id, + 'name': name, + }; + + static int getNextID() => _count++; +} + +abstract class _ReadWriteResourceInfo extends _IOResourceInfo { + int totalRead; + int totalWritten; + int readCount; + int writeCount; + double lastRead; + double lastWrite; + + // Not all call sites use this. In some cases, e.g., a socket, a read does + // not always mean that we actually read some bytes (we may do a read to see + // if there are some bytes available). + void addRead(int bytes) { + totalRead += bytes; + readCount++; + lastRead = _IOResourceInfo.timestamp; + } + + // In cases where we read but did not necessarily get any bytes, use this to + // update the readCount and timestamp. Manually update totalRead if any bytes + // where actually read. + void didRead() { + addRead(0); + } + + void addWrite(int bytes) { + totalWritten += bytes; + writeCount++; + lastWrite = _IOResourceInfo.timestamp; + } + + _ReadWriteResourceInfo(String type) + : totalRead = 0, + totalWritten = 0, + readCount = 0, + writeCount = 0, + lastRead = 0.0, + lastWrite = 0.0, + super(type); + + Map get fullValueMap => { + 'type': type, + 'id': id, + 'name': name, + 'totalRead': totalRead, + 'totalWritten': totalWritten, + 'readCount': readCount, + 'writeCount': writeCount, + 'lastRead': lastRead, + 'lastWrite': lastWrite + }; +} + +class _FileResourceInfo extends _ReadWriteResourceInfo { + static const String _type = '_file'; + + final file; + + static Map openFiles = + new Map(); + + _FileResourceInfo(this.file) : super(_type) { + FileOpened(this); + } + + static FileOpened(_FileResourceInfo info) { + assert(!openFiles.containsKey(info.id)); + openFiles[info.id] = info; + } + + static FileClosed(_FileResourceInfo info) { + assert(openFiles.containsKey(info.id)); + openFiles.remove(info.id); + } + + static Iterable> getOpenFilesList() { + return new List.from(openFiles.values.map((e) => e.referenceValueMap)); + } + + static Future getOpenFiles(function, params) { + assert(function == 'ext.dart.io.getOpenFiles'); + var data = {'type': '_openfiles', 'data': getOpenFilesList()}; + var jsonValue = json.encode(data); + return new Future.value(new ServiceExtensionResponse.result(jsonValue)); + } + + Map getFileInfoMap() { + return fullValueMap; + } + + static Future getFileInfoMapByID(function, params) { + assert(params.containsKey('id')); + var id = int.parse(params['id']); + var result = + openFiles.containsKey(id) ? openFiles[id].getFileInfoMap() : {}; + var jsonValue = json.encode(result); + return new Future.value(new ServiceExtensionResponse.result(jsonValue)); + } + + String get name { + return '${file.path}'; + } +} + +class _ProcessResourceInfo extends _IOResourceInfo { + static const String _type = '_process'; + final process; + final double startedAt; + + static Map startedProcesses = + new Map(); + + _ProcessResourceInfo(this.process) + : startedAt = _IOResourceInfo.timestamp, + super(_type) { + ProcessStarted(this); + } + + String get name => process._path; + + void stopped() { + ProcessStopped(this); + } + + Map get fullValueMap => { + 'type': type, + 'id': id, + 'name': name, + 'pid': process.pid, + 'startedAt': startedAt, + 'arguments': process._arguments, + 'workingDirectory': + process._workingDirectory == null ? '.' : process._workingDirectory, + }; + + static ProcessStarted(_ProcessResourceInfo info) { + assert(!startedProcesses.containsKey(info.id)); + startedProcesses[info.id] = info; + } + + static ProcessStopped(_ProcessResourceInfo info) { + assert(startedProcesses.containsKey(info.id)); + startedProcesses.remove(info.id); + } + + static Iterable> getStartedProcessesList() => + new List.from(startedProcesses.values.map((e) => e.referenceValueMap)); + + static Future getStartedProcesses( + String function, Map params) { + assert(function == 'ext.dart.io.getProcesses'); + var data = {'type': '_startedprocesses', 'data': getStartedProcessesList()}; + var jsonValue = json.encode(data); + return new Future.value(new ServiceExtensionResponse.result(jsonValue)); + } + + static Future getProcessInfoMapById( + String function, Map params) { + var id = int.parse(params['id']); + var result = startedProcesses.containsKey(id) + ? startedProcesses[id].fullValueMap + : {}; + var jsonValue = json.encode(result); + return new Future.value(new ServiceExtensionResponse.result(jsonValue)); + } +} + +class _SocketResourceInfo extends _ReadWriteResourceInfo { + static const String _tcpString = 'TCP'; + static const String _udpString = 'UDP'; + static const String _type = '_socket'; + + final /*_NativeSocket|*/ socket; + + static Map openSockets = + new Map(); + + _SocketResourceInfo(this.socket) : super(_type) { + SocketOpened(this); + } + + String get name { + if (socket.isListening) { + return 'listening:${socket.address.host}:${socket.port}'; + } + var remote = ''; + try { + var remoteHost = socket.remoteAddress.host; + var remotePort = socket.remotePort; + remote = ' -> $remoteHost:$remotePort'; + } catch (e) {} // ignored if we can't get the information + return '${socket.address.host}:${socket.port}$remote'; + } + + static Iterable> getOpenSocketsList() { + return new List.from(openSockets.values.map((e) => e.referenceValueMap)); + } + + Map getSocketInfoMap() { + var result = fullValueMap; + result['socketType'] = socket.isTcp ? _tcpString : _udpString; + result['listening'] = socket.isListening; + result['host'] = socket.address.host; + result['port'] = socket.port; + if (!socket.isListening) { + try { + result['remoteHost'] = socket.remoteAddress.host; + result['remotePort'] = socket.remotePort; + } catch (e) { + // UDP. + result['remotePort'] = 'NA'; + result['remoteHost'] = 'NA'; + } + } else { + result['remotePort'] = 'NA'; + result['remoteHost'] = 'NA'; + } + result['addressType'] = socket.address.type.name; + return result; + } + + static Future getSocketInfoMapByID( + String function, Map params) { + assert(params.containsKey('id')); + var id = int.parse(params['id']); + var result = + openSockets.containsKey(id) ? openSockets[id].getSocketInfoMap() : {}; + var jsonValue = json.encode(result); + return new Future.value(new ServiceExtensionResponse.result(jsonValue)); + } + + static Future getOpenSockets(function, params) { + assert(function == 'ext.dart.io.getOpenSockets'); + var data = {'type': '_opensockets', 'data': getOpenSocketsList()}; + var jsonValue = json.encode(data); + return new Future.value(new ServiceExtensionResponse.result(jsonValue)); + } + + static SocketOpened(_SocketResourceInfo info) { + assert(!openSockets.containsKey(info.id)); + openSockets[info.id] = info; + } + + static SocketClosed(_SocketResourceInfo info) { + assert(openSockets.containsKey(info.id)); + openSockets.remove(info.id); + } +} +NN<!9GNAQ9)HN2N &@MO)*OP+&- & " 9'1)0.-.,=LK4C'M*Q&&I)M5*;,%/$- )Q 54&53&EN?54Q'MA5&2,)M;**)#5+4@ +2*.>;?N,C.*" :2%% ##6@5&&O)MM6G'M2/!2.!Kfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/io_sink.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * A combined byte and text output. + * + * An [IOSink] combines a [StreamSink] of bytes with a [StringSink], + * and allows easy output of both bytes and text. + * + * Writing text ([write]) and adding bytes ([add]) may be interleaved freely. + * + * While a stream is being added using [addStream], any further attempts + * to add or write to the [IOSink] will fail until the [addStream] completes. + * + * It is an error to add data to the [IOSink] after the sink is closed. + */ +abstract class IOSink implements StreamSink>, StringSink { + /** + * Create an [IOSink] that outputs to a [target] [StreamConsumer] of bytes. + * + * Text written to [StreamSink] methods is encoded to bytes using [encoding] + * before being output on [target]. + */ + factory IOSink(StreamConsumer> target, {Encoding encoding: utf8}) => + new _IOSinkImpl(target, encoding); + + /** + * The [Encoding] used when writing strings. Depending on the + * underlying consumer this property might be mutable. + */ + Encoding encoding; + + /** + * Adds byte [data] to the target consumer, ignoring [encoding]. + * + * The [encoding] does not apply to this method, and the `data` list is passed + * directly to the target consumer as a stream event. + * + * This function must not be called when a stream is currently being added + * using [addStream]. + * + * This operation is non-blocking. See [flush] or [done] for how to get any + * errors generated by this call. + * + * The data list should not be modified after it has been passed to `add`. + */ + void add(List data); + + /** + * Converts [obj] to a String by invoking [Object.toString] and + * [add]s the encoding of the result to the target consumer. + * + * This operation is non-blocking. See [flush] or [done] for how to get any + * errors generated by this call. + */ + void write(Object obj); + + /** + * Iterates over the given [objects] and [write]s them in sequence. + * + * If [separator] is provided, a `write` with the `separator` is performed + * between any two elements of objects`. + * + * This operation is non-blocking. See [flush] or [done] for how to get any + * errors generated by this call. + */ + void writeAll(Iterable objects, [String separator = ""]); + + /** + * Converts [obj] to a String by invoking [Object.toString] and + * writes the result to `this`, followed by a newline. + * + * This operation is non-blocking. See [flush] or [done] for how to get any + * errors generated by this call. + */ + void writeln([Object obj = ""]); + + /** + * Writes the character of [charCode]. + * + * This method is equivalent to `write(new String.fromCharCode(charCode))`. + * + * This operation is non-blocking. See [flush] or [done] for how to get any + * errors generated by this call. + */ + void writeCharCode(int charCode); + + /** + * Passes the error to the target consumer as an error event. + * + * This function must not be called when a stream is currently being added + * using [addStream]. + * + * This operation is non-blocking. See [flush] or [done] for how to get any + * errors generated by this call. + */ + void addError(error, [StackTrace stackTrace]); + + /** + * Adds all elements of the given [stream] to `this`. + * + * Returns a [Future] that completes when + * all elements of the given [stream] are added to `this`. + */ + Future addStream(Stream> stream); + + /** + * Returns a [Future] that completes once all buffered data is accepted by the + * underlying [StreamConsumer]. + * + * This method must not be called while an [addStream] is incomplete. + * + * NOTE: This is not necessarily the same as the data being flushed by the + * operating system. + */ + Future flush(); + + /** + * Close the target consumer. + * + * NOTE: Writes to the [IOSink] may be buffered, and may not be flushed by + * a call to `close()`. To flush all buffered writes, call `flush()` before + * calling `close()`. + */ + Future close(); + + /** + * Get a future that will complete when the consumer closes, or when an + * error occurs. This future is identical to the future returned by + * [close]. + */ + Future get done; +} + +class _StreamSinkImpl implements StreamSink { + final StreamConsumer _target; + final Completer _doneCompleter = new Completer(); + StreamController _controllerInstance; + Completer _controllerCompleter; + bool _isClosed = false; + bool _isBound = false; + bool _hasError = false; + + _StreamSinkImpl(this._target); + + void _reportClosedSink() { + // TODO(29554): this is very brittle and depends on the layout of the + // stderr class. + if (this == stderr._sink) { + // We can't report on stderr anymore (as we would otherwise + // have an infinite recursion. + throw new StateError("Stderr is closed."); + } + // TODO(29554): throw a StateError, and don't just report the problem. + stderr.writeln("StreamSink is closed and adding to it is an error."); + stderr.writeln(" See http://dartbug.com/29554."); + stderr.writeln(StackTrace.current); + } + + void add(T data) { + if (_isClosed) { + _reportClosedSink(); + return; + } + _controller.add(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_isClosed) { + _reportClosedSink(); + return; + } + _controller.addError(error, stackTrace); + } + + Future addStream(Stream stream) { + if (_isBound) { + throw new StateError("StreamSink is already bound to a stream"); + } + if (_hasError) return done; + + _isBound = true; + var future = _controllerCompleter == null + ? _target.addStream(stream) + : _controllerCompleter.future.then((_) => _target.addStream(stream)); + _controllerInstance?.close(); + + // Wait for any pending events in [_controller] to be dispatched before + // adding [stream]. + return future.whenComplete(() { + _isBound = false; + }); + } + + Future flush() { + if (_isBound) { + throw new StateError("StreamSink is bound to a stream"); + } + if (_controllerInstance == null) return new Future.value(this); + // Adding an empty stream-controller will return a future that will complete + // when all data is done. + _isBound = true; + var future = _controllerCompleter.future; + _controllerInstance.close(); + return future.whenComplete(() { + _isBound = false; + }); + } + + Future close() { + if (_isBound) { + throw new StateError("StreamSink is bound to a stream"); + } + if (!_isClosed) { + _isClosed = true; + if (_controllerInstance != null) { + _controllerInstance.close(); + } else { + _closeTarget(); + } + } + return done; + } + + void _closeTarget() { + _target.close().then(_completeDoneValue, onError: _completeDoneError); + } + + Future get done => _doneCompleter.future; + + void _completeDoneValue(value) { + if (!_doneCompleter.isCompleted) { + _doneCompleter.complete(value); + } + } + + void _completeDoneError(error, StackTrace stackTrace) { + if (!_doneCompleter.isCompleted) { + _hasError = true; + _doneCompleter.completeError(error, stackTrace); + } + } + + StreamController get _controller { + if (_isBound) { + throw new StateError("StreamSink is bound to a stream"); + } + if (_isClosed) { + throw new StateError("StreamSink is closed"); + } + if (_controllerInstance == null) { + _controllerInstance = new StreamController(sync: true); + _controllerCompleter = new Completer(); + _target.addStream(_controller.stream).then((_) { + if (_isBound) { + // A new stream takes over - forward values to that stream. + _controllerCompleter.complete(this); + _controllerCompleter = null; + _controllerInstance = null; + } else { + // No new stream, .close was called. Close _target. + _closeTarget(); + } + }, onError: (error, stackTrace) { + if (_isBound) { + // A new stream takes over - forward errors to that stream. + _controllerCompleter.completeError(error, stackTrace); + _controllerCompleter = null; + _controllerInstance = null; + } else { + // No new stream. No need to close target, as it has already + // failed. + _completeDoneError(error, stackTrace); + } + }); + } + return _controllerInstance; + } +} + +class _IOSinkImpl extends _StreamSinkImpl> implements IOSink { + Encoding _encoding; + bool _encodingMutable = true; + + _IOSinkImpl(StreamConsumer> target, this._encoding) : super(target); + + Encoding get encoding => _encoding; + + void set encoding(Encoding value) { + if (!_encodingMutable) { + throw new StateError("IOSink encoding is not mutable"); + } + _encoding = value; + } + + void write(Object obj) { + String string = '$obj'; + if (string.isEmpty) return; + add(_encoding.encode(string)); + } + + void writeAll(Iterable objects, [String separator = ""]) { + Iterator iterator = objects.iterator; + if (!iterator.moveNext()) return; + if (separator.isEmpty) { + do { + write(iterator.current); + } while (iterator.moveNext()); + } else { + write(iterator.current); + while (iterator.moveNext()) { + write(separator); + write(iterator.current); + } + } + } + + void writeln([Object object = ""]) { + write(object); + write("\n"); + } + + void writeCharCode(int charCode) { + write(new String.fromCharCode(charCode)); + } +} +KNN<$E2NINHENO&Q)@9CQ8MN$MB?N$FM+N$<B9N$#)NN$$@MN$18,=.Q"HM MNJF4#4+"!J B%1KJ7(2-'G .$N"L$?DQ.!$?)%K,#'&:'7(?4'A.7F/'&> +(FA'&G1 + + I Q&&> #=*& !% $!'%.Nfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/io_service.dart'// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +class _IOService { + // This list must be kept in sync with the list in runtime/bin/io_service.h + static const int fileExists = 0; + static const int fileCreate = 1; + static const int fileDelete = 2; + static const int fileRename = 3; + static const int fileCopy = 4; + static const int fileOpen = 5; + static const int fileResolveSymbolicLinks = 6; + static const int fileClose = 7; + static const int filePosition = 8; + static const int fileSetPosition = 9; + static const int fileTruncate = 10; + static const int fileLength = 11; + static const int fileLengthFromPath = 12; + static const int fileLastAccessed = 13; + static const int fileSetLastAccessed = 14; + static const int fileLastModified = 15; + static const int fileSetLastModified = 16; + static const int fileFlush = 17; + static const int fileReadByte = 18; + static const int fileWriteByte = 19; + static const int fileRead = 20; + static const int fileReadInto = 21; + static const int fileWriteFrom = 22; + static const int fileCreateLink = 23; + static const int fileDeleteLink = 24; + static const int fileRenameLink = 25; + static const int fileLinkTarget = 26; + static const int fileType = 27; + static const int fileIdentical = 28; + static const int fileStat = 29; + static const int fileLock = 30; + static const int socketLookup = 31; + static const int socketListInterfaces = 32; + static const int socketReverseLookup = 33; + static const int directoryCreate = 34; + static const int directoryDelete = 35; + static const int directoryExists = 36; + static const int directoryCreateTemp = 37; + static const int directoryListStart = 38; + static const int directoryListNext = 39; + static const int directoryListStop = 40; + static const int directoryRename = 41; + static const int sslProcessFilter = 42; + + external static Future _dispatch(int request, List data); +} +8NN<N####!!1"%(&$,*-*-#&'"&'(((("'""&.-)))-,++)*<Hfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/link.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * [Link] objects are references to filesystem links. + * + */ +abstract class Link implements FileSystemEntity { + /** + * Creates a Link object. + */ + factory Link(String path) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return new _Link(path); + } + return overrides.createLink(path); + } + + factory Link.fromRawPath(Uint8List rawPath) { + // TODO(bkonyi): handle overrides + return new _Link.fromRawPath(rawPath); + } + + /** + * Creates a [Link] object. + * + * If [path] is a relative path, it will be interpreted relative to the + * current working directory (see [Directory.current]), when used. + * + * If [path] is an absolute path, it will be immune to changes to the + * current working directory. + */ + factory Link.fromUri(Uri uri) => new Link(uri.toFilePath()); + + /** + * Creates a symbolic link. Returns a [:Future:] that completes with + * the link when it has been created. If the link exists, + * the future will complete with an error. + * + * If [recursive] is false, the default, the link is created + * only if all directories in its path exist. + * If [recursive] is true, all non-existing path + * components are created. The directories in the path of [target] are + * not affected, unless they are also in [path]. + * + * On the Windows platform, this will only work with directories, and the + * target directory must exist. The link will be created as a Junction. + * Only absolute links will be created, and relative paths to the target + * will be converted to absolute paths by joining them with the path of the + * directory the link is contained in. + * + * On other platforms, the posix symlink() call is used to make a symbolic + * link containing the string [target]. If [target] is a relative path, + * it will be interpreted relative to the directory containing the link. + */ + Future create(String target, {bool recursive: false}); + + /** + * Synchronously create the link. Calling [createSync] on an existing link + * will throw an exception. + * + * If [recursive] is false, the default, the link is created only if all + * directories in its path exist. If [recursive] is true, all + * non-existing path components are created. The directories in + * the path of [target] are not affected, unless they are also in [path]. + * + * On the Windows platform, this will only work with directories, and the + * target directory must exist. The link will be created as a Junction. + * Only absolute links will be created, and relative paths to the target + * will be converted to absolute paths. + * + * On other platforms, the posix symlink() call is used to make a symbolic + * link containing the string [target]. If [target] is a relative path, + * it will be interpreted relative to the directory containing the link. + */ + void createSync(String target, {bool recursive: false}); + + /** + * Synchronously updates the link. Calling [updateSync] on a non-existing link + * will throw an exception. + * + * On the Windows platform, this will only work with directories, and the + * target directory must exist. + */ + void updateSync(String target); + + /** + * Updates the link. Returns a [:Future:] that completes with the + * link when it has been updated. Calling [update] on a non-existing link + * will complete its returned future with an exception. + * + * On the Windows platform, this will only work with directories, and the + * target directory must exist. + */ + Future update(String target); + + Future resolveSymbolicLinks(); + + String resolveSymbolicLinksSync(); + + /** + * Renames this link. Returns a `Future` that completes + * with a [Link] instance for the renamed link. + * + * If [newPath] identifies an existing link, that link is + * replaced. If [newPath] identifies an existing file or directory, + * the operation fails and the future completes with an exception. + */ + Future rename(String newPath); + + /** + * Synchronously renames this link. Returns a [Link] + * instance for the renamed link. + * + * If [newPath] identifies an existing link, that link is + * replaced. If [newPath] identifies an existing file or directory + * the operation fails and an exception is thrown. + */ + Link renameSync(String newPath); + + /** + * Returns a [Link] instance whose path is the absolute path to [this]. + * + * The absolute path is computed by prefixing + * a relative path with the current working directory, and returning + * an absolute path unchanged. + */ + Link get absolute; + + /** + * Gets the target of the link. Returns a future that completes with + * the path to the target. + * + * If the returned target is a relative path, it is relative to the + * directory containing the link. + * + * If the link does not exist, or is not a link, the future completes with + * a FileSystemException. + */ + Future target(); + + /** + * Synchronously gets the target of the link. Returns the path to the target. + * + * If the returned target is a relative path, it is relative to the + * directory containing the link. + * + * If the link does not exist, or is not a link, throws a FileSystemException. + */ + String targetSync(); +} + +class _Link extends FileSystemEntity implements Link { + String _path; + Uint8List _rawPath; + + _Link(String path) { + if (path is! String) { + throw new ArgumentError('${Error.safeToString(path)} ' + 'is not a String'); + } + _path = path; + _rawPath = FileSystemEntity._toUtf8Array(path); + } + + _Link.fromRawPath(Uint8List rawPath) { + _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(rawPath); + _path = FileSystemEntity._toStringFromUtf8Array(rawPath); + } + + String get path => _path; + + String toString() => "Link: '$path'"; + + Future exists() => FileSystemEntity._isLinkRaw(_rawPath); + + bool existsSync() => FileSystemEntity._isLinkRawSync(_rawPath); + + Link get absolute => new Link.fromRawPath(_rawAbsolutePath); + + Future create(String target, {bool recursive: false}) { + if (Platform.isWindows) { + target = _makeWindowsLinkTarget(target); + } + var result = + recursive ? parent.create(recursive: true) : new Future.value(null); + return result + .then((_) => _File._dispatchWithNamespace( + _IOService.fileCreateLink, [null, _rawPath, target])) + .then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot create link to target '$target'", path); + } + return this; + }); + } + + void createSync(String target, {bool recursive: false}) { + if (recursive) { + parent.createSync(recursive: true); + } + if (Platform.isWindows) { + target = _makeWindowsLinkTarget(target); + } + var result = _File._createLink(_Namespace._namespace, _rawPath, target); + throwIfError(result, "Cannot create link", path); + } + + // Put target into the form "\??\C:\my\target\dir". + String _makeWindowsLinkTarget(String target) { + Uri base = new Uri.file('${Directory.current.path}\\'); + Uri link = new Uri.file(path); + Uri destination = new Uri.file(target); + String result = base.resolveUri(link).resolveUri(destination).toFilePath(); + if (result.length > 3 && result[1] == ':' && result[2] == '\\') { + return '\\??\\$result'; + } else { + throw new FileSystemException( + 'Target $result of Link.create on Windows cannot be converted' + + ' to start with a drive letter. Unexpected error.'); + } + } + + void updateSync(String target) { + // TODO(12414): Replace with atomic update, where supported by platform. + // Atomically changing a link can be done by creating the new link, with + // a different name, and using the rename() posix call to move it to + // the old name atomically. + deleteSync(); + createSync(target); + } + + Future update(String target) { + // TODO(12414): Replace with atomic update, where supported by platform. + // Atomically changing a link can be done by creating the new link, with + // a different name, and using the rename() posix call to move it to + // the old name atomically. + return delete().then((_) => create(target)); + } + + Future _delete({bool recursive: false}) { + if (recursive) { + return new Directory.fromRawPath(_rawPath) + .delete(recursive: true) + .then((_) => this); + } + return _File._dispatchWithNamespace( + _IOService.fileDeleteLink, [null, _rawPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse(response, "Cannot delete link", path); + } + return this; + }); + } + + void _deleteSync({bool recursive: false}) { + if (recursive) { + return new Directory.fromRawPath(_rawPath).deleteSync(recursive: true); + } + var result = _File._deleteLinkNative(_Namespace._namespace, _rawPath); + throwIfError(result, "Cannot delete link", path); + } + + Future rename(String newPath) { + return _File._dispatchWithNamespace( + _IOService.fileRenameLink, [null, _rawPath, newPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot rename link to '$newPath'", path); + } + return new Link(newPath); + }); + } + + Link renameSync(String newPath) { + var result = _File._renameLink(_Namespace._namespace, _rawPath, newPath); + throwIfError(result, "Cannot rename link '$path' to '$newPath'"); + return new Link(newPath); + } + + Future target() { + return _File._dispatchWithNamespace( + _IOService.fileLinkTarget, [null, _rawPath]).then((response) { + if (_isErrorResponse(response)) { + throw _exceptionFromResponse( + response, "Cannot get target of link", path); + } + return response; + }); + } + + String targetSync() { + var result = _File._linkTarget(_Namespace._namespace, _rawPath); + throwIfError(result, "Cannot read link", path); + return result; + } + + static throwIfError(Object result, String msg, [String path = ""]) { + if (result is OSError) { + throw new FileSystemException(msg, path, result); + } + } + + bool _isErrorResponse(response) { + return response is List && response[0] != _successResponse; + } + + _exceptionFromResponse(response, String message, String path) { + assert(_isErrorResponse(response)); + switch (response[_errorResponseErrorType]) { + case _illegalArgumentResponse: + return new ArgumentError(); + case _osErrorResponse: + var err = new OSError(response[_osErrorResponseMessage], + response[_osErrorResponseErrorCode]); + return new FileSystemException(message, path, err); + default: + return new Exception("Unknown error"); + } + } +} +HNN<627'0&+JEH ?M<-?03I3LJKN)MKK?MK@BLLJK*MKK;QL""JM:L"&)%@2(BB?@/M3B(&G<*/M661<#,PF %KD#MMI 'MMI 721#)G(L.NK6()P(&A $NF)G(&:E4G8$@B(1%$A2</Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/namespace_impl.dartb// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +// Each Isolate may run in a different "namespace", which provides the scope in +// which file paths are resolved. +abstract class _Namespace { + // This getter does not increase the reference count on the underlying native + // object. It cannot be passed in a dispatch message to the IOService thread. + external static _Namespace get _namespace; + + // This getter does increase the reference count on the underlying native + // object. It must be passed in a dispatch message to the IOService thread. + external static int get _namespacePointer; + + // This sets up the Isolate's namespace. It should be set up by the embedder. + // If it is not set up by the embedder, relative paths will be resolved + // relative to the process's current working directory and absolute paths will + // be left relative to the file system root. + external static void _setupNamespace(var namespace); +} +NN<P"PP-LN-PJQ/7Mfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/overrides.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +final _ioOverridesToken = new Object(); + +const _asyncRunZoned = runZoned; + +/// This class facilitates overriding various APIs of dart:io with mock +/// implementations. +/// +/// This abstract base class should be extended with overrides for the +/// operations needed to construct mocks. The implementations in this base class +/// default to the actual dart:io implementation. For example: +/// +/// ``` +/// class MyDirectory implements Directory { +/// ... +/// // An implementation of the Directory interface +/// ... +/// } +/// +/// main() { +/// IOOverrides.runZoned(() { +/// ... +/// // Operations will use MyDirectory instead of dart:io's Directory +/// // implementation whenever Directory is used. +/// ... +/// }, createDirectory: (String path) => new MyDirectory(path)); +/// } +/// ``` +abstract class IOOverrides { + static IOOverrides _global; + + static IOOverrides get current { + return Zone.current[_ioOverridesToken] ?? _global; + } + + /// The [IOOverrides] to use in the root [Zone]. + /// + /// These are the [IOOverrides] that will be used in the root Zone, and in + /// Zone's that do not set [IOOverrides] and whose ancestors up to the root + /// Zone do not set [IOOverrides]. + static set global(IOOverrides overrides) { + _global = overrides; + } + + /// Runs [body] in a fresh [Zone] using the provided overrides. + /// + /// See the documentation on the corresponding methods of IOOverrides for + /// information about what the optional arguments do. + static R runZoned(R body(), + { + // Directory + Directory Function(String) createDirectory, + Directory Function() getCurrentDirectory, + void Function(String) setCurrentDirectory, + Directory Function() getSystemTempDirectory, + + // File + File Function(String) createFile, + + // FileStat + Future Function(String) stat, + FileStat Function(String) statSync, + + // FileSystemEntity + Future Function(String, String) fseIdentical, + bool Function(String, String) fseIdenticalSync, + Future Function(String, bool) fseGetType, + FileSystemEntityType Function(String, bool) fseGetTypeSync, + + // _FileSystemWatcher + Stream Function(String, int, bool) fsWatch, + bool Function() fsWatchIsSupported, + + // Link + Link Function(String) createLink, + + // Socket + Future Function(dynamic, int, + {dynamic sourceAddress, Duration timeout}) + socketConnect, + Future> Function(dynamic, int, + {dynamic sourceAddress}) + socketStartConnect, + + // Optional Zone parameters + ZoneSpecification zoneSpecification, + Function onError}) { + IOOverrides overrides = new _IOOverridesScope( + // Directory + createDirectory, + getCurrentDirectory, + setCurrentDirectory, + getSystemTempDirectory, + + // File + createFile, + + // FileStat + stat, + statSync, + + // FileSystemEntity + fseIdentical, + fseIdenticalSync, + fseGetType, + fseGetTypeSync, + + // _FileSystemWatcher + fsWatch, + fsWatchIsSupported, + + // Link + createLink, + + // Socket + socketConnect, + socketStartConnect, + ); + return _asyncRunZoned(body, + zoneValues: {_ioOverridesToken: overrides}, + zoneSpecification: zoneSpecification, + onError: onError); + } + + /// Runs [body] in a fresh [Zone] using the overrides found in [overrides]. + /// + /// Note that [overrides] should be an instance of a class that extends + /// [IOOverrides]. + static R runWithIOOverrides(R body(), IOOverrides overrides, + {ZoneSpecification zoneSpecification, Function onError}) { + return _asyncRunZoned(body, + zoneValues: {_ioOverridesToken: overrides}, + zoneSpecification: zoneSpecification, + onError: onError); + } + + // Directory + + /// Creates a new [Directory] object for the given [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// `new Directory()` and `new Directory.fromUri()`. + Directory createDirectory(String path) => new _Directory(path); + + /// Returns the current working directory. + /// + /// When this override is installed, this function overrides the behavior of + /// the static getter `Directory.current` + Directory getCurrentDirectory() => _Directory.current; + + /// Sets the current working directory to be [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// the setter `Directory.current`. + void setCurrentDirectory(String path) { + _Directory.current = path; + } + + /// Returns the system temporary directory. + /// + /// When this override is installed, this function overrides the behavior of + /// `Directory.systemTemp`. + Directory getSystemTempDirectory() => _Directory.systemTemp; + + // File + + /// Creates a new [File] object for the given [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// `new File()` and `new File.fromUri()`. + File createFile(String path) => new _File(path); + + // FileStat + + /// Asynchronously returns [FileStat] information for [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileStat.stat()`. + Future stat(String path) { + return FileStat._stat(path); + } + + /// Returns [FileStat] information for [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileStat.statSync()`. + FileStat statSync(String path) { + return FileStat._statSyncInternal(path); + } + + // FileSystemEntity + + /// Asynchronously returns `true` if [path1] and [path2] are paths to the + /// same file system object. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileSystemEntity.identical`. + Future fseIdentical(String path1, String path2) { + return FileSystemEntity._identical(path1, path2); + } + + /// Returns `true` if [path1] and [path2] are paths to the + /// same file system object. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileSystemEntity.identicalSync`. + bool fseIdenticalSync(String path1, String path2) { + return FileSystemEntity._identicalSync(path1, path2); + } + + /// Asynchronously returns the [FileSystemEntityType] for [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileSystemEntity.type`. + Future fseGetType(String path, bool followLinks) { + return FileSystemEntity._getTypeRequest(utf8.encode(path), followLinks); + } + + /// Returns the [FileSystemEntityType] for [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileSystemEntity.typeSync`. + FileSystemEntityType fseGetTypeSync(String path, bool followLinks) { + return FileSystemEntity._getTypeSyncHelper(utf8.encode(path), followLinks); + } + + // _FileSystemWatcher + + /// Returns a [Stream] of [FileSystemEvent]s. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileSystemEntity.watch()`. + Stream fsWatch(String path, int events, bool recursive) { + return _FileSystemWatcher._watch(path, events, recursive); + } + + /// Returns `true` when [FileSystemEntity.watch] is supported. + /// + /// When this override is installed, this function overrides the behavior of + /// `FileSystemEntity.isWatchSupported`. + bool fsWatchIsSupported() => _FileSystemWatcher.isSupported; + + // Link + + /// Returns a new [Link] object for the given [path]. + /// + /// When this override is installed, this function overrides the behavior of + /// `new Link()` and `new Link.fromUri()`. + Link createLink(String path) => new _Link(path); + + // Socket + + /// Asynchronously returns a [Socket] connected to the given host and port. + /// + /// When this override is installed, this functions overrides the behavior of + /// `Socket.connect(...)`. + Future socketConnect(host, int port, + {sourceAddress, Duration timeout}) { + return Socket._connect(host, port, + sourceAddress: sourceAddress, timeout: timeout); + } + + /// Asynchronously returns a [ConnectionTask] that connects to the given host + /// and port when successful. + /// + /// When this override is installed, this functions overrides the behavior of + /// `Socket.startConnect(...)`. + Future> socketStartConnect(host, int port, + {sourceAddress}) { + return Socket._startConnect(host, port, sourceAddress: sourceAddress); + } +} + +class _IOOverridesScope extends IOOverrides { + final IOOverrides _previous = IOOverrides.current; + + // Directory + Directory Function(String) _createDirectory; + Directory Function() _getCurrentDirectory; + void Function(String) _setCurrentDirectory; + Directory Function() _getSystemTempDirectory; + + // File + File Function(String) _createFile; + + // FileStat + Future Function(String) _stat; + FileStat Function(String) _statSync; + + // FileSystemEntity + Future Function(String, String) _fseIdentical; + bool Function(String, String) _fseIdenticalSync; + Future Function(String, bool) _fseGetType; + FileSystemEntityType Function(String, bool) _fseGetTypeSync; + + // _FileSystemWatcher + Stream Function(String, int, bool) _fsWatch; + bool Function() _fsWatchIsSupported; + + // Link + Link Function(String) _createLink; + + // Socket + Future Function(dynamic, int, + {dynamic sourceAddress, Duration timeout}) _socketConnect; + Future> Function(dynamic, int, {dynamic sourceAddress}) + _socketStartConnect; + + _IOOverridesScope( + // Directory + this._createDirectory, + this._getCurrentDirectory, + this._setCurrentDirectory, + this._getSystemTempDirectory, + + // File + this._createFile, + + // FileStat + this._stat, + this._statSync, + + // FileSystemEntity + this._fseIdentical, + this._fseIdenticalSync, + this._fseGetType, + this._fseGetTypeSync, + + // _FileSystemWatcher + this._fsWatch, + this._fsWatchIsSupported, + + // Link + this._createLink, + + // Socket + this._socketConnect, + this._socketStartConnect, + ); + + // Directory + @override + Directory createDirectory(String path) { + if (_createDirectory != null) return _createDirectory(path); + if (_previous != null) return _previous.createDirectory(path); + return super.createDirectory(path); + } + + @override + Directory getCurrentDirectory() { + if (_getCurrentDirectory != null) return _getCurrentDirectory(); + if (_previous != null) return _previous.getCurrentDirectory(); + return super.getCurrentDirectory(); + } + + @override + void setCurrentDirectory(String path) { + if (_setCurrentDirectory != null) + _setCurrentDirectory(path); + else if (_previous != null) + _previous.setCurrentDirectory(path); + else + super.setCurrentDirectory(path); + } + + @override + Directory getSystemTempDirectory() { + if (_getSystemTempDirectory != null) return _getSystemTempDirectory(); + if (_previous != null) return _previous.getSystemTempDirectory(); + return super.getSystemTempDirectory(); + } + + // File + @override + File createFile(String path) { + if (_createFile != null) return _createFile(path); + if (_previous != null) return _previous.createFile(path); + return super.createFile(path); + } + + // FileStat + @override + Future stat(String path) { + if (_stat != null) return _stat(path); + if (_previous != null) return _previous.stat(path); + return super.stat(path); + } + + @override + FileStat statSync(String path) { + if (_stat != null) return _statSync(path); + if (_previous != null) return _previous.statSync(path); + return super.statSync(path); + } + + // FileSystemEntity + @override + Future fseIdentical(String path1, String path2) { + if (_fseIdentical != null) return _fseIdentical(path1, path2); + if (_previous != null) return _previous.fseIdentical(path1, path2); + return super.fseIdentical(path1, path2); + } + + @override + bool fseIdenticalSync(String path1, String path2) { + if (_fseIdenticalSync != null) return _fseIdenticalSync(path1, path2); + if (_previous != null) return _previous.fseIdenticalSync(path1, path2); + return super.fseIdenticalSync(path1, path2); + } + + @override + Future fseGetType(String path, bool followLinks) { + if (_fseGetType != null) return _fseGetType(path, followLinks); + if (_previous != null) return _previous.fseGetType(path, followLinks); + return super.fseGetType(path, followLinks); + } + + @override + FileSystemEntityType fseGetTypeSync(String path, bool followLinks) { + if (_fseGetTypeSync != null) return _fseGetTypeSync(path, followLinks); + if (_previous != null) return _previous.fseGetTypeSync(path, followLinks); + return super.fseGetTypeSync(path, followLinks); + } + + // _FileSystemWatcher + @override + Stream fsWatch(String path, int events, bool recursive) { + if (_fsWatch != null) return _fsWatch(path, events, recursive); + if (_previous != null) return _previous.fsWatch(path, events, recursive); + return super.fsWatch(path, events, recursive); + } + + @override + bool fsWatchIsSupported() { + if (_fsWatchIsSupported != null) return _fsWatchIsSupported(); + if (_previous != null) return _previous.fsWatchIsSupported(); + return super.fsWatchIsSupported(); + } + + // Link + @override + Link createLink(String path) { + if (_createLink != null) return _createLink(path); + if (_previous != null) return _previous.createLink(path); + return super.createLink(path); + } + + // Socket + @override + Future socketConnect(host, int port, + {sourceAddress, Duration timeout}) { + if (_socketConnect != null) { + return _socketConnect(host, port, + sourceAddress: sourceAddress, timeout: timeout); + } + if (_previous != null) { + return _previous.socketConnect(host, port, + sourceAddress: sourceAddress, timeout: timeout); + } + return super.socketConnect(host, port, + sourceAddress: sourceAddress, timeout: timeout); + } + + @override + Future> socketStartConnect(host, int port, + {sourceAddress}) { + if (_socketStartConnect != null) { + return _socketStartConnect(host, port, sourceAddress: sourceAddress); + } + if (_previous != null) { + return _previous.socketStartConnect(host, port, + sourceAddress: sourceAddress); + } + return super.socketStartConnect(host, port, sourceAddress: sourceAddress); + } +} +NN<(!HGQ?- +6 + J6 C#73MN%-BL8!2013(.*:6FBC*(,9<'"+3 #4.NJBA#4.=O7B-O,97O&*.O? +8O-3@O'!1O#-LO$:6=O(6:DOKM5O#GP0O"M?AO+? +8O-3 NP/+'9P P"DK.5/-.0 +%+'73C?@' +% (AQ"   +AC( $EC( *&" + ' 'KF+ + !7># '+8 #/# /+"(;1;+9 D'L6)OLfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/platform.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * Information about the environment in which the current program is running. + * + * Platform provides information such as the operating system, + * the hostname of the computer, the value of environment variables, + * the path to the running program, + * and so on. + * + * ## Get the URI to the current Dart script + * + * Use the [script] getter to get the URI to the currently running + * Dart script. + * + * import 'dart:io' show Platform; + * + * void main() { + * // Get the URI of the script being run. + * var uri = Platform.script; + * // Convert the URI to a path. + * var path = uri.toFilePath(); + * } + * + * ## Get the value of an environment variable + * + * The [environment] getter returns a the names and values of environment + * variables in a [Map] that contains key-value pairs of strings. The Map is + * unmodifiable. This sample shows how to get the value of the `PATH` + * environment variable. + * + * import 'dart:io' show Platform; + * + * void main() { + * Map envVars = Platform.environment; + * print(envVars['PATH']); + * } + * + * ## Determine the OS + * + * You can get the name of the operating system as a string with the + * [operatingSystem] getter. You can also use one of the static boolean + * getters: [isMacOS], [isLinux], and [isWindows]. + * + * import 'dart:io' show Platform, stdout; + * + * void main() { + * // Get the operating system as a string. + * String os = Platform.operatingSystem; + * // Or, use a predicate getter. + * if (Platform.isMacOS) { + * print('is a Mac'); + * } else { + * print('is not a Mac'); + * } + * } + * + * ## Other resources + * + * [Dart by Example](https://www.dartlang.org/dart-by-example/#dart-io-and-command-line-apps) + * provides additional task-oriented code samples that show how to use + * various API from the [dart:io] library. + */ +class Platform { + static final _numberOfProcessors = _Platform.numberOfProcessors; + static final _pathSeparator = _Platform.pathSeparator; + static final _operatingSystem = _Platform.operatingSystem; + static final _operatingSystemVersion = _Platform.operatingSystemVersion; + static final _localHostname = _Platform.localHostname; + static final _version = _Platform.version; + + /** + * The number of individual execution units of the machine. + */ + static int get numberOfProcessors => _numberOfProcessors; + + /** + * The path separator used by the operating system to separate + * components in file paths. + */ + static String get pathSeparator => _pathSeparator; + + /** + * Get the name of the current locale. + */ + static String get localeName => _Platform.localeName(); + + /** + * A string representing the operating system or platform. + */ + static String get operatingSystem => _operatingSystem; + + /** + * A string representing the version of the operating system or platform. + */ + static String get operatingSystemVersion => _operatingSystemVersion; + + /** + * The local hostname for the system. + */ + static String get localHostname => _localHostname; + + /** + * Whether the operating system is a version of + * [Linux](https://en.wikipedia.org/wiki/Linux). + * + * This value is `false` if the operating system is a specialized + * version of Linux that identifies itself by a different name, + * for example Android (see [isAndroid]). + */ + static final bool isLinux = (_operatingSystem == "linux"); + + /** + * Whether the operating system is a version of + * [macOS](https://en.wikipedia.org/wiki/MacOS). + */ + static final bool isMacOS = (_operatingSystem == "macos"); + + /** + * Whether the operating system is a version of + * [Microsoft Windows](https://en.wikipedia.org/wiki/Microsoft_Windows). + */ + static final bool isWindows = (_operatingSystem == "windows"); + + /** + * Whether the operating system is a version of + * [Android](https://en.wikipedia.org/wiki/Android_%28operating_system%29). + */ + static final bool isAndroid = (_operatingSystem == "android"); + + /** + * Whether the operating system is a version of + * [iOS](https://en.wikipedia.org/wiki/IOS). + */ + static final bool isIOS = (_operatingSystem == "ios"); + + /** + * Whether the operating system is a version of + * [Fuchsia](https://en.wikipedia.org/wiki/Google_Fuchsia). + */ + static final bool isFuchsia = (_operatingSystem == "fuchsia"); + + /** + * The environment for this process as a map from string key to string value. + * + * The map is unmodifiable, + * and its content is retrieved from the operating system on its first use. + * + * Environment variables on Windows are case-insensitive, + * so on Windows the map is case-insensitive and will convert + * all keys to upper case. + * On other platforms, keys can be distinguished by case. + */ + static Map get environment => _Platform.environment; + + /** + * The path of the executable used to run the script in this isolate. + * + * The literal path used to identify the script. + * This path might be relative or just be a name from which the executable + * was found by searching the system path. + * + * Use [resolvedExecutable] to get an absolute path to the executable. + */ + static String get executable => _Platform.executable; + + /** + * The path of the executable used to run the script in this + * isolate after it has been resolved by the OS. + * + * This is the absolute path, with all symlinks resolved, to the + * executable used to run the script. + */ + static String get resolvedExecutable => _Platform.resolvedExecutable; + + /** + * The absolute URI of the script being run in this isolate. + * + * If the script argument on the command line is relative, + * it is resolved to an absolute URI before fetching the script, and + * that absolute URI is returned. + * + * URI resolution only does string manipulation on the script path, and this + * may be different from the file system's path resolution behavior. For + * example, a symbolic link immediately followed by '..' will not be + * looked up. + * + * If the executable environment does not support [script], + * the URI is empty. + */ + static Uri get script => _Platform.script; + + /** + * The flags passed to the executable used to run the script in this isolate. + * + * These are the command-line flags to the executable that precedes + * the script name. + * Provides a new list every time the value is read. + */ + static List get executableArguments => _Platform.executableArguments; + + /** + * This returns `null`, as `packages/` directories are no longer supported. + * + */ + @Deprecated('packages/ directory resolution is not supported in Dart 2') + static String get packageRoot => null; // TODO(mfairhurst): remove this + + /** + * The `--packages` flag passed to the executable used to run the script + * in this isolate. + * + * If present, it specifies a file describing how Dart packages are looked up. + * + * Is `null` if there is no `--packages` flag. + */ + static String get packageConfig => _Platform.packageConfig; + + /** + * The version of the current Dart runtime. + * + * The value is a [semantic versioning](http://semver.org) + * string representing the version of the current Dart runtime, + * possibly followed by whitespace and other version and + * build details. + */ + static String get version => _version; +} +NN<N?E$-C'1$'& /JMF'=! EH3/2/(!" ^G+C9=K9-><A5):=9LG(523DB,=23=2KA2NA2/92>APN<@<GH3M-I8?3C(H?=G$OKG>-PF7PNKJKQ1>.=B;)Qfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/platform_impl.dartx// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +class _Platform { + external static int _numberOfProcessors(); + external static String _pathSeparator(); + external static String _operatingSystem(); + external static _operatingSystemVersion(); + external static _localHostname(); + external static _executable(); + external static _resolvedExecutable(); + + /** + * Retrieve the entries of the process environment. + * + * The result is an [Iterable] of strings, where each string represents + * an environment entry. + * + * Environment entries should be strings containing + * a non-empty name and a value separated by a '=' character. + * The name does not contain a '=' character, + * so the name is everything up to the first '=' character. + * Values are everything after the first '=' character. + * A value may contain further '=' characters, and it may be empty. + * + * Returns an [OSError] if retrieving the environment fails. + */ + external static _environment(); + external static List _executableArguments(); + external static String _packageRoot(); // TODO(mfairhurst): remove this + external static String _packageConfig(); + external static String _version(); + external static String _localeName(); + external static Uri _script(); + + static String executable = _executable(); + static String resolvedExecutable = _resolvedExecutable(); + static String packageRoot = null; // TODO(mfairhurst): remove this + static String packageConfig = _packageConfig(); + + static String Function() _localeClosure; + static String localeName() { + final result = (_localeClosure == null) ? _localeName() : _localeClosure(); + if (result is OSError) { + throw result; + } + return result; + } + + // Cache the OS environment. This can be an OSError instance if + // retrieving the environment failed. + static var /*OSError|Map*/ _environmentCache; + + static int get numberOfProcessors => _numberOfProcessors(); + static String get pathSeparator => _pathSeparator(); + static String get operatingSystem => _operatingSystem(); + static Uri get script => _script(); + + static String _cachedOSVersion; + static String get operatingSystemVersion { + if (_cachedOSVersion == null) { + var result = _operatingSystemVersion(); + if (result is OSError) { + throw result; + } + _cachedOSVersion = result; + } + return _cachedOSVersion; + } + + static String get localHostname { + var result = _localHostname(); + if (result is OSError) { + throw result; + } + return result; + } + + static List get executableArguments => _executableArguments(); + + static Map get environment { + if (_environmentCache == null) { + var env = _environment(); + if (env is! OSError) { + var isWindows = operatingSystem == 'windows'; + var result = isWindows + ? new _CaseInsensitiveStringMap() + : new Map(); + for (var str in env) { + if (str == null) { + continue; + } + // The Strings returned by [_environment()] are expected to be + // valid environment entries, but exceptions have been seen + // (e.g., an entry of just '=' has been seen on OS/X). + // Invalid entries (lines without a '=' or with an empty name) + // are discarded. + var equalsIndex = str.indexOf('='); + if (equalsIndex > 0) { + result[str.substring(0, equalsIndex)] = + str.substring(equalsIndex + 1); + } + } + _environmentCache = new UnmodifiableMapView(result); + } else { + _environmentCache = env; + } + } + + if (_environmentCache is OSError) { + throw _environmentCache; + } else { + return _environmentCache; + } + } + + static String get version => _version(); +} + +// Environment variables are case-insensitive on Windows. In order +// to reflect that we use a case-insensitive string map on Windows. +class _CaseInsensitiveStringMap extends MapBase { + final Map _map = new Map(); + + bool containsKey(Object key) => + key is String && _map.containsKey(key.toUpperCase()); + bool containsValue(Object value) => _map.containsValue(value); + V operator [](Object key) => key is String ? _map[key.toUpperCase()] : null; + void operator []=(String key, V value) { + _map[key.toUpperCase()] = value; + } + + V putIfAbsent(String key, V ifAbsent()) { + return _map.putIfAbsent(key.toUpperCase(), ifAbsent); + } + + void addAll(Map other) { + other.forEach((key, value) => this[key.toUpperCase()] = value); + } + + V remove(Object key) => key is String ? _map.remove(key.toUpperCase()) : null; + + void clear() { + _map.clear(); + } + + void forEach(void f(String key, V value)) { + _map.forEach(f); + } + + Iterable get keys => _map.keys; + Iterable get values => _map.values; + int get length => _map.length; + bool get isEmpty => _map.isEmpty; + bool get isNotEmpty => _map.isNotEmpty; + + Iterable> get entries => _map.entries; + + Map map(MapEntry transform(String key, V value)) => + _map.map(transform); + + V update(String key, V update(V value), {V ifAbsent()}) => + _map.update(key.toUpperCase(), update, ifAbsent: ifAbsent); + + void updateAll(V update(String key, V value)) { + _map.updateAll(update); + } + + void removeWhere(bool test(String key, V value)) { + _map.removeWhere(test); + } + + String toString() => _map.toString(); +} +NN<-+--$!)6J6@0>:F?"7J+%(!,7;&"-$.!$#I/% 66) IFAI.!40 +M!( +CD@4" _watchSignal(ProcessSignal signal); +} + +/** + * Exit the Dart VM process immediately with the given exit code. + * + * This does not wait for any asynchronous operations to terminate. Using + * [exit] is therefore very likely to lose data. + * + * The handling of exit codes is platform specific. + * + * On Linux and OS X an exit code for normal termination will always + * be in the range [0..255]. If an exit code outside this range is + * set the actual exit code will be the lower 8 bits masked off and + * treated as an unsigned value. E.g. using an exit code of -1 will + * result in an actual exit code of 255 being reported. + * + * On Windows the exit code can be set to any 32-bit value. However + * some of these values are reserved for reporting system errors like + * crashes. + * + * Besides this the Dart executable itself uses an exit code of `254` + * for reporting compile time errors and an exit code of `255` for + * reporting runtime error (unhandled exception). + * + * Due to these facts it is recommended to only use exit codes in the + * range [0..127] for communicating the result of running a Dart + * program to the surrounding environment. This will avoid any + * cross-platform issues. + */ +void exit(int code) { + if (code is! int) { + throw new ArgumentError("Integer value for exit code expected"); + } + if (!_EmbedderConfig._mayExit) { + throw new UnsupportedError( + "This embedder disallows calling dart:io's exit()"); + } + _ProcessUtils._exit(code); +} + +/** + * Set the global exit code for the Dart VM. + * + * The exit code is global for the Dart VM and the last assignment to + * exitCode from any isolate determines the exit code of the Dart VM + * on normal termination. + * + * Default value is `0`. + * + * See [exit] for more information on how to chose a value for the + * exit code. + */ +void set exitCode(int code) { + if (code is! int) { + throw new ArgumentError("Integer value for exit code expected"); + } + _ProcessUtils._setExitCode(code); +} + +/** + * Get the global exit code for the Dart VM. + * + * The exit code is global for the Dart VM and the last assignment to + * exitCode from any isolate determines the exit code of the Dart VM + * on normal termination. + * + * See [exit] for more information on how to chose a value for the + * exit code. + */ +int get exitCode => _ProcessUtils._getExitCode(); + +/** + * Sleep for the duration specified in [duration]. + * + * Use this with care, as no asynchronous operations can be processed + * in a isolate while it is blocked in a [sleep] call. + */ +void sleep(Duration duration) { + int milliseconds = duration.inMilliseconds; + if (milliseconds < 0) { + throw new ArgumentError("sleep: duration cannot be negative"); + } + if (!_EmbedderConfig._maySleep) { + throw new UnsupportedError( + "This embedder disallows calling dart:io's sleep()"); + } + _ProcessUtils._sleep(milliseconds); +} + +/** + * Returns the PID of the current process. + */ +int get pid => _ProcessUtils._pid(null); + +/** + * [ProcessInfo] provides methods for retrieving information about the + * current process. + */ +class ProcessInfo { + /** + * The current resident set size of memory for the process. + * + * Note that the meaning of this field is platform dependent. For example, + * some memory accounted for here may be shared with other processes, or if + * the same page is mapped into a process's address space, it may be counted + * twice. + */ + external static int get currentRss; + + /** + * The high-watermark in bytes for the resident set size of memory for the + * process. + * + * Note that the meaning of this field is platform dependent. For example, + * some memory accounted for here may be shared with other processes, or if + * the same page is mapped into a process's address space, it may be counted + * twice. + */ + external static int get maxRss; +} + +/** + * Modes for running a new process. + */ +class ProcessStartMode { + /// Normal child process. + static const normal = const ProcessStartMode._internal(0); + @Deprecated("Use normal instead") + static const NORMAL = normal; + + /// Stdio handles are inherited by the child process. + static const inheritStdio = const ProcessStartMode._internal(1); + @Deprecated("Use inheritStdio instead") + static const INHERIT_STDIO = inheritStdio; + + /// Detached child process with no open communication channel. + static const detached = const ProcessStartMode._internal(2); + @Deprecated("Use detached instead") + static const DETACHED = detached; + + /// Detached child process with stdin, stdout and stderr still open + /// for communication with the child. + static const detachedWithStdio = const ProcessStartMode._internal(3); + @Deprecated("Use detachedWithStdio instead") + static const DETACHED_WITH_STDIO = detachedWithStdio; + + static List get values => const [ + normal, + inheritStdio, + detached, + detachedWithStdio + ]; + String toString() => + const ["normal", "inheritStdio", "detached", "detachedWithStdio"][_mode]; + + final int _mode; + const ProcessStartMode._internal(this._mode); +} + +/** + * The means to execute a program. + * + * Use the static [start] and [run] methods to start a new process. + * The run method executes the process non-interactively to completion. + * In contrast, the start method allows your code to interact with the + * running process. + * + * ## Start a process with the run method + * + * The following code sample uses the run method to create a process + * that runs the UNIX command `ls`, which lists the contents of a directory. + * The run method completes with a [ProcessResult] object when the process + * terminates. This provides access to the output and exit code from the + * process. The run method does not return a Process object; this prevents your + * code from interacting with the running process. + * + * import 'dart:io'; + * + * main() { + * // List all files in the current directory in UNIX-like systems. + * Process.run('ls', ['-l']).then((ProcessResult results) { + * print(results.stdout); + * }); + * } + * + * ## Start a process with the start method + * + * The following example uses start to create the process. + * The start method returns a [Future] for a Process object. + * When the future completes the process is started and + * your code can interact with the + * Process: writing to stdin, listening to stdout, and so on. + * + * The following sample starts the UNIX `cat` utility, which when given no + * command-line arguments, echos its input. + * The program writes to the process's standard input stream + * and prints data from its standard output stream. + * + * import 'dart:io'; + * import 'dart:convert'; + * + * main() { + * Process.start('cat', []).then((Process process) { + * process.stdout + * .transform(utf8.decoder) + * .listen((data) { print(data); }); + * process.stdin.writeln('Hello, world!'); + * process.stdin.writeln('Hello, galaxy!'); + * process.stdin.writeln('Hello, universe!'); + * }); + * } + * + * ## Standard I/O streams + * + * As seen in the previous code sample, you can interact with the Process's + * standard output stream through the getter [stdout], + * and you can interact with the Process's standard input stream through + * the getter [stdin]. + * In addition, Process provides a getter [stderr] for using the Process's + * standard error stream. + * + * A Process's streams are distinct from the top-level streams + * for the current program. + * + * ## Exit codes + * + * Call the [exitCode] method to get the exit code of the process. + * The exit code indicates whether the program terminated successfully + * (usually indicated with an exit code of 0) or with an error. + * + * If the start method is used, the exitCode is available through a future + * on the Process object (as shown in the example below). + * If the run method is used, the exitCode is available + * through a getter on the ProcessResult instance. + * + * import 'dart:io'; + * + * main() { + * Process.start('ls', ['-l']).then((process) { + * // Get the exit code from the new process. + * process.exitCode.then((exitCode) { + * print('exit code: $exitCode'); + * }); + * }); + * } + * + * ## Other resources + * + * [Dart by Example](https://www.dartlang.org/dart-by-example/#dart-io-and-command-line-apps) + * provides additional task-oriented code samples that show how to use + * various API from the [dart:io] library. + */ +abstract class Process { + /** + * Returns a [:Future:] which completes with the exit code of the process + * when the process completes. + * + * The handling of exit codes is platform specific. + * + * On Linux and OS X a normal exit code will be a positive value in + * the range [0..255]. If the process was terminated due to a signal + * the exit code will be a negative value in the range [-255..-1], + * where the absolute value of the exit code is the signal + * number. For example, if a process crashes due to a segmentation + * violation the exit code will be -11, as the signal SIGSEGV has the + * number 11. + * + * On Windows a process can report any 32-bit value as an exit + * code. When returning the exit code this exit code is turned into + * a signed value. Some special values are used to report + * termination due to some system event. E.g. if a process crashes + * due to an access violation the 32-bit exit code is `0xc0000005`, + * which will be returned as the negative number `-1073741819`. To + * get the original 32-bit value use `(0x100000000 + exitCode) & + * 0xffffffff`. + */ + Future get exitCode; + + /** + * Starts a process running the [executable] with the specified + * [arguments]. Returns a [:Future:] that completes with a + * Process instance when the process has been successfully + * started. That [Process] object can be used to interact with the + * process. If the process cannot be started the returned [Future] + * completes with an exception. + * + * Use [workingDirectory] to set the working directory for the process. Note + * that the change of directory occurs before executing the process on some + * platforms, which may have impact when using relative paths for the + * executable and the arguments. + * + * Use [environment] to set the environment variables for the process. If not + * set the environment of the parent process is inherited. Currently, only + * US-ASCII environment variables are supported and errors are likely to occur + * if an environment variable with code-points outside the US-ASCII range is + * passed in. + * + * If [includeParentEnvironment] is `true`, the process's environment will + * include the parent process's environment, with [environment] taking + * precedence. Default is `true`. + * + * If [runInShell] is `true`, the process will be spawned through a system + * shell. On Linux and OS X, [:/bin/sh:] is used, while + * [:%WINDIR%\system32\cmd.exe:] is used on Windows. + * + * Users must read all data coming on the [stdout] and [stderr] + * streams of processes started with [:Process.start:]. If the user + * does not read all data on the streams the underlying system + * resources will not be released since there is still pending data. + * + * The following code uses `Process.start` to grep for `main` in the + * file `test.dart` on Linux. + * + * Process.start('grep', ['-i', 'main', 'test.dart']).then((process) { + * stdout.addStream(process.stdout); + * stderr.addStream(process.stderr); + * }); + * + * If [mode] is [ProcessStartMode.normal] (the default) a child + * process will be started with `stdin`, `stdout` and `stderr` + * connected. + * + * If `mode` is [ProcessStartMode.detached] a detached process will + * be created. A detached process has no connection to its parent, + * and can keep running on its own when the parent dies. The only + * information available from a detached process is its `pid`. There + * is no connection to its `stdin`, `stdout` or `stderr`, nor will + * the process' exit code become available when it terminates. + * + * If `mode` is [ProcessStartMode.detachedWithStdio] a detached + * process will be created where the `stdin`, `stdout` and `stderr` + * are connected. The creator can communicate with the child through + * these. The detached process will keep running even if these + * communication channels are closed. The process' exit code will + * not become available when it terminated. + * + * The default value for `mode` is `ProcessStartMode.normal`. + */ + external static Future start( + String executable, List arguments, + {String workingDirectory, + Map environment, + bool includeParentEnvironment: true, + bool runInShell: false, + ProcessStartMode mode: ProcessStartMode.normal}); + + /** + * Starts a process and runs it non-interactively to completion. The + * process run is [executable] with the specified [arguments]. + * + * Use [workingDirectory] to set the working directory for the process. Note + * that the change of directory occurs before executing the process on some + * platforms, which may have impact when using relative paths for the + * executable and the arguments. + * + * Use [environment] to set the environment variables for the process. If not + * set the environment of the parent process is inherited. Currently, only + * US-ASCII environment variables are supported and errors are likely to occur + * if an environment variable with code-points outside the US-ASCII range is + * passed in. + * + * If [includeParentEnvironment] is `true`, the process's environment will + * include the parent process's environment, with [environment] taking + * precedence. Default is `true`. + * + * If [runInShell] is true, the process will be spawned through a system + * shell. On Linux and OS X, `/bin/sh` is used, while + * `%WINDIR%\system32\cmd.exe` is used on Windows. + * + * The encoding used for decoding `stdout` and `stderr` into text is + * controlled through [stdoutEncoding] and [stderrEncoding]. The + * default encoding is [systemEncoding]. If `null` is used no + * decoding will happen and the [ProcessResult] will hold binary + * data. + * + * Returns a `Future` that completes with the + * result of running the process, i.e., exit code, standard out and + * standard in. + * + * The following code uses `Process.run` to grep for `main` in the + * file `test.dart` on Linux. + * + * Process.run('grep', ['-i', 'main', 'test.dart']).then((result) { + * stdout.write(result.stdout); + * stderr.write(result.stderr); + * }); + */ + external static Future run( + String executable, List arguments, + {String workingDirectory, + Map environment, + bool includeParentEnvironment: true, + bool runInShell: false, + Encoding stdoutEncoding: systemEncoding, + Encoding stderrEncoding: systemEncoding}); + + /** + * Starts a process and runs it to completion. This is a synchronous + * call and will block until the child process terminates. + * + * The arguments are the same as for `Process.run`. + * + * Returns a `ProcessResult` with the result of running the process, + * i.e., exit code, standard out and standard in. + */ + external static ProcessResult runSync( + String executable, List arguments, + {String workingDirectory, + Map environment, + bool includeParentEnvironment: true, + bool runInShell: false, + Encoding stdoutEncoding: systemEncoding, + Encoding stderrEncoding: systemEncoding}); + + /** + * Kills the process with id [pid]. + * + * Where possible, sends the [signal] to the process with id + * `pid`. This includes Linux and OS X. The default signal is + * [ProcessSignal.sigterm] which will normally terminate the + * process. + * + * On platforms without signal support, including Windows, the call + * just terminates the process with id `pid` in a platform specific + * way, and the `signal` parameter is ignored. + * + * Returns `true` if the signal is successfully delivered to the + * process. Otherwise the signal could not be sent, usually meaning + * that the process is already dead. + */ + external static bool killPid(int pid, + [ProcessSignal signal = ProcessSignal.sigterm]); + + /** + * Returns the standard output stream of the process as a [:Stream:]. + */ + Stream> get stdout; + + /** + * Returns the standard error stream of the process as a [:Stream:]. + */ + Stream> get stderr; + + /** + * Returns the standard input stream of the process as an [IOSink]. + */ + IOSink get stdin; + + /** + * Returns the process id of the process. + */ + int get pid; + + /** + * Kills the process. + * + * Where possible, sends the [signal] to the process. This includes + * Linux and OS X. The default signal is [ProcessSignal.sigterm] + * which will normally terminate the process. + * + * On platforms without signal support, including Windows, the call + * just terminates the process in a platform specific way, and the + * `signal` parameter is ignored. + * + * Returns `true` if the signal is successfully delivered to the + * process. Otherwise the signal could not be sent, usually meaning + * that the process is already dead. + */ + bool kill([ProcessSignal signal = ProcessSignal.sigterm]); +} + +/** + * [ProcessResult] represents the result of running a non-interactive + * process started with [Process.run] or [Process.runSync]. + */ +class ProcessResult { + /** + * Exit code for the process. + * + * See [Process.exitCode] for more information in the exit code + * value. + */ + final int exitCode; + + /** + * Standard output from the process. The value used for the + * `stdoutEncoding` argument to `Process.run` determines the type. If + * `null` was used this value is of type `List` otherwise it is + * of type `String`. + */ + final stdout; + + /** + * Standard error from the process. The value used for the + * `stderrEncoding` argument to `Process.run` determines the type. If + * `null` was used this value is of type `List` + * otherwise it is of type `String`. + */ + final stderr; + + /** + * Process id of the process. + */ + final int pid; + + ProcessResult(this.pid, this.exitCode, this.stdout, this.stderr); +} + +/** + * On Posix systems, [ProcessSignal] is used to send a specific signal + * to a child process, see [:Process.kill:]. + * + * Some [ProcessSignal]s can also be watched, as a way to intercept the default + * signal handler and implement another. See [ProcessSignal.watch] for more + * information. + */ +class ProcessSignal { + static const ProcessSignal sighup = const ProcessSignal._(1, "SIGHUP"); + static const ProcessSignal sigint = const ProcessSignal._(2, "SIGINT"); + static const ProcessSignal sigquit = const ProcessSignal._(3, "SIGQUIT"); + static const ProcessSignal sigill = const ProcessSignal._(4, "SIGILL"); + static const ProcessSignal sigtrap = const ProcessSignal._(5, "SIGTRAP"); + static const ProcessSignal sigabrt = const ProcessSignal._(6, "SIGABRT"); + static const ProcessSignal sigbus = const ProcessSignal._(7, "SIGBUS"); + static const ProcessSignal sigfpe = const ProcessSignal._(8, "SIGFPE"); + static const ProcessSignal sigkill = const ProcessSignal._(9, "SIGKILL"); + static const ProcessSignal sigusr1 = const ProcessSignal._(10, "SIGUSR1"); + static const ProcessSignal sigsegv = const ProcessSignal._(11, "SIGSEGV"); + static const ProcessSignal sigusr2 = const ProcessSignal._(12, "SIGUSR2"); + static const ProcessSignal sigpipe = const ProcessSignal._(13, "SIGPIPE"); + static const ProcessSignal sigalrm = const ProcessSignal._(14, "SIGALRM"); + static const ProcessSignal sigterm = const ProcessSignal._(15, "SIGTERM"); + static const ProcessSignal sigchld = const ProcessSignal._(17, "SIGCHLD"); + static const ProcessSignal sigcont = const ProcessSignal._(18, "SIGCONT"); + static const ProcessSignal sigstop = const ProcessSignal._(19, "SIGSTOP"); + static const ProcessSignal sigtstp = const ProcessSignal._(20, "SIGTSTP"); + static const ProcessSignal sigttin = const ProcessSignal._(21, "SIGTTIN"); + static const ProcessSignal sigttou = const ProcessSignal._(22, "SIGTTOU"); + static const ProcessSignal sigurg = const ProcessSignal._(23, "SIGURG"); + static const ProcessSignal sigxcpu = const ProcessSignal._(24, "SIGXCPU"); + static const ProcessSignal sigxfsz = const ProcessSignal._(25, "SIGXFSZ"); + static const ProcessSignal sigvtalrm = const ProcessSignal._(26, "SIGVTALRM"); + static const ProcessSignal sigprof = const ProcessSignal._(27, "SIGPROF"); + static const ProcessSignal sigwinch = const ProcessSignal._(28, "SIGWINCH"); + static const ProcessSignal sigpoll = const ProcessSignal._(29, "SIGPOLL"); + static const ProcessSignal sigsys = const ProcessSignal._(31, "SIGSYS"); + + @Deprecated("Use sighup instead") + static const ProcessSignal SIGHUP = sighup; + @Deprecated("Use sigint instead") + static const ProcessSignal SIGINT = sigint; + @Deprecated("Use sigquit instead") + static const ProcessSignal SIGQUIT = sigquit; + @Deprecated("Use sigill instead") + static const ProcessSignal SIGILL = sigill; + @Deprecated("Use sigtrap instead") + static const ProcessSignal SIGTRAP = sigtrap; + @Deprecated("Use sigabrt instead") + static const ProcessSignal SIGABRT = sigabrt; + @Deprecated("Use sigbus instead") + static const ProcessSignal SIGBUS = sigbus; + @Deprecated("Use sigfpe instead") + static const ProcessSignal SIGFPE = sigfpe; + @Deprecated("Use sigkill instead") + static const ProcessSignal SIGKILL = sigkill; + @Deprecated("Use sigusr1 instead") + static const ProcessSignal SIGUSR1 = sigusr1; + @Deprecated("Use sigsegv instead") + static const ProcessSignal SIGSEGV = sigsegv; + @Deprecated("Use sigusr2 instead") + static const ProcessSignal SIGUSR2 = sigusr2; + @Deprecated("Use sigpipe instead") + static const ProcessSignal SIGPIPE = sigpipe; + @Deprecated("Use sigalrm instead") + static const ProcessSignal SIGALRM = sigalrm; + @Deprecated("Use sigterm instead") + static const ProcessSignal SIGTERM = sigterm; + @Deprecated("Use sigchld instead") + static const ProcessSignal SIGCHLD = sigchld; + @Deprecated("Use sigcont instead") + static const ProcessSignal SIGCONT = sigcont; + @Deprecated("Use sigstop instead") + static const ProcessSignal SIGSTOP = sigstop; + @Deprecated("Use sigtstp instead") + static const ProcessSignal SIGTSTP = sigtstp; + @Deprecated("Use sigttin instead") + static const ProcessSignal SIGTTIN = sigttin; + @Deprecated("Use sigttou instead") + static const ProcessSignal SIGTTOU = sigttou; + @Deprecated("Use sigurg instead") + static const ProcessSignal SIGURG = sigurg; + @Deprecated("Use sigxcpu instead") + static const ProcessSignal SIGXCPU = sigxcpu; + @Deprecated("Use sigxfsz instead") + static const ProcessSignal SIGXFSZ = sigxfsz; + @Deprecated("Use sigvtalrm instead") + static const ProcessSignal SIGVTALRM = sigvtalrm; + @Deprecated("Use sigprof instead") + static const ProcessSignal SIGPROF = sigprof; + @Deprecated("Use sigwinch instead") + static const ProcessSignal SIGWINCH = sigwinch; + @Deprecated("Use sigpoll instead") + static const ProcessSignal SIGPOLL = sigpoll; + @Deprecated("Use sigsys instead") + static const ProcessSignal SIGSYS = sigsys; + + final int _signalNumber; + final String _name; + + const ProcessSignal._(this._signalNumber, this._name); + + String toString() => _name; + + /** + * Watch for process signals. + * + * The following [ProcessSignal]s can be listened to: + * + * * [ProcessSignal.sighup]. + * * [ProcessSignal.sigint]. Signal sent by e.g. CTRL-C. + * * [ProcessSignal.sigterm]. Not available on Windows. + * * [ProcessSignal.sigusr1]. Not available on Windows. + * * [ProcessSignal.sigusr2]. Not available on Windows. + * * [ProcessSignal.sigwinch]. Not available on Windows. + * + * Other signals are disallowed, as they may be used by the VM. + * + * A signal can be watched multiple times, from multiple isolates, where all + * callbacks are invoked when signaled, in no specific order. + */ + Stream watch() => _ProcessUtils._watchSignal(this); +} + +class SignalException implements IOException { + final String message; + final osError; + + const SignalException(this.message, [this.osError = null]); + + String toString() { + var msg = ""; + if (osError != null) { + msg = ", osError: $osError"; + } + return "SignalException: $message$msg"; + } +} + +class ProcessException implements IOException { + /** + * Contains the executable provided for the process. + */ + final String executable; + + /** + * Contains the arguments provided for the process. + */ + final List arguments; + + /** + * Contains the system message for the process exception if any. + */ + final String message; + + /** + * Contains the OS error code for the process exception if any. + */ + final int errorCode; + + const ProcessException(this.executable, this.arguments, + [this.message = "", this.errorCode = 0]); + String toString() { + var msg = (message == null) ? 'OS error code: $errorCode' : message; + var args = arguments.join(' '); + return "ProcessException: $msg\n Command: $executable $args"; + } +} +NN<9+*1&+-LBJ14ECDD8DF FC2FA?E# =-FECE$-FEC23F7 .C$ >&+)G>MNO &MMNO "$=$ 8C*-A?&$F(H/8H P0#DHG*EMKIP3JB" ,;=8#>K,=4;(1346 L7IK?CG@K:8366., ^G+L!6FGE=EHAFHG=H7' DG-PLJJLJLLJJLMMMMMMMMMMMMKMMQMOMK$.$.%0$.%0%0$.$.%0%0%0%0%0%0%0%0%0%0%0%0%0$.%0%0'4%0&2%0$.9 8!=<<<=BO@E/>#,076 CB:0I$CXfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/secure_server_socket.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * The [SecureServerSocket] is a server socket, providing a stream of high-level + * [Socket]s. + * + * See [SecureSocket] for more info. + */ +class SecureServerSocket extends Stream { + final RawSecureServerSocket _socket; + + SecureServerSocket._(this._socket); + + /** + * Returns a future for a [SecureServerSocket]. When the future + * completes the server socket is bound to the given [address] and + * [port] and has started listening on it. + * + * The [address] can either be a [String] or an + * [InternetAddress]. If [address] is a [String], [bind] will + * perform a [InternetAddress.lookup] and use the first value in the + * list. To listen on the loopback adapter, which will allow only + * incoming connections from the local host, use the value + * [InternetAddress.loopbackIPv4] or + * [InternetAddress.loopbackIPv6]. To allow for incoming + * connection from the network use either one of the values + * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to + * bind to all interfaces or the IP address of a specific interface. + * + * If [port] has the value [:0:] an ephemeral port will be chosen by + * the system. The actual port used can be retrieved using the + * [port] getter. + * + * The optional argument [backlog] can be used to specify the listen + * backlog for the underlying OS listen setup. If [backlog] has the + * value of [:0:] (the default) a reasonable value will be chosen by + * the system. + * + * Incoming client connections are promoted to secure connections, using + * the server certificate and key set in [context]. + * + * [address] must be given as a numeric address, not a host name. + * + * To request or require that clients authenticate by providing an SSL (TLS) + * client certificate, set the optional parameter [requestClientCertificate] + * or [requireClientCertificate] to true. Requiring a certificate implies + * requesting a certificate, so setting both is redundant. + * To check whether a client certificate was received, check + * SecureSocket.peerCertificate after connecting. If no certificate + * was received, the result will be null. + * + * [supportedProtocols] is an optional list of protocols (in decreasing + * order of preference) to use during the ALPN protocol negogiation with + * clients. Example values are "http/1.1" or "h2". The selected protocol + * can be obtained via [SecureSocket.selectedProtocol]. + * + * The optional argument [shared] specifies whether additional + * SecureServerSocket objects can bind to the same combination of `address`, + * `port` and `v6Only`. If `shared` is `true` and more `SecureServerSocket`s + * from this isolate or other isolates are bound to the port, then the + * incoming connections will be distributed among all the bound + * `SecureServerSocket`s. Connections can be distributed over multiple + * isolates this way. + */ + static Future bind( + address, int port, SecurityContext context, + {int backlog: 0, + bool v6Only: false, + bool requestClientCertificate: false, + bool requireClientCertificate: false, + List supportedProtocols, + bool shared: false}) { + return RawSecureServerSocket + .bind(address, port, context, + backlog: backlog, + v6Only: v6Only, + requestClientCertificate: requestClientCertificate, + requireClientCertificate: requireClientCertificate, + supportedProtocols: supportedProtocols, + shared: shared) + .then((serverSocket) => new SecureServerSocket._(serverSocket)); + } + + StreamSubscription listen(void onData(SecureSocket socket), + {Function onError, void onDone(), bool cancelOnError}) { + return _socket.map((rawSocket) => new SecureSocket._(rawSocket)).listen( + onData, + onError: onError, + onDone: onDone, + cancelOnError: cancelOnError); + } + + /** + * Returns the port used by this socket. + */ + int get port => _socket.port; + + /** + * Returns the address used by this socket. + */ + InternetAddress get address => _socket.address; + + /** + * Closes the socket. The returned future completes when the socket + * is fully closed and is no longer bound. + */ + Future close() => _socket.close().then((_) => this); + + void set _owner(owner) { + _socket._owner = owner; + } +} + +/** + * The RawSecureServerSocket is a server socket, providing a stream of low-level + * [RawSecureSocket]s. + * + * See [RawSecureSocket] for more info. + */ +class RawSecureServerSocket extends Stream { + final RawServerSocket _socket; + StreamController _controller; + StreamSubscription _subscription; + final SecurityContext _context; + final bool requestClientCertificate; + final bool requireClientCertificate; + final List supportedProtocols; + bool _closed = false; + + RawSecureServerSocket._( + this._socket, + this._context, + this.requestClientCertificate, + this.requireClientCertificate, + this.supportedProtocols) { + _controller = new StreamController( + sync: true, + onListen: _onSubscriptionStateChange, + onPause: _onPauseStateChange, + onResume: _onPauseStateChange, + onCancel: _onSubscriptionStateChange); + } + + /** + * Returns a future for a [RawSecureServerSocket]. When the future + * completes the server socket is bound to the given [address] and + * [port] and has started listening on it. + * + * The [address] can either be a [String] or an + * [InternetAddress]. If [address] is a [String], [bind] will + * perform a [InternetAddress.lookup] and use the first value in the + * list. To listen on the loopback adapter, which will allow only + * incoming connections from the local host, use the value + * [InternetAddress.loopbackIPv4] or + * [InternetAddress.loopbackIPv6]. To allow for incoming + * connection from the network use either one of the values + * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to + * bind to all interfaces or the IP address of a specific interface. + * + * If [port] has the value [:0:] an ephemeral port will be chosen by + * the system. The actual port used can be retrieved using the + * [port] getter. + * + * The optional argument [backlog] can be used to specify the listen + * backlog for the underlying OS listen setup. If [backlog] has the + * value of [:0:] (the default) a reasonable value will be chosen by + * the system. + * + * Incoming client connections are promoted to secure connections, + * using the server certificate and key set in [context]. + * + * [address] must be given as a numeric address, not a host name. + * + * To request or require that clients authenticate by providing an SSL (TLS) + * client certificate, set the optional parameters requestClientCertificate or + * requireClientCertificate to true. Require implies request, so one doesn't + * need to specify both. To check whether a client certificate was received, + * check SecureSocket.peerCertificate after connecting. If no certificate + * was received, the result will be null. + * + * [supportedProtocols] is an optional list of protocols (in decreasing + * order of preference) to use during the ALPN protocol negotiation with + * clients. Example values are "http/1.1" or "h2". The selected protocol + * can be obtained via [RawSecureSocket.selectedProtocol]. + * + * The optional argument [shared] specifies whether additional + * RawSecureServerSocket objects can bind to the same combination of + * `address`, `port` and `v6Only`. If `shared` is `true` and more + * `RawSecureServerSocket`s from this isolate or other isolates are bound to + * the port, then the incoming connections will be distributed among all the + * bound `RawSecureServerSocket`s. Connections can be distributed over + * multiple isolates this way. + */ + static Future bind( + address, int port, SecurityContext context, + {int backlog: 0, + bool v6Only: false, + bool requestClientCertificate: false, + bool requireClientCertificate: false, + List supportedProtocols, + bool shared: false}) { + return RawServerSocket + .bind(address, port, backlog: backlog, v6Only: v6Only, shared: shared) + .then((serverSocket) => new RawSecureServerSocket._( + serverSocket, + context, + requestClientCertificate, + requireClientCertificate, + supportedProtocols)); + } + + StreamSubscription listen(void onData(RawSecureSocket s), + {Function onError, void onDone(), bool cancelOnError}) { + return _controller.stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + } + + /** + * Returns the port used by this socket. + */ + int get port => _socket.port; + + /** + * Returns the address used by this socket. + */ + InternetAddress get address => _socket.address; + + /** + * Closes the socket. The returned future completes when the socket + * is fully closed and is no longer bound. + */ + Future close() { + _closed = true; + return _socket.close().then((_) => this); + } + + void _onData(RawSocket connection) { + var remotePort; + try { + remotePort = connection.remotePort; + } catch (e) { + // If connection is already closed, remotePort throws an exception. + // Do nothing - connection is closed. + return; + } + _RawSecureSocket + .connect(connection.address, remotePort, + context: _context, + is_server: true, + socket: connection, + requestClientCertificate: requestClientCertificate, + requireClientCertificate: requireClientCertificate, + supportedProtocols: supportedProtocols) + .then((RawSecureSocket secureConnection) { + if (_closed) { + secureConnection.close(); + } else { + _controller.add(secureConnection); + } + }).catchError((e, s) { + if (!_closed) { + _controller.addError(e, s); + } + }); + } + + void _onPauseStateChange() { + if (_controller.isPaused) { + _subscription.pause(); + } else { + _subscription.resume(); + } + } + + void _onSubscriptionStateChange() { + if (_controller.hasListener) { + _subscription = _socket.listen(_onData, + onError: _controller.addError, onDone: _controller.close); + } else { + close(); + } + } + + void set _owner(owner) { + (_socket as dynamic)._owner = owner; + } +} +%NN<Q%8'&BE-2@GD=';>?GGAGFGK6DOOM=?G,JKM:AOPIBI*2,,'!&@@4IL?M'+ .2F-KQ(>!1/"'')%%!9.&'/EE-2@GD=';>?GGAGFGE<DOQPPM,JKM=AGEOOI!-2,,'O=&&"M?-I+ .2F-*.' +*J,1 @@43"+$  &#.E )Qfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/secure_socket.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * A high-level class for communicating securely over a TCP socket, using + * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an + * [IOSink] interface, making it ideal for using together with + * other [Stream]s. + */ +abstract class SecureSocket implements Socket { + external factory SecureSocket._(RawSecureSocket rawSocket); + + /** + * Constructs a new secure client socket and connects it to the given + * [host] on port [port]. The returned Future will complete with a + * [SecureSocket] that is connected and ready for subscription. + * + * The certificate provided by the server is checked + * using the trusted certificates set in the SecurityContext object. + * The default SecurityContext object contains a built-in set of trusted + * root certificates for well-known certificate authorities. + * + * [onBadCertificate] is an optional handler for unverifiable certificates. + * The handler receives the [X509Certificate], and can inspect it and + * decide (or let the user decide) whether to accept + * the connection or not. The handler should return true + * to continue the [SecureSocket] connection. + * + * [supportedProtocols] is an optional list of protocols (in decreasing + * order of preference) to use during the ALPN protocol negotiation with the + * server. Example values are "http/1.1" or "h2". The selected protocol + * can be obtained via [SecureSocket.selectedProtocol]. + * + * The argument [timeout] is used to specify the maximum allowed time to wait + * for a connection to be established. If [timeout] is longer than the system + * level timeout duration, a timeout may occur sooner than specified in + * [timeout]. On timeout, a [SocketException] is thrown and all ongoing + * connection attempts to [host] are cancelled. + + */ + static Future connect(host, int port, + {SecurityContext context, + bool onBadCertificate(X509Certificate certificate), + List supportedProtocols, + Duration timeout}) { + return RawSecureSocket.connect(host, port, + context: context, + onBadCertificate: onBadCertificate, + supportedProtocols: supportedProtocols, + timeout: timeout) + .then((rawSocket) => new SecureSocket._(rawSocket)); + } + + /// Like [connect], but returns a [Future] that completes with a + /// [ConnectionTask] that can be cancelled if the [SecureSocket] is no + /// longer needed. + static Future> startConnect(host, int port, + {SecurityContext context, + bool onBadCertificate(X509Certificate certificate), + List supportedProtocols}) { + return RawSecureSocket.startConnect(host, port, + context: context, + onBadCertificate: onBadCertificate, + supportedProtocols: supportedProtocols) + .then((rawState) { + Future socket = + rawState.socket.then((rawSocket) => new SecureSocket._(rawSocket)); + return new ConnectionTask._( + socket: socket, onCancel: rawState._onCancel); + }); + } + + /** + * Takes an already connected [socket] and starts client side TLS + * handshake to make the communication secure. When the returned + * future completes the [SecureSocket] has completed the TLS + * handshake. Using this function requires that the other end of the + * connection is prepared for TLS handshake. + * + * If the [socket] already has a subscription, this subscription + * will no longer receive and events. In most cases calling + * `pause` on this subscription before starting TLS handshake is + * the right thing to do. + * + * The given [socket] is closed and may not be used anymore. + * + * If the [host] argument is passed it will be used as the host name + * for the TLS handshake. If [host] is not passed the host name from + * the [socket] will be used. The [host] can be either a [String] or + * an [InternetAddress]. + * + * Calling this function will _not_ cause a DNS host lookup. If the + * [host] passed is a [String] the [InternetAddress] for the + * resulting [SecureSocket] will have the passed in [host] as its + * host value and the internet address of the already connected + * socket as its address value. + * + * See [connect] for more information on the arguments. + * + */ + static Future secure(Socket socket, + {host, + SecurityContext context, + bool onBadCertificate(X509Certificate certificate)}) { + return ((socket as dynamic /*_Socket*/)._detachRaw() as Future) + .then((detachedRaw) { + return RawSecureSocket.secure(detachedRaw[0] as RawSocket, + subscription: detachedRaw[1] as StreamSubscription, + host: host, + context: context, + onBadCertificate: onBadCertificate); + }).then((raw) => new SecureSocket._(raw)); + } + + /** + * Takes an already connected [socket] and starts server side TLS + * handshake to make the communication secure. When the returned + * future completes the [SecureSocket] has completed the TLS + * handshake. Using this function requires that the other end of the + * connection is going to start the TLS handshake. + * + * If the [socket] already has a subscription, this subscription + * will no longer receive and events. In most cases calling + * [:pause:] on this subscription before starting TLS handshake is + * the right thing to do. + * + * If some of the data of the TLS handshake has already been read + * from the socket this data can be passed in the [bufferedData] + * parameter. This data will be processed before any other data + * available on the socket. + * + * See [SecureServerSocket.bind] for more information on the + * arguments. + * + */ + static Future secureServer( + Socket socket, SecurityContext context, + {List bufferedData, + bool requestClientCertificate: false, + bool requireClientCertificate: false, + List supportedProtocols}) { + return ((socket as dynamic /*_Socket*/)._detachRaw() as Future) + .then((detachedRaw) { + return RawSecureSocket.secureServer(detachedRaw[0] as RawSocket, context, + subscription: detachedRaw[1] as StreamSubscription, + bufferedData: bufferedData, + requestClientCertificate: requestClientCertificate, + requireClientCertificate: requireClientCertificate, + supportedProtocols: supportedProtocols); + }).then((raw) => new SecureSocket._(raw)); + } + + /** + * Get the peer certificate for a connected SecureSocket. If this + * SecureSocket is the server end of a secure socket connection, + * [peerCertificate] will return the client certificate, or null, if no + * client certificate was received. If it is the client end, + * [peerCertificate] will return the server's certificate. + */ + X509Certificate get peerCertificate; + + /** + * The protocol which was selected during ALPN protocol negotiation. + * + * Returns null if one of the peers does not have support for ALPN, did not + * specify a list of supported ALPN protocols or there was no common + * protocol between client and server. + */ + String get selectedProtocol; + + /** + * Renegotiate an existing secure connection, renewing the session keys + * and possibly changing the connection properties. + * + * This repeats the SSL or TLS handshake, with options that allow clearing + * the session cache and requesting a client certificate. + */ + void renegotiate( + {bool useSessionCache: true, + bool requestClientCertificate: false, + bool requireClientCertificate: false}); +} + +/** + * RawSecureSocket provides a secure (SSL or TLS) network connection. + * Client connections to a server are provided by calling + * RawSecureSocket.connect. A secure server, created with + * [RawSecureServerSocket], also returns RawSecureSocket objects representing + * the server end of a secure connection. + * The certificate provided by the server is checked + * using the trusted certificates set in the SecurityContext object. + * The default [SecurityContext] object contains a built-in set of trusted + * root certificates for well-known certificate authorities. + */ +abstract class RawSecureSocket implements RawSocket { + /** + * Constructs a new secure client socket and connect it to the given + * host on the given port. The returned [Future] is completed with the + * RawSecureSocket when it is connected and ready for subscription. + * + * The certificate provided by the server is checked using the trusted + * certificates set in the SecurityContext object If a certificate and key are + * set on the client, using [SecurityContext.useCertificateChain] and + * [SecurityContext.usePrivateKey], and the server asks for a client + * certificate, then that client certificate is sent to the server. + * + * [onBadCertificate] is an optional handler for unverifiable certificates. + * The handler receives the [X509Certificate], and can inspect it and + * decide (or let the user decide) whether to accept + * the connection or not. The handler should return true + * to continue the [RawSecureSocket] connection. + * + * [supportedProtocols] is an optional list of protocols (in decreasing + * order of preference) to use during the ALPN protocol negotiation with the + * server. Example values are "http/1.1" or "h2". The selected protocol + * can be obtained via [RawSecureSocket.selectedProtocol]. + */ + static Future connect(host, int port, + {SecurityContext context, + bool onBadCertificate(X509Certificate certificate), + List supportedProtocols, + Duration timeout}) { + _RawSecureSocket._verifyFields( + host, port, false, false, false, onBadCertificate); + return RawSocket.connect(host, port, timeout: timeout).then((socket) { + return secure(socket, + context: context, + onBadCertificate: onBadCertificate, + supportedProtocols: supportedProtocols); + }); + } + + /// Like [connect], but returns a [Future] that completes with a + /// [ConnectionTask] that can be cancelled if the [RawSecureSocket] is no + /// longer needed. + static Future> startConnect(host, int port, + {SecurityContext context, + bool onBadCertificate(X509Certificate certificate), + List supportedProtocols}) { + return RawSocket.startConnect(host, port) + .then((ConnectionTask rawState) { + Future socket = rawState.socket.then((rawSocket) { + return secure(rawSocket, + context: context, + onBadCertificate: onBadCertificate, + supportedProtocols: supportedProtocols); + }); + return new ConnectionTask._( + socket: socket, onCancel: rawState._onCancel); + }); + } + + /** + * Takes an already connected [socket] and starts client side TLS + * handshake to make the communication secure. When the returned + * future completes the [RawSecureSocket] has completed the TLS + * handshake. Using this function requires that the other end of the + * connection is prepared for TLS handshake. + * + * If the [socket] already has a subscription, pass the existing + * subscription in the [subscription] parameter. The [secure] + * operation will take over the subscription by replacing the + * handlers with it own secure processing. The caller must not touch + * this subscription anymore. Passing a paused subscription is an + * error. + * + * If the [host] argument is passed it will be used as the host name + * for the TLS handshake. If [host] is not passed the host name from + * the [socket] will be used. The [host] can be either a [String] or + * an [InternetAddress]. + * + * Calling this function will _not_ cause a DNS host lookup. If the + * [host] passed is a [String] the [InternetAddress] for the + * resulting [SecureSocket] will have this passed in [host] as its + * host value and the internet address of the already connected + * socket as its address value. + * + * See [connect] for more information on the arguments. + * + */ + static Future secure(RawSocket socket, + {StreamSubscription subscription, + host, + SecurityContext context, + bool onBadCertificate(X509Certificate certificate), + List supportedProtocols}) { + socket.readEventsEnabled = false; + socket.writeEventsEnabled = false; + return _RawSecureSocket.connect( + host != null ? host : socket.address.host, socket.port, + is_server: false, + socket: socket, + subscription: subscription, + context: context, + onBadCertificate: onBadCertificate, + supportedProtocols: supportedProtocols); + } + + /** + * Takes an already connected [socket] and starts server side TLS + * handshake to make the communication secure. When the returned + * future completes the [RawSecureSocket] has completed the TLS + * handshake. Using this function requires that the other end of the + * connection is going to start the TLS handshake. + * + * If the [socket] already has a subscription, pass the existing + * subscription in the [subscription] parameter. The [secureServer] + * operation will take over the subscription by replacing the + * handlers with it own secure processing. The caller must not touch + * this subscription anymore. Passing a paused subscription is an + * error. + * + * If some of the data of the TLS handshake has already been read + * from the socket this data can be passed in the [bufferedData] + * parameter. This data will be processed before any other data + * available on the socket. + * + * See [RawSecureServerSocket.bind] for more information on the + * arguments. + * + */ + static Future secureServer( + RawSocket socket, SecurityContext context, + {StreamSubscription subscription, + List bufferedData, + bool requestClientCertificate: false, + bool requireClientCertificate: false, + List supportedProtocols}) { + socket.readEventsEnabled = false; + socket.writeEventsEnabled = false; + return _RawSecureSocket.connect(socket.address, socket.remotePort, + context: context, + is_server: true, + socket: socket, + subscription: subscription, + bufferedData: bufferedData, + requestClientCertificate: requestClientCertificate, + requireClientCertificate: requireClientCertificate, + supportedProtocols: supportedProtocols); + } + + /** + * Renegotiate an existing secure connection, renewing the session keys + * and possibly changing the connection properties. + * + * This repeats the SSL or TLS handshake, with options that allow clearing + * the session cache and requesting a client certificate. + */ + void renegotiate( + {bool useSessionCache: true, + bool requestClientCertificate: false, + bool requireClientCertificate: false}); + + /** + * Get the peer certificate for a connected RawSecureSocket. If this + * RawSecureSocket is the server end of a secure socket connection, + * [peerCertificate] will return the client certificate, or null, if no + * client certificate was received. If it is the client end, + * [peerCertificate] will return the server's certificate. + */ + X509Certificate get peerCertificate; + + /** + * The protocol which was selected during protocol negotiation. + * + * Returns null if one of the peers does not have support for ALPN, did not + * specify a list of supported ALPN protocols or there was no common + * protocol between client and server. + */ + String get selectedProtocol; +} + +/** + * X509Certificate represents an SSL certificate, with accessors to + * get the fields of the certificate. + */ +abstract class X509Certificate { + external factory X509Certificate._(); + + /// The DER encoded bytes of the certificate. + Uint8List get der; + + /// The PEM encoded String of the certificate. + String get pem; + + /// The SHA1 hash of the certificate. + Uint8List get sha1; + + String get subject; + String get issuer; + DateTime get startValidity; + DateTime get endValidity; +} + +class _FilterStatus { + bool progress = false; // The filter read or wrote data to the buffers. + bool readEmpty = true; // The read buffers and decryption filter are empty. + bool writeEmpty = true; // The write buffers and encryption filter are empty. + // These are set if a buffer changes state from empty or full. + bool readPlaintextNoLongerEmpty = false; + bool writePlaintextNoLongerFull = false; + bool readEncryptedNoLongerFull = false; + bool writeEncryptedNoLongerEmpty = false; + + _FilterStatus(); +} + +class _RawSecureSocket extends Stream + implements RawSecureSocket { + // Status states + static const int handshakeStatus = 201; + static const int connectedStatus = 202; + static const int closedStatus = 203; + + // Buffer identifiers. + // These must agree with those in the native C++ implementation. + static const int readPlaintextId = 0; + static const int writePlaintextId = 1; + static const int readEncryptedId = 2; + static const int writeEncryptedId = 3; + static const int bufferCount = 4; + + // Is a buffer identifier for an encrypted buffer? + static bool _isBufferEncrypted(int identifier) => + identifier >= readEncryptedId; + + RawSocket _socket; + final Completer<_RawSecureSocket> _handshakeComplete = + new Completer<_RawSecureSocket>(); + StreamController _controller; + Stream _stream; + StreamSubscription _socketSubscription; + List _bufferedData; + int _bufferedDataIndex = 0; + final InternetAddress address; + final bool is_server; + SecurityContext context; + final bool requestClientCertificate; + final bool requireClientCertificate; + final Function onBadCertificate; + + var _status = handshakeStatus; + bool _writeEventsEnabled = true; + bool _readEventsEnabled = true; + int _pauseCount = 0; + bool _pendingReadEvent = false; + bool _socketClosedRead = false; // The network socket is closed for reading. + bool _socketClosedWrite = false; // The network socket is closed for writing. + bool _closedRead = false; // The secure socket has fired an onClosed event. + bool _closedWrite = false; // The secure socket has been closed for writing. + // The network socket is gone. + Completer _closeCompleter = new Completer(); + _FilterStatus _filterStatus = new _FilterStatus(); + bool _connectPending = true; + bool _filterPending = false; + bool _filterActive = false; + + _SecureFilter _secureFilter = new _SecureFilter(); + String _selectedProtocol; + + static Future<_RawSecureSocket> connect( + dynamic /*String|InternetAddress*/ host, int requestedPort, + {bool is_server, + SecurityContext context, + RawSocket socket, + StreamSubscription subscription, + List bufferedData, + bool requestClientCertificate: false, + bool requireClientCertificate: false, + bool onBadCertificate(X509Certificate certificate), + List supportedProtocols}) { + _verifyFields(host, requestedPort, is_server, requestClientCertificate, + requireClientCertificate, onBadCertificate); + if (host is InternetAddress) host = host.host; + InternetAddress address = socket.address; + if (host != null) { + address = InternetAddress._cloneWithNewHost(address, host); + } + return new _RawSecureSocket( + address, + requestedPort, + is_server, + context, + socket, + subscription, + bufferedData, + requestClientCertificate, + requireClientCertificate, + onBadCertificate, + supportedProtocols) + ._handshakeComplete + .future; + } + + _RawSecureSocket( + this.address, + int requestedPort, + this.is_server, + this.context, + this._socket, + this._socketSubscription, + this._bufferedData, + this.requestClientCertificate, + this.requireClientCertificate, + this.onBadCertificate, + List supportedProtocols) { + if (context == null) { + context = SecurityContext.defaultContext; + } + _controller = new StreamController( + sync: true, + onListen: _onSubscriptionStateChange, + onPause: _onPauseStateChange, + onResume: _onPauseStateChange, + onCancel: _onSubscriptionStateChange); + _stream = _controller.stream; + // Throw an ArgumentError if any field is invalid. After this, all + // errors will be reported through the future or the stream. + _secureFilter.init(); + _secureFilter + .registerHandshakeCompleteCallback(_secureHandshakeCompleteHandler); + if (onBadCertificate != null) { + _secureFilter.registerBadCertificateCallback(_onBadCertificateWrapper); + } + _socket.readEventsEnabled = true; + _socket.writeEventsEnabled = false; + if (_socketSubscription == null) { + // If a current subscription is provided use this otherwise + // create a new one. + _socketSubscription = _socket.listen(_eventDispatcher, + onError: _reportError, onDone: _doneHandler); + } else { + if (_socketSubscription.isPaused) { + _socket.close(); + throw new ArgumentError("Subscription passed to TLS upgrade is paused"); + } + // If we are upgrading a socket that is already closed for read, + // report an error as if we received readClosed during the handshake. + dynamic s = _socket; // Cast to dynamic to avoid warning. + if (s._socket.closedReadEventSent) { + _eventDispatcher(RawSocketEvent.readClosed); + } + _socketSubscription + ..onData(_eventDispatcher) + ..onError(_reportError) + ..onDone(_doneHandler); + } + try { + var encodedProtocols = + SecurityContext._protocolsToLengthEncoding(supportedProtocols); + _secureFilter.connect( + address.host, + context, + is_server, + requestClientCertificate || requireClientCertificate, + requireClientCertificate, + encodedProtocols); + _secureHandshake(); + } catch (e, s) { + _reportError(e, s); + } + } + + StreamSubscription listen(void onData(RawSocketEvent data), + {Function onError, void onDone(), bool cancelOnError}) { + _sendWriteEvent(); + return _stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + } + + static void _verifyFields( + host, + int requestedPort, + bool is_server, + bool requestClientCertificate, + bool requireClientCertificate, + Function onBadCertificate) { + if (host is! String && host is! InternetAddress) { + throw new ArgumentError("host is not a String or an InternetAddress"); + } + if (requestedPort is! int) { + throw new ArgumentError("requestedPort is not an int"); + } + if (requestedPort < 0 || requestedPort > 65535) { + throw new ArgumentError("requestedPort is not in the range 0..65535"); + } + if (requestClientCertificate is! bool) { + throw new ArgumentError("requestClientCertificate is not a bool"); + } + if (requireClientCertificate is! bool) { + throw new ArgumentError("requireClientCertificate is not a bool"); + } + if (onBadCertificate != null && onBadCertificate is! Function) { + throw new ArgumentError("onBadCertificate is not null or a Function"); + } + } + + int get port => _socket.port; + + InternetAddress get remoteAddress => _socket.remoteAddress; + + int get remotePort => _socket.remotePort; + + void set _owner(owner) { + (_socket as dynamic)._owner = owner; + } + + int available() { + return _status != connectedStatus + ? 0 + : _secureFilter.buffers[readPlaintextId].length; + } + + Future close() { + shutdown(SocketDirection.both); + return _closeCompleter.future; + } + + void _completeCloseCompleter([RawSocket dummy]) { + if (!_closeCompleter.isCompleted) _closeCompleter.complete(this); + } + + void _close() { + _closedWrite = true; + _closedRead = true; + if (_socket != null) { + _socket.close().then(_completeCloseCompleter); + } else { + _completeCloseCompleter(); + } + _socketClosedWrite = true; + _socketClosedRead = true; + if (!_filterActive && _secureFilter != null) { + _secureFilter.destroy(); + _secureFilter = null; + } + if (_socketSubscription != null) { + _socketSubscription.cancel(); + } + _controller.close(); + _status = closedStatus; + } + + void shutdown(SocketDirection direction) { + if (direction == SocketDirection.send || + direction == SocketDirection.both) { + _closedWrite = true; + if (_filterStatus.writeEmpty) { + _socket.shutdown(SocketDirection.send); + _socketClosedWrite = true; + if (_closedRead) { + _close(); + } + } + } + if (direction == SocketDirection.receive || + direction == SocketDirection.both) { + _closedRead = true; + _socketClosedRead = true; + _socket.shutdown(SocketDirection.receive); + if (_socketClosedWrite) { + _close(); + } + } + } + + bool get writeEventsEnabled => _writeEventsEnabled; + + void set writeEventsEnabled(bool value) { + _writeEventsEnabled = value; + if (value) { + Timer.run(() => _sendWriteEvent()); + } + } + + bool get readEventsEnabled => _readEventsEnabled; + + void set readEventsEnabled(bool value) { + _readEventsEnabled = value; + _scheduleReadEvent(); + } + + List read([int length]) { + if (length != null && (length is! int || length < 0)) { + throw new ArgumentError( + "Invalid length parameter in SecureSocket.read (length: $length)"); + } + if (_closedRead) { + throw new SocketException("Reading from a closed socket"); + } + if (_status != connectedStatus) { + return null; + } + var result = _secureFilter.buffers[readPlaintextId].read(length); + _scheduleFilter(); + return result; + } + + // Write the data to the socket, and schedule the filter to encrypt it. + int write(List data, [int offset, int bytes]) { + if (bytes != null && (bytes is! int || bytes < 0)) { + throw new ArgumentError( + "Invalid bytes parameter in SecureSocket.read (bytes: $bytes)"); + } + if (offset != null && (offset is! int || offset < 0)) { + throw new ArgumentError( + "Invalid offset parameter in SecureSocket.read (offset: $offset)"); + } + if (_closedWrite) { + _controller.addError(new SocketException("Writing to a closed socket")); + return 0; + } + if (_status != connectedStatus) return 0; + if (offset == null) offset = 0; + if (bytes == null) bytes = data.length - offset; + + int written = + _secureFilter.buffers[writePlaintextId].write(data, offset, bytes); + if (written > 0) { + _filterStatus.writeEmpty = false; + } + _scheduleFilter(); + return written; + } + + X509Certificate get peerCertificate => _secureFilter.peerCertificate; + + String get selectedProtocol => _selectedProtocol; + + bool _onBadCertificateWrapper(X509Certificate certificate) { + if (onBadCertificate == null) return false; + var result = onBadCertificate(certificate); + if (result is bool) return result; + throw new HandshakeException( + "onBadCertificate callback returned non-boolean $result"); + } + + bool setOption(SocketOption option, bool enabled) { + if (_socket == null) return false; + return _socket.setOption(option, enabled); + } + + void _eventDispatcher(RawSocketEvent event) { + try { + if (event == RawSocketEvent.read) { + _readHandler(); + } else if (event == RawSocketEvent.write) { + _writeHandler(); + } else if (event == RawSocketEvent.readClosed) { + _closeHandler(); + } + } catch (e, stackTrace) { + _reportError(e, stackTrace); + } + } + + void _readHandler() { + _readSocket(); + _scheduleFilter(); + } + + void _writeHandler() { + _writeSocket(); + _scheduleFilter(); + } + + void _doneHandler() { + if (_filterStatus.readEmpty) { + _close(); + } + } + + void _reportError(e, [StackTrace stackTrace]) { + if (_status == closedStatus) { + return; + } else if (_connectPending) { + // _connectPending is true until the handshake has completed, and the + // _handshakeComplete future returned from SecureSocket.connect has + // completed. Before this point, we must complete it with an error. + _handshakeComplete.completeError(e, stackTrace); + } else { + _controller.addError(e, stackTrace); + } + _close(); + } + + void _closeHandler() { + if (_status == connectedStatus) { + if (_closedRead) return; + _socketClosedRead = true; + if (_filterStatus.readEmpty) { + _closedRead = true; + _controller.add(RawSocketEvent.readClosed); + if (_socketClosedWrite) { + _close(); + } + } else { + _scheduleFilter(); + } + } else if (_status == handshakeStatus) { + _socketClosedRead = true; + if (_filterStatus.readEmpty) { + _reportError( + new HandshakeException('Connection terminated during handshake'), + null); + } else { + _secureHandshake(); + } + } + } + + void _secureHandshake() { + try { + _secureFilter.handshake(); + _filterStatus.writeEmpty = false; + _readSocket(); + _writeSocket(); + _scheduleFilter(); + } catch (e, stackTrace) { + _reportError(e, stackTrace); + } + } + + void renegotiate( + {bool useSessionCache: true, + bool requestClientCertificate: false, + bool requireClientCertificate: false}) { + if (_status != connectedStatus) { + throw new HandshakeException( + "Called renegotiate on a non-connected socket"); + } + _secureFilter.renegotiate( + useSessionCache, requestClientCertificate, requireClientCertificate); + _status = handshakeStatus; + _filterStatus.writeEmpty = false; + _scheduleFilter(); + } + + void _secureHandshakeCompleteHandler() { + _status = connectedStatus; + if (_connectPending) { + _connectPending = false; + try { + _selectedProtocol = _secureFilter.selectedProtocol(); + // We don't want user code to run synchronously in this callback. + Timer.run(() => _handshakeComplete.complete(this)); + } catch (error, stack) { + _handshakeComplete.completeError(error, stack); + } + } + } + + void _onPauseStateChange() { + if (_controller.isPaused) { + _pauseCount++; + } else { + _pauseCount--; + if (_pauseCount == 0) { + _scheduleReadEvent(); + _sendWriteEvent(); // Can send event synchronously. + } + } + + if (!_socketClosedRead || !_socketClosedWrite) { + if (_controller.isPaused) { + _socketSubscription.pause(); + } else { + _socketSubscription.resume(); + } + } + } + + void _onSubscriptionStateChange() { + if (_controller.hasListener) { + // TODO(ajohnsen): Do something here? + } + } + + void _scheduleFilter() { + _filterPending = true; + _tryFilter(); + } + + void _tryFilter() { + if (_status == closedStatus) { + return; + } + if (_filterPending && !_filterActive) { + _filterActive = true; + _filterPending = false; + _pushAllFilterStages().then((status) { + _filterStatus = status; + _filterActive = false; + if (_status == closedStatus) { + _secureFilter.destroy(); + _secureFilter = null; + return; + } + _socket.readEventsEnabled = true; + if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) { + // Checks for and handles all cases of partially closed sockets. + shutdown(SocketDirection.send); + if (_status == closedStatus) { + return; + } + } + if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) { + if (_status == handshakeStatus) { + _secureFilter.handshake(); + if (_status == handshakeStatus) { + throw new HandshakeException( + 'Connection terminated during handshake'); + } + } + _closeHandler(); + } + if (_status == closedStatus) { + return; + } + if (_filterStatus.progress) { + _filterPending = true; + if (_filterStatus.writeEncryptedNoLongerEmpty) { + _writeSocket(); + } + if (_filterStatus.writePlaintextNoLongerFull) { + _sendWriteEvent(); + } + if (_filterStatus.readEncryptedNoLongerFull) { + _readSocket(); + } + if (_filterStatus.readPlaintextNoLongerEmpty) { + _scheduleReadEvent(); + } + if (_status == handshakeStatus) { + _secureHandshake(); + } + } + _tryFilter(); + }).catchError(_reportError); + } + } + + List _readSocketOrBufferedData(int bytes) { + if (_bufferedData != null) { + if (bytes > _bufferedData.length - _bufferedDataIndex) { + bytes = _bufferedData.length - _bufferedDataIndex; + } + var result = + _bufferedData.sublist(_bufferedDataIndex, _bufferedDataIndex + bytes); + _bufferedDataIndex += bytes; + if (_bufferedData.length == _bufferedDataIndex) { + _bufferedData = null; + } + return result; + } else if (!_socketClosedRead) { + return _socket.read(bytes); + } else { + return null; + } + } + + void _readSocket() { + if (_status == closedStatus) return; + var buffer = _secureFilter.buffers[readEncryptedId]; + if (buffer.writeFromSource(_readSocketOrBufferedData) > 0) { + _filterStatus.readEmpty = false; + } else { + _socket.readEventsEnabled = false; + } + } + + void _writeSocket() { + if (_socketClosedWrite) return; + var buffer = _secureFilter.buffers[writeEncryptedId]; + if (buffer.readToSocket(_socket)) { + // Returns true if blocked + _socket.writeEventsEnabled = true; + } + } + + // If a read event should be sent, add it to the controller. + _scheduleReadEvent() { + if (!_pendingReadEvent && + _readEventsEnabled && + _pauseCount == 0 && + _secureFilter != null && + !_secureFilter.buffers[readPlaintextId].isEmpty) { + _pendingReadEvent = true; + Timer.run(_sendReadEvent); + } + } + + _sendReadEvent() { + _pendingReadEvent = false; + if (_status != closedStatus && + _readEventsEnabled && + _pauseCount == 0 && + _secureFilter != null && + !_secureFilter.buffers[readPlaintextId].isEmpty) { + _controller.add(RawSocketEvent.read); + _scheduleReadEvent(); + } + } + + // If a write event should be sent, add it to the controller. + _sendWriteEvent() { + if (!_closedWrite && + _writeEventsEnabled && + _pauseCount == 0 && + _secureFilter != null && + _secureFilter.buffers[writePlaintextId].free > 0) { + _writeEventsEnabled = false; + _controller.add(RawSocketEvent.write); + } + } + + Future<_FilterStatus> _pushAllFilterStages() { + bool wasInHandshake = _status != connectedStatus; + List args = new List(2 + bufferCount * 2); + args[0] = _secureFilter._pointer(); + args[1] = wasInHandshake; + var bufs = _secureFilter.buffers; + for (var i = 0; i < bufferCount; ++i) { + args[2 * i + 2] = bufs[i].start; + args[2 * i + 3] = bufs[i].end; + } + + return _IOService._dispatch(_IOService.sslProcessFilter, args) + .then((response) { + if (response.length == 2) { + if (wasInHandshake) { + // If we're in handshake, throw a handshake error. + _reportError( + new HandshakeException('${response[1]} error ${response[0]}'), + null); + } else { + // If we're connected, throw a TLS error. + _reportError( + new TlsException('${response[1]} error ${response[0]}'), null); + } + } + int start(int index) => response[2 * index]; + int end(int index) => response[2 * index + 1]; + + _FilterStatus status = new _FilterStatus(); + // Compute writeEmpty as "write plaintext buffer and write encrypted + // buffer were empty when we started and are empty now". + status.writeEmpty = bufs[writePlaintextId].isEmpty && + start(writeEncryptedId) == end(writeEncryptedId); + // If we were in handshake when this started, _writeEmpty may be false + // because the handshake wrote data after we checked. + if (wasInHandshake) status.writeEmpty = false; + + // Compute readEmpty as "both read buffers were empty when we started + // and are empty now". + status.readEmpty = bufs[readEncryptedId].isEmpty && + start(readPlaintextId) == end(readPlaintextId); + + _ExternalBuffer buffer = bufs[writePlaintextId]; + int new_start = start(writePlaintextId); + if (new_start != buffer.start) { + status.progress = true; + if (buffer.free == 0) { + status.writePlaintextNoLongerFull = true; + } + buffer.start = new_start; + } + buffer = bufs[readEncryptedId]; + new_start = start(readEncryptedId); + if (new_start != buffer.start) { + status.progress = true; + if (buffer.free == 0) { + status.readEncryptedNoLongerFull = true; + } + buffer.start = new_start; + } + buffer = bufs[writeEncryptedId]; + int new_end = end(writeEncryptedId); + if (new_end != buffer.end) { + status.progress = true; + if (buffer.length == 0) { + status.writeEncryptedNoLongerEmpty = true; + } + buffer.end = new_end; + } + buffer = bufs[readPlaintextId]; + new_end = end(readPlaintextId); + if (new_end != buffer.end) { + status.progress = true; + if (buffer.length == 0) { + status.readPlaintextNoLongerEmpty = true; + } + buffer.end = new_end; + } + return status; + }); + } +} + +/** + * A circular buffer backed by an external byte array. Accessed from + * both C++ and Dart code in an unsynchronized way, with one reading + * and one writing. All updates to start and end are done by Dart code. + */ +class _ExternalBuffer { + // This will be an ExternalByteArray, backed by C allocated data. + List data; + int start; + int end; + final size; + + _ExternalBuffer(this.size) { + start = end = size ~/ 2; + } + + void advanceStart(int bytes) { + assert(start > end || start + bytes <= end); + start += bytes; + if (start >= size) { + start -= size; + assert(start <= end); + assert(start < size); + } + } + + void advanceEnd(int bytes) { + assert(start <= end || start > end + bytes); + end += bytes; + if (end >= size) { + end -= size; + assert(end < start); + assert(end < size); + } + } + + bool get isEmpty => end == start; + + int get length => start > end ? size + end - start : end - start; + + int get linearLength => start > end ? size - start : end - start; + + int get free => start > end ? start - end - 1 : size + start - end - 1; + + int get linearFree { + if (start > end) return start - end - 1; + if (start == 0) return size - end - 1; + return size - end; + } + + List read(int bytes) { + if (bytes == null) { + bytes = length; + } else { + bytes = min(bytes, length); + } + if (bytes == 0) return null; + List result = new Uint8List(bytes); + int bytesRead = 0; + // Loop over zero, one, or two linear data ranges. + while (bytesRead < bytes) { + int toRead = min(bytes - bytesRead, linearLength); + result.setRange(bytesRead, bytesRead + toRead, data, start); + advanceStart(toRead); + bytesRead += toRead; + } + return result; + } + + int write(List inputData, int offset, int bytes) { + if (bytes > free) { + bytes = free; + } + int written = 0; + int toWrite = min(bytes, linearFree); + // Loop over zero, one, or two linear data ranges. + while (toWrite > 0) { + data.setRange(end, end + toWrite, inputData, offset); + advanceEnd(toWrite); + offset += toWrite; + written += toWrite; + toWrite = min(bytes - written, linearFree); + } + return written; + } + + int writeFromSource(List getData(int requested)) { + int written = 0; + int toWrite = linearFree; + // Loop over zero, one, or two linear data ranges. + while (toWrite > 0) { + // Source returns at most toWrite bytes, and it returns null when empty. + var inputData = getData(toWrite); + if (inputData == null || inputData.length == 0) break; + var len = inputData.length; + data.setRange(end, end + len, inputData); + advanceEnd(len); + written += len; + toWrite = linearFree; + } + return written; + } + + bool readToSocket(RawSocket socket) { + // Loop over zero, one, or two linear data ranges. + while (true) { + var toWrite = linearLength; + if (toWrite == 0) return false; + int bytes = socket.write(data, start, toWrite); + advanceStart(bytes); + if (bytes < toWrite) { + // The socket has blocked while we have data to write. + return true; + } + } + } +} + +abstract class _SecureFilter { + external factory _SecureFilter(); + + void connect( + String hostName, + SecurityContext context, + bool is_server, + bool requestClientCertificate, + bool requireClientCertificate, + Uint8List protocols); + void destroy(); + void handshake(); + String selectedProtocol(); + void rehandshake(); + void renegotiate(bool useSessionCache, bool requestClientCertificate, + bool requireClientCertificate); + void init(); + X509Certificate get peerCertificate; + int processBuffer(int bufferIndex); + void registerBadCertificateCallback(Function callback); + void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); + + // This call may cause a reference counted pointer in the native + // implementation to be retained. It should only be called when the resulting + // value is passed to the IO service through a call to dispatch(). + int _pointer(); + + List<_ExternalBuffer> get buffers; +} + +/** A secure networking exception caused by a failure in the + * TLS/SSL protocol. + */ +class TlsException implements IOException { + final String type; + final String message; + final OSError osError; + + const TlsException([String message = "", OSError osError = null]) + : this._("TlsException", message, osError); + + const TlsException._(this.type, this.message, this.osError); + + String toString() { + StringBuffer sb = new StringBuffer(); + sb.write(type); + if (!message.isEmpty) { + sb.write(": $message"); + if (osError != null) { + sb.write(" ($osError)"); + } + } else if (osError != null) { + sb.write(": $osError"); + } + return sb.toString(); + } +} + +/** + * An exception that happens in the handshake phase of establishing + * a secure network connection. + */ +class HandshakeException extends TlsException { + const HandshakeException([String message = "", OSError osError = null]) + : super._("HandshakeException", message, osError); +} + +/** + * An exception that happens in the handshake phase of establishing + * a secure network connection, when looking up or verifying a + * certificate. + */ +class CertificateException extends TlsException { + const CertificateException([String message = "", OSError osError = null]) + : super._("CertificateException", message, osError); +} +NN<JB?0>HEB7GK?NH7<0JOL:PPJJ26 :'/04=CIK :*404$N19DC?G/C>C?GGGF?DB":4 =D/AN/=DC?G5C>EDCB?,.,,*D/PN&>>3=ECJ@='GNG)J6M<#,.F:;N*5EK=6GIFIQHGFNH7<3JOL=9 :'$6M-I-IEM >,)& 9$$#4F5 !3'$---&0# +0- 1 6,!*4+ !<NA&FJ79K<NO.$5L(H4?00'"C6'/0 +*27##2#"LJK7 +& %4" +- %N +!(##,/&$;N&+ >J<8  <5"%&&#,#,- '#  +*OK*) +L,'.,=  +' +&!; : 9 :" , +#3!?;Q#8%" )9A' )$:(!)?!; !#!;,@!<#-16/(&,'%C"=M4N +352K?< keyBytes, {String password}); + + /** + * Sets the set of trusted X509 certificates used by [SecureSocket] + * client connections, when connecting to a secure server. + * + * [file] is the path to a PEM or PKCS12 file containing X509 certificates, + * usually root certificates from certificate authorities. For PKCS12 files, + * [password] is the password for the file. For PEM files, [password] is + * ignored. Assuming it is well-formatted, all other contents of [file] are + * ignored. + * + * NB: This function calls [File.readAsBytesSync], and will block on file IO. + * Prefer using [setTrustedCertificatesBytes]. + * + * iOS note: On iOS, this call takes only the bytes for a single DER + * encoded X509 certificate. It may be called multiple times to add + * multiple trusted certificates to the context. A DER encoded certificate + * can be obtained from a PEM encoded certificate by using the openssl tool: + * + * $ openssl x509 -outform der -in cert.pem -out cert.der + */ + void setTrustedCertificates(String file, {String password}); + + /** + * Sets the set of trusted X509 certificates used by [SecureSocket] + * client connections, when connecting to a secure server. + * + * Like [setTrustedCertificates] but takes the contents of the file. + */ + void setTrustedCertificatesBytes(List certBytes, {String password}); + + /** + * Sets the chain of X509 certificates served by [SecureServerSocket] + * when making secure connections, including the server certificate. + * + * [file] is a PEM or PKCS12 file containing X509 certificates, starting with + * the root authority and intermediate authorities forming the signed + * chain to the server certificate, and ending with the server certificate. + * The private key for the server certificate is set by [usePrivateKey]. For + * PKCS12 files, [password] is the password for the file. For PEM files, + * [password] is ignored. Assuming it is well-formatted, all + * other contents of [file] are ignored. + * + * NB: This function calls [File.readAsBytesSync], and will block on file IO. + * Prefer using [useCertificateChainBytes]. + * + * iOS note: As noted above, [usePrivateKey] does the job of both + * that call and this one. On iOS, this call is a no-op. + */ + void useCertificateChain(String file, {String password}); + + /** + * Sets the chain of X509 certificates served by [SecureServerSocket] + * when making secure connections, including the server certificate. + * + * Like [useCertificateChain] but takes the contents of the file. + */ + void useCertificateChainBytes(List chainBytes, {String password}); + + /** + * Sets the list of authority names that a [SecureServerSocket] will advertise + * as accepted when requesting a client certificate from a connecting + * client. + * + * [file] is a PEM or PKCS12 file containing the accepted signing + * authority certificates - the authority names are extracted from the + * certificates. For PKCS12 files, [password] is the password for the file. + * For PEM files, [password] is ignored. Assuming it is well-formatted, all + * other contents of [file] are ignored. + * + * NB: This function calls [File.readAsBytesSync], and will block on file IO. + * Prefer using [setClientAuthoritiesBytes]. + * + * iOS note: This call is not supported. + */ + void setClientAuthorities(String file, {String password}); + + /** + * Sets the list of authority names that a [SecureServerSocket] will advertise + * as accepted, when requesting a client certificate from a connecting + * client. + * + * Like [setClientAuthorities] but takes the contents of the file. + */ + void setClientAuthoritiesBytes(List authCertBytes, {String password}); + + /** + * Whether the platform supports ALPN. This always returns true and will be + * removed in a future release. + */ + @deprecated + external static bool get alpnSupported; + + /** + * Sets the list of application-level protocols supported by a client + * connection or server connection. The ALPN (application level protocol + * negotiation) extension to TLS allows a client to send a list of + * protocols in the TLS client hello message, and the server to pick + * one and send the selected one back in its server hello message. + * + * Separate lists of protocols can be sent for client connections and + * for server connections, using the same SecurityContext. The [isServer] + * boolean argument specifies whether to set the list for server connections + * or client connections. + */ + void setAlpnProtocols(List protocols, bool isServer); + + /// Encodes a set of supported protocols for ALPN/NPN usage. + /// + /// The `protocols` list is expected to contain protocols in descending order + /// of preference. + /// + /// See RFC 7301 (https://tools.ietf.org/html/rfc7301) for the encoding of + /// `List protocols`: + /// opaque ProtocolName<1..2^8-1>; + /// + /// struct { + /// ProtocolName protocol_name_list<2..2^16-1> + /// } ProtocolNameList; + /// + /// The encoding of the opaque `ProtocolName` vector is + /// described in RFC 2246: 4.3 Vectors. + /// + /// Note: Even though this encoding scheme would allow a total + /// `ProtocolNameList` length of 65535, this limit cannot be reached. Testing + /// showed that more than ~ 2^14 bytes will fail to negotiate a protocol. + /// We will be conservative and support only messages up to (1<<13)-1 bytes. + static Uint8List _protocolsToLengthEncoding(List protocols) { + if (protocols == null || protocols.length == 0) { + return new Uint8List(0); + } + int protocolsLength = protocols.length; + + // Calculate the number of bytes we will need if it is ASCII. + int expectedLength = protocolsLength; + for (int i = 0; i < protocolsLength; i++) { + int length = protocols[i].length; + if (length > 0 && length <= 255) { + expectedLength += length; + } else { + throw new ArgumentError( + 'Length of protocol must be between 1 and 255 (was: $length).'); + } + } + + if (expectedLength >= (1 << 13)) { + throw new ArgumentError( + 'The maximum message length supported is 2^13-1.'); + } + + // Try encoding the `List protocols` array using fast ASCII path. + var bytes = new Uint8List(expectedLength); + int bytesOffset = 0; + for (int i = 0; i < protocolsLength; i++) { + String proto = protocols[i]; + + // Add length byte. + bytes[bytesOffset++] = proto.length; + int bits = 0; + + // Add protocol bytes. + for (int j = 0; j < proto.length; j++) { + var char = proto.codeUnitAt(j); + bits |= char; + bytes[bytesOffset++] = char & 0xff; + } + + // Go slow case if we have encountered anything non-ascii. + if (bits > 0x7f) { + return _protocolsToLengthEncodingNonAsciiBailout(protocols); + } + } + return bytes; + } + + static Uint8List _protocolsToLengthEncodingNonAsciiBailout( + List protocols) { + void addProtocol(List outBytes, String protocol) { + var protocolBytes = utf8.encode(protocol); + var len = protocolBytes.length; + + if (len > 255) { + throw new ArgumentError( + 'Length of protocol must be between 1 and 255 (was: $len)'); + } + // Add length byte. + outBytes.add(len); + + // Add protocol bytes. + outBytes.addAll(protocolBytes); + } + + List bytes = []; + for (var i = 0; i < protocols.length; i++) { + addProtocol(bytes, protocols[i]); + } + + if (bytes.length >= (1 << 13)) { + throw new ArgumentError( + 'The maximum message length supported is 2^13-1.'); + } + + return new Uint8List.fromList(bytes); + } +} +NN<?=.O5KOJ8!&Q>NMFHOPDDB?;CNJL'6JKDHPLP(QQD6JHBF=NOKNP1GFMO>?F=GLHGPHNOK?+P.D;<HGDJQH DINN+P/+=QI ENN"*HKEGEHMO@?PM )9H*APMOH6,B*0()"!M'>N/0#+/(,AE> <1&!I&1(%>*Rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/service_object.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +int _nextServiceId = 1; + +// TODO(ajohnsen): Use other way of getting a unique id. +abstract class _ServiceObject { + int __serviceId = 0; + int get _serviceId { + if (__serviceId == 0) __serviceId = _nextServiceId++; + return __serviceId; + } + + Map _toJSON(bool ref); + + String get _servicePath => "$_serviceTypePath/$_serviceId"; + + String get _serviceTypePath; + + String get _serviceTypeName; + + String _serviceType(bool ref) { + if (ref) return "@$_serviceTypeName"; + return _serviceTypeName; + } +} +NN<9 :>"*Jfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/socket.dartkC// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * [InternetAddressType] is the type an [InternetAddress]. Currently, + * IP version 4 (IPv4) and IP version 6 (IPv6) are supported. + */ +class InternetAddressType { + static const InternetAddressType IPv4 = const InternetAddressType._(0); + static const InternetAddressType IPv6 = const InternetAddressType._(1); + static const InternetAddressType any = const InternetAddressType._(-1); + + @Deprecated("Use IPv4 instead") + static const InternetAddressType IP_V4 = IPv4; + @Deprecated("Use IPv6 instead") + static const InternetAddressType IP_V6 = IPv6; + @Deprecated("Use any instead") + static const InternetAddressType ANY = any; + + final int _value; + + const InternetAddressType._(this._value); + + factory InternetAddressType._from(int value) { + if (value == 0) return IPv4; + if (value == 1) return IPv6; + throw new ArgumentError("Invalid type: $value"); + } + + /** + * Get the name of the type, e.g. "IPv4" or "IPv6". + */ + String get name { + switch (_value) { + case -1: + return "ANY"; + case 0: + return "IPv4"; + case 1: + return "IPv6"; + default: + throw new ArgumentError("Invalid InternetAddress"); + } + } + + String toString() => "InternetAddressType: $name"; +} + +/** + * An internet address. + * + * This object holds an internet address. If this internet address + * is the result of a DNS lookup, the address also holds the hostname + * used to make the lookup. + * An Internet address combined with a port number represents an + * endpoint to which a socket can connect or a listening socket can + * bind. + */ +abstract class InternetAddress { + /** + * IP version 4 loopback address. Use this address when listening on + * or connecting to the loopback adapter using IP version 4 (IPv4). + */ + static InternetAddress get loopbackIPv4 => LOOPBACK_IP_V4; + @Deprecated("Use loopbackIPv4 instead") + external static InternetAddress get LOOPBACK_IP_V4; + + /** + * IP version 6 loopback address. Use this address when listening on + * or connecting to the loopback adapter using IP version 6 (IPv6). + */ + static InternetAddress get loopbackIPv6 => LOOPBACK_IP_V6; + @Deprecated("Use loopbackIPv6 instead") + external static InternetAddress get LOOPBACK_IP_V6; + + /** + * IP version 4 any address. Use this address when listening on + * all adapters IP addresses using IP version 4 (IPv4). + */ + static InternetAddress get anyIPv4 => ANY_IP_V4; + @Deprecated("Use anyIPv4 instead") + external static InternetAddress get ANY_IP_V4; + + /** + * IP version 6 any address. Use this address when listening on + * all adapters IP addresses using IP version 6 (IPv6). + */ + static InternetAddress get anyIPv6 => ANY_IP_V6; + @Deprecated("Use anyIPv6 instead") + external static InternetAddress get ANY_IP_V6; + + /** + * The [type] of the [InternetAddress] specified what IP protocol. + */ + InternetAddressType get type; + + /** + * The numeric address of the host. For IPv4 addresses this is using + * the dotted-decimal notation. For IPv6 it is using the + * hexadecimal representation. + */ + String get address; + + /** + * The host used to lookup the address. If there is no host + * associated with the address this returns the numeric address. + */ + String get host; + + /** + * Get the raw address of this [InternetAddress]. The result is either a + * 4 or 16 byte long list. The returned list is a copy, making it possible + * to change the list without modifying the [InternetAddress]. + */ + List get rawAddress; + + /** + * Returns true if the [InternetAddress] is a loopback address. + */ + bool get isLoopback; + + /** + * Returns true if the [InternetAddress]s scope is a link-local. + */ + bool get isLinkLocal; + + /** + * Returns true if the [InternetAddress]s scope is multicast. + */ + bool get isMulticast; + + /** + * Creates a new [InternetAddress] from a numeric address. + * + * If the address in [address] is not a numeric IPv4 + * (dotted-decimal notation) or IPv6 (hexadecimal representation). + * address [ArgumentError] is thrown. + */ + external factory InternetAddress(String address); + + /** + * Perform a reverse dns lookup on the [address], creating a new + * [InternetAddress] where the host field set to the result. + */ + Future reverse(); + + /** + * Lookup a host, returning a Future of a list of + * [InternetAddress]s. If [type] is [InternetAddressType.ANY], it + * will lookup both IP version 4 (IPv4) and IP version 6 (IPv6) + * addresses. If [type] is either [InternetAddressType.IPv4] or + * [InternetAddressType.IPv6] it will only lookup addresses of the + * specified type. The order of the list can, and most likely will, + * change over time. + */ + external static Future> lookup(String host, + {InternetAddressType type: InternetAddressType.any}); + + /** + * Clones the given [address] with the new [host]. + * + * The [address] must be an [InternetAddress] that was created with one + * of the static methods of this class. + */ + external static InternetAddress _cloneWithNewHost( + InternetAddress address, String host); +} + +/** + * A [NetworkInterface] represents an active network interface on the current + * system. It contains a list of [InternetAddress]es that are bound to the + * interface. + */ +abstract class NetworkInterface { + /** + * Get the name of the [NetworkInterface]. + */ + String get name; + + /** + * Get the index of the [NetworkInterface]. + */ + int get index; + + /** + * Get a list of [InternetAddress]es currently bound to this + * [NetworkInterface]. + */ + List get addresses; + + /** + * Whether [list] is supported. + * + * [list] is currently unsupported on Android. + */ + external static bool get listSupported; + + /** + * Query the system for [NetworkInterface]s. + * + * If [includeLoopback] is `true`, the returned list will include the + * loopback device. Default is `false`. + * + * If [includeLinkLocal] is `true`, the list of addresses of the returned + * [NetworkInterface]s, may include link local addresses. Default is `false`. + * + * If [type] is either [InternetAddressType.IPv4] or + * [InternetAddressType.IPv6] it will only lookup addresses of the + * specified type. Default is [InternetAddressType.any]. + */ + external static Future> list( + {bool includeLoopback: false, + bool includeLinkLocal: false, + InternetAddressType type: InternetAddressType.any}); +} + +/** + * A [RawServerSocket] represents a listening socket, and provides a + * stream of low-level [RawSocket] objects, one for each connection + * made to the listening socket. + * + * See [RawSocket] for more info. + */ +abstract class RawServerSocket implements Stream { + /** + * Returns a future for a [:RawServerSocket:]. When the future + * completes the server socket is bound to the given [address] and + * [port] and has started listening on it. + * + * The [address] can either be a [String] or an + * [InternetAddress]. If [address] is a [String], [bind] will + * perform a [InternetAddress.lookup] and use the first value in the + * list. To listen on the loopback adapter, which will allow only + * incoming connections from the local host, use the value + * [InternetAddress.loopbackIPv4] or + * [InternetAddress.loopbackIPv6]. To allow for incoming + * connection from the network use either one of the values + * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to + * bind to all interfaces or the IP address of a specific interface. + * + * If an IP version 6 (IPv6) address is used, both IP version 6 + * (IPv6) and version 4 (IPv4) connections will be accepted. To + * restrict this to version 6 (IPv6) only, use [v6Only] to set + * version 6 only. + * + * If [port] has the value [:0:] an ephemeral port will + * be chosen by the system. The actual port used can be retrieved + * using the [:port:] getter. + * + * The optional argument [backlog] can be used to specify the listen + * backlog for the underlying OS listen setup. If [backlog] has the + * value of [:0:] (the default) a reasonable value will be chosen by + * the system. + * + * The optional argument [shared] specifies whether additional RawServerSocket + * objects can bind to the same combination of `address`, `port` and `v6Only`. + * If `shared` is `true` and more `RawServerSocket`s from this isolate or + * other isolates are bound to the port, then the incoming connections will be + * distributed among all the bound `RawServerSocket`s. Connections can be + * distributed over multiple isolates this way. + */ + external static Future bind(address, int port, + {int backlog: 0, bool v6Only: false, bool shared: false}); + + /** + * Returns the port used by this socket. + */ + int get port; + + /** + * Returns the address used by this socket. + */ + InternetAddress get address; + + /** + * Closes the socket. The returned future completes when the socket + * is fully closed and is no longer bound. + */ + Future close(); +} + +/** + * A [ServerSocket] represents a listening socket, and provides a + * stream of [Socket] objects, one for each connection made to the + * listening socket. + * + * See [Socket] for more info. + */ +abstract class ServerSocket implements Stream { + /** + * Returns a future for a [:ServerSocket:]. When the future + * completes the server socket is bound to the given [address] and + * [port] and has started listening on it. + * + * The [address] can either be a [String] or an + * [InternetAddress]. If [address] is a [String], [bind] will + * perform a [InternetAddress.lookup] and use the first value in the + * list. To listen on the loopback adapter, which will allow only + * incoming connections from the local host, use the value + * [InternetAddress.loopbackIPv4] or + * [InternetAddress.loopbackIPv6]. To allow for incoming + * connection from the network use either one of the values + * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to + * bind to all interfaces or the IP address of a specific interface. + * + * If an IP version 6 (IPv6) address is used, both IP version 6 + * (IPv6) and version 4 (IPv4) connections will be accepted. To + * restrict this to version 6 (IPv6) only, use [v6Only] to set + * version 6 only. + * + * If [port] has the value [:0:] an ephemeral port will be chosen by + * the system. The actual port used can be retrieved using the + * [port] getter. + * + * The optional argument [backlog] can be used to specify the listen + * backlog for the underlying OS listen setup. If [backlog] has the + * value of [:0:] (the default) a reasonable value will be chosen by + * the system. + * + * The optional argument [shared] specifies whether additional ServerSocket + * objects can bind to the same combination of `address`, `port` and `v6Only`. + * If `shared` is `true` and more `ServerSocket`s from this isolate or other + * isolates are bound to the port, then the incoming connections will be + * distributed among all the bound `ServerSocket`s. Connections can be + * distributed over multiple isolates this way. + */ + external static Future bind(address, int port, + {int backlog: 0, bool v6Only: false, bool shared: false}); + + /** + * Returns the port used by this socket. + */ + int get port; + + /** + * Returns the address used by this socket. + */ + InternetAddress get address; + + /** + * Closes the socket. The returned future completes when the socket + * is fully closed and is no longer bound. + */ + Future close(); +} + +/** + * The [SocketDirection] is used as a parameter to [Socket.close] and + * [RawSocket.close] to close a socket in the specified direction(s). + */ +class SocketDirection { + static const SocketDirection receive = const SocketDirection._(0); + static const SocketDirection send = const SocketDirection._(1); + static const SocketDirection both = const SocketDirection._(2); + + @Deprecated("Use receive instead") + static const SocketDirection RECEIVE = receive; + @Deprecated("Use send instead") + static const SocketDirection SEND = send; + @Deprecated("Use both instead") + static const SocketDirection BOTH = both; + + final _value; + + const SocketDirection._(this._value); +} + +/** + * The [SocketOption] is used as a parameter to [Socket.setOption] and + * [RawSocket.setOption] to set customize the behaviour of the underlying + * socket. + */ +class SocketOption { + /** + * Enable or disable no-delay on the socket. If tcpNoDelay is enabled, the + * socket will not buffer data internally, but instead write each data chunk + * as an individual TCP packet. + * + * tcpNoDelay is disabled by default. + */ + static const SocketOption tcpNoDelay = const SocketOption._(0); + @Deprecated("Use tcpNoDelay instead") + static const SocketOption TCP_NODELAY = tcpNoDelay; + + static const SocketOption _ipMulticastLoop = const SocketOption._(1); + static const SocketOption _ipMulticastHops = const SocketOption._(2); + static const SocketOption _ipMulticastIf = const SocketOption._(3); + static const SocketOption _ipBroadcast = const SocketOption._(4); + + final _value; + + const SocketOption._(this._value); +} + +/** + * Events for the [RawSocket]. + */ +class RawSocketEvent { + static const RawSocketEvent read = const RawSocketEvent._(0); + static const RawSocketEvent write = const RawSocketEvent._(1); + static const RawSocketEvent readClosed = const RawSocketEvent._(2); + static const RawSocketEvent closed = const RawSocketEvent._(3); + + @Deprecated("Use read instead") + static const RawSocketEvent READ = read; + @Deprecated("Use write instead") + static const RawSocketEvent WRITE = write; + @Deprecated("Use readClosed instead") + static const RawSocketEvent READ_CLOSED = readClosed; + @Deprecated("Use closed instead") + static const RawSocketEvent CLOSED = closed; + + final int _value; + + const RawSocketEvent._(this._value); + String toString() { + return const [ + 'RawSocketEvent.read', + 'RawSocketEvent.write', + 'RawSocketEvent.readClosed', + 'RawSocketEvent.closed' + ][_value]; + } +} + +/// Returned by the `startConnect` methods on client-side socket types `S`, +/// `ConnectionTask` allows cancelling an attempt to connect to a host. +class ConnectionTask { + /// A `Future` that completes with value that `S.connect()` would return + /// unless [cancel] is called on this [ConnectionTask]. + /// + /// If [cancel] is called, the `Future` completes with a [SocketException] + /// error whose message indicates that the connection attempt was cancelled. + final Future socket; + final void Function() _onCancel; + + ConnectionTask._({Future socket, void Function() onCancel}) + : assert(socket != null), + assert(onCancel != null), + this.socket = socket, + this._onCancel = onCancel; + + /// Cancels the connection attempt. + /// + /// This also causes the [socket] `Future` to complete with a + /// [SocketException] error. + void cancel() { + _onCancel(); + } +} + +/** + * The [RawSocket] is a low-level interface to a socket, exposing the raw + * events signaled by the system. It's a [Stream] of [RawSocketEvent]s. + */ +abstract class RawSocket implements Stream { + /** + * Set or get, if the [RawSocket] should listen for [RawSocketEvent.read] + * events. Default is [:true:]. + */ + bool readEventsEnabled; + + /** + * Set or get, if the [RawSocket] should listen for [RawSocketEvent.write] + * events. Default is [:true:]. + * This is a one-shot listener, and writeEventsEnabled must be set + * to true again to receive another write event. + */ + bool writeEventsEnabled; + + /** + * Creates a new socket connection to the host and port and returns a [Future] + * that will complete with either a [RawSocket] once connected or an error + * if the host-lookup or connection failed. + * + * [host] can either be a [String] or an [InternetAddress]. If [host] is a + * [String], [connect] will perform a [InternetAddress.lookup] and try + * all returned [InternetAddress]es, until connected. Unless a + * connection was established, the error from the first failing connection is + * returned. + * + * The argument [sourceAddress] can be used to specify the local + * address to bind when making the connection. `sourceAddress` can either + * be a `String` or an `InternetAddress`. If a `String` is passed it must + * hold a numeric IP address. + * + * The argument [timeout] is used to specify the maximum allowed time to wait + * for a connection to be established. If [timeout] is longer than the system + * level timeout duration, a timeout may occur sooner than specified in + * [timeout]. On timeout, a [SocketException] is thrown and all ongoing + * connection attempts to [host] are cancelled. + */ + external static Future connect(host, int port, + {sourceAddress, Duration timeout}); + + /// Like [connect], but returns a [Future] that completes with a + /// [ConnectionTask] that can be cancelled if the [RawSocket] is no + /// longer needed. + external static Future> startConnect(host, int port, + {sourceAddress}); + + /** + * Returns the number of received and non-read bytes in the socket that + * can be read. + */ + int available(); + + /** + * Read up to [len] bytes from the socket. This function is + * non-blocking and will only return data if data is available. The + * number of bytes read can be less then [len] if fewer bytes are + * available for immediate reading. If no data is available [:null:] + * is returned. + */ + List read([int len]); + + /** + * Writes up to [count] bytes of the buffer from [offset] buffer offset to + * the socket. The number of successfully written bytes is returned. This + * function is non-blocking and will only write data if buffer space is + * available in the socket. + * + * The default value for [offset] is 0, and the default value for [count] is + * [:buffer.length - offset:]. + */ + int write(List buffer, [int offset, int count]); + + /** + * Returns the port used by this socket. + */ + int get port; + + /** + * Returns the remote port connected to by this socket. + */ + int get remotePort; + + /** + * Returns the [InternetAddress] used to connect this socket. + */ + InternetAddress get address; + + /** + * Returns the remote [InternetAddress] connected to by this socket. + */ + InternetAddress get remoteAddress; + + /** + * Closes the socket. Returns a Future that completes with [this] when the + * underlying connection is completely destroyed. + * + * Calling [close] will never throw an exception + * and calling it several times is supported. Calling [close] can result in + * a [RawSocketEvent.readClosed] event. + */ + Future close(); + + /** + * Shutdown the socket in the [direction]. Calling [shutdown] will never + * throw an exception and calling it several times is supported. Calling + * shutdown with either [SocketDirection.both] or [SocketDirection.receive] + * can result in a [RawSocketEvent.readClosed] event. + */ + void shutdown(SocketDirection direction); + + /** + * Use [setOption] to customize the [RawSocket]. See [SocketOption] for + * available options. + * + * Returns [:true:] if the option was set successfully, false otherwise. + */ + bool setOption(SocketOption option, bool enabled); +} + +/** + * A high-level class for communicating over a TCP socket. + * + * The [Socket] exposes both a [Stream] and a [IOSink] interface, making it + * ideal for using together with other [Stream]s. + */ +abstract class Socket implements Stream>, IOSink { + /** + * Creates a new socket connection to the host and port and returns a [Future] + * that will complete with either a [Socket] once connected or an error + * if the host-lookup or connection failed. + * + * [host] can either be a [String] or an [InternetAddress]. If [host] is a + * [String], [connect] will perform a [InternetAddress.lookup] and try + * all returned [InternetAddress]es, until connected. Unless a + * connection was established, the error from the first failing connection is + * returned. + * + * The argument [sourceAddress] can be used to specify the local + * address to bind when making the connection. `sourceAddress` can either + * be a `String` or an `InternetAddress`. If a `String` is passed it must + * hold a numeric IP address. + * + * The argument [timeout] is used to specify the maximum allowed time to wait + * for a connection to be established. If [timeout] is longer than the system + * level timeout duration, a timeout may occur sooner than specified in + * [timeout]. On timeout, a [SocketException] is thrown and all ongoing + * connection attempts to [host] are cancelled. + */ + static Future connect(host, int port, + {sourceAddress, Duration timeout}) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return Socket._connect(host, port, + sourceAddress: sourceAddress, timeout: timeout); + } + return overrides.socketConnect(host, port, + sourceAddress: sourceAddress, timeout: timeout); + } + + /// Like [connect], but returns a [Future] that completes with a + /// [ConnectionTask] that can be cancelled if the [Socket] is no + /// longer needed. + static Future> startConnect(host, int port, + {sourceAddress}) { + final IOOverrides overrides = IOOverrides.current; + if (overrides == null) { + return Socket._startConnect(host, port, sourceAddress: sourceAddress); + } + return overrides.socketStartConnect(host, port, + sourceAddress: sourceAddress); + } + + external static Future _connect(host, int port, + {sourceAddress, Duration timeout}); + + external static Future> _startConnect(host, int port, + {sourceAddress}); + + /** + * Destroy the socket in both directions. Calling [destroy] will make the + * send a close event on the stream and will no longer react on data being + * piped to it. + * + * Call [close](inherited from [IOSink]) to only close the [Socket] + * for sending data. + */ + void destroy(); + + /** + * Use [setOption] to customize the [RawSocket]. See [SocketOption] for + * available options. + * + * Returns [:true:] if the option was set successfully, false otherwise. + */ + bool setOption(SocketOption option, bool enabled); + + /** + * Returns the port used by this socket. + */ + int get port; + + /** + * Returns the remote port connected to by this socket. + */ + int get remotePort; + + /** + * Returns the [InternetAddress] used to connect this socket. + */ + InternetAddress get address; + + /** + * Returns the remote [InternetAddress] connected to by this socket. + */ + InternetAddress get remoteAddress; + + Future close(); + + Future get done; +} + +/** + * Datagram package. Data send to and received from datagram sockets + * contains the internet address and port of the destination or source + * togeter with the data. + */ +class Datagram { + List data; + InternetAddress address; + int port; + + Datagram(this.data, this.address, this.port); +} + +/** + * The [RawDatagramSocket] is a low-level interface to an UDP socket, + * exposing the raw events signaled by the system. It's a [Stream] of + * [RawSocketEvent]s. + * + * Note that the event [RawSocketEvent.readClosed] will never be + * received as an UDP socket cannot be closed by a remote peer. + */ +abstract class RawDatagramSocket extends Stream { + /** + * Set or get, if the [RawDatagramSocket] should listen for + * [RawSocketEvent.read] events. Default is [:true:]. + */ + bool readEventsEnabled; + + /** + * Set or get, if the [RawDatagramSocket] should listen for + * [RawSocketEvent.write] events. Default is [:true:]. This is a + * one-shot listener, and writeEventsEnabled must be set to true + * again to receive another write event. + */ + bool writeEventsEnabled; + + /** + * Set or get, whether multicast traffic is looped back to the host. + * + * By default multicast loopback is enabled. + */ + bool multicastLoopback; + + /** + * Set or get, the maximum network hops for multicast packages + * originating from this socket. + * + * For IPv4 this is referred to as TTL (time to live). + * + * By default this value is 1 causing multicast traffic to stay on + * the local network. + */ + int multicastHops; + + /** + * Set or get, the network interface used for outgoing multicast packages. + * + * A value of `null`indicate that the system chooses the network + * interface to use. + * + * By default this value is `null` + */ + NetworkInterface multicastInterface; + + /** + * Set or get, whether IPv4 broadcast is enabled. + * + * IPv4 broadcast needs to be enabled by the sender for sending IPv4 + * broadcast packages. By default IPv4 broadcast is disabled. + * + * For IPv6 there is no general broadcast mechanism. Use multicast + * instead. + */ + bool broadcastEnabled; + + /** + * Creates a new raw datagram socket binding it to an address and + * port. + */ + external static Future bind(host, int port, + {bool reuseAddress: true}); + + /** + * Returns the port used by this socket. + */ + int get port; + + /** + * Returns the address used by this socket. + */ + InternetAddress get address; + + /** + * Close the datagram socket. + */ + void close(); + + /** + * Send a datagram. + * + * Returns the number of bytes written. This will always be either + * the size of [buffer] or `0`. + */ + int send(List buffer, InternetAddress address, int port); + + /** + * Receive a datagram. If there are no datagrams available `null` is + * returned. + * + * The maximum length of the datagram that can be received is 65503 bytes. + */ + Datagram receive(); + + /** + * Join a multicast group. + * + * If an error occur when trying to join the multicast group an + * exception is thrown. + */ + void joinMulticast(InternetAddress group, [NetworkInterface interface]); + + /** + * Leave a multicast group. + * + * If an error occur when trying to join the multicase group an + * exception is thrown. + */ + void leaveMulticast(InternetAddress group, [NetworkInterface interface]); +} + +class SocketException implements IOException { + final String message; + final OSError osError; + final InternetAddress address; + final int port; + + const SocketException(this.message, {this.osError, this.address, this.port}); + const SocketException.closed() + : message = 'Socket has been closed', + osError = null, + address = null, + port = null; + + String toString() { + StringBuffer sb = new StringBuffer(); + sb.write("SocketException"); + if (!message.isEmpty) { + sb.write(": $message"); + if (osError != null) { + sb.write(" ($osError)"); + } + } else if (osError != null) { + sb.write(": $osError"); + } + if (address != null) { + sb.write(", address = ${address.host}"); + } + if (port != null) { + sb.write(", port = $port"); + } + return sb.toString(); + } +} +LNN<F>JJJ"1"1!.,1!!56<5CFAD !GF=*6GF=*6B:3%1B:3%1E G;!>CKMABC@=7E(4C?%4DBBEFD<5J*5-NK"-.?'"1*/H*LP7E;7$$;ED!">AE-2@GD=';>?GBBA:D GFGQQLQL2BA+.F-#BC8>E-2@GD=';>?GBBAGAGFGNQOKI2?A+.F- FFEBB%2",",(GJ MO"(B(6HHFD%@AFB"+#-(8$/'#LKK:MO#A "#&@JH=L"M"E3QM.MIAPCLL PPJJ2<*CFQJ>FDGMLJO!8+:@G%M43N*KKN8,JK5;L2=QJ.MIAPCLL PPJJ20+7);/9CCE7M4':*OLMFJK5+:@G%EG 0FFA@B>8>DC+G/A#9EMC%'4G@ED A"+. E"AGMBKBL/!P!,*!!"/"Ifile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/stdio.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +const int _stdioHandleTypeTerminal = 0; +const int _stdioHandleTypePipe = 1; +const int _stdioHandleTypeFile = 2; +const int _stdioHandleTypeSocket = 3; +const int _stdioHandleTypeOther = 4; + +class _StdStream extends Stream> { + final Stream> _stream; + + _StdStream(this._stream); + + StreamSubscription> listen(void onData(List event), + {Function onError, void onDone(), bool cancelOnError}) { + return _stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + } +} + +/** + * [Stdin] allows both synchronous and asynchronous reads from the standard + * input stream. + * + * Mixing synchronous and asynchronous reads is undefined. + */ +class Stdin extends _StdStream implements Stream> { + int _fd; + + Stdin._(Stream> stream, this._fd) : super(stream); + + /** + * Synchronously read a line from stdin. This call will block until a full + * line is available. + * + * The argument [encoding] can be used to changed how the input should be + * decoded. Default is [systemEncoding]. + * + * If [retainNewlines] is `false`, the returned String will not contain the + * final newline. If `true`, the returned String will contain the line + * terminator. Default is `false`. + * + * If end-of-file is reached after any bytes have been read from stdin, + * that data is returned. + * Returns `null` if no bytes preceded the end of input. + */ + String readLineSync( + {Encoding encoding: systemEncoding, bool retainNewlines: false}) { + const CR = 13; + const LF = 10; + final List line = []; + // On Windows, if lineMode is disabled, only CR is received. + bool crIsNewline = Platform.isWindows && + (stdioType(stdin) == StdioType.terminal) && + !lineMode; + if (retainNewlines) { + int byte; + do { + byte = readByteSync(); + if (byte < 0) { + break; + } + line.add(byte); + } while (byte != LF && !(byte == CR && crIsNewline)); + if (line.isEmpty) { + return null; + } + } else if (crIsNewline) { + // CR and LF are both line terminators, neither is retained. + while (true) { + int byte = readByteSync(); + if (byte < 0) { + if (line.isEmpty) return null; + break; + } + if (byte == LF || byte == CR) break; + line.add(byte); + } + } else { + // Case having to handle CR LF as a single unretained line terminator. + outer: + while (true) { + int byte = readByteSync(); + if (byte == LF) break; + if (byte == CR) { + do { + byte = readByteSync(); + if (byte == LF) break outer; + + line.add(CR); + } while (byte == CR); + // Fall through and handle non-CR character. + } + if (byte < 0) { + if (line.isEmpty) return null; + break; + } + line.add(byte); + } + } + return encoding.decode(line); + } + + /** + * Check if echo mode is enabled on [stdin]. + */ + external bool get echoMode; + + /** + * Enable or disable echo mode on [stdin]. + * + * If disabled, input from to console will not be echoed. + * + * Default depends on the parent process, but usually enabled. + * + * On Windows this mode can only be enabled if [lineMode] is enabled as well. + */ + external void set echoMode(bool enabled); + + /** + * Check if line mode is enabled on [stdin]. + */ + external bool get lineMode; + + /** + * Enable or disable line mode on [stdin]. + * + * If enabled, characters are delayed until a new-line character is entered. + * If disabled, characters will be available as typed. + * + * Default depends on the parent process, but usually enabled. + * + * On Windows this mode can only be disabled if [echoMode] is disabled as well. + */ + external void set lineMode(bool enabled); + + /** + * Whether connected to a terminal that supports ANSI escape sequences. + * + * Not all terminals are recognized, and not all recognized terminals can + * report whether they support ANSI escape sequences, so this value is a + * best-effort attempt at detecting the support. + * + * The actual escape sequence support may differ between terminals, + * with some terminals supporting more escape sequences than others, + * and some terminals even differing in behavior for the same escape + * sequence. + * + * The ANSI color selection is generally supported. + * + * Currently, a `TERM` environment variable containing the string `xterm` + * will be taken as evidence that ANSI escape sequences are supported. + * On Windows, only versions of Windows 10 after v.1511 + * ("TH2", OS build 10586) will be detected as supporting the output of + * ANSI escape sequences, and only versions after v.1607 ("Anniversary + * Update", OS build 14393) will be detected as supporting the input of + * ANSI escape sequences. + */ + external bool get supportsAnsiEscapes; + + /** + * Synchronously read a byte from stdin. This call will block until a byte is + * available. + * + * If at end of file, -1 is returned. + */ + external int readByteSync(); + + /** + * Returns true if there is a terminal attached to stdin. + */ + bool get hasTerminal { + try { + return stdioType(this) == StdioType.terminal; + } on FileSystemException catch (_) { + // If stdioType throws a FileSystemException, then it is not hooked up to + // a terminal, probably because it is closed, but let other exception + // types bubble up. + return false; + } + } +} + +/** + * [Stdout] represents the [IOSink] for either `stdout` or `stderr`. + * + * It provides a *blocking* `IOSink`, so using this to write will block until + * the output is written. + * + * In some situations this blocking behavior is undesirable as it does not + * provide the same non-blocking behavior as dart:io in general exposes. + * Use the property [nonBlocking] to get an `IOSink` which has the non-blocking + * behavior. + * + * This class can also be used to check whether `stdout` or `stderr` is + * connected to a terminal and query some terminal properties. + */ +class Stdout extends _StdSink implements IOSink { + final int _fd; + IOSink _nonBlocking; + + Stdout._(IOSink sink, this._fd) : super(sink); + + /** + * Returns true if there is a terminal attached to stdout. + */ + bool get hasTerminal => _hasTerminal(_fd); + + /** + * Get the number of columns of the terminal. + * + * If no terminal is attached to stdout, a [StdoutException] is thrown. See + * [hasTerminal] for more info. + */ + int get terminalColumns => _terminalColumns(_fd); + + /* + * Get the number of lines of the terminal. + * + * If no terminal is attached to stdout, a [StdoutException] is thrown. See + * [hasTerminal] for more info. + */ + int get terminalLines => _terminalLines(_fd); + + /** + * Whether connected to a terminal that supports ANSI escape sequences. + * + * Not all terminals are recognized, and not all recognized terminals can + * report whether they support ANSI escape sequences, so this value is a + * best-effort attempt at detecting the support. + * + * The actual escape sequence support may differ between terminals, + * with some terminals supporting more escape sequences than others, + * and some terminals even differing in behavior for the same escape + * sequence. + * + * The ANSI color selection is generally supported. + * + * Currently, a `TERM` environment variable containing the string `xterm` + * will be taken as evidence that ANSI escape sequences are supported. + * On Windows, only versions of Windows 10 after v.1511 + * ("TH2", OS build 10586) will be detected as supporting the output of + * ANSI escape sequences, and only versions after v.1607 ("Anniversary + * Update", OS build 14393) will be detected as supporting the input of + * ANSI escape sequences. + */ + bool get supportsAnsiEscapes => _supportsAnsiEscapes(_fd); + + external bool _hasTerminal(int fd); + external int _terminalColumns(int fd); + external int _terminalLines(int fd); + external static bool _supportsAnsiEscapes(int fd); + + /** + * Get a non-blocking `IOSink`. + */ + IOSink get nonBlocking { + if (_nonBlocking == null) { + _nonBlocking = new IOSink(new _FileStreamConsumer.fromStdio(_fd)); + } + return _nonBlocking; + } +} + +class StdoutException implements IOException { + final String message; + final OSError osError; + + const StdoutException(this.message, [this.osError]); + + String toString() { + return "StdoutException: $message${osError == null ? "" : ", $osError"}"; + } +} + +class StdinException implements IOException { + final String message; + final OSError osError; + + const StdinException(this.message, [this.osError]); + + String toString() { + return "StdinException: $message${osError == null ? "" : ", $osError"}"; + } +} + +class _StdConsumer implements StreamConsumer> { + final _file; + + _StdConsumer(int fd) : _file = _File._openStdioSync(fd); + + Future addStream(Stream> stream) { + var completer = new Completer(); + var sub; + sub = stream.listen((data) { + try { + _file.writeFromSync(data); + } catch (e, s) { + sub.cancel(); + completer.completeError(e, s); + } + }, + onError: completer.completeError, + onDone: completer.complete, + cancelOnError: true); + return completer.future; + } + + Future close() { + _file.closeSync(); + return new Future.value(); + } +} + +class _StdSink implements IOSink { + final IOSink _sink; + + _StdSink(this._sink); + + Encoding get encoding => _sink.encoding; + void set encoding(Encoding encoding) { + _sink.encoding = encoding; + } + + void write(object) { + _sink.write(object); + } + + void writeln([object = ""]) { + _sink.writeln(object); + } + + void writeAll(objects, [sep = ""]) { + _sink.writeAll(objects, sep); + } + + void add(List data) { + _sink.add(data); + } + + void addError(error, [StackTrace stackTrace]) { + _sink.addError(error, stackTrace); + } + + void writeCharCode(int charCode) { + _sink.writeCharCode(charCode); + } + + Future addStream(Stream> stream) => _sink.addStream(stream); + Future flush() => _sink.flush(); + Future close() => _sink.close(); + Future get done => _sink.done; +} + +/// The type of object a standard IO stream is attached to. +class StdioType { + static const StdioType terminal = const StdioType._("terminal"); + static const StdioType pipe = const StdioType._("pipe"); + static const StdioType file = const StdioType._("file"); + static const StdioType other = const StdioType._("other"); + + @Deprecated("Use terminal instead") + static const StdioType TERMINAL = terminal; + @Deprecated("Use pipe instead") + static const StdioType PIPE = pipe; + @Deprecated("Use file instead") + static const StdioType FILE = file; + @Deprecated("Use other instead") + static const StdioType OTHER = other; + + final String name; + const StdioType._(this.name); + String toString() => "StdioType: $name"; +} + +Stdin _stdin; +Stdout _stdout; +Stdout _stderr; + +// These may be set to different values by the embedder by calling +// _setStdioFDs when initializing dart:io. +int _stdinFD = 0; +int _stdoutFD = 1; +int _stderrFD = 2; + +// This is an embedder entrypoint. +void _setStdioFDs(int stdin, int stdout, int stderr) { + _stdinFD = stdin; + _stdoutFD = stdout; + _stderrFD = stderr; +} + +/// The standard input stream of data read by this program. +Stdin get stdin { + if (_stdin == null) { + _stdin = _StdIOUtils._getStdioInputStream(_stdinFD); + } + return _stdin; +} + +/// The standard output stream of data written by this program. +Stdout get stdout { + if (_stdout == null) { + _stdout = _StdIOUtils._getStdioOutputStream(_stdoutFD); + } + return _stdout; +} + +/// The standard output stream of errors written by this program. +Stdout get stderr { + if (_stderr == null) { + _stderr = _StdIOUtils._getStdioOutputStream(_stderrFD); + } + return _stderr; +} + +/// For a stream, returns whether it is attached to a file, pipe, terminal, or +/// something else. +StdioType stdioType(object) { + if (object is _StdStream) { + object = object._stream; + } else if (object == stdout || object == stderr) { + int stdiofd = object == stdout ? _stdoutFD : _stderrFD; + switch (_StdIOUtils._getStdioHandleType(stdiofd)) { + case _stdioHandleTypeTerminal: + return StdioType.terminal; + case _stdioHandleTypePipe: + return StdioType.pipe; + case _stdioHandleTypeFile: + return StdioType.file; + } + } + if (object is _FileStream) { + return StdioType.file; + } + if (object is Socket) { + int socketType = _StdIOUtils._socketType(object); + if (socketType == null) return StdioType.other; + switch (socketType) { + case _stdioHandleTypeTerminal: + return StdioType.terminal; + case _stdioHandleTypePipe: + return StdioType.pipe; + case _stdioHandleTypeFile: + return StdioType.file; + } + } + if (object is _IOSinkImpl) { + try { + if (object._target is _FileStreamConsumer) { + return StdioType.file; + } + } catch (e) { + // Only the interface implemented, _sink not available. + } + } + return StdioType.other; +} + +class _StdIOUtils { + external static _getStdioOutputStream(int fd); + external static Stdin _getStdioInputStream(int fd); + + /// Returns the socket type or `null` if [socket] is not a builtin socket. + external static int _socketType(Socket socket); + external static _getStdioHandleType(int fd); +} +NN<($$&%-#E?"IL;> ?ML+NI%J;I$A-4  +<C#) +- M ##) 7 +) +"/-<AP,/-O9AR,KML4GHH7MJ;KJK)P(< +4)PLENKIP H?21=-0N"4.N"0KML4GHH7MJ;KJK=&)'5" I/7N.6M:;/% ! #'*$#+) '"2'%#I##!<C;;=&."&"&#( +C+#7<9@<B<O5<8%#!!64%#!! +3>16M2/Vfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/string_transformer.dartn// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/// The current system encoding. +/// +/// This us used for converting from bytes to/from String when +/// communicating on stdin, stdout and stderr. +/// +/// On Windows this will use the currently active code page for the +/// conversion. On all other systems it will always use UTF-8. +const SystemEncoding systemEncoding = const SystemEncoding(); +@Deprecated("Use systemEncoding instead") +const SystemEncoding SYSTEM_ENCODING = const SystemEncoding(); + +/** + * The system encoding is the current code page on Windows and UTF-8 on + * Linux and Mac. + */ +class SystemEncoding extends Encoding { + const SystemEncoding(); + + String get name => 'system'; + + List encode(String input) => encoder.convert(input); + String decode(List encoded) => decoder.convert(encoded); + + Converter> get encoder { + if (Platform.operatingSystem == "windows") { + return const _WindowsCodePageEncoder(); + } else { + return const Utf8Encoder(); + } + } + + Converter, String> get decoder { + if (Platform.operatingSystem == "windows") { + return const _WindowsCodePageDecoder(); + } else { + return const Utf8Decoder(); + } + } +} + +class _WindowsCodePageEncoder extends Converter> { + const _WindowsCodePageEncoder(); + + List convert(String input) { + List encoded = _encodeString(input); + if (encoded == null) { + throw new FormatException("Invalid character for encoding"); + } + return encoded; + } + + /** + * Starts a chunked conversion. + */ + StringConversionSink startChunkedConversion(Sink> sink) { + return new _WindowsCodePageEncoderSink(sink); + } + + external static List _encodeString(String string); +} + +class _WindowsCodePageEncoderSink extends StringConversionSinkBase { + // TODO(floitsch): provide more efficient conversions when the input is + // not a String. + + final Sink> _sink; + + _WindowsCodePageEncoderSink(this._sink); + + void close() { + _sink.close(); + } + + void add(String string) { + List encoded = _WindowsCodePageEncoder._encodeString(string); + if (encoded == null) { + throw new FormatException("Invalid character for encoding"); + } + _sink.add(encoded); + } + + void addSlice(String source, int start, int end, bool isLast) { + if (start != 0 || end != source.length) { + source = source.substring(start, end); + } + add(source); + if (isLast) close(); + } +} + +class _WindowsCodePageDecoder extends Converter, String> { + const _WindowsCodePageDecoder(); + + String convert(List input) { + return _decodeBytes(input); + } + + /** + * Starts a chunked conversion. + */ + ByteConversionSink startChunkedConversion(Sink sink) { + return new _WindowsCodePageDecoderSink(sink); + } + + external static String _decodeBytes(List bytes); +} + +class _WindowsCodePageDecoderSink extends ByteConversionSinkBase { + // TODO(floitsch): provide more efficient conversions when the input is + // a slice. + + final Sink _sink; + + _WindowsCodePageDecoderSink(this._sink); + + void close() { + _sink.close(); + } + + void add(List bytes) { + _sink.add(_WindowsCodePageDecoder._decodeBytes(bytes)); + } +} +NN<!?/D?>*?H(<@-1. "-1. "E#$.C"F2:EJ+GCB.-E#$ "A28CJ+<Ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/io/sync_socket.dart// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.io; + +/** + * A low-level class for communicating synchronously over a TCP socket. + * + * Warning: [RawSynchronousSocket] should probably only be used to connect to + * 'localhost'. The operations below will block the calling thread to wait for + * a response from the network. The thread can process no other events while + * waiting for these operations to complete. [RawSynchronousSocket] is not + * suitable for applications that require high performance or asynchronous I/O + * such as a server. Instead such applications should use the non-blocking + * sockets and asynchronous operations in the Socket or RawSocket classes. + */ +abstract class RawSynchronousSocket { + /** + * Creates a new socket connection and returns a [RawSynchronousSocket]. + * + * [host] can either be a [String] or an [InternetAddress]. If [host] is a + * [String], [connectSync] will perform a [InternetAddress.lookup] and try + * all returned [InternetAddress]es, until connected. Unless a + * connection was established, the error from the first failing connection is + * returned. + */ + external static RawSynchronousSocket connectSync(host, int port); + + /** + * Returns the number of received and unread bytes in the socket that can be + * read. + */ + int available(); + + /** + * Closes the [RawSynchronousSocket]. + * + * Once [closeSync] has been called, attempting to call [readSync], + * [readIntoSync], [writeFromSync], [remoteAddress], and [remotePort] will + * cause a [SocketException] to be thrown. + */ + void closeSync(); + + /** + * Reads into an existing [List] from the socket into the range: + * [[start],[end]). + * + * Reads into an existing [List] from the socket. If [start] is present, + * the bytes will be filled into [buffer] from index [start], otherwise index + * 0. If [end] is present, [end] - [start] bytes will be read into [buffer], + * otherwise up to [buffer.length]. If [end] == [start], no bytes are read. + * Returns the number of bytes read. + */ + int readIntoSync(List buffer, [int start = 0, int end]); + + /** + * Reads up to [bytes] bytes from the socket. + * + * Blocks and waits for a response of up to a specified number of bytes + * sent by the socket. [bytes] specifies the maximum number of bytes to + * be read. Returns the list of bytes read, which could be less than the + * value specified by [bytes]. + */ + List readSync(int bytes); + + /** + * Shutdown a socket in the provided direction. + * + * Calling shutdown will never throw an exception and calling it several times + * is supported. If both [SocketDirection.RECEIVE] and [SocketDirection.SEND] + * directions are closed, the socket is closed completely, the same as if + * [closeSync] has been called. + */ + void shutdown(SocketDirection direction); + + /** + * Writes data from a specified range in a [List] to the socket. + * + * Writes into the socket from a [List]. If [start] is present, the bytes + * will be written to the socket starting from index [start]. If [start] is + * not present, the bytes will be written starting from index 0. If [end] is + * present, the [end] - [start] bytes will be written into the socket starting + * at index [start]. If [end] is not provided, [buffer.length] elements will + * be written to the socket starting from index [start]. If [end] == [start], + * nothing happens. + */ + void writeFromSync(List buffer, [int start = 0, int end]); + + /** + * The port used by this socket. + */ + int get port; + + /** + * The remote port connected to by this socket. + */ + int get remotePort; + + /** + * The [InternetAddress] used to connect this socket. + */ + InternetAddress get address; + + /** + * The remote [InternetAddress] connected to by this socket. + */ + InternetAddress get remoteAddress; +} +oNN<HNOMKOKK&KMMAPDO (FM-HPPON'@0JJK!!2QPL",HQNOQOPB#28?%Pfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/isolate/isolate.dartn// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Concurrent programming using _isolates_: + * independent workers that are similar to threads + * but don't share memory, + * communicating only via messages. + * + * To use this library in your code: + * + * import 'dart:isolate'; + * + * {@category VM} + */ +library dart.isolate; + +import "dart:async"; + +part "capability.dart"; + +/** + * Thrown when an isolate cannot be created. + */ +class IsolateSpawnException implements Exception { + /** Error message reported by the spawn operation. */ + final String message; + IsolateSpawnException(this.message); + String toString() => "IsolateSpawnException: $message"; +} + +/** + * An isolated Dart execution context. + * + * All Dart code runs in an isolate, and code can access classes and values + * only from the same isolate. Different isolates can communicate by sending + * values through ports (see [ReceivePort], [SendPort]). + * + * An `Isolate` object is a reference to an isolate, usually different from + * the current isolate. + * It represents, and can be used control, the other isolate. + * + * When spawning a new isolate, the spawning isolate receives an `Isolate` + * object representing the new isolate when the spawn operation succeeds. + * + * Isolates run code in its own event loop, and each event may run smaller tasks + * in a nested microtask queue. + * + * An `Isolate` object allows other isolates to control the event loop + * of the isolate that it represents, and to inspect the isolate, + * for example by pausing the isolate or by getting events when the isolate + * has an uncaught error. + * + * The [controlPort] identifies and gives access to controlling the isolate, + * and the [pauseCapability] and [terminateCapability] guard access + * to some control operations. + * For example, calling [pause] on an `Isolate` object created without a + * [pauseCapability], has no effect. + * + * The `Isolate` object provided by a spawn operation will have the + * control port and capabilities needed to control the isolate. + * New isolate objects can be created without some of these capabilities + * if necessary, using the [Isolate.Isolate] constructor. + * + * An `Isolate` object cannot be sent over a `SendPort`, but the control port + * and capabilities can be sent, and can be used to create a new functioning + * `Isolate` object in the receiving port's isolate. + */ +class Isolate { + /** Argument to `ping` and `kill`: Ask for immediate action. */ + static const int immediate = 0; + /** Argument to `ping` and `kill`: Ask for action before the next event. */ + static const int beforeNextEvent = 1; + + /** + * Control port used to send control messages to the isolate. + * + * The control port identifies the isolate. + * + * An `Isolate` object allows sending control messages + * through the control port. + * + * Some control messages require a specific capability to be passed along + * with the message (see [pauseCapability] and [terminateCapability]), + * otherwise the message is ignored by the isolate. + */ + final SendPort controlPort; + + /** + * Capability granting the ability to pause the isolate. + * + * This capability is required by [pause]. + * If the capability is `null`, or if it is not the correct pause capability + * of the isolate identified by [controlPort], + * then calls to [pause] will have no effect. + * + * If the isolate is spawned in a paused state, use this capability as + * argument to the [resume] method in order to resume the paused isolate. + */ + final Capability pauseCapability; + + /** + * Capability granting the ability to terminate the isolate. + * + * This capability is required by [kill] and [setErrorsFatal]. + * If the capability is `null`, or if it is not the correct termination + * capability of the isolate identified by [controlPort], + * then calls to those methods will have no effect. + */ + final Capability terminateCapability; + + /** + * Create a new [Isolate] object with a restricted set of capabilities. + * + * The port should be a control port for an isolate, as taken from + * another `Isolate` object. + * + * The capabilities should be the subset of the capabilities that are + * available to the original isolate. + * Capabilities of an isolate are locked to that isolate, and have no effect + * anywhere else, so the capabilities should come from the same isolate as + * the control port. + * + * Can also be used to create an [Isolate] object from a control port, and + * any available capabilities, that have been sent through a [SendPort]. + * + * Example: + * ```dart + * Isolate isolate = findSomeIsolate(); + * Isolate restrictedIsolate = new Isolate(isolate.controlPort); + * untrustedCode(restrictedIsolate); + * ``` + * This example creates a new `Isolate` object that cannot be used to + * pause or terminate the isolate. All the untrusted code can do is to + * inspect the isolate and see uncaught errors or when it terminates. + */ + Isolate(this.controlPort, {this.pauseCapability, this.terminateCapability}); + + /** + * Return an [Isolate] object representing the current isolate. + * + * The current isolate for code using [current] + * is the isolate running the code. + * + * The isolate object provides the capabilities required to inspect, + * pause or kill the isolate, and allows granting these capabilities + * to others. + * + * It is possible to pause the current isolate, but doing so *without* + * first passing the ability to resume it again to another isolate, + * is a sure way to hang your program. + */ + external static Isolate get current; + + /** + * The location of the package configuration of the current isolate, if any. + * + * This getter returns `null`, as the `packages/` directory is not supported + * in Dart 2. + */ + @Deprecated('packages/ directory resolution is not supported in Dart 2.') + external static Future get packageRoot; + + /** + * The package root of the current isolate, if any. + * + * If the isolate is using a [packageRoot] or the isolate has not been + * setup for package resolution, this getter returns `null`, otherwise it + * returns the package config URI. + */ + external static Future get packageConfig; + + /** + * Maps a package: URI to a non-package Uri. + * + * If there is no valid mapping from the package: URI in the current + * isolate, then this call returns `null`. Non-package: URIs are + * returned unmodified. + */ + external static Future resolvePackageUri(Uri packageUri); + + /** + * Creates and spawns an isolate that shares the same code as the current + * isolate. + * + * The argument [entryPoint] specifies the initial function to call + * in the spawned isolate. + * The entry-point function is invoked in the new isolate with [message] + * as the only argument. + * + * The function must be a top-level function or a static method + * that can be called with a single argument, + * that is, a compile-time constant function value + * which accepts at least one positional parameter + * and has at most one required positional parameter. + * The function may accept any number of optional parameters, + * as long as it *can* be called with just a single argument. + * The function must not be the value of a function expression + * or an instance method tear-off. + * + * Usually the initial [message] contains a [SendPort] so + * that the spawner and spawnee can communicate with each other. + * + * If the [paused] parameter is set to `true`, + * the isolate will start up in a paused state, + * just before calling the [entryPoint] function with the [message], + * as if by an initial call of `isolate.pause(isolate.pauseCapability)`. + * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`. + * + * If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided, + * the isolate will act as if, respectively, [setErrorsFatal], + * [addOnExitListener] and [addErrorListener] were called with the + * corresponding parameter and was processed before the isolate starts + * running. + * + * If [errorsAreFatal] is omitted, the platform may choose a default behavior + * or inherit the current isolate's behavior. + * + * You can also call the [setErrorsFatal], [addOnExitListener] and + * [addErrorListener] methods on the returned isolate, but unless the + * isolate was started as [paused], it may already have terminated + * before those methods can complete. + * + * Returns a future which will complete with an [Isolate] instance if the + * spawning succeeded. It will complete with an error otherwise. + */ + external static Future spawn( + void entryPoint(T message), T message, + {bool paused: false, + bool errorsAreFatal, + SendPort onExit, + SendPort onError}); + + /** + * Creates and spawns an isolate that runs the code from the library with + * the specified URI. + * + * The isolate starts executing the top-level `main` function of the library + * with the given URI. + * + * The target `main` must be callable with zero, one or two arguments. + * Examples: + * + * * `main()` + * * `main(args)` + * * `main(args, message)` + * + * When present, the parameter `args` is set to the provided [args] list. + * When present, the parameter `message` is set to the initial [message]. + * + * If the [paused] parameter is set to `true`, + * the isolate will start up in a paused state, + * as if by an initial call of `isolate.pause(isolate.pauseCapability)`. + * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`. + * + * If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided, + * the isolate will act as if, respectively, [setErrorsFatal], + * [addOnExitListener] and [addErrorListener] were called with the + * corresponding parameter and was processed before the isolate starts + * running. + * + * You can also call the [setErrorsFatal], [addOnExitListener] and + * [addErrorListener] methods on the returned isolate, but unless the + * isolate was started as [paused], it may already have terminated + * before those methods can complete. + * + * If the [checked] parameter is set to `true` or `false`, + * the new isolate will run code in checked mode (enabling asserts and type + * checks), respectively in production mode (disabling asserts and type + * checks), if possible. If the parameter is omitted, the new isolate will + * inherit the value from the current isolate. + * + * In Dart2 strong mode, the `checked` parameter only controls asserts, but + * not type checks. + * + * It may not always be possible to honor the `checked` parameter. + * If the isolate code was pre-compiled, it may not be possible to change + * the checked mode setting dynamically. + * In that case, the `checked` parameter is ignored. + * + * WARNING: The [checked] parameter is not implemented on all platforms yet. + * + * If the [packageConfig] parameter is provided, then it is used to find the + * location of a package resolution configuration file for the spawned + * isolate. + * + * If the [automaticPackageResolution] parameter is provided, then the + * location of the package sources in the spawned isolate is automatically + * determined. + * + * The [environment] is a mapping from strings to strings which the + * spawned isolate uses when looking up [String.fromEnvironment] values. + * The system may add its own entries to environment as well. + * If `environment` is omitted, the spawned isolate has the same environment + * declarations as the spawning isolate. + * + * WARNING: The [environment] parameter is not implemented on all + * platforms yet. + * + * Returns a future that will complete with an [Isolate] instance if the + * spawning succeeded. It will complete with an error otherwise. + */ + external static Future spawnUri( + Uri uri, + List args, + var message, + {bool paused: false, + SendPort onExit, + SendPort onError, + bool errorsAreFatal, + bool checked, + Map environment, + @Deprecated('The packages/ dir is not supported in Dart 2') + Uri packageRoot, + Uri packageConfig, + bool automaticPackageResolution: false}); + + /** + * Requests the isolate to pause. + * + * When the isolate receives the pause command, it stops + * processing events from the event loop queue. + * It may still add new events to the queue in response to, e.g., timers + * or receive-port messages. When the isolate is resumed, + * it starts handling the already enqueued events. + * + * The pause request is sent through the isolate's command port, + * which bypasses the receiving isolate's event loop. + * The pause takes effect when it is received, pausing the event loop + * as it is at that time. + * + * The [resumeCapability] is used to identity the pause, + * and must be used again to end the pause using [resume]. + * If [resumeCapability] is omitted, a new capability object is created + * and used instead. + * + * If an isolate is paused more than once using the same capability, + * only one resume with that capability is needed to end the pause. + * + * If an isolate is paused using more than one capability, + * each pause must be individually ended before the isolate resumes. + * + * Returns the capability that must be used to end the pause. + * This is either [resumeCapability], or a new capability when + * [resumeCapability] is omitted. + * + * If [pauseCapability] is `null`, or it's not the pause capability + * of the isolate identified by [controlPort], + * the pause request is ignored by the receiving isolate. + */ + Capability pause([Capability resumeCapability]) { + resumeCapability ??= new Capability(); + _pause(resumeCapability); + return resumeCapability; + } + + /** Internal implementation of [pause]. */ + external void _pause(Capability resumeCapability); + + /** + * Resumes a paused isolate. + * + * Sends a message to an isolate requesting that it ends a pause + * that was previously requested. + * + * When all active pause requests have been cancelled, the isolate + * will continue processing events and handling normal messages. + * + * If the [resumeCapability] is not one that has previously been used + * to pause the isolate, or it has already been used to resume from + * that pause, the resume call has no effect. + */ + external void resume(Capability resumeCapability); + + /** + * Requests an exit message on [responsePort] when the isolate terminates. + * + * The isolate will send [response] as a message on [responsePort] as the last + * thing before it terminates. It will run no further code after the message + * has been sent. + * + * Adding the same port more than once will only cause it to receive one exit + * message, using the last response value that was added, + * and it only needs to be removed once using [removeOnExitListener]. + * + * If the isolate has terminated before it can receive this request, + * no exit message will be sent. + * + * The [response] object must follow the same restrictions as enforced by + * [SendPort.send]. + * It is recommended to only use simple values that can be sent to all + * isolates, like `null`, booleans, numbers or strings. + * + * Since isolates run concurrently, it's possible for it to exit before the + * exit listener is established, and in that case no response will be + * sent on [responsePort]. + * To avoid this, either use the corresponding parameter to the spawn + * function, or start the isolate paused, add the listener and + * then resume the isolate. + */ + /* TODO(lrn): Can we do better? Can the system recognize this message and + * send a reply if the receiving isolate is dead? + */ + external void addOnExitListener(SendPort responsePort, {Object response}); + + /** + * Stops listening for exit messages from the isolate. + * + * Requests for the isolate to not send exit messages on [responsePort]. + * If the isolate isn't expecting to send exit messages on [responsePort], + * because the port hasn't been added using [addOnExitListener], + * or because it has already been removed, the request is ignored. + * + * If the same port has been passed via [addOnExitListener] more than once, + * only one call to `removeOnExitListener` is needed to stop it from receiving + * exit messages. + * + * Closing the receive port that is associated with the [responsePort] does + * not stop the isolate from sending uncaught errors, they are just going to + * be lost. + * + * An exit message may still be sent if the isolate terminates + * before this request is received and processed. + */ + external void removeOnExitListener(SendPort responsePort); + + /** + * Sets whether uncaught errors will terminate the isolate. + * + * If errors are fatal, any uncaught error will terminate the isolate + * event loop and shut down the isolate. + * + * This call requires the [terminateCapability] for the isolate. + * If the capability is absent or incorrect, no change is made. + * + * Since isolates run concurrently, it's possible for the receiving isolate + * to exit due to an error, before a request, using this method, has been + * received and processed. + * To avoid this, either use the corresponding parameter to the spawn + * function, or start the isolate paused, set errors non-fatal and + * then resume the isolate. + */ + external void setErrorsFatal(bool errorsAreFatal); + + /** + * Requests the isolate to shut down. + * + * The isolate is requested to terminate itself. + * The [priority] argument specifies when this must happen. + * + * The [priority], when provided, must be one of [immediate] or + * [beforeNextEvent] (the default). + * The shutdown is performed at different times depending on the priority: + * + * * `immediate`: The isolate shuts down as soon as possible. + * Control messages are handled in order, so all previously sent control + * events from this isolate will all have been processed. + * The shutdown should happen no later than if sent with + * `beforeNextEvent`. + * It may happen earlier if the system has a way to shut down cleanly + * at an earlier time, even during the execution of another event. + * * `beforeNextEvent`: The shutdown is scheduled for the next time + * control returns to the event loop of the receiving isolate, + * after the current event, and any already scheduled control events, + * are completed. + * + * If [terminateCapability] is `null`, or it's not the terminate capability + * of the isolate identified by [controlPort], + * the kill request is ignored by the receiving isolate. + */ + external void kill({int priority: beforeNextEvent}); + + /** + * Requests that the isolate send [response] on the [responsePort]. + * + * The [response] object must follow the same restrictions as enforced by + * [SendPort.send]. + * It is recommended to only use simple values that can be sent to all + * isolates, like `null`, booleans, numbers or strings. + * + * If the isolate is alive, it will eventually send `response` + * (defaulting to `null`) on the response port. + * + * The [priority] must be one of [immediate] or [beforeNextEvent]. + * The response is sent at different times depending on the ping type: + * + * * `immediate`: The isolate responds as soon as it receives the + * control message. This is after any previous control message + * from the same isolate has been received and processed, + * but may be during execution of another event. + * * `beforeNextEvent`: The response is scheduled for the next time + * control returns to the event loop of the receiving isolate, + * after the current event, and any already scheduled control events, + * are completed. + */ + external void ping(SendPort responsePort, + {Object response, int priority: immediate}); + + /** + * Requests that uncaught errors of the isolate are sent back to [port]. + * + * The errors are sent back as two elements lists. + * The first element is a `String` representation of the error, usually + * created by calling `toString` on the error. + * The second element is a `String` representation of an accompanying + * stack trace, or `null` if no stack trace was provided. + * To convert this back to a [StackTrace] object, use [StackTrace.fromString]. + * + * Listening using the same port more than once does nothing. + * A port will only receive each error once, + * and will only need to be removed once using [removeErrorListener]. + + * Closing the receive port that is associated with the port does not stop + * the isolate from sending uncaught errors, they are just going to be lost. + * Instead use [removeErrorListener] to stop receiving errors on [port]. + * + * Since isolates run concurrently, it's possible for it to exit before the + * error listener is established. To avoid this, start the isolate paused, + * add the listener and then resume the isolate. + */ + external void addErrorListener(SendPort port); + + /** + * Stops listening for uncaught errors from the isolate. + * + * Requests for the isolate to not send uncaught errors on [port]. + * If the isolate isn't expecting to send uncaught errors on [port], + * because the port hasn't been added using [addErrorListener], + * or because it has already been removed, the request is ignored. + * + * If the same port has been passed via [addErrorListener] more than once, + * only one call to `removeErrorListener` is needed to stop it from receiving + * uncaught errors. + * + * Uncaught errors message may still be sent by the isolate + * until this request is received and processed. + */ + external void removeErrorListener(SendPort port); + + /** + * Returns a broadcast stream of uncaught errors from the isolate. + * + * Each error is provided as an error event on the stream. + * + * The actual error object and stackTraces will not necessarily + * be the same object types as in the actual isolate, but they will + * always have the same [Object.toString] result. + * + * This stream is based on [addErrorListener] and [removeErrorListener]. + */ + Stream get errors { + StreamController controller; + RawReceivePort port; + void handleError(message) { + String errorDescription = message[0]; + String stackDescription = message[1]; + var error = new RemoteError(errorDescription, stackDescription); + controller.addError(error, error.stackTrace); + } + + controller = new StreamController.broadcast( + sync: true, + onListen: () { + port = new RawReceivePort(handleError); + this.addErrorListener(port.sendPort); + }, + onCancel: () { + this.removeErrorListener(port.sendPort); + port.close(); + port = null; + }); + return controller.stream; + } +} + +/** + * Sends messages to its [ReceivePort]s. + * + * [SendPort]s are created from [ReceivePort]s. Any message sent through + * a [SendPort] is delivered to its corresponding [ReceivePort]. There might be + * many [SendPort]s for the same [ReceivePort]. + * + * [SendPort]s can be transmitted to other isolates, and they preserve equality + * when sent. + */ +abstract class SendPort implements Capability { + /** + * Sends an asynchronous [message] through this send port, to its + * corresponding `ReceivePort`. + * + * The content of [message] can be: primitive values (null, num, bool, double, + * String), instances of [SendPort], and lists and maps whose elements are any + * of these. List and maps are also allowed to be cyclic. + * + * In the special circumstances when two isolates share the same code and are + * running in the same process (e.g. isolates created via [Isolate.spawn]), it + * is also possible to send object instances (which would be copied in the + * process). This is currently only supported by the dartvm. For now, the + * dart2js compiler only supports the restricted messages described above. + * + * The send happens immediately and doesn't block. The corresponding receive + * port can receive the message as soon as its isolate's event loop is ready + * to deliver it, independently of what the sending isolate is doing. + */ + void send(var message); + + /** + * Tests whether [other] is a [SendPort] pointing to the same + * [ReceivePort] as this one. + */ + bool operator ==(var other); + + /** + * Returns an immutable hash code for this send port that is + * consistent with the == operator. + */ + int get hashCode; +} + +/** + * Together with [SendPort], the only means of communication between isolates. + * + * [ReceivePort]s have a `sendPort` getter which returns a [SendPort]. + * Any message that is sent through this [SendPort] + * is delivered to the [ReceivePort] it has been created from. There, the + * message is dispatched to the `ReceivePort`'s listener. + * + * A [ReceivePort] is a non-broadcast stream. This means that it buffers + * incoming messages until a listener is registered. Only one listener can + * receive messages. See [Stream.asBroadcastStream] for transforming the port + * to a broadcast stream. + * + * A [ReceivePort] may have many [SendPort]s. + */ +abstract class ReceivePort implements Stream { + /** + * Opens a long-lived port for receiving messages. + * + * A [ReceivePort] is a non-broadcast stream. This means that it buffers + * incoming messages until a listener is registered. Only one listener can + * receive messages. See [Stream.asBroadcastStream] for transforming the port + * to a broadcast stream. + * + * A receive port is closed by canceling its subscription. + */ + external factory ReceivePort(); + + /** + * Creates a [ReceivePort] from a [RawReceivePort]. + * + * The handler of the given [rawPort] is overwritten during the construction + * of the result. + */ + external factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort); + + /** + * Inherited from [Stream]. + * + * Note that [onError] and [cancelOnError] are ignored since a ReceivePort + * will never receive an error. + * + * The [onDone] handler will be called when the stream closes. + * The stream closes when [close] is called. + */ + StreamSubscription listen(void onData(var message), + {Function onError, void onDone(), bool cancelOnError}); + + /** + * Closes `this`. + * + * If the stream has not been canceled yet, adds a close-event to the event + * queue and discards any further incoming messages. + * + * If the stream has already been canceled this method has no effect. + */ + void close(); + + /** + * Returns a [SendPort] that sends to this receive port. + */ + SendPort get sendPort; +} + +abstract class RawReceivePort { + /** + * Opens a long-lived port for receiving messages. + * + * A [RawReceivePort] is low level and does not work with [Zone]s. It + * can not be paused. The data-handler must be set before the first + * event is received. + */ + external factory RawReceivePort([Function handler]); + + /** + * Sets the handler that is invoked for every incoming message. + * + * The handler is invoked in the root-zone ([Zone.root]). + */ + void set handler(Function newHandler); + + /** + * Closes the port. + * + * After a call to this method any incoming message is silently dropped. + */ + void close(); + + /** + * Returns a [SendPort] that sends to this raw receive port. + */ + SendPort get sendPort; +} + +/** + * Description of an error from another isolate. + * + * This error has the same `toString()` and `stackTrace.toString()` behavior + * as the original error, but has no other features of the original error. + */ +class RemoteError implements Error { + final String _description; + final StackTrace stackTrace; + RemoteError(String description, String stackDescription) + : _description = description, + stackTrace = new StackTrace.fromString(stackDescription); + String toString() => _description; +} +NN<,3$%-38':'LM9L>KJQ GBLMDI%D@I:NM5B"N(@.9LI6;-O10IL$?AJ<6(JEH(OMMK *C' HIHOB2&GGIF)'OOL/6IL%1/GCALFKB0558@@A%H+CBNLHE5(3>B&M@O@?LIFELN1;7FLI:A2EIDE@7FEL,3K5J1H34E=BF4K! ,,G4120 3 )IP0P0D"QQ<PQMMMPOH@ ?&OG4J:IKN./5KMP="6OKM"A/6>N7H; 5HF7B<)K?1MK%;$B%lfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dartJ// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Patch file for the dart:isolate library. + +import 'dart:_js_helper' show patch, NoReifyGeneric; +import 'dart:async'; + +@patch +class Isolate { + // `current` must be a getter, not just a final field, + // to match the external declaration. + @patch + static Isolate get current => _unsupported(); + + @patch + static Future get packageRoot => _unsupported(); + + @patch + static Future get packageConfig => _unsupported(); + + static Uri _packageBase = Uri.base.resolve('packages/'); + + @patch + static Future resolvePackageUri(Uri packageUri) async { + if (packageUri.scheme != 'package') return packageUri; + return _packageBase.resolveUri(packageUri.replace(scheme: '')); + } + + @patch + static Future spawn(void entryPoint(T message), T message, + {bool paused = false, + bool errorsAreFatal, + SendPort onExit, + SendPort onError}) => + _unsupported(); + + @patch + static Future spawnUri(Uri uri, List args, var message, + {bool paused = false, + SendPort onExit, + SendPort onError, + bool errorsAreFatal, + bool checked, + Map environment, + Uri packageRoot, + Uri packageConfig, + bool automaticPackageResolution = false}) => + _unsupported(); + + @patch + void _pause(Capability resumeCapability) => _unsupported(); + + @patch + void resume(Capability resumeCapability) => _unsupported(); + + @patch + void addOnExitListener(SendPort responsePort, {Object response}) => + _unsupported(); + + @patch + void removeOnExitListener(SendPort responsePort) => _unsupported(); + + @patch + void setErrorsFatal(bool errorsAreFatal) => _unsupported(); + + @patch + void kill({int priority = beforeNextEvent}) => _unsupported(); + @patch + void ping(SendPort responsePort, + {Object response, int priority = immediate}) => + _unsupported(); + + @patch + void addErrorListener(SendPort port) => _unsupported(); + + @patch + void removeErrorListener(SendPort port) => _unsupported(); +} + +/** Default factory for receive ports. */ +@patch +class ReceivePort { + @patch + factory ReceivePort() = _ReceivePort; + + @patch + factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) => + _unsupported(); +} + +/// ReceivePort is supported by dev_compiler because async test packages +/// (async_helper, unittest) create a dummy receive port to keep the Dart VM +/// alive. +class _ReceivePort extends Stream implements ReceivePort { + close() {} + + get sendPort => _unsupported(); + + listen(onData, {onError, onDone, cancelOnError}) => _unsupported(); +} + +@patch +class RawReceivePort { + @patch + factory RawReceivePort([void handler(event)]) => _unsupported(); +} + +@patch +class Capability { + @patch + factory Capability() => _unsupported(); +} + +@NoReifyGeneric() +T _unsupported() { + throw UnsupportedError('dart:isolate is not supported on dart4web'); +} +yNN<,59( 0 8 :; ?;D I   K +7 > > F F > A #: : =* ( DIM ; "F C *GSfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/isolate/capability.dart// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.isolate; + +/** + * An unforgeable object that comes back as equal when passed through other + * isolates. + * + * Sending a capability object to another isolate, and getting it back, + * will produce an object that is equal to the original. + * There is no other way to create objects equal to a capability object. + * + * Capabilities can be used as access guards: A remote isolate can send + * a request for an operation, but it is only allowed if the request contains + * the correct capability object. + * + * This allows exposing the same interface to multiple clients, + * but restricting some operations to only those clients + * that have also been given the corresponding capability. + * + * Capabilities can be used inside a single isolate, + * but they have no advantage over + * just using `new Object` to create a unique object, + * and it offers no real security against other code + * running in the same isolate. + */ +class Capability { + /** + * Create a new unforgeable capability object. + */ + external factory Capability(); +} +$NN<L H9IHN"@9;5#65 1!rfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dartG// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Support for interoperating with JavaScript. + * + * This library provides access to JavaScript objects from Dart, allowing + * Dart code to get and set properties, and call methods of JavaScript objects + * and invoke JavaScript functions. The library takes care of converting + * between Dart and JavaScript objects where possible, or providing proxies if + * conversion isn't possible. + * + * This library does not yet make Dart objects usable from JavaScript, their + * methods and proeprties are not accessible, though it does allow Dart + * functions to be passed into and called from JavaScript. + * + * [JsObject] is the core type and represents a proxy of a JavaScript object. + * JsObject gives access to the underlying JavaScript objects properties and + * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be + * created from proxies to JavaScript constructors. + * + * The top-level getter [context] provides a [JsObject] that represents the + * global object in JavaScript, usually `window`. + * + * The following example shows an alert dialog via a JavaScript call to the + * global function `alert()`: + * + * import 'dart:js'; + * + * main() => context.callMethod('alert', ['Hello from Dart!']); + * + * This example shows how to create a [JsObject] from a JavaScript constructor + * and access its properties: + * + * import 'dart:js'; + * + * main() { + * var object = new JsObject(context['Object']); + * object['greeting'] = 'Hello'; + * object['greet'] = (name) => "${object['greeting']} $name"; + * var message = object.callMethod('greet', ['JavaScript']); + * context['console'].callMethod('log', [message]); + * } + * + * ## Proxying and automatic conversion + * + * When setting properties on a JsObject or passing arguments to a Javascript + * method or function, Dart objects are automatically converted or proxied to + * JavaScript objects. When accessing JavaScript properties, or when a Dart + * closure is invoked from JavaScript, the JavaScript objects are also + * converted to Dart. + * + * Functions and closures are proxied in such a way that they are callable. A + * Dart closure assigned to a JavaScript property is proxied by a function in + * JavaScript. A JavaScript function accessed from Dart is proxied by a + * [JsFunction], which has a [apply] method to invoke it. + * + * The following types are transferred directly and not proxied: + * + * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime` + * * `Blob` + * * `Event` + * * `HtmlCollection` + * * `ImageData` + * * `KeyRange` + * * `Node` + * * `NodeList` + * * `TypedData`, including its subclasses like `Int32List`, but _not_ + * `ByteBuffer` + * * `Window` + * + * ## Converting collections with JsObject.jsify() + * + * To create a JavaScript collection from a Dart collection use the + * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s + * into JavaScript Objects and Arrays. + * + * The following expression creates a new JavaScript object with the properties + * `a` and `b` defined: + * + * var jsMap = new JsObject.jsify({'a': 1, 'b': 2}); + * + * This expression creates a JavaScript array: + * + * var jsArray = new JsObject.jsify([1, 2, 3]); + */ +library dart.js; + +import 'dart:collection' show HashMap, ListMixin; + +import 'dart:_js_helper' show Primitives; +import 'dart:_foreign_helper' show JS; +import 'dart:_runtime' as dart; + +final JsObject context = _wrapToDart(dart.global_); + +/** + * Proxies a JavaScript object to Dart. + * + * The properties of the JavaScript object are accessible via the `[]` and + * `[]=` operators. Methods are callable via [callMethod]. + */ +class JsObject { + // The wrapped JS object. + final dynamic _jsObject; + + // This should only be called from _wrapToDart + JsObject._fromJs(this._jsObject) { + assert(_jsObject != null); + } + + /** + * Constructs a new JavaScript object from [constructor] and returns a proxy + * to it. + */ + factory JsObject(JsFunction constructor, [List arguments]) { + var ctor = constructor._jsObject; + if (arguments == null) { + return _wrapToDart(JS('', 'new #()', ctor)); + } + var unwrapped = List.from(arguments.map(_convertToJS)); + return _wrapToDart(JS('', 'new #(...#)', ctor, unwrapped)); + } + + /** + * Constructs a [JsObject] that proxies a native Dart object; _for expert use + * only_. + * + * Use this constructor only if you wish to get access to JavaScript + * properties attached to a browser host object, such as a Node or Blob, that + * is normally automatically converted into a native Dart object. + * + * An exception will be thrown if [object] either is `null` or has the type + * `bool`, `num`, or `String`. + */ + factory JsObject.fromBrowserObject(object) { + if (object is num || object is String || object is bool || object == null) { + throw ArgumentError("object cannot be a num, string, bool, or null"); + } + return _wrapToDart(_convertToJS(object)); + } + + /** + * Recursively converts a JSON-like collection of Dart objects to a + * collection of JavaScript objects and returns a [JsObject] proxy to it. + * + * [object] must be a [Map] or [Iterable], the contents of which are also + * converted. Maps and Iterables are copied to a new JavaScript object. + * Primitives and other transferable values are directly converted to their + * JavaScript type, and all other objects are proxied. + */ + factory JsObject.jsify(object) { + if ((object is! Map) && (object is! Iterable)) { + throw ArgumentError("object must be a Map or Iterable"); + } + return _wrapToDart(_convertDataTree(object)); + } + + static _convertDataTree(data) { + var _convertedObjects = HashMap.identity(); + + _convert(o) { + if (_convertedObjects.containsKey(o)) { + return _convertedObjects[o]; + } + if (o is Map) { + final convertedMap = JS('', '{}'); + _convertedObjects[o] = convertedMap; + for (var key in o.keys) { + JS('', '#[#] = #', convertedMap, key, _convert(o[key])); + } + return convertedMap; + } else if (o is Iterable) { + var convertedList = []; + _convertedObjects[o] = convertedList; + convertedList.addAll(o.map(_convert)); + return convertedList; + } else { + return _convertToJS(o); + } + } + + return _convert(data); + } + + /** + * Returns the value associated with [property] from the proxied JavaScript + * object. + * + * The type of [property] must be either [String] or [num]. + */ + dynamic operator [](Object property) { + if (property is! String && property is! num) { + throw ArgumentError("property is not a String or num"); + } + return _convertToDart(JS('', '#[#]', _jsObject, property)); + } + + /** + * Sets the value associated with [property] on the proxied JavaScript + * object. + * + * The type of [property] must be either [String] or [num]. + */ + void operator []=(Object property, value) { + if (property is! String && property is! num) { + throw ArgumentError("property is not a String or num"); + } + JS('', '#[#] = #', _jsObject, property, _convertToJS(value)); + } + + int get hashCode => 0; + + bool operator ==(other) => + other is JsObject && JS('bool', '# === #', _jsObject, other._jsObject); + + /** + * Returns `true` if the JavaScript object contains the specified property + * either directly or though its prototype chain. + * + * This is the equivalent of the `in` operator in JavaScript. + */ + bool hasProperty(property) { + if (property is! String && property is! num) { + throw ArgumentError("property is not a String or num"); + } + return JS('bool', '# in #', property, _jsObject); + } + + /** + * Removes [property] from the JavaScript object. + * + * This is the equivalent of the `delete` operator in JavaScript. + */ + void deleteProperty(property) { + if (property is! String && property is! num) { + throw ArgumentError("property is not a String or num"); + } + JS('bool', 'delete #[#]', _jsObject, property); + } + + /** + * Returns `true` if the JavaScript object has [type] in its prototype chain. + * + * This is the equivalent of the `instanceof` operator in JavaScript. + */ + bool instanceof(JsFunction type) { + return JS('bool', '# instanceof #', _jsObject, _convertToJS(type)); + } + + /** + * Returns the result of the JavaScript objects `toString` method. + */ + String toString() { + try { + return JS('String', 'String(#)', _jsObject); + } catch (e) { + return super.toString(); + } + } + + /** + * Calls [method] on the JavaScript object with the arguments [args] and + * returns the result. + * + * The type of [method] must be either [String] or [num]. + */ + dynamic callMethod(method, [List args]) { + if (method is! String && method is! num) { + throw ArgumentError("method is not a String or num"); + } + if (args != null) args = List.from(args.map(_convertToJS)); + var fn = JS('', '#[#]', _jsObject, method); + if (JS('bool', 'typeof(#) !== "function"', fn)) { + throw NoSuchMethodError(_jsObject, Symbol(method), args, {}); + } + return _convertToDart(JS('', '#.apply(#, #)', fn, _jsObject, args)); + } +} + +/** + * Proxies a JavaScript Function object. + */ +class JsFunction extends JsObject { + /** + * Returns a [JsFunction] that captures its 'this' binding and calls [f] + * with the value of this passed as the first argument. + */ + factory JsFunction.withThis(Function f) { + return JsFunction._fromJs(JS( + '', + 'function(/*...arguments*/) {' + ' let args = [#(this)];' + ' for (let arg of arguments) {' + ' args.push(#(arg));' + ' }' + ' return #(#(...args));' + '}', + _convertToDart, + _convertToDart, + _convertToJS, + f)); + } + + JsFunction._fromJs(jsObject) : super._fromJs(jsObject); + + /** + * Invokes the JavaScript function with arguments [args]. If [thisArg] is + * supplied it is the value of `this` for the invocation. + */ + dynamic apply(List args, {thisArg}) => _convertToDart(JS( + '', + '#.apply(#, #)', + _jsObject, + _convertToJS(thisArg), + args == null ? null : List.from(args.map(_convertToJS)))); +} + +// TODO(jmesserly): this is totally unnecessary in dev_compiler. +/** A [List] that proxies a JavaScript array. */ +class JsArray extends JsObject with ListMixin { + /** + * Creates a new JavaScript array. + */ + JsArray() : super._fromJs([]); + + /** + * Creates a new JavaScript array and initializes it to the contents of + * [other]. + */ + JsArray.from(Iterable other) + : super._fromJs([]..addAll(other.map(_convertToJS))); + + JsArray._fromJs(jsObject) : super._fromJs(jsObject); + + _checkIndex(int index) { + if (index is int && (index < 0 || index >= length)) { + throw RangeError.range(index, 0, length); + } + } + + _checkInsertIndex(int index) { + if (index is int && (index < 0 || index >= length + 1)) { + throw RangeError.range(index, 0, length); + } + } + + static _checkRange(int start, int end, int length) { + if (start < 0 || start > length) { + throw RangeError.range(start, 0, length); + } + if (end < start || end > length) { + throw RangeError.range(end, start, length); + } + } + + // Methods required by ListMixin + + E operator [](Object index) { + // TODO(justinfagnani): fix the semantics for non-ints + // dartbug.com/14605 + if (index is num && index == index.toInt()) { + _checkIndex(index); + } + return super[index] as E; + } + + void operator []=(Object index, value) { + // TODO(justinfagnani): fix the semantics for non-ints + // dartbug.com/14605 + if (index is num && index == index.toInt()) { + _checkIndex(index); + } + super[index] = value; + } + + int get length { + // Check the length honours the List contract. + var len = JS('', '#.length', _jsObject); + // JavaScript arrays have lengths which are unsigned 32-bit integers. + if (JS('bool', 'typeof # === "number" && (# >>> 0) === #', len, len, len)) { + return JS('int', '#', len); + } + throw StateError('Bad JsArray length'); + } + + void set length(int length) { + super['length'] = length; + } + + // Methods overridden for better performance + + void add(E value) { + callMethod('push', [value]); + } + + void addAll(Iterable iterable) { + var list = (JS('bool', '# instanceof Array', iterable)) + ? iterable + : List.from(iterable); + callMethod('push', list); + } + + void insert(int index, E element) { + _checkInsertIndex(index); + callMethod('splice', [index, 0, element]); + } + + E removeAt(int index) { + _checkIndex(index); + return callMethod('splice', [index, 1])[0] as E; + } + + E removeLast() { + if (length == 0) throw RangeError(-1); + return callMethod('pop') as E; + } + + void removeRange(int start, int end) { + _checkRange(start, end, length); + callMethod('splice', [start, end - start]); + } + + void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { + _checkRange(start, end, this.length); + int length = end - start; + if (length == 0) return; + if (skipCount < 0) throw ArgumentError(skipCount); + var args = [start, length] + ..addAll(iterable.skip(skipCount).take(length)); + callMethod('splice', args); + } + + void sort([int compare(E a, E b)]) { + // Note: arr.sort(null) is a type error in FF + callMethod('sort', compare == null ? [] : [compare]); + } +} + +// Cross frame objects should not be considered browser types. +// We include the instanceof Object test to filter out cross frame objects +// on FireFox. Surprisingly on FireFox the instanceof Window test succeeds for +// cross frame windows while the instanceof Object test fails. +bool _isBrowserType(o) => JS( + 'bool', + '# instanceof Object && (' + '# instanceof Blob || ' + '# instanceof Event || ' + '(window.KeyRange && # instanceof KeyRange) || ' + '(window.IDBKeyRange && # instanceof IDBKeyRange) || ' + '# instanceof ImageData || ' + '# instanceof Node || ' + // Int8Array.__proto__ is TypedArray. + '(window.Int8Array && # instanceof Int8Array.__proto__) || ' + '# instanceof Window)', + o, + o, + o, + o, + o, + o, + o, + o, + o); + +class _DartObject { + final _dartObj; + _DartObject(this._dartObj); +} + +dynamic _convertToJS(dynamic o) { + if (o == null || o is String || o is num || o is bool || _isBrowserType(o)) { + return o; + } else if (o is DateTime) { + return Primitives.lazyAsJsDate(o); + } else if (o is JsObject) { + return o._jsObject; + } else if (o is Function) { + return _putIfAbsent(_jsProxies, o, _wrapDartFunction); + } else { + // TODO(jmesserly): for now, we wrap other objects, to keep compatibility + // with the original dart:js behavior. + return _putIfAbsent(_jsProxies, o, (o) => _DartObject(o)); + } +} + +dynamic _wrapDartFunction(f) { + var wrapper = JS( + '', + 'function(/*...arguments*/) {' + ' let args = Array.prototype.map.call(arguments, #);' + ' return #(#(...args));' + '}', + _convertToDart, + _convertToJS, + f); + JS('', '#.set(#, #)', _dartProxies, wrapper, f); + + return wrapper; +} + +// converts a Dart object to a reference to a native JS object +// which might be a DartObject JS->Dart proxy +Object _convertToDart(o) { + if (o == null || o is String || o is num || o is bool || _isBrowserType(o)) { + return o; + } else if (JS('!', '# instanceof Date', o)) { + num ms = JS('!', '#.getTime()', o); + return DateTime.fromMillisecondsSinceEpoch(ms); + } else if (o is _DartObject && + !identical(dart.getReifiedType(o), dart.jsobject)) { + return o._dartObj; + } else { + return _wrapToDart(o); + } +} + +Object _wrapToDart(o) => _putIfAbsent(_dartProxies, o, _wrapToDartHelper); + +Object _wrapToDartHelper(o) { + if (JS('bool', 'typeof # == "function"', o)) { + return JsFunction._fromJs(o); + } + if (JS('bool', '# instanceof Array', o)) { + return JsArray._fromJs(o); + } + return JsObject._fromJs(o); +} + +final _dartProxies = JS('', 'new WeakMap()'); +final _jsProxies = JS('', 'new WeakMap()'); + +Object _putIfAbsent(weakMap, o, getValue(o)) { + var value = JS('', '#.get(#)', weakMap, o); + if (value == null) { + value = getValue(o); + JS('', '#.set(#, #)', weakMap, o, value); + } + return value; +} + +// The allowInterop method is a no-op in Dart Dev Compiler. +// TODO(jacobr): tag methods so we can throw if a Dart method is passed to +// JavaScript using the new interop without calling allowInterop. + +/// Returns a wrapper around function [f] that can be called from JavaScript +/// using the package:js Dart-JavaScript interop. +/// +/// For performance reasons in Dart2Js, by default Dart functions cannot be +/// passed directly to JavaScript unless this method is called to create +/// a Function compatible with both Dart and JavaScript. +/// Calling this method repeatedly on a function will return the same function. +/// The [Function] returned by this method can be used from both Dart and +/// JavaScript. We may remove the need to call this method completely in the +/// future if Dart2Js is refactored so that its function calling conventions +/// are more compatible with JavaScript. +F allowInterop(F f) => f; + +Expando _interopCaptureThisExpando = Expando(); + +/// Returns a [Function] that when called from JavaScript captures its 'this' +/// binding and calls [f] with the value of this passed as the first argument. +/// When called from Dart, [null] will be passed as the first argument. +/// +/// See the documentation for [allowInterop]. This method should only be used +/// with package:js Dart-JavaScript interop. +Function allowInteropCaptureThis(Function f) { + var ret = _interopCaptureThisExpando[f]; + if (ret == null) { + ret = JS( + '', + 'function(/*...arguments*/) {' + ' let args = [this];' + ' for (let arg of arguments) {' + ' args.push(arg);' + ' }' + ' return #(...args);' + '}', + f); + _interopCaptureThisExpando[f] = ret; + } + return ret; +} +JNN</JOIOMH;NMO4L2LDO7'DC: (NNLGNNH:A@  G3DL'P9/42*' 4(K;1%O ?&3<@P GPDN!/QL.FLLJN9#5?2"0.%+-"C +" ./ N >)3>@I >.3>BNM4@3>64D"3>4PH%HE +3K<,/<@06DI)$K:," '")!"  :L<< +AA16%!J"<7:0!>07'0'2# ;2+;23-JQ", /!&<&/5+#)%0Q*7'7 '2:?KO? 5;!*A"P'; N+? +%=  +3?.P0(4!; K1"-.,/.. JS('=Object', '{}'); + +hasProperty(o, name) => JS('bool', '# in #', name, o); +getProperty(o, name) => JS('Object', '#[#]', o, name); +setProperty(o, name, value) => JS('', '#[#]=#', o, name, value); + +callMethod(o, String method, List args) => + JS('Object', '#[#].apply(#, #)', o, method, o, args); + +instanceof(o, Function type) => JS('bool', '# instanceof #', o, type); +callConstructor(Function constr, List arguments) { + if (arguments == null) { + return JS('Object', 'new #()', constr); + } + + if (JS('bool', '# instanceof Array', arguments)) { + int argumentCount = JS('!', '#.length', arguments); + switch (argumentCount) { + case 0: + return JS('Object', 'new #()', constr); + + case 1: + var arg0 = JS('', '#[0]', arguments); + return JS('Object', 'new #(#)', constr, arg0); + + case 2: + var arg0 = JS('', '#[0]', arguments); + var arg1 = JS('', '#[1]', arguments); + return JS('Object', 'new #(#, #)', constr, arg0, arg1); + + case 3: + var arg0 = JS('', '#[0]', arguments); + var arg1 = JS('', '#[1]', arguments); + var arg2 = JS('', '#[2]', arguments); + return JS('Object', 'new #(#, #, #)', constr, arg0, arg1, arg2); + + case 4: + var arg0 = JS('', '#[0]', arguments); + var arg1 = JS('', '#[1]', arguments); + var arg2 = JS('', '#[2]', arguments); + var arg3 = JS('', '#[3]', arguments); + return JS( + 'Object', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg3); + } + } + + // The following code solves the problem of invoking a JavaScript + // constructor with an unknown number arguments. + // First bind the constructor to the argument list using bind.apply(). + // The first argument to bind() is the binding of 't', so add 'null' to + // the arguments list passed to apply(). + // After that, use the JavaScript 'new' operator which overrides any binding + // of 'this' with the new instance. + var args = [null]..addAll(arguments); + var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args); + // Without this line, calling factoryFunction as a constructor throws + JS('String', 'String(#)', factoryFunction); + // This could return an UnknownJavaScriptObject, or a native + // object for which there is an interceptor + return JS('Object', 'new #()', factoryFunction); + + // TODO(sra): Investigate: + // + // var jsObj = JS('', 'Object.create(#.prototype)', constr); + // JS('', '#.apply(#, #)', constr, jsObj, + // []..addAll(arguments.map(_convertToJS))); + // return _wrapToDart(jsObj); +} +NN<ONJK''GDEKKIN83=#.,#0+ F ,- $77A+:G3,580.7..@...I....LD3IJ+O&1LH.?.3C07$Jfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/math/math.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Mathematical constants and functions, plus a random number generator. + * + * To use this library in your code: + * + * import 'dart:math'; + * + * {@category Core} + */ +library dart.math; + +part "jenkins_smi_hash.dart"; +part "point.dart"; +part "random.dart"; +part "rectangle.dart"; + +/** + * Base of the natural logarithms. + * + * Typically written as "e". + */ +const double e = 2.718281828459045; + +/** + * Natural logarithm of 10. + * + * The natural logarithm of 10 is the number such that `pow(E, LN10) == 10`. + * This value is not exact, but it is the closest representable double to the + * exact mathematical value. + */ +const double ln10 = 2.302585092994046; + +/** + * Natural logarithm of 2. + * + * The natural logarithm of 2 is the number such that `pow(E, LN2) == 2`. + * This value is not exact, but it is the closest representable double to the + * exact mathematical value. + */ +const double ln2 = 0.6931471805599453; + +/** + * Base-2 logarithm of [e]. + */ +const double log2e = 1.4426950408889634; + +/** + * Base-10 logarithm of [e]. + */ +const double log10e = 0.4342944819032518; + +/** + * The PI constant. + */ +const double pi = 3.1415926535897932; + +/** + * Square root of 1/2. + */ +const double sqrt1_2 = 0.7071067811865476; + +/** + * Square root of 2. + */ +const double sqrt2 = 1.4142135623730951; + +/** + * Returns the lesser of two numbers. + * + * Returns NaN if either argument is NaN. + * The lesser of `-0.0` and `0.0` is `-0.0`. + * If the arguments are otherwise equal (including int and doubles with the + * same mathematical value) then it is unspecified which of the two arguments + * is returned. + */ +external T min(T a, T b); + +/** + * Returns the larger of two numbers. + * + * Returns NaN if either argument is NaN. + * The larger of `-0.0` and `0.0` is `0.0`. If the arguments are + * otherwise equal (including int and doubles with the same mathematical value) + * then it is unspecified which of the two arguments is returned. + */ +external T max(T a, T b); + +/** + * A variant of [atan]. + * + * Converts both arguments to [double]s. + * + * Returns the angle in radians between the positive x-axis + * and the vector ([b],[a]). + * The result is in the range -PI..PI. + * + * If [b] is positive, this is the same as `atan(b/a)`. + * + * The result is negative when [a] is negative (including when [a] is the + * double -0.0). + * + * If [a] is equal to zero, the vector ([b],[a]) is considered parallel to + * the x-axis, even if [b] is also equal to zero. The sign of [b] determines + * the direction of the vector along the x-axis. + * + * Returns NaN if either argument is NaN. + */ +external double atan2(num a, num b); + +/** + * Returns [x] to the power of [exponent]. + * + * If [x] is an [int] and [exponent] is a non-negative [int], the result is + * an [int], otherwise both arguments are converted to doubles first, and the + * result is a [double]. + * + * For integers, the power is always equal to the mathematical result of `x` to + * the power `exponent`, only limited by the available memory. + * + * For doubles, `pow(x, y)` handles edge cases as follows: + * + * - if `y` is zero (0.0 or -0.0), the result is always 1.0. + * - if `x` is 1.0, the result is always 1.0. + * - otherwise, if either `x` or `y` is NaN then the result is NaN. + * - if `x` is negative (but not -0.0) and `y` is a finite non-integer, the + * result is NaN. + * - if `x` is Infinity and `y` is negative, the result is 0.0. + * - if `x` is Infinity and `y` is positive, the result is Infinity. + * - if `x` is 0.0 and `y` is negative, the result is Infinity. + * - if `x` is 0.0 and `y` is positive, the result is 0.0. + * - if `x` is -Infinity or -0.0 and `y` is an odd integer, then the result is + * `-pow(-x ,y)`. + * - if `x` is -Infinity or -0.0 and `y` is not an odd integer, then the result + * is the same as `pow(-x , y)`. + * - if `y` is Infinity and the absolute value of `x` is less than 1, the + * result is 0.0. + * - if `y` is Infinity and `x` is -1, the result is 1.0. + * - if `y` is Infinity and the absolute value of `x` is greater than 1, + * the result is Infinity. + * - if `y` is -Infinity, the result is `1/pow(x, Infinity)`. + * + * This corresponds to the `pow` function defined in the IEEE Standard 754-2008. + * + * Notice that an [int] result cannot overflow, but a [double] result might + * be [double.infinity]. + */ +external num pow(num x, num exponent); + +/** + * Converts [radians] to a [double] and returns the sine of the value. + * + * If [radians] is not a finite number, the result is NaN. + */ +external double sin(num radians); + +/** + * Converts [radians] to a [double] and returns the cosine of the value. + * + * If [radians] is not a finite number, the result is NaN. + */ +external double cos(num radians); + +/** + * Converts [radians] to a [double] and returns the tangent of the value. + * + * The tangent function is equivalent to `sin(radians)/cos(radians)` and may be + * infinite (positive or negative) when `cos(radians)` is equal to zero. + * If [radians] is not a finite number, the result is NaN. + */ +external double tan(num radians); + +/** + * Converts [x] to a [double] and returns its arc cosine in radians. + * + * Returns a value in the range 0..PI, or NaN if [x] is outside + * the range -1..1. + */ +external double acos(num x); + +/** + * Converts [x] to a [double] and returns its arc sine in radians. + * + * Returns a value in the range -PI/2..PI/2, or NaN if [x] is outside + * the range -1..1. + */ +external double asin(num x); + +/** + * Converts [x] to a [double] and returns its arc tangent in radians. + * + * Returns a value in the range -PI/2..PI/2, or NaN if [x] is NaN. + */ +external double atan(num x); + +/** + * Converts [x] to a [double] and returns the positive square root of the value. + * + * Returns -0.0 if [x] is -0.0, and NaN if [x] is otherwise negative or NaN. + */ +external double sqrt(num x); + +/** + * Converts [x] to a [double] and returns the natural exponent, [e], + * to the power [x]. + * + * Returns NaN if [x] is NaN. + */ +external double exp(num x); + +/** + * Converts [x] to a [double] and returns the natural logarithm of the value. + * + * Returns negative infinity if [x] is equal to zero. + * Returns NaN if [x] is NaN or less than zero. + */ +external double log(num x); +NN<I%#$MN'JN')*&+)'+.MO)'+BQC))<'8JKM1*%+LNP?;=.DL@E@;OP#J:I>QL'G;"I;"JPI;"E@CFFCQMEN60ifile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dartU// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Patch file for dart:math library. +import 'dart:_foreign_helper' show JS; +import 'dart:_js_helper' show patch, nullCheck, notNull; +import 'dart:typed_data' show ByteData; + +@patch +@notNull +T min(@nullCheck T a, @nullCheck T b) => + JS('-dynamic', r'Math.min(#, #)', a, b); + +@patch +@notNull +T max(@nullCheck T a, @nullCheck T b) => + JS('-dynamic', r'Math.max(#, #)', a, b); + +@patch +@notNull +double sqrt(@nullCheck num x) => JS('num', r'Math.sqrt(#)', x); + +@patch +@notNull +double sin(@nullCheck num radians) => JS('num', r'Math.sin(#)', radians); + +@patch +@notNull +double cos(@nullCheck num radians) => JS('num', r'Math.cos(#)', radians); + +@patch +@notNull +double tan(@nullCheck num radians) => JS('num', r'Math.tan(#)', radians); + +@patch +@notNull +double acos(@nullCheck num x) => JS('num', r'Math.acos(#)', x); + +@patch +@notNull +double asin(@nullCheck num x) => JS('num', r'Math.asin(#)', x); + +@patch +@notNull +double atan(@nullCheck num x) => JS('num', r'Math.atan(#)', x); + +@patch +@notNull +double atan2(@nullCheck num a, @nullCheck num b) => + JS('num', r'Math.atan2(#, #)', a, b); + +@patch +@notNull +double exp(@nullCheck num x) => JS('num', r'Math.exp(#)', x); + +@patch +@notNull +double log(@nullCheck num x) => JS('num', r'Math.log(#)', x); + +@patch +@notNull +num pow(@nullCheck num x, @nullCheck num exponent) => + JS('num', r'Math.pow(#, #)', x, exponent); + +const int _POW2_32 = 0x100000000; + +@patch +class Random { + static final _secureRandom = _JSSecureRandom(); + + @patch + factory Random([int seed]) => + (seed == null) ? const _JSRandom() : _Random(seed); + + @patch + factory Random.secure() => _secureRandom; +} + +class _JSRandom implements Random { + // The Dart2JS implementation of Random doesn't use a seed. + const _JSRandom(); + + @notNull + int nextInt(int max) { + if (max <= 0 || max > _POW2_32) { + throw RangeError("max must be in range 0 < max ≤ 2^32, was $max"); + } + return JS("int", "(Math.random() * #) >>> 0", max); + } + + /** + * Generates a positive random floating point value uniformly distributed on + * the range from 0.0, inclusive, to 1.0, exclusive. + */ + @notNull + double nextDouble() => JS("double", "Math.random()"); + + /** + * Generates a random boolean value. + */ + @notNull + bool nextBool() => JS("bool", "Math.random() < 0.5"); +} + +class _Random implements Random { + // Constants used by the algorithm or masking. + static const double _POW2_53_D = 1.0 * (0x20000000000000); + static const double _POW2_27_D = 1.0 * (1 << 27); + static const int _MASK32 = 0xFFFFFFFF; + + // State comprised of two unsigned 32 bit integers. + @notNull + int _lo = 0; + @notNull + int _hi = 0; + + // Implements: + // uint64_t hash = 0; + // do { + // hash = hash * 1037 ^ mix64((uint64_t)seed); + // seed >>= 64; + // } while (seed != 0 && seed != -1); // Limits for pos/neg seed. + // if (hash == 0) { + // hash = 0x5A17; + // } + // _lo = hash & _MASK_32; + // _hi = hash >> 32; + // and then does four _nextState calls to shuffle bits around. + _Random(int seed) { + int empty_seed = 0; + if (seed < 0) { + empty_seed = -1; + } + do { + int low = seed & _MASK32; + seed = (seed - low) ~/ _POW2_32; + int high = seed & _MASK32; + seed = (seed - high) ~/ _POW2_32; + + // Thomas Wang's 64-bit mix function. + // http://www.concentric.net/~Ttwang/tech/inthash.htm + // via. http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm + + // key = ~key + (key << 21); + int tmplow = low << 21; + int tmphigh = (high << 21) | (low >> 11); + tmplow = (~low & _MASK32) + tmplow; + low = tmplow & _MASK32; + high = (~high + tmphigh + ((tmplow - low) ~/ 0x100000000)) & _MASK32; + // key = key ^ (key >> 24). + tmphigh = high >> 24; + tmplow = (low >> 24) | (high << 8); + low ^= tmplow; + high ^= tmphigh; + // key = key * 265 + tmplow = low * 265; + low = tmplow & _MASK32; + high = (high * 265 + (tmplow - low) ~/ 0x100000000) & _MASK32; + // key = key ^ (key >> 14); + tmphigh = high >> 14; + tmplow = (low >> 14) | (high << 18); + low ^= tmplow; + high ^= tmphigh; + // key = key * 21 + tmplow = low * 21; + low = tmplow & _MASK32; + high = (high * 21 + (tmplow - low) ~/ 0x100000000) & _MASK32; + // key = key ^ (key >> 28). + tmphigh = high >> 28; + tmplow = (low >> 28) | (high << 4); + low ^= tmplow; + high ^= tmphigh; + // key = key + (key << 31); + tmplow = low << 31; + tmphigh = (high << 31) | (low >> 1); + tmplow += low; + low = tmplow & _MASK32; + high = (high + tmphigh + (tmplow - low) ~/ 0x100000000) & _MASK32; + // Mix end. + + // seed = seed * 1037 ^ key; + tmplow = _lo * 1037; + _lo = tmplow & _MASK32; + _hi = (_hi * 1037 + (tmplow - _lo) ~/ 0x100000000) & _MASK32; + _lo ^= low; + _hi ^= high; + } while (seed != empty_seed); + + if (_hi == 0 && _lo == 0) { + _lo = 0x5A17; + } + _nextState(); + _nextState(); + _nextState(); + _nextState(); + } + + // The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32. + // http://en.wikipedia.org/wiki/Multiply-with-carry + // The constant A (0xFFFFDA61) is selected from "Numerical Recipes 3rd + // Edition" p.348 B1. + + // Implements: + // var state = (A * _lo + _hi) & _MASK_64; + // _lo = state & _MASK_32; + // _hi = state >> 32; + void _nextState() { + // Simulate (0xFFFFDA61 * lo + hi) without overflowing 53 bits. + int tmpHi = 0xFFFF0000 * _lo; // At most 48 bits of significant result. + int tmpHiLo = tmpHi & _MASK32; // Get the lower 32 bits. + int tmpHiHi = tmpHi - tmpHiLo; // And just the upper 32 bits. + int tmpLo = 0xDA61 * _lo; + int tmpLoLo = tmpLo & _MASK32; + int tmpLoHi = tmpLo - tmpLoLo; + + int newLo = tmpLoLo + tmpHiLo + _hi; + _lo = newLo & _MASK32; + int newLoHi = newLo - _lo; + _hi = ((tmpLoHi + tmpHiHi + newLoHi) ~/ _POW2_32) & _MASK32; + assert(_lo < _POW2_32); + assert(_hi < _POW2_32); + } + + @notNull + int nextInt(@nullCheck int max) { + if (max <= 0 || max > _POW2_32) { + throw RangeError("max must be in range 0 < max ≤ 2^32, was $max"); + } + if ((max & (max - 1)) == 0) { + // Fast case for powers of two. + _nextState(); + return _lo & (max - 1); + } + + int rnd32; + int result; + do { + _nextState(); + rnd32 = _lo; + result = rnd32.remainder(max); // % max; + } while ((rnd32 - result + max) >= _POW2_32); + return result; + } + + @notNull + double nextDouble() { + _nextState(); + int bits26 = _lo & ((1 << 26) - 1); + _nextState(); + int bits27 = _lo & ((1 << 27) - 1); + return (bits26 * _POW2_27_D + bits27) / _POW2_53_D; + } + + @notNull + bool nextBool() { + _nextState(); + return (_lo & 1) == 0; + } +} + +class _JSSecureRandom implements Random { + // Reused buffer with room enough for a double. + final _buffer = ByteData(8); + + _JSSecureRandom() { + var crypto = JS("", "self.crypto"); + if (crypto != null) { + var getRandomValues = JS("", "#.getRandomValues", crypto); + if (getRandomValues != null) { + return; + } + } + throw UnsupportedError( + "No source of cryptographically secure random numbers available."); + } + + /// Fill _buffer from [start] to `start + length` with random bytes. + void _getRandomBytes(int start, int length) { + JS("void", "crypto.getRandomValues(#)", + _buffer.buffer.asUint8List(start, length)); + } + + @notNull + bool nextBool() { + _getRandomBytes(0, 1); + return _buffer.getUint8(0).isOdd; + } + + @notNull + double nextDouble() { + _getRandomBytes(1, 7); + // Set top bits 12 of double to 0x3FF which is the exponent for numbers + // between 1.0 and 2.0. + _buffer.setUint8(0, 0x3F); + int highByte = _buffer.getUint8(1); + _buffer.setUint8(1, highByte | 0xF0); + + // Buffer now contains double in the range [1.0-2.0) + // with 52 bits of entropy (not 53). + // To get 53 bits, we extract the 53rd bit from higthByte before + // overwriting it, and add that as a least significant bit. + // The getFloat64 method is big-endian as default. + double result = _buffer.getFloat64(0) - 1.0; + if (highByte & 0x10 != 0) { + result += 1.1102230246251565e-16; // pow(2,-53). + } + return result; + } + + @notNull + int nextInt(@nullCheck int max) { + if (max <= 0 || max > _POW2_32) { + throw RangeError("max must be in range 0 < max ≤ 2^32, was $max"); + } + int byteCount = 1; + if (max > 0xFF) { + byteCount++; + if (max > 0xFFFF) { + byteCount++; + if (max > 0xFFFFFF) { + byteCount++; + } + } + } + _buffer.setUint32(0, 0); + int start = 4 - byteCount; + int randomLimit = pow(256, byteCount); + while (true) { + _getRandomBytes(start, byteCount); + // The getUint32 method is big-endian as default. + int random = _buffer.getUint32(0); + if (max & (max - 1) == 0) { + // Max is power of 2. + return random & (max - 1); + } + int result = random.remainder(max); + // Ensure results have equal probability by rejecting values in the + // last range of k*max .. 256**byteCount. + // TODO: Consider picking a higher byte count if the last range is a + // significant portion of the entire range - a 50% chance of having + // to use two more bytes is no worse than always using one more. + if (random - result + max < randomLimit) { + return result; + } + } + } +} +^NN<%'9( 8- 8- @ J J J @ @ @ 4* > > 6/"2 : ,$> &I8O7 8' 8"1=4)6   6G A '!(,> 6); + } + + static int finish(int hash) { + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } + + static int hash2(a, b) => finish(combine(combine(0, a), b)); + + static int hash4(a, b, c, d) => + finish(combine(combine(combine(combine(0, a), b), c), d)); +} ++NN<D;K#> +M,(> = >?"AKfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/math/point.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +part of dart.math; + +/** + * A utility class for representing two-dimensional positions. + */ +class Point { + final T x; + final T y; + + const Point(T x, T y) + : this.x = x, + this.y = y; + + String toString() => 'Point($x, $y)'; + + /** + * A `Point` is only equal to another `Point` with the same coordinates. + * + * This point is equal to `other` if, and only if, + * `other` is a `Point` with + * [x] equal to `other.x` and [y] equal to `other.y`. + */ + bool operator ==(other) { + if (other is! Point) return false; + return x == other.x && y == other.y; + } + + int get hashCode => _JenkinsSmiHash.hash2(x.hashCode, y.hashCode); + + /** + * Add [other] to `this`, as if both points were vectors. + * + * Returns the resulting "vector" as a Point. + */ + Point operator +(Point other) { + return new Point(x + other.x, y + other.y); + } + + /** + * Subtract [other] from `this`, as if both points were vectors. + * + * Returns the resulting "vector" as a Point. + */ + Point operator -(Point other) { + return new Point(x - other.x, y - other.y); + } + + /** + * Scale this point by [factor] as if it were a vector. + * + * *Important* *Note*: This function accepts a `num` as its argument only so + * that you can scale Point objects by an `int` factor. Because the + * star operator always returns the same type of Point that originally called + * it, passing in a double [factor] on a `Point` _causes_ _a_ + * _runtime_ _error_ in checked mode. + */ + Point operator *(num /*T|int*/ factor) { + return new Point((x * factor), (y * factor)); + } + + /** + * Get the straight line (Euclidean) distance between the origin (0, 0) and + * this point. + */ + double get magnitude => sqrt(x * x + y * y); + + /** + * Returns the distance between `this` and [other]. + */ + double distanceTo(Point other) { + var dx = x - other.x; + var dy = y - other.y; + return sqrt(dx * dx + dy * dy); + } + + /** + * Returns the squared distance between `this` and [other]. + * + * Squared distances can be used for comparisons when the actual value is not + * required. + */ + T squaredDistanceTo(Point other) { + var dx = x - other.x; + var dy = y - other.y; + return dx * dx + dy * dy; + } +} +\NN<? (K58')E<0(3C0(3:ONPE(.5N/6&$>P(Lfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/math/random.dart'// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.math; + +/// A generator of random bool, int, or double values. +/// +/// The default implementation supplies a stream of pseudo-random bits that are +/// not suitable for cryptographic purposes. +/// +/// Use the [Random.secure]() constructor for cryptographic purposes. +abstract class Random { + /** + * Creates a random number generator. + * + * The optional parameter [seed] is used to initialize the + * internal state of the generator. The implementation of the + * random stream can change between releases of the library. + */ + external factory Random([int seed]); + + /** + * Creates a cryptographically secure random number generator. + * + * If the program cannot provide a cryptographically secure + * source of random numbers, it throws an [UnsupportedError]. + */ + external factory Random.secure(); + + /** + * Generates a non-negative random integer uniformly distributed in the range + * from 0, inclusive, to [max], exclusive. + * + * Implementation note: The default implementation supports [max] values + * between 1 and (1<<32) inclusive. + */ + int nextInt(int max); + + /** + * Generates a non-negative random floating point value uniformly distributed + * in the range from 0.0, inclusive, to 1.0, exclusive. + */ + double nextDouble(); + + /** + * Generates a random boolean value. + */ + bool nextBool(); +} +4NN<7P-F(=@?'A>@$P-K&P:'Ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/math/rectangle.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +part of dart.math; + +/** + * A base class for representing two-dimensional axis-aligned rectangles. + * + * This rectangle uses a left-handed Cartesian coordinate system, with x + * directed to the right and y directed down, as per the convention in 2D + * computer graphics. + * + * See also: + * [W3C Coordinate Systems Specification](http://www.w3.org/TR/SVG/coords.html#InitialCoordinateSystem). + * + * The rectangle is the set of points with representable coordinates greater + * than or equal to left/top, and with distance to left/top no greater than + * width/height (to the limit of the precision of the coordinates). + */ +abstract class _RectangleBase { + const _RectangleBase(); + + /** The x-coordinate of the left edge. */ + T get left; + /** The y-coordinate of the top edge. */ + T get top; + /** The width of the rectangle. */ + T get width; + /** The height of the rectangle. */ + T get height; + + /** The x-coordinate of the right edge. */ + T get right => left + width; + /** The y-coordinate of the bottom edge. */ + T get bottom => top + height; + + String toString() { + return 'Rectangle ($left, $top) $width x $height'; + } + + bool operator ==(other) { + if (other is! Rectangle) return false; + return left == other.left && + top == other.top && + right == other.right && + bottom == other.bottom; + } + + int get hashCode => _JenkinsSmiHash.hash4( + left.hashCode, top.hashCode, right.hashCode, bottom.hashCode); + + /** + * Computes the intersection of `this` and [other]. + * + * The intersection of two axis-aligned rectangles, if any, is always another + * axis-aligned rectangle. + * + * Returns the intersection of this and `other`, or `null` if they don't + * intersect. + */ + Rectangle intersection(Rectangle other) { + var x0 = max(left, other.left); + var x1 = min(left + width, other.left + other.width); + + if (x0 <= x1) { + var y0 = max(top, other.top); + var y1 = min(top + height, other.top + other.height); + + if (y0 <= y1) { + return new Rectangle(x0, y0, x1 - x0, y1 - y0); + } + } + return null; + } + + /** + * Returns true if `this` intersects [other]. + */ + bool intersects(Rectangle other) { + return (left <= other.left + other.width && + other.left <= left + width && + top <= other.top + other.height && + other.top <= top + height); + } + + /** + * Returns a new rectangle which completely contains `this` and [other]. + */ + Rectangle boundingBox(Rectangle other) { + var right = max(this.left + this.width, other.left + other.width); + var bottom = max(this.top + this.height, other.top + other.height); + + var left = min(this.left, other.left); + var top = min(this.top, other.top); + + return new Rectangle(left, top, right - left, bottom - top); + } + + /** + * Tests whether `this` entirely contains [another]. + */ + bool containsRectangle(Rectangle another) { + return left <= another.left && + left + width >= another.left + another.width && + top <= another.top && + top + height >= another.top + another.height; + } + + /** + * Tests whether [another] is inside or along the edges of `this`. + */ + bool containsPoint(Point another) { + return another.x >= left && + another.x <= left + width && + another.y >= top && + another.y <= top + height; + } + + Point get topLeft => new Point(this.left, this.top); + Point get topRight => new Point(this.left + this.width, this.top); + Point get bottomRight => + new Point(this.left + this.width, this.top + this.height); + Point get bottomLeft => new Point(this.left, this.top + this.height); +} + +/** + * A class for representing two-dimensional rectangles whose properties are + * immutable. + */ +class Rectangle extends _RectangleBase { + final T left; + final T top; + final T width; + final T height; + + /** + * Create a rectangle spanned by `(left, top)` and `(left+width, top+height)`. + * + * The rectangle contains the points + * with x-coordinate between `left` and `left + width`, and + * with y-coordinate between `top` and `top + height`, both inclusive. + * + * The `width` and `height` should be non-negative. + * If `width` or `height` are negative, they are clamped to zero. + * + * If `width` and `height` are zero, the "rectangle" comprises only the single + * point `(left, top)`. + */ + const Rectangle(this.left, this.top, T width, T height) + : this.width = (width < 0) ? -width * 0 : width, // Inline _clampToZero. + this.height = (height < 0) ? -height * 0 : height; + + /** + * Create a rectangle spanned by the points [a] and [b]; + * + * The rectangle contains the points + * with x-coordinate between `a.x` and `b.x`, and + * with y-coordinate between `a.y` and `b.y`, both inclusive. + * + * If the distance between `a.x` and `b.x` is not representable + * (which can happen if one or both is a double), + * the actual right edge might be slightly off from `max(a.x, b.x)`. + * Similar for the y-coordinates and the bottom edge. + */ + factory Rectangle.fromPoints(Point a, Point b) { + T left = min(a.x, b.x); + T width = max(a.x, b.x) - left; + T top = min(a.y, b.y); + T height = max(a.y, b.y) - top; + return new Rectangle(left, top, width, height); + } +} + +/** + * A class for representing two-dimensional axis-aligned rectangles with mutable + * properties. + */ +class MutableRectangle extends _RectangleBase + implements Rectangle { + /** + * The x-coordinate of the left edge. + * + * Setting the value will move the rectangle without changing its width. + */ + T left; + /** + * The y-coordinate of the left edge. + * + * Setting the value will move the rectangle without changing its height. + */ + T top; + T _width; + T _height; + + /** + * Create a mutable rectangle spanned by `(left, top)` and + * `(left+width, top+height)`. + * + * The rectangle contains the points + * with x-coordinate between `left` and `left + width`, and + * with y-coordinate between `top` and `top + height`, both inclusive. + * + * The `width` and `height` should be non-negative. + * If `width` or `height` are negative, they are clamped to zero. + * + * If `width` and `height` are zero, the "rectangle" comprises only the single + * point `(left, top)`. + */ + MutableRectangle(this.left, this.top, T width, T height) + : this._width = (width < 0) ? _clampToZero(width) : width, + this._height = (height < 0) ? _clampToZero(height) : height; + + /** + * Create a mutable rectangle spanned by the points [a] and [b]; + * + * The rectangle contains the points + * with x-coordinate between `a.x` and `b.x`, and + * with y-coordinate between `a.y` and `b.y`, both inclusive. + * + * If the distance between `a.x` and `b.x` is not representable + * (which can happen if one or both is a double), + * the actual right edge might be slightly off from `max(a.x, b.x)`. + * Similar for the y-coordinates and the bottom edge. + */ + factory MutableRectangle.fromPoints(Point a, Point b) { + T left = min(a.x, b.x); + T width = max(a.x, b.x) - left; + T top = min(a.y, b.y); + T height = max(a.y, b.y) - top; + return new MutableRectangle(left, top, width, height); + } + + T get width => _width; + + /** + * Sets the width of the rectangle. + * + * The width must be non-negative. + * If a negative width is supplied, it is clamped to zero. + * + * Setting the value will change the right edge of the rectangle, + * but will not change [left]. + */ + void set width(T width) { + if (width < 0) width = _clampToZero(width); + _width = width; + } + + T get height => _height; + + /** + * Sets the height of the rectangle. + * + * The height must be non-negative. + * If a negative height is supplied, it is clamped to zero. + * + * Setting the value will change the bottom edge of the rectangle, + * but will not change [top]. + */ + void set height(T height) { + if (height < 0) height = _clampToZero(height); + _height = height; + } +} + +/** + * Converts a negative [int] or [double] to a zero-value of the same type. + * + * Returns `0` if value is int, `0.0` if value is double. + */ +T _clampToZero(T value) { + assert(value < 0); + return -value * 0; +} +NN<JIJ lMLD/,+ %&-. 7+! -E6PK2$:$<;0*0&+$K1GH+(D73#86E+ %#=KDNL;Q'>I6DQ:O;;'4@B4G89$$7Q@(K +(L =!'>I6DQ;DHC'4@B4G8@$$>&%=D!3'&>E 6K:)lfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Patch library for dart:mirrors. + +import 'dart:_js_helper' show patch; +import 'dart:_js_mirrors' as js; +import 'dart:_runtime' as dart; + +@patch +class MirrorSystem { + @patch + LibraryMirror findLibrary(Symbol libraryName) { + return libraries.values + .singleWhere((library) => library.simpleName == libraryName); + } + + @patch + static String getName(Symbol symbol) => js.getName(symbol); + + @patch + static Symbol getSymbol(String name, [LibraryMirror library]) { + return js.getSymbol(name, library); + } +} + +@patch +MirrorSystem currentMirrorSystem() => js.currentJsMirrorSystem; + +@patch +InstanceMirror reflect(Object reflectee) => js.reflect(reflectee); + +@patch +ClassMirror reflectClass(Type key) { + if (key is! Type || key == dynamic) { + throw ArgumentError('$key does not denote a class'); + } + TypeMirror tm = reflectType(key); + if (tm is! ClassMirror) { + throw ArgumentError("$key does not denote a class"); + } + return (tm as ClassMirror).originalDeclaration; +} + +@patch +TypeMirror reflectType(Type type, [List typeArguments]) { + if (typeArguments != null) { + type = _instantiateClass(type, typeArguments); + } + return js.reflectType(type); +} + +/// Instantiates the generic class [type] with [typeArguments] and returns the +/// result. +/// +/// [type] may be instantiated with type arguments already. In that case, they +/// are ignored. For example calling this function with `(List, [String])` +/// and `(List, [String])` will produce `List` in both cases. +Type _instantiateClass(Type type, List typeArguments) { + var unwrapped = dart.unwrapType(type); + var genericClass = dart.getGenericClass(unwrapped); + if (genericClass == null) { + throw ArgumentError('Type `$type` must be generic to apply ' + 'type arguments: `$typeArguments`.'); + } + + var typeArgsLenth = typeArguments.length; + var unwrappedArgs = List(typeArgsLenth); + for (int i = 0; i < typeArgsLenth; i++) { + unwrappedArgs[i] = dart.unwrapType(typeArguments[i]); + } + var typeFormals = dart.getGenericTypeFormals(genericClass); + if (typeFormals.length != typeArgsLenth) { + throw ArgumentError('Type `$type` has ${typeFormals.length} type ' + 'parameters, but $typeArgsLenth type arguments were ' + 'passed: `$typeArguments`.'); + } + // TODO(jmesserly): this does not validate bounds, as we don't have them + // available at runtime. Consider storing them when dart:mirrors is enabled. + return dart.wrapType(dart.instantiateClass(genericClass, unwrappedArgs)); +} +TNN<#%!  2F > B(@C%(9$92@3O OPO>)6A.,+,:>-G>&KOLVfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/typed_data/typed_data.dart.// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Lists that efficiently handle fixed sized data +/// (for example, unsigned 8 byte integers) and SIMD numeric types. +/// +/// To use this library in your code: +/// +/// import 'dart:typed_data'; +/// +/// {@category Core} +library dart.typed_data; + +import "dart:_internal" show UnmodifiableListBase; + +part "unmodifiable_typed_data.dart"; + +/** + * A sequence of bytes underlying a typed data object. + * + * Used to process large quantities of binary or numerical data + * more efficiently using a typed view. + */ +abstract class ByteBuffer { + /** + * Returns the length of this byte buffer, in bytes. + */ + int get lengthInBytes; + + /** + * Creates a [Uint8List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Uint8List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes] and contains [length] bytes. + * If [length] is omitted, the range extends to the end of the buffer. + * + * The start index and length must describe a valid range of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `length` must not be negative, and + * * `offsetInBytes + length` must not be greater than [lengthInBytes]. + */ + Uint8List asUint8List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Int8List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Int8List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes] and contains [length] bytes. + * If [length] is omitted, the range extends to the end of the buffer. + * + * The start index and length must describe a valid range of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `length` must not be negative, and + * * `offsetInBytes + length` must not be greater than [lengthInBytes]. + */ + Int8List asInt8List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Uint8ClampedList] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Uint8ClampedList` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes] and contains [length] bytes. + * If [length] is omitted, the range extends to the end of the buffer. + * + * The start index and length must describe a valid range of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `length` must not be negative, and + * * `offsetInBytes + length` must not be greater than [lengthInBytes]. + */ + Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]); + + /** + * Creates a [Uint16List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Uint16List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 16-bit aligned, + * and contains [length] 16-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not even, the last byte can't be part of the view. + * + * The start index and length must describe a valid 16-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by two, + * * `length` must not be negative, and + * * `offsetInBytes + length * 2` must not be greater than [lengthInBytes]. + */ + Uint16List asUint16List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Int16List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Int16List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 16-bit aligned, + * and contains [length] 16-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not even, the last byte can't be part of the view. + * + * The start index and length must describe a valid 16-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by two, + * * `length` must not be negative, and + * * `offsetInBytes + length * 2` must not be greater than [lengthInBytes]. + */ + Int16List asInt16List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Uint32List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Uint32List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 32-bit aligned, + * and contains [length] 32-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by four, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 32-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by four, + * * `length` must not be negative, and + * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes]. + */ + Uint32List asUint32List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Int32List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Int32List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 32-bit aligned, + * and contains [length] 32-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by four, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 32-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by four, + * * `length` must not be negative, and + * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes]. + */ + Int32List asInt32List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Uint64List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Uint64List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 64-bit aligned, + * and contains [length] 64-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by eight, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 64-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by eight, + * * `length` must not be negative, and + * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes]. + */ + Uint64List asUint64List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Int64List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Int64List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 64-bit aligned, + * and contains [length] 64-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by eight, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 64-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by eight, + * * `length` must not be negative, and + * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes]. + */ + Int64List asInt64List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Int32x4List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Int32x4List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 128-bit aligned, + * and contains [length] 128-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by 16, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 128-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by sixteen, + * * `length` must not be negative, and + * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes]. + */ + Int32x4List asInt32x4List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Float32List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Float32List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 32-bit aligned, + * and contains [length] 32-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by four, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 32-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by four, + * * `length` must not be negative, and + * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes]. + */ + Float32List asFloat32List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Float64List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Float64List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 64-bit aligned, + * and contains [length] 64-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by eight, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 64-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by eight, + * * `length` must not be negative, and + * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes]. + */ + Float64List asFloat64List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Float32x4List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Float32x4List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 128-bit aligned, + * and contains [length] 128-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by 16, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 128-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by sixteen, + * * `length` must not be negative, and + * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes]. + */ + Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]); + + /** + * Creates a [Float64x2List] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `Float64x2List` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes], which must be 128-bit aligned, + * and contains [length] 128-bit integers. + * If [length] is omitted, the range extends as far towards the end of + * the buffer as possible - + * if [lengthInBytes] is not divisible by 16, the last bytes can't be part + * of the view. + * + * The start index and length must describe a valid 128-bit aligned range + * of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `offsetInBytes` must be divisible by sixteen, + * * `length` must not be negative, and + * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes]. + */ + Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]); + + /** + * Creates a [ByteData] _view_ of a region of this byte buffer. + * + * The view is backed by the bytes of this byte buffer. + * Any changes made to the `ByteData` will also change the buffer, + * and vice versa. + * + * The viewed region start at [offsetInBytes] and contains [length] bytes. + * If [length] is omitted, the range extends to the end of the buffer. + * + * The start index and length must describe a valid range of the buffer: + * + * * `offsetInBytes` must not be negative, + * * `length` must not be negative, and + * * `offsetInBytes + length` must not be greater than [lengthInBytes]. + */ + ByteData asByteData([int offsetInBytes = 0, int length]); +} + +/** + * A typed view of a sequence of bytes. + */ +abstract class TypedData { + /** + * Returns the number of bytes in the representation of each element in this + * list. + */ + int get elementSizeInBytes; + + /** + * Returns the offset in bytes into the underlying byte buffer of this view. + */ + int get offsetInBytes; + + /** + * Returns the length of this view, in bytes. + */ + int get lengthInBytes; + + /** + * Returns the byte buffer associated with this object. + */ + ByteBuffer get buffer; +} + +abstract class _TypedIntList extends TypedData { + /** + * Returns the concatenation of this list and [other]. + * + * If other is also a typed-data integer list, the returned list will + * be a type-data integer list capable of containing all the elements of + * this list and of [other]. + * Otherwise the returned list will be a normal growable `List`. + */ + List operator +(List other); +} + +abstract class _TypedFloatList extends TypedData { + /** + * Returns the concatenation of this list and [other]. + * + * If other is also a typed-data floating point number list, + * the returned list will be a type-data float list capable of containing + * all the elements of this list and of [other]. + * Otherwise the returned list will be a normal growable `List`. + */ + List operator +(List other); +} + +/** + * Describes endianness to be used when accessing or updating a + * sequence of bytes. + */ +class Endian { + final bool _littleEndian; + const Endian._(this._littleEndian); + + static const Endian big = const Endian._(false); + static const Endian little = const Endian._(true); + static final Endian host = + (new ByteData.view(new Uint16List.fromList([1]).buffer)).getInt8(0) == 1 + ? little + : big; +} + +/** + * A fixed-length, random-access sequence of bytes that also provides random + * and unaligned access to the fixed-width integers and floating point + * numbers represented by those bytes. + * + * `ByteData` may be used to pack and unpack data from external sources + * (such as networks or files systems), and to process large quantities + * of numerical data more efficiently than would be possible + * with ordinary [List] implementations. + * `ByteData` can save space, by eliminating the need for object headers, + * and time, by eliminating the need for data copies. + * Finally, `ByteData` may be used to intentionally reinterpret the bytes + * representing one arithmetic type as another. + * For example this code fragment determine what 32-bit signed integer + * is represented by the bytes of a 32-bit floating point number: + * + * var buffer = new Uint8List(8).buffer; + * var bdata = new ByteData.view(buffer); + * bdata.setFloat32(0, 3.04); + * int huh = bdata.getInt32(0); + */ +abstract class ByteData implements TypedData { + /** + * Creates a [ByteData] of the specified length (in elements), all of + * whose bytes are initially zero. + */ + external factory ByteData(int length); + + /** + * Creates an [ByteData] _view_ of the specified region in [buffer]. + * + * Changes in the [ByteData] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + */ + factory ByteData.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asByteData(offsetInBytes, length); + } + + /** + * Returns the (possibly negative) integer represented by the byte at the + * specified [byteOffset] in this object, in two's complement binary + * representation. + * + * The return value will be between -128 and 127, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * greater than or equal to the length of this object. + */ + int getInt8(int byteOffset); + + /** + * Sets the byte at the specified [byteOffset] in this object to the + * two's complement binary representation of the specified [value], which + * must fit in a single byte. + * + * In other words, [value] must be between -128 and 127, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * greater than or equal to the length of this object. + */ + void setInt8(int byteOffset, int value); + + /** + * Returns the positive integer represented by the byte at the specified + * [byteOffset] in this object, in unsigned binary form. + * + * The return value will be between 0 and 255, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * greater than or equal to the length of this object. + */ + int getUint8(int byteOffset); + + /** + * Sets the byte at the specified [byteOffset] in this object to the + * unsigned binary representation of the specified [value], which must fit + * in a single byte. + * + * In other words, [value] must be between 0 and 255, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, + * or greater than or equal to the length of this object. + */ + void setUint8(int byteOffset, int value); + + /** + * Returns the (possibly negative) integer represented by the two bytes at + * the specified [byteOffset] in this object, in two's complement binary + * form. + * + * The return value will be between -215 and 215 - 1, + * inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + int getInt16(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the two bytes starting at the specified [byteOffset] in this + * object to the two's complement binary representation of the specified + * [value], which must fit in two bytes. + * + * In other words, [value] must lie + * between -215 and 215 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + void setInt16(int byteOffset, int value, [Endian endian = Endian.big]); + + /** + * Returns the positive integer represented by the two bytes starting + * at the specified [byteOffset] in this object, in unsigned binary + * form. + * + * The return value will be between 0 and 216 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + int getUint16(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the two bytes starting at the specified [byteOffset] in this object + * to the unsigned binary representation of the specified [value], + * which must fit in two bytes. + * + * In other words, [value] must be between + * 0 and 216 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 2` is greater than the length of this object. + */ + void setUint16(int byteOffset, int value, [Endian endian = Endian.big]); + + /** + * Returns the (possibly negative) integer represented by the four bytes at + * the specified [byteOffset] in this object, in two's complement binary + * form. + * + * The return value will be between -231 and 231 - 1, + * inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + int getInt32(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the four bytes starting at the specified [byteOffset] in this + * object to the two's complement binary representation of the specified + * [value], which must fit in four bytes. + * + * In other words, [value] must lie + * between -231 and 231 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + void setInt32(int byteOffset, int value, [Endian endian = Endian.big]); + + /** + * Returns the positive integer represented by the four bytes starting + * at the specified [byteOffset] in this object, in unsigned binary + * form. + * + * The return value will be between 0 and 232 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + int getUint32(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the four bytes starting at the specified [byteOffset] in this object + * to the unsigned binary representation of the specified [value], + * which must fit in four bytes. + * + * In other words, [value] must be between + * 0 and 232 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + void setUint32(int byteOffset, int value, [Endian endian = Endian.big]); + + /** + * Returns the (possibly negative) integer represented by the eight bytes at + * the specified [byteOffset] in this object, in two's complement binary + * form. + * + * The return value will be between -263 and 263 - 1, + * inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + int getInt64(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the eight bytes starting at the specified [byteOffset] in this + * object to the two's complement binary representation of the specified + * [value], which must fit in eight bytes. + * + * In other words, [value] must lie + * between -263 and 263 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + void setInt64(int byteOffset, int value, [Endian endian = Endian.big]); + + /** + * Returns the positive integer represented by the eight bytes starting + * at the specified [byteOffset] in this object, in unsigned binary + * form. + * + * The return value will be between 0 and 264 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + int getUint64(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the eight bytes starting at the specified [byteOffset] in this object + * to the unsigned binary representation of the specified [value], + * which must fit in eight bytes. + * + * In other words, [value] must be between + * 0 and 264 - 1, inclusive. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + void setUint64(int byteOffset, int value, [Endian endian = Endian.big]); + + /** + * Returns the floating point number represented by the four bytes at + * the specified [byteOffset] in this object, in IEEE 754 + * single-precision binary floating-point format (binary32). + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + double getFloat32(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the four bytes starting at the specified [byteOffset] in this + * object to the IEEE 754 single-precision binary floating-point + * (binary32) representation of the specified [value]. + * + * **Note that this method can lose precision.** The input [value] is + * a 64-bit floating point value, which will be converted to 32-bit + * floating point value by IEEE 754 rounding rules before it is stored. + * If [value] cannot be represented exactly as a binary32, it will be + * converted to the nearest binary32 value. If two binary32 values are + * equally close, the one whose least significant bit is zero will be used. + * Note that finite (but large) values can be converted to infinity, and + * small non-zero values can be converted to zero. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 4` is greater than the length of this object. + */ + void setFloat32(int byteOffset, double value, [Endian endian = Endian.big]); + + /** + * Returns the floating point number represented by the eight bytes at + * the specified [byteOffset] in this object, in IEEE 754 + * double-precision binary floating-point format (binary64). + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + double getFloat64(int byteOffset, [Endian endian = Endian.big]); + + /** + * Sets the eight bytes starting at the specified [byteOffset] in this + * object to the IEEE 754 double-precision binary floating-point + * (binary64) representation of the specified [value]. + * + * Throws [RangeError] if [byteOffset] is negative, or + * `byteOffset + 8` is greater than the length of this object. + */ + void setFloat64(int byteOffset, double value, [Endian endian = Endian.big]); +} + +/** + * A fixed-length list of 8-bit signed integers. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low eight bits, + * interpreted as a signed 8-bit two's complement integer with values in the + * range -128 to +127. + */ +abstract class Int8List implements List, _TypedIntList { + /** + * Creates an [Int8List] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Int8List(int length); + + /** + * Creates a [Int8List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Int8List.fromList(List elements); + + /** + * Creates an [Int8List] _view_ of the specified region in [buffer]. + * + * Changes in the [Int8List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + */ + factory Int8List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asInt8List(offsetInBytes, length); + } + + static const int bytesPerElement = 1; +} + +/** + * A fixed-length list of 8-bit unsigned integers. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low eight bits, + * interpreted as an unsigned 8-bit integer with values in the + * range 0 to 255. + */ +abstract class Uint8List implements List, _TypedIntList { + /** + * Creates a [Uint8List] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Uint8List(int length); + + /** + * Creates a [Uint8List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Uint8List.fromList(List elements); + + /** + * Creates a [Uint8List] _view_ of the specified region in [buffer]. + * + * Changes in the [Uint8List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + */ + factory Uint8List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asUint8List(offsetInBytes, length); + } + + /** + * Returns a concatenation of this list and [other]. + * + * If [other] is also a typed-data list, then the return list will be a + * typed data list capable of holding both unsigned 8-bit integers and + * the elements of [other], otherwise it'll be a normal list of integers. + */ + List operator +(List other); + + static const int bytesPerElement = 1; +} + +/** + * A fixed-length list of 8-bit unsigned integers. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are clamped to an unsigned eight bit value. + * That is, all values below zero are stored as zero + * and all values above 255 are stored as 255. + */ +abstract class Uint8ClampedList implements List, _TypedIntList { + /** + * Creates a [Uint8ClampedList] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Uint8ClampedList(int length); + + /** + * Creates a [Uint8ClampedList] of the same size as the [elements] + * list and copies over the values clamping when needed. + * + * Values are clamped to fit in the list when they are copied, + * the same way storing values clamps them. + */ + external factory Uint8ClampedList.fromList(List elements); + + /** + * Creates a [Uint8ClampedList] _view_ of the specified region in the + * specified byte [buffer]. + * + * Changes in the [Uint8List] will be visible in the byte buffer + * and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + */ + factory Uint8ClampedList.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asUint8ClampedList(offsetInBytes, length); + } + + static const int bytesPerElement = 1; +} + +/** + * A fixed-length list of 16-bit signed integers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low 16 bits, + * interpreted as a signed 16-bit two's complement integer with values in the + * range -32768 to +32767. + */ +abstract class Int16List implements List, _TypedIntList { + /** + * Creates an [Int16List] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Int16List(int length); + + /** + * Creates a [Int16List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Int16List.fromList(List elements); + + /** + * Creates an [Int16List] _view_ of the specified region in [buffer]. + * + * Changes in the [Int16List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Int16List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asInt16List(offsetInBytes, length); + } + + static const int bytesPerElement = 2; +} + +/** + * A fixed-length list of 16-bit unsigned integers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low 16 bits, + * interpreted as an unsigned 16-bit integer with values in the + * range 0 to 65535. + */ +abstract class Uint16List implements List, _TypedIntList { + /** + * Creates a [Uint16List] of the specified length (in elements), all + * of whose elements are initially zero. + */ + external factory Uint16List(int length); + + /** + * Creates a [Uint16List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Uint16List.fromList(List elements); + + /** + * Creates a [Uint16List] _view_ of the specified region in + * the specified byte buffer. + * + * Changes in the [Uint16List] will be visible in the byte buffer + * and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Uint16List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asUint16List(offsetInBytes, length); + } + + static const int bytesPerElement = 2; +} + +/** + * A fixed-length list of 32-bit signed integers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low 32 bits, + * interpreted as a signed 32-bit two's complement integer with values in the + * range -2147483648 to 2147483647. + */ +abstract class Int32List implements List, _TypedIntList { + /** + * Creates an [Int32List] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Int32List(int length); + + /** + * Creates a [Int32List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Int32List.fromList(List elements); + + /** + * Creates an [Int32List] _view_ of the specified region in [buffer]. + * + * Changes in the [Int32List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Int32List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asInt32List(offsetInBytes, length); + } + + static const int bytesPerElement = 4; +} + +/** + * A fixed-length list of 32-bit unsigned integers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low 32 bits, + * interpreted as an unsigned 32-bit integer with values in the + * range 0 to 4294967295. + */ +abstract class Uint32List implements List, _TypedIntList { + /** + * Creates a [Uint32List] of the specified length (in elements), all + * of whose elements are initially zero. + */ + external factory Uint32List(int length); + + /** + * Creates a [Uint32List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Uint32List.fromList(List elements); + + /** + * Creates a [Uint32List] _view_ of the specified region in + * the specified byte buffer. + * + * Changes in the [Uint32List] will be visible in the byte buffer + * and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Uint32List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asUint32List(offsetInBytes, length); + } + + static const int bytesPerElement = 4; +} + +/** + * A fixed-length list of 64-bit signed integers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low 64 bits, + * interpreted as a signed 64-bit two's complement integer with values in the + * range -9223372036854775808 to +9223372036854775807. + */ +abstract class Int64List implements List, _TypedIntList { + /** + * Creates an [Int64List] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Int64List(int length); + + /** + * Creates a [Int64List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Int64List.fromList(List elements); + + /** + * Creates an [Int64List] _view_ of the specified region in [buffer]. + * + * Changes in the [Int64List] will be visible in the byte buffer + * and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Int64List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asInt64List(offsetInBytes, length); + } + + static const int bytesPerElement = 8; +} + +/** + * A fixed-length list of 64-bit unsigned integers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation can be considerably + * more space- and time-efficient than the default [List] implementation. + * + * Integers stored in the list are truncated to their low 64 bits, + * interpreted as an unsigned 64-bit integer with values in the + * range 0 to 18446744073709551615. + */ +abstract class Uint64List implements List, _TypedIntList { + /** + * Creates a [Uint64List] of the specified length (in elements), all + * of whose elements are initially zero. + */ + external factory Uint64List(int length); + + /** + * Creates a [Uint64List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Uint64List.fromList(List elements); + + /** + * Creates an [Uint64List] _view_ of the specified region in + * the specified byte buffer. + * + * Changes in the [Uint64List] will be visible in the byte buffer + * and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Uint64List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asUint64List(offsetInBytes, length); + } + + static const int bytesPerElement = 8; +} + +/** + * A fixed-length list of IEEE 754 single-precision binary floating-point + * numbers that is viewable as a [TypedData]. + * + * For long lists, this + * implementation can be considerably more space- and time-efficient than + * the default [List] implementation. + * + * Double values stored in the list are converted to the nearest + * single-precision value. Values read are converted to a double + * value with the same value. + */ +abstract class Float32List implements List, _TypedFloatList { + /** + * Creates a [Float32List] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Float32List(int length); + + /** + * Creates a [Float32List] with the same length as the [elements] list + * and copies over the elements. + * + * Values are truncated to fit in the list when they are copied, + * the same way storing values truncates them. + */ + external factory Float32List.fromList(List elements); + + /** + * Creates a [Float32List] _view_ of the specified region in [buffer]. + * + * Changes in the [Float32List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Float32List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asFloat32List(offsetInBytes, length); + } + + static const int bytesPerElement = 4; +} + +/** + * A fixed-length list of IEEE 754 double-precision binary floating-point + * numbers that is viewable as a [TypedData]. + * + * For long lists, this + * implementation can be considerably more space- and time-efficient than + * the default [List] implementation. + */ +abstract class Float64List implements List, _TypedFloatList { + /** + * Creates a [Float64List] of the specified length (in elements), all of + * whose elements are initially zero. + */ + external factory Float64List(int length); + + /** + * Creates a [Float64List] with the same length as the [elements] list + * and copies over the elements. + */ + external factory Float64List.fromList(List elements); + + /** + * Creates a [Float64List] _view_ of the specified region in [buffer]. + * + * Changes in the [Float64List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Float64List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asFloat64List(offsetInBytes, length); + } + + static const int bytesPerElement = 8; +} + +/** + * A fixed-length list of Float32x4 numbers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation will be considerably more + * space- and time-efficient than the default [List] implementation. + */ +abstract class Float32x4List implements List, TypedData { + /** + * Creates a [Float32x4List] of the specified length (in elements), + * all of whose elements are initially zero. + */ + external factory Float32x4List(int length); + + /** + * Creates a [Float32x4List] with the same length as the [elements] list + * and copies over the elements. + */ + external factory Float32x4List.fromList(List elements); + + /** + * Creates a [Float32x4List] _view_ of the specified region in [buffer]. + * + * Changes in the [Float32x4List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Float32x4List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asFloat32x4List(offsetInBytes, length); + } + + /** + * Returns the concatenation of this list and [other]. + * + * If [other] is also a [Float32x4List], the result is a new [Float32x4List], + * otherwise the result is a normal growable `List`. + */ + List operator +(List other); + + static const int bytesPerElement = 16; +} + +/** + * A fixed-length list of Int32x4 numbers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation will be considerably more + * space- and time-efficient than the default [List] implementation. + */ +abstract class Int32x4List implements List, TypedData { + /** + * Creates a [Int32x4List] of the specified length (in elements), + * all of whose elements are initially zero. + */ + external factory Int32x4List(int length); + + /** + * Creates a [Int32x4List] with the same length as the [elements] list + * and copies over the elements. + */ + external factory Int32x4List.fromList(List elements); + + /** + * Creates a [Int32x4List] _view_ of the specified region in [buffer]. + * + * Changes in the [Int32x4List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Int32x4List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asInt32x4List(offsetInBytes, length); + } + + /** + * Returns the concatenation of this list and [other]. + * + * If [other] is also a [Int32x4List], the result is a new [Int32x4List], + * otherwise the result is a normal growable `List`. + */ + List operator +(List other); + + static const int bytesPerElement = 16; +} + +/** + * A fixed-length list of Float64x2 numbers that is viewable as a + * [TypedData]. + * + * For long lists, this implementation will be considerably more + * space- and time-efficient than the default [List] implementation. + */ +abstract class Float64x2List implements List, TypedData { + /** + * Creates a [Float64x2List] of the specified length (in elements), + * all of whose elements have all lanes set to zero. + */ + external factory Float64x2List(int length); + + /** + * Creates a [Float64x2List] with the same length as the [elements] list + * and copies over the elements. + */ + external factory Float64x2List.fromList(List elements); + + /** + * Returns the concatenation of this list and [other]. + * + * If [other] is also a [Float64x2List], the result is a new [Float64x2List], + * otherwise the result is a normal growable `List`. + */ + List operator +(List other); + + /** + * Creates a [Float64x2List] _view_ of the specified region in [buffer]. + * + * Changes in the [Float64x2List] will be visible in the byte + * buffer and vice versa. + * If the [offsetInBytes] index of the region is not specified, + * it defaults to zero (the first byte in the byte buffer). + * If the length is not specified, it defaults to `null`, + * which indicates that the view extends to the end of the byte buffer. + * + * Throws [RangeError] if [offsetInBytes] or [length] are negative, or + * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than + * the length of [buffer]. + * + * Throws [ArgumentError] if [offsetInBytes] is not a multiple of + * [bytesPerElement]. + */ + factory Float64x2List.view(ByteBuffer buffer, + [int offsetInBytes = 0, int length]) { + return buffer.asFloat64x2List(offsetInBytes, length); + } + + static const int bytesPerElement = 16; +} + +/** + * Float32x4 immutable value type and operations. + * + * Float32x4 stores 4 32-bit floating point values in "lanes". + * The lanes are "x", "y", "z", and "w" respectively. + */ +abstract class Float32x4 { + external factory Float32x4(double x, double y, double z, double w); + external factory Float32x4.splat(double v); + external factory Float32x4.zero(); + external factory Float32x4.fromInt32x4Bits(Int32x4 x); + + /// Sets the x and y lanes to their respective values in [v] and sets the z + /// and w lanes to 0.0. + external factory Float32x4.fromFloat64x2(Float64x2 v); + + /// Addition operator. + Float32x4 operator +(Float32x4 other); + + /// Negate operator. + Float32x4 operator -(); + + /// Subtraction operator. + Float32x4 operator -(Float32x4 other); + + /// Multiplication operator. + Float32x4 operator *(Float32x4 other); + + /// Division operator. + Float32x4 operator /(Float32x4 other); + + /// Relational less than. + Int32x4 lessThan(Float32x4 other); + + /// Relational less than or equal. + Int32x4 lessThanOrEqual(Float32x4 other); + + /// Relational greater than. + Int32x4 greaterThan(Float32x4 other); + + /// Relational greater than or equal. + Int32x4 greaterThanOrEqual(Float32x4 other); + + /// Relational equal. + Int32x4 equal(Float32x4 other); + + /// Relational not-equal. + Int32x4 notEqual(Float32x4 other); + + /// Returns a copy of [this] each lane being scaled by [s]. + /// Equivalent to this * new Float32x4.splat(s) + Float32x4 scale(double s); + + /// Returns the lane-wise absolute value of this [Float32x4]. + Float32x4 abs(); + + /// Lane-wise clamp [this] to be in the range [lowerLimit]-[upperLimit]. + Float32x4 clamp(Float32x4 lowerLimit, Float32x4 upperLimit); + + /// Extracted x value. + double get x; + + /// Extracted y value. + double get y; + + /// Extracted z value. + double get z; + + /// Extracted w value. + double get w; + + /// Extract the sign bits from each lane return them in the first 4 bits. + /// "x" lane is bit 0. + /// "y" lane is bit 1. + /// "z" lane is bit 2. + /// "w" lane is bit 3. + int get signMask; + + /// Mask passed to [shuffle] or [shuffleMix]. + static const int xxxx = 0x0; + static const int xxxy = 0x40; + static const int xxxz = 0x80; + static const int xxxw = 0xC0; + static const int xxyx = 0x10; + static const int xxyy = 0x50; + static const int xxyz = 0x90; + static const int xxyw = 0xD0; + static const int xxzx = 0x20; + static const int xxzy = 0x60; + static const int xxzz = 0xA0; + static const int xxzw = 0xE0; + static const int xxwx = 0x30; + static const int xxwy = 0x70; + static const int xxwz = 0xB0; + static const int xxww = 0xF0; + static const int xyxx = 0x4; + static const int xyxy = 0x44; + static const int xyxz = 0x84; + static const int xyxw = 0xC4; + static const int xyyx = 0x14; + static const int xyyy = 0x54; + static const int xyyz = 0x94; + static const int xyyw = 0xD4; + static const int xyzx = 0x24; + static const int xyzy = 0x64; + static const int xyzz = 0xA4; + static const int xyzw = 0xE4; + static const int xywx = 0x34; + static const int xywy = 0x74; + static const int xywz = 0xB4; + static const int xyww = 0xF4; + static const int xzxx = 0x8; + static const int xzxy = 0x48; + static const int xzxz = 0x88; + static const int xzxw = 0xC8; + static const int xzyx = 0x18; + static const int xzyy = 0x58; + static const int xzyz = 0x98; + static const int xzyw = 0xD8; + static const int xzzx = 0x28; + static const int xzzy = 0x68; + static const int xzzz = 0xA8; + static const int xzzw = 0xE8; + static const int xzwx = 0x38; + static const int xzwy = 0x78; + static const int xzwz = 0xB8; + static const int xzww = 0xF8; + static const int xwxx = 0xC; + static const int xwxy = 0x4C; + static const int xwxz = 0x8C; + static const int xwxw = 0xCC; + static const int xwyx = 0x1C; + static const int xwyy = 0x5C; + static const int xwyz = 0x9C; + static const int xwyw = 0xDC; + static const int xwzx = 0x2C; + static const int xwzy = 0x6C; + static const int xwzz = 0xAC; + static const int xwzw = 0xEC; + static const int xwwx = 0x3C; + static const int xwwy = 0x7C; + static const int xwwz = 0xBC; + static const int xwww = 0xFC; + static const int yxxx = 0x1; + static const int yxxy = 0x41; + static const int yxxz = 0x81; + static const int yxxw = 0xC1; + static const int yxyx = 0x11; + static const int yxyy = 0x51; + static const int yxyz = 0x91; + static const int yxyw = 0xD1; + static const int yxzx = 0x21; + static const int yxzy = 0x61; + static const int yxzz = 0xA1; + static const int yxzw = 0xE1; + static const int yxwx = 0x31; + static const int yxwy = 0x71; + static const int yxwz = 0xB1; + static const int yxww = 0xF1; + static const int yyxx = 0x5; + static const int yyxy = 0x45; + static const int yyxz = 0x85; + static const int yyxw = 0xC5; + static const int yyyx = 0x15; + static const int yyyy = 0x55; + static const int yyyz = 0x95; + static const int yyyw = 0xD5; + static const int yyzx = 0x25; + static const int yyzy = 0x65; + static const int yyzz = 0xA5; + static const int yyzw = 0xE5; + static const int yywx = 0x35; + static const int yywy = 0x75; + static const int yywz = 0xB5; + static const int yyww = 0xF5; + static const int yzxx = 0x9; + static const int yzxy = 0x49; + static const int yzxz = 0x89; + static const int yzxw = 0xC9; + static const int yzyx = 0x19; + static const int yzyy = 0x59; + static const int yzyz = 0x99; + static const int yzyw = 0xD9; + static const int yzzx = 0x29; + static const int yzzy = 0x69; + static const int yzzz = 0xA9; + static const int yzzw = 0xE9; + static const int yzwx = 0x39; + static const int yzwy = 0x79; + static const int yzwz = 0xB9; + static const int yzww = 0xF9; + static const int ywxx = 0xD; + static const int ywxy = 0x4D; + static const int ywxz = 0x8D; + static const int ywxw = 0xCD; + static const int ywyx = 0x1D; + static const int ywyy = 0x5D; + static const int ywyz = 0x9D; + static const int ywyw = 0xDD; + static const int ywzx = 0x2D; + static const int ywzy = 0x6D; + static const int ywzz = 0xAD; + static const int ywzw = 0xED; + static const int ywwx = 0x3D; + static const int ywwy = 0x7D; + static const int ywwz = 0xBD; + static const int ywww = 0xFD; + static const int zxxx = 0x2; + static const int zxxy = 0x42; + static const int zxxz = 0x82; + static const int zxxw = 0xC2; + static const int zxyx = 0x12; + static const int zxyy = 0x52; + static const int zxyz = 0x92; + static const int zxyw = 0xD2; + static const int zxzx = 0x22; + static const int zxzy = 0x62; + static const int zxzz = 0xA2; + static const int zxzw = 0xE2; + static const int zxwx = 0x32; + static const int zxwy = 0x72; + static const int zxwz = 0xB2; + static const int zxww = 0xF2; + static const int zyxx = 0x6; + static const int zyxy = 0x46; + static const int zyxz = 0x86; + static const int zyxw = 0xC6; + static const int zyyx = 0x16; + static const int zyyy = 0x56; + static const int zyyz = 0x96; + static const int zyyw = 0xD6; + static const int zyzx = 0x26; + static const int zyzy = 0x66; + static const int zyzz = 0xA6; + static const int zyzw = 0xE6; + static const int zywx = 0x36; + static const int zywy = 0x76; + static const int zywz = 0xB6; + static const int zyww = 0xF6; + static const int zzxx = 0xA; + static const int zzxy = 0x4A; + static const int zzxz = 0x8A; + static const int zzxw = 0xCA; + static const int zzyx = 0x1A; + static const int zzyy = 0x5A; + static const int zzyz = 0x9A; + static const int zzyw = 0xDA; + static const int zzzx = 0x2A; + static const int zzzy = 0x6A; + static const int zzzz = 0xAA; + static const int zzzw = 0xEA; + static const int zzwx = 0x3A; + static const int zzwy = 0x7A; + static const int zzwz = 0xBA; + static const int zzww = 0xFA; + static const int zwxx = 0xE; + static const int zwxy = 0x4E; + static const int zwxz = 0x8E; + static const int zwxw = 0xCE; + static const int zwyx = 0x1E; + static const int zwyy = 0x5E; + static const int zwyz = 0x9E; + static const int zwyw = 0xDE; + static const int zwzx = 0x2E; + static const int zwzy = 0x6E; + static const int zwzz = 0xAE; + static const int zwzw = 0xEE; + static const int zwwx = 0x3E; + static const int zwwy = 0x7E; + static const int zwwz = 0xBE; + static const int zwww = 0xFE; + static const int wxxx = 0x3; + static const int wxxy = 0x43; + static const int wxxz = 0x83; + static const int wxxw = 0xC3; + static const int wxyx = 0x13; + static const int wxyy = 0x53; + static const int wxyz = 0x93; + static const int wxyw = 0xD3; + static const int wxzx = 0x23; + static const int wxzy = 0x63; + static const int wxzz = 0xA3; + static const int wxzw = 0xE3; + static const int wxwx = 0x33; + static const int wxwy = 0x73; + static const int wxwz = 0xB3; + static const int wxww = 0xF3; + static const int wyxx = 0x7; + static const int wyxy = 0x47; + static const int wyxz = 0x87; + static const int wyxw = 0xC7; + static const int wyyx = 0x17; + static const int wyyy = 0x57; + static const int wyyz = 0x97; + static const int wyyw = 0xD7; + static const int wyzx = 0x27; + static const int wyzy = 0x67; + static const int wyzz = 0xA7; + static const int wyzw = 0xE7; + static const int wywx = 0x37; + static const int wywy = 0x77; + static const int wywz = 0xB7; + static const int wyww = 0xF7; + static const int wzxx = 0xB; + static const int wzxy = 0x4B; + static const int wzxz = 0x8B; + static const int wzxw = 0xCB; + static const int wzyx = 0x1B; + static const int wzyy = 0x5B; + static const int wzyz = 0x9B; + static const int wzyw = 0xDB; + static const int wzzx = 0x2B; + static const int wzzy = 0x6B; + static const int wzzz = 0xAB; + static const int wzzw = 0xEB; + static const int wzwx = 0x3B; + static const int wzwy = 0x7B; + static const int wzwz = 0xBB; + static const int wzww = 0xFB; + static const int wwxx = 0xF; + static const int wwxy = 0x4F; + static const int wwxz = 0x8F; + static const int wwxw = 0xCF; + static const int wwyx = 0x1F; + static const int wwyy = 0x5F; + static const int wwyz = 0x9F; + static const int wwyw = 0xDF; + static const int wwzx = 0x2F; + static const int wwzy = 0x6F; + static const int wwzz = 0xAF; + static const int wwzw = 0xEF; + static const int wwwx = 0x3F; + static const int wwwy = 0x7F; + static const int wwwz = 0xBF; + static const int wwww = 0xFF; + + /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. + Float32x4 shuffle(int mask); + + /// Shuffle the lane values in [this] and [other]. The returned + /// Float32x4 will have XY lanes from [this] and ZW lanes from [other]. + /// Uses the same [mask] as [shuffle]. + Float32x4 shuffleMix(Float32x4 other, int mask); + + /// Returns a new [Float32x4] copied from [this] with a new x value. + Float32x4 withX(double x); + + /// Returns a new [Float32x4] copied from [this] with a new y value. + Float32x4 withY(double y); + + /// Returns a new [Float32x4] copied from [this] with a new z value. + Float32x4 withZ(double z); + + /// Returns a new [Float32x4] copied from [this] with a new w value. + Float32x4 withW(double w); + + /// Returns the lane-wise minimum value in [this] or [other]. + Float32x4 min(Float32x4 other); + + /// Returns the lane-wise maximum value in [this] or [other]. + Float32x4 max(Float32x4 other); + + /// Returns the square root of [this]. + Float32x4 sqrt(); + + /// Returns the reciprocal of [this]. + Float32x4 reciprocal(); + + /// Returns the square root of the reciprocal of [this]. + Float32x4 reciprocalSqrt(); +} + +/** + * Int32x4 and operations. + * + * Int32x4 stores 4 32-bit bit-masks in "lanes". + * The lanes are "x", "y", "z", and "w" respectively. + */ +abstract class Int32x4 { + external factory Int32x4(int x, int y, int z, int w); + external factory Int32x4.bool(bool x, bool y, bool z, bool w); + external factory Int32x4.fromFloat32x4Bits(Float32x4 x); + + /// The bit-wise or operator. + Int32x4 operator |(Int32x4 other); + + /// The bit-wise and operator. + Int32x4 operator &(Int32x4 other); + + /// The bit-wise xor operator. + Int32x4 operator ^(Int32x4 other); + + /// Addition operator. + Int32x4 operator +(Int32x4 other); + + /// Subtraction operator. + Int32x4 operator -(Int32x4 other); + + /// Extract 32-bit mask from x lane. + int get x; + + /// Extract 32-bit mask from y lane. + int get y; + + /// Extract 32-bit mask from z lane. + int get z; + + /// Extract 32-bit mask from w lane. + int get w; + + /// Extract the top bit from each lane return them in the first 4 bits. + /// "x" lane is bit 0. + /// "y" lane is bit 1. + /// "z" lane is bit 2. + /// "w" lane is bit 3. + int get signMask; + + /// Mask passed to [shuffle] or [shuffleMix]. + static const int xxxx = 0x0; + static const int xxxy = 0x40; + static const int xxxz = 0x80; + static const int xxxw = 0xC0; + static const int xxyx = 0x10; + static const int xxyy = 0x50; + static const int xxyz = 0x90; + static const int xxyw = 0xD0; + static const int xxzx = 0x20; + static const int xxzy = 0x60; + static const int xxzz = 0xA0; + static const int xxzw = 0xE0; + static const int xxwx = 0x30; + static const int xxwy = 0x70; + static const int xxwz = 0xB0; + static const int xxww = 0xF0; + static const int xyxx = 0x4; + static const int xyxy = 0x44; + static const int xyxz = 0x84; + static const int xyxw = 0xC4; + static const int xyyx = 0x14; + static const int xyyy = 0x54; + static const int xyyz = 0x94; + static const int xyyw = 0xD4; + static const int xyzx = 0x24; + static const int xyzy = 0x64; + static const int xyzz = 0xA4; + static const int xyzw = 0xE4; + static const int xywx = 0x34; + static const int xywy = 0x74; + static const int xywz = 0xB4; + static const int xyww = 0xF4; + static const int xzxx = 0x8; + static const int xzxy = 0x48; + static const int xzxz = 0x88; + static const int xzxw = 0xC8; + static const int xzyx = 0x18; + static const int xzyy = 0x58; + static const int xzyz = 0x98; + static const int xzyw = 0xD8; + static const int xzzx = 0x28; + static const int xzzy = 0x68; + static const int xzzz = 0xA8; + static const int xzzw = 0xE8; + static const int xzwx = 0x38; + static const int xzwy = 0x78; + static const int xzwz = 0xB8; + static const int xzww = 0xF8; + static const int xwxx = 0xC; + static const int xwxy = 0x4C; + static const int xwxz = 0x8C; + static const int xwxw = 0xCC; + static const int xwyx = 0x1C; + static const int xwyy = 0x5C; + static const int xwyz = 0x9C; + static const int xwyw = 0xDC; + static const int xwzx = 0x2C; + static const int xwzy = 0x6C; + static const int xwzz = 0xAC; + static const int xwzw = 0xEC; + static const int xwwx = 0x3C; + static const int xwwy = 0x7C; + static const int xwwz = 0xBC; + static const int xwww = 0xFC; + static const int yxxx = 0x1; + static const int yxxy = 0x41; + static const int yxxz = 0x81; + static const int yxxw = 0xC1; + static const int yxyx = 0x11; + static const int yxyy = 0x51; + static const int yxyz = 0x91; + static const int yxyw = 0xD1; + static const int yxzx = 0x21; + static const int yxzy = 0x61; + static const int yxzz = 0xA1; + static const int yxzw = 0xE1; + static const int yxwx = 0x31; + static const int yxwy = 0x71; + static const int yxwz = 0xB1; + static const int yxww = 0xF1; + static const int yyxx = 0x5; + static const int yyxy = 0x45; + static const int yyxz = 0x85; + static const int yyxw = 0xC5; + static const int yyyx = 0x15; + static const int yyyy = 0x55; + static const int yyyz = 0x95; + static const int yyyw = 0xD5; + static const int yyzx = 0x25; + static const int yyzy = 0x65; + static const int yyzz = 0xA5; + static const int yyzw = 0xE5; + static const int yywx = 0x35; + static const int yywy = 0x75; + static const int yywz = 0xB5; + static const int yyww = 0xF5; + static const int yzxx = 0x9; + static const int yzxy = 0x49; + static const int yzxz = 0x89; + static const int yzxw = 0xC9; + static const int yzyx = 0x19; + static const int yzyy = 0x59; + static const int yzyz = 0x99; + static const int yzyw = 0xD9; + static const int yzzx = 0x29; + static const int yzzy = 0x69; + static const int yzzz = 0xA9; + static const int yzzw = 0xE9; + static const int yzwx = 0x39; + static const int yzwy = 0x79; + static const int yzwz = 0xB9; + static const int yzww = 0xF9; + static const int ywxx = 0xD; + static const int ywxy = 0x4D; + static const int ywxz = 0x8D; + static const int ywxw = 0xCD; + static const int ywyx = 0x1D; + static const int ywyy = 0x5D; + static const int ywyz = 0x9D; + static const int ywyw = 0xDD; + static const int ywzx = 0x2D; + static const int ywzy = 0x6D; + static const int ywzz = 0xAD; + static const int ywzw = 0xED; + static const int ywwx = 0x3D; + static const int ywwy = 0x7D; + static const int ywwz = 0xBD; + static const int ywww = 0xFD; + static const int zxxx = 0x2; + static const int zxxy = 0x42; + static const int zxxz = 0x82; + static const int zxxw = 0xC2; + static const int zxyx = 0x12; + static const int zxyy = 0x52; + static const int zxyz = 0x92; + static const int zxyw = 0xD2; + static const int zxzx = 0x22; + static const int zxzy = 0x62; + static const int zxzz = 0xA2; + static const int zxzw = 0xE2; + static const int zxwx = 0x32; + static const int zxwy = 0x72; + static const int zxwz = 0xB2; + static const int zxww = 0xF2; + static const int zyxx = 0x6; + static const int zyxy = 0x46; + static const int zyxz = 0x86; + static const int zyxw = 0xC6; + static const int zyyx = 0x16; + static const int zyyy = 0x56; + static const int zyyz = 0x96; + static const int zyyw = 0xD6; + static const int zyzx = 0x26; + static const int zyzy = 0x66; + static const int zyzz = 0xA6; + static const int zyzw = 0xE6; + static const int zywx = 0x36; + static const int zywy = 0x76; + static const int zywz = 0xB6; + static const int zyww = 0xF6; + static const int zzxx = 0xA; + static const int zzxy = 0x4A; + static const int zzxz = 0x8A; + static const int zzxw = 0xCA; + static const int zzyx = 0x1A; + static const int zzyy = 0x5A; + static const int zzyz = 0x9A; + static const int zzyw = 0xDA; + static const int zzzx = 0x2A; + static const int zzzy = 0x6A; + static const int zzzz = 0xAA; + static const int zzzw = 0xEA; + static const int zzwx = 0x3A; + static const int zzwy = 0x7A; + static const int zzwz = 0xBA; + static const int zzww = 0xFA; + static const int zwxx = 0xE; + static const int zwxy = 0x4E; + static const int zwxz = 0x8E; + static const int zwxw = 0xCE; + static const int zwyx = 0x1E; + static const int zwyy = 0x5E; + static const int zwyz = 0x9E; + static const int zwyw = 0xDE; + static const int zwzx = 0x2E; + static const int zwzy = 0x6E; + static const int zwzz = 0xAE; + static const int zwzw = 0xEE; + static const int zwwx = 0x3E; + static const int zwwy = 0x7E; + static const int zwwz = 0xBE; + static const int zwww = 0xFE; + static const int wxxx = 0x3; + static const int wxxy = 0x43; + static const int wxxz = 0x83; + static const int wxxw = 0xC3; + static const int wxyx = 0x13; + static const int wxyy = 0x53; + static const int wxyz = 0x93; + static const int wxyw = 0xD3; + static const int wxzx = 0x23; + static const int wxzy = 0x63; + static const int wxzz = 0xA3; + static const int wxzw = 0xE3; + static const int wxwx = 0x33; + static const int wxwy = 0x73; + static const int wxwz = 0xB3; + static const int wxww = 0xF3; + static const int wyxx = 0x7; + static const int wyxy = 0x47; + static const int wyxz = 0x87; + static const int wyxw = 0xC7; + static const int wyyx = 0x17; + static const int wyyy = 0x57; + static const int wyyz = 0x97; + static const int wyyw = 0xD7; + static const int wyzx = 0x27; + static const int wyzy = 0x67; + static const int wyzz = 0xA7; + static const int wyzw = 0xE7; + static const int wywx = 0x37; + static const int wywy = 0x77; + static const int wywz = 0xB7; + static const int wyww = 0xF7; + static const int wzxx = 0xB; + static const int wzxy = 0x4B; + static const int wzxz = 0x8B; + static const int wzxw = 0xCB; + static const int wzyx = 0x1B; + static const int wzyy = 0x5B; + static const int wzyz = 0x9B; + static const int wzyw = 0xDB; + static const int wzzx = 0x2B; + static const int wzzy = 0x6B; + static const int wzzz = 0xAB; + static const int wzzw = 0xEB; + static const int wzwx = 0x3B; + static const int wzwy = 0x7B; + static const int wzwz = 0xBB; + static const int wzww = 0xFB; + static const int wwxx = 0xF; + static const int wwxy = 0x4F; + static const int wwxz = 0x8F; + static const int wwxw = 0xCF; + static const int wwyx = 0x1F; + static const int wwyy = 0x5F; + static const int wwyz = 0x9F; + static const int wwyw = 0xDF; + static const int wwzx = 0x2F; + static const int wwzy = 0x6F; + static const int wwzz = 0xAF; + static const int wwzw = 0xEF; + static const int wwwx = 0x3F; + static const int wwwy = 0x7F; + static const int wwwz = 0xBF; + static const int wwww = 0xFF; + + /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. + Int32x4 shuffle(int mask); + + /// Shuffle the lane values in [this] and [other]. The returned + /// Int32x4 will have XY lanes from [this] and ZW lanes from [other]. + /// Uses the same [mask] as [shuffle]. + Int32x4 shuffleMix(Int32x4 other, int mask); + + /// Returns a new [Int32x4] copied from [this] with a new x value. + Int32x4 withX(int x); + + /// Returns a new [Int32x4] copied from [this] with a new y value. + Int32x4 withY(int y); + + /// Returns a new [Int32x4] copied from [this] with a new z value. + Int32x4 withZ(int z); + + /// Returns a new [Int32x4] copied from [this] with a new w value. + Int32x4 withW(int w); + + /// Extracted x value. Returns false for 0, true for any other value. + bool get flagX; + + /// Extracted y value. Returns false for 0, true for any other value. + bool get flagY; + + /// Extracted z value. Returns false for 0, true for any other value. + bool get flagZ; + + /// Extracted w value. Returns false for 0, true for any other value. + bool get flagW; + + /// Returns a new [Int32x4] copied from [this] with a new x value. + Int32x4 withFlagX(bool x); + + /// Returns a new [Int32x4] copied from [this] with a new y value. + Int32x4 withFlagY(bool y); + + /// Returns a new [Int32x4] copied from [this] with a new z value. + Int32x4 withFlagZ(bool z); + + /// Returns a new [Int32x4] copied from [this] with a new w value. + Int32x4 withFlagW(bool w); + + /// Merge [trueValue] and [falseValue] based on [this]' bit mask: + /// Select bit from [trueValue] when bit in [this] is on. + /// Select bit from [falseValue] when bit in [this] is off. + Float32x4 select(Float32x4 trueValue, Float32x4 falseValue); +} + +/** + * Float64x2 immutable value type and operations. + * + * Float64x2 stores 2 64-bit floating point values in "lanes". + * The lanes are "x" and "y" respectively. + */ +abstract class Float64x2 { + external factory Float64x2(double x, double y); + external factory Float64x2.splat(double v); + external factory Float64x2.zero(); + + /// Uses the "x" and "y" lanes from [v]. + external factory Float64x2.fromFloat32x4(Float32x4 v); + + /// Addition operator. + Float64x2 operator +(Float64x2 other); + + /// Negate operator. + Float64x2 operator -(); + + /// Subtraction operator. + Float64x2 operator -(Float64x2 other); + + /// Multiplication operator. + Float64x2 operator *(Float64x2 other); + + /// Division operator. + Float64x2 operator /(Float64x2 other); + + /// Returns a copy of [this] each lane being scaled by [s]. + /// Equivalent to this * new Float64x2.splat(s) + Float64x2 scale(double s); + + /// Returns the lane-wise absolute value of this [Float64x2]. + Float64x2 abs(); + + /// Lane-wise clamp [this] to be in the range [lowerLimit]-[upperLimit]. + Float64x2 clamp(Float64x2 lowerLimit, Float64x2 upperLimit); + + /// Extracted x value. + double get x; + + /// Extracted y value. + double get y; + + /// Extract the sign bits from each lane return them in the first 2 bits. + /// "x" lane is bit 0. + /// "y" lane is bit 1. + int get signMask; + + /// Returns a new [Float64x2] copied from [this] with a new x value. + Float64x2 withX(double x); + + /// Returns a new [Float64x2] copied from [this] with a new y value. + Float64x2 withY(double y); + + /// Returns the lane-wise minimum value in [this] or [other]. + Float64x2 min(Float64x2 other); + + /// Returns the lane-wise maximum value in [this] or [other]. + Float64x2 max(Float64x2 other); + + /// Returns the lane-wise square root of [this]. + Float64x2 sqrt(); +} +NN<3D&"3%7@(7C:FMIK-*J>B:EMIK-*J<J:MMIK-*JLD:GO,INK-1*N@C:FO,INK-1*N>D:GO,IOK-2*N@C:FO,IOK-2*N>D:GO,IPK-3*N@C:FO,IPK-3*N>E:HP-IML-5*OBE:HO,IOK-2*NBE:HO,IPK-3*NBG:JP-IML-5*OFG:JP-IML-5*OFB:EMIK-*J<(O O0:19HKH)39?L3K/@&35OMG'HH=)J6J0GB-."$/H%)G;B>GK+&@9AJHF L9A?NE"-*9AKNK N9A>HK,&@9AJIF L9A?OE#-*9AKOK N9A>IK-&@9AJJF L9A?PE$-*9AKHI()F#C1:G;B> DB> DB>B>B>B>2@K?L0                PBJ)3GGGG@"@")(;168A; %!%!%%%' ' ' ' J0                PBH)/EEEEHHHHEEEED<>?2?+2.%+9))))>2@K?LGG@"@"3ofile:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/dev_compiler/tool/input_sdk/patch/typed_data_patch.dart// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; +import 'dart:_js_helper' show patch; +import 'dart:_native_typed_data'; + +@patch +class ByteData { + @patch + factory ByteData(int length) = NativeByteData; +} + +@patch +class Float32List { + @patch + factory Float32List(int length) = NativeFloat32List; + + @patch + factory Float32List.fromList(List elements) = + NativeFloat32List.fromList; +} + +@patch +class Float64List { + @patch + factory Float64List(int length) = NativeFloat64List; + + @patch + factory Float64List.fromList(List elements) = + NativeFloat64List.fromList; +} + +@patch +class Int16List { + @patch + factory Int16List(int length) = NativeInt16List; + + @patch + factory Int16List.fromList(List elements) = NativeInt16List.fromList; +} + +@patch +class Int32List { + @patch + factory Int32List(int length) = NativeInt32List; + + @patch + factory Int32List.fromList(List elements) = NativeInt32List.fromList; +} + +@patch +class Int8List { + @patch + factory Int8List(int length) = NativeInt8List; + + @patch + factory Int8List.fromList(List elements) = NativeInt8List.fromList; +} + +@patch +class Uint32List { + @patch + factory Uint32List(int length) = NativeUint32List; + + @patch + factory Uint32List.fromList(List elements) = NativeUint32List.fromList; +} + +@patch +class Uint16List { + @patch + factory Uint16List(int length) = NativeUint16List; + + @patch + factory Uint16List.fromList(List elements) = NativeUint16List.fromList; +} + +@patch +class Uint8ClampedList { + @patch + factory Uint8ClampedList(int length) = NativeUint8ClampedList; + + @patch + factory Uint8ClampedList.fromList(List elements) = + NativeUint8ClampedList.fromList; +} + +@patch +class Uint8List { + @patch + factory Uint8List(int length) = NativeUint8List; + + @patch + factory Uint8List.fromList(List elements) = NativeUint8List.fromList; +} + +@patch +class Int64List { + @patch + factory Int64List(int length) { + throw UnsupportedError("Int64List not supported by dart2js."); + } + + @patch + factory Int64List.fromList(List elements) { + throw UnsupportedError("Int64List not supported by dart2js."); + } +} + +@patch +class Uint64List { + @patch + factory Uint64List(int length) { + throw UnsupportedError("Uint64List not supported by dart2js."); + } + + @patch + factory Uint64List.fromList(List elements) { + throw UnsupportedError("Uint64List not supported by dart2js."); + } +} + +@patch +class Int32x4List { + @patch + factory Int32x4List(int length) = NativeInt32x4List; + + @patch + factory Int32x4List.fromList(List elements) = + NativeInt32x4List.fromList; +} + +@patch +class Float32x4List { + @patch + factory Float32x4List(int length) = NativeFloat32x4List; + + @patch + factory Float32x4List.fromList(List elements) = + NativeFloat32x4List.fromList; +} + +@patch +class Float64x2List { + @patch + factory Float64x2List(int length) = NativeFloat64x2List; + + @patch + factory Float64x2List.fromList(List elements) = + NativeFloat64x2List.fromList; +} + +@patch +class Float32x4 { + @patch + factory Float32x4(double x, double y, double z, double w) = NativeFloat32x4; + @patch + factory Float32x4.splat(double v) = NativeFloat32x4.splat; + @patch + factory Float32x4.zero() = NativeFloat32x4.zero; + @patch + factory Float32x4.fromInt32x4Bits(Int32x4 x) = + NativeFloat32x4.fromInt32x4Bits; + @patch + factory Float32x4.fromFloat64x2(Float64x2 v) = NativeFloat32x4.fromFloat64x2; +} + +@patch +class Int32x4 { + @patch + factory Int32x4(int x, int y, int z, int w) = NativeInt32x4; + @patch + factory Int32x4.bool(bool x, bool y, bool z, bool w) = NativeInt32x4.bool; + @patch + factory Int32x4.fromFloat32x4Bits(Float32x4 x) = + NativeInt32x4.fromFloat32x4Bits; +} + +@patch +class Float64x2 { + @patch + factory Float64x2(double x, double y) = NativeFloat64x2; + @patch + factory Float64x2.splat(double v) = NativeFloat64x2.splat; + @patch + factory Float64x2.zero() = NativeFloat64x2.zero; + @patch + factory Float64x2.fromFloat32x4(Float32x4 v) = NativeFloat64x2.fromFloat32x4; +} +NN<%" 1 7 8" 7 8" 3 M 3 M 1 K 5 O 5 O A :' 3 M "C 3C #D 4D 7 9" ; =$ ; =$ O = 3 1' P ? M 3' ; = 3 Pcfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/typed_data/unmodifiable_typed_data.dart// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart.typed_data; + +/** + * A read-only view of a [ByteBuffer]. + */ +class UnmodifiableByteBufferView implements ByteBuffer { + final ByteBuffer _data; + + UnmodifiableByteBufferView(ByteBuffer data) : _data = data; + + int get lengthInBytes => _data.lengthInBytes; + + Uint8List asUint8List([int offsetInBytes = 0, int length]) => + new UnmodifiableUint8ListView(_data.asUint8List(offsetInBytes, length)); + + Int8List asInt8List([int offsetInBytes = 0, int length]) => + new UnmodifiableInt8ListView(_data.asInt8List(offsetInBytes, length)); + + Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) => + new UnmodifiableUint8ClampedListView( + _data.asUint8ClampedList(offsetInBytes, length)); + + Uint16List asUint16List([int offsetInBytes = 0, int length]) => + new UnmodifiableUint16ListView(_data.asUint16List(offsetInBytes, length)); + + Int16List asInt16List([int offsetInBytes = 0, int length]) => + new UnmodifiableInt16ListView(_data.asInt16List(offsetInBytes, length)); + + Uint32List asUint32List([int offsetInBytes = 0, int length]) => + new UnmodifiableUint32ListView(_data.asUint32List(offsetInBytes, length)); + + Int32List asInt32List([int offsetInBytes = 0, int length]) => + new UnmodifiableInt32ListView(_data.asInt32List(offsetInBytes, length)); + + Uint64List asUint64List([int offsetInBytes = 0, int length]) => + new UnmodifiableUint64ListView(_data.asUint64List(offsetInBytes, length)); + + Int64List asInt64List([int offsetInBytes = 0, int length]) => + new UnmodifiableInt64ListView(_data.asInt64List(offsetInBytes, length)); + + Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) => + new UnmodifiableInt32x4ListView( + _data.asInt32x4List(offsetInBytes, length)); + + Float32List asFloat32List([int offsetInBytes = 0, int length]) => + new UnmodifiableFloat32ListView( + _data.asFloat32List(offsetInBytes, length)); + + Float64List asFloat64List([int offsetInBytes = 0, int length]) => + new UnmodifiableFloat64ListView( + _data.asFloat64List(offsetInBytes, length)); + + Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) => + new UnmodifiableFloat32x4ListView( + _data.asFloat32x4List(offsetInBytes, length)); + + Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) => + new UnmodifiableFloat64x2ListView( + _data.asFloat64x2List(offsetInBytes, length)); + + ByteData asByteData([int offsetInBytes = 0, int length]) => + new UnmodifiableByteDataView(_data.asByteData(offsetInBytes, length)); +} + +/** + * A read-only view of a [ByteData]. + */ +class UnmodifiableByteDataView implements ByteData { + final ByteData _data; + + UnmodifiableByteDataView(ByteData data) : _data = data; + + int getInt8(int byteOffset) => _data.getInt8(byteOffset); + + void setInt8(int byteOffset, int value) => _unsupported(); + + int getUint8(int byteOffset) => _data.getUint8(byteOffset); + + void setUint8(int byteOffset, int value) => _unsupported(); + + int getInt16(int byteOffset, [Endian endian = Endian.big]) => + _data.getInt16(byteOffset, endian); + + void setInt16(int byteOffset, int value, [Endian endian = Endian.big]) => + _unsupported(); + + int getUint16(int byteOffset, [Endian endian = Endian.big]) => + _data.getUint16(byteOffset, endian); + + void setUint16(int byteOffset, int value, [Endian endian = Endian.big]) => + _unsupported(); + + int getInt32(int byteOffset, [Endian endian = Endian.big]) => + _data.getInt32(byteOffset, endian); + + void setInt32(int byteOffset, int value, [Endian endian = Endian.big]) => + _unsupported(); + + int getUint32(int byteOffset, [Endian endian = Endian.big]) => + _data.getUint32(byteOffset, endian); + + void setUint32(int byteOffset, int value, [Endian endian = Endian.big]) => + _unsupported(); + + int getInt64(int byteOffset, [Endian endian = Endian.big]) => + _data.getInt64(byteOffset, endian); + + void setInt64(int byteOffset, int value, [Endian endian = Endian.big]) => + _unsupported(); + + int getUint64(int byteOffset, [Endian endian = Endian.big]) => + _data.getUint64(byteOffset, endian); + + void setUint64(int byteOffset, int value, [Endian endian = Endian.big]) => + _unsupported(); + + double getFloat32(int byteOffset, [Endian endian = Endian.big]) => + _data.getFloat32(byteOffset, endian); + + void setFloat32(int byteOffset, double value, [Endian endian = Endian.big]) => + _unsupported(); + + double getFloat64(int byteOffset, [Endian endian = Endian.big]) => + _data.getFloat64(byteOffset, endian); + + void setFloat64(int byteOffset, double value, [Endian endian = Endian.big]) => + _unsupported(); + + int get elementSizeInBytes => _data.elementSizeInBytes; + + int get offsetInBytes => _data.offsetInBytes; + + int get lengthInBytes => _data.lengthInBytes; + + ByteBuffer get buffer => new UnmodifiableByteBufferView(_data.buffer); + + void _unsupported() { + throw new UnsupportedError( + "An UnmodifiableByteDataView may not be modified"); + } +} + +abstract class _UnmodifiableListMixin, + TD extends TypedData> { + L get _list; + TD get _data => (_list as TD); + + int get length => _list.length; + + N operator [](int index) => _list[index]; + + int get elementSizeInBytes => _data.elementSizeInBytes; + + int get offsetInBytes => _data.offsetInBytes; + + int get lengthInBytes => _data.lengthInBytes; + + ByteBuffer get buffer => new UnmodifiableByteBufferView(_data.buffer); +} + +/** + * View of a [Uint8List] that disallows modification. + */ +class UnmodifiableUint8ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Uint8List { + final Uint8List _list; + UnmodifiableUint8ListView(Uint8List list) : _list = list; +} + +/** + * View of a [Int8List] that disallows modification. + */ +class UnmodifiableInt8ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Int8List { + final Int8List _list; + UnmodifiableInt8ListView(Int8List list) : _list = list; +} + +/** + * View of a [Uint8ClampedList] that disallows modification. + */ +class UnmodifiableUint8ClampedListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Uint8ClampedList { + final Uint8ClampedList _list; + UnmodifiableUint8ClampedListView(Uint8ClampedList list) : _list = list; +} + +/** + * View of a [Uint16List] that disallows modification. + */ +class UnmodifiableUint16ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Uint16List { + final Uint16List _list; + UnmodifiableUint16ListView(Uint16List list) : _list = list; +} + +/** + * View of a [Int16List] that disallows modification. + */ +class UnmodifiableInt16ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Int16List { + final Int16List _list; + UnmodifiableInt16ListView(Int16List list) : _list = list; +} + +/** + * View of a [Uint32List] that disallows modification. + */ +class UnmodifiableUint32ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Uint32List { + final Uint32List _list; + UnmodifiableUint32ListView(Uint32List list) : _list = list; +} + +/** + * View of a [Int32List] that disallows modification. + */ +class UnmodifiableInt32ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Int32List { + final Int32List _list; + UnmodifiableInt32ListView(Int32List list) : _list = list; +} + +/** + * View of a [Uint64List] that disallows modification. + */ +class UnmodifiableUint64ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Uint64List { + final Uint64List _list; + UnmodifiableUint64ListView(Uint64List list) : _list = list; +} + +/** + * View of a [Int64List] that disallows modification. + */ +class UnmodifiableInt64ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Int64List { + final Int64List _list; + UnmodifiableInt64ListView(Int64List list) : _list = list; +} + +/** + * View of a [Int32x4List] that disallows modification. + */ +class UnmodifiableInt32x4ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Int32x4List { + final Int32x4List _list; + UnmodifiableInt32x4ListView(Int32x4List list) : _list = list; +} + +/** + * View of a [Float32x4List] that disallows modification. + */ +class UnmodifiableFloat32x4ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Float32x4List { + final Float32x4List _list; + UnmodifiableFloat32x4ListView(Float32x4List list) : _list = list; +} + +/** + * View of a [Float64x2List] that disallows modification. + */ +class UnmodifiableFloat64x2ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Float64x2List { + final Float64x2List _list; + UnmodifiableFloat64x2ListView(Float64x2List list) : _list = list; +} + +/** + * View of a [Float32List] that disallows modification. + */ +class UnmodifiableFloat32ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Float32List { + final Float32List _list; + UnmodifiableFloat32ListView(Float32List list) : _list = list; +} + +/** + * View of a [Float64List] that disallows modification. + */ +class UnmodifiableFloat64ListView extends UnmodifiableListBase + with _UnmodifiableListMixin + implements Float64List { + final Float64List _list; + UnmodifiableFloat64ListView(Float64List list) : _list = list; +} +1NN<'9>0@O>MN,<BQ@OBQ@OBQ@OD'7D'7D'7H)9H)9>M%5:<=>>@*LA+M@*LA+M@*LA+ME,QE,Q:00I <<!",:00I6B;<5A9:=II" J7C=>6B;<7C=>6B;<7C=>6B;<8HC@:LID:LID8GB@8GB@ffile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart/** + * A client-side key-value store with support for indexes. + * + * Many browsers support IndexedDB—a web standard for + * an indexed database. + * By storing data on the client in an IndexedDB, + * a web app gets some advantages, such as faster performance and persistence. + * To find out which browsers support IndexedDB, + * refer to [Can I Use?](http://caniuse.com/#feat=indexeddb) + * + * In IndexedDB, each record is identified by a unique index or key, + * making data retrieval speedy. + * You can store structured data, + * such as images, arrays, and maps using IndexedDB. + * The standard does not specify size limits for individual data items + * or for the database itself, but browsers may impose storage limits. + * + * ## Using indexed_db + * + * The classes in this library provide an interface + * to the browser's IndexedDB, if it has one. + * To use this library in your code: + * + * import 'dart:indexed_db'; + * + * A web app can determine if the browser supports + * IndexedDB with [IdbFactory.supported]: + * + * if (IdbFactory.supported) + * // Use indexeddb. + * else + * // Find an alternative. + * + * Access to the browser's IndexedDB is provided by the app's top-level + * [Window] object, which your code can refer to with `window.indexedDB`. + * So, for example, + * here's how to use window.indexedDB to open a database: + * + * Future open() { + * return window.indexedDB.open('myIndexedDB', + * version: 1, + * onUpgradeNeeded: _initializeDatabase) + * .then(_loadFromDB); + * } + * void _initializeDatabase(VersionChangeEvent e) { + * ... + * } + * Future _loadFromDB(Database db) { + * ... + * } + * + * + * All data in an IndexedDB is stored within an [ObjectStore]. + * To manipulate the database use [Transaction]s. + * + * ## Other resources + * + * Other options for client-side data storage include: + * + * * [Window.localStorage]—a + * basic mechanism that stores data as a [Map], + * and where both the keys and the values are strings. + * + * * [dart:web_sql]—a database that can be queried with SQL. + * + * For a tutorial about using the indexed_db library with Dart, + * check out + * [Use IndexedDB](http://www.dartlang.org/docs/tutorials/indexeddb/). + * + * [IndexedDB reference](http://docs.webplatform.org/wiki/apis/indexeddb) + * provides wiki-style docs about indexedDB + * + * {@category Web} + */ +library dart.dom.indexed_db; + +import 'dart:async'; +import 'dart:html'; +import 'dart:html_common'; +import 'dart:_native_typed_data'; +import 'dart:typed_data'; +import 'dart:_js_helper' show Creates, Returns, JSName, Native; +import 'dart:_foreign_helper' show JS; +import 'dart:_interceptors' show Interceptor, JSExtendableArray; +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// DO NOT EDIT - unless you are editing documentation as per: +// https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation +// Auto-generated dart:svg library. + +class _KeyRangeFactoryProvider { + static KeyRange createKeyRange_only(/*Key*/ value) => + _only(_class(), _translateKey(value)); + + static KeyRange createKeyRange_lowerBound( + /*Key*/ bound, + [bool open = false]) => + _lowerBound(_class(), _translateKey(bound), open); + + static KeyRange createKeyRange_upperBound( + /*Key*/ bound, + [bool open = false]) => + _upperBound(_class(), _translateKey(bound), open); + + static KeyRange createKeyRange_bound(/*Key*/ lower, /*Key*/ upper, + [bool lowerOpen = false, bool upperOpen = false]) => + _bound(_class(), _translateKey(lower), _translateKey(upper), lowerOpen, + upperOpen); + + static var _cachedClass; + + static _class() { + if (_cachedClass != null) return _cachedClass; + return _cachedClass = _uncachedClass(); + } + + static _uncachedClass() => + JS('var', '''window.webkitIDBKeyRange || window.mozIDBKeyRange || + window.msIDBKeyRange || window.IDBKeyRange'''); + + static _translateKey(idbkey) => idbkey; // TODO: fixme. + + static KeyRange _only(cls, value) => JS('KeyRange', '#.only(#)', cls, value); + + static KeyRange _lowerBound(cls, bound, open) => + JS('KeyRange', '#.lowerBound(#, #)', cls, bound, open); + + static KeyRange _upperBound(cls, bound, open) => + JS('KeyRange', '#.upperBound(#, #)', cls, bound, open); + + static KeyRange _bound(cls, lower, upper, lowerOpen, upperOpen) => JS( + 'KeyRange', + '#.bound(#, #, #, #)', + cls, + lower, + upper, + lowerOpen, + upperOpen); +} + +// Conversions for IDBKey. +// +// Per http://www.w3.org/TR/IndexedDB/#key-construct +// +// "A value is said to be a valid key if it is one of the following types: Array +// JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float +// [WEBIDL]. However Arrays are only valid keys if every item in the array is +// defined and is a valid key (i.e. sparse arrays can not be valid keys) and if +// the Array doesn't directly or indirectly contain itself. Any non-numeric +// properties are ignored, and thus does not affect whether the Array is a valid +// key. Additionally, if the value is of type float, it is only a valid key if +// it is not NaN, and if the value is of type Date it is only a valid key if its +// [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN." + +// What is required is to ensure that an Lists in the key are actually +// JavaScript arrays, and any Dates are JavaScript Dates. + +/** + * Converts a native IDBKey into a Dart object. + * + * May return the original input. May mutate the original input (but will be + * idempotent if mutation occurs). It is assumed that this conversion happens + * on native IDBKeys on all paths that return IDBKeys from native DOM calls. + * + * If necessary, JavaScript Dates are converted into Dart Dates. + */ +_convertNativeToDart_IDBKey(nativeKey) { + containsDate(object) { + if (isJavaScriptDate(object)) return true; + if (object is List) { + for (int i = 0; i < object.length; i++) { + if (containsDate(object[i])) return true; + } + } + return false; // number, string. + } + + if (containsDate(nativeKey)) { + throw new UnimplementedError('Key containing DateTime'); + } + // TODO: Cache conversion somewhere? + return nativeKey; +} + +/** + * Converts a Dart object into a valid IDBKey. + * + * May return the original input. Does not mutate input. + * + * If necessary, [dartKey] may be copied to ensure all lists are converted into + * JavaScript Arrays and Dart Dates into JavaScript Dates. + */ +_convertDartToNative_IDBKey(dartKey) { + // TODO: Implement. + return dartKey; +} + +/// May modify original. If so, action is idempotent. +_convertNativeToDart_IDBAny(object) { + return convertNativeToDart_AcceptStructuredClone(object, mustCopy: false); +} + +// TODO(sra): Add DateTime. +const String _idbKey = 'JSExtendableArray|=Object|num|String'; +const _annotation_Creates_IDBKey = const Creates(_idbKey); +const _annotation_Returns_IDBKey = const Returns(_idbKey); +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBCursor") +class Cursor extends Interceptor { + Future delete() { + try { + return _completeRequest(_delete()); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future update(value) { + try { + return _completeRequest(_update(value)); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + @JSName('continue') + void next([Object key]) { + if (key == null) { + JS('void', '#.continue()', this); + } else { + JS('void', '#.continue(#)', this, key); + } + } + + // To suppress missing implicit constructor warnings. + factory Cursor._() { + throw new UnsupportedError("Not supported"); + } + + final String direction; + + @_annotation_Creates_IDBKey + @_annotation_Returns_IDBKey + final Object key; + + @_annotation_Creates_IDBKey + @_annotation_Returns_IDBKey + final Object primaryKey; + + @Creates('Null') + @Returns('ObjectStore|Index|Null') + final Object source; + + void advance(int count) native; + + void continuePrimaryKey(Object key, Object primaryKey) native; + + @JSName('delete') + Request _delete() native; + + Request _update(/*any*/ value) { + var value_1 = convertDartToNative_SerializedScriptValue(value); + return _update_1(value_1); + } + + @JSName('update') + Request _update_1(value) native; +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBCursorWithValue") +class CursorWithValue extends Cursor { + // To suppress missing implicit constructor warnings. + factory CursorWithValue._() { + throw new UnsupportedError("Not supported"); + } + + dynamic get value => _convertNativeToDart_IDBAny(this._get_value); + @JSName('value') + @annotation_Creates_SerializedScriptValue + @annotation_Returns_SerializedScriptValue + final dynamic _get_value; +} +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * An indexed database object for storing client-side data + * in web apps. + */ +@SupportedBrowser(SupportedBrowser.CHROME) +@SupportedBrowser(SupportedBrowser.FIREFOX, '15') +@SupportedBrowser(SupportedBrowser.IE, '10') +@Unstable() +@Native("IDBDatabase") +class Database extends EventTarget { + ObjectStore createObjectStore(String name, + {String keyPath, bool autoIncrement}) { + var options = {}; + if (keyPath != null) { + options['keyPath'] = keyPath; + } + if (autoIncrement != null) { + options['autoIncrement'] = autoIncrement; + } + + return _createObjectStore(name, options); + } + + Transaction transaction(storeName_OR_storeNames, String mode) { + if (mode != 'readonly' && mode != 'readwrite') { + throw new ArgumentError(mode); + } + + // TODO(sra): Ensure storeName_OR_storeNames is a string or List, + // and copy to JavaScript array if necessary. + + // Try and create a transaction with a string mode. Browsers that expect a + // numeric mode tend to convert the string into a number. This fails + // silently, resulting in zero ('readonly'). + return _transaction(storeName_OR_storeNames, mode); + } + + Transaction transactionStore(String storeName, String mode) { + if (mode != 'readonly' && mode != 'readwrite') { + throw new ArgumentError(mode); + } + // Try and create a transaction with a string mode. Browsers that expect a + // numeric mode tend to convert the string into a number. This fails + // silently, resulting in zero ('readonly'). + return _transaction(storeName, mode); + } + + Transaction transactionList(List storeNames, String mode) { + if (mode != 'readonly' && mode != 'readwrite') { + throw new ArgumentError(mode); + } + List storeNames_1 = convertDartToNative_StringArray(storeNames); + return _transaction(storeNames_1, mode); + } + + Transaction transactionStores(DomStringList storeNames, String mode) { + if (mode != 'readonly' && mode != 'readwrite') { + throw new ArgumentError(mode); + } + return _transaction(storeNames, mode); + } + + @JSName('transaction') + Transaction _transaction(stores, mode) native; + + // To suppress missing implicit constructor warnings. + factory Database._() { + throw new UnsupportedError("Not supported"); + } + + /** + * Static factory designed to expose `abort` events to event + * handlers that are not necessarily instances of [Database]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider abortEvent = + const EventStreamProvider('abort'); + + /** + * Static factory designed to expose `close` events to event + * handlers that are not necessarily instances of [Database]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider closeEvent = + const EventStreamProvider('close'); + + /** + * Static factory designed to expose `error` events to event + * handlers that are not necessarily instances of [Database]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider errorEvent = + const EventStreamProvider('error'); + + /** + * Static factory designed to expose `versionchange` events to event + * handlers that are not necessarily instances of [Database]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider versionChangeEvent = + const EventStreamProvider('versionchange'); + + final String name; + + @Returns('DomStringList|Null') + @Creates('DomStringList') + final List objectStoreNames; + + @Creates('int|String|Null') + @Returns('int|String|Null') + final int version; + + void close() native; + + ObjectStore _createObjectStore(String name, [Map options]) { + if (options != null) { + var options_1 = convertDartToNative_Dictionary(options); + return _createObjectStore_1(name, options_1); + } + return _createObjectStore_2(name); + } + + @JSName('createObjectStore') + ObjectStore _createObjectStore_1(name, options) native; + @JSName('createObjectStore') + ObjectStore _createObjectStore_2(name) native; + + void deleteObjectStore(String name) native; + + /// Stream of `abort` events handled by this [Database]. + Stream get onAbort => abortEvent.forTarget(this); + + /// Stream of `close` events handled by this [Database]. + Stream get onClose => closeEvent.forTarget(this); + + /// Stream of `error` events handled by this [Database]. + Stream get onError => errorEvent.forTarget(this); + + /// Stream of `versionchange` events handled by this [Database]. + Stream get onVersionChange => + versionChangeEvent.forTarget(this); +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// WARNING: Do not edit - generated code. + +typedef void ObserverCallback(ObserverChanges changes); +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@SupportedBrowser(SupportedBrowser.CHROME) +@SupportedBrowser(SupportedBrowser.FIREFOX, '15') +@SupportedBrowser(SupportedBrowser.IE, '10') +@Unstable() +@Native("IDBFactory") +class IdbFactory extends Interceptor { + /** + * Checks to see if Indexed DB is supported on the current platform. + */ + static bool get supported { + return JS( + 'bool', + '!!(window.indexedDB || ' + 'window.webkitIndexedDB || ' + 'window.mozIndexedDB)'); + } + + Future open(String name, + {int version, + void onUpgradeNeeded(VersionChangeEvent event), + void onBlocked(Event event)}) { + if ((version == null) != (onUpgradeNeeded == null)) { + return new Future.error(new ArgumentError( + 'version and onUpgradeNeeded must be specified together')); + } + try { + var request; + if (version != null) { + request = _open(name, version); + } else { + request = _open(name); + } + + if (onUpgradeNeeded != null) { + request.onUpgradeNeeded.listen(onUpgradeNeeded); + } + if (onBlocked != null) { + request.onBlocked.listen(onBlocked); + } + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future deleteDatabase(String name, {void onBlocked(Event e)}) { + try { + var request = _deleteDatabase(name); + + if (onBlocked != null) { + request.onBlocked.listen(onBlocked); + } + var completer = new Completer.sync(); + request.onSuccess.listen((e) { + completer.complete(this); + }); + request.onError.listen(completer.completeError); + return completer.future; + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + /** + * Checks to see if getDatabaseNames is supported by the current platform. + * TODO(terry): Should be able to always return false? + */ + bool get supportsDatabaseNames { + return supported && + JS('bool', '!!(#.getDatabaseNames || #.webkitGetDatabaseNames)', this, + this); + } + + // To suppress missing implicit constructor warnings. + factory IdbFactory._() { + throw new UnsupportedError("Not supported"); + } + + int cmp(Object first, Object second) native; + + @JSName('deleteDatabase') + OpenDBRequest _deleteDatabase(String name) native; + + @JSName('open') + @Returns('Request') + @Creates('Request') + @Creates('Database') + OpenDBRequest _open(String name, [int version]) native; +} + +/** + * Ties a request to a completer, so the completer is completed when it succeeds + * and errors out when the request errors. + */ +Future _completeRequest(Request request) { + var completer = new Completer.sync(); + // TODO: make sure that completer.complete is synchronous as transactions + // may be committed if the result is not processed immediately. + request.onSuccess.listen((e) { + T result = request.result; + completer.complete(result); + }); + request.onError.listen(completer.completeError); + return completer.future; +} +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBIndex") +class Index extends Interceptor { + Future count([key_OR_range]) { + try { + var request = _count(key_OR_range); + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future get(key) { + try { + var request = _get(key); + + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future getKey(key) { + try { + var request = _getKey(key); + + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + /** + * Creates a stream of cursors over the records in this object store. + * + * See also: + * + * * [ObjectStore.openCursor] + */ + Stream openCursor( + {key, KeyRange range, String direction, bool autoAdvance}) { + var key_OR_range = null; + if (key != null) { + if (range != null) { + throw new ArgumentError('Cannot specify both key and range.'); + } + key_OR_range = key; + } else { + key_OR_range = range; + } + var request; + if (direction == null) { + // FIXME: Passing in "next" should be unnecessary. + request = _openCursor(key_OR_range, "next"); + } else { + request = _openCursor(key_OR_range, direction); + } + return ObjectStore._cursorStreamFromResult(request, autoAdvance); + } + + /** + * Creates a stream of cursors over the records in this object store. + * + * See also: + * + * * [ObjectStore.openCursor] + */ + Stream openKeyCursor( + {key, KeyRange range, String direction, bool autoAdvance}) { + var key_OR_range = null; + if (key != null) { + if (range != null) { + throw new ArgumentError('Cannot specify both key and range.'); + } + key_OR_range = key; + } else { + key_OR_range = range; + } + var request; + if (direction == null) { + // FIXME: Passing in "next" should be unnecessary. + request = _openKeyCursor(key_OR_range, "next"); + } else { + request = _openKeyCursor(key_OR_range, direction); + } + return ObjectStore._cursorStreamFromResult(request, autoAdvance); + } + + // To suppress missing implicit constructor warnings. + factory Index._() { + throw new UnsupportedError("Not supported"); + } + + @annotation_Creates_SerializedScriptValue + final Object keyPath; + + final bool multiEntry; + + String name; + + final ObjectStore objectStore; + + final bool unique; + + @JSName('count') + Request _count(Object key) native; + + @JSName('get') + @Returns('Request') + @Creates('Request') + @annotation_Creates_SerializedScriptValue + Request _get(Object key) native; + + Request getAll(Object query, [int count]) native; + + Request getAllKeys(Object query, [int count]) native; + + @JSName('getKey') + @Returns('Request') + @Creates('Request') + @annotation_Creates_SerializedScriptValue + @Creates('ObjectStore') + Request _getKey(Object key) native; + + @JSName('openCursor') + @Returns('Request') + @Creates('Request') + @Creates('Cursor') + Request _openCursor(Object range, [String direction]) native; + + @JSName('openKeyCursor') + @Returns('Request') + @Creates('Request') + @Creates('Cursor') + Request _openKeyCursor(Object range, [String direction]) native; +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBKeyRange") +class KeyRange extends Interceptor { + factory KeyRange.only(/*Key*/ value) => + _KeyRangeFactoryProvider.createKeyRange_only(value); + + factory KeyRange.lowerBound(/*Key*/ bound, [bool open = false]) => + _KeyRangeFactoryProvider.createKeyRange_lowerBound(bound, open); + + factory KeyRange.upperBound(/*Key*/ bound, [bool open = false]) => + _KeyRangeFactoryProvider.createKeyRange_upperBound(bound, open); + + factory KeyRange.bound(/*Key*/ lower, /*Key*/ upper, + [bool lowerOpen = false, bool upperOpen = false]) => + _KeyRangeFactoryProvider.createKeyRange_bound( + lower, upper, lowerOpen, upperOpen); + + // To suppress missing implicit constructor warnings. + factory KeyRange._() { + throw new UnsupportedError("Not supported"); + } + + @annotation_Creates_SerializedScriptValue + final Object lower; + + final bool lowerOpen; + + @annotation_Creates_SerializedScriptValue + final Object upper; + + final bool upperOpen; + + @JSName('bound') + static KeyRange bound_(Object lower, Object upper, + [bool lowerOpen, bool upperOpen]) native; + + bool includes(Object key) native; + + @JSName('lowerBound') + static KeyRange lowerBound_(Object bound, [bool open]) native; + + @JSName('only') + static KeyRange only_(Object value) native; + + @JSName('upperBound') + static KeyRange upperBound_(Object bound, [bool open]) native; +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBObjectStore") +class ObjectStore extends Interceptor { + Future add(value, [key]) { + try { + var request; + if (key != null) { + request = _add(value, key); + } else { + request = _add(value); + } + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future clear() { + try { + return _completeRequest(_clear()); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future delete(key_OR_keyRange) { + try { + return _completeRequest(_delete(key_OR_keyRange)); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future count([key_OR_range]) { + try { + var request = _count(key_OR_range); + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future put(value, [key]) { + try { + var request; + if (key != null) { + request = _put(value, key); + } else { + request = _put(value); + } + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + Future getObject(key) { + try { + var request = _get(key); + + return _completeRequest(request); + } catch (e, stacktrace) { + return new Future.error(e, stacktrace); + } + } + + /** + * Creates a stream of cursors over the records in this object store. + * + * **The stream must be manually advanced by calling [Cursor.next] after + * each item or by specifying autoAdvance to be true.** + * + * var cursors = objectStore.openCursor().listen( + * (cursor) { + * // ...some processing with the cursor + * cursor.next(); // advance onto the next cursor. + * }, + * onDone: () { + * // called when there are no more cursors. + * print('all done!'); + * }); + * + * Asynchronous operations which are not related to the current transaction + * will cause the transaction to automatically be committed-- all processing + * must be done synchronously unless they are additional async requests to + * the current transaction. + */ + Stream openCursor( + {key, KeyRange range, String direction, bool autoAdvance}) { + var key_OR_range = null; + if (key != null) { + if (range != null) { + throw new ArgumentError('Cannot specify both key and range.'); + } + key_OR_range = key; + } else { + key_OR_range = range; + } + + // TODO: try/catch this and return a stream with an immediate error. + var request; + if (direction == null) { + request = _openCursor(key_OR_range); + } else { + request = _openCursor(key_OR_range, direction); + } + return _cursorStreamFromResult(request, autoAdvance); + } + + Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) { + var options = {}; + if (unique != null) { + options['unique'] = unique; + } + if (multiEntry != null) { + options['multiEntry'] = multiEntry; + } + + return _createIndex(name, keyPath, options); + } + + // To suppress missing implicit constructor warnings. + factory ObjectStore._() { + throw new UnsupportedError("Not supported"); + } + + final bool autoIncrement; + + @Returns('DomStringList|Null') + @Creates('DomStringList') + final List indexNames; + + @annotation_Creates_SerializedScriptValue + final Object keyPath; + + String name; + + final Transaction transaction; + + @Returns('Request') + @Creates('Request') + @_annotation_Creates_IDBKey + Request _add(/*any*/ value, [/*any*/ key]) { + if (key != null) { + var value_1 = convertDartToNative_SerializedScriptValue(value); + var key_2 = convertDartToNative_SerializedScriptValue(key); + return _add_1(value_1, key_2); + } + var value_1 = convertDartToNative_SerializedScriptValue(value); + return _add_2(value_1); + } + + @JSName('add') + @Returns('Request') + @Creates('Request') + @_annotation_Creates_IDBKey + Request _add_1(value, key) native; + @JSName('add') + @Returns('Request') + @Creates('Request') + @_annotation_Creates_IDBKey + Request _add_2(value) native; + + @JSName('clear') + Request _clear() native; + + @JSName('count') + Request _count(Object key) native; + + Index _createIndex(String name, Object keyPath, [Map options]) { + if (options != null) { + var options_1 = convertDartToNative_Dictionary(options); + return _createIndex_1(name, keyPath, options_1); + } + return _createIndex_2(name, keyPath); + } + + @JSName('createIndex') + Index _createIndex_1(name, keyPath, options) native; + @JSName('createIndex') + Index _createIndex_2(name, keyPath) native; + + @JSName('delete') + Request _delete(Object key) native; + + void deleteIndex(String name) native; + + @JSName('get') + @Returns('Request') + @Creates('Request') + @annotation_Creates_SerializedScriptValue + Request _get(Object key) native; + + Request getAll(Object query, [int count]) native; + + Request getAllKeys(Object query, [int count]) native; + + Request getKey(Object key) native; + + Index index(String name) native; + + @JSName('openCursor') + @Returns('Request') + @Creates('Request') + @Creates('Cursor') + Request _openCursor(Object range, [String direction]) native; + + Request openKeyCursor(Object range, [String direction]) native; + + @Returns('Request') + @Creates('Request') + @_annotation_Creates_IDBKey + Request _put(/*any*/ value, [/*any*/ key]) { + if (key != null) { + var value_1 = convertDartToNative_SerializedScriptValue(value); + var key_2 = convertDartToNative_SerializedScriptValue(key); + return _put_1(value_1, key_2); + } + var value_1 = convertDartToNative_SerializedScriptValue(value); + return _put_2(value_1); + } + + @JSName('put') + @Returns('Request') + @Creates('Request') + @_annotation_Creates_IDBKey + Request _put_1(value, key) native; + @JSName('put') + @Returns('Request') + @Creates('Request') + @_annotation_Creates_IDBKey + Request _put_2(value) native; + + /** + * Helper for iterating over cursors in a request. + */ + static Stream _cursorStreamFromResult( + Request request, bool autoAdvance) { + // TODO: need to guarantee that the controller provides the values + // immediately as waiting until the next tick will cause the transaction to + // close. + var controller = new StreamController(sync: true); + + //TODO: Report stacktrace once issue 4061 is resolved. + request.onError.listen(controller.addError); + + request.onSuccess.listen((e) { + T cursor = request.result as dynamic; + if (cursor == null) { + controller.close(); + } else { + controller.add(cursor); + if (autoAdvance == true && controller.hasListener) { + cursor.next(); + } + } + }); + return controller.stream; + } +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Native("IDBObservation") +class Observation extends Interceptor { + // To suppress missing implicit constructor warnings. + factory Observation._() { + throw new UnsupportedError("Not supported"); + } + + final Object key; + + final String type; + + final Object value; +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Native("IDBObserver") +class Observer extends Interceptor { + // To suppress missing implicit constructor warnings. + factory Observer._() { + throw new UnsupportedError("Not supported"); + } + + factory Observer(ObserverCallback callback) { + return Observer._create_1(callback); + } + static Observer _create_1(callback) => + JS('Observer', 'new IDBObserver(#)', callback); + + void observe(Database db, Transaction tx, Map options) { + var options_1 = convertDartToNative_Dictionary(options); + _observe_1(db, tx, options_1); + return; + } + + @JSName('observe') + void _observe_1(Database db, Transaction tx, options) native; + + void unobserve(Database db) native; +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Native("IDBObserverChanges") +class ObserverChanges extends Interceptor { + // To suppress missing implicit constructor warnings. + factory ObserverChanges._() { + throw new UnsupportedError("Not supported"); + } + + final Database database; + + final Object records; + + final Transaction transaction; +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBOpenDBRequest,IDBVersionChangeRequest") +class OpenDBRequest extends Request { + // To suppress missing implicit constructor warnings. + factory OpenDBRequest._() { + throw new UnsupportedError("Not supported"); + } + + /** + * Static factory designed to expose `blocked` events to event + * handlers that are not necessarily instances of [OpenDBRequest]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider blockedEvent = + const EventStreamProvider('blocked'); + + /** + * Static factory designed to expose `upgradeneeded` events to event + * handlers that are not necessarily instances of [OpenDBRequest]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider upgradeNeededEvent = + const EventStreamProvider('upgradeneeded'); + + /// Stream of `blocked` events handled by this [OpenDBRequest]. + Stream get onBlocked => blockedEvent.forTarget(this); + + /// Stream of `upgradeneeded` events handled by this [OpenDBRequest]. + Stream get onUpgradeNeeded => + upgradeNeededEvent.forTarget(this); +} +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBRequest") +class Request extends EventTarget { + // To suppress missing implicit constructor warnings. + factory Request._() { + throw new UnsupportedError("Not supported"); + } + + /** + * Static factory designed to expose `error` events to event + * handlers that are not necessarily instances of [Request]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider errorEvent = + const EventStreamProvider('error'); + + /** + * Static factory designed to expose `success` events to event + * handlers that are not necessarily instances of [Request]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider successEvent = + const EventStreamProvider('success'); + + final DomException error; + + final String readyState; + + dynamic get result => _convertNativeToDart_IDBAny(this._get_result); + @JSName('result') + @Creates('Null') + final dynamic _get_result; + + @Creates('Null') + final Object source; + + final Transaction transaction; + + /// Stream of `error` events handled by this [Request]. + Stream get onError => errorEvent.forTarget(this); + + /// Stream of `success` events handled by this [Request]. + Stream get onSuccess => successEvent.forTarget(this); +} +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBTransaction") +class Transaction extends EventTarget { + /** + * Provides a Future which will be completed once the transaction has + * completed. + * + * The future will error if an error occurrs on the transaction or if the + * transaction is aborted. + */ + Future get completed { + var completer = new Completer(); + + this.onComplete.first.then((_) { + completer.complete(db); + }); + + this.onError.first.then((e) { + completer.completeError(e); + }); + + this.onAbort.first.then((e) { + // Avoid completing twice if an error occurs. + if (!completer.isCompleted) { + completer.completeError(e); + } + }); + + return completer.future; + } + + // To suppress missing implicit constructor warnings. + factory Transaction._() { + throw new UnsupportedError("Not supported"); + } + + /** + * Static factory designed to expose `abort` events to event + * handlers that are not necessarily instances of [Transaction]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider abortEvent = + const EventStreamProvider('abort'); + + /** + * Static factory designed to expose `complete` events to event + * handlers that are not necessarily instances of [Transaction]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider completeEvent = + const EventStreamProvider('complete'); + + /** + * Static factory designed to expose `error` events to event + * handlers that are not necessarily instances of [Transaction]. + * + * See [EventStreamProvider] for usage information. + */ + static const EventStreamProvider errorEvent = + const EventStreamProvider('error'); + + final Database db; + + final DomException error; + + final String mode; + + @Returns('DomStringList|Null') + @Creates('DomStringList') + final List objectStoreNames; + + void abort() native; + + ObjectStore objectStore(String name) native; + + /// Stream of `abort` events handled by this [Transaction]. + Stream get onAbort => abortEvent.forTarget(this); + + /// Stream of `complete` events handled by this [Transaction]. + Stream get onComplete => completeEvent.forTarget(this); + + /// Stream of `error` events handled by this [Transaction]. + Stream get onError => errorEvent.forTarget(this); +} +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Unstable() +@Native("IDBVersionChangeEvent") +class VersionChangeEvent extends Event { + // To suppress missing implicit constructor warnings. + factory VersionChangeEvent._() { + throw new UnsupportedError("Not supported"); + } + + factory VersionChangeEvent(String type, [Map eventInitDict]) { + if (eventInitDict != null) { + var eventInitDict_1 = convertDartToNative_Dictionary(eventInitDict); + return VersionChangeEvent._create_1(type, eventInitDict_1); + } + return VersionChangeEvent._create_2(type); + } + static VersionChangeEvent _create_1(type, eventInitDict) => JS( + 'VersionChangeEvent', + 'new IDBVersionChangeEvent(#,#)', + type, + eventInitDict); + static VersionChangeEvent _create_2(type) => + JS('VersionChangeEvent', 'new IDBVersionChangeEvent(#)', type); + + final String dataLoss; + + final String dataLossMessage; + + @Creates('int|String|Null') + @Returns('int|String|Null') + final int newVersion; + + @Creates('int|String|Null') + @Returns('int|String|Null') + final int oldVersion; + + @JSName('target') + final OpenDBRequest target; +} +;<2O1=E!"5GG4.%!3*! !HJ:53 8 ) ?27#07C@ GJ,"@'ANN<>E$!8--"9-"9E?N3,H::P3>3>I 5QONPLQOQPG:0NOMA)/02%!='/:P;'7&M?;;NN< # +*. +/.( .81%"A#D#NN< '8 1E,,NN<;+2- %-.$!0.B5%N2PJ18@5%PJ1*F5%E-I5%+181?@671?@671?@671G@6LF!'??4':1.;;;;;;C4*NN<*8NN<+2- 'G"%!%6&:1F +(%9-(.N ++-8%" +7.M9#O81/5:Q+1+LB! 3NN< "& +*(. +(. +"(.H &CG 93 6FH  CG 96 9F81,!%,#48,&@CNN< %*;EGEG7?5/81,,50$A.ANN< ( +$(. +).# +9.& +*(. +$(. +(.HK:83=7!NOM&CG I+ 6:L"*181!!,!/FB%D% %C?7*7.&(,#48%#@B/FB%D% 5>+GP:;1#, = +NN<(81NN<%810))6;=# @&NN<,8 1!NN< 4&81AE693GE6LFB?H4*NN< $81??671A?693G!:;;AA>;NN< !)8#1A!KB/B( /F Zfile:///b/build/slave/dart-sdk-mac-stable/build/sdk/sdk/lib/html/dart2js/html_dart2js.dart/** + * HTML elements and other resources for web-based applications that need to + * interact with the browser and the DOM (Document Object Model). + * + * This library includes DOM element types, CSS styling, local storage, + * media, speech, events, and more. + * To get started, + * check out the [Element] class, the base class for many of the HTML + * DOM types. + * + * For information on writing web apps with Dart, see https://webdev.dartlang.org. + * + * {@category Web} + */ +library dart.dom.html; + +import 'dart:async'; +import 'dart:collection' hide LinkedList, LinkedListEntry; +import 'dart:_internal' hide Symbol; +import 'dart:html_common'; +import 'dart:indexed_db'; +import "dart:convert"; +import 'dart:math'; +import 'dart:_native_typed_data'; +import 'dart:typed_data'; +import 'dart:svg' as svg; +import 'dart:svg' show Matrix; +import 'dart:svg' show SvgSvgElement; +import 'dart:web_audio' as web_audio; +import 'dart:web_audio' show AudioBuffer, AudioTrack, AudioTrackList; +import 'dart:web_gl' as gl; +import 'dart:web_gl' show RenderingContext, RenderingContext2; +import 'dart:web_sql'; +import 'dart:_foreign_helper' show JS, JS_INTERCEPTOR_CONSTANT; +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// DO NOT EDIT - unless you are editing documentation as per: +// https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation +// Auto-generated dart:html library. + +// Not actually used, but imported since dart:html can generate these objects. +import 'dart:_js_helper' + show + convertDartClosureToJS, + Creates, + JavaScriptIndexingBehavior, + JSName, + Native, + Returns, + ForceInline, + findDispatchTagForInterceptorClass, + setNativeSubclassDispatchRecord, + makeLeafDispatchRecord, + registerGlobalObject, + applyExtension; +import 'dart:_interceptors' + show + Interceptor, + JavaScriptFunction, + JSExtendableArray, + JSUInt31, + findInterceptorConstructorForType, + findConstructorForNativeSubclassType, + getNativeInterceptor, + setDispatchProperty; + +export 'dart:math' show Rectangle, Point; + +/** + * Top-level container for a web page, which is usually a browser tab or window. + * + * Each web page loaded in the browser has its own [Window], which is a + * container for the web page. + * + * If the web page has any `