From 0c17e162c99fe3bb2cf506c25f733a331813dad8 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 20 Oct 2010 14:30:31 -0700 Subject: [PATCH 1/8] Refactored LayerPart validation - Log syntax errors on Warning level - Move the validation to the Driver --HG-- branch : dev --- .../Controllers/AdminController.cs | 31 +-------------- .../Drivers/LayerPartDriver.cs | 39 ++++++++++++++++++- .../Orchard.Widgets/Filters/WidgetFilter.cs | 5 +-- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs index 83da257c0..835c371c5 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs @@ -7,7 +7,6 @@ using Orchard.Core.Contents.Controllers; using Orchard.Localization; using Orchard.UI.Admin; using Orchard.UI.Notify; -using Orchard.UI.Widgets; using Orchard.Widgets.Models; using Orchard.Widgets.Services; using Orchard.Widgets.ViewModels; @@ -20,16 +19,13 @@ namespace Orchard.Widgets.Controllers { private const string NotAuthorizedManageWidgetsLabel = "Not authorized to manage widgets"; private readonly IWidgetsService _widgetsService; - private readonly IRuleManager _ruleManager; public AdminController( IOrchardServices services, - IWidgetsService widgetsService, - IRuleManager ruleManager) { + IWidgetsService widgetsService) { Services = services; _widgetsService = widgetsService; - _ruleManager = ruleManager; T = NullLocalizer.Instance; } @@ -179,8 +175,6 @@ namespace Orchard.Widgets.Controllers { var model = Services.ContentManager.UpdateEditor(layerPart, this); - ValidateLayer(layerPart); - if (!ModelState.IsValid) { Services.TransactionManager.Cancel(); return View(model); @@ -227,8 +221,6 @@ namespace Orchard.Widgets.Controllers { var model = Services.ContentManager.UpdateEditor(layerPart, this); - ValidateLayer(layerPart); - if (!ModelState.IsValid) { Services.TransactionManager.Cancel(); return View(model); @@ -339,27 +331,6 @@ namespace Orchard.Widgets.Controllers { RedirectToAction("Index"); } - public bool ValidateLayer(LayerPart layer) { - if ( String.IsNullOrWhiteSpace(layer.LayerRule) ) { - layer.LayerRule = "true"; - } - - if(_widgetsService.GetLayers().Count(l => String.Equals(l.Name, layer.Name, StringComparison.InvariantCultureIgnoreCase)) > 1) { // the current layer counts for 1 - ModelState.AddModelError("Name", T("A Layer with the same name already exists").Text); - return false; - } - - try { - _ruleManager.Matches(layer.LayerRule); - } - catch ( Exception e ) { - ModelState.AddModelError("Description", T("The rule is not valid: {0}", e.Message).Text); - return false; - } - - return true; - } - bool IUpdateModel.TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) { return base.TryUpdateModel(model, prefix, includeProperties, excludeProperties); } diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs index a37cfd2f6..e4d3c7b5d 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs @@ -1,12 +1,31 @@ -using JetBrains.Annotations; +using System; +using System.Linq; +using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; +using Orchard.Localization; +using Orchard.UI.Widgets; using Orchard.Widgets.Models; +using Orchard.Widgets.Services; namespace Orchard.Widgets.Drivers { [UsedImplicitly] public class LayerPartDriver : ContentPartDriver { + private readonly IRuleManager _ruleManager; + private readonly IWidgetsService _widgetsService; + + public LayerPartDriver( + IRuleManager ruleManager, + IWidgetsService widgetsService) { + + _ruleManager = ruleManager; + _widgetsService = widgetsService; + + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } protected override DriverResult Editor(LayerPart layerPart, dynamic shapeHelper) { return ContentShape("Parts_Widgets_LayerPart", @@ -14,7 +33,23 @@ namespace Orchard.Widgets.Drivers { } protected override DriverResult Editor(LayerPart layerPart, IUpdateModel updater, dynamic shapeHelper) { - updater.TryUpdateModel(layerPart, Prefix, null, null); + if(updater.TryUpdateModel(layerPart, Prefix, null, null)) { + if ( String.IsNullOrWhiteSpace(layerPart.LayerRule) ) { + layerPart.LayerRule = "true"; + } + + if ( _widgetsService.GetLayers().Any(l => String.Equals(l.Name, layerPart.Name, StringComparison.InvariantCultureIgnoreCase))) { + updater.AddModelError("Name", T("A Layer with the same name already exists")); + } + + try { + _ruleManager.Matches(layerPart.LayerRule); + } + catch ( Exception e ) { + updater.AddModelError("Description", T("The rule is not valid: {0}", e.Message)); + } + } + return Editor(layerPart, shapeHelper); } } diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs index bc0e46f69..b971b1659 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs @@ -47,9 +47,8 @@ namespace Orchard.Widgets.Filters { IEnumerable widgetParts = _contentManager.Query().List(); IEnumerable activeLayers = _contentManager.Query().List(); - List activeLayerIds = new List(); + var activeLayerIds = new List(); foreach (var activeLayer in activeLayers) { - var context = workContext.HttpContext; // ignore the rule if it fails to execute try { if (_ruleManager.Matches(activeLayer.Record.LayerRule)) { @@ -57,7 +56,7 @@ namespace Orchard.Widgets.Filters { } } catch(Exception e) { - Logger.Debug(e, T("An error occured during layer evaluation on: {0}", activeLayer.Name).Text); + Logger.Warning(e, T("An error occured during layer evaluation on: {0}", activeLayer.Name).Text); } } From cf68d0ba3374d26e0e372c9401f5c4d0e2a85fbf Mon Sep 17 00:00:00 2001 From: Andre Rodrigues Date: Mon, 8 Nov 2010 13:09:33 -0800 Subject: [PATCH 2/8] Medium Trust: Update YAML Serializer to avoid usage of SecurityCritical Marshal methods. --HG-- branch : dev --- lib/yaml/YamlSerializer.XML | 4048 +++++++++++++++++------------------ lib/yaml/YamlSerializer.dll | Bin 138752 -> 138752 bytes 2 files changed, 2024 insertions(+), 2024 deletions(-) diff --git a/lib/yaml/YamlSerializer.XML b/lib/yaml/YamlSerializer.XML index 5023c52ab..06d1a45d7 100644 --- a/lib/yaml/YamlSerializer.XML +++ b/lib/yaml/YamlSerializer.XML @@ -4,6 +4,2014 @@ YamlSerializer + + + Type 関連のユーティリティメソッド + + + + Type type; + AttributeType attr = type.GetAttribute<AttributeType>(); + + PropertyInfo propInfo; + AttributeType attr = propInfo.GetAttribute<AttributeType>(); + + string name; + Type type = TypeUtils.GetType(name); // search from all assembly loaded + + + + + + + + Type や PropertyInfo, FieldInfo から指定された型の属性を取り出して返す + 複数存在した場合には最後の値を返す + 存在しなければ null を返す + + 取り出したい属性の型 + 取り出した属性値 + + + + 現在ロードされているすべてのアセンブリから name という名の型を探して返す + + + + + + + Check if the type is a ValueType and does not contain any non ValueType members. + + + + + + + Returnes true if the specified is a struct type. + + to be analyzed. + true if the specified is a struct type; otehrwise false. + + + + Compare two objects to see if they are equal or not. Null is acceptable. + + + + + + + + Return if an object is a numeric value. + + Any object to be tested. + True if object is a numeric value. + + + + Cast an object to a specified numeric type. + + Any object + Numric type + Numeric value or null if the object is not a numeric value. + + + + Cast boxed numeric value to double + + boxed numeric value + Numeric value in double. Double.Nan if obj is not a numeric value. + + + + Check if type is fully public or not. + Nested class is checked if all declared types are public. + + + + + + + Equality comparer that uses Object.ReferenceEquals(x, y) to compare class values. + + + + + + Determines whether two objects of type T are equal by calling Object.ReferenceEquals(x, y). + + The first object to compare. + The second object to compare. + true if the specified objects are equal; otherwise, false. + + + + Serves as a hash function for the specified object for hashing algorithms and + data structures, such as a hash table. + + The object for which to get a hash code. + A hash code for the specified object. + is null. + + + + Returns a default equality comparer for the type specified by the generic argument. + + The default instance of the System.Collections.Generic.EqualityComparer<T> + class for type T. + + + + + object に代入されたクラスや構造体のメンバーに、リフレクションを + 解して簡単にアクセスできるようにしたクラス + + アクセス方法をキャッシュするので、繰り返し使用する場合に高速化が + 期待できる + + + + + Caches ObjectMemberAccessor instances for reuse. + + + + + + 指定した型へのアクセス方法を表すインスタンスを返す + キャッシュに存在すればそれを返す + キャッシュに存在しなければ新しく作って返す + 作った物はキャッシュされる + + クラスまたは構造体を表す型情報 + + + + + メンバ名と Accessor のペアを巡回する + + + + + + メンバへの読み書きを行うことができる + + オブジェクト + メンバの名前 + + + + + class has instance methods and , + with which C# native objects can be converted into / from YAML text without any preparations. + + var serializer = new YamlSerializer(); + object obj = GetObjectToSerialize(); + string yaml = serializer.Serialize(obj); + object restored = serializer.Deserialize(yaml); + Assert.AreEqual(obj, restored); + + + + +

What kind of objects can be serialized?

+ + can serialize / deserialize native C# objects of primitive types + (bool, char, int,...), enums, built-in non-primitive types (string, decimal), structures, + classes and arrays of these types. + + + On the other hand, it does not deal with IntPtr (which is a primitive type, though) and + pointer types (void*, int*, ...) because these types are, by their nature, not persistent. + + + + Classes without a default constructor can be deserialized only when the way of activating an instance + is explicitly specified by . + + + + object obj = new object[]{ + null, + "abc", + true, + 1, + (Byte)1, + 1.0, + "1", + new double[]{ 1.1, 2, -3 }, + new string[]{ "def", "ghi", "1" }, + new System.Drawing.Point(1,3), + new System.Drawing.SolidBrush(Color.Blue) + }; + + var serializer = new YamlSerializer(); + string yaml = serializer.Serialize(obj); + // %YAML 1.2 + // --- + // - null + // - abc + // - True + // - 1 + // - !System.Byte 1 + // - !!float 1 + // - "1" + // - !<!System.Double[]%gt; [1.1, 2, -3] + // - !<!System.String[]%gt; + // - def + // - ghi + // - !System.Drawing.Point 1, 3 + // - !System.Drawing.SolidBrush + // Color: Blue + // ... + + object restored; + try { + restored = YamlSerializer.Deserialize(yaml)[0]; + } catch(MissingMethodException) { + // default constructor is missing for SolidBrush + } + + // Let the library know how to activate an instance of SolidBrush. + YamlNode.DefaultConfig.AddActivator<System.Drawing.SolidBrush>( + () => new System.Drawing.SolidBrush(Color.Black /* dummy */)); + + // Then, all the objects can be restored correctly. + restored = serializer.Deserialize(yaml)[0]; + + + A YAML document generated by always have a %YAML directive and + explicit document start ("---") and end ("...") marks. + This allows several documents to be written in a single YAML stream. + + + var yaml = ""; + var serializer = new YamlSerializer(); + yaml += serializer.Serialize("a"); + yaml += serializer.Serialize(1); + yaml += serializer.Serialize(1.1); + // %YAML 1.2 + // --- + // a + // ... + // %YAML 1.2 + // --- + // 1 + // ... + // %YAML 1.2 + // --- + // 1.1 + // ... + + object[] objects = serializer.Deserialize(yaml); + // objects[0] == "a" + // objects[1] == 1 + // objects[2] == 1.1 + + + Since a YAML stream can consist of multiple YAML documents as above, + returns an array of . + + +

Serializing structures and classes

+ + For structures and classes, by default, all public fields and public properties are + serialized. Note that protected / private members are always ignored. + +

Serialization methods

+ + Readonly value-type members are also ignored because there is no way to + assign a new value to them on deserialization, while readonly class-type members + are serialized. When deserializing, instead of creating a new object and assigning it + to the member, the child members of such class instance are restored independently. + Such a deserializing method is refered to + YamlSerializeMethod.Content. + + + On the other hand, when writeable fields/properties are deserialized, new objects are + created by using the parameters in the YAML description and assiend to the fields/properties. + Such a deserializing method is refered to + YamlSerializeMethod.Assign. Writeable properties can be explicitly specified to use + YamlSerializeMethod.Content method for + deserialization, by adding to its definition. + + + Another type of serializing method is + YamlSerializeMethod.Binary. + This method is only applicable to an array-type field / property that contains + only value-type members. + + If serializing method is specified, + the member is never serialized nor deserialized. + + + public class Test1 + { + public int PublicProp { get; set; } // processed (by assign) + protected int ProtectedProp { get; set; } // Ignored + private int PrivateProp { get; set; } // Ignored + internal int InternalProp { get; set; } // Ignored + + public int PublicField; // processed (by assign) + protected int ProtectedField; // Ignored + private int PrivateField; // Ignored + internal int InternalField; // Ignored + + public List<string> ClassPropByAssign // processed (by assign) + { get; set; } + + public int ReadOnlyValueProp { get; private set; } // Ignored + public List<string> ReadOnlyClassProp // processed (by content) + { get; private set; } + + [YamlSerialize(YamlSerializeMethod.Content)] + public List<string> ClassPropByContent// processed (by content) + { get; set; } + + public int[] IntArrayField = // processed (by assign) + new int[10]; + + [YamlSerialize(YamlSerializeMethod.Binary)] + public int[] IntArrayFieldBinary = // processed (as binary) + new int[100]; + + [YamlSerialize(YamlSerializeMethod.Never)] + public int PublicPropHidden; // Ignored + + public Test1() + { + ClassPropByAssign = new List<string>(); + ReadOnlyClassProp = new List<string>(); + ClassPropByContent = new List<string>(); + } + } + + public void TestPropertiesAndFields1() + { + var test1 = new Test1(); + test1.ClassPropByAssign.Add("abc"); + test1.ReadOnlyClassProp.Add("def"); + test1.ClassPropByContent.Add("ghi"); + var rand = new Random(0); + for ( int i = 0; i < test1.IntArrayFieldBinary.Length; i++ ) + test1.IntArrayFieldBinary[i] = rand.Next(); + + var serializer = new YamlSerializer(); + string yaml = serializer.Serialize(test1); + // %YAML 1.2 + // --- + // !YamlSerializerTest.Test1 + // PublicProp: 0 + // ClassPropByAssign: + // Capacity: 4 + // ICollection.Items: + // - abc + // ReadOnlyClassProp: + // Capacity: 4 + // ICollection.Items: + // - def + // ClassPropByContent: + // Capacity: 4 + // ICollection.Items: + // - ghi + // PublicField: 0 + // IntArrayField: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + // IntArrayFieldBinary: |+2 + // Gor1XAwenmhGkU5ib9NxR11LXxp1iYlH5LH4c9hImTitWSB9Z78II2UvXSXV99A79fj6UBn3GDzbIbd9 + // yBDjAyslYm58iGd/NN+tVjuLRCg3cJBo+PWMbIWm9n4AEC0E7LKXWV5HXUNk7I13APEDWFMM/kWTz2EK + // s7LzFw2gBjpKugkmQJqIfinpQ1J1yqhhz/XjA3TBxDBsEuwrD+SNevQSqEC+/KRbwgE6D011ACMeyRt0 + // BOG6ZesRKCtL0YU6tSnLEpgKVBz+R300qD3/W0aZVk+1vHU+auzyGCGUaHCGd6dpRoEhXoIg2m3+AwJX + // EJ37T+TA9BuEPJtyGoq+crQMFQtXj1Zriz3HFbReclLvDdVpZlcOHPga/3+3Y509EHZ7UyT7H1xGeJxn + // eXPrDDb0Ul04MfZb4UYREOfR3HNzNTUYGRsIPUvHOEW7AaoplIfkVQp19DvGBrBqlP2TZ9atlWUHVdth + // 7lIBeIh0wiXxoOpCbQ7qVP9GkioQUrMkOcAJaad3exyZaOsXxznFCA== + // ... + } + + +

Default values of fields and properties

+ + is aware of + System.ComponentModel.DefaultValueAttribute. + So, when a member of a structure / class instance has a value that equals to the default value, + the member will not be written in the YAML text. + + It also checkes for the result of ShouldSerializeXXX method. For instance, just before serializing Font + property of some type, bool ShouldSerializeFont() method is called if exists. If the method returns false, + Font property will not be written in the YAML text. ShouldSerializeXXX method can be non-public. + + + using System.ComponentModel; + + public class Test2 + { + [DefaultValue(0)] + public int Default0 = 0; + + [DefaultValue("a")] + public string Defaulta = "a"; + + public int DynamicDefault = 0; + + bool ShouldSerializeDynamicDefault() + { + return Default0 != DynamicDefault; + } + } + + public void TestDefaultValue() + { + var test2 = new Test2(); + var serializer = new YamlSerializer(); + + // All properties have defalut values. + var yaml = serializer.Serialize(test2); + // %YAML 1.2 + // --- + // !YamlSerializerTest.Test2 {} + // ... + + test2.Defaulta = "b"; + yaml = serializer.Serialize(test2); + // %YAML 1.2 + // --- + // !YamlSerializerTest.Test2 + // Defaulta: b + // ... + + test2.Defaulta = "a"; + var yaml = serializer.Serialize(test2); + // %YAML 1.2 + // --- + // !YamlSerializerTest.Test2 {} + // ... + + test2.DynamicDefault = 1; + yaml = serializer.Serialize(test2); + // %YAML 1.2 + // --- + // !YamlSerializerTest.Test2 + // DynamicDefault: 1 + // ... + + test2.Default0 = 1; + yaml = serializer.Serialize(test2); + // %YAML 1.2 + // --- + // !YamlSerializerTest.Test2 + // Default0: 1 + // ... + } + + +

Collection classes

+ + If an object implements , or + the child objects are serialized as well its other public members. + Pseudproperty ICollection.Items or IDictionary.Entries appears to hold the child objects. + +

Multitime appearance of a same object

+ + preserve C# objects' graph structure. Namely, when a same objects are refered to + from several points in the object graph, the structure is correctly described in YAML text and restored objects + preserve the structure. can safely manipulate directly / indirectly self refering + objects, too. + + + public class TestClass + { + public List<TestClass> list = + new List<TestClass>(); + } + + public class ChildClass: TestClass + { + } + + void RecursiveObjectsTest() + { + var a = new TestClass(); + var b = new ChildClass(); + a.list.Add(a); + a.list.Add(a); + a.list.Add(b); + a.list.Add(a); + a.list.Add(b); + b.list.Add(a); + var serializer = new YamlSerializer(); + string yaml = serializer.Serialize(a); + // %YAML 1.2 + // --- + // &A !TestClass + // list: + // Capacity: 8 + // ICollection.Items: + // - *A + // - *A + // - &B !ChildClass + // list: + // Capacity: 4 + // ICollection.Items: + // - *A + // - *A + // - *B + // ... + + var restored = (TestClass)serializer.Deserialize(yaml)[0]; + Assert.IsTrue(restored == restored.list[0]); + Assert.IsTrue(restored == restored.list[1]); + Assert.IsTrue(restored == restored.list[3]); + Assert.IsTrue(restored == restored.list[5]); + Assert.IsTrue(restored.list[2] == restored.list[4]); + } + + + This is not the case if the object is . Same instances of + are repeatedly written in a YAML text and restored as different + instance of when deserialized, unless the content of the string + is extremely long (longer than 999 chars). + + + // 1000 chars + string long_str = + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"; + string short_str = "12345"; + object obj = new object[] { long_str, long_str, short_str, short_str }; + var serializer = new YamlSerializer(); + string yaml = serializer.Serialize(obj); + // %YAML 1.2 + // --- + // - &A 01234567890123456789012345678901234567890123456789 ... (snip) ... 789 + // - *A + // - "12345" + // - "12345" + // ... + + +

YAML text written / read by

+ + When serializing, intelligently uses various YAML 1.2 styles, + namely the block style, flow style, explicit mapping and implicit mapping, to maximize readability + of the YAML stream. + + + [Flags] + enum TestEnum: uint + { + abc = 1, + あいう = 2 + } + + public void TestVariousFormats() + { + var dict = new Dictionary<object, object>(); + dict.Add(new object[] { 1, "a" }, new object()); + object obj = new object[]{ + dict, + null, + "abc", + "1", + "a ", + "- a", + "abc\n", + "abc\ndef\n", + "abc\ndef\nghi", + new double[]{ 1.1, 2, -3, 3.12, 13.2 }, + new int[,] { { 1, 3}, {4, 5}, {10, 1} }, + new string[]{ "jkl", "mno\npqr" }, + new System.Drawing.Point(1,3), + TestEnum.abc, + TestEnum.abc | TestEnum.あいう, + }; + var config = new YamlConfig(); + config.ExplicitlyPreserveLineBreaks = false; + var serializer = new YamlSerializer(config); + string yaml = serializer.Serialize(obj); + + // %YAML 1.2 + // --- + // - !<!System.Collections.Generic.Dictionary%602[[System.Object,...],[System.Object,...]]> + // Keys: {} + // Values: {} + // IDictionary.Entries: + // ? - 1 + // - a + // : !System.Object {} + // - null + // - abc + // - "1" + // - "a " + // - "- a" + // - "abc\n" + // - |+2 + // abc + // def + // - |-2 + // abc + // def + // ghi + // - !<!System.Double[]> [1.1, 2, -3, 3.12, 13.2] + // - !<!System.Int32[,]> [[1, 3], [4, 5], [10, 1]] + // - !<!System.String[]> + // - jkl + // - |-2 + // mno + // pqr + // - !System.Drawing.Point 1, 3 + // - !TestEnum abc + // - !TestEnum abc, あいう + // ... + } + + + When deserializing, accepts any valid YAML 1.2 documents. + TAG directives, comments, flow / block styles, implicit / explicit mappings can be freely used + to express valid C# objects. Namely, the members of the array can be given eighter in a flow style + or in a block style. + + + By default, outputs a YAML stream with line break of "\r\n". + This can be customized either by setting YamlNode.DefaultConfig.LineBreakForOutput or + by giving an instance of to the + constructor. + + + + var serializer = new YamlSerializer(); + var yaml = serializer.Serialize("abc"); + // %YAML 1.2\r\n // line breaks are explicitly shown in this example + // ---\r\n + // abc\r\n + // ...\r\n + + var config = new YamlConfig(); + config.LineBreakForOutput = "\n"; + serializer = new YamlSerializer(config); + var yaml = serializer.Serialize("abc"); + // %YAML 1.2\n + // ---\n + // abc\n + // ...\n + + YamlNode.DefaultConfig.LineBreakForOutput = "\n"; + + var serializer = new YamlSerializer(); + serializer = new YamlSerializer(); + var yaml = serializer.Serialize("abc"); + // %YAML 1.2\n + // ---\n + // abc\n + // ...\n + + +

Line breaks in YAML text

+ + By default, line breaks in multi line values are explicitly presented as escaped style. + Although, this makes the resulting YAML stream hard to read, it is necessary to preserve + the exact content of the string because the YAML specification requires that a YAML parser + must normalize evely line break that is not escaped in a YAML document to be a single line + feed "\n" when deserializing. + + In order to have the YAML documents easy to be read, set + YamlConfig.ExplicitlyPreserveLineBreaks + false. Then, the multiline values of will be written in literal style. + + Of course, it makes all the line breaks to be normalized into a single line feeds "\n". + + + var serializer = new YamlSerializer(); + var text = "abc\r\n def\r\nghi\r\n"; + // abc + // def + // ghi + + // By default, line breaks explicitly appears in escaped form. + var yaml = serializer.Serialize(text); + // %YAML 1.2 + // --- + // "abc\r\n\ + // \ def\r\n\ + // ghi\r\n" + // ... + + // Original line breaks are preserved + var restored = (string)serializer.Deserialize(yaml)[0]; + // "abc\r\n def\r\nghi\r\n" + + + YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false; + + // Literal style is easier to be read. + var yaml = serializer.Serialize(text); + // %YAML 1.2 + // --- + // |+2 + // abc + // def + // ghi + // ... + + // Original line breaks are lost. + var restored = (string)serializer.Deserialize(yaml)[0]; + // "abc\n def\nghi\n" + + + This library offers two work arounds for this problem, although both of which + violates the official behavior of a YAML parser defined in the YAML specification. + + One is to set YamlConfig.LineBreakForInput + to be "\r\n". Then, the YAML parser normalizes all line breaks into "\r\n" instead of "\n". + + The other is to set YamlConfig.NormalizeLineBreaks + false. It disables the line break normalization both at output and at input. Namely, the line breaks are + written and read as-is when serialized / deserialized. + + + var serializer = new YamlSerializer(); + + // text with mixed line breaks + var text = "abc\r def\nghi\r\n"; + // abc\r // line breaks are explicitly shown in this example + // def\n + // ghi\r\n + + YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false; + + // By default, all line breaks are normalized to "\r\n" when serialized. + var yaml = serializer.Serialize(text); + // %YAML 1.2\r\n + // ---\r\n + // |+2\r\n + // abc\r\n + // def\r\n + // ghi\r\n + // ...\r\n + + // When deserialized, line breaks are normalized into "\n". + var restored = (string)serializer.Deserialize(yaml)[0]; + // "abc\n def\nghi\n" + + // Line breaks are normalized into "\r\n" instead of "\n". + YamlNode.DefaultConfig.LineBreakForInput = "\r\n"; + restored = (string)serializer.Deserialize(yaml)[0]; + // "abc\r\n def\r\nghi\r\n" + + // Line breaks are written as is, + YamlNode.DefaultConfig.NormalizeLineBreaks = false; + var yaml = serializer.Serialize(text); + // %YAML 1.2\r\n + // ---\r\n + // |+2\r\n + // abc\r + // def\n + // ghi\r\n + // ...\r\n + + // and are read as is. + restored = (string)serializer.Deserialize(yaml)[0]; + // "abc\r def\nghi\r\n" + + // Note that when the line breaks of YAML stream is changed + // between serialization and deserialization, the original + // line breaks are lost. + yaml = yaml.Replace("\r\n", "\n").Replace("\r", "\n"); + restored = (string)serializer.Deserialize(yaml)[0]; + // "abc\n def\nghi\n" + + + It is repeatedly stated that although these two options are useful in many situation, + they makes the YAML parser violate the YAML specification. + +
+
+ + + Initialize an instance of that obeys + . + + + + + Initialize an instance of with custom . + + Custom to customize serialization. + + + + Serialize C# object into YAML text. + + Object to be serialized. + YAML text. + + + + Serialize C# object into YAML text and write it into a . + + A to which the YAML text is written. + Object to be serialized. + + + + Serialize C# object into YAML text and write it into a . + + A to which the YAML text is written. + Object to be serialized. + + + + Serialize C# object into YAML text and save it into a file named as . + + A file name to which the YAML text is written. + Object to be serialized. + + + + Deserialize C# object(s) from a YAML text. Since a YAML text can contain multiple YAML documents, each of which + represents a C# object, the result is returned as an array of . + + A YAML text from which C# objects are deserialized. + Expected type(s) of the root object(s) in the YAML stream. + C# object(s) deserialized from YAML text. + + + + Deserialize C# object(s) from a YAML text in a . + Since a YAML text can contain multiple YAML documents, each of which + represents a C# object, the result is returned as an array of . + + A that contains YAML text from which C# objects are deserialized. + Expected type(s) of the root object(s) in the YAML stream. + C# object(s) deserialized from YAML text. + + + + Deserialize C# object(s) from a YAML text in a . + Since a YAML text can contain multiple YAML documents, each of which + represents a C# object, the result is returned as an array of . + + A that contains YAML text from which C# objects are deserialized. + Expected type(s) of the root object(s) in the YAML stream. + C# object(s) deserialized from YAML text. + + + + Deserialize C# object(s) from a YAML text in a file named as . + Since a YAML text can contain multiple YAML documents, each of which + represents a C# object, the result is returned as an array of . + + The name of a file that contains YAML text from which C# objects are deserialized. + Expected type(s) of the root object(s) in the YAML stream. + C# object(s) deserialized from YAML text. + + + + Add .DoFunction method to string + + + + + Short expression of string.Format(XXX, arg1, arg2, ...) + + + + + + + + Specify the way to store a property or field of some class or structure. + See for detail. + + + + + + + The property / field will not be stored. + + + + + When restored, new object is created by using the parameters in + the YAML data and assigned to the property / field. When the + property / filed is writeable, this is the default. + + + + + Only valid for a property / field that has a class or struct type. + When restored, instead of recreating the whole class or struct, + the members are independently restored. When the property / field + is not writeable this is the default. + + + + + Only valid for a property / field that has an array type of a + some value type. The content of the array is stored in a binary + format encoded in base64 style. + + + + + Specify the way to store a property or field of some class or structure. + + See for detail. + + + + + + + Specify the way to store a property or field of some class or structure. + + See for detail. + + + + + + - Never: The property / field will not be stored. + + + - Assign: When restored, new object is created by using the parameters in + the YAML data and assigned to the property / field. When the + property / filed is writeable, this is the default. + + + - Content: Only valid for a property / field that has a class or struct type. + When restored, instead of recreating the whole class or struct, + the members are independently restored. When the property / field + is not writeable this is the default. + + + - Binary: Only valid for a property / field that has an array type of a + some value type. The content of the array is stored in a binary + format encoded in base64 style. + + + + + + Converts C# object to YamlNode + + + + object obj; + YamlNode node = YamlRepresenter.ObjectToNode(obj); + + + + + + Implements utility functions to instantiating YamlNode's + + + + var node_tree = seq( + str("abc"), + str("def"), + map( + str("key"), str("value"), + str("key2"), seq( str("value2a"), str("value2b") ) + ), + str("2"), // !!str + str("!!int", "2") + ); + + string yaml = node_tree.ToYaml(); + + // %YAML 1.2 + // --- + // - abc + // - def + // - key: value + // key2: [ value2a, value2b ] + // - "2" # !!str + // - 2 # !!int + // ... + + + + + + Create a scalar node. Tag is set to be "!!str". + + + + var node_tree = seq( + str("abc"), + str("def"), + map( + str("key"), str("value"), + str("key2"), seq( str("value2a"), str("value2b") ) + ), + str("2"), // !!str + str("!!int", "2") + ); + + string yaml = node_tree.ToYaml(); + + // %YAML 1.2 + // --- + // - abc + // - def + // - key: value + // key2: [ value2a, value2b ] + // - "2" # !!str + // - 2 # !!int + // ... + + + Value for the scalar node. + Created scalar node. + + + + Create a scalar node. + + Tag for the scalar node. + Value for the scalar node. + Created scalar node. + + + + Create a sequence node. Tag is set to be "!!seq". + + Child nodes. + Created sequence node. + + + + Create a sequence node. + + Child nodes. + Tag for the seuqnce. + Created sequence node. + + + + Create a mapping node. Tag is set to be "!!map". + + Sequential list of key/value pairs. + Created mapping node. + + + + Create a mapping node. + + Sequential list of key/value pairs. + Tag for the mapping. + Created mapping node. + + + + When reports syntax error by exception, this class is thrown. + + Sytax errors can also be reported by simply returing false with giving some warnings. + + + + + Initialize an instance of + + Error message. + + + + Base class to implement a parser class. + + It allows not very efficient but easy implementation of a text parser along + with a parameterized BNF productions. + + Parser specific state structure. + + + + Parse the using the + as the starting rule. + + Starting rule. + Text to be parsed. + + + + + Gets / sets source text to be parsed. + While parsing, this variable will not be changed. + The current position to be read by parser is represented by the field . + Namely, the next character to be read is text[p]. + + + + + The current reading position. + + The next character to be read by the parser is text[p]. + + Increase to reduce some part of source text . + + The current position is automatically reverted at rewinding. + + + Example to show how to reduce BNF reduction rule of ( "t" "e" "x" "t" ). + + return RewindUnless(()=> + text[p++] == 't' && + text[p++] == 'e' && + text[p++] == 'x' && + text[p++] == 't' + ); + + + + + + Use this variable to build some string data from source text. + + It will be automatically reverted at rewinding. + + + + + Individual-parser-specific state object. + + It will be automatically reverted at rewinding. + + If some action, in addition to simply restore the value of the state object, + is needed to recover the previous state, override + method. + + + + + Initialize , which represents line number to + start position of each line list. + + + + + Line number to start position list. + + + + + Reporting syntax error by throwing . + + template for the error message. + parameters if required + Because it throw exception, nothing will be returned in reality. + + + + Give warning if is true. + + By default, the warning will not be shown / stored to anywhere. + To show or log the warning, override . + + + + return + SomeObsoleteReductionRule() && + WarningIf( + context != Context.IndeedObsolete, + "Obsolete"); + + + If true, warning is given; otherwize do nothing. + template for the warning message. + parameters if required + Always true. + + + + Give warning if is false. + + By default, the warning will not be shown / stored to anywhere. + To show or log the warning, override . + + + + return + SomeObsoleteReductionRule() && + WarningUnless( + context != Context.NotObsolete, + "Obsolete"); + + + If false, warning is given; otherwize do nothing. + template for the warning message. + parameters if required + Always true. + + + + Give warning. + + By default, the warning will not be shown / stored to anywhere. + To show or log the warning, override . + + + + return + SomeObsoleteReductionRule() && + Warning("Obsolete"); + + + template for the warning message. + parameters if required + Always true. + + + + Invoked when warning was given while parsing. + + Override this method to display / store the warning. + + Warning message. + + + + Represents EBNF operator of "join", i.e. serial appearence of several rules. + + + This recoveres , , + when does not return true. + + If any specific operation is needed for rewinding, in addition to simply + recover the value of , override . + + If false is returned, the parser status is rewound. + true if returned true; otherwise false. + + name ::= first-name middle-name? last-name + + bool Name() + { + return RewindUnless(()=> + FirstName() && + Optional(MiddleName) && + LastName() + ); + } + + + + + + This method is called just after recovers . + Override it to do any additional operation for rewinding. + + + + + Represents EBNF operator of "*". + + Reduction rule to be repeated. + Always true. + + lines-or-empty ::= line* + + bool LinesOrEmpty() + { + return + Repeat(Line); + } + + + lines-or-empty ::= (text line-break)* + Note: Do not forget if several + rules are sequentially appears in operator. + + bool LinesOrEmpty() + { + return + Repeat(()=> + RewindUnless(()=> + Text() && + LineBreak() + ) + ); + } + + + + + + Represents EBNF operator of "+". + + Reduction rule to be repeated. + true if the rule matches; otherwise false. + + lines ::= line+ + + bool Lines() + { + return + Repeat(Line); + } + + + + lines ::= (text line-break)+ + + Note: Do not forget RewindUnless in Repeat operator. + + bool Lines() + { + return + Repeat(()=> + RewindUnless(()=> + Text() && + LineBreak() + ) + ); + } + + + + + + Represents n times repeatition. + + + four-lines ::= (text line-break){4} + + Note: Do not forget if several + rules are sequentially appears in operator. + + bool FourLines() + { + return + Repeat(4, ()=> + RewindUnless(()=> + Text() && + LineBreak() + ) + ); + } + + + Repetition count. + Reduction rule to be repeated. + true if the rule matches; otherwise false. + + + + Represents at least , at most times repeatition. + + + google ::= "g" "o"{2,100} "g" "l" "e" + Note: Do not forget if several + rules are sequentially appears in operator. + + bool Google() + { + return + RewindUnless(()=> + text[p++] == 'g' && + Repeat(2, 100, + RewindUnless(()=> + text[p++] == 'o' + ) + ) + text[p++] == 'g' && + text[p++] == 'l' && + text[p++] == 'e' + ); + } + + + Minimum repetition count. Negative value is treated as 0. + Maximum repetition count. Negative value is treated as positive infinity. + Reduction rule to be repeated. + true if the rule matches; otherwise false. + + + + Represents BNF operator "?". + + + file ::= header? body footer? + + Note: Do not forget if several + rules are sequentially appears in operator. + + bool File() + { + return + Optional(Header()) && + Body() && + Optional(Footer()); + } + + + Reduction rule that is optional. + Always true. + + + + Represents BNF operator "?" (WITH rewinding wrap). + + + file = header? body footer? + + Note: Do not forget if several + rules are sequentially appears in operator. + + bool File() + { + return + Optional(Header) && + Body() && + Optional(Footer); + } + + + Reduction rule that is optional. + Always true. + + + + Reduce one character if it is a member of the specified character set. + + Acceptable character set. + true if the rule matches; otherwise false. + + alpha ::= [A-Z][a-z]
+ num ::= [0-9]
+ alpha-num :: alpha | num
+ word ::= alpha ( alpha-num )*
+ + Func<char,bool> Alpha = Charset( c => + ( 'A' <= c && c <= 'Z' ) || + ( 'a' <= c && c <= 'z' ) + ); + Func<char,bool> Num = Charset( c => + '0' <= c && c <= '9' + ); + Func<char,bool> AlphaNum = Charset( c => + Alpha(c) || Num(c) + ); + bool Word() + { + return + Accept(Alpha) && + Repeat(AlphaNum); + // No need for RewindUnless + } + +
+
+ + + Accepts a character 'c'. + + It can be also represented by text[p++] == c wrapped by . + + The character to be accepted. + true if the rule matches; otherwise false. + + YMCA ::= "Y" "M" "C" "A" + + bool YMCA() + { + return + RewindUnless(()=> + Accept('Y') && + Accept('M') && + Accept('C') && + Accept('A') + ); + } + + -or- + + bool YMCA() + { + return + RewindUnless(()=> + text[p++] == 'Y' && + text[p++] == 'M' && + text[p++] == 'C' && + text[p++] == 'A' + ); + } + + + + + + Accepts a sequence of characters. + + Sequence of characters to be accepted. + true if the rule matches; otherwise false. + + YMCA ::= "Y" "M" "C" "A" + + bool YMCA() + { + return + Accept("YMCA"); + } + + + + + + Represents sequence of characters. + + Sequence of characters to be accepted. + true if the rule matches; otherwise false. + + + + Represents BNF operator of "*". + + Character set to be accepted. + Always true. + + + + Represents BNF operator of "+". + + Character set to be accepted. + true if the rule matches; otherwise false. + + + + Represents n times repetition of characters. + + Character set to be accepted. + Repetition count. + true if the rule matches; otherwise false. + + + + Represents at least min times, at most max times + repetition of characters. + + Character set to be accepted. + Minimum repetition count. Negative value is treated as 0. + Maximum repetition count. Negative value is treated as positive infinity. + true if the rule matches; otherwise false. + + + + Represents BNF operator "?". + + Character set to be accepted. + Always true. + + + + Builds a performance-optimized table-based character set definition from a simple + but slow comparison-based definition. + + By default, the character table size is 0x100, namely only the characters of [\0-\xff] are + judged by using a character table and others are by the as-given slow comparisn-based definitions. + + To have maximized performance, locate the comparison for non-table based judgement first + in the definition as the example below. + + Use form to explicitly + specify the table size. + + This sample shows how to build a character set delegate. + + static class YamlCharsets: Charsets + { + Func<char, bool> cPrintable; + Func<char, bool> sWhite; + + static YamlCharsets() + { + cPrintable = CacheResult(c => + /* ( 0x10000 < c && c < 0x110000 ) || */ + ( 0xe000 <= c && c <= 0xfffd ) || + ( 0xa0 <= c && c <= 0xd7ff ) || + ( c < 0x100 && ( // to improve performance + c == 0x85 || + ( 0x20 <= c && c <= 0x7e ) || + c == 0x0d || + c == 0x0a || + c == 0x09 + ) ) + ); + sWhite = CacheResult(c => + c < 0x100 && ( // to improve performance + c == '\t' || + c == ' ' + ) + ); + } + } + + A simple but slow comparison-based definition of the charsert. + A performance-optimized table-based delegate built from the given . + + + + Builds a performance-optimized table-based character set definition from a simple + but slow comparison-based definition. + + Characters out of the table are judged by the as-given slow comparisn-based + definitions. + + So, to have maximized performance, locate the comparison for non-table based + judgement first in the definition as the example below. + + This sample shows how to build a character set delegate. + + static class YamlCharsets: Charsets + { + Func<char, bool> cPrintable; + Func<char, bool> sWhite; + + static YamlCharsets() + { + cPrintable = CacheResult(c => + /* ( 0x10000 < c && c < 0x110000 ) || */ + ( 0xe000 <= c && c <= 0xfffd ) || + ( 0xa0 <= c && c <= 0xd7ff ) || + ( c < 0x100 && ( // to improve performance + c == 0x85 || + ( 0x20 <= c && c <= 0x7e ) || + c == 0x0d || + c == 0x0a || + c == 0x09 + ) ) + ); + sWhite = CacheResult(c => + c < 0x100 && ( // to improve performance + c == '\t' || + c == ' ' + ) + ); + } + } + + Character table size. + A simple but slow comparison-based definition of the charsert. + A performance-optimized table-based delegate built from the given . + + + + Saves a part of the source text that is reduced in the . + If the rule does not match, nothing happends. + + Reduction rule to match. + If the matches, + the part of the source text reduced in the is set; + otherwise String.Empty is set. + true if matches; otherwise false. + + + + Saves a part of the source text that is reduced in the + and append it to . + If the rule does not match, nothing happends. + + Reduction rule to match. + true if matches; otherwise false. + + + + Saves a part of the source text that is reduced in the . + If the rule does not match, nothing happends. + + Reduction rule to match. + If matches, this delegate is invoked + with the part of the source text that is reduced in the + as the parameter. Do any action in the delegate. + true if matches; otherwise false. + + + bool SomeRule() + { + return + Save(()=> SubRule(), s => MessageBox.Show(s)); + } + + + + + Execute some action. + + Action to be done. + Always true. + + + bool SomeRule() + { + return + SubRule() && + Action(()=> do_some_action()); + } + + + + + Report error by throwing when the does not match. + + Some reduction rule that must match. + Error message as template + Parameters for template + Always true; otherwise an exception thrown. + + + + Report error by throwing when the does not match. + + Some reduction rule that must match. + Error message as template + Parameters for template + Always true; otherwise an exception is thrown. + + + + Report error by throwing when the does not match + and an additional condition is true. + + Some reduction rule that must match. + Additional condition: if this parameter is false, + rewinding occurs, instead of throwing exception. + Error message as template + Parameters for template + true if the reduction rule matches; otherwise false. + + + + Report error by throwing when is true. + + True to throw exception. + Error message as template + Parameters for template + Always true. + + + + Assign var = value and return true; + + Type of the variable and value. + Variable to be assigned. + Value to be assigned. + Always true. + + + + Get current position represented by raw and column. + + + + + Represents a position in a multiline text. + + + + + Raw in a text. + + + + + Column in a text. + + + + + Converts various types to / from string.
+ I don't remember why this class was needed.... +
+ + + object obj = GetObjectToConvert(); + + // Check if the type has [TypeConverter] attribute. + if( EasyTypeConverter.IsTypeConverterSpecified(type) ) { + + // Convert the object to string. + string s = EasyTypeConverter.ConvertToString(obj); + + // Convert the string to an object of the spific type. + object restored = EasyTypeConverter.ConvertFromString(s, type); + + Assert.AreEqual(obj, restored); + + } + + +
+ + + Construct YAML node tree that represents a given C# object. + + + + + Construct YAML node tree that represents a given C# object. + + to be converted to C# object. + to customize serialization. + + + + + Construct YAML node tree that represents a given C# object. + + to be converted to C# object. + Expected type for the root object. + to customize serialization. + + + + + Validates a text as a global tag in YAML. + + RFC4151 - The 'tag' URI Scheme> + + + + + Validates a text as a global tag in YAML. + + A candidate for a global tag in YAML. + True if is a valid global tag. + + + + Not used in this parser + + + + + A text parser for
+ YAML Ain’t Markup Language (YAML™) Version 1.2
+ 3rd Edition (2009-07-21)
+ http://yaml.org/spec/1.2/spec.html
+ + This class parse a YAML document and compose representing graph. +
+ + + string yaml = LoadYamlSource(); + YamlParser parser = new YamlParser(); + Node[] result = null; + try { + result = parser.Parse(yaml); + ... + // you can reuse parser as many times you want + ... + + } catch( ParseErrorException e ) { + MessageBox.Show(e.Message); + } + if(result != null) { + ... + + } + + + + Currently, this parser violates the YAML 1.2 specification in the following points. + - line breaks are not normalized. + - omission of the final line break is allowed in plain / literal / folded text. + - ':' followed by ns-indicator is excluded from ns-plain-char. + +
+ + + Initialize a YAML parser. + + + + + Parse YAML text and returns a list of . + + YAML text to be parsed. + A list of parsed from the given text + + + + Parse YAML text and returns a list of . + + YAML text to be parsed. + YAML Configuration to be used in parsing. + A list of parsed from the given text + + + + Add message in property. + + + + + + Invoked when unknown directive is found in YAML document. + + Name of the directive + Parameters for the directive + + + + Invoked when YAML directive is found in YAML document. + + Given version + + + + rewinding action + + + + + set status.tag with tag resolution + + + + + + + + set status.tag with verbatim tag value + + verbatim tag + + + + + Used when the parser resolves a tag for a scalar node from its value. + + New resolution rules can be add before calling method. + + + + + [105] + + + + + [106] + + + + + Warnings that are made while parsing a YAML text. + This property is cleared by new call for method. + + + + + additional fields to be rewound + + + + + tag for the next value (will be cleared when the next value is created) + + + + + anchor for the next value (will be cleared when the next value is created) + + + + + current value + + + + + anchor rewinding position + + + + + [22] + + + + + [23] + + + + + Reset(); + SetupDefaultTagPrefixes(); + Add(tag_handle, tag_prefix); + verbatim_tag = Resolve(tag_handle, tag_name); + + Configuration to customize YAML serialization. @@ -1504,1674 +3512,6 @@ The number of child nodes of the sequence. - - - Implements utility functions to instantiating YamlNode's - - - - var node_tree = seq( - str("abc"), - str("def"), - map( - str("key"), str("value"), - str("key2"), seq( str("value2a"), str("value2b") ) - ), - str("2"), // !!str - str("!!int", "2") - ); - - string yaml = node_tree.ToYaml(); - - // %YAML 1.2 - // --- - // - abc - // - def - // - key: value - // key2: [ value2a, value2b ] - // - "2" # !!str - // - 2 # !!int - // ... - - - - - - Create a scalar node. Tag is set to be "!!str". - - - - var node_tree = seq( - str("abc"), - str("def"), - map( - str("key"), str("value"), - str("key2"), seq( str("value2a"), str("value2b") ) - ), - str("2"), // !!str - str("!!int", "2") - ); - - string yaml = node_tree.ToYaml(); - - // %YAML 1.2 - // --- - // - abc - // - def - // - key: value - // key2: [ value2a, value2b ] - // - "2" # !!str - // - 2 # !!int - // ... - - - Value for the scalar node. - Created scalar node. - - - - Create a scalar node. - - Tag for the scalar node. - Value for the scalar node. - Created scalar node. - - - - Create a sequence node. Tag is set to be "!!seq". - - Child nodes. - Created sequence node. - - - - Create a sequence node. - - Child nodes. - Tag for the seuqnce. - Created sequence node. - - - - Create a mapping node. Tag is set to be "!!map". - - Sequential list of key/value pairs. - Created mapping node. - - - - Create a mapping node. - - Sequential list of key/value pairs. - Tag for the mapping. - Created mapping node. - - - - - object に代入されたクラスや構造体のメンバーに、リフレクションを - 解して簡単にアクセスできるようにしたクラス - - アクセス方法をキャッシュするので、繰り返し使用する場合に高速化が - 期待できる - - - - - Caches ObjectMemberAccessor instances for reuse. - - - - - - 指定した型へのアクセス方法を表すインスタンスを返す - キャッシュに存在すればそれを返す - キャッシュに存在しなければ新しく作って返す - 作った物はキャッシュされる - - クラスまたは構造体を表す型情報 - - - - - メンバ名と Accessor のペアを巡回する - - - - - - メンバへの読み書きを行うことができる - - オブジェクト - メンバの名前 - - - - - Validates a text as a global tag in YAML. - - RFC4151 - The 'tag' URI Scheme> - - - - - Base class to implement a parser class. - - It allows not very efficient but easy implementation of a text parser along - with a parameterized BNF productions. - - Parser specific state structure. - - - - Parse the using the - as the starting rule. - - Starting rule. - Text to be parsed. - - - - - Gets / sets source text to be parsed. - While parsing, this variable will not be changed. - The current position to be read by parser is represented by the field . - Namely, the next character to be read is text[p]. - - - - - The current reading position. - - The next character to be read by the parser is text[p]. - - Increase to reduce some part of source text . - - The current position is automatically reverted at rewinding. - - - Example to show how to reduce BNF reduction rule of ( "t" "e" "x" "t" ). - - return RewindUnless(()=> - text[p++] == 't' && - text[p++] == 'e' && - text[p++] == 'x' && - text[p++] == 't' - ); - - - - - - Use this variable to build some string data from source text. - - It will be automatically reverted at rewinding. - - - - - Individual-parser-specific state object. - - It will be automatically reverted at rewinding. - - If some action, in addition to simply restore the value of the state object, - is needed to recover the previous state, override - method. - - - - - Initialize , which represents line number to - start position of each line list. - - - - - Line number to start position list. - - - - - Reporting syntax error by throwing . - - template for the error message. - parameters if required - Because it throw exception, nothing will be returned in reality. - - - - Give warning if is true. - - By default, the warning will not be shown / stored to anywhere. - To show or log the warning, override . - - - - return - SomeObsoleteReductionRule() && - WarningIf( - context != Context.IndeedObsolete, - "Obsolete"); - - - If true, warning is given; otherwize do nothing. - template for the warning message. - parameters if required - Always true. - - - - Give warning if is false. - - By default, the warning will not be shown / stored to anywhere. - To show or log the warning, override . - - - - return - SomeObsoleteReductionRule() && - WarningUnless( - context != Context.NotObsolete, - "Obsolete"); - - - If false, warning is given; otherwize do nothing. - template for the warning message. - parameters if required - Always true. - - - - Give warning. - - By default, the warning will not be shown / stored to anywhere. - To show or log the warning, override . - - - - return - SomeObsoleteReductionRule() && - Warning("Obsolete"); - - - template for the warning message. - parameters if required - Always true. - - - - Invoked when warning was given while parsing. - - Override this method to display / store the warning. - - Warning message. - - - - Represents EBNF operator of "join", i.e. serial appearence of several rules. - - - This recoveres , , - when does not return true. - - If any specific operation is needed for rewinding, in addition to simply - recover the value of , override . - - If false is returned, the parser status is rewound. - true if returned true; otherwise false. - - name ::= first-name middle-name? last-name - - bool Name() - { - return RewindUnless(()=> - FirstName() && - Optional(MiddleName) && - LastName() - ); - } - - - - - - This method is called just after recovers . - Override it to do any additional operation for rewinding. - - - - - Represents EBNF operator of "*". - - Reduction rule to be repeated. - Always true. - - lines-or-empty ::= line* - - bool LinesOrEmpty() - { - return - Repeat(Line); - } - - - lines-or-empty ::= (text line-break)* - Note: Do not forget if several - rules are sequentially appears in operator. - - bool LinesOrEmpty() - { - return - Repeat(()=> - RewindUnless(()=> - Text() && - LineBreak() - ) - ); - } - - - - - - Represents EBNF operator of "+". - - Reduction rule to be repeated. - true if the rule matches; otherwise false. - - lines ::= line+ - - bool Lines() - { - return - Repeat(Line); - } - - - - lines ::= (text line-break)+ - - Note: Do not forget RewindUnless in Repeat operator. - - bool Lines() - { - return - Repeat(()=> - RewindUnless(()=> - Text() && - LineBreak() - ) - ); - } - - - - - - Represents n times repeatition. - - - four-lines ::= (text line-break){4} - - Note: Do not forget if several - rules are sequentially appears in operator. - - bool FourLines() - { - return - Repeat(4, ()=> - RewindUnless(()=> - Text() && - LineBreak() - ) - ); - } - - - Repetition count. - Reduction rule to be repeated. - true if the rule matches; otherwise false. - - - - Represents at least , at most times repeatition. - - - google ::= "g" "o"{2,100} "g" "l" "e" - Note: Do not forget if several - rules are sequentially appears in operator. - - bool Google() - { - return - RewindUnless(()=> - text[p++] == 'g' && - Repeat(2, 100, - RewindUnless(()=> - text[p++] == 'o' - ) - ) - text[p++] == 'g' && - text[p++] == 'l' && - text[p++] == 'e' - ); - } - - - Minimum repetition count. Negative value is treated as 0. - Maximum repetition count. Negative value is treated as positive infinity. - Reduction rule to be repeated. - true if the rule matches; otherwise false. - - - - Represents BNF operator "?". - - - file ::= header? body footer? - - Note: Do not forget if several - rules are sequentially appears in operator. - - bool File() - { - return - Optional(Header()) && - Body() && - Optional(Footer()); - } - - - Reduction rule that is optional. - Always true. - - - - Represents BNF operator "?" (WITH rewinding wrap). - - - file = header? body footer? - - Note: Do not forget if several - rules are sequentially appears in operator. - - bool File() - { - return - Optional(Header) && - Body() && - Optional(Footer); - } - - - Reduction rule that is optional. - Always true. - - - - Reduce one character if it is a member of the specified character set. - - Acceptable character set. - true if the rule matches; otherwise false. - - alpha ::= [A-Z][a-z]
- num ::= [0-9]
- alpha-num :: alpha | num
- word ::= alpha ( alpha-num )*
- - Func<char,bool> Alpha = Charset( c => - ( 'A' <= c && c <= 'Z' ) || - ( 'a' <= c && c <= 'z' ) - ); - Func<char,bool> Num = Charset( c => - '0' <= c && c <= '9' - ); - Func<char,bool> AlphaNum = Charset( c => - Alpha(c) || Num(c) - ); - bool Word() - { - return - Accept(Alpha) && - Repeat(AlphaNum); - // No need for RewindUnless - } - -
-
- - - Accepts a character 'c'. - - It can be also represented by text[p++] == c wrapped by . - - The character to be accepted. - true if the rule matches; otherwise false. - - YMCA ::= "Y" "M" "C" "A" - - bool YMCA() - { - return - RewindUnless(()=> - Accept('Y') && - Accept('M') && - Accept('C') && - Accept('A') - ); - } - - -or- - - bool YMCA() - { - return - RewindUnless(()=> - text[p++] == 'Y' && - text[p++] == 'M' && - text[p++] == 'C' && - text[p++] == 'A' - ); - } - - - - - - Accepts a sequence of characters. - - Sequence of characters to be accepted. - true if the rule matches; otherwise false. - - YMCA ::= "Y" "M" "C" "A" - - bool YMCA() - { - return - Accept("YMCA"); - } - - - - - - Represents sequence of characters. - - Sequence of characters to be accepted. - true if the rule matches; otherwise false. - - - - Represents BNF operator of "*". - - Character set to be accepted. - Always true. - - - - Represents BNF operator of "+". - - Character set to be accepted. - true if the rule matches; otherwise false. - - - - Represents n times repetition of characters. - - Character set to be accepted. - Repetition count. - true if the rule matches; otherwise false. - - - - Represents at least min times, at most max times - repetition of characters. - - Character set to be accepted. - Minimum repetition count. Negative value is treated as 0. - Maximum repetition count. Negative value is treated as positive infinity. - true if the rule matches; otherwise false. - - - - Represents BNF operator "?". - - Character set to be accepted. - Always true. - - - - Builds a performance-optimized table-based character set definition from a simple - but slow comparison-based definition. - - By default, the character table size is 0x100, namely only the characters of [\0-\xff] are - judged by using a character table and others are by the as-given slow comparisn-based definitions. - - To have maximized performance, locate the comparison for non-table based judgement first - in the definition as the example below. - - Use form to explicitly - specify the table size. - - This sample shows how to build a character set delegate. - - static class YamlCharsets: Charsets - { - Func<char, bool> cPrintable; - Func<char, bool> sWhite; - - static YamlCharsets() - { - cPrintable = CacheResult(c => - /* ( 0x10000 < c && c < 0x110000 ) || */ - ( 0xe000 <= c && c <= 0xfffd ) || - ( 0xa0 <= c && c <= 0xd7ff ) || - ( c < 0x100 && ( // to improve performance - c == 0x85 || - ( 0x20 <= c && c <= 0x7e ) || - c == 0x0d || - c == 0x0a || - c == 0x09 - ) ) - ); - sWhite = CacheResult(c => - c < 0x100 && ( // to improve performance - c == '\t' || - c == ' ' - ) - ); - } - } - - A simple but slow comparison-based definition of the charsert. - A performance-optimized table-based delegate built from the given . - - - - Builds a performance-optimized table-based character set definition from a simple - but slow comparison-based definition. - - Characters out of the table are judged by the as-given slow comparisn-based - definitions. - - So, to have maximized performance, locate the comparison for non-table based - judgement first in the definition as the example below. - - This sample shows how to build a character set delegate. - - static class YamlCharsets: Charsets - { - Func<char, bool> cPrintable; - Func<char, bool> sWhite; - - static YamlCharsets() - { - cPrintable = CacheResult(c => - /* ( 0x10000 < c && c < 0x110000 ) || */ - ( 0xe000 <= c && c <= 0xfffd ) || - ( 0xa0 <= c && c <= 0xd7ff ) || - ( c < 0x100 && ( // to improve performance - c == 0x85 || - ( 0x20 <= c && c <= 0x7e ) || - c == 0x0d || - c == 0x0a || - c == 0x09 - ) ) - ); - sWhite = CacheResult(c => - c < 0x100 && ( // to improve performance - c == '\t' || - c == ' ' - ) - ); - } - } - - Character table size. - A simple but slow comparison-based definition of the charsert. - A performance-optimized table-based delegate built from the given . - - - - Saves a part of the source text that is reduced in the . - If the rule does not match, nothing happends. - - Reduction rule to match. - If the matches, - the part of the source text reduced in the is set; - otherwise String.Empty is set. - true if matches; otherwise false. - - - - Saves a part of the source text that is reduced in the - and append it to . - If the rule does not match, nothing happends. - - Reduction rule to match. - true if matches; otherwise false. - - - - Saves a part of the source text that is reduced in the . - If the rule does not match, nothing happends. - - Reduction rule to match. - If matches, this delegate is invoked - with the part of the source text that is reduced in the - as the parameter. Do any action in the delegate. - true if matches; otherwise false. - - - bool SomeRule() - { - return - Save(()=> SubRule(), s => MessageBox.Show(s)); - } - - - - - Execute some action. - - Action to be done. - Always true. - - - bool SomeRule() - { - return - SubRule() && - Action(()=> do_some_action()); - } - - - - - Report error by throwing when the does not match. - - Some reduction rule that must match. - Error message as template - Parameters for template - Always true; otherwise an exception thrown. - - - - Report error by throwing when the does not match. - - Some reduction rule that must match. - Error message as template - Parameters for template - Always true; otherwise an exception is thrown. - - - - Report error by throwing when the does not match - and an additional condition is true. - - Some reduction rule that must match. - Additional condition: if this parameter is false, - rewinding occurs, instead of throwing exception. - Error message as template - Parameters for template - true if the reduction rule matches; otherwise false. - - - - Report error by throwing when is true. - - True to throw exception. - Error message as template - Parameters for template - Always true. - - - - Assign var = value and return true; - - Type of the variable and value. - Variable to be assigned. - Value to be assigned. - Always true. - - - - Get current position represented by raw and column. - - - - - Represents a position in a multiline text. - - - - - Raw in a text. - - - - - Column in a text. - - - - - Validates a text as a global tag in YAML. - - A candidate for a global tag in YAML. - True if is a valid global tag. - - - - Not used in this parser - - - - - Reset(); - SetupDefaultTagPrefixes(); - Add(tag_handle, tag_prefix); - verbatim_tag = Resolve(tag_handle, tag_name); - - - - - class has instance methods and , - with which C# native objects can be converted into / from YAML text without any preparations. - - var serializer = new YamlSerializer(); - object obj = GetObjectToSerialize(); - string yaml = serializer.Serialize(obj); - object restored = serializer.Deserialize(yaml); - Assert.AreEqual(obj, restored); - - - - -

What kind of objects can be serialized?

- - can serialize / deserialize native C# objects of primitive types - (bool, char, int,...), enums, built-in non-primitive types (string, decimal), structures, - classes and arrays of these types. - - - On the other hand, it does not deal with IntPtr (which is a primitive type, though) and - pointer types (void*, int*, ...) because these types are, by their nature, not persistent. - - - - Classes without a default constructor can be deserialized only when the way of activating an instance - is explicitly specified by . - - - - object obj = new object[]{ - null, - "abc", - true, - 1, - (Byte)1, - 1.0, - "1", - new double[]{ 1.1, 2, -3 }, - new string[]{ "def", "ghi", "1" }, - new System.Drawing.Point(1,3), - new System.Drawing.SolidBrush(Color.Blue) - }; - - var serializer = new YamlSerializer(); - string yaml = serializer.Serialize(obj); - // %YAML 1.2 - // --- - // - null - // - abc - // - True - // - 1 - // - !System.Byte 1 - // - !!float 1 - // - "1" - // - !<!System.Double[]%gt; [1.1, 2, -3] - // - !<!System.String[]%gt; - // - def - // - ghi - // - !System.Drawing.Point 1, 3 - // - !System.Drawing.SolidBrush - // Color: Blue - // ... - - object restored; - try { - restored = YamlSerializer.Deserialize(yaml)[0]; - } catch(MissingMethodException) { - // default constructor is missing for SolidBrush - } - - // Let the library know how to activate an instance of SolidBrush. - YamlNode.DefaultConfig.AddActivator<System.Drawing.SolidBrush>( - () => new System.Drawing.SolidBrush(Color.Black /* dummy */)); - - // Then, all the objects can be restored correctly. - restored = serializer.Deserialize(yaml)[0]; - - - A YAML document generated by always have a %YAML directive and - explicit document start ("---") and end ("...") marks. - This allows several documents to be written in a single YAML stream. - - - var yaml = ""; - var serializer = new YamlSerializer(); - yaml += serializer.Serialize("a"); - yaml += serializer.Serialize(1); - yaml += serializer.Serialize(1.1); - // %YAML 1.2 - // --- - // a - // ... - // %YAML 1.2 - // --- - // 1 - // ... - // %YAML 1.2 - // --- - // 1.1 - // ... - - object[] objects = serializer.Deserialize(yaml); - // objects[0] == "a" - // objects[1] == 1 - // objects[2] == 1.1 - - - Since a YAML stream can consist of multiple YAML documents as above, - returns an array of . - - -

Serializing structures and classes

- - For structures and classes, by default, all public fields and public properties are - serialized. Note that protected / private members are always ignored. - -

Serialization methods

- - Readonly value-type members are also ignored because there is no way to - assign a new value to them on deserialization, while readonly class-type members - are serialized. When deserializing, instead of creating a new object and assigning it - to the member, the child members of such class instance are restored independently. - Such a deserializing method is refered to - YamlSerializeMethod.Content. - - - On the other hand, when writeable fields/properties are deserialized, new objects are - created by using the parameters in the YAML description and assiend to the fields/properties. - Such a deserializing method is refered to - YamlSerializeMethod.Assign. Writeable properties can be explicitly specified to use - YamlSerializeMethod.Content method for - deserialization, by adding to its definition. - - - Another type of serializing method is - YamlSerializeMethod.Binary. - This method is only applicable to an array-type field / property that contains - only value-type members. - - If serializing method is specified, - the member is never serialized nor deserialized. - - - public class Test1 - { - public int PublicProp { get; set; } // processed (by assign) - protected int ProtectedProp { get; set; } // Ignored - private int PrivateProp { get; set; } // Ignored - internal int InternalProp { get; set; } // Ignored - - public int PublicField; // processed (by assign) - protected int ProtectedField; // Ignored - private int PrivateField; // Ignored - internal int InternalField; // Ignored - - public List<string> ClassPropByAssign // processed (by assign) - { get; set; } - - public int ReadOnlyValueProp { get; private set; } // Ignored - public List<string> ReadOnlyClassProp // processed (by content) - { get; private set; } - - [YamlSerialize(YamlSerializeMethod.Content)] - public List<string> ClassPropByContent// processed (by content) - { get; set; } - - public int[] IntArrayField = // processed (by assign) - new int[10]; - - [YamlSerialize(YamlSerializeMethod.Binary)] - public int[] IntArrayFieldBinary = // processed (as binary) - new int[100]; - - [YamlSerialize(YamlSerializeMethod.Never)] - public int PublicPropHidden; // Ignored - - public Test1() - { - ClassPropByAssign = new List<string>(); - ReadOnlyClassProp = new List<string>(); - ClassPropByContent = new List<string>(); - } - } - - public void TestPropertiesAndFields1() - { - var test1 = new Test1(); - test1.ClassPropByAssign.Add("abc"); - test1.ReadOnlyClassProp.Add("def"); - test1.ClassPropByContent.Add("ghi"); - var rand = new Random(0); - for ( int i = 0; i < test1.IntArrayFieldBinary.Length; i++ ) - test1.IntArrayFieldBinary[i] = rand.Next(); - - var serializer = new YamlSerializer(); - string yaml = serializer.Serialize(test1); - // %YAML 1.2 - // --- - // !YamlSerializerTest.Test1 - // PublicProp: 0 - // ClassPropByAssign: - // Capacity: 4 - // ICollection.Items: - // - abc - // ReadOnlyClassProp: - // Capacity: 4 - // ICollection.Items: - // - def - // ClassPropByContent: - // Capacity: 4 - // ICollection.Items: - // - ghi - // PublicField: 0 - // IntArrayField: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - // IntArrayFieldBinary: |+2 - // Gor1XAwenmhGkU5ib9NxR11LXxp1iYlH5LH4c9hImTitWSB9Z78II2UvXSXV99A79fj6UBn3GDzbIbd9 - // yBDjAyslYm58iGd/NN+tVjuLRCg3cJBo+PWMbIWm9n4AEC0E7LKXWV5HXUNk7I13APEDWFMM/kWTz2EK - // s7LzFw2gBjpKugkmQJqIfinpQ1J1yqhhz/XjA3TBxDBsEuwrD+SNevQSqEC+/KRbwgE6D011ACMeyRt0 - // BOG6ZesRKCtL0YU6tSnLEpgKVBz+R300qD3/W0aZVk+1vHU+auzyGCGUaHCGd6dpRoEhXoIg2m3+AwJX - // EJ37T+TA9BuEPJtyGoq+crQMFQtXj1Zriz3HFbReclLvDdVpZlcOHPga/3+3Y509EHZ7UyT7H1xGeJxn - // eXPrDDb0Ul04MfZb4UYREOfR3HNzNTUYGRsIPUvHOEW7AaoplIfkVQp19DvGBrBqlP2TZ9atlWUHVdth - // 7lIBeIh0wiXxoOpCbQ7qVP9GkioQUrMkOcAJaad3exyZaOsXxznFCA== - // ... - } - - -

Default values of fields and properties

- - is aware of - System.ComponentModel.DefaultValueAttribute. - So, when a member of a structure / class instance has a value that equals to the default value, - the member will not be written in the YAML text. - - It also checkes for the result of ShouldSerializeXXX method. For instance, just before serializing Font - property of some type, bool ShouldSerializeFont() method is called if exists. If the method returns false, - Font property will not be written in the YAML text. ShouldSerializeXXX method can be non-public. - - - using System.ComponentModel; - - public class Test2 - { - [DefaultValue(0)] - public int Default0 = 0; - - [DefaultValue("a")] - public string Defaulta = "a"; - - public int DynamicDefault = 0; - - bool ShouldSerializeDynamicDefault() - { - return Default0 != DynamicDefault; - } - } - - public void TestDefaultValue() - { - var test2 = new Test2(); - var serializer = new YamlSerializer(); - - // All properties have defalut values. - var yaml = serializer.Serialize(test2); - // %YAML 1.2 - // --- - // !YamlSerializerTest.Test2 {} - // ... - - test2.Defaulta = "b"; - yaml = serializer.Serialize(test2); - // %YAML 1.2 - // --- - // !YamlSerializerTest.Test2 - // Defaulta: b - // ... - - test2.Defaulta = "a"; - var yaml = serializer.Serialize(test2); - // %YAML 1.2 - // --- - // !YamlSerializerTest.Test2 {} - // ... - - test2.DynamicDefault = 1; - yaml = serializer.Serialize(test2); - // %YAML 1.2 - // --- - // !YamlSerializerTest.Test2 - // DynamicDefault: 1 - // ... - - test2.Default0 = 1; - yaml = serializer.Serialize(test2); - // %YAML 1.2 - // --- - // !YamlSerializerTest.Test2 - // Default0: 1 - // ... - } - - -

Collection classes

- - If an object implements , or - the child objects are serialized as well its other public members. - Pseudproperty ICollection.Items or IDictionary.Entries appears to hold the child objects. - -

Multitime appearance of a same object

- - preserve C# objects' graph structure. Namely, when a same objects are refered to - from several points in the object graph, the structure is correctly described in YAML text and restored objects - preserve the structure. can safely manipulate directly / indirectly self refering - objects, too. - - - public class TestClass - { - public List<TestClass> list = - new List<TestClass>(); - } - - public class ChildClass: TestClass - { - } - - void RecursiveObjectsTest() - { - var a = new TestClass(); - var b = new ChildClass(); - a.list.Add(a); - a.list.Add(a); - a.list.Add(b); - a.list.Add(a); - a.list.Add(b); - b.list.Add(a); - var serializer = new YamlSerializer(); - string yaml = serializer.Serialize(a); - // %YAML 1.2 - // --- - // &A !TestClass - // list: - // Capacity: 8 - // ICollection.Items: - // - *A - // - *A - // - &B !ChildClass - // list: - // Capacity: 4 - // ICollection.Items: - // - *A - // - *A - // - *B - // ... - - var restored = (TestClass)serializer.Deserialize(yaml)[0]; - Assert.IsTrue(restored == restored.list[0]); - Assert.IsTrue(restored == restored.list[1]); - Assert.IsTrue(restored == restored.list[3]); - Assert.IsTrue(restored == restored.list[5]); - Assert.IsTrue(restored.list[2] == restored.list[4]); - } - - - This is not the case if the object is . Same instances of - are repeatedly written in a YAML text and restored as different - instance of when deserialized, unless the content of the string - is extremely long (longer than 999 chars). - - - // 1000 chars - string long_str = - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"; - string short_str = "12345"; - object obj = new object[] { long_str, long_str, short_str, short_str }; - var serializer = new YamlSerializer(); - string yaml = serializer.Serialize(obj); - // %YAML 1.2 - // --- - // - &A 01234567890123456789012345678901234567890123456789 ... (snip) ... 789 - // - *A - // - "12345" - // - "12345" - // ... - - -

YAML text written / read by

- - When serializing, intelligently uses various YAML 1.2 styles, - namely the block style, flow style, explicit mapping and implicit mapping, to maximize readability - of the YAML stream. - - - [Flags] - enum TestEnum: uint - { - abc = 1, - あいう = 2 - } - - public void TestVariousFormats() - { - var dict = new Dictionary<object, object>(); - dict.Add(new object[] { 1, "a" }, new object()); - object obj = new object[]{ - dict, - null, - "abc", - "1", - "a ", - "- a", - "abc\n", - "abc\ndef\n", - "abc\ndef\nghi", - new double[]{ 1.1, 2, -3, 3.12, 13.2 }, - new int[,] { { 1, 3}, {4, 5}, {10, 1} }, - new string[]{ "jkl", "mno\npqr" }, - new System.Drawing.Point(1,3), - TestEnum.abc, - TestEnum.abc | TestEnum.あいう, - }; - var config = new YamlConfig(); - config.ExplicitlyPreserveLineBreaks = false; - var serializer = new YamlSerializer(config); - string yaml = serializer.Serialize(obj); - - // %YAML 1.2 - // --- - // - !<!System.Collections.Generic.Dictionary%602[[System.Object,...],[System.Object,...]]> - // Keys: {} - // Values: {} - // IDictionary.Entries: - // ? - 1 - // - a - // : !System.Object {} - // - null - // - abc - // - "1" - // - "a " - // - "- a" - // - "abc\n" - // - |+2 - // abc - // def - // - |-2 - // abc - // def - // ghi - // - !<!System.Double[]> [1.1, 2, -3, 3.12, 13.2] - // - !<!System.Int32[,]> [[1, 3], [4, 5], [10, 1]] - // - !<!System.String[]> - // - jkl - // - |-2 - // mno - // pqr - // - !System.Drawing.Point 1, 3 - // - !TestEnum abc - // - !TestEnum abc, あいう - // ... - } - - - When deserializing, accepts any valid YAML 1.2 documents. - TAG directives, comments, flow / block styles, implicit / explicit mappings can be freely used - to express valid C# objects. Namely, the members of the array can be given eighter in a flow style - or in a block style. - - - By default, outputs a YAML stream with line break of "\r\n". - This can be customized either by setting YamlNode.DefaultConfig.LineBreakForOutput or - by giving an instance of to the - constructor. - - - - var serializer = new YamlSerializer(); - var yaml = serializer.Serialize("abc"); - // %YAML 1.2\r\n // line breaks are explicitly shown in this example - // ---\r\n - // abc\r\n - // ...\r\n - - var config = new YamlConfig(); - config.LineBreakForOutput = "\n"; - serializer = new YamlSerializer(config); - var yaml = serializer.Serialize("abc"); - // %YAML 1.2\n - // ---\n - // abc\n - // ...\n - - YamlNode.DefaultConfig.LineBreakForOutput = "\n"; - - var serializer = new YamlSerializer(); - serializer = new YamlSerializer(); - var yaml = serializer.Serialize("abc"); - // %YAML 1.2\n - // ---\n - // abc\n - // ...\n - - -

Line breaks in YAML text

- - By default, line breaks in multi line values are explicitly presented as escaped style. - Although, this makes the resulting YAML stream hard to read, it is necessary to preserve - the exact content of the string because the YAML specification requires that a YAML parser - must normalize evely line break that is not escaped in a YAML document to be a single line - feed "\n" when deserializing. - - In order to have the YAML documents easy to be read, set - YamlConfig.ExplicitlyPreserveLineBreaks - false. Then, the multiline values of will be written in literal style. - - Of course, it makes all the line breaks to be normalized into a single line feeds "\n". - - - var serializer = new YamlSerializer(); - var text = "abc\r\n def\r\nghi\r\n"; - // abc - // def - // ghi - - // By default, line breaks explicitly appears in escaped form. - var yaml = serializer.Serialize(text); - // %YAML 1.2 - // --- - // "abc\r\n\ - // \ def\r\n\ - // ghi\r\n" - // ... - - // Original line breaks are preserved - var restored = (string)serializer.Deserialize(yaml)[0]; - // "abc\r\n def\r\nghi\r\n" - - - YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false; - - // Literal style is easier to be read. - var yaml = serializer.Serialize(text); - // %YAML 1.2 - // --- - // |+2 - // abc - // def - // ghi - // ... - - // Original line breaks are lost. - var restored = (string)serializer.Deserialize(yaml)[0]; - // "abc\n def\nghi\n" - - - This library offers two work arounds for this problem, although both of which - violates the official behavior of a YAML parser defined in the YAML specification. - - One is to set YamlConfig.LineBreakForInput - to be "\r\n". Then, the YAML parser normalizes all line breaks into "\r\n" instead of "\n". - - The other is to set YamlConfig.NormalizeLineBreaks - false. It disables the line break normalization both at output and at input. Namely, the line breaks are - written and read as-is when serialized / deserialized. - - - var serializer = new YamlSerializer(); - - // text with mixed line breaks - var text = "abc\r def\nghi\r\n"; - // abc\r // line breaks are explicitly shown in this example - // def\n - // ghi\r\n - - YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false; - - // By default, all line breaks are normalized to "\r\n" when serialized. - var yaml = serializer.Serialize(text); - // %YAML 1.2\r\n - // ---\r\n - // |+2\r\n - // abc\r\n - // def\r\n - // ghi\r\n - // ...\r\n - - // When deserialized, line breaks are normalized into "\n". - var restored = (string)serializer.Deserialize(yaml)[0]; - // "abc\n def\nghi\n" - - // Line breaks are normalized into "\r\n" instead of "\n". - YamlNode.DefaultConfig.LineBreakForInput = "\r\n"; - restored = (string)serializer.Deserialize(yaml)[0]; - // "abc\r\n def\r\nghi\r\n" - - // Line breaks are written as is, - YamlNode.DefaultConfig.NormalizeLineBreaks = false; - var yaml = serializer.Serialize(text); - // %YAML 1.2\r\n - // ---\r\n - // |+2\r\n - // abc\r - // def\n - // ghi\r\n - // ...\r\n - - // and are read as is. - restored = (string)serializer.Deserialize(yaml)[0]; - // "abc\r def\nghi\r\n" - - // Note that when the line breaks of YAML stream is changed - // between serialization and deserialization, the original - // line breaks are lost. - yaml = yaml.Replace("\r\n", "\n").Replace("\r", "\n"); - restored = (string)serializer.Deserialize(yaml)[0]; - // "abc\n def\nghi\n" - - - It is repeatedly stated that although these two options are useful in many situation, - they makes the YAML parser violate the YAML specification. - -
-
- - - Initialize an instance of that obeys - . - - - - - Initialize an instance of with custom . - - Custom to customize serialization. - - - - Serialize C# object into YAML text. - - Object to be serialized. - YAML text. - - - - Serialize C# object into YAML text and write it into a . - - A to which the YAML text is written. - Object to be serialized. - - - - Serialize C# object into YAML text and write it into a . - - A to which the YAML text is written. - Object to be serialized. - - - - Serialize C# object into YAML text and save it into a file named as . - - A file name to which the YAML text is written. - Object to be serialized. - - - - Deserialize C# object(s) from a YAML text. Since a YAML text can contain multiple YAML documents, each of which - represents a C# object, the result is returned as an array of . - - A YAML text from which C# objects are deserialized. - Expected type(s) of the root object(s) in the YAML stream. - C# object(s) deserialized from YAML text. - - - - Deserialize C# object(s) from a YAML text in a . - Since a YAML text can contain multiple YAML documents, each of which - represents a C# object, the result is returned as an array of . - - A that contains YAML text from which C# objects are deserialized. - Expected type(s) of the root object(s) in the YAML stream. - C# object(s) deserialized from YAML text. - - - - Deserialize C# object(s) from a YAML text in a . - Since a YAML text can contain multiple YAML documents, each of which - represents a C# object, the result is returned as an array of . - - A that contains YAML text from which C# objects are deserialized. - Expected type(s) of the root object(s) in the YAML stream. - C# object(s) deserialized from YAML text. - - - - Deserialize C# object(s) from a YAML text in a file named as . - Since a YAML text can contain multiple YAML documents, each of which - represents a C# object, the result is returned as an array of . - - The name of a file that contains YAML text from which C# objects are deserialized. - Expected type(s) of the root object(s) in the YAML stream. - C# object(s) deserialized from YAML text. - - - - Add .DoFunction method to string - - - - - Short expression of string.Format(XXX, arg1, arg2, ...) - - - - - - - - Specify the way to store a property or field of some class or structure. - See for detail. - - - - - - - The property / field will not be stored. - - - - - When restored, new object is created by using the parameters in - the YAML data and assigned to the property / field. When the - property / filed is writeable, this is the default. - - - - - Only valid for a property / field that has a class or struct type. - When restored, instead of recreating the whole class or struct, - the members are independently restored. When the property / field - is not writeable this is the default. - - - - - Only valid for a property / field that has an array type of a - some value type. The content of the array is stored in a binary - format encoded in base64 style. - - - - - Specify the way to store a property or field of some class or structure. - - See for detail. - - - - - - - Specify the way to store a property or field of some class or structure. - - See for detail. - - - - - - - Never: The property / field will not be stored. - - - - Assign: When restored, new object is created by using the parameters in - the YAML data and assigned to the property / field. When the - property / filed is writeable, this is the default. - - - - Content: Only valid for a property / field that has a class or struct type. - When restored, instead of recreating the whole class or struct, - the members are independently restored. When the property / field - is not writeable this is the default. - - - - Binary: Only valid for a property / field that has an array type of a - some value type. The content of the array is stored in a binary - format encoded in base64 style. - - - Represents the way to automatically resolve Tag from the Value of a YamlScalar. @@ -3248,6 +3588,22 @@ Decoded value. True if decoded successfully. + + + Converts YamlNode tree into yaml text. + + + + YamlNode node; + YamlPresenter.ToYaml(node); + + YamlNode node1; + YamlNode node2; + YamlNode node3; + YamlPresenter.ToYaml(node1, node2, node3); + + + Extend string object to have .DoubleQuoteEscape() / .DoubleQuoteUnescape(). @@ -3287,276 +3643,6 @@ Unescape control codes, double quotations, backslashes escape in the YAML double quoted string format - - - Type 関連のユーティリティメソッド - - - - Type type; - AttributeType attr = type.GetAttribute<AttributeType>(); - - PropertyInfo propInfo; - AttributeType attr = propInfo.GetAttribute<AttributeType>(); - - string name; - Type type = TypeUtils.GetType(name); // search from all assembly loaded - - - - - - - - Type や PropertyInfo, FieldInfo から指定された型の属性を取り出して返す - 複数存在した場合には最後の値を返す - 存在しなければ null を返す - - 取り出したい属性の型 - 取り出した属性値 - - - - 現在ロードされているすべてのアセンブリから name という名の型を探して返す - - - - - - - Check if the type is a ValueType and does not contain any non ValueType members. - - - - - - - Returnes true if the specified is a struct type. - - to be analyzed. - true if the specified is a struct type; otehrwise false. - - - - Compare two objects to see if they are equal or not. Null is acceptable. - - - - - - - - Return if an object is a numeric value. - - Any object to be tested. - True if object is a numeric value. - - - - Cast an object to a specified numeric type. - - Any object - Numric type - Numeric value or null if the object is not a numeric value. - - - - Cast boxed numeric value to double - - boxed numeric value - Numeric value in double. Double.Nan if obj is not a numeric value. - - - - Check if type is fully public or not. - Nested class is checked if all declared types are public. - - - - - - - Equality comparer that uses Object.ReferenceEquals(x, y) to compare class values. - - - - - - Determines whether two objects of type T are equal by calling Object.ReferenceEquals(x, y). - - The first object to compare. - The second object to compare. - true if the specified objects are equal; otherwise, false. - - - - Serves as a hash function for the specified object for hashing algorithms and - data structures, such as a hash table. - - The object for which to get a hash code. - A hash code for the specified object. - is null. - - - - Returns a default equality comparer for the type specified by the generic argument. - - The default instance of the System.Collections.Generic.EqualityComparer<T> - class for type T. - - - - A text parser for
- YAML Ain’t Markup Language (YAML™) Version 1.2
- 3rd Edition (2009-07-21)
- http://yaml.org/spec/1.2/spec.html
- - This class parse a YAML document and compose representing graph. -
- - - string yaml = LoadYamlSource(); - YamlParser parser = new YamlParser(); - Node[] result = null; - try { - result = parser.Parse(yaml); - ... - // you can reuse parser as many times you want - ... - - } catch( ParseErrorException e ) { - MessageBox.Show(e.Message); - } - if(result != null) { - ... - - } - - - - Currently, this parser violates the YAML 1.2 specification in the following points. - - line breaks are not normalized. - - omission of the final line break is allowed in plain / literal / folded text. - - ':' followed by ns-indicator is excluded from ns-plain-char. - -
- - - Initialize a YAML parser. - - - - - Parse YAML text and returns a list of . - - YAML text to be parsed. - A list of parsed from the given text - - - - Parse YAML text and returns a list of . - - YAML text to be parsed. - YAML Configuration to be used in parsing. - A list of parsed from the given text - - - - Add message in property. - - - - - - Invoked when unknown directive is found in YAML document. - - Name of the directive - Parameters for the directive - - - - Invoked when YAML directive is found in YAML document. - - Given version - - - - rewinding action - - - - - set status.tag with tag resolution - - - - - - - - set status.tag with verbatim tag value - - verbatim tag - - - - - Used when the parser resolves a tag for a scalar node from its value. - - New resolution rules can be add before calling method. - - - - - [105] - - - - - [106] - - - - - Warnings that are made while parsing a YAML text. - This property is cleared by new call for method. - - - - - additional fields to be rewound - - - - - tag for the next value (will be cleared when the next value is created) - - - - - anchor for the next value (will be cleared when the next value is created) - - - - - current value - - - - - anchor rewinding position - - - - - [22] - - - - - [23] - - Add string class two methods: .UriEscape(), .UriUnescape() @@ -3596,30 +3682,6 @@ NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&=$,\[\]]"); - - - When reports syntax error by exception, this class is thrown. - - Sytax errors can also be reported by simply returing false with giving some warnings. - - - - - Initialize an instance of - - Error message. - - - - Converts C# object to YamlNode - - - - object obj; - YamlNode node = YamlRepresenter.ObjectToNode(obj); - - - Dictionary that automatically rehash when the content of a key is changed. @@ -3688,67 +3750,5 @@ added to or removed from the dictionary. - - - Converts YamlNode tree into yaml text. - - - - YamlNode node; - YamlPresenter.ToYaml(node); - - YamlNode node1; - YamlNode node2; - YamlNode node3; - YamlPresenter.ToYaml(node1, node2, node3); - - - - - - Converts various types to / from string.
- I don't remember why this class was needed.... -
- - - object obj = GetObjectToConvert(); - - // Check if the type has [TypeConverter] attribute. - if( EasyTypeConverter.IsTypeConverterSpecified(type) ) { - - // Convert the object to string. - string s = EasyTypeConverter.ConvertToString(obj); - - // Convert the string to an object of the spific type. - object restored = EasyTypeConverter.ConvertFromString(s, type); - - Assert.AreEqual(obj, restored); - - } - - -
- - - Construct YAML node tree that represents a given C# object. - - - - - Construct YAML node tree that represents a given C# object. - - to be converted to C# object. - to customize serialization. - - - - - Construct YAML node tree that represents a given C# object. - - to be converted to C# object. - Expected type for the root object. - to customize serialization. - - diff --git a/lib/yaml/YamlSerializer.dll b/lib/yaml/YamlSerializer.dll index 2cc7ec2871247fae23b21649428d119e24f6c13b..74fec471071631880a7b11555250c3da80068888 100644 GIT binary patch literal 138752 zcmce92b>(mvG-oj?CjoLkoNAhdkSbz0v*GKlXM3{5=mg9$XLLMjL0Gk>>`X=?fL*4 z+gRX)v5gJJvcVbKIOmMhvn`whmT}JEIlt%UI2_v6mr2Dv`@WeUmt#SiwU-rfDBW$*7g;Y-UlU4BJ< z(gKIN!X>Vz&Q z^@U5neL|Gm<0-SOrz@LE4VhF5H~v}^2#+AJ0e4ErFoKkuzv!Nt0+1;9IjIfLNu}n? zU;A#OijoSz_vs98FsX0HOl%@=7noFUBKj`}M`F>1B#Zd53F5KqFS+r0#GgF~VUZ?f zwQ@&j0ADaxtJf|9KxBiADG!l+C*lT3KUTZsst|}GD`ZX)WyvhOBLMCAT|m9!N7+m& zoqB6`S8DryU8ydC{`;4~RZeOGWT4NPT|=qV;$UGasi9$25L{S`C*nw%iO&cjc$MN~zS~DmV2Kku{a8f8C_Ko{VV{ zvjv`RMv00bs^pT85wg+LU>U-`S3NXXjzG9KE}3cX8(>vOqx1vlquj#9t>%WNJs%pc zj{-hLkiY}sbUHU0n>)c2vwOn zvOk(%SV6Qm-&bCk?Y_tN!YZQ7&#Sump549Og~`6|?44JP|FBTXluk1tsVly6rh@XN zTTC_WKwTwAxH{n&Gsrqd0;PhL@wJc<`Q?mYg)4#Nd%MsXRo;VcMY^}^=qNsRgSYFL zIC6!z3++WQ$IkI~9T!JV_I7QIBS(0F#zL&0Ql$*#sG|!0N@on7y~daC4g7&U<|-mLjZ2w!5DzC3IM!j2V(%n zssQlH9gG1Ot7IbM?O+73SThrS-c`YBXkZ6HJ(-f|$b*hN=xA@~48OlW;hU;6RQ8Ni zZ%-zv5c2@_ah0D*D#ScMeGr&XhMhI*xq}x2e$PI)hG-4iL zguu2&fXaxVCRAb`V1%d%m6!(@0W6^s^MFLgp_Z$Bue8&IFhqWJsR{RITNyIp0lfE` za1HK3H28@I6HJ*m+Kv#GqZlk3|b<~P~ z)Bm^I?WT^(^_vvM1gJf~j(YK%l-*k5oq9J;6K%scZW9&nn|WQ+c`7PI<@!yQq4egK z4-J|Sb?8@f8Zq@1&~k_h^ld7t&5x~oWbJ3(H=4#T!OLl(j@%Hn>X%NkAXj0h5VpoN zenqtKRL0iZm>ZtP=(xH5Of-=YgS*yEI)x#K(+SkguSr(81GUoSdwF-K7j6RDC@gB@ zH%!V)k_B!tjo;1yKCl^-rNLE6p1<2O&)?4=AEk6>QM%J9-QX%OwZuuKP}-cSp8-%a z2MSfZGctr3Oo+1hgFX4d-nB1BDRMoz-h2G|H!*1Sb$d-Jt6NkSP6DrToksE@#Pll{ z*(7A>2eA3&>Z#q+-nTg5odZzMP_IQem)MIV+VdFe1Ln7hc|Kyj#?eHJe*s{bY%q!{ z&h-{12YYk9xt=?(IPAP9o_GRcN5k1*Uw*K^d|9q9*MHBTTmKH&4Q6tgoZDpWMM*9E%+hRY8kX6^(<4?G5{{t?KJn_OSfD)v^ zo>L{?&Mh*jFB!nmsp>z5NPXR=`A1-P3*qzv7;~fHbQ3dK3-5QEWT^@L>1F|u{&b~Z z0fpuQ#LFWZ%S$XBZbdGYUWE+{%%w18->clvpRQi$HI{>_FqTj2wC)r|ZIIXS#1XaY zP)Q5LFb%pn7g$$<;m({}aKo!KG^{LkpfD!9T44bODX+c(k(-pC;z<69460qFL~P-P z7oriQ!)riRU0ZusJLhyR9p{{mb50LCR+_Zt7c#$ecr9)^eLbSK#-y%Yq~d!y4@{W2 zGv^hef_TGGLA-?#J1@bm+o^pXJQOKFH}#AA47F;w=kI{A>I&-!HrXP&rCn4G(tCJ4 z;JawCbt=A(Ehxq>w_4B$dfZRg9;H(-!3{iAO;4t>HHm$0{ind{&2~50w6d9S8?$6% z%Sw|Ykyjbfh|IduV*^=@rUNu3Pmq;mcG~+{N1n-?0*$nWC?ppmFm={o5hU;?1vQNv zuBw#o1{-^L1BBw>$OI>R24fh*6pgV&Zzx^bk-%o`q{ACYGOj7%GZ{HcN5m-($n~25 znL--D0dKmmC|&@htpBH$Okvc^IRf*sK6wXl1PS_OT^f3A_zxU{ zk~r!haDelC;P7V>i;$k$FJU8s?=n-f3o{zq>3eE_Nx)A^z~Ov~@!LkCrzUutiG047lI#qgzsG>oQH6Xd`45Y&KsQZfXN~(q)XWJ1dcolZ{4iVX}k=H&K!fDv+Xh}Z73sUR1C?hH(SbxN2aH9DjkXf zyNdSi38TL5QYN?+vC3XghKAfYoT7T1>(P0-g5y}=%&z_7wv|QmIYod{;VdUisE_7i zg%3_`i;i1Gro>B3}M zN-*fsk`kPDU&wN;xQ^Gt*2$ZBPrG+JZuk-~+B*JP_0KtC12Kr^3S0g1d=y60&+?tZ zx6gV zmfd>R*Y7~ZcX1TR52ni#`9ZI|m%~NOq_~s1b1s4}4qparOpYc8FAQj5uF_mL^yj89YNYbi zUvLlj`1M!e+LP}sug(@vne@bltsKaBh=s34Qg|;eqvd`;!u#SlaeK3hJ^n~Wdb!vV zC$$#*F>3+;-=JZlxx_}TZSbXu*_6jRgyi_|rM`nY##9RJXeF}5Y*HHj1{AXgs+9)s zX4EPMFy)y4(OzJExAqUneV{vd4aoWioZx;6kNazJA9M%Y2DoBswiD5HpCPI%llg@c z7a0Vh79?JQM70MekY~CxC6|_bbLn=uK)Dcm(`L z=z(aJHQC1exa8HqxMJ4W`YijaGN$$iHZGAkqY|H)ZS<1*gQCHR2aiMno1qMKQ8!v8ULr_e{b+}aL297;JzCF z4kGOD{Rs0HtvBI&`U^NlULn{x@kjl2CXDvtKR}1-vGzimi|@2c5Lwj?5UzKqZ)nh6 z3oDoEuAW){ITSzWWx@x+UK%1gI%>0aFv=Ic0l+4O5YUk^h%)57Y3~;x7H>`;W0(SI z4A#+fTb68SUIS%w#hRL&+mRqTW9v|ziJI46j5^LrKgJ*`bGF2&;CtFR(v@Spcuoj>V$7YN_E)OPJt?8N1(IQ z3pOE}(Fp4yp?6@%0G3~rLi!5un7e~<8*R#~WBTZYZ%2y7a>I9!fyEk{BmJFB$4ZNA z!iO0_E}R3NgF7bM*zY(KOr4d-)!&8Gn=IzL5%vdCjr~AYU7)!k8j#C-kTzOg*a5Vt zB95ah$KPE#6bd5==BZ>Pv-$T@hSLCf9|9(LKdw&r0Rrza!3PP;H$TK%-E70;x@L9m51Tr4mILoHv^XCx41pYa=$&gz=3$5X%^-iVRxar{Y0FM?* z>z!&c`p4Q&z}iwhWe#5ekNI7g1bq>KLW%Q!uD_0k?)H-Y!b-5!9m2Z#J*L6x#)O8= zLbfxrO+vIuWVA_m+DgJNAt4X0VjiVX>M__S_~Z4NT=%aj$<3 zm*DHTv~y!#$Ah*ATFvVlNS~S4Hvt>}Nxp}&B+{`tTbRVgbmLo+uJ`=-_aGGKL}TDP zLYcmeWXeP~kcrq{x=BV9?K`+9L__67x`4s>E)qo=sV`UbvWz^xhXnE@0=Yca!3C}5 zzoUK?H^-IxVYi(zO_7EkejoA5e6vF82HlHQR6u?FY&Q8mv#6bkIVh#<7ohCYCxx#g z-67fK#!->b_j0&Q*e8>mJ?(;HQB^DP_&2PKmX{TjHWYS;ddYQ`Za3JX$NvB~+56TK zdg0>$M8$ll+}~O9P8O6*6jc3=wzG8Va9gfDAwuXVDN^YQUu4ySD!a$XPV}_S@`Emx zMTDXdte~k|s^F&96?qo(4uUQU68D%D;tfaB0$3GvX zq~nx_Iyki(R+Wb!B0bm|8z13h%mhD#a^sfX0)rm`Fb+q;k8yWIh>~gigpn6%f0{%Y z_h#GwDS$i=LW+#jBta%4^mlB=Jg-S2D0E>)$i0lP^n~TBVLcx80g~KyW8dj#K(7BB zmsl8hvv}0Rj?rmpUznTZ>c0fAM^{~fU>wl@iuAw6CHM_4@FZsSc#3~2J##XAI^l1T z#BE2%OnblUAdr5YPE}Dh%vdmQ5j(8*5pL;4a4WIPTI1<$*5%Xh0m_t?JK-M?Xpap4 zi5R**@)4Wisy8?IBfzDWTNzSt)i>#WH?YVs!D14l!N!6|9rxxT4CsZ@4MtXTO-=-o zL##UJHd>c(@FyfUS95-GOKXC&jquNaR5OO7nm1};f1xP1w9sXN@Ye)F$-@3d1nnE= zLMNlt2|eoEJ{eagh4Ak{^1}bZmB)Cz9;M9${|(4CR8<#F>ih%YY)L8dLZMhD_#dRK z=o5tQs2|c+V+?_>$`dzLNu4CYv%wxY&+~>%gN1X#e}WpRSMzq7D+qDgG=XQ-pTKR3 zMXaN#`%}~gX1b02ac>`$a>6bomd;9?o(f)o-1Ml_eTwdc21wP6BSk}hAP*_!-^cPO!3igdI*{{+Bc9<^ezpaDK$EXK=wx+Vz4L5tHN90Qw~+ zh|u?^vBnOwz*vX+LSL2m^H3^TtgrCbVMI$!54KPOw|e1TbsQ%1SJcKlY(@sYgx4Tk zuwlCWhHdyzz!%!^u?R1+;Y|oHw&8OSULxV?!6{~8bMgkdf*x?MoSQicEdmZ>@yT;d zPrD%FE$u1)%j?>1y;9q6TxxqpOYNYiDlW!QfC_qXDWH+cs(OiO_Sk}?y# z7`gl9b&mQ21^|cMF`1!s@G?m$I@{3cOeKdD1~Td3C6eH&Vr=QF<6dQ@Ckt3D!g9~L zt-YCUYv{=f=RqR6{)73{*jS=UFb<|u!w%{Ux^=7j)GkK-TW1@N8st@LJ9EA2Y|DZE zCbxZ@X>6O@KJYYlx!XR|G~Obzc4=&Xw|!)3Y+tv1RB3FH+di~4 z*5@WxyZf33`%+_v)bfw1{re!cc;rHKBwscHyppRcrA`}!bq?s0WL_NBlWgy#v(%`Z%>_QD|~ z!ga}h9N>6@-`9QT6*>3p!F1t{V<6OEU#>5oOW&94>s|XsbRq23<$*=Vq|TyxYQJM1 zQUQSBs2oJai1JfBtW zRVi`eacquEhTECI>dz`gwzW3O!6B4zDN?gRFM)lygd>QH zUv4l|DpUu3$My-uk#)=|H;B7^Tj=Z^a)RT5H z(vuVXdrij4XSL0x=>zvN)`U8c^KQt=A0`}kUV(M?vHfm3e_wfjj64Y46|R686Eg#k zcR!9+^n1brX)k1(TyY(*g~^+FBY_*1K{5XElJZ&Ym^L4w=4jUMhRdO}r(*IcJ3elJ zd>A8h@FY2R;jAq(2=)g3eU8dJ%DJTR+OlE;!4;M2QdC9S4IgtRbusK1=5p{0(k$0r zgeD}Llv>r7y48!))eGwTfIGyqX3+_UktJOEV`zRWkksQD40WRj4PlGpD~}yS9+RHKU=6sQ~FJ0}aJafYj~`6x6;o~KT&#Q!6Ff-Ba$|~nD=2G%H&91i`Cv6s zuztc|%oEJl7;Zp$n3xqSiiW@}-t3R+U21cgE@1KViD$`;HhY`94TaotVn~?J=I^F4Paj zP@!I9Oaqna1_v;Q`%FMi)x9D)s)JD(;0rCDFS4Oz_c70hV@{NgdfE_|Ry1JceP@gp z=Xfx4T*Dlh{~>Yy(9WBfKXP3uyqN1@QLZBYyJBuqs(*pv-JKMtnFgDY%*#xJO$nzK zuQA0HD*QYXycq;+2)sk-cS6KNBM~7QivFIMr4*?k#W*a&!8!J~0DsLNS%nhbG;Q=L6M6!-T7vl`K;pV6F<<(wO{&DaMq*xh z@&f;xR`=F^f<9n^e$2N}SNSIq;pkX|OQT#!z&_=s-WT<$)&>+rW|aVW;=Gw6NZ`R* zXt2p9WNO)NJ11_kf=%o2i0=I{9YF$DI##`D9TDMuAjTs|;EG56o7U4Jybs2B1PNU6 zSO+Fp$Cf2!xGE|`eLclIipg~>EdA!u5sRQtNBpe>o~;g*Po6I zc|_ms1iuQCj^?pKz5!^#$AQ*9uJjScRF|6~Io#%vlEuf679P%g8Wbu#LV}bed>Vtu z{c125>)_Pxg<|z=z>!Eq+Z3Xb6beQmzbIG&WVYGgGEX=~QGY0*{IKivFXws9p7Mk> zZk!0|xSQ3Kz)sVk4xR8Qh*Vu@0v5>$kCuW+N+CQ35%@aN+`H9h1ZuBEQ95=8j|I*s z)FkWDQH$r)e##=h9Ai-h+ljy36Vc$RY-*RKX<>YV`|daqU?Z+=$LKoPLhO`DMbAPw z9;oZ@Btq>dKOx*KR??Bjm)G72tXYY=v2+4>l}BoydU6cxhf1mUAW)$b zvW_eauqUV5W6qT>JkGb5X|Q|9;W*Pc1*MQVdAJr65u97XgG~upwVgV$9xPC=PVmK8 zoQCi$Br?zwL;c`cS)^d`?TPD7`m-n?L68tYPI&s>JkvOpGQA0v!^mljyaf?OwOhqr z@P$~6Az`X}wYQ`6^V;?QFAGTjU|T>voe&)>ZR<}Dn9l1;O4yZHCL^wOz12kQ|r<_ z6Jv`&_4rhBVq-4&7ORWA-PA8QC1m@brKIu%Mq2VLj)YRer*0lAxOcn2U(mClcR?S_ z`Aog9*zgWEPgqE>Eldui0xZ3}b*}=@8=1m&e7_{oLVG4-#l&_?vuG0j5Ykk(dLxg| zB3Kd=9B&EsnjA1nu+AI#PZEqJb0~Jl6qrtnSVeylD`e(T&g9E(0SmHP9Ycp5Tux_Q zXBI@d@gD8a&BCZdW*1D@mg5zR=P%ikDL(7`$xhrQ5pMT_iPfrUuQ>1gVy_@C*)o}( zO#^vtkGBMSonIUfe2@tN=(^{i>y79*p2qFzvj5lZ$w~dtq*ANqY)|K~ape6xPKV}s zIyPAk_Vf*pz7|)lT7zr%K|e)pAuyu8j3*FV4c-~FS3p;8J_?c4Kk<)Ma%wFeJ|Ot? zRTW%M*nCtPKx_)8{tEP;*gN*i1m~az0&CgufqTy8qk51I2Xg9RK=_X(liZKMox^qn zzY*cf@eitNlxjI*+d&ciW1S`8MYw+k|L9{9r!#czGk}=)*S-O_z5KP9;-r@PYhQ_5 zvD;t!V%~j!?elr>@z>tWd#}ItnY{P;Yp>&dvA^~T-behk7xKQ`U%Q$2mHt|c%&Foz z{#x|7)W~y?oxc{-pw!6y62t;EH4=;v8Zfw@1mQ1_`r>fZui!LT6nqzrKl7+>`}?pq zowdIME89n6^vXcHV`@JGgC)vf>6R>Z+%1zumdTsuV#1|2EdqMC?X3G)$dafp#u+W0 z9B`#~REJm?&eN=B~n?G zgxliBr%tfE6rq$LcnmFK(Uu5ikp()rsZeS;#dWLFPI1-dl2bfuW!5Pkz8Pi|kqhO{ zdDdBwZ3*-Qr`hq8(k~yBEVe!MQXCl@nG4)Kk-;OrLa4{UobgZC+HoSwrsLTmHXmdl z2l-kT#)a2L)^Wb(`#5Lc%)%B3SIgu6k1*=PY&1&?WD_Hv9U0@$;prZ zI4Q8`7p3^JyD>j)u*omeg5V6aZu;YXM3&NaxX!>@UVbWA<+vmxoP>M?{T0m=hr!y- zBLer0;hCUW;E^Y$Qz?C`2G6&__rWtPIoJ2%eRJ4JdEm>(eZc+`R>nqg087cIm4cu0 zuDiZ`0t|CbuXK|Qs7vpM0I9?9OcV`sHB7-!y?*Ierr~1e-ZWrsamA4XH~2A-;jT&~ zh;Ff<5m4|b`NP>0ot>M2%=JIZT-s@p56;e!k!PC18>imzu$Rq$lKDruZ!rxF5Xd(x z*KS;cpOO20nh<;y5v=1CYufvJ%m#*(#fW8qZ#h^0tCfM=AOqP!2FU?3{4FLH84m57 zE#df#OiEQ>u-{(&EaVZKtr?xf=eB-M#h_XIf+Dt$|IugCZX3Q7g;zX(4aBzED-))n zsW=_s4hO$v;fe|iE=P`4Y%#VGv|4Q$_eGt&l$_+OrfKJrIOt76$M6gAG@I52B z`af*l5C?TbY99IgpN_hrqS-FcfG#z`Ul6Lob^KS}k@9Cv5x$Xav~@Y>Vy3uaLX^3! zLtRuR#g3}s`i|7N``us~^C_cT@y;bsXk|(7dh%2}&pZ#b>bEO>S$RmoD*ITr(|DH4 zazul17)Gn{bqy#dS0(pp4^Mt*#%4QQ9&T_RTM~M`O~w5kY%T?YANgXQV|9pAE|JC>#KV~D| zPt%|*rokM;*PxqOow5Dl$VRT7wK^k()fp*lkYrR}ca&X1eg2-*N8Mq~rn+lgfQkyX zu&FG2QbVx}COi+5L(_}3O~NdTnZX62SmVw?pSX( z;eHV7tzYWRX_7tWLgbI0D_M%abEpXuW?kUw_>}{<9{kO0kn>oT@xU!DqzWG(g@O-| z81rXiKn!`Fp*_*nsmC(95;~{jCio}h=E#RBu#9{umN#Cf-HCD(QI6U3n1d&tVHY-* z;|%v+@!$z8P^Z0i3*l&nt$Q`ewpHN_n0RI~D&e8iU345h-0thAlL$_+0GmWaW7IFJxR;gI5b1Z1u8;mq)8cfy=l9ywItUU%f6c})0 z$eN#vC=zxZG;5M*SVjCCgoxUKEARTidLmcHYZJs~lgJt!p+pT1MEUFF4DCnveK7BU z-s6@GXD`FrK|GvfmiD7VDO^+7Gg_k{N17DJpmf6C&TI^$b2J82mx=lk!Z$G-+YvmE z*Mc9%mGL#6yI?F>N}ZBUY!}=k)^?o&z3bRa3_B7tIJZS9P3)t*kaIp#3Bm=2+fwA^ z>@{{UQ-@NoLsqZkYxPPAOmH!DHOdaMAmXLwXBe$^BZ}cQh{rdLc>$J;tTU|C<;4q1 z9Q;R|1Y>~}l#VIsR6Q=&Or4%HcINDkvV81_SwMAR{9DfF?@-2jp3Gg2$tIS2EJ$SB zbbP-S@@gM0qQtfy7@WHvmQNgM8ca5g5xFkIHRuLsPJ-rUF{2wVmobj-Z@U9|AI5sZ zfn`26-XzP6+aymsks{ehRiSmy)aLSuO$HB)ER58{#vAN%F;sKu&2UQ$li z&I3#al4LK%pdrt@dx^@lHrmK@Dt3J`y!j{>l18f&A7TE>>K=1bS>0oa7p?APO+{TN zhQ3JWcq)21#Kb!>a2?iVwAKS{k@g27@F^0nvPH3N*$JP!QqGxJtC+eJM@2{`)83Lu zI{^n^u8-Qe&sZOE?Ye<=u?RGL7LF2PFcJcEl*KWtNwAXn0amv283@x7d@pS5^99^vyL)%@g8N)id8rP#- z=kaG6`=Q*XQNlG~$EFLFpn%y_@DQFvuu}3W)d)F3f@K7Em=%k?pxjl6x(bae*ATQd zPh&kTv;B^lq2CD`*qY^0CFq=|X842!-8)Vo>@k*+GfWQ0`*iBf;Kx4Ix)Me|+1O>? zsQ&k}XTghyjbV&E4mL+!X*$VVKiA%Nb>aj(ZJ5A~y!Du|dzDpsxIkxM7HiJd9&K}| z9@66f5L?i}TjU7HSst~OgA4yUZ_W>~CKTVA<9l}O>SxW`e}>D$t*y|Nt51fuu4sqV zL#^wSF9UOKTeZG(OF>n)_gD{V2x}QUONAYA@lRIvZ(TB@QmngOvaZZ=kYMkz)k#&` zYMD6tNooL@arXPK>)w@3NBA4?d>);;6|Q~MG`KyP83X=aPy_$V2hhKaISL+OG-jxC z+JN`9V3s*oifS~P0c>^ zF%1D(7TUkZpsb@Q%f40?GQ#?nm=HhNFfux1^d-XXJ`HBRg+MORJr*NiA@BR*6K=9ITlFzGrNCQejN(RH2hUQgci{%B?3R1H}~ z*EWvI!iSy|Q`8`GJPUGcq#nks9!LZ|kTc$4!6HB%!qsa?T0=6$eAKHPLw(@Ig9&df z_Nt(e1Y%n{b^l;oPxP>87>=|CnH<@NnJ?}5P$|tJxbih3^hY!f77!CuseDNmj>{vi z%i>YK*+S_K6Vwg7ZYLR^(vV$2NuKs5IwX&D;-=1oPSBKc_0?7Np zvu%SCQWxVLg~MK`*AUtUNdqX36NE%rGtw8}^F^P18hP03k%{n8B(?ofaSkVh`apj? z0%5#1JE~Z&c!^{i6oYg3$7Z5G(r##foSSq;e{4)#6UnLasI($yySCA1C3V_c6Db9U z$RQ8=?4i$QAWMc2R{;Md-iO4(sKBNQ8EuWzx((3-{bc zQZ$a1>oG);p36q2{_S?ZWvW#(gHO_LnT(Uyay?eAnBmRnw{zpDJnia@+Gskp19f&1 zb#b881sOvZ!3bQZ>R*|*kC+(u8B812OC zI`lcS6LajpC~i}5L`HgIaBe*vHi5%COva&qxt@fp`n9olH8a6%Kc2|}`x6X0^Sc1~ z!7-hyuebUj8|Z_4pa^n+B1p#ea8QT*)kWy1g5MBy<-Q-4({IvVLo%C(kr$c07xS%j zz_jX!3DU&Lo3y;0$qR_XEmVSmTPWQw*jP$e_dzDJ3_r$!sCOiRHjN zErszpS3lI2gP14>QBe+3qb`LxWIe1yR;@9nNp1;&vDJJAz@~AgTqlV_bHxqgSqWmQ zqq)M(kVow!@ob-GaPGFee&Y0qBQw!(f=U)4i4_%IH6ZyrHUOLCTMd~7m?_P zbJ^3VpAA+&ED`j>+@K#}2E`oS!7Z*hG_=hkmR`~6A>!G%b~dzGshBWJZ__$rTf<&o zuKqMD1NlG(GJ*_3?KK3b%-8LytsU7RCeJcR_er)jh>S@x#MJA#5H|;Y%6yVSLLZb8`VdyAlcPI$ z#dV@OZQINXKxJiQaBdmJW-{3{E|lvQT(wEVX3k77+s|k6Oq+@Agk1etD>K^>SPTVFAlLD}g3kWKK&xW3Ha7pI~Js zJ!B>W$SkC6xhHlAp-UxB%>}(7*@+h0gB!GXg~+m1u2VB}qa z4HA$|xS9!AC+PyTdhnB_;<@<_+L)=<9aKfm!SA#wi2ddM>SpTcRMC@Z62o)yD|$9% znxyyK;T64`vQ5fCt(?}Wl>x_V5N#9YMnu7JXAb{T#%PYy!k~wqHA8pmG#s7nFU2|O zO`V4q;xXLe{Dx|LGBI(WL&fzu=>G*Tgg$~VPS7!G|NknuFLBcf)3Od@ekGL7p*oEonA zXj@Y1`Vc7O9Oi=;ImlQ`6yziL$mh&C@*zqvS3cmyev37@{7j=Rxn58F-Bbb=CIkh) zW&{mWBEMk-dwPn@>$LZKz!Li*YFGCKS2UYkebUNG#*kGAA?xN?R?OboJB>%1#*IL1 zU5FMZhqOu$JN5+vHvqmGgM>tzj9~~Pvdk-+&p?RBDha`GcVWaI;VlfK7D8+f5rN9_rsqqns#2OZcisRbrkpuRTa`m&2$~|OC4E>YF%Zuc= zQH!`yceD*>N7;!2M!g0LSXjA8xA5U+uI)cBo+OA>R1~ivj8rQtm!f%-qnsBqwbq;@ zh1D6QO^k=Pn8r<@s}@kP+bL3`iEHpQ^pYkMqW<<$luhTf#IlBj!MW#)+b1rw{I-*e z+1|i4fQQekptDIv)7~W=N~~a?Rwd9Y=z)w^2x@y=!BhqAu*jD6eOe z*P$vMmT?NSG+|6L2^H(uj_#~D6v8xw{4iTM>XB>TEiBvBwrs@1e29oBqR^s<*L1Ls z2Nm?J=KxW9)^jC;=i#b7iwWvWdLQ!8enlMHuNa)WUmdyuwh+n@hTF-;Y`+ax?OLHt zXb@C@@AI$i&Vm`L&%P&=(_WoIpG8%i%>?v4Nw8N+s^X*X34eHUyxQda*b>d`dst8A z>eqoO`yR>B_s9`_k5Z!VkxioS)jG8H6nzi&{`nvezF~(#Miexw)A6K@Aa`^-`017A zcCz_C+3aIMI365{f-dz8hC92I%mdh`E@m082Lk&P8KDsfS2Tic5s%J3wbL|SAhPbj zHLp+8puM(X!ExH)wpbtz7Itz%zHEyJ;*OoVCyKN%u_;p85J#n>!@a-c-zghGynCyrtvBuR&$t<-AmCfM$XMwBUHkWB1xRAG08Lt zmhJK;6YLoJA>_|rgmj;v-h=C;^w@Q;ZYNHAFQyprNU&}yPP2m%Gitk$i`9t>?U5Eq zfce7IJjUsG=69_XVA^|0M;@G9sQ3xVv}nO;aib87Y41gyT4KM!dW=4#T>Va@(H4^p z6iW&Z6JbVmoMoBeR-|sc?bOxuf{l2=DGk93W4@bF1e~JxM7J}y>CQ8a`$1ha6W^j+crYZj+dhgQ%VBWqd}BPn7XN4P<>6vyL^Mu+HE|KL>of@-vN{lJ)C& z-Tqo!gU4yN@!p_z0zW>&q{(0tGN|Ga-nr7wrCQmuDK}J*x`uMU%<7LBKyD#~e0RsH zVWY?1lh+`IJivv;zTJw#ivJIg20Yu|H9pS$AW%)?0bI3Vz8)d2!Q9j~Ef(6P;=F-4 zGK5^9Alu@Y+R@?;w=GT*w8h0Z9W4$9x6Rr#n02B>Nz$};Pe<|4XQ-10AzMhDyxi)9 z!a*mbK?@?MXup?5o8?MDzqow%QLp4j5RPNjzk+$kRgYV{>*f|`OLCS`;MUma^O?%za=`nPzt&t#7ge>bXx z{Ug$=u0^ltI1CS5 zH<)Z1@5HqrRw~l_TJWk-zSmm$hywWpAA;?iC0Jr_8cZU=C>PhfD%Zo3+q-bpz7Nj} zK~_`-=N5H6MQszeMU^(fxk{a~zRt?Z3?QozK-SlH$Qp|#_O|Vhdk>{L+g71O(yVAa zf60j1{%&3+EJJ~AGGihksg3uN8vRxG474t;r%Vr6nTPiLcW)SVc4$-uJnHFs- zpM=+^>`$4p2uzTDqM=f^=f=8yAIPjC8Qha1SK~V%NH&f4<67WzxiWANCT*7PI*G&v zUi{O{i+Y9~&(+^x%S09^lkh`f-q=x?SkEv)ACMeBDAx}$r?v@t@>Cf+xKGa?zG)&H zK1>cWcAzkAklD@*VzVL%)80cADz>_4nOiIk-cs8sujJKk4|6k)a-8%P={r_I?VN%mDJyz#0(7hjt#!t^{EaOCJ8k(XI_C0}9BL3UsNvy`jN)dG0)G;S zrtv9UIaB*I?pgyV@El3h1veUc4lf6qyiXVVgYwfS3FM=Fqc)5s4jvX2FHrRD#*;v%?^xCMtA}W5bb08Qn6I5tlLYkm1ctX;;AwJaX};xMDFA zlUKcL1r{i_;w@1y?D9TnYNer{gLHrrCR6gnc2)i&^lFVBf zL9QQR6HOLY`Vr1JSe;t5563N8gu`n%Btfp&jR4Pfo8*pPGWDuB^-R`T9hA{v-vc6|$ZIf!HyZLr;fFOEzUtt|r0k7v^C1WgNm`#t3|WNN1lbmmjO&eT2wn7-q>CzGF* zXY?BBp24Sjjr6i7$Jm+CSJ9!d@Lk6oKlmF-J&uyD%9@dXK7qI7jgQ<9pv0f}7UIi| zys2<(QE^0G7~fhw-xT}sU>06_=9ywQPNMVOQTo>U-r9kbLEj~xPk_%)g11`iIbK=+ zWt+60p4L#~8@&O4kFTGX@*DxN`LpGjujOI6_`bD?U`DxyZMo*h<%&yli;;IPj^&NK zj&ZEtq5`2;io3`ZM-W(pTU!Uz>Hk`WW%BO+R{O2`_gFc3G786va=Rl& zBS_$ih9eDb3w{bkyE8^3NZ^Wg5ur)(Y)J_cxT0Yb&23?&u4pfc(FhXw)P)RT z-K-ec46%#|68O{>hOi1%jF-e11PNTT!hV_C!h%cDUK*njBydGz^J`&^qiA=H0)Mb=?N0JqFu%)1}a5+d5lJoz!eQk9=Fwq&|VRv z5hU;_HqzGi2;-G820;Q>MtsDz)r`>YiO~oWxT0an;g*hop&aXmrO^&vD2=LBQX?XU zv`;!|kbo40`4e!|mf-bz-7ng;Lov+AQTLJcB?7%ctxos}m`FW~^jGLi%BSGnsNk0v>Dt1Dz{mLXYG|>1lBxY8#=|>QlhO%ZR`Etn?fjwWLq&bv zd1q&LAreaPx&_aI@a;7z0?Lq<=b2HR9c93=g4#F0FP6`-0wsCs3$5^}#G{RT0RWGJ z;B#j4={7_~ynq!G<`^3{^6^3WDk+n8FiAhaN>yR3z|>iOcxCFdk%-%Kc&ja3kh->c zn*@stK9|8d2)yR)5(F!+$*fEr3iO&}ZQtv;)HGg#n7kQB0sy=;0!RRWyCQ%DE=9&K zj5%nt3*Zdp(Za?ZL|u_|QC*EOq~U9P;dvd2@VO)t&+kZtKY;~VjB+eT{=F>saD5xp z@Oqwp_A60O^9u4(o7AG#%TNnwO;d7T)VkY7<-VweqDrdV7qwntqjG<+wl}&!fJK>C ze*l-@vkZL*tv>iXLm>nXus}h73_gdO2|tXq@CL|O+NcmG{74K!Sq$}TE*bM6`ZRX$Mzz;UQ=1#|Y8Yndg@%Guw#P z?ID!Mra8fvC2=v@H}kxiX$w{FUhtJC$upbkwt13v=}cND*fke%)UW&jm3OJB|BM3M zQv0QW?%9aMdYK)^pl~596UJXf=)#9yk_acwM99rR*xZRAeQ^=wETD|a=yp`U*|9J1 z(8$-LdPlv|ZAQis{iMu*j7MfzzyFIFlV38JvsME89po(PzOq;dEaZ8>>A+SS01KLe z{e2Nc{Ov8u;W_B;F;&3LbPx@u1 zArrO`!D5`uLnhdwWTS+bwYTcyrN7GCyZkzwZhn&rNXDrFQ-{CFZ<5Fc$+$hv+>4lu zGZI)IO;Um%Qfv$z_c5JA2LpEKxZMN~Az9Ca>W4SqA@Te9xz(SL@}@nY;I-FG-fENe z>pX!_yPEWch*FyEcY&?R?FQ!>pc4lhlzY`VB zCz2GHcQ%T*T;1chvYg+2o77GWmhaShSMRly3t06t7#p5nnf5 z0UkZ}L%iGeL7iX%>5LrG1?{>bPj9);CX1eXz3j*r9i&eB_H(^TwHR|ICCiQ=XQV6n zq+ibQoA&!6A7PNaaMDM#p7%ZdL}|2~n|bHl z^)%##xjn`o%-h@s<})saVENYUJpH_|X<%yOHZZYqWmZ|i4q)>?5aZ|*C)proMsBzp z)j(e`=WP2!6R7lD{S$DR@^iOtlbno`^MvKBPBgOyxKo0TwF0W`&4ddu7H8$kH+km3 zPX+rvvTQPQTRGYKCz)S*Ed~{QgvEX{xyjE}H*cn|jyYU6}UbJ?}UX2AkxB&qubKv3{X^cZ{xz|Ngl44-`!u2=2NobcOlHok8D9@@tZ zXjm8!KMkg}_)}&ws^P;KczGEPUf~wg*QBj4e&d!82^RTzrJts`D|a(X?n^- z8R;@yJ&2A21FDREt@tOq{Y(WBY003E=CC9Cw&%YX)l$OGs)D9Y^by{PV)T^DmcM21 zj4g^nVsR@yH76h0e4Fi;W@KygEu;=SN%Q@k%R|aObeX2oUW9OnBOjj2Q@{j!9blbi z;C;n_mgb^;&)l>GchJgNCi1qcI?)yEo34P_zw|q9)QA0+_(~K`r!+KQ)vUXX9fw1M zD_uywE!|Tt&8!6qg zTgt&}k0VD9tbIoIL5FqZSedIGhH_+dKtK=1TAM*h1v~|1C9=a;&a%Tci`sGI zEF)ESq_eYAul}3bPB>MJ+?7l(SZqPViNP7jzmLsM>)KzBME-7BppVvHs-xd^Yd*<)5+BP zm>Mya2*;j7QI}W;V-36>>CK&O+oi@P{+?rGZ2D+yf_1wGxlhmB}k>CHcddc znAr-3FSWPd#@D_bn6D8~t5u^3nhB$&Ya1Po>0g4}aK*u<%iK_ee9|7?o*TA%_#4q% z?THBK;nJ6TOu(X`3`be%d-2hgAq=o%1DSRQr^P@A&twxFv#@#r`4!<&(^a_@*Z$;l00*Jf3Qfe`){YNa_XBD|ca zj*2M$rXwNaow1C5qRV;V>w(-`o(FRY?-o|_8Icyz2NA9QVt4<5na-bz@y3qKYWo+a zmK-21CC*EONr6w9RJQ z^Lqxu;b(#a(8`Q>I%|6uQrEWLh!!Xt%LgH${w`!SMUcRUf(5XL7W?VMep7^faEwim zz&o&?LF_k2*oVZ}1PQzY`!&RVON4!Bj7^ZhBW(I*YL628tr7NN#D>eqpCU-$LqT5T z7VL>(V81QG-VkFGB=8RGTZ#Qpgnf97O_0DlupcG%+av5FVr+s0-hurDvELD4KP|>4 zNZ=jV`z-|aJ0t8PV{C#19%0ilS38l|4@cNI&*;@L!unGL34AChh)x9iUShv1!ah32 zCP?5BHeM!mZS7CQes_d@46!j%`%?r7d?*+e-dqw$=V-kr!akPR?;|!r0v`$%3iiT9 zz+R0@3p=dZ29F~)R;~UNK>}~RFG}3VM7Y8HDS`wZz#mvP!5XBLJ{f<&yzwB?o$!M| z<#}q2VgCq+us)1y_;jKV;XCmSnqS$`tbc?FAH@Za{4hf}5Dz5U?-WTkd3RxUu$aR8 z;gz^Z*9G++X%EHmIx@pcPd1MFw{Jy^#c4_S35d&tHz;mL$u1B7zfTQO+CD+V)gWn{t-@Y*?xvGfr< znZ<;d&H7;aNu*VGVk}Ni=g*DDVpIPV;LQghffr(h?hj_m2MlDnS4Gb|;TXpsL9BKG z_#*sShA%}}xQpvFgh$2)5xgUQ^^?dVJDop2kp;XYev=iJENXZ8Shz`8R7^#f*sbMd z1y}P)kPNEf7XeQ~xhV6yrFOwbO80hT-Q8I_I9>ea8)jtfmq+1WVb*lxgqxsJd>61m zG(_2uaKn6oUKnBgC>Z-m##oE(54)QhOl{eg>K7ZFx;u5mx1;cM>hz~~S@<)%Cf=%H z?!TP?U zDn)*t-qhH7&7bRf`gQQ1bB9jVr9Jj~#SzSjyxpGtE@tLdr=D~yaREzZc%oiylx}$? zzJn``G83K%?I@!#4}p5K;SbQhDt&Gy8=i`^Qwx2N)>XZI4$`_wy4*Qxgj(fC_4mlKMgn8yu&BC;Aek76e)W+5&+->5kLX} zd@uq?0GkO~3Mx6CMIwKmJ>@)?KNFmRTrdTul7bT$c7s!Rt6hc0@6PA~!AVR?H@^;+ zrr<gRD222IEfnOJL$%4fQ3+rkFyUSWqP6cG2Uu7&>~z!Vf4tl1YMcz=7UQFE=T7H zPwJd)btUZK%cM`BJHW<&5B#gEoe(o!uXZ~a^TdHaY5}j00j44Ng%I9bzkG5s{c5r} z7-~Yda)S$zX_KJ@&sqixNHLBHI>i@g$=NoFW>7iU;V}&3d(rB62*!cyVk{BRSFxtw zjR;^E4gBhlI~R(MxX&t^tp7PH?lV|IrT<&-w}x@r;O}K8G53p2fOS-&sE}D_-qk)JX}4XSh8ReKz>4G58i@ z5Vl?YPJ{wJo(%){LvWBmw=@G=YE3w6vihrGZBm$b=koaewK(S;`xUglv0N0yNi=@Q zy4=k4;_ir4E0;v6eG@>8KKJ5Jxbn?wpqmC8eB;@;@Qahuzr3usS@xE~A3@AA&YdYZ z6M=sWFot~g0Za&_D`>~a_!-UkFgoWQSS{+tlFjb|4ZDv*C$%dnZyISXf}LOsdrfdL zJIrmii~nR#*~zmSe}iuLOSE#CK2)BL6*6TDvE+s0Ua}6cR7GcfFKRB)0dxu>dvmXZ zydp!Aopi+E`A+%tBoTWX-osP-;2g}P@`O)%A&wbqdG;ia?Q{6Ht#mrrtt(i3+l>fb zfhG^|RRkl7^&O*^F)Hh5%;t38QLG2gL;RG&VNE=Q^&GyT4qNjIv>zSA{MKin7B5^2 zdN~S)FLh*sYY^+rY6C}G^D9fU^8P1X@a0TaR(b7$8801N4jR~sP&``gJ=g`A%7E3> zW3)G-sRi)ouyWH25BfdCwK{2iQbggPRNc4rsdfZUgnb;b#&d9~j5)P;(@%XV=&Q?2 z>l4It(_tO)i0M6TrZ~}*?34c3zzj&=M4zdB6!j*?yNuI=k3eP(+WTe$#TG{?gtwo)E&D z@_=Y+U#Gexn9USq00gl*P^-Ik``r~NuL*s%&jcQn+COaXg?tWj;nYf}T-tMsr>ySN zHe+*3h+A3eX*s0b=8QM9sfz1T1XJmI%Liq3IK!bsbe=MviBLzW2rs6hc=3!3O~zd) zWyV4&Ax9;nt3u945KY zjV4eh?lke3&vRhGX!a4@dPRYKI&)kx=*na+=MJW&8_2Xw@MP}T*EzrF7RymQW#veB z(GPzHE#+4(Fj<{{3RSm^RoKS2Ku-t2j0|Vkz}GrIFjY87=O^^1QSL)1w^&NwbH(gx z|5sI&@TK0BQP-WFYK-K_MQNMoqklN3nMlZMpvD$B_Q4VE(d4+=f z)@MQM$r7uYQ``g^3<$QiIaQQQ>uOLtH2|g1g(uYk55_s@)RB!W3h{{1N zOb{6iehDZh*$C%re}wSiuVTPnwZC@)me!^_0mYu0yH^KIvA5>WfGn=fp8;83%g=zE zQ(Mvrk>b{t&j8+!Qr3bQz+eQxu^B*Ww6=c))9kkj7}D|(AUhS^(Qu4+6{Z4E#sm4 z8EvWPPvC3kY)G{|Qo-M0b9LQ?6Y|+OAvl`Z!0z*iECKfQp|kTCnSkosBvLB8eA$R< z6kY5)+ze=_O;#Q5&$4&)1nf*vZyQ8w)Ek@?x}Mi*a2`4m5dDoZ;cGH#p-%9hkgg3D zzr@=xt9vclL~-Pfb1|ynVHdF~c;KbB5#`$1JzU!)_l33d`@LZYbN|F05}&xzk&L;@ojR1t6x)R zBb@klpIKLM(kg{M{5#Ns#hBw_2l&f0Y`;b`5C0p`tTyG{5MA1=7KdtX`^f^cdb1Iq zF74Za(3SW>WWO*kw%=FVHJ+Pkmr66u82eVb{XVxEyS0vT1CVBZszpum9ThEf$ofA3 z3;#zGs8iGW7Opau-yEe+5hQTI6dPQgQ^rW&+IBqAXUW!1X-kWRX3kR)=Qh7Hz;7pQ zx|F#fW$wuoPapF$#cgBhO!3BveQPHaaV}R75)U`XR`;X5m{GIZa3obKMA5|MfM?NQ zex75^&u#X8JMX%mfBl?g!IR79cq3Ct8$S`s&*HwHSM0s0IPd(C#{r%6mRwXk?0mtP z^x{zPd@^QQ@%)jG3tl_zd6E|VALiZzysDz>`(871YI;5CJ)tE)2%#Fe1BBjtXx@}4 zB2h{rDiBR1f)tTR6@q{uMNmOdQBjdZKt)AGMT{5(5d;wg6$Ig3Yt7{3a3g;A^F8l% zeP6CC|1-Z?Yu3!3UC-XL=gg#!Nquo?8mxQx5cm2wHNE}>+IX!LQ`W;Ix|ja{(AKZH ztyMK`o#$>VWj#z%+g2;2;nJ_cbsF)+7(687NQk(U6}GU44^xoH(F<1C!gU&Z6rtcR zTzz~Wg|1tuT=aicE`p*)awNr3qjcIcDnJUxyixT%zdKD`aZau*<$%N!O}%ThCEdEI zx2!FOtF~}6Vs-k)X7Kf3L%eQYOWS%}YFs>x;l;hOU^yNy=)U7QY>-Xb9d>hbkk76T z9Qac6`?qtj(<4Vod$^wHuO2bp0^#kjagaSC*W2d&RR8R4OYB9E_DBy;DjDU$xxp4E zZ_bTl?a{g3PTXpvM+I8q9{G3fr@>Ym-Vo-C&eUPj9^+Ar!o+%TZm`W6e;#XVT+bfo zq&WWnj`PuhqDSQh+H^oWJxSC7y(bOC?Y|%pmwt+jORmB$rjQBEpgA5%TjFfJ zZJ`~s$EPnHa75GLNo%RvV63*7_Pj~w+(;XDT!7gORLy2kOq;9w!k6y@x^VqHN9%7Y z4x`1(B#G+fFRr=hVGEC~!>`C}vX572lT&e=GhV}6QGG&u9rxdderYa8A${U)dTq6# zwNC12N8xzP4Ys)OR(>NI2tMA924Ck?2Y&E_9>v|aO|ExmeXVR*3tdosR79N9xQ+2#eG2_^7tSWJ`U@5Ro8L9 zlBdVJs=-(nzN<>P_^xUUF2_yps{UuWLR`UxwR?;5B*@PsA_y9D(xH8-uC#p9{ZQqGu|FCE4DV2Ub(oYIHF$de;@HKT@`-!BUd>!3bkG| z)%BFg^9+7dgKk|sINh7ZZ^8y@XAB0UIqPUq@Ovv&g5MvhMK&8RpQRucp@`d{b6i2< zS|~n9in8N3%s4a_#FP6qTLPsMbvnr-olNNzonMF2bx~;4F5Z~cb&Ri%P}7I_#=$s7HB>F zKZFfVcXG_p@wb?*+ebLaXvxL$m(>hCH}i?*aCIi}H0W}Qnb@S2O1NA5QC^0VSI1nyNo zTTRN&YsuFcXl>{ph#PG;ELzYVg-)e38imL3xEg!;+3_sc6S)CBbFyQ?=O62GyZbq8 z4l2T{i^n>5z!;L<8|t_aF^dpj>*jkaD>{iw0o|4fIizOX+Y9 z8|L-xDhjMCNyRztxNNWmzcO=SI`#IdYpRV7%`@kA{_!MwH-U@M7VGvRCVHeDEP@oQRjp>j>Ts9EmCYK4Duta#*mj z^p}M_M*nt=fTMG0sTxEUjK+^C-2XI2D$d>ic;Fb!&jhg)-T8L^H^8|Ev5dDpVleI~ z*cawM)k)P;^QtI8Evjmu$4ayUd7G|ULOdkr=yXjR+^>K0lH;Ibvu1fA)9`wc7q*CY zAewK4*E;v$H5YCb`mTdM2T6KI8n)mvxC-*HemVf(iJ!Q8(MDoxK+hq==;36|b(I(T zZ>43%!xlZxrh`$z-8FU#1i9_5Akaro8$BHNYETD5xl7zbIdmO?m$^5_qetMAGUD-U zn2ifCg&N?}4HzQvP0evw5I^$qlD2v{hXuYp z7meQuaD<{4pE^yFc6L79nK!|zxP1+4+GpxEOHB{5g1|K7KaUX9xAe@G?!9cIHr1QJ zwMN*-Ps9WslT*TS1LTvBp_{FQ)KvMM=gVg`&!y~;lBS=h;VTAoRvkYHg@%K>J0#3B zM0Yfv(=7BZupXyBwScPBlZ?`qHx&O<@5N1q@^MEhqz_g;aE_-AD!Ly9A2Q0Rl&I|~ zPp0lFm`u(Opx|ak@$ea&39L)f4%cu8J!6P(yp$72oG>xA_b;N^)|5p|Hc1Q_TJ%V!u1Uo+wBE%hEE zA5}DkJ}gC3DcrAa-)WRPl@)&w2BF|#l<|-JeReTsH^58ioBT`u-v3eZPsHAuP6@ot zO`mxA*PAwYJQU&v-)PbvH$>JeB|r0loksPHe~j|5uVdLty*qveWwpV6|C0l0{#w<0PcUzt&DGhCKMn&V7=`bwSVmu$TGIoU*6QLPy>q|MR?^mZ@;3 zV`@7z6Z28NXa!l=om+@D%ArdsYGTndWDe(oX6SX(kPSD0P58mh<#rTp zrrfY1GV-=Vthb#P$inXRsD)URa%kJ3CKkO&dEs2pY&%@RR1Q$H?Yx9edfVB8satG2 z6zLY*4u$;tZHFS?V%wp3y!t%09SX$TPHiJ;+u_FEu39oOG`V~$Zd*7G>^4NC*^WrgY zKtI@J7kpij)M-GM9JC!k-i#YzQoH=|qsSTm@E|A#t$a1ri6lG^g*!%5yv6m zHzWWj?tonsKpkXkExuiWzgvq(PTDVV830Y3rfch#_@9gaN%&ue|LD$3Lq5~+KMVhH zdxa?c$J4)AQXAZ(Mk^c4Qw6Bcv2J61m-PVad36M>f3c_CLjFFiF4lMpm959=Ox9)4 z#$tnUoPLn4Ypmq+j`fK0f;()ZQSU^x!BW&tP+`Nz2hhMCZ?{1c)?8MnW3=*v<&FaM z-->B3a5||}Yn*k{1`j(6(CY7X&glh-UX(xIYpRzYyy3MLH9O)Q`V>V_ergoO`96i( zV5viKoVkZwfR?8{|1z9#M+5<1nX4R#jGzipt2RLpK{JmtYNA4 zR2%e9%|tCk^@683{ah;5dn)x?%=by7_`}l3=Yce;{WaE8oPU8eydmYsvL>@OU`=Oj z#+t?2p0z7$AJ$yfcNST>(?Uz9j9?T%mwVdwIl-9_p zrste~aD{brCPf>H>&p*TV%iVht%z4-lNrY zvlVs4v<+ngaLeN~9F5^){pcID}Lm5{akTVu2}ga-Ijz8F2*vu6YRT1GAF&Yq3oQT7~wF|GIvO4Aso zOqvx2%RRuGJy)VF5}#PT$u@kC9NW?pN(DZZf-U%; zf^#Dwq3;ePE4EA9-eudvupB=F;B#*0qe!&u$CyfCwOEDa&LYuF3F|}&e*VR_Ct!oH zqNfcHcvc)iU4>uF0)Sd(#qprk93@QF#Xfijqm`g7k!dyj$+irn`8W#aFQzt3&q5?d z!!?a$#jCb-S&TH4X$R(#Z6eYtTvogfg*1z8Z^1B$k7CWz?n57H3tnI1Q@xLnsONRR z9Dpg3wt_WWP7|I(3{7KOHPa!$uW}gWiXr??hSZI>iEm-Pq%Cq3_J$RX!Yf>#9lN*{ z9D`TobhJewS>XqGjXl$l+QEfTEKJ~s+dkQorP+qe(6;192{d>#dHCFVEQ?OY`?*eOfzvOv%(+n6VrO8 z%W#HiFVj^x%cL^N^Dj8Zq+15!SL_#nZ`mfqMYjEk=Wg6n4e4@r@jKhP;R(}d9YqVK-7& zY^H%Co9PJCV9}l_Fq_H^6CIfDWcs)0%ru8-wCKw83e#PpJJS)Sv7#rFt1U&z7k!vI zGL0Agn2MPuih)e)mtSdzt=X zdQ41YYMMjkW{E!NLZrdqliVr6kdmlro5H z$Hg(G9(YQ&;`!?|Q`!)sU&VQ*-b@$71*W-7m&Bh;=|jmA&rKF;OMj+oLRkXgG0UfT z1=1|7t#2UMt$uj+inS)8CR~(zj90*B`BTxsjUc+Csw86)=eyB%mgHXTc2q(~= zuJ%LG^AFpr+{>1Q1%}GytKV%iq(x(V@h|goF zcXN6P>x-y?@KqD$tSx>Ph^dReC)-u-jSw&CEZ^b&1btCIh)`(tY?Sop=5A(u*#(r4H`ZOx{Evnv5 zD#K~3KE(Q4IQ6F^f;2LM@*AQmUhfLOWhCK6(i>ix_`RHZ9%u57+>2XLSR}2HB-ZC5 za?#o*it_uhj*B{P3xt_b@2Ei77&QjB^LMG&-SKtHEV32a!e0nUB-Hd^;$aRr}ZVhr|%1>8(2^DeH+us{q~{W-R~RJm-?Lz z7cf1M+O{;2w)U-@K9N{}wVzFV81?tWnW$G1sckZel=h%NcrfV*wrx(*W4Ml%u|CWC zLK5v+ZzWOBG);cYz3$p2`*;s5?!wxWwJ$36e=_Ym8KB@*`5HmO8AhQfMu7;`EsQeWC(kEvI*~?oG)+f7bxY&u`WTU-pT$_P|=`s3;(~ z&Ol7JM)f>4+F*AbI!-Q&`52EXd+OkP`tWg`aXtc^bzk(sZ;^FrE9%gwyPpm2Z!`?` zUuE6N>X|bpJ;fi7Md{>IoL(Q(+tcw!GvK}S4;?mqb&29QSpTd`$E)A!jtR8E zRZas=CsLE6^Ie&5qcw{21M1gILo8PhZU&z`!Lo8x;%@J!!o-}$a9oo%(} z-d=yYY;d~Xb<_cMEnzk|+A9F{e6LVc(VKGKs!RLATChWU36p_mhg=(1G1uD3Y-ZM1$h#0T}*koP&l$J{p38lPtI zHdr~7d^QbzKMo)1yj!``&{`x5d}`)SgiQXrXACa@Bpg|sX0>_N5OlQOeaLDH4|;~ z3^lf9;ctm7(&W6&+D-&Rxv}M-Eg04q>SpaGLg0DhImp^y;B~U0QP$x|I}DA(8p7Zm zQ!dq-Cn8{vp+am~Bz$COigg0gK||B6(?k?}qsckjI$Olx(+28^6V8R!c}S;>XAYK& zfpdnoTAvcJ@CVaT@u77!(lsXC6S0s`hoTT=qOB{_V(4nC7V%J8muw|y`%&P^qnDeY z1n#r_EE3^s8cqZ=9HXoa@V?=XZc3N+0PqeS*~VF$%LWjs3AS2qmkr@-uAvOV8lS*> z#}9A~WzZF=5&Vfy)@ewH~FcaFrTReZDFc6 zMB}|tTASb5<5gdnVCXX1`okf-8%j2RM~1>%4%lr(agNq%5S(KwgA7LpHH7AqWm_Bc z90tRh6O}=KM|U+Gb~2T~NJoG5Z{Q(h80BuqP&ER&<2_D_IoUBAT=1HvE@@@s`IS-%Tl&S#Zcr4J@;P?v3giT$VYIW9V~?G8Y!QZA~ms zK$V-aEKkB6csG>FRio!qFq>&1gnD(hEP!2Z8e~}rE%E**dB%8+u`Gti+;l-Lg>pAd zvOEo67)taiwk(GuhU$BrR^{-sn`T;80`7DivzgZd%d?PZC>K4~K@&ss?5ivr;WkaY z4Q_(T9Hj)ZGWV)YFqmz6|Jw}tOpD>H*J0QUPcW5%-Fv^~1=wOJ6zN5X?m)HAfJWXE ziw%_8*FjYC8R@|xSiYKw6W!RU$bn7 zOK!4TUxoONRC^f|d4Gr_gt9vkmB1|TFzXvoj(1pzp7E|{eGB%}<42?yyqj3xfkGON ziuAU3JL_%;??F@spLpk5_dy<034G%{%K9PX^dXz>mrr0O$1H<(&E^Ds0#6zm)NEu1nU$ApXCDVEP5pQ!|{de0M|!*_<1577lf zflLv7sV#WSVp?RVF4IOsjhXEIv}b3gC_@97>Kn>q!eJL2vw&%)p=nIZ4L!!R-%uIT zIYaB2cHuqanqK-GDom?KHm7B7#~~f>tkbqM%lEqV2PieP9P2v)RfabD+H5~U=@9KX!x3yd z1<^w_-R+38{RA%?dewKHI1MKay~Q+bnD(q>`oYivrk@Q}F{KUHp2wITH*}e4mm%<@ z8lvyeo?c7=BQ!-ZHgpO-FG2bk?RgIAPncrp3dXz&OAT54vusx(fhcb#W6!wNJ?al*S3>L7O}z56(p<3nxJjI0a-Si*lj2}V4iRY z%S3HUW6GJNsTI>SLtO*9*c{?nLxb5?X=p4{NP#Xljj7zwET-QKEn)I2)SfGu!VNvg zw8YTMOgZ;!&v&rZ4pD9BBP1^oJ6YQf2eh#Hhy#XxLh==OIfZ{Ea2d%@bTMQLoG1K6 zrJ?Y^7B+w3`=Iu$hZG=M8fuN6f#OF)otPFrq&@owX4wKo`V>v0kb=d1hQ?!*P_f<6 zBUsKQvZiX!GPJqGctfj^!o*xd+X8#o!bQ$B?YRpnLX^9ypDj`xH?$vZ(PCGT_B@2O z$B6k4YpOma$8Jea9-EYefchA%`3#pk{Y-klyOF=&- zM(gM`q}#+kLmwfv5hrJ9+X<|pt;okwkK}nBZSBRhIhw+Pvuqtj`dm%v!S~xbi*iG^ zA$1e)80v=9Qyeoi3aO89JfX`?4envV)zGt8!$7gi&~~I;@spwVkcNn? zc{jS{(Kn!G}0+496@L-8R`+U^w2r?jnU z$YR@FBE?X4NVyHiM;YoF(!w@YoHR59=^n9gfi8C^(l`;aNK;|R8e6`YzgW|3wB0Mp zmuOmqbf0i6)$|KJ-b33Yan8^uNCjfTa&0?;R47`OYdVW`zj)lx zUr3Wh&I)a_hqkaiAdVXfLwZo${fxGyAU!0aS88e+T5g*nrmfP{4sFwfWwoY0p&M*P zVyB@|p;@*^#DQnEtpGhsME+V$Gm#z@m4+6DZm~@lInQa^dZfq1aYMV1W{UaiwCyV_ zH%lb1*K`(bv&DEr4%a*}S6ng_?`mP2D>64~&sIoJi1~)PyRvNa#7RSg(KcU1J+D3Q zMq8OUY3M^m;3mJHQlT zsG8}3q0>y$U(}wLnO-sE9Y!@AFcizQbc^;(WyZS0?FlZEoAEmWgKOs2`FwPb?QOphAc#&p*7ZjY{1?k&@UcXo9l zbuqm(m2J%pEn?deLocx{`4wu5zJ^{ds$U~o3_HV4+Lnv+hANQC#T7%3ho7{q5Y8Rs zslPitBPP5|R0gxVowPk8b{X1@v{HO!=uf0o;;f;J?k8=lg>#!OcMsCDBHPfjNNdDA zLx+*pikA!p^*CvJPP}TUE7CeqY3Na;^&)7yj`;@C2GPpUuSgrkU4|O;JZXDg%r!I$ zX_I)v&@!aW;%h^nA-y0@81m|M()OaT>OO;ZNH2*%cTbe5Eh3eP?)O}_Z56j^8$1&} zPizz24Xq7#A#E^}Y6bf?k^efidIszax7lA2FB|F@;bVVIR2u3Tankap_>5_~ z_MPH8LlYw!BAwHo{O$TJK@kD=_|A@KW3Q#fNN#D{GiD*Mhqh}yZ z(!~49d9lUVc0|t>=fw`D636c7ZR)&u*X_AY{VEO^&r{J|Y!}2KLl>g=ste*rx2H>7 z6khKF{?RdVuevDey9w;Si5xd=Q-6pD+_b=PNj&eSrH;#@+D$7Qe~O^p6mv25;68ap zM7n9M(1CAF=udEtu0K{*Vi0AviCl+ zmB6_em++OV+;rXQE5qN{HcPC{=_mUe3PcK!^9@DEx|~6BouRr&A##hM%-9&GOJ;pQ zQS=gp%LyM6(et>v&Iq~8P-E+HYn0re37^L`aYoBmj4cOk(Xzr&H|uTA82Op;9E6^6 z@;gJLtR0blHZ%@vh?iHHj*6VvUd}}6wO`jx&*PG0n4u}w(at29!gN$r#7=Z3%S>(K z=W%spTWxc8h?^(s$Q9obiVimldJ&bsp7#zxQM>dJg3-Pd*HtH$%Ic$cUr zcQI80t+9GC|08OdUSkd91txrg6Mx;BChZ@StprXZHIz|?F2}o^jbt*D?%i}5@CkXI z5Pk_SIGe~=L#~AF&J3ApC?;W>%9JBDIY(J{I-AJ}hQ?X9JDbbh#xvD=-P%$fGDLmW zO133B)=8KrvgG5&lh$UIJZfmGb-(j=c|m*f zGtAp1d`dOw>!sUe{^vv`@J515+%Efl$u_*x{VkR&HALtBHgcnzes;E#KNvcK- zhBVx3gbetG3hn`_Ax|b5q8jd$%?(ivcgc2!sD`^_Zzj49nS-`F-1L;!7+LD3FtDD@$ZcuCEMcHaclrB41jr{Pf7J&E-Q@fZnTxlDr1|7wiWW^S&jlf_fPeHMz%SpqdbhBD`iJRk0Y&; zJq;~IS}hM5qWYedrRR0Imyp)TElg!_Af>tYT6xk2#m z&r7_4j(=tFbxLRNP4W>Yy;e5MT&}MSoC8w5H%p6&c{|bzva>G7V-{YNk296PZz;o_ zFUseCqnMTAYD%VfNmet>a75I(%X_N~|D9|z97#wo%N|T6Kxg!Aawt=!NUxJAUXk;S zXFK$KP3|+)6KRM1i|K@*v)b$OiwSF?55M+A4Mna?kB zt0C%%bM9mL6zdY7TAFTM;d5T@V9!0=6Bp!rx*U&mx*+$NC^=Z}f;-Aq>vKLACCyU{ zpnKw?Jj6sj@iy8{y6J15-=zabq}MFpB^k}M$3Y{jF3ZO?0j;CUa;G6$M}Nu(aV$BV zNvP+q%7si+!(^YUa)q%?!L8>nx!KTkYl-uk?2lvpb-7<~5ZeSMT@KWCW1C{VfT8+)B7HNX6jr#am)doWY8x8cs znQ1&c9crhsO+`XrM zX1v9vlH1qX!c>|jXo6!$!qnY&)!M?<1Wn+J_dmnci5qP8G3*JEY&&Z_Q<*kv8(-;! ztL?_~4z^7n>siAbP4E=k?!3p-c3Kluvn^$uuI~!o!wpyWvJJ;QwW5~2W;~lP%`vv_ zOdE}DOsl;rT$Sr6+_DID-Namso)IcLU)S(LD;LsQwv|97+rHH{Q?CEL+VdB-tu#Ye+ zvaPkDYfQr*@btV}6AZ!o*HOyvAx~SlCU}f(`=)r>4rqdEwq-u-X?s8uc;8Mjdl^b% z$})5t(^of?`_9{&X)v-Y`~!2e&=ve##N+TPU!t=Km9aZg*JCb)-fk+VE)xtib^wj~;RThnY$ z&jy-sTp!i`#SOOTIqV53*<}0Hcy?fVRohIz>@uDYu?^;V*5J?tE7`XF2HQ?!d!KC` zpY$wOstJB&TTerlw$zq!^F2KaH9%MQ`K#+Kb~uZmKS8r$%8E)lK#jBN^fMypS_ zh7wr9bkx+o9m_?l%0;y;i&5t^!4K#eqxKv617pUhvx_}FvzF*~#=s{PtR?dpc8veV#03)Oe+l) zJJYrsJg*wtcWir;3BUC)oiya#VXul)@vOb4COFTwI77CM)Rs**cz$DSjoG%%PzR=g zD?MY5UZq<-o^9pY29Gh_VQ6_r7uN8Qp{-2Ebvd&PXH1lD*w$w?$27KKn!w(P+8Ok$ zr!7(wH0?w+yke*)duAFM%k=0P&vFMe!BV!(HuM5V*Hc=sZ$gwb9V^0e42%S05Yl#qaN_>gP+fF&nGjG(qCPZK|=Vx?F2ZSI0F$F51%7 z&xY>9djd_=6+@*Mv#EOb&)RY=)ccy?MJ(4seP!rvEZ0)~VCZ9{*6O06BLnY@&QkIU zM}e~#vyCd%#K(ztYOb*b4SGJNovOS_o=3&;jCrEH%Dl$p>^3MUw!O;IBwifkLR*fZ z&zW`@&&z{$JKC#VOmwxjO|@5_FqPnlUzf;Hrwu*8RL%EMbbUE$lD>1|95r}BK#rQC ziR;TzC5EWJ95vl|QhhmUK9jC5N7Z-VOTgy{DpM0=4|zVOgG#dq_wsdA=QMGB9n~dc zqvh+UfbSO^6;xkGm95E1^>tJ|m~?#|)i9r7tos^HQwuVk>zb5DEA?pGkO@Z&4t3!?Jv4I~-D|+N z>siA+GzQZW;y5S4trE14&e7@p^(aCL``2}Q3Vbt@A|#>ebgjz2$*=Joz!9_#;g};l zay(;twwBTo#-S>>7u5mlxuZD!x_S+V=>KvWEImdI2Pzxo_@=()q z39oVlo&T0cTIW*_<2(+i5_Y31sQix{Z56!UCG2M_tp%EWgG%W>(W-Mk=Quk44hMO9 zF6jl%A(i<4Fj@6d>zwOsJ;eFds1j$5As@<-p!@1HrzuC>GRMFT zTYhc566&yLDy#PKT;5ydWT3y|zOwvn&q!=Z8?IgVxn7oVZnLNAwW+sZo!^dIqSLh2 zYPK<*?#}hb0P?adVE(t+pup6MGs|8u=ac%OT$wohuxdU{e1)Z}}nZ!T49#S4Oj z|8D6N&h>Mnr{eRPXCMCG%K7J*|7`uAwBf($z1qI=toQHJwB?MeOWWsuUSE1E)oHCd zT5Vd#`ERr)CPnyf{5^ecE-P=b-ft|W&u+TSf1lR=cy+|*!T)TV=hj%`>BBvvWBzkm zACt9e&;PIV=5x0`%Dv6YqSGI9TA%m7!nA^KQ7v$s^YvLn9|`}bs?R}m{V8!45?cE; zX^FM`&N)|D^?9eZ-)fHAMZC?B*5t_g6o<4X=T@z{`HXOL{M8(vv?khrA79t2&y`wZ zI8GeyM+&^Tot|ye+kj_|?sLza|4q84Z>fKDuZD0hMQ}?z)1IEOY}Hq!dS9r^r5bVm zf0L$CHP=77Ue6pIvqt~le{0Y!ywy?+;Pt50v(36aIzOG4t2Qlwau&tT%5eiCh>?5=v=_`L_zNhHxF7m0#(WUO-Yqr|`uI8$;Bi4fR zdGo%nBkOOkI_+uIb$NPvT5tCM-{f@TW!E)&)`jJD6Kln^rK)-OieCG&-i%nthGheDgNoxp#Q(r=Fg*`3nBcb&chgj7P1>(LVQc zjxHOAQ-IghsE;cD>0`mUpXeL?98{Y7iMG|7eV$>TP3%LSc6bBTVfaw@W$8VrbDZbWQZTYv_wmtJh zds7^}y!smKaDU37{;ydJwC(*}n%0YF{*7y@HbRZhKd;$Z|C_ggnh2gXQnVXuOdLe* zIqRW%o&H^p1?Tay;O`;O@90?|2I65Fq(ChGC*pq{{EtCxfd7r~KLh`Xn_-Inz3|@; z|AX*926I~De;fR#bTgcT|99~;^uW(%_zMV;av7$VVY(dC<(MwV^a{w3D=@tR(<`B! zT#4zGm~Mq5w^oZBoF!ikpGP8kPXfyXKT7X?=a2azR?I?{@Sbi)B}*jrZMY(i_s2_-+Oojfn5g zrOiYAnDuK`X!yEsg!F3I*UQQ8cR4X;U$2RBM8ku=56Qb4e$D!WZwX9lNM#>keG2s< zSc#=Ja|@lYwP7`s$X_hK`R?Z#qW5#Y59=&!|6X;F=S8jJ_Lp(aakOTNgFKh?ah^r` z4AA(>r+InLaM}GpbGB7sx~1Q7JmP&Ij^lCuW8vg?+Aeami@bCfxlcCAT;IF=Hp*VU z_xeR(x({kE-+_Lwov6cm>lo)zFrYh_epg6x6TmGFM;~$yZlPv_Vhh|(I%%;`j;59 zqH#4wTiBS^TAe1;lNn9A*dBs^p*s0}xf1A%`A4~DaAvh8eZ5Y}(k3nZOJGiu+fi>% zZ|A>NzJ&Qgor>P=xQg3tCeCm{TY?Wpru0_p1pkY?Tuv2Wo$4QfI@^CN&{*4KY>!K% ziBZ-~{>k`0&2VR$pfQfgA|zw0e-rd9wSNlrGrHJL$)*|WWgm`{C1`}^DcL$>w#X8+ z?PXzv;UY)S7L~>G6o6G(Hymx zZ);SFc}gzM$PS<-?a104pA~G*7!z=rYdis zsHdVg1%z;~_UETYPXj$WdK%vfb)g=}*zG96S=hb^$P=^`WnmAr^vmadC}f?6WnF>! zyj=ObT!kXL>2PO0FI_$_T_N{UAM78OC=?@`t_#Q)bbJ_$E!?Y01nftI*(5yD4f@T9-D`+O)wSs0cUCYtd3L4)y z7t>>XO9jm)wwZl43z`LZv!GdkH?!wvL8BeFvvoV?Y!@`faVPh%Q)EYM2^_3`!JLtb z)?KLx^%`WU6f|FOrJ(tOD+SFUjA`tvNUfKDDii^$f4yGaTm($GOOB@C;k8@-}0^t-7V( zDfwAuip2-h+mw%_{mw_yk;)=zkFZGEBTmWY&9Vb5Z0({J;9OU;aGTkS>uXapo85^q zDZQ=P`k*fAoo1VZs6Sr`sxOW;+Zj}*Mp<_Ujl}($_P(>t-VX}Fy68wAl2H{D&FK=b zG`|vbUIaI{1V617HVz1;C2|GR-qbF5wHn^MOK^8?d9pl!dq7)(-Sb-)!^a@w{zmyw9d_8?vy?_^gyQlk+oqKD=pY9qZej^Sg5!()b9I!)f%yx%RTSSG!}| zhC8z)9cMCuw){+PXC}8Zhka;YP$4XftaTG=ekQeT4r)DQJk6VLvd&( zxlEwFH4|v&xJ;h$kIG_S@gALJmXYST%i&(i(aX+TU=FXN9NrEm!jxXOyPD8m;M}NY z^=j+ds$T5X!?jW6SlhbjsQ!>EjgQ*`)7$X9DcTx`Njjbn9`sH!|I|aQh)kVGCYnO|Tzz1E!xL1eq_S_23<~Uy>deU|n)4N4jp`^Dh3c2hw z&M%boW=Nr=_dL4e+2%12fa;pkCexalpR13L1h1~K&NpDgV za=nGT#tXTxa&X)|o`HBN3MGxRKQCJJPV`N~Hx{o$ns6mF3{MmEhGH7-@08wZ%?zK* zTlic_=YllcKC@8i>TV&oIZX`geOGunF9q$Vm%>|#0OvK-zL9mkT8Xdv%@(c1kF4id zub{5wvYT1Av+iWAWZlntkhO}Jv5J?a9Cefbam*j?RnFTpo!?!e9G4|C{0z7A47c+l z=jUMiC-`5*`~?9PMfj|rOsE^_Z(WzQ=1tm0ns!M>&61EPK8BF3EHAEKyiG?$9z z2qB94!AH>+lB{U9{bWV6?Wf@}WH|ov4(X>H=WEnb`}+`&qg1jK9ocgDOqa#+bI8+~ zg+49)a!|+mwo>$-|NB7itG&xal70ypwtPM^bm#c_yl-|_bo|WceL0`^ z<$T^-(Te+iKJRhexwTF~Z%cLO+PkaUtbaxJS6i)tQNwT<*9COPW9D!%jF&D)koCMc z(my4tyZoVl^QiOOLZ{f&Y+%$W?6JJ461i|dA*MGqD?;^4m>!js9Ot7vS{W|KoBgSK-zPpz+W8tbLEx(XFtKUeX0oIFME zYwc7tWA#q-bYYrWwNuf^p*%%z3gsz!Lx>`5^{!;kN=0*9SF(SlqH#o(ipCFBDjGMm zAM?NVA$^;5vd=+9vtXC=_H$6tT-a+djaUAPX2jl(>8D~2a)=s2dw`c6}{M{nksXL#GVsA%@;i?}vpW3S>i^NY_#MKfqy zEVSiZR5aJNkA?RvMKf++R5Ty=MMd*&PecFA@QaG(+72=PG!u7-h4!P1ipCCIR5YIG zqN4FD!b1J#WW9*(*`_XXALc1~r!7y>`)bi>o$Ql`@8vA@PUdu)h0o61hJ3w5KwCwg zqW9GDunkX%Os>5OXnV`D&=O@?XzgTKXuj_>jDuI;7Mkxn3)9=wMBcwj6&-;~6&-tX zEcDwFITm_5s~oLkee)C@vGWuivGWwY$(N_-y}TR?{T4-zh2GW5<1IYLLhn)G?6=tR z{fd5_qPvA=81IgCxkPshjcMwS>9M}UxNXC*ZDn!8EHuyfFbmB&K8)Ko%tB+6hFPeu zhH*RRa?H8>yBB$UoSDmSjOFq2=5w@sjP`b1zJ=x`&$rMV<@p%x1Cei`aY*?bEuW(; zN;32ostmTk}0>2O*IzY5kQLH^k|SL8NX zAt?Wpc+-24%PC3QO3EL}TEf~z9TtmRYb+drb%d3Cidk2&R#+*fvXQp8k>^nx`3O5{ z0&5a$vb{a#WZT)3b4Ih~asG5puVG!wITf5f#(JD{go9!#)&$lh)?^1oZp-QRtRq=R zvrcDS!&<>w$^OSUt(+9of1us>^i*3qofS=X>uupVPozPwz%yj+}a z&pMj5gmpUWYSuNZ@3K~~9%VhoD*Py#VohL8Vr|RXo^>SaXx2PGs<(vG(^*%uu3>$b zwSu*hJ&$tw7_0E-x>yrflUS4ec`b9gJ?lu;(X4rFE#dTZ*43vYyNtQD-sSXCgEN@8u#I+}Gl>l)Sy)?=(Hi2YgHvW{deVV%ypnsp89yQ~$g z)vQNZkFi29MH8%wHJ&wzwLR--*6FOPS=X>uuvP|B?;Yc`2%%`nA(XS0RfJNGC6sa! zINg?YBx^Bi3F|7>)vUW%-({_4J<19$ZY^s(YXWOFYg^V4tRq>ASxZ<~v94x)m$jPp zC@X|&t@ILTFknNbr)+jD`ap4)@;@h zti`OWSa-2jvqDq$XU%4XW}L&C%{qd$m~|CvPIKy+;+EvOigg!jH7m5@2&~zxBUmAe z^I2E5q4X}+(zX=scn;}^PLyBFx{7rdYc(r$<_N6WtRq;9Sy!>{Vy$L{F6_^m%{qd$ zm~|EFF4k&R=*s@RNV9uYP^8CLhlOA51kbHaA;}h z?9ln4<)P1pZU}ubbbIIUz)hfvd_D88$HNwXh>$SHrB~G2xxUCx$PL_%Y&2gkNN% z$lS>3k+UM7jC?wBW#o&IJ0ri2JQMkA`Sqq#{L%DI&NIt199u(HpQKYyAYQc-zz?j*MP*QRyd{>o{M_92()%ug3V)s|h~sYHFTxwZIx&)=1nmE?L*1{$+g$)ncPx!*<%^@SL!{gQQ=liEgVv8_ebZR-=S z+xDe9XHo*?=(-Lh4)Ovxlt|J3dFectRHtX;c8vx2A(z_l$>5Z@ze`^m@|8P(&(Q36 z?Gpg&@z=f`_eNpS;dX~6W1JS2Gs)PX;Pr@MlJ$C`Qs1k-_If=i89)bD} zL}C6eR0(VFH-2!$I;zB9C#S7$BdWyT{!YO3Ce{~366S1XeMzKX{uWe;^Sso>^n0v( zMSaZK!@5tTV*dNAABu*U{{ic_f_`282h{buX&LG9J~A)2CbTx6Kvqk@YNg)I^IFHO=BgZDjFA z&9ErkSMOlWwfN%xI?AeWk9{2VY1m`$f={US*;nGPmV98xXP&U%eg*SCw)YUr;4tPa zgG2UXmSylIdM<-1v@U}qXf1~mm{SfX(OM2ap=UXqL2EgjMe7Ql5{X+br{Zjne`%UrNwX9Pmis^J zf875^|8xF-`OgV>Cg6{NzXEK5zJbYssew%bTL#`2SRA+{aAV-^z%K&74ZIvEg4zc4 z2?5;NOC;20KHZajkdN4OP0k(XcN&TA~)i$i2EWQh$xPj88I*7i-;o;A(7FMbs{@O_Ky4^(is&KwJd6F)aIyH zqyCCo6ul*STlDME`=YC&Lt|27+Q&Q|^IFWiF_zeYu_I!~#ZHbbirpUjcI>{`ld z9pn1O4T~#}do8Xi?s}XvzEOOK`0QVCbcv{U5l2G^%l~Qb{evSrvb^3~C8<^YOKz36 zXY5(YTeIWAZI4?cwbZ}7a*x$&wJqGg+)~@)vAuGsbS2evsY>m*D2Y)OC1V3U4AYdaPf(1U`lbQG4DwTRf z3>!-XsQccVdGh4R%#$Zip3FSA?k*}eLO~%9?(df~VL|Yolj=uGP@?`X7u`jdrg;?3 zMHP>Sd_j$`$VY?B36G&=iuB3n(IiixJHEj6(_EumUyMr33SZO+&vGypW~Y0dV%W-*VnjSj7~mJu@T(5I|o$C#*Z*aZI^%mFLTtCmX%=HdenQMis z!nMj3bFFc$b8T={xxUGDpR2~T$yMiSaBXqD%hlv+akaU&xgK!6$MukFhwB%(zQy%z zuJ^fqAJ^~a+U45g`he>XaD9jCyIg;e>kn~#kL&wff0)tyN4P%Z`iL?8N8$G$gWrFg z>tkl#KM`HW&brPQyUs;F;QBwf{!gw?xqis?r?~z!^Ykxr{Sv+MXXuqb%cZ}*=xyfN zetP0vWT2n<;?MOl(eeEA7C+|W$1MIheg3N?KhFHGX9VwEzEzL6>hrDn_?nMz`1pp8 zf78dmNnG;#O;4xh;Wdv}_wl-qZ~6F^#l<^UpYQnRAN0@f`R5kA1+HUA{t2!ju2WniT&KA{&-Dc9U*P&_u2HTrt}g=r64#fxp5}Un>nmJmxxUIZ z$u-4wp6enPe=|25tJ}5sO7uo~v$hyFtL0kt7vkplYONM6?QF&O+SOVsTHI;1+=uWaosRGYJM|r zZ!}grv&^>1v9jHc4ScJy8s99}t6ST(a+@kB``vh}8MmMpH>25lWuwtd+d#wKtJYVo zCU?rsRy^NqHk$JfEAf^UZ?Gl|xYKA=4KiPD?TB}CjrxPQDVnbBv#{ksQYNXbc5}ND z>abK^hf&p4Ls)E=+uJRxo1;&w%QS#Y?f79kn%huK+ARWf1MFC+uU0DwZD`$T#%tAw zv7R@jU2tY-Jr>?yOo}S&bKP%t+-PLx|3By zm-$|^I$y6eRy)Kd1B}w%o_~N8%r@6s65N(aZtH5f6;s6phCpksQL7=wl28ybF+4^l8}{Q zH`49d(W2Q0;>+b&1zZd_iy zU9asVJ;uPKBPhamvGhjhZiV-E_IOB!wa8dDqgCA3&{fKcUPy~otE2n0^MPsa`OU5N zj#p#NW_ic!=b*@2(RFm>^=vhoaddsVUO_0O_ZoEqcjI-$DQ-I5PVb~*02{)<5~F>V z$qd-Bjfz`0rv+!&5oVCs&jPeLTGX}C*siTAHMZ$3YG(9(C8LK4OHU?r0#g@mOOwRq z&1ebj`+5_>fZ<`bTxwjeGA^#6z5M)XXzD@GGT`gY#->AUz^cu1+c9@}Il2`~WzM!* z)%CiG23jb(TGbpHwc1UD=UrXP?ecoGS>DoRVe#Ttc{5&WNI{}*y`EuANXBQkw&MEg zQbW&jGhU5Q+%Dj{(xEMGuQ0aMsdKck9b4G)cf}LL8*zQTz2VVaHPcK|mlvi@;l>eD z1zqMb!@QAp`%(j#PfcbL2_!a0yIi?1)uY%_!_C4@q^6=+b8uucv5gm(dMz$*Q7w(M z4nRkwZ1eka9j--<+Ul~CZxdDKa80YxLY;}+B*jm@Hs@{yX^;%~ndRzswWdy{kC z;Ud83+jexj9?#ZSL&R*9a*Y8cdnMa~aYiF15SEN=pB5ujs%$-e7>tW(v5Z=CBhj(i zmuGBu;n%C}4aTe4J>?oY%>^AgP3h*q-ST@H(%YN$P?eWzjTN!lS$%V8W0b!cTRt2R zWrQ^9uoH_lcE%~?c>_!1Ac?iia!sO(TXChjRz><3S{-<4f|OT+FD{sx>Ohum^C(LV zl!2@ZAJ?$^%8g9Tv!6MRd7k%Z`u+1VZ$PTU3Y0d;o@`eGD0br^y zZs%+9CXBK9%?(Y2%MZ2$*-vrHZ~-~3uBs~7KvBEAzAnQEW4gT)mAA2<(QiA_D$%uD zi#ASpR$zZru5E3UnQfDRw?m_NlPMfQkR(Nzu(92oIMu=D3aBmD9hGRUSzcGQu|8IB zuXzS;Rj_O$yZa1MIverBYv^V72!w2GVs2^z_iegUV|KRTsp01bOUo2O67c~li$st; zZa#=tuT`6}>X3IcG?UnD4UM?Eqdf7d6>Q^iVNK!J%dM*<-(RS|F?;jIl5na26@XxBLBRxl!WF($Sfh+(^`zT z%1z{Hp{_P+QfRhsuUXhy?U)<2uGSir`vM2R^;+Y-OuS|WOti9GTWVG}H^nM=u~lZ_ z0_-{yfl5;*AEwbOs2mBX2~>zUX|-9rwVVJ^eTEvfmO~J+3zbhps!@yYO(z0Y$KraV z2zm)jX7GBeQ$nqqQhF6S?d5WPl^(DZ&kl9rjRq?^l0B&2a;i6l2u40jrJe;K zEy525UqC0`iS7Xs29J+9!h)^JVx^7kn}8SCf#?C&Sirt?$daKzMaz|531LWjDNS?y z-d3aDE5q#SH&GIGug+ZoT5S8ODVVLQ;yo*+gpM-Alh7)kgHe)zJgzTB2tltKXO$cP zu2P*bWw61MV7sAY3~~v}E2cDGcFUAXMneKB5hEX!HWs0QfwHsPiVfNHey*}(zZyJ}FMgcLjn5;p8gXw~nQG{I7 z>0P9K#dQ9vr(1I|E71iVqB1UG0Hv{O)is-SP~MJWD7>S+Ob7;WZDo?7 z-^B~2o_3PUp=3r&0tk|w0y@S=C{E+ZCuq5~58H{minhvt9z-t)@3NahGbtjJp&v4& zqXWZ-gkeqG;U`oAfJ)+sNQDM7>b(C#sMwMi?YhgJO z^~s7PxQp9sY=5GK8qJj|rd}PMl$&wDjcS2iDI_7Af@bSGX+%Q`0oN|TOt2=e++SY4 z$~u*);CeN#t%lWFOJ;Rcwxyfi+VSlstI*AI^M0gp90so=9imKeF}z!^YTCe13&Gh|rCPlax3#BH zZ@u1VI{VLCN6yyNI?uNm9B(tqGEb~T7jZLsb_&wev`_~xnW)rCAGJwLIh{dk>VqxK zm@R=?b<3=C)~s=Rd&_UhnLXk+wlSQv)6CL|mh03)qtzz#Rup=-wu8`^eU(W}f(Qqd z*`hvK&_Z31+nZGx-k{uVG}*SIlzS!H+kqg7-d zFoTJn)s~#<>(M+UgJUZ}ZIUH89+Jh89M}O*7A*m49j=N-Az(FbY%K@17hPi&vQ%YJ zjBI(EcZS~BrvYYMKkSF6y|6#6n*#@8xW*rt?Am>Ba%k^9jI?rEpR#Fb8{-7M((UBE zk9jVKSRfwN+3{#Cm;G}^J7Sgl#NCt4Mz^X?)->uSzf;5lPX}M>qfSU?OgSpHWi3n> znz6^embpY_a5I-OxX`^V?Nr=iN%J7~+cQGz00_GSP=6G9a*|;U$mUB^W_p76RohiD ziyLJlDZQ7{GYt(&jloT}d9}#5ty2kfGO*`1;>!JN+p?u;`YQ8_ju6?ybcYz6a46#T zMo0|9+n^zWsOa?eX53tlH9_?_c<={Wu-dM$)A@WsY< zldUvqOP}f?FS!HX+iOmrp@eG~-v=66GS2<_NI>s@Y_t=-Oxos*foMG18;9=pnd(i0g zby!P!v&)tdT`(;NxQL4S*W) zu&3tQDEr@9#5ru(MGLUVd3a=);dznW*HdOYlCrHkO>4Frjr)gNr-+{!3T}hXZR4k2 zB=^{MmB$FZ&c0HE1-P7mSRba*R^(9FxMl>nupMA*`3O6jTgl>U+Y@xyA?ERY9UKj- ze^P$HbWr?KT(#tkVj-kJ_80La3+0AQ`VJi6pc)~Tgi8&UbZ9OgAhOgT7A>+ztMd(3 zBf%xhTl2T;PBCVeA)L25V43BJ3pL$h#6@n`g8~gtA%?I=4N)8<^Dq)zt-%OMLSELGB0W;}XekS(gr^g#>hPn=)L8i@?x=~8a~H*mju?ltF+1gp93E9Mh9Z`ciMLBsRZYuw zpl)}YR&apbl!n!+O?nc?*Y@6gkiMZp75s5mSzGJy zn|%e_WLR#ou8vwd2xh;^z>VdVc-fu5KVW1E?3~(Mtl;0i*c@Kv__%q$M=s|LkS4I> z_*&H_q!jkjc6Bw4h32tIBSG7rp#I*M=&jbpxU#LYZzfY0plVR zLbI9Z0tYbG-HmJIhZbt3`F%#Ak+f2kGi{nWFTd8#s{0HYPj0tJYEUt^w6ie;WNy3F zZfqu$60cp%h<7o4f?r@{8}~C;D$C0P zSCS*>^;#KyN@14b{PZkn=!@D^RWXwnbf3brvfjQh9U1tZgX=+p9;CQqy2x1~GN7w$ zN@C>RD&LCOMhY8}q0acX;+E)Yc`L>#ZuQQ7kflQkFCA)Z6~osuMjR{76H;csO-L`t zHI8jtVc*7kStlZkL#yqer;eSd4;gyqHxjR=@CDn+Ln2K)aqq?=*e5HiQLt@|qg%{` z(TurHI+01kJuEZh$`kmSxuc4Q(EUUv@T@A7kkj9 ztfbPHGU3aa@buxNeI=8ne7G!?tY5EhpzxQ}F6M|{7X}kh%wnqX@a=MiZ>5EC$b*A!QawA_$dlamAyzo`>s$p%mA zXc@Bh;PYjS1n=+PN<1-b#~$SA<>mH9wH3`^JDUfLlU)hYB%Rr)4>H3 zy{nc}GR(=&i;T^<$c{|~Z^;Xh!$(+;tD8L6Sjo%qa0>4($05zS5%B8J8lEaw)=jbRBcVop?!7eHZfLPckK0jG=34ZSRai;HD zCJV2q9L8FnoXF(i6y{KQ;9a-hs~QHWj7z8>Aa+4ubhk=@bIwUpIpA#SDk%V*>jYpV z1rJK4qYkgHOd5pxbwQ|pcLgRX zuZMr75kN2wN}?$TCBcP*lHkWdN#%o+up7H;eU8?4IeA)*k*Xfxb8xH|7{=}+Y;9gD zuP2T!qI-^U)#*cOP}tc6+QT3_SBbPA6ZUduQU_F{Lj$`YFscgzf8@H?>7Q!35utr< zs+IsVx|_#R%*c2{6f;?vQ!qlryP$AwUw)b_%w%gDP8kIl)DsRf1b1fvp8k&IKuq>g zN2&}v__!LPcp(xUK+ld&U=Kl=f(hA;@>L@V%eu>+Mv;1lR=0s{n9~|-Zn>I;O8UCp zVMTbF=JrnLG4iJ2K$i=x(Le(CRZbG(7SGOO)(|yhR125jd{-?&L%L@|k9MD@?>&X! z-fA>@2+#S@Iy+NI%R3*~(G7>CR*!Bt!qVNs^I`^VG1P2D&i7!)dD!7m6Bk@n`aB%j zM_2-oJ=8HoIJ6(wgF6@0gne$jB5}cVO1FcrrNEBvT3j%-;;S*Qtw+NYLrwi-Nu7Z6LeK@#Fr2>3-LSu9P0UxOgsFW+@P=>@!$HF7{9r z7n8<;sq-h68A%&2_7H)Kh=2yVZ;~zbI`Z_8go|Ed_&gns%i_^RuO|*n@1Zg-N@CJ_ zWc`tiWDnL{LQFDQI^3a^=MwyRWO@&gxn#48DlU%?qXI{}1?v(*;8-RW>mb%JdnngS zVwK3LK?!1y_FqOLIFbn#P40s9P!E@Ey+R$iWH>k&G zxJ<7iPTqCeGQx&#)?7xqd66aKRc)BCp&PS&QD;0`(M(UTYs*D@4@@k>u!9qk^n(*= z@4<<*{NO|+>fl7UeQ+YOx{m=;FNtrt8eEog>4fx9Ei2Tb%Msl&i}QGgXZ+I*j2QI- z!`mL<6}Z}6&lQ--#1;r^o)F=c9!*-I0bM@uh6+=AfhCK+y0%EJJHkE2(Te7d;7o5M z9rIEPex-+qanz;xE#r7^S!w!yXoZ&dfcDU_6}2XznydvXu&EcghyJKgd6nfH`{nVk zdR5$P+zo}LJ#c%-1-lYj2|1!h5TT zYOpHRvJcopxvatwAto;~SZ+zvK46cQuS%FZUVgCb8W8)TJ!XcP6n33%7}(u`|IFQ!eJ#`V%|KhtBl+D!?pbQ_Qk+(Wxg zPSU7=n{F05e0Y0M5?necNkSW5mT_<2IBHTa*;j8I6c+4z1;?dGM+Nx|^jr#aPrB*T znbeC*=Pq!Dws|+kBLSzBnVPIfcc$UUNm#pKQgK}{?Z@ncNs)KsNs)EKG(NjwVpKN_ zmb({xtZL^j9dZY73N~i*9db`|atbDA^BwZYa&n3;$mTobhUnxJ{Lkh)?5^k(eU#02 z*qu>rjb!uj!&!&gQJtn=v-$V|i^Juk?=$(>bUI`{WGkERkcR}5+R@48!`b3+_3V_h zsj0)}LuRw(9r9FsavFV+&3FE=<)NLj`7RtbANn|(@32R_(CW*tb=dJY zz2c60@z-$PGIEx|e~%wHaKE&Nhav~AIvwUPC~oS<4bWlUCxbH~^J(NL$h(_xT&A~X z_E{31-^pRQ@3$m=E^2SY4T_zy^DNsjorqf7E9Sz;+mFfFrd*iQvncoSIY*RokeAAu zz#}Ba1&z}-97gnWDzc;=vR3PKQ+K$%pp2j%xQ7*N#!-*lhZS!|Q;*z-7V@6C4=d`7 ztR7__R^S<5J#rsb>=|V}ax;c{Ko2Y0jHDj94?Dpyo_gdy>@>ry)+6^}CmZIr9=Q)Y zg3rKgG>z4X0*2Rq@%-Vf)LxqG5rX)w+HQ zQ!xA-mFzq!!q1wSXNZr;b>UWQKcvEI%;nk+-oP{eJ+Di+0e`6GGdI}@fU+rRA zR>sZWRavN)TM*01Mf(hfU$ zhdhw?M@8%+FXMmEu2$@LUO)FGCj~jVynq`~rz^p^sYzT3y#Jng9(w1_^jE^%A^*WN zIr8eHIaR4ZQ$i%)c*px}tTW9i&4B5YV2Dlg60-fWl2`Hpj>>RaKL9R8cr)dR}7=>bK`y89nb%o&?l@U9m*+yXn}G^Zn-26e=dua0;R8N->Z6X#M?g)Dw2 z>8}i0!&fPv_FOqfv)qrog_%2DOl4jYOLKR;-kAOzYwBJ!^U8CtT^VPQ?bglq`dIL2 z>hW@2_=!hkc$^o5aO3w#nP2Q253j?`T$xqbFOLj)2?iz?A4moD(aMzE64~- z&>n?9qHVoc5M;sLj+Jy==@1HaPg5On?&9xEVSzvUM&vn0i*}UD{35DGZpRf(TmYe*#DWX5~%6^`h$jT`ol*no)TjJEAm;ywOtP7y4sf za4He6@dl7yds?-4%!^M|y{5!99z`!K0#yu~hWH%bkNi{*F}-je?J3c2SNSR9My0E2`zxi! z^r+I$Eb_I92Bp=g_9A78k7-k)tfInxz>HIx|L3@qeGaXgv+K>MCK=@RGW?YO%6?_9i#NyM4aACDI;(A3fb$EsgWZ6xB{b!)uOF^reNK zicN}0EaX?bsn08fPy)wOL62UVg-*ppQQaN*v_U;Wo5cbdosz%r= zQY?;N55bb~G-(R83>h7edbU&!?TDS4w=W z|NkFI44MRJfGSVK7rf!ofRXCkF)r%UPSw+dT_j5sNJF(SPCl{TQecF4- z?IZH4wW*2V%z=))H*a>dGSnhW5WS|$Zrv0nO=^NllWKmRv3wSZSmvWaU*w}ZzXzpz z2FZCAiFl3=D!l;4i&1X(Po7~uzKk$k;x3_bqV_glM>$8>#iu(`o`KL=E~QSIUVw0BV8NTbJE5~+Ez}L*-=VSLv@9^NcnWpzaPqX z0wXmlVRSQOn6FhIsrwb5dLKF(7!m|G3%MC`8!Ra|S)(PsJ{4-LHcUpj;kT%R%6lG# zK8?)~0eP4}q^P3v^YChm@?|$^X4iD2;qF92R+i(_8fhxeRPOo$AvYOSt+nfxccm+@ z%phkkXJ_v-lravc#wq14Uy_>RIZb`fb3H>iEh)zo)LG6wax8!&)uEa?ODTG(ldHj4 z(=g1|GMh`vNUB#exuzjmT+z|MLo7#Wluowx5~xiGNYl$)afYs&u}X+l)kH@#jGH?) z!AWsdq)b59mC}b5XgM9%R%Hg4=+Kv#6S|q;;JpPrWgZmJ;hpSrqO5L`Cet8s-5mW~ zXl-DmgiW38%Vij&*2?sWQ=BDdLMh-Lq3>aaJ8I8X=!E_ngh7p(Z*`*Q>_r&TQF-t)UFdAnc)}Yz=cSbhlH(Q^QgH z`1X&<9ewRlx!*T~{!yhzFN7XazsXwD4B_m>uow;br2sX5s#nw_aNxbW)Y8oWk^yl| zz2)W^^^-U#b@((IUYu~fulPF_cYPo`QvEOfHZ80nmfDU=a|%T1SS1TfU}pO?tG-h1 z9-Hj+e#4!rFPYaPT@JbH>-fiSC-`()5feFnJQ-S zEXbdpT2eXwini=%@$d>WsJQBszUrN-r5xj17Hev0b<%NmWEfi=ZCcO-m(8hVu=I!~ z3}+c_SwCx3y5(3_ZXD-qt6}gg(+!_f9vr9FXmw?l99LPq-{g6Qai|d=bFG<*PPJYb zDN@DKW$Je)Tha&Og=ERudtLf%_v1TM*DZ3ShyuI1hkI7s-m^}ViMU^UQ^k=AnY!mJ z_QCTQFmEzQzr{Zdwl87aJR9lTZ&&D;pT#bC5kb#w&RdsBB(mKd23D5&C0L_P0;i0A zoG2e>+Xs3Mv^yyCiAISUTp@*m4E+*xG&^aSHBT?f1gTuarr>Dk;1x5z2uMAOux7Gz~p zp;gl$ZugH7)yMY7(VwMMQ(}ET8$~zg6C+GJP3gkWEtS-l>jrn@PWnPHsV%24-TJ|| z^eflE4U@0x=_Dphz*+s^cFSbWsRVY5`o0xK16poIeMtCiO)HYrFwwdRLDr~LcQ7iQ zc9AwpCk$Eoj=Q(uuB2Bjf13*hJ}|>qZ=-=P^AWtL?;GsJ?of*Uokd^WgQ$a>1UWoa$m~gKLh>> zxg-yhjCQwek$buur(v|6)LcyQCcE(-dRmgLGPUBBd+yiM9Oc8;^(}ZDOF2ZVfFLmlu@VJJ!5p9f-i4D zBjR4R`-_v0GVfQJ0{uxwV}J$vlYFu~z%C{sK3(qVT~0#q z!^0{`2Au&8UG*AL<=t!wAH##(Wl&TKDogX6cj3u5?V&9SB zGd{N{O>-@AJ+wMJ>@VepMvu_)V%a@nDCdE}zOm7vvEuAe1&ZY)R3${;4GoRakNoxL zbj$0;L6N#JH+)9z-2HH9FhUeR92z>R=%-^y+c7~th3@XI0Y6EApBNA^L0IT15L5>} ziVs6zR((CHyv9+51`V~id92h&thiYiJ4Wq}5uk8LjSUzv>LOyFsIk!gWYq9K9V*_W zg+^>h#0b5c8=etlyN?#;O;~&wHsyi2%84FT-Q9(QxdQ!9a43IdsQ-wE4Z*nl>Ecc< zPZt#5mlO`ajQFXH-Mt)Q+h^no5<#H}pW#l3y5$Ql2=zQELU}dcmshk;H~O6MwENv- zR)~@c$I0ce3WXtdj4Xq@KNf`)7k9ZR>C_NX?~0eGd8*%cq*V2>(G#V9hoH#O3957I z$>_;QW5C*@27h$SScow1e(WT)IGZ0-r+=)@%#YF$Cp?N;C^`&6g$5>aP(y0a1$48z zwD=GPSYWpJP~?B{RESHNfFa2M;ltvrOZiko$fcYv9my3pk+H&9A%z}|`lyUx!=-+5 zeo~xexVaoiaq;VP(bwH5fyos4-Tnel$pL*uiO4|+ie*W-_|T+6B8pA`mu^?f6cRmj zUmlFy(3p?*5mnFa4xmYPcPY2cfMYljx&Q zOd<*f7~X)DbStV0<&et{ZwNfR(Ff__jp2=>60PA4C?=s#Ox%VyPEj&^&7Ufq8s0K0 zkc5_t3~xF5TPjdGH(wA#trBD;u>f5!+(V`z#RIg@M!)n#|A1~sxS=I-{Sk6Z+Lq@L zf+rq1-6O3wG&JBXl4=_oG2<6^cOz=Ix27I7qRKG89O~1Xwk|suZRHv^(S;1@}1V9(nLd z8{YjTs$sJ8j+*!*>Q@(?#D4XtQ-s10o5=7DO1- zLR5$zL&Lj&aZuAPK?nNKKvYmqiRiC6_@|1y;3qz)Uh>#Rp#KOcg;F1?KxB;>eM9{} zBNcLFOv3`S9}w)*7${&`4k6T0ANK-~LZ6zm`{ytfA5-9$rIml(%x5G|kqm@l5RH*s z{&NIK`a6b~1oET<$&ch7ONCbWh09DgmZ0gADf^zL@HG3c^mjz}Qrd-YlnRf?*-6L6 zGPx<^5u{J6k_c~Fk&|!%Ny|1_{mxiaD^56mxQNVPH~73!jrEV@=11~wY%rYN*cizh zUo*A(0$CHH1TsmdyOJD(10~J>FxM5p^x_N1q3;J#bhE>|zeO5m=xqMDEibevc{1ud zmK!}X2plwxt>W%)I}w)kVRNrm98qx(8!$q#{Ps~N>c1@uoK`;m`BO4}AVsxB&`mK< z<_3=;j9@{8p)s2;o>En^IQjl#6nJ#7Po@4-S;-9gy_3Ux!^a2v382{bP8RwHK|&Vu zQj^1bFP!Wj%%5cClLPUE0m9H8i6pF}^oEu?M{`mCg1*=n(S*HMp#U1nmbC_>ZSNkMV$^0;R$atT>h=cubaZr#RTs+!p45_v@oSj* zQ4P6ALr?(VqV-|j-sUm*4ry^|fTr(lQVT6wc-T_KVwykPLV=uGJPgqM`1)G)LAJU9cI5OBb#7f0#^WmUhOB##ZwgaHk zT3#}zAhq0bPYoVZjXo(p?vsYqD*OLQ@usI>f^=`_3-JGO)?2%ugnpL%kbN&gOimbU zF7S73)h3u`hX^LzbZA0?X$2_m)3I4u+$SW$s(bQ+>U5YVCvt;8I}%C#6&Via7l- z|Cu(2ihF;ZTu!b87+HWI*x1lmpRozT$DnZn4KfzA zD5|?a&0b{{F*|Tfch}{6#JM4g2cVkhC7zpf|PBh+5N$y+Ro-nVkSCShCTe3G#2;XP7^x`jxkYY zjYL*3o^E%_@EKOp%pz{OVZ{pr#2whKEw*`NiHBB9rpr*Pw)i_C9gn2i;v8la-|ssz z*iXw4^&_ypz&;a$7A9zDY)B0EOepqB7Jka^XYBr*-6!lm&9qtEyJU)IZ^l3`GF)8z znr0R&zPR_YrQNXmoeX@*AYVtA9i}h)Ed#$}_f_fVPZ2RAr2<(mT8gV@&B9y4`ovN{ zaj9*CKa~8VW!0i@+uen~W8v@F{X@I|al3zFcT=%@zi8plkcr~nUnmT3(Xu`R{mAZr z(eA%y_rIKJ)Bk0Vzh?LU*Y1Ballr#|@^|e1>vsQpcK?TV|3`NJ4ZHtSyZ;Nj|EAsl zt=<2F-T$NA|FiBNM0W4Dd%^A}?0(AbKV|pF?LKPvlID{So?;(nupe2oxq&fD?;n#n zbfkFsctpScefJ-E>w7Y?-5NJ(@BZ*OEZO~``!9;S-!abbnr)})?x^JAhgyVL=p%&+ z+Tqh*P$3$*wsbUEWPb{+s)5307^ck-YGhO}I$SfD>0TzHvB7~tI*??}WQUH#;Cs4# z=Qt7*mTUk%cuu!7C#2c~_%UgYG@2hyN0w5ajPfUrWzgpak5iXVZ05->IEx=lKpx_Z zuWVgX%4tYj++pQq>wBhPpLX4Gu!sv`^QW$u$Lz(rw5sPoSCAShr;o_f2L%tMHkl8=eq8LX&{#4 zGt5(}@dK?xZC%J5nmd^V$e5*qDMlWE)|yEc+wr!{Lu^#AD?lRM>gc&G1lDxF0z5dMiFY_3J!sjD9e)}k|&}?mZ8X!a^(OW;_SmB5HYw>J|>!&mT210Ld19XFEC&N zzdi%oERXLZdTgMx@TQa4KN488?q@TDHnEERpSd&w7B+@|X8F~(%I*0LqD!P0z|37H z{tArHKPo|s{E%3rca7)|kR_MVM(Ag*wse(mof#CbVh=fO{jc4I0o`hc18=B0+*r*aaiKnsS zgGUhVc&He&vmkEuS?xcVvEp7tW%Lal*RpT#--SgFAqN}Y`z;SssBh?$83+h#FeX^D zU@^SG2skx3(AQV|;M$lvLAdCSz5j%jMz#0;6O9_`>thHKx(TXHd1lh-}L>w!};9kXdH+Rdt!rIp>X7zxn~ohQlqh)s)=GIe}8Be~;NlB=)EU$XKI>cfJ5 z-JmX~3yo~e?;$RQ4`xf5SqSPi*^~dew$Y zN2@r^c7+EV3Q#Z$Mz49OHbOHjIi{m0hcCu&SWeeBK1`ABuzExbst;<0LDyh31fJww z2AA}N)zV3uDc=Om29XmdQQ9&}Xe*A}j1LZA^<&M)bJwxrWYRTiR{t3m%*x-k{3o!D z5)L^!E{4aN3CLM!vfoHZj-4&5QSVslok9UJM#Uk!@JKEivY&a3`5aP> zp8&#b=-avIy(PYOR;pE3ntTYV#COJBVyjec@~dkG9KSWcRI2kcLJ#5+-=F3ChpiId z)@qdAn7w(Uq^}%}mloQkO1WO*189xXX1QM7+OF}lE>J10$90HS9P(4#Kh&& zkID5+E_!NmYI-e>2oVouVR-N6~I)eZ-vzccA@n;l0fD z^%wII3xectw;#8#=(T7OccItt482Qe!8}ZtdCC*^w&DKY{r~2_a6}j#B_w$alG2c!LzrODR%^XNt1IBQ!msqt$I{>Ro+{>g z>acBk(fUMh2+5&t+g$Fl{rxC9;>oo2MQ8r*9#KDJ`{R=3nWgtNhV<5negj9p^P>Jv ed$K#9%KP7chv2|OJ~{!~F8;j#`|p1}4*WOCIK>M9 literal 138752 zcmd4433wb=l{Q?uRbAaGNw!;(yX7Tr*|D8UcT2XVEVi>bAqiyPgY4`MNr*{OrrQa@ zr4~wt9Vb8-0vNJjaM<^CfMFeAU?z;&w_q6dWq=uGSZ7fF_dVxUb+sgiFyHrl&)<(! zb?>?7o_p@O=bXD%)j8W<;<%3Ec=&(xQOEfp?)+_$>tkQ0k-VVtp#{!+yB}Wp!LG9( zUU~6TZ)^_lY(zISuDN;m+G}pPCE7K-{kq}Ct+x!{c+2pq=Up^>bM%z!M*I4L)t2=6 zr#a5qU9R)tjo&ysDeZfXS=rN7aGXKoIJoh5{}{r<2yDTf+%b$G`Q|UVJJSFX1wYr> z@*KxmB!BI@jVg+BHt3$m@D}5IBPC)JdAr&;y_x9a4i2ZROO^uSPs(H--F4mVyAXeU zKbS?D)YbBxpaFdKXrtM<769Q5JUTuirB1{x;C{4m-Axe?g;((G5M}usyi)+}_)Sx; z_>ni`@s8$^_aW`V|cX447 zBW_D#j=SDCi4vG{3%Nbqkj*mWx&6ijm&=!AWcK8XcH-3($3m}rpT zF%yEcA0EfZ3r)<-^#Nm|0RUP(L@X)An2~DFde_-(#cN_v_C_`&WtLlvn|J}P^`hR* z)N-&89fr%n0!R_#k*ec#fqw%dIdX$q$^hsd3A&J%%^CPTc{f~vjJv=~SFf2Q-9kQu zG;4vMAO9}MIETtN{5bNhM1HhV(XAKUThTCP#FVPdlTh)%xVs4Oqan&g%JCe?h(4!i z0?&8*yQ1TfR?p?i7v`(E(uIBmdVwp~@c}=gSY5e>tB_C!?Q#|T8V4z~`{FRKf$4W5 zG?O&NTHHg(%C8<1qEz3w(fv>gD4ZKgT7_wwCCxQn^gu@<%FiY~*pYZR6CG#Sdd~qn zuo%>Ps0nBg2sz)9I~e$N-;Y)!A=^$1%T9o7&eExVFb{2-miy8vw2egNzH|yoB~iIA zomy<8a(}1+71|lD0VhqA?}tY)v<RL#TRs7~*E4%a9fUKd7Fm5I4F! z1)(m+fp*cg6ipNI2?9UdfOt=~68Wm?THfhiq;+6E2)QGl8;;G*2%IEuP}IBw>$@E2 zp#$SBng|tOnIp&w*(Pn9O>@IhNn8f~W|^?`qFJJH_rrCMQD(vEwq-Ie?4UER8?K)( zb7EIPzw*1nG*2f3cQzoHouWkIyUd7ig3a#gwtjtoHGjngtHXH7MFrg zxUiy@1W9;i4{WFlO5TT-TkBV!YZ{kir=U%{N046hQPasG92gO+7S{ph(Lk zgM~mpf(~r;0WU(iP*C`e63TQ@92zC)HE|hH55~%9U!mUHUGIkPpw*VEh3;!$za@lh zHoZk?vLHg+1U9?gvS3sRJp)<*DDc&uCt=sKgh8`ZMVCUf2!aoqr%=Y=kveiF?y!WS z8*KqJsG)BWL}*~pqb%g3aYWWC@rVhwDupB=CGD^Oc=dNCJc^|pjZ2FH$i^uF(>#Vr z%w&V)y4}y9*|b}cz-CQ=(>a-Jqw9c!(yoI6+jYFqgs=qPG_Ijupi}TeICaEtW*q9} zS9c!*#nt2;HrdVO_B849NlsDQHu1IwyKN1gl|>YJ{w%3Z&&qO6XBD!gq*|_7Y#YMc zh@LB(Zg@Vb8=$|S*H1n|Fb~cX#(ry#OBdaP&0J;OWrvM3v{5-9Sv?)dC{{knlI_PD#?I83jSua6cY7E@oHk1pc9U+)Epu@ere8XlbKs+N*U zic(4?fzL`7v^@v{7RPL$DnDCJ$%Ld&J~R|TQ1C}8v^KpJDilc_{sbs&(=n6)t^xju z%m(3)uy2kfAh6T=DIHD~$}y>&5PwrS-jjBA#hVZ4VM%h9aP&V%}hF8S3#f z)C1ODgz>|b1@*-UfRmuFUu-$3EZgQzR6Pt>#BXYCe?UfL@RPSv$w(?NA(X%$@M^ag zy$H$`^z?Uyu(selcRq$wlf!05Ezmn`;@yOq#7Q z{0i{AZ9=n81ht}XF@-?knu!4A!W@ImlaD_7=)vBiSI+~24k>sRwn*8ra+LMj4JEh7>WN9G4?)bk`4Zp zSkNQCB=Yy1qaX=**JAT4=&=Xu@1K7R$#-Yn@!u6)ZSrUF*E*tG>{2GSPL>B@7 zDC3$26kDxc`ifFe>o=~y*Y(R2d&3(+(I1)!e2^LYskFawFa&Vmyy53*G(EM!ytD*o z4phLrPzCk*w%CVf6>G~aJI9`@<^IZxVI~1&c^!oYXB$KqtoUAx-ihGrJHR^3Fd;mz zU!5=S;`#Fu+>!TEbTT1n+gY8+3RbK$VEQ-LiL5+y#@2W`+ed~FbYCL{?^YTPy9Q58 zDAHD_&TfSrC}m_YX%vWzo=IBN3h4`3Az?nKZ8PE=b8XT#o>PXc_oJ<~Kd}9T_)>OW zhwM3e;O+C$GYo0Zv98#-1NF#jhk)LWotgUFjW1w*)$O8xxjA*z{eI&)iEgqh8bX(W zu8MBim1(NQpWoYml*c5%%)V=7*%$!>O1Y;O?)6OH^Z+>_|i#w)4UFW%6C!na^Y~q3l65D786-Q)<(JkP}|slE%& zC}>sMzDu3WkCJ9doJ}8{P53+r2o6X6%rDuiJs%MG3yv!v0L=la$Y0an|B?mKVCwVr z_obfNX(lFj`3TN5=q+eR-|n)}Kc9+(YcgGSK{}5lVIs(vCwf5qMc{Po-C&ly#^4ph z;(5oC+6}fDv)y2z-5|*nB3{`I=A*k2>MO_%ZLa3MNdW4c;OTU!+G&aC$9I0&I{p_ZEqlZ-bJ)m0W{y$Sm1lv5r9 z(@agykKjdv-r7RA%UclYF?rz@QFJcB$WIS0=r=Q^Ve~h)XI9_8#94l{EGcnZqIKN~ ze7YdZ+0z+?vtm>#mPUN0B*W2TQ1@REMW#gHleU2Yi!%g%o8Q1VtGD2`h@qqkGyXR@ z_-cSi)Wjw5OY3MKQjjk;iscBF>PI4etx%aO8^Q}KyoVJ^8G?$DAzgFAy0xw?0kE6x zCOjFAV;u~ni>^Qebk>0QGAq71(FNjQj0hZpvN$^Se)ANx1wPUmnvkymm*)5I8`dG6FOuF*4?`446)--Z653j+4``Ozeh)>ffozhP2Ik}Pn$iT`sJa6eSLYZlG_ zIyBAS&dR=)ygiw`wUjsCS?*$sg}gOkdO<5h4xQ1s!-J4}^ejLJdP)Pm8()D|DE1V4 z_Xf>xK~?&?{T4;lEdq zUY6v2E@OSbe1w?jn6TXCYNEwQ*A(On;j7TV#oqG7KyR_P*mL)dCtZml1K9S!Hik68 zKwoKKLG6ZOUva_S0k8QTkQ>MsF|BK{wTgLZwCIH_?)YMU#y^;FHjrcVyGii_7%N)r zBolgx05c$8c~}4*78Dm0`!Gg-soUr>Skc@=vR7a?1YMwKrjEpQq&PU^-w&pncOh|_ zAc41zK*(*Jlw=zy6bqZ42OTk(xxjS?rM;~+q++Axy{)x~R^7%+lPqfn3Y*@J_Gx~P zmF!M1k&&3i?qZ?w1K^hLIt-0Ju&}tWWMZc5D=v&)j1pQ@OjCr=|23&~>+mG!FOah& zITe?hD!AV#?n{_`b%Oi*HttK25Z%L6YO!Ph4_bMtGAhvLT2ZkAf6EH|kQE4uK_|zH zii=7IXf@%>KyY7ik#a)SH^pGa|4}E`%srcH+JfNzxPxmm1y7_+^FZ1(1PNUEOq@e< zztY6N2ZnVLv|zQ%drkZ&mJbEV(ja=i$nC5!r(NZqDm#F6}YD`)~gXailNmvL`_&U#3dWs|EX9^hUs%BzKwm=)5T(lQ7Mm9F?XqTKT z=F*aLY00@E*K(87@{U8s-MQ%1xP_Y_@R3s*p6Bdbs_bKF14Nj(ujrSPiuglGMf@cR zIX^?L+iko8G!#juJeAdhQ?CJ)(p{I)ncjzBiyF}_dQm@4?-6W0IBG+z(M^h$)#UwW;F5HsN$ zaCM_M5_hi&-$Yoc^=97Ux8Pce-pcUg+i;y(48vQ7fA-1f#<`DH?004sqhibY9TUTY zA{#SD@4%(?PF(t(n77ipqx&%rm+%a)ppks$u0lLnjzt(3vhXzYN{6=U0Ez_yBa?gzrbeQiDCGLXmBpb(47b0faEW z{vd8*8OyhNus|;0`?kY&apIU52a}dbYt0% zIx+s!a`j9LD_|b*QNXZykaP;j%XtgBdudZN-hhce1{_gN+0fwp+Qc6RZ0v{Z1UM!~ z-|q~w5BLPYn0~jIj0IihH2#eLN!**C!X^9%T-v3vth108=1|nKK8^I*Wqk&)u^(cx z4PG+o<*H7djNG4At1D=TO=UOC0);@=OhBY)!A`6)C z=aHypsr95>Frp|n{|O1CNd!{)=ME~+mOmwSMU53TUw0&CGmL49D0=iT;`K#ljkFES zi%nEUd;EBA_SJK8yW{iZl=iq9e2Ps9U02G_n%o#BMUeL@S8Xy&*;fVX)PW*+;h z<gA zZM_bK2&R*yM5Jp1;Z-ZDbP1$q;C6}%SNpA?jzNQx3=&y9U9Ny()tZ||VgR;&?jJtlInEjBjH14$YG0TEcgY#iq%C^ z8BKG-NigSaCS-_b^)SIkNGbfB6iU@8QyI}5k`6y&(|@7qQZ5=dTkb=o)QPFop%9(a zB{wuEoBJ4JVmJsd{5O_xzX?fcWCtIt>kprrk&4C3RYLRpoCZ;A~ zrgw{}tWo9{nh=)dQxSMaqudP^k55KMy2+D-89I>l6Vk0SNx%35ZlrG%@e47ySpIYq>5>r06$@q1U88IZvyOnFdoD zi+n78{3nt}7H1#|{x4Eiw9Bv`*NH}m9*H9w`xxKBINb@w50kbl88*EFKzB`0zsVP> z;jt`ip)W`1G*YddZyJMOL>DD{@|aJwnfop9_vJ(Q5x;h>Y3xezdJ74ja3^>L#an9{ z-vHi_%((lyOYXkzveI-T!Rr=03-ThZg7hV5U!MC#U(&9_NZB;b&1d*?Ekg+sX?nU5 zDd$w!Cg{J!$)jyfhcuvipzk_0+z|$SLPzp)Osa++iqT-|R0__I&cY0)C-3u^GCBh0 ztN-PESQXcNAW&h(|3$u)%*VZ;6(}zUKHZ_A=I>A)jFY_(dgN!1vZ5loXV8t6PTenN zfBYQeMLiEuM>$}Nqtw0}o$YP@9@Mc)>eWsyU|Z)Yh+*y1^X|TJ-IDI9(;$yx4og0J z{phn0O7sV$*9Mb>!3-3OK@(gYD#(_^*t@%SkS*&v z41OWsqPwKrt}7}%|GC|6r)N;>dTDb4EKRe`n*YKOx#j72nTt{Z{sa!70A~|^k7@ol zqOEffG0p#B@LUEHErDh7NMp>qwP47X@*D?$%S4{c>qdV@-jN~GxF^*~EabcU{16HL zS`#bQ46tbPo^vts^OvMBe;s%%-UYY7^qU3?G|{6-u~=S&p(Zxy6>D&w^e(1jnnf}Z zvfDAA>s*eqM#ygn6280c3_f4Lqj-YpA3y_Uohuk81KB?r8wzjsU187l&9al+? zy%(;|Z7~ZLVMqvzJWU^&TNe_hA`MZJj}9=(Bcbsv2untvQ325qk7uO(o&kP6@*4$! z4n;k<&X;K@#4$!#f}oW%Xa_-CeVOsA{&k71KVG^k{z|%MK2ClsiyklGLkJ1ZFgTO| z|6*G8aIlHrzdx&*1|Lm>e|VIO&_Ssh3|5ymz7GLHl|<-aADf20>m|sYN4qR^8b76k z7f||s<5vu?q7E;~o)qbAd=7n*uWopu6D|by$jJySVqgsdMFy55(9ggC$o>YTG=~tc z0#qo>0j-|}awijS5<9f&|`y{c&Pnkzj+Y#U@DL9oP#3U|*SFFHW%u5_kvp z@x;C=!7ioP1PQzY`+8zuonYfoljVdUfhXATNIM%ZB=$84_7JhbPB2Z7zz4%#k%?e` zi`d%}>?J8SK>|;(*Y|+-iMUK%n_w>`Hkc2l2@?1qpOJ!|@Yt6a#}xWSmG?4YgZW^Z zAb}6^U@WkoLfVt0eO-dRoY-JKm?lWzQ`aYnhcOYn2GaxyoDW~sFv3Pk^^Bwr&42~3!G5k^%*(j4@rGU; zZxg%_A`2J_K=g3jM)u*nMQ)~q0lGbJVVbJ}Z=rX_$ZZXR1BKer{e=+HUh)K>Bei=6itg^L-3X9cm(D6WsIA2rS{BW*T7=s9 z^+6L84N)o*Zlg#BmJt3T2nSihIBy5FF*psj{ZImh0!rYdk!uG!Z<=BUjrvNF!Q8T zx`Wl^EN`zfx>?KT+0A=U&U%#N4PKzfH}O259QNm0s(l0x-6x*U5J~%DShCJ);}owd zrB_?m@2OJe3BeP5P#{0T@oSt{lLgv(pO?q!Vx(PA?gO`;%IzP)t(TP>&WT}QqT}^b zo#UsKU#@?GR|owU`PG)thX(Q3#?h=dn1+JVAW%B=R3Ff~fJ^Q14QMxc9#jGVJT(DG z0Dv14fCP>)q1J*zP8SVPKF6sTNXyTJP-+}_&;ze9Z9EIeN}-$m0F>XGWdanBZ*r|; zz^uXM^s%^C&onXPZnP2CJ*fCHf|%s)XDq_bY)~CNz_55APL`RBhc>umfo%jdzs%+! z>-MaUbLcGzpE1U(UgofB2_8s5^aJ9}T8vsK>I3?1u*|dGhH=CgWM3J+3uL=6S#5j* znK5B)d{*v5jW5c5N#omcU)uPQ+?O?eE%)V(Kg#{EhTF${D;nK$uXHySY9MG}BOfW1 zp2ji_^fp#%ps#U+1{O3%G_bI7tOgb}PS!xNah3-98<%KcpmCK31{*hOU~!|Vfl>oc z)UvE{<9QkwYP?hfOB%1%z|zKk4J>QCLj%hj@6*6xjgM(yMdNcCs5HJTf$5u}N6q6P z!0B5M8k~+8$E+xre!9dPjQ23MmcHu4CGe-=I)=cLh{;0?>`hfR^|DOSqg3s-Xj*p%Kv zm)Io%CwaaptVbs@^(0&{OI{5F--2L|Qea*4(a8YdOlnF6IHv$K@?~`b=cO*IpbPNS zO35ER0cbpiTf>h0?;t%{T#rrzw4kc|Ca^9#tJR^HVKdf`gl5B5Bfgg7^ z1pyX4NfRhjGu6aZ#@(=cO`j%6;DRZ03a-D*W(k+tlHM8Zl7YMSu)&VrevXq zj>|!JWb0g(I``x&my8Da%B`cheC77>BN`{6Dk_xBgQYSB{bDbA7d9In2a*O+G#O0< zy3g#&{Qqc{(H<|AqcfPvzx&401{?t^q5*FO8_V|dQtj`WS7&u3vycrA z+j=?O|GEctI0p2aI5~x7C(|P4)GkyyubIw9rg||8IfrC4H9S{1896aL4}s`>T(GnA z2kO!V2#5XPZR*yfaiF?5lMMJYK>`m4fDvS<`)himOMp^409ChF0F zxG~ki9=Bba@q&ND9@Y)Olve=1w1+VO(|Q8<)IE#=m{tV9FYaLsz*GnT-YDJyz_gYC z-n@q~08P44UW)-g`}SCGH{mCvGa0u}O3l;?wjWIIJRLFHf%F)qq#W z6r@k3E}goDu+iprW|1&PUe^+)>*erEe9r~O>`wvEjjqF$4|~C*>cKwOYhDi+#?m+7 z=EqOP6_3~7h}+ug(&i4_cmF@Tz0fqDh5}n;#e_HE+Ps-@@~*3r5M#37dkcYHE8=Zo z*Ni+_DNmQQSO?UfV`Auv{OrO07KCb=JCWX+k|0(Hg4VMn_)U12)*TFn4bsGRUK97` zE?%(S?6>Y@Vh8wV1W!x$TY(m$0NYfVZKXmdZhjpf8-Dtd+l$w_oO zgD9q#eZZ&S3Ejps&|Wf%2%m{W>_JMVYV%s8VmrCCG{nSQ_9pkROg<0o$@wZ)9zuHD zW%eDaOwLxG1MXzDB7uD-rVQO^H&_~3VnSBQjbf>Yq?DscM9|OY_>c`458@ierCwFSg8?Nt*>u3jTb>+_M``mWo-@nBD5hl z`aFnnm*o>#k#d(sYc4#vt>;>1IWK%7%Hz-S`aC4nH+9H>AeXx=eo_ZQG^~i+=I~pT z758q8bB2<1_)Z|14`Vq_MZuEm9F`nrVw#7%FUrKvMlIz0GxsO_MO`i&bcR>eQ`dp2 z>H8ww5H8ZP6AR69rU0GXV(=Bzmnv8v;XAUJOmLYclOe-^JZls93t@NUsT;LsFkt}KUL z84l;;O8X`91>O9s`8r`fzOIHea7yX_jIXarzv)lCnhi3?N6?ALQAPR{te?tF{H#7} zjOxI@%yKzdNkG@Y1dQoXzd(cb$=oR4S zc*u7!7{p;((Qk~#y!zpqsg6BDX0l0WT~D)8*qWSOjqdrXq5Pf?e!&ICDXit%TA1)BG*m!q62aT!jL#?L)ZRn3*T{#< z)udJLJ0#Y8t*ShoYk8Ww|InGySSrWA#3!0HM0c-qQqTD*TH^$%?`$E}#?jM~W@R{% z8vbSVSi|$Gi-W~Ii+dOM!JW@0xn|2dsh%p^@&wjP&}I9Zpy`f3JdNwvk=aa3>^bx` z%HLr|=ca073lD2bs0oyviIFXJ2#SYmlNer^Ec-(4^U#VQRe0#p~tg9wEahE5! z-HXRJsHFYM!mBF1g1mhDL}6|o@M|sJW;pDsO26PEn`A(~?s@X{Ci&Q(ruy{2|80G8 z9X#{J=f+__vm5_%Dn}_O^^`D=$2pNKhJE4y2S#$0_3Mwpwfndqp|ubg-g=sg5c*nY z18C==uYj)GdKx0mpYi`j{BK-}7{HgTuj6|5*3)tT{t5rT1Nsl`J*QbOISwO3XCoCK zxR-A|4SksNO8mbY5dOc#hEKtr-F5=M9pR_qAGvPPT&obn$TI!kY~$!qoKNGQoix+2 zmf>u~z}hJV8{dH2VZp`+aa$2=d=+k$?qK6fc@Kh(P%o#_6Kuq|%c=AR8!^guDt*C5 zOb?vOvS1@RSEn)@Y{U%9sjLb%ZsmPlun{XXPUZ4o;~BWi`e(55LTJZIYz}(8zipUmXCSa#39Q&&z$s%( zWT_?crum5Qh$X!(tlJvvY71GO*kW4HiV3WV(mF>9rV?mLm7(p0$|5NKitQ6cuU+U0 zEwpy*JgQa+M&aJtI+{H5(l?qnLqZn)kGgv+0Bdn-?{-|9lXnE11f7rp7L>boah9q* zO^*Oh)erwgOY+F}wD<^M-8%5+AxpPf<8+n7Aa5nmH$YoGFE?aGT(!Vl1 zIy@h^dpwWFUnQe`9%AehwsqXZv$3!A*q2E;C_o-wntD}Qc~!EGX9~W9Q%!t&gWBgO zgi6(_f#5hl@TxgS|pcaWbo|9tpT_blE)M;YVj2M^^{A?uBue zvjsBu0{^r;%d!6f?)>k!|Af~TVV@4uH@wWv4bkiSRb6u7DLA+=zH(0kdUSglAUzn4 zd4BfMrJv({x7;d=3v%toHN-5BC#EwAB3n#o1QcQ!gi8g|exu;!WboYlBW#1u_K*&q z7a}3ww1l=l#>{9Z3R}lhRPRM>{L`=B&1x-Ri-D@cn9Ee!}ZfI&P~Dz@$WkyqF4s$WoC)sNLSc?W@X|Rvi^dg8C1LGR~67ym!v$IjRCsJm3&4uV6b6A-% zhYd0t#kU|SE+f8$hY}xUw?2{G6sAH_SFEuA4`^A}UEOPDr5^{p2_`aXh*w3&4I%Tv-&v;U#tqZum;H z4Scy9zKV@x{T=q&tv<*A>QGuB-PoeA% z<5{@JIIXrQuiwj3P+qV7!X2POact7~k&5ia0|LA}!5U5^feCmk`OFB-Tr@;=e{4C<+ z3O1>DtjjG3>XS$iFBwF#KBu(`GH>8$(oO}2r-Kjceqc0w7qcyzSv0IH-az@KW0D$5 zKa+Y;5rOA+316d&BM?NcN|Y5fH%zZhqj)E5l}iq2@vML%o$2}#nV)OoHDD7j_ri5Z zr_tID^hG+(A_7;T{Q7pqwsj|b{zkcce4}FOR2&T9giXoV%XG zwx}Qv*9gcVIwQ#dLm5s<$yATygExam86Ut6vsb|6T-cVr|DjX>;%@C!b6H1ctkX{{ zGtVa~@WZhJ*VXwm@ez~@$<|M@k+(7eAHx*9l!)nX1Bjcx3gT4`dSnaW@J4Nw>sp{+ zY_76(CJEG8GW$yKEi6Mj)5AMNpaZfJ&#VX^DKHy zo46|18m=LB2gIMuPhyroIika#V9r-;u0~7IpO7T{32DNgNHK@!_xKl%jUo< zCykS*`y&iebGTF3=H}#hO>!lWmT~|8V{(zMzA)^lu?4 z%W+vA_``&sqr1mLo8v=nnQehQ+_djn0En^w4A+LH_MvP~WK*4bZ9A+wr~dH^z?|P# zZSLGs&@TD#(H^wW2PqQ1o=1j0^`oZl1Cb8d=_y{T1!u*z)U`euprIC~+sYN0oRC64NCO%58N8=iPlpJF2YFl`{#>vCMlDAb7jiF$nwNClOIX7}znJ^+OC= zH#4h8yh3_J^6AU_yVQo~&)RwHrgGUh6jXSd@y8OWnV5XCFZ`(Vg+l2scZg6a)d$#_ zb1B;l{fy`)#e_B^RkRt&`GZmjfR3n!eCK?XVJnYgPAm~O?#;JjYCQXfA@DJ9qAh4u-g{gSjXaH@tRl4~1Bd1*JB zh(Y*x7Wly9?#1S~l>;+D4y26t_OS{OhfwunNsFb>PodEI6FFTyit>0dx&qnq!d?{w zl0j^9rz6&*JH(fC!->?ulRlTURP^{{sm&H#!<$hc-wbw=fS8~{y%9n+G2=S-UCX!m zX}(hg^$EOAGF$isG7WDg$us`O4$c#qc$9}TL75z5WkN!b2`NDsQr2LL6!DPst5EY6 zIixI(?Wi2~Lj73s#>^Ui6UAeIkg024Y+osR_4>q2_({xa?NL)tC4};TJ)VZJ zAATB<)ECJt@( zf5c{`w7=43x3OI|*>+*UXctmNyO3PcAQTbom(pRoY))8c+bol2+bovn&S8%D47r|3 zliDss#DXzNQ1}_tO^x^j3TT!Qx6w1Ksu7>qA{Re$L09VkNZ~9nIX{-d2GR4Pu=iuUl?$0RGHk-v6Q^WyM%0Ag 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 Date: Mon, 8 Nov 2010 14:22:10 -0800 Subject: [PATCH 3/8] More CSS updates in the admin. --HG-- branch : dev --- src/Orchard.Web/Themes/TheAdmin/Styles/site.css | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index 687ee884f..03b7e88dc 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css @@ -120,7 +120,7 @@ body { h1,h2,h3,h4,h5,h6 { font-weight: normal;} h1 { font-size: 1.692em } -h2, h2 span { font-size: 1.538em; } +h2 { font-size: 1.538em; } h3 { font-size: 1.231em; } h4 { font-size: 1.154em; } h5 { font-size: 1.077em; } @@ -482,7 +482,6 @@ label { } label.forcheckbox { display:inline; - line-height:1.8em; } .bulk-actions label, .bulk-items h3, label.sub { display:inline; @@ -618,7 +617,7 @@ input[type="submit"]:hover,input[type="reset"]:hover, input[type="button"]:hover background: -webkit-gradient(linear, 0 0, 0 100%, from(#ffac40), to(#f9760d)); background: -moz-linear-gradient(top, #ffac40, #f9760d); } -input[type="submit"]:active, input[type="reset"]:active, input[type="button"]:active, button:active { +input[type="submit"]:active, input[type="reset"]:active, input[type="button"]:active, button:active, .buton:active, .button.primaryAction:active { text-decoration:none; background: #62a9e2; color:#fff; @@ -872,7 +871,7 @@ table .button { padding:1em; } .orchard-media fieldset div, .settings fieldset div, .settings .button { - margin:1em 0 .5em; + margin:.5em 0; } .settings legend { margin:0 0 -.4em; @@ -890,7 +889,7 @@ fieldset.publish-later-datetime { min-width:13.6em; padding-left:6px; padding-right:0; - width:68%; + width:50%; } fieldset.publish-later-datetime legend { display:none; From ade2515bdc3937f95ddc68f648883c22a3c4886d Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Mon, 8 Nov 2010 14:30:05 -0800 Subject: [PATCH 4/8] Updating the markup for the content item edit template. - Includes an additional zone: Actions - Added conditional zone inclusion and more markup so it's a bit more flexible --HG-- branch : dev --- .../Contents/Views/Items/Content.Edit.cshtml | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml b/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml index af834ed7e..08a086a2a 100644 --- a/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml +++ b/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml @@ -1,8 +1,21 @@ -
-
- @Display(Model.Content) +
+
+ @if (Model.Content != null) { +
+ @Display(Model.Content) +
+ }
-
- @Display(Model.Sidebar) +
+ @if (Model.Actions != null) { +
+ @Display(Model.Actions) +
+ } + @if (Model.Sidebar != null) { +
+ @Display(Model.Sidebar) +
+ }
\ No newline at end of file From 68a6f0ca9b56d83a51773299164fd3bfcbdeb67a Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 8 Nov 2010 15:19:23 -0800 Subject: [PATCH 5/8] Adding data migration overloads to do updates based on other module's tables - e.g. creating a foreign key between tables from two distinct modules, was using the same module prefix --HG-- branch : dev --- .../Data/Migration/DataMigrationManager.cs | 2 +- .../Data/Migration/Schema/SchemaBuilder.cs | 40 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 4ddf0ba2d..98d243275 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -189,7 +189,7 @@ namespace Orchard.Data.Migration { .ToList(); foreach (var migration in migrations.OfType()) { - migration.SchemaBuilder = new SchemaBuilder(_interpreter, migration.Feature.Descriptor.Name.Replace(".", "_") + "_"); + migration.SchemaBuilder = new SchemaBuilder(_interpreter, migration.Feature.Descriptor.Name, (s) => s.Replace(".", "_") + "_"); migration.ContentDefinitionManager = _contentDefinitionManager; } diff --git a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs index cfe318267..af73145b8 100644 --- a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs +++ b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs @@ -5,28 +5,30 @@ namespace Orchard.Data.Migration.Schema { public class SchemaBuilder { private readonly IDataMigrationInterpreter _interpreter; private readonly string _featurePrefix; + private readonly Func _formatPrefix; - public SchemaBuilder(IDataMigrationInterpreter interpreter, string featurePrefix = null) { + public SchemaBuilder(IDataMigrationInterpreter interpreter, string featurePrefix = null, Func formatPrefix = null) { _interpreter = interpreter; - _featurePrefix = featurePrefix; + _featurePrefix = featurePrefix ?? String.Empty; + _formatPrefix = formatPrefix ?? (s => s ?? String.Empty); } public SchemaBuilder CreateTable(string name, Action table) { - var createTable = new CreateTableCommand(String.Concat(_featurePrefix, name)); + var createTable = new CreateTableCommand(String.Concat(_formatPrefix(_featurePrefix), name)); table(createTable); Run(createTable); return this; } public SchemaBuilder AlterTable(string name, Action table) { - var alterTable = new AlterTableCommand(String.Concat(_featurePrefix, name)); + var alterTable = new AlterTableCommand(String.Concat(_formatPrefix(_featurePrefix), name)); table(alterTable); Run(alterTable); return this; } public SchemaBuilder DropTable(string name) { - var deleteTable = new DropTableCommand(String.Concat(_featurePrefix, name)); + var deleteTable = new DropTableCommand(String.Concat(_formatPrefix(_featurePrefix), name)); Run(deleteTable); return this; } @@ -45,13 +47,37 @@ namespace Orchard.Data.Migration.Schema { } public SchemaBuilder CreateForeignKey(string name, string srcTable, string[] srcColumns, string destTable, string[] destColumns) { - var command = new CreateForeignKeyCommand(name, String.Concat(_featurePrefix, srcTable), srcColumns, String.Concat(_featurePrefix, destTable), destColumns); + var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(_featurePrefix), srcTable), srcColumns, String.Concat(_formatPrefix(_featurePrefix), destTable), destColumns); + Run(command); + return this; + } + + public SchemaBuilder CreateForeignKey(string name, string srcModule, string srcTable, string[] srcColumns, string destTable, string[] destColumns) { + var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(srcModule), srcTable), srcColumns, String.Concat(_formatPrefix(_featurePrefix), destTable), destColumns); + Run(command); + return this; + } + + public SchemaBuilder CreateForeignKey(string name, string srcTable, string[] srcColumns, string destModule, string destTable, string[] destColumns) { + var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(_featurePrefix), srcTable), srcColumns, String.Concat(_formatPrefix(destModule), destTable), destColumns); + Run(command); + return this; + } + + public SchemaBuilder CreateForeignKey(string name, string srcModule, string srcTable, string[] srcColumns, string destModule, string destTable, string[] destColumns) { + var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(srcModule), srcTable), srcColumns, String.Concat(_formatPrefix(destModule), destTable), destColumns); Run(command); return this; } public SchemaBuilder DropForeignKey(string srcTable, string name) { - var command = new DropForeignKeyCommand(String.Concat(_featurePrefix, srcTable), name); + var command = new DropForeignKeyCommand(String.Concat(_formatPrefix(_featurePrefix), srcTable), name); + Run(command); + return this; + } + + public SchemaBuilder DropForeignKey(string srcModule, string srcTable, string name) { + var command = new DropForeignKeyCommand(String.Concat(_formatPrefix(srcModule), srcTable), name); Run(command); return this; } From 5dfe86f80c1374386a699c106923c3cc77d2e793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Tue, 2 Nov 2010 21:47:55 -0700 Subject: [PATCH 6/8] Correcting data migration code generation - Changing class name to Migrations.cs for consistency - Corrected project alteration to add the correct file path - Added missing using for System.Data --HG-- branch : dev --- .../CodeGenerationTemplates/DataMigration.txt | 3 ++- .../Commands/CodeGenerationCommands.cs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/DataMigration.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/DataMigration.txt index a37519809..8ad2238b0 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/DataMigration.txt +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/DataMigration.txt @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; @@ -7,7 +8,7 @@ using Orchard.Core.Contents.Extensions; using Orchard.Data.Migration; namespace $$FeatureName$$.DataMigrations { - public class Migration : DataMigrationImpl { + public class Migrations : DataMigrationImpl { public int Create() { $$Commands$$ diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs index 63f71accc..94e6fe992 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs @@ -61,7 +61,7 @@ namespace Orchard.CodeGeneration.Commands { } string dataMigrationFolderPath = HostingEnvironment.MapPath("~/Modules/" + extensionDescriptor.Name + "/"); - string dataMigrationFilePath = dataMigrationFolderPath + "Migration.cs"; + string dataMigrationFilePath = dataMigrationFolderPath + "Migrations.cs"; string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard." + ModuleName + "/CodeGenerationTemplates/"); string moduleCsProjPath = HostingEnvironment.MapPath(string.Format("~/Modules/{0}/{0}.csproj", extensionDescriptor.Name)); @@ -93,11 +93,11 @@ namespace Orchard.CodeGeneration.Commands { // The string searches in solution/project files can be made aware of comment lines. if ( projectFileText.Contains("\r\n ", "DataMigrations\\" + extensionDescriptor.DisplayName + "DataMigration.cs"); + string compileReference = string.Format("\r\n ", "Migrations.cs"); projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("\r\n \r\n \r\n ", "DataMigrations\\" + extensionDescriptor.DisplayName + "DataMigration.cs"); + string itemGroupReference = string.Format("\r\n \r\n \r\n ", "Migrations.cs"); projectFileText = projectFileText.Insert(projectFileText.LastIndexOf(""), itemGroupReference); } From ad8c7c536e9135e214a0da2090faf53a6d8a77ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Tue, 2 Nov 2010 22:05:19 -0700 Subject: [PATCH 7/8] Correcting code generation for create module - Added missing Microsoft.CSharp reference --HG-- branch : dev --- .../CodeGenerationTemplates/ModuleCsProj.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt index 1d37c35b7..d56b6ae8f 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt @@ -6,7 +6,7 @@ 9.0.30729 2.0 {$$ModuleProjectGuid$$} - {F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties $$ModuleName$$ @@ -39,6 +39,7 @@ AllRules.ruleset + From 1364a5fcd2773216d6bd395351a961bf1fa36665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Tue, 2 Nov 2010 22:31:43 -0700 Subject: [PATCH 8/8] Correcting themes code generation - "Touching" the solution when adding the theme to Themes.csproj also --HG-- branch : dev --- .../Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs index 94e6fe992..edd77bbef 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs @@ -302,6 +302,7 @@ namespace Orchard.CodeGeneration.Commands { // include in solution but dont create a project: just add the references to Orchard.Themes project var itemGroup = CreateProjectItemGroup(HostingEnvironment.MapPath("~/Themes/"), createdFiles, createdFolders); AddFilesToOrchardThemesProject(output, itemGroup); + TouchSolution(output); } else { // create a project (already done) and add it to the solution