From 754f0703051e5887659239cef9f7f01ae3c81ae7 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Tue, 26 Mar 2019 12:21:21 +0800 Subject: [PATCH 01/59] Update entity.cpp --- kbe/src/server/cellapp/entity.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kbe/src/server/cellapp/entity.cpp b/kbe/src/server/cellapp/entity.cpp index 1fef9950dd..e4feb4727d 100644 --- a/kbe/src/server/cellapp/entity.cpp +++ b/kbe/src/server/cellapp/entity.cpp @@ -1487,7 +1487,13 @@ void Entity::addWitnessed(Entity* entity) //------------------------------------------------------------------------------------- void Entity::delWitnessed(Entity* entity) { - KBE_ASSERT(witnesses_count_ > 0); + if (witnesses_count_ == 0) + { + ERROR_MSG(fmt::format("{}::delWitnessed({}): witness is empty!\n", + scriptName(), id())); + + return; + } witnesses_.remove(entity->id()); --witnesses_count_; From d1b0c332a0fce998e1dbf711aa5ff0d349392159 Mon Sep 17 00:00:00 2001 From: chenlinyan <874499648@qq.com> Date: Wed, 27 Mar 2019 16:28:49 +0800 Subject: [PATCH 02/59] =?UTF-8?q?#=E6=9B=B4=E6=96=B0=E6=8C=89=E9=92=AE1118?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Engine/ClientSDKUpdateUI.cpp | 63 ++++++++++++++++++ .../Engine/ClientSDKUpdateUI.h | 19 ++++++ .../Source/KBEnginePlugins/Engine/KBEMain.cpp | 50 ++++++++++++--- .../Source/KBEnginePlugins/Engine/KBEMain.h | 4 ++ .../KBEnginePlugins/Engine/KBETicker.cpp | 21 +++++- .../Source/KBEnginePlugins/Engine/KBETicker.h | 2 + .../KBEnginePlugins/Engine/KBEngine.cpp | 1 + .../Engine/KBEnginePluginsPrivatePCH.h | 64 +------------------ .../Source/KBEnginePlugins/Engine/KBEvent.h | 11 ++++ .../KBEnginePlugins/Engine/KBEventTypes.cpp | 3 +- .../KBEnginePlugins/Engine/KBEventTypes.h | 1 + .../KBEnginePlugins/KBEnginePlugins.Build.cs | 43 +++++++------ 12 files changed, 188 insertions(+), 94 deletions(-) create mode 100644 kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp create mode 100644 kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.h diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp new file mode 100644 index 0000000000..34e7199aa2 --- /dev/null +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp @@ -0,0 +1,63 @@ +#include "ClientSDKUpdateUI.h" +#include "Engine.h" +#include "KBEvent.h" +#include "KBEngine.h" +#include "KBEventTypes.h" +#include "SlateOptMacros.h" + +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION +void SClientSDKUpdateUI::Construct(const FArguments& args) +{ + FTextBlockStyle textStyle = FCoreStyle::Get().GetWidgetStyle< FTextBlockStyle >("NormalText"); + textStyle.SetFont(FSlateFontInfo("Veranda", 26)); + textStyle.SetColorAndOpacity(FLinearColor::White); + + ChildSlot + [ + SNew(SOverlay) + /*+ SOverlay::Slot() + .HAlign(HAlign_Center) + .VAlign(VAlign_Top) + [ + SNew(STextBlock) + .ColorAndOpacity(FLinearColor::White) + .ShadowColorAndOpacity(FLinearColor::Black) + .ShadowOffset(FIntPoint(-1, 1)) + .Font(FSlateFontInfo("Arial", 26)) + .Text(FText::FromString("Main Menu")) + ]*/ + + SOverlay::Slot() + .HAlign(HAlign_Center) + .VAlign(VAlign_Center) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .Padding(20) + [ + SNew(SButton) + .Text(FText::FromString("Update SDK")) + .TextStyle(&textStyle) + .ContentPadding(FMargin(30.0, 15.0)) + .ButtonColorAndOpacity(FLinearColor::Green) + .HAlign(HAlign_Center) + .VAlign(VAlign_Top) + .OnClicked(this, &SClientSDKUpdateUI::UpdateSDKClicked) + ] + ] + ]; + +} +END_SLATE_FUNCTION_BUILD_OPTIMIZATION + +FReply SClientSDKUpdateUI::UpdateSDKClicked() +{ + if (GEngine) + { + GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Yellow, TEXT("Update SDK!")); + } + + UKBEventData_onDownloadSDK* pEventData = NewObject(); + pEventData->isDownload = true; + KBENGINE_EVENT_FIRE(KBEventTypes::onDownloadSDK, pEventData); + return FReply::Handled(); +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.h new file mode 100644 index 0000000000..02e04aced4 --- /dev/null +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.h @@ -0,0 +1,19 @@ +#pragma once + +#include "KBEnginePluginsPrivatePCH.h" + + +class KBENGINEPLUGINS_API SClientSDKUpdateUI : public SCompoundWidget +{ + +public: + SLATE_BEGIN_ARGS(SClientSDKUpdateUI){} + + SLATE_END_ARGS() + + void Construct(const FArguments& args); + + FReply UpdateSDKClicked(); + + +}; diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp index b98bd5831f..2632151396 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp @@ -67,9 +67,7 @@ void UKBEMain::BeginPlay() pArgs->UDP_SEND_BUFFER_MAX = UDP_SEND_BUFFER_MAX; pArgs->UDP_RECV_BUFFER_MAX = UDP_RECV_BUFFER_MAX; - KBEngineApp::destroyKBEngineApp(); - if (!KBEngineApp::getSingleton().initialize(pArgs)) - delete pArgs; + KBEngineApp::getSingleton().initialize(pArgs); installEvents(); @@ -89,7 +87,7 @@ void UKBEMain::EndPlay(const EEndPlayReason::Type EndPlayReason) delete pUpdaterObj; pUpdaterObj = nullptr; } - + ClientSDKUpdateUI.Reset(); deregisterEvents(); Super::EndPlay(EndPlayReason); } @@ -105,6 +103,7 @@ void UKBEMain::installEvents() KBENGINE_REGISTER_EVENT(KBEventTypes::onScriptVersionNotMatch, onScriptVersionNotMatch); KBENGINE_REGISTER_EVENT(KBEventTypes::onVersionNotMatch, onVersionNotMatch); KBENGINE_REGISTER_EVENT(KBEventTypes::onImportClientSDKSuccessfully, onImportClientSDKSuccessfully); + KBENGINE_REGISTER_EVENT(KBEventTypes::onDownloadSDK, onDownloadSDK); } void UKBEMain::deregisterEvents() @@ -112,6 +111,7 @@ void UKBEMain::deregisterEvents() KBENGINE_DEREGISTER_EVENT(KBEventTypes::onScriptVersionNotMatch); KBENGINE_DEREGISTER_EVENT(KBEventTypes::onVersionNotMatch); KBENGINE_DEREGISTER_EVENT(KBEventTypes::onImportClientSDKSuccessfully); + KBENGINE_DEREGISTER_EVENT(KBEventTypes::onDownloadSDK); } void UKBEMain::onVersionNotMatch(const UKBEventData* pEventData) @@ -134,7 +134,43 @@ bool UKBEMain::isUpdateSDK() void UKBEMain::downloadSDKFromServer() { + if (GEngine->IsValidLowLevel()) + { + GEngine->GameViewport->RemoveAllViewportWidgets(); + } + if (isUpdateSDK()) + { + ClientSDKUpdateUI = SNew(SClientSDKUpdateUI); + + if (GEngine->IsValidLowLevel()) + { + GEngine->GameViewport->AddViewportWidgetContent(SNew(SWeakWidget).PossiblyNullContent(ClientSDKUpdateUI.ToSharedRef())); + } + + if (ClientSDKUpdateUI.IsValid()) + { + ClientSDKUpdateUI->SetVisibility(EVisibility::Visible); + } + + } +} + +void UKBEMain::onImportClientSDKSuccessfully(const UKBEventData* pEventData) +{ + UKismetSystemLibrary::QuitGame(this, nullptr, EQuitPreference::Quit, true); +} + +void UKBEMain::onDownloadSDK(const UKBEventData* pEventData) +{ + ClientSDKUpdateUI.Reset(); + if (GEngine->IsValidLowLevel()) + { + GEngine->GameViewport->RemoveAllViewportWidgets(); + } + + const UKBEventData_onDownloadSDK* pData = Cast(pEventData); + if(pData->isDownload) { if (pUpdaterObj == nullptr) { @@ -145,17 +181,13 @@ void UKBEMain::downloadSDKFromServer() } else { - if(pUpdaterObj != nullptr) + if (pUpdaterObj != nullptr) { delete pUpdaterObj; pUpdaterObj = nullptr; } } -} -void UKBEMain::onImportClientSDKSuccessfully(const UKBEventData* pEventData) -{ - UKismetSystemLibrary::QuitGame(this, nullptr, EQuitPreference::Quit, true); } FString UKBEMain::getClientVersion() diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h index 1590049715..ae56c3eb7b 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h @@ -5,6 +5,7 @@ #include "KBECommon.h" #include "KBEvent.h" #include "ClientSDKUpdater.h" +#include "ClientSDKUpdateUI.h" #include "Components/ActorComponent.h" #include "KBEMain.generated.h" @@ -58,6 +59,7 @@ class KBENGINEPLUGINS_API UKBEMain : public UActorComponent bool isUpdateSDK(); void downloadSDKFromServer(); + void onDownloadSDK(const UKBEventData* pEventData); void onImportClientSDKSuccessfully(const UKBEventData* pEventData); @@ -138,4 +140,6 @@ class KBENGINEPLUGINS_API UKBEMain : public UActorComponent ClientSDKUpdater* pUpdaterObj; + TSharedPtr ClientSDKUpdateUI; + }; diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp index a37637f9e3..532fb57582 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp @@ -6,9 +6,15 @@ #include "Entity.h" #include "KBEngine.h" +#if WITH_EDITOR +#include "Editor.h" +#endif UKBETicker::UKBETicker() { +#if WITH_EDITOR + FEditorDelegates::EndPIE.AddUObject(this, &UKBETicker::OnEndPIE); +#endif } UKBETicker::~UKBETicker() @@ -17,6 +23,7 @@ UKBETicker::~UKBETicker() void UKBETicker::Tick(float DeltaTime) { + KBEvent::processOutEvents(); APawn* ue4_player = UGameplayStatics::GetPlayerPawn(GetWorld(), 0); @@ -47,11 +54,10 @@ TStatId UKBETicker::GetStatId() const UWorld* UKBETicker::GetWorld() const { UWorld* World = (GetOuter() != nullptr) ? GetOuter()->GetWorld() : GWorld; - if (World == nullptr) + if (World == nullptr) { - World = GWorld; + World = GWorld; } - return World; } @@ -60,12 +66,21 @@ bool UKBETicker::IsTickableWhenPaused() const return false; } + bool UKBETicker::IsTickableInEditor() const { return false; } + UWorld* UKBETicker::GetTickableGameObjectWorld() const { return GetWorld(); +} + +void UKBETicker::OnEndPIE(const bool data) +{ +#if WITH_EDITOR + KBEngineApp::destroyKBEngineApp(); +#endif } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.h index 3a7b8dda93..b4e8c2c456 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.h @@ -28,4 +28,6 @@ class KBENGINEPLUGINS_API UKBETicker : public UObject, public FTickableGameObjec virtual void Tick(float DeltaTime) override; virtual bool IsTickable() const override; virtual TStatId GetStatId() const override; + + void OnEndPIE(const bool); }; diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp index baadd72648..71d5efa448 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp @@ -272,6 +272,7 @@ void KBEngineApp::uninstallUKBETicker() if (pUKBETicker_) { pUKBETicker_->RemoveFromRoot(); + pUKBETicker_->ConditionalBeginDestroy(); pUKBETicker_ = nullptr; } } diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEnginePluginsPrivatePCH.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEnginePluginsPrivatePCH.h index 801faac386..ffe7fb40b3 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEnginePluginsPrivatePCH.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEnginePluginsPrivatePCH.h @@ -1,65 +1,5 @@ +#pragma once + // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. #include "Engine.h" #include "KBEnginePlugins.h" - -// You should place include statements to your module's private header files here. You only need to -// add includes for headers that are used in most of your module's source files though. - - -#define INFO_MSG(Format, ...) \ -{ \ - SET_WARN_COLOR(COLOR_CYAN); \ - const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ - UE_LOG(LogKBEngine, Log, TEXT("%s"), *Msg); \ - CLEAR_WARN_COLOR(); \ -} - -#define DEBUG_MSG(Format, ...) \ -{ \ - SET_WARN_COLOR(COLOR_CYAN); \ - const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ - UE_LOG(LogKBEngine, Log, TEXT("**DEBUG** %s"), *Msg); \ - CLEAR_WARN_COLOR(); \ -} - -#define WARNING_MSG(Format, ...) \ -{ \ - SET_WARN_COLOR(COLOR_YELLOW); \ - const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ - UE_LOG(LogKBEngine, Log, TEXT("**WARNING** %s"), *Msg); \ - CLEAR_WARN_COLOR(); \ -} - -#define SCREEN_WARNING_MSG(Format, ...) \ -{ \ - SET_WARN_COLOR(COLOR_YELLOW); \ - const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ - const FString NewMsg = FString::Printf(TEXT("**WARNING** %s"), *Msg); \ - UE_LOG(LogKBEngine, Log, TEXT("%s"), *NewMsg); \ - CLEAR_WARN_COLOR(); \ - GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, NewMsg); \ -} - -#define ERROR_MSG(Format, ...) \ -{ \ - SET_WARN_COLOR(COLOR_RED); \ - const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ - UE_LOG(LogKBEngine, Log, TEXT("**ERROR** %s"), *Msg); \ - CLEAR_WARN_COLOR(); \ -} - -#define SCREEN_ERROR_MSG(Format, ...) \ -{ \ - SET_WARN_COLOR(COLOR_RED); \ - const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ - const FString NewMsg = FString::Printf(TEXT("**ERROR** %s"), *Msg); \ - UE_LOG(LogKBEngine, Log, TEXT("%s"), *NewMsg); \ - CLEAR_WARN_COLOR(); \ - GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, NewMsg); \ -} - -#define SCREENDEBUG(Format, ...) \ -{ \ - const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ - GEngine->AddOnScreenDebugMessage(-1, 10000.f, FColor::White, Msg); \ -} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEvent.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEvent.h index 7c5f2fda1f..2376caeb3a 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEvent.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEvent.h @@ -634,3 +634,14 @@ class KBENGINEPLUGINS_API UKBEventData_onImportClientSDKSuccessfully : public UK public: }; + +UCLASS(Blueprintable, BlueprintType) +class KBENGINEPLUGINS_API UKBEventData_onDownloadSDK : public UKBEventData +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = KBEngine) + bool isDownload; +}; + diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp index a450a2cee4..5f83c2b8a0 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp @@ -44,4 +44,5 @@ const FString KBEventTypes::onStreamDataRecv = "onStreamDataRecv"; const FString KBEventTypes::onStreamDataCompleted = "onStreamDataCompleted"; // ------------------------------------SDK更新相关------------------------------------- -const FString KBEventTypes::onImportClientSDKSuccessfully = "onImportClientSDKSuccessfully"; \ No newline at end of file +const FString KBEventTypes::onImportClientSDKSuccessfully = "onImportClientSDKSuccessfully"; +const FString KBEventTypes::onDownloadSDK = "onDownloadSDK"; \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h index 1ce930ba3b..40ed106e57 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h @@ -161,4 +161,5 @@ struct KBENGINEPLUGINS_API KBEventTypes // ------------------------------------SDK更新相关----------------------------------- static const FString onImportClientSDKSuccessfully; + static const FString onDownloadSDK; }; \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs index a524d68b05..2d50e031db 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs @@ -1,5 +1,6 @@ // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. + using UnrealBuildTool; using System.IO; using System.Collections.Generic; @@ -13,18 +14,22 @@ public KBEnginePlugins(ReadOnlyTargetRules Target) : base(Target) bEnableUndefinedIdentifierWarnings = false; string CryptoPPPath = Target.UEThirdPartySourceDirectory + "CryptoPP/5.6.5/lib/"; - string[] PrivateModules = new string[] { "CoreUObject", "Engine", "Slate", "SlateCore", "Networking", "Sockets" }; + string[] PrivateModules = new string[] { "Slate", "SlateCore", "Networking", "Sockets", "OpenSSL" }; + string[] PublicModules = new string[] { "Core", "CoreUObject", "Engine"}; + List PublicModulesList = new List(PublicModules); + + //if (Directory.Exists(CryptoPPPath)) + //{ + // List PrivateModuleList = new List(PrivateModules); + // PrivateModuleList.Add("CryptoPP"); + // PrivateModules = PrivateModuleList.ToArray(); + //} + //else + //{ + // // PublicDefinitions.Add("KBENGINE_NO_CRYPTO"); + // // PublicDefinitions.Add("_MINWINDEF_"); + //} - if (Target.Platform == UnrealTargetPlatform.Win64 && Directory.Exists(CryptoPPPath)) - { - List PrivateModuleList = new List(PrivateModules); - PrivateModuleList.Add("CryptoPP"); - PrivateModules = PrivateModuleList.ToArray(); - } - else - { - PublicDefinitions.Add("KBENGINE_NO_CRYPTO"); - } PublicIncludePaths.AddRange( new string[] { @@ -39,14 +44,14 @@ public KBEnginePlugins(ReadOnlyTargetRules Target) : base(Target) "KBEnginePlugins/Scripts", } ); - - PublicDependencyModuleNames.AddRange( - new string[] - { - "Core", - // ... add other public dependencies that you statically link with here ... - } - ); + + if (Target.bBuildEditor) + { + PublicModulesList.Add("UnrealEd"); + } + + PublicModules = PublicModulesList.ToArray(); + PublicDependencyModuleNames.AddRange(PublicModules); PrivateDependencyModuleNames.AddRange(PrivateModules); From 4bdfddd944438e679fc535a580252606964190f0 Mon Sep 17 00:00:00 2001 From: chenlinyan <874499648@qq.com> Date: Wed, 27 Mar 2019 16:29:20 +0800 Subject: [PATCH 03/59] =?UTF-8?q?#openSSL=E5=8A=A0=E5=AF=86#1115?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Engine/EncryptionFilter.cpp | 62 +++++++------------ .../KBEnginePlugins/Engine/EncryptionFilter.h | 60 +++++++++++++----- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp index d164861dd2..0fa127b160 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp @@ -5,31 +5,26 @@ #include "PacketSenderKCP.h" #include "Engine/KBDebug.h" -#ifndef KBENGINE_NO_CRYPTO -#include "cryptlib.h" -#include "rdrand.h" -#include "secblock.h" -#endif - -BlowfishFilter::BlowfishFilter(int keySize): +BlowfishFilter::BlowfishFilter(int keySize) : isGood_(false), pPacket_(new MemoryStream()), pEncryptStream_(new MemoryStream()), packetLen_(0), padSize_(0) { -#ifndef KBENGINE_NO_CRYPTO - key_.Init(0, keySize); - CryptoPP::RDRAND rng; - rng.GenerateBlock(key_.GetData(), key_.Num()); + unsigned char buf[20] = ""; + RAND_bytes(buf, 20); + key_ = (char *)buf; + keySize_ = key_.Len(); + //reinterpret_cast(TCHAR_TO_ANSI(*key_) init(); -#endif } -BlowfishFilter::BlowfishFilter(const TArray& key): +BlowfishFilter::BlowfishFilter(const FString & key) : isGood_(false), key_(key), + keySize_(key_.Len()), pPacket_(new MemoryStream()), pEncryptStream_(new MemoryStream()), packetLen_(0), @@ -46,19 +41,20 @@ BlowfishFilter::~BlowfishFilter() bool BlowfishFilter::init() { -#ifndef KBENGINE_NO_CRYPTO - if (key_.Num() >= encripter.MinKeyLength() && key_.Num() <= encripter.MaxKeyLength()) + pBlowFishKey_ = new BF_KEY; + if (MIN_KEY_SIZE <= keySize_ && keySize_ <= MAX_KEY_SIZE) { - encripter.SetKey(key_.GetData(), key_.Num()); - decripter.SetKey(key_.GetData(), key_.Num()); + + BF_set_key(this->pBlowFishKey(), key_.Len(), reinterpret_cast(TCHAR_TO_ANSI(*key_))); isGood_ = true; } else { - ERROR_MSG("BlowfishFilter::init: invalid length %d", key_.Num()); + ERROR_MSG("BlowfishFilter::init: invalid length %d", key_.Len()); isGood_ = false; } -#endif + keyArray_.SetNum(key_.Len()); + memcpy(keyArray_.GetData(), TCHAR_TO_ANSI(*key_), key_.Len()); return isGood_; } @@ -66,7 +62,6 @@ void BlowfishFilter::encrypt(MemoryStream *pMemoryStream) { // BlowFish 每次只能加密和解密8字节数据 // 不足8字节则填充0 -#ifndef KBENGINE_NO_CRYPTO uint8 padSize = 0; if (pMemoryStream->length() % BLOCK_SIZE != 0) @@ -86,12 +81,10 @@ void BlowfishFilter::encrypt(MemoryStream *pMemoryStream) pMemoryStream->swap(*pEncryptStream_); pEncryptStream_->clear(false); -#endif } void BlowfishFilter::encrypt(uint8 *buf, MessageLengthEx len) { -#ifndef KBENGINE_NO_CRYPTO if (len % BLOCK_SIZE != 0) { ERROR_MSG("BlowfishFilter::encrypt: Input length (%d) is not a multiple of block size ", len); @@ -113,9 +106,8 @@ void BlowfishFilter::encrypt(uint8 *buf, MessageLengthEx len) prevBlock = *(uint64*)(data + i); } - encripter.ProcessData(data + i, data + i, BLOCK_SIZE); + BF_ecb_encrypt(data + i, data + i, this->pBlowFishKey(), BF_ENCRYPT); } -#endif } void BlowfishFilter::encrypt(uint8 *buf, MessageLengthEx offset, MessageLengthEx len) @@ -130,7 +122,6 @@ void BlowfishFilter::decrypt(MemoryStream *pMemoryStream) void BlowfishFilter::decrypt(uint8 *buf, MessageLengthEx len) { -#ifndef KBENGINE_NO_CRYPTO if (len % BLOCK_SIZE != 0) { ERROR_MSG("BlowfishFilter::decrypt: Input length (%d) is not a multiple of block size ", len); @@ -141,16 +132,15 @@ void BlowfishFilter::decrypt(uint8 *buf, MessageLengthEx len) uint64 prevBlock = 0; for (uint32 i = 0; i < len; i += BLOCK_SIZE) { - decripter.ProcessData(data + i, data + i, BLOCK_SIZE); + BF_ecb_encrypt(data + i, data + i, this->pBlowFishKey(), BF_DECRYPT); if (prevBlock != 0) { *(uint64*)(data + i) = *(uint64*)(data + i) ^ (prevBlock); } - + prevBlock = *(uint64*)(data + i); } -#endif } void BlowfishFilter::decrypt(uint8 *buf, MessageLengthEx offset, MessageLengthEx len) @@ -160,7 +150,6 @@ void BlowfishFilter::decrypt(uint8 *buf, MessageLengthEx offset, MessageLengthEx bool BlowfishFilter::send(PacketSenderBase* pPacketSender, MemoryStream *pPacket) { -#ifndef KBENGINE_NO_CRYPTO if (!isGood_) { ERROR_MSG("BlowfishFilter::send: Dropping packet due to invalid filter"); @@ -168,13 +157,11 @@ bool BlowfishFilter::send(PacketSenderBase* pPacketSender, MemoryStream *pPacket } encrypt(pPacket); -#endif return pPacketSender->send(pPacket);; } bool BlowfishFilter::recv(MessageReader* pMessageReader, MemoryStream *pPacket) { -#ifndef KBENGINE_NO_CRYPTO if (!isGood_) { ERROR_MSG("BlowfishFilter::recv: Dropping packet due to invalid filter"); @@ -185,7 +172,7 @@ bool BlowfishFilter::recv(MessageReader* pMessageReader, MemoryStream *pPacket) uint32 len = pPacket->length(); uint16 packeLen = pPacket->readUint16(); - if ( 0 == pPacket_->length() && len > MIN_PACKET_SIZE && packeLen - 1 == len - 3) + if (0 == pPacket_->length() && len > MIN_PACKET_SIZE && packeLen - 1 == len - 3) { int padSize = pPacket->readUint8(); decrypt(pPacket); @@ -267,12 +254,9 @@ bool BlowfishFilter::recv(MessageReader* pMessageReader, MemoryStream *pPacket) packetLen_ = 0; padSize_ = 0; } -#else - if (pMessageReader) - { - pMessageReader->process(pPacket->data() + pPacket->rpos(), 0, pPacket->length()); - } -#endif - return true; } + +EncryptionFilter::~EncryptionFilter() +{ +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h index 1a224f549c..8a5e0861cc 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h @@ -1,14 +1,29 @@ #pragma once #include "KBECommon.h" -#ifndef KBENGINE_NO_CRYPTO -// https://stackoverflow.com/questions/51416259/unreal-engine-4-20-build-error-in-plugin-adaptive-unity-build-disabling-pch-f -#pragma warning(disable:4668) // x is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' -#include "blowfish.h" -#pragma warning(default:4668) -#include "modes.h" +//#ifndef KBENGINE_NO_CRYPTO +//// https://stackoverflow.com/questions/51416259/unreal-engine-4-20-build-error-in-plugin-adaptive-unity-build-disabling-pch-f +//#pragma warning(disable:4668) // x is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' +//#include "blowfish.h" +//#pragma warning(default:4668) +//#include "modes.h" +//#endif + +#if PLATFORM_WINDOWS +#include "WindowsHWrapper.h" +#include "AllowWindowsPlatformTypes.h" #endif +#define UI UI_ST +THIRD_PARTY_INCLUDES_START +#include "openssl/rand.h" +#include "openssl/blowfish.h" +THIRD_PARTY_INCLUDES_END +#undef UI + +#if PLATFORM_WINDOWS +#include "HideWindowsPlatformTypes.h" +#endif class MemoryStream; class PacketSenderBase; @@ -17,8 +32,9 @@ class MessageReader; class EncryptionFilter { public: - virtual ~EncryptionFilter() {} + EncryptionFilter() {} + virtual ~EncryptionFilter(); virtual void encrypt(MemoryStream *pMemoryStream) = 0; virtual void encrypt(uint8 *buf, MessageLengthEx len) = 0; virtual void encrypt(uint8 *buf, MessageLengthEx offset, MessageLengthEx len) = 0; @@ -39,11 +55,20 @@ class BlowfishFilter : public EncryptionFilter static const uint32 BLOCK_SIZE = 64 / 8; static const uint32 MIN_PACKET_SIZE = (sizeof(MessageLength) + 1 + BLOCK_SIZE); - BlowfishFilter(int keySize=16); - BlowfishFilter(const TArray& key); + + // key的最小和最大大小 + static const int MIN_KEY_SIZE = 32 / 8; + static const int MAX_KEY_SIZE = 448 / 8; + + // 默认key的大小 + static const int DEFAULT_KEY_SIZE = 128 / 8; + + BlowfishFilter(const FString & key); + BlowfishFilter(int keySize = DEFAULT_KEY_SIZE); + virtual ~BlowfishFilter(); - virtual void encrypt(MemoryStream *pMemoryStream) ; + virtual void encrypt(MemoryStream *pMemoryStream); virtual void encrypt(uint8 *buf, MessageLengthEx len); virtual void encrypt(uint8 *buf, MessageLengthEx offset, MessageLengthEx len); @@ -54,8 +79,11 @@ class BlowfishFilter : public EncryptionFilter virtual bool send(PacketSenderBase *pPacketSender, MemoryStream *pPacket); virtual bool recv(MessageReader *pMessageReader, MemoryStream *pPacket); + + BF_KEY * pBlowFishKey() { return (BF_KEY*)pBlowFishKey_; } + TArray& key() { - return key_; + return keyArray_; } private: @@ -63,13 +91,13 @@ class BlowfishFilter : public EncryptionFilter private: bool isGood_; - TArray key_; MemoryStream* pPacket_; MemoryStream* pEncryptStream_; MessageLength packetLen_; uint8 padSize_; -#ifndef KBENGINE_NO_CRYPTO - CryptoPP::ECB_Mode::Encryption encripter; - CryptoPP::ECB_Mode::Decryption decripter; -#endif + + FString key_; + TArray keyArray_; + int keySize_; + void * pBlowFishKey_; }; From f2f5ca60d1db820e3c3a07f930a9eee7c9fa8513 Mon Sep 17 00:00:00 2001 From: FemelaNerve3630 <874499648@qq.com> Date: Wed, 27 Mar 2019 16:32:53 +0800 Subject: [PATCH 04/59] Update ClientSDKUpdateUI.cpp --- .../ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp index 34e7199aa2..b3c0d97e4b 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp @@ -45,7 +45,6 @@ void SClientSDKUpdateUI::Construct(const FArguments& args) ] ] ]; - } END_SLATE_FUNCTION_BUILD_OPTIMIZATION From fa700f7df33905e04adb636b9eef5c02158adb9b Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Wed, 27 Mar 2019 17:15:28 +0800 Subject: [PATCH 05/59] up --- .../Engine/EncryptionFilter.cpp | 24 ++++++++++++++----- .../KBEnginePlugins/Engine/EncryptionFilter.h | 8 ------- .../Source/KBEnginePlugins/Engine/KBEMain.cpp | 19 +++++---------- .../KBEnginePlugins/Engine/KBETicker.cpp | 3 --- .../KBEnginePlugins/Engine/KBEventTypes.h | 2 +- .../KBEnginePlugins/KBEnginePlugins.Build.cs | 17 +------------ 6 files changed, 26 insertions(+), 47 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp index 0fa127b160..551b707b86 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp @@ -5,19 +5,27 @@ #include "PacketSenderKCP.h" #include "Engine/KBDebug.h" +EncryptionFilter::~EncryptionFilter() +{ +} + BlowfishFilter::BlowfishFilter(int keySize) : isGood_(false), pPacket_(new MemoryStream()), pEncryptStream_(new MemoryStream()), packetLen_(0), - padSize_(0) + padSize_(0), + key_(), + keyArray_(), + keySize_(0), + pBlowFishKey_(NULL) { unsigned char buf[20] = ""; RAND_bytes(buf, 20); key_ = (char *)buf; keySize_ = key_.Len(); - //reinterpret_cast(TCHAR_TO_ANSI(*key_) + init(); } @@ -28,7 +36,11 @@ BlowfishFilter::BlowfishFilter(const FString & key) : pPacket_(new MemoryStream()), pEncryptStream_(new MemoryStream()), packetLen_(0), - padSize_(0) + padSize_(0), + key_(), + keyArray_(), + keySize_(0), + pBlowFishKey_(NULL) { init(); } @@ -37,11 +49,13 @@ BlowfishFilter::~BlowfishFilter() { KBE_SAFE_RELEASE(pPacket_); KBE_SAFE_RELEASE(pEncryptStream_); + KBE_SAFE_RELEASE(pBlowFishKey_); } bool BlowfishFilter::init() { pBlowFishKey_ = new BF_KEY; + if (MIN_KEY_SIZE <= keySize_ && keySize_ <= MAX_KEY_SIZE) { @@ -53,6 +67,7 @@ bool BlowfishFilter::init() ERROR_MSG("BlowfishFilter::init: invalid length %d", key_.Len()); isGood_ = false; } + keyArray_.SetNum(key_.Len()); memcpy(keyArray_.GetData(), TCHAR_TO_ANSI(*key_), key_.Len()); return isGood_; @@ -257,6 +272,3 @@ bool BlowfishFilter::recv(MessageReader* pMessageReader, MemoryStream *pPacket) return true; } -EncryptionFilter::~EncryptionFilter() -{ -} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h index 8a5e0861cc..eda9263af4 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h @@ -1,14 +1,6 @@ #pragma once #include "KBECommon.h" -//#ifndef KBENGINE_NO_CRYPTO -//// https://stackoverflow.com/questions/51416259/unreal-engine-4-20-build-error-in-plugin-adaptive-unity-build-disabling-pch-f -//#pragma warning(disable:4668) // x is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' -//#include "blowfish.h" -//#pragma warning(default:4668) -//#include "modes.h" -//#endif - #if PLATFORM_WINDOWS #include "WindowsHWrapper.h" #include "AllowWindowsPlatformTypes.h" diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp index 2632151396..57606992ba 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp @@ -70,14 +70,6 @@ void UKBEMain::BeginPlay() KBEngineApp::getSingleton().initialize(pArgs); installEvents(); - -#ifdef KBENGINE_NO_CRYPTO - if (pArgs->networkEncryptType == NETWORK_ENCRYPT_TYPE::ENCRYPT_TYPE_BLOWFISH) - { - pArgs->networkEncryptType = NETWORK_ENCRYPT_TYPE::ENCRYPT_TYPE_NONE; - ERROR_MSG("No module CryptoPP! Please use unreal engine source code to install"); - } -#endif } void UKBEMain::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -87,6 +79,7 @@ void UKBEMain::EndPlay(const EEndPlayReason::Type EndPlayReason) delete pUpdaterObj; pUpdaterObj = nullptr; } + ClientSDKUpdateUI.Reset(); deregisterEvents(); Super::EndPlay(EndPlayReason); @@ -126,10 +119,11 @@ void UKBEMain::onScriptVersionNotMatch(const UKBEventData* pEventData) bool UKBEMain::isUpdateSDK() { - #if WITH_EDITOR - return automaticallyUpdateSDK; - #endif - return false; +#if WITH_EDITOR + return automaticallyUpdateSDK; +#endif + + return false; } void UKBEMain::downloadSDKFromServer() @@ -187,7 +181,6 @@ void UKBEMain::onDownloadSDK(const UKBEventData* pEventData) pUpdaterObj = nullptr; } } - } FString UKBEMain::getClientVersion() diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp index 532fb57582..9c5a1f1cf8 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp @@ -23,7 +23,6 @@ UKBETicker::~UKBETicker() void UKBETicker::Tick(float DeltaTime) { - KBEvent::processOutEvents(); APawn* ue4_player = UGameplayStatics::GetPlayerPawn(GetWorld(), 0); @@ -66,13 +65,11 @@ bool UKBETicker::IsTickableWhenPaused() const return false; } - bool UKBETicker::IsTickableInEditor() const { return false; } - UWorld* UKBETicker::GetTickableGameObjectWorld() const { return GetWorld(); diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h index 40ed106e57..6fd1eca9a1 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h @@ -158,8 +158,8 @@ struct KBENGINEPLUGINS_API KBEventTypes // param1(uint16): resouce id static const FString onStreamDataCompleted; - // ------------------------------------SDK更新相关----------------------------------- static const FString onImportClientSDKSuccessfully; static const FString onDownloadSDK; + }; \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs index 2d50e031db..6dae3152b7 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/KBEnginePlugins.Build.cs @@ -1,6 +1,5 @@ // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. - using UnrealBuildTool; using System.IO; using System.Collections.Generic; @@ -13,24 +12,10 @@ public KBEnginePlugins(ReadOnlyTargetRules Target) : base(Target) bEnableUndefinedIdentifierWarnings = false; - string CryptoPPPath = Target.UEThirdPartySourceDirectory + "CryptoPP/5.6.5/lib/"; string[] PrivateModules = new string[] { "Slate", "SlateCore", "Networking", "Sockets", "OpenSSL" }; string[] PublicModules = new string[] { "Core", "CoreUObject", "Engine"}; List PublicModulesList = new List(PublicModules); - //if (Directory.Exists(CryptoPPPath)) - //{ - // List PrivateModuleList = new List(PrivateModules); - // PrivateModuleList.Add("CryptoPP"); - // PrivateModules = PrivateModuleList.ToArray(); - //} - //else - //{ - // // PublicDefinitions.Add("KBENGINE_NO_CRYPTO"); - // // PublicDefinitions.Add("_MINWINDEF_"); - //} - - PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... @@ -60,6 +45,6 @@ public KBEnginePlugins(ReadOnlyTargetRules Target) : base(Target) { // ... add any modules that your module loads dynamically here ... } - ); + ); } } From dbe2b88a31fe6943754c483aeadb653ef299b134 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Wed, 27 Mar 2019 17:42:29 +0800 Subject: [PATCH 06/59] Update EncryptionFilter.cpp --- .../ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp index 551b707b86..99c4c31081 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp @@ -20,7 +20,6 @@ BlowfishFilter::BlowfishFilter(int keySize) : keySize_(0), pBlowFishKey_(NULL) { - unsigned char buf[20] = ""; RAND_bytes(buf, 20); key_ = (char *)buf; @@ -31,15 +30,13 @@ BlowfishFilter::BlowfishFilter(int keySize) : BlowfishFilter::BlowfishFilter(const FString & key) : isGood_(false), - key_(key), - keySize_(key_.Len()), pPacket_(new MemoryStream()), pEncryptStream_(new MemoryStream()), packetLen_(0), padSize_(0), key_(), - keyArray_(), - keySize_(0), + key_(key), + keySize_(key_.Len()), pBlowFishKey_(NULL) { init(); From 4399e5d4ac0eb38eca0f1e97b423e050993f7cff Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Wed, 27 Mar 2019 17:52:18 +0800 Subject: [PATCH 07/59] up --- .../Source/KBEnginePlugins/Engine/EncryptionFilter.cpp | 4 ---- .../Source/KBEnginePlugins/Engine/EncryptionFilter.h | 10 +++++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp index 99c4c31081..97e4f29263 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp @@ -16,7 +16,6 @@ BlowfishFilter::BlowfishFilter(int keySize) : packetLen_(0), padSize_(0), key_(), - keyArray_(), keySize_(0), pBlowFishKey_(NULL) { @@ -34,7 +33,6 @@ BlowfishFilter::BlowfishFilter(const FString & key) : pEncryptStream_(new MemoryStream()), packetLen_(0), padSize_(0), - key_(), key_(key), keySize_(key_.Len()), pBlowFishKey_(NULL) @@ -65,8 +63,6 @@ bool BlowfishFilter::init() isGood_ = false; } - keyArray_.SetNum(key_.Len()); - memcpy(keyArray_.GetData(), TCHAR_TO_ANSI(*key_), key_.Len()); return isGood_; } diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h index eda9263af4..60c3faefa6 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h @@ -74,8 +74,13 @@ class BlowfishFilter : public EncryptionFilter BF_KEY * pBlowFishKey() { return (BF_KEY*)pBlowFishKey_; } - TArray& key() { - return keyArray_; + TArray key() + { + TArray keyArray; + keyArray.SetNum(key_.Len()); + memcpy(keyArray.GetData(), TCHAR_TO_ANSI(*key_), key_.Len()); + + return keyArray; } private: @@ -89,7 +94,6 @@ class BlowfishFilter : public EncryptionFilter uint8 padSize_; FString key_; - TArray keyArray_; int keySize_; void * pBlowFishKey_; }; From 0c9931962f20d60af49c809031331f3f69e2395f Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Thu, 28 Mar 2019 10:55:16 +0800 Subject: [PATCH 08/59] =?UTF-8?q?=E4=BA=91=E6=9C=8D=E5=8A=A1=E5=99=A8?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E8=B7=A8=E6=9C=BA=E5=85=B3=E6=9C=8D=20#1153?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kbe/tools/server/pycluster/cluster_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kbe/tools/server/pycluster/cluster_controller.py b/kbe/tools/server/pycluster/cluster_controller.py index f1e8649d58..2018872dd3 100644 --- a/kbe/tools/server/pycluster/cluster_controller.py +++ b/kbe/tools/server/pycluster/cluster_controller.py @@ -260,7 +260,7 @@ def sendStop(self, showDebug): print("\t\t%s : %i\t%s" % (ctype, len(clist), clist)) # 最好是尽量多的尝试次数,否则可能包未及时恢复造成后续查询错乱 - self.stopServer( COMPONENT_NAME2TYPE[ctype], 0, "", 3 ) + self.stopServer( COMPONENT_NAME2TYPE[ctype], 0, MACHINES_ADDRESS, 3 ) #print ("ClusterStopHandler::do: stop uid=%s, type=%s, send=%s" % (self.uid, ctype, \ # len(self.recvDatas) > 0 and self.recvDatas[0] == b'\x01')) From edc66a7a8b69e9508cc1ab928f7ec05583063fc7 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Thu, 28 Mar 2019 11:04:41 +0800 Subject: [PATCH 09/59] Update serverapp.cpp --- kbe/src/lib/server/serverapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kbe/src/lib/server/serverapp.cpp b/kbe/src/lib/server/serverapp.cpp index 3e3b1c221d..6baa798cee 100644 --- a/kbe/src/lib/server/serverapp.cpp +++ b/kbe/src/lib/server/serverapp.cpp @@ -441,7 +441,7 @@ void ServerApp::onAppActiveTick(Network::Channel* pChannel, COMPONENT_TYPE compo cinfos->pChannel->updateLastReceivedTime(); } - //DEBUG_MSG(fmt::format("ServerApp::onAppActiveTick[:p]: {}:{} lastReceivedTime:{} at {}.\n", + //DEBUG_MSG(fmt::format("ServerApp::onAppActiveTick[{:p}]: {}:{} lastReceivedTime:{} at {}.\n", // (void*)pChannel, COMPONENT_NAME_EX(componentType), componentID, pChannel->lastReceivedTime(), pChannel->c_str())); } From f3f3c484e36dfe4ca4cbb622c353674b6e6b6cac Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Thu, 28 Mar 2019 14:35:02 +0800 Subject: [PATCH 10/59] Update channel.cpp --- kbe/src/lib/network/channel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kbe/src/lib/network/channel.cpp b/kbe/src/lib/network/channel.cpp index 71eefd6d13..1f2d3f673a 100644 --- a/kbe/src/lib/network/channel.cpp +++ b/kbe/src/lib/network/channel.cpp @@ -498,7 +498,7 @@ void Channel::startInactivityDetection( float period, float checkPeriod ) return; } - inactivityExceptionPeriod_ = uint64(period * stampsPerSecond()) - uint64(0.05f * stampsPerSecond()); + inactivityExceptionPeriod_ = uint64(period * stampsPerSecond()) + uint64(0.05f * stampsPerSecond()); lastReceivedTime_ = timestamp(); inactivityTimerHandle_ = @@ -663,6 +663,7 @@ void Channel::handleTimeout(TimerHandle, void * arg) { this->networkInterface().onChannelTimeOut(this); } + break; } case KCP_UPDATE: From 72a50acca6a2fe887aac13f31753cf03031b42a3 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Thu, 28 Mar 2019 15:38:01 +0800 Subject: [PATCH 11/59] Update channel.cpp --- kbe/src/lib/network/channel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kbe/src/lib/network/channel.cpp b/kbe/src/lib/network/channel.cpp index 1f2d3f673a..5a300bdbc6 100644 --- a/kbe/src/lib/network/channel.cpp +++ b/kbe/src/lib/network/channel.cpp @@ -498,7 +498,7 @@ void Channel::startInactivityDetection( float period, float checkPeriod ) return; } - inactivityExceptionPeriod_ = uint64(period * stampsPerSecond()) + uint64(0.05f * stampsPerSecond()); + inactivityExceptionPeriod_ = uint64(period * stampsPerSecond()) - uint64(0.05f * stampsPerSecond()); lastReceivedTime_ = timestamp(); inactivityTimerHandle_ = From 84c646fb109acfc420f66458d0343f8cc41e7085 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Thu, 28 Mar 2019 16:52:04 +0800 Subject: [PATCH 12/59] up --- kbe/src/lib/network/channel.h | 18 ++++++++++-------- kbe/src/lib/server/components.cpp | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/kbe/src/lib/network/channel.h b/kbe/src/lib/network/channel.h index 99b5fe4251..48da3e2819 100644 --- a/kbe/src/lib/network/channel.h +++ b/kbe/src/lib/network/channel.h @@ -155,16 +155,18 @@ class Channel : public TimerHandler, public PoolObject ChannelID id() const { return id_; } void id(ChannelID v) { id_ = v; } - uint32 numPacketsSent() const { return numPacketsSent_; } - uint32 numPacketsReceived() const { return numPacketsReceived_; } - uint32 numBytesSent() const { return numBytesSent_; } - uint32 numBytesReceived() const { return numBytesReceived_; } - - uint64 lastReceivedTime() const { return lastReceivedTime_; } - void updateLastReceivedTime() { lastReceivedTime_ = timestamp(); } - + uint32 numPacketsSent() const { return numPacketsSent_; } + uint32 numPacketsReceived() const { return numPacketsReceived_; } + uint32 numBytesSent() const { return numBytesSent_; } + uint32 numBytesReceived() const { return numBytesReceived_; } + + uint64 lastReceivedTime() const { return lastReceivedTime_; } + void updateLastReceivedTime() { lastReceivedTime_ = timestamp(); } + void addReceiveWindow(Packet* pPacket); + uint64 inactivityExceptionPeriod() const { return inactivityExceptionPeriod_; } + void updateTick(KBEngine::Network::MessageHandlers* pMsgHandlers); void processPackets(KBEngine::Network::MessageHandlers* pMsgHandlers, Packet* pPacket); diff --git a/kbe/src/lib/server/components.cpp b/kbe/src/lib/server/components.cpp index 7a638935a2..9c9bbe93c6 100644 --- a/kbe/src/lib/server/components.cpp +++ b/kbe/src/lib/server/components.cpp @@ -326,11 +326,11 @@ void Components::removeComponentByChannel(Network::Channel * pChannel, bool isSh if (!isShutingdown && g_componentType != LOGGER_TYPE && g_componentType != INTERFACES_TYPE) { - ERROR_MSG(fmt::format("Components::removeComponentByChannel: {} : {}, Abnormal exit! {}\n", - COMPONENT_NAME_EX(componentType), (*iter).cid, pChannel->condemnReason())); + ERROR_MSG(fmt::format("Components::removeComponentByChannel: {} : {}, Abnormal exit(reason={})! Channel(timestamp={}, lastReceivedTime={}, inactivityExceptionPeriod={})\n", + COMPONENT_NAME_EX(componentType), (*iter).cid, pChannel->condemnReason(), timestamp(), pChannel->lastReceivedTime(), pChannel->inactivityExceptionPeriod())); #if KBE_PLATFORM == PLATFORM_WIN32 - printf("[ERROR]: %s.\n", (fmt::format("Components::removeComponentByChannel: {} : {}, Abnormal exit! {}\n", + printf("[ERROR]: %s.\n", (fmt::format("Components::removeComponentByChannel: {} : {}, Abnormal exit(reason={})!\n", COMPONENT_NAME_EX(componentType), (*iter).cid, pChannel->condemnReason())).c_str()); #endif } From bc99c5480ee2747ef4de357219f177661792304c Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Thu, 28 Mar 2019 20:50:23 +0800 Subject: [PATCH 13/59] up --- kbe/src/server/baseapp/baseapp.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/kbe/src/server/baseapp/baseapp.cpp b/kbe/src/server/baseapp/baseapp.cpp index 6e24969810..0a15f20182 100644 --- a/kbe/src/server/baseapp/baseapp.cpp +++ b/kbe/src/server/baseapp/baseapp.cpp @@ -3821,15 +3821,6 @@ void Baseapp::loginBaseapp(Network::Channel* pChannel, return; } - // Ȼdbmgr룬loginappʱύpasswordӦøύƥ - // ױӹʽ̽½ - if (!ptinfos->needCheckPassword && ptinfos->password != password) - { - loginBaseappFailed(pChannel, accountName, SERVER_ERR_NAME_PASSWORD); - pendingLoginMgr_.removeNextTick(accountName); - return; - } - // entityID0˵entityǴ״̬¼ if(ptinfos->entityID > 0) { From 2234f628f65c453c1c703c76e6a8c7ebdaa92618 Mon Sep 17 00:00:00 2001 From: chenlinyan <874499648@qq.com> Date: Fri, 29 Mar 2019 15:26:02 +0800 Subject: [PATCH 14/59] =?UTF-8?q?#=E6=A8=A1=E5=9D=97=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E7=A9=BA=E9=97=B4=E5=86=B2=E7=AA=81=E4=BF=AE=E6=94=B9#593?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/KBEnginePlugins/Engine/Bundle.cpp | 4 ++ .../Source/KBEnginePlugins/Engine/Bundle.h | 5 ++ .../Engine/ClientSDKUpdateUI.cpp | 2 +- .../Engine/ClientSDKUpdater.cpp | 5 +- .../KBEnginePlugins/Engine/ClientSDKUpdater.h | 5 ++ .../KBEnginePlugins/Engine/DataTypes.cpp | 5 ++ .../Source/KBEnginePlugins/Engine/DataTypes.h | 12 +++- .../Engine/EncryptionFilter.cpp | 4 ++ .../KBEnginePlugins/Engine/EncryptionFilter.h | 5 ++ .../Source/KBEnginePlugins/Engine/Entity.cpp | 4 ++ .../Source/KBEnginePlugins/Engine/Entity.h | 4 ++ .../KBEnginePlugins/Engine/EntityCall.cpp | 5 ++ .../KBEnginePlugins/Engine/EntityCall.h | 8 ++- .../Engine/EntityComponent.cpp | 4 ++ .../KBEnginePlugins/Engine/EntityComponent.h | 4 ++ .../KBEnginePlugins/Engine/Interfaces.h | 4 ++ .../Source/KBEnginePlugins/Engine/KBDebug.h | 4 ++ .../KBEnginePlugins/Engine/KBECommon.cpp | 4 ++ .../Source/KBEnginePlugins/Engine/KBECommon.h | 10 +++- .../Source/KBEnginePlugins/Engine/KBEMain.cpp | 59 +++++++++---------- .../Source/KBEnginePlugins/Engine/KBEMain.h | 2 +- .../KBEnginePlugins/Engine/KBETicker.cpp | 6 +- .../KBEnginePlugins/Engine/KBEngine.cpp | 4 ++ .../Source/KBEnginePlugins/Engine/KBEngine.h | 4 ++ .../KBEnginePlugins/Engine/KBEngineArgs.cpp | 5 ++ .../KBEnginePlugins/Engine/KBEngineArgs.h | 5 ++ .../KBEnginePlugins/Engine/KBEventTypes.cpp | 6 +- .../KBEnginePlugins/Engine/KBEventTypes.h | 6 +- .../Source/KBEnginePlugins/Engine/KBVar.cpp | 6 ++ .../ue4/Source/KBEnginePlugins/Engine/KBVar.h | 4 ++ .../KBEnginePlugins/Engine/MemoryStream.cpp | 4 ++ .../KBEnginePlugins/Engine/MemoryStream.h | 4 ++ .../KBEnginePlugins/Engine/MessageReader.cpp | 4 ++ .../KBEnginePlugins/Engine/MessageReader.h | 4 ++ .../Source/KBEnginePlugins/Engine/Method.cpp | 4 ++ .../Source/KBEnginePlugins/Engine/Method.h | 5 ++ .../Engine/NetworkInterfaceBase.cpp | 4 ++ .../Engine/NetworkInterfaceBase.h | 15 +++-- .../Engine/NetworkInterfaceKCP.cpp | 5 ++ .../Engine/NetworkInterfaceKCP.h | 5 ++ .../Engine/NetworkInterfaceTCP.cpp | 4 ++ .../Engine/NetworkInterfaceTCP.h | 5 ++ .../KBEnginePlugins/Engine/ObjectPool.h | 4 ++ .../Engine/PacketReceiverBase.cpp | 5 ++ .../Engine/PacketReceiverBase.h | 5 ++ .../Engine/PacketReceiverKCP.cpp | 5 ++ .../Engine/PacketReceiverKCP.h | 5 ++ .../Engine/PacketReceiverTCP.cpp | 5 ++ .../Engine/PacketReceiverTCP.h | 5 ++ .../Engine/PacketSenderBase.cpp | 5 ++ .../KBEnginePlugins/Engine/PacketSenderBase.h | 5 ++ .../Engine/PacketSenderKCP.cpp | 5 ++ .../KBEnginePlugins/Engine/PacketSenderKCP.h | 5 ++ .../Engine/PacketSenderTCP.cpp | 5 ++ .../KBEnginePlugins/Engine/PacketSenderTCP.h | 5 ++ .../KBEnginePlugins/Engine/Property.cpp | 5 ++ .../Source/KBEnginePlugins/Engine/Property.h | 6 ++ .../KBEnginePlugins/Engine/ScriptModule.cpp | 5 ++ .../KBEnginePlugins/Engine/ScriptModule.h | 6 ++ 59 files changed, 303 insertions(+), 51 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp index ff33131160..f42ed3e2dc 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp @@ -6,6 +6,8 @@ #include "KBDebug.h" #include "ObjectPool.h" +namespace KBEngine +{ static ObjectPool _g_bundlePool; Bundle::Bundle(): @@ -292,4 +294,6 @@ void Bundle::writeVector4(const FVector4& v) { checkStream(16); (*pCurrPacket_).writeVector4(v); +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.h index ba8bd0af0b..3056c3d1a9 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.h @@ -4,6 +4,9 @@ #include "KBECommon.h" +namespace KBEngine +{ + class MemoryStream; class NetworkInterfaceBase; class Message; @@ -145,3 +148,5 @@ class KBENGINEPLUGINS_API Bundle Message* pMsgtype_; int curMsgStreamIndex_; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp index b3c0d97e4b..3775b033d1 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdateUI.cpp @@ -57,6 +57,6 @@ FReply SClientSDKUpdateUI::UpdateSDKClicked() UKBEventData_onDownloadSDK* pEventData = NewObject(); pEventData->isDownload = true; - KBENGINE_EVENT_FIRE(KBEventTypes::onDownloadSDK, pEventData); + KBENGINE_EVENT_FIRE(KBEngine::KBEventTypes::onDownloadSDK, pEventData); return FReply::Handled(); } diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp index 6df2902eca..3a8506c56a 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp @@ -9,8 +9,10 @@ #include "FileHelper.h" #include "OutPutDeviceDebug.h" -using namespace std; +namespace KBEngine +{ +using namespace std; ClientSDKUpdater::ClientSDKUpdater() { @@ -254,3 +256,4 @@ void ClientSDKUpdater::copyDirectory(FString fromDicPath, FString toDicPath) PlatformFile.CopyDirectoryTree(*toDicPath, *fromDicPath, true); } +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.h index 4fc946f3bf..a358880cb7 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.h @@ -18,6 +18,9 @@ /** * */ +namespace KBEngine +{ + class KBENGINEPLUGINS_API ClientSDKUpdater { public: @@ -53,3 +56,5 @@ class KBENGINEPLUGINS_API ClientSDKUpdater MemoryStream* pSdkFileStream = nullptr; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp index 4c483211a1..6736301c4b 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp @@ -4,6 +4,9 @@ #include "EntityDef.h" #include "KBDebug.h" #include "Runtime/Core/Public/Misc/Variant.h" +#include "Bundle.h" +namespace KBEngine +{ KBVar* DATATYPE_INT8::createFromStream(MemoryStream& stream) { @@ -589,3 +592,5 @@ bool DATATYPE_FIXED_DICT::isSameType(KBVar& v) return true; } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h index f60ca3a75c..f8f5297659 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h @@ -5,13 +5,17 @@ #include "KBECommon.h" #include "KBVar.h" -class Bundle; -class MemoryStream; /* entitydef所支持的基本数据类型 改模块中的类抽象出了所有的支持类型并提供了这些类型的数据序列化成二进制数据与反序列化操作(主要用于网络通讯的打包与解包) */ +namespace KBEngine +{ + +class Bundle; +class MemoryStream; + class KBENGINEPLUGINS_API DATATYPE_BASE { public: @@ -88,7 +92,7 @@ class KBENGINEPLUGINS_API DATATYPE_INT32 : public DATATYPE_BASE { public: virtual KBVar* createFromStream(MemoryStream& stream) override; - virtual void addToStream(Bundle& stream, KBVar& v) override; + virtual void addToStream(KBEngine::Bundle& stream, KBVar& v) override; virtual KBVar* parseDefaultValStr(const FString& v) override; @@ -382,6 +386,8 @@ class KBENGINEPLUGINS_API DATATYPE_FIXED_DICT : public DATATYPE_BASE TMap dicttype_map; }; +} + diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp index 97e4f29263..f3ec5215eb 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.cpp @@ -5,6 +5,9 @@ #include "PacketSenderKCP.h" #include "Engine/KBDebug.h" +namespace KBEngine +{ + EncryptionFilter::~EncryptionFilter() { } @@ -265,3 +268,4 @@ bool BlowfishFilter::recv(MessageReader* pMessageReader, MemoryStream *pPacket) return true; } +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h index 60c3faefa6..5bf4820a02 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EncryptionFilter.h @@ -17,6 +17,9 @@ THIRD_PARTY_INCLUDES_END #include "HideWindowsPlatformTypes.h" #endif +namespace KBEngine +{ + class MemoryStream; class PacketSenderBase; class MessageReader; @@ -97,3 +100,5 @@ class BlowfishFilter : public EncryptionFilter int keySize_; void * pBlowFishKey_; }; + +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.cpp index 4067fe17cb..6b822821c2 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.cpp @@ -10,6 +10,8 @@ #include "Property.h" #include "KBDebug.h" +namespace KBEngine +{ Entity::Entity(): id_(0), @@ -178,3 +180,5 @@ void Entity::onDirectionChanged(const FVector& oldValue) KBENGINE_EVENT_FIRE(KBEventTypes::set_direction, pEventData); } } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.h index 9eb511a294..e37903e252 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Entity.h @@ -5,6 +5,9 @@ #include "KBVar.h" #include "KBECommon.h" +namespace KBEngine +{ + class Method; class Property; class EntityCall; @@ -213,6 +216,7 @@ class KBENGINEPLUGINS_API Entity //EntityCall* cellEntityCall = null; }; +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.cpp index c3dcc76521..516c09f0a9 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.cpp @@ -8,6 +8,9 @@ #include "Method.h" #include "ScriptModule.h" +namespace KBEngine +{ + EntityCall::EntityCall(int32 eid, const FString& ename): id(eid), className(ename), @@ -78,4 +81,6 @@ void EntityCall::sendCall(Bundle* inBundle) if (inBundle == pBundle) pBundle = NULL; +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h index 81028924cb..c813011231 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h @@ -4,13 +4,15 @@ #include "KBECommon.h" -class Bundle; - /* 实体的EntityCall 关于EntityCall请参考API手册中对它的描述 https://github.com/kbengine/kbengine/tree/master/docs/api */ +namespace KBEngine +{ + +class Bundle; class KBENGINEPLUGINS_API EntityCall { public: @@ -51,3 +53,5 @@ class KBENGINEPLUGINS_API EntityCall ENTITYCALL_TYPE type; Bundle* pBundle; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.cpp index a99b7877aa..f115088e7e 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.cpp @@ -4,6 +4,9 @@ #include "KBDebug.h" #include "MemoryStream.h" +namespace KBEngine +{ + EntityComponent::EntityComponent(): entityComponentPropertyID(0), componentType(0), @@ -30,3 +33,4 @@ void EntityComponent::createFromStream(MemoryStream& stream) onUpdatePropertys(0, stream, count); } +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h index 264666e613..d510c35337 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h @@ -3,6 +3,8 @@ #pragma once #include "KBECommon.h" +namespace KBEngine +{ class Entity; class MemoryStream; @@ -59,3 +61,5 @@ class KBENGINEPLUGINS_API EntityComponent ENTITY_ID ownerID; Entity* pOwner; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h index afa2f6b885..62a3d32637 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h @@ -3,6 +3,8 @@ #pragma once #include "KBECommon.h" +namespace KBEngine +{ /* 接口模块 @@ -16,3 +18,5 @@ class KBENGINEPLUGINS_API InterfaceConnect }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h index dbfcb0e127..e4256a8509 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h @@ -1,5 +1,7 @@ // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. #pragma once +namespace KBEngine +{ #define INFO_MSG(Format, ...) \ { \ @@ -57,4 +59,6 @@ { \ const FString Msg = FString::Printf(TEXT(Format), ##__VA_ARGS__); \ GEngine->AddOnScreenDebugMessage(-1, 10000.f, FColor::White, Msg); \ +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp index dbc5079652..3aef5100d2 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp @@ -2,9 +2,13 @@ #include "KBECommon.h" #include "KBDebug.h" +namespace KBEngine +{ DEFINE_LOG_CATEGORY(LogKBEngine); +} + double getTimeSeconds() { return FPlatformTime::Seconds(); diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.h index 538dcf65a1..c57973151d 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.h @@ -9,8 +9,12 @@ #include "GameFramework/Actor.h" #include "KBECommon.generated.h" +namespace KBEngine +{ + DECLARE_LOG_CATEGORY_EXTERN(LogKBEngine, Log, All); +} #define KBE_ASSERT check typedef uint16 MessageID; @@ -20,8 +24,8 @@ typedef int32 ENTITY_ID; typedef uint32 SPACE_ID; typedef uint64 DBID; typedef TArray ByteArray; -typedef TMap KB_FIXED_DICT; -typedef TArray KB_ARRAY; +typedef TMap KB_FIXED_DICT; +typedef TArray KB_ARRAY; #define KBE_FLT_MAX FLT_MAX @@ -170,7 +174,7 @@ inline bool almostEqual(float f1, float f2, float epsilon) return FMath::Abs(f1 - f2) < epsilon; } -inline bool isNumeric(KBVar& v) +inline bool isNumeric(KBEngine::KBVar& v) { return v.GetType() == EKBVarTypes::Bool || v.GetType() == EKBVarTypes::Double || diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp index 57606992ba..d08e1ed253 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp @@ -51,8 +51,7 @@ void UKBEMain::UninitializeComponent() void UKBEMain::BeginPlay() { Super::BeginPlay(); - - KBEngineArgs* pArgs = new KBEngineArgs(); + KBEngine::KBEngineArgs* pArgs = new KBEngine::KBEngineArgs(); pArgs->ip = ip; pArgs->port = port; pArgs->syncPlayerMS = syncPlayerMS; @@ -67,7 +66,7 @@ void UKBEMain::BeginPlay() pArgs->UDP_SEND_BUFFER_MAX = UDP_SEND_BUFFER_MAX; pArgs->UDP_RECV_BUFFER_MAX = UDP_RECV_BUFFER_MAX; - KBEngineApp::getSingleton().initialize(pArgs); + KBEngine::KBEngineApp::getSingleton().initialize(pArgs); installEvents(); } @@ -93,18 +92,18 @@ void UKBEMain::TickComponent( float DeltaTime, ELevelTick TickType, FActorCompon void UKBEMain::installEvents() { - KBENGINE_REGISTER_EVENT(KBEventTypes::onScriptVersionNotMatch, onScriptVersionNotMatch); - KBENGINE_REGISTER_EVENT(KBEventTypes::onVersionNotMatch, onVersionNotMatch); - KBENGINE_REGISTER_EVENT(KBEventTypes::onImportClientSDKSuccessfully, onImportClientSDKSuccessfully); - KBENGINE_REGISTER_EVENT(KBEventTypes::onDownloadSDK, onDownloadSDK); + KBENGINE_REGISTER_EVENT(KBEngine::KBEventTypes::onScriptVersionNotMatch, onScriptVersionNotMatch); + KBENGINE_REGISTER_EVENT(KBEngine::KBEventTypes::onVersionNotMatch, onVersionNotMatch); + KBENGINE_REGISTER_EVENT(KBEngine::KBEventTypes::onImportClientSDKSuccessfully, onImportClientSDKSuccessfully); + KBENGINE_REGISTER_EVENT(KBEngine::KBEventTypes::onDownloadSDK, onDownloadSDK); } void UKBEMain::deregisterEvents() { - KBENGINE_DEREGISTER_EVENT(KBEventTypes::onScriptVersionNotMatch); - KBENGINE_DEREGISTER_EVENT(KBEventTypes::onVersionNotMatch); - KBENGINE_DEREGISTER_EVENT(KBEventTypes::onImportClientSDKSuccessfully); - KBENGINE_DEREGISTER_EVENT(KBEventTypes::onDownloadSDK); + KBENGINE_DEREGISTER_EVENT(KBEngine::KBEventTypes::onScriptVersionNotMatch); + KBENGINE_DEREGISTER_EVENT(KBEngine::KBEventTypes::onVersionNotMatch); + KBENGINE_DEREGISTER_EVENT(KBEngine::KBEventTypes::onImportClientSDKSuccessfully); + KBENGINE_DEREGISTER_EVENT(KBEngine::KBEventTypes::onDownloadSDK); } void UKBEMain::onVersionNotMatch(const UKBEventData* pEventData) @@ -168,7 +167,7 @@ void UKBEMain::onDownloadSDK(const UKBEventData* pEventData) { if (pUpdaterObj == nullptr) { - pUpdaterObj = new ClientSDKUpdater(); + pUpdaterObj = new KBEngine::ClientSDKUpdater(); } pUpdaterObj->downloadSDKFromServer(); @@ -185,84 +184,84 @@ void UKBEMain::onDownloadSDK(const UKBEventData* pEventData) FString UKBEMain::getClientVersion() { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) return TEXT(""); - return KBEngineApp::getSingleton().clientVersion(); + return KBEngine::KBEngineApp::getSingleton().clientVersion(); } FString UKBEMain::getClientScriptVersion() { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) return TEXT(""); - return KBEngineApp::getSingleton().clientScriptVersion(); + return KBEngine::KBEngineApp::getSingleton().clientScriptVersion(); } FString UKBEMain::getServerVersion() { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) return TEXT(""); - return KBEngineApp::getSingleton().serverVersion(); + return KBEngine::KBEngineApp::getSingleton().serverVersion(); } FString UKBEMain::getServerScriptVersion() { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) return TEXT(""); - return KBEngineApp::getSingleton().serverScriptVersion(); + return KBEngine::KBEngineApp::getSingleton().serverScriptVersion(); } FString UKBEMain::getComponentName() { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) return TEXT(""); - return KBEngineApp::getSingleton().component(); + return KBEngine::KBEngineApp::getSingleton().component(); } bool UKBEMain::destroyKBEngine() { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) return false; - KBEngineApp::getSingleton().destroy(); + KBEngine::KBEngineApp::getSingleton().destroy(); KBENGINE_EVENT_CLEAR(); return true; } bool UKBEMain::login(FString username, FString password, TArray datas) { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) { return false; } - KBEngineApp::getSingleton().reset(); + KBEngine::KBEngineApp::getSingleton().reset(); UKBEventData_login* pEventData = NewObject(); pEventData->username = username; pEventData->password = password; pEventData->datas = datas; - KBENGINE_EVENT_FIRE(KBEventTypes::login, pEventData); + KBENGINE_EVENT_FIRE(KBEngine::KBEventTypes::login, pEventData); return true; } bool UKBEMain::createAccount(FString username, FString password, const TArray& datas) { - if (!KBEngineApp::getSingleton().isInitialized()) + if (!KBEngine::KBEngineApp::getSingleton().isInitialized()) { return false; } - KBEngineApp::getSingleton().reset(); + KBEngine::KBEngineApp::getSingleton().reset(); UKBEventData_createAccount* pEventData = NewObject(); pEventData->username = username; pEventData->password = password; pEventData->datas = datas; - KBENGINE_EVENT_FIRE(KBEventTypes::createAccount, pEventData); + KBENGINE_EVENT_FIRE(KBEngine::KBEventTypes::createAccount, pEventData); return true; } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h index ae56c3eb7b..77ce953dda 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h @@ -138,7 +138,7 @@ class KBENGINEPLUGINS_API UKBEMain : public UActorComponent UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = KBEngine) bool automaticallyUpdateSDK; - ClientSDKUpdater* pUpdaterObj; + KBEngine::ClientSDKUpdater* pUpdaterObj; TSharedPtr ClientSDKUpdateUI; diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp index 9c5a1f1cf8..36e21806b0 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBETicker.cpp @@ -26,7 +26,7 @@ void UKBETicker::Tick(float DeltaTime) KBEvent::processOutEvents(); APawn* ue4_player = UGameplayStatics::GetPlayerPawn(GetWorld(), 0); - Entity* kbe_player = KBEngineApp::getSingleton().player(); + KBEngine::Entity* kbe_player = KBEngine::KBEngineApp::getSingleton().player(); // 每个tick将UE4的玩家坐标写入到KBE插件中的玩家实体坐标,插件会定期同步给服务器 if (kbe_player && ue4_player) @@ -37,7 +37,7 @@ void UKBETicker::Tick(float DeltaTime) kbe_player->isOnGround(ue4_player->GetMovementComponent() && ue4_player->GetMovementComponent()->IsMovingOnGround()); } - KBEngineApp::getSingleton().process(); + KBEngine::KBEngineApp::getSingleton().process(); } bool UKBETicker::IsTickable() const @@ -78,6 +78,6 @@ UWorld* UKBETicker::GetTickableGameObjectWorld() const void UKBETicker::OnEndPIE(const bool data) { #if WITH_EDITOR - KBEngineApp::destroyKBEngineApp(); + KBEngine::KBEngineApp::destroyKBEngineApp(); #endif } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp index 71d5efa448..2d1da43713 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp @@ -17,6 +17,8 @@ #include "KBDebug.h" #include "KBEvent.h" #include "EncryptionFilter.h" +namespace KBEngine +{ ServerErrorDescrs KBEngineApp::serverErrs_; @@ -2336,4 +2338,6 @@ void KBEngineApp::_updateVolatileData(ENTITY_ID entityID, float x, float y, floa if (done) entity.onUpdateVolatileData(); +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.h index 7670f36096..5462a1150d 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.h @@ -7,6 +7,9 @@ #include "Interfaces.h" #include "KBETicker.h" +namespace KBEngine +{ + class KBEngineArgs; class Entity; class NetworkInterfaceBase; @@ -518,3 +521,4 @@ class KBENGINEPLUGINS_API KBEngineApp : public InterfaceConnect }; +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.cpp index 8ab0c7d860..c239713286 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.cpp @@ -2,6 +2,9 @@ #include "KBEngineArgs.h" #include "KBDebug.h" +namespace KBEngine +{ + KBEngineArgs::KBEngineArgs(): ip(TEXT("127.0.0.1")), port(20013), @@ -41,4 +44,6 @@ int KBEngineArgs::getUDPRecvBufferSize() int KBEngineArgs::getUDPSendBufferSize() { return (int)UDP_SEND_BUFFER_MAX; +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.h index 6b1ad4265b..935a5f4739 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngineArgs.h @@ -8,6 +8,9 @@ /* 初始化KBEngine的参数类 */ +namespace KBEngine +{ + class KBENGINEPLUGINS_API KBEngineArgs { public: @@ -48,3 +51,5 @@ class KBENGINEPLUGINS_API KBEngineArgs MessageLengthEx UDP_RECV_BUFFER_MAX; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp index 5f83c2b8a0..40a8efa80a 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp @@ -1,4 +1,6 @@ #include "KBEventTypes.h" +namespace KBEngine +{ const FString KBEventTypes::createAccount = "createAccount"; const FString KBEventTypes::login = "login"; @@ -45,4 +47,6 @@ const FString KBEventTypes::onStreamDataCompleted = "onStreamDataCompleted"; // ------------------------------------SDK更新相关------------------------------------- const FString KBEventTypes::onImportClientSDKSuccessfully = "onImportClientSDKSuccessfully"; -const FString KBEventTypes::onDownloadSDK = "onDownloadSDK"; \ No newline at end of file +const FString KBEventTypes::onDownloadSDK = "onDownloadSDK"; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h index 6fd1eca9a1..0551a93606 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h @@ -1,6 +1,8 @@ #pragma once #include "KBECommon.h" +namespace KBEngine +{ struct KBENGINEPLUGINS_API KBEventTypes { @@ -162,4 +164,6 @@ struct KBENGINEPLUGINS_API KBEventTypes static const FString onImportClientSDKSuccessfully; static const FString onDownloadSDK; -}; \ No newline at end of file +}; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.cpp index 3490e3718c..d3e9cdbd3b 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.cpp @@ -1,6 +1,10 @@ #include "KBVar.h" #include "KBDebug.h" +#include "KBECommon.h" + +namespace KBEngine +{ void KBVar::ErrorLog(const FString& errstr) const { @@ -13,3 +17,5 @@ void KBVar::ErrorLog(const FString& errstr) const GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, NewMsg); } +} + diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h index 5195848398..ae8c72e4aa 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h @@ -45,6 +45,9 @@ namespace EKBVarTypes * * @param T The type to be used in KBVar. */ +namespace KBEngine +{ + template struct TKBVariantTraits { static int32 GetType() @@ -864,3 +867,4 @@ template<> struct TKBVariantTraits> static int32 GetType() { return EKBVarTypes::KBVarMap; } }; +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp index 9dd5a69807..4476ab73dc 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp @@ -2,6 +2,8 @@ #include "MemoryStream.h" #include "KBDebug.h" #include "ObjectPool.h" +namespace KBEngine +{ static ObjectPool _g_memoryStreamPool; @@ -57,3 +59,5 @@ void MemoryStream::hexlike() rpos_ = trpos; } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h index 8ca1e99d59..a27d397cb2 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h @@ -39,6 +39,8 @@ namespace MemoryStreamConverter } } +namespace KBEngine +{ template inline void EndianConvert(T& val) { if(!FGenericPlatformProperties::IsLittleEndian()) @@ -916,3 +918,5 @@ inline void MemoryStream::read_skip() { read_skip(); } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp index 6b97b3d6d8..2439807b4a 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp @@ -3,6 +3,8 @@ #include "Messages.h" #include "KBDebug.h" #include "MemoryStream.h" +namespace KBEngine +{ MessageReader::MessageReader(): msgid_(0), @@ -155,3 +157,5 @@ void MessageReader::process(const uint8* datas, MessageLengthEx offset, MessageL } } } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h index 04d2b1e917..a39c8fd3ba 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h @@ -3,6 +3,8 @@ #pragma once #include "KBECommon.h" +namespace KBEngine +{ class MemoryStream; @@ -43,3 +45,5 @@ class KBENGINEPLUGINS_API MessageReader MemoryStream* pMemoryStream_; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp index b8a0b50542..1370b123a1 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp @@ -2,6 +2,8 @@ #include "Method.h" #include "DataTypes.h" #include "KBDebug.h" +namespace KBEngine +{ Method::Method(): name(TEXT("")), @@ -14,3 +16,5 @@ Method::Method(): Method::~Method() { } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.h index 7eb9c9bfbc..5b432bfe27 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.h @@ -4,6 +4,9 @@ #include "KBVar.h" #include "KBECommon.h" +namespace KBEngine +{ + class DATATYPE_BASE; /* @@ -24,3 +27,5 @@ class KBENGINEPLUGINS_API Method TArray args; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp index 2e11c969a7..b9cfe77358 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp @@ -7,6 +7,8 @@ #include "KBDebug.h" #include "Interfaces.h" #include "KBEngine.h" +namespace KBEngine +{ NetworkInterfaceBase::NetworkInterfaceBase(): socket_(NULL), @@ -201,3 +203,5 @@ void NetworkInterfaceBase::tickConnecting() } } } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h index 89e880c35f..5c8fcec3d0 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h @@ -10,19 +10,22 @@ #include "Runtime/Sockets/Public/Sockets.h" #include "EncryptionFilter.h" -class PacketSenderBase; -class PacketReceiverBase; -class MemoryStream; -class InterfaceConnect; + /* 网络模块 处理连接、收发数据 */ +namespace KBEngine +{ +class PacketSenderBase; +class PacketReceiverBase; +class MemoryStream; +class InterfaceConnect; class KBENGINEPLUGINS_API NetworkInterfaceBase { public: - NetworkInterfaceBase(); + NetworkInterfaceBase(); virtual ~NetworkInterfaceBase(); const FString UDP_HELLO = TEXT("62a559f3fa7748bc22f8e0766019d498"); @@ -79,3 +82,5 @@ class KBENGINEPLUGINS_API NetworkInterfaceBase EncryptionFilter *pFilter_; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.cpp index 4b4db912d5..ce3bdab111 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.cpp @@ -11,6 +11,9 @@ #include "PacketSenderKCP.h" #include "PacketReceiverKCP.h" +namespace KBEngine +{ + NetworkInterfaceKCP::NetworkInterfaceKCP(): NetworkInterfaceBase(), pKCP_(NULL), @@ -197,3 +200,5 @@ void NetworkInterfaceKCP::process() NetworkInterfaceBase::process(); } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.h index d81a07365a..b879e74b21 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceKCP.h @@ -15,6 +15,9 @@ 网络模块 处理连接、收发数据 */ +namespace KBEngine +{ + class KBENGINEPLUGINS_API NetworkInterfaceKCP : public NetworkInterfaceBase { public: @@ -58,3 +61,5 @@ class KBENGINEPLUGINS_API NetworkInterfaceKCP : public NetworkInterfaceBase TSharedRef addr_; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.cpp index 850fd76d94..fc07835817 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.cpp @@ -8,6 +8,9 @@ #include "PacketSenderTCP.h" #include "PacketReceiverTCP.h" +namespace KBEngine +{ + NetworkInterfaceTCP::NetworkInterfaceTCP(): NetworkInterfaceBase() { @@ -27,3 +30,4 @@ PacketReceiverBase* NetworkInterfaceTCP::createPacketReceiver() return new PacketReceiverTCP(this); } +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.h index f808353254..dd722be697 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceTCP.h @@ -14,6 +14,9 @@ 网络模块 处理连接、收发数据 */ +namespace KBEngine +{ + class KBENGINEPLUGINS_API NetworkInterfaceTCP : public NetworkInterfaceBase { public: @@ -25,3 +28,5 @@ class KBENGINEPLUGINS_API NetworkInterfaceTCP : public NetworkInterfaceBase PacketReceiverBase* createPacketReceiver() override; }; + +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h index 46492399ef..b3702c8855 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h @@ -1,4 +1,6 @@ #pragma once +namespace KBEngine +{ template class ObjectPool @@ -42,3 +44,5 @@ class ObjectPool private: OBJECT_LIST objects_; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.cpp index d06a14f745..3780e9101f 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.cpp @@ -6,6 +6,9 @@ #include "KBDebug.h" #include "MemoryStream.h" +namespace KBEngine +{ + PacketReceiverBase::PacketReceiverBase(NetworkInterfaceBase* pNetworkInterface): pNetworkInterface_(pNetworkInterface), pMessageReader_(new MessageReader()), @@ -24,3 +27,5 @@ PacketReceiverBase::~PacketReceiverBase() void PacketReceiverBase::process() { } + +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.h index 98a503d127..c57bbeaab8 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverBase.h @@ -4,6 +4,9 @@ #include "KBECommon.h" +namespace KBEngine +{ + class NetworkInterfaceBase; class MessageReader; class MemoryStream; @@ -26,3 +29,5 @@ class KBENGINEPLUGINS_API PacketReceiverBase MessageReader* pMessageReader_; MemoryStream* pBuffer_; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.cpp index f19125a193..5645da3a73 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.cpp @@ -6,6 +6,9 @@ #include "KBDebug.h" #include "MemoryStream.h" +namespace KBEngine +{ + PacketReceiverKCP::PacketReceiverKCP(NetworkInterfaceBase* pNetworkInterface): PacketReceiverBase(pNetworkInterface), remoteAddr_(ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr()) @@ -67,4 +70,6 @@ void PacketReceiverKCP::process() } } } +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.h index 18b5bbf329..39684b81b5 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverKCP.h @@ -6,6 +6,9 @@ #include "PacketReceiverBase.h" #include "Runtime/Sockets/Public/SocketSubsystem.h" +namespace KBEngine +{ + class NetworkInterfaceBase; class MessageReader; class MemoryStream; @@ -26,3 +29,5 @@ class KBENGINEPLUGINS_API PacketReceiverKCP : public PacketReceiverBase protected: TSharedRef remoteAddr_; }; + +} diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.cpp index da6e515d1c..f4d92af84f 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.cpp @@ -6,6 +6,9 @@ #include "KBDebug.h" #include "MemoryStream.h" +namespace KBEngine +{ + PacketReceiverTCP::PacketReceiverTCP(NetworkInterfaceBase* pNetworkInterface): PacketReceiverBase(pNetworkInterface) { @@ -39,4 +42,6 @@ void PacketReceiverTCP::process() } } } +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.h index f3c9c918a3..c8c8b5d6b6 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketReceiverTCP.h @@ -5,6 +5,9 @@ #include "KBECommon.h" #include "PacketReceiverBase.h" +namespace KBEngine +{ + class NetworkInterfaceBase; class MessageReader; class MemoryStream; @@ -25,3 +28,5 @@ class KBENGINEPLUGINS_API PacketReceiverTCP : public PacketReceiverBase protected: }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.cpp index 08533e4f40..9528e3e6df 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.cpp @@ -4,6 +4,9 @@ #include "KBDebug.h" #include "NetworkInterfaceBase.h" +namespace KBEngine +{ + PacketSenderBase::PacketSenderBase(NetworkInterfaceBase* pNetworkInterface) : pNetworkInterface_(pNetworkInterface) { @@ -16,4 +19,6 @@ PacketSenderBase::~PacketSenderBase() bool PacketSenderBase::send(MemoryStream* pMemoryStream) { return true; +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.h index ea683ce6ea..defa207c0b 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderBase.h @@ -4,6 +4,9 @@ #include "KBECommon.h" +namespace KBEngine +{ + class NetworkInterfaceBase; class MemoryStream; @@ -23,3 +26,5 @@ class KBENGINEPLUGINS_API PacketSenderBase protected: NetworkInterfaceBase * pNetworkInterface_; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.cpp index aa7c44a7c2..ee4ce8c42e 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.cpp @@ -4,6 +4,9 @@ #include "KBDebug.h" #include "NetworkInterfaceKCP.h" +namespace KBEngine +{ + PacketSenderKCP::PacketSenderKCP(NetworkInterfaceBase* pNetworkInterface) : PacketSenderBase(pNetworkInterface) { @@ -28,4 +31,6 @@ bool PacketSenderKCP::send(MemoryStream* pMemoryStream) } return true; +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.h index 2138e6b96c..5d917de0ab 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderKCP.h @@ -5,6 +5,9 @@ #include "KBECommon.h" #include "PacketSenderBase.h" +namespace KBEngine +{ + class NetworkInterfaceBase; class MemoryStream; @@ -24,3 +27,5 @@ class KBENGINEPLUGINS_API PacketSenderKCP : public PacketSenderBase protected: }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.cpp index 792287f62a..2140cfc587 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.cpp @@ -4,6 +4,9 @@ #include "KBDebug.h" #include "NetworkInterfaceBase.h" +namespace KBEngine +{ + PacketSenderTCP::PacketSenderTCP(NetworkInterfaceBase* pNetworkInterface) : PacketSenderBase(pNetworkInterface) { @@ -17,4 +20,6 @@ bool PacketSenderTCP::send(MemoryStream* pMemoryStream) { int32 sent = 0; return pNetworkInterface_->socket()->Send(pMemoryStream->data() + pMemoryStream->rpos(), pMemoryStream->length(), sent); +} + } \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.h index 04d127b9ca..71c488d41b 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/PacketSenderTCP.h @@ -5,6 +5,9 @@ #include "KBECommon.h" #include "PacketSenderBase.h" +namespace KBEngine +{ + class NetworkInterfaceBase; class MemoryStream; @@ -24,3 +27,5 @@ class KBENGINEPLUGINS_API PacketSenderTCP : public PacketSenderBase protected: }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.cpp index 85cefca820..d65e39caf7 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.cpp @@ -2,6 +2,9 @@ #include "Property.h" #include "KBDebug.h" +namespace KBEngine +{ + Property::Property(): name(TEXT("")), pUtype(NULL), @@ -17,3 +20,5 @@ Property::~Property() { KBE_SAFE_RELEASE(pDefaultVal); } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.h index 6d42d18c9d..62463d28b0 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Property.h @@ -4,6 +4,10 @@ #include "KBVar.h" #include "KBECommon.h" + +namespace KBEngine +{ + class DATATYPE_BASE; /* @@ -45,3 +49,5 @@ class KBENGINEPLUGINS_API Property KBVar* pDefaultVal; }; + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.cpp index 181ed022c3..9562014dd2 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.cpp @@ -6,6 +6,9 @@ #include "EntityDef.h" #include "KBDebug.h" +namespace KBEngine +{ + ScriptModule::ScriptModule(const FString& moduleName, int type): name(moduleName), usePropertyDescrAlias(false), @@ -30,3 +33,5 @@ Entity* ScriptModule::createEntity() { return EntityDef::createEntity(utype); } + +} \ No newline at end of file diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.h index 78efec249c..bd81dbce3c 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ScriptModule.h @@ -3,6 +3,10 @@ #pragma once #include "KBECommon.h" + +namespace KBEngine +{ + class Property; class Method; class Entity; @@ -37,3 +41,5 @@ class KBENGINEPLUGINS_API ScriptModule uint16 utype; }; + +} From 78ce3d1d67d2cefb39eed0cdfd65ce5b263d96ce Mon Sep 17 00:00:00 2001 From: chenlinyan <874499648@qq.com> Date: Fri, 29 Mar 2019 15:27:06 +0800 Subject: [PATCH 15/59] =?UTF-8?q?#=E6=A8=A1=E6=9D=BF=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=99=A8=E4=B8=AD=E6=B7=BB=E5=8A=A0=E5=91=BD=E5=90=8D=E7=A9=BA?= =?UTF-8?q?=E9=97=B4#593?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kbe/src/server/tools/kbcmd/client_sdk.cpp | 6 +- kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp | 110 ++++++++++++------ 2 files changed, 76 insertions(+), 40 deletions(-) diff --git a/kbe/src/server/tools/kbcmd/client_sdk.cpp b/kbe/src/server/tools/kbcmd/client_sdk.cpp index 43bca8d518..e2a0568e8c 100644 --- a/kbe/src/server/tools/kbcmd/client_sdk.cpp +++ b/kbe/src/server/tools/kbcmd/client_sdk.cpp @@ -1,4 +1,4 @@ -// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com +// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com #include "kbcmd.h" #include "client_sdk.h" @@ -833,7 +833,7 @@ bool ClientSDK::writeEntityCall(ScriptDefModule* pScriptDefModule) std::string newModuleName; - // дBaseEntityCall + // 先写BaseEntityCall if(!writeBaseEntityCallBegin(pScriptDefModule)) return false; @@ -932,7 +932,7 @@ bool ClientSDK::writeEntityCall(ScriptDefModule* pScriptDefModule) headerfileBody_ += fmt::format("\n"); sourcefileBody_ += fmt::format("\n"); - // дCellEntityCall + // 再写CellEntityCall if (!writeCellEntityCallBegin(pScriptDefModule)) return false; diff --git a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp index 4fa2cad4ec..86d31a7d52 100644 --- a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp +++ b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp @@ -1,4 +1,4 @@ -// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com +// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com #include "kbcmd.h" #include "client_sdk.h" @@ -15,6 +15,8 @@ namespace KBEngine { static std::string headerBody = "/*\n\tGenerated by KBEngine!\n\tPlease do not modify this file!\n#REPLACE#\ttools = kbcmd\n*/\n\n"; static std::string moduleSuffix = "Base"; static std::string ConflictTypePrefix = "KBE_"; +static std::string namespaceNameBegin = "namespace KBEngine\n{\n\n"; +static std::string namespaceNameEnd = "\n}"; //------------------------------------------------------------------------------------- ClientSDKUE4::ClientSDKUE4(): @@ -151,7 +153,7 @@ bool ClientSDKUE4::getArrayType(DataType* pDataType, std::string& outstr) { FixedArrayType* pFixedArrayType = static_cast(pDataType); - // Ԫ + // 如果元素又是数组 if (pFixedArrayType->getDataType()->type() == DATA_TYPE_FIXEDARRAY) { if (outstr.size() > 0) @@ -272,9 +274,10 @@ bool ClientSDKUE4::writeServerErrorDescrsModuleBegin() strutil::kbe_replace(fileBody(), "#REPLACE#", ""); fileBody() += "#pragma once\n\n"; - fileBody() += "#include \"KBECommon.h\"\n"; + fileBody() += "#include \"KBECommon.h\"\n\n"; - fileBody() += "\n\n// defined in */res/server/server_errors.xml\n\n"; + fileBody() += namespaceNameBegin; + fileBody() += "// defined in */res/server/server_errors.xml\n\n"; fileBody() += fmt::format("class KBENGINEPLUGINS_API {}\n{{\npublic:\n", "ServerErrorDescrs"); fileBody() += "\tServerErrorDescrs():\n\tserverErrs_()\n\t{\n"; @@ -300,7 +303,8 @@ bool ClientSDKUE4::writeServerErrorDescrsModuleEnd() fileBody() += "\tFKServerErr ServerErr(uint16 id)\n\t{\n\t\treturn serverErrs_.FindRef(id);\n\t}\n\n"; fileBody() += "\tprotected:\n\t\tTMap serverErrs_;"; - fileBody() += "\n};\n\n"; + fileBody() += "\n};\n"; + fileBody() += namespaceNameEnd; return true; } @@ -318,6 +322,7 @@ bool ClientSDKUE4::writeEngineMessagesModuleBegin() fileBody() += "#include \"MemoryStream.h\"\n\n"; fileBody() += "// engine-c++ messages\n\n"; + fileBody() += namespaceNameBegin; fileBody() += fmt::format("class KBENGINEPLUGINS_API {}\n{{\npublic:", "Message"); fileBody() += "\n\tMessage()\n\t{\n"; @@ -366,6 +371,8 @@ bool ClientSDKUE4::writeEngineMessagesModuleBegin() fileBody() += "#include \"MemoryStream.h\"\n"; fileBody() += "#include \"KBEngine.h\"\n\n"; + fileBody() += namespaceNameBegin; + fileBody() += "TMap Messages::loginappMessages;\n"; fileBody() += "TMap Messages::baseappMessages;\n"; fileBody() += "TMap Messages::clientMessages;\n"; @@ -467,6 +474,8 @@ bool ClientSDKUE4::writeEngineMessagesModuleMessage(Network::ExposedMessageInfo& //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeEngineMessagesModuleEnd() { + changeContextToSource(); + fileBody() += namespaceNameEnd; changeContextToHeader(); fileBody() += fmt::format("class KBENGINEPLUGINS_API {}\n{{\npublic:\n", "Messages"); @@ -500,8 +509,8 @@ bool ClientSDKUE4::writeEngineMessagesModuleEnd() fileBody() += "\n\t\treturn true;"; fileBody() += "\n\t}"; - fileBody() += "\n};"; - + fileBody() += "\n}\n;"; + fileBody() += namespaceNameEnd; return true; } @@ -517,6 +526,7 @@ bool ClientSDKUE4::writeEntityDefsModuleBegin() fileBody() += "#pragma once\n\n"; fileBody() += "#include \"KBECommon.h\"\n\n"; + fileBody() += namespaceNameBegin; fileBody() += "class Entity;\n"; fileBody() += "class DATATYPE_BASE;\n"; fileBody() += "class ScriptModule;\n\n"; @@ -540,6 +550,7 @@ bool ClientSDKUE4::writeEntityDefsModuleBegin() fileBody() += "\tstatic Entity* createEntity(int utype);\n"; changeContextToSource(); + fileBody() += "#include \"EntityDef.h\"\n"; fileBody() += "#include \"DataTypes.h\"\n"; fileBody() += "#include \"CustomDataTypes.h\"\n"; @@ -566,6 +577,7 @@ bool ClientSDKUE4::writeEntityDefsModuleBegin() } fileBody() += "\n"; + fileBody() += namespaceNameBegin; fileBody() += "TMap EntityDef::datatype2id;\n"; fileBody() += "TMap EntityDef::datatypes;\n"; fileBody() += "TMap EntityDef::id2datatypes;\n"; @@ -660,8 +672,11 @@ bool ClientSDKUE4::writeEntityDefsModuleBegin() //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeEntityDefsModuleEnd() { + changeContextToSource(); + fileBody() += namespaceNameEnd; changeContextToHeader(); fileBody() += "};\n"; + fileBody() += namespaceNameEnd; return true; } @@ -794,12 +809,17 @@ bool ClientSDKUE4::writeEntityCallBegin(ScriptDefModule* pScriptDefModule) } fileBody() += std::string("\n// defined in */scripts/entity_defs/") + pScriptDefModule->getName() + ".def\n\n"; + fileBody() += namespaceNameBegin; return true; } //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeEntityCallEnd(ScriptDefModule* pScriptDefModule) { + changeContextToSource(); + fileBody() += namespaceNameEnd; + changeContextToHeader(); + fileBody() += namespaceNameEnd; return true; } @@ -919,7 +939,8 @@ bool ClientSDKUE4::writeBaseEntityCallBegin(ScriptDefModule* pScriptDefModule) fileBody() += fmt::format("#include \"{}.h\"\n", (std::string("EntityCall") + pScriptDefModule->getName() + moduleSuffix)); fileBody() += fmt::format("#include \"Bundle.h\"\n\n"); - fileBody() += fmt::format("\n{}::{}(int32 eid, const FString& ename) : EntityCall(eid, ename)\n{{\n", newModuleName, newModuleName); + fileBody() += namespaceNameBegin; + fileBody() += fmt::format("{}::{}(int32 eid, const FString& ename) : EntityCall(eid, ename)\n{{\n", newModuleName, newModuleName); fileBody() += initstr; } else @@ -931,9 +952,12 @@ bool ClientSDKUE4::writeBaseEntityCallBegin(ScriptDefModule* pScriptDefModule) fileBody() += fmt::format("\n\tvirtual ~{}();\n", newModuleName); changeContextToSource(); + + fileBody() += fmt::format("#include \"{}.h\"\n", (std::string("EntityCall") + pScriptDefModule->getName() + moduleSuffix)); fileBody() += fmt::format("#include \"Bundle.h\"\n\n"); - fileBody() += fmt::format("\n{}::{}(uint16 ecpID, int32 eid) : \nEntityCall(eid, \"{}\"),\nentityComponentPropertyID(0)\n{{\n", newModuleName, newModuleName, pScriptDefModule->getName()); + fileBody() += namespaceNameBegin; + fileBody() += fmt::format("{}::{}(uint16 ecpID, int32 eid) : \nEntityCall(eid, \"{}\"),\nentityComponentPropertyID(0)\n{{\n", newModuleName, newModuleName, pScriptDefModule->getName()); fileBody() += fmt::format("\tentityComponentPropertyID = ecpID;\n"); } @@ -1071,7 +1095,8 @@ bool ClientSDKUE4::writeCustomDataTypesBegin() fileBody() += "#include \"KBETypes.h\"\n"; fileBody() += "#include \"MemoryStream.h\"\n"; fileBody() += "#include \"Bundle.h\"\n"; - fileBody() += "#include \"DataTypes.h\"\n\n"; + fileBody() += "#include \"DataTypes.h\"\n"; + fileBody() += namespaceNameBegin; changeContextToSource(); fileBody() += "#include \"CustomDataTypes.h\"\n"; @@ -1079,15 +1104,18 @@ bool ClientSDKUE4::writeCustomDataTypesBegin() fileBody() += "#include \"KBDebug.h\"\n"; fileBody() += "#include \"DataTypes.h\"\n"; fileBody() += "#include \"Runtime/Core/Public/Misc/Variant.h\"\n\n"; - + fileBody() += namespaceNameBegin; + return true; } //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeCustomDataTypesEnd() { + changeContextToSource(); + fileBody() += namespaceNameEnd; changeContextToHeader(); - fileBody() += "\n"; + fileBody() += namespaceNameEnd; return true; } @@ -1118,8 +1146,8 @@ bool ClientSDKUE4::createArrayChildClass(DataType* pRootDataType, DataType* pDat fileBody() += fmt::format("{}\tDATATYPE_{} itemType;\n\n", tabs, pDataType->aliasName(), pDataType->aliasName()); - // Ƿ飬һӦֱΪֵ - // ΪϵͳList + // 如果是非匿名的数组,则第一层解析应该直接设置为有名字的类别 + // 否则设置为系统List类别 if (numLayer == 1) { if (strlen(pRootDataType->aliasName()) == 0 || pRootDataType->aliasName()[0] == '_') @@ -1174,8 +1202,8 @@ bool ClientSDKUE4::createArrayChildClass(DataType* pRootDataType, DataType* pDat std::string classNameStr = typeName; - // Ƿ飬һӦֱΪֵ - // ΪϵͳList + // 如果是非匿名的数组,则第一层解析应该直接设置为有名字的类别 + // 否则设置为系统List类别 if (numLayer == 1) { if (strlen(pRootDataType->aliasName()) == 0 || pRootDataType->aliasName()[0] == '_') @@ -1302,7 +1330,7 @@ bool ClientSDKUE4::writeCustomDataType(const DataType* pDataType) FixedDictType* dictdatatype = const_cast(static_cast(pDataType)); - // ȴ + // 先创建属性 { FixedDictType::FIXEDDICT_KEYTYPE_MAP& keys = dictdatatype->getKeyTypes(); FixedDictType::FIXEDDICT_KEYTYPE_MAP::const_iterator keyiter = keys.begin(); @@ -1345,7 +1373,7 @@ bool ClientSDKUE4::writeCustomDataType(const DataType* pDataType) } } - // createFromStreamEx + // 创建createFromStreamEx方法 { changeContextToHeader(); fileBody() += fmt::format("\tvoid createFromStreamEx(MemoryStream& stream, {}& datas);\n", typeName); @@ -1380,7 +1408,7 @@ bool ClientSDKUE4::writeCustomDataType(const DataType* pDataType) fileBody() += fmt::format("}}\n\n"); } - // addToStreamEx + // 创建addToStreamEx方法 { changeContextToHeader(); fileBody() += fmt::format("\tvoid addToStreamEx(Bundle& stream, const {}& v);\n", typeName); @@ -1593,7 +1621,7 @@ bool ClientSDKUE4::writeEntityDefsModuleInitScript_ScriptModule(ScriptDefModule* //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeEntityDefsModuleInitScript_MethodDescr(ScriptDefModule* pScriptDefModule, MethodDescription* pDescr, COMPONENT_TYPE componentType) { - // pDescrΪNoneǿͻ˷ôҪǿ趨useMethodDescrAliasΪtrueĬΪfalse + // 如果pDescr为None,并且是客户端方法,那么需要强制设定useMethodDescrAlias为true,否则默认为false将会出现问题 if (!pDescr && componentType == CLIENT_TYPE) { fileBody() += fmt::format("\tp{}Module->useMethodDescrAlias = true;\n", pScriptDefModule->getName()); @@ -1762,15 +1790,16 @@ bool ClientSDKUE4::writeTypesBegin() strutil::kbe_replace(fileBody(), "#REPLACE#", ""); fileBody() += "#pragma once\n\n"; - fileBody() += "#include \"KBECommon.h\"\n"; - - fileBody() += "\n\n// defined in */scripts/entity_defs/types.xml\n\n"; + fileBody() += "#include \"KBECommon.h\"\n\n"; + fileBody() += namespaceNameBegin; + fileBody() += "\n// defined in */scripts/entity_defs/types.xml\n\n"; return true; } //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeTypesEnd() { + fileBody() += namespaceNameEnd; return true; } @@ -2096,6 +2125,7 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul fileBody() += fmt::format("#include \"EntityCall{}.h\"\n\n", newModuleName); + fileBody() += namespaceNameBegin; fileBody() += "class Method;\n"; fileBody() += "class Property;\n"; fileBody() += "class MemoryStream;\n"; @@ -2125,12 +2155,13 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul { fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public EntityComponent\n{{\npublic:\n", newModuleName); - // дentityCall + // 写entityCall属性 fileBody() += fmt::format("\tEntityBaseEntityCall_{}* pBaseEntityCall;\n", newModuleName); fileBody() += fmt::format("\tEntityCellEntityCall_{}* pCellEntityCall;\n", newModuleName); fileBody() += fmt::format("\tScriptModule* getScriptModule();\n\n"); changeContextToSource(); + fileBody() += fmt::format("#include \"{}.h\"\n", newModuleName); fileBody() += fmt::format("#include \"KBVar.h\"\n"); fileBody() += fmt::format("#include \"Entity.h\"\n"); @@ -2140,14 +2171,15 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul fileBody() += fmt::format("#include \"Method.h\"\n"); fileBody() += fmt::format("#include \"DataTypes.h\"\n"); fileBody() += fmt::format("#include \"CustomDataTypes.h\"\n"); - fileBody() += fmt::format("#include \"MemoryStream.h\"\n"); + fileBody() += fmt::format("#include \"MemoryStream.h\"\n\n"); + fileBody() += namespaceNameBegin; } else { fileBody() += fmt::format("\t// Please inherit and implement \"class {} : public {}\"\n", pEntityScriptDefModule->getName(), newModuleName); fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public Entity\n{{\npublic:\n", newModuleName); - // дentityCall + // 写entityCall属性 fileBody() += fmt::format("\tEntityBaseEntityCall_{}* pBaseEntityCall;\n", newModuleName); fileBody() += fmt::format("\tEntityCellEntityCall_{}* pCellEntityCall;\n\n", newModuleName); @@ -2178,13 +2210,14 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul if (includesHistroy.find(pEntityComponentType->pScriptDefModule()->getName()) != includesHistroy.end()) continue; - fileBody() += fmt::format("#include \"Scripts/Components/{}.h\"\n", pEntityComponentType->pScriptDefModule()->getName()); + fileBody() += fmt::format("#include \"Scripts/Components/{}.h\"\n\n", pEntityComponentType->pScriptDefModule()->getName()); includesHistroy[pEntityComponentType->pScriptDefModule()->getName()] = pPropertyDescription; } + fileBody() += namespaceNameBegin; } changeContextToHeader(); - // غ󣬺Ϊдʵ.. + // 函数返回后,后续流程为写实体属性.. return true; } @@ -2254,7 +2287,7 @@ bool ClientSDKUE4::writeEntityModuleEnd(ScriptDefModule* pEntityScriptDefModule) fileBody() += "}\n"; - // attach + // attach组件 if (!pEntityScriptDefModule->isComponentModule()) { changeContextToHeader(); @@ -2278,7 +2311,7 @@ bool ClientSDKUE4::writeEntityModuleEnd(ScriptDefModule* pEntityScriptDefModule) fileBody() += fmt::format("}}\n"); } - // detach + // detach组件 if (!pEntityScriptDefModule->isComponentModule()) { changeContextToHeader(); @@ -2299,11 +2332,14 @@ bool ClientSDKUE4::writeEntityModuleEnd(ScriptDefModule* pEntityScriptDefModule) fileBody() += fmt::format("\t{}->onDetached(this);\n", pPropertyDescription->getName()); } - fileBody() += fmt::format("}}\n\n"); + fileBody() += fmt::format("}}\n"); } + fileBody() += namespaceNameEnd; + changeContextToHeader(); - fileBody() += "\n};\n\n"; + fileBody() += "\n};\n"; + fileBody() += namespaceNameEnd; return true; } @@ -2430,7 +2466,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri fileBody() += "}\n"; } - // + // 处理方法 changeContextToHeader(); if (!pEntityScriptDefModule->isComponentModule()) @@ -2660,7 +2696,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri fileBody() += "}\n"; - // + // 处理属性 ENTITY_PROPERTY_UID posuid = 0; if (posuid == 0) { @@ -2798,7 +2834,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions(); - // entityʹС0ʱȻĬԣΪûԵ¿switch + // entity即使在属性小于0时仍然存在默认属性,而组件则可能因为没有属性导致空switch编译出错 if (!pEntityScriptDefModule->isComponentModule() || clientPropertys.size() > 0) { fileBody() += fmt::format("\t\tswitch(pProp->properUtype)\n\t\t{{\n"); @@ -2916,7 +2952,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri fileBody() += "\t}\n"; fileBody() += "}\n"; - // callPropertysSetMethods + // 处理属性callPropertysSetMethods changeContextToHeader(); fileBody() += fmt::format("\tvoid callPropertysSetMethods() override;\n"); @@ -3321,7 +3357,7 @@ bool ClientSDKUE4::writeEntityMethod(ScriptDefModule* pEntityScriptDefModule, //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeEntityMethodArgs_ARRAY(FixedArrayType* pFixedArrayType, std::string& stackArgsTypeBody, const std::string& childItemName) { - // Ҫֱ + // 对于匿名数组需要解析,否则直接填类型名称 if (childItemName.size() == 0 || childItemName[0] == '_') { std::string typeStr; From e0e51c7d1570b781aaa635030e462d15f144bfc7 Mon Sep 17 00:00:00 2001 From: chenlinyan <874499648@qq.com> Date: Fri, 29 Mar 2019 17:16:24 +0800 Subject: [PATCH 16/59] =?UTF-8?q?#ue4=E6=8F=92=E4=BB=B6=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=88=AB=E5=90=8D=E5=86=B2=E7=AA=81#593?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/KBVar.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/Method.cpp | 1 + .../ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp | 1 + .../ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h | 1 + .../client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h | 1 + 19 files changed, 19 insertions(+) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp index f42ed3e2dc..379119164e 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Bundle.cpp @@ -8,6 +8,7 @@ namespace KBEngine { + static ObjectPool _g_bundlePool; Bundle::Bundle(): diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp index 6736301c4b..fe2d5955dd 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.cpp @@ -5,6 +5,7 @@ #include "KBDebug.h" #include "Runtime/Core/Public/Misc/Variant.h" #include "Bundle.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h index c813011231..239d891659 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityCall.h @@ -13,6 +13,7 @@ namespace KBEngine { class Bundle; + class KBENGINEPLUGINS_API EntityCall { public: diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h index d510c35337..7191923678 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/EntityComponent.h @@ -3,6 +3,7 @@ #pragma once #include "KBECommon.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h index 62a3d32637..37e531c034 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Interfaces.h @@ -3,6 +3,7 @@ #pragma once #include "KBECommon.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h index e4256a8509..6331a2a706 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBDebug.h @@ -1,5 +1,6 @@ // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. #pragma once + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp index 3aef5100d2..73a0216337 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBECommon.cpp @@ -2,6 +2,7 @@ #include "KBECommon.h" #include "KBDebug.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp index 2d1da43713..d0e2f54c30 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEngine.cpp @@ -17,6 +17,7 @@ #include "KBDebug.h" #include "KBEvent.h" #include "EncryptionFilter.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp index 40a8efa80a..1955033d7c 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.cpp @@ -1,4 +1,5 @@ #include "KBEventTypes.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h index 0551a93606..3e24053a6a 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEventTypes.h @@ -1,6 +1,7 @@ #pragma once #include "KBECommon.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h index ae8c72e4aa..11ad3c36c6 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h @@ -9,6 +9,7 @@ namespace EKBVarTypes { + const int32 Empty = 0; const int32 Ansichar = 1; const int32 Bool = 2; diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp index 4476ab73dc..cb4c10ec72 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.cpp @@ -2,6 +2,7 @@ #include "MemoryStream.h" #include "KBDebug.h" #include "ObjectPool.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h index a27d397cb2..c53b89bad9 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MemoryStream.h @@ -41,6 +41,7 @@ namespace MemoryStreamConverter namespace KBEngine { + template inline void EndianConvert(T& val) { if(!FGenericPlatformProperties::IsLittleEndian()) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp index 2439807b4a..db19cbbe5a 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.cpp @@ -3,6 +3,7 @@ #include "Messages.h" #include "KBDebug.h" #include "MemoryStream.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h index a39c8fd3ba..316400b43d 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/MessageReader.h @@ -3,6 +3,7 @@ #pragma once #include "KBECommon.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp index 1370b123a1..8b4ba327b8 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/Method.cpp @@ -2,6 +2,7 @@ #include "Method.h" #include "DataTypes.h" #include "KBDebug.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp index b9cfe77358..3f243aa93e 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.cpp @@ -7,6 +7,7 @@ #include "KBDebug.h" #include "Interfaces.h" #include "KBEngine.h" + namespace KBEngine { diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h index 5c8fcec3d0..2ecd10d54d 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/NetworkInterfaceBase.h @@ -18,6 +18,7 @@ */ namespace KBEngine { + class PacketSenderBase; class PacketReceiverBase; class MemoryStream; diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h index b3702c8855..2709bca5f4 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ObjectPool.h @@ -1,4 +1,5 @@ #pragma once + namespace KBEngine { From bb2064526954effd0eda62c776ac679bbb799c9f Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Fri, 29 Mar 2019 17:44:27 +0800 Subject: [PATCH 17/59] up --- kbe/src/server/tools/kbcmd/client_sdk.cpp | 6 +-- kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp | 41 ++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/kbe/src/server/tools/kbcmd/client_sdk.cpp b/kbe/src/server/tools/kbcmd/client_sdk.cpp index e2a0568e8c..43bca8d518 100644 --- a/kbe/src/server/tools/kbcmd/client_sdk.cpp +++ b/kbe/src/server/tools/kbcmd/client_sdk.cpp @@ -1,4 +1,4 @@ -// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com +// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com #include "kbcmd.h" #include "client_sdk.h" @@ -833,7 +833,7 @@ bool ClientSDK::writeEntityCall(ScriptDefModule* pScriptDefModule) std::string newModuleName; - // 先写BaseEntityCall + // дBaseEntityCall if(!writeBaseEntityCallBegin(pScriptDefModule)) return false; @@ -932,7 +932,7 @@ bool ClientSDK::writeEntityCall(ScriptDefModule* pScriptDefModule) headerfileBody_ += fmt::format("\n"); sourcefileBody_ += fmt::format("\n"); - // 再写CellEntityCall + // дCellEntityCall if (!writeCellEntityCallBegin(pScriptDefModule)) return false; diff --git a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp index 86d31a7d52..af5fac1e32 100644 --- a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp +++ b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp @@ -1,4 +1,4 @@ -// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com +// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com #include "kbcmd.h" #include "client_sdk.h" @@ -153,7 +153,7 @@ bool ClientSDKUE4::getArrayType(DataType* pDataType, std::string& outstr) { FixedArrayType* pFixedArrayType = static_cast(pDataType); - // 如果元素又是数组 + // Ԫ if (pFixedArrayType->getDataType()->type() == DATA_TYPE_FIXEDARRAY) { if (outstr.size() > 0) @@ -1146,8 +1146,8 @@ bool ClientSDKUE4::createArrayChildClass(DataType* pRootDataType, DataType* pDat fileBody() += fmt::format("{}\tDATATYPE_{} itemType;\n\n", tabs, pDataType->aliasName(), pDataType->aliasName()); - // 如果是非匿名的数组,则第一层解析应该直接设置为有名字的类别 - // 否则设置为系统List类别 + // Ƿ飬һӦֱΪֵ + // ΪϵͳList if (numLayer == 1) { if (strlen(pRootDataType->aliasName()) == 0 || pRootDataType->aliasName()[0] == '_') @@ -1202,8 +1202,8 @@ bool ClientSDKUE4::createArrayChildClass(DataType* pRootDataType, DataType* pDat std::string classNameStr = typeName; - // 如果是非匿名的数组,则第一层解析应该直接设置为有名字的类别 - // 否则设置为系统List类别 + // Ƿ飬һӦֱΪֵ + // ΪϵͳList if (numLayer == 1) { if (strlen(pRootDataType->aliasName()) == 0 || pRootDataType->aliasName()[0] == '_') @@ -1330,7 +1330,7 @@ bool ClientSDKUE4::writeCustomDataType(const DataType* pDataType) FixedDictType* dictdatatype = const_cast(static_cast(pDataType)); - // 先创建属性 + // ȴ { FixedDictType::FIXEDDICT_KEYTYPE_MAP& keys = dictdatatype->getKeyTypes(); FixedDictType::FIXEDDICT_KEYTYPE_MAP::const_iterator keyiter = keys.begin(); @@ -1373,7 +1373,7 @@ bool ClientSDKUE4::writeCustomDataType(const DataType* pDataType) } } - // 创建createFromStreamEx方法 + // createFromStreamEx { changeContextToHeader(); fileBody() += fmt::format("\tvoid createFromStreamEx(MemoryStream& stream, {}& datas);\n", typeName); @@ -1408,7 +1408,7 @@ bool ClientSDKUE4::writeCustomDataType(const DataType* pDataType) fileBody() += fmt::format("}}\n\n"); } - // 创建addToStreamEx方法 + // addToStreamEx { changeContextToHeader(); fileBody() += fmt::format("\tvoid addToStreamEx(Bundle& stream, const {}& v);\n", typeName); @@ -1621,7 +1621,7 @@ bool ClientSDKUE4::writeEntityDefsModuleInitScript_ScriptModule(ScriptDefModule* //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeEntityDefsModuleInitScript_MethodDescr(ScriptDefModule* pScriptDefModule, MethodDescription* pDescr, COMPONENT_TYPE componentType) { - // 如果pDescr为None,并且是客户端方法,那么需要强制设定useMethodDescrAlias为true,否则默认为false将会出现问题 + // pDescrΪNoneǿͻ˷ôҪǿ趨useMethodDescrAliasΪtrueĬΪfalse if (!pDescr && componentType == CLIENT_TYPE) { fileBody() += fmt::format("\tp{}Module->useMethodDescrAlias = true;\n", pScriptDefModule->getName()); @@ -2155,7 +2155,7 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul { fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public EntityComponent\n{{\npublic:\n", newModuleName); - // 写entityCall属性 + // дentityCall fileBody() += fmt::format("\tEntityBaseEntityCall_{}* pBaseEntityCall;\n", newModuleName); fileBody() += fmt::format("\tEntityCellEntityCall_{}* pCellEntityCall;\n", newModuleName); fileBody() += fmt::format("\tScriptModule* getScriptModule();\n\n"); @@ -2179,7 +2179,7 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul fileBody() += fmt::format("\t// Please inherit and implement \"class {} : public {}\"\n", pEntityScriptDefModule->getName(), newModuleName); fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public Entity\n{{\npublic:\n", newModuleName); - // 写entityCall属性 + // дentityCall fileBody() += fmt::format("\tEntityBaseEntityCall_{}* pBaseEntityCall;\n", newModuleName); fileBody() += fmt::format("\tEntityCellEntityCall_{}* pCellEntityCall;\n\n", newModuleName); @@ -2213,11 +2213,12 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul fileBody() += fmt::format("#include \"Scripts/Components/{}.h\"\n\n", pEntityComponentType->pScriptDefModule()->getName()); includesHistroy[pEntityComponentType->pScriptDefModule()->getName()] = pPropertyDescription; } + fileBody() += namespaceNameBegin; } changeContextToHeader(); - // 函数返回后,后续流程为写实体属性.. + // غ󣬺Ϊдʵ.. return true; } @@ -2287,7 +2288,7 @@ bool ClientSDKUE4::writeEntityModuleEnd(ScriptDefModule* pEntityScriptDefModule) fileBody() += "}\n"; - // attach组件 + // attach if (!pEntityScriptDefModule->isComponentModule()) { changeContextToHeader(); @@ -2311,7 +2312,7 @@ bool ClientSDKUE4::writeEntityModuleEnd(ScriptDefModule* pEntityScriptDefModule) fileBody() += fmt::format("}}\n"); } - // detach组件 + // detach if (!pEntityScriptDefModule->isComponentModule()) { changeContextToHeader(); @@ -2466,7 +2467,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri fileBody() += "}\n"; } - // 处理方法 + // changeContextToHeader(); if (!pEntityScriptDefModule->isComponentModule()) @@ -2696,7 +2697,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri fileBody() += "}\n"; - // 处理属性 + // ENTITY_PROPERTY_UID posuid = 0; if (posuid == 0) { @@ -2834,7 +2835,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions(); - // entity即使在属性小于0时仍然存在默认属性,而组件则可能因为没有属性导致空switch编译出错 + // entityʹС0ʱȻĬԣΪûԵ¿switch if (!pEntityScriptDefModule->isComponentModule() || clientPropertys.size() > 0) { fileBody() += fmt::format("\t\tswitch(pProp->properUtype)\n\t\t{{\n"); @@ -2952,7 +2953,7 @@ bool ClientSDKUE4::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScri fileBody() += "\t}\n"; fileBody() += "}\n"; - // 处理属性callPropertysSetMethods + // callPropertysSetMethods changeContextToHeader(); fileBody() += fmt::format("\tvoid callPropertysSetMethods() override;\n"); @@ -3357,7 +3358,7 @@ bool ClientSDKUE4::writeEntityMethod(ScriptDefModule* pEntityScriptDefModule, //------------------------------------------------------------------------------------- bool ClientSDKUE4::writeEntityMethodArgs_ARRAY(FixedArrayType* pFixedArrayType, std::string& stackArgsTypeBody, const std::string& childItemName) { - // 对于匿名数组需要解析,否则直接填类型名称 + // Ҫֱ if (childItemName.size() == 0 || childItemName[0] == '_') { std::string typeStr; From 6a6d77e80401e61dd5916d013e519beebe5109e7 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Fri, 29 Mar 2019 17:46:35 +0800 Subject: [PATCH 18/59] Update ClientSDKUpdater.cpp --- .../ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp index 3a8506c56a..c224b50fe4 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp @@ -12,8 +12,6 @@ namespace KBEngine { -using namespace std; - ClientSDKUpdater::ClientSDKUpdater() { pSdkFileStream = nullptr; From 1b729ac37d887ca84c42b1467a718b88406b41e7 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Fri, 29 Mar 2019 17:49:57 +0800 Subject: [PATCH 19/59] Update DataTypes.h --- .../ue4/Source/KBEnginePlugins/Engine/DataTypes.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h index f8f5297659..99f437cdfa 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/DataTypes.h @@ -387,16 +387,3 @@ class KBENGINEPLUGINS_API DATATYPE_FIXED_DICT : public DATATYPE_BASE }; } - - - - - - - - - - - - - From b7fa4ccedbf064afef9641356f565aa8bb941d35 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Fri, 29 Mar 2019 18:20:08 +0800 Subject: [PATCH 20/59] up --- .../ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp | 2 +- .../client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp | 3 ++- .../client/ue4/Source/KBEnginePlugins/Engine/KBVar.h | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp index c224b50fe4..f6345adef0 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/ClientSDKUpdater.cpp @@ -246,7 +246,7 @@ void ClientSDKUpdater::moveToFile(FString fromFileName, FString toFileName) PlatformFile.MoveFile(*toFileName, *fromFileName); } -void ClientSDKUpdater::copyDirectory(FString fromDicPath, FString toDicPath) +void ClientSDKUpdater::copyDirectory(FString fromDicPath, FString toDicPath) { FPaths::NormalizeDirectoryName(fromDicPath); FPaths::NormalizeDirectoryName(toDicPath); diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp index d08e1ed253..39b0e3c368 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp @@ -66,7 +66,8 @@ void UKBEMain::BeginPlay() pArgs->UDP_SEND_BUFFER_MAX = UDP_SEND_BUFFER_MAX; pArgs->UDP_RECV_BUFFER_MAX = UDP_RECV_BUFFER_MAX; - KBEngine::KBEngineApp::getSingleton().initialize(pArgs); + if(KBEngine::KBEngineApp::getSingleton().initialize(pArgs)) + delete pArgs; installEvents(); } diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h index 11ad3c36c6..ae8c72e4aa 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBVar.h @@ -9,7 +9,6 @@ namespace EKBVarTypes { - const int32 Empty = 0; const int32 Ansichar = 1; const int32 Bool = 2; From 2c3036291fcee6f09cc08a381e67d873b095b060 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Fri, 29 Mar 2019 18:41:08 +0800 Subject: [PATCH 21/59] Update client_sdk_ue4.cpp --- kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp index af5fac1e32..4cf62b204c 100644 --- a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp +++ b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp @@ -953,7 +953,6 @@ bool ClientSDKUE4::writeBaseEntityCallBegin(ScriptDefModule* pScriptDefModule) changeContextToSource(); - fileBody() += fmt::format("#include \"{}.h\"\n", (std::string("EntityCall") + pScriptDefModule->getName() + moduleSuffix)); fileBody() += fmt::format("#include \"Bundle.h\"\n\n"); fileBody() += namespaceNameBegin; From 34921f64eced45c63851f46fd3e62bb14e6a4271 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Fri, 29 Mar 2019 18:44:04 +0800 Subject: [PATCH 22/59] Update client_sdk_ue4.cpp --- kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp index 4cf62b204c..6398bbe028 100644 --- a/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp +++ b/kbe/src/server/tools/kbcmd/client_sdk_ue4.cpp @@ -2192,7 +2192,7 @@ bool ClientSDKUE4::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModul fileBody() += fmt::format("#include \"DataTypes.h\"\n"); fileBody() += fmt::format("#include \"CustomDataTypes.h\"\n"); fileBody() += fmt::format("#include \"MemoryStream.h\"\n"); - fileBody() += fmt::format("#include \"EntityComponent.h\"\n"); + fileBody() += fmt::format("#include \"EntityComponent.h\"\n\n"); std::map includesHistroy; ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions(); From a79cb974c8aa93cfe92b8cd04189ba447d34658c Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Fri, 29 Mar 2019 22:12:24 +0800 Subject: [PATCH 23/59] Update KBEMain.cpp --- .../client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp index 39b0e3c368..64d82fe9f0 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.cpp @@ -66,7 +66,7 @@ void UKBEMain::BeginPlay() pArgs->UDP_SEND_BUFFER_MAX = UDP_SEND_BUFFER_MAX; pArgs->UDP_RECV_BUFFER_MAX = UDP_RECV_BUFFER_MAX; - if(KBEngine::KBEngineApp::getSingleton().initialize(pArgs)) + if(!KBEngine::KBEngineApp::getSingleton().initialize(pArgs)) delete pArgs; installEvents(); From 59981225a777730c59dd15a03383fdf6bf534b56 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Mon, 1 Apr 2019 21:17:55 +0800 Subject: [PATCH 24/59] Update py_entitydef.cpp --- kbe/src/lib/entitydef/py_entitydef.cpp | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/kbe/src/lib/entitydef/py_entitydef.cpp b/kbe/src/lib/entitydef/py_entitydef.cpp index f54396e8c7..bdfeac1669 100644 --- a/kbe/src/lib/entitydef/py_entitydef.cpp +++ b/kbe/src/lib/entitydef/py_entitydef.cpp @@ -13,6 +13,8 @@ #include "pyscript/script.h" #include "pyscript/copy.h" #include "resmgr/resmgr.h" +#include "server/serverconfig.h" +#include "server/components.h" namespace KBEngine{ namespace script{ namespace entitydef { @@ -1550,6 +1552,22 @@ bool uninstallModule() //------------------------------------------------------------------------------------- static bool loadAllScriptForComponentType(COMPONENT_TYPE loadComponentType) { + std::string entryScriptFileName = ""; + if (loadComponentType == BASEAPP_TYPE) + { + ENGINE_COMPONENT_INFO& info = g_kbeSrvConfig.getBaseApp(); + entryScriptFileName = info.entryScriptFile; + } + else if (loadComponentType == CELLAPP_TYPE) + { + ENGINE_COMPONENT_INFO& info = g_kbeSrvConfig.getCellApp(); + entryScriptFileName = info.entryScriptFile; + } + else + { + KBE_ASSERT(false); + } + std::string rootPath = Resmgr::getSingleton().getPyUserComponentScriptsPath(loadComponentType); if (rootPath.size() == 0) @@ -1563,10 +1581,31 @@ static bool loadAllScriptForComponentType(COMPONENT_TYPE loadComponentType) while (rootPath[rootPath.size() - 1] == '/' || rootPath[rootPath.size() - 1] == '\\') rootPath.pop_back(); wchar_t* wpath = strutil::char2wchar((rootPath).c_str()); + + wchar_t* _wentryScriptFileName = strutil::char2wchar((entryScriptFileName).c_str()); + std::wstring wentryScriptFileName = _wentryScriptFileName; + free(_wentryScriptFileName); + std::vector results; Resmgr::getSingleton().listPathRes(wpath, L"py|pyc", results); + // ִڽű std::vector::iterator iter = results.begin(); + for (; iter != results.end(); ) + { + std::wstring wstrpath = (*iter); + if (wstrpath.find(wentryScriptFileName + L".py") == std::wstring::npos && wstrpath.find(wentryScriptFileName + L".pyc") == std::wstring::npos) + { + ++iter; + continue; + } + + iter = results.erase(iter); + } + + results.insert(results.begin(), std::wstring(wpath) + L"/" + wentryScriptFileName + L".py"); + + iter = results.begin(); for (; iter != results.end(); ++iter) { std::wstring wstrpath = (*iter); @@ -1611,6 +1650,7 @@ static bool loadAllScriptForComponentType(COMPONENT_TYPE loadComponentType) if (!pyModule) { SCRIPT_ERROR_CHECK(); + free(wpath); return false; } else @@ -1623,6 +1663,7 @@ static bool loadAllScriptForComponentType(COMPONENT_TYPE loadComponentType) } free(wpath); + return true; } From 72eb7d22cb3b88e93e594361a78e344d635783e5 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Tue, 2 Apr 2019 11:41:04 +0800 Subject: [PATCH 25/59] up --- kbe/src/lib/entitydef/entitydef.cpp | 13 ++++++++++--- kbe/src/lib/entitydef/py_entitydef.cpp | 14 +++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/kbe/src/lib/entitydef/entitydef.cpp b/kbe/src/lib/entitydef/entitydef.cpp index 60306eae49..e8891253eb 100644 --- a/kbe/src/lib/entitydef/entitydef.cpp +++ b/kbe/src/lib/entitydef/entitydef.cpp @@ -1909,6 +1909,13 @@ bool EntityDef::loadAllComponentScriptModules(std::string entitiesPath, std::vec { std::string entitiesFile = entitiesPath + "entities.xml"; + // entities.xmlļ + // ű壬ûļ + if (access(entitiesFile.c_str(), 0) != 0) + { + return true; + } + SmartPointer xml(new XML()); if (!xml->openSection(entitiesFile.c_str())) return false; @@ -2144,15 +2151,15 @@ bool EntityDef::loadAllComponentScriptModules(std::string entitiesPath, std::vec bool EntityDef::loadAllEntityScriptModules(std::string entitiesPath, std::vector& scriptBaseTypes) { + std::string entitiesFile = entitiesPath + "entities.xml"; + // ű壬ûļ - if (access(entitiesPath.c_str(), 0) != 0) + if (access(entitiesFile.c_str(), 0) != 0) return true; if (!loadAllComponentScriptModules(entitiesPath, scriptBaseTypes)) return false; - std::string entitiesFile = entitiesPath + "entities.xml"; - SmartPointer xml(new XML()); if(!xml->openSection(entitiesFile.c_str())) return false; diff --git a/kbe/src/lib/entitydef/py_entitydef.cpp b/kbe/src/lib/entitydef/py_entitydef.cpp index bdfeac1669..54841d46dc 100644 --- a/kbe/src/lib/entitydef/py_entitydef.cpp +++ b/kbe/src/lib/entitydef/py_entitydef.cpp @@ -1236,11 +1236,22 @@ static PyObject* __py_def_parse(PyObject *self, PyObject* args) { continue; } - else if (parentClass == "Entity" || parentClass == "Proxy") + else if (parentClass == "Entity") { defContext.inheritEngineModuleType = DefContext::DC_TYPE_ENTITY; continue; } + else if (parentClass == "Proxy") + { + if (defContext.componentType != BASEAPP_TYPE) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' Only BASE can inherit KBEngine.Proxy!\n", defContext.optionName.c_str(), moduleQualname); + PY_RETURN_ERROR; + } + + defContext.inheritEngineModuleType = DefContext::DC_TYPE_ENTITY; + continue; + } else if (parentClass == "EntityComponent") { defContext.inheritEngineModuleType = DefContext::DC_TYPE_COMPONENT; @@ -2213,6 +2224,7 @@ static bool registerEntityDef(ScriptDefModule* pScriptModule, DefContext& defCon return false; } + pScriptModule->setScriptType((PyTypeObject *)defContext.pyObjectPtr.get()); pScriptModule->autoMatchCompOwn(); return true; } From f51fb26fcc70e50d9cb473a808d2a664a01b309e Mon Sep 17 00:00:00 2001 From: chenlinyan <874499648@qq.com> Date: Tue, 2 Apr 2019 11:57:07 +0800 Subject: [PATCH 26/59] =?UTF-8?q?#Ue4=E6=96=AD=E7=BA=BF=E9=87=8D=E8=81=94?= =?UTF-8?q?=E6=93=8D=E4=BD=9C#774?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h index 77ce953dda..db88ebfd35 100644 --- a/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h +++ b/kbe/res/sdk_templates/client/ue4/Source/KBEnginePlugins/Engine/KBEMain.h @@ -64,22 +64,22 @@ class KBENGINEPLUGINS_API UKBEMain : public UActorComponent UFUNCTION(BlueprintCallable, Category = "KBEngine") - FString getClientVersion(); + static FString getClientVersion(); UFUNCTION(BlueprintCallable, Category = "KBEngine") - FString getClientScriptVersion(); + static FString getClientScriptVersion(); UFUNCTION(BlueprintCallable, Category = "KBEngine") - FString getServerVersion(); + static FString getServerVersion(); UFUNCTION(BlueprintCallable, Category = "KBEngine") - FString getServerScriptVersion(); + static FString getServerScriptVersion(); /* 客户端属于KBE框架中的一个功能组件,这里获取将固定返回client */ UFUNCTION(BlueprintCallable, Category = "KBEngine") - FString getComponentName(); + static FString getComponentName(); /** 在程序关闭时需要主动调用, 彻底销毁KBEngine From 19198fd78d54a160c36de2304c6625e96a3ed4c7 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Wed, 3 Apr 2019 10:38:45 +0800 Subject: [PATCH 27/59] =?UTF-8?q?Linux=E5=B9=B3=E5=8F=B0=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?navmesh=E6=96=87=E4=BB=B6=E6=97=B6=E5=88=86=E9=85=8D=E7=9A=84?= =?UTF-8?q?=E4=B8=B4=E6=97=B6=E5=86=85=E5=AD=98=E6=B2=A1=E6=9C=89=E9=87=8A?= =?UTF-8?q?=E6=94=BE=20#1005=20=E5=8D=87=E7=BA=A7=E5=88=B0jemalloc-5.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kbe/src/lib/dependencies/jemalloc/.cirrus.yml | 21 + kbe/src/lib/dependencies/jemalloc/.gitignore | 3 +- kbe/src/lib/dependencies/jemalloc/.travis.yml | 81 +- kbe/src/lib/dependencies/jemalloc/COPYING | 4 +- kbe/src/lib/dependencies/jemalloc/ChangeLog | 224 +- kbe/src/lib/dependencies/jemalloc/INSTALL.md | 34 +- kbe/src/lib/dependencies/jemalloc/Makefile.in | 70 +- kbe/src/lib/dependencies/jemalloc/TUNING.md | 129 ++ .../lib/dependencies/jemalloc/bin/jeprof.in | 2 + .../lib/dependencies/jemalloc/configure.ac | 589 +++-- .../dependencies/jemalloc/doc/jemalloc.xml.in | 238 ++- .../include/jemalloc/internal/arena_externs.h | 39 +- .../jemalloc/internal/arena_inlines_a.h | 2 +- .../jemalloc/internal/arena_inlines_b.h | 106 +- .../include/jemalloc/internal/arena_stats.h | 258 +++ .../jemalloc/internal/arena_structs_b.h | 91 +- .../include/jemalloc/internal/arena_types.h | 14 +- .../include/jemalloc/internal/atomic.h | 11 +- .../jemalloc/internal/atomic_gcc_sync.h | 18 +- .../internal/background_thread_externs.h | 3 +- .../internal/background_thread_inlines.h | 7 +- .../internal/background_thread_structs.h | 2 + .../include/jemalloc/internal/base_externs.h | 5 +- .../include/jemalloc/internal/base_inlines.h | 4 + .../include/jemalloc/internal/base_structs.h | 8 +- .../include/jemalloc/internal/base_types.h | 26 + .../jemalloc/include/jemalloc/internal/bin.h | 122 ++ .../include/jemalloc/internal/bin_stats.h | 51 + .../include/jemalloc/internal/bin_types.h | 17 + .../include/jemalloc/internal/bit_util.h | 74 + .../include/jemalloc/internal/bitmap.h | 6 +- .../include/jemalloc/internal/cache_bin.h | 131 ++ .../jemalloc/include/jemalloc/internal/ctl.h | 8 +- .../jemalloc/include/jemalloc/internal/div.h | 41 + .../include/jemalloc/internal/emitter.h | 483 +++++ .../jemalloc/internal/extent_externs.h | 13 +- .../jemalloc/internal/extent_inlines.h | 104 +- .../jemalloc/internal/extent_structs.h | 130 +- .../include/jemalloc/internal/extent_types.h | 6 + .../jemalloc/include/jemalloc/internal/hash.h | 65 +- .../jemalloc/include/jemalloc/internal/hook.h | 163 ++ .../include/jemalloc/internal/hooks.h | 19 - .../internal/jemalloc_internal_decls.h | 14 +- .../internal/jemalloc_internal_defs.h.in | 71 +- .../internal/jemalloc_internal_externs.h | 4 +- .../internal/jemalloc_internal_inlines_a.h | 21 +- .../internal/jemalloc_internal_inlines_b.h | 3 +- .../internal/jemalloc_internal_inlines_c.h | 81 +- .../internal/jemalloc_internal_macros.h | 76 +- .../internal/jemalloc_internal_types.h | 68 +- .../jemalloc/internal/jemalloc_preamble.h.in | 35 +- .../include/jemalloc/internal/large_externs.h | 10 +- .../jemalloc/include/jemalloc/internal/log.h | 115 + .../include/jemalloc/internal/malloc_io.h | 40 + .../include/jemalloc/internal/mutex.h | 74 +- .../include/jemalloc/internal/mutex_prof.h | 46 +- .../include/jemalloc/internal/pages.h | 17 + .../include/jemalloc/internal/prof_externs.h | 15 +- .../jemalloc/internal/prof_inlines_a.h | 25 +- .../jemalloc/internal/prof_inlines_b.h | 86 +- .../include/jemalloc/internal/prof_structs.h | 1 - .../include/jemalloc/internal/quantum.h | 77 + .../include/jemalloc/internal/rtree.h | 100 +- .../include/jemalloc/internal/rtree_tsd.h | 2 +- .../jemalloc/include/jemalloc/internal/sc.h | 320 +++ .../jemalloc/include/jemalloc/internal/seq.h | 55 + .../include/jemalloc/internal/size_classes.sh | 361 ---- .../jemalloc/include/jemalloc/internal/spin.h | 20 +- .../include/jemalloc/internal/stats.h | 137 +- .../include/jemalloc/internal/stats_tsd.h | 12 - .../jemalloc/include/jemalloc/internal/sz.h | 175 +- .../jemalloc/internal/tcache_externs.h | 12 +- .../jemalloc/internal/tcache_inlines.h | 113 +- .../jemalloc/internal/tcache_structs.h | 82 +- .../include/jemalloc/internal/tcache_types.h | 12 +- .../include/jemalloc/internal/test_hooks.h | 19 + .../include/jemalloc/internal/ticker.h | 51 +- .../jemalloc/include/jemalloc/internal/tsd.h | 157 +- .../include/jemalloc/internal/tsd_generic.h | 6 + .../internal/tsd_malloc_thread_cleanup.h | 1 - .../include/jemalloc/internal/tsd_tls.h | 1 - .../include/jemalloc/internal/witness.h | 29 +- .../include/jemalloc/jemalloc_macros.h.in | 1 + .../include/jemalloc/jemalloc_mangle.sh | 2 +- .../lib/dependencies/jemalloc/jemalloc.pc.in | 2 +- .../lib/dependencies/jemalloc/msvc/ReadMe.txt | 7 +- .../jemalloc/msvc/jemalloc_vc2017.sln | 63 + .../projects/vc2015/jemalloc/jemalloc.vcxproj | 15 +- .../vc2015/jemalloc/jemalloc.vcxproj.filters | 13 +- .../vc2015/test_threads/test_threads.vcxproj | 6 +- .../test_threads/test_threads.vcxproj.filters | 6 +- .../projects/vc2017/jemalloc/jemalloc.vcxproj | 349 +++ .../vc2017/jemalloc/jemalloc.vcxproj.filters | 107 + .../vc2017/test_threads/test_threads.vcxproj | 326 +++ .../test_threads/test_threads.vcxproj.filters | 26 + .../vc2015 => }/test_threads/test_threads.cpp | 0 .../vc2015 => }/test_threads/test_threads.h | 0 .../test_threads/test_threads_main.cpp | 0 .../jemalloc/scripts/gen_run_tests.py | 39 +- .../jemalloc/scripts/gen_travis.py | 89 +- kbe/src/lib/dependencies/jemalloc/src/arena.c | 857 ++++---- .../jemalloc/src/background_thread.c | 193 +- kbe/src/lib/dependencies/jemalloc/src/base.c | 174 +- kbe/src/lib/dependencies/jemalloc/src/bin.c | 95 + kbe/src/lib/dependencies/jemalloc/src/ckh.c | 7 +- kbe/src/lib/dependencies/jemalloc/src/ctl.c | 679 ++++-- kbe/src/lib/dependencies/jemalloc/src/div.c | 55 + .../lib/dependencies/jemalloc/src/extent.c | 693 ++++-- .../dependencies/jemalloc/src/extent_dss.c | 9 +- kbe/src/lib/dependencies/jemalloc/src/hook.c | 195 ++ .../lib/dependencies/jemalloc/src/jemalloc.c | 894 +++++++- .../jemalloc/src/jemalloc_cpp.cpp | 23 +- kbe/src/lib/dependencies/jemalloc/src/large.c | 52 +- kbe/src/lib/dependencies/jemalloc/src/log.c | 78 + .../lib/dependencies/jemalloc/src/malloc_io.c | 17 +- kbe/src/lib/dependencies/jemalloc/src/mutex.c | 14 +- kbe/src/lib/dependencies/jemalloc/src/pages.c | 273 ++- kbe/src/lib/dependencies/jemalloc/src/prof.c | 739 ++++++- kbe/src/lib/dependencies/jemalloc/src/rtree.c | 4 +- kbe/src/lib/dependencies/jemalloc/src/sc.c | 313 +++ kbe/src/lib/dependencies/jemalloc/src/spin.c | 4 - kbe/src/lib/dependencies/jemalloc/src/stats.c | 1900 +++++++++-------- kbe/src/lib/dependencies/jemalloc/src/sz.c | 154 +- .../lib/dependencies/jemalloc/src/tcache.c | 218 +- .../jemalloc/src/{hooks.c => test_hooks.c} | 4 +- kbe/src/lib/dependencies/jemalloc/src/tsd.c | 247 ++- kbe/src/lib/dependencies/jemalloc/src/zone.c | 30 +- .../jemalloc/test/include/test/extent_hooks.h | 2 + .../test/include/test/jemalloc_test.h.in | 4 +- .../jemalloc/test/include/test/mtx.h | 2 - .../jemalloc/test/integration/aligned_alloc.c | 26 +- .../jemalloc/test/integration/extent.c | 61 +- .../jemalloc/test/integration/malloc.c | 16 + .../jemalloc/test/integration/mallocx.c | 62 +- .../jemalloc/test/integration/overflow.c | 13 + .../jemalloc/test/integration/rallocx.c | 13 + .../jemalloc/test/integration/sdallocx.c | 2 +- .../jemalloc/test/integration/slab_sizes.c | 80 + .../jemalloc/test/integration/slab_sizes.sh | 4 + .../jemalloc/test/integration/smallocx.c | 312 +++ .../jemalloc/test/integration/smallocx.sh | 5 + .../test/integration/thread_tcache_enabled.c | 2 - .../lib/dependencies/jemalloc/test/src/mtx.c | 7 - .../lib/dependencies/jemalloc/test/src/test.c | 31 +- .../jemalloc/test/stress/hookbench.c | 73 + .../jemalloc/test/unit/arena_reset.c | 6 +- .../test/unit/background_thread_enable.c | 85 + .../dependencies/jemalloc/test/unit/base.c | 24 +- .../jemalloc/test/unit/binshard.c | 154 ++ .../jemalloc/test/unit/binshard.sh | 3 + .../jemalloc/test/unit/bit_util.c | 56 +- .../dependencies/jemalloc/test/unit/decay.c | 12 +- .../lib/dependencies/jemalloc/test/unit/div.c | 29 + .../dependencies/jemalloc/test/unit/emitter.c | 469 ++++ .../dependencies/jemalloc/test/unit/fork.c | 108 +- .../dependencies/jemalloc/test/unit/hook.c | 580 +++++ .../dependencies/jemalloc/test/unit/huge.c | 108 + .../dependencies/jemalloc/test/unit/junk.c | 6 +- .../lib/dependencies/jemalloc/test/unit/log.c | 193 ++ .../dependencies/jemalloc/test/unit/mallctl.c | 168 +- .../dependencies/jemalloc/test/unit/pack.c | 6 + .../dependencies/jemalloc/test/unit/pages.c | 12 +- .../jemalloc/test/unit/prof_gdump.c | 8 +- .../jemalloc/test/unit/prof_log.c | 146 ++ .../jemalloc/test/unit/prof_log.sh | 5 + .../dependencies/jemalloc/test/unit/rtree.c | 23 +- .../lib/dependencies/jemalloc/test/unit/sc.c | 33 + .../lib/dependencies/jemalloc/test/unit/seq.c | 95 + .../jemalloc/test/unit/size_classes.c | 21 +- .../dependencies/jemalloc/test/unit/slab.c | 6 +- .../dependencies/jemalloc/test/unit/stats.c | 13 +- .../jemalloc/test/unit/stats_print.c | 2 +- .../test/unit/{hooks.c => test_hooks.c} | 6 +- .../lib/dependencies/jemalloc/test/unit/tsd.c | 134 +- .../dependencies/jemalloc/test/unit/zero.c | 4 +- 175 files changed, 14327 insertions(+), 3841 deletions(-) create mode 100644 kbe/src/lib/dependencies/jemalloc/.cirrus.yml create mode 100644 kbe/src/lib/dependencies/jemalloc/TUNING.md create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_stats.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_stats.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_types.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/cache_bin.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/div.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/emitter.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hook.h delete mode 100755 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hooks.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/log.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/quantum.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sc.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/seq.h delete mode 100755 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/size_classes.sh delete mode 100755 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats_tsd.h create mode 100644 kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/test_hooks.h create mode 100644 kbe/src/lib/dependencies/jemalloc/msvc/jemalloc_vc2017.sln create mode 100644 kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj create mode 100644 kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters create mode 100644 kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj create mode 100644 kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj.filters rename kbe/src/lib/dependencies/jemalloc/msvc/{projects/vc2015 => }/test_threads/test_threads.cpp (100%) mode change 100755 => 100644 rename kbe/src/lib/dependencies/jemalloc/msvc/{projects/vc2015 => }/test_threads/test_threads.h (100%) mode change 100755 => 100644 rename kbe/src/lib/dependencies/jemalloc/msvc/{projects/vc2015 => }/test_threads/test_threads_main.cpp (100%) mode change 100755 => 100644 create mode 100644 kbe/src/lib/dependencies/jemalloc/src/bin.c create mode 100644 kbe/src/lib/dependencies/jemalloc/src/div.c create mode 100644 kbe/src/lib/dependencies/jemalloc/src/hook.c create mode 100644 kbe/src/lib/dependencies/jemalloc/src/log.c create mode 100644 kbe/src/lib/dependencies/jemalloc/src/sc.c delete mode 100755 kbe/src/lib/dependencies/jemalloc/src/spin.c rename kbe/src/lib/dependencies/jemalloc/src/{hooks.c => test_hooks.c} (79%) mode change 100755 => 100644 create mode 100644 kbe/src/lib/dependencies/jemalloc/test/integration/malloc.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.sh create mode 100644 kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.sh create mode 100644 kbe/src/lib/dependencies/jemalloc/test/stress/hookbench.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/background_thread_enable.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/binshard.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/binshard.sh create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/div.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/emitter.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/hook.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/huge.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/log.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.sh create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/sc.c create mode 100644 kbe/src/lib/dependencies/jemalloc/test/unit/seq.c rename kbe/src/lib/dependencies/jemalloc/test/unit/{hooks.c => test_hooks.c} (82%) mode change 100755 => 100644 diff --git a/kbe/src/lib/dependencies/jemalloc/.cirrus.yml b/kbe/src/lib/dependencies/jemalloc/.cirrus.yml new file mode 100644 index 0000000000..019d2c38cd --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/.cirrus.yml @@ -0,0 +1,21 @@ +env: + CIRRUS_CLONE_DEPTH: 1 + ARCH: amd64 + +task: + freebsd_instance: + matrix: + image: freebsd-12-0-release-amd64 + image: freebsd-11-2-release-amd64 + install_script: + - sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf + - pkg upgrade -y + - pkg install -y autoconf gmake + script: + - autoconf + #- ./configure ${COMPILER_FLAGS:+ CC="$CC $COMPILER_FLAGS" CXX="$CXX $COMPILER_FLAGS" } $CONFIGURE_FLAGS + - ./configure + - export JFLAG=`sysctl -n kern.smp.cpus` + - gmake -j${JFLAG} + - gmake -j${JFLAG} tests + - gmake check diff --git a/kbe/src/lib/dependencies/jemalloc/.gitignore b/kbe/src/lib/dependencies/jemalloc/.gitignore index a25aaf7e9f..5ca0ad1daa 100755 --- a/kbe/src/lib/dependencies/jemalloc/.gitignore +++ b/kbe/src/lib/dependencies/jemalloc/.gitignore @@ -30,7 +30,6 @@ /include/jemalloc/internal/public_namespace.h /include/jemalloc/internal/public_symbols.txt /include/jemalloc/internal/public_unnamespace.h -/include/jemalloc/internal/size_classes.h /include/jemalloc/jemalloc.h /include/jemalloc/jemalloc_defs.h /include/jemalloc/jemalloc_macros.h @@ -77,12 +76,14 @@ test/include/test/jemalloc_test_defs.h *.pdb *.sdf *.opendb +*.VC.db *.opensdf *.cachefile *.suo *.user *.sln.docstates *.tmp +.vs/ /msvc/Win32/ /msvc/x64/ /msvc/projects/*/*/Debug*/ diff --git a/kbe/src/lib/dependencies/jemalloc/.travis.yml b/kbe/src/lib/dependencies/jemalloc/.travis.yml index 418fc6fd6d..40b2eb5f44 100755 --- a/kbe/src/lib/dependencies/jemalloc/.travis.yml +++ b/kbe/src/lib/dependencies/jemalloc/.travis.yml @@ -1,4 +1,5 @@ language: generic +dist: precise matrix: include: @@ -10,7 +11,7 @@ matrix: env: CC=clang CXX=clang++ COMPILER_FLAGS="" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: + addons: &gcc_multilib apt: packages: - gcc-multilib @@ -20,6 +21,8 @@ matrix: env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-libdl" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux @@ -36,20 +39,21 @@ matrix: env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: osx env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: osx + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-libdl" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: osx env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=clang CXX=clang++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib - os: linux env: CC=clang CXX=clang++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=clang CXX=clang++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=clang CXX=clang++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=clang CXX=clang++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-libdl" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=clang CXX=clang++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux @@ -60,50 +64,34 @@ matrix: env: CC=clang CXX=clang++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--enable-debug" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--disable-stats" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--disable-libdl" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + addons: *gcc_multilib - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-malloc-conf=dss:primary" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-malloc-conf=percpu_arena:percpu" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - addons: - apt: - packages: - - gcc-multilib + addons: *gcc_multilib - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --disable-stats" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --disable-libdl" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux @@ -114,6 +102,8 @@ matrix: env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof --disable-stats" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof --disable-libdl" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux @@ -122,6 +112,8 @@ matrix: env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof --with-malloc-conf=percpu_arena:percpu" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats --disable-libdl" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux @@ -130,6 +122,14 @@ matrix: env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats --with-malloc-conf=percpu_arena:percpu" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-libdl --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-libdl --with-malloc-conf=dss:primary" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-libdl --with-malloc-conf=percpu_arena:percpu" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-libdl --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--with-malloc-conf=tcache:false,dss:primary" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux @@ -142,10 +142,25 @@ matrix: env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--with-malloc-conf=dss:primary,background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" - os: linux env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--with-malloc-conf=percpu_arena:percpu,background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + # Development build + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --disable-cache-oblivious --enable-stats --enable-log --enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + # --enable-expermental-smallocx: + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --enable-experimental-smallocx --enable-stats --enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" + + # Valgrind + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" JEMALLOC_TEST_PREFIX="valgrind" + addons: + apt: + packages: + - valgrind before_script: - autoconf + - scripts/gen_travis.py > travis_script && diff .travis.yml travis_script - ./configure ${COMPILER_FLAGS:+ CC="$CC $COMPILER_FLAGS" CXX="$CXX $COMPILER_FLAGS" } $CONFIGURE_FLAGS - make -j3 - make -j3 tests diff --git a/kbe/src/lib/dependencies/jemalloc/COPYING b/kbe/src/lib/dependencies/jemalloc/COPYING index e308632a81..3b7fd3585d 100755 --- a/kbe/src/lib/dependencies/jemalloc/COPYING +++ b/kbe/src/lib/dependencies/jemalloc/COPYING @@ -1,10 +1,10 @@ Unless otherwise specified, files in the jemalloc source distribution are subject to the following license: -------------------------------------------------------------------------------- -Copyright (C) 2002-2017 Jason Evans . +Copyright (C) 2002-present Jason Evans . All rights reserved. Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. -Copyright (C) 2009-2017 Facebook, Inc. All rights reserved. +Copyright (C) 2009-present Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/kbe/src/lib/dependencies/jemalloc/ChangeLog b/kbe/src/lib/dependencies/jemalloc/ChangeLog index ee1b7ead39..7c73a8f237 100755 --- a/kbe/src/lib/dependencies/jemalloc/ChangeLog +++ b/kbe/src/lib/dependencies/jemalloc/ChangeLog @@ -4,6 +4,226 @@ brevity. Much more detail can be found in the git revision history: https://github.com/jemalloc/jemalloc +* 5.2.0 (April 2, 2019) + + This release includes a few notable improvements, which are summarized below: + 1) improved fast-path performance from the optimizations by @djwatson; 2) + reduced virtual memory fragmentation and metadata usage; and 3) bug fixes on + setting the number of background threads. In addition, peak / spike memory + usage is improved with certain allocation patterns. As usual, the release and + prior dev versions have gone through large-scale production testing. + + New features: + - Implement oversize_threshold, which uses a dedicated arena for allocations + crossing the specified threshold to reduce fragmentation. (@interwq) + - Add extents usage information to stats. (@tyleretzel) + - Log time information for sampled allocations. (@tyleretzel) + - Support 0 size in sdallocx. (@djwatson) + - Output rate for certain counters in malloc_stats. (@zinoale) + - Add configure option --enable-readlinkat, which allows the use of readlinkat + over readlink. (@davidtgoldblatt) + - Add configure options --{enable,disable}-{static,shared} to allow not + building unwanted libraries. (@Ericson2314) + - Add configure option --disable-libdl to enable fully static builds. + (@interwq) + - Add mallctl interfaces: + + opt.oversize_threshold (@interwq) + + stats.arenas..extent_avail (@tyleretzel) + + stats.arenas..extents..n{dirty,muzzy,retained} (@tyleretzel) + + stats.arenas..extents..{dirty,muzzy,retained}_bytes + (@tyleretzel) + + Portability improvements: + - Update MSVC builds. (@maksqwe, @rustyx) + - Workaround a compiler optimizer bug on s390x. (@rkmisra) + - Make use of pthread_set_name_np(3) on FreeBSD. (@trasz) + - Implement malloc_getcpu() to enable percpu_arena for windows. (@santagada) + - Link against -pthread instead of -lpthread. (@paravoid) + - Make background_thread not dependent on libdl. (@interwq) + - Add stringify to fix a linker directive issue on MSVC. (@daverigby) + - Detect and fall back when 8-bit atomics are unavailable. (@interwq) + - Fall back to the default pthread_create if dlsym(3) fails. (@interwq) + + Optimizations and refactors: + - Refactor the TSD module. (@davidtgoldblatt) + - Avoid taking extents_muzzy mutex when muzzy is disabled. (@interwq) + - Avoid taking large_mtx for auto arenas on the tcache flush path. (@interwq) + - Optimize ixalloc by avoiding a size lookup. (@interwq) + - Implement opt.oversize_threshold which uses a dedicated arena for requests + crossing the threshold, also eagerly purges the oversize extents. Default + the threshold to 8 MiB. (@interwq) + - Clean compilation with -Wextra. (@gnzlbg, @jasone) + - Refactor the size class module. (@davidtgoldblatt) + - Refactor the stats emitter. (@tyleretzel) + - Optimize pow2_ceil. (@rkmisra) + - Avoid runtime detection of lazy purging on FreeBSD. (@trasz) + - Optimize mmap(2) alignment handling on FreeBSD. (@trasz) + - Improve error handling for THP state initialization. (@jsteemann) + - Rework the malloc() fast path. (@djwatson) + - Rework the free() fast path. (@djwatson) + - Refactor and optimize the tcache fill / flush paths. (@djwatson) + - Optimize sync / lwsync on PowerPC. (@chmeeedalf) + - Bypass extent_dalloc() when retain is enabled. (@interwq) + - Optimize the locking on large deallocation. (@interwq) + - Reduce the number of pages committed from sanity checking in debug build. + (@trasz, @interwq) + - Deprecate OSSpinLock. (@interwq) + - Lower the default number of background threads to 4 (when the feature + is enabled). (@interwq) + - Optimize the trylock spin wait. (@djwatson) + - Use arena index for arena-matching checks. (@interwq) + - Avoid forced decay on thread termination when using background threads. + (@interwq) + - Disable muzzy decay by default. (@djwatson, @interwq) + - Only initialize libgcc unwinder when profiling is enabled. (@paravoid, + @interwq) + + Bug fixes (all only relevant to jemalloc 5.x): + - Fix background thread index issues with max_background_threads. (@djwatson, + @interwq) + - Fix stats output for opt.lg_extent_max_active_fit. (@interwq) + - Fix opt.prof_prefix initialization. (@davidtgoldblatt) + - Properly trigger decay on tcache destroy. (@interwq, @amosbird) + - Fix tcache.flush. (@interwq) + - Detect whether explicit extent zero out is necessary with huge pages or + custom extent hooks, which may change the purge semantics. (@interwq) + - Fix a side effect caused by extent_max_active_fit combined with decay-based + purging, where freed extents can accumulate and not be reused for an + extended period of time. (@interwq, @mpghf) + - Fix a missing unlock on extent register error handling. (@zoulasc) + + Testing: + - Simplify the Travis script output. (@gnzlbg) + - Update the test scripts for FreeBSD. (@devnexen) + - Add unit tests for the producer-consumer pattern. (@interwq) + - Add Cirrus-CI config for FreeBSD builds. (@jasone) + - Add size-matching sanity checks on tcache flush. (@davidtgoldblatt, + @interwq) + + Incompatible changes: + - Remove --with-lg-page-sizes. (@davidtgoldblatt) + + Documentation: + - Attempt to build docs by default, however skip doc building when xsltproc + is missing. (@interwq, @cmuellner) + +* 5.1.0 (May 4, 2018) + + This release is primarily about fine-tuning, ranging from several new features + to numerous notable performance and portability enhancements. The release and + prior dev versions have been running in multiple large scale applications for + months, and the cumulative improvements are substantial in many cases. + + Given the long and successful production runs, this release is likely a good + candidate for applications to upgrade, from both jemalloc 5.0 and before. For + performance-critical applications, the newly added TUNING.md provides + guidelines on jemalloc tuning. + + New features: + - Implement transparent huge page support for internal metadata. (@interwq) + - Add opt.thp to allow enabling / disabling transparent huge pages for all + mappings. (@interwq) + - Add maximum background thread count option. (@djwatson) + - Allow prof_active to control opt.lg_prof_interval and prof.gdump. + (@interwq) + - Allow arena index lookup based on allocation addresses via mallctl. + (@lionkov) + - Allow disabling initial-exec TLS model. (@davidtgoldblatt, @KenMacD) + - Add opt.lg_extent_max_active_fit to set the max ratio between the size of + the active extent selected (to split off from) and the size of the requested + allocation. (@interwq, @davidtgoldblatt) + - Add retain_grow_limit to set the max size when growing virtual address + space. (@interwq) + - Add mallctl interfaces: + + arena..retain_grow_limit (@interwq) + + arenas.lookup (@lionkov) + + max_background_threads (@djwatson) + + opt.lg_extent_max_active_fit (@interwq) + + opt.max_background_threads (@djwatson) + + opt.metadata_thp (@interwq) + + opt.thp (@interwq) + + stats.metadata_thp (@interwq) + + Portability improvements: + - Support GNU/kFreeBSD configuration. (@paravoid) + - Support m68k, nios2 and SH3 architectures. (@paravoid) + - Fall back to FD_CLOEXEC when O_CLOEXEC is unavailable. (@zonyitoo) + - Fix symbol listing for cross-compiling. (@tamird) + - Fix high bits computation on ARM. (@davidtgoldblatt, @paravoid) + - Disable the CPU_SPINWAIT macro for Power. (@davidtgoldblatt, @marxin) + - Fix MSVC 2015 & 2017 builds. (@rustyx) + - Improve RISC-V support. (@EdSchouten) + - Set name mangling script in strict mode. (@nicolov) + - Avoid MADV_HUGEPAGE on ARM. (@marxin) + - Modify configure to determine return value of strerror_r. + (@davidtgoldblatt, @cferris1000) + - Make sure CXXFLAGS is tested with CPP compiler. (@nehaljwani) + - Fix 32-bit build on MSVC. (@rustyx) + - Fix external symbol on MSVC. (@maksqwe) + - Avoid a printf format specifier warning. (@jasone) + - Add configure option --disable-initial-exec-tls which can allow jemalloc to + be dynamically loaded after program startup. (@davidtgoldblatt, @KenMacD) + - AArch64: Add ILP32 support. (@cmuellner) + - Add --with-lg-vaddr configure option to support cross compiling. + (@cmuellner, @davidtgoldblatt) + + Optimizations and refactors: + - Improve active extent fit with extent_max_active_fit. This considerably + reduces fragmentation over time and improves virtual memory and metadata + usage. (@davidtgoldblatt, @interwq) + - Eagerly coalesce large extents to reduce fragmentation. (@interwq) + - sdallocx: only read size info when page aligned (i.e. possibly sampled), + which speeds up the sized deallocation path significantly. (@interwq) + - Avoid attempting new mappings for in place expansion with retain, since + it rarely succeeds in practice and causes high overhead. (@interwq) + - Refactor OOM handling in newImpl. (@wqfish) + - Add internal fine-grained logging functionality for debugging use. + (@davidtgoldblatt) + - Refactor arena / tcache interactions. (@davidtgoldblatt) + - Refactor extent management with dumpable flag. (@davidtgoldblatt) + - Add runtime detection of lazy purging. (@interwq) + - Use pairing heap instead of red-black tree for extents_avail. (@djwatson) + - Use sysctl on startup in FreeBSD. (@trasz) + - Use thread local prng state instead of atomic. (@djwatson) + - Make decay to always purge one more extent than before, because in + practice large extents are usually the ones that cross the decay threshold. + Purging the additional extent helps save memory as well as reduce VM + fragmentation. (@interwq) + - Fast division by dynamic values. (@davidtgoldblatt) + - Improve the fit for aligned allocation. (@interwq, @edwinsmith) + - Refactor extent_t bitpacking. (@rkmisra) + - Optimize the generated assembly for ticker operations. (@davidtgoldblatt) + - Convert stats printing to use a structured text emitter. (@davidtgoldblatt) + - Remove preserve_lru feature for extents management. (@djwatson) + - Consolidate two memory loads into one on the fast deallocation path. + (@davidtgoldblatt, @interwq) + + Bug fixes (most of the issues are only relevant to jemalloc 5.0): + - Fix deadlock with multithreaded fork in OS X. (@davidtgoldblatt) + - Validate returned file descriptor before use. (@zonyitoo) + - Fix a few background thread initialization and shutdown issues. (@interwq) + - Fix an extent coalesce + decay race by taking both coalescing extents off + the LRU list. (@interwq) + - Fix potentially unbound increase during decay, caused by one thread keep + stashing memory to purge while other threads generating new pages. The + number of pages to purge is checked to prevent this. (@interwq) + - Fix a FreeBSD bootstrap assertion. (@strejda, @interwq) + - Handle 32 bit mutex counters. (@rkmisra) + - Fix a indexing bug when creating background threads. (@davidtgoldblatt, + @binliu19) + - Fix arguments passed to extent_init. (@yuleniwo, @interwq) + - Fix addresses used for ordering mutexes. (@rkmisra) + - Fix abort_conf processing during bootstrap. (@interwq) + - Fix include path order for out-of-tree builds. (@cmuellner) + + Incompatible changes: + - Remove --disable-thp. (@interwq) + - Remove mallctl interfaces: + + config.thp (@interwq) + + Documentation: + - Add TUNING.md. (@interwq, @davidtgoldblatt, @djwatson) + * 5.0.1 (July 1, 2017) This bugfix release fixes several issues, most of which are obscure enough @@ -22,7 +242,7 @@ brevity. Much more detail can be found in the git revision history: unlikely to be an issue with other libc implementations. (@interwq) - Mask signals during background thread creation. This prevents signals from being inadvertently delivered to background threads. (@jasone, - @davidgoldblatt, @interwq) + @davidtgoldblatt, @interwq) - Avoid inactivity checks within background threads, in order to prevent recursive mutex acquisition. (@interwq) - Fix extent_grow_retained() to use the specified hooks when the @@ -515,7 +735,7 @@ brevity. Much more detail can be found in the git revision history: these fixes, xallocx() now tries harder to partially fulfill requests for optional extra space. Note that a couple of minor heap profiling optimizations are included, but these are better thought of as performance - fixes that were integral to disovering most of the other bugs. + fixes that were integral to discovering most of the other bugs. Optimizations: - Avoid a chunk metadata read in arena_prof_tctx_set(), since it is in the diff --git a/kbe/src/lib/dependencies/jemalloc/INSTALL.md b/kbe/src/lib/dependencies/jemalloc/INSTALL.md index dff7cebbbb..b8f729b0d7 100755 --- a/kbe/src/lib/dependencies/jemalloc/INSTALL.md +++ b/kbe/src/lib/dependencies/jemalloc/INSTALL.md @@ -157,11 +157,6 @@ any of the following arguments (not a definitive list) to 'configure': Statically link against the specified libunwind.a rather than dynamically linking with -lunwind. -* `--disable-thp` - - Disable transparent huge page (THP) integration. This option can be useful - when cross compiling. - * `--disable-fill` Disable support for junk/zero filling of memory. See the "opt.junk" and @@ -226,13 +221,6 @@ any of the following arguments (not a definitive list) to 'configure': system page size may change between configuration and execution, e.g. when cross compiling. -* `--with-lg-page-sizes=` - - Specify the comma-separated base 2 logs of the page sizes to support. This - option may be useful when cross compiling in combination with - `--with-lg-page`, but its primary use case is for integration with FreeBSD's - libc, wherein jemalloc is embedded. - * `--with-lg-hugepage=` Specify the base 2 log of the system huge page size. This option is useful @@ -265,6 +253,27 @@ any of the following arguments (not a definitive list) to 'configure': configuration, jemalloc will provide additional size classes that are not 16-byte-aligned (24, 40, and 56). +* `--with-lg-vaddr=` + + Specify the number of significant virtual address bits. By default, the + configure script attempts to detect virtual address size on those platforms + where it knows how, and picks a default otherwise. This option may be + useful when cross-compiling. + +* `--disable-initial-exec-tls` + + Disable the initial-exec TLS model for jemalloc's internal thread-local + storage (on those platforms that support explicit settings). This can allow + jemalloc to be dynamically loaded after program startup (e.g. using dlopen). + Note that in this case, there will be two malloc implementations operating + in the same process, which will almost certainly result in confusing runtime + crashes if pointers leak from one implementation to the other. + +* `--disable-libdl` + + Disable the usage of libdl, namely dlsym(3) which is required by the lazy + lock option. This can allow building static binaries. + The following environment variables (not a definitive list) impact configure's behavior: @@ -329,6 +338,7 @@ To install only parts of jemalloc, use the following targets: install_include install_lib_shared install_lib_static + install_lib_pc install_lib install_doc_html install_doc_man diff --git a/kbe/src/lib/dependencies/jemalloc/Makefile.in b/kbe/src/lib/dependencies/jemalloc/Makefile.in index fec1397a55..0777f6a8ab 100755 --- a/kbe/src/lib/dependencies/jemalloc/Makefile.in +++ b/kbe/src/lib/dependencies/jemalloc/Makefile.in @@ -24,7 +24,7 @@ abs_srcroot := @abs_srcroot@ abs_objroot := @abs_objroot@ # Build parameters. -CPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include +CPPFLAGS := @CPPFLAGS@ -I$(objroot)include -I$(srcroot)include CONFIGURE_CFLAGS := @CONFIGURE_CFLAGS@ SPECIFIED_CFLAGS := @SPECIFIED_CFLAGS@ EXTRA_CFLAGS := @EXTRA_CFLAGS@ @@ -47,6 +47,7 @@ REV := @rev@ install_suffix := @install_suffix@ ABI := @abi@ XSLTPROC := @XSLTPROC@ +XSLROOT := @XSLROOT@ AUTOCONF := @AUTOCONF@ _RPATH = @RPATH@ RPATH = $(if $(1),$(call _RPATH,$(1))) @@ -55,8 +56,11 @@ cfghdrs_out := @cfghdrs_out@ cfgoutputs_in := $(addprefix $(srcroot),@cfgoutputs_in@) cfgoutputs_out := @cfgoutputs_out@ enable_autogen := @enable_autogen@ +enable_shared := @enable_shared@ +enable_static := @enable_static@ enable_prof := @enable_prof@ enable_zone_allocator := @enable_zone_allocator@ +enable_experimental_smallocx := @enable_experimental_smallocx@ MALLOC_CONF := @JEMALLOC_CPREFIX@MALLOC_CONF link_whole_archive := @link_whole_archive@ DSO_LDFLAGS = @DSO_LDFLAGS@ @@ -93,15 +97,18 @@ C_SRCS := $(srcroot)src/jemalloc.c \ $(srcroot)src/arena.c \ $(srcroot)src/background_thread.c \ $(srcroot)src/base.c \ + $(srcroot)src/bin.c \ $(srcroot)src/bitmap.c \ $(srcroot)src/ckh.c \ $(srcroot)src/ctl.c \ + $(srcroot)src/div.c \ $(srcroot)src/extent.c \ $(srcroot)src/extent_dss.c \ $(srcroot)src/extent_mmap.c \ $(srcroot)src/hash.c \ - $(srcroot)src/hooks.c \ + $(srcroot)src/hook.c \ $(srcroot)src/large.c \ + $(srcroot)src/log.c \ $(srcroot)src/malloc_io.c \ $(srcroot)src/mutex.c \ $(srcroot)src/mutex_pool.c \ @@ -111,9 +118,10 @@ C_SRCS := $(srcroot)src/jemalloc.c \ $(srcroot)src/prof.c \ $(srcroot)src/rtree.c \ $(srcroot)src/stats.c \ - $(srcroot)src/spin.c \ + $(srcroot)src/sc.c \ $(srcroot)src/sz.c \ $(srcroot)src/tcache.c \ + $(srcroot)src/test_hooks.c \ $(srcroot)src/ticker.c \ $(srcroot)src/tsd.c \ $(srcroot)src/witness.c @@ -160,17 +168,24 @@ TESTS_UNIT := \ $(srcroot)test/unit/arena_reset.c \ $(srcroot)test/unit/atomic.c \ $(srcroot)test/unit/background_thread.c \ + $(srcroot)test/unit/background_thread_enable.c \ $(srcroot)test/unit/base.c \ $(srcroot)test/unit/bitmap.c \ + $(srcroot)test/unit/bit_util.c \ + $(srcroot)test/unit/binshard.c \ $(srcroot)test/unit/ckh.c \ $(srcroot)test/unit/decay.c \ + $(srcroot)test/unit/div.c \ + $(srcroot)test/unit/emitter.c \ $(srcroot)test/unit/extent_quantize.c \ $(srcroot)test/unit/fork.c \ $(srcroot)test/unit/hash.c \ - $(srcroot)test/unit/hooks.c \ + $(srcroot)test/unit/hook.c \ + $(srcroot)test/unit/huge.c \ $(srcroot)test/unit/junk.c \ $(srcroot)test/unit/junk_alloc.c \ $(srcroot)test/unit/junk_free.c \ + $(srcroot)test/unit/log.c \ $(srcroot)test/unit/mallctl.c \ $(srcroot)test/unit/malloc_io.c \ $(srcroot)test/unit/math.c \ @@ -184,6 +199,7 @@ TESTS_UNIT := \ $(srcroot)test/unit/prof_active.c \ $(srcroot)test/unit/prof_gdump.c \ $(srcroot)test/unit/prof_idump.c \ + $(srcroot)test/unit/prof_log.c \ $(srcroot)test/unit/prof_reset.c \ $(srcroot)test/unit/prof_tctx.c \ $(srcroot)test/unit/prof_thread_name.c \ @@ -192,13 +208,16 @@ TESTS_UNIT := \ $(srcroot)test/unit/rb.c \ $(srcroot)test/unit/retained.c \ $(srcroot)test/unit/rtree.c \ + $(srcroot)test/unit/seq.c \ $(srcroot)test/unit/SFMT.c \ + $(srcroot)test/unit/sc.c \ $(srcroot)test/unit/size_classes.c \ $(srcroot)test/unit/slab.c \ $(srcroot)test/unit/smoothstep.c \ $(srcroot)test/unit/spin.c \ $(srcroot)test/unit/stats.c \ $(srcroot)test/unit/stats_print.c \ + $(srcroot)test/unit/test_hooks.c \ $(srcroot)test/unit/ticker.c \ $(srcroot)test/unit/nstime.c \ $(srcroot)test/unit/tsd.c \ @@ -211,15 +230,21 @@ endif TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \ $(srcroot)test/integration/allocated.c \ $(srcroot)test/integration/extent.c \ + $(srcroot)test/integration/malloc.c \ $(srcroot)test/integration/mallocx.c \ $(srcroot)test/integration/MALLOCX_ARENA.c \ $(srcroot)test/integration/overflow.c \ $(srcroot)test/integration/posix_memalign.c \ $(srcroot)test/integration/rallocx.c \ $(srcroot)test/integration/sdallocx.c \ + $(srcroot)test/integration/slab_sizes.c \ $(srcroot)test/integration/thread_arena.c \ $(srcroot)test/integration/thread_tcache_enabled.c \ $(srcroot)test/integration/xallocx.c +ifeq (@enable_experimental_smallocx@, 1) +TESTS_INTEGRATION += \ + $(srcroot)test/integration/smallocx.c +endif ifeq (@enable_cxx@, 1) CPP_SRCS := $(srcroot)src/jemalloc_cpp.cpp TESTS_INTEGRATION_CPP := $(srcroot)test/integration/cpp/basic.cpp @@ -227,7 +252,9 @@ else CPP_SRCS := TESTS_INTEGRATION_CPP := endif -TESTS_STRESS := $(srcroot)test/stress/microbench.c +TESTS_STRESS := $(srcroot)test/stress/microbench.c \ + $(srcroot)test/stress/hookbench.c + TESTS := $(TESTS_UNIT) $(TESTS_INTEGRATION) $(TESTS_INTEGRATION_CPP) $(TESTS_STRESS) @@ -268,10 +295,24 @@ all: build_lib dist: build_doc $(objroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl +ifneq ($(XSLROOT),) $(XSLTPROC) -o $@ $(objroot)doc/html.xsl $< +else +ifeq ($(wildcard $(DOCS_HTML)),) + @echo "

Missing xsltproc. Doc not built.

" > $@ +endif + @echo "Missing xsltproc. "$@" not (re)built." +endif $(objroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl +ifneq ($(XSLROOT),) $(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $< +else +ifeq ($(wildcard $(DOCS_MAN3)),) + @echo "Missing xsltproc. Doc not built." > $@ +endif + @echo "Missing xsltproc. "$@" not (re)built." +endif build_doc_html: $(DOCS_HTML) build_doc_man: $(DOCS_MAN3) @@ -394,7 +435,7 @@ $(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(C_JET_OBJS) $(C_TESTLI $(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) @mkdir -p $(@D) - $(CC) $(TEST_LD_MODE) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LJEMALLOC) $(LDFLAGS) $(filter-out -lm,$(filter -lrt -lpthread -lstdc++,$(LIBS))) $(LM) $(EXTRA_LDFLAGS) + $(CC) $(TEST_LD_MODE) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LJEMALLOC) $(LDFLAGS) $(filter-out -lm,$(filter -lrt -pthread -lstdc++,$(LIBS))) $(LM) $(EXTRA_LDFLAGS) $(objroot)test/integration/cpp/%$(EXE): $(objroot)test/integration/cpp/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) @mkdir -p $(@D) @@ -406,7 +447,12 @@ $(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TE build_lib_shared: $(DSOS) build_lib_static: $(STATIC_LIBS) -build_lib: build_lib_shared build_lib_static +ifeq ($(enable_shared), 1) +build_lib: build_lib_shared +endif +ifeq ($(enable_static), 1) +build_lib: build_lib_static +endif install_bin: $(INSTALL) -d $(BINDIR) @@ -443,7 +489,13 @@ install_lib_pc: $(PC) $(INSTALL) -m 644 $$l $(LIBDIR)/pkgconfig; \ done -install_lib: install_lib_shared install_lib_static install_lib_pc +ifeq ($(enable_shared), 1) +install_lib: install_lib_shared +endif +ifeq ($(enable_static), 1) +install_lib: install_lib_static +endif +install_lib: install_lib_pc install_doc_html: $(INSTALL) -d $(DATADIR)/doc/jemalloc$(install_suffix) @@ -459,7 +511,7 @@ install_doc_man: $(INSTALL) -m 644 $$d $(MANDIR)/man3; \ done -install_doc: install_doc_html install_doc_man +install_doc: build_doc install_doc_html install_doc_man install: install_bin install_include install_lib install_doc diff --git a/kbe/src/lib/dependencies/jemalloc/TUNING.md b/kbe/src/lib/dependencies/jemalloc/TUNING.md new file mode 100644 index 0000000000..34fca05b43 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/TUNING.md @@ -0,0 +1,129 @@ +This document summarizes the common approaches for performance fine tuning with +jemalloc (as of 5.1.0). The default configuration of jemalloc tends to work +reasonably well in practice, and most applications should not have to tune any +options. However, in order to cover a wide range of applications and avoid +pathological cases, the default setting is sometimes kept conservative and +suboptimal, even for many common workloads. When jemalloc is properly tuned for +a specific application / workload, it is common to improve system level metrics +by a few percent, or make favorable trade-offs. + + +## Notable runtime options for performance tuning + +Runtime options can be set via +[malloc_conf](http://jemalloc.net/jemalloc.3.html#tuning). + +* [background_thread](http://jemalloc.net/jemalloc.3.html#background_thread) + + Enabling jemalloc background threads generally improves the tail latency for + application threads, since unused memory purging is shifted to the dedicated + background threads. In addition, unintended purging delay caused by + application inactivity is avoided with background threads. + + Suggested: `background_thread:true` when jemalloc managed threads can be + allowed. + +* [metadata_thp](http://jemalloc.net/jemalloc.3.html#opt.metadata_thp) + + Allowing jemalloc to utilize transparent huge pages for its internal + metadata usually reduces TLB misses significantly, especially for programs + with large memory footprint and frequent allocation / deallocation + activities. Metadata memory usage may increase due to the use of huge + pages. + + Suggested for allocation intensive programs: `metadata_thp:auto` or + `metadata_thp:always`, which is expected to improve CPU utilization at a + small memory cost. + +* [dirty_decay_ms](http://jemalloc.net/jemalloc.3.html#opt.dirty_decay_ms) and + [muzzy_decay_ms](http://jemalloc.net/jemalloc.3.html#opt.muzzy_decay_ms) + + Decay time determines how fast jemalloc returns unused pages back to the + operating system, and therefore provides a fairly straightforward trade-off + between CPU and memory usage. Shorter decay time purges unused pages faster + to reduces memory usage (usually at the cost of more CPU cycles spent on + purging), and vice versa. + + Suggested: tune the values based on the desired trade-offs. + +* [narenas](http://jemalloc.net/jemalloc.3.html#opt.narenas) + + By default jemalloc uses multiple arenas to reduce internal lock contention. + However high arena count may also increase overall memory fragmentation, + since arenas manage memory independently. When high degree of parallelism + is not expected at the allocator level, lower number of arenas often + improves memory usage. + + Suggested: if low parallelism is expected, try lower arena count while + monitoring CPU and memory usage. + +* [percpu_arena](http://jemalloc.net/jemalloc.3.html#opt.percpu_arena) + + Enable dynamic thread to arena association based on running CPU. This has + the potential to improve locality, e.g. when thread to CPU affinity is + present. + + Suggested: try `percpu_arena:percpu` or `percpu_arena:phycpu` if + thread migration between processors is expected to be infrequent. + +Examples: + +* High resource consumption application, prioritizing CPU utilization: + + `background_thread:true,metadata_thp:auto` combined with relaxed decay time + (increased `dirty_decay_ms` and / or `muzzy_decay_ms`, + e.g. `dirty_decay_ms:30000,muzzy_decay_ms:30000`). + +* High resource consumption application, prioritizing memory usage: + + `background_thread:true` combined with shorter decay time (decreased + `dirty_decay_ms` and / or `muzzy_decay_ms`, + e.g. `dirty_decay_ms:5000,muzzy_decay_ms:5000`), and lower arena count + (e.g. number of CPUs). + +* Low resource consumption application: + + `narenas:1,lg_tcache_max:13` combined with shorter decay time (decreased + `dirty_decay_ms` and / or `muzzy_decay_ms`,e.g. + `dirty_decay_ms:1000,muzzy_decay_ms:0`). + +* Extremely conservative -- minimize memory usage at all costs, only suitable when +allocation activity is very rare: + + `narenas:1,tcache:false,dirty_decay_ms:0,muzzy_decay_ms:0` + +Note that it is recommended to combine the options with `abort_conf:true` which +aborts immediately on illegal options. + +## Beyond runtime options + +In addition to the runtime options, there are a number of programmatic ways to +improve application performance with jemalloc. + +* [Explicit arenas](http://jemalloc.net/jemalloc.3.html#arenas.create) + + Manually created arenas can help performance in various ways, e.g. by + managing locality and contention for specific usages. For example, + applications can explicitly allocate frequently accessed objects from a + dedicated arena with + [mallocx()](http://jemalloc.net/jemalloc.3.html#MALLOCX_ARENA) to improve + locality. In addition, explicit arenas often benefit from individually + tuned options, e.g. relaxed [decay + time](http://jemalloc.net/jemalloc.3.html#arena.i.dirty_decay_ms) if + frequent reuse is expected. + +* [Extent hooks](http://jemalloc.net/jemalloc.3.html#arena.i.extent_hooks) + + Extent hooks allow customization for managing underlying memory. One use + case for performance purpose is to utilize huge pages -- for example, + [HHVM](https://github.com/facebook/hhvm/blob/master/hphp/util/alloc.cpp) + uses explicit arenas with customized extent hooks to manage 1GB huge pages + for frequently accessed data, which reduces TLB misses significantly. + +* [Explicit thread-to-arena + binding](http://jemalloc.net/jemalloc.3.html#thread.arena) + + It is common for some threads in an application to have different memory + access / allocation patterns. Threads with heavy workloads often benefit + from explicit binding, e.g. binding very active threads to dedicated arenas + may reduce contention at the allocator level. diff --git a/kbe/src/lib/dependencies/jemalloc/bin/jeprof.in b/kbe/src/lib/dependencies/jemalloc/bin/jeprof.in index e6f4af4b71..588c6b4381 100755 --- a/kbe/src/lib/dependencies/jemalloc/bin/jeprof.in +++ b/kbe/src/lib/dependencies/jemalloc/bin/jeprof.in @@ -2895,6 +2895,8 @@ sub RemoveUninterestingFrames { foreach my $name ('@JEMALLOC_PREFIX@calloc', 'cfree', '@JEMALLOC_PREFIX@malloc', + 'newImpl', + 'void* newImpl', '@JEMALLOC_PREFIX@free', '@JEMALLOC_PREFIX@memalign', '@JEMALLOC_PREFIX@posix_memalign', diff --git a/kbe/src/lib/dependencies/jemalloc/configure.ac b/kbe/src/lib/dependencies/jemalloc/configure.ac index 1551ded8ca..96f76d3553 100755 --- a/kbe/src/lib/dependencies/jemalloc/configure.ac +++ b/kbe/src/lib/dependencies/jemalloc/configure.ac @@ -8,9 +8,9 @@ dnl ============================================================================ dnl Custom macro definitions. dnl JE_CONCAT_VVV(r, a, b) -dnl +dnl dnl Set $r to the concatenation of $a and $b, with a space separating them iff -dnl both $a and $b are non-emty. +dnl both $a and $b are non-empty. AC_DEFUN([JE_CONCAT_VVV], if test "x[$]{$2}" = "x" -o "x[$]{$3}" = "x" ; then $1="[$]{$2}[$]{$3}" @@ -20,7 +20,7 @@ fi ) dnl JE_APPEND_VS(a, b) -dnl +dnl dnl Set $a to the concatenation of $a and b, with a space separating them iff dnl both $a and b are non-empty. AC_DEFUN([JE_APPEND_VS], @@ -31,7 +31,7 @@ AC_DEFUN([JE_APPEND_VS], CONFIGURE_CFLAGS= SPECIFIED_CFLAGS="${CFLAGS}" dnl JE_CFLAGS_ADD(cflag) -dnl +dnl dnl CFLAGS is the concatenation of CONFIGURE_CFLAGS and SPECIFIED_CFLAGS dnl (ignoring EXTRA_CFLAGS, which does not impact configure tests. This macro dnl appends to CONFIGURE_CFLAGS and regenerates CFLAGS. @@ -57,7 +57,7 @@ JE_CONCAT_VVV(CFLAGS, CONFIGURE_CFLAGS, SPECIFIED_CFLAGS) dnl JE_CFLAGS_SAVE() dnl JE_CFLAGS_RESTORE() -dnl +dnl dnl Save/restore CFLAGS. Nesting is not supported. AC_DEFUN([JE_CFLAGS_SAVE], SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}" @@ -76,6 +76,7 @@ AC_MSG_CHECKING([whether compiler supports $1]) T_CONFIGURE_CXXFLAGS="${CONFIGURE_CXXFLAGS}" JE_APPEND_VS(CONFIGURE_CXXFLAGS, $1) JE_CONCAT_VVV(CXXFLAGS, CONFIGURE_CXXFLAGS, SPECIFIED_CXXFLAGS) +AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM( [[ ]], [[ @@ -87,11 +88,12 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM( AC_MSG_RESULT([no]) [CONFIGURE_CXXFLAGS="${T_CONFIGURE_CXXFLAGS}"] ) +AC_LANG_POP([C++]) JE_CONCAT_VVV(CXXFLAGS, CONFIGURE_CXXFLAGS, SPECIFIED_CXXFLAGS) ]) dnl JE_COMPILABLE(label, hcode, mcode, rvar) -dnl +dnl dnl Use AC_LINK_IFELSE() rather than AC_COMPILE_IFELSE() so that linker errors dnl cause failure. AC_DEFUN([JE_COMPILABLE], @@ -173,6 +175,9 @@ fi ], XSLROOT="${DEFAULT_XSLROOT}" ) +if test "x$XSLTPROC" = "xfalse" ; then + XSLROOT="" +fi AC_SUBST([XSLROOT]) dnl If CFLAGS isn't defined, set CFLAGS to something reasonable. Otherwise, @@ -240,9 +245,11 @@ if test "x$GCC" = "xyes" ; then fi fi JE_CFLAGS_ADD([-Wall]) + JE_CFLAGS_ADD([-Wextra]) JE_CFLAGS_ADD([-Wshorten-64-to-32]) JE_CFLAGS_ADD([-Wsign-compare]) JE_CFLAGS_ADD([-Wundef]) + JE_CFLAGS_ADD([-Wno-format-zero-length]) JE_CFLAGS_ADD([-pipe]) JE_CFLAGS_ADD([-g3]) elif test "x$je_cv_msvc" = "xyes" ; then @@ -286,6 +293,7 @@ if test "x$enable_cxx" = "x1" ; then AX_CXX_COMPILE_STDCXX([14], [noext], [optional]) if test "x${HAVE_CXX14}" = "x1" ; then JE_CXXFLAGS_ADD([-Wall]) + JE_CXXFLAGS_ADD([-Wextra]) JE_CXXFLAGS_ADD([-g3]) SAVED_LIBS="${LIBS}" @@ -380,6 +388,7 @@ dnl CPU-specific settings. CPU_SPINWAIT="" case "${host_cpu}" in i686|x86_64) + HAVE_CPU_SPINWAIT=1 if test "x${je_cv_msvc}" = "xyes" ; then AC_CACHE_VAL([je_cv_pause_msvc], [JE_COMPILABLE([pause instruction MSVC], [], @@ -398,25 +407,36 @@ case "${host_cpu}" in fi fi ;; - powerpc*) - AC_DEFINE_UNQUOTED([HAVE_ALTIVEC], [ ]) - CPU_SPINWAIT='__asm__ volatile("or 31,31,31")' - ;; *) + HAVE_CPU_SPINWAIT=0 ;; esac +AC_DEFINE_UNQUOTED([HAVE_CPU_SPINWAIT], [$HAVE_CPU_SPINWAIT]) AC_DEFINE_UNQUOTED([CPU_SPINWAIT], [$CPU_SPINWAIT]) +AC_ARG_WITH([lg_vaddr], + [AS_HELP_STRING([--with-lg-vaddr=], [Number of significant virtual address bits])], + [LG_VADDR="$with_lg_vaddr"], [LG_VADDR="detect"]) + case "${host_cpu}" in aarch64) - AC_MSG_CHECKING([number of significant virtual address bits]) - LG_VADDR=48 - AC_MSG_RESULT([$LG_VADDR]) + if test "x$LG_VADDR" = "xdetect"; then + AC_MSG_CHECKING([number of significant virtual address bits]) + if test "x${LG_SIZEOF_PTR}" = "x2" ; then + #aarch64 ILP32 + LG_VADDR=32 + else + #aarch64 LP64 + LG_VADDR=48 + fi + AC_MSG_RESULT([$LG_VADDR]) + fi ;; x86_64) - AC_CACHE_CHECK([number of significant virtual address bits], - [je_cv_lg_vaddr], - AC_RUN_IFELSE([AC_LANG_PROGRAM( + if test "x$LG_VADDR" = "xdetect"; then + AC_CACHE_CHECK([number of significant virtual address bits], + [je_cv_lg_vaddr], + AC_RUN_IFELSE([AC_LANG_PROGRAM( [[ #include #ifdef _WIN32 @@ -453,27 +473,30 @@ typedef unsigned __int32 uint32_t; [je_cv_lg_vaddr=`cat conftest.out`], [je_cv_lg_vaddr=error], [je_cv_lg_vaddr=57])) - if test "x${je_cv_lg_vaddr}" != "x" ; then - LG_VADDR="${je_cv_lg_vaddr}" - fi - if test "x${LG_VADDR}" != "xerror" ; then - AC_DEFINE_UNQUOTED([LG_VADDR], [$LG_VADDR]) - else - AC_MSG_ERROR([cannot determine number of significant virtual address bits]) + if test "x${je_cv_lg_vaddr}" != "x" ; then + LG_VADDR="${je_cv_lg_vaddr}" + fi + if test "x${LG_VADDR}" != "xerror" ; then + AC_DEFINE_UNQUOTED([LG_VADDR], [$LG_VADDR]) + else + AC_MSG_ERROR([cannot determine number of significant virtual address bits]) + fi fi ;; *) - AC_MSG_CHECKING([number of significant virtual address bits]) - if test "x${LG_SIZEOF_PTR}" = "x3" ; then - LG_VADDR=64 - elif test "x${LG_SIZEOF_PTR}" = "x2" ; then - LG_VADDR=32 - elif test "x${LG_SIZEOF_PTR}" = "xLG_SIZEOF_PTR_WIN" ; then - LG_VADDR="(1U << (LG_SIZEOF_PTR_WIN+3))" - else - AC_MSG_ERROR([Unsupported lg(pointer size): ${LG_SIZEOF_PTR}]) + if test "x$LG_VADDR" = "xdetect"; then + AC_MSG_CHECKING([number of significant virtual address bits]) + if test "x${LG_SIZEOF_PTR}" = "x3" ; then + LG_VADDR=64 + elif test "x${LG_SIZEOF_PTR}" = "x2" ; then + LG_VADDR=32 + elif test "x${LG_SIZEOF_PTR}" = "xLG_SIZEOF_PTR_WIN" ; then + LG_VADDR="(1U << (LG_SIZEOF_PTR_WIN+3))" + else + AC_MSG_ERROR([Unsupported lg(pointer size): ${LG_SIZEOF_PTR}]) + fi + AC_MSG_RESULT([$LG_VADDR]) fi - AC_MSG_RESULT([$LG_VADDR]) ;; esac AC_DEFINE_UNQUOTED([LG_VADDR], [$LG_VADDR]) @@ -511,18 +534,83 @@ AN_PROGRAM([ar], [AC_PROG_AR]) AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)]) AC_PROG_AR +AN_MAKEVAR([NM], [AC_PROG_NM]) +AN_PROGRAM([nm], [AC_PROG_NM]) +AC_DEFUN([AC_PROG_NM], [AC_CHECK_TOOL(NM, nm, :)]) +AC_PROG_NM + AC_PROG_AWK +dnl ============================================================================ +dnl jemalloc version. +dnl + +AC_ARG_WITH([version], + [AS_HELP_STRING([--with-version=..--g], + [Version string])], + [ + echo "${with_version}" | grep ['^[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+-g[0-9a-f]\+$'] 2>&1 1>/dev/null + if test $? -eq 0 ; then + echo "$with_version" > "${objroot}VERSION" + else + echo "${with_version}" | grep ['^VERSION$'] 2>&1 1>/dev/null + if test $? -ne 0 ; then + AC_MSG_ERROR([${with_version} does not match ..--g or VERSION]) + fi + fi + ], [ + dnl Set VERSION if source directory is inside a git repository. + if test "x`test ! \"${srcroot}\" && cd \"${srcroot}\"; git rev-parse --is-inside-work-tree 2>/dev/null`" = "xtrue" ; then + dnl Pattern globs aren't powerful enough to match both single- and + dnl double-digit version numbers, so iterate over patterns to support up + dnl to version 99.99.99 without any accidental matches. + for pattern in ['[0-9].[0-9].[0-9]' '[0-9].[0-9].[0-9][0-9]' \ + '[0-9].[0-9][0-9].[0-9]' '[0-9].[0-9][0-9].[0-9][0-9]' \ + '[0-9][0-9].[0-9].[0-9]' '[0-9][0-9].[0-9].[0-9][0-9]' \ + '[0-9][0-9].[0-9][0-9].[0-9]' \ + '[0-9][0-9].[0-9][0-9].[0-9][0-9]']; do + (test ! "${srcroot}" && cd "${srcroot}"; git describe --long --abbrev=40 --match="${pattern}") > "${objroot}VERSION.tmp" 2>/dev/null + if test $? -eq 0 ; then + mv "${objroot}VERSION.tmp" "${objroot}VERSION" + break + fi + done + fi + rm -f "${objroot}VERSION.tmp" + ]) + +if test ! -e "${objroot}VERSION" ; then + if test ! -e "${srcroot}VERSION" ; then + AC_MSG_RESULT( + [Missing VERSION file, and unable to generate it; creating bogus VERSION]) + echo "0.0.0-0-g0000000000000000000000000000000000000000" > "${objroot}VERSION" + else + cp ${srcroot}VERSION ${objroot}VERSION + fi +fi +jemalloc_version=`cat "${objroot}VERSION"` +jemalloc_version_major=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]1}'` +jemalloc_version_minor=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]2}'` +jemalloc_version_bugfix=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]3}'` +jemalloc_version_nrev=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]4}'` +jemalloc_version_gid=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]5}'` +AC_SUBST([jemalloc_version]) +AC_SUBST([jemalloc_version_major]) +AC_SUBST([jemalloc_version_minor]) +AC_SUBST([jemalloc_version_bugfix]) +AC_SUBST([jemalloc_version_nrev]) +AC_SUBST([jemalloc_version_gid]) + dnl Platform-specific settings. abi and RPATH can probably be determined dnl programmatically, but doing so is error-prone, which makes it generally dnl not worth the trouble. -dnl +dnl dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the dnl definitions need to be seen before any headers are included, which is a pain dnl to make happen otherwise. default_retain="0" maps_coalesce="1" -DUMP_SYMS="nm -a" +DUMP_SYMS="${NM} -a" SYM_PREFIX="" case "${host}" in *-*-darwin* | *-*-ios*) @@ -556,7 +644,7 @@ case "${host}" in dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) abi="elf" - AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS]) + AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS], [ ]) AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ]) AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) @@ -566,11 +654,11 @@ case "${host}" in default_retain="1" fi ;; - *-*-linux* | *-*-kfreebsd*) + *-*-linux*) dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) abi="elf" - AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS]) + AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS], [ ]) AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ]) AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) @@ -579,6 +667,15 @@ case "${host}" in default_retain="1" fi ;; + *-*-kfreebsd*) + dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. + JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) + abi="elf" + AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) + AC_DEFINE([JEMALLOC_SYSCTL_VM_OVERCOMMIT], [ ]) + AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) + AC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ]) + ;; *-*-netbsd*) AC_MSG_CHECKING([ABI]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM( @@ -630,7 +727,13 @@ case "${host}" in DSO_LDFLAGS="-shared" link_whole_archive="1" fi - DUMP_SYMS="dumpbin /SYMBOLS" + case "${host}" in + *-*-cygwin*) + DUMP_SYMS="dumpbin /SYMBOLS" + ;; + *) + ;; + esac a="lib" libprefix="" SOREV="${so}" @@ -711,12 +814,9 @@ JE_COMPILABLE([tls_model attribute], [], foo = 0;], [je_cv_tls_model]) JE_CFLAGS_RESTORE() -if test "x${je_cv_tls_model}" = "xyes" ; then - AC_DEFINE([JEMALLOC_TLS_MODEL], - [__attribute__((tls_model("initial-exec")))]) -else - AC_DEFINE([JEMALLOC_TLS_MODEL], [ ]) -fi +dnl (Setting of JEMALLOC_TLS_MODEL is done later, after we've checked for +dnl --disable-initial-exec-tls) + dnl Check for alloc_size attribute support. JE_CFLAGS_SAVE() JE_CFLAGS_ADD([-Werror]) @@ -781,6 +881,36 @@ AC_PROG_RANLIB AC_PATH_PROG([LD], [ld], [false], [$PATH]) AC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH]) +dnl Enable shared libs +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared], [Build shared libaries])], +if test "x$enable_shared" = "xno" ; then + enable_shared="0" +else + enable_shared="1" +fi +, +enable_shared="1" +) +AC_SUBST([enable_shared]) + +dnl Enable static libs +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static], [Build static libaries])], +if test "x$enable_static" = "xno" ; then + enable_static="0" +else + enable_static="1" +fi +, +enable_static="1" +) +AC_SUBST([enable_static]) + +if test "$enable_shared$enable_static" = "00" ; then + AC_MSG_ERROR([Please enable one of shared or static builds]) +fi + dnl Perform no name mangling by default. AC_ARG_WITH([mangling], [AS_HELP_STRING([--with-mangling=], [Mangle symbols in ])], @@ -813,7 +943,7 @@ AC_ARG_WITH([export], fi] ) -public_syms="aligned_alloc calloc dallocx free mallctl mallctlbymib mallctlnametomib malloc malloc_conf malloc_message malloc_stats_print malloc_usable_size mallocx nallocx posix_memalign rallocx realloc sallocx sdallocx xallocx" +public_syms="aligned_alloc calloc dallocx free mallctl mallctlbymib mallctlnametomib malloc malloc_conf malloc_message malloc_stats_print malloc_usable_size mallocx smallocx_${jemalloc_version_gid} nallocx posix_memalign rallocx realloc sallocx sdallocx xallocx" dnl Check for additional platform-specific public API functions. AC_CHECK_FUNC([memalign], [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ]) @@ -931,7 +1061,6 @@ cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/private_symbols.sh" cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/private_namespace.sh" cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/public_namespace.sh" cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/public_unnamespace.sh" -cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/size_classes.sh" cfghdrs_in="${cfghdrs_in} include/jemalloc/jemalloc_rename.sh" cfghdrs_in="${cfghdrs_in} include/jemalloc/jemalloc_mangle.sh" cfghdrs_in="${cfghdrs_in} include/jemalloc/jemalloc.sh" @@ -944,7 +1073,6 @@ cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/private_symbols_jet.awk" cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/public_symbols.txt" cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/public_namespace.h" cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/public_unnamespace.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/size_classes.h" cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc_protos_jet.h" cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc_rename.h" cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc_mangle.h" @@ -956,6 +1084,10 @@ cfghdrs_tup="include/jemalloc/jemalloc_defs.h:include/jemalloc/jemalloc_defs.h.i cfghdrs_tup="${cfghdrs_tup} include/jemalloc/internal/jemalloc_internal_defs.h:include/jemalloc/internal/jemalloc_internal_defs.h.in" cfghdrs_tup="${cfghdrs_tup} test/include/test/jemalloc_test_defs.h:test/include/test/jemalloc_test_defs.h.in" +dnl ============================================================================ +dnl jemalloc build options. +dnl + dnl Do not compile with debugging by default. AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], @@ -1008,6 +1140,22 @@ if test "x$enable_stats" = "x1" ; then fi AC_SUBST([enable_stats]) +dnl Do not enable smallocx by default. +AC_ARG_ENABLE([experimental_smallocx], + [AS_HELP_STRING([--enable-experimental-smallocx], [Enable experimental smallocx API])], +[if test "x$enable_experimental_smallocx" = "xno" ; then +enable_experimental_smallocx="0" +else +enable_experimental_smallocx="1" +fi +], +[enable_experimental_smallocx="0"] +) +if test "x$enable_experimental_smallocx" = "x1" ; then + AC_DEFINE([JEMALLOC_EXPERIMENTAL_SMALLOCX_API]) +fi +AC_SUBST([enable_experimental_smallocx]) + dnl Do not enable profiling by default. AC_ARG_ENABLE([prof], [AS_HELP_STRING([--enable-prof], [Enable allocation profiling])], @@ -1226,7 +1374,54 @@ if test "x$enable_cache_oblivious" = "x1" ; then fi AC_SUBST([enable_cache_oblivious]) +dnl Do not log by default. +AC_ARG_ENABLE([log], + [AS_HELP_STRING([--enable-log], [Support debug logging])], +[if test "x$enable_log" = "xno" ; then + enable_log="0" +else + enable_log="1" +fi +], +[enable_log="0"] +) +if test "x$enable_log" = "x1" ; then + AC_DEFINE([JEMALLOC_LOG], [ ]) +fi +AC_SUBST([enable_log]) + +dnl Do not use readlinkat by default +AC_ARG_ENABLE([readlinkat], + [AS_HELP_STRING([--enable-readlinkat], [Use readlinkat over readlink])], +[if test "x$enable_readlinkat" = "xno" ; then + enable_readlinkat="0" +else + enable_readlinkat="1" +fi +], +[enable_readlinkat="0"] +) +if test "x$enable_readlinkat" = "x1" ; then + AC_DEFINE([JEMALLOC_READLINKAT], [ ]) +fi +AC_SUBST([enable_readlinkat]) +dnl Avoid the extra size checking by default +AC_ARG_ENABLE([extra-size-check], + [AS_HELP_STRING([--enable-extra-size-check], + [Perform additonal size related sanity checks])], +[if test "x$enable_extra_size_check" = "xno" ; then + enable_extra_size_check="0" +else + enable_extra_size_check="1" +fi +], +[enable_extra_size_check="0"] +) +if test "x$enable_extra_size_check" = "x1" ; then + AC_DEFINE([JEMALLOC_EXTRA_SIZE_CHECK], [ ]) +fi +AC_SUBST([enable_extra_size_check]) JE_COMPILABLE([a program using __builtin_unreachable], [ void foo (void) { @@ -1283,6 +1478,21 @@ else fi fi +JE_COMPILABLE([a program using __builtin_popcountl], [ +#include +#include +#include +], [ + { + int rv = __builtin_popcountl(0x08); + printf("%d\n", rv); + } +], [je_cv_gcc_builtin_popcountl]) +if test "x${je_cv_gcc_builtin_popcountl}" = "xyes" ; then + AC_DEFINE([JEMALLOC_INTERNAL_POPCOUNT], [__builtin_popcount]) + AC_DEFINE([JEMALLOC_INTERNAL_POPCOUNTL], [__builtin_popcountl]) +fi + AC_ARG_WITH([lg_quantum], [AS_HELP_STRING([--with-lg-quantum=], [Base 2 log of minimum allocation alignment])], @@ -1380,70 +1590,20 @@ if test "x${LG_PAGE}" != "xundefined" -a \ fi AC_DEFINE_UNQUOTED([LG_HUGEPAGE], [${je_cv_lg_hugepage}]) -AC_ARG_WITH([lg_page_sizes], - [AS_HELP_STRING([--with-lg-page-sizes=], - [Base 2 logs of system page sizes to support])], - [LG_PAGE_SIZES="$with_lg_page_sizes"], [LG_PAGE_SIZES="$LG_PAGE"]) - dnl ============================================================================ -dnl jemalloc configuration. -dnl - -AC_ARG_WITH([version], - [AS_HELP_STRING([--with-version=..--g], - [Version string])], - [ - echo "${with_version}" | grep ['^[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+-g[0-9a-f]\+$'] 2>&1 1>/dev/null - if test $? -eq 0 ; then - echo "$with_version" > "${objroot}VERSION" - else - echo "${with_version}" | grep ['^VERSION$'] 2>&1 1>/dev/null - if test $? -ne 0 ; then - AC_MSG_ERROR([${with_version} does not match ..--g or VERSION]) - fi - fi - ], [ - dnl Set VERSION if source directory is inside a git repository. - if test "x`test ! \"${srcroot}\" && cd \"${srcroot}\"; git rev-parse --is-inside-work-tree 2>/dev/null`" = "xtrue" ; then - dnl Pattern globs aren't powerful enough to match both single- and - dnl double-digit version numbers, so iterate over patterns to support up - dnl to version 99.99.99 without any accidental matches. - for pattern in ['[0-9].[0-9].[0-9]' '[0-9].[0-9].[0-9][0-9]' \ - '[0-9].[0-9][0-9].[0-9]' '[0-9].[0-9][0-9].[0-9][0-9]' \ - '[0-9][0-9].[0-9].[0-9]' '[0-9][0-9].[0-9].[0-9][0-9]' \ - '[0-9][0-9].[0-9][0-9].[0-9]' \ - '[0-9][0-9].[0-9][0-9].[0-9][0-9]']; do - (test ! "${srcroot}" && cd "${srcroot}"; git describe --long --abbrev=40 --match="${pattern}") > "${objroot}VERSION.tmp" 2>/dev/null - if test $? -eq 0 ; then - mv "${objroot}VERSION.tmp" "${objroot}VERSION" - break - fi - done - fi - rm -f "${objroot}VERSION.tmp" - ]) - -if test ! -e "${objroot}VERSION" ; then - if test ! -e "${srcroot}VERSION" ; then - AC_MSG_RESULT( - [Missing VERSION file, and unable to generate it; creating bogus VERSION]) - echo "0.0.0-0-g0000000000000000000000000000000000000000" > "${objroot}VERSION" - else - cp ${srcroot}VERSION ${objroot}VERSION - fi +dnl Enable libdl by default. +AC_ARG_ENABLE([libdl], + [AS_HELP_STRING([--disable-libdl], + [Do not use libdl])], +[if test "x$enable_libdl" = "xno" ; then + enable_libdl="0" +else + enable_libdl="1" fi -jemalloc_version=`cat "${objroot}VERSION"` -jemalloc_version_major=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]1}'` -jemalloc_version_minor=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]2}'` -jemalloc_version_bugfix=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]3}'` -jemalloc_version_nrev=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]4}'` -jemalloc_version_gid=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]5}'` -AC_SUBST([jemalloc_version]) -AC_SUBST([jemalloc_version_major]) -AC_SUBST([jemalloc_version_minor]) -AC_SUBST([jemalloc_version_bugfix]) -AC_SUBST([jemalloc_version_nrev]) -AC_SUBST([jemalloc_version_gid]) +], +[enable_libdl="1"] +) +AC_SUBST([libdl]) dnl ============================================================================ dnl Configure pthreads. @@ -1453,20 +1613,26 @@ if test "x$abi" != "xpecoff" ; then AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])]) dnl Some systems may embed pthreads functionality in libc; check for libpthread dnl first, but try libc too before failing. - AC_CHECK_LIB([pthread], [pthread_create], [JE_APPEND_VS(LIBS, -lpthread)], + AC_CHECK_LIB([pthread], [pthread_create], [JE_APPEND_VS(LIBS, -pthread)], [AC_SEARCH_LIBS([pthread_create], , , AC_MSG_ERROR([libpthread is missing]))]) wrap_syms="${wrap_syms} pthread_create" have_pthread="1" - dnl Check if we have dlsym support. - have_dlsym="1" - AC_CHECK_HEADERS([dlfcn.h], - AC_CHECK_FUNC([dlsym], [], - [AC_CHECK_LIB([dl], [dlsym], [LIBS="$LIBS -ldl"], [have_dlsym="0"])]), - [have_dlsym="0"]) - if test "x$have_dlsym" = "x1" ; then - AC_DEFINE([JEMALLOC_HAVE_DLSYM], [ ]) + +dnl Check if we have dlsym support. + if test "x$enable_libdl" = "x1" ; then + have_dlsym="1" + AC_CHECK_HEADERS([dlfcn.h], + AC_CHECK_FUNC([dlsym], [], + [AC_CHECK_LIB([dl], [dlsym], [LIBS="$LIBS -ldl"], [have_dlsym="0"])]), + [have_dlsym="0"]) + if test "x$have_dlsym" = "x1" ; then + AC_DEFINE([JEMALLOC_HAVE_DLSYM], [ ]) + fi + else + have_dlsym="0" fi + JE_COMPILABLE([pthread_atfork(3)], [ #include ], [ @@ -1730,6 +1896,19 @@ JE_COMPILABLE([GCC __atomic atomics], [ ], [je_cv_gcc_atomic_atomics]) if test "x${je_cv_gcc_atomic_atomics}" = "xyes" ; then AC_DEFINE([JEMALLOC_GCC_ATOMIC_ATOMICS]) + + dnl check for 8-bit atomic support + JE_COMPILABLE([GCC 8-bit __atomic atomics], [ + ], [ + unsigned char x = 0; + int val = 1; + int y = __atomic_fetch_add(&x, val, __ATOMIC_RELAXED); + int after_add = (int)x; + return after_add == 1; + ], [je_cv_gcc_u8_atomic_atomics]) + if test "x${je_cv_gcc_u8_atomic_atomics}" = "xyes" ; then + AC_DEFINE([JEMALLOC_GCC_U8_ATOMIC_ATOMICS]) + fi fi dnl ============================================================================ @@ -1744,12 +1923,24 @@ JE_COMPILABLE([GCC __sync atomics], [ ], [je_cv_gcc_sync_atomics]) if test "x${je_cv_gcc_sync_atomics}" = "xyes" ; then AC_DEFINE([JEMALLOC_GCC_SYNC_ATOMICS]) + + dnl check for 8-bit atomic support + JE_COMPILABLE([GCC 8-bit __sync atomics], [ + ], [ + unsigned char x = 0; + int before_add = __sync_fetch_and_add(&x, 1); + int after_add = (int)x; + return (before_add == 0) && (after_add == 1); + ], [je_cv_gcc_u8_sync_atomics]) + if test "x${je_cv_gcc_u8_sync_atomics}" = "xyes" ; then + AC_DEFINE([JEMALLOC_GCC_U8_SYNC_ATOMICS]) + fi fi dnl ============================================================================ dnl Check for atomic(3) operations as provided on Darwin. dnl We need this not for the atomic operations (which are provided above), but -dnl rather for the OSSpinLock type it exposes. +dnl rather for the OS_unfair_lock type it exposes. JE_COMPILABLE([Darwin OSAtomic*()], [ #include @@ -1789,6 +1980,15 @@ if test "x${je_cv_madvise}" = "xyes" ; then ], [je_cv_madv_free]) if test "x${je_cv_madv_free}" = "xyes" ; then AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ]) + elif test "x${je_cv_madvise}" = "xyes" ; then + case "${host_cpu}" in i686|x86_64) + case "${host}" in *-*-linux*) + AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ]) + AC_DEFINE([JEMALLOC_DEFINE_MADVISE_FREE], [ ]) + ;; + esac + ;; + esac fi dnl Check for madvise(..., MADV_DONTNEED). @@ -1801,6 +2001,17 @@ if test "x${je_cv_madvise}" = "xyes" ; then AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ]) fi + dnl Check for madvise(..., MADV_DO[NT]DUMP). + JE_COMPILABLE([madvise(..., MADV_DO[[NT]]DUMP)], [ +#include +], [ + madvise((void *)0, 0, MADV_DONTDUMP); + madvise((void *)0, 0, MADV_DODUMP); +], [je_cv_madv_dontdump]) + if test "x${je_cv_madv_dontdump}" = "xyes" ; then + AC_DEFINE([JEMALLOC_MADVISE_DONTDUMP], [ ]) + fi + dnl Check for madvise(..., MADV_[NO]HUGEPAGE). JE_COMPILABLE([madvise(..., MADV_[[NO]]HUGEPAGE)], [ #include @@ -1808,61 +2019,15 @@ if test "x${je_cv_madvise}" = "xyes" ; then madvise((void *)0, 0, MADV_HUGEPAGE); madvise((void *)0, 0, MADV_NOHUGEPAGE); ], [je_cv_thp]) -fi - -dnl Enable transparent huge page support by default. -AC_ARG_ENABLE([thp], - [AS_HELP_STRING([--disable-thp], - [Disable transparent huge page support])], -[if test "x$enable_thp" = "xno" -o "x${je_cv_thp}" != "xyes" ; then - enable_thp="0" -else - enable_thp="1" -fi -], -[if test "x${je_cv_thp}" = "xyes" ; then - enable_thp="1" -else - enable_thp="0" -fi -]) -if test "x$enable_thp" = "x1" ; then - AC_DEFINE([JEMALLOC_THP], [ ]) -fi -AC_SUBST([enable_thp]) - -dnl ============================================================================ -dnl Check whether __sync_{add,sub}_and_fetch() are available despite -dnl __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros being undefined. - -AC_DEFUN([JE_SYNC_COMPARE_AND_SWAP_CHECK],[ - AC_CACHE_CHECK([whether to force $1-bit __sync_{add,sub}_and_fetch()], - [je_cv_sync_compare_and_swap_$2], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([ - #include - ], - [ - #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2 - { - uint$1_t x$1 = 0; - __sync_add_and_fetch(&x$1, 42); - __sync_sub_and_fetch(&x$1, 1); - } - #else - #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2 is defined, no need to force - #endif - ])], - [je_cv_sync_compare_and_swap_$2=yes], - [je_cv_sync_compare_and_swap_$2=no])]) - - if test "x${je_cv_sync_compare_and_swap_$2}" = "xyes" ; then - AC_DEFINE([JE_FORCE_SYNC_COMPARE_AND_SWAP_$2], [ ]) +case "${host_cpu}" in + arm*) + ;; + *) + if test "x${je_cv_thp}" = "xyes" ; then + AC_DEFINE([JEMALLOC_HAVE_MADVISE_HUGE], [ ]) fi -]) - -if test "x${je_cv_atomic9}" != "xyes" -a "x${je_cv_osatomic}" != "xyes" ; then - JE_SYNC_COMPARE_AND_SWAP_CHECK(32, 4) - JE_SYNC_COMPARE_AND_SWAP_CHECK(64, 8) + ;; +esac fi dnl ============================================================================ @@ -1907,21 +2072,6 @@ if test "x${je_cv_os_unfair_lock}" = "xyes" ; then AC_DEFINE([JEMALLOC_OS_UNFAIR_LOCK], [ ]) fi -dnl ============================================================================ -dnl Check for spinlock(3) operations as provided on Darwin. - -JE_COMPILABLE([Darwin OSSpin*()], [ -#include -#include -], [ - OSSpinLock lock = 0; - OSSpinLockLock(&lock); - OSSpinLockUnlock(&lock); -], [je_cv_osspin]) -if test "x${je_cv_osspin}" = "xyes" ; then - AC_DEFINE([JEMALLOC_OSSPIN], [ ]) -fi - dnl ============================================================================ dnl Darwin-related configuration. @@ -1948,12 +2098,33 @@ if test "x${enable_zone_allocator}" = "x1" ; then AC_DEFINE([JEMALLOC_ZONE], [ ]) fi +dnl ============================================================================ +dnl Use initial-exec TLS by default. +AC_ARG_ENABLE([initial-exec-tls], + [AS_HELP_STRING([--disable-initial-exec-tls], + [Disable the initial-exec tls model])], +[if test "x$enable_initial_exec_tls" = "xno" ; then + enable_initial_exec_tls="0" +else + enable_initial_exec_tls="1" +fi +], +[enable_initial_exec_tls="1"] +) +AC_SUBST([enable_initial_exec_tls]) + +if test "x${je_cv_tls_model}" = "xyes" -a \ + "x${enable_initial_exec_tls}" = "x1" ; then + AC_DEFINE([JEMALLOC_TLS_MODEL], + [__attribute__((tls_model("initial-exec")))]) +else + AC_DEFINE([JEMALLOC_TLS_MODEL], [ ]) +fi + dnl ============================================================================ dnl Enable background threads if possible. -if test "x${have_pthread}" = "x1" -a "x${have_dlsym}" = "x1" \ - -a "x${je_cv_os_unfair_lock}" != "xyes" \ - -a "x${je_cv_osspin}" != "xyes" ; then +if test "x${have_pthread}" = "x1" -a "x${je_cv_os_unfair_lock}" != "xyes" ; then AC_DEFINE([JEMALLOC_BACKGROUND_THREAD]) fi @@ -2006,6 +2177,25 @@ if test "x${je_cv_pthread_mutex_adaptive_np}" = "xyes" ; then AC_DEFINE([JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP], [ ]) fi +JE_CFLAGS_SAVE() +JE_CFLAGS_ADD([-D_GNU_SOURCE]) +JE_CFLAGS_ADD([-Werror]) +JE_CFLAGS_ADD([-herror_on_warning]) +JE_COMPILABLE([strerror_r returns char with gnu source], [ +#include +#include +#include +#include +], [ + char *buffer = (char *) malloc(100); + char *error = strerror_r(EINVAL, buffer, 100); + printf("%s\n", error); +], [je_cv_strerror_r_returns_char_with_gnu_source]) +JE_CFLAGS_RESTORE() +if test "x${je_cv_strerror_r_returns_char_with_gnu_source}" = "xyes" ; then + AC_DEFINE([JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE], [ ]) +fi + dnl ============================================================================ dnl Check for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL @@ -2075,16 +2265,6 @@ AC_CONFIG_COMMANDS([include/jemalloc/internal/public_unnamespace.h], [ srcdir="${srcdir}" objroot="${objroot}" ]) -AC_CONFIG_COMMANDS([include/jemalloc/internal/size_classes.h], [ - mkdir -p "${objroot}include/jemalloc/internal" - "${SHELL}" "${srcdir}/include/jemalloc/internal/size_classes.sh" "${LG_QUANTA}" 3 "${LG_PAGE_SIZES}" 2 > "${objroot}include/jemalloc/internal/size_classes.h" -], [ - SHELL="${SHELL}" - srcdir="${srcdir}" - objroot="${objroot}" - LG_QUANTA="${LG_QUANTA}" - LG_PAGE_SIZES="${LG_PAGE_SIZES}" -]) AC_CONFIG_COMMANDS([include/jemalloc/jemalloc_protos_jet.h], [ mkdir -p "${objroot}include/jemalloc" cat "${srcdir}/include/jemalloc/jemalloc_protos.h.in" | sed -e 's/@je_@/jet_/g' > "${objroot}include/jemalloc/jemalloc_protos_jet.h" @@ -2177,17 +2357,20 @@ AC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE]) AC_MSG_RESULT([ : ${JEMALLOC_PRIVATE_NAMESPACE}]) AC_MSG_RESULT([install_suffix : ${install_suffix}]) AC_MSG_RESULT([malloc_conf : ${config_malloc_conf}]) +AC_MSG_RESULT([shared libs : ${enable_shared}]) +AC_MSG_RESULT([static libs : ${enable_static}]) AC_MSG_RESULT([autogen : ${enable_autogen}]) AC_MSG_RESULT([debug : ${enable_debug}]) AC_MSG_RESULT([stats : ${enable_stats}]) +AC_MSG_RESULT([experimetal_smallocx : ${enable_experimental_smallocx}]) AC_MSG_RESULT([prof : ${enable_prof}]) AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}]) AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}]) AC_MSG_RESULT([prof-gcc : ${enable_prof_gcc}]) -AC_MSG_RESULT([thp : ${enable_thp}]) AC_MSG_RESULT([fill : ${enable_fill}]) AC_MSG_RESULT([utrace : ${enable_utrace}]) AC_MSG_RESULT([xmalloc : ${enable_xmalloc}]) +AC_MSG_RESULT([log : ${enable_log}]) AC_MSG_RESULT([lazy_lock : ${enable_lazy_lock}]) AC_MSG_RESULT([cache-oblivious : ${enable_cache_oblivious}]) AC_MSG_RESULT([cxx : ${enable_cxx}]) diff --git a/kbe/src/lib/dependencies/jemalloc/doc/jemalloc.xml.in b/kbe/src/lib/dependencies/jemalloc/doc/jemalloc.xml.in index 21e401acb4..fd0edb30b0 100755 --- a/kbe/src/lib/dependencies/jemalloc/doc/jemalloc.xml.in +++ b/kbe/src/lib/dependencies/jemalloc/doc/jemalloc.xml.in @@ -433,10 +433,11 @@ for (i = 0; i < nbins; i++) { arena statistics, respectively; b and l can be specified to omit per size class statistics for bins and large objects, respectively; x can be specified to omit all mutex - statistics. Unrecognized characters are silently ignored. Note that - thread caching may prevent some statistics from being completely up to - date, since extra locking would be required to merge counters that track - thread cache operations. + statistics; e can be used to omit extent statistics. + Unrecognized characters are silently ignored. Note that thread caching + may prevent some statistics from being completely up to date, since extra + locking would be required to merge counters that track thread cache + operations. The malloc_usable_size() function returns the usable size of the allocation pointed to by @@ -761,6 +762,18 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", selected pthread-based platforms. + + + max_background_threads + (size_t) + rw + + Maximum number of background worker threads that will + be created. This value is capped at opt.max_background_threads at + startup. + + config.cache_oblivious @@ -852,16 +865,6 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", build configuration. - - - config.thp - (bool) - r- - - was not specified - during build configuration, and the system supports transparent huge - page manipulation. - @@ -916,6 +919,20 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", + + + opt.metadata_thp + (const char *) + r- + + Controls whether to allow jemalloc to use transparent + huge page (THP) for internal metadata (see stats.metadata). always + allows such usage. auto uses no THP initially, but may + begin to do so when metadata usage reaches certain level. The default + is disabled. + + opt.retain @@ -927,6 +944,9 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", munmap 2 or equivalent (see stats.retained for related details). + It also makes jemalloc use + mmap2 + in a more greedy way, mapping larger chunks in one go. This option is disabled by default unless discarding virtual memory is known to trigger platform-specific performance problems, e.g. for [64-bit] Linux, which @@ -972,6 +992,24 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", number of CPUs, or one if there is a single CPU. + + + opt.oversize_threshold + (size_t) + r- + + The threshold in bytes of which requests are considered + oversize. Allocation requests with greater sizes are fulfilled from a + dedicated arena (automatically managed, however not within + narenas), in order to reduce fragmentation by not + mixing huge allocations with small ones. In addition, the decay API + guarantees on the extents greater than the specified threshold may be + overridden. Note that requests with arena index specified via + MALLOCX_ARENA, or threads associated with explicit + arenas will not be considered. The default threshold is 8MiB. Values + not within large size classes disables this feature. + + opt.percpu_arena @@ -993,15 +1031,29 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", opt.background_thread - (const bool) + (bool) r- - Internal background worker threads enabled/disabled. See - background_thread for dynamic - control options and details. This option is disabled by + Internal background worker threads enabled/disabled. + Because of potential circular dependencies, enabling background thread + using this option may cause crash or deadlock during initialization. For + a reliable way to use this feature, see background_thread for dynamic control + options and details. This option is disabled by default. + + + opt.max_background_threads + (size_t) + r- + + Maximum number of background threads that will be created + if background_thread is set. + Defaults to number of cpus. + + opt.dirty_decay_ms @@ -1022,10 +1074,14 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", The default decay time is 10 seconds. See arenas.dirty_decay_ms and arena.<i>.muzzy_decay_ms + linkend="arena.i.dirty_decay_ms">arena.<i>.dirty_decay_ms for related dynamic control options. See opt.muzzy_decay_ms - for a description of muzzy pages. + for a description of muzzy pages.for a description of muzzy pages. Note + that when the oversize_threshold + feature is enabled, the arenas reserved for oversize requests may have + its own default decay settings. @@ -1052,6 +1108,22 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", for related dynamic control options. + + + opt.lg_extent_max_active_fit + (size_t) + r- + + When reusing dirty extents, this determines the (log + base 2 of the) maximum ratio between the size of the active extent + selected (to split off from) and the size of the requested allocation. + This prevents the splitting of large active extents for smaller + allocations, which can reduce fragmentation over the long run + (especially for non-active extents). Lower value may reduce + fragmentation, at the cost of extra active extents. The default value + is 6, which gives a maximum ratio of 64 (2^6). + + opt.stats_print @@ -1194,6 +1266,28 @@ malloc_conf = "xmalloc:true";]]> default maximum is 32 KiB (2^15). + + + opt.thp + (const char *) + r- + + Transparent hugepage (THP) mode. Settings "always", + "never" and "default" are available if THP is supported by the operating + system. The "always" setting enables transparent hugepage for all user + memory mappings with + MADV_HUGEPAGE; "never" + ensures no transparent hugepage with + MADV_NOHUGEPAGE; the default + setting "default" makes no changes. Note that: this option does not + affect THP for jemalloc internal metadata (see opt.metadata_thp); + in addition, for arenas with customized extent_hooks, + this option is bypassed as it is implemented as part of the default + extent hooks. + + opt.prof @@ -1666,6 +1760,22 @@ malloc_conf = "xmalloc:true";]]> for additional information. + + + arena.<i>.retain_grow_limit + (size_t) + rw + + Maximum size to grow retained region (only relevant when + opt.retain is + enabled). This controls the maximum increment to expand virtual memory, + or allocation through arena.<i>extent_hooks. + In particular, if customized extent hooks reserve physical memory + (e.g. 1G huge pages), this is useful to control the allocation hook's + input size. The default is no limit. + + arena.<i>.extent_hooks @@ -1679,10 +1789,11 @@ malloc_conf = "xmalloc:true";]]> to control allocation for arenas explicitly created via arenas.create such that all extents originate from an application-supplied extent allocator - (by specifying the custom extent hook functions during arena creation), - but the automatically created arenas will have already created extents - prior to the application having an opportunity to take over extent - allocation. + (by specifying the custom extent hook functions during arena creation). + However, the API guarantees for the automatically created arenas may be + relaxed -- hooks set there may be called in a "best effort" fashion; in + addition there may be extents created prior to the application having an + opportunity to take over extent allocation. NULL, or selectively opted out - of by returning failure. + of by returning failure. Note that once the extent hook is set, the + structure is accessed directly by the associated arenas, so it must + remain valid for the entire lifetime of the arenas. typedef void *(extent_alloc_t) @@ -2044,6 +2157,15 @@ struct extent_hooks_s { and return the new arena index. + + + arenas.lookup + (unsigned, void*) + rw + + Index of the arena to which an allocation belongs to. + + prof.thread_active_init @@ -2187,7 +2309,24 @@ struct extent_hooks_s { metadata structures (see stats.arenas.<i>.base) and internal allocations (see stats.arenas.<i>.internal). + linkend="stats.arenas.i.internal">stats.arenas.<i>.internal). + Transparent huge page (enabled with opt.metadata_thp) usage is not + considered. + + + + + stats.metadata_thp + (size_t) + r- + [] + + Number of transparent huge pages (THP) used for + metadata. See stats.metadata and + opt.metadata_thp) for + details. @@ -2481,6 +2620,17 @@ struct extent_hooks_s { details. + + + stats.arenas.<i>.extent_avail + (size_t) + r- + [] + + Number of allocated (but unused) extent structs in this + arena. + + stats.arenas.<i>.base @@ -2506,6 +2656,18 @@ struct extent_hooks_s { profiles. + + + stats.arenas.<i>.metadata_thp + (size_t) + r- + [] + + Number of transparent huge pages (THP) used for + metadata. See opt.metadata_thp + for details. + + stats.arenas.<i>.resident @@ -2798,6 +2960,30 @@ struct extent_hooks_s { counters. + + + stats.arenas.<i>.extents.<j>.n{extent_type} + (size_t) + r- + [] + + Number of extents of the given type in this arena in + the bucket corresponding to page size index <j>. The extent type + is one of dirty, muzzy, or retained. + + + + + stats.arenas.<i>.extents.<j>.{extent_type}_bytes + (size_t) + r- + [] + + Sum of the bytes managed by extents of the given type + in this arena in the bucket corresponding to page size index <j>. + The extent type is one of dirty, muzzy, or retained. + + stats.arenas.<i>.lextents.<j>.nmalloc diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_externs.h index af16d15885..2bdddb77a0 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_externs.h @@ -1,33 +1,32 @@ #ifndef JEMALLOC_INTERNAL_ARENA_EXTERNS_H #define JEMALLOC_INTERNAL_ARENA_EXTERNS_H +#include "jemalloc/internal/bin.h" #include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/hook.h" #include "jemalloc/internal/pages.h" -#include "jemalloc/internal/size_classes.h" #include "jemalloc/internal/stats.h" extern ssize_t opt_dirty_decay_ms; extern ssize_t opt_muzzy_decay_ms; -extern const arena_bin_info_t arena_bin_info[NBINS]; - extern percpu_arena_mode_t opt_percpu_arena; extern const char *percpu_arena_mode_names[]; extern const uint64_t h_steps[SMOOTHSTEP_NSTEPS]; extern malloc_mutex_t arenas_lock; -void arena_stats_large_nrequests_add(tsdn_t *tsdn, arena_stats_t *arena_stats, - szind_t szind, uint64_t nrequests); -void arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats, - size_t size); +extern size_t opt_oversize_threshold; +extern size_t oversize_threshold; + void arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms, size_t *nactive, size_t *ndirty, size_t *nmuzzy); void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms, size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats, - malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats); + bin_stats_t *bstats, arena_stats_large_t *lstats, + arena_stats_extents_t *estats); void arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extent_t *extent); #ifdef JEMALLOC_JET @@ -50,11 +49,11 @@ void arena_decay(tsdn_t *tsdn, arena_t *arena, bool is_background_thread, void arena_reset(tsd_t *tsd, arena_t *arena); void arena_destroy(tsd_t *tsd, arena_t *arena); void arena_tcache_fill_small(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, - tcache_bin_t *tbin, szind_t binind, uint64_t prof_accumbytes); -void arena_alloc_junk_small(void *ptr, const arena_bin_info_t *bin_info, + cache_bin_t *tbin, szind_t binind, uint64_t prof_accumbytes); +void arena_alloc_junk_small(void *ptr, const bin_info_t *bin_info, bool zero); -typedef void (arena_dalloc_junk_small_t)(void *, const arena_bin_info_t *); +typedef void (arena_dalloc_junk_small_t)(void *, const bin_info_t *); extern arena_dalloc_junk_small_t *JET_MUTABLE arena_dalloc_junk_small; void *arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, @@ -64,25 +63,33 @@ void *arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, void arena_prof_promote(tsdn_t *tsdn, const void *ptr, size_t usize); void arena_dalloc_promoted(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool slow_path); -void arena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena, - extent_t *extent, void *ptr); +void arena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena, bin_t *bin, + szind_t binind, extent_t *extent, void *ptr); void arena_dalloc_small(tsdn_t *tsdn, void *ptr); bool arena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, - size_t extra, bool zero); + size_t extra, bool zero, size_t *newsize); void *arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, - size_t size, size_t alignment, bool zero, tcache_t *tcache); + size_t size, size_t alignment, bool zero, tcache_t *tcache, + hook_ralloc_args_t *hook_args); dss_prec_t arena_dss_prec_get(arena_t *arena); bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec); ssize_t arena_dirty_decay_ms_default_get(void); bool arena_dirty_decay_ms_default_set(ssize_t decay_ms); ssize_t arena_muzzy_decay_ms_default_get(void); bool arena_muzzy_decay_ms_default_set(ssize_t decay_ms); +bool arena_retain_grow_limit_get_set(tsd_t *tsd, arena_t *arena, + size_t *old_limit, size_t *new_limit); unsigned arena_nthreads_get(arena_t *arena, bool internal); void arena_nthreads_inc(arena_t *arena, bool internal); void arena_nthreads_dec(arena_t *arena, bool internal); size_t arena_extent_sn_next(arena_t *arena); arena_t *arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks); -void arena_boot(void); +bool arena_init_huge(void); +bool arena_is_huge(unsigned arena_ind); +arena_t *arena_choose_huge(tsd_t *tsd); +bin_t *arena_bin_choose_lock(tsdn_t *tsdn, arena_t *arena, szind_t binind, + unsigned *binshard); +void arena_boot(sc_data_t *sc_data); void arena_prefork0(tsdn_t *tsdn, arena_t *arena); void arena_prefork1(tsdn_t *tsdn, arena_t *arena); void arena_prefork2(tsdn_t *tsdn, arena_t *arena); diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_a.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_a.h index da5877060a..9abf7f6ac7 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_a.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_a.h @@ -25,7 +25,7 @@ static inline bool arena_prof_accum(tsdn_t *tsdn, arena_t *arena, uint64_t accumbytes) { cassert(config_prof); - if (likely(prof_interval == 0)) { + if (likely(prof_interval == 0 || !prof_active_get_unlocked())) { return false; } diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_b.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_b.h index 003abe116f..614deddd20 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_b.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_inlines_b.h @@ -4,15 +4,34 @@ #include "jemalloc/internal/jemalloc_internal_types.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/rtree.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/sz.h" #include "jemalloc/internal/ticker.h" -static inline szind_t -arena_bin_index(arena_t *arena, arena_bin_t *bin) { - szind_t binind = (szind_t)(bin - arena->bins); - assert(binind < NBINS); - return binind; +JEMALLOC_ALWAYS_INLINE bool +arena_has_default_hooks(arena_t *arena) { + return (extent_hooks_get(arena) == &extent_hooks_default); +} + +JEMALLOC_ALWAYS_INLINE arena_t * +arena_choose_maybe_huge(tsd_t *tsd, arena_t *arena, size_t size) { + if (arena != NULL) { + return arena; + } + + /* + * For huge allocations, use the dedicated huge arena if both are true: + * 1) is using auto arena selection (i.e. arena == NULL), and 2) the + * thread is not assigned to a manual arena. + */ + if (unlikely(size >= oversize_threshold)) { + arena_t *tsd_arena = tsd_arena_get(tsd); + if (tsd_arena == NULL || arena_is_auto(tsd_arena)) { + return arena_choose_huge(tsd); + } + } + + return arena_choose(tsd, NULL); } JEMALLOC_ALWAYS_INLINE prof_tctx_t * @@ -64,6 +83,32 @@ arena_prof_tctx_reset(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx) { large_prof_tctx_reset(tsdn, extent); } +JEMALLOC_ALWAYS_INLINE nstime_t +arena_prof_alloc_time_get(tsdn_t *tsdn, const void *ptr, + alloc_ctx_t *alloc_ctx) { + cassert(config_prof); + assert(ptr != NULL); + + extent_t *extent = iealloc(tsdn, ptr); + /* + * Unlike arena_prof_prof_tctx_{get, set}, we only call this once we're + * sure we have a sampled allocation. + */ + assert(!extent_slab_get(extent)); + return large_prof_alloc_time_get(extent); +} + +JEMALLOC_ALWAYS_INLINE void +arena_prof_alloc_time_set(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx, + nstime_t t) { + cassert(config_prof); + assert(ptr != NULL); + + extent_t *extent = iealloc(tsdn, ptr); + assert(!extent_slab_get(extent)); + large_prof_alloc_time_set(extent, t); +} + JEMALLOC_ALWAYS_INLINE void arena_decay_ticks(tsdn_t *tsdn, arena_t *arena, unsigned nticks) { tsd_t *tsd; @@ -90,14 +135,33 @@ arena_decay_tick(tsdn_t *tsdn, arena_t *arena) { arena_decay_ticks(tsdn, arena, 1); } +/* Purge a single extent to retained / unmapped directly. */ +JEMALLOC_ALWAYS_INLINE void +arena_decay_extent(tsdn_t *tsdn,arena_t *arena, extent_hooks_t **r_extent_hooks, + extent_t *extent) { + size_t extent_size = extent_size_get(extent); + extent_dalloc_wrapper(tsdn, arena, + r_extent_hooks, extent); + if (config_stats) { + /* Update stats accordingly. */ + arena_stats_lock(tsdn, &arena->stats); + arena_stats_add_u64(tsdn, &arena->stats, + &arena->decay_dirty.stats->nmadvise, 1); + arena_stats_add_u64(tsdn, &arena->stats, + &arena->decay_dirty.stats->purged, extent_size >> LG_PAGE); + arena_stats_sub_zu(tsdn, &arena->stats, &arena->stats.mapped, + extent_size); + arena_stats_unlock(tsdn, &arena->stats); + } +} + JEMALLOC_ALWAYS_INLINE void * arena_malloc(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, bool zero, tcache_t *tcache, bool slow_path) { assert(!tsdn_null(tsdn) || tcache == NULL); - assert(size != 0); if (likely(tcache != NULL)) { - if (likely(size <= SMALL_MAXCLASS)) { + if (likely(size <= SC_SMALL_MAXCLASS)) { return tcache_alloc_small(tsdn_tsd(tsdn), arena, tcache, size, ind, zero, slow_path); } @@ -126,7 +190,7 @@ arena_salloc(tsdn_t *tsdn, const void *ptr) { szind_t szind = rtree_szind_read(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, true); - assert(szind != NSIZES); + assert(szind != SC_NSIZES); return sz_index2size(szind); } @@ -159,7 +223,7 @@ arena_vsalloc(tsdn_t *tsdn, const void *ptr) { /* Only slab members should be looked up via interior pointers. */ assert(extent_addr_get(extent) == ptr || extent_slab_get(extent)); - assert(szind != NSIZES); + assert(szind != SC_NSIZES); return sz_index2size(szind); } @@ -180,7 +244,7 @@ arena_dalloc_no_tcache(tsdn_t *tsdn, void *ptr) { extent_t *extent = rtree_extent_read(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, true); assert(szind == extent_szind_get(extent)); - assert(szind < NSIZES); + assert(szind < SC_NSIZES); assert(slab == extent_slab_get(extent)); } @@ -210,7 +274,7 @@ arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, if (alloc_ctx != NULL) { szind = alloc_ctx->szind; slab = alloc_ctx->slab; - assert(szind != NSIZES); + assert(szind != SC_NSIZES); } else { rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn)); rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, @@ -222,7 +286,7 @@ arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, extent_t *extent = rtree_extent_read(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, true); assert(szind == extent_szind_get(extent)); - assert(szind < NSIZES); + assert(szind < SC_NSIZES); assert(slab == extent_slab_get(extent)); } @@ -232,7 +296,7 @@ arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, slow_path); } else { if (szind < nhbins) { - if (config_prof && unlikely(szind < NBINS)) { + if (config_prof && unlikely(szind < SC_NBINS)) { arena_dalloc_promoted(tsdn, ptr, tcache, slow_path); } else { @@ -249,7 +313,7 @@ arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, static inline void arena_sdalloc_no_tcache(tsdn_t *tsdn, void *ptr, size_t size) { assert(ptr != NULL); - assert(size <= LARGE_MAXCLASS); + assert(size <= SC_LARGE_MAXCLASS); szind_t szind; bool slab; @@ -259,7 +323,7 @@ arena_sdalloc_no_tcache(tsdn_t *tsdn, void *ptr, size_t size) { * object, so base szind and slab on the given size. */ szind = sz_size2index(size); - slab = (szind < NBINS); + slab = (szind < SC_NBINS); } if ((config_prof && opt_prof) || config_debug) { @@ -271,7 +335,7 @@ arena_sdalloc_no_tcache(tsdn_t *tsdn, void *ptr, size_t size) { (uintptr_t)ptr, true, &szind, &slab); assert(szind == sz_size2index(size)); - assert((config_prof && opt_prof) || slab == (szind < NBINS)); + assert((config_prof && opt_prof) || slab == (szind < SC_NBINS)); if (config_debug) { extent_t *extent = rtree_extent_read(tsdn, @@ -295,7 +359,7 @@ arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, alloc_ctx_t *alloc_ctx, bool slow_path) { assert(!tsdn_null(tsdn) || tcache == NULL); assert(ptr != NULL); - assert(size <= LARGE_MAXCLASS); + assert(size <= SC_LARGE_MAXCLASS); if (unlikely(tcache == NULL)) { arena_sdalloc_no_tcache(tsdn, ptr, size); @@ -304,7 +368,7 @@ arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, szind_t szind; bool slab; - UNUSED alloc_ctx_t local_ctx; + alloc_ctx_t local_ctx; if (config_prof && opt_prof) { if (alloc_ctx == NULL) { /* Uncommon case and should be a static check. */ @@ -325,7 +389,7 @@ arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, * object, so base szind and slab on the given size. */ szind = sz_size2index(size); - slab = (szind < NBINS); + slab = (szind < SC_NBINS); } if (config_debug) { @@ -344,7 +408,7 @@ arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, slow_path); } else { if (szind < nhbins) { - if (config_prof && unlikely(szind < NBINS)) { + if (config_prof && unlikely(szind < SC_NBINS)) { arena_dalloc_promoted(tsdn, ptr, tcache, slow_path); } else { diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_stats.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_stats.h new file mode 100644 index 0000000000..ef1e25b31f --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_stats.h @@ -0,0 +1,258 @@ +#ifndef JEMALLOC_INTERNAL_ARENA_STATS_H +#define JEMALLOC_INTERNAL_ARENA_STATS_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/mutex_prof.h" +#include "jemalloc/internal/sc.h" + +JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS + +/* + * In those architectures that support 64-bit atomics, we use atomic updates for + * our 64-bit values. Otherwise, we use a plain uint64_t and synchronize + * externally. + */ +#ifdef JEMALLOC_ATOMIC_U64 +typedef atomic_u64_t arena_stats_u64_t; +#else +/* Must hold the arena stats mutex while reading atomically. */ +typedef uint64_t arena_stats_u64_t; +#endif + +typedef struct arena_stats_large_s arena_stats_large_t; +struct arena_stats_large_s { + /* + * Total number of allocation/deallocation requests served directly by + * the arena. + */ + arena_stats_u64_t nmalloc; + arena_stats_u64_t ndalloc; + + /* + * Number of allocation requests that correspond to this size class. + * This includes requests served by tcache, though tcache only + * periodically merges into this counter. + */ + arena_stats_u64_t nrequests; /* Partially derived. */ + + /* Current number of allocations of this size class. */ + size_t curlextents; /* Derived. */ +}; + +typedef struct arena_stats_decay_s arena_stats_decay_t; +struct arena_stats_decay_s { + /* Total number of purge sweeps. */ + arena_stats_u64_t npurge; + /* Total number of madvise calls made. */ + arena_stats_u64_t nmadvise; + /* Total number of pages purged. */ + arena_stats_u64_t purged; +}; + +typedef struct arena_stats_extents_s arena_stats_extents_t; +struct arena_stats_extents_s { + /* + * Stats for a given index in the range [0, SC_NPSIZES] in an extents_t. + * We track both bytes and # of extents: two extents in the same bucket + * may have different sizes if adjacent size classes differ by more than + * a page, so bytes cannot always be derived from # of extents. + */ + atomic_zu_t ndirty; + atomic_zu_t dirty_bytes; + atomic_zu_t nmuzzy; + atomic_zu_t muzzy_bytes; + atomic_zu_t nretained; + atomic_zu_t retained_bytes; +}; + +/* + * Arena stats. Note that fields marked "derived" are not directly maintained + * within the arena code; rather their values are derived during stats merge + * requests. + */ +typedef struct arena_stats_s arena_stats_t; +struct arena_stats_s { +#ifndef JEMALLOC_ATOMIC_U64 + malloc_mutex_t mtx; +#endif + + /* Number of bytes currently mapped, excluding retained memory. */ + atomic_zu_t mapped; /* Partially derived. */ + + /* + * Number of unused virtual memory bytes currently retained. Retained + * bytes are technically mapped (though always decommitted or purged), + * but they are excluded from the mapped statistic (above). + */ + atomic_zu_t retained; /* Derived. */ + + /* Number of extent_t structs allocated by base, but not being used. */ + atomic_zu_t extent_avail; + + arena_stats_decay_t decay_dirty; + arena_stats_decay_t decay_muzzy; + + atomic_zu_t base; /* Derived. */ + atomic_zu_t internal; + atomic_zu_t resident; /* Derived. */ + atomic_zu_t metadata_thp; + + atomic_zu_t allocated_large; /* Derived. */ + arena_stats_u64_t nmalloc_large; /* Derived. */ + arena_stats_u64_t ndalloc_large; /* Derived. */ + arena_stats_u64_t nrequests_large; /* Derived. */ + + /* Number of bytes cached in tcache associated with this arena. */ + atomic_zu_t tcache_bytes; /* Derived. */ + + mutex_prof_data_t mutex_prof_data[mutex_prof_num_arena_mutexes]; + + /* One element for each large size class. */ + arena_stats_large_t lstats[SC_NSIZES - SC_NBINS]; + + /* Arena uptime. */ + nstime_t uptime; +}; + +static inline bool +arena_stats_init(tsdn_t *tsdn, arena_stats_t *arena_stats) { + if (config_debug) { + for (size_t i = 0; i < sizeof(arena_stats_t); i++) { + assert(((char *)arena_stats)[i] == 0); + } + } +#ifndef JEMALLOC_ATOMIC_U64 + if (malloc_mutex_init(&arena_stats->mtx, "arena_stats", + WITNESS_RANK_ARENA_STATS, malloc_mutex_rank_exclusive)) { + return true; + } +#endif + /* Memory is zeroed, so there is no need to clear stats. */ + return false; +} + +static inline void +arena_stats_lock(tsdn_t *tsdn, arena_stats_t *arena_stats) { +#ifndef JEMALLOC_ATOMIC_U64 + malloc_mutex_lock(tsdn, &arena_stats->mtx); +#endif +} + +static inline void +arena_stats_unlock(tsdn_t *tsdn, arena_stats_t *arena_stats) { +#ifndef JEMALLOC_ATOMIC_U64 + malloc_mutex_unlock(tsdn, &arena_stats->mtx); +#endif +} + +static inline uint64_t +arena_stats_read_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, + arena_stats_u64_t *p) { +#ifdef JEMALLOC_ATOMIC_U64 + return atomic_load_u64(p, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + return *p; +#endif +} + +static inline void +arena_stats_add_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, + arena_stats_u64_t *p, uint64_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + atomic_fetch_add_u64(p, x, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + *p += x; +#endif +} + +static inline void +arena_stats_sub_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, + arena_stats_u64_t *p, uint64_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + uint64_t r = atomic_fetch_sub_u64(p, x, ATOMIC_RELAXED); + assert(r - x <= r); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + *p -= x; + assert(*p + x >= *p); +#endif +} + +/* + * Non-atomically sets *dst += src. *dst needs external synchronization. + * This lets us avoid the cost of a fetch_add when its unnecessary (note that + * the types here are atomic). + */ +static inline void +arena_stats_accum_u64(arena_stats_u64_t *dst, uint64_t src) { +#ifdef JEMALLOC_ATOMIC_U64 + uint64_t cur_dst = atomic_load_u64(dst, ATOMIC_RELAXED); + atomic_store_u64(dst, src + cur_dst, ATOMIC_RELAXED); +#else + *dst += src; +#endif +} + +static inline size_t +arena_stats_read_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, + atomic_zu_t *p) { +#ifdef JEMALLOC_ATOMIC_U64 + return atomic_load_zu(p, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + return atomic_load_zu(p, ATOMIC_RELAXED); +#endif +} + +static inline void +arena_stats_add_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, + atomic_zu_t *p, size_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + atomic_fetch_add_zu(p, x, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + size_t cur = atomic_load_zu(p, ATOMIC_RELAXED); + atomic_store_zu(p, cur + x, ATOMIC_RELAXED); +#endif +} + +static inline void +arena_stats_sub_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, + atomic_zu_t *p, size_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + size_t r = atomic_fetch_sub_zu(p, x, ATOMIC_RELAXED); + assert(r - x <= r); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + size_t cur = atomic_load_zu(p, ATOMIC_RELAXED); + atomic_store_zu(p, cur - x, ATOMIC_RELAXED); +#endif +} + +/* Like the _u64 variant, needs an externally synchronized *dst. */ +static inline void +arena_stats_accum_zu(atomic_zu_t *dst, size_t src) { + size_t cur_dst = atomic_load_zu(dst, ATOMIC_RELAXED); + atomic_store_zu(dst, src + cur_dst, ATOMIC_RELAXED); +} + +static inline void +arena_stats_large_nrequests_add(tsdn_t *tsdn, arena_stats_t *arena_stats, + szind_t szind, uint64_t nrequests) { + arena_stats_lock(tsdn, arena_stats); + arena_stats_add_u64(tsdn, arena_stats, &arena_stats->lstats[szind - + SC_NBINS].nrequests, nrequests); + arena_stats_unlock(tsdn, arena_stats); +} + +static inline void +arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats, size_t size) { + arena_stats_lock(tsdn, arena_stats); + arena_stats_add_zu(tsdn, arena_stats, &arena_stats->mapped, size); + arena_stats_unlock(tsdn, arena_stats); +} + +#endif /* JEMALLOC_INTERNAL_ARENA_STATS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_structs_b.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_structs_b.h index d1fffec193..950bd13c27 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_structs_b.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_structs_b.h @@ -1,54 +1,19 @@ #ifndef JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H #define JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H +#include "jemalloc/internal/arena_stats.h" #include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/bin.h" #include "jemalloc/internal/bitmap.h" #include "jemalloc/internal/extent_dss.h" #include "jemalloc/internal/jemalloc_internal_types.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/nstime.h" #include "jemalloc/internal/ql.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/smoothstep.h" -#include "jemalloc/internal/stats.h" #include "jemalloc/internal/ticker.h" -/* - * Read-only information associated with each element of arena_t's bins array - * is stored separately, partly to reduce memory usage (only one copy, rather - * than one per arena), but mainly to avoid false cacheline sharing. - * - * Each slab has the following layout: - * - * /--------------------\ - * | region 0 | - * |--------------------| - * | region 1 | - * |--------------------| - * | ... | - * | ... | - * | ... | - * |--------------------| - * | region nregs-1 | - * \--------------------/ - */ -struct arena_bin_info_s { - /* Size of regions in a slab for this bin's size class. */ - size_t reg_size; - - /* Total size of a slab for this bin's size class. */ - size_t slab_size; - - /* Total number of regions in a slab for this bin's size class. */ - uint32_t nregs; - - /* - * Metadata used to manipulate bitmaps for slabs associated with this - * bin. - */ - bitmap_info_t bitmap_info; -}; - struct arena_decay_s { /* Synchronizes all non-atomic fields. */ malloc_mutex_t mtx; @@ -104,37 +69,11 @@ struct arena_decay_s { * arena and ctl code. * * Synchronization: Same as associated arena's stats field. */ - decay_stats_t *stats; + arena_stats_decay_t *stats; /* Peak number of pages in associated extents. Used for debug only. */ uint64_t ceil_npages; }; -struct arena_bin_s { - /* All operations on arena_bin_t fields require lock ownership. */ - malloc_mutex_t lock; - - /* - * Current slab being used to service allocations of this bin's size - * class. slabcur is independent of slabs_{nonfull,full}; whenever - * slabcur is reassigned, the previous slab must be deallocated or - * inserted into slabs_{nonfull,full}. - */ - extent_t *slabcur; - - /* - * Heap of non-full slabs. This heap is used to assure that new - * allocations come from the non-full slab that is oldest/lowest in - * memory. - */ - extent_heap_t slabs_nonfull; - - /* List used to track full slabs. */ - extent_list_t slabs_full; - - /* Bin statistics. */ - malloc_bin_stats_t stats; -}; - struct arena_s { /* * Number of threads currently assigned to this arena. Each thread has @@ -151,6 +90,9 @@ struct arena_s { */ atomic_u_t nthreads[2]; + /* Next bin shard for binding new threads. Synchronization: atomic. */ + atomic_u_t binshard_next; + /* * When percpu_arena is enabled, to amortize the cost of reading / * updating the current CPU id, track the most recent thread accessing @@ -162,14 +104,15 @@ struct arena_s { arena_stats_t stats; /* - * List of tcaches for extant threads associated with this arena. - * Stats from these are merged incrementally, and at exit if - * opt_stats_print is enabled. + * Lists of tcaches and cache_bin_array_descriptors for extant threads + * associated with this arena. Stats from these are merged + * incrementally, and at exit if opt_stats_print is enabled. * * Synchronization: tcache_ql_mtx. */ - ql_head(tcache_t) tcache_ql; - malloc_mutex_t tcache_ql_mtx; + ql_head(tcache_t) tcache_ql; + ql_head(cache_bin_array_descriptor_t) cache_bin_array_descriptor_ql; + malloc_mutex_t tcache_ql_mtx; /* Synchronization: internal. */ prof_accum_t prof_accum; @@ -239,9 +182,14 @@ struct arena_s { * be effective even if multiple arenas' extent allocation requests are * highly interleaved. * + * retain_grow_limit is the max allowed size ind to expand (unless the + * required size is greater). Default is no limit, and controlled + * through mallctl only. + * * Synchronization: extent_grow_mtx */ pszind_t extent_grow_next; + pszind_t retain_grow_limit; malloc_mutex_t extent_grow_mtx; /* @@ -251,6 +199,7 @@ struct arena_s { * Synchronization: extent_avail_mtx. */ extent_tree_t extent_avail; + atomic_zu_t extent_avail_cnt; malloc_mutex_t extent_avail_mtx; /* @@ -258,7 +207,7 @@ struct arena_s { * * Synchronization: internal. */ - arena_bin_t bins[NBINS]; + bins_t bins[SC_NBINS]; /* * Base allocator, from which arena metadata are allocated. diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_types.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_types.h index a691bd811e..624937e4f5 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_types.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/arena_types.h @@ -1,20 +1,20 @@ #ifndef JEMALLOC_INTERNAL_ARENA_TYPES_H #define JEMALLOC_INTERNAL_ARENA_TYPES_H +#include "jemalloc/internal/sc.h" + /* Maximum number of regions in one slab. */ -#define LG_SLAB_MAXREGS (LG_PAGE - LG_TINY_MIN) +#define LG_SLAB_MAXREGS (LG_PAGE - SC_LG_TINY_MIN) #define SLAB_MAXREGS (1U << LG_SLAB_MAXREGS) /* Default decay times in milliseconds. */ #define DIRTY_DECAY_MS_DEFAULT ZD(10 * 1000) -#define MUZZY_DECAY_MS_DEFAULT ZD(10 * 1000) +#define MUZZY_DECAY_MS_DEFAULT (0) /* Number of event ticks between time checks. */ #define DECAY_NTICKS_PER_UPDATE 1000 typedef struct arena_slab_data_s arena_slab_data_t; -typedef struct arena_bin_info_s arena_bin_info_t; typedef struct arena_decay_s arena_decay_t; -typedef struct arena_bin_s arena_bin_t; typedef struct arena_s arena_t; typedef struct arena_tdata_s arena_tdata_t; typedef struct alloc_ctx_s alloc_ctx_t; @@ -42,4 +42,10 @@ typedef enum { #define PERCPU_ARENA_ENABLED(m) ((m) >= percpu_arena_mode_enabled_base) #define PERCPU_ARENA_DEFAULT percpu_arena_disabled +/* + * When allocation_size >= oversize_threshold, use the dedicated huge arena + * (unless have explicitly spicified arena index). 0 disables the feature. + */ +#define OVERSIZE_THRESHOLD_DEFAULT (8 << 20) + #endif /* JEMALLOC_INTERNAL_ARENA_TYPES_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic.h index adadb1a3ac..a76f54cee3 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic.h @@ -1,12 +1,19 @@ #ifndef JEMALLOC_INTERNAL_ATOMIC_H #define JEMALLOC_INTERNAL_ATOMIC_H -#define ATOMIC_INLINE static inline +#define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE +#define JEMALLOC_U8_ATOMICS #if defined(JEMALLOC_GCC_ATOMIC_ATOMICS) # include "jemalloc/internal/atomic_gcc_atomic.h" +# if !defined(JEMALLOC_GCC_U8_ATOMIC_ATOMICS) +# undef JEMALLOC_U8_ATOMICS +# endif #elif defined(JEMALLOC_GCC_SYNC_ATOMICS) # include "jemalloc/internal/atomic_gcc_sync.h" +# if !defined(JEMALLOC_GCC_U8_SYNC_ATOMICS) +# undef JEMALLOC_U8_ATOMICS +# endif #elif defined(_MSC_VER) # include "jemalloc/internal/atomic_msvc.h" #elif defined(JEMALLOC_C11_ATOMICS) @@ -66,6 +73,8 @@ JEMALLOC_GENERATE_INT_ATOMICS(size_t, zu, LG_SIZEOF_PTR) JEMALLOC_GENERATE_INT_ATOMICS(ssize_t, zd, LG_SIZEOF_PTR) +JEMALLOC_GENERATE_INT_ATOMICS(uint8_t, u8, 0) + JEMALLOC_GENERATE_INT_ATOMICS(uint32_t, u32, 2) #ifdef JEMALLOC_ATOMIC_U64 diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h index 30846e4d27..e02b7cbe3c 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h @@ -27,8 +27,10 @@ atomic_fence(atomic_memory_order_t mo) { asm volatile("" ::: "memory"); # if defined(__i386__) || defined(__x86_64__) /* This is implicit on x86. */ -# elif defined(__ppc__) +# elif defined(__ppc64__) asm volatile("lwsync"); +# elif defined(__ppc__) + asm volatile("sync"); # elif defined(__sparc__) && defined(__arch64__) if (mo == atomic_memory_order_acquire) { asm volatile("membar #LoadLoad | #LoadStore"); @@ -113,8 +115,8 @@ atomic_store_##short_type(atomic_##short_type##_t *a, \ } \ \ ATOMIC_INLINE type \ -atomic_exchange_##short_type(atomic_##short_type##_t *a, type val, \ - atomic_memory_order_t mo) { \ +atomic_exchange_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ /* \ * Because of FreeBSD, we care about gcc 4.2, which doesn't have\ * an atomic exchange builtin. We fake it with a CAS loop. \ @@ -129,8 +131,9 @@ atomic_exchange_##short_type(atomic_##short_type##_t *a, type val, \ \ ATOMIC_INLINE bool \ atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a, \ - type *expected, type desired, atomic_memory_order_t success_mo, \ - atomic_memory_order_t failure_mo) { \ + type *expected, type desired, \ + atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ type prev = __sync_val_compare_and_swap(&a->repr, *expected, \ desired); \ if (prev == *expected) { \ @@ -142,8 +145,9 @@ atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a, \ } \ ATOMIC_INLINE bool \ atomic_compare_exchange_strong_##short_type(atomic_##short_type##_t *a, \ - type *expected, type desired, atomic_memory_order_t success_mo, \ - atomic_memory_order_t failure_mo) { \ + type *expected, type desired, \ + atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ type prev = __sync_val_compare_and_swap(&a->repr, *expected, \ desired); \ if (prev == *expected) { \ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_externs.h index 8b4b8471a9..0f997e18be 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_externs.h @@ -2,11 +2,12 @@ #define JEMALLOC_INTERNAL_BACKGROUND_THREAD_EXTERNS_H extern bool opt_background_thread; +extern size_t opt_max_background_threads; extern malloc_mutex_t background_thread_lock; extern atomic_b_t background_thread_enabled_state; extern size_t n_background_threads; +extern size_t max_background_threads; extern background_thread_info_t *background_thread_info; -extern bool can_enable_background_thread; bool background_thread_create(tsd_t *tsd, unsigned arena_ind); bool background_threads_enable(tsd_t *tsd); diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_inlines.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_inlines.h index ef50231e8d..f85e86fa37 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_inlines.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_inlines.h @@ -15,7 +15,12 @@ background_thread_enabled_set(tsdn_t *tsdn, bool state) { JEMALLOC_ALWAYS_INLINE background_thread_info_t * arena_background_thread_info_get(arena_t *arena) { unsigned arena_ind = arena_ind_get(arena); - return &background_thread_info[arena_ind % ncpus]; + return &background_thread_info[arena_ind % max_background_threads]; +} + +JEMALLOC_ALWAYS_INLINE background_thread_info_t * +background_thread_info_get(size_t ind) { + return &background_thread_info[ind % max_background_threads]; } JEMALLOC_ALWAYS_INLINE uint64_t diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_structs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_structs.h index e69a7d022b..c02aa434c7 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_structs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/background_thread_structs.h @@ -8,6 +8,8 @@ #endif #define BACKGROUND_THREAD_INDEFINITE_SLEEP UINT64_MAX +#define MAX_BACKGROUND_THREAD_LIMIT MALLOCX_ARENA_LIMIT +#define DEFAULT_NUM_BACKGROUND_THREAD 4 typedef enum { background_thread_stopped, diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_externs.h index a4fd5ac7d9..7b705c9b4d 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_externs.h @@ -1,6 +1,9 @@ #ifndef JEMALLOC_INTERNAL_BASE_EXTERNS_H #define JEMALLOC_INTERNAL_BASE_EXTERNS_H +extern metadata_thp_mode_t opt_metadata_thp; +extern const char *metadata_thp_mode_names[]; + base_t *b0get(void); base_t *base_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks); void base_delete(tsdn_t *tsdn, base_t *base); @@ -10,7 +13,7 @@ extent_hooks_t *base_extent_hooks_set(base_t *base, void *base_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment); extent_t *base_alloc_extent(tsdn_t *tsdn, base_t *base); void base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, - size_t *resident, size_t *mapped); + size_t *resident, size_t *mapped, size_t *n_thp); void base_prefork(tsdn_t *tsdn, base_t *base); void base_postfork_parent(tsdn_t *tsdn, base_t *base); void base_postfork_child(tsdn_t *tsdn, base_t *base); diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_inlines.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_inlines.h index 931560bfae..aec0e2e1e1 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_inlines.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_inlines.h @@ -6,4 +6,8 @@ base_ind_get(const base_t *base) { return base->ind; } +static inline bool +metadata_thp_enabled(void) { + return (opt_metadata_thp != metadata_thp_disabled); +} #endif /* JEMALLOC_INTERNAL_BASE_INLINES_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_structs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_structs.h index 18e227bd5a..07f214eb2f 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_structs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_structs.h @@ -3,7 +3,7 @@ #include "jemalloc/internal/jemalloc_internal_types.h" #include "jemalloc/internal/mutex.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" /* Embedded at the beginning of every block of base-managed virtual memory. */ struct base_block_s { @@ -30,6 +30,8 @@ struct base_s { /* Protects base_alloc() and base_stats_get() operations. */ malloc_mutex_t mtx; + /* Using THP when true (metadata_thp auto mode). */ + bool auto_thp_switched; /* * Most recent size class in the series of increasingly large base * extents. Logarithmic spacing between subsequent allocations ensures @@ -44,12 +46,14 @@ struct base_s { base_block_t *blocks; /* Heap of extents that track unused trailing space within blocks. */ - extent_heap_t avail[NSIZES]; + extent_heap_t avail[SC_NSIZES]; /* Stats, only maintained if config_stats. */ size_t allocated; size_t resident; size_t mapped; + /* Number of THP regions touched. */ + size_t n_thp; }; #endif /* JEMALLOC_INTERNAL_BASE_STRUCTS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_types.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_types.h index be7ee82589..b6db77df7c 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_types.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/base_types.h @@ -4,4 +4,30 @@ typedef struct base_block_s base_block_t; typedef struct base_s base_t; +#define METADATA_THP_DEFAULT metadata_thp_disabled + +/* + * In auto mode, arenas switch to huge pages for the base allocator on the + * second base block. a0 switches to thp on the 5th block (after 20 megabytes + * of metadata), since more metadata (e.g. rtree nodes) come from a0's base. + */ + +#define BASE_AUTO_THP_THRESHOLD 2 +#define BASE_AUTO_THP_THRESHOLD_A0 5 + +typedef enum { + metadata_thp_disabled = 0, + /* + * Lazily enable hugepage for metadata. To avoid high RSS caused by THP + * + low usage arena (i.e. THP becomes a significant percentage), the + * "auto" option only starts using THP after a base allocator used up + * the first THP region. Starting from the second hugepage (in a single + * arena), "auto" behaves the same as "always", i.e. madvise hugepage + * right away. + */ + metadata_thp_auto = 1, + metadata_thp_always = 2, + metadata_thp_mode_limit = 3 +} metadata_thp_mode_t; + #endif /* JEMALLOC_INTERNAL_BASE_TYPES_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin.h new file mode 100644 index 0000000000..f542c88298 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin.h @@ -0,0 +1,122 @@ +#ifndef JEMALLOC_INTERNAL_BIN_H +#define JEMALLOC_INTERNAL_BIN_H + +#include "jemalloc/internal/bin_stats.h" +#include "jemalloc/internal/bin_types.h" +#include "jemalloc/internal/extent_types.h" +#include "jemalloc/internal/extent_structs.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/sc.h" + +/* + * A bin contains a set of extents that are currently being used for slab + * allocations. + */ + +/* + * Read-only information associated with each element of arena_t's bins array + * is stored separately, partly to reduce memory usage (only one copy, rather + * than one per arena), but mainly to avoid false cacheline sharing. + * + * Each slab has the following layout: + * + * /--------------------\ + * | region 0 | + * |--------------------| + * | region 1 | + * |--------------------| + * | ... | + * | ... | + * | ... | + * |--------------------| + * | region nregs-1 | + * \--------------------/ + */ +typedef struct bin_info_s bin_info_t; +struct bin_info_s { + /* Size of regions in a slab for this bin's size class. */ + size_t reg_size; + + /* Total size of a slab for this bin's size class. */ + size_t slab_size; + + /* Total number of regions in a slab for this bin's size class. */ + uint32_t nregs; + + /* Number of sharded bins in each arena for this size class. */ + uint32_t n_shards; + + /* + * Metadata used to manipulate bitmaps for slabs associated with this + * bin. + */ + bitmap_info_t bitmap_info; +}; + +extern bin_info_t bin_infos[SC_NBINS]; + +typedef struct bin_s bin_t; +struct bin_s { + /* All operations on bin_t fields require lock ownership. */ + malloc_mutex_t lock; + + /* + * Current slab being used to service allocations of this bin's size + * class. slabcur is independent of slabs_{nonfull,full}; whenever + * slabcur is reassigned, the previous slab must be deallocated or + * inserted into slabs_{nonfull,full}. + */ + extent_t *slabcur; + + /* + * Heap of non-full slabs. This heap is used to assure that new + * allocations come from the non-full slab that is oldest/lowest in + * memory. + */ + extent_heap_t slabs_nonfull; + + /* List used to track full slabs. */ + extent_list_t slabs_full; + + /* Bin statistics. */ + bin_stats_t stats; +}; + +/* A set of sharded bins of the same size class. */ +typedef struct bins_s bins_t; +struct bins_s { + /* Sharded bins. Dynamically sized. */ + bin_t *bin_shards; +}; + +void bin_shard_sizes_boot(unsigned bin_shards[SC_NBINS]); +bool bin_update_shard_size(unsigned bin_shards[SC_NBINS], size_t start_size, + size_t end_size, size_t nshards); +void bin_boot(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]); + +/* Initializes a bin to empty. Returns true on error. */ +bool bin_init(bin_t *bin); + +/* Forking. */ +void bin_prefork(tsdn_t *tsdn, bin_t *bin); +void bin_postfork_parent(tsdn_t *tsdn, bin_t *bin); +void bin_postfork_child(tsdn_t *tsdn, bin_t *bin); + +/* Stats. */ +static inline void +bin_stats_merge(tsdn_t *tsdn, bin_stats_t *dst_bin_stats, bin_t *bin) { + malloc_mutex_lock(tsdn, &bin->lock); + malloc_mutex_prof_accum(tsdn, &dst_bin_stats->mutex_data, &bin->lock); + dst_bin_stats->nmalloc += bin->stats.nmalloc; + dst_bin_stats->ndalloc += bin->stats.ndalloc; + dst_bin_stats->nrequests += bin->stats.nrequests; + dst_bin_stats->curregs += bin->stats.curregs; + dst_bin_stats->nfills += bin->stats.nfills; + dst_bin_stats->nflushes += bin->stats.nflushes; + dst_bin_stats->nslabs += bin->stats.nslabs; + dst_bin_stats->reslabs += bin->stats.reslabs; + dst_bin_stats->curslabs += bin->stats.curslabs; + malloc_mutex_unlock(tsdn, &bin->lock); +} + +#endif /* JEMALLOC_INTERNAL_BIN_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_stats.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_stats.h new file mode 100644 index 0000000000..86e673ec44 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_stats.h @@ -0,0 +1,51 @@ +#ifndef JEMALLOC_INTERNAL_BIN_STATS_H +#define JEMALLOC_INTERNAL_BIN_STATS_H + +#include "jemalloc/internal/mutex_prof.h" + +typedef struct bin_stats_s bin_stats_t; +struct bin_stats_s { + /* + * Total number of allocation/deallocation requests served directly by + * the bin. Note that tcache may allocate an object, then recycle it + * many times, resulting many increments to nrequests, but only one + * each to nmalloc and ndalloc. + */ + uint64_t nmalloc; + uint64_t ndalloc; + + /* + * Number of allocation requests that correspond to the size of this + * bin. This includes requests served by tcache, though tcache only + * periodically merges into this counter. + */ + uint64_t nrequests; + + /* + * Current number of regions of this size class, including regions + * currently cached by tcache. + */ + size_t curregs; + + /* Number of tcache fills from this bin. */ + uint64_t nfills; + + /* Number of tcache flushes to this bin. */ + uint64_t nflushes; + + /* Total number of slabs created for this bin's size class. */ + uint64_t nslabs; + + /* + * Total number of slabs reused by extracting them from the slabs heap + * for this bin's size class. + */ + uint64_t reslabs; + + /* Current number of slabs in this bin. */ + size_t curslabs; + + mutex_prof_data_t mutex_data; +}; + +#endif /* JEMALLOC_INTERNAL_BIN_STATS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_types.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_types.h new file mode 100644 index 0000000000..3533606b90 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bin_types.h @@ -0,0 +1,17 @@ +#ifndef JEMALLOC_INTERNAL_BIN_TYPES_H +#define JEMALLOC_INTERNAL_BIN_TYPES_H + +#include "jemalloc/internal/sc.h" + +#define BIN_SHARDS_MAX (1 << EXTENT_BITS_BINSHARD_WIDTH) +#define N_BIN_SHARDS_DEFAULT 1 + +/* Used in TSD static initializer only. Real init in arena_bind(). */ +#define TSD_BINSHARDS_ZERO_INITIALIZER {{UINT8_MAX}} + +typedef struct tsd_binshards_s tsd_binshards_t; +struct tsd_binshards_s { + uint8_t binshard[SC_NBINS]; +}; + +#endif /* JEMALLOC_INTERNAL_BIN_TYPES_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bit_util.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bit_util.h index 8d078a8a35..c045eb8687 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bit_util.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bit_util.h @@ -27,6 +27,25 @@ ffs_u(unsigned bitmap) { return JEMALLOC_INTERNAL_FFS(bitmap); } +#ifdef JEMALLOC_INTERNAL_POPCOUNTL +BIT_UTIL_INLINE unsigned +popcount_lu(unsigned long bitmap) { + return JEMALLOC_INTERNAL_POPCOUNTL(bitmap); +} +#endif + +/* + * Clears first unset bit in bitmap, and returns + * place of bit. bitmap *must not* be 0. + */ + +BIT_UTIL_INLINE size_t +cfs_lu(unsigned long* bitmap) { + size_t bit = ffs_lu(*bitmap) - 1; + *bitmap ^= ZU(1) << bit; + return bit; +} + BIT_UTIL_INLINE unsigned ffs_zu(size_t bitmap) { #if LG_SIZEOF_PTR == LG_SIZEOF_INT @@ -63,6 +82,22 @@ ffs_u32(uint32_t bitmap) { BIT_UTIL_INLINE uint64_t pow2_ceil_u64(uint64_t x) { +#if (defined(__amd64__) || defined(__x86_64__) || defined(JEMALLOC_HAVE_BUILTIN_CLZ)) + if(unlikely(x <= 1)) { + return x; + } + size_t msb_on_index; +#if (defined(__amd64__) || defined(__x86_64__)) + asm ("bsrq %1, %0" + : "=r"(msb_on_index) // Outputs. + : "r"(x-1) // Inputs. + ); +#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ)) + msb_on_index = (63 ^ __builtin_clzll(x - 1)); +#endif + assert(msb_on_index < 63); + return 1ULL << (msb_on_index + 1); +#else x--; x |= x >> 1; x |= x >> 2; @@ -72,10 +107,27 @@ pow2_ceil_u64(uint64_t x) { x |= x >> 32; x++; return x; +#endif } BIT_UTIL_INLINE uint32_t pow2_ceil_u32(uint32_t x) { +#if ((defined(__i386__) || defined(JEMALLOC_HAVE_BUILTIN_CLZ)) && (!defined(__s390__))) + if(unlikely(x <= 1)) { + return x; + } + size_t msb_on_index; +#if (defined(__i386__)) + asm ("bsr %1, %0" + : "=r"(msb_on_index) // Outputs. + : "r"(x-1) // Inputs. + ); +#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ)) + msb_on_index = (31 ^ __builtin_clz(x - 1)); +#endif + assert(msb_on_index < 31); + return 1U << (msb_on_index + 1); +#else x--; x |= x >> 1; x |= x >> 2; @@ -84,6 +136,7 @@ pow2_ceil_u32(uint32_t x) { x |= x >> 16; x++; return x; +#endif } /* Compute the smallest power of 2 that is >= x. */ @@ -160,6 +213,27 @@ lg_floor(size_t x) { } #endif +BIT_UTIL_INLINE unsigned +lg_ceil(size_t x) { + return lg_floor(x) + ((x & (x - 1)) == 0 ? 0 : 1); +} + #undef BIT_UTIL_INLINE +/* A compile-time version of lg_floor and lg_ceil. */ +#define LG_FLOOR_1(x) 0 +#define LG_FLOOR_2(x) (x < (1ULL << 1) ? LG_FLOOR_1(x) : 1 + LG_FLOOR_1(x >> 1)) +#define LG_FLOOR_4(x) (x < (1ULL << 2) ? LG_FLOOR_2(x) : 2 + LG_FLOOR_2(x >> 2)) +#define LG_FLOOR_8(x) (x < (1ULL << 4) ? LG_FLOOR_4(x) : 4 + LG_FLOOR_4(x >> 4)) +#define LG_FLOOR_16(x) (x < (1ULL << 8) ? LG_FLOOR_8(x) : 8 + LG_FLOOR_8(x >> 8)) +#define LG_FLOOR_32(x) (x < (1ULL << 16) ? LG_FLOOR_16(x) : 16 + LG_FLOOR_16(x >> 16)) +#define LG_FLOOR_64(x) (x < (1ULL << 32) ? LG_FLOOR_32(x) : 32 + LG_FLOOR_32(x >> 32)) +#if LG_SIZEOF_PTR == 2 +# define LG_FLOOR(x) LG_FLOOR_32((x)) +#else +# define LG_FLOOR(x) LG_FLOOR_64((x)) +#endif + +#define LG_CEIL(x) (LG_FLOOR(x) + (((x) & ((x) - 1)) == 0 ? 0 : 1)) + #endif /* JEMALLOC_INTERNAL_BIT_UTIL_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bitmap.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bitmap.h index ac990290a5..c3f9cb490f 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bitmap.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/bitmap.h @@ -3,18 +3,18 @@ #include "jemalloc/internal/arena_types.h" #include "jemalloc/internal/bit_util.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" typedef unsigned long bitmap_t; #define LG_SIZEOF_BITMAP LG_SIZEOF_LONG /* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */ -#if LG_SLAB_MAXREGS > LG_CEIL_NSIZES +#if LG_SLAB_MAXREGS > LG_CEIL(SC_NSIZES) /* Maximum bitmap bit count is determined by maximum regions per slab. */ # define LG_BITMAP_MAXBITS LG_SLAB_MAXREGS #else /* Maximum bitmap bit count is determined by number of extent size classes. */ -# define LG_BITMAP_MAXBITS LG_CEIL_NSIZES +# define LG_BITMAP_MAXBITS LG_CEIL(SC_NSIZES) #endif #define BITMAP_MAXBITS (ZU(1) << LG_BITMAP_MAXBITS) diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/cache_bin.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/cache_bin.h new file mode 100644 index 0000000000..d14556a3da --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/cache_bin.h @@ -0,0 +1,131 @@ +#ifndef JEMALLOC_INTERNAL_CACHE_BIN_H +#define JEMALLOC_INTERNAL_CACHE_BIN_H + +#include "jemalloc/internal/ql.h" + +/* + * The cache_bins are the mechanism that the tcache and the arena use to + * communicate. The tcache fills from and flushes to the arena by passing a + * cache_bin_t to fill/flush. When the arena needs to pull stats from the + * tcaches associated with it, it does so by iterating over its + * cache_bin_array_descriptor_t objects and reading out per-bin stats it + * contains. This makes it so that the arena need not know about the existence + * of the tcache at all. + */ + + +/* + * The count of the number of cached allocations in a bin. We make this signed + * so that negative numbers can encode "invalid" states (e.g. a low water mark + * of -1 for a cache that has been depleted). + */ +typedef int32_t cache_bin_sz_t; + +typedef struct cache_bin_stats_s cache_bin_stats_t; +struct cache_bin_stats_s { + /* + * Number of allocation requests that corresponded to the size of this + * bin. + */ + uint64_t nrequests; +}; + +/* + * Read-only information associated with each element of tcache_t's tbins array + * is stored separately, mainly to reduce memory usage. + */ +typedef struct cache_bin_info_s cache_bin_info_t; +struct cache_bin_info_s { + /* Upper limit on ncached. */ + cache_bin_sz_t ncached_max; +}; + +typedef struct cache_bin_s cache_bin_t; +struct cache_bin_s { + /* Min # cached since last GC. */ + cache_bin_sz_t low_water; + /* # of cached objects. */ + cache_bin_sz_t ncached; + /* + * ncached and stats are both modified frequently. Let's keep them + * close so that they have a higher chance of being on the same + * cacheline, thus less write-backs. + */ + cache_bin_stats_t tstats; + /* + * Stack of available objects. + * + * To make use of adjacent cacheline prefetch, the items in the avail + * stack goes to higher address for newer allocations. avail points + * just above the available space, which means that + * avail[-ncached, ... -1] are available items and the lowest item will + * be allocated first. + */ + void **avail; +}; + +typedef struct cache_bin_array_descriptor_s cache_bin_array_descriptor_t; +struct cache_bin_array_descriptor_s { + /* + * The arena keeps a list of the cache bins associated with it, for + * stats collection. + */ + ql_elm(cache_bin_array_descriptor_t) link; + /* Pointers to the tcache bins. */ + cache_bin_t *bins_small; + cache_bin_t *bins_large; +}; + +static inline void +cache_bin_array_descriptor_init(cache_bin_array_descriptor_t *descriptor, + cache_bin_t *bins_small, cache_bin_t *bins_large) { + ql_elm_new(descriptor, link); + descriptor->bins_small = bins_small; + descriptor->bins_large = bins_large; +} + +JEMALLOC_ALWAYS_INLINE void * +cache_bin_alloc_easy(cache_bin_t *bin, bool *success) { + void *ret; + + bin->ncached--; + + /* + * Check for both bin->ncached == 0 and ncached < low_water + * in a single branch. + */ + if (unlikely(bin->ncached <= bin->low_water)) { + bin->low_water = bin->ncached; + if (bin->ncached == -1) { + bin->ncached = 0; + *success = false; + return NULL; + } + } + + /* + * success (instead of ret) should be checked upon the return of this + * function. We avoid checking (ret == NULL) because there is never a + * null stored on the avail stack (which is unknown to the compiler), + * and eagerly checking ret would cause pipeline stall (waiting for the + * cacheline). + */ + *success = true; + ret = *(bin->avail - (bin->ncached + 1)); + + return ret; +} + +JEMALLOC_ALWAYS_INLINE bool +cache_bin_dalloc_easy(cache_bin_t *bin, cache_bin_info_t *bin_info, void *ptr) { + if (unlikely(bin->ncached == bin_info->ncached_max)) { + return false; + } + assert(bin->ncached < bin_info->ncached_max); + bin->ncached++; + *(bin->avail - bin->ncached) = ptr; + + return true; +} + +#endif /* JEMALLOC_INTERNAL_CACHE_BIN_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ctl.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ctl.h index a91c4cf556..775fdec04e 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ctl.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ctl.h @@ -5,7 +5,7 @@ #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/mutex_prof.h" #include "jemalloc/internal/ql.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/stats.h" /* Maximum ctl tree depth. */ @@ -40,14 +40,16 @@ typedef struct ctl_arena_stats_s { uint64_t ndalloc_small; uint64_t nrequests_small; - malloc_bin_stats_t bstats[NBINS]; - malloc_large_stats_t lstats[NSIZES - NBINS]; + bin_stats_t bstats[SC_NBINS]; + arena_stats_large_t lstats[SC_NSIZES - SC_NBINS]; + arena_stats_extents_t estats[SC_NPSIZES]; } ctl_arena_stats_t; typedef struct ctl_stats_s { size_t allocated; size_t active; size_t metadata; + size_t metadata_thp; size_t resident; size_t mapped; size_t retained; diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/div.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/div.h new file mode 100644 index 0000000000..aebae9398c --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/div.h @@ -0,0 +1,41 @@ +#ifndef JEMALLOC_INTERNAL_DIV_H +#define JEMALLOC_INTERNAL_DIV_H + +#include "jemalloc/internal/assert.h" + +/* + * This module does the division that computes the index of a region in a slab, + * given its offset relative to the base. + * That is, given a divisor d, an n = i * d (all integers), we'll return i. + * We do some pre-computation to do this more quickly than a CPU division + * instruction. + * We bound n < 2^32, and don't support dividing by one. + */ + +typedef struct div_info_s div_info_t; +struct div_info_s { + uint32_t magic; +#ifdef JEMALLOC_DEBUG + size_t d; +#endif +}; + +void div_init(div_info_t *div_info, size_t divisor); + +static inline size_t +div_compute(div_info_t *div_info, size_t n) { + assert(n <= (uint32_t)-1); + /* + * This generates, e.g. mov; imul; shr on x86-64. On a 32-bit machine, + * the compilers I tried were all smart enough to turn this into the + * appropriate "get the high 32 bits of the result of a multiply" (e.g. + * mul; mov edx eax; on x86, umull on arm, etc.). + */ + size_t i = ((uint64_t)n * (uint64_t)div_info->magic) >> 32; +#ifdef JEMALLOC_DEBUG + assert(i * div_info->d == n); +#endif + return i; +} + +#endif /* JEMALLOC_INTERNAL_DIV_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/emitter.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/emitter.h new file mode 100644 index 0000000000..0a8bc2c06b --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/emitter.h @@ -0,0 +1,483 @@ +#ifndef JEMALLOC_INTERNAL_EMITTER_H +#define JEMALLOC_INTERNAL_EMITTER_H + +#include "jemalloc/internal/ql.h" + +typedef enum emitter_output_e emitter_output_t; +enum emitter_output_e { + emitter_output_json, + emitter_output_table +}; + +typedef enum emitter_justify_e emitter_justify_t; +enum emitter_justify_e { + emitter_justify_left, + emitter_justify_right, + /* Not for users; just to pass to internal functions. */ + emitter_justify_none +}; + +typedef enum emitter_type_e emitter_type_t; +enum emitter_type_e { + emitter_type_bool, + emitter_type_int, + emitter_type_unsigned, + emitter_type_uint32, + emitter_type_uint64, + emitter_type_size, + emitter_type_ssize, + emitter_type_string, + /* + * A title is a column title in a table; it's just a string, but it's + * not quoted. + */ + emitter_type_title, +}; + +typedef struct emitter_col_s emitter_col_t; +struct emitter_col_s { + /* Filled in by the user. */ + emitter_justify_t justify; + int width; + emitter_type_t type; + union { + bool bool_val; + int int_val; + unsigned unsigned_val; + uint32_t uint32_val; + uint32_t uint32_t_val; + uint64_t uint64_val; + uint64_t uint64_t_val; + size_t size_val; + ssize_t ssize_val; + const char *str_val; + }; + + /* Filled in by initialization. */ + ql_elm(emitter_col_t) link; +}; + +typedef struct emitter_row_s emitter_row_t; +struct emitter_row_s { + ql_head(emitter_col_t) cols; +}; + +typedef struct emitter_s emitter_t; +struct emitter_s { + emitter_output_t output; + /* The output information. */ + void (*write_cb)(void *, const char *); + void *cbopaque; + int nesting_depth; + /* True if we've already emitted a value at the given depth. */ + bool item_at_depth; + /* True if we emitted a key and will emit corresponding value next. */ + bool emitted_key; +}; + +/* Internal convenience function. Write to the emitter the given string. */ +JEMALLOC_FORMAT_PRINTF(2, 3) +static inline void +emitter_printf(emitter_t *emitter, const char *format, ...) { + va_list ap; + + va_start(ap, format); + malloc_vcprintf(emitter->write_cb, emitter->cbopaque, format, ap); + va_end(ap); +} + +static inline void +emitter_gen_fmt(char *out_fmt, size_t out_size, const char *fmt_specifier, + emitter_justify_t justify, int width) { + size_t written; + if (justify == emitter_justify_none) { + written = malloc_snprintf(out_fmt, out_size, + "%%%s", fmt_specifier); + } else if (justify == emitter_justify_left) { + written = malloc_snprintf(out_fmt, out_size, + "%%-%d%s", width, fmt_specifier); + } else { + written = malloc_snprintf(out_fmt, out_size, + "%%%d%s", width, fmt_specifier); + } + /* Only happens in case of bad format string, which *we* choose. */ + assert(written < out_size); +} + +/* + * Internal. Emit the given value type in the relevant encoding (so that the + * bool true gets mapped to json "true", but the string "true" gets mapped to + * json "\"true\"", for instance. + * + * Width is ignored if justify is emitter_justify_none. + */ +static inline void +emitter_print_value(emitter_t *emitter, emitter_justify_t justify, int width, + emitter_type_t value_type, const void *value) { + size_t str_written; +#define BUF_SIZE 256 +#define FMT_SIZE 10 + /* + * We dynamically generate a format string to emit, to let us use the + * snprintf machinery. This is kinda hacky, but gets the job done + * quickly without having to think about the various snprintf edge + * cases. + */ + char fmt[FMT_SIZE]; + char buf[BUF_SIZE]; + +#define EMIT_SIMPLE(type, format) \ + emitter_gen_fmt(fmt, FMT_SIZE, format, justify, width); \ + emitter_printf(emitter, fmt, *(const type *)value); \ + + switch (value_type) { + case emitter_type_bool: + emitter_gen_fmt(fmt, FMT_SIZE, "s", justify, width); + emitter_printf(emitter, fmt, *(const bool *)value ? + "true" : "false"); + break; + case emitter_type_int: + EMIT_SIMPLE(int, "d") + break; + case emitter_type_unsigned: + EMIT_SIMPLE(unsigned, "u") + break; + case emitter_type_ssize: + EMIT_SIMPLE(ssize_t, "zd") + break; + case emitter_type_size: + EMIT_SIMPLE(size_t, "zu") + break; + case emitter_type_string: + str_written = malloc_snprintf(buf, BUF_SIZE, "\"%s\"", + *(const char *const *)value); + /* + * We control the strings we output; we shouldn't get anything + * anywhere near the fmt size. + */ + assert(str_written < BUF_SIZE); + emitter_gen_fmt(fmt, FMT_SIZE, "s", justify, width); + emitter_printf(emitter, fmt, buf); + break; + case emitter_type_uint32: + EMIT_SIMPLE(uint32_t, FMTu32) + break; + case emitter_type_uint64: + EMIT_SIMPLE(uint64_t, FMTu64) + break; + case emitter_type_title: + EMIT_SIMPLE(char *const, "s"); + break; + default: + unreachable(); + } +#undef BUF_SIZE +#undef FMT_SIZE +} + + +/* Internal functions. In json mode, tracks nesting state. */ +static inline void +emitter_nest_inc(emitter_t *emitter) { + emitter->nesting_depth++; + emitter->item_at_depth = false; +} + +static inline void +emitter_nest_dec(emitter_t *emitter) { + emitter->nesting_depth--; + emitter->item_at_depth = true; +} + +static inline void +emitter_indent(emitter_t *emitter) { + int amount = emitter->nesting_depth; + const char *indent_str; + if (emitter->output == emitter_output_json) { + indent_str = "\t"; + } else { + amount *= 2; + indent_str = " "; + } + for (int i = 0; i < amount; i++) { + emitter_printf(emitter, "%s", indent_str); + } +} + +static inline void +emitter_json_key_prefix(emitter_t *emitter) { + if (emitter->emitted_key) { + emitter->emitted_key = false; + return; + } + emitter_printf(emitter, "%s\n", emitter->item_at_depth ? "," : ""); + emitter_indent(emitter); +} + +/******************************************************************************/ +/* Public functions for emitter_t. */ + +static inline void +emitter_init(emitter_t *emitter, emitter_output_t emitter_output, + void (*write_cb)(void *, const char *), void *cbopaque) { + emitter->output = emitter_output; + emitter->write_cb = write_cb; + emitter->cbopaque = cbopaque; + emitter->item_at_depth = false; + emitter->emitted_key = false; + emitter->nesting_depth = 0; +} + +/******************************************************************************/ +/* JSON public API. */ + +/* + * Emits a key (e.g. as appears in an object). The next json entity emitted will + * be the corresponding value. + */ +static inline void +emitter_json_key(emitter_t *emitter, const char *json_key) { + if (emitter->output == emitter_output_json) { + emitter_json_key_prefix(emitter); + emitter_printf(emitter, "\"%s\": ", json_key); + emitter->emitted_key = true; + } +} + +static inline void +emitter_json_value(emitter_t *emitter, emitter_type_t value_type, + const void *value) { + if (emitter->output == emitter_output_json) { + emitter_json_key_prefix(emitter); + emitter_print_value(emitter, emitter_justify_none, -1, + value_type, value); + emitter->item_at_depth = true; + } +} + +/* Shorthand for calling emitter_json_key and then emitter_json_value. */ +static inline void +emitter_json_kv(emitter_t *emitter, const char *json_key, + emitter_type_t value_type, const void *value) { + emitter_json_key(emitter, json_key); + emitter_json_value(emitter, value_type, value); +} + +static inline void +emitter_json_array_begin(emitter_t *emitter) { + if (emitter->output == emitter_output_json) { + emitter_json_key_prefix(emitter); + emitter_printf(emitter, "["); + emitter_nest_inc(emitter); + } +} + +/* Shorthand for calling emitter_json_key and then emitter_json_array_begin. */ +static inline void +emitter_json_array_kv_begin(emitter_t *emitter, const char *json_key) { + emitter_json_key(emitter, json_key); + emitter_json_array_begin(emitter); +} + +static inline void +emitter_json_array_end(emitter_t *emitter) { + if (emitter->output == emitter_output_json) { + assert(emitter->nesting_depth > 0); + emitter_nest_dec(emitter); + emitter_printf(emitter, "\n"); + emitter_indent(emitter); + emitter_printf(emitter, "]"); + } +} + +static inline void +emitter_json_object_begin(emitter_t *emitter) { + if (emitter->output == emitter_output_json) { + emitter_json_key_prefix(emitter); + emitter_printf(emitter, "{"); + emitter_nest_inc(emitter); + } +} + +/* Shorthand for calling emitter_json_key and then emitter_json_object_begin. */ +static inline void +emitter_json_object_kv_begin(emitter_t *emitter, const char *json_key) { + emitter_json_key(emitter, json_key); + emitter_json_object_begin(emitter); +} + +static inline void +emitter_json_object_end(emitter_t *emitter) { + if (emitter->output == emitter_output_json) { + assert(emitter->nesting_depth > 0); + emitter_nest_dec(emitter); + emitter_printf(emitter, "\n"); + emitter_indent(emitter); + emitter_printf(emitter, "}"); + } +} + + +/******************************************************************************/ +/* Table public API. */ + +static inline void +emitter_table_dict_begin(emitter_t *emitter, const char *table_key) { + if (emitter->output == emitter_output_table) { + emitter_indent(emitter); + emitter_printf(emitter, "%s\n", table_key); + emitter_nest_inc(emitter); + } +} + +static inline void +emitter_table_dict_end(emitter_t *emitter) { + if (emitter->output == emitter_output_table) { + emitter_nest_dec(emitter); + } +} + +static inline void +emitter_table_kv_note(emitter_t *emitter, const char *table_key, + emitter_type_t value_type, const void *value, + const char *table_note_key, emitter_type_t table_note_value_type, + const void *table_note_value) { + if (emitter->output == emitter_output_table) { + emitter_indent(emitter); + emitter_printf(emitter, "%s: ", table_key); + emitter_print_value(emitter, emitter_justify_none, -1, + value_type, value); + if (table_note_key != NULL) { + emitter_printf(emitter, " (%s: ", table_note_key); + emitter_print_value(emitter, emitter_justify_none, -1, + table_note_value_type, table_note_value); + emitter_printf(emitter, ")"); + } + emitter_printf(emitter, "\n"); + } + emitter->item_at_depth = true; +} + +static inline void +emitter_table_kv(emitter_t *emitter, const char *table_key, + emitter_type_t value_type, const void *value) { + emitter_table_kv_note(emitter, table_key, value_type, value, NULL, + emitter_type_bool, NULL); +} + + +/* Write to the emitter the given string, but only in table mode. */ +JEMALLOC_FORMAT_PRINTF(2, 3) +static inline void +emitter_table_printf(emitter_t *emitter, const char *format, ...) { + if (emitter->output == emitter_output_table) { + va_list ap; + va_start(ap, format); + malloc_vcprintf(emitter->write_cb, emitter->cbopaque, format, ap); + va_end(ap); + } +} + +static inline void +emitter_table_row(emitter_t *emitter, emitter_row_t *row) { + if (emitter->output != emitter_output_table) { + return; + } + emitter_col_t *col; + ql_foreach(col, &row->cols, link) { + emitter_print_value(emitter, col->justify, col->width, + col->type, (const void *)&col->bool_val); + } + emitter_table_printf(emitter, "\n"); +} + +static inline void +emitter_row_init(emitter_row_t *row) { + ql_new(&row->cols); +} + +static inline void +emitter_col_init(emitter_col_t *col, emitter_row_t *row) { + ql_elm_new(col, link); + ql_tail_insert(&row->cols, col, link); +} + + +/******************************************************************************/ +/* + * Generalized public API. Emits using either JSON or table, according to + * settings in the emitter_t. */ + +/* + * Note emits a different kv pair as well, but only in table mode. Omits the + * note if table_note_key is NULL. + */ +static inline void +emitter_kv_note(emitter_t *emitter, const char *json_key, const char *table_key, + emitter_type_t value_type, const void *value, + const char *table_note_key, emitter_type_t table_note_value_type, + const void *table_note_value) { + if (emitter->output == emitter_output_json) { + emitter_json_key(emitter, json_key); + emitter_json_value(emitter, value_type, value); + } else { + emitter_table_kv_note(emitter, table_key, value_type, value, + table_note_key, table_note_value_type, table_note_value); + } + emitter->item_at_depth = true; +} + +static inline void +emitter_kv(emitter_t *emitter, const char *json_key, const char *table_key, + emitter_type_t value_type, const void *value) { + emitter_kv_note(emitter, json_key, table_key, value_type, value, NULL, + emitter_type_bool, NULL); +} + +static inline void +emitter_dict_begin(emitter_t *emitter, const char *json_key, + const char *table_header) { + if (emitter->output == emitter_output_json) { + emitter_json_key(emitter, json_key); + emitter_json_object_begin(emitter); + } else { + emitter_table_dict_begin(emitter, table_header); + } +} + +static inline void +emitter_dict_end(emitter_t *emitter) { + if (emitter->output == emitter_output_json) { + emitter_json_object_end(emitter); + } else { + emitter_table_dict_end(emitter); + } +} + +static inline void +emitter_begin(emitter_t *emitter) { + if (emitter->output == emitter_output_json) { + assert(emitter->nesting_depth == 0); + emitter_printf(emitter, "{"); + emitter_nest_inc(emitter); + } else { + /* + * This guarantees that we always call write_cb at least once. + * This is useful if some invariant is established by each call + * to write_cb, but doesn't hold initially: e.g., some buffer + * holds a null-terminated string. + */ + emitter_printf(emitter, "%s", ""); + } +} + +static inline void +emitter_end(emitter_t *emitter) { + if (emitter->output == emitter_output_json) { + assert(emitter->nesting_depth == 1); + emitter_nest_dec(emitter); + emitter_printf(emitter, "\n}\n"); + } +} + +#endif /* JEMALLOC_INTERNAL_EMITTER_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_externs.h index 489a813c80..8680251aba 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_externs.h @@ -4,12 +4,13 @@ #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/mutex_pool.h" #include "jemalloc/internal/ph.h" -#include "jemalloc/internal/rb.h" #include "jemalloc/internal/rtree.h" -extern rtree_t extents_rtree; -extern const extent_hooks_t extent_hooks_default; -extern mutex_pool_t extent_mutex_pool; +extern size_t opt_lg_extent_max_active_fit; + +extern rtree_t extents_rtree; +extern const extent_hooks_t extent_hooks_default; +extern mutex_pool_t extent_mutex_pool; extent_t *extent_alloc(tsdn_t *tsdn, arena_t *arena); void extent_dalloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent); @@ -30,6 +31,10 @@ bool extents_init(tsdn_t *tsdn, extents_t *extents, extent_state_t state, bool delay_coalesce); extent_state_t extents_state_get(const extents_t *extents); size_t extents_npages_get(extents_t *extents); +/* Get the number of extents in the given page size index. */ +size_t extents_nextents_get(extents_t *extents, pszind_t ind); +/* Get the sum total bytes of the extents in the given page size index. */ +size_t extents_nbytes_get(extents_t *extents, pszind_t ind); extent_t *extents_alloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extents_t *extents, void *new_addr, size_t size, size_t pad, size_t alignment, bool slab, szind_t szind, diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_inlines.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_inlines.h index bb2bd699ed..63b710dcf0 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_inlines.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_inlines.h @@ -6,6 +6,7 @@ #include "jemalloc/internal/pages.h" #include "jemalloc/internal/prng.h" #include "jemalloc/internal/ql.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/sz.h" static inline void @@ -34,18 +35,19 @@ extent_unlock2(tsdn_t *tsdn, extent_t *extent1, extent_t *extent2) { (uintptr_t)extent2); } -static inline arena_t * -extent_arena_get(const extent_t *extent) { +static inline unsigned +extent_arena_ind_get(const extent_t *extent) { unsigned arena_ind = (unsigned)((extent->e_bits & EXTENT_BITS_ARENA_MASK) >> EXTENT_BITS_ARENA_SHIFT); - /* - * The following check is omitted because we should never actually read - * a NULL arena pointer. - */ - if (false && arena_ind >= MALLOCX_ARENA_LIMIT) { - return NULL; - } assert(arena_ind < MALLOCX_ARENA_LIMIT); + + return arena_ind; +} + +static inline arena_t * +extent_arena_get(const extent_t *extent) { + unsigned arena_ind = extent_arena_ind_get(extent); + return (arena_t *)atomic_load_p(&arenas[arena_ind], ATOMIC_ACQUIRE); } @@ -53,14 +55,14 @@ static inline szind_t extent_szind_get_maybe_invalid(const extent_t *extent) { szind_t szind = (szind_t)((extent->e_bits & EXTENT_BITS_SZIND_MASK) >> EXTENT_BITS_SZIND_SHIFT); - assert(szind <= NSIZES); + assert(szind <= SC_NSIZES); return szind; } static inline szind_t extent_szind_get(const extent_t *extent) { szind_t szind = extent_szind_get_maybe_invalid(extent); - assert(szind < NSIZES); /* Never call when "invalid". */ + assert(szind < SC_NSIZES); /* Never call when "invalid". */ return szind; } @@ -69,6 +71,14 @@ extent_usize_get(const extent_t *extent) { return sz_index2size(extent_szind_get(extent)); } +static inline unsigned +extent_binshard_get(const extent_t *extent) { + unsigned binshard = (unsigned)((extent->e_bits & + EXTENT_BITS_BINSHARD_MASK) >> EXTENT_BITS_BINSHARD_SHIFT); + assert(binshard < bin_infos[extent_szind_get(extent)].n_shards); + return binshard; +} + static inline size_t extent_sn_get(const extent_t *extent) { return (size_t)((extent->e_bits & EXTENT_BITS_SN_MASK) >> @@ -93,6 +103,12 @@ extent_committed_get(const extent_t *extent) { EXTENT_BITS_COMMITTED_SHIFT); } +static inline bool +extent_dumpable_get(const extent_t *extent) { + return (bool)((extent->e_bits & EXTENT_BITS_DUMPABLE_MASK) >> + EXTENT_BITS_DUMPABLE_SHIFT); +} + static inline bool extent_slab_get(const extent_t *extent) { return (bool)((extent->e_bits & EXTENT_BITS_SLAB_MASK) >> @@ -170,6 +186,11 @@ extent_prof_tctx_get(const extent_t *extent) { ATOMIC_ACQUIRE); } +static inline nstime_t +extent_prof_alloc_time_get(const extent_t *extent) { + return extent->e_alloc_time; +} + static inline void extent_arena_set(extent_t *extent, arena_t *arena) { unsigned arena_ind = (arena != NULL) ? arena_ind_get(arena) : ((1U << @@ -178,6 +199,14 @@ extent_arena_set(extent_t *extent, arena_t *arena) { ((uint64_t)arena_ind << EXTENT_BITS_ARENA_SHIFT); } +static inline void +extent_binshard_set(extent_t *extent, unsigned binshard) { + /* The assertion assumes szind is set already. */ + assert(binshard < bin_infos[extent_szind_get(extent)].n_shards); + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_BINSHARD_MASK) | + ((uint64_t)binshard << EXTENT_BITS_BINSHARD_SHIFT); +} + static inline void extent_addr_set(extent_t *extent, void *addr) { extent->e_addr = addr; @@ -190,9 +219,16 @@ extent_addr_randomize(tsdn_t *tsdn, extent_t *extent, size_t alignment) { if (alignment < PAGE) { unsigned lg_range = LG_PAGE - lg_floor(CACHELINE_CEILING(alignment)); - size_t r = - prng_lg_range_zu(&extent_arena_get(extent)->offset_state, - lg_range, true); + size_t r; + if (!tsdn_null(tsdn)) { + tsd_t *tsd = tsdn_tsd(tsdn); + r = (size_t)prng_lg_range_u64( + tsd_offset_statep_get(tsd), lg_range); + } else { + r = prng_lg_range_zu( + &extent_arena_get(extent)->offset_state, + lg_range, true); + } uintptr_t random_offset = ((uintptr_t)r) << (LG_PAGE - lg_range); extent->e_addr = (void *)((uintptr_t)extent->e_addr + @@ -221,7 +257,7 @@ extent_bsize_set(extent_t *extent, size_t bsize) { static inline void extent_szind_set(extent_t *extent, szind_t szind) { - assert(szind <= NSIZES); /* NSIZES means "invalid". */ + assert(szind <= SC_NSIZES); /* SC_NSIZES means "invalid". */ extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SZIND_MASK) | ((uint64_t)szind << EXTENT_BITS_SZIND_SHIFT); } @@ -233,6 +269,16 @@ extent_nfree_set(extent_t *extent, unsigned nfree) { ((uint64_t)nfree << EXTENT_BITS_NFREE_SHIFT); } +static inline void +extent_nfree_binshard_set(extent_t *extent, unsigned nfree, unsigned binshard) { + /* The assertion assumes szind is set already. */ + assert(binshard < bin_infos[extent_szind_get(extent)].n_shards); + extent->e_bits = (extent->e_bits & + (~EXTENT_BITS_NFREE_MASK & ~EXTENT_BITS_BINSHARD_MASK)) | + ((uint64_t)binshard << EXTENT_BITS_BINSHARD_SHIFT) | + ((uint64_t)nfree << EXTENT_BITS_NFREE_SHIFT); +} + static inline void extent_nfree_inc(extent_t *extent) { assert(extent_slab_get(extent)); @@ -245,6 +291,12 @@ extent_nfree_dec(extent_t *extent) { extent->e_bits -= ((uint64_t)1U << EXTENT_BITS_NFREE_SHIFT); } +static inline void +extent_nfree_sub(extent_t *extent, uint64_t n) { + assert(extent_slab_get(extent)); + extent->e_bits -= (n << EXTENT_BITS_NFREE_SHIFT); +} + static inline void extent_sn_set(extent_t *extent, size_t sn) { extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SN_MASK) | @@ -269,6 +321,12 @@ extent_committed_set(extent_t *extent, bool committed) { ((uint64_t)committed << EXTENT_BITS_COMMITTED_SHIFT); } +static inline void +extent_dumpable_set(extent_t *extent, bool dumpable) { + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_DUMPABLE_MASK) | + ((uint64_t)dumpable << EXTENT_BITS_DUMPABLE_SHIFT); +} + static inline void extent_slab_set(extent_t *extent, bool slab) { extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SLAB_MASK) | @@ -280,10 +338,15 @@ extent_prof_tctx_set(extent_t *extent, prof_tctx_t *tctx) { atomic_store_p(&extent->e_prof_tctx, tctx, ATOMIC_RELEASE); } +static inline void +extent_prof_alloc_time_set(extent_t *extent, nstime_t t) { + nstime_copy(&extent->e_alloc_time, &t); +} + static inline void extent_init(extent_t *extent, arena_t *arena, void *addr, size_t size, bool slab, szind_t szind, size_t sn, extent_state_t state, bool zeroed, - bool committed) { + bool committed, bool dumpable) { assert(addr == PAGE_ADDR2BASE(addr) || !slab); extent_arena_set(extent, arena); @@ -295,6 +358,7 @@ extent_init(extent_t *extent, arena_t *arena, void *addr, size_t size, extent_state_set(extent, state); extent_zeroed_set(extent, zeroed); extent_committed_set(extent, committed); + extent_dumpable_set(extent, dumpable); ql_elm_new(extent, ql_link); if (config_prof) { extent_prof_tctx_set(extent, NULL); @@ -307,11 +371,12 @@ extent_binit(extent_t *extent, void *addr, size_t bsize, size_t sn) { extent_addr_set(extent, addr); extent_bsize_set(extent, bsize); extent_slab_set(extent, false); - extent_szind_set(extent, NSIZES); + extent_szind_set(extent, SC_NSIZES); extent_sn_set(extent, sn); extent_state_set(extent, extent_state_active); extent_zeroed_set(extent, true); extent_committed_set(extent, true); + extent_dumpable_set(extent, true); } static inline void @@ -334,6 +399,11 @@ extent_list_append(extent_list_t *list, extent_t *extent) { ql_tail_insert(list, extent, ql_link); } +static inline void +extent_list_prepend(extent_list_t *list, extent_t *extent) { + ql_head_insert(list, extent, ql_link); +} + static inline void extent_list_replace(extent_list_t *list, extent_t *to_remove, extent_t *to_insert) { diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_structs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_structs.h index d297950345..ceb18979f1 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_structs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_structs.h @@ -2,12 +2,12 @@ #define JEMALLOC_INTERNAL_EXTENT_STRUCTS_H #include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/bit_util.h" #include "jemalloc/internal/bitmap.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/ql.h" -#include "jemalloc/internal/rb.h" #include "jemalloc/internal/ph.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" typedef enum { extent_state_active = 0, @@ -24,13 +24,15 @@ struct extent_s { * a: arena_ind * b: slab * c: committed + * d: dumpable * z: zeroed * t: state * i: szind * f: nfree + * s: bin_shard * n: sn * - * nnnnnnnn ... nnnnnfff fffffffi iiiiiiit tzcbaaaa aaaaaaaa + * nnnnnnnn ... nnnnnnss ssssffff ffffffii iiiiiitt zdcbaaaa aaaaaaaa * * arena_ind: Arena from which this extent came, or all 1 bits if * unassociated. @@ -45,6 +47,23 @@ struct extent_s { * as on a system that overcommits and satisfies physical * memory needs on demand via soft page faults. * + * dumpable: The dumpable flag indicates whether or not we've set the + * memory in question to be dumpable. Note that this + * interacts somewhat subtly with user-specified extent hooks, + * since we don't know if *they* are fiddling with + * dumpability (in which case, we don't want to undo whatever + * they're doing). To deal with this scenario, we: + * - Make dumpable false only for memory allocated with the + * default hooks. + * - Only allow memory to go from non-dumpable to dumpable, + * and only once. + * - Never make the OS call to allow dumping when the + * dumpable bit is already set. + * These three constraints mean that we will never + * accidentally dump user memory that the user meant to set + * nondumpable with their extent hooks. + * + * * zeroed: The zeroed flag is used by extent recycling code to track * whether memory is zero-filled. * @@ -58,6 +77,8 @@ struct extent_s { * * nfree: Number of free regions in slab. * + * bin_shard: the shard of the bin from which this extent came. + * * sn: Serial number (potentially non-unique). * * Serial numbers may wrap around if !opt_retain, but as long as @@ -69,38 +90,46 @@ struct extent_s { * serial number to both resulting adjacent extents. */ uint64_t e_bits; -#define EXTENT_BITS_ARENA_SHIFT 0 -#define EXTENT_BITS_ARENA_MASK \ - (((uint64_t)(1U << MALLOCX_ARENA_BITS) - 1) << EXTENT_BITS_ARENA_SHIFT) +#define MASK(CURRENT_FIELD_WIDTH, CURRENT_FIELD_SHIFT) ((((((uint64_t)0x1U) << (CURRENT_FIELD_WIDTH)) - 1)) << (CURRENT_FIELD_SHIFT)) + +#define EXTENT_BITS_ARENA_WIDTH MALLOCX_ARENA_BITS +#define EXTENT_BITS_ARENA_SHIFT 0 +#define EXTENT_BITS_ARENA_MASK MASK(EXTENT_BITS_ARENA_WIDTH, EXTENT_BITS_ARENA_SHIFT) -#define EXTENT_BITS_SLAB_SHIFT MALLOCX_ARENA_BITS -#define EXTENT_BITS_SLAB_MASK \ - ((uint64_t)0x1U << EXTENT_BITS_SLAB_SHIFT) +#define EXTENT_BITS_SLAB_WIDTH 1 +#define EXTENT_BITS_SLAB_SHIFT (EXTENT_BITS_ARENA_WIDTH + EXTENT_BITS_ARENA_SHIFT) +#define EXTENT_BITS_SLAB_MASK MASK(EXTENT_BITS_SLAB_WIDTH, EXTENT_BITS_SLAB_SHIFT) -#define EXTENT_BITS_COMMITTED_SHIFT (MALLOCX_ARENA_BITS + 1) -#define EXTENT_BITS_COMMITTED_MASK \ - ((uint64_t)0x1U << EXTENT_BITS_COMMITTED_SHIFT) +#define EXTENT_BITS_COMMITTED_WIDTH 1 +#define EXTENT_BITS_COMMITTED_SHIFT (EXTENT_BITS_SLAB_WIDTH + EXTENT_BITS_SLAB_SHIFT) +#define EXTENT_BITS_COMMITTED_MASK MASK(EXTENT_BITS_COMMITTED_WIDTH, EXTENT_BITS_COMMITTED_SHIFT) -#define EXTENT_BITS_ZEROED_SHIFT (MALLOCX_ARENA_BITS + 2) -#define EXTENT_BITS_ZEROED_MASK \ - ((uint64_t)0x1U << EXTENT_BITS_ZEROED_SHIFT) +#define EXTENT_BITS_DUMPABLE_WIDTH 1 +#define EXTENT_BITS_DUMPABLE_SHIFT (EXTENT_BITS_COMMITTED_WIDTH + EXTENT_BITS_COMMITTED_SHIFT) +#define EXTENT_BITS_DUMPABLE_MASK MASK(EXTENT_BITS_DUMPABLE_WIDTH, EXTENT_BITS_DUMPABLE_SHIFT) -#define EXTENT_BITS_STATE_SHIFT (MALLOCX_ARENA_BITS + 3) -#define EXTENT_BITS_STATE_MASK \ - ((uint64_t)0x3U << EXTENT_BITS_STATE_SHIFT) +#define EXTENT_BITS_ZEROED_WIDTH 1 +#define EXTENT_BITS_ZEROED_SHIFT (EXTENT_BITS_DUMPABLE_WIDTH + EXTENT_BITS_DUMPABLE_SHIFT) +#define EXTENT_BITS_ZEROED_MASK MASK(EXTENT_BITS_ZEROED_WIDTH, EXTENT_BITS_ZEROED_SHIFT) -#define EXTENT_BITS_SZIND_SHIFT (MALLOCX_ARENA_BITS + 5) -#define EXTENT_BITS_SZIND_MASK \ - (((uint64_t)(1U << LG_CEIL_NSIZES) - 1) << EXTENT_BITS_SZIND_SHIFT) +#define EXTENT_BITS_STATE_WIDTH 2 +#define EXTENT_BITS_STATE_SHIFT (EXTENT_BITS_ZEROED_WIDTH + EXTENT_BITS_ZEROED_SHIFT) +#define EXTENT_BITS_STATE_MASK MASK(EXTENT_BITS_STATE_WIDTH, EXTENT_BITS_STATE_SHIFT) -#define EXTENT_BITS_NFREE_SHIFT \ - (MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES) -#define EXTENT_BITS_NFREE_MASK \ - ((uint64_t)((1U << (LG_SLAB_MAXREGS + 1)) - 1) << EXTENT_BITS_NFREE_SHIFT) +#define EXTENT_BITS_SZIND_WIDTH LG_CEIL(SC_NSIZES) +#define EXTENT_BITS_SZIND_SHIFT (EXTENT_BITS_STATE_WIDTH + EXTENT_BITS_STATE_SHIFT) +#define EXTENT_BITS_SZIND_MASK MASK(EXTENT_BITS_SZIND_WIDTH, EXTENT_BITS_SZIND_SHIFT) -#define EXTENT_BITS_SN_SHIFT \ - (MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES + (LG_SLAB_MAXREGS + 1)) -#define EXTENT_BITS_SN_MASK (UINT64_MAX << EXTENT_BITS_SN_SHIFT) +#define EXTENT_BITS_NFREE_WIDTH (LG_SLAB_MAXREGS + 1) +#define EXTENT_BITS_NFREE_SHIFT (EXTENT_BITS_SZIND_WIDTH + EXTENT_BITS_SZIND_SHIFT) +#define EXTENT_BITS_NFREE_MASK MASK(EXTENT_BITS_NFREE_WIDTH, EXTENT_BITS_NFREE_SHIFT) + +#define EXTENT_BITS_BINSHARD_WIDTH 6 +#define EXTENT_BITS_BINSHARD_SHIFT (EXTENT_BITS_NFREE_WIDTH + EXTENT_BITS_NFREE_SHIFT) +#define EXTENT_BITS_BINSHARD_MASK MASK(EXTENT_BITS_BINSHARD_WIDTH, EXTENT_BITS_BINSHARD_SHIFT) + +#define EXTENT_BITS_SN_SHIFT (EXTENT_BITS_BINSHARD_WIDTH + EXTENT_BITS_BINSHARD_SHIFT) +#define EXTENT_BITS_SN_MASK (UINT64_MAX << EXTENT_BITS_SN_SHIFT) /* Pointer to the extent that this structure is responsible for. */ void *e_addr; @@ -120,35 +149,36 @@ struct extent_s { size_t e_bsize; }; - union { - /* - * List linkage, used by a variety of lists: - * - arena_bin_t's slabs_full - * - extents_t's LRU - * - stashed dirty extents - * - arena's large allocations - */ - ql_elm(extent_t) ql_link; - /* Red-black tree linkage, used by arena's extent_avail. */ - rb_node(extent_t) rb_link; - }; + /* + * List linkage, used by a variety of lists: + * - bin_t's slabs_full + * - extents_t's LRU + * - stashed dirty extents + * - arena's large allocations + */ + ql_elm(extent_t) ql_link; - /* Linkage for per size class sn/address-ordered heaps. */ + /* + * Linkage for per size class sn/address-ordered heaps, and + * for extent_avail + */ phn(extent_t) ph_link; union { /* Small region slab metadata. */ arena_slab_data_t e_slab_data; - /* - * Profile counters, used for large objects. Points to a - * prof_tctx_t. - */ - atomic_p_t e_prof_tctx; + /* Profiling data, used for large objects. */ + struct { + /* Time when this was allocated. */ + nstime_t e_alloc_time; + /* Points to a prof_tctx_t. */ + atomic_p_t e_prof_tctx; + }; }; }; typedef ql_head(extent_t) extent_list_t; -typedef rb_tree(extent_t) extent_tree_t; +typedef ph(extent_t) extent_tree_t; typedef ph(extent_t) extent_heap_t; /* Quantized collection of extents, with built-in LRU queue. */ @@ -160,14 +190,16 @@ struct extents_s { * * Synchronization: mtx. */ - extent_heap_t heaps[NPSIZES+1]; + extent_heap_t heaps[SC_NPSIZES + 1]; + atomic_zu_t nextents[SC_NPSIZES + 1]; + atomic_zu_t nbytes[SC_NPSIZES + 1]; /* * Bitmap for which set bits correspond to non-empty heaps. * * Synchronization: mtx. */ - bitmap_t bitmap[BITMAP_GROUPS(NPSIZES+1)]; + bitmap_t bitmap[BITMAP_GROUPS(SC_NPSIZES + 1)]; /* * LRU of all extents in heaps. diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_types.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_types.h index b6905ce105..acbcf27b51 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_types.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/extent_types.h @@ -6,4 +6,10 @@ typedef struct extents_s extents_t; #define EXTENT_HOOKS_INITIALIZER NULL +/* + * When reuse (and split) an active extent, (1U << opt_lg_extent_max_active_fit) + * is the max ratio between the size of the active extent and the new extent. + */ +#define LG_EXTENT_MAX_ACTIVE_FIT_DEFAULT 6 + #endif /* JEMALLOC_INTERNAL_EXTENT_TYPES_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hash.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hash.h index 188296cf0e..0270034e87 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hash.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hash.h @@ -104,8 +104,8 @@ hash_x86_32(const void *key, int len, uint32_t seed) { uint32_t k1 = 0; switch (len & 3) { - case 3: k1 ^= tail[2] << 16; - case 2: k1 ^= tail[1] << 8; + case 3: k1 ^= tail[2] << 16; JEMALLOC_FALLTHROUGH + case 2: k1 ^= tail[1] << 8; JEMALLOC_FALLTHROUGH case 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1; } @@ -119,7 +119,7 @@ hash_x86_32(const void *key, int len, uint32_t seed) { return h1; } -UNUSED static inline void +static inline void hash_x86_128(const void *key, const int len, uint32_t seed, uint64_t r_out[2]) { const uint8_t * data = (const uint8_t *) key; @@ -177,28 +177,29 @@ hash_x86_128(const void *key, const int len, uint32_t seed, uint32_t k4 = 0; switch (len & 15) { - case 15: k4 ^= tail[14] << 16; - case 14: k4 ^= tail[13] << 8; + case 15: k4 ^= tail[14] << 16; JEMALLOC_FALLTHROUGH + case 14: k4 ^= tail[13] << 8; JEMALLOC_FALLTHROUGH case 13: k4 ^= tail[12] << 0; k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4; - - case 12: k3 ^= tail[11] << 24; - case 11: k3 ^= tail[10] << 16; - case 10: k3 ^= tail[ 9] << 8; + JEMALLOC_FALLTHROUGH + case 12: k3 ^= tail[11] << 24; JEMALLOC_FALLTHROUGH + case 11: k3 ^= tail[10] << 16; JEMALLOC_FALLTHROUGH + case 10: k3 ^= tail[ 9] << 8; JEMALLOC_FALLTHROUGH case 9: k3 ^= tail[ 8] << 0; k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3; - - case 8: k2 ^= tail[ 7] << 24; - case 7: k2 ^= tail[ 6] << 16; - case 6: k2 ^= tail[ 5] << 8; + JEMALLOC_FALLTHROUGH + case 8: k2 ^= tail[ 7] << 24; JEMALLOC_FALLTHROUGH + case 7: k2 ^= tail[ 6] << 16; JEMALLOC_FALLTHROUGH + case 6: k2 ^= tail[ 5] << 8; JEMALLOC_FALLTHROUGH case 5: k2 ^= tail[ 4] << 0; k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2; - - case 4: k1 ^= tail[ 3] << 24; - case 3: k1 ^= tail[ 2] << 16; - case 2: k1 ^= tail[ 1] << 8; + JEMALLOC_FALLTHROUGH + case 4: k1 ^= tail[ 3] << 24; JEMALLOC_FALLTHROUGH + case 3: k1 ^= tail[ 2] << 16; JEMALLOC_FALLTHROUGH + case 2: k1 ^= tail[ 1] << 8; JEMALLOC_FALLTHROUGH case 1: k1 ^= tail[ 0] << 0; k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1; + JEMALLOC_FALLTHROUGH } } @@ -220,7 +221,7 @@ hash_x86_128(const void *key, const int len, uint32_t seed, r_out[1] = (((uint64_t) h4) << 32) | h3; } -UNUSED static inline void +static inline void hash_x64_128(const void *key, const int len, const uint32_t seed, uint64_t r_out[2]) { const uint8_t *data = (const uint8_t *) key; @@ -260,22 +261,22 @@ hash_x64_128(const void *key, const int len, const uint32_t seed, uint64_t k2 = 0; switch (len & 15) { - case 15: k2 ^= ((uint64_t)(tail[14])) << 48; - case 14: k2 ^= ((uint64_t)(tail[13])) << 40; - case 13: k2 ^= ((uint64_t)(tail[12])) << 32; - case 12: k2 ^= ((uint64_t)(tail[11])) << 24; - case 11: k2 ^= ((uint64_t)(tail[10])) << 16; - case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8; + case 15: k2 ^= ((uint64_t)(tail[14])) << 48; JEMALLOC_FALLTHROUGH + case 14: k2 ^= ((uint64_t)(tail[13])) << 40; JEMALLOC_FALLTHROUGH + case 13: k2 ^= ((uint64_t)(tail[12])) << 32; JEMALLOC_FALLTHROUGH + case 12: k2 ^= ((uint64_t)(tail[11])) << 24; JEMALLOC_FALLTHROUGH + case 11: k2 ^= ((uint64_t)(tail[10])) << 16; JEMALLOC_FALLTHROUGH + case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8; JEMALLOC_FALLTHROUGH case 9: k2 ^= ((uint64_t)(tail[ 8])) << 0; k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2; - - case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56; - case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48; - case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40; - case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32; - case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24; - case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16; - case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8; + JEMALLOC_FALLTHROUGH + case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56; JEMALLOC_FALLTHROUGH + case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48; JEMALLOC_FALLTHROUGH + case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40; JEMALLOC_FALLTHROUGH + case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32; JEMALLOC_FALLTHROUGH + case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24; JEMALLOC_FALLTHROUGH + case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16; JEMALLOC_FALLTHROUGH + case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8; JEMALLOC_FALLTHROUGH case 1: k1 ^= ((uint64_t)(tail[ 0])) << 0; k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1; } diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hook.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hook.h new file mode 100644 index 0000000000..ee246b1e0b --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hook.h @@ -0,0 +1,163 @@ +#ifndef JEMALLOC_INTERNAL_HOOK_H +#define JEMALLOC_INTERNAL_HOOK_H + +#include "jemalloc/internal/tsd.h" + +/* + * This API is *extremely* experimental, and may get ripped out, changed in API- + * and ABI-incompatible ways, be insufficiently or incorrectly documented, etc. + * + * It allows hooking the stateful parts of the API to see changes as they + * happen. + * + * Allocation hooks are called after the allocation is done, free hooks are + * called before the free is done, and expand hooks are called after the + * allocation is expanded. + * + * For realloc and rallocx, if the expansion happens in place, the expansion + * hook is called. If it is moved, then the alloc hook is called on the new + * location, and then the free hook is called on the old location (i.e. both + * hooks are invoked in between the alloc and the dalloc). + * + * If we return NULL from OOM, then usize might not be trustworthy. Calling + * realloc(NULL, size) only calls the alloc hook, and calling realloc(ptr, 0) + * only calls the free hook. (Calling realloc(NULL, 0) is treated as malloc(0), + * and only calls the alloc hook). + * + * Reentrancy: + * Reentrancy is guarded against from within the hook implementation. If you + * call allocator functions from within a hook, the hooks will not be invoked + * again. + * Threading: + * The installation of a hook synchronizes with all its uses. If you can + * prove the installation of a hook happens-before a jemalloc entry point, + * then the hook will get invoked (unless there's a racing removal). + * + * Hook insertion appears to be atomic at a per-thread level (i.e. if a thread + * allocates and has the alloc hook invoked, then a subsequent free on the + * same thread will also have the free hook invoked). + * + * The *removal* of a hook does *not* block until all threads are done with + * the hook. Hook authors have to be resilient to this, and need some + * out-of-band mechanism for cleaning up any dynamically allocated memory + * associated with their hook. + * Ordering: + * Order of hook execution is unspecified, and may be different than insertion + * order. + */ + +#define HOOK_MAX 4 + +enum hook_alloc_e { + hook_alloc_malloc, + hook_alloc_posix_memalign, + hook_alloc_aligned_alloc, + hook_alloc_calloc, + hook_alloc_memalign, + hook_alloc_valloc, + hook_alloc_mallocx, + + /* The reallocating functions have both alloc and dalloc variants */ + hook_alloc_realloc, + hook_alloc_rallocx, +}; +/* + * We put the enum typedef after the enum, since this file may get included by + * jemalloc_cpp.cpp, and C++ disallows enum forward declarations. + */ +typedef enum hook_alloc_e hook_alloc_t; + +enum hook_dalloc_e { + hook_dalloc_free, + hook_dalloc_dallocx, + hook_dalloc_sdallocx, + + /* + * The dalloc halves of reallocation (not called if in-place expansion + * happens). + */ + hook_dalloc_realloc, + hook_dalloc_rallocx, +}; +typedef enum hook_dalloc_e hook_dalloc_t; + + +enum hook_expand_e { + hook_expand_realloc, + hook_expand_rallocx, + hook_expand_xallocx, +}; +typedef enum hook_expand_e hook_expand_t; + +typedef void (*hook_alloc)( + void *extra, hook_alloc_t type, void *result, uintptr_t result_raw, + uintptr_t args_raw[3]); + +typedef void (*hook_dalloc)( + void *extra, hook_dalloc_t type, void *address, uintptr_t args_raw[3]); + +typedef void (*hook_expand)( + void *extra, hook_expand_t type, void *address, size_t old_usize, + size_t new_usize, uintptr_t result_raw, uintptr_t args_raw[4]); + +typedef struct hooks_s hooks_t; +struct hooks_s { + hook_alloc alloc_hook; + hook_dalloc dalloc_hook; + hook_expand expand_hook; + void *extra; +}; + +/* + * Begin implementation details; everything above this point might one day live + * in a public API. Everything below this point never will. + */ + +/* + * The realloc pathways haven't gotten any refactoring love in a while, and it's + * fairly difficult to pass information from the entry point to the hooks. We + * put the informaiton the hooks will need into a struct to encapsulate + * everything. + * + * Much of these pathways are force-inlined, so that the compiler can avoid + * materializing this struct until we hit an extern arena function. For fairly + * goofy reasons, *many* of the realloc paths hit an extern arena function. + * These paths are cold enough that it doesn't matter; eventually, we should + * rewrite the realloc code to make the expand-in-place and the + * free-then-realloc paths more orthogonal, at which point we don't need to + * spread the hook logic all over the place. + */ +typedef struct hook_ralloc_args_s hook_ralloc_args_t; +struct hook_ralloc_args_s { + /* I.e. as opposed to rallocx. */ + bool is_realloc; + /* + * The expand hook takes 4 arguments, even if only 3 are actually used; + * we add an extra one in case the user decides to memcpy without + * looking too closely at the hooked function. + */ + uintptr_t args[4]; +}; + +/* + * Returns an opaque handle to be used when removing the hook. NULL means that + * we couldn't install the hook. + */ +bool hook_boot(); + +void *hook_install(tsdn_t *tsdn, hooks_t *hooks); +/* Uninstalls the hook with the handle previously returned from hook_install. */ +void hook_remove(tsdn_t *tsdn, void *opaque); + +/* Hooks */ + +void hook_invoke_alloc(hook_alloc_t type, void *result, uintptr_t result_raw, + uintptr_t args_raw[3]); + +void hook_invoke_dalloc(hook_dalloc_t type, void *address, + uintptr_t args_raw[3]); + +void hook_invoke_expand(hook_expand_t type, void *address, size_t old_usize, + size_t new_usize, uintptr_t result_raw, uintptr_t args_raw[4]); + +#endif /* JEMALLOC_INTERNAL_HOOK_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hooks.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hooks.h deleted file mode 100755 index cd49afcb09..0000000000 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/hooks.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef JEMALLOC_INTERNAL_HOOKS_H -#define JEMALLOC_INTERNAL_HOOKS_H - -extern JEMALLOC_EXPORT void (*hooks_arena_new_hook)(); -extern JEMALLOC_EXPORT void (*hooks_libc_hook)(); - -#define JEMALLOC_HOOK(fn, hook) ((void)(hook != NULL && (hook(), 0)), fn) - -#define open JEMALLOC_HOOK(open, hooks_libc_hook) -#define read JEMALLOC_HOOK(read, hooks_libc_hook) -#define write JEMALLOC_HOOK(write, hooks_libc_hook) -#define readlink JEMALLOC_HOOK(readlink, hooks_libc_hook) -#define close JEMALLOC_HOOK(close, hooks_libc_hook) -#define creat JEMALLOC_HOOK(creat, hooks_libc_hook) -#define secure_getenv JEMALLOC_HOOK(secure_getenv, hooks_libc_hook) -/* Note that this is undef'd and re-define'd in src/prof.c. */ -#define _Unwind_Backtrace JEMALLOC_HOOK(_Unwind_Backtrace, hooks_libc_hook) - -#endif /* JEMALLOC_INTERNAL_HOOKS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h index 8ae5ef48cd..7d6053e219 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h @@ -5,7 +5,16 @@ #ifdef _WIN32 # include # include "msvc_compat/windows_extra.h" - +# ifdef _WIN64 +# if LG_VADDR <= 32 +# error Generate the headers using x64 vcargs +# endif +# else +# if LG_VADDR > 32 +# undef LG_VADDR +# define LG_VADDR 32 +# endif +# endif #else # include # include @@ -22,6 +31,9 @@ # include # endif # include +# ifdef __FreeBSD__ +# include +# endif # include # ifdef JEMALLOC_OS_UNFAIR_LOCK # include diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in index c0f834f2a4..21b6514784 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -33,6 +33,8 @@ * order to yield to another virtual CPU. */ #undef CPU_SPINWAIT +/* 1 if CPU_SPINWAIT is defined, 0 otherwise. */ +#undef HAVE_CPU_SPINWAIT /* * Number of significant bits in virtual addresses. This may be less than the @@ -46,25 +48,13 @@ /* Defined if GCC __atomic atomics are available. */ #undef JEMALLOC_GCC_ATOMIC_ATOMICS +/* and the 8-bit variant support. */ +#undef JEMALLOC_GCC_U8_ATOMIC_ATOMICS /* Defined if GCC __sync atomics are available. */ #undef JEMALLOC_GCC_SYNC_ATOMICS - -/* - * Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and - * __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite - * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the - * functions are defined in libgcc instead of being inlines). - */ -#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4 - -/* - * Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and - * __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite - * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the - * functions are defined in libgcc instead of being inlines). - */ -#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8 +/* and the 8-bit variant support. */ +#undef JEMALLOC_GCC_U8_SYNC_ATOMICS /* * Defined if __builtin_clz() and __builtin_clzl() are available. @@ -76,12 +66,6 @@ */ #undef JEMALLOC_OS_UNFAIR_LOCK -/* - * Defined if OSSpin*() functions are available, as provided by Darwin, and - * documented in the spinlock(3) manual page. - */ -#undef JEMALLOC_OSSPIN - /* Defined if syscall(2) is usable. */ #undef JEMALLOC_USE_SYSCALL @@ -151,6 +135,9 @@ /* JEMALLOC_STATS enables statistics calculation. */ #undef JEMALLOC_STATS +/* JEMALLOC_EXPERIMENTAL_SMALLOCX_API enables experimental smallocx API. */ +#undef JEMALLOC_EXPERIMENTAL_SMALLOCX_API + /* JEMALLOC_PROF enables allocation profiling. */ #undef JEMALLOC_PROF @@ -231,12 +218,30 @@ #undef JEMALLOC_INTERNAL_FFSL #undef JEMALLOC_INTERNAL_FFS +/* + * popcount*() functions to use for bitmapping. + */ +#undef JEMALLOC_INTERNAL_POPCOUNTL +#undef JEMALLOC_INTERNAL_POPCOUNT + /* * If defined, explicitly attempt to more uniformly distribute large allocation * pointer alignments across all cache indices. */ #undef JEMALLOC_CACHE_OBLIVIOUS +/* + * If defined, enable logging facilities. We make this a configure option to + * avoid taking extra branches everywhere. + */ +#undef JEMALLOC_LOG + +/* + * If defined, use readlinkat() (instead of readlink()) to follow + * /etc/malloc_conf. + */ +#undef JEMALLOC_READLINKAT + /* * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. */ @@ -254,6 +259,12 @@ /* Defined if madvise(2) is available. */ #undef JEMALLOC_HAVE_MADVISE +/* + * Defined if transparent huge pages are supported via the MADV_[NO]HUGEPAGE + * arguments to madvise(2). + */ +#undef JEMALLOC_HAVE_MADVISE_HUGE + /* * Methods for purging unused pages differ between operating systems. * @@ -271,6 +282,14 @@ #undef JEMALLOC_PURGE_MADVISE_DONTNEED #undef JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS +/* Defined if madvise(2) is available but MADV_FREE is not (x86 Linux only). */ +#undef JEMALLOC_DEFINE_MADVISE_FREE + +/* + * Defined if MADV_DO[NT]DUMP is supported as an argument to madvise. + */ +#undef JEMALLOC_MADVISE_DONTDUMP + /* * Defined if transparent huge pages (THPs) are supported via the * MADV_[NO]HUGEPAGE arguments to madvise(2), and THP support is enabled. @@ -336,4 +355,12 @@ /* If defined, jemalloc takes the malloc/free/etc. symbol names. */ #undef JEMALLOC_IS_MALLOC +/* + * Defined if strerror_r returns char * if _GNU_SOURCE is defined. + */ +#undef JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE + +/* Performs additional size-matching sanity checks when defined. */ +#undef JEMALLOC_EXTRA_SIZE_CHECK + #endif /* JEMALLOC_INTERNAL_DEFS_H_ */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h index e10fb275d4..b784362338 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h @@ -2,7 +2,6 @@ #define JEMALLOC_INTERNAL_EXTERNS_H #include "jemalloc/internal/atomic.h" -#include "jemalloc/internal/size_classes.h" #include "jemalloc/internal/tsd_types.h" /* TSD checks this to set thread local slow state accordingly. */ @@ -25,6 +24,9 @@ extern unsigned ncpus; /* Number of arenas used for automatic multiplexing of threads and arenas. */ extern unsigned narenas_auto; +/* Base index for manual arenas. */ +extern unsigned manual_arena_base; + /* * Arenas that are used to service external requests. Not all elements of the * arenas array are necessarily used; arenas are created lazily as needed. diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h index 24ea416297..ddde9b4e63 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h @@ -4,13 +4,15 @@ #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/bit_util.h" #include "jemalloc/internal/jemalloc_internal_types.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/ticker.h" JEMALLOC_ALWAYS_INLINE malloc_cpuid_t malloc_getcpu(void) { assert(have_percpu_arena); -#if defined(JEMALLOC_HAVE_SCHED_GETCPU) +#if defined(_WIN32) + return GetCurrentProcessorNumber(); +#elif defined(JEMALLOC_HAVE_SCHED_GETCPU) return (malloc_cpuid_t)sched_getcpu(); #else not_reached(); @@ -106,16 +108,16 @@ decay_ticker_get(tsd_t *tsd, unsigned ind) { return &tdata->decay_ticker; } -JEMALLOC_ALWAYS_INLINE tcache_bin_t * +JEMALLOC_ALWAYS_INLINE cache_bin_t * tcache_small_bin_get(tcache_t *tcache, szind_t binind) { - assert(binind < NBINS); - return &tcache->tbins_small[binind]; + assert(binind < SC_NBINS); + return &tcache->bins_small[binind]; } -JEMALLOC_ALWAYS_INLINE tcache_bin_t * +JEMALLOC_ALWAYS_INLINE cache_bin_t * tcache_large_bin_get(tcache_t *tcache, szind_t binind) { - assert(binind >= NBINS &&binind < nhbins); - return &tcache->tbins_large[binind - NBINS]; + assert(binind >= SC_NBINS &&binind < nhbins); + return &tcache->bins_large[binind - SC_NBINS]; } JEMALLOC_ALWAYS_INLINE bool @@ -151,11 +153,12 @@ pre_reentrancy(tsd_t *tsd, arena_t *arena) { assert(arena != arena_get(tsd_tsdn(tsd), 0, false)); bool fast = tsd_fast(tsd); + assert(tsd_reentrancy_level_get(tsd) < INT8_MAX); ++*tsd_reentrancy_levelp_get(tsd); if (fast) { /* Prepare slow path for reentrancy. */ tsd_slow_update(tsd); - assert(tsd->state == tsd_state_nominal_slow); + assert(tsd_state_get(tsd) == tsd_state_nominal_slow); } } diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h index 2e76e5d8f7..70d6e57885 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h @@ -71,7 +71,8 @@ arena_ichoose(tsd_t *tsd, arena_t *arena) { static inline bool arena_is_auto(arena_t *arena) { assert(narenas_auto > 0); - return (arena_ind_get(arena) < narenas_auto); + + return (arena_ind_get(arena) < manual_arena_base); } JEMALLOC_ALWAYS_INLINE extent_t * diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h index 7ffce6fb03..cdb10eb21f 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h @@ -1,10 +1,29 @@ #ifndef JEMALLOC_INTERNAL_INLINES_C_H #define JEMALLOC_INTERNAL_INLINES_C_H +#include "jemalloc/internal/hook.h" #include "jemalloc/internal/jemalloc_internal_types.h" #include "jemalloc/internal/sz.h" #include "jemalloc/internal/witness.h" +/* + * Translating the names of the 'i' functions: + * Abbreviations used in the first part of the function name (before + * alloc/dalloc) describe what that function accomplishes: + * a: arena (query) + * s: size (query, or sized deallocation) + * e: extent (query) + * p: aligned (allocates) + * vs: size (query, without knowing that the pointer is into the heap) + * r: rallocx implementation + * x: xallocx implementation + * Abbreviations used in the second part of the function name (after + * alloc/dalloc) describe the arguments it takes + * z: whether to return zeroed memory + * t: accepts a tcache_t * parameter + * m: accepts an arena_t * parameter + */ + JEMALLOC_ALWAYS_INLINE arena_t * iaalloc(tsdn_t *tsdn, const void *ptr) { assert(ptr != NULL); @@ -24,11 +43,12 @@ iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, tcache_t *tcache, bool is_internal, arena_t *arena, bool slow_path) { void *ret; - assert(size != 0); assert(!is_internal || tcache == NULL); assert(!is_internal || arena == NULL || arena_is_auto(arena)); - witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), - WITNESS_RANK_CORE, 0); + if (!tsdn_null(tsdn) && tsd_reentrancy_level_get(tsdn_tsd(tsdn)) == 0) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + } ret = arena_malloc(tsdn, arena, size, ind, zero, tcache, slow_path); if (config_stats && is_internal && likely(ret != NULL)) { @@ -91,7 +111,8 @@ idalloctm(tsdn_t *tsdn, void *ptr, tcache_t *tcache, alloc_ctx_t *alloc_ctx, if (config_stats && is_internal) { arena_internal_sub(iaalloc(tsdn, ptr), isalloc(tsdn, ptr)); } - if (!is_internal && tsd_reentrancy_level_get(tsdn_tsd(tsdn)) != 0) { + if (!is_internal && !tsdn_null(tsdn) && + tsd_reentrancy_level_get(tsdn_tsd(tsdn)) != 0) { assert(tcache == NULL); } arena_dalloc(tsdn, ptr, tcache, alloc_ctx, slow_path); @@ -112,31 +133,20 @@ isdalloct(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, JEMALLOC_ALWAYS_INLINE void * iralloct_realign(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, - size_t extra, size_t alignment, bool zero, tcache_t *tcache, - arena_t *arena) { + size_t alignment, bool zero, tcache_t *tcache, arena_t *arena, + hook_ralloc_args_t *hook_args) { witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); void *p; size_t usize, copysize; - usize = sz_sa2u(size + extra, alignment); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + usize = sz_sa2u(size, alignment); + if (unlikely(usize == 0 || usize > SC_LARGE_MAXCLASS)) { return NULL; } p = ipalloct(tsdn, usize, alignment, zero, tcache, arena); if (p == NULL) { - if (extra == 0) { - return NULL; - } - /* Try again, without extra this time. */ - usize = sz_sa2u(size, alignment); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { - return NULL; - } - p = ipalloct(tsdn, usize, alignment, zero, tcache, arena); - if (p == NULL) { - return NULL; - } + return NULL; } /* * Copy at most size bytes (not size+extra), since the caller has no @@ -144,13 +154,26 @@ iralloct_realign(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, */ copysize = (size < oldsize) ? size : oldsize; memcpy(p, ptr, copysize); + hook_invoke_alloc(hook_args->is_realloc + ? hook_alloc_realloc : hook_alloc_rallocx, p, (uintptr_t)p, + hook_args->args); + hook_invoke_dalloc(hook_args->is_realloc + ? hook_dalloc_realloc : hook_dalloc_rallocx, ptr, hook_args->args); isdalloct(tsdn, ptr, oldsize, tcache, NULL, true); return p; } +/* + * is_realloc threads through the knowledge of whether or not this call comes + * from je_realloc (as opposed to je_rallocx); this ensures that we pass the + * correct entry point into any hooks. + * Note that these functions are all force-inlined, so no actual bool gets + * passed-around anywhere. + */ JEMALLOC_ALWAYS_INLINE void * iralloct(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t alignment, - bool zero, tcache_t *tcache, arena_t *arena) { + bool zero, tcache_t *tcache, arena_t *arena, hook_ralloc_args_t *hook_args) +{ assert(ptr != NULL); assert(size != 0); witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), @@ -162,24 +185,24 @@ iralloct(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t alignment, * Existing object alignment is inadequate; allocate new space * and copy. */ - return iralloct_realign(tsdn, ptr, oldsize, size, 0, alignment, - zero, tcache, arena); + return iralloct_realign(tsdn, ptr, oldsize, size, alignment, + zero, tcache, arena, hook_args); } return arena_ralloc(tsdn, arena, ptr, oldsize, size, alignment, zero, - tcache); + tcache, hook_args); } JEMALLOC_ALWAYS_INLINE void * iralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment, - bool zero) { + bool zero, hook_ralloc_args_t *hook_args) { return iralloct(tsd_tsdn(tsd), ptr, oldsize, size, alignment, zero, - tcache_get(tsd), NULL); + tcache_get(tsd), NULL, hook_args); } JEMALLOC_ALWAYS_INLINE bool ixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero) { + size_t alignment, bool zero, size_t *newsize) { assert(ptr != NULL); assert(size != 0); witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), @@ -188,10 +211,12 @@ ixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra, if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1)) != 0) { /* Existing object alignment is inadequate. */ + *newsize = oldsize; return true; } - return arena_ralloc_no_move(tsdn, ptr, oldsize, size, extra, zero); + return arena_ralloc_no_move(tsdn, ptr, oldsize, size, extra, zero, + newsize); } #endif /* JEMALLOC_INTERNAL_INLINES_C_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h index 4571895ec3..d8ea06f6d0 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h @@ -30,11 +30,85 @@ # define restrict #endif -/* Various function pointers are statick and immutable except during testing. */ +/* Various function pointers are static and immutable except during testing. */ #ifdef JEMALLOC_JET # define JET_MUTABLE #else # define JET_MUTABLE const #endif +#define JEMALLOC_VA_ARGS_HEAD(head, ...) head +#define JEMALLOC_VA_ARGS_TAIL(head, ...) __VA_ARGS__ + +#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__) \ + && defined(JEMALLOC_HAVE_ATTR) && (__GNUC__ >= 7) +#define JEMALLOC_FALLTHROUGH JEMALLOC_ATTR(fallthrough); +#else +#define JEMALLOC_FALLTHROUGH /* falls through */ +#endif + +/* Diagnostic suppression macros */ +#if defined(_MSC_VER) && !defined(__clang__) +# define JEMALLOC_DIAGNOSTIC_PUSH __pragma(warning(push)) +# define JEMALLOC_DIAGNOSTIC_POP __pragma(warning(pop)) +# define JEMALLOC_DIAGNOSTIC_IGNORE(W) __pragma(warning(disable:W)) +# define JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS +# define JEMALLOC_DIAGNOSTIC_IGNORE_TYPE_LIMITS +# define JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN +# define JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS +/* #pragma GCC diagnostic first appeared in gcc 4.6. */ +#elif (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && \ + (__GNUC_MINOR__ > 5)))) || defined(__clang__) +/* + * The JEMALLOC_PRAGMA__ macro is an implementation detail of the GCC and Clang + * diagnostic suppression macros and should not be used anywhere else. + */ +# define JEMALLOC_PRAGMA__(X) _Pragma(#X) +# define JEMALLOC_DIAGNOSTIC_PUSH JEMALLOC_PRAGMA__(GCC diagnostic push) +# define JEMALLOC_DIAGNOSTIC_POP JEMALLOC_PRAGMA__(GCC diagnostic pop) +# define JEMALLOC_DIAGNOSTIC_IGNORE(W) \ + JEMALLOC_PRAGMA__(GCC diagnostic ignored W) + +/* + * The -Wmissing-field-initializers warning is buggy in GCC versions < 5.1 and + * all clang versions up to version 7 (currently trunk, unreleased). This macro + * suppresses the warning for the affected compiler versions only. + */ +# if ((defined(__GNUC__) && !defined(__clang__)) && (__GNUC__ < 5)) || \ + defined(__clang__) +# define JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS \ + JEMALLOC_DIAGNOSTIC_IGNORE("-Wmissing-field-initializers") +# else +# define JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS +# endif + +# define JEMALLOC_DIAGNOSTIC_IGNORE_TYPE_LIMITS \ + JEMALLOC_DIAGNOSTIC_IGNORE("-Wtype-limits") +# define JEMALLOC_DIAGNOSTIC_IGNORE_UNUSED_PARAMETER \ + JEMALLOC_DIAGNOSTIC_IGNORE("-Wunused-parameter") +# if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 7) +# define JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN \ + JEMALLOC_DIAGNOSTIC_IGNORE("-Walloc-size-larger-than=") +# else +# define JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN +# endif +# define JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS \ + JEMALLOC_DIAGNOSTIC_PUSH \ + JEMALLOC_DIAGNOSTIC_IGNORE_UNUSED_PARAMETER +#else +# define JEMALLOC_DIAGNOSTIC_PUSH +# define JEMALLOC_DIAGNOSTIC_POP +# define JEMALLOC_DIAGNOSTIC_IGNORE(W) +# define JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS +# define JEMALLOC_DIAGNOSTIC_IGNORE_TYPE_LIMITS +# define JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN +# define JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS +#endif + +/* + * Disables spurious diagnostics for all headers. Since these headers are not + * included by users directly, it does not affect their diagnostic settings. + */ +JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS + #endif /* JEMALLOC_INTERNAL_MACROS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h index 50f9d001d5..e296c5a7e8 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h @@ -1,6 +1,8 @@ #ifndef JEMALLOC_INTERNAL_TYPES_H #define JEMALLOC_INTERNAL_TYPES_H +#include "jemalloc/internal/quantum.h" + /* Page size index type. */ typedef unsigned pszind_t; @@ -50,72 +52,6 @@ typedef int malloc_cpuid_t; /* Smallest size class to support. */ #define TINY_MIN (1U << LG_TINY_MIN) -/* - * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size - * classes). - */ -#ifndef LG_QUANTUM -# if (defined(__i386__) || defined(_M_IX86)) -# define LG_QUANTUM 4 -# endif -# ifdef __ia64__ -# define LG_QUANTUM 4 -# endif -# ifdef __alpha__ -# define LG_QUANTUM 4 -# endif -# if (defined(__sparc64__) || defined(__sparcv9) || defined(__sparc_v9__)) -# define LG_QUANTUM 4 -# endif -# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64)) -# define LG_QUANTUM 4 -# endif -# ifdef __arm__ -# define LG_QUANTUM 3 -# endif -# ifdef __aarch64__ -# define LG_QUANTUM 4 -# endif -# ifdef __hppa__ -# define LG_QUANTUM 4 -# endif -# ifdef __mips__ -# define LG_QUANTUM 3 -# endif -# ifdef __or1k__ -# define LG_QUANTUM 3 -# endif -# ifdef __powerpc__ -# define LG_QUANTUM 4 -# endif -# ifdef __riscv__ -# define LG_QUANTUM 4 -# endif -# ifdef __s390__ -# define LG_QUANTUM 4 -# endif -# ifdef __SH4__ -# define LG_QUANTUM 4 -# endif -# ifdef __tile__ -# define LG_QUANTUM 4 -# endif -# ifdef __le32__ -# define LG_QUANTUM 4 -# endif -# ifndef LG_QUANTUM -# error "Unknown minimum alignment for architecture; specify via " - "--with-lg-quantum" -# endif -#endif - -#define QUANTUM ((size_t)(1U << LG_QUANTUM)) -#define QUANTUM_MASK (QUANTUM - 1) - -/* Return the smallest quantum multiple that is >= a. */ -#define QUANTUM_CEILING(a) \ - (((a) + QUANTUM_MASK) & ~QUANTUM_MASK) - #define LONG ((size_t)(1U << LG_SIZEOF_LONG)) #define LONG_MASK (LONG - 1) diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in index 18539a0988..4bfdb32cb4 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in @@ -21,7 +21,7 @@ # include "../jemalloc@install_suffix@.h" #endif -#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN)) +#if defined(JEMALLOC_OSATOMIC) #include #endif @@ -45,7 +45,11 @@ # include "jemalloc/internal/private_namespace_jet.h" # endif #endif -#include "jemalloc/internal/hooks.h" +#include "jemalloc/internal/test_hooks.h" + +#ifdef JEMALLOC_DEFINE_MADVISE_FREE +# define JEMALLOC_MADV_FREE 8 +#endif static const bool config_debug = #ifdef JEMALLOC_DEBUG @@ -61,6 +65,13 @@ static const bool have_dss = false #endif ; +static const bool have_madvise_huge = +#ifdef JEMALLOC_HAVE_MADVISE_HUGE + true +#else + false +#endif + ; static const bool config_fill = #ifdef JEMALLOC_FILL true @@ -111,13 +122,6 @@ static const bool config_stats = false #endif ; -static const bool config_thp = -#ifdef JEMALLOC_THP - true -#else - false -#endif - ; static const bool config_tls = #ifdef JEMALLOC_TLS true @@ -146,7 +150,18 @@ static const bool config_cache_oblivious = false #endif ; -#ifdef JEMALLOC_HAVE_SCHED_GETCPU +/* + * Undocumented, for jemalloc development use only at the moment. See the note + * in jemalloc/internal/log.h. + */ +static const bool config_log = +#ifdef JEMALLOC_LOG + true +#else + false +#endif + ; +#if defined(_WIN32) || defined(JEMALLOC_HAVE_SCHED_GETCPU) /* Currently percpu_arena depends on sched_getcpu. */ #define JEMALLOC_PERCPU_ARENA #endif diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/large_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/large_externs.h index 3f36282cd4..a05019e8a5 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/large_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/large_externs.h @@ -1,13 +1,16 @@ #ifndef JEMALLOC_INTERNAL_LARGE_EXTERNS_H #define JEMALLOC_INTERNAL_LARGE_EXTERNS_H +#include "jemalloc/internal/hook.h" + void *large_malloc(tsdn_t *tsdn, arena_t *arena, size_t usize, bool zero); void *large_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, bool zero); bool large_ralloc_no_move(tsdn_t *tsdn, extent_t *extent, size_t usize_min, size_t usize_max, bool zero); -void *large_ralloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent, size_t usize, - size_t alignment, bool zero, tcache_t *tcache); +void *large_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t usize, + size_t alignment, bool zero, tcache_t *tcache, + hook_ralloc_args_t *hook_args); typedef void (large_dalloc_junk_t)(void *, size_t); extern large_dalloc_junk_t *JET_MUTABLE large_dalloc_junk; @@ -23,4 +26,7 @@ prof_tctx_t *large_prof_tctx_get(tsdn_t *tsdn, const extent_t *extent); void large_prof_tctx_set(tsdn_t *tsdn, extent_t *extent, prof_tctx_t *tctx); void large_prof_tctx_reset(tsdn_t *tsdn, extent_t *extent); +nstime_t large_prof_alloc_time_get(const extent_t *extent); +void large_prof_alloc_time_set(extent_t *extent, nstime_t time); + #endif /* JEMALLOC_INTERNAL_LARGE_EXTERNS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/log.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/log.h new file mode 100644 index 0000000000..6420858635 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/log.h @@ -0,0 +1,115 @@ +#ifndef JEMALLOC_INTERNAL_LOG_H +#define JEMALLOC_INTERNAL_LOG_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/mutex.h" + +#ifdef JEMALLOC_LOG +# define JEMALLOC_LOG_VAR_BUFSIZE 1000 +#else +# define JEMALLOC_LOG_VAR_BUFSIZE 1 +#endif + +#define JEMALLOC_LOG_BUFSIZE 4096 + +/* + * The log malloc_conf option is a '|'-delimited list of log_var name segments + * which should be logged. The names are themselves hierarchical, with '.' as + * the delimiter (a "segment" is just a prefix in the log namespace). So, if + * you have: + * + * log("arena", "log msg for arena"); // 1 + * log("arena.a", "log msg for arena.a"); // 2 + * log("arena.b", "log msg for arena.b"); // 3 + * log("arena.a.a", "log msg for arena.a.a"); // 4 + * log("extent.a", "log msg for extent.a"); // 5 + * log("extent.b", "log msg for extent.b"); // 6 + * + * And your malloc_conf option is "log=arena.a|extent", then lines 2, 4, 5, and + * 6 will print at runtime. You can enable logging from all log vars by + * writing "log=.". + * + * None of this should be regarded as a stable API for right now. It's intended + * as a debugging interface, to let us keep around some of our printf-debugging + * statements. + */ + +extern char log_var_names[JEMALLOC_LOG_VAR_BUFSIZE]; +extern atomic_b_t log_init_done; + +typedef struct log_var_s log_var_t; +struct log_var_s { + /* + * Lowest bit is "inited", second lowest is "enabled". Putting them in + * a single word lets us avoid any fences on weak architectures. + */ + atomic_u_t state; + const char *name; +}; + +#define LOG_NOT_INITIALIZED 0U +#define LOG_INITIALIZED_NOT_ENABLED 1U +#define LOG_ENABLED 2U + +#define LOG_VAR_INIT(name_str) {ATOMIC_INIT(LOG_NOT_INITIALIZED), name_str} + +/* + * Returns the value we should assume for state (which is not necessarily + * accurate; if logging is done before logging has finished initializing, then + * we default to doing the safe thing by logging everything). + */ +unsigned log_var_update_state(log_var_t *log_var); + +/* We factor out the metadata management to allow us to test more easily. */ +#define log_do_begin(log_var) \ +if (config_log) { \ + unsigned log_state = atomic_load_u(&(log_var).state, \ + ATOMIC_RELAXED); \ + if (unlikely(log_state == LOG_NOT_INITIALIZED)) { \ + log_state = log_var_update_state(&(log_var)); \ + assert(log_state != LOG_NOT_INITIALIZED); \ + } \ + if (log_state == LOG_ENABLED) { \ + { + /* User code executes here. */ +#define log_do_end(log_var) \ + } \ + } \ +} + +/* + * MSVC has some preprocessor bugs in its expansion of __VA_ARGS__ during + * preprocessing. To work around this, we take all potential extra arguments in + * a var-args functions. Since a varargs macro needs at least one argument in + * the "...", we accept the format string there, and require that the first + * argument in this "..." is a const char *. + */ +static inline void +log_impl_varargs(const char *name, ...) { + char buf[JEMALLOC_LOG_BUFSIZE]; + va_list ap; + + va_start(ap, name); + const char *format = va_arg(ap, const char *); + size_t dst_offset = 0; + dst_offset += malloc_snprintf(buf, JEMALLOC_LOG_BUFSIZE, "%s: ", name); + dst_offset += malloc_vsnprintf(buf + dst_offset, + JEMALLOC_LOG_BUFSIZE - dst_offset, format, ap); + dst_offset += malloc_snprintf(buf + dst_offset, + JEMALLOC_LOG_BUFSIZE - dst_offset, "\n"); + va_end(ap); + + malloc_write(buf); +} + +/* Call as log("log.var.str", "format_string %d", arg_for_format_string); */ +#define LOG(log_var_str, ...) \ +do { \ + static log_var_t log_var = LOG_VAR_INIT(log_var_str); \ + log_do_begin(log_var) \ + log_impl_varargs((log_var).name, __VA_ARGS__); \ + log_do_end(log_var) \ +} while (0) + +#endif /* JEMALLOC_INTERNAL_LOG_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/malloc_io.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/malloc_io.h index 47ae58ec35..bfe556b523 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/malloc_io.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/malloc_io.h @@ -53,10 +53,50 @@ size_t malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap); size_t malloc_snprintf(char *str, size_t size, const char *format, ...) JEMALLOC_FORMAT_PRINTF(3, 4); +/* + * The caller can set write_cb and cbopaque to null to choose to print with the + * je_malloc_message hook. + */ void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, const char *format, va_list ap); void malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque, const char *format, ...) JEMALLOC_FORMAT_PRINTF(3, 4); void malloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2); +static inline ssize_t +malloc_write_fd(int fd, const void *buf, size_t count) { +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write) + /* + * Use syscall(2) rather than write(2) when possible in order to avoid + * the possibility of memory allocation within libc. This is necessary + * on FreeBSD; most operating systems do not have this problem though. + * + * syscall() returns long or int, depending on platform, so capture the + * result in the widest plausible type to avoid compiler warnings. + */ + long result = syscall(SYS_write, fd, buf, count); +#else + ssize_t result = (ssize_t)write(fd, buf, +#ifdef _WIN32 + (unsigned int) +#endif + count); +#endif + return (ssize_t)result; +} + +static inline ssize_t +malloc_read_fd(int fd, void *buf, size_t count) { +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read) + long result = syscall(SYS_read, fd, buf, count); +#else + ssize_t result = read(fd, buf, +#ifdef _WIN32 + (unsigned int) +#endif + count); +#endif + return (ssize_t)result; +} + #endif /* JEMALLOC_INTERNAL_MALLOC_IO_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex.h index 6520c2512d..7c24f0725e 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex.h @@ -37,14 +37,17 @@ struct malloc_mutex_s { # endif #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) os_unfair_lock lock; -#elif (defined(JEMALLOC_OSSPIN)) - OSSpinLock lock; #elif (defined(JEMALLOC_MUTEX_INIT_CB)) pthread_mutex_t lock; malloc_mutex_t *postponed_next; #else pthread_mutex_t lock; #endif + /* + * Hint flag to avoid exclusive cache line contention + * during spin waiting + */ + atomic_b_t locked; }; /* * We only touch witness when configured w/ debug. However we @@ -84,10 +87,6 @@ struct malloc_mutex_s { # define MALLOC_MUTEX_LOCK(m) os_unfair_lock_lock(&(m)->lock) # define MALLOC_MUTEX_UNLOCK(m) os_unfair_lock_unlock(&(m)->lock) # define MALLOC_MUTEX_TRYLOCK(m) (!os_unfair_lock_trylock(&(m)->lock)) -#elif (defined(JEMALLOC_OSSPIN)) -# define MALLOC_MUTEX_LOCK(m) OSSpinLockLock(&(m)->lock) -# define MALLOC_MUTEX_UNLOCK(m) OSSpinLockUnlock(&(m)->lock) -# define MALLOC_MUTEX_TRYLOCK(m) (!OSSpinLockTry(&(m)->lock)) #else # define MALLOC_MUTEX_LOCK(m) pthread_mutex_lock(&(m)->lock) # define MALLOC_MUTEX_UNLOCK(m) pthread_mutex_unlock(&(m)->lock) @@ -101,22 +100,37 @@ struct malloc_mutex_s { #ifdef _WIN32 # define MALLOC_MUTEX_INITIALIZER #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) -# define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, OS_UNFAIR_LOCK_INIT}}, \ - WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} -#elif (defined(JEMALLOC_OSSPIN)) -# define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, 0}}, \ +# if defined(JEMALLOC_DEBUG) +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, OS_UNFAIR_LOCK_INIT, ATOMIC_INIT(false)}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT), 0} +# else +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, OS_UNFAIR_LOCK_INIT, ATOMIC_INIT(false)}}, \ WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} +# endif #elif (defined(JEMALLOC_MUTEX_INIT_CB)) -# define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL}}, \ - WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} +# if (defined(JEMALLOC_DEBUG)) +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL, ATOMIC_INIT(false)}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT), 0} +# else +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL, ATOMIC_INIT(false)}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} +# endif + #else # define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT +# if defined(JEMALLOC_DEBUG) # define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER}}, \ - WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} + {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, ATOMIC_INIT(false)}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT), 0} +# else +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, ATOMIC_INIT(false)}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} +# endif #endif #ifdef JEMALLOC_LAZY_LOCK @@ -139,6 +153,7 @@ void malloc_mutex_lock_slow(malloc_mutex_t *mutex); static inline void malloc_mutex_lock_final(malloc_mutex_t *mutex) { MALLOC_MUTEX_LOCK(mutex); + atomic_store_b(&mutex->locked, true, ATOMIC_RELAXED); } static inline bool @@ -164,6 +179,7 @@ malloc_mutex_trylock(tsdn_t *tsdn, malloc_mutex_t *mutex) { witness_assert_not_owner(tsdn_witness_tsdp_get(tsdn), &mutex->witness); if (isthreaded) { if (malloc_mutex_trylock_final(mutex)) { + atomic_store_b(&mutex->locked, true, ATOMIC_RELAXED); return true; } mutex_owner_stats_update(tsdn, mutex); @@ -203,6 +219,7 @@ malloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex) { if (isthreaded) { if (malloc_mutex_trylock_final(mutex)) { malloc_mutex_lock_slow(mutex); + atomic_store_b(&mutex->locked, true, ATOMIC_RELAXED); } mutex_owner_stats_update(tsdn, mutex); } @@ -211,6 +228,7 @@ malloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex) { static inline void malloc_mutex_unlock(tsdn_t *tsdn, malloc_mutex_t *mutex) { + atomic_store_b(&mutex->locked, false, ATOMIC_RELAXED); witness_unlock(tsdn_witness_tsdp_get(tsdn), &mutex->witness); if (isthreaded) { MALLOC_MUTEX_UNLOCK(mutex); @@ -245,4 +263,26 @@ malloc_mutex_prof_read(tsdn_t *tsdn, mutex_prof_data_t *data, atomic_store_u32(&data->n_waiting_thds, 0, ATOMIC_RELAXED); } +static inline void +malloc_mutex_prof_accum(tsdn_t *tsdn, mutex_prof_data_t *data, + malloc_mutex_t *mutex) { + mutex_prof_data_t *source = &mutex->prof_data; + /* Can only read holding the mutex. */ + malloc_mutex_assert_owner(tsdn, mutex); + + nstime_add(&data->tot_wait_time, &source->tot_wait_time); + if (nstime_compare(&source->max_wait_time, &data->max_wait_time) > 0) { + nstime_copy(&data->max_wait_time, &source->max_wait_time); + } + data->n_wait_times += source->n_wait_times; + data->n_spin_acquired += source->n_spin_acquired; + if (data->max_n_thds < source->max_n_thds) { + data->max_n_thds = source->max_n_thds; + } + /* n_wait_thds is not reported. */ + atomic_store_u32(&data->n_waiting_thds, 0, ATOMIC_RELAXED); + data->n_owner_switches += source->n_owner_switches; + data->n_lock_ops += source->n_lock_ops; +} + #endif /* JEMALLOC_INTERNAL_MUTEX_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex_prof.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex_prof.h index 3358bcf535..2cb8fb0cbf 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex_prof.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/mutex_prof.h @@ -35,21 +35,43 @@ typedef enum { mutex_prof_num_arena_mutexes } mutex_prof_arena_ind_t; +/* + * The forth parameter is a boolean value that is true for derived rate counters + * and false for real ones. + */ +#define MUTEX_PROF_UINT64_COUNTERS \ + OP(num_ops, uint64_t, "n_lock_ops", false, num_ops) \ + OP(num_ops_ps, uint64_t, "(#/sec)", true, num_ops) \ + OP(num_wait, uint64_t, "n_waiting", false, num_wait) \ + OP(num_wait_ps, uint64_t, "(#/sec)", true, num_wait) \ + OP(num_spin_acq, uint64_t, "n_spin_acq", false, num_spin_acq) \ + OP(num_spin_acq_ps, uint64_t, "(#/sec)", true, num_spin_acq) \ + OP(num_owner_switch, uint64_t, "n_owner_switch", false, num_owner_switch) \ + OP(num_owner_switch_ps, uint64_t, "(#/sec)", true, num_owner_switch) \ + OP(total_wait_time, uint64_t, "total_wait_ns", false, total_wait_time) \ + OP(total_wait_time_ps, uint64_t, "(#/sec)", true, total_wait_time) \ + OP(max_wait_time, uint64_t, "max_wait_ns", false, max_wait_time) + +#define MUTEX_PROF_UINT32_COUNTERS \ + OP(max_num_thds, uint32_t, "max_n_thds", false, max_num_thds) + #define MUTEX_PROF_COUNTERS \ - OP(num_ops, uint64_t) \ - OP(num_wait, uint64_t) \ - OP(num_spin_acq, uint64_t) \ - OP(num_owner_switch, uint64_t) \ - OP(total_wait_time, uint64_t) \ - OP(max_wait_time, uint64_t) \ - OP(max_num_thds, uint32_t) + MUTEX_PROF_UINT64_COUNTERS \ + MUTEX_PROF_UINT32_COUNTERS -typedef enum { -#define OP(counter, type) mutex_counter_##counter, - MUTEX_PROF_COUNTERS +#define OP(counter, type, human, derived, base_counter) mutex_counter_##counter, + +#define COUNTER_ENUM(counter_list, t) \ + typedef enum { \ + counter_list \ + mutex_prof_num_##t##_counters \ + } mutex_prof_##t##_counter_ind_t; + +COUNTER_ENUM(MUTEX_PROF_UINT64_COUNTERS, uint64_t) +COUNTER_ENUM(MUTEX_PROF_UINT32_COUNTERS, uint32_t) + +#undef COUNTER_ENUM #undef OP - mutex_prof_num_counters -} mutex_prof_counter_ind_t; typedef struct { /* diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/pages.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/pages.h index 28383b7f97..7dae633afe 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/pages.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/pages.h @@ -58,6 +58,20 @@ static const bool pages_can_purge_forced = #endif ; +typedef enum { + thp_mode_default = 0, /* Do not change hugepage settings. */ + thp_mode_always = 1, /* Always set MADV_HUGEPAGE. */ + thp_mode_never = 2, /* Always set MADV_NOHUGEPAGE. */ + + thp_mode_names_limit = 3, /* Used for option processing. */ + thp_mode_not_supported = 3 /* No THP support detected. */ +} thp_mode_t; + +#define THP_MODE_DEFAULT thp_mode_default +extern thp_mode_t opt_thp; +extern thp_mode_t init_system_thp_mode; /* Initial system wide state. */ +extern const char *thp_mode_names[]; + void *pages_map(void *addr, size_t size, size_t alignment, bool *commit); void pages_unmap(void *addr, size_t size); bool pages_commit(void *addr, size_t size); @@ -66,6 +80,9 @@ bool pages_purge_lazy(void *addr, size_t size); bool pages_purge_forced(void *addr, size_t size); bool pages_huge(void *addr, size_t size); bool pages_nohuge(void *addr, size_t size); +bool pages_dontdump(void *addr, size_t size); +bool pages_dodump(void *addr, size_t size); bool pages_boot(void); +void pages_set_thp_state (void *ptr, size_t size); #endif /* JEMALLOC_INTERNAL_PAGES_EXTERNS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_externs.h index 04348696f5..094f3e170a 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_externs.h @@ -14,6 +14,7 @@ extern bool opt_prof_gdump; /* High-water memory dumping. */ extern bool opt_prof_final; /* Final profile dumping. */ extern bool opt_prof_leak; /* Dump leak summary at exit. */ extern bool opt_prof_accum; /* Report cumulative bytes. */ +extern bool opt_prof_log; /* Turn logging on at boot. */ extern char opt_prof_prefix[ /* Minimize memory bloat for non-prof builds. */ #ifdef JEMALLOC_PROF @@ -45,7 +46,8 @@ extern size_t lg_prof_sample; void prof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx, bool updated); void prof_malloc_sample_object(tsdn_t *tsdn, const void *ptr, size_t usize, prof_tctx_t *tctx); -void prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx); +void prof_free_sampled_object(tsd_t *tsd, const void *ptr, size_t usize, + prof_tctx_t *tctx); void bt_init(prof_bt_t *bt, void **vec); void prof_backtrace(prof_bt_t *bt); prof_tctx_t *prof_lookup(tsd_t *tsd, prof_bt_t *bt); @@ -89,4 +91,15 @@ void prof_postfork_parent(tsdn_t *tsdn); void prof_postfork_child(tsdn_t *tsdn); void prof_sample_threshold_update(prof_tdata_t *tdata); +bool prof_log_start(tsdn_t *tsdn, const char *filename); +bool prof_log_stop(tsdn_t *tsdn); +#ifdef JEMALLOC_JET +size_t prof_log_bt_count(void); +size_t prof_log_alloc_count(void); +size_t prof_log_thr_count(void); +bool prof_log_is_logging(void); +bool prof_log_rep_check(void); +void prof_log_dummy_set(bool new_value); +#endif + #endif /* JEMALLOC_INTERNAL_PROF_EXTERNS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_a.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_a.h index eda6839ade..471d9853cf 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_a.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_a.h @@ -4,7 +4,8 @@ #include "jemalloc/internal/mutex.h" static inline bool -prof_accum_add(tsdn_t *tsdn, prof_accum_t *prof_accum, uint64_t accumbytes) { +prof_accum_add(tsdn_t *tsdn, prof_accum_t *prof_accum, + uint64_t accumbytes) { cassert(config_prof); bool overflow; @@ -42,7 +43,8 @@ prof_accum_add(tsdn_t *tsdn, prof_accum_t *prof_accum, uint64_t accumbytes) { } static inline void -prof_accum_cancel(tsdn_t *tsdn, prof_accum_t *prof_accum, size_t usize) { +prof_accum_cancel(tsdn_t *tsdn, prof_accum_t *prof_accum, + size_t usize) { cassert(config_prof); /* @@ -55,18 +57,29 @@ prof_accum_cancel(tsdn_t *tsdn, prof_accum_t *prof_accum, size_t usize) { #ifdef JEMALLOC_ATOMIC_U64 a0 = atomic_load_u64(&prof_accum->accumbytes, ATOMIC_RELAXED); do { - a1 = (a0 >= LARGE_MINCLASS - usize) ? a0 - (LARGE_MINCLASS - - usize) : 0; + a1 = (a0 >= SC_LARGE_MINCLASS - usize) + ? a0 - (SC_LARGE_MINCLASS - usize) : 0; } while (!atomic_compare_exchange_weak_u64(&prof_accum->accumbytes, &a0, a1, ATOMIC_RELAXED, ATOMIC_RELAXED)); #else malloc_mutex_lock(tsdn, &prof_accum->mtx); a0 = prof_accum->accumbytes; - a1 = (a0 >= LARGE_MINCLASS - usize) ? a0 - (LARGE_MINCLASS - usize) : - 0; + a1 = (a0 >= SC_LARGE_MINCLASS - usize) + ? a0 - (SC_LARGE_MINCLASS - usize) : 0; prof_accum->accumbytes = a1; malloc_mutex_unlock(tsdn, &prof_accum->mtx); #endif } +JEMALLOC_ALWAYS_INLINE bool +prof_active_get_unlocked(void) { + /* + * Even if opt_prof is true, sampling can be temporarily disabled by + * setting prof_active to false. No locking is used when reading + * prof_active in the fast path, so there are no guarantees regarding + * how long it will take for all threads to notice state changes. + */ + return prof_active; +} + #endif /* JEMALLOC_INTERNAL_PROF_INLINES_A_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_b.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_b.h index d670cb7b8f..8358bffb5e 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_b.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_inlines_b.h @@ -3,17 +3,6 @@ #include "jemalloc/internal/sz.h" -JEMALLOC_ALWAYS_INLINE bool -prof_active_get_unlocked(void) { - /* - * Even if opt_prof is true, sampling can be temporarily disabled by - * setting prof_active to false. No locking is used when reading - * prof_active in the fast path, so there are no guarantees regarding - * how long it will take for all threads to notice state changes. - */ - return prof_active; -} - JEMALLOC_ALWAYS_INLINE bool prof_gdump_get_unlocked(void) { /* @@ -72,13 +61,54 @@ prof_tctx_reset(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx) { arena_prof_tctx_reset(tsdn, ptr, tctx); } +JEMALLOC_ALWAYS_INLINE nstime_t +prof_alloc_time_get(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx) { + cassert(config_prof); + assert(ptr != NULL); + + return arena_prof_alloc_time_get(tsdn, ptr, alloc_ctx); +} + +JEMALLOC_ALWAYS_INLINE void +prof_alloc_time_set(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx, + nstime_t t) { + cassert(config_prof); + assert(ptr != NULL); + + arena_prof_alloc_time_set(tsdn, ptr, alloc_ctx, t); +} + +JEMALLOC_ALWAYS_INLINE bool +prof_sample_check(tsd_t *tsd, size_t usize, bool update) { + ssize_t check = update ? 0 : usize; + + int64_t bytes_until_sample = tsd_bytes_until_sample_get(tsd); + if (update) { + bytes_until_sample -= usize; + if (tsd_nominal(tsd)) { + tsd_bytes_until_sample_set(tsd, bytes_until_sample); + } + } + if (likely(bytes_until_sample >= check)) { + return true; + } + + return false; +} + JEMALLOC_ALWAYS_INLINE bool prof_sample_accum_update(tsd_t *tsd, size_t usize, bool update, - prof_tdata_t **tdata_out) { + prof_tdata_t **tdata_out) { prof_tdata_t *tdata; cassert(config_prof); + /* Fastpath: no need to load tdata */ + if (likely(prof_sample_check(tsd, usize, update))) { + return true; + } + + bool booted = tsd_prof_tdata_get(tsd); tdata = prof_tdata_get(tsd, true); if (unlikely((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)) { tdata = NULL; @@ -92,21 +122,23 @@ prof_sample_accum_update(tsd_t *tsd, size_t usize, bool update, return true; } - if (likely(tdata->bytes_until_sample >= usize)) { - if (update) { - tdata->bytes_until_sample -= usize; - } + /* + * If this was the first creation of tdata, then + * prof_tdata_get() reset bytes_until_sample, so decrement and + * check it again + */ + if (!booted && prof_sample_check(tsd, usize, update)) { return true; - } else { - if (tsd_reentrancy_level_get(tsd) > 0) { - return true; - } - /* Compute new sample threshold. */ - if (update) { - prof_sample_threshold_update(tdata); - } - return !tdata->active; } + + if (tsd_reentrancy_level_get(tsd) > 0) { + return true; + } + /* Compute new sample threshold. */ + if (update) { + prof_sample_threshold_update(tdata); + } + return !tdata->active; } JEMALLOC_ALWAYS_INLINE prof_tctx_t * @@ -198,7 +230,7 @@ prof_realloc(tsd_t *tsd, const void *ptr, size_t usize, prof_tctx_t *tctx, * counters. */ if (unlikely(old_sampled)) { - prof_free_sampled_object(tsd, old_usize, old_tctx); + prof_free_sampled_object(tsd, ptr, old_usize, old_tctx); } } @@ -210,7 +242,7 @@ prof_free(tsd_t *tsd, const void *ptr, size_t usize, alloc_ctx_t *alloc_ctx) { assert(usize == isalloc(tsd_tsdn(tsd), ptr)); if (unlikely((uintptr_t)tctx > (uintptr_t)1U)) { - prof_free_sampled_object(tsd, usize, tctx); + prof_free_sampled_object(tsd, ptr, usize, tctx); } } diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_structs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_structs.h index 0d58ae1005..34ed4822b6 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_structs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/prof_structs.h @@ -169,7 +169,6 @@ struct prof_tdata_s { /* Sampling state. */ uint64_t prng_state; - uint64_t bytes_until_sample; /* State used to avoid dumping while operating on prof internals. */ bool enq; diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/quantum.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/quantum.h new file mode 100644 index 0000000000..821086e992 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/quantum.h @@ -0,0 +1,77 @@ +#ifndef JEMALLOC_INTERNAL_QUANTUM_H +#define JEMALLOC_INTERNAL_QUANTUM_H + +/* + * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size + * classes). + */ +#ifndef LG_QUANTUM +# if (defined(__i386__) || defined(_M_IX86)) +# define LG_QUANTUM 4 +# endif +# ifdef __ia64__ +# define LG_QUANTUM 4 +# endif +# ifdef __alpha__ +# define LG_QUANTUM 4 +# endif +# if (defined(__sparc64__) || defined(__sparcv9) || defined(__sparc_v9__)) +# define LG_QUANTUM 4 +# endif +# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64)) +# define LG_QUANTUM 4 +# endif +# ifdef __arm__ +# define LG_QUANTUM 3 +# endif +# ifdef __aarch64__ +# define LG_QUANTUM 4 +# endif +# ifdef __hppa__ +# define LG_QUANTUM 4 +# endif +# ifdef __m68k__ +# define LG_QUANTUM 3 +# endif +# ifdef __mips__ +# define LG_QUANTUM 3 +# endif +# ifdef __nios2__ +# define LG_QUANTUM 3 +# endif +# ifdef __or1k__ +# define LG_QUANTUM 3 +# endif +# ifdef __powerpc__ +# define LG_QUANTUM 4 +# endif +# if defined(__riscv) || defined(__riscv__) +# define LG_QUANTUM 4 +# endif +# ifdef __s390__ +# define LG_QUANTUM 4 +# endif +# if (defined (__SH3E__) || defined(__SH4_SINGLE__) || defined(__SH4__) || \ + defined(__SH4_SINGLE_ONLY__)) +# define LG_QUANTUM 4 +# endif +# ifdef __tile__ +# define LG_QUANTUM 4 +# endif +# ifdef __le32__ +# define LG_QUANTUM 4 +# endif +# ifndef LG_QUANTUM +# error "Unknown minimum alignment for architecture; specify via " + "--with-lg-quantum" +# endif +#endif + +#define QUANTUM ((size_t)(1U << LG_QUANTUM)) +#define QUANTUM_MASK (QUANTUM - 1) + +/* Return the smallest quantum multiple that is >= a. */ +#define QUANTUM_CEILING(a) \ + (((a) + QUANTUM_MASK) & ~QUANTUM_MASK) + +#endif /* JEMALLOC_INTERNAL_QUANTUM_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree.h index b5d4db3988..16ccbebee7 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree.h @@ -4,7 +4,7 @@ #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/rtree_tsd.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/tsd.h" /* @@ -31,7 +31,7 @@ # error Unsupported number of significant virtual address bits #endif /* Use compact leaf representation if virtual address encoding allows. */ -#if RTREE_NHIB >= LG_CEIL_NSIZES +#if RTREE_NHIB >= LG_CEIL(SC_NSIZES) # define RTREE_LEAF_COMPACT #endif @@ -170,17 +170,29 @@ rtree_subkey(uintptr_t key, unsigned level) { */ # ifdef RTREE_LEAF_COMPACT JEMALLOC_ALWAYS_INLINE uintptr_t -rtree_leaf_elm_bits_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - bool dependent) { +rtree_leaf_elm_bits_read(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, bool dependent) { return (uintptr_t)atomic_load_p(&elm->le_bits, dependent ? ATOMIC_RELAXED : ATOMIC_ACQUIRE); } JEMALLOC_ALWAYS_INLINE extent_t * rtree_leaf_elm_bits_extent_get(uintptr_t bits) { +# ifdef __aarch64__ + /* + * aarch64 doesn't sign extend the highest virtual address bit to set + * the higher ones. Instead, the high bits gets zeroed. + */ + uintptr_t high_bit_mask = ((uintptr_t)1 << LG_VADDR) - 1; + /* Mask off the slab bit. */ + uintptr_t low_bit_mask = ~(uintptr_t)1; + uintptr_t mask = high_bit_mask & low_bit_mask; + return (extent_t *)(bits & mask); +# else /* Restore sign-extended high bits, mask slab bit. */ return (extent_t *)((uintptr_t)((intptr_t)(bits << RTREE_NHIB) >> RTREE_NHIB) & ~((uintptr_t)0x1)); +# endif } JEMALLOC_ALWAYS_INLINE szind_t @@ -196,8 +208,8 @@ rtree_leaf_elm_bits_slab_get(uintptr_t bits) { # endif JEMALLOC_ALWAYS_INLINE extent_t * -rtree_leaf_elm_extent_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - bool dependent) { +rtree_leaf_elm_extent_read(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, bool dependent) { #ifdef RTREE_LEAF_COMPACT uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent); return rtree_leaf_elm_bits_extent_get(bits); @@ -209,8 +221,8 @@ rtree_leaf_elm_extent_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, } JEMALLOC_ALWAYS_INLINE szind_t -rtree_leaf_elm_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - bool dependent) { +rtree_leaf_elm_szind_read(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, bool dependent) { #ifdef RTREE_LEAF_COMPACT uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent); return rtree_leaf_elm_bits_szind_get(bits); @@ -221,8 +233,8 @@ rtree_leaf_elm_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, } JEMALLOC_ALWAYS_INLINE bool -rtree_leaf_elm_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - bool dependent) { +rtree_leaf_elm_slab_read(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, bool dependent) { #ifdef RTREE_LEAF_COMPACT uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent); return rtree_leaf_elm_bits_slab_get(bits); @@ -233,8 +245,8 @@ rtree_leaf_elm_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, } static inline void -rtree_leaf_elm_extent_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - extent_t *extent) { +rtree_leaf_elm_extent_write(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, extent_t *extent) { #ifdef RTREE_LEAF_COMPACT uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, true); uintptr_t bits = ((uintptr_t)rtree_leaf_elm_bits_szind_get(old_bits) << @@ -247,9 +259,9 @@ rtree_leaf_elm_extent_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, } static inline void -rtree_leaf_elm_szind_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - szind_t szind) { - assert(szind <= NSIZES); +rtree_leaf_elm_szind_write(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, szind_t szind) { + assert(szind <= SC_NSIZES); #ifdef RTREE_LEAF_COMPACT uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, @@ -265,8 +277,8 @@ rtree_leaf_elm_szind_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, } static inline void -rtree_leaf_elm_slab_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - bool slab) { +rtree_leaf_elm_slab_write(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, bool slab) { #ifdef RTREE_LEAF_COMPACT uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, true); @@ -280,8 +292,8 @@ rtree_leaf_elm_slab_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, } static inline void -rtree_leaf_elm_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, - extent_t *extent, szind_t szind, bool slab) { +rtree_leaf_elm_write(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, extent_t *extent, szind_t szind, bool slab) { #ifdef RTREE_LEAF_COMPACT uintptr_t bits = ((uintptr_t)szind << LG_VADDR) | ((uintptr_t)extent & (((uintptr_t)0x1 << LG_VADDR) - 1)) | @@ -301,7 +313,7 @@ rtree_leaf_elm_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, static inline void rtree_leaf_elm_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, szind_t szind, bool slab) { - assert(!slab || szind < NBINS); + assert(!slab || szind < SC_NBINS); /* * The caller implicitly assures that it is the only writer to the szind @@ -417,7 +429,7 @@ rtree_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, dependent); if (!dependent && elm == NULL) { - return NSIZES; + return SC_NSIZES; } return rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent); } @@ -440,6 +452,42 @@ rtree_extent_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, return false; } +/* + * Try to read szind_slab from the L1 cache. Returns true on a hit, + * and fills in r_szind and r_slab. Otherwise returns false. + * + * Key is allowed to be NULL in order to save an extra branch on the + * fastpath. returns false in this case. + */ +JEMALLOC_ALWAYS_INLINE bool +rtree_szind_slab_read_fast(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, szind_t *r_szind, bool *r_slab) { + rtree_leaf_elm_t *elm; + + size_t slot = rtree_cache_direct_map(key); + uintptr_t leafkey = rtree_leafkey(key); + assert(leafkey != RTREE_LEAFKEY_INVALID); + + if (likely(rtree_ctx->cache[slot].leafkey == leafkey)) { + rtree_leaf_elm_t *leaf = rtree_ctx->cache[slot].leaf; + assert(leaf != NULL); + uintptr_t subkey = rtree_subkey(key, RTREE_HEIGHT-1); + elm = &leaf[subkey]; + +#ifdef RTREE_LEAF_COMPACT + uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, + elm, true); + *r_szind = rtree_leaf_elm_bits_szind_get(bits); + *r_slab = rtree_leaf_elm_bits_slab_get(bits); +#else + *r_szind = rtree_leaf_elm_szind_read(tsdn, rtree, elm, true); + *r_slab = rtree_leaf_elm_slab_read(tsdn, rtree, elm, true); +#endif + return true; + } else { + return false; + } +} JEMALLOC_ALWAYS_INLINE bool rtree_szind_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key, bool dependent, szind_t *r_szind, bool *r_slab) { @@ -448,15 +496,21 @@ rtree_szind_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, if (!dependent && elm == NULL) { return true; } +#ifdef RTREE_LEAF_COMPACT + uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent); + *r_szind = rtree_leaf_elm_bits_szind_get(bits); + *r_slab = rtree_leaf_elm_bits_slab_get(bits); +#else *r_szind = rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent); *r_slab = rtree_leaf_elm_slab_read(tsdn, rtree, elm, dependent); +#endif return false; } static inline void rtree_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key, szind_t szind, bool slab) { - assert(!slab || szind < NBINS); + assert(!slab || szind < SC_NBINS); rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true); rtree_leaf_elm_szind_slab_update(tsdn, rtree, elm, szind, slab); @@ -468,7 +522,7 @@ rtree_clear(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true); assert(rtree_leaf_elm_extent_read(tsdn, rtree, elm, false) != NULL); - rtree_leaf_elm_write(tsdn, rtree, elm, NULL, NSIZES, false); + rtree_leaf_elm_write(tsdn, rtree, elm, NULL, SC_NSIZES, false); } #endif /* JEMALLOC_INTERNAL_RTREE_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree_tsd.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree_tsd.h index 3cdc862548..562e29297a 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree_tsd.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/rtree_tsd.h @@ -26,7 +26,7 @@ * Zero initializer required for tsd initialization only. Proper initialization * done via rtree_ctx_data_init(). */ -#define RTREE_CTX_ZERO_INITIALIZER {{{0}}} +#define RTREE_CTX_ZERO_INITIALIZER {{{0, 0}}, {{0, 0}}} typedef struct rtree_leaf_elm_s rtree_leaf_elm_t; diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sc.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sc.h new file mode 100644 index 0000000000..ef0a451237 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sc.h @@ -0,0 +1,320 @@ +#ifndef JEMALLOC_INTERNAL_SC_H +#define JEMALLOC_INTERNAL_SC_H + +#include "jemalloc/internal/jemalloc_internal_types.h" + +/* + * Size class computations: + * + * These are a little tricky; we'll first start by describing how things + * generally work, and then describe some of the details. + * + * Ignore the first few size classes for a moment. We can then split all the + * remaining size classes into groups. The size classes in a group are spaced + * such that they cover allocation request sizes in a power-of-2 range. The + * power of two is called the base of the group, and the size classes in it + * satisfy allocations in the half-open range (base, base * 2]. There are + * SC_NGROUP size classes in each group, equally spaced in the range, so that + * each one covers allocations for base / SC_NGROUP possible allocation sizes. + * We call that value (base / SC_NGROUP) the delta of the group. Each size class + * is delta larger than the one before it (including the initial size class in a + * group, which is delta large than 2**base, the largest size class in the + * previous group). + * To make the math all work out nicely, we require that SC_NGROUP is a power of + * two, and define it in terms of SC_LG_NGROUP. We'll often talk in terms of + * lg_base and lg_delta. For each of these groups then, we have that + * lg_delta == lg_base - SC_LG_NGROUP. + * The size classes in a group with a given lg_base and lg_delta (which, recall, + * can be computed from lg_base for these groups) are therefore: + * base + 1 * delta + * which covers allocations in (base, base + 1 * delta] + * base + 2 * delta + * which covers allocations in (base + 1 * delta, base + 2 * delta]. + * base + 3 * delta + * which covers allocations in (base + 2 * delta, base + 3 * delta]. + * ... + * base + SC_NGROUP * delta ( == 2 * base) + * which covers allocations in (base + (SC_NGROUP - 1) * delta, 2 * base]. + * (Note that currently SC_NGROUP is always 4, so the "..." is empty in + * practice.) + * Note that the last size class in the group is the next power of two (after + * base), so that we've set up the induction correctly for the next group's + * selection of delta. + * + * Now, let's start considering the first few size classes. Two extra constants + * come into play here: LG_QUANTUM and SC_LG_TINY_MIN. LG_QUANTUM ensures + * correct platform alignment; all objects of size (1 << LG_QUANTUM) or larger + * are at least (1 << LG_QUANTUM) aligned; this can be used to ensure that we + * never return improperly aligned memory, by making (1 << LG_QUANTUM) equal the + * highest required alignment of a platform. For allocation sizes smaller than + * (1 << LG_QUANTUM) though, we can be more relaxed (since we don't support + * platforms with types with alignment larger than their size). To allow such + * allocations (without wasting space unnecessarily), we introduce tiny size + * classes; one per power of two, up until we hit the quantum size. There are + * therefore LG_QUANTUM - SC_LG_TINY_MIN such size classes. + * + * Next, we have a size class of size LG_QUANTUM. This can't be the start of a + * group in the sense we described above (covering a power of two range) since, + * if we divided into it to pick a value of delta, we'd get a delta smaller than + * (1 << LG_QUANTUM) for sizes >= (1 << LG_QUANTUM), which is against the rules. + * + * The first base we can divide by SC_NGROUP while still being at least + * (1 << LG_QUANTUM) is SC_NGROUP * (1 << LG_QUANTUM). We can get there by + * having SC_NGROUP size classes, spaced (1 << LG_QUANTUM) apart. These size + * classes are: + * 1 * (1 << LG_QUANTUM) + * 2 * (1 << LG_QUANTUM) + * 3 * (1 << LG_QUANTUM) + * ... (although, as above, this "..." is empty in practice) + * SC_NGROUP * (1 << LG_QUANTUM). + * + * There are SC_NGROUP of these size classes, so we can regard it as a sort of + * pseudo-group, even though it spans multiple powers of 2, is divided + * differently, and both starts and ends on a power of 2 (as opposed to just + * ending). SC_NGROUP is itself a power of two, so the first group after the + * pseudo-group has the power-of-two base SC_NGROUP * (1 << LG_QUANTUM), for a + * lg_base of LG_QUANTUM + SC_LG_NGROUP. We can divide this base into SC_NGROUP + * sizes without violating our LG_QUANTUM requirements, so we can safely set + * lg_delta = lg_base - SC_LG_GROUP (== LG_QUANTUM). + * + * So, in order, the size classes are: + * + * Tiny size classes: + * - Count: LG_QUANTUM - SC_LG_TINY_MIN. + * - Sizes: + * 1 << SC_LG_TINY_MIN + * 1 << (SC_LG_TINY_MIN + 1) + * 1 << (SC_LG_TINY_MIN + 2) + * ... + * 1 << (LG_QUANTUM - 1) + * + * Initial pseudo-group: + * - Count: SC_NGROUP + * - Sizes: + * 1 * (1 << LG_QUANTUM) + * 2 * (1 << LG_QUANTUM) + * 3 * (1 << LG_QUANTUM) + * ... + * SC_NGROUP * (1 << LG_QUANTUM) + * + * Regular group 0: + * - Count: SC_NGROUP + * - Sizes: + * (relative to lg_base of LG_QUANTUM + SC_LG_NGROUP and lg_delta of + * lg_base - SC_LG_NGROUP) + * (1 << lg_base) + 1 * (1 << lg_delta) + * (1 << lg_base) + 2 * (1 << lg_delta) + * (1 << lg_base) + 3 * (1 << lg_delta) + * ... + * (1 << lg_base) + SC_NGROUP * (1 << lg_delta) [ == (1 << (lg_base + 1)) ] + * + * Regular group 1: + * - Count: SC_NGROUP + * - Sizes: + * (relative to lg_base of LG_QUANTUM + SC_LG_NGROUP + 1 and lg_delta of + * lg_base - SC_LG_NGROUP) + * (1 << lg_base) + 1 * (1 << lg_delta) + * (1 << lg_base) + 2 * (1 << lg_delta) + * (1 << lg_base) + 3 * (1 << lg_delta) + * ... + * (1 << lg_base) + SC_NGROUP * (1 << lg_delta) [ == (1 << (lg_base + 1)) ] + * + * ... + * + * Regular group N: + * - Count: SC_NGROUP + * - Sizes: + * (relative to lg_base of LG_QUANTUM + SC_LG_NGROUP + N and lg_delta of + * lg_base - SC_LG_NGROUP) + * (1 << lg_base) + 1 * (1 << lg_delta) + * (1 << lg_base) + 2 * (1 << lg_delta) + * (1 << lg_base) + 3 * (1 << lg_delta) + * ... + * (1 << lg_base) + SC_NGROUP * (1 << lg_delta) [ == (1 << (lg_base + 1)) ] + * + * + * Representation of metadata: + * To make the math easy, we'll mostly work in lg quantities. We record lg_base, + * lg_delta, and ndelta (i.e. number of deltas above the base) on a + * per-size-class basis, and maintain the invariant that, across all size + * classes, size == (1 << lg_base) + ndelta * (1 << lg_delta). + * + * For regular groups (i.e. those with lg_base >= LG_QUANTUM + SC_LG_NGROUP), + * lg_delta is lg_base - SC_LG_NGROUP, and ndelta goes from 1 to SC_NGROUP. + * + * For the initial tiny size classes (if any), lg_base is lg(size class size). + * lg_delta is lg_base for the first size class, and lg_base - 1 for all + * subsequent ones. ndelta is always 0. + * + * For the pseudo-group, if there are no tiny size classes, then we set + * lg_base == LG_QUANTUM, lg_delta == LG_QUANTUM, and have ndelta range from 0 + * to SC_NGROUP - 1. (Note that delta == base, so base + (SC_NGROUP - 1) * delta + * is just SC_NGROUP * base, or (1 << (SC_LG_NGROUP + LG_QUANTUM)), so we do + * indeed get a power of two that way). If there *are* tiny size classes, then + * the first size class needs to have lg_delta relative to the largest tiny size + * class. We therefore set lg_base == LG_QUANTUM - 1, + * lg_delta == LG_QUANTUM - 1, and ndelta == 1, keeping the rest of the + * pseudo-group the same. + * + * + * Other terminology: + * "Small" size classes mean those that are allocated out of bins, which is the + * same as those that are slab allocated. + * "Large" size classes are those that are not small. The cutoff for counting as + * large is page size * group size. + */ + +/* + * Size class N + (1 << SC_LG_NGROUP) twice the size of size class N. + */ +#define SC_LG_NGROUP 2 +#define SC_LG_TINY_MIN 3 + +#if SC_LG_TINY_MIN == 0 +/* The div module doesn't support division by 1, which this would require. */ +#error "Unsupported LG_TINY_MIN" +#endif + +/* + * The definitions below are all determined by the above settings and system + * characteristics. + */ +#define SC_NGROUP (1ULL << SC_LG_NGROUP) +#define SC_PTR_BITS ((1ULL << LG_SIZEOF_PTR) * 8) +#define SC_NTINY (LG_QUANTUM - SC_LG_TINY_MIN) +#define SC_LG_TINY_MAXCLASS (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1) +#define SC_NPSEUDO SC_NGROUP +#define SC_LG_FIRST_REGULAR_BASE (LG_QUANTUM + SC_LG_NGROUP) +/* + * We cap allocations to be less than 2 ** (ptr_bits - 1), so the highest base + * we need is 2 ** (ptr_bits - 2). (This also means that the last group is 1 + * size class shorter than the others). + * We could probably save some space in arenas by capping this at LG_VADDR size. + */ +#define SC_LG_BASE_MAX (SC_PTR_BITS - 2) +#define SC_NREGULAR (SC_NGROUP * \ + (SC_LG_BASE_MAX - SC_LG_FIRST_REGULAR_BASE + 1) - 1) +#define SC_NSIZES (SC_NTINY + SC_NPSEUDO + SC_NREGULAR) + + /* The number of size classes that are a multiple of the page size. */ +#define SC_NPSIZES ( \ + /* Start with all the size classes. */ \ + SC_NSIZES \ + /* Subtract out those groups with too small a base. */ \ + - (LG_PAGE - 1 - SC_LG_FIRST_REGULAR_BASE) * SC_NGROUP \ + /* And the pseudo-group. */ \ + - SC_NPSEUDO \ + /* And the tiny group. */ \ + - SC_NTINY \ + /* Groups where ndelta*delta is not a multiple of the page size. */ \ + - (2 * (SC_NGROUP))) + +/* + * We declare a size class is binnable if size < page size * group. Or, in other + * words, lg(size) < lg(page size) + lg(group size). + */ +#define SC_NBINS ( \ + /* Sub-regular size classes. */ \ + SC_NTINY + SC_NPSEUDO \ + /* Groups with lg_regular_min_base <= lg_base <= lg_base_max */ \ + + SC_NGROUP * (LG_PAGE + SC_LG_NGROUP - SC_LG_FIRST_REGULAR_BASE) \ + /* Last SC of the last group hits the bound exactly; exclude it. */ \ + - 1) + +/* + * The size2index_tab lookup table uses uint8_t to encode each bin index, so we + * cannot support more than 256 small size classes. + */ +#if (SC_NBINS > 256) +# error "Too many small size classes" +#endif + +/* The largest size class in the lookup table. */ +#define SC_LOOKUP_MAXCLASS ((size_t)1 << 12) + +/* Internal, only used for the definition of SC_SMALL_MAXCLASS. */ +#define SC_SMALL_MAX_BASE ((size_t)1 << (LG_PAGE + SC_LG_NGROUP - 1)) +#define SC_SMALL_MAX_DELTA ((size_t)1 << (LG_PAGE - 1)) + +/* The largest size class allocated out of a slab. */ +#define SC_SMALL_MAXCLASS (SC_SMALL_MAX_BASE \ + + (SC_NGROUP - 1) * SC_SMALL_MAX_DELTA) + +/* The smallest size class not allocated out of a slab. */ +#define SC_LARGE_MINCLASS ((size_t)1ULL << (LG_PAGE + SC_LG_NGROUP)) +#define SC_LG_LARGE_MINCLASS (LG_PAGE + SC_LG_NGROUP) + +/* Internal; only used for the definition of SC_LARGE_MAXCLASS. */ +#define SC_MAX_BASE ((size_t)1 << (SC_PTR_BITS - 2)) +#define SC_MAX_DELTA ((size_t)1 << (SC_PTR_BITS - 2 - SC_LG_NGROUP)) + +/* The largest size class supported. */ +#define SC_LARGE_MAXCLASS (SC_MAX_BASE + (SC_NGROUP - 1) * SC_MAX_DELTA) + +typedef struct sc_s sc_t; +struct sc_s { + /* Size class index, or -1 if not a valid size class. */ + int index; + /* Lg group base size (no deltas added). */ + int lg_base; + /* Lg delta to previous size class. */ + int lg_delta; + /* Delta multiplier. size == 1<data) / sizeof(size_t)]; \ + buf[sizeof(buf) / sizeof(size_t) - 1] = 0; \ + memcpy(buf, src, sizeof(type)); \ + size_t old_seq = atomic_load_zu(&dst->seq, ATOMIC_RELAXED); \ + atomic_store_zu(&dst->seq, old_seq + 1, ATOMIC_RELAXED); \ + atomic_fence(ATOMIC_RELEASE); \ + for (size_t i = 0; i < sizeof(buf) / sizeof(size_t); i++) { \ + atomic_store_zu(&dst->data[i], buf[i], ATOMIC_RELAXED); \ + } \ + atomic_store_zu(&dst->seq, old_seq + 2, ATOMIC_RELEASE); \ +} \ + \ +/* Returns whether or not the read was consistent. */ \ +static inline bool \ +seq_try_load_##short_type(type *dst, seq_##short_type##_t *src) { \ + size_t buf[sizeof(src->data) / sizeof(size_t)]; \ + size_t seq1 = atomic_load_zu(&src->seq, ATOMIC_ACQUIRE); \ + if (seq1 % 2 != 0) { \ + return false; \ + } \ + for (size_t i = 0; i < sizeof(buf) / sizeof(size_t); i++) { \ + buf[i] = atomic_load_zu(&src->data[i], ATOMIC_RELAXED); \ + } \ + atomic_fence(ATOMIC_ACQUIRE); \ + size_t seq2 = atomic_load_zu(&src->seq, ATOMIC_RELAXED); \ + if (seq1 != seq2) { \ + return false; \ + } \ + memcpy(dst, buf, sizeof(type)); \ + return true; \ +} + +#endif /* JEMALLOC_INTERNAL_SEQ_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/size_classes.sh b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/size_classes.sh deleted file mode 100755 index 998994d09e..0000000000 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/size_classes.sh +++ /dev/null @@ -1,361 +0,0 @@ -#!/bin/sh -# -# Usage: size_classes.sh - -# The following limits are chosen such that they cover all supported platforms. - -# Pointer sizes. -lg_zarr="2 3" - -# Quanta. -lg_qarr=$1 - -# The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)]. -lg_tmin=$2 - -# Maximum lookup size. -lg_kmax=12 - -# Page sizes. -lg_parr=`echo $3 | tr ',' ' '` - -# Size class group size (number of size classes for each size doubling). -lg_g=$4 - -pow2() { - e=$1 - pow2_result=1 - while [ ${e} -gt 0 ] ; do - pow2_result=$((${pow2_result} + ${pow2_result})) - e=$((${e} - 1)) - done -} - -lg() { - x=$1 - lg_result=0 - while [ ${x} -gt 1 ] ; do - lg_result=$((${lg_result} + 1)) - x=$((${x} / 2)) - done -} - -lg_ceil() { - y=$1 - lg ${y}; lg_floor=${lg_result} - pow2 ${lg_floor}; pow2_floor=${pow2_result} - if [ ${pow2_floor} -lt ${y} ] ; then - lg_ceil_result=$((${lg_floor} + 1)) - else - lg_ceil_result=${lg_floor} - fi -} - -reg_size_compute() { - lg_grp=$1 - lg_delta=$2 - ndelta=$3 - - pow2 ${lg_grp}; grp=${pow2_result} - pow2 ${lg_delta}; delta=${pow2_result} - reg_size=$((${grp} + ${delta}*${ndelta})) -} - -slab_size() { - lg_p=$1 - lg_grp=$2 - lg_delta=$3 - ndelta=$4 - - pow2 ${lg_p}; p=${pow2_result} - reg_size_compute ${lg_grp} ${lg_delta} ${ndelta} - - # Compute smallest slab size that is an integer multiple of reg_size. - try_slab_size=${p} - try_nregs=$((${try_slab_size} / ${reg_size})) - perfect=0 - while [ ${perfect} -eq 0 ] ; do - perfect_slab_size=${try_slab_size} - perfect_nregs=${try_nregs} - - try_slab_size=$((${try_slab_size} + ${p})) - try_nregs=$((${try_slab_size} / ${reg_size})) - if [ ${perfect_slab_size} -eq $((${perfect_nregs} * ${reg_size})) ] ; then - perfect=1 - fi - done - - slab_size_pgs=$((${perfect_slab_size} / ${p})) -} - -size_class() { - index=$1 - lg_grp=$2 - lg_delta=$3 - ndelta=$4 - lg_p=$5 - lg_kmax=$6 - - if [ ${lg_delta} -ge ${lg_p} ] ; then - psz="yes" - else - pow2 ${lg_p}; p=${pow2_result} - pow2 ${lg_grp}; grp=${pow2_result} - pow2 ${lg_delta}; delta=${pow2_result} - sz=$((${grp} + ${delta} * ${ndelta})) - npgs=$((${sz} / ${p})) - if [ ${sz} -eq $((${npgs} * ${p})) ] ; then - psz="yes" - else - psz="no" - fi - fi - - lg ${ndelta}; lg_ndelta=${lg_result}; pow2 ${lg_ndelta} - if [ ${pow2_result} -lt ${ndelta} ] ; then - rem="yes" - else - rem="no" - fi - - lg_size=${lg_grp} - if [ $((${lg_delta} + ${lg_ndelta})) -eq ${lg_grp} ] ; then - lg_size=$((${lg_grp} + 1)) - else - lg_size=${lg_grp} - rem="yes" - fi - - if [ ${lg_size} -lt $((${lg_p} + ${lg_g})) ] ; then - bin="yes" - slab_size ${lg_p} ${lg_grp} ${lg_delta} ${ndelta}; pgs=${slab_size_pgs} - else - bin="no" - pgs=0 - fi - if [ ${lg_size} -lt ${lg_kmax} \ - -o ${lg_size} -eq ${lg_kmax} -a ${rem} = "no" ] ; then - lg_delta_lookup=${lg_delta} - else - lg_delta_lookup="no" - fi - printf ' SC(%3d, %6d, %8d, %6d, %3s, %3s, %3d, %2s) \\\n' ${index} ${lg_grp} ${lg_delta} ${ndelta} ${psz} ${bin} ${pgs} ${lg_delta_lookup} - # Defined upon return: - # - psz ("yes" or "no") - # - bin ("yes" or "no") - # - pgs - # - lg_delta_lookup (${lg_delta} or "no") -} - -sep_line() { - echo " \\" -} - -size_classes() { - lg_z=$1 - lg_q=$2 - lg_t=$3 - lg_p=$4 - lg_g=$5 - - pow2 $((${lg_z} + 3)); ptr_bits=${pow2_result} - pow2 ${lg_g}; g=${pow2_result} - - echo "#define SIZE_CLASSES \\" - echo " /* index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup */ \\" - - ntbins=0 - nlbins=0 - lg_tiny_maxclass='"NA"' - nbins=0 - npsizes=0 - - # Tiny size classes. - ndelta=0 - index=0 - lg_grp=${lg_t} - lg_delta=${lg_grp} - while [ ${lg_grp} -lt ${lg_q} ] ; do - size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} - if [ ${lg_delta_lookup} != "no" ] ; then - nlbins=$((${index} + 1)) - fi - if [ ${psz} = "yes" ] ; then - npsizes=$((${npsizes} + 1)) - fi - if [ ${bin} != "no" ] ; then - nbins=$((${index} + 1)) - fi - ntbins=$((${ntbins} + 1)) - lg_tiny_maxclass=${lg_grp} # Final written value is correct. - index=$((${index} + 1)) - lg_delta=${lg_grp} - lg_grp=$((${lg_grp} + 1)) - done - - # First non-tiny group. - if [ ${ntbins} -gt 0 ] ; then - sep_line - # The first size class has an unusual encoding, because the size has to be - # split between grp and delta*ndelta. - lg_grp=$((${lg_grp} - 1)) - ndelta=1 - size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} - index=$((${index} + 1)) - lg_grp=$((${lg_grp} + 1)) - lg_delta=$((${lg_delta} + 1)) - if [ ${psz} = "yes" ] ; then - npsizes=$((${npsizes} + 1)) - fi - fi - while [ ${ndelta} -lt ${g} ] ; do - size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} - index=$((${index} + 1)) - ndelta=$((${ndelta} + 1)) - if [ ${psz} = "yes" ] ; then - npsizes=$((${npsizes} + 1)) - fi - done - - # All remaining groups. - lg_grp=$((${lg_grp} + ${lg_g})) - while [ ${lg_grp} -lt $((${ptr_bits} - 1)) ] ; do - sep_line - ndelta=1 - if [ ${lg_grp} -eq $((${ptr_bits} - 2)) ] ; then - ndelta_limit=$((${g} - 1)) - else - ndelta_limit=${g} - fi - while [ ${ndelta} -le ${ndelta_limit} ] ; do - size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} - if [ ${lg_delta_lookup} != "no" ] ; then - nlbins=$((${index} + 1)) - # Final written value is correct: - lookup_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" - fi - if [ ${psz} = "yes" ] ; then - npsizes=$((${npsizes} + 1)) - fi - if [ ${bin} != "no" ] ; then - nbins=$((${index} + 1)) - # Final written value is correct: - small_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" - if [ ${lg_g} -gt 0 ] ; then - lg_large_minclass=$((${lg_grp} + 1)) - else - lg_large_minclass=$((${lg_grp} + 2)) - fi - fi - # Final written value is correct: - large_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" - index=$((${index} + 1)) - ndelta=$((${ndelta} + 1)) - done - lg_grp=$((${lg_grp} + 1)) - lg_delta=$((${lg_delta} + 1)) - done - echo - nsizes=${index} - lg_ceil ${nsizes}; lg_ceil_nsizes=${lg_ceil_result} - - # Defined upon completion: - # - ntbins - # - nlbins - # - nbins - # - nsizes - # - lg_ceil_nsizes - # - npsizes - # - lg_tiny_maxclass - # - lookup_maxclass - # - small_maxclass - # - lg_large_minclass - # - large_maxclass -} - -cat < 256) -# error "Too many small size classes" -#endif - -#endif /* JEMALLOC_INTERNAL_SIZE_CLASSES_H */ -EOF diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/spin.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/spin.h index e2afc98cfd..22804c687f 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/spin.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/spin.h @@ -1,25 +1,29 @@ #ifndef JEMALLOC_INTERNAL_SPIN_H #define JEMALLOC_INTERNAL_SPIN_H -#ifdef JEMALLOC_SPIN_C_ -# define SPIN_INLINE extern inline -#else -# define SPIN_INLINE inline -#endif - #define SPIN_INITIALIZER {0U} typedef struct { unsigned iteration; } spin_t; -SPIN_INLINE void +static inline void +spin_cpu_spinwait() { +# if HAVE_CPU_SPINWAIT + CPU_SPINWAIT; +# else + volatile int x = 0; + x = x; +# endif +} + +static inline void spin_adaptive(spin_t *spin) { volatile uint32_t i; if (spin->iteration < 5) { for (i = 0; i < (1U << spin->iteration); i++) { - CPU_SPINWAIT; + spin_cpu_spinwait(); } spin->iteration++; } else { diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats.h index 1198779ab9..3b9e0eac12 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats.h @@ -1,12 +1,6 @@ #ifndef JEMALLOC_INTERNAL_STATS_H #define JEMALLOC_INTERNAL_STATS_H -#include "jemalloc/internal/atomic.h" -#include "jemalloc/internal/mutex_prof.h" -#include "jemalloc/internal/mutex.h" -#include "jemalloc/internal/size_classes.h" -#include "jemalloc/internal/stats_tsd.h" - /* OPTION(opt, var_name, default, set_value_to) */ #define STATS_PRINT_OPTIONS \ OPTION('J', json, false, true) \ @@ -16,7 +10,8 @@ OPTION('a', unmerged, config_stats, false) \ OPTION('b', bins, true, false) \ OPTION('l', large, true, false) \ - OPTION('x', mutex, true, false) + OPTION('x', mutex, true, false) \ + OPTION('e', extents, true, false) enum { #define OPTION(o, v, d, s) stats_print_option_num_##v, @@ -33,132 +28,4 @@ extern char opt_stats_print_opts[stats_print_tot_num_options+1]; void stats_print(void (*write_cb)(void *, const char *), void *cbopaque, const char *opts); -/* - * In those architectures that support 64-bit atomics, we use atomic updates for - * our 64-bit values. Otherwise, we use a plain uint64_t and synchronize - * externally. - */ -#ifdef JEMALLOC_ATOMIC_U64 -typedef atomic_u64_t arena_stats_u64_t; -#else -/* Must hold the arena stats mutex while reading atomically. */ -typedef uint64_t arena_stats_u64_t; -#endif - -typedef struct malloc_bin_stats_s { - /* - * Total number of allocation/deallocation requests served directly by - * the bin. Note that tcache may allocate an object, then recycle it - * many times, resulting many increments to nrequests, but only one - * each to nmalloc and ndalloc. - */ - uint64_t nmalloc; - uint64_t ndalloc; - - /* - * Number of allocation requests that correspond to the size of this - * bin. This includes requests served by tcache, though tcache only - * periodically merges into this counter. - */ - uint64_t nrequests; - - /* - * Current number of regions of this size class, including regions - * currently cached by tcache. - */ - size_t curregs; - - /* Number of tcache fills from this bin. */ - uint64_t nfills; - - /* Number of tcache flushes to this bin. */ - uint64_t nflushes; - - /* Total number of slabs created for this bin's size class. */ - uint64_t nslabs; - - /* - * Total number of slabs reused by extracting them from the slabs heap - * for this bin's size class. - */ - uint64_t reslabs; - - /* Current number of slabs in this bin. */ - size_t curslabs; - - mutex_prof_data_t mutex_data; -} malloc_bin_stats_t; - -typedef struct malloc_large_stats_s { - /* - * Total number of allocation/deallocation requests served directly by - * the arena. - */ - arena_stats_u64_t nmalloc; - arena_stats_u64_t ndalloc; - - /* - * Number of allocation requests that correspond to this size class. - * This includes requests served by tcache, though tcache only - * periodically merges into this counter. - */ - arena_stats_u64_t nrequests; /* Partially derived. */ - - /* Current number of allocations of this size class. */ - size_t curlextents; /* Derived. */ -} malloc_large_stats_t; - -typedef struct decay_stats_s { - /* Total number of purge sweeps. */ - arena_stats_u64_t npurge; - /* Total number of madvise calls made. */ - arena_stats_u64_t nmadvise; - /* Total number of pages purged. */ - arena_stats_u64_t purged; -} decay_stats_t; - -/* - * Arena stats. Note that fields marked "derived" are not directly maintained - * within the arena code; rather their values are derived during stats merge - * requests. - */ -typedef struct arena_stats_s { -#ifndef JEMALLOC_ATOMIC_U64 - malloc_mutex_t mtx; -#endif - - /* Number of bytes currently mapped, excluding retained memory. */ - atomic_zu_t mapped; /* Partially derived. */ - - /* - * Number of unused virtual memory bytes currently retained. Retained - * bytes are technically mapped (though always decommitted or purged), - * but they are excluded from the mapped statistic (above). - */ - atomic_zu_t retained; /* Derived. */ - - decay_stats_t decay_dirty; - decay_stats_t decay_muzzy; - - atomic_zu_t base; /* Derived. */ - atomic_zu_t internal; - atomic_zu_t resident; /* Derived. */ - - atomic_zu_t allocated_large; /* Derived. */ - arena_stats_u64_t nmalloc_large; /* Derived. */ - arena_stats_u64_t ndalloc_large; /* Derived. */ - arena_stats_u64_t nrequests_large; /* Derived. */ - - /* Number of bytes cached in tcache associated with this arena. */ - atomic_zu_t tcache_bytes; /* Derived. */ - - mutex_prof_data_t mutex_prof_data[mutex_prof_num_arena_mutexes]; - - /* One element for each large size class. */ - malloc_large_stats_t lstats[NSIZES - NBINS]; - - /* Arena uptime. */ - nstime_t uptime; -} arena_stats_t; - #endif /* JEMALLOC_INTERNAL_STATS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats_tsd.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats_tsd.h deleted file mode 100755 index d0c3bbe494..0000000000 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/stats_tsd.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef JEMALLOC_INTERNAL_STATS_TSD_H -#define JEMALLOC_INTERNAL_STATS_TSD_H - -typedef struct tcache_bin_stats_s { - /* - * Number of allocation requests that corresponded to the size of this - * bin. - */ - uint64_t nrequests; -} tcache_bin_stats_t; - -#endif /* JEMALLOC_INTERNAL_STATS_TSD_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sz.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sz.h index 7f640d55ad..68e558abfe 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sz.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/sz.h @@ -3,7 +3,7 @@ #include "jemalloc/internal/bit_util.h" #include "jemalloc/internal/pages.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/util.h" /* @@ -26,18 +26,18 @@ * sz_pind2sz_tab encodes the same information as could be computed by * sz_pind2sz_compute(). */ -extern size_t const sz_pind2sz_tab[NPSIZES+1]; +extern size_t sz_pind2sz_tab[SC_NPSIZES + 1]; /* * sz_index2size_tab encodes the same information as could be computed (at * unacceptable cost in some code paths) by sz_index2size_compute(). */ -extern size_t const sz_index2size_tab[NSIZES]; +extern size_t sz_index2size_tab[SC_NSIZES]; /* * sz_size2index_tab is a compact lookup table that rounds request sizes up to * size classes. In order to reduce cache footprint, the table is compressed, * and all accesses are via sz_size2index(). */ -extern uint8_t const sz_size2index_tab[]; +extern uint8_t sz_size2index_tab[]; static const size_t sz_large_pad = #ifdef JEMALLOC_CACHE_OBLIVIOUS @@ -47,49 +47,47 @@ static const size_t sz_large_pad = #endif ; +extern void sz_boot(const sc_data_t *sc_data); + JEMALLOC_ALWAYS_INLINE pszind_t sz_psz2ind(size_t psz) { - if (unlikely(psz > LARGE_MAXCLASS)) { - return NPSIZES; + if (unlikely(psz > SC_LARGE_MAXCLASS)) { + return SC_NPSIZES; } - { - pszind_t x = lg_floor((psz<<1)-1); - pszind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_PAGE) ? 0 : x - - (LG_SIZE_CLASS_GROUP + LG_PAGE); - pszind_t grp = shift << LG_SIZE_CLASS_GROUP; + pszind_t x = lg_floor((psz<<1)-1); + pszind_t shift = (x < SC_LG_NGROUP + LG_PAGE) ? + 0 : x - (SC_LG_NGROUP + LG_PAGE); + pszind_t grp = shift << SC_LG_NGROUP; - pszind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ? - LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1; + pszind_t lg_delta = (x < SC_LG_NGROUP + LG_PAGE + 1) ? + LG_PAGE : x - SC_LG_NGROUP - 1; - size_t delta_inverse_mask = ZD(-1) << lg_delta; - pszind_t mod = ((((psz-1) & delta_inverse_mask) >> lg_delta)) & - ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1); + size_t delta_inverse_mask = ZU(-1) << lg_delta; + pszind_t mod = ((((psz-1) & delta_inverse_mask) >> lg_delta)) & + ((ZU(1) << SC_LG_NGROUP) - 1); - pszind_t ind = grp + mod; - return ind; - } + pszind_t ind = grp + mod; + return ind; } static inline size_t sz_pind2sz_compute(pszind_t pind) { - if (unlikely(pind == NPSIZES)) { - return LARGE_MAXCLASS + PAGE; + if (unlikely(pind == SC_NPSIZES)) { + return SC_LARGE_MAXCLASS + PAGE; } - { - size_t grp = pind >> LG_SIZE_CLASS_GROUP; - size_t mod = pind & ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1); + size_t grp = pind >> SC_LG_NGROUP; + size_t mod = pind & ((ZU(1) << SC_LG_NGROUP) - 1); - size_t grp_size_mask = ~((!!grp)-1); - size_t grp_size = ((ZU(1) << (LG_PAGE + - (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask; + size_t grp_size_mask = ~((!!grp)-1); + size_t grp_size = ((ZU(1) << (LG_PAGE + (SC_LG_NGROUP-1))) << grp) + & grp_size_mask; - size_t shift = (grp == 0) ? 1 : grp; - size_t lg_delta = shift + (LG_PAGE-1); - size_t mod_size = (mod+1) << lg_delta; + size_t shift = (grp == 0) ? 1 : grp; + size_t lg_delta = shift + (LG_PAGE-1); + size_t mod_size = (mod+1) << lg_delta; - size_t sz = grp_size + mod_size; - return sz; - } + size_t sz = grp_size + mod_size; + return sz; } static inline size_t @@ -101,70 +99,70 @@ sz_pind2sz_lookup(pszind_t pind) { static inline size_t sz_pind2sz(pszind_t pind) { - assert(pind < NPSIZES+1); + assert(pind < SC_NPSIZES + 1); return sz_pind2sz_lookup(pind); } static inline size_t sz_psz2u(size_t psz) { - if (unlikely(psz > LARGE_MAXCLASS)) { - return LARGE_MAXCLASS + PAGE; - } - { - size_t x = lg_floor((psz<<1)-1); - size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ? - LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1; - size_t delta = ZU(1) << lg_delta; - size_t delta_mask = delta - 1; - size_t usize = (psz + delta_mask) & ~delta_mask; - return usize; + if (unlikely(psz > SC_LARGE_MAXCLASS)) { + return SC_LARGE_MAXCLASS + PAGE; } + size_t x = lg_floor((psz<<1)-1); + size_t lg_delta = (x < SC_LG_NGROUP + LG_PAGE + 1) ? + LG_PAGE : x - SC_LG_NGROUP - 1; + size_t delta = ZU(1) << lg_delta; + size_t delta_mask = delta - 1; + size_t usize = (psz + delta_mask) & ~delta_mask; + return usize; } static inline szind_t sz_size2index_compute(size_t size) { - if (unlikely(size > LARGE_MAXCLASS)) { - return NSIZES; + if (unlikely(size > SC_LARGE_MAXCLASS)) { + return SC_NSIZES; + } + + if (size == 0) { + return 0; } -#if (NTBINS != 0) - if (size <= (ZU(1) << LG_TINY_MAXCLASS)) { - szind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1; +#if (SC_NTINY != 0) + if (size <= (ZU(1) << SC_LG_TINY_MAXCLASS)) { + szind_t lg_tmin = SC_LG_TINY_MAXCLASS - SC_NTINY + 1; szind_t lg_ceil = lg_floor(pow2_ceil_zu(size)); return (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin); } #endif { szind_t x = lg_floor((size<<1)-1); - szind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 : - x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM); - szind_t grp = shift << LG_SIZE_CLASS_GROUP; + szind_t shift = (x < SC_LG_NGROUP + LG_QUANTUM) ? 0 : + x - (SC_LG_NGROUP + LG_QUANTUM); + szind_t grp = shift << SC_LG_NGROUP; - szind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1) - ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1; + szind_t lg_delta = (x < SC_LG_NGROUP + LG_QUANTUM + 1) + ? LG_QUANTUM : x - SC_LG_NGROUP - 1; - size_t delta_inverse_mask = ZD(-1) << lg_delta; + size_t delta_inverse_mask = ZU(-1) << lg_delta; szind_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) & - ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1); + ((ZU(1) << SC_LG_NGROUP) - 1); - szind_t index = NTBINS + grp + mod; + szind_t index = SC_NTINY + grp + mod; return index; } } JEMALLOC_ALWAYS_INLINE szind_t sz_size2index_lookup(size_t size) { - assert(size <= LOOKUP_MAXCLASS); - { - szind_t ret = (sz_size2index_tab[(size-1) >> LG_TINY_MIN]); - assert(ret == sz_size2index_compute(size)); - return ret; - } + assert(size <= SC_LOOKUP_MAXCLASS); + szind_t ret = (sz_size2index_tab[(size + (ZU(1) << SC_LG_TINY_MIN) - 1) + >> SC_LG_TINY_MIN]); + assert(ret == sz_size2index_compute(size)); + return ret; } JEMALLOC_ALWAYS_INLINE szind_t sz_size2index(size_t size) { - assert(size > 0); - if (likely(size <= LOOKUP_MAXCLASS)) { + if (likely(size <= SC_LOOKUP_MAXCLASS)) { return sz_size2index_lookup(size); } return sz_size2index_compute(size); @@ -172,20 +170,20 @@ sz_size2index(size_t size) { static inline size_t sz_index2size_compute(szind_t index) { -#if (NTBINS > 0) - if (index < NTBINS) { - return (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index)); +#if (SC_NTINY > 0) + if (index < SC_NTINY) { + return (ZU(1) << (SC_LG_TINY_MAXCLASS - SC_NTINY + 1 + index)); } #endif { - size_t reduced_index = index - NTBINS; - size_t grp = reduced_index >> LG_SIZE_CLASS_GROUP; - size_t mod = reduced_index & ((ZU(1) << LG_SIZE_CLASS_GROUP) - + size_t reduced_index = index - SC_NTINY; + size_t grp = reduced_index >> SC_LG_NGROUP; + size_t mod = reduced_index & ((ZU(1) << SC_LG_NGROUP) - 1); size_t grp_size_mask = ~((!!grp)-1); size_t grp_size = ((ZU(1) << (LG_QUANTUM + - (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask; + (SC_LG_NGROUP-1))) << grp) & grp_size_mask; size_t shift = (grp == 0) ? 1 : grp; size_t lg_delta = shift + (LG_QUANTUM-1); @@ -205,18 +203,22 @@ sz_index2size_lookup(szind_t index) { JEMALLOC_ALWAYS_INLINE size_t sz_index2size(szind_t index) { - assert(index < NSIZES); + assert(index < SC_NSIZES); return sz_index2size_lookup(index); } JEMALLOC_ALWAYS_INLINE size_t sz_s2u_compute(size_t size) { - if (unlikely(size > LARGE_MAXCLASS)) { + if (unlikely(size > SC_LARGE_MAXCLASS)) { return 0; } -#if (NTBINS > 0) - if (size <= (ZU(1) << LG_TINY_MAXCLASS)) { - size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1; + + if (size == 0) { + size++; + } +#if (SC_NTINY > 0) + if (size <= (ZU(1) << SC_LG_TINY_MAXCLASS)) { + size_t lg_tmin = SC_LG_TINY_MAXCLASS - SC_NTINY + 1; size_t lg_ceil = lg_floor(pow2_ceil_zu(size)); return (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) : (ZU(1) << lg_ceil)); @@ -224,8 +226,8 @@ sz_s2u_compute(size_t size) { #endif { size_t x = lg_floor((size<<1)-1); - size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1) - ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1; + size_t lg_delta = (x < SC_LG_NGROUP + LG_QUANTUM + 1) + ? LG_QUANTUM : x - SC_LG_NGROUP - 1; size_t delta = ZU(1) << lg_delta; size_t delta_mask = delta - 1; size_t usize = (size + delta_mask) & ~delta_mask; @@ -247,8 +249,7 @@ sz_s2u_lookup(size_t size) { */ JEMALLOC_ALWAYS_INLINE size_t sz_s2u(size_t size) { - assert(size > 0); - if (likely(size <= LOOKUP_MAXCLASS)) { + if (likely(size <= SC_LOOKUP_MAXCLASS)) { return sz_s2u_lookup(size); } return sz_s2u_compute(size); @@ -265,7 +266,7 @@ sz_sa2u(size_t size, size_t alignment) { assert(alignment != 0 && ((alignment - 1) & alignment) == 0); /* Try for a small size class. */ - if (size <= SMALL_MAXCLASS && alignment < PAGE) { + if (size <= SC_SMALL_MAXCLASS && alignment < PAGE) { /* * Round size up to the nearest multiple of alignment. * @@ -281,20 +282,20 @@ sz_sa2u(size_t size, size_t alignment) { * 192 | 11000000 | 64 */ usize = sz_s2u(ALIGNMENT_CEILING(size, alignment)); - if (usize < LARGE_MINCLASS) { + if (usize < SC_LARGE_MINCLASS) { return usize; } } /* Large size class. Beware of overflow. */ - if (unlikely(alignment > LARGE_MAXCLASS)) { + if (unlikely(alignment > SC_LARGE_MAXCLASS)) { return 0; } /* Make sure result is a large size class. */ - if (size <= LARGE_MINCLASS) { - usize = LARGE_MINCLASS; + if (size <= SC_LARGE_MINCLASS) { + usize = SC_LARGE_MINCLASS; } else { usize = sz_s2u(size); if (usize < size) { diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_externs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_externs.h index db3e9c7d5d..d63eafde8c 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_externs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_externs.h @@ -1,15 +1,13 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_EXTERNS_H #define JEMALLOC_INTERNAL_TCACHE_EXTERNS_H -#include "jemalloc/internal/size_classes.h" - extern bool opt_tcache; extern ssize_t opt_lg_tcache_max; -extern tcache_bin_info_t *tcache_bin_info; +extern cache_bin_info_t *tcache_bin_info; /* - * Number of tcache bins. There are NBINS small-object bins, plus 0 or more + * Number of tcache bins. There are SC_NBINS small-object bins, plus 0 or more * large-object bins. */ extern unsigned nhbins; @@ -30,10 +28,10 @@ extern tcaches_t *tcaches; size_t tcache_salloc(tsdn_t *tsdn, const void *ptr); void tcache_event_hard(tsd_t *tsd, tcache_t *tcache); void *tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, - tcache_bin_t *tbin, szind_t binind, bool *tcache_success); -void tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, + cache_bin_t *tbin, szind_t binind, bool *tcache_success); +void tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, cache_bin_t *tbin, szind_t binind, unsigned rem); -void tcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind, +void tcache_bin_flush_large(tsd_t *tsd, cache_bin_t *tbin, szind_t binind, unsigned rem, tcache_t *tcache); void tcache_arena_reassociate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena); diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_inlines.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_inlines.h index c55bcd2723..5eca20e893 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_inlines.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_inlines.h @@ -1,8 +1,9 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_INLINES_H #define JEMALLOC_INTERNAL_TCACHE_INLINES_H +#include "jemalloc/internal/bin.h" #include "jemalloc/internal/jemalloc_internal_types.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/sz.h" #include "jemalloc/internal/ticker.h" #include "jemalloc/internal/util.h" @@ -38,43 +39,16 @@ tcache_event(tsd_t *tsd, tcache_t *tcache) { } JEMALLOC_ALWAYS_INLINE void * -tcache_alloc_easy(tcache_bin_t *tbin, bool *tcache_success) { +tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, + size_t size, szind_t binind, bool zero, bool slow_path) { void *ret; - - if (unlikely(tbin->ncached == 0)) { - tbin->low_water = -1; - *tcache_success = false; - return NULL; - } - /* - * tcache_success (instead of ret) should be checked upon the return of - * this function. We avoid checking (ret == NULL) because there is - * never a null stored on the avail stack (which is unknown to the - * compiler), and eagerly checking ret would cause pipeline stall - * (waiting for the cacheline). - */ - *tcache_success = true; - ret = *(tbin->avail - tbin->ncached); - tbin->ncached--; - - if (unlikely((low_water_t)tbin->ncached < tbin->low_water)) { - tbin->low_water = tbin->ncached; - } - - return ret; -} - -JEMALLOC_ALWAYS_INLINE void * -tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, - szind_t binind, bool zero, bool slow_path) { - void *ret; - tcache_bin_t *tbin; + cache_bin_t *bin; bool tcache_success; size_t usize JEMALLOC_CC_SILENCE_INIT(0); - assert(binind < NBINS); - tbin = tcache_small_bin_get(tcache, binind); - ret = tcache_alloc_easy(tbin, &tcache_success); + assert(binind < SC_NBINS); + bin = tcache_small_bin_get(tcache, binind); + ret = cache_bin_alloc_easy(bin, &tcache_success); assert(tcache_success == (ret != NULL)); if (unlikely(!tcache_success)) { bool tcache_hard_success; @@ -84,7 +58,7 @@ tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, } ret = tcache_alloc_small_hard(tsd_tsdn(tsd), arena, tcache, - tbin, binind, &tcache_hard_success); + bin, binind, &tcache_hard_success); if (tcache_hard_success == false) { return NULL; } @@ -103,22 +77,21 @@ tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, if (likely(!zero)) { if (slow_path && config_fill) { if (unlikely(opt_junk_alloc)) { - arena_alloc_junk_small(ret, - &arena_bin_info[binind], false); + arena_alloc_junk_small(ret, &bin_infos[binind], + false); } else if (unlikely(opt_zero)) { memset(ret, 0, usize); } } } else { if (slow_path && config_fill && unlikely(opt_junk_alloc)) { - arena_alloc_junk_small(ret, &arena_bin_info[binind], - true); + arena_alloc_junk_small(ret, &bin_infos[binind], true); } memset(ret, 0, usize); } if (config_stats) { - tbin->tstats.nrequests++; + bin->tstats.nrequests++; } if (config_prof) { tcache->prof_accumbytes += usize; @@ -131,12 +104,12 @@ JEMALLOC_ALWAYS_INLINE void * tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, szind_t binind, bool zero, bool slow_path) { void *ret; - tcache_bin_t *tbin; + cache_bin_t *bin; bool tcache_success; - assert(binind >= NBINS &&binind < nhbins); - tbin = tcache_large_bin_get(tcache, binind); - ret = tcache_alloc_easy(tbin, &tcache_success); + assert(binind >= SC_NBINS &&binind < nhbins); + bin = tcache_large_bin_get(tcache, binind); + ret = cache_bin_alloc_easy(bin, &tcache_success); assert(tcache_success == (ret != NULL)); if (unlikely(!tcache_success)) { /* @@ -176,7 +149,7 @@ tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, } if (config_stats) { - tbin->tstats.nrequests++; + bin->tstats.nrequests++; } if (config_prof) { tcache->prof_accumbytes += usize; @@ -190,24 +163,24 @@ tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, JEMALLOC_ALWAYS_INLINE void tcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind, bool slow_path) { - tcache_bin_t *tbin; - tcache_bin_info_t *tbin_info; + cache_bin_t *bin; + cache_bin_info_t *bin_info; - assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= SMALL_MAXCLASS); + assert(tcache_salloc(tsd_tsdn(tsd), ptr) + <= SC_SMALL_MAXCLASS); if (slow_path && config_fill && unlikely(opt_junk_free)) { - arena_dalloc_junk_small(ptr, &arena_bin_info[binind]); + arena_dalloc_junk_small(ptr, &bin_infos[binind]); } - tbin = tcache_small_bin_get(tcache, binind); - tbin_info = &tcache_bin_info[binind]; - if (unlikely(tbin->ncached == tbin_info->ncached_max)) { - tcache_bin_flush_small(tsd, tcache, tbin, binind, - (tbin_info->ncached_max >> 1)); + bin = tcache_small_bin_get(tcache, binind); + bin_info = &tcache_bin_info[binind]; + if (unlikely(!cache_bin_dalloc_easy(bin, bin_info, ptr))) { + tcache_bin_flush_small(tsd, tcache, bin, binind, + (bin_info->ncached_max >> 1)); + bool ret = cache_bin_dalloc_easy(bin, bin_info, ptr); + assert(ret); } - assert(tbin->ncached < tbin_info->ncached_max); - tbin->ncached++; - *(tbin->avail - tbin->ncached) = ptr; tcache_event(tsd, tcache); } @@ -215,25 +188,26 @@ tcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind, JEMALLOC_ALWAYS_INLINE void tcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind, bool slow_path) { - tcache_bin_t *tbin; - tcache_bin_info_t *tbin_info; + cache_bin_t *bin; + cache_bin_info_t *bin_info; - assert(tcache_salloc(tsd_tsdn(tsd), ptr) > SMALL_MAXCLASS); + assert(tcache_salloc(tsd_tsdn(tsd), ptr) + > SC_SMALL_MAXCLASS); assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= tcache_maxclass); if (slow_path && config_fill && unlikely(opt_junk_free)) { large_dalloc_junk(ptr, sz_index2size(binind)); } - tbin = tcache_large_bin_get(tcache, binind); - tbin_info = &tcache_bin_info[binind]; - if (unlikely(tbin->ncached == tbin_info->ncached_max)) { - tcache_bin_flush_large(tsd, tbin, binind, - (tbin_info->ncached_max >> 1), tcache); + bin = tcache_large_bin_get(tcache, binind); + bin_info = &tcache_bin_info[binind]; + if (unlikely(bin->ncached == bin_info->ncached_max)) { + tcache_bin_flush_large(tsd, bin, binind, + (bin_info->ncached_max >> 1), tcache); } - assert(tbin->ncached < tbin_info->ncached_max); - tbin->ncached++; - *(tbin->avail - tbin->ncached) = ptr; + assert(bin->ncached < bin_info->ncached_max); + bin->ncached++; + *(bin->avail - bin->ncached) = ptr; tcache_event(tsd, tcache); } @@ -242,6 +216,9 @@ JEMALLOC_ALWAYS_INLINE tcache_t * tcaches_get(tsd_t *tsd, unsigned ind) { tcaches_t *elm = &tcaches[ind]; if (unlikely(elm->tcache == NULL)) { + malloc_printf(": invalid tcache id (%u).\n", ind); + abort(); + } else if (unlikely(elm->tcache == TCACHES_ELM_NEED_REINIT)) { elm->tcache = tcache_create_explicit(tsd); } return elm->tcache; diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_structs.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_structs.h index 7eb516fb6b..172ef9040c 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_structs.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_structs.h @@ -1,56 +1,62 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_STRUCTS_H #define JEMALLOC_INTERNAL_TCACHE_STRUCTS_H +#include "jemalloc/internal/cache_bin.h" #include "jemalloc/internal/ql.h" -#include "jemalloc/internal/size_classes.h" -#include "jemalloc/internal/stats_tsd.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/ticker.h" +#include "jemalloc/internal/tsd_types.h" -/* - * Read-only information associated with each element of tcache_t's tbins array - * is stored separately, mainly to reduce memory usage. - */ -struct tcache_bin_info_s { - unsigned ncached_max; /* Upper limit on ncached. */ -}; +/* Various uses of this struct need it to be a named type. */ +typedef ql_elm(tsd_t) tsd_link_t; -struct tcache_bin_s { - low_water_t low_water; /* Min # cached since last GC. */ - uint32_t ncached; /* # of cached objects. */ +struct tcache_s { /* - * ncached and stats are both modified frequently. Let's keep them - * close so that they have a higher chance of being on the same - * cacheline, thus less write-backs. + * To minimize our cache-footprint, we put the frequently accessed data + * together at the start of this struct. */ - tcache_bin_stats_t tstats; + + /* Cleared after arena_prof_accum(). */ + uint64_t prof_accumbytes; + /* Drives incremental GC. */ + ticker_t gc_ticker; /* - * To make use of adjacent cacheline prefetch, the items in the avail - * stack goes to higher address for newer allocations. avail points - * just above the available space, which means that - * avail[-ncached, ... -1] are available items and the lowest item will - * be allocated first. + * The pointer stacks associated with bins follow as a contiguous array. + * During tcache initialization, the avail pointer in each element of + * tbins is initialized to point to the proper offset within this array. */ - void **avail; /* Stack of available objects. */ -}; + cache_bin_t bins_small[SC_NBINS]; + + /* + * This data is less hot; we can be a little less careful with our + * footprint here. + */ + /* Lets us track all the tcaches in an arena. */ + ql_elm(tcache_t) link; + + /* Logically scoped to tsd, but put here for cache layout reasons. */ + ql_elm(tsd_t) tsd_link; + bool in_hook; -struct tcache_s { - /* Data accessed frequently first: prof, ticker and small bins. */ - uint64_t prof_accumbytes;/* Cleared after arena_prof_accum(). */ - ticker_t gc_ticker; /* Drives incremental GC. */ /* - * The pointer stacks associated with tbins follow as a contiguous - * array. During tcache initialization, the avail pointer in each - * element of tbins is initialized to point to the proper offset within - * this array. + * The descriptor lets the arena find our cache bins without seeing the + * tcache definition. This enables arenas to aggregate stats across + * tcaches without having a tcache dependency. */ - tcache_bin_t tbins_small[NBINS]; - /* Data accessed less often below. */ - ql_elm(tcache_t) link; /* Used for aggregating stats. */ - arena_t *arena; /* Associated arena. */ - szind_t next_gc_bin; /* Next bin to GC. */ + cache_bin_array_descriptor_t cache_bin_array_descriptor; + + /* The arena this tcache is associated with. */ + arena_t *arena; + /* Next bin to GC. */ + szind_t next_gc_bin; /* For small bins, fill (ncached_max >> lg_fill_div). */ - uint8_t lg_fill_div[NBINS]; - tcache_bin_t tbins_large[NSIZES-NBINS]; + uint8_t lg_fill_div[SC_NBINS]; + /* + * We put the cache bins for large size classes at the end of the + * struct, since some of them might not get used. This might end up + * letting us avoid touching an extra page if we don't have to. + */ + cache_bin_t bins_large[SC_NSIZES-SC_NBINS]; }; /* Linkage for list of available (previously used) explicit tcache IDs. */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_types.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_types.h index 1155d62cb4..dce69382eb 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_types.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tcache_types.h @@ -1,16 +1,11 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_TYPES_H #define JEMALLOC_INTERNAL_TCACHE_TYPES_H -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" -typedef struct tcache_bin_info_s tcache_bin_info_t; -typedef struct tcache_bin_s tcache_bin_t; typedef struct tcache_s tcache_t; typedef struct tcaches_s tcaches_t; -/* ncached is cast to this type for comparison. */ -typedef int32_t low_water_t; - /* * tcache pointers close to NULL are used to encode state information that is * used for two purposes: preventing thread caching on a per thread basis and @@ -50,7 +45,7 @@ typedef int32_t low_water_t; /* Number of tcache allocation/deallocation events between incremental GCs. */ #define TCACHE_GC_INCR \ - ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1)) + ((TCACHE_GC_SWEEP / SC_NBINS) + ((TCACHE_GC_SWEEP / SC_NBINS == 0) ? 0 : 1)) /* Used in TSD static initializer only. Real init in tcache_data_init(). */ #define TCACHE_ZERO_INITIALIZER {0} @@ -58,4 +53,7 @@ typedef int32_t low_water_t; /* Used in TSD static initializer only. Will be initialized to opt_tcache. */ #define TCACHE_ENABLED_ZERO_INITIALIZER false +/* Used for explicit tcache only. Means flushed but not destroyed. */ +#define TCACHES_ELM_NEED_REINIT ((tcache_t *)(uintptr_t)1) + #endif /* JEMALLOC_INTERNAL_TCACHE_TYPES_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/test_hooks.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/test_hooks.h new file mode 100644 index 0000000000..a6351e59af --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/test_hooks.h @@ -0,0 +1,19 @@ +#ifndef JEMALLOC_INTERNAL_TEST_HOOKS_H +#define JEMALLOC_INTERNAL_TEST_HOOKS_H + +extern JEMALLOC_EXPORT void (*test_hooks_arena_new_hook)(); +extern JEMALLOC_EXPORT void (*test_hooks_libc_hook)(); + +#define JEMALLOC_HOOK(fn, hook) ((void)(hook != NULL && (hook(), 0)), fn) + +#define open JEMALLOC_HOOK(open, test_hooks_libc_hook) +#define read JEMALLOC_HOOK(read, test_hooks_libc_hook) +#define write JEMALLOC_HOOK(write, test_hooks_libc_hook) +#define readlink JEMALLOC_HOOK(readlink, test_hooks_libc_hook) +#define close JEMALLOC_HOOK(close, test_hooks_libc_hook) +#define creat JEMALLOC_HOOK(creat, test_hooks_libc_hook) +#define secure_getenv JEMALLOC_HOOK(secure_getenv, test_hooks_libc_hook) +/* Note that this is undef'd and re-define'd in src/prof.c. */ +#define _Unwind_Backtrace JEMALLOC_HOOK(_Unwind_Backtrace, test_hooks_libc_hook) + +#endif /* JEMALLOC_INTERNAL_TEST_HOOKS_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ticker.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ticker.h index 572b96459c..52d0db4c89 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ticker.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/ticker.h @@ -32,14 +32,42 @@ ticker_read(const ticker_t *ticker) { return ticker->tick; } +/* + * Not intended to be a public API. Unfortunately, on x86, neither gcc nor + * clang seems smart enough to turn + * ticker->tick -= nticks; + * if (unlikely(ticker->tick < 0)) { + * fixup ticker + * return true; + * } + * return false; + * into + * subq %nticks_reg, (%ticker_reg) + * js fixup ticker + * + * unless we force "fixup ticker" out of line. In that case, gcc gets it right, + * but clang now does worse than before. So, on x86 with gcc, we force it out + * of line, but otherwise let the inlining occur. Ordinarily this wouldn't be + * worth the hassle, but this is on the fast path of both malloc and free (via + * tcache_event). + */ +#if defined(__GNUC__) && !defined(__clang__) \ + && (defined(__x86_64__) || defined(__i386__)) +JEMALLOC_NOINLINE +#endif +static bool +ticker_fixup(ticker_t *ticker) { + ticker->tick = ticker->nticks; + return true; +} + static inline bool ticker_ticks(ticker_t *ticker, int32_t nticks) { - if (unlikely(ticker->tick < nticks)) { - ticker->tick = ticker->nticks; - return true; - } ticker->tick -= nticks; - return(false); + if (unlikely(ticker->tick < 0)) { + return ticker_fixup(ticker); + } + return false; } static inline bool @@ -47,4 +75,17 @@ ticker_tick(ticker_t *ticker) { return ticker_ticks(ticker, 1); } +/* + * Try to tick. If ticker would fire, return true, but rely on + * slowpath to reset ticker. + */ +static inline bool +ticker_trytick(ticker_t *ticker) { + --ticker->tick; + if (unlikely(ticker->tick < 0)) { + return true; + } + return false; +} + #endif /* JEMALLOC_INTERNAL_TICKER_H */ diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd.h index 155a2ec6c4..9ba2600453 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd.h @@ -3,6 +3,7 @@ #include "jemalloc/internal/arena_types.h" #include "jemalloc/internal/assert.h" +#include "jemalloc/internal/bin_types.h" #include "jemalloc/internal/jemalloc_internal_externs.h" #include "jemalloc/internal/prof_types.h" #include "jemalloc/internal/ql.h" @@ -65,48 +66,120 @@ typedef void (*test_callback_t)(int *); O(arenas_tdata_bypass, bool, bool) \ O(reentrancy_level, int8_t, int8_t) \ O(narenas_tdata, uint32_t, uint32_t) \ + O(offset_state, uint64_t, uint64_t) \ O(thread_allocated, uint64_t, uint64_t) \ O(thread_deallocated, uint64_t, uint64_t) \ + O(bytes_until_sample, int64_t, int64_t) \ O(prof_tdata, prof_tdata_t *, prof_tdata_t *) \ O(rtree_ctx, rtree_ctx_t, rtree_ctx_t) \ O(iarena, arena_t *, arena_t *) \ O(arena, arena_t *, arena_t *) \ O(arenas_tdata, arena_tdata_t *, arena_tdata_t *)\ + O(binshards, tsd_binshards_t, tsd_binshards_t)\ O(tcache, tcache_t, tcache_t) \ O(witness_tsd, witness_tsd_t, witness_tsdn_t) \ MALLOC_TEST_TSD #define TSD_INITIALIZER { \ - tsd_state_uninitialized, \ + ATOMIC_INIT(tsd_state_uninitialized), \ TCACHE_ENABLED_ZERO_INITIALIZER, \ false, \ 0, \ 0, \ 0, \ 0, \ + 0, \ + 0, \ NULL, \ RTREE_CTX_ZERO_INITIALIZER, \ NULL, \ NULL, \ NULL, \ + TSD_BINSHARDS_ZERO_INITIALIZER, \ TCACHE_ZERO_INITIALIZER, \ WITNESS_TSD_INITIALIZER \ MALLOC_TEST_TSD_INITIALIZER \ } +void *malloc_tsd_malloc(size_t size); +void malloc_tsd_dalloc(void *wrapper); +void malloc_tsd_cleanup_register(bool (*f)(void)); +tsd_t *malloc_tsd_boot0(void); +void malloc_tsd_boot1(void); +void tsd_cleanup(void *arg); +tsd_t *tsd_fetch_slow(tsd_t *tsd, bool internal); +void tsd_state_set(tsd_t *tsd, uint8_t new_state); +void tsd_slow_update(tsd_t *tsd); +void tsd_prefork(tsd_t *tsd); +void tsd_postfork_parent(tsd_t *tsd); +void tsd_postfork_child(tsd_t *tsd); + +/* + * Call ..._inc when your module wants to take all threads down the slow paths, + * and ..._dec when it no longer needs to. + */ +void tsd_global_slow_inc(tsdn_t *tsdn); +void tsd_global_slow_dec(tsdn_t *tsdn); +bool tsd_global_slow(); + enum { - tsd_state_nominal = 0, /* Common case --> jnz. */ - tsd_state_nominal_slow = 1, /* Initialized but on slow path. */ - /* the above 2 nominal states should be lower values. */ - tsd_state_nominal_max = 1, /* used for comparison only. */ - tsd_state_minimal_initialized = 2, - tsd_state_purgatory = 3, - tsd_state_reincarnated = 4, - tsd_state_uninitialized = 5 + /* Common case --> jnz. */ + tsd_state_nominal = 0, + /* Initialized but on slow path. */ + tsd_state_nominal_slow = 1, + /* + * Some thread has changed global state in such a way that all nominal + * threads need to recompute their fast / slow status the next time they + * get a chance. + * + * Any thread can change another thread's status *to* recompute, but + * threads are the only ones who can change their status *from* + * recompute. + */ + tsd_state_nominal_recompute = 2, + /* + * The above nominal states should be lower values. We use + * tsd_nominal_max to separate nominal states from threads in the + * process of being born / dying. + */ + tsd_state_nominal_max = 2, + + /* + * A thread might free() during its death as its only allocator action; + * in such scenarios, we need tsd, but set up in such a way that no + * cleanup is necessary. + */ + tsd_state_minimal_initialized = 3, + /* States during which we know we're in thread death. */ + tsd_state_purgatory = 4, + tsd_state_reincarnated = 5, + /* + * What it says on the tin; tsd that hasn't been initialized. Note + * that even when the tsd struct lives in TLS, when need to keep track + * of stuff like whether or not our pthread destructors have been + * scheduled, so this really truly is different than the nominal state. + */ + tsd_state_uninitialized = 6 }; -/* Manually limit tsd_state_t to a single byte. */ -typedef uint8_t tsd_state_t; +/* + * Some TSD accesses can only be done in a nominal state. To enforce this, we + * wrap TSD member access in a function that asserts on TSD state, and mangle + * field names to prevent touching them accidentally. + */ +#define TSD_MANGLE(n) cant_access_tsd_items_directly_use_a_getter_or_setter_##n + +#ifdef JEMALLOC_U8_ATOMICS +# define tsd_state_t atomic_u8_t +# define tsd_atomic_load atomic_load_u8 +# define tsd_atomic_store atomic_store_u8 +# define tsd_atomic_exchange atomic_exchange_u8 +#else +# define tsd_state_t atomic_u32_t +# define tsd_atomic_load atomic_load_u32 +# define tsd_atomic_store atomic_store_u32 +# define tsd_atomic_exchange atomic_exchange_u32 +#endif /* The actual tsd. */ struct tsd_s { @@ -115,13 +188,29 @@ struct tsd_s { * module. Access any thread-local state through the getters and * setters below. */ - tsd_state_t state; + + /* + * We manually limit the state to just a single byte. Unless the 8-bit + * atomics are unavailable (which is rare). + */ + tsd_state_t state; #define O(n, t, nt) \ - t use_a_getter_or_setter_instead_##n; + t TSD_MANGLE(n); MALLOC_TSD #undef O }; +JEMALLOC_ALWAYS_INLINE uint8_t +tsd_state_get(tsd_t *tsd) { + /* + * This should be atomic. Unfortunately, compilers right now can't tell + * that this can be done as a memory comparison, and forces a load into + * a register that hurts fast-path performance. + */ + /* return atomic_load_u8(&tsd->state, ATOMIC_RELAXED); */ + return *(uint8_t *)&tsd->state; +} + /* * Wrapper around tsd_t that makes it possible to avoid implicit conversion * between tsd_t and tsdn_t, where tsdn_t is "nullable" and has to be @@ -148,15 +237,6 @@ tsdn_tsd(tsdn_t *tsdn) { return &tsdn->tsd; } -void *malloc_tsd_malloc(size_t size); -void malloc_tsd_dalloc(void *wrapper); -void malloc_tsd_cleanup_register(bool (*f)(void)); -tsd_t *malloc_tsd_boot0(void); -void malloc_tsd_boot1(void); -void tsd_cleanup(void *arg); -tsd_t *tsd_fetch_slow(tsd_t *tsd, bool internal); -void tsd_slow_update(tsd_t *tsd); - /* * We put the platform-specific data declarations and inlines into their own * header files to avoid cluttering this file. They define tsd_boot0, @@ -180,7 +260,7 @@ void tsd_slow_update(tsd_t *tsd); #define O(n, t, nt) \ JEMALLOC_ALWAYS_INLINE t * \ tsd_##n##p_get_unsafe(tsd_t *tsd) { \ - return &tsd->use_a_getter_or_setter_instead_##n; \ + return &tsd->TSD_MANGLE(n); \ } MALLOC_TSD #undef O @@ -189,10 +269,16 @@ MALLOC_TSD #define O(n, t, nt) \ JEMALLOC_ALWAYS_INLINE t * \ tsd_##n##p_get(tsd_t *tsd) { \ - assert(tsd->state == tsd_state_nominal || \ - tsd->state == tsd_state_nominal_slow || \ - tsd->state == tsd_state_reincarnated || \ - tsd->state == tsd_state_minimal_initialized); \ + /* \ + * Because the state might change asynchronously if it's \ + * nominal, we need to make sure that we only read it once. \ + */ \ + uint8_t state = tsd_state_get(tsd); \ + assert(state == tsd_state_nominal || \ + state == tsd_state_nominal_slow || \ + state == tsd_state_nominal_recompute || \ + state == tsd_state_reincarnated || \ + state == tsd_state_minimal_initialized); \ return tsd_##n##p_get_unsafe(tsd); \ } MALLOC_TSD @@ -227,8 +313,8 @@ MALLOC_TSD #define O(n, t, nt) \ JEMALLOC_ALWAYS_INLINE void \ tsd_##n##_set(tsd_t *tsd, t val) { \ - assert(tsd->state != tsd_state_reincarnated && \ - tsd->state != tsd_state_minimal_initialized); \ + assert(tsd_state_get(tsd) != tsd_state_reincarnated && \ + tsd_state_get(tsd) != tsd_state_minimal_initialized); \ *tsd_##n##p_get(tsd) = val; \ } MALLOC_TSD @@ -236,13 +322,18 @@ MALLOC_TSD JEMALLOC_ALWAYS_INLINE void tsd_assert_fast(tsd_t *tsd) { + /* + * Note that our fastness assertion does *not* include global slowness + * counters; it's not in general possible to ensure that they won't + * change asynchronously from underneath us. + */ assert(!malloc_slow && tsd_tcache_enabled_get(tsd) && tsd_reentrancy_level_get(tsd) == 0); } JEMALLOC_ALWAYS_INLINE bool tsd_fast(tsd_t *tsd) { - bool fast = (tsd->state == tsd_state_nominal); + bool fast = (tsd_state_get(tsd) == tsd_state_nominal); if (fast) { tsd_assert_fast(tsd); } @@ -259,7 +350,7 @@ tsd_fetch_impl(bool init, bool minimal) { } assert(tsd != NULL); - if (unlikely(tsd->state != tsd_state_nominal)) { + if (unlikely(tsd_state_get(tsd) != tsd_state_nominal)) { return tsd_fetch_slow(tsd, minimal); } assert(tsd_fast(tsd)); @@ -279,7 +370,7 @@ JEMALLOC_ALWAYS_INLINE tsd_t * tsd_internal_fetch(void) { tsd_t *tsd = tsd_fetch_min(); /* Use reincarnated state to prevent full initialization. */ - tsd->state = tsd_state_reincarnated; + tsd_state_set(tsd, tsd_state_reincarnated); return tsd; } @@ -291,7 +382,7 @@ tsd_fetch(void) { static inline bool tsd_nominal(tsd_t *tsd) { - return (tsd->state <= tsd_state_nominal_max); + return (tsd_state_get(tsd) <= tsd_state_nominal_max); } JEMALLOC_ALWAYS_INLINE tsdn_t * diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_generic.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_generic.h index 1e52ef767f..cf73c0c715 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_generic.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_generic.h @@ -77,7 +77,10 @@ tsd_wrapper_get(bool init) { abort(); } else { wrapper->initialized = false; + JEMALLOC_DIAGNOSTIC_PUSH + JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS tsd_t initializer = TSD_INITIALIZER; + JEMALLOC_DIAGNOSTIC_POP wrapper->val = initializer; } tsd_wrapper_set(wrapper); @@ -107,7 +110,10 @@ tsd_boot1(void) { tsd_boot_wrapper.initialized = false; tsd_cleanup(&tsd_boot_wrapper.val); wrapper->initialized = false; + JEMALLOC_DIAGNOSTIC_PUSH + JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS tsd_t initializer = TSD_INITIALIZER; + JEMALLOC_DIAGNOSTIC_POP wrapper->val = initializer; tsd_wrapper_set(wrapper); } diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h index beb467a67e..bf8801effe 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h @@ -47,7 +47,6 @@ tsd_get_allocates(void) { /* Get/set. */ JEMALLOC_ALWAYS_INLINE tsd_t * tsd_get(bool init) { - assert(tsd_booted); return &tsd_tls; } JEMALLOC_ALWAYS_INLINE void diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_tls.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_tls.h index 757aaa0eef..f4f165c7f5 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_tls.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/tsd_tls.h @@ -40,7 +40,6 @@ tsd_get_allocates(void) { /* Get/set. */ JEMALLOC_ALWAYS_INLINE tsd_t * tsd_get(bool init) { - assert(tsd_booted); return &tsd_tls; } diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/witness.h b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/witness.h index 33be666107..fff9e98cb6 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/witness.h +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/internal/witness.h @@ -27,9 +27,9 @@ #define WITNESS_RANK_PROF_BT2GCTX 6U #define WITNESS_RANK_PROF_TDATAS 7U #define WITNESS_RANK_PROF_TDATA 8U -#define WITNESS_RANK_PROF_GCTX 9U - -#define WITNESS_RANK_BACKGROUND_THREAD 10U +#define WITNESS_RANK_PROF_LOG 9U +#define WITNESS_RANK_PROF_GCTX 10U +#define WITNESS_RANK_BACKGROUND_THREAD 11U /* * Used as an argument to witness_assert_depth_to_rank() in order to validate @@ -37,21 +37,22 @@ * witness_assert_depth_to_rank() is inclusive rather than exclusive, this * definition can have the same value as the minimally ranked core lock. */ -#define WITNESS_RANK_CORE 11U +#define WITNESS_RANK_CORE 12U -#define WITNESS_RANK_DECAY 11U -#define WITNESS_RANK_TCACHE_QL 12U -#define WITNESS_RANK_EXTENT_GROW 13U -#define WITNESS_RANK_EXTENTS 14U -#define WITNESS_RANK_EXTENT_AVAIL 15U +#define WITNESS_RANK_DECAY 12U +#define WITNESS_RANK_TCACHE_QL 13U +#define WITNESS_RANK_EXTENT_GROW 14U +#define WITNESS_RANK_EXTENTS 15U +#define WITNESS_RANK_EXTENT_AVAIL 16U -#define WITNESS_RANK_EXTENT_POOL 16U -#define WITNESS_RANK_RTREE 17U -#define WITNESS_RANK_BASE 18U -#define WITNESS_RANK_ARENA_LARGE 19U +#define WITNESS_RANK_EXTENT_POOL 17U +#define WITNESS_RANK_RTREE 18U +#define WITNESS_RANK_BASE 19U +#define WITNESS_RANK_ARENA_LARGE 20U +#define WITNESS_RANK_HOOK 21U #define WITNESS_RANK_LEAF 0xffffffffU -#define WITNESS_RANK_ARENA_BIN WITNESS_RANK_LEAF +#define WITNESS_RANK_BIN WITNESS_RANK_LEAF #define WITNESS_RANK_ARENA_STATS WITNESS_RANK_LEAF #define WITNESS_RANK_DSS WITNESS_RANK_LEAF #define WITNESS_RANK_PROF_ACTIVE WITNESS_RANK_LEAF diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_macros.h.in b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_macros.h.in index aee55438c9..a00ce11a79 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_macros.h.in +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_macros.h.in @@ -10,6 +10,7 @@ #define JEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@ #define JEMALLOC_VERSION_NREV @jemalloc_version_nrev@ #define JEMALLOC_VERSION_GID "@jemalloc_version_gid@" +#define JEMALLOC_VERSION_GID_IDENT @jemalloc_version_gid@ #define MALLOCX_LG_ALIGN(la) ((int)(la)) #if LG_SIZEOF_PTR == 2 diff --git a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_mangle.sh b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_mangle.sh index df328b78da..c675bb469f 100755 --- a/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_mangle.sh +++ b/kbe/src/lib/dependencies/jemalloc/include/jemalloc/jemalloc_mangle.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -eu public_symbols_txt=$1 symbol_prefix=$2 diff --git a/kbe/src/lib/dependencies/jemalloc/jemalloc.pc.in b/kbe/src/lib/dependencies/jemalloc/jemalloc.pc.in index a318e8dd3f..c428a86dc3 100755 --- a/kbe/src/lib/dependencies/jemalloc/jemalloc.pc.in +++ b/kbe/src/lib/dependencies/jemalloc/jemalloc.pc.in @@ -7,6 +7,6 @@ install_suffix=@install_suffix@ Name: jemalloc Description: A general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support. URL: http://jemalloc.net/ -Version: @jemalloc_version@ +Version: @jemalloc_version_major@.@jemalloc_version_minor@.@jemalloc_version_bugfix@_@jemalloc_version_nrev@ Cflags: -I${includedir} Libs: -L${libdir} -ljemalloc${install_suffix} diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/ReadMe.txt b/kbe/src/lib/dependencies/jemalloc/msvc/ReadMe.txt index 77d567da0f..633a7d49f4 100755 --- a/kbe/src/lib/dependencies/jemalloc/msvc/ReadMe.txt +++ b/kbe/src/lib/dependencies/jemalloc/msvc/ReadMe.txt @@ -9,16 +9,15 @@ How to build jemalloc for Windows * grep * sed -2. Install Visual Studio 2015 with Visual C++ +2. Install Visual Studio 2015 or 2017 with Visual C++ 3. Add Cygwin\bin to the PATH environment variable -4. Open "VS2015 x86 Native Tools Command Prompt" +4. Open "x64 Native Tools Command Prompt for VS 2017" (note: x86/x64 doesn't matter at this point) 5. Generate header files: sh -c "CC=cl ./autogen.sh" 6. Now the project can be opened and built in Visual Studio: - msvc\jemalloc_vc2015.sln - + msvc\jemalloc_vc2017.sln diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/jemalloc_vc2017.sln b/kbe/src/lib/dependencies/jemalloc/msvc/jemalloc_vc2017.sln new file mode 100644 index 0000000000..c22fcb437b --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/msvc/jemalloc_vc2017.sln @@ -0,0 +1,63 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{70A99006-6DE9-472B-8F83-4CEE6C616DF3}" + ProjectSection(SolutionItems) = preProject + ReadMe.txt = ReadMe.txt + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jemalloc", "projects\vc2017\jemalloc\jemalloc.vcxproj", "{8D6BB292-9E1C-413D-9F98-4864BDC1514A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_threads", "projects\vc2017\test_threads\test_threads.vcxproj", "{09028CFD-4EB7-491D-869C-0708DB97ED44}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Debug-static|x64 = Debug-static|x64 + Debug-static|x86 = Debug-static|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + Release-static|x64 = Release-static|x64 + Release-static|x86 = Release-static|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x64.ActiveCfg = Debug|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x64.Build.0 = Debug|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x86.ActiveCfg = Debug|Win32 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x86.Build.0 = Debug|Win32 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x64.ActiveCfg = Debug-static|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x64.Build.0 = Debug-static|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x86.ActiveCfg = Debug-static|Win32 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x86.Build.0 = Debug-static|Win32 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x64.ActiveCfg = Release|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x64.Build.0 = Release|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x86.ActiveCfg = Release|Win32 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x86.Build.0 = Release|Win32 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x64.ActiveCfg = Release-static|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x64.Build.0 = Release-static|x64 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x86.ActiveCfg = Release-static|Win32 + {8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x86.Build.0 = Release-static|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x64.ActiveCfg = Debug|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x64.Build.0 = Debug|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x86.ActiveCfg = Debug|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x86.Build.0 = Debug|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x64.ActiveCfg = Debug-static|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x64.Build.0 = Debug-static|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x86.ActiveCfg = Debug-static|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x86.Build.0 = Debug-static|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x64.ActiveCfg = Release|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x64.Build.0 = Release|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x86.ActiveCfg = Release|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x86.Build.0 = Release|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x64.ActiveCfg = Release-static|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x64.Build.0 = Release-static|x64 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x86.ActiveCfg = Release-static|Win32 + {09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x86.Build.0 = Release-static|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj index 2addd295d7..ddc6781ca8 100755 --- a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj @@ -38,16 +38,19 @@ + + - + + @@ -56,7 +59,7 @@ - + @@ -197,7 +200,7 @@ Level3 Disabled - _REENTRANT;_WINDLL;DLLEXPORT;JEMALLOC_DEBUG;_DEBUG;%(PreprocessorDefinitions) + JEMALLOC_NO_PRIVATE_NAMESPACE;_REENTRANT;_WINDLL;DLLEXPORT;JEMALLOC_DEBUG;_DEBUG;%(PreprocessorDefinitions) ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) 4090;4146;4267;4334 $(OutputPath)$(TargetName).pdb @@ -213,7 +216,7 @@ Level3 Disabled - JEMALLOC_DEBUG;_REENTRANT;JEMALLOC_EXPORT=;_DEBUG;_LIB;%(PreprocessorDefinitions) + JEMALLOC_NO_PRIVATE_NAMESPACE;JEMALLOC_DEBUG;_REENTRANT;JEMALLOC_EXPORT=;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) MultiThreadedDebug 4090;4146;4267;4334 @@ -266,7 +269,7 @@ MaxSpeed true true - _REENTRANT;_WINDLL;DLLEXPORT;NDEBUG;%(PreprocessorDefinitions) + JEMALLOC_NO_PRIVATE_NAMESPACE;_REENTRANT;_WINDLL;DLLEXPORT;NDEBUG;%(PreprocessorDefinitions) ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) 4090;4146;4267;4334 $(OutputPath)$(TargetName).pdb @@ -286,7 +289,7 @@ MaxSpeed true true - _REENTRANT;JEMALLOC_EXPORT=;NDEBUG;_LIB;%(PreprocessorDefinitions) + JEMALLOC_NO_PRIVATE_NAMESPACE;_REENTRANT;JEMALLOC_EXPORT=;NDEBUG;_LIB;%(PreprocessorDefinitions) ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) MultiThreaded 4090;4146;4267;4334 diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters index 4edf09b449..1dcf4ed542 100755 --- a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters @@ -37,7 +37,7 @@ Source Files - + Source Files @@ -70,7 +70,7 @@ Source Files - + Source Files @@ -91,5 +91,14 @@ Source Files + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj index f5e9898f29..325876d6e8 100755 --- a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj @@ -310,8 +310,8 @@ - - + + @@ -319,7 +319,7 @@ - + diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj.filters b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj.filters index 4c23340738..fa4588fd87 100755 --- a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj.filters +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj.filters @@ -11,15 +11,15 @@ - + Source Files - + Source Files - + Header Files diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj new file mode 100644 index 0000000000..21481d5ee3 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj @@ -0,0 +1,349 @@ + + + + + Debug-static + Win32 + + + Debug-static + x64 + + + Debug + Win32 + + + Release-static + Win32 + + + Release-static + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {8D6BB292-9E1C-413D-9F98-4864BDC1514A} + Win32Proj + jemalloc + + + + DynamicLibrary + true + v141 + MultiByte + + + StaticLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + DynamicLibrary + true + v141 + MultiByte + + + StaticLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(ProjectName)d + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(ProjectName)-$(PlatformToolset)-$(Configuration) + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(ProjectName)-$(PlatformToolset)-$(Configuration) + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(ProjectName)d + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(ProjectName)-vc$(PlatformToolsetVersion)-$(Configuration) + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(ProjectName)-vc$(PlatformToolsetVersion)-$(Configuration) + + + + + + Level3 + Disabled + _REENTRANT;_WINDLL;DLLEXPORT;JEMALLOC_DEBUG;_DEBUG;%(PreprocessorDefinitions) + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + 4090;4146;4267;4334 + $(OutputPath)$(TargetName).pdb + + + Windows + true + + + + + + + Level3 + Disabled + JEMALLOC_DEBUG;_REENTRANT;JEMALLOC_EXPORT=;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreadedDebug + 4090;4146;4267;4334 + $(OutputPath)$(TargetName).pdb + + + Windows + true + + + + + + + Level3 + Disabled + JEMALLOC_NO_PRIVATE_NAMESPACE;_REENTRANT;_WINDLL;DLLEXPORT;JEMALLOC_DEBUG;_DEBUG;%(PreprocessorDefinitions) + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + 4090;4146;4267;4334 + $(OutputPath)$(TargetName).pdb + + + Windows + true + + + + + + + Level3 + Disabled + JEMALLOC_NO_PRIVATE_NAMESPACE;JEMALLOC_DEBUG;_REENTRANT;JEMALLOC_EXPORT=;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreadedDebug + 4090;4146;4267;4334 + OldStyle + false + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + _REENTRANT;_WINDLL;DLLEXPORT;NDEBUG;%(PreprocessorDefinitions) + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + 4090;4146;4267;4334 + $(OutputPath)$(TargetName).pdb + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _REENTRANT;JEMALLOC_EXPORT=;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreaded + 4090;4146;4267;4334 + $(OutputPath)$(TargetName).pdb + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + JEMALLOC_NO_PRIVATE_NAMESPACE;_REENTRANT;_WINDLL;DLLEXPORT;NDEBUG;%(PreprocessorDefinitions) + 4090;4146;4267;4334 + $(OutputPath)$(TargetName).pdb + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + JEMALLOC_NO_PRIVATE_NAMESPACE;_REENTRANT;JEMALLOC_EXPORT=;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreaded + 4090;4146;4267;4334 + OldStyle + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters new file mode 100644 index 0000000000..466dc63fa3 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters @@ -0,0 +1,107 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj new file mode 100644 index 0000000000..c35b0f5aab --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj @@ -0,0 +1,326 @@ + + + + + Debug-static + Win32 + + + Debug-static + x64 + + + Debug + Win32 + + + Release-static + Win32 + + + Release-static + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {09028CFD-4EB7-491D-869C-0708DB97ED44} + Win32Proj + test_threads + + + + Application + true + v141 + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)$(Platform)\$(Configuration) + jemallocd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + JEMALLOC_EXPORT=;JEMALLOC_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreadedDebug + + + Console + true + $(SolutionDir)$(Platform)\$(Configuration) + jemalloc-$(PlatformToolset)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + + + Console + true + jemallocd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)$(Platform)\$(Configuration) + + + + + + + Level3 + Disabled + JEMALLOC_EXPORT=;JEMALLOC_STATIC;_DEBUG;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreadedDebug + + + Console + true + jemalloc-vc$(PlatformToolsetVersion)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)$(Platform)\$(Configuration) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + + + Console + true + true + true + $(SolutionDir)$(Platform)\$(Configuration) + jemalloc.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + JEMALLOC_EXPORT=;JEMALLOC_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreaded + + + Console + true + true + true + $(SolutionDir)$(Platform)\$(Configuration) + jemalloc-$(PlatformToolset)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + + + Console + true + true + true + $(SolutionDir)$(Platform)\$(Configuration) + jemalloc.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + JEMALLOC_EXPORT=;JEMALLOC_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\..\test\include;..\..\..\..\include;..\..\..\..\include\msvc_compat;%(AdditionalIncludeDirectories) + MultiThreaded + + + Console + true + true + true + $(SolutionDir)$(Platform)\$(Configuration) + jemalloc-vc$(PlatformToolsetVersion)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + {8d6bb292-9e1c-413d-9f98-4864bdc1514a} + + + + + + + + + \ No newline at end of file diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj.filters b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj.filters new file mode 100644 index 0000000000..fa4588fd87 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2017/test_threads/test_threads.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.cpp b/kbe/src/lib/dependencies/jemalloc/msvc/test_threads/test_threads.cpp old mode 100755 new mode 100644 similarity index 100% rename from kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.cpp rename to kbe/src/lib/dependencies/jemalloc/msvc/test_threads/test_threads.cpp diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.h b/kbe/src/lib/dependencies/jemalloc/msvc/test_threads/test_threads.h old mode 100755 new mode 100644 similarity index 100% rename from kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads.h rename to kbe/src/lib/dependencies/jemalloc/msvc/test_threads/test_threads.h diff --git a/kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads_main.cpp b/kbe/src/lib/dependencies/jemalloc/msvc/test_threads/test_threads_main.cpp old mode 100755 new mode 100644 similarity index 100% rename from kbe/src/lib/dependencies/jemalloc/msvc/projects/vc2015/test_threads/test_threads_main.cpp rename to kbe/src/lib/dependencies/jemalloc/msvc/test_threads/test_threads_main.cpp diff --git a/kbe/src/lib/dependencies/jemalloc/scripts/gen_run_tests.py b/kbe/src/lib/dependencies/jemalloc/scripts/gen_run_tests.py index ddf215335b..5052b3e0d3 100755 --- a/kbe/src/lib/dependencies/jemalloc/scripts/gen_run_tests.py +++ b/kbe/src/lib/dependencies/jemalloc/scripts/gen_run_tests.py @@ -1,20 +1,38 @@ #!/usr/bin/env python +import sys from itertools import combinations from os import uname from multiprocessing import cpu_count +from subprocess import call + +# Later, we want to test extended vaddr support. Apparently, the "real" way of +# checking this is flaky on OS X. +bits_64 = sys.maxsize > 2**32 nparallel = cpu_count() * 2 uname = uname()[0] +if "BSD" in uname: + make_cmd = 'gmake' +else: + make_cmd = 'make' + def powerset(items): result = [] for i in xrange(len(items) + 1): result += combinations(items, i) return result -possible_compilers = [('gcc', 'g++'), ('clang', 'clang++')] +possible_compilers = [] +for cc, cxx in (['gcc', 'g++'], ['clang', 'clang++']): + try: + cmd_ret = call([cc, "-v"]) + if cmd_ret == 0: + possible_compilers.append((cc, cxx)) + except: + pass possible_compiler_opts = [ '-m32', ] @@ -22,8 +40,10 @@ def powerset(items): '--enable-debug', '--enable-prof', '--disable-stats', - '--with-malloc-conf=tcache:false', ] +if bits_64: + possible_config_opts.append('--with-lg-vaddr=56') + possible_malloc_conf_opts = [ 'tcache:false', 'dss:primary', @@ -32,7 +52,7 @@ def powerset(items): ] print 'set -e' -print 'if [ -f Makefile ] ; then make relclean ; fi' +print 'if [ -f Makefile ] ; then %(make_cmd)s relclean ; fi' % {'make_cmd': make_cmd} print 'autoconf' print 'rm -rf run_tests.out' print 'mkdir run_tests.out' @@ -57,6 +77,11 @@ def powerset(items): else '') ) + # We don't want to test large vaddr spaces in 32-bit mode. + if ('-m32' in compiler_opts and '--with-lg-vaddr=56' in + config_opts): + continue + # Per CPU arenas are only supported on Linux. linux_supported = ('percpu_arena:percpu' in malloc_conf_opts \ or 'background_thread:true' in malloc_conf_opts) @@ -90,11 +115,11 @@ def powerset(items): echo "==> %(config_line)s" >> run_test.log %(config_line)s >> run_test.log 2>&1 || abort -run_cmd make all tests -run_cmd make check -run_cmd make distclean +run_cmd %(make_cmd)s all tests +run_cmd %(make_cmd)s check +run_cmd %(make_cmd)s distclean EOF -chmod 755 run_test_%(ind)d.sh""" % {'ind': ind, 'config_line': config_line} +chmod 755 run_test_%(ind)d.sh""" % {'ind': ind, 'config_line': config_line, 'make_cmd': make_cmd} ind += 1 print 'for i in `seq 0 %(last_ind)d` ; do echo run_test_${i}.sh ; done | xargs -P %(nparallel)d -n 1 sh' % {'last_ind': ind-1, 'nparallel': nparallel} diff --git a/kbe/src/lib/dependencies/jemalloc/scripts/gen_travis.py b/kbe/src/lib/dependencies/jemalloc/scripts/gen_travis.py index 6dd39290c9..65b0b67c7d 100755 --- a/kbe/src/lib/dependencies/jemalloc/scripts/gen_travis.py +++ b/kbe/src/lib/dependencies/jemalloc/scripts/gen_travis.py @@ -4,6 +4,7 @@ travis_template = """\ language: generic +dist: precise matrix: include: @@ -11,6 +12,7 @@ before_script: - autoconf + - scripts/gen_travis.py > travis_script && diff .travis.yml travis_script - ./configure ${COMPILER_FLAGS:+ \ CC="$CC $COMPILER_FLAGS" \ CXX="$CXX $COMPILER_FLAGS" } \ @@ -43,6 +45,7 @@ '--enable-debug', '--enable-prof', '--disable-stats', + '--disable-libdl', ] malloc_conf_unusuals = [ @@ -61,47 +64,85 @@ for i in xrange(MAX_UNUSUAL_OPTIONS + 1): unusual_combinations_to_test += combinations(all_unusuals, i) -include_rows = "" -for unusual_combination in unusual_combinations_to_test: - os = os_default - if os_unusual in unusual_combination: - os = os_unusual - - compilers = compilers_default - if compilers_unusual in unusual_combination: - compilers = compilers_unusual +gcc_multilib_set = False +# Formats a job from a combination of flags +def format_job(combination): + global gcc_multilib_set - compiler_flags = [ - x for x in unusual_combination if x in compiler_flag_unusuals] + os = os_unusual if os_unusual in combination else os_default + compilers = compilers_unusual if compilers_unusual in combination else compilers_default - configure_flags = [ - x for x in unusual_combination if x in configure_flag_unusuals] + compiler_flags = [x for x in combination if x in compiler_flag_unusuals] + configure_flags = [x for x in combination if x in configure_flag_unusuals] + malloc_conf = [x for x in combination if x in malloc_conf_unusuals] - malloc_conf = [ - x for x in unusual_combination if x in malloc_conf_unusuals] # Filter out unsupported configurations on OS X. if os == 'osx' and ('dss:primary' in malloc_conf or \ 'percpu_arena:percpu' in malloc_conf or 'background_thread:true' \ in malloc_conf): - continue + return "" if len(malloc_conf) > 0: configure_flags.append('--with-malloc-conf=' + ",".join(malloc_conf)) # Filter out an unsupported configuration - heap profiling on OS X. if os == 'osx' and '--enable-prof' in configure_flags: - continue + return "" # We get some spurious errors when -Warray-bounds is enabled. env_string = ('{} COMPILER_FLAGS="{}" CONFIGURE_FLAGS="{}" ' 'EXTRA_CFLAGS="-Werror -Wno-array-bounds"').format( compilers, " ".join(compiler_flags), " ".join(configure_flags)) - include_rows += ' - os: %s\n' % os - include_rows += ' env: %s\n' % env_string - if '-m32' in unusual_combination and os == 'linux': - include_rows += ' addons:\n' - include_rows += ' apt:\n' - include_rows += ' packages:\n' - include_rows += ' - gcc-multilib\n' + job = "" + job += ' - os: %s\n' % os + job += ' env: %s\n' % env_string + if '-m32' in combination and os == 'linux': + job += ' addons:' + if gcc_multilib_set: + job += ' *gcc_multilib\n' + else: + job += ' &gcc_multilib\n' + job += ' apt:\n' + job += ' packages:\n' + job += ' - gcc-multilib\n' + gcc_multilib_set = True + return job + +include_rows = "" +for combination in unusual_combinations_to_test: + include_rows += format_job(combination) + +# Development build +include_rows += '''\ + # Development build + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --disable-cache-oblivious --enable-stats --enable-log --enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" +''' + +# Enable-expermental-smallocx +include_rows += '''\ + # --enable-expermental-smallocx: + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --enable-experimental-smallocx --enable-stats --enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" +''' + +# Valgrind build bots +include_rows += ''' + # Valgrind + - os: linux + env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" JEMALLOC_TEST_PREFIX="valgrind" + addons: + apt: + packages: + - valgrind +''' + +# To enable valgrind on macosx add: +# +# - os: osx +# env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" JEMALLOC_TEST_PREFIX="valgrind" +# install: brew install valgrind +# +# It currently fails due to: https://github.com/jemalloc/jemalloc/issues/1274 print travis_template % include_rows diff --git a/kbe/src/lib/dependencies/jemalloc/src/arena.c b/kbe/src/lib/dependencies/jemalloc/src/arena.c index 632fce5233..60eac232a9 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/arena.c +++ b/kbe/src/lib/dependencies/jemalloc/src/arena.c @@ -3,13 +3,15 @@ #include "jemalloc/internal/jemalloc_internal_includes.h" #include "jemalloc/internal/assert.h" +#include "jemalloc/internal/div.h" #include "jemalloc/internal/extent_dss.h" #include "jemalloc/internal/extent_mmap.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/rtree.h" -#include "jemalloc/internal/size_classes.h" #include "jemalloc/internal/util.h" +JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS + /******************************************************************************/ /* Data. */ @@ -32,21 +34,6 @@ ssize_t opt_muzzy_decay_ms = MUZZY_DECAY_MS_DEFAULT; static atomic_zd_t dirty_decay_ms_default; static atomic_zd_t muzzy_decay_ms_default; -const arena_bin_info_t arena_bin_info[NBINS] = { -#define BIN_INFO_bin_yes(reg_size, slab_size, nregs) \ - {reg_size, slab_size, nregs, BITMAP_INFO_INITIALIZER(nregs)}, -#define BIN_INFO_bin_no(reg_size, slab_size, nregs) -#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, \ - lg_delta_lookup) \ - BIN_INFO_bin_##bin((1U<mtx, "arena_stats", - WITNESS_RANK_ARENA_STATS, malloc_mutex_rank_exclusive)) { - return true; - } -#endif - /* Memory is zeroed, so there is no need to clear stats. */ - return false; -} - -static void -arena_stats_lock(tsdn_t *tsdn, arena_stats_t *arena_stats) { -#ifndef JEMALLOC_ATOMIC_U64 - malloc_mutex_lock(tsdn, &arena_stats->mtx); -#endif -} - -static void -arena_stats_unlock(tsdn_t *tsdn, arena_stats_t *arena_stats) { -#ifndef JEMALLOC_ATOMIC_U64 - malloc_mutex_unlock(tsdn, &arena_stats->mtx); -#endif -} - -static uint64_t -arena_stats_read_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, - arena_stats_u64_t *p) { -#ifdef JEMALLOC_ATOMIC_U64 - return atomic_load_u64(p, ATOMIC_RELAXED); -#else - malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); - return *p; -#endif -} - -static void -arena_stats_add_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, - arena_stats_u64_t *p, uint64_t x) { -#ifdef JEMALLOC_ATOMIC_U64 - atomic_fetch_add_u64(p, x, ATOMIC_RELAXED); -#else - malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); - *p += x; -#endif -} - -UNUSED static void -arena_stats_sub_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, - arena_stats_u64_t *p, uint64_t x) { -#ifdef JEMALLOC_ATOMIC_U64 - UNUSED uint64_t r = atomic_fetch_sub_u64(p, x, ATOMIC_RELAXED); - assert(r - x <= r); -#else - malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); - *p -= x; - assert(*p + x >= *p); -#endif -} - -/* - * Non-atomically sets *dst += src. *dst needs external synchronization. - * This lets us avoid the cost of a fetch_add when its unnecessary (note that - * the types here are atomic). - */ -static void -arena_stats_accum_u64(arena_stats_u64_t *dst, uint64_t src) { -#ifdef JEMALLOC_ATOMIC_U64 - uint64_t cur_dst = atomic_load_u64(dst, ATOMIC_RELAXED); - atomic_store_u64(dst, src + cur_dst, ATOMIC_RELAXED); -#else - *dst += src; -#endif -} - -static size_t -arena_stats_read_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, atomic_zu_t *p) { -#ifdef JEMALLOC_ATOMIC_U64 - return atomic_load_zu(p, ATOMIC_RELAXED); -#else - malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); - return atomic_load_zu(p, ATOMIC_RELAXED); -#endif -} - -static void -arena_stats_add_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, atomic_zu_t *p, - size_t x) { -#ifdef JEMALLOC_ATOMIC_U64 - atomic_fetch_add_zu(p, x, ATOMIC_RELAXED); -#else - malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); - size_t cur = atomic_load_zu(p, ATOMIC_RELAXED); - atomic_store_zu(p, cur + x, ATOMIC_RELAXED); -#endif -} - -static void -arena_stats_sub_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, atomic_zu_t *p, - size_t x) { -#ifdef JEMALLOC_ATOMIC_U64 - UNUSED size_t r = atomic_fetch_sub_zu(p, x, ATOMIC_RELAXED); - assert(r - x <= r); -#else - malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); - size_t cur = atomic_load_zu(p, ATOMIC_RELAXED); - atomic_store_zu(p, cur - x, ATOMIC_RELAXED); -#endif -} - -/* Like the _u64 variant, needs an externally synchronized *dst. */ -static void -arena_stats_accum_zu(atomic_zu_t *dst, size_t src) { - size_t cur_dst = atomic_load_zu(dst, ATOMIC_RELAXED); - atomic_store_zu(dst, src + cur_dst, ATOMIC_RELAXED); -} - -void -arena_stats_large_nrequests_add(tsdn_t *tsdn, arena_stats_t *arena_stats, - szind_t szind, uint64_t nrequests) { - arena_stats_lock(tsdn, arena_stats); - arena_stats_add_u64(tsdn, arena_stats, &arena_stats->lstats[szind - - NBINS].nrequests, nrequests); - arena_stats_unlock(tsdn, arena_stats); -} - -void -arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats, size_t size) { - arena_stats_lock(tsdn, arena_stats); - arena_stats_add_zu(tsdn, arena_stats, &arena_stats->mapped, size); - arena_stats_unlock(tsdn, arena_stats); -} - void arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms, @@ -228,15 +82,16 @@ void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms, size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats, - malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats) { + bin_stats_t *bstats, arena_stats_large_t *lstats, + arena_stats_extents_t *estats) { cassert(config_stats); arena_basic_stats_merge(tsdn, arena, nthreads, dss, dirty_decay_ms, muzzy_decay_ms, nactive, ndirty, nmuzzy); - size_t base_allocated, base_resident, base_mapped; + size_t base_allocated, base_resident, base_mapped, metadata_thp; base_stats_get(tsdn, arena->base, &base_allocated, &base_resident, - &base_mapped); + &base_mapped, &metadata_thp); arena_stats_lock(tsdn, &arena->stats); @@ -245,6 +100,10 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, arena_stats_accum_zu(&astats->retained, extents_npages_get(&arena->extents_retained) << LG_PAGE); + atomic_store_zu(&astats->extent_avail, + atomic_load_zu(&arena->extent_avail_cnt, ATOMIC_RELAXED), + ATOMIC_RELAXED); + arena_stats_accum_u64(&astats->decay_dirty.npurge, arena_stats_read_u64(tsdn, &arena->stats, &arena->stats.decay_dirty.npurge)); @@ -267,12 +126,13 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, arena_stats_accum_zu(&astats->base, base_allocated); arena_stats_accum_zu(&astats->internal, arena_internal_get(arena)); + arena_stats_accum_zu(&astats->metadata_thp, metadata_thp); arena_stats_accum_zu(&astats->resident, base_resident + (((atomic_load_zu(&arena->nactive, ATOMIC_RELAXED) + extents_npages_get(&arena->extents_dirty) + extents_npages_get(&arena->extents_muzzy)) << LG_PAGE))); - for (szind_t i = 0; i < NSIZES - NBINS; i++) { + for (szind_t i = 0; i < SC_NSIZES - SC_NBINS; i++) { uint64_t nmalloc = arena_stats_read_u64(tsdn, &arena->stats, &arena->stats.lstats[i].nmalloc); arena_stats_accum_u64(&lstats[i].nmalloc, nmalloc); @@ -295,7 +155,29 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, size_t curlextents = (size_t)(nmalloc - ndalloc); lstats[i].curlextents += curlextents; arena_stats_accum_zu(&astats->allocated_large, - curlextents * sz_index2size(NBINS + i)); + curlextents * sz_index2size(SC_NBINS + i)); + } + + for (pszind_t i = 0; i < SC_NPSIZES; i++) { + size_t dirty, muzzy, retained, dirty_bytes, muzzy_bytes, + retained_bytes; + dirty = extents_nextents_get(&arena->extents_dirty, i); + muzzy = extents_nextents_get(&arena->extents_muzzy, i); + retained = extents_nextents_get(&arena->extents_retained, i); + dirty_bytes = extents_nbytes_get(&arena->extents_dirty, i); + muzzy_bytes = extents_nbytes_get(&arena->extents_muzzy, i); + retained_bytes = + extents_nbytes_get(&arena->extents_retained, i); + + atomic_store_zu(&estats[i].ndirty, dirty, ATOMIC_RELAXED); + atomic_store_zu(&estats[i].nmuzzy, muzzy, ATOMIC_RELAXED); + atomic_store_zu(&estats[i].nretained, retained, ATOMIC_RELAXED); + atomic_store_zu(&estats[i].dirty_bytes, dirty_bytes, + ATOMIC_RELAXED); + atomic_store_zu(&estats[i].muzzy_bytes, muzzy_bytes, + ATOMIC_RELAXED); + atomic_store_zu(&estats[i].retained_bytes, retained_bytes, + ATOMIC_RELAXED); } arena_stats_unlock(tsdn, &arena->stats); @@ -303,16 +185,16 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, /* tcache_bytes counts currently cached bytes. */ atomic_store_zu(&astats->tcache_bytes, 0, ATOMIC_RELAXED); malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx); - tcache_t *tcache; - ql_foreach(tcache, &arena->tcache_ql, link) { + cache_bin_array_descriptor_t *descriptor; + ql_foreach(descriptor, &arena->cache_bin_array_descriptor_ql, link) { szind_t i = 0; - for (; i < NBINS; i++) { - tcache_bin_t *tbin = tcache_small_bin_get(tcache, i); + for (; i < SC_NBINS; i++) { + cache_bin_t *tbin = &descriptor->bins_small[i]; arena_stats_accum_zu(&astats->tcache_bytes, tbin->ncached * sz_index2size(i)); } for (; i < nhbins; i++) { - tcache_bin_t *tbin = tcache_large_bin_get(tcache, i); + cache_bin_t *tbin = &descriptor->bins_large[i]; arena_stats_accum_zu(&astats->tcache_bytes, tbin->ncached * sz_index2size(i)); } @@ -350,21 +232,11 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, nstime_update(&astats->uptime); nstime_subtract(&astats->uptime, &arena->create_time); - for (szind_t i = 0; i < NBINS; i++) { - arena_bin_t *bin = &arena->bins[i]; - - malloc_mutex_lock(tsdn, &bin->lock); - malloc_mutex_prof_read(tsdn, &bstats[i].mutex_data, &bin->lock); - bstats[i].nmalloc += bin->stats.nmalloc; - bstats[i].ndalloc += bin->stats.ndalloc; - bstats[i].nrequests += bin->stats.nrequests; - bstats[i].curregs += bin->stats.curregs; - bstats[i].nfills += bin->stats.nfills; - bstats[i].nflushes += bin->stats.nflushes; - bstats[i].nslabs += bin->stats.nslabs; - bstats[i].reslabs += bin->stats.reslabs; - bstats[i].curslabs += bin->stats.curslabs; - malloc_mutex_unlock(tsdn, &bin->lock); + for (szind_t i = 0; i < SC_NBINS; i++) { + for (unsigned j = 0; j < bin_infos[i].n_shards; j++) { + bin_stats_merge(tsdn, &bstats[i], + &arena->bins[i].bin_shards[j]); + } } } @@ -384,8 +256,7 @@ arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena, } static void * -arena_slab_reg_alloc(tsdn_t *tsdn, extent_t *slab, - const arena_bin_info_t *bin_info) { +arena_slab_reg_alloc(extent_t *slab, const bin_info_t *bin_info) { void *ret; arena_slab_data_t *slab_data = extent_slab_data_get(slab); size_t regind; @@ -400,6 +271,54 @@ arena_slab_reg_alloc(tsdn_t *tsdn, extent_t *slab, return ret; } +static void +arena_slab_reg_alloc_batch(extent_t *slab, const bin_info_t *bin_info, + unsigned cnt, void** ptrs) { + arena_slab_data_t *slab_data = extent_slab_data_get(slab); + + assert(extent_nfree_get(slab) >= cnt); + assert(!bitmap_full(slab_data->bitmap, &bin_info->bitmap_info)); + +#if (! defined JEMALLOC_INTERNAL_POPCOUNTL) || (defined BITMAP_USE_TREE) + for (unsigned i = 0; i < cnt; i++) { + size_t regind = bitmap_sfu(slab_data->bitmap, + &bin_info->bitmap_info); + *(ptrs + i) = (void *)((uintptr_t)extent_addr_get(slab) + + (uintptr_t)(bin_info->reg_size * regind)); + } +#else + unsigned group = 0; + bitmap_t g = slab_data->bitmap[group]; + unsigned i = 0; + while (i < cnt) { + while (g == 0) { + g = slab_data->bitmap[++group]; + } + size_t shift = group << LG_BITMAP_GROUP_NBITS; + size_t pop = popcount_lu(g); + if (pop > (cnt - i)) { + pop = cnt - i; + } + + /* + * Load from memory locations only once, outside the + * hot loop below. + */ + uintptr_t base = (uintptr_t)extent_addr_get(slab); + uintptr_t regsize = (uintptr_t)bin_info->reg_size; + while (pop--) { + size_t bit = cfs_lu(&g); + size_t regind = shift + bit; + *(ptrs + i) = (void *)(base + regsize * regind); + + i++; + } + slab_data->bitmap[group] = g; + } +#endif + extent_nfree_sub(slab, cnt); +} + #ifndef JEMALLOC_JET static #endif @@ -412,37 +331,22 @@ arena_slab_regind(extent_t *slab, szind_t binind, const void *ptr) { assert((uintptr_t)ptr < (uintptr_t)extent_past_get(slab)); /* Freeing an interior pointer can cause assertion failure. */ assert(((uintptr_t)ptr - (uintptr_t)extent_addr_get(slab)) % - (uintptr_t)arena_bin_info[binind].reg_size == 0); + (uintptr_t)bin_infos[binind].reg_size == 0); - /* Avoid doing division with a variable divisor. */ diff = (size_t)((uintptr_t)ptr - (uintptr_t)extent_addr_get(slab)); - switch (binind) { -#define REGIND_bin_yes(index, reg_size) \ - case index: \ - regind = diff / (reg_size); \ - assert(diff == regind * (reg_size)); \ - break; -#define REGIND_bin_no(index, reg_size) -#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, \ - lg_delta_lookup) \ - REGIND_bin_##bin(index, (1U<nregs); @@ -470,11 +374,11 @@ arena_large_malloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t usize) { cassert(config_stats); - if (usize < LARGE_MINCLASS) { - usize = LARGE_MINCLASS; + if (usize < SC_LARGE_MINCLASS) { + usize = SC_LARGE_MINCLASS; } index = sz_size2index(usize); - hindex = (index >= NBINS) ? index - NBINS : 0; + hindex = (index >= SC_NBINS) ? index - SC_NBINS : 0; arena_stats_add_u64(tsdn, &arena->stats, &arena->stats.lstats[hindex].nmalloc, 1); @@ -486,11 +390,11 @@ arena_large_dalloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t usize) { cassert(config_stats); - if (usize < LARGE_MINCLASS) { - usize = LARGE_MINCLASS; + if (usize < SC_LARGE_MINCLASS) { + usize = SC_LARGE_MINCLASS; } index = sz_size2index(usize); - hindex = (index >= NBINS) ? index - NBINS : 0; + hindex = (index >= SC_NBINS) ? index - SC_NBINS : 0; arena_stats_add_u64(tsdn, &arena->stats, &arena->stats.lstats[hindex].ndalloc, 1); @@ -503,6 +407,11 @@ arena_large_ralloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t oldusize, arena_large_malloc_stats_update(tsdn, arena, usize); } +static bool +arena_may_have_muzzy(arena_t *arena) { + return (pages_can_purge_lazy && (arena_muzzy_decay_ms_get(arena) != 0)); +} + extent_t * arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, bool *zero) { @@ -517,7 +426,7 @@ arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, extent_t *extent = extents_alloc(tsdn, arena, &extent_hooks, &arena->extents_dirty, NULL, usize, sz_large_pad, alignment, false, szind, zero, &commit); - if (extent == NULL) { + if (extent == NULL && arena_may_have_muzzy(arena)) { extent = extents_alloc(tsdn, arena, &extent_hooks, &arena->extents_muzzy, NULL, usize, sz_large_pad, alignment, false, szind, zero, &commit); @@ -692,7 +601,8 @@ arena_decay_try_purge(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, bool is_background_thread) { if (current_npages > npages_limit) { arena_decay_to_limit(tsdn, arena, decay, extents, false, - npages_limit, is_background_thread); + npages_limit, current_npages - npages_limit, + is_background_thread); } } @@ -738,7 +648,7 @@ arena_decay_epoch_advance(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, } static void -arena_decay_reinit(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms) { +arena_decay_reinit(arena_decay_t *decay, ssize_t decay_ms) { arena_decay_ms_write(decay, decay_ms); if (decay_ms > 0) { nstime_init(&decay->interval, (uint64_t)decay_ms * @@ -755,8 +665,8 @@ arena_decay_reinit(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms) { } static bool -arena_decay_init(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms, - decay_stats_t *stats) { +arena_decay_init(arena_decay_t *decay, ssize_t decay_ms, + arena_stats_decay_t *stats) { if (config_debug) { for (size_t i = 0; i < sizeof(arena_decay_t); i++) { assert(((char *)decay)[i] == 0); @@ -768,7 +678,7 @@ arena_decay_init(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms, return true; } decay->purging = false; - arena_decay_reinit(decay, extents, decay_ms); + arena_decay_reinit(decay, decay_ms); /* Memory is zeroed, so there is no need to clear stats. */ if (config_stats) { decay->stats = stats; @@ -798,7 +708,8 @@ arena_maybe_decay(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, if (decay_ms <= 0) { if (decay_ms == 0) { arena_decay_to_limit(tsdn, arena, decay, extents, false, - 0, is_background_thread); + 0, extents_npages_get(extents), + is_background_thread); } return false; } @@ -876,7 +787,7 @@ arena_decay_ms_set(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, * infrequent, either between the {-1, 0, >0} states, or a one-time * arbitrary change during initial arena configuration. */ - arena_decay_reinit(decay, extents, decay_ms); + arena_decay_reinit(decay, decay_ms); arena_maybe_decay(tsdn, arena, decay, extents, false); malloc_mutex_unlock(tsdn, &decay->mtx); @@ -900,14 +811,15 @@ arena_muzzy_decay_ms_set(tsdn_t *tsdn, arena_t *arena, static size_t arena_stash_decayed(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extents_t *extents, size_t npages_limit, - extent_list_t *decay_extents) { + size_t npages_decay_max, extent_list_t *decay_extents) { witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); /* Stash extents according to npages_limit. */ size_t nstashed = 0; extent_t *extent; - while ((extent = extents_evict(tsdn, arena, r_extent_hooks, extents, + while (nstashed < npages_decay_max && + (extent = extents_evict(tsdn, arena, r_extent_hooks, extents, npages_limit)) != NULL) { extent_list_append(decay_extents, extent); nstashed += extent_size_get(extent) >> LG_PAGE; @@ -919,7 +831,7 @@ static size_t arena_decay_stashed(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, arena_decay_t *decay, extents_t *extents, bool all, extent_list_t *decay_extents, bool is_background_thread) { - UNUSED size_t nmadvise, nunmapped; + size_t nmadvise, nunmapped; size_t npurged; if (config_stats) { @@ -982,12 +894,15 @@ arena_decay_stashed(tsdn_t *tsdn, arena_t *arena, } /* - * npages_limit: Decay as many dirty extents as possible without violating the - * invariant: (extents_npages_get(extents) >= npages_limit) + * npages_limit: Decay at most npages_decay_max pages without violating the + * invariant: (extents_npages_get(extents) >= npages_limit). We need an upper + * bound on number of pages in order to prevent unbounded growth (namely in + * stashed), otherwise unbounded new pages could be added to extents during the + * current decay run, so that the purging thread never finishes. */ static void arena_decay_to_limit(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, - extents_t *extents, bool all, size_t npages_limit, + extents_t *extents, bool all, size_t npages_limit, size_t npages_decay_max, bool is_background_thread) { witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 1); @@ -1005,9 +920,9 @@ arena_decay_to_limit(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, extent_list_init(&decay_extents); size_t npurge = arena_stash_decayed(tsdn, arena, &extent_hooks, extents, - npages_limit, &decay_extents); + npages_limit, npages_decay_max, &decay_extents); if (npurge != 0) { - UNUSED size_t npurged = arena_decay_stashed(tsdn, arena, + size_t npurged = arena_decay_stashed(tsdn, arena, &extent_hooks, decay, extents, all, &decay_extents, is_background_thread); assert(npurged == npurge); @@ -1023,7 +938,7 @@ arena_decay_impl(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, if (all) { malloc_mutex_lock(tsdn, &decay->mtx); arena_decay_to_limit(tsdn, arena, decay, extents, all, 0, - is_background_thread); + extents_npages_get(extents), is_background_thread); malloc_mutex_unlock(tsdn, &decay->mtx); return false; @@ -1045,7 +960,8 @@ arena_decay_impl(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, if (have_background_thread && background_thread_enabled() && epoch_advanced && !is_background_thread) { - background_thread_interval_check(tsdn, arena, decay, npages_new); + background_thread_interval_check(tsdn, arena, decay, + npages_new); } return false; @@ -1082,18 +998,18 @@ arena_slab_dalloc(tsdn_t *tsdn, arena_t *arena, extent_t *slab) { } static void -arena_bin_slabs_nonfull_insert(arena_bin_t *bin, extent_t *slab) { +arena_bin_slabs_nonfull_insert(bin_t *bin, extent_t *slab) { assert(extent_nfree_get(slab) > 0); extent_heap_insert(&bin->slabs_nonfull, slab); } static void -arena_bin_slabs_nonfull_remove(arena_bin_t *bin, extent_t *slab) { +arena_bin_slabs_nonfull_remove(bin_t *bin, extent_t *slab) { extent_heap_remove(&bin->slabs_nonfull, slab); } static extent_t * -arena_bin_slabs_nonfull_tryget(arena_bin_t *bin) { +arena_bin_slabs_nonfull_tryget(bin_t *bin) { extent_t *slab = extent_heap_remove_first(&bin->slabs_nonfull); if (slab == NULL) { return NULL; @@ -1105,7 +1021,7 @@ arena_bin_slabs_nonfull_tryget(arena_bin_t *bin) { } static void -arena_bin_slabs_full_insert(arena_t *arena, arena_bin_t *bin, extent_t *slab) { +arena_bin_slabs_full_insert(arena_t *arena, bin_t *bin, extent_t *slab) { assert(extent_nfree_get(slab) == 0); /* * Tracking extents is required by arena_reset, which is not allowed @@ -1119,13 +1035,44 @@ arena_bin_slabs_full_insert(arena_t *arena, arena_bin_t *bin, extent_t *slab) { } static void -arena_bin_slabs_full_remove(arena_t *arena, arena_bin_t *bin, extent_t *slab) { +arena_bin_slabs_full_remove(arena_t *arena, bin_t *bin, extent_t *slab) { if (arena_is_auto(arena)) { return; } extent_list_remove(&bin->slabs_full, slab); } +static void +arena_bin_reset(tsd_t *tsd, arena_t *arena, bin_t *bin) { + extent_t *slab; + + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + if (bin->slabcur != NULL) { + slab = bin->slabcur; + bin->slabcur = NULL; + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); + arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + } + while ((slab = extent_heap_remove_first(&bin->slabs_nonfull)) != NULL) { + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); + arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + } + for (slab = extent_list_first(&bin->slabs_full); slab != NULL; + slab = extent_list_first(&bin->slabs_full)) { + arena_bin_slabs_full_remove(arena, bin, slab); + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); + arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + } + if (config_stats) { + bin->stats.curregs = 0; + bin->stats.curslabs = 0; + } + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); +} + void arena_reset(tsd_t *tsd, arena_t *arena) { /* @@ -1155,7 +1102,7 @@ arena_reset(tsd_t *tsd, arena_t *arena) { rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); - assert(alloc_ctx.szind != NSIZES); + assert(alloc_ctx.szind != SC_NSIZES); if (config_stats || (config_prof && opt_prof)) { usize = sz_index2size(alloc_ctx.szind); @@ -1171,35 +1118,11 @@ arena_reset(tsd_t *tsd, arena_t *arena) { malloc_mutex_unlock(tsd_tsdn(tsd), &arena->large_mtx); /* Bins. */ - for (unsigned i = 0; i < NBINS; i++) { - extent_t *slab; - arena_bin_t *bin = &arena->bins[i]; - malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); - if (bin->slabcur != NULL) { - slab = bin->slabcur; - bin->slabcur = NULL; - malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); - arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); - malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); - } - while ((slab = extent_heap_remove_first(&bin->slabs_nonfull)) != - NULL) { - malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); - arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); - malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); - } - for (slab = extent_list_first(&bin->slabs_full); slab != NULL; - slab = extent_list_first(&bin->slabs_full)) { - arena_bin_slabs_full_remove(arena, bin, slab); - malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); - arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); - malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + for (unsigned i = 0; i < SC_NBINS; i++) { + for (unsigned j = 0; j < bin_infos[i].n_shards; j++) { + arena_bin_reset(tsd, arena, + &arena->bins[i].bin_shards[j]); } - if (config_stats) { - bin->stats.curregs = 0; - bin->stats.curslabs = 0; - } - malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); } atomic_store_zu(&arena->nactive, 0, ATOMIC_RELAXED); @@ -1262,7 +1185,7 @@ arena_destroy(tsd_t *tsd, arena_t *arena) { static extent_t * arena_slab_alloc_hard(tsdn_t *tsdn, arena_t *arena, - extent_hooks_t **r_extent_hooks, const arena_bin_info_t *bin_info, + extent_hooks_t **r_extent_hooks, const bin_info_t *bin_info, szind_t szind) { extent_t *slab; bool zero, commit; @@ -1284,8 +1207,8 @@ arena_slab_alloc_hard(tsdn_t *tsdn, arena_t *arena, } static extent_t * -arena_slab_alloc(tsdn_t *tsdn, arena_t *arena, szind_t binind, - const arena_bin_info_t *bin_info) { +arena_slab_alloc(tsdn_t *tsdn, arena_t *arena, szind_t binind, unsigned binshard, + const bin_info_t *bin_info) { witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); @@ -1296,7 +1219,7 @@ arena_slab_alloc(tsdn_t *tsdn, arena_t *arena, szind_t binind, extent_t *slab = extents_alloc(tsdn, arena, &extent_hooks, &arena->extents_dirty, NULL, bin_info->slab_size, 0, PAGE, true, binind, &zero, &commit); - if (slab == NULL) { + if (slab == NULL && arena_may_have_muzzy(arena)) { slab = extents_alloc(tsdn, arena, &extent_hooks, &arena->extents_muzzy, NULL, bin_info->slab_size, 0, PAGE, true, binind, &zero, &commit); @@ -1312,7 +1235,7 @@ arena_slab_alloc(tsdn_t *tsdn, arena_t *arena, szind_t binind, /* Initialize slab internals. */ arena_slab_data_t *slab_data = extent_slab_data_get(slab); - extent_nfree_set(slab, bin_info->nregs); + extent_nfree_binshard_set(slab, bin_info->nregs, binshard); bitmap_init(slab_data->bitmap, &bin_info->bitmap_info, false); arena_nactive_add(arena, extent_size_get(slab) >> LG_PAGE); @@ -1321,10 +1244,10 @@ arena_slab_alloc(tsdn_t *tsdn, arena_t *arena, szind_t binind, } static extent_t * -arena_bin_nonfull_slab_get(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin, - szind_t binind) { +arena_bin_nonfull_slab_get(tsdn_t *tsdn, arena_t *arena, bin_t *bin, + szind_t binind, unsigned binshard) { extent_t *slab; - const arena_bin_info_t *bin_info; + const bin_info_t *bin_info; /* Look for a usable slab. */ slab = arena_bin_slabs_nonfull_tryget(bin); @@ -1333,12 +1256,12 @@ arena_bin_nonfull_slab_get(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin, } /* No existing slabs have any space available. */ - bin_info = &arena_bin_info[binind]; + bin_info = &bin_infos[binind]; /* Allocate a new slab. */ malloc_mutex_unlock(tsdn, &bin->lock); /******************************/ - slab = arena_slab_alloc(tsdn, arena, binind, bin_info); + slab = arena_slab_alloc(tsdn, arena, binind, binshard, bin_info); /********************************/ malloc_mutex_lock(tsdn, &bin->lock); if (slab != NULL) { @@ -1364,24 +1287,24 @@ arena_bin_nonfull_slab_get(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin, /* Re-fill bin->slabcur, then call arena_slab_reg_alloc(). */ static void * -arena_bin_malloc_hard(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin, - szind_t binind) { - const arena_bin_info_t *bin_info; +arena_bin_malloc_hard(tsdn_t *tsdn, arena_t *arena, bin_t *bin, + szind_t binind, unsigned binshard) { + const bin_info_t *bin_info; extent_t *slab; - bin_info = &arena_bin_info[binind]; + bin_info = &bin_infos[binind]; if (!arena_is_auto(arena) && bin->slabcur != NULL) { arena_bin_slabs_full_insert(arena, bin, bin->slabcur); bin->slabcur = NULL; } - slab = arena_bin_nonfull_slab_get(tsdn, arena, bin, binind); + slab = arena_bin_nonfull_slab_get(tsdn, arena, bin, binind, binshard); if (bin->slabcur != NULL) { /* * Another thread updated slabcur while this one ran without the * bin lock in arena_bin_nonfull_slab_get(). */ if (extent_nfree_get(bin->slabcur) > 0) { - void *ret = arena_slab_reg_alloc(tsdn, bin->slabcur, + void *ret = arena_slab_reg_alloc(bin->slabcur, bin_info); if (slab != NULL) { /* @@ -1415,51 +1338,78 @@ arena_bin_malloc_hard(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin, assert(extent_nfree_get(bin->slabcur) > 0); - return arena_slab_reg_alloc(tsdn, slab, bin_info); + return arena_slab_reg_alloc(slab, bin_info); +} + +/* Choose a bin shard and return the locked bin. */ +bin_t * +arena_bin_choose_lock(tsdn_t *tsdn, arena_t *arena, szind_t binind, + unsigned *binshard) { + bin_t *bin; + if (tsdn_null(tsdn) || tsd_arena_get(tsdn_tsd(tsdn)) == NULL) { + *binshard = 0; + } else { + *binshard = tsd_binshardsp_get(tsdn_tsd(tsdn))->binshard[binind]; + } + assert(*binshard < bin_infos[binind].n_shards); + bin = &arena->bins[binind].bin_shards[*binshard]; + malloc_mutex_lock(tsdn, &bin->lock); + + return bin; } void arena_tcache_fill_small(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, - tcache_bin_t *tbin, szind_t binind, uint64_t prof_accumbytes) { - unsigned i, nfill; - arena_bin_t *bin; + cache_bin_t *tbin, szind_t binind, uint64_t prof_accumbytes) { + unsigned i, nfill, cnt; assert(tbin->ncached == 0); if (config_prof && arena_prof_accum(tsdn, arena, prof_accumbytes)) { prof_idump(tsdn); } - bin = &arena->bins[binind]; - malloc_mutex_lock(tsdn, &bin->lock); + + unsigned binshard; + bin_t *bin = arena_bin_choose_lock(tsdn, arena, binind, &binshard); + for (i = 0, nfill = (tcache_bin_info[binind].ncached_max >> - tcache->lg_fill_div[binind]); i < nfill; i++) { + tcache->lg_fill_div[binind]); i < nfill; i += cnt) { extent_t *slab; - void *ptr; if ((slab = bin->slabcur) != NULL && extent_nfree_get(slab) > 0) { - ptr = arena_slab_reg_alloc(tsdn, slab, - &arena_bin_info[binind]); + unsigned tofill = nfill - i; + cnt = tofill < extent_nfree_get(slab) ? + tofill : extent_nfree_get(slab); + arena_slab_reg_alloc_batch( + slab, &bin_infos[binind], cnt, + tbin->avail - nfill + i); } else { - ptr = arena_bin_malloc_hard(tsdn, arena, bin, binind); - } - if (ptr == NULL) { + cnt = 1; + void *ptr = arena_bin_malloc_hard(tsdn, arena, bin, + binind, binshard); /* * OOM. tbin->avail isn't yet filled down to its first * element, so the successful allocations (if any) must * be moved just before tbin->avail before bailing out. */ - if (i > 0) { - memmove(tbin->avail - i, tbin->avail - nfill, - i * sizeof(void *)); + if (ptr == NULL) { + if (i > 0) { + memmove(tbin->avail - i, + tbin->avail - nfill, + i * sizeof(void *)); + } + break; } - break; + /* Insert such that low regions get used first. */ + *(tbin->avail - nfill + i) = ptr; } if (config_fill && unlikely(opt_junk_alloc)) { - arena_alloc_junk_small(ptr, &arena_bin_info[binind], - true); + for (unsigned j = 0; j < cnt; j++) { + void* ptr = *(tbin->avail - nfill + i + j); + arena_alloc_junk_small(ptr, &bin_infos[binind], + true); + } } - /* Insert such that low regions get used first. */ - *(tbin->avail - nfill + i) = ptr; } if (config_stats) { bin->stats.nmalloc += i; @@ -1474,14 +1424,14 @@ arena_tcache_fill_small(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, } void -arena_alloc_junk_small(void *ptr, const arena_bin_info_t *bin_info, bool zero) { +arena_alloc_junk_small(void *ptr, const bin_info_t *bin_info, bool zero) { if (!zero) { memset(ptr, JEMALLOC_ALLOC_JUNK, bin_info->reg_size); } } static void -arena_dalloc_junk_small_impl(void *ptr, const arena_bin_info_t *bin_info) { +arena_dalloc_junk_small_impl(void *ptr, const bin_info_t *bin_info) { memset(ptr, JEMALLOC_FREE_JUNK, bin_info->reg_size); } arena_dalloc_junk_small_t *JET_MUTABLE arena_dalloc_junk_small = @@ -1490,19 +1440,19 @@ arena_dalloc_junk_small_t *JET_MUTABLE arena_dalloc_junk_small = static void * arena_malloc_small(tsdn_t *tsdn, arena_t *arena, szind_t binind, bool zero) { void *ret; - arena_bin_t *bin; + bin_t *bin; size_t usize; extent_t *slab; - assert(binind < NBINS); - bin = &arena->bins[binind]; + assert(binind < SC_NBINS); usize = sz_index2size(binind); + unsigned binshard; + bin = arena_bin_choose_lock(tsdn, arena, binind, &binshard); - malloc_mutex_lock(tsdn, &bin->lock); if ((slab = bin->slabcur) != NULL && extent_nfree_get(slab) > 0) { - ret = arena_slab_reg_alloc(tsdn, slab, &arena_bin_info[binind]); + ret = arena_slab_reg_alloc(slab, &bin_infos[binind]); } else { - ret = arena_bin_malloc_hard(tsdn, arena, bin, binind); + ret = arena_bin_malloc_hard(tsdn, arena, bin, binind, binshard); } if (ret == NULL) { @@ -1524,14 +1474,14 @@ arena_malloc_small(tsdn_t *tsdn, arena_t *arena, szind_t binind, bool zero) { if (config_fill) { if (unlikely(opt_junk_alloc)) { arena_alloc_junk_small(ret, - &arena_bin_info[binind], false); + &bin_infos[binind], false); } else if (unlikely(opt_zero)) { memset(ret, 0, usize); } } } else { if (config_fill && unlikely(opt_junk_alloc)) { - arena_alloc_junk_small(ret, &arena_bin_info[binind], + arena_alloc_junk_small(ret, &bin_infos[binind], true); } memset(ret, 0, usize); @@ -1547,13 +1497,13 @@ arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, assert(!tsdn_null(tsdn) || arena != NULL); if (likely(!tsdn_null(tsdn))) { - arena = arena_choose(tsdn_tsd(tsdn), arena); + arena = arena_choose_maybe_huge(tsdn_tsd(tsdn), arena, size); } if (unlikely(arena == NULL)) { return NULL; } - if (likely(size <= SMALL_MAXCLASS)) { + if (likely(size <= SC_SMALL_MAXCLASS)) { return arena_malloc_small(tsdn, arena, ind, zero); } return large_malloc(tsdn, arena, sz_index2size(ind), zero); @@ -1564,8 +1514,9 @@ arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, bool zero, tcache_t *tcache) { void *ret; - if (usize <= SMALL_MAXCLASS && (alignment < PAGE || (alignment == PAGE - && (usize & PAGE_MASK) == 0))) { + if (usize <= SC_SMALL_MAXCLASS + && (alignment < PAGE + || (alignment == PAGE && (usize & PAGE_MASK) == 0))) { /* Small; alignment doesn't require special slab placement. */ ret = arena_malloc(tsdn, arena, usize, sz_size2index(usize), zero, tcache, true); @@ -1583,8 +1534,8 @@ void arena_prof_promote(tsdn_t *tsdn, const void *ptr, size_t usize) { cassert(config_prof); assert(ptr != NULL); - assert(isalloc(tsdn, ptr) == LARGE_MINCLASS); - assert(usize <= SMALL_MAXCLASS); + assert(isalloc(tsdn, ptr) == SC_LARGE_MINCLASS); + assert(usize <= SC_SMALL_MAXCLASS); rtree_ctx_t rtree_ctx_fallback; rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); @@ -1608,15 +1559,15 @@ arena_prof_demote(tsdn_t *tsdn, extent_t *extent, const void *ptr) { cassert(config_prof); assert(ptr != NULL); - extent_szind_set(extent, NBINS); + extent_szind_set(extent, SC_NBINS); rtree_ctx_t rtree_ctx_fallback; rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, - NBINS, false); + SC_NBINS, false); - assert(isalloc(tsdn, ptr) == LARGE_MINCLASS); + assert(isalloc(tsdn, ptr) == SC_LARGE_MINCLASS); - return LARGE_MINCLASS; + return SC_LARGE_MINCLASS; } void @@ -1636,13 +1587,13 @@ arena_dalloc_promoted(tsdn_t *tsdn, void *ptr, tcache_t *tcache, } static void -arena_dissociate_bin_slab(arena_t *arena, extent_t *slab, arena_bin_t *bin) { +arena_dissociate_bin_slab(arena_t *arena, extent_t *slab, bin_t *bin) { /* Dissociate slab from bin. */ if (slab == bin->slabcur) { bin->slabcur = NULL; } else { szind_t binind = extent_szind_get(slab); - const arena_bin_info_t *bin_info = &arena_bin_info[binind]; + const bin_info_t *bin_info = &bin_infos[binind]; /* * The following block's conditional is necessary because if the @@ -1659,7 +1610,7 @@ arena_dissociate_bin_slab(arena_t *arena, extent_t *slab, arena_bin_t *bin) { static void arena_dalloc_bin_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, - arena_bin_t *bin) { + bin_t *bin) { assert(slab != bin->slabcur); malloc_mutex_unlock(tsdn, &bin->lock); @@ -1674,7 +1625,7 @@ arena_dalloc_bin_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, static void arena_bin_lower_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, - arena_bin_t *bin) { + bin_t *bin) { assert(extent_nfree_get(slab) > 0); /* @@ -1700,18 +1651,16 @@ arena_bin_lower_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, } static void -arena_dalloc_bin_locked_impl(tsdn_t *tsdn, arena_t *arena, extent_t *slab, - void *ptr, bool junked) { +arena_dalloc_bin_locked_impl(tsdn_t *tsdn, arena_t *arena, bin_t *bin, + szind_t binind, extent_t *slab, void *ptr, bool junked) { arena_slab_data_t *slab_data = extent_slab_data_get(slab); - szind_t binind = extent_szind_get(slab); - arena_bin_t *bin = &arena->bins[binind]; - const arena_bin_info_t *bin_info = &arena_bin_info[binind]; + const bin_info_t *bin_info = &bin_infos[binind]; if (!junked && config_fill && unlikely(opt_junk_free)) { arena_dalloc_junk_small(ptr, bin_info); } - arena_slab_reg_dalloc(tsdn, slab, slab_data, ptr); + arena_slab_reg_dalloc(slab, slab_data, ptr); unsigned nfree = extent_nfree_get(slab); if (nfree == bin_info->nregs) { arena_dissociate_bin_slab(arena, slab, bin); @@ -1728,18 +1677,21 @@ arena_dalloc_bin_locked_impl(tsdn_t *tsdn, arena_t *arena, extent_t *slab, } void -arena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena, extent_t *extent, - void *ptr) { - arena_dalloc_bin_locked_impl(tsdn, arena, extent, ptr, true); +arena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena, bin_t *bin, + szind_t binind, extent_t *extent, void *ptr) { + arena_dalloc_bin_locked_impl(tsdn, arena, bin, binind, extent, ptr, + true); } static void arena_dalloc_bin(tsdn_t *tsdn, arena_t *arena, extent_t *extent, void *ptr) { szind_t binind = extent_szind_get(extent); - arena_bin_t *bin = &arena->bins[binind]; + unsigned binshard = extent_binshard_get(extent); + bin_t *bin = &arena->bins[binind].bin_shards[binshard]; malloc_mutex_lock(tsdn, &bin->lock); - arena_dalloc_bin_locked_impl(tsdn, arena, extent, ptr, false); + arena_dalloc_bin_locked_impl(tsdn, arena, bin, binind, extent, ptr, + false); malloc_mutex_unlock(tsdn, &bin->lock); } @@ -1754,38 +1706,48 @@ arena_dalloc_small(tsdn_t *tsdn, void *ptr) { bool arena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, - size_t extra, bool zero) { + size_t extra, bool zero, size_t *newsize) { + bool ret; /* Calls with non-zero extra had to clamp extra. */ - assert(extra == 0 || size + extra <= LARGE_MAXCLASS); + assert(extra == 0 || size + extra <= SC_LARGE_MAXCLASS); - if (unlikely(size > LARGE_MAXCLASS)) { - return true; + extent_t *extent = iealloc(tsdn, ptr); + if (unlikely(size > SC_LARGE_MAXCLASS)) { + ret = true; + goto done; } - extent_t *extent = iealloc(tsdn, ptr); size_t usize_min = sz_s2u(size); size_t usize_max = sz_s2u(size + extra); - if (likely(oldsize <= SMALL_MAXCLASS && usize_min <= SMALL_MAXCLASS)) { + if (likely(oldsize <= SC_SMALL_MAXCLASS && usize_min + <= SC_SMALL_MAXCLASS)) { /* * Avoid moving the allocation if the size class can be left the * same. */ - assert(arena_bin_info[sz_size2index(oldsize)].reg_size == + assert(bin_infos[sz_size2index(oldsize)].reg_size == oldsize); - if ((usize_max > SMALL_MAXCLASS || sz_size2index(usize_max) != - sz_size2index(oldsize)) && (size > oldsize || usize_max < - oldsize)) { - return true; + if ((usize_max > SC_SMALL_MAXCLASS + || sz_size2index(usize_max) != sz_size2index(oldsize)) + && (size > oldsize || usize_max < oldsize)) { + ret = true; + goto done; } arena_decay_tick(tsdn, extent_arena_get(extent)); - return false; - } else if (oldsize >= LARGE_MINCLASS && usize_max >= LARGE_MINCLASS) { - return large_ralloc_no_move(tsdn, extent, usize_min, usize_max, + ret = false; + } else if (oldsize >= SC_LARGE_MINCLASS + && usize_max >= SC_LARGE_MINCLASS) { + ret = large_ralloc_no_move(tsdn, extent, usize_min, usize_max, zero); + } else { + ret = true; } +done: + assert(extent == iealloc(tsdn, ptr)); + *newsize = extent_usize_get(extent); - return true; + return ret; } static void * @@ -1796,7 +1758,7 @@ arena_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize, zero, tcache, true); } usize = sz_sa2u(usize, alignment); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + if (unlikely(usize == 0 || usize > SC_LARGE_MAXCLASS)) { return NULL; } return ipalloct(tsdn, usize, alignment, zero, tcache, arena); @@ -1804,22 +1766,30 @@ arena_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize, void * arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, - size_t size, size_t alignment, bool zero, tcache_t *tcache) { + size_t size, size_t alignment, bool zero, tcache_t *tcache, + hook_ralloc_args_t *hook_args) { size_t usize = sz_s2u(size); - if (unlikely(usize == 0 || size > LARGE_MAXCLASS)) { + if (unlikely(usize == 0 || size > SC_LARGE_MAXCLASS)) { return NULL; } - if (likely(usize <= SMALL_MAXCLASS)) { + if (likely(usize <= SC_SMALL_MAXCLASS)) { /* Try to avoid moving the allocation. */ - if (!arena_ralloc_no_move(tsdn, ptr, oldsize, usize, 0, zero)) { + UNUSED size_t newsize; + if (!arena_ralloc_no_move(tsdn, ptr, oldsize, usize, 0, zero, + &newsize)) { + hook_invoke_expand(hook_args->is_realloc + ? hook_expand_realloc : hook_expand_rallocx, + ptr, oldsize, usize, (uintptr_t)ptr, + hook_args->args); return ptr; } } - if (oldsize >= LARGE_MINCLASS && usize >= LARGE_MINCLASS) { - return large_ralloc(tsdn, arena, iealloc(tsdn, ptr), usize, - alignment, zero, tcache); + if (oldsize >= SC_LARGE_MINCLASS + && usize >= SC_LARGE_MINCLASS) { + return large_ralloc(tsdn, arena, ptr, usize, + alignment, zero, tcache, hook_args); } /* @@ -1832,11 +1802,16 @@ arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, return NULL; } + hook_invoke_alloc(hook_args->is_realloc + ? hook_alloc_realloc : hook_alloc_rallocx, ret, (uintptr_t)ret, + hook_args->args); + hook_invoke_dalloc(hook_args->is_realloc + ? hook_dalloc_realloc : hook_dalloc_rallocx, ptr, hook_args->args); + /* * Junk/zero-filling were already done by * ipalloc()/arena_malloc(). */ - size_t copysize = (usize < oldsize) ? usize : oldsize; memcpy(ret, ptr, copysize); isdalloct(tsdn, ptr, oldsize, tcache, NULL, true); @@ -1885,6 +1860,32 @@ arena_muzzy_decay_ms_default_set(ssize_t decay_ms) { return false; } +bool +arena_retain_grow_limit_get_set(tsd_t *tsd, arena_t *arena, size_t *old_limit, + size_t *new_limit) { + assert(opt_retain); + + pszind_t new_ind JEMALLOC_CC_SILENCE_INIT(0); + if (new_limit != NULL) { + size_t limit = *new_limit; + /* Grow no more than the new limit. */ + if ((new_ind = sz_psz2ind(limit + 1) - 1) >= SC_NPSIZES) { + return true; + } + } + + malloc_mutex_lock(tsd_tsdn(tsd), &arena->extent_grow_mtx); + if (old_limit != NULL) { + *old_limit = sz_pind2sz(arena->retain_grow_limit); + } + if (new_limit != NULL) { + arena->retain_grow_limit = new_ind; + } + malloc_mutex_unlock(tsd_tsdn(tsd), &arena->extent_grow_mtx); + + return false; +} + unsigned arena_nthreads_get(arena_t *arena, bool internal) { return atomic_load_u(&arena->nthreads[internal], ATOMIC_RELAXED); @@ -1920,7 +1921,12 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { } } - arena = (arena_t *)base_alloc(tsdn, base, sizeof(arena_t), CACHELINE); + unsigned nbins_total = 0; + for (i = 0; i < SC_NBINS; i++) { + nbins_total += bin_infos[i].n_shards; + } + size_t arena_size = sizeof(arena_t) + sizeof(bin_t) * nbins_total; + arena = (arena_t *)base_alloc(tsdn, base, arena_size, CACHELINE); if (arena == NULL) { goto label_error; } @@ -1935,6 +1941,7 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { } ql_new(&arena->tcache_ql); + ql_new(&arena->cache_bin_array_descriptor_ql); if (malloc_mutex_init(&arena->tcache_ql_mtx, "tcache_ql", WITNESS_RANK_TCACHE_QL, malloc_mutex_rank_exclusive)) { goto label_error; @@ -2001,16 +2008,17 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { goto label_error; } - if (arena_decay_init(&arena->decay_dirty, &arena->extents_dirty, + if (arena_decay_init(&arena->decay_dirty, arena_dirty_decay_ms_default_get(), &arena->stats.decay_dirty)) { goto label_error; } - if (arena_decay_init(&arena->decay_muzzy, &arena->extents_muzzy, + if (arena_decay_init(&arena->decay_muzzy, arena_muzzy_decay_ms_default_get(), &arena->stats.decay_muzzy)) { goto label_error; } arena->extent_grow_next = sz_psz2ind(HUGEPAGE); + arena->retain_grow_limit = sz_psz2ind(SC_LARGE_MAXCLASS); if (malloc_mutex_init(&arena->extent_grow_mtx, "extent_grow", WITNESS_RANK_EXTENT_GROW, malloc_mutex_rank_exclusive)) { goto label_error; @@ -2023,19 +2031,20 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { } /* Initialize bins. */ - for (i = 0; i < NBINS; i++) { - arena_bin_t *bin = &arena->bins[i]; - if (malloc_mutex_init(&bin->lock, "arena_bin", - WITNESS_RANK_ARENA_BIN, malloc_mutex_rank_exclusive)) { - goto label_error; - } - bin->slabcur = NULL; - extent_heap_new(&bin->slabs_nonfull); - extent_list_init(&bin->slabs_full); - if (config_stats) { - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); + uintptr_t bin_addr = (uintptr_t)arena + sizeof(arena_t); + atomic_store_u(&arena->binshard_next, 0, ATOMIC_RELEASE); + for (i = 0; i < SC_NBINS; i++) { + unsigned nshards = bin_infos[i].n_shards; + arena->bins[i].bin_shards = (bin_t *)bin_addr; + bin_addr += nshards * sizeof(bin_t); + for (unsigned j = 0; j < nshards; j++) { + bool err = bin_init(&arena->bins[i].bin_shards[j]); + if (err) { + goto label_error; + } } } + assert(bin_addr == (uintptr_t)arena + arena_size); arena->base = base; /* Set arena before creating background threads. */ @@ -2052,8 +2061,8 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { */ assert(!tsdn_null(tsdn)); pre_reentrancy(tsdn_tsd(tsdn), arena); - if (hooks_arena_new_hook) { - hooks_arena_new_hook(); + if (test_hooks_arena_new_hook) { + test_hooks_arena_new_hook(); } post_reentrancy(tsdn_tsd(tsdn)); } @@ -2066,10 +2075,75 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { return NULL; } +arena_t * +arena_choose_huge(tsd_t *tsd) { + /* huge_arena_ind can be 0 during init (will use a0). */ + if (huge_arena_ind == 0) { + assert(!malloc_initialized()); + } + + arena_t *huge_arena = arena_get(tsd_tsdn(tsd), huge_arena_ind, false); + if (huge_arena == NULL) { + /* Create the huge arena on demand. */ + assert(huge_arena_ind != 0); + huge_arena = arena_get(tsd_tsdn(tsd), huge_arena_ind, true); + if (huge_arena == NULL) { + return NULL; + } + /* + * Purge eagerly for huge allocations, because: 1) number of + * huge allocations is usually small, which means ticker based + * decay is not reliable; and 2) less immediate reuse is + * expected for huge allocations. + */ + if (arena_dirty_decay_ms_default_get() > 0) { + arena_dirty_decay_ms_set(tsd_tsdn(tsd), huge_arena, 0); + } + if (arena_muzzy_decay_ms_default_get() > 0) { + arena_muzzy_decay_ms_set(tsd_tsdn(tsd), huge_arena, 0); + } + } + + return huge_arena; +} + +bool +arena_init_huge(void) { + bool huge_enabled; + + /* The threshold should be large size class. */ + if (opt_oversize_threshold > SC_LARGE_MAXCLASS || + opt_oversize_threshold < SC_LARGE_MINCLASS) { + opt_oversize_threshold = 0; + oversize_threshold = SC_LARGE_MAXCLASS + PAGE; + huge_enabled = false; + } else { + /* Reserve the index for the huge arena. */ + huge_arena_ind = narenas_total_get(); + oversize_threshold = opt_oversize_threshold; + huge_enabled = true; + } + + return huge_enabled; +} + +bool +arena_is_huge(unsigned arena_ind) { + if (huge_arena_ind == 0) { + return false; + } + return (arena_ind == huge_arena_ind); +} + void -arena_boot(void) { +arena_boot(sc_data_t *sc_data) { arena_dirty_decay_ms_default_set(opt_dirty_decay_ms); arena_muzzy_decay_ms_default_set(opt_muzzy_decay_ms); + for (unsigned i = 0; i < SC_NBINS; i++) { + sc_t *sc = &sc_data->sc[i]; + div_init(&arena_binind_div_info[i], + (1U << sc->lg_base) + (sc->ndelta << sc->lg_delta)); + } } void @@ -2114,8 +2188,10 @@ arena_prefork6(tsdn_t *tsdn, arena_t *arena) { void arena_prefork7(tsdn_t *tsdn, arena_t *arena) { - for (unsigned i = 0; i < NBINS; i++) { - malloc_mutex_prefork(tsdn, &arena->bins[i].lock); + for (unsigned i = 0; i < SC_NBINS; i++) { + for (unsigned j = 0; j < bin_infos[i].n_shards; j++) { + bin_prefork(tsdn, &arena->bins[i].bin_shards[j]); + } } } @@ -2123,8 +2199,11 @@ void arena_postfork_parent(tsdn_t *tsdn, arena_t *arena) { unsigned i; - for (i = 0; i < NBINS; i++) { - malloc_mutex_postfork_parent(tsdn, &arena->bins[i].lock); + for (i = 0; i < SC_NBINS; i++) { + for (unsigned j = 0; j < bin_infos[i].n_shards; j++) { + bin_postfork_parent(tsdn, + &arena->bins[i].bin_shards[j]); + } } malloc_mutex_postfork_parent(tsdn, &arena->large_mtx); base_postfork_parent(tsdn, arena->base); @@ -2154,15 +2233,23 @@ arena_postfork_child(tsdn_t *tsdn, arena_t *arena) { } if (config_stats) { ql_new(&arena->tcache_ql); + ql_new(&arena->cache_bin_array_descriptor_ql); tcache_t *tcache = tcache_get(tsdn_tsd(tsdn)); if (tcache != NULL && tcache->arena == arena) { ql_elm_new(tcache, link); ql_tail_insert(&arena->tcache_ql, tcache, link); + cache_bin_array_descriptor_init( + &tcache->cache_bin_array_descriptor, + tcache->bins_small, tcache->bins_large); + ql_tail_insert(&arena->cache_bin_array_descriptor_ql, + &tcache->cache_bin_array_descriptor, link); } } - for (i = 0; i < NBINS; i++) { - malloc_mutex_postfork_child(tsdn, &arena->bins[i].lock); + for (i = 0; i < SC_NBINS; i++) { + for (unsigned j = 0; j < bin_infos[i].n_shards; j++) { + bin_postfork_child(tsdn, &arena->bins[i].bin_shards[j]); + } } malloc_mutex_postfork_child(tsdn, &arena->large_mtx); base_postfork_child(tsdn, arena->base); diff --git a/kbe/src/lib/dependencies/jemalloc/src/background_thread.c b/kbe/src/lib/dependencies/jemalloc/src/background_thread.c index eb30eb5b42..5ed6c1c959 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/background_thread.c +++ b/kbe/src/lib/dependencies/jemalloc/src/background_thread.c @@ -4,6 +4,8 @@ #include "jemalloc/internal/assert.h" +JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS + /******************************************************************************/ /* Data. */ @@ -11,38 +13,37 @@ #define BACKGROUND_THREAD_DEFAULT false /* Read-only after initialization. */ bool opt_background_thread = BACKGROUND_THREAD_DEFAULT; +size_t opt_max_background_threads = MAX_BACKGROUND_THREAD_LIMIT + 1; /* Used for thread creation, termination and stats. */ malloc_mutex_t background_thread_lock; /* Indicates global state. Atomic because decay reads this w/o locking. */ atomic_b_t background_thread_enabled_state; size_t n_background_threads; +size_t max_background_threads; /* Thread info per-index. */ background_thread_info_t *background_thread_info; -/* False if no necessary runtime support. */ -bool can_enable_background_thread; - /******************************************************************************/ #ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER -#include static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, void *(*)(void *), void *__restrict); -static pthread_once_t once_control = PTHREAD_ONCE_INIT; static void -pthread_create_wrapper_once(void) { +pthread_create_wrapper_init(void) { #ifdef JEMALLOC_LAZY_LOCK - isthreaded = true; + if (!isthreaded) { + isthreaded = true; + } #endif } int pthread_create_wrapper(pthread_t *__restrict thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *__restrict arg) { - pthread_once(&once_control, pthread_create_wrapper_once); + pthread_create_wrapper_init(); return pthread_create_fptr(thread, attr, start_routine, arg); } @@ -78,7 +79,7 @@ background_thread_info_init(tsdn_t *tsdn, background_thread_info_t *info) { } static inline bool -set_current_thread_affinity(UNUSED int cpu) { +set_current_thread_affinity(int cpu) { #if defined(JEMALLOC_HAVE_SCHED_SETAFFINITY) cpu_set_t cpuset; CPU_ZERO(&cpuset); @@ -286,7 +287,7 @@ background_work_sleep_once(tsdn_t *tsdn, background_thread_info_t *info, unsigne uint64_t min_interval = BACKGROUND_THREAD_INDEFINITE_SLEEP; unsigned narenas = narenas_total_get(); - for (unsigned i = ind; i < narenas; i += ncpus) { + for (unsigned i = ind; i < narenas; i += max_background_threads) { arena_t *arena = arena_get(tsdn, i, false); if (!arena) { continue; @@ -379,35 +380,32 @@ background_thread_create_signals_masked(pthread_t *thread, return create_err; } -static void +static bool check_background_thread_creation(tsd_t *tsd, unsigned *n_created, bool *created_threads) { + bool ret = false; if (likely(*n_created == n_background_threads)) { - return; + return ret; } - malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_info[0].mtx); -label_restart: - malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); - for (unsigned i = 1; i < ncpus; i++) { + tsdn_t *tsdn = tsd_tsdn(tsd); + malloc_mutex_unlock(tsdn, &background_thread_info[0].mtx); + for (unsigned i = 1; i < max_background_threads; i++) { if (created_threads[i]) { continue; } background_thread_info_t *info = &background_thread_info[i]; - malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); - assert(info->state != background_thread_paused); + malloc_mutex_lock(tsdn, &info->mtx); + /* + * In case of the background_thread_paused state because of + * arena reset, delay the creation. + */ bool create = (info->state == background_thread_started); - malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + malloc_mutex_unlock(tsdn, &info->mtx); if (!create) { continue; } - /* - * To avoid deadlock with prefork handlers (which waits for the - * mutex held here), unlock before calling pthread_create(). - */ - malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); - pre_reentrancy(tsd, NULL); int err = background_thread_create_signals_masked(&info->thread, NULL, background_thread_entry, (void *)(uintptr_t)i); @@ -423,19 +421,21 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created, abort(); } } - /* Restart since we unlocked. */ - goto label_restart; + /* Return to restart the loop since we unlocked. */ + ret = true; + break; } - malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_info[0].mtx); - malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); + malloc_mutex_lock(tsdn, &background_thread_info[0].mtx); + + return ret; } static void background_thread0_work(tsd_t *tsd) { /* Thread0 is also responsible for launching / terminating threads. */ - VARIABLE_ARRAY(bool, created_threads, ncpus); + VARIABLE_ARRAY(bool, created_threads, max_background_threads); unsigned i; - for (i = 1; i < ncpus; i++) { + for (i = 1; i < max_background_threads; i++) { created_threads[i] = false; } /* Start working, and create more threads when asked. */ @@ -445,8 +445,10 @@ background_thread0_work(tsd_t *tsd) { &background_thread_info[0])) { continue; } - check_background_thread_creation(tsd, &n_created, - (bool *)&created_threads); + if (check_background_thread_creation(tsd, &n_created, + (bool *)&created_threads)) { + continue; + } background_work_sleep_once(tsd_tsdn(tsd), &background_thread_info[0], 0); } @@ -456,15 +458,20 @@ background_thread0_work(tsd_t *tsd) { * the global background_thread mutex (and is waiting) for us. */ assert(!background_thread_enabled()); - for (i = 1; i < ncpus; i++) { + for (i = 1; i < max_background_threads; i++) { background_thread_info_t *info = &background_thread_info[i]; assert(info->state != background_thread_paused); if (created_threads[i]) { background_threads_disable_single(tsd, info); } else { malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); - /* Clear in case the thread wasn't created. */ - info->state = background_thread_stopped; + if (info->state != background_thread_stopped) { + /* The thread was not created. */ + assert(info->state == + background_thread_started); + n_background_threads--; + info->state = background_thread_stopped; + } malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); } } @@ -498,9 +505,11 @@ background_work(tsd_t *tsd, unsigned ind) { static void * background_thread_entry(void *ind_arg) { unsigned thread_ind = (unsigned)(uintptr_t)ind_arg; - assert(thread_ind < ncpus); + assert(thread_ind < max_background_threads); #ifdef JEMALLOC_HAVE_PTHREAD_SETNAME_NP pthread_setname_np(pthread_self(), "jemalloc_bg_thd"); +#elif defined(__FreeBSD__) + pthread_set_name_np(pthread_self(), "jemalloc_bg_thd"); #endif if (opt_percpu_arena != percpu_arena_disabled) { set_current_thread_affinity((int)thread_ind); @@ -525,14 +534,13 @@ background_thread_init(tsd_t *tsd, background_thread_info_t *info) { n_background_threads++; } -/* Create a new background thread if needed. */ -bool -background_thread_create(tsd_t *tsd, unsigned arena_ind) { +static bool +background_thread_create_locked(tsd_t *tsd, unsigned arena_ind) { assert(have_background_thread); malloc_mutex_assert_owner(tsd_tsdn(tsd), &background_thread_lock); /* We create at most NCPUs threads. */ - size_t thread_ind = arena_ind % ncpus; + size_t thread_ind = arena_ind % max_background_threads; background_thread_info_t *info = &background_thread_info[thread_ind]; bool need_new_thread; @@ -580,37 +588,53 @@ background_thread_create(tsd_t *tsd, unsigned arena_ind) { return false; } +/* Create a new background thread if needed. */ +bool +background_thread_create(tsd_t *tsd, unsigned arena_ind) { + assert(have_background_thread); + + bool ret; + malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); + ret = background_thread_create_locked(tsd, arena_ind); + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); + + return ret; +} + bool background_threads_enable(tsd_t *tsd) { assert(n_background_threads == 0); assert(background_thread_enabled()); malloc_mutex_assert_owner(tsd_tsdn(tsd), &background_thread_lock); - VARIABLE_ARRAY(bool, marked, ncpus); + VARIABLE_ARRAY(bool, marked, max_background_threads); unsigned i, nmarked; - for (i = 0; i < ncpus; i++) { + for (i = 0; i < max_background_threads; i++) { marked[i] = false; } nmarked = 0; + /* Thread 0 is required and created at the end. */ + marked[0] = true; /* Mark the threads we need to create for thread 0. */ unsigned n = narenas_total_get(); for (i = 1; i < n; i++) { - if (marked[i % ncpus] || + if (marked[i % max_background_threads] || arena_get(tsd_tsdn(tsd), i, false) == NULL) { continue; } - background_thread_info_t *info = &background_thread_info[i]; + background_thread_info_t *info = &background_thread_info[ + i % max_background_threads]; malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); assert(info->state == background_thread_stopped); background_thread_init(tsd, info); malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); - marked[i % ncpus] = true; - if (++nmarked == ncpus) { + marked[i % max_background_threads] = true; + if (++nmarked == max_background_threads) { break; } } - return background_thread_create(tsd, 0); + return background_thread_create_locked(tsd, 0); } bool @@ -720,14 +744,14 @@ background_thread_prefork0(tsdn_t *tsdn) { void background_thread_prefork1(tsdn_t *tsdn) { - for (unsigned i = 0; i < ncpus; i++) { + for (unsigned i = 0; i < max_background_threads; i++) { malloc_mutex_prefork(tsdn, &background_thread_info[i].mtx); } } void background_thread_postfork_parent(tsdn_t *tsdn) { - for (unsigned i = 0; i < ncpus; i++) { + for (unsigned i = 0; i < max_background_threads; i++) { malloc_mutex_postfork_parent(tsdn, &background_thread_info[i].mtx); } @@ -736,7 +760,7 @@ background_thread_postfork_parent(tsdn_t *tsdn) { void background_thread_postfork_child(tsdn_t *tsdn) { - for (unsigned i = 0; i < ncpus; i++) { + for (unsigned i = 0; i < max_background_threads; i++) { malloc_mutex_postfork_child(tsdn, &background_thread_info[i].mtx); } @@ -749,7 +773,7 @@ background_thread_postfork_child(tsdn_t *tsdn) { malloc_mutex_lock(tsdn, &background_thread_lock); n_background_threads = 0; background_thread_enabled_set(tsdn, false); - for (unsigned i = 0; i < ncpus; i++) { + for (unsigned i = 0; i < max_background_threads; i++) { background_thread_info_t *info = &background_thread_info[i]; malloc_mutex_lock(tsdn, &info->mtx); info->state = background_thread_stopped; @@ -773,7 +797,7 @@ background_thread_stats_read(tsdn_t *tsdn, background_thread_stats_t *stats) { stats->num_threads = n_background_threads; uint64_t num_runs = 0; nstime_init(&stats->run_interval, 0); - for (unsigned i = 0; i < ncpus; i++) { + for (unsigned i = 0; i < max_background_threads; i++) { background_thread_info_t *info = &background_thread_info[i]; malloc_mutex_lock(tsdn, &info->mtx); if (info->state != background_thread_stopped) { @@ -795,6 +819,39 @@ background_thread_stats_read(tsdn_t *tsdn, background_thread_stats_t *stats) { #undef BILLION #undef BACKGROUND_THREAD_MIN_INTERVAL_NS +#ifdef JEMALLOC_HAVE_DLSYM +#include +#endif + +static bool +pthread_create_fptr_init(void) { + if (pthread_create_fptr != NULL) { + return false; + } + /* + * Try the next symbol first, because 1) when use lazy_lock we have a + * wrapper for pthread_create; and 2) application may define its own + * wrapper as well (and can call malloc within the wrapper). + */ +#ifdef JEMALLOC_HAVE_DLSYM + pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); +#else + pthread_create_fptr = NULL; +#endif + if (pthread_create_fptr == NULL) { + if (config_lazy_lock) { + malloc_write(": Error in dlsym(RTLD_NEXT, " + "\"pthread_create\")\n"); + abort(); + } else { + /* Fall back to the default symbol. */ + pthread_create_fptr = pthread_create; + } + } + + return false; +} + /* * When lazy lock is enabled, we need to make sure setting isthreaded before * taking any background_thread locks. This is called early in ctl (instead of @@ -805,7 +862,8 @@ void background_thread_ctl_init(tsdn_t *tsdn) { malloc_mutex_assert_not_owner(tsdn, &background_thread_lock); #ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER - pthread_once(&once_control, pthread_create_wrapper_once); + pthread_create_fptr_init(); + pthread_create_wrapper_init(); #endif } @@ -818,18 +876,10 @@ background_thread_boot0(void) { "supports pthread only\n"); return true; } - #ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER - pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); - if (pthread_create_fptr == NULL) { - can_enable_background_thread = false; - if (config_lazy_lock || opt_background_thread) { - malloc_write(": Error in dlsym(RTLD_NEXT, " - "\"pthread_create\")\n"); - abort(); - } - } else { - can_enable_background_thread = true; + if ((config_lazy_lock || opt_background_thread) && + pthread_create_fptr_init()) { + return true; } #endif return false; @@ -841,6 +891,11 @@ background_thread_boot1(tsdn_t *tsdn) { assert(have_background_thread); assert(narenas_total_get() > 0); + if (opt_max_background_threads > MAX_BACKGROUND_THREAD_LIMIT) { + opt_max_background_threads = DEFAULT_NUM_BACKGROUND_THREAD; + } + max_background_threads = opt_max_background_threads; + background_thread_enabled_set(tsdn, opt_background_thread); if (malloc_mutex_init(&background_thread_lock, "background_thread_global", @@ -848,17 +903,15 @@ background_thread_boot1(tsdn_t *tsdn) { malloc_mutex_rank_exclusive)) { return true; } - if (opt_background_thread) { - background_thread_ctl_init(tsdn); - } background_thread_info = (background_thread_info_t *)base_alloc(tsdn, - b0get(), ncpus * sizeof(background_thread_info_t), CACHELINE); + b0get(), opt_max_background_threads * + sizeof(background_thread_info_t), CACHELINE); if (background_thread_info == NULL) { return true; } - for (unsigned i = 0; i < ncpus; i++) { + for (unsigned i = 0; i < max_background_threads; i++) { background_thread_info_t *info = &background_thread_info[i]; /* Thread mutex is rank_inclusive because of thread0. */ if (malloc_mutex_init(&info->mtx, "background_thread", diff --git a/kbe/src/lib/dependencies/jemalloc/src/base.c b/kbe/src/lib/dependencies/jemalloc/src/base.c index 97078b134d..f3c61661a2 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/base.c +++ b/kbe/src/lib/dependencies/jemalloc/src/base.c @@ -10,25 +10,40 @@ /******************************************************************************/ /* Data. */ -static base_t *b0; +static base_t *b0; + +metadata_thp_mode_t opt_metadata_thp = METADATA_THP_DEFAULT; + +const char *metadata_thp_mode_names[] = { + "disabled", + "auto", + "always" +}; /******************************************************************************/ +static inline bool +metadata_thp_madvise(void) { + return (metadata_thp_enabled() && + (init_system_thp_mode == thp_mode_default)); +} + static void * base_map(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, size_t size) { void *addr; bool zero = true; bool commit = true; + /* Use huge page sizes and alignment regardless of opt_metadata_thp. */ assert(size == HUGEPAGE_CEILING(size)); - + size_t alignment = HUGEPAGE; if (extent_hooks == &extent_hooks_default) { - addr = extent_alloc_mmap(NULL, size, PAGE, &zero, &commit); + addr = extent_alloc_mmap(NULL, size, alignment, &zero, &commit); } else { /* No arena context as we are creating new arenas. */ tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn); pre_reentrancy(tsd, NULL); - addr = extent_hooks->alloc(extent_hooks, NULL, size, PAGE, + addr = extent_hooks->alloc(extent_hooks, NULL, size, alignment, &zero, &commit, ind); post_reentrancy(tsd); } @@ -51,16 +66,16 @@ base_unmap(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, void *addr, */ if (extent_hooks == &extent_hooks_default) { if (!extent_dalloc_mmap(addr, size)) { - return; + goto label_done; } if (!pages_decommit(addr, size)) { - return; + goto label_done; } if (!pages_purge_forced(addr, size)) { - return; + goto label_done; } if (!pages_purge_lazy(addr, size)) { - return; + goto label_done; } /* Nothing worked. This should never happen. */ not_reached(); @@ -70,27 +85,33 @@ base_unmap(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, void *addr, if (extent_hooks->dalloc != NULL && !extent_hooks->dalloc(extent_hooks, addr, size, true, ind)) { - goto label_done; + goto label_post_reentrancy; } if (extent_hooks->decommit != NULL && !extent_hooks->decommit(extent_hooks, addr, size, 0, size, ind)) { - goto label_done; + goto label_post_reentrancy; } if (extent_hooks->purge_forced != NULL && !extent_hooks->purge_forced(extent_hooks, addr, size, 0, size, ind)) { - goto label_done; + goto label_post_reentrancy; } if (extent_hooks->purge_lazy != NULL && !extent_hooks->purge_lazy(extent_hooks, addr, size, 0, size, ind)) { - goto label_done; + goto label_post_reentrancy; } /* Nothing worked. That's the application's problem. */ - label_done: + label_post_reentrancy: post_reentrancy(tsd); - return; + } +label_done: + if (metadata_thp_madvise()) { + /* Set NOHUGEPAGE after unmap to avoid kernel defrag. */ + assert(((uintptr_t)addr & HUGEPAGE_MASK) == 0 && + (size & HUGEPAGE_MASK) == 0); + pages_nohuge(addr, size); } } @@ -105,6 +126,56 @@ base_extent_init(size_t *extent_sn_next, extent_t *extent, void *addr, extent_binit(extent, addr, size, sn); } +static size_t +base_get_num_blocks(base_t *base, bool with_new_block) { + base_block_t *b = base->blocks; + assert(b != NULL); + + size_t n_blocks = with_new_block ? 2 : 1; + while (b->next != NULL) { + n_blocks++; + b = b->next; + } + + return n_blocks; +} + +static void +base_auto_thp_switch(tsdn_t *tsdn, base_t *base) { + assert(opt_metadata_thp == metadata_thp_auto); + malloc_mutex_assert_owner(tsdn, &base->mtx); + if (base->auto_thp_switched) { + return; + } + /* Called when adding a new block. */ + bool should_switch; + if (base_ind_get(base) != 0) { + should_switch = (base_get_num_blocks(base, true) == + BASE_AUTO_THP_THRESHOLD); + } else { + should_switch = (base_get_num_blocks(base, true) == + BASE_AUTO_THP_THRESHOLD_A0); + } + if (!should_switch) { + return; + } + + base->auto_thp_switched = true; + assert(!config_stats || base->n_thp == 0); + /* Make the initial blocks THP lazily. */ + base_block_t *block = base->blocks; + while (block != NULL) { + assert((block->size & HUGEPAGE_MASK) == 0); + pages_huge(block, block->size); + if (config_stats) { + base->n_thp += HUGEPAGE_CEILING(block->size - + extent_bsize_get(&block->extent)) >> LG_HUGEPAGE; + } + block = block->next; + assert(block == NULL || (base_ind_get(base) == 0)); + } +} + static void * base_extent_bump_alloc_helper(extent_t *extent, size_t *gap_size, size_t size, size_t alignment) { @@ -124,8 +195,8 @@ base_extent_bump_alloc_helper(extent_t *extent, size_t *gap_size, size_t size, } static void -base_extent_bump_alloc_post(tsdn_t *tsdn, base_t *base, extent_t *extent, - size_t gap_size, void *addr, size_t size) { +base_extent_bump_alloc_post(base_t *base, extent_t *extent, size_t gap_size, + void *addr, size_t size) { if (extent_bsize_get(extent) > 0) { /* * Compute the index for the largest size class that does not @@ -140,23 +211,31 @@ base_extent_bump_alloc_post(tsdn_t *tsdn, base_t *base, extent_t *extent, base->allocated += size; /* * Add one PAGE to base_resident for every page boundary that is - * crossed by the new allocation. + * crossed by the new allocation. Adjust n_thp similarly when + * metadata_thp is enabled. */ base->resident += PAGE_CEILING((uintptr_t)addr + size) - PAGE_CEILING((uintptr_t)addr - gap_size); assert(base->allocated <= base->resident); assert(base->resident <= base->mapped); + if (metadata_thp_madvise() && (opt_metadata_thp == + metadata_thp_always || base->auto_thp_switched)) { + base->n_thp += (HUGEPAGE_CEILING((uintptr_t)addr + size) + - HUGEPAGE_CEILING((uintptr_t)addr - gap_size)) >> + LG_HUGEPAGE; + assert(base->mapped >= base->n_thp << LG_HUGEPAGE); + } } } static void * -base_extent_bump_alloc(tsdn_t *tsdn, base_t *base, extent_t *extent, - size_t size, size_t alignment) { +base_extent_bump_alloc(base_t *base, extent_t *extent, size_t size, + size_t alignment) { void *ret; size_t gap_size; ret = base_extent_bump_alloc_helper(extent, &gap_size, size, alignment); - base_extent_bump_alloc_post(tsdn, base, extent, gap_size, ret, size); + base_extent_bump_alloc_post(base, extent, gap_size, ret, size); return ret; } @@ -166,8 +245,8 @@ base_extent_bump_alloc(tsdn_t *tsdn, base_t *base, extent_t *extent, * On success a pointer to the initialized base_block_t header is returned. */ static base_block_t * -base_block_alloc(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, - pszind_t *pind_last, size_t *extent_sn_next, size_t size, +base_block_alloc(tsdn_t *tsdn, base_t *base, extent_hooks_t *extent_hooks, + unsigned ind, pszind_t *pind_last, size_t *extent_sn_next, size_t size, size_t alignment) { alignment = ALIGNMENT_CEILING(alignment, QUANTUM); size_t usize = ALIGNMENT_CEILING(size, alignment); @@ -183,8 +262,8 @@ base_block_alloc(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, */ size_t min_block_size = HUGEPAGE_CEILING(sz_psz2u(header_size + gap_size + usize)); - pszind_t pind_next = (*pind_last + 1 < NPSIZES) ? *pind_last + 1 : - *pind_last; + pszind_t pind_next = (*pind_last + 1 < sz_psz2ind(SC_LARGE_MAXCLASS)) ? + *pind_last + 1 : *pind_last; size_t next_block_size = HUGEPAGE_CEILING(sz_pind2sz(pind_next)); size_t block_size = (min_block_size > next_block_size) ? min_block_size : next_block_size; @@ -193,6 +272,25 @@ base_block_alloc(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, if (block == NULL) { return NULL; } + + if (metadata_thp_madvise()) { + void *addr = (void *)block; + assert(((uintptr_t)addr & HUGEPAGE_MASK) == 0 && + (block_size & HUGEPAGE_MASK) == 0); + if (opt_metadata_thp == metadata_thp_always) { + pages_huge(addr, block_size); + } else if (opt_metadata_thp == metadata_thp_auto && + base != NULL) { + /* base != NULL indicates this is not a new base. */ + malloc_mutex_lock(tsdn, &base->mtx); + base_auto_thp_switch(tsdn, base); + if (base->auto_thp_switched) { + pages_huge(addr, block_size); + } + malloc_mutex_unlock(tsdn, &base->mtx); + } + } + *pind_last = sz_psz2ind(block_size); block->size = block_size; block->next = NULL; @@ -216,7 +314,7 @@ base_extent_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) { * called. */ malloc_mutex_unlock(tsdn, &base->mtx); - base_block_t *block = base_block_alloc(tsdn, extent_hooks, + base_block_t *block = base_block_alloc(tsdn, base, extent_hooks, base_ind_get(base), &base->pind_last, &base->extent_sn_next, size, alignment); malloc_mutex_lock(tsdn, &base->mtx); @@ -229,8 +327,16 @@ base_extent_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) { base->allocated += sizeof(base_block_t); base->resident += PAGE_CEILING(sizeof(base_block_t)); base->mapped += block->size; + if (metadata_thp_madvise() && + !(opt_metadata_thp == metadata_thp_auto + && !base->auto_thp_switched)) { + assert(base->n_thp > 0); + base->n_thp += HUGEPAGE_CEILING(sizeof(base_block_t)) >> + LG_HUGEPAGE; + } assert(base->allocated <= base->resident); assert(base->resident <= base->mapped); + assert(base->n_thp << LG_HUGEPAGE <= base->mapped); } return &block->extent; } @@ -244,7 +350,7 @@ base_t * base_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { pszind_t pind_last = 0; size_t extent_sn_next = 0; - base_block_t *block = base_block_alloc(tsdn, extent_hooks, ind, + base_block_t *block = base_block_alloc(tsdn, NULL, extent_hooks, ind, &pind_last, &extent_sn_next, sizeof(base_t), QUANTUM); if (block == NULL) { return NULL; @@ -265,17 +371,22 @@ base_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { base->pind_last = pind_last; base->extent_sn_next = extent_sn_next; base->blocks = block; - for (szind_t i = 0; i < NSIZES; i++) { + base->auto_thp_switched = false; + for (szind_t i = 0; i < SC_NSIZES; i++) { extent_heap_new(&base->avail[i]); } if (config_stats) { base->allocated = sizeof(base_block_t); base->resident = PAGE_CEILING(sizeof(base_block_t)); base->mapped = block->size; + base->n_thp = (opt_metadata_thp == metadata_thp_always) && + metadata_thp_madvise() ? HUGEPAGE_CEILING(sizeof(base_block_t)) + >> LG_HUGEPAGE : 0; assert(base->allocated <= base->resident); assert(base->resident <= base->mapped); + assert(base->n_thp << LG_HUGEPAGE <= base->mapped); } - base_extent_bump_alloc_post(tsdn, base, &block->extent, gap_size, base, + base_extent_bump_alloc_post(base, &block->extent, gap_size, base, base_size); return base; @@ -315,7 +426,7 @@ base_alloc_impl(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment, extent_t *extent = NULL; malloc_mutex_lock(tsdn, &base->mtx); - for (szind_t i = sz_size2index(asize); i < NSIZES; i++) { + for (szind_t i = sz_size2index(asize); i < SC_NSIZES; i++) { extent = extent_heap_remove_first(&base->avail[i]); if (extent != NULL) { /* Use existing space. */ @@ -332,7 +443,7 @@ base_alloc_impl(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment, goto label_return; } - ret = base_extent_bump_alloc(tsdn, base, extent, usize, alignment); + ret = base_extent_bump_alloc(base, extent, usize, alignment); if (esn != NULL) { *esn = extent_sn_get(extent); } @@ -368,7 +479,7 @@ base_alloc_extent(tsdn_t *tsdn, base_t *base) { void base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, size_t *resident, - size_t *mapped) { + size_t *mapped, size_t *n_thp) { cassert(config_stats); malloc_mutex_lock(tsdn, &base->mtx); @@ -377,6 +488,7 @@ base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, size_t *resident, *allocated = base->allocated; *resident = base->resident; *mapped = base->mapped; + *n_thp = base->n_thp; malloc_mutex_unlock(tsdn, &base->mtx); } diff --git a/kbe/src/lib/dependencies/jemalloc/src/bin.c b/kbe/src/lib/dependencies/jemalloc/src/bin.c new file mode 100644 index 0000000000..bca6b12c35 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/src/bin.c @@ -0,0 +1,95 @@ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/bin.h" +#include "jemalloc/internal/sc.h" +#include "jemalloc/internal/witness.h" + +bin_info_t bin_infos[SC_NBINS]; + +static void +bin_infos_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], + bin_info_t bin_infos[SC_NBINS]) { + for (unsigned i = 0; i < SC_NBINS; i++) { + bin_info_t *bin_info = &bin_infos[i]; + sc_t *sc = &sc_data->sc[i]; + bin_info->reg_size = ((size_t)1U << sc->lg_base) + + ((size_t)sc->ndelta << sc->lg_delta); + bin_info->slab_size = (sc->pgs << LG_PAGE); + bin_info->nregs = + (uint32_t)(bin_info->slab_size / bin_info->reg_size); + bin_info->n_shards = bin_shard_sizes[i]; + bitmap_info_t bitmap_info = BITMAP_INFO_INITIALIZER( + bin_info->nregs); + bin_info->bitmap_info = bitmap_info; + } +} + +bool +bin_update_shard_size(unsigned bin_shard_sizes[SC_NBINS], size_t start_size, + size_t end_size, size_t nshards) { + if (nshards > BIN_SHARDS_MAX || nshards == 0) { + return true; + } + + if (start_size > SC_SMALL_MAXCLASS) { + return false; + } + if (end_size > SC_SMALL_MAXCLASS) { + end_size = SC_SMALL_MAXCLASS; + } + + /* Compute the index since this may happen before sz init. */ + szind_t ind1 = sz_size2index_compute(start_size); + szind_t ind2 = sz_size2index_compute(end_size); + for (unsigned i = ind1; i <= ind2; i++) { + bin_shard_sizes[i] = (unsigned)nshards; + } + + return false; +} + +void +bin_shard_sizes_boot(unsigned bin_shard_sizes[SC_NBINS]) { + /* Load the default number of shards. */ + for (unsigned i = 0; i < SC_NBINS; i++) { + bin_shard_sizes[i] = N_BIN_SHARDS_DEFAULT; + } +} + +void +bin_boot(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) { + assert(sc_data->initialized); + bin_infos_init(sc_data, bin_shard_sizes, bin_infos); +} + +bool +bin_init(bin_t *bin) { + if (malloc_mutex_init(&bin->lock, "bin", WITNESS_RANK_BIN, + malloc_mutex_rank_exclusive)) { + return true; + } + bin->slabcur = NULL; + extent_heap_new(&bin->slabs_nonfull); + extent_list_init(&bin->slabs_full); + if (config_stats) { + memset(&bin->stats, 0, sizeof(bin_stats_t)); + } + return false; +} + +void +bin_prefork(tsdn_t *tsdn, bin_t *bin) { + malloc_mutex_prefork(tsdn, &bin->lock); +} + +void +bin_postfork_parent(tsdn_t *tsdn, bin_t *bin) { + malloc_mutex_postfork_parent(tsdn, &bin->lock); +} + +void +bin_postfork_child(tsdn_t *tsdn, bin_t *bin) { + malloc_mutex_postfork_child(tsdn, &bin->lock); +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/ckh.c b/kbe/src/lib/dependencies/jemalloc/src/ckh.c index e95e0a3ed5..1bf6df5a11 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/ckh.c +++ b/kbe/src/lib/dependencies/jemalloc/src/ckh.c @@ -275,7 +275,8 @@ ckh_grow(tsd_t *tsd, ckh_t *ckh) { lg_curcells++; usize = sz_sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + if (unlikely(usize == 0 + || usize > SC_LARGE_MAXCLASS)) { ret = true; goto label_return; } @@ -320,7 +321,7 @@ ckh_shrink(tsd_t *tsd, ckh_t *ckh) { lg_prevbuckets = ckh->lg_curbuckets; lg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS - 1; usize = sz_sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + if (unlikely(usize == 0 || usize > SC_LARGE_MAXCLASS)) { return; } tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, true, NULL, @@ -396,7 +397,7 @@ ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh->keycomp = keycomp; usize = sz_sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + if (unlikely(usize == 0 || usize > SC_LARGE_MAXCLASS)) { ret = true; goto label_return; } diff --git a/kbe/src/lib/dependencies/jemalloc/src/ctl.c b/kbe/src/lib/dependencies/jemalloc/src/ctl.c index 36bc8fb5b7..09310a9d19 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/ctl.c +++ b/kbe/src/lib/dependencies/jemalloc/src/ctl.c @@ -8,7 +8,7 @@ #include "jemalloc/internal/extent_mmap.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/nstime.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/util.h" /******************************************************************************/ @@ -57,6 +57,7 @@ static const ctl_named_node_t *n##_index(tsdn_t *tsdn, \ CTL_PROTO(version) CTL_PROTO(epoch) CTL_PROTO(background_thread) +CTL_PROTO(max_background_threads) CTL_PROTO(thread_tcache_enabled) CTL_PROTO(thread_tcache_flush) CTL_PROTO(thread_prof_name) @@ -75,16 +76,18 @@ CTL_PROTO(config_prof) CTL_PROTO(config_prof_libgcc) CTL_PROTO(config_prof_libunwind) CTL_PROTO(config_stats) -CTL_PROTO(config_thp) CTL_PROTO(config_utrace) CTL_PROTO(config_xmalloc) CTL_PROTO(opt_abort) CTL_PROTO(opt_abort_conf) +CTL_PROTO(opt_metadata_thp) CTL_PROTO(opt_retain) CTL_PROTO(opt_dss) CTL_PROTO(opt_narenas) CTL_PROTO(opt_percpu_arena) +CTL_PROTO(opt_oversize_threshold) CTL_PROTO(opt_background_thread) +CTL_PROTO(opt_max_background_threads) CTL_PROTO(opt_dirty_decay_ms) CTL_PROTO(opt_muzzy_decay_ms) CTL_PROTO(opt_stats_print) @@ -94,6 +97,8 @@ CTL_PROTO(opt_zero) CTL_PROTO(opt_utrace) CTL_PROTO(opt_xmalloc) CTL_PROTO(opt_tcache) +CTL_PROTO(opt_thp) +CTL_PROTO(opt_lg_extent_max_active_fit) CTL_PROTO(opt_lg_tcache_max) CTL_PROTO(opt_prof) CTL_PROTO(opt_prof_prefix) @@ -117,10 +122,12 @@ CTL_PROTO(arena_i_dss) CTL_PROTO(arena_i_dirty_decay_ms) CTL_PROTO(arena_i_muzzy_decay_ms) CTL_PROTO(arena_i_extent_hooks) +CTL_PROTO(arena_i_retain_grow_limit) INDEX_PROTO(arena_i) CTL_PROTO(arenas_bin_i_size) CTL_PROTO(arenas_bin_i_nregs) CTL_PROTO(arenas_bin_i_slab_size) +CTL_PROTO(arenas_bin_i_nshards) INDEX_PROTO(arenas_bin_i) CTL_PROTO(arenas_lextent_i_size) INDEX_PROTO(arenas_lextent_i) @@ -134,6 +141,7 @@ CTL_PROTO(arenas_nbins) CTL_PROTO(arenas_nhbins) CTL_PROTO(arenas_nlextents) CTL_PROTO(arenas_create) +CTL_PROTO(arenas_lookup) CTL_PROTO(prof_thread_active_init) CTL_PROTO(prof_active) CTL_PROTO(prof_dump) @@ -141,6 +149,8 @@ CTL_PROTO(prof_gdump) CTL_PROTO(prof_reset) CTL_PROTO(prof_interval) CTL_PROTO(lg_prof_sample) +CTL_PROTO(prof_log_start) +CTL_PROTO(prof_log_stop) CTL_PROTO(stats_arenas_i_small_allocated) CTL_PROTO(stats_arenas_i_small_nmalloc) CTL_PROTO(stats_arenas_i_small_ndalloc) @@ -164,6 +174,13 @@ CTL_PROTO(stats_arenas_i_lextents_j_ndalloc) CTL_PROTO(stats_arenas_i_lextents_j_nrequests) CTL_PROTO(stats_arenas_i_lextents_j_curlextents) INDEX_PROTO(stats_arenas_i_lextents_j) +CTL_PROTO(stats_arenas_i_extents_j_ndirty) +CTL_PROTO(stats_arenas_i_extents_j_nmuzzy) +CTL_PROTO(stats_arenas_i_extents_j_nretained) +CTL_PROTO(stats_arenas_i_extents_j_dirty_bytes) +CTL_PROTO(stats_arenas_i_extents_j_muzzy_bytes) +CTL_PROTO(stats_arenas_i_extents_j_retained_bytes) +INDEX_PROTO(stats_arenas_i_extents_j) CTL_PROTO(stats_arenas_i_nthreads) CTL_PROTO(stats_arenas_i_uptime) CTL_PROTO(stats_arenas_i_dss) @@ -174,6 +191,7 @@ CTL_PROTO(stats_arenas_i_pdirty) CTL_PROTO(stats_arenas_i_pmuzzy) CTL_PROTO(stats_arenas_i_mapped) CTL_PROTO(stats_arenas_i_retained) +CTL_PROTO(stats_arenas_i_extent_avail) CTL_PROTO(stats_arenas_i_dirty_npurge) CTL_PROTO(stats_arenas_i_dirty_nmadvise) CTL_PROTO(stats_arenas_i_dirty_purged) @@ -182,6 +200,7 @@ CTL_PROTO(stats_arenas_i_muzzy_nmadvise) CTL_PROTO(stats_arenas_i_muzzy_purged) CTL_PROTO(stats_arenas_i_base) CTL_PROTO(stats_arenas_i_internal) +CTL_PROTO(stats_arenas_i_metadata_thp) CTL_PROTO(stats_arenas_i_tcache_bytes) CTL_PROTO(stats_arenas_i_resident) INDEX_PROTO(stats_arenas_i) @@ -191,9 +210,12 @@ CTL_PROTO(stats_background_thread_num_threads) CTL_PROTO(stats_background_thread_num_runs) CTL_PROTO(stats_background_thread_run_interval) CTL_PROTO(stats_metadata) +CTL_PROTO(stats_metadata_thp) CTL_PROTO(stats_resident) CTL_PROTO(stats_mapped) CTL_PROTO(stats_retained) +CTL_PROTO(experimental_hooks_install) +CTL_PROTO(experimental_hooks_remove) #define MUTEX_STATS_CTL_PROTO_GEN(n) \ CTL_PROTO(stats_##n##_num_ops) \ @@ -266,7 +288,6 @@ static const ctl_named_node_t config_node[] = { {NAME("prof_libgcc"), CTL(config_prof_libgcc)}, {NAME("prof_libunwind"), CTL(config_prof_libunwind)}, {NAME("stats"), CTL(config_stats)}, - {NAME("thp"), CTL(config_thp)}, {NAME("utrace"), CTL(config_utrace)}, {NAME("xmalloc"), CTL(config_xmalloc)} }; @@ -274,11 +295,14 @@ static const ctl_named_node_t config_node[] = { static const ctl_named_node_t opt_node[] = { {NAME("abort"), CTL(opt_abort)}, {NAME("abort_conf"), CTL(opt_abort_conf)}, + {NAME("metadata_thp"), CTL(opt_metadata_thp)}, {NAME("retain"), CTL(opt_retain)}, {NAME("dss"), CTL(opt_dss)}, {NAME("narenas"), CTL(opt_narenas)}, {NAME("percpu_arena"), CTL(opt_percpu_arena)}, + {NAME("oversize_threshold"), CTL(opt_oversize_threshold)}, {NAME("background_thread"), CTL(opt_background_thread)}, + {NAME("max_background_threads"), CTL(opt_max_background_threads)}, {NAME("dirty_decay_ms"), CTL(opt_dirty_decay_ms)}, {NAME("muzzy_decay_ms"), CTL(opt_muzzy_decay_ms)}, {NAME("stats_print"), CTL(opt_stats_print)}, @@ -288,6 +312,8 @@ static const ctl_named_node_t opt_node[] = { {NAME("utrace"), CTL(opt_utrace)}, {NAME("xmalloc"), CTL(opt_xmalloc)}, {NAME("tcache"), CTL(opt_tcache)}, + {NAME("thp"), CTL(opt_thp)}, + {NAME("lg_extent_max_active_fit"), CTL(opt_lg_extent_max_active_fit)}, {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)}, {NAME("prof"), CTL(opt_prof)}, {NAME("prof_prefix"), CTL(opt_prof_prefix)}, @@ -316,7 +342,8 @@ static const ctl_named_node_t arena_i_node[] = { {NAME("dss"), CTL(arena_i_dss)}, {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)}, {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)}, - {NAME("extent_hooks"), CTL(arena_i_extent_hooks)} + {NAME("extent_hooks"), CTL(arena_i_extent_hooks)}, + {NAME("retain_grow_limit"), CTL(arena_i_retain_grow_limit)} }; static const ctl_named_node_t super_arena_i_node[] = { {NAME(""), CHILD(named, arena_i)} @@ -329,7 +356,8 @@ static const ctl_indexed_node_t arena_node[] = { static const ctl_named_node_t arenas_bin_i_node[] = { {NAME("size"), CTL(arenas_bin_i_size)}, {NAME("nregs"), CTL(arenas_bin_i_nregs)}, - {NAME("slab_size"), CTL(arenas_bin_i_slab_size)} + {NAME("slab_size"), CTL(arenas_bin_i_slab_size)}, + {NAME("nshards"), CTL(arenas_bin_i_nshards)} }; static const ctl_named_node_t super_arenas_bin_i_node[] = { {NAME(""), CHILD(named, arenas_bin_i)} @@ -362,7 +390,8 @@ static const ctl_named_node_t arenas_node[] = { {NAME("bin"), CHILD(indexed, arenas_bin)}, {NAME("nlextents"), CTL(arenas_nlextents)}, {NAME("lextent"), CHILD(indexed, arenas_lextent)}, - {NAME("create"), CTL(arenas_create)} + {NAME("create"), CTL(arenas_create)}, + {NAME("lookup"), CTL(arenas_lookup)} }; static const ctl_named_node_t prof_node[] = { @@ -372,9 +401,10 @@ static const ctl_named_node_t prof_node[] = { {NAME("gdump"), CTL(prof_gdump)}, {NAME("reset"), CTL(prof_reset)}, {NAME("interval"), CTL(prof_interval)}, - {NAME("lg_sample"), CTL(lg_prof_sample)} + {NAME("lg_sample"), CTL(lg_prof_sample)}, + {NAME("log_start"), CTL(prof_log_start)}, + {NAME("log_stop"), CTL(prof_log_stop)} }; - static const ctl_named_node_t stats_arenas_i_small_node[] = { {NAME("allocated"), CTL(stats_arenas_i_small_allocated)}, {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)}, @@ -445,6 +475,23 @@ static const ctl_indexed_node_t stats_arenas_i_lextents_node[] = { {INDEX(stats_arenas_i_lextents_j)} }; +static const ctl_named_node_t stats_arenas_i_extents_j_node[] = { + {NAME("ndirty"), CTL(stats_arenas_i_extents_j_ndirty)}, + {NAME("nmuzzy"), CTL(stats_arenas_i_extents_j_nmuzzy)}, + {NAME("nretained"), CTL(stats_arenas_i_extents_j_nretained)}, + {NAME("dirty_bytes"), CTL(stats_arenas_i_extents_j_dirty_bytes)}, + {NAME("muzzy_bytes"), CTL(stats_arenas_i_extents_j_muzzy_bytes)}, + {NAME("retained_bytes"), CTL(stats_arenas_i_extents_j_retained_bytes)} +}; + +static const ctl_named_node_t super_stats_arenas_i_extents_j_node[] = { + {NAME(""), CHILD(named, stats_arenas_i_extents_j)} +}; + +static const ctl_indexed_node_t stats_arenas_i_extents_node[] = { + {INDEX(stats_arenas_i_extents_j)} +}; + #define OP(mtx) MUTEX_PROF_DATA_NODE(arenas_i_mutexes_##mtx) MUTEX_PROF_ARENA_MUTEXES #undef OP @@ -466,6 +513,7 @@ static const ctl_named_node_t stats_arenas_i_node[] = { {NAME("pmuzzy"), CTL(stats_arenas_i_pmuzzy)}, {NAME("mapped"), CTL(stats_arenas_i_mapped)}, {NAME("retained"), CTL(stats_arenas_i_retained)}, + {NAME("extent_avail"), CTL(stats_arenas_i_extent_avail)}, {NAME("dirty_npurge"), CTL(stats_arenas_i_dirty_npurge)}, {NAME("dirty_nmadvise"), CTL(stats_arenas_i_dirty_nmadvise)}, {NAME("dirty_purged"), CTL(stats_arenas_i_dirty_purged)}, @@ -474,12 +522,14 @@ static const ctl_named_node_t stats_arenas_i_node[] = { {NAME("muzzy_purged"), CTL(stats_arenas_i_muzzy_purged)}, {NAME("base"), CTL(stats_arenas_i_base)}, {NAME("internal"), CTL(stats_arenas_i_internal)}, + {NAME("metadata_thp"), CTL(stats_arenas_i_metadata_thp)}, {NAME("tcache_bytes"), CTL(stats_arenas_i_tcache_bytes)}, {NAME("resident"), CTL(stats_arenas_i_resident)}, {NAME("small"), CHILD(named, stats_arenas_i_small)}, {NAME("large"), CHILD(named, stats_arenas_i_large)}, {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)}, {NAME("lextents"), CHILD(indexed, stats_arenas_i_lextents)}, + {NAME("extents"), CHILD(indexed, stats_arenas_i_extents)}, {NAME("mutexes"), CHILD(named, stats_arenas_i_mutexes)} }; static const ctl_named_node_t super_stats_arenas_i_node[] = { @@ -512,6 +562,7 @@ static const ctl_named_node_t stats_node[] = { {NAME("allocated"), CTL(stats_allocated)}, {NAME("active"), CTL(stats_active)}, {NAME("metadata"), CTL(stats_metadata)}, + {NAME("metadata_thp"), CTL(stats_metadata_thp)}, {NAME("resident"), CTL(stats_resident)}, {NAME("mapped"), CTL(stats_mapped)}, {NAME("retained"), CTL(stats_retained)}, @@ -521,10 +572,20 @@ static const ctl_named_node_t stats_node[] = { {NAME("arenas"), CHILD(indexed, stats_arenas)} }; +static const ctl_named_node_t hooks_node[] = { + {NAME("install"), CTL(experimental_hooks_install)}, + {NAME("remove"), CTL(experimental_hooks_remove)}, +}; + +static const ctl_named_node_t experimental_node[] = { + {NAME("hooks"), CHILD(named, hooks)} +}; + static const ctl_named_node_t root_node[] = { {NAME("version"), CTL(version)}, {NAME("epoch"), CTL(epoch)}, {NAME("background_thread"), CTL(background_thread)}, + {NAME("max_background_threads"), CTL(max_background_threads)}, {NAME("thread"), CHILD(named, thread)}, {NAME("config"), CHILD(named, config)}, {NAME("opt"), CHILD(named, opt)}, @@ -532,7 +593,8 @@ static const ctl_named_node_t root_node[] = { {NAME("arena"), CHILD(indexed, arena)}, {NAME("arenas"), CHILD(named, arenas)}, {NAME("prof"), CHILD(named, prof)}, - {NAME("stats"), CHILD(named, stats)} + {NAME("stats"), CHILD(named, stats)}, + {NAME("experimental"), CHILD(named, experimental)} }; static const ctl_named_node_t super_root_node[] = { {NAME(""), CHILD(named, root)} @@ -550,7 +612,7 @@ static const ctl_named_node_t super_root_node[] = { * synchronized by the ctl mutex. */ static void -accum_arena_stats_u64(arena_stats_u64_t *dst, arena_stats_u64_t *src) { +ctl_accum_arena_stats_u64(arena_stats_u64_t *dst, arena_stats_u64_t *src) { #ifdef JEMALLOC_ATOMIC_U64 uint64_t cur_dst = atomic_load_u64(dst, ATOMIC_RELAXED); uint64_t cur_src = atomic_load_u64(src, ATOMIC_RELAXED); @@ -562,7 +624,7 @@ accum_arena_stats_u64(arena_stats_u64_t *dst, arena_stats_u64_t *src) { /* Likewise: with ctl mutex synchronization, reading is simple. */ static uint64_t -arena_stats_read_u64(arena_stats_u64_t *p) { +ctl_arena_stats_read_u64(arena_stats_u64_t *p) { #ifdef JEMALLOC_ATOMIC_U64 return atomic_load_u64(p, ATOMIC_RELAXED); #else @@ -570,7 +632,8 @@ arena_stats_read_u64(arena_stats_u64_t *p) { #endif } -static void accum_atomic_zu(atomic_zu_t *dst, atomic_zu_t *src) { +static void +accum_atomic_zu(atomic_zu_t *dst, atomic_zu_t *src) { size_t cur_dst = atomic_load_zu(dst, ATOMIC_RELAXED); size_t cur_src = atomic_load_zu(src, ATOMIC_RELAXED); atomic_store_zu(dst, cur_dst + cur_src, ATOMIC_RELAXED); @@ -679,10 +742,12 @@ ctl_arena_clear(ctl_arena_t *ctl_arena) { ctl_arena->astats->nmalloc_small = 0; ctl_arena->astats->ndalloc_small = 0; ctl_arena->astats->nrequests_small = 0; - memset(ctl_arena->astats->bstats, 0, NBINS * - sizeof(malloc_bin_stats_t)); - memset(ctl_arena->astats->lstats, 0, (NSIZES - NBINS) * - sizeof(malloc_large_stats_t)); + memset(ctl_arena->astats->bstats, 0, SC_NBINS * + sizeof(bin_stats_t)); + memset(ctl_arena->astats->lstats, 0, (SC_NSIZES - SC_NBINS) * + sizeof(arena_stats_large_t)); + memset(ctl_arena->astats->estats, 0, SC_NPSIZES * + sizeof(arena_stats_extents_t)); } } @@ -696,9 +761,9 @@ ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_t *ctl_arena, arena_t *arena) { &ctl_arena->muzzy_decay_ms, &ctl_arena->pactive, &ctl_arena->pdirty, &ctl_arena->pmuzzy, &ctl_arena->astats->astats, ctl_arena->astats->bstats, - ctl_arena->astats->lstats); + ctl_arena->astats->lstats, ctl_arena->astats->estats); - for (i = 0; i < NBINS; i++) { + for (i = 0; i < SC_NBINS; i++) { ctl_arena->astats->allocated_small += ctl_arena->astats->bstats[i].curregs * sz_index2size(i); @@ -743,20 +808,22 @@ ctl_arena_stats_sdmerge(ctl_arena_t *ctl_sdarena, ctl_arena_t *ctl_arena, &astats->astats.mapped); accum_atomic_zu(&sdstats->astats.retained, &astats->astats.retained); + accum_atomic_zu(&sdstats->astats.extent_avail, + &astats->astats.extent_avail); } - accum_arena_stats_u64(&sdstats->astats.decay_dirty.npurge, + ctl_accum_arena_stats_u64(&sdstats->astats.decay_dirty.npurge, &astats->astats.decay_dirty.npurge); - accum_arena_stats_u64(&sdstats->astats.decay_dirty.nmadvise, + ctl_accum_arena_stats_u64(&sdstats->astats.decay_dirty.nmadvise, &astats->astats.decay_dirty.nmadvise); - accum_arena_stats_u64(&sdstats->astats.decay_dirty.purged, + ctl_accum_arena_stats_u64(&sdstats->astats.decay_dirty.purged, &astats->astats.decay_dirty.purged); - accum_arena_stats_u64(&sdstats->astats.decay_muzzy.npurge, + ctl_accum_arena_stats_u64(&sdstats->astats.decay_muzzy.npurge, &astats->astats.decay_muzzy.npurge); - accum_arena_stats_u64(&sdstats->astats.decay_muzzy.nmadvise, + ctl_accum_arena_stats_u64(&sdstats->astats.decay_muzzy.nmadvise, &astats->astats.decay_muzzy.nmadvise); - accum_arena_stats_u64(&sdstats->astats.decay_muzzy.purged, + ctl_accum_arena_stats_u64(&sdstats->astats.decay_muzzy.purged, &astats->astats.decay_muzzy.purged); #define OP(mtx) malloc_mutex_prof_merge( \ @@ -773,6 +840,8 @@ MUTEX_PROF_ARENA_MUTEXES &astats->astats.internal); accum_atomic_zu(&sdstats->astats.resident, &astats->astats.resident); + accum_atomic_zu(&sdstats->astats.metadata_thp, + &astats->astats.metadata_thp); } else { assert(atomic_load_zu( &astats->astats.internal, ATOMIC_RELAXED) == 0); @@ -794,11 +863,11 @@ MUTEX_PROF_ARENA_MUTEXES assert(atomic_load_zu(&astats->astats.allocated_large, ATOMIC_RELAXED) == 0); } - accum_arena_stats_u64(&sdstats->astats.nmalloc_large, + ctl_accum_arena_stats_u64(&sdstats->astats.nmalloc_large, &astats->astats.nmalloc_large); - accum_arena_stats_u64(&sdstats->astats.ndalloc_large, + ctl_accum_arena_stats_u64(&sdstats->astats.ndalloc_large, &astats->astats.ndalloc_large); - accum_arena_stats_u64(&sdstats->astats.nrequests_large, + ctl_accum_arena_stats_u64(&sdstats->astats.nrequests_large, &astats->astats.nrequests_large); accum_atomic_zu(&sdstats->astats.tcache_bytes, @@ -808,7 +877,8 @@ MUTEX_PROF_ARENA_MUTEXES sdstats->astats.uptime = astats->astats.uptime; } - for (i = 0; i < NBINS; i++) { + /* Merge bin stats. */ + for (i = 0; i < SC_NBINS; i++) { sdstats->bstats[i].nmalloc += astats->bstats[i].nmalloc; sdstats->bstats[i].ndalloc += astats->bstats[i].ndalloc; sdstats->bstats[i].nrequests += @@ -834,12 +904,13 @@ MUTEX_PROF_ARENA_MUTEXES &astats->bstats[i].mutex_data); } - for (i = 0; i < NSIZES - NBINS; i++) { - accum_arena_stats_u64(&sdstats->lstats[i].nmalloc, + /* Merge stats for large allocations. */ + for (i = 0; i < SC_NSIZES - SC_NBINS; i++) { + ctl_accum_arena_stats_u64(&sdstats->lstats[i].nmalloc, &astats->lstats[i].nmalloc); - accum_arena_stats_u64(&sdstats->lstats[i].ndalloc, + ctl_accum_arena_stats_u64(&sdstats->lstats[i].ndalloc, &astats->lstats[i].ndalloc); - accum_arena_stats_u64(&sdstats->lstats[i].nrequests, + ctl_accum_arena_stats_u64(&sdstats->lstats[i].nrequests, &astats->lstats[i].nrequests); if (!destroyed) { sdstats->lstats[i].curlextents += @@ -848,6 +919,22 @@ MUTEX_PROF_ARENA_MUTEXES assert(astats->lstats[i].curlextents == 0); } } + + /* Merge extents stats. */ + for (i = 0; i < SC_NPSIZES; i++) { + accum_atomic_zu(&sdstats->estats[i].ndirty, + &astats->estats[i].ndirty); + accum_atomic_zu(&sdstats->estats[i].nmuzzy, + &astats->estats[i].nmuzzy); + accum_atomic_zu(&sdstats->estats[i].nretained, + &astats->estats[i].nretained); + accum_atomic_zu(&sdstats->estats[i].dirty_bytes, + &astats->estats[i].dirty_bytes); + accum_atomic_zu(&sdstats->estats[i].muzzy_bytes, + &astats->estats[i].muzzy_bytes); + accum_atomic_zu(&sdstats->estats[i].retained_bytes, + &astats->estats[i].retained_bytes); + } } } @@ -938,6 +1025,8 @@ ctl_refresh(tsdn_t *tsdn) { &ctl_sarena->astats->astats.base, ATOMIC_RELAXED) + atomic_load_zu(&ctl_sarena->astats->astats.internal, ATOMIC_RELAXED); + ctl_stats->metadata_thp = atomic_load_zu( + &ctl_sarena->astats->astats.metadata_thp, ATOMIC_RELAXED); ctl_stats->resident = atomic_load_zu( &ctl_sarena->astats->astats.resident, ATOMIC_RELAXED); ctl_stats->mapped = atomic_load_zu( @@ -1357,8 +1446,8 @@ label_return: \ #define CTL_RO_CGEN(c, n, v, t) \ static int \ -n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ - size_t *oldlenp, void *newp, size_t newlen) { \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \ + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ @@ -1400,8 +1489,8 @@ label_return: \ */ #define CTL_RO_NL_CGEN(c, n, v, t) \ static int \ -n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ - size_t *oldlenp, void *newp, size_t newlen) { \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \ + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ @@ -1419,8 +1508,8 @@ label_return: \ #define CTL_RO_NL_GEN(n, v, t) \ static int \ -n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ - size_t *oldlenp, void *newp, size_t newlen) { \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \ + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ @@ -1454,8 +1543,8 @@ label_return: \ #define CTL_RO_CONFIG_GEN(n, t) \ static int \ -n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ - size_t *oldlenp, void *newp, size_t newlen) { \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \ + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ @@ -1473,8 +1562,8 @@ label_return: \ CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *) static int -epoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +epoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; UNUSED uint64_t newval; @@ -1492,8 +1581,9 @@ epoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -background_thread_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, - void *oldp, size_t *oldlenp, void *newp, size_t newlen) { +background_thread_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) { int ret; bool oldval; @@ -1523,22 +1613,74 @@ background_thread_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, background_thread_enabled_set(tsd_tsdn(tsd), newval); if (newval) { - if (!can_enable_background_thread) { - malloc_printf(": Error in dlsym(" - "RTLD_NEXT, \"pthread_create\"). Cannot " - "enable background_thread\n"); + if (background_threads_enable(tsd)) { ret = EFAULT; goto label_return; } - if (background_threads_enable(tsd)) { + } else { + if (background_threads_disable(tsd)) { ret = EFAULT; goto label_return; } - } else { + } + } + ret = 0; +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + + return ret; +} + +static int +max_background_threads_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { + int ret; + size_t oldval; + + if (!have_background_thread) { + return ENOENT; + } + background_thread_ctl_init(tsd_tsdn(tsd)); + + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); + malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); + if (newp == NULL) { + oldval = max_background_threads; + READ(oldval, size_t); + } else { + if (newlen != sizeof(size_t)) { + ret = EINVAL; + goto label_return; + } + oldval = max_background_threads; + READ(oldval, size_t); + + size_t newval = *(size_t *)newp; + if (newval == oldval) { + ret = 0; + goto label_return; + } + if (newval > opt_max_background_threads) { + ret = EINVAL; + goto label_return; + } + + if (background_thread_enabled()) { + background_thread_enabled_set(tsd_tsdn(tsd), false); if (background_threads_disable(tsd)) { ret = EFAULT; goto label_return; } + max_background_threads = newval; + background_thread_enabled_set(tsd_tsdn(tsd), true); + if (background_threads_enable(tsd)) { + ret = EFAULT; + goto label_return; + } + } else { + max_background_threads = newval; } } ret = 0; @@ -1560,7 +1702,6 @@ CTL_RO_CONFIG_GEN(config_prof, bool) CTL_RO_CONFIG_GEN(config_prof_libgcc, bool) CTL_RO_CONFIG_GEN(config_prof_libunwind, bool) CTL_RO_CONFIG_GEN(config_stats, bool) -CTL_RO_CONFIG_GEN(config_thp, bool) CTL_RO_CONFIG_GEN(config_utrace, bool) CTL_RO_CONFIG_GEN(config_xmalloc, bool) @@ -1568,12 +1709,16 @@ CTL_RO_CONFIG_GEN(config_xmalloc, bool) CTL_RO_NL_GEN(opt_abort, opt_abort, bool) CTL_RO_NL_GEN(opt_abort_conf, opt_abort_conf, bool) +CTL_RO_NL_GEN(opt_metadata_thp, metadata_thp_mode_names[opt_metadata_thp], + const char *) CTL_RO_NL_GEN(opt_retain, opt_retain, bool) CTL_RO_NL_GEN(opt_dss, opt_dss, const char *) CTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned) CTL_RO_NL_GEN(opt_percpu_arena, percpu_arena_mode_names[opt_percpu_arena], const char *) +CTL_RO_NL_GEN(opt_oversize_threshold, opt_oversize_threshold, size_t) CTL_RO_NL_GEN(opt_background_thread, opt_background_thread, bool) +CTL_RO_NL_GEN(opt_max_background_threads, opt_max_background_threads, size_t) CTL_RO_NL_GEN(opt_dirty_decay_ms, opt_dirty_decay_ms, ssize_t) CTL_RO_NL_GEN(opt_muzzy_decay_ms, opt_muzzy_decay_ms, ssize_t) CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool) @@ -1583,6 +1728,9 @@ CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool) CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool) CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool) CTL_RO_NL_GEN(opt_tcache, opt_tcache, bool) +CTL_RO_NL_GEN(opt_thp, thp_mode_names[opt_thp], const char *) +CTL_RO_NL_GEN(opt_lg_extent_max_active_fit, opt_lg_extent_max_active_fit, + size_t) CTL_RO_NL_GEN(opt_lg_tcache_max, opt_lg_tcache_max, ssize_t) CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *) @@ -1599,8 +1747,8 @@ CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool) /******************************************************************************/ static int -thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; arena_t *oldarena; unsigned newind, oldind; @@ -1664,8 +1812,9 @@ CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp, tsd_thread_deallocatedp_get, uint64_t *) static int -thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, - void *oldp, size_t *oldlenp, void *newp, size_t newlen) { +thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { int ret; bool oldval; @@ -1685,8 +1834,9 @@ thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, } static int -thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, - void *oldp, size_t *oldlenp, void *newp, size_t newlen) { +thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { int ret; if (!tcache_available(tsd)) { @@ -1705,8 +1855,9 @@ thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, } static int -thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { int ret; if (!config_prof) { @@ -1736,8 +1887,9 @@ thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { int ret; bool oldval; @@ -1766,8 +1918,8 @@ thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, /******************************************************************************/ static int -tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; unsigned tcache_ind; @@ -1784,8 +1936,8 @@ tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; unsigned tcache_ind; @@ -1804,8 +1956,8 @@ tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; unsigned tcache_ind; @@ -1953,9 +2105,8 @@ arena_reset_prepare_background_thread(tsd_t *tsd, unsigned arena_ind) { if (have_background_thread) { malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); if (background_thread_enabled()) { - unsigned ind = arena_ind % ncpus; background_thread_info_t *info = - &background_thread_info[ind]; + background_thread_info_get(arena_ind); assert(info->state == background_thread_started); malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); info->state = background_thread_paused; @@ -1968,9 +2119,8 @@ static void arena_reset_finish_background_thread(tsd_t *tsd, unsigned arena_ind) { if (have_background_thread) { if (background_thread_enabled()) { - unsigned ind = arena_ind % ncpus; background_thread_info_t *info = - &background_thread_info[ind]; + background_thread_info_get(arena_ind); assert(info->state == background_thread_paused); malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); info->state = background_thread_started; @@ -2126,6 +2276,17 @@ arena_i_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, ret = EINVAL; goto label_return; } + if (arena_is_huge(arena_ind) && *(ssize_t *)newp > 0) { + /* + * By default the huge arena purges eagerly. If it is + * set to non-zero decay time afterwards, background + * thread might be needed. + */ + if (background_thread_create(tsd, arena_ind)) { + ret = EFAULT; + goto label_return; + } + } if (dirty ? arena_dirty_decay_ms_set(tsd_tsdn(tsd), arena, *(ssize_t *)newp) : arena_muzzy_decay_ms_set(tsd_tsdn(tsd), arena, *(ssize_t *)newp)) { @@ -2162,20 +2323,41 @@ arena_i_extent_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); MIB_UNSIGNED(arena_ind, 1); - if (arena_ind < narenas_total_get() && (arena = - arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) { - if (newp != NULL) { - extent_hooks_t *old_extent_hooks; - extent_hooks_t *new_extent_hooks - JEMALLOC_CC_SILENCE_INIT(NULL); - WRITE(new_extent_hooks, extent_hooks_t *); - old_extent_hooks = extent_hooks_set(tsd, arena, - new_extent_hooks); + if (arena_ind < narenas_total_get()) { + extent_hooks_t *old_extent_hooks; + arena = arena_get(tsd_tsdn(tsd), arena_ind, false); + if (arena == NULL) { + if (arena_ind >= narenas_auto) { + ret = EFAULT; + goto label_return; + } + old_extent_hooks = + (extent_hooks_t *)&extent_hooks_default; READ(old_extent_hooks, extent_hooks_t *); + if (newp != NULL) { + /* Initialize a new arena as a side effect. */ + extent_hooks_t *new_extent_hooks + JEMALLOC_CC_SILENCE_INIT(NULL); + WRITE(new_extent_hooks, extent_hooks_t *); + arena = arena_init(tsd_tsdn(tsd), arena_ind, + new_extent_hooks); + if (arena == NULL) { + ret = EFAULT; + goto label_return; + } + } } else { - extent_hooks_t *old_extent_hooks = - extent_hooks_get(arena); - READ(old_extent_hooks, extent_hooks_t *); + if (newp != NULL) { + extent_hooks_t *new_extent_hooks + JEMALLOC_CC_SILENCE_INIT(NULL); + WRITE(new_extent_hooks, extent_hooks_t *); + old_extent_hooks = extent_hooks_set(tsd, arena, + new_extent_hooks); + READ(old_extent_hooks, extent_hooks_t *); + } else { + old_extent_hooks = extent_hooks_get(arena); + READ(old_extent_hooks, extent_hooks_t *); + } } } else { ret = EFAULT; @@ -2187,8 +2369,46 @@ arena_i_extent_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, return ret; } +static int +arena_i_retain_grow_limit_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { + int ret; + unsigned arena_ind; + arena_t *arena; + + if (!opt_retain) { + /* Only relevant when retain is enabled. */ + return ENOENT; + } + + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); + MIB_UNSIGNED(arena_ind, 1); + if (arena_ind < narenas_total_get() && (arena = + arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) { + size_t old_limit, new_limit; + if (newp != NULL) { + WRITE(new_limit, size_t); + } + bool err = arena_retain_grow_limit_get_set(tsd, arena, + &old_limit, newp != NULL ? &new_limit : NULL); + if (!err) { + READ(old_limit, size_t); + ret = 0; + } else { + ret = EFAULT; + } + } else { + ret = EFAULT; + } +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; +} + static const ctl_named_node_t * -arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { +arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, + size_t i) { const ctl_named_node_t *ret; malloc_mutex_lock(tsdn, &ctl_mtx); @@ -2213,8 +2433,8 @@ arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { /******************************************************************************/ static int -arenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +arenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; unsigned narenas; @@ -2234,8 +2454,9 @@ arenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -arenas_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, - void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) { +arenas_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen, bool dirty) { int ret; if (oldp != NULL && oldlenp != NULL) { @@ -2248,7 +2469,7 @@ arenas_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, ret = EINVAL; goto label_return; } - if (dirty ? arena_dirty_decay_ms_default_set(*(ssize_t *)newp) + if (dirty ? arena_dirty_decay_ms_default_set(*(ssize_t *)newp) : arena_muzzy_decay_ms_default_set(*(ssize_t *)newp)) { ret = EFAULT; goto label_return; @@ -2277,34 +2498,36 @@ arenas_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t) CTL_RO_NL_GEN(arenas_page, PAGE, size_t) CTL_RO_NL_GEN(arenas_tcache_max, tcache_maxclass, size_t) -CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned) +CTL_RO_NL_GEN(arenas_nbins, SC_NBINS, unsigned) CTL_RO_NL_GEN(arenas_nhbins, nhbins, unsigned) -CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t) -CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t) -CTL_RO_NL_GEN(arenas_bin_i_slab_size, arena_bin_info[mib[2]].slab_size, size_t) +CTL_RO_NL_GEN(arenas_bin_i_size, bin_infos[mib[2]].reg_size, size_t) +CTL_RO_NL_GEN(arenas_bin_i_nregs, bin_infos[mib[2]].nregs, uint32_t) +CTL_RO_NL_GEN(arenas_bin_i_slab_size, bin_infos[mib[2]].slab_size, size_t) +CTL_RO_NL_GEN(arenas_bin_i_nshards, bin_infos[mib[2]].n_shards, uint32_t) static const ctl_named_node_t * -arenas_bin_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { - if (i > NBINS) { +arenas_bin_i_index(tsdn_t *tsdn, const size_t *mib, + size_t miblen, size_t i) { + if (i > SC_NBINS) { return NULL; } return super_arenas_bin_i_node; } -CTL_RO_NL_GEN(arenas_nlextents, NSIZES - NBINS, unsigned) -CTL_RO_NL_GEN(arenas_lextent_i_size, sz_index2size(NBINS+(szind_t)mib[2]), +CTL_RO_NL_GEN(arenas_nlextents, SC_NSIZES - SC_NBINS, unsigned) +CTL_RO_NL_GEN(arenas_lextent_i_size, sz_index2size(SC_NBINS+(szind_t)mib[2]), size_t) static const ctl_named_node_t * -arenas_lextent_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, - size_t i) { - if (i > NSIZES - NBINS) { +arenas_lextent_i_index(tsdn_t *tsdn, const size_t *mib, + size_t miblen, size_t i) { + if (i > SC_NSIZES - SC_NBINS) { return NULL; } return super_arenas_lextent_i_node; } static int -arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; extent_hooks_t *extent_hooks; unsigned arena_ind; @@ -2325,11 +2548,43 @@ arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, return ret; } +static int +arenas_lookup_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { + int ret; + unsigned arena_ind; + void *ptr; + extent_t *extent; + arena_t *arena; + + ptr = NULL; + ret = EINVAL; + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); + WRITE(ptr, void *); + extent = iealloc(tsd_tsdn(tsd), ptr); + if (extent == NULL) + goto label_return; + + arena = extent_arena_get(extent); + if (arena == NULL) + goto label_return; + + arena_ind = arena_ind_get(arena); + READ(arena_ind, unsigned); + + ret = 0; +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; +} + /******************************************************************************/ static int -prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, - void *oldp, size_t *oldlenp, void *newp, size_t newlen) { +prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { int ret; bool oldval; @@ -2355,8 +2610,8 @@ prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, } static int -prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; bool oldval; @@ -2381,8 +2636,8 @@ prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; const char *filename = NULL; @@ -2404,8 +2659,8 @@ prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; bool oldval; @@ -2430,8 +2685,8 @@ prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, } static int -prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) { +prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; size_t lg_sample = lg_prof_sample; @@ -2455,11 +2710,50 @@ prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t) CTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t) +static int +prof_log_start_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + + const char *filename = NULL; + + if (!config_prof) { + return ENOENT; + } + + WRITEONLY(); + WRITE(filename, const char *); + + if (prof_log_start(tsd_tsdn(tsd), filename)) { + ret = EFAULT; + goto label_return; + } + + ret = 0; +label_return: + return ret; +} + +static int +prof_log_stop_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + if (!config_prof) { + return ENOENT; + } + + if (prof_log_stop(tsd_tsdn(tsd))) { + return EFAULT; + } + + return 0; +} + /******************************************************************************/ CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats->allocated, size_t) CTL_RO_CGEN(config_stats, stats_active, ctl_stats->active, size_t) CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats->metadata, size_t) +CTL_RO_CGEN(config_stats, stats_metadata_thp, ctl_stats->metadata_thp, size_t) CTL_RO_CGEN(config_stats, stats_resident, ctl_stats->resident, size_t) CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats->mapped, size_t) CTL_RO_CGEN(config_stats, stats_retained, ctl_stats->retained, size_t) @@ -2488,26 +2782,30 @@ CTL_RO_CGEN(config_stats, stats_arenas_i_mapped, CTL_RO_CGEN(config_stats, stats_arenas_i_retained, atomic_load_zu(&arenas_i(mib[2])->astats->astats.retained, ATOMIC_RELAXED), size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_extent_avail, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.extent_avail, + ATOMIC_RELAXED), + size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_npurge, - arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_dirty.npurge), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.decay_dirty.npurge), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_nmadvise, - arena_stats_read_u64( + ctl_arena_stats_read_u64( &arenas_i(mib[2])->astats->astats.decay_dirty.nmadvise), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_purged, - arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_dirty.purged), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.decay_dirty.purged), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_npurge, - arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_muzzy.npurge), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.decay_muzzy.npurge), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_nmadvise, - arena_stats_read_u64( + ctl_arena_stats_read_u64( &arenas_i(mib[2])->astats->astats.decay_muzzy.nmadvise), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_purged, - arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_muzzy.purged), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.decay_muzzy.purged), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_base, atomic_load_zu(&arenas_i(mib[2])->astats->astats.base, ATOMIC_RELAXED), @@ -2515,6 +2813,9 @@ CTL_RO_CGEN(config_stats, stats_arenas_i_base, CTL_RO_CGEN(config_stats, stats_arenas_i_internal, atomic_load_zu(&arenas_i(mib[2])->astats->astats.internal, ATOMIC_RELAXED), size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_thp, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.metadata_thp, + ATOMIC_RELAXED), size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_tcache_bytes, atomic_load_zu(&arenas_i(mib[2])->astats->astats.tcache_bytes, ATOMIC_RELAXED), size_t) @@ -2534,14 +2835,17 @@ CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated, atomic_load_zu(&arenas_i(mib[2])->astats->astats.allocated_large, ATOMIC_RELAXED), size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc, - arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.nmalloc_large), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.nmalloc_large), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc, - arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.ndalloc_large), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.ndalloc_large), uint64_t) +/* + * Note: "nmalloc" here instead of "nrequests" in the read. This is intentional. + */ CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests, - arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.nmalloc_large), - uint64_t) /* Intentional. */ + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.nmalloc_large), uint64_t) /* Intentional. */ /* Lock profiling related APIs below. */ #define RO_MUTEX_CTL_GEN(n, l) \ @@ -2580,8 +2884,9 @@ RO_MUTEX_CTL_GEN(arenas_i_bins_j_mutex, /* Resets all mutex stats, including global, arena and bin mutexes. */ static int -stats_mutexes_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, - void *oldp, size_t *oldlenp, void *newp, size_t newlen) { +stats_mutexes_reset_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) { if (!config_stats) { return ENOENT; } @@ -2621,9 +2926,11 @@ stats_mutexes_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, MUTEX_PROF_RESET(arena->tcache_ql_mtx); MUTEX_PROF_RESET(arena->base->mtx); - for (szind_t i = 0; i < NBINS; i++) { - arena_bin_t *bin = &arena->bins[i]; - MUTEX_PROF_RESET(bin->lock); + for (szind_t i = 0; i < SC_NBINS; i++) { + for (unsigned j = 0; j < bin_infos[i].n_shards; j++) { + bin_t *bin = &arena->bins[i].bin_shards[j]; + MUTEX_PROF_RESET(bin->lock); + } } } #undef MUTEX_PROF_RESET @@ -2650,37 +2957,72 @@ CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curslabs, arenas_i(mib[2])->astats->bstats[mib[4]].curslabs, size_t) static const ctl_named_node_t * -stats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, - size_t j) { - if (j > NBINS) { +stats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib, + size_t miblen, size_t j) { + if (j > SC_NBINS) { return NULL; } return super_stats_arenas_i_bins_j_node; } CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_nmalloc, - arena_stats_read_u64(&arenas_i(mib[2])->astats->lstats[mib[4]].nmalloc), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->lstats[mib[4]].nmalloc), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_ndalloc, - arena_stats_read_u64(&arenas_i(mib[2])->astats->lstats[mib[4]].ndalloc), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->lstats[mib[4]].ndalloc), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_nrequests, - arena_stats_read_u64(&arenas_i(mib[2])->astats->lstats[mib[4]].nrequests), - uint64_t) + ctl_arena_stats_read_u64( + &arenas_i(mib[2])->astats->lstats[mib[4]].nrequests), uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_curlextents, arenas_i(mib[2])->astats->lstats[mib[4]].curlextents, size_t) static const ctl_named_node_t * -stats_arenas_i_lextents_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, - size_t j) { - if (j > NSIZES - NBINS) { +stats_arenas_i_lextents_j_index(tsdn_t *tsdn, const size_t *mib, + size_t miblen, size_t j) { + if (j > SC_NSIZES - SC_NBINS) { return NULL; } return super_stats_arenas_i_lextents_j_node; } +CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_ndirty, + atomic_load_zu( + &arenas_i(mib[2])->astats->estats[mib[4]].ndirty, + ATOMIC_RELAXED), size_t); +CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_nmuzzy, + atomic_load_zu( + &arenas_i(mib[2])->astats->estats[mib[4]].nmuzzy, + ATOMIC_RELAXED), size_t); +CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_nretained, + atomic_load_zu( + &arenas_i(mib[2])->astats->estats[mib[4]].nretained, + ATOMIC_RELAXED), size_t); +CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_dirty_bytes, + atomic_load_zu( + &arenas_i(mib[2])->astats->estats[mib[4]].dirty_bytes, + ATOMIC_RELAXED), size_t); +CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_muzzy_bytes, + atomic_load_zu( + &arenas_i(mib[2])->astats->estats[mib[4]].muzzy_bytes, + ATOMIC_RELAXED), size_t); +CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_retained_bytes, + atomic_load_zu( + &arenas_i(mib[2])->astats->estats[mib[4]].retained_bytes, + ATOMIC_RELAXED), size_t); + static const ctl_named_node_t * -stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { +stats_arenas_i_extents_j_index(tsdn_t *tsdn, const size_t *mib, + size_t miblen, size_t j) { + if (j >= SC_NPSIZES) { + return NULL; + } + return super_stats_arenas_i_extents_j_node; +} + +static const ctl_named_node_t * +stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, + size_t miblen, size_t i) { const ctl_named_node_t *ret; size_t a; @@ -2696,3 +3038,48 @@ stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { malloc_mutex_unlock(tsdn, &ctl_mtx); return ret; } + +static int +experimental_hooks_install_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + if (oldp == NULL || oldlenp == NULL|| newp == NULL) { + ret = EINVAL; + goto label_return; + } + /* + * Note: this is a *private* struct. This is an experimental interface; + * forcing the user to know the jemalloc internals well enough to + * extract the ABI hopefully ensures nobody gets too comfortable with + * this API, which can change at a moment's notice. + */ + hooks_t hooks; + WRITE(hooks, hooks_t); + void *handle = hook_install(tsd_tsdn(tsd), &hooks); + if (handle == NULL) { + ret = EAGAIN; + goto label_return; + } + READ(handle, void *); + + ret = 0; +label_return: + return ret; +} + +static int +experimental_hooks_remove_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + WRITEONLY(); + void *handle = NULL; + WRITE(handle, void *); + if (handle == NULL) { + ret = EINVAL; + goto label_return; + } + hook_remove(tsd_tsdn(tsd), handle); + ret = 0; +label_return: + return ret; +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/div.c b/kbe/src/lib/dependencies/jemalloc/src/div.c new file mode 100644 index 0000000000..808892a133 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/src/div.c @@ -0,0 +1,55 @@ +#include "jemalloc/internal/jemalloc_preamble.h" + +#include "jemalloc/internal/div.h" + +#include "jemalloc/internal/assert.h" + +/* + * Suppose we have n = q * d, all integers. We know n and d, and want q = n / d. + * + * For any k, we have (here, all division is exact; not C-style rounding): + * floor(ceil(2^k / d) * n / 2^k) = floor((2^k + r) / d * n / 2^k), where + * r = (-2^k) mod d. + * + * Expanding this out: + * ... = floor(2^k / d * n / 2^k + r / d * n / 2^k) + * = floor(n / d + (r / d) * (n / 2^k)). + * + * The fractional part of n / d is 0 (because of the assumption that d divides n + * exactly), so we have: + * ... = n / d + floor((r / d) * (n / 2^k)) + * + * So that our initial expression is equal to the quantity we seek, so long as + * (r / d) * (n / 2^k) < 1. + * + * r is a remainder mod d, so r < d and r / d < 1 always. We can make + * n / 2 ^ k < 1 by setting k = 32. This gets us a value of magic that works. + */ + +void +div_init(div_info_t *div_info, size_t d) { + /* Nonsensical. */ + assert(d != 0); + /* + * This would make the value of magic too high to fit into a uint32_t + * (we would want magic = 2^32 exactly). This would mess with code gen + * on 32-bit machines. + */ + assert(d != 1); + + uint64_t two_to_k = ((uint64_t)1 << 32); + uint32_t magic = (uint32_t)(two_to_k / d); + + /* + * We want magic = ceil(2^k / d), but C gives us floor. We have to + * increment it unless the result was exact (i.e. unless d is a power of + * two). + */ + if (two_to_k % d != 0) { + magic++; + } + div_info->magic = magic; +#ifdef JEMALLOC_DEBUG + div_info->d = d; +#endif +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/extent.c b/kbe/src/lib/dependencies/jemalloc/src/extent.c index fa45c84d34..62086c7d7b 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/extent.c +++ b/kbe/src/lib/dependencies/jemalloc/src/extent.c @@ -17,8 +17,10 @@ rtree_t extents_rtree; /* Keyed by the address of the extent_t being protected. */ mutex_pool_t extent_mutex_pool; +size_t opt_lg_extent_max_active_fit = LG_EXTENT_MAX_ACTIVE_FIT_DEFAULT; + static const bitmap_info_t extents_bitmap_info = - BITMAP_INFO_INITIALIZER(NPSIZES+1); + BITMAP_INFO_INITIALIZER(SC_NPSIZES+1); static void *extent_alloc_default(extent_hooks_t *extent_hooks, void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit, @@ -117,9 +119,13 @@ static void extent_record(tsdn_t *tsdn, arena_t *arena, /******************************************************************************/ -rb_gen(UNUSED, extent_avail_, extent_tree_t, extent_t, rb_link, +#define ATTR_NONE /* does nothing */ + +ph_gen(ATTR_NONE, extent_avail_, extent_tree_t, extent_t, ph_link, extent_esnead_comp) +#undef ATTR_NONE + typedef enum { lock_result_success, lock_result_failure, @@ -128,13 +134,16 @@ typedef enum { static lock_result_t extent_rtree_leaf_elm_try_lock(tsdn_t *tsdn, rtree_leaf_elm_t *elm, - extent_t **result) { + extent_t **result, bool inactive_only) { extent_t *extent1 = rtree_leaf_elm_extent_read(tsdn, &extents_rtree, elm, true); - if (extent1 == NULL) { + /* Slab implies active extents and should be skipped. */ + if (extent1 == NULL || (inactive_only && rtree_leaf_elm_slab_read(tsdn, + &extents_rtree, elm, true))) { return lock_result_no_extent; } + /* * It's possible that the extent changed out from under us, and with it * the leaf->extent mapping. We have to recheck while holding the lock. @@ -157,7 +166,8 @@ extent_rtree_leaf_elm_try_lock(tsdn_t *tsdn, rtree_leaf_elm_t *elm, * address, and NULL otherwise. */ static extent_t * -extent_lock_from_addr(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, void *addr) { +extent_lock_from_addr(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, void *addr, + bool inactive_only) { extent_t *ret = NULL; rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)addr, false, false); @@ -166,7 +176,8 @@ extent_lock_from_addr(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, void *addr) { } lock_result_t lock_result; do { - lock_result = extent_rtree_leaf_elm_try_lock(tsdn, elm, &ret); + lock_result = extent_rtree_leaf_elm_try_lock(tsdn, elm, &ret, + inactive_only); } while (lock_result == lock_result_failure); return ret; } @@ -180,6 +191,7 @@ extent_alloc(tsdn_t *tsdn, arena_t *arena) { return base_alloc_extent(tsdn, arena->base); } extent_avail_remove(&arena->extent_avail, extent); + atomic_fetch_sub_zu(&arena->extent_avail_cnt, 1, ATOMIC_RELAXED); malloc_mutex_unlock(tsdn, &arena->extent_avail_mtx); return extent; } @@ -188,6 +200,7 @@ void extent_dalloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent) { malloc_mutex_lock(tsdn, &arena->extent_avail_mtx); extent_avail_insert(&arena->extent_avail, extent); + atomic_fetch_add_zu(&arena->extent_avail_cnt, 1, ATOMIC_RELAXED); malloc_mutex_unlock(tsdn, &arena->extent_avail_mtx); } @@ -253,7 +266,7 @@ extent_size_quantize_ceil(size_t size) { size_t ret; assert(size > 0); - assert(size - sz_large_pad <= LARGE_MAXCLASS); + assert(size - sz_large_pad <= SC_LARGE_MAXCLASS); assert((size & PAGE_MASK) == 0); ret = extent_size_quantize_floor(size); @@ -282,7 +295,7 @@ extents_init(tsdn_t *tsdn, extents_t *extents, extent_state_t state, malloc_mutex_rank_exclusive)) { return true; } - for (unsigned i = 0; i < NPSIZES+1; i++) { + for (unsigned i = 0; i < SC_NPSIZES + 1; i++) { extent_heap_new(&extents->heaps[i]); } bitmap_init(extents->bitmap, &extents_bitmap_info, true); @@ -303,9 +316,34 @@ extents_npages_get(extents_t *extents) { return atomic_load_zu(&extents->npages, ATOMIC_RELAXED); } +size_t +extents_nextents_get(extents_t *extents, pszind_t pind) { + return atomic_load_zu(&extents->nextents[pind], ATOMIC_RELAXED); +} + +size_t +extents_nbytes_get(extents_t *extents, pszind_t pind) { + return atomic_load_zu(&extents->nbytes[pind], ATOMIC_RELAXED); +} + +static void +extents_stats_add(extents_t *extent, pszind_t pind, size_t sz) { + size_t cur = atomic_load_zu(&extent->nextents[pind], ATOMIC_RELAXED); + atomic_store_zu(&extent->nextents[pind], cur + 1, ATOMIC_RELAXED); + cur = atomic_load_zu(&extent->nbytes[pind], ATOMIC_RELAXED); + atomic_store_zu(&extent->nbytes[pind], cur + sz, ATOMIC_RELAXED); +} + +static void +extents_stats_sub(extents_t *extent, pszind_t pind, size_t sz) { + size_t cur = atomic_load_zu(&extent->nextents[pind], ATOMIC_RELAXED); + atomic_store_zu(&extent->nextents[pind], cur - 1, ATOMIC_RELAXED); + cur = atomic_load_zu(&extent->nbytes[pind], ATOMIC_RELAXED); + atomic_store_zu(&extent->nbytes[pind], cur - sz, ATOMIC_RELAXED); +} + static void -extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, - bool preserve_lru) { +extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent) { malloc_mutex_assert_owner(tsdn, &extents->mtx); assert(extent_state_get(extent) == extents->state); @@ -317,9 +355,12 @@ extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, (size_t)pind); } extent_heap_insert(&extents->heaps[pind], extent); - if (!preserve_lru) { - extent_list_append(&extents->lru, extent); + + if (config_stats) { + extents_stats_add(extents, pind, size); } + + extent_list_append(&extents->lru, extent); size_t npages = size >> LG_PAGE; /* * All modifications to npages hold the mutex (as asserted above), so we @@ -333,8 +374,7 @@ extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, } static void -extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, - bool preserve_lru) { +extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent) { malloc_mutex_assert_owner(tsdn, &extents->mtx); assert(extent_state_get(extent) == extents->state); @@ -342,13 +382,16 @@ extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, size_t psz = extent_size_quantize_floor(size); pszind_t pind = sz_psz2ind(psz); extent_heap_remove(&extents->heaps[pind], extent); + + if (config_stats) { + extents_stats_sub(extents, pind, size); + } + if (extent_heap_empty(&extents->heaps[pind])) { bitmap_set(extents->bitmap, &extents_bitmap_info, (size_t)pind); } - if (!preserve_lru) { - extent_list_remove(&extents->lru, extent); - } + extent_list_remove(&extents->lru, extent); size_t npages = size >> LG_PAGE; /* * As in extents_insert_locked, we hold extents->mtx and so don't need @@ -361,6 +404,43 @@ extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, cur_extents_npages - (size >> LG_PAGE), ATOMIC_RELAXED); } +/* + * Find an extent with size [min_size, max_size) to satisfy the alignment + * requirement. For each size, try only the first extent in the heap. + */ +static extent_t * +extents_fit_alignment(extents_t *extents, size_t min_size, size_t max_size, + size_t alignment) { + pszind_t pind = sz_psz2ind(extent_size_quantize_ceil(min_size)); + pszind_t pind_max = sz_psz2ind(extent_size_quantize_ceil(max_size)); + + for (pszind_t i = (pszind_t)bitmap_ffu(extents->bitmap, + &extents_bitmap_info, (size_t)pind); i < pind_max; i = + (pszind_t)bitmap_ffu(extents->bitmap, &extents_bitmap_info, + (size_t)i+1)) { + assert(i < SC_NPSIZES); + assert(!extent_heap_empty(&extents->heaps[i])); + extent_t *extent = extent_heap_first(&extents->heaps[i]); + uintptr_t base = (uintptr_t)extent_base_get(extent); + size_t candidate_size = extent_size_get(extent); + assert(candidate_size >= min_size); + + uintptr_t next_align = ALIGNMENT_CEILING((uintptr_t)base, + PAGE_CEILING(alignment)); + if (base > next_align || base + candidate_size <= next_align) { + /* Overflow or not crossing the next alignment. */ + continue; + } + + size_t leadsize = next_align - base; + if (candidate_size - leadsize >= min_size) { + return extent; + } + } + + return NULL; +} + /* Do any-best-fit extent selection, i.e. select any extent that best fits. */ static extent_t * extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, @@ -368,9 +448,16 @@ extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, pszind_t pind = sz_psz2ind(extent_size_quantize_ceil(size)); pszind_t i = (pszind_t)bitmap_ffu(extents->bitmap, &extents_bitmap_info, (size_t)pind); - if (i < NPSIZES+1) { + if (i < SC_NPSIZES + 1) { + /* + * In order to reduce fragmentation, avoid reusing and splitting + * large extents for much smaller sizes. + */ + if ((sz_pind2sz(i) >> opt_lg_extent_max_active_fit) > size) { + return NULL; + } assert(!extent_heap_empty(&extents->heaps[i])); - extent_t *extent = extent_heap_any(&extents->heaps[i]); + extent_t *extent = extent_heap_first(&extents->heaps[i]); assert(extent_size_get(extent) >= size); return extent; } @@ -389,8 +476,9 @@ extents_first_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, pszind_t pind = sz_psz2ind(extent_size_quantize_ceil(size)); for (pszind_t i = (pszind_t)bitmap_ffu(extents->bitmap, - &extents_bitmap_info, (size_t)pind); i < NPSIZES+1; i = - (pszind_t)bitmap_ffu(extents->bitmap, &extents_bitmap_info, + &extents_bitmap_info, (size_t)pind); + i < SC_NPSIZES + 1; + i = (pszind_t)bitmap_ffu(extents->bitmap, &extents_bitmap_info, (size_t)i+1)) { assert(!extent_heap_empty(&extents->heaps[i])); extent_t *extent = extent_heap_first(&extents->heaps[i]); @@ -398,10 +486,10 @@ extents_first_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, if (ret == NULL || extent_snad_comp(extent, ret) < 0) { ret = extent; } - if (i == NPSIZES) { + if (i == SC_NPSIZES) { break; } - assert(i < NPSIZES); + assert(i < SC_NPSIZES); } return ret; @@ -415,12 +503,30 @@ extents_first_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, */ static extent_t * extents_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, - size_t size) { + size_t esize, size_t alignment) { malloc_mutex_assert_owner(tsdn, &extents->mtx); - return extents->delay_coalesce ? extents_best_fit_locked(tsdn, arena, - extents, size) : extents_first_fit_locked(tsdn, arena, extents, - size); + size_t max_size = esize + PAGE_CEILING(alignment) - PAGE; + /* Beware size_t wrap-around. */ + if (max_size < esize) { + return NULL; + } + + extent_t *extent = extents->delay_coalesce ? + extents_best_fit_locked(tsdn, arena, extents, max_size) : + extents_first_fit_locked(tsdn, arena, extents, max_size); + + if (alignment > PAGE && extent == NULL) { + /* + * max_size guarantees the alignment requirement but is rather + * pessimistic. Next we try to satisfy the aligned allocation + * with sizes in [esize, max_size). + */ + extent = extents_fit_alignment(extents, esize, max_size, + alignment); + } + + return extent; } static bool @@ -436,7 +542,7 @@ extent_try_delayed_coalesce(tsdn_t *tsdn, arena_t *arena, if (!coalesced) { return true; } - extents_insert_locked(tsdn, extents, extent, true); + extents_insert_locked(tsdn, extents, extent); return false; } @@ -449,8 +555,10 @@ extents_alloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); - return extent_recycle(tsdn, arena, r_extent_hooks, extents, new_addr, - size, pad, alignment, slab, szind, zero, commit, false); + extent_t *extent = extent_recycle(tsdn, arena, r_extent_hooks, extents, + new_addr, size, pad, alignment, slab, szind, zero, commit, false); + assert(extent == NULL || extent_dumpable_get(extent)); + return extent; } void @@ -458,6 +566,7 @@ extents_dalloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extents_t *extents, extent_t *extent) { assert(extent_base_get(extent) != NULL); assert(extent_size_get(extent) != 0); + assert(extent_dumpable_get(extent)); witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); @@ -487,14 +596,13 @@ extents_evict(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, goto label_return; } /* Check the eviction limit. */ - size_t npages = extent_size_get(extent) >> LG_PAGE; size_t extents_npages = atomic_load_zu(&extents->npages, ATOMIC_RELAXED); - if (extents_npages - npages < npages_min) { + if (extents_npages <= npages_min) { extent = NULL; goto label_return; } - extents_remove_locked(tsdn, extents, extent, false); + extents_remove_locked(tsdn, extents, extent); if (!extents->delay_coalesce) { break; } @@ -567,29 +675,29 @@ extents_postfork_child(tsdn_t *tsdn, extents_t *extents) { static void extent_deactivate_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, - extent_t *extent, bool preserve_lru) { + extent_t *extent) { assert(extent_arena_get(extent) == arena); assert(extent_state_get(extent) == extent_state_active); extent_state_set(extent, extents_state_get(extents)); - extents_insert_locked(tsdn, extents, extent, preserve_lru); + extents_insert_locked(tsdn, extents, extent); } static void extent_deactivate(tsdn_t *tsdn, arena_t *arena, extents_t *extents, - extent_t *extent, bool preserve_lru) { + extent_t *extent) { malloc_mutex_lock(tsdn, &extents->mtx); - extent_deactivate_locked(tsdn, arena, extents, extent, preserve_lru); + extent_deactivate_locked(tsdn, arena, extents, extent); malloc_mutex_unlock(tsdn, &extents->mtx); } static void extent_activate_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, - extent_t *extent, bool preserve_lru) { + extent_t *extent) { assert(extent_arena_get(extent) == arena); assert(extent_state_get(extent) == extents_state_get(extents)); - extents_remove_locked(tsdn, extents, extent, preserve_lru); + extents_remove_locked(tsdn, extents, extent); extent_state_set(extent, extent_state_active); } @@ -688,6 +796,7 @@ extent_register_impl(tsdn_t *tsdn, extent_t *extent, bool gdump_add) { if (extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, extent, false, true, &elm_a, &elm_b)) { + extent_unlock(tsdn, extent); return true; } @@ -723,6 +832,13 @@ extent_reregister(tsdn_t *tsdn, extent_t *extent) { assert(!err); } +/* + * Removes all pointers to the given extent from the global rtree indices for + * its interior. This is relevant for slab extents, for which we need to do + * metadata lookups at places other than the head of the extent. We deregister + * on the interior, then, when an extent moves from being an active slab to an + * inactive state. + */ static void extent_interior_deregister(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, extent_t *extent) { @@ -737,8 +853,11 @@ extent_interior_deregister(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, } } +/* + * Removes all pointers to the given extent from the global rtree. + */ static void -extent_deregister(tsdn_t *tsdn, extent_t *extent) { +extent_deregister_impl(tsdn_t *tsdn, extent_t *extent, bool gdump) { rtree_ctx_t rtree_ctx_fallback; rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); rtree_leaf_elm_t *elm_a, *elm_b; @@ -747,7 +866,7 @@ extent_deregister(tsdn_t *tsdn, extent_t *extent) { extent_lock(tsdn, extent); - extent_rtree_write_acquired(tsdn, elm_a, elm_b, NULL, NSIZES, false); + extent_rtree_write_acquired(tsdn, elm_a, elm_b, NULL, SC_NSIZES, false); if (extent_slab_get(extent)) { extent_interior_deregister(tsdn, rtree_ctx, extent); extent_slab_set(extent, false); @@ -755,16 +874,30 @@ extent_deregister(tsdn_t *tsdn, extent_t *extent) { extent_unlock(tsdn, extent); - if (config_prof) { + if (config_prof && gdump) { extent_gdump_sub(tsdn, extent); } } +static void +extent_deregister(tsdn_t *tsdn, extent_t *extent) { + extent_deregister_impl(tsdn, extent, true); +} + +static void +extent_deregister_no_gdump_sub(tsdn_t *tsdn, extent_t *extent) { + extent_deregister_impl(tsdn, extent, false); +} + +/* + * Tries to find and remove an extent from extents that can be used for the + * given allocation request. + */ static extent_t * extent_recycle_extract(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, void *new_addr, size_t size, size_t pad, size_t alignment, bool slab, - bool *zero, bool *commit, bool growing_retained) { + bool growing_retained) { witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, growing_retained ? 1 : 0); assert(alignment > 0); @@ -786,16 +919,12 @@ extent_recycle_extract(tsdn_t *tsdn, arena_t *arena, } size_t esize = size + pad; - size_t alloc_size = esize + PAGE_CEILING(alignment) - PAGE; - /* Beware size_t wrap-around. */ - if (alloc_size < esize) { - return NULL; - } malloc_mutex_lock(tsdn, &extents->mtx); extent_hooks_assure_initialized(arena, r_extent_hooks); extent_t *extent; if (new_addr != NULL) { - extent = extent_lock_from_addr(tsdn, rtree_ctx, new_addr); + extent = extent_lock_from_addr(tsdn, rtree_ctx, new_addr, + false); if (extent != NULL) { /* * We might null-out extent to report an error, but we @@ -812,86 +941,183 @@ extent_recycle_extract(tsdn_t *tsdn, arena_t *arena, extent_unlock(tsdn, unlock_extent); } } else { - extent = extents_fit_locked(tsdn, arena, extents, alloc_size); + extent = extents_fit_locked(tsdn, arena, extents, esize, + alignment); } if (extent == NULL) { malloc_mutex_unlock(tsdn, &extents->mtx); return NULL; } - extent_activate_locked(tsdn, arena, extents, extent, false); + extent_activate_locked(tsdn, arena, extents, extent); malloc_mutex_unlock(tsdn, &extents->mtx); - if (extent_zeroed_get(extent)) { - *zero = true; - } - if (extent_committed_get(extent)) { - *commit = true; - } - return extent; } -static extent_t * -extent_recycle_split(tsdn_t *tsdn, arena_t *arena, - extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, +/* + * Given an allocation request and an extent guaranteed to be able to satisfy + * it, this splits off lead and trail extents, leaving extent pointing to an + * extent satisfying the allocation. + * This function doesn't put lead or trail into any extents_t; it's the caller's + * job to ensure that they can be reused. + */ +typedef enum { + /* + * Split successfully. lead, extent, and trail, are modified to extents + * describing the ranges before, in, and after the given allocation. + */ + extent_split_interior_ok, + /* + * The extent can't satisfy the given allocation request. None of the + * input extent_t *s are touched. + */ + extent_split_interior_cant_alloc, + /* + * In a potentially invalid state. Must leak (if *to_leak is non-NULL), + * and salvage what's still salvageable (if *to_salvage is non-NULL). + * None of lead, extent, or trail are valid. + */ + extent_split_interior_error +} extent_split_interior_result_t; + +static extent_split_interior_result_t +extent_split_interior(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, + /* The result of splitting, in case of success. */ + extent_t **extent, extent_t **lead, extent_t **trail, + /* The mess to clean up, in case of error. */ + extent_t **to_leak, extent_t **to_salvage, void *new_addr, size_t size, size_t pad, size_t alignment, bool slab, - szind_t szind, extent_t *extent, bool growing_retained) { + szind_t szind, bool growing_retained) { size_t esize = size + pad; - size_t leadsize = ALIGNMENT_CEILING((uintptr_t)extent_base_get(extent), - PAGE_CEILING(alignment)) - (uintptr_t)extent_base_get(extent); + size_t leadsize = ALIGNMENT_CEILING((uintptr_t)extent_base_get(*extent), + PAGE_CEILING(alignment)) - (uintptr_t)extent_base_get(*extent); assert(new_addr == NULL || leadsize == 0); - assert(extent_size_get(extent) >= leadsize + esize); - size_t trailsize = extent_size_get(extent) - leadsize - esize; + if (extent_size_get(*extent) < leadsize + esize) { + return extent_split_interior_cant_alloc; + } + size_t trailsize = extent_size_get(*extent) - leadsize - esize; + + *lead = NULL; + *trail = NULL; + *to_leak = NULL; + *to_salvage = NULL; /* Split the lead. */ if (leadsize != 0) { - extent_t *lead = extent; - extent = extent_split_impl(tsdn, arena, r_extent_hooks, - lead, leadsize, NSIZES, false, esize + trailsize, szind, + *lead = *extent; + *extent = extent_split_impl(tsdn, arena, r_extent_hooks, + *lead, leadsize, SC_NSIZES, false, esize + trailsize, szind, slab, growing_retained); - if (extent == NULL) { - extent_deregister(tsdn, lead); - extents_leak(tsdn, arena, r_extent_hooks, extents, - lead, growing_retained); - return NULL; + if (*extent == NULL) { + *to_leak = *lead; + *lead = NULL; + return extent_split_interior_error; } - extent_deactivate(tsdn, arena, extents, lead, false); } /* Split the trail. */ if (trailsize != 0) { - extent_t *trail = extent_split_impl(tsdn, arena, - r_extent_hooks, extent, esize, szind, slab, trailsize, - NSIZES, false, growing_retained); - if (trail == NULL) { - extent_deregister(tsdn, extent); - extents_leak(tsdn, arena, r_extent_hooks, extents, - extent, growing_retained); - return NULL; + *trail = extent_split_impl(tsdn, arena, r_extent_hooks, *extent, + esize, szind, slab, trailsize, SC_NSIZES, false, + growing_retained); + if (*trail == NULL) { + *to_leak = *extent; + *to_salvage = *lead; + *lead = NULL; + *extent = NULL; + return extent_split_interior_error; } - extent_deactivate(tsdn, arena, extents, trail, false); - } else if (leadsize == 0) { + } + + if (leadsize == 0 && trailsize == 0) { /* * Splitting causes szind to be set as a side effect, but no * splitting occurred. */ - extent_szind_set(extent, szind); - if (szind != NSIZES) { + extent_szind_set(*extent, szind); + if (szind != SC_NSIZES) { rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, - (uintptr_t)extent_addr_get(extent), szind, slab); - if (slab && extent_size_get(extent) > PAGE) { + (uintptr_t)extent_addr_get(*extent), szind, slab); + if (slab && extent_size_get(*extent) > PAGE) { rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, - (uintptr_t)extent_past_get(extent) - + (uintptr_t)extent_past_get(*extent) - (uintptr_t)PAGE, szind, slab); } } } - return extent; + return extent_split_interior_ok; } +/* + * This fulfills the indicated allocation request out of the given extent (which + * the caller should have ensured was big enough). If there's any unused space + * before or after the resulting allocation, that space is given its own extent + * and put back into extents. + */ +static extent_t * +extent_recycle_split(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + void *new_addr, size_t size, size_t pad, size_t alignment, bool slab, + szind_t szind, extent_t *extent, bool growing_retained) { + extent_t *lead; + extent_t *trail; + extent_t *to_leak; + extent_t *to_salvage; + + extent_split_interior_result_t result = extent_split_interior( + tsdn, arena, r_extent_hooks, rtree_ctx, &extent, &lead, &trail, + &to_leak, &to_salvage, new_addr, size, pad, alignment, slab, szind, + growing_retained); + + if (result == extent_split_interior_ok) { + if (lead != NULL) { + extent_deactivate(tsdn, arena, extents, lead); + } + if (trail != NULL) { + extent_deactivate(tsdn, arena, extents, trail); + } + return extent; + } else { + /* + * We should have picked an extent that was large enough to + * fulfill our allocation request. + */ + assert(result == extent_split_interior_error); + if (to_salvage != NULL) { + extent_deregister(tsdn, to_salvage); + } + if (to_leak != NULL) { + void *leak = extent_base_get(to_leak); + extent_deregister_no_gdump_sub(tsdn, to_leak); + extents_leak(tsdn, arena, r_extent_hooks, extents, + to_leak, growing_retained); + assert(extent_lock_from_addr(tsdn, rtree_ctx, leak, + false) == NULL); + } + return NULL; + } + unreachable(); +} + +static bool +extent_need_manual_zero(arena_t *arena) { + /* + * Need to manually zero the extent on repopulating if either; 1) non + * default extent hooks installed (in which case the purge semantics may + * change); or 2) transparent huge pages enabled. + */ + return (!arena_has_default_hooks(arena) || + (opt_thp == thp_mode_always)); +} + +/* + * Tries to satisfy the given allocation request by reusing one of the extents + * in the given extents_t. + */ static extent_t * extent_recycle(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extents_t *extents, void *new_addr, size_t size, size_t pad, @@ -906,16 +1132,12 @@ extent_recycle(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, rtree_ctx_t rtree_ctx_fallback; rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); - bool committed = false; extent_t *extent = extent_recycle_extract(tsdn, arena, r_extent_hooks, - rtree_ctx, extents, new_addr, size, pad, alignment, slab, zero, - &committed, growing_retained); + rtree_ctx, extents, new_addr, size, pad, alignment, slab, + growing_retained); if (extent == NULL) { return NULL; } - if (committed) { - *commit = true; - } extent = extent_recycle_split(tsdn, arena, r_extent_hooks, rtree_ctx, extents, new_addr, size, pad, alignment, slab, szind, extent, @@ -931,7 +1153,16 @@ extent_recycle(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extent, growing_retained); return NULL; } - extent_zeroed_set(extent, true); + if (!extent_need_manual_zero(arena)) { + extent_zeroed_set(extent, true); + } + } + + if (extent_committed_get(extent)) { + *commit = true; + } + if (extent_zeroed_get(extent)) { + *zero = true; } if (pad != 0) { @@ -945,14 +1176,16 @@ extent_recycle(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, if (*zero) { void *addr = extent_base_get(extent); - size_t size = extent_size_get(extent); if (!extent_zeroed_get(extent)) { - if (pages_purge_forced(addr, size)) { + size_t size = extent_size_get(extent); + if (extent_need_manual_zero(arena) || + pages_purge_forced(addr, size)) { memset(addr, 0, size); } } else if (config_debug) { size_t *p = (size_t *)(uintptr_t)addr; - for (size_t i = 0; i < size / sizeof(size_t); i++) { + /* Check the first page only. */ + for (size_t i = 0; i < PAGE / sizeof(size_t); i++) { assert(p[i] == 0); } } @@ -999,11 +1232,12 @@ extent_alloc_core(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, static void * extent_alloc_default_impl(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit) { - void *ret; - - ret = extent_alloc_core(tsdn, arena, new_addr, size, alignment, zero, + void *ret = extent_alloc_core(tsdn, arena, new_addr, size, alignment, zero, commit, (dss_prec_t)atomic_load_u(&arena->dss_prec, ATOMIC_RELAXED)); + if (have_madvise_huge && ret) { + pages_set_thp_state(ret, size); + } return ret; } @@ -1028,7 +1262,18 @@ extent_alloc_default(extent_hooks_t *extent_hooks, void *new_addr, size_t size, static void extent_hook_pre_reentrancy(tsdn_t *tsdn, arena_t *arena) { tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn); - pre_reentrancy(tsd, arena); + if (arena == arena_get(tsd_tsdn(tsd), 0, false)) { + /* + * The only legitimate case of customized extent hooks for a0 is + * hooks with no allocation activities. One such example is to + * place metadata on pre-allocated resources such as huge pages. + * In that case, rely on reentrancy_level checks to catch + * infinite recursions. + */ + pre_reentrancy(tsd, NULL); + } else { + pre_reentrancy(tsd, arena); + } } static void @@ -1064,11 +1309,11 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena, size_t alloc_size = sz_pind2sz(arena->extent_grow_next + egn_skip); while (alloc_size < alloc_size_min) { egn_skip++; - if (arena->extent_grow_next + egn_skip == NPSIZES) { + if (arena->extent_grow_next + egn_skip >= + sz_psz2ind(SC_LARGE_MAXCLASS)) { /* Outside legal range. */ goto label_err; } - assert(arena->extent_grow_next + egn_skip < NPSIZES); alloc_size = sz_pind2sz(arena->extent_grow_next + egn_skip); } @@ -1081,9 +1326,8 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena, void *ptr; if (*r_extent_hooks == &extent_hooks_default) { - ptr = extent_alloc_core(tsdn, arena, NULL, alloc_size, PAGE, - &zeroed, &committed, (dss_prec_t)atomic_load_u( - &arena->dss_prec, ATOMIC_RELAXED)); + ptr = extent_alloc_default_impl(tsdn, arena, NULL, + alloc_size, PAGE, &zeroed, &committed); } else { extent_hook_pre_reentrancy(tsdn, arena); ptr = (*r_extent_hooks)->alloc(*r_extent_hooks, NULL, @@ -1092,23 +1336,20 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena, extent_hook_post_reentrancy(tsdn); } - extent_init(extent, arena, ptr, alloc_size, false, NSIZES, + extent_init(extent, arena, ptr, alloc_size, false, SC_NSIZES, arena_extent_sn_next(arena), extent_state_active, zeroed, - committed); + committed, true); if (ptr == NULL) { extent_dalloc(tsdn, arena, extent); goto label_err; } + if (extent_register_no_gdump_add(tsdn, extent)) { extents_leak(tsdn, arena, r_extent_hooks, &arena->extents_retained, extent, true); goto label_err; } - size_t leadsize = ALIGNMENT_CEILING((uintptr_t)ptr, - PAGE_CEILING(alignment)) - (uintptr_t)ptr; - assert(alloc_size >= leadsize + esize); - size_t trailsize = alloc_size - leadsize - esize; if (extent_zeroed_get(extent) && extent_committed_get(extent)) { *zero = true; } @@ -1116,54 +1357,46 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena, *commit = true; } - /* Split the lead. */ - if (leadsize != 0) { - extent_t *lead = extent; - extent = extent_split_impl(tsdn, arena, r_extent_hooks, lead, - leadsize, NSIZES, false, esize + trailsize, szind, slab, - true); - if (extent == NULL) { - extent_deregister(tsdn, lead); - extents_leak(tsdn, arena, r_extent_hooks, + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + extent_t *lead; + extent_t *trail; + extent_t *to_leak; + extent_t *to_salvage; + extent_split_interior_result_t result = extent_split_interior( + tsdn, arena, r_extent_hooks, rtree_ctx, &extent, &lead, &trail, + &to_leak, &to_salvage, NULL, size, pad, alignment, slab, szind, + true); + + if (result == extent_split_interior_ok) { + if (lead != NULL) { + extent_record(tsdn, arena, r_extent_hooks, &arena->extents_retained, lead, true); - goto label_err; } - extent_record(tsdn, arena, r_extent_hooks, - &arena->extents_retained, lead, true); - } - - /* Split the trail. */ - if (trailsize != 0) { - extent_t *trail = extent_split_impl(tsdn, arena, r_extent_hooks, - extent, esize, szind, slab, trailsize, NSIZES, false, true); - if (trail == NULL) { - extent_deregister(tsdn, extent); - extents_leak(tsdn, arena, r_extent_hooks, - &arena->extents_retained, extent, true); - goto label_err; + if (trail != NULL) { + extent_record(tsdn, arena, r_extent_hooks, + &arena->extents_retained, trail, true); } - extent_record(tsdn, arena, r_extent_hooks, - &arena->extents_retained, trail, true); - } else if (leadsize == 0) { + } else { /* - * Splitting causes szind to be set as a side effect, but no - * splitting occurred. + * We should have allocated a sufficiently large extent; the + * cant_alloc case should not occur. */ - rtree_ctx_t rtree_ctx_fallback; - rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, - &rtree_ctx_fallback); - - extent_szind_set(extent, szind); - if (szind != NSIZES) { - rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, - (uintptr_t)extent_addr_get(extent), szind, slab); - if (slab && extent_size_get(extent) > PAGE) { - rtree_szind_slab_update(tsdn, &extents_rtree, - rtree_ctx, - (uintptr_t)extent_past_get(extent) - - (uintptr_t)PAGE, szind, slab); + assert(result == extent_split_interior_error); + if (to_salvage != NULL) { + if (config_prof) { + extent_gdump_add(tsdn, to_salvage); } + extent_record(tsdn, arena, r_extent_hooks, + &arena->extents_retained, to_salvage, true); } + if (to_leak != NULL) { + extent_deregister_no_gdump_sub(tsdn, to_leak); + extents_leak(tsdn, arena, r_extent_hooks, + &arena->extents_retained, to_leak, true); + } + goto label_err; } if (*commit && !extent_committed_get(extent)) { @@ -1173,17 +1406,20 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena, &arena->extents_retained, extent, true); goto label_err; } - extent_zeroed_set(extent, true); + if (!extent_need_manual_zero(arena)) { + extent_zeroed_set(extent, true); + } } /* - * Increment extent_grow_next if doing so wouldn't exceed the legal + * Increment extent_grow_next if doing so wouldn't exceed the allowed * range. */ - if (arena->extent_grow_next + egn_skip + 1 < NPSIZES) { + if (arena->extent_grow_next + egn_skip + 1 <= + arena->retain_grow_limit) { arena->extent_grow_next += egn_skip + 1; } else { - arena->extent_grow_next = NPSIZES - 1; + arena->extent_grow_next = arena->retain_grow_limit; } /* All opportunities for failure are past. */ malloc_mutex_unlock(tsdn, &arena->extent_grow_mtx); @@ -1206,7 +1442,8 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena, if (*zero && !extent_zeroed_get(extent)) { void *addr = extent_base_get(extent); size_t size = extent_size_get(extent); - if (pages_purge_forced(addr, size)) { + if (extent_need_manual_zero(arena) || + pages_purge_forced(addr, size)) { memset(addr, 0, size); } } @@ -1271,7 +1508,8 @@ extent_alloc_wrapper_hard(tsdn_t *tsdn, arena_t *arena, return NULL; } extent_init(extent, arena, addr, esize, slab, szind, - arena_extent_sn_next(arena), extent_state_active, zero, commit); + arena_extent_sn_next(arena), extent_state_active, *zero, *commit, + true); if (pad != 0) { extent_addr_randomize(tsdn, extent, alignment); } @@ -1296,10 +1534,20 @@ extent_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, extent_t *extent = extent_alloc_retained(tsdn, arena, r_extent_hooks, new_addr, size, pad, alignment, slab, szind, zero, commit); if (extent == NULL) { + if (opt_retain && new_addr != NULL) { + /* + * When retain is enabled and new_addr is set, we do not + * attempt extent_alloc_wrapper_hard which does mmap + * that is very unlikely to succeed (unless it happens + * to be at the end). + */ + return NULL; + } extent = extent_alloc_wrapper_hard(tsdn, arena, r_extent_hooks, new_addr, size, pad, alignment, slab, szind, zero, commit); } + assert(extent == NULL || extent_dumpable_get(extent)); return extent; } @@ -1329,16 +1577,7 @@ extent_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, bool growing_retained) { assert(extent_can_coalesce(arena, extents, inner, outer)); - if (forward && extents->delay_coalesce) { - /* - * The extent that remains after coalescing must occupy the - * outer extent's position in the LRU. For forward coalescing, - * swap the inner extent into the LRU. - */ - extent_list_replace(&extents->lru, outer, inner); - } - extent_activate_locked(tsdn, arena, extents, outer, - extents->delay_coalesce); + extent_activate_locked(tsdn, arena, extents, outer); malloc_mutex_unlock(tsdn, &extents->mtx); bool err = extent_merge_impl(tsdn, arena, r_extent_hooks, @@ -1346,20 +1585,22 @@ extent_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, malloc_mutex_lock(tsdn, &extents->mtx); if (err) { - if (forward && extents->delay_coalesce) { - extent_list_replace(&extents->lru, inner, outer); - } - extent_deactivate_locked(tsdn, arena, extents, outer, - extents->delay_coalesce); + extent_deactivate_locked(tsdn, arena, extents, outer); } return err; } static extent_t * -extent_try_coalesce(tsdn_t *tsdn, arena_t *arena, +extent_try_coalesce_impl(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, - extent_t *extent, bool *coalesced, bool growing_retained) { + extent_t *extent, bool *coalesced, bool growing_retained, + bool inactive_only) { + /* + * We avoid checking / locking inactive neighbors for large size + * classes, since they are eagerly coalesced on deallocation which can + * cause lock contention. + */ /* * Continue attempting to coalesce until failure, to protect against * races with other threads that are thwarted by this one. @@ -1370,7 +1611,7 @@ extent_try_coalesce(tsdn_t *tsdn, arena_t *arena, /* Try to coalesce forward. */ extent_t *next = extent_lock_from_addr(tsdn, rtree_ctx, - extent_past_get(extent)); + extent_past_get(extent), inactive_only); if (next != NULL) { /* * extents->mtx only protects against races for @@ -1396,7 +1637,7 @@ extent_try_coalesce(tsdn_t *tsdn, arena_t *arena, /* Try to coalesce backward. */ extent_t *prev = extent_lock_from_addr(tsdn, rtree_ctx, - extent_before_get(extent)); + extent_before_get(extent), inactive_only); if (prev != NULL) { bool can_coalesce = extent_can_coalesce(arena, extents, extent, prev); @@ -1422,6 +1663,26 @@ extent_try_coalesce(tsdn_t *tsdn, arena_t *arena, return extent; } +static extent_t * +extent_try_coalesce(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + extent_t *extent, bool *coalesced, bool growing_retained) { + return extent_try_coalesce_impl(tsdn, arena, r_extent_hooks, rtree_ctx, + extents, extent, coalesced, growing_retained, false); +} + +static extent_t * +extent_try_coalesce_large(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + extent_t *extent, bool *coalesced, bool growing_retained) { + return extent_try_coalesce_impl(tsdn, arena, r_extent_hooks, rtree_ctx, + extents, extent, coalesced, growing_retained, true); +} + +/* + * Does the metadata management portions of putting an unused extent into the + * given extents_t (coalesces, deregisters slab interiors, the heap operations). + */ static void extent_record(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extents_t *extents, extent_t *extent, bool growing_retained) { @@ -1435,7 +1696,7 @@ extent_record(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, malloc_mutex_lock(tsdn, &extents->mtx); extent_hooks_assure_initialized(arena, r_extent_hooks); - extent_szind_set(extent, NSIZES); + extent_szind_set(extent, SC_NSIZES); if (extent_slab_get(extent)) { extent_interior_deregister(tsdn, rtree_ctx, extent); extent_slab_set(extent, false); @@ -1447,9 +1708,24 @@ extent_record(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, if (!extents->delay_coalesce) { extent = extent_try_coalesce(tsdn, arena, r_extent_hooks, rtree_ctx, extents, extent, NULL, growing_retained); + } else if (extent_size_get(extent) >= SC_LARGE_MINCLASS) { + assert(extents == &arena->extents_dirty); + /* Always coalesce large extents eagerly. */ + bool coalesced; + do { + assert(extent_state_get(extent) == extent_state_active); + extent = extent_try_coalesce_large(tsdn, arena, + r_extent_hooks, rtree_ctx, extents, extent, + &coalesced, growing_retained); + } while (coalesced); + if (extent_size_get(extent) >= oversize_threshold) { + /* Shortcut to purge the oversize extent eagerly. */ + malloc_mutex_unlock(tsdn, &extents->mtx); + arena_decay_extent(tsdn, arena, r_extent_hooks, extent); + return; + } } - - extent_deactivate_locked(tsdn, arena, extents, extent, false); + extent_deactivate_locked(tsdn, arena, extents, extent); malloc_mutex_unlock(tsdn, &extents->mtx); } @@ -1469,6 +1745,12 @@ extent_dalloc_gap(tsdn_t *tsdn, arena_t *arena, extent_t *extent) { extent_dalloc_wrapper(tsdn, arena, &extent_hooks, extent); } +static bool +extent_may_dalloc(void) { + /* With retain enabled, the default dalloc always fails. */ + return !opt_retain; +} + static bool extent_dalloc_default_impl(void *addr, size_t size) { if (!have_dss || !extent_in_dss(addr)) { @@ -1520,19 +1802,24 @@ extent_dalloc_wrapper_try(tsdn_t *tsdn, arena_t *arena, void extent_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extent_t *extent) { + assert(extent_dumpable_get(extent)); witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); - /* - * Deregister first to avoid a race with other allocating threads, and - * reregister if deallocation fails. - */ - extent_deregister(tsdn, extent); - if (!extent_dalloc_wrapper_try(tsdn, arena, r_extent_hooks, extent)) { - return; + /* Avoid calling the default extent_dalloc unless have to. */ + if (*r_extent_hooks != &extent_hooks_default || extent_may_dalloc()) { + /* + * Deregister first to avoid a race with other allocating + * threads, and reregister if deallocation fails. + */ + extent_deregister(tsdn, extent); + if (!extent_dalloc_wrapper_try(tsdn, arena, r_extent_hooks, + extent)) { + return; + } + extent_reregister(tsdn, extent); } - extent_reregister(tsdn, extent); if (*r_extent_hooks != &extent_hooks_default) { extent_hook_pre_reentrancy(tsdn, arena); } @@ -1780,6 +2067,13 @@ extent_split_default(extent_hooks_t *extent_hooks, void *addr, size_t size, } #endif +/* + * Accepts the extent to split, and the characteristics of each side of the + * split. The 'a' parameters go with the 'lead' of the resulting pair of + * extents (the lower addressed portion of the split), and the 'b' parameters go + * with the trail (the higher addressed portion). This makes 'extent' the lead, + * and returns the trail (except in case of error). + */ static extent_t * extent_split_impl(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extent_t *extent, size_t size_a, @@ -1803,7 +2097,7 @@ extent_split_impl(tsdn_t *tsdn, arena_t *arena, extent_init(trail, arena, (void *)((uintptr_t)extent_base_get(extent) + size_a), size_b, slab_b, szind_b, extent_sn_get(extent), extent_state_get(extent), extent_zeroed_get(extent), - extent_committed_get(extent)); + extent_committed_get(extent), extent_dumpable_get(extent)); rtree_ctx_t rtree_ctx_fallback; rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); @@ -1814,7 +2108,7 @@ extent_split_impl(tsdn_t *tsdn, arena_t *arena, extent_init(&lead, arena, extent_addr_get(extent), size_a, slab_a, szind_a, extent_sn_get(extent), extent_state_get(extent), extent_zeroed_get(extent), - extent_committed_get(extent)); + extent_committed_get(extent), extent_dumpable_get(extent)); extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, &lead, false, true, &lead_elm_a, &lead_elm_b); @@ -1938,22 +2232,23 @@ extent_merge_impl(tsdn_t *tsdn, arena_t *arena, if (a_elm_b != NULL) { rtree_leaf_elm_write(tsdn, &extents_rtree, a_elm_b, NULL, - NSIZES, false); + SC_NSIZES, false); } if (b_elm_b != NULL) { rtree_leaf_elm_write(tsdn, &extents_rtree, b_elm_a, NULL, - NSIZES, false); + SC_NSIZES, false); } else { b_elm_b = b_elm_a; } extent_size_set(a, extent_size_get(a) + extent_size_get(b)); - extent_szind_set(a, NSIZES); + extent_szind_set(a, SC_NSIZES); extent_sn_set(a, (extent_sn_get(a) < extent_sn_get(b)) ? extent_sn_get(a) : extent_sn_get(b)); extent_zeroed_set(a, extent_zeroed_get(a) && extent_zeroed_get(b)); - extent_rtree_write_acquired(tsdn, a_elm_a, b_elm_b, a, NSIZES, false); + extent_rtree_write_acquired(tsdn, a_elm_a, b_elm_b, a, SC_NSIZES, + false); extent_unlock2(tsdn, a, b); diff --git a/kbe/src/lib/dependencies/jemalloc/src/extent_dss.c b/kbe/src/lib/dependencies/jemalloc/src/extent_dss.c index e72da95870..6c56cf6568 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/extent_dss.c +++ b/kbe/src/lib/dependencies/jemalloc/src/extent_dss.c @@ -154,9 +154,9 @@ extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, (uintptr_t)gap_addr_page; if (gap_size_page != 0) { extent_init(gap, arena, gap_addr_page, - gap_size_page, false, NSIZES, + gap_size_page, false, SC_NSIZES, arena_extent_sn_next(arena), - extent_state_active, false, true); + extent_state_active, false, true, true); } /* * Compute the address just past the end of the desired @@ -198,8 +198,9 @@ extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, extent_t extent; extent_init(&extent, arena, ret, size, - size, false, NSIZES, - extent_state_active, false, true); + size, false, SC_NSIZES, + extent_state_active, false, true, + true); if (extent_purge_forced_wrapper(tsdn, arena, &extent_hooks, &extent, 0, size)) { diff --git a/kbe/src/lib/dependencies/jemalloc/src/hook.c b/kbe/src/lib/dependencies/jemalloc/src/hook.c new file mode 100644 index 0000000000..9ac703cf9f --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/src/hook.c @@ -0,0 +1,195 @@ +#include "jemalloc/internal/jemalloc_preamble.h" + +#include "jemalloc/internal/hook.h" + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/seq.h" + +typedef struct hooks_internal_s hooks_internal_t; +struct hooks_internal_s { + hooks_t hooks; + bool in_use; +}; + +seq_define(hooks_internal_t, hooks) + +static atomic_u_t nhooks = ATOMIC_INIT(0); +static seq_hooks_t hooks[HOOK_MAX]; +static malloc_mutex_t hooks_mu; + +bool +hook_boot() { + return malloc_mutex_init(&hooks_mu, "hooks", WITNESS_RANK_HOOK, + malloc_mutex_rank_exclusive); +} + +static void * +hook_install_locked(hooks_t *to_install) { + hooks_internal_t hooks_internal; + for (int i = 0; i < HOOK_MAX; i++) { + bool success = seq_try_load_hooks(&hooks_internal, &hooks[i]); + /* We hold mu; no concurrent access. */ + assert(success); + if (!hooks_internal.in_use) { + hooks_internal.hooks = *to_install; + hooks_internal.in_use = true; + seq_store_hooks(&hooks[i], &hooks_internal); + atomic_store_u(&nhooks, + atomic_load_u(&nhooks, ATOMIC_RELAXED) + 1, + ATOMIC_RELAXED); + return &hooks[i]; + } + } + return NULL; +} + +void * +hook_install(tsdn_t *tsdn, hooks_t *to_install) { + malloc_mutex_lock(tsdn, &hooks_mu); + void *ret = hook_install_locked(to_install); + if (ret != NULL) { + tsd_global_slow_inc(tsdn); + } + malloc_mutex_unlock(tsdn, &hooks_mu); + return ret; +} + +static void +hook_remove_locked(seq_hooks_t *to_remove) { + hooks_internal_t hooks_internal; + bool success = seq_try_load_hooks(&hooks_internal, to_remove); + /* We hold mu; no concurrent access. */ + assert(success); + /* Should only remove hooks that were added. */ + assert(hooks_internal.in_use); + hooks_internal.in_use = false; + seq_store_hooks(to_remove, &hooks_internal); + atomic_store_u(&nhooks, atomic_load_u(&nhooks, ATOMIC_RELAXED) - 1, + ATOMIC_RELAXED); +} + +void +hook_remove(tsdn_t *tsdn, void *opaque) { + if (config_debug) { + char *hooks_begin = (char *)&hooks[0]; + char *hooks_end = (char *)&hooks[HOOK_MAX]; + char *hook = (char *)opaque; + assert(hooks_begin <= hook && hook < hooks_end + && (hook - hooks_begin) % sizeof(seq_hooks_t) == 0); + } + malloc_mutex_lock(tsdn, &hooks_mu); + hook_remove_locked((seq_hooks_t *)opaque); + tsd_global_slow_dec(tsdn); + malloc_mutex_unlock(tsdn, &hooks_mu); +} + +#define FOR_EACH_HOOK_BEGIN(hooks_internal_ptr) \ +for (int for_each_hook_counter = 0; \ + for_each_hook_counter < HOOK_MAX; \ + for_each_hook_counter++) { \ + bool for_each_hook_success = seq_try_load_hooks( \ + (hooks_internal_ptr), &hooks[for_each_hook_counter]); \ + if (!for_each_hook_success) { \ + continue; \ + } \ + if (!(hooks_internal_ptr)->in_use) { \ + continue; \ + } +#define FOR_EACH_HOOK_END \ +} + +static bool * +hook_reentrantp() { + /* + * We prevent user reentrancy within hooks. This is basically just a + * thread-local bool that triggers an early-exit. + * + * We don't fold in_hook into reentrancy. There are two reasons for + * this: + * - Right now, we turn on reentrancy during things like extent hook + * execution. Allocating during extent hooks is not officially + * supported, but we don't want to break it for the time being. These + * sorts of allocations should probably still be hooked, though. + * - If a hook allocates, we may want it to be relatively fast (after + * all, it executes on every allocator operation). Turning on + * reentrancy is a fairly heavyweight mode (disabling tcache, + * redirecting to arena 0, etc.). It's possible we may one day want + * to turn on reentrant mode here, if it proves too difficult to keep + * this working. But that's fairly easy for us to see; OTOH, people + * not using hooks because they're too slow is easy for us to miss. + * + * The tricky part is + * that this code might get invoked even if we don't have access to tsd. + * This function mimics getting a pointer to thread-local data, except + * that it might secretly return a pointer to some global data if we + * know that the caller will take the early-exit path. + * If we return a bool that indicates that we are reentrant, then the + * caller will go down the early exit path, leaving the global + * untouched. + */ + static bool in_hook_global = true; + tsdn_t *tsdn = tsdn_fetch(); + tcache_t *tcache = tsdn_tcachep_get(tsdn); + if (tcache != NULL) { + return &tcache->in_hook; + } + return &in_hook_global; +} + +#define HOOK_PROLOGUE \ + if (likely(atomic_load_u(&nhooks, ATOMIC_RELAXED) == 0)) { \ + return; \ + } \ + bool *in_hook = hook_reentrantp(); \ + if (*in_hook) { \ + return; \ + } \ + *in_hook = true; + +#define HOOK_EPILOGUE \ + *in_hook = false; + +void +hook_invoke_alloc(hook_alloc_t type, void *result, uintptr_t result_raw, + uintptr_t args_raw[3]) { + HOOK_PROLOGUE + + hooks_internal_t hook; + FOR_EACH_HOOK_BEGIN(&hook) + hook_alloc h = hook.hooks.alloc_hook; + if (h != NULL) { + h(hook.hooks.extra, type, result, result_raw, args_raw); + } + FOR_EACH_HOOK_END + + HOOK_EPILOGUE +} + +void +hook_invoke_dalloc(hook_dalloc_t type, void *address, uintptr_t args_raw[3]) { + HOOK_PROLOGUE + hooks_internal_t hook; + FOR_EACH_HOOK_BEGIN(&hook) + hook_dalloc h = hook.hooks.dalloc_hook; + if (h != NULL) { + h(hook.hooks.extra, type, address, args_raw); + } + FOR_EACH_HOOK_END + HOOK_EPILOGUE +} + +void +hook_invoke_expand(hook_expand_t type, void *address, size_t old_usize, + size_t new_usize, uintptr_t result_raw, uintptr_t args_raw[4]) { + HOOK_PROLOGUE + hooks_internal_t hook; + FOR_EACH_HOOK_BEGIN(&hook) + hook_expand h = hook.hooks.expand_hook; + if (h != NULL) { + h(hook.hooks.extra, type, address, old_usize, new_usize, + result_raw, args_raw); + } + FOR_EACH_HOOK_END + HOOK_EPILOGUE +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/jemalloc.c b/kbe/src/lib/dependencies/jemalloc/src/jemalloc.c index 0ee8ad48b9..c8afa9c4d5 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/jemalloc.c +++ b/kbe/src/lib/dependencies/jemalloc/src/jemalloc.c @@ -7,11 +7,13 @@ #include "jemalloc/internal/ctl.h" #include "jemalloc/internal/extent_dss.h" #include "jemalloc/internal/extent_mmap.h" +#include "jemalloc/internal/hook.h" #include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/log.h" #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/rtree.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" #include "jemalloc/internal/spin.h" #include "jemalloc/internal/sz.h" #include "jemalloc/internal/ticker.h" @@ -84,8 +86,10 @@ malloc_mutex_t arenas_lock; JEMALLOC_ALIGNED(CACHELINE) atomic_p_t arenas[MALLOCX_ARENA_LIMIT]; static atomic_u_t narenas_total; /* Use narenas_total_*(). */ -static arena_t *a0; /* arenas[0]; read-only after initialization. */ -unsigned narenas_auto; /* Read-only after initialization. */ +/* Below three are read-only after initialization. */ +static arena_t *a0; /* arenas[0]. */ +unsigned narenas_auto; +unsigned manual_arena_base; typedef enum { malloc_init_uninitialized = 3, @@ -325,7 +329,7 @@ arena_init_locked(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { */ arena = arena_get(tsdn, ind, false); if (arena != NULL) { - assert(ind < narenas_auto); + assert(arena_is_auto(arena)); return arena; } @@ -340,12 +344,12 @@ arena_new_create_background_thread(tsdn_t *tsdn, unsigned ind) { if (ind == 0) { return; } - if (have_background_thread) { - bool err; - malloc_mutex_lock(tsdn, &background_thread_lock); - err = background_thread_create(tsdn_tsd(tsdn), ind); - malloc_mutex_unlock(tsdn, &background_thread_lock); - if (err) { + /* + * Avoid creating a new background thread just for the huge arena, which + * purges eagerly by default. + */ + if (have_background_thread && !arena_is_huge(ind)) { + if (background_thread_create(tsdn_tsd(tsdn), ind)) { malloc_printf(": error in background thread " "creation for arena %u. Abort.\n", ind); abort(); @@ -375,6 +379,14 @@ arena_bind(tsd_t *tsd, unsigned ind, bool internal) { tsd_iarena_set(tsd, arena); } else { tsd_arena_set(tsd, arena); + unsigned shard = atomic_fetch_add_u(&arena->binshard_next, 1, + ATOMIC_RELAXED); + tsd_binshards_t *bins = tsd_binshardsp_get(tsd); + for (unsigned i = 0; i < SC_NBINS; i++) { + assert(bin_infos[i].n_shards > 0 && + bin_infos[i].n_shards <= BIN_SHARDS_MAX); + bins->binshard[i] = shard % bin_infos[i].n_shards; + } } } @@ -760,6 +772,50 @@ init_opt_stats_print_opts(const char *v, size_t vlen) { assert(opts_len == strlen(opt_stats_print_opts)); } +/* Reads the next size pair in a multi-sized option. */ +static bool +malloc_conf_multi_sizes_next(const char **slab_size_segment_cur, + size_t *vlen_left, size_t *slab_start, size_t *slab_end, size_t *new_size) { + const char *cur = *slab_size_segment_cur; + char *end; + uintmax_t um; + + set_errno(0); + + /* First number, then '-' */ + um = malloc_strtoumax(cur, &end, 0); + if (get_errno() != 0 || *end != '-') { + return true; + } + *slab_start = (size_t)um; + cur = end + 1; + + /* Second number, then ':' */ + um = malloc_strtoumax(cur, &end, 0); + if (get_errno() != 0 || *end != ':') { + return true; + } + *slab_end = (size_t)um; + cur = end + 1; + + /* Last number */ + um = malloc_strtoumax(cur, &end, 0); + if (get_errno() != 0) { + return true; + } + *new_size = (size_t)um; + + /* Consume the separator if there is one. */ + if (*end == '|') { + end++; + } + + *vlen_left -= end - *slab_size_segment_cur; + *slab_size_segment_cur = end; + + return false; +} + static bool malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, char const **v_p, size_t *vlen_p) { @@ -848,10 +904,13 @@ malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v, size_t vlen) { malloc_printf(": %s: %.*s:%.*s\n", msg, (int)klen, k, (int)vlen, v); - had_conf_error = true; - if (opt_abort_conf) { - malloc_abort_invalid_conf(); + /* If abort_conf is set, error out after processing all options. */ + const char *experimental = "experimental_"; + if (strncmp(k, experimental, strlen(experimental)) == 0) { + /* However, tolerate experimental features. */ + return; } + had_conf_error = true; } static void @@ -870,7 +929,7 @@ malloc_slow_flag_init(void) { } static void -malloc_conf_init(void) { +malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) { unsigned i; char buf[PATH_MAX + 1]; const char *opts, *k, *v; @@ -911,7 +970,12 @@ malloc_conf_init(void) { * Try to use the contents of the "/etc/malloc.conf" * symbolic link's name. */ +#ifndef JEMALLOC_READLINKAT linklen = readlink(linkname, buf, sizeof(buf) - 1); +#else + linklen = readlinkat(AT_FDCWD, linkname, buf, + sizeof(buf) - 1); +#endif if (linklen == -1) { /* No configuration specified. */ linklen = 0; @@ -968,6 +1032,14 @@ malloc_conf_init(void) { } \ continue; \ } + /* + * One of the CONF_MIN macros below expands, in one of the use points, + * to "unsigned integer < 0", which is always false, triggering the + * GCC -Wtype-limits warning, which we disable here and re-enable below. + */ + JEMALLOC_DIAGNOSTIC_PUSH + JEMALLOC_DIAGNOSTIC_IGNORE_TYPE_LIMITS + #define CONF_MIN_no(um, min) false #define CONF_MIN_yes(um, min) ((um) < (min)) #define CONF_MAX_no(um, max) false @@ -1051,8 +1123,22 @@ malloc_conf_init(void) { CONF_HANDLE_BOOL(opt_abort, "abort") CONF_HANDLE_BOOL(opt_abort_conf, "abort_conf") - if (opt_abort_conf && had_conf_error) { - malloc_abort_invalid_conf(); + if (strncmp("metadata_thp", k, klen) == 0) { + int i; + bool match = false; + for (i = 0; i < metadata_thp_mode_limit; i++) { + if (strncmp(metadata_thp_mode_names[i], + v, vlen) == 0) { + opt_metadata_thp = i; + match = true; + break; + } + } + if (!match) { + malloc_conf_error("Invalid conf value", + k, klen, v, vlen); + } + continue; } CONF_HANDLE_BOOL(opt_retain, "retain") if (strncmp("dss", k, klen) == 0) { @@ -1081,6 +1167,28 @@ malloc_conf_init(void) { } CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1, UINT_MAX, yes, no, false) + if (CONF_MATCH("bin_shards")) { + const char *bin_shards_segment_cur = v; + size_t vlen_left = vlen; + do { + size_t size_start; + size_t size_end; + size_t nshards; + bool err = malloc_conf_multi_sizes_next( + &bin_shards_segment_cur, &vlen_left, + &size_start, &size_end, &nshards); + if (err || bin_update_shard_size( + bin_shard_sizes, size_start, + size_end, nshards)) { + malloc_conf_error( + "Invalid settings for " + "bin_shards", k, klen, v, + vlen); + break; + } + } while (vlen_left > 0); + continue; + } CONF_HANDLE_SSIZE_T(opt_dirty_decay_ms, "dirty_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) < QU(SSIZE_MAX) ? NSTIME_SEC_MAX * KQU(1000) : @@ -1130,10 +1238,25 @@ malloc_conf_init(void) { CONF_HANDLE_BOOL(opt_tcache, "tcache") CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, "lg_tcache_max", -1, (sizeof(size_t) << 3) - 1) + + /* + * The runtime option of oversize_threshold remains + * undocumented. It may be tweaked in the next major + * release (6.0). The default value 8M is rather + * conservative / safe. Tuning it further down may + * improve fragmentation a bit more, but may also cause + * contention on the huge arena. + */ + CONF_HANDLE_SIZE_T(opt_oversize_threshold, + "oversize_threshold", 0, SC_LARGE_MAXCLASS, no, yes, + false) + CONF_HANDLE_SIZE_T(opt_lg_extent_max_active_fit, + "lg_extent_max_active_fit", 0, + (sizeof(size_t) << 3), no, yes, false) + if (strncmp("percpu_arena", k, klen) == 0) { - int i; bool match = false; - for (i = percpu_arena_mode_names_base; i < + for (int i = percpu_arena_mode_names_base; i < percpu_arena_mode_names_limit; i++) { if (strncmp(percpu_arena_mode_names[i], v, vlen) == 0) { @@ -1155,6 +1278,35 @@ malloc_conf_init(void) { } CONF_HANDLE_BOOL(opt_background_thread, "background_thread"); + CONF_HANDLE_SIZE_T(opt_max_background_threads, + "max_background_threads", 1, + opt_max_background_threads, yes, yes, + true); + if (CONF_MATCH("slab_sizes")) { + bool err; + const char *slab_size_segment_cur = v; + size_t vlen_left = vlen; + do { + size_t slab_start; + size_t slab_end; + size_t pgs; + err = malloc_conf_multi_sizes_next( + &slab_size_segment_cur, + &vlen_left, &slab_start, &slab_end, + &pgs); + if (!err) { + sc_data_update_slab_size( + sc_data, slab_start, + slab_end, (int)pgs); + } else { + malloc_conf_error( + "Invalid settings for " + "slab_sizes", k, klen, v, + vlen); + } + } while (!err && vlen_left > 0); + continue; + } if (config_prof) { CONF_HANDLE_BOOL(opt_prof, "prof") CONF_HANDLE_CHAR_P(opt_prof_prefix, @@ -1172,6 +1324,38 @@ malloc_conf_init(void) { CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump") CONF_HANDLE_BOOL(opt_prof_final, "prof_final") CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak") + CONF_HANDLE_BOOL(opt_prof_log, "prof_log") + } + if (config_log) { + if (CONF_MATCH("log")) { + size_t cpylen = ( + vlen <= sizeof(log_var_names) ? + vlen : sizeof(log_var_names) - 1); + strncpy(log_var_names, v, cpylen); + log_var_names[cpylen] = '\0'; + continue; + } + } + if (CONF_MATCH("thp")) { + bool match = false; + for (int i = 0; i < thp_mode_names_limit; i++) { + if (strncmp(thp_mode_names[i],v, vlen) + == 0) { + if (!have_madvise_huge) { + malloc_conf_error( + "No THP support", + k, klen, v, vlen); + } + opt_thp = i; + match = true; + break; + } + } + if (!match) { + malloc_conf_error("Invalid conf value", + k, klen, v, vlen); + } + continue; } malloc_conf_error("Invalid conf pair", k, klen, v, vlen); @@ -1187,8 +1371,14 @@ malloc_conf_init(void) { #undef CONF_HANDLE_SIZE_T #undef CONF_HANDLE_SSIZE_T #undef CONF_HANDLE_CHAR_P + /* Re-enable diagnostic "-Wtype-limits" */ + JEMALLOC_DIAGNOSTIC_POP + } + if (opt_abort_conf && had_conf_error) { + malloc_abort_invalid_conf(); } } + atomic_store_b(&log_init_done, true, ATOMIC_RELEASE); } static bool @@ -1221,10 +1411,33 @@ static bool malloc_init_hard_a0_locked() { malloc_initializer = INITIALIZER; + JEMALLOC_DIAGNOSTIC_PUSH + JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS + sc_data_t sc_data = {0}; + JEMALLOC_DIAGNOSTIC_POP + + /* + * Ordering here is somewhat tricky; we need sc_boot() first, since that + * determines what the size classes will be, and then + * malloc_conf_init(), since any slab size tweaking will need to be done + * before sz_boot and bin_boot, which assume that the values they read + * out of sc_data_global are final. + */ + sc_boot(&sc_data); + unsigned bin_shard_sizes[SC_NBINS]; + bin_shard_sizes_boot(bin_shard_sizes); + /* + * prof_boot0 only initializes opt_prof_prefix. We need to do it before + * we parse malloc_conf options, in case malloc_conf parsing overwrites + * it. + */ if (config_prof) { prof_boot0(); } - malloc_conf_init(); + malloc_conf_init(&sc_data, bin_shard_sizes); + sz_boot(&sc_data); + bin_boot(&sc_data, bin_shard_sizes); + if (opt_stats_print) { /* Print statistics at exit. */ if (atexit(stats_print_atexit) != 0) { @@ -1249,7 +1462,7 @@ malloc_init_hard_a0_locked() { if (config_prof) { prof_boot1(); } - arena_boot(); + arena_boot(&sc_data); if (tcache_boot(TSDN_NULL)) { return true; } @@ -1257,11 +1470,13 @@ malloc_init_hard_a0_locked() { malloc_mutex_rank_exclusive)) { return true; } + hook_boot(); /* * Create enough scaffolding to allow recursive allocation in * malloc_ncpus(). */ narenas_auto = 1; + manual_arena_base = narenas_auto + 1; memset(arenas, 0, sizeof(arena_t *) * narenas_auto); /* * Initialize one arena here. The rest are lazily created in @@ -1409,6 +1624,10 @@ malloc_init_narenas(void) { narenas_auto); } narenas_total_set(narenas_auto); + if (arena_init_huge()) { + narenas_total_inc(); + } + manual_arena_base = narenas_total_get(); return false; } @@ -1493,6 +1712,8 @@ malloc_init_hard(void) { post_reentrancy(tsd); malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock); + witness_assert_lockless(witness_tsd_tsdn( + tsd_witness_tsdp_get_unsafe(tsd))); malloc_tsd_boot1(); /* Update TSD after tsd_boot1. */ tsd = tsd_fetch(); @@ -1500,12 +1721,11 @@ malloc_init_hard(void) { assert(have_background_thread); /* * Need to finish init & unlock first before creating background - * threads (pthread_create depends on malloc). + * threads (pthread_create depends on malloc). ctl_init (which + * sets isthreaded) needs to be called without holding any lock. */ - malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); - bool err = background_thread_create(tsd, 0); - malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); - if (err) { + background_thread_ctl_init(tsd_tsdn(tsd)); + if (background_thread_create(tsd, 0)) { return true; } } @@ -1528,8 +1748,7 @@ typedef struct static_opts_s static_opts_t; struct static_opts_s { /* Whether or not allocation size may overflow. */ bool may_overflow; - /* Whether or not allocations of size 0 should be treated as size 1. */ - bool bump_empty_alloc; + /* * Whether to assert that allocations are not of size 0 (after any * bumping). @@ -1562,12 +1781,15 @@ struct static_opts_s { * initialization) options. */ bool slow; + /* + * Return size. + */ + bool usize; }; JEMALLOC_ALWAYS_INLINE void static_opts_init(static_opts_t *static_opts) { static_opts->may_overflow = false; - static_opts->bump_empty_alloc = false; static_opts->assert_nonempty_alloc = false; static_opts->null_out_result_on_error = false; static_opts->set_errno_on_error = false; @@ -1575,6 +1797,7 @@ static_opts_init(static_opts_t *static_opts) { static_opts->oom_string = ""; static_opts->invalid_alignment_string = ""; static_opts->slow = false; + static_opts->usize = false; } /* @@ -1589,6 +1812,7 @@ static_opts_init(static_opts_t *static_opts) { typedef struct dynamic_opts_s dynamic_opts_t; struct dynamic_opts_s { void **result; + size_t usize; size_t num_items; size_t item_size; size_t alignment; @@ -1600,6 +1824,7 @@ struct dynamic_opts_s { JEMALLOC_ALWAYS_INLINE void dynamic_opts_init(dynamic_opts_t *dynamic_opts) { dynamic_opts->result = NULL; + dynamic_opts->usize = 0; dynamic_opts->num_items = 0; dynamic_opts->item_size = 0; dynamic_opts->alignment = 0; @@ -1663,12 +1888,13 @@ imalloc_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd, szind_t ind_large; size_t bumped_usize = usize; - if (usize <= SMALL_MAXCLASS) { - assert(((dopts->alignment == 0) ? sz_s2u(LARGE_MINCLASS) : - sz_sa2u(LARGE_MINCLASS, dopts->alignment)) - == LARGE_MINCLASS); - ind_large = sz_size2index(LARGE_MINCLASS); - bumped_usize = sz_s2u(LARGE_MINCLASS); + if (usize <= SC_SMALL_MAXCLASS) { + assert(((dopts->alignment == 0) ? + sz_s2u(SC_LARGE_MINCLASS) : + sz_sa2u(SC_LARGE_MINCLASS, dopts->alignment)) + == SC_LARGE_MINCLASS); + ind_large = sz_size2index(SC_LARGE_MINCLASS); + bumped_usize = sz_s2u(SC_LARGE_MINCLASS); ret = imalloc_no_sample(sopts, dopts, tsd, bumped_usize, bumped_usize, ind_large); if (unlikely(ret == NULL)) { @@ -1701,7 +1927,7 @@ compute_size_with_overflow(bool may_overflow, dynamic_opts_t *dopts, } /* A size_t with its high-half bits all set to 1. */ - const static size_t high_bits = SIZE_T_MAX << (sizeof(size_t) * 8 / 2); + static const size_t high_bits = SIZE_T_MAX << (sizeof(size_t) * 8 / 2); *size = dopts->item_size * dopts->num_items; @@ -1752,12 +1978,6 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { } /* Validate the user input. */ - if (sopts->bump_empty_alloc) { - if (unlikely(size == 0)) { - size = 1; - } - } - if (sopts->assert_nonempty_alloc) { assert (size != 0); } @@ -1771,16 +1991,20 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { if (dopts->alignment == 0) { ind = sz_size2index(size); - if (unlikely(ind >= NSIZES)) { + if (unlikely(ind >= SC_NSIZES)) { goto label_oom; } - if (config_stats || (config_prof && opt_prof)) { + if (config_stats || (config_prof && opt_prof) || sopts->usize) { usize = sz_index2size(ind); - assert(usize > 0 && usize <= LARGE_MAXCLASS); + dopts->usize = usize; + assert(usize > 0 && usize + <= SC_LARGE_MAXCLASS); } } else { usize = sz_sa2u(size, dopts->alignment); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + dopts->usize = usize; + if (unlikely(usize == 0 + || usize > SC_LARGE_MAXCLASS)) { goto label_oom; } } @@ -1816,7 +2040,8 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { alloc_ctx_t alloc_ctx; if (likely((uintptr_t)tctx == (uintptr_t)1U)) { - alloc_ctx.slab = (usize <= SMALL_MAXCLASS); + alloc_ctx.slab = (usize + <= SC_SMALL_MAXCLASS); allocation = imalloc_no_sample( sopts, dopts, tsd, usize, usize, ind); } else if ((uintptr_t)tctx > (uintptr_t)1U) { @@ -1921,9 +2146,8 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { return EINVAL; } -/* Returns the errno-style error code of the allocation. */ -JEMALLOC_ALWAYS_INLINE int -imalloc(static_opts_t *sopts, dynamic_opts_t *dopts) { +JEMALLOC_ALWAYS_INLINE bool +imalloc_init_check(static_opts_t *sopts, dynamic_opts_t *dopts) { if (unlikely(!malloc_initialized()) && unlikely(malloc_init())) { if (config_xmalloc && unlikely(opt_xmalloc)) { malloc_write(sopts->oom_string); @@ -1933,6 +2157,16 @@ imalloc(static_opts_t *sopts, dynamic_opts_t *dopts) { set_errno(ENOMEM); *dopts->result = NULL; + return false; + } + + return true; +} + +/* Returns the errno-style error code of the allocation. */ +JEMALLOC_ALWAYS_INLINE int +imalloc(static_opts_t *sopts, dynamic_opts_t *dopts) { + if (tsd_get_allocates() && !imalloc_init_check(sopts, dopts)) { return ENOMEM; } @@ -1945,27 +2179,27 @@ imalloc(static_opts_t *sopts, dynamic_opts_t *dopts) { sopts->slow = false; return imalloc_body(sopts, dopts, tsd); } else { + if (!tsd_get_allocates() && !imalloc_init_check(sopts, dopts)) { + return ENOMEM; + } + sopts->slow = true; return imalloc_body(sopts, dopts, tsd); } } -/******************************************************************************/ -/* - * Begin malloc(3)-compatible functions. - */ -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN -void JEMALLOC_NOTHROW * -JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) -je_malloc(size_t size) { +JEMALLOC_NOINLINE +void * +malloc_default(size_t size) { void *ret; static_opts_t sopts; dynamic_opts_t dopts; + LOG("core.malloc.entry", "size: %zu", size); + static_opts_init(&sopts); dynamic_opts_init(&dopts); - sopts.bump_empty_alloc = true; sopts.null_out_result_on_error = true; sopts.set_errno_on_error = true; sopts.oom_string = ": Error in malloc(): out of memory\n"; @@ -1975,10 +2209,107 @@ je_malloc(size_t size) { dopts.item_size = size; imalloc(&sopts, &dopts); + /* + * Note that this branch gets optimized away -- it immediately follows + * the check on tsd_fast that sets sopts.slow. + */ + if (sopts.slow) { + uintptr_t args[3] = {size}; + hook_invoke_alloc(hook_alloc_malloc, ret, (uintptr_t)ret, args); + } + + LOG("core.malloc.exit", "result: %p", ret); return ret; } +/******************************************************************************/ +/* + * Begin malloc(3)-compatible functions. + */ + +/* + * malloc() fastpath. + * + * Fastpath assumes size <= SC_LOOKUP_MAXCLASS, and that we hit + * tcache. If either of these is false, we tail-call to the slowpath, + * malloc_default(). Tail-calling is used to avoid any caller-saved + * registers. + * + * fastpath supports ticker and profiling, both of which will also + * tail-call to the slowpath if they fire. + */ +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) +je_malloc(size_t size) { + LOG("core.malloc.entry", "size: %zu", size); + + if (tsd_get_allocates() && unlikely(!malloc_initialized())) { + return malloc_default(size); + } + + tsd_t *tsd = tsd_get(false); + if (unlikely(!tsd || !tsd_fast(tsd) || (size > SC_LOOKUP_MAXCLASS))) { + return malloc_default(size); + } + + tcache_t *tcache = tsd_tcachep_get(tsd); + + if (unlikely(ticker_trytick(&tcache->gc_ticker))) { + return malloc_default(size); + } + + szind_t ind = sz_size2index_lookup(size); + size_t usize; + if (config_stats || config_prof) { + usize = sz_index2size(ind); + } + /* Fast path relies on size being a bin. I.e. SC_LOOKUP_MAXCLASS < SC_SMALL_MAXCLASS */ + assert(ind < SC_NBINS); + assert(size <= SC_SMALL_MAXCLASS); + + if (config_prof) { + int64_t bytes_until_sample = tsd_bytes_until_sample_get(tsd); + bytes_until_sample -= usize; + tsd_bytes_until_sample_set(tsd, bytes_until_sample); + + if (unlikely(bytes_until_sample < 0)) { + /* + * Avoid a prof_active check on the fastpath. + * If prof_active is false, set bytes_until_sample to + * a large value. If prof_active is set to true, + * bytes_until_sample will be reset. + */ + if (!prof_active) { + tsd_bytes_until_sample_set(tsd, SSIZE_MAX); + } + return malloc_default(size); + } + } + + cache_bin_t *bin = tcache_small_bin_get(tcache, ind); + bool tcache_success; + void* ret = cache_bin_alloc_easy(bin, &tcache_success); + + if (tcache_success) { + if (config_stats) { + *tsd_thread_allocatedp_get(tsd) += usize; + bin->tstats.nrequests++; + } + if (config_prof) { + tcache->prof_accumbytes += usize; + } + + LOG("core.malloc.exit", "result: %p", ret); + + /* Fastpath success */ + return ret; + } + + return malloc_default(size); +} + JEMALLOC_EXPORT int JEMALLOC_NOTHROW JEMALLOC_ATTR(nonnull(1)) je_posix_memalign(void **memptr, size_t alignment, size_t size) { @@ -1986,10 +2317,12 @@ je_posix_memalign(void **memptr, size_t alignment, size_t size) { static_opts_t sopts; dynamic_opts_t dopts; + LOG("core.posix_memalign.entry", "mem ptr: %p, alignment: %zu, " + "size: %zu", memptr, alignment, size); + static_opts_init(&sopts); dynamic_opts_init(&dopts); - sopts.bump_empty_alloc = true; sopts.min_alignment = sizeof(void *); sopts.oom_string = ": Error allocating aligned memory: out of memory\n"; @@ -2002,6 +2335,16 @@ je_posix_memalign(void **memptr, size_t alignment, size_t size) { dopts.alignment = alignment; ret = imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {(uintptr_t)memptr, (uintptr_t)alignment, + (uintptr_t)size}; + hook_invoke_alloc(hook_alloc_posix_memalign, *memptr, + (uintptr_t)ret, args); + } + + LOG("core.posix_memalign.exit", "result: %d, alloc ptr: %p", ret, + *memptr); + return ret; } @@ -2014,10 +2357,12 @@ je_aligned_alloc(size_t alignment, size_t size) { static_opts_t sopts; dynamic_opts_t dopts; + LOG("core.aligned_alloc.entry", "alignment: %zu, size: %zu\n", + alignment, size); + static_opts_init(&sopts); dynamic_opts_init(&dopts); - sopts.bump_empty_alloc = true; sopts.null_out_result_on_error = true; sopts.set_errno_on_error = true; sopts.min_alignment = 1; @@ -2032,6 +2377,14 @@ je_aligned_alloc(size_t alignment, size_t size) { dopts.alignment = alignment; imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {(uintptr_t)alignment, (uintptr_t)size}; + hook_invoke_alloc(hook_alloc_aligned_alloc, ret, + (uintptr_t)ret, args); + } + + LOG("core.aligned_alloc.exit", "result: %p", ret); + return ret; } @@ -2043,11 +2396,12 @@ je_calloc(size_t num, size_t size) { static_opts_t sopts; dynamic_opts_t dopts; + LOG("core.calloc.entry", "num: %zu, size: %zu\n", num, size); + static_opts_init(&sopts); dynamic_opts_init(&dopts); sopts.may_overflow = true; - sopts.bump_empty_alloc = true; sopts.null_out_result_on_error = true; sopts.set_errno_on_error = true; sopts.oom_string = ": Error in calloc(): out of memory\n"; @@ -2058,26 +2412,34 @@ je_calloc(size_t num, size_t size) { dopts.zero = true; imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {(uintptr_t)num, (uintptr_t)size}; + hook_invoke_alloc(hook_alloc_calloc, ret, (uintptr_t)ret, args); + } + + LOG("core.calloc.exit", "result: %p", ret); return ret; } static void * irealloc_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize, - prof_tctx_t *tctx) { + prof_tctx_t *tctx, hook_ralloc_args_t *hook_args) { void *p; if (tctx == NULL) { return NULL; } - if (usize <= SMALL_MAXCLASS) { - p = iralloc(tsd, old_ptr, old_usize, LARGE_MINCLASS, 0, false); + if (usize <= SC_SMALL_MAXCLASS) { + p = iralloc(tsd, old_ptr, old_usize, + SC_LARGE_MINCLASS, 0, false, hook_args); if (p == NULL) { return NULL; } arena_prof_promote(tsd_tsdn(tsd), p, usize); } else { - p = iralloc(tsd, old_ptr, old_usize, usize, 0, false); + p = iralloc(tsd, old_ptr, old_usize, usize, 0, false, + hook_args); } return p; @@ -2085,7 +2447,7 @@ irealloc_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize, JEMALLOC_ALWAYS_INLINE void * irealloc_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize, - alloc_ctx_t *alloc_ctx) { + alloc_ctx_t *alloc_ctx, hook_ralloc_args_t *hook_args) { void *p; bool prof_active; prof_tctx_t *old_tctx, *tctx; @@ -2094,9 +2456,11 @@ irealloc_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize, old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr, alloc_ctx); tctx = prof_alloc_prep(tsd, usize, prof_active, true); if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { - p = irealloc_prof_sample(tsd, old_ptr, old_usize, usize, tctx); + p = irealloc_prof_sample(tsd, old_ptr, old_usize, usize, tctx, + hook_args); } else { - p = iralloc(tsd, old_ptr, old_usize, usize, 0, false); + p = iralloc(tsd, old_ptr, old_usize, usize, 0, false, + hook_args); } if (unlikely(p == NULL)) { prof_alloc_rollback(tsd, tctx, true); @@ -2125,7 +2489,7 @@ ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path) { rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); - assert(alloc_ctx.szind != NSIZES); + assert(alloc_ctx.szind != SC_NSIZES); size_t usize; if (config_prof && opt_prof) { @@ -2161,17 +2525,37 @@ isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) { assert(malloc_initialized() || IS_INITIALIZER); alloc_ctx_t alloc_ctx, *ctx; - if (config_prof && opt_prof) { + if (!config_cache_oblivious && ((uintptr_t)ptr & PAGE_MASK) != 0) { + /* + * When cache_oblivious is disabled and ptr is not page aligned, + * the allocation was not sampled -- usize can be used to + * determine szind directly. + */ + alloc_ctx.szind = sz_size2index(usize); + alloc_ctx.slab = true; + ctx = &alloc_ctx; + if (config_debug) { + alloc_ctx_t dbg_ctx; + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, + rtree_ctx, (uintptr_t)ptr, true, &dbg_ctx.szind, + &dbg_ctx.slab); + assert(dbg_ctx.szind == alloc_ctx.szind); + assert(dbg_ctx.slab == alloc_ctx.slab); + } + } else if (config_prof && opt_prof) { rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); assert(alloc_ctx.szind == sz_size2index(usize)); ctx = &alloc_ctx; - prof_free(tsd, ptr, usize, ctx); } else { ctx = NULL; } + if (config_prof && opt_prof) { + prof_free(tsd, ptr, usize, ctx); + } if (config_stats) { *tsd_thread_deallocatedp_get(tsd) += usize; } @@ -2186,11 +2570,14 @@ isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) { JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_NOTHROW * JEMALLOC_ALLOC_SIZE(2) -je_realloc(void *ptr, size_t size) { +je_realloc(void *ptr, size_t arg_size) { void *ret; tsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL); size_t usize JEMALLOC_CC_SILENCE_INIT(0); size_t old_usize = 0; + size_t size = arg_size; + + LOG("core.realloc.entry", "ptr: %p, size: %zu\n", ptr, size); if (unlikely(size == 0)) { if (ptr != NULL) { @@ -2203,7 +2590,13 @@ je_realloc(void *ptr, size_t size) { } else { tcache = NULL; } + + uintptr_t args[3] = {(uintptr_t)ptr, size}; + hook_invoke_dalloc(hook_dalloc_realloc, ptr, args); + ifree(tsd, ptr, tcache, true); + + LOG("core.realloc.exit", "result: %p", NULL); return NULL; } size = 1; @@ -2215,28 +2608,59 @@ je_realloc(void *ptr, size_t size) { check_entry_exit_locking(tsd_tsdn(tsd)); + + hook_ralloc_args_t hook_args = {true, {(uintptr_t)ptr, + (uintptr_t)arg_size, 0, 0}}; + alloc_ctx_t alloc_ctx; rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); - assert(alloc_ctx.szind != NSIZES); + assert(alloc_ctx.szind != SC_NSIZES); old_usize = sz_index2size(alloc_ctx.szind); assert(old_usize == isalloc(tsd_tsdn(tsd), ptr)); if (config_prof && opt_prof) { usize = sz_s2u(size); - ret = unlikely(usize == 0 || usize > LARGE_MAXCLASS) ? - NULL : irealloc_prof(tsd, ptr, old_usize, usize, - &alloc_ctx); + if (unlikely(usize == 0 + || usize > SC_LARGE_MAXCLASS)) { + ret = NULL; + } else { + ret = irealloc_prof(tsd, ptr, old_usize, usize, + &alloc_ctx, &hook_args); + } } else { if (config_stats) { usize = sz_s2u(size); } - ret = iralloc(tsd, ptr, old_usize, size, 0, false); + ret = iralloc(tsd, ptr, old_usize, size, 0, false, + &hook_args); } tsdn = tsd_tsdn(tsd); } else { /* realloc(NULL, size) is equivalent to malloc(size). */ - return je_malloc(size); + static_opts_t sopts; + dynamic_opts_t dopts; + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.null_out_result_on_error = true; + sopts.set_errno_on_error = true; + sopts.oom_string = + ": Error in realloc(): out of memory\n"; + + dopts.result = &ret; + dopts.num_items = 1; + dopts.item_size = size; + + imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {(uintptr_t)ptr, arg_size}; + hook_invoke_alloc(hook_alloc_realloc, ret, + (uintptr_t)ret, args); + } + + return ret; } if (unlikely(ret == NULL)) { @@ -2257,11 +2681,14 @@ je_realloc(void *ptr, size_t size) { } UTRACE(ptr, size, ret); check_entry_exit_locking(tsdn); + + LOG("core.realloc.exit", "result: %p", ret); return ret; } -JEMALLOC_EXPORT void JEMALLOC_NOTHROW -je_free(void *ptr) { +JEMALLOC_NOINLINE +void +free_default(void *ptr) { UTRACE(ptr, 0, 0); if (likely(ptr != NULL)) { /* @@ -2287,12 +2714,82 @@ je_free(void *ptr) { } else { tcache = NULL; } + uintptr_t args_raw[3] = {(uintptr_t)ptr}; + hook_invoke_dalloc(hook_dalloc_free, ptr, args_raw); ifree(tsd, ptr, tcache, true); } check_entry_exit_locking(tsd_tsdn(tsd)); } } +JEMALLOC_ALWAYS_INLINE +bool free_fastpath(void *ptr, size_t size, bool size_hint) { + tsd_t *tsd = tsd_get(false); + if (unlikely(!tsd || !tsd_fast(tsd))) { + return false; + } + + tcache_t *tcache = tsd_tcachep_get(tsd); + + alloc_ctx_t alloc_ctx; + /* + * If !config_cache_oblivious, we can check PAGE alignment to + * detect sampled objects. Otherwise addresses are + * randomized, and we have to look it up in the rtree anyway. + * See also isfree(). + */ + if (!size_hint || config_cache_oblivious) { + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + bool res = rtree_szind_slab_read_fast(tsd_tsdn(tsd), &extents_rtree, + rtree_ctx, (uintptr_t)ptr, + &alloc_ctx.szind, &alloc_ctx.slab); + assert(alloc_ctx.szind != SC_NSIZES); + + /* Note: profiled objects will have alloc_ctx.slab set */ + if (!res || !alloc_ctx.slab) { + return false; + } + } else { + /* + * Check for both sizes that are too large, and for sampled objects. + * Sampled objects are always page-aligned. The sampled object check + * will also check for null ptr. + */ + if (size > SC_LOOKUP_MAXCLASS || (((uintptr_t)ptr & PAGE_MASK) == 0)) { + return false; + } + alloc_ctx.szind = sz_size2index_lookup(size); + } + + if (unlikely(ticker_trytick(&tcache->gc_ticker))) { + return false; + } + + cache_bin_t *bin = tcache_small_bin_get(tcache, alloc_ctx.szind); + cache_bin_info_t *bin_info = &tcache_bin_info[alloc_ctx.szind]; + if (!cache_bin_dalloc_easy(bin, bin_info, ptr)) { + return false; + } + + if (config_stats) { + size_t usize = sz_index2size(alloc_ctx.szind); + *tsd_thread_deallocatedp_get(tsd) += usize; + } + + return true; +} + +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_free(void *ptr) { + LOG("core.free.entry", "ptr: %p", ptr); + + if (!free_fastpath(ptr, 0, false)) { + free_default(ptr); + } + + LOG("core.free.exit", ""); +} + /* * End malloc(3)-compatible functions. */ @@ -2310,10 +2807,12 @@ je_memalign(size_t alignment, size_t size) { static_opts_t sopts; dynamic_opts_t dopts; + LOG("core.memalign.entry", "alignment: %zu, size: %zu\n", alignment, + size); + static_opts_init(&sopts); dynamic_opts_init(&dopts); - sopts.bump_empty_alloc = true; sopts.min_alignment = 1; sopts.oom_string = ": Error allocating aligned memory: out of memory\n"; @@ -2327,6 +2826,13 @@ je_memalign(size_t alignment, size_t size) { dopts.alignment = alignment; imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {alignment, size}; + hook_invoke_alloc(hook_alloc_memalign, ret, (uintptr_t)ret, + args); + } + + LOG("core.memalign.exit", "result: %p", ret); return ret; } #endif @@ -2341,10 +2847,11 @@ je_valloc(size_t size) { static_opts_t sopts; dynamic_opts_t dopts; + LOG("core.valloc.entry", "size: %zu\n", size); + static_opts_init(&sopts); dynamic_opts_init(&dopts); - sopts.bump_empty_alloc = true; sopts.null_out_result_on_error = true; sopts.min_alignment = PAGE; sopts.oom_string = @@ -2358,7 +2865,12 @@ je_valloc(size_t size) { dopts.alignment = PAGE; imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {size}; + hook_invoke_alloc(hook_alloc_valloc, ret, (uintptr_t)ret, args); + } + LOG("core.valloc.exit", "result: %p\n", ret); return ret; } #endif @@ -2424,6 +2936,82 @@ int __posix_memalign(void** r, size_t a, size_t s) PREALIAS(je_posix_memalign); * Begin non-standard functions. */ +#ifdef JEMALLOC_EXPERIMENTAL_SMALLOCX_API + +#define JEMALLOC_SMALLOCX_CONCAT_HELPER(x, y) x ## y +#define JEMALLOC_SMALLOCX_CONCAT_HELPER2(x, y) \ + JEMALLOC_SMALLOCX_CONCAT_HELPER(x, y) + +typedef struct { + void *ptr; + size_t size; +} smallocx_return_t; + +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +smallocx_return_t JEMALLOC_NOTHROW +/* + * The attribute JEMALLOC_ATTR(malloc) cannot be used due to: + * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86488 + */ +JEMALLOC_SMALLOCX_CONCAT_HELPER2(je_smallocx_, JEMALLOC_VERSION_GID_IDENT) + (size_t size, int flags) { + /* + * Note: the attribute JEMALLOC_ALLOC_SIZE(1) cannot be + * used here because it makes writing beyond the `size` + * of the `ptr` undefined behavior, but the objective + * of this function is to allow writing beyond `size` + * up to `smallocx_return_t::size`. + */ + smallocx_return_t ret; + static_opts_t sopts; + dynamic_opts_t dopts; + + LOG("core.smallocx.entry", "size: %zu, flags: %d", size, flags); + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.assert_nonempty_alloc = true; + sopts.null_out_result_on_error = true; + sopts.oom_string = ": Error in mallocx(): out of memory\n"; + sopts.usize = true; + + dopts.result = &ret.ptr; + dopts.num_items = 1; + dopts.item_size = size; + if (unlikely(flags != 0)) { + if ((flags & MALLOCX_LG_ALIGN_MASK) != 0) { + dopts.alignment = MALLOCX_ALIGN_GET_SPECIFIED(flags); + } + + dopts.zero = MALLOCX_ZERO_GET(flags); + + if ((flags & MALLOCX_TCACHE_MASK) != 0) { + if ((flags & MALLOCX_TCACHE_MASK) + == MALLOCX_TCACHE_NONE) { + dopts.tcache_ind = TCACHE_IND_NONE; + } else { + dopts.tcache_ind = MALLOCX_TCACHE_GET(flags); + } + } else { + dopts.tcache_ind = TCACHE_IND_AUTOMATIC; + } + + if ((flags & MALLOCX_ARENA_MASK) != 0) + dopts.arena_ind = MALLOCX_ARENA_GET(flags); + } + + imalloc(&sopts, &dopts); + assert(dopts.usize == je_nallocx(size, flags)); + ret.size = dopts.usize; + + LOG("core.smallocx.exit", "result: %p, size: %zu", ret.ptr, ret.size); + return ret; +} +#undef JEMALLOC_SMALLOCX_CONCAT_HELPER +#undef JEMALLOC_SMALLOCX_CONCAT_HELPER2 +#endif + JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_NOTHROW * JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) @@ -2432,6 +3020,8 @@ je_mallocx(size_t size, int flags) { static_opts_t sopts; dynamic_opts_t dopts; + LOG("core.mallocx.entry", "size: %zu, flags: %d", size, flags); + static_opts_init(&sopts); dynamic_opts_init(&dopts); @@ -2465,28 +3055,36 @@ je_mallocx(size_t size, int flags) { } imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {size, flags}; + hook_invoke_alloc(hook_alloc_mallocx, ret, (uintptr_t)ret, + args); + } + + LOG("core.mallocx.exit", "result: %p", ret); return ret; } static void * irallocx_prof_sample(tsdn_t *tsdn, void *old_ptr, size_t old_usize, size_t usize, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena, - prof_tctx_t *tctx) { + prof_tctx_t *tctx, hook_ralloc_args_t *hook_args) { void *p; if (tctx == NULL) { return NULL; } - if (usize <= SMALL_MAXCLASS) { - p = iralloct(tsdn, old_ptr, old_usize, LARGE_MINCLASS, - alignment, zero, tcache, arena); + if (usize <= SC_SMALL_MAXCLASS) { + p = iralloct(tsdn, old_ptr, old_usize, + SC_LARGE_MINCLASS, alignment, zero, tcache, + arena, hook_args); if (p == NULL) { return NULL; } arena_prof_promote(tsdn, p, usize); } else { p = iralloct(tsdn, old_ptr, old_usize, usize, alignment, zero, - tcache, arena); + tcache, arena, hook_args); } return p; @@ -2495,7 +3093,7 @@ irallocx_prof_sample(tsdn_t *tsdn, void *old_ptr, size_t old_usize, JEMALLOC_ALWAYS_INLINE void * irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size, size_t alignment, size_t *usize, bool zero, tcache_t *tcache, - arena_t *arena, alloc_ctx_t *alloc_ctx) { + arena_t *arena, alloc_ctx_t *alloc_ctx, hook_ralloc_args_t *hook_args) { void *p; bool prof_active; prof_tctx_t *old_tctx, *tctx; @@ -2505,10 +3103,10 @@ irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size, tctx = prof_alloc_prep(tsd, *usize, prof_active, false); if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { p = irallocx_prof_sample(tsd_tsdn(tsd), old_ptr, old_usize, - *usize, alignment, zero, tcache, arena, tctx); + *usize, alignment, zero, tcache, arena, tctx, hook_args); } else { p = iralloct(tsd_tsdn(tsd), old_ptr, old_usize, size, alignment, - zero, tcache, arena); + zero, tcache, arena, hook_args); } if (unlikely(p == NULL)) { prof_alloc_rollback(tsd, tctx, false); @@ -2545,6 +3143,10 @@ je_rallocx(void *ptr, size_t size, int flags) { arena_t *arena; tcache_t *tcache; + LOG("core.rallocx.entry", "ptr: %p, size: %zu, flags: %d", ptr, + size, flags); + + assert(ptr != NULL); assert(size != 0); assert(malloc_initialized() || IS_INITIALIZER); @@ -2575,23 +3177,27 @@ je_rallocx(void *ptr, size_t size, int flags) { rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); - assert(alloc_ctx.szind != NSIZES); + assert(alloc_ctx.szind != SC_NSIZES); old_usize = sz_index2size(alloc_ctx.szind); assert(old_usize == isalloc(tsd_tsdn(tsd), ptr)); + + hook_ralloc_args_t hook_args = {false, {(uintptr_t)ptr, size, flags, + 0}}; if (config_prof && opt_prof) { usize = (alignment == 0) ? sz_s2u(size) : sz_sa2u(size, alignment); - if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + if (unlikely(usize == 0 + || usize > SC_LARGE_MAXCLASS)) { goto label_oom; } p = irallocx_prof(tsd, ptr, old_usize, size, alignment, &usize, - zero, tcache, arena, &alloc_ctx); + zero, tcache, arena, &alloc_ctx, &hook_args); if (unlikely(p == NULL)) { goto label_oom; } } else { p = iralloct(tsd_tsdn(tsd), ptr, old_usize, size, alignment, - zero, tcache, arena); + zero, tcache, arena, &hook_args); if (unlikely(p == NULL)) { goto label_oom; } @@ -2607,6 +3213,8 @@ je_rallocx(void *ptr, size_t size, int flags) { } UTRACE(ptr, size, p); check_entry_exit_locking(tsd_tsdn(tsd)); + + LOG("core.rallocx.exit", "result: %p", p); return p; label_oom: if (config_xmalloc && unlikely(opt_xmalloc)) { @@ -2615,20 +3223,22 @@ je_rallocx(void *ptr, size_t size, int flags) { } UTRACE(ptr, size, 0); check_entry_exit_locking(tsd_tsdn(tsd)); + + LOG("core.rallocx.exit", "result: %p", NULL); return NULL; } JEMALLOC_ALWAYS_INLINE size_t ixallocx_helper(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size, size_t extra, size_t alignment, bool zero) { - size_t usize; + size_t newsize; - if (ixalloc(tsdn, ptr, old_usize, size, extra, alignment, zero)) { + if (ixalloc(tsdn, ptr, old_usize, size, extra, alignment, zero, + &newsize)) { return old_usize; } - usize = isalloc(tsdn, ptr); - return usize; + return newsize; } static size_t @@ -2662,17 +3272,19 @@ ixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size, */ if (alignment == 0) { usize_max = sz_s2u(size+extra); - assert(usize_max > 0 && usize_max <= LARGE_MAXCLASS); + assert(usize_max > 0 + && usize_max <= SC_LARGE_MAXCLASS); } else { usize_max = sz_sa2u(size+extra, alignment); - if (unlikely(usize_max == 0 || usize_max > LARGE_MAXCLASS)) { + if (unlikely(usize_max == 0 + || usize_max > SC_LARGE_MAXCLASS)) { /* * usize_max is out of range, and chances are that * allocation will fail, but use the maximum possible * value and carry on with prof_alloc_prep(), just in * case allocation succeeds. */ - usize_max = LARGE_MAXCLASS; + usize_max = SC_LARGE_MAXCLASS; } } tctx = prof_alloc_prep(tsd, usize_max, prof_active, false); @@ -2701,6 +3313,9 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags) { size_t alignment = MALLOCX_ALIGN_GET(flags); bool zero = flags & MALLOCX_ZERO; + LOG("core.xallocx.entry", "ptr: %p, size: %zu, extra: %zu, " + "flags: %d", ptr, size, extra, flags); + assert(ptr != NULL); assert(size != 0); assert(SIZE_T_MAX - size >= extra); @@ -2712,24 +3327,24 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags) { rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); - assert(alloc_ctx.szind != NSIZES); + assert(alloc_ctx.szind != SC_NSIZES); old_usize = sz_index2size(alloc_ctx.szind); assert(old_usize == isalloc(tsd_tsdn(tsd), ptr)); /* * The API explicitly absolves itself of protecting against (size + * extra) numerical overflow, but we may need to clamp extra to avoid - * exceeding LARGE_MAXCLASS. + * exceeding SC_LARGE_MAXCLASS. * * Ordinarily, size limit checking is handled deeper down, but here we * have to check as part of (size + extra) clamping, since we need the * clamped value in the above helper functions. */ - if (unlikely(size > LARGE_MAXCLASS)) { + if (unlikely(size > SC_LARGE_MAXCLASS)) { usize = old_usize; goto label_not_resized; } - if (unlikely(LARGE_MAXCLASS - size < extra)) { - extra = LARGE_MAXCLASS - size; + if (unlikely(SC_LARGE_MAXCLASS - size < extra)) { + extra = SC_LARGE_MAXCLASS - size; } if (config_prof && opt_prof) { @@ -2748,8 +3363,16 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags) { *tsd_thread_deallocatedp_get(tsd) += old_usize; } label_not_resized: + if (unlikely(!tsd_fast(tsd))) { + uintptr_t args[4] = {(uintptr_t)ptr, size, extra, flags}; + hook_invoke_expand(hook_expand_xallocx, ptr, old_usize, + usize, (uintptr_t)usize, args); + } + UTRACE(ptr, size, ptr); check_entry_exit_locking(tsd_tsdn(tsd)); + + LOG("core.xallocx.exit", "result: %zu", usize); return usize; } @@ -2759,6 +3382,8 @@ je_sallocx(const void *ptr, int flags) { size_t usize; tsdn_t *tsdn; + LOG("core.sallocx.entry", "ptr: %p, flags: %d", ptr, flags); + assert(malloc_initialized() || IS_INITIALIZER); assert(ptr != NULL); @@ -2773,11 +3398,15 @@ je_sallocx(const void *ptr, int flags) { } check_entry_exit_locking(tsdn); + + LOG("core.sallocx.exit", "result: %zu", usize); return usize; } JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_dallocx(void *ptr, int flags) { + LOG("core.dallocx.entry", "ptr: %p, flags: %d", ptr, flags); + assert(ptr != NULL); assert(malloc_initialized() || IS_INITIALIZER); @@ -2812,9 +3441,13 @@ je_dallocx(void *ptr, int flags) { tsd_assert_fast(tsd); ifree(tsd, ptr, tcache, false); } else { + uintptr_t args_raw[3] = {(uintptr_t)ptr, flags}; + hook_invoke_dalloc(hook_dalloc_dallocx, ptr, args_raw); ifree(tsd, ptr, tcache, true); } check_entry_exit_locking(tsd_tsdn(tsd)); + + LOG("core.dallocx.exit", ""); } JEMALLOC_ALWAYS_INLINE size_t @@ -2831,8 +3464,8 @@ inallocx(tsdn_t *tsdn, size_t size, int flags) { return usize; } -JEMALLOC_EXPORT void JEMALLOC_NOTHROW -je_sdallocx(void *ptr, size_t size, int flags) { +JEMALLOC_NOINLINE void +sdallocx_default(void *ptr, size_t size, int flags) { assert(ptr != NULL); assert(malloc_initialized() || IS_INITIALIZER); @@ -2869,9 +3502,24 @@ je_sdallocx(void *ptr, size_t size, int flags) { tsd_assert_fast(tsd); isfree(tsd, ptr, usize, tcache, false); } else { + uintptr_t args_raw[3] = {(uintptr_t)ptr, size, flags}; + hook_invoke_dalloc(hook_dalloc_sdallocx, ptr, args_raw); isfree(tsd, ptr, usize, tcache, true); } check_entry_exit_locking(tsd_tsdn(tsd)); + +} + +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_sdallocx(void *ptr, size_t size, int flags) { + LOG("core.sdallocx.entry", "ptr: %p, size: %zu, flags: %d", ptr, + size, flags); + + if (flags !=0 || !free_fastpath(ptr, size, true)) { + sdallocx_default(ptr, size, flags); + } + + LOG("core.sdallocx.exit", ""); } JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @@ -2883,6 +3531,7 @@ je_nallocx(size_t size, int flags) { assert(size != 0); if (unlikely(malloc_init())) { + LOG("core.nallocx.exit", "result: %zu", ZU(0)); return 0; } @@ -2890,11 +3539,13 @@ je_nallocx(size_t size, int flags) { check_entry_exit_locking(tsdn); usize = inallocx(tsdn, size, flags); - if (unlikely(usize > LARGE_MAXCLASS)) { + if (unlikely(usize > SC_LARGE_MAXCLASS)) { + LOG("core.nallocx.exit", "result: %zu", ZU(0)); return 0; } check_entry_exit_locking(tsdn); + LOG("core.nallocx.exit", "result: %zu", usize); return usize; } @@ -2904,7 +3555,10 @@ je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, int ret; tsd_t *tsd; + LOG("core.mallctl.entry", "name: %s", name); + if (unlikely(malloc_init())) { + LOG("core.mallctl.exit", "result: %d", EAGAIN); return EAGAIN; } @@ -2912,6 +3566,8 @@ je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, check_entry_exit_locking(tsd_tsdn(tsd)); ret = ctl_byname(tsd, name, oldp, oldlenp, newp, newlen); check_entry_exit_locking(tsd_tsdn(tsd)); + + LOG("core.mallctl.exit", "result: %d", ret); return ret; } @@ -2919,7 +3575,10 @@ JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) { int ret; + LOG("core.mallctlnametomib.entry", "name: %s", name); + if (unlikely(malloc_init())) { + LOG("core.mallctlnametomib.exit", "result: %d", EAGAIN); return EAGAIN; } @@ -2927,6 +3586,8 @@ je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) { check_entry_exit_locking(tsd_tsdn(tsd)); ret = ctl_nametomib(tsd, name, mibp, miblenp); check_entry_exit_locking(tsd_tsdn(tsd)); + + LOG("core.mallctlnametomib.exit", "result: %d", ret); return ret; } @@ -2936,7 +3597,10 @@ je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, int ret; tsd_t *tsd; + LOG("core.mallctlbymib.entry", ""); + if (unlikely(malloc_init())) { + LOG("core.mallctlbymib.exit", "result: %d", EAGAIN); return EAGAIN; } @@ -2944,6 +3608,7 @@ je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, check_entry_exit_locking(tsd_tsdn(tsd)); ret = ctl_bymib(tsd, mib, miblen, oldp, oldlenp, newp, newlen); check_entry_exit_locking(tsd_tsdn(tsd)); + LOG("core.mallctlbymib.exit", "result: %d", ret); return ret; } @@ -2952,10 +3617,13 @@ je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque, const char *opts) { tsdn_t *tsdn; + LOG("core.malloc_stats_print.entry", ""); + tsdn = tsdn_fetch(); check_entry_exit_locking(tsdn); stats_print(write_cb, cbopaque, opts); check_entry_exit_locking(tsdn); + LOG("core.malloc_stats_print.exit", ""); } JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @@ -2963,6 +3631,8 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) { size_t ret; tsdn_t *tsdn; + LOG("core.malloc_usable_size.entry", "ptr: %p", ptr); + assert(malloc_initialized() || IS_INITIALIZER); tsdn = tsdn_fetch(); @@ -2980,6 +3650,7 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) { } check_entry_exit_locking(tsdn); + LOG("core.malloc_usable_size.exit", "result: %zu", ret); return ret; } @@ -3084,6 +3755,7 @@ _malloc_prefork(void) } } prof_prefork1(tsd_tsdn(tsd)); + tsd_prefork(tsd); } #ifndef JEMALLOC_MUTEX_INIT_CB @@ -3106,6 +3778,8 @@ _malloc_postfork(void) tsd = tsd_fetch(); + tsd_postfork_parent(tsd); + witness_postfork_parent(tsd_witness_tsdp_get(tsd)); /* Release all mutexes, now that fork() has completed. */ for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { @@ -3133,6 +3807,8 @@ jemalloc_postfork_child(void) { tsd = tsd_fetch(); + tsd_postfork_child(tsd); + witness_postfork_child(tsd_witness_tsdp_get(tsd)); /* Release all mutexes, now that fork() has completed. */ for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { diff --git a/kbe/src/lib/dependencies/jemalloc/src/jemalloc_cpp.cpp b/kbe/src/lib/dependencies/jemalloc/src/jemalloc_cpp.cpp index 844ab398a7..f0ceddae33 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/jemalloc_cpp.cpp +++ b/kbe/src/lib/dependencies/jemalloc/src/jemalloc_cpp.cpp @@ -39,12 +39,10 @@ void operator delete(void *ptr, std::size_t size) noexcept; void operator delete[](void *ptr, std::size_t size) noexcept; #endif -template -void * -newImpl(std::size_t size) noexcept(IsNoExcept) { - void *ptr = je_malloc(size); - if (likely(ptr != nullptr)) - return ptr; +JEMALLOC_NOINLINE +static void * +handleOOM(std::size_t size, bool nothrow) { + void *ptr = nullptr; while (ptr == nullptr) { std::new_handler handler; @@ -68,11 +66,22 @@ newImpl(std::size_t size) noexcept(IsNoExcept) { ptr = je_malloc(size); } - if (ptr == nullptr && !IsNoExcept) + if (ptr == nullptr && !nothrow) std::__throw_bad_alloc(); return ptr; } +template +JEMALLOC_ALWAYS_INLINE +void * +newImpl(std::size_t size) noexcept(IsNoExcept) { + void *ptr = je_malloc(size); + if (likely(ptr != nullptr)) + return ptr; + + return handleOOM(size, IsNoExcept); +} + void * operator new(std::size_t size) { return newImpl(size); diff --git a/kbe/src/lib/dependencies/jemalloc/src/large.c b/kbe/src/lib/dependencies/jemalloc/src/large.c index 27a2c67987..8e7a781d33 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/large.c +++ b/kbe/src/lib/dependencies/jemalloc/src/large.c @@ -28,7 +28,7 @@ large_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, assert(!tsdn_null(tsdn) || arena != NULL); ausize = sz_sa2u(usize, alignment); - if (unlikely(ausize == 0 || ausize > LARGE_MAXCLASS)) { + if (unlikely(ausize == 0 || ausize > SC_LARGE_MAXCLASS)) { return NULL; } @@ -42,7 +42,7 @@ large_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, */ is_zeroed = zero; if (likely(!tsdn_null(tsdn))) { - arena = arena_choose(tsdn_tsd(tsdn), arena); + arena = arena_choose_maybe_huge(tsdn_tsd(tsdn), arena, usize); } if (unlikely(arena == NULL) || (extent = arena_extent_alloc_large(tsdn, arena, usize, alignment, &is_zeroed)) == NULL) { @@ -109,7 +109,7 @@ large_ralloc_no_move_shrink(tsdn_t *tsdn, extent_t *extent, size_t usize) { if (diff != 0) { extent_t *trail = extent_split_wrapper(tsdn, arena, &extent_hooks, extent, usize + sz_large_pad, - sz_size2index(usize), false, diff, NSIZES, false); + sz_size2index(usize), false, diff, SC_NSIZES, false); if (trail == NULL) { return true; } @@ -154,17 +154,17 @@ large_ralloc_no_move_expand(tsdn_t *tsdn, extent_t *extent, size_t usize, bool new_mapping; if ((trail = extents_alloc(tsdn, arena, &extent_hooks, &arena->extents_dirty, extent_past_get(extent), trailsize, 0, - CACHELINE, false, NSIZES, &is_zeroed_trail, &commit)) != NULL + CACHELINE, false, SC_NSIZES, &is_zeroed_trail, &commit)) != NULL || (trail = extents_alloc(tsdn, arena, &extent_hooks, &arena->extents_muzzy, extent_past_get(extent), trailsize, 0, - CACHELINE, false, NSIZES, &is_zeroed_trail, &commit)) != NULL) { + CACHELINE, false, SC_NSIZES, &is_zeroed_trail, &commit)) != NULL) { if (config_stats) { new_mapping = false; } } else { if ((trail = extent_alloc_wrapper(tsdn, arena, &extent_hooks, extent_past_get(extent), trailsize, 0, CACHELINE, false, - NSIZES, &is_zeroed_trail, &commit)) == NULL) { + SC_NSIZES, &is_zeroed_trail, &commit)) == NULL) { return true; } if (config_stats) { @@ -221,9 +221,10 @@ large_ralloc_no_move(tsdn_t *tsdn, extent_t *extent, size_t usize_min, size_t oldusize = extent_usize_get(extent); /* The following should have been caught by callers. */ - assert(usize_min > 0 && usize_max <= LARGE_MAXCLASS); + assert(usize_min > 0 && usize_max <= SC_LARGE_MAXCLASS); /* Both allocation sizes must be large to avoid a move. */ - assert(oldusize >= LARGE_MINCLASS && usize_max >= LARGE_MINCLASS); + assert(oldusize >= SC_LARGE_MINCLASS + && usize_max >= SC_LARGE_MINCLASS); if (usize_max > oldusize) { /* Attempt to expand the allocation in-place. */ @@ -270,17 +271,23 @@ large_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize, } void * -large_ralloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent, size_t usize, - size_t alignment, bool zero, tcache_t *tcache) { - size_t oldusize = extent_usize_get(extent); +large_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t usize, + size_t alignment, bool zero, tcache_t *tcache, + hook_ralloc_args_t *hook_args) { + extent_t *extent = iealloc(tsdn, ptr); + size_t oldusize = extent_usize_get(extent); /* The following should have been caught by callers. */ - assert(usize > 0 && usize <= LARGE_MAXCLASS); + assert(usize > 0 && usize <= SC_LARGE_MAXCLASS); /* Both allocation sizes must be large to avoid a move. */ - assert(oldusize >= LARGE_MINCLASS && usize >= LARGE_MINCLASS); + assert(oldusize >= SC_LARGE_MINCLASS + && usize >= SC_LARGE_MINCLASS); /* Try to avoid moving the allocation. */ if (!large_ralloc_no_move(tsdn, extent, usize, usize, zero)) { + hook_invoke_expand(hook_args->is_realloc + ? hook_expand_realloc : hook_expand_rallocx, ptr, oldusize, + usize, (uintptr_t)ptr, hook_args->args); return extent_addr_get(extent); } @@ -295,6 +302,12 @@ large_ralloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent, size_t usize, return NULL; } + hook_invoke_alloc(hook_args->is_realloc + ? hook_alloc_realloc : hook_alloc_rallocx, ret, (uintptr_t)ret, + hook_args->args); + hook_invoke_dalloc(hook_args->is_realloc + ? hook_dalloc_realloc : hook_dalloc_rallocx, ptr, hook_args->args); + size_t copysize = (usize < oldusize) ? usize : oldusize; memcpy(ret, extent_addr_get(extent), copysize); isdalloct(tsdn, extent_addr_get(extent), oldusize, tcache, NULL, true); @@ -318,8 +331,9 @@ large_dalloc_prep_impl(tsdn_t *tsdn, arena_t *arena, extent_t *extent, large_dalloc_maybe_junk(extent_addr_get(extent), extent_usize_get(extent)); } else { - malloc_mutex_assert_owner(tsdn, &arena->large_mtx); + /* Only hold the large_mtx if necessary. */ if (!arena_is_auto(arena)) { + malloc_mutex_assert_owner(tsdn, &arena->large_mtx); extent_list_remove(&arena->large, extent); } } @@ -369,3 +383,13 @@ void large_prof_tctx_reset(tsdn_t *tsdn, extent_t *extent) { large_prof_tctx_set(tsdn, extent, (prof_tctx_t *)(uintptr_t)1U); } + +nstime_t +large_prof_alloc_time_get(const extent_t *extent) { + return extent_prof_alloc_time_get(extent); +} + +void +large_prof_alloc_time_set(extent_t *extent, nstime_t t) { + extent_prof_alloc_time_set(extent, t); +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/log.c b/kbe/src/lib/dependencies/jemalloc/src/log.c new file mode 100644 index 0000000000..778902fb9b --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/src/log.c @@ -0,0 +1,78 @@ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/log.h" + +char log_var_names[JEMALLOC_LOG_VAR_BUFSIZE]; +atomic_b_t log_init_done = ATOMIC_INIT(false); + +/* + * Returns true if we were able to pick out a segment. Fills in r_segment_end + * with a pointer to the first character after the end of the string. + */ +static const char * +log_var_extract_segment(const char* segment_begin) { + const char *end; + for (end = segment_begin; *end != '\0' && *end != '|'; end++) { + } + return end; +} + +static bool +log_var_matches_segment(const char *segment_begin, const char *segment_end, + const char *log_var_begin, const char *log_var_end) { + assert(segment_begin <= segment_end); + assert(log_var_begin < log_var_end); + + ptrdiff_t segment_len = segment_end - segment_begin; + ptrdiff_t log_var_len = log_var_end - log_var_begin; + /* The special '.' segment matches everything. */ + if (segment_len == 1 && *segment_begin == '.') { + return true; + } + if (segment_len == log_var_len) { + return strncmp(segment_begin, log_var_begin, segment_len) == 0; + } else if (segment_len < log_var_len) { + return strncmp(segment_begin, log_var_begin, segment_len) == 0 + && log_var_begin[segment_len] == '.'; + } else { + return false; + } +} + +unsigned +log_var_update_state(log_var_t *log_var) { + const char *log_var_begin = log_var->name; + const char *log_var_end = log_var->name + strlen(log_var->name); + + /* Pointer to one before the beginning of the current segment. */ + const char *segment_begin = log_var_names; + + /* + * If log_init done is false, we haven't parsed the malloc conf yet. To + * avoid log-spew, we default to not displaying anything. + */ + if (!atomic_load_b(&log_init_done, ATOMIC_ACQUIRE)) { + return LOG_INITIALIZED_NOT_ENABLED; + } + + while (true) { + const char *segment_end = log_var_extract_segment( + segment_begin); + assert(segment_end < log_var_names + JEMALLOC_LOG_VAR_BUFSIZE); + if (log_var_matches_segment(segment_begin, segment_end, + log_var_begin, log_var_end)) { + atomic_store_u(&log_var->state, LOG_ENABLED, + ATOMIC_RELAXED); + return LOG_ENABLED; + } + if (*segment_end == '\0') { + /* Hit the end of the segment string with no match. */ + atomic_store_u(&log_var->state, + LOG_INITIALIZED_NOT_ENABLED, ATOMIC_RELAXED); + return LOG_INITIALIZED_NOT_ENABLED; + } + /* Otherwise, skip the delimiter and continue. */ + segment_begin = segment_end + 1; + } +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/malloc_io.c b/kbe/src/lib/dependencies/jemalloc/src/malloc_io.c index 6b99afcd3f..7bdc13f951 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/malloc_io.c +++ b/kbe/src/lib/dependencies/jemalloc/src/malloc_io.c @@ -70,20 +70,7 @@ static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, /* malloc_message() setup. */ static void wrtmessage(void *cbopaque, const char *s) { -#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write) - /* - * Use syscall(2) rather than write(2) when possible in order to avoid - * the possibility of memory allocation within libc. This is necessary - * on FreeBSD; most operating systems do not have this problem though. - * - * syscall() returns long or int, depending on platform, so capture the - * unused result in the widest plausible type to avoid compiler - * warnings. - */ - UNUSED long result = syscall(SYS_write, STDERR_FILENO, s, strlen(s)); -#else - UNUSED ssize_t result = write(STDERR_FILENO, s, strlen(s)); -#endif + malloc_write_fd(STDERR_FILENO, s, strlen(s)); } JEMALLOC_EXPORT void (*je_malloc_message)(void *, const char *s); @@ -111,7 +98,7 @@ buferror(int err, char *buf, size_t buflen) { FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (LPSTR)buf, (DWORD)buflen, NULL); return 0; -#elif defined(__GLIBC__) && defined(_GNU_SOURCE) +#elif defined(JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE) && defined(_GNU_SOURCE) char *b = strerror_r(err, buf, buflen); if (b != buf) { strncpy(buf, b, buflen); diff --git a/kbe/src/lib/dependencies/jemalloc/src/mutex.c b/kbe/src/lib/dependencies/jemalloc/src/mutex.c index a528ef0c24..3f920f5b1c 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/mutex.c +++ b/kbe/src/lib/dependencies/jemalloc/src/mutex.c @@ -4,6 +4,7 @@ #include "jemalloc/internal/assert.h" #include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/spin.h" #ifndef _CRT_SPINCOUNT #define _CRT_SPINCOUNT 4000 @@ -45,7 +46,7 @@ JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, void malloc_mutex_lock_slow(malloc_mutex_t *mutex) { mutex_prof_data_t *data = &mutex->prof_data; - UNUSED nstime_t before = NSTIME_ZERO_INITIALIZER; + nstime_t before = NSTIME_ZERO_INITIALIZER; if (ncpus == 1) { goto label_spin_done; @@ -53,8 +54,9 @@ malloc_mutex_lock_slow(malloc_mutex_t *mutex) { int cnt = 0, max_cnt = MALLOC_MUTEX_MAX_SPIN; do { - CPU_SPINWAIT; - if (!malloc_mutex_trylock_final(mutex)) { + spin_cpu_spinwait(); + if (!atomic_load_b(&mutex->locked, ATOMIC_RELAXED) + && !malloc_mutex_trylock_final(mutex)) { data->n_spin_acquired++; return; } @@ -143,9 +145,7 @@ malloc_mutex_init(malloc_mutex_t *mutex, const char *name, } # endif #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) - mutex->lock = OS_UNFAIR_LOCK_INIT; -#elif (defined(JEMALLOC_OSSPIN)) - mutex->lock = 0; + mutex->lock = OS_UNFAIR_LOCK_INIT; #elif (defined(JEMALLOC_MUTEX_INIT_CB)) if (postpone_init) { mutex->postponed_next = postponed_mutexes; @@ -173,7 +173,7 @@ malloc_mutex_init(malloc_mutex_t *mutex, const char *name, mutex->lock_order = lock_order; if (lock_order == malloc_mutex_address_ordered) { witness_init(&mutex->witness, name, rank, - mutex_addr_comp, &mutex); + mutex_addr_comp, mutex); } else { witness_init(&mutex->witness, name, rank, NULL, NULL); } diff --git a/kbe/src/lib/dependencies/jemalloc/src/pages.c b/kbe/src/lib/dependencies/jemalloc/src/pages.c index fec64dd01d..13de27a008 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/pages.c +++ b/kbe/src/lib/dependencies/jemalloc/src/pages.c @@ -10,6 +10,9 @@ #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT #include +#ifdef __FreeBSD__ +#include +#endif #endif /******************************************************************************/ @@ -25,6 +28,18 @@ static int mmap_flags; #endif static bool os_overcommits; +const char *thp_mode_names[] = { + "default", + "always", + "never", + "not supported" +}; +thp_mode_t opt_thp = THP_MODE_DEFAULT; +thp_mode_t init_system_thp_mode; + +/* Runtime support for lazy purge. Irrelevant when !pages_can_purge_lazy. */ +static bool pages_can_purge_lazy_runtime = true; + /******************************************************************************/ /* * Function prototypes for static functions that are referenced prior to @@ -165,6 +180,35 @@ pages_map(void *addr, size_t size, size_t alignment, bool *commit) { assert(alignment >= PAGE); assert(ALIGNMENT_ADDR2BASE(addr, alignment) == addr); +#if defined(__FreeBSD__) && defined(MAP_EXCL) + /* + * FreeBSD has mechanisms both to mmap at specific address without + * touching existing mappings, and to mmap with specific alignment. + */ + { + if (os_overcommits) { + *commit = true; + } + + int prot = *commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT; + int flags = mmap_flags; + + if (addr != NULL) { + flags |= MAP_FIXED | MAP_EXCL; + } else { + unsigned alignment_bits = ffs_zu(alignment); + assert(alignment_bits > 1); + flags |= MAP_ALIGNED(alignment_bits - 1); + } + + void *ret = mmap(addr, size, prot, flags, -1, 0); + if (ret == MAP_FAILED) { + ret = NULL; + } + + return ret; + } +#endif /* * Ideally, there would be a way to specify alignment to mmap() (like * NetBSD has), but in the absence of such a feature, we have to work @@ -246,18 +290,31 @@ pages_decommit(void *addr, size_t size) { bool pages_purge_lazy(void *addr, size_t size) { - assert(PAGE_ADDR2BASE(addr) == addr); + assert(ALIGNMENT_ADDR2BASE(addr, os_page) == addr); assert(PAGE_CEILING(size) == size); if (!pages_can_purge_lazy) { return true; } + if (!pages_can_purge_lazy_runtime) { + /* + * Built with lazy purge enabled, but detected it was not + * supported on the current system. + */ + return true; + } #ifdef _WIN32 VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE); return false; #elif defined(JEMALLOC_PURGE_MADVISE_FREE) - return (madvise(addr, size, MADV_FREE) != 0); + return (madvise(addr, size, +# ifdef MADV_FREE + MADV_FREE +# else + JEMALLOC_MADV_FREE +# endif + ) != 0); #elif defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \ !defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS) return (madvise(addr, size, MADV_DONTNEED) != 0); @@ -286,36 +343,88 @@ pages_purge_forced(void *addr, size_t size) { #endif } +static bool +pages_huge_impl(void *addr, size_t size, bool aligned) { + if (aligned) { + assert(HUGEPAGE_ADDR2BASE(addr) == addr); + assert(HUGEPAGE_CEILING(size) == size); + } +#ifdef JEMALLOC_HAVE_MADVISE_HUGE + return (madvise(addr, size, MADV_HUGEPAGE) != 0); +#else + return true; +#endif +} + bool pages_huge(void *addr, size_t size) { - assert(HUGEPAGE_ADDR2BASE(addr) == addr); - assert(HUGEPAGE_CEILING(size) == size); + return pages_huge_impl(addr, size, true); +} -#ifdef JEMALLOC_THP - return (madvise(addr, size, MADV_HUGEPAGE) != 0); +static bool +pages_huge_unaligned(void *addr, size_t size) { + return pages_huge_impl(addr, size, false); +} + +static bool +pages_nohuge_impl(void *addr, size_t size, bool aligned) { + if (aligned) { + assert(HUGEPAGE_ADDR2BASE(addr) == addr); + assert(HUGEPAGE_CEILING(size) == size); + } + +#ifdef JEMALLOC_HAVE_MADVISE_HUGE + return (madvise(addr, size, MADV_NOHUGEPAGE) != 0); #else - return true; + return false; #endif } bool pages_nohuge(void *addr, size_t size) { - assert(HUGEPAGE_ADDR2BASE(addr) == addr); - assert(HUGEPAGE_CEILING(size) == size); + return pages_nohuge_impl(addr, size, true); +} -#ifdef JEMALLOC_THP - return (madvise(addr, size, MADV_NOHUGEPAGE) != 0); +static bool +pages_nohuge_unaligned(void *addr, size_t size) { + return pages_nohuge_impl(addr, size, false); +} + +bool +pages_dontdump(void *addr, size_t size) { + assert(PAGE_ADDR2BASE(addr) == addr); + assert(PAGE_CEILING(size) == size); +#ifdef JEMALLOC_MADVISE_DONTDUMP + return madvise(addr, size, MADV_DONTDUMP) != 0; #else return false; #endif } +bool +pages_dodump(void *addr, size_t size) { + assert(PAGE_ADDR2BASE(addr) == addr); + assert(PAGE_CEILING(size) == size); +#ifdef JEMALLOC_MADVISE_DONTDUMP + return madvise(addr, size, MADV_DODUMP) != 0; +#else + return false; +#endif +} + + static size_t os_page_detect(void) { #ifdef _WIN32 SYSTEM_INFO si; GetSystemInfo(&si); return si.dwPageSize; +#elif defined(__FreeBSD__) + /* + * This returns the value obtained from + * the auxv vector, avoiding a syscall. + */ + return getpagesize(); #else long result = sysconf(_SC_PAGESIZE); if (result == -1) { @@ -332,9 +441,19 @@ os_overcommits_sysctl(void) { size_t sz; sz = sizeof(vm_overcommit); +#if defined(__FreeBSD__) && defined(VM_OVERCOMMIT) + int mib[2]; + + mib[0] = CTL_VM; + mib[1] = VM_OVERCOMMIT; + if (sysctl(mib, 2, &vm_overcommit, &sz, NULL, 0) != 0) { + return false; /* Error. */ + } +#else if (sysctlbyname("vm.overcommit", &vm_overcommit, &sz, NULL, 0) != 0) { return false; /* Error. */ } +#endif return ((vm_overcommit & 0x3) == 0); } @@ -350,27 +469,44 @@ static bool os_overcommits_proc(void) { int fd; char buf[1]; - ssize_t nread; #if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open) - fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY | - O_CLOEXEC); + #if defined(O_CLOEXEC) + fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY | + O_CLOEXEC); + #else + fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY); + if (fd != -1) { + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + #endif #elif defined(JEMALLOC_USE_SYSCALL) && defined(SYS_openat) - fd = (int)syscall(SYS_openat, - AT_FDCWD, "/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC); + #if defined(O_CLOEXEC) + fd = (int)syscall(SYS_openat, + AT_FDCWD, "/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC); + #else + fd = (int)syscall(SYS_openat, + AT_FDCWD, "/proc/sys/vm/overcommit_memory", O_RDONLY); + if (fd != -1) { + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + #endif #else - fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC); + #if defined(O_CLOEXEC) + fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC); + #else + fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY); + if (fd != -1) { + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + #endif #endif + if (fd == -1) { return false; /* Error. */ } -#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read) - nread = (ssize_t)syscall(SYS_read, fd, &buf, sizeof(buf)); -#else - nread = read(fd, &buf, sizeof(buf)); -#endif - + ssize_t nread = malloc_read_fd(fd, &buf, sizeof(buf)); #if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close) syscall(SYS_close, fd); #else @@ -390,6 +526,75 @@ os_overcommits_proc(void) { } #endif +void +pages_set_thp_state (void *ptr, size_t size) { + if (opt_thp == thp_mode_default || opt_thp == init_system_thp_mode) { + return; + } + assert(opt_thp != thp_mode_not_supported && + init_system_thp_mode != thp_mode_not_supported); + + if (opt_thp == thp_mode_always + && init_system_thp_mode != thp_mode_never) { + assert(init_system_thp_mode == thp_mode_default); + pages_huge_unaligned(ptr, size); + } else if (opt_thp == thp_mode_never) { + assert(init_system_thp_mode == thp_mode_default || + init_system_thp_mode == thp_mode_always); + pages_nohuge_unaligned(ptr, size); + } +} + +static void +init_thp_state(void) { + if (!have_madvise_huge) { + if (metadata_thp_enabled() && opt_abort) { + malloc_write(": no MADV_HUGEPAGE support\n"); + abort(); + } + goto label_error; + } + + static const char sys_state_madvise[] = "always [madvise] never\n"; + static const char sys_state_always[] = "[always] madvise never\n"; + static const char sys_state_never[] = "always madvise [never]\n"; + char buf[sizeof(sys_state_madvise)]; + +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open) + int fd = (int)syscall(SYS_open, + "/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY); +#else + int fd = open("/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY); +#endif + if (fd == -1) { + goto label_error; + } + + ssize_t nread = malloc_read_fd(fd, &buf, sizeof(buf)); +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close) + syscall(SYS_close, fd); +#else + close(fd); +#endif + + if (nread < 0) { + goto label_error; + } + + if (strncmp(buf, sys_state_madvise, (size_t)nread) == 0) { + init_system_thp_mode = thp_mode_default; + } else if (strncmp(buf, sys_state_always, (size_t)nread) == 0) { + init_system_thp_mode = thp_mode_always; + } else if (strncmp(buf, sys_state_never, (size_t)nread) == 0) { + init_system_thp_mode = thp_mode_never; + } else { + goto label_error; + } + return; +label_error: + opt_thp = init_system_thp_mode = thp_mode_not_supported; +} + bool pages_boot(void) { os_page = os_page_detect(); @@ -418,5 +623,27 @@ pages_boot(void) { os_overcommits = false; #endif + init_thp_state(); + +#ifdef __FreeBSD__ + /* + * FreeBSD doesn't need the check; madvise(2) is known to work. + */ +#else + /* Detect lazy purge runtime support. */ + if (pages_can_purge_lazy) { + bool committed = false; + void *madv_free_page = os_pages_map(NULL, PAGE, PAGE, &committed); + if (madv_free_page == NULL) { + return true; + } + assert(pages_can_purge_lazy_runtime); + if (pages_purge_lazy(madv_free_page, PAGE)) { + pages_can_purge_lazy_runtime = false; + } + os_pages_unmap(madv_free_page, PAGE); + } +#endif + return false; } diff --git a/kbe/src/lib/dependencies/jemalloc/src/prof.c b/kbe/src/lib/dependencies/jemalloc/src/prof.c index 975722c4c3..4d7d65db40 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/prof.c +++ b/kbe/src/lib/dependencies/jemalloc/src/prof.c @@ -7,6 +7,7 @@ #include "jemalloc/internal/hash.h" #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/emitter.h" /******************************************************************************/ @@ -23,7 +24,7 @@ */ #undef _Unwind_Backtrace #include -#define _Unwind_Backtrace JEMALLOC_HOOK(_Unwind_Backtrace, hooks_libc_hook) +#define _Unwind_Backtrace JEMALLOC_HOOK(_Unwind_Backtrace, test_hooks_libc_hook) #endif /******************************************************************************/ @@ -38,6 +39,7 @@ bool opt_prof_gdump = false; bool opt_prof_final = false; bool opt_prof_leak = false; bool opt_prof_accum = false; +bool opt_prof_log = false; char opt_prof_prefix[ /* Minimize memory bloat for non-prof builds. */ #ifdef JEMALLOC_PROF @@ -70,6 +72,100 @@ uint64_t prof_interval = 0; size_t lg_prof_sample; +typedef enum prof_logging_state_e prof_logging_state_t; +enum prof_logging_state_e { + prof_logging_state_stopped, + prof_logging_state_started, + prof_logging_state_dumping +}; + +/* + * - stopped: log_start never called, or previous log_stop has completed. + * - started: log_start called, log_stop not called yet. Allocations are logged. + * - dumping: log_stop called but not finished; samples are not logged anymore. + */ +prof_logging_state_t prof_logging_state = prof_logging_state_stopped; + +#ifdef JEMALLOC_JET +static bool prof_log_dummy = false; +#endif + +/* Incremented for every log file that is output. */ +static uint64_t log_seq = 0; +static char log_filename[ + /* Minimize memory bloat for non-prof builds. */ +#ifdef JEMALLOC_PROF + PATH_MAX + +#endif + 1]; + +/* Timestamp for most recent call to log_start(). */ +static nstime_t log_start_timestamp = NSTIME_ZERO_INITIALIZER; + +/* Increment these when adding to the log_bt and log_thr linked lists. */ +static size_t log_bt_index = 0; +static size_t log_thr_index = 0; + +/* Linked list node definitions. These are only used in prof.c. */ +typedef struct prof_bt_node_s prof_bt_node_t; + +struct prof_bt_node_s { + prof_bt_node_t *next; + size_t index; + prof_bt_t bt; + /* Variable size backtrace vector pointed to by bt. */ + void *vec[1]; +}; + +typedef struct prof_thr_node_s prof_thr_node_t; + +struct prof_thr_node_s { + prof_thr_node_t *next; + size_t index; + uint64_t thr_uid; + /* Variable size based on thr_name_sz. */ + char name[1]; +}; + +typedef struct prof_alloc_node_s prof_alloc_node_t; + +/* This is output when logging sampled allocations. */ +struct prof_alloc_node_s { + prof_alloc_node_t *next; + /* Indices into an array of thread data. */ + size_t alloc_thr_ind; + size_t free_thr_ind; + + /* Indices into an array of backtraces. */ + size_t alloc_bt_ind; + size_t free_bt_ind; + + uint64_t alloc_time_ns; + uint64_t free_time_ns; + + size_t usize; +}; + +/* + * Created on the first call to prof_log_start and deleted on prof_log_stop. + * These are the backtraces and threads that have already been logged by an + * allocation. + */ +static bool log_tables_initialized = false; +static ckh_t log_bt_node_set; +static ckh_t log_thr_node_set; + +/* Store linked lists for logged data. */ +static prof_bt_node_t *log_bt_first = NULL; +static prof_bt_node_t *log_bt_last = NULL; +static prof_thr_node_t *log_thr_first = NULL; +static prof_thr_node_t *log_thr_last = NULL; +static prof_alloc_node_t *log_alloc_first = NULL; +static prof_alloc_node_t *log_alloc_last = NULL; + +/* Protects the prof_logging_state and any log_{...} variable. */ +static malloc_mutex_t log_mtx; + /* * Table of mutexes that are shared among gctx's. These are leaf locks, so * there is no problem with using them for more than one gctx at the same time. @@ -145,6 +241,12 @@ static void prof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata, bool even_if_attached); static char *prof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name); +/* Hashtable functions for log_bt_node_set and log_thr_node_set. */ +static void prof_thr_node_hash(const void *key, size_t r_hash[2]); +static bool prof_thr_node_keycomp(const void *k1, const void *k2); +static void prof_bt_node_hash(const void *key, size_t r_hash[2]); +static bool prof_bt_node_keycomp(const void *k1, const void *k2); + /******************************************************************************/ /* Red-black trees. */ @@ -242,6 +344,12 @@ prof_malloc_sample_object(tsdn_t *tsdn, const void *ptr, size_t usize, prof_tctx_t *tctx) { prof_tctx_set(tsdn, ptr, usize, NULL, tctx); + /* Get the current time and set this in the extent_t. We'll read this + * when free() is called. */ + nstime_t t = NSTIME_ZERO_INITIALIZER; + nstime_update(&t); + prof_alloc_time_set(tsdn, ptr, NULL, t); + malloc_mutex_lock(tsdn, tctx->tdata->lock); tctx->cnts.curobjs++; tctx->cnts.curbytes += usize; @@ -253,14 +361,174 @@ prof_malloc_sample_object(tsdn_t *tsdn, const void *ptr, size_t usize, malloc_mutex_unlock(tsdn, tctx->tdata->lock); } +static size_t +prof_log_bt_index(tsd_t *tsd, prof_bt_t *bt) { + assert(prof_logging_state == prof_logging_state_started); + malloc_mutex_assert_owner(tsd_tsdn(tsd), &log_mtx); + + prof_bt_node_t dummy_node; + dummy_node.bt = *bt; + prof_bt_node_t *node; + + /* See if this backtrace is already cached in the table. */ + if (ckh_search(&log_bt_node_set, (void *)(&dummy_node), + (void **)(&node), NULL)) { + size_t sz = offsetof(prof_bt_node_t, vec) + + (bt->len * sizeof(void *)); + prof_bt_node_t *new_node = (prof_bt_node_t *) + iallocztm(tsd_tsdn(tsd), sz, sz_size2index(sz), false, NULL, + true, arena_get(TSDN_NULL, 0, true), true); + if (log_bt_first == NULL) { + log_bt_first = new_node; + log_bt_last = new_node; + } else { + log_bt_last->next = new_node; + log_bt_last = new_node; + } + + new_node->next = NULL; + new_node->index = log_bt_index; + /* + * Copy the backtrace: bt is inside a tdata or gctx, which + * might die before prof_log_stop is called. + */ + new_node->bt.len = bt->len; + memcpy(new_node->vec, bt->vec, bt->len * sizeof(void *)); + new_node->bt.vec = new_node->vec; + + log_bt_index++; + ckh_insert(tsd, &log_bt_node_set, (void *)new_node, NULL); + return new_node->index; + } else { + return node->index; + } +} +static size_t +prof_log_thr_index(tsd_t *tsd, uint64_t thr_uid, const char *name) { + assert(prof_logging_state == prof_logging_state_started); + malloc_mutex_assert_owner(tsd_tsdn(tsd), &log_mtx); + + prof_thr_node_t dummy_node; + dummy_node.thr_uid = thr_uid; + prof_thr_node_t *node; + + /* See if this thread is already cached in the table. */ + if (ckh_search(&log_thr_node_set, (void *)(&dummy_node), + (void **)(&node), NULL)) { + size_t sz = offsetof(prof_thr_node_t, name) + strlen(name) + 1; + prof_thr_node_t *new_node = (prof_thr_node_t *) + iallocztm(tsd_tsdn(tsd), sz, sz_size2index(sz), false, NULL, + true, arena_get(TSDN_NULL, 0, true), true); + if (log_thr_first == NULL) { + log_thr_first = new_node; + log_thr_last = new_node; + } else { + log_thr_last->next = new_node; + log_thr_last = new_node; + } + + new_node->next = NULL; + new_node->index = log_thr_index; + new_node->thr_uid = thr_uid; + strcpy(new_node->name, name); + + log_thr_index++; + ckh_insert(tsd, &log_thr_node_set, (void *)new_node, NULL); + return new_node->index; + } else { + return node->index; + } +} + +static void +prof_try_log(tsd_t *tsd, const void *ptr, size_t usize, prof_tctx_t *tctx) { + malloc_mutex_assert_owner(tsd_tsdn(tsd), tctx->tdata->lock); + + prof_tdata_t *cons_tdata = prof_tdata_get(tsd, false); + if (cons_tdata == NULL) { + /* + * We decide not to log these allocations. cons_tdata will be + * NULL only when the current thread is in a weird state (e.g. + * it's being destroyed). + */ + return; + } + + malloc_mutex_lock(tsd_tsdn(tsd), &log_mtx); + + if (prof_logging_state != prof_logging_state_started) { + goto label_done; + } + + if (!log_tables_initialized) { + bool err1 = ckh_new(tsd, &log_bt_node_set, PROF_CKH_MINITEMS, + prof_bt_node_hash, prof_bt_node_keycomp); + bool err2 = ckh_new(tsd, &log_thr_node_set, PROF_CKH_MINITEMS, + prof_thr_node_hash, prof_thr_node_keycomp); + if (err1 || err2) { + goto label_done; + } + log_tables_initialized = true; + } + + nstime_t alloc_time = prof_alloc_time_get(tsd_tsdn(tsd), ptr, + (alloc_ctx_t *)NULL); + nstime_t free_time = NSTIME_ZERO_INITIALIZER; + nstime_update(&free_time); + + size_t sz = sizeof(prof_alloc_node_t); + prof_alloc_node_t *new_node = (prof_alloc_node_t *) + iallocztm(tsd_tsdn(tsd), sz, sz_size2index(sz), false, NULL, true, + arena_get(TSDN_NULL, 0, true), true); + + const char *prod_thr_name = (tctx->tdata->thread_name == NULL)? + "" : tctx->tdata->thread_name; + const char *cons_thr_name = prof_thread_name_get(tsd); + + prof_bt_t bt; + /* Initialize the backtrace, using the buffer in tdata to store it. */ + bt_init(&bt, cons_tdata->vec); + prof_backtrace(&bt); + prof_bt_t *cons_bt = &bt; + + /* We haven't destroyed tctx yet, so gctx should be good to read. */ + prof_bt_t *prod_bt = &tctx->gctx->bt; + + new_node->next = NULL; + new_node->alloc_thr_ind = prof_log_thr_index(tsd, tctx->tdata->thr_uid, + prod_thr_name); + new_node->free_thr_ind = prof_log_thr_index(tsd, cons_tdata->thr_uid, + cons_thr_name); + new_node->alloc_bt_ind = prof_log_bt_index(tsd, prod_bt); + new_node->free_bt_ind = prof_log_bt_index(tsd, cons_bt); + new_node->alloc_time_ns = nstime_ns(&alloc_time); + new_node->free_time_ns = nstime_ns(&free_time); + new_node->usize = usize; + + if (log_alloc_first == NULL) { + log_alloc_first = new_node; + log_alloc_last = new_node; + } else { + log_alloc_last->next = new_node; + log_alloc_last = new_node; + } + +label_done: + malloc_mutex_unlock(tsd_tsdn(tsd), &log_mtx); +} + void -prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx) { +prof_free_sampled_object(tsd_t *tsd, const void *ptr, size_t usize, + prof_tctx_t *tctx) { malloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock); + assert(tctx->cnts.curobjs > 0); assert(tctx->cnts.curbytes >= usize); tctx->cnts.curobjs--; tctx->cnts.curbytes -= usize; + prof_try_log(tsd, ptr, usize, tctx); + if (prof_tctx_should_destroy(tsd_tsdn(tsd), tctx)) { prof_tctx_destroy(tsd, tctx); } else { @@ -871,15 +1139,12 @@ prof_lookup(tsd_t *tsd, prof_bt_t *bt) { void prof_sample_threshold_update(prof_tdata_t *tdata) { #ifdef JEMALLOC_PROF - uint64_t r; - double u; - if (!config_prof) { return; } if (lg_prof_sample == 0) { - tdata->bytes_until_sample = 0; + tsd_bytes_until_sample_set(tsd_fetch(), 0); return; } @@ -901,11 +1166,16 @@ prof_sample_threshold_update(prof_tdata_t *tdata) { * pp 500 * (http://luc.devroye.org/rnbookindex.html) */ - r = prng_lg_range_u64(&tdata->prng_state, 53); - u = (double)r * (1.0/9007199254740992.0L); - tdata->bytes_until_sample = (uint64_t)(log(u) / + uint64_t r = prng_lg_range_u64(&tdata->prng_state, 53); + double u = (double)r * (1.0/9007199254740992.0L); + uint64_t bytes_until_sample = (uint64_t)(log(u) / log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample)))) + (uint64_t)1U; + if (bytes_until_sample > SSIZE_MAX) { + bytes_until_sample = SSIZE_MAX; + } + tsd_bytes_until_sample_set(tsd_fetch(), bytes_until_sample); + #endif } @@ -978,7 +1248,7 @@ prof_dump_flush(bool propagate_err) { cassert(config_prof); - err = write(prof_dump_fd, prof_dump_buf, prof_dump_buf_end); + err = malloc_write_fd(prof_dump_fd, prof_dump_buf, prof_dump_buf_end); if (err == -1) { if (!propagate_err) { malloc_write(": write() failed during heap " @@ -1409,7 +1679,15 @@ prof_open_maps(const char *format, ...) { va_start(ap, format); malloc_vsnprintf(filename, sizeof(filename), format, ap); va_end(ap); + +#if defined(O_CLOEXEC) mfd = open(filename, O_RDONLY | O_CLOEXEC); +#else + mfd = open(filename, O_RDONLY); + if (mfd != -1) { + fcntl(mfd, F_SETFD, fcntl(mfd, F_GETFD) | FD_CLOEXEC); + } +#endif return mfd; } @@ -1463,8 +1741,9 @@ prof_dump_maps(bool propagate_err) { goto label_return; } } - nread = read(mfd, &prof_dump_buf[prof_dump_buf_end], - PROF_DUMP_BUFSIZE - prof_dump_buf_end); + nread = malloc_read_fd(mfd, + &prof_dump_buf[prof_dump_buf_end], PROF_DUMP_BUFSIZE + - prof_dump_buf_end); } while (nread > 0); } else { ret = true; @@ -1772,7 +2051,7 @@ prof_idump(tsdn_t *tsdn) { cassert(config_prof); - if (!prof_booted || tsdn_null(tsdn)) { + if (!prof_booted || tsdn_null(tsdn) || !prof_active_get_unlocked()) { return; } tsd = tsdn_tsd(tsdn); @@ -1829,7 +2108,7 @@ prof_gdump(tsdn_t *tsdn) { cassert(config_prof); - if (!prof_booted || tsdn_null(tsdn)) { + if (!prof_booted || tsdn_null(tsdn) || !prof_active_get_unlocked()) { return; } tsd = tsdn_tsd(tsdn); @@ -1878,6 +2157,33 @@ prof_bt_keycomp(const void *k1, const void *k2) { return (memcmp(bt1->vec, bt2->vec, bt1->len * sizeof(void *)) == 0); } +static void +prof_bt_node_hash(const void *key, size_t r_hash[2]) { + const prof_bt_node_t *bt_node = (prof_bt_node_t *)key; + prof_bt_hash((void *)(&bt_node->bt), r_hash); +} + +static bool +prof_bt_node_keycomp(const void *k1, const void *k2) { + const prof_bt_node_t *bt_node1 = (prof_bt_node_t *)k1; + const prof_bt_node_t *bt_node2 = (prof_bt_node_t *)k2; + return prof_bt_keycomp((void *)(&bt_node1->bt), + (void *)(&bt_node2->bt)); +} + +static void +prof_thr_node_hash(const void *key, size_t r_hash[2]) { + const prof_thr_node_t *thr_node = (prof_thr_node_t *)key; + hash(&thr_node->thr_uid, sizeof(uint64_t), 0x94122f35U, r_hash); +} + +static bool +prof_thr_node_keycomp(const void *k1, const void *k2) { + const prof_thr_node_t *thr_node1 = (prof_thr_node_t *)k1; + const prof_thr_node_t *thr_node2 = (prof_thr_node_t *)k2; + return thr_node1->thr_uid == thr_node2->thr_uid; +} + static uint64_t prof_thr_uid_alloc(tsdn_t *tsdn) { uint64_t thr_uid; @@ -2110,6 +2416,368 @@ prof_active_set(tsdn_t *tsdn, bool active) { return prof_active_old; } +#ifdef JEMALLOC_JET +size_t +prof_log_bt_count(void) { + size_t cnt = 0; + prof_bt_node_t *node = log_bt_first; + while (node != NULL) { + cnt++; + node = node->next; + } + return cnt; +} + +size_t +prof_log_alloc_count(void) { + size_t cnt = 0; + prof_alloc_node_t *node = log_alloc_first; + while (node != NULL) { + cnt++; + node = node->next; + } + return cnt; +} + +size_t +prof_log_thr_count(void) { + size_t cnt = 0; + prof_thr_node_t *node = log_thr_first; + while (node != NULL) { + cnt++; + node = node->next; + } + return cnt; +} + +bool +prof_log_is_logging(void) { + return prof_logging_state == prof_logging_state_started; +} + +bool +prof_log_rep_check(void) { + if (prof_logging_state == prof_logging_state_stopped + && log_tables_initialized) { + return true; + } + + if (log_bt_last != NULL && log_bt_last->next != NULL) { + return true; + } + if (log_thr_last != NULL && log_thr_last->next != NULL) { + return true; + } + if (log_alloc_last != NULL && log_alloc_last->next != NULL) { + return true; + } + + size_t bt_count = prof_log_bt_count(); + size_t thr_count = prof_log_thr_count(); + size_t alloc_count = prof_log_alloc_count(); + + + if (prof_logging_state == prof_logging_state_stopped) { + if (bt_count != 0 || thr_count != 0 || alloc_count || 0) { + return true; + } + } + + prof_alloc_node_t *node = log_alloc_first; + while (node != NULL) { + if (node->alloc_bt_ind >= bt_count) { + return true; + } + if (node->free_bt_ind >= bt_count) { + return true; + } + if (node->alloc_thr_ind >= thr_count) { + return true; + } + if (node->free_thr_ind >= thr_count) { + return true; + } + if (node->alloc_time_ns > node->free_time_ns) { + return true; + } + node = node->next; + } + + return false; +} + +void +prof_log_dummy_set(bool new_value) { + prof_log_dummy = new_value; +} +#endif + +bool +prof_log_start(tsdn_t *tsdn, const char *filename) { + if (!opt_prof || !prof_booted) { + return true; + } + + bool ret = false; + size_t buf_size = PATH_MAX + 1; + + malloc_mutex_lock(tsdn, &log_mtx); + + if (prof_logging_state != prof_logging_state_stopped) { + ret = true; + } else if (filename == NULL) { + /* Make default name. */ + malloc_snprintf(log_filename, buf_size, "%s.%d.%"FMTu64".json", + opt_prof_prefix, prof_getpid(), log_seq); + log_seq++; + prof_logging_state = prof_logging_state_started; + } else if (strlen(filename) >= buf_size) { + ret = true; + } else { + strcpy(log_filename, filename); + prof_logging_state = prof_logging_state_started; + } + + if (!ret) { + nstime_update(&log_start_timestamp); + } + + malloc_mutex_unlock(tsdn, &log_mtx); + + return ret; +} + +/* Used as an atexit function to stop logging on exit. */ +static void +prof_log_stop_final(void) { + tsd_t *tsd = tsd_fetch(); + prof_log_stop(tsd_tsdn(tsd)); +} + +struct prof_emitter_cb_arg_s { + int fd; + ssize_t ret; +}; + +static void +prof_emitter_write_cb(void *opaque, const char *to_write) { + struct prof_emitter_cb_arg_s *arg = + (struct prof_emitter_cb_arg_s *)opaque; + size_t bytes = strlen(to_write); +#ifdef JEMALLOC_JET + if (prof_log_dummy) { + return; + } +#endif + arg->ret = write(arg->fd, (void *)to_write, bytes); +} + +/* + * prof_log_emit_{...} goes through the appropriate linked list, emitting each + * node to the json and deallocating it. + */ +static void +prof_log_emit_threads(tsd_t *tsd, emitter_t *emitter) { + emitter_json_array_kv_begin(emitter, "threads"); + prof_thr_node_t *thr_node = log_thr_first; + prof_thr_node_t *thr_old_node; + while (thr_node != NULL) { + emitter_json_object_begin(emitter); + + emitter_json_kv(emitter, "thr_uid", emitter_type_uint64, + &thr_node->thr_uid); + + char *thr_name = thr_node->name; + + emitter_json_kv(emitter, "thr_name", emitter_type_string, + &thr_name); + + emitter_json_object_end(emitter); + thr_old_node = thr_node; + thr_node = thr_node->next; + idalloc(tsd, thr_old_node); + } + emitter_json_array_end(emitter); +} + +static void +prof_log_emit_traces(tsd_t *tsd, emitter_t *emitter) { + emitter_json_array_kv_begin(emitter, "stack_traces"); + prof_bt_node_t *bt_node = log_bt_first; + prof_bt_node_t *bt_old_node; + /* + * Calculate how many hex digits we need: twice number of bytes, two for + * "0x", and then one more for terminating '\0'. + */ + char buf[2 * sizeof(intptr_t) + 3]; + size_t buf_sz = sizeof(buf); + while (bt_node != NULL) { + emitter_json_array_begin(emitter); + size_t i; + for (i = 0; i < bt_node->bt.len; i++) { + malloc_snprintf(buf, buf_sz, "%p", bt_node->bt.vec[i]); + char *trace_str = buf; + emitter_json_value(emitter, emitter_type_string, + &trace_str); + } + emitter_json_array_end(emitter); + + bt_old_node = bt_node; + bt_node = bt_node->next; + idalloc(tsd, bt_old_node); + } + emitter_json_array_end(emitter); +} + +static void +prof_log_emit_allocs(tsd_t *tsd, emitter_t *emitter) { + emitter_json_array_kv_begin(emitter, "allocations"); + prof_alloc_node_t *alloc_node = log_alloc_first; + prof_alloc_node_t *alloc_old_node; + while (alloc_node != NULL) { + emitter_json_object_begin(emitter); + + emitter_json_kv(emitter, "alloc_thread", emitter_type_size, + &alloc_node->alloc_thr_ind); + + emitter_json_kv(emitter, "free_thread", emitter_type_size, + &alloc_node->free_thr_ind); + + emitter_json_kv(emitter, "alloc_trace", emitter_type_size, + &alloc_node->alloc_bt_ind); + + emitter_json_kv(emitter, "free_trace", emitter_type_size, + &alloc_node->free_bt_ind); + + emitter_json_kv(emitter, "alloc_timestamp", + emitter_type_uint64, &alloc_node->alloc_time_ns); + + emitter_json_kv(emitter, "free_timestamp", emitter_type_uint64, + &alloc_node->free_time_ns); + + emitter_json_kv(emitter, "usize", emitter_type_uint64, + &alloc_node->usize); + + emitter_json_object_end(emitter); + + alloc_old_node = alloc_node; + alloc_node = alloc_node->next; + idalloc(tsd, alloc_old_node); + } + emitter_json_array_end(emitter); +} + +static void +prof_log_emit_metadata(emitter_t *emitter) { + emitter_json_object_kv_begin(emitter, "info"); + + nstime_t now = NSTIME_ZERO_INITIALIZER; + + nstime_update(&now); + uint64_t ns = nstime_ns(&now) - nstime_ns(&log_start_timestamp); + emitter_json_kv(emitter, "duration", emitter_type_uint64, &ns); + + char *vers = JEMALLOC_VERSION; + emitter_json_kv(emitter, "version", + emitter_type_string, &vers); + + emitter_json_kv(emitter, "lg_sample_rate", + emitter_type_int, &lg_prof_sample); + + int pid = prof_getpid(); + emitter_json_kv(emitter, "pid", emitter_type_int, &pid); + + emitter_json_object_end(emitter); +} + + +bool +prof_log_stop(tsdn_t *tsdn) { + if (!opt_prof || !prof_booted) { + return true; + } + + tsd_t *tsd = tsdn_tsd(tsdn); + malloc_mutex_lock(tsdn, &log_mtx); + + if (prof_logging_state != prof_logging_state_started) { + malloc_mutex_unlock(tsdn, &log_mtx); + return true; + } + + /* + * Set the state to dumping. We'll set it to stopped when we're done. + * Since other threads won't be able to start/stop/log when the state is + * dumping, we don't have to hold the lock during the whole method. + */ + prof_logging_state = prof_logging_state_dumping; + malloc_mutex_unlock(tsdn, &log_mtx); + + + emitter_t emitter; + + /* Create a file. */ + + int fd; +#ifdef JEMALLOC_JET + if (prof_log_dummy) { + fd = 0; + } else { + fd = creat(log_filename, 0644); + } +#else + fd = creat(log_filename, 0644); +#endif + + if (fd == -1) { + malloc_printf(": creat() for log file \"%s\" " + " failed with %d\n", log_filename, errno); + if (opt_abort) { + abort(); + } + return true; + } + + /* Emit to json. */ + struct prof_emitter_cb_arg_s arg; + arg.fd = fd; + emitter_init(&emitter, emitter_output_json, &prof_emitter_write_cb, + (void *)(&arg)); + + emitter_json_object_begin(&emitter); + prof_log_emit_metadata(&emitter); + prof_log_emit_threads(tsd, &emitter); + prof_log_emit_traces(tsd, &emitter); + prof_log_emit_allocs(tsd, &emitter); + emitter_json_object_end(&emitter); + + /* Reset global state. */ + if (log_tables_initialized) { + ckh_delete(tsd, &log_bt_node_set); + ckh_delete(tsd, &log_thr_node_set); + } + log_tables_initialized = false; + log_bt_index = 0; + log_thr_index = 0; + log_bt_first = NULL; + log_bt_last = NULL; + log_thr_first = NULL; + log_thr_last = NULL; + log_alloc_first = NULL; + log_alloc_last = NULL; + + malloc_mutex_lock(tsdn, &log_mtx); + prof_logging_state = prof_logging_state_stopped; + malloc_mutex_unlock(tsdn, &log_mtx); + +#ifdef JEMALLOC_JET + if (prof_log_dummy) { + return false; + } +#endif + return close(fd); +} + const char * prof_thread_name_get(tsd_t *tsd) { prof_tdata_t *tdata; @@ -2346,6 +3014,35 @@ prof_boot2(tsd_t *tsd) { } } + if (opt_prof_log) { + prof_log_start(tsd_tsdn(tsd), NULL); + } + + if (atexit(prof_log_stop_final) != 0) { + malloc_write(": Error in atexit() " + "for logging\n"); + if (opt_abort) { + abort(); + } + } + + if (malloc_mutex_init(&log_mtx, "prof_log", + WITNESS_RANK_PROF_LOG, malloc_mutex_rank_exclusive)) { + return true; + } + + if (ckh_new(tsd, &log_bt_node_set, PROF_CKH_MINITEMS, + prof_bt_node_hash, prof_bt_node_keycomp)) { + return true; + } + + if (ckh_new(tsd, &log_thr_node_set, PROF_CKH_MINITEMS, + prof_thr_node_hash, prof_thr_node_keycomp)) { + return true; + } + + log_tables_initialized = true; + gctx_locks = (malloc_mutex_t *)base_alloc(tsd_tsdn(tsd), b0get(), PROF_NCTX_LOCKS * sizeof(malloc_mutex_t), CACHELINE); @@ -2373,16 +3070,14 @@ prof_boot2(tsd_t *tsd) { return true; } } - } - #ifdef JEMALLOC_PROF_LIBGCC - /* - * Cause the backtracing machinery to allocate its internal state - * before enabling profiling. - */ - _Unwind_Backtrace(prof_unwind_init_callback, NULL); + /* + * Cause the backtracing machinery to allocate its internal + * state before enabling profiling. + */ + _Unwind_Backtrace(prof_unwind_init_callback, NULL); #endif - + } prof_booted = true; return false; diff --git a/kbe/src/lib/dependencies/jemalloc/src/rtree.c b/kbe/src/lib/dependencies/jemalloc/src/rtree.c index 53702cf723..4ae41fe2fe 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/rtree.c +++ b/kbe/src/lib/dependencies/jemalloc/src/rtree.c @@ -39,7 +39,7 @@ rtree_node_dalloc_impl(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *node) { /* Nodes are never deleted during normal operation. */ not_reached(); } -UNUSED rtree_node_dalloc_t *JET_MUTABLE rtree_node_dalloc = +rtree_node_dalloc_t *JET_MUTABLE rtree_node_dalloc = rtree_node_dalloc_impl; static rtree_leaf_elm_t * @@ -54,7 +54,7 @@ rtree_leaf_dalloc_impl(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *leaf) { /* Leaves are never deleted during normal operation. */ not_reached(); } -UNUSED rtree_leaf_dalloc_t *JET_MUTABLE rtree_leaf_dalloc = +rtree_leaf_dalloc_t *JET_MUTABLE rtree_leaf_dalloc = rtree_leaf_dalloc_impl; #ifdef JEMALLOC_JET diff --git a/kbe/src/lib/dependencies/jemalloc/src/sc.c b/kbe/src/lib/dependencies/jemalloc/src/sc.c new file mode 100644 index 0000000000..89ddb6ba6a --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/src/sc.c @@ -0,0 +1,313 @@ +#include "jemalloc/internal/jemalloc_preamble.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/bit_util.h" +#include "jemalloc/internal/bitmap.h" +#include "jemalloc/internal/pages.h" +#include "jemalloc/internal/sc.h" + +/* + * This module computes the size classes used to satisfy allocations. The logic + * here was ported more or less line-by-line from a shell script, and because of + * that is not the most idiomatic C. Eventually we should fix this, but for now + * at least the damage is compartmentalized to this file. + */ + +sc_data_t sc_data_global; + +static size_t +reg_size_compute(int lg_base, int lg_delta, int ndelta) { + return (ZU(1) << lg_base) + (ZU(ndelta) << lg_delta); +} + +/* Returns the number of pages in the slab. */ +static int +slab_size(int lg_page, int lg_base, int lg_delta, int ndelta) { + size_t page = (ZU(1) << lg_page); + size_t reg_size = reg_size_compute(lg_base, lg_delta, ndelta); + + size_t try_slab_size = page; + size_t try_nregs = try_slab_size / reg_size; + size_t perfect_slab_size = 0; + bool perfect = false; + /* + * This loop continues until we find the least common multiple of the + * page size and size class size. Size classes are all of the form + * base + ndelta * delta == (ndelta + base/ndelta) * delta, which is + * (ndelta + ngroup) * delta. The way we choose slabbing strategies + * means that delta is at most the page size and ndelta < ngroup. So + * the loop executes for at most 2 * ngroup - 1 iterations, which is + * also the bound on the number of pages in a slab chosen by default. + * With the current default settings, this is at most 7. + */ + while (!perfect) { + perfect_slab_size = try_slab_size; + size_t perfect_nregs = try_nregs; + try_slab_size += page; + try_nregs = try_slab_size / reg_size; + if (perfect_slab_size == perfect_nregs * reg_size) { + perfect = true; + } + } + return (int)(perfect_slab_size / page); +} + +static void +size_class( + /* Output. */ + sc_t *sc, + /* Configuration decisions. */ + int lg_max_lookup, int lg_page, int lg_ngroup, + /* Inputs specific to the size class. */ + int index, int lg_base, int lg_delta, int ndelta) { + sc->index = index; + sc->lg_base = lg_base; + sc->lg_delta = lg_delta; + sc->ndelta = ndelta; + sc->psz = (reg_size_compute(lg_base, lg_delta, ndelta) + % (ZU(1) << lg_page) == 0); + size_t size = (ZU(1) << lg_base) + (ZU(ndelta) << lg_delta); + if (index == 0) { + assert(!sc->psz); + } + if (size < (ZU(1) << (lg_page + lg_ngroup))) { + sc->bin = true; + sc->pgs = slab_size(lg_page, lg_base, lg_delta, ndelta); + } else { + sc->bin = false; + sc->pgs = 0; + } + if (size <= (ZU(1) << lg_max_lookup)) { + sc->lg_delta_lookup = lg_delta; + } else { + sc->lg_delta_lookup = 0; + } +} + +static void +size_classes( + /* Output. */ + sc_data_t *sc_data, + /* Determined by the system. */ + size_t lg_ptr_size, int lg_quantum, + /* Configuration decisions. */ + int lg_tiny_min, int lg_max_lookup, int lg_page, int lg_ngroup) { + int ptr_bits = (1 << lg_ptr_size) * 8; + int ngroup = (1 << lg_ngroup); + int ntiny = 0; + int nlbins = 0; + int lg_tiny_maxclass = (unsigned)-1; + int nbins = 0; + int npsizes = 0; + + int index = 0; + + int ndelta = 0; + int lg_base = lg_tiny_min; + int lg_delta = lg_base; + + /* Outputs that we update as we go. */ + size_t lookup_maxclass = 0; + size_t small_maxclass = 0; + int lg_large_minclass = 0; + size_t large_maxclass = 0; + + /* Tiny size classes. */ + while (lg_base < lg_quantum) { + sc_t *sc = &sc_data->sc[index]; + size_class(sc, lg_max_lookup, lg_page, lg_ngroup, index, + lg_base, lg_delta, ndelta); + if (sc->lg_delta_lookup != 0) { + nlbins = index + 1; + } + if (sc->psz) { + npsizes++; + } + if (sc->bin) { + nbins++; + } + ntiny++; + /* Final written value is correct. */ + lg_tiny_maxclass = lg_base; + index++; + lg_delta = lg_base; + lg_base++; + } + + /* First non-tiny (pseudo) group. */ + if (ntiny != 0) { + sc_t *sc = &sc_data->sc[index]; + /* + * See the note in sc.h; the first non-tiny size class has an + * unusual encoding. + */ + lg_base--; + ndelta = 1; + size_class(sc, lg_max_lookup, lg_page, lg_ngroup, index, + lg_base, lg_delta, ndelta); + index++; + lg_base++; + lg_delta++; + if (sc->psz) { + npsizes++; + } + if (sc->bin) { + nbins++; + } + } + while (ndelta < ngroup) { + sc_t *sc = &sc_data->sc[index]; + size_class(sc, lg_max_lookup, lg_page, lg_ngroup, index, + lg_base, lg_delta, ndelta); + index++; + ndelta++; + if (sc->psz) { + npsizes++; + } + if (sc->bin) { + nbins++; + } + } + + /* All remaining groups. */ + lg_base = lg_base + lg_ngroup; + while (lg_base < ptr_bits - 1) { + ndelta = 1; + int ndelta_limit; + if (lg_base == ptr_bits - 2) { + ndelta_limit = ngroup - 1; + } else { + ndelta_limit = ngroup; + } + while (ndelta <= ndelta_limit) { + sc_t *sc = &sc_data->sc[index]; + size_class(sc, lg_max_lookup, lg_page, lg_ngroup, index, + lg_base, lg_delta, ndelta); + if (sc->lg_delta_lookup != 0) { + nlbins = index + 1; + /* Final written value is correct. */ + lookup_maxclass = (ZU(1) << lg_base) + + (ZU(ndelta) << lg_delta); + } + if (sc->psz) { + npsizes++; + } + if (sc->bin) { + nbins++; + /* Final written value is correct. */ + small_maxclass = (ZU(1) << lg_base) + + (ZU(ndelta) << lg_delta); + if (lg_ngroup > 0) { + lg_large_minclass = lg_base + 1; + } else { + lg_large_minclass = lg_base + 2; + } + } + large_maxclass = (ZU(1) << lg_base) + + (ZU(ndelta) << lg_delta); + index++; + ndelta++; + } + lg_base++; + lg_delta++; + } + /* Additional outputs. */ + int nsizes = index; + unsigned lg_ceil_nsizes = lg_ceil(nsizes); + + /* Fill in the output data. */ + sc_data->ntiny = ntiny; + sc_data->nlbins = nlbins; + sc_data->nbins = nbins; + sc_data->nsizes = nsizes; + sc_data->lg_ceil_nsizes = lg_ceil_nsizes; + sc_data->npsizes = npsizes; + sc_data->lg_tiny_maxclass = lg_tiny_maxclass; + sc_data->lookup_maxclass = lookup_maxclass; + sc_data->small_maxclass = small_maxclass; + sc_data->lg_large_minclass = lg_large_minclass; + sc_data->large_minclass = (ZU(1) << lg_large_minclass); + sc_data->large_maxclass = large_maxclass; + + /* + * We compute these values in two ways: + * - Incrementally, as above. + * - In macros, in sc.h. + * The computation is easier when done incrementally, but putting it in + * a constant makes it available to the fast paths without having to + * touch the extra global cacheline. We assert, however, that the two + * computations are equivalent. + */ + assert(sc_data->npsizes == SC_NPSIZES); + assert(sc_data->lg_tiny_maxclass == SC_LG_TINY_MAXCLASS); + assert(sc_data->small_maxclass == SC_SMALL_MAXCLASS); + assert(sc_data->large_minclass == SC_LARGE_MINCLASS); + assert(sc_data->lg_large_minclass == SC_LG_LARGE_MINCLASS); + assert(sc_data->large_maxclass == SC_LARGE_MAXCLASS); + + /* + * In the allocation fastpath, we want to assume that we can + * unconditionally subtract the requested allocation size from + * a ssize_t, and detect passing through 0 correctly. This + * results in optimal generated code. For this to work, the + * maximum allocation size must be less than SSIZE_MAX. + */ + assert(SC_LARGE_MAXCLASS < SSIZE_MAX); +} + +void +sc_data_init(sc_data_t *sc_data) { + assert(!sc_data->initialized); + + int lg_max_lookup = 12; + + size_classes(sc_data, LG_SIZEOF_PTR, LG_QUANTUM, SC_LG_TINY_MIN, + lg_max_lookup, LG_PAGE, 2); + + sc_data->initialized = true; +} + +static void +sc_data_update_sc_slab_size(sc_t *sc, size_t reg_size, size_t pgs_guess) { + size_t min_pgs = reg_size / PAGE; + if (reg_size % PAGE != 0) { + min_pgs++; + } + /* + * BITMAP_MAXBITS is actually determined by putting the smallest + * possible size-class on one page, so this can never be 0. + */ + size_t max_pgs = BITMAP_MAXBITS * reg_size / PAGE; + + assert(min_pgs <= max_pgs); + assert(min_pgs > 0); + assert(max_pgs >= 1); + if (pgs_guess < min_pgs) { + sc->pgs = (int)min_pgs; + } else if (pgs_guess > max_pgs) { + sc->pgs = (int)max_pgs; + } else { + sc->pgs = (int)pgs_guess; + } +} + +void +sc_data_update_slab_size(sc_data_t *data, size_t begin, size_t end, int pgs) { + assert(data->initialized); + for (int i = 0; i < data->nsizes; i++) { + sc_t *sc = &data->sc[i]; + if (!sc->bin) { + break; + } + size_t reg_size = reg_size_compute(sc->lg_base, sc->lg_delta, + sc->ndelta); + if (begin <= reg_size && reg_size <= end) { + sc_data_update_sc_slab_size(sc, reg_size, pgs); + } + } +} + +void +sc_boot(sc_data_t *data) { + sc_data_init(data); +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/spin.c b/kbe/src/lib/dependencies/jemalloc/src/spin.c deleted file mode 100755 index 24372c26c9..0000000000 --- a/kbe/src/lib/dependencies/jemalloc/src/spin.c +++ /dev/null @@ -1,4 +0,0 @@ -#define JEMALLOC_SPIN_C_ -#include "jemalloc/internal/jemalloc_preamble.h" - -#include "jemalloc/internal/spin.h" diff --git a/kbe/src/lib/dependencies/jemalloc/src/stats.c b/kbe/src/lib/dependencies/jemalloc/src/stats.c index 087df7676e..4c427e0d35 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/stats.c +++ b/kbe/src/lib/dependencies/jemalloc/src/stats.c @@ -4,6 +4,7 @@ #include "jemalloc/internal/assert.h" #include "jemalloc/internal/ctl.h" +#include "jemalloc/internal/emitter.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/mutex_prof.h" @@ -51,6 +52,20 @@ char opt_stats_print_opts[stats_print_tot_num_options+1] = ""; /******************************************************************************/ +static uint64_t +rate_per_second(uint64_t value, uint64_t uptime_ns) { + uint64_t billion = 1000000000; + if (uptime_ns == 0 || value == 0) { + return 0; + } + if (uptime_ns < billion) { + return value; + } else { + uint64_t uptime_s = uptime_ns / billion; + return value / uptime_s; + } +} + /* Calculate x.yyy and output a string (takes a fixed sized char array). */ static bool get_rate_str(uint64_t dividend, uint64_t divisor, char str[6]) { @@ -84,41 +99,175 @@ gen_mutex_ctl_str(char *str, size_t buf_len, const char *prefix, } static void -read_arena_bin_mutex_stats(unsigned arena_ind, unsigned bin_ind, - uint64_t results[mutex_prof_num_counters]) { +mutex_stats_init_cols(emitter_row_t *row, const char *table_name, + emitter_col_t *name, + emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters], + emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters]) { + mutex_prof_uint64_t_counter_ind_t k_uint64_t = 0; + mutex_prof_uint32_t_counter_ind_t k_uint32_t = 0; + + emitter_col_t *col; + + if (name != NULL) { + emitter_col_init(name, row); + name->justify = emitter_justify_left; + name->width = 21; + name->type = emitter_type_title; + name->str_val = table_name; + } + +#define WIDTH_uint32_t 12 +#define WIDTH_uint64_t 16 +#define OP(counter, counter_type, human, derived, base_counter) \ + col = &col_##counter_type[k_##counter_type]; \ + ++k_##counter_type; \ + emitter_col_init(col, row); \ + col->justify = emitter_justify_right; \ + col->width = derived ? 8 : WIDTH_##counter_type; \ + col->type = emitter_type_title; \ + col->str_val = human; + MUTEX_PROF_COUNTERS +#undef OP +#undef WIDTH_uint32_t +#undef WIDTH_uint64_t + col_uint64_t[mutex_counter_total_wait_time_ps].width = 10; +} + +static void +mutex_stats_read_global(const char *name, emitter_col_t *col_name, + emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters], + emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters], + uint64_t uptime) { + char cmd[MUTEX_CTL_STR_MAX_LENGTH]; + + col_name->str_val = name; + + emitter_col_t *dst; +#define EMITTER_TYPE_uint32_t emitter_type_uint32 +#define EMITTER_TYPE_uint64_t emitter_type_uint64 +#define OP(counter, counter_type, human, derived, base_counter) \ + dst = &col_##counter_type[mutex_counter_##counter]; \ + dst->type = EMITTER_TYPE_##counter_type; \ + if (!derived) { \ + gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ + "mutexes", name, #counter); \ + CTL_GET(cmd, (counter_type *)&dst->bool_val, counter_type); \ + } else { \ + emitter_col_t *base = &col_##counter_type[mutex_counter_##base_counter]; \ + dst->counter_type##_val = rate_per_second(base->counter_type##_val, uptime); \ + } + MUTEX_PROF_COUNTERS +#undef OP +#undef EMITTER_TYPE_uint32_t +#undef EMITTER_TYPE_uint64_t +} + +static void +mutex_stats_read_arena(unsigned arena_ind, mutex_prof_arena_ind_t mutex_ind, + const char *name, emitter_col_t *col_name, + emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters], + emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters], + uint64_t uptime) { char cmd[MUTEX_CTL_STR_MAX_LENGTH]; -#define OP(c, t) \ - gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ - "arenas.0.bins.0","mutex", #c); \ - CTL_M2_M4_GET(cmd, arena_ind, bin_ind, \ - (t *)&results[mutex_counter_##c], t); -MUTEX_PROF_COUNTERS + + col_name->str_val = name; + + emitter_col_t *dst; +#define EMITTER_TYPE_uint32_t emitter_type_uint32 +#define EMITTER_TYPE_uint64_t emitter_type_uint64 +#define OP(counter, counter_type, human, derived, base_counter) \ + dst = &col_##counter_type[mutex_counter_##counter]; \ + dst->type = EMITTER_TYPE_##counter_type; \ + if (!derived) { \ + gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ + "arenas.0.mutexes", arena_mutex_names[mutex_ind], #counter);\ + CTL_M2_GET(cmd, arena_ind, (counter_type *)&dst->bool_val, counter_type); \ + } else { \ + emitter_col_t *base = &col_##counter_type[mutex_counter_##base_counter]; \ + dst->counter_type##_val = rate_per_second(base->counter_type##_val, uptime); \ + } + MUTEX_PROF_COUNTERS #undef OP +#undef EMITTER_TYPE_uint32_t +#undef EMITTER_TYPE_uint64_t } static void -mutex_stats_output_json(void (*write_cb)(void *, const char *), void *cbopaque, - const char *name, uint64_t stats[mutex_prof_num_counters], - const char *json_indent, bool last) { - malloc_cprintf(write_cb, cbopaque, "%s\"%s\": {\n", json_indent, name); - - mutex_prof_counter_ind_t k = 0; - char *fmt_str[2] = {"%s\t\"%s\": %"FMTu32"%s\n", - "%s\t\"%s\": %"FMTu64"%s\n"}; -#define OP(c, t) \ - malloc_cprintf(write_cb, cbopaque, \ - fmt_str[sizeof(t) / sizeof(uint32_t) - 1], \ - json_indent, #c, (t)stats[mutex_counter_##c], \ - (++k == mutex_prof_num_counters) ? "" : ","); -MUTEX_PROF_COUNTERS +mutex_stats_read_arena_bin(unsigned arena_ind, unsigned bin_ind, + emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters], + emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters], + uint64_t uptime) { + char cmd[MUTEX_CTL_STR_MAX_LENGTH]; + emitter_col_t *dst; + +#define EMITTER_TYPE_uint32_t emitter_type_uint32 +#define EMITTER_TYPE_uint64_t emitter_type_uint64 +#define OP(counter, counter_type, human, derived, base_counter) \ + dst = &col_##counter_type[mutex_counter_##counter]; \ + dst->type = EMITTER_TYPE_##counter_type; \ + if (!derived) { \ + gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ + "arenas.0.bins.0","mutex", #counter); \ + CTL_M2_M4_GET(cmd, arena_ind, bin_ind, \ + (counter_type *)&dst->bool_val, counter_type); \ + } else { \ + emitter_col_t *base = &col_##counter_type[mutex_counter_##base_counter]; \ + dst->counter_type##_val = rate_per_second(base->counter_type##_val, uptime); \ + } + MUTEX_PROF_COUNTERS +#undef OP +#undef EMITTER_TYPE_uint32_t +#undef EMITTER_TYPE_uint64_t +} + +/* "row" can be NULL to avoid emitting in table mode. */ +static void +mutex_stats_emit(emitter_t *emitter, emitter_row_t *row, + emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters], + emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters]) { + if (row != NULL) { + emitter_table_row(emitter, row); + } + + mutex_prof_uint64_t_counter_ind_t k_uint64_t = 0; + mutex_prof_uint32_t_counter_ind_t k_uint32_t = 0; + + emitter_col_t *col; + +#define EMITTER_TYPE_uint32_t emitter_type_uint32 +#define EMITTER_TYPE_uint64_t emitter_type_uint64 +#define OP(counter, type, human, derived, base_counter) \ + if (!derived) { \ + col = &col_##type[k_##type]; \ + ++k_##type; \ + emitter_json_kv(emitter, #counter, EMITTER_TYPE_##type, \ + (const void *)&col->bool_val); \ + } + MUTEX_PROF_COUNTERS; #undef OP - malloc_cprintf(write_cb, cbopaque, "%s}%s\n", json_indent, - last ? "" : ","); +#undef EMITTER_TYPE_uint32_t +#undef EMITTER_TYPE_uint64_t } +#define COL(row_name, column_name, left_or_right, col_width, etype) \ + emitter_col_t col_##column_name; \ + emitter_col_init(&col_##column_name, &row_name); \ + col_##column_name.justify = emitter_justify_##left_or_right; \ + col_##column_name.width = col_width; \ + col_##column_name.type = emitter_type_##etype; + +#define COL_HDR(row_name, column_name, human, left_or_right, col_width, etype) \ + COL(row_name, column_name, left_or_right, col_width, etype) \ + emitter_col_t header_##column_name; \ + emitter_col_init(&header_##column_name, &header_##row_name); \ + header_##column_name.justify = emitter_justify_##left_or_right; \ + header_##column_name.width = col_width; \ + header_##column_name.type = emitter_type_title; \ + header_##column_name.str_val = human ? human : #column_name; + + static void -stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, - bool json, bool large, bool mutex, unsigned i) { +stats_arena_bins_print(emitter_t *emitter, bool mutex, unsigned i, uint64_t uptime) { size_t page; bool in_gap, in_gap_prev; unsigned nbins, j; @@ -126,23 +275,69 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, CTL_GET("arenas.page", &page, size_t); CTL_GET("arenas.nbins", &nbins, unsigned); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"bins\": [\n"); - } else { - char *mutex_counters = " n_lock_ops n_waiting" - " n_spin_acq total_wait_ns max_wait_ns\n"; - malloc_cprintf(write_cb, cbopaque, - "bins: size ind allocated nmalloc" - " ndalloc nrequests curregs curslabs regs" - " pgs util nfills nflushes newslabs" - " reslabs%s", mutex ? mutex_counters : "\n"); + + emitter_row_t header_row; + emitter_row_init(&header_row); + + emitter_row_t row; + emitter_row_init(&row); + + COL_HDR(row, size, NULL, right, 20, size) + COL_HDR(row, ind, NULL, right, 4, unsigned) + COL_HDR(row, allocated, NULL, right, 13, uint64) + COL_HDR(row, nmalloc, NULL, right, 13, uint64) + COL_HDR(row, nmalloc_ps, "(#/sec)", right, 8, uint64) + COL_HDR(row, ndalloc, NULL, right, 13, uint64) + COL_HDR(row, ndalloc_ps, "(#/sec)", right, 8, uint64) + COL_HDR(row, nrequests, NULL, right, 13, uint64) + COL_HDR(row, nrequests_ps, "(#/sec)", right, 10, uint64) + COL_HDR(row, nshards, NULL, right, 9, unsigned) + COL_HDR(row, curregs, NULL, right, 13, size) + COL_HDR(row, curslabs, NULL, right, 13, size) + COL_HDR(row, regs, NULL, right, 5, unsigned) + COL_HDR(row, pgs, NULL, right, 4, size) + /* To buffer a right- and left-justified column. */ + COL_HDR(row, justify_spacer, NULL, right, 1, title) + COL_HDR(row, util, NULL, right, 6, title) + COL_HDR(row, nfills, NULL, right, 13, uint64) + COL_HDR(row, nfills_ps, "(#/sec)", right, 8, uint64) + COL_HDR(row, nflushes, NULL, right, 13, uint64) + COL_HDR(row, nflushes_ps, "(#/sec)", right, 8, uint64) + COL_HDR(row, nslabs, NULL, right, 13, uint64) + COL_HDR(row, nreslabs, NULL, right, 13, uint64) + COL_HDR(row, nreslabs_ps, "(#/sec)", right, 8, uint64) + + /* Don't want to actually print the name. */ + header_justify_spacer.str_val = " "; + col_justify_spacer.str_val = " "; + + emitter_col_t col_mutex64[mutex_prof_num_uint64_t_counters]; + emitter_col_t col_mutex32[mutex_prof_num_uint32_t_counters]; + + emitter_col_t header_mutex64[mutex_prof_num_uint64_t_counters]; + emitter_col_t header_mutex32[mutex_prof_num_uint32_t_counters]; + + if (mutex) { + mutex_stats_init_cols(&row, NULL, NULL, col_mutex64, + col_mutex32); + mutex_stats_init_cols(&header_row, NULL, NULL, header_mutex64, + header_mutex32); } + + /* + * We print a "bins:" header as part of the table row; we need to adjust + * the header size column to compensate. + */ + header_size.width -=5; + emitter_table_printf(emitter, "bins:"); + emitter_table_row(emitter, &header_row); + emitter_json_array_kv_begin(emitter, "bins"); + for (j = 0, in_gap = false; j < nbins; j++) { uint64_t nslabs; size_t reg_size, slab_size, curregs; size_t curslabs; - uint32_t nregs; + uint32_t nregs, nshards; uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; uint64_t nreslabs; @@ -151,14 +346,15 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, in_gap_prev = in_gap; in_gap = (nslabs == 0); - if (!json && in_gap_prev && !in_gap) { - malloc_cprintf(write_cb, cbopaque, + if (in_gap_prev && !in_gap) { + emitter_table_printf(emitter, " ---\n"); } CTL_M2_GET("arenas.bin.0.size", j, ®_size, size_t); CTL_M2_GET("arenas.bin.0.nregs", j, &nregs, uint32_t); CTL_M2_GET("arenas.bin.0.slab_size", j, &slab_size, size_t); + CTL_M2_GET("arenas.bin.0.nshards", j, &nshards, uint32_t); CTL_M2_M4_GET("stats.arenas.0.bins.0.nmalloc", i, j, &nmalloc, uint64_t); @@ -177,105 +373,122 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, CTL_M2_M4_GET("stats.arenas.0.bins.0.curslabs", i, j, &curslabs, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t{\n" - "\t\t\t\t\t\t\"nmalloc\": %"FMTu64",\n" - "\t\t\t\t\t\t\"ndalloc\": %"FMTu64",\n" - "\t\t\t\t\t\t\"curregs\": %zu,\n" - "\t\t\t\t\t\t\"nrequests\": %"FMTu64",\n" - "\t\t\t\t\t\t\"nfills\": %"FMTu64",\n" - "\t\t\t\t\t\t\"nflushes\": %"FMTu64",\n" - "\t\t\t\t\t\t\"nreslabs\": %"FMTu64",\n" - "\t\t\t\t\t\t\"curslabs\": %zu%s\n", - nmalloc, ndalloc, curregs, nrequests, nfills, - nflushes, nreslabs, curslabs, mutex ? "," : ""); - if (mutex) { - uint64_t mutex_stats[mutex_prof_num_counters]; - read_arena_bin_mutex_stats(i, j, mutex_stats); - mutex_stats_output_json(write_cb, cbopaque, - "mutex", mutex_stats, "\t\t\t\t\t\t", true); - } - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t}%s\n", - (j + 1 < nbins) ? "," : ""); - } else if (!in_gap) { - size_t availregs = nregs * curslabs; - char util[6]; - if (get_rate_str((uint64_t)curregs, (uint64_t)availregs, - util)) { - if (availregs == 0) { - malloc_snprintf(util, sizeof(util), - "1"); - } else if (curregs > availregs) { - /* - * Race detected: the counters were read - * in separate mallctl calls and - * concurrent operations happened in - * between. In this case no meaningful - * utilization can be computed. - */ - malloc_snprintf(util, sizeof(util), - " race"); - } else { - not_reached(); - } - } - uint64_t mutex_stats[mutex_prof_num_counters]; - if (mutex) { - read_arena_bin_mutex_stats(i, j, mutex_stats); - } + if (mutex) { + mutex_stats_read_arena_bin(i, j, col_mutex64, + col_mutex32, uptime); + } - malloc_cprintf(write_cb, cbopaque, "%20zu %3u %12zu %12" - FMTu64" %12"FMTu64" %12"FMTu64" %12zu %12zu %4u" - " %3zu %-5s %12"FMTu64" %12"FMTu64" %12"FMTu64 - " %12"FMTu64, reg_size, j, curregs * reg_size, - nmalloc, ndalloc, nrequests, curregs, curslabs, - nregs, slab_size / page, util, nfills, nflushes, - nslabs, nreslabs); - - /* Output less info for bin mutexes to save space. */ - if (mutex) { - malloc_cprintf(write_cb, cbopaque, - " %12"FMTu64" %12"FMTu64" %12"FMTu64 - " %14"FMTu64" %12"FMTu64"\n", - mutex_stats[mutex_counter_num_ops], - mutex_stats[mutex_counter_num_wait], - mutex_stats[mutex_counter_num_spin_acq], - mutex_stats[mutex_counter_total_wait_time], - mutex_stats[mutex_counter_max_wait_time]); + emitter_json_object_begin(emitter); + emitter_json_kv(emitter, "nmalloc", emitter_type_uint64, + &nmalloc); + emitter_json_kv(emitter, "ndalloc", emitter_type_uint64, + &ndalloc); + emitter_json_kv(emitter, "curregs", emitter_type_size, + &curregs); + emitter_json_kv(emitter, "nrequests", emitter_type_uint64, + &nrequests); + emitter_json_kv(emitter, "nfills", emitter_type_uint64, + &nfills); + emitter_json_kv(emitter, "nflushes", emitter_type_uint64, + &nflushes); + emitter_json_kv(emitter, "nreslabs", emitter_type_uint64, + &nreslabs); + emitter_json_kv(emitter, "curslabs", emitter_type_size, + &curslabs); + if (mutex) { + emitter_json_object_kv_begin(emitter, "mutex"); + mutex_stats_emit(emitter, NULL, col_mutex64, + col_mutex32); + emitter_json_object_end(emitter); + } + emitter_json_object_end(emitter); + + size_t availregs = nregs * curslabs; + char util[6]; + if (get_rate_str((uint64_t)curregs, (uint64_t)availregs, util)) + { + if (availregs == 0) { + malloc_snprintf(util, sizeof(util), "1"); + } else if (curregs > availregs) { + /* + * Race detected: the counters were read in + * separate mallctl calls and concurrent + * operations happened in between. In this case + * no meaningful utilization can be computed. + */ + malloc_snprintf(util, sizeof(util), " race"); } else { - malloc_cprintf(write_cb, cbopaque, "\n"); + not_reached(); } } + + col_size.size_val = reg_size; + col_ind.unsigned_val = j; + col_allocated.size_val = curregs * reg_size; + col_nmalloc.uint64_val = nmalloc; + col_nmalloc_ps.uint64_val = rate_per_second(nmalloc, uptime); + col_ndalloc.uint64_val = ndalloc; + col_ndalloc_ps.uint64_val = rate_per_second(ndalloc, uptime); + col_nrequests.uint64_val = nrequests; + col_nrequests_ps.uint64_val = rate_per_second(nrequests, uptime); + col_nshards.unsigned_val = nshards; + col_curregs.size_val = curregs; + col_curslabs.size_val = curslabs; + col_regs.unsigned_val = nregs; + col_pgs.size_val = slab_size / page; + col_util.str_val = util; + col_nfills.uint64_val = nfills; + col_nfills_ps.uint64_val = rate_per_second(nfills, uptime); + col_nflushes.uint64_val = nflushes; + col_nflushes_ps.uint64_val = rate_per_second(nflushes, uptime); + col_nslabs.uint64_val = nslabs; + col_nreslabs.uint64_val = nreslabs; + col_nreslabs_ps.uint64_val = rate_per_second(nreslabs, uptime); + + /* + * Note that mutex columns were initialized above, if mutex == + * true. + */ + + emitter_table_row(emitter, &row); } - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t]%s\n", large ? "," : ""); - } else { - if (in_gap) { - malloc_cprintf(write_cb, cbopaque, - " ---\n"); - } + emitter_json_array_end(emitter); /* Close "bins". */ + + if (in_gap) { + emitter_table_printf(emitter, " ---\n"); } } static void -stats_arena_lextents_print(void (*write_cb)(void *, const char *), - void *cbopaque, bool json, unsigned i) { +stats_arena_lextents_print(emitter_t *emitter, unsigned i, uint64_t uptime) { unsigned nbins, nlextents, j; bool in_gap, in_gap_prev; CTL_GET("arenas.nbins", &nbins, unsigned); CTL_GET("arenas.nlextents", &nlextents, unsigned); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"lextents\": [\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - "large: size ind allocated nmalloc" - " ndalloc nrequests curlextents\n"); - } + + emitter_row_t header_row; + emitter_row_init(&header_row); + emitter_row_t row; + emitter_row_init(&row); + + COL_HDR(row, size, NULL, right, 20, size) + COL_HDR(row, ind, NULL, right, 4, unsigned) + COL_HDR(row, allocated, NULL, right, 13, size) + COL_HDR(row, nmalloc, NULL, right, 13, uint64) + COL_HDR(row, nmalloc_ps, "(#/sec)", right, 8, uint64) + COL_HDR(row, ndalloc, NULL, right, 13, uint64) + COL_HDR(row, ndalloc_ps, "(#/sec)", right, 8, uint64) + COL_HDR(row, nrequests, NULL, right, 13, uint64) + COL_HDR(row, nrequests_ps, "(#/sec)", right, 8, uint64) + COL_HDR(row, curlextents, NULL, right, 13, size) + + /* As with bins, we label the large extents table. */ + header_size.width -= 6; + emitter_table_printf(emitter, "large:"); + emitter_table_row(emitter, &header_row); + emitter_json_array_kv_begin(emitter, "lextents"); + for (j = 0, in_gap = false; j < nlextents; j++) { uint64_t nmalloc, ndalloc, nrequests; size_t lextent_size, curlextents; @@ -289,119 +502,162 @@ stats_arena_lextents_print(void (*write_cb)(void *, const char *), in_gap_prev = in_gap; in_gap = (nrequests == 0); - if (!json && in_gap_prev && !in_gap) { - malloc_cprintf(write_cb, cbopaque, + if (in_gap_prev && !in_gap) { + emitter_table_printf(emitter, " ---\n"); } CTL_M2_GET("arenas.lextent.0.size", j, &lextent_size, size_t); CTL_M2_M4_GET("stats.arenas.0.lextents.0.curlextents", i, j, &curlextents, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t{\n" - "\t\t\t\t\t\t\"curlextents\": %zu\n" - "\t\t\t\t\t}%s\n", - curlextents, - (j + 1 < nlextents) ? "," : ""); - } else if (!in_gap) { - malloc_cprintf(write_cb, cbopaque, - "%20zu %3u %12zu %12"FMTu64" %12"FMTu64 - " %12"FMTu64" %12zu\n", - lextent_size, nbins + j, - curlextents * lextent_size, nmalloc, ndalloc, - nrequests, curlextents); + + emitter_json_object_begin(emitter); + emitter_json_kv(emitter, "curlextents", emitter_type_size, + &curlextents); + emitter_json_object_end(emitter); + + col_size.size_val = lextent_size; + col_ind.unsigned_val = nbins + j; + col_allocated.size_val = curlextents * lextent_size; + col_nmalloc.uint64_val = nmalloc; + col_nmalloc_ps.uint64_val = rate_per_second(nmalloc, uptime); + col_ndalloc.uint64_val = ndalloc; + col_ndalloc_ps.uint64_val = rate_per_second(ndalloc, uptime); + col_nrequests.uint64_val = nrequests; + col_nrequests_ps.uint64_val = rate_per_second(nrequests, uptime); + col_curlextents.size_val = curlextents; + + if (!in_gap) { + emitter_table_row(emitter, &row); } } - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t]\n"); - } else { - if (in_gap) { - malloc_cprintf(write_cb, cbopaque, - " ---\n"); - } + emitter_json_array_end(emitter); /* Close "lextents". */ + if (in_gap) { + emitter_table_printf(emitter, " ---\n"); } } static void -read_arena_mutex_stats(unsigned arena_ind, - uint64_t results[mutex_prof_num_arena_mutexes][mutex_prof_num_counters]) { - char cmd[MUTEX_CTL_STR_MAX_LENGTH]; - - mutex_prof_arena_ind_t i; - for (i = 0; i < mutex_prof_num_arena_mutexes; i++) { -#define OP(c, t) \ - gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ - "arenas.0.mutexes", arena_mutex_names[i], #c); \ - CTL_M2_GET(cmd, arena_ind, \ - (t *)&results[i][mutex_counter_##c], t); -MUTEX_PROF_COUNTERS -#undef OP - } -} +stats_arena_extents_print(emitter_t *emitter, unsigned i) { + unsigned j; + bool in_gap, in_gap_prev; + emitter_row_t header_row; + emitter_row_init(&header_row); + emitter_row_t row; + emitter_row_init(&row); + + COL_HDR(row, size, NULL, right, 20, size) + COL_HDR(row, ind, NULL, right, 4, unsigned) + COL_HDR(row, ndirty, NULL, right, 13, size) + COL_HDR(row, dirty, NULL, right, 13, size) + COL_HDR(row, nmuzzy, NULL, right, 13, size) + COL_HDR(row, muzzy, NULL, right, 13, size) + COL_HDR(row, nretained, NULL, right, 13, size) + COL_HDR(row, retained, NULL, right, 13, size) + COL_HDR(row, ntotal, NULL, right, 13, size) + COL_HDR(row, total, NULL, right, 13, size) + + /* Label this section. */ + header_size.width -= 8; + emitter_table_printf(emitter, "extents:"); + emitter_table_row(emitter, &header_row); + emitter_json_array_kv_begin(emitter, "extents"); + + in_gap = false; + for (j = 0; j < SC_NPSIZES; j++) { + size_t ndirty, nmuzzy, nretained, total, dirty_bytes, + muzzy_bytes, retained_bytes, total_bytes; + CTL_M2_M4_GET("stats.arenas.0.extents.0.ndirty", i, j, + &ndirty, size_t); + CTL_M2_M4_GET("stats.arenas.0.extents.0.nmuzzy", i, j, + &nmuzzy, size_t); + CTL_M2_M4_GET("stats.arenas.0.extents.0.nretained", i, j, + &nretained, size_t); + CTL_M2_M4_GET("stats.arenas.0.extents.0.dirty_bytes", i, j, + &dirty_bytes, size_t); + CTL_M2_M4_GET("stats.arenas.0.extents.0.muzzy_bytes", i, j, + &muzzy_bytes, size_t); + CTL_M2_M4_GET("stats.arenas.0.extents.0.retained_bytes", i, j, + &retained_bytes, size_t); + total = ndirty + nmuzzy + nretained; + total_bytes = dirty_bytes + muzzy_bytes + retained_bytes; -static void -mutex_stats_output(void (*write_cb)(void *, const char *), void *cbopaque, - const char *name, uint64_t stats[mutex_prof_num_counters], - bool first_mutex) { - if (first_mutex) { - /* Print title. */ - malloc_cprintf(write_cb, cbopaque, - " n_lock_ops n_waiting" - " n_spin_acq n_owner_switch total_wait_ns" - " max_wait_ns max_n_thds\n"); - } + in_gap_prev = in_gap; + in_gap = (total == 0); - malloc_cprintf(write_cb, cbopaque, "%s", name); - malloc_cprintf(write_cb, cbopaque, ":%*c", - (int)(20 - strlen(name)), ' '); + if (in_gap_prev && !in_gap) { + emitter_table_printf(emitter, + " ---\n"); + } - char *fmt_str[2] = {"%12"FMTu32, "%16"FMTu64}; -#define OP(c, t) \ - malloc_cprintf(write_cb, cbopaque, \ - fmt_str[sizeof(t) / sizeof(uint32_t) - 1], \ - (t)stats[mutex_counter_##c]); -MUTEX_PROF_COUNTERS -#undef OP - malloc_cprintf(write_cb, cbopaque, "\n"); + emitter_json_object_begin(emitter); + emitter_json_kv(emitter, "ndirty", emitter_type_size, &ndirty); + emitter_json_kv(emitter, "nmuzzy", emitter_type_size, &nmuzzy); + emitter_json_kv(emitter, "nretained", emitter_type_size, + &nretained); + + emitter_json_kv(emitter, "dirty_bytes", emitter_type_size, + &dirty_bytes); + emitter_json_kv(emitter, "muzzy_bytes", emitter_type_size, + &muzzy_bytes); + emitter_json_kv(emitter, "retained_bytes", emitter_type_size, + &retained_bytes); + emitter_json_object_end(emitter); + + col_size.size_val = sz_pind2sz(j); + col_ind.size_val = j; + col_ndirty.size_val = ndirty; + col_dirty.size_val = dirty_bytes; + col_nmuzzy.size_val = nmuzzy; + col_muzzy.size_val = muzzy_bytes; + col_nretained.size_val = nretained; + col_retained.size_val = retained_bytes; + col_ntotal.size_val = total; + col_total.size_val = total_bytes; + + if (!in_gap) { + emitter_table_row(emitter, &row); + } + } + emitter_json_array_end(emitter); /* Close "extents". */ + if (in_gap) { + emitter_table_printf(emitter, " ---\n"); + } } static void -stats_arena_mutexes_print(void (*write_cb)(void *, const char *), - void *cbopaque, bool json, bool json_end, unsigned arena_ind) { - uint64_t mutex_stats[mutex_prof_num_arena_mutexes][mutex_prof_num_counters]; - read_arena_mutex_stats(arena_ind, mutex_stats); - - /* Output mutex stats. */ - if (json) { - malloc_cprintf(write_cb, cbopaque, "\t\t\t\t\"mutexes\": {\n"); - mutex_prof_arena_ind_t i, last_mutex; - last_mutex = mutex_prof_num_arena_mutexes - 1; - for (i = 0; i < mutex_prof_num_arena_mutexes; i++) { - mutex_stats_output_json(write_cb, cbopaque, - arena_mutex_names[i], mutex_stats[i], - "\t\t\t\t\t", (i == last_mutex)); - } - malloc_cprintf(write_cb, cbopaque, "\t\t\t\t}%s\n", - json_end ? "" : ","); - } else { - mutex_prof_arena_ind_t i; - for (i = 0; i < mutex_prof_num_arena_mutexes; i++) { - mutex_stats_output(write_cb, cbopaque, - arena_mutex_names[i], mutex_stats[i], i == 0); - } +stats_arena_mutexes_print(emitter_t *emitter, unsigned arena_ind, uint64_t uptime) { + emitter_row_t row; + emitter_col_t col_name; + emitter_col_t col64[mutex_prof_num_uint64_t_counters]; + emitter_col_t col32[mutex_prof_num_uint32_t_counters]; + + emitter_row_init(&row); + mutex_stats_init_cols(&row, "", &col_name, col64, col32); + + emitter_json_object_kv_begin(emitter, "mutexes"); + emitter_table_row(emitter, &row); + + for (mutex_prof_arena_ind_t i = 0; i < mutex_prof_num_arena_mutexes; + i++) { + const char *name = arena_mutex_names[i]; + emitter_json_object_kv_begin(emitter, name); + mutex_stats_read_arena(arena_ind, i, name, &col_name, col64, + col32, uptime); + mutex_stats_emit(emitter, &row, col64, col32); + emitter_json_object_end(emitter); /* Close the mutex dict. */ } + emitter_json_object_end(emitter); /* End "mutexes". */ } static void -stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, - bool json, unsigned i, bool bins, bool large, bool mutex) { +stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large, + bool mutex, bool extents) { unsigned nthreads; const char *dss; ssize_t dirty_decay_ms, muzzy_decay_ms; size_t page, pactive, pdirty, pmuzzy, mapped, retained; - size_t base, internal, resident; + size_t base, internal, resident, metadata_thp, extent_avail; uint64_t dirty_npurge, dirty_nmadvise, dirty_purged; uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged; size_t small_allocated; @@ -414,31 +670,16 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, CTL_GET("arenas.page", &page, size_t); CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"nthreads\": %u,\n", nthreads); - } else { - malloc_cprintf(write_cb, cbopaque, - "assigned threads: %u\n", nthreads); - } + emitter_kv(emitter, "nthreads", "assigned threads", + emitter_type_unsigned, &nthreads); CTL_M2_GET("stats.arenas.0.uptime", i, &uptime, uint64_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"uptime_ns\": %"FMTu64",\n", uptime); - } else { - malloc_cprintf(write_cb, cbopaque, - "uptime: %"FMTu64"\n", uptime); - } + emitter_kv(emitter, "uptime_ns", "uptime", emitter_type_uint64, + &uptime); CTL_M2_GET("stats.arenas.0.dss", i, &dss, const char *); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"dss\": \"%s\",\n", dss); - } else { - malloc_cprintf(write_cb, cbopaque, - "dss allocation precedence: %s\n", dss); - } + emitter_kv(emitter, "dss", "dss allocation precedence", + emitter_type_string, &dss); CTL_M2_GET("stats.arenas.0.dirty_decay_ms", i, &dirty_decay_ms, ssize_t); @@ -455,205 +696,259 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, CTL_M2_GET("stats.arenas.0.muzzy_nmadvise", i, &muzzy_nmadvise, uint64_t); CTL_M2_GET("stats.arenas.0.muzzy_purged", i, &muzzy_purged, uint64_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"dirty_decay_ms\": %zd,\n", dirty_decay_ms); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"muzzy_decay_ms\": %zd,\n", muzzy_decay_ms); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"pactive\": %zu,\n", pactive); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"pdirty\": %zu,\n", pdirty); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"pmuzzy\": %zu,\n", pmuzzy); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"dirty_npurge\": %"FMTu64",\n", dirty_npurge); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"dirty_nmadvise\": %"FMTu64",\n", dirty_nmadvise); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"dirty_purged\": %"FMTu64",\n", dirty_purged); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"muzzy_npurge\": %"FMTu64",\n", muzzy_npurge); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"muzzy_nmadvise\": %"FMTu64",\n", muzzy_nmadvise); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"muzzy_purged\": %"FMTu64",\n", muzzy_purged); - } else { - malloc_cprintf(write_cb, cbopaque, - "decaying: time npages sweeps madvises" - " purged\n"); - if (dirty_decay_ms >= 0) { - malloc_cprintf(write_cb, cbopaque, - " dirty: %5zd %12zu %12"FMTu64" %12"FMTu64" %12" - FMTu64"\n", dirty_decay_ms, pdirty, dirty_npurge, - dirty_nmadvise, dirty_purged); - } else { - malloc_cprintf(write_cb, cbopaque, - " dirty: N/A %12zu %12"FMTu64" %12"FMTu64" %12" - FMTu64"\n", pdirty, dirty_npurge, dirty_nmadvise, - dirty_purged); - } - if (muzzy_decay_ms >= 0) { - malloc_cprintf(write_cb, cbopaque, - " muzzy: %5zd %12zu %12"FMTu64" %12"FMTu64" %12" - FMTu64"\n", muzzy_decay_ms, pmuzzy, muzzy_npurge, - muzzy_nmadvise, muzzy_purged); - } else { - malloc_cprintf(write_cb, cbopaque, - " muzzy: N/A %12zu %12"FMTu64" %12"FMTu64" %12" - FMTu64"\n", pmuzzy, muzzy_npurge, muzzy_nmadvise, - muzzy_purged); - } - } - CTL_M2_GET("stats.arenas.0.small.allocated", i, &small_allocated, - size_t); - CTL_M2_GET("stats.arenas.0.small.nmalloc", i, &small_nmalloc, uint64_t); - CTL_M2_GET("stats.arenas.0.small.ndalloc", i, &small_ndalloc, uint64_t); - CTL_M2_GET("stats.arenas.0.small.nrequests", i, &small_nrequests, - uint64_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"small\": {\n"); - - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"allocated\": %zu,\n", small_allocated); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", small_nmalloc); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", small_ndalloc); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", small_nrequests); - - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t},\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - " allocated nmalloc" - " ndalloc nrequests\n"); - malloc_cprintf(write_cb, cbopaque, - "small: %12zu %12"FMTu64" %12"FMTu64 - " %12"FMTu64"\n", - small_allocated, small_nmalloc, small_ndalloc, - small_nrequests); - } + emitter_row_t decay_row; + emitter_row_init(&decay_row); - CTL_M2_GET("stats.arenas.0.large.allocated", i, &large_allocated, - size_t); - CTL_M2_GET("stats.arenas.0.large.nmalloc", i, &large_nmalloc, uint64_t); - CTL_M2_GET("stats.arenas.0.large.ndalloc", i, &large_ndalloc, uint64_t); - CTL_M2_GET("stats.arenas.0.large.nrequests", i, &large_nrequests, - uint64_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"large\": {\n"); - - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"allocated\": %zu,\n", large_allocated); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", large_nmalloc); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", large_ndalloc); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", large_nrequests); - - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t},\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - "large: %12zu %12"FMTu64" %12"FMTu64 - " %12"FMTu64"\n", - large_allocated, large_nmalloc, large_ndalloc, - large_nrequests); - malloc_cprintf(write_cb, cbopaque, - "total: %12zu %12"FMTu64" %12"FMTu64 - " %12"FMTu64"\n", - small_allocated + large_allocated, small_nmalloc + - large_nmalloc, small_ndalloc + large_ndalloc, - small_nrequests + large_nrequests); - } - if (!json) { - malloc_cprintf(write_cb, cbopaque, - "active: %12zu\n", pactive * page); - } + /* JSON-style emission. */ + emitter_json_kv(emitter, "dirty_decay_ms", emitter_type_ssize, + &dirty_decay_ms); + emitter_json_kv(emitter, "muzzy_decay_ms", emitter_type_ssize, + &muzzy_decay_ms); - CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"mapped\": %zu,\n", mapped); - } else { - malloc_cprintf(write_cb, cbopaque, - "mapped: %12zu\n", mapped); - } + emitter_json_kv(emitter, "pactive", emitter_type_size, &pactive); + emitter_json_kv(emitter, "pdirty", emitter_type_size, &pdirty); + emitter_json_kv(emitter, "pmuzzy", emitter_type_size, &pmuzzy); - CTL_M2_GET("stats.arenas.0.retained", i, &retained, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"retained\": %zu,\n", retained); - } else { - malloc_cprintf(write_cb, cbopaque, - "retained: %12zu\n", retained); - } + emitter_json_kv(emitter, "dirty_npurge", emitter_type_uint64, + &dirty_npurge); + emitter_json_kv(emitter, "dirty_nmadvise", emitter_type_uint64, + &dirty_nmadvise); + emitter_json_kv(emitter, "dirty_purged", emitter_type_uint64, + &dirty_purged); - CTL_M2_GET("stats.arenas.0.base", i, &base, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"base\": %zu,\n", base); - } else { - malloc_cprintf(write_cb, cbopaque, - "base: %12zu\n", base); - } + emitter_json_kv(emitter, "muzzy_npurge", emitter_type_uint64, + &muzzy_npurge); + emitter_json_kv(emitter, "muzzy_nmadvise", emitter_type_uint64, + &muzzy_nmadvise); + emitter_json_kv(emitter, "muzzy_purged", emitter_type_uint64, + &muzzy_purged); - CTL_M2_GET("stats.arenas.0.internal", i, &internal, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"internal\": %zu,\n", internal); - } else { - malloc_cprintf(write_cb, cbopaque, - "internal: %12zu\n", internal); - } + /* Table-style emission. */ + COL(decay_row, decay_type, right, 9, title); + col_decay_type.str_val = "decaying:"; + + COL(decay_row, decay_time, right, 6, title); + col_decay_time.str_val = "time"; + + COL(decay_row, decay_npages, right, 13, title); + col_decay_npages.str_val = "npages"; + + COL(decay_row, decay_sweeps, right, 13, title); + col_decay_sweeps.str_val = "sweeps"; + + COL(decay_row, decay_madvises, right, 13, title); + col_decay_madvises.str_val = "madvises"; + + COL(decay_row, decay_purged, right, 13, title); + col_decay_purged.str_val = "purged"; + + /* Title row. */ + emitter_table_row(emitter, &decay_row); - CTL_M2_GET("stats.arenas.0.tcache_bytes", i, &tcache_bytes, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"tcache\": %zu,\n", tcache_bytes); + /* Dirty row. */ + col_decay_type.str_val = "dirty:"; + + if (dirty_decay_ms >= 0) { + col_decay_time.type = emitter_type_ssize; + col_decay_time.ssize_val = dirty_decay_ms; } else { - malloc_cprintf(write_cb, cbopaque, - "tcache: %12zu\n", tcache_bytes); + col_decay_time.type = emitter_type_title; + col_decay_time.str_val = "N/A"; } - CTL_M2_GET("stats.arenas.0.resident", i, &resident, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"resident\": %zu%s\n", resident, - (bins || large || mutex) ? "," : ""); + col_decay_npages.type = emitter_type_size; + col_decay_npages.size_val = pdirty; + + col_decay_sweeps.type = emitter_type_uint64; + col_decay_sweeps.uint64_val = dirty_npurge; + + col_decay_madvises.type = emitter_type_uint64; + col_decay_madvises.uint64_val = dirty_nmadvise; + + col_decay_purged.type = emitter_type_uint64; + col_decay_purged.uint64_val = dirty_purged; + + emitter_table_row(emitter, &decay_row); + + /* Muzzy row. */ + col_decay_type.str_val = "muzzy:"; + + if (muzzy_decay_ms >= 0) { + col_decay_time.type = emitter_type_ssize; + col_decay_time.ssize_val = muzzy_decay_ms; } else { - malloc_cprintf(write_cb, cbopaque, - "resident: %12zu\n", resident); + col_decay_time.type = emitter_type_title; + col_decay_time.str_val = "N/A"; } + col_decay_npages.type = emitter_type_size; + col_decay_npages.size_val = pmuzzy; + + col_decay_sweeps.type = emitter_type_uint64; + col_decay_sweeps.uint64_val = muzzy_npurge; + + col_decay_madvises.type = emitter_type_uint64; + col_decay_madvises.uint64_val = muzzy_nmadvise; + + col_decay_purged.type = emitter_type_uint64; + col_decay_purged.uint64_val = muzzy_purged; + + emitter_table_row(emitter, &decay_row); + + /* Small / large / total allocation counts. */ + emitter_row_t alloc_count_row; + emitter_row_init(&alloc_count_row); + + COL(alloc_count_row, count_title, left, 21, title); + col_count_title.str_val = ""; + + COL(alloc_count_row, count_allocated, right, 16, title); + col_count_allocated.str_val = "allocated"; + + COL(alloc_count_row, count_nmalloc, right, 16, title); + col_count_nmalloc.str_val = "nmalloc"; + COL(alloc_count_row, count_nmalloc_ps, right, 8, title); + col_count_nmalloc_ps.str_val = "(#/sec)"; + + COL(alloc_count_row, count_ndalloc, right, 16, title); + col_count_ndalloc.str_val = "ndalloc"; + COL(alloc_count_row, count_ndalloc_ps, right, 8, title); + col_count_ndalloc_ps.str_val = "(#/sec)"; + + COL(alloc_count_row, count_nrequests, right, 16, title); + col_count_nrequests.str_val = "nrequests"; + COL(alloc_count_row, count_nrequests_ps, right, 10, title); + col_count_nrequests_ps.str_val = "(#/sec)"; + + emitter_table_row(emitter, &alloc_count_row); + + col_count_nmalloc_ps.type = emitter_type_uint64; + col_count_ndalloc_ps.type = emitter_type_uint64; + col_count_nrequests_ps.type = emitter_type_uint64; + +#define GET_AND_EMIT_ALLOC_STAT(small_or_large, name, valtype) \ + CTL_M2_GET("stats.arenas.0." #small_or_large "." #name, i, \ + &small_or_large##_##name, valtype##_t); \ + emitter_json_kv(emitter, #name, emitter_type_##valtype, \ + &small_or_large##_##name); \ + col_count_##name.type = emitter_type_##valtype; \ + col_count_##name.valtype##_val = small_or_large##_##name; + + emitter_json_object_kv_begin(emitter, "small"); + col_count_title.str_val = "small:"; + + GET_AND_EMIT_ALLOC_STAT(small, allocated, size) + GET_AND_EMIT_ALLOC_STAT(small, nmalloc, uint64) + col_count_nmalloc_ps.uint64_val = + rate_per_second(col_count_nmalloc.uint64_val, uptime); + GET_AND_EMIT_ALLOC_STAT(small, ndalloc, uint64) + col_count_ndalloc_ps.uint64_val = + rate_per_second(col_count_ndalloc.uint64_val, uptime); + GET_AND_EMIT_ALLOC_STAT(small, nrequests, uint64) + col_count_nrequests_ps.uint64_val = + rate_per_second(col_count_nrequests.uint64_val, uptime); + + emitter_table_row(emitter, &alloc_count_row); + emitter_json_object_end(emitter); /* Close "small". */ + + emitter_json_object_kv_begin(emitter, "large"); + col_count_title.str_val = "large:"; + + GET_AND_EMIT_ALLOC_STAT(large, allocated, size) + GET_AND_EMIT_ALLOC_STAT(large, nmalloc, uint64) + col_count_nmalloc_ps.uint64_val = + rate_per_second(col_count_nmalloc.uint64_val, uptime); + GET_AND_EMIT_ALLOC_STAT(large, ndalloc, uint64) + col_count_ndalloc_ps.uint64_val = + rate_per_second(col_count_ndalloc.uint64_val, uptime); + GET_AND_EMIT_ALLOC_STAT(large, nrequests, uint64) + col_count_nrequests_ps.uint64_val = + rate_per_second(col_count_nrequests.uint64_val, uptime); + + emitter_table_row(emitter, &alloc_count_row); + emitter_json_object_end(emitter); /* Close "large". */ + +#undef GET_AND_EMIT_ALLOC_STAT + + /* Aggregated small + large stats are emitter only in table mode. */ + col_count_title.str_val = "total:"; + col_count_allocated.size_val = small_allocated + large_allocated; + col_count_nmalloc.uint64_val = small_nmalloc + large_nmalloc; + col_count_ndalloc.uint64_val = small_ndalloc + large_ndalloc; + col_count_nrequests.uint64_val = small_nrequests + large_nrequests; + col_count_nmalloc_ps.uint64_val = + rate_per_second(col_count_nmalloc.uint64_val, uptime); + col_count_ndalloc_ps.uint64_val = + rate_per_second(col_count_ndalloc.uint64_val, uptime); + col_count_nrequests_ps.uint64_val = + rate_per_second(col_count_nrequests.uint64_val, uptime); + emitter_table_row(emitter, &alloc_count_row); + + emitter_row_t mem_count_row; + emitter_row_init(&mem_count_row); + + emitter_col_t mem_count_title; + emitter_col_init(&mem_count_title, &mem_count_row); + mem_count_title.justify = emitter_justify_left; + mem_count_title.width = 21; + mem_count_title.type = emitter_type_title; + mem_count_title.str_val = ""; + + emitter_col_t mem_count_val; + emitter_col_init(&mem_count_val, &mem_count_row); + mem_count_val.justify = emitter_justify_right; + mem_count_val.width = 16; + mem_count_val.type = emitter_type_title; + mem_count_val.str_val = ""; + + emitter_table_row(emitter, &mem_count_row); + mem_count_val.type = emitter_type_size; + + /* Active count in bytes is emitted only in table mode. */ + mem_count_title.str_val = "active:"; + mem_count_val.size_val = pactive * page; + emitter_table_row(emitter, &mem_count_row); + +#define GET_AND_EMIT_MEM_STAT(stat) \ + CTL_M2_GET("stats.arenas.0."#stat, i, &stat, size_t); \ + emitter_json_kv(emitter, #stat, emitter_type_size, &stat); \ + mem_count_title.str_val = #stat":"; \ + mem_count_val.size_val = stat; \ + emitter_table_row(emitter, &mem_count_row); + + GET_AND_EMIT_MEM_STAT(mapped) + GET_AND_EMIT_MEM_STAT(retained) + GET_AND_EMIT_MEM_STAT(base) + GET_AND_EMIT_MEM_STAT(internal) + GET_AND_EMIT_MEM_STAT(metadata_thp) + GET_AND_EMIT_MEM_STAT(tcache_bytes) + GET_AND_EMIT_MEM_STAT(resident) + GET_AND_EMIT_MEM_STAT(extent_avail) +#undef GET_AND_EMIT_MEM_STAT + if (mutex) { - stats_arena_mutexes_print(write_cb, cbopaque, json, - !(bins || large), i); + stats_arena_mutexes_print(emitter, i, uptime); } if (bins) { - stats_arena_bins_print(write_cb, cbopaque, json, large, mutex, - i); + stats_arena_bins_print(emitter, mutex, i, uptime); } if (large) { - stats_arena_lextents_print(write_cb, cbopaque, json, i); + stats_arena_lextents_print(emitter, i, uptime); + } + if (extents) { + stats_arena_extents_print(emitter, i); } } static void -stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque, - bool json, bool more) { +stats_general_print(emitter_t *emitter) { const char *cpv; - bool bv; + bool bv, bv2; unsigned uv; uint32_t u32v; uint64_t u64v; - ssize_t ssv; + ssize_t ssv, ssv2; size_t sv, bsz, usz, ssz, sssz, cpsz; bsz = sizeof(bool); @@ -663,365 +958,255 @@ stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque, cpsz = sizeof(const char *); CTL_GET("version", &cpv, const char *); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\"version\": \"%s\",\n", cpv); - } else { - malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv); - } + emitter_kv(emitter, "version", "Version", emitter_type_string, &cpv); /* config. */ -#define CONFIG_WRITE_BOOL_JSON(n, c) \ - if (json) { \ - CTL_GET("config."#n, &bv, bool); \ - malloc_cprintf(write_cb, cbopaque, \ - "\t\t\t\""#n"\": %s%s\n", bv ? "true" : "false", \ - (c)); \ + emitter_dict_begin(emitter, "config", "Build-time option settings"); +#define CONFIG_WRITE_BOOL(name) \ + do { \ + CTL_GET("config."#name, &bv, bool); \ + emitter_kv(emitter, #name, "config."#name, \ + emitter_type_bool, &bv); \ + } while (0) + + CONFIG_WRITE_BOOL(cache_oblivious); + CONFIG_WRITE_BOOL(debug); + CONFIG_WRITE_BOOL(fill); + CONFIG_WRITE_BOOL(lazy_lock); + emitter_kv(emitter, "malloc_conf", "config.malloc_conf", + emitter_type_string, &config_malloc_conf); + + CONFIG_WRITE_BOOL(prof); + CONFIG_WRITE_BOOL(prof_libgcc); + CONFIG_WRITE_BOOL(prof_libunwind); + CONFIG_WRITE_BOOL(stats); + CONFIG_WRITE_BOOL(utrace); + CONFIG_WRITE_BOOL(xmalloc); +#undef CONFIG_WRITE_BOOL + emitter_dict_end(emitter); /* Close "config" dict. */ + + /* opt. */ +#define OPT_WRITE(name, var, size, emitter_type) \ + if (je_mallctl("opt."name, (void *)&var, &size, NULL, 0) == \ + 0) { \ + emitter_kv(emitter, name, "opt."name, emitter_type, \ + &var); \ } - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\"config\": {\n"); +#define OPT_WRITE_MUTABLE(name, var1, var2, size, emitter_type, \ + altname) \ + if (je_mallctl("opt."name, (void *)&var1, &size, NULL, 0) == \ + 0 && je_mallctl(altname, (void *)&var2, &size, NULL, 0) \ + == 0) { \ + emitter_kv_note(emitter, name, "opt."name, \ + emitter_type, &var1, altname, emitter_type, \ + &var2); \ } - CONFIG_WRITE_BOOL_JSON(cache_oblivious, ",") +#define OPT_WRITE_BOOL(name) OPT_WRITE(name, bv, bsz, emitter_type_bool) +#define OPT_WRITE_BOOL_MUTABLE(name, altname) \ + OPT_WRITE_MUTABLE(name, bv, bv2, bsz, emitter_type_bool, altname) + +#define OPT_WRITE_UNSIGNED(name) \ + OPT_WRITE(name, uv, usz, emitter_type_unsigned) + +#define OPT_WRITE_SIZE_T(name) \ + OPT_WRITE(name, sv, ssz, emitter_type_size) +#define OPT_WRITE_SSIZE_T(name) \ + OPT_WRITE(name, ssv, sssz, emitter_type_ssize) +#define OPT_WRITE_SSIZE_T_MUTABLE(name, altname) \ + OPT_WRITE_MUTABLE(name, ssv, ssv2, sssz, emitter_type_ssize, \ + altname) + +#define OPT_WRITE_CHAR_P(name) \ + OPT_WRITE(name, cpv, cpsz, emitter_type_string) + + emitter_dict_begin(emitter, "opt", "Run-time option settings"); + + OPT_WRITE_BOOL("abort") + OPT_WRITE_BOOL("abort_conf") + OPT_WRITE_BOOL("retain") + OPT_WRITE_CHAR_P("dss") + OPT_WRITE_UNSIGNED("narenas") + OPT_WRITE_CHAR_P("percpu_arena") + OPT_WRITE_SIZE_T("oversize_threshold") + OPT_WRITE_CHAR_P("metadata_thp") + OPT_WRITE_BOOL_MUTABLE("background_thread", "background_thread") + OPT_WRITE_SSIZE_T_MUTABLE("dirty_decay_ms", "arenas.dirty_decay_ms") + OPT_WRITE_SSIZE_T_MUTABLE("muzzy_decay_ms", "arenas.muzzy_decay_ms") + OPT_WRITE_SIZE_T("lg_extent_max_active_fit") + OPT_WRITE_CHAR_P("junk") + OPT_WRITE_BOOL("zero") + OPT_WRITE_BOOL("utrace") + OPT_WRITE_BOOL("xmalloc") + OPT_WRITE_BOOL("tcache") + OPT_WRITE_SSIZE_T("lg_tcache_max") + OPT_WRITE_CHAR_P("thp") + OPT_WRITE_BOOL("prof") + OPT_WRITE_CHAR_P("prof_prefix") + OPT_WRITE_BOOL_MUTABLE("prof_active", "prof.active") + OPT_WRITE_BOOL_MUTABLE("prof_thread_active_init", + "prof.thread_active_init") + OPT_WRITE_SSIZE_T_MUTABLE("lg_prof_sample", "prof.lg_sample") + OPT_WRITE_BOOL("prof_accum") + OPT_WRITE_SSIZE_T("lg_prof_interval") + OPT_WRITE_BOOL("prof_gdump") + OPT_WRITE_BOOL("prof_final") + OPT_WRITE_BOOL("prof_leak") + OPT_WRITE_BOOL("stats_print") + OPT_WRITE_CHAR_P("stats_print_opts") + + emitter_dict_end(emitter); + +#undef OPT_WRITE +#undef OPT_WRITE_MUTABLE +#undef OPT_WRITE_BOOL +#undef OPT_WRITE_BOOL_MUTABLE +#undef OPT_WRITE_UNSIGNED +#undef OPT_WRITE_SSIZE_T +#undef OPT_WRITE_SSIZE_T_MUTABLE +#undef OPT_WRITE_CHAR_P - CTL_GET("config.debug", &bv, bool); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"debug\": %s,\n", bv ? "true" : "false"); - } else { - malloc_cprintf(write_cb, cbopaque, "Assertions %s\n", - bv ? "enabled" : "disabled"); - } + /* prof. */ + if (config_prof) { + emitter_dict_begin(emitter, "prof", "Profiling settings"); - CONFIG_WRITE_BOOL_JSON(fill, ",") - CONFIG_WRITE_BOOL_JSON(lazy_lock, ",") + CTL_GET("prof.thread_active_init", &bv, bool); + emitter_kv(emitter, "thread_active_init", + "prof.thread_active_init", emitter_type_bool, &bv); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"malloc_conf\": \"%s\",\n", - config_malloc_conf); - } else { - malloc_cprintf(write_cb, cbopaque, - "config.malloc_conf: \"%s\"\n", config_malloc_conf); - } + CTL_GET("prof.active", &bv, bool); + emitter_kv(emitter, "active", "prof.active", emitter_type_bool, + &bv); - CONFIG_WRITE_BOOL_JSON(prof, ",") - CONFIG_WRITE_BOOL_JSON(prof_libgcc, ",") - CONFIG_WRITE_BOOL_JSON(prof_libunwind, ",") - CONFIG_WRITE_BOOL_JSON(stats, ",") - CONFIG_WRITE_BOOL_JSON(thp, ",") - CONFIG_WRITE_BOOL_JSON(utrace, ",") - CONFIG_WRITE_BOOL_JSON(xmalloc, "") - - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t},\n"); - } -#undef CONFIG_WRITE_BOOL_JSON + CTL_GET("prof.gdump", &bv, bool); + emitter_kv(emitter, "gdump", "prof.gdump", emitter_type_bool, + &bv); - /* opt. */ -#define OPT_WRITE_BOOL(n, c) \ - if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0) { \ - if (json) { \ - malloc_cprintf(write_cb, cbopaque, \ - "\t\t\t\""#n"\": %s%s\n", bv ? "true" : \ - "false", (c)); \ - } else { \ - malloc_cprintf(write_cb, cbopaque, \ - " opt."#n": %s\n", bv ? "true" : "false"); \ - } \ - } -#define OPT_WRITE_BOOL_MUTABLE(n, m, c) { \ - bool bv2; \ - if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0 && \ - je_mallctl(#m, (void *)&bv2, &bsz, NULL, 0) == 0) { \ - if (json) { \ - malloc_cprintf(write_cb, cbopaque, \ - "\t\t\t\""#n"\": %s%s\n", bv ? "true" : \ - "false", (c)); \ - } else { \ - malloc_cprintf(write_cb, cbopaque, \ - " opt."#n": %s ("#m": %s)\n", bv ? "true" \ - : "false", bv2 ? "true" : "false"); \ - } \ - } \ -} -#define OPT_WRITE_UNSIGNED(n, c) \ - if (je_mallctl("opt."#n, (void *)&uv, &usz, NULL, 0) == 0) { \ - if (json) { \ - malloc_cprintf(write_cb, cbopaque, \ - "\t\t\t\""#n"\": %u%s\n", uv, (c)); \ - } else { \ - malloc_cprintf(write_cb, cbopaque, \ - " opt."#n": %u\n", uv); \ - } \ - } -#define OPT_WRITE_SSIZE_T(n, c) \ - if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0) { \ - if (json) { \ - malloc_cprintf(write_cb, cbopaque, \ - "\t\t\t\""#n"\": %zd%s\n", ssv, (c)); \ - } else { \ - malloc_cprintf(write_cb, cbopaque, \ - " opt."#n": %zd\n", ssv); \ - } \ - } -#define OPT_WRITE_SSIZE_T_MUTABLE(n, m, c) { \ - ssize_t ssv2; \ - if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0 && \ - je_mallctl(#m, (void *)&ssv2, &sssz, NULL, 0) == 0) { \ - if (json) { \ - malloc_cprintf(write_cb, cbopaque, \ - "\t\t\t\""#n"\": %zd%s\n", ssv, (c)); \ - } else { \ - malloc_cprintf(write_cb, cbopaque, \ - " opt."#n": %zd ("#m": %zd)\n", \ - ssv, ssv2); \ - } \ - } \ -} -#define OPT_WRITE_CHAR_P(n, c) \ - if (je_mallctl("opt."#n, (void *)&cpv, &cpsz, NULL, 0) == 0) { \ - if (json) { \ - malloc_cprintf(write_cb, cbopaque, \ - "\t\t\t\""#n"\": \"%s\"%s\n", cpv, (c)); \ - } else { \ - malloc_cprintf(write_cb, cbopaque, \ - " opt."#n": \"%s\"\n", cpv); \ - } \ - } + CTL_GET("prof.interval", &u64v, uint64_t); + emitter_kv(emitter, "interval", "prof.interval", + emitter_type_uint64, &u64v); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\"opt\": {\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - "Run-time option settings:\n"); - } - OPT_WRITE_BOOL(abort, ",") - OPT_WRITE_BOOL(abort_conf, ",") - OPT_WRITE_BOOL(retain, ",") - OPT_WRITE_CHAR_P(dss, ",") - OPT_WRITE_UNSIGNED(narenas, ",") - OPT_WRITE_CHAR_P(percpu_arena, ",") - OPT_WRITE_BOOL_MUTABLE(background_thread, background_thread, ",") - OPT_WRITE_SSIZE_T_MUTABLE(dirty_decay_ms, arenas.dirty_decay_ms, ",") - OPT_WRITE_SSIZE_T_MUTABLE(muzzy_decay_ms, arenas.muzzy_decay_ms, ",") - OPT_WRITE_CHAR_P(junk, ",") - OPT_WRITE_BOOL(zero, ",") - OPT_WRITE_BOOL(utrace, ",") - OPT_WRITE_BOOL(xmalloc, ",") - OPT_WRITE_BOOL(tcache, ",") - OPT_WRITE_SSIZE_T(lg_tcache_max, ",") - OPT_WRITE_BOOL(prof, ",") - OPT_WRITE_CHAR_P(prof_prefix, ",") - OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active, ",") - OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init, prof.thread_active_init, - ",") - OPT_WRITE_SSIZE_T_MUTABLE(lg_prof_sample, prof.lg_sample, ",") - OPT_WRITE_BOOL(prof_accum, ",") - OPT_WRITE_SSIZE_T(lg_prof_interval, ",") - OPT_WRITE_BOOL(prof_gdump, ",") - OPT_WRITE_BOOL(prof_final, ",") - OPT_WRITE_BOOL(prof_leak, ",") - OPT_WRITE_BOOL(stats_print, ",") - if (json || opt_stats_print) { - /* - * stats_print_opts is always emitted for JSON, so as long as it - * comes last it's safe to unconditionally omit the comma here - * (rather than having to conditionally omit it elsewhere - * depending on configuration). - */ - OPT_WRITE_CHAR_P(stats_print_opts, "") - } - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t},\n"); - } + CTL_GET("prof.lg_sample", &ssv, ssize_t); + emitter_kv(emitter, "lg_sample", "prof.lg_sample", + emitter_type_ssize, &ssv); -#undef OPT_WRITE_BOOL -#undef OPT_WRITE_BOOL_MUTABLE -#undef OPT_WRITE_SSIZE_T -#undef OPT_WRITE_CHAR_P + emitter_dict_end(emitter); /* Close "prof". */ + } /* arenas. */ - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\"arenas\": {\n"); - } + /* + * The json output sticks arena info into an "arenas" dict; the table + * output puts them at the top-level. + */ + emitter_json_object_kv_begin(emitter, "arenas"); CTL_GET("arenas.narenas", &uv, unsigned); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"narenas\": %u,\n", uv); - } else { - malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv); - } + emitter_kv(emitter, "narenas", "Arenas", emitter_type_unsigned, &uv); - if (json) { - CTL_GET("arenas.dirty_decay_ms", &ssv, ssize_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"dirty_decay_ms\": %zd,\n", ssv); + /* + * Decay settings are emitted only in json mode; in table mode, they're + * emitted as notes with the opt output, above. + */ + CTL_GET("arenas.dirty_decay_ms", &ssv, ssize_t); + emitter_json_kv(emitter, "dirty_decay_ms", emitter_type_ssize, &ssv); - CTL_GET("arenas.muzzy_decay_ms", &ssv, ssize_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"muzzy_decay_ms\": %zd,\n", ssv); - } + CTL_GET("arenas.muzzy_decay_ms", &ssv, ssize_t); + emitter_json_kv(emitter, "muzzy_decay_ms", emitter_type_ssize, &ssv); CTL_GET("arenas.quantum", &sv, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"quantum\": %zu,\n", sv); - } else { - malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv); - } + emitter_kv(emitter, "quantum", "Quantum size", emitter_type_size, &sv); CTL_GET("arenas.page", &sv, size_t); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"page\": %zu,\n", sv); - } else { - malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv); - } + emitter_kv(emitter, "page", "Page size", emitter_type_size, &sv); if (je_mallctl("arenas.tcache_max", (void *)&sv, &ssz, NULL, 0) == 0) { - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"tcache_max\": %zu,\n", sv); - } else { - malloc_cprintf(write_cb, cbopaque, - "Maximum thread-cached size class: %zu\n", sv); - } + emitter_kv(emitter, "tcache_max", + "Maximum thread-cached size class", emitter_type_size, &sv); } - if (json) { - unsigned nbins, nlextents, i; - - CTL_GET("arenas.nbins", &nbins, unsigned); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"nbins\": %u,\n", nbins); + unsigned nbins; + CTL_GET("arenas.nbins", &nbins, unsigned); + emitter_kv(emitter, "nbins", "Number of bin size classes", + emitter_type_unsigned, &nbins); - CTL_GET("arenas.nhbins", &uv, unsigned); - malloc_cprintf(write_cb, cbopaque, "\t\t\t\"nhbins\": %u,\n", - uv); + unsigned nhbins; + CTL_GET("arenas.nhbins", &nhbins, unsigned); + emitter_kv(emitter, "nhbins", "Number of thread-cache bin size classes", + emitter_type_unsigned, &nhbins); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"bin\": [\n"); - for (i = 0; i < nbins; i++) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t{\n"); + /* + * We do enough mallctls in a loop that we actually want to omit them + * (not just omit the printing). + */ + if (emitter->output == emitter_output_json) { + emitter_json_array_kv_begin(emitter, "bin"); + for (unsigned i = 0; i < nbins; i++) { + emitter_json_object_begin(emitter); CTL_M2_GET("arenas.bin.0.size", i, &sv, size_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"size\": %zu,\n", sv); + emitter_json_kv(emitter, "size", emitter_type_size, + &sv); CTL_M2_GET("arenas.bin.0.nregs", i, &u32v, uint32_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"nregs\": %"FMTu32",\n", u32v); + emitter_json_kv(emitter, "nregs", emitter_type_uint32, + &u32v); CTL_M2_GET("arenas.bin.0.slab_size", i, &sv, size_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"slab_size\": %zu\n", sv); + emitter_json_kv(emitter, "slab_size", emitter_type_size, + &sv); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t}%s\n", (i + 1 < nbins) ? "," : ""); - } - malloc_cprintf(write_cb, cbopaque, - "\t\t\t],\n"); - - CTL_GET("arenas.nlextents", &nlextents, unsigned); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"nlextents\": %u,\n", nlextents); - - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"lextent\": [\n"); - for (i = 0; i < nlextents; i++) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t{\n"); - - CTL_M2_GET("arenas.lextent.0.size", i, &sv, size_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\t\"size\": %zu\n", sv); + CTL_M2_GET("arenas.bin.0.nshards", i, &u32v, uint32_t); + emitter_json_kv(emitter, "nshards", emitter_type_uint32, + &u32v); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t}%s\n", (i + 1 < nlextents) ? "," : ""); + emitter_json_object_end(emitter); } - malloc_cprintf(write_cb, cbopaque, - "\t\t\t]\n"); - - malloc_cprintf(write_cb, cbopaque, - "\t\t}%s\n", (config_prof || more) ? "," : ""); + emitter_json_array_end(emitter); /* Close "bin". */ } - /* prof. */ - if (config_prof && json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\"prof\": {\n"); - - CTL_GET("prof.thread_active_init", &bv, bool); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"thread_active_init\": %s,\n", bv ? "true" : - "false"); - - CTL_GET("prof.active", &bv, bool); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"active\": %s,\n", bv ? "true" : "false"); - - CTL_GET("prof.gdump", &bv, bool); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"gdump\": %s,\n", bv ? "true" : "false"); + unsigned nlextents; + CTL_GET("arenas.nlextents", &nlextents, unsigned); + emitter_kv(emitter, "nlextents", "Number of large size classes", + emitter_type_unsigned, &nlextents); - CTL_GET("prof.interval", &u64v, uint64_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"interval\": %"FMTu64",\n", u64v); + if (emitter->output == emitter_output_json) { + emitter_json_array_kv_begin(emitter, "lextent"); + for (unsigned i = 0; i < nlextents; i++) { + emitter_json_object_begin(emitter); - CTL_GET("prof.lg_sample", &ssv, ssize_t); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"lg_sample\": %zd\n", ssv); + CTL_M2_GET("arenas.lextent.0.size", i, &sv, size_t); + emitter_json_kv(emitter, "size", emitter_type_size, + &sv); - malloc_cprintf(write_cb, cbopaque, - "\t\t}%s\n", more ? "," : ""); + emitter_json_object_end(emitter); + } + emitter_json_array_end(emitter); /* Close "lextent". */ } -} -static void -read_global_mutex_stats( - uint64_t results[mutex_prof_num_global_mutexes][mutex_prof_num_counters]) { - char cmd[MUTEX_CTL_STR_MAX_LENGTH]; - - mutex_prof_global_ind_t i; - for (i = 0; i < mutex_prof_num_global_mutexes; i++) { -#define OP(c, t) \ - gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ - "mutexes", global_mutex_names[i], #c); \ - CTL_GET(cmd, (t *)&results[i][mutex_counter_##c], t); -MUTEX_PROF_COUNTERS -#undef OP - } + emitter_json_object_end(emitter); /* Close "arenas" */ } static void -stats_print_helper(void (*write_cb)(void *, const char *), void *cbopaque, - bool json, bool merged, bool destroyed, bool unmerged, bool bins, - bool large, bool mutex) { - size_t allocated, active, metadata, resident, mapped, retained; +stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, + bool unmerged, bool bins, bool large, bool mutex, bool extents) { + /* + * These should be deleted. We keep them around for a while, to aid in + * the transition to the emitter code. + */ + size_t allocated, active, metadata, metadata_thp, resident, mapped, + retained; size_t num_background_threads; uint64_t background_thread_num_runs, background_thread_run_interval; CTL_GET("stats.allocated", &allocated, size_t); CTL_GET("stats.active", &active, size_t); CTL_GET("stats.metadata", &metadata, size_t); + CTL_GET("stats.metadata_thp", &metadata_thp, size_t); CTL_GET("stats.resident", &resident, size_t); CTL_GET("stats.mapped", &mapped, size_t); CTL_GET("stats.retained", &retained, size_t); - uint64_t mutex_stats[mutex_prof_num_global_mutexes][mutex_prof_num_counters]; - if (mutex) { - read_global_mutex_stats(mutex_stats); - } - if (have_background_thread) { CTL_GET("stats.background_thread.num_threads", &num_background_threads, size_t); @@ -1035,182 +1220,133 @@ stats_print_helper(void (*write_cb)(void *, const char *), void *cbopaque, background_thread_run_interval = 0; } - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\"stats\": {\n"); - - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"allocated\": %zu,\n", allocated); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"active\": %zu,\n", active); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"metadata\": %zu,\n", metadata); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"resident\": %zu,\n", resident); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"mapped\": %zu,\n", mapped); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"retained\": %zu,\n", retained); - - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"background_thread\": {\n"); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"num_threads\": %zu,\n", num_background_threads); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"num_runs\": %"FMTu64",\n", - background_thread_num_runs); - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\t\"run_interval\": %"FMTu64"\n", - background_thread_run_interval); - malloc_cprintf(write_cb, cbopaque, "\t\t\t}%s\n", - mutex ? "," : ""); + /* Generic global stats. */ + emitter_json_object_kv_begin(emitter, "stats"); + emitter_json_kv(emitter, "allocated", emitter_type_size, &allocated); + emitter_json_kv(emitter, "active", emitter_type_size, &active); + emitter_json_kv(emitter, "metadata", emitter_type_size, &metadata); + emitter_json_kv(emitter, "metadata_thp", emitter_type_size, + &metadata_thp); + emitter_json_kv(emitter, "resident", emitter_type_size, &resident); + emitter_json_kv(emitter, "mapped", emitter_type_size, &mapped); + emitter_json_kv(emitter, "retained", emitter_type_size, &retained); + + emitter_table_printf(emitter, "Allocated: %zu, active: %zu, " + "metadata: %zu (n_thp %zu), resident: %zu, mapped: %zu, " + "retained: %zu\n", allocated, active, metadata, metadata_thp, + resident, mapped, retained); + + /* Background thread stats. */ + emitter_json_object_kv_begin(emitter, "background_thread"); + emitter_json_kv(emitter, "num_threads", emitter_type_size, + &num_background_threads); + emitter_json_kv(emitter, "num_runs", emitter_type_uint64, + &background_thread_num_runs); + emitter_json_kv(emitter, "run_interval", emitter_type_uint64, + &background_thread_run_interval); + emitter_json_object_end(emitter); /* Close "background_thread". */ + + emitter_table_printf(emitter, "Background threads: %zu, " + "num_runs: %"FMTu64", run_interval: %"FMTu64" ns\n", + num_background_threads, background_thread_num_runs, + background_thread_run_interval); - if (mutex) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"mutexes\": {\n"); - mutex_prof_global_ind_t i; - for (i = 0; i < mutex_prof_num_global_mutexes; i++) { - mutex_stats_output_json(write_cb, cbopaque, - global_mutex_names[i], mutex_stats[i], - "\t\t\t\t", - i == mutex_prof_num_global_mutexes - 1); - } - malloc_cprintf(write_cb, cbopaque, "\t\t\t}\n"); - } - malloc_cprintf(write_cb, cbopaque, - "\t\t}%s\n", (merged || unmerged || destroyed) ? "," : ""); - } else { - malloc_cprintf(write_cb, cbopaque, - "Allocated: %zu, active: %zu, metadata: %zu," - " resident: %zu, mapped: %zu, retained: %zu\n", - allocated, active, metadata, resident, mapped, retained); - - if (have_background_thread && num_background_threads > 0) { - malloc_cprintf(write_cb, cbopaque, - "Background threads: %zu, num_runs: %"FMTu64", " - "run_interval: %"FMTu64" ns\n", - num_background_threads, - background_thread_num_runs, - background_thread_run_interval); - } - if (mutex) { - mutex_prof_global_ind_t i; - for (i = 0; i < mutex_prof_num_global_mutexes; i++) { - mutex_stats_output(write_cb, cbopaque, - global_mutex_names[i], mutex_stats[i], - i == 0); - } + if (mutex) { + emitter_row_t row; + emitter_col_t name; + emitter_col_t col64[mutex_prof_num_uint64_t_counters]; + emitter_col_t col32[mutex_prof_num_uint32_t_counters]; + uint64_t uptime; + + emitter_row_init(&row); + mutex_stats_init_cols(&row, "", &name, col64, col32); + + emitter_table_row(emitter, &row); + emitter_json_object_kv_begin(emitter, "mutexes"); + + CTL_M2_GET("stats.arenas.0.uptime", 0, &uptime, uint64_t); + + for (int i = 0; i < mutex_prof_num_global_mutexes; i++) { + mutex_stats_read_global(global_mutex_names[i], &name, + col64, col32, uptime); + emitter_json_object_kv_begin(emitter, global_mutex_names[i]); + mutex_stats_emit(emitter, &row, col64, col32); + emitter_json_object_end(emitter); } + + emitter_json_object_end(emitter); /* Close "mutexes". */ } + emitter_json_object_end(emitter); /* Close "stats". */ + if (merged || destroyed || unmerged) { unsigned narenas; - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\"stats.arenas\": {\n"); - } + emitter_json_object_kv_begin(emitter, "stats.arenas"); CTL_GET("arenas.narenas", &narenas, unsigned); - { - size_t mib[3]; - size_t miblen = sizeof(mib) / sizeof(size_t); - size_t sz; - VARIABLE_ARRAY(bool, initialized, narenas); - bool destroyed_initialized; - unsigned i, j, ninitialized; - - xmallctlnametomib("arena.0.initialized", mib, &miblen); - for (i = ninitialized = 0; i < narenas; i++) { - mib[1] = i; - sz = sizeof(bool); - xmallctlbymib(mib, miblen, &initialized[i], &sz, - NULL, 0); - if (initialized[i]) { - ninitialized++; - } - } - mib[1] = MALLCTL_ARENAS_DESTROYED; + size_t mib[3]; + size_t miblen = sizeof(mib) / sizeof(size_t); + size_t sz; + VARIABLE_ARRAY(bool, initialized, narenas); + bool destroyed_initialized; + unsigned i, j, ninitialized; + + xmallctlnametomib("arena.0.initialized", mib, &miblen); + for (i = ninitialized = 0; i < narenas; i++) { + mib[1] = i; sz = sizeof(bool); - xmallctlbymib(mib, miblen, &destroyed_initialized, &sz, + xmallctlbymib(mib, miblen, &initialized[i], &sz, NULL, 0); - - /* Merged stats. */ - if (merged && (ninitialized > 1 || !unmerged)) { - /* Print merged arena stats. */ - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"merged\": {\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - "\nMerged arenas stats:\n"); - } - stats_arena_print(write_cb, cbopaque, json, - MALLCTL_ARENAS_ALL, bins, large, mutex); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t}%s\n", - ((destroyed_initialized && - destroyed) || unmerged) ? "," : - ""); - } + if (initialized[i]) { + ninitialized++; } + } + mib[1] = MALLCTL_ARENAS_DESTROYED; + sz = sizeof(bool); + xmallctlbymib(mib, miblen, &destroyed_initialized, &sz, + NULL, 0); + + /* Merged stats. */ + if (merged && (ninitialized > 1 || !unmerged)) { + /* Print merged arena stats. */ + emitter_table_printf(emitter, "Merged arenas stats:\n"); + emitter_json_object_kv_begin(emitter, "merged"); + stats_arena_print(emitter, MALLCTL_ARENAS_ALL, bins, + large, mutex, extents); + emitter_json_object_end(emitter); /* Close "merged". */ + } - /* Destroyed stats. */ - if (destroyed_initialized && destroyed) { - /* Print destroyed arena stats. */ - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t\"destroyed\": {\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - "\nDestroyed arenas stats:\n"); - } - stats_arena_print(write_cb, cbopaque, json, - MALLCTL_ARENAS_DESTROYED, bins, large, - mutex); - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t\t}%s\n", unmerged ? "," : - ""); - } - } + /* Destroyed stats. */ + if (destroyed_initialized && destroyed) { + /* Print destroyed arena stats. */ + emitter_table_printf(emitter, + "Destroyed arenas stats:\n"); + emitter_json_object_kv_begin(emitter, "destroyed"); + stats_arena_print(emitter, MALLCTL_ARENAS_DESTROYED, + bins, large, mutex, extents); + emitter_json_object_end(emitter); /* Close "destroyed". */ + } - /* Unmerged stats. */ - if (unmerged) { - for (i = j = 0; i < narenas; i++) { - if (initialized[i]) { - if (json) { - j++; - malloc_cprintf(write_cb, - cbopaque, - "\t\t\t\"%u\": {\n", - i); - } else { - malloc_cprintf(write_cb, - cbopaque, - "\narenas[%u]:\n", - i); - } - stats_arena_print(write_cb, - cbopaque, json, i, bins, - large, mutex); - if (json) { - malloc_cprintf(write_cb, - cbopaque, - "\t\t\t}%s\n", (j < - ninitialized) ? "," - : ""); - } - } + /* Unmerged stats. */ + if (unmerged) { + for (i = j = 0; i < narenas; i++) { + if (initialized[i]) { + char arena_ind_str[20]; + malloc_snprintf(arena_ind_str, + sizeof(arena_ind_str), "%u", i); + emitter_json_object_kv_begin(emitter, + arena_ind_str); + emitter_table_printf(emitter, + "arenas[%s]:\n", arena_ind_str); + stats_arena_print(emitter, i, bins, + large, mutex, extents); + /* Close "". */ + emitter_json_object_end(emitter); } } } - - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t\t}\n"); - } + emitter_json_object_end(emitter); /* Close "stats.arenas". */ } } @@ -1257,29 +1393,23 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, } } - if (json) { - malloc_cprintf(write_cb, cbopaque, - "{\n" - "\t\"jemalloc\": {\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - "___ Begin jemalloc statistics ___\n"); - } + emitter_t emitter; + emitter_init(&emitter, + json ? emitter_output_json : emitter_output_table, write_cb, + cbopaque); + emitter_begin(&emitter); + emitter_table_printf(&emitter, "___ Begin jemalloc statistics ___\n"); + emitter_json_object_kv_begin(&emitter, "jemalloc"); if (general) { - stats_general_print(write_cb, cbopaque, json, config_stats); + stats_general_print(&emitter); } if (config_stats) { - stats_print_helper(write_cb, cbopaque, json, merged, destroyed, - unmerged, bins, large, mutex); + stats_print_helper(&emitter, merged, destroyed, unmerged, + bins, large, mutex, extents); } - if (json) { - malloc_cprintf(write_cb, cbopaque, - "\t}\n" - "}\n"); - } else { - malloc_cprintf(write_cb, cbopaque, - "--- End jemalloc statistics ---\n"); - } + emitter_json_object_end(&emitter); /* Closes the "jemalloc" dict. */ + emitter_table_printf(&emitter, "--- End jemalloc statistics ---\n"); + emitter_end(&emitter); } diff --git a/kbe/src/lib/dependencies/jemalloc/src/sz.c b/kbe/src/lib/dependencies/jemalloc/src/sz.c index 0986615f71..8633fb0500 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/sz.c +++ b/kbe/src/lib/dependencies/jemalloc/src/sz.c @@ -2,105 +2,63 @@ #include "jemalloc/internal/sz.h" JEMALLOC_ALIGNED(CACHELINE) -const size_t sz_pind2sz_tab[NPSIZES+1] = { -#define PSZ_yes(lg_grp, ndelta, lg_delta) \ - (((ZU(1)<sc[i]; + if (sc->psz) { + sz_pind2sz_tab[pind] = (ZU(1) << sc->lg_base) + + (ZU(sc->ndelta) << sc->lg_delta); + pind++; + } + } + for (int i = pind; i <= (int)SC_NPSIZES; i++) { + sz_pind2sz_tab[pind] = sc_data->large_maxclass + PAGE; + } +} JEMALLOC_ALIGNED(CACHELINE) -const size_t sz_index2size_tab[NSIZES] = { -#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup) \ - ((ZU(1)<sc[i]; + sz_index2size_tab[i] = (ZU(1) << sc->lg_base) + + (ZU(sc->ndelta) << (sc->lg_delta)); + } +} +/* + * To keep this table small, we divide sizes by the tiny min size, which gives + * the smallest interval for which the result can change. + */ JEMALLOC_ALIGNED(CACHELINE) -const uint8_t sz_size2index_tab[] = { -#if LG_TINY_MIN == 0 -#warning "Dangerous LG_TINY_MIN" -#define S2B_0(i) i, -#elif LG_TINY_MIN == 1 -#warning "Dangerous LG_TINY_MIN" -#define S2B_1(i) i, -#elif LG_TINY_MIN == 2 -#warning "Dangerous LG_TINY_MIN" -#define S2B_2(i) i, -#elif LG_TINY_MIN == 3 -#define S2B_3(i) i, -#elif LG_TINY_MIN == 4 -#define S2B_4(i) i, -#elif LG_TINY_MIN == 5 -#define S2B_5(i) i, -#elif LG_TINY_MIN == 6 -#define S2B_6(i) i, -#elif LG_TINY_MIN == 7 -#define S2B_7(i) i, -#elif LG_TINY_MIN == 8 -#define S2B_8(i) i, -#elif LG_TINY_MIN == 9 -#define S2B_9(i) i, -#elif LG_TINY_MIN == 10 -#define S2B_10(i) i, -#elif LG_TINY_MIN == 11 -#define S2B_11(i) i, -#else -#error "Unsupported LG_TINY_MIN" -#endif -#if LG_TINY_MIN < 1 -#define S2B_1(i) S2B_0(i) S2B_0(i) -#endif -#if LG_TINY_MIN < 2 -#define S2B_2(i) S2B_1(i) S2B_1(i) -#endif -#if LG_TINY_MIN < 3 -#define S2B_3(i) S2B_2(i) S2B_2(i) -#endif -#if LG_TINY_MIN < 4 -#define S2B_4(i) S2B_3(i) S2B_3(i) -#endif -#if LG_TINY_MIN < 5 -#define S2B_5(i) S2B_4(i) S2B_4(i) -#endif -#if LG_TINY_MIN < 6 -#define S2B_6(i) S2B_5(i) S2B_5(i) -#endif -#if LG_TINY_MIN < 7 -#define S2B_7(i) S2B_6(i) S2B_6(i) -#endif -#if LG_TINY_MIN < 8 -#define S2B_8(i) S2B_7(i) S2B_7(i) -#endif -#if LG_TINY_MIN < 9 -#define S2B_9(i) S2B_8(i) S2B_8(i) -#endif -#if LG_TINY_MIN < 10 -#define S2B_10(i) S2B_9(i) S2B_9(i) -#endif -#if LG_TINY_MIN < 11 -#define S2B_11(i) S2B_10(i) S2B_10(i) -#endif -#define S2B_no(i) -#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup) \ - S2B_##lg_delta_lookup(index) - SIZE_CLASSES -#undef S2B_3 -#undef S2B_4 -#undef S2B_5 -#undef S2B_6 -#undef S2B_7 -#undef S2B_8 -#undef S2B_9 -#undef S2B_10 -#undef S2B_11 -#undef S2B_no -#undef SC -}; +uint8_t sz_size2index_tab[(SC_LOOKUP_MAXCLASS >> SC_LG_TINY_MIN) + 1]; + +static void +sz_boot_size2index_tab(const sc_data_t *sc_data) { + size_t dst_max = (SC_LOOKUP_MAXCLASS >> SC_LG_TINY_MIN) + 1; + size_t dst_ind = 0; + for (unsigned sc_ind = 0; sc_ind < SC_NSIZES && dst_ind < dst_max; + sc_ind++) { + const sc_t *sc = &sc_data->sc[sc_ind]; + size_t sz = (ZU(1) << sc->lg_base) + + (ZU(sc->ndelta) << sc->lg_delta); + size_t max_ind = ((sz + (ZU(1) << SC_LG_TINY_MIN) - 1) + >> SC_LG_TINY_MIN); + for (; dst_ind <= max_ind && dst_ind < dst_max; dst_ind++) { + sz_size2index_tab[dst_ind] = sc_ind; + } + } +} + +void +sz_boot(const sc_data_t *sc_data) { + sz_boot_pind2sz_tab(sc_data); + sz_boot_index2size_tab(sc_data); + sz_boot_size2index_tab(sc_data); +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/tcache.c b/kbe/src/lib/dependencies/jemalloc/src/tcache.c index 936ef3140d..e7b970d904 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/tcache.c +++ b/kbe/src/lib/dependencies/jemalloc/src/tcache.c @@ -4,7 +4,7 @@ #include "jemalloc/internal/assert.h" #include "jemalloc/internal/mutex.h" -#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sc.h" /******************************************************************************/ /* Data. */ @@ -12,7 +12,7 @@ bool opt_tcache = true; ssize_t opt_lg_tcache_max = LG_TCACHE_MAXCLASS_DEFAULT; -tcache_bin_info_t *tcache_bin_info; +cache_bin_info_t *tcache_bin_info; static unsigned stack_nelms; /* Total stack elms per tcache. */ unsigned nhbins; @@ -40,8 +40,8 @@ void tcache_event_hard(tsd_t *tsd, tcache_t *tcache) { szind_t binind = tcache->next_gc_bin; - tcache_bin_t *tbin; - if (binind < NBINS) { + cache_bin_t *tbin; + if (binind < SC_NBINS) { tbin = tcache_small_bin_get(tcache, binind); } else { tbin = tcache_large_bin_get(tcache, binind); @@ -50,7 +50,7 @@ tcache_event_hard(tsd_t *tsd, tcache_t *tcache) { /* * Flush (ceiling) 3/4 of the objects below the low water mark. */ - if (binind < NBINS) { + if (binind < SC_NBINS) { tcache_bin_flush_small(tsd, tcache, tbin, binind, tbin->ncached - tbin->low_water + (tbin->low_water >> 2)); @@ -58,7 +58,7 @@ tcache_event_hard(tsd_t *tsd, tcache_t *tcache) { * Reduce fill count by 2X. Limit lg_fill_div such that * the fill count is always at least 1. */ - tcache_bin_info_t *tbin_info = &tcache_bin_info[binind]; + cache_bin_info_t *tbin_info = &tcache_bin_info[binind]; if ((tbin_info->ncached_max >> (tcache->lg_fill_div[binind] + 1)) >= 1) { tcache->lg_fill_div[binind]++; @@ -72,7 +72,7 @@ tcache_event_hard(tsd_t *tsd, tcache_t *tcache) { * Increase fill count by 2X for small bins. Make sure * lg_fill_div stays greater than 0. */ - if (binind < NBINS && tcache->lg_fill_div[binind] > 1) { + if (binind < SC_NBINS && tcache->lg_fill_div[binind] > 1) { tcache->lg_fill_div[binind]--; } } @@ -86,7 +86,7 @@ tcache_event_hard(tsd_t *tsd, tcache_t *tcache) { void * tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, - tcache_bin_t *tbin, szind_t binind, bool *tcache_success) { + cache_bin_t *tbin, szind_t binind, bool *tcache_success) { void *ret; assert(tcache->arena != NULL); @@ -95,33 +95,73 @@ tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, if (config_prof) { tcache->prof_accumbytes = 0; } - ret = tcache_alloc_easy(tbin, tcache_success); + ret = cache_bin_alloc_easy(tbin, tcache_success); return ret; } +/* Enabled with --enable-extra-size-check. */ +#ifdef JEMALLOC_EXTRA_SIZE_CHECK +static void +tbin_extents_lookup_size_check(tsdn_t *tsdn, cache_bin_t *tbin, szind_t binind, + size_t nflush, extent_t **extents){ + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + /* + * Verify that the items in the tcache all have the correct size; this + * is useful for catching sized deallocation bugs, also to fail early + * instead of corrupting metadata. Since this can be turned on for opt + * builds, avoid the branch in the loop. + */ + szind_t szind; + size_t sz_sum = binind * nflush; + for (unsigned i = 0 ; i < nflush; i++) { + rtree_extent_szind_read(tsdn, &extents_rtree, + rtree_ctx, (uintptr_t)*(tbin->avail - 1 - i), true, + &extents[i], &szind); + sz_sum -= szind; + } + if (sz_sum != 0) { + malloc_printf(": size mismatch in thread cache " + "detected, likely caused by sized deallocation bugs by " + "application. Abort.\n"); + abort(); + } +} +#endif + void -tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, +tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, cache_bin_t *tbin, szind_t binind, unsigned rem) { bool merged_stats = false; - assert(binind < NBINS); - assert(rem <= tbin->ncached); + assert(binind < SC_NBINS); + assert((cache_bin_sz_t)rem <= tbin->ncached); arena_t *arena = tcache->arena; assert(arena != NULL); unsigned nflush = tbin->ncached - rem; VARIABLE_ARRAY(extent_t *, item_extent, nflush); + +#ifndef JEMALLOC_EXTRA_SIZE_CHECK /* Look up extent once per item. */ for (unsigned i = 0 ; i < nflush; i++) { item_extent[i] = iealloc(tsd_tsdn(tsd), *(tbin->avail - 1 - i)); } - +#else + tbin_extents_lookup_size_check(tsd_tsdn(tsd), tbin, binind, nflush, + item_extent); +#endif while (nflush > 0) { /* Lock the arena bin associated with the first object. */ extent_t *extent = item_extent[0]; - arena_t *bin_arena = extent_arena_get(extent); - arena_bin_t *bin = &bin_arena->bins[binind]; + unsigned bin_arena_ind = extent_arena_ind_get(extent); + arena_t *bin_arena = arena_get(tsd_tsdn(tsd), bin_arena_ind, + false); + unsigned binshard = extent_binshard_get(extent); + assert(binshard < bin_infos[binind].n_shards); + bin_t *bin = &bin_arena->bins[binind].bin_shards[binshard]; if (config_prof && bin_arena == arena) { if (arena_prof_accum(tsd_tsdn(tsd), arena, @@ -132,8 +172,7 @@ tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, } malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); - if (config_stats && bin_arena == arena) { - assert(!merged_stats); + if (config_stats && bin_arena == arena && !merged_stats) { merged_stats = true; bin->stats.nflushes++; bin->stats.nrequests += tbin->tstats.nrequests; @@ -145,9 +184,10 @@ tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, extent = item_extent[i]; assert(ptr != NULL && extent != NULL); - if (extent_arena_get(extent) == bin_arena) { + if (extent_arena_ind_get(extent) == bin_arena_ind + && extent_binshard_get(extent) == binshard) { arena_dalloc_bin_junked_locked(tsd_tsdn(tsd), - bin_arena, extent, ptr); + bin_arena, bin, binind, extent, ptr); } else { /* * This object was allocated via a different @@ -169,8 +209,9 @@ tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, * The flush loop didn't happen to flush to this thread's * arena, so the stats didn't get merged. Manually do so now. */ - arena_bin_t *bin = &arena->bins[binind]; - malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + unsigned binshard; + bin_t *bin = arena_bin_choose_lock(tsd_tsdn(tsd), arena, binind, + &binshard); bin->stats.nflushes++; bin->stats.nrequests += tbin->tstats.nrequests; tbin->tstats.nrequests = 0; @@ -180,63 +221,76 @@ tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, memmove(tbin->avail - rem, tbin->avail - tbin->ncached, rem * sizeof(void *)); tbin->ncached = rem; - if ((low_water_t)tbin->ncached < tbin->low_water) { + if (tbin->ncached < tbin->low_water) { tbin->low_water = tbin->ncached; } } void -tcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind, +tcache_bin_flush_large(tsd_t *tsd, cache_bin_t *tbin, szind_t binind, unsigned rem, tcache_t *tcache) { bool merged_stats = false; assert(binind < nhbins); - assert(rem <= tbin->ncached); + assert((cache_bin_sz_t)rem <= tbin->ncached); - arena_t *arena = tcache->arena; - assert(arena != NULL); + arena_t *tcache_arena = tcache->arena; + assert(tcache_arena != NULL); unsigned nflush = tbin->ncached - rem; VARIABLE_ARRAY(extent_t *, item_extent, nflush); + +#ifndef JEMALLOC_EXTRA_SIZE_CHECK /* Look up extent once per item. */ for (unsigned i = 0 ; i < nflush; i++) { item_extent[i] = iealloc(tsd_tsdn(tsd), *(tbin->avail - 1 - i)); } - +#else + tbin_extents_lookup_size_check(tsd_tsdn(tsd), tbin, binind, nflush, + item_extent); +#endif while (nflush > 0) { /* Lock the arena associated with the first object. */ extent_t *extent = item_extent[0]; - arena_t *locked_arena = extent_arena_get(extent); - UNUSED bool idump; + unsigned locked_arena_ind = extent_arena_ind_get(extent); + arena_t *locked_arena = arena_get(tsd_tsdn(tsd), + locked_arena_ind, false); + bool idump; if (config_prof) { idump = false; } - malloc_mutex_lock(tsd_tsdn(tsd), &locked_arena->large_mtx); + bool lock_large = !arena_is_auto(locked_arena); + if (lock_large) { + malloc_mutex_lock(tsd_tsdn(tsd), &locked_arena->large_mtx); + } for (unsigned i = 0; i < nflush; i++) { void *ptr = *(tbin->avail - 1 - i); assert(ptr != NULL); extent = item_extent[i]; - if (extent_arena_get(extent) == locked_arena) { + if (extent_arena_ind_get(extent) == locked_arena_ind) { large_dalloc_prep_junked_locked(tsd_tsdn(tsd), extent); } } - if ((config_prof || config_stats) && locked_arena == arena) { + if ((config_prof || config_stats) && + (locked_arena == tcache_arena)) { if (config_prof) { - idump = arena_prof_accum(tsd_tsdn(tsd), arena, - tcache->prof_accumbytes); + idump = arena_prof_accum(tsd_tsdn(tsd), + tcache_arena, tcache->prof_accumbytes); tcache->prof_accumbytes = 0; } if (config_stats) { merged_stats = true; arena_stats_large_nrequests_add(tsd_tsdn(tsd), - &arena->stats, binind, + &tcache_arena->stats, binind, tbin->tstats.nrequests); tbin->tstats.nrequests = 0; } } - malloc_mutex_unlock(tsd_tsdn(tsd), &locked_arena->large_mtx); + if (lock_large) { + malloc_mutex_unlock(tsd_tsdn(tsd), &locked_arena->large_mtx); + } unsigned ndeferred = 0; for (unsigned i = 0; i < nflush; i++) { @@ -244,7 +298,7 @@ tcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind, extent = item_extent[i]; assert(ptr != NULL && extent != NULL); - if (extent_arena_get(extent) == locked_arena) { + if (extent_arena_ind_get(extent) == locked_arena_ind) { large_dalloc_finish(tsd_tsdn(tsd), extent); } else { /* @@ -270,15 +324,15 @@ tcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind, * The flush loop didn't happen to flush to this thread's * arena, so the stats didn't get merged. Manually do so now. */ - arena_stats_large_nrequests_add(tsd_tsdn(tsd), &arena->stats, - binind, tbin->tstats.nrequests); + arena_stats_large_nrequests_add(tsd_tsdn(tsd), + &tcache_arena->stats, binind, tbin->tstats.nrequests); tbin->tstats.nrequests = 0; } memmove(tbin->avail - rem, tbin->avail - tbin->ncached, rem * sizeof(void *)); tbin->ncached = rem; - if ((low_water_t)tbin->ncached < tbin->low_water) { + if (tbin->ncached < tbin->low_water) { tbin->low_water = tbin->ncached; } } @@ -291,8 +345,15 @@ tcache_arena_associate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena) { if (config_stats) { /* Link into list of extant tcaches. */ malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx); + ql_elm_new(tcache, link); ql_tail_insert(&arena->tcache_ql, tcache, link); + cache_bin_array_descriptor_init( + &tcache->cache_bin_array_descriptor, tcache->bins_small, + tcache->bins_large); + ql_tail_insert(&arena->cache_bin_array_descriptor_ql, + &tcache->cache_bin_array_descriptor, link); + malloc_mutex_unlock(tsdn, &arena->tcache_ql_mtx); } } @@ -316,6 +377,8 @@ tcache_arena_dissociate(tsdn_t *tsdn, tcache_t *tcache) { assert(in_ql); } ql_remove(&arena->tcache_ql, tcache, link); + ql_remove(&arena->cache_bin_array_descriptor_ql, + &tcache->cache_bin_array_descriptor, link); tcache_stats_merge(tsdn, tcache, arena); malloc_mutex_unlock(tsdn, &arena->tcache_ql_mtx); } @@ -354,10 +417,10 @@ tcache_init(tsd_t *tsd, tcache_t *tcache, void *avail_stack) { size_t stack_offset = 0; assert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0); - memset(tcache->tbins_small, 0, sizeof(tcache_bin_t) * NBINS); - memset(tcache->tbins_large, 0, sizeof(tcache_bin_t) * (nhbins - NBINS)); + memset(tcache->bins_small, 0, sizeof(cache_bin_t) * SC_NBINS); + memset(tcache->bins_large, 0, sizeof(cache_bin_t) * (nhbins - SC_NBINS)); unsigned i = 0; - for (; i < NBINS; i++) { + for (; i < SC_NBINS; i++) { tcache->lg_fill_div[i] = 1; stack_offset += tcache_bin_info[i].ncached_max * sizeof(void *); /* @@ -449,16 +512,16 @@ static void tcache_flush_cache(tsd_t *tsd, tcache_t *tcache) { assert(tcache->arena != NULL); - for (unsigned i = 0; i < NBINS; i++) { - tcache_bin_t *tbin = tcache_small_bin_get(tcache, i); + for (unsigned i = 0; i < SC_NBINS; i++) { + cache_bin_t *tbin = tcache_small_bin_get(tcache, i); tcache_bin_flush_small(tsd, tcache, tbin, i, 0); if (config_stats) { assert(tbin->tstats.nrequests == 0); } } - for (unsigned i = NBINS; i < nhbins; i++) { - tcache_bin_t *tbin = tcache_large_bin_get(tcache, i); + for (unsigned i = SC_NBINS; i < nhbins; i++) { + cache_bin_t *tbin = tcache_large_bin_get(tcache, i); tcache_bin_flush_large(tsd, tbin, i, 0, tcache); if (config_stats) { @@ -482,6 +545,7 @@ tcache_flush(tsd_t *tsd) { static void tcache_destroy(tsd_t *tsd, tcache_t *tcache, bool tsd_tcache) { tcache_flush_cache(tsd, tcache); + arena_t *arena = tcache->arena; tcache_arena_dissociate(tsd_tsdn(tsd), tcache); if (tsd_tcache) { @@ -494,6 +558,23 @@ tcache_destroy(tsd_t *tsd, tcache_t *tcache, bool tsd_tcache) { /* Release both the tcache struct and avail array. */ idalloctm(tsd_tsdn(tsd), tcache, NULL, NULL, true, true); } + + /* + * The deallocation and tcache flush above may not trigger decay since + * we are on the tcache shutdown path (potentially with non-nominal + * tsd). Manually trigger decay to avoid pathological cases. Also + * include arena 0 because the tcache array is allocated from it. + */ + arena_decay(tsd_tsdn(tsd), arena_get(tsd_tsdn(tsd), 0, false), + false, false); + + if (arena_nthreads_get(arena, false) == 0 && + !background_thread_enabled()) { + /* Force purging when no threads assigned to the arena anymore. */ + arena_decay(tsd_tsdn(tsd), arena, false, true); + } else { + arena_decay(tsd_tsdn(tsd), arena, false, false); + } } /* For auto tcache (embedded in TSD) only. */ @@ -523,17 +604,17 @@ tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena) { cassert(config_stats); /* Merge and reset tcache stats. */ - for (i = 0; i < NBINS; i++) { - arena_bin_t *bin = &arena->bins[i]; - tcache_bin_t *tbin = tcache_small_bin_get(tcache, i); - malloc_mutex_lock(tsdn, &bin->lock); + for (i = 0; i < SC_NBINS; i++) { + cache_bin_t *tbin = tcache_small_bin_get(tcache, i); + unsigned binshard; + bin_t *bin = arena_bin_choose_lock(tsdn, arena, i, &binshard); bin->stats.nrequests += tbin->tstats.nrequests; malloc_mutex_unlock(tsdn, &bin->lock); tbin->tstats.nrequests = 0; } for (; i < nhbins; i++) { - tcache_bin_t *tbin = tcache_large_bin_get(tcache, i); + cache_bin_t *tbin = tcache_large_bin_get(tcache, i); arena_stats_large_nrequests_add(tsdn, &arena->stats, i, tbin->tstats.nrequests); tbin->tstats.nrequests = 0; @@ -605,23 +686,32 @@ tcaches_create(tsd_t *tsd, unsigned *r_ind) { } static tcache_t * -tcaches_elm_remove(tsd_t *tsd, tcaches_t *elm) { +tcaches_elm_remove(tsd_t *tsd, tcaches_t *elm, bool allow_reinit) { malloc_mutex_assert_owner(tsd_tsdn(tsd), &tcaches_mtx); if (elm->tcache == NULL) { return NULL; } tcache_t *tcache = elm->tcache; - elm->tcache = NULL; + if (allow_reinit) { + elm->tcache = TCACHES_ELM_NEED_REINIT; + } else { + elm->tcache = NULL; + } + + if (tcache == TCACHES_ELM_NEED_REINIT) { + return NULL; + } return tcache; } void tcaches_flush(tsd_t *tsd, unsigned ind) { malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); - tcache_t *tcache = tcaches_elm_remove(tsd, &tcaches[ind]); + tcache_t *tcache = tcaches_elm_remove(tsd, &tcaches[ind], true); malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); if (tcache != NULL) { + /* Destroy the tcache; recreate in tcaches_get() if needed. */ tcache_destroy(tsd, tcache, false); } } @@ -630,7 +720,7 @@ void tcaches_destroy(tsd_t *tsd, unsigned ind) { malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); tcaches_t *elm = &tcaches[ind]; - tcache_t *tcache = tcaches_elm_remove(tsd, elm); + tcache_t *tcache = tcaches_elm_remove(tsd, elm, false); elm->next = tcaches_avail; tcaches_avail = elm; malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); @@ -643,8 +733,8 @@ bool tcache_boot(tsdn_t *tsdn) { /* If necessary, clamp opt_lg_tcache_max. */ if (opt_lg_tcache_max < 0 || (ZU(1) << opt_lg_tcache_max) < - SMALL_MAXCLASS) { - tcache_maxclass = SMALL_MAXCLASS; + SC_SMALL_MAXCLASS) { + tcache_maxclass = SC_SMALL_MAXCLASS; } else { tcache_maxclass = (ZU(1) << opt_lg_tcache_max); } @@ -657,21 +747,21 @@ tcache_boot(tsdn_t *tsdn) { nhbins = sz_size2index(tcache_maxclass) + 1; /* Initialize tcache_bin_info. */ - tcache_bin_info = (tcache_bin_info_t *)base_alloc(tsdn, b0get(), nhbins - * sizeof(tcache_bin_info_t), CACHELINE); + tcache_bin_info = (cache_bin_info_t *)base_alloc(tsdn, b0get(), nhbins + * sizeof(cache_bin_info_t), CACHELINE); if (tcache_bin_info == NULL) { return true; } stack_nelms = 0; unsigned i; - for (i = 0; i < NBINS; i++) { - if ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MIN) { + for (i = 0; i < SC_NBINS; i++) { + if ((bin_infos[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MIN) { tcache_bin_info[i].ncached_max = TCACHE_NSLOTS_SMALL_MIN; - } else if ((arena_bin_info[i].nregs << 1) <= + } else if ((bin_infos[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MAX) { tcache_bin_info[i].ncached_max = - (arena_bin_info[i].nregs << 1); + (bin_infos[i].nregs << 1); } else { tcache_bin_info[i].ncached_max = TCACHE_NSLOTS_SMALL_MAX; diff --git a/kbe/src/lib/dependencies/jemalloc/src/hooks.c b/kbe/src/lib/dependencies/jemalloc/src/test_hooks.c old mode 100755 new mode 100644 similarity index 79% rename from kbe/src/lib/dependencies/jemalloc/src/hooks.c rename to kbe/src/lib/dependencies/jemalloc/src/test_hooks.c index 6266ecd47f..ace00d9c46 --- a/kbe/src/lib/dependencies/jemalloc/src/hooks.c +++ b/kbe/src/lib/dependencies/jemalloc/src/test_hooks.c @@ -6,7 +6,7 @@ * from outside the generated library, so that we can use them in test code. */ JEMALLOC_EXPORT -void (*hooks_arena_new_hook)() = NULL; +void (*test_hooks_arena_new_hook)() = NULL; JEMALLOC_EXPORT -void (*hooks_libc_hook)() = NULL; +void (*test_hooks_libc_hook)() = NULL; diff --git a/kbe/src/lib/dependencies/jemalloc/src/tsd.c b/kbe/src/lib/dependencies/jemalloc/src/tsd.c index f968992f2b..d5fb4d6f82 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/tsd.c +++ b/kbe/src/lib/dependencies/jemalloc/src/tsd.c @@ -12,6 +12,10 @@ static unsigned ncleanups; static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX]; +/* TSD_INITIALIZER triggers "-Wmissing-field-initializer" */ +JEMALLOC_DIAGNOSTIC_PUSH +JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS + #ifdef JEMALLOC_MALLOC_THREAD_CLEANUP __thread tsd_t JEMALLOC_TLS_MODEL tsd_tls = TSD_INITIALIZER; __thread bool JEMALLOC_TLS_MODEL tsd_initialized = false; @@ -41,6 +45,7 @@ tsd_init_head_t tsd_init_head = { ql_head_initializer(blocks), MALLOC_MUTEX_INITIALIZER }; + tsd_wrapper_t tsd_boot_wrapper = { false, TSD_INITIALIZER @@ -48,17 +53,164 @@ tsd_wrapper_t tsd_boot_wrapper = { bool tsd_booted = false; #endif +JEMALLOC_DIAGNOSTIC_POP /******************************************************************************/ +/* A list of all the tsds in the nominal state. */ +typedef ql_head(tsd_t) tsd_list_t; +static tsd_list_t tsd_nominal_tsds = ql_head_initializer(tsd_nominal_tsds); +static malloc_mutex_t tsd_nominal_tsds_lock; + +/* How many slow-path-enabling features are turned on. */ +static atomic_u32_t tsd_global_slow_count = ATOMIC_INIT(0); + +static bool +tsd_in_nominal_list(tsd_t *tsd) { + tsd_t *tsd_list; + bool found = false; + /* + * We don't know that tsd is nominal; it might not be safe to get data + * out of it here. + */ + malloc_mutex_lock(TSDN_NULL, &tsd_nominal_tsds_lock); + ql_foreach(tsd_list, &tsd_nominal_tsds, TSD_MANGLE(tcache).tsd_link) { + if (tsd == tsd_list) { + found = true; + break; + } + } + malloc_mutex_unlock(TSDN_NULL, &tsd_nominal_tsds_lock); + return found; +} + +static void +tsd_add_nominal(tsd_t *tsd) { + assert(!tsd_in_nominal_list(tsd)); + assert(tsd_state_get(tsd) <= tsd_state_nominal_max); + ql_elm_new(tsd, TSD_MANGLE(tcache).tsd_link); + malloc_mutex_lock(tsd_tsdn(tsd), &tsd_nominal_tsds_lock); + ql_tail_insert(&tsd_nominal_tsds, tsd, TSD_MANGLE(tcache).tsd_link); + malloc_mutex_unlock(tsd_tsdn(tsd), &tsd_nominal_tsds_lock); +} + +static void +tsd_remove_nominal(tsd_t *tsd) { + assert(tsd_in_nominal_list(tsd)); + assert(tsd_state_get(tsd) <= tsd_state_nominal_max); + malloc_mutex_lock(tsd_tsdn(tsd), &tsd_nominal_tsds_lock); + ql_remove(&tsd_nominal_tsds, tsd, TSD_MANGLE(tcache).tsd_link); + malloc_mutex_unlock(tsd_tsdn(tsd), &tsd_nominal_tsds_lock); +} + +static void +tsd_force_recompute(tsdn_t *tsdn) { + /* + * The stores to tsd->state here need to synchronize with the exchange + * in tsd_slow_update. + */ + atomic_fence(ATOMIC_RELEASE); + malloc_mutex_lock(tsdn, &tsd_nominal_tsds_lock); + tsd_t *remote_tsd; + ql_foreach(remote_tsd, &tsd_nominal_tsds, TSD_MANGLE(tcache).tsd_link) { + assert(tsd_atomic_load(&remote_tsd->state, ATOMIC_RELAXED) + <= tsd_state_nominal_max); + tsd_atomic_store(&remote_tsd->state, tsd_state_nominal_recompute, + ATOMIC_RELAXED); + } + malloc_mutex_unlock(tsdn, &tsd_nominal_tsds_lock); +} + +void +tsd_global_slow_inc(tsdn_t *tsdn) { + atomic_fetch_add_u32(&tsd_global_slow_count, 1, ATOMIC_RELAXED); + /* + * We unconditionally force a recompute, even if the global slow count + * was already positive. If we didn't, then it would be possible for us + * to return to the user, have the user synchronize externally with some + * other thread, and then have that other thread not have picked up the + * update yet (since the original incrementing thread might still be + * making its way through the tsd list). + */ + tsd_force_recompute(tsdn); +} + +void tsd_global_slow_dec(tsdn_t *tsdn) { + atomic_fetch_sub_u32(&tsd_global_slow_count, 1, ATOMIC_RELAXED); + /* See the note in ..._inc(). */ + tsd_force_recompute(tsdn); +} + +static bool +tsd_local_slow(tsd_t *tsd) { + return !tsd_tcache_enabled_get(tsd) + || tsd_reentrancy_level_get(tsd) > 0; +} + +bool +tsd_global_slow() { + return atomic_load_u32(&tsd_global_slow_count, ATOMIC_RELAXED) > 0; +} + +/******************************************************************************/ + +static uint8_t +tsd_state_compute(tsd_t *tsd) { + if (!tsd_nominal(tsd)) { + return tsd_state_get(tsd); + } + /* We're in *a* nominal state; but which one? */ + if (malloc_slow || tsd_local_slow(tsd) || tsd_global_slow()) { + return tsd_state_nominal_slow; + } else { + return tsd_state_nominal; + } +} + void tsd_slow_update(tsd_t *tsd) { - if (tsd_nominal(tsd)) { - if (malloc_slow || !tsd_tcache_enabled_get(tsd) || - tsd_reentrancy_level_get(tsd) > 0) { - tsd->state = tsd_state_nominal_slow; + uint8_t old_state; + do { + uint8_t new_state = tsd_state_compute(tsd); + old_state = tsd_atomic_exchange(&tsd->state, new_state, + ATOMIC_ACQUIRE); + } while (old_state == tsd_state_nominal_recompute); +} + +void +tsd_state_set(tsd_t *tsd, uint8_t new_state) { + /* Only the tsd module can change the state *to* recompute. */ + assert(new_state != tsd_state_nominal_recompute); + uint8_t old_state = tsd_atomic_load(&tsd->state, ATOMIC_RELAXED); + if (old_state > tsd_state_nominal_max) { + /* + * Not currently in the nominal list, but it might need to be + * inserted there. + */ + assert(!tsd_in_nominal_list(tsd)); + tsd_atomic_store(&tsd->state, new_state, ATOMIC_RELAXED); + if (new_state <= tsd_state_nominal_max) { + tsd_add_nominal(tsd); + } + } else { + /* + * We're currently nominal. If the new state is non-nominal, + * great; we take ourselves off the list and just enter the new + * state. + */ + assert(tsd_in_nominal_list(tsd)); + if (new_state > tsd_state_nominal_max) { + tsd_remove_nominal(tsd); + tsd_atomic_store(&tsd->state, new_state, + ATOMIC_RELAXED); } else { - tsd->state = tsd_state_nominal; + /* + * This is the tricky case. We're transitioning from + * one nominal state to another. The caller can't know + * about any races that are occuring at the same time, + * so we always have to recompute no matter what. + */ + tsd_slow_update(tsd); } } } @@ -71,12 +223,23 @@ tsd_data_init(tsd_t *tsd) { */ rtree_ctx_data_init(tsd_rtree_ctxp_get_unsafe(tsd)); + /* + * A nondeterministic seed based on the address of tsd reduces + * the likelihood of lockstep non-uniform cache index + * utilization among identical concurrent processes, but at the + * cost of test repeatability. For debug builds, instead use a + * deterministic seed. + */ + *tsd_offset_statep_get(tsd) = config_debug ? 0 : + (uint64_t)(uintptr_t)tsd; + return tsd_tcache_enabled_data_init(tsd); } static void assert_tsd_data_cleanup_done(tsd_t *tsd) { assert(!tsd_nominal(tsd)); + assert(!tsd_in_nominal_list(tsd)); assert(*tsd_arenap_get_unsafe(tsd) == NULL); assert(*tsd_iarenap_get_unsafe(tsd) == NULL); assert(*tsd_arenas_tdata_bypassp_get_unsafe(tsd) == true); @@ -87,8 +250,8 @@ assert_tsd_data_cleanup_done(tsd_t *tsd) { static bool tsd_data_init_nocleanup(tsd_t *tsd) { - assert(tsd->state == tsd_state_reincarnated || - tsd->state == tsd_state_minimal_initialized); + assert(tsd_state_get(tsd) == tsd_state_reincarnated || + tsd_state_get(tsd) == tsd_state_minimal_initialized); /* * During reincarnation, there is no guarantee that the cleanup function * will be called (deallocation may happen after all tsd destructors). @@ -107,27 +270,33 @@ tsd_t * tsd_fetch_slow(tsd_t *tsd, bool minimal) { assert(!tsd_fast(tsd)); - if (tsd->state == tsd_state_nominal_slow) { - /* On slow path but no work needed. */ - assert(malloc_slow || !tsd_tcache_enabled_get(tsd) || - tsd_reentrancy_level_get(tsd) > 0 || - *tsd_arenas_tdata_bypassp_get(tsd)); - } else if (tsd->state == tsd_state_uninitialized) { + if (tsd_state_get(tsd) == tsd_state_nominal_slow) { + /* + * On slow path but no work needed. Note that we can't + * necessarily *assert* that we're slow, because we might be + * slow because of an asynchronous modification to global state, + * which might be asynchronously modified *back*. + */ + } else if (tsd_state_get(tsd) == tsd_state_nominal_recompute) { + tsd_slow_update(tsd); + } else if (tsd_state_get(tsd) == tsd_state_uninitialized) { if (!minimal) { - tsd->state = tsd_state_nominal; - tsd_slow_update(tsd); - /* Trigger cleanup handler registration. */ - tsd_set(tsd); - tsd_data_init(tsd); + if (tsd_booted) { + tsd_state_set(tsd, tsd_state_nominal); + tsd_slow_update(tsd); + /* Trigger cleanup handler registration. */ + tsd_set(tsd); + tsd_data_init(tsd); + } } else { - tsd->state = tsd_state_minimal_initialized; + tsd_state_set(tsd, tsd_state_minimal_initialized); tsd_set(tsd); tsd_data_init_nocleanup(tsd); } - } else if (tsd->state == tsd_state_minimal_initialized) { + } else if (tsd_state_get(tsd) == tsd_state_minimal_initialized) { if (!minimal) { /* Switch to fully initialized. */ - tsd->state = tsd_state_nominal; + tsd_state_set(tsd, tsd_state_nominal); assert(*tsd_reentrancy_levelp_get(tsd) >= 1); (*tsd_reentrancy_levelp_get(tsd))--; tsd_slow_update(tsd); @@ -135,12 +304,12 @@ tsd_fetch_slow(tsd_t *tsd, bool minimal) { } else { assert_tsd_data_cleanup_done(tsd); } - } else if (tsd->state == tsd_state_purgatory) { - tsd->state = tsd_state_reincarnated; + } else if (tsd_state_get(tsd) == tsd_state_purgatory) { + tsd_state_set(tsd, tsd_state_reincarnated); tsd_set(tsd); tsd_data_init_nocleanup(tsd); } else { - assert(tsd->state == tsd_state_reincarnated); + assert(tsd_state_get(tsd) == tsd_state_reincarnated); } return tsd; @@ -204,7 +373,7 @@ void tsd_cleanup(void *arg) { tsd_t *tsd = (tsd_t *)arg; - switch (tsd->state) { + switch (tsd_state_get(tsd)) { case tsd_state_uninitialized: /* Do nothing. */ break; @@ -222,7 +391,7 @@ tsd_cleanup(void *arg) { case tsd_state_nominal: case tsd_state_nominal_slow: tsd_do_data_cleanup(tsd); - tsd->state = tsd_state_purgatory; + tsd_state_set(tsd, tsd_state_purgatory); tsd_set(tsd); break; case tsd_state_purgatory: @@ -250,6 +419,10 @@ malloc_tsd_boot0(void) { tsd_t *tsd; ncleanups = 0; + if (malloc_mutex_init(&tsd_nominal_tsds_lock, "tsd_nominal_tsds_lock", + WITNESS_RANK_OMIT, malloc_mutex_rank_exclusive)) { + return NULL; + } if (tsd_boot0()) { return NULL; } @@ -300,7 +473,7 @@ _tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { # pragma comment(linker, "/INCLUDE:_tls_callback") # else # pragma comment(linker, "/INCLUDE:_tls_used") -# pragma comment(linker, "/INCLUDE:tls_callback") +# pragma comment(linker, "/INCLUDE:" STRINGIFY(tls_callback) ) # endif # pragma section(".CRT$XLY",long,read) #endif @@ -339,3 +512,23 @@ tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block) { malloc_mutex_unlock(TSDN_NULL, &head->lock); } #endif + +void +tsd_prefork(tsd_t *tsd) { + malloc_mutex_prefork(tsd_tsdn(tsd), &tsd_nominal_tsds_lock); +} + +void +tsd_postfork_parent(tsd_t *tsd) { + malloc_mutex_postfork_parent(tsd_tsdn(tsd), &tsd_nominal_tsds_lock); +} + +void +tsd_postfork_child(tsd_t *tsd) { + malloc_mutex_postfork_child(tsd_tsdn(tsd), &tsd_nominal_tsds_lock); + ql_new(&tsd_nominal_tsds); + + if (tsd_state_get(tsd) <= tsd_state_nominal_max) { + tsd_add_nominal(tsd); + } +} diff --git a/kbe/src/lib/dependencies/jemalloc/src/zone.c b/kbe/src/lib/dependencies/jemalloc/src/zone.c index 9d3b7b4952..23dfdd04a9 100755 --- a/kbe/src/lib/dependencies/jemalloc/src/zone.c +++ b/kbe/src/lib/dependencies/jemalloc/src/zone.c @@ -89,6 +89,7 @@ JEMALLOC_ATTR(weak_import); static malloc_zone_t *default_zone, *purgeable_zone; static malloc_zone_t jemalloc_zone; static struct malloc_introspection_t jemalloc_zone_introspect; +static pid_t zone_force_lock_pid = -1; /******************************************************************************/ /* Function prototypes for non-inline static functions. */ @@ -270,6 +271,12 @@ zone_log(malloc_zone_t *zone, void *address) { static void zone_force_lock(malloc_zone_t *zone) { if (isthreaded) { + /* + * See the note in zone_force_unlock, below, to see why we need + * this. + */ + assert(zone_force_lock_pid == -1); + zone_force_lock_pid = getpid(); jemalloc_prefork(); } } @@ -277,14 +284,25 @@ zone_force_lock(malloc_zone_t *zone) { static void zone_force_unlock(malloc_zone_t *zone) { /* - * Call jemalloc_postfork_child() rather than - * jemalloc_postfork_parent(), because this function is executed by both - * parent and child. The parent can tolerate having state - * reinitialized, but the child cannot unlock mutexes that were locked - * by the parent. + * zone_force_lock and zone_force_unlock are the entry points to the + * forking machinery on OS X. The tricky thing is, the child is not + * allowed to unlock mutexes locked in the parent, even if owned by the + * forking thread (and the mutex type we use in OS X will fail an assert + * if we try). In the child, we can get away with reinitializing all + * the mutexes, which has the effect of unlocking them. In the parent, + * doing this would mean we wouldn't wake any waiters blocked on the + * mutexes we unlock. So, we record the pid of the current thread in + * zone_force_lock, and use that to detect if we're in the parent or + * child here, to decide which unlock logic we need. */ if (isthreaded) { - jemalloc_postfork_child(); + assert(zone_force_lock_pid != -1); + if (getpid() == zone_force_lock_pid) { + jemalloc_postfork_parent(); + } else { + jemalloc_postfork_child(); + } + zone_force_lock_pid = -1; } } diff --git a/kbe/src/lib/dependencies/jemalloc/test/include/test/extent_hooks.h b/kbe/src/lib/dependencies/jemalloc/test/include/test/extent_hooks.h index ea0128573a..1f0620154d 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/include/test/extent_hooks.h +++ b/kbe/src/lib/dependencies/jemalloc/test/include/test/extent_hooks.h @@ -266,6 +266,8 @@ extent_merge_hook(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a, "extent_hooks should be same as pointer used to set hooks"); assert_ptr_eq(extent_hooks->merge, extent_merge_hook, "Wrong hook function"); + assert_ptr_eq((void *)((uintptr_t)addr_a + size_a), addr_b, + "Extents not mergeable"); called_merge = true; if (!try_merge) { return true; diff --git a/kbe/src/lib/dependencies/jemalloc/test/include/test/jemalloc_test.h.in b/kbe/src/lib/dependencies/jemalloc/test/include/test/jemalloc_test.h.in index 67caa86bf6..c46af5d9b2 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/include/test/jemalloc_test.h.in +++ b/kbe/src/lib/dependencies/jemalloc/test/include/test/jemalloc_test.h.in @@ -25,7 +25,7 @@ extern "C" { #include "test/jemalloc_test_defs.h" -#ifdef JEMALLOC_OSSPIN +#if defined(JEMALLOC_OSATOMIC) # include #endif @@ -69,7 +69,7 @@ static const bool config_debug = # define JEMALLOC_N(n) @private_namespace@##n # include "jemalloc/internal/private_namespace.h" -# include "jemalloc/internal/hooks.h" +# include "jemalloc/internal/test_hooks.h" /* Hermetic headers. */ # include "jemalloc/internal/assert.h" diff --git a/kbe/src/lib/dependencies/jemalloc/test/include/test/mtx.h b/kbe/src/lib/dependencies/jemalloc/test/include/test/mtx.h index 58afbc3d13..066a213790 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/include/test/mtx.h +++ b/kbe/src/lib/dependencies/jemalloc/test/include/test/mtx.h @@ -10,8 +10,6 @@ typedef struct { CRITICAL_SECTION lock; #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) os_unfair_lock lock; -#elif (defined(JEMALLOC_OSSPIN)) - OSSpinLock lock; #else pthread_mutex_t lock; #endif diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/aligned_alloc.c b/kbe/src/lib/dependencies/jemalloc/test/integration/aligned_alloc.c index 536b67ea87..4375b172ad 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/integration/aligned_alloc.c +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/aligned_alloc.c @@ -34,6 +34,17 @@ TEST_BEGIN(test_alignment_errors) { } TEST_END + +/* + * GCC "-Walloc-size-larger-than" warning detects when one of the memory + * allocation functions is called with a size larger than the maximum size that + * they support. Here we want to explicitly test that the allocation functions + * do indeed fail properly when this is the case, which triggers the warning. + * Therefore we disable the warning for these tests. + */ +JEMALLOC_DIAGNOSTIC_PUSH +JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN + TEST_BEGIN(test_oom_errors) { size_t alignment, size; void *p; @@ -78,6 +89,9 @@ TEST_BEGIN(test_oom_errors) { } TEST_END +/* Re-enable the "-Walloc-size-larger-than=" warning */ +JEMALLOC_DIAGNOSTIC_POP + TEST_BEGIN(test_alignment_and_size) { #define NITER 4 size_t alignment, size, total; @@ -124,10 +138,20 @@ TEST_BEGIN(test_alignment_and_size) { } TEST_END +TEST_BEGIN(test_zero_alloc) { + void *res = aligned_alloc(8, 0); + assert(res); + size_t usable = malloc_usable_size(res); + assert(usable > 0); + free(res); +} +TEST_END + int main(void) { return test( test_alignment_errors, test_oom_errors, - test_alignment_and_size); + test_alignment_and_size, + test_zero_alloc); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/extent.c b/kbe/src/lib/dependencies/jemalloc/test/integration/extent.c index 1dcf217630..b5db087665 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/integration/extent.c +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/extent.c @@ -98,7 +98,45 @@ test_extent_body(unsigned arena_ind) { dallocx(p, flags); } -TEST_BEGIN(test_extent_manual_hook) { +static void +test_manual_hook_auto_arena(void) { + unsigned narenas; + size_t old_size, new_size, sz; + size_t hooks_mib[3]; + size_t hooks_miblen; + extent_hooks_t *new_hooks, *old_hooks; + + extent_hooks_prep(); + + sz = sizeof(unsigned); + /* Get number of auto arenas. */ + assert_d_eq(mallctl("opt.narenas", (void *)&narenas, &sz, NULL, 0), + 0, "Unexpected mallctl() failure"); + if (narenas == 1) { + return; + } + + /* Install custom extent hooks on arena 1 (might not be initialized). */ + hooks_miblen = sizeof(hooks_mib)/sizeof(size_t); + assert_d_eq(mallctlnametomib("arena.0.extent_hooks", hooks_mib, + &hooks_miblen), 0, "Unexpected mallctlnametomib() failure"); + hooks_mib[1] = 1; + old_size = sizeof(extent_hooks_t *); + new_hooks = &hooks; + new_size = sizeof(extent_hooks_t *); + assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, (void *)&old_hooks, + &old_size, (void *)&new_hooks, new_size), 0, + "Unexpected extent_hooks error"); + static bool auto_arena_created = false; + if (old_hooks != &hooks) { + assert_b_eq(auto_arena_created, false, + "Expected auto arena 1 created only once."); + auto_arena_created = true; + } +} + +static void +test_manual_hook_body(void) { unsigned arena_ind; size_t old_size, new_size, sz; size_t hooks_mib[3]; @@ -139,8 +177,9 @@ TEST_BEGIN(test_extent_manual_hook) { assert_ptr_ne(old_hooks->merge, extent_merge_hook, "Unexpected extent_hooks error"); - test_skip_if(check_background_thread_enabled()); - test_extent_body(arena_ind); + if (!check_background_thread_enabled()) { + test_extent_body(arena_ind); + } /* Restore extent hooks. */ assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, NULL, NULL, @@ -165,6 +204,22 @@ TEST_BEGIN(test_extent_manual_hook) { assert_ptr_eq(old_hooks->merge, default_hooks->merge, "Unexpected extent_hooks error"); } + +TEST_BEGIN(test_extent_manual_hook) { + test_manual_hook_auto_arena(); + test_manual_hook_body(); + + /* Test failure paths. */ + try_split = false; + test_manual_hook_body(); + try_merge = false; + test_manual_hook_body(); + try_purge_lazy = false; + try_purge_forced = false; + test_manual_hook_body(); + + try_split = try_merge = try_purge_lazy = try_purge_forced = true; +} TEST_END TEST_BEGIN(test_extent_auto_hook) { diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/malloc.c b/kbe/src/lib/dependencies/jemalloc/test/integration/malloc.c new file mode 100644 index 0000000000..8b33bc8f3b --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/malloc.c @@ -0,0 +1,16 @@ +#include "test/jemalloc_test.h" + +TEST_BEGIN(test_zero_alloc) { + void *res = malloc(0); + assert(res); + size_t usable = malloc_usable_size(res); + assert(usable > 0); + free(res); +} +TEST_END + +int +main(void) { + return test( + test_zero_alloc); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/mallocx.c b/kbe/src/lib/dependencies/jemalloc/test/integration/mallocx.c index b0b5cdac23..645d4db48f 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/integration/mallocx.c +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/mallocx.c @@ -51,6 +51,16 @@ purge(void) { "Unexpected mallctl error"); } +/* + * GCC "-Walloc-size-larger-than" warning detects when one of the memory + * allocation functions is called with a size larger than the maximum size that + * they support. Here we want to explicitly test that the allocation functions + * do indeed fail properly when this is the case, which triggers the warning. + * Therefore we disable the warning for these tests. + */ +JEMALLOC_DIAGNOSTIC_PUSH +JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN + TEST_BEGIN(test_overflow) { size_t largemax; @@ -71,6 +81,38 @@ TEST_BEGIN(test_overflow) { } TEST_END +static void * +remote_alloc(void *arg) { + unsigned arena; + size_t sz = sizeof(unsigned); + assert_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + size_t large_sz; + sz = sizeof(size_t); + assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&large_sz, &sz, + NULL, 0), 0, "Unexpected mallctl failure"); + + void *ptr = mallocx(large_sz, MALLOCX_ARENA(arena) + | MALLOCX_TCACHE_NONE); + void **ret = (void **)arg; + *ret = ptr; + + return NULL; +} + +TEST_BEGIN(test_remote_free) { + thd_t thd; + void *ret; + thd_create(&thd, remote_alloc, (void *)&ret); + thd_join(thd, NULL); + assert_ptr_not_null(ret, "Unexpected mallocx failure"); + + /* Avoid TCACHE_NONE to explicitly test tcache_flush(). */ + dallocx(ret, 0); + mallctl("thread.tcache.flush", NULL, NULL, NULL, 0); +} +TEST_END + TEST_BEGIN(test_oom) { size_t largemax; bool oom; @@ -84,7 +126,7 @@ TEST_BEGIN(test_oom) { largemax = get_large_size(get_nlarge()-1); oom = false; for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) { - ptrs[i] = mallocx(largemax, 0); + ptrs[i] = mallocx(largemax, MALLOCX_ARENA(0)); if (ptrs[i] == NULL) { oom = true; } @@ -113,6 +155,9 @@ TEST_BEGIN(test_oom) { } TEST_END +/* Re-enable the "-Walloc-size-larger-than=" warning */ +JEMALLOC_DIAGNOSTIC_POP + TEST_BEGIN(test_basic) { #define MAXSZ (((size_t)1) << 23) size_t sz; @@ -151,9 +196,17 @@ TEST_BEGIN(test_basic) { TEST_END TEST_BEGIN(test_alignment_and_size) { + const char *percpu_arena; + size_t sz = sizeof(percpu_arena); + + if(mallctl("opt.percpu_arena", (void *)&percpu_arena, &sz, NULL, 0) || + strcmp(percpu_arena, "disabled") != 0) { + test_skip("test_alignment_and_size skipped: " + "not working with percpu arena."); + }; #define MAXALIGN (((size_t)1) << 23) #define NITER 4 - size_t nsz, rsz, sz, alignment, total; + size_t nsz, rsz, alignment, total; unsigned i; void *ps[NITER]; @@ -170,12 +223,12 @@ TEST_BEGIN(test_alignment_and_size) { sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { for (i = 0; i < NITER; i++) { nsz = nallocx(sz, MALLOCX_ALIGN(alignment) | - MALLOCX_ZERO); + MALLOCX_ZERO | MALLOCX_ARENA(0)); assert_zu_ne(nsz, 0, "nallocx() error for alignment=%zu, " "size=%zu (%#zx)", alignment, sz, sz); ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) | - MALLOCX_ZERO); + MALLOCX_ZERO | MALLOCX_ARENA(0)); assert_ptr_not_null(ps[i], "mallocx() error for alignment=%zu, " "size=%zu (%#zx)", alignment, sz, sz); @@ -215,6 +268,7 @@ main(void) { return test( test_overflow, test_oom, + test_remote_free, test_basic, test_alignment_and_size); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/overflow.c b/kbe/src/lib/dependencies/jemalloc/test/integration/overflow.c index 6a9785b2e2..748ebb6772 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/integration/overflow.c +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/overflow.c @@ -1,5 +1,15 @@ #include "test/jemalloc_test.h" +/* + * GCC "-Walloc-size-larger-than" warning detects when one of the memory + * allocation functions is called with a size larger than the maximum size that + * they support. Here we want to explicitly test that the allocation functions + * do indeed fail properly when this is the case, which triggers the warning. + * Therefore we disable the warning for these tests. + */ +JEMALLOC_DIAGNOSTIC_PUSH +JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN + TEST_BEGIN(test_overflow) { unsigned nlextents; size_t mib[4]; @@ -39,6 +49,9 @@ TEST_BEGIN(test_overflow) { } TEST_END +/* Re-enable the "-Walloc-size-larger-than=" warning */ +JEMALLOC_DIAGNOSTIC_POP + int main(void) { return test( diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/rallocx.c b/kbe/src/lib/dependencies/jemalloc/test/integration/rallocx.c index 7821ca5f56..08ed08d3fb 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/integration/rallocx.c +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/rallocx.c @@ -208,6 +208,16 @@ TEST_BEGIN(test_lg_align_and_zero) { } TEST_END +/* + * GCC "-Walloc-size-larger-than" warning detects when one of the memory + * allocation functions is called with a size larger than the maximum size that + * they support. Here we want to explicitly test that the allocation functions + * do indeed fail properly when this is the case, which triggers the warning. + * Therefore we disable the warning for these tests. + */ +JEMALLOC_DIAGNOSTIC_PUSH +JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN + TEST_BEGIN(test_overflow) { size_t largemax; void *p; @@ -234,6 +244,9 @@ TEST_BEGIN(test_overflow) { } TEST_END +/* Re-enable the "-Walloc-size-larger-than=" warning */ +JEMALLOC_DIAGNOSTIC_POP + int main(void) { return test( diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/sdallocx.c b/kbe/src/lib/dependencies/jemalloc/test/integration/sdallocx.c index e7ea1d82c0..ca0144855a 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/integration/sdallocx.c +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/sdallocx.c @@ -49,7 +49,7 @@ TEST_END int main(void) { - return test( + return test_no_reentrancy( test_basic, test_alignment_and_size); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.c b/kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.c new file mode 100644 index 0000000000..af250c3f46 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.c @@ -0,0 +1,80 @@ +#include "test/jemalloc_test.h" + +/* Note that this test relies on the unusual slab sizes set in slab_sizes.sh. */ + +TEST_BEGIN(test_slab_sizes) { + unsigned nbins; + size_t page; + size_t sizemib[4]; + size_t slabmib[4]; + size_t len; + + len = sizeof(nbins); + assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0, + "nbins mallctl failure"); + + len = sizeof(page); + assert_d_eq(mallctl("arenas.page", &page, &len, NULL, 0), 0, + "page mallctl failure"); + + len = 4; + assert_d_eq(mallctlnametomib("arenas.bin.0.size", sizemib, &len), 0, + "bin size mallctlnametomib failure"); + + len = 4; + assert_d_eq(mallctlnametomib("arenas.bin.0.slab_size", slabmib, &len), + 0, "slab size mallctlnametomib failure"); + + size_t biggest_slab_seen = 0; + + for (unsigned i = 0; i < nbins; i++) { + size_t bin_size; + size_t slab_size; + len = sizeof(size_t); + sizemib[2] = i; + slabmib[2] = i; + assert_d_eq(mallctlbymib(sizemib, 4, (void *)&bin_size, &len, + NULL, 0), 0, "bin size mallctlbymib failure"); + + len = sizeof(size_t); + assert_d_eq(mallctlbymib(slabmib, 4, (void *)&slab_size, &len, + NULL, 0), 0, "slab size mallctlbymib failure"); + + if (bin_size < 100) { + /* + * Then we should be as close to 17 as possible. Since + * not all page sizes are valid (because of bitmap + * limitations on the number of items in a slab), we + * should at least make sure that the number of pages + * goes up. + */ + assert_zu_ge(slab_size, biggest_slab_seen, + "Slab sizes should go up"); + biggest_slab_seen = slab_size; + } else if ( + (100 <= bin_size && bin_size < 128) + || (128 < bin_size && bin_size <= 200)) { + assert_zu_eq(slab_size, page, + "Forced-small slabs should be small"); + } else if (bin_size == 128) { + assert_zu_eq(slab_size, 2 * page, + "Forced-2-page slab should be 2 pages"); + } else if (200 < bin_size && bin_size <= 4096) { + assert_zu_ge(slab_size, biggest_slab_seen, + "Slab sizes should go up"); + biggest_slab_seen = slab_size; + } + } + /* + * For any reasonable configuration, 17 pages should be a valid slab + * size for 4096-byte items. + */ + assert_zu_eq(biggest_slab_seen, 17 * page, "Didn't hit page target"); +} +TEST_END + +int +main(void) { + return test( + test_slab_sizes); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.sh b/kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.sh new file mode 100644 index 0000000000..07e3db81bc --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/slab_sizes.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +# Some screwy-looking slab sizes. +export MALLOC_CONF="slab_sizes:1-4096:17|100-200:1|128-128:2" diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.c b/kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.c new file mode 100644 index 0000000000..2486752beb --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.c @@ -0,0 +1,312 @@ +#include "test/jemalloc_test.h" +#include "jemalloc/jemalloc_macros.h" + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +#ifndef JEMALLOC_VERSION_GID_IDENT + #error "JEMALLOC_VERSION_GID_IDENT not defined" +#endif + +#define JOIN(x, y) x ## y +#define JOIN2(x, y) JOIN(x, y) +#define smallocx JOIN2(smallocx_, JEMALLOC_VERSION_GID_IDENT) + +typedef struct { + void *ptr; + size_t size; +} smallocx_return_t; + +extern smallocx_return_t +smallocx(size_t size, int flags); + +static unsigned +get_nsizes_impl(const char *cmd) { + unsigned ret; + size_t z; + + z = sizeof(unsigned); + assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0, + "Unexpected mallctl(\"%s\", ...) failure", cmd); + + return ret; +} + +static unsigned +get_nlarge(void) { + return get_nsizes_impl("arenas.nlextents"); +} + +static size_t +get_size_impl(const char *cmd, size_t ind) { + size_t ret; + size_t z; + size_t mib[4]; + size_t miblen = 4; + + z = sizeof(size_t); + assert_d_eq(mallctlnametomib(cmd, mib, &miblen), + 0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd); + mib[2] = ind; + z = sizeof(size_t); + assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0), + 0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind); + + return ret; +} + +static size_t +get_large_size(size_t ind) { + return get_size_impl("arenas.lextent.0.size", ind); +} + +/* + * On systems which can't merge extents, tests that call this function generate + * a lot of dirty memory very quickly. Purging between cycles mitigates + * potential OOM on e.g. 32-bit Windows. + */ +static void +purge(void) { + assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl error"); +} + +/* + * GCC "-Walloc-size-larger-than" warning detects when one of the memory + * allocation functions is called with a size larger than the maximum size that + * they support. Here we want to explicitly test that the allocation functions + * do indeed fail properly when this is the case, which triggers the warning. + * Therefore we disable the warning for these tests. + */ +JEMALLOC_DIAGNOSTIC_PUSH +JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN + +TEST_BEGIN(test_overflow) { + size_t largemax; + + largemax = get_large_size(get_nlarge()-1); + + assert_ptr_null(smallocx(largemax+1, 0).ptr, + "Expected OOM for smallocx(size=%#zx, 0)", largemax+1); + + assert_ptr_null(smallocx(ZU(PTRDIFF_MAX)+1, 0).ptr, + "Expected OOM for smallocx(size=%#zx, 0)", ZU(PTRDIFF_MAX)+1); + + assert_ptr_null(smallocx(SIZE_T_MAX, 0).ptr, + "Expected OOM for smallocx(size=%#zx, 0)", SIZE_T_MAX); + + assert_ptr_null(smallocx(1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)).ptr, + "Expected OOM for smallocx(size=1, MALLOCX_ALIGN(%#zx))", + ZU(PTRDIFF_MAX)+1); +} +TEST_END + +static void * +remote_alloc(void *arg) { + unsigned arena; + size_t sz = sizeof(unsigned); + assert_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + size_t large_sz; + sz = sizeof(size_t); + assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&large_sz, &sz, + NULL, 0), 0, "Unexpected mallctl failure"); + + smallocx_return_t r + = smallocx(large_sz, MALLOCX_ARENA(arena) | MALLOCX_TCACHE_NONE); + void *ptr = r.ptr; + assert_zu_eq(r.size, + nallocx(large_sz, MALLOCX_ARENA(arena) | MALLOCX_TCACHE_NONE), + "Expected smalloc(size,flags).size == nallocx(size,flags)"); + void **ret = (void **)arg; + *ret = ptr; + + return NULL; +} + +TEST_BEGIN(test_remote_free) { + thd_t thd; + void *ret; + thd_create(&thd, remote_alloc, (void *)&ret); + thd_join(thd, NULL); + assert_ptr_not_null(ret, "Unexpected smallocx failure"); + + /* Avoid TCACHE_NONE to explicitly test tcache_flush(). */ + dallocx(ret, 0); + mallctl("thread.tcache.flush", NULL, NULL, NULL, 0); +} +TEST_END + +TEST_BEGIN(test_oom) { + size_t largemax; + bool oom; + void *ptrs[3]; + unsigned i; + + /* + * It should be impossible to allocate three objects that each consume + * nearly half the virtual address space. + */ + largemax = get_large_size(get_nlarge()-1); + oom = false; + for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) { + ptrs[i] = smallocx(largemax, 0).ptr; + if (ptrs[i] == NULL) { + oom = true; + } + } + assert_true(oom, + "Expected OOM during series of calls to smallocx(size=%zu, 0)", + largemax); + for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) { + if (ptrs[i] != NULL) { + dallocx(ptrs[i], 0); + } + } + purge(); + +#if LG_SIZEOF_PTR == 3 + assert_ptr_null(smallocx(0x8000000000000000ULL, + MALLOCX_ALIGN(0x8000000000000000ULL)).ptr, + "Expected OOM for smallocx()"); + assert_ptr_null(smallocx(0x8000000000000000ULL, + MALLOCX_ALIGN(0x80000000)).ptr, + "Expected OOM for smallocx()"); +#else + assert_ptr_null(smallocx(0x80000000UL, MALLOCX_ALIGN(0x80000000UL)).ptr, + "Expected OOM for smallocx()"); +#endif +} +TEST_END + +/* Re-enable the "-Walloc-size-larger-than=" warning */ +JEMALLOC_DIAGNOSTIC_POP + +TEST_BEGIN(test_basic) { +#define MAXSZ (((size_t)1) << 23) + size_t sz; + + for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) { + smallocx_return_t ret; + size_t nsz, rsz, smz; + void *p; + nsz = nallocx(sz, 0); + assert_zu_ne(nsz, 0, "Unexpected nallocx() error"); + ret = smallocx(sz, 0); + p = ret.ptr; + smz = ret.size; + assert_ptr_not_null(p, + "Unexpected smallocx(size=%zx, flags=0) error", sz); + rsz = sallocx(p, 0); + assert_zu_ge(rsz, sz, "Real size smaller than expected"); + assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch"); + assert_zu_eq(nsz, smz, "nallocx()/smallocx() size mismatch"); + dallocx(p, 0); + + ret = smallocx(sz, 0); + p = ret.ptr; + smz = ret.size; + assert_ptr_not_null(p, + "Unexpected smallocx(size=%zx, flags=0) error", sz); + dallocx(p, 0); + + nsz = nallocx(sz, MALLOCX_ZERO); + assert_zu_ne(nsz, 0, "Unexpected nallocx() error"); + assert_zu_ne(smz, 0, "Unexpected smallocx() error"); + ret = smallocx(sz, MALLOCX_ZERO); + p = ret.ptr; + assert_ptr_not_null(p, + "Unexpected smallocx(size=%zx, flags=MALLOCX_ZERO) error", + nsz); + rsz = sallocx(p, 0); + assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch"); + assert_zu_eq(nsz, smz, "nallocx()/smallocx() size mismatch"); + dallocx(p, 0); + purge(); + } +#undef MAXSZ +} +TEST_END + +TEST_BEGIN(test_alignment_and_size) { + const char *percpu_arena; + size_t sz = sizeof(percpu_arena); + + if(mallctl("opt.percpu_arena", (void *)&percpu_arena, &sz, NULL, 0) || + strcmp(percpu_arena, "disabled") != 0) { + test_skip("test_alignment_and_size skipped: " + "not working with percpu arena."); + }; +#define MAXALIGN (((size_t)1) << 23) +#define NITER 4 + size_t nsz, rsz, smz, alignment, total; + unsigned i; + void *ps[NITER]; + + for (i = 0; i < NITER; i++) { + ps[i] = NULL; + } + + for (alignment = 8; + alignment <= MAXALIGN; + alignment <<= 1) { + total = 0; + for (sz = 1; + sz < 3 * alignment && sz < (1U << 31); + sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { + for (i = 0; i < NITER; i++) { + nsz = nallocx(sz, MALLOCX_ALIGN(alignment) | + MALLOCX_ZERO); + assert_zu_ne(nsz, 0, + "nallocx() error for alignment=%zu, " + "size=%zu (%#zx)", alignment, sz, sz); + smallocx_return_t ret + = smallocx(sz, MALLOCX_ALIGN(alignment) | MALLOCX_ZERO); + ps[i] = ret.ptr; + assert_ptr_not_null(ps[i], + "smallocx() error for alignment=%zu, " + "size=%zu (%#zx)", alignment, sz, sz); + rsz = sallocx(ps[i], 0); + smz = ret.size; + assert_zu_ge(rsz, sz, + "Real size smaller than expected for " + "alignment=%zu, size=%zu", alignment, sz); + assert_zu_eq(nsz, rsz, + "nallocx()/sallocx() size mismatch for " + "alignment=%zu, size=%zu", alignment, sz); + assert_zu_eq(nsz, smz, + "nallocx()/smallocx() size mismatch for " + "alignment=%zu, size=%zu", alignment, sz); + assert_ptr_null( + (void *)((uintptr_t)ps[i] & (alignment-1)), + "%p inadequately aligned for" + " alignment=%zu, size=%zu", ps[i], + alignment, sz); + total += rsz; + if (total >= (MAXALIGN << 1)) { + break; + } + } + for (i = 0; i < NITER; i++) { + if (ps[i] != NULL) { + dallocx(ps[i], 0); + ps[i] = NULL; + } + } + } + purge(); + } +#undef MAXALIGN +#undef NITER +} +TEST_END + +int +main(void) { + return test( + test_overflow, + test_oom, + test_remote_free, + test_basic, + test_alignment_and_size); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.sh b/kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.sh new file mode 100644 index 0000000000..d07f10f3ce --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/smallocx.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +if [ "x${enable_fill}" = "x1" ] ; then + export MALLOC_CONF="junk:false" +fi diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/thread_tcache_enabled.c b/kbe/src/lib/dependencies/jemalloc/test/integration/thread_tcache_enabled.c index 0c343a6c56..95c9acc138 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/integration/thread_tcache_enabled.c +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/thread_tcache_enabled.c @@ -60,8 +60,6 @@ thd_start(void *arg) { free(malloc(1)); return NULL; - test_skip("\"thread.tcache.enabled\" mallctl not available"); - return NULL; } TEST_BEGIN(test_main_thread) { diff --git a/kbe/src/lib/dependencies/jemalloc/test/src/mtx.c b/kbe/src/lib/dependencies/jemalloc/test/src/mtx.c index a393c01fc6..d9ce375c35 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/src/mtx.c +++ b/kbe/src/lib/dependencies/jemalloc/test/src/mtx.c @@ -13,8 +13,6 @@ mtx_init(mtx_t *mtx) { } #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) mtx->lock = OS_UNFAIR_LOCK_INIT; -#elif (defined(JEMALLOC_OSSPIN)) - mtx->lock = 0; #else pthread_mutexattr_t attr; @@ -35,7 +33,6 @@ void mtx_fini(mtx_t *mtx) { #ifdef _WIN32 #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) -#elif (defined(JEMALLOC_OSSPIN)) #else pthread_mutex_destroy(&mtx->lock); #endif @@ -47,8 +44,6 @@ mtx_lock(mtx_t *mtx) { EnterCriticalSection(&mtx->lock); #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) os_unfair_lock_lock(&mtx->lock); -#elif (defined(JEMALLOC_OSSPIN)) - OSSpinLockLock(&mtx->lock); #else pthread_mutex_lock(&mtx->lock); #endif @@ -60,8 +55,6 @@ mtx_unlock(mtx_t *mtx) { LeaveCriticalSection(&mtx->lock); #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) os_unfair_lock_unlock(&mtx->lock); -#elif (defined(JEMALLOC_OSSPIN)) - OSSpinLockUnlock(&mtx->lock); #else pthread_mutex_unlock(&mtx->lock); #endif diff --git a/kbe/src/lib/dependencies/jemalloc/test/src/test.c b/kbe/src/lib/dependencies/jemalloc/test/src/test.c index 01a4d7380b..f97ce4d18d 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/src/test.c +++ b/kbe/src/lib/dependencies/jemalloc/test/src/test.c @@ -48,12 +48,12 @@ do_hook(bool *hook_ran, void (**hook)()) { static void libc_reentrancy_hook() { - do_hook(&libc_hook_ran, &hooks_libc_hook); + do_hook(&libc_hook_ran, &test_hooks_libc_hook); } static void arena_new_reentrancy_hook() { - do_hook(&arena_new_hook_ran, &hooks_arena_new_hook); + do_hook(&arena_new_hook_ran, &test_hooks_arena_new_hook); } /* Actual test infrastructure. */ @@ -110,6 +110,20 @@ p_test_fini(void) { test_status_string(test_status)); } +static void +check_global_slow(test_status_t *status) { +#ifdef JEMALLOC_UNIT_TEST + /* + * This check needs to peek into tsd internals, which is why it's only + * exposed in unit tests. + */ + if (tsd_global_slow()) { + malloc_printf("Testing increased global slow count\n"); + *status = test_status_fail; + } +#endif +} + static test_status_t p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) { test_status_t ret; @@ -131,28 +145,31 @@ p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) { for (; t != NULL; t = va_arg(ap, test_t *)) { /* Non-reentrant run. */ reentrancy = non_reentrant; - hooks_arena_new_hook = hooks_libc_hook = NULL; + test_hooks_arena_new_hook = test_hooks_libc_hook = NULL; t(); if (test_status > ret) { ret = test_status; } + check_global_slow(&ret); /* Reentrant run. */ if (do_reentrant) { reentrancy = libc_reentrant; - hooks_arena_new_hook = NULL; - hooks_libc_hook = &libc_reentrancy_hook; + test_hooks_arena_new_hook = NULL; + test_hooks_libc_hook = &libc_reentrancy_hook; t(); if (test_status > ret) { ret = test_status; } + check_global_slow(&ret); reentrancy = arena_new_reentrant; - hooks_libc_hook = NULL; - hooks_arena_new_hook = &arena_new_reentrancy_hook; + test_hooks_libc_hook = NULL; + test_hooks_arena_new_hook = &arena_new_reentrancy_hook; t(); if (test_status > ret) { ret = test_status; } + check_global_slow(&ret); } } diff --git a/kbe/src/lib/dependencies/jemalloc/test/stress/hookbench.c b/kbe/src/lib/dependencies/jemalloc/test/stress/hookbench.c new file mode 100644 index 0000000000..97e90b0e35 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/stress/hookbench.c @@ -0,0 +1,73 @@ +#include "test/jemalloc_test.h" + +static void +noop_alloc_hook(void *extra, hook_alloc_t type, void *result, + uintptr_t result_raw, uintptr_t args_raw[3]) { +} + +static void +noop_dalloc_hook(void *extra, hook_dalloc_t type, void *address, + uintptr_t args_raw[3]) { +} + +static void +noop_expand_hook(void *extra, hook_expand_t type, void *address, + size_t old_usize, size_t new_usize, uintptr_t result_raw, + uintptr_t args_raw[4]) { +} + +static void +malloc_free_loop(int iters) { + for (int i = 0; i < iters; i++) { + void *p = mallocx(1, 0); + free(p); + } +} + +static void +test_hooked(int iters) { + hooks_t hooks = {&noop_alloc_hook, &noop_dalloc_hook, &noop_expand_hook, + NULL}; + + int err; + void *handles[HOOK_MAX]; + size_t sz = sizeof(handles[0]); + + for (int i = 0; i < HOOK_MAX; i++) { + err = mallctl("experimental.hooks.install", &handles[i], + &sz, &hooks, sizeof(hooks)); + assert(err == 0); + + timedelta_t timer; + timer_start(&timer); + malloc_free_loop(iters); + timer_stop(&timer); + malloc_printf("With %d hook%s: %"FMTu64"us\n", i + 1, + i + 1 == 1 ? "" : "s", timer_usec(&timer)); + } + for (int i = 0; i < HOOK_MAX; i++) { + err = mallctl("experimental.hooks.remove", NULL, NULL, + &handles[i], sizeof(handles[i])); + assert(err == 0); + } +} + +static void +test_unhooked(int iters) { + timedelta_t timer; + timer_start(&timer); + malloc_free_loop(iters); + timer_stop(&timer); + + malloc_printf("Without hooks: %"FMTu64"us\n", timer_usec(&timer)); +} + +int +main(void) { + /* Initialize */ + free(mallocx(1, 0)); + int iters = 10 * 1000 * 1000; + malloc_printf("Benchmarking hooks with %d iterations:\n", iters); + test_hooked(iters); + test_unhooked(iters); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/arena_reset.c b/kbe/src/lib/dependencies/jemalloc/test/unit/arena_reset.c index f5fb24d1ed..96b042ddea 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/arena_reset.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/arena_reset.c @@ -77,7 +77,7 @@ vsalloc(tsdn_t *tsdn, const void *ptr) { return 0; } - if (szind == NSIZES) { + if (szind == SC_NSIZES) { return 0; } @@ -142,7 +142,7 @@ do_arena_reset_post(void **ptrs, unsigned nptrs, unsigned arena_ind) { if (have_background_thread) { malloc_mutex_lock(tsdn, - &background_thread_info[arena_ind % ncpus].mtx); + &background_thread_info_get(arena_ind)->mtx); } /* Verify allocations no longer exist. */ for (i = 0; i < nptrs; i++) { @@ -151,7 +151,7 @@ do_arena_reset_post(void **ptrs, unsigned nptrs, unsigned arena_ind) { } if (have_background_thread) { malloc_mutex_unlock(tsdn, - &background_thread_info[arena_ind % ncpus].mtx); + &background_thread_info_get(arena_ind)->mtx); } free(ptrs); diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/background_thread_enable.c b/kbe/src/lib/dependencies/jemalloc/test/unit/background_thread_enable.c new file mode 100644 index 0000000000..d894e93716 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/background_thread_enable.c @@ -0,0 +1,85 @@ +#include "test/jemalloc_test.h" + +const char *malloc_conf = "background_thread:false,narenas:1,max_background_threads:20"; + +TEST_BEGIN(test_deferred) { + test_skip_if(!have_background_thread); + + unsigned id; + size_t sz_u = sizeof(unsigned); + + /* + * 10 here is somewhat arbitrary, except insofar as we want to ensure + * that the number of background threads is smaller than the number of + * arenas. I'll ragequit long before we have to spin up 10 threads per + * cpu to handle background purging, so this is a conservative + * approximation. + */ + for (unsigned i = 0; i < 10 * ncpus; i++) { + assert_d_eq(mallctl("arenas.create", &id, &sz_u, NULL, 0), 0, + "Failed to create arena"); + } + + bool enable = true; + size_t sz_b = sizeof(bool); + assert_d_eq(mallctl("background_thread", NULL, NULL, &enable, sz_b), 0, + "Failed to enable background threads"); + enable = false; + assert_d_eq(mallctl("background_thread", NULL, NULL, &enable, sz_b), 0, + "Failed to disable background threads"); +} +TEST_END + +TEST_BEGIN(test_max_background_threads) { + test_skip_if(!have_background_thread); + + size_t max_n_thds; + size_t opt_max_n_thds; + size_t sz_m = sizeof(max_n_thds); + assert_d_eq(mallctl("opt.max_background_threads", + &opt_max_n_thds, &sz_m, NULL, 0), 0, + "Failed to get opt.max_background_threads"); + assert_d_eq(mallctl("max_background_threads", &max_n_thds, &sz_m, NULL, + 0), 0, "Failed to get max background threads"); + assert_zu_eq(opt_max_n_thds, max_n_thds, + "max_background_threads and " + "opt.max_background_threads should match"); + assert_d_eq(mallctl("max_background_threads", NULL, NULL, &max_n_thds, + sz_m), 0, "Failed to set max background threads"); + + unsigned id; + size_t sz_u = sizeof(unsigned); + + for (unsigned i = 0; i < 10 * ncpus; i++) { + assert_d_eq(mallctl("arenas.create", &id, &sz_u, NULL, 0), 0, + "Failed to create arena"); + } + + bool enable = true; + size_t sz_b = sizeof(bool); + assert_d_eq(mallctl("background_thread", NULL, NULL, &enable, sz_b), 0, + "Failed to enable background threads"); + assert_zu_eq(n_background_threads, max_n_thds, + "Number of background threads should not change.\n"); + size_t new_max_thds = max_n_thds - 1; + if (new_max_thds > 0) { + assert_d_eq(mallctl("max_background_threads", NULL, NULL, + &new_max_thds, sz_m), 0, + "Failed to set max background threads"); + assert_zu_eq(n_background_threads, new_max_thds, + "Number of background threads should decrease by 1.\n"); + } + new_max_thds = 1; + assert_d_eq(mallctl("max_background_threads", NULL, NULL, &new_max_thds, + sz_m), 0, "Failed to set max background threads"); + assert_zu_eq(n_background_threads, new_max_thds, + "Number of background threads should be 1.\n"); +} +TEST_END + +int +main(void) { + return test_no_reentrancy( + test_deferred, + test_max_background_threads); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/base.c b/kbe/src/lib/dependencies/jemalloc/test/unit/base.c index 7fa24ac035..6b792cf21a 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/base.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/base.c @@ -28,22 +28,28 @@ static extent_hooks_t hooks_not_null = { TEST_BEGIN(test_base_hooks_default) { base_t *base; - size_t allocated0, allocated1, resident, mapped; + size_t allocated0, allocated1, resident, mapped, n_thp; tsdn_t *tsdn = tsd_tsdn(tsd_fetch()); base = base_new(tsdn, 0, (extent_hooks_t *)&extent_hooks_default); if (config_stats) { - base_stats_get(tsdn, base, &allocated0, &resident, &mapped); + base_stats_get(tsdn, base, &allocated0, &resident, &mapped, + &n_thp); assert_zu_ge(allocated0, sizeof(base_t), "Base header should count as allocated"); + if (opt_metadata_thp == metadata_thp_always) { + assert_zu_gt(n_thp, 0, + "Base should have 1 THP at least."); + } } assert_ptr_not_null(base_alloc(tsdn, base, 42, 1), "Unexpected base_alloc() failure"); if (config_stats) { - base_stats_get(tsdn, base, &allocated1, &resident, &mapped); + base_stats_get(tsdn, base, &allocated1, &resident, &mapped, + &n_thp); assert_zu_ge(allocated1 - allocated0, 42, "At least 42 bytes were allocated by base_alloc()"); } @@ -55,7 +61,7 @@ TEST_END TEST_BEGIN(test_base_hooks_null) { extent_hooks_t hooks_orig; base_t *base; - size_t allocated0, allocated1, resident, mapped; + size_t allocated0, allocated1, resident, mapped, n_thp; extent_hooks_prep(); try_dalloc = false; @@ -71,16 +77,22 @@ TEST_BEGIN(test_base_hooks_null) { assert_ptr_not_null(base, "Unexpected base_new() failure"); if (config_stats) { - base_stats_get(tsdn, base, &allocated0, &resident, &mapped); + base_stats_get(tsdn, base, &allocated0, &resident, &mapped, + &n_thp); assert_zu_ge(allocated0, sizeof(base_t), "Base header should count as allocated"); + if (opt_metadata_thp == metadata_thp_always) { + assert_zu_gt(n_thp, 0, + "Base should have 1 THP at least."); + } } assert_ptr_not_null(base_alloc(tsdn, base, 42, 1), "Unexpected base_alloc() failure"); if (config_stats) { - base_stats_get(tsdn, base, &allocated1, &resident, &mapped); + base_stats_get(tsdn, base, &allocated1, &resident, &mapped, + &n_thp); assert_zu_ge(allocated1 - allocated0, 42, "At least 42 bytes were allocated by base_alloc()"); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/binshard.c b/kbe/src/lib/dependencies/jemalloc/test/unit/binshard.c new file mode 100644 index 0000000000..d7a8df8fc0 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/binshard.c @@ -0,0 +1,154 @@ +#include "test/jemalloc_test.h" + +/* Config -- "narenas:1,bin_shards:1-160:16|129-512:4|256-256:8" */ + +#define NTHREADS 16 +#define REMOTE_NALLOC 256 + +static void * +thd_producer(void *varg) { + void **mem = varg; + unsigned arena, i; + size_t sz; + + sz = sizeof(arena); + /* Remote arena. */ + assert_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + for (i = 0; i < REMOTE_NALLOC / 2; i++) { + mem[i] = mallocx(1, MALLOCX_TCACHE_NONE | MALLOCX_ARENA(arena)); + } + + /* Remote bin. */ + for (; i < REMOTE_NALLOC; i++) { + mem[i] = mallocx(1, MALLOCX_TCACHE_NONE | MALLOCX_ARENA(0)); + } + + return NULL; +} + +TEST_BEGIN(test_producer_consumer) { + thd_t thds[NTHREADS]; + void *mem[NTHREADS][REMOTE_NALLOC]; + unsigned i; + + /* Create producer threads to allocate. */ + for (i = 0; i < NTHREADS; i++) { + thd_create(&thds[i], thd_producer, mem[i]); + } + for (i = 0; i < NTHREADS; i++) { + thd_join(thds[i], NULL); + } + /* Remote deallocation by the current thread. */ + for (i = 0; i < NTHREADS; i++) { + for (unsigned j = 0; j < REMOTE_NALLOC; j++) { + assert_ptr_not_null(mem[i][j], + "Unexpected remote allocation failure"); + dallocx(mem[i][j], 0); + } + } +} +TEST_END + +static void * +thd_start(void *varg) { + void *ptr, *ptr2; + extent_t *extent; + unsigned shard1, shard2; + + tsdn_t *tsdn = tsdn_fetch(); + /* Try triggering allocations from sharded bins. */ + for (unsigned i = 0; i < 1024; i++) { + ptr = mallocx(1, MALLOCX_TCACHE_NONE); + ptr2 = mallocx(129, MALLOCX_TCACHE_NONE); + + extent = iealloc(tsdn, ptr); + shard1 = extent_binshard_get(extent); + dallocx(ptr, 0); + assert_u_lt(shard1, 16, "Unexpected bin shard used"); + + extent = iealloc(tsdn, ptr2); + shard2 = extent_binshard_get(extent); + dallocx(ptr2, 0); + assert_u_lt(shard2, 4, "Unexpected bin shard used"); + + if (shard1 > 0 || shard2 > 0) { + /* Triggered sharded bin usage. */ + return (void *)(uintptr_t)shard1; + } + } + + return NULL; +} + +TEST_BEGIN(test_bin_shard_mt) { + test_skip_if(have_percpu_arena && + PERCPU_ARENA_ENABLED(opt_percpu_arena)); + + thd_t thds[NTHREADS]; + unsigned i; + for (i = 0; i < NTHREADS; i++) { + thd_create(&thds[i], thd_start, NULL); + } + bool sharded = false; + for (i = 0; i < NTHREADS; i++) { + void *ret; + thd_join(thds[i], &ret); + if (ret != NULL) { + sharded = true; + } + } + assert_b_eq(sharded, true, "Did not find sharded bins"); +} +TEST_END + +TEST_BEGIN(test_bin_shard) { + unsigned nbins, i; + size_t mib[4], mib2[4]; + size_t miblen, miblen2, len; + + len = sizeof(nbins); + assert_d_eq(mallctl("arenas.nbins", (void *)&nbins, &len, NULL, 0), 0, + "Unexpected mallctl() failure"); + + miblen = 4; + assert_d_eq(mallctlnametomib("arenas.bin.0.nshards", mib, &miblen), 0, + "Unexpected mallctlnametomib() failure"); + miblen2 = 4; + assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib2, &miblen2), 0, + "Unexpected mallctlnametomib() failure"); + + for (i = 0; i < nbins; i++) { + uint32_t nshards; + size_t size, sz1, sz2; + + mib[2] = i; + sz1 = sizeof(nshards); + assert_d_eq(mallctlbymib(mib, miblen, (void *)&nshards, &sz1, + NULL, 0), 0, "Unexpected mallctlbymib() failure"); + + mib2[2] = i; + sz2 = sizeof(size); + assert_d_eq(mallctlbymib(mib2, miblen2, (void *)&size, &sz2, + NULL, 0), 0, "Unexpected mallctlbymib() failure"); + + if (size >= 1 && size <= 128) { + assert_u_eq(nshards, 16, "Unexpected nshards"); + } else if (size == 256) { + assert_u_eq(nshards, 8, "Unexpected nshards"); + } else if (size > 128 && size <= 512) { + assert_u_eq(nshards, 4, "Unexpected nshards"); + } else { + assert_u_eq(nshards, 1, "Unexpected nshards"); + } + } +} +TEST_END + +int +main(void) { + return test_no_reentrancy( + test_bin_shard, + test_bin_shard_mt, + test_producer_consumer); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/binshard.sh b/kbe/src/lib/dependencies/jemalloc/test/unit/binshard.sh new file mode 100644 index 0000000000..c1d58c8837 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/binshard.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +export MALLOC_CONF="narenas:1,bin_shards:1-160:16|129-512:4|256-256:8" diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/bit_util.c b/kbe/src/lib/dependencies/jemalloc/test/unit/bit_util.c index 42a97013d0..b747deb433 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/bit_util.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/bit_util.c @@ -48,10 +48,64 @@ TEST_BEGIN(test_pow2_ceil_zu) { } TEST_END +void +assert_lg_ceil_range(size_t input, unsigned answer) { + if (input == 1) { + assert_u_eq(0, answer, "Got %u as lg_ceil of 1", answer); + return; + } + assert_zu_le(input, (ZU(1) << answer), + "Got %u as lg_ceil of %zu", answer, input); + assert_zu_gt(input, (ZU(1) << (answer - 1)), + "Got %u as lg_ceil of %zu", answer, input); +} + +void +assert_lg_floor_range(size_t input, unsigned answer) { + if (input == 1) { + assert_u_eq(0, answer, "Got %u as lg_floor of 1", answer); + return; + } + assert_zu_ge(input, (ZU(1) << answer), + "Got %u as lg_floor of %zu", answer, input); + assert_zu_lt(input, (ZU(1) << (answer + 1)), + "Got %u as lg_floor of %zu", answer, input); +} + +TEST_BEGIN(test_lg_ceil_floor) { + for (size_t i = 1; i < 10 * 1000 * 1000; i++) { + assert_lg_ceil_range(i, lg_ceil(i)); + assert_lg_ceil_range(i, LG_CEIL(i)); + assert_lg_floor_range(i, lg_floor(i)); + assert_lg_floor_range(i, LG_FLOOR(i)); + } + for (int i = 10; i < 8 * (1 << LG_SIZEOF_PTR) - 5; i++) { + for (size_t j = 0; j < (1 << 4); j++) { + size_t num1 = ((size_t)1 << i) + - j * ((size_t)1 << (i - 4)); + size_t num2 = ((size_t)1 << i) + + j * ((size_t)1 << (i - 4)); + assert_zu_ne(num1, 0, "Invalid lg argument"); + assert_zu_ne(num2, 0, "Invalid lg argument"); + assert_lg_ceil_range(num1, lg_ceil(num1)); + assert_lg_ceil_range(num1, LG_CEIL(num1)); + assert_lg_ceil_range(num2, lg_ceil(num2)); + assert_lg_ceil_range(num2, LG_CEIL(num2)); + + assert_lg_floor_range(num1, lg_floor(num1)); + assert_lg_floor_range(num1, LG_FLOOR(num1)); + assert_lg_floor_range(num2, lg_floor(num2)); + assert_lg_floor_range(num2, LG_FLOOR(num2)); + } + } +} +TEST_END + int main(void) { return test( test_pow2_ceil_u64, test_pow2_ceil_u32, - test_pow2_ceil_zu); + test_pow2_ceil_zu, + test_lg_ceil_floor); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/decay.c b/kbe/src/lib/dependencies/jemalloc/test/unit/decay.c index f727bf9316..cf3c07960e 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/decay.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/decay.c @@ -121,6 +121,12 @@ get_arena_dirty_npurge(unsigned arena_ind) { return get_arena_npurge_impl("stats.arenas.0.dirty_npurge", arena_ind); } +static uint64_t +get_arena_dirty_purged(unsigned arena_ind) { + do_epoch(); + return get_arena_npurge_impl("stats.arenas.0.dirty_purged", arena_ind); +} + static uint64_t get_arena_muzzy_npurge(unsigned arena_ind) { do_epoch(); @@ -559,7 +565,7 @@ TEST_BEGIN(test_decay_now) { TEST_END TEST_BEGIN(test_decay_never) { - test_skip_if(check_background_thread_enabled()); + test_skip_if(check_background_thread_enabled() || !config_stats); unsigned arena_ind = do_arena_create(-1, -1); int flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE; @@ -579,8 +585,8 @@ TEST_BEGIN(test_decay_never) { dallocx(ptrs[i], flags); size_t pdirty = get_arena_pdirty(arena_ind); size_t pmuzzy = get_arena_pmuzzy(arena_ind); - assert_zu_gt(pdirty, pdirty_prev, - "Expected dirty pages to increase."); + assert_zu_gt(pdirty + (size_t)get_arena_dirty_purged(arena_ind), + pdirty_prev, "Expected dirty pages to increase."); assert_zu_eq(pmuzzy, 0, "Unexpected muzzy pages"); pdirty_prev = pdirty; } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/div.c b/kbe/src/lib/dependencies/jemalloc/test/unit/div.c new file mode 100644 index 0000000000..b47f10b2ba --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/div.c @@ -0,0 +1,29 @@ +#include "test/jemalloc_test.h" + +#include "jemalloc/internal/div.h" + +TEST_BEGIN(test_div_exhaustive) { + for (size_t divisor = 2; divisor < 1000 * 1000; ++divisor) { + div_info_t div_info; + div_init(&div_info, divisor); + size_t max = 1000 * divisor; + if (max < 1000 * 1000) { + max = 1000 * 1000; + } + for (size_t dividend = 0; dividend < 1000 * divisor; + dividend += divisor) { + size_t quotient = div_compute( + &div_info, dividend); + assert_zu_eq(dividend, quotient * divisor, + "With divisor = %zu, dividend = %zu, " + "got quotient %zu", divisor, dividend, quotient); + } + } +} +TEST_END + +int +main(void) { + return test_no_reentrancy( + test_div_exhaustive); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/emitter.c b/kbe/src/lib/dependencies/jemalloc/test/unit/emitter.c new file mode 100644 index 0000000000..b4a693f4b3 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/emitter.c @@ -0,0 +1,469 @@ +#include "test/jemalloc_test.h" +#include "jemalloc/internal/emitter.h" + +/* + * This is so useful for debugging and feature work, we'll leave printing + * functionality committed but disabled by default. + */ +/* Print the text as it will appear. */ +static bool print_raw = false; +/* Print the text escaped, so it can be copied back into the test case. */ +static bool print_escaped = false; + +typedef struct buf_descriptor_s buf_descriptor_t; +struct buf_descriptor_s { + char *buf; + size_t len; + bool mid_quote; +}; + +/* + * Forwards all writes to the passed-in buf_v (which should be cast from a + * buf_descriptor_t *). + */ +static void +forwarding_cb(void *buf_descriptor_v, const char *str) { + buf_descriptor_t *buf_descriptor = (buf_descriptor_t *)buf_descriptor_v; + + if (print_raw) { + malloc_printf("%s", str); + } + if (print_escaped) { + const char *it = str; + while (*it != '\0') { + if (!buf_descriptor->mid_quote) { + malloc_printf("\""); + buf_descriptor->mid_quote = true; + } + switch (*it) { + case '\\': + malloc_printf("\\"); + break; + case '\"': + malloc_printf("\\\""); + break; + case '\t': + malloc_printf("\\t"); + break; + case '\n': + malloc_printf("\\n\"\n"); + buf_descriptor->mid_quote = false; + break; + default: + malloc_printf("%c", *it); + } + it++; + } + } + + size_t written = malloc_snprintf(buf_descriptor->buf, + buf_descriptor->len, "%s", str); + assert_zu_eq(written, strlen(str), "Buffer overflow!"); + buf_descriptor->buf += written; + buf_descriptor->len -= written; + assert_zu_gt(buf_descriptor->len, 0, "Buffer out of space!"); +} + +static void +assert_emit_output(void (*emit_fn)(emitter_t *), + const char *expected_json_output, const char *expected_table_output) { + emitter_t emitter; + char buf[MALLOC_PRINTF_BUFSIZE]; + buf_descriptor_t buf_descriptor; + + buf_descriptor.buf = buf; + buf_descriptor.len = MALLOC_PRINTF_BUFSIZE; + buf_descriptor.mid_quote = false; + + emitter_init(&emitter, emitter_output_json, &forwarding_cb, + &buf_descriptor); + (*emit_fn)(&emitter); + assert_str_eq(expected_json_output, buf, "json output failure"); + + buf_descriptor.buf = buf; + buf_descriptor.len = MALLOC_PRINTF_BUFSIZE; + buf_descriptor.mid_quote = false; + + emitter_init(&emitter, emitter_output_table, &forwarding_cb, + &buf_descriptor); + (*emit_fn)(&emitter); + assert_str_eq(expected_table_output, buf, "table output failure"); +} + +static void +emit_dict(emitter_t *emitter) { + bool b_false = false; + bool b_true = true; + int i_123 = 123; + const char *str = "a string"; + + emitter_begin(emitter); + emitter_dict_begin(emitter, "foo", "This is the foo table:"); + emitter_kv(emitter, "abc", "ABC", emitter_type_bool, &b_false); + emitter_kv(emitter, "def", "DEF", emitter_type_bool, &b_true); + emitter_kv_note(emitter, "ghi", "GHI", emitter_type_int, &i_123, + "note_key1", emitter_type_string, &str); + emitter_kv_note(emitter, "jkl", "JKL", emitter_type_string, &str, + "note_key2", emitter_type_bool, &b_false); + emitter_dict_end(emitter); + emitter_end(emitter); +} +static const char *dict_json = +"{\n" +"\t\"foo\": {\n" +"\t\t\"abc\": false,\n" +"\t\t\"def\": true,\n" +"\t\t\"ghi\": 123,\n" +"\t\t\"jkl\": \"a string\"\n" +"\t}\n" +"}\n"; +static const char *dict_table = +"This is the foo table:\n" +" ABC: false\n" +" DEF: true\n" +" GHI: 123 (note_key1: \"a string\")\n" +" JKL: \"a string\" (note_key2: false)\n"; + +TEST_BEGIN(test_dict) { + assert_emit_output(&emit_dict, dict_json, dict_table); +} +TEST_END + +static void +emit_table_printf(emitter_t *emitter) { + emitter_begin(emitter); + emitter_table_printf(emitter, "Table note 1\n"); + emitter_table_printf(emitter, "Table note 2 %s\n", + "with format string"); + emitter_end(emitter); +} + +static const char *table_printf_json = +"{\n" +"}\n"; + +static const char *table_printf_table = +"Table note 1\n" +"Table note 2 with format string\n"; + +TEST_BEGIN(test_table_printf) { + assert_emit_output(&emit_table_printf, table_printf_json, + table_printf_table); +} +TEST_END + +static void emit_nested_dict(emitter_t *emitter) { + int val = 123; + emitter_begin(emitter); + emitter_dict_begin(emitter, "json1", "Dict 1"); + emitter_dict_begin(emitter, "json2", "Dict 2"); + emitter_kv(emitter, "primitive", "A primitive", emitter_type_int, &val); + emitter_dict_end(emitter); /* Close 2 */ + emitter_dict_begin(emitter, "json3", "Dict 3"); + emitter_dict_end(emitter); /* Close 3 */ + emitter_dict_end(emitter); /* Close 1 */ + emitter_dict_begin(emitter, "json4", "Dict 4"); + emitter_kv(emitter, "primitive", "Another primitive", + emitter_type_int, &val); + emitter_dict_end(emitter); /* Close 4 */ + emitter_end(emitter); +} + +static const char *nested_object_json = +"{\n" +"\t\"json1\": {\n" +"\t\t\"json2\": {\n" +"\t\t\t\"primitive\": 123\n" +"\t\t},\n" +"\t\t\"json3\": {\n" +"\t\t}\n" +"\t},\n" +"\t\"json4\": {\n" +"\t\t\"primitive\": 123\n" +"\t}\n" +"}\n"; + +static const char *nested_object_table = +"Dict 1\n" +" Dict 2\n" +" A primitive: 123\n" +" Dict 3\n" +"Dict 4\n" +" Another primitive: 123\n"; + +TEST_BEGIN(test_nested_dict) { + assert_emit_output(&emit_nested_dict, nested_object_json, + nested_object_table); +} +TEST_END + +static void +emit_types(emitter_t *emitter) { + bool b = false; + int i = -123; + unsigned u = 123; + ssize_t zd = -456; + size_t zu = 456; + const char *str = "string"; + uint32_t u32 = 789; + uint64_t u64 = 10000000000ULL; + + emitter_begin(emitter); + emitter_kv(emitter, "k1", "K1", emitter_type_bool, &b); + emitter_kv(emitter, "k2", "K2", emitter_type_int, &i); + emitter_kv(emitter, "k3", "K3", emitter_type_unsigned, &u); + emitter_kv(emitter, "k4", "K4", emitter_type_ssize, &zd); + emitter_kv(emitter, "k5", "K5", emitter_type_size, &zu); + emitter_kv(emitter, "k6", "K6", emitter_type_string, &str); + emitter_kv(emitter, "k7", "K7", emitter_type_uint32, &u32); + emitter_kv(emitter, "k8", "K8", emitter_type_uint64, &u64); + /* + * We don't test the title type, since it's only used for tables. It's + * tested in the emitter_table_row tests. + */ + emitter_end(emitter); +} + +static const char *types_json = +"{\n" +"\t\"k1\": false,\n" +"\t\"k2\": -123,\n" +"\t\"k3\": 123,\n" +"\t\"k4\": -456,\n" +"\t\"k5\": 456,\n" +"\t\"k6\": \"string\",\n" +"\t\"k7\": 789,\n" +"\t\"k8\": 10000000000\n" +"}\n"; + +static const char *types_table = +"K1: false\n" +"K2: -123\n" +"K3: 123\n" +"K4: -456\n" +"K5: 456\n" +"K6: \"string\"\n" +"K7: 789\n" +"K8: 10000000000\n"; + +TEST_BEGIN(test_types) { + assert_emit_output(&emit_types, types_json, types_table); +} +TEST_END + +static void +emit_modal(emitter_t *emitter) { + int val = 123; + emitter_begin(emitter); + emitter_dict_begin(emitter, "j0", "T0"); + emitter_json_key(emitter, "j1"); + emitter_json_object_begin(emitter); + emitter_kv(emitter, "i1", "I1", emitter_type_int, &val); + emitter_json_kv(emitter, "i2", emitter_type_int, &val); + emitter_table_kv(emitter, "I3", emitter_type_int, &val); + emitter_table_dict_begin(emitter, "T1"); + emitter_kv(emitter, "i4", "I4", emitter_type_int, &val); + emitter_json_object_end(emitter); /* Close j1 */ + emitter_kv(emitter, "i5", "I5", emitter_type_int, &val); + emitter_table_dict_end(emitter); /* Close T1 */ + emitter_kv(emitter, "i6", "I6", emitter_type_int, &val); + emitter_dict_end(emitter); /* Close j0 / T0 */ + emitter_end(emitter); +} + +const char *modal_json = +"{\n" +"\t\"j0\": {\n" +"\t\t\"j1\": {\n" +"\t\t\t\"i1\": 123,\n" +"\t\t\t\"i2\": 123,\n" +"\t\t\t\"i4\": 123\n" +"\t\t},\n" +"\t\t\"i5\": 123,\n" +"\t\t\"i6\": 123\n" +"\t}\n" +"}\n"; + +const char *modal_table = +"T0\n" +" I1: 123\n" +" I3: 123\n" +" T1\n" +" I4: 123\n" +" I5: 123\n" +" I6: 123\n"; + +TEST_BEGIN(test_modal) { + assert_emit_output(&emit_modal, modal_json, modal_table); +} +TEST_END + +static void +emit_json_arr(emitter_t *emitter) { + int ival = 123; + + emitter_begin(emitter); + emitter_json_key(emitter, "dict"); + emitter_json_object_begin(emitter); + emitter_json_key(emitter, "arr"); + emitter_json_array_begin(emitter); + emitter_json_object_begin(emitter); + emitter_json_kv(emitter, "foo", emitter_type_int, &ival); + emitter_json_object_end(emitter); /* Close arr[0] */ + /* arr[1] and arr[2] are primitives. */ + emitter_json_value(emitter, emitter_type_int, &ival); + emitter_json_value(emitter, emitter_type_int, &ival); + emitter_json_object_begin(emitter); + emitter_json_kv(emitter, "bar", emitter_type_int, &ival); + emitter_json_kv(emitter, "baz", emitter_type_int, &ival); + emitter_json_object_end(emitter); /* Close arr[3]. */ + emitter_json_array_end(emitter); /* Close arr. */ + emitter_json_object_end(emitter); /* Close dict. */ + emitter_end(emitter); +} + +static const char *json_array_json = +"{\n" +"\t\"dict\": {\n" +"\t\t\"arr\": [\n" +"\t\t\t{\n" +"\t\t\t\t\"foo\": 123\n" +"\t\t\t},\n" +"\t\t\t123,\n" +"\t\t\t123,\n" +"\t\t\t{\n" +"\t\t\t\t\"bar\": 123,\n" +"\t\t\t\t\"baz\": 123\n" +"\t\t\t}\n" +"\t\t]\n" +"\t}\n" +"}\n"; + +static const char *json_array_table = ""; + +TEST_BEGIN(test_json_arr) { + assert_emit_output(&emit_json_arr, json_array_json, json_array_table); +} +TEST_END + +static void +emit_json_nested_array(emitter_t *emitter) { + int ival = 123; + char *sval = "foo"; + emitter_begin(emitter); + emitter_json_array_begin(emitter); + emitter_json_array_begin(emitter); + emitter_json_value(emitter, emitter_type_int, &ival); + emitter_json_value(emitter, emitter_type_string, &sval); + emitter_json_value(emitter, emitter_type_int, &ival); + emitter_json_value(emitter, emitter_type_string, &sval); + emitter_json_array_end(emitter); + emitter_json_array_begin(emitter); + emitter_json_value(emitter, emitter_type_int, &ival); + emitter_json_array_end(emitter); + emitter_json_array_begin(emitter); + emitter_json_value(emitter, emitter_type_string, &sval); + emitter_json_value(emitter, emitter_type_int, &ival); + emitter_json_array_end(emitter); + emitter_json_array_begin(emitter); + emitter_json_array_end(emitter); + emitter_json_array_end(emitter); + emitter_end(emitter); +} + +static const char *json_nested_array_json = +"{\n" +"\t[\n" +"\t\t[\n" +"\t\t\t123,\n" +"\t\t\t\"foo\",\n" +"\t\t\t123,\n" +"\t\t\t\"foo\"\n" +"\t\t],\n" +"\t\t[\n" +"\t\t\t123\n" +"\t\t],\n" +"\t\t[\n" +"\t\t\t\"foo\",\n" +"\t\t\t123\n" +"\t\t],\n" +"\t\t[\n" +"\t\t]\n" +"\t]\n" +"}\n"; + +TEST_BEGIN(test_json_nested_arr) { + assert_emit_output(&emit_json_nested_array, json_nested_array_json, + json_array_table); +} +TEST_END + +static void +emit_table_row(emitter_t *emitter) { + emitter_begin(emitter); + emitter_row_t row; + emitter_col_t abc = {emitter_justify_left, 10, emitter_type_title, {0}, {0, 0}}; + abc.str_val = "ABC title"; + emitter_col_t def = {emitter_justify_right, 15, emitter_type_title, {0}, {0, 0}}; + def.str_val = "DEF title"; + emitter_col_t ghi = {emitter_justify_right, 5, emitter_type_title, {0}, {0, 0}}; + ghi.str_val = "GHI"; + + emitter_row_init(&row); + emitter_col_init(&abc, &row); + emitter_col_init(&def, &row); + emitter_col_init(&ghi, &row); + + emitter_table_row(emitter, &row); + + abc.type = emitter_type_int; + def.type = emitter_type_bool; + ghi.type = emitter_type_int; + + abc.int_val = 123; + def.bool_val = true; + ghi.int_val = 456; + emitter_table_row(emitter, &row); + + abc.int_val = 789; + def.bool_val = false; + ghi.int_val = 1011; + emitter_table_row(emitter, &row); + + abc.type = emitter_type_string; + abc.str_val = "a string"; + def.bool_val = false; + ghi.type = emitter_type_title; + ghi.str_val = "ghi"; + emitter_table_row(emitter, &row); + + emitter_end(emitter); +} + +static const char *table_row_json = +"{\n" +"}\n"; + +static const char *table_row_table = +"ABC title DEF title GHI\n" +"123 true 456\n" +"789 false 1011\n" +"\"a string\" false ghi\n"; + +TEST_BEGIN(test_table_row) { + assert_emit_output(&emit_table_row, table_row_json, table_row_table); +} +TEST_END + +int +main(void) { + return test_no_reentrancy( + test_dict, + test_table_printf, + test_nested_dict, + test_types, + test_modal, + test_json_arr, + test_json_nested_arr, + test_table_row); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/fork.c b/kbe/src/lib/dependencies/jemalloc/test/unit/fork.c index afe2214139..b1690750ad 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/fork.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/fork.c @@ -4,6 +4,30 @@ #include #endif +#ifndef _WIN32 +static void +wait_for_child_exit(int pid) { + int status; + while (true) { + if (waitpid(pid, &status, 0) == -1) { + test_fail("Unexpected waitpid() failure."); + } + if (WIFSIGNALED(status)) { + test_fail("Unexpected child termination due to " + "signal %d", WTERMSIG(status)); + break; + } + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) { + test_fail("Unexpected child exit value %d", + WEXITSTATUS(status)); + } + break; + } + } +} +#endif + TEST_BEGIN(test_fork) { #ifndef _WIN32 void *p; @@ -40,26 +64,67 @@ TEST_BEGIN(test_fork) { /* Child. */ _exit(0); } else { - int status; + wait_for_child_exit(pid); + } +#else + test_skip("fork(2) is irrelevant to Windows"); +#endif +} +TEST_END - /* Parent. */ - while (true) { - if (waitpid(pid, &status, 0) == -1) { - test_fail("Unexpected waitpid() failure"); - } - if (WIFSIGNALED(status)) { - test_fail("Unexpected child termination due to " - "signal %d", WTERMSIG(status)); - break; - } - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) { - test_fail( - "Unexpected child exit value %d", - WEXITSTATUS(status)); - } - break; - } +#ifndef _WIN32 +static void * +do_fork_thd(void *arg) { + malloc(1); + int pid = fork(); + if (pid == -1) { + /* Error. */ + test_fail("Unexpected fork() failure"); + } else if (pid == 0) { + /* Child. */ + char *args[] = {"true", NULL}; + execvp(args[0], args); + test_fail("Exec failed"); + } else { + /* Parent */ + wait_for_child_exit(pid); + } + return NULL; +} +#endif + +#ifndef _WIN32 +static void +do_test_fork_multithreaded() { + thd_t child; + thd_create(&child, do_fork_thd, NULL); + do_fork_thd(NULL); + thd_join(child, NULL); +} +#endif + +TEST_BEGIN(test_fork_multithreaded) { +#ifndef _WIN32 + /* + * We've seen bugs involving hanging on arenas_lock (though the same + * class of bugs can happen on any mutex). The bugs are intermittent + * though, so we want to run the test multiple times. Since we hold the + * arenas lock only early in the process lifetime, we can't just run + * this test in a loop (since, after all the arenas are initialized, we + * won't acquire arenas_lock any further). We therefore repeat the test + * with multiple processes. + */ + for (int i = 0; i < 100; i++) { + int pid = fork(); + if (pid == -1) { + /* Error. */ + test_fail("Unexpected fork() failure,"); + } else if (pid == 0) { + /* Child. */ + do_test_fork_multithreaded(); + _exit(0); + } else { + wait_for_child_exit(pid); } } #else @@ -70,6 +135,7 @@ TEST_END int main(void) { - return test( - test_fork); + return test_no_reentrancy( + test_fork, + test_fork_multithreaded); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/hook.c b/kbe/src/lib/dependencies/jemalloc/test/unit/hook.c new file mode 100644 index 0000000000..72fcc433cc --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/hook.c @@ -0,0 +1,580 @@ +#include "test/jemalloc_test.h" + +#include "jemalloc/internal/hook.h" + +static void *arg_extra; +static int arg_type; +static void *arg_result; +static void *arg_address; +static size_t arg_old_usize; +static size_t arg_new_usize; +static uintptr_t arg_result_raw; +static uintptr_t arg_args_raw[4]; + +static int call_count = 0; + +static void +reset_args() { + arg_extra = NULL; + arg_type = 12345; + arg_result = NULL; + arg_address = NULL; + arg_old_usize = 0; + arg_new_usize = 0; + arg_result_raw = 0; + memset(arg_args_raw, 77, sizeof(arg_args_raw)); +} + +static void +alloc_free_size(size_t sz) { + void *ptr = mallocx(1, 0); + free(ptr); + ptr = mallocx(1, 0); + free(ptr); + ptr = mallocx(1, MALLOCX_TCACHE_NONE); + dallocx(ptr, MALLOCX_TCACHE_NONE); +} + +/* + * We want to support a degree of user reentrancy. This tests a variety of + * allocation scenarios. + */ +static void +be_reentrant() { + /* Let's make sure the tcache is non-empty if enabled. */ + alloc_free_size(1); + alloc_free_size(1024); + alloc_free_size(64 * 1024); + alloc_free_size(256 * 1024); + alloc_free_size(1024 * 1024); + + /* Some reallocation. */ + void *ptr = mallocx(129, 0); + ptr = rallocx(ptr, 130, 0); + free(ptr); + + ptr = mallocx(2 * 1024 * 1024, 0); + free(ptr); + ptr = mallocx(1 * 1024 * 1024, 0); + ptr = rallocx(ptr, 2 * 1024 * 1024, 0); + free(ptr); + + ptr = mallocx(1, 0); + ptr = rallocx(ptr, 1000, 0); + free(ptr); +} + +static void +set_args_raw(uintptr_t *args_raw, int nargs) { + memcpy(arg_args_raw, args_raw, sizeof(uintptr_t) * nargs); +} + +static void +assert_args_raw(uintptr_t *args_raw_expected, int nargs) { + int cmp = memcmp(args_raw_expected, arg_args_raw, + sizeof(uintptr_t) * nargs); + assert_d_eq(cmp, 0, "Raw args mismatch"); +} + +static void +reset() { + call_count = 0; + reset_args(); +} + +static void +test_alloc_hook(void *extra, hook_alloc_t type, void *result, + uintptr_t result_raw, uintptr_t args_raw[3]) { + call_count++; + arg_extra = extra; + arg_type = (int)type; + arg_result = result; + arg_result_raw = result_raw; + set_args_raw(args_raw, 3); + be_reentrant(); +} + +static void +test_dalloc_hook(void *extra, hook_dalloc_t type, void *address, + uintptr_t args_raw[3]) { + call_count++; + arg_extra = extra; + arg_type = (int)type; + arg_address = address; + set_args_raw(args_raw, 3); + be_reentrant(); +} + +static void +test_expand_hook(void *extra, hook_expand_t type, void *address, + size_t old_usize, size_t new_usize, uintptr_t result_raw, + uintptr_t args_raw[4]) { + call_count++; + arg_extra = extra; + arg_type = (int)type; + arg_address = address; + arg_old_usize = old_usize; + arg_new_usize = new_usize; + arg_result_raw = result_raw; + set_args_raw(args_raw, 4); + be_reentrant(); +} + +TEST_BEGIN(test_hooks_basic) { + /* Just verify that the record their arguments correctly. */ + hooks_t hooks = { + &test_alloc_hook, &test_dalloc_hook, &test_expand_hook, + (void *)111}; + void *handle = hook_install(TSDN_NULL, &hooks); + uintptr_t args_raw[4] = {10, 20, 30, 40}; + + /* Alloc */ + reset_args(); + hook_invoke_alloc(hook_alloc_posix_memalign, (void *)222, 333, + args_raw); + assert_ptr_eq(arg_extra, (void *)111, "Passed wrong user pointer"); + assert_d_eq((int)hook_alloc_posix_memalign, arg_type, + "Passed wrong alloc type"); + assert_ptr_eq((void *)222, arg_result, "Passed wrong result address"); + assert_u64_eq(333, arg_result_raw, "Passed wrong result"); + assert_args_raw(args_raw, 3); + + /* Dalloc */ + reset_args(); + hook_invoke_dalloc(hook_dalloc_sdallocx, (void *)222, args_raw); + assert_d_eq((int)hook_dalloc_sdallocx, arg_type, + "Passed wrong dalloc type"); + assert_ptr_eq((void *)111, arg_extra, "Passed wrong user pointer"); + assert_ptr_eq((void *)222, arg_address, "Passed wrong address"); + assert_args_raw(args_raw, 3); + + /* Expand */ + reset_args(); + hook_invoke_expand(hook_expand_xallocx, (void *)222, 333, 444, 555, + args_raw); + assert_d_eq((int)hook_expand_xallocx, arg_type, + "Passed wrong expand type"); + assert_ptr_eq((void *)111, arg_extra, "Passed wrong user pointer"); + assert_ptr_eq((void *)222, arg_address, "Passed wrong address"); + assert_zu_eq(333, arg_old_usize, "Passed wrong old usize"); + assert_zu_eq(444, arg_new_usize, "Passed wrong new usize"); + assert_zu_eq(555, arg_result_raw, "Passed wrong result"); + assert_args_raw(args_raw, 4); + + hook_remove(TSDN_NULL, handle); +} +TEST_END + +TEST_BEGIN(test_hooks_null) { + /* Null hooks should be ignored, not crash. */ + hooks_t hooks1 = {NULL, NULL, NULL, NULL}; + hooks_t hooks2 = {&test_alloc_hook, NULL, NULL, NULL}; + hooks_t hooks3 = {NULL, &test_dalloc_hook, NULL, NULL}; + hooks_t hooks4 = {NULL, NULL, &test_expand_hook, NULL}; + + void *handle1 = hook_install(TSDN_NULL, &hooks1); + void *handle2 = hook_install(TSDN_NULL, &hooks2); + void *handle3 = hook_install(TSDN_NULL, &hooks3); + void *handle4 = hook_install(TSDN_NULL, &hooks4); + + assert_ptr_ne(handle1, NULL, "Hook installation failed"); + assert_ptr_ne(handle2, NULL, "Hook installation failed"); + assert_ptr_ne(handle3, NULL, "Hook installation failed"); + assert_ptr_ne(handle4, NULL, "Hook installation failed"); + + uintptr_t args_raw[4] = {10, 20, 30, 40}; + + call_count = 0; + hook_invoke_alloc(hook_alloc_malloc, NULL, 0, args_raw); + assert_d_eq(call_count, 1, "Called wrong number of times"); + + call_count = 0; + hook_invoke_dalloc(hook_dalloc_free, NULL, args_raw); + assert_d_eq(call_count, 1, "Called wrong number of times"); + + call_count = 0; + hook_invoke_expand(hook_expand_realloc, NULL, 0, 0, 0, args_raw); + assert_d_eq(call_count, 1, "Called wrong number of times"); + + hook_remove(TSDN_NULL, handle1); + hook_remove(TSDN_NULL, handle2); + hook_remove(TSDN_NULL, handle3); + hook_remove(TSDN_NULL, handle4); +} +TEST_END + +TEST_BEGIN(test_hooks_remove) { + hooks_t hooks = {&test_alloc_hook, NULL, NULL, NULL}; + void *handle = hook_install(TSDN_NULL, &hooks); + assert_ptr_ne(handle, NULL, "Hook installation failed"); + call_count = 0; + uintptr_t args_raw[4] = {10, 20, 30, 40}; + hook_invoke_alloc(hook_alloc_malloc, NULL, 0, args_raw); + assert_d_eq(call_count, 1, "Hook not invoked"); + + call_count = 0; + hook_remove(TSDN_NULL, handle); + hook_invoke_alloc(hook_alloc_malloc, NULL, 0, NULL); + assert_d_eq(call_count, 0, "Hook invoked after removal"); + +} +TEST_END + +TEST_BEGIN(test_hooks_alloc_simple) { + /* "Simple" in the sense that we're not in a realloc variant. */ + hooks_t hooks = {&test_alloc_hook, NULL, NULL, (void *)123}; + void *handle = hook_install(TSDN_NULL, &hooks); + assert_ptr_ne(handle, NULL, "Hook installation failed"); + + /* Stop malloc from being optimized away. */ + volatile int err; + void *volatile ptr; + + /* malloc */ + reset(); + ptr = malloc(1); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_malloc, "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); + free(ptr); + + /* posix_memalign */ + reset(); + err = posix_memalign((void **)&ptr, 1024, 1); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_posix_memalign, + "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)err, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)&ptr, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)1024, arg_args_raw[1], "Wrong argument"); + assert_u64_eq((uintptr_t)1, arg_args_raw[2], "Wrong argument"); + free(ptr); + + /* aligned_alloc */ + reset(); + ptr = aligned_alloc(1024, 1); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_aligned_alloc, + "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)1024, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); + free(ptr); + + /* calloc */ + reset(); + ptr = calloc(11, 13); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_calloc, "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)11, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)13, arg_args_raw[1], "Wrong argument"); + free(ptr); + + /* memalign */ +#ifdef JEMALLOC_OVERRIDE_MEMALIGN + reset(); + ptr = memalign(1024, 1); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_memalign, "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)1024, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); + free(ptr); +#endif /* JEMALLOC_OVERRIDE_MEMALIGN */ + + /* valloc */ +#ifdef JEMALLOC_OVERRIDE_VALLOC + reset(); + ptr = valloc(1); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_valloc, "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); + free(ptr); +#endif /* JEMALLOC_OVERRIDE_VALLOC */ + + /* mallocx */ + reset(); + ptr = mallocx(1, MALLOCX_LG_ALIGN(10)); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_mallocx, "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)MALLOCX_LG_ALIGN(10), arg_args_raw[1], + "Wrong flags"); + free(ptr); + + hook_remove(TSDN_NULL, handle); +} +TEST_END + +TEST_BEGIN(test_hooks_dalloc_simple) { + /* "Simple" in the sense that we're not in a realloc variant. */ + hooks_t hooks = {NULL, &test_dalloc_hook, NULL, (void *)123}; + void *handle = hook_install(TSDN_NULL, &hooks); + assert_ptr_ne(handle, NULL, "Hook installation failed"); + + void *volatile ptr; + + /* free() */ + reset(); + ptr = malloc(1); + free(ptr); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_dalloc_free, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); + + /* dallocx() */ + reset(); + ptr = malloc(1); + dallocx(ptr, MALLOCX_TCACHE_NONE); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_dalloc_dallocx, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); + assert_u64_eq((uintptr_t)MALLOCX_TCACHE_NONE, arg_args_raw[1], + "Wrong raw arg"); + + /* sdallocx() */ + reset(); + ptr = malloc(1); + sdallocx(ptr, 1, MALLOCX_TCACHE_NONE); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_dalloc_sdallocx, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); + assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong raw arg"); + assert_u64_eq((uintptr_t)MALLOCX_TCACHE_NONE, arg_args_raw[2], + "Wrong raw arg"); + + hook_remove(TSDN_NULL, handle); +} +TEST_END + +TEST_BEGIN(test_hooks_expand_simple) { + /* "Simple" in the sense that we're not in a realloc variant. */ + hooks_t hooks = {NULL, NULL, &test_expand_hook, (void *)123}; + void *handle = hook_install(TSDN_NULL, &hooks); + assert_ptr_ne(handle, NULL, "Hook installation failed"); + + void *volatile ptr; + + /* xallocx() */ + reset(); + ptr = malloc(1); + size_t new_usize = xallocx(ptr, 100, 200, MALLOCX_TCACHE_NONE); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_expand_xallocx, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong pointer expanded"); + assert_u64_eq(arg_old_usize, nallocx(1, 0), "Wrong old usize"); + assert_u64_eq(arg_new_usize, sallocx(ptr, 0), "Wrong new usize"); + assert_u64_eq(new_usize, arg_result_raw, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong arg"); + assert_u64_eq(100, arg_args_raw[1], "Wrong arg"); + assert_u64_eq(200, arg_args_raw[2], "Wrong arg"); + assert_u64_eq(MALLOCX_TCACHE_NONE, arg_args_raw[3], "Wrong arg"); + + hook_remove(TSDN_NULL, handle); +} +TEST_END + +TEST_BEGIN(test_hooks_realloc_as_malloc_or_free) { + hooks_t hooks = {&test_alloc_hook, &test_dalloc_hook, + &test_expand_hook, (void *)123}; + void *handle = hook_install(TSDN_NULL, &hooks); + assert_ptr_ne(handle, NULL, "Hook installation failed"); + + void *volatile ptr; + + /* realloc(NULL, size) as malloc */ + reset(); + ptr = realloc(NULL, 1); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); + free(ptr); + + /* realloc(ptr, 0) as free */ + ptr = malloc(1); + reset(); + realloc(ptr, 0); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_dalloc_realloc, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); + assert_u64_eq((uintptr_t)0, arg_args_raw[1], "Wrong raw arg"); + + /* realloc(NULL, 0) as malloc(0) */ + reset(); + ptr = realloc(NULL, 0); + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type"); + assert_ptr_eq(ptr, arg_result, "Wrong result"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)0, arg_args_raw[1], "Wrong argument"); + free(ptr); + + hook_remove(TSDN_NULL, handle); +} +TEST_END + +static void +do_realloc_test(void *(*ralloc)(void *, size_t, int), int flags, + int expand_type, int dalloc_type) { + hooks_t hooks = {&test_alloc_hook, &test_dalloc_hook, + &test_expand_hook, (void *)123}; + void *handle = hook_install(TSDN_NULL, &hooks); + assert_ptr_ne(handle, NULL, "Hook installation failed"); + + void *volatile ptr; + void *volatile ptr2; + + /* Realloc in-place, small. */ + ptr = malloc(129); + reset(); + ptr2 = ralloc(ptr, 130, flags); + assert_ptr_eq(ptr, ptr2, "Small realloc moved"); + + assert_d_eq(call_count, 1, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, expand_type, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong address"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)130, arg_args_raw[1], "Wrong argument"); + free(ptr); + + /* + * Realloc in-place, large. Since we can't guarantee the large case + * across all platforms, we stay resilient to moving results. + */ + ptr = malloc(2 * 1024 * 1024); + free(ptr); + ptr2 = malloc(1 * 1024 * 1024); + reset(); + ptr = ralloc(ptr2, 2 * 1024 * 1024, flags); + /* ptr is the new address, ptr2 is the old address. */ + if (ptr == ptr2) { + assert_d_eq(call_count, 1, "Hook not called"); + assert_d_eq(arg_type, expand_type, "Wrong hook type"); + } else { + assert_d_eq(call_count, 2, "Wrong hooks called"); + assert_ptr_eq(ptr, arg_result, "Wrong address"); + assert_d_eq(arg_type, dalloc_type, "Wrong hook type"); + } + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_ptr_eq(ptr2, arg_address, "Wrong address"); + assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)ptr2, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)2 * 1024 * 1024, arg_args_raw[1], + "Wrong argument"); + free(ptr); + + /* Realloc with move, small. */ + ptr = malloc(8); + reset(); + ptr2 = ralloc(ptr, 128, flags); + assert_ptr_ne(ptr, ptr2, "Small realloc didn't move"); + + assert_d_eq(call_count, 2, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, dalloc_type, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong address"); + assert_ptr_eq(ptr2, arg_result, "Wrong address"); + assert_u64_eq((uintptr_t)ptr2, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)128, arg_args_raw[1], "Wrong argument"); + free(ptr2); + + /* Realloc with move, large. */ + ptr = malloc(1); + reset(); + ptr2 = ralloc(ptr, 2 * 1024 * 1024, flags); + assert_ptr_ne(ptr, ptr2, "Large realloc didn't move"); + + assert_d_eq(call_count, 2, "Hook not called"); + assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); + assert_d_eq(arg_type, dalloc_type, "Wrong hook type"); + assert_ptr_eq(ptr, arg_address, "Wrong address"); + assert_ptr_eq(ptr2, arg_result, "Wrong address"); + assert_u64_eq((uintptr_t)ptr2, (uintptr_t)arg_result_raw, + "Wrong raw result"); + assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); + assert_u64_eq((uintptr_t)2 * 1024 * 1024, arg_args_raw[1], + "Wrong argument"); + free(ptr2); + + hook_remove(TSDN_NULL, handle); +} + +static void * +realloc_wrapper(void *ptr, size_t size, UNUSED int flags) { + return realloc(ptr, size); +} + +TEST_BEGIN(test_hooks_realloc) { + do_realloc_test(&realloc_wrapper, 0, hook_expand_realloc, + hook_dalloc_realloc); +} +TEST_END + +TEST_BEGIN(test_hooks_rallocx) { + do_realloc_test(&rallocx, MALLOCX_TCACHE_NONE, hook_expand_rallocx, + hook_dalloc_rallocx); +} +TEST_END + +int +main(void) { + /* We assert on call counts. */ + return test_no_reentrancy( + test_hooks_basic, + test_hooks_null, + test_hooks_remove, + test_hooks_alloc_simple, + test_hooks_dalloc_simple, + test_hooks_expand_simple, + test_hooks_realloc_as_malloc_or_free, + test_hooks_realloc, + test_hooks_rallocx); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/huge.c b/kbe/src/lib/dependencies/jemalloc/test/unit/huge.c new file mode 100644 index 0000000000..ab72cf0071 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/huge.c @@ -0,0 +1,108 @@ +#include "test/jemalloc_test.h" + +/* Threshold: 2 << 20 = 2097152. */ +const char *malloc_conf = "oversize_threshold:2097152"; + +#define HUGE_SZ (2 << 20) +#define SMALL_SZ (8) + +TEST_BEGIN(huge_bind_thread) { + unsigned arena1, arena2; + size_t sz = sizeof(unsigned); + + /* Bind to a manual arena. */ + assert_d_eq(mallctl("arenas.create", &arena1, &sz, NULL, 0), 0, + "Failed to create arena"); + assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena1, + sizeof(arena1)), 0, "Fail to bind thread"); + + void *ptr = mallocx(HUGE_SZ, 0); + assert_ptr_not_null(ptr, "Fail to allocate huge size"); + assert_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, + sizeof(ptr)), 0, "Unexpected mallctl() failure"); + assert_u_eq(arena1, arena2, "Wrong arena used after binding"); + dallocx(ptr, 0); + + /* Switch back to arena 0. */ + test_skip_if(have_percpu_arena && + PERCPU_ARENA_ENABLED(opt_percpu_arena)); + arena2 = 0; + assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena2, + sizeof(arena2)), 0, "Fail to bind thread"); + ptr = mallocx(SMALL_SZ, MALLOCX_TCACHE_NONE); + assert_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, + sizeof(ptr)), 0, "Unexpected mallctl() failure"); + assert_u_eq(arena2, 0, "Wrong arena used after binding"); + dallocx(ptr, MALLOCX_TCACHE_NONE); + + /* Then huge allocation should use the huge arena. */ + ptr = mallocx(HUGE_SZ, 0); + assert_ptr_not_null(ptr, "Fail to allocate huge size"); + assert_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, + sizeof(ptr)), 0, "Unexpected mallctl() failure"); + assert_u_ne(arena2, 0, "Wrong arena used after binding"); + assert_u_ne(arena1, arena2, "Wrong arena used after binding"); + dallocx(ptr, 0); +} +TEST_END + +TEST_BEGIN(huge_mallocx) { + unsigned arena1, arena2; + size_t sz = sizeof(unsigned); + + assert_d_eq(mallctl("arenas.create", &arena1, &sz, NULL, 0), 0, + "Failed to create arena"); + void *huge = mallocx(HUGE_SZ, MALLOCX_ARENA(arena1)); + assert_ptr_not_null(huge, "Fail to allocate huge size"); + assert_d_eq(mallctl("arenas.lookup", &arena2, &sz, &huge, + sizeof(huge)), 0, "Unexpected mallctl() failure"); + assert_u_eq(arena1, arena2, "Wrong arena used for mallocx"); + dallocx(huge, MALLOCX_ARENA(arena1)); + + void *huge2 = mallocx(HUGE_SZ, 0); + assert_ptr_not_null(huge, "Fail to allocate huge size"); + assert_d_eq(mallctl("arenas.lookup", &arena2, &sz, &huge2, + sizeof(huge2)), 0, "Unexpected mallctl() failure"); + assert_u_ne(arena1, arena2, + "Huge allocation should not come from the manual arena."); + assert_u_ne(arena2, 0, + "Huge allocation should not come from the arena 0."); + dallocx(huge2, 0); +} +TEST_END + +TEST_BEGIN(huge_allocation) { + unsigned arena1, arena2; + + void *ptr = mallocx(HUGE_SZ, 0); + assert_ptr_not_null(ptr, "Fail to allocate huge size"); + size_t sz = sizeof(unsigned); + assert_d_eq(mallctl("arenas.lookup", &arena1, &sz, &ptr, sizeof(ptr)), + 0, "Unexpected mallctl() failure"); + assert_u_gt(arena1, 0, "Huge allocation should not come from arena 0"); + dallocx(ptr, 0); + + ptr = mallocx(HUGE_SZ >> 1, 0); + assert_ptr_not_null(ptr, "Fail to allocate half huge size"); + assert_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, + sizeof(ptr)), 0, "Unexpected mallctl() failure"); + assert_u_ne(arena1, arena2, "Wrong arena used for half huge"); + dallocx(ptr, 0); + + ptr = mallocx(SMALL_SZ, MALLOCX_TCACHE_NONE); + assert_ptr_not_null(ptr, "Fail to allocate small size"); + assert_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, + sizeof(ptr)), 0, "Unexpected mallctl() failure"); + assert_u_ne(arena1, arena2, + "Huge and small should be from different arenas"); + dallocx(ptr, 0); +} +TEST_END + +int +main(void) { + return test( + huge_allocation, + huge_mallocx, + huge_bind_thread); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/junk.c b/kbe/src/lib/dependencies/jemalloc/test/unit/junk.c index fd0e65b1cd..57e3ad431a 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/junk.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/junk.c @@ -15,7 +15,7 @@ watch_junking(void *p) { } static void -arena_dalloc_junk_small_intercept(void *ptr, const arena_bin_info_t *bin_info) { +arena_dalloc_junk_small_intercept(void *ptr, const bin_info_t *bin_info) { size_t i; arena_dalloc_junk_small_orig(ptr, bin_info); @@ -123,13 +123,13 @@ test_junk(size_t sz_min, size_t sz_max) { TEST_BEGIN(test_junk_small) { test_skip_if(!config_fill); - test_junk(1, SMALL_MAXCLASS-1); + test_junk(1, SC_SMALL_MAXCLASS - 1); } TEST_END TEST_BEGIN(test_junk_large) { test_skip_if(!config_fill); - test_junk(SMALL_MAXCLASS+1, (1U << (LG_LARGE_MINCLASS+1))); + test_junk(SC_SMALL_MAXCLASS + 1, (1U << (SC_LG_LARGE_MINCLASS + 1))); } TEST_END diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/log.c b/kbe/src/lib/dependencies/jemalloc/test/unit/log.c new file mode 100644 index 0000000000..a52bd737d4 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/log.c @@ -0,0 +1,193 @@ +#include "test/jemalloc_test.h" + +#include "jemalloc/internal/log.h" + +static void +expect_no_logging(const char *names) { + log_var_t log_l1 = LOG_VAR_INIT("l1"); + log_var_t log_l2 = LOG_VAR_INIT("l2"); + log_var_t log_l2_a = LOG_VAR_INIT("l2.a"); + + strcpy(log_var_names, names); + + int count = 0; + + for (int i = 0; i < 10; i++) { + log_do_begin(log_l1) + count++; + log_do_end(log_l1) + + log_do_begin(log_l2) + count++; + log_do_end(log_l2) + + log_do_begin(log_l2_a) + count++; + log_do_end(log_l2_a) + } + assert_d_eq(count, 0, "Disabled logging not ignored!"); +} + +TEST_BEGIN(test_log_disabled) { + test_skip_if(!config_log); + atomic_store_b(&log_init_done, true, ATOMIC_RELAXED); + expect_no_logging(""); + expect_no_logging("abc"); + expect_no_logging("a.b.c"); + expect_no_logging("l12"); + expect_no_logging("l123|a456|b789"); + expect_no_logging("|||"); +} +TEST_END + +TEST_BEGIN(test_log_enabled_direct) { + test_skip_if(!config_log); + atomic_store_b(&log_init_done, true, ATOMIC_RELAXED); + log_var_t log_l1 = LOG_VAR_INIT("l1"); + log_var_t log_l1_a = LOG_VAR_INIT("l1.a"); + log_var_t log_l2 = LOG_VAR_INIT("l2"); + + int count; + + count = 0; + strcpy(log_var_names, "l1"); + for (int i = 0; i < 10; i++) { + log_do_begin(log_l1) + count++; + log_do_end(log_l1) + } + assert_d_eq(count, 10, "Mis-logged!"); + + count = 0; + strcpy(log_var_names, "l1.a"); + for (int i = 0; i < 10; i++) { + log_do_begin(log_l1_a) + count++; + log_do_end(log_l1_a) + } + assert_d_eq(count, 10, "Mis-logged!"); + + count = 0; + strcpy(log_var_names, "l1.a|abc|l2|def"); + for (int i = 0; i < 10; i++) { + log_do_begin(log_l1_a) + count++; + log_do_end(log_l1_a) + + log_do_begin(log_l2) + count++; + log_do_end(log_l2) + } + assert_d_eq(count, 20, "Mis-logged!"); +} +TEST_END + +TEST_BEGIN(test_log_enabled_indirect) { + test_skip_if(!config_log); + atomic_store_b(&log_init_done, true, ATOMIC_RELAXED); + strcpy(log_var_names, "l0|l1|abc|l2.b|def"); + + /* On. */ + log_var_t log_l1 = LOG_VAR_INIT("l1"); + /* Off. */ + log_var_t log_l1a = LOG_VAR_INIT("l1a"); + /* On. */ + log_var_t log_l1_a = LOG_VAR_INIT("l1.a"); + /* Off. */ + log_var_t log_l2_a = LOG_VAR_INIT("l2.a"); + /* On. */ + log_var_t log_l2_b_a = LOG_VAR_INIT("l2.b.a"); + /* On. */ + log_var_t log_l2_b_b = LOG_VAR_INIT("l2.b.b"); + + /* 4 are on total, so should sum to 40. */ + int count = 0; + for (int i = 0; i < 10; i++) { + log_do_begin(log_l1) + count++; + log_do_end(log_l1) + + log_do_begin(log_l1a) + count++; + log_do_end(log_l1a) + + log_do_begin(log_l1_a) + count++; + log_do_end(log_l1_a) + + log_do_begin(log_l2_a) + count++; + log_do_end(log_l2_a) + + log_do_begin(log_l2_b_a) + count++; + log_do_end(log_l2_b_a) + + log_do_begin(log_l2_b_b) + count++; + log_do_end(log_l2_b_b) + } + + assert_d_eq(count, 40, "Mis-logged!"); +} +TEST_END + +TEST_BEGIN(test_log_enabled_global) { + test_skip_if(!config_log); + atomic_store_b(&log_init_done, true, ATOMIC_RELAXED); + strcpy(log_var_names, "abc|.|def"); + + log_var_t log_l1 = LOG_VAR_INIT("l1"); + log_var_t log_l2_a_a = LOG_VAR_INIT("l2.a.a"); + + int count = 0; + for (int i = 0; i < 10; i++) { + log_do_begin(log_l1) + count++; + log_do_end(log_l1) + + log_do_begin(log_l2_a_a) + count++; + log_do_end(log_l2_a_a) + } + assert_d_eq(count, 20, "Mis-logged!"); +} +TEST_END + +TEST_BEGIN(test_logs_if_no_init) { + test_skip_if(!config_log); + atomic_store_b(&log_init_done, false, ATOMIC_RELAXED); + + log_var_t l = LOG_VAR_INIT("definitely.not.enabled"); + + int count = 0; + for (int i = 0; i < 10; i++) { + log_do_begin(l) + count++; + log_do_end(l) + } + assert_d_eq(count, 0, "Logging shouldn't happen if not initialized."); +} +TEST_END + +/* + * This really just checks to make sure that this usage compiles; we don't have + * any test code to run. + */ +TEST_BEGIN(test_log_only_format_string) { + if (false) { + LOG("log_str", "No arguments follow this format string."); + } +} +TEST_END + +int +main(void) { + return test( + test_log_disabled, + test_log_enabled_direct, + test_log_enabled_indirect, + test_log_enabled_global, + test_logs_if_no_init, + test_log_only_format_string); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/mallctl.c b/kbe/src/lib/dependencies/jemalloc/test/unit/mallctl.c index f611654946..498f9e06ac 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/mallctl.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/mallctl.c @@ -1,5 +1,6 @@ #include "test/jemalloc_test.h" +#include "jemalloc/internal/hook.h" #include "jemalloc/internal/util.h" TEST_BEGIN(test_mallctl_errors) { @@ -157,10 +158,13 @@ TEST_BEGIN(test_mallctl_opt) { } while (0) TEST_MALLCTL_OPT(bool, abort, always); + TEST_MALLCTL_OPT(bool, abort_conf, always); + TEST_MALLCTL_OPT(const char *, metadata_thp, always); TEST_MALLCTL_OPT(bool, retain, always); TEST_MALLCTL_OPT(const char *, dss, always); TEST_MALLCTL_OPT(unsigned, narenas, always); TEST_MALLCTL_OPT(const char *, percpu_arena, always); + TEST_MALLCTL_OPT(size_t, oversize_threshold, always); TEST_MALLCTL_OPT(bool, background_thread, always); TEST_MALLCTL_OPT(ssize_t, dirty_decay_ms, always); TEST_MALLCTL_OPT(ssize_t, muzzy_decay_ms, always); @@ -170,7 +174,9 @@ TEST_BEGIN(test_mallctl_opt) { TEST_MALLCTL_OPT(bool, utrace, utrace); TEST_MALLCTL_OPT(bool, xmalloc, xmalloc); TEST_MALLCTL_OPT(bool, tcache, always); + TEST_MALLCTL_OPT(size_t, lg_extent_max_active_fit, always); TEST_MALLCTL_OPT(size_t, lg_tcache_max, always); + TEST_MALLCTL_OPT(const char *, thp, always); TEST_MALLCTL_OPT(bool, prof, prof); TEST_MALLCTL_OPT(const char *, prof_prefix, prof); TEST_MALLCTL_OPT(bool, prof_active, prof); @@ -330,12 +336,15 @@ TEST_BEGIN(test_thread_arena) { const char *opa; size_t sz = sizeof(opa); - assert_d_eq(mallctl("opt.percpu_arena", &opa, &sz, NULL, 0), 0, + assert_d_eq(mallctl("opt.percpu_arena", (void *)&opa, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); sz = sizeof(unsigned); assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); + if (opt_oversize_threshold != 0) { + narenas--; + } assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect"); if (strcmp(opa, "disabled") == 0) { @@ -554,6 +563,54 @@ TEST_BEGIN(test_arena_i_dss) { } TEST_END +TEST_BEGIN(test_arena_i_retain_grow_limit) { + size_t old_limit, new_limit, default_limit; + size_t mib[3]; + size_t miblen; + + bool retain_enabled; + size_t sz = sizeof(retain_enabled); + assert_d_eq(mallctl("opt.retain", &retain_enabled, &sz, NULL, 0), + 0, "Unexpected mallctl() failure"); + test_skip_if(!retain_enabled); + + sz = sizeof(default_limit); + miblen = sizeof(mib)/sizeof(size_t); + assert_d_eq(mallctlnametomib("arena.0.retain_grow_limit", mib, &miblen), + 0, "Unexpected mallctlnametomib() error"); + + assert_d_eq(mallctlbymib(mib, miblen, &default_limit, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + assert_zu_eq(default_limit, SC_LARGE_MAXCLASS, + "Unexpected default for retain_grow_limit"); + + new_limit = PAGE - 1; + assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &new_limit, + sizeof(new_limit)), EFAULT, "Unexpected mallctl() success"); + + new_limit = PAGE + 1; + assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &new_limit, + sizeof(new_limit)), 0, "Unexpected mallctl() failure"); + assert_d_eq(mallctlbymib(mib, miblen, &old_limit, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + assert_zu_eq(old_limit, PAGE, + "Unexpected value for retain_grow_limit"); + + /* Expect grow less than psize class 10. */ + new_limit = sz_pind2sz(10) - 1; + assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &new_limit, + sizeof(new_limit)), 0, "Unexpected mallctl() failure"); + assert_d_eq(mallctlbymib(mib, miblen, &old_limit, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + assert_zu_eq(old_limit, sz_pind2sz(9), + "Unexpected value for retain_grow_limit"); + + /* Restore to default. */ + assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &default_limit, + sizeof(default_limit)), 0, "Unexpected mallctl() failure"); +} +TEST_END + TEST_BEGIN(test_arenas_dirty_decay_ms) { ssize_t dirty_decay_ms, orig_dirty_decay_ms, prev_dirty_decay_ms; size_t sz = sizeof(ssize_t); @@ -629,8 +686,8 @@ TEST_BEGIN(test_arenas_constants) { TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM); TEST_ARENAS_CONSTANT(size_t, page, PAGE); - TEST_ARENAS_CONSTANT(unsigned, nbins, NBINS); - TEST_ARENAS_CONSTANT(unsigned, nlextents, NSIZES - NBINS); + TEST_ARENAS_CONSTANT(unsigned, nbins, SC_NBINS); + TEST_ARENAS_CONSTANT(unsigned, nlextents, SC_NSIZES - SC_NBINS); #undef TEST_ARENAS_CONSTANT } @@ -645,10 +702,11 @@ TEST_BEGIN(test_arenas_bin_constants) { assert_zu_eq(name, expected, "Incorrect "#name" size"); \ } while (0) - TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size); - TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs); + TEST_ARENAS_BIN_CONSTANT(size_t, size, bin_infos[0].reg_size); + TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, bin_infos[0].nregs); TEST_ARENAS_BIN_CONSTANT(size_t, slab_size, - arena_bin_info[0].slab_size); + bin_infos[0].slab_size); + TEST_ARENAS_BIN_CONSTANT(uint32_t, nshards, bin_infos[0].n_shards); #undef TEST_ARENAS_BIN_CONSTANT } @@ -663,7 +721,8 @@ TEST_BEGIN(test_arenas_lextent_constants) { assert_zu_eq(name, expected, "Incorrect "#name" size"); \ } while (0) - TEST_ARENAS_LEXTENT_CONSTANT(size_t, size, LARGE_MINCLASS); + TEST_ARENAS_LEXTENT_CONSTANT(size_t, size, + SC_LARGE_MINCLASS); #undef TEST_ARENAS_LEXTENT_CONSTANT } @@ -686,6 +745,22 @@ TEST_BEGIN(test_arenas_create) { } TEST_END +TEST_BEGIN(test_arenas_lookup) { + unsigned arena, arena1; + void *ptr; + size_t sz = sizeof(unsigned); + + assert_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + ptr = mallocx(42, MALLOCX_ARENA(arena) | MALLOCX_TCACHE_NONE); + assert_ptr_not_null(ptr, "Unexpected mallocx() failure"); + assert_d_eq(mallctl("arenas.lookup", &arena1, &sz, &ptr, sizeof(ptr)), + 0, "Unexpected mallctl() failure"); + assert_u_eq(arena, arena1, "Unexpected arena index"); + dallocx(ptr, 0); +} +TEST_END + TEST_BEGIN(test_stats_arenas) { #define TEST_STATS_ARENAS(t, name) do { \ t name; \ @@ -705,6 +780,79 @@ TEST_BEGIN(test_stats_arenas) { } TEST_END +static void +alloc_hook(void *extra, UNUSED hook_alloc_t type, UNUSED void *result, + UNUSED uintptr_t result_raw, UNUSED uintptr_t args_raw[3]) { + *(bool *)extra = true; +} + +static void +dalloc_hook(void *extra, UNUSED hook_dalloc_t type, + UNUSED void *address, UNUSED uintptr_t args_raw[3]) { + *(bool *)extra = true; +} + +TEST_BEGIN(test_hooks) { + bool hook_called = false; + hooks_t hooks = {&alloc_hook, &dalloc_hook, NULL, &hook_called}; + void *handle = NULL; + size_t sz = sizeof(handle); + int err = mallctl("experimental.hooks.install", &handle, &sz, &hooks, + sizeof(hooks)); + assert_d_eq(err, 0, "Hook installation failed"); + assert_ptr_ne(handle, NULL, "Hook installation gave null handle"); + void *ptr = mallocx(1, 0); + assert_true(hook_called, "Alloc hook not called"); + hook_called = false; + free(ptr); + assert_true(hook_called, "Free hook not called"); + + err = mallctl("experimental.hooks.remove", NULL, NULL, &handle, + sizeof(handle)); + assert_d_eq(err, 0, "Hook removal failed"); + hook_called = false; + ptr = mallocx(1, 0); + free(ptr); + assert_false(hook_called, "Hook called after removal"); +} +TEST_END + +TEST_BEGIN(test_hooks_exhaustion) { + bool hook_called = false; + hooks_t hooks = {&alloc_hook, &dalloc_hook, NULL, &hook_called}; + + void *handle; + void *handles[HOOK_MAX]; + size_t sz = sizeof(handle); + int err; + for (int i = 0; i < HOOK_MAX; i++) { + handle = NULL; + err = mallctl("experimental.hooks.install", &handle, &sz, + &hooks, sizeof(hooks)); + assert_d_eq(err, 0, "Error installation hooks"); + assert_ptr_ne(handle, NULL, "Got NULL handle"); + handles[i] = handle; + } + err = mallctl("experimental.hooks.install", &handle, &sz, &hooks, + sizeof(hooks)); + assert_d_eq(err, EAGAIN, "Should have failed hook installation"); + for (int i = 0; i < HOOK_MAX; i++) { + err = mallctl("experimental.hooks.remove", NULL, NULL, + &handles[i], sizeof(handles[i])); + assert_d_eq(err, 0, "Hook removal failed"); + } + /* Insertion failed, but then we removed some; it should work now. */ + handle = NULL; + err = mallctl("experimental.hooks.install", &handle, &sz, &hooks, + sizeof(hooks)); + assert_d_eq(err, 0, "Hook insertion failed"); + assert_ptr_ne(handle, NULL, "Got NULL handle"); + err = mallctl("experimental.hooks.remove", NULL, NULL, &handle, + sizeof(handle)); + assert_d_eq(err, 0, "Hook removal failed"); +} +TEST_END + int main(void) { return test( @@ -725,11 +873,15 @@ main(void) { test_arena_i_purge, test_arena_i_decay, test_arena_i_dss, + test_arena_i_retain_grow_limit, test_arenas_dirty_decay_ms, test_arenas_muzzy_decay_ms, test_arenas_constants, test_arenas_bin_constants, test_arenas_lextent_constants, test_arenas_create, - test_stats_arenas); + test_arenas_lookup, + test_stats_arenas, + test_hooks, + test_hooks_exhaustion); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/pack.c b/kbe/src/lib/dependencies/jemalloc/test/unit/pack.c index edfc548ff2..fc188b0033 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/pack.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/pack.c @@ -88,6 +88,12 @@ arena_reset_mallctl(unsigned arena_ind) { } TEST_BEGIN(test_pack) { + bool prof_enabled; + size_t sz = sizeof(prof_enabled); + if (mallctl("opt.prof", (void *)&prof_enabled, &sz, NULL, 0) == 0) { + test_skip_if(prof_enabled); + } + unsigned arena_ind = arenas_create_mallctl(); size_t nregs_per_run = nregs_per_run_compute(); size_t nregs = nregs_per_run * NSLABS; diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/pages.c b/kbe/src/lib/dependencies/jemalloc/test/unit/pages.c index 67dbb4cd2f..ee729eece8 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/pages.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/pages.c @@ -10,11 +10,13 @@ TEST_BEGIN(test_pages_huge) { pages = pages_map(NULL, alloc_size, PAGE, &commit); assert_ptr_not_null(pages, "Unexpected pages_map() error"); - hugepage = (void *)(ALIGNMENT_CEILING((uintptr_t)pages, HUGEPAGE)); - assert_b_ne(pages_huge(hugepage, HUGEPAGE), config_thp, - "Unexpected pages_huge() result"); - assert_false(pages_nohuge(hugepage, HUGEPAGE), - "Unexpected pages_nohuge() result"); + if (init_system_thp_mode == thp_mode_default) { + hugepage = (void *)(ALIGNMENT_CEILING((uintptr_t)pages, HUGEPAGE)); + assert_b_ne(pages_huge(hugepage, HUGEPAGE), have_madvise_huge, + "Unexpected pages_huge() result"); + assert_false(pages_nohuge(hugepage, HUGEPAGE), + "Unexpected pages_nohuge() result"); + } pages_unmap(pages, alloc_size); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/prof_gdump.c b/kbe/src/lib/dependencies/jemalloc/test/unit/prof_gdump.c index fcb434cb94..f7e0aac766 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/prof_gdump.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/prof_gdump.c @@ -29,12 +29,12 @@ TEST_BEGIN(test_gdump) { prof_dump_open = prof_dump_open_intercept; did_prof_dump_open = false; - p = mallocx((1U << LG_LARGE_MINCLASS), 0); + p = mallocx((1U << SC_LG_LARGE_MINCLASS), 0); assert_ptr_not_null(p, "Unexpected mallocx() failure"); assert_true(did_prof_dump_open, "Expected a profile dump"); did_prof_dump_open = false; - q = mallocx((1U << LG_LARGE_MINCLASS), 0); + q = mallocx((1U << SC_LG_LARGE_MINCLASS), 0); assert_ptr_not_null(q, "Unexpected mallocx() failure"); assert_true(did_prof_dump_open, "Expected a profile dump"); @@ -45,7 +45,7 @@ TEST_BEGIN(test_gdump) { "Unexpected mallctl failure while disabling prof.gdump"); assert(gdump_old); did_prof_dump_open = false; - r = mallocx((1U << LG_LARGE_MINCLASS), 0); + r = mallocx((1U << SC_LG_LARGE_MINCLASS), 0); assert_ptr_not_null(q, "Unexpected mallocx() failure"); assert_false(did_prof_dump_open, "Unexpected profile dump"); @@ -56,7 +56,7 @@ TEST_BEGIN(test_gdump) { "Unexpected mallctl failure while enabling prof.gdump"); assert(!gdump_old); did_prof_dump_open = false; - s = mallocx((1U << LG_LARGE_MINCLASS), 0); + s = mallocx((1U << SC_LG_LARGE_MINCLASS), 0); assert_ptr_not_null(q, "Unexpected mallocx() failure"); assert_true(did_prof_dump_open, "Expected a profile dump"); diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.c b/kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.c new file mode 100644 index 0000000000..6a3464b420 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.c @@ -0,0 +1,146 @@ +#include "test/jemalloc_test.h" + +#define N_PARAM 100 +#define N_THREADS 10 + +static void assert_rep() { + assert_b_eq(prof_log_rep_check(), false, "Rep check failed"); +} + +static void assert_log_empty() { + assert_zu_eq(prof_log_bt_count(), 0, + "The log has backtraces; it isn't empty"); + assert_zu_eq(prof_log_thr_count(), 0, + "The log has threads; it isn't empty"); + assert_zu_eq(prof_log_alloc_count(), 0, + "The log has allocations; it isn't empty"); +} + +void *buf[N_PARAM]; + +static void f() { + int i; + for (i = 0; i < N_PARAM; i++) { + buf[i] = malloc(100); + } + for (i = 0; i < N_PARAM; i++) { + free(buf[i]); + } +} + +TEST_BEGIN(test_prof_log_many_logs) { + int i; + + test_skip_if(!config_prof); + + for (i = 0; i < N_PARAM; i++) { + assert_b_eq(prof_log_is_logging(), false, + "Logging shouldn't have started yet"); + assert_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl failure when starting logging"); + assert_b_eq(prof_log_is_logging(), true, + "Logging should be started by now"); + assert_log_empty(); + assert_rep(); + f(); + assert_zu_eq(prof_log_thr_count(), 1, "Wrong thread count"); + assert_rep(); + assert_b_eq(prof_log_is_logging(), true, + "Logging should still be on"); + assert_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl failure when stopping logging"); + assert_b_eq(prof_log_is_logging(), false, + "Logging should have turned off"); + } +} +TEST_END + +thd_t thr_buf[N_THREADS]; + +static void *f_thread(void *unused) { + int i; + for (i = 0; i < N_PARAM; i++) { + void *p = malloc(100); + memset(p, 100, sizeof(char)); + free(p); + } + + return NULL; +} + +TEST_BEGIN(test_prof_log_many_threads) { + + test_skip_if(!config_prof); + + int i; + assert_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl failure when starting logging"); + for (i = 0; i < N_THREADS; i++) { + thd_create(&thr_buf[i], &f_thread, NULL); + } + + for (i = 0; i < N_THREADS; i++) { + thd_join(thr_buf[i], NULL); + } + assert_zu_eq(prof_log_thr_count(), N_THREADS, + "Wrong number of thread entries"); + assert_rep(); + assert_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl failure when stopping logging"); +} +TEST_END + +static void f3() { + void *p = malloc(100); + free(p); +} + +static void f1() { + void *p = malloc(100); + f3(); + free(p); +} + +static void f2() { + void *p = malloc(100); + free(p); +} + +TEST_BEGIN(test_prof_log_many_traces) { + + test_skip_if(!config_prof); + + assert_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl failure when starting logging"); + int i; + assert_rep(); + assert_log_empty(); + for (i = 0; i < N_PARAM; i++) { + assert_rep(); + f1(); + assert_rep(); + f2(); + assert_rep(); + f3(); + assert_rep(); + } + /* + * There should be 8 total backtraces: two for malloc/free in f1(), + * two for malloc/free in f2(), two for malloc/free in f3(), and then + * two for malloc/free in f1()'s call to f3(). + */ + assert_zu_eq(prof_log_bt_count(), 8, + "Wrong number of backtraces given sample workload"); + assert_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl failure when stopping logging"); +} +TEST_END + +int +main(void) { + prof_log_dummy_set(true); + return test_no_reentrancy( + test_prof_log_many_logs, + test_prof_log_many_traces, + test_prof_log_many_threads); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.sh b/kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.sh new file mode 100644 index 0000000000..8fcc7d8a79 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/prof_log.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +if [ "x${enable_prof}" = "x1" ] ; then + export MALLOC_CONF="prof:true,lg_prof_sample:0" +fi diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/rtree.c b/kbe/src/lib/dependencies/jemalloc/test/unit/rtree.c index 814837bf1b..b017bc0327 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/rtree.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/rtree.c @@ -85,11 +85,11 @@ TEST_END TEST_BEGIN(test_rtree_extrema) { extent_t extent_a, extent_b; - extent_init(&extent_a, NULL, NULL, LARGE_MINCLASS, false, - sz_size2index(LARGE_MINCLASS), 0, extent_state_active, false, - false); - extent_init(&extent_b, NULL, NULL, 0, false, NSIZES, 0, - extent_state_active, false, false); + extent_init(&extent_a, NULL, NULL, SC_LARGE_MINCLASS, false, + sz_size2index(SC_LARGE_MINCLASS), 0, + extent_state_active, false, false, true); + extent_init(&extent_b, NULL, NULL, 0, false, SC_NSIZES, 0, + extent_state_active, false, false, true); tsdn_t *tsdn = tsdn_fetch(); @@ -125,8 +125,8 @@ TEST_BEGIN(test_rtree_bits) { PAGE + (((uintptr_t)1) << LG_PAGE) - 1}; extent_t extent; - extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0, - extent_state_active, false, false); + extent_init(&extent, NULL, NULL, 0, false, SC_NSIZES, 0, + extent_state_active, false, false, true); rtree_t *rtree = &test_rtree; rtree_ctx_t rtree_ctx; @@ -135,7 +135,7 @@ TEST_BEGIN(test_rtree_bits) { for (unsigned i = 0; i < sizeof(keys)/sizeof(uintptr_t); i++) { assert_false(rtree_write(tsdn, rtree, &rtree_ctx, keys[i], - &extent, NSIZES, false), + &extent, SC_NSIZES, false), "Unexpected rtree_write() failure"); for (unsigned j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) { assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx, @@ -166,8 +166,8 @@ TEST_BEGIN(test_rtree_random) { rtree_ctx_data_init(&rtree_ctx); extent_t extent; - extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0, - extent_state_active, false, false); + extent_init(&extent, NULL, NULL, 0, false, SC_NSIZES, 0, + extent_state_active, false, false, true); assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure"); @@ -177,7 +177,8 @@ TEST_BEGIN(test_rtree_random) { &rtree_ctx, keys[i], false, true); assert_ptr_not_null(elm, "Unexpected rtree_leaf_elm_lookup() failure"); - rtree_leaf_elm_write(tsdn, rtree, elm, &extent, NSIZES, false); + rtree_leaf_elm_write(tsdn, rtree, elm, &extent, SC_NSIZES, + false); assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx, keys[i], true), &extent, "rtree_extent_read() should return previously set value"); diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/sc.c b/kbe/src/lib/dependencies/jemalloc/test/unit/sc.c new file mode 100644 index 0000000000..bf51d8e59f --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/sc.c @@ -0,0 +1,33 @@ +#include "test/jemalloc_test.h" + +TEST_BEGIN(test_update_slab_size) { + sc_data_t data; + memset(&data, 0, sizeof(data)); + sc_data_init(&data); + sc_t *tiny = &data.sc[0]; + size_t tiny_size = (ZU(1) << tiny->lg_base) + + (ZU(tiny->ndelta) << tiny->lg_delta); + size_t pgs_too_big = (tiny_size * BITMAP_MAXBITS + PAGE - 1) / PAGE + 1; + sc_data_update_slab_size(&data, tiny_size, tiny_size, (int)pgs_too_big); + assert_zu_lt((size_t)tiny->pgs, pgs_too_big, "Allowed excessive pages"); + + sc_data_update_slab_size(&data, 1, 10 * PAGE, 1); + for (int i = 0; i < data.nbins; i++) { + sc_t *sc = &data.sc[i]; + size_t reg_size = (ZU(1) << sc->lg_base) + + (ZU(sc->ndelta) << sc->lg_delta); + if (reg_size <= PAGE) { + assert_d_eq(sc->pgs, 1, "Ignored valid page size hint"); + } else { + assert_d_gt(sc->pgs, 1, + "Allowed invalid page size hint"); + } + } +} +TEST_END + +int +main(void) { + return test( + test_update_slab_size); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/seq.c b/kbe/src/lib/dependencies/jemalloc/test/unit/seq.c new file mode 100644 index 0000000000..19613b0b24 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/seq.c @@ -0,0 +1,95 @@ +#include "test/jemalloc_test.h" + +#include "jemalloc/internal/seq.h" + +typedef struct data_s data_t; +struct data_s { + int arr[10]; +}; + +static void +set_data(data_t *data, int num) { + for (int i = 0; i < 10; i++) { + data->arr[i] = num; + } +} + +static void +assert_data(data_t *data) { + int num = data->arr[0]; + for (int i = 0; i < 10; i++) { + assert_d_eq(num, data->arr[i], "Data consistency error"); + } +} + +seq_define(data_t, data) + +typedef struct thd_data_s thd_data_t; +struct thd_data_s { + seq_data_t data; +}; + +static void * +seq_reader_thd(void *arg) { + thd_data_t *thd_data = (thd_data_t *)arg; + int iter = 0; + data_t local_data; + while (iter < 1000 * 1000 - 1) { + bool success = seq_try_load_data(&local_data, &thd_data->data); + if (success) { + assert_data(&local_data); + assert_d_le(iter, local_data.arr[0], + "Seq read went back in time."); + iter = local_data.arr[0]; + } + } + return NULL; +} + +static void * +seq_writer_thd(void *arg) { + thd_data_t *thd_data = (thd_data_t *)arg; + data_t local_data; + memset(&local_data, 0, sizeof(local_data)); + for (int i = 0; i < 1000 * 1000; i++) { + set_data(&local_data, i); + seq_store_data(&thd_data->data, &local_data); + } + return NULL; +} + +TEST_BEGIN(test_seq_threaded) { + thd_data_t thd_data; + memset(&thd_data, 0, sizeof(thd_data)); + + thd_t reader; + thd_t writer; + + thd_create(&reader, seq_reader_thd, &thd_data); + thd_create(&writer, seq_writer_thd, &thd_data); + + thd_join(reader, NULL); + thd_join(writer, NULL); +} +TEST_END + +TEST_BEGIN(test_seq_simple) { + data_t data; + seq_data_t seq; + memset(&seq, 0, sizeof(seq)); + for (int i = 0; i < 1000 * 1000; i++) { + set_data(&data, i); + seq_store_data(&seq, &data); + set_data(&data, 0); + bool success = seq_try_load_data(&data, &seq); + assert_b_eq(success, true, "Failed non-racing read"); + assert_data(&data); + } +} +TEST_END + +int main(void) { + return test_no_reentrancy( + test_seq_simple, + test_seq_threaded); +} diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/size_classes.c b/kbe/src/lib/dependencies/jemalloc/test/unit/size_classes.c index bcff560983..694733635b 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/size_classes.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/size_classes.c @@ -108,8 +108,13 @@ TEST_BEGIN(test_psize_classes) { size_class, sz_psz2ind(size_class), sz_pind2sz(sz_psz2ind(size_class))); - assert_u_eq(pind+1, sz_psz2ind(size_class+1), - "Next size_class does not round up properly"); + if (size_class == SC_LARGE_MAXCLASS) { + assert_u_eq(SC_NPSIZES, sz_psz2ind(size_class + 1), + "Next size_class does not round up properly"); + } else { + assert_u_eq(pind + 1, sz_psz2ind(size_class + 1), + "Next size_class does not round up properly"); + } assert_zu_eq(size_class, (pind > 0) ? sz_psz2u(sz_pind2sz(pind-1)+1) : sz_psz2u(1), @@ -142,11 +147,11 @@ TEST_BEGIN(test_overflow) { max_size_class = get_max_size_class(); max_psz = max_size_class + PAGE; - assert_u_eq(sz_size2index(max_size_class+1), NSIZES, + assert_u_eq(sz_size2index(max_size_class+1), SC_NSIZES, "sz_size2index() should return NSIZES on overflow"); - assert_u_eq(sz_size2index(ZU(PTRDIFF_MAX)+1), NSIZES, + assert_u_eq(sz_size2index(ZU(PTRDIFF_MAX)+1), SC_NSIZES, "sz_size2index() should return NSIZES on overflow"); - assert_u_eq(sz_size2index(SIZE_T_MAX), NSIZES, + assert_u_eq(sz_size2index(SIZE_T_MAX), SC_NSIZES, "sz_size2index() should return NSIZES on overflow"); assert_zu_eq(sz_s2u(max_size_class+1), 0, @@ -156,11 +161,11 @@ TEST_BEGIN(test_overflow) { assert_zu_eq(sz_s2u(SIZE_T_MAX), 0, "sz_s2u() should return 0 on overflow"); - assert_u_eq(sz_psz2ind(max_size_class+1), NPSIZES, + assert_u_eq(sz_psz2ind(max_size_class+1), SC_NPSIZES, "sz_psz2ind() should return NPSIZES on overflow"); - assert_u_eq(sz_psz2ind(ZU(PTRDIFF_MAX)+1), NPSIZES, + assert_u_eq(sz_psz2ind(ZU(PTRDIFF_MAX)+1), SC_NPSIZES, "sz_psz2ind() should return NPSIZES on overflow"); - assert_u_eq(sz_psz2ind(SIZE_T_MAX), NPSIZES, + assert_u_eq(sz_psz2ind(SIZE_T_MAX), SC_NPSIZES, "sz_psz2ind() should return NPSIZES on overflow"); assert_zu_eq(sz_psz2u(max_size_class+1), max_psz, diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/slab.c b/kbe/src/lib/dependencies/jemalloc/test/unit/slab.c index 6f40aeef6c..ef7188215c 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/slab.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/slab.c @@ -3,13 +3,13 @@ TEST_BEGIN(test_arena_slab_regind) { szind_t binind; - for (binind = 0; binind < NBINS; binind++) { + for (binind = 0; binind < SC_NBINS; binind++) { size_t regind; extent_t slab; - const arena_bin_info_t *bin_info = &arena_bin_info[binind]; + const bin_info_t *bin_info = &bin_infos[binind]; extent_init(&slab, NULL, mallocx(bin_info->slab_size, MALLOCX_LG_ALIGN(LG_PAGE)), bin_info->slab_size, true, - binind, 0, extent_state_active, false, true); + binind, 0, extent_state_active, false, true, true); assert_ptr_not_null(extent_addr_get(&slab), "Unexpected malloc() failure"); for (regind = 0; regind < bin_info->nregs; regind++) { diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/stats.c b/kbe/src/lib/dependencies/jemalloc/test/unit/stats.c index d9849d800b..4323bfa3b2 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/stats.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/stats.c @@ -33,7 +33,7 @@ TEST_BEGIN(test_stats_large) { size_t sz; int expected = config_stats ? 0 : ENOENT; - p = mallocx(SMALL_MAXCLASS+1, MALLOCX_ARENA(0)); + p = mallocx(SC_SMALL_MAXCLASS + 1, MALLOCX_ARENA(0)); assert_ptr_not_null(p, "Unexpected mallocx() failure"); assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), @@ -74,9 +74,10 @@ TEST_BEGIN(test_stats_arenas_summary) { uint64_t dirty_npurge, dirty_nmadvise, dirty_purged; uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged; - little = mallocx(SMALL_MAXCLASS, MALLOCX_ARENA(0)); + little = mallocx(SC_SMALL_MAXCLASS, MALLOCX_ARENA(0)); assert_ptr_not_null(little, "Unexpected mallocx() failure"); - large = mallocx((1U << LG_LARGE_MINCLASS), MALLOCX_ARENA(0)); + large = mallocx((1U << SC_LG_LARGE_MINCLASS), + MALLOCX_ARENA(0)); assert_ptr_not_null(large, "Unexpected mallocx() failure"); dallocx(little, 0); @@ -148,7 +149,7 @@ TEST_BEGIN(test_stats_arenas_small) { no_lazy_lock(); /* Lazy locking would dodge tcache testing. */ - p = mallocx(SMALL_MAXCLASS, MALLOCX_ARENA(0)); + p = mallocx(SC_SMALL_MAXCLASS, MALLOCX_ARENA(0)); assert_ptr_not_null(p, "Unexpected mallocx() failure"); assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), @@ -191,7 +192,7 @@ TEST_BEGIN(test_stats_arenas_large) { uint64_t epoch, nmalloc, ndalloc; int expected = config_stats ? 0 : ENOENT; - p = mallocx((1U << LG_LARGE_MINCLASS), MALLOCX_ARENA(0)); + p = mallocx((1U << SC_LG_LARGE_MINCLASS), MALLOCX_ARENA(0)); assert_ptr_not_null(p, "Unexpected mallocx() failure"); assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), @@ -245,7 +246,7 @@ TEST_BEGIN(test_stats_arenas_bins) { (void *)&arena_ind, sizeof(arena_ind)), 0, "Unexpected mallctl() failure"); - p = malloc(arena_bin_info[0].reg_size); + p = malloc(bin_infos[0].reg_size); assert_ptr_not_null(p, "Unexpected malloc() failure"); assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/stats_print.c b/kbe/src/lib/dependencies/jemalloc/test/unit/stats_print.c index acb26b068e..014d002fd4 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/stats_print.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/stats_print.c @@ -67,7 +67,7 @@ token_error(token_t *token) { token->col); break; } - UNUSED ssize_t err = write(STDERR_FILENO, + UNUSED ssize_t err = malloc_write_fd(STDERR_FILENO, &token->parser->buf[token->pos], token->len); malloc_printf("\n"); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/hooks.c b/kbe/src/lib/dependencies/jemalloc/test/unit/test_hooks.c old mode 100755 new mode 100644 similarity index 82% rename from kbe/src/lib/dependencies/jemalloc/test/unit/hooks.c rename to kbe/src/lib/dependencies/jemalloc/test/unit/test_hooks.c index b70172e13c..ded8698bc7 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/hooks.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/test_hooks.c @@ -12,10 +12,10 @@ func_to_hook(int arg1, int arg2) { return arg1 + arg2; } -#define func_to_hook JEMALLOC_HOOK(func_to_hook, hooks_libc_hook) +#define func_to_hook JEMALLOC_HOOK(func_to_hook, test_hooks_libc_hook) TEST_BEGIN(unhooked_call) { - hooks_libc_hook = NULL; + test_hooks_libc_hook = NULL; hook_called = false; assert_d_eq(3, func_to_hook(1, 2), "Hooking changed return value."); assert_false(hook_called, "Nulling out hook didn't take."); @@ -23,7 +23,7 @@ TEST_BEGIN(unhooked_call) { TEST_END TEST_BEGIN(hooked_call) { - hooks_libc_hook = &hook; + test_hooks_libc_hook = &hook; hook_called = false; assert_d_eq(3, func_to_hook(1, 2), "Hooking changed return value."); assert_true(hook_called, "Hook should have executed."); diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/tsd.c b/kbe/src/lib/dependencies/jemalloc/test/unit/tsd.c index 6c479139bd..917884dcf0 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/tsd.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/tsd.c @@ -1,5 +1,10 @@ #include "test/jemalloc_test.h" +/* + * If we're e.g. in debug mode, we *never* enter the fast path, and so shouldn't + * be asserting that we're on one. + */ +static bool originally_fast; static int data_cleanup_count; void @@ -98,11 +103,11 @@ thd_start_reincarnated(void *arg) { tsd_cleanup((void *)tsd); assert_ptr_null(*tsd_arenap_get_unsafe(tsd), "TSD arena should have been cleared."); - assert_u_eq(tsd->state, tsd_state_purgatory, + assert_u_eq(tsd_state_get(tsd), tsd_state_purgatory, "TSD state should be purgatory\n"); free(p); - assert_u_eq(tsd->state, tsd_state_reincarnated, + assert_u_eq(tsd_state_get(tsd), tsd_state_reincarnated, "TSD state should be reincarnated\n"); p = mallocx(1, MALLOCX_TCACHE_NONE); assert_ptr_not_null(p, "Unexpected malloc() failure"); @@ -124,6 +129,128 @@ TEST_BEGIN(test_tsd_reincarnation) { } TEST_END +typedef struct { + atomic_u32_t phase; + atomic_b_t error; +} global_slow_data_t; + +static void * +thd_start_global_slow(void *arg) { + /* PHASE 0 */ + global_slow_data_t *data = (global_slow_data_t *)arg; + free(mallocx(1, 0)); + + tsd_t *tsd = tsd_fetch(); + /* + * No global slowness has happened yet; there was an error if we were + * originally fast but aren't now. + */ + atomic_store_b(&data->error, originally_fast && !tsd_fast(tsd), + ATOMIC_SEQ_CST); + atomic_store_u32(&data->phase, 1, ATOMIC_SEQ_CST); + + /* PHASE 2 */ + while (atomic_load_u32(&data->phase, ATOMIC_SEQ_CST) != 2) { + } + free(mallocx(1, 0)); + atomic_store_b(&data->error, tsd_fast(tsd), ATOMIC_SEQ_CST); + atomic_store_u32(&data->phase, 3, ATOMIC_SEQ_CST); + + /* PHASE 4 */ + while (atomic_load_u32(&data->phase, ATOMIC_SEQ_CST) != 4) { + } + free(mallocx(1, 0)); + atomic_store_b(&data->error, tsd_fast(tsd), ATOMIC_SEQ_CST); + atomic_store_u32(&data->phase, 5, ATOMIC_SEQ_CST); + + /* PHASE 6 */ + while (atomic_load_u32(&data->phase, ATOMIC_SEQ_CST) != 6) { + } + free(mallocx(1, 0)); + /* Only one decrement so far. */ + atomic_store_b(&data->error, tsd_fast(tsd), ATOMIC_SEQ_CST); + atomic_store_u32(&data->phase, 7, ATOMIC_SEQ_CST); + + /* PHASE 8 */ + while (atomic_load_u32(&data->phase, ATOMIC_SEQ_CST) != 8) { + } + free(mallocx(1, 0)); + /* + * Both decrements happened; we should be fast again (if we ever + * were) + */ + atomic_store_b(&data->error, originally_fast && !tsd_fast(tsd), + ATOMIC_SEQ_CST); + atomic_store_u32(&data->phase, 9, ATOMIC_SEQ_CST); + + return NULL; +} + +TEST_BEGIN(test_tsd_global_slow) { + global_slow_data_t data = {ATOMIC_INIT(0), ATOMIC_INIT(false)}; + /* + * Note that the "mallocx" here (vs. malloc) is important, since the + * compiler is allowed to optimize away free(malloc(1)) but not + * free(mallocx(1)). + */ + free(mallocx(1, 0)); + tsd_t *tsd = tsd_fetch(); + originally_fast = tsd_fast(tsd); + + thd_t thd; + thd_create(&thd, thd_start_global_slow, (void *)&data.phase); + /* PHASE 1 */ + while (atomic_load_u32(&data.phase, ATOMIC_SEQ_CST) != 1) { + /* + * We don't have a portable condvar/semaphore mechanism. + * Spin-wait. + */ + } + assert_false(atomic_load_b(&data.error, ATOMIC_SEQ_CST), ""); + tsd_global_slow_inc(tsd_tsdn(tsd)); + free(mallocx(1, 0)); + assert_false(tsd_fast(tsd), ""); + atomic_store_u32(&data.phase, 2, ATOMIC_SEQ_CST); + + /* PHASE 3 */ + while (atomic_load_u32(&data.phase, ATOMIC_SEQ_CST) != 3) { + } + assert_false(atomic_load_b(&data.error, ATOMIC_SEQ_CST), ""); + /* Increase again, so that we can test multiple fast/slow changes. */ + tsd_global_slow_inc(tsd_tsdn(tsd)); + atomic_store_u32(&data.phase, 4, ATOMIC_SEQ_CST); + free(mallocx(1, 0)); + assert_false(tsd_fast(tsd), ""); + + /* PHASE 5 */ + while (atomic_load_u32(&data.phase, ATOMIC_SEQ_CST) != 5) { + } + assert_false(atomic_load_b(&data.error, ATOMIC_SEQ_CST), ""); + tsd_global_slow_dec(tsd_tsdn(tsd)); + atomic_store_u32(&data.phase, 6, ATOMIC_SEQ_CST); + /* We only decreased once; things should still be slow. */ + free(mallocx(1, 0)); + assert_false(tsd_fast(tsd), ""); + + /* PHASE 7 */ + while (atomic_load_u32(&data.phase, ATOMIC_SEQ_CST) != 7) { + } + assert_false(atomic_load_b(&data.error, ATOMIC_SEQ_CST), ""); + tsd_global_slow_dec(tsd_tsdn(tsd)); + atomic_store_u32(&data.phase, 8, ATOMIC_SEQ_CST); + /* We incremented and then decremented twice; we should be fast now. */ + free(mallocx(1, 0)); + assert_true(!originally_fast || tsd_fast(tsd), ""); + + /* PHASE 9 */ + while (atomic_load_u32(&data.phase, ATOMIC_SEQ_CST) != 9) { + } + assert_false(atomic_load_b(&data.error, ATOMIC_SEQ_CST), ""); + + thd_join(thd, NULL); +} +TEST_END + int main(void) { /* Ensure tsd bootstrapped. */ @@ -135,5 +262,6 @@ main(void) { return test_no_reentrancy( test_tsd_main_thread, test_tsd_sub_thread, - test_tsd_reincarnation); + test_tsd_reincarnation, + test_tsd_global_slow); } diff --git a/kbe/src/lib/dependencies/jemalloc/test/unit/zero.c b/kbe/src/lib/dependencies/jemalloc/test/unit/zero.c index 553692ba7b..271fd5cba4 100755 --- a/kbe/src/lib/dependencies/jemalloc/test/unit/zero.c +++ b/kbe/src/lib/dependencies/jemalloc/test/unit/zero.c @@ -41,13 +41,13 @@ test_zero(size_t sz_min, size_t sz_max) { TEST_BEGIN(test_zero_small) { test_skip_if(!config_fill); - test_zero(1, SMALL_MAXCLASS-1); + test_zero(1, SC_SMALL_MAXCLASS - 1); } TEST_END TEST_BEGIN(test_zero_large) { test_skip_if(!config_fill); - test_zero(SMALL_MAXCLASS+1, (1U << (LG_LARGE_MINCLASS+1))); + test_zero(SC_SMALL_MAXCLASS + 1, 1U << (SC_LG_LARGE_MINCLASS + 1)); } TEST_END From 4e1fb30321a322ddada81fa1a4ac1995e1fa26f6 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Wed, 3 Apr 2019 10:39:56 +0800 Subject: [PATCH 28/59] up --- .../jemalloc/test/integration/cpp/basic.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 kbe/src/lib/dependencies/jemalloc/test/integration/cpp/basic.cpp diff --git a/kbe/src/lib/dependencies/jemalloc/test/integration/cpp/basic.cpp b/kbe/src/lib/dependencies/jemalloc/test/integration/cpp/basic.cpp new file mode 100644 index 0000000000..65890ecd55 --- /dev/null +++ b/kbe/src/lib/dependencies/jemalloc/test/integration/cpp/basic.cpp @@ -0,0 +1,25 @@ +#include +#include "test/jemalloc_test.h" + +TEST_BEGIN(test_basic) { + auto foo = new long(4); + assert_ptr_not_null(foo, "Unexpected new[] failure"); + delete foo; + // Test nullptr handling. + foo = nullptr; + delete foo; + + auto bar = new long; + assert_ptr_not_null(bar, "Unexpected new failure"); + delete bar; + // Test nullptr handling. + bar = nullptr; + delete bar; +} +TEST_END + +int +main() { + return test( + test_basic); +} From 1f77cfb9d1e28b13bd4bfefc1268e9223cde498c Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Wed, 3 Apr 2019 13:58:22 +0800 Subject: [PATCH 29/59] up --- kbe/src/lib/entitydef/py_entitydef.cpp | 4828 ++++++++++++------------ kbe/src/server/dbmgr/dbmgr.cpp | 2561 ++++++------- kbe/src/server/dbmgr/dbmgr.h | 555 +-- 3 files changed, 3981 insertions(+), 3963 deletions(-) diff --git a/kbe/src/lib/entitydef/py_entitydef.cpp b/kbe/src/lib/entitydef/py_entitydef.cpp index 54841d46dc..2b5fb53640 100644 --- a/kbe/src/lib/entitydef/py_entitydef.cpp +++ b/kbe/src/lib/entitydef/py_entitydef.cpp @@ -1,2413 +1,2415 @@ -// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com - -#include -#include -#include - -#include "common.h" -#include "entitydef.h" -#include "datatypes.h" -#include "py_entitydef.h" -#include "scriptdef_module.h" -#include "pyscript/py_platform.h" -#include "pyscript/script.h" -#include "pyscript/copy.h" -#include "resmgr/resmgr.h" -#include "server/serverconfig.h" -#include "server/components.h" - -namespace KBEngine{ namespace script{ namespace entitydef { - -struct CallContext -{ - PyObjectPtr pyArgs; - PyObjectPtr pyKwargs; - std::string optionName; -}; - -static std::stack g_callContexts; -static std::string pyDefModuleName = ""; - -DefContext::DEF_CONTEXT_MAP DefContext::allScriptDefContextMaps; -DefContext::DEF_CONTEXT_MAP DefContext::allScriptDefContextLineMaps; - -static bool g_inited = false; - -//------------------------------------------------------------------------------------- -static PyObject* __py_array(PyObject* self, PyObject* args) -{ - if (PyTuple_GET_SIZE(args) == 0) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.ARRAY: does not set itemType! should be like this \"EntityDef.ARRAY(itemType)\"\n"); - return NULL; - } - - PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); - PyObject* pyARRAY = PyObject_GetAttrString(entitydefModule, "ARRAY"); - - PyObject* pyArrayItemType = PyTuple_GET_ITEM(args, 0); - Py_INCREF(pyArrayItemType); - - PyObject* ret = PyTuple_New(2); - PyTuple_SET_ITEM(ret, 0, pyARRAY); - PyTuple_SET_ITEM(ret, 1, pyArrayItemType); - - return ret; -} - -//------------------------------------------------------------------------------------- -class Entity : public script::ScriptObject -{ - BASE_SCRIPT_HREADER(Entity, ScriptObject) -public: - Entity(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : - ScriptObject(pyType, isInitialised) {} - ~Entity() {} -}; - -SCRIPT_METHOD_DECLARE_BEGIN(Entity) -SCRIPT_METHOD_DECLARE_END() - -SCRIPT_MEMBER_DECLARE_BEGIN(Entity) -SCRIPT_MEMBER_DECLARE_END() - -SCRIPT_GETSET_DECLARE_BEGIN(Entity) -SCRIPT_GETSET_DECLARE_END() -BASE_SCRIPT_INIT(Entity, 0, 0, 0, 0, 0) - -//------------------------------------------------------------------------------------- -class Space : public script::ScriptObject -{ - BASE_SCRIPT_HREADER(Space, ScriptObject) -public: - Space(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : - ScriptObject(pyType, isInitialised) {} - ~Space() {} -}; - -SCRIPT_METHOD_DECLARE_BEGIN(Space) -SCRIPT_METHOD_DECLARE_END() - -SCRIPT_MEMBER_DECLARE_BEGIN(Space) -SCRIPT_MEMBER_DECLARE_END() - -SCRIPT_GETSET_DECLARE_BEGIN(Space) -SCRIPT_GETSET_DECLARE_END() -BASE_SCRIPT_INIT(Space, 0, 0, 0, 0, 0) - -//------------------------------------------------------------------------------------- -class Proxy : public script::ScriptObject -{ - BASE_SCRIPT_HREADER(Proxy, ScriptObject) -public: - Proxy(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : - ScriptObject(pyType, isInitialised) {} - ~Proxy() {} -}; - -SCRIPT_METHOD_DECLARE_BEGIN(Proxy) -SCRIPT_METHOD_DECLARE_END() - -SCRIPT_MEMBER_DECLARE_BEGIN(Proxy) -SCRIPT_MEMBER_DECLARE_END() - -SCRIPT_GETSET_DECLARE_BEGIN(Proxy) -SCRIPT_GETSET_DECLARE_END() -BASE_SCRIPT_INIT(Proxy, 0, 0, 0, 0, 0) - -//------------------------------------------------------------------------------------- -class EntityComponent : public script::ScriptObject -{ - BASE_SCRIPT_HREADER(EntityComponent, ScriptObject) -public: - EntityComponent(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : - ScriptObject(pyType, isInitialised) {} - ~EntityComponent() {} -}; - -SCRIPT_METHOD_DECLARE_BEGIN(EntityComponent) -SCRIPT_METHOD_DECLARE_END() - -SCRIPT_MEMBER_DECLARE_BEGIN(EntityComponent) -SCRIPT_MEMBER_DECLARE_END() - -SCRIPT_GETSET_DECLARE_BEGIN(EntityComponent) -SCRIPT_GETSET_DECLARE_END() -BASE_SCRIPT_INIT(EntityComponent, 0, 0, 0, 0, 0) - -//------------------------------------------------------------------------------------- -DefContext::DefContext() -{ - optionName = ""; - - moduleName = ""; - attrName = ""; - methodArgs = ""; - returnType = ""; - - isModuleScope = false; - - exposed = false; - hasClient = false; - persistent = -1; - databaseLength = 0; - utype = -1; - detailLevel = ""; - - propertyFlags = ""; - propertyIndex = ""; - propertyDefaultVal = ""; - - implementedByModuleName = ""; - implementedByModuleFile = ""; - pyObjectSourceFile = ""; - - inheritEngineModuleType = DC_TYPE_UNKNOWN; - type = DC_TYPE_UNKNOWN; - - componentType = UNKNOWN_COMPONENT_TYPE; -} - -//------------------------------------------------------------------------------------- -bool DefContext::addToStream(MemoryStream* pMemoryStream) -{ - (*pMemoryStream) << optionName; - (*pMemoryStream) << moduleName; - (*pMemoryStream) << attrName; - (*pMemoryStream) << methodArgs; - (*pMemoryStream) << returnType; - - (*pMemoryStream) << (int)argsvecs.size(); - std::vector< std::string >::iterator argsvecsIter = argsvecs.begin(); - for(; argsvecsIter != argsvecs.end(); ++argsvecsIter) - (*pMemoryStream) << (*argsvecsIter); - - (*pMemoryStream) << (int)annotationsMaps.size(); - std::map< std::string, std::string >::iterator annotationsMapsIter = annotationsMaps.begin(); - for (; annotationsMapsIter != annotationsMaps.end(); ++annotationsMapsIter) - (*pMemoryStream) << annotationsMapsIter->first << annotationsMapsIter->second; - - (*pMemoryStream) << isModuleScope; - (*pMemoryStream) << exposed; - (*pMemoryStream) << hasClient; - - (*pMemoryStream) << persistent; - (*pMemoryStream) << databaseLength; - (*pMemoryStream) << utype; - (*pMemoryStream) << detailLevel; - - (*pMemoryStream) << propertyFlags; - (*pMemoryStream) << propertyIndex; - (*pMemoryStream) << propertyDefaultVal; - - (*pMemoryStream) << implementedByModuleName; - (*pMemoryStream) << implementedByModuleFile; - (*pMemoryStream) << pyObjectSourceFile; - - (*pMemoryStream) << (int)baseClasses.size(); - std::vector< std::string >::iterator baseClassesIter = baseClasses.begin(); - for (; baseClassesIter != baseClasses.end(); ++baseClassesIter) - (*pMemoryStream) << (*baseClassesIter); - - (*pMemoryStream) << (int)inheritEngineModuleType; - (*pMemoryStream) << (int)type; - - (*pMemoryStream) << (int)methods.size(); - std::vector< DefContext >::iterator methodsIter = methods.begin(); - for (; methodsIter != methods.end(); ++methodsIter) - (*methodsIter).addToStream(pMemoryStream); - - (*pMemoryStream) << (int)client_methods.size(); - std::vector< DefContext >::iterator client_methodsIter = client_methods.begin(); - for (; client_methodsIter != client_methods.end(); ++client_methodsIter) - (*client_methodsIter).addToStream(pMemoryStream); - - (*pMemoryStream) << (int)propertys.size(); - std::vector< DefContext >::iterator propertysIter = propertys.begin(); - for (; propertysIter != propertys.end(); ++propertysIter) - (*propertysIter).addToStream(pMemoryStream); - - (*pMemoryStream) << (int)components.size(); - std::vector< std::string >::iterator componentsIter = components.begin(); - for (; componentsIter != components.end(); ++componentsIter) - (*pMemoryStream) << (*componentsIter); - - return true; -} - -//------------------------------------------------------------------------------------- -bool DefContext::createFromStream(MemoryStream* pMemoryStream) -{ - (*pMemoryStream) >> optionName; - (*pMemoryStream) >> moduleName; - (*pMemoryStream) >> attrName; - (*pMemoryStream) >> methodArgs; - (*pMemoryStream) >> returnType; - - int size = 0; - - (*pMemoryStream) >> size; - for (int i = 0; i < size; ++i) - { - std::string str; - (*pMemoryStream) >> str; - - argsvecs.push_back(str); - } - - (*pMemoryStream) >> size; - for (int i = 0; i < size; ++i) - { - std::string key, val; - (*pMemoryStream) >> key >> val; - - annotationsMaps[key] = val; - } - - (*pMemoryStream) >> isModuleScope; - (*pMemoryStream) >> exposed; - (*pMemoryStream) >> hasClient; - - (*pMemoryStream) >> persistent; - (*pMemoryStream) >> databaseLength; - (*pMemoryStream) >> utype; - (*pMemoryStream) >> detailLevel; - - (*pMemoryStream) >> propertyFlags; - (*pMemoryStream) >> propertyIndex; - (*pMemoryStream) >> propertyDefaultVal; - - (*pMemoryStream) >> implementedByModuleName; - (*pMemoryStream) >> implementedByModuleFile; - (*pMemoryStream) >> pyObjectSourceFile; - - (*pMemoryStream) >> size; - for (int i = 0; i < size; ++i) - { - std::string str; - (*pMemoryStream) >> str; - - baseClasses.push_back(str); - } - - int t_inheritEngineModuleType; - (*pMemoryStream) >> t_inheritEngineModuleType; - inheritEngineModuleType = (DCType)t_inheritEngineModuleType; - - int t_type; - (*pMemoryStream) >> t_type; - type = (DCType)t_type; - - (*pMemoryStream) >> size; - for (int i = 0; i < size; ++i) - { - DefContext dc; - dc.createFromStream(pMemoryStream); - - methods.push_back(dc); - } - - (*pMemoryStream) >> size; - for (int i = 0; i < size; ++i) - { - DefContext dc; - dc.createFromStream(pMemoryStream); - - client_methods.push_back(dc); - } - - (*pMemoryStream) >> size; - for (int i = 0; i < size; ++i) - { - DefContext dc; - dc.createFromStream(pMemoryStream); - - propertys.push_back(dc); - } - - (*pMemoryStream) >> size; - for (int i = 0; i < size; ++i) - { - std::string str; - (*pMemoryStream) >> str; - - components.push_back(str); - } - - return true; -} - -//------------------------------------------------------------------------------------- -bool DefContext::addChildContext(DefContext& defContext) -{ - std::vector< DefContext >* pContexts = NULL; - - if (defContext.type == DefContext::DC_TYPE_PROPERTY) - pContexts = &propertys; - else if (defContext.type == DefContext::DC_TYPE_METHOD) - pContexts = &methods; - else if (defContext.type == DefContext::DC_TYPE_CLIENT_METHOD) - pContexts = &client_methods; - else if (defContext.type == DefContext::DC_TYPE_FIXED_ITEM) - pContexts = &propertys; - else - KBE_ASSERT(false); - - std::vector< DefContext >::iterator iter = pContexts->begin(); - for (; iter != pContexts->end(); ++iter) - { - if ((*iter).attrName == defContext.attrName) - { - // assemblyContextsʱܻᷢ - // - if (moduleName != defContext.moduleName || (*iter).pyObjectSourceFile == defContext.pyObjectSourceFile) - return true; - - return false; - } - } - - pContexts->push_back(defContext); - return true; -} - -//------------------------------------------------------------------------------------- -static bool assemblyContexts(bool notfoundModuleError = false) -{ - std::vector< std::string > dels; - - DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); - for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) - { - DefContext& defContext = iter->second; - - if (defContext.type == DefContext::DC_TYPE_PROPERTY || - defContext.type == DefContext::DC_TYPE_METHOD || - defContext.type == DefContext::DC_TYPE_CLIENT_METHOD || - defContext.type == DefContext::DC_TYPE_FIXED_ITEM) - { - DefContext::DEF_CONTEXT_MAP::iterator fiter = DefContext::allScriptDefContextMaps.find(defContext.moduleName); - if (fiter == DefContext::allScriptDefContextMaps.end()) - { - if (notfoundModuleError) - { - PyErr_Format(PyExc_AssertionError, "PyEntityDef::process(): No \'%s\' module defined!\n", defContext.moduleName.c_str()); - return false; - } - - return true; - } - - if (!fiter->second.addChildContext(defContext)) - { - PyErr_Format(PyExc_AssertionError, "\'%s.%s\' already exists!\n", - fiter->second.moduleName.c_str(), defContext.attrName.c_str()); - - return false; - } - - dels.push_back(iter->first); - } - else - { - } - } - - std::vector< std::string >::iterator diter = dels.begin(); - for (; diter != dels.end(); ++diter) - { - DefContext::allScriptDefContextMaps.erase((*diter)); - } - - // ԽϢ䵽 - iter = DefContext::allScriptDefContextMaps.begin(); - for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) - { - DefContext& defContext = iter->second; - if (defContext.baseClasses.size() > 0) - { - for (size_t i = 0; i < defContext.baseClasses.size(); ++i) - { - std::string parentClass = defContext.baseClasses[i]; - - DefContext::DEF_CONTEXT_MAP::iterator fiter = DefContext::allScriptDefContextMaps.find(parentClass); - if (fiter == DefContext::allScriptDefContextMaps.end()) - { - //PyErr_Format(PyExc_AssertionError, "not found parentClass(\'%s\')!\n", parentClass.c_str()); - //return false; - continue; - } - - DefContext& parentDefContext = fiter->second; - std::vector< DefContext > childContexts; - - childContexts.insert(childContexts.end(), parentDefContext.methods.begin(), parentDefContext.methods.end()); - childContexts.insert(childContexts.end(), parentDefContext.client_methods.begin(), parentDefContext.client_methods.end()); - childContexts.insert(childContexts.end(), parentDefContext.propertys.begin(), parentDefContext.propertys.end()); - - std::vector< DefContext >::iterator itemIter = childContexts.begin(); - for (; itemIter != childContexts.end(); ++itemIter) - { - DefContext& parentDefContext = (*itemIter); - if (!defContext.addChildContext(parentDefContext)) - { - PyErr_Format(PyExc_AssertionError, "\'%s.%s\' already exists(%s.%s)!\n", - defContext.moduleName.c_str(), parentDefContext.attrName.c_str(), parentDefContext.moduleName.c_str(), parentDefContext.attrName.c_str()); - - return false; - } - } - } - } - } - - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerDefContext(DefContext& defContext) -{ - DefContext::allScriptDefContextLineMaps[defContext.pyObjectSourceFile] = defContext; - - std::string name = defContext.moduleName; - - if (defContext.type == DefContext::DC_TYPE_PROPERTY) - { - if(!EntityDef::validDefPropertyName(name)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: '%s' is limited!\n\n", - defContext.optionName.c_str(), name.c_str()); - - return false; - } - - // Ƿڸý - bool flagsGood = true; - if (defContext.componentType == BASEAPP_TYPE) - flagsGood = (stringToEntityDataFlags(defContext.propertyFlags) & ENTITY_BASE_DATA_FLAGS) != 0; - else if (defContext.componentType == CELLAPP_TYPE) - flagsGood = (stringToEntityDataFlags(defContext.propertyFlags) & ENTITY_CELL_DATA_FLAGS) != 0; - else if (defContext.componentType == CLIENT_TYPE) - flagsGood = (stringToEntityDataFlags(defContext.propertyFlags) & ENTITY_CLIENT_DATA_FLAGS) != 0; - - name += "." + defContext.attrName; - - if (!flagsGood) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: '%s'(%s) not a valid %s property flags!\n\n", - defContext.optionName.c_str(), name.c_str(), defContext.propertyFlags.c_str(), COMPONENT_NAME_EX(defContext.componentType)); - - return false; - } - } - else if(defContext.type == DefContext::DC_TYPE_METHOD || - defContext.type == DefContext::DC_TYPE_CLIENT_METHOD) - { - name += "." + defContext.attrName; - } - else if (defContext.type == DefContext::DC_TYPE_FIXED_ITEM) - { - name += "." + defContext.attrName; - } - else if (defContext.type == DefContext::DC_TYPE_FIXED_ARRAY || - defContext.type == DefContext::DC_TYPE_FIXED_DICT || - defContext.type == DefContext::DC_TYPE_RENAME) - { - if (!DataTypes::validTypeName(name)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: Not allowed to use the prefix \"_\"! typeName=%s\n", - defContext.optionName.c_str(), name.c_str()); - - return false; - } - } - - DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.find(name); - if (iter != DefContext::allScriptDefContextMaps.end()) - { - if (iter->second.pyObjectSourceFile != defContext.pyObjectSourceFile) - { - // Dz̵ͬĽű֣ôҪкϲע - if (iter->second.componentType != defContext.componentType && DefContext::allScriptDefContextLineMaps.find(defContext.pyObjectSourceFile) != DefContext::allScriptDefContextLineMaps.end() && - (defContext.type == DefContext::DC_TYPE_ENTITY || defContext.type == DefContext::DC_TYPE_COMPONENT || defContext.type == DefContext::DC_TYPE_INTERFACE) && - iter->second.type == defContext.type) - { - std::vector< std::string >::iterator bciter = defContext.baseClasses.begin(); - for (; bciter != defContext.baseClasses.end(); ++bciter) - { - if (std::find(iter->second.baseClasses.begin(), iter->second.baseClasses.end(), (*bciter)) == iter->second.baseClasses.end()) - { - iter->second.baseClasses.push_back((*bciter)); - } - - KBE_ASSERT(defContext.methods.size() == 0 && defContext.client_methods.size() == 0 && defContext.components.size() == 0 && defContext.propertys.size() == 0); - if (defContext.hasClient) - iter->second.hasClient = true; - - } - - return true; - } - - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' already exists!\n", - defContext.optionName.c_str(), name.c_str()); - - return false; - } - - return true; - } - - DefContext::allScriptDefContextMaps[name] = defContext; - return assemblyContexts(); -} - -//------------------------------------------------------------------------------------- - -static bool onDefRename(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_RENAME; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefFixedDict(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_FIXED_DICT; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefFixedArray(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_FIXED_ARRAY; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefFixedItem(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_FIXED_ITEM; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefProperty(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_PROPERTY; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefMethod(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_METHOD; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefClientMethod(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_CLIENT_METHOD; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefEntity(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_ENTITY; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefInterface(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_INTERFACE; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool onDefComponent(DefContext& defContext) -{ - defContext.type = DefContext::DC_TYPE_COMPONENT; - return registerDefContext(defContext); -} - -//------------------------------------------------------------------------------------- -static bool isRefEntityDefModule(PyObject *pyObj) -{ - if(!pyObj) - return true; - - PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); - PyObject* pydict = PyObject_GetAttrString(entitydefModule, "__dict__"); - - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pydict, &pos, &key, &value)) { - if (value == pyObj) - { - Py_DECREF(pydict); - return true; - } - } - - Py_DECREF(pydict); - return false; -} - -//------------------------------------------------------------------------------------- -#define PY_RETURN_ERROR { DefContext::allScriptDefContextLineMaps.clear(); DefContext::allScriptDefContextMaps.clear(); while(!g_callContexts.empty()) g_callContexts.pop(); return NULL; } - -#define PYOBJECT_SOURCEFILE(PYOBJ, OUT) \ -{ \ - PyObject* pyInspectModule = \ - PyImport_ImportModule(const_cast("inspect")); \ - \ - PyObject* pyGetsourcefile = NULL; \ - PyObject* pyGetLineno = NULL; \ - PyObject* pyGetCurrentFrame = NULL; \ - \ - if (pyInspectModule) \ - { \ - pyGetsourcefile = \ - PyObject_GetAttrString(pyInspectModule, const_cast("getsourcefile")); \ - pyGetLineno = \ - PyObject_GetAttrString(pyInspectModule, const_cast("getlineno")); \ - pyGetCurrentFrame = \ - PyObject_GetAttrString(pyInspectModule, const_cast("currentframe")); \ - \ - Py_DECREF(pyInspectModule); \ - } \ - else \ - { \ - PY_RETURN_ERROR; \ - } \ - \ - if (pyGetsourcefile) \ - { \ - PyObject* pyFile = PyObject_CallFunction(pyGetsourcefile, \ - const_cast("(O)"), PYOBJ); \ - \ - Py_DECREF(pyGetsourcefile); \ - \ - if (!pyFile) \ - { \ - Py_XDECREF(pyGetLineno); \ - Py_XDECREF(pyGetCurrentFrame); \ - PY_RETURN_ERROR; \ - } \ - else \ - { \ - /* ֹͬϵͳɵ·һ£޳ϵͳ· */ \ - OUT = PyUnicode_AsUTF8AndSize(pyFile, NULL); \ - strutil::kbe_replace(OUT, "\\\\", "/"); \ - strutil::kbe_replace(OUT, "\\", "/"); \ - strutil::kbe_replace(OUT, "//", "/"); \ - std::string kbe_root = Resmgr::getSingleton().getPyUserScriptsPath(); \ - strutil::kbe_replace(kbe_root, "\\\\", "/"); \ - strutil::kbe_replace(kbe_root, "\\", "/"); \ - strutil::kbe_replace(kbe_root, "/", "/"); \ - strutil::kbe_replace(OUT, kbe_root, ""); \ - Py_DECREF(pyFile); \ - } \ - } \ - else \ - { \ - Py_XDECREF(pyGetLineno); \ - Py_XDECREF(pyGetCurrentFrame); \ - PY_RETURN_ERROR; \ - } \ - \ - if (pyGetLineno) \ - { \ - if(!pyGetCurrentFrame) \ - { \ - Py_DECREF(pyGetLineno); \ - } \ - \ - PyObject* pyCurrentFrame = PyObject_CallFunction(pyGetCurrentFrame, \ - const_cast("()")); \ - \ - PyObject* pyLine = PyObject_CallFunction(pyGetLineno, \ - const_cast("(O)"), pyCurrentFrame); \ - \ - Py_DECREF(pyGetLineno); \ - Py_DECREF(pyGetCurrentFrame); \ - Py_DECREF(pyCurrentFrame); \ - \ - if (!pyLine) \ - { \ - PY_RETURN_ERROR; \ - } \ - else \ - { \ - /* кţͬļжζ */ \ - OUT += fmt::format("#{}", PyLong_AsLong(pyLine)); \ - Py_DECREF(pyLine); \ - } \ - } \ - else \ - { \ - Py_XDECREF(pyGetCurrentFrame); \ - PY_RETURN_ERROR; \ - } \ -} - -static PyObject* __py_def_parse(PyObject *self, PyObject* args) -{ - CallContext cc = g_callContexts.top(); - g_callContexts.pop(); - - DefContext defContext; - defContext.optionName = cc.optionName; - - PyObject* kbeModule = PyImport_AddModule("KBEngine"); - KBE_ASSERT(kbeModule); - - PyObject* pyComponentName = PyObject_GetAttrString(kbeModule, "component"); - if (!pyComponentName) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.__py_def_call(): get KBEngine.component error!\n"); - PY_RETURN_ERROR; - } - - defContext.componentType = ComponentName2ComponentType(PyUnicode_AsUTF8AndSize(pyComponentName, NULL)); - Py_DECREF(pyComponentName); - - if (!args || PyTuple_Size(args) < 1) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.__py_def_call(EntityDef.%s): error!\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - PyObject* pyFunc = PyTuple_GET_ITEM(args, 0); - - PyObject* pyModuleQualname = PyObject_GetAttrString(pyFunc, "__qualname__"); - if (!pyModuleQualname) - { - PY_RETURN_ERROR; - } - - const char* moduleQualname = PyUnicode_AsUTF8AndSize(pyModuleQualname, NULL); - Py_DECREF(pyModuleQualname); - - defContext.pyObjectPtr = PyObjectPtr(pyFunc); - PYOBJECT_SOURCEFILE(defContext.pyObjectPtr.get(), defContext.pyObjectSourceFile); - - if (defContext.optionName == "method") - { - static char * keywords[] = - { - const_cast ("exposed"), - const_cast ("utype"), - NULL - }; - - PyObject* pyExposed = NULL; - PyObject* pyUtype = NULL; - - if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|OO", - keywords, &pyExposed, &pyUtype)) - { - PY_RETURN_ERROR; - } - - if (pyExposed && !PyBool_Check(pyExposed)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'exposed\' error! not a bool type.\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - if (pyUtype && !PyLong_Check(pyUtype)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'utype\' error! not a number type.\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - defContext.exposed = pyExposed == Py_True; - - if (pyUtype) - defContext.utype = (int)PyLong_AsLong(pyUtype); - } - else if (defContext.optionName == "property" || defContext.optionName == "fixed_item") - { - if (defContext.optionName != "fixed_item") - { - static char * keywords[] = - { - const_cast ("flags"), - const_cast ("persistent"), - const_cast ("index"), - const_cast ("databaseLength"), - const_cast ("utype"), - NULL - }; - - PyObject* pyFlags = NULL; - PyObject* pyPersistent = NULL; - PyObject* pyIndex = NULL; - PyObject* pyDatabaseLength = NULL; - PyObject* pyUtype = NULL; - - if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|OOOOO", - keywords, &pyFlags, &pyPersistent, &pyIndex, &pyDatabaseLength, &pyUtype)) - { - PY_RETURN_ERROR; - } - - if (!pyFlags || !isRefEntityDefModule(pyFlags)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'flags\' must be referenced from the [EntityDef.ALL_CLIENTS, EntityDef.*] module!\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - if (!isRefEntityDefModule(pyIndex)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'index\' must be referenced from the [EntityDef.UNIQUE, EntityDef.INDEX] module!\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - if (pyDatabaseLength && !PyLong_Check(pyDatabaseLength)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'databaseLength\' error! not a number type.\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - if (pyPersistent && !PyBool_Check(pyPersistent)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'persistent\' error! not a bool type.\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - if(pyUtype && !PyLong_Check(pyUtype)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'utype\' error! not a number type.\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - defContext.propertyFlags = PyUnicode_AsUTF8AndSize(pyFlags, NULL); - - if (pyPersistent) - defContext.persistent = pyPersistent == Py_True; - - if (pyIndex) - defContext.propertyIndex = PyUnicode_AsUTF8AndSize(pyIndex, NULL); - - if (pyDatabaseLength) - defContext.databaseLength = (int)PyLong_AsLong(pyDatabaseLength); - - if (pyUtype) - defContext.utype = (int)PyLong_AsLong(pyUtype); - } - - // ԣ Ҫ÷ֵΪĬֵ - PyObject* pyRet = PyObject_CallFunction(pyFunc, - const_cast("(O)"), Py_None); - - if (!pyRet) - return NULL; - - if (pyRet != Py_None) - { - PyObject* pyStrResult = PyObject_Str(pyRet); - Py_DECREF(pyRet); - - defContext.propertyDefaultVal = PyUnicode_AsUTF8AndSize(pyStrResult, NULL); - Py_DECREF(pyStrResult); - - // ַ֤ǷԻԭɶ - if (defContext.propertyDefaultVal.size() > 0) - { - PyObject* module = PyImport_AddModule("__main__"); - if (module == NULL) - return NULL; - - PyObject* mdict = PyModule_GetDict(module); // Borrowed reference. - PyObject* result = PyRun_String(const_cast(defContext.propertyDefaultVal.c_str()), - Py_eval_input, mdict, mdict); - - if (result == NULL) - return NULL; - - Py_DECREF(result); - } - } - else - { - Py_DECREF(pyRet); - } - } - else if (defContext.optionName == "entity") - { - defContext.isModuleScope = true; - - static char * keywords[] = - { - const_cast ("hasClient"), - NULL - }; - - PyObject* pyHasClient = NULL; - - if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|O", - keywords, &pyHasClient)) - { - PY_RETURN_ERROR; - } - - defContext.hasClient = pyHasClient == Py_True; - } - else if (defContext.optionName == "interface") - { - defContext.isModuleScope = true; - defContext.inheritEngineModuleType = DefContext::DC_TYPE_INTERFACE; - } - else if (defContext.optionName == "component") - { - defContext.isModuleScope = true; - } - else if (defContext.optionName == "fixed_dict") - { - defContext.isModuleScope = true; - - static char * keywords[] = - { - const_cast ("implementedBy"), - NULL - }; - - PyObject* pImplementedBy = NULL; - - if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|O", - keywords, &pImplementedBy)) - { - PY_RETURN_ERROR; - } - - if (pImplementedBy) - { - if (isRefEntityDefModule(pImplementedBy)) - { - if (std::string(PyUnicode_AsUTF8AndSize(pImplementedBy, NULL)) == "thisClass") - { - defContext.implementedBy = pyFunc; - } - } - else - { - defContext.implementedBy = pImplementedBy; - } - - PyObject* pyQualname = PyObject_GetAttrString(defContext.implementedBy.get(), "__qualname__"); - if (!pyQualname) - { - PY_RETURN_ERROR; - } - - defContext.implementedByModuleName = PyUnicode_AsUTF8AndSize(pyQualname, NULL); - Py_DECREF(pyQualname); - - PYOBJECT_SOURCEFILE(defContext.implementedBy.get(), defContext.implementedByModuleFile); - } - } - else if (defContext.optionName == "fixed_array") - { - defContext.isModuleScope = true; - } - else if (defContext.optionName == "fixed_item") - { - } - else if (defContext.optionName == "rename") - { - } - else - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: not support!\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - if (!defContext.isModuleScope) - { - std::vector outs; - - if (moduleQualname) - strutil::kbe_splits(moduleQualname, ".", outs); - - if (defContext.optionName != "rename") - { - if (outs.size() != 2) - { - if(PyFunction_Check(pyFunc)) - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' must be defined in the entity module!\n", - defContext.optionName.c_str(), moduleQualname); - else - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: please check the command format is: EntityDef.%s(..)\n", - defContext.optionName.c_str(), defContext.optionName.c_str()); - - PY_RETURN_ERROR; - } - - defContext.moduleName = outs[0]; - defContext.attrName = outs[1]; - } - else - { - if (outs.size() != 1) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: error! such as: @EntityDef.rename()\n\tdef ENTITY_ID() -> EntityDef.INT32: pass\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - - defContext.moduleName = outs[0]; - } - - PyObject* pyInspectModule = - PyImport_ImportModule(const_cast("inspect")); - - PyObject* pyGetfullargspec = NULL; - if (pyInspectModule) - { - pyGetfullargspec = - PyObject_GetAttrString(pyInspectModule, const_cast("getfullargspec")); - - Py_DECREF(pyInspectModule); - } - else - { - PY_RETURN_ERROR; - } - - if (pyGetfullargspec) - { - PyObject* pyGetMethodArgs = PyObject_CallFunction(pyGetfullargspec, - const_cast("(O)"), pyFunc); - - if (!pyGetMethodArgs) - { - PY_RETURN_ERROR; - } - else - { - PyObject* pyGetMethodArgsResult = PyObject_GetAttrString(pyGetMethodArgs, const_cast("args")); - PyObject* pyGetMethodAnnotationsResult = PyObject_GetAttrString(pyGetMethodArgs, const_cast("annotations")); - - Py_DECREF(pyGetMethodArgs); - - if (!pyGetMethodArgsResult || !pyGetMethodAnnotationsResult) - { - Py_XDECREF(pyGetMethodArgsResult); - Py_XDECREF(pyGetMethodAnnotationsResult); - PY_RETURN_ERROR; - } - - PyObjectPtr pyGetMethodArgsResultPtr = pyGetMethodArgsResult; - PyObjectPtr pyGetMethodAnnotationsResultPtr = pyGetMethodAnnotationsResult; - Py_DECREF(pyGetMethodArgsResult); - Py_DECREF(pyGetMethodAnnotationsResult); - - if (defContext.optionName != "rename") - { - Py_ssize_t argsSize = PyList_Size(pyGetMethodArgsResult); - if (argsSize == 0) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' did not find \'self\' parameter!\n", defContext.optionName.c_str(), moduleQualname); - PY_RETURN_ERROR; - } - - for (Py_ssize_t i = 1; i < argsSize; ++i) - { - PyObject* pyItem = PyList_GetItem(pyGetMethodArgsResult, i); - - const char* ccattr = PyUnicode_AsUTF8AndSize(pyItem, NULL); - if (!ccattr) - { - PY_RETURN_ERROR; - } - - defContext.argsvecs.push_back(ccattr); - } - } - - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyGetMethodAnnotationsResult, &pos, &key, &value)) { - const char* skey = PyUnicode_AsUTF8AndSize(key, NULL); - if (!skey) - { - PY_RETURN_ERROR; - } - - std::string svalue = ""; - - // EntityDef.Array˴һtupleο__py_array - if (PyTuple_Check(value) && PyTuple_Size(value) == 2) - { - PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); - PyObject* pyARRAY = PyObject_GetAttrString(entitydefModule, "ARRAY"); - PyObject* item0 = PyTuple_GET_ITEM(value, 0); - - if (pyARRAY == item0) - { - value = PyTuple_GET_ITEM(value, 1); - defContext.optionName = "anonymous_fixed_array"; - - if (std::string(skey) != "return") - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'EntityDef.ARRAY\' Can only be used to define property types!\n", defContext.optionName.c_str()); - PY_RETURN_ERROR; - } - } - else - { - Py_DECREF(pyARRAY); - PY_RETURN_ERROR; - } - - Py_DECREF(pyARRAY); - } - - if (PyUnicode_Check(value)) - { - svalue = PyUnicode_AsUTF8AndSize(value, NULL); - } - else - { - PyObject* pyQualname = PyObject_GetAttrString(value, "__qualname__"); - if (!pyQualname) - { - PY_RETURN_ERROR; - } - - svalue = PyUnicode_AsUTF8AndSize(pyQualname, NULL); - Py_DECREF(pyQualname); - } - - if (svalue.size() == 0) - { - PY_RETURN_ERROR; - } - - if (std::string(skey) == "return") - defContext.returnType = svalue; - else - defContext.annotationsMaps[skey] = svalue; - } - } - } - else - { - PY_RETURN_ERROR; - } - } - else - { - defContext.moduleName = moduleQualname; - - PyObject* pyBases = PyObject_GetAttrString(pyFunc, "__bases__"); - if (!pyBases) - PY_RETURN_ERROR; - - Py_ssize_t basesSize = PyTuple_Size(pyBases); - if (basesSize == 0) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' does not inherit the KBEngine.Entity class!\n", defContext.optionName.c_str(), moduleQualname); - Py_XDECREF(pyBases); - PY_RETURN_ERROR; - } - - for (Py_ssize_t i = 0; i < basesSize; ++i) - { - PyObject* pyClass = PyTuple_GetItem(pyBases, i); - - PyObject* pyQualname = PyObject_GetAttrString(pyClass, "__qualname__"); - if (!pyQualname) - { - Py_XDECREF(pyBases); - PY_RETURN_ERROR; - } - - std::string parentClass = PyUnicode_AsUTF8AndSize(pyQualname, NULL); - Py_DECREF(pyQualname); - - if (parentClass == "object") - { - continue; - } - else if (parentClass == "Entity") - { - defContext.inheritEngineModuleType = DefContext::DC_TYPE_ENTITY; - continue; - } - else if (parentClass == "Proxy") - { - if (defContext.componentType != BASEAPP_TYPE) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' Only BASE can inherit KBEngine.Proxy!\n", defContext.optionName.c_str(), moduleQualname); - PY_RETURN_ERROR; - } - - defContext.inheritEngineModuleType = DefContext::DC_TYPE_ENTITY; - continue; - } - else if (parentClass == "EntityComponent") - { - defContext.inheritEngineModuleType = DefContext::DC_TYPE_COMPONENT; - continue; - } - - defContext.baseClasses.push_back(parentClass); - } - - Py_XDECREF(pyBases); - } - - bool noerror = true; - - if (defContext.optionName == "method" || defContext.optionName == "clientmethod") - { - if (defContext.annotationsMaps.size() != defContext.argsvecs.size()) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' all parameters must have annotations!\n", defContext.optionName.c_str(), moduleQualname); - PY_RETURN_ERROR; - } - - if (defContext.optionName == "method") - noerror = onDefMethod(defContext); - else - noerror = onDefClientMethod(defContext); - } - else if (defContext.optionName == "rename") - { - noerror = onDefRename(defContext); - } - else if (defContext.optionName == "property") - { - noerror = onDefProperty(defContext); - } - else if (defContext.optionName == "entity") - { - noerror = onDefEntity(defContext); - } - else if (defContext.optionName == "interface") - { - noerror = onDefInterface(defContext); - } - else if (defContext.optionName == "component") - { - noerror = onDefComponent(defContext); - } - else if (defContext.optionName == "fixed_dict") - { - noerror = onDefFixedDict(defContext); - } - else if (defContext.optionName == "fixed_array") - { - noerror = onDefFixedArray(defContext); - } - else if (defContext.optionName == "anonymous_fixed_array") - { - // һ - DefContext arrayType; - arrayType = defContext; - arrayType.moduleName += ".anonymous_fixed_array"; - - // ֹ2Դļһ£ײΪظ - arrayType.pyObjectSourceFile += "(array)"; - - // һitem - DefContext itemType; - itemType = arrayType; - itemType.optionName = "fixed_item"; - - // ֹ2Դļһ£ײΪظ - itemType.pyObjectSourceFile += "(array_item)"; - - noerror = onDefFixedItem(itemType); - - arrayType.returnType = ""; - - if(noerror) - noerror = onDefFixedArray(arrayType); - - defContext.returnType = arrayType.moduleName; - - if (noerror) - noerror = onDefFixedItem(defContext); - } - else if (defContext.optionName == "fixed_item") - { - noerror = onDefFixedItem(defContext); - } - - if (!noerror) - { - PY_RETURN_ERROR; - } - - Py_INCREF(pyFunc); - return pyFunc; -} - -//------------------------------------------------------------------------------------- -static PyMethodDef __call_def_parse = { "_PyEntityDefParse", (PyCFunction)&__py_def_parse, METH_VARARGS, 0 }; - -#define PY_DEF_HOOK(NAME) \ - static PyObject* __py_def_##NAME(PyObject* self, PyObject* args, PyObject* kwargs) \ - { \ - CallContext cc; \ - cc.pyArgs = PyObjectPtr(Copy::deepcopy(args)); \ - cc.pyKwargs = kwargs ? PyObjectPtr(Copy::deepcopy(kwargs)) : PyObjectPtr(NULL); \ - cc.optionName = #NAME; \ - g_callContexts.push(cc); \ - Py_XDECREF(cc.pyArgs.get()); \ - Py_XDECREF(cc.pyKwargs.get()); \ - \ - return PyCFunction_New(&__call_def_parse, self); \ - } - -static PyObject* __py_def_rename(PyObject* self, PyObject* args, PyObject* kwargs) -{ - CallContext cc; - cc.pyArgs = PyObjectPtr(Copy::deepcopy(args)); - cc.pyKwargs = kwargs ? PyObjectPtr(Copy::deepcopy(kwargs)) : PyObjectPtr(NULL); - cc.optionName = "rename"; - - Py_XDECREF(cc.pyArgs.get()); - Py_XDECREF(cc.pyKwargs.get()); - - // ֶ巽ʽ EntityDef.rename(ENTITY_ID=EntityDef.INT32) - if (kwargs) - { - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(kwargs, &pos, &key, &value)) { - if (!PyType_Check(value)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 not legal type! such as: EntityDef.rename(ENTITY_ID=EntityDef.INT32)\n", cc.optionName.c_str()); - return NULL; - } - - PyObject* pyQualname = PyObject_GetAttrString(value, "__qualname__"); - if (!pyQualname) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 get __qualname__ error! such as: EntityDef.rename(ENTITY_ID=EntityDef.INT32)\n", cc.optionName.c_str()); - return NULL; - } - - std::string typeName = PyUnicode_AsUTF8AndSize(pyQualname, NULL); - Py_DECREF(pyQualname); - - if (!PyUnicode_Check(key)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg1 must be a string! such as: EntityDef.rename(ENTITY_ID=EntityDef.INT32)\n", cc.optionName.c_str()); - return NULL; - } - - DefContext defContext; - defContext.optionName = cc.optionName; - defContext.moduleName = PyUnicode_AsUTF8AndSize(key, NULL); - defContext.returnType = typeName; - - PyObject* kbeModule = PyImport_AddModule("KBEngine"); - KBE_ASSERT(kbeModule); - - PyObject* pyComponentName = PyObject_GetAttrString(kbeModule, "component"); - if (!pyComponentName) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.rename(): get KBEngine.component error!\n"); - PY_RETURN_ERROR; - } - - defContext.componentType = ComponentName2ComponentType(PyUnicode_AsUTF8AndSize(pyComponentName, NULL)); - Py_DECREF(pyComponentName); - - if (!onDefRename(defContext)) - return NULL; - } - - S_Return; - } - - g_callContexts.push(cc); - - // @EntityDef.rename() - // def ENTITY_ID() -> int: pass - return PyCFunction_New(&__call_def_parse, self); -} - -static PyObject* __py_def_fixed_array(PyObject* self, PyObject* args, PyObject* kwargs) -{ - CallContext cc; - cc.pyArgs = PyObjectPtr(Copy::deepcopy(args)); - cc.pyKwargs = kwargs ? PyObjectPtr(Copy::deepcopy(kwargs)) : PyObjectPtr(NULL); - cc.optionName = "fixed_array"; - - Py_XDECREF(cc.pyArgs.get()); - Py_XDECREF(cc.pyKwargs.get()); - - // ֶ巽ʽ EntityDef.fixed_array(XXArray=EntityDef.INT32) - if (kwargs) - { - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(kwargs, &pos, &key, &value)) { - if (!PyType_Check(value)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 not legal type! such as: EntityDef.fixed_array(XXArray=EntityDef.INT32)\n", cc.optionName.c_str()); - return NULL; - } - - PyObject* pyQualname = PyObject_GetAttrString(value, "__qualname__"); - if (!pyQualname) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 get __qualname__ error! such as: EntityDef.fixed_array(XXArray=EntityDef.INT32)\n", cc.optionName.c_str()); - return NULL; - } - - std::string typeName = PyUnicode_AsUTF8AndSize(pyQualname, NULL); - Py_DECREF(pyQualname); - - if (!PyUnicode_Check(key)) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg1 must be a string! such as: EntityDef.fixed_array(XXArray=EntityDef.INT32)\n", cc.optionName.c_str()); - return NULL; - } - - DefContext defContext; - defContext.optionName = cc.optionName; - defContext.moduleName = PyUnicode_AsUTF8AndSize(key, NULL); - defContext.returnType = typeName; - - PyObject* kbeModule = PyImport_AddModule("KBEngine"); - KBE_ASSERT(kbeModule); - - PyObject* pyComponentName = PyObject_GetAttrString(kbeModule, "component"); - if (!pyComponentName) - { - PyErr_Format(PyExc_AssertionError, "EntityDef.fixed_array(): get KBEngine.component error!\n"); - PY_RETURN_ERROR; - } - - defContext.componentType = ComponentName2ComponentType(PyUnicode_AsUTF8AndSize(pyComponentName, NULL)); - Py_DECREF(pyComponentName); - - if (!onDefRename(defContext)) - return NULL; - } - - S_Return; - } - - g_callContexts.push(cc); - - // @EntityDef.fixed_array() - // class XXXArray - return PyCFunction_New(&__call_def_parse, self); -} - -#define PY_ADD_METHOD(NAME, DOCS) APPEND_SCRIPT_MODULE_METHOD(entitydefModule, NAME, __py_def_##NAME, METH_VARARGS | METH_KEYWORDS, 0); - -#ifdef interface -#undef interface -#endif - -#ifdef property -#undef property -#endif - -PY_DEF_HOOK(method) -PY_DEF_HOOK(clientmethod) -PY_DEF_HOOK(property) -PY_DEF_HOOK(entity) -PY_DEF_HOOK(interface) -PY_DEF_HOOK(component) -PY_DEF_HOOK(fixed_dict) -PY_DEF_HOOK(fixed_item) - -//------------------------------------------------------------------------------------- -bool installModule(const char* moduleName) -{ - pyDefModuleName = moduleName; - - PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); - PyObject_SetAttrString(entitydefModule, "__doc__", PyUnicode_FromString("This module is created by KBEngine!")); - - PY_ADD_METHOD(rename, ""); - PY_ADD_METHOD(method, ""); - PY_ADD_METHOD(clientmethod, ""); - PY_ADD_METHOD(property, ""); - PY_ADD_METHOD(entity, ""); - PY_ADD_METHOD(interface, ""); - PY_ADD_METHOD(component, ""); - PY_ADD_METHOD(fixed_dict, ""); - PY_ADD_METHOD(fixed_array, ""); - PY_ADD_METHOD(fixed_item, ""); - - return true; -} - -//------------------------------------------------------------------------------------- -bool uninstallModule() -{ - while (!g_callContexts.empty()) g_callContexts.pop(); - DefContext::allScriptDefContextMaps.clear(); - DefContext::allScriptDefContextLineMaps.clear(); - return true; -} - -//------------------------------------------------------------------------------------- -static bool loadAllScriptForComponentType(COMPONENT_TYPE loadComponentType) -{ - std::string entryScriptFileName = ""; - if (loadComponentType == BASEAPP_TYPE) - { - ENGINE_COMPONENT_INFO& info = g_kbeSrvConfig.getBaseApp(); - entryScriptFileName = info.entryScriptFile; - } - else if (loadComponentType == CELLAPP_TYPE) - { - ENGINE_COMPONENT_INFO& info = g_kbeSrvConfig.getCellApp(); - entryScriptFileName = info.entryScriptFile; - } - else - { - KBE_ASSERT(false); - } - - std::string rootPath = Resmgr::getSingleton().getPyUserComponentScriptsPath(loadComponentType); - - if (rootPath.size() == 0) - { - ERROR_MSG(fmt::format("PyEntityDef::loadAllScriptForComponentType(): get scripts path error! loadComponentType={}\n", - COMPONENT_NAME_EX(loadComponentType))); - - return false; - } - - while (rootPath[rootPath.size() - 1] == '/' || rootPath[rootPath.size() - 1] == '\\') rootPath.pop_back(); - - wchar_t* wpath = strutil::char2wchar((rootPath).c_str()); - - wchar_t* _wentryScriptFileName = strutil::char2wchar((entryScriptFileName).c_str()); - std::wstring wentryScriptFileName = _wentryScriptFileName; - free(_wentryScriptFileName); - - std::vector results; - Resmgr::getSingleton().listPathRes(wpath, L"py|pyc", results); - - // ִڽű - std::vector::iterator iter = results.begin(); - for (; iter != results.end(); ) - { - std::wstring wstrpath = (*iter); - if (wstrpath.find(wentryScriptFileName + L".py") == std::wstring::npos && wstrpath.find(wentryScriptFileName + L".pyc") == std::wstring::npos) - { - ++iter; - continue; - } - - iter = results.erase(iter); - } - - results.insert(results.begin(), std::wstring(wpath) + L"/" + wentryScriptFileName + L".py"); - - iter = results.begin(); - for (; iter != results.end(); ++iter) - { - std::wstring wstrpath = (*iter); - - if (wstrpath.find(L"__pycache__") != std::wstring::npos) - continue; - - if (wstrpath.find(L"__init__.") != std::wstring::npos) - continue; - - std::pair pathPair = script::PyPlatform::splitPath(wstrpath); - std::pair filePair = script::PyPlatform::splitText(pathPair.second); - - if (filePair.first.size() == 0) - continue; - - char* cpacketPath = strutil::wchar2char(pathPair.first.c_str()); - std::string packetPath = cpacketPath; - free(cpacketPath); - - strutil::kbe_replace(packetPath, rootPath, ""); - while (packetPath.size() > 0 && (packetPath[0] == '/' || packetPath[0] == '\\')) packetPath.erase(0, 1); - strutil::kbe_replace(packetPath, "/", "."); - strutil::kbe_replace(packetPath, "\\", "."); - - char* moduleName = strutil::wchar2char(filePair.first.c_str()); - - // ڽűڲܻimportظimport ǹѾimportģ - if (DefContext::allScriptDefContextMaps.find(moduleName) == DefContext::allScriptDefContextMaps.end()) - { - PyObject* pyModule = NULL; - - if (packetPath.size() == 0 || packetPath == "components" || packetPath == "interfaces") - { - pyModule = PyImport_ImportModule(const_cast(moduleName)); - } - else - { - pyModule = PyImport_ImportModule(const_cast((packetPath + "." + moduleName).c_str())); - } - - if (!pyModule) - { - SCRIPT_ERROR_CHECK(); - free(wpath); - return false; - } - else - { - Py_DECREF(pyModule); - } - } - - free(moduleName); - } - - free(wpath); - - return true; -} - -//------------------------------------------------------------------------------------- -PyObject* __py_getAppPublish(PyObject* self, PyObject* args) -{ - return PyLong_FromLong(g_appPublish); -} - -//------------------------------------------------------------------------------------- -static bool execPython(COMPONENT_TYPE componentType) -{ - std::pair pyPaths = getComponentPythonPaths(componentType); - if (pyPaths.first.size() == 0) - { - ERROR_MSG(fmt::format("PyEntityDef::execPython(): PythonApp({}) paths error!\n", COMPONENT_NAME_EX(componentType))); - return false; - } - - APPEND_PYSYSPATH(pyPaths.second); - - PyObject* modulesOld = PySys_GetObject("modules"); - - PyThreadState* pCurInterpreter = PyThreadState_Get(); - PyThreadState* pNewInterpreter = Py_NewInterpreter(); - - if (!pNewInterpreter) - { - ERROR_MSG(fmt::format("PyEntityDef::execPython(): Py_NewInterpreter()!\n")); - SCRIPT_ERROR_CHECK(); - return false; - } - -#if KBE_PLATFORM != PLATFORM_WIN32 - strutil::kbe_replace(pyPaths.second, L";", L":"); -#endif - - PySys_SetPath(pyPaths.second.c_str()); - - PyObject* modulesNew = PySys_GetObject("modules"); - PyDict_Merge(modulesNew, Script::getSingleton().getSysInitModules(), 0); - - { - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(modulesOld, &pos, &key, &value)) - { - const char* typeName = PyUnicode_AsUTF8AndSize(key, NULL); - - if (std::string(typeName) == "KBEngine") - continue; - - PyObject* pyDoc = PyObject_GetAttrString(value, "__doc__"); - - if (pyDoc) - { - const char* doc = PyUnicode_AsUTF8AndSize(pyDoc, NULL); - - if (doc && std::string(doc).find("KBEngine") != std::string::npos) - PyDict_SetItemString(modulesNew, typeName, value); - - if (PyErr_Occurred()) - PyErr_Clear(); - - Py_XDECREF(pyDoc); - } - else - { - SCRIPT_ERROR_CHECK(); - } - } - } - - PyObject *m = PyImport_AddModule("__main__"); - - // һűģ - PyObject* kbeModule = PyImport_AddModule("KBEngine"); - KBE_ASSERT(kbeModule); - - Entity::registerScript(kbeModule); - Space::registerScript(kbeModule); - EntityComponent::registerScript(kbeModule); - - if (componentType == BASEAPP_TYPE) - Proxy::registerScript(kbeModule); - - const char* componentName = COMPONENT_NAME_EX(componentType); - if (PyModule_AddStringConstant(kbeModule, "component", componentName)) - { - ERROR_MSG(fmt::format("PyEntityDef::execPython(): Unable to set KBEngine.component to {}\n", - componentName)); - - return false; - } - - APPEND_SCRIPT_MODULE_METHOD(kbeModule, publish, __py_getAppPublish, METH_VARARGS, 0); - - // ģmain - PyObject_SetAttrString(m, "KBEngine", kbeModule); - - if (pNewInterpreter != PyThreadState_Swap(pCurInterpreter)) - { - KBE_ASSERT(false); - return false; - } - - PyThreadState_Swap(pNewInterpreter); - - bool otherPartSuccess = loadAllScriptForComponentType(componentType); - - Entity::unregisterScript(); - Space::unregisterScript(); - EntityComponent::unregisterScript(); - - if (componentType == BASEAPP_TYPE) - Proxy::unregisterScript(); - - if (pNewInterpreter != PyThreadState_Swap(pCurInterpreter)) - { - KBE_ASSERT(false); - return false; - } - - // ˴ʹPy_EndInterpreterᵼMathDefģ - PyInterpreterState_Clear(pNewInterpreter->interp); - PyInterpreterState_Delete(pNewInterpreter->interp); - return otherPartSuccess; -} - -//------------------------------------------------------------------------------------- -static bool loadAllScripts() -{ - std::vector< COMPONENT_TYPE > loadOtherComponentTypes; - - if (g_componentType == CELLAPP_TYPE || g_componentType == BASEAPP_TYPE) - { - bool otherPartSuccess = loadAllScriptForComponentType(g_componentType); - if (!otherPartSuccess) - return false; - - loadOtherComponentTypes.push_back((g_componentType == BASEAPP_TYPE) ? CELLAPP_TYPE : BASEAPP_TYPE); - } - else - { - loadOtherComponentTypes.push_back(BASEAPP_TYPE); - loadOtherComponentTypes.push_back(CELLAPP_TYPE); - } - - for (std::vector< COMPONENT_TYPE >::iterator iter = loadOtherComponentTypes.begin(); iter != loadOtherComponentTypes.end(); ++iter) - { - COMPONENT_TYPE componentType = (*iter); - - if (!execPython(componentType)) - return false; - } - - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerDefTypes() -{ - DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); - for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) - { - DefContext& defContext = iter->second; - - if (defContext.type == DefContext::DC_TYPE_FIXED_ARRAY) - { - FixedArrayType* fixedArray = new FixedArrayType; - - if (fixedArray->initialize(&defContext, defContext.moduleName)) - { - if (!DataTypes::addDataType(defContext.moduleName, fixedArray)) - return false; - } - else - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: parse ARRAY [{}] error! file: \"{}\"!\n", - defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); - - delete fixedArray; - return false; - } - } - else if (defContext.type == DefContext::DC_TYPE_FIXED_DICT) - { - FixedDictType* fixedDict = new FixedDictType; - - if (fixedDict->initialize(&defContext, defContext.moduleName)) - { - if (!DataTypes::addDataType(defContext.moduleName, fixedDict)) - return false; - } - else - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: parse FIXED_DICT [{}] error! file: \"{}\"!\n", - defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); - - delete fixedDict; - return false; - } - } - else if (defContext.type == DefContext::DC_TYPE_RENAME) - { - DataType* dataType = DataTypes::getDataType(defContext.returnType, false); - if (dataType == NULL) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: cannot fount type \'{}\', by alias[{}], file: \"{}\"!\n", - defContext.returnType, defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); - - return false; - } - - if (!DataTypes::addDataType(defContext.moduleName, dataType)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: addDataType \"{}\" error! file: \"{}\"!\n", - defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); - - return false; - } - } - } - - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerDetailLevelInfo(ScriptDefModule* pScriptModule, DefContext& defContext) -{ - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerVolatileInfo(ScriptDefModule* pScriptModule, DefContext& defContext) -{ - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerDefPropertys(ScriptDefModule* pScriptModule, DefContext& defContext) -{ - DefContext::DEF_CONTEXTS& propertys = defContext.propertys; - - DefContext::DEF_CONTEXTS::iterator iter = propertys.begin(); - for (; iter != propertys.end(); ++iter) - { - DefContext& defPropContext = (*iter); - - ENTITY_PROPERTY_UID futype = 0; - EntityDataFlags flags = stringToEntityDataFlags(defPropContext.propertyFlags); - int32 hasBaseFlags = 0; - int32 hasCellFlags = 0; - int32 hasClientFlags = 0; - DataType* dataType = NULL; - bool isPersistent = (defPropContext.persistent != 0); - bool isIdentifier = false; // Ƿһ - uint32 databaseLength = defPropContext.databaseLength; // ݿеij - std::string indexType = defPropContext.propertyIndex; - DETAIL_TYPE detailLevel = DETAIL_LEVEL_FAR; - std::string name = defPropContext.attrName; - - if (!EntityDef::validDefPropertyName(name)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: '{}' is limited, in module({}), file: \"{}\"!\n", - name, pScriptModule->getName(), defPropContext.pyObjectSourceFile)); - - return false; - } - - if (defPropContext.detailLevel == "FAR") - detailLevel = DETAIL_LEVEL_FAR; - else if (defPropContext.detailLevel == "MEDIUM") - detailLevel = DETAIL_LEVEL_MEDIUM; - else if (defPropContext.detailLevel == "NEAR") - detailLevel = DETAIL_LEVEL_NEAR; - else - detailLevel = DETAIL_LEVEL_FAR; - - if (!EntityDef::calcDefPropertyUType(pScriptModule->getName(), name, defPropContext.utype > 0 ? defPropContext.utype : -1, pScriptModule, futype)) - return false; - - hasBaseFlags = ((uint32)flags) & ENTITY_BASE_DATA_FLAGS; - if (hasBaseFlags > 0) - pScriptModule->setBase(true); - - hasCellFlags = ((uint32)flags) & ENTITY_CELL_DATA_FLAGS; - if (hasCellFlags > 0) - pScriptModule->setCell(true); - - hasClientFlags = ((uint32)flags) & ENTITY_CLIENT_DATA_FLAGS; - if (hasClientFlags > 0) - pScriptModule->setClient(true); - - if (hasBaseFlags <= 0 && hasCellFlags <= 0) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: not fount flags[{}], is {}.{}, file: \"{}\"!\n", - defPropContext.propertyFlags, pScriptModule->getName(), defPropContext.pyObjectSourceFile)); - - return false; - } - - dataType = DataTypes::getDataType(defPropContext.returnType, false); - - if (!dataType) - { - DefContext* pDefPropTypeContext = DefContext::findDefContext(defPropContext.returnType); - if (!pDefPropTypeContext) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: not fount type[{}], is {}.{}, file: \"{}\"!\n", - defPropContext.returnType, pScriptModule->getName(), name.c_str(), defPropContext.pyObjectSourceFile)); - - return false; - } - - // ŵд - if (pDefPropTypeContext->type == DefContext::DC_TYPE_COMPONENT) - continue; - - if (pDefPropTypeContext->type == DefContext::DC_TYPE_FIXED_ARRAY) - { - FixedArrayType* dataType1 = new FixedArrayType(); - if (dataType1->initialize(pDefPropTypeContext, std::string(pScriptModule->getName()) + "_" + name)) - dataType = dataType1; - else - return false; - } - else - { - dataType = DataTypes::getDataType(defPropContext.returnType, false); - } - } - - if (dataType == NULL) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: not fount type[{}], is {}.{}, file: \"{}\"!\n", - defPropContext.returnType, pScriptModule->getName(), name.c_str(), defPropContext.pyObjectSourceFile)); - - return false; - } - - // һʵ - PropertyDescription* propertyDescription = PropertyDescription::createDescription(futype, defPropContext.returnType, - name, flags, isPersistent, - dataType, isIdentifier, indexType, - databaseLength, defPropContext.propertyDefaultVal, - detailLevel); - - bool ret = true; - - // ӵģ - if (hasCellFlags > 0) - ret = pScriptModule->addPropertyDescription(name.c_str(), - propertyDescription, CELLAPP_TYPE); - - if (hasBaseFlags > 0) - ret = pScriptModule->addPropertyDescription(name.c_str(), - propertyDescription, BASEAPP_TYPE); - - if (hasClientFlags > 0) - ret = pScriptModule->addPropertyDescription(name.c_str(), - propertyDescription, CLIENT_TYPE); - - if (!ret) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: error, is {}.{}, file: \"{}\"!\n", - pScriptModule->getName(), name.c_str(), defPropContext.pyObjectSourceFile)); - - return false; - } - } - - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerDefComponents(ScriptDefModule* pScriptModule, DefContext& defContext) -{ - DefContext::DEF_CONTEXTS& propertys = defContext.propertys; - - DefContext::DEF_CONTEXTS::iterator iter = propertys.begin(); - for (; iter != propertys.end(); ++iter) - { - DefContext& defPropContext = (*iter); - - std::string componentName = defPropContext.attrName; - std::string componentTypeName = defPropContext.returnType; - bool isPersistent = (defPropContext.persistent != 0); - ENTITY_PROPERTY_UID futype = 0; - - DefContext* pDefPropTypeContext = DefContext::findDefContext(componentTypeName); - if (!pDefPropTypeContext) - { - continue; - } - - if (pDefPropTypeContext->type != DefContext::DC_TYPE_COMPONENT) - continue; - - if (!EntityDef::calcDefPropertyUType(pScriptModule->getName(), componentName, defPropContext.utype > 0 ? defPropContext.utype : -1, pScriptModule, futype)) - return false; - - // һʵ - uint32 flags = ED_FLAG_BASE | ED_FLAG_CELL_PUBLIC | ENTITY_CLIENT_DATA_FLAGS; - bool isIdentifier = false; // Ƿһ - uint32 databaseLength = 0; // ݿеij - std::string indexType = ""; - DETAIL_TYPE detailLevel = DETAIL_LEVEL_FAR; - std::string detailLevelStr = ""; - std::string strisPersistent; - std::string defaultStr = ""; - - if (!EntityDef::validDefPropertyName(componentName)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: '{}' is limited, in module({}), file: \"{}\"!\n", - componentName, pScriptModule->getName(), defPropContext.pyObjectSourceFile)); - - return false; - } - - // Ƿģ飬˵Ѿعٴμ - ScriptDefModule* pCompScriptDefModule = EntityDef::findScriptModule(componentTypeName.c_str(), false); - - if (!pCompScriptDefModule) - { - pCompScriptDefModule = EntityDef::registerNewScriptDefModule(componentTypeName); - pCompScriptDefModule->isPersistent(false); - pCompScriptDefModule->isComponentModule(true); - } - else - { - flags = ED_FLAG_UNKOWN; - - if (pCompScriptDefModule->hasBase()) - flags |= ED_FLAG_BASE; - - if (pCompScriptDefModule->hasCell()) - flags |= ED_FLAG_CELL_PUBLIC; - - if (pCompScriptDefModule->hasClient()) - { - if (pCompScriptDefModule->hasBase()) - flags |= ED_FLAG_BASE_AND_CLIENT; - else - flags |= (ED_FLAG_ALL_CLIENTS | ED_FLAG_CELL_PUBLIC_AND_OWN | ED_FLAG_OTHER_CLIENTS | ED_FLAG_OWN_CLIENT); - } - - EntityDef::addComponentProperty(futype, componentTypeName, componentName, flags, isPersistent, isIdentifier, - indexType, databaseLength, defaultStr, detailLevel, pScriptModule, pCompScriptDefModule); - - pScriptModule->addComponentDescription(componentName.c_str(), pCompScriptDefModule); - continue; - } - - // - if (!registerDefPropertys(pScriptModule, defContext)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: failed to loadDefPropertys(), entity:{}\n", - pScriptModule->getName())); - - return false; - } - - // ԼdetailLevelInfo - if (!registerDetailLevelInfo(pScriptModule, defContext)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: failed to register component:{} detailLevelInfo.\n", - pScriptModule->getName())); - - return false; - } - - // ԼvolatileInfo - if (!registerVolatileInfo(pScriptModule, defContext)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: failed to register component:{} volatileInfo.\n", - pScriptModule->getName())); - - return false; - } - - pCompScriptDefModule->autoMatchCompOwn(); - - flags = ED_FLAG_UNKOWN; - - if (pCompScriptDefModule->hasBase()) - flags |= ED_FLAG_BASE; - - if (pCompScriptDefModule->hasCell()) - flags |= ED_FLAG_CELL_PUBLIC; - - if (pCompScriptDefModule->hasClient()) - { - if (pCompScriptDefModule->hasBase()) - flags |= ED_FLAG_BASE_AND_CLIENT; - - if (pCompScriptDefModule->hasCell()) - flags |= (ED_FLAG_ALL_CLIENTS | ED_FLAG_CELL_PUBLIC_AND_OWN | ED_FLAG_OTHER_CLIENTS | ED_FLAG_OWN_CLIENT); - } - - EntityDef::addComponentProperty(futype, componentTypeName, componentName, flags, isPersistent, isIdentifier, - indexType, databaseLength, defaultStr, detailLevel, pScriptModule, pCompScriptDefModule); - - pScriptModule->addComponentDescription(componentName.c_str(), pCompScriptDefModule); - } - - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerEntityDef(ScriptDefModule* pScriptModule, DefContext& defContext) -{ - // - if (!registerDefPropertys(pScriptModule, defContext)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to registerDefPropertys(), entity:{}\n", - pScriptModule->getName())); - - return false; - } - - // ǵķԼ뵽ģ - if (!registerDefComponents(pScriptModule, defContext)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to registerDefComponents(), component:{}\n", - pScriptModule->getName())); - - return false; - } - - // ԼdetailLevelInfo - if (!registerDetailLevelInfo(pScriptModule, defContext)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to register entity:{} detailLevelInfo.\n", - pScriptModule->getName())); - - return false; - } - - // ԼvolatileInfo - if (!registerVolatileInfo(pScriptModule, defContext)) - { - ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to register entity:{} volatileInfo.\n", - pScriptModule->getName())); - - return false; - } - - pScriptModule->setScriptType((PyTypeObject *)defContext.pyObjectPtr.get()); - pScriptModule->autoMatchCompOwn(); - return true; -} - -//------------------------------------------------------------------------------------- -static bool registerEntityDefs() -{ - if (!registerDefTypes()) - return false; - - DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); - for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) - { - DefContext& defContext = iter->second; - - if (defContext.type != DefContext::DC_TYPE_ENTITY) - continue; - - ScriptDefModule* pScriptModule = EntityDef::registerNewScriptDefModule(defContext.moduleName); - - if (!registerEntityDef(pScriptModule, defContext)) - return false; - - pScriptModule->onLoaded(); - } - - return true; -} - -//------------------------------------------------------------------------------------- -bool initialize() -{ - if (g_inited) - return false; - - g_inited = true; - - PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); - - ENTITYFLAGMAP::iterator iter = g_entityFlagMapping.begin(); - for (; iter != g_entityFlagMapping.end(); ++iter) - { - if (PyModule_AddStringConstant(entitydefModule, iter->first.c_str(), iter->first.c_str())) - { - ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", - iter->first, iter->first)); - - return false; - } - } - - static const char* UNIQUE = "UNIQUE"; - if (PyModule_AddStringConstant(entitydefModule, UNIQUE, UNIQUE)) - { - ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", - UNIQUE, UNIQUE)); - - return false; - } - - static const char* INDEX = "INDEX"; - if (PyModule_AddStringConstant(entitydefModule, INDEX, INDEX)) - { - ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", - INDEX, INDEX)); - - return false; - } - - static const char* thisClass = "thisClass"; - if (PyModule_AddStringConstant(entitydefModule, thisClass, thisClass)) - { - ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", - thisClass, thisClass)); - - return false; - } - - APPEND_SCRIPT_MODULE_METHOD(entitydefModule, ARRAY, __py_array, METH_VARARGS, 0); - - static char allBaseTypeNames[64][MAX_BUF]; - std::vector< std::string > baseTypeNames = DataTypes::getBaseTypeNames(); - KBE_ASSERT(baseTypeNames.size() < 64); - - for (size_t idx = 0; idx < baseTypeNames.size(); idx++) - { - memset(allBaseTypeNames[idx], 0, MAX_BUF); - kbe_snprintf(allBaseTypeNames[idx], MAX_BUF, "%s", baseTypeNames[idx].c_str()); - if (PyModule_AddStringConstant(entitydefModule, allBaseTypeNames[idx], allBaseTypeNames[idx])) - { - ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", - allBaseTypeNames[idx], allBaseTypeNames[idx])); - - return false; - } - } - - if (!loadAllScripts()) - { - SCRIPT_ERROR_CHECK(); - return false; - } - - while (!g_callContexts.empty()) - g_callContexts.pop(); - - DefContext::allScriptDefContextLineMaps.clear(); - - if (!assemblyContexts(true)) - { - SCRIPT_ERROR_CHECK(); - DefContext::allScriptDefContextMaps.clear(); - return false; - } - - if (!registerEntityDefs()) - { - DefContext::allScriptDefContextMaps.clear(); - return false; - } - - return true; -} - -//------------------------------------------------------------------------------------- -bool finalise(bool isReload) -{ - return true; -} - -//------------------------------------------------------------------------------------- -void reload(bool fullReload) -{ - g_inited = false; -} - -//------------------------------------------------------------------------------------- -bool initializeWatcher() -{ - return true; -} - -//------------------------------------------------------------------------------------- -bool addToStream(MemoryStream* pMemoryStream) -{ - int size = DefContext::allScriptDefContextMaps.size(); - (*pMemoryStream) << size; - - DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); - for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) - { - const std::string& name = iter->first; - DefContext& defContext = iter->second; - - (*pMemoryStream) << name; - - defContext.addToStream(pMemoryStream); - } - - return true; -} - -//------------------------------------------------------------------------------------- -bool createFromStream(MemoryStream* pMemoryStream) -{ - int size = 0; - (*pMemoryStream) >> size; - - for (int i = 0; i < size; ++i) - { - std::string name = ""; - (*pMemoryStream) >> name; - - DefContext defContext; - defContext.createFromStream(pMemoryStream); - DefContext::allScriptDefContextLineMaps[defContext.pyObjectSourceFile] = defContext; - } - - return true; -} - -//------------------------------------------------------------------------------------- - -} -} -} +// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com + +#include +#include +#include + +#include "common.h" +#include "entitydef.h" +#include "datatypes.h" +#include "py_entitydef.h" +#include "scriptdef_module.h" +#include "pyscript/py_platform.h" +#include "pyscript/script.h" +#include "pyscript/copy.h" +#include "resmgr/resmgr.h" +#include "server/serverconfig.h" +#include "server/components.h" + +namespace KBEngine{ namespace script{ namespace entitydef { + +struct CallContext +{ + PyObjectPtr pyArgs; + PyObjectPtr pyKwargs; + std::string optionName; +}; + +static std::stack g_callContexts; +static std::string pyDefModuleName = ""; + +DefContext::DEF_CONTEXT_MAP DefContext::allScriptDefContextMaps; +DefContext::DEF_CONTEXT_MAP DefContext::allScriptDefContextLineMaps; + +static bool g_inited = false; + +//------------------------------------------------------------------------------------- +static PyObject* __py_array(PyObject* self, PyObject* args) +{ + if (PyTuple_GET_SIZE(args) == 0) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.ARRAY: does not set itemType! should be like this \"EntityDef.ARRAY(itemType)\"\n"); + return NULL; + } + + PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); + PyObject* pyARRAY = PyObject_GetAttrString(entitydefModule, "ARRAY"); + + PyObject* pyArrayItemType = PyTuple_GET_ITEM(args, 0); + Py_INCREF(pyArrayItemType); + + PyObject* ret = PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, pyARRAY); + PyTuple_SET_ITEM(ret, 1, pyArrayItemType); + + return ret; +} + +//------------------------------------------------------------------------------------- +class Entity : public script::ScriptObject +{ + BASE_SCRIPT_HREADER(Entity, ScriptObject) +public: + Entity(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : + ScriptObject(pyType, isInitialised) {} + ~Entity() {} +}; + +SCRIPT_METHOD_DECLARE_BEGIN(Entity) +SCRIPT_METHOD_DECLARE_END() + +SCRIPT_MEMBER_DECLARE_BEGIN(Entity) +SCRIPT_MEMBER_DECLARE_END() + +SCRIPT_GETSET_DECLARE_BEGIN(Entity) +SCRIPT_GETSET_DECLARE_END() +BASE_SCRIPT_INIT(Entity, 0, 0, 0, 0, 0) + +//------------------------------------------------------------------------------------- +class Space : public script::ScriptObject +{ + BASE_SCRIPT_HREADER(Space, ScriptObject) +public: + Space(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : + ScriptObject(pyType, isInitialised) {} + ~Space() {} +}; + +SCRIPT_METHOD_DECLARE_BEGIN(Space) +SCRIPT_METHOD_DECLARE_END() + +SCRIPT_MEMBER_DECLARE_BEGIN(Space) +SCRIPT_MEMBER_DECLARE_END() + +SCRIPT_GETSET_DECLARE_BEGIN(Space) +SCRIPT_GETSET_DECLARE_END() +BASE_SCRIPT_INIT(Space, 0, 0, 0, 0, 0) + +//------------------------------------------------------------------------------------- +class Proxy : public script::ScriptObject +{ + BASE_SCRIPT_HREADER(Proxy, ScriptObject) +public: + Proxy(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : + ScriptObject(pyType, isInitialised) {} + ~Proxy() {} +}; + +SCRIPT_METHOD_DECLARE_BEGIN(Proxy) +SCRIPT_METHOD_DECLARE_END() + +SCRIPT_MEMBER_DECLARE_BEGIN(Proxy) +SCRIPT_MEMBER_DECLARE_END() + +SCRIPT_GETSET_DECLARE_BEGIN(Proxy) +SCRIPT_GETSET_DECLARE_END() +BASE_SCRIPT_INIT(Proxy, 0, 0, 0, 0, 0) + +//------------------------------------------------------------------------------------- +class EntityComponent : public script::ScriptObject +{ + BASE_SCRIPT_HREADER(EntityComponent, ScriptObject) +public: + EntityComponent(PyTypeObject* pyType = getScriptType(), bool isInitialised = true) : + ScriptObject(pyType, isInitialised) {} + ~EntityComponent() {} +}; + +SCRIPT_METHOD_DECLARE_BEGIN(EntityComponent) +SCRIPT_METHOD_DECLARE_END() + +SCRIPT_MEMBER_DECLARE_BEGIN(EntityComponent) +SCRIPT_MEMBER_DECLARE_END() + +SCRIPT_GETSET_DECLARE_BEGIN(EntityComponent) +SCRIPT_GETSET_DECLARE_END() +BASE_SCRIPT_INIT(EntityComponent, 0, 0, 0, 0, 0) + +//------------------------------------------------------------------------------------- +DefContext::DefContext() +{ + optionName = ""; + + moduleName = ""; + attrName = ""; + methodArgs = ""; + returnType = ""; + + isModuleScope = false; + + exposed = false; + hasClient = false; + persistent = -1; + databaseLength = 0; + utype = -1; + detailLevel = ""; + + propertyFlags = ""; + propertyIndex = ""; + propertyDefaultVal = ""; + + implementedByModuleName = ""; + implementedByModuleFile = ""; + pyObjectSourceFile = ""; + + inheritEngineModuleType = DC_TYPE_UNKNOWN; + type = DC_TYPE_UNKNOWN; + + componentType = UNKNOWN_COMPONENT_TYPE; +} + +//------------------------------------------------------------------------------------- +bool DefContext::addToStream(MemoryStream* pMemoryStream) +{ + (*pMemoryStream) << optionName; + (*pMemoryStream) << moduleName; + (*pMemoryStream) << attrName; + (*pMemoryStream) << methodArgs; + (*pMemoryStream) << returnType; + + (*pMemoryStream) << (int)argsvecs.size(); + std::vector< std::string >::iterator argsvecsIter = argsvecs.begin(); + for(; argsvecsIter != argsvecs.end(); ++argsvecsIter) + (*pMemoryStream) << (*argsvecsIter); + + (*pMemoryStream) << (int)annotationsMaps.size(); + std::map< std::string, std::string >::iterator annotationsMapsIter = annotationsMaps.begin(); + for (; annotationsMapsIter != annotationsMaps.end(); ++annotationsMapsIter) + (*pMemoryStream) << annotationsMapsIter->first << annotationsMapsIter->second; + + (*pMemoryStream) << isModuleScope; + (*pMemoryStream) << exposed; + (*pMemoryStream) << hasClient; + + (*pMemoryStream) << persistent; + (*pMemoryStream) << databaseLength; + (*pMemoryStream) << utype; + (*pMemoryStream) << detailLevel; + + (*pMemoryStream) << propertyFlags; + (*pMemoryStream) << propertyIndex; + (*pMemoryStream) << propertyDefaultVal; + + (*pMemoryStream) << implementedByModuleName; + (*pMemoryStream) << implementedByModuleFile; + (*pMemoryStream) << pyObjectSourceFile; + + (*pMemoryStream) << (int)baseClasses.size(); + std::vector< std::string >::iterator baseClassesIter = baseClasses.begin(); + for (; baseClassesIter != baseClasses.end(); ++baseClassesIter) + (*pMemoryStream) << (*baseClassesIter); + + (*pMemoryStream) << (int)inheritEngineModuleType; + (*pMemoryStream) << (int)type; + + (*pMemoryStream) << (int)methods.size(); + std::vector< DefContext >::iterator methodsIter = methods.begin(); + for (; methodsIter != methods.end(); ++methodsIter) + (*methodsIter).addToStream(pMemoryStream); + + (*pMemoryStream) << (int)client_methods.size(); + std::vector< DefContext >::iterator client_methodsIter = client_methods.begin(); + for (; client_methodsIter != client_methods.end(); ++client_methodsIter) + (*client_methodsIter).addToStream(pMemoryStream); + + (*pMemoryStream) << (int)propertys.size(); + std::vector< DefContext >::iterator propertysIter = propertys.begin(); + for (; propertysIter != propertys.end(); ++propertysIter) + (*propertysIter).addToStream(pMemoryStream); + + (*pMemoryStream) << (int)components.size(); + std::vector< std::string >::iterator componentsIter = components.begin(); + for (; componentsIter != components.end(); ++componentsIter) + (*pMemoryStream) << (*componentsIter); + + return true; +} + +//------------------------------------------------------------------------------------- +bool DefContext::createFromStream(MemoryStream* pMemoryStream) +{ + (*pMemoryStream) >> optionName; + (*pMemoryStream) >> moduleName; + (*pMemoryStream) >> attrName; + (*pMemoryStream) >> methodArgs; + (*pMemoryStream) >> returnType; + + int size = 0; + + (*pMemoryStream) >> size; + for (int i = 0; i < size; ++i) + { + std::string str; + (*pMemoryStream) >> str; + + argsvecs.push_back(str); + } + + (*pMemoryStream) >> size; + for (int i = 0; i < size; ++i) + { + std::string key, val; + (*pMemoryStream) >> key >> val; + + annotationsMaps[key] = val; + } + + (*pMemoryStream) >> isModuleScope; + (*pMemoryStream) >> exposed; + (*pMemoryStream) >> hasClient; + + (*pMemoryStream) >> persistent; + (*pMemoryStream) >> databaseLength; + (*pMemoryStream) >> utype; + (*pMemoryStream) >> detailLevel; + + (*pMemoryStream) >> propertyFlags; + (*pMemoryStream) >> propertyIndex; + (*pMemoryStream) >> propertyDefaultVal; + + (*pMemoryStream) >> implementedByModuleName; + (*pMemoryStream) >> implementedByModuleFile; + (*pMemoryStream) >> pyObjectSourceFile; + + (*pMemoryStream) >> size; + for (int i = 0; i < size; ++i) + { + std::string str; + (*pMemoryStream) >> str; + + baseClasses.push_back(str); + } + + int t_inheritEngineModuleType; + (*pMemoryStream) >> t_inheritEngineModuleType; + inheritEngineModuleType = (DCType)t_inheritEngineModuleType; + + int t_type; + (*pMemoryStream) >> t_type; + type = (DCType)t_type; + + (*pMemoryStream) >> size; + for (int i = 0; i < size; ++i) + { + DefContext dc; + dc.createFromStream(pMemoryStream); + + methods.push_back(dc); + } + + (*pMemoryStream) >> size; + for (int i = 0; i < size; ++i) + { + DefContext dc; + dc.createFromStream(pMemoryStream); + + client_methods.push_back(dc); + } + + (*pMemoryStream) >> size; + for (int i = 0; i < size; ++i) + { + DefContext dc; + dc.createFromStream(pMemoryStream); + + propertys.push_back(dc); + } + + (*pMemoryStream) >> size; + for (int i = 0; i < size; ++i) + { + std::string str; + (*pMemoryStream) >> str; + + components.push_back(str); + } + + return true; +} + +//------------------------------------------------------------------------------------- +bool DefContext::addChildContext(DefContext& defContext) +{ + std::vector< DefContext >* pContexts = NULL; + + if (defContext.type == DefContext::DC_TYPE_PROPERTY) + pContexts = &propertys; + else if (defContext.type == DefContext::DC_TYPE_METHOD) + pContexts = &methods; + else if (defContext.type == DefContext::DC_TYPE_CLIENT_METHOD) + pContexts = &client_methods; + else if (defContext.type == DefContext::DC_TYPE_FIXED_ITEM) + pContexts = &propertys; + else + KBE_ASSERT(false); + + std::vector< DefContext >::iterator iter = pContexts->begin(); + for (; iter != pContexts->end(); ++iter) + { + if ((*iter).attrName == defContext.attrName) + { + // assemblyContextsʱܻᷢ + // + if (moduleName != defContext.moduleName || (*iter).pyObjectSourceFile == defContext.pyObjectSourceFile) + return true; + + return false; + } + } + + pContexts->push_back(defContext); + return true; +} + +//------------------------------------------------------------------------------------- +static bool assemblyContexts(bool notfoundModuleError = false) +{ + std::vector< std::string > dels; + + DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); + for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) + { + DefContext& defContext = iter->second; + + if (defContext.type == DefContext::DC_TYPE_PROPERTY || + defContext.type == DefContext::DC_TYPE_METHOD || + defContext.type == DefContext::DC_TYPE_CLIENT_METHOD || + defContext.type == DefContext::DC_TYPE_FIXED_ITEM) + { + DefContext::DEF_CONTEXT_MAP::iterator fiter = DefContext::allScriptDefContextMaps.find(defContext.moduleName); + if (fiter == DefContext::allScriptDefContextMaps.end()) + { + if (notfoundModuleError) + { + PyErr_Format(PyExc_AssertionError, "PyEntityDef::process(): No \'%s\' module defined!\n", defContext.moduleName.c_str()); + return false; + } + + return true; + } + + if (!fiter->second.addChildContext(defContext)) + { + PyErr_Format(PyExc_AssertionError, "\'%s.%s\' already exists!\n", + fiter->second.moduleName.c_str(), defContext.attrName.c_str()); + + return false; + } + + dels.push_back(iter->first); + } + else + { + } + } + + std::vector< std::string >::iterator diter = dels.begin(); + for (; diter != dels.end(); ++diter) + { + DefContext::allScriptDefContextMaps.erase((*diter)); + } + + // ԽϢ䵽 + iter = DefContext::allScriptDefContextMaps.begin(); + for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) + { + DefContext& defContext = iter->second; + if (defContext.baseClasses.size() > 0) + { + for (size_t i = 0; i < defContext.baseClasses.size(); ++i) + { + std::string parentClass = defContext.baseClasses[i]; + + DefContext::DEF_CONTEXT_MAP::iterator fiter = DefContext::allScriptDefContextMaps.find(parentClass); + if (fiter == DefContext::allScriptDefContextMaps.end()) + { + //PyErr_Format(PyExc_AssertionError, "not found parentClass(\'%s\')!\n", parentClass.c_str()); + //return false; + continue; + } + + DefContext& parentDefContext = fiter->second; + std::vector< DefContext > childContexts; + + childContexts.insert(childContexts.end(), parentDefContext.methods.begin(), parentDefContext.methods.end()); + childContexts.insert(childContexts.end(), parentDefContext.client_methods.begin(), parentDefContext.client_methods.end()); + childContexts.insert(childContexts.end(), parentDefContext.propertys.begin(), parentDefContext.propertys.end()); + + std::vector< DefContext >::iterator itemIter = childContexts.begin(); + for (; itemIter != childContexts.end(); ++itemIter) + { + DefContext& parentDefContext = (*itemIter); + if (!defContext.addChildContext(parentDefContext)) + { + PyErr_Format(PyExc_AssertionError, "\'%s.%s\' already exists(%s.%s)!\n", + defContext.moduleName.c_str(), parentDefContext.attrName.c_str(), parentDefContext.moduleName.c_str(), parentDefContext.attrName.c_str()); + + return false; + } + } + } + } + } + + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerDefContext(DefContext& defContext) +{ + DefContext::allScriptDefContextLineMaps[defContext.pyObjectSourceFile] = defContext; + + std::string name = defContext.moduleName; + + if (defContext.type == DefContext::DC_TYPE_PROPERTY) + { + if(!EntityDef::validDefPropertyName(name)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: '%s' is limited!\n\n", + defContext.optionName.c_str(), name.c_str()); + + return false; + } + + // Ƿڸý + bool flagsGood = true; + if (defContext.componentType == BASEAPP_TYPE) + flagsGood = (stringToEntityDataFlags(defContext.propertyFlags) & ENTITY_BASE_DATA_FLAGS) != 0; + else if (defContext.componentType == CELLAPP_TYPE) + flagsGood = (stringToEntityDataFlags(defContext.propertyFlags) & ENTITY_CELL_DATA_FLAGS) != 0; + else if (defContext.componentType == CLIENT_TYPE) + flagsGood = (stringToEntityDataFlags(defContext.propertyFlags) & ENTITY_CLIENT_DATA_FLAGS) != 0; + + name += "." + defContext.attrName; + + if (!flagsGood) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: '%s'(%s) not a valid %s property flags!\n\n", + defContext.optionName.c_str(), name.c_str(), defContext.propertyFlags.c_str(), COMPONENT_NAME_EX(defContext.componentType)); + + return false; + } + } + else if(defContext.type == DefContext::DC_TYPE_METHOD || + defContext.type == DefContext::DC_TYPE_CLIENT_METHOD) + { + name += "." + defContext.attrName; + } + else if (defContext.type == DefContext::DC_TYPE_FIXED_ITEM) + { + name += "." + defContext.attrName; + } + else if (defContext.type == DefContext::DC_TYPE_FIXED_ARRAY || + defContext.type == DefContext::DC_TYPE_FIXED_DICT || + defContext.type == DefContext::DC_TYPE_RENAME) + { + if (!DataTypes::validTypeName(name)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: Not allowed to use the prefix \"_\"! typeName=%s\n", + defContext.optionName.c_str(), name.c_str()); + + return false; + } + } + + DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.find(name); + if (iter != DefContext::allScriptDefContextMaps.end()) + { + if (iter->second.pyObjectSourceFile != defContext.pyObjectSourceFile) + { + // Dz̵ͬĽű֣ôҪкϲע + if (iter->second.componentType != defContext.componentType && DefContext::allScriptDefContextLineMaps.find(defContext.pyObjectSourceFile) != DefContext::allScriptDefContextLineMaps.end() && + (defContext.type == DefContext::DC_TYPE_ENTITY || defContext.type == DefContext::DC_TYPE_COMPONENT || defContext.type == DefContext::DC_TYPE_INTERFACE) && + iter->second.type == defContext.type) + { + std::vector< std::string >::iterator bciter = defContext.baseClasses.begin(); + for (; bciter != defContext.baseClasses.end(); ++bciter) + { + if (std::find(iter->second.baseClasses.begin(), iter->second.baseClasses.end(), (*bciter)) == iter->second.baseClasses.end()) + { + iter->second.baseClasses.push_back((*bciter)); + } + + KBE_ASSERT(defContext.methods.size() == 0 && defContext.client_methods.size() == 0 && defContext.components.size() == 0 && defContext.propertys.size() == 0); + if (defContext.hasClient) + iter->second.hasClient = true; + + } + + return true; + } + + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' already exists!\n", + defContext.optionName.c_str(), name.c_str()); + + return false; + } + + return true; + } + + DefContext::allScriptDefContextMaps[name] = defContext; + return assemblyContexts(); +} + +//------------------------------------------------------------------------------------- + +static bool onDefRename(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_RENAME; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefFixedDict(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_FIXED_DICT; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefFixedArray(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_FIXED_ARRAY; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefFixedItem(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_FIXED_ITEM; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefProperty(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_PROPERTY; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefMethod(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_METHOD; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefClientMethod(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_CLIENT_METHOD; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefEntity(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_ENTITY; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefInterface(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_INTERFACE; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool onDefComponent(DefContext& defContext) +{ + defContext.type = DefContext::DC_TYPE_COMPONENT; + return registerDefContext(defContext); +} + +//------------------------------------------------------------------------------------- +static bool isRefEntityDefModule(PyObject *pyObj) +{ + if(!pyObj) + return true; + + PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); + PyObject* pydict = PyObject_GetAttrString(entitydefModule, "__dict__"); + + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(pydict, &pos, &key, &value)) { + if (value == pyObj) + { + Py_DECREF(pydict); + return true; + } + } + + Py_DECREF(pydict); + return false; +} + +//------------------------------------------------------------------------------------- +#define PY_RETURN_ERROR { DefContext::allScriptDefContextLineMaps.clear(); DefContext::allScriptDefContextMaps.clear(); while(!g_callContexts.empty()) g_callContexts.pop(); return NULL; } + +#define PYOBJECT_SOURCEFILE(PYOBJ, OUT) \ +{ \ + PyObject* pyInspectModule = \ + PyImport_ImportModule(const_cast("inspect")); \ + \ + PyObject* pyGetsourcefile = NULL; \ + PyObject* pyGetLineno = NULL; \ + PyObject* pyGetCurrentFrame = NULL; \ + \ + if (pyInspectModule) \ + { \ + pyGetsourcefile = \ + PyObject_GetAttrString(pyInspectModule, const_cast("getsourcefile")); \ + pyGetLineno = \ + PyObject_GetAttrString(pyInspectModule, const_cast("getlineno")); \ + pyGetCurrentFrame = \ + PyObject_GetAttrString(pyInspectModule, const_cast("currentframe")); \ + \ + Py_DECREF(pyInspectModule); \ + } \ + else \ + { \ + PY_RETURN_ERROR; \ + } \ + \ + if (pyGetsourcefile) \ + { \ + PyObject* pyFile = PyObject_CallFunction(pyGetsourcefile, \ + const_cast("(O)"), PYOBJ); \ + \ + Py_DECREF(pyGetsourcefile); \ + \ + if (!pyFile) \ + { \ + Py_XDECREF(pyGetLineno); \ + Py_XDECREF(pyGetCurrentFrame); \ + PY_RETURN_ERROR; \ + } \ + else \ + { \ + /* ֹͬϵͳɵ·һ£޳ϵͳ· */ \ + OUT = PyUnicode_AsUTF8AndSize(pyFile, NULL); \ + strutil::kbe_replace(OUT, "\\\\", "/"); \ + strutil::kbe_replace(OUT, "\\", "/"); \ + strutil::kbe_replace(OUT, "//", "/"); \ + std::string kbe_root = Resmgr::getSingleton().getPyUserScriptsPath(); \ + strutil::kbe_replace(kbe_root, "\\\\", "/"); \ + strutil::kbe_replace(kbe_root, "\\", "/"); \ + strutil::kbe_replace(kbe_root, "/", "/"); \ + strutil::kbe_replace(OUT, kbe_root, ""); \ + Py_DECREF(pyFile); \ + } \ + } \ + else \ + { \ + Py_XDECREF(pyGetLineno); \ + Py_XDECREF(pyGetCurrentFrame); \ + PY_RETURN_ERROR; \ + } \ + \ + if (pyGetLineno) \ + { \ + if(!pyGetCurrentFrame) \ + { \ + Py_DECREF(pyGetLineno); \ + } \ + \ + PyObject* pyCurrentFrame = PyObject_CallFunction(pyGetCurrentFrame, \ + const_cast("()")); \ + \ + PyObject* pyLine = PyObject_CallFunction(pyGetLineno, \ + const_cast("(O)"), pyCurrentFrame); \ + \ + Py_DECREF(pyGetLineno); \ + Py_DECREF(pyGetCurrentFrame); \ + Py_DECREF(pyCurrentFrame); \ + \ + if (!pyLine) \ + { \ + PY_RETURN_ERROR; \ + } \ + else \ + { \ + /* кţͬļжζ */ \ + OUT += fmt::format("#{}", PyLong_AsLong(pyLine)); \ + Py_DECREF(pyLine); \ + } \ + } \ + else \ + { \ + Py_XDECREF(pyGetCurrentFrame); \ + PY_RETURN_ERROR; \ + } \ +} + +static PyObject* __py_def_parse(PyObject *self, PyObject* args) +{ + CallContext cc = g_callContexts.top(); + g_callContexts.pop(); + + DefContext defContext; + defContext.optionName = cc.optionName; + + PyObject* kbeModule = PyImport_AddModule("KBEngine"); + KBE_ASSERT(kbeModule); + + PyObject* pyComponentName = PyObject_GetAttrString(kbeModule, "component"); + if (!pyComponentName) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.__py_def_call(): get KBEngine.component error!\n"); + PY_RETURN_ERROR; + } + + defContext.componentType = ComponentName2ComponentType(PyUnicode_AsUTF8AndSize(pyComponentName, NULL)); + Py_DECREF(pyComponentName); + + if (!args || PyTuple_Size(args) < 1) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.__py_def_call(EntityDef.%s): error!\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + PyObject* pyFunc = PyTuple_GET_ITEM(args, 0); + + PyObject* pyModuleQualname = PyObject_GetAttrString(pyFunc, "__qualname__"); + if (!pyModuleQualname) + { + PY_RETURN_ERROR; + } + + const char* moduleQualname = PyUnicode_AsUTF8AndSize(pyModuleQualname, NULL); + Py_DECREF(pyModuleQualname); + + defContext.pyObjectPtr = PyObjectPtr(pyFunc); + PYOBJECT_SOURCEFILE(defContext.pyObjectPtr.get(), defContext.pyObjectSourceFile); + + if (defContext.optionName == "method") + { + static char * keywords[] = + { + const_cast ("exposed"), + const_cast ("utype"), + NULL + }; + + PyObject* pyExposed = NULL; + PyObject* pyUtype = NULL; + + if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|OO", + keywords, &pyExposed, &pyUtype)) + { + PY_RETURN_ERROR; + } + + if (pyExposed && !PyBool_Check(pyExposed)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'exposed\' error! not a bool type.\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + if (pyUtype && !PyLong_Check(pyUtype)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'utype\' error! not a number type.\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + defContext.exposed = pyExposed == Py_True; + + if (pyUtype) + defContext.utype = (int)PyLong_AsLong(pyUtype); + } + else if (defContext.optionName == "property" || defContext.optionName == "fixed_item") + { + if (defContext.optionName != "fixed_item") + { + static char * keywords[] = + { + const_cast ("flags"), + const_cast ("persistent"), + const_cast ("index"), + const_cast ("databaseLength"), + const_cast ("utype"), + NULL + }; + + PyObject* pyFlags = NULL; + PyObject* pyPersistent = NULL; + PyObject* pyIndex = NULL; + PyObject* pyDatabaseLength = NULL; + PyObject* pyUtype = NULL; + + if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|OOOOO", + keywords, &pyFlags, &pyPersistent, &pyIndex, &pyDatabaseLength, &pyUtype)) + { + PY_RETURN_ERROR; + } + + if (!pyFlags || !isRefEntityDefModule(pyFlags)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'flags\' must be referenced from the [EntityDef.ALL_CLIENTS, EntityDef.*] module!\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + if (!isRefEntityDefModule(pyIndex)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'index\' must be referenced from the [EntityDef.UNIQUE, EntityDef.INDEX] module!\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + if (pyDatabaseLength && !PyLong_Check(pyDatabaseLength)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'databaseLength\' error! not a number type.\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + if (pyPersistent && !PyBool_Check(pyPersistent)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'persistent\' error! not a bool type.\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + if(pyUtype && !PyLong_Check(pyUtype)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'utype\' error! not a number type.\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + defContext.propertyFlags = PyUnicode_AsUTF8AndSize(pyFlags, NULL); + + if (pyPersistent) + defContext.persistent = pyPersistent == Py_True; + + if (pyIndex) + defContext.propertyIndex = PyUnicode_AsUTF8AndSize(pyIndex, NULL); + + if (pyDatabaseLength) + defContext.databaseLength = (int)PyLong_AsLong(pyDatabaseLength); + + if (pyUtype) + defContext.utype = (int)PyLong_AsLong(pyUtype); + } + + // ԣ Ҫ÷ֵΪĬֵ + PyObject* pyRet = PyObject_CallFunction(pyFunc, + const_cast("(O)"), Py_None); + + if (!pyRet) + return NULL; + + if (pyRet != Py_None) + { + PyObject* pyStrResult = PyObject_Str(pyRet); + Py_DECREF(pyRet); + + defContext.propertyDefaultVal = PyUnicode_AsUTF8AndSize(pyStrResult, NULL); + Py_DECREF(pyStrResult); + + // ַ֤ǷԻԭɶ + if (defContext.propertyDefaultVal.size() > 0) + { + PyObject* module = PyImport_AddModule("__main__"); + if (module == NULL) + return NULL; + + PyObject* mdict = PyModule_GetDict(module); // Borrowed reference. + PyObject* result = PyRun_String(const_cast(defContext.propertyDefaultVal.c_str()), + Py_eval_input, mdict, mdict); + + if (result == NULL) + return NULL; + + Py_DECREF(result); + } + } + else + { + Py_DECREF(pyRet); + } + } + else if (defContext.optionName == "entity") + { + defContext.isModuleScope = true; + + static char * keywords[] = + { + const_cast ("hasClient"), + NULL + }; + + PyObject* pyHasClient = NULL; + + if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|O", + keywords, &pyHasClient)) + { + PY_RETURN_ERROR; + } + + defContext.hasClient = pyHasClient == Py_True; + } + else if (defContext.optionName == "interface") + { + defContext.isModuleScope = true; + defContext.inheritEngineModuleType = DefContext::DC_TYPE_INTERFACE; + } + else if (defContext.optionName == "component") + { + defContext.isModuleScope = true; + } + else if (defContext.optionName == "fixed_dict") + { + defContext.isModuleScope = true; + + static char * keywords[] = + { + const_cast ("implementedBy"), + NULL + }; + + PyObject* pImplementedBy = NULL; + + if (!PyArg_ParseTupleAndKeywords(cc.pyArgs.get(), cc.pyKwargs.get(), "|O", + keywords, &pImplementedBy)) + { + PY_RETURN_ERROR; + } + + if (pImplementedBy) + { + if (isRefEntityDefModule(pImplementedBy)) + { + if (std::string(PyUnicode_AsUTF8AndSize(pImplementedBy, NULL)) == "thisClass") + { + defContext.implementedBy = pyFunc; + } + } + else + { + defContext.implementedBy = pImplementedBy; + } + + PyObject* pyQualname = PyObject_GetAttrString(defContext.implementedBy.get(), "__qualname__"); + if (!pyQualname) + { + PY_RETURN_ERROR; + } + + defContext.implementedByModuleName = PyUnicode_AsUTF8AndSize(pyQualname, NULL); + Py_DECREF(pyQualname); + + PYOBJECT_SOURCEFILE(defContext.implementedBy.get(), defContext.implementedByModuleFile); + } + } + else if (defContext.optionName == "fixed_array") + { + defContext.isModuleScope = true; + } + else if (defContext.optionName == "fixed_item") + { + } + else if (defContext.optionName == "rename") + { + } + else + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: not support!\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + if (!defContext.isModuleScope) + { + std::vector outs; + + if (moduleQualname) + strutil::kbe_splits(moduleQualname, ".", outs); + + if (defContext.optionName != "rename") + { + if (outs.size() != 2) + { + if(PyFunction_Check(pyFunc)) + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' must be defined in the entity module!\n", + defContext.optionName.c_str(), moduleQualname); + else + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: please check the command format is: EntityDef.%s(..)\n", + defContext.optionName.c_str(), defContext.optionName.c_str()); + + PY_RETURN_ERROR; + } + + defContext.moduleName = outs[0]; + defContext.attrName = outs[1]; + } + else + { + if (outs.size() != 1) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: error! such as: @EntityDef.rename()\n\tdef ENTITY_ID() -> EntityDef.INT32: pass\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + + defContext.moduleName = outs[0]; + } + + PyObject* pyInspectModule = + PyImport_ImportModule(const_cast("inspect")); + + PyObject* pyGetfullargspec = NULL; + if (pyInspectModule) + { + pyGetfullargspec = + PyObject_GetAttrString(pyInspectModule, const_cast("getfullargspec")); + + Py_DECREF(pyInspectModule); + } + else + { + PY_RETURN_ERROR; + } + + if (pyGetfullargspec) + { + PyObject* pyGetMethodArgs = PyObject_CallFunction(pyGetfullargspec, + const_cast("(O)"), pyFunc); + + if (!pyGetMethodArgs) + { + PY_RETURN_ERROR; + } + else + { + PyObject* pyGetMethodArgsResult = PyObject_GetAttrString(pyGetMethodArgs, const_cast("args")); + PyObject* pyGetMethodAnnotationsResult = PyObject_GetAttrString(pyGetMethodArgs, const_cast("annotations")); + + Py_DECREF(pyGetMethodArgs); + + if (!pyGetMethodArgsResult || !pyGetMethodAnnotationsResult) + { + Py_XDECREF(pyGetMethodArgsResult); + Py_XDECREF(pyGetMethodAnnotationsResult); + PY_RETURN_ERROR; + } + + PyObjectPtr pyGetMethodArgsResultPtr = pyGetMethodArgsResult; + PyObjectPtr pyGetMethodAnnotationsResultPtr = pyGetMethodAnnotationsResult; + Py_DECREF(pyGetMethodArgsResult); + Py_DECREF(pyGetMethodAnnotationsResult); + + if (defContext.optionName != "rename") + { + Py_ssize_t argsSize = PyList_Size(pyGetMethodArgsResult); + if (argsSize == 0) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' did not find \'self\' parameter!\n", defContext.optionName.c_str(), moduleQualname); + PY_RETURN_ERROR; + } + + for (Py_ssize_t i = 1; i < argsSize; ++i) + { + PyObject* pyItem = PyList_GetItem(pyGetMethodArgsResult, i); + + const char* ccattr = PyUnicode_AsUTF8AndSize(pyItem, NULL); + if (!ccattr) + { + PY_RETURN_ERROR; + } + + defContext.argsvecs.push_back(ccattr); + } + } + + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(pyGetMethodAnnotationsResult, &pos, &key, &value)) { + const char* skey = PyUnicode_AsUTF8AndSize(key, NULL); + if (!skey) + { + PY_RETURN_ERROR; + } + + std::string svalue = ""; + + // EntityDef.Array˴һtupleο__py_array + if (PyTuple_Check(value) && PyTuple_Size(value) == 2) + { + PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); + PyObject* pyARRAY = PyObject_GetAttrString(entitydefModule, "ARRAY"); + PyObject* item0 = PyTuple_GET_ITEM(value, 0); + + if (pyARRAY == item0) + { + value = PyTuple_GET_ITEM(value, 1); + defContext.optionName = "anonymous_fixed_array"; + + if (std::string(skey) != "return") + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'EntityDef.ARRAY\' Can only be used to define property types!\n", defContext.optionName.c_str()); + PY_RETURN_ERROR; + } + } + else + { + Py_DECREF(pyARRAY); + PY_RETURN_ERROR; + } + + Py_DECREF(pyARRAY); + } + + if (PyUnicode_Check(value)) + { + svalue = PyUnicode_AsUTF8AndSize(value, NULL); + } + else + { + PyObject* pyQualname = PyObject_GetAttrString(value, "__qualname__"); + if (!pyQualname) + { + PY_RETURN_ERROR; + } + + svalue = PyUnicode_AsUTF8AndSize(pyQualname, NULL); + Py_DECREF(pyQualname); + } + + if (svalue.size() == 0) + { + PY_RETURN_ERROR; + } + + if (std::string(skey) == "return") + defContext.returnType = svalue; + else + defContext.annotationsMaps[skey] = svalue; + } + } + } + else + { + PY_RETURN_ERROR; + } + } + else + { + defContext.moduleName = moduleQualname; + + PyObject* pyBases = PyObject_GetAttrString(pyFunc, "__bases__"); + if (!pyBases) + PY_RETURN_ERROR; + + Py_ssize_t basesSize = PyTuple_Size(pyBases); + if (basesSize == 0) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' does not inherit the KBEngine.Entity class!\n", defContext.optionName.c_str(), moduleQualname); + Py_XDECREF(pyBases); + PY_RETURN_ERROR; + } + + for (Py_ssize_t i = 0; i < basesSize; ++i) + { + PyObject* pyClass = PyTuple_GetItem(pyBases, i); + + PyObject* pyQualname = PyObject_GetAttrString(pyClass, "__qualname__"); + if (!pyQualname) + { + Py_XDECREF(pyBases); + PY_RETURN_ERROR; + } + + std::string parentClass = PyUnicode_AsUTF8AndSize(pyQualname, NULL); + Py_DECREF(pyQualname); + + if (parentClass == "object") + { + continue; + } + else if (parentClass == "Entity") + { + defContext.inheritEngineModuleType = DefContext::DC_TYPE_ENTITY; + continue; + } + else if (parentClass == "Proxy") + { + if (defContext.componentType != BASEAPP_TYPE) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' Only BASE can inherit KBEngine.Proxy!\n", defContext.optionName.c_str(), moduleQualname); + PY_RETURN_ERROR; + } + + defContext.inheritEngineModuleType = DefContext::DC_TYPE_ENTITY; + continue; + } + else if (parentClass == "EntityComponent") + { + defContext.inheritEngineModuleType = DefContext::DC_TYPE_COMPONENT; + continue; + } + + defContext.baseClasses.push_back(parentClass); + } + + Py_XDECREF(pyBases); + } + + bool noerror = true; + + if (defContext.optionName == "method" || defContext.optionName == "clientmethod") + { + if (defContext.annotationsMaps.size() != defContext.argsvecs.size()) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: \'%s\' all parameters must have annotations!\n", defContext.optionName.c_str(), moduleQualname); + PY_RETURN_ERROR; + } + + if (defContext.optionName == "method") + noerror = onDefMethod(defContext); + else + noerror = onDefClientMethod(defContext); + } + else if (defContext.optionName == "rename") + { + noerror = onDefRename(defContext); + } + else if (defContext.optionName == "property") + { + noerror = onDefProperty(defContext); + } + else if (defContext.optionName == "entity") + { + noerror = onDefEntity(defContext); + } + else if (defContext.optionName == "interface") + { + noerror = onDefInterface(defContext); + } + else if (defContext.optionName == "component") + { + noerror = onDefComponent(defContext); + } + else if (defContext.optionName == "fixed_dict") + { + noerror = onDefFixedDict(defContext); + } + else if (defContext.optionName == "fixed_array") + { + noerror = onDefFixedArray(defContext); + } + else if (defContext.optionName == "anonymous_fixed_array") + { + // һ + DefContext arrayType; + arrayType = defContext; + arrayType.moduleName += ".anonymous_fixed_array"; + + // ֹ2Դļһ£ײΪظ + arrayType.pyObjectSourceFile += "(array)"; + + // һitem + DefContext itemType; + itemType = arrayType; + itemType.optionName = "fixed_item"; + + // ֹ2Դļһ£ײΪظ + itemType.pyObjectSourceFile += "(array_item)"; + + noerror = onDefFixedItem(itemType); + + arrayType.returnType = ""; + + if(noerror) + noerror = onDefFixedArray(arrayType); + + defContext.returnType = arrayType.moduleName; + + if (noerror) + noerror = onDefFixedItem(defContext); + } + else if (defContext.optionName == "fixed_item") + { + noerror = onDefFixedItem(defContext); + } + + if (!noerror) + { + PY_RETURN_ERROR; + } + + Py_INCREF(pyFunc); + return pyFunc; +} + +//------------------------------------------------------------------------------------- +static PyMethodDef __call_def_parse = { "_PyEntityDefParse", (PyCFunction)&__py_def_parse, METH_VARARGS, 0 }; + +#define PY_DEF_HOOK(NAME) \ + static PyObject* __py_def_##NAME(PyObject* self, PyObject* args, PyObject* kwargs) \ + { \ + CallContext cc; \ + cc.pyArgs = PyObjectPtr(Copy::deepcopy(args)); \ + cc.pyKwargs = kwargs ? PyObjectPtr(Copy::deepcopy(kwargs)) : PyObjectPtr(NULL); \ + cc.optionName = #NAME; \ + g_callContexts.push(cc); \ + Py_XDECREF(cc.pyArgs.get()); \ + Py_XDECREF(cc.pyKwargs.get()); \ + \ + return PyCFunction_New(&__call_def_parse, self); \ + } + +static PyObject* __py_def_rename(PyObject* self, PyObject* args, PyObject* kwargs) +{ + CallContext cc; + cc.pyArgs = PyObjectPtr(Copy::deepcopy(args)); + cc.pyKwargs = kwargs ? PyObjectPtr(Copy::deepcopy(kwargs)) : PyObjectPtr(NULL); + cc.optionName = "rename"; + + Py_XDECREF(cc.pyArgs.get()); + Py_XDECREF(cc.pyKwargs.get()); + + // ֶ巽ʽ EntityDef.rename(ENTITY_ID=EntityDef.INT32) + if (kwargs) + { + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(kwargs, &pos, &key, &value)) { + if (!PyType_Check(value)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 not legal type! such as: EntityDef.rename(ENTITY_ID=EntityDef.INT32)\n", cc.optionName.c_str()); + return NULL; + } + + PyObject* pyQualname = PyObject_GetAttrString(value, "__qualname__"); + if (!pyQualname) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 get __qualname__ error! such as: EntityDef.rename(ENTITY_ID=EntityDef.INT32)\n", cc.optionName.c_str()); + return NULL; + } + + std::string typeName = PyUnicode_AsUTF8AndSize(pyQualname, NULL); + Py_DECREF(pyQualname); + + if (!PyUnicode_Check(key)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg1 must be a string! such as: EntityDef.rename(ENTITY_ID=EntityDef.INT32)\n", cc.optionName.c_str()); + return NULL; + } + + DefContext defContext; + defContext.optionName = cc.optionName; + defContext.moduleName = PyUnicode_AsUTF8AndSize(key, NULL); + defContext.returnType = typeName; + + PyObject* kbeModule = PyImport_AddModule("KBEngine"); + KBE_ASSERT(kbeModule); + + PyObject* pyComponentName = PyObject_GetAttrString(kbeModule, "component"); + if (!pyComponentName) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.rename(): get KBEngine.component error!\n"); + PY_RETURN_ERROR; + } + + defContext.componentType = ComponentName2ComponentType(PyUnicode_AsUTF8AndSize(pyComponentName, NULL)); + Py_DECREF(pyComponentName); + + if (!onDefRename(defContext)) + return NULL; + } + + S_Return; + } + + g_callContexts.push(cc); + + // @EntityDef.rename() + // def ENTITY_ID() -> int: pass + return PyCFunction_New(&__call_def_parse, self); +} + +static PyObject* __py_def_fixed_array(PyObject* self, PyObject* args, PyObject* kwargs) +{ + CallContext cc; + cc.pyArgs = PyObjectPtr(Copy::deepcopy(args)); + cc.pyKwargs = kwargs ? PyObjectPtr(Copy::deepcopy(kwargs)) : PyObjectPtr(NULL); + cc.optionName = "fixed_array"; + + Py_XDECREF(cc.pyArgs.get()); + Py_XDECREF(cc.pyKwargs.get()); + + // ֶ巽ʽ EntityDef.fixed_array(XXArray=EntityDef.INT32) + if (kwargs) + { + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(kwargs, &pos, &key, &value)) { + if (!PyType_Check(value)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 not legal type! such as: EntityDef.fixed_array(XXArray=EntityDef.INT32)\n", cc.optionName.c_str()); + return NULL; + } + + PyObject* pyQualname = PyObject_GetAttrString(value, "__qualname__"); + if (!pyQualname) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg2 get __qualname__ error! such as: EntityDef.fixed_array(XXArray=EntityDef.INT32)\n", cc.optionName.c_str()); + return NULL; + } + + std::string typeName = PyUnicode_AsUTF8AndSize(pyQualname, NULL); + Py_DECREF(pyQualname); + + if (!PyUnicode_Check(key)) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.%s: arg1 must be a string! such as: EntityDef.fixed_array(XXArray=EntityDef.INT32)\n", cc.optionName.c_str()); + return NULL; + } + + DefContext defContext; + defContext.optionName = cc.optionName; + defContext.moduleName = PyUnicode_AsUTF8AndSize(key, NULL); + defContext.returnType = typeName; + + PyObject* kbeModule = PyImport_AddModule("KBEngine"); + KBE_ASSERT(kbeModule); + + PyObject* pyComponentName = PyObject_GetAttrString(kbeModule, "component"); + if (!pyComponentName) + { + PyErr_Format(PyExc_AssertionError, "EntityDef.fixed_array(): get KBEngine.component error!\n"); + PY_RETURN_ERROR; + } + + defContext.componentType = ComponentName2ComponentType(PyUnicode_AsUTF8AndSize(pyComponentName, NULL)); + Py_DECREF(pyComponentName); + + if (!onDefRename(defContext)) + return NULL; + } + + S_Return; + } + + g_callContexts.push(cc); + + // @EntityDef.fixed_array() + // class XXXArray + return PyCFunction_New(&__call_def_parse, self); +} + +#define PY_ADD_METHOD(NAME, DOCS) APPEND_SCRIPT_MODULE_METHOD(entitydefModule, NAME, __py_def_##NAME, METH_VARARGS | METH_KEYWORDS, 0); + +#ifdef interface +#undef interface +#endif + +#ifdef property +#undef property +#endif + +PY_DEF_HOOK(method) +PY_DEF_HOOK(clientmethod) +PY_DEF_HOOK(property) +PY_DEF_HOOK(entity) +PY_DEF_HOOK(interface) +PY_DEF_HOOK(component) +PY_DEF_HOOK(fixed_dict) +PY_DEF_HOOK(fixed_item) + +//------------------------------------------------------------------------------------- +bool installModule(const char* moduleName) +{ + pyDefModuleName = moduleName; + + PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); + PyObject_SetAttrString(entitydefModule, "__doc__", PyUnicode_FromString("This module is created by KBEngine!")); + + PY_ADD_METHOD(rename, ""); + PY_ADD_METHOD(method, ""); + PY_ADD_METHOD(clientmethod, ""); + PY_ADD_METHOD(property, ""); + PY_ADD_METHOD(entity, ""); + PY_ADD_METHOD(interface, ""); + PY_ADD_METHOD(component, ""); + PY_ADD_METHOD(fixed_dict, ""); + PY_ADD_METHOD(fixed_array, ""); + PY_ADD_METHOD(fixed_item, ""); + + return true; +} + +//------------------------------------------------------------------------------------- +bool uninstallModule() +{ + while (!g_callContexts.empty()) g_callContexts.pop(); + DefContext::allScriptDefContextMaps.clear(); + DefContext::allScriptDefContextLineMaps.clear(); + return true; +} + +//------------------------------------------------------------------------------------- +static bool loadAllScriptForComponentType(COMPONENT_TYPE loadComponentType) +{ + std::string entryScriptFileName = ""; + if (loadComponentType == BASEAPP_TYPE) + { + ENGINE_COMPONENT_INFO& info = g_kbeSrvConfig.getBaseApp(); + entryScriptFileName = info.entryScriptFile; + } + else if (loadComponentType == CELLAPP_TYPE) + { + ENGINE_COMPONENT_INFO& info = g_kbeSrvConfig.getCellApp(); + entryScriptFileName = info.entryScriptFile; + } + else + { + KBE_ASSERT(false); + } + + std::string rootPath = Resmgr::getSingleton().getPyUserComponentScriptsPath(loadComponentType); + + if (rootPath.size() == 0) + { + ERROR_MSG(fmt::format("PyEntityDef::loadAllScriptForComponentType(): get scripts path error! loadComponentType={}\n", + COMPONENT_NAME_EX(loadComponentType))); + + return false; + } + + while (rootPath[rootPath.size() - 1] == '/' || rootPath[rootPath.size() - 1] == '\\') rootPath.pop_back(); + + wchar_t* wpath = strutil::char2wchar((rootPath).c_str()); + + wchar_t* _wentryScriptFileName = strutil::char2wchar((entryScriptFileName).c_str()); + std::wstring wentryScriptFileName = _wentryScriptFileName; + free(_wentryScriptFileName); + + std::vector results; + Resmgr::getSingleton().listPathRes(wpath, L"py|pyc", results); + + // ִڽű + std::vector::iterator iter = results.begin(); + for (; iter != results.end(); ) + { + std::wstring wstrpath = (*iter); + if (wstrpath.find(wentryScriptFileName + L".py") == std::wstring::npos && wstrpath.find(wentryScriptFileName + L".pyc") == std::wstring::npos) + { + ++iter; + continue; + } + + iter = results.erase(iter); + } + + results.insert(results.begin(), std::wstring(wpath) + L"/" + wentryScriptFileName + L".py"); + + iter = results.begin(); + for (; iter != results.end(); ++iter) + { + std::wstring wstrpath = (*iter); + + if (wstrpath.find(L"__pycache__") != std::wstring::npos) + continue; + + if (wstrpath.find(L"__init__.") != std::wstring::npos) + continue; + + std::pair pathPair = script::PyPlatform::splitPath(wstrpath); + std::pair filePair = script::PyPlatform::splitText(pathPair.second); + + if (filePair.first.size() == 0) + continue; + + char* cpacketPath = strutil::wchar2char(pathPair.first.c_str()); + std::string packetPath = cpacketPath; + free(cpacketPath); + + strutil::kbe_replace(packetPath, rootPath, ""); + while (packetPath.size() > 0 && (packetPath[0] == '/' || packetPath[0] == '\\')) packetPath.erase(0, 1); + strutil::kbe_replace(packetPath, "/", "."); + strutil::kbe_replace(packetPath, "\\", "."); + + char* moduleName = strutil::wchar2char(filePair.first.c_str()); + + // ڽűڲܻimportظimport ǹѾimportģ + if (DefContext::allScriptDefContextMaps.find(moduleName) == DefContext::allScriptDefContextMaps.end()) + { + PyObject* pyModule = NULL; + + if (packetPath.size() == 0 || packetPath == "components" || packetPath == "interfaces") + { + pyModule = PyImport_ImportModule(const_cast(moduleName)); + } + else + { + pyModule = PyImport_ImportModule(const_cast((packetPath + "." + moduleName).c_str())); + } + + if (!pyModule) + { + SCRIPT_ERROR_CHECK(); + free(wpath); + return false; + } + else + { + Py_DECREF(pyModule); + } + } + + free(moduleName); + } + + free(wpath); + + return true; +} + +//------------------------------------------------------------------------------------- +PyObject* __py_getAppPublish(PyObject* self, PyObject* args) +{ + return PyLong_FromLong(g_appPublish); +} + +//------------------------------------------------------------------------------------- +static bool execPython(COMPONENT_TYPE componentType) +{ + std::pair pyPaths = getComponentPythonPaths(componentType); + if (pyPaths.first.size() == 0) + { + ERROR_MSG(fmt::format("PyEntityDef::execPython(): PythonApp({}) paths error!\n", COMPONENT_NAME_EX(componentType))); + return false; + } + + APPEND_PYSYSPATH(pyPaths.second); + + PyObject* modulesOld = PySys_GetObject("modules"); + + PyThreadState* pCurInterpreter = PyThreadState_Get(); + PyThreadState* pNewInterpreter = Py_NewInterpreter(); + + if (!pNewInterpreter) + { + ERROR_MSG(fmt::format("PyEntityDef::execPython(): Py_NewInterpreter()!\n")); + SCRIPT_ERROR_CHECK(); + return false; + } + +#if KBE_PLATFORM != PLATFORM_WIN32 + strutil::kbe_replace(pyPaths.second, L";", L":"); +#endif + + PySys_SetPath(pyPaths.second.c_str()); + + PyObject* modulesNew = PySys_GetObject("modules"); + PyDict_Merge(modulesNew, Script::getSingleton().getSysInitModules(), 0); + + { + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(modulesOld, &pos, &key, &value)) + { + const char* typeName = PyUnicode_AsUTF8AndSize(key, NULL); + + if (std::string(typeName) == "KBEngine") + continue; + + PyObject* pyDoc = PyObject_GetAttrString(value, "__doc__"); + + if (pyDoc) + { + const char* doc = PyUnicode_AsUTF8AndSize(pyDoc, NULL); + + if (doc && std::string(doc).find("KBEngine") != std::string::npos) + PyDict_SetItemString(modulesNew, typeName, value); + + if (PyErr_Occurred()) + PyErr_Clear(); + + Py_XDECREF(pyDoc); + } + else + { + SCRIPT_ERROR_CHECK(); + } + } + } + + PyObject *m = PyImport_AddModule("__main__"); + + // һűģ + PyObject* kbeModule = PyImport_AddModule("KBEngine"); + KBE_ASSERT(kbeModule); + + Entity::registerScript(kbeModule); + Space::registerScript(kbeModule); + EntityComponent::registerScript(kbeModule); + + if (componentType == BASEAPP_TYPE) + Proxy::registerScript(kbeModule); + + const char* componentName = COMPONENT_NAME_EX(componentType); + if (PyModule_AddStringConstant(kbeModule, "component", componentName)) + { + ERROR_MSG(fmt::format("PyEntityDef::execPython(): Unable to set KBEngine.component to {}\n", + componentName)); + + return false; + } + + APPEND_SCRIPT_MODULE_METHOD(kbeModule, publish, __py_getAppPublish, METH_VARARGS, 0); + + // ģmain + PyObject_SetAttrString(m, "KBEngine", kbeModule); + + if (pNewInterpreter != PyThreadState_Swap(pCurInterpreter)) + { + KBE_ASSERT(false); + return false; + } + + PyThreadState_Swap(pNewInterpreter); + + bool otherPartSuccess = loadAllScriptForComponentType(componentType); + + Entity::unregisterScript(); + Space::unregisterScript(); + EntityComponent::unregisterScript(); + + if (componentType == BASEAPP_TYPE) + Proxy::unregisterScript(); + + if (pNewInterpreter != PyThreadState_Swap(pCurInterpreter)) + { + KBE_ASSERT(false); + return false; + } + + // ˴ʹPy_EndInterpreterᵼMathDefģ + PyInterpreterState_Clear(pNewInterpreter->interp); + PyInterpreterState_Delete(pNewInterpreter->interp); + return otherPartSuccess; +} + +//------------------------------------------------------------------------------------- +static bool loadAllScripts() +{ + std::vector< COMPONENT_TYPE > loadOtherComponentTypes; + + if (g_componentType == CELLAPP_TYPE || g_componentType == BASEAPP_TYPE) + { + bool otherPartSuccess = loadAllScriptForComponentType(g_componentType); + if (!otherPartSuccess) + return false; + + loadOtherComponentTypes.push_back((g_componentType == BASEAPP_TYPE) ? CELLAPP_TYPE : BASEAPP_TYPE); + } + else + { + loadOtherComponentTypes.push_back(BASEAPP_TYPE); + loadOtherComponentTypes.push_back(CELLAPP_TYPE); + } + + for (std::vector< COMPONENT_TYPE >::iterator iter = loadOtherComponentTypes.begin(); iter != loadOtherComponentTypes.end(); ++iter) + { + COMPONENT_TYPE componentType = (*iter); + + if (!execPython(componentType)) + return false; + } + + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerDefTypes() +{ + DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); + for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) + { + DefContext& defContext = iter->second; + + if (defContext.type == DefContext::DC_TYPE_FIXED_ARRAY) + { + FixedArrayType* fixedArray = new FixedArrayType; + + if (fixedArray->initialize(&defContext, defContext.moduleName)) + { + if (!DataTypes::addDataType(defContext.moduleName, fixedArray)) + return false; + } + else + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: parse ARRAY [{}] error! file: \"{}\"!\n", + defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); + + delete fixedArray; + return false; + } + } + else if (defContext.type == DefContext::DC_TYPE_FIXED_DICT) + { + FixedDictType* fixedDict = new FixedDictType; + + if (fixedDict->initialize(&defContext, defContext.moduleName)) + { + if (!DataTypes::addDataType(defContext.moduleName, fixedDict)) + return false; + } + else + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: parse FIXED_DICT [{}] error! file: \"{}\"!\n", + defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); + + delete fixedDict; + return false; + } + } + else if (defContext.type == DefContext::DC_TYPE_RENAME) + { + DataType* dataType = DataTypes::getDataType(defContext.returnType, false); + if (dataType == NULL) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: cannot fount type \'{}\', by alias[{}], file: \"{}\"!\n", + defContext.returnType, defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); + + return false; + } + + if (!DataTypes::addDataType(defContext.moduleName, dataType)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefTypes: addDataType \"{}\" error! file: \"{}\"!\n", + defContext.moduleName.c_str(), defContext.pyObjectSourceFile)); + + return false; + } + } + } + + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerDetailLevelInfo(ScriptDefModule* pScriptModule, DefContext& defContext) +{ + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerVolatileInfo(ScriptDefModule* pScriptModule, DefContext& defContext) +{ + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerDefPropertys(ScriptDefModule* pScriptModule, DefContext& defContext) +{ + DefContext::DEF_CONTEXTS& propertys = defContext.propertys; + + DefContext::DEF_CONTEXTS::iterator iter = propertys.begin(); + for (; iter != propertys.end(); ++iter) + { + DefContext& defPropContext = (*iter); + + ENTITY_PROPERTY_UID futype = 0; + EntityDataFlags flags = stringToEntityDataFlags(defPropContext.propertyFlags); + int32 hasBaseFlags = 0; + int32 hasCellFlags = 0; + int32 hasClientFlags = 0; + DataType* dataType = NULL; + bool isPersistent = (defPropContext.persistent != 0); + bool isIdentifier = false; // Ƿһ + uint32 databaseLength = defPropContext.databaseLength; // ݿеij + std::string indexType = defPropContext.propertyIndex; + DETAIL_TYPE detailLevel = DETAIL_LEVEL_FAR; + std::string name = defPropContext.attrName; + + if (!EntityDef::validDefPropertyName(name)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: '{}' is limited, in module({}), file: \"{}\"!\n", + name, pScriptModule->getName(), defPropContext.pyObjectSourceFile)); + + return false; + } + + if (defPropContext.detailLevel == "FAR") + detailLevel = DETAIL_LEVEL_FAR; + else if (defPropContext.detailLevel == "MEDIUM") + detailLevel = DETAIL_LEVEL_MEDIUM; + else if (defPropContext.detailLevel == "NEAR") + detailLevel = DETAIL_LEVEL_NEAR; + else + detailLevel = DETAIL_LEVEL_FAR; + + if (!EntityDef::calcDefPropertyUType(pScriptModule->getName(), name, defPropContext.utype > 0 ? defPropContext.utype : -1, pScriptModule, futype)) + return false; + + hasBaseFlags = ((uint32)flags) & ENTITY_BASE_DATA_FLAGS; + if (hasBaseFlags > 0) + pScriptModule->setBase(true); + + hasCellFlags = ((uint32)flags) & ENTITY_CELL_DATA_FLAGS; + if (hasCellFlags > 0) + pScriptModule->setCell(true); + + hasClientFlags = ((uint32)flags) & ENTITY_CLIENT_DATA_FLAGS; + if (hasClientFlags > 0) + pScriptModule->setClient(true); + + if (hasBaseFlags <= 0 && hasCellFlags <= 0) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: not fount flags[{}], is {}.{}, file: \"{}\"!\n", + defPropContext.propertyFlags, pScriptModule->getName(), defPropContext.pyObjectSourceFile)); + + return false; + } + + dataType = DataTypes::getDataType(defPropContext.returnType, false); + + if (!dataType) + { + DefContext* pDefPropTypeContext = DefContext::findDefContext(defPropContext.returnType); + if (!pDefPropTypeContext) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: not fount type[{}], is {}.{}, file: \"{}\"!\n", + defPropContext.returnType, pScriptModule->getName(), name.c_str(), defPropContext.pyObjectSourceFile)); + + return false; + } + + // ŵд + if (pDefPropTypeContext->type == DefContext::DC_TYPE_COMPONENT) + continue; + + if (pDefPropTypeContext->type == DefContext::DC_TYPE_FIXED_ARRAY) + { + FixedArrayType* dataType1 = new FixedArrayType(); + if (dataType1->initialize(pDefPropTypeContext, std::string(pScriptModule->getName()) + "_" + name)) + dataType = dataType1; + else + return false; + } + else + { + dataType = DataTypes::getDataType(defPropContext.returnType, false); + } + } + + if (dataType == NULL) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: not fount type[{}], is {}.{}, file: \"{}\"!\n", + defPropContext.returnType, pScriptModule->getName(), name.c_str(), defPropContext.pyObjectSourceFile)); + + return false; + } + + // һʵ + PropertyDescription* propertyDescription = PropertyDescription::createDescription(futype, defPropContext.returnType, + name, flags, isPersistent, + dataType, isIdentifier, indexType, + databaseLength, defPropContext.propertyDefaultVal, + detailLevel); + + bool ret = true; + + // ӵģ + if (hasCellFlags > 0) + ret = pScriptModule->addPropertyDescription(name.c_str(), + propertyDescription, CELLAPP_TYPE); + + if (hasBaseFlags > 0) + ret = pScriptModule->addPropertyDescription(name.c_str(), + propertyDescription, BASEAPP_TYPE); + + if (hasClientFlags > 0) + ret = pScriptModule->addPropertyDescription(name.c_str(), + propertyDescription, CLIENT_TYPE); + + if (!ret) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefPropertys: error, is {}.{}, file: \"{}\"!\n", + pScriptModule->getName(), name.c_str(), defPropContext.pyObjectSourceFile)); + + return false; + } + } + + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerDefComponents(ScriptDefModule* pScriptModule, DefContext& defContext) +{ + DefContext::DEF_CONTEXTS& propertys = defContext.propertys; + + DefContext::DEF_CONTEXTS::iterator iter = propertys.begin(); + for (; iter != propertys.end(); ++iter) + { + DefContext& defPropContext = (*iter); + + std::string componentName = defPropContext.attrName; + std::string componentTypeName = defPropContext.returnType; + bool isPersistent = (defPropContext.persistent != 0); + ENTITY_PROPERTY_UID futype = 0; + + DefContext* pDefPropTypeContext = DefContext::findDefContext(componentTypeName); + if (!pDefPropTypeContext) + { + continue; + } + + if (pDefPropTypeContext->type != DefContext::DC_TYPE_COMPONENT) + continue; + + if (!EntityDef::calcDefPropertyUType(pScriptModule->getName(), componentName, defPropContext.utype > 0 ? defPropContext.utype : -1, pScriptModule, futype)) + return false; + + // һʵ + uint32 flags = ED_FLAG_BASE | ED_FLAG_CELL_PUBLIC | ENTITY_CLIENT_DATA_FLAGS; + bool isIdentifier = false; // Ƿһ + uint32 databaseLength = 0; // ݿеij + std::string indexType = ""; + DETAIL_TYPE detailLevel = DETAIL_LEVEL_FAR; + std::string detailLevelStr = ""; + std::string strisPersistent; + std::string defaultStr = ""; + + if (!EntityDef::validDefPropertyName(componentName)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: '{}' is limited, in module({}), file: \"{}\"!\n", + componentName, pScriptModule->getName(), defPropContext.pyObjectSourceFile)); + + return false; + } + + // Ƿģ飬˵Ѿعٴμ + ScriptDefModule* pCompScriptDefModule = EntityDef::findScriptModule(componentTypeName.c_str(), false); + + if (!pCompScriptDefModule) + { + pCompScriptDefModule = EntityDef::registerNewScriptDefModule(componentTypeName); + pCompScriptDefModule->isPersistent(false); + pCompScriptDefModule->isComponentModule(true); + } + else + { + flags = ED_FLAG_UNKOWN; + + if (pCompScriptDefModule->hasBase()) + flags |= ED_FLAG_BASE; + + if (pCompScriptDefModule->hasCell()) + flags |= ED_FLAG_CELL_PUBLIC; + + if (pCompScriptDefModule->hasClient()) + { + if (pCompScriptDefModule->hasBase()) + flags |= ED_FLAG_BASE_AND_CLIENT; + else + flags |= (ED_FLAG_ALL_CLIENTS | ED_FLAG_CELL_PUBLIC_AND_OWN | ED_FLAG_OTHER_CLIENTS | ED_FLAG_OWN_CLIENT); + } + + EntityDef::addComponentProperty(futype, componentTypeName, componentName, flags, isPersistent, isIdentifier, + indexType, databaseLength, defaultStr, detailLevel, pScriptModule, pCompScriptDefModule); + + pScriptModule->addComponentDescription(componentName.c_str(), pCompScriptDefModule); + continue; + } + + // + if (!registerDefPropertys(pScriptModule, defContext)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: failed to loadDefPropertys(), entity:{}\n", + pScriptModule->getName())); + + return false; + } + + // ԼdetailLevelInfo + if (!registerDetailLevelInfo(pScriptModule, defContext)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: failed to register component:{} detailLevelInfo.\n", + pScriptModule->getName())); + + return false; + } + + // ԼvolatileInfo + if (!registerVolatileInfo(pScriptModule, defContext)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerDefComponents: failed to register component:{} volatileInfo.\n", + pScriptModule->getName())); + + return false; + } + + pCompScriptDefModule->autoMatchCompOwn(); + + flags = ED_FLAG_UNKOWN; + + if (pCompScriptDefModule->hasBase()) + flags |= ED_FLAG_BASE; + + if (pCompScriptDefModule->hasCell()) + flags |= ED_FLAG_CELL_PUBLIC; + + if (pCompScriptDefModule->hasClient()) + { + if (pCompScriptDefModule->hasBase()) + flags |= ED_FLAG_BASE_AND_CLIENT; + + if (pCompScriptDefModule->hasCell()) + flags |= (ED_FLAG_ALL_CLIENTS | ED_FLAG_CELL_PUBLIC_AND_OWN | ED_FLAG_OTHER_CLIENTS | ED_FLAG_OWN_CLIENT); + } + + EntityDef::addComponentProperty(futype, componentTypeName, componentName, flags, isPersistent, isIdentifier, + indexType, databaseLength, defaultStr, detailLevel, pScriptModule, pCompScriptDefModule); + + pScriptModule->addComponentDescription(componentName.c_str(), pCompScriptDefModule); + } + + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerEntityDef(ScriptDefModule* pScriptModule, DefContext& defContext) +{ + // + if (!registerDefPropertys(pScriptModule, defContext)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to registerDefPropertys(), entity:{}\n", + pScriptModule->getName())); + + return false; + } + + // ǵķԼ뵽ģ + if (!registerDefComponents(pScriptModule, defContext)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to registerDefComponents(), component:{}\n", + pScriptModule->getName())); + + return false; + } + + // ԼdetailLevelInfo + if (!registerDetailLevelInfo(pScriptModule, defContext)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to register entity:{} detailLevelInfo.\n", + pScriptModule->getName())); + + return false; + } + + // ԼvolatileInfo + if (!registerVolatileInfo(pScriptModule, defContext)) + { + ERROR_MSG(fmt::format("PyEntityDef::registerEntityDef: failed to register entity:{} volatileInfo.\n", + pScriptModule->getName())); + + return false; + } + + Py_INCREF((PyTypeObject *)defContext.pyObjectPtr.get()); + pScriptModule->setScriptType((PyTypeObject *)defContext.pyObjectPtr.get()); + pScriptModule->autoMatchCompOwn(); + return true; +} + +//------------------------------------------------------------------------------------- +static bool registerEntityDefs() +{ + if (!registerDefTypes()) + return false; + + DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); + for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) + { + DefContext& defContext = iter->second; + + if (defContext.type != DefContext::DC_TYPE_ENTITY) + continue; + + ScriptDefModule* pScriptModule = EntityDef::registerNewScriptDefModule(defContext.moduleName); + + if (!registerEntityDef(pScriptModule, defContext)) + return false; + + pScriptModule->onLoaded(); + } + + return true; +} + +//------------------------------------------------------------------------------------- +bool initialize() +{ + if (g_inited) + return false; + + g_inited = true; + + KBE_ASSERT(pyDefModuleName.size() > 0); + PyObject *entitydefModule = PyImport_AddModule(pyDefModuleName.c_str()); + + ENTITYFLAGMAP::iterator iter = g_entityFlagMapping.begin(); + for (; iter != g_entityFlagMapping.end(); ++iter) + { + if (PyModule_AddStringConstant(entitydefModule, iter->first.c_str(), iter->first.c_str())) + { + ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", + iter->first, iter->first)); + + return false; + } + } + + static const char* UNIQUE = "UNIQUE"; + if (PyModule_AddStringConstant(entitydefModule, UNIQUE, UNIQUE)) + { + ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", + UNIQUE, UNIQUE)); + + return false; + } + + static const char* INDEX = "INDEX"; + if (PyModule_AddStringConstant(entitydefModule, INDEX, INDEX)) + { + ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", + INDEX, INDEX)); + + return false; + } + + static const char* thisClass = "thisClass"; + if (PyModule_AddStringConstant(entitydefModule, thisClass, thisClass)) + { + ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", + thisClass, thisClass)); + + return false; + } + + APPEND_SCRIPT_MODULE_METHOD(entitydefModule, ARRAY, __py_array, METH_VARARGS, 0); + + static char allBaseTypeNames[64][MAX_BUF]; + std::vector< std::string > baseTypeNames = DataTypes::getBaseTypeNames(); + KBE_ASSERT(baseTypeNames.size() < 64); + + for (size_t idx = 0; idx < baseTypeNames.size(); idx++) + { + memset(allBaseTypeNames[idx], 0, MAX_BUF); + kbe_snprintf(allBaseTypeNames[idx], MAX_BUF, "%s", baseTypeNames[idx].c_str()); + if (PyModule_AddStringConstant(entitydefModule, allBaseTypeNames[idx], allBaseTypeNames[idx])) + { + ERROR_MSG(fmt::format("PyEntityDef::initialize(): Unable to set EntityDef.{} to {}\n", + allBaseTypeNames[idx], allBaseTypeNames[idx])); + + return false; + } + } + + if (!loadAllScripts()) + { + SCRIPT_ERROR_CHECK(); + return false; + } + + while (!g_callContexts.empty()) + g_callContexts.pop(); + + DefContext::allScriptDefContextLineMaps.clear(); + + if (!assemblyContexts(true)) + { + SCRIPT_ERROR_CHECK(); + DefContext::allScriptDefContextMaps.clear(); + return false; + } + + if (!registerEntityDefs()) + { + DefContext::allScriptDefContextMaps.clear(); + return false; + } + + return true; +} + +//------------------------------------------------------------------------------------- +bool finalise(bool isReload) +{ + return true; +} + +//------------------------------------------------------------------------------------- +void reload(bool fullReload) +{ + g_inited = false; +} + +//------------------------------------------------------------------------------------- +bool initializeWatcher() +{ + return true; +} + +//------------------------------------------------------------------------------------- +bool addToStream(MemoryStream* pMemoryStream) +{ + int size = DefContext::allScriptDefContextMaps.size(); + (*pMemoryStream) << size; + + DefContext::DEF_CONTEXT_MAP::iterator iter = DefContext::allScriptDefContextMaps.begin(); + for (; iter != DefContext::allScriptDefContextMaps.end(); ++iter) + { + const std::string& name = iter->first; + DefContext& defContext = iter->second; + + (*pMemoryStream) << name; + + defContext.addToStream(pMemoryStream); + } + + return true; +} + +//------------------------------------------------------------------------------------- +bool createFromStream(MemoryStream* pMemoryStream) +{ + int size = 0; + (*pMemoryStream) >> size; + + for (int i = 0; i < size; ++i) + { + std::string name = ""; + (*pMemoryStream) >> name; + + DefContext defContext; + defContext.createFromStream(pMemoryStream); + DefContext::allScriptDefContextLineMaps[defContext.pyObjectSourceFile] = defContext; + } + + return true; +} + +//------------------------------------------------------------------------------------- + +} +} +} diff --git a/kbe/src/server/dbmgr/dbmgr.cpp b/kbe/src/server/dbmgr/dbmgr.cpp index 5f95de31fe..7cf1fdf3c3 100644 --- a/kbe/src/server/dbmgr/dbmgr.cpp +++ b/kbe/src/server/dbmgr/dbmgr.cpp @@ -1,1274 +1,1287 @@ -// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com - - -#include "dbmgr.h" -#include "dbmgr_interface.h" -#include "dbtasks.h" -#include "profile.h" -#include "interfaces_handler.h" -#include "sync_app_datas_handler.h" -#include "update_dblog_handler.h" -#include "db_mysql/kbe_table_mysql.h" -#include "network/common.h" -#include "network/tcp_packet.h" -#include "network/udp_packet.h" -#include "network/message_handler.h" -#include "thread/threadpool.h" -#include "server/components.h" -#include "server/telnet_server.h" -#include "db_interface/db_interface.h" -#include "db_mysql/db_interface_mysql.h" -#include "entitydef/scriptdef_module.h" - -#include "baseapp/baseapp_interface.h" -#include "cellapp/cellapp_interface.h" -#include "baseappmgr/baseappmgr_interface.h" -#include "cellappmgr/cellappmgr_interface.h" -#include "loginapp/loginapp_interface.h" - -namespace KBEngine{ - -ServerConfig g_serverConfig; -KBE_SINGLETON_INIT(Dbmgr); - -//------------------------------------------------------------------------------------- -Dbmgr::Dbmgr(Network::EventDispatcher& dispatcher, - Network::NetworkInterface& ninterface, - COMPONENT_TYPE componentType, - COMPONENT_ID componentID): - PythonApp(dispatcher, ninterface, componentType, componentID), - loopCheckTimerHandle_(), - mainProcessTimer_(), - idServer_(1, 1024), - pGlobalData_(NULL), - pBaseAppData_(NULL), - pCellAppData_(NULL), - bufferedDBTasksMaps_(), - numWrittenEntity_(0), - numRemovedEntity_(0), - numQueryEntity_(0), - numExecuteRawDatabaseCommand_(0), - numCreatedAccount_(0), - pInterfacesHandlers_(), - pSyncAppDatasHandler_(NULL), - pUpdateDBServerLogHandler_(NULL), - pTelnetServer_(NULL), - loseBaseappts_() -{ - KBEngine::Network::MessageHandlers::pMainMessageHandlers = &DbmgrInterface::messageHandlers; -} - -//------------------------------------------------------------------------------------- -Dbmgr::~Dbmgr() -{ - loopCheckTimerHandle_.cancel(); - mainProcessTimer_.cancel(); - KBEngine::sleep(300); - - for (std::vector::iterator iter = pInterfacesHandlers_.begin(); iter != pInterfacesHandlers_.end(); ++iter) - { - SAFE_RELEASE((*iter)); - } -} - -//------------------------------------------------------------------------------------- -ShutdownHandler::CAN_SHUTDOWN_STATE Dbmgr::canShutdown() -{ - if (getEntryScript().get() && PyObject_HasAttrString(getEntryScript().get(), "onReadyForShutDown") > 0) - { - // нű - PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), - const_cast("onReadyForShutDown"), - const_cast("")); - - if (pyResult != NULL) - { - bool isReady = (pyResult == Py_True); - Py_DECREF(pyResult); - - if (!isReady) - return ShutdownHandler::CAN_SHUTDOWN_STATE_USER_FALSE; - } - else - { - SCRIPT_ERROR_CHECK(); - return ShutdownHandler::CAN_SHUTDOWN_STATE_USER_FALSE; - } - } - - KBEUnordered_map::iterator bditer = bufferedDBTasksMaps_.begin(); - for (; bditer != bufferedDBTasksMaps_.end(); ++bditer) - { - if (bditer->second.size() > 0) - { - thread::ThreadPool* pThreadPool = DBUtil::pThreadPool(bditer->first); - KBE_ASSERT(pThreadPool); - - INFO_MSG(fmt::format("Dbmgr::canShutdown(): Wait for the task to complete, dbInterface={}, tasks{}=[{}], threads={}/{}, threadpoolDestroyed={}!\n", - bditer->first, bditer->second.size(), bditer->second.getTasksinfos(), (pThreadPool->currentThreadCount() - pThreadPool->currentFreeThreadCount()), - pThreadPool->currentThreadCount(), pThreadPool->isDestroyed())); - - return ShutdownHandler::CAN_SHUTDOWN_STATE_FALSE; - } - } - - Components::COMPONENTS& cellapp_components = Components::getSingleton().getComponents(CELLAPP_TYPE); - if (cellapp_components.size() > 0) - { - std::string s; - for (size_t i = 0; i 0) - { - std::string s; - for (size_t i = 0; i("onDBMgrShutDown"), false); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onShutdownEnd() -{ - PythonApp::onShutdownEnd(); -} - -//------------------------------------------------------------------------------------- -bool Dbmgr::initializeWatcher() -{ - WATCH_OBJECT("numWrittenEntity", numWrittenEntity_); - WATCH_OBJECT("numRemovedEntity", numRemovedEntity_); - WATCH_OBJECT("numQueryEntity", numQueryEntity_); - WATCH_OBJECT("numExecuteRawDatabaseCommand", numExecuteRawDatabaseCommand_); - WATCH_OBJECT("numCreatedAccount", numCreatedAccount_); - - KBEUnordered_map::iterator bditer = bufferedDBTasksMaps_.begin(); - for (; bditer != bufferedDBTasksMaps_.end(); ++bditer) - { - WATCH_OBJECT(fmt::format("DBThreadPool/{}/dbid_tasksSize", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::dbid_tasksSize); - WATCH_OBJECT(fmt::format("DBThreadPool/{}/entityid_tasksSize", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::entityid_tasksSize); - WATCH_OBJECT(fmt::format("DBThreadPool/{}/printBuffered_dbid", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::printBuffered_dbid); - WATCH_OBJECT(fmt::format("DBThreadPool/{}/printBuffered_entityID", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::printBuffered_entityID); - } - - return ServerApp::initializeWatcher() && DBUtil::initializeWatcher(); -} - -//------------------------------------------------------------------------------------- -bool Dbmgr::run() -{ - return PythonApp::run(); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::handleTimeout(TimerHandle handle, void * arg) -{ - PythonApp::handleTimeout(handle, arg); - - switch (reinterpret_cast(arg)) - { - case TIMEOUT_TICK: - this->handleMainTick(); - break; - case TIMEOUT_CHECK_STATUS: - this->handleCheckStatusTick(); - break; - default: - break; - } -} - -//------------------------------------------------------------------------------------- -void Dbmgr::handleMainTick() -{ - AUTO_SCOPED_PROFILE("mainTick"); - - // time_t t = ::time(NULL); - // static int kbeTime = 0; - // DEBUG_MSG(fmt::format("Dbmgr::handleGameTick[{}]:{}\n", t, ++kbeTime)); - - threadPool_.onMainThreadTick(); - DBUtil::handleMainTick(); - networkInterface().processChannels(&DbmgrInterface::messageHandlers); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::handleCheckStatusTick() -{ - // 鶪ʧ̣һʱ֮Ȼ޷֣Ҫݿentitylog - if (loseBaseappts_.size() > 0) - { - std::map::iterator iter = loseBaseappts_.begin(); - for (; iter != loseBaseappts_.end();) - { - if (timestamp() > iter->second) - { - Components::ComponentInfos* cinfo = Components::getSingleton().findComponent(iter->first); - if (!cinfo) - { - ENGINE_COMPONENT_INFO& dbcfg = g_kbeSrvConfig.getDBMgr(); - std::vector::iterator dbinfo_iter = dbcfg.dbInterfaceInfos.begin(); - for (; dbinfo_iter != dbcfg.dbInterfaceInfos.end(); ++dbinfo_iter) - { - std::string dbInterfaceName = dbinfo_iter->name; - - DBUtil::pThreadPool(dbInterfaceName)-> - addTask(new DBTaskEraseBaseappEntityLog(iter->first)); - } - } - - loseBaseappts_.erase(iter++); - } - else - { - ++iter; - } - } - } -} - -//------------------------------------------------------------------------------------- -bool Dbmgr::initializeBegin() -{ - idServer_.set_range_step(g_kbeSrvConfig.getDBMgr().ids_increasing_range); - return true; -} - -//------------------------------------------------------------------------------------- -bool Dbmgr::inInitialize() -{ - // ʼչģ - // assets/scripts/ - if (!PythonApp::inInitialize()) - return false; - - std::vector scriptBaseTypes; - if(!EntityDef::initialize(scriptBaseTypes, componentType_)){ - return false; - } - - return true; -} - -//------------------------------------------------------------------------------------- -bool Dbmgr::initializeEnd() -{ - PythonApp::initializeEnd(); - - // һtimer ÿһЩ״̬ - loopCheckTimerHandle_ = this->dispatcher().addTimer(1000000, this, - reinterpret_cast(TIMEOUT_CHECK_STATUS)); - - mainProcessTimer_ = this->dispatcher().addTimer(1000000 / 50, this, - reinterpret_cast(TIMEOUT_TICK)); - - // globalData, baseAppData, cellAppData֧ - pGlobalData_ = new GlobalDataServer(GlobalDataServer::GLOBAL_DATA); - pBaseAppData_ = new GlobalDataServer(GlobalDataServer::BASEAPP_DATA); - pCellAppData_ = new GlobalDataServer(GlobalDataServer::CELLAPP_DATA); - pGlobalData_->addConcernComponentType(CELLAPP_TYPE); - pGlobalData_->addConcernComponentType(BASEAPP_TYPE); - pBaseAppData_->addConcernComponentType(BASEAPP_TYPE); - pCellAppData_->addConcernComponentType(CELLAPP_TYPE); - - INFO_MSG(fmt::format("Dbmgr::initializeEnd: digest({})\n", - EntityDef::md5().getDigestStr())); - - SCOPED_PROFILE(SCRIPTCALL_PROFILE); - - // нű - PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), - const_cast("onDBMgrReady"), - const_cast("")); - - if(pyResult != NULL) - Py_DECREF(pyResult); - else - SCRIPT_ERROR_CHECK(); - - pTelnetServer_ = new TelnetServer(&this->dispatcher(), &this->networkInterface()); - pTelnetServer_->pScript(&this->getScript()); - - bool ret = pTelnetServer_->start(g_kbeSrvConfig.getDBMgr().telnet_passwd, - g_kbeSrvConfig.getDBMgr().telnet_deflayer, - g_kbeSrvConfig.getDBMgr().telnet_port); - - Components::getSingleton().extraData4(pTelnetServer_->port()); - - return ret && initInterfacesHandler() && initDB(); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onInstallPyModules() -{ - PyObject * module = getScript().getModule(); - - for (int i = 0; i < SERVER_ERR_MAX; i++) - { - if(PyModule_AddIntConstant(module, SERVER_ERR_STR[i], i)) - { - ERROR_MSG( fmt::format("Dbmgr::onInstallPyModules: Unable to set KBEngine.{}.\n", SERVER_ERR_STR[i])); - } - } - - APPEND_SCRIPT_MODULE_METHOD(module, executeRawDatabaseCommand, __py_executeRawDatabaseCommand, METH_VARARGS, 0); -} - -//------------------------------------------------------------------------------------- -bool Dbmgr::initInterfacesHandler() -{ - std::vector< Network::Address > addresses = g_kbeSrvConfig.interfacesAddrs(); - std::string type = addresses.size() == 0 ? "dbmgr" : "interfaces"; - - if (type == "dbmgr") - { - InterfacesHandler* pInterfacesHandler = InterfacesHandlerFactory::create(type); - - INFO_MSG(fmt::format("Dbmgr::initInterfacesHandler: interfaces addr({}), accountType:({}), chargeType:({}).\n", - Network::Address::NONE.c_str(), - type, - type)); - - if (!pInterfacesHandler->initialize()) - return false; - - pInterfacesHandlers_.push_back(pInterfacesHandler); - } - else - { - std::vector< Network::Address >::iterator iter = addresses.begin(); - for (; iter != addresses.end(); ++iter) - { - InterfacesHandler* pInterfacesHandler = InterfacesHandlerFactory::create(type); - - const Network::Address& addr = (*iter); - - INFO_MSG(fmt::format("Dbmgr::initInterfacesHandler: interfaces addr({}), accountType:({}), chargeType:({}).\n", - addr.c_str(), - type, - type)); - - ((InterfacesHandler_Interfaces*)pInterfacesHandler)->setAddr(addr); - - if (!pInterfacesHandler->initialize()) - return false; - - pInterfacesHandlers_.push_back(pInterfacesHandler); - } - } - - return pInterfacesHandlers_.size() > 0; -} - -//------------------------------------------------------------------------------------- -bool Dbmgr::initDB() -{ - ScriptDefModule* pModule = EntityDef::findScriptModule(DBUtil::accountScriptName()); - if(pModule == NULL) - { - ERROR_MSG(fmt::format("Dbmgr::initDB(): not found account script[{}]!\n", - DBUtil::accountScriptName())); - - return false; - } - - ENGINE_COMPONENT_INFO& dbcfg = g_kbeSrvConfig.getDBMgr(); - if (dbcfg.dbInterfaceInfos.size() == 0) - { - ERROR_MSG(fmt::format("DBUtil::initialize: not found dbInterface! (kbengine[_defs].xml->dbmgr->databaseInterfaces)\n")); - return false; - } - - if (!DBUtil::initialize()) - { - ERROR_MSG("Dbmgr::initDB(): can't initialize dbInterface!\n"); - return false; - } - - bool hasDefaultInterface = false; - - std::vector::iterator dbinfo_iter = dbcfg.dbInterfaceInfos.begin(); - for (; dbinfo_iter != dbcfg.dbInterfaceInfos.end(); ++dbinfo_iter) - { - Buffered_DBTasks buffered_DBTasks; - bufferedDBTasksMaps_.insert(std::make_pair((*dbinfo_iter).name, buffered_DBTasks)); - BUFFERED_DBTASKS_MAP::iterator buffered_DBTasks_iter = bufferedDBTasksMaps_.find((*dbinfo_iter).name); - buffered_DBTasks_iter->second.dbInterfaceName((*dbinfo_iter).name); - } - - for (dbinfo_iter = dbcfg.dbInterfaceInfos.begin(); dbinfo_iter != dbcfg.dbInterfaceInfos.end(); ++dbinfo_iter) - { - DBInterface* pDBInterface = DBUtil::createInterface((*dbinfo_iter).name); - if(pDBInterface == NULL) - { - ERROR_MSG("Dbmgr::initDB(): can't create dbInterface!\n"); - return false; - } - - bool ret = DBUtil::initInterface(pDBInterface); - pDBInterface->detach(); - SAFE_RELEASE(pDBInterface); - - if(!ret) - return false; - - if (std::string("default") == (*dbinfo_iter).name) - hasDefaultInterface = true; - } - - if (!hasDefaultInterface) - { - ERROR_MSG("Dbmgr::initDB(): \"default\" dbInterface was not found! (kbengine[_defs].xml->dbmgr->databaseInterfaces)\n"); - return false; - } - - if(pUpdateDBServerLogHandler_ == NULL) - pUpdateDBServerLogHandler_ = new UpdateDBServerLogHandler(); - - return true; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::finalise() -{ - SAFE_RELEASE(pUpdateDBServerLogHandler_); - - SAFE_RELEASE(pGlobalData_); - SAFE_RELEASE(pBaseAppData_); - SAFE_RELEASE(pCellAppData_); - - if (pTelnetServer_) - { - pTelnetServer_->stop(); - SAFE_RELEASE(pTelnetServer_); - } - - DBUtil::finalise(); - PythonApp::finalise(); -} - -//------------------------------------------------------------------------------------- -InterfacesHandler* Dbmgr::findBestInterfacesHandler() -{ - if (pInterfacesHandlers_.size() == 0) - return NULL; - - static size_t i = 0; - - return pInterfacesHandlers_[i++ % pInterfacesHandlers_.size()]; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onReqAllocEntityID(Network::Channel* pChannel, COMPONENT_ORDER componentType, COMPONENT_ID componentID) -{ - KBEngine::COMPONENT_TYPE ct = static_cast(componentType); - - // ȡһid IDClient - std::pair idRange = idServer_.allocRange(); - Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT); - - if(ct == BASEAPP_TYPE) - (*pBundle).newMessage(BaseappInterface::onReqAllocEntityID); - else - (*pBundle).newMessage(CellappInterface::onReqAllocEntityID); - - (*pBundle) << idRange.first; - (*pBundle) << idRange.second; - pChannel->send(pBundle); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onRegisterNewApp(Network::Channel* pChannel, int32 uid, std::string& username, - COMPONENT_TYPE componentType, COMPONENT_ID componentID, COMPONENT_ORDER globalorderID, COMPONENT_ORDER grouporderID, - uint32 intaddr, uint16 intport, uint32 extaddr, uint16 extport, std::string& extaddrEx) -{ - if(pChannel->isExternal()) - return; - - ServerApp::onRegisterNewApp(pChannel, uid, username, componentType, componentID, globalorderID, grouporderID, - intaddr, intport, extaddr, extport, extaddrEx); - - KBEngine::COMPONENT_TYPE tcomponentType = (KBEngine::COMPONENT_TYPE)componentType; - - COMPONENT_ORDER startGroupOrder = 1; - COMPONENT_ORDER startGlobalOrder = Components::getSingleton().getGlobalOrderLog()[getUserUID()]; - - if(grouporderID > 0) - startGroupOrder = grouporderID; - - if(globalorderID > 0) - startGlobalOrder = globalorderID; - - if(pSyncAppDatasHandler_ == NULL) - pSyncAppDatasHandler_ = new SyncAppDatasHandler(this->networkInterface()); - - // һ: - // ӵdbmgrҪȴappʼϢ - // 磺ʼentityIDԼapp˳ϢǷһbaseapp - if(tcomponentType == BASEAPP_TYPE || - tcomponentType == CELLAPP_TYPE || - tcomponentType == LOGINAPP_TYPE) - { - switch(tcomponentType) - { - case BASEAPP_TYPE: - { - if(grouporderID <= 0) - startGroupOrder = Components::getSingleton().getBaseappGroupOrderLog()[getUserUID()]; - } - break; - case CELLAPP_TYPE: - { - if(grouporderID <= 0) - startGroupOrder = Components::getSingleton().getCellappGroupOrderLog()[getUserUID()]; - } - break; - case LOGINAPP_TYPE: - if(grouporderID <= 0) - startGroupOrder = Components::getSingleton().getLoginappGroupOrderLog()[getUserUID()]; - - break; - default: - break; - } - } - - pSyncAppDatasHandler_->pushApp(componentID, startGroupOrder, startGlobalOrder); - - // baseappcellappԼעᵽbaseappcellapp - if(tcomponentType == BASEAPP_TYPE || - tcomponentType == CELLAPP_TYPE) - { - KBEngine::COMPONENT_TYPE broadcastCpTypes[2] = {BASEAPP_TYPE, CELLAPP_TYPE}; - for(int idx = 0; idx < 2; ++idx) - { - Components::COMPONENTS& cts = Components::getSingleton().getComponents(broadcastCpTypes[idx]); - Components::COMPONENTS::iterator fiter = cts.begin(); - for(; fiter != cts.end(); ++fiter) - { - if((*fiter).cid == componentID) - continue; - - Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT); - ENTITTAPP_COMMON_NETWORK_MESSAGE(broadcastCpTypes[idx], (*pBundle), onGetEntityAppFromDbmgr); - - if(tcomponentType == BASEAPP_TYPE) - { - BaseappInterface::onGetEntityAppFromDbmgrArgs11::staticAddToBundle((*pBundle), - uid, username, componentType, componentID, startGlobalOrder, startGroupOrder, - intaddr, intport, extaddr, extport, g_kbeSrvConfig.getConfig().externalAddress); - } - else - { - CellappInterface::onGetEntityAppFromDbmgrArgs11::staticAddToBundle((*pBundle), - uid, username, componentType, componentID, startGlobalOrder, startGroupOrder, - intaddr, intport, extaddr, extport, g_kbeSrvConfig.getConfig().externalAddress); - } - - KBE_ASSERT((*fiter).pChannel != NULL); - (*fiter).pChannel->send(pBundle); - } - } - } -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onGlobalDataClientLogon(Network::Channel* pChannel, COMPONENT_TYPE componentType) -{ - if(BASEAPP_TYPE == componentType) - { - pBaseAppData_->onGlobalDataClientLogon(pChannel, componentType); - pGlobalData_->onGlobalDataClientLogon(pChannel, componentType); - } - else if(CELLAPP_TYPE == componentType) - { - pGlobalData_->onGlobalDataClientLogon(pChannel, componentType); - pCellAppData_->onGlobalDataClientLogon(pChannel, componentType); - } - else - { - ERROR_MSG(fmt::format("Dbmgr::onGlobalDataClientLogon: nonsupport {}!\n", - COMPONENT_NAME_EX(componentType))); - } -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onBroadcastGlobalDataChanged(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - uint8 dataType; - std::string key, value; - bool isDelete; - COMPONENT_TYPE componentType; - - s >> dataType; - s >> isDelete; - - s.readBlob(key); - - if(!isDelete) - { - s.readBlob(value); - } - - s >> componentType; - - switch(dataType) - { - case GlobalDataServer::GLOBAL_DATA: - if(isDelete) - pGlobalData_->del(pChannel, componentType, key); - else - pGlobalData_->write(pChannel, componentType, key, value); - break; - case GlobalDataServer::BASEAPP_DATA: - if(isDelete) - pBaseAppData_->del(pChannel, componentType, key); - else - pBaseAppData_->write(pChannel, componentType, key, value); - break; - case GlobalDataServer::CELLAPP_DATA: - if(isDelete) - pCellAppData_->del(pChannel, componentType, key); - else - pCellAppData_->write(pChannel, componentType, key, value); - break; - default: - KBE_ASSERT(false && "dataType error!\n"); - break; - }; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::reqCreateAccount(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - std::string registerName, password, datas; - uint8 uatype = 0; - - s >> registerName >> password >> uatype; - s.readBlob(datas); - - if(registerName.size() == 0) - { - ERROR_MSG("Dbmgr::reqCreateAccount: registerName is empty.\n"); - return; - } - - findBestInterfacesHandler()->createAccount(pChannel, registerName, password, datas, ACCOUNT_TYPE(uatype)); - numCreatedAccount_++; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onCreateAccountCBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - findBestInterfacesHandler()->onCreateAccountCB(s); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onAccountLogin(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - std::string loginName, password, datas; - s >> loginName >> password; - s.readBlob(datas); - - if(loginName.size() == 0) - { - ERROR_MSG("Dbmgr::onAccountLogin: loginName is empty.\n"); - return; - } - - findBestInterfacesHandler()->loginAccount(pChannel, loginName, password, datas); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onLoginAccountCBBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - findBestInterfacesHandler()->onLoginAccountCB(s); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::queryAccount(Network::Channel* pChannel, - std::string& accountName, - std::string& password, - bool needCheckPassword, - COMPONENT_ID componentID, - ENTITY_ID entityID, - DBID entityDBID, - uint32 ip, - uint16 port) -{ - if(accountName.size() == 0) - { - ERROR_MSG("Dbmgr::queryAccount: accountName is empty.\n"); - return; - } - - Buffered_DBTasks* pBuffered_DBTasks = - findBufferedDBTask(Dbmgr::getSingleton().selectAccountDBInterfaceName(accountName)); - - if (!pBuffered_DBTasks) - { - ERROR_MSG(fmt::format("Dbmgr::queryAccount: not found dbInterface({})!\n", - Dbmgr::getSingleton().selectAccountDBInterfaceName(accountName))); - return; - } - - pBuffered_DBTasks->addTask(new DBTaskQueryAccount(pChannel->addr(), accountName, password, needCheckPassword, - componentID, entityID, entityDBID, ip, port)); - - numQueryEntity_++; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onAccountOnline(Network::Channel* pChannel, - std::string& accountName, - COMPONENT_ID componentID, - ENTITY_ID entityID) -{ - // bufferedDBTasks_.addTask(new DBTaskAccountOnline(pChannel->addr(), - // accountName, componentID, entityID)); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onEntityOffline(Network::Channel* pChannel, DBID dbid, ENTITY_SCRIPT_UID sid, uint16 dbInterfaceIndex) -{ - Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)); - if (!pBuffered_DBTasks) - { - ERROR_MSG(fmt::format("Dbmgr::onEntityOffline: not found dbInterfaceIndex({})!\n", dbInterfaceIndex)); - return; - } - - pBuffered_DBTasks->addTask(new DBTaskEntityOffline(pChannel->addr(), dbid, sid)); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::executeRawDatabaseCommand(Network::Channel* pChannel, - KBEngine::MemoryStream& s) -{ - ENTITY_ID entityID = -1; - s >> entityID; - - uint16 dbInterfaceIndex = 0; - s >> dbInterfaceIndex; - - std::string dbInterfaceName = g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex); - if (dbInterfaceName.size() == 0) - { - ERROR_MSG(fmt::format("Dbmgr::executeRawDatabaseCommand: not found dbInterface({})!\n", dbInterfaceName)); - s.done(); - return; - } - - if (entityID == -1) - { - thread::ThreadPool* pThreadPool = DBUtil::pThreadPool(dbInterfaceName); - if (!pThreadPool) - { - ERROR_MSG(fmt::format("Dbmgr::executeRawDatabaseCommand: not found pThreadPool(dbInterface={})!\n", dbInterfaceName)); - s.done(); - return; - } - - pThreadPool->addTask(new DBTaskExecuteRawDatabaseCommand(pChannel ? pChannel->addr() : Network::Address::NONE, s)); - } - else - { - Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(dbInterfaceName); - if (!pBuffered_DBTasks) - { - ERROR_MSG(fmt::format("Dbmgr::executeRawDatabaseCommand: not found pBuffered_DBTasks(dbInterface={})!\n", dbInterfaceName)); - s.done(); - return; - } - - pBuffered_DBTasks->addTask(new DBTaskExecuteRawDatabaseCommandByEntity(pChannel ? pChannel->addr() : Network::Address::NONE, s, entityID)); - } - - s.done(); - - ++numExecuteRawDatabaseCommand_; -} - -//------------------------------------------------------------------------------------- -PyObject* Dbmgr::__py_executeRawDatabaseCommand(PyObject* self, PyObject* args) -{ - int argCount = (int)PyTuple_Size(args); - PyObject* pycallback = NULL; - PyObject* pyDBInterfaceName = NULL; - int ret = -1; - ENTITY_ID eid = -1; - - char* data = NULL; - Py_ssize_t size; - - if (argCount == 4) - ret = PyArg_ParseTuple(args, "s#|O|i|O", &data, &size, &pycallback, &eid, &pyDBInterfaceName); - else if (argCount == 3) - ret = PyArg_ParseTuple(args, "s#|O|i", &data, &size, &pycallback, &eid); - else if (argCount == 2) - ret = PyArg_ParseTuple(args, "s#|O", &data, &size, &pycallback); - else if (argCount == 1) - ret = PyArg_ParseTuple(args, "s#", &data, &size); - - if (ret == -1) - { - PyErr_Format(PyExc_TypeError, "KBEngine::executeRawDatabaseCommand: args error!"); - PyErr_PrintEx(0); - S_Return; - } - - std::string dbInterfaceName = "default"; - if (pyDBInterfaceName) - { - dbInterfaceName = PyUnicode_AsUTF8AndSize(pyDBInterfaceName, NULL); - - if (!g_kbeSrvConfig.dbInterface(dbInterfaceName)) - { - PyErr_Format(PyExc_TypeError, "KBEngine::executeRawDatabaseCommand: args4, incorrect dbInterfaceName(%s)!", - dbInterfaceName.c_str()); - - PyErr_PrintEx(0); - S_Return; - } - } - - Dbmgr::getSingleton().executeRawDatabaseCommand(data, (uint32)size, pycallback, eid, dbInterfaceName); - S_Return; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::executeRawDatabaseCommand(const char* datas, uint32 size, PyObject* pycallback, ENTITY_ID eid, const std::string& dbInterfaceName) -{ - if (datas == NULL) - { - ERROR_MSG("KBEngine::executeRawDatabaseCommand: execute error!\n"); - return; - } - - int dbInterfaceIndex = g_kbeSrvConfig.dbInterfaceName2dbInterfaceIndex(dbInterfaceName); - if (dbInterfaceIndex < 0) - { - ERROR_MSG(fmt::format("KBEngine::executeRawDatabaseCommand: not found dbInterface({})!\n", - dbInterfaceName)); - - return; - } - - //INFO_MSG(fmt::format("KBEngine::executeRawDatabaseCommand{}:{}.\n", (eid > 0 ? fmt::format("(entityID={})", eid) : ""), datas)); - - MemoryStream* pMemoryStream = MemoryStream::createPoolObject(OBJECTPOOL_POINT); - (*pMemoryStream) << eid; - (*pMemoryStream) << (uint16)dbInterfaceIndex; - (*pMemoryStream) << componentID_ << componentType_; - - CALLBACK_ID callbackID = 0; - - if (pycallback && PyCallable_Check(pycallback)) - callbackID = callbackMgr().save(pycallback); - - (*pMemoryStream) << callbackID; - (*pMemoryStream) << size; - (*pMemoryStream).append(datas, size); - executeRawDatabaseCommand(NULL, *pMemoryStream); - MemoryStream::reclaimPoolObject(pMemoryStream); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onExecuteRawDatabaseCommandCB(KBEngine::MemoryStream& s) -{ - std::string err; - CALLBACK_ID callbackID = 0; - uint32 nrows = 0; - uint32 nfields = 0; - uint64 affectedRows = 0; - uint64 lastInsertID = 0; - - PyObject* pResultSet = NULL; - PyObject* pAffectedRows = NULL; - PyObject* pLastInsertID = NULL; - PyObject* pErrorMsg = NULL; - - s >> callbackID; - s >> err; - - if (err.size() <= 0) - { - s >> nfields; - - pErrorMsg = Py_None; - Py_INCREF(pErrorMsg); - - if (nfields > 0) - { - pAffectedRows = Py_None; - Py_INCREF(pAffectedRows); - - pLastInsertID = Py_None; - Py_INCREF(pLastInsertID); - - s >> nrows; - - pResultSet = PyList_New(nrows); - for (uint32 i = 0; i < nrows; ++i) - { - PyObject* pRow = PyList_New(nfields); - for (uint32 j = 0; j < nfields; ++j) - { - std::string cell; - s.readBlob(cell); - - PyObject* pCell = NULL; - - if (cell == "KBE_QUERY_DB_NULL") - { - Py_INCREF(Py_None); - pCell = Py_None; - } - else - { - pCell = PyBytes_FromStringAndSize(cell.data(), cell.length()); - } - - PyList_SET_ITEM(pRow, j, pCell); - } - - PyList_SET_ITEM(pResultSet, i, pRow); - } - } - else - { - pResultSet = Py_None; - Py_INCREF(pResultSet); - - pErrorMsg = Py_None; - Py_INCREF(pErrorMsg); - - s >> affectedRows; - - pAffectedRows = PyLong_FromUnsignedLongLong(affectedRows); - - s >> lastInsertID; - pLastInsertID = PyLong_FromUnsignedLongLong(lastInsertID); - } - } - else - { - pResultSet = Py_None; - Py_INCREF(pResultSet); - - pErrorMsg = PyUnicode_FromString(err.c_str()); - - pAffectedRows = Py_None; - Py_INCREF(pAffectedRows); - - pLastInsertID = Py_None; - Py_INCREF(pLastInsertID); - } - - s.done(); - - //DEBUG_MSG(fmt::format("Cellapp::onExecuteRawDatabaseCommandCB: nrows={}, nfields={}, err={}.\n", - // nrows, nfields, err.c_str())); - - if (callbackID > 0) - { - SCOPED_PROFILE(SCRIPTCALL_PROFILE); - - PyObjectPtr pyfunc = pyCallbackMgr_.take(callbackID); - if (pyfunc != NULL) - { - PyObject* pyResult = PyObject_CallFunction(pyfunc.get(), - const_cast("OOOO"), - pResultSet, pAffectedRows, pLastInsertID, pErrorMsg); - - if (pyResult != NULL) - Py_DECREF(pyResult); - else - SCRIPT_ERROR_CHECK(); - } - else - { - ERROR_MSG(fmt::format("Cellapp::onExecuteRawDatabaseCommandCB: not found callback:{}.\n", - callbackID)); - } - } - - Py_XDECREF(pResultSet); - Py_XDECREF(pAffectedRows); - Py_XDECREF(pLastInsertID); - Py_XDECREF(pErrorMsg); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::writeEntity(Network::Channel* pChannel, - KBEngine::MemoryStream& s) -{ - ENTITY_ID eid; - DBID entityDBID; - COMPONENT_ID componentID; - uint16 dbInterfaceIndex; - - s >> componentID >> eid >> entityDBID >> dbInterfaceIndex; - - Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)); - if (!pBuffered_DBTasks) - { - ERROR_MSG(fmt::format("Dbmgr::writeEntity: not found dbInterfaceIndex({})!\n", dbInterfaceIndex)); - s.done(); - return; - } - - pBuffered_DBTasks->addTask(new DBTaskWriteEntity(pChannel->addr(), componentID, eid, entityDBID, s)); - s.done(); - - ++numWrittenEntity_; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::removeEntity(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - ENTITY_ID eid; - DBID entityDBID; - COMPONENT_ID componentID; - uint16 dbInterfaceIndex; - - s >> dbInterfaceIndex >> componentID >> eid >> entityDBID; - KBE_ASSERT(entityDBID > 0); - - Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)); - if (!pBuffered_DBTasks) - { - ERROR_MSG(fmt::format("Dbmgr::removeEntity: not found dbInterfaceIndex({})!\n", dbInterfaceIndex)); - s.done(); - return; - } - - pBuffered_DBTasks->addTask(new DBTaskRemoveEntity(pChannel->addr(), - componentID, eid, entityDBID, s)); - - s.done(); - - ++numRemovedEntity_; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::entityAutoLoad(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - COMPONENT_ID componentID; - ENTITY_SCRIPT_UID entityType; - ENTITY_ID start; - ENTITY_ID end; - uint16 dbInterfaceIndex = 0; - - s >> dbInterfaceIndex >> componentID >> entityType >> start >> end; - - DBUtil::pThreadPool(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex))-> - addTask(new DBTaskEntityAutoLoad(pChannel->addr(), componentID, entityType, start, end)); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::deleteEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - COMPONENT_ID componentID; - ENTITY_SCRIPT_UID sid; - CALLBACK_ID callbackID = 0; - DBID entityDBID; - uint16 dbInterfaceIndex = 0; - - s >> dbInterfaceIndex >> componentID >> entityDBID >> callbackID >> sid; - KBE_ASSERT(entityDBID > 0); - - DBUtil::pThreadPool(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex))-> - addTask(new DBTaskDeleteEntityByDBID(pChannel->addr(), componentID, entityDBID, callbackID, sid)); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::lookUpEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - COMPONENT_ID componentID; - ENTITY_SCRIPT_UID sid; - CALLBACK_ID callbackID = 0; - DBID entityDBID; - uint16 dbInterfaceIndex = 0; - - s >> dbInterfaceIndex >> componentID >> entityDBID >> callbackID >> sid; - KBE_ASSERT(entityDBID > 0); - - DBUtil::pThreadPool(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex))-> - addTask(new DBTaskLookUpEntityByDBID(pChannel->addr(), componentID, entityDBID, callbackID, sid)); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::queryEntity(Network::Channel* pChannel, uint16 dbInterfaceIndex, COMPONENT_ID componentID, int8 queryMode, DBID dbid, - std::string& entityType, CALLBACK_ID callbackID, ENTITY_ID entityID) -{ - bufferedDBTasksMaps_[g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)]. - addTask(new DBTaskQueryEntity(pChannel->addr(), queryMode, entityType, dbid, componentID, callbackID, entityID)); - - numQueryEntity_++; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::syncEntityStreamTemplate(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - int rpos = s.rpos(); - EntityTables::ENTITY_TABLES_MAP::iterator iter = EntityTables::sEntityTables.begin(); - for (; iter != EntityTables::sEntityTables.end(); ++iter) - { - KBEAccountTable* pTable = - static_cast(iter->second.findKBETable(KBE_TABLE_PERFIX "_accountinfos")); - - KBE_ASSERT(pTable); - - s.rpos(rpos); - pTable->accountDefMemoryStream(s); - } - - s.done(); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::charge(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - findBestInterfacesHandler()->charge(pChannel, s); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onChargeCB(Network::Channel* pChannel, KBEngine::MemoryStream& s) -{ - findBestInterfacesHandler()->onChargeCB(s); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::eraseClientReq(Network::Channel* pChannel, std::string& logkey) -{ - std::vector::iterator iter = pInterfacesHandlers_.begin(); - for(; iter != pInterfacesHandlers_.end(); ++iter) - (*iter)->eraseClientReq(pChannel, logkey); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::accountActivate(Network::Channel* pChannel, std::string& scode) -{ - INFO_MSG(fmt::format("Dbmgr::accountActivate: code={}.\n", scode)); - findBestInterfacesHandler()->accountActivate(pChannel, scode); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::accountReqResetPassword(Network::Channel* pChannel, std::string& accountName) -{ - INFO_MSG(fmt::format("Dbmgr::accountReqResetPassword: accountName={}.\n", accountName)); - findBestInterfacesHandler()->accountReqResetPassword(pChannel, accountName); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::accountResetPassword(Network::Channel* pChannel, std::string& accountName, std::string& newpassword, std::string& code) -{ - INFO_MSG(fmt::format("Dbmgr::accountResetPassword: accountName={}.\n", accountName)); - findBestInterfacesHandler()->accountResetPassword(pChannel, accountName, newpassword, code); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::accountReqBindMail(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, - std::string& password, std::string& email) -{ - INFO_MSG(fmt::format("Dbmgr::accountReqBindMail: accountName={}, email={}.\n", accountName, email)); - findBestInterfacesHandler()->accountReqBindMail(pChannel, entityID, accountName, password, email); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::accountBindMail(Network::Channel* pChannel, std::string& username, std::string& scode) -{ - INFO_MSG(fmt::format("Dbmgr::accountBindMail: username={}, scode={}.\n", username, scode)); - findBestInterfacesHandler()->accountBindMail(pChannel, username, scode); -} - -//------------------------------------------------------------------------------------- -void Dbmgr::accountNewPassword(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, - std::string& password, std::string& newpassword) -{ - INFO_MSG(fmt::format("Dbmgr::accountNewPassword: accountName={}.\n", accountName)); - findBestInterfacesHandler()->accountNewPassword(pChannel, entityID, accountName, password, newpassword); -} - -//------------------------------------------------------------------------------------- -std::string Dbmgr::selectAccountDBInterfaceName(const std::string& name) -{ - std::string dbInterfaceName = "default"; - - // ɽű - SCOPED_PROFILE(SCRIPTCALL_PROFILE); - PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), - const_cast("onSelectAccountDBInterface"), - const_cast("s"), - name.c_str()); - - if (pyResult != NULL) - { - dbInterfaceName = PyUnicode_AsUTF8AndSize(pyResult, NULL); - Py_DECREF(pyResult); - } - else - { - SCRIPT_ERROR_CHECK(); - } - - if (dbInterfaceName == "" || g_kbeSrvConfig.dbInterface(dbInterfaceName) == NULL) - { - ERROR_MSG(fmt::format("Dbmgr::selectAccountDBInterfaceName: not found dbInterface({}), accountName={}.\n", dbInterfaceName, name)); - return "default"; - } - - return dbInterfaceName; -} - -//------------------------------------------------------------------------------------- -void Dbmgr::onChannelDeregister(Network::Channel * pChannel) -{ - // app - if (pChannel->isInternal()) - { - Components::ComponentInfos* cinfo = Components::getSingleton().findComponent(pChannel); - if (cinfo) - { - if (cinfo->componentType == BASEAPP_TYPE) - { - loseBaseappts_[cinfo->cid] = timestamp() + uint64(60 * stampsPerSecond()); - WARNING_MSG(fmt::format("Dbmgr::onChannelDeregister(): If the process cannot be resumed, the entitylog(baseapp={}) will be cleaned up after 60 seconds!\n", cinfo->cid)); - } - } - } - - ServerApp::onChannelDeregister(pChannel); -} - -//------------------------------------------------------------------------------------- -} +// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com + + +#include "dbmgr.h" +#include "dbmgr_interface.h" +#include "dbtasks.h" +#include "profile.h" +#include "interfaces_handler.h" +#include "sync_app_datas_handler.h" +#include "update_dblog_handler.h" +#include "db_mysql/kbe_table_mysql.h" +#include "network/common.h" +#include "network/tcp_packet.h" +#include "network/udp_packet.h" +#include "network/message_handler.h" +#include "thread/threadpool.h" +#include "server/components.h" +#include "server/telnet_server.h" +#include "db_interface/db_interface.h" +#include "db_mysql/db_interface_mysql.h" +#include "entitydef/scriptdef_module.h" +#include "entitydef/py_entitydef.h" + +#include "baseapp/baseapp_interface.h" +#include "cellapp/cellapp_interface.h" +#include "baseappmgr/baseappmgr_interface.h" +#include "cellappmgr/cellappmgr_interface.h" +#include "loginapp/loginapp_interface.h" + +namespace KBEngine{ + +ServerConfig g_serverConfig; +KBE_SINGLETON_INIT(Dbmgr); + +//------------------------------------------------------------------------------------- +Dbmgr::Dbmgr(Network::EventDispatcher& dispatcher, + Network::NetworkInterface& ninterface, + COMPONENT_TYPE componentType, + COMPONENT_ID componentID): + PythonApp(dispatcher, ninterface, componentType, componentID), + loopCheckTimerHandle_(), + mainProcessTimer_(), + idServer_(1, 1024), + pGlobalData_(NULL), + pBaseAppData_(NULL), + pCellAppData_(NULL), + bufferedDBTasksMaps_(), + numWrittenEntity_(0), + numRemovedEntity_(0), + numQueryEntity_(0), + numExecuteRawDatabaseCommand_(0), + numCreatedAccount_(0), + pInterfacesHandlers_(), + pSyncAppDatasHandler_(NULL), + pUpdateDBServerLogHandler_(NULL), + pTelnetServer_(NULL), + loseBaseappts_() +{ + KBEngine::Network::MessageHandlers::pMainMessageHandlers = &DbmgrInterface::messageHandlers; +} + +//------------------------------------------------------------------------------------- +Dbmgr::~Dbmgr() +{ + loopCheckTimerHandle_.cancel(); + mainProcessTimer_.cancel(); + KBEngine::sleep(300); + + for (std::vector::iterator iter = pInterfacesHandlers_.begin(); iter != pInterfacesHandlers_.end(); ++iter) + { + SAFE_RELEASE((*iter)); + } +} + +//------------------------------------------------------------------------------------- +ShutdownHandler::CAN_SHUTDOWN_STATE Dbmgr::canShutdown() +{ + if (getEntryScript().get() && PyObject_HasAttrString(getEntryScript().get(), "onReadyForShutDown") > 0) + { + // нű + PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), + const_cast("onReadyForShutDown"), + const_cast("")); + + if (pyResult != NULL) + { + bool isReady = (pyResult == Py_True); + Py_DECREF(pyResult); + + if (!isReady) + return ShutdownHandler::CAN_SHUTDOWN_STATE_USER_FALSE; + } + else + { + SCRIPT_ERROR_CHECK(); + return ShutdownHandler::CAN_SHUTDOWN_STATE_USER_FALSE; + } + } + + KBEUnordered_map::iterator bditer = bufferedDBTasksMaps_.begin(); + for (; bditer != bufferedDBTasksMaps_.end(); ++bditer) + { + if (bditer->second.size() > 0) + { + thread::ThreadPool* pThreadPool = DBUtil::pThreadPool(bditer->first); + KBE_ASSERT(pThreadPool); + + INFO_MSG(fmt::format("Dbmgr::canShutdown(): Wait for the task to complete, dbInterface={}, tasks{}=[{}], threads={}/{}, threadpoolDestroyed={}!\n", + bditer->first, bditer->second.size(), bditer->second.getTasksinfos(), (pThreadPool->currentThreadCount() - pThreadPool->currentFreeThreadCount()), + pThreadPool->currentThreadCount(), pThreadPool->isDestroyed())); + + return ShutdownHandler::CAN_SHUTDOWN_STATE_FALSE; + } + } + + Components::COMPONENTS& cellapp_components = Components::getSingleton().getComponents(CELLAPP_TYPE); + if (cellapp_components.size() > 0) + { + std::string s; + for (size_t i = 0; i 0) + { + std::string s; + for (size_t i = 0; i("onDBMgrShutDown"), false); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onShutdownEnd() +{ + PythonApp::onShutdownEnd(); +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::initializeWatcher() +{ + WATCH_OBJECT("numWrittenEntity", numWrittenEntity_); + WATCH_OBJECT("numRemovedEntity", numRemovedEntity_); + WATCH_OBJECT("numQueryEntity", numQueryEntity_); + WATCH_OBJECT("numExecuteRawDatabaseCommand", numExecuteRawDatabaseCommand_); + WATCH_OBJECT("numCreatedAccount", numCreatedAccount_); + + KBEUnordered_map::iterator bditer = bufferedDBTasksMaps_.begin(); + for (; bditer != bufferedDBTasksMaps_.end(); ++bditer) + { + WATCH_OBJECT(fmt::format("DBThreadPool/{}/dbid_tasksSize", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::dbid_tasksSize); + WATCH_OBJECT(fmt::format("DBThreadPool/{}/entityid_tasksSize", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::entityid_tasksSize); + WATCH_OBJECT(fmt::format("DBThreadPool/{}/printBuffered_dbid", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::printBuffered_dbid); + WATCH_OBJECT(fmt::format("DBThreadPool/{}/printBuffered_entityID", bditer->first).c_str(), &bditer->second, &Buffered_DBTasks::printBuffered_entityID); + } + + return ServerApp::initializeWatcher() && DBUtil::initializeWatcher(); +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::run() +{ + return PythonApp::run(); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::handleTimeout(TimerHandle handle, void * arg) +{ + PythonApp::handleTimeout(handle, arg); + + switch (reinterpret_cast(arg)) + { + case TIMEOUT_TICK: + this->handleMainTick(); + break; + case TIMEOUT_CHECK_STATUS: + this->handleCheckStatusTick(); + break; + default: + break; + } +} + +//------------------------------------------------------------------------------------- +void Dbmgr::handleMainTick() +{ + AUTO_SCOPED_PROFILE("mainTick"); + + // time_t t = ::time(NULL); + // static int kbeTime = 0; + // DEBUG_MSG(fmt::format("Dbmgr::handleGameTick[{}]:{}\n", t, ++kbeTime)); + + threadPool_.onMainThreadTick(); + DBUtil::handleMainTick(); + networkInterface().processChannels(&DbmgrInterface::messageHandlers); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::handleCheckStatusTick() +{ + // 鶪ʧ̣һʱ֮Ȼ޷֣Ҫݿentitylog + if (loseBaseappts_.size() > 0) + { + std::map::iterator iter = loseBaseappts_.begin(); + for (; iter != loseBaseappts_.end();) + { + if (timestamp() > iter->second) + { + Components::ComponentInfos* cinfo = Components::getSingleton().findComponent(iter->first); + if (!cinfo) + { + ENGINE_COMPONENT_INFO& dbcfg = g_kbeSrvConfig.getDBMgr(); + std::vector::iterator dbinfo_iter = dbcfg.dbInterfaceInfos.begin(); + for (; dbinfo_iter != dbcfg.dbInterfaceInfos.end(); ++dbinfo_iter) + { + std::string dbInterfaceName = dbinfo_iter->name; + + DBUtil::pThreadPool(dbInterfaceName)-> + addTask(new DBTaskEraseBaseappEntityLog(iter->first)); + } + } + + loseBaseappts_.erase(iter++); + } + else + { + ++iter; + } + } + } +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::initializeBegin() +{ + idServer_.set_range_step(g_kbeSrvConfig.getDBMgr().ids_increasing_range); + return true; +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::inInitialize() +{ + // ʼչģ + // assets/scripts/ + if (!PythonApp::inInitialize()) + return false; + + std::vector scriptBaseTypes; + if(!EntityDef::initialize(scriptBaseTypes, componentType_)){ + return false; + } + + return true; +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::initializeEnd() +{ + PythonApp::initializeEnd(); + + // һtimer ÿһЩ״̬ + loopCheckTimerHandle_ = this->dispatcher().addTimer(1000000, this, + reinterpret_cast(TIMEOUT_CHECK_STATUS)); + + mainProcessTimer_ = this->dispatcher().addTimer(1000000 / 50, this, + reinterpret_cast(TIMEOUT_TICK)); + + // globalData, baseAppData, cellAppData֧ + pGlobalData_ = new GlobalDataServer(GlobalDataServer::GLOBAL_DATA); + pBaseAppData_ = new GlobalDataServer(GlobalDataServer::BASEAPP_DATA); + pCellAppData_ = new GlobalDataServer(GlobalDataServer::CELLAPP_DATA); + pGlobalData_->addConcernComponentType(CELLAPP_TYPE); + pGlobalData_->addConcernComponentType(BASEAPP_TYPE); + pBaseAppData_->addConcernComponentType(BASEAPP_TYPE); + pCellAppData_->addConcernComponentType(CELLAPP_TYPE); + + INFO_MSG(fmt::format("Dbmgr::initializeEnd: digest({})\n", + EntityDef::md5().getDigestStr())); + + SCOPED_PROFILE(SCRIPTCALL_PROFILE); + + // нű + PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), + const_cast("onDBMgrReady"), + const_cast("")); + + if(pyResult != NULL) + Py_DECREF(pyResult); + else + SCRIPT_ERROR_CHECK(); + + pTelnetServer_ = new TelnetServer(&this->dispatcher(), &this->networkInterface()); + pTelnetServer_->pScript(&this->getScript()); + + bool ret = pTelnetServer_->start(g_kbeSrvConfig.getDBMgr().telnet_passwd, + g_kbeSrvConfig.getDBMgr().telnet_deflayer, + g_kbeSrvConfig.getDBMgr().telnet_port); + + Components::getSingleton().extraData4(pTelnetServer_->port()); + + return ret && initInterfacesHandler() && initDB(); +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::installPyModules() +{ + return PythonApp::installPyModules() && script::entitydef::installModule("EntityDef"); +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::uninstallPyModules() +{ + return script::entitydef::uninstallModule() && PythonApp::uninstallPyModules(); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onInstallPyModules() +{ + PyObject * module = getScript().getModule(); + + for (int i = 0; i < SERVER_ERR_MAX; i++) + { + if(PyModule_AddIntConstant(module, SERVER_ERR_STR[i], i)) + { + ERROR_MSG( fmt::format("Dbmgr::onInstallPyModules: Unable to set KBEngine.{}.\n", SERVER_ERR_STR[i])); + } + } + + APPEND_SCRIPT_MODULE_METHOD(module, executeRawDatabaseCommand, __py_executeRawDatabaseCommand, METH_VARARGS, 0); +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::initInterfacesHandler() +{ + std::vector< Network::Address > addresses = g_kbeSrvConfig.interfacesAddrs(); + std::string type = addresses.size() == 0 ? "dbmgr" : "interfaces"; + + if (type == "dbmgr") + { + InterfacesHandler* pInterfacesHandler = InterfacesHandlerFactory::create(type); + + INFO_MSG(fmt::format("Dbmgr::initInterfacesHandler: interfaces addr({}), accountType:({}), chargeType:({}).\n", + Network::Address::NONE.c_str(), + type, + type)); + + if (!pInterfacesHandler->initialize()) + return false; + + pInterfacesHandlers_.push_back(pInterfacesHandler); + } + else + { + std::vector< Network::Address >::iterator iter = addresses.begin(); + for (; iter != addresses.end(); ++iter) + { + InterfacesHandler* pInterfacesHandler = InterfacesHandlerFactory::create(type); + + const Network::Address& addr = (*iter); + + INFO_MSG(fmt::format("Dbmgr::initInterfacesHandler: interfaces addr({}), accountType:({}), chargeType:({}).\n", + addr.c_str(), + type, + type)); + + ((InterfacesHandler_Interfaces*)pInterfacesHandler)->setAddr(addr); + + if (!pInterfacesHandler->initialize()) + return false; + + pInterfacesHandlers_.push_back(pInterfacesHandler); + } + } + + return pInterfacesHandlers_.size() > 0; +} + +//------------------------------------------------------------------------------------- +bool Dbmgr::initDB() +{ + ScriptDefModule* pModule = EntityDef::findScriptModule(DBUtil::accountScriptName()); + if(pModule == NULL) + { + ERROR_MSG(fmt::format("Dbmgr::initDB(): not found account script[{}]!\n", + DBUtil::accountScriptName())); + + return false; + } + + ENGINE_COMPONENT_INFO& dbcfg = g_kbeSrvConfig.getDBMgr(); + if (dbcfg.dbInterfaceInfos.size() == 0) + { + ERROR_MSG(fmt::format("DBUtil::initialize: not found dbInterface! (kbengine[_defs].xml->dbmgr->databaseInterfaces)\n")); + return false; + } + + if (!DBUtil::initialize()) + { + ERROR_MSG("Dbmgr::initDB(): can't initialize dbInterface!\n"); + return false; + } + + bool hasDefaultInterface = false; + + std::vector::iterator dbinfo_iter = dbcfg.dbInterfaceInfos.begin(); + for (; dbinfo_iter != dbcfg.dbInterfaceInfos.end(); ++dbinfo_iter) + { + Buffered_DBTasks buffered_DBTasks; + bufferedDBTasksMaps_.insert(std::make_pair((*dbinfo_iter).name, buffered_DBTasks)); + BUFFERED_DBTASKS_MAP::iterator buffered_DBTasks_iter = bufferedDBTasksMaps_.find((*dbinfo_iter).name); + buffered_DBTasks_iter->second.dbInterfaceName((*dbinfo_iter).name); + } + + for (dbinfo_iter = dbcfg.dbInterfaceInfos.begin(); dbinfo_iter != dbcfg.dbInterfaceInfos.end(); ++dbinfo_iter) + { + DBInterface* pDBInterface = DBUtil::createInterface((*dbinfo_iter).name); + if(pDBInterface == NULL) + { + ERROR_MSG("Dbmgr::initDB(): can't create dbInterface!\n"); + return false; + } + + bool ret = DBUtil::initInterface(pDBInterface); + pDBInterface->detach(); + SAFE_RELEASE(pDBInterface); + + if(!ret) + return false; + + if (std::string("default") == (*dbinfo_iter).name) + hasDefaultInterface = true; + } + + if (!hasDefaultInterface) + { + ERROR_MSG("Dbmgr::initDB(): \"default\" dbInterface was not found! (kbengine[_defs].xml->dbmgr->databaseInterfaces)\n"); + return false; + } + + if(pUpdateDBServerLogHandler_ == NULL) + pUpdateDBServerLogHandler_ = new UpdateDBServerLogHandler(); + + return true; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::finalise() +{ + SAFE_RELEASE(pUpdateDBServerLogHandler_); + + SAFE_RELEASE(pGlobalData_); + SAFE_RELEASE(pBaseAppData_); + SAFE_RELEASE(pCellAppData_); + + if (pTelnetServer_) + { + pTelnetServer_->stop(); + SAFE_RELEASE(pTelnetServer_); + } + + DBUtil::finalise(); + PythonApp::finalise(); +} + +//------------------------------------------------------------------------------------- +InterfacesHandler* Dbmgr::findBestInterfacesHandler() +{ + if (pInterfacesHandlers_.size() == 0) + return NULL; + + static size_t i = 0; + + return pInterfacesHandlers_[i++ % pInterfacesHandlers_.size()]; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onReqAllocEntityID(Network::Channel* pChannel, COMPONENT_ORDER componentType, COMPONENT_ID componentID) +{ + KBEngine::COMPONENT_TYPE ct = static_cast(componentType); + + // ȡһid IDClient + std::pair idRange = idServer_.allocRange(); + Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT); + + if(ct == BASEAPP_TYPE) + (*pBundle).newMessage(BaseappInterface::onReqAllocEntityID); + else + (*pBundle).newMessage(CellappInterface::onReqAllocEntityID); + + (*pBundle) << idRange.first; + (*pBundle) << idRange.second; + pChannel->send(pBundle); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onRegisterNewApp(Network::Channel* pChannel, int32 uid, std::string& username, + COMPONENT_TYPE componentType, COMPONENT_ID componentID, COMPONENT_ORDER globalorderID, COMPONENT_ORDER grouporderID, + uint32 intaddr, uint16 intport, uint32 extaddr, uint16 extport, std::string& extaddrEx) +{ + if(pChannel->isExternal()) + return; + + ServerApp::onRegisterNewApp(pChannel, uid, username, componentType, componentID, globalorderID, grouporderID, + intaddr, intport, extaddr, extport, extaddrEx); + + KBEngine::COMPONENT_TYPE tcomponentType = (KBEngine::COMPONENT_TYPE)componentType; + + COMPONENT_ORDER startGroupOrder = 1; + COMPONENT_ORDER startGlobalOrder = Components::getSingleton().getGlobalOrderLog()[getUserUID()]; + + if(grouporderID > 0) + startGroupOrder = grouporderID; + + if(globalorderID > 0) + startGlobalOrder = globalorderID; + + if(pSyncAppDatasHandler_ == NULL) + pSyncAppDatasHandler_ = new SyncAppDatasHandler(this->networkInterface()); + + // һ: + // ӵdbmgrҪȴappʼϢ + // 磺ʼentityIDԼapp˳ϢǷһbaseapp + if(tcomponentType == BASEAPP_TYPE || + tcomponentType == CELLAPP_TYPE || + tcomponentType == LOGINAPP_TYPE) + { + switch(tcomponentType) + { + case BASEAPP_TYPE: + { + if(grouporderID <= 0) + startGroupOrder = Components::getSingleton().getBaseappGroupOrderLog()[getUserUID()]; + } + break; + case CELLAPP_TYPE: + { + if(grouporderID <= 0) + startGroupOrder = Components::getSingleton().getCellappGroupOrderLog()[getUserUID()]; + } + break; + case LOGINAPP_TYPE: + if(grouporderID <= 0) + startGroupOrder = Components::getSingleton().getLoginappGroupOrderLog()[getUserUID()]; + + break; + default: + break; + } + } + + pSyncAppDatasHandler_->pushApp(componentID, startGroupOrder, startGlobalOrder); + + // baseappcellappԼעᵽbaseappcellapp + if(tcomponentType == BASEAPP_TYPE || + tcomponentType == CELLAPP_TYPE) + { + KBEngine::COMPONENT_TYPE broadcastCpTypes[2] = {BASEAPP_TYPE, CELLAPP_TYPE}; + for(int idx = 0; idx < 2; ++idx) + { + Components::COMPONENTS& cts = Components::getSingleton().getComponents(broadcastCpTypes[idx]); + Components::COMPONENTS::iterator fiter = cts.begin(); + for(; fiter != cts.end(); ++fiter) + { + if((*fiter).cid == componentID) + continue; + + Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT); + ENTITTAPP_COMMON_NETWORK_MESSAGE(broadcastCpTypes[idx], (*pBundle), onGetEntityAppFromDbmgr); + + if(tcomponentType == BASEAPP_TYPE) + { + BaseappInterface::onGetEntityAppFromDbmgrArgs11::staticAddToBundle((*pBundle), + uid, username, componentType, componentID, startGlobalOrder, startGroupOrder, + intaddr, intport, extaddr, extport, g_kbeSrvConfig.getConfig().externalAddress); + } + else + { + CellappInterface::onGetEntityAppFromDbmgrArgs11::staticAddToBundle((*pBundle), + uid, username, componentType, componentID, startGlobalOrder, startGroupOrder, + intaddr, intport, extaddr, extport, g_kbeSrvConfig.getConfig().externalAddress); + } + + KBE_ASSERT((*fiter).pChannel != NULL); + (*fiter).pChannel->send(pBundle); + } + } + } +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onGlobalDataClientLogon(Network::Channel* pChannel, COMPONENT_TYPE componentType) +{ + if(BASEAPP_TYPE == componentType) + { + pBaseAppData_->onGlobalDataClientLogon(pChannel, componentType); + pGlobalData_->onGlobalDataClientLogon(pChannel, componentType); + } + else if(CELLAPP_TYPE == componentType) + { + pGlobalData_->onGlobalDataClientLogon(pChannel, componentType); + pCellAppData_->onGlobalDataClientLogon(pChannel, componentType); + } + else + { + ERROR_MSG(fmt::format("Dbmgr::onGlobalDataClientLogon: nonsupport {}!\n", + COMPONENT_NAME_EX(componentType))); + } +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onBroadcastGlobalDataChanged(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + uint8 dataType; + std::string key, value; + bool isDelete; + COMPONENT_TYPE componentType; + + s >> dataType; + s >> isDelete; + + s.readBlob(key); + + if(!isDelete) + { + s.readBlob(value); + } + + s >> componentType; + + switch(dataType) + { + case GlobalDataServer::GLOBAL_DATA: + if(isDelete) + pGlobalData_->del(pChannel, componentType, key); + else + pGlobalData_->write(pChannel, componentType, key, value); + break; + case GlobalDataServer::BASEAPP_DATA: + if(isDelete) + pBaseAppData_->del(pChannel, componentType, key); + else + pBaseAppData_->write(pChannel, componentType, key, value); + break; + case GlobalDataServer::CELLAPP_DATA: + if(isDelete) + pCellAppData_->del(pChannel, componentType, key); + else + pCellAppData_->write(pChannel, componentType, key, value); + break; + default: + KBE_ASSERT(false && "dataType error!\n"); + break; + }; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::reqCreateAccount(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + std::string registerName, password, datas; + uint8 uatype = 0; + + s >> registerName >> password >> uatype; + s.readBlob(datas); + + if(registerName.size() == 0) + { + ERROR_MSG("Dbmgr::reqCreateAccount: registerName is empty.\n"); + return; + } + + findBestInterfacesHandler()->createAccount(pChannel, registerName, password, datas, ACCOUNT_TYPE(uatype)); + numCreatedAccount_++; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onCreateAccountCBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + findBestInterfacesHandler()->onCreateAccountCB(s); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onAccountLogin(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + std::string loginName, password, datas; + s >> loginName >> password; + s.readBlob(datas); + + if(loginName.size() == 0) + { + ERROR_MSG("Dbmgr::onAccountLogin: loginName is empty.\n"); + return; + } + + findBestInterfacesHandler()->loginAccount(pChannel, loginName, password, datas); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onLoginAccountCBBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + findBestInterfacesHandler()->onLoginAccountCB(s); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::queryAccount(Network::Channel* pChannel, + std::string& accountName, + std::string& password, + bool needCheckPassword, + COMPONENT_ID componentID, + ENTITY_ID entityID, + DBID entityDBID, + uint32 ip, + uint16 port) +{ + if(accountName.size() == 0) + { + ERROR_MSG("Dbmgr::queryAccount: accountName is empty.\n"); + return; + } + + Buffered_DBTasks* pBuffered_DBTasks = + findBufferedDBTask(Dbmgr::getSingleton().selectAccountDBInterfaceName(accountName)); + + if (!pBuffered_DBTasks) + { + ERROR_MSG(fmt::format("Dbmgr::queryAccount: not found dbInterface({})!\n", + Dbmgr::getSingleton().selectAccountDBInterfaceName(accountName))); + return; + } + + pBuffered_DBTasks->addTask(new DBTaskQueryAccount(pChannel->addr(), accountName, password, needCheckPassword, + componentID, entityID, entityDBID, ip, port)); + + numQueryEntity_++; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onAccountOnline(Network::Channel* pChannel, + std::string& accountName, + COMPONENT_ID componentID, + ENTITY_ID entityID) +{ + // bufferedDBTasks_.addTask(new DBTaskAccountOnline(pChannel->addr(), + // accountName, componentID, entityID)); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onEntityOffline(Network::Channel* pChannel, DBID dbid, ENTITY_SCRIPT_UID sid, uint16 dbInterfaceIndex) +{ + Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)); + if (!pBuffered_DBTasks) + { + ERROR_MSG(fmt::format("Dbmgr::onEntityOffline: not found dbInterfaceIndex({})!\n", dbInterfaceIndex)); + return; + } + + pBuffered_DBTasks->addTask(new DBTaskEntityOffline(pChannel->addr(), dbid, sid)); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::executeRawDatabaseCommand(Network::Channel* pChannel, + KBEngine::MemoryStream& s) +{ + ENTITY_ID entityID = -1; + s >> entityID; + + uint16 dbInterfaceIndex = 0; + s >> dbInterfaceIndex; + + std::string dbInterfaceName = g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex); + if (dbInterfaceName.size() == 0) + { + ERROR_MSG(fmt::format("Dbmgr::executeRawDatabaseCommand: not found dbInterface({})!\n", dbInterfaceName)); + s.done(); + return; + } + + if (entityID == -1) + { + thread::ThreadPool* pThreadPool = DBUtil::pThreadPool(dbInterfaceName); + if (!pThreadPool) + { + ERROR_MSG(fmt::format("Dbmgr::executeRawDatabaseCommand: not found pThreadPool(dbInterface={})!\n", dbInterfaceName)); + s.done(); + return; + } + + pThreadPool->addTask(new DBTaskExecuteRawDatabaseCommand(pChannel ? pChannel->addr() : Network::Address::NONE, s)); + } + else + { + Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(dbInterfaceName); + if (!pBuffered_DBTasks) + { + ERROR_MSG(fmt::format("Dbmgr::executeRawDatabaseCommand: not found pBuffered_DBTasks(dbInterface={})!\n", dbInterfaceName)); + s.done(); + return; + } + + pBuffered_DBTasks->addTask(new DBTaskExecuteRawDatabaseCommandByEntity(pChannel ? pChannel->addr() : Network::Address::NONE, s, entityID)); + } + + s.done(); + + ++numExecuteRawDatabaseCommand_; +} + +//------------------------------------------------------------------------------------- +PyObject* Dbmgr::__py_executeRawDatabaseCommand(PyObject* self, PyObject* args) +{ + int argCount = (int)PyTuple_Size(args); + PyObject* pycallback = NULL; + PyObject* pyDBInterfaceName = NULL; + int ret = -1; + ENTITY_ID eid = -1; + + char* data = NULL; + Py_ssize_t size; + + if (argCount == 4) + ret = PyArg_ParseTuple(args, "s#|O|i|O", &data, &size, &pycallback, &eid, &pyDBInterfaceName); + else if (argCount == 3) + ret = PyArg_ParseTuple(args, "s#|O|i", &data, &size, &pycallback, &eid); + else if (argCount == 2) + ret = PyArg_ParseTuple(args, "s#|O", &data, &size, &pycallback); + else if (argCount == 1) + ret = PyArg_ParseTuple(args, "s#", &data, &size); + + if (ret == -1) + { + PyErr_Format(PyExc_TypeError, "KBEngine::executeRawDatabaseCommand: args error!"); + PyErr_PrintEx(0); + S_Return; + } + + std::string dbInterfaceName = "default"; + if (pyDBInterfaceName) + { + dbInterfaceName = PyUnicode_AsUTF8AndSize(pyDBInterfaceName, NULL); + + if (!g_kbeSrvConfig.dbInterface(dbInterfaceName)) + { + PyErr_Format(PyExc_TypeError, "KBEngine::executeRawDatabaseCommand: args4, incorrect dbInterfaceName(%s)!", + dbInterfaceName.c_str()); + + PyErr_PrintEx(0); + S_Return; + } + } + + Dbmgr::getSingleton().executeRawDatabaseCommand(data, (uint32)size, pycallback, eid, dbInterfaceName); + S_Return; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::executeRawDatabaseCommand(const char* datas, uint32 size, PyObject* pycallback, ENTITY_ID eid, const std::string& dbInterfaceName) +{ + if (datas == NULL) + { + ERROR_MSG("KBEngine::executeRawDatabaseCommand: execute error!\n"); + return; + } + + int dbInterfaceIndex = g_kbeSrvConfig.dbInterfaceName2dbInterfaceIndex(dbInterfaceName); + if (dbInterfaceIndex < 0) + { + ERROR_MSG(fmt::format("KBEngine::executeRawDatabaseCommand: not found dbInterface({})!\n", + dbInterfaceName)); + + return; + } + + //INFO_MSG(fmt::format("KBEngine::executeRawDatabaseCommand{}:{}.\n", (eid > 0 ? fmt::format("(entityID={})", eid) : ""), datas)); + + MemoryStream* pMemoryStream = MemoryStream::createPoolObject(OBJECTPOOL_POINT); + (*pMemoryStream) << eid; + (*pMemoryStream) << (uint16)dbInterfaceIndex; + (*pMemoryStream) << componentID_ << componentType_; + + CALLBACK_ID callbackID = 0; + + if (pycallback && PyCallable_Check(pycallback)) + callbackID = callbackMgr().save(pycallback); + + (*pMemoryStream) << callbackID; + (*pMemoryStream) << size; + (*pMemoryStream).append(datas, size); + executeRawDatabaseCommand(NULL, *pMemoryStream); + MemoryStream::reclaimPoolObject(pMemoryStream); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onExecuteRawDatabaseCommandCB(KBEngine::MemoryStream& s) +{ + std::string err; + CALLBACK_ID callbackID = 0; + uint32 nrows = 0; + uint32 nfields = 0; + uint64 affectedRows = 0; + uint64 lastInsertID = 0; + + PyObject* pResultSet = NULL; + PyObject* pAffectedRows = NULL; + PyObject* pLastInsertID = NULL; + PyObject* pErrorMsg = NULL; + + s >> callbackID; + s >> err; + + if (err.size() <= 0) + { + s >> nfields; + + pErrorMsg = Py_None; + Py_INCREF(pErrorMsg); + + if (nfields > 0) + { + pAffectedRows = Py_None; + Py_INCREF(pAffectedRows); + + pLastInsertID = Py_None; + Py_INCREF(pLastInsertID); + + s >> nrows; + + pResultSet = PyList_New(nrows); + for (uint32 i = 0; i < nrows; ++i) + { + PyObject* pRow = PyList_New(nfields); + for (uint32 j = 0; j < nfields; ++j) + { + std::string cell; + s.readBlob(cell); + + PyObject* pCell = NULL; + + if (cell == "KBE_QUERY_DB_NULL") + { + Py_INCREF(Py_None); + pCell = Py_None; + } + else + { + pCell = PyBytes_FromStringAndSize(cell.data(), cell.length()); + } + + PyList_SET_ITEM(pRow, j, pCell); + } + + PyList_SET_ITEM(pResultSet, i, pRow); + } + } + else + { + pResultSet = Py_None; + Py_INCREF(pResultSet); + + pErrorMsg = Py_None; + Py_INCREF(pErrorMsg); + + s >> affectedRows; + + pAffectedRows = PyLong_FromUnsignedLongLong(affectedRows); + + s >> lastInsertID; + pLastInsertID = PyLong_FromUnsignedLongLong(lastInsertID); + } + } + else + { + pResultSet = Py_None; + Py_INCREF(pResultSet); + + pErrorMsg = PyUnicode_FromString(err.c_str()); + + pAffectedRows = Py_None; + Py_INCREF(pAffectedRows); + + pLastInsertID = Py_None; + Py_INCREF(pLastInsertID); + } + + s.done(); + + //DEBUG_MSG(fmt::format("Cellapp::onExecuteRawDatabaseCommandCB: nrows={}, nfields={}, err={}.\n", + // nrows, nfields, err.c_str())); + + if (callbackID > 0) + { + SCOPED_PROFILE(SCRIPTCALL_PROFILE); + + PyObjectPtr pyfunc = pyCallbackMgr_.take(callbackID); + if (pyfunc != NULL) + { + PyObject* pyResult = PyObject_CallFunction(pyfunc.get(), + const_cast("OOOO"), + pResultSet, pAffectedRows, pLastInsertID, pErrorMsg); + + if (pyResult != NULL) + Py_DECREF(pyResult); + else + SCRIPT_ERROR_CHECK(); + } + else + { + ERROR_MSG(fmt::format("Cellapp::onExecuteRawDatabaseCommandCB: not found callback:{}.\n", + callbackID)); + } + } + + Py_XDECREF(pResultSet); + Py_XDECREF(pAffectedRows); + Py_XDECREF(pLastInsertID); + Py_XDECREF(pErrorMsg); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::writeEntity(Network::Channel* pChannel, + KBEngine::MemoryStream& s) +{ + ENTITY_ID eid; + DBID entityDBID; + COMPONENT_ID componentID; + uint16 dbInterfaceIndex; + + s >> componentID >> eid >> entityDBID >> dbInterfaceIndex; + + Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)); + if (!pBuffered_DBTasks) + { + ERROR_MSG(fmt::format("Dbmgr::writeEntity: not found dbInterfaceIndex({})!\n", dbInterfaceIndex)); + s.done(); + return; + } + + pBuffered_DBTasks->addTask(new DBTaskWriteEntity(pChannel->addr(), componentID, eid, entityDBID, s)); + s.done(); + + ++numWrittenEntity_; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::removeEntity(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + ENTITY_ID eid; + DBID entityDBID; + COMPONENT_ID componentID; + uint16 dbInterfaceIndex; + + s >> dbInterfaceIndex >> componentID >> eid >> entityDBID; + KBE_ASSERT(entityDBID > 0); + + Buffered_DBTasks* pBuffered_DBTasks = findBufferedDBTask(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)); + if (!pBuffered_DBTasks) + { + ERROR_MSG(fmt::format("Dbmgr::removeEntity: not found dbInterfaceIndex({})!\n", dbInterfaceIndex)); + s.done(); + return; + } + + pBuffered_DBTasks->addTask(new DBTaskRemoveEntity(pChannel->addr(), + componentID, eid, entityDBID, s)); + + s.done(); + + ++numRemovedEntity_; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::entityAutoLoad(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + COMPONENT_ID componentID; + ENTITY_SCRIPT_UID entityType; + ENTITY_ID start; + ENTITY_ID end; + uint16 dbInterfaceIndex = 0; + + s >> dbInterfaceIndex >> componentID >> entityType >> start >> end; + + DBUtil::pThreadPool(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex))-> + addTask(new DBTaskEntityAutoLoad(pChannel->addr(), componentID, entityType, start, end)); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::deleteEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + COMPONENT_ID componentID; + ENTITY_SCRIPT_UID sid; + CALLBACK_ID callbackID = 0; + DBID entityDBID; + uint16 dbInterfaceIndex = 0; + + s >> dbInterfaceIndex >> componentID >> entityDBID >> callbackID >> sid; + KBE_ASSERT(entityDBID > 0); + + DBUtil::pThreadPool(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex))-> + addTask(new DBTaskDeleteEntityByDBID(pChannel->addr(), componentID, entityDBID, callbackID, sid)); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::lookUpEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + COMPONENT_ID componentID; + ENTITY_SCRIPT_UID sid; + CALLBACK_ID callbackID = 0; + DBID entityDBID; + uint16 dbInterfaceIndex = 0; + + s >> dbInterfaceIndex >> componentID >> entityDBID >> callbackID >> sid; + KBE_ASSERT(entityDBID > 0); + + DBUtil::pThreadPool(g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex))-> + addTask(new DBTaskLookUpEntityByDBID(pChannel->addr(), componentID, entityDBID, callbackID, sid)); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::queryEntity(Network::Channel* pChannel, uint16 dbInterfaceIndex, COMPONENT_ID componentID, int8 queryMode, DBID dbid, + std::string& entityType, CALLBACK_ID callbackID, ENTITY_ID entityID) +{ + bufferedDBTasksMaps_[g_kbeSrvConfig.dbInterfaceIndex2dbInterfaceName(dbInterfaceIndex)]. + addTask(new DBTaskQueryEntity(pChannel->addr(), queryMode, entityType, dbid, componentID, callbackID, entityID)); + + numQueryEntity_++; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::syncEntityStreamTemplate(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + int rpos = s.rpos(); + EntityTables::ENTITY_TABLES_MAP::iterator iter = EntityTables::sEntityTables.begin(); + for (; iter != EntityTables::sEntityTables.end(); ++iter) + { + KBEAccountTable* pTable = + static_cast(iter->second.findKBETable(KBE_TABLE_PERFIX "_accountinfos")); + + KBE_ASSERT(pTable); + + s.rpos(rpos); + pTable->accountDefMemoryStream(s); + } + + s.done(); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::charge(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + findBestInterfacesHandler()->charge(pChannel, s); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onChargeCB(Network::Channel* pChannel, KBEngine::MemoryStream& s) +{ + findBestInterfacesHandler()->onChargeCB(s); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::eraseClientReq(Network::Channel* pChannel, std::string& logkey) +{ + std::vector::iterator iter = pInterfacesHandlers_.begin(); + for(; iter != pInterfacesHandlers_.end(); ++iter) + (*iter)->eraseClientReq(pChannel, logkey); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::accountActivate(Network::Channel* pChannel, std::string& scode) +{ + INFO_MSG(fmt::format("Dbmgr::accountActivate: code={}.\n", scode)); + findBestInterfacesHandler()->accountActivate(pChannel, scode); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::accountReqResetPassword(Network::Channel* pChannel, std::string& accountName) +{ + INFO_MSG(fmt::format("Dbmgr::accountReqResetPassword: accountName={}.\n", accountName)); + findBestInterfacesHandler()->accountReqResetPassword(pChannel, accountName); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::accountResetPassword(Network::Channel* pChannel, std::string& accountName, std::string& newpassword, std::string& code) +{ + INFO_MSG(fmt::format("Dbmgr::accountResetPassword: accountName={}.\n", accountName)); + findBestInterfacesHandler()->accountResetPassword(pChannel, accountName, newpassword, code); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::accountReqBindMail(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, + std::string& password, std::string& email) +{ + INFO_MSG(fmt::format("Dbmgr::accountReqBindMail: accountName={}, email={}.\n", accountName, email)); + findBestInterfacesHandler()->accountReqBindMail(pChannel, entityID, accountName, password, email); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::accountBindMail(Network::Channel* pChannel, std::string& username, std::string& scode) +{ + INFO_MSG(fmt::format("Dbmgr::accountBindMail: username={}, scode={}.\n", username, scode)); + findBestInterfacesHandler()->accountBindMail(pChannel, username, scode); +} + +//------------------------------------------------------------------------------------- +void Dbmgr::accountNewPassword(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, + std::string& password, std::string& newpassword) +{ + INFO_MSG(fmt::format("Dbmgr::accountNewPassword: accountName={}.\n", accountName)); + findBestInterfacesHandler()->accountNewPassword(pChannel, entityID, accountName, password, newpassword); +} + +//------------------------------------------------------------------------------------- +std::string Dbmgr::selectAccountDBInterfaceName(const std::string& name) +{ + std::string dbInterfaceName = "default"; + + // ɽű + SCOPED_PROFILE(SCRIPTCALL_PROFILE); + PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), + const_cast("onSelectAccountDBInterface"), + const_cast("s"), + name.c_str()); + + if (pyResult != NULL) + { + dbInterfaceName = PyUnicode_AsUTF8AndSize(pyResult, NULL); + Py_DECREF(pyResult); + } + else + { + SCRIPT_ERROR_CHECK(); + } + + if (dbInterfaceName == "" || g_kbeSrvConfig.dbInterface(dbInterfaceName) == NULL) + { + ERROR_MSG(fmt::format("Dbmgr::selectAccountDBInterfaceName: not found dbInterface({}), accountName={}.\n", dbInterfaceName, name)); + return "default"; + } + + return dbInterfaceName; +} + +//------------------------------------------------------------------------------------- +void Dbmgr::onChannelDeregister(Network::Channel * pChannel) +{ + // app + if (pChannel->isInternal()) + { + Components::ComponentInfos* cinfo = Components::getSingleton().findComponent(pChannel); + if (cinfo) + { + if (cinfo->componentType == BASEAPP_TYPE) + { + loseBaseappts_[cinfo->cid] = timestamp() + uint64(60 * stampsPerSecond()); + WARNING_MSG(fmt::format("Dbmgr::onChannelDeregister(): If the process cannot be resumed, the entitylog(baseapp={}) will be cleaned up after 60 seconds!\n", cinfo->cid)); + } + } + } + + ServerApp::onChannelDeregister(pChannel); +} + +//------------------------------------------------------------------------------------- +} diff --git a/kbe/src/server/dbmgr/dbmgr.h b/kbe/src/server/dbmgr/dbmgr.h index 1194656df2..4128c2d671 100644 --- a/kbe/src/server/dbmgr/dbmgr.h +++ b/kbe/src/server/dbmgr/dbmgr.h @@ -1,276 +1,279 @@ -// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com - -#ifndef KBE_DBMGR_H -#define KBE_DBMGR_H - -#include "db_interface/db_threadpool.h" -#include "buffered_dbtasks.h" -#include "server/kbemain.h" -#include "pyscript/script.h" -#include "pyscript/pyobject_pointer.h" -#include "entitydef/entitydef.h" -#include "server/python_app.h" -#include "server/idallocate.h" -#include "server/serverconfig.h" -#include "server/globaldata_client.h" -#include "server/globaldata_server.h" -#include "server/callbackmgr.h" -#include "common/timer.h" -#include "network/endpoint.h" -#include "resmgr/resmgr.h" -#include "thread/threadpool.h" - - -namespace KBEngine{ - -class DBInterface; -class TelnetServer; -class InterfacesHandler; -class SyncAppDatasHandler; -class UpdateDBServerLogHandler; - -class Dbmgr : public PythonApp, - public Singleton -{ -public: - enum TimeOutType - { - TIMEOUT_TICK = TIMEOUT_PYTHONAPP_MAX + 1, - TIMEOUT_CHECK_STATUS - }; - - Dbmgr(Network::EventDispatcher& dispatcher, - Network::NetworkInterface& ninterface, - COMPONENT_TYPE componentType, - COMPONENT_ID componentID); - - ~Dbmgr(); - - bool run(); - - void handleTimeout(TimerHandle handle, void * arg); - void handleMainTick(); - void handleCheckStatusTick(); - - /* ʼؽӿ */ - bool initializeBegin(); - bool inInitialize(); - bool initializeEnd(); - void finalise(); - void onInstallPyModules(); - - bool initInterfacesHandler(); - - bool initDB(); - - virtual ShutdownHandler::CAN_SHUTDOWN_STATE canShutdown(); - - virtual void onShutdownBegin(); - virtual void onShutdownEnd(); - - /** ȡIDָ */ - IDServer& idServer(void){ return idServer_; } - - /** ӿ - һENTITY_ID - */ - void onReqAllocEntityID(Network::Channel* pChannel, COMPONENT_ORDER componentType, COMPONENT_ID componentID); - - /* ӿ - עһ¼baseappcellappdbmgr - ͨһµappˣ ҪijЩעԼ - */ - virtual void onRegisterNewApp(Network::Channel* pChannel, - int32 uid, - std::string& username, - COMPONENT_TYPE componentType, COMPONENT_ID componentID, COMPONENT_ORDER globalorderID, COMPONENT_ORDER grouporderID, - uint32 intaddr, uint16 intport, uint32 extaddr, uint16 extport, std::string& extaddrEx); - - - /** ӿ - dbmgr㲥globalݵĸı - */ - void onGlobalDataClientLogon(Network::Channel* pChannel, COMPONENT_TYPE componentType); - void onBroadcastGlobalDataChanged(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - 󴴽˺ - */ - void reqCreateAccount(Network::Channel* pChannel, KBEngine::MemoryStream& s); - void onCreateAccountCBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - ͻ - */ - void eraseClientReq(Network::Channel* pChannel, std::string& logkey); - - /** ӿ - һû¼ ҪϷ - */ - void onAccountLogin(Network::Channel* pChannel, KBEngine::MemoryStream& s); - void onLoginAccountCBBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - baseappѯaccountϢ - */ - void queryAccount(Network::Channel* pChannel, std::string& accountName, std::string& password, bool needCheckPassword, - COMPONENT_ID componentID, ENTITY_ID entityID, DBID entityDBID, uint32 ip, uint16 port); - - /** ӿ - ʵԶع - */ - void entityAutoLoad(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - ˺Ŵbaseapp - */ - void onAccountOnline(Network::Channel* pChannel, std::string& accountName, - COMPONENT_ID componentID, ENTITY_ID entityID); - - /** ӿ - entity-baseapp - */ - void onEntityOffline(Network::Channel* pChannel, DBID dbid, ENTITY_SCRIPT_UID sid, uint16 dbInterfaceIndex); - - /** ӿ - ִݿѯ - */ - void executeRawDatabaseCommand(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - ijentity浵 - */ - void writeEntity(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - ɾijentityĴ浵 - */ - void removeEntity(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - ͨdbidݿɾһʵĻص - */ - void deleteEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - ͨdbidѯһʵǷݿ - */ - void lookUpEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - dbȡentity - */ - void queryEntity(Network::Channel* pChannel, uint16 dbInterfaceIndex, COMPONENT_ID componentID, int8 queryMode, DBID dbid, - std::string& entityType, CALLBACK_ID callbackID, ENTITY_ID entityID); - - /** ӿ - ͬentityģ - */ - void syncEntityStreamTemplate(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - virtual bool initializeWatcher(); - - /** ӿ - ֵ - */ - void charge(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - /** ӿ - ֵص - */ - void onChargeCB(Network::Channel* pChannel, KBEngine::MemoryStream& s); - - - /** ӿ - ص - */ - void accountActivate(Network::Channel* pChannel, std::string& scode); - - /** ӿ - ˺ - */ - void accountReqResetPassword(Network::Channel* pChannel, std::string& accountName); - void accountResetPassword(Network::Channel* pChannel, std::string& accountName, - std::string& newpassword, std::string& code); - - /** ӿ - ˺Ű - */ - void accountReqBindMail(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, - std::string& password, std::string& email); - void accountBindMail(Network::Channel* pChannel, std::string& username, std::string& scode); - - /** ӿ - ˺޸ - */ - void accountNewPassword(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, - std::string& password, std::string& newpassword); - - SyncAppDatasHandler* pSyncAppDatasHandler() const { return pSyncAppDatasHandler_; } - void pSyncAppDatasHandler(SyncAppDatasHandler* p){ pSyncAppDatasHandler_ = p; } - - std::string selectAccountDBInterfaceName(const std::string& name); - - Buffered_DBTasks* findBufferedDBTask(const std::string& dbInterfaceName) - { - BUFFERED_DBTASKS_MAP::iterator dbin_iter = bufferedDBTasksMaps_.find(dbInterfaceName); - if (dbin_iter == bufferedDBTasksMaps_.end()) - return NULL; - - return &dbin_iter->second; - } - - virtual void onChannelDeregister(Network::Channel * pChannel); - - InterfacesHandler* findBestInterfacesHandler(); - - /** - dbmgrִһݿ - */ - static PyObject* __py_executeRawDatabaseCommand(PyObject* self, PyObject* args); - void executeRawDatabaseCommand(const char* datas, uint32 size, PyObject* pycallback, ENTITY_ID eid, const std::string& dbInterfaceName); - void onExecuteRawDatabaseCommandCB(KBEngine::MemoryStream& s); - - PY_CALLBACKMGR& callbackMgr() { return pyCallbackMgr_; } - -protected: - TimerHandle loopCheckTimerHandle_; - TimerHandle mainProcessTimer_; - - // entityID - IDServer idServer_; - - // globalData - GlobalDataServer* pGlobalData_; - - // baseAppData - GlobalDataServer* pBaseAppData_; - - // cellAppData - GlobalDataServer* pCellAppData_; - - typedef KBEUnordered_map BUFFERED_DBTASKS_MAP; - BUFFERED_DBTASKS_MAP bufferedDBTasksMaps_; - - // Statistics - uint32 numWrittenEntity_; - uint32 numRemovedEntity_; - uint32 numQueryEntity_; - uint32 numExecuteRawDatabaseCommand_; - uint32 numCreatedAccount_; - - std::vector pInterfacesHandlers_; - - SyncAppDatasHandler* pSyncAppDatasHandler_; - UpdateDBServerLogHandler* pUpdateDBServerLogHandler_; - - TelnetServer* pTelnetServer_; - - std::map loseBaseappts_; - - PY_CALLBACKMGR pyCallbackMgr_; -}; - -} - -#endif // KBE_DBMGR_H +// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com + +#ifndef KBE_DBMGR_H +#define KBE_DBMGR_H + +#include "db_interface/db_threadpool.h" +#include "buffered_dbtasks.h" +#include "server/kbemain.h" +#include "pyscript/script.h" +#include "pyscript/pyobject_pointer.h" +#include "entitydef/entitydef.h" +#include "server/python_app.h" +#include "server/idallocate.h" +#include "server/serverconfig.h" +#include "server/globaldata_client.h" +#include "server/globaldata_server.h" +#include "server/callbackmgr.h" +#include "common/timer.h" +#include "network/endpoint.h" +#include "resmgr/resmgr.h" +#include "thread/threadpool.h" + + +namespace KBEngine{ + +class DBInterface; +class TelnetServer; +class InterfacesHandler; +class SyncAppDatasHandler; +class UpdateDBServerLogHandler; + +class Dbmgr : public PythonApp, + public Singleton +{ +public: + enum TimeOutType + { + TIMEOUT_TICK = TIMEOUT_PYTHONAPP_MAX + 1, + TIMEOUT_CHECK_STATUS + }; + + Dbmgr(Network::EventDispatcher& dispatcher, + Network::NetworkInterface& ninterface, + COMPONENT_TYPE componentType, + COMPONENT_ID componentID); + + ~Dbmgr(); + + bool run(); + + void handleTimeout(TimerHandle handle, void * arg); + void handleMainTick(); + void handleCheckStatusTick(); + + /* ʼؽӿ */ + bool initializeBegin(); + bool inInitialize(); + bool initializeEnd(); + void finalise(); + + bool installPyModules(); + bool uninstallPyModules(); + void onInstallPyModules(); + + bool initInterfacesHandler(); + + bool initDB(); + + virtual ShutdownHandler::CAN_SHUTDOWN_STATE canShutdown(); + + virtual void onShutdownBegin(); + virtual void onShutdownEnd(); + + /** ȡIDָ */ + IDServer& idServer(void){ return idServer_; } + + /** ӿ + һENTITY_ID + */ + void onReqAllocEntityID(Network::Channel* pChannel, COMPONENT_ORDER componentType, COMPONENT_ID componentID); + + /* ӿ + עһ¼baseappcellappdbmgr + ͨһµappˣ ҪijЩעԼ + */ + virtual void onRegisterNewApp(Network::Channel* pChannel, + int32 uid, + std::string& username, + COMPONENT_TYPE componentType, COMPONENT_ID componentID, COMPONENT_ORDER globalorderID, COMPONENT_ORDER grouporderID, + uint32 intaddr, uint16 intport, uint32 extaddr, uint16 extport, std::string& extaddrEx); + + + /** ӿ + dbmgr㲥globalݵĸı + */ + void onGlobalDataClientLogon(Network::Channel* pChannel, COMPONENT_TYPE componentType); + void onBroadcastGlobalDataChanged(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + 󴴽˺ + */ + void reqCreateAccount(Network::Channel* pChannel, KBEngine::MemoryStream& s); + void onCreateAccountCBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + ͻ + */ + void eraseClientReq(Network::Channel* pChannel, std::string& logkey); + + /** ӿ + һû¼ ҪϷ + */ + void onAccountLogin(Network::Channel* pChannel, KBEngine::MemoryStream& s); + void onLoginAccountCBBFromInterfaces(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + baseappѯaccountϢ + */ + void queryAccount(Network::Channel* pChannel, std::string& accountName, std::string& password, bool needCheckPassword, + COMPONENT_ID componentID, ENTITY_ID entityID, DBID entityDBID, uint32 ip, uint16 port); + + /** ӿ + ʵԶع + */ + void entityAutoLoad(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + ˺Ŵbaseapp + */ + void onAccountOnline(Network::Channel* pChannel, std::string& accountName, + COMPONENT_ID componentID, ENTITY_ID entityID); + + /** ӿ + entity-baseapp + */ + void onEntityOffline(Network::Channel* pChannel, DBID dbid, ENTITY_SCRIPT_UID sid, uint16 dbInterfaceIndex); + + /** ӿ + ִݿѯ + */ + void executeRawDatabaseCommand(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + ijentity浵 + */ + void writeEntity(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + ɾijentityĴ浵 + */ + void removeEntity(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + ͨdbidݿɾһʵĻص + */ + void deleteEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + ͨdbidѯһʵǷݿ + */ + void lookUpEntityByDBID(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + dbȡentity + */ + void queryEntity(Network::Channel* pChannel, uint16 dbInterfaceIndex, COMPONENT_ID componentID, int8 queryMode, DBID dbid, + std::string& entityType, CALLBACK_ID callbackID, ENTITY_ID entityID); + + /** ӿ + ͬentityģ + */ + void syncEntityStreamTemplate(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + virtual bool initializeWatcher(); + + /** ӿ + ֵ + */ + void charge(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + /** ӿ + ֵص + */ + void onChargeCB(Network::Channel* pChannel, KBEngine::MemoryStream& s); + + + /** ӿ + ص + */ + void accountActivate(Network::Channel* pChannel, std::string& scode); + + /** ӿ + ˺ + */ + void accountReqResetPassword(Network::Channel* pChannel, std::string& accountName); + void accountResetPassword(Network::Channel* pChannel, std::string& accountName, + std::string& newpassword, std::string& code); + + /** ӿ + ˺Ű + */ + void accountReqBindMail(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, + std::string& password, std::string& email); + void accountBindMail(Network::Channel* pChannel, std::string& username, std::string& scode); + + /** ӿ + ˺޸ + */ + void accountNewPassword(Network::Channel* pChannel, ENTITY_ID entityID, std::string& accountName, + std::string& password, std::string& newpassword); + + SyncAppDatasHandler* pSyncAppDatasHandler() const { return pSyncAppDatasHandler_; } + void pSyncAppDatasHandler(SyncAppDatasHandler* p){ pSyncAppDatasHandler_ = p; } + + std::string selectAccountDBInterfaceName(const std::string& name); + + Buffered_DBTasks* findBufferedDBTask(const std::string& dbInterfaceName) + { + BUFFERED_DBTASKS_MAP::iterator dbin_iter = bufferedDBTasksMaps_.find(dbInterfaceName); + if (dbin_iter == bufferedDBTasksMaps_.end()) + return NULL; + + return &dbin_iter->second; + } + + virtual void onChannelDeregister(Network::Channel * pChannel); + + InterfacesHandler* findBestInterfacesHandler(); + + /** + dbmgrִһݿ + */ + static PyObject* __py_executeRawDatabaseCommand(PyObject* self, PyObject* args); + void executeRawDatabaseCommand(const char* datas, uint32 size, PyObject* pycallback, ENTITY_ID eid, const std::string& dbInterfaceName); + void onExecuteRawDatabaseCommandCB(KBEngine::MemoryStream& s); + + PY_CALLBACKMGR& callbackMgr() { return pyCallbackMgr_; } + +protected: + TimerHandle loopCheckTimerHandle_; + TimerHandle mainProcessTimer_; + + // entityID + IDServer idServer_; + + // globalData + GlobalDataServer* pGlobalData_; + + // baseAppData + GlobalDataServer* pBaseAppData_; + + // cellAppData + GlobalDataServer* pCellAppData_; + + typedef KBEUnordered_map BUFFERED_DBTASKS_MAP; + BUFFERED_DBTASKS_MAP bufferedDBTasksMaps_; + + // Statistics + uint32 numWrittenEntity_; + uint32 numRemovedEntity_; + uint32 numQueryEntity_; + uint32 numExecuteRawDatabaseCommand_; + uint32 numCreatedAccount_; + + std::vector pInterfacesHandlers_; + + SyncAppDatasHandler* pSyncAppDatasHandler_; + UpdateDBServerLogHandler* pUpdateDBServerLogHandler_; + + TelnetServer* pTelnetServer_; + + std::map loseBaseappts_; + + PY_CALLBACKMGR pyCallbackMgr_; +}; + +} + +#endif // KBE_DBMGR_H From 0f66f88c49b3bc43bc8531f5439c321d2c29e369 Mon Sep 17 00:00:00 2001 From: kebiao <380000937@qq.com> Date: Wed, 3 Apr 2019 14:44:11 +0800 Subject: [PATCH 30/59] =?UTF-8?q?=E5=8D=87=E7=BA=A7python=E5=88=B03.7.3=20?= =?UTF-8?q?#1165?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kbe/src/lib/python/.azure-pipelines/ci.yml | 34 +- .../python/.azure-pipelines/docker-steps.yml | 76 - .../{posix-deps.sh => posix-deps-apt.sh} | 4 +- .../python/.azure-pipelines/posix-steps.yml | 30 +- kbe/src/lib/python/.azure-pipelines/pr.yml | 71 +- .../.azure-pipelines/windows-appx-test.yml | 67 - .../.azure-pipelines/windows-layout-steps.yml | 28 + .../python/.azure-pipelines/windows-steps.yml | 5 +- kbe/src/lib/python/Doc/bugs.rst | 4 +- kbe/src/lib/python/Doc/c-api/buffer.rst | 4 +- kbe/src/lib/python/Doc/c-api/codec.rst | 2 +- kbe/src/lib/python/Doc/c-api/dict.rst | 11 +- kbe/src/lib/python/Doc/c-api/exceptions.rst | 8 +- kbe/src/lib/python/Doc/c-api/mapping.rst | 8 + kbe/src/lib/python/Doc/c-api/number.rst | 1 + kbe/src/lib/python/Doc/c-api/objbuffer.rst | 6 +- kbe/src/lib/python/Doc/c-api/object.rst | 9 + kbe/src/lib/python/Doc/c-api/tuple.rst | 2 +- kbe/src/lib/python/Doc/c-api/unicode.rst | 8 +- kbe/src/lib/python/Doc/copyright.rst | 2 +- kbe/src/lib/python/Doc/data/refcounts.dat | 1827 +++++++++++++---- .../lib/python/Doc/distutils/setupscript.rst | 25 +- kbe/src/lib/python/Doc/faq/general.rst | 10 +- kbe/src/lib/python/Doc/faq/programming.rst | 40 +- kbe/src/lib/python/Doc/glossary.rst | 6 +- kbe/src/lib/python/Doc/howto/functional.rst | 2 +- .../lib/python/Doc/howto/logging-cookbook.rst | 4 +- kbe/src/lib/python/Doc/howto/logging.rst | 14 +- kbe/src/lib/python/Doc/howto/regex.rst | 5 +- kbe/src/lib/python/Doc/howto/unicode.rst | 341 +-- kbe/src/lib/python/Doc/library/aifc.rst | 2 +- .../python/Doc/library/asyncio-eventloop.rst | 8 + .../python/Doc/library/asyncio-exceptions.rst | 6 +- .../lib/python/Doc/library/asyncio-policy.rst | 2 +- .../lib/python/Doc/library/asyncio-queue.rst | 2 +- .../lib/python/Doc/library/asyncio-task.rst | 2 +- kbe/src/lib/python/Doc/library/binascii.rst | 5 + .../lib/python/Doc/library/collections.rst | 113 +- kbe/src/lib/python/Doc/library/compileall.rst | 2 +- .../lib/python/Doc/library/configparser.rst | 54 +- kbe/src/lib/python/Doc/library/contextlib.rst | 14 +- .../lib/python/Doc/library/dataclasses.rst | 6 +- kbe/src/lib/python/Doc/library/datetime.rst | 6 + kbe/src/lib/python/Doc/library/decimal.rst | 20 + kbe/src/lib/python/Doc/library/enum.rst | 2 +- kbe/src/lib/python/Doc/library/fileinput.rst | 4 +- kbe/src/lib/python/Doc/library/functions.rst | 29 +- .../lib/python/Doc/library/http.client.rst | 1 + kbe/src/lib/python/Doc/library/http.rst | 2 +- kbe/src/lib/python/Doc/library/idle.rst | 134 +- kbe/src/lib/python/Doc/library/imaplib.rst | 2 +- kbe/src/lib/python/Doc/library/imp.rst | 2 +- kbe/src/lib/python/Doc/library/importlib.rst | 11 +- kbe/src/lib/python/Doc/library/inspect.rst | 4 + kbe/src/lib/python/Doc/library/io.rst | 6 +- .../lib/python/Doc/library/logging.config.rst | 10 +- .../python/Doc/library/multiprocessing.rst | 15 +- kbe/src/lib/python/Doc/library/nntplib.rst | 4 +- kbe/src/lib/python/Doc/library/os.path.rst | 7 +- kbe/src/lib/python/Doc/library/parser.rst | 2 +- .../Doc/library/pathlib-inheritance.png | Bin 11280 -> 6431 bytes .../Doc/library/pathlib-inheritance.svg | 5 +- kbe/src/lib/python/Doc/library/pathlib.rst | 6 +- kbe/src/lib/python/Doc/library/pdb.rst | 4 + kbe/src/lib/python/Doc/library/pickle.rst | 2 +- kbe/src/lib/python/Doc/library/random.rst | 15 +- kbe/src/lib/python/Doc/library/re.rst | 9 +- kbe/src/lib/python/Doc/library/select.rst | 3 + kbe/src/lib/python/Doc/library/smtplib.rst | 2 +- .../lib/python/Doc/library/socketserver.rst | 2 +- kbe/src/lib/python/Doc/library/ssl.rst | 16 +- kbe/src/lib/python/Doc/library/stdtypes.rst | 18 +- kbe/src/lib/python/Doc/library/subprocess.rst | 8 +- kbe/src/lib/python/Doc/library/sys.rst | 31 +- kbe/src/lib/python/Doc/library/telnetlib.rst | 2 +- kbe/src/lib/python/Doc/library/tempfile.rst | 2 +- kbe/src/lib/python/Doc/library/test.rst | 4 + kbe/src/lib/python/Doc/library/threading.rst | 4 +- kbe/src/lib/python/Doc/library/time.rst | 14 +- kbe/src/lib/python/Doc/library/timeit.rst | 4 +- .../lib/python/Doc/library/tkinter.tix.rst | 11 - kbe/src/lib/python/Doc/library/types.rst | 2 +- kbe/src/lib/python/Doc/library/typing.rst | 27 +- .../lib/python/Doc/library/unittest.mock.rst | 35 +- kbe/src/lib/python/Doc/library/unittest.rst | 2 +- .../lib/python/Doc/library/urllib.parse.rst | 18 + kbe/src/lib/python/Doc/library/venv.rst | 22 +- kbe/src/lib/python/Doc/library/wave.rst | 2 +- .../python/Doc/library/xml.dom.minidom.rst | 2 +- .../Doc/library/xml.etree.elementtree.rst | 6 +- kbe/src/lib/python/Doc/library/zipfile.rst | 2 +- kbe/src/lib/python/Doc/license.rst | 2 +- kbe/src/lib/python/Doc/make.bat | 2 +- .../python/Doc/reference/compound_stmts.rst | 80 +- .../lib/python/Doc/reference/datamodel.rst | 9 +- .../python/Doc/reference/executionmodel.rst | 6 +- .../lib/python/Doc/reference/expressions.rst | 42 +- kbe/src/lib/python/Doc/reference/import.rst | 6 +- .../lib/python/Doc/reference/simple_stmts.rst | 90 +- .../Doc/tools/extensions/c_annotations.py | 2 +- .../Doc/tools/templates/indexsidebar.html | 2 +- kbe/src/lib/python/Doc/tutorial/classes.rst | 2 +- .../lib/python/Doc/tutorial/controlflow.rst | 42 +- .../python/Doc/tutorial/datastructures.rst | 10 +- kbe/src/lib/python/Doc/tutorial/errors.rst | 20 +- .../lib/python/Doc/tutorial/inputoutput.rst | 2 +- kbe/src/lib/python/Doc/tutorial/modules.rst | 4 +- kbe/src/lib/python/Doc/using/venv-create.inc | 16 +- kbe/src/lib/python/Doc/whatsnew/2.0.rst | 12 +- kbe/src/lib/python/Doc/whatsnew/2.1.rst | 4 +- kbe/src/lib/python/Doc/whatsnew/2.2.rst | 22 +- kbe/src/lib/python/Doc/whatsnew/2.3.rst | 16 +- kbe/src/lib/python/Doc/whatsnew/2.5.rst | 16 +- kbe/src/lib/python/Doc/whatsnew/2.6.rst | 14 +- kbe/src/lib/python/Doc/whatsnew/2.7.rst | 6 +- kbe/src/lib/python/Doc/whatsnew/3.0.rst | 12 +- kbe/src/lib/python/Doc/whatsnew/3.4.rst | 2 +- kbe/src/lib/python/Doc/whatsnew/3.6.rst | 11 + kbe/src/lib/python/Doc/whatsnew/3.7.rst | 2 +- kbe/src/lib/python/Include/Python.h | 10 + kbe/src/lib/python/Include/patchlevel.h | 4 +- kbe/src/lib/python/LICENSE | 4 +- .../lib/python/Lib/asyncio/proactor_events.py | 10 +- .../lib/python/Lib/asyncio/windows_events.py | 43 +- .../python/Lib/ctypes/test/test_strings.py | 7 + kbe/src/lib/python/Lib/dataclasses.py | 2 +- .../lib/python/Lib/distutils/_msvccompiler.py | 1 + .../python/Lib/distutils/command/build_ext.py | 5 +- kbe/src/lib/python/Lib/distutils/sysconfig.py | 25 +- .../Lib/distutils/tests/test_build_ext.py | 6 +- .../python/Lib/distutils/tests/test_util.py | 34 +- .../lib/python/Lib/distutils/unixccompiler.py | 10 +- kbe/src/lib/python/Lib/distutils/util.py | 9 +- kbe/src/lib/python/Lib/doctest.py | 2 - kbe/src/lib/python/Lib/ensurepip/__init__.py | 4 +- ...ny.whl => pip-19.0.3-py2.py3-none-any.whl} | Bin 1323545 -> 1353599 bytes ...=> setuptools-40.8.0-py2.py3-none-any.whl} | Bin 573107 -> 575457 bytes kbe/src/lib/python/Lib/enum.py | 25 +- kbe/src/lib/python/Lib/functools.py | 17 +- kbe/src/lib/python/Lib/http/cookiejar.py | 27 +- kbe/src/lib/python/Lib/idlelib/NEWS.txt | 62 +- .../lib/python/Lib/idlelib/autocomplete_w.py | 4 +- kbe/src/lib/python/Lib/idlelib/calltip.py | 2 +- kbe/src/lib/python/Lib/idlelib/calltip_w.py | 3 +- kbe/src/lib/python/Lib/idlelib/codecontext.py | 4 + kbe/src/lib/python/Lib/idlelib/colorizer.py | 82 +- kbe/src/lib/python/Lib/idlelib/config_key.py | 357 ++-- .../lib/python/Lib/idlelib/configdialog.py | 2 +- kbe/src/lib/python/Lib/idlelib/debugger.py | 2 +- kbe/src/lib/python/Lib/idlelib/editor.py | 19 +- kbe/src/lib/python/Lib/idlelib/grep.py | 11 +- kbe/src/lib/python/Lib/idlelib/help.html | 140 +- .../lib/python/Lib/idlelib/idle_test/htest.py | 3 +- .../Lib/idlelib/idle_test/test_calltip.py | 29 + .../Lib/idlelib/idle_test/test_codecontext.py | 6 + .../Lib/idlelib/idle_test/test_colorizer.py | 390 +++- .../Lib/idlelib/idle_test/test_config_key.py | 244 ++- .../Lib/idlelib/idle_test/test_help_about.py | 2 + .../Lib/idlelib/idle_test/test_searchbase.py | 8 +- .../Lib/idlelib/idle_test/test_squeezer.py | 304 ++- kbe/src/lib/python/Lib/idlelib/macosx.py | 2 +- kbe/src/lib/python/Lib/idlelib/mainmenu.py | 8 +- kbe/src/lib/python/Lib/idlelib/outwin.py | 1 + kbe/src/lib/python/Lib/idlelib/pyshell.py | 7 +- kbe/src/lib/python/Lib/idlelib/query.py | 1 - kbe/src/lib/python/Lib/idlelib/replace.py | 14 +- .../lib/python/Lib/idlelib/scrolledlist.py | 2 +- kbe/src/lib/python/Lib/idlelib/search.py | 15 +- kbe/src/lib/python/Lib/idlelib/searchbase.py | 6 +- kbe/src/lib/python/Lib/idlelib/squeezer.py | 200 +- kbe/src/lib/python/Lib/idlelib/tree.py | 2 +- kbe/src/lib/python/Lib/idlelib/window.py | 3 +- kbe/src/lib/python/Lib/idlelib/zoomheight.py | 6 +- .../python/Lib/multiprocessing/managers.py | 2 +- .../Lib/multiprocessing/popen_spawn_win32.py | 28 +- .../lib/python/Lib/multiprocessing/spawn.py | 2 +- kbe/src/lib/python/Lib/pathlib.py | 32 +- kbe/src/lib/python/Lib/pdb.py | 6 +- kbe/src/lib/python/Lib/pprint.py | 6 +- kbe/src/lib/python/Lib/pydoc.py | 4 +- kbe/src/lib/python/Lib/pydoc_data/topics.py | 127 +- kbe/src/lib/python/Lib/random.py | 4 +- kbe/src/lib/python/Lib/site.py | 9 +- kbe/src/lib/python/Lib/socketserver.py | 2 +- .../lib/python/Lib/sqlite3/test/regression.py | 4 + kbe/src/lib/python/Lib/sysconfig.py | 13 +- .../python/Lib/test/_test_multiprocessing.py | 311 ++- .../Lib/test/{bisect.py => bisect_cmd.py} | 0 kbe/src/lib/python/Lib/test/clinic.test | 1205 +++++++++++ kbe/src/lib/python/Lib/test/datetimetester.py | 11 + .../python/Lib/test/eintrdata/eintr_tester.py | 4 + .../python/Lib/test/libregrtest/cmdline.py | 2 +- .../lib/python/Lib/test/libregrtest/main.py | 4 + .../python/Lib/test/libregrtest/runtest.py | 4 +- kbe/src/lib/python/Lib/test/list_tests.py | 8 +- kbe/src/lib/python/Lib/test/lock_tests.py | 26 +- .../python/Lib/test/multibytecodec_support.py | 5 + kbe/src/lib/python/Lib/test/pickletester.py | 67 +- kbe/src/lib/python/Lib/test/pythoninfo.py | 2 + .../lib/python/Lib/test/support/__init__.py | 16 +- .../lib/python/Lib/test/talos-2019-0758.pem | 22 + .../Lib/test/test_asyncio/test_events.py | 4 +- .../Lib/test/test_asyncio/test_futures.py | 7 + .../Lib/test/test_asyncio/test_tasks.py | 9 + .../Lib/test/test_asyncio/test_unix_events.py | 10 +- .../lib/python/Lib/test/test_asyncio/utils.py | 4 +- kbe/src/lib/python/Lib/test/test_asyncore.py | 4 +- kbe/src/lib/python/Lib/test/test_bigmem.py | 137 +- kbe/src/lib/python/Lib/test/test_builtin.py | 1 + kbe/src/lib/python/Lib/test/test_bytes.py | 6 + kbe/src/lib/python/Lib/test/test_class.py | 20 +- kbe/src/lib/python/Lib/test/test_clinic.py | 18 +- .../lib/python/Lib/test/test_collections.py | 14 + .../lib/python/Lib/test/test_dataclasses.py | 14 +- kbe/src/lib/python/Lib/test/test_doctest.py | 47 +- .../lib/python/Lib/test/test_dummy_thread.py | 4 +- kbe/src/lib/python/Lib/test/test_enum.py | 26 + .../lib/python/Lib/test/test_faulthandler.py | 18 +- kbe/src/lib/python/Lib/test/test_float.py | 19 + kbe/src/lib/python/Lib/test/test_frame.py | 10 +- kbe/src/lib/python/Lib/test/test_functools.py | 29 +- kbe/src/lib/python/Lib/test/test_future4.py | 7 +- .../lib/python/Lib/test/test_genericclass.py | 9 +- .../python/Lib/test/test_http_cookiejar.py | 54 + kbe/src/lib/python/Lib/test/test_imaplib.py | 10 + kbe/src/lib/python/Lib/test/test_io.py | 31 +- kbe/src/lib/python/Lib/test/test_msilib.py | 27 +- .../test_multiprocessing_main_handling.py | 42 +- kbe/src/lib/python/Lib/test/test_os.py | 97 +- .../lib/python/Lib/test/test_ossaudiodev.py | 4 +- kbe/src/lib/python/Lib/test/test_pdb.py | 22 + kbe/src/lib/python/Lib/test/test_pydoc.py | 4 +- kbe/src/lib/python/Lib/test/test_re.py | 48 +- kbe/src/lib/python/Lib/test/test_regrtest.py | 14 + kbe/src/lib/python/Lib/test/test_signal.py | 10 +- kbe/src/lib/python/Lib/test/test_site.py | 4 +- kbe/src/lib/python/Lib/test/test_socket.py | 12 +- kbe/src/lib/python/Lib/test/test_ssl.py | 57 +- kbe/src/lib/python/Lib/test/test_symbol.py | 5 +- kbe/src/lib/python/Lib/test/test_tarfile.py | 9 +- kbe/src/lib/python/Lib/test/test_threading.py | 3 +- .../python/Lib/test/test_threading_local.py | 1 + .../lib/python/Lib/test/test_threadsignals.py | 12 +- kbe/src/lib/python/Lib/test/test_timeout.py | 4 +- kbe/src/lib/python/Lib/test/test_unicode.py | 6 + kbe/src/lib/python/Lib/test/test_urllib.py | 4 +- .../lib/python/Lib/test/test_urllib2net.py | 12 +- kbe/src/lib/python/Lib/test/test_urllibnet.py | 6 +- kbe/src/lib/python/Lib/test/test_urlparse.py | 23 + kbe/src/lib/python/Lib/test/test_uu.py | 19 + kbe/src/lib/python/Lib/test/test_venv.py | 25 +- .../python/Lib/test/test_warnings/__init__.py | 19 + kbe/src/lib/python/Lib/test/test_weakref.py | 82 + .../lib/python/Lib/test/test_xml_etree_c.py | 21 + kbe/src/lib/python/Lib/test/test_xmlrpc.py | 5 +- kbe/src/lib/python/Lib/test/test_zipfile64.py | 12 +- kbe/src/lib/python/Lib/test/time_hashlib.py | 12 +- kbe/src/lib/python/Lib/threading.py | 18 +- .../Lib/tkinter/test/test_ttk/test_widgets.py | 7 +- kbe/src/lib/python/Lib/types.py | 2 +- kbe/src/lib/python/Lib/unittest/loader.py | 4 +- kbe/src/lib/python/Lib/unittest/mock.py | 27 +- kbe/src/lib/python/Lib/unittest/runner.py | 4 +- .../python/Lib/unittest/test/test_loader.py | 16 + .../Lib/unittest/test/testmock/support.py | 3 + .../Lib/unittest/test/testmock/testhelpers.py | 30 + .../Lib/unittest/test/testmock/testmock.py | 40 + .../Lib/unittest/test/testmock/testpatch.py | 17 + .../Lib/unittest/test/testmock/testwith.py | 14 + kbe/src/lib/python/Lib/urllib/parse.py | 17 + kbe/src/lib/python/Lib/uu.py | 5 +- kbe/src/lib/python/Lib/venv/__init__.py | 66 +- kbe/src/lib/python/Lib/warnings.py | 2 +- kbe/src/lib/python/Lib/weakref.py | 36 +- .../python/Mac/BuildScript/build-installer.py | 18 +- .../Mac/BuildScript/tk868_on_10_8_10_9.patch | 18 + .../Mac/IDLE/IDLE.app/Contents/Info.plist | 2 +- .../python/Mac/PythonLauncher/Info.plist.in | 2 +- .../python/Mac/Resources/app/Info.plist.in | 2 +- .../Mac/Resources/framework/Info.plist.in | 4 +- kbe/src/lib/python/Misc/ACKS | 3 + kbe/src/lib/python/Misc/NEWS | 448 +++- kbe/src/lib/python/Misc/python.man | 6 +- kbe/src/lib/python/Modules/_abc.c | 2 +- kbe/src/lib/python/Modules/_asynciomodule.c | 12 + kbe/src/lib/python/Modules/_cryptmodule.c | 10 +- kbe/src/lib/python/Modules/_ctypes/_ctypes.c | 17 +- kbe/src/lib/python/Modules/_ctypes/callproc.c | 2 +- kbe/src/lib/python/Modules/_datetimemodule.c | 13 +- kbe/src/lib/python/Modules/_elementtree.c | 5 + kbe/src/lib/python/Modules/_functoolsmodule.c | 301 ++- kbe/src/lib/python/Modules/_hashopenssl.c | 14 +- kbe/src/lib/python/Modules/_io/textio.c | 4 + kbe/src/lib/python/Modules/_pickle.c | 12 +- kbe/src/lib/python/Modules/_posixsubprocess.c | 2 +- kbe/src/lib/python/Modules/_randommodule.c | 1 - kbe/src/lib/python/Modules/_sha3/cleanup.py | 2 +- .../lib/python/Modules/_sqlite/connection.c | 4 + kbe/src/lib/python/Modules/_sre.c | 4 +- kbe/src/lib/python/Modules/_ssl.c | 8 + kbe/src/lib/python/Modules/_winapi.c | 29 +- kbe/src/lib/python/Modules/arraymodule.c | 4 +- .../python/Modules/cjkcodecs/multibytecodec.c | 4 + kbe/src/lib/python/Modules/clinic/_winapi.c.h | 19 +- .../lib/python/Modules/clinic/arraymodule.c.h | 6 +- .../lib/python/Modules/clinic/posixmodule.c.h | 13 +- kbe/src/lib/python/Modules/getpath.c | 45 + kbe/src/lib/python/Modules/main.c | 1 + kbe/src/lib/python/Modules/mathmodule.c | 8 +- kbe/src/lib/python/Modules/overlapped.c | 76 +- kbe/src/lib/python/Modules/posixmodule.c | 69 +- kbe/src/lib/python/Modules/socketmodule.c | 22 +- kbe/src/lib/python/Modules/sre_lib.h | 8 + kbe/src/lib/python/Modules/timemodule.c | 31 +- kbe/src/lib/python/Objects/abstract.c | 7 +- kbe/src/lib/python/Objects/bytesobject.c | 25 +- kbe/src/lib/python/Objects/call.c | 4 + kbe/src/lib/python/Objects/fileobject.c | 2 +- kbe/src/lib/python/Objects/frameobject.c | 4 + kbe/src/lib/python/Objects/listobject.c | 4 +- kbe/src/lib/python/Objects/sliceobject.c | 38 +- kbe/src/lib/python/Objects/typeobject.c | 9 +- kbe/src/lib/python/Objects/unicodeobject.c | 14 +- kbe/src/lib/python/PC/_msi.c | 31 +- kbe/src/lib/python/PC/clinic/winreg.c.h | 82 +- kbe/src/lib/python/PC/config.c | 4 + kbe/src/lib/python/PC/launcher.c | 13 +- kbe/src/lib/python/PC/layout/main.py | 24 +- kbe/src/lib/python/PC/pyconfig.h | 13 - kbe/src/lib/python/PC/winreg.c | 76 +- .../lib/python/PCbuild/_contextvars.vcxproj | 93 - .../PCbuild/_contextvars.vcxproj.filters | 16 - .../python/PCbuild/_testcapi.vcxproj.filters | 3 - kbe/src/lib/python/PCbuild/find_python.bat | 2 +- kbe/src/lib/python/PCbuild/get_externals.bat | 6 +- kbe/src/lib/python/PCbuild/openssl.props | 2 +- kbe/src/lib/python/PCbuild/pcbuild.proj | 2 +- kbe/src/lib/python/PCbuild/pyexpat.vcxproj | 3 +- kbe/src/lib/python/PCbuild/pyproject.props | 5 +- kbe/src/lib/python/PCbuild/python.props | 2 +- kbe/src/lib/python/PCbuild/pythoncore.vcxproj | 3 +- .../python/PCbuild/pythoncore.vcxproj.filters | 83 +- kbe/src/lib/python/PCbuild/tcltk.props | 2 +- kbe/src/lib/python/Python/bootstrap_hash.c | 4 +- kbe/src/lib/python/Python/ceval.c | 4 + kbe/src/lib/python/Python/getcopyright.c | 2 +- kbe/src/lib/python/Python/import.c | 1 - kbe/src/lib/python/Python/sysmodule.c | 19 +- kbe/src/lib/python/Python/thread_nt.h | 5 +- kbe/src/lib/python/README.rst | 12 +- kbe/src/lib/python/Tools/clinic/clinic.py | 2 +- kbe/src/lib/python/Tools/gdb/libpython.py | 2 +- kbe/src/lib/python/Tools/msi/dev/dev.wixproj | 3 +- .../lib/python/Tools/msi/lib/lib_files.wxs | 2 +- kbe/src/lib/python/Tools/msi/sdktools.psm1 | 5 +- kbe/src/lib/python/Tools/nuget/python.nuspec | 3 +- .../lib/python/Tools/nuget/pythondaily.nuspec | 5 +- .../Tools/nuget/pythondaily.symbols.nuspec | 2 - .../lib/python/Tools/nuget/pythonx86.nuspec | 3 +- kbe/src/lib/python/aclocal.m4 | 8 +- kbe/src/lib/python/configure | 162 +- kbe/src/lib/python/configure.ac | 19 + kbe/src/lib/python/pyconfig.h.in | 3 + 363 files changed, 8697 insertions(+), 2810 deletions(-) delete mode 100644 kbe/src/lib/python/.azure-pipelines/docker-steps.yml rename kbe/src/lib/python/.azure-pipelines/{posix-deps.sh => posix-deps-apt.sh} (92%) mode change 100755 => 100644 delete mode 100644 kbe/src/lib/python/.azure-pipelines/windows-appx-test.yml create mode 100644 kbe/src/lib/python/.azure-pipelines/windows-layout-steps.yml rename kbe/src/lib/python/Lib/ensurepip/_bundled/{pip-18.1-py2.py3-none-any.whl => pip-19.0.3-py2.py3-none-any.whl} (50%) rename kbe/src/lib/python/Lib/ensurepip/_bundled/{setuptools-40.6.2-py2.py3-none-any.whl => setuptools-40.8.0-py2.py3-none-any.whl} (81%) rename kbe/src/lib/python/Lib/test/{bisect.py => bisect_cmd.py} (100%) mode change 100755 => 100644 create mode 100644 kbe/src/lib/python/Lib/test/clinic.test create mode 100644 kbe/src/lib/python/Lib/test/talos-2019-0758.pem create mode 100644 kbe/src/lib/python/Mac/BuildScript/tk868_on_10_8_10_9.patch delete mode 100644 kbe/src/lib/python/PCbuild/_contextvars.vcxproj delete mode 100644 kbe/src/lib/python/PCbuild/_contextvars.vcxproj.filters diff --git a/kbe/src/lib/python/.azure-pipelines/ci.yml b/kbe/src/lib/python/.azure-pipelines/ci.yml index 49a7bb6232..15a83dd037 100644 --- a/kbe/src/lib/python/.azure-pipelines/ci.yml +++ b/kbe/src/lib/python/.azure-pipelines/ci.yml @@ -2,6 +2,11 @@ variables: manylinux: false coverage: false +resources: + containers: + - container: manylinux1 + image: pyca/cryptography-manylinux1:x86_64 + jobs: - job: Prebuild displayName: Pre-build checks @@ -54,10 +59,12 @@ jobs: variables: testRunTitle: '$(build.sourceBranchName)-linux' testRunPlatform: linux - openssl_version: 1.1.0g + openssl_version: 1.1.0j steps: - template: ./posix-steps.yml + parameters: + dependencies: apt - job: ManyLinux1_CI_Tests @@ -75,13 +82,20 @@ jobs: pool: vmImage: ubuntu-16.04 + container: manylinux1 + variables: testRunTitle: '$(build.sourceBranchName)-manylinux1' testRunPlatform: manylinux1 - imageName: 'dockcross/manylinux-x64' + openssl_version: '' steps: - - template: ./docker-steps.yml + - template: ./posix-steps.yml + parameters: + dependencies: yum + sudo_dependencies: '' + xvfb: false + patchcheck: false - job: Ubuntu_Coverage_CI_Tests @@ -102,11 +116,12 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.0g + openssl_version: 1.1.0j steps: - template: ./posix-steps.yml parameters: + dependencies: apt coverage: true @@ -134,3 +149,14 @@ jobs: steps: - template: ./windows-steps.yml + + - template: ./windows-layout-steps.yml + parameters: + kind: nuget + - template: ./windows-layout-steps.yml + parameters: + kind: embed + - template: ./windows-layout-steps.yml + parameters: + kind: appx + fulltest: true diff --git a/kbe/src/lib/python/.azure-pipelines/docker-steps.yml b/kbe/src/lib/python/.azure-pipelines/docker-steps.yml deleted file mode 100644 index ba4dfd72dd..0000000000 --- a/kbe/src/lib/python/.azure-pipelines/docker-steps.yml +++ /dev/null @@ -1,76 +0,0 @@ -steps: -- checkout: self - clean: true - fetchDepth: 5 - -- ${{ if ne(parameters.targetBranch, '') }}: - - script: | - git fetch -q origin ${{ parameters.targetbranch }} - if ! git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD) | grep -qvE '(\.rst$|^Doc|^Misc)' - then - echo "Only docs were updated, stopping build process." - echo "##vso[task.setvariable variable=DocOnly]true" - exit - fi - displayName: Detect doc-only changes - -- task: docker@0 - displayName: 'Configure CPython (debug)' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: './configure --with-pydebug' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: docker@0 - displayName: 'Build CPython' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: 'make -s -j4' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: docker@0 - displayName: 'Display build info' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: 'make pythoninfo' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: docker@0 - displayName: 'Tests' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: 'make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=/build/test-results.xml"' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '$(build.binariesDirectory)/test-results.xml' - mergeTestResults: true - testRunTitle: $(testRunTitle) - platform: $(testRunPlatform) - condition: and(succeededOrFailed(), ne(variables['DocOnly'], 'true')) diff --git a/kbe/src/lib/python/.azure-pipelines/posix-deps.sh b/kbe/src/lib/python/.azure-pipelines/posix-deps-apt.sh old mode 100755 new mode 100644 similarity index 92% rename from kbe/src/lib/python/.azure-pipelines/posix-deps.sh rename to kbe/src/lib/python/.azure-pipelines/posix-deps-apt.sh index a572107566..4f489903ab --- a/kbe/src/lib/python/.azure-pipelines/posix-deps.sh +++ b/kbe/src/lib/python/.azure-pipelines/posix-deps-apt.sh @@ -1,6 +1,6 @@ -sudo apt-get update +apt-get update -sudo apt-get -yq install \ +apt-get -yq install \ build-essential \ zlib1g-dev \ libbz2-dev \ diff --git a/kbe/src/lib/python/.azure-pipelines/posix-steps.yml b/kbe/src/lib/python/.azure-pipelines/posix-steps.yml index 9fec9be801..a4160e5a1b 100644 --- a/kbe/src/lib/python/.azure-pipelines/posix-steps.yml +++ b/kbe/src/lib/python/.azure-pipelines/posix-steps.yml @@ -1,12 +1,16 @@ parameters: coverage: false + sudo_dependencies: sudo + dependencies: apt + patchcheck: true + xvfb: true steps: - checkout: self clean: true fetchDepth: 5 -- script: ./.azure-pipelines/posix-deps.sh $(openssl_version) +- script: ${{ parameters.sudo_dependencies }} ./.azure-pipelines/posix-deps-${{ parameters.dependencies }}.sh $(openssl_version) displayName: 'Install dependencies' - script: ./configure --with-pydebug @@ -23,7 +27,7 @@ steps: displayName: 'Display build info' - script: | - xvfb-run ./venv/bin/python -m coverage run --pylib -m test \ + $COMMAND -m coverage run --pylib -m test \ --fail-env-changed \ -uall,-cpu \ --junit-xml=$(build.binariesDirectory)/test-results.xml" \ @@ -32,6 +36,11 @@ steps: -x test_multiprocessing_spawn \ -x test_concurrent_futures displayName: 'Tests with coverage' + env: + ${{ if eq(parameters.xvfb, 'true') }}: + COMMAND: xvfb-run ./venv/bin/python + ${{ if ne(parameters.xvfb, 'true') }}: + COMMAND: ./venv/bin/python - script: ./venv/bin/python -m coverage xml displayName: 'Generate coverage.xml' @@ -44,13 +53,18 @@ steps: - script: make pythoninfo displayName: 'Display build info' - - script: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml" + - script: $COMMAND buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml" displayName: 'Tests' - - -- script: ./python Tools/scripts/patchcheck.py --travis true - displayName: 'Run patchcheck.py' - condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) + env: + ${{ if eq(parameters.xvfb, 'true') }}: + COMMAND: xvfb-run make + ${{ if ne(parameters.xvfb, 'true') }}: + COMMAND: make + +- ${{ if eq(parameters.patchcheck, 'true') }}: + - script: ./python Tools/scripts/patchcheck.py --travis true + displayName: 'Run patchcheck.py' + condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) - task: PublishTestResults@2 diff --git a/kbe/src/lib/python/.azure-pipelines/pr.yml b/kbe/src/lib/python/.azure-pipelines/pr.yml index 2d7fba9cf3..0bd7921bcb 100644 --- a/kbe/src/lib/python/.azure-pipelines/pr.yml +++ b/kbe/src/lib/python/.azure-pipelines/pr.yml @@ -1,3 +1,12 @@ +variables: + manylinux: false + coverage: false + +resources: + containers: + - container: manylinux1 + image: pyca/cryptography-manylinux1:x86_64 + jobs: - job: Prebuild displayName: Pre-build checks @@ -50,12 +59,70 @@ jobs: variables: testRunTitle: '$(system.pullRequest.TargetBranch)-linux' testRunPlatform: linux - openssl_version: 1.1.0g + openssl_version: 1.1.0j steps: - template: ./posix-steps.yml parameters: - targetBranch: $(System.PullRequest.TargetBranch) + dependencies: apt + + +- job: ManyLinux1_PR_Tests + displayName: ManyLinux1 PR Tests + dependsOn: Prebuild + condition: | + and( + and( + succeeded(), + eq(variables['manylinux'], 'true') + ), + eq(dependencies.Prebuild.outputs['tests.run'], 'true') + ) + + pool: + vmImage: ubuntu-16.04 + + container: manylinux1 + + variables: + testRunTitle: '$(system.pullRequest.TargetBranch)-manylinux1' + testRunPlatform: manylinux1 + openssl_version: '' + + steps: + - template: ./posix-steps.yml + parameters: + dependencies: yum + sudo_dependencies: '' + xvfb: false + patchcheck: false + + +- job: Ubuntu_Coverage_PR_Tests + displayName: Ubuntu PR Tests (coverage) + dependsOn: Prebuild + condition: | + and( + and( + succeeded(), + eq(variables['coverage'], 'true') + ), + eq(dependencies.Prebuild.outputs['tests.run'], 'true') + ) + + pool: + vmImage: ubuntu-16.04 + + variables: + testRunTitle: '$(Build.SourceBranchName)-linux-coverage' + testRunPlatform: linux-coverage + openssl_version: 1.1.0j + + steps: + - template: ./posix-steps.yml + parameters: + dependencies: apt + coverage: true - job: Windows_PR_Tests diff --git a/kbe/src/lib/python/.azure-pipelines/windows-appx-test.yml b/kbe/src/lib/python/.azure-pipelines/windows-appx-test.yml deleted file mode 100644 index 5f3fe6c945..0000000000 --- a/kbe/src/lib/python/.azure-pipelines/windows-appx-test.yml +++ /dev/null @@ -1,67 +0,0 @@ -jobs: -- job: Prebuild - displayName: Pre-build checks - - pool: - vmImage: ubuntu-16.04 - - steps: - - template: ./prebuild-checks.yml - - -- job: Windows_Appx_Tests - displayName: Windows Appx Tests - dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) - - pool: - vmImage: vs2017-win2016 - - strategy: - matrix: - win64: - arch: amd64 - buildOpt: '-p x64' - testRunTitle: '$(Build.SourceBranchName)-win64-appx' - testRunPlatform: win64 - maxParallel: 2 - - steps: - - checkout: self - clean: true - fetchDepth: 5 - - - powershell: | - # Relocate build outputs outside of source directory to make cleaning faster - Write-Host '##vso[task.setvariable variable=Py_IntDir]$(Build.BinariesDirectory)\obj' - # UNDONE: Do not build to a different directory because of broken tests - Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.SourcesDirectory)\PCbuild' - Write-Host '##vso[task.setvariable variable=EXTERNAL_DIR]$(Build.BinariesDirectory)\externals' - displayName: Update build locations - - - script: PCbuild\build.bat -e $(buildOpt) - displayName: 'Build CPython' - env: - IncludeUwp: true - - - script: python.bat PC\layout -vv -s "$(Build.SourcesDirectory)" -b "$(Py_OutDir)\$(arch)" -t "$(Py_IntDir)\layout-tmp-$(arch)" --copy "$(Py_IntDir)\layout-$(arch)" --precompile --preset-appx --include-tests - displayName: 'Create APPX layout' - - - script: .\python.exe -m test.pythoninfo - workingDirectory: $(Py_IntDir)\layout-$(arch) - displayName: 'Display build info' - - - script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results.xml" --tempdir "$(Py_IntDir)\tmp-$(arch)" - workingDirectory: $(Py_IntDir)\layout-$(arch) - displayName: 'Tests' - env: - PREFIX: $(Py_IntDir)\layout-$(arch) - - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '$(Build.BinariesDirectory)\test-results.xml' - mergeTestResults: true - testRunTitle: $(testRunTitle) - platform: $(testRunPlatform) - condition: succeededOrFailed() diff --git a/kbe/src/lib/python/.azure-pipelines/windows-layout-steps.yml b/kbe/src/lib/python/.azure-pipelines/windows-layout-steps.yml new file mode 100644 index 0000000000..e15729fac3 --- /dev/null +++ b/kbe/src/lib/python/.azure-pipelines/windows-layout-steps.yml @@ -0,0 +1,28 @@ +parameters: + kind: nuget + extraOpts: --precompile + fulltest: false + +steps: +- script: .\python.bat PC\layout -vv -s "$(Build.SourcesDirectory)" -b "$(Py_OutDir)\$(arch)" -t "$(Build.BinariesDirectory)\layout-tmp-${{ parameters.kind }}-$(arch)" --copy "$(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch)" ${{ parameters.extraOpts }} --preset-${{ parameters.kind }} --include-tests + displayName: Create ${{ parameters.kind }} layout + +- script: .\python.exe -m test.pythoninfo + workingDirectory: $(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch) + displayName: Show layout info (${{ parameters.kind }}) + +- ${{ if eq(parameters.fulltest, 'true') }}: + - script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results-${{ parameters.kind }}.xml" --tempdir "$(Build.BinariesDirectory)\tmp-${{ parameters.kind }}-$(arch)" + workingDirectory: $(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch) + displayName: ${{ parameters.kind }} Tests + env: + PREFIX: $(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch) + + - task: PublishTestResults@2 + displayName: Publish ${{ parameters.kind }} Test Results + inputs: + testResultsFiles: $(Build.BinariesDirectory)\test-results-${{ parameters.kind }}.xml + mergeTestResults: true + testRunTitle: ${{ parameters.kind }}-$(testRunTitle) + platform: $(testRunPlatform) + condition: succeededOrFailed() diff --git a/kbe/src/lib/python/.azure-pipelines/windows-steps.yml b/kbe/src/lib/python/.azure-pipelines/windows-steps.yml index cba00158ad..794a23a5d7 100644 --- a/kbe/src/lib/python/.azure-pipelines/windows-steps.yml +++ b/kbe/src/lib/python/.azure-pipelines/windows-steps.yml @@ -1,6 +1,6 @@ steps: - checkout: self - clean: true + clean: false fetchDepth: 5 - powershell: | @@ -8,7 +8,8 @@ steps: Write-Host '##vso[task.setvariable variable=Py_IntDir]$(Build.BinariesDirectory)\obj' # UNDONE: Do not build to a different directory because of broken tests Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.SourcesDirectory)\PCbuild' - Write-Host '##vso[task.setvariable variable=EXTERNAL_DIR]$(Build.BinariesDirectory)\externals' + #Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.BinariesDirectory)\bin' + Write-Host '##vso[task.setvariable variable=EXTERNALS_DIR]$(Build.BinariesDirectory)\externals' displayName: Update build locations - script: PCbuild\build.bat -e $(buildOpt) diff --git a/kbe/src/lib/python/Doc/bugs.rst b/kbe/src/lib/python/Doc/bugs.rst index 109e9eb202..c449ba2e71 100644 --- a/kbe/src/lib/python/Doc/bugs.rst +++ b/kbe/src/lib/python/Doc/bugs.rst @@ -17,7 +17,7 @@ Documentation bugs If you find a bug in this documentation or would like to propose an improvement, please submit a bug report on the :ref:`tracker `. If you -have a suggestion how to fix it, include that as well. +have a suggestion on how to fix it, include that as well. If you're short on time, you can also email documentation bug reports to docs@python.org (behavioral bugs can be sent to python-list@python.org). @@ -89,4 +89,4 @@ any and all questions pertaining to the process of fixing issues in Python. .. _Documentation bugs: https://bugs.python.org/issue?@filter=status&@filter=components&components=4&status=1&@columns=id,activity,title,status&@sort=-activity .. _Python Developer's Guide: https://devguide.python.org/ -.. _core-mentorship mailing list: https://mail.python.org/mailman/listinfo/core-mentorship/ +.. _core-mentorship mailing list: https://mail.python.org/mailman3/lists/core-mentorship.python.org/ diff --git a/kbe/src/lib/python/Doc/c-api/buffer.rst b/kbe/src/lib/python/Doc/c-api/buffer.rst index 33abb5bb94..c7c1e3cc74 100644 --- a/kbe/src/lib/python/Doc/c-api/buffer.rst +++ b/kbe/src/lib/python/Doc/c-api/buffer.rst @@ -429,7 +429,7 @@ Buffer-related functions Return ``1`` if *obj* supports the buffer interface otherwise ``0``. When ``1`` is returned, it doesn't guarantee that :c:func:`PyObject_GetBuffer` will - succeed. + succeed. This function always succeeds. .. c:function:: int PyObject_GetBuffer(PyObject *exporter, Py_buffer *view, int flags) @@ -470,7 +470,7 @@ Buffer-related functions Return ``1`` if the memory defined by the *view* is C-style (*order* is ``'C'``) or Fortran-style (*order* is ``'F'``) :term:`contiguous` or either one - (*order* is ``'A'``). Return ``0`` otherwise. + (*order* is ``'A'``). Return ``0`` otherwise. This function always succeeds. .. c:function:: int PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order) diff --git a/kbe/src/lib/python/Doc/c-api/codec.rst b/kbe/src/lib/python/Doc/c-api/codec.rst index dfe3d436e5..c55f19970e 100644 --- a/kbe/src/lib/python/Doc/c-api/codec.rst +++ b/kbe/src/lib/python/Doc/c-api/codec.rst @@ -13,7 +13,7 @@ Codec registry and support functions .. c:function:: int PyCodec_KnownEncoding(const char *encoding) Return ``1`` or ``0`` depending on whether there is a registered codec for - the given *encoding*. + the given *encoding*. This function always succeeds. .. c:function:: PyObject* PyCodec_Encode(PyObject *object, const char *encoding, const char *errors) diff --git a/kbe/src/lib/python/Doc/c-api/dict.rst b/kbe/src/lib/python/Doc/c-api/dict.rst index b7225faf40..0ced5a5fd0 100644 --- a/kbe/src/lib/python/Doc/c-api/dict.rst +++ b/kbe/src/lib/python/Doc/c-api/dict.rst @@ -95,6 +95,10 @@ Dictionary Objects Return the object from dictionary *p* which has a key *key*. Return *NULL* if the key *key* is not present, but *without* setting an exception. + Note that exceptions which occur while calling :meth:`__hash__` and + :meth:`__eq__` methods will get suppressed. + To get error reporting use :c:func:`PyDict_GetItemWithError()` instead. + .. c:function:: PyObject* PyDict_GetItemWithError(PyObject *p, PyObject *key) @@ -109,8 +113,13 @@ Dictionary Objects This is the same as :c:func:`PyDict_GetItem`, but *key* is specified as a :c:type:`const char\*`, rather than a :c:type:`PyObject\*`. + Note that exceptions which occur while calling :meth:`__hash__` and + :meth:`__eq__` methods and creating a temporary string object + will get suppressed. + To get error reporting use :c:func:`PyDict_GetItemWithError()` instead. + -.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *default) +.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *defaultobj) This is the same as the Python-level :meth:`dict.setdefault`. If present, it returns the value corresponding to *key* from the dictionary *p*. If the key diff --git a/kbe/src/lib/python/Doc/c-api/exceptions.rst b/kbe/src/lib/python/Doc/c-api/exceptions.rst index dd1e026cb0..cd06096ef7 100644 --- a/kbe/src/lib/python/Doc/c-api/exceptions.rst +++ b/kbe/src/lib/python/Doc/c-api/exceptions.rst @@ -53,8 +53,12 @@ Printing and clearing .. c:function:: void PyErr_PrintEx(int set_sys_last_vars) Print a standard traceback to ``sys.stderr`` and clear the error indicator. - Call this function only when the error indicator is set. (Otherwise it will - cause a fatal error!) + **Unless** the error is a ``SystemExit``. In that case the no traceback + is printed and Python process will exit with the error code specified by + the ``SystemExit`` instance. + + Call this function **only** when the error indicator is set. Otherwise it + will cause a fatal error! If *set_sys_last_vars* is nonzero, the variables :data:`sys.last_type`, :data:`sys.last_value` and :data:`sys.last_traceback` will be set to the diff --git a/kbe/src/lib/python/Doc/c-api/mapping.rst b/kbe/src/lib/python/Doc/c-api/mapping.rst index b8eaadbd70..e37dec9949 100644 --- a/kbe/src/lib/python/Doc/c-api/mapping.rst +++ b/kbe/src/lib/python/Doc/c-api/mapping.rst @@ -60,6 +60,10 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and This is equivalent to the Python expression ``key in o``. This function always succeeds. + Note that exceptions which occur while calling the :meth:`__getitem__` + method will get suppressed. + To get error reporting use :c:func:`PyObject_GetItem()` instead. + .. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) @@ -67,6 +71,10 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and This is equivalent to the Python expression ``key in o``. This function always succeeds. + Note that exceptions which occur while calling the :meth:`__getitem__` + method and creating a temporary string object will get suppressed. + To get error reporting use :c:func:`PyMapping_GetItemString()` instead. + .. c:function:: PyObject* PyMapping_Keys(PyObject *o) diff --git a/kbe/src/lib/python/Doc/c-api/number.rst b/kbe/src/lib/python/Doc/c-api/number.rst index 3c7605a67f..296b21c132 100644 --- a/kbe/src/lib/python/Doc/c-api/number.rst +++ b/kbe/src/lib/python/Doc/c-api/number.rst @@ -280,3 +280,4 @@ Number Protocol Returns ``1`` if *o* is an index integer (has the nb_index slot of the tp_as_number structure filled in), and ``0`` otherwise. + This function always succeeds. diff --git a/kbe/src/lib/python/Doc/c-api/objbuffer.rst b/kbe/src/lib/python/Doc/c-api/objbuffer.rst index e7f4fde002..3572564b13 100644 --- a/kbe/src/lib/python/Doc/c-api/objbuffer.rst +++ b/kbe/src/lib/python/Doc/c-api/objbuffer.rst @@ -39,7 +39,11 @@ an object, and :c:func:`PyBuffer_Release` when the buffer view can be released. .. c:function:: int PyObject_CheckReadBuffer(PyObject *o) Returns ``1`` if *o* supports the single-segment readable buffer interface. - Otherwise returns ``0``. + Otherwise returns ``0``. This function always succeeds. + + Note that this function tries to get and release a buffer, and exceptions + which occur while calling corresponding functions will get suppressed. + To get error reporting use :c:func:`PyObject_GetBuffer()` instead. .. c:function:: int PyObject_AsWriteBuffer(PyObject *obj, void **buffer, Py_ssize_t *buffer_len) diff --git a/kbe/src/lib/python/Doc/c-api/object.rst b/kbe/src/lib/python/Doc/c-api/object.rst index f0b2005f2d..a64ff2e6b5 100644 --- a/kbe/src/lib/python/Doc/c-api/object.rst +++ b/kbe/src/lib/python/Doc/c-api/object.rst @@ -33,6 +33,10 @@ Object Protocol is equivalent to the Python expression ``hasattr(o, attr_name)``. This function always succeeds. + Note that exceptions which occur while calling :meth:`__getattr__` and + :meth:`__getattribute__` methods will get suppressed. + To get error reporting use :c:func:`PyObject_GetAttr()` instead. + .. c:function:: int PyObject_HasAttrString(PyObject *o, const char *attr_name) @@ -40,6 +44,11 @@ Object Protocol is equivalent to the Python expression ``hasattr(o, attr_name)``. This function always succeeds. + Note that exceptions which occur while calling :meth:`__getattr__` and + :meth:`__getattribute__` methods and creating a temporary string object + will get suppressed. + To get error reporting use :c:func:`PyObject_GetAttrString()` instead. + .. c:function:: PyObject* PyObject_GetAttr(PyObject *o, PyObject *attr_name) diff --git a/kbe/src/lib/python/Doc/c-api/tuple.rst b/kbe/src/lib/python/Doc/c-api/tuple.rst index a66832cfa4..20bf9f0b08 100644 --- a/kbe/src/lib/python/Doc/c-api/tuple.rst +++ b/kbe/src/lib/python/Doc/c-api/tuple.rst @@ -209,7 +209,7 @@ type. This function "steals" a reference to *o*. -.. c:function:: PyObject* PyStructSequence_SET_ITEM(PyObject *p, Py_ssize_t *pos, PyObject *o) +.. c:function:: void PyStructSequence_SET_ITEM(PyObject *p, Py_ssize_t *pos, PyObject *o) Macro equivalent of :c:func:`PyStructSequence_SetItem`. diff --git a/kbe/src/lib/python/Doc/c-api/unicode.rst b/kbe/src/lib/python/Doc/c-api/unicode.rst index 92e22b16a4..39c067d439 100644 --- a/kbe/src/lib/python/Doc/c-api/unicode.rst +++ b/kbe/src/lib/python/Doc/c-api/unicode.rst @@ -935,7 +935,7 @@ wchar_t Support Return *NULL* on failure. -.. c:function:: Py_ssize_t PyUnicode_AsWideChar(PyUnicodeObject *unicode, wchar_t *w, Py_ssize_t size) +.. c:function:: Py_ssize_t PyUnicode_AsWideChar(PyObject *unicode, wchar_t *w, Py_ssize_t size) Copy the Unicode object contents into the :c:type:`wchar_t` buffer *w*. At most *size* :c:type:`wchar_t` characters are copied (excluding a possibly trailing @@ -1346,7 +1346,7 @@ These are the "Raw Unicode Escape" codec APIs: .. c:function:: PyObject* PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s, \ - Py_ssize_t size, const char *errors) + Py_ssize_t size) Encode the :c:type:`Py_UNICODE` buffer of the given *size* using Raw-Unicode-Escape and return a bytes object. Return *NULL* if an exception was raised by the codec. @@ -1515,8 +1515,8 @@ the user settings on the machine running the codec. Return *NULL* if an exception was raised by the codec. -.. c:function:: PyObject* PyUnicode_DecodeMBCSStateful(const char *s, int size, \ - const char *errors, int *consumed) +.. c:function:: PyObject* PyUnicode_DecodeMBCSStateful(const char *s, Py_ssize_t size, \ + const char *errors, Py_ssize_t *consumed) If *consumed* is *NULL*, behave like :c:func:`PyUnicode_DecodeMBCS`. If *consumed* is not *NULL*, :c:func:`PyUnicode_DecodeMBCSStateful` will not decode diff --git a/kbe/src/lib/python/Doc/copyright.rst b/kbe/src/lib/python/Doc/copyright.rst index 540ff5ef05..393a1f0375 100644 --- a/kbe/src/lib/python/Doc/copyright.rst +++ b/kbe/src/lib/python/Doc/copyright.rst @@ -4,7 +4,7 @@ Copyright Python and this documentation is: -Copyright © 2001-2018 Python Software Foundation. All rights reserved. +Copyright © 2001-2019 Python Software Foundation. All rights reserved. Copyright © 2000 BeOpen.com. All rights reserved. diff --git a/kbe/src/lib/python/Doc/data/refcounts.dat b/kbe/src/lib/python/Doc/data/refcounts.dat index 62cc938327..35527c179f 100644 --- a/kbe/src/lib/python/Doc/data/refcounts.dat +++ b/kbe/src/lib/python/Doc/data/refcounts.dat @@ -31,29 +31,130 @@ # The parameter names are as they appear in the API manual, not the source # code. +PyAnySet_Check:int::: +PyAnySet_Check:PyObject*:p:0: + +PyAnySet_CheckExact:int::: +PyAnySet_CheckExact:PyObject*:p:0: + +PyBool_Check:int::: +PyBool_Check:PyObject*:o:0: + PyBool_FromLong:PyObject*::+1: -PyBool_FromLong:long:v:0: +PyBool_FromLong:long:v:: + +PyBuffer_FillContiguousStrides:void::: +PyBuffer_FillContiguousStrides:int:ndims:: +PyBuffer_FillContiguousStrides:Py_ssize_t*:shape:: +PyBuffer_FillContiguousStrides:Py_ssize_t*:strides:: +PyBuffer_FillContiguousStrides:int:itemsize:: +PyBuffer_FillContiguousStrides:char:order:: + +PyBuffer_FillInfo:int::: +PyBuffer_FillInfo:Py_buffer*:view:: +PyBuffer_FillInfo:PyObject*:exporter:0: +PyBuffer_FillInfo:void*:buf:: +PyBuffer_FillInfo:Py_ssize_t:len:: +PyBuffer_FillInfo:int:readonly:: +PyBuffer_FillInfo:int:flags:: + +PyBuffer_IsContiguous:int::: +PyBuffer_IsContiguous:Py_buffer*:view:: +PyBuffer_IsContiguous:char:order:: + +PyBuffer_Release:void::: +PyBuffer_Release:Py_buffer*:view:: + +PyBuffer_ToContiguous:int::: +PyBuffer_ToContiguous:void*:buf:: +PyBuffer_ToContiguous:Py_buffer*:src:: +PyBuffer_ToContiguous:Py_ssize_t:len:: +PyBuffer_ToContiguous:char:order:: + +PyByteArray_AS_STRING:char*::: +PyByteArray_AS_STRING:PyObject*:bytearray:0: + +PyByteArray_AsString:char*::: +PyByteArray_AsString:PyObject*:bytearray:0: + +PyByteArray_Check:int::: +PyByteArray_Check:PyObject*:o:0: + +PyByteArray_CheckExact:int::: +PyByteArray_CheckExact:PyObject*:o:0: + +PyByteArray_Concat:PyObject*::+1: +PyByteArray_Concat:PyObject*:a:0: +PyByteArray_Concat:PyObject*:b:0: + +PyByteArray_FromObject:PyObject*::+1: +PyByteArray_FromObject:PyObject*:o:0: + +PyByteArray_FromStringAndSize:PyObject*::+1: +PyByteArray_FromStringAndSize:const char*:string:: +PyByteArray_FromStringAndSize:Py_ssize_t:len:: + +PyByteArray_GET_SIZE:Py_ssize_t::: +PyByteArray_GET_SIZE:PyObject*:bytearray:0: + +PyByteArray_Resize:int::: +PyByteArray_Resize:PyObject*:bytearray:0: +PyByteArray_Resize:Py_ssize_t:len:: + +PyByteArray_Size:Py_ssize_t::: +PyByteArray_Size:PyObject*:bytearray:0: + +PyBytes_AS_STRING:char*::: +PyBytes_AS_STRING:PyObject*:string:0: -PyBuffer_FromObject:PyObject*::+1: -PyBuffer_FromObject:PyObject*:base:+1: -PyBuffer_FromObject:int:offset:: -PyBuffer_FromObject:int:size:: +PyBytes_AsString:char*::: +PyBytes_AsString:PyObject*:o:0: -PyBuffer_FromReadWriteObject:PyObject*::+1: -PyBuffer_FromReadWriteObject:PyObject*:base:+1: -PyBuffer_FromReadWriteObject:int:offset:: -PyBuffer_FromReadWriteObject:int:size:: +PyBytes_AsStringAndSize:int::: +PyBytes_AsStringAndSize:PyObject*:obj:0: +PyBytes_AsStringAndSize:char**:buffer:: +PyBytes_AsStringAndSize:Py_ssize_t*:length:: -PyBuffer_FromMemory:PyObject*::+1: -PyBuffer_FromMemory:void*:ptr:: -PyBuffer_FromMemory:int:size:: +PyBytes_Check:int::: +PyBytes_Check:PyObject*:o:0: -PyBuffer_FromReadWriteMemory:PyObject*::+1: -PyBuffer_FromReadWriteMemory:void*:ptr:: -PyBuffer_FromReadWriteMemory:int:size:: +PyBytes_CheckExact:int::: +PyBytes_CheckExact:PyObject*:o:0: -PyBuffer_New:PyObject*::+1: -PyBuffer_New:int:size:: +PyBytes_Concat:void::: +PyBytes_Concat:PyObject**:bytes:0: +PyBytes_Concat:PyObject*:newpart:0: + +PyBytes_ConcatAndDel:void::: +PyBytes_ConcatAndDel:PyObject**:bytes:0: +PyBytes_ConcatAndDel:PyObject*:newpart:-1: + +PyBytes_FromString:PyObject*::+1: +PyBytes_FromString:const char*:v:: + +PyBytes_FromStringAndSize:PyObject*::+1: +PyBytes_FromStringAndSize:const char*:v:: +PyBytes_FromStringAndSize:Py_ssize_t:len:: + +PyBytes_FromFormat:PyObject*::+1: +PyBytes_FromFormat:const char*:format:: +PyBytes_FromFormat::...:: + +PyBytes_FromFormatV:PyObject*::+1: +PyBytes_FromFormatV:const char*:format:: +PyBytes_FromFormatV:va_list:vargs:: + +PyBytes_FromObject:PyObject*::+1: +PyBytes_FromObject:PyObject*:o:0: + +PyBytes_GET_SIZE:Py_ssize_t::: +PyBytes_GET_SIZE:PyObject*:o:0: + +PyBytes_Size:Py_ssize_t::: +PyBytes_Size:PyObject*:o:0: + +PyCapsule_CheckExact:int::: +PyCapsule_CheckExact:PyObject*:p:0: PyCapsule_GetContext:void *::: PyCapsule_GetContext:PyObject*:self:0: @@ -72,6 +173,10 @@ PyCapsule_Import:void *::: PyCapsule_Import:const char *:name:: PyCapsule_Import:int:no_block:: +PyCapsule_IsValid:int::: +PyCapsule_IsValid:PyObject*:capsule:0: +PyCapsule_IsValid:const char*:name:: + PyCapsule_New:PyObject*::+1: PyCapsule_New:void*:pointer:: PyCapsule_New:const char *:name:: @@ -93,21 +198,8 @@ PyCapsule_SetPointer:int::: PyCapsule_SetPointer:PyObject*:self:0: PyCapsule_SetPointer:void*:pointer:: - -PyCObject_AsVoidPtr:void*::: -PyCObject_AsVoidPtr:PyObject*:self:0: - -PyCObject_FromVoidPtr:PyObject*::+1: -PyCObject_FromVoidPtr:void*:cobj:: -PyCObject_FromVoidPtr::void (* destr)(void* ):: - -PyCObject_FromVoidPtrAndDesc:PyObject*::+1: -PyCObject_FromVoidPtrAndDesc:void*:cobj:: -PyCObject_FromVoidPtrAndDesc:void*:desc:: -PyCObject_FromVoidPtrAndDesc:void(*)(void*,void*):destr:: - -PyCObject_GetDesc:void*::: -PyCObject_GetDesc:PyObject*:self:0: +PyCell_Check:int::: +PyCell_Check::ob:: PyCell_New:PyObject*::+1: PyCell_New:PyObject*:ob:0: @@ -126,19 +218,118 @@ PyCell_Set:int::: PyCell_Set:PyObject*:cell:0: PyCell_Set:PyObject*:value:0: +PyCallIter_Check:int::: +PyCallIter_Check::op:: + PyCallIter_New:PyObject*::+1: -PyCallIter_New:PyObject*:callable:: -PyCallIter_New:PyObject*:sentinel:: +PyCallIter_New:PyObject*:callable:+1: +PyCallIter_New:PyObject*:sentinel:+1: PyCallable_Check:int::: PyCallable_Check:PyObject*:o:0: +PyCode_Check:int::: +PyCode_Check:PyObject*:co:0: + +PyCode_GetNumFree:int::: +PyCode_GetNumFree:PyCodeObject*:co:0: + +PyCode_New:PyCodeObject*::+1: +PyCode_New:int:argcount:: +PyCode_New:int:kwonlyargcount:: +PyCode_New:int:nlocals:: +PyCode_New:int:stacksize:: +PyCode_New:int:flags:: +PyCode_New:PyObject*:code:0: +PyCode_New:PyObject*:consts:0: +PyCode_New:PyObject*:names:0: +PyCode_New:PyObject*:varnames:0: +PyCode_New:PyObject*:freevars:0: +PyCode_New:PyObject*:cellvars:0: +PyCode_New:PyObject*:filename:0: +PyCode_New:PyObject*:name:0: +PyCode_New:int:firstlineno:: +PyCode_New:PyObject*:lnotab:0: + +PyCode_NewEmpty:PyCodeObject*::+1: +PyCode_NewEmpty:const char*:filename:: +PyCode_NewEmpty:const char*:funcname:: +PyCode_NewEmpty:int:firstlineno:: + +PyCodec_Register:int::: +PyCodec_Register:PyObject*:search_function:+1: + +PyCodec_KnownEncoding:int::: +PyCodec_KnownEncoding:const char*:encoding:: + +PyCodec_Encode:PyObject*::+1: +PyCodec_Encode:PyObject*:object:0: +PyCodec_Encode:const char*:encoding:: +PyCodec_Encode:const char*:errors:: + +PyCodec_Decode:PyObject*::+1: +PyCodec_Decode:PyObject*:object:0: +PyCodec_Decode:const char*:encoding:: +PyCodec_Decode:const char*:errors:: + +PyCodec_Encoder:PyObject*::+1: +PyCodec_Encoder:const char*:encoding:: + +PyCodec_Decoder:PyObject*::+1: +PyCodec_Decoder:const char*:encoding:: + +PyCodec_IncrementalEncoder:PyObject*::+1: +PyCodec_IncrementalEncoder:const char*:encoding:: +PyCodec_IncrementalEncoder:const char*:errors:: + +PyCodec_IncrementalDecoder:PyObject*::+1: +PyCodec_IncrementalDecoder:const char*:encoding:: +PyCodec_IncrementalDecoder:const char*:errors:: + +PyCodec_StreamReader:PyObject*::+1: +PyCodec_StreamReader:const char*:encoding:: +PyCodec_StreamReader:PyObject*:stream:0: +PyCodec_StreamReader:const char*:errors:: + +PyCodec_StreamWriter:PyObject*::+1: +PyCodec_StreamWriter:const char*:encoding:: +PyCodec_StreamWriter:PyObject*:stream:0: +PyCodec_StreamWriter:const char*:errors:: + +PyCodec_RegisterError:int::: +PyCodec_RegisterError:const char*:name:: +PyCodec_RegisterError:PyObject*:error:+1: + +PyCodec_LookupError:PyObject*::+1: +PyCodec_LookupError:const char*:name:: + +PyCodec_StrictErrors:PyObject*::null: +PyCodec_StrictErrors:PyObject*:exc:0: + +PyCodec_IgnoreErrors:PyObject*::+1: +PyCodec_IgnoreErrors:PyObject*:exc:0: + +PyCodec_ReplaceErrors:PyObject*::+1: +PyCodec_ReplaceErrors:PyObject*:exc:0: + +PyCodec_XMLCharRefReplaceErrors:PyObject*::+1: +PyCodec_XMLCharRefReplaceErrors:PyObject*:exc:0: + +PyCodec_BackslashReplaceErrors:PyObject*::+1: +PyCodec_BackslashReplaceErrors:PyObject*:exc:0: + +PyCodec_NameReplaceErrors:PyObject*::+1: +PyCodec_NameReplaceErrors:PyObject*:exc:0: + PyComplex_AsCComplex:Py_complex::: PyComplex_AsCComplex:PyObject*:op:0: PyComplex_Check:int::: PyComplex_Check:PyObject*:p:0: +PyComplex_CheckExact:int::: +PyComplex_CheckExact:PyObject*:p:0: + PyComplex_FromCComplex:PyObject*::+1: PyComplex_FromCComplex::Py_complex v:: @@ -193,6 +384,12 @@ PyContextVar_Reset:int::: PyContextVar_Reset:PyObject*:var:0: PyContextVar_Reset:PyObject*:token:-1: +PyDate_Check:int::: +PyDate_Check:PyObject*:ob:0: + +PyDate_CheckExact:int::: +PyDate_CheckExact:PyObject*:ob:0: + PyDate_FromDate:PyObject*::+1: PyDate_FromDate:int:year:: PyDate_FromDate:int:month:: @@ -201,6 +398,12 @@ PyDate_FromDate:int:day:: PyDate_FromTimestamp:PyObject*::+1: PyDate_FromTimestamp:PyObject*:args:0: +PyDateTime_Check:int::: +PyDateTime_Check:PyObject*:ob:0: + +PyDateTime_CheckExact:int::: +PyDateTime_CheckExact:PyObject*:ob:0: + PyDateTime_FromDateAndTime:PyObject*::+1: PyDateTime_FromDateAndTime:int:year:: PyDateTime_FromDateAndTime:int:month:: @@ -213,46 +416,62 @@ PyDateTime_FromDateAndTime:int:usecond:: PyDateTime_FromTimestamp:PyObject*::+1: PyDateTime_FromTimestamp:PyObject*:args:0: +PyDelta_Check:int::: +PyDelta_Check:PyObject*:ob:0: + +PyDelta_CheckExact:int::: +PyDelta_CheckExact:PyObject*:ob:0: + PyDelta_FromDSU:PyObject*::+1: PyDelta_FromDSU:int:days:: PyDelta_FromDSU:int:seconds:: PyDelta_FromDSU:int:useconds:: PyTimeZone_FromOffset:PyObject*::+1: -PyTimeZone_FromOffset:PyDateTime_DeltaType*:offset:+1:Reference count not increased if offset is +00:00 +PyTimeZone_FromOffset:PyObject*:offset:+1:Reference count not increased if offset is +00:00 PyTimeZone_FromOffsetAndName:PyObject*::+1: -PyTimeZone_FromOffsetAndName:PyDateTime_DeltaType*:offset:+1:Reference count not increased if offset is +00:00 and name == NULL -PyTimeZone_FromOffsetAndName:PyUnicode*:name:+1: +PyTimeZone_FromOffsetAndName:PyObject*:offset:+1:Reference count not increased if offset is +00:00 and name == NULL +PyTimeZone_FromOffsetAndName:PyObject*:name:+1: +PyDescr_IsData:int::: +PyDescr_IsData:PyObject*:descr:0: + PyDescr_NewClassMethod:PyObject*::+1: -PyDescr_NewClassMethod:PyTypeObject*:type:: +PyDescr_NewClassMethod:PyTypeObject*:type:+1: PyDescr_NewClassMethod:PyMethodDef*:method:: PyDescr_NewGetSet:PyObject*::+1: -PyDescr_NewGetSet:PyTypeObject*:type:: +PyDescr_NewGetSet:PyTypeObject*:type:+1: PyDescr_NewGetSet:PyGetSetDef*:getset:: PyDescr_NewMember:PyObject*::+1: -PyDescr_NewMember:PyTypeObject*:type:: +PyDescr_NewMember:PyTypeObject*:type:+1: PyDescr_NewMember:PyMemberDef*:member:: PyDescr_NewMethod:PyObject*::+1: -PyDescr_NewMethod:PyTypeObject*:type:: +PyDescr_NewMethod:PyTypeObject*:type:+1: PyDescr_NewMethod:PyMethodDef*:meth:: PyDescr_NewWrapper:PyObject*::+1: -PyDescr_NewWrapper:PyTypeObject*:type:: +PyDescr_NewWrapper:PyTypeObject*:type:+1: PyDescr_NewWrapper:struct wrapperbase*:base:: PyDescr_NewWrapper:void*:wrapped:: PyDict_Check:int::: PyDict_Check:PyObject*:p:0: +PyDict_CheckExact:int::: +PyDict_CheckExact:PyObject*:p:0: + PyDict_Clear:void::: PyDict_Clear:PyObject*:p:0: +PyDict_Contains:int::: +PyDict_Contains:PyObject*:p:0: +PyDict_Contains:PyObject*:key:0: + PyDict_DelItem:int::: PyDict_DelItem:PyObject*:p:0: PyDict_DelItem:PyObject*:key:0: @@ -261,7 +480,7 @@ PyDict_DelItemString:int::: PyDict_DelItemString:PyObject*:p:0: PyDict_DelItemString:const char*:key:: -PyDict_GetItem:PyObject*::0:0 +PyDict_GetItem:PyObject*::0: PyDict_GetItem:PyObject*:p:0: PyDict_GetItem:PyObject*:key:0: @@ -289,9 +508,19 @@ PyDict_New:PyObject*::+1: PyDict_Copy:PyObject*::+1: PyDict_Copy:PyObject*:p:0: +PyDict_Merge:int::: +PyDict_Merge:PyObject*:a:0: +PyDict_Merge:PyObject*:b:0: +PyDict_Merge:int:override:: + +PyDict_MergeFromSeq2:int::: +PyDict_MergeFromSeq2:PyObject*:a:0: +PyDict_MergeFromSeq2:PyObject*:seq2:0: +PyDict_MergeFromSeq2:int:override:: + PyDict_Next:int::: PyDict_Next:PyObject*:p:0: -PyDict_Next:int:ppos:: +PyDict_Next:Py_ssize_t:ppos:: PyDict_Next:PyObject**:pkey:0: PyDict_Next:PyObject**:pvalue:0: @@ -305,8 +534,12 @@ PyDict_SetItemString:PyObject*:p:0: PyDict_SetItemString:const char*:key:: PyDict_SetItemString:PyObject*:val:+1: -PyDict_Size:int::: -PyDict_Size:PyObject*:p:: +PyDict_Size:Py_ssize_t::: +PyDict_Size:PyObject*:p:0: + +PyDict_Update:int::: +PyDict_Update:PyObject*:a:0: +PyDict_Update:PyObject*:b:0: PyDict_Values:PyObject*::+1: PyDict_Values:PyObject*:p:0: @@ -330,6 +563,21 @@ PyErr_Fetch:PyObject**:ptype:0: PyErr_Fetch:PyObject**:pvalue:0: PyErr_Fetch:PyObject**:ptraceback:0: +PyErr_Format:PyObject*::null: +PyErr_Format:PyObject*:exception:+1: +PyErr_Format:const char*:format:: +PyErr_Format::...:: + +PyErr_FormatV:PyObject*::null: +PyErr_FormatV:PyObject*:exception:+1: +PyErr_FormatV:const char*:format:: +PyErr_FormatV:va_list:vargs:: + +PyErr_GetExcInfo:void::: +PyErr_GetExcInfo:PyObject**:ptype:+1: +PyErr_GetExcInfo:PyObject**:pvalue:+1: +PyErr_GetExcInfo:PyObject**:ptraceback:+1: + PyErr_GivenExceptionMatches:int::: PyErr_GivenExceptionMatches:PyObject*:given:0: PyErr_GivenExceptionMatches:PyObject*:exc:0: @@ -356,27 +604,61 @@ PyErr_Occurred:PyObject*::0: PyErr_Print:void::: +PyErr_PrintEx:void::: +PyErr_PrintEx:int:set_sys_last_vars:: + +PyErr_ResourceWarning:int::: +PyErr_ResourceWarning:PyObject*:source:0: +PyErr_ResourceWarning:Py_ssize_t:stack_level:: +PyErr_ResourceWarning:const char*:format:: +PyErr_ResourceWarning::...:: + PyErr_Restore:void::: PyErr_Restore:PyObject*:type:-1: PyErr_Restore:PyObject*:value:-1: PyErr_Restore:PyObject*:traceback:-1: PyErr_SetExcFromWindowsErr:PyObject*::null: -PyErr_SetExcFromWindowsErr:PyObject*:type:0: +PyErr_SetExcFromWindowsErr:PyObject*:type:+1: PyErr_SetExcFromWindowsErr:int:ierr:: PyErr_SetExcFromWindowsErrWithFilename:PyObject*::null: -PyErr_SetExcFromWindowsErrWithFilename:PyObject*:type:0: +PyErr_SetExcFromWindowsErrWithFilename:PyObject*:type:+1: PyErr_SetExcFromWindowsErrWithFilename:int:ierr:: PyErr_SetExcFromWindowsErrWithFilename:const char*:filename:: +PyErr_SetExcFromWindowsErrWithFilenameObject:PyObject*::null: +PyErr_SetExcFromWindowsErrWithFilenameObject:PyObject*:type:+1: +PyErr_SetExcFromWindowsErrWithFilenameObject:int:ierr:: +PyErr_SetExcFromWindowsErrWithFilenameObject:PyObject*:filename:+1: + +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*::null: +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*:type:+1: +PyErr_SetExcFromWindowsErrWithFilenameObjects:int:ierr:: +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*:filename:+1: +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*:filename2:+1: + +PyErr_SetExcInfo:void::: +PyErr_SetExcInfo:PyObject*:type:0: +PyErr_SetExcInfo:PyObject*:value:0: +PyErr_SetExcInfo:PyObject*:traceback:0: + PyErr_SetFromErrno:PyObject*::null: -PyErr_SetFromErrno:PyObject*:type:0: +PyErr_SetFromErrno:PyObject*:type:+1: PyErr_SetFromErrnoWithFilename:PyObject*::null: -PyErr_SetFromErrnoWithFilename:PyObject*:type:0: +PyErr_SetFromErrnoWithFilename:PyObject*:type:+1: PyErr_SetFromErrnoWithFilename:const char*:filename:: +PyErr_SetFromErrnoWithFilenameObject:PyObject*::null: +PyErr_SetFromErrnoWithFilenameObject:PyObject*:type:+1: +PyErr_SetFromErrnoWithFilenameObject:PyObject*:filenameObject:+1: + +PyErr_SetFromErrnoWithFilenameObjects:PyObject*::null: +PyErr_SetFromErrnoWithFilenameObjects:PyObject*:type:+1: +PyErr_SetFromErrnoWithFilenameObjects:PyObject*:filenameObject:+1: +PyErr_SetFromErrnoWithFilenameObjects:PyObject*:filenameObject2:+1: + PyErr_SetFromWindowsErr:PyObject*::null: PyErr_SetFromWindowsErr:int:ierr:: @@ -384,6 +666,16 @@ PyErr_SetFromWindowsErrWithFilename:PyObject*::null: PyErr_SetFromWindowsErrWithFilename:int:ierr:: PyErr_SetFromWindowsErrWithFilename:const char*:filename:: +PyErr_SetImportError:PyObject*::null: +PyErr_SetImportError:PyObject*:msg:+1: +PyErr_SetImportError:PyObject*:name:+1: +PyErr_SetImportError:PyObject*:path:+1: + +PyErr_SetImportErrorSubclass:PyObject*::null: +PyErr_SetImportErrorSubclass:PyObject*:msg:+1: +PyErr_SetImportErrorSubclass:PyObject*:name:+1: +PyErr_SetImportErrorSubclass:PyObject*:path:+1: + PyErr_SetInterrupt:void::: PyErr_SetNone:void::: @@ -397,31 +689,69 @@ PyErr_SetString:void::: PyErr_SetString:PyObject*:type:+1: PyErr_SetString:const char*:message:: -PyErr_Format:PyObject*::null: -PyErr_Format:PyObject*:exception:+1: -PyErr_Format:const char*:format:: -PyErr_Format::...:: +PyErr_SyntaxLocation:void::: +PyErr_SyntaxLocation:const char*:filename:: +PyErr_SyntaxLocation:int:lineno:: -PyErr_FormatV:PyObject*::null: -PyErr_FormatV:PyObject*:exception:+1: -PyErr_FormatV:const char*:format:: -PyErr_FormatV:va_list:vargs:: +PyErr_SyntaxLocationEx:void::: +PyErr_SyntaxLocationEx:const char*:filename:: +PyErr_SyntaxLocationEx:int:lineno:: +PyErr_SyntaxLocationEx:int:col_offset:: + +PyErr_SyntaxLocationObject:void::: +PyErr_SyntaxLocationObject:PyObject*:filename:+1: +PyErr_SyntaxLocationObject:int:lineno:: +PyErr_SyntaxLocationObject:int:col_offset:: PyErr_WarnEx:int::: PyErr_WarnEx:PyObject*:category:0: PyErr_WarnEx:const char*:message:: PyErr_WarnEx:Py_ssize_t:stack_level:: +PyErr_WarnExplicit:int::: +PyErr_WarnExplicit:PyObject*:category:0: +PyErr_WarnExplicit:const char*:message:: +PyErr_WarnExplicit:const char*:filename:: +PyErr_WarnExplicit:int:lineno:: +PyErr_WarnExplicit:const char*:module:: +PyErr_WarnExplicit:PyObject*:registry:0: + +PyErr_WarnExplicitObject:int::: +PyErr_WarnExplicitObject:PyObject*:category:0: +PyErr_WarnExplicitObject:PyObject*:message:0: +PyErr_WarnExplicitObject:PyObject*:filename:0: +PyErr_WarnExplicitObject:int:lineno:: +PyErr_WarnExplicitObject:PyObject*:module:0: +PyErr_WarnExplicitObject:PyObject*:registry:0: + +PyErr_WarnFormat:int::: +PyErr_WarnFormat:PyObject*:category:0: +PyErr_WarnFormat:Py_ssize_t:stack_level:: +PyErr_WarnFormat:const char*:format:: +PyErr_WarnFormat::...:: + +PyErr_WriteUnraisable:void::: +PyErr_WriteUnraisable:PyObject*:obj:0: + PyEval_AcquireLock:void::: PyEval_AcquireThread:void::: PyEval_AcquireThread:PyThreadState*:tstate:: PyEval_GetBuiltins:PyObject*::0: + PyEval_GetLocals:PyObject*::0: + PyEval_GetGlobals:PyObject*::0: + PyEval_GetFrame:PyObject*::0: +PyEval_GetFuncDesc:const char*::: +PyEval_GetFuncDesc:PyObject*:func:0: + +PyEval_GetFuncName:const char*::: +PyEval_GetFuncName:PyObject*:func:0: + PyEval_InitThreads:void::: PyEval_ReleaseLock:void::: @@ -434,61 +764,85 @@ PyEval_RestoreThread:PyThreadState*:tstate:: PyEval_SaveThread:PyThreadState*::: +PyEval_SetProfile:void::: +PyEval_SetProfile:Py_tracefunc:func:: +PyEval_SetProfile:PyObject*:obj:+1: + +PyEval_SetTrace:void::: +PyEval_SetTrace:Py_tracefunc:func:: +PyEval_SetTrace:PyObject*:obj:+1: + PyEval_EvalCode:PyObject*::+1: -PyEval_EvalCode:PyCodeObject*:co:0: +PyEval_EvalCode:PyObject*:co:0: PyEval_EvalCode:PyObject*:globals:0: PyEval_EvalCode:PyObject*:locals:0: -PyException_GetTraceback:PyObject*::+1: +PyEval_EvalCodeEx:PyObject*::+1: +PyEval_EvalCodeEx:PyObject*:co:0: +PyEval_EvalCodeEx:PyObject*:globals:0: +PyEval_EvalCodeEx:PyObject*:locals:0: +PyEval_EvalCodeEx:PyObject*const*:args:: +PyEval_EvalCodeEx:int:argcount:: +PyEval_EvalCodeEx:PyObject*const*:kws:: +PyEval_EvalCodeEx:int:kwcount:: +PyEval_EvalCodeEx:PyObject*const*:defs:: +PyEval_EvalCodeEx:int:defcount:: +PyEval_EvalCodeEx:PyObject*:kwdefs:0: +PyEval_EvalCodeEx:PyObject*:closure:0: -PyFile_AsFile:FILE*::: -PyFile_AsFile:PyFileObject*:p:0: +PyEval_EvalFrame:PyObject*::+1: +PyEval_EvalFrame:PyFrameObject*:f:0: -PyFile_Check:int::: -PyFile_Check:PyObject*:p:0: +PyEval_EvalFrameEx:PyObject*::+1: +PyEval_EvalFrameEx:PyFrameObject*:f:0: +PyEval_EvalFrameEx:int:throwflag:: -PyFile_FromFile:PyObject*::+1: -PyFile_FromFile:FILE*:fp:: -PyFile_FromFile:const char*:name:: -PyFile_FromFile:const char*:mode:: -PyFile_FromFile:int(*:close):: +PyEval_MergeCompilerFlags:int::: +PyEval_MergeCompilerFlags:PyCompilerFlags*:cf:: -PyFile_FromFileEx:PyObject*::+1: -PyFile_FromFileEx:FILE*:fp:: -PyFile_FromFileEx:const char*:name:: -PyFile_FromFileEx:const char*:mode:: -PyFile_FromFileEx:int(*:close):: -PyFile_FromFileEx:int:buffering:: -PyFile_FromFileEx:const char*:encoding:: -PyFile_FromFileEx:const char*:newline:: +PyException_GetCause:PyObject*::+1: +PyException_GetCause:PyObject*:ex:0: -PyFile_FromString:PyObject*::+1: -PyFile_FromString:const char*:name:: -PyFile_FromString:const char*:mode:: +PyException_GetContext:PyObject*::+1: +PyException_GetContext:PyObject*:ex:0: + +PyException_GetTraceback:PyObject*::+1: +PyException_GetTraceback:PyObject*:ex:0: + +PyException_SetCause:void::: +PyException_SetCause:PyObject*:ex:0: +PyException_SetCause:PyObject*:cause:+1: + +PyException_SetContext:void::: +PyException_SetContext:PyObject*:ex:0: +PyException_SetContext:PyObject*:ctx:+1: + +PyException_SetTraceback:int::: +PyException_SetTraceback:PyObject*:ex:0: +PyException_SetTraceback:PyObject*:tb:+1: + +PyFile_FromFd:PyObject*::+1: +PyFile_FromFd:int:fd:: +PyFile_FromFd:const char*:name:: +PyFile_FromFd:const char*:mode:: +PyFile_FromFd:int:buffering:: +PyFile_FromFd:const char*:encoding:: +PyFile_FromFd:const char*:errors:: +PyFile_FromFd:const char*:newline:: +PyFile_FromFd:int:closefd:: PyFile_GetLine:PyObject*::+1: -PyFile_GetLine:PyObject*:p:: +PyFile_GetLine:PyObject*:p:0: PyFile_GetLine:int:n:: -PyFile_Name:PyObject*::0: -PyFile_Name:PyObject*:p:0: - -PyFile_SetBufSize:void::: -PyFile_SetBufSize:PyFileObject*:p:0: -PyFile_SetBufSize:int:n:: - -PyFile_SoftSpace:int::: -PyFile_SoftSpace:PyFileObject*:p:0: -PyFile_SoftSpace:int:newflag:: - PyFile_WriteObject:int::: PyFile_WriteObject:PyObject*:obj:0: -PyFile_WriteObject:PyFileObject*:p:0: +PyFile_WriteObject:PyObject*:p:0: PyFile_WriteObject:int:flags:: PyFile_WriteString:int::: PyFile_WriteString:const char*:s:: -PyFile_WriteString:PyFileObject*:p:0: +PyFile_WriteString:PyObject*:p:0: PyFile_WriteString:int:flags:: PyFloat_AS_DOUBLE:double::: @@ -500,15 +854,33 @@ PyFloat_AsDouble:PyObject*:pyfloat:0: PyFloat_Check:int::: PyFloat_Check:PyObject*:p:0: +PyFloat_CheckExact:int::: +PyFloat_CheckExact:PyObject*:p:0: + PyFloat_FromDouble:PyObject*::+1: PyFloat_FromDouble:double:v:: PyFloat_FromString:PyObject*::+1: PyFloat_FromString:PyObject*:str:0: +PyFloat_GetInfo:PyObject*::+1: +PyFloat_GetInfo::void:: + +PyFrozenSet_Check:int::: +PyFrozenSet_Check:PyObject*:p:0: + +PyFrozenSet_CheckExact:int::: +PyFrozenSet_CheckExact:PyObject*:p:0: + PyFrozenSet_New:PyObject*::+1: PyFrozenSet_New:PyObject*:iterable:0: +PyFunction_Check:int::: +PyFunction_Check:PyObject*:o:0: + +PyFunction_GetAnnotations:PyObject*::0: +PyFunction_GetAnnotations:PyObject*:op:0: + PyFunction_GetClosure:PyObject*::0: PyFunction_GetClosure:PyObject*:op:0: @@ -533,6 +905,10 @@ PyFunction_NewWithQualName:PyObject*:code:+1: PyFunction_NewWithQualName:PyObject*:globals:+1: PyFunction_NewWithQualName:PyObject*:qualname:+1: +PyFunction_SetAnnotations:int::: +PyFunction_SetAnnotations:PyObject*:op:0: +PyFunction_SetAnnotations:PyObject*:annotations:+1: + PyFunction_SetClosure:int::: PyFunction_SetClosure:PyObject*:op:0: PyFunction_SetClosure:PyObject*:closure:+1: @@ -541,34 +917,34 @@ PyFunction_SetDefaults:int::: PyFunction_SetDefaults:PyObject*:op:0: PyFunction_SetDefaults:PyObject*:defaults:+1: +PyGen_Check:int::: +PyGen_Check:PyObject*:ob:0: + +PyGen_CheckExact:int::: +PyGen_CheckExact:PyObject*:ob:0: + PyGen_New:PyObject*::+1: PyGen_New:PyFrameObject*:frame:0: PyGen_NewWithQualName:PyObject*::+1: PyGen_NewWithQualName:PyFrameObject*:frame:0: +PyGen_NewWithQualName:PyObject*:name:0: +PyGen_NewWithQualName:PyObject*:qualname:0: + +PyCoro_CheckExact:int::: +PyCoro_CheckExact:PyObject*:ob:0: PyCoro_New:PyObject*::+1: PyCoro_New:PyFrameObject*:frame:0: - -Py_InitModule:PyObject*::0: -Py_InitModule:const char*:name:: -Py_InitModule:PyMethodDef[]:methods:: - -Py_InitModule3:PyObject*::0: -Py_InitModule3:const char*:name:: -Py_InitModule3:PyMethodDef[]:methods:: -Py_InitModule3:const char*:doc:: - -Py_InitModule4:PyObject*::0: -Py_InitModule4:const char*:name:: -Py_InitModule4:PyMethodDef[]:methods:: -Py_InitModule4:const char*:doc:: -Py_InitModule4:PyObject*:self:: -Py_InitModule4:int:apiver::usually provided by Py_InitModule or Py_InitModule3 +PyCoro_New:PyObject*:name:0: +PyCoro_New:PyObject*:qualname:0: PyImport_AddModule:PyObject*::0:reference borrowed from sys.modules PyImport_AddModule:const char*:name:: +PyImport_AddModuleObject:PyObject*::0:reference borrowed from sys.modules +PyImport_AddModuleObject:PyObject*:name:0: + PyImport_Cleanup:void::: PyImport_ExecCodeModule:PyObject*::+1: @@ -580,6 +956,21 @@ PyImport_ExecCodeModuleEx:const char*:name:: PyImport_ExecCodeModuleEx:PyObject*:co:0: PyImport_ExecCodeModuleEx:const char*:pathname:: +PyImport_ExecCodeModuleObject:PyObject*::+1: +PyImport_ExecCodeModuleObject:const char*:name:: +PyImport_ExecCodeModuleObject:PyObject*:co:0: +PyImport_ExecCodeModuleObject:PyObject*:pathname:0: +PyImport_ExecCodeModuleObject:PyObject*:cpathname:0: + +PyImport_ExecCodeModuleWithPathnames:PyObject*::+1: +PyImport_ExecCodeModuleWithPathnames:const char*:name:: +PyImport_ExecCodeModuleWithPathnames:PyObject*:co:0: +PyImport_ExecCodeModuleWithPathnames:const char*:pathname:: +PyImport_ExecCodeModuleWithPathnames:const char*:cpathname:: + +PyImport_GetImporter:PyObject*::+1: +PyImport_GetImporter:PyObject*:path:0: + PyImport_GetMagicNumber:long::: PyImport_GetModule:PyObject*::+1: @@ -593,6 +984,9 @@ PyImport_Import:PyObject*:name:0: PyImport_ImportFrozenModule:int::: PyImport_ImportFrozenModule:const char*::: +PyImport_ImportFrozenModuleObject:int::: +PyImport_ImportFrozenModuleObject:PyObject*::+1: + PyImport_ImportModule:PyObject*::+1: PyImport_ImportModule:const char*:name:: @@ -609,39 +1003,33 @@ PyImport_ImportModuleLevel:PyObject*:locals:0:??? PyImport_ImportModuleLevel:PyObject*:fromlist:0:??? PyImport_ImportModuleLevel:int:level:: -PyImport_ReloadModule:PyObject*::+1: -PyImport_ReloadModule:PyObject*:m:0: - -PyInstance_New:PyObject*::+1: -PyInstance_New:PyObject*:klass:+1: -PyInstance_New:PyObject*:arg:0: -PyInstance_New:PyObject*:kw:0: - -PyInstance_NewRaw:PyObject*::+1: -PyInstance_NewRaw:PyObject*:klass:+1: -PyInstance_NewRaw:PyObject*:dict:+1: +PyImport_ImportModuleLevelObject:PyObject*::+1: +PyImport_ImportModuleLevelObject:PyObject*:name:0: +PyImport_ImportModuleLevelObject:PyObject*:globals:0:??? +PyImport_ImportModuleLevelObject:PyObject*:locals:0:??? +PyImport_ImportModuleLevelObject:PyObject*:fromlist:0:??? +PyImport_ImportModuleLevelObject:int:level:: -PyInt_AS_LONG:long::: -PyInt_AS_LONG:PyIntObject*:io:0: +PyImport_ImportModuleNoBlock:PyObject*::+1: +PyImport_ImportModuleNoBlock:const char*:name:: -PyInt_AsLong:long::: -PyInt_AsLong:PyObject*:io:0: +PyImport_ReloadModule:PyObject*::+1: +PyImport_ReloadModule:PyObject*:m:0: -PyInt_Check:int::: -PyInt_Check:PyObject*:op:0: +PyIndex_Check:int::: +PyIndex_Check:PyObject*:o:0: -PyInt_FromLong:PyObject*::+1: -PyInt_FromLong:long:ival:: +PyInstanceMethod_Check:int::: +PyInstanceMethod_Check:PyObject*:o:0: -PyInt_FromString:PyObject*::+1: -PyInt_FromString:char*:str:0: -PyInt_FromString:char**:pend:0: -PyInt_FromString:int:base:0: +PyInstanceMethod_Function:PyObject*::0: +PyInstanceMethod_Function:PyObject*:im:0: -PyInt_FromSsize_t:PyObject*::+1: -PyInt_FromSsize_t:Py_ssize_t:ival:: +PyInstanceMethod_GET_FUNCTION:PyObject*::0: +PyInstanceMethod_GET_FUNCTION:PyObject*:im:0: -PyInt_GetMax:long::: +PyInstanceMethod_New:PyObject*::+1: +PyInstanceMethod_New:PyObject*:func:0: PyInterpreterState_Clear:void::: PyInterpreterState_Clear:PyInterpreterState*:interp:: @@ -654,7 +1042,8 @@ PyInterpreterState_GetID:PyInterpreterState*:interp:: PyInterpreterState_New:PyInterpreterState*::: -PyIter_Check:int:o:0: +PyIter_Check:int::: +PyIter_Check:PyObject*:o:0: PyIter_Next:PyObject*::+1: PyIter_Next:PyObject*:o:0: @@ -669,50 +1058,53 @@ PyList_AsTuple:PyObject*:list:0: PyList_Check:int::: PyList_Check:PyObject*:p:0: +PyList_CheckExact:int::: +PyList_CheckExact:PyObject*:p:0: + PyList_GET_ITEM:PyObject*::0: PyList_GET_ITEM:PyObject*:list:0: -PyList_GET_ITEM:int:i:0: +PyList_GET_ITEM:Py_ssize_t:i:: -PyList_GET_SIZE:int::: +PyList_GET_SIZE:Py_ssize_t::: PyList_GET_SIZE:PyObject*:list:0: PyList_GetItem:PyObject*::0: PyList_GetItem:PyObject*:list:0: -PyList_GetItem:int:index:: +PyList_GetItem:Py_ssize_t:index:: PyList_GetSlice:PyObject*::+1: PyList_GetSlice:PyObject*:list:0: -PyList_GetSlice:int:low:: -PyList_GetSlice:int:high:: +PyList_GetSlice:Py_ssize_t:low:: +PyList_GetSlice:Py_ssize_t:high:: PyList_Insert:int::: PyList_Insert:PyObject*:list:0: -PyList_Insert:int:index:: +PyList_Insert:Py_ssize_t:index:: PyList_Insert:PyObject*:item:+1: PyList_New:PyObject*::+1: -PyList_New:int:len:: +PyList_New:Py_ssize_t:len:: PyList_Reverse:int::: PyList_Reverse:PyObject*:list:0: PyList_SET_ITEM:void::: PyList_SET_ITEM:PyObject*:list:0: -PyList_SET_ITEM:int:i:: +PyList_SET_ITEM:Py_ssize_t:i:: PyList_SET_ITEM:PyObject*:o:0: PyList_SetItem:int::: PyList_SetItem:PyObject*:list:0: -PyList_SetItem:int:index:: +PyList_SetItem:Py_ssize_t:index:: PyList_SetItem:PyObject*:item:0: PyList_SetSlice:int::: PyList_SetSlice:PyObject*:list:0: -PyList_SetSlice:int:low:: -PyList_SetSlice:int:high:: +PyList_SetSlice:Py_ssize_t:low:: +PyList_SetSlice:Py_ssize_t:high:: PyList_SetSlice:PyObject*:itemlist:0:but increfs its elements? -PyList_Size:int::: +PyList_Size:Py_ssize_t::: PyList_Size:PyObject*:list:0: PyList_Sort:int::: @@ -724,12 +1116,44 @@ PyLong_AsDouble:PyObject*:pylong:0: PyLong_AsLong:long::: PyLong_AsLong:PyObject*:pylong:0: +PyLong_AsLongAndOverflow:long::: +PyLong_AsLongAndOverflow:PyObject*:obj:0: +PyLong_AsLongAndOverflow:int*:overflow:: + +PyLong_AsLongLong:long long::: +PyLong_AsLongLong:PyObject*:obj:0: + +PyLong_AsLongLongAndOverflow:long long::: +PyLong_AsLongLongAndOverflow:PyObject*:obj:0: +PyLong_AsLongLongAndOverflow:int*:overflow:: + +PyLong_AsSize_t:size_t::: +PyLong_AsSize_t:PyObject*:pylong:0: + +PyLong_AsSsize_t:Py_ssize_t::: +PyLong_AsSsize_t:PyObject*:pylong:0: + PyLong_AsUnsignedLong:unsigned long::: PyLong_AsUnsignedLong:PyObject*:pylong:0: +PyLong_AsUnsignedLongLong:unsigned long long::: +PyLong_AsUnsignedLongLong:PyObject*:pylong:0: + +PyLong_AsUnsignedLongMask:unsigned long::: +PyLong_AsUnsignedLongMask:PyObject*:obj:0: + +PyLong_AsUnsignedLongLongMask:unsigned long long::: +PyLong_AsUnsignedLongLongMask:PyObject*:obj:0: + +PyLong_AsVoidPtr:void*::: +PyLong_AsVoidPtr:PyObject*:pylong:0: + PyLong_Check:int::: PyLong_Check:PyObject*:p:0: +PyLong_CheckExact:int::: +PyLong_CheckExact:PyObject*:p:0: + PyLong_FromDouble:PyObject*::+1: PyLong_FromDouble:double:v:: @@ -742,16 +1166,26 @@ PyLong_FromLongLong:long long:v:: PyLong_FromUnsignedLongLong:PyObject*::+1: PyLong_FromUnsignedLongLong:unsigned long long:v:: +PyLong_FromSize_t:PyObject*::+1: +PyLong_FromSize_t:size_t:v:: + +PyLong_FromSsize_t:PyObject*::+1: +PyLong_FromSsize_t:Py_ssize_t:v:: + PyLong_FromString:PyObject*::+1: PyLong_FromString:const char*:str:: PyLong_FromString:char**:pend:: PyLong_FromString:int:base:: PyLong_FromUnicode:PyObject*::+1: -PyLong_FromUnicode:Py_UNICODE:u:: -PyLong_FromUnicode:int:length:: +PyLong_FromUnicode:Py_UNICODE*:u:: +PyLong_FromUnicode:Py_ssize_t:length:: PyLong_FromUnicode:int:base:: +PyLong_FromUnicodeObject:PyObject*::+1: +PyLong_FromUnicodeObject:PyObject*:u:0: +PyLong_FromUnicodeObject:int:base:: + PyLong_FromUnsignedLong:PyObject*::+1: PyLong_FromUnsignedLong:unsignedlong:v:: @@ -787,7 +1221,7 @@ PyMapping_Items:PyObject*:o:0: PyMapping_Keys:PyObject*::+1: PyMapping_Keys:PyObject*:o:0: -PyMapping_Length:int::: +PyMapping_Length:Py_ssize_t::: PyMapping_Length:PyObject*:o:0: PyMapping_SetItemString:int::: @@ -795,6 +1229,9 @@ PyMapping_SetItemString:PyObject*:o:0: PyMapping_SetItemString:const char*:key:: PyMapping_SetItemString:PyObject*:v:+1: +PyMapping_Size:Py_ssize_t::: +PyMapping_Size:PyObject*:o:0: + PyMapping_Values:PyObject*::+1: PyMapping_Values:PyObject*:o:0: @@ -806,20 +1243,43 @@ PyMarshal_ReadObjectFromFile:FILE*:file:: PyMarshal_ReadObjectFromString:PyObject*::+1: PyMarshal_ReadObjectFromString:const char*:string:: -PyMarshal_ReadObjectFromString:int:len:: +PyMarshal_ReadObjectFromString:Py_ssize_t:len:: PyMarshal_WriteObjectToString:PyObject*::+1: PyMarshal_WriteObjectToString:PyObject*:value:0: +PyMarshal_WriteObjectToString:int:version:: + +PyMemoryView_Check:int::: +PyMemoryView_Check:PyObject*:obj:0: + +PyMemoryView_FromBuffer:PyObject*::+1: +PyMemoryView_FromBuffer:Py_buffer*:view:: + +PyMemoryView_FromMemory:PyObject*::+1: +PyMemoryView_FromMemory:char*:mem:: +PyMemoryView_FromMemory:Py_ssize_t:size:: +PyMemoryView_FromMemory:int:flags:: + +PyMemoryView_FromObject:PyObject*::+1: +PyMemoryView_FromObject:PyObject*:obj:0: + +PyMemoryView_GET_BASE:Py_buffer*::: +PyMemoryView_GET_BASE:PyObject*:mview:0: + +PyMemoryView_GET_BUFFER:Py_buffer*::: +PyMemoryView_GET_BUFFER:PyObject*:mview:0: -PyMethod_Class:PyObject*::0: -PyMethod_Class:PyObject*:im:0: +PyMemoryView_GetContiguous:PyObject*::+1: +PyMemoryView_GetContiguous:PyObject*:obj:0: +PyMemoryView_GetContiguous:int:buffertype:: +PyMemoryView_GetContiguous:char:order:: + +PyMethod_Check:int::: +PyMethod_Check:PyObject*:o:0: PyMethod_Function:PyObject*::0: PyMethod_Function:PyObject*:im:0: -PyMethod_GET_CLASS:PyObject*::0: -PyMethod_GET_CLASS:PyObject*:im:0: - PyMethod_GET_FUNCTION:PyObject*::0: PyMethod_GET_FUNCTION:PyObject*:im:0: @@ -834,18 +1294,93 @@ PyMethod_New:PyObject*:class:0: PyMethod_Self:PyObject*::0: PyMethod_Self:PyObject*:im:0: +PyModule_AddFunctions:int::: +PyModule_AddFunctions:PyObject*:module:0: +PyModule_AddFunctions:PyMethodDef*:functions:: + +PyModule_AddIntConstant:int::: +PyModule_AddIntConstant:PyObject*:module:0: +PyModule_AddIntConstant:const char*:name:: +PyModule_AddIntConstant:long:value:: + +PyModule_AddIntMacro:int::: +PyModule_AddIntMacro:PyObject*:module:0: +PyModule_AddIntMacro::macro:: + +PyModule_AddObject:int::: +PyModule_AddObject:PyObject*:module:0: +PyModule_AddObject:const char*:name:: +PyModule_AddObject:PyObject*:value:+1: + +PyModule_AddStringConstant:int::: +PyModule_AddStringConstant:PyObject*:module:0: +PyModule_AddStringConstant:const char*:name:: +PyModule_AddStringConstant:const char*:value:: + +PyModule_AddStringMacro:int::: +PyModule_AddStringMacro:PyObject*:module:0: +PyModule_AddStringMacro::macro:: + +PyModule_Check:int::: +PyModule_Check:PyObject*:p:0: + +PyModule_CheckExact:int::: +PyModule_CheckExact:PyObject*:p:0: + +PyModule_Create:PyObject*::+1: +PyModule_Create:PyModuleDef*:def:: + +PyModule_Create2:PyObject*::+1: +PyModule_Create2:PyModuleDef*:def:: +PyModule_Create2:int:module_api_version:: + +PyModule_ExecDef:int::: +PyModule_ExecDef:PyObject*:module:0: +PyModule_ExecDef:PyModuleDef*:def:: + +PyModule_FromDefAndSpec:PyObject*::+1: +PyModule_FromDefAndSpec:PyModuleDef*:def:: +PyModule_FromDefAndSpec:PyObject*:spec:0: + +PyModule_FromDefAndSpec2:PyObject*::+1: +PyModule_FromDefAndSpec2:PyModuleDef*:def:: +PyModule_FromDefAndSpec2:PyObject*:spec:0: +PyModule_FromDefAndSpec2:int:module_api_version:: + +PyModule_GetDef:PyModuleDef*::0: +PyModule_GetDef:PyObject*:module:0: + PyModule_GetDict:PyObject*::0: -PyModule_GetDict::PyObject* module:0: +PyModule_GetDict:PyObject*:module:0: PyModule_GetFilename:const char*::: PyModule_GetFilename:PyObject*:module:0: +PyModule_GetFilenameObject:PyObject*::+1: +PyModule_GetFilenameObject:PyObject*:module:0: + PyModule_GetName:const char*::: PyModule_GetName:PyObject*:module:0: +PyModule_GetNameObject:PyObject*::+1: +PyModule_GetNameObject:PyObject*:module:0: + +PyModule_GetState:void*::: +PyModule_GetState:PyObject*:module:0: + PyModule_New:PyObject*::+1: PyModule_New::char* name:: +PyModule_NewObject:PyObject*::+1: +PyModule_NewObject:PyObject*:name:+1: + +PyModule_SetDocString:int::: +PyModule_SetDocString:PyObject*:module:0: +PyModule_SetDocString:const char*:docstring:: + +PyModuleDef_Init:PyObject*::0: +PyModuleDef_Init:PyModuleDef*:def:0: + PyNumber_Absolute:PyObject*::+1: PyNumber_Absolute:PyObject*:o:0: @@ -857,12 +1392,12 @@ PyNumber_And:PyObject*::+1: PyNumber_And:PyObject*:o1:0: PyNumber_And:PyObject*:o2:0: -PyNumber_Check:PyObject*:o:0: -PyNumber_Check:int::: +PyNumber_AsSsize_t:Py_ssize_t::: +PyNumber_AsSsize_t:PyObject*:o:0: +PyNumber_AsSsize_t:PyObject*:exc:0: -PyNumber_Divide:PyObject*::+1: -PyNumber_Divide:PyObject*:o1:0: -PyNumber_Divide:PyObject*:o2:0: +PyNumber_Check:int::: +PyNumber_Check:PyObject*:o:0: PyNumber_Divmod:PyObject*::+1: PyNumber_Divmod:PyObject*:o1:0: @@ -875,6 +1410,9 @@ PyNumber_FloorDivide:PyObject*::+1: PyNumber_FloorDivide:PyObject*:v:0: PyNumber_FloorDivide:PyObject*:w:0: +PyNumber_Index:PyObject*::+1: +PyNumber_Index:PyObject*:o:0: + PyNumber_InPlaceAdd:PyObject*::+1: PyNumber_InPlaceAdd:PyObject*:v:0: PyNumber_InPlaceAdd:PyObject*:w:0: @@ -883,10 +1421,6 @@ PyNumber_InPlaceAnd:PyObject*::+1: PyNumber_InPlaceAnd:PyObject*:v:0: PyNumber_InPlaceAnd:PyObject*:w:0: -PyNumber_InPlaceDivide:PyObject*::+1: -PyNumber_InPlaceDivide:PyObject*:v:0: -PyNumber_InPlaceDivide:PyObject*:w:0: - PyNumber_InPlaceFloorDivide:PyObject*::+1: PyNumber_InPlaceFloorDivide:PyObject*:v:0: PyNumber_InPlaceFloorDivide:PyObject*:w:0: @@ -895,6 +1429,10 @@ PyNumber_InPlaceLshift:PyObject*::+1: PyNumber_InPlaceLshift:PyObject*:v:0: PyNumber_InPlaceLshift:PyObject*:w:0: +PyNumber_InPlaceMatrixMultiply:PyObject*::+1: +PyNumber_InPlaceMatrixMultiply:PyObject*:o1:0: +PyNumber_InPlaceMatrixMultiply:PyObject*:o2:0: + PyNumber_InPlaceMultiply:PyObject*::+1: PyNumber_InPlaceMultiply:PyObject*:v:0: PyNumber_InPlaceMultiply:PyObject*:w:0: @@ -938,6 +1476,10 @@ PyNumber_Lshift:PyObject*::+1: PyNumber_Lshift:PyObject*:o1:0: PyNumber_Lshift:PyObject*:o2:0: +PyNumber_MatrixMultiply:PyObject*::+1: +PyNumber_MatrixMultiply:PyObject*:o1:0: +PyNumber_MatrixMultiply:PyObject*:o2:0: + PyNumber_Multiply:PyObject*::+1: PyNumber_Multiply:PyObject*:o1:0: PyNumber_Multiply:PyObject*:o2:0: @@ -969,6 +1511,10 @@ PyNumber_Subtract:PyObject*::+1: PyNumber_Subtract:PyObject*:o1:0: PyNumber_Subtract:PyObject*:o2:0: +PyNumber_ToBase:PyObject*::+1: +PyNumber_ToBase:PyObject*:n:0: +PyNumber_ToBase:int:base:: + PyNumber_TrueDivide:PyObject*::+1: PyNumber_TrueDivide:PyObject*:v:0: PyNumber_TrueDivide:PyObject*:w:0: @@ -991,6 +1537,27 @@ PyOS_BeforeFork:void::: PyOS_FSPath:PyObject*::+1: PyOS_FSPath:PyObject*:path:0: +PyObject_ASCII:PyObject*::+1: +PyObject_ASCII:PyObject*:o:0: + +PyObject_AsCharBuffer:int::: +PyObject_AsCharBuffer:PyObject*:obj:0: +PyObject_AsCharBuffer:const char**:buffer:: +PyObject_AsCharBuffer:Py_ssize_t*:buffer_len:: + +PyObject_AsReadBuffer:int::: +PyObject_AsReadBuffer:PyObject*:obj:0: +PyObject_AsReadBuffer:const void**:buffer:: +PyObject_AsReadBuffer:Py_ssize_t*:buffer_len:: + +PyObject_AsWriteBuffer:int::: +PyObject_AsWriteBuffer:PyObject*:obj:0: +PyObject_AsWriteBuffer:void**:buffer:: +PyObject_AsWriteBuffer:Py_ssize_t*:buffer_len:: + +PyObject_Bytes:PyObject*::+1: +PyObject_Bytes:PyObject*:o:0: + PyObject_Call:PyObject*::+1: PyObject_Call:PyObject*:callable_object:0: PyObject_Call:PyObject*:args:0: @@ -1020,14 +1587,11 @@ PyObject_CallObject:PyObject*::+1: PyObject_CallObject:PyObject*:callable_object:0: PyObject_CallObject:PyObject*:args:0: -PyObject_Cmp:int::: -PyObject_Cmp:PyObject*:o1:0: -PyObject_Cmp:PyObject*:o2:0: -PyObject_Cmp:int*:result:: +PyObject_CheckBuffer:int::: +PyObject_CheckBuffer:PyObject*:obj:0: -PyObject_Compare:int::: -PyObject_Compare:PyObject*:o1:0: -PyObject_Compare:PyObject*:o2:0: +PyObject_CheckReadBuffer:int::: +PyObject_CheckReadBuffer:PyObject*:o:0: PyObject_DelAttr:int::: PyObject_DelAttr:PyObject*:o:0: @@ -1044,6 +1608,46 @@ PyObject_DelItem:PyObject*:key:0: PyObject_Dir:PyObject*::+1: PyObject_Dir:PyObject*:o:0: +PyObject_GC_Del:void::: +PyObject_GC_Del:void*:op:: + +PyObject_GC_New:TYPE*::+1: +PyObject_GC_New::TYPE:: +PyObject_GC_New:PyTypeObject*:type:0: + +PyObject_GC_NewVar:TYPE*::+1: +PyObject_GC_NewVar::TYPE:: +PyObject_GC_NewVar:PyTypeObject*:type:0: +PyObject_GC_NewVar:Py_ssize_t:size:: + +PyObject_GC_Resize:TYPE*::0: +PyObject_GC_Resize::TYPE:: +PyObject_GC_Resize:PyVarObject*:op:0: +PyObject_GC_Resize:Py_ssize_t:newsize:: + +PyObject_GC_Track:void::: +PyObject_GC_Track:PyObject*:op:0: + +PyObject_GC_UnTrack:void::: +PyObject_GC_UnTrack:void*:op:: + +PyObject_GenericGetAttr:PyObject*::+1: +PyObject_GenericGetAttr:PyObject*:o:0: +PyObject_GenericGetAttr:PyObject*:name:0: + +PyObject_GenericGetDict:PyObject*::+1: +PyObject_GenericGetDict:PyObject*:o:0: +PyObject_GenericGetDict:void*:context:: + +PyObject_GenericSetAttr:int::: +PyObject_GenericSetAttr:PyObject*:o:0: +PyObject_GenericSetAttr:PyObject*:name:0: +PyObject_GenericSetAttr:PyObject*:value:+1: + +PyObject_GenericSetDict:int::: +PyObject_GenericSetDict:PyObject*:o:+1: +PyObject_GenericSetDict:void*:context:: + PyObject_GetAttr:PyObject*::+1: PyObject_GetAttr:PyObject*:o:0: PyObject_GetAttr:PyObject*:attr_name:0: @@ -1052,6 +1656,11 @@ PyObject_GetAttrString:PyObject*::+1: PyObject_GetAttrString:PyObject*:o:0: PyObject_GetAttrString:const char*:attr_name:: +PyObject_GetBuffer:int::: +PyObject_GetBuffer:PyObject*:exporter:0: +PyObject_GetBuffer:Py_buffer*:view:: +PyObject_GetBuffer:int:flags:: + PyObject_GetItem:PyObject*::+1: PyObject_GetItem:PyObject*:o:0: PyObject_GetItem:PyObject*:key:0: @@ -1065,30 +1674,59 @@ PyObject_HasAttr:PyObject*:attr_name:0: PyObject_HasAttrString:int::: PyObject_HasAttrString:PyObject*:o:0: -PyObject_HasAttrString:const char*:attr_name:0: +PyObject_HasAttrString:const char*:attr_name:: PyObject_Hash:int::: PyObject_Hash:PyObject*:o:0: +PyObject_HashNotImplemented:Py_hash_t::: +PyObject_HashNotImplemented:PyObject*:o:0: + +PyObject_IsInstance:int::: +PyObject_IsInstance:PyObject*:inst:0: +PyObject_IsInstance:PyObject*:cls:0: + +PyObject_IsSubclass:int::: +PyObject_IsSubclass:PyObject*:derived:0: +PyObject_IsSubclass:PyObject*:cls:0: + PyObject_IsTrue:int::: PyObject_IsTrue:PyObject*:o:0: PyObject_Init:PyObject*::0: PyObject_Init:PyObject*:op:0: +PyObject_Init:PyTypeObject*:type:0: PyObject_InitVar:PyVarObject*::0: PyObject_InitVar:PyVarObject*:op:0: -PyObject_Length:int::: +PyObject_Length:Py_ssize_t::: PyObject_Length:PyObject*:o:0: +PyObject_LengthHint:Py_ssize_t::: +PyObject_LengthHint:PyObject*:o:0: +PyObject_LengthHint:Py_ssize_t:default:: + PyObject_NEW:PyObject*::+1: +PyObject_NEW::TYPE:: +PyObject_NEW:PyTypeObject*:type:0: PyObject_New:PyObject*::+1: +PyObject_New::TYPE:: +PyObject_New:PyTypeObject*:type:0: PyObject_NEW_VAR:PyObject*::+1: +PyObject_NEW_VAR::TYPE:: +PyObject_NEW_VAR:PyTypeObject*:type:0: +PyObject_NEW_VAR:Py_ssize_t:size:: PyObject_NewVar:PyObject*::+1: +PyObject_NewVar::TYPE:: +PyObject_NewVar:PyTypeObject*:type:0: +PyObject_NewVar:Py_ssize_t:size:: + +PyObject_Not:int::: +PyObject_Not:PyObject*:o:0: PyObject_Print:int::: PyObject_Print:PyObject*:o:0: @@ -1123,28 +1761,65 @@ PyObject_SetItem:PyObject*:o:0: PyObject_SetItem:PyObject*:key:0: PyObject_SetItem:PyObject*:v:+1: +PyObject_Size:Py_ssize_t::: +PyObject_Size:PyObject*:o:0: + PyObject_Str:PyObject*::+1: PyObject_Str:PyObject*:o:0: PyObject_Type:PyObject*::+1: PyObject_Type:PyObject*:o:0: -PyObject_Unicode:PyObject*::+1: -PyObject_Unicode:PyObject*:o:0: +PyObject_TypeCheck:int::: +PyObject_TypeCheck:PyObject*:o:0: +PyObject_TypeCheck:PyTypeObject*:type:0: PyParser_SimpleParseFile:struct _node*::: PyParser_SimpleParseFile:FILE*:fp:: PyParser_SimpleParseFile:const char*:filename:: PyParser_SimpleParseFile:int:start:: +PyParser_SimpleParseFileFlags:struct _node*::: +PyParser_SimpleParseFileFlags:FILE*:fp:: +PyParser_SimpleParseFileFlags:const char*:filename:: +PyParser_SimpleParseFileFlags:int:start:: +PyParser_SimpleParseFileFlags:int:flags:: + PyParser_SimpleParseString:struct _node*::: PyParser_SimpleParseString:const char*:str:: PyParser_SimpleParseString:int:start:: +PyParser_SimpleParseStringFlags:struct _node*::: +PyParser_SimpleParseStringFlags:const char*:str:: +PyParser_SimpleParseStringFlags:int:start:: +PyParser_SimpleParseStringFlags:int:flags:: + +PyParser_SimpleParseStringFlagsFilename:struct _node*::: +PyParser_SimpleParseStringFlagsFilename:const char*:str:: +PyParser_SimpleParseStringFlagsFilename:const char*:filename:: +PyParser_SimpleParseStringFlagsFilename:int:start:: +PyParser_SimpleParseStringFlagsFilename:int:flags:: + PyRun_AnyFile:int::: PyRun_AnyFile:FILE*:fp:: PyRun_AnyFile:const char*:filename:: +PyRun_AnyFileFlags:int::: +PyRun_AnyFileFlags:FILE*:fp:: +PyRun_AnyFileFlags:const char*:filename:: +PyRun_AnyFileFlags:PyCompilerFlags*:flags:: + +PyRun_AnyFileEx:int::: +PyRun_AnyFileEx:FILE*:fp:: +PyRun_AnyFileEx:const char*:filename:: +PyRun_AnyFileEx:int:closeit:: + +PyRun_AnyFileExFlags:int::: +PyRun_AnyFileExFlags:FILE*:fp:: +PyRun_AnyFileExFlags:const char*:filename:: +PyRun_AnyFileExFlags:int:closeit:: +PyRun_AnyFileExFlags:PyCompilerFlags*:flags:: + PyRun_File:PyObject*::+1:??? -- same as eval_code2() PyRun_File:FILE*:fp:: PyRun_File:const char*:filename:: @@ -1181,17 +1856,42 @@ PyRun_InteractiveLoop:int::: PyRun_InteractiveLoop:FILE*:fp:: PyRun_InteractiveLoop:const char*:filename:: +PyRun_InteractiveLoopFlags:int::: +PyRun_InteractiveLoopFlags:FILE*:fp:: +PyRun_InteractiveLoopFlags:const char*:filename:: +PyRun_InteractiveLoopFlags:PyCompilerFlags*:flags:: + PyRun_InteractiveOne:int::: PyRun_InteractiveOne:FILE*:fp:: PyRun_InteractiveOne:const char*:filename:: +PyRun_InteractiveOneFlags:int::: +PyRun_InteractiveOneFlags:FILE*:fp:: +PyRun_InteractiveOneFlags:const char*:filename:: +PyRun_InteractiveOneFlags:PyCompilerFlags*:flags:: + PyRun_SimpleFile:int::: PyRun_SimpleFile:FILE*:fp:: PyRun_SimpleFile:const char*:filename:: +PyRun_SimpleFileEx:int::: +PyRun_SimpleFileEx:FILE*:fp:: +PyRun_SimpleFileEx:const char*:filename:: +PyRun_SimpleFileEx:int:closeit:: + +PyRun_SimpleFileExFlags:int::: +PyRun_SimpleFileExFlags:FILE*:fp:: +PyRun_SimpleFileExFlags:const char*:filename:: +PyRun_SimpleFileExFlags:int:closeit:: +PyRun_SimpleFileExFlags:PyCompilerFlags*:flags:: + PyRun_SimpleString:int::: PyRun_SimpleString:const char*:command:: +PyRun_SimpleStringFlags:int::: +PyRun_SimpleStringFlags:const char*:command:: +PyRun_SimpleStringFlags:PyCompilerFlags*:flags:: + PyRun_String:PyObject*::+1:??? -- same as eval_code2() PyRun_String:const char*:str:: PyRun_String:int:start:: @@ -1205,6 +1905,9 @@ PyRun_StringFlags:PyObject*:globals:0: PyRun_StringFlags:PyObject*:locals:0: PyRun_StringFlags:PyCompilerFlags*:flags:: +PySeqIter_Check:int::: +PySeqIter_Check::op:: + PySeqIter_New:PyObject*::+1: PySeqIter_New:PyObject*:seq:: @@ -1215,18 +1918,22 @@ PySequence_Concat:PyObject*::+1: PySequence_Concat:PyObject*:o1:0: PySequence_Concat:PyObject*:o2:0: -PySequence_Count:int::: +PySequence_Contains:int::: +PySequence_Contains:PyObject*:o:0: +PySequence_Contains:PyObject*:value:0: + +PySequence_Count:Py_ssize_t::: PySequence_Count:PyObject*:o:0: PySequence_Count:PyObject*:value:0: PySequence_DelItem:int::: PySequence_DelItem:PyObject*:o:0: -PySequence_DelItem:int:i:: +PySequence_DelItem:Py_ssize_t:i:: PySequence_DelSlice:int::: PySequence_DelSlice:PyObject*:o:0: -PySequence_DelSlice:int:i1:: -PySequence_DelSlice:int:i2:: +PySequence_DelSlice:Py_ssize_t:i1:: +PySequence_DelSlice:Py_ssize_t:i2:: PySequence_Fast:PyObject*::+1: PySequence_Fast:PyObject*:v:0: @@ -1234,22 +1941,28 @@ PySequence_Fast:const char*:m:: PySequence_Fast_GET_ITEM:PyObject*::0: PySequence_Fast_GET_ITEM:PyObject*:o:0: -PySequence_Fast_GET_ITEM:int:i:: +PySequence_Fast_GET_ITEM:Py_ssize_t:i:: + +PySequence_Fast_GET_SIZE:Py_ssize_t::: +PySequence_Fast_GET_SIZE:PyObject*:o:0: + +PySequence_Fast_ITEMS:PyObject**::: +PySequence_Fast_ITEMS:PyObject*:o:0: PySequence_GetItem:PyObject*::+1: PySequence_GetItem:PyObject*:o:0: -PySequence_GetItem:int:i:: +PySequence_GetItem:Py_ssize_t:i:: PySequence_GetSlice:PyObject*::+1: PySequence_GetSlice:PyObject*:o:0: -PySequence_GetSlice:int:i1:: -PySequence_GetSlice:int:i2:: +PySequence_GetSlice:Py_ssize_t:i1:: +PySequence_GetSlice:Py_ssize_t:i2:: PySequence_In:int::: PySequence_In:PyObject*:o:0: PySequence_In:PyObject*:value:0: -PySequence_Index:int::: +PySequence_Index:Py_ssize_t::: PySequence_Index:PyObject*:o:0: PySequence_Index:PyObject*:value:0: @@ -1263,22 +1976,25 @@ PySequence_InPlaceRepeat:PyObject*:o:0: PySequence_ITEM:PyObject*::+1: PySequence_ITEM:PyObject*:o:0: -PySequence_ITEM:int:i:: +PySequence_ITEM:Py_ssize_t:i:: PySequence_Repeat:PyObject*::+1: PySequence_Repeat:PyObject*:o:0: -PySequence_Repeat:int:count:: +PySequence_Repeat:Py_ssize_t:count:: PySequence_SetItem:int::: PySequence_SetItem:PyObject*:o:0: -PySequence_SetItem:int:i:: +PySequence_SetItem:Py_ssize_t:i:: PySequence_SetItem:PyObject*:v:+1: PySequence_SetSlice:int::: PySequence_SetSlice:PyObject*:o:0: -PySequence_SetSlice:int:i1:: -PySequence_SetSlice:int:i2:: -PySequence_SetSlice:PyObject*:v:+1: +PySequence_SetSlice:Py_ssize_t:i1:: +PySequence_SetSlice:Py_ssize_t:i2:: +PySequence_SetSlice:PyObject*:v:0: + +PySequence_Size:Py_ssize_t::: +PySequence_Size:PyObject*:o:0: PySequence_List:PyObject*::+1: PySequence_List:PyObject*:o:0: @@ -1286,9 +2002,15 @@ PySequence_List:PyObject*:o:0: PySequence_Tuple:PyObject*::+1: PySequence_Tuple:PyObject*:o:0: -PySet_Append:int::: -PySet_Append:PyObject*:set:0: -PySet_Append:PyObject*:key:+1: +PySet_Add:int::: +PySet_Add:PyObject*:set:0: +PySet_Add:PyObject*:key:+1: + +PySet_Check:int::: +PySet_Check:PyObject*:p:0: + +PySet_Clear:int::: +PySet_Clear:PyObject*:set:0: PySet_Contains:int::: PySet_Contains:PyObject*:anyset:0: @@ -1298,15 +2020,21 @@ PySet_Discard:int::: PySet_Discard:PyObject*:set:0: PySet_Discard:PyObject*:key:-1:no effect if key not found +PySet_GET_SIZE:Py_ssize_t::: +PySet_GET_SIZE:PyObject*:anyset:0: + PySet_New:PyObject*::+1: PySet_New:PyObject*:iterable:0: PySet_Pop:PyObject*::+1:or returns NULL and raises KeyError if set is empty PySet_Pop:PyObject*:set:0: -PySet_Size:int::: +PySet_Size:Py_ssize_t::: PySet_Size:PyObject*:anyset:0: +PySignal_SetWakeupFd:int::: +PySignal_SetWakeupFd:int:fd:: + PySlice_AdjustIndices:Py_ssize_t::: PySlice_AdjustIndices:Py_ssize_t:length:: PySlice_AdjustIndices:Py_ssize_t*:start:: @@ -1316,6 +2044,21 @@ PySlice_AdjustIndices:Py_ssize_t*:step:: PySlice_Check:int::: PySlice_Check:PyObject*:ob:0: +PySlice_GetIndices:int::: +PySlice_GetIndices:PyObject*:slice:0: +PySlice_GetIndices:Py_ssize_t:length:: +PySlice_GetIndices:Py_ssize_t*:start:: +PySlice_GetIndices:Py_ssize_t*:stop:: +PySlice_GetIndices:Py_ssize_t*:step:: + +PySlice_GetIndicesEx:int::: +PySlice_GetIndicesEx:PyObject*:slice:0: +PySlice_GetIndicesEx:Py_ssize_t:length:: +PySlice_GetIndicesEx:Py_ssize_t*:start:: +PySlice_GetIndicesEx:Py_ssize_t*:stop:: +PySlice_GetIndicesEx:Py_ssize_t*:step:: +PySlice_GetIndicesEx:Py_ssize_t*:slicelength:: + PySlice_New:PyObject*::+1: PySlice_New:PyObject*:start:0: PySlice_New:PyObject*:stop:0: @@ -1327,100 +2070,78 @@ PySlice_Unpack:Py_ssize_t*:start:: PySlice_Unpack:Py_ssize_t*:stop:: PySlice_Unpack:Py_ssize_t*:step:: -PyString_AS_STRING:const char*::: -PyString_AS_STRING:PyObject*:string:0: - -PyString_AsDecodedObject:PyObject*::+1: -PyString_AsDecodedObject:PyObject*:str:0: -PyString_AsDecodedObject:const char*:encoding:: -PyString_AsDecodedObject:const char*:errors:: - -PyString_AsEncodedObject:PyObject*::+1: -PyString_AsEncodedObject:PyObject*:str:0: -PyString_AsEncodedObject:const char*:encoding:: -PyString_AsEncodedObject:const char*:errors:: - -PyString_AsString:const char*::: -PyString_AsString:PyObject*:string:0: - -PyString_AsStringAndSize:int::: -PyString_AsStringAndSize:PyObject*:obj:0: -PyString_AsStringAndSize:char**:buffer:: -PyString_AsStringAndSize:int*:length:: - -PyString_Check:int::: -PyString_Check:PyObject*:o:0: - -PyString_Concat:void::: -PyString_Concat:PyObject**:string:0:??? -- replaces w/ new string or NULL -PyString_Concat:PyObject*:newpart:0: - -PyString_ConcatAndDel:void::: -PyString_ConcatAndDel:PyObject**:string:0:??? -- replaces w/ new string or NULL -PyString_ConcatAndDel:PyObject*:newpart:-1: - -PyString_Format:PyObject*::+1: -PyString_Format:PyObject*:format:0: -PyString_Format:PyObject*:args:0: - -PyString_FromString:PyObject*::+1: -PyString_FromString:const char*:v:: +PyState_AddModule:int::: +PyState_AddModule:PyObject*:module:+1: +PyState_AddModule:PyModuleDef*:def:: -PyString_FromStringAndSize:PyObject*::+1: -PyString_FromStringAndSize:const char*:v:: -PyString_FromStringAndSize:int:len:: +PyState_FindModule:PyObject*::0: +PyState_FindModule:PyModuleDef*:def:: -PyString_FromFormat:PyObject*::+1: -PyString_FromFormat:const char*:format:: -PyString_FromFormat::...:: +PyState_RemoveModule:int::: +PyState_RemoveModule:PyModuleDef*:def:: -PyString_FromFormatV:PyObject*::+1: -PyString_FromFormatV:const char*:format:: -PyString_FromFormatV:va_list:vargs:: +PyStructSequence_GET_ITEM:PyObject*::0: +PyStructSequence_GET_ITEM:PyObject*:p:0: +PyStructSequence_GET_ITEM:Py_ssize_t:pos:: -PyString_GET_SIZE:int::: -PyString_GET_SIZE:PyObject*:string:0: +PyStructSequence_GetItem:PyObject*::0: +PyStructSequence_GetItem:PyObject*:p:0: +PyStructSequence_GetItem:Py_ssize_t:pos:: -PyString_InternFromString:PyObject*::+1: -PyString_InternFromString:const char*:v:: +PyStructSequence_InitType:void::: +PyStructSequence_InitType:PyTypeObject*:type:+1: +PyStructSequence_InitType:PyStructSequence_Desc*:desc:: -PyString_InternInPlace:void::: -PyString_InternInPlace:PyObject**:string:+1:??? +PyStructSequence_InitType2:int::: +PyStructSequence_InitType2:PyTypeObject*:type:+1: +PyStructSequence_InitType2:PyStructSequence_Desc*:desc:: -PyString_Size:int::: -PyString_Size:PyObject*:string:0: +PyStructSequence_New:PyObject*::+1: +PyStructSequence_New:PyTypeObject*:type:0: -PyString_Decode:PyObject*::+1: -PyString_Decode:const char*:s:: -PyString_Decode:int:size:: -PyString_Decode:const char*:encoding:: -PyString_Decode:const char*:errors:: +PyStructSequence_NewType:PyTypeObject*::+1: +PyStructSequence_NewType:PyStructSequence_Desc*:desc:: -PyString_Encode:PyObject*::+1: -PyString_Encode:const char*:s:: -PyString_Encode:int:size:: -PyString_Encode:const char*:encoding:: -PyString_Encode:const char*:errors:: +PyStructSequence_SET_ITEM:void::: +PyStructSequence_SET_ITEM:PyObject*:p:0: +PyStructSequence_SET_ITEM:Py_ssize_t*:pos:: +PyStructSequence_SET_ITEM:PyObject*:o:0: -PyString_AsEncodedString:PyObject*::+1: -PyString_AsEncodedString:PyObject*:str:: -PyString_AsEncodedString:const char*:encoding:: -PyString_AsEncodedString:const char*:errors:: +PyStructSequence_SetItem:void::: +PyStructSequence_SetItem:PyObject*:p:0: +PyStructSequence_SetItem:Py_ssize_t:pos:: +PyStructSequence_SetItem:PyObject*:o:0: PySys_AddWarnOption:void::: -PySys_AddWarnOption:const char*:s:: +PySys_AddWarnOption:const wchar_t*:s:: + +PySys_AddWarnOptionUnicode:void::: +PySys_AddWarnOptionUnicode:PyObject*:unicode:0: PySys_AddXOption:void::: PySys_AddXOption:const wchar_t*:s:: +PySys_FormatStderr:void::: +PySys_FormatStderr:const char*:format:: +PySys_FormatStderr::...:: + +PySys_FormatStdout:void::: +PySys_FormatStdout:const char*:format:: +PySys_FormatStdout::...:: + PySys_GetObject:PyObject*::0: PySys_GetObject:const char*:name:: PySys_GetXOptions:PyObject*::0: -PySys_SetArgv:int::: +PySys_SetArgv:void::: PySys_SetArgv:int:argc:: -PySys_SetArgv:char**:argv:: +PySys_SetArgv:wchar_t**:argv:: + +PySys_SetArgvEx:void::: +PySys_SetArgvEx:int:argc:: +PySys_SetArgvEx:wchar_t**:argv:: +PySys_SetArgvEx:int:updatepath:: PySys_SetObject:int::: PySys_SetObject:const char*:name:: @@ -1430,9 +2151,11 @@ PySys_ResetWarnOptions:void::: PySys_WriteStdout:void::: PySys_WriteStdout:const char*:format:: +PySys_WriteStdout::...:: PySys_WriteStderr:void::: PySys_WriteStderr:const char*:format:: +PySys_WriteStderr::...:: PyThreadState_Clear:void::: PyThreadState_Clear:PyThreadState*:tstate:: @@ -1447,6 +2170,10 @@ PyThreadState_GetDict:PyObject*::0: PyThreadState_New:PyThreadState*::: PyThreadState_New:PyInterpreterState*:interp:: +PyThreadState_SetAsyncExc:int::: +PyThreadState_SetAsyncExc:unsigned long:id:: +PyThreadState_SetAsyncExc:PyObject*:exc:+1: + PyThreadState_Swap:PyThreadState*::: PyThreadState_Swap:PyThreadState*:tstate:: @@ -1471,6 +2198,12 @@ PyThread_tss_set:int::: PyThread_tss_set:Py_tss_t*:key:: PyThread_tss_set:void*:value:: +PyTime_Check:int::: +PyTime_Check:PyObject*:ob:0: + +PyTime_CheckExact:int::: +PyTime_CheckExact:PyObject*:ob:0: + PyTime_FromTime:PyObject*::+1: PyTime_FromTime:int:hour:: PyTime_FromTime:int:minute:: @@ -1489,63 +2222,130 @@ PyTraceMalloc_Untrack:uintptr_t:ptr:: PyTuple_Check:int::: PyTuple_Check:PyObject*:p:0: +PyTuple_CheckExact:int::: +PyTuple_CheckExact:PyObject*:p:0: + PyTuple_GET_ITEM:PyObject*::0: -PyTuple_GET_ITEM:PyTupleObject*:p:0: -PyTuple_GET_ITEM:int:pos:: +PyTuple_GET_ITEM:PyObject*:p:0: +PyTuple_GET_ITEM:Py_ssize_t:pos:: PyTuple_GetItem:PyObject*::0: -PyTuple_GetItem:PyTupleObject*:p:0: -PyTuple_GetItem:int:pos:: +PyTuple_GetItem:PyObject*:p:0: +PyTuple_GetItem:Py_ssize_t:pos:: + +PyTuple_GET_SIZE:Py_ssize_t::: +PyTuple_GET_SIZE:PyObject*:p:0: PyTuple_GetSlice:PyObject*::+1: -PyTuple_GetSlice:PyTupleObject*:p:0: -PyTuple_GetSlice:int:low:: -PyTuple_GetSlice:int:high:: +PyTuple_GetSlice:PyObject*:p:0: +PyTuple_GetSlice:Py_ssize_t:low:: +PyTuple_GetSlice:Py_ssize_t:high:: PyTuple_New:PyObject*::+1: -PyTuple_New:int:len:: +PyTuple_New:Py_ssize_t:len:: PyTuple_Pack:PyObject*::+1: -PyTuple_Pack:int:len:: +PyTuple_Pack:Py_ssize_t:len:: PyTuple_Pack:PyObject*:...:0: PyTuple_SET_ITEM:void::: -PyTuple_SET_ITEM:PyTupleObject*:p:0: -PyTuple_SET_ITEM:int:pos:: +PyTuple_SET_ITEM:PyObject*:p:0: +PyTuple_SET_ITEM:Py_ssize_t:pos:: PyTuple_SET_ITEM:PyObject*:o:0: PyTuple_SetItem:int::: -PyTuple_SetItem:PyTupleObject*:p:0: -PyTuple_SetItem:int:pos:: +PyTuple_SetItem:PyObject*:p:0: +PyTuple_SetItem:Py_ssize_t:pos:: PyTuple_SetItem:PyObject*:o:0: -PyTuple_Size:int::: -PyTuple_Size:PyTupleObject*:p:0: +PyTuple_Size:Py_ssize_t::: +PyTuple_Size:PyObject*:p:0: + +PyType_Check:int::: +PyType_Check:PyObject*:o:0: + +PyType_CheckExact:int::: +PyType_CheckExact:PyObject*:o:0: + +PyType_FromSpec:PyObject*::+1: +PyType_FromSpec:PyType_Spec*:spec:: + +PyType_FromSpecWithBases:PyObject*::+1: +PyType_FromSpecWithBases:PyType_Spec*:spec:: +PyType_FromSpecWithBases:PyObject*:bases:0: PyType_GenericAlloc:PyObject*::+1: PyType_GenericAlloc:PyObject*:type:0: -PyType_GenericAlloc:int:nitems:0: +PyType_GenericAlloc:Py_ssize_t:nitems:: PyType_GenericNew:PyObject*::+1: PyType_GenericNew:PyObject*:type:0: PyType_GenericNew:PyObject*:args:0: PyType_GenericNew:PyObject*:kwds:0: +PyType_GetFlags:unsigned long::: +PyType_GetFlags:PyTypeObject*:type:0: + +PyType_GetSlot:void*::: +PyType_GetSlot:PyTypeObject*:type:0: +PyType_GetSlot:int:slot:: + +PyType_HasFeature:int::: +PyType_HasFeature:PyTypeObject*:o:0: +PyType_HasFeature:int:feature:: + +PyType_IS_GC:int::: +PyType_IS_GC:PyTypeObject*:o:0: + +PyType_IsSubtype:int::: +PyType_IsSubtype:PyTypeObject*:a:0: +PyType_IsSubtype:PyTypeObject*:b:0: + +PyType_Modified:void::: +PyType_Modified:PyTypeObject*:type:0: + +PyType_Ready:int::: +PyType_Ready:PyTypeObject*:type:0: + +PyUnicode_1BYTE_DATA:Py_UCS1*::: +PyUnicode_1BYTE_DATA:PyObject*:o:0: + PyUnicode_Check:int::: PyUnicode_Check:PyObject*:o:0: -PyUnicode_GET_SIZE:int::: +PyUnicode_CheckExact:int::: +PyUnicode_CheckExact:PyObject*:o:0: + +PyUnicode_DATA:void*::: +PyUnicode_DATA:PyObject*:o:0: + +PyUnicode_GET_LENGTH:Py_ssize_t::: +PyUnicode_GET_LENGTH:PyObject*:o:0: + +PyUnicode_GET_SIZE:Py_ssize_t::: PyUnicode_GET_SIZE:PyObject*:o:0: -PyUnicode_GET_DATA_SIZE:int::: +PyUnicode_GET_DATA_SIZE:Py_ssize_t::: PyUnicode_GET_DATA_SIZE:PyObject*:o:0: +PyUnicode_KIND:int::: +PyUnicode_KIND:PyObject*:o:0: + +PyUnicode_MAX_CHAR_VALUE:::: +PyUnicode_MAX_CHAR_VALUE:PyObject*:o:0: + PyUnicode_AS_UNICODE:Py_UNICODE*::: PyUnicode_AS_UNICODE:PyObject*:o:0: PyUnicode_AS_DATA:const char*::: PyUnicode_AS_DATA:PyObject*:o:0: +Py_UNICODE_ISALNUM:int::: +Py_UNICODE_ISALNUM:Py_UNICODE:ch:: + +Py_UNICODE_ISALPHA:int::: +Py_UNICODE_ISALPHA:Py_UNICODE:ch:: + Py_UNICODE_ISSPACE:int::: Py_UNICODE_ISSPACE:Py_UNICODE:ch:: @@ -1570,6 +2370,9 @@ Py_UNICODE_ISDIGIT:Py_UNICODE:ch:: Py_UNICODE_ISNUMERIC:int::: Py_UNICODE_ISNUMERIC:Py_UNICODE:ch:: +Py_UNICODE_ISPRINTABLE:int::: +Py_UNICODE_ISPRINTABLE:Py_UNICODE:ch:: + Py_UNICODE_TOLOWER:Py_UNICODE::: Py_UNICODE_TOLOWER:Py_UNICODE:ch:: @@ -1590,150 +2393,210 @@ Py_UNICODE_TONUMERIC:Py_UNICODE:ch:: PyUnicode_FromUnicode:PyObject*::+1: PyUnicode_FromUnicode:const Py_UNICODE*:u:: -PyUnicode_FromUnicode:int:size:: +PyUnicode_FromUnicode:Py_ssize_t:size:: PyUnicode_AsUnicode:Py_UNICODE*::: -PyUnicode_AsUnicode:PyObject :*unicode:0: +PyUnicode_AsUnicode:PyObject*:unicode:0: + +PyUnicode_TransformDecimalToASCII:PyObject*::+1: +PyUnicode_TransformDecimalToASCII:Py_UNICODE*:s:: +PyUnicode_TransformDecimalToASCII:Py_ssize_t:size:: + +PyUnicode_AsUnicodeAndSize:Py_UNICODE*::: +PyUnicode_AsUnicodeAndSize:PyObject*:unicode:0: +PyUnicode_AsUnicodeAndSize:Py_ssize_t*:size:: + +PyUnicode_AsUnicodeCopy:Py_UNICODE*::: +PyUnicode_AsUnicodeCopy:PyObject*:unicode:0: -PyUnicode_GetSize:int::: -PyUnicode_GetSize:PyObject :*unicode:0: +PyUnicode_GetSize:Py_ssize_t::: +PyUnicode_GetSize:PyObject*:unicode:0: PyUnicode_FromObject:PyObject*::+1: -PyUnicode_FromObject:PyObject*:*obj:0: +PyUnicode_FromObject:PyObject*:obj:0: PyUnicode_FromEncodedObject:PyObject*::+1: -PyUnicode_FromEncodedObject:PyObject*:*obj:0: +PyUnicode_FromEncodedObject:PyObject*:obj:0: PyUnicode_FromEncodedObject:const char*:encoding:: PyUnicode_FromEncodedObject:const char*:errors:: PyUnicode_FromWideChar:PyObject*::+1: PyUnicode_FromWideChar:const wchar_t*:w:: -PyUnicode_FromWideChar:int:size:: +PyUnicode_FromWideChar:Py_ssize_t:size:: -PyUnicode_AsWideChar:int::: +PyUnicode_AsWideChar:Py_ssize_t::: PyUnicode_AsWideChar:PyObject*:*unicode:0: PyUnicode_AsWideChar:wchar_t*:w:: -PyUnicode_AsWideChar:int:size:: +PyUnicode_AsWideChar:Pyssize_t:size:: + +PyUnicode_AsWideCharString:wchar_t*::: +PyUnicode_AsWideCharString:PyObject*:unicode:0: +PyUnicode_AsWideCharString:Py_ssize_t*:size:: PyUnicode_Decode:PyObject*::+1: PyUnicode_Decode:const char*:s:: -PyUnicode_Decode:int:size:: +PyUnicode_Decode:Py_ssize_t:size:: PyUnicode_Decode:const char*:encoding:: PyUnicode_Decode:const char*:errors:: PyUnicode_DecodeUTF16Stateful:PyObject*::+1: PyUnicode_DecodeUTF16Stateful:const char*:s:: -PyUnicode_DecodeUTF16Stateful:int:size:: +PyUnicode_DecodeUTF16Stateful:Py_ssize_t:size:: PyUnicode_DecodeUTF16Stateful:const char*:errors:: PyUnicode_DecodeUTF16Stateful:int*:byteorder:: -PyUnicode_DecodeUTF16Stateful:int*:consumed:: +PyUnicode_DecodeUTF16Stateful:Py_ssize_t*:consumed:: PyUnicode_DecodeUTF8Stateful:PyObject*::+1: PyUnicode_DecodeUTF8Stateful:const char*:s:: -PyUnicode_DecodeUTF8Stateful:int:size:: +PyUnicode_DecodeUTF8Stateful:Py_ssize_t:size:: PyUnicode_DecodeUTF8Stateful:const char*:errors:: -PyUnicode_DecodeUTF8Stateful:int*:consumed:: +PyUnicode_DecodeUTF8Stateful:Py_ssize_t*:consumed:: PyUnicode_Encode:PyObject*::+1: PyUnicode_Encode:const Py_UNICODE*:s:: -PyUnicode_Encode:int:size:: +PyUnicode_Encode:Py_ssize_t:size:: PyUnicode_Encode:const char*:encoding:: PyUnicode_Encode:const char*:errors:: PyUnicode_AsEncodedString:PyObject*::+1: -PyUnicode_AsEncodedString:PyObject*:unicode:: +PyUnicode_AsEncodedString:PyObject*:unicode:0: PyUnicode_AsEncodedString:const char*:encoding:: PyUnicode_AsEncodedString:const char*:errors:: +PyUnicode_DecodeUTF7:PyObject*::+1: +PyUnicode_DecodeUTF7:const char*:s:: +PyUnicode_DecodeUTF7:Py_ssize_t:size:: +PyUnicode_DecodeUTF7:const char*:errors:: + +PyUnicode_DecodeUTF7Stateful:PyObject*::+1: +PyUnicode_DecodeUTF7Stateful:const char*:s:: +PyUnicode_DecodeUTF7Stateful:Py_ssize_t:size:: +PyUnicode_DecodeUTF7Stateful:const char*:errors:: +PyUnicode_DecodeUTF7Stateful:Py_ssize_t*:consumed:: + +PyUnicode_EncodeUTF7:PyObject*::+1: +PyUnicode_EncodeUTF7:const Py_UNICODE*:s:: +PyUnicode_EncodeUTF7:Py_ssize_t:size:: +PyUnicode_EncodeUTF7:int:base64SetO:: +PyUnicode_EncodeUTF7:int:base64WhiteSpace:: +PyUnicode_EncodeUTF7:const char*:errors:: + PyUnicode_DecodeUTF8:PyObject*::+1: PyUnicode_DecodeUTF8:const char*:s:: -PyUnicode_DecodeUTF8:int:size:: +PyUnicode_DecodeUTF8:Py_ssize_t:size:: PyUnicode_DecodeUTF8:const char*:errors:: PyUnicode_EncodeUTF8:PyObject*::+1: PyUnicode_EncodeUTF8:const Py_UNICODE*:s:: -PyUnicode_EncodeUTF8:int:size:: +PyUnicode_EncodeUTF8:Py_ssize_t:size:: PyUnicode_EncodeUTF8:const char*:errors:: PyUnicode_AsUTF8String:PyObject*::+1: -PyUnicode_AsUTF8String:PyObject*:unicode:: +PyUnicode_AsUTF8String:PyObject*:unicode:0: + +PyUnicode_AsUTF8AndSize:const char*::: +PyUnicode_AsUTF8AndSize:PyObject*:unicode:0: +PyUnicode_AsUTF8AndSize:Py_ssize_t*:size:0: + +PyUnicode_AsUTF8:const char*::: +PyUnicode_AsUTF8:PyObject*:unicode:0: PyUnicode_DecodeUTF16:PyObject*::+1: PyUnicode_DecodeUTF16:const char*:s:: -PyUnicode_DecodeUTF16:int:size:: +PyUnicode_DecodeUTF16:Py_ssize_t:size:: PyUnicode_DecodeUTF16:const char*:errors:: PyUnicode_DecodeUTF16:int*:byteorder:: PyUnicode_EncodeUTF16:PyObject*::+1: PyUnicode_EncodeUTF16:const Py_UNICODE*:s:: -PyUnicode_EncodeUTF16:int:size:: +PyUnicode_EncodeUTF16:Py_ssize_t:size:: PyUnicode_EncodeUTF16:const char*:errors:: PyUnicode_EncodeUTF16:int:byteorder:: PyUnicode_AsUTF16String:PyObject*::+1: -PyUnicode_AsUTF16String:PyObject*:unicode:: +PyUnicode_AsUTF16String:PyObject*:unicode:0: + +PyUnicode_DecodeUTF32:PyObject*::+1: +PyUnicode_DecodeUTF32:const char*:s:: +PyUnicode_DecodeUTF32:Py_ssize_t:size:: +PyUnicode_DecodeUTF32:const char*:errors:: +PyUnicode_DecodeUTF32:int*:byteorder:: + +PyUnicode_DecodeUTF32Stateful:PyObject*::+1: +PyUnicode_DecodeUTF32Stateful:const char*:s:: +PyUnicode_DecodeUTF32Stateful:Py_ssize_t:size:: +PyUnicode_DecodeUTF32Stateful:const char*:errors:: +PyUnicode_DecodeUTF32Stateful:int*:byteorder:: +PyUnicode_DecodeUTF32Stateful:Py_ssize_t*:consumed:: + +PyUnicode_AsUTF32String:PyObject*::+1: +PyUnicode_AsUTF32String:PyObject*:unicode:0: + +PyUnicode_EncodeUTF32:PyObject*::+1: +PyUnicode_EncodeUTF32:const Py_UNICODE*:s:: +PyUnicode_EncodeUTF32:Py_ssize_t:size:: +PyUnicode_EncodeUTF32:const char*:errors:: +PyUnicode_EncodeUTF32:int:byteorder:: PyUnicode_DecodeUnicodeEscape:PyObject*::+1: PyUnicode_DecodeUnicodeEscape:const char*:s:: -PyUnicode_DecodeUnicodeEscape:int:size:: +PyUnicode_DecodeUnicodeEscape:Py_ssize_t:size:: PyUnicode_DecodeUnicodeEscape:const char*:errors:: PyUnicode_EncodeUnicodeEscape:PyObject*::+1: PyUnicode_EncodeUnicodeEscape:const Py_UNICODE*:s:: -PyUnicode_EncodeUnicodeEscape:int:size:: -PyUnicode_EncodeUnicodeEscape:const char*:errors:: +PyUnicode_EncodeUnicodeEscape:Py_ssize_t:size:: PyUnicode_AsUnicodeEscapeString:PyObject*::+1: -PyUnicode_AsUnicodeEscapeString:PyObject*:unicode:: +PyUnicode_AsUnicodeEscapeString:PyObject*:unicode:0: PyUnicode_DecodeRawUnicodeEscape:PyObject*::+1: PyUnicode_DecodeRawUnicodeEscape:const char*:s:: -PyUnicode_DecodeRawUnicodeEscape:int:size:: +PyUnicode_DecodeRawUnicodeEscape:Py_ssize_t:size:: PyUnicode_DecodeRawUnicodeEscape:const char*:errors:: PyUnicode_EncodeRawUnicodeEscape:PyObject*::+1: PyUnicode_EncodeRawUnicodeEscape:const Py_UNICODE*:s:: -PyUnicode_EncodeRawUnicodeEscape:int:size:: -PyUnicode_EncodeRawUnicodeEscape:const char*:errors:: +PyUnicode_EncodeRawUnicodeEscape:Py_ssize_t:size:: PyUnicode_AsRawUnicodeEscapeString:PyObject*::+1: -PyUnicode_AsRawUnicodeEscapeString:PyObject*:unicode:: +PyUnicode_AsRawUnicodeEscapeString:PyObject*:unicode:0: PyUnicode_DecodeLatin1:PyObject*::+1: PyUnicode_DecodeLatin1:const char*:s:: -PyUnicode_DecodeLatin1:int:size:: +PyUnicode_DecodeLatin1:Py_ssize_t:size:: PyUnicode_DecodeLatin1:const char*:errors:: PyUnicode_EncodeLatin1:PyObject*::+1: PyUnicode_EncodeLatin1:const Py_UNICODE*:s:: -PyUnicode_EncodeLatin1:int:size:: +PyUnicode_EncodeLatin1:Py_ssize_t:size:: PyUnicode_EncodeLatin1:const char*:errors:: PyUnicode_AsLatin1String:PyObject*::+1: -PyUnicode_AsLatin1String:PyObject*:unicode:: +PyUnicode_AsLatin1String:PyObject*:unicode:0: PyUnicode_DecodeASCII:PyObject*::+1: PyUnicode_DecodeASCII:const char*:s:: -PyUnicode_DecodeASCII:int:size:: +PyUnicode_DecodeASCII:Py_ssize_t:size:: PyUnicode_DecodeASCII:const char*:errors:: PyUnicode_EncodeASCII:PyObject*::+1: PyUnicode_EncodeASCII:const Py_UNICODE*:s:: -PyUnicode_EncodeASCII:int:size:: +PyUnicode_EncodeASCII:Py_ssize_t:size:: PyUnicode_EncodeASCII:const char*:errors:: PyUnicode_AsASCIIString:PyObject*::+1: -PyUnicode_AsASCIIString:PyObject*:unicode:: +PyUnicode_AsASCIIString:PyObject*:unicode:0: PyUnicode_DecodeCharmap:PyObject*::+1: PyUnicode_DecodeCharmap:const char*:s:: -PyUnicode_DecodeCharmap:int:size:: +PyUnicode_DecodeCharmap:Py_ssize_t:size:: PyUnicode_DecodeCharmap:PyObject*:mapping:0: PyUnicode_DecodeCharmap:const char*:errors:: PyUnicode_EncodeCharmap:PyObject*::+1: PyUnicode_EncodeCharmap:const Py_UNICODE*:s:: -PyUnicode_EncodeCharmap:int:size:: +PyUnicode_EncodeCharmap:Py_ssize_t:size:: PyUnicode_EncodeCharmap:PyObject*:mapping:0: PyUnicode_EncodeCharmap:const char*:errors:: @@ -1743,22 +2606,33 @@ PyUnicode_AsCharmapString:PyObject*:mapping:0: PyUnicode_TranslateCharmap:PyObject*::+1: PyUnicode_TranslateCharmap:const Py_UNICODE*:s:: -PyUnicode_TranslateCharmap:int:size:: -PyUnicode_TranslateCharmap:PyObject*:table:0: +PyUnicode_TranslateCharmap:Py_ssize_t:size:: +PyUnicode_TranslateCharmap:PyObject*:mapping:0: PyUnicode_TranslateCharmap:const char*:errors:: PyUnicode_DecodeMBCS:PyObject*::+1: PyUnicode_DecodeMBCS:const char*:s:: -PyUnicode_DecodeMBCS:int:size:: +PyUnicode_DecodeMBCS:Py_ssize_t:size:: PyUnicode_DecodeMBCS:const char*:errors:: +PyUnicode_DecodeMBCSStateful:PyObject*::+1: +PyUnicode_DecodeMBCSStateful:const char*:s:: +PyUnicode_DecodeMBCSStateful:Py_ssize_t:size:: +PyUnicode_DecodeMBCSStateful:const char*:errors:: +PyUnicode_DecodeMBCSStateful:Py_ssize_t*:consumed:: + +PyUnicode_EncodeCodePage:PyObject*::+1: +PyUnicode_EncodeCodePage:int:code_page:: +PyUnicode_EncodeCodePage:PyObject*:unicode:0: +PyUnicode_EncodeCodePage:const char*:errors:: + PyUnicode_EncodeMBCS:PyObject*::+1: PyUnicode_EncodeMBCS:const Py_UNICODE*:s:: -PyUnicode_EncodeMBCS:int:size:: +PyUnicode_EncodeMBCS:Py_ssize_t:size:: PyUnicode_EncodeMBCS:const char*:errors:: PyUnicode_AsMBCSString:PyObject*::+1: -PyUnicode_AsMBCSString:PyObject*:unicode:: +PyUnicode_AsMBCSString:PyObject*:unicode:0: PyUnicode_Concat:PyObject*::+1: PyUnicode_Concat:PyObject*:left:0: @@ -1767,11 +2641,11 @@ PyUnicode_Concat:PyObject*:right:0: PyUnicode_Split:PyObject*::+1: PyUnicode_Split:PyObject*:left:0: PyUnicode_Split:PyObject*:right:0: -PyUnicode_Split:int:maxsplit:: +PyUnicode_Split:Py_ssize_t:maxsplit:: PyUnicode_Splitlines:PyObject*::+1: PyUnicode_Splitlines:PyObject*:s:0: -PyUnicode_Splitlines:int:maxsplit:: +PyUnicode_Splitlines:int:keepend:: PyUnicode_Translate:PyObject*::+1: PyUnicode_Translate:PyObject*:str:0: @@ -1782,36 +2656,52 @@ PyUnicode_Join:PyObject*::+1: PyUnicode_Join:PyObject*:separator:0: PyUnicode_Join:PyObject*:seq:0: -PyUnicode_Tailmatch:int::: +PyUnicode_Tailmatch:Py_ssize_t::: PyUnicode_Tailmatch:PyObject*:str:0: PyUnicode_Tailmatch:PyObject*:substr:0: -PyUnicode_Tailmatch:int:start:: -PyUnicode_Tailmatch:int:end:: +PyUnicode_Tailmatch:Py_ssize_t:start:: +PyUnicode_Tailmatch:Py_ssize_t:end:: PyUnicode_Tailmatch:int:direction:: -PyUnicode_Find:int::: +PyUnicode_Find:Py_ssize_t::: PyUnicode_Find:PyObject*:str:0: PyUnicode_Find:PyObject*:substr:0: -PyUnicode_Find:int:start:: -PyUnicode_Find:int:end:: +PyUnicode_Find:Py_ssize_t:start:: +PyUnicode_Find:Py_ssize_t:end:: PyUnicode_Find:int:direction:: -PyUnicode_Count:int::: +PyUnicode_FindChar:Py_ssize_t::: +PyUnicode_FindChar:PyObject*:str:0: +PyUnicode_FindChar:Py_UCS4:ch:: +PyUnicode_FindChar:Py_ssize_t:start:: +PyUnicode_FindChar:Py_ssize_t:end:: +PyUnicode_FindChar:int:direction:: + +PyUnicode_Count:Py_ssize_t::: PyUnicode_Count:PyObject*:str:0: PyUnicode_Count:PyObject*:substr:0: -PyUnicode_Count:int:start:: -PyUnicode_Count:int:end:: +PyUnicode_Count:Py_ssize_t:start:: +PyUnicode_Count:Py_ssize_t:end:: PyUnicode_Replace:PyObject*::+1: PyUnicode_Replace:PyObject*:str:0: PyUnicode_Replace:PyObject*:substr:0: PyUnicode_Replace:PyObject*:replstr:0: -PyUnicode_Replace:int:maxcount:: +PyUnicode_Replace:Py_ssize_t:maxcount:: PyUnicode_Compare:int::: PyUnicode_Compare:PyObject*:left:0: PyUnicode_Compare:PyObject*:right:0: +PyUnicode_CompareWithASCIIString:int::: +PyUnicode_CompareWithASCIIString:PyObject*:uni:0: +PyUnicode_CompareWithASCIIString:const char*:string:: + +PyUnicode_RichCompare:PyObject*::+1: +PyUnicode_RichCompare:PyObject*:left:0: +PyUnicode_RichCompare:PyObject*:right:0: +PyUnicode_RichCompare:int:op:: + PyUnicode_Format:PyObject*::+1: PyUnicode_Format:PyObject*:format:0: PyUnicode_Format:PyObject*:args:0: @@ -1820,6 +2710,185 @@ PyUnicode_Contains:int::: PyUnicode_Contains:PyObject*:container:0: PyUnicode_Contains:PyObject*:element:0: +PyUnicode_InternInPlace:void::: +PyUnicode_InternInPlace:PyObject**:string:+1: + +PyUnicode_InternFromString:PyObject*::+1: +PyUnicode_InternFromString:const char*:v:: + +PyUnicode_New:PyObject*::+1: +PyUnicode_New:Py_ssize_t:size:: +PyUnicode_New:Py_UCS4:maxchar:: + +PyUnicode_FromKindAndData:PyObject*::+1: +PyUnicode_FromKindAndData:int:kind:: +PyUnicode_FromKindAndData:const void*:buffer:: +PyUnicode_FromKindAndData:Py_ssize_t:size:: + +PyUnicode_FromStringAndSize:PyObject*::+1: +PyUnicode_FromStringAndSize:const char*:u:: +PyUnicode_FromStringAndSize:Py_ssize_t:size:: + +PyUnicode_FromString:PyObject*::+1: +PyUnicode_FromString:const char*:u:: + +PyUnicode_FromFormat:PyObject*::+1: +PyUnicode_FromFormat:const char*:format:: +PyUnicode_FromFormat::...:: + +PyUnicode_FromFormatV:PyObject*::+1: +PyUnicode_FromFormatV:const char*:format:: +PyUnicode_FromFormatV:va_list:args:: + +PyUnicode_GetLength:Py_ssize_t::: +PyUnicode_GetLength:PyObject*:unicode:0: + +PyUnicode_CopyCharacters:Py_ssize_t::: +PyUnicode_CopyCharacters:PyObject*:to:0: +PyUnicode_CopyCharacters:Py_ssize_t:to_start:: +PyUnicode_CopyCharacters:PyObject*:from:0: +PyUnicode_CopyCharacters:Py_ssize_t:from_start:: +PyUnicode_CopyCharacters:Py_ssize_t:how_many:: + +PyUnicode_Fill:Py_ssize_t::: +PyUnicode_Fill:PyObject*:unicode:0: +PyUnicode_Fill:Py_ssize_t:start:: +PyUnicode_Fill:Py_ssize_t:length:: +PyUnicode_Fill:Py_UCS4:fill_char:: + +PyUnicode_READ:Py_UCS4::: +PyUnicode_READ:int:kind:: +PyUnicode_READ:void*:data:: +PyUnicode_READ:Py_ssize_t:index:: + +PyUnicode_READ_CHAR:Py_UCS4::: +PyUnicode_READ_CHAR:PyObject*:o:0: +PyUnicode_READ_CHAR:Py_ssize_t:index:: + +PyUnicode_ReadChar:Py_UCS4::: +PyUnicode_ReadChar:PyObject*:unicode:0: +PyUnicode_ReadChar:Py_ssize_t:index:: + +PyUnicode_WRITE:void::: +PyUnicode_WRITE:int:kind:: +PyUnicode_WRITE:void*:data:: +PyUnicode_WRITE:Py_ssize_t:index:: +PyUnicode_WRITE:Py_UCS4:value:: + +PyUnicode_WriteChar:int::: +PyUnicode_WriteChar:PyObject*:unicode:0: +PyUnicode_WriteChar:Py_ssize_t:index:: +PyUnicode_WriteChar:Py_UCS4:character:: + +PyUnicode_READY:int::: +PyUnicode_READY:PyObject*:o:0: + +PyUnicode_Substring:PyObject*::+1: +PyUnicode_Substring:PyObject*:str:0: +PyUnicode_Substring:Py_ssize_t:start:: +PyUnicode_Substring:Py_ssize_t:end:: + +PyUnicode_AsUCS4:Py_UCS4*::: +PyUnicode_AsUCS4:PyObject*:u:0: +PyUnicode_AsUCS4:Py_UCS4*:buffer:: +PyUnicode_AsUCS4:Py_ssize_t:buflen:: +PyUnicode_AsUCS4:int:copy_null:: + +PyUnicode_AsUCS4Copy:Py_UCS4*::: +PyUnicode_AsUCS4Copy:PyObject*:u:0: + +PyUnicode_DecodeLocaleAndSize:PyObject*::+1: +PyUnicode_DecodeLocaleAndSize:const char*:str:: +PyUnicode_DecodeLocaleAndSize:Py_ssize_t:len:: +PyUnicode_DecodeLocaleAndSize:const char*:errors:: + +PyUnicode_DecodeLocale:PyObject*::+1: +PyUnicode_DecodeLocale:const char*:str:: +PyUnicode_DecodeLocale:const char*:errors:: + +PyUnicode_EncodeLocale:PyObject*::+1: +PyUnicode_EncodeLocale:PyObject*:unicode:0: +PyUnicode_EncodeLocale:const char*:errors:: + +PyUnicode_FSConverter:int::: +PyUnicode_FSConverter:PyObject*:obj:0: +PyUnicode_FSConverter:void*:result:: + +PyUnicode_FSDecoder:int::: +PyUnicode_FSDecoder:PyObject*:obj:0: +PyUnicode_FSDecoder:void*:result:: + +PyUnicode_DecodeFSDefaultAndSize:PyObject*::+1: +PyUnicode_DecodeFSDefaultAndSize:const char*:s:: +PyUnicode_DecodeFSDefaultAndSize:Py_ssize_t:size:: + +PyUnicode_DecodeFSDefault:PyObject*::+1: +PyUnicode_DecodeFSDefault:const char*:s:: + +PyUnicode_EncodeFSDefault:PyObject*::+1: +PyUnicode_EncodeFSDefault:PyObject*:unicode:0: + +PyUnicodeDecodeError_Create:PyObject*::+1: +PyUnicodeDecodeError_Create:const char*:encoding:: +PyUnicodeDecodeError_Create:const char*:object:: +PyUnicodeDecodeError_Create:Py_ssize_t:length:: +PyUnicodeDecodeError_Create:Py_ssize_t:start:: +PyUnicodeDecodeError_Create:Py_ssize_t:end:: +PyUnicodeDecodeError_Create:const char*:reason:: + +PyUnicodeDecodeError_GetEncoding:PyObject*::+1: +PyUnicodeDecodeError_GetEncoding:PyObject*:exc:0: + +PyUnicodeDecodeError_GetEnd:Py_ssize_t::: +PyUnicodeDecodeError_GetEnd:PyObject*:exc:0: +PyUnicodeDecodeError_GetEnd:Py_ssize_t*:end:: + +PyUnicodeDecodeError_GetObject:PyObject*::+1: +PyUnicodeDecodeError_GetObject:PyObject*:exc:0: + +PyUnicodeDecodeError_GetReason:PyObject*::+1: +PyUnicodeDecodeError_GetReason:PyObject*:exc:0: + +PyUnicodeDecodeError_GetStart:Py_ssize_t::: +PyUnicodeDecodeError_GetStart:PyObject*:exc:0: +PyUnicodeDecodeError_GetStart:Py_ssize_t*:start:: + +PyUnicodeDecodeError_SetEnd:int::: +PyUnicodeDecodeError_SetEnd:PyObject*:exc:0: +PyUnicodeDecodeError_SetEnd:Py_ssize_t:end:: + +PyUnicodeDecodeError_SetReason:int::: +PyUnicodeDecodeError_SetReason:PyObject*:exc:0: +PyUnicodeDecodeError_SetReason:const char*:reason:: + +PyUnicodeDecodeError_SetStart:int::: +PyUnicodeDecodeError_SetStart:PyObject*:exc:0: +PyUnicodeDecodeError_SetStart:Py_ssize_t:start:: + +PyUnicodeEncodeError_Create:PyObject*::+1: +PyUnicodeEncodeError_Create:const char*:encoding:: +PyUnicodeEncodeError_Create:const Py_UNICODE*:object:: +PyUnicodeEncodeError_Create:Py_ssize_t:length:: +PyUnicodeEncodeError_Create:Py_ssize_t:start:: +PyUnicodeEncodeError_Create:Py_ssize_t:end:: +PyUnicodeEncodeError_Create:const char*:reason:: + +PyUnicodeTranslateError_Create:PyObject*::+1: +PyUnicodeTranslateError_Create:const Py_UNICODE*:object:: +PyUnicodeTranslateError_Create:Py_ssize_t:length:: +PyUnicodeTranslateError_Create:Py_ssize_t:start:: +PyUnicodeTranslateError_Create:Py_ssize_t:end:: +PyUnicodeTranslateError_Create:const char*:reason:: + +PyWeakref_Check:int::: +PyWeakref_Check:PyObject*:ob:: + +PyWeakref_CheckProxy:int::: +PyWeakref_CheckProxy:PyObject*:ob:: + +PyWeakref_CheckRef:int::: +PyWeakref_CheckRef:PyObject*:ob:: + PyWeakref_GET_OBJECT:PyObject*::0: PyWeakref_GET_OBJECT:PyObject*:ref:0: @@ -1843,18 +2912,40 @@ Py_AtExit:void (*)():func:: Py_BuildValue:PyObject*::+1: Py_BuildValue:const char*:format:: +Py_BuildValue::...:: + +Py_VaBuildValue:PyObject*::+1: +Py_VaBuildValue:const char*:format:: +Py_VaBuildValue:va_list:vargs:: + +Py_CLEAR:void::: +Py_CLEAR:PyObject*:o:-1: Py_CompileString:PyObject*::+1: Py_CompileString:const char*:str:: Py_CompileString:const char*:filename:: Py_CompileString:int:start:: +Py_CompileStringExFlags:PyObject*::+1: +Py_CompileStringExFlags:const char*:str:: +Py_CompileStringExFlags:const char*:filename:: +Py_CompileStringExFlags:int:start:: +Py_CompileStringExFlags:PyCompilerFlags*:flags:: +Py_CompileStringExFlags:int:optimize:: + Py_CompileStringFlags:PyObject*::+1: Py_CompileStringFlags:const char*:str:: Py_CompileStringFlags:const char*:filename:: Py_CompileStringFlags:int:start:: Py_CompileStringFlags:PyCompilerFlags*:flags:: +Py_CompileStringObject:PyObject*::+1: +Py_CompileStringObject:const char*:str:: +Py_CompileStringObject:PyObject*:filename:0: +Py_CompileStringObject:int:start:: +Py_CompileStringObject:PyCompilerFlags*:flags:: +Py_CompileStringObject:int:optimize:: + Py_DECREF:void::: Py_DECREF:PyObject*:o:-1: @@ -1873,25 +2964,25 @@ Py_FdIsInteractive:const char*:filename:: Py_Finalize:void::: -Py_GetBuildInfoconst:const char*::: +Py_GetBuildInfo:const char*::: -Py_GetCompilerconst:const char*::: +Py_GetCompiler:const char*::: -Py_GetCopyrightconst:const char*::: +Py_GetCopyright:const char*::: -Py_GetExecPrefix:const char*::: +Py_GetExecPrefix:wchar_t*::: -Py_GetPath:const char*::: +Py_GetPath:wchar_t*::: -Py_GetPlatformconst:const char*::: +Py_GetPlatform:const char*::: -Py_GetPrefix:const char*::: +Py_GetPrefix:wchar_t*::: -Py_GetProgramFullPath:const char*::: +Py_GetProgramFullPath:wchar_t*::: -Py_GetProgramName:const char*::: +Py_GetProgramName:wchar_t*::: -Py_GetVersionconst:const char*::: +Py_GetVersion:const char*::: Py_INCREF:void::: Py_INCREF:PyObject*:o:+1: @@ -1902,8 +2993,14 @@ Py_IsInitialized:int::: Py_NewInterpreter:PyThreadState*::: +Py_ReprEnter:int::: +Py_ReprEnter:PyObject*:object:+1: + +Py_ReprLeave:void::: +Py_ReprLeave:PyObject*:object:-1: + Py_SetProgramName:void::: -Py_SetProgramName:const char*:name:: +Py_SetProgramName:const wchar_t*:name:: Py_XDECREF:void::: Py_XDECREF:PyObject*:o:-1:if o is not NULL @@ -1911,32 +3008,24 @@ Py_XDECREF:PyObject*:o:-1:if o is not NULL Py_XINCREF:void::: Py_XINCREF:PyObject*:o:+1:if o is not NULL -_PyImport_FindExtension:PyObject*::0:??? see PyImport_AddModule -_PyImport_FindExtension:const char*::: -_PyImport_FindExtension:const char*::: - _PyImport_Fini:void::: -_PyImport_FixupExtension:PyObject*:::??? -_PyImport_FixupExtension:const char*::: -_PyImport_FixupExtension:const char*::: - _PyImport_Init:void::: _PyObject_New:PyObject*::+1: _PyObject_New:PyTypeObject*:type:0: -_PyObject_NewVar:PyObject*::+1: +_PyObject_NewVar:PyVarObject*::+1: _PyObject_NewVar:PyTypeObject*:type:0: -_PyObject_NewVar:int:size:: +_PyObject_NewVar:Py_ssize_t:size:: -_PyString_Resize:int::: -_PyString_Resize:PyObject**:string:+1: -_PyString_Resize:int:newsize:: +_PyBytes_Resize:int::: +_PyBytes_Resize:PyObject**:bytes:0: +_PyBytes_Resize:Py_ssize_t:newsize:: _PyTuple_Resize:int::: -_PyTuple_Resize:PyTupleObject**:p:+1: -_PyTuple_Resize:int:new:: +_PyTuple_Resize:PyObject**:p:0: +_PyTuple_Resize:Py_ssize_t:new:: _Py_c_diff:Py_complex::: _Py_c_diff:Py_complex:left:: diff --git a/kbe/src/lib/python/Doc/distutils/setupscript.rst b/kbe/src/lib/python/Doc/distutils/setupscript.rst index c1051d2e80..54ed1aebc2 100644 --- a/kbe/src/lib/python/Doc/distutils/setupscript.rst +++ b/kbe/src/lib/python/Doc/distutils/setupscript.rst @@ -524,20 +524,23 @@ following way:: setup(..., data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']), ('config', ['cfg/data.cfg']), - ('/etc/init.d', ['init-script'])] ) -Note that you can specify the directory names where the data files will be -installed, but you cannot rename the data files themselves. - Each (*directory*, *files*) pair in the sequence specifies the installation -directory and the files to install there. If *directory* is a relative path, it -is interpreted relative to the installation prefix (Python's ``sys.prefix`` for -pure-Python packages, ``sys.exec_prefix`` for packages that contain extension -modules). Each file name in *files* is interpreted relative to the -:file:`setup.py` script at the top of the package source distribution. No -directory information from *files* is used to determine the final location of -the installed file; only the name of the file is used. +directory and the files to install there. + +Each file name in *files* is interpreted relative to the :file:`setup.py` +script at the top of the package source distribution. Note that you can +specify the directory where the data files will be installed, but you cannot +rename the data files themselves. + +The *directory* should be a relative path. It is interpreted relative to the +installation prefix (Python's ``sys.prefix`` for system installations; +``site.USER_BASE`` for user installations). Distutils allows *directory* to be +an absolute installation path, but this is discouraged since it is +incompatible with the wheel packaging format. No directory information from +*files* is used to determine the final location of the installed file; only +the name of the file is used. You can specify the ``data_files`` options as a simple sequence of files without specifying a target directory, but this is not recommended, and the diff --git a/kbe/src/lib/python/Doc/faq/general.rst b/kbe/src/lib/python/Doc/faq/general.rst index 90fd69e729..7ee340d795 100644 --- a/kbe/src/lib/python/Doc/faq/general.rst +++ b/kbe/src/lib/python/Doc/faq/general.rst @@ -268,14 +268,8 @@ Python references; or perhaps search for "Python" and "language". Where in the world is www.python.org located? --------------------------------------------- -The Python project's infrastructure is located all over the world. -`www.python.org `_ is graciously hosted by `Rackspace -`_, with CDN caching provided by `Fastly -`_. `Upfront Systems -`_ hosts `bugs.python.org -`_. Many other Python services like `the Wiki -`_ are hosted by `Oregon State -University Open Source Lab `_. +The Python project's infrastructure is located all over the world and is managed +by the Python Infrastructure Team. Details `here `__. Why is it called Python? diff --git a/kbe/src/lib/python/Doc/faq/programming.rst b/kbe/src/lib/python/Doc/faq/programming.rst index fd720c1a30..31614189a6 100644 --- a/kbe/src/lib/python/Doc/faq/programming.rst +++ b/kbe/src/lib/python/Doc/faq/programming.rst @@ -738,7 +738,7 @@ Is it possible to write obfuscated one-liners in Python? -------------------------------------------------------- Yes. Usually this is done by nesting :keyword:`lambda` within -:keyword:`lambda`. See the following three examples, due to Ulf Bartelt:: +:keyword:`!lambda`. See the following three examples, due to Ulf Bartelt:: from functools import reduce @@ -767,6 +767,41 @@ Yes. Usually this is done by nesting :keyword:`lambda` within Don't try this at home, kids! +.. _faq-positional-only-arguments: + +What does the slash(/) in the parameter list of a function mean? +---------------------------------------------------------------- + +A slash in the argument list of a function denotes that the parameters prior to +it are positional-only. Positional-only parameters are the ones without an +externally-usable name. Upon calling a function that accepts positional-only +parameters, arguments are mapped to parameters based solely on their position. +For example, :func:`pow` is a function that accepts positional-only parameters. +Its documentation looks like this:: + + >>> help(pow) + Help on built-in function pow in module builtins: + + pow(x, y, z=None, /) + Equivalent to x**y (with two arguments) or x**y % z (with three arguments) + + Some types, such as ints, are able to use a more efficient algorithm when + invoked using the three argument form. + +The slash at the end of the parameter list means that all three parameters are +positional-only. Thus, calling :func:`pow` with keyword aguments would lead to +an error:: + + >>> pow(x=3, y=4) + Traceback (most recent call last): + File "", line 1, in + TypeError: pow() takes no keyword arguments + +Note that as of this writing this is only documentational and no valid syntax +in Python, although there is :pep:`570`, which proposes a syntax for +position-only parameters in Python. + + Numbers and strings =================== @@ -1317,9 +1352,6 @@ The ``__iadd__`` succeeds, and thus the list is extended, but even though that final assignment still results in an error, because tuples are immutable. -Dictionaries -============ - I want to do a complicated sort: can you do a Schwartzian Transform in Python? ------------------------------------------------------------------------------ diff --git a/kbe/src/lib/python/Doc/glossary.rst b/kbe/src/lib/python/Doc/glossary.rst index b8d98dd34c..fb8ff2a7c6 100644 --- a/kbe/src/lib/python/Doc/glossary.rst +++ b/kbe/src/lib/python/Doc/glossary.rst @@ -332,7 +332,7 @@ Glossary names, attribute access, operators or function calls which all return a value. In contrast to many other languages, not all language constructs are expressions. There are also :term:`statement`\s which cannot be used - as expressions, such as :keyword:`if`. Assignments are also statements, + as expressions, such as :keyword:`while`. Assignments are also statements, not expressions. extension module @@ -444,8 +444,8 @@ Glossary generator expression An expression that returns an iterator. It looks like a normal expression - followed by a :keyword:`for` expression defining a loop variable, range, - and an optional :keyword:`if` expression. The combined expression + followed by a :keyword:`!for` clause defining a loop variable, range, + and an optional :keyword:`!if` clause. The combined expression generates values for an enclosing function:: >>> sum(i*i for i in range(10)) # sum of squares 0, 1, 4, ... 81 diff --git a/kbe/src/lib/python/Doc/howto/functional.rst b/kbe/src/lib/python/Doc/howto/functional.rst index 2efe4537e2..f8f2aac70f 100644 --- a/kbe/src/lib/python/Doc/howto/functional.rst +++ b/kbe/src/lib/python/Doc/howto/functional.rst @@ -1108,7 +1108,7 @@ need to define a new function at all:: existing_files = filter(os.path.exists, file_list) If the function you need doesn't exist, you need to write it. One way to write -small functions is to use the :keyword:`lambda` statement. ``lambda`` takes a +small functions is to use the :keyword:`lambda` expression. ``lambda`` takes a number of parameters and an expression combining these parameters, and creates an anonymous function that returns the value of the expression:: diff --git a/kbe/src/lib/python/Doc/howto/logging-cookbook.rst b/kbe/src/lib/python/Doc/howto/logging-cookbook.rst index b1930a791f..e391506ce2 100644 --- a/kbe/src/lib/python/Doc/howto/logging-cookbook.rst +++ b/kbe/src/lib/python/Doc/howto/logging-cookbook.rst @@ -186,7 +186,7 @@ previous simple module-based configuration example:: # 'application' code logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') @@ -295,7 +295,7 @@ Here is an example of a module using the logging configuration server:: while True: logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') time.sleep(5) diff --git a/kbe/src/lib/python/Doc/howto/logging.rst b/kbe/src/lib/python/Doc/howto/logging.rst index 2a2282e9ec..7a68ca8919 100644 --- a/kbe/src/lib/python/Doc/howto/logging.rst +++ b/kbe/src/lib/python/Doc/howto/logging.rst @@ -610,7 +610,7 @@ logger, a console handler, and a simple formatter using Python code:: # 'application' code logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') @@ -640,7 +640,7 @@ the names of the objects:: # 'application' code logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') @@ -695,15 +695,15 @@ noncoders to easily modify the logging properties. .. warning:: The :func:`fileConfig` function takes a default parameter, ``disable_existing_loggers``, which defaults to ``True`` for reasons of backward compatibility. This may or may not be what you want, since it - will cause any loggers existing before the :func:`fileConfig` call to - be disabled unless they (or an ancestor) are explicitly named in the - configuration. Please refer to the reference documentation for more + will cause any non-root loggers existing before the :func:`fileConfig` + call to be disabled unless they (or an ancestor) are explicitly named in + the configuration. Please refer to the reference documentation for more information, and specify ``False`` for this parameter if you wish. The dictionary passed to :func:`dictConfig` can also specify a Boolean value with key ``disable_existing_loggers``, which if not specified explicitly in the dictionary also defaults to being interpreted as - ``True``. This leads to the logger-disabling behaviour described above, + ``True``. This leads to the logger-disabling behaviour described above, which may not be what you want - in which case, provide the key explicitly with a value of ``False``. @@ -802,7 +802,7 @@ the best default behaviour. If for some reason you *don't* want these messages printed in the absence of any logging configuration, you can attach a do-nothing handler to the top-level logger for your library. This avoids the message being printed, since a handler -will be always be found for the library's events: it just doesn't produce any +will always be found for the library's events: it just doesn't produce any output. If the library user configures logging for application use, presumably that configuration will add some handlers, and if levels are suitably configured then logging calls made in library code will send output to those diff --git a/kbe/src/lib/python/Doc/howto/regex.rst b/kbe/src/lib/python/Doc/howto/regex.rst index b09f748a92..d385d99134 100644 --- a/kbe/src/lib/python/Doc/howto/regex.rst +++ b/kbe/src/lib/python/Doc/howto/regex.rst @@ -96,8 +96,9 @@ special nature. You can match the characters not listed within the class by :dfn:`complementing` the set. This is indicated by including a ``'^'`` as the first character of the -class; ``'^'`` outside a character class will simply match the ``'^'`` -character. For example, ``[^5]`` will match any character except ``'5'``. +class. For example, ``[^5]`` will match any character except ``'5'``. If the +caret appears elsewhere in a character class, it does not have special meaning. +For example: ``[5^]`` will match either a ``'5'`` or a ``'^'``. Perhaps the most important metacharacter is the backslash, ``\``. As in Python string literals, the backslash can be followed by various characters to signal diff --git a/kbe/src/lib/python/Doc/howto/unicode.rst b/kbe/src/lib/python/Doc/howto/unicode.rst index be1fefb35a..5339bf45bf 100644 --- a/kbe/src/lib/python/Doc/howto/unicode.rst +++ b/kbe/src/lib/python/Doc/howto/unicode.rst @@ -6,95 +6,48 @@ :Release: 1.12 -This HOWTO discusses Python support for Unicode, and explains -various problems that people commonly encounter when trying to work -with Unicode. +This HOWTO discusses Python's support for the Unicode specification +for representing textual data, and explains various problems that +people commonly encounter when trying to work with Unicode. + Introduction to Unicode ======================= -History of Character Codes --------------------------- - -In 1968, the American Standard Code for Information Interchange, better known by -its acronym ASCII, was standardized. ASCII defined numeric codes for various -characters, with the numeric values running from 0 to 127. For example, the -lowercase letter 'a' is assigned 97 as its code value. - -ASCII was an American-developed standard, so it only defined unaccented -characters. There was an 'e', but no 'é' or 'Í'. This meant that languages -which required accented characters couldn't be faithfully represented in ASCII. -(Actually the missing accents matter for English, too, which contains words such -as 'naïve' and 'café', and some publications have house styles which require -spellings such as 'coöperate'.) - -For a while people just wrote programs that didn't display accents. -In the mid-1980s an Apple II BASIC program written by a French speaker -might have lines like these: - -.. code-block:: basic - - PRINT "MISE A JOUR TERMINEE" - PRINT "PARAMETRES ENREGISTRES" - -Those messages should contain accents (terminée, paramètre, enregistrés) and -they just look wrong to someone who can read French. - -In the 1980s, almost all personal computers were 8-bit, meaning that bytes could -hold values ranging from 0 to 255. ASCII codes only went up to 127, so some -machines assigned values between 128 and 255 to accented characters. Different -machines had different codes, however, which led to problems exchanging files. -Eventually various commonly used sets of values for the 128--255 range emerged. -Some were true standards, defined by the International Organization for -Standardization, and some were *de facto* conventions that were invented by one -company or another and managed to catch on. - -255 characters aren't very many. For example, you can't fit both the accented -characters used in Western Europe and the Cyrillic alphabet used for Russian -into the 128--255 range because there are more than 128 such characters. - -You could write files using different codes (all your Russian files in a coding -system called KOI8, all your French files in a different coding system called -Latin1), but what if you wanted to write a French document that quotes some -Russian text? In the 1980s people began to want to solve this problem, and the -Unicode standardization effort began. - -Unicode started out using 16-bit characters instead of 8-bit characters. 16 -bits means you have 2^16 = 65,536 distinct values available, making it possible -to represent many different characters from many different alphabets; an initial -goal was to have Unicode contain the alphabets for every single human language. -It turns out that even 16 bits isn't enough to meet that goal, and the modern -Unicode specification uses a wider range of codes, 0 through 1,114,111 ( -``0x10FFFF`` in base 16). - -There's a related ISO standard, ISO 10646. Unicode and ISO 10646 were -originally separate efforts, but the specifications were merged with the 1.1 -revision of Unicode. - -(This discussion of Unicode's history is highly simplified. The -precise historical details aren't necessary for understanding how to -use Unicode effectively, but if you're curious, consult the Unicode -consortium site listed in the References or -the `Wikipedia entry for Unicode `_ -for more information.) - - Definitions ----------- +Today's programs need to be able to handle a wide variety of +characters. Applications are often internationalized to display +messages and output in a variety of user-selectable languages; the +same program might need to output an error message in English, French, +Japanese, Hebrew, or Russian. Web content can be written in any of +these languages and can also include a variety of emoji symbols. +Python's string type uses the Unicode Standard for representing +characters, which lets Python programs work with all these different +possible characters. + +Unicode (https://www.unicode.org/) is a specification that aims to +list every character used by human languages and give each character +its own unique code. The Unicode specifications are continually +revised and updated to add new languages and symbols. + A **character** is the smallest possible component of a text. 'A', 'B', 'C', -etc., are all different characters. So are 'È' and 'Í'. Characters are -abstractions, and vary depending on the language or context you're talking -about. For example, the symbol for ohms (Ω) is usually drawn much like the -capital letter omega (Ω) in the Greek alphabet (they may even be the same in -some fonts), but these are two different characters that have different -meanings. - -The Unicode standard describes how characters are represented by **code -points**. A code point is an integer value, usually denoted in base 16. In the -standard, a code point is written using the notation ``U+12CA`` to mean the -character with value ``0x12ca`` (4,810 decimal). The Unicode standard contains -a lot of tables listing characters and their corresponding code points: +etc., are all different characters. So are 'È' and 'Í'. Characters vary +depending on the language or context you're talking +about. For example, there's a character for "Roman Numeral One", 'Ⅰ', that's +separate from the uppercase letter 'I'. They'll usually look the same, +but these are two different characters that have different meanings. + +The Unicode standard describes how characters are represented by +**code points**. A code point value is an integer in the range 0 to +0x10FFFF (about 1.1 million values, with some 110 thousand assigned so +far). In the standard and in this document, a code point is written +using the notation ``U+265E`` to mean the character with value +``0x265e`` (9,822 in decimal). + +The Unicode standard contains a lot of tables listing characters and +their corresponding code points: .. code-block:: none @@ -103,10 +56,21 @@ a lot of tables listing characters and their corresponding code points: 0063 'c'; LATIN SMALL LETTER C ... 007B '{'; LEFT CURLY BRACKET + ... + 2167 'Ⅶ': ROMAN NUMERAL EIGHT + 2168 'Ⅸ': ROMAN NUMERAL NINE + ... + 265E '♞': BLACK CHESS KNIGHT + 265F '♟': BLACK CHESS PAWN + ... + 1F600 '😀': GRINNING FACE + 1F609 '😉': WINKING FACE + ... Strictly, these definitions imply that it's meaningless to say 'this is -character ``U+12CA``'. ``U+12CA`` is a code point, which represents some particular -character; in this case, it represents the character 'ETHIOPIC SYLLABLE WI'. In +character ``U+265E``'. ``U+265E`` is a code point, which represents some particular +character; in this case, it represents the character 'BLACK CHESS KNIGHT', +'♞'. In informal contexts, this distinction between code points and characters will sometimes be forgotten. @@ -121,14 +85,17 @@ toolkit or a terminal's font renderer. Encodings --------- -To summarize the previous section: a Unicode string is a sequence of code -points, which are numbers from 0 through ``0x10FFFF`` (1,114,111 decimal). This -sequence needs to be represented as a set of bytes (meaning, values -from 0 through 255) in memory. The rules for translating a Unicode string -into a sequence of bytes are called an **encoding**. +To summarize the previous section: a Unicode string is a sequence of +code points, which are numbers from 0 through ``0x10FFFF`` (1,114,111 +decimal). This sequence of code points needs to be represented in +memory as a set of **code units**, and **code units** are then mapped +to 8-bit bytes. The rules for translating a Unicode string into a +sequence of bytes are called a **character encoding**, or just +an **encoding**. -The first encoding you might think of is an array of 32-bit integers. In this -representation, the string "Python" would look like this: +The first encoding you might think of is using 32-bit integers as the +code unit, and then using the CPU's representation of 32-bit integers. +In this representation, the string "Python" might look like this: .. code-block:: none @@ -152,40 +119,14 @@ problems. 3. It's not compatible with existing C functions such as ``strlen()``, so a new family of wide string functions would need to be used. -4. Many Internet standards are defined in terms of textual data, and can't - handle content with embedded zero bytes. - -Generally people don't use this encoding, instead choosing other -encodings that are more efficient and convenient. UTF-8 is probably -the most commonly supported encoding; it will be discussed below. - -Encodings don't have to handle every possible Unicode character, and most -encodings don't. The rules for converting a Unicode string into the ASCII -encoding, for example, are simple; for each code point: - -1. If the code point is < 128, each byte is the same as the value of the code - point. +Therefore this encoding isn't used very much, and people instead choose other +encodings that are more efficient and convenient, such as UTF-8. -2. If the code point is 128 or greater, the Unicode string can't be represented - in this encoding. (Python raises a :exc:`UnicodeEncodeError` exception in this - case.) - -Latin-1, also known as ISO-8859-1, is a similar encoding. Unicode code points -0--255 are identical to the Latin-1 values, so converting to this encoding simply -requires converting code points to byte values; if a code point larger than 255 -is encountered, the string can't be encoded into Latin-1. - -Encodings don't have to be simple one-to-one mappings like Latin-1. Consider -IBM's EBCDIC, which was used on IBM mainframes. Letter values weren't in one -block: 'a' through 'i' had values from 129 to 137, but 'j' through 'r' were 145 -through 153. If you wanted to use EBCDIC as an encoding, you'd probably use -some sort of lookup table to perform the conversion, but this is largely an -internal detail. - -UTF-8 is one of the most commonly used encodings. UTF stands for "Unicode -Transformation Format", and the '8' means that 8-bit numbers are used in the -encoding. (There are also a UTF-16 and UTF-32 encodings, but they are less -frequently used than UTF-8.) UTF-8 uses the following rules: +UTF-8 is one of the most commonly used encodings, and Python often +defaults to using it. UTF stands for "Unicode Transformation Format", +and the '8' means that 8-bit values are used in the encoding. (There +are also UTF-16 and UTF-32 encodings, but they are less frequently +used than UTF-8.) UTF-8 uses the following rules: 1. If the code point is < 128, it's represented by the corresponding byte value. 2. If the code point is >= 128, it's turned into a sequence of two, three, or @@ -215,6 +156,10 @@ glossary, and PDF versions of the Unicode specification. Be prepared for some difficult reading. `A chronology `_ of the origin and development of Unicode is also available on the site. +On the Computerphile Youtube channel, Tom Scott briefly +`discusses the history of Unicode and UTF-8 ` +(9 minutes 36 seconds). + To help understand the standard, Jukka Korpela has written `an introductory guide `_ to reading the Unicode character tables. @@ -238,7 +183,7 @@ Unicode features. The String Type --------------- -Since Python 3.0, the language features a :class:`str` type that contain Unicode +Since Python 3.0, the language's :class:`str` type contains Unicode characters, meaning any string created using ``"unicode rocks!"``, ``'unicode rocks!'``, or the triple-quoted string syntax is stored as Unicode. @@ -252,11 +197,6 @@ include a Unicode character in a string literal:: # 'File not found' error message. print("Fichier non trouvé") -You can use a different encoding from UTF-8 by putting a specially-formatted -comment as the first or second line of the source code:: - - # -*- coding: -*- - Side note: Python 3 also supports using Unicode characters in identifiers:: répertoire = "/tmp/records.log" @@ -299,7 +239,7 @@ The following examples show the differences:: >>> b'\x80abc'.decode("utf-8", "ignore") 'abc' -Encodings are specified as strings containing the encoding's name. Python 3.2 +Encodings are specified as strings containing the encoding's name. Python comes with roughly 100 different encodings; see the Python Library Reference at :ref:`standard-encodings` for a list. Some encodings have multiple names; for example, ``'latin-1'``, ``'iso_8859_1'`` and ``'8859``' are all synonyms for @@ -409,12 +349,13 @@ already mentioned. See also :pep:`263` for more information. Unicode Properties ------------------ -The Unicode specification includes a database of information about code points. -For each defined code point, the information includes the character's -name, its category, the numeric value if applicable (Unicode has characters -representing the Roman numerals and fractions such as one-third and -four-fifths). There are also properties related to the code point's use in -bidirectional text and other display-related properties. +The Unicode specification includes a database of information about +code points. For each defined code point, the information includes +the character's name, its category, the numeric value if applicable +(for characters representing numeric concepts such as the Roman +numerals, fractions such as one-third and four-fifths, etc.). There +are also display-related properties, such as how to use the code point +in bidirectional text. The following program displays some information about several characters, and prints the numeric value of one particular character:: @@ -451,6 +392,88 @@ other". See list of category codes. +Comparing Strings +----------------- + +Unicode adds some complication to comparing strings, because the same +set of characters can be represented by different sequences of code +points. For example, a letter like 'ê' can be represented as a single +code point U+00EA, or as U+0065 U+0302, which is the code point for +'e' followed by a code point for 'COMBINING CIRCUMFLEX ACCENT'. These +will produce the same output when printed, but one is a string of +length 1 and the other is of length 2. + +One tool for a case-insensitive comparison is the +:meth:`~str.casefold` string method that converts a string to a +case-insensitive form following an algorithm described by the Unicode +Standard. This algorithm has special handling for characters such as +the German letter 'ß' (code point U+00DF), which becomes the pair of +lowercase letters 'ss'. + +:: + + >>> street = 'Gürzenichstraße' + >>> street.casefold() + 'gürzenichstrasse' + +A second tool is the :mod:`unicodedata` module's +:func:`~unicodedata.normalize` function that converts strings to one +of several normal forms, where letters followed by a combining +character are replaced with single characters. :func:`normalize` can +be used to perform string comparisons that won't falsely report +inequality if two strings use combining characters differently: + +:: + + import unicodedata + + def compare_strs(s1, s2): + def NFD(s): + return unicodedata.normalize('NFD', s) + + return NFD(s1) == NFD(s2) + + single_char = 'ê' + multiple_chars = '\N{LATIN SMALL LETTER E}\N{COMBINING CIRCUMFLEX ACCENT}' + print('length of first string=', len(single_char)) + print('length of second string=', len(multiple_chars)) + print(compare_strs(single_char, multiple_chars)) + +When run, this outputs: + +.. code-block:: shell-session + + $ python3 compare-strs.py + length of first string= 1 + length of second string= 2 + True + +The first argument to the :func:`~unicodedata.normalize` function is a +string giving the desired normalization form, which can be one of +'NFC', 'NFKC', 'NFD', and 'NFKD'. + +The Unicode Standard also specifies how to do caseless comparisons:: + + import unicodedata + + def compare_caseless(s1, s2): + def NFD(s): + return unicodedata.normalize('NFD', s) + + return NFD(NFD(s1).casefold()) == NFD(NFD(s2).casefold()) + + # Example usage + single_char = 'ê' + multiple_chars = '\N{LATIN CAPITAL LETTER E}\N{COMBINING CIRCUMFLEX ACCENT}' + + print(compare_caseless(single_char, multiple_chars)) + +This will print ``True``. (Why is :func:`NFD` invoked twice? Because +there are a few characters that make :meth:`casefold` return a +non-normalized string, so the result needs to be normalized again. See +section 3.13 of the Unicode Standard for a discussion and an example.) + + Unicode Regular Expressions --------------------------- @@ -567,22 +590,22 @@ particular byte ordering and don't skip the BOM. In some areas, it is also convention to use a "BOM" at the start of UTF-8 encoded files; the name is misleading since UTF-8 is not byte-order dependent. -The mark simply announces that the file is encoded in UTF-8. Use the -'utf-8-sig' codec to automatically skip the mark if present for reading such -files. +The mark simply announces that the file is encoded in UTF-8. For reading such +files, use the 'utf-8-sig' codec to automatically skip the mark if present. Unicode filenames ----------------- -Most of the operating systems in common use today support filenames that contain -arbitrary Unicode characters. Usually this is implemented by converting the -Unicode string into some encoding that varies depending on the system. For -example, Mac OS X uses UTF-8 while Windows uses a configurable encoding; on -Windows, Python uses the name "mbcs" to refer to whatever the currently -configured encoding is. On Unix systems, there will only be a filesystem -encoding if you've set the ``LANG`` or ``LC_CTYPE`` environment variables; if -you haven't, the default encoding is UTF-8. +Most of the operating systems in common use today support filenames +that contain arbitrary Unicode characters. Usually this is +implemented by converting the Unicode string into some encoding that +varies depending on the system. Today Python is converging on using +UTF-8: Python on MacOS has used UTF-8 for several versions, and Python +3.6 switched to using UTF-8 on Windows as well. On Unix systems, +there will only be a filesystem encoding if you've set the ``LANG`` or +``LC_CTYPE`` environment variables; if you haven't, the default +encoding is again UTF-8. The :func:`sys.getfilesystemencoding` function returns the encoding to use on your current system, in case you want to do the encoding manually, but there's @@ -597,9 +620,9 @@ automatically converted to the right encoding for you:: Functions in the :mod:`os` module such as :func:`os.stat` will also accept Unicode filenames. -The :func:`os.listdir` function returns filenames and raises an issue: should it return +The :func:`os.listdir` function returns filenames, which raises an issue: should it return the Unicode version of filenames, or should it return bytes containing -the encoded versions? :func:`os.listdir` will do both, depending on whether you +the encoded versions? :func:`os.listdir` can do both, depending on whether you provided the directory path as bytes or a Unicode string. If you pass a Unicode string as the path, filenames will be decoded using the filesystem's encoding and a list of Unicode strings will be returned, while passing a byte @@ -619,16 +642,17 @@ will produce the following output: .. code-block:: shell-session - amk:~$ python t.py + $ python listdir-test.py [b'filename\xe4\x94\x80abc', ...] ['filename\u4500abc', ...] The first list contains UTF-8-encoded filenames, and the second list contains the Unicode versions. -Note that on most occasions, the Unicode APIs should be used. The bytes APIs -should only be used on systems where undecodable file names can be present, -i.e. Unix systems. +Note that on most occasions, you should can just stick with using +Unicode with these APIs. The bytes APIs should only be used on +systems where undecodable file names can be present; that's +pretty much only Unix systems now. Tips for Writing Unicode-aware Programs @@ -695,10 +719,10 @@ with the ``surrogateescape`` error handler:: f.write(data) The ``surrogateescape`` error handler will decode any non-ASCII bytes -as code points in the Unicode Private Use Area ranging from U+DC80 to -U+DCFF. These private code points will then be turned back into the -same bytes when the ``surrogateescape`` error handler is used when -encoding the data and writing it back out. +as code points in a special range running from U+DC80 to +U+DCFF. These code points will then turn back into the +same bytes when the ``surrogateescape`` error handler is used to +encode the data and write it back out. References @@ -730,4 +754,5 @@ Andrew Kuchling, and Ezio Melotti. Thanks to the following people who have noted errors or offered suggestions on this article: Éric Araujo, Nicholas Bastin, Nick Coghlan, Marius Gedminas, Kent Johnson, Ken Krugler, Marc-André -Lemburg, Martin von Löwis, Terry J. Reedy, Chad Whitacre. +Lemburg, Martin von Löwis, Terry J. Reedy, Serhiy Storchaka, +Eryk Sun, Chad Whitacre, Graham Wideman. diff --git a/kbe/src/lib/python/Doc/library/aifc.rst b/kbe/src/lib/python/Doc/library/aifc.rst index 970a7aeb98..7328907730 100644 --- a/kbe/src/lib/python/Doc/library/aifc.rst +++ b/kbe/src/lib/python/Doc/library/aifc.rst @@ -45,7 +45,7 @@ Module :mod:`aifc` defines the following function: time how many samples you are going to write in total and use :meth:`writeframesraw` and :meth:`setnframes`. The :func:`.open` function may be used in a :keyword:`with` statement. When - the :keyword:`with` block completes, the :meth:`~aifc.close` method is called. + the :keyword:`!with` block completes, the :meth:`~aifc.close` method is called. .. versionchanged:: 3.4 Support for the :keyword:`with` statement was added. diff --git a/kbe/src/lib/python/Doc/library/asyncio-eventloop.rst b/kbe/src/lib/python/Doc/library/asyncio-eventloop.rst index 647b7fc5e7..d59cf055b6 100644 --- a/kbe/src/lib/python/Doc/library/asyncio-eventloop.rst +++ b/kbe/src/lib/python/Doc/library/asyncio-eventloop.rst @@ -960,12 +960,20 @@ Unix signals Set *callback* as the handler for the *signum* signal. + The callback will be invoked by *loop*, along with other queued callbacks + and runnable coroutines of that event loop. Unlike signal handlers + registered using :func:`signal.signal`, a callback registered with this + function is allowed to interact with the event loop. + Raise :exc:`ValueError` if the signal number is invalid or uncatchable. Raise :exc:`RuntimeError` if there is a problem setting up the handler. Use :func:`functools.partial` :ref:`to pass keyword arguments ` to *callback*. + Like :func:`signal.signal`, this function must be invoked in the main + thread. + .. method:: loop.remove_signal_handler(sig) Remove the handler for the *sig* signal. diff --git a/kbe/src/lib/python/Doc/library/asyncio-exceptions.rst b/kbe/src/lib/python/Doc/library/asyncio-exceptions.rst index dbd5df7208..e49577a203 100644 --- a/kbe/src/lib/python/Doc/library/asyncio-exceptions.rst +++ b/kbe/src/lib/python/Doc/library/asyncio-exceptions.rst @@ -65,11 +65,11 @@ Exceptions .. exception:: IncompleteReadError - The requested read operation did not complete fully. + The requested read operation did not complete fully. - Raised by the :ref:`asyncio stream APIs`. + Raised by the :ref:`asyncio stream APIs`. - This exception is a subclass of :exc:`EOFError`. + This exception is a subclass of :exc:`EOFError`. .. attribute:: expected diff --git a/kbe/src/lib/python/Doc/library/asyncio-policy.rst b/kbe/src/lib/python/Doc/library/asyncio-policy.rst index cab25934d7..07842daa28 100644 --- a/kbe/src/lib/python/Doc/library/asyncio-policy.rst +++ b/kbe/src/lib/python/Doc/library/asyncio-policy.rst @@ -81,7 +81,7 @@ The abstract event loop policy base class is defined as follows: .. method:: set_child_watcher(watcher) - Get the current child process watcher to *watcher*. + Set the current child process watcher to *watcher*. This function is Unix specific. diff --git a/kbe/src/lib/python/Doc/library/asyncio-queue.rst b/kbe/src/lib/python/Doc/library/asyncio-queue.rst index bd0e70c0d9..7be1023c80 100644 --- a/kbe/src/lib/python/Doc/library/asyncio-queue.rst +++ b/kbe/src/lib/python/Doc/library/asyncio-queue.rst @@ -64,7 +64,7 @@ Queue Block until all items in the queue have been received and processed. The count of unfinished tasks goes up whenever an item is added - to the queue. The count goes down whenever a consumer thread calls + to the queue. The count goes down whenever a consumer coroutine calls :meth:`task_done` to indicate that the item was retrieved and all work on it is complete. When the count of unfinished tasks drops to zero, :meth:`join` unblocks. diff --git a/kbe/src/lib/python/Doc/library/asyncio-task.rst b/kbe/src/lib/python/Doc/library/asyncio-task.rst index 376de8f404..9e685b1764 100644 --- a/kbe/src/lib/python/Doc/library/asyncio-task.rst +++ b/kbe/src/lib/python/Doc/library/asyncio-task.rst @@ -604,7 +604,7 @@ Scheduling From Other Threads See the :ref:`concurrency and multithreading ` section of the documentation. - Unlike other asyncio functions this functions requires the *loop* + Unlike other asyncio functions this function requires the *loop* argument to be passed explicitly. .. versionadded:: 3.5.1 diff --git a/kbe/src/lib/python/Doc/library/binascii.rst b/kbe/src/lib/python/Doc/library/binascii.rst index a4efef8465..89ecddc778 100644 --- a/kbe/src/lib/python/Doc/library/binascii.rst +++ b/kbe/src/lib/python/Doc/library/binascii.rst @@ -152,6 +152,8 @@ The :mod:`binascii` module defines the following functions: *data* is converted into the corresponding 2-digit hex representation. The returned bytes object is therefore twice as long as the length of *data*. + Similar functionality (but returning a text string) is also conveniently + accessible using the :meth:`bytes.hex` method. .. function:: a2b_hex(hexstr) unhexlify(hexstr) @@ -161,6 +163,9 @@ The :mod:`binascii` module defines the following functions: of hexadecimal digits (which can be upper or lower case), otherwise an :exc:`Error` exception is raised. + Similar functionality (accepting only text string arguments, but more + liberal towards whitespace) is also accessible using the + :meth:`bytes.fromhex` class method. .. exception:: Error diff --git a/kbe/src/lib/python/Doc/library/collections.rst b/kbe/src/lib/python/Doc/library/collections.rst index 016e56c4bd..0413f46922 100644 --- a/kbe/src/lib/python/Doc/library/collections.rst +++ b/kbe/src/lib/python/Doc/library/collections.rst @@ -100,6 +100,21 @@ The class can be used to simulate nested scopes and is useful in templating. :func:`super` function. A reference to ``d.parents`` is equivalent to: ``ChainMap(*d.maps[1:])``. + Note, the iteration order of a :class:`ChainMap()` is determined by + scanning the mappings last to first:: + + >>> baseline = {'music': 'bach', 'art': 'rembrandt'} + >>> adjustments = {'art': 'van gogh', 'opera': 'carmen'} + >>> list(ChainMap(adjustments, baseline)) + ['music', 'art', 'opera'] + + This gives the same ordering as a series of :meth:`dict.update` calls + starting with the last mapping:: + + >>> combined = baseline.copy() + >>> combined.update(adjustments) + >>> list(combined) + ['music', 'art', 'opera'] .. seealso:: @@ -163,8 +178,8 @@ contexts:: e.maps[-1] # Root context -- like Python's globals() e.parents # Enclosing context chain -- like Python's nonlocals - d['x'] # Get first key in the chain of contexts d['x'] = 1 # Set value in current context + d['x'] # Get first key in the chain of contexts del d['x'] # Delete from current context list(d) # All nested values k in d # Check all nested values @@ -887,7 +902,7 @@ field names, the method and attribute names start with an underscore. .. method:: somenamedtuple._asdict() - Return a new :class:`OrderedDict` which maps field names to their corresponding + Return a new :class:`dict` which maps field names to their corresponding values: .. doctest:: @@ -1017,17 +1032,41 @@ customize a prototype instance: :class:`OrderedDict` objects ---------------------------- -Ordered dictionaries are just like regular dictionaries but they remember the -order that items were inserted. When iterating over an ordered dictionary, -the items are returned in the order their keys were first added. +Ordered dictionaries are just like regular dictionaries but have some extra +capabilities relating to ordering operations. They have become less +important now that the built-in :class:`dict` class gained the ability +to remember insertion order (this new behavior became guaranteed in +Python 3.7). + +Some differences from :class:`dict` still remain: + +* The regular :class:`dict` was designed to be very good at mapping + operations. Tracking insertion order was secondary. + +* The :class:`OrderedDict` was designed to be good at reordering operations. + Space efficiency, iteration speed, and the performance of update + operations were secondary. + +* Algorithmically, :class:`OrderedDict` can handle frequent reordering + operations better than :class:`dict`. This makes it suitable for tracking + recent accesses (for example in an `LRU cache + `_). + +* The equality operation for :class:`OrderedDict` checks for matching order. + +* The :meth:`popitem` method of :class:`OrderedDict` has a different + signature. It accepts an optional argument to specify which item is popped. + +* :class:`OrderedDict` has a :meth:`move_to_end` method to + efficiently reposition an element to an endpoint. + +* Until Python 3.8, :class:`dict` lacked a :meth:`__reversed__` method. + .. class:: OrderedDict([items]) - Return an instance of a dict subclass, supporting the usual :class:`dict` - methods. An *OrderedDict* is a dict that remembers the order that keys - were first inserted. If a new entry overwrites an existing entry, the - original insertion position is left unchanged. Deleting an entry and - reinserting it will move it to the end. + Return an instance of a :class:`dict` subclass that has methods + specialized for rearranging dictionary order. .. versionadded:: 3.1 @@ -1077,29 +1116,7 @@ anywhere a regular dictionary is used. :class:`OrderedDict` Examples and Recipes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Since an ordered dictionary remembers its insertion order, it can be used -in conjunction with sorting to make a sorted dictionary:: - - >>> # regular unsorted dictionary - >>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2} - - >>> # dictionary sorted by key - >>> OrderedDict(sorted(d.items(), key=lambda t: t[0])) - OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)]) - - >>> # dictionary sorted by value - >>> OrderedDict(sorted(d.items(), key=lambda t: t[1])) - OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)]) - - >>> # dictionary sorted by length of the key string - >>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0]))) - OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)]) - -The new sorted dictionaries maintain their sort order when entries -are deleted. But when new keys are added, the keys are appended -to the end and the sort is not maintained. - -It is also straight-forward to create an ordered dictionary variant +It is straightforward to create an ordered dictionary variant that remembers the order the keys were *last* inserted. If a new entry overwrites an existing entry, the original insertion position is changed and moved to the end:: @@ -1108,21 +1125,29 @@ original insertion position is changed and moved to the end:: 'Store items in the order the keys were last added' def __setitem__(self, key, value): - if key in self: - del self[key] - OrderedDict.__setitem__(self, key, value) + super().__setitem__(key, value) + super().move_to_end(key) -An ordered dictionary can be combined with the :class:`Counter` class -so that the counter remembers the order elements are first encountered:: +An :class:`OrderedDict` would also be useful for implementing +variants of :func:`functools.lru_cache`:: - class OrderedCounter(Counter, OrderedDict): - 'Counter that remembers the order elements are first encountered' + class LRU(OrderedDict): + 'Limit size, evicting the least recently looked-up key when full' - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, OrderedDict(self)) + def __init__(self, maxsize=128, *args, **kwds): + self.maxsize = maxsize + super().__init__(*args, **kwds) - def __reduce__(self): - return self.__class__, (OrderedDict(self),) + def __getitem__(self, key): + value = super().__getitem__(key) + self.move_to_end(key) + return value + + def __setitem__(self, key, value): + super().__setitem__(key, value) + if len(self) > self.maxsize: + oldest = next(iter(self)) + del self[oldest] :class:`UserDict` objects diff --git a/kbe/src/lib/python/Doc/library/compileall.rst b/kbe/src/lib/python/Doc/library/compileall.rst index 5151f3a523..258de28e3b 100644 --- a/kbe/src/lib/python/Doc/library/compileall.rst +++ b/kbe/src/lib/python/Doc/library/compileall.rst @@ -105,7 +105,7 @@ compile Python sources. byte-code file ending in ``.pyc``, never ``.pyo``. .. versionchanged:: 3.7 - Added the ``--invalidation-mode`` parameter. + Added the ``--invalidation-mode`` option. There is no command-line option to control the optimization level used by the diff --git a/kbe/src/lib/python/Doc/library/configparser.rst b/kbe/src/lib/python/Doc/library/configparser.rst index 321770242b..95cc352010 100644 --- a/kbe/src/lib/python/Doc/library/configparser.rst +++ b/kbe/src/lib/python/Doc/library/configparser.rst @@ -462,7 +462,8 @@ the :meth:`__init__` options: Please note: there are ways to add a set of key-value pairs in a single operation. When you use a regular dictionary in those operations, the order - of the keys may be random. For example: + of the keys will be ordered because dict preserves order from Python 3.7. + For example: .. doctest:: @@ -477,41 +478,10 @@ the :meth:`__init__` options: ... 'bar': 'y', ... 'baz': 'z'} ... }) - >>> parser.sections() # doctest: +SKIP - ['section3', 'section2', 'section1'] - >>> [option for option in parser['section3']] # doctest: +SKIP - ['baz', 'foo', 'bar'] - - In these operations you need to use an ordered dictionary as well: - - .. doctest:: - - >>> from collections import OrderedDict - >>> parser = configparser.ConfigParser() - >>> parser.read_dict( - ... OrderedDict(( - ... ('s1', - ... OrderedDict(( - ... ('1', '2'), - ... ('3', '4'), - ... ('5', '6'), - ... )) - ... ), - ... ('s2', - ... OrderedDict(( - ... ('a', 'b'), - ... ('c', 'd'), - ... ('e', 'f'), - ... )) - ... ), - ... )) - ... ) - >>> parser.sections() # doctest: +SKIP - ['s1', 's2'] - >>> [option for option in parser['s1']] # doctest: +SKIP - ['1', '3', '5'] - >>> [option for option in parser['s2'].values()] # doctest: +SKIP - ['b', 'd', 'f'] + >>> parser.sections() + ['section1', 'section2', 'section3'] + >>> [option for option in parser['section3']] + ['foo', 'bar', 'baz'] * *allow_no_value*, default value: ``False`` @@ -891,7 +861,7 @@ interpolation if an option used is not defined elsewhere. :: ConfigParser Objects -------------------- -.. class:: ConfigParser(defaults=None, dict_type=dict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation(), converters={}) +.. class:: ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation(), converters={}) The main configuration parser. When *defaults* is given, it is initialized into the dictionary of intrinsic defaults. When *dict_type* is given, it @@ -953,10 +923,6 @@ ConfigParser Objects providing consistent behavior across the parser: non-string keys and values are implicitly converted to strings. - .. versionchanged:: 3.7 - The default *dict_type* is :class:`dict`, since it now preserves - insertion order. - .. method:: defaults() Return a dictionary containing the instance-wide defaults. @@ -1213,7 +1179,7 @@ ConfigParser Objects RawConfigParser Objects ----------------------- -.. class:: RawConfigParser(defaults=None, dict_type=dict, \ +.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, \ allow_no_value=False, *, delimiters=('=', ':'), \ comment_prefixes=('#', ';'), \ inline_comment_prefixes=None, strict=True, \ @@ -1226,10 +1192,6 @@ RawConfigParser Objects names, and values via its unsafe ``add_section`` and ``set`` methods, as well as the legacy ``defaults=`` keyword argument handling. - .. versionchanged:: 3.7 - The default *dict_type* is :class:`dict`, since it now preserves - insertion order. - .. note:: Consider using :class:`ConfigParser` instead which checks types of the values to be stored internally. If you don't want interpolation, you diff --git a/kbe/src/lib/python/Doc/library/contextlib.rst b/kbe/src/lib/python/Doc/library/contextlib.rst index 930c97358e..017a87a564 100644 --- a/kbe/src/lib/python/Doc/library/contextlib.rst +++ b/kbe/src/lib/python/Doc/library/contextlib.rst @@ -1,5 +1,5 @@ -:mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts -======================================================================== +:mod:`!contextlib` --- Utilities for :keyword:`!with`\ -statement contexts +========================================================================== .. module:: contextlib :synopsis: Utilities for with-statement contexts. @@ -72,7 +72,7 @@ Functions and classes provided: The function being decorated must return a :term:`generator`-iterator when called. This iterator must yield exactly one value, which will be bound to - the targets in the :keyword:`with` statement's :keyword:`as` clause, if any. + the targets in the :keyword:`with` statement's :keyword:`!as` clause, if any. At the point where the generator yields, the block nested in the :keyword:`with` statement is executed. The generator is then resumed after the block is exited. @@ -82,9 +82,9 @@ Functions and classes provided: the error (if any), or ensure that some cleanup takes place. If an exception is trapped merely in order to log it or to perform some action (rather than to suppress it entirely), the generator must reraise that exception. Otherwise the - generator context manager will indicate to the :keyword:`with` statement that + generator context manager will indicate to the :keyword:`!with` statement that the exception has been handled, and execution will resume with the statement - immediately following the :keyword:`with` statement. + immediately following the :keyword:`!with` statement. :func:`contextmanager` uses :class:`ContextDecorator` so the context managers it creates can be used as decorators as well as in :keyword:`with` statements. @@ -346,7 +346,7 @@ Functions and classes provided: As the decorated function must be able to be called multiple times, the underlying context manager must support use in multiple :keyword:`with` statements. If this is not the case, then the original construct with the - explicit :keyword:`with` statement inside the function should be used. + explicit :keyword:`!with` statement inside the function should be used. .. versionadded:: 3.2 @@ -771,7 +771,7 @@ Reentrant context managers More sophisticated context managers may be "reentrant". These context managers can not only be used in multiple :keyword:`with` statements, -but may also be used *inside* a :keyword:`with` statement that is already +but may also be used *inside* a :keyword:`!with` statement that is already using the same context manager. :class:`threading.RLock` is an example of a reentrant context manager, as are diff --git a/kbe/src/lib/python/Doc/library/dataclasses.rst b/kbe/src/lib/python/Doc/library/dataclasses.rst index fe0feeda8b..6af60b6e26 100644 --- a/kbe/src/lib/python/Doc/library/dataclasses.rst +++ b/kbe/src/lib/python/Doc/library/dataclasses.rst @@ -51,9 +51,9 @@ Module-level decorators, classes, and functions The :func:`dataclass` decorator examines the class to find ``field``\s. A ``field`` is defined as class variable that has a - type annotation. With two exceptions described below, nothing in - :func:`dataclass` examines the type specified in the variable - annotation. + :term:`type annotation `. With two + exceptions described below, nothing in :func:`dataclass` + examines the type specified in the variable annotation. The order of the fields in all of the generated methods is the order in which they appear in the class definition. diff --git a/kbe/src/lib/python/Doc/library/datetime.rst b/kbe/src/lib/python/Doc/library/datetime.rst index db3a6522c2..121f73bbe8 100644 --- a/kbe/src/lib/python/Doc/library/datetime.rst +++ b/kbe/src/lib/python/Doc/library/datetime.rst @@ -2034,6 +2034,12 @@ calls the platform C library's :func:`strftime` function, and platform variations are common. To see the full set of format codes supported on your platform, consult the :manpage:`strftime(3)` documentation. +For the same reason, handling of format strings containing Unicode code points +that can't be represented in the charset of the current locale is also +platform-dependent. On some platforms such code points are preserved intact in +the output, while on others ``strftime`` may raise :exc:`UnicodeError` or return +an empty string instead. + The following is a list of all the format codes that the C standard (1989 version) requires, and these work on all platforms with a standard C implementation. Note that the 1999 version of the C standard added additional diff --git a/kbe/src/lib/python/Doc/library/decimal.rst b/kbe/src/lib/python/Doc/library/decimal.rst index f2a677e693..bcae55eb82 100644 --- a/kbe/src/lib/python/Doc/library/decimal.rst +++ b/kbe/src/lib/python/Doc/library/decimal.rst @@ -2115,3 +2115,23 @@ Alternatively, inputs can be rounded upon creation using the >>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678') Decimal('1.2345') + +Q. Is the CPython implementation fast for large numbers? + +A. Yes. In the CPython and PyPy3 implementations, the C/CFFI versions of +the decimal module integrate the high speed `libmpdec +`_ library for +arbitrary precision correctly-rounded decimal floating point arithmetic. +``libmpdec`` uses `Karatsuba multiplication +`_ +for medium-sized numbers and the `Number Theoretic Transform +`_ +for very large numbers. However, to realize this performance gain, the +context needs to be set for unrounded calculations. + + >>> c = getcontext() + >>> c.prec = MAX_PREC + >>> c.Emax = MAX_EMAX + >>> c.Emin = MIN_EMIN + +.. versionadded:: 3.3 \ No newline at end of file diff --git a/kbe/src/lib/python/Doc/library/enum.rst b/kbe/src/lib/python/Doc/library/enum.rst index 81e9766e42..a6285ffaf1 100644 --- a/kbe/src/lib/python/Doc/library/enum.rst +++ b/kbe/src/lib/python/Doc/library/enum.rst @@ -394,7 +394,7 @@ A new :class:`Enum` class must have one base Enum class, up to one concrete data type, and as many :class:`object`-based mixin classes as needed. The order of these base classes is:: - def EnumName([mix-in, ...,] [data-type,] base-enum): + class EnumName([mix-in, ...,] [data-type,] base-enum): pass Also, subclassing an enumeration is allowed only if the enumeration does not define diff --git a/kbe/src/lib/python/Doc/library/fileinput.rst b/kbe/src/lib/python/Doc/library/fileinput.rst index 5881fefe29..1fc11ffce2 100644 --- a/kbe/src/lib/python/Doc/library/fileinput.rst +++ b/kbe/src/lib/python/Doc/library/fileinput.rst @@ -63,7 +63,7 @@ The following function is the primary interface of this module: The :class:`FileInput` instance can be used as a context manager in the :keyword:`with` statement. In this example, *input* is closed after the - :keyword:`with` statement is exited, even if an exception occurs:: + :keyword:`!with` statement is exited, even if an exception occurs:: with fileinput.input(files=('spam.txt', 'eggs.txt')) as f: for line in f: @@ -155,7 +155,7 @@ available for subclassing as well: A :class:`FileInput` instance can be used as a context manager in the :keyword:`with` statement. In this example, *input* is closed after the - :keyword:`with` statement is exited, even if an exception occurs:: + :keyword:`!with` statement is exited, even if an exception occurs:: with FileInput(files=('spam.txt', 'eggs.txt')) as input: process(input) diff --git a/kbe/src/lib/python/Doc/library/functions.rst b/kbe/src/lib/python/Doc/library/functions.rst index c0f4ffd2cb..9326b8d0fe 100644 --- a/kbe/src/lib/python/Doc/library/functions.rst +++ b/kbe/src/lib/python/Doc/library/functions.rst @@ -668,6 +668,11 @@ are always available. They are listed here in alphabetical order. topic, and a help page is printed on the console. If the argument is any other kind of object, a help page on the object is generated. + Note that if a slash(/) appears in the parameter list of a function, when + invoking :func:`help`, it means that the parameters prior to the slash are + positional-only. For more info, see + :ref:`the FAQ entry on positional-only parameters `. + This function is added to the built-in namespace by the :mod:`site` module. .. versionchanged:: 3.4 @@ -809,13 +814,14 @@ are always available. They are listed here in alphabetical order. See also :ref:`typeiter`. - One useful application of the second form of :func:`iter` is to read lines of - a file until a certain line is reached. The following example reads a file - until the :meth:`~io.TextIOBase.readline` method returns an empty string:: + One useful application of the second form of :func:`iter` is to build a + block-reader. For example, reading fixed-width blocks from a binary + database file until the end of file is reached:: - with open('mydata.txt') as fp: - for line in iter(fp.readline, ''): - process_line(line) + from functools import partial + with open('mydata.db', 'rb') as f: + for block in iter(partial(f.read, 64), b''): + process_block(block) .. function:: len(s) @@ -996,7 +1002,6 @@ are always available. They are listed here in alphabetical order. ``'b'`` binary mode ``'t'`` text mode (default) ``'+'`` open a disk file for updating (reading and writing) - ``'U'`` :term:`universal newlines` mode (deprecated) ========= =============================================================== The default mode is ``'r'`` (open for reading text, synonym of ``'rt'``). @@ -1011,6 +1016,12 @@ are always available. They are listed here in alphabetical order. first decoded using a platform-dependent encoding or using the specified *encoding* if given. + There is an additional mode character permitted, ``'U'``, which no longer + has any effect, and is considered deprecated. It previously enabled + :term:`universal newlines` in text mode, which became the default behaviour + in Python 3.0. Refer to the documentation of the + :ref:`newline ` parameter for further details. + .. note:: Python doesn't depend on the underlying operating system's notion of text @@ -1077,6 +1088,8 @@ are always available. They are listed here in alphabetical order. .. index:: single: universal newlines; open() built-in function + .. _open-newline-parameter: + *newline* controls how :term:`universal newlines` mode works (it only applies to text mode). It can be ``None``, ``''``, ``'\n'``, ``'\r'``, and ``'\r\n'``. It works as follows: @@ -1655,7 +1668,7 @@ are always available. They are listed here in alphabetical order. This function is invoked by the :keyword:`import` statement. It can be replaced (by importing the :mod:`builtins` module and assigning to ``builtins.__import__``) in order to change semantics of the - :keyword:`import` statement, but doing so is **strongly** discouraged as it + :keyword:`!import` statement, but doing so is **strongly** discouraged as it is usually simpler to use import hooks (see :pep:`302`) to attain the same goals and does not cause issues with code which assumes the default import implementation is in use. Direct use of :func:`__import__` is also diff --git a/kbe/src/lib/python/Doc/library/http.client.rst b/kbe/src/lib/python/Doc/library/http.client.rst index c4b7c79730..3408c103e2 100644 --- a/kbe/src/lib/python/Doc/library/http.client.rst +++ b/kbe/src/lib/python/Doc/library/http.client.rst @@ -497,6 +497,7 @@ Here is an example session that uses the ``GET`` method:: b'\ndc^hYnFV`hLppYL z)PJNLj455pQmb@I6m&%$D!sRe=u+P(cKWOblE`dNLh?p>x>VOWuv3jU{@GpZ3f$AG zeOKZS_Yw>K`?FtkJ343?7$ZN)z|rV85W3@rJ(Id$%bIL!DEZeMS|O?kPPxr3NjHf@ zR(~4l*FPi~j_Nd}2y*RG&&8q5r+_oU)_n zrrPd#(wp4iRomY~50WvncYIf=0UzP6N$;%_+Y42u2u+Nyw-V~h%;wjy4A!4LweYY~ z^`Hags=Jr5R|kEJ;d^Zw$=u=CX2`v8iLw$LAG&w7x^`mw{cz!Hh7GmI(bqpVY1OUXkgq#85>Ol_ zEkZZq^jrSm2*wP529`RWvEI2f`N&$gQlCebUn`P&#U8-@j+rdh$O$%Uzxp8FdqEGqErcI4Ccz@C z5==0Ck=P=_TL0Cydop|DrS6OWxN*duWA+3B*Mq;_&VASNfA)kBY{f*fW82|uHU6+AT0u+~a))Ntb-8}nq+cuNG`>((; z)1mZz64Uf?-;Jm4oa?xW=bA)gJMHxHWjGK8NvtW7<-@kF*Z=+Y0e}GYjN9JaTxKFm zB(PZQF7|~5f*?4lm$FhbQIt(uZWnMJ}c)%@^=q zHWtuB+AM`k@W)vw%TndDP$V*k|5ddX0JTvkQ`I~um5WkVwW=dgrltNa7AjYj%q+a- zAx!}1yirw-1^|ENQSspegrK}Nq1{{go0+133^i1o2M&%7O&oT!&_%ScCtat#d zfe8dQMM#yPhWNo8j{(W+ypEv5Ud8lM*em}@6 z2XfR5X9nZ9O`6paei~SHQ#Hl3C^Bv|Z}X&qU$uD;L;#xWw}3Sf#k{vwNo#jnqAUSHnq?$oSHlwI9_>CMlRpJSNb#ec-t@87g%-_Ky%;hPaDCz5YwQF|ST~_nkA$KAqNVQ)C1Q|6Se)4L zyjs)@O6Ufs2*$&bl~$r6-Hyj_+HJG|1W!@F>G5$%M;^Y=K%9y2x8J$Nsrc>pP)qi} zou$**=!Iww+GY@nF#4rP^8vh!>M~24!Enfb&AoXN5GL$O-dVbm9v{%>NO#Z_eTFin zPQ?JF=L0B~5sKBv(H8a%#rRuKO?VtppziXHM$|$S(_d85Py-rVi1Ao}s%=+bXc|(o zGZ>fEeVEIY3P~}CTGfW)POWQan$$n<Fmb00bac?Mf<^B>@OU4YiogsbOlfX^ z8W=1-8j3W9*mKIHA=jo=GYhEeh8R{x>Ya| z0khM6V%TjSeKeDh`FgODure8$5rZ8%C>gtFXV5c<{e}^E3=%z)c$((2N>x377}_?* zw}|k|z&^%*AxjD>PLzoj)>bh$Vl!(Mat$?{elZ@?w8w_Pp%3giG+;8=7Whch!90t? z5jtGSU8e3;cJ{@{0vUR%1)ZR{QlOmD#93^1r8Kev0-k*@vwG)BL2qeeb$pMG6E1mN z{WAroY?bC@U}5OCZqUkQvO$V}d#i*9tY)9MQnsuQ#{5+Lv{XP`Xj##MFe?P{7>~IT zia0yUz=D~-9Qp)`VHtzOpmcrMSV-l%SwfS01tt^h&gOePYoDnV_{ikz z@q5sz^p`|%9T$1F26Q~1Z2%|^h9mJ?cnZ`!4S#1Tt!XMVg$}=ha6{F9u_iVE7;FsQ za}NLI%o`FciS2=8wJ0z00$g)`xc0$a0p(D6^IKB zk`ybzL1{>J(N>9~_EidTk&UeI$+#|6lFrjauQP};YFuP%5;6d$fh=TOK@_E|%|y={ zf*2gD1SCPhM@FM;6$Ofab#_wL(SPJtxqiK`Bm$7ryqh;VS!Q|Q5abMkLl2)6J2e0= zZw$=>AJllvf;cvU2$F6^55A+YA?ZPD_!8C!q*7Ws<8fY$VS1VsQ?g|m0!qV}CF6|5 z&9>>mGQ=Wa+@a$vgA@Y*=?sA^=|MTo(G(4%z}07(Ki;~x@Aol(&Xrv52MVz|^@cpe zI6~_J947?UlIy&7R9gknX)3HV8dcZknS!u5*aW2&IkNRWl_E4sD)if;8h_UPJ9%b7 zKl7fSELB#+BbHf;k3r@#Xcc*q4{RY3PNRjX_la(dW& zIaqfb46fUpk{c;G*ao^l=-@=5HlyGtzfY?o$CV=P!Sv(ISlP5_g*w&*3HkP*R1hUC zro&?>Q>kCu6wrr(npS2o;y&^`6NoseVi0hUnH0z=Mb{aB%(BF+2DyQeX7pGOGVa+N%T;)sC7s(WEXp`&)VpW0qlqaU(3i9u3Sz^$^#XOzY*#82nf zn70~<%j@fR*9_|7`s()T;`|5jT^0*y=fWZPzaB<^;qi*7tcnGSNIaE?WYjbrLsO58 zE)4ww#{^m~i!?Eu<{$N02KISiQ*{yMB_P`O2_9O(>C^m%Z0ni^!1&3GZId81SmQO2 z`9moF-gWzLo%PumSNvUsAH_fqd@4TE--e$+L*T>#;|47-e5Ehrd73Hn3*1kB=@`B4 z_X^^FXD~o#0XV12z+KrBcz{!u!st)V?W5p8e=tQysirgsvE6TZUIHt?f2!{&wxbS? z(xTserR6^S%k2jUz~lO`IvU8)673LX($2n^%N@B4s$!6|Ni zJk0+6BfXE{$vr+Ss^%zefVYoHh66Lvt$J2}+kM8fNjG%Z*Y0HA$j5Zmu0-ChrWh^H zg&AJSWQj3Ht~j9QogE>YMy<-mbzuXuXzZF{JqGUjF^dM<7W;({yqrd!{oWvu-xbS!Is z__0ur``6yN;6|+5$a=t61SMQhhFJJw?7kRNcaJDL@c5La;O~1KF?Y&9fkm%jG}Z@$ zes;-8iPH<6K;$Q#`hR9D?8B0_D{*f#tCXCr8Gfhm$73FF%map9zJ=-Fq2s*WVz}_1 zF}pF_6P4s3=;r*bO7iL{*2@B{uQo%6ZTiB0EP! z+taDmie z{gg^s*HY^-wC11Xx=i_(Lpuwx&*=BpKlF%)JH}B>2`KE~((F44-V5|VD>R`@mY9HW z%7qeFwCTK|dWVrmt6Qub&~~bS1ShXy$EZ?eQK#T`aC$FGWv=(fCYKZO_2*yu#*B16 zA?WrzpIi+ot;4B8@GmPcjQA##DaBJB6zvq$a-}|rH(EnBm5eP>jgH)*3Q5C32bWVD zI?e-FZ__&+tM=-tZAy*VcZq`_|7vo_HRoth#d}&ci7N+0z}$^AA7y`k%p@Xl!<@8b zA)1_3OG%iGESlHZQDWqW&h}eaN4j_16{J8U*YsT<{~(qbjfmsA#_t2wMNR86qd zN@Emqv20cusmc+`fv!(~qBw+Uwnda=l`J9bt|LJ(dDRj~=!Kw8pFgLOuu3Wff$ElY zKOrsx8Wb5uV;a!L^>=guSYY6(D}Kltkdzvem&*bo-X}5##9MW)jaa3I=V;ekg&-7BO=(Jq#MB5lO1019Dtd@1jh zxR)8I$v$0?nE6_~zP+8?^oi!|cRXF76Bg(W)`mbk!~9{1MzQLPba-I~FnKMreS@O2 zNRepn)(*mmoZa7$teP&QaMMRCK!b`0O%Bo}p6l2@oqCm*CPrWz(dFQm|zCbrXkiZ{y3>nlRe*}K?jyzl%K$2AyiXlVA|n;I3NOY zQOychIr_y0Fq2@08N{Nb_Q8;eZ?&j~YqY5pKVICRE{(!rw}$H~Ibd?31=EZ7blvY` z(5e03tYiHkwn}1Z>ARiXBSXWkFw(WoFRkLX^#SO}Sz_sbiK3!!3L{@3RwEcs6#W@z z`vnue!8f>TLd5y@IgA@@?TB`S>p6tp`m4Ef(pD9Q3or-W{g~YalHVA2GW`ww!M(25 z;I**7>WResJYQ3rAP8RJeyQkH1aJXbWC|sE1wQ_85pv0_u6QXio{Pb!;(cISrw4yy zs*|JMyUOW*Oj#|pq>qhKI$McCp)l&$v#mtY1%5r+P*1O^Kt2E3IUBXJ!d#pel@Utp0IpGv^<4iQK+9eseXsV-LidJ_>CM5y8iOF!;d zyF=uEkEs?U&PuMu9Jk5gxmLcMP}_9-J1-)w*@GxF9zAc>UBv&3vg_30{5jI=E!RIq zes#gt|5f?zq4(Fz@5BfwHtFS!2%26|euW#Kkl7}*Jt6Hw+aX%>XVP#eq-q^FJG792)B_7 zht#k5I47X!bzT=Oo0?qLM%TL9VSmwZ;8q%Qxv#G$*;H+oExRt(u?$3a3uAdz9qVxI z_MaGz^`Lq=Rd19nIn|BIQ&%9Iy#Ol}!Gs`+BAdZy&vh0B5DN(Z0H1xQDX?~bI{{Bf zVbbG3r4hBmw24J=DGp~r_DzVI3?;QQ#l2a^NGq0f5DS0&OPkt=5v`n+(gks$ql+qlFmg!GdyRNiTMrGey4sg2y&M zhB$A;bJA=r#BJ5;y9)-emNX<>S`V_Cbp|obQV6s7=7M_2p4u*uq*Nmf>IxPwP4J-r zczC10gIw2igd}Zj>rH95nj$qqPML%O?NJRWJm(?2q*&x?UV_Yjo6Ag={mR%~_05QCtDDX7RLijA>J9)do%A`lM~KWl^!sh;dsikqt?#XZbQQU+_E2G$Jo6iv1R9>&2d(pAAq|J`3Dssqr+iSE zfT1v|&IO0Ucl&073U8bF5QE#xHxpdrKc)Gsc)&$p!lEoIyw)V^;r0`o3bd3XJxv!W zeXvg?nUXoJX~2_@)MC1%t&TjOp+#12E7mdluZQA2>SQ*5NNer%Zd(dHxW}D_(A6VI z&TBJ-4ja;(6L9E?9C`eNg_F-Z9S&tND^8MbJ8Y5k{yTp@WVCwAn{0x&5LjPzXi=m< z;Hf%>b|Ard-*WELmy_>UG#tI)BpN_aso3kqzuA+9rfgDc7HH%`BcrjA{XKp!4(JUX z;!>4gzxc<0U*_Gy5Mv(V>F%wE=??GqhP=@Jkh@&bk>h%rhZ@jUpV$Gp;S_uBurd6` z(S5p$Yn%~uba%M8NFVhmsSq&GjvRzZF~|{MO1^GzjI+y^j{q&tb*l$yCpj;wJ_)*r z5m-J2RMt9d)=6!g)dn_Or(gkTMhD(Ff#5TXT!E^8*-jZ4%$9ZPn33*a%`FB8hPT5y zV_GnqW1Et<&c8R}hyOm!H|INBn8ojqY7fwRv>|K`BX&!h?*lq3rE>zkhx>GDH@2rs zyZ*;INxfuKh-_p1_79RNt3J1$mUs2s05ep5!r1g%rWP_;!@^q1`xHP8eFccM0w=!y zIA~OVK9vSWUxk~V@D>HTmrOfP6wy3-SBf06{NBYIy=rI=P;Wk7nUD1k{kCpFt<|bJ z#IxIGdJDwfJYzg$w+vZ}vmh>0B-zLO?4LpRs7|W1Z0fV;ZCyR5TA$}Gv}v0EGZ?ax zu$y*$fbOL4I_^^(R2NWz0jOXUD34ue+9tZ?W@0bpa`s+>Dq;l`<8_=9V~m zdt9X8UpI3=5WGuSJUQ^e{6R6$wL%Wv_Q`@L1GG!8=EjpWa-wD9==hKv>?2MuW3xXP z?D0@-x#{j7m0c{W1E^o+!JYXiy4mQ; zrNu1O_pK1RcqoMLzT^voXwQVa9f|qyZ99Aco-x1+9KgxFhd7VOH+L?U0X4GX#X&lw zEAT(^AjUKCQUQzckPXD0*J@SVQ=UwJRVSQhirf6Z(sI9`{U@gkxWkw__&ZAuq@zN@ zryaSASE^d581G~J3oFd9VvtI6P0Rw}7sXY9%ofGzEL|w9Th|Aab>%!hhv ze)09cp2}%5Qy>SS_-s2Q&HSOEAd|JAdRFhA&YiQ+h!D=$yMjfws%Zs&#z~pa>fPfH ztn}dm;S>4ZxV@_wJ;p^~=CqD~88CM~d>lqBRRd-eZj=#f`^^A03C(uNYizHR&Ulmo z>l;Bsp{TZWQH(CEzU~UojU@4HZW>M;qrk>77}#=6SD)n=%3(B*2WJ%CoY`prhH#|M z>#SpbV~;4}{SU6H{SlNbUXFknLn@Tv+#;TH;lnFjcR~4ezi5asGX6q;cPmjOE;$xH z-6m^u6t<((k-1sMuEG6>-1&YQk4XLvHCyR-{P`@+OtboI893FOIY$hHTu3Aarv=;q zs#2wrY`sk(cO-88)KO|I5uMu2?Upa=Hy>K>R0HA#ZJ6dJOh1m)-ZfEt@3ePI6gawE z1YmFW{EZ1uw|Jh4P}c~5Xpn};)=51T-BoyW-Bg#l@UCm>9&cWD)V-6Z7 zmhNX(EV>`&vI#GH^0;<~rfUtl2l_mJ_h83?_^yF>QrrRL9K3Q0D^=zG>JAsXwU>G$ z$D0N{b*c$=d0~Dhyw-=Gd^~ZCntuhYIr_VU-Tq@6aWAK2moSUqa3kDcV zfx&CnU|m)W>4(A-2->0*Hj>DZRFh!cf8UWJ_2M|i3?veHue^Kiq2f6H88q+ehJkG8 zfx%HIIEYRg)gKHBfOZwIdnv3Im>UKyG*eL=$5F&vDU<=B!<&B4QFK(I1<57& zO+r31f2FzT2pMGs;hkZsqfK#Wc+fnwm5>HC^%IK45IyLp5#Vntx+AauaE9-lJckdm zqV^EKup{joqu;Vdz7eXW2A${It&~vbEPBHmU9?;uf`yGEf0d}8);15)w#)1P{_*`svVHq{`y2W5 z!`0R0)vwsJlW ze;F&3XxP5H42F?=88pc49j5+|+p)i-*R*EI29m$Jm8~-TVpcX3^G#i^jHX+qP||Qn9Uy^ToF9q+(TU z+qP{RJ8S*tJo{PuZr+bM`{=Xxx3wmhq}K3|@~V-j6aKq|HQ$XD$_bD&xcZYsfU!h8 zmX?6QKnhEZ6%X2+-7@biiEx1FQ02)X4_CvRuXV#Fr?tai;ox~Gw;o@bCO~y{mv+A{ zrhnooY<}txk)DnJLPoud>s`6D{Z(2=TTRUus+b;Wv<)=xebD*K&wdwmm;u|5ZT)!= zJB06-0BAJb2zg@~zbW##4sQowMn;k{X6(W#kCl=tHPAUGT|~YnNI3WRqu<2eUE2P{ zP&=9u$2DO*$3fQ<#0*f$DU>|Z{^TA0$)=ltobA&HUw z(v?4~WQBd!#Pd6*3c7T{R0*&Ry#&?EA1iHu_yHp_wjXC2A{nZpkl( z{T;l9X2(NU#rsyz1wpWYEKKXTmJ-g&%z@X{NaP;FkYB zHNPSNV}t$|$o6SYciRUB0!jh@zvZ}+5-@ZsKMF83K(*Iug9)kgoHiu5mg6Tg3YPy+ z$LYdUJBlvW*40!x`5@@?J*J_Fl+sdEcA#%;-@|^Z1ABZF2U95BFwWDU(#;Hn)^<}0 zf5x)fD&J(&DK?sEe!vy-F2tjSzYCHX10QkDLO&9D&@>ng?xaY`xV7a57&kT_WH%0S z!dSitKrTVpqOzi1X+l>n2Dz=#`slao6@e~a_!=ZHsx3!##m_fD6FFq`%GgZ-9NNDN z$+N0&xF1^F5E?H?tW=SLV}ULbis2fnBlW;ej4Dbe!4p%KYz#A*vxBCq3UpP;3Yrxq zuaLEj=}SR>g|quzwl{*J9LnFKjY*)c->Xsr0J(zbX2Y4DG9S;T+{aN_@>IFWzZP#r zmY1^P6HRdzb&@1H{h08t ze-I>7emTlFb`vx5xJjdNp_6*6L+;(_*xwfcFga(~p?Sk6!yNFCC-07J;8VI~I)bhS zuntwHcy$tIs-C^pWPGyayjh&9MTZ4p&#JynLC>4lH(`%wsqMqRI$%?Wl)PcxDMBf-))yRG;1M$F8}9Gh-pJpJ(D8?ER(tM?uzam&?#z7 z5Wj;fjr}b_u{19O6+AabqG!KMacn`{cR(V`WNfC!!0c$t@G+wM&;o$Q=QkY{#Lb5^ zCfqH-1?4ltUI&^aT;b!7Qy#1#+`C^JhKxxSZegAIvKwqj?xE9Z7cYcHKJy>}94Y@b zhMnWMK&~Lb1UWdO9`a5ky;sm+sgk1bMlml1!*$*^biKQQ!X0Fr z)nZi*j=FVV$>1|SwsDQ)JHMAj;$wU#e8wHVm&IqjYs&W1gChV>QEKhXzxHV5TXJUo zc;V&C%Pq1A>m>=~i^Ahv2IXBSr4s6Hv>encqVeg!xG z8KQfOFMEy3K8V;(Tr<4RaG*ZM3tHg1;8>jNu(Ux~K1|>$XBe$+WCM{;-vxM=YY-4- zkakOn2*bcCVSg%eImylu!{Hw+nXf?&~E^;Y0%P?U$Q1z!?tb1xl+0-#-I{1(p zl0SF)#AS=&ULhBQ=tt1pgV={>5K~OOUJHiPh01E24^13?IH&%GJ;C0Dj;_}Ib+_Ju zAL`AC{Vx7i*|cgE_}z?+<@FlOK)FV5CVXS6s;-&oPX{QF_MAA1aT9U?qs_8mQQak^Bg`vJu;6C+2L&C`DgNem>*TZh>JRNrSs3YL!+bO_xJsZlT8GMV zpB0%cy}M&!rxuot*RqJ7i=e{aR_Gp(l6~D+UXlOLM?DKnlC_}$)Z&64{v?mP(-ke? z`_iF5mlKfl=bYOn8-6KutmwR+UZ!dbR|0&9R`%25X@$~gKh{+Q4cx>c)k{xQ@i{`6 zqG|x`%yF8SKISTYC`7NIzq}y(#ddTb$$mXwt5|(1l*yg(-?37Bf z@bdI-Tdmqeozt2#-(2f_Sk}wUi3g|ou2MU$yA`12C@5%^z>9+q_(N(Ww>(Jr=|Oy@ z@h+V$g_K5zUKO+CvL2J2orJ_%4=ERsuU zUtj=n2>hA9_+zn=Oi&OVhQLH$Wco@uOmq=*)}~-!Y8Qqii|Z@hlr>i^4X_)H&hv>F zMOFMAPy2#~XcOG|og_%-9yd>HCf%`egBTnyu-jt<#=Rzwl2-j|Lo6+q~5=$v&bSeNKdxA_?ns+L}4wJAZq(tKB>=dp{NcML4 zHj5f?c}J1pO^C_lVXPWsSBJB9{WA7UqCJsFIMP+jt@@|RC1#4KYqHS9lW6;!0JR-R z@9x|P6mL;@tQ5M6^KRbb$gNRN3}PJpUIC+7ok4pc?7&$svmJ(tY4?E9 z`u_BM?TwO7*K3SI`3`At;*q`Z5L0rz*#4oW>EYe;)U*cbsq%7UIX``BXXon}stbKi zxUD;H_d5USn>8|)r{lc#z?=HWg!9z%I?gp~ZhjY0H*(A-NkW2A@<^xv3N+iZ-%jd~ z{R6(2G9uvg6GtEtDzx4Aw|O$ zer@64m>&KSwI>2!SSEarsrR3*+U#z?H^SsSeOvb&LP;Q%Xh$IP}?K4 z3Z{hAT*YG7j-*YKet^ARgA3-`EV?H+$b}QD^s>1PIzY8Pil78!H9sbkaO2Y3BRaOO zY#t4ivc~aX2XmLyBi8t`Znc#uiWl>(VKb7>8NI5@UHA34=a1<=KP19uM5i0RmR@j@ z!{>zhKMalIx0{%T>Xvrym=4Tn_7$DjsKyt>|Gh_>4=90c|9^LJ`#wv52= zAjtoTFLq8hnXW;jR( z?Qo$E2>o%}sbeIh0A&zwBCDq6n52-zKxps&EPorctJjUyK6ViM!%xy)QE{%fC~l|I zL}}S}+TK-cDKqBNzZPR+JyqUSSoY!LTzEC#RF(dvTzA=2+5ARnZIS6($===i6?y$u z4XCu^Xu+^)q}>E`w0i-(0J&dI@8_G*c=Ji}Spu_d22})0-fJcFhn4ouW0!`e zo3l+*`11Tek>RGW<;2n10HmRs>jBHLMErS(ne+dMDb~r^j73r#VZT zy02txnQq$4&T0Be)#lq>fbZq!F6akYfC4#-r-h5?j*9h06TNlnfgZe21x>&I*^-`Y zuFTRs;d?!eFO9CpyVbO4LkAR&|74zyPdr+T{EZx~&ojFbQqCB*3KgTy7syy9Gb)+@_qG8}(f0CYXr z-2G}K@W$|Wv0mn3uEjach8s1IJhEq-xp*seF<#Nlc0QOM?~UKU z$Rh9|gytNUx8F9A6;NuUHXnP9;6A+mpt2;n2M1h>8Yk#w{tg ziR2t}VQt;Ag^&d$$%>@}zy z^jU=+<${9hjtH_&5MN+S9gS`a+Xf8ywPc!Fg8X;UO!_OSQ5WI+<8)p)ye$a4gw-k8 zSlVHTgahcJjMI#Us}oJ>$PY3m_VM~OjEi=Fu(sX8A-Qfc&Z4db;DX~0f?(FvVTaL@ z7r?PR0i+mE$cV2HSwFsn&fgs15w`5TIGK9$U4bAaw`+e)?f%Y?J}zm&CK>zOFrHJ- zk*-Jx{Qa-%ETOwLqfPNogH=NKhTl;D1OU;`H*9nxo#^)Cw$w1ePSeSW%J9!550kij zvOjWxJ`oTS2E^njpcyxW183K>w=7ve1gu%-ak6O=CW6BRWKu+_;27MEsvW=V)SoIe z*fWpt_mn+U2uJ0nJ}Jqt9b}ARmFJ+?jd?PX_by*eT3XfkKN0SPTJ`BuH36mi9pMN> z)!%!0;q!6Ki&P1iqbL2cJR4GZX%_S0)!e_0ZcI$Qhsd*Py&$?C45=c2O*g*6h98 zQqs!{BSWyg10bsywf$c_^pzmWTX^J5$Wi-M|5k+vtddA^N#MrM?%lhm4=_S38<@OxCco z5*CxH4s9@AY?-HOXS_-tk}HL{&}qSa31bsEfYhP^14@$7J&kMHm7Z|u;3rmqF~uw< zIQ+~+iBT$@q1qM^V9-+jcq~;NYWCEA&4+g7|{_@g`X-{ z0;m=C>;b^(TwM2(qNN6I&&1V04Hd4#`0s)WH2an6*?K{!+t8&JWVu0 z+ltg(2LABm0V-#_E2-a%b%+2O`=Br+97-5 zc1}WH$EL5W?9B4l?)qaJc&=h%rR584fDp-ficdi2`qzgOL9C6cw)y2PjJhPG*C!p^ zHnC*8CxJnlCR_WE8I5Z86-!s)a&pBAh8&;baysr=89Z`GM2`lQis%xAa)cwmY0Em)gutNi_GmU5u~ho_S8d`j z6lM^J${Lrh^9N@}l%x72IegCXuD0cJN}q;UNaHKsQbp!Oj-3F6+9&WL70Vs)S^;=z$Y1k1cnZ`*42GaWepw9d51T<3F~^w z?GBe-1UD;7EO*sZRJRf}!Di)epBh?{sl2^uz)24WbEJ@kA~|E7g3?kw0E~TyAa}Ej z7S?eoPc)KEBNZWKL;9lhck;)iq2*pqqC{?w6$LBz7)_vd06QMe%jE!0{d5F?tl*elqKY>80C?5?@K2g2v#3)}yN|W%y%i|6b)CNt_{dZuZ=C{b zkD?wU!I?sQ!CfTz051QL>`LlK0(sX(dMeB1J+|-tORqsmMEpW z6;qC=DG`Z!3%q4OMY&FKP=nDxZL=arDi1%q{=;R1+oI25CyAWbMG+qBr~;B|i;K zy2J{(Solj>z}062^q(g|cgAxw_p{Qj%oZGzt59IAv-Fj6oE;q@UX$rUgUk=s3EIhh zv2Wxdd6?e?2iHL>+2L>xrqHHFpZGaD2mT>VQ=6!XlIZ>>-unYXoBL@4ck@r5OhC!R zE9z~;6zKxIuof;5%pvTa-WXY#GeHzoO0PX#)Jgb8_cS~^> zwutQ91_a^-g+kOWykc$KqvFGgdGYYFkNs$#cT6l7vat@)6Gdb&Ja^wJncLW zF`}jEJ&A=|t#J&3`~As#@{1a|0Kv<|)L|0nm1Pec7dP0=@R|CZnESoou4(R_wWchx z6s4ZS*3YZgr69Z&E-p?^9JOkZo_qUiQ1PW-2VkyIp3Ps`!1IS?D(2ULI~fBHrLX(1 zn0ogP*KE7)GKAH5T4CT~3Zl^%clTpyJ`Qc|M}sSa<n(ZPH6_a&$mP z6zOPHUctg)ckn&?7()nj_&Z$*l+o>H%*f=kH^}Gj_Ne%Ad4FA!ZyZS)>4z zCt9osl10Z7E7retC`_p)7~k2+t_u-(a)35zmjni3j7Xqno|1mX8E4c(t!uP0rDA@| z8wr9}Y+$HsG1WEQiA;6t+|v3H5R%>^y|D#{ud7t>)rpk1nBKZRjE#Wo46gvw18s-u zoMYXG2qM&h7qBP8^b~Z>?JNre`?wE5=tv9vr|~8T@LMJct6>W0b3Cyi9Xo=x}5q z*fw)tSw=9|%UxD*PMWito~T*In-7WUGZW42<_BoPi(ih~ArC$qF|xhh+VdQ}3I2{) zKa2nQZ(VtJh{)>XfaBT+?$ws<0|35Oy_Iu z4tS#PeyrawEdoP@BbFx==Rko?IcVd*Q$u5({ROW+xq&av-u|O@?tszb@!ew=cKOI% zbbaJiBVUnzZYD51Nae3$Yp6yh5tLalB;Uy%4*XF>Xb<$67JdV2eW;Ys73!wgutt?f zD!NED-<}>l-_z^C)}cHq834>pe4kNxgLHgLc>C{}1Q&iW(K}~&U>2|LjvdO|1HR?? z7Q>XG2a`J!)uk7wY(hS;84#=OAg~z(TXqymmLg?WdARFLHJ4Wj!^>tFJWqv#YgX7n zE0&n#>%5}=yqoZR*C39oP^}oR2Rx#F2DF-C=qPuF-=jGNq`Vl4)qtv{hKRU+Ok9%o z>mfb>bCH1c(xnt=Vefgk8nQ0Vjs5vMNFOk^v4L>ic6Gpp({xVHk8!j{VF@}bxE}3B zutA91+;+NTedge1=6GFA;3F$DCJAZRFA(=wK{J%eULA;jO3euLrL!X4DL`69yE7+{ zQaes;vYVuFWaYR7DByPK!*R`Ow@FtU>J^8YF2*v{beap&d!@I}EUD*V8zmD5v)UGz z?_X2NNN_t#zg|GNO0x(S2$R9&!JuBXy(0lY%*VwDXN7;#j?bnd?{;a*s#@a08?# z&L^n%YtULO6+qk|Fsj}`SCZ60bFQe#1YRTPx6;>>^ns#c4yGJ4ntc+i;*+Try(PLv zDaer5&F%=y1_&BVHCVS8DtmcD@U5~mcD@$rfEhCc41Syc)>R%1u1wK4i(L0vR^ds< zjai${v1GZ36){ruhqy!Z4@*O?u33YS!4@^m?vrZ`!d_~p`g$vicnqOAt9_Rqs?O9C z=S0Vd6(93ojsN~B-@zqIy7B#gYxatN!Fn&nJBvqBnX69Zt#8JU}rMw}(e>^bY7Y%Hu@ zNrd8riZ4QXo$dF#*);^$RxPhXj$Abu7+Y z-~I6{sR%40=&dX11M#Y9J;@1y{7nts1xhyZCZRC=tETO>85^<{G=`i9(2{cmCFUP!Gef?SIi-rWZQJ?QOk_=SbC?IywZF;)Zir`5@EOFq@f%Ey$SIn_ z?X6Fu5pG;O4e`&d$mCFT9!L)EZB!pM%cz#fkMba|L~6nplMng!^k`oT&St7ZUGoRt z0JtoSL_zd}Zk=%OXCmwRhMugqG>rJ}7^7^)%u2h!cTknBQ@%Ck5H^T9z1L%Spub8%%hXtL>)k!2B)r~K%+wWLZSp+$-m>dRvSjZHn9^1$2b_9wudUm4AVi)lwi4X+fT_o3P*$v{W5}d(aS7^B4mbgeoxMhsSG?{KXA?n!U&RR3@ zxPsOGQXVYVv1x9w=3CNzXAkZpurhGK)Y3`DkNri}s2UqwUhKui;nk(sl) zpd^}{cB=P%LHEbw_U+u@pt>Bsa~zs{yQ#J%}%H_mC^n> zo0x8tU;-1%S{SK=O7a59o?}n=MS~~@L>sB=VH=THW-SddPg=lkkCqp6733=?QkWC1 zGMT=>M~8HZMO8-sAS$cq!9oT6Q$Ej?6SPJT5UvvAtnlC!)yYwd&xWdYgw~`#eNy!6?tj&jS zx6j2I{ty5lc%mGbXW`cycgdYZ7c%7?!#VBs8ak{k0I;WF48h_}tu$3qhyK$YvRS9` zpu1%0G+fkIu9X0|;2Q-`r^Mq9r4R*MGl18VM>gGeBV&s7exWDHh5kjT#=j*1a zGK7;#I#CMM5vAD76**&t#VvnSz(b}(=6qiF94;^X@UcpzF-o;GnO5u}?PVY<)y&7Z zOZ^8!Z5jPBT9oQ?WS`3wu%g%y5A!njIQJxF|FWgDT!W$}p9tw{@|1L6!?9Z`pU3Ic zyK(>p;i$WAZ0VG=dlfyZ=yeCSU)~^7)aa9y=aeayPYlfuDcs2w(P*NCv;;yrFc3pi zQcN{6RJmm{P))K~FvT$*9Xenj=+naY)ieRz_Ut!JWm)m%jp;j^Gsi*C7Z9s7Xul1C z;YxZe@5m0SOt`{lM$bZs^7+}memiX}fZPEhXxBwIk&ES265$Yx^}O4{@IF99Nq5x&pe9W*$DuV&E zAvwCYG3+zYe^>BnkM9zaUh{>57;8p6K zc9~s-Oin&3IGz!(h=H!6cJUH<5xOyC{KVLE$-5_g-s(n7HPDEX%qj z*pa>V?6|>gTUXd{3&q6XIv2XO;2Od_vjVRZRqII4oC)xwLMZjqWHJK;2%jpUcxT7w zV*mC?H0Y24AqaD2_hpSx+`ieO08yCZ_2!P3?3g3>8C7Tc(3_4q#bK4N(1o=a-0VT% z&`je!IwR*hi>hA-={gHra}V&8tQANlxfv}1F3o@aul1NGI-{U zYP7^{0b)Z6-5uVU@I(P9vhRz#z3`Cc-hcsr<1jqN^!$>(VJex>16LD>hIIM(112-Tp*tZUR62ppBiu8kuN=gI`TU&6Yr-g#uQt=l^ zRA7b>Hb& z=1TGIjOpJ8q}UUn(($k#p2Xdj^;7kgRYA*<2xx&>AD?CKc<_g-2@PW>ju{u6UPat__u}h8jIUKfx3O zo6)ep>tC3%oSy!u?(R1CQyPvy{=-B_0bN3rW#iL$qebJR;;6 z>R?5*U)BXSmj*F?%Ki1tRrzrhz0}#((X!GL#$Gw5W5f8Sr^x8JrSDJ-QNqyWbH91c zdXIe_ZE(Q8nLud^=L?k*IDKr5P9+TccseQJ(@ZcFyxjPGdNN*X-iQ0-WK3hn~*D*GzAQyMF2v`fl}ecb#)&#hxT%c3Ww&5OW=qvDBn-0K5J*}jc=(1rdF`Yu>B1$k%WFyXO!EH82k#k?0qyy zEg=b*-G0wCf1wp~W(r0);Fdh}h7aZq>~my1poaiKLwbxv zMzp3=uv0A(#Rync3hGp_NWt53b&+-5*o-OAT#gGPr^*32KOTQLT zO|-%i-D>J)@Sni&CrIAU2HmgUUxXFtnQlR^vTF|&>Vdd7H2TL>#kNQ*mXIzu#_r82 z$(MT4c#`r6n1Pz^MVr_Vg_A_VKlrY~t^aQ2J_Y=5XN(Bcf0haHgPpshq+U@1<2P$7 z0aru(A3Ff63H%Qd`9Ey>>a5uC#}A~J_yg&Y{+AtSKK%`h0*3G(u;3Szq*5p(5YRX7 z|BG`1+$>B@ZGJlHZ0z-zAGh62{a#mPt*Nn$2gABvqA}5ScqId6uy)`#q#w6k{MCz@ z0vVM*AJ6<9QYCa_1j9Yjn~ zAyma>%v7Ot%qz7#5BAkK*R2x=f2o%S7tYiJIB2yBg*lSU$?2bG65oswdjQO|%1Tq7 zJ$Fjs8mzOW*gZC~=xD`UcowRUTHk@)JQTY?(O-j?1GT%l&@q2vkNpA3DkDkW2@WO& zs)BA&n%{^%^3wwLqv7eYz*$Pw`Vbwtca(X8xkEaN2Zs2M~n?Yz`>{9!$$w)eOoUl z6j+=98{2kj(a9(z-x2TOCCK5o`Tj=wpi7l~-@bF;3L0~oj>(gvC*zJ(K=BaP92k%W zr)NWFBL_{UrvncicgVGgPups+5NiVkh#m^LTHT821*(Y|lg*z=;o1U;$>ZeHBR52H zHAEFU#r#8Q6iD|g<*~#7j`pFbRL*e9iI1h)6;89AL7U7*0XG=YwVFywrdniOwcad0 z{!7^&VpoJNl3o=RPHBd zSl5s{?F)Cv7uv}Tkua=8J@*2&G^ESlGSSh(H4@-J=dCX<+z@^o;;{RNICPGML_566 z;5rsJ0=bNGXG}X7<9!>vL+e5Kl30o%qrnhk(DXshS zFXXg93hjo6+`e?f(4y1h-s#SAf5doIrjLzvcKF85*XRq$)AS`ZKB8g^Bs+( zFxf}QHPLWhV&kYm=GMztea*l}yO`7uCXm}rSy|2vF^yi5=3X7Ht^|J>(5j@pD!oBy zf9>DwQIEHZDw|4ljr<^Ll~N?%lM`14b>zxTvM(TeKqL>B6Xeajs`nVotXs|Kz07&( z#JyWDfu_5ZH=g)d;V9NW9c#SH92|U+?5>%!zOt~@GFiG#=Qph3TpejYKUaA~yOsgc z8Np@$dd|uBT03&hlR8!cSn&%#N?|RXI3HW8sN@e7w@Ie&o+sD94S_7?-zThPS(+;d ze$p5Gd4dj+_FukV!!l`llB-Y_#i9R=|J$DcU5- zx<~vS<~KE+)`xf)zmo4>zM>NOq(pGpvZCTk8;>_2N3kiF%xj4OFiS8N;WHr1mV3qh z@y3Bnb>DCdstK;is9@R;vmdX+5irB1Q)C^ZvF#HXzrx9@c_*aSM5=o2W+%U<>6ypo zK;hci*zxKmb(mc<18HY9#h3LJcqW^7zvSdkr0!agVM`_%E13=Mc>!`KvXV`@h!=XM zR=Fr!3&a5@hJn}yycO~YanE4hBt>MS>GA#%N()H|2*zGtAo$>#rixSM5A-1m*!G;b zvBi;U_64ir9DbX-8mYd`j!ETZ9}a}^%&t|q%J-)BhP;Ywm-QbAl%or~Ot0HXty6b+ zq2SvRod_*wP?9&a-TQ?%CZ{H;BQZla3mO@m>9mY7(L$4Ogg4L0XYbgGJ2NQbALiKPs=vU!c zHP_wFA7dgjKr`GPQek=~Ei7MiBN|`rh(YqHRIZja*gSxTU?fqxI72E2<*z*fO)koX zeucN?BUUQ!xTA$lE+#61u%KVpeChWKf-#M%-{H6hL5mFFlW91s2XYVZ7{x?26!mIM*1nKuJd`|4eCboiJofbrx<%XkQrX=ZsSR7bx#SoxD^*cV1-xT^?cakLGUL^y143>OT*0U+t)$%v z^sfnf@%%$O^Azi473d!yc}rYBnN$4C&0jpRzpBWJuy&v~IU55#C zm(JH8-9$|IojZt-3cngCwqhPOa(k&Q?q%tAj@DCazLDVf@x_?QA35SbZ0-?zRPj?i z6?dh-x1-`zps#l|-ieY>h*K(qs!hm2j+~d!AQbcWKYYFePND5g7n&!tu{OX-?)put;AFk?yhP4*i@mb8eNac*ti4h{DOe*a*# zaHB;H$45P7v?%UQUDqa@-n#C-^zqiCQ#lT$SS1pY5{w6@3dYUxOYl1k0--@mqv@|w zU$sE8<>dZ$!twx1+LQj>y0PmWUws12!@BO59PE60PrL7M=JpiW;DY1*OU#=K5CbS| z=)(-#JI2?&FyJ7USP9Z6#SHmE{_okkWx&mY{B&+BP(VNw|97Gp8$Vu@RqET;>r6<# z&-#unh>mII8Y`+q#!5@BQKrVmQ7REim$HTO@xQd~GD1GC=Mg32vm1h$`N6c^o=>ml z-BMc;- zs~}l^ac(Xk$M)M<6w)eAYite-iwS3})C~!IiJaYa3&w~!C8ywbIOr3_0p#e_D({9Q zIDluX-Z5~c8?n49JUgT`3${bN3Zu}Z7WrUjq7dK`=uw=5`;7yDm|a?)6@Rw0Ketrx z@~w1glpbZ1T9!~##qHRFYqsdMGhEHKKRldaNVfxY?GW~J-k-}!RSPBaeJ&1}6L*)3 z+DJr%rV)}M#P=>)LbA7r@cwq8%mr9AWKI~@ilAYVBBNqMtP<60Oa&t*e@1`kGB>{~ zvug}vs!H`xr=I{yyQWpM%ziUo1=yO5O37cLmqAittE(EsWP&a*Mfi1tzb@hQ60W0R z*lANsG3#M08B0sK5=<*}$Djq0I;v_%uc+;#zu459n;b*3z;4-f;K`l~K)|af3fo{K zN{-~r3%wgK(=AD2m@?90(xc?AwZ8oaHfU4u$|43VQx%^9+^ALMmHk)ivCyW4JX(7~Gx zjYw&?nVf|78(_=+%Ux8{7S@O^4TOzGpdg3<|NR3u#G zXL_A`|Eg{iTIX>!vaV6%8dq(;3J|3%(uFqTm_&qEal9P>=6a;SG;>%&>gX`!ym3(- z^LuW_GDGsw@JYo@8RIOZY?B-mjlmMQbm4kPU-f^o=bkdeej)Y*4)dD~7{cC-?cPFv zaYeEQdBzg!E|CcBPDgV8`T|c0Tp{HeII;dG&QYDAaAYRVrTfIsnF4oAw)15*~?A>Yn-GV46H*<=-J0Zr-SJB8dytdutu5W z?DkzL_kWL@1h8S04-N!0ivk3M_uu09vk0=Y{`qa~)O!D~0DBWKNGwcasoKCLA3~qj zZm8XcCcjA(Yb$UCti=~QtCf|;t_k@)xO_v6YrEybeOtF|4&Vp+`0()k^Jh2r)76=y%lF>*f@C8O3A|k=}LzJbg%RR`L)b3!cDT%2@l&T~@OjMY>?pbwo4&veAZ_haQzY@40IvVM>qoA zA;5#Rgptvrg)%ohxA8jJ9x2Q6mwvIAC@h|?#bC5^6TLPObYpe3wV*67fkFmkR25$& z%Bs~GB$cdX8DYz!IRz{{#~7wr6SFwj-vjCt&Rc9W>3Th3h!s;V1O(8PH)mqQb_BgR z>OF$h_As9u;cg@W%k}oJ0=kgWK$d(XqMBE9J{z0XI7e>j$kA-C=Zkjch{hO4?={N8 zig6I=2D>zjgkqExS?L08(itiu5FZ+@3~45cEBOz;>O6^T5eamLa1{;fco>Whwm&(? zT$H)=2?(ZNZ5>y~m<%8?tK`+1G-?Y~JkG*Z)SHw!RN*(RcF7Pdtr&1Z61e4C-=vDfc-Z`hMjky&Q`E>NdY(AW=0BtIrzocqZqIY>FxpcePf_1P(N1vcbY!P>z#O`IPqD`sM zo9wifvHoMT zUTBDCT}TfH{HTjSle=Qt#xowlMDzop%UR<68Yz1@JcOIQRCt@-pME-i4sRVKhf$eq zdEtY+H()B|K#L;bowav1MAJCI(+|U-8W|(!MSYdtI<EXFLiJDEbwHVyjVVLu?Ox2 zbc$vsS2w0p=d{GzZeF}6o(1Yx5jSzCCPS{Q%49bWw)Km(tbjWoJ^Ni-tmOC@6;|Ke zh0J-$ehmN>J{=Y&dWbxk@kiHIuzN}E{iwG;W%>6N17qJGRRI&V%3oBI{Dp#ERur;M z;9iA-&P22p52xP02LsQOSGOM4(u}rO``Xrhn1$oxeV(TyM>%5_r@u0?Cp*|;T#_dO zN{K|SDV8{B6jew9N&}%blu)XjE~nJn9e>dcMKu68G5KUK4W)x7N{H>O{P&C+qvKsy zFBe>NzMNv-fB^9IBqW8D8w(jJ(dMnY<{xhE?nT|dzYMw%V!N01hx_}dBX3rO&qls3 z48Dg)n-zQ|P7alLKb*#3R&cS;%+0gI`zbrMa-Z5}-`Cx4YH<5*w24Q;7%TRdSV^fS zp6LO%M``v;^w!HxhNYa#PCLg=dCe?o54R8!%|Mw>1kJZt$8S0UIE{dWl^wX6ACox9 zUh@~-?&2?r+l+1l=wu#MneFk3Y_&65>aB}aNdx{cd^28`s=8*9xD{+u(8H%YKm>qDdkpCw$SI1X?J zGg=t96Nho={orGxG}`$_4e)4phka2-G`9K7HC-#u!erG3odq04`Z~@=P_wxT&YZwl z+FLAmL7~~UO)CBLZnVwp#fbBOhxw z4;Kcxx`K0ipU?NlO=*I4>SByk?#Euc`FRFc+KD>W_k1I|s+7@;8gPP?KD4hwf&#iX z-x(h`3FGUatCNVIiTq#RTQ?xvY?nvF9PgjY1g!2c;XXQ|qXbcdrk84x$+tWv4#0iA zq(-Kf8ig6Qw{(vez}{T|$uoWj89PjU-tz)@W#M0(;|`+?p-*FmT=!m1Hk^G(+A2O8 z2)lM8mfK4<8|v&Nbne0bs?OY5uf>`Upq)FFaUqYO@#RKE_)u7R7(HueF6c;-ro|LTtLBUC3h=?A#SFXRg zi@}-@(%{w-ijw)?ox*vFDNJ;zZ9D{Qkv&1+1}sOlV#wBGQPRLgg{6J4fH-ztZ(p%! zZum+8383}Y;XsV)pK7Tl-lJ1)nsIiH_r%1E&)h%-N zs!~N}VIY@PIywf?vEW{g(vnJnvVE!vd6Z_c)MCrxo8&5*t+$}B zc~6e0Pk=U83)gvO+)kM9jm8IJ04Qz3BJtNLG{N&WS>9s+y~BBK=G>E-V*PZ;H>x-H z`TdWTG3Vo>zWSf4J`K-F6ZSo6zIrFdYtrBvjApP8IN|I!yqhr&Zk(#GZKBNEo6-@L zzSRiYBstE6G^8=mF=>`n%%iEt3zf2%DJfJ_ph2?hoQ@c#eVT4b8jSS2FSNClMSgw_%24zbPTtqw)L%Evg60T zIg2fKkZ;~xK-hdutci-KiPvyDWT0Hv5A#{)(0&P0Es(lladrgUh8 z%+oTcVY665ONz_kt=z&!0bg@;>;D5;A{nppmIDSWf%`gsK~UFD#vgJ`H(T@u=HRJC z5plr}mCG=YT9LUB!kH8ZOT$)|J26{;Z*m(2ajo;jM(;A3fX&l-osX2#pQIv&=a6T5 z`N(wupy|h1%dZQ+arL_GXgmyx{ zR9iJ1@OyRykH{I-08Nxk3y!;kGBk?sWzNmG_+O&{&V5q{VX@8Pq~uH=Ypk?P^L(`d zzoEuYM3A>J=U^vy=Pj3z0d|x&`(}f%*0&1@0A);hn_}hMFk4#P7J7(w1L6Is_9%^v z2ZEJ8Cxks!k>cazDGPZS5PAFe*A&OA53G@(@rgE@uU!35r7!=K8G1v`NI`TROr2w( z37f*}N!%%&tgp|J7HiQ5Vd#7V*3I*vf1b?Uw!J-E71n~|v=hA+gda_zu*O9BT6&)& zAcf96-eqaqhp57*;`hkclhcho)?D_f1B_|PLz=cnHuISN1^$}Xj=bp#`{Zh;q4$uDA4cPj` zqRRVwToT}{E0=ETX9ri3?yt}lQAJ&CLPl}7@^xCgg7a(@jE(p7@#4l>Y)m0f8za{T zp#^K_sr;;&J;8@F8|6mBL{@YfY!>~=6_eBzh}qNsccFVb4z*Xt_K!ldB1_Bl1*QgQ z={Rh0Vfek&8RCN_*0??4pOZ(}b2iRqBRUD`lfef}M&xW19vy()V%^NjecN#=bW z-K5p1goMDhcp|mZM0(4i{f5a1`IM%TTk+aw`_VPugo1 zqsh=3MQ%)GRo3xoDhzRrGp}gtq5*j`-e^?q5+>PEO+r`8d7IhO$n@V&(H{Ap+9nn1 zBG&G40Z<(Kw&3UUUEA4T!ZnSbX#2kH?e4BOULgy?``;xa^SXKn0>qePm~pP+yWhui zf|e}Zy93o|bX`P!mKqDL!n;9$WLRhN`^3P7{Uu6>Il%`kKS2%f%91cE@V+A^=_c6D z4!sy-oV~WtuczFGN9jInX;%V}GS|0_#_PdREBf4TlODgc8*nY$6pom8+?sg^E^fNk zE$|I!B^^jXhqk5-xT0h!L*+0VsBgczy|)B}N~%CF3+SyN`)FS?2+Br)Np~+YknA!P z-l%#FF2^e0CL5mu(lFxRZR867{aCSF0t(4|iO_as*<6__0#9K54imm8>4k+{@mR?TV zXC~xXsEV1)-b0UlI=S$+?IfAw1Q|IS3n^=syG);t-Sa46yZUeS$U3?<(G+nuXI^y};@_mv9>w|2Xmz*&kCzG^&oBu~SDfZ75EFap-_)v+%o>Y z)I!Cj$Y-ZELlQdxo2CMTiCE;+JCsIfzA>b0xJs}{e-~<`np~trghBSI#Y9o-wsx&X zn!say`f!w^jD&1pjrh}m1`tC~dQ@cZaXF$_el;fcX;lS#8Omt;{{HeXGO+Ij-f?Cs z97cX|wAj@;9z$$>C6hvSq!jnuz|5^<0#+RZ4ulF(TH$g)jaE%BId1cBj4a;oU_~Of zSlV%?=;d^ACq0Q~Dk9*D)x_c>Y!#!aDyvLIpQ;e}f^8+NL?P!pmFTjD;H4^cPoqXF zPYH1P8>KiUpFdC20YYeWFFDM>zyNj!^`QL9C8{bd1;v&1XJ*|5o?%@Le?Yz*evutR z7RI--77ZF;>4l*?$;7vc#IV>sPM{HfHm5tsH9hz}tu1*M#4jy1p=SwtUFUlXuIQYV zzuYVZa6F=Q_-u~1T31qQU=ed*js|DUI3-Ln@5F>>Gjom#*tSljxCT8H(FYwk2%B-44s z!2(Lf<*=sbd?Q}Uv@>l&?dHyt6L#MO&8}{D8;`OL*W<$P_k6qi*p;WO!>7CMsXaPj zrS&PmJ6@8l7R3&iqRIAOVrHbNR`@>oKWw0Wz4t(*V8u$r=1+T-e6j=W!oZ(Q4>)a_9)xjz9eUOX2rU)Hilp7daR0{O zO;}MNm&wozIsAC;>dO~z!?ZL~+QobwgFo8f;s(o8e7Y-lY4K^YgFmt@mF4;lLDb+l z2oDjTVt!cfRhXXgx_XsT;>?@!l3~aIoUZ3vj{z40Xz1gmG4k33=-Sy^92WaCZ%oXi ze`8htYMK#N4Eiy}P0aXS;ohA9&+GX>%qR1U$`6$0E-jAIX&$Yqlg+tNy;rfNNb2YX zNO#RLwk`7H?&|TVQ8g$Kmh&xszI1?N=Rt4~0Tx>X0p{=8pwXal7@Ve(Xk2GNsve2n z^CN`1gT~S>_S#lfkDj9(e_mFx7kOhLP1X*{b~W)R2-saK(as+UI+m+AAzX~C(BEN) z>kv9IH|DLKzaJIkZP{-t!S7}eoO*V;Hdd(y=_Rk`*pX?5+Ywxdo6>1cI2q66{}{}0 z*+Q@};c>TkMs9&ZwvPcDF>aVEju4;PE{8TzJ@kbk$`1YiaN{IThgqE(g^ZKY)RzLnOA=X{(JjpFbW zyhJmX6s_eLy5^=HwS^*d}eVT$=2=yR)2A7L($>Q9VFAR zR}1y78}+Y|gI8IAb>yZgf!RrQ8Z7fqiG}F!KK0a8{U-H3=x^s{w2z&9(r;tveYdRt z6Oxo=wwKA3)AwzNf!@T#eM#iGP8&%vQrjdQ9ngPaLdX*oA zg|#7{Y+?@PRO+2-jC>ml?7;*2VuGK12RY%lInrZlNd$tk1_k|YmhTi#-*%Y8Jkdj5 zHD_^^(9*vPxbHL?RYBdmGZp$4LlWt8Q3jgNWro#WBTK{+I z;plAUXyk16-+hCQx5G9E%FkY2;5v~eeSK=yK_oBMt=<+}2bLWQsnaHHq{wk?yZ-8L zwd8Im!LJ!OLK5=HxKfSnLc}^Tgs_L#nV{_vW2c44&^8g~S?7vQb^CYuRrIYD`lOV< zo=T4YHlUhxv9YEb%XVXt?|-G$HJ)t%HLSC8 zwEmuBIUifklo#pd2i9jHz4o2%ROtX^gN30tDTx>N)M{r%SqO#GvSekuD^I4z()~8= z`RdB8M9g~+;k{F8*S46plM6xsqu+FH-|xH6t;?M-PKVjOPhJkxWn0SrJj1T8@nIEZ zpc#a<*UC=4rnX`SeWqtH&99ie#x%gkpoZc~13aC4Bmxh+oSfr88<7y|^LFh?g_tWo$8 zn@g^xey41@@%QYE3X@m;-X`HLW{|xT4wx!{Ttk~yL6Q6*nOp_BcKuFp;7;`=B_j$d z#098C-}zo*bww=qE^-4M>OiyS4IPhzzp=Nirb;)_B(D*(aSQZ@NwS}{ml{k2gSX#A z=oh?6IGqgyQdxh(ihLx1Z)J5(r{-}eZGl1`+X%_{%^87&)K2fIkuc9LR^ z8C9ficjwjf(F}x>(j(Fd*4T@<5@GVj05dO?`m-Shu4mLxzrAz3kItktk^+HS=!s2R zZodeV*Ho1mB#aF+99o+#qA~rW?6%mRZVTU-k#zMUFGdeaiY0e>cF>x^e@47Os`LVf{VSy(5dGq3NQgQZphyz}vzkP7n@6CpbxxWUAI_8#H)XD^QM)N+6;}HY6HQ z@WfpEcCs3JVJMo6k*zq}9|A~zDjN3Wpa;m@L=8a)>Zms17U?Rrj{oG@%uc4L*%7X->a zTyhe(#Hy|2KU0mXNM#LSG2S5))HD<5dIa+qNMbw23=|7n4EFv_&H~9&D{+d0A>vM0 zfOga(={R^QA@MnpmVz%R?hrqTDhh&RfteqC0SYHziZj+V+`DQ;A@A!mt?~fc+v_`T zjZywZZ>@YODT&tcz%QudLCR(87PY?ybv&p*g4^r)a^uuqAC%?Uw8mtI)XYxo^auzd z-=p(AFN)}Pk#ZW%*VID{y@~A^6pRj-Xm3TpY&5szl6RU^SjbL}VRgl90Oc1snFxZT zHS!c-`jyY@W}p+;9{J7^oT8h>9t4Y;qB28=Xb3zppmfvZh(!m}pTV90jZ2F(lQH)z zr!gZTJTwIAbUcdXSB-l}a4~5EVBnfn?1B9u56J6y!qag`3LSHk+w1eAvl;g#AcyQ* zwZqNT^fyezsY(jNx(WyRaTK+wVpDf8V9@|TY&ceSU;#}F(mpPo7LGz1q2(E2lL-}y z{x^WMx!PRH%Pzo(i!ZT*k z7z$n~52cXpEi>6$7)*4Y$l;meIC$;-W|ugIQS?T%@e4KWa|$0?<92zJ2pp9VOO62 zM!4Gu*>pARNYC&M%*%tc)fo~!z{m>_wDKEVKWer)95wJYYyw(-ub}P^-ZW2-?$k-o z!a&t-U76G+an&;Af{q(z1Hq3aq0s45QX4N(QKnB1Dj2AS21B2{@5Tc zc`$8{j*1uMp1gbpkJ50YAVwd#oEI+83kI*x5JV20#xchiY85H~RxF4ltPJ~m*c`VjB+eg`=HT)>@< zg+4sihb2p50K#94@J0YN{;-PJj1ACX;N*Viu7Fj-r4@n(hz~dXD%$m{79`igqOEcH z&SmUiwlD%jlK8H0+~5S0cY#;1qmB5kLkKs~%C;d0rSskqMJ%Sa?lfaq(vIo< z??mtw8u2Dsw=@6+i%}+S#<=&!vymM>!N+fX(IMI8;aM2Fo@B0fERjhuCVrjnU4!{ z4iA?H`$(9TtNaB#0fNI0QPwG($*1ioJnN}K#$6h3Arqi6A%hoqN!TM~cU_9EV$w`B z9`0?-vJ=ssRJ`Y$OBg9fWD8X)Z*q91*B-p@8uylgPF`kON~iULR@>l>07LLfHGV%; z@in`Fe6+^Qa@`Vn-)c7}et0H0tN<7nF@B|1J{8k0rZoH(I<*bK4({hLV`aGjM0w6; z9Zd~CGZ`SD)goHqjK^R=R^=pkHO1)kf|l%{MmhP13T7o>SLObBQ<mpWc9hyVgE2^4Gx zW*G20^`%(-U!GB9S)kPzPX}Knw^FV0L+o}AEj;9iQCiaeMxvNi5ViV&zjwt6C{Byc%r2<59W0Z)a*%BZ-e3)k)uMZ?%?ljOy zq*j0@x2sH8awnwod;yjUj)H?iE>IpzpAUdHgvj33?EccY6bm#sU#$XzQ*C_6td3@4 zfYSz}*vl2Gw2){!oN8h(9dT{>S8Yybd{(`=@=0hPlP$m_j|;!<5MAghRalgyn9S{m zeRPjp9$Yj*C<{UMtK9O6|ekGD-_4)!i))UcayCz7%k+ zf1q*{`N?1q=Y)$KdW!^X@FX5)qJ-z!Nh(1vvqO_9Vf7jBJ{#&$6tcSv=>c;6I~{5K z%8q)8B}BOe2z#jAX7a{e1>d`k3647Q8jKbuZdclNz!)#&Ao{%st$sNig-Hc|OF`=% zB~j`w;gGn?L{cS3e-v+_&_?p|;}meS5$3TsK-O6;0=v)W;u$ZG@;J|Ij?j zFpah;U&ZsxjeA{-T@{IhRoju6TwfnxhPxo;>t=eYw9o*zT22ytiB6I&x8_g0#0}xG z`4p1M$O>;p(^!>%4CK{IJ(Eb+SX?#pJ!NrS7gd>c77pLeCEI}x3cC2ew(v%b4m zAJ5Vyr)d_SJcFuWws20rHeo$Abk_4CnpP(hmW6|TUe6Z zNKqS@MPz8$gr@YSMyn{Bc!=|4(O9Z;UP(8KXEu%l_(#H%1tz%kbrGtvk4$f?YIb`P zeJ4Z78%fp|1@)KHC`%mEp1R@-fx(KKJ+}~SLm5-UloVA76md%$xiw%_*Ky~LepJzg zQ;t;diFd&5!Um@H0}4Ia+kuB7xjSFa`i~Q#Y(`fCp;?K*dJz*FGrr=PAzaN=3w2qg zvosXLaGV-A_KIq9k^D??8Iq)jKHh6hBX-u*IC`!X)l$=lD)Qi6vd*qYOKwI-hQ-ne zykEER`p)wTGVyL&HYfmX5ZYJV_3ZL1aAAPm@C;ea$0roZ5Ym)uJ-_s0u0fdDN&=?@ zal_n)mg)Zc%i0|<@4XsyK90~Tqi3$Nh``&6;xxS!Jm{U?Fh|N3ndhlvKimP3RBMvP z?N?358?JVN%us6kG?GpUZP$S`W|6cR#mu#TSH*&AM#utBjP6pp4 zpPjIyaR?zO51f?yHX_YL z*}h_g_@n&Z_X2oG-B4S+Rpo7$<`7sW81utHw|;ek3Titr7Ae4O|J^n)LoaP>t|+0MLh()AI{05xqqMAh~M80%I5?tv_f#jkY8 zn$R=P+yw+Qd1v#%m1I|dGadW6v)U&Oe%F~LofE?HUvhH4qb%`sH$OnZG5Z7fxJF3( zhaDn7@`+5-d7`vkasRZ*RV;}420_z1tobpz@pt0)jhD<4-lnl}jeS?c{Mb*!B!xPz z0~r`rVV4Fq3D{wlA`;k}GDWJPJ%Ie4@&KOR?*aJns9~Au?jk_WKu(n&HkGgBK^295 z>Ds<$;EqhaG;S{50Yi%At}E4}+@w7U2b5klVRk`JxOzLguUe(Ud-%$&D(x%B_RFvZ#{B)a`4 z;=lj}`$ymaK>_`DNr+3m5_1d!1Vjn_KZI@XE-E6RMqSP!`yXQap`j_JMpRgy@>|== zJ0g+88b?j)cX;9W{a}A5aMrqc($@?ALrZ;q)vp>xx|5kKPKVL@3UzQZx*FS(0A`v< zWhT{!DL?%`aWEjCgF~il`{IZYJWGe{_quK6_i+tuiz`_%GgmoO*nFp!OhQ z3UqFOYkr~)sO(LCDR63GG*bgOy%&L+`Vob7iCcjPMYu(~H`lQJl<@Fem;vJD=f}t! zqWj0k$;san+|-;|TSll6wWe6?+K>j~9?=dWll;eE>8C-=$NQE*&u=D8^?BtXE`fJ_-CW)Bq=l)2ELegbu zemM)3wM_-IV6Y+Ldi#f}M=JOW%oU3; zY6JwmhZtC?<*I3Ph3#HhOL7?k!NZtCCqXX=in9lf-C|JDESPQUcQoh>n!Y{Pi)OXI ziz6`P!x*TpN3ib$*`bI2@wpO!4*Gw$-$% z6P*9)JARV$0YvY|GdW3xluls$bEOPCZUIdbZU!{!{pHI0bwN}o6o5w2#b}fiydxk; zV62iV_$!a$r)r4T0LSjeqh#R5izPV-vjy0Ez_+bqm!*gXKWMKPiG9DX;7?ZUC;0zn z)$kxeby?tnAb_0d{zKIKGl0?4;P?K05LY-h4u|b`|9NQGQi8cUw+h99G3~qL9K40= zwnhZB@lf)FWSVPY=>CdPYZ)y3>}C*CCnR2O+Xwhn2FyqwIC9;jvE|ME3@?RsZ#R4@ zq8|`VhH`e$ZK$tawyMH2Mz$S{anxDSD_$n7b=acIkXNtTZH{ZtnBTkv9%t+WY#FWF zm8&-%AiklD(k$($eErfT|sIt3Ds$Bi=vH=KEK zA8_YR9^Pyr3MFS@I<|nPp4Dl*)uJ|Rb*4Z`;*unl%o}5A=W!)pU;8g0|22Hi`WCJ_ z;N292+b&vtj>L1hhw0N@To7_9#WEdS!h$`XCx%bW%1Q+?T!ke3iFrsRDq9GKJRy-T^-T)yhgpYNTj1V^5TP0t?&#c};TwquyqSfgSGQkgydwG>Gz zRY6+x#wIo;g3YvSukTHu9=9ZGoU&n0%VEG|i-mXQ7xX+M08s1|p;(rZn$LRF52ntY4|u6>s0Z+YbS>f0SEr!%0A3qYnQfH^Sh>pM~MqzRF86sTWqE z2B^b`xdIduX-_kdAFeRgM|Fj8hDb)tYoi-En_$SILZfSRjn%fA?^h1N1K*3ivgmIuqAQ8P1H-V)JUf=)& zv`4=7FEi)EHNnbMp-|>zv&#Ah4>8pGks!sW(Ez98*aD+f?MA>CZ+OG$Vm;JEuEXkqB&vuRCvPS5R52wsG6Ct8c{QvL z7Vu0UqcrIbe<-~+r%H13Cl<3lb6`RwSurE(5g5u}yL0PiVpB{|g&+ROkbc)25Azwq3ZV+gs4UU9!+?bh~3VeWA^8v1Y42gnhF!PAgj7 z7ZI19w?&Do4kkCUhb})Ry@~dO6?R#EAK=Immu7?)$^Ra@5UQM0%b2gxkbwMNUz(~2 zl%h%Gg$(|z5c#7_59-c6%;X46?=9q zh9Vb0CH_yIprgYubM9E|Ox6B88(>vFZZrv#+3O1i(m z9A#wT^H*zGn;aAjtT7Fkr7q=cwp43#e*~u5@PHeZlg%iV2Xg+A581MFzUSGoiw*fuwdv#X?FT z#;GDJeJj7Dd7q=BUVxurBL`jKCzoqWW-2iCP(Jn;Gx$sdG3Frmo#vW$M6hw$sMGyl zThJTT?$Zk${+r?R^jhr8Y3567s=aN#*WT-)D?k@vwdXx^UW%}*P3b~JM)s0omzp zQWufAbR$B=K1o=~aLTD5=HE;EmaX`i3ygXQUGV1nW&qj~G_X9#tkF+lOLQgv8%|q{VP<+J8^mHv$ps|M zJQ(Odj#?%Wp_b9w@5%U({O7q&Z$7W1#JKrnXtK%Lx5QHJ9WNyBz~W75gZ}^! zLj0-*vJzto>@&S4XV0?mk{4R%PpE$#pGk;Z10Zlaw85f83wE5*n#m)e68d6apf|2B za9em@6P{k7k?COd_p^rmz+bpMUHBWVT_^a0wLr`u@F{teB~iuK6o?Xq?}!!CpG@DJ`7Ypz)Yw&xCq zUoi>Y;kuoNZjJmjMA`Tn2-x32L-gqJL4YC?@`j>cH(#jpG?d)0r-y4$|39!}z}~b~ zD6_6XmYfGRqtOt0ulVQ?<$}|Y!H79F{+p0L8_-X#Rlf~z)?U)}*ICQ-)p9Q_`q~Rh zR?&W3QywNie{>1o1uq2i&J%l{A2a;W7@O0FYKdBne-d|H3yHrn=ugs`qkX9iCsn#@@ zzJdTbvaS#3`eSA6?pL1p0sIg~Ny|>3^UooR=$Q@7<`iAXNhIue-+!%F?3N_RR`#Y;VWgA8x0 zxS~l{{HYUUVhdjX$MsX?^WNcu@dvr@?fUk1|F(|kbY%QCn~JzvAk@EsUOl<*mfQR3 z@{WOis1I~KWk}2XvbiFDnba6*&f;=Qc7^pB z2szbR>o@YF(pMM=2zxk(OT!CJN|UTJxFO7q6#^Ih`CU7x&{n7*kQtgZf#E%4V_0Nd z*gj*b6)$ApF|F9VRjD7;)^Y3=0C%CX~f6lcnKH&tJgGJ~f0$Pb}o@ zz%KYhP#(n@bpIJ!r?!puGf~N`T-z8p^<)Sk-fdNzID{J1q}uZ9&4ON>J3B?&>xDCSCtOC<^ed#YEdL&*Mk?!&>-diIgR<!-+R;4{-jIpm``jGWs|J>9kzF3l{ThIfINa&2&-W*ah0{6$Ns7cOQi z+()h^pfDiWeLBm^+P95-T>D~|R#qP`y{d8AY6gEaD_vw>qFYaP(Gz#yjJ$HrJr8vp z3aqd%J(!1WYXeA?*mTRl)yM>k`3WNa6aV6ILd7bFIMBuPLiXrfv!7g#0cCvDwLcRS z^Q|)F0dFjp`_)Ym*AeNg50Y0*fDFddo&_=pfIq+#omdpXr*`Yl8v_I;i2@=5EU!n- zLMrj(@nRSgdX~d1-u!&Rz=Fd}STY;>T)q@V;HJ(G^ldoMZxiq;2ZB(2bHaWoY%UY9 z5RGZa@Wk|hcbthhUNlj@M2}g%P$3sf*~Wa}`r-I~iv7g0TXmh5WOF-X)|=r_v? zu=awGc7xgc^=3aWj}(YZiQK4G8jj!fTu$AEe9?t6$eOkW&ydw5DNtBJY`7T{rj37y z&Dz1^+35Gao3PYDK33)`Xi-DS^dp~5&oranK$VGZ3p`MfNS+=9Gflx-C27w6t^gJR zye};zA5D0sz{}^NvFQXcDw7UPZ}tQXD0xO$ArP?>W{nd!0bIY?RyRQAbW}cWmE%FK zd}Vih*MDHU>q4q4@)$Hj=6LH^)q%QjRPy!j8Jg;B<^yK)jBteLHWlPw!c(Au>iGN^NEflK(&U+1{Rs=+C^ z831Sfx!`Cu>vx1D4YqGrLmrdW-jcKi1HQZlH1nf=ArvwXz(p6Xw`>>iU^)H4%9a2%42yf6O4{ zaxi_gKs{C!2Yw2+I|8GBB617(0wTeWvysvdfH6h4jJ!|;&0U*n>+}m&CC@3Jh183%*tZOKsW&0I79J{7D!D`^Z_6W4 zUM7>a+feCz#k;?fPQgtQpqfa#B9Deg0l8~vAvGtSPLi>pi5V8q*KC6dg!B%a1)AC2 z6SGGTB=&}0M}3+|E`p8mb~s8^s|MF?Sp@1w^k&$_$vl$@eTt-WscF9cNWGDC=Jn`W zsxxc(UEWr)-*HXHE}oiP;a?6tQU?u4@2*vIr6uDTna&2gW z^%Rc1kmWbVs!1(7b7Ym^JFO~Ve*b0PApBaoTVhInq>R~0mNdUuq`I2-I9EgzQb@Tc4sozQt;AX>}5 zDr~m9Me>#%*tLjcv###>pPzHmv`zZVO^QN0c?I4a>0ko^#o|uc=2G}$M{nH;thye5 zL|?`iWY~f}{OPk(x6ejG3~1bA3(E9yt>OBNvFqeNn{e;`ofX!=Zn_{GtBHHh-uP{7 z(2x)NES2C}mX5a&xW(u`g;||JjBdvGoV>GT^Y`9X?h6b77%j$*Sx0YQPHH;No4zf& z^Z%}2%%mv;5P5_>c3Eu+2iKfU$vb(f)~}`av)j~@FnMF`>L@9aw})QwS@t0LOEF?4 zsVhJs?&3D3;^&f)&Zw%}CGG1%NXXk|Qv=*O3lz36N&~YyJylU?U8RY-F4emLBiGVi zP3K(KHFUe%B$4?pH|}Qb2|kY^5(n=(nRfW@gH}v{6GZuCV?zD~$m~*8z1If$xL)qeCc;#kLiEc}J)UO>Cq%rCh*XEYkR=(24Sqe_y$HUaM)6`7MYd}W z0IpU0ixTqs!&F6?1YuDRW#jqqwXlKE$l9yr0 zDT))oDX;@^$SK0F!%^f8Ah#Z3sq@L7dFQU%>6=OTYRVXH%Nfa;^YM=YX7Dx$JBd2^ zBA^QU^?S|rFK7JzZ>8b^DqF7p-5tc|nTwTyxVjhOxL}eJTcKLTUSSjlro0a1LSujK zj)oX!@Dw$Y-&oVxO(FD?{fzP`$vnPH=1wH@TNMM{1BOA=cBU#>ZOGbCmHq~?`vH@T*f^(mYcLO`v z;3?d4C%FeknN&1^B<0D{!SLTL94Q5WHNo;JT;UXOf_}6Z6%P0<JJUh2wU^Tm&QbGT#=IzJ$yv|Ac?GU?o7-+jgg?2zqK zpLLJZ7VUQm+a%iXqcL*z@=uM+hSdx!jLA%@?-C@oG;ku?36iy$#e&1|NM)EqDA%lE z5jP+Aui0#MSt82H;X6jB-(u3Qf$a(hdim#Q{U55%fjJXsi?Xq8+qP}ncG4Z&`C{AY z*tR;hZQC|FoV)T+UJJD&sj~s4-wF4Z?Jk(R(%-c(p9EWfY!wqRJgNjn z3!CDaE(&BNXku$%7(f_qfz`USR^(KC5Xh$Gu{yo;b3G5EfW{)$+zNVlYvuhJhU)`s zf1ZBV5JH>+@vaFVyf|b3tsFJ1=(;_xh6AE6r7X?-H_+qGd-I#c%OSan0mS4ozR*{=l zH~fm2@_s8Z_2vHIXuBbf*(WFKTx^>g(^}u#?7>@t`U=tEz&`DcXBcxxtEh3Dym0JW z7NE-fNO{ps9Jx+<0a>*MvPPpxPzzBql|mOR&UTAS6i|`b8*XRu={rMWjX?}fY4NQ> zCa`TxWS>3(jM%+&qz51be?dAw~SHe02XRCtgx1xkt%prbZ%{N?WsBDO>qD?UR z996mQ)>RE{c6#`0^Ge%NO*%1a28QdCePye=E0wMqT=V4;w3XUr#;1Lz z?WCoro)Yz+^L8GFTETIX7_Y{RmKgW;xI-oiwgU#GROPIPlgMO^5s6%mOnQF=K4mt!B8qSxUzo-!F$Q)IFXwg%UXll&Y)Rd`f-G%mvM6*^s?@BQl4KBMqzV?R@ zY-(!Nh-R zjnBKeS5-h_jO4WiDrcl3in7ocX|PfJ;I*A!R5pxv<7MEJ421C8-@ZZq_i^!`UeDgU z3OVkNz63Q32#Dyvqhh8qV6ZgB)}Ot5#s6Q2^Cztb3!F+F*@$oh_oT!axt~q6tIa?x zXX^<&mW<7>zoH3x0u~a`_dB%}Z=XcP(oQc&vHl~hX72SJ?d|Q`o6S$eG7DR?i1e}x zWn65o8TzKs`bXEYHJVHX6s0c6oW>ZTHUp>w)Il_i}U=g20LWeq3RWv zC9{o6ILOZ5YdxU_=8zgs*}=COJDKM)2dbhI740-F+S(tJ^EAA5@}_@3`%s`uc|aW8;a<6f98{mbNL>Svz_x z8W1_P9HPp{)Ri^n6PiyK$GV;Ws@fUW+nsJpc^Wq8t-Y{nab}__E{ut=w|$mdTyf7e zmNzEPQ#PY^y&m@E-yYW{ECu;wd%lma40F5Wb9+4gT`qC%2Iyi9PCt!8fTb_TcD3o}?4zr`8y;)J zONXUkC*Wb=Vuf+1_@>+Y?vu+u2Or9`;Q;aWMb*e~quVYHbt^W8dHLr1>-gp@=_ZH& zpY_}GXQd{i!KZoWiPETn>j2O{pi&cInT~B5kRU@*`tXiXjxe0?)axP-6c>l~OAykI zJaRIlXR<^pKs%xOQ%^(G=|9U{zMo!E7lmC?A4|9YibW<0)js*`CT1lLK$+R_gfz73>fLNNqRNM1_*tt}3U;Hbro-QyexWDol z`j$fEfKWITb9Dl9b4^JiyeI5VC`%0+Qh({$!ODN(T8rl5cF%_85e{x+ZbXCV>T{*P z3Z6wr#RvRv% z!v=s5wewFz5x8HyaT^WWbOX1P>+IF@!ywK$0^l92{3#os5U-eEu*w zHnFdR?_D5(L(MaV`*^9aV)2vZrd8)T!{wG`M%eHxc~I3#YTD|(D7R^1 z+d$%xU(3}e&N2GEAJn55AZPWP6t_xWUNd$HIA*}r(LIwHPX9EkK<`Nht6l-%^YQ!* z?{k@!_60M7|6Wc%H_|9*8+4E-*&`Mr06?s*BNRHbH?F!stTW?kn}gri8KQ@Wm_o<^ zf2=%1xM&eZk2|$A!zxP;?U93u2{*dpW$4c=Qq^NdkQTXB$L+|K+ENYmE<&*-7MgZ2#Sb)N!5s!>J1g>_0j?mth%WU*Gv^^fth#W-r{0N8j6v&rJ02tpwV|9!~?<`V$hS#QFbsw zFjg->&Fl(an?Rm>j;Pz5#ob?0*yC*4unl0+A1aNmsUcwA#q_{fvJHwgLgTtKMvt<; zSu=6%J$Cw_gjY}V$Vq)JC%iyq0KN=AkZdr5HpX*?i~LD=E3#!9tjYpo)T7>#kwE)8VM zz7ESNnl9VgEz6mQVx1PJxVD6U!Ie4~;IK3fSy4evf1z8! zGtBjIuaF?ftC`nRn9*tLwmJ|y03;7%jSSQBtB9ni;r(<|AGVr3-k!@A0snV^lh`Qt zrtQDxwTPCcF0S4+-s#mjpE0Ly`11-ri4|?=Kja@^_mnmyhD^QrbRr$@=)Mzf9^*t% zShInO&=CE?WRR)(0A!9o$e|9I_4*vipOZv#`vUweBIiA}yN`5UUv5~r(A(L-ou#-q zY{SMI1330rLfjEDwj|T%+qQ1#18%!!*49!Y>(uBJ`ZOC4nLR z^{G$S`eZps|D{#QmGWy^9pFEelGLWCEOn_+IvJ$LAVI&i1)J0tGalha-2L;!CtfEY zvyt){foeFW0en_H{qAJX>j}4MiJ$cHn)4K`O1wa9p0b|V7XfUpth;xLIz;RSV!SN2 z3_^7qt-bXai5tb6*~krCS`u^M8O*PWI|$5~Q#sg@j7D4se`pEDdl}rGfNT_<)ui&#cn-Fn+Cnkc#taPt( zWA!0yPN%G>Z%QUYJ0}FX0D2)dEMEP;7W<)^1AbW?$-7;iT3twMQ%@WOT7!GmZv>Qq zfuhz1QENVe*!895-M^LWTShZ&77k^~t>9bN2FN~eBSPg>+ZW&ygBVMM6`&@@9Z$}L zVJy{y0`TBqnSV2{LoqQ_wfY2~z6Y7^Dycb?1Z@VosVCw%9q@^E&_#3dEHdSbP_g(r zGVM@T518DXnWLY33N>RM!zwhe@M*;(fJ_33_ zlIvgYHYjye<;V$y>G5`qrl3yh7I{dLmY_bL_tBDbEU=MF?pj~~!Ym@ekr^u>DyFW8k> zKlDa=Vr$AyLI}9sf(R}KSJPlfm?zZI0dHV&dmO`RR*iI&xk6Ur=y$ryA8}tI1Aamn zhak^31Gc{UhtZ6@I5Klo;A)6C5TbVi7ylf|=#$*+*>dwAqDuywgGj?nVb!OJjIxus z3|{e;n94%M8 zNBo^NyQ*)I>-UD8K;ER>>(98%iATvc2p;cR-<90%$A0Jy!CJZJ035tyW=nvaVtLek zJ!@epMDpw9Nf(7-5$EccM6XP(cJZCag$dm%xQ;X;LWI7N8sr{m>K}q%CgF+iOpWYq z;*7Q;u+_L}ncP~@xsgJSfR?8sPmhgVvtk*dE*n!^$flWNE33>JJn3f->(I@t%lB(J z1UY_3@Ud|Jo5rSJZR+ZylmZ2pFL~Wme!a8US$omqMeO zEkeve3x^IzLqumF=rP?`owc<>Qis4Ai48V)G!P}c#?VV3FL*;q4rp9bvfmoinKKUr|VJ zcUYfk;;VO`^1ZAJ2rHPb%Dq{<6AwBBk9($>Akb4PQtLi0qK1_N6xIP#88Lhv$5?es z_vn9`OE)imgyPZ@S@H^E_|~>qT6=dJ6sq@C8$+uWGlm~0fR`DD0?flr5oxgHPD+4y zhV57_2~?zyg;S@Y9&R?%&tdQg*8SjZLcY$A;|UX z*Xr*cn8u`k0F&h0Xs5*d{-z(b9caQK!n!ri_Q4=u5sYM3n56cpD=Dzbkl0_=7PUWt zi(>a7wr!;ZV)U^nNyg9&!Mk3(RiYEy_fHEggU%q6uZNpKBW54lZKf?5n>PimkC+0_U&AM}ZQd6%y|-9p;B~WDaB*R}Gok@ezm4i4ryWDJN!bqFld`p$ zOpIU;)zD47W~FyXx-ompSIJB~x7!-)cI+8WeVCa!;K#xd^W^H$r#C>F>M)%BFqqT% zvk>-#0Aw9=TOwSNbpiysmT&jD4%>E+u2ix0L=jz>Z2KFHok|Eh(EhfE2)7%&o5gI$ zuz+&$q1e;LiFH3)`Uc-#P?Eums=_HTB(KZyq%8`^7~2zIY$~i(65i8;WczA0$BX3J z=dIXWw zfjZ{&AdMVe5)~~Xm-@bsc@1?XzQ?V4O>~T^JGB#$0|s|lkMn0Rpg^QQ8sc{!buT5o z8_9%R`xcJ`v`I1_$FFbasghIaV~8drI70Wg$nanU&^2|wGUD>QVD%B zf92_jg4U;o3XB?bB2CtW(T0)90ey`MK&klYZ{_S)iw(`weEgj+v$F-~{0Xo?g0g$8n4VH2`VhKU+@#;i~Zx{19z`H+B#iO1|w zZ@wE35|$73Ex{3{Sk`B8q}0&^KayL^paj-ZalWqhy>eRHNuPcCuA%i0@lXsqK&XvL z41>|LD(P+b!1>uzp+ln?9U`ulq*PkGCR5i6_W7vR494gY`#Z8HRs|OeWXDN6MFCYm zav2r2%WtEDHLf}oh$uG-hB%Ntd+k{5VyMS}_$SM`AZ4IuGEEkXRNdYyOJij@gXgU} z`DccU^M7RO4xzDQy8&E}Y*=bSfSH@!a`XSNuz zq+X%IM%0htgleexg_c7n*ckUp>R2CJ`941dsbRurTOINb;~k9f<8SUbz~bhTy&Gss z&o6TNRolQQ)b?NJ1Ew1l6DbH-P;mV;Aitc+q7Dw18^Sq_!r;Qmbpmb)X=-z}t+(ow zakSd48~HtPjUXKP2v*640bi@~9jWE}lLkvFvckn6%#xj{I)BP3K0<10#`myS^~9Jz z+kVI1Z7y!^;Jr_@zoA7P0)QNg%AMFjYx^gQDpr@sPiYB2JTuNzjbHq zyzjfYDKnXk{$0StqIrl1Lc&8KH8qa53cm#SB(^b|4550S)Th*0r+?H|hhgdGnMC%G zh1y|KbvSW~e~|<2p5eF|0Fx}#K|WkYRF8K`PE|ul!*jF2z;4#y1I+o;cC{qeKKbK3 zQK@kt0Hu)>P}IrI#)lhyRhmRYN?CIC_~TXjTF=g;+`?Tt5VVLSkV8V$ZJ{1OpG-=4vT5)@x`vD6K^qoK_RH8C?nk7yv9L)2xcyYfyqt8r!y zZ4(-IfiYIG&U{`gfbkE9!EXne+NFVc{@X-sMc54frf{?C1ZE<_bFF@qPr(pY(jl2I z9II;!vbJ(b;#4Y~8QT?-qil%`hYX31{B@@&DS2MX`5_+>&^{iPGhl)OVlVtL6pVY4 zg)RRSi^MBnW%ndl=m?YZ+1DUxKRdI+P7kgm=pZrUs%Kvi3@+2fEq!ORd&F$|Kv?1P7K*gD4rdGiD z#<=E!+Qb-z0O_`&aSHru1^W6T=!3ajc{Adb+7euSv ze|P|SUcm*{Ncwk%S|P~KR6OPI3fvFt0cYOQ<&-wlKC6LJW-q9lfhFI0y5ciY8>dj- z4sescdEe}9(rpF{)%y`CM>5syj-(mG7o7brz9P*;)4m+%*S8OCXAQ0e{B7PD7j@t(4Y)j)W`exfaYpO&O#z_ju2guke zdW?>ioRO|QQ$&&$FbP2#j7~kU^nFo`u)>mrs$kmz^;E|Yf?-<0aU4O-Rs&+5Lg?d?Tr;{#C0s9LfA!2 zIkiTX{^<(klnP|xAQtt~`c3>;$X68|dNC2(+hB~H($)RlSAWO!Nl2{r%q)EGDvz5z zJcP>p3nUdil3>)5DQzicf}m2W0F@XmC6YCDg)C`60!_c{yvb8-PbkeG^dz zgbfx6A$272Gaj~}d3Y(#4sN={O`!AvTAwx=xO0(QxPW66=1v+H!V=n*0tLhWuu5CPH6V*8SHQj#2V>kM2b%t3kbP}#T6Di8GQ&C#5e8p9g zH)r-|`c_1b8qlEOLI(#qm5|42$c36lX7L*T-mJJ(U>U;8KC8tCv@D|5B4ajNX z>CDrGB2bFY{-mI-edQg%fQW>kp#nU5ZB*}SdMW>{$Evo9W5l%&!)(#IyDc5uP`_`V zf#nViR#P?b3my})+W9!6y!>8Jv?`I%JT^X+Mj{MIygQA{l%1?(^rCJ?oeexMmJCE} zc@nDd#8SAAtv_wJ$-Lg5E9Af21sDf$lg9lqP2vxH@>_&6|99Fb=-Uo6Gtx_i07XeK zZav57BSWG)(%=@Q!zodQg>EDpKg#3p5)#UAHJ0N)5`C^}T0JW*(B|SHea<*y(o@1S zm#VA=t!u8THb@hZG-$k;vBFm|kXkUi;r9SFa~_b!o#IXgX2hp6nax5)1qgoPeBm+O zMjZ@X(awaaeV^mhTH)jzgN@RM^M1{BRWM8TR7L{FueqQaE^#Ca*V#VZ7c`2GtTvXG znXG+BqR3g`LcM*Q9(VyfzH3LjNaDLC_my7{3^mUV)%NSisd4sABi8&@|?=&Gs^xnfy$R0*^jBF zG~+huBq~PUF;!bw3A3_K%J2rU{8pA_eZs8O=nT2b!HkYf7aT`;nU*Tf6Up+D ztMCXJCt(^81q7NRpouS1V_GUu@VTQWghu3M;>c66WJxCZNy?T5b~mpD;JVZ)#1O=B zEzEl9J(a3l%UcH@oKIyHd|=TZ6gk`{)>*K$YkOqAU2R@28o3DzQ+UwK2mZSD8$;yJ zgsni6^|W}kMLme%dPrxs)2-XTu0{#&sM)F@fT`wN0caQ3oRtZ|9|bo4iJI&3;(2<^ zy1~KHU^}v8TV|y)|660LpiCp)SJhn&Ev2!YIyKzyV$Q3)XvS>bf7m>0zTnEjsWWl& z9W8OF0DhQ*k4UQp%1z-DyLfkPp<59ryVG?;%x0`iBpY-RL&y!Msk$ zrYdVw+!5!zSy#SDZ!j5H4t)okg5NsnVHIADHZ#9H>YYS*`r;`U^s6D~XwZ$KOwoz4 zaa*^0pfq$eMS1tNSn7=ZOy^auc~C{0-(9~z0QXp5Kd3vC*E=~)gcALt-*0jtVcnpGiC>R z^G%m!^<9aA3y^wZO%{ty-En&kz>m)sAo}$n*2_K?2e3t>35R6@lhG?N=WLRWko~$T z0A91>ucl92fBipVlF+egTG1-IgnBI^=z^(}6|tsBysDHdeV?uNB>8nWrNNjgAp$%s z5J7lwfHNC9o}7A=XcHP|7T~mKw=MWgF>C9BhJ*X<>ha#W&1qY%-ZLx{^Q zkQwZt18a-;xQMNAhwIVxD78$@|J2zpKuI*{S)Mw6lXsgLTNQ8Q|Evx*@OKxej(>Yx z;OFwXgnzn|LSA$;-r?t=mLyBQHp|)7ZdGy70dHes3yOkc`wI}ati zbf$o2Q!O}mZe;{~X;2{B@;s$tt7fq*)P3mKYn-zbW_(67jv*Zem_QHmGvok-g6Ui( zgr;0d7Ptl}RlY$3A3aD-?bPBciE+(8A4BqTgtF45X=~@#ms{#{v#pH6o`Wz^U2rq= z>V1}lu9>3ZM`AiOJI!wAo>ZbrfEk7lZk)8=o{p_q-n;F70!#W{G;$^?9a9VRAV8Bp zsUk$8&o(O;H4?_UCL|RKCWO@pwUaOw3J$GeV{dIeTmtF7+_GtO^uFC|Cy{}3sQ!S*Do}`b_ zayr#1R8GG(c^0*BtIM&o>uzx%q|suo+Xw;mxetO~fcsJ3N2q-XSTUI;h1A0YHmq*d zacf65*oO^;$jbyGI!O=DRWZlrq1Yc96!W>!s{TRE51^W^gAFGSd==nH6Ib3N`Y8It z%aN7A4ex-kWo^!eN2&`iP{kPgKr6OtqC&AD1l!=cR!wr!vymtmGs7As;35j;Y6-MF z$I0`!39ioiJHJW;)}p`F*-n?99e>3oT4_J!2MW&^`aKLZmVOtsFUdZ+1pf7q3ix>AMU2%+zXRbJA7{LvVzQ8oh`0@oV50q}b{$qu#cCQq zs5=83Yi*hBxP3<}6ul9wU~ulBFZ=lErnTRs9~T-3ba(p%;GjaxPKw}O3u__Te<`Ix z`xy3&^mFik9=kfQR4iodi6;1lMjTN*XB7DMsro)Ip=S!sm*=VjC(rGGr`{EtjYW4y zF`$K$NT@c>jKy5QK^#sf{s@Gpiu)jA9wq*WMgI^T+hgOmDq7nQSRZTXqvF0jT2yUS zVt4o4{;eAbDA+A()~0xIUt|9Vu9y`eqm|SGG|})H#zi7(Tbwe|iz5p!$3-nH*3 zn1x%Hu*ECksaj$F-RG_y1{z3@+jvuqLyqhX6jiQ6mSmxQ1-bu=GqzaC^Z0Bpa>b~A zo^b@uw-dBgd6tsFDcnyO$F|6#{~*rJYAt>WV4+9g89r~H<+?F26F1;+TsJpY z(Da8MjEi~00fDuey=RSVB~wkJ%b=8#QKJ#VdM2yhZ^f1#VpAQzcJ66#Ay#>-FJl>v zo>2$u!8Gv;duaBE_>zPDZfe^K>i?_TH2;+5YFS)Y=Ewfc6CtH1WR0Daf50{eM>)>Q z_1xJt@9pyERJAC5ZvqFd%`J=@=!G5 z4clz*;dVJglZ5jK94X8QujwZw-C4F3C=`KF`-@sgjJLisuPH7`2D0{xTn+iG<7i9c z)AmNn5hYW*Lvx3nSs+FH#drAN-oR2VYV=ST0703){vBo)mx?x%!RTJ=aJ=!19(Lfx zP6Kr6q8^DV;8?jvebdr8UE{Pz-z$2Po_XmF*;Ctjt#tImck1STM8pFew94ll-~mCs7F}$_SgDG9MUtlqN?2 zZ|BNyge|?amsD(Cwv3IxXI@_iLrGPYJQO`vM||sH!Lm*FNUGd|-!{vpuguXWfHW>~ zG(4bb`((4_8-NXK-l#}tSZXTcQU zD^^9Q56)X9IarY!n66oolu4E>-!snwAgNAyWf!`FiF2dhaKF$+CjY&91=3YZsNBkOSK5K+&(Ns+{+`tJr$B1q%(~bF!9Ao)7 zK2ZxhBPn!7+C!|01)WAqDEtz49monddKAl=`(0wW4y(YKq_Tj|?zv;O59Mh)P>F7&g0ju#ySPML0wY4Qn&4*YZ&AoOz_s5&lEzc{Za z05_9L4N}tEm(BV_+PeF2VXQNJtOHv*&i;Hm9ImG3IYB&lG1bC0S#$FA&flNs6}~l7 zcBK_tOR0k}h0S!o&1qJ~y6TIY8UP;#=u`tyvFGVW6&1zR!PAE)A_Sxnnd3_$*20Lj z)$DFERplve+8v&hNn)5SxVgZJ5TZLph1uL)yRT$^>QSs|VC zbCGUOYmAt1ArMqU+kN4uhM>ZS?#{liX*eDNo5gbu=g*Wp0n$hh?{wf z;o0pWFiw(r53_HNbF)0H)-EkjGsUtCH2*kos=!%KoSWi!PE5 zbZdW1@Nu3#pZzrLS_RT#aoL{(XIC(xp`aEncp=H((wJYN)%B0~&}PwpE`?7e+RZ#u zFa6>{XjGGoG}41yxXmwon}m;<3dSTob*vp%lLHBAv;y&BKAytITJ<1UM%&Tpj1qjA zDrBgXq%-d(X601;dH`^UzmD#{9ml_y{G!pqc9z2>{T$`av}iHV#{V@e@^M*FMs#zCx_iT+lH8W7m2bMl|$#(Sk*OQ<^oI>=_b-;+IBbfWm4H@ zdHuX2fD>$cXeVYFiSWXi43sjjeU~5BVE9Q9M8B(cKMg>9N&ZycITu+m{w^yb!zh0l z7YFKv8fUpUN(ma?>yM!W^8+GVgh7a@LH7dINrhb+IjDC%J}ovo}AsV^gmpSdnjRjVd3)318PGkW_H|Wx5xELHyg&A8uPb!~$K$ zgezeSHH$9mLJub~&3FqegeYTz(Z?}93Zl(VWla-%Eeu$Vn{PK_RfM1w3Z_P!qB1C2 zLoX=EI}pB$R#BEJ<0!Ljnn9BOn`)&y`wy0d2fV1L18BI&#Ozu~oH6!<5%_}Nr`O2X z2I$+ccl_=?7~IL^jMrAJ#gr5|34&Hjme z00^R~&j@f7%OnbyZZ_D^h`XM{lfeBh`RxA-i!U%YO@GxyfA#|yY12?F&s?D3Q&07kZQE)$->db7%i z-pBV!_#2AM?UPP@f;+*rxovDMxJ*V$ydEWjJ_7vWQ&CuaHTM0%&fB8^A$1V$q$feT zgXJ0B-NtKaPq_IEb*bp%EyliTir0WWN!jdC*&Y;=N++t;MHz!`0cV3&%HO>8Cic_l z_X8*paQHISJ;ZY;{FGQC@@ao-)e>Vb@~KEm4NsE^+{+2kiktT`OHlVb?*~8-)rR87 z1f@zFb0pWy5|YB#doZGA|0|8Shob8B(cOcsM-85@z*D{;b?%i2JrhzpeGlyBF@YX7 z?v!WKkUcn!@Bd33KK%rOQyEbm2U2O<^Z-~1ZS-y($k4tl5Qz3;h~>ma;nqPX0sL|9 ze`6}jUC%KQJ+i!Px|P!#T=8?yYANJkRiFhRf(VYHQuZdD?@!e~9)^^+XvMa(Teem~ z*0lo(!WIm}Qo7 z%WJDAwW%6H3HP_t0}92+0gzsSlZW#G|9&9Q6wdJv$#sQ%@bW)m5r)YYUY=Rs&2KoC zkEN*{L&MtmVsL#Pm8&BIT=xdZe87?*7uB_{|AkFjalGlwpFYhUgbP)!Toj{WGZu3r zcS|SC$fT}9m4N9q*ed>hL~bsYyiy6<3{bGSyoVf$u!agWNUBbG-S6R)w9 zoOeTesK?OPTh*TKKxWJ-wY=^wZ;IADs3m=nnEZPIawb;3VCV3xHHb+VxG6aS4vq%h73o;ks_kV6*+L?UXrPl*j zX-Uy?00(S{!NQ!}FYIiW!M-CGY6LrvS|2z5_s=NIe^;qEE95iXk#_GMY07!Jduyf&Xhue}0;NDRlIoZ_#=~`a=2__-)LWj8uUO`9y=u5rAnG#}=npHZ8>6 z5&48cEA|z((lM3ZE77R&y@ww0fHUBzu0gRa-2#J!rk4Eki9%yl^;*spHe&IS@P9Wp zjsj(c^PuXu2~Z#)ZP@?6MRBwL)1qkB_l=q#NSTFOUZuoQ{P?90<>+80Y*y(5img&a%6bLTMdo8Pj^i`egGz5?4 z9J%w)Yz+hjhO`X}$Y|wuZMrG9(2qxq*O1y4wBg*6sfXL zvqJg{-d23Xc71i?q5!7`NcXE3lj#&L6Xw#SF|#ySYi-7GT~aqh4=H;=;?{+KgChwd zp)~O_JkzGIo*dO!1t;jrV9pqdYe%&<)#y#Rr)K>z%Lt%z9KcUxF&b#Hcw2f~w^Qf# zejT12K0WJV3(Ih_^Nq>NL2d}VhZ<;6N{GxVUQX`jEb5fkbVr^N*v>v# z+0g6_1cR*X`WN%a5$Su z+MPkL#AJ$-nR$GdGY^Zw94CpG%R23YGdAvC>J;y~n$ij${Y4bt={^o5M{S>BB1EI@Pn_1r16&CI@AnUqQJ8Hn2E znp{R59c_P*Iu5OAQwFm;5Nv`u$;hzOj9i^9^#huyS;(9>=rRSUHE9vJTlJHuwnr9M zdmS4uPBMM`BJ|kQT1X58)WAvLKQK!yI}swSF#_gNd^E0MK@a=n#VEHyYKVxQuT{mU za{@Vy3jku}(-o6Dp>JK3DYiqCDZN7#?>PTyhy6UC>74VUcnx#DC8^`6^4bW5{uKrB z6u4I&B_65$0@?=1m|Hu88k5K@PZnu)j&i{p^p~J?SjOUZpjq9Ej5x>L--eDPMoLQK ze?_10pQ67wlg{32=ir{iMQ%wP9OGA94iT_qn{C%|H{}x)_~wmrY#Mx`Et3HtOo2;JIm3CVo@!Bfe>3UM+*Pbm-ua9|dihsv_YS6T5FTpj~NAe^Qwl?5a zv?!O%{4kly^2;tj2zxHyTjE@+Hf;BvHq_*|vo#;TmB*|~50sW@Hd?}Ju;hB&YXM$& z4;`(v_4F;?8K$*amYpal2#O~icr?xIS4ptIxtc>UKI%(M zR{3@s1yzgj7b#`G7r8XEszXyi1+XAT0&jH1L8xtj5Qs9ON zqKrr9B-y#^M2PwZ8g7U^i~z=#x;(?(e^C`_K*_;e9r%rQ3Q8?RkCc3 zT)wpYM%h|D(3at^iy05Y5WAk;HW{H6J?zS;m3ZfJo2900M-bzxF9gu15*0aR`2C8z zRAO6FsOUR`LEW9g9{~^zvDb23OjCyC%nUP96jMJn9T;l{Et{%-Iwp_R%yqnFtEU3i z${Be=>`%d4mSb|!KG~%qYg(?}VZ(@C@N{G|hB{b$S?^%VWM(Hpyc&bo z)AGb762pxZJ$lf^Rrk{{aQ8$*tf*o@COoXHy}u9&ds0B_S`aL-Wj9xtkE34}TDa70`u(q;Qq>kt_OSlyq8;Hgxmv*?0pCwM2b| z&|=v2j7ux+x8rmHEt@XI@$ErIRGR^2(ha+Xm&Spa8@{9-!haS%rCXqHn znAVYWCau{<4;-RjC#|i$+#$Gtn=(m$T*&7wz*t;#e!u`e&namrNgVKJy}4tn#wgFj z`vHGBq2y+We7fu5?EuC`Q)l?E+Qw|7aG6MU^J}lWSJG=-_{#Y_xgZJbre4Z`n$vT$ zNHTV90g?Z&yu5|*_e$3-f~$^iAe90l(& zs{p}1P|!{q==RPvng3KL?Wqr|FPrzlV&Hxs4r?0g##etR?P{cO&wwv@%?$t}2u zF(PxRyF#CL;N{!Xb1+a)`ra2gkdcn0sSk{ED?zyhXvCURs48M_Kas={G=KZdrd&Wf=)E!@R* z-RwnLaJSj;e%^E~T(YV%9xE;A-b;BybuY6RL9oe}`{9{CS0*@cKbe#G&`7^!nDJmo z9lP8}b$CnkI|AGetBBj`??@MKx@(;R8LyB(5Eg&jOQtuY;NuMl^s_ULQ1#z!A~G>w zpgn|OLpEq>XrSl5WC4EgWz+bpgk zFJrq^il}7*dc)Yr-2XGh(GTp2m<0?UjvMaH*0j|Qk*&vDP}L>Bl|imcmrK`1i;7zY z{pwT~zyvT=*B4!NJ*Flms5CCO>P8x%#mOXQ$H8!6$`d}Tl>>FwTO;^HRH3qBz|{o^_LY;=f2dlmAWvP79#Jzq-g@u-2hK06YOQmQG3GHyhq)}} z2K~c}ETnv55um$9W67!cr(*BX)^VzmC4$Y;EjEq62J7=GVb1O4Lk+i~27%ermd_$M zLhcHbrAOmM4Y0~HL5xlm^==@Y=-D?}JE%8P*{EM|w2JItPO6=ir%{9ZbLJEBgwpmu z%K>#=rAjQ9_)YB=Gn77pUeS*aRzjr~-MA{OeW&goG@)cDg{)68TQh?mvwp5TL}LAu z$^?-fNv=SVOdomZ6W$cvjLe(?8`j3DRPeO5A>z5>va?~2Xv~SM7ikrIZ(Wtgv^^h+AjYIu{c*O{@`Dg9w5UNw%7u^M z7*7(B``lu0R|3C`_TcEjs#dj-)5*Hm$Kx7tawCt3zVN0~p#$}X#Pph?`>zf{aDW5> zRvs4`mvW#~V=P?wP#o9c(#PC}_(twVcD-`+k+&*kn0#%@Kx)oFF>5c-(M!2xB>JHbW>H%tF0DGkI%Ihh(%)|AJO8Q zfIilqwZ5;_HH?eWptFn8?QYhNvWYDT5X(R-1MMwx80G5cqZ6nXcm*l}%nkxFj|U?A zxija>S*N!|#Of^jddsRHfNNX9FQ&s3+CF)gwXofAOnZkq>1_Jc>hZYQ4IuIpWgF5+ zOD*rYLmdT28}Ji@S+Mj5jcLEjwXXe=%O$lm38OmV@ASBO#afR0iA~Qnz3$tqkY=&y zfHBEDhAYrzN5iecrZky$dV@VQu{tt&Q+&&BVcwpW6vGFS6qM4uLb1`!n|Bq`Sn>U_ zzU<*(GU`R%19g&P=Pxac(9l;ddyv^I_CVm(0$T_U1 z{0P1dG2O@qgiC?75iRQbbhGMgofk0YG`0+{{h1p6OC@f<5S zGCC3i1VOxt%;*jJ(tu01_Jtd)r^r+l})>lN+BYbIQD5X^xCRjpY zh#9gPTM5j*uNt=f0?R%oy@*6<4X4pC*%ZDP*j%X1^`L@@0SsBJQPj!Rd#d$jO5OS> z;?Ps!uUEcBdg>ZDwm`8c)#=5EfIEP&z5MT%k)L))K2HL)1gG*P{uv- zGxD@}@W#!0ufNU%Xvb#o;M;vWfn9k3wfG5?9VFr1_!3g^@*6eO5IJt)pVhM6*OPV} zhFCnN$WJj^0rDfNsjj@Xb$2iDTo3Wh7a#;|B6Zw9avDnZ)4r*c)Q6R^Q?-VsIV@1< zv{ty7^YRGR>(>L{yw&ottpnu&_bY84EJPONZL$#LLDQ!POi3#ZvjDw9Cj{vvx05|00Y^WzE(px8a_+jGthOFzPpn$ zFA18{J!f4WG=5K_B369f!)MyI7+U^FaYvND4T?EioL8fz73n5Jd>$Xno#M4(Jh4KE z@{)I~PaV3q;n=drMLO~Y6Rj{jmi&<>lu`Hu?sV+5W^Lxle7<<85x=g&D)GFJl#(<= z(QU`|06CC|Z%U+x=h!)PD)?Y;w)T4lrp&DoQf>KTtL*_(9eq6W1G(99ifQng9N{I$ z@RxqITgP(VClDFp$=<{=tIKe8g^^3}cUiOx-~$;-S#Td|OeZk(bEe{V*MlVbrQdhe01ZorRo><%EJA^p*{@q+!*dNwYg=HH z+WYxP2SHy)i4cYW&c&#|c|XkT;Hj^R8Xy-^)$<`w(S%Xv++5|x&UVm@-b75TmMCrc^EPS2gF6C6&f+vHokQNk7_b3JXQ^_-NCweE-oQU`HSB@W zfU{l(-qfCUt;Lb^H)r;okRn>kiD8(H*`eWJcZ&fg5aXCWpetxNiq2p!2jWy|HhYq8 z><_3k6&YM^;97LTcPjEqP;BNzai8!Z&I6|y;>2msc;5(2SidcWQ%0Mgya@sCk?F(( zJWF$j+_)Bm9lNSuzRvh1Jd)0&k9=UA0Dk+ruqYWH`fejoOK}%NqBM&7ib~2-AK3eM zk-Uq0r<&C2-PzPe!C9UFnb->Vrr?vt7?NPrIf>yhVZE9VpGR8(ZBellP=66-I4>~M zfrBUBq26mPJRQEij2xE{_}zTWf{YKobfrsE3bd%*gl%*LQL0pI->r0E;3slSz`%m~ zJ2V4)G-(=+9|LtM@NGkQjF zzmN)c4qO1}-<8*dy1|sa=q;!oh)bj6z{!5e-EY2}=iS?Y(yO{j3>70wKvS-cn4^7z zmC+XbwlHuVbGY}myhQWrjIyHp9#OcT&U$1bApTRTxhYfZ(=^+46{Gc9U+cN}eX(N_ zbsHP{#Sx}1PnYWK60@v(gh`b2roOG}y}1t!g4~Ki%rc1c9uF{Z)<7*XgCv-U;{`+$ zXwu0x6BNS-+Uk2gta?BR@F|FaIgE^kWlwQy(kfo~D<;T{lHUd)di=nL9g`;TBbBAN zy9PN7QySm{)KYjVQ%jF4<}~T`v;XBuH3NOI-IQOKhz|lgv(CWTGM=C4(RZ19{0P1V z_LZ6^U~xF|wltgf$&Y+kpi~<=5dWxOYT$GByt_AayNqs|X|K<`$>5 zB-4Snttu)LCj9COt^J!q{AGcDjderFZgUA_GRo-Gt4udf{Kat4kw8Y^_DLC^W4oXa z{dHHfSE<>sq^z`|Hoss@DW~wdz?DB=G}gZEG_v}ZhY%l?TJS||FpmGYsTU`8_s4c_ z0UngCQU)d?M)s){aH@|}*MV1~%i_&2?|~s$pz=Oy8N)~tbYcdKtryfWkVTN$gE~n% z;FtfNB#Iq{Eo%iazu{MK`IJkR*_`RLVz;oVYmuponR!n95Q#V#$S*B!r{5S!&O~0+nKy;~h8P}y?Hd?L+^ow5 zm+(gXM1W}ZR4&1F1_V;Dxk)XWz})<=T!dV3%_)+`f;7rHXu~p|DqsJLHHPT=^-OoX zv7l)wKv%UnB| zrvxHnLFuP0D}nYlS& zQzU9mCQV@)SeVp?(J66YzeU^moJ)rf^KReSrO9U!Y&f!-iC4f}mQvn4D=`e`Ci7WS zqwe3@?ak*?^fQI`mpna_6z^whJUN*@wHsoF zK{xr2M_UD)E3x<>o~;GeG|e-Qh(d;KDjNrh{06i0u!kQ8D8S8$&yYKK%DTV@+2DoG zdReAGY0Vj`#J|s|vti?$?j2IH-da89v=iW>qVb(OC%W6&C)?gBB3j^C&j5}swdooZ z6FdF`CcS?q*xGaKtrEAG{z#9m0V*^0Azc;ufSk7?!56u%Pj%PRPSx!9?T<(;6>#OB zOpM=jesmg4akkzVIVa7(tbOn7p65K+*hugp*<>9CfngHU4o>U&>&U1TC zA&oLX$~e6J{!#+M1rIsga0KQBIfYk(&d>-_!0_YQ?nCf5sqZ)8?N4he08b4sCVYjE zfsh-`DP#Lwm&-rRPz{64MMj{0KiZRz&#J7Vv)Q`Vs-LKCr#RYTaa(-ImS7IerCecw zeADbXbW0XIm_9$41l0nE{_1!=f3QD6_T~AhAj0qt4!%)6b&^i^k@xMog2KW_qch}|5waU1AYVMMgEVhFMj-JFZ9pP+aLo1B1jWP2f<9E+e7^aMbrLp*l0)p-U5K1 zz}4z;IcGj%vthGPTE!kWwOZLLVbc7|UOAX5X%riOAZ+Y(yC9Iu+>^Tdv;c#egGJaS zo(#EkKP0*~X;=B;NKNq_!E)?nVt*5fa6~Mn$HqiH8db2Tn5R7AE5zzh<|f7$+O#6m z6a4CqVLvFC86HmqfKq=(DalgKGyNWFU1W$VeC86)pVL=}#k>y2q5|{dRO5z47e`SpGiU-qzD|tKJUY3Pv{| zRLAO+wAK>Isl&%8-+3kG1=PJ{hwWX6STC4*6sQvWt(2+KbYn3!PCvDBqA-AUA=Dwh zX|h#*;-fJjXz69O_PNJnfBu1Fh9KD4go)sxvq1ra6Jav0l{Y7oysVB3fvh-TPMQ%C zz%9ed71a*_6bgB72Jp+9*_*L18JIDF9qmGvLePc*Kw9_-5=wOgZ)2iLfZpo3vZL`` zZrXh;cYYe&h(DO)Evh)==c_y@m0ZEC<4y+t5$Rmn;5;Nf1!9%}+ofF+-+%04h;Bg8#u}L*P=p%_NUY9oZ?5c59{amm?elb7DLFa+Q0B>Z&xo?S zVEv~4ej{N+Q|<^OBU9b8uYAQ~g-beQg{rKH=rNM!#Zf34n<~Nnr~(YhsEg;xQi`P$BUc7>+o3 zr=5FXgLQf!RKqVedZ1PWhA4G;oOKv?Mx!cp)}6W~OAZ?T_1pHjzAUkEUT8blHNanI zf=`+)Y6{Q<(zR4C*;}H!(t!L(gp72Q)K%vMC@xaV9?D`Dy#)4J4*eB`BLYl;22cruX^ zv^vKPDWTEWLUBQh{+UR@89oe@oeyQTJbhF@_}1(>;>*R$%+Ja{>iR@3M_AXoDqn!T zowBe}hn`6pEBhXy1Cl7gg9$;kN#{ghc1GrepJaFJSt!CZmu zXbOhim)zzi12UIKeFMHt5R!uuN}wR+Q7&to+6rZ>6&^1riiBecE<0~;tgt^;PS^+f zEx~OV2u;m7u8DknCEfmLin>19E9p{Hx2WGj0#U)1dS5oHWup)*Ry9XAHOaI0IROE| zut3J{KJgQ`9RwaCxnVs8aI}$uHxqAQuIJAC`&+rOS_DCRm@#`i54MsSz2+2lx2MJ82P`RFDqxzFgNsIdGN6ZXgX|6GT-fX!GK2LK( zxR#ZFLwiAiBmenn$?N3Ho!)Y8p1xfHh6A^mMC;}&5~5D|exX(a0M-)pF>!1DHFULJ zpFp@4b5)E*8bys2O&ssXLzN(ocB`;JjnN+!mZ1%$0|z@YI7hc%B`HpyHBxm_gNP6Z zEsr^5$1^tgFk5rGx8YlnCPHNa%-63SnbL<^*C^x;eftFxcK)+!b*wvdY`ke-G^?$Z zL~q1rDm;|Lb+zdZ=oxni{d-svK;OwfqCN728A?}cRpG)PECAfvIM{GH%7X*HlcweD zAaKcANua=AndgH239Y$JoC|?qA~3Agh?gB(d;{Byvr(FRL~mRo&J;$*TY_rv%(L_u z7y|507A9vr`fD3e%-bI#SUrkPr|EP8EhQbKTAO{$w`uL95v`t7zGo-AYqADs`LZ0)7mI|WWX zVG)-RE<>y1+y+#&FhnnW7fR0Ys|Dkc2M5HAMZfx&YVNz;_g}oKU!*TU*o0+v4URbh;spZ zK!T_GOXDM`N0v=lrFcCp+%yCq)cdB7p;*D8Lx9HY>IVp)Va|HGXOX;dppETJFDpdG z-x*=Q^xO1saVRqUke%EpX88bJZxXt22){}7HCB{hfcXV@n4!b*tdXLz=pPBBqe(w& zSc%IUuLG(ZRYWcJtssr8XcG);+_2^)PdK+GcX6)BBBwr5SK5q6dW zqObwFfU_LABB3FYYd2Iq~Pz1hv zIR!Brciyv|cSwoQS9CqWxZ@xpINQNq86*5dfa#g9Nh9kH%2RTIJJ*-A&_NAY1VT_F z^s1n1XTfLmWBhjKrq9Ros`^fZ4Q5F@6-xG>DpLNw`X{9K-f=wEJ0`N{3;kgHhOab6 zz=UBt6&z=239w(pndowjOp%LlzCGYWP15W)=7DhUF}4Qia$$7AV2RMYqX8r^0y10F zw|{bCSv@WX{H+so?}-ZSqfIc%7LXX-;3!E(6Lrm}bCV%{bq(Rh#-H2>xQm3=1}^nb zD!Wwma}2Ga>b4)=$%I$BVuM1{t}%UAfQZPvX1Lyg9`B>odXB|PAvI@@YJyv8r6jM! z>>J4`WUuk*X1k4|xkHl_?ik2raB6{?zgezcb1CNCr;?PxK^q8?Bob4qN{YpeNh0&k zTF5`{e+6;Z>QB0R)LKv_+I5@O=GyYfo1PYyjfe z^AXRNs$Z=X-*f2J&UKJ5lJ25hZi9E9P3jmQ<~oyByM)s6|EE>NqzQ*#u5W7tf5|`gAHpvh-!UQGOv=k^oaPj54E+E0p(LW%9mMv zWhjFeGAT9c09)-nuYm8@E4$anNpcH7PQWi$ex_6~u=fpgK!OxPu#l%1;JBt5nqDho zIJJsEyR`F$%E%8M#Dw_x)xY?^mB>L@Z>UT}?uyBD>K zPtQ)1hFyQdI-}>t;_MNQYJNqpt3>H}ZRPZRzMHxsR*Ld2dAx#%{ENFq#*9M_%?NYb zVB#(Z7VNIWWF%}7B314N7+(nOeL>q)MJM^I1`-!dN?vo6Q|pl0tGg&Qbn$C`6iy?Z zhxU-}ul(BEb^H=4=dZO`G*iTF9zGM{AAL94J-OFE*+qqa!9A1n8^QRES z5+fKmAsz$-1LrSn9P&vhqm)u&2$0qI9Y|o|Q|KRe>9KhVtI?ym0DS``B9FhgbKJ%J z>WV?Sn|Ul%a*o2rszoZyD51!r;kxQYc0C*G5#ddh`&W0ApEq)Lfugppy9g60Oh^>$ z=U|fiDbh)lZwhME;)q(tK6QY=DkgjN_{JF$|#D{E1Vcmh*{K zDw4eFVRy9xg7=2KiTOcEFTzO871EV3J~TjN)mY$=62L6cZA{O|@9(|G2jTyUJT|rU zMWsZ3GAEOJabsvpY&qF0M0OmWhVKdp-M>YfF13Z-$ zg-4&M^>21+4@}%w@9N82eceZoKjj0W==2uh)R~(e|alCc9>hn49gBt<#_Tzrip=fAr18C9eBnqvni;#d31wkrI>hcZw_MQkcoxZNs$f{!{VR+xtIlKzKA5$yDbC=;beNf@ zuzXk&0hGed&NqhNzumjOH2w0OIazh;rCWhHuozi}B~BU{okf&@I~WKPDp<5riQV{% z#YzU@)hkD1HXG_4Z#KL5c73sIuF}+R8wPwG*Z7pHXNu4~(MCss%g`(1z}^BoQ-&CJ z=bqb0+Yk~#h#J2d=SK6WvVWqyf5@v{pNL^s06;2Iw5$Ne1INrlo;O3(R|~RPbU(%e zGX{p~uqX{j^ow>Yn!8al-S>TbMJ|iz{1Uv?fdYj?PIID(`1CIma@O@Yp@fd=Sd&}X z;)4K-DJ`}V00lbj^%Hr+r2738EQaGdZMG)!C*7*x6f{(1!6`E`AC;YG7%)YyL$|nm%S085~T--cpZqc%-eGpj5e|gr}BXVn^0q6k4le#kULx zZ?>om1biBcx2ep~0@oKyTC+^f(`G$OhUAME#V7&}2coY@iy}s4awv;Yum4d`v}lJ+ zq-YDZ3*spgWM?2D^eNgR$;~BId6iEg0bmr9Dr?Q)qS5Scy#qJj?Urg~gfZbjCqf0w z?cY|#5?-BOhu*CNYL!(f^AJLzVo1w}cogyULa)sLcGX+tRx=v{K2bx55rw zAs#$1w`7zdU=4Mlv4{#^EIzN@QHZ}YYTy8amqZ-}wF?dY(Q}K?A&N6

5iJJ4~%8 z3~;qyo)AfGDMfWrTKUbrzL5nQ#@4{4Hqm9RcgGKP(^XC#)g{OWXiJt#25^M&$@chm z|5yWl+Dd+q>C=%J8ak;}K)AqQn<{TpD~Uzlaaklg;Es2){j8!xdK9CX>!8kSr8kA$ zLC^w2m^ET*Ue~Q$irc_UO-?X5jv8nsm5SL2NM6>Ju*LpBMC!uk4uR_Qozb@v&nh{( z?|HHC3-SYgzCUR$@eSg70r|3UzwM6MR4W6fNF6Ge}xo=-Dukn0~ z2~M=YzOdrlu}t?H6~%Y6>1}7H?uv8Vvdz4|y`PRzw{q*WMW`VS|A8B>GYio&H)Kuk zIyIa{L5wQ+hdT592*rDVxE0$paT;}ZPI!hFBRpC%d)LN~>)A_60S@|W4#88RHVMoT zL#5p9L^rGRMjs8O{T=%_4fG|ufp6G(e|eeVy1uW8Gm}~QSV8mNNIQ~dbBm;WVPTX> zRR~#Dg9D->`bE82I!mLxN#Q7%L`JXks3y*)l&PK*te z{pt&693TFg0HK`+1&Hye_(1bX6rWptVRlwu;ptN(Y@NdQ2(=(EVIyO%I-oR*io&lrX=bT+?r3}`R3tqt9y4- z7KEWe{-fjHdiTymQD;M{RN6{kD}_>=Z4c!~#|;>~^hX>%0>mI1e0=;m&+hKxS0E)g z{eJEb414hnQ@8KiEIT}Xo~)f*$5uFKs3p)tt9T3Ek2KjeV;nW35fI7W;<~1SxFDfL zTI5WPCh3|%Ate)Fvo)llX^BL(~Qux@SQJLJ|Qt6Y>F3B zY690$HYk$_z(T-MjE{s`JQWYkJDOW@o~kSR9)I8}C3e}L#wQDe$LHRcCj?mg_?=i1TK3$lI6?uG#S}7(auu>(qj|8pVC|S?hJcW0>XDy#I$Gmzh z0x~|wag1m5(Fg?6jZCumM0*%F#pC4WMb|nWSFZ<_AiE+4OCdf`XBduIgMa7?wvQ+g z2>fq`0Rxs5iY_tn^u(}_`f4A6@N8S}-N?_@cU5C|qHYyk-vcv7D~jiPO-gE5Ritz=?5;s(u~QiR1JdUCOMZvEKFvtZ-DM*e+e40PJv&WPWDkWr zdGUm3{n+7Tj^+`Bv#jgyqs*08KZJ6@-crAp0l)511A2#cYPWGQc!GUuQwyd>y|kBy zOp*r;GDb@6q&G9=?ocyxqO(vMp#1LEsuON888G$+;JKtQlFjqy2VqeSa&vl`GDV2+ z@B{#N_u(2}VIx0bq}S>Y8c_PB#>SbmW>R9VU5K$Rb;&4hkG;+(neo-(P}*-HXj zfHH(IgywJr$Q^a2g3@>1IL}!_LtY_@$>F*Dxz*;)=Jf8+)1T(|=o?PAq1ZS2SV^c9 z?G%sn6Q)gOK?Mbd{5e5itKV3%-T&^Cw*j<21~(3%v|@K$ODm9^bAy66J7PsYK>ybV z&=;$MX#xWRI{fDVko;Huw?G2H08|?|DG8{OoR`yonU)7QZ4R@!#W+EihL|<-YQqy; z*&Y-B3i*D?MoCf z`&nv|6h!JP*$G6$zJIOc0sM1iDMB%(=W?vKb5lOk#nPL49>BH?Nf8c*Y08LPubYo& z&wtUjvp1Q#Vx?i)qWKuijWFo;e7%NkQ&ycpAZT!8W~MlciWaZQ^H9>X5jiIQt|RJE z!lAAmz+(|vrkJW+HO`Cz=wu>=Ye;c(os(8I&N9S35N=K7&0RG#0O&v8?3b+?xj@rL z5*H2sWW!!yC9gqSvGF{hDvZ)mb4dm1lERWV3ZP^$n0U*`gjdltyDDlgs4tQq_7Sk) zs^;MJ!j=Dh7@ZqlP5<-Njp4GiB(E;@BQQNxdIHT~IeqqtE%Z#cp95o$6nLZf1E3X@ z2y%Y@yY5w%*mCM+4B)hRxK^q$xMPyh3Gp&6}UccmpV2!0fn6*=_`j? zS1^dU3=&(&KdB_J4WL2(J8vF)j=y9wfAkgo*DrUOQSCPJ3aEpZtvQ1Ags(7HZ`O>v z!E&usKjC*Q#xL7T*m5BV>iUQ_fA#jR<>?KTiFe2%1xCa~TR`5lNwCgt&LX@rnuo+p z*dgW-U&D4tyJYxpL363D!N=mc;Lm+fFolOf{bjgt?>*^;t0$LL0%q{g873u@Y6)!_ zEkw34ZI>>hopo1W=u=~kE?dmBlG(b+&heI4JXJdOu07#qBn9u$LP#u zGbcY9u0k)fguJbTr=;6zl@p#JU35!pIx0>`BpUIe{(TAU>Vw=Y+R?H4vS?lA=eUqV znG9DkH;*cf1{h{!p@Oo>l>TonDzmn*3=SQJCt*CjP5`om3vX`hV#Z)HA3+Sg)GAGJ z3w(o`*3@&bq?0jf;+t zi;9WxEC6B)CR@ph-IA-FRsQTN|AufE1cn|8pJSBIMMJQ`&s3?_y#gb{w-&LwCq4LbWqk#O~T!^L`vkL^ai5a;qHeppI z-oJq#4&i|zw@%$SX!)-p31B8Rn6x2PFVrl@MPAPwep3c}Jbq@aVdN-#yK?>a^X6`o zVbRqc=FXbhW{dCl!&QgvQ~y!uMx*DvGvm{F+S}p(lvT^15Tx^f00E7Gr3EU1;G}7y zgTMh&b{y83kVbaCG_u#j2XV!~OUp%!5zYSf_)(w7htr59qGlT}t!7+B-0$3E3$@FO zWg1BO67IZQU%(pcSRW9r*yQSvWODv>p?JHSYE*D{fToVw7NH)eLLYZ3N{^wTERNmm zMmq;bxV(C}=g#>~mjjf%C`1p<40(u%IT-_dWPvnto=n2pYO5jR)u_3@Z#f|y5u|_2 zO zPu5$tTxBXUqMRL%4cl^#nA)imXSi$5ck$Kb#aIa&THAKoSWP7hnZ#J=aIkdu78C`H zz{NXv(T5%ynS-PVtsLBuX{{+3Z5mt^9RI7>ojSH0S{+U3);&APrw@ zTDBXS|5bso3O;!nbS`>M%}Nxm3{aUyv^JR4{o?8m9W66X8G6O1xRZN8~@ zkGJ3u@&CS^B0|6?lfXbg+y6FViU0d{8t$XQ1MF1f95$HXx;``8WYUFL@~s)(@|54#%JT__&FwuCGh&)eDMdybt_mFRG^Ors%GyF z7H}D<%l$Uj7crXzKsuem4GNr-C1PU@dW2eaTa8!}t%6*%nuWkh$AL3SR`xZ*z3bzC z#SIRCCMHlqRBKjORLZDms?;4+$sukARru@7MAAu8(y?%@2)l*;WW_9PirB+#{5u%* zAgct+5VmL3Brdkg4eGDMYa_pfu4JP+Goao5)jl}HCRzT1AlKy}Gv{yPLSj{Vm-7v! zB?+r{AXdT!?yjuCV9j#vR{x34dB(R}?=a3E{*PrXKtLQ;y5%w0MPTbvtiG^(-{E7x zWhvq)4yq#f^Jw}Wu^;hZs$t{23YzC9LJn)VcOXV?>U({gS>xj7g;ds-HqmWYpSAGr z(GxA}-AK&QcQ-bsW1=DgquNqy7Mbc|QcLfm%R;g67F$*&U>Kb+Vp-vJ#i z(g(-W2yd6c3ip~L%9RP*Ji=+K)(6t>|2gy${MUCMa3G-Ff3hv!e-FK89~BBv_5W=@ zJ1MGb_S>>MX;)6ABG_cQ57k#n>Y)A7fNJz@UX?7CR(AU`>+wUR9&>PFhRga_6Yuu2 zdDphmHivGu*69?xM@Oo)w9bX1QZX^?v@C!KvE_BG&c5+I=J;bn9g}2j1R2~0S!tGI zuFTCLonm!hYNcW+QV8I@{rJ$hX^1vpWb~h~-_|$i>GTK2eE=P?0PUyDzb5%q;{6LO zSjZ`-$1;aZ{iT&X_W(IU8Qf<$?4q6GoM~aOsu^LvjD0#H1?zQq_ZqVwGOVy{Nl5g_ z+!=3=l})t~qzEZOKN`_kU{jU8+c+PGbD;-YXvKC4*JxXUIRmJ!HfGFLoRMlP#M?J&5lRW5NYZP>Db*-@-UV@Wlwl|hHyH6d;JZL;?WK3IsrD+uiR z`T&14BQSwJgya1pm;-@W<~^hp2p{r><=m1@Z#t4;#t?9lN}XAZSk%|zDG9GLvl}+X zHvwx@&r@b=CP;<=JScUd-<3J*=bNWoU7^jz{kz0f535})EuzFtk!lcg+WSU&dVT-#ZK_|o*rteV z9y2DOYZd@{AM~(c`v>*X+y2#s6n>^&+IQZwx;RNq#q70a%D({$r)>Wgoo7V#qCVM+ zJmyHixjQx34h43P8#Zhgt9n7Adg-EZhZzPO8=?&yP&IZ@+q-o_z|zESEUYpenkGWS z5bE4bVljW*pYK$r7H(>YtLtZtCf$sLprMU64GBQMb#cvCoZIui=;k0eK>D>2g;BWe zO1MKGGN5PvBK&wY47l*KAw?>BRBlg_#^P_ZS^V}32b;Olr);`F%fpMO9HB&B#Vp|Wda5L&5-P@$t-hVSDt0$h;|~MubHC^L`Fij&mS@FvpLQN!IOi@+zG0Vq&PbsNbSH64x5 zKt)OGzk;Li+%fE;q`h4oi}i+~an^rY8dqe!qZWx*9oNO->d53EbRB0hXouS$&kq>fyCn4bh(98HSJZpiiF-V`d%9Z%NKrJ@i-l-p0!T; z7COid+d5u={fT%xDe@WV;*tsjCMJOR7(j*(WR`U|QdkK80lhRqj6V1y*TKQHkPlEk ze5M~?gZnDU8~&cn8=Uc^sdMOT^?rK{Qv6B28He*2+@)Q+?_MdZ;jdOAaVEtB4WEUqBKWIQYof%!)R*7L zBB@!7_1Oom>$!rNXr@`mwFBrmI~E{9`|^>H=U#Q@j}MY*P-=?A zs;yfz+m#|%pzK8BR0fJ#Qq%?d*G&hnbW{ozRTMC4LP+6g$G=H;YCIEf-c{{we4GvZ zciONw60C*mkr~c*QQ7tmRLh(-^1sX0%KI>V8CJoVR@Kk%X7tDq@g=g%?@Z{)CO zA#F{gjPp^wc;j#54D+n=)%I}4SHDQ>Oj-wlu8)-5?3~=sM19}%scDOv#N?&k=MrmA7gMVF%PpC?umC)nM^)x#$@6StGs2aDAf>v{iqf()7+smlYhpeeq~WXst$ zP{P3r*0tJjUPLPHz$GAzCX+ss=-17iS5%oiuFWQXL+QEA1w#8)O05`vn_uFXdpaJo zJYJAaN{ipF3qb3{4aQAlZ8FuqA!k~ z+IPr!bGqH^>+55_tfZ1TMir)`DM>@Pm-bP!9=iqQQ!!1t8s}iy;0ekN)`Shk9`0`r zT|<|!F-e_0bgT;gVK{=ZiJ(bQSXhm`n(~1K3gFE6a~k528J4Om85)Hnw*Y z49qzQVXhy<`g)g^)RNR3$?svMQU!gkyu-t|TUjwBQr~m}AFg*eM)0po7g><@NM8n94lO+qKL`N> z{V2H82PmSD#PVH=b}P4`!^%OcUKFcZi_wQ-N-cKlLxrll%Ft_RC-{9XbFY(I+9l}j zA2q9DP4p@|gO?Rn{W!%>#=SjycHB6y_19=?t(5(dUo1}OX#HZk)`Qan+mA;pE}-ls zpP!hx^CM4%?^%)Dp9>EX6-c3DNyU1cd)_;`aXyb^BAPkxA15xp0 zsFJ@+4%1!5m1FdWNLrgZ58$Ij<_>Ow74d`l@Ric?16(}`b|XG!b1Dt@gPJ#LYdl2r zcZ69I-ZptMxq41*>Rw3d35ALHYt$ z0e$0h*c!$hC&C?dA9mIqR@|nX%7C3i{AGnphx&*!oMx;Jtk}QIiS7Q9d@-p~7QQ(N zl5?McVsb95aj;o3Y;WvuhfJ-{Ir(XFuNAuBOq!<zUv6Ny8m9bRR6#li>6TVJXpRAHfZhqk zGDMWuXb|in53;e&N1t3U3O-JnDq`7;CqeXSqF+RRZ^LUuZU(o(r;|4NHTKBRUpD#n z0*gao8BW>+l~63Phe)I$foXs&HgDm&xV@j>BKI5AJ1x ziqe(xDQM-pp0C$F?C~%+&=o-I=qls_=SuEiZFtCC+oQMXCYGwVHC0(4Beqq!(@t_F z_MDTAVIyo-%Kc!Q+zp6)iIgOX7i^gWOExB}ci< z?H3uT;?Q^Dnk=uM01IFM-;+sdI7(V>RLwkYBGS?Z*$lHLah@7Xsb!(XaXX!omuy$c zMw#V7y7!E);yXD6Dk+@BmIp8$3H zJ^VQ!Y@}pl{wF|x9=S@PP@qg12hmZCKZxAsh^@K9cuy2!44r<4DVybGTNvWHiZ`bJ z!K^rHF%^dGj;+eMtSL<`vuPqDrLBU7vxaR(Bm*7`2(P?;(|+jE zQ~8ZRgbh&45>N`No>0y?z`xh(Lg^l9L$%Nov8KNUc^1-yUhAH;zFi8gqwg#x8@v+{iPyw-}fzmj>YcXk@1#UE* zjYQjCCXlXSFNvJ*j~XA`fQ!Y588+hlU5}t6t#bd*pW`NXAkj!Vu?8hM0j=Q-khqv# zmTN)rB8Guv%^)ktA99vPP;sPub$NA*R`9`lj)9Xz>CWek(O}brVcV-?uVyd0#q&@v znFYid!poC^c8t2JOa(j!J%A`_r50i>*Migb*(!==kw~CwuP^_FHS3(?_ zbxs?I)R;%ccd(D+d!z>-NXQWWKd#OxI+r$Dv$1X4wr$(CZGX{@ZQJ&a^T$qhY}>Xv zr_WV)-PcWx@mAFu&wA$6?1l-MF<>GmR2f58j^0r#*e_fzk8(ld1%FZJb>`5b!7~M( zejym{1KmL>6ATVbTka6nfMgJorvb3E>_Y>Yx>}PCz4sQktp>T+g7~M~@cX~eor2Pj zpj#kL2`ef>JCd=oaHFhy1peHY>V~W{vx)yr;b8->u-*ZwC=?{`?@wQW%wBe(jhl`8q3+qt~1;Fl8MemC;8@}YXpNBtp-{+g}so@MG zL!H0}+O?$4n#S=5hwmdxdoOeDKDr}JsTN_S0sjvcyC$Cu^|{5wP!a%);qqVz(ZrQp z%gi|uNAn0VJa7DNEZNpDPwSGqv~QP-o7vD;cv!4(Oi|^t7o0a@xD#+J(ae{Frc7)-)qGr?~dK%U`j)ipsPoU&le7>?~#-oI~tM zxKSho_rOq*{SUF-WUl~jUa@ikIMkCn(j1V(gW#ud>8i~v zDZ~+`i^XUgq?rMw97P%0yWrqkPwdSSu z9-SoD4f3fqlqp=locU7pZ&t?YbhyHis6(gsHQpr!a`)=3CHc8ti6}7))DO^>dEY( zL`3eN#k0t#_x;g?JkrA`8u6fEezDre(C~2;W z*3Tu(NY+nZ*sO!LN_CY(%0Pwi4#vzN+5)4mSo+F*-r8RjDJ%h^dzGm-4j4T zR^46*Sd+L(-WJavff!8SNlEQP4l2X zx>Lgr?0>wtZZD)}Df-r$4Jm4=I^zltBHwe-l(D6Vs&07S0q(>A+NkllcyoRyeLh!^YZ-o zpq;ofUd|(1ek`q$=55?t@~o;c1=y!s<5gOT)EU-{j8b2cTN&;iM@b#MFsqZ$ZqzG# zb1A9QJhLmUi>An~wn3kbwpFj6mnnsHbEL7+s|Tu)OOwY)hubZ|kLs^zS5fDWf7EbyH1WOdqk(Bv)C<;KWgU>>p(}qlz>!I5P1U zNgDi{IDFh`r${R4sB+|xZY`Q+dm+(`Cm;Ygzura<9xzg5l~DtY?>wDDEXt*OD^nCu zzDRHuvXde|H^AzG!7ZJ30aPG2zr+SFJV|x33F-s<*j@$nFf}7f6|x+&d?dRXs9E=U zWoz4OP^NSVBtO5NuL~a+gt9(ORTmkszJ~NmQ?z=g4(Q|rrjug-7AZzO@ywi9nro+^ zy62&um}$pQd|E+4afCsVt`453$mgLZT7P=0NN8GXbG88Pt0Sva0PA7dULM$t$u_}T zN)lci%J$V%j78=eatC$;|LSDjvM9AhergWxlimZ_DSZ!!bN>5O=b~M1;q_|?-~!w| z9wB0)+W93xNvmNht1sxGu1mk+jmb4!c!4vdFUd6%yl7WMaKh=;0&I0I z0^({SJl6$_bPFv#&o!N#v=gHnqj&uz7A$;E9jjHg06_&0*yR-pKE31wG^z z*r{x;(NES{pRa+sa_u%8YAyjacVvvRLQSCIR=<%r>SRbZV^c2n*0FDTr3eNZd7*Z8 zYmPj&=C+9x1r)b;4*A;TiY&QpGeo)Iue1OM7*|+}M@-ZeFJT2rz*kl0Na(xx+670X zY8hzemhqVYQpoS{a1(_q=Vy&5u^=-i(i}rKHtalXMbEUa=)IY*P^2z z(is{4eePdXYcd-4ar>@&e-Gx*&gA`_M@*$PMvc%`S9P3$G+_C?xRNJ+@Tq(xmk)3%n!9=?3J*G=y z@zj*}#fEr2Io2f&N^+z9mcI4Cnp|hitmpgop$FPV2%> ziYX;LmP9q+;8k>fT#9AWELgzp91yYkuIT06k&y!Q43OvMd0SNLPv=YWJtRRd+OKP% znDTT>xwnsFZjx-+uLyiE$KxWcy!3%+Sh!PwVF4Ji-T0+F&2#ZY%1;*npszxt1!3jR zTtuJNJ$L>yODFgDQGV{rOUbual7oL&BwI6@-r@46r(^OVT8))liNG*HuSseCc+f2S zP>JTW>uRSu%RDDfjYU)!@M7kHTjvW{SSjdPSg^;^rUd|NPa5kn)Nk|q33@p1Kbryi zA&Mj5QrO~)oLocbUAS;#c{9k#He6Z(^(x^tInPV{T6<>kNGxv*QjyOZVZrxHtW&LYZfBwOF?( zJ{R#XBUJa@X?Vg@b8jrP1_Vc9?BoCfo^SU=n^sL#1fw5SSp>fZ2g6Mbpy%>|>0iZk z*OftrsunDneqIcGjG*Cw z0||6(rQsMa8b1Y}3TJaf=`xM{8v(hJy44K1>og^ySEH?(M6aZ(DWnCIXMCB0pdHeo3y|x-8 zV!?~rO{F^D=UmpHAV(k8B^|-@86c{`khjrmbt;wTA$a-ZnNO>%cj2fc({%J1_lEg= z@2fbEq~9mIM*~6)FQY$iU6c06vEnBIl0@(0RdqYu(EcY&e-<7v%_**4+G6C< z@ozR!pXuC!tPkXYC{Kfa+Y}T6MM{@%YK3fX@vPG4FbXbglIfTX=$HgSx|5}RN6o!S z!No`66~eSF%gTb)DvcOvb1|5xYD8Y+<}|*th_F#uThmBmDxwpG-s*?10ktk^x;^}f z3Qrl;@7G9Bw&Ch`zl{zE#ZyjHcd++CW@$+%C!GgRFBTS7w{AV9duVo(?o>0@G_EZa zQEMzfr|=rDVUQY{H!;D(s9h9G%QL`LMjHA>*%@y_|GXd@tIUpAbhu`1H7K;iVfVVZ`cCtl*rw2T3e8Py?32 zMr3IQk(v%iw`&05RL}e7Zr}S$8=U;0;K2&H*r}+Gk0+<%#C!DfcjzLNLlfhA;6K+Q z*wj2iR<~=Ns;ZRozuF@Y2bg7cHH|@1TjZAts_r|eS)y4EgpwW)$}Q6H!v)(tw2O*gB?@Tw=7hJgs~!W zWDiq8+(rcc&C1V|u8By*?ouzK_o}%0@9`%7uFTF1D%uq+=hyG2Xm{ZxP=g=hgW4Kx z7HrgC)z;&QYe;eY7H67$(`mom_mZ~D9xsD|QwR*WY;0uCi{dm>NJFo-Z{$&J*Strm z;@50=9(SXzLWA24T1qa|SJaTvo6!*Fes5B^pnE&t`tf`F{=PV*F?auX`0R&<2Ft_0 ze424^^z93dAvI?0QSM)%G#t74KB<0r>HD_%d=h812h|D$-67&5#LYeWg8=Fm;@%WH zx1$B{1<{FsJKOXKD&)YA-79D0=yBJx6VZAmi)|g}vN<2#1FTzt8b~y&CmX_`a1p(d zbIV8Hp8amKIp+68_WFNZuB~01?thjyFR#2a%Qtaz&q9NYi#>bmjiOw|dRv5R`$%6f zgNIj!;pNEX_V{7E)1dGzlT1k=sTOzb!pQ;nu7dQ(r~S@&OPAB1$Ki`drXTTq6IZ*s z;GjldyqDM?yj9JM?jNQie1Ppo^>@F(Ki7SKql}>`IC1|o0iX(I=~`e# zoo}oxjmp7b89LXtQK)Y*eBS-7VRK7Ko0CU8q>Gytr2SPoshvnq);(XFe>&#;A}@eY zKTU>&qJK?6yA$I~y&6o9PwgTmmuQVA3rx_ID2A1q?__9cP})f9toG=T{L#o98MR~E z&CB04TJ__i8!6)?Ut*JvAtVh6;y+N+c-ay-razkOB1?mptLAQJ>{ga7I-_-k@tE?^ z5pTI&6_b#JF#&Imw7jKoqoU!NBIP>h=4keEf zGHk6hY>9iRg|oro862d|Z42Vn=|iMEzmg74xG#ZFPxQuvq$Tr^!IRSUTdPEE64ZoF zeSlH8+q$nXPhL3ss>w;8IqL5y9j{Ca?ml~8S%xx zvB>-!@G=ybgaNj{S+ya^+6m9CE!A1^=!#@@Sfcg`1hhG9S+yj5t0t9e^#)r-Jm3 zm9XF-f{28{G_O_|a5DYIIYbo6#=u6I1MEP%tW{ z%f%61(_Wg1xs1amLhRe<5Zsi0X@inx6nOp6Q~@28^1%|t1}u*R$3QK$vWQGIk0&3o z?6+hC@8oyMd&v~uU2*Sz3B`(>dqu>N&Q4tpf&ChLKo|6pfdPWfrq@&5FkYq-T%{(y zj;CDzeySN3rYqCIJapsP^3A9D8Yi{3oXIu}{vBX%ZAW`*Y!ps1>>^MSMvG3H%ys_Q z_sFIzh6NLmeY4nrFm`Pzfs(Y_JgtT!(*JJp13fU?LcAx0U*ZcSu?;MYv!<|GU&9~Z z^r{(JG|S+pO#%o7jGnBf+VwaZ64*}4*M|q`RwejC?W@`Hn>;NL4UZmQ6=h5(8wtYk zbF`nA^(kmCDvreks<=@?yG<5`N|XA&5lZQT+Fn}q8d|d@H5Kahou3=M*pQ^`GgvM& z5wBp{x|H*l_9cAI{r}thuh)(j>;b=PJ!Y-A9C4bj7ay?8#Nm04n7e~HX&PPJXE6vm z)|ER52j7T$!3*>hVU1m4KM~)3WILTmU%bKaH{QFTY@BYyn9rU?a7p!EklWwQzquo5 z5RQkmQ%tuyvvYi>E(SnpO=&mcg*13kG}PgxM()n&y)n#k#bnHw!Gp+{jB9!(?DeSQ zwq{`q3IP1^nbuSBVU%l_IPF`8>RLi;P_|!L@c8o=T7en=Zn(;1{Pe#%Qs}`M{76I_ zWrOkr11GIkHLsAxB;`Nd`PklR<~pab-h2csiPM`l+*`-u5cbAFy*;~1*V(KJiQ`{( zPS>wibhr2WN-F=|K&(ODXF|9ns{shnAbT(@7nlJ^<9X=AmOw{mfkr zkonA9&l^sZW-`2H0w+q!f3o2t^^A;g24z@b#Tp2;{l`=`8K9&;-9?Tsa`UeAF~ts5+>|ULLOaui|?l{rjqNcxa6p)eRFBB zxOQCU(sfBSt9Ux5DZ(wdn$O9QGEK)&;u-(~m=mQcdz99Ncga|6A@edpo^Q?QQ#ZW#M+JiOoRSdxar1mImvoy-y!{bq7hW_T2)C|ky1D;2+)iO*Cgr6 z(geD;pCP=VMJUqiWJf%|rHM*Yd%M#Elq3wzaX&lk^aYk_d_f7{+?w)8g*b{aP8pYg zr@Ky2?u2To$tEif)I->Wp5#RNeoBDcM-F-=f#3S5vs>E!z-BNWo(f$%^;itu0!(Cr zJ4u8PlYaK6nx!4P?l51JRp zghH(ON0+cZ-9u%EFV=U8LtaoR7KEg5w5`wc=&kD;3;61?L@BjM* z9P9cv5xfflvCTh%{L&sq7497833*Xgf@cJHT=#^$8kRc})^uo{V@sm69<6?%prEfE3N+FQy*Chwtw0JnjjI`gG93jHW@B z3#K#)c%ZI;(6KuBFbbjFi^v(G6(!vq{+PIK_mlSz?ng8BDuwGW)qlrN$x0siM$gR8 z*R{^g9`kGm2J}A6l`aE@{p3Cn&rBf1&R_FOqOkR9;_bfEtM-53JGBfC|3iV#O=Sek z!5B&6ZhpC<1*hQ@--qVeYTBMqeS>!iOSQjyVJdyA_Y+IyUx%qO%Kj(9w54BK%DALI zO5SZDsO)c>T`f_>hdc53%Gi@->IC*lUAuLwaaW0L| z%_V8nX70!RB-#a&4xz_e&2mV)yZL<%pLn*mj0q6)+FHUjCiA#PAEh!(ZIU^A{^xaW z(0GX@#SnUK!4C#7uFhA?^|? zmxIUU?Rswb;N(d^4H1swsO>H3?+&O>3OTOkl0ESoHU0p+i;=*Q{jJf(Ta$R&*G@?~KRxDxL4J9yhj<07UBMu>zwhoi{4v;kdtoW88g0UQQmzkPo4w62`+xfrczjK53MoX`G4Xt=@ycguw!^} zO2)<6ynS0JPZv6mN!RjvbhRX3jpC!ss5wTLyX}BprKZE@jq`|FyhR&7{Alc9+4ZaQ zl7}0L(el9~B=Hz|S=0r>jmWKBAO5s!bX#WBY|a@#g|gssj>IIsyaw zIm$n7t38V?M-Fk(Tfh!K*>I@K(X8!#cWT!-yq#_Z5cBA7(WyOzX0*g>lx>b5R9MI! zh)#fT9Nb@z7olv(5L+rY1p$D12$RR*e9p$z8X%jgm=idB}Su0JQdm_2Cwk_^D z+2GpKCz^|Mc?o5zey(asLQo|iz%A&gpxrAqA9nF-*yXB3}=)Gm~NZ#^h7;QtT*1ZS#Du5P}la`!d` zd@aP!OgCw#w0d-?;pCo+a^*}fNvPcmrimRk_)o0K3=@J=57k0?!rM$H0w#f0j`#V+X&4SgjQU*YmV6A=Mzt zAfuKLn0;0fsvbqtzL^_;3A7>;XUjbeYk%YDxNa_9sV~Yg9o$XX7Z;VbFM z2r8GGCRK}Y*MbjiFb+tSf(kjN#B$PzMEY9Ct{gtqV*n5mpzzAUmJ~<{!KM;AMMC{y zR4}eK8>S?otnmT@2C!RLik@vziD@>TPV9uYR!=c#8q`;nEy3>b$ zan`mkZsmSd_2ydbbb)+-E@c9rpMUi-QJ_MCyV^yY;7w!30TwsEOSq00^d;mxVyN%~K-ppR-Iqr`A zVC={r?Yd%Hn=eydHvqLa8D}$Q%-4#1QtL9a^+T=f>c&V9(Cd2SD^4yc76IrScq`D| z7(7r)QslP1u7{aG1cCC6&_jVEBnWs~Mqj)+|5f$Mc10eqs+J!OXO}bX^zLz52do=Y z>?EvA(f-J-P60}P6ax>a8L;72?|?8^tQc?IZ5w>cDVrJ15yrg}tH4ms&T5H8BDX~x z+}U1n`GDzh^{ORqSoJ^WcEm-+k+FPVNy>AR#)AsM)!5Crbifa`m7&7=tH0CkswucY z_wpMS#r?V=u1coj_81VoE}p}d)hPLWM#A7aRAz~bLjaBM^Ngz#D88rdX9HH?1eD~- zHhCy7mR~WLj+jMH`b`GiRFxW5qK%@(7ZB;wUkmV}pSX5wI>a!n5W4#wDiiZ`b|(`x z&HD@=J7EPuYdY(>DY~(2#K{`fM)~dw-!pD|3W)QG;{m$lGlX(gx^8)AElPtC zR3|?;dV_`0o#>32IbxEJ($8}%k{ATv?-p#TnE3Bv38UfiGRGk62`K!UyFRzXt4=yp ztCsLGLlJ2e84S(~>%HWT@kkbT z767(RLg-`yhP&(MDPlaAGmKQwT2)g-VL*C8)~TU;&{P{(8~Cqeksh9em9Xb82LrqD zma))vg~FXDWzDJfE}<${^vFhlRi*sDzur-8-3jADOVQiF%~-}J%t?&03UIa~QH+|0 zhh0D+ktt&bbNR4@r&!>G^7}LfMgCr{{y{!x(`b8atXUk^948O9AJUGLe}kny6adS9 zlfNnY)$_9jwsBn^GTaPW`sCQvRRrOL*MXjKn6<{)x=g1VShI%hfQcyxDa38)BzX5g ze9bPASF<&v?Cl{*lh8R8Ocj}~99VmC(;Zt(8Z<~~P>zo!mhSqMHj{^w8`jNkd4CLo zt1~*f^JN77gX-!5xP3Noom1fIH-I?gVo9Z=A{sutyQA!68z^+nYL*}C5B>(dnu{RP$n`XY+LAS4JOHF5F9`BQ z_OoZT$X8+u|M;v5A?R8DED}2=RN&a0acx!9w4)Ia~EoFC{qQ|%2e)aFVe*GD#o1nGR-w0s1Vq-A>#uV&j8rI~Fr`cmq7&$FcnMR)TVEm1?Fv$Fn+>Rm3nOz~PK>$}gm9 zIT#o1=}Pzu;5)qM{=DHs0>*3A0a!}3q4#k5c9r`P z&_2j`M01k|5?R~Kxa2zvB(lJ0+8Eq1f}U=fRpc!fbitb?Z%K5k@%;I67Lu$|iE~VP z=8hU8cgH0>aYwHanZ&^KW4|{WGswhn&m}jj84EAA){u)Q2pb*UBYY&)=?OU*HT>*H zan24N>d;aYlz1>10rb_IwZ(n@`WX70KzKI^9F2G91h2WMfK9^+%`=1|K33At&YX-z z4pj;^QBN)(u&KhIjv!l&CLVNPzbNg9q)U}eh2biNTUuvJ+kU9COgqnFl>99zQL_x8 zec~(1yYl3KH5BD~Cs6`1!%Y428>1`e@qbH6!sOPX10qR{&1WE|!RJcs62OC5g&{KtqGyMa zu=+X^>yrO*0GyQ1W{x1eJrfsewdV{$U&2}#j#g5x8wReZ({G%@l1XaCL}5S1X)^UE z^bPf=<>=r3V*HH_8}nDbP;q~p!1Ffv3&u9=bFRFU*5sy@>`1o}Lt;!C2i=~>Ua?V= z9QXii^AWJ7dGR?ITj3ZTukQDq z|AUB%3Oqa8iQN9F+*SKSl_Cyt?09v0BY^|b!JQMs;xh|=^_D4X&IRZ{jd@S_fZ?Cq ziaj>f1YFo?h|g#YDW-z|D}4>bsnA3{O2f`Lt!l!*pN|hNg|N3Cn z6NE(#2J?g7|1Ih?Qe4bHxA4}egE0^rLYO@=}vJ!dO%y@5-0nf*#| z|Ak%RXAk4u9eC2UC*EH9C*A=6>{;^kzGNm!o9M?aElyuU;4?Kk^H?(ot@8n25zdMn zJ`}&;bZOB%PB8^SAW_$8fHC4d@ijC4ql2^9(GJ_{Y}M74j!&8>iByQ*{@1Rcah3Gd z1*o#`1Z9Jnw~n$s`hKKlL4KO`v!Yr6Q;w9mj%bp`lXX9GEFgJxAd+tR5AWw>3?x(7 z2!+vwATILW`3Ntw%2Y1#-6kAQJq^3A%)%@`NDA>XSrY%nvkV9y1Ij> zWGrd;rfi6Qkqf&(qFYR8raTfXc|`V?Nn1=ic*@z48%VIm8!XHyO5?>TiaW)&HJ))p(EC@n^=GhFu1~k^ zBFJUm^mQ2Hw@}V4DS@7cbxl-T9<7w!&Af0JafF6UWH3qYnacvP(JlYqD1h;uc+xp> zcv41m_a6FPgjXA8m_?G`TX&>!itoZVq7@G(&VSte_FJE9FJq5mkDT0+KC&TbP=U=H zN?b7ship7W1V_MmOae&{)3x^t(v`gE=j=lcSa8&_quAQ^r#tC;J$HCI{7{vobMa4T z2#dc2MbgsOm&9uM^9e{QK0qpoM6)bPca3OeRJuN4EcLUd97fb|#zY|L#II_-dgTMB z|10w4bYQ{q(V8=fdq?YG*aTQJ%pC2{OKd;|>|P^+YxP`=akK%9FUY z)k5B!F$#*GM8KE4m(x9UWobT{cH74L4e?!bt;doV;H_R>4#TcLY)5|Dc082Ov$BG z;OScb5zyN)`25`aemZJFwOfhmMwjLw@s6X$Yg|Wn%$z8d)}dC$l98c#3g(B7E*-h2 zL$&_f571m%^uhj|c_~8i+;V|bV&DPz_-7R37s3w+|EHgczw^WRpUyx5;Gfq{AhXD(!)7y69BdxwzAK$9ivwI2 z=Gr^H`SCW$a-ohtMr7^^v(zw-IWesD0T-KAyAiY`4mIvH$~$inRRk*rPW8#ad*X4af+DfgIY5-c*wQA{lPRk38 zs|jb$VNk*58~O=76^D~CJ`dt9DPq3q_WeY*7Jc)Fah7II?}zO9+D4$wXNbXYLXKkI z!q=h-r87tZtW^U_FAIDyM64m#sFFqjK(}!>K!S?e38rma)szB0kr+)$x{}EzhoPG{ z&W0nM7I;)Mn7^kxXH+j%+p3O8rlAu(Ffue$ALu-%?7nCabLTx&xANqn=blui9mbet=VYEJp$begCGbWptl() zv{*9#QP@FT97gX)EbJ~2+5NWT?N;qk3riUxF8^QU4K#UzT$$Y;p3U7l7LdCzskBDQ zCDl<*5cY{^w|3D6u78ERr7Bn>cPw)t2rq%oR=|dB{ofWd^gK$^Q0Bb!$}*vnP3zBc zn4*vq3KQxM8?nW>dU|^%^J#>#fRa-8e|L#*Ael3}KjP?)4WYAenVCw?Mki}_kKMB@ zEf!?>1@Wt^!^~U{6DYiMww+L;SGK)awC9*yYTi%RwFIwk7N0`fUAs5Iry%JX-rA53 z&RWs3Eyu6gm(%ycnkJVXj0PahAdo53EN~dWbot<5qu9u6aoO9qP3xl>0B{jGA9w-@ zdACxv<83hEU8#YFEeWpYAhb%;T%IbCit6Hfp(8C#vvVtuRmDy;Q}l^57#P z&nf?sR-&`4l(j6%w!Fai^=#!j0!HFV*iX^^Y??JCy9JO{#?{pS0w;=>9ba}X;+%#+ z#J59bAEf0NTlCZy&Goc+0Et=rd>y?#0It4{j&9ye)WH}P*I@hH ze`Psznbzh9au@?%I5yGpH;?$;r`(>^m#I}zk9McK=#tLt<6&DE9q#5pnPu0yRSqSC zErb?*;+$?0b&j}wmaR@kwr-jRM7fI_oA~nS><|uS47HQbI?+3{0A(`YvSs!)Y>?0* z3Ih;XUgA8`<1j&xKwzIlXJY(+X3CaGK7lZi4h^a68hoh3X>;SH4oX8`lwn^!0B_7b zUdh~1%oR^Ka!`32ea@dO;T)bNKHx*SB69I;ss+$#t0_n;iqRjYz&r~A+x2~`X(n~| z7$0sDF$6?~L|I`jfQm-;xoa|Ko{yDdq&t(DXUI_#u&5hWHR9B=rOGK*EDP5W*`M`4 z;WFGNm>`nTc>l_@j6$iv+#UY-gF;#y>25A*@O z9}{0OzQaUMc_#)X1Ro(|`i!8p4f&*t3nvr*khrI|<1UKwnPx%J=nH3G9wN4&E_4C` z-IVqv07+1+j--D3)e;>(szw8X^R8t*CDJIAG1P)nGqz>+_GP7YEu3fKB95?A_%X<-H1X zXm>K^q&lS;ELne%#mJX=^#Ul!&E6zuo7#MCMX@%NSPrQTFcg&8OqbEE4`DDH3~SA921_R=>v5&K$XkTa5!gi(QA_e92QT z3u(mZJz_ba#RCG+N|mlv(8yxr{7D=Ne?pU|XiMUy$yIW3*@Qp4d~Ct*-crh{z!P=D z0XLO73$l2fD~_B38)tL9F#jk$Mp~jUsnk*z3Go6)#JUgVl`%@F>04=^D6xO)6vd@G zg4hTeWrEYHTiSJF%m4cSu0 zMK=rmVG=-uvmRs0>Jr;E(Zu_iP|R5qrBX{a-)|hHBQeO=gk})i$Y&7Jo4W=@#$k|E z*vgb+kcO&tXhKet)67k=tn-U2d<`e2!=hsWi@x~iX+i2K>Fs4QtVi4q*pr&q@{7SX z2BuA>BDV zppy7NCsVIV=VABbJMI;C>6el+3tygr%L}5?*&WTD@h3sfmHe@HZ;4E5hpQNHn8Ukzf^yW?LkvLJw8p~qSYZNJiQZaT_#dw>;mvhUG=?)c_i`xqv zj-J(Hy9NN>_pv)q2_qmn0cWVGAg;?~V3&A>p8kn;%mrFbBr9PF89qbTW`Z54LI}38 zn0%J-llzik!PMa_PMghft|9@3qaT!<*asdm@MFPMPPFnf8i-u41Lqo6qMov2XjN{J5 z&}UEgL)rxIz;aw%WsWE4J4-ix06%Q?;IrN9gH?WkifbYQ6~^;kPJd@mEFlUzOH~y0 z7M}I`&gnnBXiwA&+a#yyKOAaiQ^T|277_NJAWiu9N{NIMMuHqDj+NK0k%Bul^#Xde z_4@#}E7;3)VFpYVDM2V_;F{3SIHr05e?CJx$G)L@ifd9H6MQ!P3zk<-br3#^OnUQK zjWLPCHUvu_4#L+aRM>PDSN^qB=M-tYzgKGip^J6up0TtiB)N6RT>T8G!ugPjnU{uQ z;QHiGTbcw4ORhGpw}Bd25XD-b;Ng-0A%FmC8>Ibqf@U-k7RPNCdo|HzEPIZBUhj?T zYCpizDZXjkR5va_LS2D>+CY=w26EPN&IX~CqQ&nrIR&WOR@IyWEFNUD>?M$ZBiWlVh3vz0CLco8iP$CBe=ok+D zsRhp%p4SvcJP)AG6e0ye4Q_`UK|$Q0G_qI`n%r1?J}*4`2+>D_@8{Ro#{w;o?R-k( z;LXK+caSEUkC9^zq_F)Q@jTe{&y+ZU19RYnum2ys3!~^>rt23;fbmOhqx|24-*sagtsV#Ri62$`Ljz0$_k@c;VPHGjKC_#<>!h0+lUz9B z(q*X)pBe*oU_+{(ljkz65v&eSFpB|&kcEG3dZ^jWD()Yd_nkKAHPcAZ;40*QnYXfV z8G*jJPMzub>jIAL)bGLM<8C$6q)*D8R-L(xhJ*40><&J42V+cVUiJS>O8xSHcx9m)-#h(j!Dj=AX_2k1% zVTSZ%67rD@GFD063n9AWNs{g&q3EJPO!Jew<`(I2RaRzP`OoB*x~UjzkQBK>nz?U~ z&`fHKh4NTeFLlkBXPKs9@jmz*m( z63-@Nah@?U7qokOv7w3DIeMDe z1BXH}WuX05#(RnnexPa*G)fgSC2?8sF-L~P@9Zu`fGruJjlv%=^g2NKxiAfnk(QCI zuv!~vQ@8e7o~`Tg@Za_~pMr}i?6oyfXr9cfOXecD+jbVm#Q-X7_$!-NgZ)9(Yh!rh z#Xrf*d2ZiP^!vqno`i&V1*CUtgh_Vaw*EK_JS@md_~8T5)?!T_oS!Z(&o=f z(S=H8Dih>;gI8<05gtI9ur%Km${^EF9CG;lC&?$8e^}@c?kT)Yb2#qw&kSB%AW!lE zPqj={4Q#TGwhts5Ydd(MCl0-8-Qi9V^}1cF<#w?Avhf*!2EM>&eCZ#Kqyo9*U-d;i z=_`OBVk?+*lzrHXs?}u2CjAJJgo2}k;)nC-G>5I|*7g$${+dV2#dhK(LpW(|I9UKW z3@VCS%7{C*Bu{bMt&q)jCC*P+FIz_()}`u+{^*22M+hFT#F)dYC~1tzC7^6D(N(i&jPQDtiD^M6 zr{zkDBDsu?+~DEoGsa5=NhV52*iD&d3j8d%rv%Lii)hFEKgyI(An?`5ZGziURevV%+Yf%&v5(+a0dj0ZPc|8gkdA_f=m9@REPn|aa zz{{PTl-hl5Svdsp`Kj5j@QQGxFI=0s(32>$u|e)t$|IM5Ls=Y2>DvYtuo%VjI!PRQ(tW^*hf<&~g!B z^Z|2!HATL~ceqph&1Mpdz_I#B*X`T&qs|7n+RDn%dV`pwNDBDOm_?2UqL1Tqic2+x z<}J?1-nyfKY5Xxnx&ttasm_p5V-YWt`FJ(a80c!KTK~q5y+gle%aM=ikUTa4>dhb+ z90&9MUDo!wSTMo&2Z6`n)C8>P!%&JpuBO5?r!u@?q+l1Lwz7ngpjx>>|KT}BM-_Ll z=>HYB#>b93h#kZW)dwKBi;H|Ji+R{;So?J_ka}HC2`N!Pse7KtbOGLp+2+v3S&jxN z22u-JA?_D;q;vD$0H3`0S1cU?KrO$1ried4C6b)m-PM&3f>J`Q8)WoyM&91`aiSGHwtQy)1PBq7)ZV=%|9U4t`0pI9#TcXz zNwKsOh5<#OFBP5HF1=$8iRU8BuyKWb$Npt^Xw=Yy)w3%6Ew%b zd`S=^v6`xCs>CCDx=Q!wotq3_qBJzJybW9giu`)f>*?v~3zo(WF}12yo0f7{y@<8w zF*PmK%)55#2JNVfPd?L%t|V!USBpb&Qn8w$?&-r#fdp;U4oc=D0+S)YRLrFPheEUE zwnaNi5jb7-q1-e}@8#psbDD;IU8d$O_X11C#aiNtCHbEU9PWmDX|3T#o`f>7BMKVN z-bZ@+%KcIl=^^KBxa?>w{vD@TUW0#;9;^cT&B zd}`yom{Tn^S2K!&@pN7}Dvruk(lwti?r9o3-Cpk9-fatc1OO6ABC0FhB(lrw z)N+WgcqV5Cg^Dby;h zKgtJ`&j`8(c7By+IJd6rB_*#R%>XwqTD)T&ED6$vimIV-pN8M7-;cJ*cnAc)PBZ*R zuTuC2rkrVyYq&c2z>sPwd5m}LJXy1So03i)lQp?7Q0R0%o?T%-p-n-wVlCtq)Kc5+ zqv0}I54{~LMiLw_dzd2J)A*$2?{thy|f*m9F(mns<>35B%C8Ni%QC` zP9r3`8g+3$Ap>C^J7uyerr!j+5i?hY0%hUZXgc%knUD~Vg`XrJVXQ?-c4EjTM7tY7 zjySZvjGMU}qUAyNI3N4?&++gVe_*@$rSHH{s;*RVrLw&ll0189x*LHCR!*P)5NTwo zciDB$L;Vb3ltnW})r(oQLf455&7%8| zGNX;dYP^kgtwK%l;O^lJn(?b7{E#Fw2n9B%MEhZi$iv9Js@+1IQ>g4|5 zZuR4{ub4P7Z4{lk7oAVt;P1V2MQTzwZTwHbncP%t+HS~9{}!g<*?MrS_hY93DJT$*TBoUloB zANuFbJcLQ6!F-@rLL2%1$jh*(U|n| zx+pyuYjlet;-@sr9)X1s7_4!=$n1(jvV#RMqUz^j!dPOYy}xevOe3Ze_DYqXNCM`a zG{TjpFeQ(F=WsheF{6f-HEc}|TlQqpJT^InE>8%%11Fstb^NDzs-7jMsl{O05KO+y zD1$U)=xET-%gBt5y|Y^@m?=}2-1POMnsA|!;)1lA<}2Z@Wegy*@)zfF)q=^%5$%zI@2yVYz?<&yX$3L^%etSyG#+ueeE5;8Wp76UbQr9dGr4OA9 zpb%RH_6lT|j}#({Kt7xgU^JZ6KjX}QhR|U~L|#TtgtPmHOSr7Ly?0mRb$SMHv5FDM zH;Ye%RvkdL@ z&_eJq^s5==vMoFcT(nT1$R7xx{9_E~qqv-%@^-E#lp?_w7A2SNJZuoT_T}<+<@Chl z`WP%0#;h?4&A>`+vN46D1UYOHNhj)kCmAoM35KB54GPl*m6U~&&29;-nm}``wT~n_ zW_9kJvU04a_Df*xj*{agQ)9sRhi@j}#~rYb+7&lnrf`J;G;Rjwe+dLw=C?6#55p+k z?<>X!czFBx`271fG4l<#`s?FE<@qG-0B`n`C(X>yN%*FqXoLdIdOpa6U>X#!q?$2q z2Wp+dZJPggl72OOrO$A##DhI&AM>Y1Ix^>6mKiL6QDjrC1ft@`pUvoS%j)-2A})u>M4(n}5{bh$jhDEgRV7oNl`p7b<}8!mx6N!fvIG}nPITwYyKD3X+kPw{Xk zXIO@%s!qB8o36LrtyMaFm!ZN^I-l+El*{@FjVSTrx05)@WAc$XMV}KGP)VuNlU_`^9%hXRY$XCQhjTI#zkw5)Yq4_?gf2(AlLjxCo%yrTi014GHN*|gB->o96Vv% zY4|xDS9NL$%NbDhC24sV#Hw8;VtQ-2NeOX_Jm7m{2vC0klLFRsPv8z`Ss)+2Uq172 z;oSFCC#YLgrjy3pv zxutkUE>Gv_`4A)qQ!0MHx`+!>|2p%$eB^ZMo47(Ye=xAydaQPu&zORGA|bqG; zqEw33>%|lWj{~3Wkq;guZqZovOB1+g8mHEcVHxXDo8^|gQ-JolxUpkwcgWqh- zT`(F{vXpKi+2|HXlwK0X)+)`L!9p9A6f@)@9uXQ`R#3TCeACKtYhw+Cz<(Tld#>| zS^axJVOm1Qi-15*>nYD;tVpYmqU!yLX@A8LGVwcyaE*^F=WSu;v;H1=jtS@~c+k8Q z4Udu-U~?gpfrJ5pJdGL>OO|TO~e>JdmDz;{lv00E)z^mNQzEQNS zziCKTXBm}AfPB?V(bXd&gXmf#4n{UP92a*rDET=@uQR2SyObKU;a+zR8CtsH8f#!| zmvv-lm-fBJ_o;rzN$;n#hP05p)9ZWZ^>lm!$fK{R4+5+{In`@ME3BE&pv$&42Jv{~ zV76z}v*^gVbA?g-RUzJo!7qJ)SdiISf)5}tUj{;~jC^)$?X6NFNjyz%HS=qjuwQeh?mdL8C5<)g*AC5q zJrXw*a|qihvHr6<)pJlWy@5>b#{5#!ob>dhdg=5V6S=2`Kxyh4RPKf2_P$f_J;^}( zh6YXjV;2agGCU0$UKMd^Nn*8`Qc z(<`-c*bb`(?{?CVkBbPu6v6NFaBR6vsqHHxm*&MyQ3p0NYvM@-nns^#_O z&4fH@Rlypa#EU8J)-ulS4f54VyIlz4#}n2f_qVqz+AtabL_VVx zVYs5ZM1qut2f>ef2KgSh+(Q(-GP@G7t539!6eput_@kT`WT%3Ia{EjknzSFT2|RSk zMSjg!;JsX6mXa;`dG@Y5^x7F0wx7GCAWNI!QmSih0v8~eW}*EeI|=b&+E9`u%lhiE zgeP|@*}rApj$kU|6a-ljhlUNn;mOTq(GrF+Kbzai$GsZtCc<>nrngmN!LlP)lmwx*{WMI6=Oe2z>=}=_GI)FD(qFQ(5K7BF zme*#H^~L!|S6%HGSsSOhii@|O(DN{-R(vcxO8Sd;JxiM;XU;Y3N4o_`uEB4Y^|%?p z$M#(OQNZF)xFJooO=R%#lPgV9f>ku$?S&zJ^Zr82f1tQDR+A>>^u~H=9wXr{ef;8gi_Egd;F5Th!gnmZnvP%vLzTr&;X&+dd~fN*j63X{V98j z2lp8pFs>Hb%PTAdg#H0|+LOtV{Z&+&EiZ`sZ7yWf7$z=aF0MDmH_*lzyVf>ypk12z z%Xp-3EP(7vUilqEhK|5QDM^W^6VB$XuyDWscbKc1#U9VYeN208iF7X5Nu_gui;$G{ zxr(k}%rMM?4(+w5X?kM?iwrg}l(%`GOOVL?N9aULnY{gZ;(0Fs(HTXn?tN?CH7S>g z=2+2q26u?k@FCJpq=TH@{66}mRd!AfC8>5{@u8wx(7pBytVcwSlHV;F%ckB=$Jyq$ z4N@sS_S?sqR?%|-OOsy)?pOa4nmuR zz0ik;%2FT<>XSNPZV7LLk@9S`UM}rjCRDr)%rTDz~@!&uwKSn zakFg9=e=Q0V}!@XeEcb>E9ccp!g%$nwpZZ2?Rpl=Oc9tP8dM_#Jf~;}egAn7U0`qt zlGy+)=}yH}n&Nz+#wWAnJ1$U(M(rP=hSgkm$hRlyzihT)({q7NMjnqp2&cj#6v}c% zVIWyl4Qh0kY zB_dl+qYzz9r`;KJ+CB9ez_p>&>0L7u3WHGlqJHL!j;Q)cH?*gD9gzv0gW5#l_HOrlnM8z+lkmF_41MVA4(-lQFVT*B+Fp@@z*WEuQv-DnK`>p=BTX7DZ(e zNq6v5Eg;0NbbyzuvYq*f8-4vRn$OoXjoKRhPgILetTtcyy174F=*GkN^~yaH(`&5; zfV<$(y%W#&oCZu{4iz_WAd^NApilh2Sq%gYFdFF%1QGgLOs4iPe7qhi8l2}-E&EN= z#ajRus1$7vLj3_RG7XIvpM;|>NL0G}F80bwC!)2Gt&{Z|zv`F{%YcH3tfC@TF{d)d z5AO9t?m!(0N@LwVItuHt#H^b${p?cH7KntLzja-sO=bf3&8#0OtUKc!*}baLe_l#3 z6C=nhz(IqcabSaEk1i2&aj-;-6j^THO)~)IDK$}(`TPa!Ip>il#zan~FXHjq*khs< z@IZ)xN|L*aIgB)^DLUDL7i}l9>su(D6X@G?LJjGFL)hFc$ zgrvsZHSqt~Ed856CNcB-3(?5seosXWB?Et!LhTLFXn_O;tWnFbG%vag%z+5RDRux} zxS{~f;`{UK;rQ->GRc$^_0T-N;|}d+ObYD#{5H#W14xC=q(rHhs1hg;RNI*3Y@ zG~AunD&?v%PM~;#k3|HlQJ8otEh@TqdY6LM42dTh&7}&eiYd&AA;AbrWQTeG8Yrg8 zs%9iMytqs)BkOfGgC#)t3t@=tQT>4U?;KJS?m-}JX&EQBOC2WNItC(L`}U^U@hPLP zr|tLr{w#;~dkk{EDM3HCuLuC6e`y6&_}AKn4XRVy?;`I>TfWWOc0b$St;k-y*US( zrkM{Q%OI|T+!B1Rt$n^uX%#5K@0=Zz(%Gj*1&5EK5@7Q4q3?h_6pTCvYg`%Gp%PJp zes9$a-p(f#dw-@|Z>VLiyd|It4nw3&lK9xo6S}50+58aKb{Rv=%!ARn{4VG&2-gbC zVnk;UsXHL-4N5HoHmN) z3n9K_Dzr68KTy&soHe4kcy8YTi{jCT`Z9SYoUphbYgq(jBjR6Y6%@#Jc|OBCAn>r1 zLvYC0YB6Y1E#O>=Odm?>Xtm^=v+ibIB3?@MvbTe5F=s%~TWIW}ktBIG=WHfGA59XB z;gp8z5U>38@OO&CEYb5rUC?5}6hTltV>l|0zuRvyNSfelQH&FiESz}%@h0yJ zJ{?>z-7Y{N`(nw!i%1W!^wY+NK2W4*Gp=$l&YERyXRK!vxj48#jFU=i=<|aAJ)J$n zspLVbF&;d8a%=@(C2ZJMefa1!%;;-%%h$E;Y6x(>2nb$4W`-SRi`dO0TREY$=ki8Q z=E6~SEnk#kbKGZPCb344n(IpOFzOZz5TmXLNwBgm;_2Ep7c*y;To(q~3!>TLIDv=b z%Q6!LIhuE=K&Y|pmO9b}jDLR4aqKblbgl+$Rz3F8zVLGu|Wtm^4V#yGU zu>m|)z!;q>$yz){L~x+4D;>l-0_}hmArG>Zz6Qkp^JbncB9eq!micu-4WB!WMY)UD zgilEN;ym4qOjf-}yT+XpOd*(U3@df1r!{IL?~GBn`ml$H+UTOV&vOJz3Kfxl< zCO0RrLbCDK4_Jz3D~DTwG4M_y`Suy<>j-diL$WnFBAsJ3g`uu{Nm2|EjBe{oOZgWR zi^$8{WxmFANtwDHtOJA3a5G(zflm2kAbukZzJlr(n3F~%!=NwFIF3v1ZR<2x!^BFm z{z@ac2W|F1l7mD9SE_4COa;IvPST^yOF#@$~Wj7HP!#6_kG3IUqS2P9Go3Uh#r zZ7H_rP*P2J5IZECNRyPRG#YK7cu<)yIzg&E<$(K4WS{)dVwZ2U;R9UGHrzOoO^gM+ z;W}4%a(EZ3D51oiqjGbzzLz0=T;sT*WKS^iq;B@Q3`;$**N_^ZAS*4*^%TRl?wKZV zWU-mDmxJ29U?bV%9NrsAUfxW0zd`_8uxj7ap^Gyl6{H1c=QnawBlD(JJs**;hI4Zc zbCuefBsryVMc^fc-AaUi(TGw~yv~ouwb$gg-;l{5{>D}C>qu=$zusLF=n@%d2$f=> zE(`(=`K5>ZdKP+$yWp(DGDm)(0s#Qj%E*L1s_ewveCO|E*+M}@vj3Ufs|UbT7Mx^7 z$7Bh6lk45+z3UJD-O;~5KfHGscSzfhU^a2y+|64&nOQRST#{MDi*RGY&1Aj|T>__JR5e5=snkPi6)g)x{-U~>~JtOxY!8HQ<~}NeXc(w?v6Ry9@yRPbXS*}3vO1pCK_} z(OCKRj!x+xN*i(*gPSHQ^hPfEzh5nlB--4}b&Lhn5l=SDg`>XY6jAh_sRewIwZO}eDQGsN8T_~!+VFU}C zl}}M^&b*EN-WdR7^plF-D+cq?AXE%!9;_AAZ)>jB1k;qG*0n?=Rb5ohQ^Hw0R+*Rw zLto-Gq}a|B!KEbIqO33{K>FGAXAuCD*j4nQhlRR%;!fFt=RnHa zTGlk#s=b)`9jnG!=Sx5Bj3bChih<82Hof;;2dk^xP`b_T1dxjxSCR zb9qtLo6$ej9|b-L4gJF|L1@0=`(X~XMF0|4pbu4~5;cgK(n3uIO1q2(O^DQzQ!&t2emdNF_jtNN!XM>gz~zqQF^RTl+ld;+g8 z{kZ$tQ@9b8cwSx(UBJ{MT=kBYShbG%g>5q*s`iR*9-rsG)>;YZp18?skZT? zMihWp&J}}A+0PjY4n6Y?dXK(B+Vj^{x)wZW)I9z*mJ9lInus}AeFt-ifIpq%%g*x; z_{07>A8-i0h_6+UTs090c;y>CG|WKbK^;$s=`mPAhdJ?r(fRzgEt_RHPdPYVCBp?* z=Duz)e8vo<+5zY#TRl|E32-Lwnz$52hl_xLK*mcmlB`9xuO(&6&8BaucRnnW=#Ew3 zj*d&$=yF?PP2=n@WICxL%RbY-zI=bE*TvCV@#PNZm#{rkYm-cLW86~(kVmi{|4|;u z$nI8huYzYug?N>PW6S&a@S}f)PgH#Pyk5f&nw7Z1`|fNWl(LPNW6m37V5P7N=?{Rt z#fGu-Ok8M&DkP4H#zbdcP8Mdy%1-l&+{>ZV_GU(0%Yyz6>NBYeqCwjcs$Rr-u-(}( z^BZ5GQ&2p{E=1&ahqvt%I79?HYm*hd0V!Nu!hV*Q zSaoaR^+RQ+t4v9bY%60<8d-w+5<37;%dl?e{03MO5-2>k{P|V^PTt-FV<$o%(1)kiW$p1(Gg@|wDw5C z1Xpi3R3&3SOyyR~AiaGMwwDX$4wV~xD)nif^Jy6)n*f|}XXOPNPR_o5ZWCaHX=cK< zuB63YNI#l2`q3b<2{mleCy}(L;-lk0R3}I;~Ueq6@Hwn z(38%)qz5Q;PT`MHL6Dm?BnMC#bc`r{JUbPnelcp{afe*z;d!Nt$J)Dq?HRy(w#j7y z&+zY>N0R+aOy}vq+IoRybhNX|*Teu{LBHqi?x>Pum5#>N9O{=OEf%|2!*)~U{A1>> z68@?QgU?6q$&;^Uyois2xdz%@(2WOq6Weee5nSgIoVC}+%BTd4Ne$qq4xvbwU6@Vj z2ICiHYiirA&dQ59+&+lNSK?a_dR$(AC%^}|-`Zi4i|R%Jx5si3ncahl8G=47f2sJ~ z>f(%R8p~W@_Ua_S@pk%Wde3)lR@EWJj|w`Va1L>q^3|9>9BsYc68D+%?$B<>@kW-( z;4L2>0ftZ9kEzbo_X3DT*R%nEByK!Ph1t8ag0&bv3mXGo!-BEg&2z?jEZkd9{Ae+_ zvRi_Cj@*-oc41H4D*N+L6s@IYrfJSIwL~I?#DcJ&`7Drpl%WSCC}nF|LKrM2+kta~ zGX^qGDyz`EY$LY2{AF-l`7qt817PNK0(Q;EmAJAL^9bB?Ecib7ML4zbiSbv%k8zH< zdteFjNsme)$TnNlf8QuE{j-D1WDj~}_;22axMnp3<;S0>o+c0m!USlBQO>8VD-UR~ z^oH?*n%9R5+LcZoq8FnkJ(BSAH7my?n^;{MLgAXR@4=ognPV$xveC2VED>FdVUMjd zuQa{jyy__`H%NPPKssmivBD7})3y*znj_H&Vb4H6salq>Yh0G3%7x5=XGujhlWLXy zbT4N}J`iWhKz}PPHUkV5pHZK)f)BCXEkj#2YOnezN)m%85ZREdg%o;8TRrukF|{t< z+E+7n9gi0bC8w`rPcK+FZ?qk_iohB{KpO15D=;SV*wR~D?OMct#^KO3y%ndh{MzhO zMtQiVY%iEfQUIWs_Q`&HYz_J@n`urA ziw)q&Nhl4d>bv5w*8)MqPT-lnc<5AodzNQg_q+4>XzIk&9+4gxn5W_&)`3930(nA5 zqe^p1qfVG+5Rk;wx7FrUbxDC5Ul(X}?QUiy=QoiaWXs`&`V*pTPlH3rGcxG@oSA_{_= zKV)bjzzHae=1XAmgC2y6RMIp=5!8>?wdTR`p9~B#xZ;$R{#1pV}BmWJ|d&;N!GwW6?Fx_ zSZ5hMgPJJHXH^v+65W9suEz{-B{?j0ttDX=L|*BgJlh57VucQDQU<0s|1o-%VU~O` z1i3HDwgjM0x$3c$U)W&g>1}#Om1SNo&{TY=+L-(0OHun4E~9t2ZuDk=oliA^oF{J{ zp{so?uHaW5ZOpR-pF`xVV@Jg{<<&CsfMmcOyYwc=;;qJX%9bn7+(!wh@j^->f(4R3 zKW!UV+}LK*cN+B|z2w;kiwN|wvM+q0Dd=PNhyVzmwipo$7zlcYy#Lk7j%zwRo&uRyt?vA6Azp;#8tv+WM+(p)QTIfe zu^$o~+CU!jPR@r~z98e73ZbEx)47XsNCDIJ-Sy3`QXTx>#CMOk=ebz&Je<4aeIYwN zgxx#!#3$(W2+!hiM#jv9?eA>{Dd3IaMChr+tdbFXj54>6p;7r=ePqoGZOBQO;sIm= zwX{v2nFP*sY?7}N9+QjZvcRdO>-5z}kYRGlMn?-~ttZ2w%qEoipbdtq_*c zOPS!CE7#nc{C{-56?t>!XD>mDEq6hD>$e>!Fu=iSWT#_;!HXTP-t=-;!D||qTU_0b zxZS>)X*WI9E(s|)J^SCa2!6`dA7ml{9xMwxsqbeU5q?1by(!0l#WXN}@{k6sX>rj% zdB~qQ5qF| zdv>k*3V;>PjcI!|;Fqgg3wh|f4FLt>AAqJMXyAkXeEy3NcGg*8?r(+|HDT>%vOD`Q zIGZQ3?K4QzgYlo>5^l769O~ES$DX)vO)?!Q#FtcCSQTXol?i?&L&bWUW?uEkw_eTm z>6Sc3CDYrVNhh2#FUZ$LlB&%L*VM{|htA1Tw#P%+-Nx}t{?2*Z4AA1Q9bo+UXBs^s)%}|n1qVsXExNIeY6OGvzwcEOBtMG z7xFNUn%~F_xs%Tv{<|zf$-tSQgL#za_?Sy4CsD;WT^Fv z3il{kHY~fbO*BWkQeVFsv^#o;46#S+Dnyd0zL%O{-yUOjH5nwHB67a7RhRGReCD+< z(v)l(8y~e^T%6fIE>QB$S&UoI#T@5rJ;RW0@i?Ch;GeV_{_fgLJ>vhc16&X++g;QG zb7>i{{+3tydKdn%K*KFTJ5rArr$*H(hzy%N4UCrIl}s8ljU}t&sw1mP33wSIqG>fD z(8xud0k}E_M6@g=9{SY_Tpxi;(lcA{X=A3P?Q|JiS*WE%}sU>Muq?A_o1Y}4y2HXk6|HQI;{cv)Y?17E75>lj?>!}T9Mq@E{L}FR) z*oHMf?jJt`dW0BaC=J5%n%i52e=!>q!4f^!@vd{CQKv4E6N3LP4Jd!9ZBBp~xEQ?%;A(w)3Cq>VX)0t2GU6sPFbuJ*W{n*4!n+San+ zle8nebfL5FMHnyq&+n|bI{=sT(vbeY7Xeg_f8hFqE-tEYVPmE+wO>b=%-B_ox>tsi zx6tHHi4Q<584o2l&j1d^zb>P)HG3Fi{I!yi`oI@ensS9{bE;ivX%waI#jP4wFFcBn zQNOmj49;wM&d;y0CvsyXOFT^~`5e&11yBzK7TO#s5Ey(3thNvcvuVlpIl2ABPT6d`=_GGjd~JWh=u3i#xGyj&CD3yI|jivr-4K27>AV&&9GD_|#* zHb#4+3Gq9Z!Uj`m^irbSnOpxHMCLNKkl}8;$}xJ+c&<}@w(9&#NBGpceBkKzUE+@I zuPWmdQ}SnxkJ2=U7#rg-uC+b>htO>nk1$lHS^-uEA#!&MG_U{(W<`px?h_Gr_dWEb z1@|b-yqome1PfR-58B(Qh>?xskB=B&muVF~hV*Rezc$Gw`AXFZ9OGUbA&Cs%r~E3L zj+7!%O9jVQu&?cD&w8pZO!{65@*+=F4>jb{`lY3KYl;)pEt4phpLc(MfBYWvTS54K zAOwdWbsY)@q1X$C1W6T{2z?NcTWrJ(JUpT)PPOMkQwqo(E?Vd&T$;RcY+dwBorYJh z=`ksB4M3?-^F*5lvRrrGcai^<2><_4i~u?xQy7t0H}N%~PbLPoHeE=4yXLhtLf_jW-GDw@XRhaX4%B(9Y!PRLd7 zRP^H6t_&D%Y9M0tXWJAnkc6r_$va~RyIJNUO!ZZZZFd~`jf+shP?8YQqmT_gM}KMT z#D%(mERh%SP^Z1vGGAzD5oRrWsgBf1i6TgnEQW%ZPt+uvV?8^SC>2!`UuYygWed^gA(`jVLYb27B;tKIN3u8o2f+V9z>S3Bl z{RU8S1gk2ql5CQKk=J9n07i841wx}l?s8idO7zE8JVN=C(qvE@XpL0JrrYQlOak{) znAMadbRJcdNunFB<~JBv5oVjisNp>sK2>k7Iq*keF@R5VfMEv|gG45JY0@>ZNc3wn zUs5HQk3#1KAOm5SPlCdcVaprQKFr~sO96aEJn7nK3vE;^iV6|TkUBo!bnZ>y1CFuJ zN=}U;VErGa<-P3GG7lJ8!V=B#lPwf;WL!>lMT9>{@1-4o+?DqrOg~{6Lf#1F+7$P?RXu%E8Uy^Zf6v5Oenw)#aPRKp__Lo8IJ8A>@;%q&&lpBTtw@kFZTi%d~9U;vPR z0-?{c_CA|#gu%CoUz9Nv0@-6Qz8vUgbxCxwqpyVY&iGSFyop*s;%UEQT zfzI@y>y+fGk2#j#2C!omraf6J@^b1re3IL`{F|g|Jc1F`>#T)ndY!sJhIEeE%?dl7 zC^X0FNj3Z;A1sR5KXn5{$ z3hTF*ug8)ZNpJ29PgN$HKBVbPs|yK3GR*^Ya(r2C1e_XZr05u5Yrhw(s|c>I?g9Oi z%&+0g`_{EcEv2!|7q@`H(jn#6N+83YjYr-@B%kz|D;4#J=o{Z5L>Gy%m zbDHhW{O-o@zt0FT%3g*ZdVorlcOdjx#5D#GK_n7_8527a{7uq{TT?5zU~*L}4cq7O zH>1TYh)Ta8Y2%`fgtf9rhtrOJ(%vC{4`?B!{W_~%(P~h-Lid%t?Jfn*MnsaM`|Of9 zPtY;c!#=5OCh|3Er97GpcfmN`^E)tD%VdT>>wg#-?fZDEYnupEa{%ohz*5Le#QsIa zK&3w1B>&XMAMlQPkn&nI6MSZ|IcO>i6{*k-)92MEy5}BX<#SK&(&?N(utq&~i&W}0 zZ&9?@8ihE0`52~We@NGJ3%pe;y-@SN;!w5fm-XDkw+}PtE@|FV$bw82Ib9F?^yake zzo&%Fa!Alymzd14r2tHN2K={D6oH+7)vI<%|8|w&VWNU5b)1=QK5q$aeaTDIeIG;c z57n0uKPi&u_7>oI6x(TKSfEGiTm2!jiV0ay8N+Olh{N{gt{%dO!zdK#mC{UHjppxp zuOMgty%kWoqQ}1s}7{UyoVkiSdC1c+vU@~+t#MWDFnv;aq$ZNAPO%y zl?mGKmTM_A`h`#HL0PW2S)_bkAOX|L&^3*SIMb6+1 zM_=wVUIFCvXHbJlJZcE_!`(OW-Ko^awPFMcTx=QmX&*jg<<$*%)I2U3(Z9P-*$Rp# zUTW_u{iI*|6(q?>)Lvb`Q*tKVMnumKDn;zi@X@Nszi?31G)!3N>;*CEJOE<1RjqZ!Lk+IKKRxl>1?95;5P8{dAzGu~>L>-Nsbd=H+SAt%f(2_&UO`R%Ct^~5?@G1=yKAW z5MI5XznnmO%Ht@3!%+AN(3zQLI<_f`*ICFOOzQGKKb$m^!6=JGEpLJ zFhyOH{&pRop)T~xNJ#c3`ltH7zA0H~TPLc^PfW1ps2VUXp_w2`l?oTUZg+eqPwG3p zb4rc)mJoxA6wOXg*3)1Na^D|lnj3ZRsQyK-#Ye5;#ywwOtRQjqo5S@@q5t4O9Rv{9 zaXZUGMe>xUOws%q3o=xJ{n@zA%*f}i2D197n-^$nJ%6igP0;-;zMv#He{pjci(B=e z+)!Z4-o4Wu>+Gu-I(-yq2r1D0>&ZVuU?(S?M9`^&b{c1#ZL&9(2XfToh(JGyF1Ur$%m*6hWSW@7Y_kuVy4C*aR1v4?zJ-QGb3 ziJmDsfk2PDz)KTJ5zB1~ec|#4;`(N%WwFEk3y$a4@=UANYmc`4?>qP6LP$U!_CzLx z$E-sklDJ0VkhhrBosi=%FagoQWE?BxTT?!unQ^C?p$Ybb_mf0$=LT%t1fW%qMq>|4 zw69`Ws+Y_YHOb`ys~Vmb4vMw%jf;NPu_l2~l{9PvxMOjelGe|xz#?*{whZnDAOWgW zBtG@4uZ;;TDe`x?_n7cHEM9;oc3GM{FLLNuIp2g3sT(Yh-p-Tqgqb5LPpe@X|6GdP zGkm^sA1Q(A0_y24XNr3+ge4$tja}&6L|ICxL=B<5^v>b-fGJddOkqVZm=Wy{=i8fFcOig`TzO{U}S;$p8gbj8A62^(M*|S5@5m_+?5`7 zc#27*61%lpEk8(Oj`_{$YpN`vO4LrcX(-7WEMr`QeL;%2DJ;HoNkR28287NBUaSbE zsA~&SY=z>4(}pn!^P+}v!K269=2Cc@CIjo3dKcw20aL0@_2*bqns33Q)j&k zIpNzAz?zbZHo^RDtY2)gak19iFK*>_X6*-;UA9m}$*C@%>*lV?9P1(ptX$ypyD=t; zSKnO`jvyr^`&L4J+`-|3Zy%`3sP%z^8Mm4+4$6>t0CUswy{aoxJw68GCsNmTy+^yM`EYcmc3AyC? zdELc!O!xbV3~zon<%$Bmiwabk=|zwGU?<6a!Us$eF!WJg#h~fnO$|?Y?BVOJS7-3v z9$teDrN+RIQ_-l;jzz%D$69h^iMC7$z>ZtqPf*(@Lh?flro=EeIA**7ho#ZX5Sy;5 zWeRZ6I>&=c0tqtBaq{gy`6#%OrE#f35tFyHX#2`hSB{txYlUl(SLaR;%T5Bnn-sf{ zeA+mGw2qlN>HD_AuU}xA+WTD>2I9;E+NCh*MQh+@^Jd7chGM&^IBm%~a!+Xp0HEIP ztYE<(MWyob#K8BAesBoRe}Cc8dV{w1|C1hR&QUG`)Q5bNWN(PP64{K4x2-2P`UY=o z?PdfrndZ@QH%~H+&m;ZEOAmLb#D# z<2|@N`t{>WgJ=x_kZ#F>$uS0$ha9bwFykx4F}V()tNd+(I7^H7<*pR_$B70#FJ_a| z<{Fy7E$k{m9oC~PJe?Bg0wrib4@=Le!%j_DETJ-@RpviD+nkkT!GR@C)soJ zgI$Z#w9YDI1CixrrZxMey?=CmiKhOEuWfLM9;`y>68dPVZY}8-6>ntPE$0WGKgia& zPa3Zk*Z2@wCL7D^LhD2Kcrd0JKkJ?bf8@~AO65BSGt&D^bL+%R?RBJixkFy?N3X0? z1qolX+wf9__S<&gz@I1){5IrFW?=7V@7dYeXG_A&fisA=hG}7>dS;nhg`1g?_OamF zh}tsgxq(H`&Sfo>l?{C&ACPE@hYx4}$?B9~(c4Qu7srG$APSvcRBJP}&NZoXe@;%b z@_Ms+K1X2=qtc8<2GdXMQ0)m7U&5b+Hac4IO!s>;N*Gp1uImuJLp*R&!Umop@=St+ zWi_)5sjV#eAdh%%Ex5egNtJW96Hmw!a}avN?!n}kX(sCuo-YbszyfRfyX4yiH`f`W zrRns`tHNdrynh?I3<$UEVjP&ne@K^5G1hM89OtmRs z{>}GUsre{#ciiL$^r@pyJxZL-B0VNa{FwT-Xe)lAss9kgtC=#RQ2WWuW&uF9o&A>Z+$PE9lv~pWt*6Ke~=+Cy@SKJ(AG3lt?;ED25pK6Nz^UtoiQuC{_CsDN(>-IAg zG0VylWn7|+Tl5>ev%PraLw8(d`iA`^4ZmgvlOJqohHJ=ajFi9&-kyZ-_jVYLYs3k@ zVOK-bBrRx2Y^cG&Ag2v_e+PQpF)JTVH8*rYI3Ve!TP+FASRTtJNUOKkTZ+_n@iE8v z6m`p;WwnGYwdRauQysQ-?&fQWmZsZ#;uXx9CxAU@q0vaAX-`8dSAy$wN7i@U`!^}- z$k{&Hh^q6{VLZ2(teo}!f%9tj|NhHAfBbw+&8{sAb|kx0{oP3?e*|;W`rcY1e9)Z~ zO(_it>-d>yZHR-pvb4%>Zu(qWs^=)Y7?eo(Hnd9X?2+4?RT2i{+tin(_k`bv1RCBF zZ8Bx3NgSM7|6?{7)?@^)cMf4ts?kvM!1h5jOqh8m?y?*e7j>_L6XQ`q*y8L+rohR8 zvCx%lRp`ifA!ORJ5kv0n<_Zka6$8bNZ4=?HR01q{TiQ+E*uoyF4AV$_EoS@VN_FC zPQryZ>`RSu(wMr(16Qu`YS|LP7j_b7e(pK=zp-60D`mac=r1Ea76c^CGmV*pZQ&9E z|*pg`(zOWIoO7*4>kd~;cSQlOGJRAu+Z{sofSqZ zU`xLXfAA$f+pLmK!oDPl7c0I%ev&m`RLv@O>7#XfwSA$O7W+<>)5?_=f693`D&5W2 z7fej}$L{^C6sFhEiaeg9l$vA3A$z}u7ngSgW4^P5xAzUQ;q{b=;W)orflryqpcoD> z7#E{6Eyof1+ScxH;qdVW$NxXtdk332hYr~Fe=6Gy4p#VwVKBBPqUFit_){3O+1T&4 zPw3vilJ4Erq7!&kN;oj8vL@0-C3a$$qUH#{<3S5icvs&&UFCN*m`t;>;H4!*e&HWE z2&u#X&AJ+fB`d?P+wzAgMn&q`8HMDEire?w*wvps`;fNOW)R3CW*^ym3!aFI&ZU&! ze?zQ5xA4G+@1Cl1K8gX7a!SP6y=$U*rf`HOCacF3yKk92Digr`zh-62ZQ@7aU$dgL zT?9J}`UY{lX6Gto=WNN{Ima?j_DZ%*^e(1#@73X&4cO|=@}d_>Uph)FDhX{1Bd!U)%Yr4f3+3fh6GyerOYM8X>{ea-a8i;T(9Y$&cACn z*A%j+s~WxR``MlQ5CoFA;5RJ`*J77_bs3coIFgn$B{qcj#+`<~UC&cz zIL+z!g*&$C{FL=8=Z+@e=)Tb>p7qLQ&B`*J)EByIY4@$Q}+j(R1_(8XXWIcZsro4 zIR8=}vuBMNrrXNR9AAnW@6aWAK z2mom>2Y|D1KDp(#8o8bm&&RFCIL&A@u~tie>@VGX4Av~0y!#tRLjmA>%^u~MI|bEOTcZ}HKj&+rn6%d z`)f$;47?!#Yyg!Lw^Db+*8vFLc9e-fd3mF>#&@+|lf^+`QI^W%x>84LpbST_D`e+L z1lXO>>V`z>)Lq)Ul($mp2&N0rCzn^R|N8y%-PNUdCEg$(;_JQM3L@Q=?6hA9ZOjdq zva146e=@2@0N|3AN;ZK$ZwNe-NReURC|3o@VCoq&QdYp1_)rn)*aat*!+EJn2Ba@9 zCzpKq?ds}Xe);x2Q0y6#fnEG}Hhc$mjjU+~9s;L4pU;y(C0Z%mM+#R<6uBbZqQ)x# z%k>TMv_iEwlh`L9RBg&m$7~o^TtK5IC;+qye@nZgybOp$V?6p0;PjM2dr2-ssOts+ zyu6_%bPv2#-nZ`M#l>3rs#|7-sV}hGpr0)%|IdY`zdLf?U9_Fn7e77!DvtTrqpf!{NF>jokVjJH}6R`vE&dJ92 zm^q!-{9j>S;jTPv{~s?|IvV^UdhW>uPlh^R3m1>R2#2qGTr2R;mZ_>$zGcO1yD-^1QY-O00;naQB6*_ zZLk7x5(IHkO-{Gr!UBmV1aVPKPPcC90+DK7BIN)8?6;RJB?BOTYh&BS zvFLaG3WUBXK^vq+IY|@6@~v#kiB4?E*HW7FC@Kk&poEA77yy*aHtBD_^Vl~QBqclN z^qw20wMbxhc6WAmc6N3i54sP#!6+Z6+2wAqs3zSn19-CaAeiOj#WV@#%XwUs@U}N! zZaskKFY@`aNH4FdARKjqo$c*^C*7Ux{#QZpHeO7F(_Zjq^vxnI5-R*QDQ0O|rg;{m zWpI@g$;C3bEaI$6#!)aSk|f9{!RRV3E|Vyz@*vKZ!8|ESsE}V&ahgHP04Ihn&X-uW zx&lCDKB;cwB7x%LATG;%l*Rxt80VwKEXk_4!WJj#G%16yx`Mt0trJmyr`4f`#z{O4 z(hT4wfqWI*rqxxxsDdIXt0EmCln4rqri(H6Ll&5(vsAQ#00_;{3LSPw??I4^=SnNAT#3caTh>mE`WXa|7I5w(>- z7PWnQmCx+)0IDX7B7rUKPRJ#;b4VHKAq;bFhpoJ8>cv~a+fCX6yC-c z`AtHD;(5>V3VO^v!P%JWNfxils~CoGfp}-^LGys?*cexVy(lZ7gcK%Xo)^@pJKi35 z;@gAZuKgLf~!g$Mi34__ai{w)e#9iAQ`)K>s@KX|+U?)31*_pkTg z1#iE9_xAYY0J`vh5&$0^9=&=8?Hs&0I68$9LCf$oIQT343{Jk?fBl-8+y5TM@Q(WU z;`r^~-W`7P?P>7s@#~id@bLKo^ltz8>jQ4==x?|ZU+*8jiGr8=Z}z`ApnAsu=N%Ok zJ^bO@19}84?!*6HoE{z@A#PqAADzB~pNN~&<9Da3@(+i9CkIim|L*Vv5%cQZF*JaP zg*wLs25KH1FdRfW_8efS*?~ehmhVpvbbnqR?7s$RCs^H_N}SxS!2lNRU=ZvDKW(*I ztu4iGBm?ROFQ%}>fo724W(h37amg!ql4eYX$@^pkt0|CGfy2yZ@O^9VV}7=_a5dCA zm}1X>wyUIn$bcolQigaLg+E>A(ybV5TXS`f#J=zhQrp=GM+A&b3coMr}21RQSt1$y)(6%{wbh3=%qQ?vpM|$TZGy(wDqGf-IgTrP$p8 znpodJHqe1z+w{Es_qL{$9(PGjHPP0)q+Cp^5-5td_adoa^9P#1x!$shDl#;XI1EO> z$6(V2j)Q9gC942=M2U0-vP%X1g9S=|Vi7EEVn%T$TSL)^hB4lXDpfUcR~6iC|Da-NPrXjpFDB=52I?NyQmw?#@TyGq_y%ms>)CbbKM4(yYd z7Rn=30j8py#~_o?dSp>X63A@|0!chAbI~6n3_*l~1|#u12%>S7OE37oWFW9POJ;*RMDjkyeT(F@tNa$4 zL(F##W`3vYYz%SK%(LK8nJTSx~C=uKOOX*$~IdE*V zE#}@P2PO`VEzxfThj`*KNX82*8#ozl;dNjV(0?XHeq6lCi-f?LQ*oRn;*HsDT+8M@ z0Brpk>>TRRukELA5LvI%qO7bpe{VlMF5rpVPWw;orw1SoSeplJsj~}zWY0plFvkE) zG)FKq=pB}W_wR!|;~uIL6tf{-%CJ=zyu8ME9zybBOqkPUGm|o@1R)*)oFRgS?PAQU z99Z;x0w+Y>D>x>=KGPi`kDjL28cXAZ&R5C!H87nTmZ8_j6Ahe31UN?6xZVJ+J#dQ* z6x|QFEJ3GH6O&-#KsgkD1XI{i5e5mTt)1SJUcaTEo~E;e-)w&s{0Fc>It1@L+1>df z`2O?-mV})d2FQiza4b&7!P9v)8(scoft;&X0-i?+EUwF>mnGFRXj*K*yzsVY-P|Ve zb&*Wu-i%*?JKy3nSsV{&s_L?oU*Q;)5oc0WRiPpo(3*;oMJXtM(`iC1UOk%A9xQ(W zhaDvs@#tDTSk8frsF!1)p$ZTqyD5KfZB@l`SI7`z8-1e15M1k3o=;0z4^HmzXacM` z0hxJ}%&Xv#-W(J~UhJ-@nHp6QLnb8M3937&u5gc*HQ&9?VN5Gq;|hj|#C28=&Om4{ zz8J}>hsfV9#GbQ%s^A+CSE1Y+I0GOxG<8rlz0>=%7v@F{H#F*C&QsyI7=w^LehJb6 zqJ3ceZtSuGssQI)3uTN=0Asx-;P^2M!y-Ha&fyM)h*!3CLVWW`a)ZW>v&iO@-UVh^ z;!gkIU%32wWd&^)J(O0GFld1oLi@if3c<;b8A|Xe$bX-ImOo{!;L{*9xKHHroKDa| z_5^|v@s_i#Hf$*lmN z_T%dOxL#20ChF0vxQeGnNzstl{8X_MI$GBu$_*1A{2vk@Spvu3?~>61Ci^D&h7S~0 zEANua%78A^Bu6r>^7o)BHMr$<&t@;=D*m`T>PxapW1xzXBqD zRq(XvBk2gM(}6Bq%%~YY-RW;%UZhkN&g3tqd6}HXm*VH~Jjukb(Mh$OCNEf6rUyAu z25!;uNdgNd7Qz6(#Etvg(>JdVGLY7m{A__L<^7_F`S*P8!W>^rZCr2RqZ3%lS7s?w z^q>cSuqciv^ew;5MnFo0KpJAg3nXY?CGQylTkWfAHZ|b=9N)xlPo`qMP4(KCnrj1p zWH|zx#n%ZA6!1h1;_n~LpRhJ?0qj>V@~L_P3+g7#7bOyI?V+*o_+%$bWsB+bWpc5& z+#g9|m6J*m7k!!Uqo~MVS@0CAS1cit6maK%AY9BB*+>$=oOUM{6~8#tUnDa)pwT>) z{2LC+qr{x-E%^}DTwJDv8G0>{T3$}wB~=!2cF8aGV%ZWu6xK#QjU| zKhVXzbGG~BeCzGs22Y@fUFU53JlNXSmeNC zDWe`=Rs}u8j$IY-0RB}Epr=NW!2-U2iQhuvL1i6lCh$CpgN0L1TwJmiFU?>>rE@Rq zHSmx?It|tw#zM$NP+WDtxO^@u;GLrvIx#E1>IM{5=!tq6bWqzAq!q7s2RzY zs4SaC!7PO;Fk(P&0%B(qLQtf}H$DM43xFtfPb0}#ck_nujDg}bd zAO-yz^m@JESUaJJ!vDKnQ5RijmzGNN=(T5|RTG2T7Xw3piO^ljb^kpR%NgJ?;5AD>g3PH6# zGwv7;@L0qchPGYcK!w)SaY5n+mq{fiLE=7y@wDI1rl^a7Q>dWFcE%jURp8SQ6C;1|JTm@$6z82i0!S{^_ShJ9repb{oR-2`gYeXFI#y{&}YZf6qHU zY#D%o#b+hn1PHA$l<3@rm*mp~udcCxIBW?f_(6Q;oL-3|$Y3Da8w~i60!w>>`UzBI zw16ccM-mK4@gwdwaU*1ZMnpz<*9x2n8BwcO&ZlV=8f0H1?^@4#aP$K<5yHfyIyW>r z7Ey;f9hdynM(82EQ4ZU8wgCP%xJ)t@9Zuowghp;c!W0gY zauh?kF-YEG9I(_6=wa}uD0mtL&!V7(%6rny(si@Ypx}IAy&ma*b$Ght8D5;zjUp^z zoHaqfV`ho!gg7XdvkO!(>;>&VJ$u^vsomzoYi_&=+ka|5Dj&7KZZj{Y$$}<=%PN>w zq#_RDd0wiS=;+DCHX?wAb^ejgL$lGyXvUa591OHdV-nrwYE+(K3+l%*TU#uPQ{6p* zlwMqp(sTePgrq=!nFf}X^#Tuk^kNI8K+!O2yZSp%KKuNOKY#gEYfFf|{D!_g3R?Tm zU%Whc6<>^C>RMasaDYWbHy%;ht-(c!!Z+83eLwtar?aI6NNlXt`#Ddua736IA%;XB zRWW4pBQ!fOUTUR35D=f$>*v5webeMb8uLUx7sq^T8W)p)Jhm5b(m)lLDp$%qhs<4& zz2JTW%P}LHn%l%sT*tw~XGH0Vyr527?f7M&~1A~~bMh}VtzTsbU^Ms0c zorM(~W`R|I@a-P8RDU;TQO($kwIt*L0{=F`uo~bO<`Ei7;Hc~pz_w{sDl`xh1grlG zO)J|GXav&oQBxX@aP7?#TlCVn$>^?s3KKG-J3NMl@)oJy)5%ib`y;xM#nG-|X&7wX zSDf+9OgD&c@^oAVC_zAdIky1%GK*nR6Fp6)a4s!>fsN&8Ot836_YI!z3RVDP3g=0W zkpf=`FYp&oLw_y2b__vuAoc)FUoq`SHg-y2CA=-^>%ZV)Ny>G+&9i2|8}K0)zL>%w zK1AklkreV)P%lTk@3Ucy@~H!0M9Qc;fS?vVoxuHyt%QRAF$kO?_Gb6fG1}No;co|(r9W9M<0n+yC31Vts24v3xpa&k z;qCs4F0sImFLk9^TwEV!^F^gm716__IFSc`-PW^Dp0=D7bAY$iBVnMRDU9e(+&AFF z17NYUv3&qSF3lkm(W2tOFh|hf=nw^>&^#HTr5#HX{sR-XJP@aBi7Wf1K-ivzzHZRB zwhd$CHc=Sx<<=g`XJ@-c1Lsj~O5KmyN~9p489?AX&~c|vmg^xx=b<_A;}qweX0}d$ zh=N-o!=bez z*L zDhbcdQ?wDNv?-Jlgw&-l85)oQV5zrBY2c%-zD$A^Cuce|I}||bE80oMJw5k-FjX+U zm9+X1A2j|M@xP)vR}97rV!^WMkZd6FzyPpgXWk<^MetHGr&%BPwbU<6YRDp5b(4>s z=E1*Xc9G^F2!$pECj%bp#WRKTJe(&59)+bJ{vh;{;U*sRHTKLt(g9(SQKM|p@HKK{ zmi);CZUMP`5oAX9Auos6k}4jdZtY`S#!7}N&R$}9q=(8CvHDE8De}ny^uQv=5BA|AsHyGfw4h9jDbEo6M%(GzI(XYkRDR4v> zu|Ox{Ce5;>m>{<-sau1A;?oEmw_ey}_XwmttTIVh$}=%4C?rUKqhK<@g_i*9LRDT8 zissL{1PdfDyLVKxm;uDeq(>dvs=ptQ$i0UJdy@eQv{Rblu#GR;5z#`YR?nVRh7#Gl z!_ym4liMOq`zR-@OI=dfrsaDGk_XW>&&FqpL?R}BO|Gf9`69%L$~~hn^R5PO~hysJ`w$Gfg_{K=cnBN zXB$!bCWulch5Li8lA?OWH#e%ly1_tOqPp(C%E=cS({IseCcDJ(rjy< zl}9x++3eB*jdtI}duRgz0ybb2r!rxn&a5_5G9~)u<*-G54I6MiFD?CYI-4b9G{&7S zg2@!dof9Ch5xc z0(UAxX3siLGtM6TOK9=mCG!mr@4jS_8tTa;?Z=*~&PZU#5;bfKM0T^z|X zh;bjmg1#KJIl{!OWgmeQLTofhS(Kd6XjG47S9^9})rmm#H)gqzfg)?igELxD@QHC2 z8yDw1opNT4%Mz)mgXSep(UJ%-_BtP#nmV-SL~R!oB%(n}9=z|8^=bvh{Jy3;6%A9a z;6@97Ki`#9jl*0l8;tJ(H!0d%50OX8xshH;qkJ(PBW^(EE^v9mN-JbPtaanPPBQEz z(JrobePk9mrL*N;tIOV8_n>Se#05nqO?-uAg}5V|i0QESfZrcoEl zSX+ibhm8c7^b=ayivrjMuUX;iK~D0*qm$3+Xk9Q%Vm<=1kC;50N@q}1x4^cd^)g-d zAtSX#I2=wB+T*V@Xj82O@iP);}K(wda+tsWhHO#op6Gd!jsl z8xDoP&qjVLokq2z)Ya`7`bPB<7oX5>hoYbZIczPHxMHb--Soc4sIp&)I%E_>r934-{6=Hh6=h@ti`hKvv?APW zo3zq_IY#!1MFit<;4%Kw-%($m^xNmoB%v)R)Zr@bJ2`$XvE#nS@zX1St6tTA#*ZaV z3*%Jm89$bJMGil13xt3>jH(MXx7-b$^o=LfqurptV?4uU0gnKrXDbCc0T}*>jd`vS zzrq>=Pe0;oT;dM7ha;o7A@P*Hn|q_J<`9q~ywvw!+lmtA76S_lmJu(np3$+6Q>ceA z8E|KW(iXDSHdQHG$$uZ4m%Ac=H!|?Kr@uNlryW(|!(+f=pvtB>qXb{Gv-^?fHLx=_ zWN9h@d+lOIenwE}pTBvF&=}FgioW=Y(8$r)2LD%mQ0AdV(}cAQ3h3X~dvGx7D@hgEntX74h8{1e)`T2`xQ z-4hWsKHPOth$U!Z8vCP(;0z(0LyOxhCIZVusaN$W$dN4>NCgu-kgo8z@v@Z5oXjU# zEr3Tgw!bGsJgMCnEmx2`{_zbn^i3-(ze&Lx86EGP^W7G##YXP|zv~bq#pSuWu^v{ieU{S@-QqSnN={lkvql2fJvm1x$ zFD{_cjfo+5r@D@eiEZowO(^x?#@E1#iN4P$nwIkotXuB@8!!!TS8+0UZHhA#oFFvr zr-YqVGTnHcq$`krIa^NYjuLeW?xt;XBWTgHmaHNqfTBk%9$iT(PfCYr@H-*#uoK0@v?t1j)M}^W zUSCtCp710I-9{(r`^8)~NBUrNJ2Zj-S>nRF5pE10@bikDL3Qn4F@Ltm)AKMQ^~ondNA)}}wf z3e6=UY~V_R5qi|3*L75yKwx$aovJc;Y+M~&>mtvmN*^gJg|w64|GhO~E6=lkBt=f) z2P6#hU{)o6g{Lq0cx7j#KhuVF&vw!E%Y=ZXu9Ib1S1rS`yoyWmWU^5h1ua>twQd`h z)XQzGG=DaFZPzz>A-?7-jYeHK)ke}Js@D{td*K4))zt_Oc7{N}?5qW9`Sjuk-{PFh zlIlgP)lz0%JZ?Ork){|978Djts%NmCcE!SvxYpT!Gcj@>$XwHgP3VxI>Bl|$+$HGj zWoNWu&%MOU$G}k#s)#P{$-Jsl8(HyjF}F#JzYjjwwT#s5U)XNLeoX3H2o+Znn~Laq z!sx4h`=s}t``}sDw87GnsjV2<*`{T^uDfy~e$NhzzPVj)U>qADxLfZvD*Je5KYss( z{9rJDK49&B>c9)G6i*L4N&3n`cOl~Id*Q-GQL2S8CSJCp8G(7n8wl$fGG&Maa_&U2r*ArjDLQwwl%u#qe+gZQds4`CN(x57Dy?{yeq!a32(?7OKuJ+`d==JWo+mz(SviE?z zphHHWM}QWXMaYishcDJtjHXcElsbMG+d+TlN$_N+-|CdcFVr;5FTZdb{Zv4%T-ZRQ8|i zE{a>Lj(c9k0G%|ietR1pzs;#bkmv>H@)0L1s-0%!sgfv{Ru^9OaO`Q;0W=X1VPYc! zl1OXPF>%ov(i^6nfPEB1*KbGhbJm7xE6KDQP#<;!D0r8;PV5pqe<7E*aVLC#n^94x zp7V*ARBpU6_>b5C^BUbf+k&gK>$4&~r|~b@UfgVQWy1DgN}n3Gm@qGK0BFXSNMEOG z4h*L`So_nmjaTp29dqR76@lsrs#}7*s5LG>c+#a!5r^1cRZ@VI=N=bJv@h<-Qm!~6 z)NN-}?A#&#Y2!P6b-GefK=Zs*6B@>F;JA*=pwfe97At|ixCHa7O`-+mX>F5FSWkz@80sbBh+U9xZv`NvRu-&@`N$WnI`Cd~7mcg~;ssn0- z$|^jHGy{}tPA1g&_gqI9N_`=mqA@y`y@%0v{rBy zD956+cuv=3a@Bc{85^x9-Tpl=76qSu_Sr@YO7tD+#2}*NedQ2Qnf$Vnj*?#%Qr{w} zAS7Ptv=L-&JtN0^05XLI2IsA$Mju#Wpx>`0 z5`j{AuM(cgI}_4>St(Xko_pNOq~nxun-WbmovR!|aysfz)3m%E{~VO#>GjW(V0v8| z0tmh0H~3;)UQZ`KUr)#7&*STI+V;|db2H0?69ubos!>h&XipN^3bDhXT!Bzg&mi6r zrd0CkAJz94ScLSaiQ&@jXa~JDJr~%9y_~aoa8FjpZ*s$bH`R=6Ou>w7UNnl>j7D0~ zc&k}=2GR`9-R0^waEABoy-irCv%jkq3!4C)Z*co3(ZG{H>7L{SaHuc)dQL~xnJ*nb zb|6)%vE{UY$4R4!bafkmV|vy!2RZHi!lc5cH+$VfGrBBC=Ztq{b+nIrx=mOK;z#_@ zZl=1@*GNu(hotCJuRzk2sC0&xn2n+fY70~k;U`814gB_L<_G5+;NH-1ao&x7Dq6Uy z8-g0j7rUc=Q%;}NkC+_OrU?hJfzcqATWND6n>B9SA6ZzpjKpipuD6)uAvIJr3|r({ za3!p5l4HT-Xi#ILp%1+!dsX6zOuBn}t{Ke(ndk+7k&byaDUSjw)UC~)6ZW8J)REy^ zo4A|1+Ukq>fw&)vmqO1KYfTq=6_LwfJ(ey-6sBQ3sv~A~jImb8sURr0S;$^tHM5DR z_MGgHDK~^}X|p zwzHCdN0rHZuiZAghS^muBXfd}CyH7VwH*ZOBKZJR&)H|81W$P1aqC*vnb4d)X7@r= z_Eg9aJ$rDQ=uD072vcklhwG~f3K|EkQe&@4&Uk0&-7J^BT0S=vMzx-g1iVNjX*JRb z3K8{#C1$gzQi0W#^5t}V{c|ua@n8DxXu%$T1PSUAF%R$Ml@P577^~}b9M~@TyyJBR z-QQvU$WgUGr*;&wl_#<}%^vBN4AX@}lypTD!s=6YuhgOTdsY?@JR{KnD5payzVMUU z>GFF@SH#p~WF*7HqSR?Spq57AKv=8`y_^KGdLRQ~C~p3;hlG#T48TWvf@IGCuYn=SZ87w}7p~;>rhd|MPWiepcSM2F;?wU3EkmJKzO3Mjsh8YoiOh=Rq zj{-~Cm!&hUhS$6jSavC2f^bRtkCWpg zSV%<*=k$N52pemlt7(wU{8NzfZqRzt$EyV-VEBOu#hp_#}1p;lbjrWt2w^m03dhfYon(FG?{#47E9sDYl6((tH3JlB~e{M73oj8pqe zbo-{G&mjQu4#!(7vxU4!!QQ}mM*;7cCmDfH%gBl(<&79GCzi(YoFRBsmRi5YgO9`3 zvAo&FAHxjQJn{T0b+?i_I9a}bm`)+jaj5Q@=|UFXPKHn1%ENnH{`ls#l#0jssERKQ zPu4NcQHhzJ_Q=bW@3^vRuLUcNgDSyhR`VG)F&e(a0ECoXsIyu`gpTwAOff|{cv%n` zv&N9Etx&|qDG(triEa69-Ml@?(440AQ>LHPWPUwnIh}NlkFGoQW4eETqSqexSAFc` zzJ`@0@2l4sqw|okPuo0wc@(r@jAonzOpzGRQQy0$M5&U(zwu;=07x9ls!R*RGEG>1 zs9CLBCs50dp=7;lZh1tMBHV z1M;dZs3s*hI2xsyfdv09qPovQIkFjDh4f82#=|2q?ua7bn8rIX>)ctx;#oa^rH4Pr&!*(3pjbrb z1BWY}OE-E}uUqi)vod(*YCmYzU%>|4_wQ%Z=lOUkf`FN+iCBvR^*xtq77uYLfSCz5 zOuXdo0V9oG-Mw<_>0`Tnlb1DczsGg)C-yux7( zaEC0=)H9F$u>AZQFbFv!s0m*;s333z<>Skw)$#NZvtwF1Pu24#9geDIt37vif_}f> z-P!3rflu&YXQ%(%>7l6!XK;0T=2JWAq$R;(p1$2STU1a`xh<=3&A=Ik8teu;J1#N6 zL!*a{lTLMi`_G$>`i!n>ZunKrU|Hn@b< z(@@@@3RC3RvGfT7=Z2N^Q;lVDy9hm=q&?-w)xkW7eKKecx1(;~b(I%AZ3HAd*fzM* zwpk)s%xjxVIFGj5GSS3#L82c<49=hK+f8hp7& zIr#pkYL2bAX&X33tWpwNMMYpW6){ae7va^O^quD-#M+LRkZSsaqu1~oLq3~D)O8z^ z!y}!4%1PZ-nAdN3SO)_3pJ!L-{iKls=jaSWY~;Fwo)o5nO=~qnkGSY);u=J2zVTcU z+(3`{=(T^dGttuewEVQ}2A`I@0bM)`VJ~b4LHi-+2#A8~CQ}MGCd-BqkDywEROajA z4b!6N8TIK=f0c2^YFXa_&jfMfnUD3L3@~(m^WZ|EjUmpKrfbWMgC&+`6?u5Db|bbq zFTtb{*VPJ#o94s^E4s1KAX`6WNG@lej?Z`btB9d#QBBBX(}~i^^BktG1AT6o(+`}5 zkJdp!6*nD|1Fk&d%$a-M#bx&`0IZf>s+e$;HQVN1$I*?1d5f9#X2?wjPp_(KUhY1B zemu@cWp7T7)xEs9eEj6`G`%R|V)>X$_O7bg^x1F_aEyPgs8t*2c$|v;QyPB5S7b}t zg^M~R6~7b1;YxI;cduSOuqtC8H`rf=&eJeBXgpfLljeOGlM7)e$Gm{q8aqNH%nVlL z#(pJ0@}STTaVMtQuq}7m9;i>B%BqilM5SXPp@bL`X$FjbOuG;^Q;*Xl_HhJd9~>rG z9K_K@6i%{>U=)p`o$c*T)ZgB2`9KJ?hPUY$gtX7LH`vvofwrSmIBVA)1?`L4qccDY z2msJA_;c1C;g2!?16{;xV?b0*{n+l~JHL5>MH%+aU0-M_(=%F%^K~q*t8{dKJxwsQ zb(N3usiB#G0~4lEOB&;IyLV6?Rf}toCG5+*N*U|GQi~Jm9A|LtH7Xiw*HNoVvGH%< zMq)FE9?=gs$ha94lM0wNwr*G*-2oVZ@hi>teZ4gL)=}X5H6!PyP^gWDi)M3{Y=>vY zl{Xx9vr726>WJi4vd>CHURgqawAn~t4tbeaQ9qdC)lUxRYBaMdk7ej2s{~f0Lu;s0 z;MSW3<<@=!TPa$D6v-t^Ug|NF(CG$jLf(j!sJEow* zY}&A!0cJ3{7Huh<4-S(kV0;d~MLb29G<4>dpm6S3-_Ym%!N}_-f+k3R3$Kd=Qz_?# zNI8OI{W0YY9zA4pRe-of z3xE~*l&m#VV1<>PnGbU~e0sY79D~;j2cmLuc}eF`gu_SXk{w4b}C(fmj@O(!29g)M{X`jk`fDYWyH^d4;ETb{uK z^hMd@qZ-?Rp(?iOuWMvSbO&AjIE1%3 z&L|rQ!ahN&e3@JX99&4^Ia_X~uw>>q}$H*`_af*IhW z6lvheWP<&zjaOoSrdr{r<47d;4$T!Wo9j?wT>DW#TbI?{1)1D6beNVH_c|M^-jfq$ z>5PGg0A%MIME4mz#)nu{>yn(_D094Z2&Al!ZVwKew6?ouS4Og}Y%!gh;2#=CPN2K? z%e)H$51M3x4=78@xji?L`OA3C2q=f4;F4Af#nGDP% z2v_YbncxX)52!?lFfdE)d&I=v6P@FW)O#7-8?rz0esTGneMJm)8x)iw$k@-RjHXew zOI1T*83bj2==i20vcm&PNVZRXG!p}e4vHju*7S(i3Sk5?(s0Z|w^u2gVET@q%D?=v zvUv#N=*Uf;5%Asfx{Af^x|RN+j+DZ2?NWKb42x4=^>iXpwkPKX&o{bhzlsMNM(X#0 zWO$E!IRh~XoM{lC`!6N}iI{Ex&`p+NAe2VTx-OD`@~FtmvWwo{uw$XA?8l(j)x;`u zQEf)4Yspm7s64b;^L$1$dM?k*I-R$)7R9UBQl^R$>DI;^z3)lyb6V*jTujq{B%Hn) zlSg54U=amS4y0U`Xjv-oe73uDj=NU)B>LP~2ErK}`cMrhhjU1M-`jRnlMgsl2`m=q z&X`hvQ=_z_7|`dvZAu6ZkN{>fr+E=sp)ZyWp(uyO?vr{)kxsFb(YA0`=-RiVl+qU6 z=4Ww%=v4UY`Nq-ZwjR;1ZohNJzrBHe&MeS~uyZe-s*A9?hyp*NI0dk`UsgT(x3h9& z49bc=wLx!fQNzMXGq!5wtBZyqNV3J`kXK26i9~pdw|ciS>m7Fw2o|Qjp|v0u*NsRc zBCQ#@8y4--_Umuss%ldf8@fBZ1;Ibh+Gqe`K%Kv{0%s2fFi*00T48E3Q5P-#xtp&K zj}8Ve4`024!F(Z_IeZoDAN?(Oas2Wic=7H2(KiPtQE>3rgQMU-zCSsI=WpH|9G#v7 z$M1sYf3NqCz9S$|ieS?!Qs)# zA++(syZyIs58g#aXWn2#&kuq($MEy;;N>UqAt=Zg2PDkyc~|95M^VE(9^mMy^nfM< z%{LSP3ge}J_0J!v<_%?3)8^>i^t?Nsf4hU$e|u0toWkj>B#+>!l1BV+R6(zpfuBah ze?#uMSeE1&L3=vsVqvcoL{IxynPimdN=WD|gY%XRRitA<>#50U6}45yi-0OMl5nzaOqrSk7~(_u>lr5~BQ6SU$y;72z?o zSES>lw3JG>3J6zUdnxvyu_`%s(C;W9RSzeoV&#PeqrsQgzJZD_M%dI(+2vIlfBbws zZFK?}BM4s6rB5=!Kky#^K#{rwtj^#|K5-SgoyaaxM!57cODE|l&TJlB%jDUBbC}V} zxe@z_gY(~4*?sd=KhWovH$s9j40JEjPU=lGWn}v$;+uAsi@cRff7~}_Q?f|$7JzZ+Y;R(uaul$X(P(sr=SQ7)-O??X)PZL| zrlfd$Ln+EwBBSVtcB`x6S|9d!)ljHswkk0G4LZSt5$wTm95Hpof2B*|Uc$y@^0r7A z6SV=wH+hOCO=CE~#3+hMMHw){xAH#H2KJJ4&!@%G7P&TaNPfc+^`s{<>G-_&X2V_} z9Wij4i8Yv~FYSn7O5Hm5Lx~Gr-P56$R*^|VEoePWEc0cokr(M@O6FArPza~@GbKi` z$Be!wlz@00u^Ui)e+2l3rvDuusPFVvBdk^2Xnqzv0qbFZd*?IUdX#fV>${d0{+s*5 z_cZdx-PqjlmTFYL>JF%{j&S$+cR_!9JNV+W?eBt}&%b!n+Q7>B^Zw3ugw>+pi_brQ z@&)|e`QppZo_zk<=U*67?SY+H9m#Jv#Oob_0}g3TvMxWze@6|IZD8=jk>^_{qd6`w z>{!oSROWkUJ9c+yGaw-9Q8e~5`508_zsC&KL@OLqHoak}dy7qmGE;iM(#t#!xtC41Va?OKRfUy4{~ z163`xL}0a^Rocn(7PZtQxY^wpu6)~L@J3@U>DWQs08j6T(;h%Y8&eivc}{f3watv$+fW`f5s!>vfO2H|$+UVgGM{ zmk`;DYts4nLTp=TCwD~=t#EG>%F@)*YQz`hl}DN-w#4d@#%VZI9e_0g?@8{bP~2!p z8i~_lm7BoEX^AiWL1JK@6i9n|2Gp<^lJxqVTZadUBZ2_b;uzVCb8-Bk>5Bq!W+5); zfBGw`{%{N~z*g-QJi}!%AjPmJ@{E{4v)?tlAJrwhH;!kM7*B5?IrLi#6=nm2CrhQOQOnn^yL#&F8Na+eU%Szo(yrKOA5JpE)_=|Bif3AB1t|}1c;-wB zlFZrjo^8d@<8P@qUh8ZoPKE4UFPnI4f8GpFGLEW&Q;4K3-CAj<+U`D4{-&sswUdmrBk5$xW;Oym-L;}9AoGb`VJ^hd5SJ8GBTe5#n59yO5ol^e zO%)Ou~jPrzj4rI(f(IpIFOl=!Nfpib5Wz8~9Mcu&F zk(db`iR%JIbT~N)1{6&vwlPC_f2C|B7MV2kLr3`dDv8G&>non3IsgDf2XSz6Da4>u!xlMtWZQ^ zmSNC8(K4)AH|l#T$UYQ54+5QWQC0vpG9B{`Y?j~BU?L83#x!|P1miP-f7AYs`0}Lh zzqo0-UBNsuhB+c1WW$M_QO2v76d4wNRqhkqOW zi1nBf7bmc>0)oZfN2TggfMZ ztZP}<_V(^-S5|wP%tPP?LpLMM1LdI+Y*+gEE7~_OgLZ-FRVp>|4$WZ(NTUHFTE&&v zp4uTYwQzCeXF{}he{7m@+p>)3oiu_Ji6IWj65by^6L(!oz0T(^DAp9lnHGW^C6xud zInmM_Mla(~%;WzSb`C4#OCKks8lBoeq8ORt(M&vqk_}CVL z@g0KomO#p3x+r0n2*DstK*nL1e4&z}z%#8l(HaH2($&;Gf5h5__}HqBtOUmxgz(U~ z#e-*6C9^r{)?qm@>D#bGG&>zM*?>c1^HwTk9eo{CT^0GQ70dn9ILa!$e3pwdA)IzA zNSbJ=?qkKgch1sxjljvA(VwEuOu0=H>@!bG(?%aPcNWu@$;Q zZLHlqa$SNJK65oYfx=lCL8dr z3cs$eb{&ZVpidJzrX-nC=GrLcS;OX^>I%4!WpVU2f2Rm}x1NYuSdVPFS0fWKc?d#} z7n`nL*^_UHN}U9!T|H7>gfw`gOyuY0ho z;|^=~e^4kSHtDmSay1pcV=^Jyu(bIqtcz(S<%{8&7^_V$;Z-cg@7kdtAsw49Sbs_W z-0+r**#&&;v5{vA1$B}sV-I7k=x%d6kwqphD8c=-k=`ni%;u36hD=TonfLnMnKF6q z^VooidSa;O^*`EHtT0UM}f55O5ET_KSFMT_uRTH+!Q(4)(N($Az zkb7Ali41Iej)``}CbxU_n|sTypr-0W;tutwaJiwj6IiJwP}}Bk)@fXUR)92TLA5$F%E{V zM(;DXODiiYl|bF2P<~Q%P3VSpvmYxQuJL_bN6#y3H-BoY;GS^&YlmfU9c)ze)e0pR zQ92ZVjJyp#>ldf|+9Se{C|&svc} zvyS|iFh^tgzp8}xdh(s?uv z4omokLWsSja3pwhRQA~75krB5@K_RTtxD;yQm&{%WAIg?7md{hI6B(F>J{bSt#t+L zY;atRlOh>oLQ{VXT|us|(n;PxsS?8$wL(MbKYa6iZvs_wjF*K*w|(U{e<5aL&NnA$ z34BAMR(-Y!+gD6zy%qHZ&j^DbaOmSv&GR|tod}(qM)xDw-*?G!g{nb*I9j0lbnOb& zo${_y1!LVx#m}16il2L|SXJ$At5#LJ`^r^S@4R~Lt>)iynL2wDeqbF8CMhM_!n~@9 zFdiBwzbumQ>|FHcf7ptae}i7XsMVTPb?^sz;A32TY^Vq|O~y#fJxQZbw9kR3cme@?*bhI(@Y5VA2a z;JerGSJ0DP03+q#x%O;33bu9FN^Dp7TwpQ>g@@@<`dbJKcMBQho}s+>m03#A6<}`@ z@*ZGJV1Plh5Zz#42J9RVnM`klaZ3gGMdO!zf)U`P!G+9c7LzHJM!7n%@Nw#+-PeA5 zcp3$74o@)95IU`^e;1tU4sUV2jhH}DuX< z3&PBENt12Y`Nyh06H%QZx*8(9HA+viuf~yB-nwt*=ygY3<-B1xcp$KBhP*Hgk0P2k znOIK+!d$`8ONI6b8tthFaN$GvMOML^>KSQFjqwNTt%ZbBe+n7N-}>jm`m?D?-WBRw ztH0ItgaC`DfexJfS=eHv?KD>!5&Cz2nVzG0%*^7HPn|_$tD=XQTvzvN#o%k3_5YDzwCGGFZykv9y24*lN<`FyyALNXW7* zoAODOkdA$Z?q3*NdYZfsE{hnW=awDXbPN+c!pbgpkprWrYC02He>PSqQmn=Fyl0{TT!4U3+UDWi zz@0UCWV)=u91e#acu48;lufnb@$(|TNymwkB$dq7863?6MsQMoSTyzA?$-#GH0r7J z1t8a~%m&ACfJYJ%K}Vx}seL0b+YSs-0}I>GFqi0Lf`^tHoJHaGJhl;bN(o5kNiv3Q z8BIOOe@hqeE3%=&xREeK*eTaTiXWTsu23W?0aIOW8@=XU$-pH5y2RZ;;zrqnma2Co zGnxRG`9kDDk*?57Q4JuU=G2iJ@)0zUK1s++Bf{F&jhGltFhkE(4!KN0Bk(*b1UP?w z6N?25Z5w15-bGTXKo7jbVw47pZBP^kV^zhle+sR>@%RYoYKYccHF!P*0XvS)(|K=j z0|zQ}esplo z+o(&tN3pxqFN?HDbmSLkGc9cIUI3~vCk}+4wb{9#GDaFA~eE@P)v!jxsuHO z5YC1}o|S`ajElWvjDy{kho;XkafA6Ze;uWjI3<=G*afyZ^j0Q*k=H$z^}Y+Z&r!3? z*x>bEJZUIL*<<+HuQv z8$plp_9SptQDu# z+8#G_HA(z!m|c|NP#sG^v6qnZqhS6fSJK?TRZ5ulkd{iqygT2no2ttx^1Dae$@Z2J z40R}4Y)C-}HBa^wUF$}(+H}h`{ejWgbW)Gt?zzj|&^8K{Ea)`GG0M8if1pS7hh#w1 zd`7G`FDX5}67+bV<^U{|CCoBbaLhexL% z8US*p@qD$Ya)O&cjl4J9J^(G(2){$DGFEJDyQS0C;go#({lXt&)1VDf1iC0Pp*HSeEH|E zrq@50lkrzy{<&q<6?vTrf|G`b(rgi(5W=E_T)WJK-<_U8`2vQ|{vVrY2knQ9_(wte z@9l>nfa}r&k8-hIg?oYy>+7P$Zh`}=!r$>z2jSHy{{8Ru(()r3^uBW;tSQ7jUQ_69 zAk~MFu~Ev7MjZF-k@YD>2g>w-+|aW$ZK@VQkz zhA)rmcLU9L93oNcYxEUDD9so860MDChVZk*Ktei%ni#EUf1$A!bV6)btF3hq&i&@b z8SZrbaOH>FTQ>syG$YxCw-SZx!L0AnY8VZ~^8c+gtE5yYn3X7m_(j!bjah}+u{cuBoK*usvQ5q3_BBue!rK1tZT*hq~-I4`nggOmTBF*1V8Rvq>i#mG(D@)!X z(%tP?#v2l{p!0TR03s0`s8^-cGzr~c#w`5-2zLZ6e+u8my}zYpfO-qm(Tvj)m3OEa zo5kZKxSZxinlIqsu$ax*W`?d|$_2&HT;|1fZ-dMON6_A3Nuff1;P#Fu!7;S=Qn&X8 z+xtegcf##GU$VCN1loftf5Y~?s|%O*9tJ3o4=}IDfh8O~K-$4nCn!!7H!2V)1y3w_ z`K1}>e^6Ous4zwflBiR~h{{MyjOH=g$CV76N&7h?)&$~hw>$&1L&IFx}>|8$xX3%4^1}aX+`<5p*I*FkaP(`#R5C>0#jU$ ze>i6)?z9mApHA~z&RP7Aq{vl(OMGe;wWH-gLj!8S+7NpLAI*WqZvxV=*+~#Riy&H< zT?ZwVEI2GE<%#A; z0Wn6Io`^h!oCe);YLxMz>!U&NzvGD3e|o}Ti|a9TfF5zMg#40 zo2v;}QNWPkFTsJo1O=btKNbY<5^Zwovm8awf@;H^(PR%nCpiCutr~0BYZU_+67$wxq?ue-(U_ z`6V^sa!YM`#dqB#;$gv3XNi&5nFhGpfX$0)Patz(Uz|Ey_S_Ws?Bkw}Yc3j5;Zzw% zDlg7D<~_$W&3hPO_;^Ao^}<#!`g-?q_mltKa+Jl)Z>S8`>hZ+4Q1<4$=l?qrf`5Y2 zI%eO69~Uv2r(=a`fwqO8Y{XRBe+U(qIzhxQ>W2bPPdqJ9>4wnIG-;N^k5ZWRU?oTJ z$_tWg9C4F1SeCd4GPBDMYD7|B*g_R%`WPEM*NfEGpb?F2Fo?%v<>SO6OvB>C7&gS9 z)QRR%fF>Wb9=qyfD`lSjY&`5?r0UcNK2KYj#qAV$5$(L>R0W3cBr?bje@m1K!~$7Q z!EA+}i}<6_+5dcy80O2cXyM zN!x0NZ4T%WQf-9)&>Q^nNdpnvCmo*1h!TSPk8wQHHKVV3LfcRhh1nEd6L^}lfVnN+ z#s%I$mOcCuwqC>;LK)?=e+$$f$$TSd27ys^KP^4}78v}FqR~=&4KWc;D4o?0+*-sN z7v)6X+p$@f*!``1p5oa)o@~zob5WcJ9dp$bA7|N+mlArd@goWcLD-EO5|RBe`M>+* z^N=68(Ow7T;=-QsjVHXTCOq=8Npa~+Azm<8?H`l;yH7GsBg`>if4?^%NA45AI~naz z%hpn_P5kCdz5B;f|97SW9&)#~)MtySobkJ@^oPbuk5QLV(#?rVoCpP;*clZK%?uTI z6c~Son4|eXd#RF_1SNNzB{DZ;%IcCh*y+mX`x0cem}4Tk5>6^pwp<<#|2a#u2!zw$ zpc@JT8|oIx$4f9g0;S-bdjkLJ)uasy2c zN?pW9?ULPhYWc2`c=okO3RJqOM!n4@8DF}@c&JKeiy{C^mYpD45$~V>|1g*Gy#H-l3}|j+vAjvQ~2& zW=HnmNWC(=fkE#6&;bs#hKTh7nx=d|u;v>bLr8e2+IzIRd)}$EkX3uxKle}%e%4V? zeI|`E-95AZ20B7s;TU>>Bq2<`L3_5?9+pAd+MU}Rf8@3OX$faj_@^WE&?TIJ^{$PU zf|2pFZ)Upj81~+$57@f5@s4fPW}qW@>XIP0{8x0gY-rjRcVMs0l1nyCB^S+>B{G>a zu|Zp9g2`ogrxqTcn)cKaS{*0l@Wf?MN&23Ebj zcCg+&1Yxu2>$r)(yY(M{qPpS?A)h}q`qH^mI}NOX;BN-S8~J=aZZuvt?oY#bUFjbF zSm!uHs;?d3t@w^Y{^v3#h`hM(LGagAs#4M!f4{<|{l}s2_doP$Y_HSteU$0`qK@3j>Tvvc1W|I?}! zjn005%M239%x&$Kb=au5@8l( z2Pzp3u}Rkdve^^cSfasJDxyfVAGV1I8;xNL`_}46n-5IQ z{HWD!)ytLns7yv#?&QB{Xr>Xa7m(}XiOBKB5I0Dz6k%D-PGZHCN;IRY$QrFk6jLbU ztN_9UU{2GxoS&)8;Tp6U*l{7F^&_~k+8t;;s-dwx;e{d^) z_Y5(l6Q}ojT+<}JNpzmg)x&$qk-m6vn4pvV*I{_K3V;kSqD|{CfRJ1@rMTEo5dA1= zmx0V3Eu4sYI(kutP9YcxD96;+BI`MuS;FrN?U+T*MamR&mX8;Bn|HC`yto$$ndY*Q zUzr0*=|OZ$v_U5or3|g-M=w*Ef0e1UmSnam*Rrlc`AensJmRWsnt)^A+eJDSGa!t) zOze-WRH*B_YPq;j5uH&L1F2fz)WUel4gX*k-C)pGjGfh#rUxnqscxh&oD)a784k&X zXgDm{kTu3TLqUIX+THjQhS{pn6AQalQO^zZL}HBwBE9rfq@_e^=d5UYf9!3b`e!VF z6?D|(dE~_&dJJ^K#YSh>0S0P{pn2TJ=uACoO6T-T7UM);KkQ+ z5ef9^u*qcIE8H4|Dm;Fhdga9-i_DuO%XUjhS1r*GS**SbH&rw?F@hns=%5qSG}kp=`_jmdB-adi z)9|xMhM1E-)m^vOkohwd2>FEDR#2XT08@A@g;_Jsjnure~MOc12d%)1>M%& z#Z@#Ae32468N*wX=*k+W1&3d34#`E40ZaL77|=SN(QU-&_`1hy(FHeR9V47M^1#f29QqxS~6x8Sx(muF&;4N;=yN~C0iCsKSQ%$ZZs0W*=8f@_YpfgA21fE>+W+mpHjLRs975rq}LQ6%_s;nI$yN*$PQA<#2Hs)6A z1^Z~anB^h>t+35B@J6~9LR5+2FQFq>i&>m?(Z-M1G9BK9udab5)g(tg#~bs~z#7Fm zQyo=YJc-McgQ#L$-~weCSVY9gq+}DBRH9m;UW^J3f6PwKNmn}l8M0Y(3RMOK9a2<| zl(aU0#2>EdQezh1OH}}^ZX-(sutmqS=)+` zkt4|#tSHB^dTa$!3_>GwK`cOUE;7wcDji&!e+rYVIA?UqSZmY@T7j;s`bQe zdSy;lQ+l%?>B;`XKigzy$uCVF4&HORg#mwpS7LBTpmffrrC*fH5z+LEe$@`ocT)n+~e6%`dyYo*oS-fp;;@+X5f*(yso8e<)UIO;ssf1o@| ztZC%E-bKs8oFY@e&ncqDpwrSJQKbjoYd>gvR6rQ&{^epe7lr9GFYegHBh1eSk_t7% z0s<7vOAe;C>RNZ5ynw+cij>`gj5UB^py68XFgNbV1?_lvfZc)oFDL zn+OLV|0RpdXhZ6??IwVHxCMs;q}ezfaXu*(CR$!SNVg|!!XZ5#+t=JrO2?$tZmI_$ zx$ym{**!_IjVKu7OO>grCt|J> z@)~UD>C9771);!gsm} zp~0_#S?t%qCa>T0Xtry&9`*Q!O^c{;0o@&`zDumt(@oh~e+(&8xmmJc&e0VSV$aU} zCeMUwkH+n@oW~f9K^TXqHfXzxgkD}Abf@WcLPts8@l7(suxQBy;#}>gpNyEnrP(UJ zdBRPZtRgg1tVl>je5(QrvqdpyH>0u301mi?OUi2(?OvnZq8Un;PhO3R8kQ~gND!bn zv``9_+38%If7*Hl{R%rAF^+~~r8&0S69V#z7NrQi7l?RavW^A`LXQ+xt%%P`dbgfR z$;p!gi^Ch>Flw4Y*$uIwe@UX?UmD9@T+$uL40Ihha|U_;$1sgV zDLxwUFP@bPM=kSt;+x#nS3tflb`O4haq#x^@c2k~7Ak(^-l|(0`5`8#l`h_Z1d{En zpCAuE6sf<|20$U>?LO#@R01;ihEZ1Cya*MAuD7+d#fh&^G2FR*DKSF@n*@a$ zm0d{=h_gRZC1W62fL1q4j_w|@i%mSejh7{N@$TKCcHC|`Mv8Rj3~Y$XI(O)^c*$xc zdg(PjfFg&OHka;rm1Tt-=uuAgIklmRf9x$JiPAW;1a|%V4pX$U;Xp;{k2O@QNKzED z5)DjR-)A%!(%jNuTaNJoI-b>&2@pRX=fX&)W&+B$w01VG(5Y>7gnwwdlTxoU9j81Q z=yDKKl3h0SiVZsiE8&bs2`3@9FQ)O8o9~vNsZ6=_^L+EFlRW=02<=sQbz4|Te@xCR zl(S*;?gC1cbBtsU5m|ysF7pD4O@U#_z{5Qa;W}B88KB}TAx9~rhZk_}yOzgxWbvFq zp)&FciK7eOOPOtc$ABq9p4$)kZr$pMxS5lhqbV;XF`P9^iRoj{1m!94TIKXJ%B?Wf zpqdoCh!!aN+}LfHajeCbtQX`;e+SkKb61N)u5eWZaup{SZp3_XKTpC~n&;4)%X)I|YDf3I>%$#h%~ z@D{YFx}&rhEij^g$;Jf0vrx>=%Q7XKby`?Ac{*0+jGR^kbz2PRU%_AIMUGZLAAv1n za4Q`>Js(lrIUhOODbj-=v{uXBUOy04oy2W*pN(>ueZA9hT~~w@h1v8hkdd(-KXexv zyw-}7t+l@BMp?1@2o`nkf8B?3GYIY)*?}U{O6ls-*(@2Sag_il^MW&mQ)t$e%vljw zF9=@bGnjiO1k!%GQRU@EhtV|UX46V1t&a4B*0#}77cm^R(@C4cxJta!qy21roK2U9 z_^zj+O59jb;ne&!j*NcLHEXRM3pO{$--Gvi{Wj*_qiCw|AYASNe{X8b(4PAvocJ=R zZgb;8Gtbxv6R+S!z6rVuj>qFvrsb2KtrC+wIVOtIG1McMNxlkN zK;>`<0?vJ5REVU7v$zJ0Nj{!m#Tj(8NJk|`=^wPrMb`RXE#0k=*eWp$Er;D*vDZtJ zdoq2t{pmg8kD5MOf3hvdQA9jc;tTyY| zaQyD&;KjH5?@nMDOB|PvT7&;(h_NdKizv`Eu*We-CHCv)v@CguJ~c}os2)*3{jo%i z_j?knJ@2soN6Ir|#J`(7;}ups`^$f+lwuW;M2247;;TtNfAX1Up5!YJDaagQ&7`J( z)XK7>r&+j6s!%_0ZPM>6e^`U4-8h7Xd_p;gYl1>>F1xN|7Yikwn(RWKkkS}CnY+6- zWJ9DmtF^0}wVZA>epa-L;YwZT-Tr!rp17iSlApXmEbk`((pc^-1bU%;@QmDPCRRkp5yvbQP{h7i{s4Tn?>cm($*fj#2D2e?U5T1GVX;>?UJc;IdH zuBG~rR$`{^lTwv&gcSiq`P69jt!nY;__S7*qgtSGe?YSYr#*e$akpN)dD-eXLfL3G z4&Zt4Vm9t?w^WP+c!UuSj6cG{Bz%!)Re|XSIE@Q;z>4iu6V5sxrpj@~QPWO)b~wX< z4$l3Y$vBZT#(Hyc(9@nnw9c5oMNd}9QBntsLAhH}crYv9QHJ<9d*|J^MtXIp6S#Mf z_vK^ue*%@q2k}=gQ2HxN1;8^(5#r2MDBfjRsKd(rmc`xIgVM0xX+6|VAk7P;;pEW- z%{a<1EvflH7rTc0j+?khMTEJmre09~z?>$uMZS71Tk|Eg9m?8=gSS<|EC(b~0^YP# z8fP~YkHV?y;xMSl{djH|>+7R30TOn}a9r-%f5yjxTbsq-zY(odbhvI14u{fmx{o%~ zwfr1%E@rA8AIkY8Gs+iP#rhuJ`KkD+VMk0(Z*kq~nsyFpWNdCN$o>fm)pR2!Y4sy% zjPMCE7_}o=$gzj2Et$#HA}`rBl_tmz1ZHAYm|h#hzfEN3WZe{Oo|kC`B!Uf5ur=|( ze}*NK0*?$u7JRgil08@+3q|F##)7IEc?pSQ65;<87U2}iB~VeP_ugjiAz~OA3!}Av z`U3v<&Hn!BH{a|VZbr3`Lb~LSRFZi~c-FR_V`AWcw)H65yTRGnSLg7wEm4J!+E%me z^WWAr{G;2j@9M~b8icea7jvA7zA?3(e+^9|A24Pe@39q_Ic>nqX%l8PL5$HIVnkBB zlk0-Vw_}WN^ZDlNr>dftEMd>W8^(OMPTe}-vtEFjB_Iw0kjtD98XJSE8IGaEt8=7DrCZ@u+fukrl2GxjLxdo&u-jF<#` zl{;P`mdFi{8|UZs@rc@InuVROr6a4J!4k2ihg<6^^5mi%#0>MS53@M=q4B~`5h4jg zP^={Jg`!lTOSljQ^+j-*R6?44DZ+@brvk4rA@Y$ZN4f*9PJu%3X3Mxme~MXepl-dq z5ct+GA1}=ts}LguitxpfTg5cV!V|C79QImx!GYkUnw&vF5QifnM3HPvr5P9!tGa#lr@*6S~s_7$mb1j6R4M5~?Wm6dnrGTe@58d~Ioqs1Su;Apj)A583As z^W8xgDCv9>Y{S-<#DteDe^-LM>?c*`z9R7eDv34sg8j_QXrH_%KLU9vs7@Uit%^aU z=B>ZD9Gs<>S9GUKVzHesa5%)-5daB<^q$p`hDCtRm`!h(s@QgsBm9a>7sMx?5Ctmm zO4OtmGt!cfbyYB^BF-*3thH#>GBOnLxh!h19GI=rLk`MhMrA4^e-X8d+R?5!Dq?ay z9cOLDP`UkpT_KSV;K7eVjpf$mAV-9%tMf)u=VKr_;zXXJ%OI+a$JjhxUH5`_$t_U0;i-&~{o z@*=H<0Y`YeNGc!`I{^0n$&157LAU*#FS|RRe=au_I5Weke?6lh@D+>%|1M_JctKB+ zY9!r@bekA1T(pQ*9GkQ%TN8~_xID@Mx`a(?IlIWGs7*o9y&M(k99@;hX$)ThYK-sv z9Z}o^2M@%A-Em@5Q+GOzr{V{aA({Ifx$_y9m7aK*cs{i9w({EB?(aPL?DH@F{N-0I zaulMc%$VS1e;1y1JZ+2E|I%D#6wlKNJ-?8=|B)0qLZZB_xDytr@zPfyTy{WktU#Yq zPZ|Z{H&qVp4qWAB#X$yecQFk(L^=c6Cwe6oTvvMu%KCQGkzu9)rL7i$Sz_*4l5VF+ zK+;tY)++~riHIWSWbDGh$Y$w#+g!znzf0gm>#f7TfByLT#mhG>8_7Tz+UBK+M9RqA zf!dKC#a}{qsWwevmH{%uUY`!Pd)pE7F#Hlrt*8uc zVm0d5r~a_ce8Ys{+@H!0qGf?}DkH3na8>Kqc!@8s6-{upe2i+GbrD{@@;9bmuWyWR zHf8UQe?e47YXJGXp_sG*kiRV)>DE0)3hJe3N&Q|?RJ5jkuZ@xDHc}r>Vz zbva0S3OJc0@&jMo!#{T4gFAR5s>JWt;aQa(f4tfMad3Eax@E5wlqS}+q9t&D$N9Zi z`(%cqwBFy@ZfBjgN3jw#C6nK+v9{qq%T&NzP>(!BNx6lQbM5u%J94kRZ4p2fIoRHI zJ+!-zxc58_Hbi+Z5_P@VI{UOde}o#cK~lnQ2xt4t4FU4K79jl=Sbfhv0rjo8tT-CW=MM%vXS_Y{PtN6rE8@cr;g=U(==}y8Cz4sOEYs;8>Zh~wJi9R7y8gC=%opmk1p6&} z*YrYE_<$U*KsBiy=>{?9uIQd#r!%XySixG*43YY@v+g!Z578peZkSGsXur3$BBlXV ze;8dGU$?~V&Ubq$2Gr^+1oN(pe-~Un(J+KkfZ&R*aoFtAz!eg!Tbr*tl{i8-kYl%a zhtgSq;7V|4>^urzW~dGvZaxATrQL3qBLyr?b?@C7kpXewsPmc6ALwc5LdfnqZ1F#A z#`lWmJ-KCcx*XWAOYhy?*WcZ$r3@bfYJPF!Wj}QbkiO->@-$g&lOOR^f5VXaR4Ab9 zja^j$O0J#8$q7p+6pzyQtBbM`mDs3U@SW)>q@Gqe5CC6cy5Odph>*_8ciQk=R-HN1 zOJRetEARWV+zsXA)#MsA0tDH)Xv)JkO-hZ*_Y0!w<^b)YOBZFX(kr)v*G+Q%97^)F zfEr%>z7lMHjM3|}v&ryhf0NUrnDs}))9B6R>>Nr*Cuj^r+54ic^Vw`#Y(99<&w53B zN(I_ke)izu1E`TF`Q-y3$@y$N+Bxa+(C%ACv4~9i(IjtUJ0=oQ3W{e*o#AVRlau(H zH(QjL1JgR3oHUfRS*mQQPE!u3lYij+o(#?jaanBugaN}QbIj7ie*=`)4%b@8-yHSV zj@n24`WJ25n&dl2{a+sa+GyeLG4$vh9vt<*;RpTXQhr(?D(*s~gUv|M zkUUwk4{1IaWfwS)9{e=Nz|$b4KG^vDi-%u*_24|aX!Wz!Wj1foglM6wU5nI!Ezcb*wJd6fyRE+;*Ceb+NCPOLEjY7O!5Y4A zaZ0?<@hR{TnXm9q*W&zuqX>(sASDnafcnOe;L435dnB1Xe>Rh>F&4(?<2b++pd3x5 zH7wfEyOeE>c}eK%H(eR35=G=T;9$%~$wX)S#RggT>*VL-=quQ#iWC#X9%+!vDo=aY zwMblc?<-rO?utsF8lsz;%!hPD`TiOU9p9aIc_Am>6!xl7%koSWqBjEOgu zM{=sKtdx+0QNmS^qqlpK7p0`d{g>-ISBNBI@m^Aj>R*1bmw)1oDBo@+gv@m`E(^3R zpL%v%pk*#@S7h!@?3aCygc%hmR{Q@`&4?+<%3-(_?V1yq5! zJ-u&6A5entw}-QI40u(Z&JN$BG1rIC2^hY9@`2ag&~9?#wK^L<@Y+@UQ`y^8AImV4 zmc#y+9mQ17i+}m49BMGqV?`DQUZBi2g|AF7?Oj5y0xaBeK0T6N@?=tw7;h3S`0FX* z>q3r#BEmH+F2n|C99a4eRtTyGba8^Af`0z3ujhQ^P(YYVj$Uwg6J`^tMUGdnKMdsU-6)fKy@P_8f$ zP@s&xNw{)<5)H!bA4}-JSKr)@@J19p$ed$mFFmsF2mB!Q4>UI?0*L;P?C}0Ritn#rvOvBLGnbB)G1WR zYDS2Fc`eS7^S=Abi#nyKtZ@qC00?+_a?)5GRg-_F6`f|;C`~4IR+o$Ol#B?OER=H< zBX3*qbyj%JZxKjU;F{7xr(PF0Q-S_EAE&~`hU5F`K2PTpQr9r zGk?*W0tAn?cQB1m>gGn#)7?f>;zIwR&8YThj0^KhM!g>yQ!9J8PfqGbGm40W-zM~p zEc~qC(&3sR`c)~se!`QF!%gZnOF6~6>rX|yNRwPSm&Wx`@ne4w)ea<9nkHf`Dn|Vu z2X$+c#S_mc{n!mO^vf^xrZb$|^h=VNi z?Ru@;d9Jr20hmeFYHAtRYO>-i%G}Ygo#^?8hxHP;`tfnqd+F(d5;j5_A3;Y|TV#Z% zr*%`YS~0=XeO-eA?39Zv3~_4 zxzI8__@cNKU1Sps=9Ob&vCE6ZL^w2?*S7i2VgBRNK~oo4C@~q3B0HV3;*dR8ncdWy zt^jm%`Nv_9!DEb5!s_J$5yz`y|18nQqK{o}sk+K(<2ER@lv*TZ1qZyMhzY3`VEU|0 z!uUBs>e|t>SkX{T)9Qi-1N*73BYzUnXj`q^(rXrLw)I+e3wWFRwzs6+!j(JScI66p ztrHdh2t^|k-5f~GFTa0ru>WHJ)gI+_X+L{?u>0c0BAsAfzgNWHY##pOUU9EDt_O{? z;>a^GGs7A>tSq_~w1)#F`cVB?4UC^jqXMuLC&Pz&y|FxBxT4qkiiA0u9Dn8idBm}e z6`fTQ?f9mO4r$i5qqu}v{R(J>QU2=<`o{LxXwLW#xh(e06rIj)4#T}&_*t2h0K7V< zh5aF)FjU#GpGBBFtxj{j+3GYXQ9`4fEX*~I7tXPSo;lI)UeTzNl1vdw)o%DO%R5CS z$aWbfbt9nTmsf8&m&zNn6o0&t69{XyxZUsquDcjC?%yli*30CyHkxp(#hcw8t#os= z>aEcYZ;TvFOY`JD-_>fM7-YXpr134|Ay0+V_B zku8eO|Ur~>HTq$XL+ zFxRX>Zn`d63w)%+S;yBhc~Qv4t5%`q$&O{msntEB{(s$FcP#d&{TF_73CmWLsi8+D zS-@4t7sfs#j}$b**ZKej0X=z~`m4FPd}e%H+_|_|LX)^%xFPtm**m$jH(_SAV~Y{i z^iI;o0N?o-Z3UD=i;=+!4h_zx5+>-)S)Ra_pBHTj@52pXX_n*q0tjY*k&PX(j?F~p zxx^L0+REl4(&?YH6{#hjq3{!o(&0wE{aQc=hZ)S{!K+0jvcbTp}9 z0HkPlRAdrg*NTBf0$J0RrkW*jN^^|LtUGeRo{c>Nf?@_szuU~!p`o;e4tL|T4|FHL>`)=>e?%Umi z*KfTF8|&)~c<)vBFW>JzE5GjW>z5U;H&kuHsr>$-s$TK_5!3U#w|jf7H+yee)g>P@ z*?(St|8_~i&#B5fA#d>`(4aRTUGEY>BoL$iCrr3 z-R}O|suEAA#NYSczV808|LowqigFvzd71>~$;SF)e);lc>D@y$)ceo&UVr;`_sw_v zPs=U*T9&6-%D5=DVb#uH%}#0+B6T^w4Sz1JRWc(|L0Eqm-pwAI8;zjNR}ipnO95!8 zEUjafx$Q7CUL#J#{(th@QJQ>6O*<9QXJgecm27LaaR^d_i;2}*S+rYb>AqS7e*^J9 zNe2I9@pe%N0c%ulMKII7Sw+nK1o!_{<=d(l0AA<+Kmx5uR^2xeA)d2Z+alH~xqpt` z>MKN=-llIl1F247f9<7QaggI)eVZL*PqWc{Jn=9Lq>D-V9}=ODDdtnVp)I=0e?xgS&Rne8j5r#ieU2DpEHmZX3f`^CWM{6pz6f!nZ>`PBdQlqLL`=sONa!sMreotU;2Y*gfxi()) z{BWG86eM$|6IoDJ2+kpKnw||O6EP1?$go+mT=3#l&M{7!iGYe1BopjWy}h^>Vy`S<1*Qh#T)>c1(oL5=gutcK#~uPjJXm^Fez z3yZJwVd3=BK3@=E#49h<6^A-POALv2b#kJUrk^&l zI)zH7>3Q;Dh{+%Zfrw6&i$Rq))X-taDffZ(1^`ML(?Vwon15+Oxx{gW@tmgO2wGq) zd<=3?CK;28_T{CKy);oU@P{TuFn0GU%-RNr5uf$%$_4xiO*3ZFMPch4gFd*7Z;P+{ z8JQ*cq1TBlFY)2v1*%)^U&Xy~P*&vKOBS3KS!t=sG9xh9L3Ti1X{ou(j3BJM)B?-w z4tGAh)MPOs1%E<|44w-HY`f3QYX0Z^zh%>vRkI2 zQi43Zl~|;9oYBQg^#%*oPd5H9T&l8G1)iG0v2!4^!a|-xJ9y1d%ul%@jEhs2^9}W~ z@u^r1%G`uiJ!?(#4AY&OSu7zBmMcJUabdobjIU^2NZKfsuE-Z)SpoIGf9M?Wf~rYV5N>f8s$gC!6Ty`ykf67sO*`4mYmAfra) ziCTeH_pvet;aH&q_WQf6pp~cwFvcoagfb@u7Lq4ZHWz(ivLg%XF6v5fC& zqTo}}H-83ayFzrFOyi}Lk!ccg_*u~3vZPrZ;LU-f#=)a38Rg)t*$YQy^TwOMdA^_+ zqT)@S@?oW9bk>F0IYV=LD@BUyX<`gx2>jvDvPhDYgi?`{N!iOt*HXy~RT+<)Yf~M^ z55;QRH0j^zmX24j^!Gl_pfR*Z@k+y%t4v8SntwA)AT}Hkvt!&hhm#K(TC0TWW=^EI z#H3dyn`pgdx1I2aD{oh37~8#UioptLR%=e~k8a?tw=x%8fCp*I2l>k3^!Nh3Z$|It zQ|h_T7cfB}L2&X}EV`p%uIuj~%4kg?=g**($zjN1_tQq{5I4_-p0GE@a3$q)1SntCHZAjAreY&ZmOwPLS)L|i6ltqeGGR(s^%{4sv-rXl z@1oLwluUv3Oj7c&*q!w2g%Zyxw%RUoO7l2umlf=jdoychfe- zmWMPC(Drt;;d2LGBir`IvVQFIk2u6{+?f$Iv{>kV&|-vYu=4_o?^T7lphXllW2=En zoql>cuMYICcsiHmZf+h&Yry2Kj>FPE4%e^P7@abny~34h&3#^3*D_>q>YC?wmVXT# z@TULRk+ZtFi9C4C8_Pe$xK$~V(f-VKhgiJ7zAGXUuf_@YvZ9$LJ&Llz^dJBe&pd$yd5jfasga zoTt6_Z`0m9r$car7#M6xz@v^|hkr&a7TOhz)VN4!ESW|S<@nHzn~B$&Iiu6xx0q^^ zjLAXZWeu3Jz4j`eM9M4p%W|H|zf4LIkU6d> ztJ3OgbrjC0e8@IcNSxM&R?RKXC>{lLpn$~9GOFb8rO#XTBE7K#5Md1PxSlb41ONl(g204OOs*< z0>MR&o?aMVe$#KpX#p5QsSSAMwxVYTeGyweVma?-*)%4;WzFk=&hUPcpTVK){{8nC z_|4a1&=P>|w+&QZ`Qk$;OMjMP-D~Gd)$hvZqHAc2d<~#R*T>PTy3Ax4l^m)6IIx;m zuz_%-D%*g1nHtrt=)PX4R&XO*Sfa1TF@I$99QlAQXvZnF z(yqzObVrXdD%s}g?lmJBL*n9U&o=BqExnSuB0%!P&gOC1e#O$*H6wRDhxBt+gO1Iu z`k=C9IPqSfy@IM(h8a}9Y2qR3tTje+^`!(0C>`WbOcazzaMig4@xyUx7J+$^SlW1+ z3l(u3rhsu5_oWm!D1Q*BE2K@`Y!Jrj^|^vgLx#1zWLi73^D*h4%~8 za?pC|7DkV}95et?AIlX2?8ooZ%V2;JYrU;)TXlSv<1J2Se@Xg%y%VmeWUE&BtMk|j zx_)0T zl9Htyb9R(X&VN!#3nD8)CFPpK{@Gr7Nccxx?#RtSp-Pm$YoGu<1PlPsRZUS4^G`jY zKl(@Xl&MeS<-{#?-aW#>41gyYr~?dGy7XUo8r-aaf14_2XuA zSmz4-9crx-l6U1x(bxIPVy+HHR9>+a0^a2EngU*>cYoW$z-!CI)7SZO=@h%WTd2G> zgt+zSUn!N2X`g*T9u%#P_gH5mbwmTTu(oY8xutA2C`P)pKRexC6x=Tx285E5(iQgo12vbeqjLt6=i^d0(@iQ%EC16rZ$s6eXumRks;Tk!XwD0zWvLyG<*`Rp7p@@^m08^plSS%V#*%Sap^Q zbyl9~OtqC}yD93W0wE>3*;b}Et1Fo9c9yh+@5r*y7@;tb||shT$lcS;x+4~ z5S)tb$D%bpp(eHJn<_0AsjpnU`zqqJp@R~uuR>z=-ROe08$u5+4p13pcS|kkg@X9i zZ+|I>1CAgg4@aLxtsPhT=07D7+}8WeXRMxwsg?GSMcHQ`8mDr{R_hCNI&lAR-Hts; zF*a$bXTRaO!c2^Rr}G65*QW~nzs)JdqS$}-Y2{`I6TVKpkqBqqlG=~2C)xeqk>sXF z5{priHPac$ne2avdOMp_N+7bP2!~pUZGQr>DMeBrYO@ExV4h=6_t}Egxw5S5(`Sji zi=PEDZx|U<>DFXl1S!n=k0AM4veO?;0>1h`30O(Mdr9wn1=;tyMkY0-tIk%UccRa_3d8tzk4rUy#68j_U+!@tAFUp zi|_ZMH{ZW~^I{La?>_x=L=g(2CvRW>@XAU=Tbw7;w2Mj14a|3c`F{89Ui5VT?Ng|I z@OB@-!!%0!*MhXrK82gXC4!Teer-~8GTnU4Pc4ActeEI3 z_=9Rt*4bDajC>^fk$SUkTajFXlz$mh6$=~@PQ#;L1dzVP{JF;Rl7V6hKmWSjH+?KfotPyz?Q zfnKV}mp;8Q;uCHchWLN7sQRZ!M|C!|Y1of74ea2&8ge_IPY!@p7cmBQaetTDfzFH`bev z+?qb>mG>Xl@6%zO>tJXZu7=;ZCVr#J_=W1%=}fo2jt`pn4}h{$B(|J3t;gJYpsv-g z7Ai5Jfb-~b(?Pf8cJWTB>wniB7`y*mmx8imb^P*p-6zNQdoDE|n+|abLsdUj~Q=9*2IhS%!}Nq7rArq(CRr=cWARg9Wdlmpj`TFm~K7_ z(}y4j2;|lD3A9ln(4zo>6jCJ;N%iX;+rw6G$WVVLvp3&#tsJHg@qa-vfVQL}Sj0IO zU+?%$UH=0bvFUJm4s`<3EbLkx&L-3!_GWQB>;vM68yxS#zG=SAm)fYjylDtn9NowU z^;)1jR|$Z%!LX{pl!%R6Gx?+i;U5PHLGQ?u194xYW&;Wx%r|M5zE&6ip5_@F2K${f zz?GPBZSpCb;~;1kYJU~L63t>oGz)dBrNvFHZ3ntlE?-*1t|{VdJbj@;2igzeIMG)J zaRuD=)_@{_e58u#F|*6iq4_l_pXr`lzj&Xf)0ZmByT?^HUZh>ZQ&o+pdt$P$&|Fj4 ztOaM$+A=x~5@@pT-sRJCHH@mwYg~Y8x`yxd<@Jh}pW!ALZGUyz4;dW>RU!B>BcrO@ z46A*X&WKqdp9<@qkSz#ha0sezPo+ScGe3v0WK1o9Fp>-5!TSnuqMKvFG*qZ0HF^PK zL~kNmuH6DI*uU|R!zRGFsadU_kgA~s(UmGd*m!C$1v*|Tp%N~$4oAu+x`>pcr^3ZK zsU`hBoxA1}m4BT|F`5GRxu}PJ+i)tsjLy+8!AsL5I8VTL`1o<9lqY zYApNfkTH#E-W>%bR<5%kYc;h)OudPFqoCVV(_aAD{;5O2-eg%W=Hu8@Yw{4v>-f-4 z^=jL%+Ccuj^=yCoKRufpeudlIo1D{xzD@`hNA0HSoPYd=u~^Jeq3kzkd&4gWu$J|_ahpfI#Uts5c==?>uNYb+w1WjzN7tQ? zK_Ed?uP@aIE;!ZvVxd(ous@{Vaso3eNq}En9DnX@r_`HDP}e2c3gVQa*zE@vxGu6c zjxz8`5rM+u)^89M$Rs;ofgqn6FKB7FAd#Y z#Ad0$n5?i!d~#yoV@$FvRq2~`Mi_}NO)|BLV(Mj>;OsDJj~+_wpATt191N8eDY+GM zVt*MB%Z)rzGNRD|QvKMeZ695#pNuY&%R)#9b)(6AG-9!ztV_`zl@9Uhj60!FLwFl% zAJ8R2#7I-o;Dt7;8PM)NTBY8{t9for(g5OZEyiYGSrMTxGC;-4U(*L|5`!^Llhbsh zqb3b!Y*A}PfsN{$<_Z#)VbaBrn(7)|qJKB&0t{~3D!69PC4gnh;z?Nrh2U#*uDz!B zeku>YO~?oh7qgUS)7O)2szdQp-k5MXaXqTjf!KDeFi>>MUTWv1m#Baj?6#wHFsngT zwkloZl12cn3sy26CAj8>m7XDZd}JC})w;C2*&2F>uBKMX+;$7Xcekk`y7+>1C4Y#3 zzNZiK0l?ULY1hNp(;udn&9j(+C{86T35Ek;U;pB!U}EZy!2vNo(-%7uL?4> zIx^Fw8WV#8)!ZLwb}m(|{$UJmJ@%rjXhwfdFPWW*u7Cq`qw3h?E#}y;i8U=aK_MA= zezdZrlb?gxAQe5PivCKtPzvdG^cs&37~QU^OVbdXO3Dx2BJ>_d8xylHpnsnt9K{TZ zFtUP1#-*EHA+(p-6l33u1$)_FpR|hEY+`CX3 zwMd3Z)b5gPmQFd`?PcRJteasU6M#UcElm+@7v=i@wX}XU1Gm+GLilZ*sO6KBZqQ_} zuIA?cK|gLRO9Fc1bbnsEIDa4gSKh4x>pEw7StCyKj<0*lT0y4)2RlDhGq(`?YpYS& zps3zp!rAF6Z`3G<(>H6jAy+5d0;LT7%w!u~g3!lLMJJdipxoU0ijBxUvZ^NEyeXjL z>-jl5$dD3mCCc-)LU|PsKLXMRX6SY0kD%@k`cu*%alRM3TQ@U0w|{!>OjnIiUEn5-rk}227QL0bKKnpXT;~n)bWDO@w-^m+ zaJgpfhK`J z2HZzNvBgL%zWFbQFn>C&P!-ygnVtp$BURb}aA=n0WqB6scC39=Ie8P`ryE?9g6ZOl zr9hNi(j51EIL9jK&pFTDL`(eRou3O&@at!u63|M%f2CAtrqyg)!r|>$&O)5iCn8ihsp6|Mh>?SFrcref6vv zy?)z_UcEkuIJv-6nEoRmfEI0QPzcIkky^W$j)rh(b}Sxd$$P+pgEdq9gfZZU&)zeL zg4VwgtSre6pFz9-jIoU?Y~>2uX(+EyUqNx2Wk9=07g*pJ>S01=+0e=qdn1dKbA1cGa45aKcw%4+Q@ZJ?_V!dH|AFQgZ;3>OUQL$n^`>-&9UGHZ!J(1L5Kz}GmOzN}fBAL+qo95XxIiqYv z>~L4OOxg&u`7r0Y6#+oXHtb<^sUO>nDD$!WW56Uhaq%}#9&E}9uPG)9b~8i%%!{G}J{ zb;S`?aRR^#j2xPdzP7gmSVSOfptWV=`UrdM#DD1jae#DGN^d-FY*JB@-GO`Tn>%V~ zDMs4kfByZoE2*=2a;GdNFY5TU2w(wpkqpBGNrH2~hvwtrP-6J0J|AenzLPwDc$8r4 zT4A6V(BgmrY-(#_iRvGVLWvSdxystMsbZKIpQvJYTWT6rl%HkYxooxfBmt}VN zL4H>Y-Xc&;rx$ICESVxz!RR8Jk5KIlr-~%Ukm+L`fF{@Eu)vw-8I zp|ElPRkwit#h-I6X!2Ywy<9}-=FSi~Fn>qS!I;?MXIMvF0pd){51+$)n;=%)RSrkv z-6=9YUVt5vbb0=0e_qaCqtGOe-w)ZaPYB?g;Wo-KxN!;~Qnxb_tKZw+l(Ki-=sm$J z*wA%r=xWv>YLAwP%Bo;e3g{vR!RUSzcbbhwcx5dxX@Ax6 z+u|`e<$i{mza`Ig;QuEu-KZFjhnP7RR<$x<*X!nFrK9=c(~0Hb7C4yby8P!~Wn!?{ zjLSk<4pXM3swPT?T`Nl;e~2^iVb!8OUU^Y>U(H7&x>bs^(;w5`%sKR;@=0zt%SklN zLs9|mP0DrJLZpU3% z@gS=RR)61rLtSu+bT%G7dVI&L1tr%WQEEZ2Y-hdGT3=u9_!Wi|vN^?y&YQ2k{NnS+ zE$0#7SZM&Z1YgEg{h~O7j~>?@kt2Y)g|%H(J#_1bIuhta^bh^>`R@LUO^hDIDbiHt zbQD5CydhJM=y9WoX%T_jbblz`%jV~+X@8q)rf-MVZ#fLPae01%Z9v!1r)cDY_}p0z!~h82kt!txKK}y=4y#EG@7@om2Y=b(O_(-r601=S zHl@CRvyk3Qtr?SDwKHKU2%P&m?nPxzePevhb5p(n%Q& zWsBL@I7pnb@iZM|qB{?c702AO;9^Oh-HJ0N5}CP51cQ@ZMt`M;<+81)6a5beY8$Y_-|;!i-RLTMm!eq$rcsTarA03vvgyg<&s7vXLo0#TQ_tG0 zg`c&S{#aj^e(bU?rXZnUL~1}2=M#M0pU~+UwJ5WwxGZMrIO^p|aUQ}{eLnZP|J5T3 zb6vpl9`=wD(|>d{LJCq=G&ELzk)6Sq$MsQmb~ULt0zf;DJfL5E1#e#tCzxCo3%+CI z3baDGI0r5TA}YCo&ocC+AU6*jsKNsJ=nG#?G%R>gD8hGpZ{UT|q+MA$P*&{8bVJL7 zAxti%HNYuwIiu6dd}^^sQXm3U3yS6i?ve(XDwEYjaev9RT`vk8!#Wm&4s*I90h?F(#o3bRl=+!*<$chS|4f^J!)!4;0HRV$0iVe}P^$ zrEA-a={qmYhgHp2JyP2*lW7cP7(?q^0+Z`~s!g>_d`I+|PrERJWD9Il+5N29EyuMY z{cybsNPmZ=H8fUzSk@q*rIVVi-$rWB-je~H)g3n+I?rSOW(7|+Shd}skEaV9Uh1&M zDV&}xa{OMo%JJprbvr7YMtjp*<}I27o7LRHDyc^UqX~Ab7eMb#&3Y_+zj{RI3j2WX zwWa){hVcs@RpD*15{39uh~W-=^{9luplRX%#eY|bKXEEjaj(j!D6-xcRh_U{m+r)> zki(t%;w!&1g!9rXo|EzKgvf)VGKFt;8>2xh{aED) z=oeXLEic`nV-s1<($59w*F|Ra-2Vl390X2es#UBxxaiX8{Td>Faj`eXPp_1#AHqXwB741lv1YO(SO4Z?4jwzNtf(Z%3<}gkJW@2`g zVTfwLywWx!CdQ$e&kJmB@G}FFmuSb<67p(mThlVAB?uB>Veo;wY{X2$H&deQm0P7! z2(@Nu^%>_1qXR3er4Kbk=Oukm7R6IE$bS*B$~v8tYE+t_&@faPsnbg}MpdYm2@r%; zX{uh`bbw?*R4o${9~XP=3Lh^ktAfe$e0^0^sj$M&UCfanS%1{nAlWcf2q9F~%rITo zwxf>Qd__7qC9L8RQp`iiezdGk^2io+-AM4pbKt8RY}<3POV8#rb35U*j4Q#_{eRrd zn$r^BPv^r?A5RgY(&5l@x&Y5YCY#|?h!ZnD?FyoJvg;CpC0R4)>-rRoMp<2D@0kH* z=~%l@Ees^rTsGw_+}6;VeO6L$G5K^c6EGpaNZ>HHP{k#MV5fshVhWyNoB-$Eh?Go9 z-!)3elz||Sjs|zoTm>1?dKy4!j(@HNs7*RcPhkr5*s2_P7d6CcpdV0n^K#7sgL^;8 zF0}V9bO)FV>rgoOzu+yg547K<%xh4LKy1vt$k=2T=Z#!+<)4Fx>wOD z{3mJu=+vt1;bBZtTnCguA#u(dRR9w-){4$#>UFT@n8_qC244UB3C`bfInEGi>`OPNf5v=HXtotr&?`bxH zp_s`?%{k&EQgPc1v^G;>N`H|x(d>MPj_Db6X{-h+^%A(rau-vW6E>y5H9)#DS`lW7 z^GqPA70!EUVw_a0UM-KbNAiBfDM7%L?wREDQMzcd8W|Pm!-3z-zb1(cl??m;(kt&g z5sq^gJhB*JHyq0@d=zqOg@V~J9)Uo1re-jjUD&z9y3-4Xv%ASPV1FPoov9SGDh@`O zf+?gYhBYtBwhVMEh2_Tsrt9BIXI1OYPv|de)wicz4gz)0?5q972}Vs9>VK7 z0jX5*E{PTA6!omzR|;Kq)84Hf!s_t&w@c|1dQpxUh1YtUk!uii7bed9^c16i%sF2k z2n?9VffzFEx)+1_D1REK<1FU@^T1X)plIrOPIYtCQ_qNnX@3iagI82NM$;bQ(XTQl zl@$WrKZmS7K0pU%sMvt7lCTR_xYktibbL9!+7d4 zK)O^GStcCX%}D3;cX>?UJuNxwsK8oOlJLJ`cW_(rf89<5&0(U(T`OJ5B3l@Vu)uv& zmRoKMh9vqC3W3ni9<25Wx<%>?=qwe!_>Hi3 zteu`0c{c-l8~HA;e#%*0m<_wJievVz(#BF|S+q&7KScF=n-U>WK3R*+vLua^z}tdJ z3RG~+g4t!))?!q*8ZB$q@8*rN1+UWIcB!9AN5iK=I)5b56+T{J4{JRmk0Nf}*V8+vSRj4C0w1FV-wT z0!~cHQPgXH>y=0wSj>yIK{eM()^jz<3}7I3lY)l=cZAp*D@R zXqt|e?0;jIT&oFs5ojckV${^K-udgvdgUgWHP5~ErQdi3e-V5)eUec3Hhuc3K5Xhf zsJyE9NXYZ6xkeeYbpdfXidY`HSARL78{Dq$7Sy+liYe)eMfqRiLbhb&4k78!}XHd*Sg5Ta?Rny zZ`A_93PlFgP!_LMC~j{D3_^6*4iO|euypNV{$V&fe@)Q{F_+BH*H}8xH-AD|KM}Xi zanptwikrAH76Pw?Nl15!-0OolTR}ZJcRG<>-s}v5mlFIe6}5RkaNaX z&-Gik^F$>5&KzMD1ut2NGN!#imzMY(U9SNk3AVB5m{xHhvn9`J)YOSe71m)LwM4O8 zQl*uQXK5utD!xP)zoJ4d`G4F7WV<4p=cIh7B_Pr^qh7Ob)R56b(HI=m-IHqJ&z6_YM*n?ktYF#-X|TuEWdrFtE;?bV0Djo8F1b8$B2cslREbfT{obNYnmad6XXjb}Db(;UhY<=X z3V~@r|Hs_~{exnwLVvkD-R7E0WNr^%sP>BHs5z^+F=hZhx6lbVZJc6;Q`SmqBuZDx zS{1~}IQ8R@sT)GCNkB^M1BS7km6DhTI(-LA2r>ex)s~98Va!w!lW4e23B35a|>`3yG?qoYZ!9Q1nlUU4QVnwNP?n&+9D-AKT@X z*u{rC&1j2S>#DQ__(U{cUDjspG-}FRCX8V(LpD3Z^9DQMR3o^x1+bhbqLOuhoe_D* zi^#a=Qj9ruV1!b;G?WV>7nJ$Ae)Zq}m|5CV9DYnT-0jcNVhTjYZjY=^m>gmCWS!5p zz~#`6D#q!f9)C%-hRyab`Z&eS$?&3l)(<05X0?TvkY@D0|6>sqqdxuz|MY z0YPSfL4WY$`%z(OSPs=ASDiQT*x10V?w{lP(_}Y4vww#Ym)3LEM-KF@xmo(ieK6oQ zRXc1w+;no2q4+2ecOH61A_lHhUOx`s&-1OBDsP&;EZ`{6PxHKu@uOgqs#&9TPmjz! zB>6pH68G}P(S%ZbDOgRikr_3M1~Jh^Q4;x5exM0t;P~W9J!_{u(ld+CJxi_*z&uYs(v^~$o%PMSnVpnD!)0+skHbq}YKIoS zOq>H;brrGYouSE(H9>;tG|&3;9ujh*d(Qfw%EjsobM;!SZ$!yy)ays-pl)t26JDr&KTwlc z&Xd(bGdLa}RQw%|N(NOc^x(}Gj)tk>a9A7w38uRs?!lxF~2*q9N~6&cXej1*-0 zV!FQGsh1?#Q8GU5ClPGTD6!5^;eQluSfXDgam-S1Tl0w4Szkgmo7GS+#9!AnKGe(c zIjXs97_O+5u!6yp>11|sE)P)$*eBQ)^hcBgeys1 zGCA%-bQK@8OesF|Iaqy|+qg{h3pRfdW7%#d=nzA zBbQZEXEx&~F*8<>BY%{|%atII-;oe24f3@T@fLBlsl~c*MwNJ%#~G#p&VV!F|JZ^d z#qY%vPA^@nS^{Zj=dvX)-H2?G7DM>jGjd|#%6N!UC-~&7bF!jpH6f-^WCW_lqN{q& ztN~vz%dy#pIbC|JV|BKXZYaAoOETaU1J5_E#af6~2P&lD!hh9GO99pjxo*Qbp-8!2 z38qYF^?ntu0sPFV^4YeHS%ANV?h9(Q=DNNxuvWayF@ik^@r>yA<~rT9=q1ziEgTs> zzQsI=>}09bqj&!a$WaL<90mC*Hlu&EjATW@67t#+JgZqZCU}k0hIU41Fy3o+PYc-b z&etT$g!{U7G=HfzbNn~_c1CY!HKz~agC!Cm$jPq0V%o#sk&BX1XW#u zQ={jBV^tqQOXxU`A!f(JpA$ZHAg5LU&(aB*|3Ehw5Z}9gZ7cDJv#WxtVwl!kJBo*> zRnSvSX@4H^tf2`+9*=Z!uOSfzC(K(4-o%BqRHsHkmXFc4$XlBxdTk57?qHamoo(P_ z7CYk1(^aP8r&WOj#abL|Ur9ly`6M3}na(aKSp^MVYxGFh;0r3Ro*O%^_5|Q`Hlk>E zcYEVu^ki#$cNf0zbT$@TRvjMJpWxAcn+&-(*nhNdcUM2!c*u{a&=x&{w^pegRngT9 zpbAk2(h`V^6l0j9C2S<8>ZEzP86|Bp%Zo`YKGi>L@uVQP47Zvt*``1z1#Zu=hGo~E zT7HMh^;Msjn*=B6dKF`FUP0Z$ck3%9{zb+d3QOPB_Dra=#+jL_L1~MI@;c7C|Z!!1EX2eCBMozL7+_eVWjeGbL6LC zv_)qysorQ=$FSawAcCE8{TsDD>)f|c?@C3Bb@Iy}E z2kq(%tRL4pWy`uy#$jrLW?u}Dm1orr8<5v+j$aZFo1UMROC>kPMHtEQ0ddG-p6qed zdmG9CYG*RFKwx64cAl`c)=sS%)vm;=DmruoE|Ik^$9!sqFBEr*J9Zq|0Yw9D>wosN z*xtrp%6UsY4G>ml9W@_EwZnVGFZIm&W4|B-1Q9z+dn zTjDiO;}TD9k)Yk?TPZ|E@Z&=`-ScqBc9D(Az$(e#<7F+{>CGn?^ogZTkVNqafPa6LnVuXG z)QwcL6yu5Fi({B8j7|ld15rRrf5GU3PCcM*?rfac1w;(pOho1qnH*cVG623hW844g zo2);gyOCr^Tse&c#NVmpE2RpUP!XE z4gO6F;cL4fg_MjYVu?zDa25lM8sAq%MJ6gGMl4pH^ZSO~FphdKO{OSQeR0hY3Y zNaXAxAs*B=p@B&s35YgvaB_W}oTw2vIWeakvKc7YA(pCXtqko;6U!u58xVL}C)an( zLXg9H8=ov}|b zJK5=3jIDr7$ ztVkWWVuZ24oh3)Z(we$uL|tRFb-ELQVAqefhC4{3tp~%MXzKwyo#21|Fk-@4fv3o? znu3YMwbNR&HuR%{VTgA)3HC-=L7F4fdg5X_NY08Fs=6{hN+@{P@;Cwm!JVBGFEBLR zALW}1gqS~qaur6<;Rc#BR6CJWcHeOyv0i%iA)~DKk_0>GgIo$$SXUGjD0a4KvU#VI zzFl2^w{K7EGJY%*<4AvDUvBB*ajmPU+9f_#)AnU+4qUq+Jg;dbgqoISe1QlUyXt_Y zI@2@kS8+INdo6C-PXP3BK+A&rfdw{vX>+)V&S{6(#59}6b+4UzW3%)EnyWWtGuHI+ z$Hr>7;guXZ>EHeMjP|yt>+t3_pPU&d@W3uMpY$_hGFC5ic1C}yCaU$_N#D6fWWteE z)_|1YD9)k5AEzanw8%opzoH}bya;71z*boR&3L&`j7W6xNc&6fmC1P{rH~L}y2?D6 zI3NaPpaEiLPuc#|2~T;D=%baxlgs9aNxxsX5vp9KYHlh3@`UFFF9!~T%w~vcJFxit zX$ljja4M&Cr@Vi>DwNX|wX^AYDlvV%U~P=w6Ao64Ldej*x*;~J_mY#7t%KbsJFo@l z6gj+W$Rxeg`vHma&PJ<45>fN$!+DUL7AM#6d$D;v-&qeQ&U9e^6I(Ms`myK_IvWp1 z?~DGAKk~QtKmOR+*x2y*2WHj;cY%Dqj>0wq1^M&wvF(4||0TZRX5d}Nec9o+&@{Z; zcz9gm*5qll0_${h-?sAmB$&eyS z_r!FO6&@gzs~n$p;D1{3(sQRrY=K9wftjN_$2(dL5ozJ&mt9mBk>YzW|07)-e))y> zXq(`*`c8jV+B@^hE^ZalRT#di;=$KNp!glpF81HBQw&YhNG^t(c!hj;+`8ZXueE=C z6F2@D)l|yYjcD=EBAYwx0H;&%zhl)ZG{JgBfPA$6&Edzt9Urc@zDiny-PZHtwc28+ z^U1Jxp2y0HvOQv_{Jeg&{;}R@c0R`gkZSRDZ&rV95gPmAy3HJRHjkTM5@?o+1*}85 ztH|%Ed7?16ib!?)Dx2+35b5K(B4-C+BO@aHt`1FOH)p9}YAsp-)?28Zr%!;5y-$@1 zsWQK+9oC!_zO{dF=ieH4^0+oh&w%w%L2lVnl0+6_S9YVyh~9yO8NO;duOzwQ=2%r* zFXVqA^`)pR<$y&McwwU66<8zAO4gDow-Y*SKFRVtyMP^#l)8NQ$Z@QvQT_0^?!dED zmb59lVmqN&!*?d3$;>)jU<&sJ3XHzmc?E&Po^Wl&0N8?F0{V6YI z^A8svFMkf#{I4$7U0n0Ox;3>$d$}a&Sc8AD>?b6tlf4-9w$P?ZMpCfSWef{-{7NVm zy~zxRCnVHvsc`dt1W?3)K!^#t-7bQ}wrR&aO^t}4f#`Phn~7Mj*f@|dlW40gJggH3 ziei-%;pF6~C01PUfvEuxj!#Y+0kG%k$7;|gC-tL`bpt5|I3G7Uc-X!;AL34o)*ydS z>a)5n95krl`p3I>O;wfn6BWtiX37>HfIFIOiBZ^Wcsd*nXO|&FvmPb!UWDqphwA#H z<*1r5pgG6tmP=*GlALBAC?F#1Psr&viTXrrjJDeP8KCLQlXTW=Tc}@(SC3A7p&@eR zbePRA?fMLHxAk{eTHXJ`Hx@`GHFSUVtkg%I>1H%l*L&8D^VAFXL3xmrW3RC7Uc)kh zqD6;$+7#vPCVzu{X{{rwQ|A^>=ciXUZ-N(I?T8sGenZGE!*wGoG}_1pl^I#pU6*dm zvNgph1iQ1R*(jcrP6O;fE`IBB_2Rg#^EE@B{xl!vmiL?JdlKbe(^Ik7oMV3htF7!& zp-Am%J{(*kKEMnp6Uzhx_!O>*GQf-J6&7ls37>bR7k2X35NnR#5vO3)5##Rl@iKJc zNQxRQCY>0ip(Kv!4>8BWBI=J*dCFQRAv$ngiOgOqMcSk zs`COIekTRq1Mt+?a?cOm+ns-t2*k9?V}u`6vg(Kl!y}$O7-3ZVnh=P@7%RPcup7PF zElWZ+F=1TJ+mpn;vk{x5Nh0AZ^$R00P;5xo3-RH`BRDKPim*}mtKAUcIi4cmA83WX zx#tO$vBx_TnfKahr-^6AX;=-IHqLoH0Fx~A%i z#U1yxIq5nLB`G;AO4o}>w73Vs016Dfar=E

!=cxkSWob!0y2EV3BQv>Dw`Ok{$v z*QYbPPEnK2;h+j8Mr)8HkA+H`(di+Zh>4k(&x`v`N3O&ZLL|%^}v9^X95U z&J5T@++=%V=R(~!T4Fk|=-NT95C#-@RQVv#W%+O-w-6vlb-hH#%KNx7^DdNcMtBZW zG5|{|oIaRUWcG!S%E@kdZgSK|G))6I?t+WNdQqHR(Mp4IsPTVGSXW^+jmKu41WM9J zH~NRu)fM_$g4WLGlY_LF6|tWoe0@FYbfS%oC`qE{&!hDuTJJ}l#3=)Htea-KC=7%@ zU6}lsDp`n`zG-lcY9z;((R(0NAJ#eF^_^#SzK$}EB@Nd?+OmN}{aWXXW`uiN z=L`6;@%S-(!>147$LALFT|(}|`pf^tJK{g@zxwvs>zDZT`Rli2MvMP^_xkO-J=+!e zHzCI%apV1hj-$d~Uk{?!4u6eaBG_*g*mn%}$tA0q-vNJEsPex6)(ggmDV zyczN?s)9cH;o!xpx>SX|qZxf1kBlU+uM%CHYmq>!r|6DW-N~T3gs#q$GuLyCH|m65 zQ2Hlh`ECdK->+5k%?7?(0)I{k#_e@-uv+v|TWXx|7tWnq5;H-4*g+kR)GeW^zLqI6>3?F&4?<0=uFj}+ zdF3D#cqO~C)NSgbN_pp+;Dj_#*WDjznIcdYRQ%1N&8FvgQin##r({UpCA^PAU9%@L z1S_aNX`1O)pOQ2Y8uU!`9eDLJk?+flp2PyVzBTLb;OfJy#aSc<&s!kP=ILO&c0PZb zO^eM356+;K`6+OY@dLdPTi-5*?}xP={d?;{vJ>Gm5CP88tq0JAk^S#FWY>0jp)NixDo4Y~du2JD7}F}M*r0pe_g$nGtwwrk z`QYP#K>@M^P;guu05S%46{~mcK^1>}?$+)OO_F#te4j=&B!3N~DP2q=G_z=E19%Gv zUSmkSdCFv5xJK+waW*eN9NW4_AR)KVjgOvUivi}G(Pu1N|8ETh6jX>C5Rg;i%&*+%6i8i|>1Co57x+}Mc-xU6-A#F&2$P|f@I zaoXUn86*g$1ch!%&Qt%QLGqhxjkjyWTj(6m^v>>vjKxVLK`Vk?qy#h3$%%tE+ijv7 z+;DKIt}~R~6H;HU&gAl=ZyB^p3|mw(QF`lvYt)zGFsUm6Lf_mtZXG;B3n98}+*^?AmNC|Q z7VwQ?Pn39o9*E|{v&nWXN2BywgFT`3Wu7=Xa~5*WQzFqT?%&5=ON#KOqmO`ii3;eVNG*Xu6@23`#;jm2VgxFo{kh-Xef7WHzwW;H zeh)3%3zN&fT5LFW0ekBmKQhT|I>^A)-hdQ^6HtmakqO#_yXSSm6s_C^QznIWFmq{aEk=VefblY$p1! zt^kxgw^doC1DRbX{t)FWPziC_=0Yu341lFzmm(h-ygq;1jw+@STXhjOhYHX!me-Z9 zgQP(WBa{<+V_w1m%av^z{(^J!LJhh9i8Z-P=r#?qZp@=;a;K`>+v1xTTXHOWRnrbP zp@#GhxLvOsQT830aZn^#-0})BRkC+RBeaopW5hx74w#Vh^oNKugS7azq(2-ChCOs6 zIF-m`W^aGi4q1-ugVTs*qThBGBrI0m26gFc?Sp?B&Ax^oe>$6et@cC$bnBaCb#AmKA=MvCgsd} zLkfS`)|Ry1+V0LuPOCQlL~H>yYEB$=x`9?f!6eOkZi2$faQCt^^jIcA4|#Qlk^*Mi z!H9WuV<`C!Qqzj*GPCozNOh`4Ko8Dq$~q5*G2ImBQ9JQNIyKNZO)niBfl>&{3IoS7 zQ&HeyUd#uX^41(_W4=h|Oy`=laMZ{*97})lL`(<9Y41Fl42v$B*n0&a}SH!Rcj33Xe*X=0E=fn z`h=-G405_hzdNj%VjAPX_(T-4MFB0RE0(GMH3J~1sHd>P>!a!*o6-W*xXs50X+D33 z=4sZxfH_R-S<=xmb8fKpb(*J!w_!(AY;dw|3Mim${WJCEYnm2%#?psk-RpE0#&GI1 zRX5(eE)wP4@innM!P~$AJRUYJq!J+k_WvSt@1PZ4@WKEvJVDIF)d)W%`_IDkTs5xx zF5&F3C3?)@k@jj7VeVo#e2*1w8!x@@Ze674A{p4nBV`zZr$&(umrI;2LO&w4h^{#(#kVuWs zq;fnF5_&Su{Q)i|Qy>oWIJcJZ_Q1W;Wk%YSl7e62{$ufb)s7vi(%ES(N0NLoXx`CQ zhTUM;RpS3$i5R1|8Kf?7=a#YF%wcW-I|iQ09>0J%21*}H|w=A-7HzWU}&SX zuZ%l&4FDu|AEg?wQ39WbBUOKH1>ix{l=SI}H>&L`1=BUQI&^-;^%nY>BFD0pS;MUo zv)Ow6e)IqZqYYCUmtRHUwWzhc@Npy5rD}7-$7>Jof9^I1j~d>y)<&z<={S!75b)bM zMhhNKISg*4xa>A^c=)&()z_fM1RELoGddJlksw(dval8bg%aj9J)vZZt{ky~vlhje zm898d9Bw``?%KEqi>VeIo9HK=nv`TPp!t3oZNa|IN2Ys4shHs>s`&PH^suBqGtvg7 zNuqssA|e*K1Z`BQsYoqEsoUb9zNyAC4#^YSMy^p}L|}jNgq(kxJF;BAqX2D?@r%<_ z+|>M(G}@>{(X?R`#*pfAr>#n;p*q0Z=6CE2b*W^GjrOu0oAdw7Gf>e#(n(=*N` zPT6qG{*)145p;j4Gr?G&{t~Qd8B;AVI^jog2R2eZ-$(IAgQIbw{VV={*s#_ZQLTDG z(B^)v6>%4ByUhjui?=FAAIhB=Uxsc>L(|#w9u8Gc+&fDe zk<)j|t2=PE9?opt@(|^<(n`0zxsxUwUvc+t(%u~kj$9d8>i#rYg>aSi?dp0cFpo;? z)^Rs|knIBe)e-^~C@nA|NcG;wRY`w^26GX;M=6?}u&0A-fp3`(OW2fpE&gWn@E^6K$x(iEbbJNBYPAObIXa>@ zACIp-+Cf|zjmG_YW367Rmx9hX!6W+F98axeW{N^uakd1LTAkXfTbR`A%P^@m)@t?I zVoW4fg~sHk--;ktRV?IId+4Cg$}Z_4-u8G@$Ebe^SwAgxw)-Nk&&kd_VDfJ@CiT6% zBQ?48V1+NmwBm?^+qJkR*3mv~-Y|7ZwMzs!W(z)v-Gr1c{SlPyoVLXSdBQ^bDt|pn!)mXpI$yhg# zABb-aRUAk$*9cA#wt=LxLn${L>+PBB95kNW7mG-q*5=AX4atI>;TV8iOaUY;2OWQL zFj)mqKA&;qdL(Kz7-ghdL+)+cNu<3|*M_6`w|Qno|Kg;;uo+n<1f<$^o%z=4-Fh=J z9)0jLkg=$wB=%AiLH~6qGY`!*Zq)#N@n-jJ^DX>CW+Bs9Y0#TdEpFJhlDOA&(b52e zkeJP-{tNm-|5|r8kl2}RS5fcX>~epUKIO?~8;tb2THn4MdAPjglwL6fifqKRU=Jh=*$Uy|DQ3+0yL0NP(0-cd~sKjet1yE`h*@5-)puJD|EkJdAX+RAr<3 z158M~(*iez*JfT~mdn ztYT>9vpCdonM{%eYd7!DZ_|r#4}RY<|ECK4spjgMd8A{!Uw8KW zapp^ag#U2_Sy6FU;;7m~OsfnPk7aRJkjGt@>;q8U17Q_HJGSKwRMCU5zBYq zhIU0&uQX$K=MQr!xaG`YLv3`lpThGuoxebtU5mAy2-Gi4Bpf@9i$ zGRk`I<5T?i-3*RbI7EC;!6n{djxzNloVq2X1@TXwT%QBEQDYMGUY*Q1-Nl?Ua;PID z6+}q8N z7{V#*LgkctdP&wv?CCmACdpaqkcKkCX{CiedupUGF5T}-BLJUD7C8%m^?nXwNd+dfof%yTqZV#~>| zDd;Z{fZe4jY%PBQ%LZ&ag_fKOf;IYqRKGmZyX-4$qokA!3ATx$+R!ZE=v$4z8UDW_teR;utjBdbkC4eKxGdMcqHeBmt(1A4@fWF*A4Xbq!j@*;5snH;I zk9t`8yIFIaQc3`qjbdM#ffc3k8)%h;L3qsqX!Sl<87JHgPr)J|a0SfisMkZcgSlkt z;=VQf*0z7PqF6(}vI%%)#eOx_V8CI+9JBZn!etwAkw)Di$EGw@u53t7yB0;pS${s# z>K7wpAvmiTS!o^QDbmiW;)M6a)!iu9Xixc=yC|_7%q=H)8^*!2eje6iJeU5A|1|2y zPRUKT4wH0 zS(!oq=TaY#p$Wd_n1Q|XwDKvC815$ElaY6i8Zkf+v`j0%{%pr&+XURw@%{^t}BF9s7h@Ju+ zB4|IqRO(VqqIdJt3JR@4f+ZcZUbd4d$i4ko)m(mLsqRiOKMi;0`^oV3M;qFV?G2KS zONK0lQ_mCzTxE1wWAq^#!@M6 zRi4oOSI_odp=(+!$!uV2s7Tb~P8{pPx6VN1Lg3Bb-rLB_j#C0-mZ$|r0DP}dS_D9i zxmEr9R}LOSb)K@4(2vC=L!~rP`|+z6{)zwYKP?;Pz){REFLYdsEIk90LPr=>iR&k0pTTvnsd&HmN7L$|JQ##kceiNFOzA+Ieg=vhts%r2Im`C$>V7>IW0I^ zdX!AFqNW1UHS0TDe~M~Hbp*smKE#8e>Fh-HKgHj?*-Gi*P911nzml{TZrknm=_Rh` zXsy=x+BW)-!z5)@WiUVvD?5T|Gp-1bpIiP(QYk7y9jY)naHt&Skt9Q~?tOp#=u|HD zXXz|P*Tos7M7eV}8qVqkrU4=Y&$E;Q(-f(`5oUMRd5*2-co*8Dz~}Xx91t!AKT5Jq z{&Y|*9gS$PvEVpLJ|x2tddJ*xZovY^MGubdlZnm!<1763*#k1I!I8NCz_w(13P@d! zG>SmwngZ%N7(TckwcG9J{)2y$liHm-NC(rnYIN(fR_pMnIC^({|C?58#~x6k`O-!Z z05t=(sU1wa`+9&Y)oP{~n@&GvjIJUNZ+p;GhrOd0OmxMJEe%4R{*1{{#;tLf0qp`QTOq9clhxRUl=eYEnv)~ty#UpA$v!70hmN@a|_ zi#_(3>_h)*%!HG7Dgl2I`5atHF0soqE!~ zL&l?bf$^dpDhD3rbU3y?v?Yc*6zi;ovChQHi_BNy6>KpVoMV3#290y-Xm3|ChSEVD z?r=pPJ!>b+84zJ4`xdm@B8_Lz7)qiTQmRlsDEv4dPg^>$pzMl$1dvU~BwZ>6EqQGX zDVFlMFz&13_*iVomz|TQrY!cb*usBzOoA-+vgi$2<3drGNf*5Z&$?V(>xHFXda&}0 zbjuVxK&xz^b^U*RN5|8fq%(~0fXP6R5~+pt%iX72R{`|)-+XwqHJpBUWRqO!AUwTpQE7k55R$bNpuy-i{8yfgfVkJ~yP>rU^Lnsje6F7}#z{=33 z5lvSdFs|AjF!vv<`41kpJC8b#zjB^^-d^8GHy*l>(^kjTz`NN?Ni%x8y%<;g^>CO}(q=R#|U<3tYmU zbBFN5c4v3qwcM9$3o82S>rft8Mf~MQF2w(;0bgJiJ~c=Ol+RbGeosyke7+r^#bcGy~Pf8heFTH01PgpS?Mo3`Yx z`@@cphqK_Wwb%}Et;h9M>eL(N-h{sRB8;7yXQ)iFl@iAmhg5_ytgWTvz6vu!F}37G zIuw5ghjN=F71=G)oWFLPGOMg6&Dzn8da3Jl-a0;+$=h!aO zR8dW;WnD;KJB`wkjCzb2E}Kg1oaA#l_uK;Pu+5~O_J-qRv=l!#E{xGU)DPEM$KM?F z*Bp;Nr_Z-SNYyZhx|S2T&WDT*R-&$!GhTmgxZMccDLB)S)JG3c<$BF}7A;ikHQh<| zBpG>!daIlLA-fx42Ifg%aCla$b)khOIAjIQ1u2u|gBjjY$u{grJ4hK#r7M4|t!n}O zrQWLBcSvX_A@xIjCuIe(R)N_nQ^k4jD5&b{VM{ksZ&pl%5~UnExgwrNtYSWHs9=9C z$tWiAxexaLuo)3aL@MrO{pY@7pGVH@Ky*ti!89QTEPSiQ6ta;xqC%MxUO}c z%G3%j29v`l^9v@$Az@JCQ=qi1D)%k}0{?ch~{Mv|*+RJ|nHGX;c ztKCUde<{V8>ZbiHicd~J$j1Kx0|V)`ZT)w0(h#J(q$HbS3VCY=7{ zT?`=BwUuo+r!By1QC#1|-OM~|-2cL!NB|&0m7Uk2E_oc5K6jmYTR?4sZM#A8xi=#|`h{H=9Qt_fg{)cecOWed?oUJ&Hbl+_ZoGAH^zwDkgnM zF>D<%iFVy`s8(42HySYydu%69PspCg*0;uk@oc+x?|)nO#;tq(nq|kM1PlBGvLsEH zpI1gTufF;UPPwgz z9Vg^_S>c4ALx;pM)@{N`yBR&~G>(JgOVi@RtUH*L?91@uBpFs8v2-X6LyYox6UVN> z?R(y1oH*Ec?ck35VfAbd(Wpsjg+JK2v;`OL!pd`>uyyAD!M%U)Ht)UMy!WnsZ{V$k z8!Z7tU}Cgh1-C%jp;DndRY~cbq*m$`4_$&B-8y;PI zwNSJ6ifKk051Y~BulPTBvA(|kuU$pI%kr_u)fP0rd9!tyCi%`$A9k?@>~1Z51fw@Q zhi6B9{ivT@@&kW3k2w;(x*A2udONnBp-_1VpVoNX>i3Nl>Cd!ktbCMQd=3wyV|;L) z&2xUTN#%!=`7D(_&=XE}Mo(foW@1ko-{7m+&pUs=!UGGw-28?rRdy1Q4Rw?ksNLCv z^YhK|coW3CBL4f;T5ElM6DAvw0PVkEKu4qxBD7#6$HRZoXsCZtz8rw~GsPhlA@plX zZ#kVg5zS9d>IZd|;IAIl$ruK)L(Oc3bo1q}am)SF^%osV^>Y1y^vUs#!EZ7B{`(#-ZrBq6=vK^f)nFnHqXEqC@ zq=|z(8%KW^=_%!D<>%}mxRj;dWhA%`<_{HM6Xfipa>|?EE!`|N-fzzO!R$2$&pdm5 zGS}$}wlgdL3Q(Jt!iY3 zKth%#zp1HNATKgMlejG6hpCQR40v9KB+fw3c;3ykK6K)A_}B4Dh)eSniI9G zN)!c&&JgA`#mhk$-Ep3EyN8`k-_6EuVLN~N#f0C%h9swf5Z92#>Vz&P+5aqfl?@%L zO2-B`cC{=`hU(}!Bk>b~OU&HKqS)&$IcvjG{azw18e4l#-!e)jXLDf8Eza0F?CH1; z1BtM9a>B|~OkQ(xf(ljsrgggblarbl?x|9m?Aj=@0Vy*QytdN8>c}-i=O8bk$~u4l zlzem1^PReGk`bPqbQu65A`uDfy-D6uLdf-x>+2iq%?ST~fvIolNg_`MgGTfCj*B=E z&<=E{dcek}+R1-7IZyK;MFhewiB+qC;h@A_c=|toj-Q?bup(_n|C3A;{`O~JsL8|+ z;G~?h)yP`C5|sa&pn5_YEnK8z(S?5jl}fR@csVl1p*fDxDZJ;coU-pCW!ACAw|sm$ zg`T{3o+9X+a>ey}Z9yk^o@;~Pf&PHvwv*FA4*s+{$7`MPsp}B&I0r7m>z|M>GE90D z`plWfv5ks0lHg*0_B%miXvl5FO6amV5G+?0PsJQl*i z*`J^_nbyJKYN+$~BGh@6hR~)rr<4ZfrYKw360}do78ys7#Bxp6AAe(yJ5Z)azA z-iRML@yL`JBd9YLl8=62@Y1upgJI0doYK((PToDe5K?=Bxro=<(bKCvwws#fQ|2;h z>P)x0sV2FO2}J(^6U*!|*wnD%fFCH%lab-t=S}I`D>C5h``*Gile2$T7?t8ND#d1G zE`WVAueD!}XTKcZegW*Kvwr*UbZmPgs(G$F&3IR9-Q%Shl}sL}WLQ-&iRnP$n2wnf z60?93OGwhFla)GI)X7@@vzVAPhx)m^(9ac<^0MY$TJEI-N%GQY0YPe6A*n5bq@L9o zt>dp&M(A5YQj-!3B({IdzLN%tBds`?%CQwIo@%RXci0qEJ!;Jf{n#xhi!C=xtINv( z#vqXifO=f}SsUyZ9noAe3n0nR7DOc;PGUF|m6Xt*#)^dsXVU@9AzmV_PZ~+%VxvPo zA}s==*GpuJY|w8w7}e&&_|QLu<4{vLYI*Vm;YFt@z9lTaw`+ehi_hgI@)w7mNOKm3 z8QQ{tPf^Q9lyJP_!df{SA%cXQK>LD0cGT7d+HqSvsY3->c_KUn-aSlH_5m{k9L)ks zNO6%%NHLERD_=vLC_N|YQ$-+?&_U>vjV3kkAy5c&)WCdrQSb*Ah1TlFWLifFFk!l} z-J88&a`$Fu2o8T0?2H4FT+Lrdr4Fe@ce$V)o6#aV+(i>_8T85qiKxhhJnH20fr`9n z)5oVzqjCi8*c@|3u%8Qdk+Nx_D0P=MQ2U_hJ_tuy69 z&CSr_o>%BboXR~H9EZDr!dJdZOyTbYCJ%Ff@f6)z5;=dAch7BLgZbC!L;1UFRXoF} zi!)^bYe^$9`u4@G(edbq(cz0bqwf+)4JByv^Py0G^p8&O-PS^&9|^}8J{|U--x&6X z&*-QB{IlUBJsysH!T|?&2hZr|r@=3SDyUS}sxu7{9}7-#kbl#{HL}+;t8a)z_4ek~W{aN? z3W+qa7-^ZL5@P6WL;P9)+NHYmGw(yj@CxD>2o>K|n)fVZF=;oU0b#}Ng zd-Vo5!g>H3YFh0req6mgnOa@0qFFZHgmr)Zm9>@B<+UqU*3_+Wb!_Tz6r0g*8Htsp z<)zAM0>-iQcgnWLLbYwR4bg8T0O$$}96f22$`#dwShzsmeEJQ*;iXp|tO9{H>}|Ft z>f%EVN~L7EoUBwZBir4Sb(L&-wi=411*n<;K+-5D4PW}CvC5RwDo&#X@pZj?jPrjY zqOe06n^OJq3~(+9=`$aM`7+M2|!;jqvHYQs}^ zl6tnodN#lM_qzHwwt6?Qx>Vxs*bR>%@c(g-w%30eA7vY^3+dmY{&L&XL$;=Sn8n!^ z%lZBXP)h>@6aWAK2mo`Z1Z>*7)*WN}Q98a`}mxAwnZKL8SZ zN|t?fu2e(<-Hk?fqtSQ}cqNXb)jIZX7pbt^f!Kfh?(G}+@2}#c4F7PJekd+wD&r&y zd#`%0;3Z!AN#aML@Ds6+v7D{Ne{Jl9sq}_o9!n{rxo{Uwd@F|{jf4}f#ftDnG)o;n z^ut@>2p38PasZnyfKU?6(+4M(0PYDVNg~&GfTHjsH(Sauby6&G?gugvR=SX)f2A<` z11iRoP5|_PUCh;);=xZBQI?8WCTZ-uNM#5>ZjgD%ht3ZCrLW3BbP`7bf8>C0mOwp_ z+o4!So4x)Sg+&*sqY$c zomq4*sY7j65VM*n#f^VimAoIT@db{?Qe@_lM%^ z_}k?CWGKeJT~5bWSK?v{#3pB#r;{g#oprFHnamaw(24E`Og+e))VYK3|-k zj3M#k7`Qw7csl07f1ql|r$>{sp*T4@JNjizSQkJCYlwi%qxkxHjEPw05&S#8o?M(` zWsWb-ucz=jgt|_zbL6j+tMO1AO($0Y<}iw6eS3Q&4iCjX zWFNF=A7J+T#{3WaH{z#5VI2&``vHh-E&%jHPrx5KtMJw)2_SA74=LRTAAT$2JOkc2 z!wtYA=gIiX>8X57DVeEI+RP7~c&$@s>lCGo8D~eoe_c)fXRMfAI**C}PuY_}A{)7y zIf>+?X67v9P6SbSJ80n1A|_eMqhrjvhQ~pT>n!xqG8;I@`f$N>Vt5reDd==L0v{Kr z33eP-{}1Qh=?|EH{Cg$-i>=xT9-MW8eMce=_JMSojB=<#5>N-rdMAGTQ5?J*h&SRL zb65z4e~C`gJ@CpAxa3(N(Z??waNsDvXl{`R#D5&>_sg}N;G>-miXurm;x{XzZUQ*Y zbMViTb7*#f1Z%dSvzi+<(tojpHW>=VYo49P>oP15v3|1#gFI0_x^k6@3$V^P^hx75 zj^Z-PE0E9|kWeXcqm1fuVp>1E--^}`2NhbLe+ z2j4^qpwtv7r+J~aCT=s`o}oHwbwnZghM70O51WO3>ilzkA`>^R*azDML~N-tjG-{t zf5ksc9AO$%5r0g)TUnq1U1*If0}}$WEJ(4TAqg8^qu^dz1A{ckHzk&aML9!-IG}bB z-bZ)P!fZRivPSJ@iGdG9Ht^5E#wfDe0OB}^*r3l4&VA&233g0M)ChJ9kt(>a3YAzc zqx&4lLz($2=wL>b_7rH=!35Yd*+wO5f34#vRq44AvMw^%OF?a8N_qm8QW8# z%ne!ur34VMhw|a@JPJ!n&7j+~45G~XV3boSSHkRDj5MH(0!QL?e}b9HWXxm|5m+ha z$%l@HZU90xjEZVQs`xP_xJu*GR0b8hMeXIn!WV;*!tJo!dnd>+UlFow-JFS1f6c&) zQihB=sB%rI<>soi%^e)SP!G3#%Oxcnv^FT2E1UZ>^{Q-JXPAY1eq8TPu$I_Af9op@ zi1pzSi-PBy3fx}+5TDq?U_^y)IQHP;muRB4qZ?0hQxzPMVWuEV&1S?dIE(}aeSs$c zJ&t_}Onq)+HIm5dO}U}vjrECbe+|um+8aM$3YJ5ykJIzl=Ej&8ymNcRk~`a^t=e99 zyF{oa>a3kM@&Kgk+zzDqAgBgL@UQL-8ZdQH^=fF+3U+HJ(^Tut70Mynq*~>7qbtk( zPpdQ2kg64EKeRO3`G|c{?o+P($1?!CbkYUKAhH?^=osTjECCR@rF5YNe`pwuM0&86 z_>UuOL~?jWyFTcd?qD6!fd5l;oG409Jo z524CNH}bE48>L}@X{e2+f0l;gH4GdBq?8y1qTAEy==yS)23swa`K@5}FQPx{!~Yr= z29H>x!4L*(C5AL;y$^j_Nkti`*XA;YWKC7i2hGc@cfHuM01WP`93$asWV)%cwGgts z_C;MatP1P?Cf5xCUF`UY6x_-v+v-z`U}J}P9?T_-Qh|l&#%_w#e+X6(<>@t{SyC6q z*VrN)s2GxItgA6(cw!|>Q7gMp6*3sYFKT4y+)w-v=Mi0LQKK;8(8{=!$-@6lL0H|J z6QIpf&SRLO%{J9lHIs^1N-f7v?3Lr*Ikz1e(5@5zrc5J^GcbFfXGam-)2gO1iXu5G z#_3-HOiDFF3m$k8f6@FeND~}l9OL9~vXZV~r=5^n%#oFQJQ%$fz@K^6~t3*kX(YU$Vu|FUeC^Zf55}$K2*oHMpsJ)JxS#< zF~e`8o5e(G+Sq$R6Q!6`E4CQwv*am2Mdp@He22^_p+R|#!7L$H;@G}>MKf)a3k=6g zFMfpo=P83>BmUeEpt1z7r(p4AmO(nSX38jF)Ke#|xdZLDMzH)+fiz!RX#3$ROL@ql zc;gX>$!P36f7m%3KeSSV^1=pk;7i(Ymd>hMObP&hT1bHPxep!!MM?2Lr)I@tH~Op@ zzj&H;;73`iGTHE;C1n13`_HD?H z0iN*}e||=o)C6vO*>btI(?u*DatGD-GC&iFMVhXle~j*Y`G*rTgZP525neERRAg_U zkgzcDv4Whmpe_R&m)BB-iwX3;hTtSm8Ra0YL<(JezCJs>%-;xo)vg$3KJcLg&2g#b zoYRCUmyRFUOCJITT>e57N*bL_&c+{0DF`$of1nM7phLN>P@0sJh!lfupta1vfT8AT znci7FnP?W^8|a2n*g_g&vNq}^qzwh&l3$tdbt#1i5>OK%l>F!G>&q({-?ItSQ%JQ5 zzc$f0{$)}|s3mNoa77_-8K)_26CL-`ckj5*G#*#{)P(S7CNqNhZ+d6~iRCI*Hja;t ze=tep-pMp6c&GQPc18`KV|bqqzmwikM22A3>ahdN_IxLZ$bX*XPbzPu^19G*FH%9` z6TH>Q7%*L=5;w+9)6-^prQWrXYH}sGPJ(0?1$S&Gb^c0lT?A8~f|qOl(dd}kiIv_F zxcbpp@Y;n1Jt6HQN?4JlS52cx?9_1Re=!a9kZU*WG$7z0h+=mUMatu+cgL7=tW#=} zyarzeW_JXzbl()diN|NokyWE#$26KaAsZ9tz+A^ZQHhO z+kTUD%nmxXosMnWcE`4L^8eqtIp=QHs+zlM-R!mYo@0zh@imDAsp-KI#~s=f@!Vg8cWx}Db%hDMrAf_XLs9N%xty;Qay$~j(f7c6;7hN<+ z9j=gwBa(FR?2)KH$aBxr8dIp9j1i=GsLpIr!ZGKg2XQ;jE<&WBgb&u^7Ag!QSnlT9 zlbx-=7#|&{fK1cgj=Sl0?ES9~vFn65|CI@F)j?tyPQI+IfAmT}{>xXW-q8M)w=#)&Xfyl zyxy*1?2^S?q7u?ayJ9oY8M;i9#^_y|6$e?)nlj7=FEcxsdpTTLxSbck!}@M{hqq~j zX%-k1q;|1+74ac?5YAhWaicgSue8bg&tlJ2X1YInV){72rM8J>4+s2ZUIZ8) z1IKmoS!b@@trStRHBuXZw-7X>VRNhrxxKuy)O4iPccy1&b<=Tt%g>Th69^ z@1&TQIrIHeq1%Vv|2|B>OH_-mEPR&+$uTZ}N{xOeb`L0Ygb@S5>90NvB$f5M)9%EB zn_k@RGw&~NP;^Qsk0JiBKFr3&bE*`<*~UrT2_shL;u={h_(S9h5e^-kgdHeVYJb5#C#8 zSgB0NH6f7CnaC^vFB2N^_w5>Vmyx76QFZx4ME3Fgo_VgUf!cPRL*Qp?00Jr7%J*cH zUa+WFgvs^Alem@N<3i~CiW*O!3uT6616eFSXXxAOm2wJ0j_w#HvDldpvP^pbr9jP0 zw-~r#7|PPkVVV!a*ODvLZpdB3P438d-9EzstF<4rHS00Jbx11U-a7{-&ji}>E})bE zDsNMW$GCYN9JgS_=K39sohQE|00aDjcZDf%#J-SsZ{Z|NV;dAO5|?bfIVO1BQaFbv z*&=SRAwCb|TdJkA=OM9Rzsb*@GyQ9IIij89LY}z^qE=#wJDvXDnHhR0BbR6uv<9iI z!j?cIg!36-3lH9+dfci`y4U>|RRU~8hzEJ#&M!g87XAW;*^PCP=&ELWxR`EJTcZQ` zsr=Bs(iTX2KYaKCy2~kgk-nA85Q@e&c{Eyg#ud7lr5=|FDwbwPJXNuNrh-+&rlkVY z=sx$qe~YKk(L7i?KzcUrc)0xQZ_{-gT6*3pE+tR_bhZWAn-rpUp9<)7CtN8CG@+^u zY;SZV+T1k)Tw)Y1+yn9DH<{3%(xSjkkJDaYB-7E3Crb0fl3?=p$!As&G55`b3#=j$ zrEhig%+Ut%&TV~;v03ks{S0VL^g;DD2~s1JU1#T!j=mvvoM^skj($o@yOI`BIk0cO zoQiCKClAn_`LZ#sIv%}c{#w!08BZq>J{gP1ofR~R@~KMaJp$q6QX-cMI39*T-_&to zMAh*%o>_myTp*WG$&R{oqE(}g5}{c|iI8_VbCx@ZfK%X!7IARJ?5B zn`r#$uu_+t5mrj*%n+(>8d}Xh!+BFxcp_NB4H~0v&Ltv%b)^V( zelfxkug6*&Ki4+@6-}LUCNDv<*p9eh34igI>ugRwz=6XYZbI>Vx>r$BY8dC?1~LMm zQ71>BM+udM?LSvV$UDA5^y2Q)Wkji`TjrJ(*Zhu!vuWIutjp~$?>mx95bnl@G#B(? zj(4l6Q<8l)vsUkfVV-Y!u4+K{N6Avi{BOPf*}C1Z`pyM@g=pmT3Hp0~{{W4bK8|Ub zsMRJ>d1{z;i~u#-XkVsr1@DSU(PTSd*ccQLdse2=6j=Nn1^Q!JMG}!E_NxLhp)&uy z+?0i*AkyDIW`i3i#1d8ium%fN*)d>HNq%ez&2HU$QrCO_O`HIx}_H2|SW%9B}Q96xM4YRpRJP z#b385{>}AIgi=uz+B6f#J5dCHwKY4EwAi;A#?h=E7Uq>G;*v&5MGh&PwK-xPG+^Xh z!E2T0(DfICeI8j(mm6e##_^OI6-(Um%{9G2I+p0)BCtlxCE5GLm`v z1Iw29#%%~#P!`)lovI4^V#K~3=BSK+PwD5po)p$yju3|SdfEd4g?ItvqC7w|SZB5Q z1?Lc!yth`y&4`99&Y^#5edY>0L6YJrRVIR+`C|Pc=WR z8?2T4X>Zx1uCvle5&2Fz-9=`giF#33nS#JbDu*DFR3Ytk#;8&%d!38XuRlMpeMN%= zZMli^>s~QwXTUPaJy|ce{vki= zcHkJ~LQh8r=57uIndK8K^!u=@POhcUqfu8n{?+O6ZzF_P#7_mM3{QV3kDVH>ipHay zuCSdK(_(g2ZT%iFZcX2J0d`R6X1{MGoHH=Dlm6=gx%c6_u4oL0R==FVo@!qEvFOLd zj)XQAj@3+HTQb8Xr#YO?OF;wo+vz=23^GWP`#xRbv}(^vJ44=tjIXJrw_#p8y%jj4 zbmkKY(TjRv>Eh6`{XjkYbTR6ibWDd&A55liPspUQ;q?MQJMxeSs!#-pYIc@5mhxNeD#VC8d+~IP_9x4h!IQ5uTOariJ(f6e3$pgJsXIU*& z^Tk3fFw*I~pl0igh0?`#8uMBclKI;uK}vlgyKs2p=F3*)2uQ3R1;J& zF#QbhX*=tJ%C*Sc3=XQ8^yxx(%d{?yCyNl6L4sGhg()sVqRU;d6=*vExe*Cf66lnk zcPGLwOzZ74q87}!;m4P66@2SHz&WBd`U4%WF&71x7VKv?RMSZGQBFxwkOaN4=*X`r z=1UK?yq2ACRk2iZy*`PFt%X6hvdU`Pb^_rFzTpa#P60BAgeEi(+uUC>=6c9Ch9=mZ zR#bru@-r*UjjNE;hLCi%8j!LJRH^KG-0ZXMG~zu6ZI6Y@8+Y7x@Fm_q>d&U)rN?uKw(o>Wq|D0=Z|;Ez1JQiwjcB(4C?wUH6-d&P5sa4sn-9**n)D*Xr4w}0 zw|Pot=!_K3i(4T6`)<9nm5X}w$iPh*q`QC=cF5V(8t#P6`lHcP4EAu5)^+*MIN@o; zzWg_W>80HoQ(!7=!o?`hrM%1r2=n^U4(&0Sh+h|jEokIRGPSU%M(rVOu|khKbScx> zV^+LLyQ83jYz$$4-vEg3hhf9KC~#17*F5g^M3F@})WD%(!y25N4mBZ5Mg{I(94>$% zp}D<4l8^l5P&nbrx}?OxBp<;&PArx-Y@-r7Oa%yU=3!@rETSTE@EuRy;Ync6a)Bw_`V}S{ z#EwwA6cL{k^Z^wUWDryNryC+(*N_15!8;`0%EA8cp9D7wIQq{GC7`q4Q{uA`-qgq*Bgp2vE~8av39uVJ zTm^N86XO^(m1s09ZRwsNu&y(TquN6g^v6#4zDEA7Ez=qqN>YZOrj9R1Pn3$C($U#z zeRwt6NWmq0^YZ2UlQK>B3(XNQiMpD?dXGjKSRsB z47aXV(y=>@hd zBhWMNRF@K?x3#+j{Q17dYOUT+vlKx`$gL$v=cCuaw#+NIiUl={I7!dR|96eGc6D%5 zw+wwPo}sbrU{Tmpep^b(!n2yN?*(_o27l%eSHO_BNpUS8m$#8fk5a6FRod^(DCsf1 zecq5z>ze@>Y-J3kycp-oTHm@{>ldYd)Mr%agM~G?eD4xQDm-(^yArB zXu^jsXl`^PX>X20DVgbTsky_F5#*e~R2g?d;+*f4oyoi_R&`K91C(FRh}YJGZBYIz z4eci&U9&KN+Qv~09%=swF)=DG&R%0Yf^<&PMS*)IQTpuyC+==EuXLmgY=NHdFMMMp z7UDxfl-(f&Kguw!mp#bad$sw5;BDksr8)~P5KUWqBB~4npf(ZKk%rE5=7wq9Lr%iA zNH-HtVOV=V#(E2#TZ({Tib#onpJ#&tmw5ibU1pxvg zO;r{G!%Ov31bhGAj#OVIFu(tL-<80$ApR>gHNk3u;s2-Cf}skIY z?i{~*|-_x@L|;A-bG0H(ia-T##kaP_0RTkcCLff8a@Fa-lQr4ru<6YWEj zW?_=cV?tOj1GyEaxze8J%lwBx5lqgTwTgU#K8d1*AKe$;iEmt+Ai+bZ}&9JB{py{uqOU{xy24L-`X zmD`9IfN(z_>~%k4%$Epkd+&y!&(pXS^ggBxKkkaeBGu?Tg1K2V(S6gs)hK+SpW0$L9HkSBE!O%zfl-;9RU za2(8t#dxIY&bM>o5;$poeDD>19HQY^xRj|oK>44WMI`g?98|X?`66VBX%N}6V6JjQ~zkqqvR8?Lo)-I2;qwob^H`88WMZbr&y)#{R1%{4o3V63_v`>mBaXfcHs8 zo(@=c+|(QeVTrX{KY}CBQhkyGo2XXt@x?SN%Hu(AR^R;twgyulq@-iDx~DIG`xen{{I~F!E`OY+P$G@ka7s#XA;8UeZx!lKeWz@!I%Gt?zu! zxCj$9L}vH74&FP54U-P!0qT=muroFs(|R2mNTU6>L#W~7y?O+q$nm!*`=J}r18`iw zww`DtQHqzCN}85%S!B{3q`WXaYulB>w9BGq4Vval`{C!+xs2ATZn%$L{^;5b-8pr> zDQ11ve!pqWi^;#-2Sa=!GzA3W0=rU~goAX50m?h=hsg{2+U=Xc^MzxC zOxet`c~jQq5X9g3aWaeM%r(Cn5Dgu<1VivCl)g)ZQJcFp{kB$#?4M@1!tWfQ$3)U< zC&R7U5c8VT0mNsuclYnJ-z2RtD`)GK2{5an{G{PYR&~{P#awi)J zoBV{#pUHu5viSF_TEp!1wpO6?QzKD4g78IXrZhwir0$1e zZKegJ0;U=KVi)*$qv&w6+B$k&mFxqM3cD0~_MrIWc6DzgjEiX@>}o~_>oD>Vf%-8x zzO1670V*ZBj}mL595~|dDZbA5d!FHv;mn1(m@j4K*T5=qr6WmW9J}|HkeijkUBHt4 zrd;{!cz1*NZ*PtC=L;Scku*o?-u{RRH7vO{vr zY=VAmS(v~^=IVoPi&<(^tc?(JPIQyM`tsNb;#*3vTun&J(-`Bq4+-~eFu#l=D=}o4 zT_R0EgBZV=$%;lhOINdRuweA2JYFIhK-TO&`4ir*5g4qiF0wYb`7_wR?ZH@G%#cA| z8Pwu6R57DQDw^sfYUC4k!}GO}x*c06Ee4qB=Z0mg z`5XDOmJw=z$uQvTHrKF7@}B$!%TxLvqkpEK_h#iQCDd1scTTQUkB9a56nB6k08%N9 z%sR_VD%r#dW(Wz3+$p)h3P!>zjaXVKjI@UgQn~X?IPeU(DQX1DkbDnv9rQC2)CoKa zCGSG_zJHQ&444Sas`J-=i_EZxS1V~cJ}5-ACvl*c38pbGoRo^2BoZ$Sl#6$sFo0ZnO8M=U>Su6 z*=-5hoDM=6DEbu@nqO8A31mTM@K)JP!F0Iw5g`Gr@Yq>L zr48hNf`d79agZB2Vw#6^ue9qqm+Lv8@3FVlBpO|u`wL&^^_@1l<#)7HfQri6Rr|@h zN?-|KjU|6RF?Zf!s$Wkm9Y({b15JMViM-VXr#v(&mRc(M=iCDrjoeXinr$B=yzQuxbXKKyrB zc6zK1J9=r%QHpqMb>+?jM8ZkI9m(9Bcnpn=Hl-dTF1)fr9}OCyTSTn!;J!qN_e4wf zOEu0$6*PhozdyoKTrz2tnuMp*EWrXflVTX~r@$HLfHAVS)>Kqr3 z%qKI$Z{;NG1nq|b7js&X@hI|ip19(^&G)7ulsivX?9|qCUmsD{+Rk1q{6bf)F3MR%_HOHgKAi>N67|yU)T|iCM~flb+tYf} zJRM^VO>}kfqAxq5QA|3@@Na5TB{bRS=Bzkh!KBPg?7-<^2IViCeP)G}f3X0P1Jx?(WC#>bnwEZVk1Cy8jn)>Pl^$IvBx@}|{j>QU#~YgpGL zzLUx>P2r=)0}5uuey$O?6zdal$%}9#H>!&iuq?B*r($x>g{&*%}2cN{3pf_RXY^m{00F2{oTzh^x};7o$#UDc*wZ& z?P>p3+$tG=^cv5&_faf85Ab`9hv7rhe=nv9z9IZRM})cg^eSzVM)@9;`C`o4ro?{j zewrt9pIb599xzNQb4>hW2Pb`>6hFO7CdWdB@ExT~Hf9rH>UfMRs`(C_=OuE5BE%J; zFH;Rr@QJu)`k=o8*z+M(lGptjTk?Vo0s9-Z#82rVT(1Jd1R?YtqB92F>wg1DB(O_j zBn9^h-$Jzi=P-~KgywI3mQ}U^R4oB$WKAb95_X0*JhYG&kS|n$`}*z1VcuVS_}Xny zyy|IQBXs002q2S(OWi=`@}2{Xkw3a}J28-eTRPBm+7A|X>%xw9t)zNxyLX@g=CIW?SK>tC`Hz);g#hQPoAQ5uOv#~v>-RB9Mku!*upuY%U z@Ak=+w>s)-81?SF;z4g8yTGfYg9C4L60a2^|7NWUh9`in=jX0T|0u0nrOaB4*syKJ ze4ciF4SjtI|-;l z5R2>JembNOPsQb%+FwMVZTz&ufia zk7hR!Lm;?+8skM#cYwo-<_~Its*u8L=27@xvY@s3EiKmEh0cuS2qzOehKmojWZR`- zalb^f+BxG16yh+GhvY(GyB(pL0Q!FWIK5A%phPumJY3?#d+)->y>tLcV=EtE+P7%r z>9U!}$p@q<=Yvik4YKk*ax1DcZ)$46#PK30sIn06-meSoBJe;9Wdqp*mw6oi%r*&E zv#s72Q-#){RSf*pQnrmh|Ajqqw!i&#BLV*EV<8XQ5S_ZhL{}|ep zvd{c&%P{@v){gfG>r4XQbqNPBAFEn>!YQeSS3jvG2yZhUw}UdMZ`d@;#cff|aiQNA z;un1nC!~B1=O<&+J<>3CMfTkXbv23`uelZcb_O%@t)<#HEO&ZJE!IW{A1`edoatBs6``%*3PYRg0e7UerCnwqrt3J2~C-5q6UmO-cG5y2hV5sBC9Uh)k&b0NGTujMsZN zHpEe?EIb^(Niv$AltJtts`L2OOb}81C=n2{`}+r1H%c5LVrt=*GA`A_18S{XCX4lE z#?Hh8ML`m6(k8p~A3nNLFK}H1#URRgD&8BNXbNK}%P6z(RAX8IhZ0SK@TTUMeAB62 z9o!Daw|jpdxVq*dBGB&-Jc_As?whB}nVluzm#@M%N`;&2*c<4Lp36^uIa4g*T{4kR zm}1~=;MbYm$_NXfDrH)lVIY+qXRD*?Cg2MYCC|B*RSyKo}jkhP%$8||uA`6>c1f-5Y$E~lt!dTFPF9i@yZt>$m^ zcSF%(L-BLXDW5<%)y@jMcjyhst`wcWS)NANwQ8dH;-9PlxeqjyVU~*&^9Qy(m$tK>MvJ)Z@tm+TEE8kYK&?U*L4O!S}D8=Y54V|n9vUjm9*LJ zn=#@PUXlI2W4a9KZBb-3zA^ItB6zn#_Fgct9%KSSK!7^&0j=#s7)H+TaHuak06w7m z5J)y2GXN0aLK4Z~1()QhEb7zGE>A~DFY)=fy$(902h&SsbxoSUxk!-knCGTR{)&RC z_1+_VTDxa)q#swRb(TQWg&J4tmRX~xIm`X}PnvRJqQdAl?Qf!vokDqwlaWQOMN4Ia zx}R;Y&&MIksuLdUvOzL(i##qw8z=-D4i8y0FR25vS~@3JP2KhwNj-U7>o@#z{B z;jqV>6^p}(3D6R_>-NvrMIGqv+EXd*6)h%-ISCRR4CoDim%5HQTnx76lTZ$5lf3tt zNRy0#lWZwCV1~f%B7eaRA^+0mv`hDIzLc-ZsLk+BKhd3%MV8#m5j{v)P^**G&*+oqu?7Hu7zX65bWQL8uy_c462p;9Q9(_oq+r~h$h8eeLdmc8b_AtAT*B2 zg+*pUCb5Fbq!8hYC%G$Jo+g>f#_j5@|jErdoJXbdir|;qJUFLgxD_Oph3c)?3^kP5iYPJ!&fPEi5*)`w$FW$Z{je>e~UkvI!o^zn4J ztq~AqhGN-!lv@@fZtf@rxi6sb$4%r=)26$ESoEv=SG&4sHH#HDXc?%~v+EibgCI#Z zxGpLg^u;6YV&9IU>c6E*PJ-1LD4x5CH6bIO6#BY!XfjhcGLyd_V83>@FbAfLfl|AU zW3Ff4qk?C5g8NjX#tw^1ST*?4pC_xr5Y|;yX=kbGsi#lo6Y{NcwkQFH<>dec$aC=> zj=x0D#}oB+ys|b~HZ}Ceees$t(29zwK|YU7ODRIuCTx8D;?X1YEcd7EarI zYn!GABY(1hTi-#?POkHnRn|N;R?}XuOBpqWX+2rJYyAH1K!knq-O!$%cLT!-1*DaJ;kG9PD(~U-PASK8?CJAqRNb zaZJon}m{-o-R;5Qp$+67tFPpIM^)JhyEczx z6X)gj(ov^*W`09A%lJq?Jqq7u_L~)&8t|}fArBYfXUC;;SSZHmnvxN@;CWBXcGL&q z>ur?|Z*>vIX-z~(ay>UGC!^lg_>QtOPLVE`rMOQfy_o=z= zSa_f?dTe%O=M0pNm?3;Da3fAgJXsjfC>zj~i_ghQ!Yfa^{N_SQ_%_zPd9&L<;vVGx zimknV_4;~~RyMhCU#5PVMMO_tHi_yrq+07Tp-i)ve$`~qAqzczdMK|-#=nSpk3zpc zv31cwuBQX`PN6NQy-U9B_up;DR~@Sk9dqsojV}#b#|@*NDoa0rJjo(^a3-XaHVY5z zDGQn80$z>F4Bt1uAuaEdsy`Ji??4NMq_W72aXyQS;fu^~;w&j|Gv4t>Y$fnN5co}R zGk~Y_Xya<($Ud{R5bA0zoTa*4Tk6>FGlo~PTCf14YbW+p`-W@aFThB^S=!{T;~!x< zO4n!(z1TqBy$kHX3?!Nu$b+^rct(^?^~)5C8TF6{oaohZq}~f~M2*5bOMfU=*o28z z=A4$!0$r4LQOSAv-ehf@byfT7-ZHf~vJ_eXrq(U}@vCra%{p)P zJI?^!S+DfrJl*Glc(;2s2JkSONh9&W8khn*@1B3XYW$RhhUc5P36cKnlpc75xR z=WKUg3(eUVwW#dzmRushd*PREvmtnO_tUlAWo;+8y1er;hEsw{=+fDgZucMIj8_J{ zhTosiz;>$aoysPH$Uv_H+g~^bnm>|@##;cbw>B5uaKZNXoECvw2rGJxn12m{$3(3r;pNb znO(yYNVjv=WCY41!Vsu8TM4w)E%|-U>K%Mri9RS%{*45&CLCg&dC+;Esx1LRJ!wGH z%Wb_;!O2P~Zq{flR+_z445Xy>(!0jvdZ@V%-N1Tm0TwhmLDoL=5b=jvT|&AHD_(Zx zEA;M{m2Vp^&Ln=&t8wO5n5d~rWci~HMV;=pZ{!8`t`fAbEDzIcT?J_9-_4{GGT&q* z6iAIN(Y7`MRq3GpQT*RIX;NwBuF!xdkUrx05thwVNySw>J?)^3-$k-6?HVm#=H9FF zdSba~(3jH>_R$jxAGQWa~J^hnRRZnb}&B}*_fUr_RF-eZx3>Al1=ds0N{e-G)TNbEIEk z*aNpq+s6_+CX*OlrnMYFBcf!{R@MgiRY(^Bag7?)w|?<&H}u_IKJE?J%}Vo0^N;A~ zYoR?I|0a0U8`Uxw)D^+1lNd3Vd6GO2QT|ZL&W*xeJ^9C5bOmg8h*}V_gCW-8Lie%Q z1(l5q(zNKhW}@nr&Yc1P{K$gdepo<1i6Ms10Dp|HV9yU({BH8~@A6wjF`yCWvs5yo z;$^rtBE7;5p;%D;?EJmDX`xs-ShdjQFm;`jr!}NnlWR)?7W4 zNvMAWjqx5(M=$-uU(t36iJliIDz482Jx#kppH>FF%@^g&Rlq+x248c>W#YcKPXoIt zGP!9=0X+B_LF<5l(wsLL2$4S>{)s{7&yTZ~^&h@7D?3m#1(zq@(Y-=&n15Uj9r40S zMDshvjbnEH(SAm_y1Pz>GIa1wRkj}gVR7;*5iqn3bB$iuq9fG9>dAXx*ojyk&530) zJ3ikVbx0J&^H_V@Sn!hN2pxBb*o~;MWFL)?6GYJi$n_#{I<}Z)b%s)))k?ghk`

+0pfmfwCe3Iiz!L4M;jT*c06*%#0Zr%0YZ^MjN3uDH^9m_QUe- z`pW&>Q8lkKY|;H=;>}C}4~^$2C6#}APGnu1>*WNX(e{2097&#f-<&tQRVXtZE zRY|tRvlq{1FaMg)TrQ!MnkwThS^pjT1~bf z%ilZFlRyRy9qCS6=W-^Ml<-VpMjDYB5S3`dg-cNo>m2^2=G8fD^~3tkZsM#L_5-B= z#|3`Bb5kOfThA+wUj75dEn8}>Iq<#j@vf8rm)ad!o(D`@p8}Wt;|vFYp(F1gtHG~y zjeD%{W?UP~k2tOQ0L)COyjyJZWqU$qa z@%r~(aGc8;|CfK2ZZrYMzxX-h)dQ zSwF({Qtf>on-#> zhK8BmJicaqCSFuXjTXrPRm3`|WxLRhu@QIiS>ixahT#rVeBLxp(Mewo95Y7$y#6Mn zdK|jEs%pg|y;66N!1}ocHRoiH@q8&%5Tw;qlB`n}om)bF1^A(<$hy~RUJ;&IoF@SX zz`Thlv-$hZK_ag$%I9L(H$fr(`aK66RR-FQ80gb=?D<-Z>MPCnDn(>B#fL#cQ=(|E zdbmNRjj&Q3q>@c=U{6dw!}a$U;L{_-CN~O>e*-DT1xaqCpYO^JxqRdFPuXZYDKN2- zOa+Ej@@G3?BW~24$cm(BW01936tVBO-(A2--a-zo{_$Kn8*?QW{|$uvVks#B$z+m< zo*|*bM*n5|TZyS31{VC}rRjEPyV%n-TlDMhdHM7Uv|_bnlKXVv7^Qg)p!E(}M)N=@ z-?wdTAMsuLDR^Os!1mf)b@N?m{2(hHKe}+(3|pJ>J|K@?E;D^*zA zWBGpL%)M+4qH;I0NcDyg;JNd1{aXHY>=R+|>UuO!mqDQuO|mF?Ukw~A6TKJtGLViWfc?N7u?iCST@m-&WXJOh zzerTj$cLi7LU$SUu;jDP$kLOs8?1%hC1ytTagVBR)bZF=cNtR@;DTewOhN^9<)d%$ zP|~78Unh=t93jKt!0#^)TpEO#lmsj0Ska50X1;%niAAjAlhJ<4{<|EO+BAIyg`7(} zt~=N$;u!uY8)>dAGk={$7Jba}&MCjSBt}`qEFuN90+X34gx8Yc9^ZuBvxnb9f0%H% zwA-wvM({^$&X3>=AYBq6t_FK|z{K66%iM0VqOKWO^MOV{a$m+U$P2jb#A#triFqtF z5^-GIvg9|DcPhqe_SuK-UYU=cgOLkR1#t7fOIZzN!;Mu-jgeLP6 zOyDy@-PZS9eu})F=r|UF?ufIu{K|So^lQkXHHpy|qSJA;`d3E=4*OV=t=jK61UFx-v3qxk9FXn2xqo9$ zcLk0XMh=c3&}3JgcBwxQ&pD0>ha`MFd8IZU!E$iW$YBoq^)s&Gv#natwggzy ziA`Hu97b>!0KfmI@(dnAJd_EU+}+Owtj0Y}|3wo={s94n>;tJjG?PG`f?uy0Q>8KI z0m3+N{*4+a zzK#DJgr6$a9`qooYV71lf{)74wK}bdDrjq!1%@fhq-l9!Ytu@$p2ur@BAOY+OlweRzH?NTcS^FDEpxxZ)*(~T4SeOCp z^uFgMfESqG$FhU;8WFrktoXc*&K88H>#lfd?t21_gW6BEl^7%$cvHIy}lduu!V49T+rhF6X9LlJZ*89;tn{Up^wudE>LIHPT>{-UQ(yke2lCC`6Ij>I-CevgDF4_zp|==5ErhL%J7dtiNzA-E;N2db%$wD`3I1tzw(`97;&9Fw+Mtp9bBE0;-{b1S z8z3a1QPw=B7WT8wOcPGFj^TDpWDJvT0LHQ7I2YS`ak;zPKnVF9Wg|0z+=<9xA8kO_ zCAwp2OX1gA88@Vf>q+oo2w)0#1VrxZhB$P}=Rhuh}-hTvkKqbG{R>@$bze&F-fTt{Z$RDa34gva;@_dJU3bfi$v?^j;WRp0X|2 zUN<$hnr!b&u6S9jBfG@X&XdV5@1jK+B|_3};jp8Z!?`wG>CPvM!~qLSZ4%5W7>dz8 z8)bNq0zSIHSyP4D^^a@RX)C8efVRXAqkGO&xhWPySd2;TaU5sT*4Tm)&vhH zC2xSgkZ|*sC+1exw1m_tVCvC3V#yQ{k=T<@Pvw>XKbH|h`Hpu|&`&JQ`XIpsPM>8f zB-4Lan8GAs`G{q9fIa)~kZat7sy78!fJm(BKtAn)F2}<{t6omq`($S|}x&HgVeWewF0z18Zu^i;ev>d-DKoLCTFe+u={J*=Z zQyh_DT>oiFQLoqPW_cdb$o0YupE?&kqjc_dwP?IrX$`yjkH`_u>VCCk*!4)2tG7KP zQOoXGy6`A+ZjOO2G<klS05OMwnztzspc(fobltrv_(tGWd;d^X?y4=Gp_4b>jkqYP|f@R5tD^gv>!~t zT%vi;1lP-|u%?(aEEdvt8R4y|IcLu{_Ru!d*wH)Vf9-vkU4Ch(d^xt>k{+W+-20O~ts^7U5?iu#E`?e$U&q0c}8 z&yH6EJ5+19Jt{cO1Dqw0?Pblg`tHoQy}-t%=S+2o9d4@e7$Nyy@%#ign^G(iuzamEJEBk?kzyQ{F<4; zbOV*kKJH028am2!A!-b7TK3&0LdE=m9Dp7wB(Gp`{V|Kczj7w{e>8BwNBfKI@z9SM z1O$6ejUG>)Xg+^Unqghf!!1;@F^I=&vyr*YnP5*OO?I)RJRDW;1BmMcDdJDs^@>;? zJ)>cr%RF*<&G2{|Pt$Dn%_IdBY#$z1zSYRK)H1w#9qd#soXaJFFm*d*cumHbs!06f7R7&cmvlJfWtu}Pk3if!rpH8P zbqeFm;N8_KAGodE^q1B;k{j&RE{=yVOQ}7iI>_*s+PaD08&Gqu6K0>0Wkg?43#=OK z+?)vd%*GU09jgO<#nNVPXfjbC2JKeIcu(B8a_>FoO-4sGlq}@&5Tz{UW3}dFx^h4- zs775!{2G4=HuX5sw{IB)qrh{+Poa9~!HGv@Ast#zTl_^oDg0Qa3_Ctg`fqj+{Fqh= zecC+B~LT6mahpj9kf2GUo(w3FxZbzr2T)#OZN51qd%<^&}aOImqMBy_>jD8 zZkx`hrrVWWZd-9mJ=Rg@x@$)3>SSWvmo-&kEt@eJ@<4R(F3`1^?MtHJE2`Phv1D+= z7NfD35VgvoOP+ALuI)D*<|Pk!I0O3uJWgF!kJPq*a)mC#LFbZIa|u%)fP~N3iwSTVB~lVEDD=nPMJMwibv3S zdW@T7*mMs93Fl@wmB%F`c~3?H+;xWn>n?xO3xnGFQZSCvW}We3MMK0LXu* zAlD*R{$aKwmT<1)!`wPKU*8>9K^}Iv!oeKff;9t2WFaQkhRQ$0$zwz~A`6cde zf5LqpGELD}x#-iY&@I;<>{`05X^DT|!S)Xu$G=aMgMObWC-y4;ElO2=Kk&aez9ZJdplpEAde@{RQuZjKDzK>BNXjr-R%;xN88xnSusAJI7E0g z2nkc%lu6})3IK7RHELvGpfrd*y}W*KySPMXG$yT}>`oHBw@V7C&ce%v1;o~FRGQe) zbj&HwaqI)+@L&Ocb!qzCK9PSL)@IoCIiZV371c4nK4j@qSwwdUd_6gNOLRpTp&dap z-MW@k)Mt>iktRRFW53*EaVGln9u}NaU|$Wi7K`vPWfO{@wR+w><7W}}L^P#?lib;B zbbho?3z|ZStPEt@-yY8*12^L4a!;;G!X?y3@;G)|B08TB*Wr?j`X+zS`|+#ofGfNO zcr(P_@bRL1%5n78yq`U|`yzPK29<|pe$A*|A$eiBypSI8-Wa20g>Qhk7~4nS@rL5} z^Q{ej?Jw(h?SEkTZ_*F}%`+Y!As+S$eilava6aw*-LK?uodqjz9G2x&Wlw>>7MEoW zm#qvl;@Ohtrs>5^(xHC}I=BXBo>kY~Vzu=GvwOU2~^E(pl4>{yv#s@9oKL&VTRg!;@5b<+=O$h$^V@TYv z&LjbErIL9H^zG}*L`SN>5uPtsNeoEIt*P`*&6*=yPfMcULCpb7}g!D^r%~WLNR4 zkox68(!b3SDms7N>QV}>pU1l#UvE%)SG=boWZMNG+o}y<^4n6 zXiu4?&Ko$^A0oA-c|9G%)0w%ZG(_=?`MPTqyC87bd(OS@t5bX3+C{7%(IYwB+UO$L zk#4}Z;h|&(f`RpoAf>uYQwuSmXrH@#Q%$z|(Z92c#%F)_Wup4?bMKPZ8l5r)KiEwj z$+fU?qrIDSqmgKW<3=)u1n>;ix=I%9WE}wdWNvFJl}sA-oc9Dpa`JRI+^-k-erXng zFNpr>D~}Yfw$^!@H0tf8JJ2L49$DWncBLT0UM50?>`udoU(wP*!~Xx~C++ zKStZRurPm%Qr&{MH@a4wkI?n5qnp2TnAFeI>K(lLnX3JB#`oJkzoTzIg}YGtm)wnb zAAdxJ>kgEZUXMXo<4Nf1i3HKgwLl3Rz4ySvJ2dP!}aWh z5MB3$pzm`VXn1u|z||0DC0kUqOR3**H=0<@n)rWx5K~O8{eyVrl^-dwV4hgKPHEj> z^5&S)y9y`XsjzRmh@#%VNda3~BA}%Kv1Z0b`0Cft{PZbbp&+o26Sr{8{gj`R1a zIUm1;0G^;9ehtA7E94*E#1Fr1p!%+j^vACx$kg(KYH9DYnsq>{6zucNL(uKB>`lK^ z(fWV3o%Xcw#V0VJ!>Q^msUDWHX;*Ng(bSDM@C=LW3Y$@Xa| z?sCHAPR&W(Xf|bDc)@-kHhV53-NOWE$NV5;1yIX9lH1(=L?WKFjL+I` zo7^_k*vRc9JTdhkOWQo&24=7&2ta(EORaxyyjwLy+rDa>{r-WBoqylHy4q5@?kKYj z#l+c2C+48Q=q=T@8?7}&`WnSp$U#jL@xenPUzQ`_nOpbvdfb0=|>kZCcC%| zX-WG5-#a6YFiEf;a&xIA5;mXEhBX$tzi-?_p)&4y2q=c3lLzwPyqIUJ85=T1>{0B05x&ADjgJ!rV_xD81$@x@k6v zJ9i|x#iVu!m#ftf#+Is|+XAwpk+jB1Au^JgLj&ciQ!N^2DXPI^bY?}ZXfs(qJ>p}O zc5UVO1BV>q=|1X2?kU9rT{`)(Jzjr;eJB|1RkJYIK*I##P*t9l#y9sGjqKw&kLSlk z@EAfQZaANXE#V0+kDfDVyPR`@dbE<^zAEZ+eKgL7e$383e_i&@eDlnN$nWX`dOG() zW3rc_X2~&!!{^;4tUdIYBZJC4J)tJ)dYflXJA$vxWdvz|w&aJRrnP})^TmIc0G(T2 zCq-cT(utUJ7j9C!SD@LZs72mK#iC&_tk0TW72H8_z=ux`a7vx$eYrWevGa{~$|GPE z-KTQ|{k$WW|6q-O?A-k!0;UJKe59}9xEyrTqB;SESX%duPPT%D`^HuLg{!h(H2&6> zlnzfZdM_~0&nwK|U0|S}SD1fq3(VuUOWQ|SO~8-R4NW1g>L1Nrich08_#4kOyo;!T zhi&9NRS509FJXAMKOKyhCCGei7jDkP{mao5)>X9S4rSXy+p-CcR*ZJ4lR3X&zHyl_ zOWD`y$vg;pH(T2r<;IvZ2v6N?c>eIz?DB#ad+^*sskFTxnhT~rdCz~+bS$!6^j1hX zL)gS-$hyNLuI-Y;o@I=yh@v}3eCv7C95nku-V;a2aW2O)I5^|JIpy|4zZj5dDL!_|5yuY7O^_dwv>1fuW<2&Y7W6O- zpS;>DvmhTAoV>t2OmJI{5MTS)-?)k+Ky}FCys&+`!wum!=D~lf2{$EUy-E{uJ`8pF zQn)Gh>jA5BdKn`;ta(>LvvG6xt|!=s9=T}A4msy}_qg0LOnwxY>-))FO@{-jDEL$K zUF|d}F-l7Ck*_eBvljVz-};Q#Ff)V)XLBFT$3yivoHgN$j3_HL2L3c(ds9J=&)Al$ ztG(Z5VYdM6HHZwAKT>#@w!!*`Z)e1e7l0k%FNbaAF@_q z#9z@e`EK$&r#OGmvdH^CLCcn(XxW>JX+P33lSMVb_}@;;)W1Q?1QoJj#jy`dU27N9 zOsEYNC8>YDR7XF&Jfuekqa)(qT=Q~kGEqOm{B@C=K|zf`%Q7K*RU=T221 zEBAjmFH^XFlmxxJjH=?|bD4z`qj6Fr-9r|6G7o~Ml)w)%1=SE(mVmeG4)RZ>Z@?w z=%^`|q+!{Hp5NS@KAi7zyJfP^N@g<*y%B#`+jOeR>9CY+EK*V8djwb*uk*y3RDqQi zSbccN!&>MEC=19fHkPgB5{g6@-3HYrlhauuRqPqVEZ;rLJ}$TsaA@9Dknx!#dI52+Q7%}R{(x($ zZ`~l)fDuF4N2Ah<*52vE9mDeq^fLCgEK)XgX5)ko8$577ar=%e+wwNW;4$oUtj}V) z#$N#EG5j15mbAv{6SYYNlb*PUSH<=*qaoRZ3l#UwQ#@vm*gP&eWrk(gFl>0g462V2 zKuL<_;*`N9Vjfl@k3@ezdR7!(uMz*iOVZ3C;$g)3K=~O9;+$uDtxy|v(Tb^|%J=}R zqWjE_&g|WrOL$5POH&MX#vp}x2GbD?u18Ucj{|Xs1vD@-=b9Nw#I}(X7Z)@H?|`#F z;8i~R-mBCi3hE|77AKtn72^CzLyQp!mo^3`mxeL52EHvv)O&x9w_Z69M)68ET#&1* zI?eYLYMTl|&s%zDX)lxrtnktMST63Yk9NyWn(HB%%M#8`h(TV7)iTvObrk?L?OY{f zUpUB5XpP-5gFAj~|7Dp`|Nl&$)zuGIneS5XZ^`w&Gt9Pi{cOIsfA?6FrJ)}~+yB|= z-=o~WS@=sQ`Rji{__wtC7UJT;9v^ODWQgq)t@N$Cnh^W&;?D1icNshMYhzRdf1A04 zd(fLwJ13q>_Tu60==P>|A>@C+bQiS2-fXg+B_Hht%HLKYllK_@-YJgvX~pd{@J+Yh zrS#CfoC&_i5Ce2?T}Q|s2}AGd<`(fH)IJVLzI)Zg+d_Y4i{a5=Z!T|CX8Dc=z5BZ+ zvy;R|Aa<}H5NL-lgS%Sa2jkUQx71nXuDjSd_QApb`555bzrMA9duPD!ZtZt>_N(tH z@O$G^b{&6?*b#)`7xD5*8^5Wc8z^V+dGs%%O05~so{+=aL??*tl!v@heO3~)+dPvBGKE}dO-lZUfPZX!II z1dChN^;)<@za=z6&6rM3$+`A;jWQG@_JN@1Q%HXS>ToDwk6b9rx7g8DLgLXVyE-^q;|A0g2 zXkUMn3U@bfi+xyT^Y#0*-DRbzy*38?SsXL72(0};TTTw_-s>fsZ0ta(#4MWJUjvcv z?OEU#nV8=;y8@o=`twv;5QGi01Dyyh;}4SnlogVJvDP1_=b?t-<7>7@XG2Hv!Xj{M zcyxWiO(vWy{C1|m-XrgaM8F|2fG;}Brw@PNcBjxrp|rR@_-0F!G?+ zviG{xqnBZ?&Qkg_8OU*|(fmtmE`fXlWP>}C)?ya zSE5NcQJ)i0SW+2{do8%FEIFZ30bL}68ekr8<-MUX$`C-i;@Ki_wjO+-1mQDH2Dwswhi0<6W@-1-PJ;fy>NoZyPg?H?CmNF z+$B{ukU^5Yfwf`MF1!Z44Ls0&I&7Z{3pU*Pox0k#_mlfl5ZTKz(ObTCI~jaSzmW0% zG6=Q<3$fqTUTE13QK6l+1irP(5oG5pgV^4c+s@r!1j6=S*v^dpN5c?KdXIl{e=?F7 z@kY*DuF5{P?+WW0d8Kd;j9!<&)N8sxA4d?Zx{cZP-$R>-RhQZk44L-zMAt zwb7_dyXM`AmxKt0Y$Lk~gdTDooTnx%)0_AEkDi3jT z&tH$PNK6m%aL8Oig$?)kl+isPB#+tkSKqo>5Adj ztTe5FMi-hX4%fRauF_*Fu42YI(P-ROn7;#){vevGVuN9TMON3b9C;b_6Z=B%&;={n zj%XuPJiQ1gcQc#8U10=`4Bx&LckbTjPk?N^B`gwdZZ0dr+}lyU^zqGjFan)Lb|N;Z zerRR-e(~B8joTb1)o*{4UiB@l3;ag>%lOXoWwWbf_H6G+mgU~(zw}#xue5+Zl(v{) zZBy*jNVW|QG3-xGTX-`eYYjqqBX~C_YAq^Y?FZ)>3{%Rv=Z8jLMt*)AC2k7P#c)?2 zrl{vCyqcamOUBVTy^J&2ZaaEB5gLcfha-S+ycC6Oe2+cQSe1Y4tG<;K&L}ButoOB= zPUveHL+HGS4>Un9oWkP~n{>^EkQ;`XIN+o`Pz)@~GN$8T>T*4y9@uh%m@M`9$2FHk zhK)QixX3L$^?t}X-B9NTBRMu00V+6Pm3Xpl=~|_&zTv+Tg5M%0oB-X(eDUL|=y>*Q z3?pD%2O+fhjy``{Xxu*7GPwthzruk3xOoq{uWi-?RZ0ry*f6RC;5%XhvW+mhkiivKri>t6um|L!Y& zhoGNdh5oB>I7mPsNr5B@A~*(NAca#fMS>8F!U#fae`bFOrLeCJGoXFzM?c1kgB=NC za^L8;{DO*i=!)MN%kGyM{3nLK)&PAY8j1hsV`yflxW1J|H(2^GzC^%1qe_uI55nH$ z+~h3^^IOZzDA{wa_zibE6Zh?#z3Yjl-_S4K{X6#yAs?n$@Q!3;v?CV$cC(7WH&Nrw z2La>Vv5S9v`*>`C8T_-nxVrDkuTPY^-ehASn0pWTFAeh3DfSN8<4fdX86f+`nqrqq z`BMsIuukq<^AnBg(-?_b`aXZs{8BfJ+_|%W#?jzApIUG8`yh8) zwUx)VY>@dkZx8sp_xEq!9`JYX@87&V;K%p(Yf|<%IhiLjICTn596-oK?aTz$>9HdT zU+>xZDH%{?Xk_lX=smt*N%}C95f4TYCo(1viyE4IA2A-T$6f%%hXsMEBhJsqIHy}j zH>!U@q?B5$Q&d%7X-hvwZ`~keF!GT*x2*?zie;;kJi-of1-RGtO~m5Vf=>adTUZ%P zjc7edTs?xp0)nY7OP;alBz)pm;gFeqeH(Zr!0-}G8VLn@UQ{pg)ku>`>e>a#he=V_ z$-h|1`GB;CyjYuviWD1vmG!H6P&CQ2Qa^vtugLc=MgYjBqG{~1P<0mbHDVPxdV>e^ z(mkbn9@{tx-W5qb6^T% z34L)e7n4VDsNueHO7q;ZFopT&+zx+r40O_4>S~8BwOr5C9zzP@0>kiL)-JCR=zWw) z?_{@Ttc4sAxomW~aLfc-rc#vo0em!i8ex;_Hx~9FOtIr;)-W)a)gM-T4gkrZwA!s> zG$Nbk#fGAkX@k_2S4%*-db!Gq8M>lyc|OL2$V_3-(ibUQI~Wg;>&0Av05^N3CTgxA3M>De|g^F$QW>J7)M8)Eap=x2^ViMXw>nde2x<|If;kKZN!VE{Nmh58=^1yFazMKaYRU^Zvz1%>S_~eoBV? z<&=LeTT;+IUjpL$SZWaNAen!@;SM5p&SV(A-omM@Ie=1wv zzmN;bf$wvu8$fyX-bCZ$N#c#%7YuBByo887|0!6_&*$${>?Ie&h2i%edHF6B3a2$% z=;a@|*`Kql-m;~i2(Ul+$WPVJgWrzL-uhSk{d3H;wS<$gWr-&9zLjrxB1Sa@MSrS* zzf_j|KC{yrFqs*`sq}xv@_W{t0ekZL&uZ6yG4%VM*J|HpRkM%8R>NcH(76I%=gwhr zU9b@F2N53+*5tod(07W}Mug055`yqY8FyJ4xY(ZO&G`gRXBFhABVAn!o8i2n6>qb6 zqfF!|#-w^klp&yrTNW%-uMpy?5DEVI!e?NP^OFo8dJVcG`4WG+FpI#wksu->!B+3N z7ufO2ap=PeE{^RzV=3&2d7zCZ(^((g0^obeI>&|nfJpNa&=PYkU{|p#oi|;?9FkuU$*K2!Sq6DywXyX;|~289F-H@sjYvS@MY1dB$|w+ZV!N0zoVu6iNC($N+`*9leJ0vFN0wjC$J$za@|V_2zn#%)Qt z?v2lz;p)%?y0UzB?JQG938}h!Sin|9TmVaLSLu*Nh0@0bczT|OGQ+$&S*mXeuvoL6JorE17+v{3wMGN+2Nh-!ZQ@}_(tyzj_2+M!osghBf50mH~!^tQAeQ$6K9%+$O z@gG(a8GEw_ofm74SJ*nyb+bG4iPPJKuSg(#fbiIDdxl zYx3c$ik44o+Xef-V_OIObkeuNti(zGHYI7Nb>OhO*;uo|K8!J*<@sT9Bf6$Als>W#XgJGX!1 zux)M8e69TFh@^+uf0ey28^#S^LXkvBAF`PFjvr>DcpM+e&=GNx_L(WRl!X<+4Fp_j z7}-3jvRFFZAtWN?n5kDzf`R~0&|6*R zOG7^{TUvO~8PBz-cv2;i{j~*obcxhhM=;GN zBea7xf?gcU^|gepEK`0+NZc7oP&Swrvv2ExFHgWvLnpLz!2LBS{L}TkwZwmu25v|y zZ(kaF@LA@zrMGQZQ$q;Ho$soj7AWeSp1)Ue6np1+eV)Ss|2Cfe9XtcSwST6a_<|NO z7?pt?2t$xwRwwR5+KU1UO1jo9Wo4WY;7mx#s>aE-b8|T^xCB^2mnIUfc3w;<<~`}I zxg3@iF;BHfR<}cQRxh^~4NHH*6k|9CB#&qDI^Mt&O8ESZ1CQ+7TZVn?U^zY)u0_*B zCgf0iFcOqH!{;qq_mLau6t9F^&T<9376|Wxp1h&{h}cQFOj&lljxBkyi1>^-uG?W$ zTE=;zj#WrNk-xizfN7o4%J%*10Na#3n!WVsOXd`N6j=>cuTEDn{k?yZf{q#GTV90~ z1zP5Vr-E_P*5YC{+GJr+r0^c#TraZpFfWZ}C(4*q<9JoVv_P)RNvLxQ<7(x|Vd;Rf zWO~B>t?QP)C9G5OXzHZ-dw;2)!S~;v^c`BQpqPW^55f2uQBfF#5s&~$kl6k~z$k=K z6a_&jh+#Me6CjS0Ups$TY!J8$T%tR=?GTLZrd1o*ZP1n?JG3Rxo&-ne+fgd{5_VH` zS15;|UC(<&JZ8r!{$X)1i zSMp5v(Lfm8WjyyaZ!3%qXM?7=3f(-%Nk`?f#HARXzM?>4#`1 z?m(Y%PgfCxd}oZNIrI6>qop9x66!0SB1a#AUjXf9ul%gC=y$oJ#(*h!_v70cpg)>N z{cX_xEz4b0Yj>~USM{#0D)dfre?2w>mtV8oQ}o)<@%e2-Q)Muob}h`XhN`gnt3wm; z+obhh>Wl-l+*W^2eO24WX_I5BJ5a4`xGV5kek0^{!N3qME*gmkZffxn+%W?qiezG= zy*87s0Z7RukU2_Hj?eVm3pZ?;qmmMi!Yqh4tkJvUO_5w5IpQ_)YV?~0h6vA>$f3`D z(}sE=yT%ULJ}_qFkcgGF@fj4qIcctU><3mQs|xfS-?&e>kes4|7u zs4T#e&wApC&ge1)OY={wBz4FTram}U_2U?=Qas8}OSbVdQB94CT9kDcUTWHn7E6x< za5|37qAKGM!SpDnQM}L1CshyOR-W*wo{uh}rWafdQLr!WM8war8EyHq42^ytz`)%x z4x`ERjrD(I#+IUKVcTWB09^(5aI!BQql%9Ef_P|dCmHL6G~l&3fNpv2My55rfNDT5 zHO>t!(#6ww>*L$GN+`S<`+icCWhj*y9VxrjOdm%s5kVfIQ%woP71<)JZJ%iCP@|P!OiVEPF(8%Bg zpR&mFX1XsAW0PZYatmRaib5NQB%m%hVqARhoO_5CED15rPDq@eMt^NZfX@`yD%dM| zAvN(SGdiWw`ZLkoxT`T*nHfm&TpHKa4gI^$C2XU5S`z*==L0ocxdyoHfft=ndpWE# zp5%Xk@oK$tdvEr6vNH881~RZwt;qS-=HH9#!5)@=n+gQJ`GKgbepD5QEp)4pCBhO_gD&~Dy*L-=IiTvAC${RDj9RzoAT5L)>&ky!`C+~@TakC`_ z`gJmoh~qA}b@%7{5sPSNyk$(9G#ERPA?9@5gk*WIDvgBKLXY?kPNOQ7Ut*;W6u^Jy zw;yj_h$U^N*GfSwayl5`3D%P1krqAJu$1ss1}8U>%7G#7rW|-SnA~i)yS*d20<*e`^hNZuKTY!c;6zU)= zFOTD8adxUEO{J*r9vGSc*cL7%{CdvV-s1V@VCQ)`%q!^0=8F-_|@0U3{oOMtV=aa&$9A@s93 zlws;=�@aYiw#=gz3v6omqcy3)i9uz0yy#xl7jZ!QV6az+@*yZz0jHeMNunAr%$w)r)|9 z3o*c78<%76nZtK21&sGW#P~hS_fcTkqBJPk>n(A*S3veFQG29>?#AQ43Cnic+?!Ca zod806a7LzY4qmk1+lMtd74MPOcIn+?6xs_VJJk)_Uznu!H7T^eBu?#g>}?qm@0Fb` z^u+#|PyJSP=sr~)uAG0KW|)zB#)Mxmha-g}J?md9b5_5GWqX~$R+-NViE0Q{6WsPN z>_bib2X5S%e=!K~cGKJ!Iqya9Asp4b?&3J#2y`PKIC1wbF|Z7?Oa4T)U2fSS|Kt4O zxAMqtfXII+Z+;g+U-_Sp-I?kuXR`n5wtu{9;D2)4-|u?o0sMc3y7e0(z{usUj`2F} zo&}L4;_Tq^W)~0mlJqp@-9HlNpL)@31Tg6`=t8AA}+UDOq+#s#e?#KQ`GY{$#kG2<}evF@u}8Y zAr>IV+rVW9U^agy?#^9&m?gbqkzEEn;h;f#8Y+`(zUOSwT~r|c2pxsOoWaL&9v8U7 zGEl;=TI8dE?L}D|9joyAkW6=e)toj+&sqdIIcOiPmF4278%bPS-O?r@-f4|}T2IiU zwJE7bj{tq!qWU7oma`aOr^tPYXv95OuIXmOP3BoCkj^Dp=>aMib2eGk=`(|)G()d~9*tmbHeQ}X-@(NH+lMvJ5TSm`4> z9(z?Bp<;`4u09bDQ+jy;B0Q*C7CGq}Zz0DxCKG>e8a2y7OT8(Ft&9!BBRf;f_0qcNJb>zeQyR^J)U5n2!xt+XAA@k+c>>eLE}7 zA?r?O{5+HYjlAV2RDEN>{qMo^e{!L}0O!va`I(PLp&MvY7)4ST45A=HpcDp?2u$I~ z2AzK>h9W5b6=)LFUVjg$w}tjwdI$;j-uwo8TmFxxdsiNP^XN7tg1@e1>^Mm7qea`P z_*--6Lv|>9qi2lod~y{0){KDDolZx+)s>Ln(ed_IBzF?Pu2PNeuTGFV?GDD@jeBh8 zjqgbMel~n7VQ;s(-S)2C6z|L8HxGeG_cedW+b49pW<=}|j6?qjnvXYVezp*+viaKf2Bf+-lv>*x5PuStQJc8o1$D;B)KkuQW5!Cud0CoSd&v}UvI2Ci`XmcMMf^W&)5BuH^Q|XhMjcxf(vK*R#SU?|v*Tz?t!WlTq_ux9MnjMx z4;PE>bOyhV<{e5#_i!&&eUj&&%rA7{OFxRQsq8;VR?`%A)$Gs!tn*lt%B2uq6IT%u z1=_b+oWJ!Om~1|^^ylKQ*8aYLuRbFU?uDTfi_8=f+UiTQAUwZ+(hd+Uo?q88yx96+;+_vmyd6Zrif2|Ka z{NDo7VOG9t%q;Sc&?aq{pbOqzJ572hukkJ zW^V^mi?%);O!kq0BFZH^?DgvDA_oDm0=o_E?p|YQ{5XDcQ!T$I&8~xDb z01Vsv3=Do94*T2LFf~*$_fi7~$|Nuo9MwKdF^@kk5m=d_|5ApFU2#U!Zi(G+qPnhR zU$1kr+$q-Ul!|ezhlR+N16;Hb)D=Tnd9cc+Sm|ul)OCMi-O|lh>0f7ULkm-!{X zc$IKCsO|u-g^A8##mc-2yx5$v)9LKArJXintA&&nWhFJ;Tl97s5!HBV0~wWu-!~5d zq)(@oABon&AzrCB$N;1gt2{4Zt~OgI_97#BrP$Q%iB({9TV97+1p_7z%0Rqaw-3Z} zmD3A^I?{iR$Hdop1jtv$Vf33ZvfH*foiN=i3OYZLGQ6c7=NKi2R_VFo!PXW#!G2tM z7So!yB!|G@Mh_Xl4=?5kqvxAdpe8wd8xGU%TlDpXg~MOj=fIcr^D}>#;gUO?DUps% zPtIG3eo}Xzowy$zJ9ooQ;BOcIcDRg=ge-6oEs1}CW?dvd^CWu_L+O^HN}cr6D_i1{ zzS^XqkjTU59Y@#FJ~{FZ)Qpv?-kxZgio;6suMAu{VqF*|)pqr& z;gLqdt#&?j^>UG#CMy(#;ZVpHRfqQp=zaonlhV~okg0}uU-Y!_4R2itG7xZ@I;dSz ztipfUqYL?bodx%#Ag@cQ)EaNQ7->$;3C>=ae-QjGAWwwCGDlKYWZ#^oAV(# zN=#J47meVPUN+;V<ibZTj2z}W9gPbQt*e@_S=8U zh}ax(t!UP)Z+$rIvKF@ z$!?r;C;9Qdxb9}7i`RE*(3wphjOC z;qma{4Dtqg^j!J6oPjc;!`glNb_P$xsE`Jf-jiEJXj0k8l9deGT{t{(utqAFN@0A^ z_me;q6IflIp~l7lpYhf`UTA-BO6>k-N@jD?y_1u`i|Qw~CvqHhXQ5?AAK2lPE;kj* z8C|q^)H|G!B^UsaaLzgrbB^^~)bD58!CIp_+#CP=84OH-rw$JDA)IrH0}*pqyT_Cgf6Zhy~DF*J+Zku zg?$mX4arQr2g=%+YZi9IU687d2ja%ojkke**hFG`bKs&3^Fn{6fhBy(X^qnbgHEUO zm6Mfh31>YpmU*74Q0PF3jhLywY6Z?*wVA<9=Xiu9b$;ZC;xIrdj~e1`?}<2TuA28% zT2xev@UELlQ!@xq*<1w6ze)=#VI6w1ZjlEWVK>A9%xew-RK%gUKaAVI&lpYXGmUeR zZ<*W}RDYO7)&zg!^O1arG5x`|zd9oSm#2Q_e?Oh}lfMrHQxvgfd<2Fd6t(>W!M1#F zxBS5|5=4kC-@~vk4ga7Wz&2ppa<2_hHb}$39V(zVzZra66mPhKzvbB@>}&I%VD~Bh z7(&9{CCuIMCw(iQB5$@cv}PcjAXk*MfD(C>d*jo=%@;J4rMhK&KSv%a>+ zF}2Swr*937Eq$bZm{H!TUGctbd&%^z6Sb>qfNuxFw>;H{s{F3eLH#4PnLD=KKc$FRNTFoTr=)zD)LZ2H2nNHRXGIEf!9Lbkep22+L#9Ubb}X7B%*|=Q81f zzD_G`f9iidbERR~Ka>=uQ}*4nZ_CNbRpq2DN0VN<{auD*KgREVelN}bV1WHJD*R5Z zTw||OTHD<`J=fUMs@r$jrtAunPt}O#(>Ig__!;AG(4W+>tI2rkKUnPjh;Q4LbeM2I zzOs_$j_RxM)8LvtS8N>qdM?dF=>I_ z=TTF04t7mtESEdFRuq!VeDj2=h?QHs#))kQO|n@~TfIoz_NJ?O z!?YhCkej1(i>^ps(w#j|9B%a!YoGF2D2min^n}w|`F=;;b56vPMuotu=#_rKsYpRi z?5lsRO3_$e?%4OM<)~6~#GK4ZpzC?jf+un6qcTS+|E#O8@o-#jrx_p^e}T+!&`&q) zN^#`T$fN5;aB<2BY7~s0V_Q9=&_hVxrtkd&u8G&BARw16qKg)AK#*Lo^{ed1qH@v0 zjjFNZOjqFdl#5k2;QCDsQ~xmQ{juQrt2Te6YBob)5NA=u;lt@%ith2n*jetC*YC&! zd;vXop;*Gx%tXCGJQcx1^v8jFt<-s*>#Q=F7^N!T(4+%r;S^Am&n#w+Ixi_v%(QXZ zWdRZmmPx3Yp_>LCtz;UwVeoVh*o0)(2qQGtLlIw3lXswTgGXLlQ;z@>jqhhsP?{vj*NTDCD21h`ey3 zwB%$s8|TrAYKWsuU#cs)8KL5FtYbKG?;#h+&WTYmK<0!~+h^=`=V|+l2mYR= zp%Quu(ZQ@{-LC&$qG>LMVTX!8gmxdZq5t@Q{t$M1kw2fHgy+F@E4F_GghIYX z7;-N( z*r(@?F!(3J$n<%nMg9W0?tcK*pr;Uq}qHpJmn=!2K?%dtCi`ZasvOz!7` z<_(Fv2+`hXBk?CuHNF*m-Z`9a0YBcV0aNcGiK|JE5+5zw=fg^W=}CU;pk?oW4jK!* zTWA?iKMvM2ZHJP}V9OlX@bS;)!Kf*^6An@~b zW=K}%TdQixJAd$6hi2~v83`SFy(`3%s*3SwN6UG(qm--VilacvZo3uku>%l>JtK-6 z$gng7-!v`1^gIkn139BjJdclm>BUb`Q>5oHJ79T+I7PP{;;txV#a{A51mK}cD&(}% zhJJL0BQsvRY>Hv1b`0yOu+9J<3%N;*yUr9mt)v=#C?Q{3Z!vzjhdmD@HBD~eVyYar z93|tAVTn{XDLjwLaWr`Dv{bzckJ2Mm?$4DUAiMJ2rqy-tlo)wXd{W$O>9x_ zbfBsg?cyXpbg=9_mK)fA-9+&c&e~0FIeI1~CqLK`k{1(BEx<`A^)9(_TvOK{t3A#A4Eq zzH=)0h&@~+@T`LuuS->iUUX-}zz-xjjKsp$b!;hLDv(KAPy(}mfjAyuvdj|h(do7T zd#ElHLN6mX^~ihJc`#n}_J{Ky>%f1esE=Lsrnf%u`d7IAH~mRxvA5i%H>#V9qk4Lw z6Twe#?$MAs`j`IXzWA%Pz`oeXzNv3>}5L z;Ec#sBv9)XWp3Yp`SKZk{QlSd_x~>Tn_o{Dze&t&f&(aKkYqs6NS@YMe77mvoU@}z ztTuW|z(X24!F17cC!JnP!etz6j)gF@*g>zdEo0V!oA(fJ-06wlx`V({ofCSLFYyl) z)p@K?#CwBeM5g#&m?hLXdlby}JyNAtxfYHZ1Q?)0>TzCwOv|puu6(YiIUG=0zYHh5 zMiDh8X-`kpGQn?!1d5i7vv$y=><#WM=nM}m3xsn|@IxV*OJp1jbbMjzu^Goyu16C# zafLK2!H__^50m2*8LV z-BH3;(59|`<&+M~oV+4GUaA}3%CD|&j{!gs%6yRzV#r7j-=*!_oeyM{np9J}isKu@RZdgMd(zUzQxoc6?%^wj-GdsCNsR3*C&r^MhGqfcA?Od zgP;3<`&8)DV}d67K(qSFz=wPsfonuELsFxQ6K)$+xaz$Dl4V&sWIcnYl-c#QQ9qUc z2jQAoR8#W!Zv(b}I_s|?+s|kG7_?yo2qGi`Vh98g7)4?Dmlf~b2n7F60PT4_5${R% z_8^V+R67Fq3NwMdsa51oQ-Z#Z*|y|72=<15?T7YqlI(=wDBRggI}JJ6qqW^9INj6x z6x@5ZTWko$d+qt_m@Ryp5To&4fe*tyYzu?EuN>mUD*K|8WCUFLbuYF8@7{mg9 z-bN;1_H*C#^k+=Ak0KjCC_>OL)%!7u0`~GjDEd`Y{17R9c5&%NvuIRZB~Yv0UEE)f z&4BUCT-bkmH^5Ip-B)+>4{_W6A+q1&w%0`vQ%XbCG(wm3&eb=ad>s=~JH&bvcIP{8 zucG~W)(XnmIEreZIsvB@OcxbvdG&;UKJt=NUL1ZFYmRyrSa7avGBfyYZLlM4p2bNh zEHlMC_lb`Or{Ib30eBX14K=Yo9J_=tV6f?F$iW43IWpU>ho9K&cEHB+jFtxik#ERR z7CZHRD?o$9ts*%AO-S1ncMiNOBw7x`J~~;%B`vs}?p@J7F*gt+#IF=_^_wSucrP=; zLvS#|A2Ze5Uy%slw51Sm`^qVc9;f;ixntv>3%I;>Yy#h&s?e&G&poRoTvqQqz`;o& zF2Q0R>{FijBap}{f9@7Gw1V!%ok|f6ICgn}+OPtwSvD>41NlIqt4^ zU%*RrkhCKZks_yqS)XNOUK4kJwdY(eXP(@!;)hPQJKE}HTFiJjYQWm4A9jO<1?piZ zUnqHYmI1Y8vH`o$%ER+m3_9Fz&BF8D@etd>`Bj_k7Rt%}LfpBv<{mGRpD#DO~7l*$fQBXS%;V+B6a>n9*o-3y4`DL%4sc{KDh(d$ ztu~&RzVc+k6A|iEI*p$`Ml>3Dfm9ksXUW69R*6V=Vi$vIhn&mRK?yx4~iy{Ltl zFrzhPW^j4dd-d!fC=a)aOp!XC5!cy1MF=aUIYdufjoigUEsnE`J68Z!5R`uS69{wh zbqn5J7Ch=rp9*;=mTtK|+jFGWC0EsGY95)_@u@XY&%P#TIb)aJ2c#k4pT<+$GKwQ% zy4eal1m*BNL4nDCP<4z{^?3t<1Adz1Fep_{EP7A%o%?(WIH4ecz^JxwAa$r_=lDv> z@@5k^=r&qJT;83#$N9m9p>c>&FPb2r&h-I15EP2#sT$GPfZZ(#g#6y@F9}6(Ia*%p zTeT)?Mol&k#q7f-U91z9p3n)fddgjJapk-e0+Gm8$BM6i1`yL@f6NB%sA#s0HV1Qf zKAl%|S}uwvttU&@q%pW3*rx|d!4xM~*Lcpa(}BU~&Xf5gpsStB(=es7N3lzMrq%i< z<0V0>7*)7e2c#N*YC1N{x}sis4fDIl>3Y(A{1JGScK~uaufgF8r$Kb!FN=g~CXHQL zs-HBS=`}omn5rUrshFr$qN&i5k+8Tw7;L7270Y*W+ftlC)=)zGE(KA#L1UWHa zbWbSd`d}RzTZgWIS?u52%Lz&Q(S`XW6#Q1C_H*ejobyW{_rJKzr?}m}yu?rRKbW9M z7{)OS+5#yGM-UiAAcO>Q6u~JH+MeA0{Z;U{MM&^}J9zpS@&d`d-nIu-$R0w);J1iy zJCfl43BNY4L*5(-2-@36Q21s_kZ;i&_-zpKW;X27>G9r{*jnMRH?VAF|PtbjZ-p;FhpgHoMhaMy%tE) zK29wf7q4j|PD~MT3zk~rq3wL3(k}^rhtW849yXhhPKOjZQ#FD4(3$hyr>MfBCK8)i z?2aAfSKUdvUpGEX9G$v_^4c1t5872$$C3f2W9Hkt~x1`}*9FL9Wo=QwQc z@Y6K8j+=Dz3t=8sM^pI85E=W$GVBNY`tJgpgT8zk!o;h#{84YE*nSQ-H0*YN8u8XT zgg)iKOP4W!&FL^(M5U#%x(gV)VwK-E(;MS8oDT$Z+M~SPMgUMgvXTYo#a4wuAB4b`nb9K z*IC{cTVB$2Uz;np^IMqOPfIF)!kYqy-t%Yc@57XeJhdVBP``h|52XrTbrH5n^Xj@< zx5?L2j<{K@FnT=8WDzQn)b!J^ZQ&$fZF|?e666xPv{Xax@)5hxoo$%Aar59OvkflS z%V1Fs=c=WZqtQJbGux$)HL~C4*H>4{$gQ%rQK0Xq-i26)WNC3ZS$;Mxuze{+1SJ_akJ~*XtXn*L%^%@_%^V4(a6J0oGfmU>-f7`z}F*=2p z1YMr5Mf{5zHrVjFm$i#3s3TCF1*VZ@idoIOT<6+YYnhiSe_%2h`eu=y^hTAL#}dSU zbm*Y9Mc2Kb<~Q*9%?$Q8ljGR;ljFe%>9hC^!4V{#i$dL`vy-rH%r|;4^ zX3eqC&-CX1J{=&+-_E6ToJINY=?L9u>X1F*>0Dl}!&8?@Bvswdq%XgWnrD{6+LU1p z&v_*M+=T?6ke|H2c^ECy*S@pCGJB-)h_#PdZ6avaJ~ZaC zqm*f9NGRB0H<>wE@!1luQNU4>S1G3qKdFRjpI(W9B-U+@%sP%gGwEeUVjc#v&~Dj; zQ7iTYO~=G16DLTXotj{CE>*O5btopPGM9SX1Sfwz4Mf^MMV-=0S#=t{5N^SX4-dP5y#1GX@BjQI6AQY( zZ~lK3-#>Qvmi+43F!s0eS6KgHi{Fhe{{MWQ?*Yhva*p3s0WcV&NE}B1Wglu&{OtePkVt)Y0;fmwfEU5+QCu>6R2z<-rxnU$2+*ey+C_;l$_RNMu@;e0|%sk7s?4Xvjfo}Z8p75>5iQT#Ob)^!fO96!GDEOA2w^9?~ zMwdF4NpoGY(Oh1knj^u?4?)|{2)u=VbT#v<2jP&s>wOsX#Ohc?^gq&a-`hpdd%r0D z)&t%g#lYe6-a`w2=0Z(MM$Za%V9qH-T_AhiYW$K5%&Y=&g?keUjh744tv4q}?xTAh z5Vw)uu+dt5WOcPGZFSkU2y9UkXuYDD-fk(}S`Azx&Q zS4Z+uap$j+U%)GT%|kwDTW?QtwUuOC6;nS z8*fHWj;d;;=WRNmwg#0SzTJceWJfz z`r8^r{766f{ms5J5&ziamwn*`Jb%wT_Gk)>KPGQ24IEH(v2|`FUCS8^3LX#)h;XPB z#2@LZvy#1u6icrBS0%h7Z=Be|zeEV1Z-v`#Dt|-xbFTpP zvtGoqc;WB8h|?E8x#sI|2=hu7)cJx!6ZGw@iqO27)PL*2Y5nB$32twt>f|S+=@89yN!Dv(>0%sWkNrl z%iKTCMdo{RenKUc;vM?t;(uM``MZh3O*Axl^JIkL426$&g9pYlXkI%wAJ0B2&p0Pq zrZuMVlgA(1I=kR9c{$f|H=)e4Coc;c;*9}csh^B;;VMeOeG zn3%>rF@`M0i|F^VY1yz%E6=#ww8t#GPUuCEYlspeH&QOx<)Cyzwc)bI9!dK6*|(1a z&2D2DId31`p0;>9!7*cINal2a)wYWo_)%~+M4z9!i%kkYN0QJ+7k-!cx|DO_Gh^`$ zGJ0C(;5^<-UaLHA_kR!WMCb5aTeHprUuVEd5ZOS*BvxI1{aUn5zPQ(U@Y@II z&A`q@tWOQ>psx;gfAe$t+T0L?!GUk3FI?=Tc_5do-pKoia(|rxgUArO!UU7xqSs_2 zw)Z!?(LL;4&axkNlIf;*X<7149hxnKoi5K)swK>Eqb_*H zUrld%9kToGQ9K59x^6Kgc^s6yjVD_5%o`z9)dNW`w+ngcr*jJl#QDJ=gy+`pj;+=2 z>dff6*K?=W77w*M=(w|UPZu_5m0Ngr>zBdg1RsAZG_#gaJ~nU#8&r6!AGYQ(JTP)7 zbB*27wYm>p!59%w3&PYvc|2qS@egKy72t66@V&1^@#y#)E!2AAI_Z?H6Lxt}Li|47 z%KmAG4Ae};s=x#9O%_;sW2hBYamXGa1lSPX#)gdlJfLy;vVri`W7-nXRW3%&tkofvfc7f3~6 zAl{!MV6qfjb^TX?0dNUO0!XF+NJ-GVUoL-bf!5{B(iMxN0^DpeBPMf|L0)%RX=V)HR%gh+20tfepj~#J@+%L)hfQ`xb+z{=7HeO z8ClXyV2HE-(=&p8Jf+_`qd%#dKXsc5Zt~UU1?4BoQsYG7q+0iH^XL~F!Hl%i`OC`*nHJv9fr}Am$9zk1486qt< zqOoxK*((HEoV|C)N z`s(hGQ}=Y!4NZ85+m0`bSiCg51704Me6xa2$F9aM!dF*Uc!Y|u|1DeBKhuBJ*)t-i z?YR702`G#c>|?%{%B`L6?O7Adcddd!jPv|kZT13HI?+sFrHCU zIg-p<_ufe=k=z(TPtu!+uRMR4(<$S&+nb(nQ4#-q5l?60wCPR;q`BfFKy zn5ryU;Ii4hp5jX=Tl1Vd@h0hb;bO=ZOGnRjjmpI`MyBi^tFm!T1L@+WQ;WzYbMf z4O#l5K+nIkgAdi7f82lgdqr3rBNmv%NSsD-W`RluU(!jMfa&Eg8pClCC#X-y7>ES) z!WWRt*O35fmD?dmP$34g0Lg0AhJcKahW|xVjeUDm2HeRqZ9qO9>z- z2drXOO@nv^IY4zwfglg{Q{kQj$O)w+fb0BCiZ1_Ggn=sc0_lI*n%N=2@X$c;rKwgt!xs^YLZ$s-}yr#H))ECO82m3UZEgH z8dtpIn`Od`?!bT6aUD$+r%UWNaOj)UZf2X0PPuZ{kB-ZT&g-`+a4$`G(^iMRP~d}$zQzf#~-nfn2K6|)v&jeEOXp3`g#+cm(U2h2U_Kv*x5mn=c{UYf`59H&1Sp%ci$^+_M5bpqM&FZS3Jqd6_w zYJ*|7(*@d~>0o9pZN%^k^;MpZ<^Jg7SZAnDd@!nA|CAq+Csc-5AFn5SCp1@!ytBw& zp0D<40}0NiQ{tPm+>66Szupal@m$`NLN{`Bksg2Q2$KOM7n{XpWBCvrzHe%q2jB1y(|PoC(qgX;e^FyX(VL48{a6wH=K%t4 z_eRR2MbKu~1hRmRdzLKgvQHIjG%ETD;CQ9&`^-5;_419v&#a$1OJx4`U4gzOVlHof z#s7cMW0(BCnzu1hv*bEM}{ ziu;`!v=6<&4V}J53~bL@vW2WE)%v?CH${Kvqg#A?6hjU}>dGr<+MvbcJfA{C+TW>r zeLvKk(Fi`g5Y4{B-@m`}@V^fKi~o_J{$JVQ zJFfrc&b|Y9gj|wd23ay;lmT+@%kKsADS{v|nxqjFr>W(MmnrQ8ApxJ4OYH{hgP_X31%YK(MmWtN%mx%2I9DffMqu|VdwOs_>u$&6O`(IPl37{=;CqDq*qwjM} z?-J<|DpHx(XF=-m&&$KrXBqK#F4a!!!ReB6Mla5Z(Fs|pVVzbuJfR)V+5;F~jfZ!A z_gDJSTUDiHEmFL7-AR7H?Il0`@L`3%ddLRAQ*-*RExe@6YsUQ17UrrS&wm*D(^LNO zjG;e0rOaXxvB5eg6xh*$lynLS2Seu%t==`;N#`! zM3Gw0XL*_p$5ZCms_GkF%YVm8l9~%;Vor`e`v-e$9Q4*et*l>c*54eS^gKM;lkazU zIJJ*6D*G09a*`XneaaVx63cC!7`JOD-dwcd+}TF%hfadH;wIk36JmPEqjEj!=-k_S zi9Lz*VCAuDA;%%ms(n;wU9vUjOOD_|L*o?7*~$)Map)QlkNYb{TYpI@xJ)ar)6FYw zmEOmGB;9@XdbFu%=8p$B;QO1XsSm;Vno=hqr8d9MhIw&(+du=wNq;4aUnYfwkb z-*YX!@4gGa(gLJz=YMB6Ao(pP`(apOl+wR(#NJH_BcUNOx5Dt0A=wgX*0zh{%Jp=p zYt}<~p=BeXqZ%}82@^kD)x&X;X096B(6fZcm_F2c3zZ0)6bo?T!k&GS?7^aILCZE_ zIPY0!O3KWfE+?JH^gYfGc6@bpW-H6?{gv-(JUT1Twwopey?@U;xzD&fk(OxxDlTw# zYL&ySs-674hr^55p62nflePz+-QM=b>nVouj48tt8uyt>H#&Alx$Jhud$e}%@oY)( zD=x9e6g#iXo*f2fB`tEfAi@;GC9xA8bzj3Uv7j zWYxu2cQOUep4V1o6Nz&jR?b?~2=_I+=Zazh-P$;UBH7GyrSk)+=}$B2H+6x3Bcldg zun)~a^?z$dEt#r9+O5df@H^$10l> zZuaLR2XmaUM72GqgiT7bWZjg9Tbb1ha z-(yMY81Gqfs{DNeZ}~TLhbFWCX1}GFtE~B3e+d=RLAlfsC%tB8U9jG!i06;z z2;GrD3H8SYCXfdFTKQcTYvtpJ&NsEyNwZCq8MD*w5~3xn@@2iZ+1G+9h-Ry!$_4`T zM&WIawx_$6&B-z5Jwo}t>I)t-uLSkZnq7>$4~H@4{rx9sdC=IXNBrHlE9E}(?)tHu z3VmBoe|^E5ncdwPeZUCVZLZP8?Uc++;zX_jsH) z1-5++H!^ju&+3+5CGm!!u@HDu!QN|R?sk;1yx(bEwY{U~sO&g49_GuCqtM7;`g3m| zhOj9gtX%bsr6bE~dX6xBV9P1oGb3$HxBM9ke<=Z<6YO~w)VV~RxNL*F1hwXKupDvs zx~nX@O<(;kx;DYGYTq+7IB9y?MjFOF;DFrcIiWe)Q7(7PGu*x=uiD84gp0It=gTGY zF5(8ZjVi?o38lLIV{NU~<;(&|Q`^B;Vkuqm5oO*{`v@AOi#89A+JQIUbp^ ze`hGvm&s|oTY<|nL-DWy4fabp6%j{g{yP;2`W=0h`>1bjbwuBl&cb$PJCyQ9jdz#w zVvf+a6rSH=@Q9CcJ3f^7b|gmEm>~P8^&E+(t&?ei6Gj`a*@6ySWuuQT&h zTTMHguM$-^m>DX#Cp}~C?&fC{%7-W7e+VjRx=d`*+n#@+=)|>Ys(H#(4_AR4U38w| zgm_)Jlx8u-!Z*(X38XVGP9+UJkAr^axxu7{LQ^iChRjl%D)_-^>}31Uu9u`aDTk2f z$eUBob>YZ4OUBfA#4nX}il9>WOqPnPa&NTywYQ8yDP{5LTXHoY^TtV4d$ul;f7}#2 zRxGE7XPSu*kBWFzM>Y&ANUCubpI(jLi$Q;$?DWoBJxaC9U8?;Xj=HqFNrR0X*-hY5 ze)2#!`AKsFN{63#Snr_ify(&;{(T@{vznrdfM9xAwXc4t{$?8T`CGpA3IQ*FSAL{H zXAwpj3P)iEBTZ5z5mAYCc6pP?XHT zWbFc_I029>!a?^B%%7m3xcDYtM!ZSm;;U6hy6UJ?KS9MMb&1!>TwoKKt!9@QXnN8( zNO+c92w1nhoM9X zSf-Ew7&SrwT6xH_RE_$ZBKnWdjk@rO-N+K%LtpS$<6Wzde1wQG>ypf0oj}-eRKMg2 zUEGR)o3?=dp~|O5M`ec$f6=TfZd;VpeK=6plOeX0B`HBBS2-8rkjX3OU`IqR`B+W| z**`z&AokBSZVwg1V3l5NERJf_d8F=H9NdZ7IwWk-^z%!Rr|tz6W^y!kYzR-vro1^X z*uyjB66=LL8^$aaXv}y0t?WJ0NRT~%LrF!lZkI>BJe|HbrUi#u1@C#6# zi0O%mbzPcw&%Z`wM@}j}wl8LDzOV*|pXG#~++92ucvZuw2_YE#k`LP9AYZq2O}k=n zE`%;|2M2X|HOF=q<=tDBrDXcL=e@_i#)Du=n&V7}Di@>B?p`#v!rKo9pp+Tj8@%Uhd#YOw$t> zCyr3aeo@?#;L*p~e|WQ88haD{_G1h_#n8X|F)oTTyB+2lV$JQ&KK^V%ZzwuB-za&8_+&PJvSjVO&^jsbH`M3WEhj|ZgqC3hh& zCsH!59HYw2;JRG#uvpB!$I2cFLVr2y2O(rRf+3EMJ>mc<&T4}mo6#mmXn@Uj9P%xEL=}@$Jkd5NTVu;>WcG&~_BIF3*l(A}z<(*U7>e-o ztUNOUJ*D~P)Fiy`^V{nKj!%z`6CVD^fH`{%_oU4Ja{E? zH?~^DTcvM#uKxRFK;Sz5lgog>b^IrPmjSIM!R0dkU{LbLlNy4n_ltB8U8sy`S~N@| zp1st*Qb4&`Z`=-!QM;B~uD$FVR_&b-*`Jzhrx_6|4-Xefj63B#_9YLQ`u5mU*JTyC z+A=vN?a-_Hm)mU?n76h{LB1xk-MS7ta2s8j`K}&WKYAi)F(X<%-k_T#M9BRsm=%Px zzp}4TD{$48!Z><9Bit(k)@}0SEYgx0aCL(Y*IVTb8k&)0-bWRejQj*2e^t@r(caDo zhYRS?(NCGLv@zWF31nWM5)$Rdh~4;vA(gEXmam;eBOnR5NM^Z_Q~nVR4Wp)0ePLeI z9I>hA0%|#-(QbZo7p4uiHVo= zS<{aD>Tcqeh(`SGcyuA|jvSoQT!EuGMFwqKP#eGKrU#;F z3`LM^e7j$uVONrOXK=~+e6lb+s*5MB%u=YC_G>Ql`Jknh-kd6RsCHg#2loDQ-V8ya z52ct%mk3hl%c7?%cvY%+!x@ zcFtid92$tMr1ET-lN#XgJx`vxdzD1})>U;)tK!{c)LN|D2~ z!K-Jtfu{Ht=nq?gV7j4!5B)>IKhxKN>db0;~4pQ=L-d50Sm;@6zCa|%xW~e5;(F5O#CfR=IiL- zf_2&F(}+Y4gbOkPU}U^HpHMWwu_e_5gj5PtHSyJ(F(Coif1oj7sbcu@-=AqBkYElm z%>mtH$tyEvE!3_W-GFM!0MaP%I*9_G%olk3LZ_YsQ|s=ZR%?L;)490 zX^4>dI}kU2e}RIx5+3wk!}~gQs80I3n1J-fAnW_*K90V&&i<35gM&ls(f@#mxzQ^6 zX<24i9=Eiv6A;B8U&C}$>i#r|ozcosZ=%F&IU_4dXTr+87{z!4MGPeO4yEyd?JLfUt!NgXrI+{tY=~3zZt4ehU55~61M=zBD>QC_+0+5L4_#h2{WyKE+hM`^8uBF5C;-6LNczMGv`e+LbjIt71}Rmy7RctAfo9ZQEm%|?Wr z_haFxp|3U6@rsht;l!OjtF1s^hAVt(?CV~#j3&%?8?}p;1jy}2wqZEhxl&nOdgW!T z`2pqp{UJN<=0J)zidIAZbwR=W$f)(*fX!G$=TJ*V+aO}LBDB+dxSm3FW8luYFD@v~ zfA4m5704-7O~{K++zC1v4bkD8a*WWD9~1ZJ=35p$M*=&D1gbR`Z1Z}>C0ZJA&2+GG zU2-p&+04&PyC3do5A|(wa|a&_bCz&qqd1>h$1NBa3k<4bsq>B#v&}F9XvGf z>vEp_G)PSD1lK;~9}r)&c7~V~C4SJXvww<*eWV&1;r$-OEr?V;x}qGTHIGV`Jc{rC z*Z=j`k_oSRLD_Mye#xvp=V^QkeE*G|y~E)z-}@~xqBKL0FikI@NMQs*GbBO4e;7eD$zWGzL)tJV(ia3og>WeVDKdA6222~g++O~v?M@#p=+1*aC+f>-H5 zDgzXdSeHP;1mmn3n)Sz={qCOJ?hT6Vv{aROW`e*%+BN*R%0GcYuXfs!dGfv!@< zK$18I(m~{kk;{VxEEli`x#c<=e}b*_k(>a~POKD@Y_0k(?}1mV%inO1xPwY5@m1ka zN-8FF)8s}~ON2$8xnWOtpU){~Ke94iZ~mGA@x>UKXoV3 z3VD3m*KGf#v8buOXWH=j!{PB)QxwoTMj?nV(0qJjV5V;^z#pE|B>V>|3^sRr`yA1_yyGN?W;!4nwkVXdugGr}FQ}{)@G^)d|Q7of6zm^iKK=vz)c~`%y zA#r`_uE6-*rKaameV941e@(AyEn^4n^umug8=a5a5lAZG^ib0LRGE28qD7D zmf9*iYL8m`s&VFs^s_C$=gv42@&kN&Hd_Z}(hRXnm-iJk@Wr8cYS;-9!rsx4qZQ;0 ziKHohC;FKgd3i1oy%DPC)tGSi#P3fWFSxdXi4F{x4b|8hdMW}He}NpXyN7vrn@qo? z&WVHEv~ow7CO@3d26f$7oGxp^=5*BS6N26z#$4BX#y$zRbG*RW4$9}`x;drzj5vc2 zM`@3<#@Rh`NHgTp;hJB1_-w&k_{3EFUWa#my9r?rHhlAXi}IX>?u8{~jmh3_gu~oU z9iA6-KP&b%$4j?$JETjSkExl+4QF#+5_AMBA0=A4CTX^@w+|Qc6=Wki#$-OzD&}f` z9-IEyF?XgUkHHmf0_MKEOmt`Jap>9X8Z9@qB!J9<%| zv^}B5eRB-TB+SOXpRJo+On5oHUfbuBDWgN$$<%;50cM1o(|HU?Ohx0W3%MoFt1ggU zJ@!kiLv-1!RW}9S1x@1Lf@jS!LuT8Z+txxUoT{)#YN7IU#A;tecg8NSed-C~l7Gy; zS%6+Ox%i&q%Hd1K8g}$Uws%D%jgm_o0KfKpU814!%f#q6)1rnMh~cYOSk?rJpTvlTfne&q+##y3z&XVrhL4o)tq^V}Wh24per6YGK=Ro|~^vLo><6}c` zku!I^c)Ld~bI{}2pek=5JCuVF`F|Sf5^-mxW7uu??cFvNOYX1J)i*Nk&|6Fs$dh(G zb#2^@{WTmJojo>%1T z_T14dGYID+v^x#Gt5{ygPGRo#j2W7ZThxX18a>VGyyuvD)9r2#VGf^gLw|a73WxeH zPCNyB{>E>i;*w)zjggzjI9%<@HIO)k8xe?IFg)jLDWby75XCoLOY2rV>ZeD1tD6gt z?h2DWd6UhLDyVH2Ogth)6m5;6`pGF51!l}G!&D>qm;hI~TBSRE}{d%$dN zvfh#q@o4sB!|w%Dc9e%Y$bXqSHiB=TOcLctIxJL1IZM*vaK_RyJJ@`q?j_2X=;eXLBU66hC9NmYx*Ks9*OZX)9&0m!ES;Z;NiYw;Lt4?%|HxGKM2U zK9gX#vzNdJ1sF|Mbxvyt951RNj=hR=XZl-on$3*>mAbi6)e~md@U1(-SH5U;vR801 z9DlQ@Vf^385>VNytb>s3Sv2JDxD2n8*F_J(JmZ;k^;uwPax3=o1rbz_ojxWDPIZ?E!|Q?>8LSzF5l)Y(O+*3tSnz9VXthTo7a=faz(l2tO>a<+pN%d zcU7y~4Y}5=(QY2+_~BzZb>K3-@QCWL7x^$Yn907g`Q4$}Sw9IGR&DM?3R!7@&yJ7Y z?~2)}(*F9eU#vH#HL?k(gFGy;U`Z0Je_HgytnGDyxbO>#yS<$uF+!eA$Y7~W4Nq|k z$5%7=M_zFRSS{wEn@_2}O-fx7gw7>;+hg~}1%HkB{ZO}Qtqu>V9G}pxS55q(Hx1j1 zqeNjR?}>}X!F+U=!-l~zb^&JpRoC!knveBfY4^&`wYMkiI?i{P{=n{E+IN4)f74CA z3i3fK&>OtgGWW)gk5jJ3{{6gHc!s<6dUyW$un4<>%hwJ%)F*nQoKm7=n(Ao19PNBZ z=AA(^aG1FnQ`bX$9vRcNO(&X6IeE}Kn3PK#=EYZ*1d!I5v@PSu4t~1KL^)?XJbSye zP8z}Uk}aw3G`_z)1(nbZsqxTWf8mHYflGy^pNDu1AsjEJjdYHR<%igiAv~di=+o1w zzU`2$b?5nX2xDyTM0qlq>5_aOHp=}5`&r&zi36!ZyA&yRFD)4yQQ?FLmM=WhE7s(y z&G6)$TEL?R9o;t*$?oR8uELoRhel=($>y1y^%1JJ-4bGr&b1@$7D=7+fA%tt7tzr2 zHVzT&($r;kqV(D63om5IEG@Z8JrG_LdIBpnI>bE4(LWPAOR|C!ychoazC!==myG@B z3ItH&3uBo6>-$%JSO56`i{t;PlhJzY@2e3s%pfp9kqm><1PQ#17#fFZ0)-idB50Z* zm{0u{Vgi5@h65N&7%+8-f3JOMoCYmiAS$>Lf>Rs}fWV)NKr9%?WUFH&y?TaIU~Cfu z@$nl3Qz!LrC&nf7R-n~f1Hx0 zfn%!dGET)&nSTuD?{948_7l-Qsb<{|9bPwWV&uJ4-aLXAJ{b$by|bDj?JK<(SH-`* zxj3xsUbP55()vpi@*I+&ZV{uz9m*UL{UTrkI>5u9`XfPWUE|HSa{kgfz?U74YboQS zb)aFIvjDQA&bo6(e+;h&Rl^mSp`RHgeeRQV9`*5ER``v?4S^#WJomRZ|Bh|M5<+5T%;#0eK@c>Iew7)Y)2J?%k_ghYWiuS9D6n4)}yM&j$4t3beMSru|)@`Bk9yL`i zkO*!U$(}jNmt@PG9q*M5FHynHnq5Ui9o_H z>%dKZCY+q(%udQZ8aM|ZWKwT=w>S)CfKIW5QMtJ@v+IcQs$GuNaqC07cDe_w**J~2 z$+OM25$kN2uryI&>3@V*O}jnt)Z=EEqBI0`k$Ocev2bdsTt{aUdw_&?|418u!S`%) zJfAstMuVNHqdTcj2mP@lyRI2-8g-;D+Fq2l+>+GROYp)JZklHy50ww2LEMD@x55H5 z7@_a-f6XFZJy|-1mMZ#mLuV;&1bnM0^zdU?z>jZX0kp&g!+&HQk6zDFSywR~iQn5S zf1<<2Jr&L6vPmD2`eKqBpWjRs698EFycMB0)(T;cV*A`H3<2DL^-+s4Kx}aCmdwdoh+g zom2`ZO!vdnbzagPRHZmmJDtQSjFNk{WPFO4-DCk`{gSC&xoo(a+j%ohA4!4jQ(7>w zQ~y;TRd|$wR$#h}zC#17C5nv$9fUkLF3cBVCDr4E&IDaeT zuU<&_=cMcfTEVPmvUb}sFeI9+R5n0>rhtqgMt_6;d5!~y^zu%aUbUd$4|Ar!fqS&N zCM=jvz#zR{lJSUKWfzezMu!W&1MYVYe$z2L!X&ljhtGNI(eVXq6(i0?EkZo(%<}$pf~TI@-8v6FM zmmQ3H@ddnJ^w$Zj7q`SF5|+yD{l~Zk`dQ$z#4TrySKs57`28Mzi`$?j1Fh1<@4nj0 zk|?r)0`PgRVX*2;dt4M*UKN6Z75l+Yihu6mb-83`YQCw;XbW*!ocH7ID44m-O7gNC z?(BoTKbv(YZu{-^mB<@J#I_xF&G4HeCc(Sy_=7@Q9c7m0k^El2z$FA^$~@|H@JDJRSp@@{-wM zpYyhI1gz8`+e^XDG6obr!RQTWIj^l~4D_cF3art(EDKO1O`*MHjSnvBBh z5bKhU=Idx}zDfi}*-ABL*81wIJp{CaNbvVtD|$Kn0weKTH#!D6A{b>|_2%(k$^?mf zkOEHo50nU4`82>$N8W6>9m2z5o0*%RrGU53ylnnATkaMAHpF}g3H}zu%x@60pb4z4 z*!E_l3w=z$3g3wcK7I#cz<*go9}x3(VD%tQf0t=fCD8E(|MzB9v@U7e%&UCc&#-C9 zD}Rbj-$E1g?_kq6&@@ATLVUa5=&~bQ2TCi|f;!5A8iGPNp0OsBJS4Q{4iJmv*P!6U`pY)^of~vta0% z(7G3~r^xHXj=L?tQGbQwDYqg_BjEBHY+`nBUN_W+=JG5jk3c&K(plx#m^S8N!S>Vjo!2JtQLC2)o00cF&OUo9?|ogJI|$hj0Gt+Q@uDWzKd} z06K~jCF=Lg|o`{ohjFWSo+tOW;*SAM+SwToFka|51PZMI@F zsJ78-Xl}3id4HaSYa1IG5^iOwmY_|r&EpiXggLvhL}MwzP=SXFbv!NK zlb#*7=_`a$+kdsuT8ZS6N}#pMMfZWg$Tv<;*Q2bME;VnTV zQosQN9DlY1u-dQ$(A2i95qoP~0Ec=QbYZCt285rFJ0)-7UL1%fZCN3()5Ac?7ZiSB zz?CE3vc3cY=-@yem;~kPEyhQ`BDsM}ir!~{&#!T?I9)tO=9FtMF;xBZ>0^O^YNZ6{(oz2VZH;HqWoQ3c-yC8hkda4M0J|5 z;c$Tx!k?vOw#>8nH1qriC1p@ihQ5}Rv42xi1{G!KzbPq$iZYabq-l)u5Ee_K)pa0xO>4h5R<-1?Lq182YlE9Z=>1ENFHDrr7 zWXJcz=)otXK2B|TQ_EQ)l(YRTSEri!U_bPiR~hM*e1@JD)!dVLQS?LJE_s}$iel#K ze5}K%x!XN6jRG#5&b+iM?uHiK;m9BQ(dL@tjT<*$wuRP5ZtK=cbyk&+=)Db}9Dlnz z{Bt{3_kNqwuK$>~`L#IRKXpc>|7!==|1&P_52meu@3MY~L!gaGP&kF*FpU#5!fa89 z#3%wKaU8}F3MJ{!$=3ASMHN`6ARqz66Ci@LWs7wDE?2$wS1mR%I zSTO>yYPMiOp9X7g~dS%x(w*4=}RH0A&cM;L_k-mq{1}9e;wEBvSretcmNyD=%-!nkWd}REb3= zDSseaf6Z;D&#cq`zwl|@(zbu;)B1ZJxaFeE4<@Hx)YRzq^Xofhr@u${{yE|OMZU{? zlJ8z1gL6L;-lNxeYv{eLCO^{A?@ZqNv-I5!{h0NIRFS9?CD|^iUydbx=bz@l&}T{Tf{NIs6FJiyZph+C zd!z_U-YAiVKUPUu2haEBTb0_WhuUg{qxMf z?oAPQ>C9qjCBD+5_`)Z{lJ7eO(sc@DvV_M+e_x;n?J{#ZMqd&_@kFB%N#!n$VchG9 z8>n#HIS1lmz4jwv$wO62i3#mF!%l`F~0= z>X=W;OwISFZB$-3szOwr&QPZ@9&2PMFF)PU+s9kfTMAhq{57_R)9lmT;D-;kE`J~X zTDMQ-^kI+#{VgAQ8J2mzmjPp$n?-}$KFAkRN*+=_L;jh&7?SJremw+!QtN2aUP~5e zOwZgLNQW60*y15d>b{1Tr`)ONF@K~_r(Et_hs%2?U8>RGUH?00ojyX7Nx#28d9U}! z_lrC*8h`a?eH*=g9Z7>eX3~;<+d5*Jxr^@2<3lm-fdXG+MgD9n`>F%tOeGHW?5WY^ zgd#K>3+QD$pK3@wH7rF zx!SviLZ|SEE;oMoS^|2+&m3~C#BEpQf`@`UNAWaru87G*|~DItQ_ zjGPa1zPn!V$8JA8<>&N*lYb$xaB@iJi_o6Ja(9~L>y|)wEgD)rqbfF3+tx9QQO`8* zPKj}^{4&N_hXz4XNCk1TmUNU2BS5CTu%8iM&EaX{uBseo2fWda7(^K;A7mmR02u1O##a9aUgsZx*1x#M?@S{LFn5-Mf8Edz@=m5vAinh}>e?Pj-cw}BTbUR} zLE&HnZ1md}h)Dp(iZjr#KoejG5Hmofiv&IGU!X3M0gdY9J&g`v(_67Dev7Ce80de* zZ+$Y*vWUTJ<8L~+VtIcq>k!w@Q%Os{OrV+P!-~7@o9{MxB z*WYoAhd#55|0izo&}Vk>f7>lyH+-ndu(55ZYH$dx#1ni2T|E)W2q=&ISRKh(Lw0#X z4hn(Gn?QQtDRSi@{E&aq=EJrthwYOJ5l*p{6#U8R%qwkL(edRsOvPeRBo@44kxvUS z0<@WNgzfk3GkI-`6jN+$IqY!}|w-~O*J!AO48$^ZCG`d=fA5XcbT|JRa*{r`Vj(qx#nugLwYkIwsv zhirI<$nz(sRktwN4r0}|@TaZ!|M5o~pa0EQ^PLCKzqpbg%kl({qdmuriu#5=Mg?fKxEXjxd0X02tfI+YOKb5juH~Hf`4g%naU~ zHvH|5%g}#W_K-l?WBNw?k{ws<36`}!qke8V(*66)ean+H)jR*LeaQjs%ez+v7p{&m z>-+Y;A%NsuT&4i+a|gY`dMRR%A-EqC+oLB-<4m=$nMB~EKNit{z3xI^s%FaURKEDM z#SMM*xDP|6 z0in`>B6NFy;?Qh=8S`SkSma~gUa##U>W^ehABRMVgojTMAzBw#fhac>!N|TnIA;64=&~lQpIG7WUE!hNUAP>eARy>a=q|&8dHQG*=OOA zoy(fwMxc_Zl&|s1)D_M>w{7|{ua8ry8cN9s-5IJSI?SYhVVGXrso*p8zA)Nkgjc>5 zR$=e$E!@HaMAp-%H}91;cm-rc#ikso_IydY7sOuKaxdcZ^FkFGdb(4-ML+aXGtkpc zYK48TmkdH~=tHvwo{Bs_3{!7lD+S|-j_C==W05*ZD$lxFT!&CS^T3upiB$U=A0o)B z+dqShm!0x|hF!hR#;JqMj>UR;JfC#7G`0+>dNOCPSL&Ff?@}?5?5q&)W4}1Uhz|7M|Yw)KCx$dAsv;J-Hu z`ZJTDkO1uh;9wVl{xy}nXM15lYuj>6;+-$!D2S8v=k4(=1Ok3E3YrrP0;q04!y12o z3!72E)**gRA8$D>2#^s7-N`#^Mt&ug2AUi3+x`K6D}BE0g{Zd@%obp`bbgDs8)U%V zwtOiGE_Dn2$=iZxLmUzIrv71X$G!-3EPx#_0(f{7vSs~$sR6Ts_Bi#8awoFd%`g8T zngH4mT=-K}{Ro`}F*UgPL-WORF}nzVE>?b(y%iM8!M|JLG;aTnhSSf7ui|9_ubsER zSO89O^>*0VQn4+x^np)QS0DeG)V2OT4`r<8J8I^Oi9CSZHfRQH2hV_PZ7e`b&HsrA zc&_F}DcSe~DM+3P2fhTWvb_cP+m=!K_Lhn+Mby}JREnL!S091?_GfPi(DI;vAF1D9 zn)_FyOX`==r5ubdZ8zKSt^~T_wr5G`ciqQ34cCd&{klGfq@-LzRP{@TDEVcxA}!I;jvWVe|fRG|;QLN~cTa-XgS<#NwJu$Ys5M`eD<)c>8FG zxDo_np+7?HQl$5Azl9cA@I^dvDBs8;-(%*&4HBa(vc_slMGvIHWO%qf(9V|ODt5P= zv7|q=Du0H@?OmIY++3~){1!IR9Axc&%={~T>QHx7mE-H08zSBBqRcHDzXs9PUb zy??nm&w=g&`LsfWM-n)H-H{o>%crLb%NrI5`P^2H=VJ8colQN~(^48fenx0?fEPuB z@${%a#3xhw!32@dZR5HL=bNe(G^gH%?qwn2x$h81)f|g%QFMuK)&5kcO@{az9E;@b zIt@!&Y+Dr%P-+r~SMBeWO5Xrh&9&tnbJQ5f~~8{2M^N6uM)s1lj`acu(g>E^qK zmIvjrqRfzlI5HWRn0DLk-B;x~$g>Nrc zi_;7-mO05yRF<7jFP7o*yyJ49yBPDV9V{QIJ)~m^maN3Q;n3-w-^*Tm<%u!knK?q2 z4T{$r^ki1h1Jf^m+=eRaGIbCzb8-C28vGNAgeE^%Wdz6_Q2&eH{wYa^skDdXVv39&ZbtB(Uegw%83~C)q(hHNH9I$sVFO_ z!EB#v#YqG9wIdL98W(N@NLf}Tta9{7-grK5m_JCynJ49cfX?$R_7S&~_m{E}Q0nRm z?)m95zcs zYKJJSFSWjZfC?_LN3>7`PPO(t+{ zZy&;tIZBk&YW?AvN=dZ1=$*LYl0=*jeZ9*a`(~Pd$EtxMF;Ab(&EZm+kCA7Du}Q?s z2(zIFQ%&x)#PiR&x@4za%=WcX%~LLomntlU^Xpzu6=Whq=L~f3;VtWzA&FhQ4FxBB zy!|FI2`?Up<6+kLI5b;}s9ej&Zs>X2I@j31u${z10mW?@nLDKTGoI$l^Xj=T=2cmX zlRwpe%Okq=R<%3R-l{!3_2hX$8x7Ibw5Fr;Ob^%CiTlDh-@Px?U0h6eC0j={KG{5f_5)tK-< z+e#=58X7PI>K+L3c38v#(F4r@g2QkiK^vi91|kALaQo&L*e!eWA2-y7VPBWXCayZc<)*8aJKAodINBbBk3q9*Agl(?%BH-Xy9mJFsJd;|&p!{a&h9Y$Ne;C|oyhDh6eqgAZ<0y`fqK_?q9A(tyG~Zq9DkE(BvY^uI3NJRTqN}z&NiWe* zSVGHqY%d_GH^gsWgIjyS&9~_-->37FkKW7PS>6vf)W>%L2Lvcyw{h=1ARYqgK>^;`uC| zS7M*EXTEJ#%*q6BWdocTECZhm>MSExX*hyLi|0bB80dcY;9S^*^H3v-YALQ8s+vY^8F>P2 zC5j96Gw$a!rOlJ~^vAv(qm+U8iU&?qFXIp}dSxI`$t+q@%x^d`Njtc9WN ztiwxO;Og#@p6#g+bAJ1qjfm0~?}RinDwh`Gi9aM-4~fNj1MFxoYJ6HqJVk5Q$-eFm zG~M>+{lh*Mu4nfrQ^CzhcSVQtxVvQ=j2e#a?b#lo%#fEInfZegPc=D=IEUR}d+rtZ zeB0}!{kXm;1gmFIp21{=vmtG{-B-;B2{#Rh%nFJo_Kzyi!? zQ*cpJc#FQS;28A%K|{)a)GMo6>$@7nL0q*%aN!Ej-2Ev1L!XVe{ob6OXZf3lqj|pi zCK5N^SCSqW7|^qUqMG=(!w=ZY_Lub8+N;H#C;hDTFPG&k1tov1nL6(;vvf~5-^XW_ zh6-jJ*I7Q!li4f}PhwbIK6c)%f9}b3sAc zBk5Rqua807$iZv3$F9aRCku46jcnMm3hUvY)G;3A>EQ8^Dh;lEOh_@G!uxv8TLy9u z7{XbIbcV0X-pN#V?!FgM9=lv^D?PYl8ZMwD8tGg~H8?fo)euHQu z7W{a7cjN7Dbf=~fd3lN9yZD%llqNCpyxamdE>E|CjarB0eH86c28&*o-7N(de}hHB zlT2Rs!7#IhnQtcm?ed=j(?5RlM>zWPC;kwba2UZU1f?hvVF-%Gaq82TTrUM6 ze{*iv7BiB!#XT6}irJ~Q z-CE{BwRJlDZuDqqJ8QO&_KUv$qP@(2e*`Y*YvlU#_VVvZ$(F<*ZGdT049uTCL@-zD7n1}rC0dC`@_WQX zjdQR7_ekShydxfT1op=-_S?bl-{0SPd(fY~zrXYLpg((mf9LH%$@w2>eI4(3f4Miy zE_ur6A??gi*QequsGb(Yc{(+2E5oXB&0@X~i`9$V4n~c%KA(-T zIM-})!Cfd**$wOnish&HL*)wZe{k*3#Xi4VxI)GaY3#DyEV&PzJ+SR^NAAPox%2Uo z&WXAw?i6I=k7|+bhRbnf`Fyr=$BXhKA}-XpxH4J6R%aj=X}7JmMSt%c-L!07rv_1$ zq#Gh0+A^7%vy?04Z4t>aiT$ZlHTCGxl=pNk#Y&i{6`u+rKTcF$j6|9f@fWA7irp$ypUbg{n5Bnc+#hG1trOt^`1R_Ax# z|N8^rZ-=XQVs`xDe+T#bpMG!V+Stz%-2Y~QZzI^BpYcntEs9`plmz0PpDS3$1c;!~ zI~H$|3ntza=C?C35TFi0q87hZzJM6@=LD~W1QX3)rqDpv2!pxiEh=tn;{+&e#t5iP zqHhZiU@k(u!#nw(@K>^(arCZTqVG9s3e*+Rw{ibf6{M%=xw>}m6CUL5lum) zhpGR3X=ek0&k$&3Z}qz8x$%!*JMH`6hajD3Q$E0)P1~!~53ib+#v;feG%1UD)A=w@`k0 z@M}W*(_=q|Jm^njo-x-+%Msi?ze&@D&8bjaZ?|-Bd8ios!%fj?$j&ukp$><;WoMev zkIqiY^C~LbXK&axvwcA4g)iIhCOaUV|U{ZByn!bhacmw1hOnVKlVJ_l1kfGJ4-LM zob)n%f3zGYl*{_aU-Kk7WXXPKOUK=)ig&tmSV#>>WV3ym z8dRqQ|CM`k$ikVG_DDjg%KZ%3DI8#V9^x-2>7qx9Tdy+BL`U z#!xrR9_e4{Te23XTjs>Nhiq~U#Xt9lYmktJkxBKyGmpf+r zD9ed|dK~fB%PnTQe(ZZHoa^KBrSS)d%(%pUtR8l0g9G=Nl!P)_A>qm$B1TDaK4{5~ ze@0_bDK3{=8*a%AVQ8dn$e8&`ChGzRkuL;s2z6$%K+6upZjj-ApzF z`dGGSEWkweBV{_eVA_{iL*Fj0e}L%pqf|%vWy<;5#tl+Hv7$}a#(Rrsfw5={u4Ppe zQKJlArof^{;aet%ywfbf*aDjO#i~INS7-}J-wqm*_*3oEI~%S#TkKc53v9xnZpI@yl@uMS2(B;&Itqe2Bn&hZg38w9%UV0}j6T=3SdxR*;-cNQ zzL!pe!|{aLpNL`0X!4_@?_Haa^^0*Aan!O5C=PqZz2GN~VM@+>wG&}av(xaieh%G8 z;7E)GQO5V(ND`zC`=O=QD+n|&d~4Ki6~=1M%5rS8aJYNYw=IpLi113NCl^Qnlu zdA+QxB)i!VZoyRS+hlJBUEiv-YU~T>Lely4K*Oy0I8bG_a*&gcpvhbTyUp%VsA$@{;QjR$;n> zcNM)Sr^8@K_e-Td;w?>zoOspv6}s-NKxz$gFJ=LJx%q~@BM<)}RG57WM6cSIO z7lTxil1){HyT0bMmYp%3CkZ0Win|F_SmW2qN?fX#mvNWxf91)|-RV`Eh(>V3W9KXW z(XW`s+u+p_YB zivscwR-ShKO2^K$arShlyu@JRK`|AfXe<52bM4m!^6f=ZLzScL|A5PFK&Jvltdqgh z-;IW=oOCmPf3W$~n`;Y!UFD}u<-_Z9j$d5-0|%?*ETzI(m*ompG1#lcO%Tho?3Lwe z@NWbj*#5P0ZenGe4J>YCWtvU$FUL)m#lAkiEugZ&%+(Mp&ulb<6Gavv-LDTS#v5^T2!`a&Q>RhPjk zAJ^KrXBQlH(3umTxn40)*bsEX9EZJe@*lfvb-282{G6xxZQ5(7Kkb&lTXdq&kY7tH(1 z;!+)^oIRglg{UAWJ+Bz4_r3dK4+VA~bg6#ye-2GwOZa(bm4I?^v>c3G#oi35x7&%8 zgg)R|_|_HeC_z{bH!ws>ntv!ZxU1$-w5i7U>7^?lr(YAck7PbJak|%t)WkW z@gN`kxr{vny2jF+M>)P1jisLg!4%WAJM}lN?^Dc96h&g1F)_l&@UZ*Pp;h``O^<9p ze_kDQC&4-740c9P$RkBBt7KEo@mURIQgqs3z4)T7bY2zEj#O{=e>;9SY3Sc{Vcnpj`bzI@`u_mW)Z_nDucCPp ze{=pH_UGQipPcpq7=J(Idj!ZJ6hUGzN#G2O(F}?s1Va!QNzx?4AUM3?!cW`b8}y6d zx53rhT{H8-+=DMd!BrQx6HdKj=j0{z<~@0s=3HtljCVno@T!Jh+C}AWB&HJxlsFJ-TOMS z+?(uE%^nv2*&tPNU!wapZUC~pf9`m#bgnr`m5eRT{h^Fu@KsGhSD%=#4pBxZ{QKy2 zDZW6x|0t;Vm(lC5$Ao+}Un=64EdFzk;~&5B#|uN?l>xN-o5)UsvF;!&WZ&Y^Lu$My z)W>RMpS7h|O zv?O^`AC;?f6o=FBIK%^5HufdV!-K*o!>HX;%|Bp1Ij^gAXwc;sxuuc@~LXyrY6 zz6jBAZ)v(`-JQcc;jz=7`cki|<$OHHC1o1iE@d@aM9ixp6oU6u)NUPQ^0b4r&h=fj1DhFB8(@dkC{(`5| zvxvAlb%wM0*hz%q_P$={qt9{&OUNGR9=-2w0+E~q(=c~TW)l}}2PsB@?U6AQsC4Aq zsHVf*r^K|9en)obhU{J&zM4Ne4|%v{Hlfc6XgxyLhGBt1e`9p#>bEjZ=y27U=gLx2 z4AK4gXS~t}|IncQhN_B9m3x47LsLW!GJIm^`MHnC`wsbILfTsvkjh zXx&ve;hp=U9w$%Abi*iX3GX!bjP((dMR{0>Yggqbe}!^Y?v?L@K6~D(QOcu`Afa$> zp3Ch%hGKm;RJKY>(LZ{_j<)9!^JlHg)MXB|;}}iE)X~r4yl1V0LHgNpbzbuW(##Q- zF8(M4H&VZ!*vY#ogsZP4LXAqv-kP|_;MgjnElrpjxFL#HW!?DHruaTb>KW37i{HHh zcrajUesvzR5WbLoy1|5(t}meNYDAiX$7CQCFa z+;mqhv+Uj^?ibAp$Z*RNLdKD?;24-QDO_eQf03Wl@f5AB{>)A&kM>#wxurig!gCl) z|E!X6=9n;Ix3^W4%c?yqJiq-t%7JLD9*69YZ7B7)jqIq&Rr4Xp=sjfJ4XGASURf?j z_WZcEHY1emhW@w{w?V9~OLD(cSRUj;Wm?PBlE(9dr*3`mE^N*6QSl ze=*}4O?g~P-W>DZ-f5DLh49>zQ&!)U(vM;TZAFYeAy>aUURSy9A!`jd(>HT3sD$JF z5{y-M^-lW{dkBG^h&bZm15Xspsd+_vKHNSO|9~3F7hw~nUH{u7`;C7zP1?ojmmbvr z{YA?0_&-_xH$L1R$Ut%LGYI%^*Z9DPe}DD-A9yIpTXh)4X`F^P#7H6drxFK5`esR{ zKp>b1{{yE0+re*(fen>q?`|0KcB{vLJnyF{5je`di;rRa?rTL~>vS6?+>UQ>Z$q6M zpxa&~r2j*ufLy|a|A|wevG|L^Aqie?1De@eWOxI6Nd^oDu=gdw??UDVYjG4{e@&bO zSDVm)>k0UsDX1pmDQJsrXmvZdy(FN7CZHg?{TRc4g%XwXi|4s>`a2KhaN2e$vg$)B z{M5(wJ3;<$7|lCNf+2os8F7n2o_(nT^+&5r|0;?2`|##lCTKOv3i(}m7%2At zesGJo_|K(F&v1>|`f`Pe_-f6-x3`FC8{C#(?DeDXC{~iNz0L0z z%iWdW^ipiM&>DYq`*I5{wv)Ei??xV>!S*vVfF}j0`*lo#9lkgc<=@aX^w;p3pIBp< z&2?n`>On@z&CNn{FBf~%e@uJ^Lh0VL6?La|2g~i+^0*d3MEbAj>NGTiRDyItnK4_{ z+kw4|(rxL277wJJ?)G(d)}D}eU{~3@?-YExoP1s`9DBmIJCMBaye{1$qzo0ku;cZV zidB8`g^sswkFG3mScWOof`svKeb}Qc49}47dOh%1*`4Gx!=iqjfA^M>W2ffKGKyhK zqIBz#;q*Xum*--MO2S-ih{( zaw5H$sb*1!%W=TOJkz18C@FD!>|Ep2@t135nkq41fz4Y8YR697mB_QBJm%``+zrhAcj1GAcUg)bM zkSRL%e(!`f*+V-7ZI^4=4$=^$9nL%|iwuyv%deMIhIb5Mf63`9QCs9nUu3JDrg^pC zxz5n^crfFIfcy%+n#2KH40-7GHlb#7^OmmX+6WpcKbLZ+q?KMR* z1{zXEdQn1aNOBi0M{td&rgAx%>w(C|>2$xxMO(sno((Emip*hm)R=@vrVEw3hUMHM zqil)|W^Rj(5z&sujio@vZxWa)7l8(gpU;=!F=^RyYalmmuRK!T3sH|@^b;N z(-%yiZyWz?3hWAs&Ct8r%s=J>`<=R1F8Yf6O)~V$OfFV!?^znQSkS!tMPEx6&@XGe z8tZg_tBTA|gP?gTC8JB5DvLUm3}aulluVwBoXtLT(sr#5F3i=~`_C-Cmdaeh`&`;< z2HokBrD3DmMOR%uy0lN0%Py@V*Y;cac^nWyD6hl&ljP`-GhR#!&$LY6kB(IyT7jwf z3ZdImW*#mwvoEKTWp2)W9pSy_?oQI5Che{gc5UP2JjmDOx&{UTL%8 zgoTKD#mh0;^>BvUXs#N+Uw7qOku zQMKLucxiv5>V64YPQ`C_a~N>J!AouO+SNuLxy4f^eAP5KIGs@FwG^j7S4-H4saGTE zO|a($lVkg~jD@f`KB(%@HGJN=o)b`QGx=q{i}3KN%9K(`IFuwOZl7~ruO=?Zrg;u+DJMn_wm-rl*q4V!Edq(S54L}GykzAnL(1c3Ow++GRHin~oINY( z_G?VS!{u?1d24>WQY3v=T;@dn&LWR~rZDpBh#b!Sw(Ca3rM>aYmF{>cc@F;qQ%g=&u7;}k`A_FVKRn?nbN$odx-EY> z=!72y5NywVm(;&%D4vfMQfz3wg|0mNh*7UrWfO_-S{>c3e9Hy4oyU8{D_3lr&4&2n z&+zU9&V#<3SS{jP=@+c-o_QBYBge4uQgQPoMh5q7PS&wp0Ox;S3<@0XtXJY_IPt7m zAJeA9S1$7W9rk|{oPR1P+<1t$1nqy7oLb}pm#=?-_dno1^l$P0&s*B>cwgn!3=`7o zR$jTQE$<2L^322uTOMY(Z)u@eG)<}Qs2Dz@wZ1~`qnO39OHP>|xd2~4pudPc;XZ$R zvJF8Uhihg82%XFUnMrpd+>v(5YFOWj0jneu{Q_mnVHs1q%FxVL*A5t!wR49Sy(=NwYrm(28f$bhyX5Eg%Ie+=m)}kW6@THAlTU1eAaUzzrCXFs zACw+(IA6*OS7z0LS=R&#iWk~lUP)Vu>Ch=k_Hdis(|!)y5yMob>Xok78^dr}b|2s| zsD%rQo*(UeMORla63BVhVcS;%wZmY7EXG@BUy9>cofu(!KA(z@o*vas>z<~A$M>R> zcQ8RnTQ*BR6@SEKju3mIu3<~lhDATvTw>VCiD&Pny2@vB+IbGM~qSNc9I zr}DKlhfI<=bx(Bt12SN}wXK$pvV)vDdnqq!h7W4GuWj^ppwc-z8MseHMiQR8w#lh= zTa&nH{_8P{c%DKN%{#SVMfjRxw}qIjX@4irY24Y@(RIBKED>jJTDim(AT@eW4OVa7%E=%)W^{B2$LDg+Ue=sHYDYF+jf+j zqHeW&?(f6>$8SQIBIzj7%i-u6)ucxhme9Dy_w&d-Z zXAYKt>E9GJ;&&X3_{`U48DTaYqjnL=?jo0L@KGd!L^ql2cNwbsQp^5kzbDT6hkE^5 zDACG^AS9*EkCs8uSC#tu2ZN;_bry;D$jpx>ftUfbe766gZ!Up>@na?JZ4$_S856WD zRezil4mce}C{Y-;F^gX-Y>+s&=k3zBsA5)uzto2PnB@;=!9`Lc*alFY_yXI%i9{@b z_xNU8vy1VtQ9A#6A3pVvx;lR}0yMtP-uzse`h50AXO z37NrOZyW6P>%n}?wybC8zF6`>C`tD5I>HPha}0hsjYEVT`L3R7P#Gny<~W4GqFD zAIkriy7y{wQ(d=4@A(z$p7U*TT291S z;KG;L8-V?V>EW+D4*`*Xg@qMc!Cayg6f&GE4zhl9(Hu&DK6`TrPy`{6?0x}!KjyEQ z2%6({N^G={W#SZEQEOBKXlw+vDFY7amUL!amX->>I-ZeB8g4~p=v7mO?xn}0OiCO)+1%}8dG zL|FgC;U*K8Cfi_XwnEnDnnNqFA@OcV81I9p(Uy(FzDNxb8_c4~hIZMm^RV76!8gr0 zI9nn2XHAy7%y1lSh??!9c$*#svQ_k%-GyLrrn%;k5dnf>Xs|t8Z{Bi3WV#n2hgr!GUuF-*`m# z-3;v+T=Z||fLrqBBiW;Rf1I=V)qiHm_uKFa{D`lAz$^V*@Cy8huYZA8+a2Zc174?1 zd3h^V)zQ()y`xtF;gNW6&ME8j{GoQV2`jT7;Y9u2Nk76Z@P8}3{T18-U+@;|N9#m0 z4~S-4@$D0gj0OmSzf_DxMgO?cp1#l2lj9Dhd%_<6J;EN35IXBQ&}e5RS>&hpMhQw@ z68Zg{u|rbSAcgu5r;Ca^QQAvfh;J`B_3efBmFJnWOE>Tstv~?D3?M?Z2OBE9xQ-9U zEWgBF(@JG7C4Vba+ZxgJC;Qf&jGKYo?a`c$mj)^#&(NL;_ zea~-PMN`Tg7B}M_w=UmYbORc+G8Th%0nmjqvcTc-CzTjLQa{q9#^KQ{eeZc!JBWjx zI?7!bSQF9*39hE$4gSoF9Wx`D2atUQpt04}Swv5V=Zk$(-0&cNRB^o}x!^ z%x)*)yII%&++$c8b-e%^)Zw5>LLLuPeLP~a<&duVOB2H%c*~ys>`^6&FAqA{IGbVhw1Kzv;H$gKSkmd zWq(&HNoN}&-c*m0ZG1I_cc+})z=sUClG&!rK<|u`-UcH!4cqJ|NKBC1wbp=OjR3-Z z1ec~Z-WuYY&i{(XD+V+079zyi_BBE__n&RT0^V+hU|V3ZA~DKrfFJK>dFkF9m#i%Q z*GNolQVxCkOC-MY|6d}pxv<0s60dCJJAWkpleXYLM`hseSnoGf4)UL(GVph-_jgbk z_%kejj>_F=eq@Cg<$F{{y%|W>=Um^cf6Rz~PmRKGb+fZxpi7lZga)T|X3Kbn#PINR~UIY04dQ62l4B zFAx=QI)=YF@5bw|Y^?V-)$~kTwauHCh;tSlt~%}bmfYt02%i~{z@A(kS=vccj`!z~ zr9g2mlyxqb+*-xy(Xvp3l8 zax9L+aD}Ak5f$a(bXvJAzko8_jdmilPS`?Um9uFFY9<1iot8JWT zE=s4hYmdd{_0E!4Z4+IhKqpCa=E*u%MZ(Re7qS4aaflLY>d#SX*6O?|59Y8;d*_j= zNcogh5cak#5nB%F^ZIZXx_^pg3X@LB7^O3JOMp_~Pnmm7pox<3n1W>HeFPtf=e%wQ z0*=q;ih`jCp;SAhUcOiwbBStpiwbgZn=gk3fL|!4UO0lRmhd|J8RVCkZcZbJ`D%|M zc|ghOtTj(mE#B;-Z+I8Jdzci;r-ifYg8_7QN&dbXMYeTwe6ghc+JCUU0@&8<@y8E- z6rT9KQ@&|Te0unIE_WnMV+6ra6hq?3rXTTXA2|I*GdJ8?HPT()j}A9v3wIemVi&8W z@vki$(dT{O>me(bjdqcAoY)|fi8rd5#+$J1CM*d5JBhcJZ8F{Pbu-#Qcky@XXMNz< zM??88V;Fx~2E4;LzJHy(f;#-gMyelDP+iF7U zm+1X$l{ef17%<9`=W`}W$tlE1p${==03 zA4~bmO8$u)J5%(hV2si7ah<8qs|sEe;vHg{gHp5oSsJ?Lq*q)X~m3fhVs=u!Qm zuPqRTut=X;?|(ppA(3&`Q|_oU=~h1WBtc$>1``ZwP|wHY`Y2=21*ux3QiByI$xTk| z`X;7wtK46aBc?-pV8P+$kz8gncl7494Pwg2lVDt~BsXe`0b$Y^q#pF;n#9v(u1OmK zX6Z?wuDWtwCWbov?vTbkcl`HRd%99Fj{4nCh-!8&HGgNO+YIB8(vR;q0axju99}Kp zje4oFh>~1DOf{a!8>cFaB?$d*^l+Qtbae4PonJHrG!uRzg1h%VIA|^Z)e83SuxR_3 z1D{&EiDk#Imbt{N0gWw#Xb=A~-pPjPWGLRu0=srK6NCJX&;Vs9Dg<{p2-1&z?}JxfSX`@gDGe^4O#p~ zY{L~r_IZ6vni|INt?1lZI=d;n8SDsgZQQ#l=$Y#QXzHgKM84Y=?@WzYpN?p@$zxJP zZG_X@YQ-qEc7{u4(!W2K^k)G0>UzFzpuY_J&wM zs((?m*?JILPIQHYb<<{cDIt6>)Y0+3aby?aOZI8*mB?kE52Q2OzK-sx%*{G{r%v0T z60woAP2LXOY)+Fs>$(!FFEz-`!{cWR4Gy>T?FLcdhJY*kqISu>^|bZ;Z3GG1u!Bgp zDW>&u>upw$+vJppjVZ1Rj`l<;ynC6$>3=qhw4Rc|yYI)Z#rA%Lm`tDr^Sros8~)t+ z<9`}rzPWFQKGFOYV)FTm>&KrVW`FH}9%8;<$v=UZUUqbSiieOmcOfd;4|Av%?Cv_I z@8(LQdHz`lu1piGyETrCn4MkUcia}F5}Sdm0*_8N3q>k-%S5J76}CDSBWEK=>VM+F z7(+qwedV1=@fBX*0i<Z-28pJ`$QPownAW4Gr?Kv% zr7peXN;1x`)>g^8B@B^&(cb0x?%8JzumpQLGFdS`E-Y5C&?!anHGH0APzw`siZC#z@J8*C@#7ikF?~Q3###dg(RP=o05>Oj;yN+#p5^Vi z41jfoClrifvc46FC6Wkg;{o3obBewxx8rR!&F|Kc#g2YuyolO&i&K7k%Rweyq|^%l zEq_3fQJtC8Rr=$!Qn5A{U4K+cd=&GQAjEvkW>p@(!zDN_>20W@Jd;zgo*v$##|Pk1 z4@^5%#7*RlSZr_wT?rVS=G^jRV0%g;?nVZ!$3TJj&f6n+P)?C3WYeR{q;r7Nz=Wmm zKrI~%3Z6Nx1*U4##?VV2Jh|Rd$Y@y0o6M3kPF@mv z=Q`L%Oj3B0yIWa8gluD`E9oJzO>TtxqQOdTIEL;tXT1;lGx9?1^QTz0jlyEo=FPpb z4|un?TGzRO3$ZoJtbg}F@J;t_MZL`|B;6a{(@i5~1;iD4R%}Cw4VAWR=05R?ZQVJ) zlsY+YiJ+PMhAh!_bkFVaei-l{kwxE-#rjeG?$`VIANCnMXZ!_OtoZKr;l=C!f+`NX zd?7B@AE@%>wQs8cejimnUj^_LRsL9oEFXS~DEW>khuy>@7k}7^(=y=YL7xKZ${JTA+0{PW zoPIchHy6taYjTdtBUM!8R6&Qbu-+PTs3G`uzEWji%;D>i5^Vs0Rh6E_*dwx1pN(3^ zbJ$lVIGtrvRDYtBeAOPeuzG3F=($=Utqhs_1U8Tg-ssk7ZJ?u1MX1aQC_PxOr(iGe zI*@waFkjWMaoZF7ayf+Iof=-(hoSduKFMEr+EfRC!&GkJ& zg+jODL2>WN@uUs(+)tI}lctp@3ADVmr)qImxYw|R0)Hsjgp3s>(Nn!V=VgY)Y)}RK ze!)R2WN+``RK?tI8}1cxelkKiv9HDyimrniC<})p;DIKIJUl$1o;-OgAf_)t8HLj~ zBcPF3#B@sDj-C}V*2zwWsHilU?ifS1K}`lF&<0*oaBKvnKE14Tv|`@BUHd`FmY(rv z&z9apKY!`0l2M}KHaZ18EI2vBc^Qazmby2T4G;s2lf%eK)g*hj+xiO_F;*dEzT+0$ zXYS-hk#run2&?1g;CWz=i&#rUG0AO~;c^HZkVfzw1?#9O54|e^Mb|R!?eM92i-}5Ye7*l#5{J0+^!+*MB!HXH9ts!B(UiwHqi1Bww!wXe?;g z+|~a6z5ea@Z8ZwE{${Vb+~4ku>$lG}@DSE0=p0Vf?`XpVe+cM)pK;{bZ>E}y2gBC& zhLeQ4yasN5>*Y!A;5u}J2?bOcAzpQI6qyU+zC-M6=JHviuZ1CNxsHj#8)iMrD+*YO zdw<(bPr7rRPyN`G3|>F$YIpa35sj7eD|q%= zV^3SpmsEpCtwtXkrd@HiZbbu)A&6~sqGzMu#5q&_`G z2#mmVBmY58k!Aq{em~y8GMX)#d}1&Bk#YF>-O|Pk)#bxkFbEgWP<%WN^bODN9)H*S z-aH7mdgy89sf)k>A`59_=fr6)#Oy?SU50P zL1YT3=>Z+s`f)suSL>f>fP5C%2#3Qz4u(EE=Wha{?fCELHVz{wiZd`plYhwi7fOB_ z6m6a@@Ft-~5WD##vIQ6nvr*TTfFszJR$U{WHE>E-8lHUKnnZ8zn``8z8P&k8T}BKkM|}Ci9T39XQ*)J6F2B8M9?u%kawE$z8xW z+4bgDR=%!(4Y??06Ti>sU4L>e-Dvfua2#&QWn$MYq3JDrT7xJQ`&CfHL0eFC_5aA| zDsf$QF_hNUc*w8v78ETNyzZa+cy_)oiUPk3MgCBmUqg}PyMSnmM1YS_L>4^WTK0Lm zN$1%~uWpmEjeAt*ZJrL^0;O%9?&CFGaQ6}=@O_Qa`Z9QLSt`%=-+$ljs~rDV&-07r z2VaI!JV`-zb4^L9Bfmx>n-eWqACrB$C0+xg$~;*z$K`IDTNW$lM#-|4p^JDV1~3o6 zsz?}7Or8{loC`Nzd~InCLCh^!?VVl~(v3Fxw%iL?n#ZtvYq#p&as{8Ni)GLz19TnS z5x1;74nZ~W@StIp;D0c0m?zH|6omGhwWUG zBPSq+9h`NR=fgL_A|d6Uc=q(?0VU31`3=W5V@lvhXG*SORW8rJKKqJuqtUQDcVjE| za>z`n6uGda*EgtTqzmMAK=_FA>5#w#UpUCqnXWdaous?Y@0@=KKJ!lncB(& zSB|%SMR&FH_0*NkAW4+a+miyG^nyczqudmqmU4*Tg;v-E?WM$PGfZp)+mt)sv8qI*pSm-Bn&ne`Pdh6tVB!S3b$muWXm zm(q}&piy&O40ID_~)`7iA%Iq+4vqtOpv z#Q~@Ff9Li%(zd04*Ou~(P&~IT9vp63fR{6|y?=oG(SAAA{Kxz8Wk){O!JiVKn^DSV z2~gl?rjt0-GY?E9$2YHta)yMXXyQJ>a@4a|5SP7b1r2|Czg|-`%E2RCu`BVcE}@qe zN4`$N`F=+X5va5oIbH}#l>LH6X#gUp0IG0mIlf-F4BF}%Newnq)3$0uk4+4dz z6@{9+s8M-|=VlB%lw_h6iR1=v`<14X=K>t}zF5n>_v}i(Ht{wL5a!X`0c~idKZ9=PaReWy@LB7;u0vUlX9fXBp5>6QFAN zXl>189rXTym=YGsq(q1r=%hlxnK5q1hLPcleA}%sc&^Z&4^?Gn=>b0`MC0@esPej!-;!; z!)Z^#oO%3xP<8wj*?#Cx{0_KQ*mGFfXN~`}L7@A8zj{;sfSUh}%Y4A%FE8;+ljKc( zgWd{PYy6!tTen2CTOzOYU_}-r-C8BKfxcbZgJM2K#ubP*`4DPrkW8>W=#RIoCQ5&9 z@%#!+D}t?G*GN8u_x=rLhfD0=IQ?^z5piO{#VjMkXw%@ zoNnO02}UCufr*%HsoN|=x^%Uu2`%uW08YrsEPT*nPU(&sGckljVN4THt5PT{p3xNlkNKwD5#Y3vUCq!)1vqD8;4NJnfoF+P zY7r{12~^Umw6!~;}6k+&I*Uhj66@B*>WvJgA}v??FF^3xe}>~jy#v) zZUq~El}m0=c}qh%cx~2SKY;m@9b|VckMI&dPgjN-k)$lMEk`y7zxJ)(c(~^h^pqEL7LKGH;rVc{ zW2!B%B_=wFM0ubt3Wjf8*StEDYTo(>K~Pfjoc)Knq(1cSPm6VUc~=LHG7v=wKT`#N zxmE|BUZ{+JH$d1urE6@Epkb~b9uSvhr!Z>EpI|;U@#lgW(DC3d8D+E(A{vKB+|1Vk zF7su+OxY~}t}A5XC(U{xYoBZfWJNPmo5Kf zyr+bcE&sHF!b+)DG8Um5NlVBLLAKHwy7g@&E6@5|!;08Frs#OXz!hXR)`jg!CwfaX z#e4H2vQLu7>+8ED)e1Nm-q>uM3)qcg5uWfe8#Fp5icjp8o+yrfZltHEEi{By|<;Gnv^Py_lw|DZy# z3wyi+e-IQacd>foU;WDPcxT2tM?4EZvLV1ly-iwi??&H63@_gBCvezNWhHHYnwxXy z-2jVc7t?!O0N#;*d~v+|kchK?YxcWA14%SQ3ucU!i_XB7h?7Nw*f>?RvNj8*hn0c4 z=kM%~J4dRGdXt>m$k|t|TVy4*74X5{_J;cn0Dp7j?MpvB>j9>xPHtA^oj72t=4dfj{(LaWt(Vi%`Q*5%sare%To zh^e~n4%$n(psi{@{WN{h(v&w6Y$g*uJ0N zp$(@w%G}@HMIKp6KF1JXSIwDoZ`zZ(VtME#mHJpN58;u2sR^Ti9os%&?6--Sl-6~+ z!o4Zq3E~r(_e{Uya6blZ7xA84${#+`p#@b zFWmLtSJJw2#$-q36;jD;Ys6d^fl|9D&8|+f@=r9`VgmwS$>3gF3b$E$3i%b73i>w5 zKHdKYOx=BcuKod`&WJn#XP!HJK$Hm=b#$ES4Pj(|L9DL+d8@xv@=+YNdGp}1qS4k} zzm0`82E3vY0_>pK=wE2o;fH*p%Z{h~V{R;w1ApoQpLky9bw}K!ihbk>tp6yY`!?R~ zErBo2S2W+GS5_FW;bez7V)?@5&b+m2y9?9TW}Q843K*5J82k;*Ty_> ze~?~(PHf$^M(b-`3J{k5)202^$^@eZ;>H@j8}V~QR_E~# zjZn7luRd{GA8ow=>J{ym&tV?;6zA32VNHE_ zzC#nd^H(i!LGUoXJb^NX>$#}K;#4iDMhK^W1xT)U!%ZFDU{tjf5JGBW8*>fZe!Og= zPh`XbZ)RBwMwCm;Jx{zC#@+0oEBsMx@sk2%X^piY9Hs<(0V6XpMfUWppTzBYcpD^n zhZl+J?W@u_Q%E6_s4}2`NxNCfwJ;W%4v6wazE`QiKmvLdy1OQ;DJ)eBZ!y(V6h=IM zyS2(BOQ`u`jz{&{i7UQD)IiVN*{WYWKoKSxo-fn&iDq}_et1L)tUccDWc8E=@$#X6 zFsbzlZ_`|>lCs=fGkh|lQCw}}b+J!?DDVy z*RxT8A9HgiS2_o-_$f7IyRWeR4bs1V>rQ<>#RGIU3cEDZgK9kiBFP=@a2hPz9nW97 zQ&Vm|_4HzCo%IjwOf+%Dig~UN!Nnc9^%JAry<6h2$2_+NAi|VpJ&^l$p!IQ}@W+9c zHGDbluVoeB>+F0+VfFfdtRGI4suxvquy1&5Or#OCE8xfVNyzD9WX(%adi^DT(MvTf zx<`&~ZNBhv{aBL|z3}(y482Bb<(5kU4opoIVN*Y!mNDZ@w~STkp(4L zqCSLHFK$QN(9-bL8vLLF;p+5+Cpp1*Lyw^wv zNaXHvwgX*!9(m}VFpG;+0n{#k?4jn>HZXl)B3;oSLoXQmH4`4q#&ZW4 z%?o-o2Fc(M*9Wgc)YOws&;~VYanKCH+jTEo1=Dj|V}=Z=WJg1~Lsg||vbKGZftvD@ z`?EGWe!=bh5CsOBneO|nFe(1~og8r=)@8Q?Y})jHCZ1oam>&n&|MmQTFZRD6c#Y9% z0)-ip`mw*`zjdW=T_1mYmGAtZQ3|1PoT5-1UBAKvOn*v^nN8gdPIl+!JtvDq8-vZh zBvJRl_Gs_j$TpMc&(VA*yel2vM%Kw~J_4opc8hQ)%h+C%O!sDB~ z-g#x{47#yhdhg+2$gOmLO77UbO$2^ShO8Hbqs=RZ+<%%y+p?p5UN8*z-Fmf+ zt7n@y+%_)%OKL3c1yJ%^npgJ5$GL_z0jED7=L?q~I$~|lS|fT^|2qAyb1w3XRs`2= zeU!fn4D;NRyJFike7$VK!tsINw2~eHebEtfWwtthLyhGR-pr1FW4a<2eD$a23QBwa zbaN*7kv0Q+HueLZ`P-~-0&3L?$R9I+-@o?V^7sCg|IYHa)dT;XQ)(VIezHm_`wy>E%K$oWg+a0JfyMYk(Gy(Dvwu4c#4AC z;r3*G#G~a%ZY}_S9?rC^s}n98=kmTupRH7QhS;-2R{UU}7q1$y(_4~mo`l&cabS6?zR`7(i9AynMlBF9vn>2;7P=cs0R^b5mCO!6cWAV+15)FNw;BaG_7?kmcet zGFwb}&N2k#hj{Tv5-am5;g(pQ(Zx=0ae3x1;-Zg3)x$4;DoU6jN3yFYl-~JWorhC( zN?7FjY$KqZ9N8x&y*$6y-)clZlrGD|M3P3QeJppIdx8N>K@NFitcGjA`Vpt6;{|<8 z`TDM1Er3`fju-z#6#?Yr_)_tshTn*@Bx`RFVJRonnq-n*LOvLdCpF0$i`jIZMp_%v zrvVj#D5YzEAyY5Mn^G|F>q5%IB(ND7T#xh0{7=lXK*!VjNP92MPvt`^4K^&`u7lJf zlTRt2ir`4{jJVL?`;J0XVHlYI^xmyv3(Y{%qwqS}&l7$=NTu$2g)86|YU)TPj6rYU zBJd{lV?&q7l3E!u#Yg_~@)FTCLatq7guVR4&Rjfc;0Nx?wX8I@KV_wJa2 z5f!n*Qs=Li3@d?wxINi4A#4_SZO8ul9&@*UB!|jS^?i`x!4S>(1@Iqn5nnlD23h>R zfD|~eqZ5Ni7~L>+o5O8dmjYn3OB* zRE0y2YK(N((pbtZNhl(;oo}Z0Y$(qKFLjn7tid|+@dn?R3V4q7;c#|nR&5TsWSq2r zj$_fYNZIC-WINs==bTgO0v=;-jiFJe&R`;ox)%^qzC#k=qc9lM3IFf z9(K=z;#gYPLAMEApuyEU7HP066b-(A6}=93<)z}9Mx6l_zc5d=-DuMVXIo)CkEwBE}L9YAYNub?dOA5>NKOJ}J`wgLA%BHsM2htNwoxDq2IwP3I`yI(1?6tB=Qjx{fWpOn1Gd z{VXc^WpN|eBDmYP;)Zpcz`ieeLNRnSgffY~&bj}2@m~DVzFD#=;i_}jkAlbPYbVwg z#pt1rJhx`EKTQ{DfG`6g3vI2tv+h`5#Tn!;?Yz!rkFi{l zeRTH6bP+61M}Fm&U$aGjJo2TXIK1e&bFBODa;^hjhyk5@eAHT;KP~s@ihl?MSwBf+ zYTzyMNFude6=W@)d)*te>8*Bq->+b#@I9V9nPtwIBT3 zfwB9wzW1Q7dXLa)j)fMowtge@!>QtJV|kR<>n$!^f~gq)oh}!DG%E`UC><&0oBAdZ zjqOt{n4t%#P2bIl&!1rl)iOL0r>3FH(0#EX$Z;3KQy(`e zd8Il(;kjo{i+g-Jmj*ot!X5qy1)Oya-wnh9f0~HR_N0Za3)}BM=WG&eggU+U7t3~w zBJU@XQf~aCD}v>Z1P8EXIEMFgQZ9GRgN0hYUbQ$K=71%CHQA4U-cTkHR|tX;U=0W3 zqX4GeVW6wW=tA?Hqqig)L6FlzS|ppZ>_a-}Vgt^USy!*hiSwr7g z{lY08sF;VjY@V0(7wzF4ZoCumcpD!}KyZVJ_>OGfEWN}#)osHID}>z%2M|u4L5t$M zWSk4Z>LR*VKl0%7ZduHU_R9L1!v>E^=`$db%=e2Emo+cZGbxgns5lUS3~`VLcsSA0 z{{fA#tH zOj@d?%tlU@>{^!`d07s}ShWNL2-1H2P#c%J?d9bv{C-CnH_Xql>;849x3B1*(ghzs zVeS9J&=^8u82V$%;UAy;fmJ^_@w=AlPlX%Ez3UkL_m}+s%E!swEOuq+1hcCwL|eTa z$G30L&r1V1v!MgEEA%CM^Vs@Ne|&dqCFo7PXGNxXACg@$E+%&iT6F7cW|*Hq5fg6d zi}eVU*m4lm?lKiI+dvD0?;?47mvx+MW>Q-!L3*w#~T!e;RZ-B$s-;Zf;G2(d~cp^7n95 z{xq-tgFljyNtbuVam*P5e__2~P7V^L&YNE(NRS-ST7WF3LUcL=%J0ItteP&GsX`CTF0UthSx>)AcwCL%C3?2^*0w5}Sf3)MlYZ2=h8TnDb zkq82X`_XGyMSF4aWkpSqdnn2|8#Mh)+ckF$4Q`%w6p5uZAgEc(X&|_Gp1Q&?&9^W> z7gjX61&c-b>8vDw2N-E$mrd<}3w6Spi_(lk(DJ`J=vceP2IC#wAFv%>3F*;friUP8f2%2JmW5**@i6K*uQFdQ-9Xnj4hY-W7}gJ2_UQ2AQr!=A8k|zR zAk`DXb5T-)BV0Ylm&CH3h$D}jQO0J<<>f3skhpFEx5I?<1B(0XboDSjB?F7#G|0iK zD(%Hn7oO)b>+BQ3^<$f)Ge?t5jaUy-ek5YSysOO!f zXJkUO(}4(CPdy(pEh8V;mAi4(tB`I`r(;cVwt*Aml*>seZj8hP==xzA?N3^0K+@c zM~1{7D_{6Y!@^%Tmpx}Dur5Lu0294Nvz7@>QOAho6^h1lYK-RkNj;y^8A^*4Um+g_ zCpS8g!+n&LM9{>EYNr!Uq8-4Z@DSVNdos=bLBYBZKBh1PzvgsWBNj5bSdqrIZ>#f@ zKoaC?kv-w5>(9J+F~`@0^?+FqV{H%u4h!<5lR7Dh7>A1dGsC(Ey1mbr|Ahq>fB6Fd zv#yMjn&}qg_@->3CD@q9X*+yDZ>k{3HdoZLh}+~%cAk8@X#x%Pt=c$``Ed&}3Q*&K zx*SkqMnkkGi%6)CVsF*pwJApERllysu=2e@dRCwtgW^PC%g9=e0~B-%QI?Z?c|Yw*w^FmR*v- z`2HRyoxg@6Xf^bgPJdDC>$PC;W&MybmW1CbOn#8#Q(<1qgPglN4?kwj0%UM-{pR_^ zED*B9v`p2MLgqL;cPNXv0Q+oE`dpv`!&8NzpjY%XpKVPR8q3X~RVhR8|iJ{|o=_OK7ml*F+LrdfL^&^$RnNF2uF5mugzr`%q%a|@3lqp7#k0$dR!^iBDVPuT61 zMAo4{q;DqW4w1jS zqP5-XXIdm_vR!Tst+qqat)CDLx5NORY+tEpYk9=?p|dsi+B^%;e_f3j-|oF~cs$+| zh}VCH=`O_>?e3iD7G*_y_s0KEf~CLk^*;qmRgReA55dxx*Z$XoCH+4Pmefmlc)Gr8 znjT$~Nm2<%y?I6SnL`Km5cZyoF7{dK6#5DT+8i?P)=QJpy57c8V{rVGMET3S#hTIM zLV7ntQSjm}TXa0Te?3H4yO`XCn;#<+V*+4c@xwWnXQG8X_l->2g#`&Z63XE;s_Yw1 zo@G(uiPu#R2hw6tSyEFT%!f0#@2l1^K)*CRpNrDngKdZDd9Y3kD!V7|LX?!cbM9)N zh>zE3Ow*-tFHosm(Kq#0Ijnyd=;;E$yz)Y7q~lM=C90Y-e_VvYwAe;8aC|h!Ab4DD zQbA_1Fm7&_K8ZE>9Shhye&=9o8Hs#xY2n2|SSX4I90WOr$@IdUPjITpYjC zXvdP!DJBqRe5B|bX&`+VUHSs31-~qM`ye5tea&Rp%;+J?9oNl|j^?08NTO&AWDZgo zv=nvAr+3Ocf7H~2!t7q!&J|eX5spl`(wLilERTd2i0=a-5=U$9Ejia>Qz7A;x`skY z<%LcNV)aB14{0j2$T!|LU?Q${9$ha$74Ud8@8^nE_}ZE;Ep1$zM?>NK17&KBs~?zO zUaSMBV91eHTqR~^4&wm~pF~}ZjxcJs!TZEsp6gCde>?9Ho7!@D5*cME%Yv0<0OqDigZ6^{_s5e`3X=NenN|7-6t#6_LY7%xa!&?IggaDiagR>=-nS39VM+Q1e&Ou zp2q50J61w>=(G^~=fRSY;!6hA5lG?PFunmNrwAoFn5W~L|EIwcdtfWTa$Mo2E9~{o zzwye`e~|_3@XEFZReUG!hcCX)vN12uo372LQ?52l$q`W>p{3ic;OhagZOu%VYjiuk zK*j93JUd(nC|dMVeYM0Z0!2m8#|gm?)Ie9)M^4;4@KrLg`qa-C8<3A}2OVTi)xqN+ zv*{}y&rfHW#nzCTY_ao$B+Lva#lo?eA9`>&e@s1HBUmFpT!FDrKvJ}ku&x-UM)#Yt zt{$1%BOD$rSjkSgAi2mn2`(5`HfC|J&!IHeym-hCg#{v|)P;aa*qG!Wnm$+>)vqu9 zb8ym|J|4%@<=PeO^VQOUc~%iZbl5P@%Oe?IV0#U&4xC|5Zve)y&=#S#R}Qom-r@r} zf5u3tJY<;_koP=QGf3H$VAzjqOoB41+7W{Gl|VOMv0&r?BzHqiZ(M!DGhBKc^kVRj z$b&W^QSYv1?qAQZ@^mw(#i?`e*dp}fc4z&Pw^ex|^_u|PBKd4^0!a28e>~ItjbL>M z5f~3TbI~Aa4~=SP|71k*as&DB6)Njaf8wE+Sg?#f#}NQC1^p5Yxf?iIRz$5}gVpVJ zksV12-ugXo>*S~*{ORp@PlkuRB@b(jr9tL#Bx~)>0|Uj>si7Xzj8V+##q%dVP0dB7 zZ-{>E$%C3zoZq)SHC&s^P^_Q?$8K0WUa(Waa{mHwD5nNyG7!|6-H5usUVTV9f6~CU z)AF8-^6-SDA&CFMtm6N1(mJ)%_+MWdSvuVg{&Ae~fAvn^>MMV9mtPJ$#^IjJfwxQ*zI!Jz=+?f1><;I2x()Kj_}(kJ z#%P}_j&2rA_PYtqT~!V0#FZ^QcyHgyzo6H9@2H^hY5#p}|ownC*_-DkZqwab%k#g}CF zKVRd!U)NB^T?SzIn_k5X_!X{r8Ogdfs{^V~m(_8CEaFPEs-=XW0X!YLF>jKZHx1QFo*16M1 zF!vEg{YeU7>*r)=({a%+!;$(|ot3SLWuK1x{P}+8@qoX3zTbH~;P0OA?;h`CniBZc zI3;Txm?Suj*HU>aDwU^Af7oRa7AS^~_t0Vhw4miAR?1#YM)%rE9BWpY{&b2@XS+{I zhck_1(TJQ~zDKp3JeCRM5o8I|#O4b>Lcm#@os)lToennMZ#Gwu+&oLPaD1dSLR?+r z$y@fi5FGHWL&hEe*k7cnZI1PajA%H zhDP;>zS!>IEEpb$bmiQe?`#%6pt<=ac$>wwU(dL&r+Ym%-E*P!rovJEgJ`%a!rxOGM4 z-cM7DTs(;6sDkFtke^TF@_!M(0Dl+2{J-SASJR_d7A^SBujqHhT;WZ>fp9{A0O4a^ z@E#$IFu#64X(}r_v#aXP9TPKAS@B5-b0nd&*4}6DwSHNP@uzOe2L#aP7{0^8CCG0t zf!BI^6|DD}xUat>Fgw4oOXR)B{uJEaSHO|+sk*_Qgrz4s6lN>CpnqnfhgVk*(}A7b zrg}*M6+t-?fNd+0Sk$4{KtwXbXV1J3K*EE6V9i_7^<=ezuBPzIkdJeVZE%lp3*ruZ z_t?xS>O^YjS87Ve$;!@eCO~Ef0RcQ~-h_6Cu-Qqv9KTtR=v1hv#F7S2@vD(^8%*r( zq_gRJ-^Athd~RVr@^$tb?;3wNb> zXH_DUSTIaR&+-PITIzkeHZ_n?Nul|HuxZyuy+E(3g9BltXS9ayjLf9P%A8`7qiRn! zjP6NjVu6OZsI$(aNEoyO%uZuFUbmcoq6NlrKegZ=$kiu57Jq&|4sbg57>8s>siqjJ zWT>X$Cmj7hccyPR`4?yT6I4Pl0;42M;sg$ZAWT6d0Z}lHA`nTED7F8Gk@zoNB2eTb zxkVlg7esutF`^$d+98cZkJgSIgp%;6;oNt?e+{S+b-;1>scqQ7l?0Dd9&13zAuC1@ z$66DN9j6ICQh#E^$CfzS5%71(4dkN&76!*c4+H zLD5G8VJ8HK6c2V(DnK6qrm*8O`+0VXa8yQw#{=Ro%St)=0MzL_pz8LO#h#)zYBQs( z&(=c`v3dN*Px@1o0R3E)z#HZdf;8Fe>$dXo0s4pnxPQjxJN9}MCq(dA@Bc$Uv~f@6 z;(e>dOpQGn{e_Ca2YI5#`XSZurTXDVFp+4(lOkd4bW!c)#;%pi)nm7#=VJ#?R{8$d z$umtU>Fua&02DJ?mCeFbvknyT=Y|lQ|4}-KWopJ+Kdw$67o%9*A$@<+g-*Q%JD3KD zy(y1umVdryOeo%X{Mq*CXx})RLv}=7{Ri^^z9)5zZ055cQzsR}XZ0MwH66jjnGQDE5!#Nf!UD^>JQ$6A48n(jP!a$ve6sz543 zB~i=^hQ0BMKMQqKdr)!OQH_XHBaJU6)@;4Py?^t!2%oL)eFwsJtjV%i=G%28;M*G9 zncN~dxK7VQEkEJDo1<>KYM8r%OGANYckuAr;u5--J@#)1aQHX11!eP0m-&6g9}zXV z9Wv*Ai7=E^h~Xun+SLX#+nFiEg|)z_0?OAg5~F+l90SUDCyQJ%8>Nv>3muz>mtjsh z?0?B?; z*CHS|yd+IDlGS<;177|HqM3KtVn(0x2;hIpABmAyrzBo>zMg?i4+b*j>UEFPAm-sK z+^0r4-r?<}u(NQv48rltV`gRNe_79DM}KKV#O^1(-e&JevsofND?jeY{kY?W{<7nj z{i^?{vjF}mw0OgqLaVR57Do_rpJ#lW2>!LBT>_tsa`Euo;sdkpGj#v`7k7L`4E`I_&xnY5RdrtlJsLAY^YmEV*Om>Nfay`I ztkp=I7p>08ml>t3+`A7(m=W_`X4WY|zy!}>W;ge2++)46MMWtMP?AyE)d33HlgF1Y zUoWMFl(5{J5pN;pDI8W(U*g4mw}1S`ygDx-kT~16=xwZhM6Gn`i3WLo1A={#JZ0-7 z$~l324~R^W(Vk}?=m_pF7~h) zhd;#}AI&-p{RkIepPml>hq&IS!}PFgg8m)-jb_XP zXP56d%U(Qf`&E6j!ht_wkbl7gieb&%{7o%$;pDHHo!^4DKcoTnc>zf~=|NKLDI)_<(CS(IRTc$C?% zb7HyWa4V7R!R5M^^{G)ivIHY6$AM~PODud%GuJ|4V0?%-cdKcJr}hA4Etg{IbcXQN zr|CSj`$H@Z;d(Kdju-BaynkCP)wxD}HX===J<0&qhxUwKIQZs0DP3e)l!f=rr*Et6 zDlByeg$WW>ySowovVSobQGfNI!Vwm|7XGjZg96n2%dXW8y|=0ostMe0^h+-c z_@%rsWv-&ET*a$$73imkXX(|)L&3-+_W71!ql+551Y&_&lLuDG?w7kwZm>GOP^?)( z#~t{vZPk*@>-^;=vsUG64&vCRtUKG;H!zA;d!fKYm zYw({vI}agTIDdq{lGA4CB1E5coME2qNzj}ej71ukR|<)dX!0)*_$7UUO}?wYJwzG+ z8P>=6O95;e9mC|Q^7C7O$j#kP>~2!}`7J!KGHU*_z3T^{KDqG5UXh(Kr4Js@ME1@z zQdck!+v9Ymm*r03PNAhp4J_iSBHOc)v;`1E=@zL&#(#UE&Zd`BPxDZ&V5b&@&m&9| zt)|_?L`nj+C|f_Rb%A}Tg?Iwx2g*|&2t1Lqg%B5yel70+9tP=QtWU?CB)hM%Qf|rd z)IZXGtAwhAXVb@^#XAeGRTG4AzMwZ?yI3z(H&IXG?AU~u^Qxpmln*#6nanM$%!{O! z-imMaxPKAC9v29R(ef@4L<&5kD+y>kKn#C0j^Iy$WSAV6*$G369OpgMiO?f}J{ktl1MT-Hd4DPXAUXNh zh<~jgh`s&^vB6&=Hc$U^#J-jE^BXo^t-pcThVA_ZwXIoY{hv_Vnt@~EuZH$_M+W?E zXuluXKk@FB+9hX=c`8nba=YB$?#yijR=lN_%DVKCWL*o?WhPNMbFUxL)_6OxJdl=2 zXFpnRNZDodo1Llt#t$dT$0TbSNoA?vXMc9Og_(AV6%as74e~}Y-;A~+@?10dVnTDm zVfn#!#tfen-SZiuREQf?xbdBp&wecoW(|{%J?Qa)mu@P2vSa}pju&x4sPJSGj<;m! zCPd~#H1qV;qmxk@i=zi>7Gyg)+3_Oi#e}dPWK$fHh*YZ zf;SEhmX|%>LvlyhcZKCtDc&7&aNoIm8E=n}1jI}~i8t0`$?=iF5=lHqv-U5Yjms}j zcfFH^aMHP(`UJrsNJIks2jqU}^U*Ys{jHU1^==i_QgG|jmxuKoJv&MrlK>FarTz6v z^@Tz7@5pWM$o<%nTYO#xZvUUjTYqZs1%3wZ1^M=cdi5O@3=s*Fn{V)^Phn$&GN|6Q zKW?;IDZf;@96)?jzW@=U)JMYRvjOCe$Lj~BZSV6~VQEa}NXoc;ldC^q|8qMJ`i|^? zVN&IvtfyV6jvMN$)-g5&hyFbmWX6rT8z*xf$-Vge4_|GnWc4HE7cXt#$|+{u7*Em0=4lcqfr>k;<( z+3NsgVi!p9s!P%`8)Ste%lcd1pO{)`_&^^CLXzJr{gkYos+2yW-t!89ZVMO1TQYzc z&dt^?Rx*h;0G2Kh zz^lw+oHU+$w(vRhE=@75UIOTHZQYBYmiJ2xiKX@mUuE24wH9+QQ)76HjQB4XxY_gj z{p6X++s=3kWlTq?(1w`uOR?X#vXLhHJyR=6ui~p+!bRpE(BD^|r~kzkLy>&}Qv*Iw z_wzjXAH)CnSwsFW_WiB||I>bd%4CBW0V5cQgD^rN2tvZpFPF=l1t1SvC~yyKap=fO zCm%(=I60U4oCO+xZXGy*kLVo@K3-$-rw9-HC@x_i^oKr@y5Ir#haezzGy=vucL1a`I{U%!|D&_ z+YVpWJ^AZbkw9*roTBA^hy|L~rhKW<+hdSFZ=9{4mUAs|Sh$TgzKR`~mr7cX$tv3C zn7H8<;Exxd`-{g5b-T~IQ?#OsVAAe45qj^a7moJIr>yb!4 zypf70sneH#IN;p}H1b+_nUQ+}sFAeTF3z0rQLyeTlX5kRy++Jox8RJ-QA-sr-Dal% zQ^j^(Mk zld43W(%RKP^x*~}6DELeW+482lVFl@yugjRiw_GD-&csYP7wYOn1OSeQdlDsAD4U9 z$dPd)QpYA2vdz;ypkLinUZIs-drHE=32oe(8y+#fgOOeibGdqc&3jbeJzjQ3swSr| zo2XBJtI@HBUiNoD7jU~z&q95JrW$?RQ|FWvPg;FA(1y0tLmaeiPPJan>^E$@H5Ku= zRW<^QN!pcyU_hj3Kc2FI2{or>O|Kr8JjXa5-O3AHY5+&Y(aZv1TQIgS|GChwcTuP#q) z5y#B3SfDujt&@}tlM56QooKqEYF*4D17feu$xAc$T^YAL%>BMV>fTbQ=jIolH z-i-lhW#z6JNimfA18VX0#We)zKA*ab7kqwBF*Zs$S0gIAt9AUUrdlS@wzZ`ptxlSM z2?71fzSzhNbKXL@gU+_zg0;VpzWAu77J+tbj0=G{ZjUUyg&o(%$@TD44xWlHocYQ0wq2+z*! z#)5!N+a3&&f9dx_3pX_oSuVEY$vta*{5kB^y z_sm*k#rEQyM1_gt{QPa{`J`N_SfNf5>*69E-J1<8)`?sI8C?giN8b9SByUcV4!NrN zg~?e<+lfVG6DNNhL~``c$QCjqWW2Qck*8g!M)KcRpt@XagTDHQFy!(0D2CH+*W=;O z3RC}e&+iIS-}d@bx`Kp%NetY15lWyWPT?f@OX_$`#TT4N$}_cO+M}f@rUAs$-%84>gZkAsn*VWV&Y>O{^`1ZfZ>DZ?F0z=3>*I9 z0`$?BilIaG>S%h{hw_*7NCdabg$cjsF0SryN4iQqcX#@i#@u@OhqyjK&$FakDr?sg z^RS=GPvZLe1FRVxR2@YJ=gap@g7J0RFatl91X$mk!akD7)_gY=MA_maU$K343j4lI z;jRl;(mL=hGjg$i_&ucXAG%csJD1VF&e+^#o<)lrzl^fv)USGaN6i6uYy<3{%j4{$ z0PSxxo)CBi)7i6LZoi&fzw1DkV*UD!XnU;R5DS?an|3j7TH1_gI@)H;yGy4U{CgrZ zrEH!aAdZCw8v)628SH9IIbclSUUUS)HD{gcWlA|FdOqfVG#=GVK}ZljODFXOvrqY9 zc+L|L;NqzzC1?mM^^9bhCU8Z|6*^a`+e2Z?Yt}z;Gie2GT`oFU+AYbMapmSrQLk!8 z1GT92TZXwBeP`|+czfD08w86Rx{aRP9cX0V-kV$1+f8Vnc!JXvT7!?*LSgQGXfWSj}YlB14A7&{9^?<`m%0u`PL z#q+ti8YN_O259G3cwltI81JSY{2y#{6<%|*ldgE#a zEc(@}!Sh^bnS7?}#@&c%kpmfy3q@H5kX>-)4BzD`!c_hY-EFTyHXPEFJJ2AGfyv!N z&g&DHx~h}6LlyyPUX*DoegR9f0W$arB zsm>89--r9MM;}+?ro*^@Rp>6#d)oiTc=p?QJyMrLG^e_E1->u&>l_!E%v<4ps3q9w zUnD&E(nGw-ca^u_)C1rxSo>CSa$&gFnSu9acpwPt;*Q6@6KC%9#CeaLA-P-aZF^ z@CB0@w)mhw7F7=W$!Q9}A2k)%%kcuw;1}AUX#9LXn%i~w4l>hnyF~P zI{vc9Um(gD@Uuh4bhMz*p1w29{W&=^6Mdm+E87pegLIP7*>M72KmN}9e*0gJqXB*1 z&%}HC8R_S-!JnC$7Es!oj}vk~UeP*#{(8rW1(FVF=1mI`4G{W%h5bs&=ZwmJg?-5T z&;y-mj*;vKmnQ|D~=* zoQ?bbTbLg&=KACU!4UquboaTH3#{I6?Iv)RdcVy_AaKyPen=e)H5?+!+xwwd%@_9H z1tR5v+kHl%*i_}a*Xc{{@7J+^hWq7K<~WYs8Lqy34%CJ3zrf!W>FlsBMGM`X+q0#% zj~(@}OCu82{Pf3*rpBG>h4HNhVFLNUW_(zx z7t(>`=tL#AlE(j(b6M1tJC}$=- zlxif9+5jOnUB*V)k7P9>$J285^~e?w5^)~7+ZX7A$`7P8Y8xRb$(aqrSm*Qzgqo8 zlbL)@IuTac7;W{W7~$MOhKm;8@X~|}M+Ar@w+#-y?zG^POC8#4(cP}9J5(w)^fYw6 znKLd2Ur>mXWP4#ck;&ef12q`R88VgwSA6Tb$3x+~i{-p-#bmXAk2&6q?gTE}V@-r0 zoKV}%=X}okQlvLGu^*N|3>yvP&_ct*YHN_2sZoOFG7h>Cgl99q63?`87kC;y zSCGbYGy8ofW|G*hucHqo+)fJ*#K_5$u;=PN`ZB*0d?R@8x}f)8QOQbFGM`eyPa{Nc zQBvml+-TR6Ja5^5h)jhBJz){(G~3aaz?Zd0W%oKb2^_LUl9w@4R^uY+cu2>kp}~Tq zt#aP0Kt1B0`IdcYoB5%d`0qNE{oMoqBnUgiw}FxC_dJ5N#Y1G20y-*xe*d8Viz5C|2^@VB7CZW80Gp4GeC*dgl=+8};je*6NyADR&1!i?l}-II z5Lr~y!hlaDFwgzuB5LgO)ph2+nTXD{wFf1xZlR+Na?3G$fAeMm80f3P*#3gZ(!uv! zEM&NcV7mb?Z?EBp??z-G_ov_l_>1UdX5#l1M>j5id_Hpm#ne{hZXzVjgacn%DdhnO zT<(U|$~t$0xY8JeNCG>SPjmg|5=SXotv%Z7dLM}#gV(nmyl;1ZFsIwhiPiYn0Fahb zOY`j>_U`M65xoo9D`f>)<@1@HbAlf{ZxUq3SRG?~(>_q4YAW(ddUHWnO{$- zX!sC+na)N9llPmUqi1{_JzWB8g`g0I^z6AI``3%_*s}l&A)<9E=ydzMF9O>&hs1sy znD;3RHq<2q;T5@?AONGf|YH|Oby5SK=LxF8f468rs;UT)z&?H6GLp!n@sInQ+N zc)sAbx{>pxGc12~7l@0NIp)Z*SzyD^Am?^}V^0(6zgDe_E>IaQ)d&OYZ75(@(Yn+K z=x22{F|^1gyoh<_rP)dw7|>9b*TJXh#)CQ7e5t~?QPi-)L+D=$pbq5wM!hcB9D#x# zcGE?8-CVr6%lQ3fJ#)XU(t*4~7bi`iQ5TK3@`5L?P+?ZiLQeyp^toFl`}~F+gK>L* zO*33Nq)=%mPb{?Q;l^ERQZ7QDa=gl%+FUGb>16~LE$d@>XKW0+r4#eGbhQEQheQpTwTwKutEEKtZs{#V~C7@;u+Rm@63DVuj91=P?I-OQ;yjAYjmzDx5|U#D?iPzb_rEOD~X1$THr#NV2FpU*c9RY*G# z%%QfaWwYR$O)+ivhGJ4jQ2u^(oMoIiH}P$r8L)Iy7ol*}CtzG*lM;;i$-?oCcG7&)}WQ-9fpe^czB6-7O&Iz1NtL!?6 z4i+YM_Oaz@#2H^_wYH$ml_V=j9Ce8n5!fgtWxPkalLHW@2L&rH*H$n3m(#$E)S1Gi zq$ji|RHLl2F?kmh9N>3Y>Q{}XvKzUF=0*=<-sCs{z8NLA-%E8WjKt}G9A$id#jOd& z8)v}Nl^#R)YNX9D`)7Yjx}vxe9BEA~_d=QiH65TGv3#)D#7x5QXCe3V{>|fdqx4`zDwqV2B_{oCG0%4Ev>y|Ka@o$zMXB z>?VdE%hoXdmBB>tq1E!W#TolI`fD{A6gfCgc(A7w7&&sr!NJ9gyXB=wi<=zgRW*2_0`WYCgx;$JKxSK*Ru%_Vxj zF-(h2~p2?+O^EXEq zm-Ex8{-9tF1_qShsKoqIBu2TN@HL&Ufwlz?-%dM(2W%rSTn%|&L(0s==LmL!;%(wg zT+DgK-AB~UdYJ0ScygOmY+t49TnZe!j<1qVG7LHK@}lMDC+CYMjBVxS1MoeES-(0tq}4IR}+ ze3_ci$B9~M)<_4GK#Nq28amCnP{||DE3uq_bLr-U%@8m1q6)Dhl}+BdAxYLtZcb}m zEK!$4gDBRc8Op&06yb^`?tNitoT6!$0U#k|B$*9=BAgk!yLXx&^2Z*ZswhiDh`ESQ zd4P)P<^|X3goV^fj56LO;Dbn4Pq)CmtsrWl=?x#Or337Gl`64UgsOWbrI=#@*C-L7v!71N^kp|pD@tgU|Q57Rc9`d#VW102>e7Qm-(<}fejIAtRp6LFz)Xjx+eu+?=x+EIjt~#XS8O+6R-yl%cT-yH3 z*1jY^DIChSMuN-|F!e5r8dUAg^ z!c@VS=n~H=lf-}rXGw6{SkntoZlm9><*EDUY72PhvwabB?icn}w_F!k7Fuu=!e3{-c zf3RyEE?-yRzSgW!-o1ALk^Qkh|b*Gq_wGz+vZc0Phv#Qq= z@*b=xCjxle?>=^s?sCNiWnHj%uDi}_$pN|OITC2#dL#4!r=oetq@vfG4VuNm7&b44 zUq<2pBT1^&d%6p^#(Ts(%+LM8ZUS;i(+U@=JM{I?lDb(R4^NYn^ zfX59+@Gu#jycPi{@WuQnkBd z^#AzmmV8`*zg_5S>v|Oo>wY06>8oTbe(smMwFMl1ub5o;u|Yga{g9);K8z2BM0`|S z$l&lT+&LN&95jufcEb1TmOkiMSU(&P$%7N_^a)RnL=*L?)5oHZigA1t6Yf0fXw3UG z&|^E3`<;mLF_QG4gz%?NF#c35?ql1}xNpbeW05`jbQuO80vCaw1_$)WWbNFPL=HcK zB=|IcCQ=_eDeTkEj~zleNc2}sPIw%P?Cc+oOhJ>KT3!fO=s(i-pL|yq{zna>@lbT~ z*!fd~$kIL&He-G;xg8Wv-^5&0&>C&g_sKy@rEI|-{Y{Xy_;fi6;iNmpM-FesvRoY`(aEbaSJ#y$e%(|51# zC+mH;>wa!(mu&+A{LgUy)ExEk9{!Wlxv5C$N zDe7?xaJ$sE278=Sc4;1x=IfJvWgd645+C3@&h;41$@MH_wz7$EtA&dQuvk8yt}8FL zk9*aCp{@!(8;(#o6kUMzbj}LzwbJB$8VB*6{syxULOOQ4+`6!8A3UH_ce;NGR|m&8 zye4G6>kvaJa;i3-+lXuRI^hmTUsyqZcW2o#w?texIJ~oB`v!gP3A~_F#?{w3TAF)# z+L;h8vlH0Qcuv}{J6dlyLpU)*K@iGaC!T{Om%PkxmZ;^iFC#2aLFlvF$d>fb1YA3v z2~-=7-tFDi=tja7Te!(m&myS@k(d%BekIvim9|4&sQx<=f%Jmzu?ih&)W}MIigV7Z z7#ol(qM#n+PRnp&&xK>0Y@)iJrT~5_Pg|Imuk+V4&7CcC_Qw?n;%>@mEYSq-@{ zxqp9k5S-mSJk411l=am81-8W73fRVajCPe+hOM$&(fiRjarB{$p~rXM1}SiaE+pv)2EqsT9A* z*F9*4F^^U@BwbH%49QPX&GZU(H?ppTjzyDOvczC~>C-!XtGFB`EZn29_H+|21|XVr zJP9iKx_i)=_NM2C4V1-y^4c`P@HFrkQ+a;>DkSydaf^JOaC$mhn3A8%yL)?ifH1om z&H1-I0@Q4T=DQP%j1v z61JfT1KoyaM}zOr?AAEc360Ruf;(L zE<+7C+rT&#OUeL$ud&H8K7*f0+$m(vzS&^;qL}PyNE-6i-OZG1VBO;g9Y-knNi6+I z1{>}95LeclZ;_Hmj!v<|SQo(}%h-|KUchHB!ANGZ3o5k^tO2w{Uf@B*MWn+ok#WPG z*{jA*QgH?m7b5Yk%>BHY-jP0muqMqWMy}lHK6g-B!(+#P0xPP6WKnW>gMhc`%mhdn zoDiJI&Fx{4lKO7N+=xZ$3P&o3xWoqA?X`oa{TnkbDH#K*d_G;V2m#9$*Yy3CCCu=S z-}?}nd|7`+`{|m14Hv|^pzZ6(JmSn?Y%{D=g{uMkr zdQ(8~kV}MrfkI-N`qeuVCCHDe1$p$*9(q#5A?~z4J(ic_qo@@7xS5h4QN<`e z8h}vjSgH-9j{(U?`x-<)$=8p@1-!Fc`2W8Gi`Soj1r`ryEAam_0*lvwB(V5$sb}b( z@~ukTz||fFR;4uw=e9>%F+jf_TLZP5__3=x3cRy))#m(_MLrQSQ7^cn zdjc=1IFhpQcBa0e=e)Q8{L{q!p1v-%US^4@PF8iMDr!=}?0Kip{CkR@kp^Nlh&&do zFsxgD&l$2(re-bTwp0L6ely)ZTI%Y`pOByxUm7&Ow=Nm%;pOrgK8)yFxV#sN*db^- zrRBX2y9Z0MCVmaxFQ9C1nTDH*!oS~n1-)u}WQ|*<^Tt-wcFH%J*f2$5yb6{dA*Hdb z`+8Xf+qsK0i-bNfUm-F})isi^_c?#vVVi`1mR@?R;(B^;I~y!p7nUHj?M{N0sfpl? z+;eor|5XBuXTW*TFfBGa5s>;)byqLGp|Ubv{!@+Z4}nERzZaf9r13pp0d?@llLaTI z;`T&6-q}c)Xiu-cGAgvkJCe7MZG7F;E`8jo>d|$lEUyFbMDJ9-(C7;=y_fuY^0sDw zWAI?}iv$O`D{6RtB8NA$ZzWqnyjo4)>XY$`rs#@z!OCZm4*Xm6?HRao&m+P7Ixh~5 zg}s}Mc^JDhpA@y2R+pz@sK{o~#K`kvQlJJ3Mh4PB4S0Rqwh-b#2Dz_Pxpsx|?m|Ml zqnX345Au{;?IIlNbawMH=1cm)WJ+Uywtc6}!RXdOX*dzg=qf<9Pthi$BAcyIlZIL< zL2tloHdV^&3w~(q>wa#TDOS{X05a9|D!1jd-FFgas=ZNb0P{%h9L`Vk-!^YN+8)N| zSIkP{4<^AN^l5?ExBuKB@!xm--Xig<-Tu@rfujgX5GX~E5Q0EB3jVTUDM*eiZp=g5 z;j?NLM281879UG-JL2tdw_{Tn9@R_xW9-)zOGmoplPp0#$r3O+m+`&@7k@_ohJULn zj2x?jVe(l^LyzNwPs?bC9Am?f1LCMpuLOyIb?)Bbj{HbfAfGa(V;S$GBz#~sd8i(z z=mF!wj_v4Qf?j-pUVZwbU4qqQuUOJy`;T?1PbNoWxkO>+@9h${?j9x3Ung?GuD+~z z9i8di@^hO+EKu8z!ifMkOMm;IzPCvr$C{kVTBx!yKUOFGAydfCi&)apcWou!;=vG6 zvahC!wg0uSNGT7X`>8$R80pX6+B>-YQd;mg=wavP54+sty0ccnF=F*^@@bTn|F_)y?+AOEUsJ1iH0PX zz-8wGF(yCmv$kZX;b61yATX8VcHK7Lk#L4jYl*#MQGUHj`W3;q6Y%i)d*D5k&$UnU>VNE1HGTId_ri~ff5o4WepcIL6G)LAK^cfTc%R-qu{Oyk`$qWK zqD-iL1mi`Y%Is!rNXRz}X2;TkUPEz~Q%-J4*{<^}C3(F7lIQ##K2nn*enNz{)Axww z=1Jb2FzQo1_x(%=&K6$3R>T8;SrUIsYNqFgE~_(Q6kOcBOn+~7@I!UT6(;*4&UB@9 zW5=!IzL!6(1GF&9y29=E{x5J#_)|O${3L78#G4t`Tp`>lA(mNGs05ZPZ?kO6Svt9I zliAwpRAR(XLU+O^OW^INTL5iu;tkQ=c*-lByXCL#eN`EZ4k46UT2I<}+dish%AH_d z(+K8BZQBFbGk;cT0Ne3>Y=rqW-8^ZC#SsrRN0gSd?{m|)#XH%&!$1J%WR<91*Y2`g z`08A5co^bX7XeKm@)wn$u(7wHy5m{pfy}*S5rl4>XVe~37lO%v!l747@?P;Wm)cf5 z`z6CdJHRYZH#r`8f`sbt9M8Ehpi3q2iJ`58#9*&YGJoB~OUqIC$p|`C4wncKkcK%= zsj3;0{044)(> zDt@^Vv479!;m0fyNsj^!rg`@eu)>;QhET;=ijYIpQ$uS+0kh_44wDOZF z-jEAYaY4mt%xD9167N$iSdEJI&SPAW?;@kcrwdk{Mgxrpf*+;X>g@?V4>`V^v+gAj zEXX$Yl>tj90eZEcEwXMj^)b+y80_zucz@B7(Bpc9p7YHS1BA+OoekZ2BRBjM`3e@@ z_v!bg^83#Pz)3fqW;~j&u!y1=nmZ}34M~qO_lPkHZ^JZb@NeMxqL~}zauV2PZMlY* z+dc(8o;iSOGxn;rAa!>v&ua6{gFK_0^2hTe$Iq+!Ov}fz7>I+>FoO!AmW8-gV}Iom zc=Y+@c7T<5AWFFPu&RCbEY;(s&Jsi7UpvjDB)aZINjzv%FU^xzfGE2 z?x!aZgfrUUkE$N|0&ZHG_Je694MV*@mDiih%l+ed)LZ5GuNIuDS8|06&3xL#OY+NC z9RbMTV%22_ZO&d0U+_cmm1-vJrGGpDzjOcj7-DvC_E4RjGp7J{!N~i)*ucz)b`QPm$`GGetyruEe!=TYoviZ+F0~ z!0H4M6(eJ-fP1ZM)j{L-u1iO4H1vH0woCc$ ztaP*HzpsGsV^b3FvjV~sOC1uz3+^uThEI|_tdm5>&#m&G%7kBSy7yU#DRBpJNv-Wg z7fHo+JZmngJQj|LA@=r~gn!=hqd^``nIUAYv8sJn>prsED9FgYsTb ze$;B(*_3!{>lb39nF~4^1=ab35|(FT&_?Z6%M^SmEERaU!$rKc`hOiF<@w6tnq%f~ zJQ~d&QWrJrmg4GxiZevn?V{mN{JBTH^(Mv_L1Sa%fdSqn8y&dJ_*dOzg=$dAXu_-z zCZ`5zt#@BAp?0!Cw5Y1NJRu9dv|zkE7lDIXTbSQK2)h`(A;UFU5=wi>Ys1vG$}hfV zV%_V`D4VxM>7`0|>VMvQN{*C}w7}de)Y7aCa3Zgs&u}HC zQEb(U)z|?EaVlkoRu}YBhwD_gtQ(jH^Kz~L^}(2AZSFi+V7p8%By&H%c^%#Mu3I&9 zSrn9doJ36U^cV^xedENPBAM(v4khQMmVlq#=(ld+cQA3Ky+k0EH8 z@P_8;n5Jj-y(^uQ0jFA;P*TK!;=su};02*LAufA_5fQnCCw$m|yme-4xAP#f9&l&H z$h9urULVK{ND+2dqqjQL73tb|{0Ou;Dcs8WFvj^cF5;ucSQah!GFi9(tnQxb9nHv!*wz^3ObGw5#rEG z06%Wq;m6zPFr*}oO!t26{k;2ycaj*#NBJ(89EBz5r(f6Tui&@q6AG4~wFPxP&%E(5u zvoXD~{(mI*S41qDk zG+hEW!s*CC&_^(wfIIO*A(UoLxZ68~#=8yuQi97{J!RRwJ3W5a3eQ*DFV{T9H= z3x9IXi#CRI43@w(IJ(AnvMD@G!q7^tm}o>un>v(Lv5=`gTWMv=zkH>qetQPwQ~Vk6^Bn#v!h3o&uGFX`-$Rg zK2Gg3Eex=ypp`GV8$hOpFs<1q@XjlDsMeSfc! zv^>svR27u7A`L(U<<{JH2z#y}N;^r*orda>AwzR18Z$C*3cU^+%JaP2+yxpPz-qlm z{++C5t){ORAZAf!uxA(gpF&kcn!J8H}_JZUii^v<%l-mb;vl8FzQ2Tty3@*Aga8^tGFv3q#9r@#ES zxQL;H(qj?egJyD()KJgG#eY5LEUk22&kv~D-xbjX;xSyZOGC_O2R7rSh#E|7R5u-7 zx$Zq)XNp8}BHW?!c6+%@b>ax(ojuIKIB9dMO$m@hl6E&zL9kQ|dW+f9@^4UGi6icp zl&vE7e%}`I!Y_>bK2yFENSX}heJ3U3O}lG3ps?3!4DQ_K-&@2YZ+{q^SkW-P3vYw0 z?$#|fLBB122XAL`nl+hj-jbX~rOQ=N>Zd9oy83zqO-xmZ*IR{-qN2&Ei#TtC6Zx`r zgp(w3%!_=;+;fAyLf--RDl+y=mhB@%fx9)p<^~2Oi#&?-k`j_5g@Z6^YMl^#KIlj_ z1*4^>_m)Gtllsq56@T*2P}PrL_Cr*Ke1ocXzywktfkO}h?r`czP2mW&<0}k?Fam)I z7=u!ge)a

QR(`v_`(B4CU&zD?^;0 z5Xa@(L4K+m-rav0xI{D#+@oWf65m1)MwLGXiT$jGDI@NY~f0-vIp#GUe5tq%fJQ8($6S++fc;5}0oSLjEXn8J4^|^_!NJ=>TOQ0P#J8>sTA0ceH zjM9jCw}g<@3upi|>S<(lQiZ`|#tN6B3v;gdlS`fbX)t(zRyJ!o z(=jIbJ*g7!@NzRIi&cdCCCnb7KdBv?yx;1pqVJoc6-#H>*!}$m9*g&+&!}C(b`6rE zg-bSJCA?vKO^f3LMM>ZycC<4jTN*6dZc*Igea(W}OO}f-if68mF82 zk%@ooSHLAk(!yGIrMMRt_w8FYZ~YUQ&N@~NLVOM^?>0Wd8vxSP`6c>JG!cz_T8H%N z+ONnz<1B}P&+@cCq7>-Lljm-ET*^o)a7Nxgc8n}6Gwo*pqHy-h4LcOerwr8-1f7SD zQ*^brXWE`irKh;LB)FEVMO}Q8Ue2)l9kGAPUCR}>r~yb-F!_?F}mrA}6ah`2Fa;CFHYxFVK7u=GIjVv#h7-KyOtiHJ{@ z%IgJpph{S+C3q%xWT^EOW>>f?Y)?D8ozzjH2HcuQuU%`ZQ1K;5%%Bd0dt!-9f)RgM z`V#Uk(I`sKCEIo}|pnqZQ~s^nPqelmAHE7ua+8qFes+qf!?ioXdHh|4*_X zi}z#yCw{cw4lDV$i~TaX%M9(oYNc4ur_;Co1_a`r5%7`qAdufzOVN4vEq5 z$S9%UA+LjG2P8|u5AFgFkx&Xbl+Cf^CnWm;`q}{@_?ZtH;h!#bb*wM%oMhD0|W`XY)g8eDer8$J|I{cS$ zpDd=v`s8E5X%8`oGdExZXnjv|gJYU+$9=la#=9z`e&LoBs%l=EE_4p+qmf&8tojuW zy6!j#0X`FvjwjtePkQ+sP&6Rb7h)IvjG0$Q2PRd_c;HzDBjOAs$tRE+yZFO3LTqEjxc6yXohP12Ifb z({E$Z_!}xtX&eJlDZA?Z?!6P$0}HGqsrNGySoMY)YBQdYb-v|m3l{=EM`eOc^p&wP z)pEhA+u}j z%cnaVI5;+ckD+<_4MP)P7+asgC)T>&`qHNSjW?(F4kDT@?4W-?U}&yS*RAxM1Q>U$ zm+=JRQ<5yI;0^Z3CFSxY48pQ*>z966qs*|KGQ97%c&e7NDo1vKm@9heN}y?H-MsjQ zDV-)JeWPi(wwHfXj%YGuulLLI(I{`LqwmEi;p>&RV=nTy69KZ7?cTwS0vK#9UsKJ* z&9>RGm~aChbFo>yp9m=2UNWJ`3|DXJDkS?&k8;luRI5iDwD)bkaqJt=HR}CV^pj%I z-4n6T{3@eJpIEMmbCYZ2^a+2>JatE^Or4R_lVMW=L{fj$pGGf}=LaAa+7_u~OZkr; z`#U4Bf9!sc|4FC#7Z>|;r-=O4DWce+N=}gw2$C3v5C}xUBtoJTw&P9=g>i!V?hI_= z!}r|1AOd|VK3|d%$x+-v(qqna`U(5P9SsHHXBgNqhlD)(dgG6u-4BA` zA&#;;wIqN3Bm~IA;qFcf0S|GMA2`J?6`W7e2#pV6?A;53UtWeE1tci?nbEns*666+ z9GR4T^`j<*e^g+wqhb|7pZ*Q#xJLA&>5Uv|i$8OUta&)a82+zQ#D(xwAlc*U%BFJG zWQ7?Cj#ijF-#^p)r+2sc^!CNG0RP4z9-amGHx7UC@GQWQA^4{b@z^!+Zye&WYv7+b zM0HL+Vt?@y`0`hk7$$dy+%RY<*Gif;0*qKk^Wsh0Zrks-mo~a-Z?d2uWY;%)CXGZs zL4G4=K+vHXmdugq)z?i8Y_^9r&$#ZfSeMex05{e{uk1o8>+bSaeNLy7%uV_ednd{a zA`E}PwCLO2^9^W^9Z42RwYNMfcKer|1n@mCu{((?c!hg3$OR`9G!0j{G{!a28tUSk z8w#Ljt=nN%O;>c&OM*bRqh%p3Xp?z`BHWsI*EEy5dBcR&53rP%<-i?UZdtfa*Bc*@ ztAK)111zeVRmB;0&h(7kwQ>9Lhyy=m%{ZQyp^t%Q$`NR!}v=o2! z5ir0H_C0}rUW6YbjtS&I{~&(Q3FG)PL^(U6g%JIL0o_gKzT*D%VBUj=aZj-$FoBRG zxY=KyARp~5=~QSkR_ChwTMQCW8ZBgV~T(Ot*C;Y#b2yZ@@s4Ktum;1_g@UE^UE>y@~twcYyW22BR?;{KARl1>aWt%qs@ySo$C5{&PP3(#VR0z!A0We z^q2HBX!ZfzaL3R(iBHA|mWzn}ni!7PLxNoTy%5mPvH`|NHh}ra2JDdYwPk;rrY%HB zwreP}lht`=b9fYNUTT!tIBWKj0QjuG$m%KA_JU*2@p5V3w}C|-US8McwJ+O_xIggX zgbF4k(f850rm?^DqpEG8xU>rZEkt@wvV6rXPQ!^&1T`J;#t|IAS8tu`XH-u5WCi`z zZ}4Cm=sgPZZ`4h4YM+8r19*SJ{H2r5>+98mcp$AI;cf1zNG>F-is8#;WLG9PXKG%W z93>Efo+sHNtkE^nzQXPsFtIveUm$_Jh5gt&^K^q$*PlD9iJeSRlFidCa0zy+yQ+?M zxrupu5^%AV;(^Lfjsd(Syf&71no+ZDQ zD4?YR3@4}77~Y~umzRHR3qV;I!iWZ)yM3p~x=W_wERQoJDis`Di79>&o+Ig(z=O04 zASBbHJ#(9?IVUw$v_dATavH*>LLnY^GxFBVj>w3HDR>u$per1`EV5$@D;deV0|Ut6 zqPL;&<_Up`Gh9-};>NR#3!PQROugK^+0O!V)_NvR4jAEA899HKtAbfnEt{d80{wN5 znKUrUTqUcThAX8@-Ib9W;Yh;8K9Z&2{x^F!$qt%{YSk72y5I3@5VZKF*;xaq!{5*( z`o6dMH&MhtS?G^_-*2LaPtg)ZcfSWB;O+-u3L@}5jzEqfgd~dKD1?4DcsS&7k|WuL zeH0tB=rax{JsN+tb}SAihp(dWBfEy}0m1hhrio8a^6r92>Toi9(6ReIJo#|K@I$(B z_f*Jd=1xK#0}T)T>*V0YQ|S+U-|ps}j z*;bldhxYXmqFgZ6J z2&lO_&uaWQNvFSC!#aEc@M~uoz8pQ1z9OirDM#+bQ&4Sj~U5((laXH>>={ZlV~3fgpyF6hR;aNDu^t>~`~*P6k3a z4xxWA^8KU>`RVhCk4dM8hJSXX>m&3?@*iDCUxXcy4`~DYk$PH^9QO7YYn~jr|J^k0 zFWuvWBjfTBgg7!C;7@oQ`LOJnb^k}k&INxGE(TS=F{zU5=b ze}_nN#(HK8cPNhukaFYbQoYn0p(@>ux_3y7tUx&x!TjR;euMlc5{6rd5f{|Z7H)qx zddsWUnP_mw(2GoX7`tv=3(>-a^PRC5i-V*LSbEg$J^a++jVCmX8$YQ>jd1KZ^iX^6 zH?_A-p5Olf(}^YLl*c-Qh&-{p8goRHoC~ZLo%m}#ZLcM@$I?ErLeXyaz{EjH2xIux z-||MnqsBAY==CkpWs;>7tqY}@E0ljaz_BmH#^V`wqu1I^35p}K4H1o&#>+}QZEsrj z3gyD7zxamCU^7yQ(;)KG{o(7hY5-MIIT~)f7!Q^xUpn!!Fh8L?YuHy0p3O~Zag+Au z!qzNuC`K-EAvBn3Ty?Ba1=%yeYDs8?Hj6#mJfPrOCf35 zhJI2(f#=9@fwo@g^%AMGCBPR`+jh2s)MJXxST(#Nhrkp|?@{i54@BBp;LeU*3feyMzW*qXN+`5cN#%Vu4p@4113o@d=O6BjciE} zr#Se7OLH>vpDi$62dHzI001B_G5uGmw!sn{Wc;aw5-Y}dGYS1imX_7JEeH5pfP_3lHUeo>VJtO z*QtO#xR0)=x5#`n5frt zqUqJqvQ(E2Xb-CZa_fH!GSUtzCF4o2qSk^TE%?Iu(MMJ{;1v?t_ZY~8rvg1Cw9PcM zJewL=?hZb;UzI$GxhH8eW30r+1lK2#$C-S`E>ADQWFrbfEfk+2Fjl^k=Fuu&YngXB zkG)>d(tGj}EU-#?ueMOijU+R>iyh!)Sd@$H*-X1Sys+GCN&|mlR=;rk5a-ENReOu) zj9hM(csAc@8dzGzHiSV1x!hSdvKov_79>W2U^8a7}W0DAWkR0qO{3a$?ad!Ak1 zUT3&HU2(L&qY|WzOiOjHM_ndoK1XE{rdDM2N>MhHlmh4rQc7Zu&Q79m3DpH1zTQF6 z&`&m~pN;(;>fV2IW6(~>D$3aDsk*uNBjzvHn?8W81Po{0YNK$&TK)z;92$e@5My3$ zXST&FSeKUIY4LS7IFMo^wN~Cb#+|Bu>El9^pAH0^{U&)!ZYkPV>%mSA5%k`iym4M7 zg9)9K3raFmnYzxYgv&b=y)TuseDBn*R+XA`5-Nk=FC%Kuj6RUmVg@#}nuIAQd zVirc^Ls+~SnVCe}jf8{KUj}WguIilrAJd}$KTygk z_(*JJ$xnajew_S1fh0RJvB^i(BqR@@bj*H*k7`(!9cfr9`!ubS2N5`m4s>^np^bNV z_#@Z`e;VDPJo-$3I>gAxBSgnO^JQV;Gb;f( zU?&uw78^4<2w|_r`U75r)9}yz=iCF&( z^XPvA(qX`X=f1&t=ph{TRX6O%Yy7iI1pe$A|LhWh?_J~H7>;WKxL{de-rvV? z)?^J4Hqh)6xgIoJqa=i;<7lxF(#DlSxmgHlxC5NUqJsF|S+-`<1NsfAM%pZhH)%Fx z1{M{noGL6n1-Dichd{WzyY8wB4@t(8C$)dnS~i{y1n({zju0#hP>gvxMFiiM)GfoB z^OP;!9G zch{jboiak8C^uPQBy7-MqOVPgbrtu|yCL z>r!1N%3HY;iMt5j;*`*)N_8(S@bzr&x0rfA-;{j65;O3;oxzua^xFA_zi!4=e|HZ9 zl+rRO`E|K1aP%(9JBwCqaUU2X>F9rY zd0~7K_2c_E5K5>_n-J@5FQTf3-4j2*JkM*`mro!b7SEdGYZr~i`O2t9>P?~zrHTy4 z+x4_L$+I(0cmA7Z_+OwNaA3U`PMzoq!TUE)77{)YRp}F2y{glX6lDKf4hDWx5B?4? z{NO@*SRg0lCmb_h@VeR#@6dm;rgrMP0cOFzJ=nWWzdLGFB#p9I|Hi1(AcWBQP*8OQD5II5EBzx=$5Allas#!{a*Nz@g<6o*AFLG~r8z3jJ$$Nn>^D zp7>269#orEempn6+2U!39E-p4ZKCz{V)toLMuI1IVVs3vTA&mUrCFZKvFO{}4#ll7vV(QHMARV9`zo51=CX7Wp=$B?Trm@q|>N}K!G z!RG}Al^R_e09096j8NR}trCKp>ukbcKZ77jTbjx5b2X z4FfYw3o zL5?v71pI+r*+;GwJMdbB{YX-e%nkteg_^trwH*wG@K1jUc;G=iKFGltaZr!bkK$|+ z{@hna{-`XH5(gVOrVaoLXGfD(7#@6p^dm-ue5PBGADP?z3FHTt;^Y4LJh zb>TPK{0e`f*cxk+l~Dpu-U6>)1ny9PJRXZ}7VHm}uGXX$!+k~&{I}6c;TP8lFHY{d zn&331wSRXceqT&X-f=rF*NPs0!HKf#+NLXiRcHNMSn*4r*q>muUix%|okjetM@<9bo-b$~pFY~0!Z&07_l1$6D z*Y%O8wGT|P==iN2Ww?4F{oD_Gy1ZSt6Mtq!L43m)bJ8K*G?zl?%)BsH)OXw+e5q&b z6v=hCfe(pL5>Dr{ezIZY zdW~Sf)es3=B-{=$wH%VT9V|rR5G7kBaOhAXy!ec%$BbPEcDrdgg;^(OON|)3ZR)7m z071Q;=g!o_I2o!7Ya^pAa@x62pM+X(lbL_YZdaaA%6+3Mc&Trf`Mk+iFsLwsM0JJ( z`$|og<4rK|ea0!g58dU3Mwl8h=8LJ1AOa%&X-f2VhCFRzpye7qo%)JUC0*vN4fqcn z3P!RiRhWNW`E$?JH`q{8e38}0+qQ7N_g)cl+qLM>S8jLl66KSojwdKOQ^fvh#OHrX zUqSl4xo$!?GR!yrr8`;LD=_Pv*yIk3Z8Ig;bm8QQJsU1XKOK{&Trg^ZDLymgrCxDMh1<ZvE!Vop`it0`Yo zkhvD|^i=<`-f@{_7FmyK<>0P)9 z){RZYhOH)XdoUUVkOH)4!)d-L`Q#hB(hOZ|boEpJ5Jf?w9kEBy>B|5_c zL268lEmaz}(L#-VCzMN4899F!a9P!xd?FodArCDMckfBk=uD55?>k=cRdvgAN( z(4nt%jHZG=>=by1ThR9l!XIvC9DXSA@Mj8E_~G_{Xfrr*)PZ-rnSlq9^H?=LNbVImdNK(^g~gNk^^M!uiBr3 zheu&Kfe$6;@W_8^{wa~BI*2sIe~C1n^a>XD=`4x7xD%n3KBvmRBhq|9QNX`JiwBAV z{ta3@P!#YDj1mk`{p*><9W4H7X7SHJG4OBD;&GY4KR}DWxlG_k*ZGy_{{xzTI0$C= z%$f%voe~_f%(p`Z;SM&2WxB&)8fb`-aMtgx&GMM`SPWT2!bQ)S(t!k?u4=@M5onU_6zPV**?QwKd(iIH{IDcogt!`$9 z5gq)5-c^4F*tXZxD1`bU!;Wr9X6i14nDzB5MeoL-pUY8_7k#To2V_-)>y=gzD?wH) z5cT6*bO%f=cu~HNM{Y^UT64Gb;k_vGCHIS`UPtCLn6&jShM)_1VUhoJs^b?4*U64R^|WukBNR`u>bKQUoG_?JnMfq_8CQR0zyfcLMa%ga12oB0}s=~MWCNqg)w~CbL`VN zkbHlp*MQ+iY@hm=ZQ`Ib?vCIXs)&913*w^&1;{yl!d&0mWWKBL$+g0hug=L=? zOGT-VEd+B~Ih3JL{KKSrU;vOR_2DYJy$dKUMyglN3Vu$A22plvc>wgp|^taj7tyN%_$Z=1> zYQwB^TiXtjf_VhW&v}}^h01=z_qwHiZ^`c`Lp}L+2pDSz*eB#?+z*eFXUwS-k3tS-M6r_+IDUdbL7dNPX%)EcfQ>%9d%jr?Uh zXiZ@_{U=F>J^bCjHer{f-LDMMr`P1WPx{6d{;P$)+QUCz@!v(LXK6CkA%xXxgifpKnywTXbK&* zqK|~jVH~sMXj9p7+-??+&iL#g9qnfL$P|3~;Nd^#S0@Ki2U@>cJ)V}!QvZGrX7~*` zSqJQ24SzUd^VxL}v+zA54=(O{M25%r=pwxK?=RIFXXR(p!LhQPT!aGH4Nv`HxU}y6 zT^{{ARtI6jIY@LnC0(=K`}pP zY;W}O$Ic(@7ZxbGJ{sc&#J6$ugl>pbt9H^-P==doRrWdx=ZzcV_~xoiwh1E)y+KJ{`S5M!_aexP6iH<{KaE>@L+zom^R1@) zRXRVQjSUtx5mrEvufcuQreJU<2D}b^b<^wVO;hbsr7EJ>6%1jn5|I%~V2zoN7e8gg zQ9L)6%sW>TpjHd_#XM|pnapS4eYTy@6@R_ALEW06CUgvWb4!gCj`JGY+PywZig`PQ zEqFrBqTvQ$7Jk~EMl@S3{}{Y0%WAN(O0~GeJaob1<-MF0*bfP5XrPhOsJkjpi-SSk zYs60)3E&PvCeBqN+|uRffPM5Ef{E;gAoBZOC3KmTLa${DOJUq4F_k;Js%6!tZ-3Mh zNz*3)E#G>Ou$72u7$!B5d3Bq&$~}Z77Wu)A!RMIQgx%&3ZPrFld!X=Cp4Mu1bP=m>rFO;La`PsD z*}Cw_KzO%>DL>F^U@C@i=K{HAcz+ZM^4{c}u-Ygine}^}!UUESiE|FlW4eloJprE6 zZqNI04IYLKxoeJS)awvSh&@ko;nSN#lIZK?sqYCM0DpaOq3I0SAl6O#TC00}Ev^K1 z?Gr%KR>%FGuGDADIZvx{n=tlO@^X}DX&x`1cE_9({G_KL0_`Bi!Q$sFet(cAmcLNb zCCK2q`N`9e&7hfO%JB@8)1e93?_hq)Vc*;AM2Bzeyq3(|&pmK0yK+@khOBN+<++;z zqe6mvcG;4%J(aKS9d9PrG1-f~nJXsf?Aw;omlyb3#6a4a1f)Jgd;xhX7Uhov}Nrk=BIk_#KxOJsQHP?*NCsod8zW~m6ni{Gr4Zd)#e{aOMg5|1`U!xRzf|Q zkWe0{oJU_l^iporPgwB5OQI^UZB*>usYPX%C`u*yLgjU6v4uO` zjc7AWWqR@iVP1t2;VaD_tE57h8`Lo1888G9vd<1q#Fc=PQYxCEn~urJ=q`3tkM6W_ z*>evK3a1>!`;h4Ou138EeUGScu&@CNWeDjWcY84Z*JIG{qfQ;({RQy+8|3wumic4c z_1`7FMO{1SLcUwXh>uD|_-P?a$)g!8gAS32qp^)VVmso~>b8TXJ(!Dr&<%_qd=w%* zkk1iQMn}B2|Gd9wmmT{BLw}A?AL32?VY?hn&&jbZ>`#jrLi|Bp<*!lKz4|`t^8Y33 zs%Lrrin^FTMqQ@s{}*|Eoiuq&l{}^)+dQUL&C&F`0&4Zk!C9?}P!+yaH^$Uomkv0_ z{hayhiGgpze8tx(CU_q1$>o0J_2{?cRFf63x8bXAAt+@BXF@h z50p$!WmebLHdw$OEJN2zHzIUfqtN9cTNC!8a|)F&cp-V0BD583tX~dp%Q8by?mbvM zYZLrS&QDaw0#50prDET8kZtD?Ja0j1kC5Tq<-mnp?o>SC+DE9kIEOk`rdF_|*6ut< zL<`zPM-m`7pBdkWDt~)EMZ1rkcXK&_1!+8Posca-pBtJ;nAoH8l){drb{YE7gOU3{ zT^1h2dtk`4G~9jmg~J$S70$$CN|-rJ4ASV?@=Yogep$Db)8C!UCBs1xCR3i@lGo*Y zg^&j5<-*_?FF|k5INOQ`cvaf;nVD(?oysQf3_{0MOtgC}cYi&3Xu+9+;A~-9IX*p0 zF9Iq|dX3_!dS{_}+8Nd&Zf~=BD<^|X7V>PmUWFi9s-2x8l387I2N_&%14y!`R9RR+ z5sJ2Vf+?o29)D}D?rlkm`YCS6Suw-eybn(9_~5(bQ%{e%+iPT4+F=8W<*y;0S-?4n zTrk2eozvwk9)IRijiR8+lj?Put95}kjT0(?CvJNn9pY@qB|G5a;^s z9lTVm!R&5m69QETG}_9z79uIIZPQL2Fd=2#MLG$8hGN`LPx^T&{3rXaB@uw$5}J3n zuz=ppP1Do;Z%K4-gB#D?l9?JvzfZ&?^>A9OrT5{5torBEC}VT1xP_(*S&hoS&ZA`}XLS4SX1j(#)ZQ?uK#QTi!LCdf}I zazH4QIvTq6uNd{|B>O?0EBojprUy|2{fMlfpQ0j${Y0Wi=RW?K{dGtlr=QUe@lgmx z!k=L5M-6GoQH9)p&r3zexUS^G5Fw)jVjV?N@RRaSkKzOI86Sp$$A2U`PC$HW3j4|S z7w*t&-^9_t1|G?~6gwy|VfuIHNf>M{usOZ|bDV1BE$H}>{+=K!$0*;^5wP}1_iMA2 zZ0!&wYRon9G*Gp6SN=6czF_i!!hkO$w~gF@_W96eQ@5lgj4%4MKtfnANyO4Lv^nGQ0I;UHJHc6p1 zHh>uOW4H738OL1%QG!$CCYdxa#*1GZ(Kd4fBDY{Hp5Uz<6eulPVq^VBcCQrb@p?JH zDJ^35wVhjkO?k(W4mud67pIf;z9OT&Nps1Mp4Vi&LtbIJPc`^14e!;+{0EZFMBW1y z*q}FA%S-l3w#frtRi%X3#i1`T6m|NUZmPN0kY-e*HXVmtdpd#e_NeJ}dfh+{0wVXp zpJNnUOFK?jHS+BJeQ6M$wmewXK-LS+Ipn0&q>s^mBbsC@DYN^0-O86y*Sc8(Hh5+R zbkq|jeSn@Kh24X(;uSQz?jjIk*fOYi&w5Dm-3AGm`}Tef{hdt~8Nr-^y#jAP!>VZstYZRxNd9%cvB<9c$_|lYZup z#BAPwSld6#_KYI9c`CSe$o!JHYDQqD)+Whz1)l0xSGsEqzEn;30|iLL&As~>djnC` z6RzMbORW4YJ|Fl-S+)@>H;pN|hfTby^o-SsM+{e-A=a16pjZ(FHRUpDYqbJ@-#oR!vs26v98$c2hFIe33%j+e)V%oxOd`E+-Mw~ZsjyI5M*yqB6y#Bah8c<%`A+>ezn<-sCEDL=P zas5^Xz%hbZyUonw{p!Wn$#})BtCqUf`F}7^f`(r;cZK_UB2Cc`d=u>y6-r&5Y~H$m zD%H2Thj8q{>KBI=s`s_TP7b7~Q!|SI{wVR*pNvLJ*<7Ov)?n?y*gp~@!H`wzq*o^E zu6h|0<&6ncbo0T}c&&(8JuT#Go`9?QRte=9j(DHv#W?At&fnZrX$m|}qH2dwP|ixa z0iu{gI#4?c5J-b;MLgWoTu=zm(a~dn4rAYQ6_<#+L=Ld&^z5d`_5eYlA>bEeklX!C zq@!coqUhi3ko40St*dew9RxVdzH#c@AgBaUNqV>~wmyFn?{;WR3eBswZC$_G8rP>` z2r}67`GW1}&5_`Dk>r_CaCkdumgS`#V^LzB-$41<*lo`kGJGJ-^iQd8I;GGNA>0kSe!}n~W*<1oO z+vZc3cjKVMd3eXhI6l)=2LM2&@u>2(Me%{?=CwrXcRJ3`0D@9+IGREHCh`ao?}mxJOk$ZB1Wl2#PM{pBMACCFEQsgH^FWdxTp zWsVvurBpXldg`*pVPP~FI^h<<03_HwT|Sc@#;9QNf}PD*)IATnG}=mYA&p3SspM?9 z2eu$`i8%fXV0E3ss)#mZ6OC>E53$v+UHfNv^^@!V9$~>Wxq(}P!cZDT37Yy5!a~V+ zO$*=KcIkV(fPQOZ?{l$#;oeV#-%j&UywAw~q^7l2Xg4^#Y3WV4vGHCeC;>Y&^t{C1cZQDT@ z+UsT%@vdM6Z?DzpKjeFegT{BBS&Y3~kkmewf&8tytLX3Z6AiyW_) zy=@m{G8dHZqH8OEA?Hp=A70}nLV|4zlUBfBLx>o8;#klLLX9syASmX{DhkA{{Y4;e zlsq=cEw2wtaLLJqJ70C2(_t1rM59{WfG{48YkPnlkmD%`Je~tr?xV?;75%A*vFA)T zO~Sjr$sm==+Sg^uE!Hd*D7V^SE#22*dsrLFNADD zI^yP7F<%&$Ucg z&Dh25m2}{ghB6*-KvYyZ9*NeAAg}|A|3jn&{A>URLyuWA7L7hOVdRT_b-MNoaWzCm z{SIk=0l!P&Zo83?5~$uSf-hjb1;_Nkx>T_4XZPZ0%WLPK8qb*tnTc%g;nz|NT$w8TaW#SFT_XKvN@l-%%pPF*pm=P4 zOdkn|UWWE^IZf>IDMn$Uy3`H5h+|EF4RNC3L|A*HoPt+RiINCwqPaLgomV=0>ejk{ zrmF%zrB^W%6wYP*T6m`0mpBgZK_?%bC{JEbU43eXh$YH7BTP|w{C)GXGPwpOlr?7Ma#x0?ocwP?5k`Etb zu06w!bxx}DJRQj(fd)8to>22jpQn~H#U~}9n0Zf0xOJzeoil(G=Z-; z9*XWmuO}UKDmq9Z#_k-nKL_JTwFf3SM8Ax*gl7C;u)k5xPpD1*^`Vdd<=p>g z7rXrLeJb^qB){#7m&wN;{CAU#V3lM+^+$Y?BkiCGoEeK0? z@VUXj4XncN*|u#>`|#~9lKgk5P`K`>aQ#Z~7jD%>RsN*cIlKw|^B)GcfStP}mW=i3 z*~(k?6n{XfK^CgXTe0VMv-(p!_y}v2fBPbW>EICXK|jJL-__?(vbSx18RNY@>Z<#o zEc$t&%H^eUV^)=Ca9Q|&{UN}Yr|i>Rb%@H@mhM7<}(}F(A zfXuG4ydQ+$$I3syuphlI;Gev(AH6T&pS-Xiy)WROys#g=FW|3#UfAxI_IGA!z=vBJ zN91RJMQ}_F4vJ5h4EsRCPVEa@H~JG&ix=m3zJhbWB_aLtbWeHQQg47k6EG|+ibnsU z&Zo7=Ks0+cdeCwVBUs6xrcK>bH+zku7RhF=P3WK=E^h6pu7WoOqcl%U~tZVKXT z@6IbjSl$eZysuV&BV33yIlu;OljK53;dc8UvM!mSF;ELrbCfIuD1pn~hYFxe`U`7_^x@5jQrsPGAhCFeAW$iO~Yp^T(=_EdK-MgxB4mX`Qb zTnzz|m{d`EshKaT;7O0ZE^xnaRihWK25nqHpfvCOa#d&(<<#y5b|R&p?GtH9c;Kn8 zwe20HV2(k5?>N=O=J4Tpu7uJrW??jPWNCfCxTh}yjLXGhL|t)jBY1=BG5|X-M+(NU zS#FAQlnS)h^KcHV0MTwIcj)MzhX+JLW&ln#WJ`_6g3pS^S`zWBUF((k0R*HI7yO<|zeqjdCFw?#9+nfS_xsZFY7(yMR9J(H6=@P7i%N^C` zSf&&yRGEzT9!(zG!JH?)8Zh-L)yFMUzT6{9F+o_+d)Bs?xTM%nI<@Ww-SNi>rk|Gt zd&nU+iu6BerTt<|6*&0c2YVR#p9LcS-!1MRB9U!j-$D@_#<4fQhk|JoA}|_;F&HLb zbT3+e{je)YygeA=H`SZk4cYfj;F~&*hI>%o!aq&DNj&j?!sy5HL(nb|v;h$e+Cc@q zK?Qs-Cc()5!_M%5_fl0#?#)Fi*hl4e=Hm7!@+as7LiWc&J05!1&9I$Gj^Vq4IUel| zLxSAl6!~V76L0g=nA|Ce+aGNoBz#Mb!*4Es6ZLke-_A_%oz%FkFa2AeQ|_=+72B^e zl^UZ2=j3*Om#Qp{GY;mTiRAO^Bj^Hu6?K0l=mLKgb^ki(3hN$p{}|eT1*N>Ui$8;I z2mDpk{b|s()aNG)2~bV>dEo_EEv=VUwc9}z{XDjzl>OL}h13r`A-qLocE-({Wdw_V zVe?T&JAZgWOzJILPT8lfIc@rmmBkxQIoDrb?iAJ=xHu!v%16ZE?CxV?@Jlr}@boE& z{$g5hy=QNgrGov_L-vmY?CP2Fmh#3@K1X#$_>P`!CsndUPvP;tv#g$L!0{g*B5wbtCt3JN|8bv)W^WU_1X%NycIszxaJm{{;Z#SAEV(p2uFT-1?bQ!qZ;&L~WbAUlpQD0qr zk@V-|5zXhPWI_5xj+2{K1UDsy!X$K#Gc&v77=tQ!Cqb}l>c=844&JyxZbs7R4lf7jqXN z&Wk44ceJ2+PjdWZ`~IW0@xQ&vS8d~OZt$I59Yo?dj!-|gm%#QC{}u+e4HtPA{mFNe z0EOQ6(%9P~I^1(l3f>O>FaRWPI?~>^2)~Si1aCIf9#D|C*EO-nlpuQReNb<9e^R=i zMxj3&3yI!xac{2(>>ZzWuQ_}-&D)j-VPEWib_1Zd5#F9szrC)vloXEM+9%1biwwOv zSlgQRSzP>`KJWafzinESdjLScs)-1a(5pZ6<>guD58VJBFiT-kIqY)~x6zUO5!OOx z)Z2FK;2T~RhrilUfe(p|ucmN3f6qL5|^7k?fs|GdP%TOsgwOZ>YP0{aqwT@{#jU1!z=o=RD}u~`d3fk7vSnwu`7ff9FU zaI->uZd-|KImRLmCp)l^i|8Qfye#1|aivdtYOhj7-_fYeJ&6;;aDNq)jz_uM`>czlt{wq2=|{X*sW=v-Xl)ZhT%%(-pORpv-a@(~0HyZ|#Yy`We;d(BE8$5&!g*%LY&lZW#C{4SM(E4nXyLPxcudW?|K%tb(v4}{O!rp>MTW!0uHHi{= zVep0(d1p+tlm#zj5#fxn6oy>g=~k(4r!1(o3@{r{ss)112q<>sw#wu4(KoQM9Kv)Q z!aT)VK{l*Md}R*Je~F8Ej(ip+9&{T{I1Z@|T$SrsQEH-HTkN1`7mQ+K1-lw{-JixT zx2$zb{OgF$8XAJGb3SHvHo1IQW-~6p`3ywP_Lny2@Wm2NBr2!=OT<9j6U$HkK15wM z^pd{Q*qbUyJmX}nS%L*hD;jeK#;`-$;Rdo@yQSk-^8EUBe`^W$kN!>=h;6@&Qs+pA z7`wADFG0t8t9e-eqzL!5(E%`=D^2y>=hU2JW$j#3R(K$j5G~iFxsBJUV8QuVtS>xS zB>eS)(fdSO1p>{3TUv_!=q`x{MqbPMSZ;90tA(ZUuNohWK6Sn5dLTd3 zbVAq;gR>E|f363!+kRz0d3lXi&8-h6?96F~f@eb$pcP=8)z#zcsGA|W9(6J2Yx@#= z=L?}Xhiuz-SQ2A5NCXJCtYtuOwh)hbSS=*hJ_YLay?@}1RMRYn43dEF5@donatEz& zyqDtoR-GTQ6WFc56+dRL3<{|i6Z9cfxW;VGt0kI=e{_?YgWtTK!ky|ZU8sgkPFm@RfGbF{g`&$f@XBQH*e3?cZcmSy7#xb?MyQ7_#Z1{~=Ht!8ctnD@`EtSx z>sY;nfBdWgc)iAFIbW|l$FdKhAgX#q^7|wYinam$BPIn@v}&pB7-c4uaLX^=)i>pv zAjJClkpSR~JD1=nzhEMf977Vc*1d<3m?`VI_D?iUoIQ3KkkcWS6Ngh4Ix^jBzUmsS ztkl5=7^Y>or(`3QFEUuBG)St$ZvE_Jmv8A4O13#ZFvL>Afzk)GiTg%Zy z53>*8O*li`g}e|IKF}7YM98Vdz3Z)X8}oi<;s`pv4&FeZ!}RO$YllWnTNlGFi1C%n z^v&TdSBD@7`3*x+nx<$7{Ui4JS9kadynb-?cMXCc3jbnXJb$Tpm-$7gJtIb`w-oR@ zf05nta^fwt3+<+cKLlR%8_$H{?zR=+yV^zo?Ya7vaPRnsd@FgtJBJ)acKm~4Z$3J; zJ@6;M3kmiy-koz5?RVL`1LW=w9KQ2uVp|Ng1Gn8BIC|d>f8(ui$8;pMr|DbPkEeU? zzQIT2&332Wx*R(-{ug|`_PzkxeF86*fB7}exnz}s38<{_IfJ2mQ5Bm)1b##>!Btu7 zQ}5#PW`q|Eq`p-AVrKXTm7YhF34yOhf?uFdSkq(Rs(S+cbuQy~&iR&cn+&d+(eom{ zQ`{Huhl79OoEw$=jp|x!a`*2Z^aR8gV}IuL{M$TH&NN z2JLwwZ8@iD4eWj|9qiRiugUP8Q(6J%BJqgFrH%1Xp)NF(acHly2N;PGrjg|4?v=}} zZDLd|Yw_CH%nE{4JkiZz84kH_e*=zhDbIUM1xA5CmMgwC!Q(~6^C)5>IFYQ?pJ263 z2l7_c7f@5g_PqU)`!ITx4|L{5z*L-mOj;Iem&rfU_Yg$NlYcp{ihQ|w5Ja)y;0V^F zDV<=Q(Pp@}=5%JReVNCDau2s%>Uwgzqwn9juCtI@W0WyJ601xdNoDXGf11A`8wTxE zh<+MpXIzf=S8?G$GPq>o`4$0O$S4@XZD2943l$D2HxjY4{R#(>Hnv!CTa)@_S_+uh zS{k%nyEaFs&IDouZ+F5dfMsxNS^%YkPX(oSI!RuyIF?Ef474t(p$dyOhn)xB-RpU6 zv{@*)GdXZvqHR0xa5@3Ye-jDt%>wx3Nl+J%2J zz2}uz+0gKnSD1Afc9Vb_tTHI4$Gd(tJtefSejmp;Lu<&)Shy8y9LJ_0+2t$x}Tnm{9va7J_+h+30p{U+BT%@aDnw^>U(v) zs6jBbhl6qM?TVr;f0fLLdsd$Y8n+w5IG*kx04b7j-zM(t6(SO8;EVKC z5i8{>@R+89(>8Z$7V?u=e}>dF>BG4XodpmH?^bF?kz5{5Ff9sn=lLsRE!R6@jX14r zzfk%FO$c~5FNgg8l4|6xkH`3>mNNYGZ$Ji7aCKI1wu@HSfBoF!r`6;lR&|!7e<8&95y#bJhvx&)7E2C3{-0$ol;=())5Ynpfm4U~O~z13$6O%JaHHik1%a+Q@lYW(vPK@-0!4^?UPZ_5(?M{@DhjK28?fsfj;oSwa)H{qQHRum5c~{e)?M zbHnct8%~l0g>QfuCUA$@EsJ<(2lZjc*9gb#C1@*m$NYF?UPFFe=MzCk}-G->r#7%V*`xao#^CU_=@-H zT=1@XB|n=2Cf<^~8+c2oy$!NYD3f~^C3-8e5%@lpyswb>4+8Hkpyb^M!h-#r^j*@! zlegU~{O-)a@8MtatwOXNB>oQ9@#79h9>~`z;J6nut1*|{i=_d~N@)(c<%jbh?D)qi ze_;N`|891*VZEabRi)HCe(5jsG z+4x95FZg=H+lTKp@U8K+Ui?mj*WNUE;i>I1ysy)T_qF+XOxTWzfhs{y;CmXpCacDm ziu$|H5xX~At8R#mt2cR(na}=4b={6zf5wfKfDpAOU;6AM>_5|MgxL3Q8Y0^>>CX$k z-tf~08~B~Y6?0!G^6XD3^7@-1&%P=0TQEh~1O<*ldsjA;Iz)YOoJaa{Ie2s^#eYk=-f7G6D zcpP+BUnY+*$wyGmj)z1{VYavzsC>QUNj|y&EW$cSJ{p9(_(v)OF`5KJcti(hoF=up z(}$y?Ti!)+kNR}GQmZGX<{Zx`c@TP6y8{y$b7kEi@X?FY2hvPpqF7G6!t|}3PPU~V zRi2)Dhyby6+b_Z9riMfB(HW~Be@za*0yJ$YVusNET}9JE`k5pG!1#i&bYSKd1*i^sBz#A#291wQ6#f0>^Yi?#;~ zta`wbwe}=EeW2oSX6l!hlgdlc!amD^$S&M8z)(@44mg+uSc4*wU-+!@;NxRaVo;S| zn~Q4tW_ECo!kBv(3(ZovQ;z3F#)0g1r~0Sk$tHhLP7G6O$9x4J$$CXGLGZ}7$+^1` zL$=;0mK1CLC^aC6`pemAe_O1-0RC)UbqZ+|I3_*F@45oNAy;$69As2{7Q3DMTqe4* zNLIMRLuM4F;^-$yGM^^>cuaxdDpqEMQ*2C|eo$A`S#sGUV;kAUgEa-T&$rAu!ncrq zIH&q-A=-3O9V()@GY27Z1ZWYg28L}(56(lUA#te(`lP1I)zTi#f9c^toKB+8k*OLC z?!DvDY$T#!)qkM);xnRbeDs1iW*>u8`k-u=;5Ydd23yp6RYmklnqoh6`)}sI|0wnH zFRuTp@$&t(-|36uB!r<5ijf2fQv?lT2uva*iDDQ|ktjuw7>bf4j#CItAoLFhB4PN= zf`NBV%5E?8b_v=|e=Ff#f{#qz#F^x+qnB)9@@E~V-O4i9DJf|BMb-s*>(7Vr9^kgf zo1%Nj+k)a2`luzhzI>krnEmau#?UeKyXXk0z#F~^9I-P}jv?KKVbF$9iA z0KS7iLNv~0QJwS~_S}=5PvI3F)&kw~PgcR+Oo+DL!K3^V|MnPX-WNc7=`Z!gz60Rr z!Ovr=DEy((f6uDlge`?<=`#@3V)tHwP!V1&?9rCksWC}yPg~4Gx8<7WyD;r|TFgGX zPPFOVMd@bC8DQP%tNku~{Mzu}m)Spb=5f6fW)0BK?!`+IXYFq}k}bt>?cfCUm>65m zFBEC>VX3V|&#s=O!c|$~px#L*G=KuECa2K^(CbZye{)UYPYktyW&pLAb}##A2#?@J zBl)R-)9ifbW~+;(?9?S-7HUk04plk*o;Y!>c zS%Glxg3WOlHWmKDuQPlw9a=jd4l?ib1c0Uj9Tr^GvI=Cn9R3>P^@7#r1LK4v7oVbg z4TG=Ae{P1Ox-!RsU&%JKRl0gZe2NiZRK-q9DVAI$}XU+md`@C4ajm#nhs>#3j&8PhJY9$jaAHbxeG ze+Z0uSZnSIwD%S3BQU=+pw?&o(RC-(($1Eb_O=+$ZiB^!eVHokFrV^(sboGS%K=k0 z+03u9v;r}N^A9gi^E%0|NdUQ$gj~n@Fs`N8X2~>0y;9!V8;PgmQgZk8_8<1(XWfFfnr|jw59+Rx5 zcqL=|o0&v;(^hR(B*Qxz?J3=tOMh{A;(zct- zQj);7=!wG!P80Nxhw(mq^0ufK)BEJy_McnAhM>Fc@}7NRy8#QF?0MG~?b07pe+BkP z^;Y0OlRaMTh4*M@jBa^fknV%}TQ;}F%`LG+-a=;k`O!Y@K_fr&4S2f*r0@B>wk1Cd^ z%$DpjknnlS_?p16UwbeF_Gox|Z6WJ(O7Ej$4~I9F|H}z4^Fw1B_>x4E@1odCJ%i~KeB9N+IFcA)Ho-fHYKh8N#8&@FjA^&gy8`JZ@2(+9W2@X=uaUb@A3 zJ~_S=fpXaa>&ZG-vM`0nVG5$O!c%f+xr}pjyX%^Gd8~;Hvxjjpt=?He&6yOD1um!AIJ`u# zJg_Mi3LuYR&duRnwuQVy(AI)7bP&xOJ_dzGj~`XdnxgS2dUW4-e`qBD>3u9uaxI-p z9aOC6tysHexhRGr*Z3mN_%Uvp6M=$trnpPw>-WdNozKW)G7X>W4+3zT!4&K-DM8l> zcFIap@%#AcbqKYNm*;xV>8BLInD5oOXdiBRc2`J!3>Poq+4cq3KntUgbRp!`gIwcQ z`)XrxYJxpZL*6q}e*k-T8`Pe5AS1;I=E=k?l7$i&brv9Zg^&Umo}|uJeM~>DR~vPF zI_)H>jsyn7e5vfFA00{M})N9 z8~v)zoMo>kY)S+YL$+UFUc3|=R0BLJZpE|Xs;1{>k+}guoL!uIaK21KeJHM{vFF(N zE;Em7xqSp?deSF}o}5dZqU-D2=s7&AY|dsArotnPHvoE1huSKi4@I!S4pF@p!)=Sg z#lC)eI0}y6e^Xlj)PDf}+<>?tt*ztCaLKM1q0HCbIg{{zFcpTk z*W}va0sJtuC^L+aZ>4Qho)mNNua6imj(0N!IJ6I4hx#n5A;#UY$zfl;O7qve z=1<5xF=rfCJ=wsnH}MY7BYS*iSDdQgC`4$$)i5Z3;q1VW$P{}ZXIvbS1Cu(3gUJpr zn%ONb%4+VUKB$}8Mpcb;l%o2D7scyR199n`6(xSO*E>nyu5oU#(CRb1{Wvx~`8dL? z;tIEOf7#w^E4(Dz_irN3ff=aSs6Or{2sq_SIy$B|ZX5ced=i})osk2aOT+wpH5%#> zw_^xBjf)oET`Eb(R_JiqmJ>TqE?^k~OnYh;vk4c}IA2XKIoxWqkn*q-bYD)nhS>JI z^QADgUPp(aTcp(|>cUFvN5?exp#!eqRMs>8e^Q$x*9`uOd5`u49`8J93Z`P`cd&2; zChAnqc}!9MoGx_x;@|_Fum>JfS|B6?B9t{grV!fIV)!^pKn>}ucjO5M|XWHkssnXC!BH^e>i9F{2I6K zf1XD(*+i0-f>!{)V4#2;CxmXtJmt0ifvgf!i3_geQJzu;8D!l0dOkIr z5171jU-J^zSMtSp!(#{wfbSiAE^gOfhLgvns*~^Df5097 z=BMt;D9K*RL4tjEMY%YDfn_n&tSTtF62RfO1iRBP?d=Gaix zV}oXIv>B}*2=x5DUEXtxI)|^me}Wp6SE2N*!VSW0@U--HX%c7qc^3la*bNG4mFJ$y zV5dGb8nnSW_}wLGJ}h8>_zP@PP3z0dvGs+7x`A3#e$O0hyDeR*E?2&ntYP1PEdaKCw>5 z$j#i@E4z#1mc6fz!-2Rmf4ZN*5P;ndO{!3hb{-z7KOwKBk?~knKsm2`S69%Z8o4UW z493eE+nZ{N{56n?)(J@N1Q8t2mToLw^%NveDC|XZSL5`FOPl8~)cE8c{3R|C!O~Fk z;rnLgB@e}qN+ilfLYBkQ259a@Auf9}(E^*zr7v*DqroPI^^Ya zJr$Zu!){i!Jk72h1JSr$A$2i@3U`|semb7{sH%5+DK{DWu_OQwc zJ#x52l}9YSJh;(U9Xnogo>elW77sj}dl6!+&qFSj6=e5?ml`sfOGOOc1M`6I!q(l9oneSmk)vg5;#o0t_+WVT})n4fuF^A0nrpk+vkX zn}yx=)*Fm7HuD}4_E!9?ReYZFStK2yQ4+3#J-3MH@}r_)BF>Y>qk$?Ns2~*OD?eUNcDLngyo8h| z`qoDVf8HI2ffP?kNibv+91MTDdnSD3N*Uxr6@IR|-Nh*ozFJ{cVXV-n3%?%9?tUnw zr%a1k&hVfpnOf2%OUZJxJ)UTcE2*9zZ?i%qvn<;x20WsLM2-=vDyJ*rfChEvM%``Q zXY4DQSEG7tZ!nj(O;1xEu9_`;H{Y*PaFR*Ce{7BlkdTFh^vbn1u~=B3n~;!J2l5Zm z^*H>(r(MA$4kC%Zz&-A#NbBwE&B>AD25Md3Q6ONh>FxnqgFZoPA9{Jy6V(3*l>M~) z`#%k5|97wB-$2?wtl@8AEd}pAybUqJoFxr9VhLH(s$D3iWqg>)=uon9uK;v)A>s=pt zXSCtLuC21+a2Vf>wB?vr$&DsTe6^i_cDRshk4?gs=v86dmZ#B zEIu1c8^~cSV-_zW55LmcHnp)z{Z3`_6ON`?%i9vK}Jde|-nu zf6l{tCnei2-w{_2$+DY+zqT7gK>RN0;;)^Etgj!_LAzzyPK(z5f|&f~C7+ZG(3AX} zZAbx|v!~$Kk}qJV)9n!JH%jSC`x>8|)pCr!bmsbsayG@-f2e?f;E0pG>7 zY~lzPeOJy!YAAG_Pz5~0>dF{vsxQ(@%Q>84{JPre&5%Au9No7#YBMH%lZ?9n>hxBS z_`1hReLFq=sJHr$ul}mI`puQ!%~g^JMG-VY5d=-r5JnOZfe|ExU?>h@FhN5E3?o0> z$DwH72h+E&V*FuBi|)mPefJ{|Y1b~i$FzACI*i&iqwZV;sL8;1K(u=@U>Q?l0|D6BqIF8Yix`yK{ufnox- z)HAaXyNum;r1);5e>2e29J|a@G#T?VdhkMJTKDL4n9~E)f5MYd(Drn^LL#5OY8>nB zHH(0pB%_h0u)F-6t{2~Jk0lyMN&(Jx7tS7Iu4RbUg%k=mbL_puhQQTz3JP0Qyp6VOA>f5I28@^z+=#SJ^4wM$q4 zgM+4l$5d@)rFF=#{!S?&rcRJmxuwiP_AsIGquju{1DKR@ z5v=j>TILocZS*|f)&%M^la(v}$Z5=4XPB+tN%rcKc?}9@O)2@qY0C=?v|En=i<^*# z9*6UEnjO4ge=)C$v|}~I6Gh&o6OND5y)LNw88bSjlL=yQ7jd3Ynkdod!Q!?X6jv=P zZ2TajRR$rkPm+A2JdgfFF<^CK(FU{OC?TuIVGv9 zG(u)$P68b)H?z6raxG(KW<&XqKy7qGRZ*B<5;3v5fIj&R!U~znE zy?&gA4K;{QdBkM0R(#r%yP{od?se|yY|+EERe3!)I&3P0OCK&kcU+|l6tp+4lhI=k z#66V;f1O239@t;5+8rITp4ZzJ1k(`9Z4Tzn`Uyt!E#P=K%E>@)ku~BC#B+oi%OSy8 zGGP_cuD>F}_2bt6q`CB!wP4_SGIj=R`%i1Qyqq1#)yF*c{ADu?RDY0b|SCy z=c6ap_w2OZPXCL(k`dJl{M8!aHW}#8q_i zRMh#Z>0cA;6JdW6lY`WF2O+zLcfyx+0A-Uc5gSEH3T&u(&db!2khaL#WUL4|l zf1c6jIX#-?#LeYVmK*JLACFw7=s0jOn3s&5)a&UW4VB{^L+p{aOHt!w5xhqC(w-J` zOPilqbLO&G3om(G4$b`P=Hote5KmUj=|Eydu7J}&6#EFP)@co-B$ zp5`$or-SxPaK?d_I58@X(w3M5O6@9Ce~*`4hgOH3tRNGL$>i_H*YG?(M8#If4m%L& zO@%cYH()J{oqUL5E19ViyA~*mp-pLCbbP&}2bhZz=PALVZV$LWrQ2()Htc2< z5C~UueppH_zhd`Jxtx&h*#Vf5bwiNzo;{mKdLc_UT+d0N#WCfo$UOnV;P&_Anz@F7xgARS zP>JutXbZ)2b?uf|SZwJ{aDI3v;+{|NLG z=(H!}@8Q}F*=;BbdJh3_IF2CqtTuQviMM=qpISn8whHv_`w;Lx0=2V~$(>lUA;Iu{ zlUiATr%&lb+%8uX$ro|e|`Zj%cAR+npt=81ULoz%}MWR+U2q*n&o{={cI+6(P%8-3GNQE8vlL+2=P&$+^9MZ{d&}3M<9Q~&3c{zMBFTgp9(Rj7{aMW4roSA9;R9dJp zWVV@Rm3c^#)1Wgsqk5;yNfh|_Y42>O=8L1Q`BMZ&mUjbTOBw~9z|qJ}ChuG#c6in5 zz#1ob_HpU;Li@XJe{stxSmW)NBb+?)K6g>N9DD#Ju~M_FgsEPKF(|_N<_7Mp7R#%F zaju;p%1fWp+C7bD$LO|lrqALMWYDRC>qjhefSlgFaS37bQO%t)s#a27Ew&V6D#N+k z^K>s2zdH}Eh}MfUxOGbzzHdcv1``j0x6VKv&iB`imuje$e=ecjf}BE-m7^*U*-_-N z1kZtAk2ZH`M2%Aq$7B6?rfFl2m%55Pkpz}IeylndiCd>sWblzm1ZxrY=#sg7h|ajy zdDAUDVAY_gEO`lw?YBZahX^g;1$!hnKvkp@Mn3J1OP$*R(R*(uywK?b8y=c?qZ zdPPYLC9m1de{ki_c(q3$IAU5OOFj_5zpaCf(KO8@7K{m8RUst{HTEv1eK6)`+xFqE zXK{TP+ej}T-WkG!h=h7db96Ns0jrZwxO9*VtWAkEYg|vw`o%njVh|Ki2!A4=%u|=l z`*XcJg}7fRBLzrO zepR{Pja0RviZX8rGdkoY4v~vlzbZmI_oklCe}vk$-MCH?ht&M#Oln1eog)R&fYakV z9cPPGb_?rA5{47kO2$IS-k=`u+{hf#*l$R9x-lAaD4c_L5@Ei{T852bysUxL$D4?{ z1j@XHTtXnk3kA)hd@1}QU|S;FK7*RK69%AM{Gw7Y^+en>OK-D?Yyi9W)TmyQzEYc&DQe+fXC;mf^bX~ z937WSi4-NeeFu8SF>O?&*RLCwWh$kcerLP6?9FHrI}LWIf1X9`5vg+Oelg<9wk<8~9WXjU?&&ZvjM{-k zHFhuqr&Jy_4u^9|SyKOiRqug?9IS5QA>O+pb>3H8^@nr5t4d)gvKOQ%8YT!Ff2VMQ zBB`C^1S2R+A}9pm7>-gXv29V<4>jJ=_h3u;#$ zUI3QvVy@I1TI~ug;a-E0YFY!oAC}eU|M5 zehl>xe@|)pkRYi)0hYv0Bd`M{<)$rJqA5{*VFg+aQhj+5bYMjrF=lIdG+ICQ42_3i(n?!CI)RJU!> zcYeiu*WE|tuv)thfQSMie=_2Y97Ga9Ab$M;+2v(>miP2rYn^@XadW9vf%Fk1jnPNy zoq4uMXsVgWuf7UU8ZJp>bimgX8jS`u-C{<@1dGcozWMn5*h+AhIA>=vcrFA=6%QQa?XwS|*`2}&&UJAjLL-kXW#O#kr$ZmbkKqB5 z9eF<$kOEK$A9;0i#5r9FYKv*1yExFpR<0&MK6 zvTRw_tap`g3quOgN+nzFZ9Isro@L>OoQOVWEO`}55L1@pf3Y5(;26X@G}{AkIbhmow>9}VDm^w&@mul#T z{B-u@q7ACpf6Geye#TK)MeTWH9I_4JMZTP3*w1IBY4teq5`jL2_wEJs56?)$R&QE= z5YPwaTGuV^HTCCH!2VT-0{^B%fq%oHz@Io25++HE!VwIENQgwx&Aos)Mp7^af}6Y9 zen(*B(};a{6WCsDj*>mF-a_gv!rlehz`c5bMgJh8e|@|LemfofbBBTjdqAC}dzCpR zzP4jx?*aw!-bIEx(d%Bpz;^DgDBY6)Xt=qBUpN#fe5>2R@1k|IJ1P`>*Dv6Gl`VkZ z{9XF4es2zJa~wFld%Z2BCz1U^B6KgI?|k6Y?sup+H`x}<2k73Z8UFPo(A%NBesm~c zcZ2ede>|TKu8>^w?VCQGFMqGmv?e zQ75nS3m!Au&`8S#g`+}CWeob9(2H_5L$Jy`C20#s6(P*^>&d0YGp?5CT?~D|1&^hr zWy0l-s2irFPBPu!M}3R4+2H~jSbh`O-f0n(e@4_M@Kw7BA36pj%!Svf%F6&KKG)`U zp_fB*P9IoQ*^pG1hwb{hv5-CgqU5G<*YrW51}3cGL`ff@rsG#ewr)@A43N!qxae-j zl~zf@26!uGisq`|d_`ZzhW-)PZs>+1;CqjVRDYpfymRNsD{;nI)Tep?wmoY)GHHGQ ze@W$33vhW%2vK%$q~1*0Gfov27gd5p?j#fss1sm4vW4S8q(NJK^^n3P^iqy5Ov{k zacF2x57>b+4$sE46Nd$HS;{IIy*j!0+&(64_X=CaKSB`>96bBgf>=suV0#;@e@k>! z)Xa!8B0_rPGBsN~f1rEh<KsPwevv7Gg;HMaj2l(hkuV}Jwz#(hER#pcuKCAJ~fqj3wRHQ~!^HTO+abjMl&?Wgb~QLMpo_&zg}4lgkxR3tX|TMOGZJg$_Mx>G+IZfVifD72kg3fR#F4~ zI80pGHdT4!pam{6LF?+He^>!iZ;-sgXs?hEoP9R+%n1>PclLRA?KxQDBcofANw{)wpT-m}0R(=oJZVABLEO&5H0hUfJ8J!flpsZuXTQ#e)=>)it{u z`7W!`tp|ytfuSNml}^=N)U)$ELOg5?1fCVLU0dTw(md7O(h8XtW17L3PbK3d9#Re8 z%zML--U1D&1)$eKf4&LxzZ_U2zlnp8-@rl0XEXerO;ap?X5eKAUlW( z$-RRkdB^=bH!8GGJMTd3q|c-zeW?!_BS4`*R_D#?6!43iN>dqA{1th(M-8SC zx_z6myw|*W?IK6Z+s$snd0{v)W$;-%tZC)XW$%x83H%*Oi%+~#4~*l}V>%S+PprUT z{JdZ*CxkpY|J;X}U1a*i2z0@1VWexeOM;Z?y$6_we{1#3;}!_~>o5s9cpaidU~3&~ z_(|1SNoON^Ixdy`TB~Q%FGY`z#d^>>+UCbZ1#T}x5-;SO#!jpK9ZH9vzVPU88V~e0 zj0gIe@t_Ed1j)^KAQXW@AO`RDWB-#Rh|OWZBuWyWGV$&FLhmlx7<+3D5qm(jch0^? z!Q!_Zf5i42^xeK2eO~rV@tre)MEA01jPKFS_8rFG!rWlAHxqAh*=Ak#U&1{(2E8LL zeEUBC%6M!R0*m*CF!W7uv>OI+Z#~2_SlKqAJKOlxW!%3duT2V_YB?M zKnCyAY`a~2>n&{;LcB>F{>pfeyYcXfAB_hoe-IouclyEEK3~J|VtVHEv+-E}!^Q*r z|IT<^PJhwedO7z+8E+s+y&MPOoPblCfWC4gm;#^*FofrPkz$F)1&ykUlps&lT(^HwX4Em&EX~poaYpgs6RRfmjV7PyOYtXV6*D!p-8Df zrMWPI8g;9Rql;tE;Vyyw3j5CdTFdjfngRA6Y2+#PxhFZ+zTR3zcfHu)>SoeHYaK*$ zD6yO#HrI)=%LTDyTwWboM8#yN<~X?ke{_B+0X)iFrLKLP-k*g})G)z$YVD1OQ{GX+G(6{hTy60|SYBxLJTfgl~ z!^ocTq4wGUgzs&v@LOhQ`(=9s;r%=}fD^ylLXx+M#NT2*8;GOcfGGY;EjIo=sepe2 zJ2uDMo26NxRd^CW%iY*kkpQZ4nh{f>MzwgNwFEE(Y^3#vL6=c@Ee~XHe+C2#KRW5&h6eDuJIO=vHS@^zY9FoZ@*KR=alUd36h6;2n4 z*#5hk(3&#oZuDDze5v{Uu)X_~CMK{?#4z-<&)vP|e~lrrWU0$K!nwDC zse7~!P`Fjy!HJCFXhDpXQa$>@V|VqS&zNAg-e@t46WiCmD)XyJf;D+asixrP?t(`p zRs$tAyPV5jo3?uT1d$m~OPu7cDM(6K9w^!#&&^W{-P|2kS)>b-9Hg3fN(Wl%#Bg)H zCoVV!Xc7*uuGULOe+bVHyie;}a;S92(3dA621)|cy_?++aNWZqXQ`Us3}{RrZ`A=H z?^lD1$)|5p_q8JJDHM)s2#X2d`TnhV9QpgpltR~1?wyHwR{XpmvJ0`|sW@3FTml|8 z9+hChgc)O1KQ6oLv<1!fw%62E7T=;~W*j?ncuJ!NAt!RNe+tcKz1*^DeI05M$oc%6 zq-+*sa~9aYsN;MYyb(>B(>C0qo}$gyPYiIL_X+KGR!;O|12;XBaXh0(EN$G9Ks3Ne zRB`1+y?l>(MsNj&h>R)q_VpLPeEos_k6-lA{>&7A6xbX-*cq>!g^4tW@Jz@SaNtIA z_=&&uxMXeof2<_NeC7R<>xI|!vX8lvD(a^u?aO?u(E7XvO-aNJIi+7Bk?^Rdl-b$P z7Dd$V$muZf7Oiey%ng`%&-qxP<&^@M)u*Ej4aU0jq3l!z>?u|n=_112T{T%Qwd>j~ z)82?`o{BAT`;>}UH#!)-wvW)#fRdje&RMTThF+k@e}ZHw`f6A+i3ZFjDdyQ$p-ZSL zq6p6ISw*z)l%T^j5~_o2Cnr%r)e2J8HjL{mIMz_}MN3X-FXm{N-w4WdFoBIoIq;%( z?Q>e1{M+F^Qu5KK5DCPv2zWf|d&}B3(>(_ZK}QxL<2dD3SVOc)bjE8nVKoCTCnvn= zGdbTwe~Aky$bEJ$?YPMSfK~Ve8|9>A2SM@ANyJGkt`L1SJqI-)h~ zvxnbZpFC`qQ&({E;h*Jmp8#v$oDbH)3XgR;O^@o@)qmqLrHDFpD&oobXCd|OvU}%H zv&&VnT?Y)h!)ow6tq;i6Q$R6WQ;WirTPmZ0aqg*~(b+jACD}giCp{wWg5B__uRL?! z^egZl(p-2@Iky-3^W%8{7K(MpvCqv~7s8skJZ)J!B4r?}Z8%;MS94zzspF3hfu!Qa zs4Hx_lYblw14kI=>V^ZYtWiBm-%+|dU}W#Srh<3k89q;f9mrSFZ)EO-(z#mC)$-El zZ0`Ht#&wp>NEUtm;~dn}AEx?;X)1r5+xw2UcACC>Fcg3M*9PkPseU(nSW|y5UdbO! zQ5E%&RDV2^Kdj`wv;CFD{SUeihOy}D;E(hEl7DG??Z*)``~UrNkZ&u$wvbd!`g^kO z$M|{%KS9XxO5y!|as9_&yT0t+S^C zcQE@`u#~&)uoRsBLa2ykz@N~k!%GYBPkPx7_`x4j#P4YR7zE$Oge>AJ+ON zm83X^qu(oAw}stS-exeJAAj9_PwM8A@FqYB_R|KlTYhfMe6e4kE^YAD~XABq}hyF7Yl zaC~1fuwC<_Sakov4Jm)zq%Yc2b${TF+X8RNfs4N#)%UvY%iH|rJ^_}+!Rkr>NLGvv z@35w0Y&d}Vcvmjlk7cp@DCf{sy6ck8I%z{vd#W(tL%HkbLKl z#}XQZiROrndS&5y<@hYLRHWRRm;1A2M611`wT_PHi^Qc8D_&*~D32?2Ie!>*nP*jU zyFlXlJcj3zU#butHTZ0twLaulQjAX#0T98TrOx+z|~*NA;e!-=fOum{|NNT2x4CC=z5uQ`Zp zz!|=yCJKU%lqnLboyZdopMN2;vTb!HPGsw5lBL^Dcq%LZ2o$EYDu;k)d$@Wq1B{H< zND)9{Sv1Nu)d8E_J4Iy*kvw#rGdFlMSy0T<7sVG68chLOz6fYSbcbZQ@;{QM{DAX( z>nIj&C|oZf>F_gjIQ65QEh6BM+27Jv{sk!9ur1pj(Ug0Y4&bXi4=*ZV)RQ5k{zu_uetj0 z5sJ)Uyzd+TG5Gz#*MErqF`+=U&L^SoPD>YHh9{u|p5#>t8wo1M*@a)3N=l zBR%X(@f566iP@+AbbHxE1dt{7a;ENnNFGpQ__f|BYf5R0YG27tLOs$2%LiuEhciN) z=6sS1=*Z8JJhUret8BW#Qsg>5LAr5TyY5NWxO&Xok%jk=u77RvH~LnE6H9-g38rmJ z{KLRLG@S*Tz6gJuwC&-$CH~l-r5TcS`-9c~*Z-qfr=Rmx|B(eh(81@6eGdaD5Tr>NA+zBb5bZ_tZh0@JFb4~6U zBJw>9y{E#F9e*bv@3I>CCd5dn{RlX|ueTj@mnB4hMOU2e39b!H#Nb=U8hP_##Cz7C z4E7W|_$~m#AB|8{y63dQaK|&d$TYlH0>AbtA#cVFcu%fF@q5JRFPSy?Vo$Lk><2KA zQoZ($Pe#O>_R}fs+jjr~*b#ybqMI|M=a2l<*^V9E#(zYKGp^P>%5=~%9j+2g`@-yE zHM-;2CP$f@?AzgG z91RDmOMj|47>h|rtm;LZ{ezRfpqoU&c`mc56nwyJ(fVcUo5lwb<3mg^4s=WehHmC-kR@c6u(kKZp0h3p2$HYdeo-rRe zcTz5nwG$Ui6R70n86RD7t{(NIs1YLE0e=Mn%}j|cmGcu5GW`>r%3V~xBvoJu88i@5 zVh>A8fC-q@6IJW-$!+Z%UTry^**^?E9)YB6gm$SdP}&;a~p zVfvGX<(0Ze&9qh=zGzu7>#|^=X zMYl%WZGJ-iYx^A36?y|Vs8hdgYocCYmyd)la_8zb1yFfa#Q1QXU(YoWFn?vzYBoMh zIq9MvZIIc9ZDdz^$*O;w0xLDH6JyL$FP_iXNjpdUOtFVJJ)U)O^aF&5 zg`*Y-hvAt4TXca>k5Hk!HMu?9r8p2tRtIORY-e#j&@UWprff+did~$cL!$5u#R0EB zZ05w1QVYNlWfss=x={vueSgqva=%T~+-62)9D+N!kT?FIH#+KjYC{Y@IZ1@qS-n@E zg{Wj02LP#2Avjhi2WWCAxi~e8cPE40BVXJBvsNl6e z5XF@yX#dmka7nm-!YIHnMEq+m&-ZdN)>x0YZHmh&io(&w99Q>|$miG+^ zs*7qxFLm9vl`I2vf0E$fzU$n`RHoWF%J}hSaT^T%a(}tZJS!jfXvehgQwyJzQ2L`w^Yg{kGB{6plk6XaQ@*Yeql*_ z^Rew+EZ}dYU4W0g%M-R2C;NKm68dw7uz&# zUFwP$Fn>mcdHI+oywKrPma9-Wt$6kWCb=aASR8BF2d{N=#zP0~^niqPCSmpdB_o}A zWDy4#k_TA0+~zA<3&xwPJ%OsMJg{b34zy_DcN`kd{&})PlK`RQI2^UM^jA>kh6mKu z2|&rjVHPn~n#n+Fx-~c=E3>|^#FxokCIV(1 zfV-i2rnpoqUT>fxBMav}+#)3W#)l8|Exozm)rs8GxG-*%-NY`{79mr4pT=Xi?Oh;m z=uo~8hqKi7pzxTF;-f$m89TLOb^1uV!0LRneoVU%^(bG(_6VF3ZDGUY{Mt3V5p}h- zXnz*Jln*y2nazAle|z$0&jo&)YVP(YiH0|?E$}5rW8WZIxN-;lD(0YJQ|)N5cfVz@ zUiGod7JZCYXJJCj?&UL&)u$G{JSW2MFbOzftWK#3;vi&Lb1=Wd=gVnc|p)C1%K|z!6=9{BHW-@QLNU8SE^-7CR3nWtE>aj zk2@v_LG0^LBQt4niiF;&9kxFiKBfA=t8E&!YGLt&vk(4ZJ%>>DWdUBP8Wz-Jn2vJQ z;vrY&(K4swAs(Mro?LE26XS6?4uAsD5k@^>AGxR0?d;T9((vcQb&HvEe{M|Z4u1tA zbB}f^ycyH)S4-|qgs>CYJUz?!0<6_h6z?dBO82$Whihjk?v?K_g}MKm&L94taQ^>^ zgZ#J7|A)RLn1CRhLNN%0C~AAasn1o5-@QjExi|EDVK3dM#;|`x#NMX}2k+KpVyDeV z_nzrbeSb*)BYczYM{niC4MmHx{QJQS1ALV_WWHku-G6M9|KZ~o z{zRK!i$E$1ef5DRbNWzL0;F&Hh@<_T2eOj4dKC25r;-Gt+D?12*dJu7RB?0Rz&8iU zeXGIjI!@J3I#oZk7k%#|fv<%3J2AyRcs72MeJpq8RDJjLFSWdUQGMK{kk@^VT7uQJ z+NG)PKlh9NZ5#xA0HJ>s2Y&${K&nG%fV(8nrap8~oy|S4k94$LBNV+s8!# z*>FTIAzEcw$??U)Nq>CM84QmQ5DbbzmjJO6DkyyOX#I%YG5 zkmTHC2tFRzG3(EC-RF8PlRg5}rAA+QOt>D?(-3HaN`|eM!Pv!oJ&Zx%>Bgm7ZMYv6 z_kjuVF>InEMSq)T1z8AmiF1IwfbzpUNzbglgCfSwgfyFF@pvTjZS%tHnVQgsDMol= z1Rh_np8g}K0=`F8aEj)-fZI*~3a|b`)hz8}w|Tzx(w{)p$8&+tp8R(}74S>702$+( zY$nF(m}^5$f;vsD2j#)^?n~Vbu9(~}1mC_aOur5d& z@GX-aq<=QWjp4C8Yn(Q^?n%kF1u{HxE!S(&+eQzDgdw9yI+SU68~0te4x; z`U}%^jx>_0>6ggi2)fT=v{M&=W0tRN*sfDr(h#WN@3=jrsgzJ_B& zlS08pWp%tU$xC2Z+86>GdJw<`50Izw;BW&QgweReqj5TRnqnR|yJFmQNLH0XI^?i) zv$xX|>sNLspxCskg>B9~0+`9%;2fO{cpyv7IihrM9r>bEPtO<GH%JUJ?ykafxtpl(PVjE{&J4>8(i99%jty+&PMFukj;v+mVyr@0Gm7Koi2 zIYHp%V5&oTJVE>fK+`P$eYnc~pUhGHr+*gz6FlX9&Ph=iO2Q~ip&K40aTue>Pl=@ag0D`Eq)@vmCqgPl@m1D+xDmBk=_i&#b2K2b;^``-OA+JAfa zH{cwCtDM|Jb!0qIyFO-SI`x-W^lm!c)Co}~E;{FGJ|+G~~)_O)h-sAV=^pmxsu z`Ts&_?x~FZ0nN1^pt)gxNyYuX)PMQuS{`U)^bc*^gy9B=D4Reo<@t6V4KgT$%{zGO z71bfJ6H3icjUi~ZyhdeRP zR4McfzBKurf&8S#GZf6R-J_`DjYNtxWzCYcki|OK24!2|6=M zdc=I0J)A164)T&tfggLu|Jx`3NlJ7FOu%Q&==mpvS|76LjDADfyVo3C1tcQ@uIzVKJc}hS zSnYU7Pb;k46q7B3R+!I7t#1j)E|?Gv*-> z2%?{M50m&_quHG!xHs>l(B6p~y#GgEN=wn6yx9rq_W82U6HCNDf^hHT0pG4X3HHVw zg4nZE(B@9TH=|v!7ns8M9|5&@6rt4K=d+o)Ur^&=dovLp?0G6U*(D{yWUoslZ{hU_ z+Cc^Ro}k;sB!BU}SVbiJ_FYmk-rI?=^etW)>?Nn2&nVr;c%k>m8&3UYlMu2q8IkU{ z#8UElh2RpwnRQvj#pDJm1{C4Sru6+8nYK zt(v7`Uqm9gZ`*+P#*!gFnJ3oN4UBvRCA=dz=*?3X?(`)d+#NCl=FhkP+)w$Roz$&* zg5I67n}3w&?I(Y$=ak%{vgC&kZEfhHD)r?Fgyz=)z8@X%pES-TUbgg47?OWIR(HK$ zkwER!=zpo7pTyv!ZjHUraB9*VJ-W|MTXD034PfD8F<5dWK*HD2-(IC3S-wLRf4I1n zjCvXBY0h+f@lTMxJ?(;ZtkySTO%I#Q0s{|tZkj5BFd-{l3yLyaP{hl1y~Fg9Di4&lASPal6+c;pRL0bv8R*mwU=c7 z42DfxEXOQq6YYig-12x0F>^gsW~L(mesk~Y>q()b?_9*$@3^jAh;s`P>2{wq2`2^b zDXo|o-;10zz-88{;BoKnIIT2u+Xmm!%Ab%>#hE_ZyRznYy4_JHI10$M7asOyVSgn{ zk`0%=qeIBy%P~4cZ1^Yu^{_ePUm_SQX6U=vJ{>%DWQ*(04pA1gti!cy{ZcsMOAC@T z>o=7NX#N6ntezB<*HLz*n)l9|G>NWGf$#4C2Ka3RlX0}fWJbj{gxrCVm}B!T6&xVy zE{lAI+B;Ne>Vpgigg$LIvyUZLzkho9gHmdx^CMz33S(OE=3q17J*}KNAQLWTB0vn{ z8YKjqndg@lgb#sWFqna(h_lLKM7V=*r$w2cuCu^*cG6t!;Puq(BDlsxbIAtanzi|h z1=n6V@|k~MVwH!Y$UO`xT^gww2gljJVQ~4REkU4%YJxQRL};{q!Fb|s9DjiaW}v=Y zT2xWSIhD`8XA!6VZsB-zy#@DIHLS^WfJ%!gh=+YbTHcr>DPLlvd?dXN0?|a5G7?8) zcY5T7Lq87WdLpMZ>+wRmKH<>>18g|+gQs5)WM0va&86FEym^1-NtHbi;L8D-mQr0@ zM4F51k{vF()5qoDV&%c%uYX7xPNNj+ig<`@@Q6x6F;zH7FkW`wOer8DMDF-^MT&8& z$$A2NT;%8G3yxEa3=amX2z$(Kndh4)1ny|MAuDq|Dd&r~LYw)!0cR?O>xvmT>|aWq%%8{^U@m-K+w^WeJ%f&usi+4y@;U;#NbWSzq?z9UDS~IF@(6jQth>l|41;+x z@i!`yzXis26~zAtG=KcnLVpVyZj1Z?4N(dsV1$Gam?B^ZN8!(tJIPKBkf3`Nk4WDw zKIvZO+aTUfW%6zpf{49xhXns1f1&7w?C6V#_BCMiEux6NB_qN&VM4g0G78)Kyc77{ zW|Zt*-5|VSzh6K@*CqWW;baEAZrQkX7UGE zxT8Yg-+_fYDg^!=Sh%A?;1gKL>!A7*EX=kympP)cidICXiI?{pW0+B_s-jnX zPXY)Zl`c`%;ApMdP}$$w{y_4>HCTD`2699ZAp@ZV7a>+bhI$c8<{#&~>k#UAe6ZIH zV3V3TJTD@MUrKemg+KBaD@N|AGq&0sh@$NM`K-E&$bU&mdHLua27aD6`njT$jRGI7 zr{R>u@`yXtQnXU_TSh}(dF+eH5x%l&Mqe{ZSp%{30A zBn%TMg(4WdJs{YpTztu!tQUdyoHZ2eZ55lT#oop=eH-d6oQA&0>BgJQ{nT7F_Q}qnzXax6kUd{MIv81OkM^e-*n zIO!}WoUm8U$jq^fa!;p?p70vF+)PUfXvy`u*o1Je!Fp*XVxZcl(H{bS;}9k#=ExI= zd0D#~E_u9+JOwzla>r)r(U)J*5&&o@BH?;YU$IUUoX|E3qCBW^Oy+yq-j~q!zP|d!d|>c%$(T0-2>kSshtajlM&-qwa$9MqVt67atSvC)5L}k)g}j4S z@Dhz#oeT283)E)z8@0}G81UwW@3B=yVaGZyQ1LOu{Fd=OCoeNn}6WpqMR!b z?is$&bOK?;NH=a?s~XT{u49I6TcCwClzIf84JYiQ2)y9Fvu&YRB|Df^El+c1i)m

`i1CZ!{;sKHUqR4V9rB*O+%i2B{e>$Yu_-Dn@!tRjyWgcED`X438>u7cVGz zcsyO^-ljet+yIqXV`clU2!FEU`9pa0q|v3k=tKD6jRk(uZ;^h90XZG`EB)5;~?%YP`7u$1rYRmtH6#jvSto zfiP=RV@N*E(5pP0@5{MD56NKns()f4xzfz+Mh_Z0bRhq%y%DG?s)|o5!CLl|V6$~J zhN~CFV`g>kiJS>EAX(*g9*m(Au4g*3E3k*}iC=c23Q#$a&_j?ZU64=*(f^+alF6`4QgBZY?< zrca=COz(YS^s`O)QIdsCQY$IYPmwKp}C@>A-x9cwsoXJz^9l6C?M!)^Em| zR5u26B=RPz*MF6!*ki|CpuAFVN!CuRF~bceQrY$$1Wbz4Y}Sikv#RoBeWK}HyV&r# zI3P3K8MVS0#}{TdRi2Ej#SUY`d0{(vR6ffP3lczmb`}uQE!aJ+ls(qgv0sRSHp|c) z9D?U>xG=$OShmeVgMaMK!Yx%`$t};cYKiz=r2$6@qoZ+5 zX(eZF)fz?2?Sg*Z2v-0Ke>>%Un1FzBO<*PPdZ?WJq{V>GT^8f{SBs@h; zUEATdTu;Yz@sXRB?E;ZEl2uO#EWNVYQvD3bF}1D<2@?C>rPkFDRRWi-S1q(#EO1oK z6TD9Tt(SAW#Fzt9)a??Pf2UOch4R%bvVUeL-1zPf`}@B>D6IeM4+H<1z2je5;2T@V z=g;_&C>tUO9LFJoA`lcssa;`cGs++WLO4WW2=S?AUAmjpEhtXVJ>=f)^E(r}GswP$ z=XTMdH-qe3_U&`cI&dH2z~2*^;oI^B&_3k>z5C*z_Yq=jPvw%(JL!tNHSV^+AAkCl zS&sIk?RMNWd8dNGJ+9vj^*({J`G_yZ9o(%v5`X2jg{eK85WRB|+o^2NLEqdSJF(bX z9XN>J$$|8D3iCgS0&7MR5HzZ;GwM{P79I`fPb{U8#V(*05ipiLllC!o;;67N#&Ocnjw)0~jz5KlI zpXG7jFZGCITg1id*?%?zuXe=s8eQ0{02=x*WW6B)%QS}9Gk%)5&3G*4J%2=w-FaAr zLCX6j3}i40UdP4KY(vipu8#$%7oawsEUR^x3AzJ*Hkp~)aY&=t)>CT=kGdv;D!mw4 z4{fx4JpAhvq=E$L*t>O)pltC8UFkk;bX{xd+>tvmCU&MQn89P!WYr)=I8jLZ`m{4}gF06zhpjvsqh~r zKTHwh73Ffx+bPT8W%HI3ds@ZBZuvhO$XXNdZ%+Q(*+q}l9|>KeD_7HjW?;^(B6N7Q z-JUub_n~qn&VLC8*Iw{)r}io*6w~%*)W=>7-m_V-0@$~}IY#sIT^s>kS>az*|k@%eZ4v0aCnDUD%L1NzATzRJZt-COtNou1wModGe=cQc4{=7e(P>?vRa z7wLAo#eqOEMjrGJ9MdnC3M44CS=k=72fJ9*3s#;(OX@bDm6C4R#cGCWvh>CSaeeeJ zaUJ~{Wq;U2AxCgxPPv1g9%>Y-3+KnziH^6J5?B~2cCy?UcaqiViLGk{eYA=t)DnRX zP9SyVtFCwwmn7Sm1Jv8z&Wc>>R7j~t1~=H2-(EHV9YbHt>|{?iQ?Sr_J!_y?jrHB@ zt-HId<)#g8?iz%~I9L2)rDAjrbltr)Q9sfP_Lc5N) zfTO}^n(1~%dp6}&&*wUJ+$Yl@a9Js{=wSf%*>|7ij}q>q^-yL?7I(}w8}|H-JM zo|2#s9!7sA8xhn&^APl>6fT7hwnkwelYb8E(6v!|h~1sAMIT*zjt$|s4AHeMn-ayRfN_k$c$Qw~CT zn0MgE0LchFoI7@vjpK(U8%+O3CBIbG;gLX3!EY4qCR?4yt7OQlBV$HX-{ufO{C{P* z2|FH26!?P_!7JSV>8>VK7mxI0G3v&?+sh1GRG?wA%UMyNXhck!FHcc=R< zfMdihFV6d5LE1ZW;mG-9?aP` zs@r@CuJJRckgG@xSd#;(^D2Z_(z~1;Ioat&Gi5o?L*7v1OTko@Pc)|Aq<=Dzm1)iW zdm(uVmAr5DOVMN>^MDR9Zcx!ULy%zpl6ySNM7kYc!y$?hQ`bA0xanX>dz)ys@NIUA zANvh~k7m6Ee-|wOA^vU2vC|t@zUkP9F=lF>k~Yu>E98iu?_E*nfMpqx(-(*RvN7|g z7|(?d8D_rUVIJDfGiUEjrw^y`0g5mL`*(|s1A*c{+3dI zr+>qbEzxIE?hcPIdVe&$9aF5nq}}5qR=I2B9W&8S|JV-PyQn^bq3ID#JuDUC1ACK? zH|H^@Jv!3u^v4v5{N;2g!8^1Zq<#m_s7$-X86}=UhYQUqlet0IU#zZo_Q|u-&!$8D z4wTQ!-9+g39a$>*`?QrK>UI+*B`a- zmt(*mw6FBv+zs%@+xgYq{H*&Q_;dUJ*Y1Dhd{Z@PGM))Okf;Va*FJSSh@sjH;Xof+ z*;ZNTcX$D^)4N5;<)wA0-(rgfT5n{?8so_#3mAJoI)OO#x^{0?Rs2`_a$avtUNf!J z#5kbeK2ZDQ%zss6AF2_wRGq{-(Cq^5)Y~+Qm3O6Db_`5Bip)K_yfC~ zEG|e%U~`Jujx{cAb9Ey7t7kS|kAX8wa_J=#xjEj+-s?U_Y-xhCK_66e4t#zHXg_)T# z2HsgH4Vydk?DLjk_QSp)7PRu+gsj`|B}zTs0Vun5BiSG$+{<`wA6LjbDV4_4NHZOH${ z^AY&=fW%d*SDJIELXYNY(bhfR-jrP0v5oyKnD(WipU*vjn=pD*g474Wq+y1wS>KQK zjelCjqs?x*F`O#$i@YRu8XQ;Mi|j_zmGc3~jF^EK0JI#E|OG>qAu)}_TbL6f*-5&s-$P0uRfsE@Rvp+FL60)a5*m2JBKbdrpQyeV&)X1;K#+FA4Tc;3c* zO2Hk}HIh8tO;)Z3Lam@S8vKFuX~4SC)YVvdkz;v#^z5m>L4!$o`jfig^$i!wEyk`` zvZ_^nb@d?u_E_ zR>F>Xb!c>$Meg(|Ob_;R45uW%*4k0gPl?k`xQsq+hd9mR->|>S=YJmY|KunIJTCfip(4nGmLZ=MGm0N77y9^8Vd-a@9d(TV z+{xK7To^xk^^ey7@Y7uQx$rJIcgD7puEW$E`tOKS_1f^27cNSB3I%PAw*NQ8N&f$e zIQ`r<>2HV=Z=i3a2ElC*`2Eo{-@`~~P|@}ini3N??Cs5-$`aMy0Dt%H#wLsAXTV0S z^R$|+5k?Sed*h@f^~0GGaAdsoE>X8!x}U(f$sU?8y>Z4m*{J#e#KH;)zG_LusZun2 z;&qKbcTt}Q8`!72nrIB_gkAF$MOkRT)d7QqrX7`%KCvFnPJsVrrVB@Kr|XLv*;us< zPp&C13Ta|q`x{T`J%3bc&+2|nVp~PqtiGppl45f~$`ETLK%bJO=}(HArK*G|){|AY zx#WBdYcmrU>qO`+P!kH3<*;F{F}F#WHV=a|jzDzvC*V4HkBl~-JS=Ee9=srvFeiG! zg{p+lx2(+vSTD`g;dVghIL`qcQ4xb4^DyI12 z+{#-LJTGq<#nWwbDheK)J#rh^ zXdbzWF@G<3X9WxdoK6?JQ%*`Ti&{*XXfm#R`*tpt`D&AquxiA{hIJDZ`XbFt&H$Z~ zTi7gm%&X$)Ds|t&j&BMR%?zca0`)?{0x^jTzv5v(vPvwu=pK@_QaP0W*}%Zde8K z(X~{8-wdfOgD2+8d@_b5f^zq_a#GEJjv}%-W5I+w98QR1J!g|%4%DNe6`86HKLX!SVrJE0B7dhbLAW9=-zYY zF+orpDVXd+RdlnVnxzpBOVtu-Lyhe#*7ueW1 zGkr#D%+s<8byy5v!kRTJOVh#&m&GK^eNWBj=(uY9)FWg zlISyfjs6VujXq|X^kHtW^PMz0c+D}?g!nDR|AsihAD_>NIt&%C&)nd{)FAm(=zZpy zhs05aag^C%2Ng>{R-7SybbK6PDEOGy7D5MWIv87Y^xBc|5%7=V2 zI3a5nuO^eL_hn_RcEweX6x~#R@26nnq@zXnt3Q>iL3QfZDgf9xYoRmsf zBT&uY*HzuG=a}s@0wlWYGGkq`{B(NxVj{|>z@7y+%HJ=g0m+h)3TvqeTz{}U^Hwjg zx0HIqP`@VHX zzxhA?{%5`0iF19#x*x(+0vUH@s?ZrwjZmW1z*`!w7(q$PaFZKffgaUG%fgCzd(X#` zikQp4S^XJT$VH@&O@OBGtbasyDkpPFQZy|^;3|oJw<}d4q_J|*+Y|Pud^;INsD>{O z!Y;)cnq&}NFU<5z{tNiR{ww(U)vCY37xq*5LJ%6oA#BGgn80BgBPbf7$)lJTCVxJj z{O~*bc&6+)KtRXG|A3+Jh@#W<;gEtwhpE{PH_?tz#82UC*LrYrtbazx!!zv|&0#pJ$l5BX^_OH3oJbDAP$dC z7jVS6O4xL1imPfucl-5#v#`y3HVoJf0xMkvRIq`|O2mN)cQp&X$X?#*9MIL_FW`Ll zj^kvDH8k2YILq)SH&FhguTU^>xn}wuS`8?01v4nZlJo=4+d`WrvhN95iv`JqJ17|w zS(rjNpGD-uH6QNY>2>Qjw?bOc&4+f2s}%mh#NwEBak3wE%gHp zghz36uP6xx`i*M{-edC3tkn=v!YnH<2D2`W_qDZES4JtKOnJJMC7>0UCI<9BI-)42S&xVKI*5)5h?L6C+ z^!(~f4`${<8GDxAb$%8#NTz~cH^~XN`&N&?E3OHGI8Fj#H@C(Ith6t5zuZfk)W7KW zjJr*%(K?DPthSI@eW{^g4|8(529=g?j;!NFjTiuziQ&$)Exm_@K2 zmXj&|I?#5Djn1m?J!dWCrru&(q_0gOmgnIKcSpgVM}_+nd)G{+Q8kb{brzv6FT@91 zrP|y_^AMU0i#AYvI88yI94w?Mob1ey45wE!xU87_b|-z9Jsqy3U4R3hzYSF!pXe^6 z+@-ps1;#55uhGH=oD`1~F(sR$QGZ|DvL=SumOae_UPYooIzO%!rmd=<(ScY1gvP7VP- z;f;|{kh?`*keEVSha!5%>??eYl^<>!k&3|ZJikzz=k9&PjPiEoLX_x=qhxkFaZdZgFVOwt~qWA!i-`(!?BC92owc;oYTwWemzJnCn5H zMlCpF@|2OiK^#?#QJK&rRJInlmhmrZ??I*hO-RUy&;|QxW z@M0O@&uRG}xea@&tNRuA_*umx%ZwyT54h6}kD8oa-{Wv4geFUkuJfn`{pj`&MT2yfDAi7o7=po{^;ZzmW4{`U7;TC8-AS{zLKz&Jx5A)^4=zJ-!+9QdHn`Jr%I;EdA(rGgwOr?4mLprE3iO zEi__%oI9?;_}1}@bQ%@7PXE8PQFRq zAu^qds%cVM4n$YV>z2v6)>^S#<+g*^1W0VORtsUA;ZBmU9LmuI9-hY|=}`~%kheD~ zmYOeB#1jQVhdF3>Iq-O-f%un>^QXo=Bvz^HQ^)y{JfeKGW{$EWyxg~7;ZSOhaXZhe zlc;wj&V_euCGtsBpUwkxpW4_jHtv6B)ZY`S-#4R3a52PsQA7UvQ4HKBSzd3ACrJ6L zeur=YqDSmTM))NQ-dZC_xu(WKdj=hp8k*q+Gn}D(e;(kjL4B_Eu#WvrrP} zJER|Uw~-_<>hq#w$%zuOH=?z09IWy~B!gKValwTOQRqh&n&SyIO)~<|+rqA>zd6!E z9+|_d1nN!s&qCxeDG?GZ{Lg0gmK1)4>B1sO*w+(fZUJQCH7uSaV8?-I?I(AO#e%cJ z1xjx!m$DCgu+PscAmo8X%xO(q7jPmyrKtOr-Xtjm#RNS-m95eeXuQF*jL=#9s-OET zuIIPpHQmWxd?}gp_=ITk>hV{^m8+M;;aJ1tE)P@OZG+K%rlEZS-u-iIw{zBYy*B!E zkV@OJ-7sbmrETT+bx>ERFy2>a|47-?Xh#Nk3|I6l_R1Qd08i*6>Ur>;E?4DHNpSvN z4x*Lf!J2q|RTraSYm|nV9^@TT_itDjN}7+PW}XeLjc4!Z@?#_(QHI#Rd(bIQ{zTbP z9g4J${Nh#!wS&POl?Y%HSi6CcfUB3}@sS~_@sbEkI1jndVNxSAAE3M+^Wp8k^Hcg^ z1^2KWAYC90ghNzL*kyn~nD9CDF*<40K+7{1*REA_Wu{VC$r|1r{cxq5g$5qVEhxvU zLUGCq5@;b0&iaqFvDD;?Ikh&?(#pG;m_Iz7s=5j2zNqvTWF*U@z*VTV)@KFr!jTK^ zFRA>7@9pxOu`g<~b?Wolmp7$bmtgV0 z1~-G9xy~eZ#`7z7(<;1rZ%9OjG8r>iVE@vSTe>pk%gKf^yC)vgrAEig;JFIwNbQId z0DBnh@t9+{AFaGy=W6TQ(AHS?8Mf}<|Nc~X5WO|(sh)P6tj5*6m{OG`o~rJR3?1ED zOKQIZq|%qjHZQ=>%atNS_E|=C`%TXd`%F#g;11Z7|JoBzywBVc-Xj81_bw|SMg$}-;F6A%KKdjf!ec0VI*98fxI5r zo`LLgh*}mt}Qy&W{6;Z!lwCG z)K*nWkLFsZjT7~l9ob$@T`B%u<1_L=j$$+!Ya%bhGLqx!lfVB%wAct}_A>DobH0oS zP!5?qT)8%;1@@cWy*y>1{KzA5$L9R8J7~OeUhqtQI4~VozjkG`-1#T-w@hY&o@`AF zS?pErybH0Ds^m}#QwH4rH5ZB|0XKQ0>kMI@Z66Q7*JpdCqTG_eE-Ca{x{>7%`&Cp_u;JM-E&eO$98{(ZYE!6y+DYgAC zd*Nd{5`bA1Q2i=OyH&ezC#3oacDkb>KC(t&q=mud>k#f$4Sg$%KN@(0wM+)0YrPvX zgu>RBy11eMY?v=`VH_de@zr-*nJ#sAh&!91T-!=-huXZ8M}N>^vVLcC4M*f$17(p} zPg1k06EcnxlVPQA6v%uUKJW7^oO|%h94iYBj8`wex81u2+Tdv63)qa-^zy{ zKAlb^g1>-@6QGH7;jg|~CXwg`0IR+a_^vp57bjV|%p}z-dz1XQ!fyF_)25iK_~UQ7 zcoO#V_?y8ZxSkeXg3kfLJ8!!YUv6H9{G8>t^99mik;Q2z(myj@%b$Nw=;AKtX?(Is z#pg@o4j4v#A@e;}!j+iis}3R~6rIa4Cqs?IxK_jf&W6Y5&!YK=jFK~kO9Ca`ZI2m@ zya{9a;}P)u<>1N2@O$!L&AQYG=tbFNYVj&8EHvt{=U8NA0P9h)P&$7)7I9e7p#{Ns1v|dOyiGSw7oij14bYvA zo2tOrr-bL+PqTb!FXuH;IW%T5dv~4DjZ%!8bsqKV3KITt=l9{8!;>Z?`kNPw?Q&WN zDXU;iv3lDjfs)y!5`I?4DLJYbvqvMhzv`ZMa`m~xtMh;@z7)95a+@sY&S_|4vZY7A zUMbI}0$&(t^-e#eH0nk$wj%E&f6Q37m+^(RhcP`aA^m+AQJ>bF5MFmC<($S~1gC8t5Y~rrt6)y4Fu8F4G&c5b};SRM&22H&^=p z zJcdW1xc40B;!G&nLol&bPUc&7z3@CIf0mug;ufcK5iuse=hxmQ>R(NKKca4Y7+Yix zM{G8UFMn_qeo>Mnmljkm@wMAg!lT29Q}jI>XY*jD3=Ia#3f+`wKb+AJ8jU_s2{MYm zG?{viQ90L%x28RTgQM4!?$_@C(99_sJ)L?MxzCfc10iPGcCbsd=omc9EjSdJd|O9# zLW0gz0tiIW=uVPcOOvPKr0N9*qzm61M7rGL+1Fu9#W<=&T8)J!jeiWA7bs0_|zb@$F(tkE+nUSb%iwn)aQIQmTN{gT&>Vm+9%tfV*~aTrPBtQ6-Ah!{Rt zi@)LIZ7CgV)cfnBuH**!cQ5pz$ITdXJI$Uu+PkC;HQGI;UZl4fZk?ONRUj!mQdwH1 z9g2XsT@;1W7zcEEFVniutlKtB+Q`2~k1RzsEmT7xyp;>#X&L#V$x7jzvxzp^5zBBJlBMB-3s z^7VNiKf@1wp$E^C-T(53-ZoMp6kG6~&wv=H&>nwcyvyWK6k98saUc{u*j^^ZDz)LW z=Jjn~tp^9C$t&*?$L}Y`I48vH{?;fvbJIO-{``63#AC?X)|3^a(Tp!pP;p>6o|bJ1oJA2Ibtzn}VeLulb1|6zb~SEok> ziiT9_faEncitek2@%5)uHD)E=bDi2m55r4oDAhELSky7v^6%;LL*Lii%pc$@FI{c;(Ad>+>A*yVyp~X+HMTo!(9+A!29_EZ5)zR2d9Fs znI@`I`=Qj+BR0b@=+b;2!_MqDdiC7&#KioA(PDW#n)cG!1JWjcCR>20IQA>3Pw{lL zjJ%#+sjZ~3!ve%%@~T}OSK6Fw4C7Mr@qekU;nZqd&h{XDypw#Fg@D8a006K6Cnb3W zz2fk&!M|6eU;qFC2uvFi7wF(@#^mTF9xH4g!h$IN_$_pTA)q3}juXA*WJ{*cN*9V+ zMx=7}&qZiK=0~cT;HQTdeoNAb$6Vq)!b0^+nPcCsS1%7!A&JID1%ZA%lF$MNi_6cw z!5;)~{NUF|#XI;QMi%p*I?F*z>``gfqP1#;#u0ZsV&M$}nR0te8(KbQ@~j#$PylTA zr%N7}6$7wG?(BzX>1OW+DfJF#$pZ=&B@~Z?ly7A-G;3`*wx0r*3PIcyydRN{nYEPK z)ig>zQOelWn|U4K2LHFNEd-&^L=cewt9A>21T+orztFND+5-alf7Bf<8UX<~0APRu zw2cRg56Zs6z-YlAhL(i;m(y$px(V`MNW2LB4)ZT0*?>NV`WM3QK?i{U3*!!;fBdKG z>k0J3e^i!pXa}f&boId-7GgpJ0LZi;p%Z9=meFfyO6Y$@Zyun{|0_`E4LS?=U+N1c zj4K4%|ID0RmtJD$1pq>Q{`MOvFc1a@qf*iwiKBf$F)N4{_@E;j@Ku<%#Gmw!1b z?l6#BuvB0~{xeEP9VVCh-;&?`U|jyAx(325qyI})NP&@O`4{F5!h~Y{3u%7Am>~QM z>Z6ap6aKi&dlSeF0b5*{oZ!ar6XTwMPE{k8Dr@8d`g zN_>XFYk{SN{rO)jw9~^9{nrZXEU@+e8JNfcONjKZ(mG+-?f<$UMH+VKzmCyUfYtd= ztWyQH9_b%V_dT5g;*bEqG&}%6_D_4Xq#42L{wo4{FoV7Mr%2GbIjqpXg)>{gZbSYf zYbTSxQ2%#?T>Wp9fKcsVaY0nZsD2?-v8(4OXq2|WKHM7O<+9dj&&b-5g2?Kx z3MIv*Zd^bIQ>+Ko#Uf(PAnl)Bx2Lw(lxUYRXkW{)%fe58R1q>{QmXFr?l7W3+S5|e zk)riIH0WPuViEErOvKRfm8z&(8MO4^(Tvx~#XNeQW}uyg!6h>BedlNEA4K zGMpPz$N8D??Uyu%L#QMSvWs8CvebKbeRg$tChUkdGF4l!?U_6d{5HP11fOKWyEDxR zy9=ct@sc|X8a~J_VKcUIZUs7Wke0Ss9Fz&hSyJIf_6H0F-A5S4=;{Mws5M$J*bvCS z{(=L+DN;&jbfMcAF}M9%%_#PjhUUN~V^x%Nd?!}~L#k1*x-P7-KjaMxKN~5l?$@k$ zwc@-QctW=K@nk(hQ(RIL-#wX)8kpjU@_v#{o(0K`=Hw7X^H6B;Lswcz#DxS6>Q zoPG5Y4S$p+cb{Cw6rN1Ra@<%tDW&J=d>72XLXVpu6DUF5CT*g=q@ zv_)!IlGi5kQwOXOg`>szm#?Ks@{tE27Uli;cTWVeeXQuiBJ@*EI_1u^%ixO^zgan~p*b8xd6RCw2a9u3zra&yq7Dm~Qz`=b z0;TS4MsTtZ+>FT=oJnL`(Xs*lQMK9jz$=~dg47y#+y=7zf&NgUk#(MAZqMH=_{Xj3 zY#GI@tjhXcn&g+je%8q>!V4n#V{reiuBz(_Oy0y=(jSRAgAsQi2C|uRNN2?U9nEHt zK_%*Qw{{HjqR6-y;nihdHZ(J#Z??EEC+w5+6$p_{@SyG&ANSkc+^)grLuuEN@n)Vg zmGLT9**lh^!3#I1-vho3j3yIXL5Y67243ilsr0dtp2<_cr< zIn0A0G{OToaiRdYny(sV$oM%Cgg>*wROE8zpMT{d{eWK!Il4u4K_Ty@4b4{cE=8_{ zII>fsRK-zcVf=|Q%1dg<&NMBC>eN@#<3VMukOoa;IeT?2FFwDF$l&bpMl7r9GSsR` zg{IRV)Ekw6(M|~?elGAsA|U-XwRara4Z#)>gRLFd-bLCMRPtRd-Q2s+@DQR0LGSMt z9#%UaIy2G?Qqd$inSuH5!3S$XnYNNxQrVi$Iw%FL)Aig!U&+8!sg-^bS%wIP0l6?D z+{P39(Je7Lr}sZT`o{J@=H~YIgO76v1-~hL-gUqJJQtY#=#hK}3b+aHUH@31l;Zhb zWI9d`bhhCq#qkuJ0^iTTKYnrF;GM>ZWA9Z`Xy4jD|1iiVTij-93)?851GLzX^{ucP zFp=>xJvOTMlQH$>=7PJ(vm3%ur4v>RGR?i~b(MIrDuPhQnzVDgH!IXCuMCUbCv;V7 z-0cOlt{H+}whK#j%jzW{D zD31wtnO*bC48wOuhGtS4u!6oQwW=>Luv?6$_^MJ=sumKppTWOb!42smE7FM^8D&+0 z!CEm#0iL!jBnda($R){qMcYI|@WK2EjzWEz-`ybtWl%7RK*iWDl}yY?MIf#`Hl@bD znHQj{#J3|V8XXJ65H?T!yX;+law975#u$H7+^8tV>dh$Bnm*R*!v9JD<8^7Y>zvf* zSjpD(GVbixk|u5qd*9JV?q}vzwTI6J%rs&bH>TXKQYi9xIE4Pp%yxXUxvjp?#_DOj zC@}&ovXEP|7dr!yC8Q!XwoI974{R+oYUvoF@{J?c@TqCAT`FLuqJdc=B4p4 z$@6n{q$a+X?9VbI$Sk=O$v8I2t@8!}HF@uohQ*8EX>^6$CNOn|W8@3k$Z^<#Y@)fB zyKHkE&^fhBYc=o$3djr&yjjBcYF&Iket7TyfRG6hF^x*}jN6w0lV0O6Y7?hD&`2+o z_pq!N$!Wl)L+tir(k4{HNeDD1endh@q$osh_La@AVu*8$AHm4}zC+B{!U12f8`Td2 zugE`x67L`bw}h^8i|Cu!g!$6jM@)tr zs2o%s(aFYTb^kS1eq%A^s{^$GJJ(XOrR)!Aduy3;#<|Saa@Iaz^I)ZmifFrCfMkXX=?MfTLJO)u$OBK&tqBPL&P2GOz`(bUxLc)i41murtP8|?Hp3> z^{upEwGO*rfxJ3dqT01&)vh^)X~!th#fm!NH2C{5>mKeB37_y{xZ5^ZI;&scjLOw5@%{{F2J35Q($DY~+B_G2bq<2YyLXC`t+uY%WM4 zSub1j4_t4Zk{!{`pzjjjrEI|1R8Z$vi%K#qcP}Lm&Cxm+AGhjh!9Hcb5gFJvIg_OH zvqlKo)kPre%Lvbfm17Xf^?AmHPo1fHud7wK+2sc4J<0d3C<+9t;TKrtMv3dsIU>~< z+AI)A(qsVbDOd#fjvJ<-&&|@rCWATmDfJfny+SJmdxO54${?$jP{ZycLg5jF&YyQ) zsiIpq!IGCKHIlP5gx@D+-s@c^0pECi&zdYizSMX$9cL*(EVOcKH25sUd z=$3fPtX-fGk3OHN+G#F$e%DkaxEG?-0RD1FW1kJ(=yPhw=UFE>>!uQnAWEAtJ5RQV zEeE2vIM^(_)}d>!N7bdkA4QXzd8r5KJZ0Q6nplhaS`&SNH+c|54$v*yx>!3)azv|$ z&+r3^Vh86l3{3XlxJ;ZbZ&Tqi=>%)^>lF6s>TZ9% z?0dRh#HGie=6&bEm>&pSGghq$`Zdep?o0rD!G9-u`kY-!|1G0-Yf^j*iCAM_2jOXL z_~0Bk-DfAMVrI_;a~<6%EtxIW3H81(cBrE^!iXc-`B~82?olB0aPtX1=wc}+ig)@+ zfi4nYgfR361V?NVd^XClONhzc_K*S+3=AujzN^}xVEiJqJ4(~ z00^-F0HS}nx85*dfm0ef4n-1}{*N`dlxz6SkcYR}oG6j|u6kaVqn@c%6;abpqo?hO7>kk7#-xe=WyzPIU8hLY2YGfcM5 z`x{Bo$x3@>gi`3Q3C^{!Fr*7(mi#Wm6fqdJFu^A1Z0%I*KyE!R!VAkC28UyVw1cSZ z?3^*sjd5a6HVSmmB@+x}o@ZBq9IC;^*IpNypJH8CilsMEUbbAt`TzzC5pv!}+6awKG8#2w#amX0FqRB7G*~~yz=JN-0j?nDA0NlBh1<17P zFEU7@NuK9wz@5bS-)2Lxw_8;1P>yr`U~u6ROb!}+&;{azeQXA%h$dGZ{s#qFk9T9X zJo<>vV{^XUt>T+Lj?Gyriv@X}+2j+G8Hyu6*|lRv*dLE3Ha9(Y70f+ciWc>EQfKDo z&}POc6pFR;O59D!n+_ZYaFYT$EFWf)Xh`;He(~OT0J-Z^3`&-`iOphE+!ehTj5FQY z>?cN@4`}-Y8gHD#NWSIkRZ@QF6~~m-1Y!O_S$jLS2(#T z3b5&(S$dy}O)Y(4tF{DPq`sjRQPGo>&#N0X^k_G&j6l11>7x`;c{*xt~6uTZ9(1ucj*KB;)?p2mz znznmyr8V@qkjBc*oih8fIi8|obyF>#Ze&KDryr2_)1qa;=}>!)i7*fB2bUHuc-9Xx zJCDZTXHK)4fbUFdV|uQrMIG$v;RzjxEs#6r-++18*Bu>)WDm&G`kW48dgos_ef3^| zn7Umj-g8S@uUK7Z23!5Sjzl!SVcc=3rOCKv2LB#K&*sZz4$x~cJm2+K+ay54#;9$P zLHSZp>XXxzyXU9S&8qEZwKesYSr5#+`1Bau(&w7M#hDKOuuo`cMCe9OI(-wb)Ho; z@-ZSUTF=!T)jYbeUZ>M#8zLi(wAhKZJ+%wmCStyc6~$ptjax zgDXY!4$T@#4&C01L!R0F0MgX}kC>!!4`8&X)WMaAj^;(C#_*P&S;18K3*l_n8YV{y z^2c~Gr?}iH9XWSSC#h0Kco}&=+pxFc#WYVE9)UzI&6uID{lH4b zwp<XHT1>!CzX;=9H!22!ZPn#n7K2*;>5rzFhZG zw3PRji#viNwW(aAWYilLm^C#7e(N-qfd%)uyfjhux(7D>NE9beH5z3qTUh$Lz6{)l zSRx3g;GWIUa>&gOvt|-z)yB4;$v`$9sn>c1V^kVouY)|>8c zVcrRfjND;wbzlx#V7S@?O6GsGQsd1;=jgjRbUJjf5x}gHpH-Px@P-)0#d3Q|CSBh| zC;B2e2oJ_mj_YqGm1F@_55n2l?mCi}t9ffW*0Ki=e(HBUtM*NzudA|bC%|XZoXeKi zWTfzcZvqr_$W@(J=PQ;Mb~^kikE;AXQlKhI7;dAPgZoIL6pagGJ$^)J7|>T6Ce*-M8X3lnhLoAoL>-PAPe{yQL(UlS5wt{j>lqkQfrgJM0mGvs^ zQ8$A6Z0jfUS62<`Dz~@TL3-wCP@?D>el*Nm>@L3_ort_`>-KIo<$8T2{8;a3JMY@0 zM&T9Ka#T>JM{pdyH)P)!C=&+B3TUl_Wngs;?q7nPNJ^Z5BAsg~4LqKxGdM8_n!|to z{7|o463!vVWjmX)Hrgwt^^LNMr;Op!ybcX1eD*=Q_VD*xeuemSFRepc+Pf85_+CwBrd&AdM>}aGN{8j zVG$upl1%>u_B|KOKVE)aB#SyG9qqC#ujxhU*>Xyolgi>~Z};_35q`#}g&+!-jG#U~ zDV~_S-rwm*?QtK%|B8LHmQK)rY@>s@5+P^A7HP#ml`J8XRL-jWL2)9FIxvGCSg)$u zCHuuYri6iPKLJBzrr|W@nx5ATDVC+X4cEWZ%6ozxNajgs8uWu{A|)a+-ot7jakdJZ zKZ8x-d;7PPUTl6V=RoQ}M$d9YtH82+@CIZJOx$=_n7)9?hCv**rQ+k)JhGB`I5eFS zMon~B++$lfV~N{YI{Vxq`^oDy92@L{$u~@2d>#%|)_ggk^jcD((?JxA-UN0Bt&Q&` zJM(g#!1N+8guEjEF?f1(_7!ywsE62V%J@)H%pj~z@sW3Dd!J%^`a0=+Hj<@Ssk2o6 zj55sRQ0;@+91IouNNzN|QuRMOp;%u$k#jUW=WBz&P@2<^w8OHv7@v-)@m5DQl9|rX zbB&xjR;Xn0Up}S?JXfoF$6Y9n=SOt{E#B?{z+#L_7RFQ_B^l~Sr3@w0*wvv92njCN z?HU#e^)mX}g4zzgiLx)6^WqX@&*iRGfg%^(_ZX|YD^V2?vJ09E6ETUd=LpX()=Nw~ zXQVt_ZYQ8~JG^ME+yax*zk4H!Yv{L{p9*x4l>%jE3ok=v+OHqKj>iJ3-c^0Ic0pt2 zKte`A6!%7%Wf@7nsp;PVOQ*!Gp*<6G4}$T1;wmKgB&cE)uJ@9hYx zFWW?4rY%?JW$1n*f8Xw3lsFmR9)JzivRIcCq!Owkd;b^21I z6ljDTEwBfT12WdIwA3~+T*zTTNE`lQ4qSW^D$+hWdVFP|5Bn9J))iA4^J!&S&BjAr zu;wFpnh`&Msu7I)Xc`1TNTB)3eXWANilH61SntOKBz;8C?NvUpw002nxnl1eZP7n| zTNdCd;_P8Ei$>Re&_w>7%pJ;3?*hYBT-2to#WoFxH70XK#oDDpprjCYPvt>c2$Y02 zGmILduWK;YI4~*jTM%9j`<&1^lc0PU>giXB63pXGB*EfX z?YX>HB(Ij4d;xjGp;ak=Rm;;30(RAVJQ$-Tbfhb1TSc7Xs4g?aP=ikTanQO?r&EPAG5@1M6e9<`YuC|ru6Nv;>v7H) zC4*W}$K2>Sj3WwZRNatI5j!0ax<8|S)TdYax3mXG)BJR8eW<+$A+U-cL}Yl)&&3WbU{$4 z|E&9W9Znn^^vMi|5Bd@XO9+Liw#T*%5{-hT1DbA;S^tozb)CwPQ)2U!B{5$JUlnVX zd}2}0BU{cZfeUH=O1p;5ZV03Mr8B3^726ne7f%&}ufn$(1$pEUs&Wm1k-js#5T; z&YJgJXdv=vSjT@?RY1|O=Jfw8e{~W$O1>}y0BR%u))nak0|CU+0t*RTA8p$4c!wWk z!jTFsJkCjRPwk4T&Ny%Puf80cWQ>gt8Z8MygLMRaM^Enh^qVQ#MoGAptCzkMr!+x3 z`L^lz^2h7`bRoW>XrRb;i(&lbjC=jhM3LZLR`3W+e1pZ5_j;Pfir-i7uhZR67kA8Y zJA%N`Z@SSJm(4x)XBU3JhKs8xb<^#yS>8&2%v2N$j(o`KLCm>1UH-tYmshV?H?e$U|!_0CN{2W1uoAOe|TU?!Ti%oxsZHw$PZ;i&c6kg`1y?9f;XmRyGzsc2Ko!d7Iw;12xFu5%^%hS{U6f@}M$E-Ly zN%dtN)6ena_Va%M?z%o)MuRMB6b*9Z>q$P|FD?!l-W(H#@<0~bIp1DqYWp>tyH6)% zS~{856ehKACQ59r%&Av91B4mO&zrTPo3|C%m{f4+St0N<#*8G_9mMO>BYi?PpdF=qu}arX*bht{%kt%`9 zKC?dX)!hAIALe2|rCk#oy1)YFuHvNK_5qRBbW!(%;pqJ-eN99?;4{~ph!w7+&{nN# zC7=tDbr~(36~M0hQ*W7TwLdd(8mt9Xc8AeS@1bE8Scb8r{M7=~cMO$66J2ou$&r*Q zg?O(kmxutqP2W*vzlJqC^3}#VkumEl#%#}I-is9`cQfA*8bIXZ!Qi(Iq3FSVYFXfU z-&wfBHuxh3j5qh44CdvmX0B0SRZkjsHej$@k|IsuOXWpJ)xoYg%cTCr$)6Mg!tnPv zAl`{Luuk*)2sMXEckjnf^f#DW;dP5&<_pepyaX*) z+uF`skRgXg=yKo|9hCiMv7Zm5SIeogz{(9^H*}$e6iD9ZPP`EWxs`9J^?9K zcNoG1FnOXxuvnrJ;6fiR{2*?XO=LZ`<9cK9Ny%z7rMzDY_MNj7 z2#6p%0{cg_BhdZzyq^7}mA(?5LfA#L3Sw0g!Nk@kGBkyvWF*G|cP0m5c+Grb-uv@A zQK2-5S3PNOiPX_v43Bh!((6Pm1F+5yxIgcuAD#RVlMZvbXb54` z{lUaUzsH}rRcjBm9aG3TeyA)yCq6n11q|FK^8D74nv7$$8Z<9nAXmR$xb};lb_+;1 zH2bC~Q->c)lp~f&Avs#=zWuUe}749r4wb%>Qd%g z=JFZ&cX|e>FQ{m$ssIEFxug}0g1xfeN$a%%B7rJGS4Ui}62Ha#>GK!Bsan9a=YVIv z>Z)a#;M6^sci>NeDsBX9EPt)#EFWF*E={*pDY=@Gx81f@hUk~mM^IM#cJE~Kb>-D? zgyDCl-r9OHI}J6h?OwVbCgDCnDx|u1FlB?87Tf_X2Ww$B<9dlitdF%30k411+d?Mz z0e9y^vWUIbGJ>-Dy=Up0HFT z**QzN=QQ4GbqZBkDag3aft-c{48v47cCDN^eI1+D*=@Vfu#lI`v!_GVmk_hTXHx;G zTbw9J?m-(os#XINZ}ApWHRAWr5WG6hOQ%jW7V8dl&t637a5c-?#D^A0a^Q?;?AT~> zJ+q*M(GDi9k48L%69F<)9HcJ?fO0CON$|am)+TpB`j;H{)S1!31UXV^s;gegkgC9@ zfiF|w?uM8w?DwI0H%>EgS<+KYdvwFmfT$PiL4i!{O+?L78ug+ZTsOpzI)b_YxWiyv zvIn7Pf!%gP|AaDuF|C!cePD!^B)G(d1ms7Vr16(AEqBwo9XaB9x~#3!>p>6&KbT(HaNE-ZG1(0PuHBG_g1XAW&(< z4eSJ@Y&`a*_79%jByXq|Myz5jOkiU!D*SA?J(dJ@ptrIXvJS%UvI@)$XMn!@_yZ|~ zO_KP#4xDoxS^#7(cBKK`ROs6-0d9A`1~=@k7|M$pNFx zA|y1kN%=|}7$?TXy!;(H0!-722TLWOeTs?cw&-mSoI?Y^yTYPV_cN+Z++y%|!8Ia6 z13nym&(WxU9acmhddNThY<JBE*A#J7nW( z_B-P{)kfAK2LTD;)~ZRR?qhXRGuI?doH%R2sdo=1xgqs|4MYvF=a3GTUtp>4I?$+ZN3- zb_dwnt3Fw!4(mtFx(PMBMLG1iun1(XpRRCPR3rAoGC+pYr!V78Mr19*W20Y(LLUU( zhD~CliI1?QEX`_EBXu@SXzGhlW-kL+9?s>)g|Va*9t_?jL=ri%MjQxaSi(+DX>)(U z`}8VDO~N^^Us!L03~P zwQnrCXaP&s=&VcUC+b6$0=7;7*fa|Gu^p) zq4xK{_0UPDcd%N*f364Ygh%?aNzH+kfU#Dr(tI4yD30o&AL^^QP}@GPZu_Z~KG)>;>$OP;<9ja<- z+my@pSJ3%vjkjVp;`Cov>R-E)qtv~+MU$w8w>d8NgoV{dKNHe+Aj6zkeJau-HyTw6 zR{*J&_F^i_v{`9mN~j*gen7&=rMZZ-6h9zaOR_P6zX0ITE3SVC-`P`rP~^|nv{*RA zcfXz4>=5{z<^)Hj$dk*xZ{Cr3E>rNC!3ca2{@O{2cpu_tGpk2`ue zEkOm+ZuOwo{8d+8Bu{hEKm|>S%-6PxbjkGYb7b#L(|FZW$&m{jc*c*`rW)?x6a=6O z6!jm0c_zp z=W~hSJF|3lON1nc1U*V`x~dBQ;l5UnXAIU>3S0$F7@&)s5FxZ~t$8#5Q9$=%+q367 zb&md7n|SUIvX=2x&rr#CZr8$K$2$bNVen#N_Y!G-A@ycXp(DHc2djNr)^lhBMMkp;a0Tz3;g5-dRRC*Ls2AR58dt~^*QDTiw;mZJU+gG79 zJml4FS6N76F}G4=H!NwHSw)$d239Ol-^sbDZu$`bL%VmFW_VS*E=S%n7g3;!NCX{f zs>|=lE%%)?5n(I}&w4c{JWJ~_iep-a&P~Hs`bNjDJ$DG*&iWh)<4Ia9(L-$TR&hfc zKOql0@494_Um-yaVMAk z=+K597Q$1FDfMas*)*!qmFmmNsiv{g$t|phqMB`27v8AMtnR` z26CK9tixLH^5* zPL9a29O#s5j{6DQ>uL(BTUk-7yPV8LpbK4du2iB9;OT&dPKt0={^qdGv|#$piN-w} zKWhFoJRB8HrYWe|j9@r5pwq_i_knqD9oSpMu%L2|A4T=nVCzb1vCbLX%5o%?X3Y0( z1g;9`_5{^I7S27OxUxE?SYKebUcSM+1@r7IFKX zFmz9SpTe#=OPiB;wiM$B-XFG>%A+x8RI9wTAQi4n$a6tp-mfqno=sR9s`t|7-9>q> zI@FfGH}#g{2F+eu8f3F5li-PHn_FczpKRc02pGArXbjZ2s4&z-k^bO34Oc{~!8XZ( zo8Hkn4=Gt0N|AlCwO5=Cgj|3xQ>qk{UsXwHun^2q6WAg#6Uu{BR78Li5>y%Y-!Tuo;0RZ?Go`*nbYa2}QygN8G+_Z*cWg>wmfMqcu!ddxB>DEai8Z6d z6;u3@sHdOm{6V)B;^YQJTjrau=_Cv^MD1I|B9a`Yn)Kf$Zd>fkYn7KTuZ`Fa=f}Q# z+6mD+EZyV;Jqq(ba72nIb*M?8+&?UQoiOu?$Cq>e`0*O?60NbtQ0B<4pfL?$b^}}^ z4wC~`NGi4qB3Vgcz|A2)W(6MQSIN}dsu1eHPSp{;*O^YWkWb-YNe7`{TYD1-f(@JF z!$2!Epd3&F;viJON$mE={ZwVQ;xcXmPVC8ELEZC^3`0`ik-n;6D7i5z86o+$v zGfTu6AFdT@5Xat9Nb-nCk+tV%IRBAnH%Nz*Wj%Q-z&rxr2UMZ$VjGwhG;h zK3;?SL7N8Z&}t@iReFT7wWm}FGSsu_1xsb%f&fR1kX}-ku0l zI49DluwrXqjyz^&EGDWUYduA!2N#!aX^m0 zaY7316N@~Da_dCy06<|Kl8JGf7+0d>#4p0Y6Kh;*2b`TFB4uB54`7nG1Dc970)-b=9;Wk1(8fX?myjT*6Hq<3}ahVqZ6P zZQ%!3a?#6eZ#g+66dnu1VNDj}JeUJISvgRYOLYmoG%|rkQsuRRo~GH^eSxqje3ZB8 zty6f7i;KLwEu=Pz)#7UzuRILy>(9Tyh+d8p zQ|t`r(%R&xuH%XPXVL{cq=6g+jJSjDfHu9wlu2orzt*|ILClRK8MJ~4-*p8$U*IJW)BF# z(wmVDsQ53~;O8Zy1-LqIy5RUMc{&agtX!a~fqFr&cJP0AnS+vmv1k)yh_DJf;{4=$ z0SHP>G4gQ)WtN+YA;&e*5Z zEH)LN68-3Y(MN?glbSS4(SdoVLnHZ=?Bb8J4+3*46+pB{G~geug{ZR6 zreA!iB(m>n83=RoTTh(Z-PH$~rQ_GPpR1?a+Q^_1d=Da4i?W;|={32dJXPEdplI#D8(nOj z!Ka3EkMPkP?t0!g>scjkMTMEfn^cHj{- z^Q3=!w0rm0+LfGR6v~hjMVUS-xsLHRaH5Ks1sZz2PIdi$qbvuWem0iSYgYbMOo3#2 zd74*!2$wjP%vO}l(9)TyCuEqZ$Twqf(?ODA4vK9Ejn;G1vIOUFbr3}(b~Kcfil@|R zcg89A5QW6M0#$3CDjbdunksoZQW@C{HU57(21K=W?z|Bfk!*)5@np|h`W~*4$K;sG zC}KsrWjXKw)hwJZD;dk84E6ZOsA$e~b+gvh(OQe3_pV!9cBE@K-^2Pi^=)%U;ex}X z#Aj7@WVFLMC(cb!#2}a^o1%XTfys6yzv836H)6|!qY$+LZsVpC+`(-8WR8xM zZ4+ApQm~s;oui#@d8hQ?MXfPp0tK ztFpR-?u@cD*+m6TLRV>^%3le3pe(O)(FL>0GZ&={O&HSC%@sbCK9bgi$t{2QATmk9 zGvu=$wJf8gffyMe3!@#kfdBk1svWyirO~wX&Of*(B~)2ZeUY9fu{^=W z0=<^nX1zyse303xc{(}qCNnuT>g11U(IAqX5C0*y#`O@PGTkQ48JKi=s;#`Vg7VSc zOPwo1mNL^NX*CbZO!pM9I(L9J1QTj}XnTRE8ATI~g~ z-x=QAu}rj?MJf(j?Hhl%?iGm|JM$ui4(w%`k(sa|kFN%g@1`&rAR;KO8GlGZ*XD-X z2Wg?HbhL4?7Fx$Lk`IfF@;UAkAnG~4nStmYCS;=U)mvf(j&Dk_HcmD_vf)uGUV0to zVo+XZnwn_V1!L#|s@c%XWJM=C+$b)FDYQv-vU!w-?fp$=}@Nyq*^?WbF(`L)|yMIy9w zzg$Z%UNk!=b;=@9BtJs=C?x2CE#>&*1DEulO3UdQ-yjC`w#kH+N;m)}v?>47+>I<| z%h=FXw^NnQ1`&Vr;#DKLP>+an3X<^Dv>o6nW(L@6)gOxWH8!GPG*0kF7Gb*1K0{TU?w++PKV^g?=Lpw{c9<4sQj&n>Fp7$iC}YxmLMD=)EqIZZX>^7>k~T?xk|WXVDv6I1TEd0pi2(pI$vzLx4Vb*`$;JSUE4cW%U%qvIsA$K#GUs}I&OlYG4a(OO<27hi+XDE~y4(wceu zHCe{=CwfhDS`j&&z{E6@R_qjIhG<$asn$(R++XKZ3wptP!3&mbcE(8;OuHc z$H&Ig>_zRs!t*dn2wEt}=q48G^c@}cAt|c-cdj|*hyrrKG)>P*Mio4DC|{=J4>lYe zgmb1V8V?oKCw*}raXuGlMoy%!rxLeC-8+AK8>M|NrC6BUt9AKN=8vC;()0{B>X2X!~t)J zy&^x!8=_X5rHkXT!bJenGtzP^%cXySvZRtFt4Kh3Ji*$^?ue#+r8RVzaJg81Gwh~X zR~RuXqr_;*`2k)y0J=X*`q4m#8ClDDl8t;b-UY9V%2w*mvcY$7y1P9&-I7h^QT|gc zlNVDTLQTd3A0~Qr_W{hJw}z)I3z^}-+$0!_*-Yo=BN&_~)(9h{`s1{B+WrEN!oVM0@*_9sn?9VzGe`a^RxIx%7V zL#J+eBTfhWiac0@!O)gZ!mt@iqhU^{Dra|ehm7)M^5$59hbx}u7Z*n|H@uM3Zts;1 zp213nY|{;Cu0HlZ(qMpz%TRytvJ2|j2^KSQYNY|`J;QV?ITB(TK;ayivWbVY5EsrF zGCr`w$aGT&3?FTH%pNRrQZyK|JQI(XR7ro_gx!Fcm&ae~Oq4QSDEre%_L+aap3-dj zjr=dCkbhai#EDE|B}z7Ne)Pq0z}x-$WWKA_@fr9}X3(~06s5pGcbi!frJ(WTUs*aoM=^?uv^O*S>1 z?MwTtoz7H=h8Xm;mo88lN}?F5KED}f2gcpns;v5WwQ9Gyw6B@mwQK5HoA#*p_i`F{ zr5Aa)&ju?q3*--ykvD&>Ji>yeW~EpNog({3dN=Jo2s7poG;a{Q8qZ+r0ZFPO>xvvI zlDZ=&x*KGjGF4~PEgI*$(Xab{ef;z(SS&DXx=DT7v{z3-M;0x5)1RUqj7NQ{$DGD- zs?M$x5cLD`=6zO2sv=qG_c>6t`z)0?YwXHpS|9326@gP%^FDv@NR>8&crR+Aj-Z!I zD{P1GdrgYAihC(ceeO3!v`caWDq8+;jMRdt0m~&5B^DOYk5ET$di>ShGROJs_V=709R&?+}7 zDiSi@SOLPbM>2`E1LqK7A08|2*HfZBI#X}1uRa1+x!BCbA_mRtl;?c;#q+b^quejy zNhG_}9*$1>tX!OQ#y9HRl;5=&&d+1nW9cRoeD`)7WN>^`$RX9e3gTYlLbA*u{~#zNnuZm5sBD~bSiO__3S&=KqJeF(uBqgBs{vRG}lBu|4cDfKG6X8xO!L3WUOtQq9Rod zW`lp4se`*#t4fX!t}B-wq7374_U(%wU!8$=UN0(j7i_2U5B;@VtNj~fT{@va00s*} zZ{VL255V_R{g-GHA&m0;Hq?4gKGYX);{GNC%~3}_br z|L!r@(Y1|_1fA;W4mu#vdTphEcqCyD8Cicvif1IqL@ReboQRy+!A87>9Ns`NJ`wJ~ zccp$Ji%2dx$xw%}{Ygs)pMfR^m`rMs7lQ}%@kz3$9h@nWi7?^hq>hmXRn*d%p(h8O z75HPar|xsrC@-gHrcq!lV>oW?p+yuVz^3wMOpodEPmU#N)<=Z0Ol1~8Z-|Y@35kCs z-i@)lq1IS*(~7?07=Kt`Sy=_iXt2-5_C$uhg+z|6YW0T`);Ewx8k!v$x+Sn5bf z2&S0)D{cgNc^hO|-~Xrm0+wH9M;3>Ojr&iU!{NW9qW}MkijGI*2LU6RD2`}ycBWRb zkG#YWx=gYe{O>`L(XuJ!Kp%`^#%F)XV%|TR*(0ilMKmX3MSrXFdXZ`Qdmr92*6EI; zdyXMITP?nhAsE$XKZ1C-X(>HtsT4fRvc{OJ$azsZqAEsF>)p!CHAOA1npVgp<=z{Tie=ZbH(v8OE8l6!GpAN z2D&1nUNxhgNbUimP_DXh;D3K}YB*%fsS9b7Y-gg0RD{7qhp`L>xc)j0t-}wDE^CD$ zJS_acV)Mye*}b9)WF4F#eZ%&KXr; zAe9?7G|k>2Ie4LWZymmK#3e zu9>j84&P#u~YO5^}Qc+E`92M|l z>-O&A;vQv{886HTFh|jKO-t7q+@R~Xn@sS=z;z1})`|D1h5oN7wsL!N=HH}w}6vLX)AB%PG~(T8L- zEez3tvqMZZ?r?wlftM0E`&LHmG2cV$k*=bBi?LX7OnxS5mu9^)W}H6GOh)9hNyTV~ zPNA>Wxh7oR))0od$=;sI^aqD_kwX==MoZOJlK2t@tLU+g>BhHsPiObV6qyxeJc;N1 zALPO&ACTFUx$ets~am#xRNA|C_>!ZWuJ5! zHx%QPMsJjx+vi{1s@6eR2Z|9kv^Rs5teK5$($FpmZN$)x4ZKT2e}=mx1hU56DgzS8 z8#m%kK6eS^ZCg@&AKx$!RyK(a8&S=s$Mj3UA31;a)AW~m>YkXil`_2qBHY|t2aD3& zYHT&YO1)DOZ88RKb^}B6LBd0%sVf9W5(%`%oeDfa9Z-d@^6Ze&mHnQQcF;(@B zjTyO&719+FB!JI@igd%cs;|ys|5WGEeu?{@E?tId=bs;c3@<3rXD7LWMF)K|TQrKU z;D3K;ULt0}6s>8m<^(Nqmmp-yxFUQ0=7XAh%^=7EkUECet;o4^xU^XX`d@;^$Pt6V zzyQGbV`v)*J#~&&rXi6|SFlQ_mCQaP4L+vNv91YCuiYD`h&e2e(S?rf%Wy#G2loEr z;;1Tb1iJa#!fl@`24g|qg5H+|bFqtBngxG8>d5P(Mak%NH0QtlR6lahzcAUt66zA` zX$sI*u@pU+)f?-L(SH4mEFR@!aK{o`KKiR#7qkT2J&eeD$M&K-V%V}?xba16V<&%v zTf#?w%IM#7*1YiVk3Zp|v_T}uub!TQ)7R> z9A|&>&nN1(6;F1F>TdzN&=nZXC)uOtR)t6D@|RchrfT@K@q&s4(@gxdtg~UVanOZG z(m09)nOP^l6aD%x=acu^;&E%}{Z%=~j7G4ehxRAmiWWV&xYKBAWmrpXqD#X`Rj{&e zlY3zzH~%r`iQuc{u%r`cw7< z{+bsX_EGa)kRiBv+47}+u1Qa~yk-)8^XC@x+oiWq8 zM+NE$Pc47o#qWe6o!-ZtbR-30qFoYwMS6zuv1a*v1jboAX1+DSt9fb!0qaBAWqR=5 zDHO*dcm>)GZ(lJ*^TuXc@SHo5_zR_=n@e)3KW_8UEkdd9=~9U;!HG>#m~3k_-s9pP zSgG$KcXmt07gzgT4gVAM5m(9f6lPDoPAj$tIJSQk@RAwzmnwE9=2Dtqxp8Q}qLf_` zH@2okHhN>;Y-?wc+OY#mLS@xh$57DEo&NwwNi;?4LycmSpP&0CQ!iMF9Ndin?@CWa z2aMN@?sA;*j}iaFlf|e!3APo+uJaX{IC)dhnM-M9a9JUaDEw}ug9nKYq$6MLvdF-* z%T0e-Ei5C1_VY`O0tF(yV}|9N-}TfM`$P{5`M~AM8m>d^YgKzHVSCCgFLHB;lp~je z(~Mp;gv)5iliTRdBcGYb|K}681&JXCn5t*HAh?p{dhk%Jx3FrE#kidGR!FxCcUG7- ztH2-*b*Ogse;8SGP{X{8ODHTzvl>)ih}(Zz7;DV=)qkckbsV(nN!|AT~$%klQuh& ziQ4&UuvGo4cYYVMcrjTG)wP6~87Rij)x#FINE z*)3-%sV?&kp!ZgQX>}!P3S~+OWtM;NOe=l)wN*;TA%Xm+Tofx0O-d#%Fudy6ruWuF&sue^m!R{SZSExq?kC zM<*>tnrq%N6zd5E5%hdH4k`rD6Hb?k+tC<5*T}#KeYeZnT0v4MF8%=vNHvAq>i@ld zexvn+x(!-eOdb-!JC;stXXSr4Ts*dhfQmzW{j6nNN4!hn3Zn9If&l993c|t~LFyQ^ zZ3xmvk*6ge9^Qavb=7%+O{W-x2QyvL;TFuQ+AKImr?{aT(wKIb8h*y}cLggXXlzK} zQwL(VS*e!^go175u``;;xgN)v_@2b^+RohUkrfIg zKnf!gU;t1uGtPhCdUd0_(Euqsvp0Lr;v^Occ2~cu>)q8y!STn(!K_U4VsRR5n)&gc z@y)@}!BOy}TyLv!K>t-`8t1wV&CPntf;dzXv(0u z%7Pc$=Bg}$SLM99O{y&TrrZ>1(&X?CK4evpKzl_~<zB{|_T%dxUcSPYQ10L$U#-ik2^PQR>w|e!u7bP_%|ar-SV6 zEL%6hGkX8Ds>)YCF*&f}}R!Nts`l`SgHC6RUb( z=XC?GpHho3h4S;PTtRPDp=eVr|5@h6IDil9q^dLev?+hu&nGyzB3Z#V_2~p&kExHH z=a)^kfs(&$$_A?!Sv^bE@TrDXD;ASxyUyxyFx}+KbW*OfBCC1;ef#?LiolN5u(A= zjjeAlU>1MI!791VCMmp@`m3x-5QeJ%y?h_*PtS^*WSOVbs#F4aOT84cWOkLMlXV62 zQZ-wgZdilKtjbcr@jO|=#KCsiRN16nCiRtfu=RSGHiDJ9V~y!Y6V03l?$qwl(K4E*n=8IhQ0X_ zy1&M^S^5tyWzNR!RhH@L_%Hl24)S`!7@JR**}(yBLqLQxwI5@E{vExGCfwV}=-}Yn z$FIJ9`f`GQplFp5(!-QQRrquC=Ju1(S#+Kp&mSEB<>Hf3I68Rp?c{Ree+tJ~^4aL%+t=TJH$gJ<^!e+_>;L`YsSP7U%)Ecqtd{SR zHLT2xh}r$O(N#10YPE!>zkd47;~&3!J$d&0>!&|KNIv@!5lj#h$WCKm+%Q~25vt)x5vkB^CTT^Fvrw3su^Ue}u}IC}W$7k~MJrwO+P?w(18 zG-dMXgOjMvmUG;yzl?+Ve|n6<3J{@Hy%@_N>ruPlAVT20)r47f5aq?JtZ-46+mS+` z)n?h`>t*InR&79u>Js>QIZdW8%o=b$Sd_5Ia40{%d#EQoXlBr&wdp!+YfO9bnSd|)!)08xaO(P$jF zpauL@QYTGQMKW}l!zx=ZlUX+5H|})eBV}W|WCXM3ZzfyTSuYftZ0I{zbP1G)mc;v_ zv|scYeAFg5pt@E=e-9Bq%om@!FaD?d;zUtM+8kvSl~WWuI>eCZ6_-TJUUKO=IEJkb zEFI}c((vod;vfz=tjkRW%K;n~q$2zoIuwO*lT`8ISKJ=-ar*0t`b>X8?C0;Q%=Fig z*KZ0epxSoeWs3zB%-&}7_x5Tj6+oC@Zc-50+$!sI9*$*Je~%2t*d#DI;GHA~fGB@^ zmCvpM5_{@kTW*5e1h^ZpiB;0fu43Z4K-ChUIsywMNT7NE3iluv1KN@-lDw!JB9+ue zD>4PQd2_||byF0mGB6;fqD1;T4F@HZuedGPA|U>7A14GGh+d)=O%Zu$JSk=wLP*-t zZh%q(Azg28e^5wIraAmm&8|i=?(TpIoY9ofL8k5?Pb^Ciq+w9@gm>}a6I=vbC$$L3 z8YYvx0MU3NJBaDaSt#>sZhVDc_&kF;AbRJ3vLqexKwF9}LJ~te4gMx9Q6u%TEUyX8 zS7nX5;SA*$Vb(CWFwxt-jay`_8KWpgE2wz9kVg0kf0{xp0h(N|vspgRv$_u&0+?-p zp+WmEp1wGSu9Pbf{{ep$z+>XYmzUu(TO_k>czM|eEN84yJrtoHHUum^BDS?_5o2C# zUp$Mw6O5}7Pe}KHwfxs__792+NEZz@t7aMy4P>EO%TXesUNQBg#?ALY!W&qQRXsLf z-DWg$f54*vrB>EUgDRnI0Mw`m{<(qG+tfHVAlq0VwmT|y&Meh7a%IKQ$Y}N1+|$F5r@uYXhZgFKc%=7+du#^ z?YK&AV7+F9(5WA>s;q{64IMadg&U|0B(W$PvyXAMS~uHhv|FUHbPDwlb{f!NV9__A ztY@Q6QSMR{z!&w1MTtCbNDp>orMzJxO6nqLDEjG?Uzgb{S@% ze`r*DEW{Hm*IkEIvgNgyW+2^@cHXlbN5OyM9)j5+92F>NrE9J#CUC1DxlOh<8X0IZ za(hig!|k*|Phu)&)|<4(2)CZh4_6mz)7Go)dShmeon|$;qMy0Gey0pO(Zn=~7@*yb zD$2kul8ME?INzW#G+5*}um)0zEI;rPe`F0L!XVhdTCLY)K)eC%4cVyXL%6+73s)b@ePf%R+~&(A!bYlwB83K| z3MjqMq;$xKK<26EAeNH=bDOhns-Pi_>LC>g7JXhe&)UI|VJZq=kRslWQYqbPf1II1 z(mXbqJ;)n$5P|mEX2?FC*GjDTw~yivjCqJiwY5JGMq27gL=(%H2n#W7J!Z6;AX&hU zER!u@QHc|~_D?2AIHqKB2d!7Q4%ap(lWnA`V75e^8qEWFVK#L-1dd9aW33AVkgIM| zS&Oib-mi}unAtE{IBTVnFg!17f2n6>m61NqXoQNgAB+AD_=Dm#s`Uxi6aLalAtb}h zuF4YdcwJ@l3^_jOQ4{0$wzQ#codvHe zgEQy#gss|V8e|N-zecSrGIdEQY-%~)IXb~4cV$+$QmGCT_c4v=CSVg*y!t6PlQ3I7zu3rddMEDJ{g9w z2Q_EZ25w72A5=I2-=@Gb0(3e8%B6Vuo~1QH^81#iZ>f9=*lzKcp2 z7lg$@8zjDDU0+!h*-i`iswO{Q=FK*U0HIngOeIDlyJgHtq(!1=JLGX(A;;wR&>>(C z6>(~52$pgv(}}m#Nyq31;2uHgt{`o8>7iRoe*B0#+^x*6s5s3)fBlR?V7mbu2$8?s ztJv;x4{c5cUhZKhw86gIA7mdDwj6@8Ra*a`@(m8~_{U9y8WIUu2n>*0)yKW9C@sTN zdjOF`EcNoL4=Y&gwtLyrKSKd13jo{TnopWilaNVX%*&P>>@_^nhH=ND!y#uWK`4N5 z6a`(oBoaO7sA0#Le};C2?s=eqGxBnfR#eZbWUXc2B0!%Z=;e!SWQ)i!vpMWPOLBt# z@C-qHTK?;7TL*_YoWpT&C{ugb(v(9rb%(SBhcF9=e{JRAF&hpIu>NHs%t3dmDHuFt zQSfBs$|$siwlkP3jF2^WemEH&bm@X^LlE^y_y&a@kncKKf7KXXkX0b&&p{IFW#O=< z_i;Q1+3bfI=cBD>dKvx^d|SZuN7F#|l>dTcpIqzhNN z>9&B6jR4dZfo$Qy!lT&Z?|`4gtC1Th(RG1$Diq{wa0Sf$TC)LI8=Iye_7U5jZVR0L zhV+L1SO0c^C&X3&d5jJWmzS-ltEiZi;aZ9w>S~&|e+<_HS^`ztSg0s+Ns`(sclNwF zR4fcfqaB@Lar(HO0rEtV^K)n8=V2^G(J>R=mmmzHP-ibJ;jVV^Al$E0IS*&V<#|k(x(q z>1(=Ge;@JFB9m96?2-@G7#eLI=ow#k8+K?a6z-vJHeH7PQQ2-R06yAY;D~C%nD?O^ zxN^;YNYb}9;-JLIktXlUrWmBddd+$pvZPl4gWCZ{-1L)E!9fS8I^8H$6jQU>KLSRKcY#s{*8naf1f)OPkfF-3HQPvQ6!%=s^>%UTHsPV z_rYz3NOCuPRu3=qxl7p5xJFRD06HN#f-WeNp=9SX9iD^KI$?n?4DL}eY=qzJ(j6yk z(Z-^pRH1&=XT%e$FUgi-=QlK&>6U!qWCm_njS-hDx??qz5PPUPZ0JWXB@QhKPL3(C ze;|lVVRl5~K8DqeX`{2TKX}3>lx6Ew!akr=7?d+4BCo!EeDe7hW42>_|MllPOc$N7 zEbIfvWz|;+KtjH}NpyrY!Pmi z>#K5^*3?DNFD>)jVwojH>uu7kmqPGFg)g+pO4;yCi=7`2gnwg`@w!|`OoQ9$SIVJT zL~U(LmD3^8YE|sj#-3<1`?(ah+43r-U0gRh@O(h+6L>mgJ#x66#KIU67o&X}f1|fr zq0}E*&w`K-!X#abFRJ^1*;!g+c zqwQOT2%mARL63VbXB({*ePmgtf0Y}b1Ie%``A>{K>ShgUEKyI!j~M@LdSeaR4uV8k z2GPU#!6?KnxX!ApWZfI6L=RVabQVCZaqwkuf`2~3ub+-Ww;RT6oT4G^@)A|#%gZtP z1j}3e{a6ZU$Kzn@O^Hq?p8hlrerT;{cLs$Xg@SCuuDQ(!oIfQe?CGWHe+j+RE>IMh zU`)t+E-zW`4C>A7s@tx$vNPqOSL3(?YpX~raL$QD#%GI~Rd;ZYl8@Rwn#5XH60jm@ zVb#3~d8M~y9a!N6b#zFW6RXsIlCW}l5mm9b9a{&H!l-Tp(Y<;UjupT$@}?}3Z=<+9 zkfI=IulHFS+@f@aDzh*x`<=S~+YSR`3`&{%YU%!ujN%lTXf2MFpBY2!w=vbWB zllIqP6_Hj*g^=}hWp{VFgRZZ04$?45TsR28dX%7p`vQnRDdX3A)?&Y5z%?W7uS~gC zBnouk*2r5{8{V>AD~BDo4(-a9TC?mNEve${ZBr$lT`i%F{4>g~^3fwl zX;apOC|TPR3Y}C`;a|Uv=({6f*>bHNF-)tFb^t2!LNGhjiq5nY-mZCRmz1y5{c$x_ zGHlJCymKP79Av;gzGZW0Tc?wg7wF-C`QnK>fFXaK6Bw_Je@HTntf_;azW?qRsEz+6_`g;`P{{ZgShwAX41R0vi%hjvDEjDs|7enom1QFCOk_E`>3fIf-h zAAfueTikNb>=T{uN{H4OMvj}O#g~D1!uh$;)8K`Up5|yd5M6nqVH7Yyn^|u#9+i#k z^7TQDNmt}-_nP3GR5f7zfI}{5~i2Ey%`NdmFA1y!A zXUU_TD!UYn#b$w@&)Hsa;V;-S4=$^1lK$dL&fOrzf0@$CyRfG#zyNQ{Dy^+L>Lrlp z^NXH}^=7p~%aB=5-Z^cFrNdODA_b~hw2xQJVDUY`uNfJV@_r8qB)M)ytt-+*ft*-1x>HDdCJJ8+azL(VR(TgJ>9Jh4rgrk|2Sl5|W zf885|QOg9Y($IGx>no5)y^5bk=raSohb>mzw`7TXcpIdq{-&PtZW~jos0}EeyhYj# zD4)8edvm zzU%Tb=dn|GFA3FO%fX3Gp*^~a&mNr|f1dmyQZoqZuJpzq`DWXojH9^gO%v(#WKrfA zu*A-nwT=*yI_DV$If2NNrDE|j=s=I@2lQEg#tl9;M}?|PTm&_pv*NgP9gptGHU#U3 zE;KZ$)=Nz2hko}YueQf3n4`)T*;_tp$FUX4oi2tRv<3@2^tl(aE6n+k7uREbf0VnX zUmB)CS#Wq&W%I)z%ZZlft5uffNs~d#YxH2ISt{^K`&aHN31&2V^4_m05Orvdt zlUvC7GJyv&)-tJ-IV&wUC~uNzhgmRSu=*?8@70%M840kF6i+k?IGluKRxALPctf+d zIQ{KmhzX7~urh|>>_^b`H4hldwmMbOycql-^Qe=gAe93Y$! zum4=4-@MqSRQa*UQ7Wg+)8f0Fi(*@&ncriEOdIu=flL@m@-|~ETrG~ickP2KO}wxy z5JwDfi8R!qvjlDna+n}`D04T#)1<|ua+f1K|2aAS^}+F9{`5aS8Q(ws>)BWT5g*-~ zym|BP_(JE%BMATDWH;1He}bf7A2m~Ev{nh`Xm?>u+5Z&JQ#Mq7*}i^9+yAtH9f^8Ul{0!cW3IWfO{N?&~AIk-jHiyo-Noh&5+Fe(JVCX#z8u2t*CaYZt;i&cixoCeMLgA42zLe0)>i@slSdPRP#SF%5ct%Z-ZsgU>|KK6T2BnP} z=~1vKOO}Y>^EzLLC<~H%1East?Ja4>%Ica_UJ}C+5IxHc^em~bba!x+t?Y+fuWHZU zr&+RO!g`ZbIo5r`9PjvP!C9b%7S$>pBl1Q{0n|pbW4f&+%uRSoIg81xwIZRYr70n% zW`+W?rqff(f7KlS9scXDaVhhHUfBdai7_gjZd@`=s ztR^^ZFp9H>58m4wseX5zkyTkXu1B)VCZv}1jBCo5F%wFVJW|XhMp0{&XO>q?lB?8l zFS#cC6BUY3PKTLAAl^zVI=5Il>h#K(A?_Kxm||*;e|f;KH9ni!-T<)ysfW2pr)v)% z+}TY#0WHy^c)wU}PTq?DJF1yQWge zO^ILRf9&19RapfTu?18>GGstPIwnnxIXNwnCfEv+HX)vGfY<{uLY@R_Uf9qcYrARy z1Hws%uW1L)O5lTe!5JDcB^>#HFqmDT@-g*|M7J_%mJ1Lxlceni8j5XUy>qHK zLRoUvO#nNnJS~nhj}IT77$nVUc}T8)Eu*2Fe-}Iqj@F>rH}mW0ymXvahXrIPuR%>I zFa+mN(gl;Yy(Q2THv*b_z5=cR&|$4{^8z>`lt2f9D31*)NmxzdcQ$2~IvUWI)JW}^ zMY1|kSWi+cBr4QET=#sjwG=!rQ3KmPYuFOYJIxk_8nixron))Bh-@iCe#PVFPU0P_ zf5$4)tTFY|+XTqYK8u%u3Z&E^LuAlv6GYQ3v{&$z0r&~<8AM>tTZZeXVPTufYO@mZ zT$g=W+@6CLz!_TG43M`d@|0_~l7N7Mzwnl;lP!xMrf^5y<+NOAv(FL~q@;t^61Jxw z)tq?LR!s@X)<((Cxt;d{+3-=>4z)G0f2>`u-`Cy9QB($r@QhXibaF810@i`Vv!LT1 z*y+>k^=G!Tfow@9*X#b=^0c8s4yAJTk1w>>j*29H$FZKFM^!P_&cu&>$~hQ-PbWRR zUDevQj>8Z(ow0I#x(L3~^ghjyGH{%iWo~%`id$Z6-cF+YP5S3A-o5?v7n3hOe|wiy zE4scp9*G{^AdPTzKB_4*pq zp0mv&ptCld9#}y-)+fA_p7fO$jG36R+Y4ppvV$3LQ_euC(1~Goc2;G9DcUqJ^(Jp9 z%9A<&6RCp+k`F?C`+^rXmC_>I4_QUoRCf+SkK-T$(dKN(WYn1iuDuI@3AE{q1t?Gl221I96Bk0 zHdnHJ+Gja2fqy>RER&9n)yNx49ZY+4UQ5jL8aOBXpJ~*@j#^9R$r9nq70x`cll=XY zeqzcFzHavSPGThC)wWVae_1Si+80hGMvUP=%ydN-lfFY6eC~`_{r7-ZN%9*yymM8q zGDHA6z$4qpJ;5_L0epI^h1WEcm|y1+oWu9KPG}GHAO7e+Q#wkjVgc|G;--cb;p{Ec2epnT(6hO{l5o7=Be?w}#cMTe+NJ8H= zUM8`?Hg~3(W6^0yW#Rk)V(tIT$m|rkxh}wB$=bA0#X14EA-O4-UE2}%(Xio$phvC z#7F{Kox#&^#8zbYw_3&UiM8GXf97MTDCnoKxxzq)BAph#D?JhrOKIMt2PPxt8ERc7 zyN7{Kufn7Dv);+QtMBidr4sF)A&GhMU1WEvkxAuo+Ur;}e?DvX@aP95mD)e#rdN~0 zK)qYM#wz7_WiqHIHzf=SsKTNSPLFqLj=seE_y{xh?&u?Xm0u}K4Pr2QQ1b>Yk#X2< zoU?pr60AwVE?wvECWVz`7(kcDn3$^0F>YO@s?3YyRkkWYRbh3$C7D0{^i%Nqhp&Gi z)#FrM86l~%e+%@!wK@kG0q`I_h0w#QZ&qkE0(C`$qX2RYeYh=AT|piI0t--8Nmq-$ z{yCju=IpxKFsx!SaQA9xMTXl~?2XmNNb$k`go#w|F)SXbM7nF3-?+(^bXCfx$eS(d z;`hJKZk}L(dUgM4Qg5GO7naK-Ia72@cjFxci@Cc5f4gz=R~qS+(diWuTPthIJ{{+E znpc$YR$a@<&iRp#2`PI|$6En{7GLIvmlTGEkKQ=y=oobdGnBW*xLnSzRtlDX^%LesI9h$}?;~Tn?2kJ7kb{P0|pVYrq_6u}RE-Ph? zR&MAzfBRSXc!pH*I1^thCb7!tUeIP6{??@py{yt6z&DvbFx_WFlezPrT%c>nl+V=k zclp71+6F=}+_cPqIu1d~zQ3ddU=i65^zC*W@UL9euQC4@Wew|-l{zhJ>5eA&}we7c7{dW)*X?;D+R#P^I&e@3XF49g(mzE`WRy!q#<_Cq zccb)M!!RYdjbV9Csq_psq}!$Yt(zG6CU>|hd!V&kL$k3Oo(7{AMo?T|>74?q5#Fbc z^r#jFW`gA+i8kDEYXEsbhQIV3S`L@!Dio;|MY;2kso>BMFB$R@UIeJnfe1HEt zoI%&|Tz@9v3|imV?1{5h58`x8ftVki1)n|mY-gSiBi{NOC)COAcK-9Di;o{g=RbdW@yY1RKY!9aKmO=RuT{V{^_jvQr_o)w(p*n| zrXLIPgh2mLG>63u?gc%tJyD#-WVgYbWGC2Jxj z#=lPLXW5yyl1D{8G`X6dGL=-#Zn)jeP=7Fx?Ef0w#h4|z-@CVnBp7nl=UQc-kCBIS zN~a}i&|mPhP2#`}@8qc7alwKw`>%TXUB!Mcu>jS^ZB5v^P3)C5_>U?4 z{C|Y!=Z}i;6qfgX2ye)Pd_I`-O@I9U7|zns`(%uv5S?Vn7eHY2htAkUPNg<^iQI(E zcc+RJRmxC36UtybmApcyhqk_(ZK~8MC7i6K%n8B1MPJK^gG4Gc;XZA>Gl26 zS+A75HFblSrShy8SHkISzybD{f4u7!JZhak(;N*6lHdmLtjOk2E!|MGQM(^JAle<$ z`LUDy+{{`dS@hfNG<(oT8GqBQyEv}f4#2U$>D8;Anf zms}mEs!g!&Gp2M8j5$-hhr*8rmtghqr@qlo4+tDC)U&Gn*0F5a`B;_w-S&$X{Uxjc zrCSXQkHk^;Q|xqZWuWo*4sd4Z036SSZM>v+z_R#i5WBqY$(gM=Pyr%zUDO_+bs8`E zzIpP{xDx*^ux3?TrEkN0?9SV`p|k=UPP=1j`+kVA9D+NwCuXAWlc1kJpdSt(Dx=@2 z1SpDJNa=VE9A zbhA=_Hh1;l8H~3SMW4wfC}=6at@0*wgs`#xuCsu7Axisfbc;Os@u<6V-|%{k9y}p* zjmLZ-oCNRF7;_qGs?ndK(1A~PYz%>J`+a_W5xfIz9e*sk`#y;lSRbr3?ODv;SyDJa z^W?$27P4L)uHkWV_YS~5PyJ^i^2i8KRA7otp)GvWB?EOr-DKATjkGv*YKxg3u=)mA z^liq@EOn+0Z)TzJtGt^|kzpmums)ct;@}&)7&Ji}$CxiJcYRSkpyX^e=W5eeGD-Bh zHLhUZ3x7o2%X9)&aXcX~w>3b{IO!F@xCLduD0x`?rY?Jckx8lEOlu5zE1H%|ioSvA zgL3NzCTOt-)-COH8k=&)m_wulC|H7S`om0Zq_^~ql0yjSqyk={Wsh2&?JB$WH&4G{ z2FOSvzR1`*te4AOgs{jBM!DhH`yN0~e_wJw!*v{uQk(R-hst=AZONs^|vMX5FC^~}NJGjntpo5?4>A zTOx$#_)o`J+?G3+yI@Rv)u>aRE<#sM!C1|KO**a1UITTpBgNx^M5|&5qO~_Qu?!#A zt?vD8Ok}A0iu8GIaxbetoKGdWd&CNoPkrBn3toAduAyW zVbB#z^yE2hSn{5_W0Wzr%6{p?SUx7LW=_fS9293=#_J#(f|RJywp3e)4u8dP8Nj3V zeR~P5+hk;>JT5)@sdB8Scmx3uf6o9ed#sin>Cw24wPi!?rK~try1YILQE%33N(1^2 zZgtO75l3`z5#^7hIbPwB0a#bL%#N~BAyx3*mmu2#$6?#jM0%AUTU0@U zG!ZfP9)FL<`ScM|xR;C}^0%Q@0D2YL3w9z)IC1App_lpRvdM4ETNC}E^RjVWV$o9nIXA_z4NQrwwYM%8QR`=SI@NC<`Km zmE2g-C!`-BOVSy8+4)#Y8cKZ)daJ5Ne+&2~b7gFMqRZ&t9*&Gn`3;4ED9@D|3}5|z zd8x*8c?o@}G0Fy6Mt^s2)y7zG8(v=0$f25S#=1)f6l|si?aXm1U|1z__^bKFDebT# zYNi7r^a1D|evlj41>v*9hn#wcA|3v9Tul+5n-W-i7QuWPe7qP=Y)jXsnP$_FOnm z2Q^@K-%?^!y_RiXXrtI2&Ac`~#~Nu_nbdX29FqA9h?NAs<(Zp;XXr_aD+~`kZ8BK+ zad0}_q4duwqPtX37p7+Ys7qGMj|iSfm!AD>ci zu}NfXNum8gS$L?DP4tg~Q!Gdn2SlU|$VZ3+=s(G4Io@|B$9>X1;OO(BIKq&L7@nFD zGJi%N)9mIH19;8e8!@34_b@lMd&v#UQ|i)2pOpt6C($WyrF)om$*ck$D{X68S0Hd2 zv|It~jIjDXNcKFB$rg>z-FTzkpj3QzA6OT^37>g2Iy_{0wLu1Fpy-z zF+xx*a>w*w+evao$`~s)c)yZp_V3z57n6=jfZDX`GWYTp%v8a;lRGk>Ta<{xq?TF zwM>0@uhtVHjoG8e;il@Q4e)T|7(F5?TmF< zzDuG|rvyC{X0}RsTU7RAQ-<$FnY&Fz_kNCnj_k}HBn$Y2y#_3FZ3h=ldTgrvrhtd_ z{1t}-unG(eJ<|g~0^eE>VxJeo8G3{eMqNt3BMU3Cn%#C^88l<~p5-ygG=I@9-otkw zXBHH*=$@6aWAK2mo0Q;TtzxeeU2NG;k`ueK zLQ~6;#EMI9NUmfx@pnG}^P4l|uH^K!*LQktERi!932Pd2tTwt}bS;;zarubLowItV7)JCoq#iUqIlnya!1j?0VYe>SOD@Vs0WY0_k6 zF@{dZj0G*SKv!RzVkdc3i5yj(2Gs;Pq{&x5(qVV=OlXlJ}V40gsl z_@Bv;P?(Ij1NL#jf2xcI%m-t{VB?}H=Rq7_ESqJ;;yB3W2sc<38IXjBe&dT{BX=IP%rUH-$uZBTQzs1ene}dJ+pkW^y`d##zC)G6o zlHIZbX11tUBVI2XJs0R%C9@_zzl*Qg-7vUhO-#?k#K!_7*&g55vnyE2AuiC9C)@G& z)1%{qSBLS@bYlZ&&8lEePJayTU(mBCj*DatbRPgAW_eQAYV}`cbq#H&RaI6|n<|6d zjR1aN0r!E3e?Kj=ilv$jvO1Xa-nhbTz)#EKBF|>cO2|#a=8Gn1N*E$Z17OD63fRG5 zw~Xa!4Ll2rf%{-4ATN`A>>K$_QL$NhS!DlU>Gzz1tB`n8To>hSp~sYzFP8IjR(Xdx zC~lHGOIK4)15NTJL$YPOD?!}~7Rz&(PO$&_fNxEte`}d8fwkip_8sh&z2G#I!-m5k zeEr=w@xkHqSMl`l>8oc4hu>HaUms1MPmhkK&m?z*XE@BX;L;~p*074W=}`(muMzeN za4*#x4rCZRBxw~AsujCn6>@7USf8t;xMV3bhcyMk5R}D? zA;Sh=e?IvNr(bia0#F!$xx2k$utU4iM-)KF00QxggTpB`ICvZH#1nW^G1{kqd=$Pf z0{-*<{V(CbZVmtR^$4*2KUtNRYttwY4{zxyDh7<#+Kife{(ikfQ-XG_Lm@+EB)JugrNt*i)_Y< zn!z+S;xBie{Mz#n3pUb?{w1@6mQQgLW*`%&-!s^?d6}f6H%Bkf2eS*_^xa{uT%U^gO|0i>f>3y=0tExc%qCtv-Ct;x#-&NlczUkLq|>|m^# zf75r(MI516^{?dL*{qT6(vARq@!hu~Rxmq=oGggh{0qycedwRaX zhcgY*ugK;q)4|QE|C+C2E5WVak9ae+jzL*3S0tcfsNTl?m*J+K{+GIh!p(t-h_w z;u4gNtRVG8>Q>|6pqS;$lmWP`k#Aw}oCU(T0M#TfZ&4=!r3!w5W)W&Zp!mVr|JCn} zy<+a1FMt*XTaQ4m1>~F238?(eNrF&JB6fGg*84AB=rL>7L<95Lc)5U?vB*$MfBf(D zao_P?9X5MreSf>>`lH)`XP%9QYy2T__!VkMzIoa98mcm{ZHD2n@>5E0#OGc09c_ zy}Ei$e7zJE-Cn?M5p??!`C$TMe-8S(14kJo^`kKHPFF7!y{eL|W~;3pNmohvb5=K! z{1LaUw6*dKHuJ2Z&4cX}QYl-of~<#j)P?m6K}8+LU^pvR#nl~(v>HX|MIel2G_s1a2^LA! zpiK$*O0SO?*rbL_Vt|Cte-T7xZ8LK55We`rnT<^o=k>T^^YVs81Ylsb<-Ut?%FdUU z5y(_*mxA%Q9i*@ZFu_NtH4q^?kTi@Qf#lBTBDu3Bk~`}osilBGa`L%IPS!+nvNn>& zQ7Dl7@^g{=a!n+^d@z!e^_E*e`OTiKtM1~qIw*n(`Z81ff~yLEe_C<@Iz({Ak`%x? zqNsc76Nibqr$4y|BN+;cnEq#O$;p~qa^l;PLN2wTlT-x#ybgX^CON9!%5PN5Lq2Ck zn?5 z{H&AM_I!qpZxP^xe~M;YiVN|La(Y>0KLLH^=~wf~adOr1PP`-CVcz8?Zg9_F)5S5+ zuqMG?j|}RBrHx_*Yr^sB+=X4R429W%wH@sBuyhwJ!-5$|_5uSj;$$0u-lhJU7=KNy zcQE)M__M`)eT)09TylSER`BZr#1xN&-vL>F2UGYR?rP32e|phxS#XuyFglQDS0$LN zc!RP%MCUi%q`<$>SF{d*8Sx~98N&g8UX|CZ2!zos&iivn4E3-#y3{BvTzg@w>-KqQ-$%RDW@29SkjNpTm{3pN9>G84PS6qY^i zjPFgbo1MDnC<;Pzo41 zDLBSC_y6!`Mz>b$h4l99I_{xRIrC$)f0fTuB-?Xu(XQb*;%`#xK=$~O z!fWY3+BKa?{M}VKXE8aHb}jD`f17X*)2{Y4na^YHKHByApTfCzI_-Mga>jcN$8}Bd zwz+Um?Y2Et;Y_=yc0JzZFcl7~cv;a1wgZc|DWwxDPSMk{+u_y<7s8RFnzg)Hyp_1| z)2)0if3C1b7fHl@yaIPcT=7Yh8ly}EoIC8OcJF}UZJKe+`f1enyOz*MnmhHR0F>hbYTbXrSx9fWC zTRhc*Vmg33eBqsJ??p&CQcaI2QS0Q*>lag#WajATJeG9)6te{*>7 z^wl#Hg!Z!AZuAcSJpy@oaD2=!fy;9oKEj934_-`<_n)_1fZ^$n`=h@lqkn9V{xClK ze?oiuFlvFK58!ZDekXh|l*YgiJrNYlfsgmdd!t=aNBrbNT?vItm4S9bSM$)8t2^>8 znxB*h7Zx~Dda5OiCXUb~kgrBC+hoBn!{^G2mD&AGCFD8iW#=V~NPtmUk(Lf>Bh?ag z(-O6vVwB{ItE5=YSq0h&^a{tJ0cUoVe_-GThKXQ6L&f0eoB6pn*n zKTR{7Z-Q6sFpL4FUO=x}I=dw*JUk^hXRtEN8kn%&3)BLR>*aX_qYUYdHfNM4($`cH zTOb{U0W!`w91JWy{9*h{SgP+qXhWOgU@lZf+|UUdwB%BhJqoJw?Xe^o4J zNzKG!s{kcs9LSg?S{_twBRJ#BQA&g=J;xR&^kzxyaNGmOAEcE%4SI=GrX*r__ z@>>-?427g18HMW;9lXghZ_w!9&>r77E3zhzqnhOxLn6T*dPs+Xn6CIs0Ofx zUMR*0ZC~suf>jU|urm-pOEBEXBOClFn6&hGGTrdPMVMa|_lT+8LM+Ulpny4RVkhCt#g6vu1OiDK zVLOd7c|hbGSNA5=BhkJEMN+39inu5ejR$T6&=KRdbrKCU3whsTPlE}}g*bKXnlqGE z*42jD!5Ay1=raCXu&m-Le<7;S?{8jL@YiGN7=dI%FVOqK6mHbR90X52yi-uyf+VbC z;1Q0{G~xo-=wEyKyQrC9Y5_*JGNGj`@56?O5sTx2(+va<5R#wVk$pTg)t$`*0Nq|5 z4Nva|Mxk*5C@HiTeH&H2bEzR6i7Ut%@dLlGcWqfY(xz*U?Y<@we^zTR7U<~^2pIRM zUe|&W!}uczkN@an70=o*4hLg&Kv&VAJy*j8pg2e#so#JYx(c%svW~+I*c|@MUNV1$on|?#l*VYlhg{%;k%^{D5#yUBB?gk%3Uk~K_2!$2KFo>2^@Ah znyE~LFYk$Pr0rclgS`- zFu(5Eq4EHze^cf79Z3(=nch%a!4Frgpy>edD93h^PUQUqlh~oMWV7 zVk2=Q35d8M8ctM%)zfA$xA&I7jNg?IkMnS@g1J|)g7QQWJP$E)o=3O1*RKu+rn7~t zdJe2p>vaY_rAV`g{vOv0P`09Q2qrNRQ^k?+=4TElf2F<=R^o7}ZM@w>ijzqA3Xmv% zng}K#(C*MW%tg;tlYs8Y#D4Z@M|wF(J5e zZi^)Vb)79@agpmgqJE%E6Kf00Y?D%fSzAoqK0r)KYlP&Kjqn4cmI2K&Z9oFuhZs63 zgfhJXekpo;I32k zcY84WSuMtT6l6sm%kVVUMeH097~{W}SrLit@5-%yJY;A{pGZ}W_u2t4-p&0`HQc*e z{1b$4|KfqJrMDE!{pXZ%e@eIrX<+s`b{qlrPIg;7kcZl4iSW#D zSx~~(u7or0@#E{;q`Ita32V=kl^djUVjCipKo#fy4!L ze>;P2sB_nKc3CidL!ia0u>v&(P8!O$qK`455^(wu>FCe_HW4q)xqXKbrId`AmKcoy z0&;d`dwh{=D8DXgxbgzy;IVfnmKo-wz@=b}!NkVqI_Q^ZTH@(ypydr{v&~8^?K=1f zL3)e<4Cb<#NDP6pg~(>Z+u{$AlB77mf1LR=g};W`o|gqIk?miE#Ydw#A}~X`;IG@l zgrZb&g4Ae?O(KuH;banAetLb@XWtV@n5cr<4erJ!1n2Z_XksTg;ly2Fh4-`9$p;L9 zxdT;6T6;lSQ=8q!_pvU`2}P0L%cJ~1cv7ev&H-|kH7Opg!>>_hLIWNK5uWEmf1ZCa z7`QC!_AryGJ#>?*?CH%ITP`9YSCzyxv~F9=^`9RK-kHsik)?taw(uUOganoD519OZ`@e;y>{ndwq@a9EBw5G$spF$s89MK_Yi{umBUw|$DD z{1M~^Sx^9lqt15tvl%|3z!SVJ74zo4Bd*obi@~Pn!p!(F7YpP^`#zUbCe}`<+=_Zxb zdl1l1N4`g0T6#(H>rg~mP5;J}u=D~+1S{Ia5q#<(={Gr~@ZtxT=dz%!nOF`o@|a6Y zz;aq!r>nRT*^{v?_Cfp2=bo+YSqrPo#MB{=yjF+RlUTXLk&Wco_RWsVq{5Xen%#HN z?4>X%>>GrWTt2k7N0&Lef943LgUY{?+#4wVv~?SgKf=)JIXqg+w%YC!W64x60P7l> z-6rf-Z~|gCta%L{9pbfW7#s(VAljLyJ7)v$(nI@=jz#J5SFFD-_f}_2ZZY(=jn;e5 z$Z9v!u`c#Ajy7w2o~);I_-7ZkXD`EWnmG)c6wMe-P!0f})BO!8f7kq`ExXVgz6?<9 zL4Ejp8SDjGgb2h;@9hNJ3f{hb8`M`A%&xQ)rsJ0)fi`*CZZQbIOkf;MB~f!{7>EOa z^ZC$H`H-E^u;PxIc9Q>q(w$U6pYuCeoTa_O1j3MD?ve^*Bwu0&`-BiQrcfK+7M;qc zXErE)BNECMPOTxzf4d1D@lZ2zu85{B#!k~*jzFGvX_WrrV5IQN&Pq8G$ zry)NSjB%$k=Lk_#Yuh?cy4<7WrMHuoi5Pr0IqYH_pQ}`N%MSru@2G9HS5aA|q5mp+ zww3DZc|m!>)`D}1G9>2&7}GgVE{-C{5*hmEI#^3{irPBze_Fj(smAvl`?H3Yp_-mm zRSr>~CWAlL>2ayAg(yJJ#|Zx0C;US%Q?E8G*;?+p%^$Ergn)}UbM^R9y@~N!mY>vM z@czw$?BA5=!jwl3UM+~mJ)sZcE-8`0nuZtgIrrHoSmi<$&f@AM$UP7Q%bMTCEDKCI zos|_EQ6$hTe}NZubC(;Dg1{mA1tW?#mb{jJnsvVc#ZhLK%)loSBe@?4~k)@#hdF@s@3#nb?%0E zzKzgacG z={wCO_q#9U9Lzz^TGr-@{j<}#e|9?d&%#LhQVC$a+;10X>g8KI`|R_$V&|X673&Ev z>HC4kT7gN@RHkWCCW}yI%tvkn?mgB|hHHi5f6fzgaFn6*7__>_0cFQgV!9l*b_lCf z%vK#nZ}y)@Cp53^{bm{`NN&*2&e=F^$>p=)i#>}>GL8SGPLmN&D3ylt)REkDef$`d z%?e!(hAv5Wn63NS&HmGO z{-*L_=oBAz^5y8?6Vu&gWy`^G&gWCKa)?-2fYx;^^C{^)OKk@zJZkIo*;hl9WTe>Oy^ zI6e@N+|fO?x3S^zo0l*5kKT2RI{tZQIN5&kU!Np~?di#yC;aU<)5Gb}{>du@6Q;bn zbPzqN2guWAt#S@)|L_?$eiwf?eRr%%Lg0@q^$;0Hno;V(daP?RfR#dP8V<$#Pa?VY z@Y(dO9E2Nc>Xu2^HGzO)*HI#ie<%n&JI%750%^IzJlHKTLQb8fc){o7!{~l1Hk_M>k#Z6X~ z1)Vi=8prPrPxjx&-|xRTpp|YdvZwY()U|(xu;}KhO9nBw%+Tb34$g7GfBL%^T-Dkl zzAl2%;<(OBphZjz7Ry#a7|SB)+-()w=ih&PCaTDZ_9c?W!n|HT#dJ%2SYVN!{}KN~ z&K~?G0gEip^U5?(C$?E5MLtC=k0F4_G|^$;3lMQ8BU)RHL@ME`%9mXjDH66)&?Q^6 z5ZvpZi_Cx5K9v*?iWqDrTjwJ`p+ND}o>6A3WW$1vQ}VT_`r$_o%3KY$yEL0;Xu#?#j&=q$MNi(E%kZK;HzFlERJk zph1-3^?2fbu%!bIS2xA=D!;As0ybRUHUQM2jq$OFh7km{h}Pw@nlVw1D{9yA zC-tjErnX+}`w)WB?~_z0b7Q6&Z%@uQ`I)%m-F^&Yzud90- zd>vYvn{cG?fA_Wo&#zH=y{0cl@%Q9_X`lV3Z1J9l`E|EyfIq;WJZ_C{cS)PPHgX2= zoaK+A`$SGDs3v}NcCV?v|D zF;lS+QT-~kX>%o$w|+L!h9Qu$1`I_-@#T1ce?j2>AY-%(Sy^>)yqSzGJC*Z`Z%6)n zt5fkmTa_Y40fSq8(UoyN>GgD-=GSMAAi|%vF#2^>nN^C6mMHQ<+lOIC)r++imeyec z+$h|-mX%Sxb{%@*N{$Ik#A=`+~?Dj ztPP}tmrjl3bW~R0Kvq|~U30cG0pu>?e}noEk>SvFubTE(i4~&Sh;)62hTZk~yrk@< zphqyYDQR$+rkX#quOpzTsfYaI+O@dxW5rEd%QOR>zs5jmUU>qYt>~(?tK#w67xd{C zjH?hI>6YEGl2OuR^~D`IdqGv>-^+jl%DBqqwR}G|+VQ-*NUCJc5#9~<$<>A6e{1>u z!x4IhL1D3w>5vAn2d*$0L$+=3OKsw!8?iDlaWLS`Occ}vFn$3Dhn0`dnas^$bz@en zkWh*n0MRjd`aGz@^_h-t#&SVfmzv^|0_imSk`qp8;&qC861EEkYK%7UsAIUeb`r12taZr#NoJOF+f2!+*Gnem$ z_`UH`Qd~y%lLD^-~kowwmQkqF!kQ%Huf3_!BAMC9W=F(-rMzg1ZlaQvTu(27{Qf#BJ!9n#i!ky` zRiRs#v3*JImhYMu0^oLFYfX&w3fbFTj#d#Bbtk;5Rsl$>hvy%DTqS57toz&*>%`_b z$=Iz-)CY-PK|uk=eCoV=Y83YEfO!J6=91JkNP9c1MWzKCXM=;H9YglO z*s--@#&oP$K2O`cX;PNjY*F5iW=ykyu_|x3DkR28X-%C^f1csq=3fKjzS#s`c{v}BZMMP(xw$Ezy5L-D#lBw}@3hcytuU1NE|KMJKYsuUJorKo;tjKVY4`OZIeW}WVQ zFS+M?E3j1$Rm|;sK1;F|SQYkK8348{>NEhjEG~S!5>30Y`?;#MPz*~{%MPXk-& zMqlX4f7~95z(g{GHwT!%OP}!}WA**^-J8olN zV653?VpjXd6xv-;S6I|fsh3z_nSTrqG|<`@z^huC-va1N0^&Tzi?_6DZ;YyFDKlt`oMF{FMmdh0wF%5=J`H@|Jw&^U}b$oLFQ$x0or?o+)qSJ0lx#Q8`};6 zB}VPc&!L2abU9x{sgZOB`p&XqaZ=B+jM#Mu!U|pRdy_sR6*nA3wd}cuvma~9<}p8a ze_?#;LME{Es- zWoET$JkAPKC!+140JaWeS9q1nwQb(XTDtxSexW!16}K@r`x$2%bhpCb{3Q#_YO;l> zG8sli$xH2O{Z)UF*Nh3E*3ej5O6_w|S3;ohg8p&{E0sh1Q96t1R#A29Wu(IY0#Hi> z1QY-O00;naQB6*_$7>1V3lVWqO-@hV&l9>60090#0017Be+>;6m(h0#6n|i8r%1&T z<;NzMn~I#BB;#6LIkw9)&U(-GsVEYX=%Gk10ggtgtNZQO-2g~{q%`AfXqPRLK%>#` zZZt=1`puL@d7NaMb5_aq^m}|V7!5}3=e#(S$!05=|MQqVd-C-86#n^^{g!0mfn9}P zk|Ka%uabyog2zneOl~=Qdw-DIJY!e+TJFP=vzK|5#i2~#8T{ZS3t_!XmdUD;IoxeZ z&UZYM2niqiUI)B+rSj;7l>YkymBJg_*ieaI^YtC6m;=@Nw3gf|ns|f5J8#fZpL7fGx|z1gUe& z;TG`NP6n)dsVO|FWVlNCgeBSXmS?x)!2ov-6rLLr1Tgd!J@c2#EZp(s5=Je5xqNx? z{?+yJ*NfMSmzP)9Fn_`GyulAY-tAHbYYSl3eE2kYGGu1I^WppJm(%ZuKsjJanC2Ou z4-Z@ne|$0cAryk|R_TGk{7lS;RhgZOXv=q@nC_CO%moO;6i9m>id}H~bjWsLmaMsu zzuAku7_b`DA_i(C^5CF@e})5AlsOPuGxV4->Rx zd``PDAn`Xsg&p(wZJFGH2yD1;9$yki0g+eymZvPmf9JzcEVA4DhL=NDB^MFydp=x; zso=OJ_QUK5*ngS5^sL4nm^CvbegQlWKoOF{2cZ}-*i3Z8lC{y`M6f7KQ_yUTFJCQQUoPKWf=rd1)CrLCSKj}O9tGbN1bP4C z$0yVO3_gG3e`KHJ=ir<1kALyTgR7t4E#6))uP=Xn`+w@sN3OI03{! zy%8VP|DWp-MOaD!V-RK_K(eIo1zrOI)~-?s13)c9DN9^pqGkm}UieSO&Db^A#sXAZ zy*_vBKz|30dH|s8wLmK}Jyh)zx_e37mK46ODyUh)7e(AF~mA4aNj^DtQT_1d_}` z!Jg1qei!jVvP=38brjz4a|Uzr49tzF3gi_?hJTUS7jyP3_|Dm+kYI<)U=PZGsGW&V zna9q~7;mBTbYN!iJ78QHjR$BH2Llotp8c!JCAaLZ-~80_10w0cAK+Q@sv-CYjNT0g zoWUpVIU{gt8>m~&44fZ@0^Y5``rcaeQ6%_XxGP}LtPe&(PuY%i|_%v#(#6AV2EhzIlA$TcW%Fuvz) zgmC3QzOY%fc}f$s4qHzLgD3_2&8|pEe}4smD*b%*1zezBV>na{yI^V{1Z5G#aSTK! zDtQPZr}SGeicD0{Qa{5{VDf7OM8TtEtsSHYoE6lZrQ{%w2zSm}27EB+Y?L%zOS0JV zRhVsrWt*2tmZ0SoJY7#TZc7l&2?KIs)I-0+I9{e97!MFeF~2S=-V-IoCOX9#% z=!Y1Z``)HXVDH4}F|BN&Pkyc_!_6){2m1ng46(3-e4K$~XKI_6EohtBXMeQtqM_>y zauv|n2%Mn`$B_6sF!S6Aj_#T@zT`>ftCc&^hHa_zcG01tfdGl$IcAZlJwCljA~+BO zY(<)O2;4HO#xR-d7leGe#b%Qk!3^yQYEa0k2(s-%;caPZvn=h9tp11a3>&s6F0rgJ7 zAngj+LZz7^p$L~^V1K{a)C7&UJEexV-zL%4$b`&uka`$`(Tq`I71xeg1wccy1lpu3 zRoOrMuE7x&YMp?+F+uNyCKG|g7IoN-+b2rdO?B&*H?Gs*tk8r23$~*cA-jXh2u_Ug z1eelPGM&&+poA-9L92#WCCYeV5`kqNcD)U=8;bV+9+n}{_J4I=#+#DUz8L1|Nmf)c zXk;HtZJ^WnIonEEoX=+a{XR&tX_fARn9u%i7YZr}%+Oiqm6+*G%tk5CHgek|{Rl_^ zr0oVW^Fe@stok%vdmJ0{Qa zf@DMD5M(OrF(SM0ZrNG%+o#W3cBH+(qf?(g`;XIv^ZgZOQ>Zyk<~n{r^yjyh`(fUL z#Mp|?kQ5FAM+zG&;?ZN;sl&;ZDXmM)*241@2FW^hZ09k$IMLPu<7)e=5j4#X?^+{U ziMoMLVE{cFfdv#5Xedj7c|eB0zlu4PH}Tu0 z0UI^9-tCWFxVnG(?cWnhcAz@(Y=amshR=OZC&k{lw+LTfI(An6(uJdbF2REO-sOi& zJG~)!{WlQqpmcoYpBArwS-k7nMvb|`-9HZEx65}|i#My-zzv>*arO2J>*n5wHuD&_Fy=vN(w| zPwM3607l!1NfHSb`GBgKaXdT-%L7CS7N`hFTI$kbjR@i(?1CWkQGF}0OuL;EYC8PX zcH#s-@2R8OTLkOE+34G+=Pb@~gBX0R1sO-!7sNvm)lpNzUv{=dhZ%AkN;{gv5HaQe zfzY9#N*#YG1pVx=LUpyU@6mA2#?-3UF3LPpfg2d_6zDF(wW>_=j6kkS2x^2WT-&ts zJ0U`pCaN0YO+TE!q=~hgwmgGF?0R^WrpKo|K<*u%hdz`wNOa;_qZw{ua4aRTNT-9` zA}mpom3~q*j8$rrmTNxI`6Gy+Oj4Wp65RtO>H2?+=H+ujxeU=b{T8N`n$dMEo=rsmtQ?y>%iWIBBl3Z2Y>&Ot z{KOekL((QHLqNh*2?+p9+{1iI(yZxSMvNz4m*#^B#D8c)e60<2NlVWg_nI{HEqXv3 zkd1b0uC;I6kOAeq_{vC|>T*&YSsZ%O@-_iUw9P}`lkLiRZ-Ragkaqc9NbrLY3z+^U z-+fKtneIaJ)z}F`AXuCFecfID_q93&hp~R$FA>0YT~TsZ`8_F?aVSH?nbyF-{uT{U z3!N5M>VLgHwisl9)e|x9q&g1-C?vct)_En>F-$94bC2YdW^~So9RYffm4&FyUW-ms z&}?Zmy2Wvn8YitlYWCD^-MwU;_su)+Oi=L`41#{x8QklHhy&JC zfC5$cln=<#>ODL5Lzi=EP9m&6bXu}&tXz$n-Hy;tpSJQ|-6TbUye5$N17%7bG9ERe zc;T5zl2u)a{d1(%(B5=GJivYmr|3wt{C|&nxzDY0brX37crKU4jlXEZIqcbRqdDE} zYlUq`s=Ib7j+uC)N5@KN;2F^cJDmnie_gr6_rQ^lpF2Ji-*kzi;d%N{&;vasKa9`2 z#CGw;F-K#@b^*aIhU>vj?VzDiUG1wusl>&BWMv*I=QxUp)*h81IQCuvAr9$w6@Mq> z^{5Zc>1ycLf*$LSk2(tB{>J7S>_>rJ^jc)v#rR zt{a}(-D`G7zed=i;X{MmPG;GGWPehyro+rJ<;JvS9J>z8c8#%eiSPP$1c3xYi+(1U zUlmiCPa%@$<2re84S`B>n_B#cU8MW)AXL|h>L$lJ+p3brkz&MCmG}ikhV6S(JQAmt zwdvHUWbntzNZ&uSWZ z<*Hk5(>*s2$}MXi=!Uhfjim}t2McrsCsc%LmrJT$&e@t;hVaJk*mYdL8T_!oqV3$z z#5pn_8>S%E-xczpyt^;7*9Td+FT^7nsFR`H4uq4s?ELYB^$HQur6ovs?Lryh*|zh+ zK|oLaW|wuJ+sgY?e!@04IxR9DcZfq1d%T{}dFN2oT&|ZR5W%L*tHOUu-IVC3+lr|m zcKV@uQgw>EL?^|U#E1zdf4)#5qu$t2p=z1PUa5C>cU1eDGk2;+0Y_Wkd-;uab!8N( z%WwQA-8ZKKoZfT(-q>|j_h+JQ{8~Mx{q=a<`dx3j;>_w!vb#=ehjcW=@A2Cov(J{l zR@6m9(Dv9ZQk>KkdiA$Lx9!!wUUQv1>XEW@OF%RveTPaRHDTNEe{U-Ec|mTetYRXCUx% z&zbJsF>q(ChES)RsiTNi@6QRh@BTUk96F4q{&t|k zcYkel!}bcW8U6g3e>=KKl$%nUk7!P4iYsyE9Qt{E480A@7;^}8g5gT!X(jQzJh}-t zoT+dbVwx6^xM@YkuTZh&@RpkoW+8SdA@MLkoT)LS(P^?;ng!o$0!3)a{?TgEB;IOR&w`Ic4v^DCct_G9Os8v$0YN z65a#Kd^(mF%6xmp`?5Wpk{rVh7XtYR^@6aWAK z2modOgriI_Rd?iOHnl*gHBrJ309J!`acv zDL#a98~JQr)on1TrrD&~xT>oed@qV@f`FPpyq;zs7g<-fY_o^9$S>8C=8mgg7uBV# zlhcp137U4A&<|NWujIF%nyQrFi|YD1FR$g#s*&I3kIAH(&GSNGe^9G$O*OgA+Ksk; z+}#M^BOf=#M)okt=5265PxkA&s&|86Gnm)u^(@^D$_hGim(^4a$_Jz1uqr#ii_3Xk zO|nLz(LAcJZCYPx=(O2vZvK8~@9T8F;o#NY)LA;kUOojoIS7l{>@iUwkhC2<*+4$a zHh3&zS?`;?!NJ<6e->d>#cQN#+R8#v)7AhdX&>iVGo&ui_hHc7EZV#n26cL$~alC&Ve75tSP{mE`zPL7SZ(lY^acLaYyO&-zm`>d-n`690p-ZW zu&U25`Q@9#Z=AO<`ttQ5^z`)j&ECFUC^|otojV1Ae|PxTWbf^V!|$A8OJnZ}bCR%W{Ydf@n39UfD%r!l2H8WxoIs+)*XrEo zMIkE&f4A9V6FjTt&xXOX;-+~vNitaDtli*w69&%%4-N5CArb^XuCsZOPO|9ZFbKoJ z8iaebYoZL(vu&Wn_@nv!{s!iIA1(2tctmmN7S3t>|zqNnF9f+rBgB( zje?JEJNUVT1^d={LnCfOsCqz9KjU;he@DKlJ`TKv)*~6WZ8L`a;AGGRX#aGuXn}k) z^TQx=u0io1b5LahVOS--H?lK6fEjodcOqXD;DjswxZ^G!|_!P?S>b?l&=h9DGxpm zcGj?Bv?Z9ZUb6T$)`FW~e`v$yBT62;4E*b|q|f-m5*dvvDx6_&))f_=4$sm8EcBV( zTMH!Pw}yU;eQ0__jlio}M}$GyMru#P^|Yr+HJhc1lX2EF);(QfOueHa5Ea!ugy`c{ zzuGBz_A9F&n?c@&D40H+9QfE|2;&Y!GlZGs{>FLN*_>cupRX%FIZ zUTwYJdHv^CL;m{dXFH$868N;rnliM(q{V&u*zmd&bYyskYeHQEe-)3x7K~od+*FHV z%EYr^WYXE)kPEDve`g5CHz-jXH%b4Bl(dlqW)3qZvo2+uBFvHlm2st8?=jgf$q2~pv5CHhHL)9G)G_B zbVzv8e2mv>9;Zv^aTfE%?1xiFTdLH=*FUZ^&Qo*j+8p>{e>s0vFM50+_*ui;(Hczj zp*DUmF@NL-$>VzQ*CUfgjuj3V{45bUf@+eN*KGFgDMX@Ckt3FtpaRY4IG z42T62&XNUB|M*Sf^-%3yMfA__nIcwCfB)En+70+YGwlcVH^K8j2ppS9SKE=7Yk|5_Pzv?vvDF`PmHK zkO7A>KP|uQQ& z?0<|z!RRuZqzj-FsvRD1sC8h|LhDTHBIgZMk53i`M8ug{jc4J+PscZj%`YCv%f0Bm zBHaT?;Q4ePdjAyeX=Oc$Z5b8I$9+R_k}CdYb3q&Nw9yx;C*@@K5qovNERIi=&Ir!i*fgU zf`SC*JN}z@qW?mu17bx`&Y}oGjXIcY5{~$vp~gndNKIfrKQf_5+F*c@Gy=tas1Nz5 zZlog&ML?Z#L`#!Q!T!OOL;kL-3f;yF(42oe=h(NfIs{k}MY^&^RHXo;h8k3pmD7_O zDUx~Gf*naP@vE_;U4khCtobvFO%+o>yY9ql^K81cz13vEPhuTuZ@SR|kjSF&kJ@pq zni$K(Pz6S4Tibla$HbZNc6DiV_+h*jz3p6S*p@y~Xh5;hxX4O=+f5S!D5#;4Z4`g} z!v0L8-(}ihT+-s|Dt{PKIpiE7eMhEwoxy9UDDfr6v&RcTb+{q$^s-6tDT1V^wTK~E zs{|IK05_`vSzY313NhIL(N#4dVfn00fp3DGB9@_!J*>`1$li62$<&bEMWJTE-_>2l zfgojDKa#f62KTTMqeH+uY4kCP=hc5aGVmJ`@TaVevMYAaIx6<}N!F*1jR>`V9*t{_ zy;k*XZ1n1aB)VwlB|?M05>s79=^%v2$V*Tf%DYI6EKv9+ZP3XbHIL-1&r*Ox{1qBg z{4THCMGEudE*Eq)??KIsTvT_Yc2M-o5#7xc7GdBuQYkDJL1JYjf88ibsrdEUFTN z=E^LaqCX*R0L0`bg@+Vjg#6jGi_4%$7v%(_G-g?f+X5+tWX4_V%5hYo_y;I@ZCG87 zPJ_S0QyvHET#>fu79#)PG_8N{^D-of8igMGL$15>1JfGV4~U=FRY?S~hd_Hj_O^7v zm3U;``ewJefH^ouaXA@q*_glxM`nFvw<2$HSU_>0BDoW)LP3rF5CK~TNs7|_j6%V* z*%X9nHJi6Xsj??9(lxLi#eXFHa)eR@<@!|$_34*r8vQU_hJN~dH)NMm4htTC9azJl zOSPpLLvb>8j1I5qgx9I!R+*EYH9-aLycEjT#3bcVblDh}i5L>nnI>&=`Iy{hj}gp0 z3?%GCmBtJBVi@Ql!WuJB_~D5Di78k&8kh{IE!|Kk5D|-pf-as5>P&+V~IZJ0g*phFaaEzt{KY8v)X=JcJw;3-s8Y!F0fXsyi+%zo z94(L0z1V7o+I4%i^`GHDHoUz)_g!MN0uU3F*YG6st}L?*bx@xcPi8zKR*c&7+)V_^9EwZ;84+jaR}YbN>Z1@ zi*Yz7|9mXSiBHs5Ls=r*aY*_@jviw8e#x2*T_!iD*l4hS7Akrq#c1Z zJ-P*{E+erJA&v<>@>$kGKNZ?eLzCa@h7!n)Z;|b&xUIfwa#lq0tMK|=i(fzq$!?>a zVX!mk)O_MrejiQd!@yvFSi!VXRlxTlRX}wlv}iS%$LgIk%C6=mieJrD*$sY7Y~6*# z#~fNu8~akE87$V*1DzxWy!Uy78%U>ovg9qz8$S17(+h*qGEIsKUY4gSVo(z>3ZY~D zuC9M-EJJsdqyl<1;xJ6)EPzrnN&Z&=BoMYy@6uwC31H0cP;cO4t~3U_YgH|;lp26lsH*&<+Ozp0g*B1f^Ut#uc3EJ28(|!-u_n#V`{%g7_Y_PhJa%9T>%AR z{pgz`P*F3G-&7i_iJcQ1u1@KO@lL0}cFaK0t!ZhBktu_h&kze2fBOSipEtXL+w|H) zqg6+n;g?rMdhJnTBpZ*PHx~rB(cL~;Rcp70rdf+Jp35-zH*)M^8rn`|ZG6=oLW{-M zSz4xGNDwFDiL7Z}OM@w-o`J?2?4h2qQ&cwnN?-ttMPxSjzTS=3Gk zEAg1zAQn@B#^ip=mt_$P7k@6nLt+(Z$H13WIc-L-K9dN-gd2%ch@?<`WqA+2qHN=o z6|mRpMK2J*2YWRsK$h{TvMDOIbC7F~QFZwf%qxL8_AUWwlDA0`p%?=_3(Q4rLgB+0 zpP|(P|8(=2oHDS`;#5S-j}K}g*CxrVnl1|UYg$d9WmqJm4EIFA#8|kUTj8Pf00n#Ffi5PBoSCc`_!^39!ml^ zi_az$gtvGKDM`j|1zaFjv@ZAeuoSNuz$LI2wCwi5KXlATIZ#EkLMY#ayir8qaO47@ zgHZQXO{z3n`{;nV%YWFj`q;ok*A7sz+pXavg;)WdIcWTWt;qU#TfvynQIKm4K3q^# zJc6ApYIIrf;N=*FQi1RmPS&c9gW!-H7=hfaLIe;^(u&Cq0bQ8~&7{sjHIhLU!e!Ac z=719KV0|b-)Hm%T`qL1%n-sltv=Rzpp$nf~8$~rq3!b|8s(-{~1_}a4XTd#`Pr>e- zpd+bx40sDIn@M~$3I)LlZW!>w^*s&_X=X?vJUoUNZRO2Pz{M#tL>m!tc!oW`LB(5s z8BBf-Buaw@=I@OeqlsMIpnHydFWdUoMdu$@8w|owm(NxfmcM1}*S51Y(seR=MqCl% zLJ0K2c2MWIY=5d^(PqzJ4O3j{fZuxcyWryqEg}t6G#g+q2mEY=*Bu`VqguHx+3kU% ze^CP~@=hvL(R|GqzVpfS~dB8S}bsa zB&d0SY3y$oDAgnrP)b@2GtJ0D;7O{02r^h3I;awNxL9U^g9vJr5qrc{LuH13Ck8H0 zT*GVxQKmHmQ|~MTVVQIIG`}aq0BfT(6>^FI#NBq~iP&FiYqVlu>T?O0_zz$Y7zCJ`uZu%LHgY z*xF;YKtHpBMg5iS$1DJYV^{-HJh_c*%`#BO5-}3NsnDc`*kRR*^+?4=N|Or&_9F=4 z2_90s&|Uktub zuLMl>s+%a2YW^rZB{W&U{G@#=P&WAsS#=|9*qk|-hyzx#D?Uepp)f6Npx2LED6^3H zV1Ln_z^aPIjem?ZF_xgtE-3-uQOrjI35{f&PasAkISLU4Z1XwU#ju<>=sUF5<*F6Q z-dy`)u+UkJ6!1hnU8#}Fn<6i76}ml9FVp~n8FUBC+aZLtwb>{P zNaR97zjyq!^*~=fR5_EOg6?Ix8m?mns$uAAjF90$`P=2s4mGiYnp#r8PW$ zPl*me_?m1$p+;l*#RP2_%{}Y@+EZlE!}jLl$1$EAG#&rx+RViMyUQFiOz2V)hk8hE zSX+Hs!V;vSJZ&_s$#1Dis-sG?b>jj^tESOmoN0{FWV~|WTnVR=zllubu$1R*#u#*66yY)1^6G^@1Nv)HO<=5i%bD|4I4I)-D0+k zntz(F%{2;Da@MaxVUv4LZ!Kp(z-V@hO?m70nt2LY-JtYYdY6wNJ!A?aUFuYz#n1Ae zGq$aVtc}Va?AI4@6*p;vepC_OO5sY5K|U43?PT&2(uxLBwAi!ee+`&!F{YN*Dg>Ux zIxE))*03={5td@3R|n=57v$`q{`)8QG=ER8MQ{Ck!M$RkC)`mFnOf4A3V@X1g=X}% z7~|yj9*h}lXHoRbGmyez$os}!-aJ?cj~^!oTEX`q4s0p!HaiY=;3Pvr^zwF)V-MVT z@9qBHcl+NYZ{M80HCoW>Ngme5Z>Y#KB-3vgym(>aGax9NLKCMzmsJb5#bz>8kAGtK zY~jah#kAK;vs!c+R+16}9_xiHs2-*j(`cGqF0P~S1d$?JQ+b_n`zc7kbr$whwXn z{ey$EOw|>Do;)yyGjYYpn2tvS6@N8%axOsOpWcb1f-6iHD|@jy8AIa)-mPs7=uwX8 z1oL$YkpjQ}mK=TO63vaY<7iY(pD=6~8!uU!Mff_Ad`jZ09VEuwh@g=4#DnyCYdfoT zKhhqR5Z-0btVFQvFkt`Km2^DQacyoz)fHv^4l1#rX)NUqqRSUUcNUvM*?)4*ujqeW z6$Ng^*%VkgX_V=J2b&`oPrrI#aoJUm=;&smWjSo3TyEr1bhL3UVP%@lTa0bKAIeau zc~;+~b2|QERZo)nBdb{nCY?oSR*5>pXqk*p-lwfBg<;fLTFdP|Fs<@h@R$jK3gfmu z?i@zWU=3vh?DlkMN?vNL;D0fp3yvEC>fkqziY=&21(#}30@NtLh-gKTu;)nH)IN5B z1_46oP5FicI3w%EgQ0pkl^TW^&#N>qnDfdl8q}qnE#gp{ssKI_kpmpaGOd6Er->%R z(8<`9AnE)FwgWxVC=Cxpz_)lc)@q6DF2>Tu6_SM0`X-5vhuQ$t(0_3~XI&!8YU*h~ zW?9r=$PLOk9Jo+qBm_VkinMlkaAZgG4I!7!#evY)VlxMh3`?K;W6gP2a-V{?_9-lG z)utqmkPLm2r;0d8$#UL^EIg&TT>~%FVIwR4ie8H7t&xCjzNB_ABnAIvDfpEY>7o#) zunAi(b_5`{)6f~}&3_wlCv`TjMgIr=X{R;l;pZAf0}-aUON!1H9Ofm-Gt>#vbMkJ< zN5goi5y-$k``87|VB~?jNNADkRAQ(zgtOP=RZm=nP!)_cUKlY7{0r3lo(>yKBI}6X zD{4vZk+sC{6}1Fg$x4EVU00l?H%ZW(Oz^0)3K8NbFsb$r&woz-CpmEvEr((BXui(dTw{>j%zr~3o_D3cyf%Pz_Z8McCJa1%gMBW_^% z#WUPSIVof9+<#w^dkiN7ZZ3~QlKwgn^l^k2?(_9Fa%DOi6QrAp#q)WFVJaAs;^~t) zBc|QiaSRC4^g1CVr(;TPrmf&Y4TcwT__ddls^D{;w4h9?MF|VaZfH1&WSNnjQNa}6 z0?5!LwL76Zh@XstSAF|^|5W;}qVduW$z@ijid;T`sDJcTqbR9e_}05O_J=s{|ClBAplnj@fZ<@u7!yV}$K!+V~HRWt?wG`V)W_d>ul_ru7 zBuT`Mk4_K%&b2FrrVmS`qrjBV!uZKLY=WCgD1U!lOIspN6pwX2%mFkOjlzF~19-Ip zM*^keNe|A{14QMgMblcttq(-$hn+S;XX2DHxCL_wx*dgH(LO0h%Yv|0dvW~y#~+zP ze*Dpi+3Y)rpyX7Cm#m`iIhHN&IEFg0L-WL}XUXhrbR_OwS~pSnCklN96Bsv6L*EL8 zX@6^wdji_hazNt4KNc?mUytC-?Z_%83$8gqU` z;WvtJL@3_nLWQtN|K2Y9HT9#uCdr*B2Y=iSOK&su9vCNtozAG!>;#m3CZL*`=fiw> ze<%q82nd#QI*R0dp(92f*M@4k)BAhKr8uPL1c{fNLS`x&P{<00lD=SD*$rjF ziG;lEP106kby2$v=Bl#Cq2d8XfQwjWR=|K#njB>TfGfa)Q(mOJ#AtFTEv_qIfPb4A z7QskQk(F>WHUvGU3jFa$P)>gQQHrE#jgk1kL?SJNk}u)b)>bIR3&42;b*l-7*iUF% z{Kp?TJRE^}>+99wK}=YOT%6O&$uo`Qn2PpJ2D?{#0}@A&|7JY z?9DJY==u|2^~lIWG*=6j!yAWrsS>T&vTORr`Vc7LkZuNk;{ zv?Tw5*d-CC=Nr6A4LuW$%A)P&^f2-<b9<@4nd~)>P`+H}};hXpS$(zG(5|QrAbQgrtINkbrXY0R`i43#_m46i*^aq2Dpbod@kJ0(`JpS^0`ek>o6Y)$U z59~zp3nfoLR|q*zeX9FDXHbyGeECc(RO9TnMw+}-9S91dvI^93d*Rs!loATP8zupzk3-dzVnK6l$d}t73k!eVopH28 zB+Rb-%AhkTh!_{4nhd@OI8LG~G@zV?s+k#&vrN7mXU!y?XHJbeJiiQwf!P_2rPr(Qb)%Q;aIx^PG1s$2P zHp03$;gf1K1X7WOg;->#n38`^Smd`^@a*g!e!yb9SJm0G4Z>UIH*{Tu%0W0jzYo+^ zb<1Ztj8i0BeSr5D;~&nO0ahIRDIDml8XY?Xc9Dr0qq#Ld-vk)kkhhP)EQ2XIWeo;2 zAUye^n9Z7};-Uhcm*3*EEWVE6#W7pC%@#U6*cmTM?cyoGSuo#)7S(@Y|CCaC1mRUx z1<|W`XTZJQfEaN7n1%u3cJ&t|{O?XfgTOt`YHoq;KmiG~z zhtHeykYeB%wBOYywHfK=lU^2?1ZRk^0CsqxyH_zwAKo9a$Qs&uOz*%nqAWz#QrI1~ zQl-Vy?l%a=vDofYa72Hh?zdJ5wU8GfXDJadbX7_`k{i9@3wJx~*HPD!TAS-0h&b`d z?A`L-aYW&LwVta3D;RfBY}p}NixLe>B1P?7<^|Q&d!cD5WP78Gl*O_Djd@a}wS5Nl_P+*C|{76S1#-;#;S@DG>2$&V5{((Jy}nG9#tjBY2LPE?z`Y zf>(0VK9pc+)GCVv%SDU2u-RBd?HPvgro0U`n9-^_6f8^Zgbi4cA0jUemlSE5Vv!C_)-!8# zNta|^rp7vcU@%XYy@}f}lItjmj%$Y2A3>t56Zqc(e|3M$o@7~0tApfv-UuSWI1hu& zYr~kFPA=^PilfI5FY;}6x3}-_?|}%@ttm`(Q~C_^wD6STcdT^!w4b17;Gl~1GI6|I|h-Mw~N?-T( zf=h2bZ&rVFq=WK1dql|g^+(10vtypR=G!^&FAF3XI0svsXv zmr_6^31C)5#i_X=u?$K`ol?p#(0p)Pf?C6DqZD+@+LzWwMOjFdyvsRoZXyraktTQf z$otzOlm_z%VvC5%{Y{n?;(4b^u|DI*fKVD(f3$zy0hG%@^5gAPWgyLK?d-2m{tyH! zb>=<_V#48Bf|eq*=u+(P=qF(GcK?venE|ZtcE*o&K9}9kOqiu1BKXn$yk<&WfU3^T z&>MAh=HKWX$^bWCcf3;GWs;b48upbHi ztJ;5A7&`;78IDPw)`qS>WA>HFhkd?QF;#?@)dx^ZYGJu~#mNGN>!bkdd}*jC7Fg9D zkWz-eo13b%Us{Uo85!WGh-)YJEA5y(RTAuDYX{eR9MX;DhHA8JV;=gw@`ZBZM+?%l z+QW}=zL>eY7m^tjZ$s@a(v@MAfgwQ4>`URb`$8*&XfBc14H6(e61eufD&T(!JlR z4rjnF8JH_X>9J-SS65nLt8539D`<^~?cynF@e!KW7;u8y2e`WovtgP0ff_>zBWQmM z=8Dra_j@<^+YKiR!g)@QkXvDv(%06(DJ}aNCV5ULq`L|f5G(iQEfN@M1)z!y%+?1| z7s1>qc`OggSSRk_$(YJeo>kPGqj3l7VwvvTe5A-m1;DoE1g)H&Hy`E9=o(t*#D}U^ zWLK?GSMjV60zGWo!>K2n4*ma%S*3rp_*V_Fle{22tTZgp1gKFvB`^b{WihZ)wt7j9 zdZz|Wr+qKI`5rP1_u%wFirIB(WDY_92ypkwaOV9l6UNe&ma;}V#3l1pa8EQaR0Ng` zCWF1e18R6=O&nG8_xhNt0-G_y-Te*Pjcl9^QaoohH`ikNbsU#5r6P&I*A;(bfF~El z5DE5h;KK!~|D=NBR+-E-M&LsC1|AnDs~IK;H*}jl(th3VYo(_hb4Z10XX!E8gp((s zY@W5b6+d1@MJ2gYm7^Xec%s_i+U}i|KV6`ERtzeQDEmn~_Zdk1ob#;G{l#+EO7Ca- zRs_$Gb3mLxeGWZS$5Ed*!;XK}=soa{n4k-jg)5t34~&+%DY3B`oU(o+HcRpDuT7yK zor?X_RoTWI9S7FssdbQ6&iTp2`=SIhrIEg9dX9ImOyv!kU=Q?D`;Orq@~HoYN+oZJH^TX1Jc?^rAr_!b>B~04{$X2;DtSHD|!$ zG!;{j#3JK_QnBY8yF4o>y6-@4OvpsRCqd?N)(qQ}t2mz3$+O03RwnoDj);j)i7dbU zN67DbPLF4W&R*l&i*?%M?*8#M2@baDQP&Y4RC^|R5>$C)9UU^CjOeXzmT0M1BP=uI zDKOxS1hwwL*E^)u60LuCwFr?O746BWI#OBAZG9-PhB+E?qU*%NvRW81i|FsNM-Dw( z>G*Kfs^`3Yky2|})1duI7pb;4AjaroGa|+EzNiUQ+dD5zYNd#ac5f41ze0 zDYz8JL}>h;>O_AP!WORt61je*;}r9_^JbQPo|Y?Pte2}oN)mlCV(5P9YHnE)J1;9I zZCIyVkM){~44!_#tAOIiBkO48WLia@YjlZcDB_5vx9=nvkCO^xqXJ(!ClH&quFC5K z=wHf95iDJ66SsqQx3{62_xWu;&!%}ASM~Ka{@OlE>z{wp^7-pOQ#c%eDjp>;yc(yP z%|T@as~}N9r`;?rr`bb72ZLyK(N`};Q)vlj=zy&#OpQVcZ- zftu<;bh@|q`}@u_L+`l7od;LJk64rg!}*L12Gcw5fuPG(LAkoe%7U|X7C4e4!gD6bKAMzBZ^jwJng#8AS+b0 zOsRjb-Jzs^%r#JhX83cY*-Ns+2_d4lE2ptXh&$9hoNB$c8 z658IV$;48Je~&?P#oG;25mavjaj6*wczA#73;6pNQt36*Yv84CuUo+bm_VBLzE$eC z&`~|Y^D@*=yA0R?^r6JK&?mD+k@}- zll{M+?H^*O5rS@V+rg|=iU>OvrzMdIJ2 ziyy}uL2>7HC~kKX8TgDO(~6hqX?G9C(%^nR-|V}Yk(j5;FxMN8q#uQ`_r^J+io$>0 zpUHKu2X4v2v|T$NgFqz)OECdJ9eVd;A;1qL-~v_#5$h5ylRzB8Kim9pg%-3@H&2A&&({F;qDYC(A5L8 z7?f%Xb5XrH-8(qIWNru*w>Y=ZF;iqIUz&%TsxyqF&07l!=8q)>V8IBBD~0F)0DDvz zGyvh1!%fc&eL~VvfOa>KjJ<#NCQoCCj(yH^a4=lwgg=KVC7pDWSjIb|C*GWO$X@FUAn}Z{fW5+qol~=JSA?CzX zTgg;Q^oF*eq@a-pg`eF&qjcv#Yx&M8c9ZUh$M8InE?fk4-KWK^(*=LMqMU<0>A0^J zMPY}1aa-nel%G1o;#gvgJ==BDyNTP}tz*zdAHbhw7I(yi6)tb|uC}KLO8hlEZi36S zMuqXi;lUZ}h`0iNhkxGVpTCB~@C^Px4!ii-V^P=Kdt8V`1tiUf!|x7{{&pDlMw-qj zqwZ)2lea(Mw^utm?yi3azmpmXDplgi7b5|o^L?R$4$q{q0H%1*Qz%8(7XvcikS3QI zCx6wutVrh#z1uNgOc67AfK+vNfe9Jp#tz_eXSmt*43miS=OaIPqaY1Xyb=?;HNK?Ctl@FM62drQrpL9iVt>gvyX8hrlgGrTlO zFRj8j6lPNS(D$fGkwUePHeY_ZOaFD`*(BO_P3gyfH_gghTf6k% zGTL@IJy0?_+wKYO!2Td5?H;WzNk zG=Ws=T_IjfwT_d02J`9VU+@oI_<(wkF78|!bnO9}f!W?lK9)#rncD^33{Y|qn1U`J z@r}Pn<7ViDJ$W0)ACzd zQ>`8J@4kP{v&^~1&`0kcUI$UK&XnkrHQw$~>Xpm)Qum6=q|kG^uRM71f+X-S)x3Q* zgg>wG&!@k|S{5&F7iFdgyKVgNMQQ*+Tn9l&1kdYT=oauvgPsC<^z6lpXTc29mB}Mo zX#szt!wAsy-J-_#t#GpzmO34OAC9xUp`-E?U!S3JUEhMC9sWX>B89(&Pe)H4x3h;! zjH2^goC?k-H;H-(*eaIPZm^+uDtQfVJAv(I*2Ih$uN-C3R}O^1r$eh;2e~3Vo(SihogzZMv<0d~>&$JLo1V?2FliS6ub_Vs2U%bT zZ7WpBGtlAVFCc(LR%C;4s>-{bfJLF<)6;j9ZsDQz-R-m)df&E`edWd;RGXu@OTtG6u#IVz_b> zjG!@B2r_nT5_#}+<*BG0R}_WSU=|##cXSM+#+CXxN{&SjD+tJ#yq0uhp_kMbVH)m-j$LI99?KbvThBF@W(QNvUT5}JR`Z{M6Ir-uhi zM2Ja%aR`baAfT2Sx~xqJw58KacEX)v{=-Z*Sv$9nF6lkyy)PONKjtDCDco>#3GCh) zTZyC~#$tUzWBMtkw^h^1b#f}QoGbw#0uJqEc)dAhP&CF9$!i>Ga_5@(C>3}HzMS~4UMJQKFf_C8*Xf#voe=ggC|C+6;B~k zA<%!Cp|-R-CzxJBF0lPaE%BpUbNHcbBbac6&wzKCg43W|_q)U%pmx+4koy=sR*TSd zw9!FDqZ$tb?v_>w?vM{TZ*oid*fBMFI%yXKjXLPWtEUWs6Ow;Zo^MWRM9qj>65`-Z z1AL9?SQ^ybFSDBz3~nlof&2zQzzwwT1@7mGczG;5B%NO+9y$7s_Oby@jQf_Cg2@Y} z40urQ1se1(ROcDr`z$O9MaeSwP&VmRW-F>x*n~%_E8z}`WMk@uKu3~vDy)>KOIg_I zcM*`DINu^OO)NB?Ye10N>}+Deq`MJc{rQf`nm0SxHeQWTXE3zkf>k?H0T@cOzKBeX0QmOo z{W}?H!ug-XagK+_p974dF0nrKKi;^yLVyFt!j3PvlYfgy~ znz$$|`P><0Bh{%98x%aiLqPRyLr3Dv8yINHnn89s){$8 z!oW=y^$MO2yQONk<7MF{|NHxQTPMeRA|Di+w&X8BC6>aYf{`0Bwfp*loFZDGQ4qZz z2LB=Y))CEcFD%zaaCVI_00a3|gvs`-@90ZIrlyS!8p)ktmZiY%$Zhm$hi|CXuT;V3 zu3L%VxaZ`>u^*6ybF{s4aAsZiEgIXlla6htqmFHLY@1JPc5K_|*fu)0Z96&n-hRJR z_ugOCt@F>RTF=^J&zjF%bFaOtHfqf=WB@Nr_^2m({RALjImF=~IDUCI*cx6&t=bh; z?@YaK@nQ9mf`Eh{(y{e8NPSH+eHA5#sALfy3jqD>pDOJVet)ivpMDmI&m2wS)DFRJ z&RNP?*3JhbXu?)>-^)E>I2#uH_F;ize)`<5&;0x)#YvzrpvbCE;z*^zp1e0Stq91& z6%B~nq}!J%FPrSP!0#3XuFXYVSZKSBK9q;W%qwXv7z0ad;WsKSROnvIx$U|LI}6ja ztMMq*TQE8jc&R{bArU0MXG*>HYWb--VP(mfG2$e4YRR|}pCV@{xR0(e;*S#&YD8z* zre1I;!3=AVR?uO%8ZnSUP?(W$M7$cE;+WY4?AI7id4)h}RD6AQXtY zs$Xc>@$a-$k&`Io7jst1mRX#tEjRyxPg0Htq<~7Bn7?H2JzwdgZ?FXdkN8Oc9`+J*E>w zNmKU$)4IF42WrihW@5_T4)EKz1)cbe7DDqX3#H;Bj}$ z+BpUR`6g-jt#Ou?PF)mZ;0S<&A6$ARSM&tCb5Ae4*WZiXIosF1Gaj^-KH?aMmFJHbvmFa*`HTUq8?TYe7mz;Yd2 z{Juf7K1dW4EA#k7cmxE%<96S2Gn2Q8mJ;9wlnyxfjClKQpKM5IY-8yYe5Q-WVcic? z>5Op4&G~1enJ7uJ?WzEdLKi;R7s#7OfAqWex~|O;-!wywPSa{2~1msXaz5pyOwl9CPjuYI|>= zl8ma0upQww15h{nE@S86`2N8}(hFjXI32fDIU!UmZ0`)vb$SVLv78QwMGNanZQvzM$;ob zs|XA28i)X}@Ip?5t~vTqTp1G@p3!KurVzY>I;2^R8#SCzj7)Cg#G}01eZKP(uC;bA zWQle=6KP|n(xt1}AwL$2csMK2A^u}sypzuMLSjK9oHzbXlOp-f{fe_+WN;!`C;K9a z&{iK9{11pe4YqSS-wP{@HB3})s6AZ=yAC-9tLZbq#*9haTTOCVkgCe(I727SLe)ho zelSlf1Fy;QW4Ye+Mpln}N~PDLq_eFfD#5l~LZ$zOqTaDm%wt)E-RW((qQl#jQvKLt zgbbaVt`z4ki*-D=ZbZzXWdMJfMhe=l8oTv`Ji!Twj(z~WRH}+HN6qWZO(BV-yrU$^ zK4%(0me~ZG3PoAX^gN{9Y~sN{mxJp--{ZDT+brxHyQqO3XOc(jBGd-EK2vx=(lIQscO$fw@3;PeVGVys$EK;E_eBN7`qmqI@ z`XBdJ$MKSbZEO;5Sj9MqrG{z0tb#+$MR-L(2?+kNlcY=JVti$pf(r^Z@{h>jQ-cS$ z|+Cve@*Ec&4*Q;JFE-}lB80Gwn89jY)C@5fKf{1h!hLAequvVU|5@Gh&b#96Xr$*0Ny z^PRouj}XrwmkYf4wkZ%Gs_}6qt`0?43V|a*MSEs&&k?d^4~gx9jh=TeuHBGp*!*5h zTU{<&Q@gLM95`MBH_Ii)d~rhG%b%AhF@oG!(dP4zNPSqNPZ88SmKTiGK%8`2*{`+n zl&Pr}=sr^~73VJvK*Q`Q_43>dLh_nbC#Bc4aL~-{{#GBCqA{lX`QYO%=G|q_p4oV2 zP2j%O{|04iBNaY+R2i2d9q$!GWuI?Ee$-+$QBpuu_gVj22n>ZzZ3CFTNHJ0)^YEN@O!+wj<*%R zn!0QUJWAkHcicWH{R)vkb7n?1rz+A-bf5oyCA&E9oaAx1T%kD-bfs%N=7ggL-5!9L zcV%G4P#JF2Ucvn2q5@TmWFAyA`Q<>^!O6=n09QVhh*_+3IWTg)TAzP-xsjETxhqB4 z#6nXSgeh8Y{F_z;&3%MqDja6(8zUO>M7$&b?Yez!IZhyQSJCTH+PjZAUePYb0O+&FQ34C!;fsGmgkpe!+na_mV`Y(+&SzC81zV-zMFgGM;oK!Y-dv*d- zQ`u?KO6smkk$v0Ts>%QZ-_l;xSz>FcQ;ZU^cGjC5*yYe9JikxbiY^MRgd{3_Ne%}< zYIT2dCvnKY&~W)hmt$XT18QQPqz&KEMe$7I%XMc$z6Ec`5ojWyrto|6+L#&AND9k$ z49mVU2d~f=ed^F4-1<-C;yIlNx}m$uL)07p-3DGKpPT#D1CfXG-OJU}*2MPo>+w)u z-=e}PBs5H1emB_CVm#gfVTomE0faE1nxy}9+SC5yL%Lru@b0=8 zxcuXgx*PMduCHJ;Fo}QyO`GT~N=MB4mbL+|kT3{K^wKkla1RE9Z(7=Yap3_#JwgJy zRb3>xS0pYnfQk4ST!5{ng52GJz$c)0Xeom%!9DiYL$ELz@nnH~>240;7O)9TE^aHE zKU?3YCJqQrdgFa`?Z+bmDPYVVnuilZ@1+F=QI&AUf6Crjb@Oz~UO;f$;D2LI{r1r) zk8+|y^?=tUv(=RO7-Bl}+@=P2lbm(=F)KlszuFAt1xjbmK0yue9hRyeEeAex&&;gT zye3RQl-%?bBxQ;7u6?|7IJ{$!PeE#Z=nxm1z(3;qG=l4+u5q+`*b#qPH&JHA2fswe|s*G*KLU?Yc# z{l^L}vNSC`6|=`f+C~&DCSDMv=iAViYytQJHV#ztoM?&__lr+!v@QWZ;4#3qd(N(p zb4rvO{*B7Xl*Uc~zvG>W`+Y1uV6j?G_pVRd3Kq5X>Eh{VU}UWC=488=g)tv$gTaB{nczZq>y^}w)Osq@^W)0FU5YYShp1BoM4ETY$ zsrP2>^lVnc(p%kh{76_7b2ZV|BP&=vI9T38*rML~@zHmJ+>XE>_@;j){~hbwQ~VnW z=2H-?ei-8RiN{Aez8Ri|rQ2QK^~myeM8K`^CE*jk+1B&OGcgi?-WjJei!c-K(;;)S zX#bWFF`E$YbK1g5`-yNgq)kuf?OgbpxWfwywJ^Lh(E9Y~clqEZNExb^_jOY>1EKeO z4B}x7L;&J`K9LvaQxx#_9fK`^mn-t0>LHX>l>9h!b>l82|w&slL)c=6rZ9DYG@5QBvnQU zBgvGF9Rbl5T*Hv}1mTI^fH3j?p8ar1R4}}VqsyC#Qj!~j%WV@VjA(?6BYvID>Ao4)IVLLg%>a8xM>pEX9F z_9PA0G!A%Lg64irBE{zp;c3-meRF;}-+KUEQn}MZ4ZVG?h3525wh=CM* z!{<`Syyg(fe+G)C2AuSR^u`OJ5<2FxV_$k+hJiwtP4H%|<@g6iDF#IhCF|4^=$J0U zCn(_+98d{t``2=fF6sef0DAJkg6D3jesLgb;6k91Z?f)4$0BZHC`LZ=2?1J9*4)!kfwDv*@Jo!c%x~szcA0dC zv!OfyQ1Yh$o!~1sDHuqr%mumUv`xL(eh>3csPAABW>k^uwjZj}RmVe|IviiFVX6!K z7xF~tGODxPzf$LXI||5(^p$XXV!!yV9BS2H&o@s??+HWX@W4sdL-*!RJQ20jiBRi} zW9*RC;!g!tZ0OQOJqvR%fP68wRpNR~;-vvUC!PaTnH*CJIG>Jty9+#AI#`4fl%Scr z$LqgVD9l~y*GEfWx&&0$_S3BueHhcVh*Q?Zw6>ba!>bV#M_*WnS#oq<$Mq{Ruu2MTf>08M%oV?O!-)zVR`%sWPoy(sD_I%9z%|oDfZ!+a6KivqJ zUgQabbNyVgjEF^xk$S@&*5fvr%^*2ElSlMX7(FlO&X%zax3uS)u4NGJXmWN+c25P% zuu}5F##;=9ZG%vGW-#Vt-eVNAQX*hqes=6A9qC}MqRMXM(B8`tpjfWElTQWuNb!$8 z0tt?glz7xYwTJG~!(q-O5z(yOl(K+b-w(Utau}q<4b&MAJLl~qwiOcDc zM53Gs8;KaHvciTzi#bu{7E#f~6$#aR8xwyLv^c*#MSNuyW5H zPNeAtd&M@*A|kX&&h>e4EAT7x7M%1XOH7+dMF4HB1GvP`&eX-&BX z2JGh0ZDH(a7YdZQb$2ik#WhO!9DTI|F7}KbnXyFlG8g3tNTRkmSGRSzDeAD{w85cF ze7GT1{msjOk>4i_y~{Vi%bmFn+w;mgRD5V{ykX<8(u<2izqN-uXgno(o&-=5IV7$N z0p21*>*-qDnATvc%vwi4>`!@AENf-m2>T3O3F_XJ!5sO+vdTTh{XFI(&0~ztvXLo{;^r>)Ynl%B?M%fHm?9rNK^#RehmjPlPAZd9jnE-8&=Z%fnICAa@_8j=`&6&ySXdk$@q_ z(F&;j%r!H!zSXD)h@3Prg8uy2;uC`>;P*y!#^b3Ld~6WEZ|a7#IQx+pZ-6Msf0Lz~ z#{%&RdB5H!xBh*`D!(mLOms77HJIfXS?#BE6Bce~{R1LvIL@iJx|RffXTXa8NyBC; zgzApiOA!6SFS{D3bD3#u7~|L(b}{jj=Y-Wap#h<9y|v4(fMtisSUCT)f!p#5Ak{Yc z2W)ZAv?d3J)Ky^6E)-*Q&TxBP#b(+AV_wvmr#4fP0U7Eolz^IUyHvbkr%gysG-uQ& zdoGDzjSgk6ELPX2=wi(x;ByQKn~_}!CjoGgJqXxJl(4z5NJwbI)u2BMBc8tSa+V8joFI=3M3{zL6MDn~2E|Ht-N#kUNXf`J zon}b1h^3MRS1rR&gWkSrfnR-gN3AICU^G1u=U7Saz*^)VnGZ!L$nNRRjiV1xRM`wG zJt-s~=>k2V)OCb2Z7~h$Yj&6q{|FWMRf=>xkg^X6DR>(nX@rr7HNRApx}*WMmh8tM zIZd>oF9r0JFoLOcscngJ~=sb9uA+m zo9J5|wy56E36Awu9iut&kIJ9(!;IZm)#AlO80{Y3R}WW(N|b9!B3IiftXpEc`zpzc z^Kj&V#6P(v&&O$6QGHgU=u7gW1cGQ^Y#kCN&^1oWK$>dF55HEq+P?}B+o8F2Ei1e|1GTHF(&^HeP&Pr=GE4-!qDX( z)KGiN4*thhDV5r_x#a8xI357Kn}1Z+rjqwJu2uQX?Q$i@P00yYN4|~YJKMI6@&cj@ z9XivRINfh%7j(`k;8&q>aKt5Qq@u$>Lc)IC#j+sJdhzUfJ3|g2H;O9kptp=>5Ec^C z_>u5^Gx1L5T3ZDYnQ<~HHrqDd;v#_0Ps2S4OJ(Whu_TTe<`|3IWP zfM``z?PSp!)}LpFrDqie5RhiHm{JSTnaZx|l$&xWgRzMu2Q9*p0v77zZja-GxJQ|7 z%~Rx83={yEYOAga*3D~ywI9*-Dwg+bY8%sIWtPk_{ZuxtV$S5sOrai-2~xq>DpGaU zX)TxatkVy$Dt0H=i|jBiLWlViEu#*$^fp2$!+*G9^|3d@TWOZq&%*QY(Q2gJOoz=-U8??;=A})673I1W$mRmv0U;kJef*4*T(Ja41`yH! zk@yoV@ zY;a6=O(J4Q+@{hVybV^exgF^H?xPY)C~!wjlmCmvC#qQzYX@>wmZdU>0ziPoQ43lr zE=lanbj(fxLTJ^8^{7sS%`*aIyfwOLVEq=>3g8qiKeaSvuRJd#YP5C4Y|VO}R;F!D z6)V))SP7&6X6W^FWfG(tG%2VRji~wn?5_S>9}B93G?orI`th3d&2Rs!r_J)9EPF#5 z07a-2CBXGW^^Hc}6sA%HRHB%{`=m}ki&N}csHERgt^iZ%r%CTfE@L)3rb*=F0%JLs zPX5WW%8M|Uf5{+*wqUgvW)?zTL~TNX&5PZ@J{Mi z88|@}if}}M?X~05Gif(UdcfC_$7@@I!bI!0|_r_>mB+IM-?P zHeZ;}sq_}Ow)SZ10_vp&Ly*;z-EX@wu)GMRlx=F)S@abym1=-ha>-pzJZZvbtQ9A# zY)DB5y&-tIBybli?h?p)?WnODSdsVTsHw}F8;Ez#sPIeZ@|)sREM|LbNLhApmnSQf zYa}+R#qTwPCt$e;00H>)rMFX7=ewCmYO(KSTBCr^_?~pDNfeydk0n&zO)V~*k0<2) z*BC{;0Lz>Qbr;M&NKtJ{3lFfg7`$mwpAqBpZIrmf`l<7M^)EhW{m%yZOy@}Q zwUR!qr@^naiZQ_INDac==;a=UpqUcsRRz^JB2+6bZw^a9z61tH4arVE6s4LGl)_GF z667E)j^|@t=g!Id#H3gjI~ODHiP-FcH!5)xhr4bL0Aar%W{Ci3Ltejd%Bro>0rMnP zWT{up9U?b|dh#qr=>haJr6!QT#l_{yl1fFVYbRf(G7ZO`~WXi4f{SCi9#}HOb(^DwVEgp0+D@{nnxH`!j?0;w$N|K;612a zGrYP*0MrzPUwr%9+$rp{)Fbx=DR-Jl9AJ0kum;B9mP2Lzy+2avBEn){i|``yv0Sw< zEWyvY^Bs^A^?pzWCBkNa2>eQ}?pp)nj$4B+O?u5q@bLBdr5NW;RE~43;Sm`;R$?RJ zF)=*@+6)SFYa^yC!*qwMQzol9g|_Bd0ide z4x?2^6|nm`akL%ZHb%_j3pq7GR8bAuU%&i8!tgGgc;N}NgOvFqWp~*gt|jCMxg^8b zf&tzdnj?&_*4Tqy6`88{hDwy&{C}i5HjYZef}N41c$|!nmV4NuXU0|-)mVE!Y@B71 z!ESCT;0U?QJw{s(q%D=vP;(ap;&#d9JzwReAan*Dyv{h0!F^&fsJW^}Ae$3yi7320 z)YKKl970weK}?%0kMlOW#A0p;Td_c1kpXQ?M^-w9Ww;8+qD^QiVlc*Vpm5cpwm>p+ zZLjnk4@D@Wzi5Fw8*cT$Gdq`jC=kCVg(^J+Yw-8h*s{%Ofxdv?;ml3Xy|Fi&drIU& zVvmAYTG&r`Bbwy+D?R^$wb#D)lNi2&N7 z_86(d!zwi!Tbe*gM+1dTl{jiVq6m7U&Wg7UHUo*h8co(u{LsO}yQj8x4t&{isvpQF z*&ng8t+`%1np-`*kQ^nbnm-|Og|5YF;}WhI`vVVjG1xSWIycbFXWUIDyr$#Zs#PJ& zc;ZHr3Mh|EBj@zjR$bE}IZ%H%5(B;uz0!=tI>{iW+xtmj4lL8$A<#MY3j8$c$I@px zpp`w?H_15j*d;g45~&8CBr2&}wAcMr8oUH_B!2!g^nldWH>!Z-%Z1EX65mU0iSGAYwZF$T<=x;{GbW;T~ixj-M{&7^QpQ98G0qD{nZ# zx+%vU)9Iz;VUWiWW$P4{65VZ)ni(oiCvfFEZo(WD-_QC!?YC?im=x<36%~|1xxk2) z_dOVx)VN9veW^Bxgf^Lxhrj1%j*_bi!%@Ns9z)U`t=MGm=L4dL%x{ zh#jZ>&@Wj;Vd@a!*D8z;)nBY%aNuR0AeXOybn$D}3g|WKlgw+)zA8NA5uwq9i~H0` z^tPwMoiA8AuGa-)|EiIiiOL=lc)Q+yvz{|#xD6lnoL>@nWc>T-11BIQhKUK@(&e_+ z-^MRBX<0i5{lOyDYUTX8MW0Z)Ab^#SsKMHZLDFfcZ&mg{(XjPu<{E`hJ}TGUv(-K4 zz}NP)k->&uSaE-h-ZJx)%6-Z6PrWPdK~M^L4)130z5_&dqrCV&Xh}1?>8&c#243fs5-aZaz8hZ{LH)bem0xecS^drjX5mx%)%^H9S_s@?h8)aan3&;TN zHbOAx5C!$N zn4OW5<^(Rak{%iPdch}2i#gpgq|yrF@i@azDyC?D9zOwWd+P~H%-^jAxp>%liWOay zA$1f56-&>c_vJ}L_cT6lCQY&?b5ESO3;Cid&%160q*AZ?mqhLgoA$?ztjWnD>K1Z-*m5?9JF|o-hcV~}2^a2m_3FBea zdD-UG7(W46OKuY#i5HdZj7Qkk8;!=b*W?!SyK7#1Pm>TXf&s!HwBtimYqYZGA(TKKd>@pz&Q#TIb>ZqP z&#C?o7t5=I--N?tLZ;a{@n~C&)gp7#48UR$@3*v3c$8J_@0=-7-clo4ou;y-@+?%b zY4uQmn)h`Hqak|}B4IxGI&h=4v$MH+iNH@V1|Oi32;OO9jw2o~i(6QCDk`CjUc)Xb zzl>uYoiA>oJ0zd=JXkgt_>#@Vfb(=YjV8iVMotY`c$*{ZJRPq+XONQ$^mt~OWF1pO zNpYG?Lve$)g2<iVeH2M z3y0IRCr&)iz&@tcCtPdORAxTNm>j(N3DLUqZ_Dp9X35D#4RSN92rNf3yoaFv%z$89 zZO?of?n}AtR9C1$OSWxAOM9Cp{1#*to!BG4qJW{Q4f*>8K3*B2TIY-0(;fV0mQCfn zUkO{z%pj!g8Rk&RYR<@Psvv(3-0!#n{bNxULgVi5)6A8N3)L-Ytb&H^TGQcirp8j- zGpN)Ist!{o0S?$Y3j>npTwCAMyA5KRK#Hlh`0E)wiB0vUDD(zyE_3SM4xN?(vdQnT zvdQNjwsN{zN1$UOpU|s)A9{q%tz*P-m58Bhw|2wqkixCbm9KbEe$g-bKb{i-&dwZn zRnwB#ZHEf#5WOwwhA|j9l9v`>MNPhIuS=s0_D1_3Ln_?)#ZCN0H@7h*Z<0ew?1VDQ zcC`Ch;))mO7fmX>x9>5zYx_{6)gEvC?stLxYMmPKY<;5aqP7-2ntV2W%=?GI$^@5C zQ07ZNmJ&w!SkQENZzcF&jCLvkJI+5WRoN(Fz$|{MULd4y`+g}wuS7!Uk<*_vTzeL< zeSN&hEd5@@jLii3s|vq01xeBo4%yTbJ9*hlgX#2VA5bzocvc=0_Xh}G{&>BUq#EdG z0n?H;iPHjtWQ{0jl`$imT_gxCn5giNPYu)nYWE+<3O{klfv|Ug$2D8g05t1ldh$UI zl^#KuIzSzv+|A5;86-q2+NMgQ@e1W2e=Y)}zP}fkJ&KxIgdNM9t8Vd9elEwF$OM!} zaxIK}SCkwQDivE&!ID37R87h`uO?^1i5N+-F-z<_eKun{^cb)kjUhz;?cf4ON(x6F zicaH5u?&RE3?eeliH`Qo%LpgTCSVkiqSr*Mf^Dr z{O~;PN3q-N_YkPkHYk?cBj_MT?rDFyCcHA+81c*kqs+h?8>&Ua9lo2avsBjy=jYdJ zkky%ZDY#OvI?)i7B|x!*J%#Ia{9^KkU#M}JqStlR?2YxBI?-WqACgVFrLG+-t}DTU zq~tfQ1L&-~d@|9gEItCOl~-@kNkm4Tx_DX?(QE{zErSzX$Y}pTzBm+ZPcJ;t(Nff< zk%EFfcsOBp;@kLg8#wZQ?~mCk15#xYy?D?=F-YQ z0eyK5L5qi5@VN>CA>Iy4suhF;V=sU21v`??=B{9(W(_V)GuMNC~bgX|>who-Pu> zTG~yIC#G$;z+3pj5uu4MP3MxlgjPx4EDa}QL*>8%4nPO1cxo@6Rcgv!h`NL_B}Sd| zOA+|`IoUhAYN}&VK{vX5`4FAY04(wX5(XZjLkf4{&L}I9B!vr(ew}v-dn12(vG2X@ zX_E;k;xuC=Jjy&&*7u%lDa^&VP}W_DZvqz2%v0G?bO7OZxpN`OB3`X&oc(VXl2ug+ z@ei#C1%N9>(r=(SXmj!^cGXo6^xhnQRSY&HilWgwK=5(JsH8SrQ4B*7Fv@ z4>T;HOsCjakh{XTMl2i~f}x}u5&=F%*1q(u&o(Z+WO89ZKr@AWjB zTuK3jznp785}1i7;R^1NjaU@pVSD=>ZW>=+@bHjdCJybvht;Qh7R|LQP;O;=z%?HB zbpWwJgkI`=I3hhErPmDY&+u??z*-xhgYa>*-J{33rPyUsE2rfo)(XBQpbU)Vd)g}k zhS_fNP{q!_!zG0f>NcCYKBMWmN59b@27?tKb48?ov**d}$)4)^q<^_sPO|Gd2ZaLy zp4JgE=$Xh|Cm>s~I&=ks&Tf{BLLnH&um;f0f?+zWS=l;A(KBUzUOwtj5bO}_Y5DR? z)ZkkwXA!D?#+{syi2461ol9t@j~jgCb?6^)qhKC%u^DVXV`Z^Rfi(*yZGfKn`q-OZ zQIWvq1`^4jg+bk`D`hlHF7H&3euB<^wL^KQ2_#j5EF>_Tx;we_!y-_enjQzQg9{KP zJB8q%{Nt z#3IdAr}u`=YZr{h;I6jziPD=p;n?WqSPX0h**G0@I}<$k1pcq$2?P|-KjJ21=Wr0f ze-~xVU%6yjk-Oku{|$z;1}_Qm*Fkp&KKjRBctwpMDe@Qc+alZ}{R5LZd=U=*8j1Z7I)M@X zlP;M`W@!;H5KtOea&#C1Zt_(i0z?x+07A>ZhcFh1p!PSHWQq`ke`DH&AfWtf3=Bh< z{Tov&9KjIupP0X9jB>0%fq-}r{u7flxds{yvgsiT!3FfMr(GNZ4dh>#or1uI`4=u# zBXIqD)aZ2xRsW7ZRF9Af@=sJ>^U`Dy5Fnr{h-Ai)uS|7e(cqhs8WEKL{nJG=LK^tr zP?4PoT!??+$OHmD)L(cqkKhXP7aDINl)(Rm$QKBk5dRE7Otds(?ZK1M-gtkhpd_3lI1mQa(T5>)-;=d>E5*|_J?<^$?A|v+wlNWmO zvg!j25YRkbGBOGxAwbjGc9j$5<3g{;Ltt3Ux-Sg%lC1>MY}RSD!^*>K*1+EU=QK)U zO&mEs)xL4W`z4Q8{0~WovyBU#DM7pl64NaAeYnCDV@p;cr%cldK~_ooK-jg}MVe6w z^^|hvLVXNmPY}`rOu$x$I!eBIkDZ68o9H|oZ67Tiql{btZk$mn3(Bk~mL~Y)u^Zl95>7YsC`_jjm<ezmxvpS^<=R2?7X?~e@ zLhjOjt~_IR7~fdAA$o4$;F{poB1uMt2G0;m{F{xb=>gxVewslMk1C8b8GFJ-f4^wj z(bYyxj)+xM1Ra`nC1(=h5fUL2>tsOa)n@4cN38JzD9YebLL#$-I8Zz-RbG{pYLfml=uu#E5b9a5l4q#M3Y`{fv95^fm$SeV_m)vnf%qrQG+vWxH==+icLbNhD72 zKy1IztcVw};RJ}{;E-rghb!N>X;7h>SltC_{Oz*7k(7ug#WNFID@AW)XD?Lsk(2jG zmtttQ4N^GF`-(mK5)s0DBQ0%auoTRUH)ueDS;ktKnuhD&hd<~T2QQD3B z`{h71sJs>&M5E%fRxr23{-k9-$fYiFBQ1f$jb0e&sv6@`|ABuy0gJ2^dyKEB&A-yX+5bN>Eim zk$vA#virf<8eR3T25bYm!7983FWw>VI(bR=1o?A(>n%hAU_Ffz@LKlj{m2Qfom~&h zfgGmAD7Nf)(Y-LyLT|sPhL=GmS@I(`v?FSE6f(0L8-^0PO)#_a8#~xdfp?oX9Vkk$ zM3l?D%Uf~ngN9YZ4^6_RM{>_z(&txzGKFQz=nOtx6|xM91GtR>&9uyh-(-jmII{8* z_&^x_7__A_Kvn{w<(b+L@qV(%v#lGWZSef3ZXAumH;K8eMK(K~gT;9z#xOsdHz;&XxoWJ~O(^vr&NZ_d<-i}`0RghxXZK9atyL90YWvmaMBhb$UN~nP zYVIBu?Si5~o1&)awlM1f0V{AdjCvd4Ca`aM4FZyCcApOFz}3Zqmabg_nZe?dx(M~T ze=HH@xwW@@GL1Az9wy}_CqhDKG^0#UVlw{=yn4@x7YrsB)a@xdUsrfYvwG*o<%O7~7M$hzxwf)CfkX45eb5^r zqgo*S-8JOcMDvp&+9IKTy43kFE)MgwL#>pM1Wg_v^Z09kXEgj&9s5h8g>wY0utbtB z+bOI>fvIS;J4L3dT#+ThiAHhINv+r`EvVAIvA#o_Lg2-2x_NspNPV7!UiG^r3&#;T+RlK<}Juua#G6-#5^l_F84q; z-IOnC+n`Z>9FAr$=4{_S)Zdd0Z;EWLUSZxPsmDh zwg-$ZEBom?SGuy7%AjI;vocNv@+i*NY0)SIz;!N_-d$0zI5T2UkfaVNI@Uq2q>D!Z z+v;zp#J4y)IT30O>{f<&x2_dKG6>hI%(4Ne|ma z#Ur;Yc}nJQ9-DTLr50JAF1fmcH0EW$!qlde3x@Q-COuKkW$KvI9}|Mrri?0fGoV~L z0WVc5TAZyV(V7MUh1~I5RfG1Y1hlLNgpSaevUXYVtjq=+_rHb2Ub(6tEfU@lA|_1G zkDj$V54oWCuAc;D99TCWIx%e9%jd(c66d<~B-5J~oM_ECHt3Q*4(;>h&+r(jf4hQB z9Q-^AB|=L5jPqd@!TMIXmz z`|Fsifc=H(;#5_(*L~m9$Ga{6#}_&5<9yruAh`>FedxdQ*>gn9MVvM@dhwb8p90I$+H(hMkUIVp6L@^*T5n_NY$H>t&&u{+ zB_Dfskc(P3?kMb;{wd3P=Q}zJP%wD1M6@DDNlSkx>eG=}UW#+jjoFa8)!%k|$f3Z%T+iL`QG4f%!GIsyd z?Dp3Eh+^i;L7WvlDmPBS>v?NfOS}X&+`usOeSm1~;pD`+U-i@Hy&6u_LT*_HU>++y z1zJB6K`W$bI*vkfw7!1((iYNt#{$xp@m()xQ(8c{UW(xksCA9wKv*vM>gB`pHPM?f z6QK%9#oQ{RnjLZdDeNpJ#NgBQ@F~ol#rVU)>lCmOzfk=-T?yaR=?>C-;b=KD$kW{l z!QdnyWNL^sIc^u!J?O9+O`6{Zs8QVRXe~aq)Xm{Hu>%g~uDIu@L^ACE?3$Pmv%m%om0V$=FO2j~eb>*VO)am8 z|FSS1^rpbZC~PxP^NIyw(~ke#H?6tBQX$A6HB@$wq>fS8XDZ_rOB^b>VNs7N|8G)n zaO^%1xG}a8yVusdol(|b1qlDy4mB}#MLqvT*H7#On}fTnZeCGCi~qB`UslhKdS*LV zOwlv+`2xv8#E7`b62ypb0M{CR!~<8xu7G>@FSKyj^TMm14S9O|)0^P!4Z+6;@|Nf6 z8Grn8>(KS)N%p|?=9cG+2n}vh;=rSJUEOOlUHs|*xji*MeXvA3rfNrPekK-O+)!D2 z%VN)BXVat#qe``ky$a`Xt%bXpyQQ_6<{U=m8p=o`iXpoy_7D6#A6 zsSZ?Q$&dC-5W|HCmM1m{f0()Xu!pa{lp(;=L`e_galELrrj#L`oJ+%z!gA6`LN;md zt6RtzNn`n%kGHRxVeX25&K$oq@WH%oOW7QFqd#zE>WX;Q`QN5P-lxW*^08|MN;@6-%siH9pl@_E2lwV4Io!0*fK{AA3=AUwykIE>&Wb#YD6g zHU#ecsMzm1h00WYBMctg`818QREoG!shIztW&u*?=xmp$-ER@0t);=?cC5go@v-uC zE$iueDC=7OZF7_P-Ih_K|81>i)l>5{QklMI+!_HodR}~<{%scp7li}`1cg}zS%vgZ zZpF5X>2oqCIw!&>N+(h$9E-^{q=;m|NXhf0h~&U%$*=#}pd=HMA(8_yJ|eF40zXOK zFt@v)K1H7xdI8A)F)=hw%}eN<0pJy56y>rntTDMBW#Rv08-ITFosCN~NdCMZj z6R*vf31kNIN8DJkV<>iKjCj)`#Zf=fuQmfeDc(4?yP!X1o@{#os2?&<9NU|L|8H>U z4fqMr*>!whxqof}Y*!x+j+vgHRbF_+c_ezgw%afZq>jr`+{TZ*8U0^^fd9k54;k5# z9~G0gJ;nj>qZFLvZscI(BIMH)j{&jwjiUdHwYQ9_quJI*aSd((g1ZL~9xMqEAh?tYuRd!PNCGwvPd`*FvZRr9H7U367fSNAHaOY=OW z$5`H@>H%DFFU2+=#5HGn*aF;{+L+o{#Me31$QwP+DNX6{#rr)qu_RRdm@-(57>$_E zax{QB3C#iuxpgYJA^8tvI!Zw1I|#L&3TmixU++2dJ5Lvnz)2QAeVp%6aZ%NgnE?d> zKfM$5e}8{@#-LKF=@HnUl`s6GzXLxZ5f_S!pTP7|N48FjY=cI7+et4Cl924~{^8c0<3ODw5grTNZ>^sj_*j1t`pz5O< zKeL@~m=4GeC<^#nF9a0{jrI@is_n{ty=M{3k$K?LYh)f*ICEseRbO+g>yN6j?39yK z=QQw z{EzZ~75}OI$>-_zMS!G9||>A3j*sKeZ0%HVOg<$hf3v18HV4N~TnNG>;( z7}bXf2~l?#jf}0ckQd=et2faUG}~_=@QIb7B`{nJJ-Y7>>S^ER`06Ikz25kiR_H&7 z$_Gp$BudVfcKoW@m2z#}e_ji3+fzqoFEgT%Ly;^y(O! z;oZw}1UydD<{gRa1em%Bme{{F!0?+#3z|kl+w0KnogDKe9rI1lchPu&nzC*}3u~ir5vXf@ zzqoIrB(I7|srC%e_>YJ0y2CXtXt?rn(Z#oMxCSdks6urU}H%&(tGwo~c z+O*2aQJk=+EO}~-xnf_3%E=y+`)ApQnCw58Cx#~oiKhw>9VV<7IR9vb6H-O!B6Bd*Zs zc;1Q!o_tXP96l@YUd-YN?^r)tQ5f#S>)gUvl`<$5O~Mik3PY%vvG6!2L|bQ&Yc60X zMD4kNI@qXTY81`UpaxFj+D4ga>OagClcdY%Z!SD&8W(!??E)sjSq(E589@D((a}^o z;=@{R=!<{!XF?S|J#ce@4wCyOMstXD*Pnu4`O=-hvX;ZSna$Y;nV8WM)E0RSgzA7H zS!}1T;$N{-@im)uu#twLi8`862=E0LaK5e^iUxO1z^I$fiomE7@D}4++VFoy{bIj2 z!Zjd^Z2EVEeHD$+41lw#A!Ra$G}m1Rnm$Gxwb0xy{`O7U44V4Vz9+4(afJk?=xX;r$RL5xqtfX)MOt&>Ae)EOQapMcn%} z)V7m75(b0;hUrca%CO;_Dy+FP7%zkfA4&}hMQ^46!R`zvjd+}gQmJm#8!5e~3Z0F3 z?h7FaZYwdd`d~d${yz-(?H9k1jw!8eGaAd|y36C*Ej1JK$1_Jmm~mn?)^cP!mFZ5D z>5TJZKIg}jsme5}%4inQ>KD+ms^M~|;l?wEK$ubGzIOt0-ve@FS8`5Tq2 z`~N@8lM+7jbCPwq(uqD}1B{TFk1_wu8cA83;8|N6lO}cVZe_Nvp>PeDzNQD(#NYn8 z+@+Iob$02FR!r0&zJ9^yZ03sRBuXei^aFuQIA`!Df5+K|K%y7ShBWTr?jS~Du_E}O zc+{b%f9OSBu2Sa3BD`&!b;4{NhqfnU4kf*A!+e07}-o2*?4&w_+L(azMfd3=Ud3P zp31jwyqtm}3%n$TnYQ_K|4h+jGE;n?^cLI3IqDPD^vewX)REa;Q=U}4SvcI(u^9~7 zMhnYJxJ27e35MUyae>V;{~VBz6omWdoMYQqGP|oGVo&)n*QA+rEbqitQyNW zEsDy!Nq8nSO)yBT_TowB98JP`L0JZ$MG;0b35k`zLx&GQdKgdoFB@xe3`|w?)2WOf zDQcCHytllGUbItMyh5s#m6on~AI-=2KKvrTivRFyNN_5{-;q`SYlVw?4W`*{ku{l< zGw68yv9!{C??cVdMtO&@>w-kI=w%cD0=nk$k>p2sP2*?Z`X5DTuE)>?(U+#h8Z?DP3^|$ zXfECT%o{`fmjjuvznW7W%~V@~K>82=?=}Jc_GJ|qdx@CpH8{UfS!P>VcB0W@S$b*h zP>x87{NV*(X(E?vHzTpk`c`11W+KPglvMy2jI)OR{DwzJIyJBZe4129tg}n?pMBHX z&^Xhv{Rxa)k4f*)?A|Y>@`M|I2Qc_P!+UT^DVC9t?JY=0w{`P&3VzPA{{kKumz}EV%Nz=fD&#R*Dv-a(b@)NPBB8gr+Th?1Z zK+19mSzcd*6kg=9=`cQra%mr_FdmJVJA*lG{orG?iaYuRC zWu2z?QU9*CwIbnOpK-DF%Yd+b)SAMQt_DZ+3)Au&$^*Mwo`^m&(-mA~9|Qiw;MbES zN&GKtKXda7&G1t<9ee=iG4TqR2T5f6q~$vNEiH}54<`{`*qlRN&C|b|aSU8e0ah22 z_?Xo$2k4cH`RJ4oX|I>uXIZzWao=5KDG0SeU||!?uczzFzcmY}Zg!8^pN`qDeyW>R zfi5%6-xVwcq)#i7V(Xu)x_I8K@K7B z44n<6Khqe@4cO`A_N*U_oGD2=z2_E!X^7Z$-(EWEgf<5Fta|teeFNr~-(qKU9*_<9 z67+~`AyVl&-ZgYo9)@;05pK!gG|Rqu3|u!D!f<7}f1R3xPPWL+crx$jNJ!QYhtj>; zvlnxI%BHT=UitF)Pq4YZ;i%YN z5N`$r(MO1I^JkNW0glc$vaH>%6-SF=x1i(BnUeO%AZKL=ihW3DRcXFRW@DDNu)De8jzoNT-3R$e9K9Y0ok!|JJ zCS!qZxq=5X+RsG@cQMQ5z)=dVR@9;3kz7QNpIA+&f!>wED6W`|*%E{&^7|Kq6Jd2E zADJ^v;w!o_6HurciP!+8oqU4sUTs*qG5h6cM{>{}=2ni=NiajDD1>R5x<(Xg30>l7 zH9!DheG(@LH!kUXSY6d!nXXuliV zxD@G5{)m6c&aVZmEBEf+^`Y{?ti8c?0T!QEvX|Ip*Dr6*c8gI#gq&>;tiPf ziAy}a@^^2narc#vNRQmw7QeKhKVaUiY?fl)RVe6^T{SEnwk{$9$Uc2`T4YyUcDh%# zb1{eA#Q^M`k>t)7{VjW1Jf15kz$+J7lR2E zE4WAeJ56&oE%Rd3y9#|xysLFjNA$&5oeFjxyenQ6bJ&)jJFH8Sx+#cvKZ+`S4Jus- zkF20Wa6Z2#wOUJ2h0w3oh1}71k6q9oNUzMi%K_UZ$oVSt%Ol|(|4|r4v%XIq?IY_R z2V38R7JoAbqYv*w^W9ZLh#dt%>~6X3_Y@^J6YsOELnfc?h7e7$1+HQ0B6~;-ao|0| zbfNQ9k#mJs{qB{55tBsEC7D@MU#Uivvf!k2q%LV_NfM@8YAAc}kt!b;PPWL517{>(cAg;U#Yvv53WLxnBt~ z=|mYCBS|9|XY6ONf}2y{{B8;B504>W<3@_^#f$?c79;L68hT@0F(#V zyC27VzJI|}TT}P}|FrT`14CZ(VIcxfEi7lbkkBfI_=xbI_7*J?r2pIU0NMlUo!k+} zl7Sxp`-m%4V~9n!X`h@eDQ3I9`9|!dZFbUuRfS7#bNX@GjNk?#KXa=Jov&LF=dm8)^bm|K^-X_qH*? zay;|fog0RT65PJ^*?L||!yfj6*(?~DUxrxRtJCZ{##dD;_2WVs4?^eRD7uI*d0^`6 z;lHgz`rn)9a@UpYijJM1VM)@ z!Rvfe%V1CWig~H9|D3=}ZMo2o1NF<$Kd6-1OYKN4uoSJi;7F|v(y6(L_V)sZEbY$y zr}3XIcL47W<0@%MjEXWIau)ggc2nwld=EGg^!sr|0uT84fCX_1 ziL`W%42o+AI6T@TwGsQOaKXvK3{k#=hOX8RA7{@V!*# z2s@(Ko;l8~mZ4bK)G*vF(=k>9<{d=%6&4vJ_7xU6(CI@sH5`KoAo-LR=D>&@cI-jF zECheb4Yg}^YYAa_A);$_ z@I7l;n)IIemwQ%YG4#JjBd&xfLBkv_VM4n8Px|qmHo5e4RAOL zynWQWIovY9_397bwX1)~rqL!4iVQX^yj%E%O=POZ6^MP;AlJ+xaa-K)y*vGSZXNrE zxRn01i{&~$L{H)_k~bo2_MApBQt+A6xUcm0bCLy7k@Dhy#`oS-W)Zmic85hRK%E?#5A;tx>G*94FxnDsD$e z5ksj|W%JriWyvDl0PJ;lLmYk;x4uehPw_9sw)yU3wuXb(kPkC>ixmU3XSX9wXRE&> zAwI%4$D_l?S+0FlWAkL-&T;DpffmMEZx=sf`RsZg(FAQSVc8_)wpr00IsuGsOq(wH z=KJ@I5WcxwDoe@sU$K0uJQi1n(?@P%f+_pH9xpTps75eJ5gXzpuTnj+hlA)aN+oUm zJ5g-f>)nHI!ZxW?Bb76gaLk+#-Ps%wTQNv3U%>G9hKJns#h{Gb8;55?zF=a7zCRAP*ijUA5^Dc$qu%N}Yx zJT_%x*k?qFr4LFw9O;>AnBV6EvNF|{)mw{CsP_tJxaV3DE3{2U|pWHeyQI zDv%13(C+M5*15+{-Y1oThsl=l#to-s>3{Rk`P0WUuB4Y`-43sv$KdH$oewo3L{L7gV4g z8>v9xdlF2YWcAwjtC#1*Qc~^g(!}PC$27nOF3oM-#HcjuH7=6C=u$xpuIBrD@k^eD9> zKjy0rLzJ5^bNYv@KS{`Q!i;m9?8EHqQ%CZQ79&YLlN?gPM=-AWdAQJ+Ud-%K;W+)} z72;=FW@`3Ws4Mm;%+rw}&+s$N-9F8fjZmTyW!Njh)$(Pei(kD)D2}b{xTp*%iRmn} zY5zS>D+2{D?{c8v6`IRA* z{*OO9mRBQ{p?-&_S4R~*OB*iR90#XfJTkPcVL5sQeJ{64WGr}wRu*zP69fz2F7s@g z;?a|s3co}Zialdq3l#3B;7!hT4Tit&r4+yrtO}-_%Sk5z)`d55SC1*v#r=flLu{vV zq)3~*8;$hEEb}a0+Pp$CWTxPLP6Fk7#=~m!N>a!r9ow@`uF3t4zm$ocgt+7wQhGrq z_%u70Ga2NIwBLV(uJy6*RCZp(_%v^sO@ljF|N2U{InDxjF$yhav7_+1X_O?yqFfE> zrtHuY3R zH2ta}4RaSV*b?zR{lM&dC|kOoW6>=A5|Jb!23cPz&|p0}GD7)dO7X=+R-ACzH$E6ltXFB6W1UC|%&=(SOX1{|xNOWU^a@Q!XKmM@4 zm<#cUlOg3I(cD9qY$&K3N^?Y^-M%_rFEW?JYgtoKhY>?6dk$G_Uw?&{ytLFnyJFjp z+PSATWbwU6{EZJQMxqeaui1QW8uvv@yV#0qs<%Pu*R9;hQpJ0*|GsddwnP+* z4F2!xWX7mW2_kT1G69$<|5=@UB#uQ%Uio2j1rFxFyTQTFsdB}^z{DXz*d?%D0mSl( z8-0VpJ_)yuw+mar2hAj*`c>3SLTH$^tm>z0|(oWWqnk6@MOzaP0@D z8KL}ki)Kzry#3*RvH%`Y;@eEipm3tqe)YwSRYQyJh2pU2&T;2B&8^sU_NOqi1$g)qJK%FRU{>04cYB$DO%G!l2HF=KVSw<&Wmt2I)`do&f%l=^ z!=0PyL&UGekZU1cfPZjN{?u*YZk`Wt8(d7h7UBooek}%GH}C)&7oI6FMF`X^e!cya z6%xTk_|z;xz5P@be!)NyEj3GMZ$EWKdvFmCHA_TqKTXX^uwHoCNpP{SF-zps-}3*2 zSIxo?c7$;?t^G9H+#0meY{53-#^}mABV~y4IwKW`Haa8ai0b4a-`^UqM^D{6k*0fg zjZgOF`mxx!(AD0^_EqEoKUQ7<;>_fmep36)hD#;*Vit^%DVHiD`LW0 z3PQ1gm7$K6P0eHx)(6h8)305_m36meSBQi}SYZaH4%cN@bc7lp{K>HIsdWlwDA3vfy>Wow)PTcYqUs|dEOgC#X7?3S8qnoH$ zC^cLEU2$TePwgR!7?VYu_ zB|1q>`X_YlnsggK}vJ z@*j)oE7fDQ3j2!2O(!fXTt6o*7SWbX#3FJGz7ehzr30yfBMUJ7a?Yd`2zidsTWr@? z9CtGEvx^ne=EvDH<+~9yzmWoO!9GWp);YA7xiDBb0o|;|4%jq0Cv%~kSVof0Ze515 zswgpsn9GvJhd@O{1F7HF%f*lG!Q=~z11FR_my1U3QRla}n&fc7mzR~oy*KyptXNc? zx5!%L#=(~qXbHcp=L!?|gI=!QcX%0p_;q_&A-n}{Qp1WBJ%9UFi`@C_fioT%u?a|C z7Z*BAGjtC=SP%<2fg=&@a(&}#Y*_tcZl(l zM?_kfZ3e~y2x4uHD5)FTua8t%zbO3Gyo;de@W#9CMs$j@ zwU5_Nmmk&MF`RPp7hJL~O|MHK48tUf<2?Oel^e=mmEJ!pRo_@Eg!*Q>R-lhJNcR#A z)KN`(gF2Jmb6?QyxuXaz=oX~ANU*d<0zQZ#2I~^D(l+@8G6t-dZBT0wc{6eo@EFZ>$s^uN>7=KV>^Q!Xg$0rSj z25B_m-G{kP9pi7-5XA7^X6!#k1}uGDQ6N<)!RS?+`vi3KRm0XlxzzJfX*lGv>pbUu z;_?iW^lQuqf6S1x{_-5ufA~83Kb#Kpi4TpMVgJK(aI*;41i@2XjaVOnZtrL#Ua}&h z7td)4@+e&>r)5UuX{zrMmMDJh&Pk*aOWinDS8+|U4q$^=dy`Q&9`96Gyre#zA2P!i z8adPUOP?Ui4td*$R@`bR_A=&ad|VU8Bvc`|MMZA2FccQ%zT1 z2<1Af8ZJ3%Hlx6Ybs>{X%0n$#h2hUs;Yz5WcojtxRcp0j%7~wycS5kyV9dogEkW@s zjjjg3Ir&HkyZP#i0`|jr2b=`P<2$h#_Xq`hWR0$Fp^O=Q5w=#fSxi&bk3SHJ0osL$ z_4irN&ehkJV{(;(JXjVc%#^ZNgAZcY;Xc?&J0}*_5@#Zm=MB0CvZ9>Q92X~^7Hj2| zr3EjWiYHKTy5QHxS;l?+anolBE1r<{?#gcu*m-M?P#1+BG9EdEYEPv>9&jC^`98wq zvyyM&*WMpKJanxgnA?2}<5|?pSAGG@y;#lJlz&blC(-SzU(`28^5fzwaK1bBW`$!) zMi&n{G&wE`97BomqzHp&OMVkd85~)QZa+?%*c9o8267pYquW0`cW;QKqh-sg`I<>FxWkG;~A;DU^U$_z0=jlEG%CE|j)9^9CE zVFT45=wo>u2IMGA7VJpX19#GDc>#(KvM^FK2Q%yEnatq!E!!_ukJ4}@)uN&j8s)B} z321q!T4nP50y>52@C{YPC2l?f>JpreUo^l0fS2P9`%%9yjLxa?8eHi!)UuWEX!J%d z>eh+I=k={Dg$SDU-MxtVS~RWwyib-LLoDzKZ%Se4U8mchPq(v>BE0IO(fMo^3&Y@U zie73>xI`Oiz5KlxE_p4Qt+7JhH&(bJP{S3)KIU!BQ9nDZ!bvZoJ~04Z-=UycEyAmM zYMra!p8ff z9Os^pxYv?Opx1~>5Brl}7@QQ3K2S&8io%yOO9l}a;CSag^2s~5Mxffq z=11S$?$^Qa7lH!CH9EZ=4)LAC+D*h@QX|c=J%R~ZHlb9U4kOU9vhe86=3#Enqa1oPg(PI3X{N}fzF%YtSghBfH$0VL-Z4X z|F=Z)-@pxV>Z3rHZtCt^#3>}2C(r}@Tg31Lq`y8uU%i;jQ2d?I!k*ggvZdm@RT>uN zKz4&qcC)*pGpC!1@8n(*rs80QGDf(@ywK^g`owLs*VktJbi076WZhZu68=tysubPd znDK3Dc$oIJmc&FzaO$PKF9h4z^}Bh z4b~V)){Xw&0tPC6|2{er1Z-}O(##J*pR4Ek2n4R4Z2LR$r!PUEdn3|S(D@{RcH*m8 zgU(JW*2+b18lSwS-#762CmIv4$cOkt`Mgt%5m)3XiOvV*BS`CZzv1 z0sb#+{$o;G_ENfH<0lxeNG7_dp2_x)yo@X--8Lwx-FVrhn++awUN;+G>&Mf<zoc;>cQC z15U)H9oHu?pKhlGb2D_{7_=Ryll5fvw*EXGyl>KeumwjhU@dg8ulQ-^9nDqm^7_e} zt`_sjJ7#U7;YmzZ?*h)&Sw^XApXQa)qH7Z}V9*eZIuaR_I#D7S6ZX+faPu37$xUke zB8@w*7GG>1Z+6F?imqWSG!&(&P3i|)l-pBqZujz{-U1dcM^ucOvePszj4OunW*CS> zMah`n%*1;Sxw#AQjf%d}RrS9nO-sXt@&1PDE2@C*E830tn!+3bOd#I``6kGTKu!d5 z2*~l^(j#SHM|$F5wpJ@(w*12_;jQR_T3v9|In1`{8tq#=M+b+Yd0%iuTEsvDVMCts1&XMS!HdFqq-+(pT)Z^f)O|m#MJ@$wYW&Vxgq@RuMy0rpFJ%4woLk5_8K*k;$C2vi zXV8T5bGGSIt8ex$l#6?9TH>`cYUYGH)osl`R6!2_f$yFX=<>7WvkwDwQ?nuSu!Sj5 zD-zqR@}T<**A9`~?bI=6p#-yoA9MRT8xz#kPM3NmZgcGOe6}UIlWmzBLbtUG(_&0z z@K-+riI@1$om%G!U12Y^HDQ`fj8H%SX-7NC{-S_KRvW0-Q;fV{_eqxwB5`mvzoIKq z2d;Dn=ByWTVjDKs_#*%G%{M!hd~|kfkx7=HbB5ZwK}*63g!C?l^hmE=ptc+$5czF< zTOA=&iGvq&o}1~6XhO8}0#^}%wx>`yS+UQfx(BW@J8=rzwvky1>-?QgI*aGio2Dfc ziRW4>!@9YwVMU|dlU@DBg~6;f-x=iQoWOlZn~D9Fg}y2-3J5cect_3F(@3ItZ5|=s z!pshu+tx0!maB0)o!(V;{?Og1S?^W0LP|`MNy|~NwAJ^DpV^74w_&IVa>*oaT3O}~ zf4)V4Wmk!yEft=G+7z@&AyT!Vo)e z!sT?7fSWDHKXh2B#`Rx?{{~Xo+(3$80!h&(DNzW>jTQPg@z0T`V$6Qr_?8&4-{kcE z0>*66d5;YJ{!qZ1C*@nRLGOI%m&Se5{X2;Rkf3(%vw~N1U8?o7anx?4I~%qygxzje zH^_1|z)yT1xcc;Ro0HmZ2@LDr+k3LEC3;fSj$0pieMoJvg4Vze&TknWtkli{;pgi^ z$p0et?g71T5Fv`Vh6U}~;Rp4}>j>Ml`-_rOviWyAK~*_TZu%|bPGLygeyV-V8( zJ@pA2{2>JN$xfn@5RT+T!lC!*=0BxP&-Gu;G9~Zh54ob53rTnQc>XRsWk%E3L zw%A@?clk$MJFi3F>`c>Eog3haTGIXt%H){j%shu5-%jU;24Q4@9(e0|vqLBB@byUP z@dL*ovoSgLF3t9y<@h~MDpf>Pzi#T4&E16M>^|RnvCoX{h@cNpLMEg z7ngARxljdZuxXo4OPVp`a9gpU-sGvi8(Ob~n~z_SpM9-itKd1F8PId^K80|L_FG17 z*T67})W@TfZ6OE*-5RyXj_-veHl&Ab59N%%!LBDh`oVD$NY&7!^4>fleS<^BfV2t2 z0url8vy*$RcXpvg!h+Z4iM~_)uDLpKm-~qR0W--*;>CKeKOoXpaJS076^}@0{C5VZ1Eeg`9t*{Uxv<;6Szd%u2)3(MCMX!vw( zU|pZ;`o~dkKaXJgC6{H_gO+UoyJfvQrc$91&1v3xaq~LdH)wB*#(>&dypUxn`$@|d zz+y144uF3wg~b2{_FFcHLOxh6+j@A@9cnkVS*yJH%>vKaH2YEg7w8Xf*&It}Tvg0= zs2_3ltM}sz-|y31jJi&5=I!&(+IZgXUkx8f4Y|4AdAbIE za2V5Il8|Y;Lfvn>a$yhNR3;1Wh>7)zV!rEPSo(!y4>7hWpg^gdN#zbT0LC_tH6J=n zpGIv|!s$a5T`?`lVM9;Rh`3N+V9a)%{X< zfcP`LrHIl(+*Q9=W~7}34QRJ6(LglByxB$bWA`bb+*;X0iy^N@avCY!>E28T@NtQa zN&mLZeIKeVQb4kiVb#|Crdx8w9R1{-B}8x!&J?vMOnH1Zg9%hAw9X*^582p6hO z_FiI=CJ>GGPgSNNAv6`LWJq#zmdH=Q>s!NQd6B2z`}-4HJF8}~G?1{%>-|QaguCfX zDg_$qqCK75NoiN z@_9)`5PVal1~vF}nwoKSLVM}8c(>2)`inL-JdlI#vaElq;MGDrzl5Wd?nEO`y<0{_ zd}U->h?{(KU8chds{ssS2=692kc5!Ds!{)}4ePowK86Y7Fvb5I!P-k8w6kn!ry4LE#((QhKZJ z-KY#2)v_j$L4}reb3)fexE5P}G3gnKRjBPH7#`VjZ7PZp%xwT+e_`CxRqVKI)S^I^ z3(mEvNM=rJ1ZIVvtGu6|PY&hQCZ0`(!^#=MjD$%TvPe}<@3N>`rl>7jeDJ&bV+=ZV zenkV#jNY`9FNi~9L`eA8{-R}m?lCI8aF< zE!T?>z7XgV3f$FGXpRVb8~IZM*|JjZcFJq(WJ(K31n%x{<1W>u^%ro~o8+S*Zc^@t zAO5Nu@c*jvs5uUUPkiJ+)qD3{D!zy039g@w=PyVBRV!kZ1&_FJvEu4)Om-r_x+$i# zyW?ufEmnuE*-ZL%hN~RH(srr)bt0>eH-U4-1=MRT$zfrNOG8u8U;!4hUs5=7MzqWuBo@3%IW5bMQROzwuI<^VmhtnZ-Gr zZ!)1*&LNe_=`mqDD=MY97a|-5VQ$=GyVQAWnb6PtYMJbQvg`$6mv1}bfh{Wq1686! zZUZ`XVZ|qe70gB&R}1|Nys@56ZyfKsH8GZR(8RFCxuUImehjxP0Wp*SiBDPs;IZjeXW>9ja12B88BfTa(4@y z(VZ{al3VB@xEm-x&R?8#cmEiJ`~ez@d3ULMZ$V%FSRUr`rj5ULfd;CsjCP=dT+q{@ z9{1Ie-k5!T0+A55a;A;dG+p(8YlQCYdPGSVCG1wKQl{g@wBy_J-w)1HT&tIbV&}-6 z@x(0#_xWNpHG`Uqe}FV-NVQU8d9%n_E-u~q9CB5&XNVKH$ISRTw23o|%jCN%WEU%u zjT`*5V7=|v!MwqIToA+#LW7x=AiE#;-kK?V&l_;rRokI1kkTueWvgV*l>M`Qi&50G8L<2P6vT94P3F7 z0ukJYJhcGU9UDu(&V8-UsXCDoD4$14alu(Hewd{o)m4wHy|Js6HwWuc_;`_v1WA5) zmGR&iGRO_&iYVkgUf{(JggynS+55))@hby_rTuDa4Ndy27aIA94ypr3T6}(ukhy%2kv{3u>z)Gv0iA$?iT{ZU)3lt?} zBn#&RrwRTHPV>;l5p&VS5j+1z?NdOmJT$nzCLn#M>LBzz?UhzevjR8qs~o~`8OAXc z%ir(O6!N7_$otRYw0UCvK|w+Ymq-rbK14{>$I)Q@qAxG(>cKJ=gFi@v_iDk?!uGql zD!_ZyY-#9IE)}>XBCpAA9H*Yoc!Etfuvs!2ORE+?g)i}_&V>fi2OKZ z@Irq2u=A{NCQ=8*TLFZ$MKciO-p^bI^)}YtVydEM(qE>vs|RYanbRsVmy(N_7(y?y zq<*`{F;=_{p*GOQ$1=QBTGRrMFaSn94?aBGC1U>hELUNA_jh`@R#1mf$rVGxWvs4?-1h?c-eWamd&fnN$ zkt#ENts$cH%o2p7K(@s;|BT#LJY03!2!R?gka0UsPN4AdK~-ofP$yocp3HoQx_4LP z6h?LTvWma;ZaMCv6b9r6#F3uYG?dulM0krC3|z;-75lyw?qA?;fusvoTeBzpE-ryJG0y z8NLk?(<^Q*u`LceXc_VESgfAA__QJl2`UVe$aZ$Sej{BIrb$$NM6eoat;l{5R;-vG zW?fRlUXd6G&D%M?W^Ym@qPy}PI~U8z&j1eKk}ONYe$;JR-z$C^_@GNEZan-eaM%2^ z7Td=Xa<3DEyFlC|)sisH#320XY{xkWQqFyc7~?18OfhIe(#_azf~Pfu@PSoTV^neS z{K9h=B@Q-@4eP2H{{5IWDC4_c z3*-Hk+Gf!F9(Ndf$@>pW2@p12+}24$C3tVY_$@)nRj_wvF7X3C+|$AC>r=m-pjF1! z{;nzh@<2+QBfQGThGOlU?h~mVo@L`*NGFpt!;Z@!2svu2&sAabl zz6)e{crcTePfue;ll`7k$?H%o5#TUn01jzNBU{{PCpo)X0aQRA7A9(&NBky!r`%*K zo|43+R9X72*LLr)XKp`*2EQwdSlFWy8qNF$kx%(9iI&mTc zYjxa$Qf=iG>Mj(?T1Bx3bm=V(HVr?-*;UyB{Y%6B-udr0;kNtl^zfz5v;EYu#*H*J z#7O+1V(LpdUl56Y&lC8w1xB|qWM!T9W)?xGB!a^u72TUUVh&&I{_uTsVm zI!TfbZ2L$`zTs%DW2B+q+bThBW!U?zM!0B=Kakh6nrRAcNkFoUz*ky4Z211Y%!drv zDU4R(B2?oKVZAR^op?3A#gSt3T%ezpz35C&XSE6b(R9Ze)H`m<`MM;cVq8wBICbXJ z`Gi7YuB&zvxSn<=KSkYczluBq+^TE8%Hvb+xQbBm0%$U-PzV7{K#Lr*S`}42Q~ryR zFt2ApLz-!)=C;U((B6&jtGzZp#695Z;}T)*M-}boJM8vKufH)a9rWX!i)F~9WgNgw zT8d0j^Zd@FD`B2jv(0>$Y&bgIw9Z0c_PP*%8kmlDAek-3TKyv*R}i*GZsUNqNz8<@ zas5(&lFDFMm^1aN&xf1DjV0=JX{sws3^K0CW2R;m{o8>j7}=^kO}R6 zvN&o0RwOS5+I3owHqtt5H3k}SdXFFy6*B%gvAUm@ zyQ<+E%6-w7G|{dIAEhc1vTwP$xwM?efsbz(Z3=$9%fV=pe#2_R$j;^XNz$o2T5dL+ zA)D;ol|vI09`&)866FfjpK_6bzzq9P1xXx$Dv}~Bi<)4Y-WG{t?>ixhSBUYU_<1i- z_MRj98{%+~AcTGHqtxsiKx(7b=R~==2@xNeEJPAFC?!VlZYp8?+U#SAeRj_6pI(|q zir{_UPPw%U0o5&Bj65$RSu{Ns8%P3>Hc$~WzPKxkTNtD&`;s^KjX;I7D0$e2nE@1= z0VgzxF>3D({DJ9I4Q!Hl@OjyFT^cb%%Uwo1@=j(31LJ`O%}>-PlX7cS4N;t;lnLeL zv!3`!k0JqU)2bc@s44+fL{B#Plv|P~wx52R@KCX3lJk~tMY}0*;z?Uk$2WbFXC)D_ zq>gU}fwqXHakhwpO{a0t<^m!0-OhaYt<}hgX&A z>O~1-{n~Ftm|4_+eKPCHeqLOpDUkcUTGzv^orK3zb)sTCtHL-YTwVQrIp~JUNAecR z>+CRL-r(7+2&reQT6u=EecAE|FWr{**cwG2EY6Ocnh`N40{%Zi5<1#E%ermYCA4=a zC*(dP)g_uV^mtRd`@wMF)#aE5bSioOAYUc)<>K0(gv{q#Rn+fKUh$Toa0@G>DE)yE zEJSevkxIbyv)myTOL*|!1q;n%gokFMthVRUUQm_twow6-hLrdI2QY!< zePuAIOL>PgX9CR^j3+)LiW<96Jj4~-*qOP)-t|-HyH9%Hul{mGLj^jo)prZ1Y`@ja zX8U2XIEG8r%5=R@S|bUwjYSjq*~>mv5LQN1G-0-uUt-DPCp@mkivdFRdWBa9?pqSx zm6K9o7un%4vs4A_ndKH?tE5}($_L=P8L1O)L~&{j;7a8G{So}r z_W=#L@TYXooXdj2JvtYQq>s_TrEP~`P%2lb{gj~k$v^n!h%rDlgBU18>;zEj7TBDBrrd z>)h4DO7d^%n}V8QiT&RHB#=t?U#S3}|2Go+Z+U*RI2pMAC;M+ZAy`1RHC7Yk+3a zSbSRTAmu)J)XZ$DZY-IvyOE8XkPQa{Qy# zuk;?P_9m=5#6eFNd8#&SqEg;jRs!r=AmMRf+m=>$+J% z&A6dZ*RVHyxWAOSda)u(AH$8_{Q+jsz<#!>)Tm{*Zh88}W;g?O<}M$ryPTq+M*Q8z zZyLsS8`xsZFUoQ>3fb$OgcXtAkB~;Z+ElX?=)s9SGP>ca5RNXJxHPBK-AYBXHHBTg#J! z!GDt)c~%q&zV+0KDiSWaF<`#HK<)2hvz4eu1-rWn%_sKM#@t<=N)uzd;THZ= zF1ux{>l76q!-3wk{Q@F&jT&}$O%dkO`K0DjtzNA0Tc;=!_Rv@DIyX#&ka&uIc>>1T z`;(!w&+IX;+J#Fnp52XJl&BiLv-B0E(tLTF`CRcL$S?m2`-B)HOA?&p3Deo@q48;bP2*~G#Hmd)=72=}Zf6fNIw|>@JzKOXfVSwi6nI6?G zfV1T)hwT17Z6+CI@wua~4A;jpgiTlaaBr#~nNwLP3n;^xs$ZkOm0dY&seWVneM_Ut z(A%&{H@O&VmfT*dif^oYl6b~dN%H&F^dQD~*g9Lk^{Jb%4xv)__gQGBD^!YHo0KKe zBEOq(wk!0iEUO}@tk^U%h`FW66<(W!#b!p0%-9I+&D2jL?e3uT-AQ)tx=QI(I~&Ue zHY>e0g!$aU$K%tO#-?bwDI6U?YtZbAunmW8R?F7Hvsfq6jP`9-ZEaB<_z$|?fRh)| zp8cAD!8uBBUZmfnF%NYK$}dgfC(5{IlpHkDj!1~eRyMgG=eDub|#iv< zdWQjitm~#cM}gko&uD8>Bj$F{aOWuvW$X-vN8mUo31}zV*dXqDw(Os%W<{(r<=|N& zS?;Y_F{_M~JC?C4+UM(mq_Q@){HM>1-O!Zh-{Z?@mAqnet9Q^O!!|2p)#0|c2(gaS zyJ?&1h&G)PTUC9K^CNpJ)sR0Y5Vjj9=w4tk-uE(M{hf7>=vEe`iRLs0Llr!tq`uWf zdr`zKPm^C}-Y6vdT9Vvm`-HA&X>TRFRJu+%ne4ncLO7^tru|s&!7AI1o@%GWqx-TI z&Ws}tDfR5O`q^CPBDK`5YX7(_CX0F?Ga-^XeHVJiDphzT>tBO*%6%#R4>H*2)Z~KY z$P4UGpVD`kMFwCpg$2e4$gjU|$m~D;6(dMU!u>Q;DR2Y|59z}*oETo62(MK9`=^1@ zMw$PEI5sx}xgb-h`SjC6714yJOgT~#ctZIBT8$pT2fy?{EBK2MW~{_ic8EdH5}Tai z1I_X;FPK4u8F84Qg&7ji_)y^Ejkb_^Nq|PGMjmGLu}^8bol)HNpk#8sLh!7|mj^Sj zr#>%r;EOVN>3^VrBj&y$yN*j&6BVjMYc z->ct?b3;u28RB&ez_`)p=pLvc2t-Aq{?=@!vS-M7{>uF)=AokK+siu2YoXfJXJ`4` z!<-&SQ|nr%0aoh#5$+06U&Y=Q_I7i6B29U~M1KC%{}RnQIK7ZY8FF+j6*?#6f@{K$ zOFvVTh4Al~h+-scrA2O&9LECz3gKTfv1kV6m*w!Un0P3FlP~Q=8098Xn^+s5?Vcb0 zqx0F&*36@Lppp+M!;+&EKb0;8-Fj{P{6ywfjms6AuBlKh)@j0%fvZb25sjGQ#Rhk^ zbt0vVOJi0iypr9D&KO^G`~nZbtMYe)wssL}xOs~%jB-&<{9{=xG2&3)`^J%d{o}Ny zysb|1vn9gNm9hhTJ`BECy08zQCv zEV=Bvci63jMOiY~v950~;HcV=!KSu=R&;Eu-M+ReNbsR@G#vB#w)^}J@>uY-Vz^y# z*F4m5B^61mHJ;ux-mY>RLF{drn3Y7=oj#oFfZ{)Kg-2%(C1#C6L8jKKUA#;6rJVCp%svn^7t8)>D4&>Ko=D zlvCd3gOA|o_7^13Bd>(TGl5e7Pz99XUROlnOy?37Vq~8mnakEMPI=us3SasOnnP+N zbF^byJh(ULfr94TL}=1kqsePX;4*Bv&GiXquE?bD1?FOrr#|PwkQ4SP=iH1rS48e5 zRhr+*E23pM<$Y@upH3UNhG}gtBu` zxT<`mx2TEUL7>1@l5hb}N_!r1iVBuwBMhjFcddzJ-k3a4eF9>_l;hHK@sU;`YiQO} zDpuDrzNbGR>4!@sf9Q@(pRHSGZ7&t35#I#+@e9||0^}$^Gwn6*=3iF({Q=w8pNO;3 zd>vJ=Lr&G`e~apr1p#q#g4mGqkfDqS@bEIRVZ6JjZPk+XfiR9S<>wy)<=C{p+k8ZU zJye5yC`^?kjKjw~>~+2(<33T>RSDFTszPiPw`jpEREps!GG-HdpA24{jgB8!{Bjb` z_ET3)eG)nMm}yxxFn%B_mg1OVZ?e3B&_<^=Qd0`e9+Sb}N7m{|$IJZWRkCn4$LmW$ zF&W1)wZK}Pl+tj{`9yBTr2JRT_pn}ZKsZED9d9-*N8c556=n3oZyIx znT@}U-!^d1CgrP04EVE2Tbe!Cf#;O4UhAa1c#D=`@LR|Lb6`j$RRl0A-l`?|N)m<{ zFr52`X)tV*EQ%FUP_i9+x%=GEZ;amr zGgpyyv&=;s=Gw4@DS2n?DXl~w)GXyT=GFx)sw@Z{mK+$29afLhqs;s4ss{LbWnL%8 zWi1ovK}uK!>`Qx)gd##-EDa3RkNhlUF0Q9|jfp2(eb3I5dR;2?Q@w4(94hpE7`T76 zKr@h%B8dg~%a(Jbt{+~8a(I@h8V_%|5ORlfcxJs9na+K5R^r?%h;VWJ70+>e)Z4%E zd1ou!S;ws7$@0hGU$cq7mOr}HRPGfd>*5)&jCjM(cNlKLHsOXxU_;zzbOGC}8a%*6 zr0%C_7l<{O!2++3Ff8m*p;V?tlG$SL7itU{DfQ(d$(Tb^U>o8&=sqC6`dC`XdZ4Z{ znJ8|Df0nPNsi<$2@PCI@O);OMPPNHIVjD3ZOV)2WZIfS^cBO3_bJ||vfxKKN;n#d+ z{iYM21^)(IAaXB}B)vM1ITiC7`PpOyo(xK6dLXZn%T~Yi-fy%%VS1dF)Jdm56%Q*g z_V1mq<#)I+TFn+40`fljp8RUPci*!)Vp$6H8RPwWc!EKnhxmiU!pyOpwOIhW5oHFoS?aezABI$nuX9PveO42*LqbCEdx?bx{45p* z-9`z7lW4OsFPj{h;81S8GY*yC7FlPSK;dPhz2DKIc?~Ox=ABknW}>H4)pd4E%de>+ zA1^;tF2k4K=9Y#We*1ntGruUx5R^Qv@{z9bLt*-ndhuLIef(bJkbva45N_tu;d@8N z`OV70!!i!DVOMd@M9+Za_%pASnYL^Kmv!|+?K&&Afm4+7RVk;|ta4d`)5mIYWDx`{ zUkNJXBJUf^xRp$4=2|Z^HXo~f(p5{cgfee??zT$ICf?h-JINWl`(2?-M+rdZ4!e;P zlX}KbJ_W&Ig&)bOe}SIEq|07hO+G;+>vg}#p{*wS^0o7jLHSNU7wzJEPLT(jUz-sc z0_XD@FAj*C0^i7>HJT07@tB^?wu?r7Q9FF>BOJiB{wttgh1CFq_qgMzDWu111ZtMj z6p3EGP^2}m%=7A8&w*!u+ez#+To)BpFn;6aQt?o8^Gq!+-yaWs?|g(PV9PN(I!Frp zO>n1fUrebpx<+WH83kpU&wKegW43?8tBhqOh*y}5JfX-3vK&tMS zs3{+MbFv0!n5}*_t9B8h`$9jlG;%0}l1E8!T&`-gSP}j8IjH-FhyvFN(K~tDgAv38 z?UCiKxt<~fbjWMqotj8S>T@6?nv>%6e$1?-FC2)Y^&QO0Dj+y2U%XD~suMo>BBb3r zWI%Z78R6fgSA&f7M-%V#YzL z@?X-3q+C)2Wbud?=mooYEyGJ(Iny}A2ahQd<4vCBP_VIzfH|Q*V?EaM7@Z&gL_Awk zk1JSYN59R@r1w*`eCJ2;i>~Ik;iJp2COv@)yOo1j9RiBSKQ}P~nnrJxBo&6Mt#Al` z_?+X@2(gd0=235NTx~%Kr!L-vgFg4J6odmlLPwqN4$-a=3Hy9jO%n)v9rZ7R;j_Jdte=mu+dV$9U8lknOcE9 zc%`X3F)WR6$A4%rFo4IG{*r+=xr;-tpfd6^!^<@j)S=g~DD+=(8I&QDg1{gS(7j2c$|(q3+>hs0v(t7C6TF`*=eYMT8>iX?cT66ETdq< zcYMR84E|_LCyM^KPcD=YF*+TK9gEbPf->=U5TOdWH$@KSVNmGRae0d2``3SQP#Gcd zH!PN!x)4$Fv&JPIx-;z)_u|3BmbkM3 z#Zxc{j4|k)2v&q4ZU_|j4>b#Uf+5ABW=YQ@u!d_XujK*^CEF=2BY|aGJPiNFj#J|= znn7-`Q3SbV2X7iES?#F{+m?#RyV57r3Bcz~rbHT?uXicmJACy*c9+wKbP-SvRWMh7 z?36^j=uF?GSmgC_#injh76^RvwSvVT!M!-dVe52Ctnk}^vR0XavF!i&gHdd(!?ZTo zx}5)mP$ydg#-xEqU}6(}|IM`(O}1ovn_8H_1--S}xM|E-(N?ySCN#t|$UOY*((OV} zOm3HX_$wed7|CP;qWDKifSSY8Cbg5E|2;U&{YSt592~BN>oD6JvUJxs%QHIFwj?O{ zuZ6cD;7a`|rDW|4#Nn^#muAaGU}ZeUk)iKI5!3TWp?RJEPg_x5r|IvvbqS(`w&=7X z7sX-Mkkg5T46M@|0lH{xA`eylPgQU&i5jEI75}5AgNrF{mrL@`_p_{r^?&5*|H!br z2Z~rK=pRarUD$@*K2WebxJPE|+t4>&^0vJGj22yjjRr5JSb^b6mM)I%>fKoFTWZ%>J0aU? zqwOXM-8@WPZFJp>!idvs>xk?IF|s%g=U zLLuVk2Kkv0v96TMb+qokDw=6M4&la)_-v zwYBcLUQzmWiPquC{NX+{TDnv#IoZ^IRqeJ4{Y>XhaV2&WX>RJDN|zhT*Lri`%BSo7 z+7>nquu`JjP=C}=E3UceovQget~oi;>PyqbAn|>1uy;l2YD&C~R5?;%~(inzm5GAKdQP#gOG^o~sAmsmx?51VVTA zGtwUE&JPP`U-1<4jl&DaCqQrn<4;5&XoA2irc$H@chRm331O>xDS{x0ea4j?3I>Bk zePkJO+E~EEVBXhQs^E;}N*&mYLJ;U$iL?XL{SjthJ+1B-n5l%BP|9uTA9rOi#{^2S zQncF&3}^*&fzB6(HJDr=nP%{B<1PimhPE*#av6&Ma}IL1h;!GvnsV1V0)!IE-91?_ zK*kM%8wgK9kOP4Q1UnE4fzKz(U1={BPdOh;+(c#l`JRo*L~cjkvwT^d|CXTtgEl#X zEjF20rw?2Y)Pd_w0?6$Pa@XnG*@=8fWFZ_`dOGeJizeR8a?4D9>hYi%?gS;I!YLBW z#nf7;){!W?RyIJsHu;qMziam*Dbu*HJf@K?cTB=OD__zY||NQ z-VD!0g;#1XdrRPV{-`Tc4&)TT+*e0PDA&wKZr+HpQ3t|`uQaxsK4-?Gy(x2dd*#3- zjL~AoZ{j|7BYBkjU+ApYtOJ*3STLEo>^!@-@C`3&xr*^h88VkjA^b;ZgXW*?)B=rT z)Ik>i4|X#YVq=M<1Ugh{olUy!XlpGeZzit{EiZ4cK8HJO{<3qe(ZFtVSX_K^!&jk) zRMN4vtXTpMgiL`aIAO(kYgsLD>6qIB|GUyrP;D_@B+}k$B$xjX|8)W7zFmVn6Stb{ zs7%UA*S9I->thY5SD^iO73F2O>Jh#F+r_Wqfq#ErIlAg=R?YI-j4X zHdlIYhiaidQyq=8IQahhWYN%>;M7&FHuCT06~;V{;niu^Q^?ki?T{ZbYRt*1nB!tx zMm)=Rg`aD@$^}ntZEcMXirBZSl4pv9pE7jI2}_(BW|tFihRw(%+;95VB@k9*kjCJNsU)3Bb#i%Uwu6QI1}?g*{J8JjcasJv)oAyg&exsQ5_y{c*I_qp$FAgPl4N70={60nvfZwS=`t}xdIN;Ra z&K$s1I8we5&Y9%XvWpSOj+4l7*%YWX1v{Uy#0>#g3MGL8C*S$&BqKO1P9IHbsrKZt z!xudL%lY5Hml3&P1`_;giv~`5h|5Aa$HlJooIeJfd!C$t@fT6%Ct>4P_*R?m<5@~4 z!=prZx>#hVUnn-Q6}!TNOHhqGg1i@)3U7lW8qOj z6P!b57|=H-ugyqb0yVkO4E6fRgo%^Sh!laZ5F=T7Abh^-djx+r&p z(ybCS#009H1~}O#GPdAV$x3T7<_amOr!_|-Ee)bnr>hrgLq3U3SLa%#YZwdM{4f+l zrsx~7r=XrI%#40A?Y!`6vg>-ck-;{$vc=0c(--1UQy)E2ZV&xFg;o&qDSryBdDyzc zv|M#7#B{1UvF5BhXE!-2H{8IV%F0|rLEs{|j#)!apj{S1izp&+v$_n(pF}eTGlVf- zt8ug~mEvA*pBm9vPFl2NzL$QR#sHW0jnyIQb;_H9CE?+r)Hh{Iw51Ul+PQFCYGR{j zCD7-Nl9v2x3;U(fLms6@58R1%Whgun zUMJ;KJB2`TOBE*k-quYyeKiD3H!wh)4yR?x9>TVwupacuvHU8R0MB#P7|YtQv5^>i z@nc(_wx9+9SU%{kgngZNqw<_IcplPF#9Ha%EfXaS)*@73HX^h#{7Oy3fiB_$IbQ`* zzK-`32_K^)Q%db&n~Z$=$c!*JC3fxDDsZ>W?lWbc?h2`DV3H2(+fX0@4tQKEQrHs3JM|PEklNzR^xgPGFtJ+8xmT% zeU&2bR;WI*fd6P%I9II&<$C1o1cm4+cKygex}S7MO86m{!V`oxfK7?Z{T>7tYsW3Rj+WJD7Irq1z9XA zRcEByYlA$iL*23)!lINnRl?X>X`eS)YF?+T4#CP0dJ+^{+!z6E)@M~Pl>Gue`sHWX zRH`RbefSgyj9V8|$lWBV)RZG^q+IR#XF;olR{_PW=n^B(Cyu%tCU4n&FhJy!b*Vo{ z;nd0nZqQX4<+`uT4e))!YfvtZT(j&Yk3Ijbp3AA*VRApbI^19Bz5$BTdfA)1scxrk zLRYT}5h13wHD-NdMocveKD*Gi$)D^ts@zE((#mC@eZ`qqiyk1$*$s|c$@&#rpTWd1 zF~%0}tjRq0Q*PU(V&t-Tvpx>H@7AO~5di_jWlp%u?!EXF7!C#s*i8&bHMVQ-$D6N- zNhSFTq+(;KF?KvAcLRMn#N*5gmceQ>U9}46V{G0WTp2_tnL?&?5e6bcToRGgbKI#C zWlvknkf)7PoTI5N!+F;fOGs20fZI}oHg-<9ETdjDwXJGmZ!GnMZEUXEl#da$rP~FI zSSX{+)*~v(>b@xnBkBQk9&`wtiwH@k&7XWoxwb2u3=}1` zA?B1a6eki?l{o7=l(Dq@#-_c+!SqT*k(-vxIxCuvFp%I zT9O*aN=v17X~fhThF=B~m36*^Hd-3_iZ75--7JD3IIw5b9)r&#OD;q&tPZ{#e2yYx zpRM^*w~Gc+N_z|@y4b;r3>%Km$DHWgcYo7ci}545r)0Ec(RuD1R}iD>JeGG+&LBej zYqLf~?0=hS(ny}Wza5MRgoYhEpOAWMSNyQQz9r}2l||=emcgL+pJuT(_^qa>&Wi&L z%fBt7?%&?oibp^Zxbu%gkmuydf45owB5OuZ-AFxKg;$OIgYV{v^Po}{{2;N3M8Xs1 z559AP)!%QTnW~wN_Hq>}exZ#aV~Wz8lhH|L}Db9k^pmeHquThP60MaOC?4)dvZ}*xIv8uKl$>6G+cJjPV350`>b{H zl2SVh_&xBsq3qPVFI<=OVQ;<3LzGsYl#$iQ2M&-`q3^!2(UjPKM>Of)QvCkWJlxd~Qm!TGFmnPTjI%yA!?H54SvhA>Mmf zCxvoVTXD{W(teUa-PW+xqaGjybsc@+%0g)8EJbLi+F`N_{4>QzldT5Ts-Y|!w8kks zv}qL~9M$Pc7K-TGD*4xcnZ&Gzzue8kX<2B%Y4MvTI~{LVvdyKtPnc#rO>LiU3TXQ~ zGmn!^catzJ>cZIm#UW{^v3;7>_nUL!-=H_Bd4t$JzWJ-@kAGCu%DpJKg|zmt3mARM zuD`qFRY=%bQwI)+>q`?*^abWrgv29YK&?_J)D^2(1%DU0FAxSG&p$&VgG~nd_Nr?B zOVg~q>nYcQ2`>u9CS^=R!#KD&M{VMEW(>`w?^v#VlJbsgXRYc#*^ zhz!PM*pDBq%`EAaz3gGohsf)W#;G}v#wp)qmtvT$REwA`b5e005m{X&O6+^P4Geof zGuaeS{2V=dQQChhz>b!0cAcRye7B)^l9BZ37;L<^Ri=h-^`y*vF|Xg4wUMP4vwoUe z3Am45xCjL1CaWFyye)FL1?|+mOAz;(q<-{e|1hUC#}sput3DK+x*}44I8?ovyglpV zIlYW@m(F<<_Ct4Mm{Xa+8JMw^1323k&D*%sGN!?Th9kq?W+vihyt4;Frn(#_K2MUb+Tw;kJU`{J zXoG9*N!j7aO4Q)ILzHQ56tGyvUHYD~S&IF z^C&qs8C;6sga3Isv)c`CGVqhz=-xm<-J1gJ-#5=gJ>}hqB!-U+<77vMkMd16FS6RF z&M#6-7zt!*ijoJPaN62c)ctpH5B#n-@f??<>_b`Ys$Z67Rsvd=sdZAHuU_9&nNWv`hh$p$;mP6srNk%hZzlI}tTbv{*S-IK}GPUKHQc)K6o>KYj zSL`#IHrzs2V*zh0Gg_4FIT|yAR4<8-cLHve_X)o@&9CzBwbIH*W;oJT0ER#YL+atXbkw-iP_V*A=B_9$s`jq=g( zu45S&&U>i5wzq|RMvJO-UCVlS-;tRqPQKjq`y%;FRoxuw{LyE%v0L(%?LUdqqtx4; z_p(0Cui~}x=WXZ@Mys-4sTMP1agq)7S_K z&8{)XxZ^iT_&^?>vF|B}bs_}T#IsLzODzrF3`0-n?E44A<9~jich8QfJrX9cUJ=tN zZ9}Vy<(hCG==r|eY~u25QhP zJ;ievt2p_ZKnB|>-DDUW`e*-RC?0JhH~wJhRo5{ms15{XB2Z`Hlcg}%gneIO)ZUm; zN(?YEU(M#v3HIsd%{NUpZ<;{JdP_oJz+Y&#dGqV7t+tNS%kIUHv#s)_9*sC_9_byU zq?^1u&WlcHp1VB$d~^}%!E)hIr2f<}AWx`wIWac*hCJ4S={X4B@6omS6sag2M@2sE zE|e@!kpx(k&#NdNSp~q=FAV9T!VOJZTR9^W#*`GvQX2fdPTZ2s8eDBUp;h>PeAcwe zaZx)k?4xi>%;df4bJSqQ4QAwErt~Y!t>(N#NWvPz z{J-eGfp6R5Fv5Ew0G)6CW_HA1+`SgyCGg4w97KQ4|AU_IRBaU> zdM;F3+cBxa4{z9VECK=_Q-yP5(F2sQK#QcG|6%8cEw(Vn41_n$V&l8aiFr%f5R2p% zw$lLlUyQL8(4w}B)X&g6Pt-(whZ9N`SA9j@Y#WCwCKAU=E1>v_`n%KO^3aQk0*dh9 zJk8+!+XafHfRd5lBBwA%ZvDN5|zOZ^GOJQn?UXml8|rL!vu&xWqMgXL=2F1V@k zubYz^JTr-Tox#t5-Tl}cz@cmKhVl!v@3^_hk>lbW8n<}0&*1ZZezUT%vM_*1fAepp z&^+Brb5^aO!Dz*IlU@pIw;r$t^Iw-tNqWsoj=8@k}b8*++7X21vNvs zZAjBBo%)tbx=GIU%MiCA=}OSY1VRmO0q3lgOiP4Q$EzHYz+{p$3@&!b0?*W_w#GUZAaIAM?5$R->W&} z9aWLoEOWZk6>0v|Qtz>@ouHLDqRl?DcDj&I)0E4{X2hUeedyjikPEfd50(1eESInQ zEVj-&e`~k?P?~K=X3<&u$lM-tmpIx#Y{*xh!e69zC;4aeC2jTUv=#1zqMG!?OWF!2MAd}M?!myZ}M1P~sig>EP=S5WyNtN_mqbc+)3HJaQU zmN8nfCu3G(G-JeK_%WqSjO^d9mXB4#H3()HyOxoMW*DSCPBTgQanoBh48|gg-A4Fl zg+j_$Up}$kjKt*RNIbE8X;_N+&R*KaL)zw)qd~mzqg76n9^wr0N*QfV+8!0FPvbELUU2UC%6=n@>b0&rS7lW_Xq71Vr53+E{hG}e?N zTxY?5%I%d2k*PVAr`Sj+yCnyx`l~l)1xoM6JIJMB{qP-Ei#dtEPH@;s1i#H37{9;I zWGE$rV$QY&ARY&rXhVK`xxd zf&~2PKG{3BXiqvXAax<+vnuwuX>Hb(lXE|5sGu z0~>nerHcZ81#@jw;lMdHEGs7o@G{>8K7tRZs6x*lRE3a#LRl|fbv(!ljfDh`sghFW zJ(RzIw$~g%@>?bF_0d58tWV(6J3jp2`z&jgKpmwA?*xLI-v{0$3_0mT^>6po6WX?E z%X%@}7lG>U(~|e%ays#e!8G{f&j0yULa=ukkbe|*7{UNpVIU<``3X|Q+86Q0SA}rU z*FmjK=E_5mS@sm)D9;ePH^+k`-Rk`+rT6CJYt* z(E4emcwCQra@$lS>i>Jw>O_d|MEFqQZy*dkXbZ7rKgfe)TMEEQQhUw#tK804+psGv z7)zG+$26nSZ<};V+8=84s40y+Y}thflYB?VpmT2Ybw5uM6RYtgfPDyV7Mti|_;{=`yMwWE#CtC^}<_#7p zacQi-`--H_;4g(V6|t#OM$5)0n3BZ~gMS zaF%x{qUtLB-L*zFiz`36d%Y)PbQ+lu*=4Q#@GqivB!^klPTxYuL~rRz@r1@l7@MZ- zus$nqN**u12D%ROk5hZA=pjiEU(*x~ct%lSe3uV3QKGz3;e1AGBBxVu`Z zwjOS&cE!vH{Hpe8zTgk{6}3i2uKT(Z%JfTrtb@3|xz}5)`TO}bcUui>V0*i3L=mAG z9X%~!Hx}4mS{(@&c5S;UK;+TD@ODpasvGwTDXge~M&)7}_02+{qr|x|Nmosq4d?dK zg9>e#H_3a?IOWdy-c0QHCJRK?vPdU3lz;1SfAyuIytT(Q0cy8EX%vlEdv?y}{nT2w zE(!nD42`tT%=vXFpY*L=-yYTAmj*lbc#au-X`L;zc(K~~TUW=v6er!fo}=ENhouIc z-%W!MBvBQZ_IY-QHO%KuTB)MmB+M(O24oC7lI7E5k?fmk&ui|varJ4Hf0kaOmuSR% z{G7**-^M`na*Rk4Vd^BQ@aCeg>Q!v*Qk@qFZn>95l` z6iz+o-u>M2MpVj7y?nix0o%=?)6J`&HKCM zR`p9vQFvTRcw7;2^o}^HDMg;eBibzqHL9ML9G?et?-2rwG#ebL4&QvWqR=tnz*@P3 zj2d{3yM-RJXPkr}_jvqxPK&k13kAN5+`3hSiG46}6f5*^+S@~a_FiY-FR&yOSP~ry zNXn#y`KQ1{BA93n6GySPF)b|(LS^8Ug|&`{GMcRM&lkGzAAehUR*n;TSLYD*ZofWg z55cIN8G89o2!IKxFkz7r>%_n??A>rc&;o)H`O8HLSUedP$A8R@`AiL^hhIa33MMW+ z36bNsWF+DHyZB-(jBZ3(gf8QiJVv_5I6s%mZ^@I%{~sdszqw9?9n5=~p_@{0Y)q1jsUm*C!muJK)d#(+oaa}1kbM`p{-B~8|rzXaD< zQ8-B&Mz2R>k?!pT|Fp9{zr0Jty!?voJtOtdM*YXr?sQvy&As@bngs5$QG}yw%#*Djxpf=!@d7 zo1Bgd&m)1wX0^+UCxto?El7cL%|SnPPQL!Y0^d9`j&O*U=dt5Su~cjLOHe*&zIpSc z*yir0xFbgK$+hW&u9u7cixtMT3;l$vD@9Yk8`OKaq2=0+6^z2CszeQ}G40(QCr{xW zyLZPYoKulddW!5$u>4+6*^<*@eQg?{LijyydP48l;4;TA{(=S4*@<+o?RJGu-W0ML$Ic4dtV5(_Mq8>Aiqf9GV7 z%7no8SBD0aOAOQ*;CkhXwo&?R-8%YQ@F?&@K-(h9mB8cln1}aSxW_jLd=$_-03iU} z!F!PsWV0V+K%5SiAeHs@4F-JmK3nDBLWTX#vN{qsp{qfFB9fXtBx`_Q`C!d*(Z*A#{l)sqmi@;j>*d|T)aX{t=H}koVGw&m(QMr&@zXVu z$NI=M64Kv$Yv0ivmJD7udvCBDA!#J}-3 zc4v0TWPL5}i0={It9>Bh_)#7FgR3ZR-aOC(M^v8QytyU8@h6iijGwivd9#l>?9Nxt zs6F#DsPJK#TVY3W&FhW?OF6KGKGv2rz8->-~39*q^dS4a>O6sw;7`figIBWIW(Jm+Hp;X#Cp%X60g ztwc;5LJE)24#LiE1X^Tr3O2Dn^nQq)#t2#n=E%cX{Bj1-zh3%1@ux$6iOnx*5cG@T zaR_n-ZKe1hbUzG#a}*owH0RF2uq|FtYk%Nw_dqB7uqufRs-z#NbpPsR7=T1rB@F_g z4udEFuqxOH>e?s?sF*F10JK>M3C$mOxw?<&JK-(cH{}+hN1~bTezJ#yd&TGs4Zeg0 z>2@DjR2vGz!n)4MK5`TlSy>AWZd1p_@G*Qn4?&#_O9URvh6cWbhz0lA>J!dKDeZU* z1W&dF^&dr@ulTHk>Uy1j{^YXoTp-8d!S&IH%=Yy{_`CY{rHz~0tCDk!titn8cdj!Z zGN$3~r~Eu7{XARUwp`66sr50cF4!|4-<&1v$ZKVK-2}z$2tM@atK87t=giLx=H8)J zKp*sf9bNaa=kQg&vHDQKWOb_&0lzDhhPQn2-A~mfP3y>WZBjn!Fs0rk0$zG_Hg9<> z4q-kq@7sm@#Jd}%y`ytm14$Fm1MKpD%Qv}-A(ze>% zdZ=^bD^s9O2`+q;FkynWs}nM6p|$XunE4MEkIEpK7!t_;$1;yMj_x1WGFnzJIN90Nvob ztR#BeV(6aq#_^4*pLL8T^JTG3$3nzy&6~0dt_ZGs1w7HZhxhvVBw8)2;Sl^S;w@yi zeGk3o5z9^`|0(OZUC`&EjMKD(vJ@X|=OxAC>90g~b?)dsLL$72oVdtirgzioKXgdK zY5$mKa+&9HDOmcCejAO0GRZY9w5!ceJ_F&dtV_1Iu1l|QNw)mB7HccXzDar;J>&QJ z%60L&5li9Co)1mb;Yr_;UC{R1#~B|Uf@3m@A&K{+qx!hxpO1M0Pi1bIDelNmj!<@Z zk{;f@Z*RUOqqv(sevYzpk?H0bH&f1BD@b%>f`S;H=|HbG)?3RSW=fk}WkRZCePooglc;6OlV0?J418VwfREe>$ zT!;I#*Qg<*0FD9l{Q$5D00{>303=2L{DAok1Ly+aS`eD6U=jWrHK8CB%2lueR11@A z08GKa4!{`<901^d1>gjL3kEI#RAJx-z!e4_01{x}nerMn=xbQ6f;#|H7`Orug8>A5 zo)iKfKL9i^2ml}k08$77WD1i)00hAx3_v~%A^?1c!T<9i_AWeen<+J-!%L-f6Ru@2 zqKk(?D}a`z$XOJ7?wdh5b4z;b`y-zQHH2UcRBS>wT2X`9I4nQI=fViV&=xas?wD80+i(1~d>^<;32IXmEd^nmYs6w2d(2mlGduX|kkj%&K*k4N$?a1)sx@X>GoBJTSVFLdnD zoqzl(zhA@;*Vy}fe%!QB&C|&v>TP-cU-Udt;?Z|+seAn_-bV&JpB(oC0GZ=|I)<}w*Jn#jMX#tv`F>$60i)?(=?N>lY zTVcHlxB5~c5u+Vc)@Y5C^|)%RwNyaFcruNV=w?k_V4NmzokFjEVNo0e8=;EB^@Q~6(Erw?D;G>c09l_DNX`*fdT6;BNmmj4s_Q(Ov3CfZn=6&R#} zvJC_yW$xhu+Ob(oXZjQud1`R^R7e4Q5Q%>&^h%QHHA)K!=jfMr?8f=IANC z6vswvW_e5x#y*X*L|JoaaF-NSOkkKK=~yDJ^?%r!)?5YJ#OLbac^f$ZIqrfFY06CB z=(Q9JhZE!fA+u1N;Q5wv(uhq9NnjC~@&8*xQt3ZjzZI8xJjIt?2qSAJU)REto~+U6 zAZe1r-wW0M6fwd5*<+V4wK8H1nZbwlZ-^#HB?n(s>%WF2P%m_cNQ84yBD{MsPf z632PX&GLdCeWj4PWHd`Qf^mb)O`e8X0oxMidCk4@f^q#a?u!iV9cEhX$ zNl6f&CbC^V){;C~eVm|G-ne6$Y-vukwiHQ8D4!;#T|V)WJa2uR%|AWR0qxlASTrwv{~Eo4a=8vGyl{{p^)218rYf;OxT zjs1Ut^NdMz#09kmdD=R*(DtLDuN755+vbH$n$uT2yd`j<(2*?XRSa*CMXi}odp;*0W6n*hUL}_^YpgHrJr|u|cP#e4aUJ&H!3j8MHEJJ{A8zPP;;Foph$8ISXj? zH%F8Bz6Mzu=o4| zQNov0^bh=Xz}?-?kS_LzyR>Xke2R6z?BLe6Vc-MU2jU~AP7xh@hI*KHaRD#k+u`#R zku7Q}N=928yHF&BK+wwn;NdGMsZLR)X2LQhsHF6q7J544D=$Wt$9^jHU>%w*n*Tip zZ#L{|rW`$>|LOoi!dL#)Hn{`Gh~5IUs66U;{w;MA%){B+ZEY4BG}niLTopkiI?IXJ z6hVaL2EpSdeS!*ss-upM8Bn1BROk#99zcZ)P(>r&3~;4DO%Am-K5v7aQ?46q78BUp zM~WC3A%I3c0~sTySB{MWb92IXS#EIzP4!_Tsp8!_CgT<4T17yb;WZRHm-yLb$#uy^SBIpWq9RtsPl&iwyuE2-`K`dkNSgH!w@L;fE(cyWBWIntrNW)-OK_^;0o>Vxl% z*iR4GmcAP6`b_;`u_5qRmKmN$!Vo5C2S+p`voJn)CmQYbe_4s zp3VqPnPpnlsMhN-7?k6&%|{R(Nk_Wo_Csm1X(-34OHQWeR+px3ZoGr`NBNc~+zNA{LoPg$AHmEU43d?|=%TSbj6!X^m=d6sP8Gs6+cK7usiX{iKKqUj)$J zCh@BQMYsYr`Y~XNz5seLbO^+N9`9B6Adz(SoK^3{6K1nob!so%aMY{4=od zO;FPfn%NU`Av+M7x+64o@ZZ$ypjzwxtFeOIxBxq7hVIY|Z}9n@@t>G}GXk|oH5`k* zVgy-qo-312XIk<(7xmVJbYPP~@G2%F zboQlLTyhBn-xsLXYgP$&ZETUUx?&{@A}eJE6^wUtB?fhh3wA3ibG!^_PQNkc$YpN@ zOPjcKhj;7;;`mM>(mdp%%U)HubWQ%tlz9`iANdwI^$%?`7`h7G(A5p(^krf5%0`zZ zm7$0PeGw&es*i`j`GkrRa-#XL{$^a%8`Y?;`Jn(V4imYm35VS`*GLW1oEi(AP9F^w zWZp3MZI$?HlEeYeVk0iUz8e?mk3)br?d~BdzrM~y{xvK}a~2r_me-*0r;zc5af33=8neh? zSt#)aO6dHRXsjR?90w`hbgSP;usvp9Ja*|vyg=4k69QCZRuSG3xZ591^vXp+HzG(Mf3$gZxMic?~S( zQV(xteO?esN^&>B^ElIUA7f#iHNJem{0oEn%vfoax5{^n@@9={!T55m8(RFNa9#MZ z(B!u8qtsm``!&sHA7UbUwU+a1r{VPnVruYAI*U6>6u^j{L)I~*3!(cRoEE|Y3J*#p zo)yjyC2;5lQh-3S`&K7|JXOZ$QwTrNu;Vn=gg}fV^ z7n14W2OSIFQ$sKl*2TsRzc3Qn`8#ZX%@F{cn4>}PVi&dlGE1R>_R5w4P4$DZ`e4sRE5^@H`m3&WTiZO|<(__^mw}(3 zqPp7832c-@ru%z32@xuYsDirM;P+SvU^d}mFAw2b`{^DiA%X+RqAD)h+*1kk!u500 zstBOk-IGF)$j-u>MLyi?{c8bcvFW~dVo8kGs&_gSJ-Sd#Pu%WDQss-`B2f9t1A?zO zp(lQ^PRe5JgFRh@YpUm`P)Zag{ygjh$e*HzuP=LcfzVR<9`NY7+$RV*Fw1nQxor(Q zHK6GG9*c($L@~?MthsI6I!zld(A(22cV?Pz!9Ozk;`+8+qw(bG@P$;N&g@J{h| zSHVsWkWn?i23zxr*=5I8khA_R3+v{Nu*>xAu2T;>oqx0yA}f^*+wrzk(7P8Rk0?6} z&ye1(2d^5>kWO5Ip$`qYX7s-z)>1;t16S$71ge=Ml-FIz`6_R_|Im-EDV2nycixrG z)C&S}VLB(xTO(I2F0E=u$HUhTq6<5mBYdAI+>?BYit z*ooF&&F+#$AUKAWX%V7YCt0^ge&ko2nx4tKos4Kc2 zQ4Yw^=OEMRxl0nesOl%+{fbTKAo1g2m#^za$NVFzGl{Q8MLhc|=x!aM-y{bTp0mS( z&z^h=fcxcWT-Gw=^aJak0y#VU{eaQa1;^zOHA z@U@87#u@Oa?W(Ja=;-mP%K>;Kblv4ZbmV>Awaz{7eiQ%!m!B=bcbb=8;lx zzeLn@*kV6%o4<>F&Z;qu^&Nret(w2~=*^hF{?uDGU&kSodV1*s_Cdd8BJtE=iLrGH zZw}}b^X<<-%=3#@y>&vl=)BOC3V$612H&j{1p!`>%>i4T9P`-2hREzbov!E9o6pTp zwvrFlSFyoYb^BEiDZuQ~Bf3Pz_j1a2zEa`EaWho8vZ`U>!~$g0HaifP|IGaNgdKv| zmwWjCwTAyje|2$B#-D>d*@PiMKuAr4;>9ogFP3k?YA zPQWyab!Gr87_Bz>9d5z;YJH@Ttlq@c@B^1A zk&k^)HR;P5nyJY8pl&h>=fs2!h*q?kmT1?pn5XJ9>gDTQ zADk(mvq1`4%knP|DX4sf72528L$R1C9mo6pm*9pjkGM{5jd$MHH|+@4&Uy7{2?D@T6=c7587SF5pw?_aIzk^L6#R5a3+5d zli6DZc@~PAnZ`qZA)CLCIZAmJ;wmC5vcGfR88>MG-eH|pzbENseQKy$ua`3=KFddw%>GP?ek% z(43UKJ;g@f?$K9pja58QFtOLXRF!ewbjr(4?vy0AwqEgPvCW~m>gQ{P_t;Tqa|v;b z1LR4`?`dM^F{>J-8hT9U{kb`k3huTZDadn22~IkEr0aQ*@ObQ%>R|;tpavx!cJ~Hf zOP%gdlJtNJg?*AZQki1Q@pNGM>bBRn9TqlQeB-Pv?zJ74b7rtD*49vWPn z65z~$8YDi7^TyPY)7Yz8nNr&9RIY~-*I5lENIoNvF<=9<1&c>JI3;X6bkbg#Pid z3;a-Yo>HGAfK)EUIv1hesoo=kBYcYB3x!oop3F}!0GXUFQv$RBW8dFq&D-A!aFE=E zN9yJM;REvwEm4Djt6QDOoCdkp=xA3__S5Bv1YWXAJgq%WJyQ_eUHI93qSc)IQ0I`D zWpo~8$!}RxT(1%+8(f%s>cy7zlCZ&fp_QV|VG=O9jQSg+n^s92jPu;>zR_F&RSH!H zlTJCxV8_f>B<7o_)AtM*k{&5Kbn11M^?o57D4PSsrqwx}s@iowzAd*QmAHQor3H-1 z-HHK_&|{X5o+KbB6Ep_eUEO_CG=3aV`w#$119?fCONUOisF|P@;mO5Xl?MJ1&KvCG zbU^QP$IShcdIx>evdMn>22PbRCTkK4&gL>IOTBNSc+2XN(iD(c!~@f1+JA78lK9op z$muF07oNbY6&tr{V`FPypb1~{HY3y>)D7}_iQxbeLrm7_F{p3jy-2V)?b$@AG5#FV zu^DYdZS51#36N@%UJT%>GR3@i03hN1va@Hvh<3N=xM{2dCOe$}dK3oDH?^FBuY9Cz znLu+OFR25#L1H-vt6`Wu=)xKk37Mqmc09{n;=D`N!MfVNE_z0&$l5G`CMrSyCkdz* z*b^aa=QIB(50bsGyT3K^LpM8A+rRg(t%J$KTdk z#wqnsYqZKpZXh;cvwo*jd9r5$RnmA-r9_on>bu9es6DsTGq2GVUs^SSz-?bE$ zgAL{qn-Pk=JD>{Ovnuvi6x$Y9dX*~qexaYHm_0u+Z=7b9vpC_AC5DWXQ8e|Y^f_um z%Oz(8$`Ed-pIO=lB{!&_Tl&Q9NEhF6cMN?G`X0zmk$;c){yk@hvN_|Ab~B$$Bo`0g z{ySz=8g(A4BT+kroKKT?#CDMDY{yB$s>mFd$@$nmAR{?XS`HKLPvmF|`RqVA$!!^f z0}0fe3tr-sobbt=bNHSI82gE-Iw`6gPKSV;#7U31P&7t*p7;6J#EE#s>)BM8XlT(6 zUsqu0LJCKm6SLIcSslS5zBz=FQyy4JAp`tO@Hvf>cYKJbrRdRT=a9WFI=!r-wNPBC zZ6Tfj@wl7|+!9@N3#%WJL5%psOJ4FN=mntzWwcS^H8~f=A8`{&h^uB)3DK~k&!&KA zbYX=f3wKIXh!EPJ;;T6ogY^PIwUXP9CI>s^F}q6Pt+7%kIR}5pmN+Hvb1vWy^%%wL zuY&^->B0xFt!_f7r6Jp4`0|WWJbv<@f+eN5!)Q~Qn)TY{Y{iRZdD@?&>PZ>pd5mA; zUTOP&c}p)+ycH{mz(>Q2{yq(z!Vxc;zon#l$+M@%A0+0SB*+@h?ROKv5x#ku5-d?D zDkcr=JHJOV1@!J!LC>-sAX#9l#K?p_F3L!z70`xM38_pF0S?RtWeinvg z)MN8z?mCD(@O$ZgWk6gLw|5E$h!6Cb!2xn}+afjPP^&chMhB2|{{ua#v?jbk4Z1Sa z-?10!lVrHs*yC@i{Ks-j)N95Fv#+HPY8;Ac6L=^Zt#_#$ zax!f)lsk(AX4K6dGfCJ@sHD{L0dN!!tzP?#0oD2U2V|zc_)XZjx7|a_Evj`0K+l;u z8lIJ)goOY#)L<7w5wD~!e2Eu>p(Yt(+0FBfacWnAR8JxP@OR+fc9+$d7He2UT8OEh z%aAZDW*BaVM-I$oCZxj^OgO4l`1Zwnc zvikv|1ut+?4wea_G8|WpYHx9nteX{_`GMX->3y0UH*Q%@hTuM<=PotuviQBH0!R86 z9=5^mt7T7xI`ULMp(;jY@WaWE!f%+$ohLIq$$@+P#@p{OQ~hQd@Meh_Rcn1iLm`@u zuZ6Znz+hlUkqpuzWTs(;hbi#2=`vtmc;oftsn28y+3EAwN2I{!M)5qTuW zM?NQK<8;Q@Qc*l36)8x6Qdof$emABB5KPt8AHs*lw%5Rsb_}ytsC8|o`(%5Pk#?MT z65m5XM*bKT&?g~bwg`N#qB@O_F{dQUVEr7hM)3_D(F1~a<_zdfs3(Iras2$n0(^zI za5{qk-?6cS&vwvFn33@tIapd)>Hwi}V~6$Rwd*f4AptY-2mS^En=y)m4b_ac)!M^C z{TMZXPu-|w?JQ8$=#&AVoJbO&~wW zSWFTfg35v1#ID&HAOLDnG-TvJX3%Bo17oRH;u3U|W*E_-VvTkW^A1pkE?B)HtZjUV zOTOH|RIP+GY-jM+`piwQ4N_@2Og17O_YPB!d4nlb?H!vW3)k`sv%DJ3Tx#H#i)!B~}>JABdNPyksFXatj}CR?Y%E<4sLJ7X_~F6&w)Bm4!n zWYw5WC*9*Q3hwUcU9l7PxMP$5o18N@QR3QNVRBa z8v~;%nEZ5niV@-W=BWTAm)|37rY)B75~^sI&WF8p^p5Vp&*)xNlHMeg8hS#qbo9$@cEtB-2J0dmlTOA+{Y@D(Y zcT56TKyv2zz@X*ZI~=NTl09ow#PN;Oc#=NcmCn@y=naE92?YAv4W*^gC#+gjefgFj zHORon$)9#tW^sCJg1xgTyh@cWMDuv{h0uRNh6_Uj<)WCoY)h_#}0hK+| zSAeO1_$UDLMN6m7hd`ItQ?eX(#9IgNO9IpE=@lWbDDl**)3HBIJ@Z@ScG^nkuWsu< z=rH`^@1JlXrhvYtD%7Bhc-5w4=mFocUE~k!NT&qU(!gGL(?8phy7Wft(agp~`7e#yz@BqMN2+IIB6*@z{4Y4$5xkV5`KW1Q zqIjb8&2zRR@jqaRZ|IU`@xKbKp#QL!EK7XVlK+12sGhj1g2o`%mYaO>7}}gul)vogM7jf0-Ej*t#hHWG&CJ6%hYv)?Z`$ z{Y$`ikKGD~^*4-c4iH8NZ5|&cMf@I{B!%b+oB5w|xhL!_*ngS_&)6O$n1AIE4A?i} zurM(DDfUDFR>+qX4vh9a7U|^nf^WYHQrPg9PET{H6MGWhD{^K@e+w6EjN1))^0i}_ zd8idw+?P@F@|wqdN@ePjMxt6ZpGCsJw1STToP=X=(V+an?NXt;JHGx}nZi~P^nEBG z!_I!AL(DDvL~ptyBdbzCBm;nc_viZJe)+)D!3up~d>Eo5#00*2`xW$Ft9_Ug!~OyZ z(NucsgXFsMF(LGCOSnWya0WljVSTa2r6n5r$)c_l_4Samh83w7C2A*Sne3F!{DMs| z^Q+z|$}2O^yXjK)eVqC+ul}L5cfszIcv{0^kT*~X*BHL7jh6@1$z^Q8v~gDMkdlDk zID8`ZAbA6s=1VGl+MD8(#OI<7&S}2(Re@vuM2hiEQ+w}9zb_0stT*IC%$_Kb_j%bu zSgC}TN)nSh_H#}4LO0jlPB|Y<2CZsB;vRi^``Zz25R39&>icS!^}UH7HRqxsJx9Yy zJ+H?@M4lg~0S>Hs@2iYzYi*rPu{U2lZeNTA$v60D>K)NvKk`Fh|9vO=NP;7c5A7r_ zI2ahJ6m?1fQA#=iJ~~9@tBP$e2S(`GJwa~!CqU1lZ(q=!|d$~*0($p4%mPU#U<{>KYI~c{ffmR z$dPK;G1I#4A&)vppqDWBe;UdK$Hp0J^3+x44 zA>Mz?Z~=1`zIPefmf7dAlGwjwm3hm+LP>vCVT7ix>7Jq{DU-1W|GwM&-R{dyzaW5|WVb8od6CUb>Ek$t)SAp+IQjEAq$2E`Ad zBJA6qxIqvR0|oG0)Jur_;EzK#zhwfhEf{T}24FPEq|v~&g`1>F(RsY_b?u}DKR24> zX`#%)5!9u+vheC|QkGcIPjTgiJua4Qg-w~*4kr*tckVtmBCR29bI)%m!v~q}e7*&i zEFu(YtHBEsiymkwp0N(-73soPaXA`FmzMs#RiRAeqoQT_;9(KD+v8xu!T0elfZPI) z7Ct9U81+Fw-z7DzVS)x%VJ6@JbtbtwOhb{-M=W-`*2Xw+r^Ztbe4xyCKv3rtH&rv- zN*$R|XjhXk8A|g@^MpC2$INojn(9@tv$*|ucq!6FbD`ets@Qe)*P?%~Mk9}1%D8XB zm{Mg$4coT2SDEoA=~P|^O?Bcee%LumJ|eNQr!uZwZPG7&0=vEyM_`L zi&NGYz|$=CJNIjeRkYRvMJENVT{yzRc0`dX>-bJSUe52)R!e*eD%(9WYu6{mp0yh# zmNK@h>N5M7L2HiPk;Or%silL4N+q?W*+L7LPwYx9E@>PB4%Koc`=3EFGUP4DES@+nNm^%pbG^Boa_&)3-t4nbo=Nd-ji!x?i zRt6%2e7CU^jx}Fzp;Z$_X5g0?J&XbVzL*2|O42MU58gl%t?;vCw?5Y|rs+6R30WNT zjgd9nQ(l?@Hw#|xhJ9*Huni5rKWm9HnaNv?vad}MJF9+LVPqx0nxJk3g3-yN1z5dYj^2Jy})cTgu6=Usg5 zw(GRRy0b@|yn?xqp_m8lpA}CJdoKmiwZydv;_kMgV+eu}?Jo=4nP za9;nA4e|1|lK}zW@6r@l%{CbOG!(zF% zuwQ6rLaF<3YQD6CO`y!ZKAEDHtl?3V%73hDmgywG)D}K)=N&!5MRQn+{@gUdUX+}3 zGzG$;yMB-*vwW>q_72u)!$(IlvuU*1_bb(n%w76T9uhzS!_2tvv3?4Ig2}tV_7i61 z#t^&=`HS)V{5GWVZ(WkI_Hi&qZ$M>%8X6Q`rVY`8v6`aPyQq(F? zNbA8%V^P_TQQ2{X31iw+epQlVt<_ZL2o@ed39|^K>6zJ&azQ0eFn-4)Z7X20q&B_4 z_n9$ZX)#h$nKYP1ywpPZ^yYX-Y-GA4MY-MgmQ<1M|gb2� zeQmq0KP<}+FiS9dW$xbASv3j^ynhcVf7{hd?s8Q_n3gc^NAKhjnufQ2jAZelM1bhA z2QZ&D64GERwP-EWoH_$Y9)FE~sc4HvUDTLkReHx5@~*LsnG3E#i2zUFY&)*T?z75A z#sxW&#gJE=(DsqJ`~HiAu&dQa?%U7ogy^8As)s4j_JgeV?rQ9(Ei_5>nJ+HFZ&Mf`;Ka{IVTK{CXFm3xUEbrONAsHV< zt7eOL>{r9T{`g!=ppzkK1inKlf=C8W9k2ZQ^29dcaDB!-JD6B&$}sq6n~8a&^m4A) z9O$;if*U5y9Vy&XWrCNomZK#THn2$kP4zAKMEj8Dz3--IdI=o0W#S%Bzht^(PnVh4 ztXR)Z*Jt#0f>}APGH09Hr&DkS+d@L{h&-K9&*DfZb~^|#38;x zdrYs9iNx{+h4@c=JEw)C4%H_JDA~beR3Bsml`(4CNPfC*@58~!GS$TUe}}hHIVtmjF_X}m?7uB?0-Q}MtZJeDK%ngd9j&#Nm=4~+dP z45n^w7wDy4XGwiKa1GbsEWQIwW?dI?v(Ahea8f}=8Qw9($hntRtiRgDw#RQ4qjosZ z6NtpEV1r$}=GtWfpZ_sgd%E)NkB>IVZ`Qb;XIMMWlWozT2Mjw-liS}#ybFw=#y4P` z6xOD$lZ~)DX1#BpDd&aoAh)?(`g2q#TSnV@$$-s`(n>dnt&%6T>?j3K#E5sk?O@oD zoFgYrf<$fLYOjzBnctYi486xeG%|}cm@#eQo15@{zZ}at)QjU14dl~)EUvuijXh6v z@ufAG$nt>@M2*VQCDI=UbR8|l^ak!@5hs+2lB%N*Qsm5d50*l{@iTl#w`}5<)1s7D z_L}zXngoJl{G6*aLgA6txt7TDYG5V8Y_6+&3Cil?aUrp;qk!yN=(91EK3sZ2{{zz2 z0lwlBlz=0*@(|% zyvM(#f{G*DEM}{w%!kK7T4(mQ@2&?CSYE~^ACNGZ5m(4*MTXIL_ntM=b8$-GdNk@<-Pm(?&Ni9{huuD6NKHx+G7Xu3ImZ*4Jj zn!l#TDatrle>9I;g1`n-eff}-m%Z!Rtj?i6ypLuy#n&zLXDi^IFo!n{h!WUQ=LC>@ByG|R&jEFxGMNFJ-WVvGnh+Vf zck9!@ah!y?g8c?>o#B(6Db}xuB=mBBvO@_#IR;1lu|aA6M8aO00N*d&sBXK8h=)&B zM{N%fgA-#Zn3`RJ;mR85l)07_kBR}EzBR!Fl7NAcL8;(0YDzA!7J0@#U;Vvkz)&;n71MUt# zy#I{eAAqm-_HlKHd`V#$-y_jpA4GD$Se$l6v%;E1O*;01{O`Al1e#e-yGYQH4qO-* zx_{oBFB0NoLy~ll64Lnquj3{;judd_Jw}2D%D<jzBcXx5|Jd#lc5#}-4KHs1Olu6`8vYCXS#V}W5`JIqNr7!2?&VbkK+TCml>pHy0_ z`oVmXr~3F+iFFc?gO^y>c~O&^eY+X6ii?vhJhJb~R?!t6A7cJ&BtySq`ts&O+iwz? zI{pjRh;=nfSYm5~enzy~LK2$`tYN|`ir?3s{*YGkJ!!$1y76j&)z|f{s6y^P?g|3G z;*7i;oOI$-od=$|k-H~cjh`uY)s@r8rWeoigd9zK6_dVeG8*<_vT*m;X@rbT@?_&XA?Z`N+_JL4T$6|K*i712DLL^o1*Eb^tfkimg&zz@Yuya?YAf` zU_)f|@iS01@5jq!j2a?(t$88`LwCrA^l3X)4%KAyhSUT3K9a{GJr6r-4!2ur<^2p# zIWf2N;yq=r% zXe{*S17b0P=pf8!!X~)V%xuG8J{5S2QKAV#)~Ql(t7^&13MpKv(!yHGp>bsGg4weZ zPM7k)Wo)yYP$f}H|AUQJiG|Bp3G;;q;YAm3KiOnzYYqff zu-RM;V_`#OfO!$w!cW@H74w#n7*efS${rUzOQamxjXlXAd)d;VxTikIAv~=HlnoVz zL~~mS0osGN+oT)tP{5k#6GcuGJpA3aKMn~`E*hM^BKw{OP4IP#b)g}~wVKL#NqP{i z85aQ~U?eV+EagL^i6#$nwDdU3K0yS4Fz?YRo~#6OkAz;8uKygM)$3O@N_~^L_EEQZ z;IXPj3H##Giq-Iq{xpKl!-yr|A;3D!1wV}&ND0=-1CvW-DvE%0Q2L6MU)67hCB zHYbW^PmnDp03Q_+A^Cn^hC2*&KR+P<{B3kgtP-it17Q`;!_`Efwd3%&7c!*z@#ilJ zI4hEI19X@zJyVBHmag~a(YA47$<_Ccfm*cZNb?!-wvwuJAptko$zCBi7^|>xRLnTt zhCOx2AX{{rN3(6dG0eVD=Hx@9TRJohgKZYi=SRJxku><)a;;;j(oC7<7Z&AMkt-HJ zW8_&~vduIVR8`%j);}n=4>u9m=u;A)H z6$^gyhG+zQTLv%Q=kVxKV4XFK@8jL!0yQxnG*0R7!**{^=kq@v#}d1gW3nrr}8fCFFVo+ngnOa^qP>H>{y4zeX+iKuGNf{%2v!kGUQP@ss@go*6^kI zdtm#s>l0j#XR!qk3S1uMDwImbWtPP{g!M7b55E{R)3DX z2B=9T(pj1FMJ*?9_oqV;Plb+(`O&f>JYOF?)r;D{&iuJbwY(GoNkc~jgJ2{ z3{3GyXEL1_UvySoNUVJzf@LJ!4f00`9_hT})@vN`=2pDR21TYlwRHHYR z1$OiIBXu?oDC8L>Yk%+S=C!Tvd|@fX>I%Z%!b_1?gR4HH_jo>qQxHfx#FL(}>rj5rL! z$6qQ{O{+HaH8OD6*w|<2XRs4tQ|^&QvbvsB)OP}gMKanu-xv#0WsW}69~SF}7vo%O z%FYq^dbTTa-(3*!lgO+`8vK6e=?DR~%d5(27>pPH+B@r*wTs`+1YDh$U9zwJ@V%AA z)SIqrEhP@c1kReh8~#yp$kx?XddOIoTqemwofbhqhW?GzXl{-xO}TP@td%f9A(378 z-Kz9~woZR54&ICC7mIt9nDFS_cbO@eE{t_ZI3gS(T+b}+Wu=mb$O6j0Jk=qQ@Z5>q29q$wzpJI4C=O}V52yEkKrObAVJcyWH!S9xx(lyJnFuZh4n#YwD$gZ67 z^h_YUKVDV*aR2V@;pVM%4WYwfYw7k(5Q=C}x4&Np($EShzSXr}!Bn3`uScUknM0EH z&0K40w{WGSM%jKk|GG5fg_0ETW{q3L71VXG10PE5F$)R06}I zt7t(o=PQ7OMBS!TYZImgCoRYj=otj0!;z=g z9=q-Fd8f;w4rdr7gkgd%E`!!GG40JLd1k&UqUdCnj;I{vs2G{MbbLfceD9YAikWK;{S2H zM+8}d9TmlZ2a%*&Mn;wpIZKpKi^Gt^DAF=h6}^VPa=lQ(&{!jF0@_42))sLJrDI)Gt(NgyG2dXJ|-`Gz4$gj}uBAlc$GPR}RI^cAUg~ z7aS|tC;r*p;()1^S45#I3Vl~BI{+378$eN?p#<8{61S44p}TA~s0xJ_*_O!2E-=B| z*4W`uA87Y==oX2BtV!rj&FREos{dvlG8~Fh7tT&X6RC5aRgC>WzwWR;Zg2e?FWD}uqT%F$s5oiXI&`E?uZB`Sl)uC9K+(= zj&e%B@;}mtUb*dnVrxcLRN7rBHo{toa;Ab!txj9MxtP z1`(1GCNS>E$k>k@+TRl!SE4;XKg|^$V1;dBr=8{>B#5Ss%b07o(4Ul!989v>5wDtc zkx(o;2jF``sBMmWWExtd?Ba%)H7w0?>+^49@6y}i$z|-X8m;#25@y+JQO+$Aw zF9~1<-N1-=iuXlqRGM~A`A!C26#s}Du zlI4Q8Z9;ZYQ)TvGR{46CNJp;GwsD#>KM!p`#u0K99?J)$y`!y1i-AYTSinvHa31vg z%}38nNX6v{jk^dHhA z&5%BG>PSycFp2IcJobN7$~(ery@xOB-kANE1c?D#V}EV$I6G{(+n*%8n!;6P1f+5} zfU#YIgpzWzc`1!)Tt7@6Cpbo%me;TJBoD*M8Pfe3kP}w$ir2#{H|(&vHO|_}Ye`ix zc*IF$aVKLo1Rm*Mf7x4$n zojjbt=kK`Q00k6uSv1C5RmFuy_yz8LS(iqePtjmRD_W%sFa@;|VdZ}~UCuFv_{BvQ znPsKW{W!(NW+KbdV5w!4dR8%V554d-gxG;RU|1b#>a)l6rV*Z+3X&*V1Y=0boa`PE zBnQm|raz;6pz;EYrK%kW@ii!jkMc*(v*>;p=J@n^V_bmaN;022&w^Dof8Ka?ZXB=esX1Fo>;H$`j1)Smro$_brGWVb_nTu zX7{VRrPD~x*>2p7oT>9~O7Dx?DM)9^#V$@LP&_+ibDM`4Klm&=X^D?1uZVDq!H8^4 zC~gi3d2_I#k5!>z;N!eFl^4@05PSH76|4_!G$ERKY>J;`IIG^vTQQ`vG7-OgECuh5Y31iwkT8KM zjcSsymy@`tq~5z2ImTtbiF;$Fhy8-ZA`qVSi}eCS4=(G)nxm(1z4QL&vTD6O;`Dsv z-eleH`6QkFeWy2Gn3>&4_BJPQ6IP}gnXLdxZJ$$qDF5=1uALd-6Vnvi5g!DUhjeL> z?YnP%IUTThbt6=kLLqkWcG9WLyU9s_JD}@@dpZlvB8NyahJ;i8?ezj z@Xvpie$3`!SJlh=SaAIsE>wl+;;sWfTnsCY-iTMRgsUD^0|iOg&NknPX{4r>W=c*i zuBq9&Lde%WL*I17vaL?qI)+tAsy?|lD||Cmto1{P9ZI!k-Ze>Lq-S5=2y3MXIJxYol$dnBrMme-M#I0ZA8?PBLeIqe6iQBq< zAQnX^)^+YwA$wQcjg@s}7rkK^e09A)R(SeJu3gT|a!@L^g8%RXqIS1%7j96NDTC7b z%Bb0PvnI+jezD{G`B#53xX^v3?YMIMblR-JpFLOM42JThZMeU%ZLb}hTBSg#0wiB? z?!)}+I0N7!tb^Ys70=Blb?lC8wLVwl)z|E@2Q!3lcMK7yV`gg{NDUg?XF5N`Jl%`f z_U4zUW-0!iQH-bxDY|+qm&(zKEPjfz$kk5x)NHUhoX?Z(E5%isRdx?6d8%w!DMb6} zENAP{^3B18S{f!%q9-m*b1(V*z=ZMn!Q;*|4wHnGa0^@d6(OejXLb`|Rm%(g)(k8u zEBM?D(yu4#}Xzc9+#<+w8L4 z<@(CDZQHhO+qT_PGZS&*{B!kQ?wdDu?#x{4Sx08-Wg-B+U^3q&yJF33u7-$Ufl~w6 zONzNqqgOBtswj~8`d~yIq4aQG@SY(j} z_ z%aH*%=>b$R@+G`J7q5piXfoFHrT8?TDPg)a*3f^oJ}Viq7NX#r23JWR z9kG6fB!m=6`S-M~Q)71XAb5DrO2zILaw9oWV|)Po7zcsub@yi-$IZQyyNE+@p9WuF z9G-!Z0_IOZVe|d712}Fpze`~}e32((Abp%9x5NYwG_X)r_ODbh@bpcnv{-@B4`a1A z5*qMSxJ^qnnmYuU_UX&EAPBij<5ff{{T5I6Z~=oJ5MAl%^OV1VCL;7&qIO0CjLbPw zG$4R7o3H{lYHbq&9AjFW?PytkmGxbw4FwySY~tOndJ8aQT(W?}5gNuV5zDxV;tVbJ z7WH@t>qXNa9k7atXnW@L{OL1VmM=xStZ~9})FAwfy>A2FplQfecVHUgK4)e*GYYZ# zu97`i!^Zql#NE)@-Gj7rgr>0vUxubF2nk?7XXmyLUNIgr^2|9p<89D0c##L^5iiLJ z;ZH7qScvW$8BO4NOkEc%YDvS%+92XG{s+Wl*n*^9W5>XV)oHIH7cJaVqqK>~J~qT@ zJP`KMI!IOL?6sluG>Nb{WH~Ki>eP#r*eWvI^>Ain7y`wHh`ic`MVwh($N-NqWjBB* za0Hi`kxMkBQL)TIupBw@%($=OOi5b`vj!;B-m zy51V+wG6g=NLan=d}lzesC-JVT0S82hbn`^f2&yexCc27>3Px`=)xzQ(Rl2DjumyCPPT8{A$DQ5KVT&B z%<*_sKUbC8sa{$xK<&6aM0u8-I*;-|MyCb^-Q9vP01kTOW$RND_IXo3T@yh5DiICi z!Z|*OXMc`m9vlpvxVQ-kL;pu>l!kYh|Fb&YsF1Bp+10MQC-}i8K1Y@VvW3uql^{;_ znA9}Wrx9LWzx^6`)vLVF$v1$&cZhOQ_#cZ1L3}a-RHoCWhMAc-#af`*cO&t($`kt; z>d3+2hSz&-wtJJd3~*e~Xf*)29PLkvxu4Py_C4@!bU4RY5tvE#rv72)tdL>7Xkui; z!}zS1k$eff?=+2y$Ua7;RU^Y3YQLw0p#L;73*!W0&$X+;D~}VJ5_p1r{h?AohI;x+|RLki2V^56qHQ;N+^TM(6jrBMf|#^-w96 zjhM^Mv);%V-Dw;D6K4&MqY#aj9IvXZq-~SkwV_kvC`K*AO2)7_)4zh`jV*HZ4zrP5 z!u1mj_SR`GM{ewQ=|{lsjT&f~vpg z<7>-_WzO4AZ_R#1|2>Wjc9}SE&2JAl-zQ$*@E6Tk46(2i7svpZKYU-8^$f|~V(9RZ zX)TCaTow`X@Av0z=cL((x2oQOoz(W2%lM(5z`&Ht!(v!_j$_{v5G>jw0&Tfg@RkyJ zRtw#0=<VXOr|^h;j?B4wrEGUIarnJ8MNa7ffb(dQfZ`Rtq&weO0qIf?(uXCs{Dr zP*w}YR3=Pb(JKNn_^*gNSlWA64?QGW2Ez8m!s?6o6f<>j) zJI^LT_l2k0q{x%`fcbe*6M;(@sw|5(^+?yZ28@bk6gvQ4BilyJUzZnye#Po+-dzQ9 z){p`95^e$93NrvsYQu=F&W!3>Q|v|l-bKJGKDys@<>}I~Pr#s_g)Z2jkU|RZUPUFw z(r^Ib4rhR$mf^yAn8H+3rMC*_sF^|;0ITPr>%9s{*dTKl?luWs{2-dku?QN9yK zk;u32OjKa(zmt0>+d$dTnoGI6Y*&BRtdDWM=q^pl=cLF14KzcJD zC0$MdQE9}}_%IMeYvn&fYZXtBjV*qf0fcx;7j^=E>nM*=DI{7|Hk`pj=hNnt=9^o1 z!W6(S*8K{|=_2m#Ng2xa2d!o^fBT(Nr14aY&PJ%`p!!+r8&l*MWW%MAQS%jz2mbf%^S0@TDFGi-G1}^`lR8jcn2#P`y*^JWrU5QT5_34T zjYUb6uj`9nT6~?#&p-eU zk}U}_uDN$WXzkjQo=jLFvp=|JmrRXvz{+yaRrVdWS6>UsYh|i^s?brogSxQu{%kRN z6QOgTA+#UP!(!M+eFf?|Rt~vNPA%{HcKuS&x>Lff-f5|~TcEzC7f(=rp*q1-9ac^) z|9TI$V$LHfI^MJ1hmbh8$0Q{8Nf!X$Nw;O>>h0DbvpXmRTvDZP!Cr$wOO5rYsu`J! z2Pa9Y3^A>@+Pzx7P#f+s?6>1dxg%P(-!IYMT01jn-F4czeKWnHWP~=xzz_M6^sv6= ztSgMz^Dde;GSrk6r4hL4Jl8IJ&T@IWT?E&(S)5NRqx!fi3*`ieC)KU-ajJltWd!NJ z^>lx22umJNP{H9=!i`7`x_SY(g&6Yob>=7TIC&cazz`>zDl_gn>DJrHzB=a0u&ROKazM_;=MH#n4TMxnH1h{h%@Z==qHy z!4)q#ywp5m7#yujdm$v9Q)egpg4!S#^;TJCh%TjUfZI8Rh(3SCt|xNdM0GkVk-^2r zwNdwmd6)5wsCYzcYcxL%^n?L*$iYx=pa-3~@$DDF8N$}D-DH3kq`zlqXvRfu z9Vb8B<_t;>NJndtB+Di(#{OS0o{fHG^0Fq%@?Vmp!r9vntAW z1%|obZC_c%%bFAv>YCIo^E6zCH1HFtQ#>hzGJI1_+~^#JFHa3X99;e6>`#0JTc&UV z?ei&!dqjo)Pq~o)VEhr?nR$yA9BUYs*VdMF}a?otMYETHWMndX)2htPLTE|@*U_QBZN)^Unglou5kNz@lb`ZF*+9Al z**@*~|Ds@o*;^X4UwOX<{X>M#mHL2nOgluAvx`unpf#%q=Zql@L!Rpm@p~88;H~KV z{&PzHEPP8xKz@!k{>KbuIS;otzulI_QfOO^q!jThwZ0n(^vBLjtN@*Gnm zgyvF8|7sJz=9NqmSvL;%d~H6tB9q{8jz0En;j`hFSGHOxJ}ul#?aV2*3w8x!6OXXd zo3C{_*LffqIZ71MSy4Z7r z{3tRRMZ`%44a-SChH}@PP*c8fQo$ltp3%Kx<0ta9v$DXRlhUd+=nB zwPtfB@UQA6kr1b`iqKg(e1b~vKh^DCpwL^Am=85RgC8t#uN*JRTX<{Ro zmTQEL88?@!Ny$-==+eQehM8+&td+;3etA;GKT?nn2mdLX?*tJfP#-+)6&w^zmeixU zQi74J$R9liCx=Wo;H0K)3J){2kR&*1V3V)-=rdpfq={%km?8|ewM42=cjetinx4+M zIuZ=MLx`mxB!&+9WQv-!{mU@C{-r1b2!V>MHn+8JG-~PFmrkP$ z#511PM7(M=)`>IF4PPiwzMJ}W@Xow2iq)bEi=Rg0QWI1dv$t)pXyunP(V@XGwkuoU zB8bnt3jM)VK*4hY586~oDyL#D4h zwYsC58$-MWl2)Q!jwKC{r%+dPXHR=Anlu#>C-NAL=^tzA3?Z{>tz=R7tr*+Z(Tfv3 zZC6-0lMzf3fwAzDrj^4&Q zIBo@5qQdbhg>5VKV}TI>c!*wTWP2zLAV<*qPmUkxz{HERDqY;aYb%n8CA6j91MG`G zslrQtXHItaGMj<>%3L6-&_-u zw2=j8X9j@M2!jj^5aS$>qB&y`z_a2xjiiDb{XOQ@vjK6J;gAjlQT)2|gqV8)04(rQ z=UUjKCB&Xgd~n@JPIyf;r@%D2eDc`uvIQzt>5u-1F2k=6ilmn5^-!NYxXAh+V^Lj0 zfE45BH$l%o7MJBf*s65k&vL0AHtyW=6tzQbr>>6=A>P5nCAW5uqbt2E4E+h9dCx>pEQaLfHE=$6rw4Y z-u!0MM#|XOSeQ=3R~q*Oqo_lIVr!hhE4i`Lk{Y{`D`#plH^|v@=JxW& z4tW^tI0N6!3PlV;O|OtH0PF2JnUqsJ%%3^k96OA=ZB_D$Q>(dVr3&4|EEf*^`Qi|| z$_0*>#Zx_+q7oe~!;_1r@A4yey7EM9kurLj=M+34)AdgXiL0d zO5lF&9Y$6(VhQXzfAwL$uOu?QrD~YVY|yO}WUqlJm$mn_s05(~fGI%?#j^Re<^g#c zH*2;=2I{eO6Q5+vDx> zM2cQy^5W+kw;;Ps>4x67iLdpBB*QPZOLz#LeM)G`SeOwgJy{3%q!V=OxLIZrJ3~^I z5h4>^iI;}o>kYm!fc_a@7&U1JtTBgfHLYIHK5_hw#KAV4#&uUI+2*_s_W}Lyj3$WN zmVd{O>vZMdCK+mF~a98281=5Qr7Q3BXtz3#|3I{M(=Se5^h9OWQ4`@mm# zH-)kDH+6Nm=zza4$e#n`n0kx#~) zbGi%fax%dYRBdCEY2NVb* zfMDX1Ec%tvvuNhUS9BOaqKb<$VuepzZi|Mob_1JHQna3OHanM{nnSnb{es~-%7qNpTl}m9>}}dV`20>g$cO2=eIc3B%;oW(zd0>r zRWstnys?lUGg=FwF00B@kQzv_VX-cNWus5O^_vnYGjJzU-G+N=TQ3kz*_B7xGOi;V za&hb`l6L7e8vA1xLZb?XFy}gTxmlM%Ug7jg3Vrjpl*KKf+Qro<)>Qtk5!zVZ*lk+^ zQ2)!H*IR5YjO8a!>hJG4uBpGKe2C86-rIo)W7Bwe6$2sGPEo=dfSB&|@* zQ~3m}RNLGdEy&Aim>pD9Fa8gAM^43;|J0dZB`Keo1FpO6#f}v8W&TyVyV-SqXTG@+ zo?N@NsV1G}{7yfRxwsJcalrn{h}I{U1-MNtc7Er%jWZwBQNTkkVA+hMPNK1w03C;C zyDSS12VnB?3g3zis190)G>GD4=lMZr$pyNT#!z-{9?NUlxVtH^huRiY4L!jnkIX9|_-!zOJV7tKVukqBbcwMbjE{xII- z+)aQNhE0mKS_t5g@sz;EJi$^N7auyJlAzo56+TYTSh8~V^v*-WE)SHsvg+ApWp>W` zD!)|bG>oRwht)D1IO}k3 zcG6dPL(&}pkba!YC+q#DUf|q>tmQ-Z<-+uK`@D%LC%=iPbWq&;YR z*H^+Z$RVdQyyl4AH9bSGV_=3_F>i5D9Gj=-@uZpr2c(Tm{)}JGE_y1N$>^5>y+Wa}UCKfqE8+0@}pSFTfDRiMyYj zKRK*L*E$tym;E_rukhr4nOxR&q4wX5cGioIj><^pfsQ;9P+H=1m!dEyso)1wIJfx$aYhjZ z(H+AZ(H+)a7bu;Hu|e`{psAxHg}Un{Y<(AP)Ypd4KBF3A2!O!lEkW(Liq0B5Tvuk- zvGuui?`#~hP_Xb0F5P8AwyhMWsvn7SSVXG+u~)Fi>Yg$@q$4^}!B!mM4tZaQIc#u# z$=}hhjJ35r$Af1o%5TTtv9tsWnWgDLnL)Qv0q%}D2YsU<8KNs7n*73v`%CXlx=oIG zZMEhqY-u=ki}X+fbt>bfedFPLx92}QH926=T-6_(fl5j&7&2N4zzqo^1z8(Oi+G7u z;RNLWv~?r)t-hv^KtNTP|Lv2vb3?*N$<;7d2)h->n|fp)qJ z&U0GLa?sa93>|xb*vv8GN-j!_M`IrL+(e_1bH!&Fuj*l-$%<^_$GmvE^470hcxyR| z-s(4_tk4DT1fr-;I#M6YQ0IfEEszm=jEz?AO3Iiz`%KlR(gn4u<(*_%^xHaetXQ7n z17cT5WT_`9c#Q(bY1!HQ6~&Y}h@9dqsN<=QQH)2{!lmPi=oXAc$x9jn;m1bqMsD=K zk?{4iyLiH)WAu9Pb8;dDMQrS3wK*~h|`4=wmjpwKnN zmo-%A4slF1cxdBNu;|Asj9HiJe#q)%BLbO~m5qz_v%F>99ODn!$RTNTku3cY>&K5HYLpXh-?s}6LWGsh2AhcW#=W##!U}pbeoAf;J zL}M;&!^_m8$-$faFah>@Bwr{aUZOeQ&^7f3;B&f=S?MVUN6ojldL|%ScpD) zAW*aEa8^`UM^lkuB^XUBX*ely08kWA;P{)86dD)p<&pcDlVNm^fH$AHe)1Dj3OXO8Fm}d)^uMFP!pxmDC$7Z0zJ`B z;tP)5-r+z){2|L)UyrCd;)bXxat+{MdWj9U)cIS+fxFz1m=H2y^C+bO9JD!>+M{sL zdE~vSO!wE4per95UI?XJz{tt3gF7DOe16fJ7>4a=Mk2XtNBpi1EW)f$H91_x9rTG* zTKqd};(T!VRG8%nviFD+`1C;_4t;C5RN`>LT+YP=GE)?ouzltV!GBpNB?gqvr^5NZ zq~v?L(EaDi)u{UxS-x|*ie5?zada|e*^HoP^52}F_a^UCLT?|^fUChgJ87jJCGh#8 z4OKW^D2r^;0!u}tfIGE8!$}XDaw``M@Ghshx~Cwj`qgXj=4~g&hu5p+M%Q__AtrsnqFWeWvAc_Zu5`@a!!Mt8`Gl zBoUi;I`Mszq}#0J0IdBjiM#aj{Tj2W28I#6K*0vm z@VEFv6+P0{Q@5kGwWUzrRvo7lc>M`MuxS;-3~D&FE0LrS4X7JR^6+K6k(yc&d|&oP z0vGp$dgtLn9M$7yxhqTO`>Vw#pb#IzZoD`@PzMpzG4oDlfQ#ylNIAvn1vzb)THK-* zlUKm++*mg$qNer9b0UmF8iJ!Ma_u!w29}8?DGYhY(^soqLF~Mul{ODK$$c>m7JVwD)kb^N{EdwqS>c>}v+k z*5kN+r4(onVPG)Opz|{MnvgVFfXVraV?%B1n{jG$2sJ5N7 zWYHIEMU!5f8#!&wURmg8YlRnAX4MpSAoS|-a{oP4z#GJkE{X&gx-=towt*^Pu-tmB z?UAyrDANNf`E+%!{9^$ z|6p%4K&>eN`JF{sG&&19Lf{Z?-ZbP*+0VPm6h(*zt${uvqD)gFj=|`OR3riQ_+N?6 zSo?Sc^Ph2KsIlDXc>?Nz?P7BNZr2(`8%VgW42=e zL0MZk>;V1ZSB|o;kn_@n3#|2#Hyid}&g%P_042_jiK(QJlJ(x8-+EQ=hm`la1>F5i z9exxQuG1Qo&)pi&){_;IP=O8H?iQ#O#9Nu(>@L-d9ts9$RH{D-)c#&iBZiOY&U zH&Z@{F`t$I9Usf6=f}AhOYO@_?7`CEc6XvJY})uSw|mpmh5#PCF7BSVru9Qi`GHnt zK6K=Aim%$E)&+jbx;eyg9KP7+vCFw}2eOO$HT)=v^IwOL374MrqJF1C+$Rb*V?D#9 zYvmS=c%>G}qKcnPCQ2nELYB}C`33kR%hcNR`e+~k!X03y5pBd5UAO9Fhnehr#n((U zV&I*-emM&fwv8y`#lN@7rT4l}WSPs(#e0ji3{z6R;Yp{753dv_%4nm7b&oHKnvR(; z{xpmjuES!v$I7?gI?Ec^g*CRe9t-2!suM@(XbQJ9T`g~~6#@CE$?(9h%JZ)V;ihCu61wHLDOhP98_G|Vg^LJO5`sUryq`cot60(CLiAO~)w zkA7fB<4eiW?f6SMCeS>jfpok~B)0wf& zVoIkQA#~E-;bB6>KtGceAfT>vy5tt=viNWsSC+DCFio-eVtcfDUG&iGPr=rl5><*X zPCrXxIKEb*vouMnvdXXGkt{r;slFY+kY?Kufmr<~t(7=N#^r1EWW<;$?S^OMbC6`9 z6i=-d?>{E}Z%i7=sag9|-Ws3DwFYwANdR|6?!qJeLJs`S^tnDN|4 zcv`vhCFwh=<1A|SS;wiv9MKnwd~_J~ri&>zHI&YBO;Ws@G|=_^ySujbayBD-)PyK%uxcs-kE)ROfu=0U>}L}T%l}nKN3o=;;n~5JoajgSHrxFb zN`+UR3qz}z;*}+5H6j98by%c7rGbu64bpD0kJ5m9`pKa8hTgq%PM z-QDP>x<->{b-LNJeTPPUKuveZ_ZGm7Y(h_w`;NGM1zNd=eS zJxHrckiP#gqZMarK8HR!RbQCnsw1uMmUsXhI)u_$sz~UmDz9sHhq)Tx4 z44&ZMhF98qrj$?nZ0bRP`CdVdDRNyj-hn+S#tIVUBzoElb*Hu}uICCs?{v^6Ox0oV zMD3;CLj7So^L}{BZg@^F>NFl-+HUkiuUGs2Gdf$FT)oUZ{7n6sF^i#>q@y$7_<0fz zb(ms0hjl;XFU7*=jFh=;u^B4JOczkj)qzy81Yd5=%C6B<_0=u_w1L`<1$ACSFb(c< zRvU3wnK*?eOn(_A6WL8W?t{~~Gca|R1#@$-iViU9&ULuj0Q!U%lJFW2qk;f@UB_oh z=*8BOlzbSEfpmRP9N-7BsYr-!FJ|P>tkOR6-SJ{X_E}mvf*Lq88Wv_I_vZJ6c}98S&^48;KeO2Yn=s(%pf8(VMsMy`4w# z>68e^41=(a3`JN#FaT`~?l_lBj+nlrqUFvROX2D|fZ7X?Khe7zMl9n%Y9zhvJQ216 zZBL&95g9eC!4*dT%R3IQy+67lWFm(O9Mvers2O-zh^iQn>mK)i%o z!6koND)$U%G~h)M zVTe|rCly6C&Y?YqeDC{5`R6BvD5f-(=*=13N#y4Qc@<_<(4Ky-nbg_scSp=>QenYH zX;U)WV&%`Z7mFfPEW`EzlM{t9DHfK}e0gok2|yRd@RmEA6#T=&1bg))?PwsrwZ=h; z_j&qQq@r}+^DzUdX0xZa97ADWqrpn1b!lLe)J-Vr7;1t`DWc!u#@$NZ~RoLCq6-uA3dZ<`ilHg%eg zdBp1>WPr9A$(%!LVR$o8aHfo9E;iE7j{tscjHh5XJ!+z}U!rZ77c0r*UVf*LGNc4s z>o1Hhv;UCZ9ghS0C^WAn#GQEOOtkb@={NBUv&+K()qcfNXvR&%QWvCHbJ1lVa4 zB{FD@nvwV%893WNu81;Y(ku06A1Ik(I!7$nX&hkRG~Kt#bi4VwiWTluvKq(}p^!Q6 zM&Qp#&{$vHA|ur@!k&fsNr}3NpC*3pTU@sffUz6Hyd41wv4e@4&TP5(>)V5rBnQI; zl4?IAdF)Fu!6e*3S1qd3Dn|(b#`@3k4t$;3Z1@is0tD%Qr6d16-;pu0v$k`zwln*A z8+xl7{`chO>ssHzo=HSchg?>``ZgI@Z@+Pv7qT`1T~u*3QeB>zxNFLlIT8V|ehQogk|kgp!-OGKrWJ9RzCA_xPWxuu*D^wgLHj ze69E+lNqi8&Z?ACW<$8wmbp;nOJC`vZR&AoJd9D3TjeEzVv`w`-3CzEAC&e1u1LU% z?yD0g;mpUayVt+7>pg-xenhi|y+YL(U2OoD^XgjusoL?Y-sFGjayAr6j z136N%-vtT&RD-{RxG3Y@o!ko1PhzRvNm$|xbR1Rd&_j~mr<=%-lXNiqXN7Q_8AapJ z`dOrJLY>jj&f$KktjA-iLn-v6SDgWzE4LB2eSfI13Td0p{eCf9yAoDKT}e5?w5c>> zJXvz%tQuGm+UG%KQuQ3LD6P>RhTvVh{@Tg7*RJE1Soc0ta1AG49|V*z?*=J@EZzH z0n!)0$s0!6G-g}D0!%FrC}Y|&2M`KNmkVi-6-CYjw_hlK2E20Enn2|nRk?|nbaC5f zGUl#s4IO)0yE8VYj!$nMri(mc?jE0Qfl|DEQC~ydNn+>}<`(WA4}kbN3mAE4mX1d) z*)q1KAa1wUCfz)Y?fC{oS_uGhqr1Kqrw7KLH`iK$cT(n&)6FAHcL2V50JhT z4XLAylgF3R!l)3TNTWwdbsUGymxb;5Y?%+-Q$`^D4S*YPd{aKuxkv*X&5xytwaQ>l znRk`oTFj;0qri_j(TN<2PWL=)O19$DsnU}p3jfvfFhuls_hTkby{n?gRP8NfDyx*h z2;IsfUoFrxVa;3yvb~K!A7aizT#PEsZ{pr{#AZ&2bw?y+bhUy}5y4m}Be(}R`@%#qx;_lB9f?$GV@M!e&vodjf~PFA`Pzu$n;3Wz&1og? zHIz}Z;eR+4#=m~nXRP5Pzuo`!uFOH5SJ1_RO;TH3tmXJ~BWxOX|1eVJ!jhtSl-?Q( zc`;F?OZ!GVEN3CA$0{Z=lsX;6f)Nx$Q3maDX3({fi&*NIs2mO0Vs~JlCj4dT6}iPE z3!c=$Z(aM3)k2XIlB&F(oFrEVzGj6(JxI%iUocQJ!r0rlR`GqOwlLoRaphGI&yaGc zno(h!Zf2?u(ok`6AhZ8I=tN%TykD14!6dsx8naZoYw_q6IK0P{c#A!zBWd(B+ooA- zk&ndk1;d&9{0|}E4|a31nixKRP1T*WLW%emZGS`OY2QsXJ;aVeOV&|0=ZfQl8=_=b2IQ#`i~4*1#)o1i1+iE^$+!nzsNNbNF#JHQkZO!p3zgKPFS}V@ z@#f;gu4YT1*4{4ATF9aE8*cml`|(lG?-#F;svJ&{cioTjS9r*7Zv{4|NR2wZ(CWeg zrtO1gTW?H)rL*tH7jvExQ7r!9@zrt@p9k}bNf~x=3phO4pH<69)kUD!5g2^U z4%6?uPjLmz{J5`=*q%Q`3_odl-Rg3ORwC@a2u-ID3AEHf=U((WD0ot4IwyEmbQrGc z9PDLYHv$v>y}q!DKn`{VoVqM-XNdO<1TM&J4Di7$GMot$;QMM6+axSqd2NKOVV+)J z*J&S;zb1Eh@-zX)pTekF?y+o=?JP{ zeOM!r(eO=ixvR)eR~=Wr9*+DbfS`SMnBDAssXo|Sv_z^(jH)|ZVglYpCk@Pub=n@% zJNZA5*A`woBr4$l0U8fQCp*vl>;M8%9PE+U00}Ohkd5kKqmUzt9Q|C)hO{m4^Fc(? zDw7d( zfWrNJM7Bm84D{a~Uh}${j0H<|i|myU)h7BPiBzSjHRF-^5h|g&^#@23L_!sk@JInR zGs4v9agCcx{;|xvO!keBk;G((r|K8FgL>ooqsBi+Ie^bMtLCt;rS%n4OBRY5CMrMNJk`c1^2%BfPcd%d`kK8&=E=uBW9qzJ!aLeL{e&zf%g)^ zH^2HKrnxXPlQ&5ZI1iWyVd~Sfzt_L0qFf>!m((6ZU#M_1oQ{`g=}cQZKew5+Q8$01 za^_4~j5(7>B%f}_T@s?F$Z+LsOwnZy7VDf!M3gJN9l7(4EXUk^$bRJEz zFMVlSp@m1?`(b#m+2d1pZVV{K0}c^+;0ui51iW8wSH|QCeLi6WdBmuwW>6=B?!w~! zz!kUbJvnyWvC#-ctKh!zL^S_#1k5DuQ=#5(F^@3?5*SBHl`t5i0E+~F<4!;xr&G}& z2<}P{HFF<>4@pF!7ib;%O<&;qQ^%d1Xt0n;&cP>2xJ8!6h8L0~45qinOHh?VIF412IMJ~qK;km z>lN}A=$oR^SJ+H1O*cs->X7ZI;k2OHq*XXbHW1$4qy4rM#EVYHx{8TUXC0jYNiw#z zfj9rz%`3*by8K=+Ih`NPE*b^`k+pb@HzTMEr9yRQ$fjN~M3Lk=E1mYhl(9v&8$x9b zUyfFWio#ippOZ}zr>xbs1eoDpg288V@zACN18kO0fs>^_0FKN~i5 z!U)K&@PpxMRHgJlqve?ho3bQ$O<@3wSo?ft(eMg{E!3m?oeGI135Cx9uMLa!D&cD42eAEoy2QaO!R+IO zy3uKc=?5p)Cw@dzTX4aev^`m1ue4pMI2smLWT3zL(*}j1ZgqIN^BOVx8`>WJQ~wT} zV`brOv$hFYqJBELqQm9(jyv$;=yQH#2zJMRD&TBrvt}*7zTu6n)nU)kgZ1kacb)uC z)f6-BS&7vS9q|hFH(;jUpsm)xyl%}Ax!Pe)^lHTr_Lh3}l|g2uFBs0HNsk1Tg+qxB z9&MiflL13l{NM5|QP+;`XMs-2w{vtTuKy{)^ZBIs6A0?NFj}P^6FFu7V_pH&gG#m` z*)bhM`8{tUIxe9VgpEhsmI&O(Vo;xTf8h{UQDdgf7G6@k3E=Z+lUg<}bI}DD^=S~h z#aV-nPtW+zVW15|O@cRNK~7&z;sJqsB&2sYjnAJrlW6b-B_&`2t_lmcs7B+cJ8cz6 z8J!`|M%Po>2m)bPLt5p++Pzg)vcE7_Kr_Bl97&#>H7mouvZw!VBAkSD3@6nAe{^^!3?skO8dp1jx#pS5)s-*bPw)W`Q55=9$Uv!;jfAodH(yL1UtZ3@|ZNc@t#yn}5@ zGrlKgWKp>?xtO=82Rj&U&PoTx)_zlL5_MHK_mT`Bo|!Dy`Qg`bZ>y`OuKW8hwVCkj zO)KjfaXa)_b?7KC(!6aaqZ+g$9+M+&Wp#l&ZvcI8k7Djh(>dY@PjDm*CQ2Wx7(KEY^dv_iSNq!j(@3aFnyh(d?->fgZ$fZWFt@q1<{CMwjmz<~Fa z@;|#r30%#h6+d+Ukt1Lj-R+q7K1Ng!G1f?6N z#3jN#_-3Am@cOiy+mKDBXKbe)s?=$$RXh>e z$vehe^b>O3cgJuWs#bdSYR<08yR(ztvYt7v2HqSKt)mL=#ZE)CzcHqxRy(jg84u`w z7in_jP?A|v`iWaCi9D=XKW{(<`d3xa=2B+oOhWM%16^%rxm^dV9CYt3*sEa>nLsY< z^q%|I{GctaBLC0qF*cb*j#6vTAWjfEqN zwwZ$O?QSQ>C1prE(gd=-ZtVr2^h;S6brN6w5t281Ryu8Wtj9!GMw`NC`J}V~>7ad8 ze5fCF?rXyC=o9U8vP=zDgwcoR#=y42WDXM0N};&miYwCsKo#$MsgsfIU`Dtq0d)~! zgqzB2I+6$BU+BIAQFM{i8=2C=lB|H84Gs-+H>x-Ki-IpU@b7vlKs$h`d2U%SR1A-x zCbQOVgdjr9x6>Hd+zEp8hvs++zg+nCfSu6q*2Fx=t1@Qyc)=>V!_U{+w!IHJE-+rJ zp75&HLnu%K=IYhB1{Ogj%W(dX1%rVaj%NRMRI2CIMp4)dCUNm;OT(TdqXaW-D1%!- zF05N0R0A0Y&(~lF!t+SRX`@xHsDf`$HgTVgItxDvqX*q>bEP2Wus|%cEbz-5B_eDa ztJi37%mU-5%(mJd<{hPol?fQ4Uw1@%33$kR6hxN+V0{vV%dJ7*zp$(je+7EAx;Z%r zPse@ept?^iDpPRiFcoXu(faZFrveixn27*`|D>Nc***5SNuf=_>im*&a_^7-gr8-D>AO5ny#6WFa(&Il1YOvh_~DQG;u6bG>{(&CT~!F~C&XZ%L~YHM$yX zuRTpI$=ST9>INn0w9o@1!#eBOPOSb5T0o`0EOJmJHRN}?Nqe*STpd|`^!33ht}|fk?&H%}%Mi)#-I?)WMC}>sh@-E?D@w@c0Y1?vbkWH;n4S2S zdCv)8NJSOPpx#p`!*s%nfe}ZNPIg%09w5%rS%Ucglwy;6%Eej&XUYPoYO8Il*AmI5 zY8#m;i+>PW)*-`O4_V6)mX5w!->&V552)K*wOlo4d4jhXeqnsqxdj!nSr4lpRJ zPdJQj7*$jcWJ?B3yPZq*jV(srxX+8EQ$|4+=k=J_PMF(u*sUA%{KpaJp`cF5GYu*5 zr>*_dkMrb_+)ECU?*X3K4-b)S=*iU8157*(1AozC{5@=gEpW&+0hJc&FD(<_aF7WY z9y>P*1JPBBfH{4v-^x9}GsR=v%^RT+kFS!uv{5 z!`{@fIoW`#47l8>P_kbzEQ$QDjrcv}I9E^TS3HU59~*X#3h5|8dq++obC50sUF z8&gmj3clfx&DfE$grxQb(A`qI|3L{F?4+<8;Zc|dsyt-e6*7*^QcI{C;;D1Vo`2i` z0c^v7#s-gfEzD%#6cyM|HJkU8gEplbox;L3RI&^=XIIaz$pQ-2u%3+%!PAp*Y5`+$ zWZjDT7R5@<9;>X+E4OEDFVqkmQw+7a8@+U|xMA5REk*n}a_j>hyO%GCzuhy?>?1C! z+N3BMjS^w{aIE-daXg<51fP)ib$@V8HcIKqPVd0kHJ%v0!bq??me&UF@)9z-q8y}` zDXyok1t~O=II8=r#b|yqaot`e9=w0NU!{=kBJS5Xy(&l@2>M!# zI@6aWAK2mob7dt zy03$5*37H=;#sy?pCA5yZ-0M(@3@#<6&Gc;D%)nWnw8n}O?Fw_ln9|(!I$ex_|FR3wI%#ptYskCboyvI9cK^f zX8j<$y@VGx-)zB8Zf_db7d%aVH)tr}Yb%Cn~Uw_;-t1BLS-K?%YqFhhr#kv@drqjLaa(&s% zb3(4Y^A$jtOn=Td>&>d1OtR{lJ}b`JX0ch96aIT|PoBdh_1DJzRyF$Dy1Fj)_m%r? zyb*&AM8+ArTHVEB6`@;2d^H z|DH9A1)wS-iEmQ1>qT{@f0x%qwE&D-wWR}7u2!|5Vt;uZOkiDpT;HyWrCW@3xeCTu z)h(V6UTGPyE;H^6{|deBtykM;dl~%5TYR-wew>xdb@rMby;`lB6}LIaj<>Lnb@qAw z6ee~JhoCyE7S(!dLBKy*(J~|t|4%UfS07>GEdkU%-oODdJw&atqwMW_ZZC7GmigqS ztmk+tWq-4(kDYfpJj}0~8^By?wOK7-#m8_+mt(|fn*0GAgC!y%qAZ+iIA&*CJf>L- z2!Gam1f*ctjR!>d=B5?By}kl6HU>PzgFlAjx2WnXYWUr|*B@R@-hXp^{Px`knAeBZ zrrfd6HJr>9?5iHCakgAFXT{lK3qaw>Wq*GDDl!T8PjITsy?E4sr8RC!(@yYLea&P{ z_pPO|w}77OE@JRMu!i|{F#}Rw0--Ki|9Ijams)}lHyRPF%$ugxg~_$M<@WO@jL5zC zRVhY6 zo((@AXOBnOzabUY;ZLgiyn#pf?zbae@>Nm60eZKo@p#Zy4EG(e_$^-ccroHtn#oA# z`y=WBkLvN?o+{#hxNHE>*#?d%+)BK|bi)>KOq&|;e_oywOMd~cwFmn4xLjRVEe=p= z2kkh%def|*zf}GrcndUOUc$ryc-vf;*~J1**+MR~+iJ0Z%iHzHQ&>0fQ46H6J>N3V z09QJ!Oui>GQ`mU5!b(rta;=Yw`Fv8qZE!-3oquN`3>d`(?u}JJm(heye*6WIfD|0$U*s`fHWR?I)poLMVCLPi;H*+` z@Cw6|+j&tE#n;C$mzHS;juTd%I1GJB92H=3IRQE`U!-3tL*#aOk8m5=mf!yN@ppXP z4+UH0PeEklQ1IVxkXO6C1hPr&C^5G+{I}hd%n22l9DfHyZg*ITM?{LU*y5TIA4SLs z3=?#nyFT{z0IM>(^d|yncq3zQw3kj+2{%-ob%;p*t^11F3Nh@qdtKiYi)t>-?*aI$ z@}ih+4R|0B$P&Ro3tH}T?`YVdD}aR*!}bc8eBCM( z2kGSM6d{}pCM~i`gY02;b2_|$#|%xDjoP|VwSH9euTFmFSg2)p6x4MqU7PX32u_Fa zEe-`B^pA$djcW-TvQYZW?chN^YnI!gTTtqW8h^v0gH#4QlAS?wmLu_5$?)M%*(+`o zblIH!z3l5W+_<1~`K+(|#NrY{VvjW(ZdhW5BY!N4>$7>0Jt$Te?K3_8*c*Nz+*CQA zD4#y`=l&fJ7X;PTvGIczSjLal_2$|!ydc-=N!g=MkzOH(4R{Ry&9NU3UBorGw^k)~ z-G9=Rab48}QvmT?&$F+K88E!rf5`RIY!-98fAq#g7U}^Apby}%!@becy$F2ad^3ZW zXWM8rS@y@xn#9}e7Km0+ubH6DF3TBSOd$)86b|5D)y*vqkzhFr*BM$#_wj?(rbgQN z0A=+C1j+?`ylGLEZO)xoN}mXg0_Jj7t$%4X_^vFny1WItndoYa-CTpf$&zX?ve{+@ zO!nG-hU@zFz3j>BbKb{UQ_rh4wV1&-Egit3-ewJwb+^qiNr%%}ty_ZRn(#FUf;9mq zxe%MSm%2@~DRbBfV11hv>Qok6Pw*8Mk_5mII0(3yEw#Ww z5laf#M9k=kaE5;@+G^%?Br0FP)PF6*@Q7HGj93$VF#{=3WRij4++Ym9Zt6)pTUE<7 z{zXT2)!bCTYUtk<=wQqMP~Bm9A8pHzK(-7YAfK$CcGxC;5wTe`xR8Sj9w`&m`CPcJ zpfNL6!6Rbv;A2_TSM^P`YHAc4iUsNGR?UJT>)r0yDuiQrTKuzzpVh%3^M4jBB#kA( ziQ?l9ldDi@H_G#3vsh1NAkdY5_{XaXpzU|9pk}c+42!R?>+o3<4o92mqZ2{7g>ui>5vYGDwhYM8bfMPR283sljl)4z} z#vBDWUd-f9SgOS*B|O+5*PxGdA&lZQnl@aisF8GMrsgrXf+B0;t$uqmp&sw4;*;&z+#1+lUC9*H|Y)h9c ze~*gjX4R6!ieIw01FY-{x$$ywKI#aR_!PKy(Iz=<9SAe{8GV!^b3Sszjp*Vq8h#|1 zKS#?2+>7(=VTC7cu>h7!8Mm3hXqlr!o)F1c*{*#fVG-Xuf5r`%@pVOqeC|K2PAfEx0oS==} zR3~R!16sEme}7(|+eXa#)`vt;#yW<=$^r(x(so*O!1Ia-jbSr9wN?~`*K?xT@+;LrD92ZU@tKrzNiBszvBbk=7@3ge&mN5AH@ z@1zyn%e^Va4j4Gn7>*pYa7xLuHb87EmZ(OcTXhhR1#d`}T|;Q2e>^Fh;8b>BgVL2h z#FnS;e@C|9#+f%|TMyRk*-!wpNjz|NUKVJ&+*j4dMRilw2oB3u@0{0?cPNq}l5AiG}hC^5f$1nhVPKtM$)MQbW-cScMKl+L4iQdu zf7Q~>0CJJ-X>9qW?#VGah8!9CV34M-AyN|iZiF-p0R@^a86zV*|Iwb9&rU@(NeZmL zmfJ{uWh|+-uTKQeTf@3PG>Ho=AXXm3fOMfYFHr20L^A=QY6(YRnAr5OfF21%r(3t0 zJ64+D)R?aP09%UH>~bhh6QL33r@?V^Tds~@ z44!3!<#LAiEIpaP_M=Z*d#P`JMiYoaL6;i_XUI>i{JzTsBU&m%Hhp?1Cf8ZOOSQZn z|M4IHk-cCG!D7qMgyy$se+GVQe>&Z1wL$Mdl*uZ#ThwJaZ`ncM60n}HnXjsP^O3Ft z)oX_onjA)eD4oKLZm3$6!@ca40(f2w1b2!W& zj9@Ex#5=#{Cc)PckOMkEf00sZ&mw5jh$RO+rQ{vT#WnZRzCZLY3e?-oOUGL%do`bW z>lYpWow+fRMH3(wi`-L@H+1qt zwH(<`V;aEr#7$j&+yX5q+mIH(SaeP}2r}AvMkaXX+8rIa_a1K#f3mV@VF*QA#%vRL z6pC)qS!;<(qGhL0dkDb9w>u1tZijT}{D~g~4)G2cI*ZYs89LEmVwCY~(X0L;mI4KO zd{&i;D_X|8LYISDoXLMIJ1gN~8NmUraQ<#pS8JAXx?e}={O4>msXGvEPwI6A^}>q34IaC!%4Oxb$y8!t%p*ulknCv5!c1v z8}GItCAB1-;S2ZU=nc>Y9zT2Y;OY`B zRN4cyD42nwR)7oHm-IYFk^77&L9&qA#^lr+2}44rP8SzVhR%6=-Hur8;D3z#L*(`* z2xFY_6S7M9JLszhEis{9Zt6aovN3H#ULo1kK$r?RCG>SGk|6p!ouft-Ha9m? zi$XniH3iNeCs;t%cCgEh6@U53W0ELeT2+8R#^e~xtw^KM8pN8j1Zk}XmY>dhC?BM-BF_F&OKHa$KZWIEWXP~AM*OsfR*$7 z)M3(CqBUieWygO1%;}~ti^iDfvba&Ie@d;N(i+p4IdTus;N*U>xO+ zZa#EAH~w452YM=y1b@jcAql{LLx+)Fph?HnoRcJXwkYZ=`VHtF(H{cqZlkZtVoq`& zns(t3EXZ^FvRbnP0A8Lr&gBw1BcZ;8i=JSxlLbQ)U=m+=FrDHs2uZ6IjKvRRc3Gg| z9j-SDX}GS|Kpyg74cz?6TPrdD*KJ~JU_G7d${(_9xTvl$5Pwg#WDILGosQCdi33@p zx36R|T}K?&DEQ$6H%*TUtkYfZ9i{#jVb`xdmNN<-aHv~zUmT~y`Vf1jZvHNJ!U21osk_a2b zcmiG#WeL8XdVij3D)6W5GkaD>mIZNfV*->OD*GFL+CWhoiry$R*h9hqO9%hYjuyi> zK54X~Nfi2qzakcidXa)Jcw*C7cGJv(=G5fBYeEPn~nh`mmC zb*t1PjMe@$>LG{N`)(S$ypOOY8yVQ?Nd48LYyfVpslL;A0} zCD0~vD1W$LZq^}Q7ii-h&K7OB$nN*!6^7&UMZk^i%BTHzZgCQ`g;i{KRN)egj`EKW zMW3keYde|5+T>2Oss0>Lx&jiU;KH~7*^f;3Bt8&MVAz56qe;ohx2+Z1*&)@6?(Ber z3jyocKdakTJs*a4E?w1l=!TON-C+T9*(F@8z<(_`f*#BFI-6ZP--QVslH!R4+cY}- z5x<3V+&O)PT`AHURvmt;{)U#0n6J*Z85v+S;1BNw z@=eQvh7KD~POTHz5BRw2a6NPj5D2Q+m^Qa<7B_gI`~YiZJluyyMMqAZh4|>ii})N@g=soQ>|xi_slrBc0vhUBir98)3J_u0aK~bJa@Wpwtj?-iA{a19kTalv zdWn5FK*i#=fXjt#$J}i=xe|SgP^H2Sm2w=G(7W?^#h>8^RnnKU0yX5*scr{MYF31T zC8<%-OCN|?Lu9V-%Gjo!m2LvTXw=~;fbBU0)eZ8TJi$Z5PVh}WN>YL7#?67U2!9>W zO|s|L-rQO-p~;%Ij%P7CI+@)EF^Gw>N7TUyUWrDF zN=~@Kkcqb|V;$R=>mWlvexAc0Bh=ipwo1oF-aF38HyqNR5U-1{bFzaVE?XLo=03xQ zQ)Hiy$nKj%==m+PVH0jNp%$?kRV)S#o?iOvx-2D7Q}z4trGmlUF65F$Mn9o8}0p3zXHBdbkvMr>>jD4i}46Ur^ zR-j;2l=jB^g+5P1UzL{GLX#C2WvrYK0{qXA~2Kw02?PlHBCf zx5V%m(`0z>2$?l3(wOZkx41x*O9Ogp-KZRxvj%lo(h2!H^4Rbep_1%F0q zZIz8xXj5h+nRUvPB&rbp)?1TyS(5PQKGq~^*K1K?D1lXpAN5(5@W*;it2aPRU}ehH`UrUzJaFV~cEoH?hb0$=MiS&XG6<GpkI(KjwKug6sI;Y*V{CeT?_N z6Z`}xfLTQUf5cbjKe=0vA8#>LQ6(ZMIgY@#t;s@Qx(V>CL@W2XMLC0E>p>gxyhCQb zZwvBdh#2ruZlnu;$Kery??Y|I#)0HRa9oJX)Ij?rfd|?f2OxxmO<8$d^i91$?f6u; z3^#BZFd@_<4QWhrl2=h_gn*5}17>}5hGgcfL``63^auE(*_mb(c+?xg#n=?$Fz#i2JvB`Wwh7hBLLMcStB{1EnXXGf#%K?ZeZFk0nhB~|av9;$I`Jf5Q7!xFW zi^DA3E=|Y596H3Ls&ASrB|>E9wUQrM17}5z(>No46)YrBln^ep-q00IFDNZ&$@)0Go7zwz?=K%!fUzL~Q!c40jHC8~ z6}~RE875`O*z$F~MGf#5Mn{id9A*3Pf_~qJ&1JThQ$u-SjxZOlPhbd;=ON#UlqWS?J!crNluy0&C?S>cdM*!@-4B^H~mX+@3pc&2=OQ|h*{=79jZs)0Y|nQ z@&Tp<^`^bjcfr}wnc=`gjb!ttspfZp!wdI(vm!_5MA{OwymtVyxbcaLW95W@)DP{T zx2^QHH%NaX2!?DwbeQ9_2?sdzc17pxwl&;zmyz~uyNplbS@QedP|f=xm`f($$r(~s zJyte+H~Bd!rjuzW=xdX!ApX=`LROwh6O}&2IsP1EZ<}SyDL(dbYxc9Y$Y}$RzZf{r@k#>~17F7aK%9uBorUv7GLwn+6x!7C) zod~H33+eo70%T`QzTuNzIo(CDA4P^&XPE@~Lk2*+aL2SV^_>}U`_;z+13ozk>a%BE z*1*9SOKL52Qiu{Bq^C&W4egfx=hdnkg+7W<5xE5c`fyR5wMowj{6R~K9S(dr4#ypX zhL=Emw=$auEifEl@PdSY6>@`Wiuph%J_>dDc0KQ>S`cwutlwVHp(OELuDT#&p*6Y= z+H9YD^=^p!R{qwfXx!&PDpo~$gq;I+;B=^jTr-VNKlECTVAMHlsa=m^CH3kn*SW+m z&&VMWPjHCyAxrLsQyQa`OG5eC)}^W9&Q){g zmBzYz^64}?Ulb@i&B@@@VqRq8!$1h;o%CvvHRb{$rcS_S&0_8o7E9t7K_fQ&Q%d7@ z9b|W={dbxp0X5Hm?HPax%Rac&Fxk_?^#e0kzAFUhnZF5q72Le(K?=#(*k8dVv<`ELmMeF6Ydp@ynE zW#(cPUcy5|b)#t=iEM$hf{HH0?~EtG2Xv~O`Nnxx7mMX(aaOKLLoi^?~ryIk7-a zqfhXM`Ea(mP{e`b+lHglZu5@Au!lnjlik1lfb ztPQoGjpn*hU#qLKTxJ)|E}K(yC^BnoG5i@_bzj4#-7-PNo(K@n8vc>rc2Jwo5eZtn^DBW7ets><)XYP z>Uc4Wm9-Pi78~*}P?u%$eSy+0e4-%yYqrII-0=a+0y|rY?@jN*LUhA{m0v7+eKQ;@uYL&5AtV)v;;;0esVcg3t!xZ^j%6@bQpX+WNJ0lCovDEBtZf*KAFaBy-p zIh)wf9p_ww{f{&5bDY@_HTh^SHH+*h^YiJpaItY_c3~?QBp1xK2cghXW+$!DhsMM= z@1|M)x>zP02AaT-Ocz0UT~Lrk6{iY+r)X?zesZ2CJA6gF=1J-uC8J z;Mk@dx_Q|Fxu@?;Iu#Xb5!xl$mbnkQDb9<^c%n+x1v2;>d%wx|k|qW;t_gmP%Rh`x z>JMU;%eAP(@TUP+f_TPX{v0weIEagXg;2(j zaRH&B8L`jEU}PMJ9q&s_R!0(QTNlgrvPsx|8wyUQmgHxV4oOX@Joy_cP9d62O`3Dm zSMVx4IctPq-hK6HkG0B7xn>D;;BJN{yk0 zCG?@X%UM-Z@wgnWI1}1rnTOYuM)QFQIF7Jv$pgU%L{e;XSmqZwEZyMq{GSKY>BxI1 z>=;W}c>#a^)@;cC#gqg?5#6l$5U9%|^qZH#k2oxiJ))2#ZJUh)2V~}dlG8yivj;%D zAHza zaT+dd<|BFggeo)Dv^v%{=u7h8!&zM0C~v~DPXrn?_q=Z7MN8V$0P})DvIJUS7#h)>1rjjh+_wz6R=^22nDCz zMe$ld97EtXXxH^(;&1@{Zqd@HHxk9NYj7*c4tNi%BIXPusR)_-ahU`&21Y&m_yx?Y zqm`2*RKxc!%)(7G4wrDVw4X*!Gz2M;brm1?d*b*eq-BJEj*hS#O0jNMIp(2<1;=bB z1DL|)?0Pw%M5{O#4w^CR-se4KL_=e)@47kkh94wc9)cU5ybc33C5J5vtwt`wbUd}Z zf>@DTu{u)_I6Cq;Ypjdlw-DGRmSoMsP}{2OeqmD(a42)GsRxjwBwr&>`BU~c@;(PX zTA@e&<7!TS^ZkU{O6N!5*_dD|`G~HKB0YS=#!z$>L6qd;k^R@$k`qA=M!VuUCoUM` z;@9KI4m9yfq&i(}Ziq>Wf-6AREN5cq@z)=7S`O9_w3zg~@zM%nf(jL8oD|>2p8PDA zdwY^clQ;-qH`CX#X^B%}r<_O-1b&}HIAH{pJxd9HAFKfT%rF8TG7rnJAqR%c?xOJTaN4KO9^3ZAXAY- zZ>qwL*eK0INR6Bc1XQ+xdM*KlLL!3GMFkRLA0$%ujDt{57BA)K8v5hrY>fj{VL}5Y z!(*j?{%YcX6Qp{7qooSuB+!BafyzVw5i-bJVq^*XU|?NtJg;ZAFfRTe>md#e;*u7(iZ3z$=#?5p_p%sN_Xw5*v=vAWn0E8dOD6nCDxjzD_(J|Ws1hqS3HVDlqC z38D5q?pJoeaU`{4DaZyo>YP71o!yg(KO7i;4ex>(U;-lLd}$+M%gvz#Z_c%v`FXrC zlpY}|+J&i*34Cw5lhyni8?zZRxcP{$ai(^ z-<@2{FABPFfnEJ2YzyG5y@>flz6qZGv}DZO9lDx7dtF`8X} zQS`FrHgr1YG#NLFs^iqEV+Rk(JHMmqE^jGQc%uG?W(!Z3pAG$cygocESv`EWsn^wY z8P`^nGPBO(D%0}dM1M4KByR!gqRtznX!Lf?V<-y7FEOlaXcrcLm@yRKI$Yuq zFD`f#p>t!%gG9Uw$4`SiElD{eumK>En8dp1dh0m&{v^xwb9Wr^w}#_DMVzaG$dRdC z$bOL{;K$|avVT~%Xl7lZt+3gk=bdIWrW6pAR@Y?3C+5gsPyskJ_)-SY%c8!J>=Ds; z&uEluRTmxq?ZaQ*zL{W6;up_f{N+^u&T`i`#j4VT1)P14`D-3n#iE^b5?1B{L>T1@ zs_tNvg>bnscOEMpY+jIRQ0POyyFCVylDvGgMEyC(xA)4C%y+K zGe_aQYyW9e8WVbYel7bbxK3^Tq5SQUJ)s1DzX{AlcJ# z>Mm=O1S@e~D?}?V{}>Yiu|4R)5RSrI@Yc#`>!oh1)-$5a77Zsdh9fd$r3&haB@`$2 z-0L5FKW?VsCh)m7zf_v5;rB zzo~(~@AG&rE(Wb-&2^i4Vuz$Jih^_5u{g|B?iXJz+j-?$yQJh-A)d3-DJy~r__<_J zY}v&Y^N-X4Ao+YONmcQWD`sym${MX9TDF5Pj(taQBDMQe52UIxTLJv<;_Anb90v#BPvj;Tt9f{>9XIpgQn{W>Ii8~iV({o1+{mP4{ z7FIk#zLw2B$I1eb*6YcpZj1AB5-mqCsrW-Ho1K{9h3Wk?FxS7AaVei_P*4rp%?(VSQ<5PrYQ_Z;k1;KlKl&bN+YKCgK*L9{dE_+JEK4-b zF4?UMUF0^kR*}S;V~r8yDEc>M{+d8dM}@(Rm3k17MXA`pBCM((F@0{aMTK&neOE}O zC=l1ZWREte?5b{V{kRPQ?)aj;FHPovGJiYx{9k@YW2FF!dAUX>%wCTGz-~=@nyRG8n`bXzvyl3u z7cU}@;9dfhLq|*y#4yo@9-n3{#+HB(b8tznZIq+(wG)XRGRm^8ZH~VTVS&f!yRrI? z9~y5scX&U4)SI0G}(qYuki_rhzAEoTdseHhNbr2jNn6+e=_yN>uo1 z=?TXI%$vIWB7ZJ$iBAXqd~mAGdb_@Kex}8O?^yvfZvtoS&ebl>X6&cp*@L%lzWSRK zxRt;xjGr`F^{nOqU(yg@<>$n3?v*{(-_|Xx zCi7MI(ILKRR>f*N3V1aHBc^HH+aOE1e^gBeFk`s57uAn^>vY3z*v7V2 za}f&18piZ(G+5p*(M5HezpjC+s^;>QAA<{laq&^I#=}8|3zZK#E;YMXRmWo&md+%r zv3?2aNWADhvF5%wGa0aMSnHID|0_8TlPjHb=AYjixej?9CIgB39XTg{UX69*4cI*g z$$4Ehe?FxN$tUZE6xaIwVcE`#B@?}Czbdc?@d9`|Qn(Z_%;dyK*Wj?=kSC-ws2GnX z98fz%>s)kBzQy+#%#82Y8hrffIQ!k>-v`u^0eqpI+C)zTrgD9`ATpmcJMTYK8fF}f z(4LL=TVT^ay0kXN@vO|9AtLhmEpsdsUN`Y`e;IsfmyhG!c(qc45!A3=v^o(N2fk~` za(giq*;&)z9jOV?)Bq;|&x+LD@GJpC9HL#4N(0#`6*})guI^i$9eq)HQD@VN-_BsU z#he<@{{ThS&0^OkNe@ScP)X=}{&l=LUqp1=i_KcLWXh@$<(|Df=3X$tfSoi;GE&Y4}Xice!W$-EM!a zu`GD(x8=SC)&QODhTII#^Mv0`kWz(Ci1Z~lj4dp{D-h*MfWw1Bzy^cSD70_(c^%zZ z`#XqtI+s!}W@Pb~J>3SrKKJdkYVtpBf7fOE`t4A25Zt$T`HpdTkDE`MJhFE8UIx>D z;Qp5Ind$2fzWc@f={b=8c68&=olQaMj`Pe;8A-x*H? zioVb1<*b>*<+)j(AO3zYB2m5im>>V`bMkfOR_Uos@TO^Zt{(ZJn|67y6!AJGf887J zg$DkEPelYb8QbTlp+c(jeq`wJ^t#tH?I*u@qG7*XM7$dbcMaw)tUEE~**bL(!)kx1 z+E`*yEOS{<13>x#|JFVlWDo6U$rBYGc4|CIsh^@$f(aeed+z@y2J)NL&(w*_YwB*+ z0^8W-fTmr`Rl?6F%$hQaCO#oXfAuKq9wnKTXNJFDeP81x2mkGb;{USW^?hYH&b}>| zQMfPN7M}Qv_tf{S5bdVv4X$3=Vaqs%gw<(BWN7cS%~2N^)##kD-2+Wdh_4wUobp;auSW^G->8tfA|>_2RhCk zkAp33my2pWq^;~sum{V`ZpRDd0e{MB8DM>j<{3r3Qakn`KAmrx^=sv5%X#92iiUV8 zmR1rYI3QXr9h=%z02H2cyktIoq$$%`d$ zkYacbg0B>*9}T)U3${1oe^Q31vrZLpeYJB;YJPFv40#$hbDd4#f3f`1}&TbsZYGAvdBOjUt@85 zZ&Xib59<;0Y)5&zaVXefB=u%FS+2_S>f_L2T<{|D8b83y5R^Wnf6T~E$2qn)D}Ohm z5$y~k-dj%2iGC_DzkQhNRk^m>_XfBo^eV+t3vkJ`Ul6nbngcP}CuQBR@~4E!;&-_? z^f_qOiO_uG-ZzVRtg>MjZ~E{zT}>;ntFj8=`RMGZFKH zqsgr1;MJf1eE9m!5ue@;c6`2Snzh>1;zpch*FKlSw-7ojf4}=8a1gXv^!cw>IxxR= zUnvAoWpy?f-G?}nx|g5}j^T%>5aVH{2{XNyD7X+Ie>cbw^E0%F+vg61dMP8?Sa9KZ z<;{$;PpWE)dBH_>Hn}b^2SJHW49r#$EhnAVD4KVI=6m4dY{uClqtlT41u&NZ))~9+ zbs%*EIc*3?KIAv1>3uOc2xzKT9EPenuN7qM$7+U`RMc=$T%XO0%;Uo|)lA=wFM@NBp0AuZk=I1`2Cc8MMa z>K2@~m{UuMsK{ZkcvzYGAr1KvA4iuc=3h(7SLr%(p~dMDkOrAhx|AICh}A@2bG$a<0tQlp0NoA0cVLti*^S4qLx2uN!nB53tt$5oaEj_PV?d zf0f(NdZLffi7=`LN=^fWP{V<3h6L6fjB5V(iCH_K0Jp0l-hNcBHgnNF=wW47s-M#Te;Ks>uIE~A&gJYyz9uy6cGbG^n=$FXn zTL-QcH;FcMIXDl_@tkJ8hx*5u`{-tZf49StwwBE8=C7Qeu%rbhbOx+p>k~54-nN9? zMr#@02{fEI)PgrjJRRL%@GwKXm)wEW{T3Am#ZHkp;~*%$Ia`1m-@3tdjx(6(caGjWf1~Au9$7D9 zyMn-BvBrVh^Z9cp56Pr}?52cL{wehye;A?$EIQk>+gEu{qmxOcEn0U0a>Lyj$S4ZF zasqecq=gHQripE>`3wE;jxv2iPC(SyZ0+`XetF$Kyqy;yM{eoAbK^=(eF(4O;P{6R zv*Ba1Bpg1m`10gmfBzUxf9W~;;VaKHx4J6)7(iWPMsoZ;zrMnMh7NLP+1wXnnwFum zou!OUoT0oHR~$~d{AnO5lpo{7X%;tvW+w_Dkr50SA79w5GrlD2?}i&_&a@Bp>5RXM z>z?Xj1u+Ss`*(_Z$9^z4ew(l&T>IcWhDfOQ4Anz(3pCn`$=rAEe_nrhHF^Kd@$uVt zA5vuQ^;;%wgMAnqM@Q`wKZt*C>P1yw?Yp2%Pt*p`fjeHAvG4CEiLBA|e#g*igDWcP;`G@ogNsaU@xYXdhkU5N@+sW5^-JU7;T3`U*9a z%f!8r|C6B2epl`USL8T~5yf@bYl)`*+nfRphdhv^WyDkI_*2Y$z@LV%HbgOaR^x1F zkktJe0n>f7;h6fppGmlO$)bdekavD7>JfBhM`Z58F$V0arBo~)R65V#FGmsmmzKQ{ zJ%0}+fQ*94`)ALj!z}ZTA@}X^FP#T0Vm^USR@d>)S5VS&OzvZo=*L&`=m;J`uH;{R%_ta7uLt`Wk5R#dh9toJFydba4 zp(Q3XTD#6&6%|%k(N{73d9K+?Uv;SvX5bHM2I(>foU@$7?&5IbprgzfU}F`4{;2hO zm8xtYu#l7-i5fyJ%h3Mh+2NDZG+8F~DScN_AVL4d054Ct>8XE~P+;J_u<@sBlGdNy z#db|^h{n_tuq8{Zi)`D4I|o#Kb8u&2lXYy{=ESyb+qSLw#kOrH6PpujV%xTzYh$UEbL4in7ZCPM;_$ZCHfCwv$!-PlsV7xNc$#;yX{_gsRpVYe zSPC_d=ddT~M++`%5ZSeaL6F*?0rGBA=&!Z{0lMGN1a0_c4kr*1YnAx?ZTM_s0;R{B z2!E|GiOU$KHUSP))i{Se9JYn%mp0^C0gv-EpO1d-&}rNh9h}EDjk%bxvXp=ijVE-Y zI2ipz2gba87Sb{jV(OWI)E`!OwMg)~qjjBHu|<#$$SS zh2Oi=W|>1xX&%W*y*x`PL5KDa(d&kK_q+B`J+Y|Q>f`q)JLkW0*|8D7fisja6}EN{ zZX;QSbFCn)yI3+$p)<=?iFf1tO@(?vh!O4$L_(TzY6#v|!GgP|H#LqK8U1uRIX{M9 zv?0cJ5P(GOd#f)7<0tV!-_(p+N-TJOlvYSss^xn!@jid^1XT6-4!~ z0T9LDDg1#Ayvc}c3zX!k1pK*N1Kkx<1U|4UB7l$9R&tcNl#!Pu3>!mCYYwsJMaC1v zC&G+-F#JbHq0B~bj+L=otT1j#xecQVIP+A;wjr(W1(&2R;mzYH*Rnp|0CRLO^C{_YAopY+wGR9!q(Hih=s z5#=vi<2cQ?6K`3-(Gk&cLX{s{%H`8*UH#GGLO}YN;AUk4=7s3@L(c8$PJMx25Cp`7 zVZ@)rc~-EH9yNwgq^Jz-%-86Pf4AHaBw~SD*O<33Grg)SNCK2$-PU6V*RYf9U5`d! zC~p3CBCT994hP}KW_%VSF+#t6+OfcN_b<($T}h3YP~(UIvNwZ1=e-60Vv|7RMXuiW1tU7D*ElRXr*=A+IuvPGKPhy(Xqv4{4;m{ZXcC&YhYy5)sIw`Y* z4PUcY((EzkDh_h7PBo1ne_;@F@~x$KUW43`emy*s@nss&EOv$hwCdIt5B{N}LShu; z^j#U19c-a0H4CVq^!20jE}@<6MD5dCJXs|LAHH= zKZ*86ZTr3Zeyh29L4z$}8N6I5V4LxDnaPrctYXS=Y_9w&Rg=JQ* zd(r6tcAiksnn_m^2G)7@tWTVZO5v){B}Jw!(liwoLNf@APadFseb#2*vt3csjFbx! zqv1%IDyqYKloe1M3V-Q!RE0Tb);Tw7WyoikE0D6rTy?J|@nEq=Ubt>JmyyMT#>%Eo z0FBVIxJ=ZXHb*UQi<`QTxt2~+ZrlJ{$?H7>0u;B}+b$9xHrV|NqL$`aHym#@YL}Bw zp28c4R$sU~Q6Rg%@wO+71IX})W6B~+V>x3Fqug5x;i~6Az3hsDC>1N!`!%IrWveK+ z!QOxI-Usft*h#|nKlEVeb|TZtm`|SInq_%KY|KQhMSYD5bE}~P z?lIXnMuoCphAs*Oxie<&Qqpo4xTY5?s1_!N@-ho@!A^!WEqd^vImk&ZY=mQXYT>mVq2&->h|&5Yw72V{(wQ z2{RPvOYUZy4ZjQ#1-_JeX*qpF{Omdn3{MZ>4|JltY{748d}Kh|4^o)^bCnAPl^d<) z9!wf!;}&Y$3?GVpkC-@mSm4M6BCiF|YD}62N+<|wiQ%6KW*5>2%vu+TxA<@ZVD2m+ zkVkf%dDBp4PF!NkhBK!%BO)p~mEwntfdr{*<<#cfB_exzJS}`F*-LlptB8d|sbtAp ze}5@MC;dT-5;`S>Yu(6B>fdRrdz7cpZaj-Xr`MyhL7Y@~4n9M)FN zy@RSkKL^S0hH@t{YtOyu;nL~N#Xy;yVIQ)<1?ji7@|deYf}-~>1Pu_V{G zx5%GKBW^FQBULLjlMI-^J!!_HNYua#Y0;xd3YZCFFG>Ge82|1+PzG{1o~0z?lfBSC z8>HQhBFO;=F@sdnuN|!zS!12ib&Zcg9JRLE4(I$R z#rz#2!Nsr`i}BLe{!*CTh+zN~iN2^`z-A81Ord1KWN( z#}ug|X4v)=xSm5Q?2H&BOa+*SA{?Q9&WHB5Q_z(}m@E0TDez)@8?RvQ)PL%bnR|S*=bW@6LcXQ#QFTJ@*^a36r+ z35~O%DUS5 zBHD1k;!wx3wRFCj8#O|`X-I#|LbY;Yn+#)FAn;{@JS#ze zKT`#R=^xb24Y3sY^pN}T+6f&@k-vaYXcyWU&IIi{rH@nml?pnAO+KaOGgOvngoSig z(W3P6&S%Q$lR37s2|n| zlf^J2pW|OMQKE&TJyqpU-{7Kj-B$%^113@NMj-IqT@H8y*vB*}QF~Gi5-h;d02;ao zPwYi&#msuLPE8^?6$)R<$@N&(G9y?lQ#MgBNvP9&{A=&nKW~a$l*-w|6Yb9hAH4-Z zfzqDe--i9wKSHRtle6tAVn*~45alPYZuaW`>H|9iB;a_N-!05qw2bSDHDD<)&}fdN z-59k5l6!742|zJf?tm35svdtjK}Vr{^#$KJ?CeSc*dL@Axxs&qNU}?4H}hjK4b^f@ zG8x?o%64FqD~FL8F*I8=@okYI5Vt2!?%SplzI2v}xbvvQ3s9S~71-K-Z_uJfnM|_r z=9CM@rjVsp-9enY(YJ&-`yN4SX^X)L=u&=eg!$fxm)9k3D4JJgpuqtoy0^GC&EQgJ zejl{=Um>6AaliI6=@cn!CktwJ2~eK9AB(wk5AGc~wwygFrpcxGUs~~>SBVZLh&Swe z__k^!k+<%t03|Pl5q03Yzo8G0gGgXjoWPNwOR0=F?EU8Bk-W_ zJL4sv!T;hNP?zw3tl@2ez=iONQqA3YrbF}MR5uqRU)*A>eXhe6j#fGTV8|>` zqgkL?aO0V^5((|5h%=*UO<^p$4Uv!DU2r9e^ZtcTFg;QF*^8+-ORYMp<}4zqv=NSw zh77-IV^gz+U>645H{Hqo)dJ5iY8hNlw)3#Sidj_0bjzirIUWM_u#s}b&yXCe5UCI9 zx&W<#I>4(lRp34tUJluzEN}e1)ZJ`KwsACw-f74@Se-cxpP5B$4R5LfGlKtE=(<4) z$RD_tDyTVsY|t(8Ybo``(pAr}Byv_Al1|G)eJ9t*OyvUX(nKLRld^=zt}ig)j}8xt zZz?4<^LQmcZJtv}x>~@z)I$T~dp$$Rt!x+Z>{E-+Il1cGiH#9kQq<^|j8YBwPy7PP z)7DyMvm7$bLBeIdcF+5zM2QB5UZXMWz|L&V-@onetk^_|%Q=QY(kw!KeU6CRl)uUd z#DGD1!{h~UyumEKZmF0UQ_4w3pGjPf4nueGq@pCJ%Y!tno|?h{N8);WN`PyFUnABc zQbQ8MU8znC3Q`@1XU}edE)5*MfWSYboP7n8*|_rWZGC=RPuuo=jD!-ZIkZ-P-`?iO z`<*uckU;#h0wlYXqSLZ}9K9|pnegLwfDQ=Yed7WO`_d@C-)|mvN3&B!e8Dwjp5eRo z>~HzR&`NbUu_SeR{}GDUgaKBfey0Eo4NbUuUVm`J=k4XY#wuW!u=e}o=(1DeN97E_ zwl$C4vBI~|iVyl$i*Mg!20CAf#=^3QT`Tl37+r$?t1lg$xD&?(u@mH_I#boP)U#%- zXcr)P7J64}InWG}NQ7F5e7!OAS2FdGS#9^ZM6tB;lR8G1F_J1>=R|ym(YEOPp!=1^ zR$N6G6~ydMX>TEcXJrlaH+FLZlH$|%{W+}d>iZ6=A05tQjmOpKyG^q%RGHjVdOULVAMhET!a3Zc09Rdox!9PSZZdB@EEQlG zSZeOmxqcFL>^ruWo>jr)U6~sgV|5WEXgMzTsRW|931q>GB>Tq^df)FX zAD*L>Yi)t?jY_z{(Z$P*N{1rjG_5V~LN)lzuK=gbIr!r=#*IR(C^=eTE8V{^^$p5q zeV4S_j$_I*fe9O0$wXzE^9o?7HpRiBQRQxn;LIWBr5rY9C2dZ3NknZcG#ji%>*WWsBH35+Ebae{)V2Sp0=j3b~~EV_6sDe z+)qDLaOCaSnNA+@f$o;->thZ6`0dnD^Vj%Op$PnA)mN|ymdei@g|jMI3Me3u#&w)f zo<-KsrLR)w3&dfn1v+2KoFn<`gbog!a4dj8MV%uB}6gwbT;@6NECSaO4k0E7bGYDpw#*b zVG#ZGJy&CH^&7_KL2*g&PduOU39KLFi4ln9uHOwnpbK~cltE_+lwgM zmdRZAfb)%&jkBsf&U}Wee&aeXBJj#T`pIM%+AhDQ<8zP6^xnFkc{Pn7W3wY{u}*7vgq z^`*&R%>I%;+_Z>k9soc)tB26m>t*=0R)R1!5Q1KydIfQdBtZ^ib5wRdBQcPy3Au;# z2BC@As6M+s)y4qWXQ+J9u4w5M>3)AFhxps`%b;<;niR9;xU?~~f6OudGk_?Pxu_G9 zi`+af1{Jv^C6;GSs%jFg6l(;gHwc zD_d9^^1|A+?&j!frEv0E!3QY}(oxo%rHTOLnbvG$I8FgrzTcLcnjH*SJz&)oi5JDx z&2>Mpp&k$k5)|1tZ`M?`;4R1didU%=M5kz#Ffq%&3QE9(?-2HdLtC6dL5xvkETK_P z!-5+&TFG~>x?ki}#6-bUOs5(Q44Tn2akCeZjQmGlCXAI?@82UfwFkkW{`t2jg%$i* za%q^=O+5h+vlvBUlWc;>cE-6^>1HwvJmaWBEptAX0es;+-a0KhYbWH?f$01%h8y`| zSAnc8goJ{Mg26vvkpuiGc*EcG3+z~Tu;QCb3zxz7{o z;qpfFkB7GTnf&l|{ePM=CK`4mx6KhT!fGtTVr~synO|(t*(P=uu$t8Y;gd#d;*&ob zO@nSZC*{qctuY@C#W@d+qOei#q}B%)0rtTC5FHocTHeJ)8RvUMaL*Deqf4u?f%l46{8NT#-m7`! zrG63*cRp96uj3sxKyyP6w?&$m4_BxDlkX~dm@i=`!AJze6&Z!Te#-idRU$t0)Hl^) zSQ(?_DntcEB!^N^{v7F4&vK+cLs;e!Atv>U>n@#!Yua=1YN|pbU|;>s0{~RZkK~r@xYYX(gn;MP%xKoPU|@QfntO_B4#4*ol!sQD(HZLRcCFaS7wBTx z@WiqSAyw47dHqu?i2&RuQT-_?ch#NTvSdH#iLs->>{dY6YkZF3=-o&S8Y1ZwgbyrU zAkwJ{2$~orsnAlJgiMmM#9kV-ik4f$z)>@DKE{w1_Bar65E7p__WZ03Q>O_L2+F&d z{oum=BAWpaC@oBAMFgRgfZ(i{jtoq6hf0lJQIP-Peb;Fu_6CTL1!TSA0f9pQq004? z2maAz#Ka)=ne-47b4I=$w zTvKV7od(p7aing=&E+M*#D|r}D@zM#B^6z;m(l@UiCT zwF?}6GWgM9|F%HaPTTF@OPRAg0e{-Y0> z$p-w4cObml9&Sim(R5HYb*3FM*SvXJm{Flmd0^-^i66>)5$KrLPXlMOxSWpGX`aEG zE8dkTiT2T4XvPzyrH+T#tnpxYp`63%xu6G8Z!G&V#xD3XMcTG!k{3V_a_eBqaLC`!&oK85N-NOw%p(*kPgef4?_gCHXu=f1eJU`E0ei{<`C7~aw7 z97|Q%Q+m=!oj9I@aJe?Nzbv7zoM}VYh zXkIg^h^)6_^?6?YhQV@o=LmI=h;BD+AvKj3l(js*B+7Vt?d1gL-fsJY=&nhl$vY)3 zMc>AqN_I|e`g5aB-~t=0 zikRDX-2$<~L%^&Bexb-$1lm?iFQ;;u$>WT&YK*H|#N*knx*t7lmDfV}Mu00ihO5>a zv%ioK=0FLpEAVv#fLmGgNr5n~ef{k8kF_7Q&~2H(mJ90@1p(W2wiG=OCIDyppW2o- zMdLRHRm155WAr@r`I;okKoHV4VtRpni@xorse@$ejcGnvYc#Z%9yA|HZAm!x{kz~*$BR1-XBRM!K#4+`Bo_}8 zv^%DBnRI^T9xI4z2;o}IB_KD2kKb~06!KgQ;)4O7v9e!G2HTbKN}BmF@h(YAq=v8{ z(yc)l+C#8W(A`YYE$~1xHB2{V^w^v9bf9I$w2XpM`Nuhxf)W}CAFR-mHq$JOzSL7J zh_j!ZS^o)1`dl{s$->FU--KvZ)*TkLfC9I~J>ur%E8I4_o1Cs}6;Kftebi($PaW&Y z-Mnt9rbC=tS4AXO_=Jr*7WVJUhgUMbK0|3&ZuY$D% zz0h2&u6#_DLpA>zSn&9UPiuPz<_dA-y-kgx#_Q0MrWn+FSN`K>DLo{fiF17)89Ic&k8hMh0Ito^}4BRpAe&owF1Mzbf$D3$T<5)-ho!E@r zsZ&4$@e~78#yj8fQ3f6_nV4c-T?on@rjd(j(v+l9B6ze z3g+D4>z=ulH7E@|x;akrSpW`3mZQftu~l6$jcIg~@Fl6OP>ei4zNx&)?zT`a-vZ-Q z7v=Mu`S%mD_gr%2mS0}>mmj08{rVK8-f~3Ak%U899bn$qWFu7@$(=m7buf^%k%9T) z(#V6yr2(%=$9dpnOHGQ;HAXk*3c3_>=o5$?6g7?_Wya4N<>OR2_F*so?|8TlgF;4G z-!=;5X~T=0hn3Y}{l}hGX)gY?l3BvQtP=YT0YL)tq5njJD8G zk+*KL8`h2u+F%3~*}0@THDTPG8GK5UK+fA%5FCWSf47$CEbkG3zQy=C8A_u($Tg9q zI|*-IayfW2r!3cn2q)4p!`!b|gg7^SlL}#FjAW@sOpPQIm>A8;0M@?MM9Bz2CY?ndIcA4CC3Wjeb$__55TD8}?E9Efy5 zhaw1_Qy=oU-lldCqeVHC+to+(RG7iwO=Ey^ULWUN=Tm!dIL&Q*YST3E$V;Z{V>;!1 zA{*^XEosPEbD&zs4@l7MFOG^@e)KYV1pEt_)7se{h!UVRJwxeo?g-*CI|6M>ziR-8 z;O-r*=e=^4nfq6*Z9nN1!1LQZqQ%Zw9aq-Vtlw*RkLVZ?o(m*Q%tL3K1P(V<4>KLx zP(FfogHlk|KK;-i^b+Rdu5EZV>0>PE!-=24fk43b?R6eN7d6*ml(~%R#Wy}=0^p|Q zlAiMN%*lS8C(8}$s-VcZ?rIMi0s(Q0u`zr0KgO;0&+&5_vac|`v|lENHCFy}D4ZA; zTqP1bU6bcAf0SHn;|!zWF;@;|r|^b#&iHZ8dwBEaGUGnt_3B;$iY|J#2|4X1{EWC) zbi^O;ko_v1P=~!PhQ?(D`qA_I5wQC@aZH%YV(0zXtN&TcnYDg%@V@(k#^M0in|F*z zWi@hR`tf<<+O#c$zi^J70Z|4d3%NSYf-=|0`LoJuTn3s05_es!XRV>??yMw+GyvkC8YZAOj=G39-&#!+6ix}{|4)8ud=3lj5=u@0}_k(X6B>+$`<(}Yd zR(5a_GsVPEsWOmvr>%V}Q;2U=tA@s;`Mf`1sGVi_rnNZ?lukgJn4;CHs^E0mIugX z%)LiI@_O(PNQdnnJ((WWA54vGm&ENBC22i!?W7HqrQ({9m$OdMIyuTK?A%dLlQAA< z$@u0uR#?4V-SP`mg|y8FgH6-@oOIuzG~fI(^)hSYm{7k{yX=R31OPJCfYH3HLC1!5 zvf}>HHg=fO-F8h@i@%9wi93XjK)~D6Rqm76=RmM9atYvJZ@`AzpqiOn<4H#<%Jw>| z%=2$@r8BsPJCVlhny^6}#9Jo|tMQ?HlN*h|l=w@zd9lPsyk%UfI!mu(f9I8`cO6ofGY)1N6C4h8t&;|KMYsS&~Bm$xl zD^`zX;+|6hRCL^Kw2Ii%WM^&QPM(lEqv8&7>T6{gS=jTww&ne>0QeznvJl05yx`ct|Rt$rMPOMNVAt!T$DHBDnpB z+j#ApSESyBvv5N3d?|fk$POQ=~pZe~t4bT7`)c>sDvPr&v%Da3D#d*5~yYt29E_6!#oHDLjj@{zT*B+{16l*a0Er~K>rZ-!^^*C4w+pERH)9TQJ$-0@Sx+-QBH9Y z|H3k+iBBUuMZyFLvrgkYMbgJ2aAILeAhD&qr3q{S)8dT4aFYTdYX<2`t2zBq9%rl6 zXzGRb!-Y=m5^(zISE2Z#qR~c_{1VhB`WAWhlnn&kY?=T;3OZe-Nxm#qv0_QVxf*<6 zFgl&2PjUd`n8&)_{fgk_N@0y_t0oUh-a;!5RpXhVE$DL&Pn=BVa;o+ZHwaVB&e1>2 zz>Fy8Ht9YT#;=GBk@o@Kpx0YKrzWumw{KqfC>#W7M=(H3{>!SF`xiQ=Hh=|P|- zkTgDW5B6kN+l?y33!2ORd#7~jNQzx(0pM^Xm~+!s0*eocnPIIoC zYT(IEZSVTbeHRPd{}E#njPjE&YnuQ!=y31hrzP6U3W7_rG|e)D7$kHGuy8iMywn6G zj$GEzG<3|E@#%Bp29_!`XO8YISR4J1ICHqR`6KCo)d`ux}+cz{mnnr#8Gt}D) zHqJYK8JF>#pu%<*wfG}!P4%fccMoc(Mdz<&+G*oLKl@z?Ak|P~WgFfKOcug&X-j_1 zRapwzMtEKwgF-^cX{YyJA_SLVO5JTgzxRJl>cy-wUOK2T7kwi8*8R2DwlcQ!jSD0! zCB5*@rMZX+tr?Z0Pb%t&2=9nB_pSSdBcgW4I&ZNEZ=-THe28~CZsu{ohcthrN6StzNn0YG?*7*ueR&DcZ8vbk!beu%#fmF}_`)|)~WX2D&5z z3RRu<70R5kbo+B3bsy{CWq{V|FlLN&53BmX?!immy zmz@9)>Ue@aldqt`#84-NFJsC?W%YUun3e}$syb55p%EaYbbv;Zd)R=P$o`SGx@_K^ zI#R)R)gnJW!4bg9f*ksebCuEYxdi{eS;_Le2K4-V@bf1#od3?s%8|jq-OS$9!I{A^ zjR+ih5&6FpbdcyKJ%I)SQl|m}!b?K}N5)9o#zTV!Y--CSt+yffoNE}SfJ$Z=OYv0b z`HYV*5Ok%f9wttjk!Of0?Z9dHmIF!VMp%6LbO7@Mp%fq3${S6t5CQw1e09uP0wtlB zMaqznO^=WGJ7OT+l7KjelP78QnN!!opirP&kj>ixsv981X2Ih^lVh=a{ZKIXUvA26arh*P`pZagJYT56L2srsj%jLBXNzO zGE(|OkPMUK{*nY~B#>6iUb+{EObNhV2&0F&x**Dz--Z#<@=n8I52|V-kHj*?wM<+| z7W%)a0yK#&fX=ew?Z&{_UQps$C$z9JZ9hi=rnKbCB+4J62^&dod+)!?LT-X*<9^Sj zzTkecWCBlSj7k&lGaH5X0up2wQeL2Tl!GBtRUwaN8)Y#GsYVyn0?NJM{7zFHWa2~m zd)+|w)lk;pz;1li==S}l21P*=R4E}I!&MN+P(9bklP><78Pe5r1%qwcn2$ttv`NMxqtIH7nM(p8l&dAMCN_|_RWdCM zH@g${D;vel8kB9=V^8|kSLa2eT*fvb*PX(n%wZyexapa1H{Bq;yMM*r*JL^(UoC&j zz0uUThRZ2-sRtvph+PBXzw`AhzfQow2QCyLvybc-MYFnqhsUpR{ECK??JfGcEs zyA992Z3hIf3<$`i_g7>DKr>PCAA6tpdw!QoFOwWrG@BbHMBHrfMn+TMJcxl~ zsQN+603$(=#4ws=j{eb@fE)%@kUC!4_ZejtDr2-@-}u{xW4cf$3Cipkl=-+Ycge^u zPFg>UA`q=WsZP*EjsGUy#@RlLu}yB8LRhF>jbfZG&Vj!{F18MRptMl{*p`Qx2PfsT zDLY}V-i$DO=ChaUoaB00D034Q?@l zE3^Rs4MZ>$P1yt=$;DwAn&q9BRR2~oa`Ff&!!E}-5j#}D94&>QDLi9lQE{%KJc{^} zVctj<7h;(>^uE-DY)iomz!u9j^n&rhB8?Cw&1`32g;Gnk0YtirAN>JoxbsnKm*+#S z(3p<~X_lL{ua8S2t$rP20*NA%F!fpXA_JjGn2c^JEx})vb@a~=KU!@l~DA6eT zH&6a9&69>hkFpR|(Q%z0tX2{9(*)J9Dp)9)aM+NXIdkY8W~_&><_ztrgm`i)pOr;U zGn(uUy}^GApBmh`Tp2bSAI2=LzF@tY4CYL38-|2Ct)q5$*)fl&ats<5Zho>t645uT zYLk~k=D$1hy-WQ9kVy=INk9ZgRqvHT@2KBY-V1V^7$RYaRVPO;6Soj5`WV&7=%Nt| zVdi^4&zlAc8&^Q(^BjD#G3Ykt$0U@(;TjrPYQz#-Mw zf|LfvLKx1Y-t0S_@ohMas$c1UH@r5`d0e-c>AZcq>AYPF8i_4J1FuQ`>bI9)8s!Xi zfeLZhiSBCxP|1?rO67F-GJX3{Mc zSEei9LA<&oPFLKG?TFdL6biQTMFYcxNz3KOU zo)w3GSLusq_03TA3Ax#`v`jvwpGv(QD9dB3*-+~RP-nhiw1gWZnzd|?JyTZ+4?zhe zAdp%bYL*i5iKTT_4`VRM15&3mF|S6K<7Ji85P6Fw+BQYMoC|?Cr5o{?+ACuF^KWHy zzGL|rjH}7d(A+;w>!UuV`p=$gf5_SDijEoga%7W5$!a*BhgDvb?34 zYt$|#fFtopDv4@_Edbhgt%r{dT+zrTtb!^6M0O{Wc7?2?8x8q|WH zANj~-nYE3Z=`kD2Y3bGXw;O@)^1^i=Vp(8^S)i%%XLS6{HvvM8Oa7D4CA_;s*viWs zP)j=>*f4$GKZ?fM3&25ghpN|7e_0MTV}XEUC(j=sfY;YRHdg#QvNe zG0=U{2-u1W=nFC;l39Mq7Gfy2#~PMJ+-G#b&%I(W7FWCVV$zQ%_pvAwgy$wK-egRkWPO62OXpRKt?E_|3-*^ zfHwdRKOpiGGz}gc85`hg=Hg24=;fExXCK4}7kbSb;sGNGWp`$TGZ))=RcE7C04Ix% zj>{8uE4pYg(cja+JvV_4pdcRA~>#gqE0~79%888d_|orlrWQfm2Ctp?cK$Loz_6 zPgw!ko25#fnhYO9(D@3V>|tsDaaJ)rAeX+UyAH(qRTQV>?+1v5A84(7qvzRSlTLMTbM zM!Uo8kI#JWfk{ZZ?P?Cy=Gs zOej>1C@_C26j-u7!5>9~%buZyVrq9p1Pc5wyhr=rW7)%Sn{@c8SOOq`fN=i@xC7i= zt!!O>jwVKR+98V(t><3D6EaxpuiSiv&TNOi&nf++nH5d&U;6~cSX;`q#6!S#quk%( z@?Vg)A6w7e26+{);*v3y!YX<$I15)gb42mgT^$`AW8`A3j)KyC9Bv}@(Kjw`FW%8A zjr3t|i+@&EBlE^w*y65l^jf~c@&HGt6DtG~PDrZB1#-mblbvmzm=?f+VOckR^ud@N zzMw_Ti*U`tK~X;<#TwKtxLx71X*x|VhWC<{tqo$mqB5Y@K4|diOnK4+*mxPivYz#Q zZdFMtoFV&V7jGpB$H_yjo|68{C20O;F;uJsym;a4kv-3PV8_whe8UOR+~L%>L`i`}!G1Hok- z!JwLP4`4qTVh7VMv>isXicdx*y#ZXqQEMe0n$Di>M3?XW%i=Jgj;WDMO=+%zpJpbh z%wdmRkUr?x$v}(6rLbGbhUFs%ciD)DRFE3lFqf`o5&pA#-6yUT@ieyvZKb1A!k(X= z!3^l_?0m-&D->OHosL1*HWN=MzJPUg{rQT5h36azqYw}bHH0#ihB@t6K1B;_c_kl2 z?0URN-1P+g7U1q2pb3kzl^2r=GR}%X>V4?Fs6=c@t0+MJKzU!h57btpIh5qi@T6G3% z9i)A9bq5sf-v&~?xepR=_?@x+W6wxrN(3_F;VY0b>QiHvmoI;dfGfGx_!IwE5%0aY zHGuv);S0yvmV96*c7M<(ClPSthy8eDrFf1<6MDXwCtSM{jXi*1NPben(|tb4w1fOO z9ZE2bZ?EwIf@!rzQD#D=(2)>eJur6Ch>C|ux4)mZ7X^G}%>C?E7c917UU1EWt&Pty zK8mO9v%PX!Q`V0f8-zZ3EOs%i%o`N^2EIZ;9$ozP9BcEH=w@}cvY@J{#B3yXKQtZt9Ve6;Kw&V-KpX{J>RD9Z&pde-`TUQO4EZui&S{>9Vz=I5uxA^Y2Z zadpnYmBin+kF68i_QbYr+qQLLJCmGvVoxx!ZQJG~6MLdNzkBPwSNB!*-(6kZRo~rv z@6TE*61DrzU2<8Cyn{y3u0juYCBbr*O2KQ~jkw7O%s>aVdx8k5xY1(You0MiTG$J| zmNqk>b@cf?54HE>8GxjJ@!fIoR@n2bwifMgAY420BiK6Xlh|-xQWMEN9GDOK2jc&p zkj11eTk-s>p695bZ)5-h5F!o$8EEXh$%O_yEpO{U&47(a%rj$%=Mz~iv#;ksMz8aw zMM%%E$w{EBqQuf>=$P#(mKneM0Y$`0@pJ5O`}S(I^YE6A@WTzNK|!J?SHu=udX_07 zxf~2l@`*jZ2t4sZ*yT$a4fzrl6os}&%M)s%^Fqgs_3 z++6>Iz&vE|O)~|E@-Y^vYh%)mA)6-yXHONs&l^oxOW&C43x`-~qG>h8cY2mscEi6& z9w|IyRkGwTP7_{0S6*ID`b&%+a^iX}8B0MQ-_Q-?L3;$#kBzW))n0GuO{Fs9LzF?Z z*|cm4AU4M28W6Bm^O$Ga4186gZP#F&oMV;I?O~kH?`bxg*EudI)}+E*weY(^>e z(FdLyje6I-`8N94Wy2i8?rYgNw0wAL*Qav z8Zk}LYb%bca1Oa)IykmbsA5>qQ=n}44!)S}Y~XO5udr_p6yAUSPzF=phtxJxskFjGV9YI6BZ^Bt3qu zZG_BJG8M2T_n4*9(jg4{{Py>V$;Xn+fxGpz8@hax$=tXE0laZL$c5AB64I*q_>Li` zFXyy)p2Cd_2zik%dN$&$2BWr2 zpZovJW2*ZBdEtkzPbJK@~+65w^Z6laz*)gtG z8qm1qEebWaLa|4sY-~%a^TWL}2DDWnJN!5pn8y-f#FHJQY!kxFWjaq<62s?gkyO=3 z?HmFJ-jc$yT(F9oC3vifZo~GqD0fp!+LzRL3K?DalKUEhHS(S5oOWC^<2nWjI?tpT zg(#m$j=n2W5kpL0Bm5x5dB0$o&ctFt@H1qB?#+q+4h80 zAgx?mVtU21Hx$PtvR?Zr$FzJ3b>ffowX4dX-)8Gs+%b2j1#5p^BIPMeUDX7GY~FYX zmiamUpk3FGJCETBp)G7nO|Nhnl1>SPGyE~FA60x$#To4JI&DUW=ur^Uam@(lT8{6f zx>Y~G_1=eBmi7K;9(khYowPVB-sTz>33R;AwAH;B4~BDU9VB*c z=NX2D#bU2j2BY?myQ;PyzM~wLhSp;BVu4;+l3z#1`8AccQ>MdB)QaPE#hv}Wp+zOc zwZrEt_MRQc`L9`LCyRB){XQ-7-$LUF-IW5{jaUiYBA@J0~_bW`KO4H&tcaI#D9d{Z_7>+*{5k97F@)V8?ph) z3;cAk)joc?XK^QTFEOJy{s3MoP)u26LpmqD|HpPUwr5zMy8ZS=T*~MO)vY66NTV6N zcX~5VDXy|tKFbTb7fF1>!A+Y@qjg^Wm?U|!*z;{v9++%Sfd$mQ?I ztKvA)@2`s$^ULk?Z~awS1y7j_{EC?s*UH9(FU@j^2fqjLLpvhfIvzMFlKU)}JxWBVcxF-))O8?gvAVi)LQ@k1WK03Vdmeqfu4Q*vRsW=A-0c6ry zdV>FOhte3!-EVGA!Z_a_+Qu=w0)cl!lL7s=1I9jj7wdL@P>~WPdC(8jl07in+}z*- zl}q8%ygI2>U>IevMf5tP#jB^n`8}OoakEN?+Sj#4#`&Yp%GW{JthewAOGUB3jGP1+ zGY*Dhi#~`S{;I>|>RM{+u~>6NjQAU<4I!5!$7WP3e1sx`2O%Au(om)5KSu|qjW#U;dd zd%pPE#}#$qcH0|O|D7v;0~yO86z8@@n9q-565RqZxR5oZf(#KgN6TKs>z>akE`1z}xNNocjxJZyBi?&Ew?dtbLPn@m+KyxBqikuKgh?V5AQX5L zey}Co;GrPi#6RJ#kWk?QWdFX@ApqA9E40qK=@P#BJI@T-2fROKgu#`Sw|Hl7@=eqC&M1p zdn|2Hq(B&K3WfE2fgUy zheMet4=djvyukrxSMlqpfA!%pE6)|_a|Jaz6Kq;UF80_sYP!{_5O<_zsZ^2BqG+XW z90o`?wrY>ehOueq)#iVW^@lic`nHOR->EoNu!o~v-enxgGgGy36?)g^s+q)iBEM%L z;)?axz;Z=Z1Fg#)jI80qmu@f)j-Ezb=$!S-*HK2XXh_$S(BDxvtZ*oxI7SNywXkKS zshh-nSXDh9Ju_t75C}u%C0rV1f5%ZcrBq8Y*?XsJn{cbUB$KAZc)dvVmRmb-~$t2#b08ZOyY0>mC6FNHJ{|>#yM!0T` zouK{wOpXDqtc+=Ix@|U&6MC|y06UPDy2Y3r?^Y5K>w~vSA0h1Invgn87ohDgk}ihs zJ>}4-GDHim?!Ps`LFMDAdylCDMQ9vs2mTGs>3FS3KLY(t6bP=U&MNW;s!|AC?}&7_ zbf-B53pkg%COh{%W%B%ykorVkoSr7Cn9lB*P{3#@q~+v?+-svs@?Mm|sy%E`Bd#v_ zXLL!~$DRi&@l@hBL~>h{u*KG_y^2(9ufrc&zIoK~+N4$l^?ymV&a9GWXkU3aXTL)* zwkw3R)zvxm2b`cj!sPbM$Rcy#_)fVJ{laDEHU(zQX{{V>*#z{}rY0EPE{N%iZ^d9s zF#KQ>0r)qI8yT&_|d*hXBa22X{g$G*Gx9 zCsKTGyxy*)vJmjpN{Fnk+EDnqi6VQMZD^2r;7$}piDOGNO?eiFMMEMQn8~;!?j3gg z>A-Avj1LoPCm1Tj`96oyuE>WkY#)^kKBsuKuzg#bJ)=ivN5VSbwh{v*sv`q28~i&q zu+J)C@wst)F*IV?{J08(C7?6S`C-}AU2(&s@Az34m`@2rI23PDtlsacf#T^U3iGj` zXj%XzP;9HB`*TR&yhy`)rH`O96`t2aH$?v81Pl6K)*X&UCf&)#i)0*YP@YO8J9SQQ z@BBYqIWE!LvSGyo&Oj4n5bp(%IB`BQL;WmfRY=q^dR9(pOHQVVRk$zn?ElXlXq z2FoLgeI|R@bkX#e$ya963+frk?Lup6KoXM@@u&4>K6Y&{={}rnqZu)Lc77Fk{d2i5 zbpULtoMwfstxj=oK2cnV12uX71xEr*IEVVO9e%pUgnLVeD+`IJ8QjRVh_Wq-dQR)L zhLEVnUbhEa280)Eb(kBaXJKF+jOjhzC4Bgs}7#`v^!F0?AnA#!$U%BZGBdI*D9_YY~tjDQQBcYP<6DKFLG$ zD<-qQ+sU!L*ijCT4}@&R9%trVCgp3@;}OL{T`=nCZH0T`63vgwe{;oSJm0xXYI@RKw8I^27s&1QjzN>Ej!fj)~594F5+3*sXj<`w&m z#RJwsv)T(!u%Dd&I3dIGb2m2kyC@2j-1(p2ezsRJwFH#uczWBu6aGj%5n3I51 zdFH8XO`vB?D}~k)LEQ}h)>+;`XEvRugaKXNSVzpCD~{YLFO;I6(kD-CaS=khU1jHQ zXJ=FN7itjgqH1=!rkF~hP+Q)*Rg|U!iF_&_vnd**<&^5`W2Q;uD(9Sa_(OV|V$E@9 z)U>F6q5JEv$Qcoz_uIqMuNS7ta8`@I6f7E?XA$_4T;ZVq_*HP%UjXwq)XjCMIXd|p zt@*WAwND58`e4}6PiJecp@t_f z56Z;hB*C2be9B!&d2KUH827DjsPgtM6-UQ)23~xe! z?OO3;W6-b<6?af_IRbqZqrg73o!YLAZQWGw8w@i6ftK#(TQ*Prew}!{}`+}A9Y?>)E z>$2O0VS989B5mgN0NhnFP)c<)Sqf?XSdFNW*?bte;^E50u>P5AoX zg!K2#c9}3^;E`F>!~-4vo3a!d85^<_Q*$F`vA>fR6Eh2-P&L$qZufF0_qWeAWRV`jaxu+KM(CrzD&#>oik_z2C0gwmI1P)C{{ zxSF`4eqIKKRuB`daZV&Nq5W=19O2@mcxjytAZoN?FxjO}DAZKH}=#7KZ7eF0r@ zvAR9$WNmr>$_ogA6+jEzwVGNw|MQN|i?b-J;83r5dF>Sukppv=v`Ol+_MQ$t;ZFMi zCf_Nbsjde;>Kvi15uN$^AC=R%H#SlWAC=^6`k2M>r>0`>)syV39=heYE)umDA2$S* zJF!m%8a{D>J4Zo7u5)1>;KHcMZu2sJvGYC0(w8vUVX-8@2qZBNdfSE?b9j@!&JN93`*Aw+619?#=8vl2tz9In%{ zaky%RxB{3TDzvuXoloPDs2qhP(z~Dai;V_E-dU$5{@sRsWo6#KY8P8rZAZ(qU@(9J ztk2~!0HUCb%wy!=F*y+E8~#m{9d!!n>)xH1iP?V`N_ceQN8PKEe1fV&S>p8>JXZ)< z(TqV`yzXuaHb>kYORv-)CPBO*DdPOYPxB!P_ADTrtpXAwij|nI%&*;LVz_%krg*N- zr(1fLt19bNVi|k_!7C9pOdA`nP@<0GZsMIzBs-kwEy{9zl6R!EON1eduxH{6Ge6<) zd$1EtCN&=XZ0DXm0NvJ0WZ^3HN!&P@40&^8gH*fH)k2`7xA`_1AC^0 zLZ#O{wC~~i3?e*QT_uAumiv$5%sSYP&qLWsUfPtb(`TaA4%yD;-VP1{IrFKyX9>`U z%moG09@^1do~7J^d=diUKa52pL4j5L3I*$X$9$-o}S{o0UGEJ*PRClZP(BQL=@lmEc;c<$rh^4_C4 z5)KXP%vCc$xIe+24JP%~AD7FE#d-w_Ktm4J2f~C}PC?&tBK?GLMrD*qpncb#SIMe& z+rXCB$?{c0C%cu@y#K!LjTW)5n^7G$R1deHmVj#$L+H!0%$9U4jhT>0m(LWdan_U=|LgD%B$__+!Cw-AAJY|7qQL~MG8~VkvpT^&nhk$V1Z1+PQiT@_pQ!FH4 zQtw=j-4g$2zMj63>ZQXM^8cPff&rLm;r=ZF9YL3z05PCWRBXl!7mnGmy%|S*W_=%P5((p z>Y5jc@)U2phWo53S8mYi8qX8m@~r@0;%+>>zANFt#qBUJ-lE#kU05bMJIiXg?5nXM zlM2wHLRia=%atw5U?9eLrA=4X>^W>iy|k8UhigWX-)+_iu{*E7JnJNT7soTzLtfQ{ zd#9lBf+&l!&@o%Rs<%2=?Zx2cJmYkavZLAxrUg23nQSdYHIrK)P)BfYJX=~*Ic63f2gMV~^W3Kc3Z zK*6>?c8F)6J1m>z0IJ0ZfCI#Itwrm$ZAO9iCkQEpX3=^fOW=3ct?!*=tId3CwXQj= z)ZF=-*aAy65{n4?#+Ds3We?Av4{d;KU2VC!M!88*Ae_VTo4eSasI=m={o6AK4m@OK zsi;vE0xEk*o{_8qX18Uz)R@`|d8bG}hD17E=R63#4_8n?I5W$T+c;IJrB*4uwJ;J4 z2~P;f!E`$mWRlwGIe8Qf1&bG1sVrm$Fl4gmD9GpHfbglZODAw5X!VKcR|7&Og;f;( zTR9v#Ako<|ShHbaLoW3+Ub(2E(RBwgMi@3tt0DHylPOfQ-PhD2?dTi-V0aZ%ZE{Pm zi5HIEB8>z4w~c1Bm05dulsn;tC65a&C>*=zw6N3s^yrK>Jhz8(d z?KZQa?()kbajcEcG$-^Hi$O&}IR{klxE#W7hkhiK`kkMv3A@xF+JmTxQC@-clOYTD z`-G0IBnljW0TzE2qjx`*B+H#wcb{fzT6@#WyYW@3rHYdX@z6Dq37{$c-`gcO3Q~EG zY=$sA3LOC5w@i%d^r>K;KP4j-5BM>}b}D^`pZ-8kBpY8OwEAQ2n3x}+?=q8-;mw@LluHv3;UxHup`{X{<*;Cbj zsUkFlWyPvIZuDFeP8z+{;zosXLqv0YWzRiZoAUf39>-fHgL{5cIc45JV9Y%LTUDRa zxw<=zyqtm!#dxZO*bkKJ9tsP#FP}$Mob!i?>AAwgzU&JrT!63_+vz82K{ZqImZ90V zd$>*UyWk`locY5-?zg>bAd{Z`qPJD*UJ)b5`|x&^`=N#qAOyk7Daw;Z>$p3Kd2J8+ zi7cS3BaWq2hTNgU2UGE7`-(v|A6+#Q;)h5&l6%w3Uc5+9i*tfKgKFu+op$gz}h2 zE7n2(@Us1`7VqAoVJkfBQr6L;&SoPj)>Ge}+*+&-<7(D;>bzowY@#OYOP~DBl$x@e zY3COH?zHQ$^8MPcoS70h!Ji*{ucWwSx$Pn|6HA8+&lY!b)BLnC5&(f70<4CZeH&d` zS>~A#tv_Iu#!r#97c7C#@8}&qJmZn;g)5vaH<#qi_6|PD20}DF{OZfR51eD>xsKLb|lR2*e@+z$aRAgT(cyF);|i9jVU` zyYUQaPgdrSy$QY0OZlk?vJwG&W42od*b{Bn`99#kxueG#)f*O>6G?(un2B8Be5)kN zSfaro6T91u$0?pQ8N9*;4T}IIFcTp<7}tok!b|Q^hNnU;uq~GUh=Pbj0VJs6pP`&e zBK+_r)vDV|;5i_9Q2-^l7sy2vK#R6J(C5j|j1wdeBMW^=@T3Z=5CzbIOMwgL`tJHAPYG%BJ=>KGh+hoA2JeTl zwhJ`y^)3f_i2+n0ZnHq+VgMTE+=BI$Wc@M%SWJA(-!08-?ADn8xc+M5FSwBe zTfTG$D0WflM`x5qZHFLYaR45~JspTw91sKU1{xFxsDdYhup|Jy;D15N5&&$(2pET= zEsJu6yhaenMFNn7acy%_)m_(V5^KA#!}jYpdsW3*pV@@3pJwa>shkCs&6}8Ab&}KIx0>iLzl=Om3^NuM`o$p z6VSFKfE0=qrS=>IE(M@~srF0G%d!X2O94p1BS7*}00MFrlAAmHOR}tPXZB}@)LCEf zT(E-RzhI*Cg~6x&yqRfxnxJT@f3MaK^h*j52#y0{l?Lb|O{h8VDUuYFfsm$AK_F>> z*8k`tZ>0g2;QzhdZSVlQnf^yAr^A9+?f-FBKv@7HP|p{0<1>LWG z@BM9HZG0TQ(FbSF7lh?!-Dcg3LNe0h5D}Kg944{mrYYw^>LsO*su-(-NEd)Sz*_}n z|9~0|L=ajHs>WgrcGJ0FYlL3j(B(U3ciyHN zKb52B+XMSAX2B|6PLC(45>HpjCLK}J7NXWqY5h|WgPHp=G&wEv_Tv(jM>uNOBVPZh z?U-VV?O-qMsV&sm$16!Bfwn~_6h$KEOuow#s4)PY=0&ct#ll&>*G~qAIzsNaGuq9e z%t|nM7(ep*5QMQ*1PcPpZTc-AbfO@uT#*LZ55@n&+?K~8htG- z`%QQ0KNE<9-6*r>%rp-sRJ*kLo2!fg&RRDkuV0%=#tp6nxyb;ms}0w zuE5S?5ktD${m*A=(10(OnndBFatIVLFqK8E0@A>CB7N{Yp_Q^@^1`Y69#*2TbZB5v z^*rel8kAZ`b=!L|f|eh@XI}DL_nTIqQ8+pj#e=>DMa-|z?Q{|Tu_b0DKb-qz+Ro-^ zk+iLtf&N!fM8B*({hzs5^5n|_7wCA(>YHB{eP0;ZW9n=n=x=%nM`HsdA-Rbl zdS_=xb%#-YmDAsdHa}mg*p`~?OSOmX?PcIW+WMb^1GBQDUB62HJS@jI6|cp zz~!qaU+rxz&t;;NL`=2IO>dShOm<=YUCn0f zWvAULr8xfOtD$ZUH!==YW;d$qzuBWXMtDEHM|w^0-ikkVH2Ht$pEf&87))D9aOi6* z(rBiwUbx8VJa&NR6Cdk&BOICe;S5!|xZ`GE7im8VY3nVt_Iv~G8n@n*NA?Cr{qo7X zewMLcsXTO}-ZQuE)Mk^uojn>AyW+o%&Hoau)RH8c3~J@CHS|uoF!|%4wbZ`CYJYo^ z0iD&-N@6iTodq{`>YskyJT^QcyYaBKCv{n6sAPz~-1pdh^zkzrgMeQ6 z%2dce6Z)6L{LV2D`q5dF4ogX`Nlx^~Ul~eo-!$h^KllSKNs1DPB=rk5tg z@V=2(0eC&nV)Gcm5)@Ns#M*!qCu=!ns%7V7wN%^_3W@F`y07|zGck$FQk9*42uxc( zBL_HPflb{;nUK|#zv1`@$64U!83N~ft)@s*ttpZdWa==`7vC2wZ#u-DiI@THT+7Se zr;Q7B@ilTqLT!T~Cd_qDDLA{rtFEdmjprWKQCVVtpQ&PAmC#KGD#hFgX&8Cp0wr8C z)a3jrd0o+3t5C5LN-=_!E=cd$c=zbOl#U zoGA?UUI7Q#m-ArX|9A*?j>QO0IbS`35ih;fTCluGQC99~q1`H}5bhm-%$Q#+ZLyVm zp9$qd;(}L2oES*f1L@g7sq-bHX;C!X*}5AY+l(Gig#PTiPDymmD)`oceDpCuo8%7$ znbXq9|2@mF54sFKQ6W?lsolgBs>yhsKC!4qF1rVKu0qhaJT6_Y#f4q3rsG}yHxxA5 zg1j*db5c?0W3n2>%uZDEAXs;2MP@PBZq`7ZLi{OH_kQg*bC#q75&g zP!Z)i_4`dmMWAwi7P_Ia9<_gS7gkuKXYq<=EsBr1OlG?>pc7Jgf5QplvhtzBnYgs- ziXI7wK=b`t?=j?L_jDsOuVIUNcl?$#AhySg)c3|EtgJ5{_JlJxJV0(|b^Cm?B`ecS zj>vb*rmSFkE*I8pe3C8yLzEcj;9Ff7Z$GHLB8&|@46S)f3vI7o8+}H^TA|+>_O^%# z80Dc_=zMSbRuRXYvAUb%bqb&1m!gRRWf4SN zD5Z*@&uw;2wTM&W^p!63$C*dew(`OUCMq!*rPpLR*+SszC158YF!1A~c?sWT0#gn+ zVWM4qQX656O=GF+)i&Gtg>8J&0WqW-Mjd8sC)z)!i^me>k*5ae8Ip=dBvr)WB+TVG z8U=HQmZ^>)lkk4_=;Ll2rheoDf@vm(i&sRq;b27cQx~2iq$C&iqGw_JvtSSB zOX8M3ARJYS?R45D^$`*Uea61#yh-G0f~e+UvN5(XhIgV93qQuB1_hnKsIpfDah8G@ zw$XgSfl8MZ!3=FvV}qK2TLuC1HDd0QBHz#VrN3cO&eRXqnE>;%WUutTR=pBfT8}oq z0ddtFCgl!A2>CFexZd_`GyD4#G4-U4+s7Y%r(?lE(qzlOzFS2b*1<&rwlMf0qVhZR zq*aR`m-s8h&CuD+Lumu=a+6aHb+j7$FIL&hnr=NQaJG^8x@ z&z3~=a2eHZzlB}yDklH2CDLjj!U8HFLa4uQ#^M=Yoy=^7IxRUkxSK+$zM~qgkHyu1 zBa4ql&jK0Jvdg1*aAZuAORfwT?%ofB0fNe#2~17={HaaKUg?zvey|S!(G>22w(a>$ zwiY7U3%TySahl&M&5qWCOG}~mu(5Y;_*ZrlrKt%3Gm7QBBgxe7J%t0T$lfiT7KoFO z_=&5cD!j8h$F9U-3tb?Si0F)B;z8X>)%Hxnpl6kf4dxW7&Vv6U(Oj7 z8BsZgRbCWtkzP70ERPWWQE+6LT)50-nJtB=8{ULXc7d%^G~{4>W#L+1eu=YBY4>C$ zupkb%Gg`NCQd^5qyHo;neuI%$d>CYy<;1R)K>6wrzjz12zJRe-jlUykdV&?Y6_Qmz zrlyv9Vp;XNs!H4tz0hfRqT7~DgR1Dxd%k;(=C-*vFRR`jW9OkV4o|5=CHJ#(ArSwT zSi;L_5@-!GBTaoLsuB~z>go&bV_{<(V79a@imoPXXG6|NTZ;g`&3TLT%X+AX5FKP} zMoWc)Ep$L!%aU_LlTUQWLP?8C)rp3Zrh8e(2_%bv?XiuQ-1mAtJ2bI1ZM#F6f8@)1 z_Qi=*AS?toL;@HLb;2y(&X8$KK23+?CsQ8*L#tGJ0cV`wMt8_k*?3K(VL1A*E9;d& zF)ZgB@?mn`)c!!;rt=UPQ#khYUz<X7kfC4oIf+a(Hc!QCBbU1bD zjZ%+9hT8dH?yMlitL^ogDYSazf$Zgm&=k=`PSNPfCp|#raCq^H=lV>B14P^DX*Rn{ zOvt0w^5d2An&lLCEyTa8D@o`$5w|#T30M~#{bNRl>JN=O`YHl$-@W=IplyF5D}g5_ zN&G&t4qFKIz@!2xl6z{8xBP&MFfZzM+VEV5T%+$(@x+HQz%F9B$UJ!darCVs02MBW z=vKcBR$mIJdn?uz@aiJso4-Ny@#W`TCh;-Qp3ygu6_$S+^C-55-0xE57^aEDv6@@V z8bd9H_yF~czZrFxAF7n%TF+abix+fTY~eIT;V=L@9w5|E-smDp%6n*|)|eI$%|`2l z9USYm6fBF&k_roTu5m&36rxJ_?N738UQDCdrHcnp?}fTJNz@Wg{3T2vk)9=Gr(H?v zH4{k+({6$v&bZ#Zjrp$WX>A(a-S-d{M0NmMqaz=ajiePH9!-@Su?HR+r*wrzt$eN( z&)D#m4F66@mxf@HarzLm6PF*Ny=;V#xX?DAc+22StXkt+=_Duq*%N0t~@Kc>abm`*vEH?{H#c zSliQm>tgK-4(If6%yeJ|A+-fsmfg_j!wUJG1M0?56@xzmSX?0(9N<^!AzM0l{P!Im zyCh%rWl!d((JSI$_(Qup9_oP0d%54%XA8bSUS;~U6v+blwH_{4Ke700zR071zrloQ zTgmniuVq{&sr;B4Z7`dE*gj7gf|WmzokX`_fJozQ?yR8cn&SRqT5CSkA(7<-WgG}( zekus3cU=h5CaX0XH}jKrW{gH+bJal}&j$zn5-%yp9sIa{NCEdX`-LyEDMZOV+O>Tk z5b7hnXm~zKZnFNyDb}vlQD52aj-^s^kbI`#F+M2bH1n%zrvbCAr5di{z!C{!F$kXI zhAU~CtOhaF+qC3w?)OVRVBhzALczY?d=>Tp;XL@c{Wj0|H$DL*=YHhg7(vawZ{wN~ zrr+oxp|`$%)?pHfoyX*PTc*y>yeaSiJ92OTOe;%oX8K8zQn`GuL8;M_5<0{eN@#8F z>$mYkGB>XtoDCSz=Iz;mB}17NDJJDsAr__=Kpmu~pfBLZARvUwo3imAOBnqYH`{)y zE0HN5kr6CwPeUJ>hA~X@b-`)F5m~5ykznS%=I_)Js6iKtAhG(4Fz{gVQv)m-Xn?bV zB&wamnnY#RmaWibr;`?EAP=M%$Y`-?dXMG|u44BDU=Xmb$IW5^jRX&PkE48P4F$=z zZ^_<8#+>F@D9vh;R(yK=9;}fx(jZedLYosXwN?^|$KS(i9!qMEFi40PwdfzzqxLN+R+20I)aw(xQuyQ} zO|v-GX?G6K>dXO~eBQ8@FX3(a6qLd~5n!Kfpx_yNcA67KL)Np~H*P5>)<sPp9OSRM6&rb$J?ldch~%~762XtiJ4#jF!^gwE^zRyos6FT->vFaB|B{kR*ew4DiPx6T!QE*N1p9j#OjqGgjzgRw zaXTohx`TzpV(b0qu3sH_p#eAm)0wg85dE`)?5m|EhP<@~ChHxY{k(A#a8&wcVBeEy z!a|puiz4iBtKLc>m3pzb*sftl2BFN#!-OE*k0NCPkIQdj1woCpvf&|U8{e5=teS7! z`hKopUT5Amhe;&4&ijwK-h8QZ^E~?j2Isi|b_EVn)d!FQ6KJS*f)=q+_kRjYvv0P( zak%18+MjWQt2CUF!Xx?`x+EEA9!G1&+1uv3EW+BidJfqU);n8TQdZww z0#ffPJIJV%-zcns%R`R2(KKCP+5y48M?hXDVM^hFzaQ!IbD8I|cJEbB!Jd-5k~)X5 zT7z#WwLf=&GX&?qozhfrr1t)AJv_ zP_~i3R}pW!75XI8+3LP=+#P?8u;6-GQC{u`ctlJQEOIEK89-h&!J$*|k54&4vo)g& zX}_9W-(^er$0X+u&ogx3+H?x%fkEdecxtA;yU$Dkw~<-h^R{Zj>qIzwq!$exDGWlL zpL8o8N;`X+S!tlKh?*T;=)-1gdXPK4g05$~F81a6WyOYGW^jxGY*=9`iv8XiE$X9uG6u)D=3G-y!qk46KbtMf^Xev@lcahPO% zv!UG}%E%d|P=M^Y;BpG*bs0+Seri{hA}Sl*pCr;Ws+(*n zP8k$c#iEyoxqwdR>on46Cm0P%K6$lM_K2Nfxc9u@DD8%n)!AU(Bp`8{ZrJ~30RnbSw6eAHs&77Hn*7By6pQ=<=lqK$ zh&P{|H1QWGTAW{Xg32+uAo2kThIDn7;q2=~1wL@AF=b9vZ!yhh0iV$s$>C+pUL?=# z-Zyu=e0;fljCyc)aeVym`Z4^~)1w5mGOxYdycv4*!Xf!e<{{PHN|TYY*BNs6@0SRn z^F0J#0oBoBn!10M~QhhO{f; zfgHZiB+8Xi08j|PdXw=;sU8#E=zl>$AhxFF4(a6BaT|m4|Eq&C@)l)Q@K3T25`^QX zHfwL*g!2lsErmB*iS_LS1FQKKbRSX$ZuAnk&!1_Bxbx2oF{o{z?cnFfPk!o0+NkP* zvn=7ml4+8q;cEeCcIM&hkM5+|sYh}b+~CZ)tmOL}TwjH7qaO%%q{c6&GBC#I$h$M= z8_|)6%tg27GZGvyRGD;{2k#ZYDpO_eciu!<-(&E=oc3GWS#NU#ye`$_RROV%9$P+w zXxWBK5<9(&ciRqP6)lZK)^>!_J+P*g9@0JA&AvcHB;1cx$k8;KZS^eukIO)N1&jkUi z!TQzRWlE~IvOD(X_^19KgYic$=ZujQ`AJc>cjB9iU*%!Uj>)Vr8QDI=gwqu`N4O`8 zd_u>Cc<;uP1_(G->13sx4R%VlIlf)&a0NUa+ZLVs>kbRfTR&`iHV66-v9QVurA~5dvO;?)donu$C6q z=DUwq_Zo(-+U0zs$V`eNeG{f2DT3ffb*Wsnh$1>u=LOUa9;CIAxm76DdKsz+4gN#| z#Y1yJLZrTYZ;F~s)RKE2L`JB(yaCzo{r%QVjj`H!GaA{(Ylu9pSU$|UnMvSqi4L=D zYN`|2Xld*U=AzvKTOKdc)S=+;yDO>6FR?+yMgKW}gbSr>=%_+mG^5ZYg$$kWX3W`| zl6rtqa$2^Y(EWk0sKaa+pSC_-ii#(xzSB8#nDIC7hjiQ>-hw4*mJhNw-Z%KnhUO|( z(~*F+Xa*PI=Kq0VZqOIX-Wt)=~1vw=f z%Te;5&cL~3Em?6{w_Z(USl!VSOrGG15bU!fJ(QovWBdsrRIr%5#r>P6|GXB}xfJFP zA11<7o8|<4GFHA!qGp1orcwyT3aaH464SWM<4@x50|!+wY!jXyz}>$8cF_5( zWQosQOfy^I#u4ZR)D|h;{8(F%eyl;J;n_*WfMm7dBleG6y*>kW^Q!s{Sdrx6_nlu`Q*BZ{>-FP= zFeM^sg~Ui#WZTef!MMCS?8ZAIsa8IFT1fjO;QSX?=MbIC7O30Uwryv}wr$(C@yEuF zlO5Z(ZQHhOy>rKH-Pfz|LRdW&0OiM>K!EUty$k0?*`8;K4tEsMUfHYTCDXR1tH!^74Uzh^IVr)dr@Pu)T` z@l4r~!~aE>aHU=Lz5WX`J%gkLb|d2gEFB#FE7v-D*(C@$1PLOA-hR?jcmu^c+e`AY z-p>_DNohNb^ud7I4(WAtu3?z~e8Ry+H|0TK9Woqt_)F@t7>U&~{)$1xPNykU53HH~ zF~SkRWnBR)R)!qxA&jb*qlUv%TTz8-R;NtJ2i74e>N@dJf~J)mOL0H&K?H>afV!|_ z!~>hmQZmr=P=;+nVauSzmZ&cnCWgS3u`dZ&D&~n!)0_XbaRcN33wrua9;Gi}2(IH` zdFLKe59g8>&5;tjjR#oCXWI~$Y1@M?hBxYT3ERenf=2K#vxUjD#1AcmoyS)jzmVm? z6Ngf9$xO8m1N1!>@Tj#8VYm7MfFIxYqb~=Z5XPQ6917doJ`)AY(WRZY7o_OGxPr6| zrCF>H0)t-K=<{G*muruHoWCm}!8casrtBhpC2>Ej(e2xsH*WELoU$G&qD&mv{oQA` zJHof^YT;)xO1J#yH=`VopK`u_|9Dvvt9a<4wX0(6P~Av87+MF!^S$=sdZGb<{_h)F zWRFVaq5uLqOk=b`mcTjrgF-LNzKT|!n2hgXaqH0g3XTLM1<>VLO#5qtOa<4m?4~k$ z`DfXy`%$2E$Oah(9M~jn))6@fI6F<*37G>Jv^B~J*&Y&`4Hp)UE6YsD z!~y7q?p~ei1ap8A!DMgn6Tm<*ry-z*1q+OzQN&e;u=I9UCOf8$|G1`48JYIxs#2cz z^rj#c%EAs{P5~-5or*fXN@ReJ2tZJ(7LZ9z`$|$^vgFH)mAk_n0q<$K>{vH_tjUywtudX3$%B7 z8ur=5i%%wz!1l<+;u7C{-=3QG zr^&sinj5`uGP^R=cRG?ge=cdy-!8Yp9CPb0Y!Vh~s#D0-V+0>CZ5(j9!k$dQedMTR z<7=3Phs_KWi^iYwsEy{`y016<9MhRHa zwtfm&B7*=ohKK(|gEF{CLK166@153VNy3S4N~az@G&68!1p@8)DWVq^shYQG|4i_gf{eg*4SsyqVYI%81^*xev~EBpD% zY7&K1it{#`apYJD+EMPxsLNIIIj|8xZ1_T| ztP42fTqsAcApseVbJW6RQw3v*w%`XnMGQ3bON3QTo)pYKMUCDq=@TM1*Fpmgf`uaC zme-h=xM>JBCT8izE;s`v*>tE9%aWWkQkJZ|H-(Nf5df*Z?=Dt-T4(MG$13hBPPUSq z>s$}HDH{%-M4LUr&I-Pji3Q+a+m{r6Lr|KKa;q2_VwPaBX~f-4poYY+oxDIPB#wll z!6v_k)+JF00R0>sO;T~whoHofh#MD7zMq773~%wONMuFF+ymM;znc3UMV#B=-ugwL zM`*kgHuN}GPnF;y%3huFfyZ^%Z_-^hYhacO45A^pbpz3~74V$0J_IxjGNmy+ycP4f z?faxcb~K`%EIa@4sQWwrRF_MTGH%GlnQ|4G+>K=p>br$snpz6HYu$roI`P?Wn1@I< zW#(!{v18BP5jE0!3Sk66O7S2)AP8eBOQEyPc?s8O5nC{X-B+SE$`Yk$n7B3}dUS{E z7+&&ofh+F@RS3v8NCt2d_IiI7%yLM}KgVZDO5G0P5ASzmTBFQF$Z45-*V>68rgoMR z5gE`~73f2}i#ZpQBh=h|*(_N`W^hHpK7A|23)2lPQ$rbS&C#WZB#9-!(vrWBJ7$^|R zz@-;M7p4~`ssTjKopkdo-%^!Cs#oQm$jShw!E)we?S1~1| zuKjxhb955!!jppsVU~DFI2wf|C<*TixEtpmDjS2x2d6{OQIib7Er!qF!?o7`fJ>yg zk9OgUkS;W7GpSC{pxlJ{D6<5iy(Lq!YUc&Bn%}>>o&l-;>29t`5BEbM@2W#08_7?W z2BT7L`k%z?4}ObJUpxQuW>lMKks>(#`M=^X(x{mnZj#pUiZr`dm&F>&m*v{Qq5t;L zAiX*+{rAAJN9Upb-jhSj%uP`wH(qXBMphmXdGP9q*{+0k6l%~gam%e>OzV&YdUZT! zm)14|6@Y#pnU`USYyFC8+@`t)mHDb)U#MgUW6F`P#-3`6x}M9(sKjs-IC}JYczp8E zM4Cw$?VF)n#JR|c)8G{Q=zXc_i4RAzr}tDb ze1j1TJ{xf_JnOZHK{x*mGa+5r68F8})>7uT&%rYv>b8YlgE8)9c-qa!v*LKYm9G9g z6#*t|&8?q4m7t(<615Nd1Q|G>fY;t?CA*Ah9hd=qQ1p#j6K?`z+Uh5)`*YbDakbP#r3y8~0pnU>}0aOEJghk~bc>qG7 zrHB^dwzxAELY_IuCgyvw-P9R-QcQeo6TlYyH5YxV%Vt)4xPd7WHx-k@$jiB+x`I_m z^vHbShXCQSDJtxSj;2wLn!!kN;NlC+r9@Uiby>Ar6hAgMhwHfOkbk}){yQ&17fJQa z60=}TcvvjbVQG6Bu(9o34QV;sijOrYsROO-MMyZc^qLVNmHG7;CrZmD3Hp+aFC^tk$|3MyTjj{MiURc_*aXB~2i<6YUn#;jNyNRy6qYE}_BRnDri1wC zs$1IS>^km)nqqxSD-V&IV?V`HwEcRdr5JoFld(0rzq2fpY$8x9pVD$_Md0N1J2)>8 zJQIhSwbP!yO@ncW4$wa{*s@t0JOJ52GlC{D0vbBni)eQCKvwWf1RuFslWV{qQK^Bh zVJ9G&^?Gma3TWLd`_)YD08%M@UOBn?M+K4rxUWv&bJT z2|}-GZ~^&j;#r1=?kogzywr*D2$A;%kbjCyQ-zmYY2gLl38(XvyMRBcFo2`ZreG_n zb>+;F8L1&ua_nK{!}Gez*+ZQy&US_wDZvdG6$Vn6>gqEzCI+!~M#B|s+wAupjSpS| ztP+uU42i{_Y8zOiEQY*slmpLj@z|M1wzP3d5pUjf5=#tK9005L6A>yW&BJQe<{GFl2~7zYo9$fXo|Ce#us0m-es za=rV|qe0_VzAeJL3?fiH&Ac*2{K!CCwnYjeE7Dqnku;q>zmG~Nm>288AArk$y~%_~f#5}P zMMwh&+$cIy_D4H-+X)sPQ&oz40=M-PJ<@U?fwvs(ctvZj=0#-C_V|^s*}C}+UHS1p57CDQ4l8VKKdS<$|H_M9?M z0~E`?uOGve^XYZxp@c#m68naSKMVi(+(4+H+z~OnBv%mPX^At(+D4Pw@%?XsJlW|SMHz}$E# zuKl79=yhE%j=F`Y?VPKDbk#$fV@^Lv3#0J*!eSxAAM-S;2Sa3c-9%al3)lRQUR~r! zN@lsP5JG&O-N5MloP4hsw5gCDEQ)qF(5P*ZAG^^l?M|NL;MBzw;uG4>>R;bkOcCaX z!Vi5Iuz1szTkvhM!i<`uKlpW824V@~mef6w$W`VnsYc3oyANRZ>*jD3piIR&b%!Uh>8>*OY*jH z)C0hNUmGTpAv#AqolUoaUr?R`&CiIu8NuoH$8c$)$hJAPjB}0LqTORraoCK$@|YQ9 z77F)3A&DOI92MPsB~t?mfM0^8IA^y027ai<%5;sDMsvnYJ9#LrE*O~=%KOSM`gbAL zA?+#{Sqv~&4Kn_Z*DX4f?_k8W;q2Fzv(}WmJ%(_vt}|;(GCFjbyZRb2o1Xk0EBJls zyC2M9hJ9bd`T9Gi6l0o6Q&eNBNMo#DMP7=)2kK38u?aJproBWf${@q_X*h^4Fqs>| zVfLt_b)d4@b#0)$yblx$jdKu-_g=Lr?|lH*lvapBio4YG>g7Zs7oKd@Z}XdC@XC5A z;Xhz&`*@$#19QYC6GDkbKI-5L$T^hUbrhjEaTtEi4QQc6@u|m}_ zi4J>9fcqcNs5OY!&dIK0;!p3S#R)v!JaTCWd`w{^dUq@=ITZL$RV_?oY0SK3G?76< zc&vOTb4Vc3HDYSnuLLZ8(Mr&&x>ejLFVbk=4q2YIi24r&we!MEh?~kwC5D!t5ITgE z+U60_e(J>?(C;**iq9M@IkG3To!eUSq~N}kqSu%osO*z+4b-R0(uYi#t4MnRPz@mXgC zDr;Ira{%KofIiaN$?kLV0CX-iMH1~*Z zf4VfEa8D6lBPL}$N~0RyGHWJ&cdG#5(-Yoep!!sUUd`!kQyk5li4sx=#Zso&I8gzx zJdruPe&*6D+^-;$#{vL>>JW{OuT7bKHHywKp7=i@= zy%gwE!t#s#C4sQjt;d9RJlv)9D)%h4x^)b&&443P1kJZ1nYL$MXTe-mm`S{oca-uL~@!)PS?pr6lEOf>QQ5 zj;##wWHcC~be#n5-%z1GVsi=pvix^)Ts-_#pfv>3k82LJZ??Z6_3FFcD za~r&vL-I!gU~I_S_3eb|aMlS!sFRp3-e0Mh{aquly-z5ist+ntztG3VJ7ih_o z4UOi$AEO?UFNLs^Xt%>BR1FtkRF`RJ^WWc3ALuaDcw_mlyi!ytCEpU zh3O){?mvPydZgLJ$gfcI%^dE1&Bg*vmUoh44XZBq8Ml}b#Q$LQA!UP$c|&)ixV|NO z%|8KA*osTaseD^OGz?4l^70-1lib*jrLhr!+f!%nin}R7i@oP>D%m1P7tHM3i*{Vs z+1iOM5bm%2+|ND_KrRIUY&-Y3Ih;Z2hpqHKgZK7iOV_{pbUr(8kC;@_&;;S~{T|+N0l{TnK(Gv8PL(48^>`gCUmQ6* z#XvQw9;;l{#An!2VP!q6Z*W=goS)Xkncmt(fKfV26z|*L{GmtOgnoae!?N|HmCJXB zT_**~HTmRhG1>mHk&Y3;)x5nBy3SLd9B(X;6SH#5+8ee1U?cGTXJHevs6y!+4#7%{ zjvFp99lCv6fc^}S)>h!@P@%PMJ$Jt@D@1SBjHYguQy>T1GmujX)C=+G4YW_L3LDB* zq8`|j(m?ToDQ$%3GakPR_+9RvP=cC>@wb`i-A^mIul;DlQYy7|#ROAA8gZ6{-6tey zn7$}5BwKw$C{k0Q)k%1@!s#V3C9+-7H_w%uPw;Zw-Oa& zMdE_p?Esvh=X6_DJ=5S`EpwVo zjU0HPZx0Yh5kL538ymwY-a;K8ldP?OyC+#cSl$PVPC~iX@8|(yELbXDFWJ>|!tICI ze2gW?bTf=aU;j_~=)oEc_qXcD;>Q>>CY}L#0^$bjD3AU?^A*h83qp!Cm+amc(Uvo~ zz>k=XmrG;hwEso5TwQ|Q7o$+<^?HaM2O4t=7D$Y$6wYmIj-d7`lA3A$L=}GdNSQ3? z3bW%`Wgll3dZkW9pZ8XRVV^Ok0OPH@QJP@DND(_Q4)n)bYlNB1rh-nYwQ>wfm5=Zh z#JB+fEA9NHh1gfw3D!ZHPgw2GcV6J_YKp(%BaibaUEPcteZdz?rDjqLh z=(ePB_BZxeuztkP{0@E9=^ArOuqYiV+#vuoh7@CczZFhjxQxf_H}^`G-(hUWLYN1K z!{Jk0!X>l##w6durgYCVT_wwzoAcB=R@#TUDw9|Y;%ZOXscy@)q2A)#dZ;?35tG0U zMd>7&)&acmkFZta9x>))su8EUsU}n9C>WB8a6rPN$FDDcyMK58^r?0iEwi=u74~+AE@JLotfLDIFfwj+jD{qUtOSIkv8ob30x{CWvGKs z$JJ&BcklZL?%W>(uZJ!aC~tRAYQHZsOMAm4uAq1io`P^Zax#e3!}}(Iwni5@AZIBq zfYw;&*8Ardv1S;YVTc{afgoJ&bbJL_KnFq7-^_{@V`W2E#9!=!xxL%A@6d?f*s%Gktr^tM!KDp^)PTn}*1WTMc>LqGt|s*H+B zHYn?k;`jA_tr3BhPS>sDzKXv%wGDqt9hH7(y|35d*dsIlyTamZV+V_;2pz_Hv9)KK zeSG!>y+Zco4;K7N%roV7PgV`kHx2za;6r>I=RfeCYKZnbVy9-~;{fq|Hvf^H@AWmX zg5xT4gcQYi!u*;X^fTphcm%T8jZ9&q97hDmrsId-H^Z5X zZa6{#h8s9R@ffE`LZMy#HykGR_^Qa5FKvLct{$s>lC^x?-)Ld*d$I>z+SO0X9SICK z*lAdHCTjEi6THFm@o|>Xo81k!WWLSKiQ7es_Dj%rZ6CVLaJ_;{{b}e436&)5&vUu4 z)~jYfNC5F#6b9CW&sPChmYKmuem+pL0}*{|=isw1fU|05OYIr`yzJ-lbLr*EW_taG zoQ7VH;gHQW*d`bpbKt3uaXR7j83z_UFZ26Ko%-Rf`=nPwC1jZ7Rll9kKL<;?esWFBPj<<)+ygZ-k4`wRkYp*u^`u+c=99#b; zAQ%6yODS*?ye2{f1eEOjzs-96BxFPYF311Wa_gLmB|pmUAKkmF=F}Rh$U0nXbIESE zQ&+{}Bo+Tzat^|olews@@A`j(K=i?pbNR$~ca$kJbAhr3+=v(E?twP{IvUVVn5pZ^ zs;bn!80;l=ch~lOSl2EHux%_+FmI$+(Y^d&d|zK@>zRvJPnsp!G?!0Y+Li-irI)Ea z6p!EIy_G6ER4N<{-8x2ZQNipCW@c29=*{0O%`c?2 z=_Z~js_k%dRC2Q8)y&N^uNwjN-Wv37#c8#TVtndyDZiTL;C^dGDf1@JA|2~}Ao!fx z$)OxuDtDuZ0NF}x_J8!y$v?Up=LI=Z@mhK_dBd97P(cXi@4b74%{2^7cASX`0R-G0 zpi;H<-Ue3b>G~azwedZCZ+9oQ?#@piZ%1c$wl61d;fE~1&d^NwF~tD=VmbZUvwcl^ z7SMDp-31RTfypRs4Y7Z-|F~@=!rL*evh{34ZKGq_rc-uiYVsX&_J_6{xxwKw-AitF zv$L{cpuWBGIoKSvLKYeuzKH2tD7`b(`h4d;+kocQA6%WvSI;%^_1TA0^a;?XUL@4i zKqwGp(g8}nD?5t`W*C5UpT@Gx3i4ee>nA58SEE0=_zwYQRc0N)vTdomx!K(Udlo)^ zm8V*yk7><0Y-;T4m>oIi2i%nt#uQVth_HGZQ>7+m43iZ9opWpE64q)=fRT!^xiO95 z7;|6mIE4vx}!#qn6+uBeg#0r&>gHuz(JaHw?2hi z0aJs+s#&$mq~Vcn_QFnpMO&SRkB5_I#3+DPqXVQxHM&bzHx?KN1ajZWC4-(}AN0y7 znVCtmLz5N#e~Ld9uzfy(oxLlUri?oKqozrvY%{uYrPe?){x7af#92$r?geNut<{YA zpN&WF0`o3kn}9X0DN6)v=>rmAp=OXH*0HsvR4sY@rM`(%x#~zMs0$_Si=U9mW<^0mrr z7b1>P5GOhYwDy^yN>ob^s(Zk;Ta)uR&-^0{hj_?j`P6a6LHKfxEtf!v zt=K)yJwC*PMGX26BlXi(wS`Ou=^!j{|G-=0O2&)g-*ZjKscV^?>3Qp!%cPw2y|rOM zgwdTL8?UR1YFQ>7uNTmrm9WbvvYI%=jJL%_OP@E#)b3^{;; z{P6lPj)~|<6$$hEOS}2v3HCn)|I7hjJ5r1`i}mt!JETG13c>x|qx>tLot8(9Qrs5$|=X;=zZBQ>i6{odwrS8xa3u= zVhQlNKrG%12ovGkrLb3#@X>C<7-#_oXl_pg|SOFklZ=m=Lv^fDZYfI9#99k*B#VO*KDAcz9qG1oP zP(HV?oDd*S*+JBcsTk66IIzc!hN8&V`0hhWex%qa9*5-ior^AQl=WVSMYYX^*F507on>% z-g!lqp^53NYhEG{F%d;51c~S>XSiQTQIt&U0nB&l#4vb*0&5?D=LE{XPP1x7>~z=V zLsN(@&&B9*66{|nOorF*`GBbcJWpIE2uUt@5Z z;3bO8i0&jJ?6_vcuvWLJPx)O)|;gy`~?tN)ew}#LVgPBv?b(!yytC! zmO-x1!jWoA)Kxe$9 zwt|(ii8DyD9G_TKERT%+@0w#)K@(PGXiZW0bMC}{WG-;IJ79C2nSdXycNvc3HuRkY z{!SRvlB)lok;oOOBjoQ%986Xi?srMpW;|4Xn3v5oDJk#&OD#GJx-!Io`! zVRzm+=yTwd27m`(JmhE=w{a~PxDjh4ppWzFm5y;i@V^zmPNWQrU)S{>9g{ib+*4fhsms= z6$H2Yl{x`JoS_~LTXQX6G&y!ztxsNDb_2iJhA6M&Km=*xAUBL$4HUP``g|B8yIBUM zUIoJgN?RwWG6H((L7oJ9oFNjKa|G329-{TT5WvI1J!~Cb`|_hw4EGxL87+huFfklt zJOR9S1YqEghx&coa|`|yvtq;*AqSqX9fbj|=w@A^fH%=G6t+@8apPL6S+o4(Rc%wW zlxcLmMxm6&aFDYx@VB*WSH2~u!V+O3<@lmws@`=?BT@iaxE!sEp;8sT>(M+zRX-94 zxTkqiDJ)-;UI{+YKA7uHw(u+yUn27b+LO_SBp@0#`N=D7xJM4NY%_l=I9nlEr8=}s z_YDGGMd?&KrNM--{?+9U%5`K?!tEVucDzLUEKqosyib@~x?}ZdzR;{)zLBK-(X92G z3d9%6+cGDxc$%9k=JzU|(O-dLQCtMlbAMfK%!WBsi3eF1ts@NG9r>z_pfDireAM4C z9FR^)ku%?EIL!BI&zFUAv$QU}okNyQBh8sze~I8_#&wAl0Do2P zI1g1xK;fW1{(Igj1hzCeg?O!43z+#NFD-;E_V|`Ma$TBPPA}6~VXKBDYFL4f0x%&l z!c$!zL(m&U$HrAqbQUHw;#{FdDJG7?JRJS$Ua=H$phlSQOK6rQQGFVI;rV3DXvc&4 z164JEy1*UrvkMX2(lv?FmZEmlzpd!wiiJX*+(cYz@Q!_mhZX-kKy^K5nyPudBTeSD zMVe?!FlKKh&R^&=(E!>k&EiV93g8ZJgcp$zpQaW@puh`zo-~e|VzYR?aAd{gfc`+T zq74PAUF@27OvIW%O?MgM>kco2qMw0P=AV!5-M} z|2U>t`p_-IP_@R-Xx{sI$X~f{`>g~|hMqCWSfJeYRn#{4dujn%l)BP`6T*%;Xqjh{axG*!9#iL{aIa+LMCe% z0yMd3S4wALcFUQBiIWweRI6GnuTr~9@hQIf77F7=}Es*1eM_7-Bk>lRkk9~MIDso-5gpxZpj7Oduk2#8ye z2MBTrve!ieR$})-?%Ug9F@dmoK*YqRq}LE1Cmwh^_x4aaZ*{B>09>G5oxtFP+ba8K z9LWV>15>6{K-=lpngK3{T&7<{eVAq9#&pk?NAwav!;nIjBuFWEYNLEx(1DtXWCWV* zL6iw)-1@|FOiag0(3o-)h#iyTCkdKRi?G|keUZpTQ1RW!WrEkR8ZYA>MHIc&^9FgI38u;^y#>KfqRQ%UBcXq}1g>jTv-)fd|>< ztv(-F7@{WYKRZ9>X$~GPTE}LqKMgdpb=|)9qgVtqD0zQz+&})JfJ5%mbXs!ag2!6& zLhq|q9DRB0k=gyF`?_qJxC3L2tb;Hg8>+hBKY|D99AQNY09@{M`EmFF9&QAFrtn0n z8cf(Dy~CYaGvT(!II@BoA#f)tR+;?kaZmUE4h4fB_KB>4z~1`=lJ##(o7k#~HRO*;@)}*vy2nmnCso=BanZlL_iaMxKTx;a%1Pln zAE|pQT!#~VpxdYoO^-~?At}HfW9U~#|ws{*v z{as4DS10ZD0E&|cm4|*}m(ghcfO7P;670xpeB}~ zU_+GP^Kh>D*8%Anv(n5{-vL8hj8AaaPT*=1!GWLJsH=a�uUfkbR8^G*y#UGsw)1 z{?V&V1T=Jbx@y%vN-SFk-fTjKT~B}SQqCrw@&jj&9Qb^cs5l*CS6h&qSrhr0Dfebp z^uJ0#)!K<4Epb>>3}xSc!zASlAT`zb>il)%X7Z=?;ja8sZS?7X@}P!W?pk>xBIQ< z<{os@TR5*|3~W_Y5OoFD$zvWhZ|$y;Gp$-ipcaQmavV$vMJ$savKl!0RZOtvXp?a- z0H72GvRUol563b(eMrTXd$^=M-cc@_ZZTgFzWQr?p}#p6;C57=`&q-gYh&#nZ%_A! z3XEP)9_XjfO0JJC^r5P1oLt7KH+XfWJQQ{KKi?bcP|%)h>u`-Q)3#woz7p4gV`i>V z(cLkGN-&4LB)a#cHkVtK;VU08&EznN2^L59LZB@n>cKJOrSg)TV;qxw6VkIr;ZVfL%gP zh|J}Ke{{qNX_&TW&fy#V$%?LJz=pgY!vtQqN3N4h!Mg?ihb7UNlH^7LVvCKJ(zCP)dzZF7CbxTd#I%RfYT zQ?4wGF=3`RoRdtYQgQ|9dG!(R0?(AL(M~At;_poeXWPU`L(-suPW-%~a&4fqr`QkF zD8$LlZzRnDAh3zj7+|^wI7o^7!2n%h0{q3&5SJxF8{uZ=cGr7gBL`=BK&4T`{3Wv1 zjz!zzi1is54%R?0vfxC8W!O@;1?=}<|CyC(ZS?66U5)=V!`P}t$(#+zk2d{(alYe? zZeebkaa;#esqN0iDMcxUo&(Xwz)%aEU|e_ubrOggpXA>u#U|9}u&0k#P9Y(J_Mq(U z$>k8J!taD{{JKu}QDU-JfM!Rr68`kDYcYAQKJ}atS8KUt0&{M~8o@M899E_+CPB(( zN2v!hm83A~8U@Vlq})(mWg3GhxJRll)8_R1PO6zZae)M>i*Sm3mY_; zbh`4($M(uVdEL?Xt>X8SZNr#bE{(+=>(l+&-WZT>eT*}5p>eP|VuIsvY;e0*hH8>ar^&5gsijV}a>8CnO6kt)++1f}IqYhq$ra zglF*`U{5KgdB)bJGt#;e?+5aSniF=pvH{FXu{cxR9ZVhPc)STciver7k+iU`@4B-V zcM_22pZCEtkU;;GWRC1+L4U=BO8f`@TLXWb1yAf8+FfZMP$ch0v>PaSv>z$fk~fh` z9GnNP-I9)mzMKf!yE6!Xj)HR+t>Pxa`YJ)qt5MyG1Ggsrbr@M43(r4fDeB{evoSB# zxSnSUBa+9ov4qRz8#xi_RC}(o2GlJ5O3)ip3t%eV-`qfDV1C8WoG%hUq_m>`^Cpdy*KNhvzbMRvGg$SA7K1;gLaLPLCs zHGr8a+XaH$qZK!7`&GFiBAvz$H%gO~4<{lpKu)g!Xqpskmo?YMoVBN7Bvq_O&7GNIH7#eK!@k{F~(W@FL zC?GRb&zDX4(R9R~%_WUOqx@KucgH9}55gSxs)5<2+@Vkd?UKtYRH zA?A5{kO;~^_q*sGQp{$k?c9~@~*SNTb0dhkcpyAWcvO6mi;P^)3p9&k@hEOi@0uQ$&o?JzA=FvdEmROb`1QqO;SeFGFMI?7cj*UuI{q z25TE*kPl;ZiO3jpb~t{tOa&w${g&Dt|FC74Uq<2)9L@9f=jv^Hb8)xqPD~Z4YFii@ zZQMW*VruFw7J?qWNbp0QM3H^c9>!K0HG*XJc`xRj=Umu}@mI(7z1Mzy2mT(A`sm#r z@h8+5gBVay3i$UzP(B@riSO=4;I& zVjISA%C%35zbJIWUzL2k5YO5x)fzSt%xkE-Ht~AYye^jI2*Q5Ypk;YaIQ~t5 zZ&D{g=&Tj2uRed)g7BY?Hm^X^(HzXlrz<{N9lKd1DUeB5=N8YrwXR-Itc*M1aq_Ri zHSl#8osG&{Cl$Z^ImA`-J@BKZU#5B?8ZCGnPL{z}M^T715v*HI=&jwytFAMazeheg zD&sfA%SaW13Gb`jHsZm|s1(yFQwkzm(V@|*GVMx^p0>k=t%C;;eZcp^@7*q*z^K*? zMEZ?s>zEI+Q|MS4deAUagnB#!1KV6}OJIQX{J8p*eGnG<0DwC@b`yK=u@?Vqa7FQkxx`N`7pFcR*fzTz2b zkz;>mteR!cS?vi}sj0nQWKn9KjkcsrX{z34DdeDis4j^+#nQMtWVQ&rM?1nlHu(pLjK@59B7`G7>gPu7WlC(OHJNu8H3}T*SzH>>ly*HpFxq`}lVTH!%xldU z6LC9V`61sOvEgcFO$%QKB!WV+l)x>J2$O1q8Zus18bjHH& z9x60BY9JXee>tM<#Xqblp_H=5nrP0m5!33MqTE~6?CyZw9_(8 zdM=N+9X((ln*@hb zYb>k>4UCEp#erPhJHw4#oU_iSY83}*po7B`_y~&xXJx(PB=#yk3E{)#ONMifAh9Nc zfLOqCd!pFFEwBOFKL*-csa7(=U)_P9I@UPNQZU_8QjH|vMoJMA>mq<&!F@IEtT{ZR9|!!FEUylle@>@ZDpT5%c8-MU1O;+tUP zDQ^#C!z_27c5I}ZB(G=1n(^LS$k>7$2q1PcuLP{ACD}FZXf+0FcT)Yho_t3^R%-zV zB#;J~{TdfGxAJmD=%)n|8Q1B5!)MD6iohjTZE=uhqGf)=eT{APJ?cl%CF-|2Zp;T< z)O%>V5h76ZRD1))a#NOMM!JNtQG|mrS|RPpJwHXYmUS6Am(26u>!|CyfK;s77%rdIZFVWnKg&fVE+IC$tO21 zRt%S9ON>&6_<~GRS6cEE7g7(LURwYMXbhz+8$D0_1Mg}xsK)v5 z!;}p{64jKV3jjTWx!xQ&{{_SRztXdGhq=4oe~TK#X$TF-K>(P~tM$f%LG^}A+&O6v zm%*uv#wy;*V{NPRbi?X1?)1@>l_tYNyI6DWraT?o$)3-wXo5lPK)QB=d{7(dv~ zWW)mS!cmbii<6fVidg?2;+Q_ygePN2FJRKWtmXwb2mnTjBVmge_ZQEaL+crA3ZQHi(QR$@!%VVKn6X`{UEJF3_{Q5>02R;E&^)IMtqwZgl&M znB(kwRV|ES-W8cD(vaSpxh$NWhLfaERwXB1mx|enK>)U>zRa;Cr(929m2CC-1dPeJeQ63xWHaf`(8P8mTvzPvpresdoJLbO_^dWJ_)>N{GXDxbXFP`3yS0DSVH0v zIeAf1jmsqHF9*7;PFB2I%m7XR*Ek4$p;hg2Tor+fn?kj@*@G45f^rd{ahAyMp_7S87C3j($01vmVKL_eE$AhSpsng43yAFm zH?0q=I8W@RU00F1KAXFs6iyqXJy4`9)XSZ85uqKrg~}bDWqozNxgBDFT34V6L0pg14&){1ULKO zN$DVkY%EeR@o5N0gVV-$6^oKbN8JcbL)n$|38=7EJf#N@P~YjN!#=5AywLU9em_U| zPr|rIG*=BKLsqYY?wXkrjdDw1nc$a3vpaz5weaG%V8UI%29MeTLUCd<+!wK2<<;Xl zwxwa|%;dI?MYd+NBw;u4Ttj!5iTWHu_EnGG(%w)!O%cTJ!Rvyyf>nY>yE ze$Oy&Mrap@r&M(YRAicZmc;+q_dqCU*Ce$#%WH$1w_JIe)|`4EnW0S_t?MENy(lYD zxHh1s?C97bxJYvVjabJbUob1?ohs-M>+UU)EH>Pf$vT3bKGhaP+hUC{Q1^N9brgtV zn=L#{Zg$FiFLsReH^>Q=r`J)PpWQT+A$ZZx)mi-E24-h}OZcH<;+o0X+!h{E=JS2U z2?B}*Uq>Hc@L?F*a(PX9BxT)L%*1Z6yM`e)d_|Rjka?&9{fHV1H$52xm_$O+vmZ`~ zB};Jm!X9qb0@FAiWtT>Zikw})O6I-Czm2_v8R|!!)W9i&WS5GC^h`psO>NcH^q;VG zh!XCOj-YgU$hi%0TubJk_=CH1;A}YxOg)W?D19P5rjWbYX}qIAN+P< zy&^{$zWxV(JB{FUcm63>D*AD9kfhwQA!Gg2kD|dhKeQkNz~KMi9{+K}5W!9k1f-wh z+led!kfUj5l%OS7BkBRl{YhN{-qY4W+JPiEd3mqz@p!FeK-%kn9+scC-@5T$Pki!@ zW0Zc#LV40Pdnci)s#mW@`6NfRt#V9HncTef@z1fX<@p0M^&&}(YMIJ7Nw=JV_Aje+ zC0C2CF%#u@)1q?v0x8iTl?uh-Gm0|$1b_@a>`B#|bz(B-@3d+~wrSWRTN-U61(*@z zLyKAwJ>a~?B-&(m1>z+SmEYTSFmHvU3p|nz_te#z=xbiT?pKrko!Kharn7BdogpOY z&>l-_xVDFd!&J{5|3X3bG-bP6CXIRsPBac*IHKXV$=3 z&L7Na$}?mMO_*&U1Z}dp*nT|>u7KSK8|)-ZscJjVIV|MP( zHLyertImoCt3swpyov80?`ExFrTrcTujmbBm=Rq*k>N4UZh?QTcj$0C0#(rGMvA%9T9=OfqI$r@;-m#y+-^tb-OqfsAIhvX`7)W zDvz(yG2TE@Yg_Ia?(1;wBwiq6(ivVLPnZl_VosB+&cGx*b~_f$%a)rETS2cPR8)0z zokcFq^tFhBAjC!&XkuMFEJ4Q_T%DcsD`1M?D}fNvI<(I&7~ZB*ssY=dhc~vn5%v4~ z{p=;XtE0QOr2&q+SqJwpU_n05-pn+2C|#YX4&6V~IE>yGp*!&w{%Fe>92}2f|C$Q_ z4ho*hh-VGCig{(R20q~zHP351NLpZy&ey}!%b|pE4@}Q+jzq39LTVAXk$(c){Oh?C zrYpbLsTASXn>C43383k9y58^Y{)UwMJkIEDyIR0&h^;19h{Pot&gDz+DN4#xP+f4afo8k`jk#m?N?4(xq7KeT4h~=zFmrt`XR4>ijuDHyhFZ#=W zK-0M_X*C&U1!e`OD?lsN+{@JOHoN$hRw~C`$Z!T}AtQS)7;tp;Ys|odZ`|+CxN-L2 zlfPAkdg7rvh_@`R%#gbh6}Z?R@MsK{M}rV3q~WBgR^_BY&HR`bQSci~$P0i3CsvNt z0SnRZfj>@z4mj2WY^*;6Kf)6%c$=muxa2L0rvFh63)cGm4u{sI&j?Zk4#9_Mt%1&! zOMZhq6-vd_7b4zIFZdQZYrNZpfV|in@$IPe3`TR`0?d&g6!1vdMavMiV2H(qkp6iK zvRZP$0hk8=?eMg8)ok*if9;}UipE5Y zgFLU`=|h{kzzW`*PHmXE^dXEd2rgRFsWQ${?j+FEHF3xM ztDyYX2UcYan3aRP47@+njRxL~VS_fUmtk+Y7G1BDjPud)T=f_YW7O`bs5A8DcF*sU zV-}UrT>!KAIy_uL*xI>XT!Cy*R{zXU0eC{l{uGzBb4Utq+Yzvr);wwquKJaAom&fZ z?`}+2V^bwxJP${J<6=A_x}Gu`vfOe|z<7rr^_oOVZ%1YR*fCRx9#)9)-KZkrOLJ9M z#6N|-AAJHB5Yb9{4^jjfsi+{TJe*r#KF9n_6JSi!cV~qCPdIoEBMncKVmB`1xC3KC z?zlx5vr{^fX0L)Wq&4xrtffK*s7vCDi5L7Bu`vD9lHhSF13;sR3|0-VVl$O&A{ zDr&EJBI*NQTHOy@8vd6qtJSaVw7E;8q+BjT|GK!^Dcxqnop+BEu}0Mu^39;P*YBE+ zaCeCAi=xdx2$YIef7Q;wxC;nkSrQqP9iT+BR`2#x!cgR25+|LtcroiA{6vTMw}7=% zcpifdVMKQ?S}moXL|sLoj}`d+UuDlkKDi*Db^oZ|wEsYH6!vkNY8ee{mW>-`x;N}T zunwn%Ameu&4c{qUMk9!Hrm#v^?E&;3*Z>u zp{ntuXi0S|R(5vjuGhoQidhz^JpASbp(UpJ(#}lTH*Ic z-nS5^CqUq&vgvgk)ata~h70TI_sI$V?xO5|{x&ouCP+nk&yCFQ%k-=9(oz(I9uRWy z{7zxGlt29brBv*bdG(n+m7bfD-hiVc4VG`QMO&TIFB=0V+I-EzmU)ws{^%h+koTxf z7X5~D`cLIJ|2SOoA_TTQZMhMjOB{ukc?&=Fs^lJVDBlL@Li%{iSTLYSYdM@;rc%5q z3mmLx2yg5%_LphI6DLxb-#oo1^aVo>4st?{XiCW}<;JWJ_H1~;E4~7`et<6RzAnE_ zg_kXUSHSBc>`YZ)@ZgNLo%%)hNqcrZpB`1GH3ExR8-AlDg$bRS4*#TX==Wr}Tb2#|_bK`Y3S3)dSR zaJeiKhX?tSsjn>ATB$F|P84IgqX<@^JJZaX941=gh`$y+q?M#~1v7^jDw zkKqwIpF~Qgn#uWk%uvRLpdu4MAg_m7@LuJ58C7cW+;)jKWLgXF;l`|)bv;eAOTgUZ z6^0km(g#!n!=@%o0hHghPw7w=Qj$S-K1ZB*-L}~ZGz=^{Ih~EvFcG1U!8vDoD3~fF zEa+z~7^GdM_n%04jVtYxR0}XBa4-Fw-|T~;{b+WSi@Blqlp%)9pw0T?C*xtN{@sN~ zGtq9l@6;LYuJm;e&-&TAAL<*@r-ZD66Qt7%QucQj`LZ4R zMR5H_sD+s&@`IiP8Q9a08+z=Za{okG#Onz={?c#kU*lnnhOuD$xyMs1K9FK5zs%sq z1!Cc3o&S|)O{?q-oW96K#5H(9!#?GoNjh>S``x*BAt4ng%`*6nl>`?O z0wQyG^B2U#6(I9o{9yj9rjgp2j=dApmwZ8FH5{T4sZ~P_uOw(`ir@i>C}xqT5KY`k z5{Zw}QJSg^vg@Xb%|Nxz;m9Km&DXlBz-5!If8rBEDdO?HKXYSR;U z;ecAPR{2NOUd_>1tYH5a=ZL-V&a0o05*P;W=aDZ$JOB-;s~_n)D7_kH!`6Dvkg&fe z*Va(K5QLFkfXRsaIt?go$5)VC@Gw5i42nv?FGCfUZmYfym|O~)A2+*dSs0<=H_b{rz2Pk6tTw+Uk{V%R78&?B_^+Y#EFMn=8M>Ei z4M6y~>@M5hhqz%Va;Z8ef;-_ya1&I!*+3W1*|fxzAM`L;Hr~inwk+|QXilt-InVQl zTG_ztTAW!Br|)IUmMHT0?jNtdiTv*NukY{SPH~m1g|?U5X7tL1y`_en9v z^OXa3;Me9`r=JNLHut7xoGT=biH-5 zcb1@|P1QZ6Q!fYI@4M2GfU{`g#FaH8UzC3X)TUViWb089t=lON=^2w#iYhx%iC`2K z&HR)ysbVf-0jfW7H%PKZ&E^$hN5d#1wZ7Y9P|lRC3Nl{r-;wyj({`L-mHf}Q50L19 ze$6PIW@G{T`x>EH)x}fg=pi4?GhBc+o&$odbV2tOoxbe$ zuwRf`SHumAy!rtzdi_Ytq*Oldk^z1v(OtPtn|BDT{}z(MyA1x2zXn>SLwJ0Ws^?%f zhydN9R;mIl%UHQiz)0X|Vh1i)22h7_L{EX$3$FiHYq@vxFEd4$;n}6%EAb5fF9Wvh zB0cA5exfq|P_W=z^G`EzDai*jloI^rjhU-nXp_g8|kTV0uqY? zC_O19jWyuH^X}-H0?ut4HHy_$E5LkM1<`ykU4`{UYgoyUs14E%@35+#@ zlDEd)2-C0y?*sxOe3+?QNJ@|h5z}XW3N&?SW*yOPYesc7CAcSn;oBn6{JB17HiD)u zrRwBsqZdS|Z$-zGsc2i(Io-hah2L55p|R|?0yyidzV_>NmFznV-GHwM+?k98WXFq@ zr)!cIN3Yv0xe7)=>7V!ssX6`U=-K&|>C6F&9+>2a87vBu>z_w6BV z&~?=4jqS$wIdWcy@xG*EA1`?2nmWa=Mib88CW&`3Oi#LE)ZwtZ|E{nIgZ<1HHws#h zV#^pQ-q`;NM%CS@paX{OOGJJC=67c)-jiF&*m2MRuZnR!-q9CHtDoe{GN3`>L4adi zH}fm7+;d%Wo^NVj4eaXaK`r)6X!b5kON|Ds?vi=(JhX7n?1?oAtY zHlS~Hz6U8bZ6~0fb;ptIRmv0ajuslvCm-ihYby|L-AAIE!2sCrqXDI6O=V6A>?7zz zZu>cTK`OG8+Ef7dG1Jc5UNU>G&!WL>h7wlaZluFW*BHa>0m}>u{{bV?YG`aQT!m$yEQ;f8Puav%%Z$=b{MwT@tUAj5d{q_Pp-%u!zcj z6$DbdI(U+ZZtmP8cj9_;{5aTW#GSz^X~WTnur=eu)e|E2xTbwM!0n*8z>fa0I-GsL zy^z}8A)zvbe_AWincD?`pm%h6yx4DXH=a6A1@!397z3`Ph|pXC+%OW6s8-TAX^Zkz zAusSY99Y#9NsC{Z{E%W|o<{@w{uZF)UCyddNc8K&(3P;LWokGoCyS(5<=-`N5aTp2rz1-KI zp!_d)8N@zbPXvLG6jw>8V>uLN<0NfrA{o9+MPMt-Y&Vm7wwUIK6969XXZQ}_QWH)O zJ11TiAC^s^eGxssg^Q9dCo*&1q<0)UjcuydpaMvy5(f|(Tn4XKR@?jb}eYrQJ7>`6SxmR3NHlWKQh^Sms5VACNe{bLgLZ}7l5~E z=`svquFr27{2-F=?p>)1DRF!2zPUjA+2hHMrIyRspSEL_8Q|)4=W;xnQ2kX?f1Or= zge3s^`Nv(HShw6?U1BWZ5B4AQ;s~|AtH3v^s{pY$^TUlrb6zxP;%f6YsNsUD@j5@@9;sWQ%x>fuWv`e1`vf{fEAoK7>|ryi6Yq%saU z^VNIu_Hm#FcsW`HFX#=~>F(p>m5r@%Q`MPxS~#Y2ghC)hkI}d7;wtfePXMTpK|RaQf2m2 z;ll`B(uWkQVgZH6N|xPwl5wJq9{%jXvZO_@#ukA`0AY)n0TN}E&&eoYM6;13O}ZCV_R2i z=Q}G9GV{thzuU`6#qjs_D4~o0O%ABx9B#8^Kvws!crmF=WA3(0Q6uH;yk(bQEs~f> z-SE9MWZ8-`6GhO3{f{ICVPLcN632&yE!TC3yN(TD<4K49q=?jQW+ z+8GWyC6Ofyi}VXtx}H4L+)vWy>nqfV(Ya>-I>pLD<Re5+LvZ6J8-FMDWskki`J34&|l9$vIy?iJK8NhzmXT+Q6}3OURNMGoUc2^!QHzoeqrFz~Q| z>QphNMF^!xN2WA_0V|GNNiaY$7jhr%8$v?_xV8ELV_3R02OcP-dEOyy-wB#7Aa7Fm zl&%-299=R)2*VQ&_uAGk>{2oq6MClTnsOZ3EQ7HR{mp>JDAonZ=k`&lB%c zKp&=ogQ|%LNWbpy%LpD|#4oFMM7!~l`wNGS7_q=- zd_#`ykU2pHM??f^XF0(A1e{VQQA;NPZhCWFb5Mn)Zv67nTJN)akSyK^#MIoasig&uH5IJT|&C#O6F(n9=}$917g7COUCJxRPvKK1ndVq`z* zUuO~YMakh~f&A~3%%>f7;h4$FMP z7+oM>!D%&HsJ`R=5C+(VEh0@X+-W3Z2T!t0hJu$mIB^HE@=-xgMJogOBwHnQZyrI|5$k)23TZ=Aqm7b}) zF|tKH0(|uOv~7SH@b}>pMu{Yaom^*p4d`FV!ZNCtT=ZB~0 z?Czhh=oVw`d=0Tz_E4U^$+0m}X&mMf(L$xe{LV&)lQ&=yfg3sMB{4v*VZo!3fY5zC zxAAGnr*d8=kgxwsmnFtSe&2;$HH12g6y5VBzZ992j@sx$Rqsj+^=d+k27PPX1EfjUoQGs<&(H$o-xFpb1UimCK`c5q zJ}mjeVH*H9XToB4P%olZi4!~hQBDQ(hSZ_BHk@X42sE^{9*0CFHc0~B=>=;uN47(lBTiNnX1&_T!s1g#%3Ax4%q%Q zqZe0KdjiJ8V5AvE`c^)!$Y(GXMxE=I2M!_TJJ~EUvao;cq^|%VhLQwE7~Dk` zH~yA0;u_8Jh?^y1h|u0OiLMET1&sYexHyfhAX$+~0(W(s(D3-OtG|6UEa&c0<#!TZ z$khRBP!B4;j#cRM*0RVEh0nh8eI|uhesekxPu#ym7ERhm3nAM7sf@;Tq9;4OuAyo4 zFsg+w!|up{lSE#3NF8Dx0M|92VQxyn@BlHzaj*i#-XIJrczQm_*3qonhdb;H#RDZg zEv##Z=@{FdOn%>i>%vmrku5y>+T>elLu2tUGo z8QM5jZ_w>$+QSs@vE8?&qnJw85l#Y~VzuT+QrhVEHc^@3Hv3$vS0h$oD&%{fVJrY{ z=qz!UG6-EGw}OTKMcD*BhUt7_j0FDMe@-K&_~gmq#t0BFUnR&Yyg#VF$dMdJsxu)D zBky$a`3p45PC2hwqURoJP{dRiWZhfhbS!VdHdVAi!Y1b4Hc$@#lom}IaN{#E8x7KL zOo6@@&a_r#yin_Lb#z{e0=DEY%YF}t>$v1ZzaIssR@yy#=HL3~c*~`!GRDL#K6`zu3=!?K5sZIT?e!vIcvq+@_I+Kp|YHvTezanDQST1w- zBi-80y4kC~#@)C$hl-*vJ||5J>U69*Y3N;aYAOMyW0*cCxLWNkFEdP;W90*o^Tw!{ zqZ_#ABgy644VAS2l>ax>8~V2dID7uRqdb?cD>e!PQc-#i1=`+^XRi%m7~5o!`s1Bf z_!X=?;IksMHXya^=6yzpY&KR1>HRqCS#x53^gUO3hb?1q%qcg9`y4kDPV6~tO6B5; zKzAZ3~?>8yR& z0^=>-yeLU!>niHJA1idk9W~V>0ajM=X&QCOQop-`pA8?;Vl?+RiJ)ALiBcD(A(0AcS7NS1(jnr;JcLO$0>vs1Ty>rvl1>FF(6~Zw6hK16d z_YixK_Sc6F!3pzQWxYMFQfmg`LzWIOdB}r&=X+D6k2__@9yT}C1wHEgsfF}rTV&!~ zn6X#4CC)uN`uR*pX4JLOd<~#3e&1saoh8$ujQzTszbvZoBxwxqSwLzxGe?e87Httm zo6h{wR^^lRx92*yJ8A$3l4qF^A9G!4vghrMRa=#eoxlMHy6cT5Fmx%m0(1KLa>Y(y z!MHl;|0>Xe2&H4yD=fOuO`yPS4K}VW-4&@T|Fs7#>1QE>WN|Xus=^uqL8d;7$Nn(z zJ`Xb<4>QySMng~grQu7V!%aY2DgZwB_aVHMQ^ja4VE?~axr=}S!qJN%i+Vh&o($e1 z-&ut)^b$1p)F?gy*3|{ZXN-jWvfl#=8%Zly>s9F;!90E**-Hif6K_wK&!kI9g&r$P z^sffCS6j-3=_Gt>=dSLWORT9K4L^F4QmgLIA6=(wKR)r z$U7g%hbFF((vN(P!0ha4-%O3z=Ed{%ba81$G>pk3N_-Qnw9SB%7Nr=J)SAwlnLPmK+)TP28+z{s3?~3D; z0r^UPp1I9r-AQ-q!WI4s2GEV#%AeCg`ZvDKQxedOm1pKI(SQA-rRvFPMOMs{n zGXcVV#o#AKrC`uFMf5>23C(QW8#bWC5NwX2P0j8t)LYHLOb>6O*sqm6jl7;_A|UkU z7%EnElvrqyOfO|VMh|=0L7RdFMJ-Z^?$@H@-*Q0Yoq301bmEE6cA97fj4(elR4hay zE+~?j*Ctqk>oI(Cq_9;I7g>@d8<}-MIH9_nd4!G;tGqEg!IVkKQAw)TH~XxInJz;= zOjxD`^vy};nm#9we*JKBnOc|z3^?GxYYsgWWq9)ua_A+$0pd&H!Q zUJpR}6{lyw^=55z>CC=J+6Mmq6H@`gIbln=wwM3V47A0&jrov5f-C1m^kHqrnmU@7 zc=6n`k_x%5GWpj9baL=-Nid0wbDmxq!`9@Yo3|JIRcX!Lh~<#!?Z9n(K7hL$9s%Lk z=?#Cs?YE1^$<}_l$M+92d4Tuzx5G1~69Bkr|9%_321@9fqAVHC;?`Setl?tjmtW~= ztIr;gbY5jE_NM%Yc|F+-C!xeY6KY3A2y2+a&>%RF6vg@{Up~Ola|!r2*1S3MHY4j zPKtyON&tnZ&+gjIJG#o8+3Z#*CbuPbedYw)uN>HnzxL(56esg@SBy-*nM+U*o#Q+w z3WUPc2b8X)EXYzxu4L{u%Kl;wYJG|-9I0gL?E<+rlQI)0&DoakHQB?~!~tG!{Zz6x zio26CX8&cZ152=$j!!rHaN8#Y6cSwVrEXG%BpMK;>C&8|V|R9&o*-tM7PH<*S{x5+ zRcEc&H75WljqjhFo0)wnN97qJH$JRHF@Enl5Ao-TAwYR)@6W=1bpJ@~{?lO>7YQoM z^TSu=!vFyhro;)MU;=b?&27w`baj7RQb{W6wi~~Ze3q-Rtn?&sE5Qpd6M#XT=ldZH z43TYT#QkWZT-5&-_Vwc)F1t#ES9EUV`Y`e=voDwAnbxZxH6VF?vS{^NRK&3@2RA}B z#-mt{Ck5(I_Z~u|S_$kovXCXNMhexdR3Ma>J1?16{@T&5ZUBHc{g&d0P)@8@=rq(& zti;|QqYn8K=N|!ga_rNn;j^)xVx)WVIGqBAs&+U_V?mQqA_I-vy}05@$bzFmU!yv7 zg>O`aQ^`e1d!5##T;a6LI4%azH5(>d&y^$Y3LGxg=uxb&?bkW$WKBXPW=+qA=|Q{Z ze&ab4!!&Ir>IPIJl#Fpb`7b6v1+3w1S@D22i2w^`X@XxU-$I!Dv8c96N|?0jK47-?hKr^~oip=v5ZV}i zp{@9JbfIFtH%oWmS~ttl6AzF?2QCq(|pptlmdjgWdF_FVVip}*xBzNJJ&In z%Z3wt&ign`xf3REfI@bPGkN8lz8f@h@3P`jd)0BSc@Yk5SS^GFmFsJXBC9Jdi!1^^ zADcD@Y3sQ(vS`t_^i#(1oa>f6IEWpIKM?jI-(&(vN)s-$^v3V;2a!aS$5$5YPD@+p zZJ5~CtO5+=^s()sr*LS&y7F6OQ@g)!*HgNW*oj-a8FmB2XCYn8U(VbH%@ck zwY5Zna6DAHk!lTiYxxas09GU%#s4U#3*6Dgb&3SvDHQ_M&zG4YWYRy%^@^XCjcj&) zT}@KLDuxWndpjol$b8ud?(}6GjfxXa^-|WNp#S%kDI@@ZqwF0tAkA ziw*^h62Rv5Wxeg@!Q1mxrI$_|os3%+8v*kh2!P=}=+rQLTsSMV(x#xtSULB!%j^0) zTw2B_wIBY+go8Kk5cf5CVf67~<`77kbi}C_B%3F%SQ*Jb=dI8Y4Ywkh%skSBg zCH-Qm%roO$#AQ#N`Y3KwUZCJ}RUK*4A=WPZwlyTaNZUiTLfk?0)DTV>eQe-uYibld zeE)ImblR9Pl4h1I#@&p-K*!t&? zLHWAU6lY7!1z8OWIH(rk$j4p*D_mC6zU?hApm_xU1?Rrg<$G`o2hioLkYfrH7U%w(nVp^fy}f*>VgjP$@TEc3g+be|6QQ*QyE1&M z-_D)3RSW->%YbJ2t5~}K;K-!^S?Y`0#s-U8y0Dcf_%PZa^!f!D0G$l`?;+pCfF5VW z9J6vDkG77uexU86V~=f{@!9!$EayeXCLNw8eG=v_$s2lfF;389A zt^@*EFX8F3Z7mAVbSTEC6Wjh<<`+d1Blv*Ra39M^ho-yZzGGxmifIjaa*18-2+9!s ztw7$%L`#C*Zq-b5?tPg1iI-~{&C6=cPnFh}@$O(Z%hX`R@x4H2M9#R7+wPx*(K&^H zW>1*ycQ}FlZ-6`V&O*p=(C1JJejc{`F~>tLOGr*%(=vE6QGn|i5fx9~G}0<;U}ldW z2__P?lGuTw|J;Gen+6&-xSu;&^=?NUUOpLqLDqt6CzZY;BSJS;d6JSbdIBr(rSAz0 z*s_{5EeIEw?%#E_yGCV0>*EPAS%w5yo{aIHjm$SnbAW%K)-Q6^*IwpYj8*BPQJrMM z3pD+8Dm9J`2QyeV>fd!Z>e)sp{bxo*TkUM?3eltC65Po4dqU91B6V@iuIZb%RYZiY zV{j{Jm3?cKeKIOcTNhIoQX6CWL|gQH9$9@@Y60rVh)!v>%e$@6ld?HQOyh=6!nAQ( zO!19fZh&z|a+6N;n&+1r`#`4=bj~8G#>bx56;MGE7!`k~6qJA3+-Gd;xEQ#$hTAT(TjNX(Ae9=$22ta0LbcQ_!ZmADO(%SPTm72Q6LB@WE zu^5YIN^?a#GQuj3=x6}`O|lJw*rpa2glgzzMSut-1PK^?uWH+TlV8PP3OYICP;%JW zor?7w>tKTJDh^82S^5En`^t6f)hoc{abLsas!;u`)3v0*Qprugx1km*#C2rH;hTg> z0Me~>jn(ps<8%hJ1I*9dI@@n^Mrnmqhp%cV;W=X>R)R5Lnu=Mh%0tdEOVFBy`7tfo%NA6V}*dF^u-&9)lZ!1-Q!^PHTy67*QK8($5p3Mmk2w` z!7I?NEU60V`lIoKU`arqNY%mr&{gmL0}SEFo#~>NIXdnu8=L(@koT~ad;2%kJcg6t za@3|A5;hG#P3chTPO$T}4h)X^ZhGQ*6`cZ~BZh4DQP`2^}Q`SVab!4j?$c z!5UY>QPokQnS3ktA+$act8O-TEUE^`%~<`gXilzYxmvfG5>DOHj>l9OWsWtP52mw) zcHEP?R9_?Ia4>v%7Ifg|j^r{_^deVo#xGS9MMga(;l&txUo`eoZtrUpcsb7%+ zqNd5daja=7VTfhsYc|NVxV4h6i$bJJ&3okDLAkcWCMm3DYBZgfhcMWbApi>F4(CF; zH~Rw^PZ0g-Z1D9Fvq!MQyKW;|h_`1Ph=>Gc>0#r)c zkLKI$EK;b)fb>i=Zm=G^9ngXm^lhj$aYUTab06e3(S z2Z0rsjbiqpCv}80!1+=^(Z_9%)F0O(=RKy{PJr+Qmz z(pSB|@EF3VUUfm}{6ViKWKAwRCh_1*k=Egt8-bu0>i&H`z3;g~1UIV#wDZ%2k>1wt za$P(pZGbUgFh#k~@_mpX=ee+j&MN8#QWjbM4eF6ep16t8`3d@@iFp2*{7jd|VzU(C zekikOCD$^VjEigm0R;5QKK5p!F(a-g!Nbu#EjX>%qp+!hrP5`a>%rzs52Gj)kj|-K zXr?pFk>onXJsWMlbbP*e*I@@g1mJUv*iN#P=S~e8{dT>owAo)Xt>j7?#EbA5S2(qD z^q@)~?!(=X$I6$KcF&Tfc#ON6pNKizM0_!47qUQH((xr_1#q&~MxRbJCa{2>A*U3{ zv#Olsw%;b7i!8I!9dNQ8L;j&>jj%=)&MCl3tkGWB9|!InOtl@K^BXrWrx6NOuuUrk zkBF-_dWOTLmGuc>)j7P_Dj-%%*J6R@nbNaYXm#vb-Cjq1PkgiXOo$>DbULWTHF69$OTLBK>gpCBQ39+$INI@9EJ8RW86 zz)*N6k!cf)-@L+4cE4n$yjGR+wmav0_~>EPTqwm;YdDK>tECj2=YbbyS>OovLT)q! zK3LpP#JNG7F?2}OCDbCaHKZt!uWELmKEQ3&PSM})jAf;5{joL+E>6-b03MR)A#rB< zlr)3f1mN{p>N4+%@VCoWgge{%gffs&f$IOdyFwB9! zsvtn*euloEh7|u(GKsjJG&<0^B7BP{LyC|V)w~*P3jGXC!2vcjdcw zZ+*{;O}&n=`pw%~bpcdEJhK*Xljs$iZej9A1MrXRtv7(_C~HZXUNsoy>g+uK2Ui2} z5eS#Kw(~DGC);#+(&e>3ACOb|+Hr12)=o!!RlCrMu&^k!b>{Of-ZQmu8OyG1v7OSh z2v0n8u;DJVpFebk{PZIz$T4 z1UL$=DYY(#2DWF&1{g`?P|C3UTU{RLYajQe3oe$suS3$m=Z4j#0L6`7GZ0?9o-29j zRpH2Rp{KoYh64|Z;&wcg?rx@<>tKSHg@_ngh~1O5tK^NDg#dhpHcx2zS^Qa9u@=l= zN3=cz-%3~vDsC{Uq%`QuTz-o{`$F;N1}H~T3{%J?&_7gLv^gG!hibmNI!f33;TSJ5 z73`?DHK3KWGWjZgs7w@xAQf8yIX9Y*Zou3}|5W$VrC`9nsc;)6<@uy}8CnGPR{sk) zV8tliNnpR;UbPJ2CH~_Oirv_5&8uV3nOw%2vIzYy@*IjURW;c6WmbN~jXUy54rof4 zHZ&q{Od0Tet4(N9CH?A><7)eDftgIxsFmVw;zb)FW;EU*y=rg7^UCl8k$DSsw;}ie zg-O&N7)gtz7(Nh7NbvUyC{{F*NZ|3)_K6fb{wSXdkJ)#5>sKoZ#I|T9U*Jp3` z{Ycs7Q;bP~PFiv}^zmjng6ib!0CZ~2(4oD*{BlqGm~55CNaHjO6ppN#{OuzBU?1h< zOPnS4EDZ-keAeDnXQf0#SJ(3HjO4+l1Jr97-CZb0fxQMn^g^!jLDUgL3+xEdjA=21 zV<$TsNp$>IcGO_* zA6&)VYB>-lTGUJreDPzbXH4Rfe`(ECrIcdL^^l?MV?}SUq5nG=5zT|2a3TW%A^uLW zWkSUP7~0y{7#lj7+uHo>VJ0=L9oK(Gq<^}85hbMMMcBuOb4t9^S(fA0#s4mcq*$_8 zh5wR~)fPhq6Oo>CeO@>JMBaQ0@9y#(7o99nz+5mR2J0CFl8aVq7`2v^weJ{>PK%L@ z2lIo_)U|KrJ7b(2QItER*f%;%4H~8Hlibk(b3BsB+qV`CB4=l-@<+zhQW%mh!jmjs zkJu>a&Wlac$^m)JQDb;mlA=sh`7iVu_U55u4_)`8D|irMT!AB;J= zIpI9V_DSJ*t-&_)rhhXwhdYQ2E_@I7v{{Xh|HKePi7B^c7_67ApqUS$Hpy17wYRnc zUY2JYVJ}%$SR8UTAWUOS9%5|7r9`=9D5p3ZSYW znE-wUOzYQ{16nB*HFlM%zoWl^0i5H20{E0%b%f;Jx$r@SDGV)3e@dwl7wSlQE;=#% z6oDult1yB;RcX!;9)zi>8qPLctWSpu!_r-sGk4bNjiVZbHfMv^H@jpN@?*tdj}Zv!k>dBFY^I%R(xpze!`(&+7l`sI<()HG#4uv`Mj$?8_A%)U8agb4iVSo{)}`>h?~4?@%sWIiE1gLD({X$s%0Odl0K}Sb#p2~x7WM zQzY5*0A0d~BiQMtE_3&&aCMrg`xQ9C72Y0PteMeOI-VNh`vOF!cv}`4^Vau(3DIe$gE+6g@{d%GW%=aP%o}Z1Uj@U7OLuEGGb?wGV-?){xRdfV@@Ap9fNq zqfVdSL8m5xR`g(O6d%?2G9n7){{U@3lE3_hERxxzt93;?Z#r!m;(zaxG{e4PZ=6y1 z^YpUZTwR1WSEoPD=00nh!XIa|>ywKYzW~TSn)uG(x2*(Mr4kQ-Y8&N*!%FAenG9R( zNO&{`+|Qc=_h~A@{qbNG_^`rn-rn9$f(9l=mO+H%a*mnnLEb3Op@lh^vNO%Nzr?^@ zlL|~{U})z5;`;jK)qngdgtciDV3`BXA7pa`>S*_veHO7sVsLDrrBcOWmXU$0$Niy< z4`T|LP22_)Y7(gob-x4zIFB;P8?8b9kmhL>hG5*;(q~^r8}CE2tX#6s1mD1At*AKa_|A4%h@u50oHqKYxO}Ko_C}pzC}X+mxql zPDn+$icz(83kj|%p$x=98d#b>03S9LGXw)*>~CA98PgNDv%ZZQoDZN5>OO21)?7Mn zG5Emps6qb$p$k~?U9+NS2GreJK;uvG_dTyL&;W0<7UZx>PQeidB;Y+$L_u&b6~#P| zDCG&+Qe$E&n13aAd;as;r3Gs*a<<|*FQd%Il*P70KvRc>}6cj6roJTliFR}p*KV-fYp#Z z!2D57uz!aI1P~OM;FhIXSTsQ{XpJF`luB$x*`Ax11{^#Kt&GwiYE{n+J+iDYHjp%j zhHw;DV3*{lEkKUqQb?(z3zbH%h$PUF9OT6P4O)Iz164T*26t%5tGdh;VuVR9DO(Im zL{>nSz+m5hs9Dl>?(cpd_d?D0fWVCc0Ta&M;(xGPX0XJv%hw!J$lB}=5Si3qIXsB&G2P7vFp|xhrH+h0u@@HvMF*CPghTFt&j?r)$f7t6si|7QDV81j zbbp5Brqm_8+hV@^r{j71Zm|{G9{Hy0Bi~{fsy})(K;3pn`>8uF&7y9%x74xJu}*tUzjJhjAL4u#>f?ijqSH%iDeBQx9u*HI||cpl5?&RRiCQ7TKNK0h?c) zT}|0}de2lRU42Xhm+15pULdrJ+~NY0GV!k?f@b4QIxK#Q%DY~84SGhmUhbP-0|zmlVYp-Bh299@zYTf*9Lgz>u0A&$|iR-v4axa_lqNOs2< zd;4rnbvH?Gd;Gvj25umSxC?#0&^hd819R7`8sf^Op%0UeA4GmCzR*HJ1{;e+C2*>M z79m1%w#Z;%2Bpw~f^OV$p=UmTk$*IgYE5uXj6*5|XlZHiE-k`{iYj3v#xWbKrbE*- z#(Y{6bjNC+F{WH9mfOIM`C5ZBvd&tG_ zQtRjqe*Xf#Ck2nieF zRxSI+DrUP$yH@`v)TE>-N?FG?&iURzg+>JnNKK>s9p8mZaOV0oR)5Dm=DlwTsz9TA zoA^W*pu+DjuD(0D2+wBcC$BE%;rzuopW-pX3&`s@J9zTXXZ;XFR3a7`c|x+&zc{wRUz3bj`URvPK>7YE44-BW1i$S* zJ03VP^(a#6+gfwjdfYpH9U9WLIvw_Qj#XXhuU#Dkh8xI+?6?hm({6$xohoJGMhm9XR-?O^Y0Uzp2>cc2Xr7_y1;ck(!Nv#d_ zW|0i0Qe#AmH`Ep;X=yhPpfWc1kJNjZEg>I9iW=5F7ouBx(*v~3`}%8%I?&sfb1%Pk z{vS#f=9nJox__}g$fjz}0x>AdXeDD{tdFSs2V!_cI$ZrYz{-5PUOK{a3i5c@q$+m= zXEh!i;1E;UXDjgL7PT6SlSmH_zoSKju77KlvUqz8g;m3}nzn$7M{*V^>Wt)xXii3V zs*y(>S|eqx46kxs?6eGaclU3< zu_Hzc8_gr;w?YO*RILMkU%)GxqG!HO1}SKevEM#S2fIu@>VFULhJt4^ty=5LH<0-&|)HDzykpM<}9@g?i%Mz@yGqT4QP$m=G|3`(VC3yup zF4Lqv8*2|*usosa|2ht%GZDZdx~Sla-Br3hO?yXm1InIxH~YHNb$`M<5Tp*c`<8(W zF}@DPa@oCC6woasZ^Hg%UwE=bvj)3Tm>Z%2K7V-qsBNrn+);>+bAj}Yp#+|GG=CiZ zISG_^GDlhqSj`<9_eo_uqN*pNxV=Nv2syu5F0})~G4&c53@PNIB@Wn(f zHC=3Q_%;?(3M>W?uvq6;;D5>*cqJizSHSYO3Yifc3eHQ4ju&Yj zm7pisamVwr9!kABzdiihMWoY05 zXJcR8qM7WWF&LC+45oqI^NrVQ41vtCDu3|Cdr#7;RneIXLS93Tt`Q@cpgZZ1Lo}IR z+~`x&ov*!Klv6QYQC#5VhMWiNMo@5#6T~BM41)KNyHMm9_%Z-lyhD2@)oFSoj1f-; zJ+rq@3mqfq6=HLZgZkc&a}gUga?BP|q9!6y=we0JeA~lx_tgS#{}#ZYOP`-=XiK6kADm zNx_2lFi3b&aulD&y*ximVc>1wT=>bFiJ2oZiljZ2QOBm}G{Iy;$} ze;)HwbVr8;qEMyTN=5Vv=3eFRhpS)uK+|fW{{3Eis%InKIE((6&XxVq{{T=+0|XQR z000O8aZyc9ur7LQOC|sS83c&{040~vg%TQ<>IV`Je?4n++emWX^(zpmTqGSD^5gFI zqJ(?pv$eabv)77cXDiv;A|YZ(A_f5-29V56CBHrWnkPU>-c7EqQc-QKC19p!rl+T0 z)7@A#^){K$S6$mRYCcbj?XGUxB)isi*|loUe;>(X)ihOY{wVA9x~SIXPrcXX*W0YA z;Eg^ye_A1UT`xbWHgPcOCdqViMUT(%&uP*YTUB?hd;WnRSm^ZdNFb)_^HS~FqOP<7 zJ3dO_=T%v2m0#9%$#Ci6WmC8HGI(^p-L?Cu*>@_-Rdbm&8s_dluXX!slT~Y#dr#lg z%M2&*FIm|s@A=#8^Ly1c`*8fv{@?FmAX%RGfAs3=jrUjo{Y9nK5;p0*`b(#D`vc>c z-+ixcU)5EmmN+BnGZ9qnvgN02t#qn&Ip1dOax>q+imGg@4DMd3rY%+lEQnVU^)$_N z@wo@H_?&L*8`lQr)+uSVv{MQ<34fhm@8^2CQCr0;c-?Kcd$$I`{D%*h-ZT39%75@L zf2x6bt2};Td!HLRnI?bCv~oB$*l8G>W`cs;x2oOLxwdWe4k*o{3jx2EXNDlVwkQV{ zTHya2}b~uyOMZ(d~T4gd27MLUc=mKm51m z$jN(i;Jg-HQ<}GHm>81HH2K(+)8zYifA8PEd~@+{FaP-Fe17%nyYsi_SAI_-1Jn0S zv8w->=;G+;bAtydnI)ETQhs!F1pEY^3s*^Dz&G%#YR2<9(&~IZIXarZR;#QlTWD8b z|2trH3=fY^5!<>ZVg#aI zD%$yctW~+1CcGPn;28ptrQuJpN~*f02JRvLG+6-)?sKm3@%J?~PxMYL=|rW+lOx*~ z2TbYxESVR(o8J*BjClt1lGic`e|yY#$oS^c5&ucc`WALHYDYveqow$()omk-_0|R? z-8EG*dZcOi*`r2q@Ti%Ll1It7-R~54N)6#m10>w}V^=zLQ=9mcQdO%CPYa(0tv`Dk z1~O}ov*X`xvQi#hdvIvbB?>VQNhf%A5&Sn<3H#U9Fx(T~%dFbN@>`fyf031mlZx@g zsHdA5j}WcFoC^FQIZ6itPl3w4bD@dQ^Fn9WB}`_cs7X2qW(S9X4(NwX0U|;tZT3l3 z2{DRI+wRUzPdDpyw+C)prFFADUGndz$OBKm%ChV1tLM+u_44WIo8tPEl>lgeQa=Cf z^P~B72@il-%txXwA-@N|gn|H7N^q(*rKJfh$JP!Yy zM#3QC9UnFg@ZBdmTdA075Ho=z$t2HMKLhrhZKE@Znnluq!a_Y-#1T%*<6X&ErRy{~ zhJ|J&c0Qg=39HbjsM^|sGK>eYS{Bz4gIa{MK&p1LxWwak&n%F`f8hQBMhc)@pf@DL z-#@jpam)v1^<}exb6zaH`MkjeffZe{U%6)QMH=ls=tK^ah zJ9(b+S)ipW;3bIFe_~zL4UKM^y$DexqS}FH9ocHl1+pHX!kh(}%0OflRbJc_d6)S@ zO-2W7Sx|tpELoLx)*@m60SbifG`Zar00i_AO}I8AF^MRq5K&$ne?=h*x=#hDt(GdO zR~Cn$N&pI9uy!D-#zF>J7pOq)>n_;>8Z59CY|N82Y&@ZrQ?IHktO835Blee%;d{HIOa2D`z)s@}}O17Zm6fJQWSUYHf9Z76h z=*22oEQs$de-_wRD>{k9-=`t|{Mp24BVOuaA((@S4^53YP}aJWOWT_!KWt!VfV66q z3dImW&Tg`zL_sv=%}0sF0C8p(RtNI21c)A^2HN0Ne>JL98EuOZQkm=sAU;=#TCJc9 z622$az+PH*W!41N^W7IB-7>mfO6Yar2=7C1M(UJgAj{n((wrO85rQQ zXv=*#e<~Unh4MxvBLkPPD%M>?s4y$O-lOV4+B;3eOakeh&LgW4K6q9jJxN8!H=(D= z$MsLH7xQ#S|Rp_|4hTm5ZTfpyy~jt6El?_v5S z3`qd8X3tCG2};AeC+VGfH`!k?$v^-3@ndW~fB$sr%`nf&m;_N^Sz+5wT@qVA;l&-iy^$B%_9B72u8 z1lqEUiog)-n8|JryfXw~+t>%7@chSre>!j{$u}qnQ7p1IrrRaDW_={DL4cr7XFN&J zS=D+%6S)`2oze}CI^P`GG<$07szNMVETp@xC4*t&Pv*l$p+(uC=+nUYSd#=I!{IRm_y zRMsTRQI{~nQoQFi8}?J&!&}?GQM)o@eJvWJEYSAsZIG-z1wBm$7>{^_xr{KHCO`h< z`#dUjOL)J_Umy;OERrBSi)pCuf8gf+{VaKATa@)WCGr>_gGtyB$-u1G2=R2f@uPfl zmORpDkM!}7(`RU;>7dUC57Y7QpZZQP>|+jiAeGn=}EwCb+%wmN_NmnwR-hKQs#!-yN(8=&b3)$)`rrMIu~y_9bZK}4wJ=P8#0WZC@HN5>;SH=CO|8X& zqa`$J9n3^)O~m4S!Y2NWe{zAf7$>eADfHzpuPS-j0>y!0$v)*XWI|3dieMgaM@Lt7 zLU_lQ(u-V`p*vc}BdNxC3>ReBd1Rf2!-n|hQ6J_f=BYL4WC6McVOVUtZ9=vi(t$C0 zj~@uFN9iRx$!W!YJ9JPXO5bgO{g>qw{y)O|3Rc`R;)foQ<00_HfA7W0IX%#<)F2+v znsi;J39JXiKVT0?d=0`SFSNY&{d?@@prsDpZjJF#q#Jk)9CUNl5(k&|-V~5`AA1aW z(xcO!Z(ODXB%1;G(b&^ulyz+l@=R4A%$`k>87KpNIymtRewO2Th(S=4te0Thwd^?A z55O@F!g@^b$#sTwf{tG2{*M_cHV<*``IFhNW}S)4u4#}M z$<=|Vlj}{(r(?9AfeE_-K4@3Az{T39Mu;s!vEuXBtVEX$e`ui{o+WV{dJ=-!j=Abs zW=-y$foruyA2sS>$ct3Yd;nPhdFbLJZ6TmA0=88JmOsfWo%lFAv{!=Z&b4fW&=kY=9t6C`zcr)l}hiC7?B3s z6CP=gAr6a#e{WzZje_Ry}8{ub?%;(P2H6{Y{_=1d(g;HW1i2^h>5sGe5?cG?_d>EF|N`JV3qsk)9kU zkD~SY?BYuCb$oUWSjG)O{{#L73*Za!;DRx^e{h$QD9JXNci(eD_g5SYvLrMuF>(xb z7nCIJrm1g(dqF~~j~mdONFyV}jOZeM#Cj3@p3>hqo%jy_uZ^@&5ae3uK7xMqK@#Y_#{v8b{#MR!l7*w3EVtcDv6qF(u|OhO_+Pu6}= ze?*~mr=C51{?&6I!6Uoq5#9eXt|v&VqrBkj20WFe0{eilG6@=zfhGj-Ps#K2tMoU2 zHQduV-e#Ya@z;6GeVS~^?Hr!xnPHb`rgYUOl^=Am)6e6_qLiBvLYH`;-l_(8+13+a zHTo^+1}tH&?kiTJyLyoc0np`t z0OU|00I8F7xr@>qV@J(6w6DSSDE@dtUsfZG!#-~4wyPI0aHszykge0f@PQy~AXa@` z2*DolY~u&+_DfoyGC3ukzAS_d1Yz7Kfkt6P*Fc9F1U zCkV)eCNE5rf^0t>kn?~mJ5mIIr_B^Gjagq2nE7~}^!c2ROloTQ(u86Pv^DV`n>SM< z1cY4y4SO&Q!P*mdftsVP1sbwGe++R$j=8*{I~aE|LJgjo-GCBr_?omB2V8TI{oSGS z1#5l)ByXwY&>4&o!nKW~#d(g3ET0b(y8p@_>E&*hoLB2YVk$7;3zZfiC4`O6lRyKB zd_ve}G)*E;HbZu*(2K+d88Xjfy+`yX^7FE;N)d6lXm|rFiNIkD1UJoce`lxBhVN=* ztc?rA*%N7jT3&#*CM+!iC!qo6cw|v%oOLRrO2;iR776Da`=d`-0X7|IlE7fQEnULF zY7anWHwG>z1}7ZUI1ed|I{8^OwWS6z4}s*#O7p}}?8FO6V$f%IKq(ni0=`&N@yG9Z z7=y_H3p)@B(4R6LEhMUxe;l7;wJ?#b?Jb;nF$o8zlgd^uss{}RGe!=IgQJ8C3eN0O z6*o$DL$V4;3!#&$nj6nR>j?^c;3=f~#pjeIDNbsv zghhUd(4YFbTtgbbm&@zJXR#-*K`abQg&Vx)z}*2U;MR^?J~yvsv6PteYh7Xb0f>tc zMGgO9N%@zqq@xJ z?7i-VQ1RpNZmUPJpe(@vxLdGHyE zTA}A?L30w7f7MbBZJ@c7MeMOpVuAKBhks|lE==^fwaob%jZLk6*khLEpW8cZQLs5~-AxiSBlEk%vm5Q+RN8*LzAoC7qE%nGGEOJn$)C z7R|UqEV(fsl#u4l@S|2Xkl998*$I*ZyD2mp%p7sfe<3PiAhbINO)IzkZIn(!8}BmO zT%s$HV4NtYN{NmP!7_lmAPf#Tco#hGBbBbi$M=dS&sztm$NO|4*FZ*H*SU#N{gUX` zMsX1IjB^D<`q+aZk9+RF9vq}*qbb;dDWsoV81m>Iry;HZb8e;e^?ofOmGDdv>L6_=Am7K_cWGQBo^-WUzA6T3i`(eB~EJ^pscLzk9}AR{f_DaWMWOR8hC1#r+^8uqz(j)hX~A$Hz*t>c&j+-+De}wn z7}`t+3;!nHWM`mn<{@1X!-k8{_yxKYbqzLVwugV|4jxwQ1rj4(K(VDAJ#cl__Z>5m z!{hE#li7u_!Roi?AEwFWyDR)Z#-^)wnNE6Ok>W$3ud_BIa#B^!Ng38ur`Dicaas(q ze@paV#O?(g)JrbGOoo1%C2$tqqN3FE8E=^eEqzV;$mk_s(8OK(1v)-D-PX3HS&$<- zyxe^9a*f`W0LsPc2_F6@Z_#nWSi`FxW(aho{rnhC;=K7EZe`60> zEpZ*Z%A<%JdoitMZzZG%wQCOSVYk0=Bw&0i<;jLFtSvAmWaZ^PO~g{R;p0`$?LdV{WZo__78Y@m) zjCTX8Yp`a5=R=$GWFZ^P0`0~CN>6p9<2rHrzbI6IbyVqL3^FIVQ>D_tiv+0FT1`GWLRT`#-6y+x*Og>D+TCZ* z3I$B}mx`&&9yNrkJ)FWUaf)row#2k__wb^6`su+OXDDvn#UY27QQ`-^o-P@a{U`kA zU8%346ihi6weMRCGF54UKmx9p^_n={L1f;{Pg9MvW8Hy2f8@ROTFjD%9?Bq+jvSRJ z$o-*X9mYD%XtseTH1vVetOoTDKLoA6+`+5}jF3S_1@uQs`GOq?NQv5%mXR_LVla7K znF+$_J{2wbw827rnwZ1KUCty9XuZjrf@CA^xs9yY`WxRv#lWTvaa+GomdbB)U7JI|h zHKv^S(`s{~t-`O_@!~A26Av=RrcxMVa`L<1K1+Ul_7f>6);l%S2OIqpo=&`FTZ6jM zU8i74pXyEabA5X%N1LM~^(lb;+Vgz!LUCIhO}oYWf0Xf7HEZSaY^)v5^?OXfX2B{f z1#^2$!jwV3jD0p(QHjbn8|&8LwyfIYx#0LLVt_Rf;zYmFPXX zq)|I3@xR*#fkK`$7oEFYLg5gzGHXOA(fzi0)e&Kj`-$hlp?}-Kk^ZFAF1pOV2D^wP zMg|i@e}>&EcRa8{5!x8Nd%qL*lz>&QC2sj+MUb#$9c!pw4oTAtobx}?TTT-F)aBReXbKdG*#9+pwaWf3jYNNzP4iOu*dU+t@PTU1Iu}OW)y=ygn#Yr71x&)k{)T#*hlRJ?_*Gvxot4juaV<0IIcMbUM-=(I_QPL{1Vbj z__A{L1-a(&k0X*k!0>KUK}Udzn90nNCg zrR)0S6KdvoL+4I0UlrwOs@QN_o5(i+j%;O<`R5(R3`}-YWYHB-gyvEYu&w(+xhE2| z7lNAF>?>&R<9~0I-zL$^YWDfs&8?q9tRUa z-vSRgyKGgj;m~ef_H-m(e}i$|*xUGCA%_8Aun$GUCZJdPObIT%bhou?9ed>BnFHW@ z^@W6yTK?I`r0Dvl07s8aWd0w{UY?m>?uT|rQ^E+l9HSZLaIogV{fy}lmq;ASXgD!NCnzESWB@?qi)hhu zc{heDg$zJ*K2bSr;pLilHx}NqWqlTD9q{;eJebSzKc`pW&#-Paq)FkAD-6La|1Jy_ z_=D$JKe^;Ub_-0!cipRg#+FLpCzUXyNkVTRH=-GSm^hJOEVsg!r(YNOx zMo0IP%7e8AGXraH`1-@(J_Zpa{gGX@PDwkdtNCykhueu9ApvvZ@(6Biktx=+y=wl#YizGgrg_ijtVhgX3UxX5SsbH!Jfai- zgv#)bCJ~bpfBqt{#%}wLNSbT16gp0Hl-Aj zorjcowypECh1TUFf!{j$!~|PjcBlg%pj$|AS8nXdf5*$LdW;FFn5VIH&MzSfFB13A z7sTvGbM76QzMdo1WEKk{j};sv)$G7BZ5L9u-@Y@S16=So%oYoLfca$-XjnHnM?;(W z$EDRSR)fHxs|5H}(zg(u8S4VNoVX7g3_1Ix_H-?YS1F6dk|!Pf*{Hv0`7@j26YZ8F zPv&rJf3OL!1HX7E$+NgN`W{EQ=Z_u$|MqrR90g&OVeGJyj{?O3MHK0Y@bPkC&e?4g zGS}_a4IFm@7qK`~1P{Sw71fmTD}EgK4uU@XAp~#RAN;9laKlFXt0hKS53ARMtA>JgE+e{}4huzN;CBDINTNFSVJX4?>_NO24+H8}6?nA_!r6Ohwr4mX&Ao& z*<>UU8*Rbgn)0XOQ<8Vn!luyyVHlYZTqFhEvVfPd{8clC=o+7RtMpuf-ie-6;&KrQd+C`6|tRu)~{-a~7{`UHIL2#$%( z&*{n<%z3pn8Et(Px%9U{sBAZW)mFZcLRT^vo_Zz>)Ls#ebaHWdh79^}VSb`SsTgje zf6Vt%{Td+yAAgDJ#Vu_aIftKL@zoChdxxP0It1j`eZJ%BfARYrzxmCJ zworQb6u40IRqCPWWP3w>{E9w7>0K7{`aZsYV@V5{9jbkIejDJJ%?%TCHXMt<AbCaClo(6Q(~5Ux5dM9U72Yy3hLJj~`kWpqsy<;*BRts|WXQ?Mo^# zhYCaZ;;X&Cr8?WX1O7E0u(tUKe@%wVKziQ9Z|Y`gZ5w8wF6FqRn0f;t4sMIj<6UL? z!tzdALIZu;8pGR?1r&?QI1G zZ_|dP$*A8I6Id|k$l3lqlNji%uGUzRI=?CCM*B*svmsz6D&D2HWI3QYf3KH1E$UNM zonqpRZchOcYDxK%PG@VCZrW`*0PY0D?h~{4(WHMqE-H<_I3>ZqKX6n0_Bs_IvYSgK z#7tQwJTSI;hM~T1se(;rvo}coRL-jr`E7!4$zs-l_eo{<^$xuO?y!_}PoWP9-sJL7 zCdM+XgklP<5HyKJ!MX%;f6z>cg9pto{BR{e@xHz&#i2+NATOaPE6g9q;Cb_LPB*=j zzsQV^7pbHZ0>?ZlKRpU#E){(>Y#>8Q+^S3OtGKdKueyf?b!eF>R!uOaAEev}F9Rut z%FkICJv-DHmsnGQmva6&!;%PoeUGod{@M>Qi3w^X#j)3Qy#`r`e~BPoQ8w({nBsjV zh?(v}fu)#+h6W!{WC)viMSQ3L{Gn1jQ~VA#yYW^@l!2kW6bzyEAs?qF?^xxdlS4hj zTCE<8hk@V|+OLu17ZEaexom1G)pc=s^E)J`2LC7vprfqRp^M6X^TtLsQ_3Mm)1Y7V zR$02fZs>z}l&jzaf0n%XljO>)GC!3Is$OUG-cr!B`zQ`>i*?Al`7E34=YkS(x~n#694@7zkTr!f819fV5JAj!>b0jmA^Nb z{7l8Jat!7G;nqxTR?`XQbuTe&S7Vy~RumCnWfznniyrPJR%}6r<$svu<<+Z;3v(!l zY5PURew0rE&Q)&P}=wJ-oJhM z=HlO8{_)NEFZ}A&cjs@@6aWAK2mo~s z007Jxmv1o>8n?$T5|;=OaZyc9gZ07=EC&DpHx~c^9hZ?p5*N3IHxfSw1aVPKPPfTE z61M{laZyc9FcOJwYZCwf)t8Mz5-ool$F={TpJE^*AnDTU*bdrU0Sw@(P7@?{0?WC@ zg=;K_%b_^Ya+lrNmBbYN?mdrr?k*+yHWgr*oX44&^Z1>|jJ8d^7kR$z+OAP~F7*CT zH?5FsQ2> z<1a>SF6ye4x>AiDU({8_!w*2!&G_!aho3Ke&(F}aptj4j@m?DED_bk0LD@*Mli)(qMOlI_5 zwy$sCQ`eNGUPDh~lv@JYeyx|fLlPW+Xo&k8++rXDUnY}Dp3AZX!7jzeDYEFTtYC-D zbRnj6jOhCTzvoC0DNjGaY!D{Qv?9%}RQn@*RLv~UE4c@KnNKE{mp|q|y!pSs{q+7X zmoRoVy;eX(mkLQ13V5D;fzulLB6Iu>pC_XCGc~5nZ&YJI3enJfqiLJi3leUB)m=M< z^`D5>WhqDs0+zn5n~jjoRksHfGosx|RNJoHh_w=M!W+F&8`0L#1K&|S_RN8W(5(S# z*k%@@ZfHbTZB$bp;q)SCmC3}1od%6DqBBelI!)Vj1(*&~g{@?hoOz+jjX~DXNr^wK zgK!%0M8Lezv8zox(u^YIW?i*^p}Ez2Rd=BWcfBoZNgqCNXBdt8p_NHSvzml`!HB}r zTcbhwo^@Fl*JB-~?wUg7aom(U z$+WU6l&H4?Iy2Dq3+_kWv1z|z5|qmxVgq~&4_!IgBKMH3 zZv?fMVMP*6e@4|Dpl{3&Uo5 z=^&sKooNACVXR+1VNWf6*w} zstA+>Kmtl%x{1P0B+Nr_phvviTJ7YG2AoD_9})wb){L4UjFch3r+1$G)QKcRd;wvMoDi{PD*hm>G~I+leL%P5&-NGgT#Ts5EC4OLm;uZ(2KPeQe@g@= zeoM4z+>}SM%(})zC3zT%BPiy$?$JoxFK&hR$Pg4(m_2>!oalt&i5LqRoA&a6h-5t< zs+ad27QD#cnj{OL$V8h2*l;SkA3FRksI(hy*o`{Jp*9OV=SCUbs14D2Ba5AgQaQpg z$S3dza|r8Axl!3dp0;yOGwurDJ&5E z2|M_R^|Lft@5NpaM%K3+Y074;0h&M<)~Of>5Oitr3XVzj5Rkt*P^i$zQsNp!No0bt z_Z%UUhM*^nPO5I7Q+F_gcinysiUPVZAc3J0D3o%c*G8K{+Ncj&OC_yeWQ*a#4eKz+ z%kk3IlZ1u8;|5&Ch0O#%pj)033rMn;@ktUnH?TWD?VJOsl}q!|s#2CJ$jY0Dv738y zC-(rw=jRho@tbeHan%OU%2FWn?$;aeE$8Bp6(uzLcnN==Q1KFB8-lA);IfcNu@ZS0a0qN` zkqVM~iYV2PW`8%D(_EWdB*z>D+VPHb@`wZJH@QeVQUzcqr2Qhz;2C?yP))WK?UkTK2I7R?bJCJ{PD>>ko9oY$A6`@M34i#j~8(ZgGzX6cqSP^ zr42~Zf@&7D4HE9vs<&H+@gVkaWmYVy#@{iW8&LH0;+kwI-Pm+_PqrIZTxHR6h+@GT z=EkvV>g9HDP~<|_iuF;PBenBYWX-PVy-GL&sCJMQQrTPR5Z}{*AhS@_#^+zwRyL6F zqete_k$?V;t`V|P$yq}|thmRbKJtH`;)u7$aNNx>;pz`sp2D=m(pcwTmvGeXYM12r zJCK}$Qyw9WKfjmL zE(={v!VSiv+KOkBU^Y^N`f`1+OI;IPcrv|7DfoQezlx}3B$!ziXy$GEu zBH-+L08cqGus_}qR)u2Y_R*#_M^q9fS%MiDnB zHslf4X3^*Qsp&~w(c%W+18ZIX5Gbki5Oe{&>|J`0S%2E6 zhxr;Oei(pK-xrb5*}454-eab223zX*HOPNph`sBP$O6Zro_&YK$d>cvq)Z-}9$gQC zQtK${;fpq!PE}3of5t8$!gZuGkrPruw(=w?}E<@7)O(SjUx$fIRY|_#7ZbohRrahJhR?65-LN zR^+YrvMqLyGC?4Sp=5oCDm+Xki2<Ot5045xmgj3 zm(i_LoOgz@Js942(#5o0WPgLTC{6Y3kO_k}eO~o(EIJEu!Z0JJ#nGK82^sdgy0w_2 zxA76tWRV9+Ol5Ok4#+nC9fj4BMT&oYp2{Yi5}8XG{-|I()FSuFZ3h45kMbH6yLVX> zw|7}w@_?^a=O15#i&Zg+-a=hx80N7myDHiV?R|^WfaB3+4S>=`NxZI(Tq?9djNekUQ!eCOo#S)ZZPcyfq_J(=wr$(C zo%~`ujoLVkZL6`>*iIVT$?5yfoHO&Bf8qXc@7ZgwwXSuLlC2269_>-i5yY&hDY(56 zO0#ScFWkGkUDSx>$G*N~c)S3?D{RH1;r7bo0x1wv&wK5xp^v61m#)xhzk96*Y=_mWG$DjSB}owyWsu`H5} zR(c&|x&q8g53Kjrul>9niMnP`^RK~EZrOU+-WMjcm@xO|F}*)C1JVN0()%vvNbnr_ zLRI}A4lD2ZAA5{xPC8h>Nt{A1qTWa6y|-!2fhX7??cZKx5j5@`&xfMck;!ytz^kH? z85vdc(K1igGsm77oU6My5Y+mur-df_J@ikc{?v6kNsj3ps8ILQ<66GY4tLfVS#+H@ zb_hwHIeHEPMMlgs+x3$Q+zO)~x_m%s)WJ62hyHv^p|`9zQ}XmJ1y_=+&4^b;6$CBL zm{dg-2K>6wKISIqJH9TvH(%HUaiEevVghq=`+2lN9pWugw&=onQZALvf?j4;^eQl-e$!2bzn~u7?l=j5MSZELFQou0MV#VZGp> z4}_J9(0gBchaQ0Qkc#i>$0N-ThF9jRD8|D7iuciN2rUnCL8LAp5SYFxx*m%0i`WBe z5ZBo7!}?R1a*1Hr?fvqwGc*Mk*B!-@_oaJ$DCTz4+g#Jo(T?lqFyQ9rOK}GO9Z+ux8D%0GhfJgfiJUy6)uSyAzh!$s*P6^%->wf++ z->Vdg`WEqJqbCRGL%eXVh)e!;yW&9a0dR<;Q#wMUg?{b3M23`aF`ChZUlvHnq8V!N zT!R2K^2>2ASbaf{f0NU(7-dS0i?5{Ms7cDv3B)F-fO?n+9Ig=3)iNq#__D<`wPM*T z@V3Y2^VhhT=ZAf^;O@yV6cp=Y{^_Ug=2eq7^3SRCBB;)s+3U6(lp`GJLsW+-eYicA zs2tiVY8ZiR#JdkJK`+r1POzBJFzC#uL$#-@NjNOm22hC;bOe) z`1i8`y0@7bqNhe4voB+;pKI1V9Kqsl-?Y4ICl!8Pi2D{d&o2Ota(Qq=jW;4}la<`t z#lCqIGm^&%wQQLhwk3}gdXe^PB?|}kOQ%zQgEZak#sbAW(tky?$X$%f6kgpoe^)2Z zMXLB`Z&#bGjdEj1)52MwHSa@-+Iz=;FVG*?t|gezmZ~cLXLr@TL|%U0A6@81H7~En z0F|whL6|~QX5({L*_v9Cfylj-hb*M|Yqvz0&ThgpXH3W&CFA6S3-q&qMrxc`+sPB5#Ad>b%GS|+a zc@PI4=1k4!oRP*reBW2ke>5-0hkL0nPD$l_T+?q#SX2knW*2m7+x1kb=&Suh5 zDh7$TrO5~or=Exroxtk%Zh3%){LSaNH;%0W@TS%sn8 zA!9!=>hn5mjQ>jet-pP)Eo}z3&&=p?8a|<)tqM(Q^mKZDO$AD=J^POEIXZN2Lk@na zu4>mR{e|F{H$hAo(vi3FigSNoUo9hGOVv7_Xtn}4i(!wfMtamSgbrd#ODFip8wvs= zEDORmRmeJ|Qr&<2ByThGvW&&`6c3VWwS~J`Kjxw;3A6ULEv;W?HVnHQXfbdoXbsQ& zZi46k&w7@N>u*zt%emJ~`$8$?u0S^vMznA3Ev({}(~=CyfiFvOj(hkhW6h_J{@%wK zh-NDGZ}91{PE~o5;01SDZ)yj>Z>@}Sb#H#x2<^gslm<{ z3@Ud33VwXgY~OGOV@bWjpEIpkkkn^`bmRrsm~0VrV+VRTL+eTo_es3Yot< zzn_RNz25CoAuzu&p>i2SfYR!T-}0EKW6>MtP6shkV!k173o+g|@G4>xV7kP`zs?T) z@n1MbgXd@TvA0i1h4kINE{7DxtA6Bw6`omS5&O2>TNG2h+#}jIV&h$nHxBae)E6(2 zp$P7jUMGGK8%=Nkj=P6P*1lzDBOINlcPYk+!Hl9mi-da$iWBextLkJz>gPdXkE8N5)=0j=wca)0xp!je^3S7N%eYUwocPk)MDp@}ds`atFDp4O zA?{O8*L;^O)>)oab!>TD-Ic0b0Hw}e@b=sFpv}%5V7+)=@A!FNgw-hWm z7go?Va^SLw$0i-*qNk?GIly4}g@49Z&W-KM!ntAZJnXIM{qRSn7ZXqrz#o^~Si3J; zKv%H2zlK$?yH{F*gsSHxa(-fc{IPY}qV@pSh;o6Yx9ap);tT1&AL-chGbJ}32*@|{ z|I28|sGvZH11|XO-0-+k{)N(=)r+Nh|A?o!jpcH#RWVH1U96?csZMtudL)aXl2hSM zJ0FuoyzK_QJ%IOtU^|m9AGtp5YDddYgT!A-7R@mks~p&|5HkI(U_9`qPkEqZqD4`f z;IF3RIogJXv*(;>l>JmK9#iL1Q(AJtWU_F{&;3Nx1x~JHYI=)bT(ivOpfrve{d8=Y zH5$@=5Q@_G(hWCmLY4J&(0%5bx(4&0H<)o}ZrRfsX~!B>TLCw(r``Ct;|A}vN%TSK zPu5ht($yW|zGDl)?e3XME{$eTT*li6%9<1#TB$v;WG$Yc(i_RWwCqE-^1uxc?{F3& z5^b&qV51KNb;qFU@44Z$)E@0m&`EVo)VH0hNN$Crxb1#rlh$afr@k3h+EgRL)& zt*uU3s~e>?DeSc9@f~`q30U0nhNR8ca$MM2z>7DeIw5`#c9a_f{G6($({3d_)V>R5 ztq52oG&FQ0JEPpr4QV{xSQR7G%e_^fi?^rnM$QCeltT)|qBlRaMMn^pXu!1)^uQ)Y^S$BBK5YcoLg2O^=zgEu_g!m7myVzaR6@jv$I&2feT{Hje{y6WxNy_~>m+E+}T0md^3EI^8Pt34wgh09{h#J*$$!bmI>Q=P>wF>2sQLIP=sUJ zDXS_IbA2vz8%g&W9s8V&5k_?Knsne{Lpeg)y7;WD&(PSFB%T+Al}0b#oDzabf(PP9 z9&q(%eZ%en^78E&QkZ*wyCew(NG^H7^v0#4v3D}X!BSgEl;9Ub95R-PB1hvvR*Ry5 zC-#&|Kecq>I#;|Vsatr6vB_sN8Q+eRuG6;g)E>CvTndFWCw zID{zsbrV+7v&%Ue8uHf5YhAJ1WP zlgrFjDnoq;?dKI0b7R9s90GfZ;zo`t3j?hb0sasL{!>nVd9>d)cbK`KBnuJ%32hHp z)GFd83DkWtkl3z*&cTSlj3}IGk5MR3#2?W5i2}k;+RQr3AWen9SZ*ot^7Y`$h+gIL zdzZN{MA87-?7>8x1^JG&iL_xbl&x?9L< zHLx~nV4iZsYD8)irD2dPE{*DOcvoQOE8G34^Wj>NPuzY@VdvOKfj0WPO^62hhM zz(VFp#2!1JZ$s@4fz8m0*6TC@KT`??Zq2Za{qWc5e2O~| z6wiAC+)V%E2k944} zhAc#0JMgLK;Y`MRFg9R(A}Kyl;((7G=HY4WpC&gnQ+BTOuQ5J}ByPDEfAe|{K2?-W za#fxN*m#uj34C_jO!}5J6-=NOTZh$@}KPy_F*5&xs1oXDbT>FNRu{ z74-EyInWGUdrfo|k0CD5x>OvxM$1SO(RXs6{2GW1ZrZ{p$em$);AApD(>$H$qW@A> z%(*|9z{B%RPiaU?_@^lVb-AZH_rkbd;0F`t)DF$I?&AS(J3oK&0QD z5e7subDum8g72O?f0qjc<`+d{d7%~;fe2Iiy3vw}b%&^A1!3%;UQwM(&UeAB0_{Q! zMhG9jM5j~1!~?RA*lx1|mX-L(p4$x$Ik>y@*tObzDo=|9*Nh}0tXkQ-f43Tawr#fK zJ#kT&g&2eKmdj^##P#VQ5HfGuv;OYNVoZ81t-LaqsPhbh4o<-BDWxm1!3IYn41`LG zXr3hH*=AB7w^@vxBW>}WDVr^}ic4`E6+2QQh(mBP{g__T=Xn8F^`MAV* zomJqBL+wU75PXc)+xovqT~KkNfL#*>3?dELxwp?2P2nY`8%W?_*?{q?;4JTPzos8) z2qfyNp=whrzW-jFC|Ndb>_uXz1a#mdn$7MJp5|7Vi`Y{3oY+<{)F}_QAKjbO+`;49 znoH=iN(|(lePgEK%JZrWm4a*YpRJi7wP+OP@cfl;))?p^L3`dv8A)##w}N?%c8=9&e?Wb4#jP#mFtji#Ik>3r@-vnPWH5L&LVPi z)q8*iX?*lW52wY`O{M8E%-UYrMMfggNH65ei-bV#jGrO+yKv1Y^azI+U@?P~6nG1j z$!GC9lS?At-4IWz1m%`c0M$;g3l%{S)3F2^4j{b273KQI=U4&?tgNgiw_hriPCuB6 z9Q1c21x_}tyJ8|V^POS0dasTOB~P34SM#=VTGHIPv7hy6cz1q*825GZP}x@O3jCyYz13*kwHYy~31-=_dtvS+ z(olV>X9inK$)16-5)KJ)6-x^QeDZ={7~9iN_$hl}Bw9-{DH_GBp=Puz(r(}NBUnJ| zv$Q9ke_hlP*=lnD>9Oeeo3#7Q?xsx7$`+)`5bf9$b>!%9DhukNN1mUT5g>F7Jk(RS@>Sa9O`<3yuOtj5~@5G>mW+7rz z55E~8ogw^L7cUe zMowl>sGAULu)@j>VN!OGwG=$erS%AP2kSwk_^1M=KPg)$N66d)BW6Qk*WbzU_wf(^ zq6#H=_XMgBIlpn7wF2WwQNG1It~#G$V3W5KOI$P%$YUc&RMXnDK>2jsYL8?-LM14} z#fuVRT&_S~e_Ef|GV|tMiQ|KnpF z5nxigegH$$uSyv)jDTaRJ+J30h4EddKr`%ocGEImjiX>>{U@_#jGePb^`OF^iDXZ%cD!{NO%h7Sfk?4Rv}ho*fk` z)Cf)GgFXjMM%L^`Kikoj&LlGG6ioKSTp-SY$L8g!^4z-h$2Z!B9Sv)|>EyNqD{Dv( zw@a{}K`-r)R<|N0rUNohB_Y1#%;O1;h9rqiiN&T2P~+e$cq}VTWO2~W-Lb*e7-mJq zF^V>{`+iGso`ybY^jZ~4T{49cf9(dT$|ZSQiqW2UbANqE!t$A^(@LMhzgn6>nD6Za zZx8abLaQb`iDx6!7Q5e@Bk_MOYXJdXK9n^_DSx&#AM0~>4PS9=xN@_? zHh?2zs-0Kd2JN}ysL_h{Ri$ERLeRnj+$G{~lHoOh%|kyJ5nA5sAyK_tW%*1-e8-PkobkQAyngtI3r8h(y+JYOp7@sq+vdM-!g( zVIroHC{)7}op#KC8K;Yzoj{`;A=J(=gh{ETZfALv$3tOfeSa z8kO_(T&&2~Z{1~yKqj`8p%_7X`T5Og?>@RXYc5)-WszpuTL$7Tj&$b6OiU=6+IZ++ z(@p(3zxc2eq-?lH;6o%IE3j_Kf6X8+U9urVE z{?z1(3L8p|Ab2&qidpQ(I%_cOROup4jTCW#0e(r@WeaQ1A86AU6e9g#nmp+)gCYVS zG!P@PA~ zHprhrLEFW#;(_hLFjhwbk&HPWjU5?3buW=qg2>HQ%fQ?59t%`|M-fU)W7Cb|#=rVq zG$=8nD?!mQibR|IB&lWEg;`#+Fs_xZz-9bz+Z8a;Ppb|5qg|5=TslW!M$_2G|3KCI zkSWVX#!jGf$XGVkvq-C0ihp-C$mSwu9bv$qs0s*oDG*{P*)=araMt#Q zuMr`_%svSUrb0^^DaqCbn59_Z8EGnG3U9Cx6sm=VnScGMn1EHcgLLaQaSo*1cnJS! zz&kch50swBm2$}enoQ{CLEmAEf{B<>9Lq)b{;tsr-BLHno*{c)teJ*rgkhkqLXxwWTVe;YZ~yYY4KdXt14q6hw-e4n{zoa zGTwUYO)r-`tv*yl#+tHNC(;Dl01@0HcK|hBr`OSCv65jIzjRh@uzvQ`K06&8K@_EOnVCqD&-w>ffR8 zvvhO)y}0V%qRyCAHG52|2HODhQ9JBMkm;HpL3azAkgU~!VGUS4{Ks6oB%YNTrdb*g_Z#i6 zq~Ln#spw&iks2zCKQ=Etho2nBByu&Q)FbglP$eFK&reYZ?Ch_ZoU{L`ToZlD^kvSR zXmrZjES<^C@yBZFe9By5x-U=aVwRF%KK<>9d1+CRO&(H0t^0RW{zvGYN~p}j%Fi{- z-QOj^Q5CU5K5QC~EqnwCOv1wncjq|YD@T>H`!<7WGR%icC+IZwXcp;CIxBCd%^bKzAif&n_iEmjOvZ6Uo^%SFux46C+lsM& zGydbso%h@A)jg4Bz`9F0;9SZG8B`7Ua~%1R%-w>7o8kSBnr6%k?P>^-pw|q;zpOU5 zsF|Zqr(UgKr5BK1J!_TAt5>=27|sj&0E6lN9RGD{kAu86{dj5mH1*AY1kE3tdtH91 zdhP2a=yD6Z=&yC?p0^fgi(tXhrKJHy2(KH;vdx6&s@CL{J8p}#D}tw(Ec*m-_a^>{ z&!w{kv5`tu1W>DUL%|a^I8T*PjvN%>F^r#t{toL2PX#Kq zuuwLs4{vDIFiHEVfUHZR-V;DrpuH=2Ubs4RrznA)NIhLVebbtlJmBPs)KOXB=aRf^ zyt4{1u$PH32KBg`o5loV=(EeB!{= zv_~)(S(zRR|JAk@S`E8PcR<(kVvl5uUi@9i?wx>ZhvE2bQPPA!d4(S(1j_XITab&3eMBmwx&K6k>*d_Wu} z`O(iF11)W*zUK_HfP3H%ez{Ac=We%Brpoy~PpWye3S}2#1CKWj+x*c^*))!fW?21wGdZAK^Er|BCHoOT;@lg%UT{&HUu7(I zB$yuhVH*Z!(CgbProX zse!gR=&kD+tzLMTG3rIZ=MFva;ex|-utM&_uoVt_Rz-5UU3X*J&rgujF(EgtX1LK6 zz@R>?XsLimWD?HZ{`8&WB3=3rDNruMkZ})jVSW62)5t$7>2Btxe*wz6cW!IYM`hHf zWOg8G^7x&&=ohd9ejaf@6!NS$@0d-2XX6#iwf6Ci0$HiX^Q6i(s&Se$QaOI$ON;HD z5@lu@zq5S0D|sEP5}9@aYOp&K`+I(9U#riJ`5CMtqRpZ;dC3cF7LT6GzFI^=!CzC! zub4w)27j|hHH&OPBiu5d}2`HM*d8uFA`9mtz@b(gC#wZ5#*vybcTh|j4X!qenYCRXK1d9$3->W$Jl@>Sj zExdqV2XxNO_r^+Z0YgRvX+eR0y%nLSow~E(Nb&Bc>ijxc?yK2njc!~WE8;}MMzx3d za2X#BsuO@u+#}EF8}qu?f}NPp=wC!k?WV_+^z~vPHR9Kvhv7{W0z78zg@P-D`}x#A z`^kUAtafHUxpfpY8n6ltcIUI&b||YStuvrTW=L|i+mwSX(Z3^gBJp(+XWf~0Ag*MG z!-B9z>c}r42!CdgfOlD)nYUNu+9+pgBY}Wcb`JuZd1o7H^pqskITtNAH934wR%1d< z3;mM<%{;(m+2E-$M=rDk=z<>uwxn(1i{H)Dxx5ik7*$4YmuT+MxX!ORpEU9&Zk!=K zehod!OsS=`0qZ`L9|41nL?wJ(h0L&`*n5i)e>&|1d^cW4eVi*1U!F8o5W^3Bl{5y7 zYBYfO_;&H)MW3O99S*To6VEL97`{hV;~KNQ6l(x+QmaBq_0mm3>cr|zs+ zkNKe1I!sHR%jC=LLCJD?-4jtA3q!AhTte_s!IYgM5HRXK^=DCFz6?SHIsOT{TFf32 z@)uEs0ikOE_|lPngx zvcPqHORc8d527~%s(yPVwNN(?r}D=UVn4H-@D>r@cSbx~u&IM&r5@RJ4G*XTDd-N{ zYs@h{BGmTf6$AnD%ERAxIPym~-FvW&ZW7UM&ATyAO|xQ1{S@yGWu248Tha1<^5x=& z?J~dDrL%R@_j&`v}Q8 z^WZI?i1tW}*BjjMWoE<=!C12GOuLV+QvLT?A-s%God4mWJ7_bIj{kLUUwfls0uHI` zEhwMUM#1B$$&5w&t2eDbX>(!&JRMC(wDLCOOQ)34zsZayLx=@+sPSDmT`_LKpniAt zRGnIp3XUBzeOl!bP8}oHz04%0m{|`=>Dcv4R})cHbu&z2t)6Fah}tMlX#z9sI`oGN z)ACTLsbr`;Q5UaNBHHdQU|mn<1J=%UB**f+RG0Q{_eklye~##J&`f*#BrkDj+%dZ5 zM#sJqdv$eK|1=GS?=hfoK{pU8u|SAz0>kX>iX#QfQy7p_ZRAyaY#R4L8^{i+HbT{0 z>PkMqJP4>A5|BYsRc|mkTahv4>C3%OhyTfALh7O(EnVq9Mbyl0&-Uu-33!$p?jP&) zDcjA)D?+-&bar%;*mam`Aa<09n>Q8yt`~Jkk?3>sETOh0DeJ8&{nl+N3o&z9&d+p` zi>ahHVFor))`|eXzus2R+oC?YdVlfY%1fnYXFoHkmf5&57mab>^NHor@6!fO62h!!>scLXg9KuPVrOEMRZpS4k3jPA4)#e1EVqWaoc16YiUsNGw5%R=OJmfx%Y=Vbt|3%#brcP<6Ts z)$!^UfaY+~tATSLx+NQ@gNqYS3tS%eeQX>jc=utX;nS2If%=<-YQAF>gx*yBWluOy z*Qe>HXMy%do-4fI0Z=%mR*v##n|C3Z2f9O5(@M1HkU0f^S=8&UY8Q7ktWmu+ndH;b z@;(jDtXG~LENpuGyRI)HEl+eFydB;?Zccd}q{v$=%-f)M$Bj)vz0keWG$m_5Gv1cu zC&FV(DQWHwPqu+9PGVTud0~KqNcyZDBsT}l97K_9$rc)q0F?;qE%B=Spjygnpnv)T zbp|R^G*j9FM&=+`<$syFq}c0zqg6n~b6#lPk)X3F?3J?2ba_+1zQ81y@(+;y3EKlZ z#guTy-U%XzgcD>~e`Mkr-Q^_@S!2oGton$bxj7P^n*@8U^4jt`8!S=L@auYK=@R)y;crr^OJ3M7a(3Tl%_nRFWtyGGi;44IZo7LSU=l zDvaKE)GS`y^BTa!l+RIClV~Xz?23^HzKjviZOOZ)Rk(g)4$k}Z$Le)44u8l`YxlxIgBg4Cf zrWk7xIc9JX1$MD%J|_^i(L(bukE#mq`WvID;jN@Z7NW#K&<^g4DRLnn>I|8uOhPbl zx;228%}dhHo*qLKAs0Qa3o>XUMk%naNwVK+KyF-9DaY9 z+#E`InaS<8^+{AjA39~Xhonh`M0FAm1INT&6@yc2Qo4*JtsZGL!+YyWmllC-JSGh6P5JeRL zK_q9K+wp2cN%&OACY3O7lldhqOMrK&gwKm6kBcbrfkRLb5W-$M9`*e2@Uv3sDm@Sa zgno7y<_eUkq(z|^`>~9uJ4f^*X;e(%0nL60zS=MTL2Bw0;U2d_)aj&s3J+Sxneah{_4LcOdgk1=a+Z*U3mrgzfpMx1@Y{3v+RnhHgWb z5Ad$*ABbCX_Q#1LW&N*FmN$Yfn20tO)5swUij@Q#bm}8pN+f!Dx{2?K$I1lEutuyms(8gg~3 zKvT)=`0k7oODbV)3fKBqMLm#OJ!Ke(wsL+loWB4pw$GnBtf~d4{$NeWp9m4sRp2S@ zm~HHiLyXTjpkpC1YG*&0h=f$#3%4Oi>Z-GJO+S!Hbmzo9?u_WOs0rLU!wi({iPZk) zQ4oG()D>4Il@f9`t*b#}F#Q*f;4F+Mll2S)K@qL%^6U-Ar@3gg+ZK4(6ixq{1+^Lh z@16K*-5aK*ST*xB5e>iLKmRoMNfAtCY{Unq`;KWF4C(XoZXumWv>?qG#rv5E_9K7( z1fGMM)J)R?VQ9%@sj|I_JvP_gEoCR?yR3m#KiIIFFD@>Y7|wIl(TLSM3Dk8{5Qepr zT>)x!SYdvXB8UwvPb8q@q}wLk-|C{ceBsIYVtvr}`Ik;)x>usr6P6H!|KLE{IHYFe z8s6ja{r@;&4Ez%##I%+KCZ(F9Moz6tQA?|fUB zYgP{mAcSPRzdWT_I@PV!C{Cd|h?O^Sh56u2leX6FD|Xxi!<&GGMiF#YMN@2EBAmOG z7w6sG;DK-3e5y1+0ox;SRDIvBqxQKUj8OO)mB<(tk9WCm8{scZse%WJI$zdb32!~N z;dx0?2BW7ikrM{Ff{D0<5&{Fi8Jr$y9@i`FKu{@l`O&s^Y@iD?hTY;wZRmWyeddZF zK~(6ss-_`>J8A>UAa&1%+w|?Ly8AAPxJU{h!O>*8_pO+CYy|_8B@wS1s!B7jE@+;3 ztYPdHoU90;eu}X-kY6Z_kB!@MrD-d(N71f&u1432MnWona^;9Wswql;J6c|%z?E5* zXYYmgcem&J_bt5G#>i?(;5*@gj2Ui!v+8W=DCG%eWQqp@wBzhS*)2w)e>9L|3xxR8 zm%&k5rM}c{)uoyuL}Zz5mGTvSDq9Je4YA}6(<1O(5<++nfNb0BE|-3$t=fb9!RzXo zoJvzrjK|I219ql9@E>$rX5SY35U zfIE|=?PkD)?_^W1-XP9~Di|w37VnRw$12t0s;O`}G}>%m{>K$0<`X5n^~mBo1>RS$ z1C{V7DfUa;M`eQB$N*xMqFe}RO7Pu<+;&;f=0IDy6Esn zSt8Ze^FmUVoa}^fZjZc6$jIj7wNW)p!mgp^YYngf5JCMxEB$V^^vj&|T?KNlNxonFI`Pj%hjG@c0O0^#s=^NuDwG!?dWeMxdDA>n+&6+f zCnYx_t1uD!{TQk$p8VL5wcC?PK^<-tgA^h`mzKi#Pw4+{Dq*qy|U1 z#}upAn~KR!-zEL(QVyx6g~ZVbpd?-ifW?6+hhUH_lB1y`o}t`Nk`AI-rPWZJ`NvZh zY1;Kq75jd>spF#=&2LqiVI|L$WQ9XLeru$SsRRrcp^4XF`b(vl8lcq=`;}-G9f2iM@T~wU>GU!=Gb(Y`=Wv7$9R25ahMW_UTkYXl4 zc?WDH@4pUfCQTxfDGDHQ)T6NuK;;U)UUc=?>CY-S6cuou1gFB~TTjq-eR(-fS4(lK zk^xQTH1eJ>e}WX*5EvPqNJ{Eg#4$HoPSmg5?d8{s;4{&s-r;QKFoim$f75i}jV{C) zncp);c*R>Ljgtma3ucKkbDCw1Zyu&88ZdlFF38huDT6SY)A-C{KD%3Pb+XJ@Zf$+7 zF3GKGUr||Xr#)Lzi9RfAA8m^E$zK+iLQB?&9>Pyo^z!RLEEF(_>~bfZWwd>X(zAT6 zg{)R6tQVP=6Qn8c+gs;Krgtmxzj|DP8#^F|a+ObxUD0X5-ivk_tRe+L*V4CW=04n{KNA2GR$RG=zt_x-qF z8<${BcYg4=Tb1mf@Jvx z^iHx}+o0oEjoAW0PZmxI?Npx8xobEb`yn3|5PfcO=BL_=9v{EwV6Qt)aOr>Gk0#cl zj39b4csv>!@tou(<59D!_C?THT3AD?7CI7Aww)(!n~3*H6mw#?;$OU`H?w69dp?g0F+JU#f^y69$krCMOsEdR*48F?-8`dIF?}B9K=`9rKk!> zS$<#0mMgkU;5sW2>DK~`kx+Y~RMj>t=gtJCgZI~{MG{Y}4M^uYR6mB<^r?J0hDw8<5#4;JbCJI)pGgMYS*HN54WA*a2=4uhNA@cLnh0jOCLzG72#QXgPm z*b=YfNS-*Q!%u6=LUiI){s%!jxLs^gb9QHA|2?G?`u7d(JITkL5=~5XI>?n6Xr62* zj+t6ipqau&9pS$QiDN$Z@DXbG2vJw(Up({))u%ps{P;7H-aDdeo1lZJ1vxW zG(3PnXU7jCBX?C+W8gSHldoLK4P4*qgahbj2H4j&%+t;0ez_?PIBz`s8EgCH2Kz89)^8wmRJ6-*otlW$RI; zogn$p`h$$(L{S+cb;t>ovUR5rGibXh+@|u9Ki;9NwdqLCE;9T`M_S&k#`}@y(!<&< zG64b{rxzcwBq;8iI0}<^c)BzJOq%ouf^CAwYrUKG2w1DsY|&eYo8Sj)roq#oZOJlE zBO&ESHBwo61S2S@(o!zeVQw`QpDj&5L+Ai0L=o`+A>PQ)?=vg^Rou)7{6C2aCgY0| z9UeI3b8uU4o7;Y&W1ilK8Xt?x(dT<=(M`#R#2Wg&`bPeIBYw)rPRrXrnS&5SxL-h261Y49R)dvD7&a47_n0d>hCd!MgvuoE0o^CGSaya67PMW#zS7s#^hgC-`L2K_LTCY zn5E;Zl)vjyWR@t4)o()4$foogVOlN5{iuxqNp@F8J;9W}2yWUo`$neCFO%JiExDJJ|rzSGye6?Eu^$)%pTWe`Nkq0R$$^} zIw(#&mCGS>^m0jjb!N@Z)8qJ9hV<}5vB{pS+Hdj`4M}fozJ0yka+iL}h!{IsGUEjE z{GSvDI{hV0!{V|eXW@UaJqX=39A-dMWhO+QrzS~ncFiz69%Yo=)CE)% ze90ILS)9zOb(bb9xt^=UJgZUoc8#web|x)8zfPGQ7ZIL79zdgpo`JB2ipx55fr#kQ z1Vv*D&f58>32EI`W`Vc-kjXtRgQ2rz;eyW4(ce(mRuWEw1iS}+6aD_HMgS4o z)He!FYA|%BdaLO^VZ$>;%#1dSvnFB~(tkik#zl1usZiClRaDfPI&p`j*u3zolL=NZ zbF08K8)0GDG;Ll*_@e%-QGXysI(GCc#2xn%SJ=y*OkIZ#Bd&i`!r@djDB)kmWjt<&FI$x+fF` z@0uw*EPi(6W$|ey;SLO(VzAwyZiePzOyGF)Wpbp}j5C8mD)ULCOq--OuL`{QWxQC}(G zZd>W-%5f{9!;SclU^ZvzY^m*VE%7zRuv3)qe0V!?)RFy{JM*uL0T7*05bXi$FmQ)c zf^0NfQ37|vEEC!D&-pon#J_Pz|MN2Y`_L6{XWzl&3M_TZ_}dt-tS~5>qfL*ewc`uE`KuT`5j=Tj)oF zvklLa$>3$AI?ra}3OLkJsOgRI#P(5=Cc>ORJV2%jMy@I!XAF0!toxp(Dhb=GUG_qB zRdN^oHLy4}WMs9_t7QDKu-*Ie$v1++YWRk&@V@qTv$#-;39{236b42b6D-ov_1d`4 zjl5&59LeJ}6-(!RF#qs@z5qcq>PcL0(%oK|^10J3ef9E*EeiLCobp=PLODFwY)ywu z9_W%kJVj8~Jp1`NrF96eBvu9=0Ha9E5pqIC5LJ_e=SaJv%PL8&z@GSjxH_lc%%W~x z$F^aJD8| zt0u-&PL25>NsIgBcc9FNqE)O^lT%NMqeNFN}NVyvXb zIS3GAfftZHq{SqAGr0`{0HU>h(}MNDfY35k-cdO@&n&@s8yb^f$Vg4Py1WpeD1yCo z`=Zq&8>1r>*h?e9?yk}T5_B4i*4T$w4rAapyqR=x)fJRa8 zGSC7zt5s#~OI)IiqFgv;E_8~)m}0E<0)2zs*{6VH{Qx?*HJFg+w>1Io9E7xTz3+G2SU zTPQsb{iI{Gu}b`@p_P;sp+_JobVa+yQ_m1^lFZ~J#azlb(vn5of|=b+=%;FWY3!_OU@n`_kHU^t5bCg5WKba{&2IFkQfD-uK)Qb1e z*SbJt8$x^uypaO!iIc|2GqlkFkRcO7k0oI;3n<*Ma78R=VP3! zWkNQ;7Qe7tbZvO@Wr0%emRMS-*9>1@0)ZxWjBcDsQF0&+?~1T=6=56mpLM8bw|P0h zwLr#p=ggFhRMsi%Ai+N*(gXJc&|7HhX-6?6lS;$1v+^Bdvm?=oB61S=$YM+4vp|c zupj6f!OEL19w+(X07Vy&AW*@F+y4e+9+mzU#0A=0^=+qEso}kB+tE!JINJQcic~#( z_y$C|+R!#hZT8}qgD83AYzpn^JXDcOcQ2sL1>#W$+;RKgnIf`5Fx`2Zt5aN|a#-Fy z=(0b;IcP<$dwOm$;uc1T%H55GaJ7K>yZXH0G zW3~G#7P6(5&Lz&p;W!*oJx^6Bp^8VP1Tk2~h@S?gt(Wp<`JS|=tz{<_d((|Ohgyfi zwSp;X1#M{L zIhTvv?HGn#hSuodqzBwoINehbd`|;iEfc=)HjJX-faI4J)e#bJWs{2wiQteC&Z!q{3ACmSWi%XPhB>A=C)B$!$FeX@;?$?PWdWJ-(Yj)LZv|WgD;`FA>~6n# zKRDrHDZ@8z((1QR<&6z+7I0fm7iU$K084m?J`^kNF?!|8K;|wTA@-zwY!OyHUKTU1 zD^1#DfH1AoKdoY8%wO$O5SK9H+FBWI7SG8^wE--tABc*CVQ2jw1TVP!3ti8u@t@n( z(`Vj@+bZ$+^~rN#2l9P8PwP%tAM8+7-_Q(r&?;6WtH`HTL~voD4?n3+%Qszo8wiNl zoSU;1EhO@!i-y(}R`g<88fS!ISpAL|{TxS3R=b=15j` ze9PCkJAdL=WSf{8E6oAQTPW}NafUi5KruY(xW6DnU~_^2RRS1>A2O8x8vlk@h;nHK zjJIU-e*cI`pDBBPh2#R;{0Sc^H=@|xD~o2W$DvdG_{b`M<2~HpdL@P7uNqHFkTaE{ zdhs2cODz~7FaCc#sUdI`dF=xulDh5cb)67ERwB&4@9LNWeE=W4W-%Hj$v_AZK#w)w z&=w^4g~zZuiCDu8okmDx6lmQ$m;uAXOK#H7OY;qt$FgMCM{vZ%bzQ8;{W@I^Gz6VY z{{B`-r*}fIrf*xnyK`qRQOvNEH$aa}@QTgl2DyPF!?k#hYhv{TGmb@ma*W)b!Q}Of z9pMr3dJn}0?x_Fn3`(a(Q3!+?ke5C-b(B~7J^!v3K)ITmY3TqiYfF5=wKQa55}HAf z^F3YMR;ZR^JduF6M3dPNHpl?}LcpmIe@%gzcov)3`hB?-`nHi7yYhqS%{M$Cu_}7) zj`XzXkJS*&jUQYE1p*bK3SC!o#99~v3heYAw~qf@9#mvQ1mW~o6-Cq?04Z33%gKdd zgzN6EBu6|7!NN#QgN*sXf@SWml><6uZC99K&sMs` zpp@_~sa2vJ5?yAbzelSPpm&A9!{ok1Col7j_NEXN?pe-n-s}v&B%SbhQHUfK_v-9m zLa8e)x4cV;{miM8c&DJCwkEv+hV-oxeKaZjN`LXo>Sr@48J@o+nXX25)1ugrarNlY z{)W-D5rN-G3G!2r*vFKUFRe~}9;mf<8b76beLlqzW{COkqN^-+2RVh${7Nga>X*O* zF&=k|^PGXB>&>++WD-Y{n8;1gv40U}@NfJb6>HXJM0qSv!A-h zCo3UgF24i_y_t^cBQbtCQ-PIZsHXRH^TavEQQHlOS>ezgK&y^D%r2zq=8o-y`1sLe zJb)gyLOv|R>M!~ebgyxKJspPZ-rb_=s1a+}U#uW#Lb+t249a7UU#{*j3>v^mn}1g} zeog4pS#ejQLlL?VCxQWFjCa~Eb8=g_$@v*4|f-o4W3a?cfDqy0Hrp zxA{Ir+xR&_>xq%0(YIP~Yvj2kW%h2 z&EH#ofXZ9A4dao+5kyX*EFAvO@NiOyIv)xm@zug?620^G%*7zzh&KAH?s%D1$HN?t) zXoBYs0j7k6(h0^$^*0HB$=-Tt;~nB}#sM$!-jXKOE{ z3)UI%h1ID{S8F-W+gIu=ig0YKcC=JY%co$WCq)d9r^Qxzcf|*MQ)~^tKI&vj#jkYGIBL}Pp@+R>FqYEzEF_az3obV-Fi?u{!713 zZ=C=^iB*|3AxAeI!)*|78Cfyx;@n|K_3|{)eoMl^REbhM#(mgi1*N4iX|8A!AIsVHr{Jym6r;>}NwjbeHvu)yex(gUOdK zqMc2);DI2FGiw1+vqijFay#-OYyHxg|F7-?L^#r3ajL6wIRU2Nr@2dYKaIg> zJ~tf-4T;1Y!Po=VX@IJzOrzK0`r%)-3ym@fwylPuH>wwxAQ*V#V^`rPj76J~>vXO> zV=W0ro5U+c16#xFoCm;FBt{zAcg>s4o8r||M(48m{kC5ja5N8ZLYJEITNk6P3wTHv zqOMaCmIY{o+g-tKG5|Ey{(jaD1YAoz!OB=KWSjjPzD%iOCu^Sz52>X~j~@KFd{qRP zJLW53mg{C=A<)Y5({K)Eh}z+Tf!G!%;PmWC$t`PG(5GXdFmlB~iATnem(0^OW(b2u zQI>S~b)DwA@N~hctxng%*mUpD&8cGnOe}iwr!nty4tl9wgTn1iX_#Eu+n533zd&Yd zaXxK94ibHIHtErM@aT;EvKW$;I)AOpn5>pi&K+e39#ytsz5O3tOREAZY7+2&aOwqw z2Ud;$fb62Jw`iypzyPys7b1faff7*r)&<~CoNWCHmh3I*Y+RY-1Dsg+Lp=%^g;Jxh zL2Z+RspV3Mu)isReQ+#QppL&;tD+6H-%0qe;2{F5khosNwQDhGQ1u~xjnx)tj?^Ad zH4ZZ4%^U^%Zg;g&Y+@XH3bMkbbeP(*DU9Gn<#3aLT(VWXO{E(*Cu^8o&FblcCfx4I z*MMXMq{Su1uhq`?6om#lR2HOgmN=9r_#&qbd9SC+VxrREy3RcjQ-yljRd%&ys#C(W z-_mOG7)!|PqQ|LIaf%1xwTMujG1_Gw=z-{s@wKo` z?P&W*>*J6c<|N1k8LQg#^C5`oW5%lEEp<{TdEU_>SdX`V8>R# zB^Kj#GT=)?YZJtr8FZ+#=Hen?n%RIdTa3`Nsu7{KE+J$5lpSKX0j{6HY?JFU#8c^W zDme2_r?m88`~)kaj>TXtE@R**7>X2m&W-lk{(9?tD8UgvM3B;(`vo9qq3eUZ*@4{!hU^=Fr#5kVvQEL<#ybkH$D|SA+*A##xi^+JfNn7>J% zl&y4Cj%Jwf@o53$JX&-VlYxGGWlNGCEn&0`jBOY#1vnTS*19mtN-0!@W2X;23yd?B zLGfacYA_ijM;zmfiF4W88@TzO8ypmftsM}bc3}t$(`P@l09pKBr;qBswDJzcx>IHr zHgLFeVtz3%6=^O<-c^{G-l9VJOT_SE`QL#T?R))bDEp4B+Ue4%;mQ=vJR{AK*_ZEU zopxo3NY@laf1$~L!$u|q`csGnZrN~j>{K#~WnhpbmNoTU#pL;!MDMR2BCi`es8==W zu2?m2Azf-00!Ec;X$Hk@j4clyEodGe-30G~wVCDftW08AAqz1NcnBP|u)k7b=4-{z zf{LRK=6itfLlu5}UBCAZr|yo%+-J+NxYCA)by%Hr|BWPnTUWc=$xMD)izzVawlmS4 z(N!s|_L;1vKlCOo2l~&$iU0}^9p?AgV?aG5s0s@10QfaLIMAuo;8h8*RXjM3n=At7 z`9sMtx~xg6CV?~uy}jy&jreHt*Md902aTn3^c7t+{<8gTlIKitJFQN?H{wc^kDWa{ z61GGjJ8rNx>HAa*BcAcx`=eZX3Jg(`+9WaX&}=T2nofP>ko61!?SN5#gwTw#AxJDl zpjTq(4A8cNQ4dK%&pJ0C#$GtWmc?yHxRsvQ0e3SP2xghax z)*|XdCM@U2{H}tn!5Cc#-pkiHM$I5~*NX_Uwd+V@V z=@iG9Zx`1k9?chJntg{}zN;{?-Q$}jm0$W?TbJKKJdoniryN)v$ur2j24iW*#8i|! z25f$WbSag*V6({R-Lk_T{@g{1Y`@I{Nmk63hXH!z(u|uSbg89?9xzih}L|JRM@|z zd<6Ufw1yY(NT1NuXzCTA7AM&!hCfP@qzoKmr}|Pkih79cWSgT`L3ZiCE~$010j_(- zoNyKH&{6L|by|VdbkM=)+Z|j`zKW7wAwlPJIyLkakP$?tn~vg;SQdI;Rd;0k6nc?& zzPQ(UHXXM=2n`VyoU7OhqD z@Y=as?qi=XWmCO0_&9%%YWCNFvlmIh)5+N=hBD<-IP;e%t8i`J^FT1xu{`jjuTE(`@OTx7m{7+wXv3{ORctZuFaCOYcUzvklWA*R=Y6wn z9ky_SZlX7^OvIfYcW0w*`Xf%aaF?Zqt^u&lcb{I8$Ep@DR2tJDvWd|_XUv+VVT>O3 zISNWCVfAxzPnslte&*4+6Rr|v2Kmg&&VD#!aub=`>%4Z~5^fwyYr zK8L1U#?Cd6B=*(*rvZ2qp?L~|p&+c^TGMGHi*>s(m8oRuj@*4tr3bO=q_rT$_o?Z{ zJX@-|vViz|k$AC79k~1fe_bJbeh@&^JGeXqkrr$QI=8WKiIfF$xsql1mnfT%9EiBF zSQK!>31Y;#>9G3883l?{96PHr2{n`j!h@F>mdVO^!sSX|U?K;c^R5=W_PZGGyL3am z&?!wNq{?dP*e;*eAK@My9fq|M2Wh-?#N>dZ?Mmz!R5KL2Up5@;ly^WDGzOqUcdX5o z(=EZmw--3eatc0N6>oN z)a!{-@z`FrckSo~pOT5siD4vd1RLF>#B25S@TF3rw4piDs%T}mv}zP`+rtN^@HXaZigt}v*{^%cE z@JJ)P&G4&)eR#|05s3$kPaMK*r&{nVhe#G(M?-V2lMDn7%ep)@O$AF^U1mjEjGot! z37!?=%uswfgFdcf|GLcs*Q>_3 z^jUmj<7r^H*+6Q%ucd;ySr%M@R#ph`J|h1j(ITOMIyYca<`7GOHCufnRyOf$EH$t} zTr$BKWsb>zFtB!D`L?z8`LN1h#g>nnXx`poxbE5p=j6q{RAf9*OPPvX69*QNBEJU2 zkyOoaQvg>L(hP|2?&uJtCxM{U>hINtM55Z5B?62}{7EsX6>N2d6DWKVn+(Jyo8xBZ zl)#n%-!`BdT183bXt9Vdz`hQh(>KmM=aJ4Ff^tF4w7u77agmRnV%Ta!a6&tKwBuvL zzC_m|e5NuS=j3t0x}I0a#ir}MC%OcuY5gjRS`(3~lB@fj zMLQjIUo+Rk{P{1rVI=VbSAwE^|91jxjH$Y9u_}NAyZB#XCg&4_W>>mtT4cGU4f1E) zE~}Y0qovA;uTDWx@LWrZUO^%>r36HJIc~1E(%sxpeUYhn@)Fgo1GP!*wW8z4!S-isV@JYNBY(YIXfw8}v>Z*0#( zA5F)BQch0IGhFb~H4sYRYv>R1G?X%mJw5r7M@z0V`cT2y)z1sL?W&Az$U~pG{m)KR zIBqAi5QA=S6U)8y$!B{6{Dh>4yKp2nprlym8VkQ81`r|Y#$3f_7{aO(QZMi{l6I;$ zpe0vB6C+pebc)WnfX}(6j_Wk@0z3UPN5naugKZ9#Mmw;9nrs^gQ z+q^89=Pr5Tq~UjfVB?BY8-ktADF6AG{fW<>*D-q~`3^;KKcdBQG**-}!omzPCx=!c z#&21fU7VbpznZhCs1w3*gH~45W4~xF#vV+&2B@rdc6WdJ|0Ufv`qNlh(TM&@0sh@O zjdl=pXHa$amE(R_YS;lm?<37trfp?zS}s6->lhDKqQas|QJal&KP^N29Qz*dtYCK& z^&$sqM7enBS0|$Ee;o2WO*#B1S(I_ z(3a%J>?tKF>DOT~?BfCL$Uod<39~FDR)Fvh-ySz})+u^b zorFP!;I!}*>R5Gys34}~W;pAKWR<8F(si*-KK6uUPLtmkCRwnT!R8kFECW=|XaHjP z-xx{Rw7$F(I1)ylzsqCj`%+uFFY-T}TRuv)5=a@sk>(T9dB`nz{`xu10wwoODf9SY zH9bbC)I;mOm(=-Wb3tBQV}>3&J968_tpK=ne@>F+Y=bGu#6A0@C(!r);CO-ZK7&S~WrYyI z^2mC|7%^=0eShP>yq8{QQsOv7nXRz%$AQXFxq}L_y z1*76MCkTz!mJ?I?g6aDaWAX?~?IWymZMm7)d18`m#b_2+6-cjOpb;1@RkB!ctSDkL1rtm7!j<8u&!Npb2U8tI;WHr4$*qHJ1jH=(3(_G$I5K@JOw7+)Mw3oy@5b-p>AW46YEGD<{Q;%3s zYXLLEw-J<$rLR4zlb2c+C0FO~Ku+5r&4ljL$ixxzvR{PUGLo|W?pYYrOkjmKC$LP% zP=xZiyvT0eh{rL@L*HXmNqF7VYeGqsRuHg;1OD2PxOJ`>VG$0;N4=aS$ zLz6|?@{~rawdYOym2l2of6XBUVG024-hi=2X}VMZ9;T?Gqo7wuf&&PGos2IR5NKU? z3E1-4eNP>AgR{%=YtHBcjm+|4dRYZ2CP-(~epGzc;&TS*LfI<2y(F*5Vx8jsqOqgr zE;(dqdSEP_RgPRV4908n(UdQ_^cnhLze}Hc3VJKDj-N_37FR;Eq-ZyWsg-)~Ie`4K zfugo@)ap@t7bfqDFcL2*I#;GX6uZ|}d#?rzaVQ=!htg&sUgOpS4vR7(B(7kR;R4w% z%~r{e1GO*SI5?8%*Qf5K(MNcvw8q-k7{k`}A%C!22!;VFyRb=OWCy4X9#f2DO8}b| zGV5oFkGmG=!2ECmYj@b4C!#~PiXrPLO-a#EPP@a@TXr5 zS^pzHq>BleknsIocbU?|Q8ZO`Wa@1vc!t`NpPB3K^*zY%Wadz(O5&EHw`=TjI~LLVcWyUGKX z!&|-{$gkezGN4sT<3`|#FN7)|Wl!i*0{BynBJkTY!v~*1{nC%c>)Pp>I2E}1XNX^% zB1p_xUD|Zp+5$3nXpLxaw*bFo(YnU5Gb~@ee<`)s3u|>vP6v*+2g1Vmp9S@#gii|R zY9QU1UA-{mmZXm@5o0Q1YIaD=5&AZXy>h#m3-(Di(-fIE4hWGNF^KYXqc_BURHB?F za+NMDS1-8>*)B0ZLD0Qg(VYxQuu*8ZmH}zm9P?Y?F&{2UPzUF5O zgvtz&#feG`RU}C!&Jsx6AC157KTB64Uqj#amohQ$W>T*>P-g&GzJR(jJTtHLN^euj zOVyJ}Fw1?2MmkGv1EsPW4a%KcHpD-w0m5zIUyhj0VF3SwB8dINGEP+yTSWFf8-=PsZbF!<&mhDFG_-jNVN3h zQ2VTRZ4Bj7Xda1YYcuFRWMS5a0wCXZ(l+Hg3t8fu(*w!||MgXZ0}`F?mH%)Jqs+W* zfCLdAUey9B-}cW5@7^YcK54r3vlxB<#xQPorWr8Ky~hn8f{}T2s_?3B>;C~E43m=> ziQcdIBOjvraer^|$cbTrVeXM&j1A>C)y1Y_ypW?ql-VbA3PYy%OO@;jk9S^;lzKxE z$(+^nUW3alg4^9ZEJ}ZB#=tOJFd26HTlA+ZttSV-c>H=cwJ~&*NmzS#uz&t(%>OQi zNeAJ4#rU{HO*Ux2_w{=+M{fF2b?RX0bLeR4(-@f)^`Y|O_08HLPR~x_1b#4`8lA8`W_!yuX>fcug!hzE zMZuKSXqe(VvIX4`Y)ZhY(Nf<{J{O?_11bdIc!JCn-a-6m-ZBTlx)J*cT@7Zr45ATv zM*z$-15tv7+LZG;;8wzBA7Df+Vx}{1l$4+ys^1b02b>xP*VQylirG4D&-<@bszjnb z#lh80^@r=)h*>BxA7nJiN2wvPr}xHWM1I-|pN#9K%4;oxdwByQ5gQtPr-%{ICo4BR z7G$wF{3uQxJtNoLOJku;a$VApwu{1=OIV+~$24Mgq=8vzx&%WF%2sZHIAW`LJ&cw} zn~edPy3t8xTc91>f_5+&dDO`j_~<^o>-O)MVbZ%HI`~lQU)xIB!e%trF2xDV-HKK7 zgd9*Kfz~xZ>W_sT0@m*d#%lmzMxs`l+Hz_kWj=-IsO(~CN~m*cTVF2d-d~b6n*iEp zg`u)w+C(UkD%_8F9f81IM~D>hUvX~zxB9K#525v>!jzTl3ko***OopmrP{RsUynBT zWy)LWji;86$v0FaG$#;8cRk-)e7>B&-i}il_XcufLNP`N)p~(_@-qQWBWoh|3gRIH zvm?XzntX{bWF(4IO!72Dh?_Dqw;Lq$7kd`JDk$AK2?9)>nol}>StIA=; zjMw~`-&DVt^jNA8S*8S-hp=s?h*2d)1_)|suBvW*?XOKy1<(Yi zeUH}Di#3_lGNRHiE*H)1`SEt+nVRhzVJ%A2$-;0qaG#)XgUL81p<0Gw`{cNCy%Z#j zG!Ve?|CulK(s6DeDf?ynC5R zj`8Ar*WmIm{3N_wcV-;+H@>jal`5HG*bqJ%W^U6|;QW0)t(fB$MI@R*sXxQLC)`{+ zQK?dkXkE;=%8FD&{#Pw2J@yv$wnPnvj*eu+)*qB~u0X-+diK)LUn# z&duc;*~@>^s; z%ZhCZYi(OvSeucz0ExLI0ymB|ebX@qPB#nv*cq*&XlDxmq;fR_)Cwj>=+78kjla5u z9UNQ06OZ(HmT{zx=b^0;G_Mr~g$|*^8|n=;!0%j^$(WScW1hO_Lic>fsPmrDb!T}- zLy?=K0^@*Ej=v7P3RNmC7Vi$qIQt{uc@t{NiH-feqo^E2qWKw*%{mbPAmp1<$^Zp)C+i|VO-Rzt0sI`H z@31wrz)R`Bb#|oQ@IZjJyDY3u^mpBCLm@gxD?O2}@Q_FJ!98tYr;iKE`?Q)vM1s!J zI;2=-Kb@Dh5N>DkSoqgkbN5(o%TAGpFL#vEu8}?EMVo;$Se$S`D1LAz8ow3o1BTpL z)uRUiD4Xv-di_QXjBXwC@T=cC;~_lx_KRiwWtpqx$JtWarv;(o8)VGqPtv}spqsH@ zKI=`@+!tS^nyii(=emLHDojLYwD%JnrA|(@$&XNQl?r@5`kY0vTQa7vA}(xBfnqN^ z9>q@SV0=svw{nSQ*I!fRXeesI5gL|^WSzZGZy>TW%AKw#|Zu0$<=ali%hxe zX}1_dx&v zfow9W@>;I4xME{j)uVDVWT&~&ySnV#b?v69k_R6ou~oVUUN7@4rRa@so@dOpXESXC z0ZQ)JO(&#>H0VdEVy+YJB3S&9YKRNLBXlT5dmo`7fZ&QM57BazL!EG6Hk#y`SLd8h z5mW5K^X9ZHHVF1xVQin!PR?F=#_Hu??}2?p;!=5p@^O)tc#WQ;q$m$5wfN=^WT|ls zOxGw<)IMc+jAy(t+Kn8U&~2lwrlM0|GNL>8hpXprXV{5`hJDT7<+DcbkLOy}z6Wi@ zjKvDo=<77sw3Cb0hscT4j5EpSynxVD$-yde!PWFzOVo|!#+C4I6otlX{8B*xVKdQn z=2y9Av>sK638m;6L97f^In^zwFrCX5B)UF-jYP~RkRP}|gQ_$!&sx#@Y4-oOp zkscfz)rXT>V9s2lgP^P1jScr!lMLliA~dmUGl;C1gn??I0}ZZ~=r$9!>%9KMc-K)N zfV<4@?KN17dm@V8kW=~RYi|S~h_fFkN5Q`iD@3^I4U`khZGju_!k@OeTWC^*sIPoG zw|X9!2kXx;WxiVfxYZL>(8+Uv^~oIH!H%!}S9CXU zw);!>)XsT!u*A>*0jxa|b2WbdYYRBD0s#^IqpdllwppWMrFM&;q5vq>@W<$&#|o|v z)0B&`GWg5KQ=ALDb!w{Nxxhm92Z?%t@~D0{zHHo_c?2S-P)lIr|%5r&*n@1nm8WFv6N?Cm9E+0GxNIyD83+xLn zoz(|@sa5nvm9>wp0e4xWOGdq}<^S}w%bl8(e=Ns1?mB>Jmp`N5Z-zQvLiCWrP9$w) z(u;$Ovu6aR?s+F5FS+SOgPJ$VJ9W+8jwR@i{HE+{1SSf4?H|VfY}}vX0?=YKh;w)d%k~Idpf!R z4!PW=m#jM&Rl2Y#VUP8?jW$DEk>nJNTIqW)9DzX-qEvcyOAOH#={A|>cMJiOSah(g z0bqaMUypv{_~vXHr5JF-0mLy)ihn)bK6_WOm*s5t;N!|6aQ7I8*K5`@1z^a0x-}j# z0ZskV6(%o=1P~C`nE|TAbF;F_0Hqm8$sdzY%Cp>q2ClsI7YWoV-X0MyW6@CDR;Qrq zcA++|nh(mev-frARa6g+NBL-Cd6GBaa3~)iaW`Ozw8dHQw?wi4_$Pk ziivEPLk#&>f$T3tTCp!{aiW*>A3kEhphjbUM`X7KfTI=(kXzmp$T;JpYv@O9Xo8I% zy@sH#@T1=}C@WL$W7GLN>RZBD5=!?ClU|2Rpv%>O8-z_!#xD<_nfJ8zNko%j`87~E z$w)F(J!pA(eX8%}Gw4tw|juwrxJnQS(J}V88hZT zRDgzz;qmgAa>q67ih2_ayp<|qhFiF7JXmuqLd(tq zh;}*j<`v94i8MpS5f!N9g^R{QHLYO4bH9ri)T_T!hKVH&6|AUPmT%O~;b^#`fd9eG z$h8XT#;6}!m(=07f{UyUJCqhTktSG&`_3=MX8x=ucB&`o{Y@czk-q8}lnr!qyv7h~ zh;;anNkkfQ1@WZx;R6JaLox;hD`GXR5Eu}QY$O++amaKcV}f#~SkUB!y!ey2 z7*dN^{)%BUh&>~e>gO=^psDCdKv0*mr%x9eoY8}2oRg3IEeoyicBoWDB5@oK7+o6W zNLUVrzW!4mpf>Nh14i2TTm6zON(9-4UFa&%wbe$9u!Y1RzEsEuh@1J08*|S8iC=eW z`nSqwtH3RGxdvTeUX<@F1f7@`j(ig&)7&~#4#BD^2jTb2W8=8l0{h5Lq|?-(Z}zw2 zI|wTdn6GRmFh|Ak)*tmryo=&60M{FnCH4f02!R-hKZp$S0+P58*@jJnDr=-!A9T#7 z_uFIm9eyX@5I?mOPTdUQcKuAEWq#2QQ!eeVY9=N_eIf<$Y{bUcM8;f#{;Rhd2_P(9ShrO*UKxwVL_{mKe z4CuM);L+634ISnU&($pAYZPO%MoO)Zhv<^9iHFB!tiC3Wq)KVM!pnn{3B|)O|2HIM zR|ln%SHSb#$H_PC+QL8`+9>iplG5${k++ReUmw^$l~BO*>th3XyW3B(rul<0{bF#w ztQmGlmoQl+u>TrMWCIx)pfrS-9fS}WJOyHSo~#x*w}CMj*6%W$k_X1O2tpnr&Aot7 z0i{~(k-o?;<38Gf>njWawNMS{ zbtw7AR5DgR8;^E%#OelBoaF&-b{s>HDL-SajAUu#5eK4^GECjARi1Qtq)Vi|3A$8a zL^@ZUdk9hS-AX$D7pxBk`S+({^wDYY2UnqUYE_S77i7C!?{RJo#30-njOnweQ`wc% zsZRR1QpRLzPKp+AfR~_vrv%QKyx)>*e=N@WMm5PBYASRwD5z4rrQd!X@|KA{1dNq| zXjel*tRyUzVL8g44%ZV$>L|BgQxYG?XRq^bt39y}crP`PJ{t7+XCl=}T1m9J+BNyY zg)5Wky`qXF`5^+_<^JhGm)z98&kgD(&lf3y0o zjwh{KjUDo9x680_L4?=!|MM>f$PDn`qJxcbQ<*e)h>QdzyImVPzE zyR7ieyk_040%Uf4ATK$4=H9O|ePQOw>8*nKkblYY(t90x5WB77=sdoS(A<{)9|CXIXS zu~^^XO-O`)sWP;p!FZhb0eJwgrQ9CSDYebiD2brP0(Odjz(Ut3@Ro1|iO(191SDCw z>=bb8&ur6L=8LViUo%ui7ikOCvAaL$>vxemG)(fw@+~5MyC$uymX`))7&-d{o2qsL z+l;QVbq-&qJ{WZP$6&An%N1~$3BZVwQArk6JYI^#hcN}EwT8|O-K_CX7=bNb@aUGs zwc$qx07}kN=;2#=CS^#%eUyOax|cyh0XFi<%o3A70^NiqCq=1P#m= zo1&KR#*08XydW%!Ha$U>vf)-q`LjRok5>|Rxo9#3=-=^Ie>X6i_SknJi}4IS&4OnT z*kA-Wq$X9PZd*%VSvs6M*COMKFSrJaKuCu;X*8PU@!~+ ztUCu8^%Y7*`5Rb`mA^2=5yY>spn6kf$Xv_kb8?zEXIA?THKU&pZ5#zYav4`%8WCZ| z0q|I+d>J!9!( zKxCg&x19Og=<2VtSin=Np`jGOsz5t2cki-xuYN_fZXsRI45~ba1l9eGG3qoIycoOS z{Cea{sb7kYmz=>R+ci7Uu1WCrxA&)!fbY0b`~6j)Z$~i>+~FUFbLT%_PBhVm#l=wY zuZ6ee6{ZRUEhY6di!-%PuX6qtkT|P*Y9gzCQVDHTYNyMMFf@k`i@zvRh1d1t0HHaw zbQloKpLd3p$NqNs9gP&{<^zn0RZVjuj>Vrv?%^th;|0)s=wM3pX&zBIk(!I*BDR22%60?NXXe*H$ZWVt3AxHtS2fLo#pDF8w>F_t6EyxaH*D!F1gK!rP7g2Dkx_2Sv0h2;*8wQB(yD+1;*Y}3sKhb zHNH7LM&R&bj?kXTmD!ZwIZZtzNV2f1U3Kd)a4?FX69BZ#4ns;!;gsl%IYYT++HKr2 zb_2$%7dViztcn?yv+7h4;J#_Iv$m-6D{m#^F)B3=uDa969Rm~B?XiQSg)q=R+P7Kc zHcX_LKcLn%Sn$)2g#H%xiAj}Ao)vMce1P94TzJZMYUYMaTStj{2{}!7_>`%}^NOVm zo?Wfg}#9HQ6Ge zXG^~SA6H))6Ijq>i@U?%GPt|DGq}6EyZgo6VSvHiox$DR2N>Ml-QmrC`|`5;est2w zt)ze4%BfCQopY*5IbDznk*BSlmr7V?%XX{4VrjWD>yWRIOd;Qz@<;(6Z(j9kq@PH> zTz@6M+)%A?Sc;?ZO@G$V3Mjh3>x^{xwXj?K6v#vwsH)f%B<3WvFZ1A4{~^C8{_QVT zvz7QZLvciz_sj}97-mQw76dsyYf2z);?P4=%fRoeqW;L`*9LB5MuhGnHHvvQIPE@( zCKCY}pIJvmq`uL|GTF5Q^4LB091{Ku~m;EB~(5;~;q4mX%Yr(XT zIxJ9BRARa~LZa_cC_*g1Cj7=M*P}1CjOw^wY$!GvpHKSaQ9<^5dbjrdMfU z93o!~_I1#u{0y85bS|tWlenA$2a-O1ZQ2$8!YG(d%_Y^?uznhFmpZ@2MdP50!4xG7 zDtE3A1oeu&Q*jA~YJi{@`g#k^!OH3eLMx*%Df-iaO7|?@gZ{&&45bVGSjuyFyyMkt zffgFjRq!31#rDGQw_U$oP~V&N&6YC(eR{d&VhK_?#kzPVqx8NJ+q7YC7CofA9HoDP zv}gUkr>7DShXM?(TQj8;ufkg6dh`q)F-_c^rSft(@8xBa%Ot#LOz2 zpALSTaI;j4ZK^)(3TQEk6_m#4dJB56y(nCkXMb~o^q~WymW7+!yw?RLdA$S#T$;b* z5&JWq)3-Md&9re=IM8~UftOl-_ubDKx&XnwWF8EWMRvXO^bfj;r}y7GaJZ4| zijyw0-$h?QFHO_3&0Nrii&@tF_vl$YO&g@+2nK1jjUk`CRi2Ke);5N?K zI9gk;RuCRTYhu`uJI54Mz5iw?qOz@=@Md0Obm)@-DqSLdQ44kon%~U;c7@=`w670Q zs43-a&J#@NZ0`lR&86fkCU z$!#jN7OEMp{cAy&8dV&vJn%|kDE6FeF;*n=@N(P1Wl}4U%sb1C)EYq zGf1tcL*8?qGnVua0KdL9BS1s;%LG0WxUUd{K zKjt6r8-aJ=b6VRZ7Zo^05Rx^iKicLYAilqUg=q?@9lTX`_tgW5`}Y z7R}Dcuck*JY~4gETwQ*a*0IHNYROQ<5S&$BFKAy2i;46W_)YXN=>W58AC`u89s51M zLOGP=LcE8ZKy`B*T9eFrZv|sGY8=jCFs|&|=D2Zqahs+J@k+aGIq6IWdx4FSnXuO4 zF}OYestbl>8huIhWEGJu!UIcAD!=Is9GLS!puYYPmh zW83G7sAfm5*grq3w$*6}Fgf_yBhug|VCi%+xS*_(*;TANZ6^ZcefsXsO3Q68-q0Sx)0 z`SHcS7?0_M#sspx^+i4qdMS?8JPO0*4n=WZXn-!SX$>_{aW1?-OfjCHfasrS>1Woh zyqxpi%RWjg3!H9aer@1Xj0-jh+Q*g*XhS5Ci%4OktJxLh%I!p)EY=<6&Ef!&MytJR z!1R%9*v3by%>Jf3CCtD+Ue7d_NhgAbFI*u7*&XeTIrS=kOFQT8;%-M)Gdyl{(PHuQ z+3p)@5u1ty?3LzyR5%s?;-!f0yvS02d%h^G|+1XV~J}8Sd>CrT)xma2hUl{vfuM8`&4Z|LzCZ z#NOm9rmXxz7cLl0Kp@xqJ&w&lF_iuY-6?Y;66&(S62~Eb`o>KY{Jn zGAOW#dyK;7s#WLyH}wm2gi6|0nSBalz^Zm|tx$KHaeN zcQc;>(MIenA%#Ps#jzs0Yy0fO9T`Ppy>^t2uuC({sFD~1(5GAonuy+@#{2&qeh`D( z*(&S4Tp4~SAI->`G3wI|8Q9w+O|hE|oWZ(ho^BWXU!7n3UA#$ie5l*9w}yhvCUO zy4s7JP_ReokQvF&5qKb3Jo}?NL^1Jc*mv4dVNg<=&la3hB@9g(#@75PX>^KkX^EhN z2Y3GQrv4gaBbXn0#?c=3Gw^xnjSPJ&<9#A_2oaKqgc;!7?aPXtq|Lp-S!37xM`D z$mRiz92+3YC46l9vaVwh=Z^Oy-(wpE z^CcIMB3NoQe8K;)%sODflMQFj=;V91$+U}jS*{swk49u+`v?5shtOO=yf7(N1F!2c zIInP~8B;3K@|z-&mxBG~{a>2QU?jP2^Fzy;;kMLR9H{5W4I_2G%AL*^VD)+cL(t^q z>i;YLl`iOx|F`%P0qDX||9uZI4Mh(E`|s^(IQl*0e+Xu4Q145{{|4O`P(VOv(wsuk z@mt{I(0d^WHzHN#&txC|1pTA;i~I}tPaDe0k)D~Gfr)`N?I;PI60qy|HHcwD9EYzm z%uE*M3Fm~7+2H@yg>}3tCnD0kb#)ayh*(?5-wb+r>f`C_`TTlvvopatTOHVkG@FjK z(AF12c-hI^%i&F~#*N$qj&EymSy;xjH|Fi2hrA?eBhd(i?rA>su`%OIh_!+Lv12Ec zL+BG;>;YpY>Aes&1ANwq3gN7OizMfZ<6a@{D91vDVao#h&$){a}aBo?7;F6p)s~V6%V@=i=*53V1HK4I0ipr95nGum#i1 z35AB~h$mkbyOjdThT`FOe+!GON?MUKs<@IeUk^H z`M9$la0RB_rJV<>5|j(HH40aY!207@K8>ZC$Uha&y%c} z$_m#jh0<}4mnt#1Br<-hxMrVuz*kd(duAof)2*iiGK=g1wA-{%chT>X8Y^ zc$Pj)oE~YTGBOim0@3lM^GF4%NIE#n^F#ZN-Gy(b%YH8#n4#J7~$c`aknL|lXO*R3nb@l<>ZcwN6lp-q>k^_xpn!Mwe1 z9=@-XxU|1%w#j$_bB)d+FrK;ki`$!-m8TWzjt9GmsrG;ls2y)VKO`ubjpj0%s$MI4 zqkKddGlDebvWytr!f&pfzWeN}F zk;)!oMOzuh6QN}OA?fp%wM}!~jat=i^vt9@=Ur4vT2a@4k^9Kzj(4$~8GKoY+a|0P zXq(>F6CLOoE*;Mn5l1R za^dLo9djQ5+PRch2`X5p%aPXJF`TOU>oBxxG)8$76zy#Fx*0M2DW`IEK?(BBH32$3 ztTtKnqA?dqEQ`=O_rsBC_n|L>2w4I@l(3$h8qyX@Ysw| zVCR;8*+GntLuKckV7;(NhwCjNfWVE&#oCk6nkHGP9I?^o*1Ps`0ZT2y`fX6OdaKO6 z5`$S9?1v7iQgAbp2(#@+;Bl@9YMVO488Gk|AcWoo>r`YJ;csQ><=Qy!)%+>Cfh|%W zS(`w*Jvj!ZM9bKkek|>~2vS>xP_i(Ju{Lal42eWW`1Ug?7oWnDYC*S1@(bdwNCaiIKwMfpHg(K?{+F5J=K!`B3TRNGnZR__$fq#ASQ ztDY&M@3_%{H?RHD^nolI#5+TRsAO&F=e`d#N7W;aZpgDYD3*5U7E@uX@{QJyDOYJZGmMryw+6Sj%l|729E6H$>>3dfuJ zfo20U$I-WSW|wdCDt5@SY!@>$Z!U@z4a${Q&+8;M|8S}>^XSmX0J-3#HT=sZ$nM?l zXuyraMwgaU!2MmO*RqWjg^?Je<{UsV{R07BhgoxT=Qsn4bF)qLkD&PcWs^Ii(uCT~ zi3gr^DO23yuKVoF6(8b1|Ff`8!NH7MD%#=BLBIIv@O4RpRc;r=V2AIwHs+zE(y}R> z-e*av(zlHn1FeuIM7dk)aQd-9^bY8;sf1$T0Go5VzLX7_{^8X!*mVvJIpO_J% zw0@|6-~OQ*$iFlG2c)HiXP{I42ljTBqy$JgK|p5zor(9qV*Us0DT|9LD2p|9jb!YN z&X=@Z*$~T%Mi0?}pap$rgH7s%LT1Zv>U;%lq-n%PkjTEY_|!5L7c*NtlXr1xoY57} z{`0lwl*DpEa3uK9a7M@wv-1@X?ydxoR{e8y#CMed0hhM`oeJNHb5e@vMd)jlI;yz- zXbn#MQu`{vuvhlammF2HOrO2b9K#s4>U+eZ)T*s|Patk35=}44$p2A3V0n4Hm0ol{ z(Cm7ruyNaaKY8)A90D*UIMJd*xL|Ojqrg+~b#(1gd2O3<3KVT1Q8=B(9wP!$gj`14 z-QUglAw8nUo#oa# zk_?5w=HekaFEao1&HD<>VY*+Ia0sjC#W_0v*d}|8s~o3_3}3oPuJG;4*-!rw7GX2B zurasd0`_+6wvU!_?1DCwj@)YS7P73h@tTD#TVb{?t zLPVpak8EMGA5y09Ny#Gpxkx!$MHRF9w-R>F!yg(mH_kwCEEZNwWQ+yf*rz z*&fZKs%J*4Z2ib2F?{z9eqMEZprSdP+iI$ia(JfIy4mRCIR;F;G+_E_f)qhqSfHN= z+q4W&-}{A})=3yudF*MJBkL$UUz zj^Q89;HFcYztzJeV?G0zLc`H=rI%MlXE4m+==yynX>0qkIk4n0saCVpQ(ifyeBVm2 z`>Xcye44RPDBT z0Rhu#d3B#)11lt&*EAq}>xag_lCu^%4Yh^v$n&eJc-wPt6@`{ToiV+wMyc zONz$Q^4NL2fc!S0l2v6JGeYVX{aHh|W}_K?4XXk5R>(>PTWH-}Cxy<^y0q$#XZ%Jb zXq~w^HQCWf`H-zmc))B2Ctu%Iy2hJnj@T6I4e2?2hN~iwOh*msA&7oT^}>NxtsXlm zLzKV^_j1^%V7}b(F>6PG)UUzo`0TjtBtVXEP!xTbk02=`$o>O{lQ$0<+i{)?dhy`( z&|&(mx)DIsd>Y$&9Fs@(F=R1J!A@&nI^VJ~Y)EH~V^nE1zsvS*H7p5U&%8hlGw*PuH)4+X z3<-vD21-~9@!+HFX@}hn4yh1d-^hKdA^`RCINAcHZJohj}ksABb`ZshXSf$+ty(tcMiGd{_2T*mqFh%~Z z@kQ(AvY)tVixS#==Iwkn+jEw^UU-3VYW4`Cpz)D>&!p;^+A${|=G#;GV?=Xa^Ia5V zTj(oJ)9G2!)6{#1-e-EaGu%#4gwoF9qfG$m=9|9G{oaxZ%v<7GsQp<_Mr*Py&5Z)f z#H|rUOr_CZXJ^XRl7ffacoF3Y45!`7DrTr_?IgzGRFX0 zC0r!~1bN&IZbI`p2j~q^*E4@PT0_CgRAjrIuvfh9u3HKYC=(m026uT5E*!tj2KA(rE2lWuz{QO`tq&zRC8 zrhSk2M}tG9hR>fou>vyYkzXsf6PD7Y{Dp73i1@ZwnAQ<~7TF0F&s1cb7Q;Yq&)GP- z#2ndms{l3*)YY#y%eie9tB?%y-F^-a(4a}F?HVUihwR}k{uc-9oRnJ7o>>68;-Tpe z`?Je}*Eh;JVLCjltiELWZi=^4W$ONj8VlF(q}jJwHMeIC>`yLVDksAS9&*UTbFk?H z&2b*@UmSib*zRvQtrTR%*ynbv5*`kW_qY0ZMalkZ2w=z>9FM(+s%^)%qYiQ z9lhDGDN522v-Im|r+#Y>&&9z;klB1a zpJ-N{R6A&sm&}D_Zxtvr5w-aPPo{;%ze;ET!_R`nxM}YsIE&l{iE(Hd@!7d%Rr<;V8=rIv^#)mk^KXtBvt*9+Dj3+ zaK5C|DeC5=N5A7RffxM5uO8Wxo;-U!=rJro_$)D|8+3{zG+#?e&7Md1$&E8|>$L&L z^f13feCEK@hw4v>L=WEgP(K>^C%3Nj_?Q)Ve~G~)k3C{N4*#H%{OXY> zP-Ie-x|Brtl0^ji?FiqlL{v7%Yay?(#R3bhbFrFn#AF@ZQLAgn(4SXI;$tCMYlz#` zh_@#edvXik=yBJVE z_I|_Ql0*3J(`e~)aKOZgMYhkuDa3TokNSc5@iWb!4tk?uW|)*>>c>4;X>!xSi^Bv9pj4R;Sm!L`n$rO@O_>{J=wodmnQ6T94=oQ32zA<< zo;iGTj(BBlTP#aRg%LCQIu62YtNyu7YzP$HnNAR&X6EW1mhgZ^u4p|meVw&} z23w5nfxu1m>KA1mVsSj4t*c;L9;JlW)t#dVzE&XTiipE#a2H+|Vep28k_WR8EZn17cgNLuy^ zyIip!Co*-#i$B7H!#2;|dV}?MG*J&MvIba}K8JM=?|v`tU$?l0%za^xsg*6(`?y)o zVG=j0EIBx-i%dts3ijgVvIzNqQ?{!M@E$e`Eu*;GMCwv{6tda+cWO9DC=JPWa%lCQtaeR zbsCLlw%3+C@|~iy4k}NP7f=oeYnOJhCWl45WzWK2-@&3`EWWTEzuDh?zko#U@2QwC}eZL)d#TR&^fDOgGj-@3^6culZ}Vh)~6Hi2&rIXsFVrU zD`bOS``>b`an!lp3KfF)>mNVBL-Vj_$L(TTpYVQ&B2GKnW~GV55P2}YQks5D!8fnA zSL?I3(6pS~2!O#D)aloPMjZ!ZI}s8~liKo(iWovL%9fEWB5ip7#nM&o5C&$$Hf*4c z*dH4b1bVAeUY>^UMrcIDCcitINPjCgPQ7y;OaD}TDZb#r zFhV9OPrq@?2Kg>QYZHNb4-q(IbC)R@)X-1sTyjOGc_4E1qqu=&N9h#6u@F63%|2E~UOL|2_xV~KEI;>FOxL4#XTtg$woXCq~UjiLAA4e*Q}g*r1S)2S5T1gWGxsflK(jKWPSw)Ez81GJ( zOO*vKRZ>iPHN;WVF`&YBys_jZnZ-bIWozflJg%qb(16YujoDCctYUzs1p8(z@q%MN zuOUqdv-mNB!%^}Z$gds-${>*zRN7gDmov)Q)(G%s*lv_8)^R*;>VtWSSUlNR+ zk-=~!-{0Gc+X9*m{h%FwU0ZyTuJ76|Q+}qU58MPr(7l$hTmYuAG;k?ocw&rku^TgQ zZ=-5{I_T!m?w|JX+uJkG489UK`!Yk*;e^q7O1|Z(YhwSj1dx$$`>f%*9cT!93B!Cj z+wY}WUl$&aXYQ}UP6|>RLe>xr)10f^RlYu5CLSv67zJ~y!=)7qi0W+H~yS$-~Df*lM2K-7n1Ki&DZ#bM;kX|_58K8 zSJ0?<1W)$5!UMnV8jMs_Ss1`_^Pvqk^$;=XBqid%#5GVX{!od zdHAC8KBJk>Z;~4VUymEWY2CkT_%mcvo@d@UWbe~^Yw;q_U-ZmFh6EVnVj3*U14WkM zXN-RANFXn_Z!yiSFxe&6G%I)7$Z02OI;L$ciF+F2n`+k)cksZ{M1?WoS5cBfxtBFnWp1RQ?v93`ahGX1EZ3-tolV!0O3frc=^o8Dl!@fx{+W zrzP}ZMjN+_m^$!KS+r%cEA9^@@6xWKW?f0{J3u{#M+X$T?~3&nQn%&jlbL||B%SBl z7E2Q*noFjSQ0uo!sl`3Z^N@EfI20}mn4`eaOw*x=_N>5?8 z3_xIl%;t0|GJp&85cOkhy_JcY(Y*5EUEfju)qaK&%#M~aU2`o@!?;K2_-lfXIUb^* z?M6IX4@ALI0U z#Un@+y~&t8E=mWBcjl!+QD~l^E&-{GU%MIC1z(>Qn`_IildqTDS{LT}T#@Ua2EH!0 zR_1k0Ml%uyl#0zzAA@}7Op+Iff`zt5d-prem8o0qN|ve48@)IkpW5$D5T5wdhbL~f zo6VRG+Ztx-GNU=1wH|U8|BZ3EK*>FFd&uw=Z1Ng@gVTaR25j3hBVV#PKs12`u;;&TDCw9JT*eSR`XPWw@l9CzHBu3=>I@&x7p1z=dv*&o;; z!rznnT(W{GcXB_=*_oCr&ySp)38LAB>YNq<=Z1V~#Xj+FqMiiYUtP8%_&uXr9l9{D zOgH6rq-e%JR85Ph>%1w4w9bBKB-d}I$N2o7`@`|%!6Ye^do*fr?648{a^opewzikh z&|9??s>ID;M;%*5xuD*e4p`ugK(K1x9+3{vz$ero2?EZ63SCpO_ryh7nr>rW1-n3OI6kIT$9S(kv-X z#2NQIV+buA{b75VTF<#(-$A`|yF9;BnG6%#J)}^}sA9Ra$9*F1l{LznldUaV{Vuz* z))KL}R?QS@i1xxqlq>fvlezD;+tc#B9Ga7$WuG)*(3k+}H8Sj}#Feup_l*>Rw2xGp zD1~1|fwRazoo@zn7vMl>^x(6aPL&b8dAD!ED=jdtztzP66gn@8wD2a8!BHgq(q**miQ{mM&gPs*>^T&Vr+`9ZEpGt3wU@zt!r5fTc&so&-7(g zL=u7MN1jGJ8Z%~aedu?#-0V~DMO*icM&ak3p#!jTE2FQGah|dKEE|h_IyoJKcV-m_ zYq)m@V&h8QUR=92#{K?k%lVLj>-1p6Asj-b*&zyDMMD9&$H{1~940f@^~$l(X~Y;K z&er~i_I|#403YexHFV#;G9iqHpazRe^6jV(`7>w7wg0@}Z($>1O2xg|tU{%EJII7O zGQ^f1RaJ9?jm*e%rk@$)e&KnuN3hL19W$#Jfd(-Rzi~CQy^b;QnUwU*1zVTMQLhcb zV-U19wX3cPk1?t8XHx(Do1&w}(B6fIQR4p7Qq2BVz*d7%74aodZTb|x;oHA|hyqlL;3C^s2flY%XvjkyZdA~Y{ zV!;T`mbO^sq1cs_rr!zEa2(8w-~ZqzO!w>@$z93|x30HjJ*nheHh+JQ_2qjMvM=41 zvz52h0n#768`x8@TvGXd+0JM!_Z3__R{m<4Ba4_RH=#;C!mZA95Dc05xJZM-waS#S z^l#R}2o;428)rFVOmTTQA%}=uKd?8qY_{5R-~o{so9Qz=CcX993I^vUIg`7@|wjEb<5~!~O7&3#Xkbp43i)&q|GkscCySu)dyvf^Q z0$TBHUs(0?-G>* zt~Ln@q*+O*Tbo3K;XLi&6_LzHn28;kkkOShUP z>iR`pi{dNZTQy%c_z(lGd|ybUs1Px`w5$Yi)#H;R<`&|iJ{lKu?igx<2i3iO=+@uf zi;W}h^JS7FGB_@g=)pp%;+!o7;Iw#y;(hN=|FZo_Fttot6dU+bZL>E)NO}DBlZkOS z$atIvN)J(RvFhmp-DramzQTrI*<>8${hs#YTvN-Fj!2*o*o)+c8|==RQy%Nkz{qrs zaA8WzYnB6}5FZK|^kOw#CN*~5$gtsqY2g%M%p?a$sTByOaWh&1bP#4u|Et*!p z9I8WE*)c<6hajn%Z_ANF5kk6_YnoiG1NF{lAG&6~lZLeSJO24C!bFpFz4ObLx8jKe zYW=k=ksIILz9{QzR7xMjxrKY>sjJ4|Z=FZ3$y0k?_4&kVM5|32W3z!9Jx^+tiPx_k zVl1<62dBGv!ge);9Qf5)U=3>4;rgy-VD{AjNw61RFsQj#`1mA8dPEltF)HX*eA!Dd z>kq4T1c*A=Zj-M>#M9tS=K71B@>8wukTn7-A(T5x>5>wLRTr$`j%(ba+GgMazpmw> zaQMv5y>9)pQU8OEEzHq1C)+7B@@;#g`Q>5~b)e(co4rrFX&%@mfTKQuVouet=Zn5V z0J$faoCe?9aD2O}c`FgTVNS8QRm0I!58?cvdAC7U)^s2{PFu{Ehv-m2E%1b$V^2G2c zyy;-%X&%wFiWR*AsKdD2K6-F-Mk-V3&-6{iFb}_Y{hBHZw6r(SSDCvw*anbh{oVMl z>R?1DmIffWVmG*`r~{~5NvRXw`7{?aIc`>sT@aOExGC`h@TF>1^A0fO;4; zWHM<4FB^eZP?fgcrkvlFN5a~7yJcvH`e%uf#ajlfL zrPewFNsJe|5&DHE^SpH*sRBUV|co*I0mM zC(fUPKYH2`{KPr9JWixpFaBJD2>ohNI^KA^kUhQul+Z6Wu2rr)Ge*0#6&JYw)L__M zdt6N_F$1LsXiI^~FEQi}moLZB_;12!fBkgO4o5*35(`a&jdT@LLHv7b3q|ch|!>7_?1O{}_w&IT-#1O+v z&d%HcoesR?jK>XxuQgi@Ta{wBYS_KSRwL{HYb_R@Jl)12_fT`8fY{m8OsdsWLobT{%bY8(ODN`v1A7$b!Z9 z$!z|r0|?Z;^^h*3G6ce7;Y$%a9%PwRoY_PG9+FfOH<}+(eFehV*Uk{RkvGu6?>w>R zsRn4+8CZ{Ur&?19<5{XpWg4_+Bv9XSmh#taJZF!6nA|&$Hu)RM<7bWywtPE4Fin{8 zYgT4q??{RHuyGWSP_`+vBI62n*nf0kyIG5`JfDz|J-8olBY(_1-qZRL}2Dcdubk(c4$20dI_zHENnMiWlfMqUgQbUxkr>>4^T#faB653g4Of4d4) zi|-*0+pkjX9I21P`#v^S*N$s?=Zb7srOz%`*@v1a8+MvU68{9`jR@P{d^8b2w~#o@ z*qOa=tw_Ce!kqIBHQYT(|2g}W^X$l}wWB}F7aDln8AO?tid6qI*1RJe52kU_rfgq> zf3pwc)nJ%xYkX|^P7i0(@YyyHP|MJq(}c#&TRjSbV~kaRmbm+?v09G|KULr{`quEu z`D~D;wefyY!}e>70fHikp%5+<^M|+#>U5&IjWePM7Mhwocq?bW;bSh=7Sk;>@UbC% zBw+Jg8wjTM4Ml+ZWEO%U<%)6=^{Is4=X>KOf-Hq#tm* zmUT^a&;AHX3aZJh4rTJE_v?l0^R?2a&CS+b97dom>bzOceKtL8XyIm0o_ZxK@Jvbz z8#}59Wm6WvSL8oL5Vpqv0#7Rkyd;X+nyAsg&shh8W*Llju9r67rn08@RZr4xQ`mM& zFxtJonDAij4A&efkfVL2F%#9ck~dgm-kJDw5Z`&G-jj<{FXrY~yMsYH;hHBe^><~S zKaxg!5QcK0`i~T9!`(7T3vbKO9n}ZYhv#}im}{AkU#Tk4QyroEL>D+3L#h+P4Z*&! zdOlXel7XMDf4(6AmyML#>fl+8o(t`9G=0+UO{Z+-n#ddQ_S%8OO}5e?q1ymX!q`+J zk%XVux<$VHoeTO&^vUq3B-kGP&nAu??Bw4F+A61_le*H*;iz96@Brs6$MIr9*@mM& z=TFb5&a!+eU6UW8v?YzxT5Pd~o|b~oVEJeBG&3XZYoBi4nRwd zSO&3KOfNk?gV;->4fu~XZfScGT}}6wjvf=X$mAe40B@ypG6Q&s2EcKQCMoorwJVxt-SOGzi)Q zfbw%4|F(>ji;4=TmV>T=sr1t8H*C@M%smgRKwY?OUKoN#tC4;UWcpZ7XF8TJV=%n~{|*U$PysrfUD@_Qpr+|Fb`4giqc^%gh%<^HmTJVz`c>uc zKoQwxlT-R&e+<-^Kw3V1I6ZDj?HnEmCfx#0K{U$dpB_xliLW;sWx5l`gE-$cfiZ4Q z{wk^wX^TKal4RfCPz_;eH?EX=ewsjb)thZNJ@L^@X#H|9lwnS?%ZiXrv9wjN{7ImT z?>)byeQ`5H)KqY(Jf@f4{JGX#=SBE?TYk&0zYi5Vm9Y-YFnlS`#{Kfse+6dv>e>Sk ztgUDXtbS}GHB0?V1Ke5;tAI~Q;M0GZjIIl}V?-i_#mb`yq!vP$_#4SNNpFIC!lDYr z=BO7~3BhCYW@h-s(@j}fyS@azVyG3w>KD>E`tp*J*67&OAR~xw(6%|LWFOT zZ_6K#`5$N{XEs8C9$)s?Dt34=3lQs$X6RS-Sf?F(Qh%+RF!BOI6$IQ6fKTxEw`uge z(!zB9X%bdewJPO;fu#%qh@dlRjiT6E^%49Gv^sL&NB^jTx&45-Sbw155Y85LT0|pT2$FzfJ%U%M6yFPO%UbV?%!9wD zttq%d`FQg*EoAY6U?vc70DNZ-=|B10&*$|jKqvhL`m>wO(~Z$5K`ufq^eC$!c3-`! zZb(X3!Ja{Yk1T%r>Q>}#$OQ-CvwUWYvPBtM+eBnj(6g4^7(8)KGGQ5eag3GHBwd)5Q09#az4kuZ!#J zt^FtX1|cbHEW?PIS#ryYXe;5uHKP09KVNak75+UwfYTxKB+t$~c%7o(eIz1UeV690 zgOcpjXJ#=@9D#v|19S!ro|LMS33Ge zil#4wmQQ2Vm+}?rNzWcs+?Q1*W9dyzR5=7izjA4B8AEss=Hd}04TLAS<_+_U5 zL$=pZH?28BqLUu(EB50}ey$Q+F;EW-vCpVfT<}*xR>-wuMi}Oyrz7Kr24(U&JNjby z$9l9cuY|fq{hh_$bMji0uSB10gkpe<`z!O6N+viGj#=f8RggPx2bJo@TM^fvKsK|N zj>PMDEf&P9IdI;UXvaf47Zd!)3s!yYvm8AxuFz{}AYU<(PFvc5YBhN3DzLkH_b7Bm zfgej^kR%k76B9@HXYaJOPS04$KR!fD&X(*5>tdX;|ouYNpF z$lGN}x;^RC{vmI_qH^GiuhI+vmku843C0h4n0Nsqqs@D=IB2$bq(Y(NwMX{}@kk%O z=@?E_LqK-`>+Gd!O(#I}wc^>c=l(EDfi(zTj|)`i2qjDDj3Wikb$hnbC9<(!tNc;3 z{Jhrfm%^VGn)ub0B-fMg^sU9`rYTFSys)@@5L<*VZ7$F9)AX-#WSH#(z40IK&0XM6 z;XbL*u_e**Lx`7^5H0U}r^Sc;R68G^jw@yNp#c77lo^be;X8WMm$xY-!vm7r)u^6@ zp2pV9^Lg3s0RlYXF@AEi9a|JGA)Hl@`iu$OEakpW6vk5$6M6`f5L7>C4k~4sx2*hx z|IZTg`*GX_lu6D(FPSrxPX@P7V|lyVMHPpff@9`+{w&&AVl9OvZ( z&%2%XoI7{!W4&a9%i6MmPuoflul45+w&7Lk} z)@a^)OX~!0zr6Y@*V6?SZyu@DZGW`8i{Bqy-EqxZ;?}1JZ?6Sz$nktqYsYp3Dom<-Er8&eR0cBiCzQL|+ZA;%(iM_xe)C$gnv6poZUx~dmp7*X=i+1-A|=YRV) zzP4ufNq3#xIH5bbo@Jh-lDqT6wWtTqX^0Cg06#q$yygPd9?N7y& zi{-u^E4$JzaeM~KOeQm)YjJOw|{2a*sjLThgqpBdh2x;KQNt` z+-706v|z=rkkVaq>{OO-bXN%D~Xi%f35gcK3YV>7pN- zvjTh<=tWPKU)a@p#`{>uU5&n#(%ql_J-^gFwqSZi>*6;RO7re7efiv8`nK9Yup>_MO*#W@dKUD*;t;LJEJ6eY@@$h<(=1oFKcw< z@=pBP$>*8;Q|xG%u#-R2`u_C8DraxZQC+(y{NKidVVs-us_fFuBcF4(nEc$^*`muc zKC_aOeCNLW=*W-zw{iW??Oq$dW8Sr~3la;*S1i2PlFE|Fv!B+yK{;q`>*SUgm-z5& zj~~4D8KEJVXO)?3vNUz}yY!9i2SR3L{AD7uC@|X~t<3Rxwr$*0_x?_&UHuzM8^0~w z>d9X|YTKscW7jM{F3VQfS7utSA~&^S*2;;OwRxMiKlS+3IOU#yj>m?sCp_K@_fL<~ zj(nQj{>6gJFKo!!lz+kY41e~f)aYL`m!G(j+jP#O_{Eg68of;`Lbi|1j0%yq2`l~) zwt^kB|76k8;nyZB*qxRs6T5k0ve>7d&he8oigx)c*I4)cW3eu`S$*_VAD5Fev^Bk_ z{dhR@d5P^q-olpQZ+{y&c*aavp}1*pjejlT#hx~L9&YvSVeaLGzVK1c8pWG7PAZT~ z%`DKdZeJ~{fetK=epvFwm`Uh4LxOFRUsaz7NuWkkI@dfsO2q%f%|`wpEh zJYB1G<8Hio>V+LIy+(8v2anXtb*bSd?2gEzl+@``8K1uyc+4K} zVaBoE`!kRC+v1sZN7l=cH3EgC{0sU%`A#Q#R#iAi1)242V(tCyoMsuw z>*%?sdHQgrqK@oC&9Cx0hqg+zm1Oa(+s>URet4$EbHs2AMy{{=PfF8sJl@t71mJaDnC=_+(WIFvgx`u3$#A1kG6L*8EaA2 zyfFCkk>2K=rir_!27hhh-gvEdvWc7P)jrw3b4OZoZc=NneR871jr@oEckSov9Xz1X zA(PzHzID?y?LaS`3#Gfdy0?7hWp6R--+y?*V#yCjPsTJ#mu2k>(!F=iU}w&2MW>`m zzO`N%zmtdO&bfBK%Eg}7nwss>(x26TJNv8gmyEqiE76aSP7|jxx_pyvBunIO@6L#~ zyYb&_W8a^e*ZewG|5I!x7P`XwQNPvl=NF$mx!>}Pxjt*@W#%+rIl~S?g<15N7GBem zYg~7Y6XJzuH8v{M7AQWf-SD=(<{~epx@uT`&BWTTtdaTN-=>)Bc26?Cn)puUxWrKJC5ErEVe}4Aj9DL(TW>iv2hIw zx@Bp0w=;}`=T>&t$|^VPZD@PEa>WnKuW4%H<2Z@A*&R9icl>jyGHtBeh1WsgTY&z(#AgHUyE@-B_}q@8hDhE#^nf zzs%Dvs$7$}mvwgDqH4p!(7d3|WpO>bc<{UafXNxV&a_9?O1<<3fBd~rYZahH0Q zx#WaJU-xYeckPz!yJRHs{K@iF4d=ASuX=QI+SxO%(<@k!?1v}reKB`GyQAfGY3-Tf zY{M`94gP^*yXVZy)oXbCpv{ZPZoeYf^Wcf;-m{%?agrVCQ$0)f`@7iKh5oL{uMX+n zQ8&J(ZSDutCjwq!j!wPmX4UBnjVEU&GeeF?qH;g?My0Sy3_O@H-YX@Ef3ylr!d8vD^>;#nU@5As)EvrN)GTkiH80~L(2R0zrb8j&twp2V&t`5pvp~Ev=u@o9*8SqIZ$)2-wU0cwTva+| zclBhwg5aRrR?W3$P3FrQxBJY|i&}paLgO;gi(9 z%=`k=uNEh74}WHzsDPoLrJ94Cjjt3RhMl5f1&Q1dv;zwrFJ zmfs3t9~j;*8V|ORagLf_;Ry*R_Z+8=q3!;im&^ImIEtYQN%&BE~KH z&*yX7w!NWWH5*orW8JLi@8U6C=Q71GaSR^YlVR+GhXTd@OkQfhe`@I18_p==5qAnomZLx*Pp?%7GXtcAE`z}p!r-rfAF70|zU3H^vXsB&Xo{6< z#F}#Tk@`ET@2?#i%|^o+jEKFWqHHjYyxaUKmvY&OKhd1 z4w|HoDd=zZTHvgF-$Q$+89db(D=JUNa`gTk$B2-6;>Ry1x5&Xy62OCx^!cU!7poPj zjZ%dppBy6?KLUQ)U@`oTHvW{P@DlJBA3~n*Ii>`^VYBv0y@waoJA+2){H`aX^Y1~c zxNIBRtdBUtZ*uRL#9*ik8Npux|K0`E@}4tXUn^pf^P>a2=X@&$!}OHs45r^g)`dci zdK7|2+rP*5ywgMMZjJ(}=LDOfztD1lRb`;SPaIs(F}$GZQOBfu@lP; z(ZnK-0^uC*?{@AjhdIn!0WS=uAv5BNIjU$!5l4fVaQ1?bRp;R8(gHAwJ`Gr)jhMw8 zELOLVh3d4yD!4yQiTzQs7oaIdqFPKhz~QE(^p?dS{f3bQ1LVPCveAZO;mksyP2ALy ziR@gN>PVl>lt<1on1TV$J|sJSYYmgZhy%Z-i#=;J)xlPUDTCxdBjiY$AAp!+2i}-Gmufsx!r_pTT*T?Q&J_J4&<$`O3X1>tRXW7|UrR-8 z`P7xdT9k6Qgj#NYHkWt>UVe52g8|_=a0&R=y(nyODe%RGWHav9C&1*k!E2)R2avdL z-VGqI2IzIEQ09-NAlvb+1YHAh%Qz~e%ob%ppU-2WH!GP&XhRuCfsol<#=&(j{AgG| z1Q6Xk(czRFnPnV|PE4G^_y7?J>1E&&@Ux;QzQ@ZsIs|ssCv&x@z}E=);y?Z%yafEt7y_$1Qq-Qq zc;%~;!PDM=s9f&^$DvjPs=1)*++ScnABY;d!(}It4D&*mvKE8o!(GIsBgn=DWc$~S!GL@@a0&S4 z7szhgDmh$Y1TE9Ts4rp+#t6vZ^x5CMg{rGK7|JZBMAnuTcORq3U<6u-id>dYLKUkx zS_Iby2cy0K$eAhQM7cV>z@h5Mvx>tZQet)Y0%I+3Pfnt!+qGAaP?v0`9L)sw{Q1uD zH?Nlmg3MvyPIMEvN{YpmGIdaY6*%Acl=;r};pqpTfio-{lBs%FI8+TaePYU?c^?6f z2g2wtstViH7>u_IMU^heA@QrqIO?RYrhf!qy=^9j=BtURqNO}F)_{6~op%fwKV7HveK*Xp-B?tA zX-g>f?uKG=$hn4+XT*0V#xh|rS8D>=w*?50g0ddm7_{PpD<@G;er?*e~DH-|GdDV!wJ--OJNIK!6aM3 zP3SR`Q9&|%_LZYfK;w>Ha>I+Q^Fx-CNuNmQ&QoHFXgx;BDyGjU9uB&^2=fC&4qO7h z(|6=r%P}UnR(VMMH4P9o9-?K}xfXP^R#_`Si=X4n@7qaj;dq}X%!7DuCv#Wm2*I-wUFz`I|aD}kaq#MNop4iDqC`R;Fi zfKncWg4+&=k9$>)n*=%}Cc*hXHODttcZxP47Bd(dt|C#y|`igR2|RIJ^iUpzh8!F5vtH5_w z&D%0fVLZSgenfJCM>_Ir9FX5fJ zNcRV|6sXPz zgF*e+ zqOrzYPC|=XsI+!h&NBsrG{pkp=!@zmPZDbMQ&=QV{t1KK^CroD@DC}&0i0~%OOkm# zQVQtlPodbQc-ynx18tIMev>c`&03+&K7wp>Z>0n}Wf!GB0bKPR2t_Y9uHGY|7oZ;* zF*Dy5{{yl5-BmOpSUjReTr91K*0xe+3%%HPa6GUs1=fZ%TfA%>z)K;QHp+_?P2Xk4 zL+WEe9MJJITS)xzHjWmNckgN1tWq7tU|jiEbRp4`kRiSGdmH8PQrnH!IfLiibP`?l z0{)_~*1v>Ga{UEL>U2PNeseUD>j!CN^!+zAor0Fd31WCHG>gH2GGyQq@I4oj_=;Z~ zZPG@)IGa=tlHA_}TA2oH$TnACE#~Hfw`rmDPU)d3=O9fOXpq*6rZ~6UTGq{sc;emF6-ke>$YUQ%(&8)0ack(mSM`qB``Cf)03y zlaop4fNZi_KsCPTpvoKF%}u&Vz(fO%o#>2qU7@h*og7_~$HY$H;gw6#eFx~#INkC# zMZeQ2JO`-2=~4HAzDkCRl)9+0>{tFR+nF%imtX?=!e{@6zz+K}QHRGd#kru7pYWkq zG>;3Z@ie_<kEN~*&n_ZwUMMW;!0$5UyF}*P7MLh&v72Vt~LuPd% zf!)#xaOi?VH@C;4jBbxWcl%+zQtYEP!by?a=8uPY%wHgyr++OWp-#0jGDB8zr^8nl z&4fe5O;1Hf@Y+CjyVWBjk23m%-jLtN(PEw=n>0qr%A=lvCWU@zx;)Tj$n8c ze!GxR?a`^2rdWLsN!*B$CrZ~P1;JVOzzbuTBIU%(3_093s_4`dIq4yOob9|Za`IG& zuWzDd$c;dGvY$8;qfW^*nV6=yRVGDuVq)aU*T{&~_ugNEvB5d$rA+QK3VUpTM+VO0 z(GCTYcQw!npS}I@{i`g{XF-CfovUmVNvxR|Ms9Kqo7VK)hv8Jf7wKvFxd(yOL!n|A zd6Jb8Y3212aQLAFuphVt{31^ZTPP-+UxOIPR=b*@>myTfj5;N=69;+_kDyziNO6qH zmB(>3a67moXUceV8H(RLvv;q9Hzw zo8;CjgK>y~TklL&?5f{2m9L>-~NlI);b= zwav%PzJQy!Lx5Tgu*3a&qc|JAiDK!Z6Ngyrp*uwbIf$uKaumj04kJ&QJp=pMzhEA> zLDi5)2QC4>#DKzP$zjxeh1WO_t`Qq0%VUN}NnWTjb9tZ_7*q81@)&v27v^&w%>cDG zgS>RDdzlbeY7bnBcW*LdBfcD46GeXntLo>n2HhEXP?(bT8`RP|K{PQ%jT+qR_HC9l z+NmIPhyx11_vzHZi02BJ3Zcj35Y#*t>Ys8bLFx1U?(nAr3yo03sNMfWMd0SW;7=nL zO=VNJZqmKWW#VC$3!sXlTSdi_=r9ZwDGIgKf;0N%P0>fOs7&n@>3_Z*EU^cwh7kjH zz%9GLkHY@P!l-)`i7em|9YE2W#MzSQBMV~_Q;SnfbXW_*oPoP@mNZ8BoBwoBB%~*6 z3KuqT3))FEnh#mZ7!K|UxbIGc4}D7)&SRrPifkR?REA{L0<6TEc}P(S8$n33lOGpw z5PH_ZhkjGhE}V^Al-XJ+K#2-dRaCP0HyEXGr05}=%x;vZgbgP+J|Feh@)?j#?71KuHuAzs(ff&9u-Y{$z2$=vust=PAUIPBnIZ8-b1sh4g%qxG67zW|& z4p4eHyDd^e%xbnV+R35Z$6)xa&>+C7!|sc|nC31~LRVCrW0GsVT!?JcaW= zLo`Vp(?QNfY+0nq!N_9v=APy}S#Y0SP}mI@$_0M~{HOmYA-f_r7aeG3D-#2g<~jgf z#npVM#(WM&?KG-!dc3a^>f>M*B-9cE(h`4y#6_zxs%k>PIQ;_9k71Z434Mx_oHi<< zj$XF@ko3t@V5&ucqt`)d05c9;a2xyp(&xfb>!eC899~+=GcbUT0jR+M5T8&?Gzm>q zrB-F{$kLh@09^%o)Tcpf4wBF`Z6#UM)l4n;>kn!l4Fr4y=!D zPJO;rk%9jp{eB1ldiA=hh+-b2K~Nf6}p~r4;s(I)zodviNl*q&G3B zRp>%Te5A1LLZN3*dAtkXxo!mw(o>gnErs>)2d{9_poD%H9k=Nf%rYDVp)=o6M|FtO zpfsXf`unI9VAVk*bnKpH0;@N~^{<(~*=ZO6)%Y={h>tvOM@pL5Si&r;jKquPf@|Vl zPhSZ}u2n|LnwS>iX$sfmL`{gbJRfBg)275luQY|LOg&D|^dsonLvngT;H%9>5Gfs? zbSPy9E&)F`NEx|m34=aN3%F=*rMRxFx>g3-BL@&&fzAVh{wl zPETi+^ZbENFHDHe%QI3L|J86Sk1bw)|M~}71#I8szrojPlUL9t%Yf~JZ#m<9K5;j{ z@CTjq!Mo^QD1G4n^4Yv;jE`^7|KVhVmA&PG?}tJ{r^}rYjW8X|jL^Zp*h23KFjhU3 z{Q95^;U(a&jYU`VVIv{0rYw)bbf{eLG5x}legIvCxf%+=@K?aEj3@Dzb(C2{OTTIz zSOj$wNC>8j=@O$S+E~sw06QKFFqS@z+tw2#)X6|ueuxV*lr2qUKtZUz2;=KEtntUsVZe#$TG*9CK;!hNGI>{K$}3Bl)f@QGZ)ci6AelPqQG0_cn;6Y6 zz(_|S^5{`_OcsFxGQSZh_ z#@P&qyLNj-=QOXDlwD(Fp)G8cImP#J0J*YFSaV9O(cq9$F> zCa`MABNir$e=m&4G>$jCw}gN(4Ir1&7r_QAqJui>H4tVR&0#R;#qk8)5dA%jN|`;) zR{O1uVd32@Iz`V(lz=COQN}xTKz!b0&|(U#3G}q{))OfkVO&%@j9U7!cDdo*5I$Y7 z(V;v0TrUzTU8l_c^A$J!can8B@U=Adc+vG~Zy>5RhN>dMkjhY(EqAP+3+mR`C%RJi zhm+8HX%*HGTjsrAel85kujg>2XFv;>s0+A65$Qycf5x=NWu7;(*zbx7ka z30(F5|f0iss+Us3(Hl#tL1#+3f?34+rS*9ht_{zt&~{)H=P9KrC1)yZ1? zxCoC(*hvjs0)9Gy(wnv_Ai&FSjgOy~hnL?LpFn@V|C25ywt6TBfUR$siEb2G?f6)_ zsAHRo0`eSAx!i8Ycb)05a;*n@(`9=g&OsZkRa8;)HWeAvyhlZT$kJzswH><%ntcW5 z9I&hmT=0D|*}481-B)CSPJ(X=`#BzVR_=f0x*m=8IPY7cA6EXBv;;OJ^Zjq1AL9n zSI|LWW2}VEe9;PKWY$g5KUoRQ)`ioDF)>^Y^9h6N!~gdhIH5!WK3fVK{C1jcqp)HB z_oZBadc2Yu++)zYYJ{)o5*=Lh-8z3*IV%1?R!DU;hFSc-SMB`iSxxJS7LLY75Isa+ zyz{5WQr6(HkYF@sv=CQ~=xca{J+3lO(s~SN$0asUeW--22Ux@?1r0|>Y+KZR`5IEW+! z!m%W|Y#zAWCOjkn(1ViHABqMva<#NE(Koeoqj&JEQQwT+WJmISQAhd*My7(2xGD0D%!vXu8HlPFd>Jb?p4}oRJsPbHLvtiFY;w1 zY1*`GupHFXP|5~McO+^z7}L!l*l6Wk^(0zSvBST47EbSEiT+WDpq4}=ge^(Bn4(`c zP^ocd#2bQo?ZUvekVpQ&YaYny79LkRYQGIz&{x=xGw|glqO-_Ikt{mbOYaVvYHE~` z?Wt%MCOTnG3h_1344Cz^p({4~EL2Q~cZ+4unET6gGf(}rV z7dN!ujGk8ePr3-gz9{skmb9Z9F0wKz*lA0;%v&cuuV}=;Bj*F3qLvpx#wcBX>lw&6 zl{q1?qX5M|)bp<^(&UAhQfdZPwB!=P7glk`!7$M{)JJAqC`V#Gg`p$eAa%Cl4#D-l+YT^``>VxvxE|P{sUM7Mqx5p%d5F@^t}^sw^e5H z!{{*r>R5JZlD(c;OdS|0WDq{S|2(>8SA%*tBQ9&jn4x%f*zk2o%)-7&eBHW&VDv{h z`QS7!`+^Q&N4JrJUB3K#n;b^QpVN0`9&nM&2XOv>si^7#^8y_GBe**P2^nKe2I%H*2 zAzHTJ!P;{9i57B7M0S2HVO z`her2?4i=}KgNTA7%d zU>Z%~b<Ccx@tgM+#o<;w^)Ia^o<_h>?m_^BV;S_l(@d1uSLVwT0wZA6oNJBV(Fhcjs)!Tqp zi$6>?u9mYJ^{RKVV}at%v0dhuPrSMblI9gf#EY{Xx%xGy=S&HhJjrX0BjY0^1glBh zH(18I%Hv$Ql5okwes@bn+EUhWSw!TWYx4zSF8XnXi{aZeLFV&IU>xa&YfQ-)SarL| z2ClY$!E*ZUkJNrXy))AE?``$1f# z9tKu5DD?CWGJVb7&zCEL`<;+?Z}E587E7BzI5+gt3e?<3|Fye2BN(rkGFQ}yy0)LFh}mPR1Y zzZejD8FJ&op90i#nY}l(I0^d~)${TE_7yG5Y`1Ta{~eWd6be}Ye7R&CGyqV8orI)= zmL?#M1`TY{kd52qMCtiZN181t2`QR}T*t*e8=93d=MW?ZBh@_mYXRLXvMDoFoSM9G z2mY{os;WqkY-66Ztx14QSE*6W(Cbxl?DUpI>n8O{9J5u~!#rcup+k@1rLVmTeVpC! zH6-`0TeA9PY}%%6+xk`X6g4us-c#wN(L@aG=ymDV|TtAMP(N@nv-Q84D<*#b?Jag|J_&F6>Pp_``F26Ee zKGn)>e45nVnJ@RvN!xhx=HGiWzgC&oaOZ8iu2-(SDACUn_t5bxZc*=4I(n75Jv0)U zR{_dxJsQrmR(cLuOU@EaKDab!prt(OIn1JTeFrBkUWW7|YJPMfJ6+>Yz>1_F=SFU< zi|bOy#Vcn{&1%G?#JCnF$DrA8guwqc(S7WyElK*QkJ0JHAgJHfjFPbz3Ho_cW#0wV zc&{IYu*EbjxA-d#$Zb4F>VKo{xU#cjm;-NISttv4wQwfHYSE2|vW3y>Gtv-KRZS5q zr-MMgwQ$`!*Ib`HxP61tKNN#*c{bHbZo|ckWBn%3aU8l)D1SK~+g`$iK$UrPu`M?U z$P<>;+*{@aBMm6oio`PimCdElQ_Wh&npmb4tLiw{6+1uO#D?fU*ZZ}QWEQmHk_;S- zviTc_jcv{KJ5{-WqX-#PT{NO?rMx1w!cu`vHyvi~D)iCDl(sBeS|IVW5l&IJc99(vBP2?{+DbN76Gsm@4b$-F`5&djZ`^SzP^4M!o|hor$rxZsxh-Sh zuj>#HKZWJHf}zXTnWrOigfO$l+Ii)~v11P*XB3HFMQ z&8ZX(lHO{46gaMC*lt@B2rytK_6^D~#lp&!7K6VY|Cy>K`FDi&ox~>A3J1<{GL?gb z#GxKP;iv_9a92X1V&Yxi78wUjgg|);H zX^+AaBm>W%vF}4VDNqJ$C;>QiTEm{<%zb?0O9^d=0;|R!!DprY&_JMjO~Ky0+-@yJ z;$QJF(G9&G0z5n`ZVw;#uTQ^aPvFbv`^f972po-u0ihp#En)me_Qat6&>DR|% zz`L9yO$T*N;%&F?s`;h2mN+D|gfB+nFPsZ5#6I7@SGcw$`+r%ys6g-zYK^*N$A7~9 zq;2J z)d)8LAuayYw>=ef5`n@^e`T%~i}jIjnCBTEZ4R!YS@8i?X2l?zXC3(|OIQ{yDYmq3 zWo3>QW}YUzVe0_SEJ|aEzuL3LxY$5?Oe-s3akA6V3U0FE&mf>K1Ld>iHSV|aQ3rX! z5~5r_r>KZzf8%Ycg^;x%$!jryGV5ObWh6{Znl*}5};JxlFNr>0!G5>~2 z8>mh9-Wq^sKie)RY|YPt^;A{+=ErWu`f`@9TLR84F2{g&#KKDG52iMSU2(=^hSCpz zJ>a^VYxlDC)TR6fJP7adr_F~7Gf zWwy*VWlZL{Z^Jd6EP=|QZ+`lzE+&K$^Ey&Y+HKgVMOQPWd;%r{CYoXl`^42`385if zxKr_*rSU+LGO#pJ1EF5Z!K1h`eC%FKB!UZ2^1#E5&zZo9>FJWr?!IvBpUh*6X zx1OJ^vI6B47l>xdNluqTt*Kr zWs(f@S*}U+2U4lc9_>4P9mEtr5{4U&r34T<$Mw>rfZaC4PmP*4-yiT;1zpZ{w*7RH z-^Bhe-5~4CUn#8cy3fkSMtYlwu)zG|;M%At$NpP}{L$PY{~Oj~I-oQH*1eNJMgDBh z)Y;sNGdC#r?K=DBOAnuYAZq+5YTC<5u>RURE`s;H)VQ}KVjs{PUVt~p%e7i$lum!` zRz#RVF>T1c!prhqmB~{V6l&jn({Oy4(x-uvFir431S4H2BHMKFI|dQqR~)>o5-!sI zH7Njq7MNyG42qUECyoXSyyp9I-fU0l`>5-uNY*I;4Ku@trJM2S}mUP2~Xd#pQ0JxyQd+fSYLXgY<-&j){Bp9 zJ_1#jRt5l;AWonu8ttnA~{xaaRtf8{vkTX=h*X9CYBvV3|*B-1DQJdIs&) zZJGV9PHsxq6+)B}(wEAmCjwo(aRW(`zPc6&Bqj9buun9GG)b?2zRjH3oSR=-YJKSe+}!O}q}$Wm(~b7~ap>~pMsCD1VG7uY+<{^Wk*zcMvnXap%mC4_ z1;bw^rBdSI`1rXwRAi5s2joF_ukt|DXoBa!x(^ zrBp5>c4(E&_^_e(^T}%YxBHXt(>DqlOqJkAcX2~?K+@9f=ecU_j&l$2aV=$N3d~N) z>|}l4wBF2yZJ>mWHfF2;hUTV`*enek*xTO&Yyp3TK{>9Bx15I#9z(9QYmzPNQbC!I z`lbmUbexCg1-yG_T65WO?@dpV2b6VnRXdwPg(Emvcl!X}FFwnfj;`bhVd!UfdppuW z1uT4yedPk(Q)lfrWD}1GOHb-$BCO1_Iy0pq7=)ZE-RR1|>8H@4zvx`^V3NNqlgd9a z{w8tt-m!+w<*zW^II~;IjbR3N2bSIAnjo!ji?AN6gmBM6A>X$7R0CR&Kpy}-A56uI9dow((y#4Gr33i~fMR$eqa<0}RN4>45B(&^bt_{|Xi&1V46nCbE*@$75`xw}@2V z=Ui2Xd(+C!4!=9+3FPK)Rd91<2KV>tDic>Qxod9_s<+PxC_o)I0d%ZuU7Q>jf@T%R z8+4)Ft6?lTCJgbrdL8K3;pB5c|GRiyU2UbH#CZ#G;EysW@<97(nVcHO0bas*uy^L= zgJZl{&_6+*Gk)9}8Gt}z4F2%Nw zXQ;6Qs;zItlMoVgW8u%F9Jsif&uD65K;f7f3rUdt^SM7u=oX%6rANLR+WWlxt|i6p zqqZ62_9@*_?G_+1A`5P_3t&Oytmh{k|Mq&AScxKL6LM+0KbgauCP%pqGUgN z4pGAVXDu^sgEr@FF#!3Zr!Py(w(qxvW|qEbX+^(Y2{p%XFIDD_F3z~ooM#nshQko- z89*}xz^hT4@z_mN#882_tp0*gCARY-BzB;C0)Ck;A4Q0Th&odPz&Za~?^iGl#xG<8 zx2o=|7zegYdo6-+Tgw0o7K$rP+x~qO(Sv{5ulUwc6mREOeAvx!qfBV7-WGfoiGwn> zoAbj?Vtswab|K|Y+AMB8W6?S@siS8kPpzYaPw2J#Pi5vkr=2fP6nDrZEO}x~SsMvq zW52%ZHjUTr!GAE#f!AI|#9pwR0rKgAEmd-b^JtzA9;^XlgawH>9jX**t~5__qFI)D z#ZnOj{$%$zm9Cj-?EjE5Jix1&HiZoI$OQMgB@>~WuZ*bstu^fb`Ww~bZQr`u>=Fy4 z&k3PoebrX7pd}CpbR5PT8;yd*t%1nt*+cT_gyHyVy(0-313wFYBmCrs3rvREbSts% zxxplZszwoo*Ti3DOf&m))RA@Scxt&!ina;N8;^eS)lT$8i2cBU`|)>h`}kcWxD`Nw zk&3kB$Bj}agF!ihUcIrmwW*BERciMq$h<7YZz0bU+`fb?AcCc zZKl=D{J7=0<1n%!s*&Zw_}ake8QFit(Tp+)ydbVCG-FX@VvGM4&cJ(raXe?i;s`0C zS3bUU$EnW-TS0S=qPFq^lH&@-OkLtGtLPMvH&pRWUvrF74R*`ZAkNAhBc`0o|018? z#}d1O4E)=J>ZSXK=6T7Cy7%qmguW)t>HvF4z__~!Fp)5*Rm_4$iXW)FbuLJO)Z2W} zU+r!w33^sn^M@_Ef>_kQ)ODF&UBrGZ%T`OnfIeuCg|#G8jSPz$^~WI)i~wpXpQ4N% zihnkoZp6=AP_aK`S@_hiN{W*8xD65#c8(t(8aS-Z94ELhGy>ub%Qn^p_=6TpWmDb- z)xO)yhpfBC&cH!e9zy`1Uj|bxai;=4ST?l!&pf9;;;C=`EN4B(=xBfQdNzlXcz++l zu>YJaE9H$>6Y0v%9s|+d>G6zmh0D~y|2@Rr!(zq&xmX=G4%R)*%yMNn$$hbtf}&5DhC~2) zRL2-88YISv!Yf@*0cUPjK?St}%qVDfCY7qwhD${MQ{vdU?%>>VE={-CiK^@CJBcFW z+>F@;QuQl^x9@_+22bjDYjbRE&olIOIxs&Ym!B65wcK0$L$588ZOJ%rK6VM6C$GllgZdA6Sp$)vwF#_|hD)R<*ZFnCQJ51{Vw_r-i6mNx3Pj855IGs!&eT zPJY95+1}KAf=7;9w)+t^V8)b|z>6h7_=!I)QqMEgy=j4YCW2JlYfaF_ik|iNIMCwY zhE+W*I~-G7{M)+K2X7qD0OvoB0~!V|Tnc$I`_kxyGDGH$v#Z$9m z(r|(EhjzX7d=g#;2gkoX_B^>RVCFYct+evsoeI@zdIQg zyCQ969Nftj9y_9xgY>8*V<9zNtjGduL}Vn#E-fEQ$9ir7gOv#SwIVa!n)AeFe~C>8 z;mL4H7lOfvLNkj=3?;0ZXbj{`K64Q)xQmM2$esr?$ge|^2~*QHqQ=FhcUr0~8O;$y zXiWkjh+~>>(QDKV1yvu$ zafNoJzwmpu>k-53Qza%L&MCfx?>^WW@2Oy3%%zVt7fSxH`Hit$z7rC7d4=S)eRR)q}`P> zl=ujL+(3P@CEE>Flf16&dlkwUZ63v)#Yo`|7m%Ow~|_0p}nbO_mvcElGal4yfh5?~!QPpvQN$FYk9L|Hiqf&ls=IhG+wsvgm@pNnF3 z)0@8j<0wr)w}7c5Y^F)7C7DRAKPc~d9TTW#r*_t>!y9BbQ*pNy7y`K8g4tkbY%0ln>sU|d( zX%U+-J=n~yTvDslxLyd_!_m7?Hg2 z@HG}9*nrU*y6~Vl@r8lrkOkBlAxzb)jVM(2cv5Wut(mB;VK8t`VixRd@*~c5Fhs0g zowC0EVtT*ro38_CzS!N~S2bLI=#%F1jVo`BfqtWt_?g1W(?)>6^%0CiCUHzDG{Miy zwJY$Pxj00tY`pvurdz-Sn>IQGxF2Nm@2|RMF)&|@83zxuN3`l9nq#$8Y!^@U){D+s zSqXaci9HWWCZwpJaDrHr&)W&D@3lsm3zbwxW`TUbM!qm4XXf5uh9`*)9VRzUO;VA(v_2x=Q->`+D$M+-Ihi^@Rl`d@y9 zA<&6WwYGA>-2=}-!la(hA5lt%Uy=~l7IH&Vmjci{e#2)5-XnK2cmy8d>?;v8sN1th z;#-yu$az)F;nHRhWTT~%yDbmb7Tf=>S^N-*ijuQwhsR|p!(_iQyvhWC#q;TT!V0ga zBiM-_I#7Fg7^dQ&f*y27WpKs|t~!=<0b6whHI*ap)a1A=189>uvf+d3G`hV%uQFcm zzN~K-Q^2m}4ltBeJp60W*#F>JTOo|LwVyn}=Y8c5VRBMq2rurq2MjpOHm30f!mrDH z{1S(W2Nz^zK2tnc3E^E|&(;o0e;q+Exl;rnl_6}%zy~hE19XsH@~#qpwL@Br0n@_F z6zAEOhx1dY+H$Upmaih`C=8M&*v>IW`-k4*5aGqcE7Xj?46$8tHkeaoLUBq z>HMsCWp26jPrnrpZll?X{ej~y*Yt`6pX{GucYjv4^kp0^|MQYx&7LBm*Un%bk5V6!!qs0 zw8GkltZ{Tz`Mf1?D3v}Qs9khj=R#2IaR!ph-LvQE$l5N&1oflpp1y2kK#yW);|O6y zIC%4SUhyruNd0YjzdB}g|K1_(GAt9B&9_Vw1BCTgoe@oQlrgJxp?4a|;raG-S<{u>C zKEOi4s>nzdQ>6}JxyZM-f%CoQ@B8{M8*~MDBx%tU0VK2FmpR`TRqJ=&=4@PC_h`~y z7zQPS7gQz!9t(KisN?=4?NDbG;oRVs#&0cS`_Vzz-^siLM`E+kadBhG=6-&BO9(#! zJ>66b9nqt}H&}dCPxj{|SvPp5Kb8H4dSse0rxpfG=XfQRpZs5g69 zZVZJ*8SUq9EJyDHAU;hrMnA13hGi_Pc>fLpMFByJ`)C~M@Uf>$Uz8tkF%sph>g1+!&5*C z%*ga2BF(;du`Hk&tIi*G8}Jk8d_F2sJlz5l)NkkpgCtbigL0;~1DR_8ytvgGamz^N zBy+``EJ+eJy?YueFr z{}EqAJ%mXCs{Z7!CAi67{!%M&eZq;T*vf$6fB%J;7|_W@ZnSz6q1^~e^K_!}0`-D* z8F3b&bxtj4v$Q57H4ao(Yhyh()l~57Fu$s-BfLV$ps7_@4c0@-bNuq~;3QjsT zqF^XnWRfVWkCpmei{`1%ZHb-o14Ua(5R zidCp>V+PxZLDs=fI{jD3-7^abV9XLt_$0^n(#lnMFdN*~vlH|^u?+pgfj(Ne+%(vR zl_5kAgt(3w#d}rPJm4*hO{#aD-m3|*A>G19;w669FcV29okaXvc5FO*Rq;f1FC2%f zI*zUj`_ya?dcGWGE6Jwc-nb0vqVMc{tFDZ+nA^eyv7h}w5M;v2fFMY;#3PLE1b5&j z@74}b4*8E>8}WmmVcZDjPH44JC+}Z49D)i4KJEu;7+XP+5yH|sq|pSHRPcd`D}lv~ zP>phJX)>{4dd7?p?dXY}Nm3M6gEBVBJ+31%YAupo*x93I;^oow^EB4e>f1ifKZ=M; z4~Y5esu(95rp;9oWtl-HI>uUX>)6bC4=s7j2l&!%YZ!`l;CZBG!eyJ&C^qv_mEXet zC-FbVZACU!H9&fg%Z{$*>Y{xmW7I5p_5xG1zb3r&lXAfDn4YL)(lRd8_x?76kc5}9 z3BM3BSrVZjsEwa-|2}hQ)i416R_h%_9p0P!+R5b<06u(akDY3%y1U^S)X$FRv(zGx z$Nf8;Ie#I3pGkNX;}ziM&b)#&48a!y3i7)Z@K)woMZM~po*7{#FY!h;Yw7B;d2xgCBlg(hCm&%t*1T051*@B5-_=Ei002v+ywlQe} zd@PvXQD!W(BC=U4%Q1KeHQ+jn+3rCp{JF4$pHwP!ZvY0Rm+UR%G5iB&^$B0l0l82Y z?)Bk}V}K~Z8{VM_^22(?8(F585SLoz)J<5l?_-vT|`$sWINq?Sa7b<0|Hy}4iA2sgU?MjD~ zfuC-S_adcQG8`66NCY=KYrZ5XJ-Oe?-d1@_y^fRe)8gQ>KNW=k2W^&xHGuf2eltL#H;OitvLAK+GQ_5idu*h(ZVoUmd`~< zN_>P!F-W1U9{H5;+{y_Fis{@=CE98>w*7a*?*3pklaMBwgc;&9%3 z%~MC!x?;v{MC+p2kXTLnMvbAJ$Oe-*ps8$YV%{G8ZNGV{T7ce0@jEvh&_-1&1qQ&1 zA_!nyhgTk2pcNdjv}XbiS$TJYeM!UH>A|Y$SWq@?{Zh#-b~hSc7qP$7zqAE4s8Avi zk&J!s+CJ6RqG-V86wFyH8WbR~A*xg7)L zUd)xo^o?+7=xH5YhPZzf&5K+2?Ypw zu;OTsH;~=~_nyJmDu&|5TB7K>u(^%9DT@iCV!J-+i?gs4WbM|0PH&1p$lILp$K8Kl zWTobJX*~wwS9S_J`+z{YJxk=?9%P>o_YlsWN5e(&xLhpeU#noG@5Ox|P){T&s%CmO z^zugFAABxzxiHK1SQC&K3|@)Eu@+wCbdWPs7R%E`fNv931P@|C zO%DS~DS9$WPEEN}I1fvtK5X6LW>3kGnD=;Bz{1&zv83yCsjgH%`;Z z2Y_y8-KWPKX$9du?|dUTuJB(M^#{$*rzT5Wx~0_xbPvz@!5>|u(YHL1ut2z-2Dcmo z#NK!b5fwa!VsXRDBN@SlBcj>H+~aw{#lnE>6>LyLoC_C&&rQwx@#|a$x%n(ZSPH}x z>G6e$rF&P-y)^qJ`j8U^y$LZupI^>P9E`Y8!P@EP?NP<8);_g?o6ygd)N@V+pEzVe zIY}0+^{WsEXs{hnQ{h@+VOl=~%u#;>Zbyu$`ET7PIi|AjUD2>}Hf}diwaOZtE3klW z1EAt}VA_~<(8D*6Om@~5tSSHIAk=y00o2=freZMRrDwHa>lk3ModT^R;V~mA040?; z7!8CsYCz>YI{Gr_J;^qK+t7`H_&rs;5_?#s)n!L+IQ$F`*l^ylk5(>Q*Q(N2lPqDP zcJp~TbOv3%xP}1F`Z;j+;;pXUgBNIh%9J{5T!XtS=IFidx@b8!#~$=(1&ldyeX4T|V~nrd%z>2Z4wRdx^%+-h#5tzPjxF~CS0b*d*?S4m31-`JH zQ8yMAGP`w#<}idU`Qu(2F{cyG1uS^nBEGh)oD(?x5&-X%m!76LFqa8Cj^V{ zk~noE3yRR_z!)L2xKAVgMgn3gZ8Xsd#;EcPVM`E>k^4eEdO>nSo&8*mJODpy(9sa7 z?{iUBgWfpj|8$147Z@z1^N(fGrAaAgfzt@xhJkXL1aKG`ppU!$9o%|jR%eyWP*Ijdrt{Xcx_tvrh99;CD-Wp#VzcoR-7cmDq?>IdOYWtIK>4B{v!fw`7OuhPsU>6*A_bHm~g& zKb`bFy^d1afjVB+8JJWm8;5&7k6I!GrXOtuhD+g7Xb*ZV=kXKahjWS&XLw*(KmJjZ zy~ck7o+?+|@AuVjdk1{6wCO?|?912PI-z2}mNRAC-n!cErHMXs*GHL*#G=TUJ1vPB zX5sBoIYjt81k}O~@o~l$DbAnFPLa@w4Hz~Ir{eJ_xZLTjDTV#DiTJ2hR`RH{vWj)v zwBAkBOtC%R`l(j(g~56x!K}fr{)gRp`}i5;j?6KOhtT7c_Yb(z5NG@%+;G=`wdiVE zFL)^5i@8_=%lkf@Z}nI~*@>~4^=+Q+h+TsERoBB-2mF;aa8wWk5nNg-U{E6fk>B3f z-4(nBh|5;|=hbGomW6R^arjUBs`)B?m5b~Zir#nd`(5ElxrF6VT9?khqeBl7i=?%j z3-icP$w~fiPB`!w3bL1$T2?$ymgVH~JeSgS%~$>JMjVRpmAQ2Te+kfg*#N_xW{WV_86l<|D-9?( zZ3IHn-bZW3r+-irjq8#XDFJAoT>`=Hq|l2gnhRUmL=itZJP+;P3CIkmmWqc0 zIHITKZYT6;EboDpxW=kuD3^jczBMd`m7B5`FoNiY8rJ$U4HQ$jxT%}@*b`tFxt9e! z=$fv*z5oS{GvKt|e%k$q=BP>}prR z+n8U_XbjGye^3Ih>PlOZJ(~(t;CF9ncE!(AL4Z6^6nW9xuwHy$0uFX_B&JZS6b*Ds zzFgvXXDXw|E;9~IPgSnoX&Nj@zAITI1K<%>8l8n=+T2H}bqG4o36a`sXDFefzfojY3AnogGsmxJW6NvrY*5mJ^wau)tV?m6fBJi09 zTcm!Xp;uCyrcTDEp%b~H5A$v|4yJBItV6Eog1|3*0DOOH;Tt?>fW_JC>d&erhucM{ zmtb}g3)(&T6!zEY8}n)|$xs|5w>w%3_v27l<@c@Ot49>DNQO$Rm`E&r-g5iW=t>b? zT4ivugT0i5|8UBgBW~=Gr}QMt3@CO(SWd^liuwC&n6>*7deC=J1d4YgYkI)KMRROQ z-%Ekl2N$uSVlo+8sW|1%WP!$c@DBJy^{dc_dY{=&qI0n*qXbl8t3a8=FQ2h-G5 z)bBP@DCVmipiTIXl(F~ZY8NC5%e&bpAAj_O&#m|hayw#HVVNVsdxzCd5ZG--SEr@w z(W0)^13*7fjo|_bG(VNHlzkXoql~I7(Z`vGB0(qUC(qkDp}c13$7T&xE6IEG^hv08 zKFW4qdov?esYd$lCWS&Y9vPyEkZz6(lKP{eDwVvacC6#m}>1L3x7Kr1LRpWp5aBkN~ z+!(R6mxf7c+ZfaouXScW2ul}L|@Xlj!U zDWr|?cAh4h`xM6#nZ-UTrV1F_6{Ib>e=uJrk3Yn%%)l}5zQ47!kBx=9yBqhDYUCML zbOox8By1ytZbi}Y#OKo(4XmT7Mis-6#o-GuP{?*IL*v3}(y_Q)e);Mcn!l3DJYr4zUBhX#KRdCQ0u#&=Fg8G+fdbQS|Cu#@SC`+OWbP>M$*}TM6*zo&b(BSZ7#GsPR9@J4hTe1R# z5DDubQ*~4^sTIW0vRGQw$Z&-VdhucyKFN*%#q976u$jdq7fi|XbNc3X-%=6lEX;+C z_!Rhpu4DnO8Wzm8#^0gZ)uduJB?7~SN!=(~NZ5%lUlpy4S?vVdr8TTVEu%|7ju*i) zpVF*Re}fqnD;lHvBt=NOK?qR>61gI+n6P@jv-p<-P+9ZG%0^oMT1tEk9^2r zhWlmNl5v}!`w-3cqZqR7Zjjz3;(1lu!~x9E!_S#W>Vzr%AbL{}x&JveB6E#YlDmZ` zU5wsgi=1dFCPZ%=wVOHL*buQH)Z(%~;_XcmG}u_~;4EX-ggFgL9dm_2-3;;9{1?Ap zl@gnPz$0j8uGkRros(YdRt1xc&Jgm)46-4*hmbr(qT0zUdeZop;xNoNVM+{T2PyEs z_@E9>P&G`HBYrR;cnvj>%b7DVoZEEok^ zR#yjdfE4!_$Ym7vrCcX4q`qbHJ1HP5l@MKaRGfwrbdcQJh)0A#h+bX5WJKQVR0Jc~ zZi_YA@dEPWfKr34#WZb$@|hcm3v35C*D1RB1M}2AF?Qw zBx^6jUqbGZ3&XU6p~+FO*S`JV>es?O+Li)5F2zOW2))EjV=oj8S2;b` zwsX-%^-zC0W@w7rwE%v0AZ9q8V>;ugNLOLRtzu*+#g|n?`O)VeEF2hfpsg-8`VJGm z-Ly-Exg89nQTKadwYi=R_>RD?!skcc`nnIjn@$g`Wy*K?O&$9-)QXTpgi9>W+>V5b zMzXWrAiI#fZbU+3sgPnnBx=#rXqus0t;3~up}V;T62hDMI7zT8y68Ob@@>#1N-dW_ z)4FsrNFy(pMAbmU>`uG|P99w;BNMzbB4e7oVr>WqG7C{~kgxq-Cu3j_r;@Nx2!W1) z5^Inne8pRwU9OxMW@2%$*MT&obO24xh4Ldd9rkvSo=sdJm9`1JLHeo|%fEWYQT;L@ zY><_Q`R2tdaQe3ji6493x1rrTQpL@;mtBHq%FwIOooPCB%S!VB4zRQY?VWt;!G3Wa zlVmHrC0U_%|Br|gl4;=#B9NwF&DQ+IJLTQilsA6S^sa8}l-EE@Gw%5)I^mTbY-8nh>e(!hI zkhgU4sD$(9U@zQ=_ktxD5RACMKmvU`J$vGm2%Fh33mf|VTS5(4JqTxzo&TC?m=1MF z5oG{L+&;rMw5a!+3P|U6g{Ga09io3rqccL|{NB`A{Q}+y=_<6;)A>$_OcGk68AF;p%d9H94Dz)Cmba;hWYbw9t@${1x3qo@Umu-4Ql$O zxT_6E%UN?B(PTDDo98y;AJA0H=eBqm>o(;5&-hZAc+3WN$}qF!^Vnso{9@kFI-7<> zOSRqN9e<2};l-rGYD{az_y6G^$HOx`smLK&+($HL>nU z?4eHQ*<@!%JrEV z51@E@`^ccVL+Et5i7Hl)BED&aDnEKzE`XWB8rsf9E?jG0lRRVq7+c;Ly`#BqTyyaMwFLB;t+1&`

uqP@@zwJ8;qQ4g@<$DJc$9hE&S!})5PM< zlyBblD6a1lCYFHWq5_ET0#?5lMgV+&ODp^4qP!w2B=M2h|8IcMc5~$J#$z-Cq_tt% zhuT;?k9XA_@KI6MXQX6BMgQ0snV;7DytM2Fp>-aA@H|mtLKJQwkVsm(bgEsvqsWxw z$8zyU>YSoJzn^;gB?2wktDEz=v-T$LJHY+hn;`Boy>Ko7^|O=jc)f{S?$xBJBQ(dQ z$#M^dm6FC6u|OQx{gZSjOCpb4YFyA#*y_J{v&Xt}I$I8YT*)(GANzOwg2Nxif3nxX zhv%h%(Q1NY8Z@J2!vpG9B#SmM$xk5VWy@-W<9; zo6enKUG=J&-7Uw?PnjQ86W?E6)+_ect|YEE`;Asz`!rgY@_nX1xj96=1(0LZdI1YI zGwYP()*|gm&+xkzDR4m|_&cJNZwrzEEMDu_tIU+W~3k#)O;iov)b6$LF z^J&5_?CHBqO+~jtzVnz5Pn(#FtEY8XgZ~G0K#IT6y;f#)vA6v&`Rlj74DZ}oPvP|B zzfem91QY-O00;m}qC`y|)>TC@CjbEDhm#Oo9e-W_m)o|H|9$@oR<0|mmT0frUUPf5 zm%7fT@vH0jc{l0ZbM_cYqE_rmq)Jd;E4}1zzxm7nAV7lJ^`-BWc%MXqgTY`h-vN$B zqj%N5Dau?$b-u}(d>J)W^!D)f)if%~W&SZ&qtWPORae_6O;`J7U*~BW7291^H&HfM z)qiH+@KTS9%V|tr21|jfEjj@e_Z4{kA9bzuP^Gls{0QS zg_3RcAy>)1-VjxKoyz5ue?RpIUjUlyAj6E|gG-;`><1Mpn#PERHwT(;FR->8IUe_1SP zB^r!$&l$RVX>J|?u&U~9)})K7Y=7!%W1xJ=S6|A-BTw_9HxEG$9BI2L%3IU)HGK~? z-Q~OAKL1^l-B=3WQ|8jKezZKY9ntv9 zCZ(&xk8BII@cHG%yO&?R`t~Bd_|L10HQArUT;eGn&!cEpS4~B- zc^a)N)$me?SVPF|tL!!}BY#Hk<(mHHV-;;^RYlb*Qu%^(OjOkc4Nyh#WuBjryl!@9 zPoK_kmxgrUVF+*G4!H2SstnN0N!{=KP4k^+m+&C}<H2wW8H+x_eWVxxVozQff_7D9Sc>*+J=nB>Ew`=c5Svfq(b%n&_sPFrl^a zny9fnls8ec&ZC#obaq8eK~`M5 zDM%7WA{Q07CyTzic=3f1z)|C=TKDbtvVRSn6TPm~j_}kpO4cODg=)m))g3LDC9Rf4qt37DeLk^| zBz0Dh?j$*ylH_gnDxMg444&Hn7%2$MSUhrxjR_vvSzD99-hbpgc{^G==_)HWG2|vJ zk4#nNROSPtJZEM)GsMFsuoJGfl;W$xFgckg`FwwKVy**`{btGZUggbV9ewleb@W)B z(Z6UGsoP?=BT^EEE(RWl!7yS>HIkZk9n|#IK6XsG2xMRrBDOb}J3Bp0$oNytho_Mi zUCZb;KipOIGJneIn?3mKEE?0Yx-U;s#+1qK#SXpyI>>p}8FsEVOItL)*zpn>c0y%=5w|;)&H^s-5goMIz>3D9WWDgAW>OK{s{kS0vo`P$~0X*=T(>l8C z-5~=h4}Z7!<|fzzpYf$$uFQFuvpJbEd&Sb+6*y-+k%Mq}9S`1hM;~t0CmKG&94Gdk z&u^rJ8VB<+3%N<#8WsR8Lbf#%kTxPTDrNxE@?cKAB6k(7FnFXQsmUlHN6|ou!-|UZ zQMOe*g*72I`OX_lSAX%BR)66`{Goe^&d;MU5PuwF74~RS!6<9iNudbS*mq+9`#J7{ zxnq2pOggMYI&DdwH;K;;=%zLqOo!>YMOtB#Kb_ju3oE~>6%Dq`YcfO*QT}m<5C#n#JRbnk+!bXW z?RV_<{_0myJ+yY%D~#?6`m@@X90Q?V_J1U8S0Nbd{4oB&BO)9;5X4Zh4vFWQ=%>?X zq?OBkVHxOo5!k*wH~Q->wIS`~|kS1b{BkrB(n!y=akV`7Q8&aip|U>0O9-ViMa zWty0&?e=ebgh#}!C`xiG7*>tILujgNnp~(~G;)XZr;95h&YerEs@xm`AgXdfxY9hd z?2rVSk&75@s~VP#L>-t1iQj3|M1KMTaoA-~iPs+e?q7cYtPf%I67w|EJ|1fdtm#%j(6Nd?0es=Hzhm;EAE@TLs|=YC*(7I7X0;4jAi(2tUD) zg2#Fb4mMDe=qt;-2wW%@x0wS)8@cR05$!Yf#ggcoazkPblTGIEKJR#C5r5nqf_iWO z0ZnSY5VP(UbDFL7j5Y-+D>gdeM#EUQxD!fWUH#>?1BjXtgcfrFswtMO8onfAL!xfP zoaBRB2pu!5=NXM%Lj|7Sz67@A*i*3>#C>L%BdaGzOx+%f{aiCDY(5Q}O(7e)Wk{?% zq7!D}EnFZbm92>6Q&AHXesG{Pp8djVIP*b0ytt6Jq{Dic6mkXt=cya>;tQlmVfCU(Wn-r=PGEw z3#>w(`GVB4ioDQUT+RPRc(yU0D=1$w{FVs&b3>BWe3S3c|Jz)fFeIZF>xc+@NVWPO zla9<6>$0Hnu-t%f!=xI6#(Ee6yM|+9|iy34bR9Ka~m5AR0;bZ=JJBQRiP~M5=(F($u6O^JR)SpW1=x=NVLh!SW9D1CFy2|Tx zPBwgf5Ih}WM`V0S^lzXcJcdYG0dvOQPY3z4=!GBukA#CD{(pf9sURhZKmCA*887Z! zXW2MHTkUI@2bwRUr;#AsULkv@1T3}Rz&h-KlOzLkPs=3^`i9Iv9Jv;W1q!OKR*{fY z!FrWxDG(N9x& zhT9Ch?1t%uFWKFf>H@NoLCcKXJTg+P=buEE6{3qaIp)d?_BtUdh=BAh|5&h71`7^T zVDo89!|jRlsF~blzA5J9ZZ|nCI0&Y^{vhbg81>?2&C6*8N1MH^rgFd-m(_L#$5m`< zrUSk(C4aK$rzB|+fQn06A|gR{?FC3BgIYR-?nOm8y6VOwe+q?c%KVO>r!M>qW84qy zYQQFBB@~Sfgn=NZ0j^tlZ92nD$P6Hjt9$l|(W-a?*8cDtbv3ro&G+gMJRr$FuXr^} zGnUQkjAk{Hq&-b3DI&HSm+S|vtGhG5FS%*^QGevLbaCz^)XzKG6{5t`t}z3d3M_9` zeNk;QBsFbNg2PMs7I78Hd5Jb-{mH>PUf{6xFMXUOxtN+PsmZ*WkK`|54N1DuyNMof z3yc?gmJ_?d-UXPZMEn-OwLcyng|;o(WQ*8lgC#RFR@>)3>OsqnMi9K-?@gO^QOhJU z`+uEYhO9s8Xy{fqZg8o^HF?0Kt6AW{fWFPG@!y>jX>Y@nU4UF55^*gAY%O-OcNKiU z0%8*397)DUwg`l5?3;{T0k12Dlrp6Aju!H!+S;S$i*IyVbJl$EZ^L}0fBr>i)N^00 zy0MwSe8HxTs?AcOlZ^V*n2bxdN)UP=$$w%jOI+;ErehfM6gt1%K1oa6nXoNOf~(h; zQC?wtx>J38wvEhE!y zfJ_-D|&~hfqzGNIn1;uRCEZz&5J0 zZ?wJEZZ;T8>N3xwfBZPo$|*+GL4U%jnBZ_j6-J!tVva>Pk>GZ4p7@lT^oBfSv^;zy z@^E+@-PJLKjSiQLzAN>E-2J4T+ibb)iFzG;=&n0khQjF#wMI1sBnerDH=AlsLYloO z++~wjTKGZqM~H%utw<8yiT5f~gQFclSt_PD6f4KIoO?=(gyuf)qnT|~#eZ1>jYv}? zt-2sXNAWaAagpSS7|X9cVPWQQNEiAu+Sbtp=JShI5x-_+HB8L$I#XhUwGeoDu=hI; z$%v7#D*R`%rlsIG($+u{NYm9h3vtl+eDwC>ZS=cmpK)r@j)=$`cKgWC^qR1DI6JLQPcXucO92DP%>i6q6UkCzf}}7gegmbV7GkV z7lhiT_YL*kzEL)@Vp394hQ?kY91uYoH~jFSV*`LzOe*$hID_spsDGrUoyuQn)b*uo zv3YW{2iH55B28T^8cpi=&#pP$-&TGEbL3XWc_jn*glj*TXx=lPFQ}!koy@ZnAAQA) zvSAv~U_0(x4+mWWmXHSr6V97!@RQ=KVe!QY-@f)Y&(9e#;^d3o3bKn^9(8%24P+x zTnqI88FIunERmCN;!Kisc}Sg;p{=o#`lERieU0cX>UKCC3x7*^L2AlW`~5Q{#zUwT zqEr&SVoF&;l~p-oK>?*4CfLZVcv7dg$n$CAWTD41NIb7fhix&@9z0+t?_+&h(R#P} zL0e(=#(<9dQdhUYjNvSWl+NfJ6Eh0N8r%7a| zPv`C2RLAo~0~ctBg%+8V_a{0skcwfyHI{W7L2w!IH;M7VjqTtL#P`CH4OV%h$HTQq zf&*tRlF9A9966My#;_gU-UbvNvYH2jua-2%zw zY6q66Y9&zy#%Wos2w#p?bDTk%jrX0;P=$M!Tw5K#D)yI7J{pKXGiYG_^V zx2TKFkI)*48@@&jnO|e)9uqhfa_1<;Igg&Xrn_A+iLn+)Xs1m6Ze1Z#Rgzi=ZBX(W zOX%rb_40qYF*qsULl-3%WLo?;f~LduYgmEhlLL^>a)3 zNai0kIthP`>+yfb-z}d^;^fzpUyi3;Xnn12Z-1pXb+zBY+Gj|K{EUx0K}};?$Z;10 zS=y6n5Agd_C*aJQk!!HLu%JsoXW8}Q0&#C19EFqE^=?r>-9X_)4^o~0)>>}J-2@O= zK~JsG?!^+m$VuUBkx}C6vVylaiW1ArHYf7fOC=j&b5#Eosx9cfC;Eq48ryF>Zov-( z_kW^*Qxg<)He|^K^xmtPGaI-d{dD9T^?bTa&fewucO^TbzF1$2YF{>5*cs;vH2<6u;sK2isyao5kwTi83oUSrcpDtnq*Y zYn|20MTNY7c>CK_cAt=LMd?+^=BBCUq*bn5inUQ$u1F|4RYPJo5dXK6#Z`hXS93)_wBRhNx=-zlB4=)f)q>>g1*7 z6_*Q0N>Gy|Vs}+8Y0{wjJOE2ll9EAWrq}CNi$1&SHc+(<9&1@4w3o$vT4LyW-2U2j z?j3{FeMqnUf#`x203L~h4l+|!R&fDyD^MBERg2ZGI zpm(_HcJ~acW1-82#EycMV-;Arb|tNuz312c`FK7&qrHYQ2M=%WSeFAE@pvtfr>(6>jJlos|^XaIIjc9*Q}gGuz3${>tP$O_mq46WEiJLYYyIR=J@AUv18Th z{-t9FnAzzPWxTD3tCf^xM}K3W$^62pPQbGKkWPL&u*jUGC(ZU}qp{#mb6|(Pf2aEX zSa=8}+pg`!h{)Cw*Ok)M9+9;Kq%wr_1wK4PD00TY#+bBK>+}K}$mC-=2EnB(7(@qJ zP2zRC&8eG1wP$-yTI#JSWapWROm2YMG6nZ+(SyV&7?J^RDMR6+v46u|b`TGLJe%pE z&Uk>2)wr8Y>e|N-yV;L^aSp+8Adp*bv#OosGM6dC-r(*2egNzp!;>}9rg)@G1hnns zYg`22Gadq%Fy{P^7|6ycU6hGRV4G?hzg${WMNJ(3DK=H02&RP1qIFl%Pu^|Hzwtpklh>#|l_K2}|0L9>8lnQX@ zM)neLsH^}K@u?W{L=H>fg(B0}f#etIC{yK#$_K4y4pQU79)E+sC!hmro|BR-s@m6p zI`Ttvc;AjvnP&Wb(%V+5mkr(QEv5GX{y9>yaNVvtE*wBDSzAeU?|Oru#EjjFu;AG{ zQgH5oY4PTI(}gTQx75d}0mbz8GR79b3+mp~YU!n()h1#M@eKe2Xkj5cTLCV~oM7;& zt~p2@z%}7Oc7M)>%bV`j1^L;M(?xHh$?~PQuI;4ruv&R^F0(K!<~)LTz;Nn{_io!q zQ{fc>+R2Z1`fj1EHV!EIaSt4i|2l;xUg{l|LultAO`y{ue%;e!uu#BF0Bc~Ds4>Fb zJ%;brl=;iCLsE|@9>(p6yui<2bFl|xzajU@HV7*cMSoHTazZ%ujs;0wOsz-M;tz# z9II+E5r6KX*r$zpdL>0pkj&rj|F|`SV>M|lVMfi$q-uqeYK9K7KrY3bjY&t6`?VC- z>@G@w5|5pd@@qMGz{XTtkk+n9^^qs{7#c1vQqB*_%|+Za3$mK&#Jhp)zc z74DSzO*^s~&_l-d&QoZ;jTOAv*MPTMF_q6lgT_FgH(r$4=I}$i)j*B_vd5d?ThdGF zvk}=IC>IASe4SyK!m$B=JUCa}GX#$=Y@C>laiN%%tG|o@{X}*MOO~*DoA&3=d?OJP zz<=SBHg@-lB-vaV*v5^$=i*$v4^r3c9kRJjQ?O>w*DON__h4O5I&#(5@b?qjHw5~V zsn1CoAenb7fejMZShXs5&NzD@eP7$nTR)GqZV6W)sT{0F;;|6*ox?Coe{i2b`F0yv zhI!=u7MwxZ)#TE^+vBPUxA@;A4~L0Mj(bQc;_5U!Doy~C)6aGlRcAXtzl<^ z61p3(BcFfTHb7Qi1rJGu1$g9S)i&l6bUb`-&Z^Xaqer7lIz|Ec`kpn|H3s36OMiwO z89jSwZ)*YQ=s5*AD}Xhm$jOy`H;TA{*-V?!J+talC*kGrreagSga zg4#o}-$-YwdDV3W8Qes#O@EpNX?1u*0jtJ2Ayu@c=}I=_=wT^cy3(q}$0{24p~dV6 zw8tzwR+E5*1Z{i7YznX8z-~_W^N)wgj~|D*4$S6F>_g9g95l3etX$L=(*A+TcvH1@ zihJmVj(lQFC~SVrM$AB`%odh&h^-|5Vr~c73hdNJC(K}>k_x}2J%5A$-_QGfO#&;` z#n#VFnll>3{*q%4LW^Qx>8?8P2P?{toIN_e=oA{aCo4oT@i!kQgcRC-H*2aHlL~nD zR|i9DSCq4w2BJK@p@xdh-Cswm=6}u@gIEs@G47JXnW(Tpc;I013A5ULgz25#%RL@v z52u!*Y^%*}g(UN$-ha&nFy_vuxRkFR%u(?!Yr7!98j!tV(msH!t>o20Hee7;`{HpD ztgafBMB~x1XsSrWBYw|7+|&ay{zf^o0d0f>J94QRJf?ph!ax6Kf&?r+&3T<}jkn)P zi%U$-l+xZ8m2;iJ|0?p$Qbip8lJHw9F)8Tdc9WqSNYUp2I)B9WwyiVg^SN&-e1MO_ zK2~!=h`HDeHV*`vagK}A3ZRaZ(6|@TG|86BI1rY`hhvcEoj9k{xPyhnMMI{OhkG<>d)sT&LPLp$|D=REM)K!jCl4!I6jo&j(FP@Z0k z!3}$Q*x|?ZVmG9D!aX@t-HUEI6K+GB?#YKZFmCviB!4%v%KQ^LH{*j{4Z+;EeXl`3 zMot9%aC{GiAZTdup+^Y0?+}0lddh-FA2H+*z`lOLdjWvY6`k{mjwLAUF{cdSvHCZi z%<^9J;6C1i?y#COfFKRsQS@ffRxS-!D(J)4+(p)L3p*q^!sNJv13}G;2;7!_!;g(^ z^Rd0vXMcSIaq2$8TLS2J+~XO{7TpM~U*^It3kcc9Qh&!M%J6XPer2l>&l76Qj?@6(V1qaGN!9(_McFMHg03{pJJ zvu@jc60U=R6+MW%y23%ZV$1Sd3CU)!8n)5<9QUx-Y&e7azwNpF8RIGJndYr~V7AX< zvwsmM7LLzR?_MkQWhlm{v<-FcPS<(Q@fHMghN~uEb!#>xbKTuk=RM3}>d$}w?3s6V z*GR(s_er2%46d4olCPCKHo@?zg6E#Y#Dxho%{o?)C9KhAsV=dPTlLoMyHn6ptlUUO z-y-@%Li|M^S87&-fjvlz|`0TlP*(l`PJj}6gEe|vu>`&v2A6Hok| zM{Q63{@3`l?`*YAA#4sRu^s&8`k$iKbT-eKrlMR_H41d@*AYF@Z}!n*J?nP}qSh(& zZb4B9or_KaK=eWT^3z1ChD&qhh%IXlx?tvhipTIH&zcc7Mgw zUBcwUm=Dt-7^w|3JvOo{=L9g>hJpF&N>jWy1CWMKHi^e?CHzDrHCmW3Hx+ymB(RwDHU&);ueZif3 zf~R>SUQcwoApuW@rY&o=WKQk#b$@>D#Yp1!+3bgBvwuyK>nD?0`|B4^W^`c;hb?(! z-VsG!(%b!J$`bXj7GZl4&A&66eHZ>R2DO!tZnA^FB-|F$(16y(N3PIe#y1_SIf( z4*Dg+`gHP^#qf?5#&h;umus|#HCIG`Tqgy>P3TwR4hGX9qmW}^T0+=T;;D|{$va@7 zjk026U)yOMRHJL$88u4AT(U2{#Lzlgrt>yFn}U=vTSbW2rQmGWOfSS>y<^VW+sW!{ z=oRryY7lqz)UzJUwyAk*;(x5&`HptF>eYv0c7AdTveV4VB|zqp%2qJ3c-IiW$jz&? zSny#yI-a3{GpFd&{NiznnDlIHfO}RnOf*BYE$UKnm`9E&*C+90(K1s~b%^cvsI868 zU254)t52fQY-A@6cbr4g%(Hz-;uC^j$JjO&k_F%CA^8}2+vd_7BY%+2GsV&Ccv&s@ zaCIl3ZACzP>Hz4A7sy1W`Ir_XUbytlyVve(KjbAv{92Ca`|tl9P5$Hi?;}1ar0hdU z^a($T5kRJAUFY)Vt*nvEEUJr$ZFP3s^eL}0TC8yh3%}-BfO~KoE@diYU6+*{>;Oz+ zoSMc5yLU_SMd1U7wtxT0)Z)#MIC`SYo8;tV4IepQC>os3q8FtDxd-HPnM9%4$eE+>CmCW3VWYPrePlqRf4InSqWuvP1`dvJ!@3tfI-q)nx5DC-vrjSX} zSR16@`yj79x{VfVJkoGa0xC#4x%Gamn~$$uI%-LfzI=W0;!XPc)tf)3?=HHjl=uHF zhQTj?^|VtKF0 zj(xnuhy1>>DVID&WBQN$?K=fuTOZ2OXdOD0orrRHYn|WKh1o#;`1!LamedLu3P*a+ zuqo4I+#W+q%U(qgBwI9Kj>Jrj7qw(X%kDq@WGq`2!%i)Q6 zX{3H>l6}io_kBt4%v#6pH+d%?UN}^lw>Uuf(YieL+9LbTF5cB(UN+g;8_zbSZV7Ia zZ~kq2Jg0xz@b|fa?P5Ykj7Frdnhemky|X!>^9T)4=TUh(uSu(!_Y}I}c`GLgAz!@p zLjs02-hUl?(2*4v=SPHxOM_0CAs=f&mS~RYz0hgF?mL~Fv(&V5h4pq+2IIXtb{ zhQw~xJ;S0fy3m!neOF(L=YG>(OO3j}zWXm=H3OP5=)i%YyMsBG-RpLY655$@`ewVK zAfEg9zRcAk+vTynIFV?FX);_gDyiglJCGszG=J*&o#!oVTF;ke^Aje2DaYlFnYTS!_}T$V-1cqoSZoH1 zg7KEvtaP8yxJi2(ca(i#&RKT4ujtaoK7p`^4>{97;+|tj*0Gq@{GE@M;q8bCMt}0Z zP!~%B1QY-O00;o(NhVDq+PHa@2><}27?Z$;B7a+R+qw~c=dVEJ2TG|$HSP2~sN?B) z5~cN=B+f)WlhbiM9EyZw98&}ffR@!v&TsFx3-BWOlD5;S9&8faT`WF)*b7FZ(R-a| zPU*^u-K{iI?4&5Qz7uP0M6Ro~+SpT}D(kYc6xKEC^{J39AB{%Q+UTuF({p~g(tQ<{>rMKc=ESB!#9L)#?zBy)@mZX;(xUx0$&EhBU*t zlb*~Yfgf?5{(m6_hJxVnioz=f9Dgfd#-8>Q9#|kLVm^EfXCV1StE!*zR6M`137gm{ zsOwr*djDORL^%$9z zX>H_MJ;alKF{YoF$7BgjXe3@#{N_w-r0eaBR+*K-&ggU?`HanIFu)!MT>6!yl}@eWr zV=fOTz*fHCR6J>S|9Rpue64+D`FtME|J+_iFWU7=*5rX6k5K z;^z;Gxww(`L5uNsq{{am81AqX=DU}ZAY-r4DDM9Km4kl*?;$rKko-#Kxx<> zPdZ1K`VYCRow!^sh%LRP6LA4oKzrs--WVe*CwAK05m&l6L+1? zD_|fWlpA*=OxG(I_AB84o#E`u2bnj_Mv9D_{PL_K+LyZ8KyXDW*o9=&*_u$Mg^F(-u;9n4;;J1J&_-puJ)y?3{|nypkd zOA<(b)DEeBTN64~Amv^ze}=;(W%t`sRd+Uea)Y`v(tYGLF*ih^ zrLAJ@f1YFEj;X=%fDBR+)WVZk9Gr_N;`7tKVz#b+AtIza;eV(`!Bwgia{P(lG_Ghj z^Q@sDy9Vc04FzKHY5!>-+d*Z7bJ>&RImuRyAZ1vv%QPwun z&VK*L-~BM_Y)t(rvr|>&+7O?n5t-^N!6g@9!^T-S za!UCVbdr??wiJC)rS+lpJ}Vn8X;h`0%1Y$0qGO~F<6MJrct2ymlP4yIcj4fkBT1ePn^_z2(K#BH~XzV)v!uIQ|vU0BZ?lq_+aP1AmVfg;@$10sW zk2FreFI5)0apbcVF-*jCa=xHo)H|T3^`G0=PG`5Zi)dn<9eWoCf&1U^nWmT=D16Un zufZywDk+r%6zxKZh{|8ZUZ9klEZ?UVu@U=plpA}?KBYl5xDwQY`KPjB=keniPP=bM z?)eYHgn#oN;q$-2hKBzeaFYKQIw28jlXDfMiHc&@STm#2sHCvZ0SR44Rb-|JS!Qiu zgYse9kl0}9ytI_A*wnAH_i9Bcd-h&$?2PS@c`m*wvA#jWtV@}o0b`weB@w_{%JasA zkas=*;fBIm3?FuMOsJsgckX)rI((lkxkBt_j(?vx9`WJ&;*c!{2vd~2X2k=beV=fI zq{oof#+i^x*3eH5t3vK&pu(#m*<15fDU*| z4V-l;bA@B-8Q1cs;udwn*+*UB(P-`b<3VlH{S6yMVWN=9GYp=+B+k2S{JPMJ=^j$9i(e2WPUBmzq zO{XZs35sdH-i&U(h3=^hFVC3qVh2Mpp&HLchwzb1($odq8y{HYB&LtuvSi z!f5c(Ef>ru*vi^H&dbb(qJvzcezEr~^ofv=;0fhZ4!9giLfwg8mzni3LC3LCR9SY>`roBnae`bwV1vq+GvE> zP`A_01p|~OFfvI5wQ{DV-eeR~s%^EP!)%fWT>s(Bbf8(nZAY_4osJ#J4hokd1GiEkszlPhkh+ zSVvwqg^Z7eDO(u9z0wb{T_9%9zL5@6aWAK2moVNGffl)=M)$Y003Poli*Jjm+MFr4S%g#dvn`168~SH0w+&~ z)P$xVa-5u}z8lwZQ_ZBYr%A5qxgH)wLK0$%?Zn)Fu%@V6l%M z_63c{<2ND^IWGm{NyP5c{FdFza>cGLuGrDx3wEBaGhWKMjAglDANaEH$K&y6k*8}G z1dFPyauEbfu79&MFBzW~XG~vhprXge3x>&vOJx>}vJ_RKKd3_)6SKfMkT)j>TFeB}bDo zR3O0*SI7lh@q(9S?t+{ibFxjg3GPHrCXvY^bta8QvJKJ#T{~IkDA8k}04sfiJHIG- zUKR*{*ZIuv`0)DAn=R|vDZCA1=?txs^{#~&dVe44_gY=*g{3fjMB)1S>gY%-piz@v z2%B_3Ft*f{q)}RqCq}VJS~d#-7afz4q@c$}5Nj95@js_Bao0R^i!%3G?ANw&CzFXS zu$eF*vbClwJF4HFu^Y=>|3QAoF`)mF= z&Apm}`D~etVoe5cmJh3|-nTV)aMLwH$(NSy>0f1lg0u-yfwWz&WWkC|gmNLn4le!H zYRwP$5X*~n^zL*Q5J+|O+Jb&lmtp~0Qb_S<$`XR4`N8XCQHjIA+H1K)_ zTZ?j)M#Om}z}JKJ5FhU^&wiXS+@U};pn!=G5qKjVcnCH;XCQ2q6r#ifQYGLoWX$Jr z5j?al4@*r_T<~%E$nj4Q@ZGS+n zgrO8*IJV{+Htqqa{*32%M8Y)BL3?A5)eKs8GAeUhN0#I}t@YmW?y`d!eO^(ShOap< zK&QZ{Qn(9(*E*b_PQ|*4F)^X{M94kYvK^w7SDQ(#>mr3c``UJBtuv`Tp`K#F%yxN- z3MN7{7d*!obj%)||F86-9dg$Ep?^wbm`1{m6%l#C`f=TUtlE##LbP+W30`0P`0gF?Y|U>e4eHs$U@wIUagK!w6}d^~7@GigS4 z^~gX(Qxqtx#K+v^j#9g!Kz|lNUM1+!gX!TMc+z}Zp%5TZ$o~)?4iAoA9=)0#AHB5P zm`UvVek`r>x?G{GlsWe@nI0m)u}rFm;NjJAaD3!gX++<{&VGG!@qYoA+^=M~GU4JL za+-N1V+bH>9O8yW3Zg_ImkCC8o|N&1r7@IMuq#(vL#CBG1q&;PBS{I1!<9^gZ$%Q~ z*JFWaUV{DV)EkBrEb9dXB%M;~#RgnHRzqeUXtt(z%En6XV*>G3446;D$XHHa9XC;u zFl&>|vhdGPg=OQBrGEng4@8X+3&1a5)&Gu3fNGIdURFOH+|)YLg72_TpFRP-b$TZn z&_EiKi6jz9xY1BAsu=6bM`88k0|+WH6hSl_=1)+}4x1h_7&CCo@^qQ=HFNa}#3N_N zM>OXx(w>}P9nOkXTE&R)*oLD_z&FJ)?F$qPaa~16tgg)qjDO;QQh0|5vTUJsqXm)2 zXn)&7s2SQFfM{!;Y-sL55bCA~)azQr9d-!}D#ktH3K?dgo?Vb>k0E)xzOYU;)mo5g zv^DCr82j2w<$vPf4h`% z2bIujCAc%9Nq_wWkDWo9BIi{p=(&Z5pU{5gDo?BBij^r_i7E%2Lgf&WICBxF_f4hD zi=r(q^=s<-jh%zrxqQ!FpeHKy%R~Q#->Ry&wSD{*zY~^30gbwlX1=h?4&||_b0Z2@ zm1e4zYz}Czoxx&|3hhx;8EOX5sR%$^PQti~5dBL~Lw}~nCum7!D{!n!c_$KP??v!3 zP6n6A60(&lC!=$m8-gNQ9@vB-z40l#zER4gP^lR!NU)ArIMg!R+cdpJj^RWhdprX- z6{^;Qrb9qfOla%qLny$qkWg5}zzf_-EUo67x|kM;e=l!kCL+oGG+*xF)86I#;M2}O zYH}rREPr@j*wGGxGPa;%)JqI(7L33J=MdWhmJrsWgMELW?Xp=?=5R(rP!9NPBZ=Rh zc+{JCeB?2V9O}rcqiYs>Y?a=NI|`CQO}5DCPk$K}a_4Vnaad$A3WVb)IHL%ivuBVdBee69+BvhJa44 z`W}K>N{;b1N$;s77EUgV*C+TXCBb3nD8pjhLqhASAl*S#2r0@Pytq@nZg40SByIqu zwOp=f&LgyF$y}hH!0r#Qv{jFhjEMI%glx#7h7Hn~tlCb@kK`?Ce+Wj_4UKzUFL1{TjtwbS<>sEsrYBZ& z1KvO^k7-VmHqq?%G$2Ip>}e{a@6DSY4w36@exuXyZ|SI=6W~V$U>}2561nZ9et*C? zt+t>E`Hksl_Kixuzt>i6PSlLisQ<>P5{Y4)$ENBswKh$&vZFe`aZT7i#roWXLymJ# z$@E@b^Qo5u_`x29UJ3O)eS1lH~?jO@F?;!|EK= zBo-<`r%Q7vzOZqKhNYY@7YlG~5K)b{X!7B1+rNH8dv!)t2k>;;tyt4(##0aTTGu%z zy9W)y9rj)$4y&&WFIv;8&~=3_%?&F}+@*w`rhxCsd9oC4Yl~g%Q0yMypN^NQX&Gl(QvDQ>H}e?>x6MHpGT2v7MKo~#}2WBY6fS1$6DNMAKA8rRDs|jbc*7PR2X+=vO)qln6O0-kEH1&QL z3x-{a)7au^2LHONVr-{%RuW6CA4vE#>Z%B3&!(7I+7g)$wq!llsbrx>=5e5friH$W zqwb_fpj5Z=szvuq2G5GROJ~vUud@s6?mId~bb_!dgi_8`M+ubU>WuC=JLq16*sHn0 zU%L@O1c)E%=v#trp?}qIYT$zMK7&IDt0!%#+HH69*-_vD>tHhlOP<6jwfWq?|K%~o zP|niswAKjJZc$yqeWT?zOu6Y@(n5zW=?oQTq8b|Z_Fd_^j9RYqTsOD1Q}gO>_u18q zxzs$bufM^)ZpdaB*_C6p_$Fh5pOSQCF_5I2G*EHV*MA+GjDG=Lr*qq5Jn!}X&4dyu z-OHKS5~2Ul&B1~-Dpt`eJ1tTD9CPy(B`B$?JavtGs02tXu1H*!ZLWK$vZO*U{LHgUH zVUNu#{3+hQD+$>Rp}C#?os70@`zRjG&JLVSM|+$d{2|E_kkL9rs3L($c$lX}v1@?Q zfK{(`3A3LuDWhNbP+rk10w&+j?J&c`x?19oDP?G%6ihUj^lU(j1hRkp$z^R2%QHN| ze%==S>7yg*e*3#o@ran_%G3}U(eEfN3}BLFr>83C`Y%vR0|XQR000O8sTn6tL9-(u zNe2J`X%&;eh7^Brd2n)XYGq?|E^v9xSl^G^HVl5xUm>^;7XyibZ75a*$c7EQVFwgl z(H7W4Q5cF%C+azpXUR#8!~O3g^~08(r0e7Iau=JV$dBYlDpjkFEYGXXbS>mL6URoi zhVh+Nb!Q-V-xmx2T&VD$(u+k!%8h8U`~zdQU`?gi>VzDTpV!6v|s2W zv>+q00FqiUQcD?^W)3haWu(L^QA4({ zQtx<+DhQk23}KANu{HaXYij}@wsb@X+Ca(P-M?cbfOZSe81w#D_Et$4j7&a9;4(6E z;9A}p249<66vEU!(+w1&5>RG?foY)V$s1MJ^f6Vrpxos1Yg4esP0ge3KHc~mx1@T&La2;MkXq>%k)8Y zbxEMvQ)}4sqGyFF@jPx0E2i*qdlvYfGYlbeemU_V@>et0FcZvH6X_6XNb-&skJx{! z+a^a}ivtvYkBlQC!nGV03$L)i2xJQT0-3I{!RL5>|Rg$a@f@!E{`xlF6><_j@ zp2!G`OlV5pa#}X&pkh;eDIUthCj()h*dMcU7UqELl&J>fa^8d>F((+?Ht9^Yew83C zAk3Rds7>PvdF$CLqfTE|=^$hQ$aSxY8n!_`+k;tuCidOhy-S=5)EYLolx-{8moIGX zR;sSmnToUE8ZmKr*62Q`{hO1C9j3%I~&v`nUQfJPrMf8 zh9#GOy205}A(+nF6ZK#qlBr61jas+tW7~mGB}O*MAc5eM?wc>6X%Wl(pJ54ft`QQ~ z*FFkjm8a)xsutlCE`U)ABi z2O!F2M#b&JdN3=mN~!zSq%)jafg`F=L5s|P0YMW_EEUs=5*p1XGD7m#X82G&(*mIO zzdFyi(`F0d{$}t%)N2&3P%CoeQL6J0tebFqMHMg&+WFaLxovozn z^NfxIuYDk~s%z<)x8Z1sd_bT`Gz%O;r;X>2vHLA(rrPM=Ewx*usgan!;+X$s@B8gw^i*YK9vR3_6cVv+#JzZWC#zB4A6vNx@&0X z@!!17(f`@(dYUwA;!oAdhJ8v#%fD=Ye|nYun7vF^EU^wHpQroDj1-WsM&-;MiHk2! zMy=-?rRr;a6)3?|S|}jtc#0OwC5X6Muk2Y=54h&@uBKe?dJDL10KQWvNHeedRv9;5 z8NcXFtbHnX+oGN-#yTwwjq2W;8TM)-;*d*&o7(;`Y2A5C%$xUKYP`NVhlXW;%~yS> zb#_7F7?=e|dn?$t4$D`bxo8CCXrjT91ep4f>yxJj-Q|0DzDshX=3sV<`<8tg&*-Jv(!}?Yj9NnYunPGWI)dOUP}UjPFp!5eV9`94cf{cO{gOrD2-PW{4{~8X`5V zl(tKQi&#vS{UbBWp-3eF600X!uaf$L7475(o3RgSIuMWikv4j1iCB4fJpn2W)B7*C zzW{)y-vbnm;K)uG8W>Q2xavli+<1zA{Ok2!8}=Sf0?v-}*G$mQ6L^pzUutEGhSt&1 zCEAHBa(%ph_(^ZCdzrlgB7I_q61%Tl81#zS!D7%6K~uw>6xl&eJz_rAVHfoyoR@A_ z@!ZOQx2RnCU5D>PEexWrESOR z-NXszeHtw@L)+fiHwMX}VZXiAEGEB31}<5REnw}Wi+=%7O9KQH000080GJXdO?3*} zUg-}2017n#02lz1-l`veHj@7CU%~YtYa44TcffucpmCT@Hn;$LlR+}M3y=f~Ez!2p zvgn9%cZ|jU_kF5JN+d=1bj}ERY>6xu>-DK3vs^B}R2S9Ns;h3|TV-^69U9#&79USa z)YGeed?lJrT$+n$jJT-&p!>6`g*4)z+g3lDw~Gayi9ug>t$I>_EoT09ZF+T9-GG+@ zA6W?9wKx1x!dz4(B+UdB&=Z$l|Ej8Ci+M-c*R3)}=!2+qcW9exz>i*ZdMKC@K6*H* z{<$$qNU^N-b>FIR$)!-gSL$LJH=>sqS@Ya|AuttOJgL5KYOr$M@1h+~d>6c@Xh5Tk z-^}vR^k#qnu3f!<70*p)mSX)3wiK-ZhHLB#i|>0S>)|AL_-3(OE*FdDe9`?NT75h= z-Enc~^%;9@TZjNG8{yv9>L9P}P(uQCOf#r{(7GK*R43U$ZTu4IDaxk9kWRM6D1dS7 znmPZQGQ-r&usxwyf0}QeaX!SW34Hi*rv(Q%uwR# z{VC_hRHIa}NxUzwhIk#+Rw(SES7qJw_bFUt^(ez-tCOl8OD5)w#*`P9!D2xiLi-P1 z!^Kez|KMkT>$2?RS(W8xu~<~Cgq^eh!5r6mPd>1*?gBe;FN}CTHPuO24)C*6@R~u3 zz4C%n_2<`a{7&zjlZv017#Son3Ekth#!Jb*@!Wvl>%cbpNPF`Gy$g^N%I@aZE<9@s z{!%&@E}>94s3W`sd;aHAVQ9bHiX}Pxt~u<8V^!0ClR@tc);5RRj$SVRWhueZMG28N zLs_nkY7bk41a*@+DiaN(_g z*i5GHo+PTw(1Tbj8t3L>CbWdzgU0o8>}9RIIBrgr^nsf|!(P?2r}nTZ#w~Bgfv^bp z_>2^P#b26JWMsaWR-qAIa8QN+8V|5y#B2K{e(8jbx9;0S{f&74&BwpL6(3IsYtQ=H z)&jA<8?IpKM%IYcT3Nxu$gU8XSwpZX32%{|I5tlzAm-H5k)2v|lzTQt1b1P`v0!?& zRkjh>ZD(jR-O%2OnCHMAz<2N~k&IJrc|sI_V^e)k$q20Qj_{vR6i#f~drD`|RPr#> zQX=QrQb^$OlX$qdBaHK3lL2!}rm^#<*=bXFc$k@gc0%F`)3h|)#Zn60kwg^!P9#dv zv!YB4b53>@q`r0AP~sfpgwu`-6G5~pp}xT7rU(j?fC-LaFN&ZwOkiT`oq^dJ;DVih zIvfy;DgF&)9A|~C!o?{-j)8bh_K7D=FGBVMXYOf%=dRVT5(*F<%_Zc7iOxA|vI-x_ znZJVVaU^2LNe^a-VX?o7Uw)x9HEqiK{V%^1(|*3`DkVPLK71`;^8!l@O%(z>Y)jU1 zkU~Dmrj>wEh-ZUy?)~Jg7mZjzAPYi&J40hu4gq5<%u1gLkRi!jpkRJS+e1nn31z`$ z5$Y_65NG*lS7Mh&rZN*p%^{9m404Kfw4ucEi)%-J$f7Qz z{QZ|`3VG5xofkpgC)oletT&SlZ$1%2UuG&9uKQ>-1WW7`c*`S7?I0_;1YU43_5ui5 z3WN*HimY=J7J9qf20v-FW^ofK@3G^wR#z?*JcK!sa9U~e5iGYHM+NyAb~iqb4a|bR zf)d(#91^kmu5!83*&f^Wp=k+!kx)c%B>>yogx?GCKiaUVodQ|`zDI6FZA8J0ZH&Up z3BaCXS96A~!82v(J8wv~#YJDPlx51c=^ob`4vNM_#mZ)iy@D{{ev0!qyJHP2Cs<$t zYI|u2R(66YiQ#rpll=xE-dXXFKaVe2=ZfnIyqJoMK;D5RaIv!B z6hzmU5SSMXGZ+(-=K?r<9iZ;Ulpe-7XgOupK%ze0&QZ|A9MvbQtKr&r;w#w(HmKSc zDcTYuOXp*M4apc4k8%Ki`abETD9J5B?g6SwZJqqYiokaan1FdF(rYN*QI1 zq;|WP{=U@R3YCB_>^NHZjtJ?a))e0)L97u#2nR_5GSd`8J(OfZ5o(xTXHXoBHZ7Vt zY+Icp<(2!}Ce;;J`nG#hay`Iy9nD#Uqr(>tnp?@g5kLI!!&~ux9WpQiIdBLzoj4*# z370!2ZP^OlJT{jJ=}y`rCA!D4;=Z71B#n5GFeitK1d+Uu-o|ORBx*3K^0QqjO;Qia zOjprR`-;Me0L+QJ9~@m>$E8YOdis*Jeys4Shw zAbCCdR0p@CFk*~VwOyA*7vM5LSIA<=YHZFINUxzrRCBn0*+uZ&*BMB(R#$cpgf*wm z0-hstN>UObeD+hCfT=W)`GewnO$c+a1RZxy(w_&8%jaMx=2Gv}uy&H%^ZeNqe=6J&Kvy!&WJGu3CvT8?pmD|XC z;wl8QHcWEYpK3ua5Sz9cZnkIWNf$zVg)xK-cZ?Hb6gpKZ&&o!h$X$A+LMLDknCw3w zMWdf=?^(RT1~p82MP*f2lOsK&Kp;A^Y?qi5vH1#r6d9Hb^iNoGB`O`ef)9jSve58_ zmi&BaYF4R^_q)fuanoU%DL!cn*UJu=4V8bQddE@j93aQad(8pc5A}y3kUj;)->y^_ z6Q>M1VF_Ok9O^TasC&q#G%gZ8(iP&UK~xN-6hRwqfZ?G>Us+7L4M|bp5@#}7xCEmuGTb6n(hME^lxYc< z4~V&hO~wDow3=7JNcI1%gNf^V;!ZN?xVe0C4SKPmJNj9(9Z&*ziT#Q7@l+~* zw2_p%*l03a&iAzFoF({4r}Flooot9sA6>+!>{}~@#&gp#NIlT03+zMEalLJNi6+dG zN3IzyPDgAF&JP`EcPH&G^6*-A0>uvUj3Q#J86E!8>pk4>CJ_5X)hgL3Ds0I0r8rz+ zHMHVE(!p;LZkFuL6-w+l+=>>Gs}|dTFz0=K|Ls45NteeXl`$73{YmVIB8l0tXx`~= zmsVGA#QM#D{&j{dUxjIZdlhDVy*pXqm1kX3-H>)uN28e`z&~ZWE@^jloShy--5WPM zDas6_?U0ic27)*%f}$&GVXhK?4Sx}i4flBmP~AGfN^?_q={f6+YI_(Pm(RAq!ez&jjE3dM#bHSXIJ>zgD>BH_dN$s_-!y(?>Shl zefHi=)d}4J(3P?sA8x6)RIy`!gug4(9Yd!EajNh!L`*$@L5Cun#37>^l<%W}hrza8 zqL&^-Wpm(2eRHJ@9<=5vs@@LAx~~$_4#d2YGXU($B2ix_`}P zUGurHALvS#dpDA}?cVqK0y}@OeK*KF%bwEh8uSX;AI*>d@$+j!6xSh>1kY|scP27P zOtD|mtF^iA8F8rJAw5%$cX*OU0fu=MmG%fBccUtkTZY~(v6%<4q>i1v_m>nNqT37e zalw6zhxEEe3aZ0j_Ob_m?|^*R_K!m+qo;ALu1izNu9Qc(^Ol8(N0yGA9{G(E@_n3| zh;_cTgvE#C_k2RC$A|R6O9FwlrZOS#i?(?$wcfdD@nb^pXCFMWDKApIF>Ms|iWW}0&F*NjL6(ZIb{Xy4uL&JG!UO<+wS5F?cv6dj5+HSC z0}@3lbk`?}Z0F>ZmT&s7X>M{Ila)KAUnR{iYJd}P20zFeRPueoAE)yvpJOuP|CqVY z7un7%oI3z7;hjKc_bx5XEohst@hVrei!svIzU6}Woq%AWbs+Q%-rsC zpVf9%{Hp1+ImcFiCRkc2q)*NbgO|y@Dcf>xx_9C{vn02o*zrrwp6<~n9FRT)EgTO7 zEoSVzC|{rD?hENNx{ai4YY0&7iSAQ#yN|{F6W;%{THO~iZD#A4x+Brq9};RP zH}U5ewdiy~<;2P-p|L}zghqPDh~b#J4*Zlt%fQx2SF?6hMJ` zJfO30V0isaToCSt$yv#I_`*-8-BIoFDtp-tD$I~c9T=R}(upYZ%6szn-Js#KywOdb z4yBp2SDkp}fXsM=>03_I-8#D&V^3rK|71b;io30UF90a52gIU#rQBELTZ&5dZDXMT zaA>3W;AxV!(~&1**NLt!@uTTd6GfCwjNz$4QeRuXDltFUn>BE!drl$gd&hb?a#JPy zs#)PO1P@6aWAK2mm8kGffSylML@A000MllMq}KlWx2Sf3-bpa~sEz-}x&h z;Hh?D0jr1YT#6T3CChZoiX^H;DRGM8Z5F_Q*bvx7_CX49{NJx%^V(fNlJ5>xwus%C zo}Qkbo_R>-9*@@*=Bt zYMae(vm1@wHd&J#e~kdtvMM(!O_y!cRys{pz9GojtS;AWqf`EVbR^H`<$A5>OK2{!icogMf- zs|o;C^BiVbt$+WG!N0B6b+**$?Dya3VqPvZH`1FdU&EMHf2}Li^bLJG;s)D%o1}NT zSd{kt_Vy;NbX~U9T-Uu;$s(^Cm|;@St9;wkrq?BXeU;q;=w2UQ2*5qTY1%&XtSF0o zo~`qL>9oi;y5FM{%SvfMsKz_ zr0Mt$zWrv#@-`@N!eeu)Ti$AAt-@kr+{`yb*d$zghRc>{W)&Qr# zos};Kf54m&=?GRh;t%;8DE1OoaiT7W$AF*Ju`0@cW+&>$ZyrB6IwHB2>W_^&RZ()k zT1Q7me>r=5d4BOaeR1*X&GUEX-@iPAm+_N{dOSWlI>Lp9J%4IMP;#T2m-H-7X|JUz zHe2W=ED%bq737BJKw?rRfUSN^+W+<-!!W+$z<%R z+8QS%0x+pp+0$=-ACFPyV*eGO(tSrS7!JIBOkeMF_=4mVe4=U=ja62wCF4Ovgdqt} z;9sA;;^jmU>UI)i*U1~};VJ$VQ>$^%V3oAnMb>El-6FryH4&ciK8@7FzPyc(91QLu zfAbqB3r!6oloG|0Xq;3vh_Y=QokrZG62fvnOIleT;w_kR3dc;$!ej&RWNN@`a6}|` zx~hS5fJ2w%)#GdRNA+~`GO80}d7{PWN1?b(Zqw?7ca=^DVU*Q(HZp_)?7wBkix z7y`<%oa8k^^>IANkvyf4!0)9#QWP5LH0jS2^rVi`#gA8ywobt{mqeLxP~C zZ30RTpjYWc6uP(q7W(h_*_%J&e>`DBeP{muE_wKD98d8pKE`k3XXD?F|iiC>~ANW8u7XzUcU)`WINDSU6=Q8j#@!J%nC3+?sKX}xX#nOp2{Me zs0J2sG&~S~e3tdT^Ok4Ue}Rphg6>xBwlMJq&OT8!-MN6`#ZX6ogyrZp@<9Lc>jaMo z5uxu^IcT7@T9hz>nVx5Dt<|n#p8994@)RgJ+_WqaByV62F4ii z*52nMzlZ51vPon;@y&Q&qtS=Llcw~d*7`O^)sC@-r0b7F>z0QHNw{h(;Dab1`VPQKEQ-C~xCUZ%ZOXX&Ol6F(xL0e)2qzXZ`;GhF2 zUq%Rey8wX0xK0Ktl!2phLfzxh>B!O_CJko+qvS?bDDWoOLSzYWNS)p2G@F6- zW>zMJotc743C6`wu{@I{IYtvkpQsqEmMfU%^;k{6v(^heG3U$=8f>Nw?TaNW#ZDQ= zK?Zx8L{y=0e+XJ8_SArI5no4gN}ReKv-t& zx}n7cD|qY(jJ6?C6YLt@T-%d)0s0Loz_89elwtd#e@)NB82Jz1P!PnXrxPyRKNZE% zv`6pKo(|zuuH10fNw!$T9z45Q{;KgLiO_`wdjxg{E+fxG?DJg9@qjBQtHvvYT!_ta z1Qc6WZWjx#1u)GV@QrhOBA4h+*z#`3%^FA_UEJkWS&$?e;W)t_7ogaiI$g^Y&XIYQ z)2YGGe{5uDhsrjnZ*I0S%e+Yh41VZvotJ2`5$_=GD8TLjGr;xEx_}TmY)AzfUVewh zBYQcq-2iP8Ja>yl+#^eu2SR+uA{_`0A`9l<056?bj%S14JfGO-D02eVNKgl><3Qu< zA?F~CX$Jz7U{=)mSAUNhL=SG#AB`XpK|zl5Sy8{^eKDaz+VDLDL(|c?UQ&*7pIb5faSGg6b)n z$n&f+n^8`tPe6)4R3j3^Blyd_ffqr4+13F?4f6#JN2tT$oIGi$qF;WEST{tC&J)tf ze<2iaVaF~o=5+gjp+byaYxK9CDIeaDxwc+WsD5v;j%5<6<*R9NBY1il-5ykneB3p&dmD(|b~*g2SZpb#|~29`>8ix9gJ|1Ipf>x9s$yq}lb z9KNzk9(u701$I4tLA@t0GOMa1e+Y3kIsoz=q}f{gfk`7&)$#AxBt(xtMoo5O3+zT0 zy26#T;Lzu~^PVr-${hIu+W@vkwg?$-YU1W~sDk1sN3cKQ)wQAE3*JTw!3+6dZwX4I zlHKbFl(L&rto@lkRl{F)J9hl0oybtkK0f+;z@cLzoXH&BL8&<>e^Wpd3=G>e z%5Olo&{5wfM}a;pFPyZu<8WtC&=NA=$9w3J)it`l*j(fDeWK#% z73zswI7%GizMgraBK7bfD&fatf`=-ad|_|wz${}>9Pe?{%WJc?ZrE{;YnSBP#jV>X z%(1$>&9|y8(8qyl1vVSvPL?k0?xH{AE8s$Ij?b z^GfsC0H(+~``3!zf)2m{EpSJ;$8*-9W_n%Tk1;}1fEuFft~y8(rWt_5F&5{9Cs#gq zheM23Q=<#qe@0i95-r%2^$YyUnbmsAb-8ke&$Ff1PQf-WQ;3-WqKfmumnTj8fj$ zM0RWm%B)Xz(bB1r0VD}bCa%1H=bAfL=lj)8{tNwsW8EE*QW0~;{qD9C2Qj`y0~#^m6~MX7*gsQEoW z9{^<`;K1{yMZ1eere6J}_94u^=<%^ zXpJl?K*nrXb=lxw1L!s^$1zLP;5w)Vfnb15e^`O)Hc_J%fsGFEBEI*Ob1-pWgp{xW zJ&V2&LgPVdoCEu}6(0gHQQsX-TbjbJ*uod2d-k!HxUy%PWpmuNZlU1O&*{aV_ss6| z2!@|6Myl$XobSF1u@8~Rf$2{Frfl8hGClwK{pDN#>!04f@xNZY`)Lr~FeZTRd<6q| ze=Fi4H?RcG;P2-J3E{}Z*`sNAo(*U;5cM&i&#^!Snqb*Ayu|FAD7LSujcAlkn;bo; zhtx<;7g&~Uu^6cb=t{IvISCJgsRyU(B8ZE#<7%4@=|E;kFlazy3_{h-$0iD*-xGD;? zD0U+x-S!><&&gTjQElo-EyVA7Z(;||1?M@L#d{8nBJ4o6Kb#Ddm|Qqp(o1K>e=P^N zQT)n1BrBo&6isKgiNZvzJy}pPaMzF<98q}1*xi`#Dk&NRIa30_Wp)lUkqHd$g`m0h z{~n%&ai8@49M1pDEy8%!u;)iY1MK&q|69io|0C;%Cl^k`yWkMBo5;Al4VkWO9OaC) zAJi88j0DscP&);E)Wm}?wN|U9f7#Y2j~?9s$G0Eh}RIEk}l5A~Fkz-JvjgAEiw9&J2u_HyS z9>RT=H?wwrtDB^(ZWw*JD8f^C^!2xoya`xrFxNQhrJaFXZ}W<5F-Fj(e{Kj=wnlYr zr(%-_;D8WlT|MGUF@EY}3?hOL{E+6C`DP2^Yv*TNv1R{})j&`{ZQh%bL=V%jzGsug z;0yEy2@d)(rWZ8X{1&s?=D!j9Zyx=oZeKsLhggc|oW#U1{u2g0%OqMQ}vvzO3K6-^+7p=3@at-#nO_& z-ACdqYodlO9t}XkU|Zb~m8u*}aqP5eHtS=N{8K+If=rYFAgE+uG?k*mptmq3DHIwC zvtH7&FrQh34Tje=K=>u-Hsa*6(TS`_Hx9^1&~+1X@!5tOuGC6Tc!KR-%y=7ohr<~K33DOri!!DPgL71r+>gF12^V&wOj;y5cBNE_RiFU z*qiIPrVBad(hD7IX}ZbsB2DFF!-SZuy1B!P6O<7Sr$}5yv8?R};F9}i|NemL()ihb zpl1>O^E!=vt*pA`q*x=N(VfBBhjEQ#Eji>k85nGgP6Yvm8T{mp$G50?qQ{1$s~TB6Mq#4q z6k$G1{*!Vy+#QW$1vCULRXP4?j{24UfVlE2-6}ff4C;mefjslD@oYg0Hp*NsgKB2oJU4*jAxJ^nf>i7=tgy7 z1!k7LAy2b)BW@r|8z$C&Qx}72HDAd zf6ORVS^e%*joc!P_9FKH4Xg)sges?ZOZ4jG$@RoTdHkDk{+zMC-ZR!`jANPthv~Hz zOO|XwPk`bg^t^qBIW#WN6$_YK-(iC}apqoHh4{xG7V(GV!(#l5b-dfL^CH;Z46<{# zN3RXkt6NEu^O$uHfBH?jj5^T$|B7RMf6&6Z1Ec+~`61Y?2RUP4^#6Mn31&UWD*+nJ zGyxGl$w5AVc=}<%ti+6DAq{X;XW)aZWnJA)C$QL{jQrF4^H7}-Gk_DXtzu!=4D*Sk z`&fOa9-s8-o_6kb0bSe@q#H^22yOYR$XoE+JDzHAlSvZl9W@TD_+C^($vKq2f7|f_ z*Efj$CvQ3(7|;iYX=ngZQrP=$5Bx~VpyVcEg0xG>MdG8Acn{&t^gE91PmumF`SC`W zA$>m$`WL*F7oCuI>(}6IFW26t-IDHH`x&a@*|pyehg;5HU%q?(^5xlEiL+1zk1y?; z;88DkSnU1H5R!Ml+&-g_jVD%vf9G-ybA|`QheDuBoEU@eJ^1#|PO7cRD)QckB=jvkn|6OuD#S>EDb=b z4P6ud65C`UoPuc54MOgMhmdO})0_zqF7L@nh!VM-#%`)IXa%E6u#0@== z{?!>Zwn@B8m%Tgb0NjU>rDPwY?l3M7czMmvwkR3^D{Clsums3ZsyOk9uuFMQWE(6t96B z-9gKgkSp*A8O@Z`IJ#m}ZDF`Q*By(;e7_uTTD#ZYVQwtYy?9zr+cPjLy&P=_pUiQ9UgJHhX^V<|}6M(`o%VC6FEWjqp zi}qUKe+C@RDSm}>nW$Gd0DFmGp=lmo6Vw84fATw_M(0YonV91vLZUlP z=jP;tnjP6VaO;{XDuBpgGO2a=Ak1m7Mx?Q_;4u15^=pN}^DjmTxTCWO59+Z|fxCP| z4kxqnVN7gPk~4-PVSEt{_N81Rgndi*-Hm^DJnl@5vPBHsp_zHN(?b0_z#%$!OiN*; z46{W+x9HC>e+rf51Gok^?~dkcER@2eF&*97vVGui8EQHl!MH1d5h_d23f;JO7E zqjV$%e}G2Qky>y@HDe8+a07BCjn_Z^oSc{^-#+flsjEBqSi`%6ND}~J^t8!t20_r< zZWr1GCS|nWhh9fxPyYzJ!>$?b2rmwF!~L~qKzI{&^yvDWQ|uMa5NJA+Ox)UBf~89d zYu)D*q)8o=hQLq!aiVq;^)D{8@sXp*0Zn>JfBVihqM75Pf4P1*E8FE)Cj#VPO0iz) z$8>{b3rH3qR^5Ag{*Lu@a?CBPx#HK&*1qY-n&U^oZYe)Dxk%yX;hXkdk5+quNim+wesW>PlQi~S)II&f6EI6bCCj@x0 ze{i~*ZpKdriGj= zfxs1&O~8s9mE7!2=db~W3MjDDe@$J#j$sp6gvY5el-~-ReL>)o`e_+;l z_+X%mArD=b=0CkPk`W6nt3-7)z<$}bQoDw8*^p5NIG$MoB?L`1ann0tHawx2tee9zFkzc!@399BY?>!rUv+pQeP3DNJMurgL0pwElXxDCgXx0@dP^yQz#;7u z$c-_4DaQBL?On(KdWQ<$022?VL0H2mh)IbGR~%h7bW;+u`pvpwc537=fBP^PVcY{K z?Ds?YA1uWgys%dqcmyg&#usQ8C5A@fbOU{x4$ijL%XS@Jv0`2#$zxclThzBxYKwP4 zR_l~1u6kjv*JOgc3Yc7F<2d!+J!lFk|O3^;XPJZ;Rf$M7FgCzOA;g= zL+EU6Y+V_UWyK<^7U=vY;RWklOG=jq&5h@%D})Q9%H7Iw(X=JAWZrQ(bV}g!%_lCH zpKjfa!fW-ARK%dc6Thzz7uSs-6<1x zlYgkLA`f#~u!Vtetv>WN>casI;;1Xd9oY}Zls%*#f_6QcPPyk4dXD_nyAFpK6zrWJ za)=%9iJIRpPJJ%>f4t+fUX}M!>&Fz|l7%^ye}}FVhQ*G}=hGrkK%(ZD*Q32i4QE{Ejam+qS2gz0S=)(;Qh%E$~dExjUk zonq3FJE?oT(d7#V)Z+^qB%1VBeelo-7WnYu4lWpBfz%LXe-bqKPb}K-f>C$3R>mr- zvB+x8v74-IO2Z#Rb(DMq%U7l0w8%E{Q!*!bDVpm^iPwqG5Q@m%8`YYuGjW)Q?9b)E z0tFm{cVw~1{b~1eNPM?sK&O{t@tHVp2@l1aSY4QucFe`bda@B{4)QHAo!b z3p}aGGCuW9)+BuC_dy2ZL<7fXJq;e27n6;!hI!Epi0Pp^FwzgEu%~Ffc%6NU?Wt_< zNu0d`KEmoY^s_Y&V55i=H(O%@1u&_$ay0Qa!4Nb1aPa}sA2h@q@A(bY1p3R1OO6s_xj5yC4fT(@Y$|f2I!0bH*k1=>W%HM1&z|!WFO}i-A6|tTS&0$_~hyeOeL)U_1{y-omECmGmHdzi-D9uKTx= ze{@=-k}hVW zEqws-PEN(>`ynezoWjWXqtAA^TCt(_xc~4Iu%(d&Juj92IZ%{w-vR}T(@{zH801n~ zrsIhomd2mulOA-~_L~mopgNR>=ND}Ce@_zevotguvZ%T7a6FM%tu9)PydK*fPFfv&|nx=yjs zTmewB7iuq5A$3ZqD&h11AebRKInfunpsLBU3{Ms+SG>2I=<`llwYp}fu3X^YfBxj= z>YD2Ne@XO^hCz@hP31Y6Q2VPmbU!1UyCa;MDk@@yKjD&9w|dB1V?Opu51Gvj!rIL) z$c^UbUKlui{xP7`u4Bru_9&)2axLYgtgAs{RM`!fXfO$rI&@o<_r+lp3^m~btics8IHTp36Vm6@RAA3Kw8$0o| zrz9(W#8mg~tS~XFkEO|n_VOPJQ_cOr#N7}79ww+kWzySIY^$)l^Al@A{-smnXZnK0 z*ne8>KN3Cd7UT$4sS%m~NLu>}b8sjOdgF%ei|CTOEZenpSM~H=YB;R&Q;LHm7~WTT zLvmO|Wd>h@sJIc)#GzgNo3WI!_hV^(Nh5H-v2x764^>;5**;>H&=1r4qtGvgJU;p# zP)h>@6aWAK2ms|tCQZ(F>NIEo004vlml2Tx6qg1{6c3X!>~aKSRx?ersO*;q4$L$% zP3~w9ygLg30P7}`P4p*!)f#JW+c@&Oe+A(pu)OCOyTIO;07kD((yg(r6Xem`q9_Pj zqHS(vQA<)ueT)A0o1sWal<2gF1A2P`f=JZNa5(Q7c|0D!WSWz6x!$%)+MX~KY&Qn=z zM6)VOQ!=G_^Q`@yKIl=sWhu%z6@}rdVEH`Fh2J^dXMitcp^pI0Ep6rDlM#XI+%j-w z5wGq08M!Yr2It&f@C~bSqhIs9d?nSM86Y+rO^?ynhM7v!RAyXzr4MLy;r}kuKu}l>lXRl^5*XT#hc63JG#2Mqpz;+ zR~JXP$mC;@OP2ZFuSI#wwT83Bp!w&N*Aff4eaSLs1T$|9mr6;H%(8$p=3oqf3RqyDIVG2+bktxrFVe6dFhOcsPg(K&|O)Q+qx!=HAA7WQR z@jWk0)K0;{ay@tM;ZZd=RY|=I9mU!UoqCilH?&l8J0k^JZZ7`CY01p)I5zlpX1(0= zD@yvn6&eqJO?N!~bR5+j$_}@0-(SC{=dUl%f2B9~tJQM#3q*lUWckdB+)@oG)b7Y~ zLY@Kpf3P$1>gOMS8jUDL1yHgeA12N)Cm%;66b$(FqKPVS_&0Vfp|oIo2v5_|Xk-JL zH|RvJf9I*0);u5(;ICxCaZliepEX>309*NJ!72@ZcKHo(JCS9)0Kiu)*B!{UlzDAt zThK~l3?Sy>;Rv(^&-eyHttf<{G|@cYfHgvxMQtrCk~;=ob&#W<9)aMW%_?3K%l_ny zAceVon1xiGQ*hux)9zzC+1R$Vv6GE$+qVAECL7zfZCe{_W7{_N?EAf^>O1FdYHsFY zy1J)&p8h=`mdrQ)&IRM)IdSL-o@~-3jkt&u9GCfazP1n>R3;Ylqo!IC9w5T!V~8(L z-2BuVz(Qm6bN4ceoeBjXD7?58rHZsqfWA4%p@YsZroy8?36A5&sN*Q($b#(3IW3km zU3OLl9u2?Qz(&a!sZhznS79%6#xb3({xJp$^zx=rl)xWj)Dfq~k7?*g2=lq97UB$~ z0BUi>6@ln!8?;{H!y=b5tu_P45Ujq2Ri|G>0HnrFpg^%VjOO!t6Rby%MQ+;yNpnb| z&>ex4WNRqgSfTQrP-}L-L2ZhiegDe+%P1c2sidi!0XsYDX(9VPM;_Xh*dD15 z78qp?tb*F%-@b!({Tr|BQW+?yBFQ2%;jjxLA`Jk9U(Pd)2*!650!grW|gAt{y$52@nWb zQnEmx7=p1}-7b+#*A3zp;dfcD3&4+0?is#WwK3^!F>#wF@h=*V?UUgL zeH;7iVUIRL9g_`FyV1l}T8^UjK~dixK8E3_ovTOD(hT=jhl3q&t>QU@QYcs51?t!H zRIt2c?V91aJ=epjXU0N}R$&t)rbvKLQN4D|cIGgWSIz@BYMqSB93RSv7kjy;K{sv{ z83&;<^Q#m*Fr=0g+%^(i6-@AVR`oU;y2Z(imHikx0b~=G$dxzg?vZh;MzC+lT>peO zGx}i@J?I+&CW0c$ zj{#1+GIckVR+P+*rpswzez$HGqT!7{cn&A+4Cq9Z%M&&y^ry~legM}i@au3?A(5Kq zOG~J()Uf~Ng}r-XJEhg5^t0FvOQw&S=B9DViC-&{!HpZEyc2TF!&OU#m=Nj zNP3Cr+V032r0iLjVRxDc47u=UD?o*W4hIQn=4X&|vYf!Il=)+~2E!8(@3j3u`Ch`` z-=qEY^mK=S!1kQ7t=h%t*dG{&D%lnm;~ny%lm{immR{W#((>sR@0>dgH_aB)@clw~ z!LPgN=0`Uy=Luy23X!y^{MnqOucvU@$TLZKkAD8L3`m(q!}qc%ptjPEwf*7#n_=}; z{Hz@%Tamnzl~ZYj{p;rL^GaD65Jb+J5I&{HBbt3`uop15;94rTJ#;vf@O{vI>FQ0d z{WF>9PeQqE_yUSr@)2E^e)8;_CX_P!2Hz;Re_grNogU8UcL&i28!-Ew9=k!qfK?Eo zv_WRPD@eLKmMj)=Kt{jpksKqn#m^ly>|zDHwS74T>6~%)AKC#Nj<+NoG}wM%ZN*%? z4_|?WP`pL=iL+@kXn@!(7*`4Liobz>1C>lO@su^+DO3uYjH5~-m=6*EXUc4B_pyK< z|6TY%&?M$JVrY8!rs^%*30f}hawfeDOH#u~8_WjxS!<|bRHJ(y#K2$7wFrU}nl)F@%E6TrCxT1)%$r(a67om~n5%`uy6atO;=kMDa|zM=<4`a_Wcw`BWvfS|+V1 zZIjkW1I-p0@X-sDiXbn7cWA+grqL?x)7ta%8KDWGSkx>{adE*hVpzAxjH2lS=QvvJ zr1OZw-ESXYkRH)6AHOtnVEVRcbN;Hc%f%iD2!2XB-$^-XAzDQJ{i__=ZoiD)8++|P ztOjil;85K4dZ@*k@SZHFK)aujo{$aR*pl&eIHoqV+@+&}7u$tNQ;qNXhF4!sHmJ}8 z6y{7ZLw^m84bK@eop~tK_W3u583*~xJCN~!HzxU)Ynfi>J6FXi>;!?+U)E`szz?I& zbh6-p=LXVuxU-h(0Phr>1Q#d;?(xebS*ZemD*RKuaNH5ikcJ{|jku8@j@TlAZRD-C zpXUdCr3$~lKz3Xrb+l{|l#M#G8hjUal`fi&5lA#20J@xxL(9 zzu%yto7^|PQVXcMo4ci9(pSEXP9!p zafE0Yl%Q*vqwue~2Gs^tFoQRRSiK(|EtLA)0HR;2 z)~pz_fcm^?tU2ygq^hET=F!r%QN5sQp6|zmY84W7jd@x^U!gtL&e%|*&LS8qQSzy;{+-_7zRfI=%1z014Jr5$@f?Ti z3Mcyr{?QOx&z^}X^o`REPH$PcRxR@UacZfvwRUg0bh&n>mWW8zK?XyV?PQ86wRfnl zs}UH|xZdvR_Iy9PjhC~Q^aH$sZ`&WvunST1hage=@c{tDSnd`3Hk=dr-5!@0z5mP6 z#Bt#qjH`_8L3M=Im9g>&i=VvKbR{gfSp8tH2AnA)^qjl65XQZMnz9NsF8z=#rO;L; zqNR^qLXT8ph8yGLp~TN3g8cYr#f^&Ul3PBy=owzCt|E10bSyKcy#hAC99w1N5Pas@ zX&{7#mJLmH$-Pd~_n`SHU(&gr83Q*{5It0#g=1qnv|?PFqLl@wls@uUE`!0iMHVU~ zCqv-q_P{Q_GG>KIh2hu`=6YE=zk*S`ydpjH^>^7uP_%OttaWby94gEYlO7;e6zkfZyR>d-nu#jvAzs2^H1^{sc+B zm~C+G_r_5`ej_j|05zjYQMbj67O4p|Xks#F(|(#n<9-O_4@Qy=ZGq;*;aO>+&MLr@ zv1fBDZAh#wVTcQ-`l>79sY$A-WOr&R{r0J?F4UJuWLiQn_ZO4^gO>X2OeBzCqv$&h zYry&muAC{Q4S6Y03MR(i{E}$RO#Bh`r~bvOI>33hk<_YnFV=I?d;|6{)dW88dLZ@j z>&#?U2?ZJ>8<|&I+5VivwOu7y0=n~ktIG2^I;*rZ+VGyOIj}Csm$nxgUJCfp)8Z6w zp(8YUA8jJ!#FrkiJ!q15Fq&5(p$3GBCoQ?A8NT}xtt29SCTr2giWfVNrkAN8R4Nr6R? zCDIs=waWi&cMUOg%sW(nbjYF?ilL-gE#@)6;()LTsW+4p->6oH4Z=X}31n45koS8_ z{?SE<0Q(sR#47(`v1f(cbla!e27@3j^=h>z7ON!Wh7?Cb;qIsUnaR;NVI$Mn2hEXL zPdr^k98}a=0KKiW68B(;<_micu1r%tZJUC{rkP_joQ0np7%rT01Gc+CC|R^gC#d{X+Q~-?Kn9gj(TKJVQ~Vgn8SAg#*Kk}qXnL2S zd1;=76bbW$vBR3zJM^$pJ1E22L+aulakSOOefUm52BtV{)&YhdM2(Z51wtTEDE;}T zD1b<)0xunO%+{f z2|uwKleO#b?43DIkPzr*T6m&%j?rGniMKr?sSZ=cKL`ga;OG7v z;Z{;WCTl$`&$>!V_mVe%K=<7GIZ4uJ5S3T}wwEg2lgF+?;xEuWF!iFEWuVvHX{>0W zfyISoQ7R~sSEns3h=l|>?~V4en&1Q#sH}?kcE^=7Aqr;RIh|K2$&MB3703p1_(wcL zlkqNCV7%`!dfiqu1n*y~^z8sqC;vp{C1c}H3T2;PSa#*ZHE8-G;EalJHWS>nzeGUy`+q;jLv$;+p!9uWeo@5X3?TW*=#b*>Xrg;x>7cjX zvaMSg9u7X$Aqd#M4=lITEeb0x4U!@7Cz^{%!R4UxG1;5aaK8myJz%R;JV*ZhlDa0d zY#$scsDP$M1ZB3bK;E(Qe&ovq)<@b(c~g#bupYVYNH*E=;<+-v+Y_e_$k&=Sj4<oHmPc=OGd$_XQn*V9OW40Z1Jj%8>>xfU)@_L&o%xk;(v#SrhxtTVz;8^=y@0Rcf3iPrVAVeMMyz z4jiMWZy5jap{H`GBQ7%IM(~gcuRtotbiWN5wmOlK=#&s!XY;BCAE$md7`(du_ptJf zFDI#1Xuud^_J{LcbOD(_8USS(K{!*H>+ShcVm1wob9#rf38a<+45vxJ@sOrd&~g*l zd@MI5Cj}QsHFVf$ZFBeF^F*J{aAaZH%)*Q_Bc2_91fXB%K9BdTn)zb z(}6X8K4u`;_@h1ruQ?2Tq-ZHQN(YUQ+1j+yFkm8;z~&HiQ53VtWKutp%`_)X>zEtX zSw;oI=0z-#RzP5mJfh14ME#09o0``M3pL#4NXMtf=9dNskVL*Re(D)a;3BrWY1|9m zl)qbWJb1C9fQUE<-;gE1F_d|u`#~Z2Q#t8uL_Cu}Jr0(PB3ct;9z${SYP;rgW|ZwZM!HP}6t%g92*Oxc zRRV`CryDs8KuJd!7@`Do_Oi;B0c(RL5|GGigAC9tt@dWSersYaFr zI^YwR&HNn9-T&PSq`>N*U7p8mA+QrP-;V?jW-eSObG7r>d7jx?>M$K#YI%aEwdw2! zAuks0o#RPsC>lM%n6ac?)U1gi1T)!KLt*=QZ3+biR4WJ+Y4v=ob+Biw)my_4r)#D$ zOw%<+`}BHXxC%tu_|cmF&LFcMNKlHyc^+E-;mtcWY6w`Pv2o9wQn#1D;RQu&!%_J3S-B+py4JY za;Sj;_F$IamWo~pQ*Z5S`}PP(Xytbe)!gP`(u`dIV)|rY1`VdwkA3-%bj!j%;Q|E0 zqDbS8m9I|!?XH*ef4q`++rE}qod(4%&~xqCfVFU%U1YppFl8c3*t*h(M1_OWL6GJT z5eaY5=p{}z+lab0$HgzF7r52F81g)gg_Q?DKv)=|ER(>jYwt|o+H>ye+q=#hZFqSp z(So~NN~qprG9E>)8?GcZ`y;41J@btFW8VF!fNOC*G0q%K^T+AsDA;pap_h)^$#Q zSO1RCgQIRa@nn1IQU4DWwYK{Jj z?4rtS?zq4L7I)Zs|DqU}fTLwg4-q_oc!UzjE1Y1*vx-_nbA3u;SOyhD3&do*%FGeU zX9jzqzlipEkNoLn0K4Z0$@O{=rI!Zwd^XsvbTStkay-$)7a%Gno0-KSbn%%{_?Tql z@wLwhy;b^;Ke-XuDs{H()AxeG;3FytJn=j%27ekig~{K*5W)MkVPj83k=+6t7Fxgd#m(Kcz7eQ)thZS_wD88fDSgFH%nKg zd#-_4c0%+FSy9fNA0`V&GymTj<2BK11E!Kxb)jDU>jDzakASI$x;r2 zJm_+KFJ^kge9EfRt=YzYZT1aQzgW_FJ%8G{sPaF#q*~}BC+j}!Og3?6VVX?6rZy55 z@6*i-@wv)?9O4QML>x<#*5_ZNoQgzhVX@28G{gliVf_t#qScy$egQX?j>gYK3{YcK zb!g)ms#ADVY-(rnZ1;V(_xMn@^jZqyr(Ulus8tQdjb>S@phQ7`gG55S5;$b@#0h6y|SyDpHT4bgSt!P9p^}`mk+8ww0Hc0A`Zke>@;FUMSx)vwl6HxD#DV)NeAtC7qM%BagtpoFR#zBdREK2DS&L~GJE+iO?qxqveR zVe0ux**KInBXE*0MrR=Tz3472VTYrHPu5cG=3!pW4zxFejC|X|sNFR1HZ-N!WAm3&42ZeqBi< zIi)#6tOCZcoH-c?v=0(t__9ru?=Uwe`utE0pn5D?cyX^Fiity9Vg7#fuHnJ8s1C2d zoE(VAq<-pQwx58~+}4&7pdnwQY1Fp$gD)1ArD{6Jg>EnNv!pIn>@I*a_E@)Wnd2>O z88=bRSJO(pbcA4=nb`ne${sRK@cGSNk;Fh#_uO`R8CQA3 zL`!Jc>5)CN-+_F@#JYK~M?ibI-!e42Rcy@fZfA&kz_7ADLH?u0kvKau*|$=@#TY+uBn4j)Xh>m=!C1 ztgz7<-{%lo_Wud3lr>qRnsCC>W_+H)0?juNMppX(iT$p$8>N$6--D?rI<;iX$VJ@= zGS_;}NI)&2HZDe0KQYnIPOSHlcP0uMT1 zF4M`R$$^=MKW1JL87^b3Ahvulf8G7HI z1Y-~Rw92R>L~e(f$p>4*i?I{yfjn@n>t%XEy`RD%jw5s5#=ayHjeYx#uCd;3Uq`EV z^2qOtksY?ezeiykt3vn>m3^hP-|y~|8`I#j6*`K_m0h+DuMC&<$9qP9dXdr+4SV2>!gKFpnh9u+nSUT(svA|j42Sd}fx;pW<{^ZgeFC0l6Q&J0^1$rk;k)$uO zvz|7JRD}H(QqK2&k}iXNL9`%WZ|~$pIWKql45G2t!0*e_V6xVH@(CE35;%L5vZEa% zqp=B$iZ--}8R6C8J*^p58ofIh+#HI=l7Br83S0Acd(YKPpK0qf3qcFW??%Sah0Ek7 z@OAckK??VnhFP5>kvi>%{rmE8gI3MXX$>cC(HCgauSVR1^h+DyMC26Hyar?X`zyf% zz$y@vKWXlbyW>qv_eVU`458e%@HG6fCgC|+@E#A=0kc8T)m7Q7cYoErbd}wXe8}-4 z=qkkZ)-hV8>4y9ypt3B&<-bvW>Mplz$e7`Z7`w4~!sGc&gfApdqF3k=Q%?I_PFLU& z%OjUFp##;-gEKq|Mg*YfpB|*d77E%ry_4BKPK@XFZM6JaEB>jWw`npoK%t{ydCp={ z7f`P=@E8357k^l28#0SRfPhTErS9N^(f~FGoGAa`!z^v|Ew%a!SkgvTNYZPCfzFp< z=cTTw+CG2g#9N}s4bZ$luL;Hz3^>Q=r#~J2Bc>%afmHmqVLFl-5zC+)AfPB)6#M!5#wHjjLBEiv|?= zO&Y6=3tG#37%R0S%CtP9ap|oxG%zY@yccKC^R}DMW(qzB@xD$EDLy#ZHz;o5b6%;d zUl9*)@$&=H@$Z&zY8KFPT4rHw95DfRFHZv%*~lbLg?J zD-R^T4-BF1pX)-;EOc0YTkIDxFUE;+^xIBWj>S$fvI!TFvd6=}D~_|n<^XB8J!gWs ze9|9P_Dydd*_ek9U2}I_4o5|i$<9kKg9>O=j8j6u3UiH4B36Gn_KM@Svc~tB--;IN zoe{ZFokzE?g=l^P`%$H)`_AJyyzmkIaK@b#^Eca-Sa|G4U(||6N6r>~9(a29yW?B& zrWO$h?sY@jh<5EzIvqH%NPq+KHj!u-O=WGs*geC7acqXnultK4*CTF@5R>$Wiv4Ho zGV^Nn{kYnY{wZ>5QGv`2-B#NwlO*FQ{X?A>IDr#X0@*@7>1A_f5A==av;HC3k{{vs z$jaEg-}L@+Sz0sr&OXLys{f-aR)zQmbv3vIXPQaAWH5GqdI;hc^Z{(d(l44X)K^F_ zk8IbYa;0{@^HF9h%T?2&6eZy?@V?s6nH2GzP>Ab>_HU_}67+LEX16G6Hri59J+m)n zRUHzdiEwAK3IjvViQi$?xZoyb`0Fkdn!~`(bPRrJqin-eV^^ z+Vvo_w-qg`gl3>WTIW~ps*$3Tjvz!t(xLFha6iRs4G{pIumHip_f}@hg5}yzX1b6@ z4fkZK`s5jf)@}UVh_y`|(;UXZ}K-xDvoiPhd?4C_|YouTc}6|cBI z&_HLL!+g^>PS=e<7h)`rzB%18#7h!^M!mb0Jf0h0YzAd)igd7*uj9-eaO-d<=*3Z( z->BRg31vJ~?W-$Lg-~&bgmtwxGC8zFRJZ4?)%L31Av~d^Ab8QIEGd9r&>n|93eWnO zHDMKJRi3z&&~6dNWbR9wlnU&ckqkUVlpa>)en9_kmXRqClWXlH0quf^_>bBw)rSGJ z?SEFST#TSN;7I@3yb7~LUIGOHafkfxZx@jeC~T^qECvivtt=P0!Hm%TuJJ3-3=PJ} zhvA`VdESI+5QQ%$p>2Pq{LnTX=xv}H_kJprnaB{r7r#C|{o$RJg>0z1ZLl{)I=0U5zC5t0S0M>81lAyyIbt8PsBGllfz$fgIXduKOm6ne;3qiZXGU@ z8@8^0iq&?)+kVs~QDPsEfwl5Dfl~#~?uE37SF$TljSZnh*2nl+o8^kIv1FOp!1Zk& z=pjRMQBcL4BWGwu_KLj#6)TZqi^kCYEs*)Aw3@#GRboE{nZjGs9OrT5XvW`&->pgA z(@XblEt=pyP-*mIYR9gMS9Y@R`;b0FzRf$fO(oxH>G8#$gcq~9Nw|*Xk9v={_YZ?* zGNnd+VfyIM=bRHRt-05DKC&^45r7I30yAqST^ctQv(_MThI*bkn%$LKreoh!ZNk(j zpB(|fH~OQm+ZHMJY^Q*Ai?ev+Ju)Hp@Qj$tLb8b@-6sQFcf(ijJ?SZSgw^O#o(^!) z@;ILc(YdYZB^gF>eMCmLEa*+4JA{~I@vT%gV{{}VR~VNIIXP#_@A zIH|&npaiMZLZFDiRLnXjO3ynD40PaOpSq8}SUWj2E-`hG`P_tY|16pr8(kvpKZ`{H zKMQK<67t{mHipZX-`TRZ9YSfFdC;UMMmRH6q=)L&*U(znDy->CFYk?am+6|f;oGkX zleOrjlN2L)ibb?*C@SZ>(6aMBG|SfDD5emMI!rdJsOaFs;e_IdZ zjf$g;@2ghTUQ_I`H-Mdot8Bm#Aj#e1#48#FELx}ZIuaQ9+Is9w?#wI;2|i;}*j1Iu zYDYw5Hr9Wv_}ul~V`;Pbgla+Y7A=~WR1XK*6Io}F!~TrTjeCY1 zD;S#CCkp^fm}%gKz#j_Hj^n3D9U1E63mB^=eR@o<;V6<^p=Ig%fiRYI3HQ%B;u|f- z)T>StVh--a%XX5o`qlK5UI#UCK3~`{m+DS@-$B;e0DyiGhhsk#*v&O@-!_~Hu*o=fKXpxlszG?rk zptQaA1kjk~19@2pQ7Y70d#%;%5ZW;R@Un_*4cz+N9Yj8+cg1$xfqUIKt@6w`_`I>p zS&##Ek3yO@Pk&J#zBssyJ_K|NtD#tiLwcpJM8l1N)9^Xon11%SinpkktOJWPJ?$H` z097d?8aag8--uqL4_kf9ovDd4ck0+X>a4U;h{7puYceoiSo}wG`5Zv&WVtA_tLW%Ny0u=mqvszj3DN_JG zFOVa73S-frupSG!1-YxD(e(SJuVQgT7xWwQsk7hiYdE|}Z}778$=h?tnJu!kGPZow z^K*0*GrcMj$(zvT*qFO9iuy7#PZIn|%*9V1_m1U?^00m+H77Luso4c2HY0p?UCB+H zi(r%&hcM``4%jB0?ZH2DnN%@*qDI`SjC9V<6;*g$VGan1EbS zdL3!s!5C7H5%AkO{+~bEx^M)Rpd&DAow z9MxA`DlC3VVnziDB%K~4iw5XN>1p7uKwSM3OeJ`66QPq;gI|Zy9bgIeg1K9sO4!SB_}P#5j{N=NpM24?78PPeo3cM#0)Zzc`LUV zk@KfhM;;iY*2wVXG?H-M_V*(w#W|cn?>)B@*B!+=h<}rfJ&xb0plAU!r6MVviELRR z{I8iJcl|C$`5_C&MxitFO$p_N#e8@4l-KVzt}Oy-OUX7=<9RisyJ#=82{!BJY8MHU z;{9sFV0ymJMt=9dDaJ%VG-v``C=N0*)Q%!2c2KLac69fSfzd9ru>ubSU0(9HE`KLk z#OU(oOpUle&+34MuLCBI5AO{R(YCu5tG=#6;qG?QsS$QZtEm(4a2l^y0YhRbG1qc! zRw#f?h2*1wX=CZc8Aj;Z7lrf-J*+iW#sL;{-?p$)l9N8gpMM&_S2e;^KVTraV}f5t zX%^gfIyFvr6RauLbr(IFdN%)PlJ}T(9bON3z?l2j-{ro;3of?}t=qCucZ|3uquvF5q!yt1)3oCR0DULXK2Z5v*BnfSZl#u zJrmc#4wj(L&?^MQGTUwkIq0>xUZ*9ZdW)l7+%=$VTgI!siNdDyO;I$65_kZPOp}M$ zL@Emh-^t}y`;vq8Llh496`I40jt7{tb#L}du}EZ+t9l?Mf4cXzHNfVON%WEsZ9@E6 zWTDvLW5fNkcNP`xQ6wj~Ik7>`t?9CU65fdU_rJz6u>a~O49I^pM6Cjnpmq@dt(mnl zpcwzRe2&V4B7&j*$NG(WhJz{u9R!3)83cqR)rbWYH}$U~C<36DxXzhyeNX4;+%9HE z?(Gs=!>l&#*|Jx$ag}7@>y;+!M1q>oRw9)_Y*Cf^e!08}A{79^p0M1`lad$@<61bk zZ3(i*xfED@+G5iwQA9I=?6%YtRcof^S}nEoTuJw-&n~Bx&LrNvet0!hZQeC}lN*op9OQZ@JiqoKiLmkAztlb`**}T{757s6Ei~#mRV>A|wA(i^DddM? z(9wkot<@*_v*nJq!$yMmFf|(c_vHi}#eho$)dc8}&_E#MACX&7ol5Yd2DMUh zyeKo+=BNz9?WKG&~2e6N|)YQ7N%cS*=izS5_?TbQR|?q z;9&ACOBzDeK#0qn;a9nZcO~O7x;ktb z+W8=T#tui+5R|0Z*Xf}NR>J?(>6#kyM?=&wmg{V)R@=?3on5QiM=vSV3)PE{(&d8hLf2A1 z)u?__8v(V_PHt{L?V%5nu>YbDP6CAp|q@gk@%Ngk9i>mekL1EU)^Ze9gKi&&_7bOfjQ~J)`Sk7yFb8^mjywi#HH?Sn64^g#w`g|`2 z&06>RL761TUsg4l#}U)=UE3!BfZh!*O)hTmWA81OXp z=wMm7HysrIDu~&~ruY^Jz#lcwQ7n?vAMS{XL22l-| zoBQ<3OM=MIeGbLKM2C3J*ohH41Qk|*rxyWkPlNJIhL{+^=-Q<-lHTF91BEGimTQmA zp!uHS16Tr!g!FaSCQ-9YY_}GP<+T?0l_GdcnXZs2^wmYT2Ekvv-hd^ZE&BjPk467N zCG_Ajd4v>DaGzS(KfdP2xaxv53z#hh(N(}B$xHeEya?n&=t$&Rha=$Idn{NW^9y=# zXg)jB8)ORCywq9>< z_WFE|5_#jl9E(17{x&wo+=Mk+NLI_NIp&EEW{VZv-1L-)d^|aU~V-K;> z)bI7jtdjg99ueVIb&1LoUTT=5YCU?%BBrExk82l|zGS9%%%>wqU@xnaM1HKEOnm~# zUa%Xh8Z+RXhI?Y)fCi_}AM0!EmQ0^LOdR%J8k5?^xx zY*f6EGnx&)m1#i;`{HDt?g-e271ioE*phs`wmC#e@Dm;sDD7v>gS>i6G>C3IEsqTGh93Af;Etp1zkM{}J% zHeiMq!A1k70FX^qA$H-;cS!`s(gnC~g^)n0<(4t`!L-;}L~?znG*Pt&zN{?x&BJMoIbf>yjq*JLBfP zGNASoYHc6O;-3a{(gwjYKL2cETAC+3+wz>&xA!%@?LBAC;wEEU_OXFhCB+!g&9^rf zyO!D!hS|(v8*~{K50^)7k%X05)iPB8WnL8}OhX-tFI7|XP6%4<9AUkk>L1dmgcFQh zM>Ga3BVesREa=X8B^0I%!&J&n-+iEx8B6T)VE36$DDZh#1$f1K`p%VB>EzOk-@hmNp6;ir^40VYx zI%!ih$*Dy>Y&y&Gm$AH#DMD<86`mPtyK zo#7(CWg2+|`K<)qqh-q5nH)89b~9F{w84%b;UlXj39GKSFs`0yv@pCd=Eyap=a#=1 z{EE}h`%w^zJjcubi4h-Jha}A)8PCkETe~h(LQh&hWiqY`vs5#82p7G|1}vlNK(Y20 zHZv1FBcvJNZT{4A*t)V2+)n;^g3d`QlUzViRF`OZk~n^#cAkkPV125#M8MtClVo9j zmYWtvVSQ-EFqAZ*-;j6gHZn@aC$kRk)v2I{NaUAO>r`w!efQI1_FRTF?b}-sdQpX% zDASKmeuTI{HLPzMg|Z%Z7l7o{Cm4v&qo5emxf!;rsZG@JIKbSAA%^Wx{ zX{$EEUPatkk@b${Sj)Vn_=89Xak@8?c^Kuf~jX1#0sd8cwa^R?o z6ShWx0{@6xfHLaQ9|+4n1iw+*TBKJZBup(7|JDOXdJ`!>wZ66lPEn+1Ki$G78BeV~ z-{E$NTmUypEXLCi*+z~Dvc0pqU?C-Zi$6ufSYhat;blV6%$2ZDrSGbFB``HqpK0D@ zLx+pI$exbDd_k3WY-ffKMJ?hm^{3q3E@A4&Cbrxqt7s?GDF9x3YC6ba?)~NqQw_hE zkZP3iN`DkAy$|aOfJsu3DsPV<*1!g<)Fu9i^^x>J7{KM;&cotXsry7<46`#>g7IaZ zBiwRZyKyGMtC&=Rr7oQ^lH*mf18$=)218gvJX`vYATxAC+!FP?yE` z4gRz*f70;>7~0$J5A^xzfNYFc9s+ujd>_H5PFLtFybWhfD#s0(`)vo5xnk`b2GURe z*L|0zyv}7ah~o~Uk522sprFCe9k?_2&6qqiVRqAg;G&V6@+if0avigMRfIirpVg-a z=Ec~M>vDqMJG0f5=>+~CG^5QZH`tT9!9QQkZ^a}84voLymV&K1B=Na45ycmQMJDr~ znba$Js3W610)H!i%bYO=vvfnls+3l?d$m^=yy~@rKBjuYZ3%F^YEP#QE}vS4Vh!@MtUdK> z=V04EMiWVK=ad_g{E4$R3Kd(0VD{Gwbl_>oMSn8s+d~p6?ocaf(No^IDXLfA#P}ng zUo+b=$n@Dcn#zqa^+SZniZ*2|6C*vdZ6A{V2e2;8S;U9{y>ik0er|DV3O&%cw1OPH z?w*LL>As7IDCjMf2Wz7dhA}H|hlpyVhtH%^<^z51%9o1yvwB+_7B_7SU?okeEay`v zFqIFJ-^FcJdmy;pVHhoy-hlJ?D>vcY6_Ee0tHwnknO*<=dkf*hS}V>Kg5;CD)ApCO zCh%5O={{q9f~XYx8>9_3EVo*w0wciN!qBKb_M{e)S5;w$=cet;GP4=Fe-_SxBt5=5 z!ox3d4RAX?lD>FX{ESXY{5`wrmFMG|Eszo1icq3ZgK1OoxD^!yq@B0AaDmP?;y$Z6 zNcypD-6=`>asXNONFC4+^g+HlK+2FT(APksFCs8$XapZY{TVxSG?H$j17m=_?szb% z^|+}QnvaPSL;~7KQtJ8R@MI4NUo@m*A7J+3IP8u~)Q>UBO>eglrKVw4l);>)e9-LT zlRyKS3alt_^^)QpPkwKBh9Wy?2ns-ramIfCwOji_?ITp6jJ(=nz#9)GC&nuR_yma% z#CMf~kIsBw-*{r{B_g8oVt9XtkC;!}Jgt1pc}FmDo%YjO<6&+!XHgxxUpVCPmGFJ# zQa(>q9v(%LW{m9m@C{VFc|}i?L!wMQuFGH}|8CyeWq0FJkp zAai3EBqJ=i8_PagFnPK(kw0gd{oIkM^sxhdOBjqw0kzGPE*Hj!@m2A z6sr=+A$2k<)2_q1fT&V#Dr7Rjd9lcV+XDWOot`{CbEjcHn`|Z}6*w}!F<9=Mb_N82 z;6ExJjziy1`O6hm`YDK1%zq>3-Yq%wevd3O3CqvMd6X!Ek78%Ii5zRsre`@aK8K=R z!-Kh_6`8@{TP`>06&5qVZQpBo*H8iD$!-S<)^AW4O{kJ<^xxlbZR*~vKRqMdo_8N; zjSxhMz4cz0wGin`fBY>hq1A+h#o#?jI#)cx_D4T;a7~HxNBt$uT{0UK0md{+L0DW) zq|I}vZpTUR#MAQqH4KU$&c68c-swdYN#`Aje4)4D=qo}oy1lF!AoLynf)AZ|e6$tE zyi$WVM@qP+#Vs$e+UwV6n*+@qKet$RwOMW0GI~sPOS17QDd)OzdpluWaG!V*a!7B! zyk;M7QF5MxG~{Y(*EGI|2dO3Ym^{_c@+M45zwJHn{=WH!7CcFsyv+o~$R`9AJ3PHg zbXX<19=IgUqtbo}!1?i4_gci#-l;#E&cz;u)pnd30eRGKGmyBcJOnHPx>np$L!%F! zL2U#1$hT9S=jWN7fv`pCZ+oc9G0*;%jhL~NbZ97_f=gb1fwPE-9g-?1XwU8VnRFG( zg5f|L+`>pEa{Sw7@m)UItf90EicAs%K7A`$LtWJw&!c(a%U5p8xMQ@KYHAZ-(51{_ zVy|kYwV6qC+V=eaL)ANQht)>i+Od7V>C9KMr~|!$4(mCwr$(CZ5t=gIb(e9 z`~8N!$GYcOYtCzWg<)G0%uoBiXT|OP?jt!H)BX(omB`eERulVhtkU4vw9 zX=_`Pv1NY%8R==S1!GXZ$K++Q1EBExq{76d)llg4_to^v&q*Tl)#i>vXgp&(O03fN>$cjxO zHa{%KfB11yUq`Lg0-b3b)}Lch6t_oKRSzY3zIpZ&zD9}Epb)9@Khw2fd@ES?nrvMRrlvn>NR|AOhB}|rVD|1!!Vxw^Pp({F~D$lllZ|H4pZx>V}p{F&^Op(3186v@0howHM=B;74kIt?35^4=v zO~}_e(KJU=j35WK9Ah*Pg_ws3tfsDBL%`bTjJH2}jEF2Z z_amN#g)BF0;fJ`mM7p4b*Ix>lJ3bOTGNWGUmA4Jlg5jWYslHdOq706*cB+$v?{?A@ z%j_N^cw0&=u+ciUGj{p2iR7U4v?V^)kyzDlBjOLaFG6r>)!kx@$w|kQ^E@FIZ%&=> za~u-kpB3tUP`c9~egMfTJhdi5`ZK<@uEUP=zgmZ9A$45@W+xJj-mH?Z6d6XVG2-Pz znd)8!Y=|l|6~N0ALt7KhWd|!8Xj9jX*^)v&(|0MThx2r!xnkYCr0h5WqR41ChM}nQ z#W9Di9qEW4wP|hJXBTCJXjvaLT7etrI9eN29QZfZoi_^j0T|Md&0RXg*bn{}`f|;r z3HVawAj_fHHHxte`ozMzqm>-^MuaX8ou2d^1sl1DKEk%XzKWXar6g;P7+p>g+`p@l zC^;7r*w3ykRr)1ofc6%qIDNq%j5$21A^sRtLrE5&-B&ko_0gF}KBF!_c103T^5BbX^)#fGG4d?6~!o2J({jqR} z+Y;{^9C$=)-oavpqNu^scq)Yle73`qvD8}*&vlgmcBSfhv^Ij5uVU(7jJP2^(sbS% z=v;Cc{%vRoR46=JztG6*{025da5*u8+Dh_|vmb(E0EuE)sGw>NzF+>7;x}T-jm~!G zGW-kya)j|3?l1nfOKfl1-k(X%toY~K#Ix5+rXk_`-t2_OO^k+l1V-TwGA5nb z0&?p?0;58PNe29Llx0{p6#^ka`a~LoeV_PmfSHzFMX!~&BP}Pl+RbPAtlK+&zORXk4l{LVKLKxw zx6(0nRAnL=@<5JAfasK3ozAsnRBubcRyoO6UZQa=sH1so{h>l%YvX6_jiHA^DdR*?r*JbGf4G7gpeZ+7Pk&>Sjp?S_+tC9V+II&6Xq*oZR$n4Cb2N{cl+$epDV!Mh|GBs&QhiQd zk5olvzq%YkFDyHGrc6I`>`V1A>*4p0$H`@WsnMApFgaAG;QG^zt}vezb>vAKO}N=J zuEGn#LY=DUL)}GwD_+-3{?tbNY2dOf*VfGd$Axz4_EdmD)VUp@2!fx_36u>1;JQ|& zM!M40XKk8kGwepV>WzE!bt4($9Gn`);sgsu^50A)Z3#Q3q1UP#81SOu+nO12GJHoy zK=qE$(G+h?E3fJ@1b0*l%eo1zaLji&sz8fK4z>rk>O3&z)p{{nKih~iug<_eOSFo} zd=%rhm=#X6QB5%5Dxt3IhquvzmdjCXC0_~c%d*1^6XJL%i_V!szQZkrrry3w8Ck536gmA-WMR-oi!v7vZf(VPZW%4Ib`mM^gKui$fbP^xDh^d3(0jpYiPd}JuShx^r<*Mk-U^D@J z4ORrp_rNc5EbhVy)94n^cjZR7^H2d@>8yht$?e`qd)2nK!^^ejw+wGQO?Vna(sI@3 zl*k#S#Ds+mhXdlrr>e6jk3M90wC7e!DqX{-yp!QnOb;DI8>2(Mhrz8eTr(C6IlG;~ z!Gk9rQ|S4HlfA*@=PZIYukdOozPvZzJ&cr+}J_)YIY7w zcXXab611P4T+}4g7~kBiHg2}NX8+iYz(_-3=y1J#`0B>JU0?lSPO4&-m}|*qSQjxp zxcvTdk60A;j_HGxtaju5-ON8=R$EYKN$gU#l+5>OONJa&O-h<6b-=eCb-IlRB@fp$ z0D_fQP7pZ3V~+$@sGfyh91;5y`~7Y!5IftR*T~KhM6&zDgGGjaxQsfi#F9U#S$JfS zmI4dHuJ$Y2f+ic*=wzHTgeq^5{>;Xb9-iXoUI%KjeGU&!??KJkm`xAXIYB znbSXB$cEtVG&uGzg!P}NIWqq^MNUiIeY*%ExmZxl+{*^%o)F^R6yBE0vf;C_4e|kj zgy4@s=;Q~cyfmBLiZ>HT{3Q%o4)i1Xhb_Y$hJ=~$LYa>J-G+D8A)IXr*DYyy9N9w@ ze9vgAtUAJfzsvIT+)~Dj5TclIi13*XTn|C~xMil}w{;Avi_*~co!Nf8blvA-Cf5<` zd3(DHB!JTcVA&+6nx%}0ktC}7THuMV9}PkYRD4tkrTm^v`kwDyokXWA&<_3g0?T@* z8Nm3Kv_ygyB-V2zc#Z~yR+Cd4hYBN~2#o0KbL=Og`+G4iP*B)zlaOfue-9#%4$aAi?ptxI)`&~{zE84) zA0tE1;-!Q9Mwcl4x>>R90u#TVK_C>ZC25D5PJYu<5!@{WNzaDCMgbmAUj{KaYLj81 zn6y!6BH98@wlC;t_AL6#4^R;$i!pV~i{OCBp^TVPgIN*7*BY?3xB5e2=E>q+#A6Bt z8sSMHOJ5C%-5pXt65^~PO$Tf2wCs;#0Mg*FU?IFrOwbL| zH8$~nN*hAnQ_l9RAn#TeFGZ^o>_?VxHrS?mGU-YPmaUyQ6)B603N$4|WomszMu(|< zt@k{)yE4x$PqN%ldZ20ZRvCfrKNl?LJL=S>p&Ivwmh-XkDGMlluJ#O2Hz$S0b9dCQeKPA3LL{w z2r1eVSuB;bKx$>p13qQ7YQtM5Lv^dZi^2-)2NG@KQ$P!8#~gu<0<&x*{)HawZ5M&X z&je?M+FyQDs@sc7V(tsCtz$k7efE!pkm<+FB^SO8UnHoKC8bd(tU6~M3!2UVO9^K1 zi_{}e&}WjSb<#dGabzo&8IT)WGp!xizUU52f#~ucfS9;LX#m18^AD5Zn1z}tI6Qr; zxvu~QkfS5Sh6q^w+)(v~ru@qCbt!Em8cS^D)F1L<%8c+Nyt!S76Ab`Xd^(fv`p#|25dDFGCoP;nlyFT$x&6;J=G|T_pBFeKjXFG3gl1k=s;KxZp3(IDXfJT(wFp6G$C1 zo^Y0i)lmA(lX;G*r~x3&V@BaX#S2=zwENHjY`ZlLzhSnYT`2=9Avhd62LMYp>=^pq z6IK(ySeLtj+vVFux(~n4*H4Y-Z{W~eUA;hgWf6pB_gax<6FUq7!>Dh;(upMlwZaAp z>!e2B94Y2&IqPt1C{*F((1_$}v&{rks~l+CWpbd^4mN2?5BZIbMdQ!PAF2ghA(0Fq z(tXb;rkFCNuT)a^4@A=r=|Z+fj|r7ba1py{@s5J@QF~!A!5yy-xQkYWz2D^k%)ATP1%pz2T?3^ zVIfV_>SD}3b72NvyMhX3?dwmi?}`Ah2OdX+hXjkfe3wKAj`mDr{J7TMQ#ot^N;#@5Sj>%H`Z9XPmz=8U`tKmq|endK)X37(AZ~P!F z{k%ZZ=7`5flF{BoWp{0@CB4B)y;2}i+|$J=uZ?vccxmzecRF~se$$q6 zZMbkEj^m`f&4_#Z%9OcJHPUp-KrnO#Lh^oJr~PBWVVvgDODE(r5LMkxX>Y&J-;mF1 z?0}LL#)QWl&3gD$)e8G+q&cC@9NykB+{#mS;lefQ<$s=UND$b6h_Z=#VW5s^|Lv^8 zplrep)gcBRAZ3P*a#txUd_I8>A z7cY5?I;i$V7Y_b*BjaO%;Jx)rCRrRjXR^(En)xWAZp4C}3Or&ezu57tg(nJ!!o?|b zP6Bq+4K@7K*vZr*OuJa?d-k}@bK1DMbnD6fX54(U)b~kK$4V~u9k)eN?%fEjMvZLk zw4;@URsBEAsdVm~HQup5xus?aTc3r`tzI!q8UpQj#te=I*a}>}8nsM67dF4Wk!^oi zW(52^Ol3;oeRn5l#<{@yAAR(n5}I%7i2!8;q{CL3kUI|5ziO+I*aLOJ zeG-JT6Cae0veC2asY0~G>?mAoO^1NX@I7j$n04XeZyPRzn;y4o^|ic5D(YbpY~_xQ zRH>PExnl(velvt~6}1e4WD)Eo(OU1~`g=&mwVJv4k5}C-=?ItQuoEXU0&iWEbP23k zh18+WRbuNvwx3a3!yRq1S!nm>o{U{V^=8Rm_z)1cC?p{qqP&Hr1(d5@T=FuE6HIh& zsq=3bMS?_s3A+r7mdW9^xPHeR+IfXydYQZ5F{LLo(e( z=pFAXjo}L5d4ibRYzd0_K<_o7Ff2(cMEMj!)%W589mwG#L|qkRG7Cp(JHezVp zcPL@8@}l3DN(Ix#K{-NG;ymeMv)dkYhB^#;u*?##4(0kf=_`a_{-_}5+!ZZiVAB%D zMPF3Ch+e4r6G#W@-t;0lHUwc9>oN$IGZO2#K7h@sjL>BWhYN=b4eY>bobPr#al41 zP}WH-T>JBag2kZ2{T*<6AtIq%I*jmtCQ0n;&Lr9n8FU2OzFsch{;iIrd<^%5e-ds7 zp0@2vW&WXw3AeYOP;_EC$>J#l_PC;zaj`r1$@4mHod?+5e_c zV)Kke_16^I1OE?!O%5n^+vR?Rj&3nh&Ono-hTB=6y*F6WH*lauZOtwIQPd1?RzgT& zI?XQhb`M?hOUa)oVH2-t%v0T2N@6VAv-_hdu~QzNp`0O$7z9(I_>v^`-rr^Z(cDEq z!I!x;-MH>=bYbYZ2FGK_WR0p_w$Np!B)^l@#A3iD z#h5j=*W+rAXAGbnE!+277+`)i&gV2tX$G;|O6L4-)Mr}w9X2Im*r!4VzwR3|dQzeK z0Xgc23*sKH8^m7&KmKOtEZmKrzAwzMk5PLN%|!z_QKBq*>4+60Y4dxJmH4wT)FtEr zFGc`FoNJ}yKJ}&-G!JQUzi3vEp&JdDi-PaZu*-?Xp~WIkA74;1imK&dp@S#>>OglHHsaYFF+ZhY~^}#$L4mqZ50SVL|;iVED2}tzbfzfAw)tBA&Dy z1SD0Eh#JTQWtWIhb|5;DD}tn+FSK zKk_FHM-2$4UhobPN6_+4l{8X>#inW#Z_S^UFw!yYL4m6GYWK8vwDjl~{JG-Yg(+=B z4@dY)OioRYvk8GX(v>Oj#!DN%&`gPq2Y9d*5m|pvpEWPNMPVtCl40{<&!t&WuiJB;?RdBO<6FNDh(20o6*8Z!4(x5a?yP$86M!I zM^VPeMi5pLXPlVu(~U_*%3Tu9vG(S(?f%{1^3$*WZj6cXKD1jh7Y81d-z9OUVl)r;f}6+6iO zd&XRXPk}n(c93_LZv1=x+-|+Z(ZC?QS|ts>;PKd!9`Hwi|z7`)W5f!+cnH@;GD9G_z3V(RQy&=T~_kinqZR+^=meE^m>)1Q6& zT_Q`BE3>w)=``+Fd%rxkiNL?Sb<&Idja0i`Zxrx34IXs3J)#s8I=BdW2@aeLkie`z zc0v6g3JT4)*=jH0Etx~Vy8&s)$1Hw#nId7-nehVsh;=Kfreq@Sg<9J5Z-a~%3P#6X zPpAFsSQ)GY!$=cTui;13LPn>9QwCYo(TXfP- zLxYZ|xPC0cz<{)hNx9DU*BRQz%Hbz$zo1@4MV_Pgy2D?LSnluBge(Ke0fz1~fSC1% z=A8;@!$Tj3Kt_RhCO^gs&K5qez}WbL0^^$kqs-s1;;9V}q;XOFpeh|FYspv*7p_0% zsOR@0j|Mj>JMXlHX~1_hDa**62i%-7dWdg5MY>VwX4E#ORj^kU;Z&O#Qp&C6wT`KX z>*_y9Y1g0?u7~t?^GW_Z&go7%7^uL$**+uLh@*}}d=saM)WIamJ@5+oS8K%_hZmII zdC>JQ6MPRRf!3_2OJ>o8!235SLn z<dXD}KM4?)Q5n}w#7IvIz{hi> zr$w_7MkzZ9RvsqNF^21Nuk)sRlfK~e81vh6z5vA@F7k1O5p45zvfNPlKpb3h6epr? zY65Jtan&^;d{WdVbG!)w;~0Ro_W>e@R5uZ?>0-_e%3);5#2MA=uj6#eDWg2JyuX0& zH6Gt1xrn(z7|?WfQC}2>icCobyj3GZrXzY7l%-nP^ZKOyAjG$!giavXWS&oG`A2${ z6wXXiwEe4lq*0JfPE?p9@te%|A@(;f8cRnKp{Omf3Ah+3adzoeU1a zk374|oze<&1;9y6kH8K+_V5R!7&BGYFA|fh5{&FTfA`c2q-8np2r!OzV1FdpNzO_` zh?&Z!j9pB$q$Nb~J??LOb%0eBXzYE8$BV~2>r8o!{HT)PZD9_BymS^l zJ%){Sab%m%kKCtPdXFeHwigRtK}mZInC)UGLSsarN(O`tM*u~uCm03jHDRT-wMOf! z>Q1KzL6Ej6Z^fmeY>5Ag4Wnz54?EDFB9EyOEn{K+fb$BH;|gvVQ|_n?FgoQ`tYwDv z0QHo%)>*WUdS3NE^QUgq7K!)1;8(YSEfxRe4Z%8rA@i!$?Wl*o?7N298+;`r5^vxt z+;s6U6bY)d5CF25B}kgI*wtTE(tyjP-m*um$}A^-N`mnmt~}-sRMJw~*^sla-$DDL zVplA$s=PalWLJ`D7h5pJwM1mNRB%x`2~Zb3I)Uc4c^|BVsAak-+bAGNkv&c9NZ% zOxAS<-|8&%2PCfXTk5&~9l*8axDw(RP{9z&cNgU2=EEP<86_^6MDqK^uEY3kQHe}O zH0o;(-~^3r)vNZh=-M=Ki;L) z-qTmx^S2iGEDV88MpL6aTY1cpdbe0yCm~9*wld z0~0>u_P{_s2K*Gs#%(KUV6;kYyVVzdhS-2)Er*jn)i{LmZZUlO2!l$L-8+tazV%N2 zu3Jyh<5YS8PL3fKbwVDVi#1{`IEEaBU!VGBGc1!>c*yXl#re|^i^pMS*T?*T99L)M zCv_(risRzhVvgySJ&I#q=s}*$&SrE72u{>1EW6T-8IY*VYFr65+wiSUB6OXqf5&&N z-Sx94;ptF(=521l?Az$&HzsXfv%RRqP(QR84(F{gO@yIQhLlV> zPPG@nTfRyVgRR0nnhPbx370fs$(p1)g?3924snj&9&>u`(HUyD_=1Dy#drUvInkf^ zNYvWsgk!KiaIDEh&|iF}TYY{%m*q1^BpaW#u#>)*Gga)mIv(Y5d??RJz&f08HU7-C z>r;18W7n#G+Bf-IYZ%Ij+=-S-Fn7*HeGc*Gn(=@1_J4o}7LOrkn6L2u4E29OeDp-A zWKj6Ti_99piR9P}etpXulfi?FSkfCzwnEa*(l#}qE8c{$wWcU) z?t(|G^L0GREy`^+2L_aPsyn29%%5`M}?S3+|u71cFOSUT*_ z@yZP4GcG>JQ5Y}PIeTnd;{2EMPP}YTEpko4xVz^AU?fLHyxn+ZN*0JxC>N-SUKfIz z>df3_*EOjZSDlvsNx7j$O-?bJ3j<@Y!Oc!6vq(}hsq7{2Ey$+S$KWF%&7X7JyO z+G;=?WuBX-&>p_;5*WJ1%-luZa}hh-d^aq2eo5n+;|R|g?@`C_*y8KrY3|TuyBqd7 zxkIA1DGER=NYA|+h}}??_)SwA=1>S->G96MwN9BGT&?F-aLb1wxo>hxC4X#{F}e0G<-3ANY+ zPDRpRSeaRtT{MY_B)opJhKXL2#Y6TzC`9Z_D|U}zfGJ^x+FToh$2Q|nqwLnl?Klr5 za>z%}hG69(j)#RdXD?PiYGz#T} z$O>4!?+W`ViQM*i+%4aIVUcN}g$QwIuq7cqFK}o{&a!NX4WOA2L%~VAr3cVEYkd ze^e+qvmb@b1%>mcqU4IW#t7QF?}s!wG?EA3h+-^pTHQq&uEDFGddy9gJ& zGHr^9IpLjiVAH*F+Y=<#(+nh(7w!5SPaW5bp7S0yn?_S{EDLOUi{cRn&S-mKQ1|I{ zn(M9@VoNX(CzEnKIeBaVfxPEZEfMlIIH?UrA_ zjwy#%_?YWQUTpEok~Qhch!$kOpI|v22B$S{+TPuVjmvtBEFz4Y-BKKYD0jS^!`NC` z`&u&bL1%c98#0Ep`6I-E!6@w2m_HbU6M__2BE(GAAhB*8Z= zd!?J>Lp~c7w7RG0(5ejM6uHZ`NLIFU4Qs6rWzF0^(Nrs0AN3xbxOGW}SvqRSHnfI8 zG**XH6T!9GUI@STnlD6`cJ_lVq;5I`#Q=(Lvg0zfsarte%v|y4RS^~*L8z9k=jop3-tZ6aT=NTqzX8p1hHlSs=@Z@O9vOoa zNgwQ;@1Izl=s;CIOVPRzsUJg(0N%U&m$upyT8`ObHhg#miRAmSwwS_L5o>3GvGzz&)%<{bL4kKP$Zy5Sz z=rYDK`lLdptZG3&>Xg+b2d4gcLTB@FmL=3|1OMJ80O zW1dQ08A9$ESIJdYnx=Ya&YuMr)8Vb&FH``(xX%z5?$Ws08~vVn5_xNz*8E%ip8qbi z=5xfcUJy1T-U8W300+~G?VJ9Y?&Ve<(qrb)+%BbW}rx0Ld zfBrz^p?=w?|4W|VuJ}j*qN;ZQqb|0l9J|Pf` zRQVy-meSj5HS4V4C>tYSETdYZqKW@+y!{b_DRi5JcMkQyP_#kY?vFG1_4CUr-V@RE zpi&4B2R=4tn;RI?8US>%v^kAp_6a?K&3-GVOuT`1Kk;vLkztSf6JM=x zo_gDrSL3~K;_NtEX!4B)^m3QybdD-kpS~;6Oeu0ug(_QoX6u<4(7Kk&Kc z9!yfsH@9R#GuM9nH_Zt`f-<%4A_!~NiEi`rrlA)LLeO3pJXs_eoNW-wz%t3IGVveZ z-f4mOE3DGGIwfywDe|P@O zJ+}T1B2%06f`=vCpo;8g=6q-On7;zjGwxV3sW980di;UEg@jT-68@;9^2g<#qPznG zfC=SIi@Us`7*ZURXa}LGpm;Od z7MNAwYYgjJ$Q`CMY#;LX?kMRZLYjC{-?OGJSHvP!x~(g$yquA%Tsam0D?N*N`qoi6 z;W_0NFLBhg^KW_4=bVw(E_gWF#ldalG$I1qUI0y;)ALnk^Z2f23S_aoEVnlOwSd+U z`cZ49I@1rrT@6NZnX6fyVFq@*7_Ej65|K_|A^@SOiQ3y zh-hlaARt4WARuIkT*;vLfQ{WB8-2S!Uwi9u?bH7&q%S&sZIG9s+E%1}dO_jOei2Dc zZKXiRSlSCJ7S)Nao}H*hYYo1iTK|>&nJ0Q~74vE%K3zd>$CY+y9e8Hf?6DXc*eJ|A zVOQ)x>ztn8*#F=-YLw5$2p7qSIl6CG9rZ`KF$Lp(o4C}^y=)#ZsJ1?hVXu*z;Z@w{ zTJ|uv`bHB~*~)=tHmY@POcjSjIrKBEVMnay)F`?zr^P%(z!}H@3>;)xyHaz9ne=O!$u8< z!EmqBKsxK_{?QE3d+nV(+2^-Fb%uG2j)jSi8QGHZ#`*r9{)b3IW{n|&_bgg>Cm0W9YZBR@axUml zPT)=!-3hJ+x^?U|2!bz|>mTxS@TDi|iBCReSlQOkh~(dR!{18mHqlFY#|3ZHT%1Gw z{}OJ9B+*=mrq&(&yN8Mp{i|leDS>JReGytMsu;Wr%xe-2rcRt?*ugd!i;L0)Njj|m2EA!EQMi4CoIfT684+ak= ztRut$WgcGQV*f8$P=iVQW^M9xpq7b$F4V#K?6KRK-J}IQPX$8>6o(8t%1}?2_+r-`_Z#X_G-{dQWzaWlCNR1!!FM?(Kn?v_!^1x zD?RgkfH7EZ*)!XtgZN}id{rW;Ab_8Om{M@D-J_&yJ=S_SQi#|sTX?;%TK}f)q&nL# z{cQ8Hb)0KaR8LHVX8N!S+S;q(=6pj1-riBYp}f0BjVCiaXD7`CaWhn8BAd5R z8(>ygQ%vD^a|} z>bl}@Pbx@yJMa(^mJC?>JUN+f31%Ot!5vr+9QgEg=vFo;5kqI$26rq;Na}(CU>z0j z)#3coOY*@ZLdTY}8D*z6dgjRaeOKV-rLs)Bss5fIoPJYb)Bn`;dU`)%C1Z)tPUhpm5woCcRQNQ28E){3fGkZsbVdPjEepFF}Zj-Ti zHAwF0^2CWR#s(~;LLZPPgw6d1Ow8;jVBEm`OwL8?(`B?eaBEVglQT0DSOY^kXXfy# zvVQ~c0$EE0@B)JxnSUgr*L7u^vKBi+b8jhUp)g5>Yl%d%QPRhge(^etBo?d1pjp#C z31DzbO=0S)d4M{A^x|?OyKO4R(-o$4Wv&j~ogR$3h)h{5LRV2CTY<{~=Ax93$Q1OW zyj=`gH}sl(5H1bjXnr!GvyVr}T+oW4i4O#FDVrNHYG0+_AZI#>Z9b$qLVo!>E|&FG z%QBBGA)?X*4^aeEp_Iwm#HG$r^v@l_X zdDR4k9T9P1nA)J2zJ?|yegalF zGDXta#E!nrwsu!wn;*(vaUCT_p}ro{T5mW;UF$DYch6ExCcjb^rQkNNcQiMwV3}Y& zm8lXZOv=eycIwP1GT1+1E;8DG8k@eLXx?VfJx<`!?#_Qpb=OLb_AEQ>{qWx;euGuU z$AU0>hMG2DM0CY=fj zmJhYcEJYS-qGnePdA6pwsGF!UAL41%pAH|w&K0TpHY8$05F|4}l5ljc)%}9u>wQRj z)zpacDa@fMSN{7@7jdF337H@RqEvQbGCL^hj`zo<|;y?N3;(W9%^2+ygK8kjD3l){uyZ~E_A{)W6N z^k+FqDQ9}A6do0d_M>qxq(1ecY(t>$OTh-MoNsLa#D5tggUwrsQ0#Q_wae0T5Z{X+ zrux2fDHZge1u9uvb5&?q56rJMZl(wmDXnUnDkAZ7t3an153g!Zu8-Gs7|N>>FT>Q| zycQ61m5e0`LSxI8*Or-M1dfi>y>*@9Qsc8bsepd?707@+t~xk<36wNLh~LGF^1tZn zsvJy!>oO6YTAXSBxp7(g0IoIvB>K5iT1bzyseB(YnffyY<@-rGe8TByRVWU~T3HOq z8#38_gwsF1P8#yqnTIvOXOllXWW+ZuE(2F=sLTjj51P^b(0Uv5rFHXfDgKe{GF$kW z_%eU?_yr|@U6f0PGJllZm*#RDRa1c#8gE|#`V6=r=Z=K7Wfc1PEadQU@0j$G@QJAz znUiYT$m(yBa}axX0?>AsPL^JZSIEzxFhD=YqNw-iNtGIrmGUehcsNjyB82u>9Z-Ah zswU)!89@kf*;sjMiec9L2d6Jcv|zW#8>bsU98%2hX^hvR%l-js-2i8@}7xF^~G^d#-=c@qUoGDxW4kVK$R? zjyCQ#MW6)kkU)9NW8eVs^PU&?d+r+ZO-)K%6Hp1VJ;!xNU53PAkdY)bO3O1Sw&wcHf z$>gk01>vouPt>3GS??J1J-cdvxoAwGCL1bOWKoXt`= zV6!C3g4l+5wfDYEQA4$(d{0nPOhkNFnSVFf6KYTeVOhT9MYl$q-|?TzCVU`*yUd2#jv=A+G^ zsq?{zMYye%6H9?wE~%A81UPdZL-Gvr(^c#rG!7O#1M&B>)NO&m#6yq$o45XyWI50X zMn<$zssEU}T#JLiOXVQguBAPL#48Z&GRErP15Z=EX>5WHTz4!6+ke(X>c?|5$SJ&Gcf8wYrvybHt-(z-Y5)umzK+}u`ah+lhAc#Ie z&iD@y9%^6mGW)sU!pe6X)(WTs+4^4$|E{IjmzMO1hsW1m!MCm_M4U=Ex;4G?%Bu!TKoh(P21)PIJ8nB<0{2_~D zwD?L+$8)fNkCz807keHq(*}{(&UUz!@#Tj_*p!an0?j`nYluCC|_tU;tP!epN~~^s!(xbIj)*^fTdV`tUpI&Gv1|V+D}R^y<|Rkg#8EXOqj<$$0*Jkvzt-pwjnf82 zX`BHx;i(}C7Y+mKBxIaShajO~dOcQVf5FgLalnPK^R=3o-|14I)slH z=Q3t&Zh!7gokU`}q}uRYc+Ih`eTP?8nzR1I`Cl7~|9m65y}0y#Urud$nE!l|=!x9Q z=-+^HwbjT}CS=b?bqy6&Vqp)#JiZ2{e1UpT?Q%M3D4WHlGREP9OWp%ajUf)DQ!K;R zv9aV`oGiAM?C|&vSMYGf>ADrJ5qUM~OYeJg;Xu#g(w{}4Q7lV;pmdWJ7HnxGMy=m( zpxfN^vq1O%YQS6djf4EqkE99kN13xT^hpN(4*;P+UcVdE_P|!O83uM>6qlKILfUMg zHkt}mAfDkaA%rocgxMYG6QMYwW%MYe(VBOZ_SiLvfFIIkl{kY6r?^X=2?;d7V5EUh zR)PE8?Zu2K-k`_{GAf{?YZtN8qn_z>tXn6vvMH^kKJjUNjFX<=#@KUHp}~ItatTk# zq0c0Wx_@~{mBJa!)zzJ7in&adVf|madIO#xESw$>FTgxfGN(9S*}$n zMeZyM?hmW`x|{lx(O2zJU3kMg=`X4a%0mfk2r!QO9MCt4+|d*S0Zzmu(*no%a{9;Vp;O z(SI-96mE2dx3%`NUAh}Q%S7j{`vAT8Y0IoC}i-2YVhUlqRT(sO%U zl^*|2lQ|un^ck3g@Wtfj%B=P#hj@4)8Y94eg87?{`~gr)0|XQR000O8B%(x3N_JVq zo(li~WhDRrA(tQ%0u`4FzyS|`y&7F_+_>>wzk*oTl?1PKO&?td{m5NV1L+~irR{_5 z6Sxw0SFu*qk&?3Q?3fZvks7 z4T$Vo4GbV&BAr)U>tHXc23S=BU^U%oBidFd*42ejK)x>crmV{LM4Nz#DWO|~MG&oo zE(h1(aIu5nb&E7Nf^`~y$csvgC%W@f+3w4lHD!bQh9oQTiggaOvT(RvGw0)&kh$y>ipj!%JA^)PrNs|QNwsDT zK4&hst{lo5G+Xm3DdbaKNnZ5WqJY6qsWYzfeR&kwwyeY&7dllT)^?w@(!9Vge8#nP z5HDdDUvkl)k2sTOCWP7b>5!?=~zsBQ;Do77jJdU2Pweg5(IdM7?}Atz63#* z0op8MDZ3-ptSlu|ZH729@b4DsuGR~iAPv|sCyhxA;K4%>pdW#Yr@ccZJJG(UwJ6JK zeh^s}2eJ{0W9$OB!8(&{SWX_rNk?%I1clhL3_@MmWa0~dIG~QuIN}?ke}LmkfXB7@ zK2qV&QF0YW_jh+c-#hDh`bCR_+;TZy()^#o#V@!I?PQjPitRDr!X1TOMS4Z)f9`^<4oh<&Xb z8M=n}@9v_19^B2E{qy5{XTh@LEc7&_aX#AmYmUAMaoCLsBT;>TbioKKx#H8?bMIx$Kl4A#MSI%q$MLk~=NIbcnBqUIa#>5Hmo+ zu8_?71-sqCwK3X|xG^vGv9X|p!FuVFeL<2idB?1OCOz`Gnt+^dk^mJ4y+ui#Ai1Q} zaDm7}5RbwEz*@Egu=rByR!9BoXIa+Kgm$RGbeg0&g|UN&Y>JnVA!l(g@_VGnP-g5BZ- zDP7cmP@IVT5tIYvM6gK1x{}Qo6X6aT@RpNGK0)k>6S$>nHR?SI(I{@h*!5UUpMnAu z5Wy%v!JdHGLIC7D3gV6$&Hh9q#>?j#aOtd{m*;%j$s*CJsh}9y%L*!~6}w{oWr5oT z98MVX!j;3Z$KTZYDQ?m!EZ2HZg;KOt5|T`RjY-I}a5%px{!4umvdbxkiB%iF2H2}h zjnL5qoY;%KBO9=#$H5H3tI!%aLXOB^AmbKs4{_Pfwe0{6AC0yVRA@sIj>lw zMgURUb91yZlI{6p3xdKrjPgAVCd4x|$(GjG z+fyMHUMq+d72hF!Tc$jB8qZi0pO$)Hr=_cM(?%|Ly1tf7Ka&(<)9s?wTVuXPY3R48 zSntX{b0~m8YFIz!(3@>#`evzZ7!+ozFvRYAQ8J)%y&8^z2VX#_zP>hpy3X4Ua+5nF zf;dw_Rv;Mb?q|C`6T{qSvIblbMF}j$h=J|9tZ)RBzT*|@%=QIlmk?0vndKZ@$(}I` zacE7MJ=5!N+E z=h@+!3@@G9A7re^G8>=s8;shKW60m;D|0^yCSvh?1rp#}J5c3+OL}881mc#Jr+u04 z*`eI+Ddlpjb7!bHblym@1$tPgjt$_NBA7u2vViI>@$xWcNE+lB+je3ZjXg6h8muJ$ zWNYF{yz^ngVJ0)KL)`Z3F2hPcV@>JZ7Qo{%tb-?1Xl7%c66)Qf5yBRFcH8&9@$}#` z^NaX^X5wqv(Tjn9evZ_Zqvkpee-nSD{v#dAom#2`#j$>YZ#2D=HVg)uUOFiJG1&83 zv}eg}&qb8x>{w(Ry%8=cA2m43V;@)jK}i!+;pG?5J&0opV1^#Zc=f6!urW3h!s)ib z5>L@s!H+p42}jmFQ}OTN8-cZ?`Scd9H!uEPJ-5N1muEMBKiWps8Q-jyQPtRVG$-4< zCapYF;W*~;r-O4DkTM;^a3?ZN><$@>UAc4rnH(l_uu?BV5lK^sJ#mFGYFS938wo*7 zq$`HHvXej)J~mxz3e06B3;jztpT^+NZS3Z_zK&o<#efTty@w*AQ7RYg z?_k|D^hMKuISSJ#L4ektvBIH5Lu$e3lA5c952Fl!dUe*%6cXaPHrhtRLT3dE(46QA zrl+#1AYWr4fmuH6YGkGe-PFBs2NHuf#;^wF5C4Y`glEe`l2LDW)A{BQ?7w{+xj=Bh z77f)r^6+ab?4c_#xL;LZJL3bJA#e&YGjv`QnVlruwti%xv-4QnpMak3%xuLwLh&+8 zL(2hwc_|8k*QZGKe9^$jybWK=7J{Y2Y}yNxGt)2h=Mwfkyx}|mKdfVT`15MQ(A3C% z)Wi4i1pml@w~+Vq$iLI;KTVwNX6|e2mehz?>OPg&`?mH?%?!0A_-iOCQ~Uq_zXy4t z74lk?7kUzSi2C~R6&=a62kE;F&*Pr)wpVz6+OKP4i2~s$O+syngU3NIzhZ}KXe@_4IE5O zC(P6@;@{d(z^Jrjd#UjgFB~G--Pe;Nm)hdRuLBI;$X6YqnLO%6yWilib6-5?SJpxP z2T)4`1QY-O00;n>5+_Z`Wo?t-4gdh8E|(FJ0Th=WR1^r8fXx91f2|s8bKJJ^`~3=x zY|oL&iL&grsjg8nd7P)})RtAVBgIJ5x<2J_3uy z?qc7--rnBiE&rv>1>f+pk!+P0oYjetd3iJ0gW1VSR2vq@tF~zck7Jf^>Pj>$S<0$t z8y>6g$wZG=b%V>ffBlx`m#|}UUGN9{v6Xt0I_BAGu#o9d2BvmX%FaIs1X zK)o9}YDH1xOS6b5VTojFI98N7>+=$jmPrw%MQ#?Qn+%x9t5S{uX4QRJR7qx_Z+H`< z(BiZLkg^$D!yi(vFq&1a%wNIkGbC&wL?y=73;s(4=w&0?f3&HD#S%;y{N*r_6h#bB zF)ogImN&_=;IrXWk(Ycn2`7^{#_^aPvv*UH3c^^DrdN~6`FDR^yk5j_7XTwT?7yjj z&_GOo4%SUm|BC;Uzas15d^$srlW_9g>Fd{vHy0zTf}elAl;P)3qR*aAVgD!Wb<(73 zIA31g<)SKae_wW&h#V>3m(3RR@GdD@)PRyrpT2+nulR>=-kyB(?cW#i;fE=^&zm)C z)*MioWvom#oS~$0*?lyL0e`p znO1^_5xZFDU=LMMRQHmA&Q8xyeqtceGD}3pGQI+7e`ZMD$zri!=S{{ApFe*Y9nJvP zi|2oHQ6d6|gqUm_2v(t{kHW(i6R-w0 zbR+@#2UO`9L%rbQ_)P^K2yAr2CAlO$plMcL#K_2>gi`}3i^FL9@hc1qGj_k`yol2T z{0hN@bHW5+>`Vm$?;KRD17l{}oEI58QPOr?v+|!MC`&XUOmpBc*)YS@9LLTQ@IxRT ze^6-jH-jA_eUeI zwOYPvXAE{mNn9W;-}xwYCh$dPd3~+`d(@fZfb}OU2F3$NqEiVFeK)TJFFC+5 z^L|`-&hgF%K@_#1f2w>P5FA=~7V zm^w5BXY7`5?<)ujiMVMIY|i$4L{m+`v>OkVQpKdom^*;U_0x%toX(OQx`Vue<~wL^({Cg)+HE-5;DLgkmF5yrqz&6p&K{40(y_11CtrGddK2D!|)UX z|H0k4VJMPFKEVXx3^O0m93O_mf0f8ntl+xw5xD%Ogxm^rd!tP0QDAwS*I;=!{K0{9 zRCP%ILk$9jue;b}gu^YgxVvF{oS&w_oo!nu>Wqh^bX+zi&0qC*h8OBpnS=@oDo&n->O>$< zB5(?i84jt#R6Gt;W+X*`4B=vDhAv6a}ma2JsPW2Iq*Td3J4aV?V3bGr+C(qpRj8!e+vjPo1~%0E~?@h zDp-&r9Hb%`3d)u;bJKk>2<(pjdf0XpuePci8G|sbyTlLVAB_Jtrdd7VNCC5?t&HxV z1cn)?(^eJxk_9hj?28$D8M-W;i5x5EioJ-wh+fWAM+Y4ZT1du|LY3!jnWt68A+kWx z!KFpu6XkqGP>sQYe_+}+t3OW_SuhO-7I$Z(ax!EhpnX-C3LG?`rABHxrFo*vMSwl7 zbj=Uefl?;|Ye+_IK#4o24x3J&Ne2IsoZv?|WzSfbl}-24DGJWXZaH{q7#GuB5yZ{R zp6I+nhkwVZm?JSq*@-`wRY3}4MHiW&c!S))Dq|Q#3wnWVqM*H4raIw_-)E+mM>gH`0kj!Qc3odF)po}`)SQ4QK$Sk^4;2Izh8<&mRQN5QWp0GLYd;^3i|j6Ib6tZ|jH?xWULb;K*Vh<>+^CQ^^Q_ zMZ|^q$Z~*DnL(>eQby(L;(P~~gKm>^<-3)XS&{fBUR%^;hm+mm}<6kl6J zHklgfe~pZiZOi?~%lTc_JJ7d}u~_rVDeD#8JBxZHBfKXdzre72x=(?SZW2_Bt*!49 zk&WBA?gV!mjCYEA7OY3j{*pIZT3(V)oAonGv%k$mecp6-XlEsLbiD;v16-!zk4B3| z{ShdKNP2yK`5QMGt?I~WKt*!yg6#^@G`!OxJq8h+Yj*V`)8Ev;R}p6wugivZx$NauBr7xlKJ zjMXI0l*p-DqlmE|b)Vxtfxr*I>MozCf7Gp-(!K!*-GX37Q3nSQd8D#p>P^}9L?UjX z_9SHY>pWdks7)&&+8U$pa;tWWyxP90ZaLKt$bc>dr%cz5w1@RkU9F)Oy_;Xzem9Mv zJk^xvWoam)_NT8^^?ZiD(1i=w>c9e87L$#YOQ^`e>riE zB3>oEB^jFHwBIJk!@%)AbXOoK_25+mY3@?te(8+qe3 zV1P;pRx3~%+z^k(P68;lElx^soViz}%-J(}Sw550!caYK#M{;5bQQMyZAxIFwXBdp z+m|77C$5I7ajk~qcLY`y{|3|2v_Ujm`0(Shd+C8KoV&bgRdbsKN^qDAf0p{4hH0Cb z3x*Kf%mpmOy}^OdvL?CZbXtf}(koJ z<+!pqU%gs-D3b_dZLL(m`ko@us%fI7WS6ExI3(tigs68=)!`a~IOK+qPD0+CtngkJ zOfb?m{K);CA5+ee1y{eyOkaXBzNwq7vIO7EKFMnIDLZ;E+hs7Ff2vhsAI_1hmq`xK zaF|P*|Widz*5X-(>8|)LxDHas?FETnrorDYx-XpdS(3iWtn04N621T-2W(fn%G%nLB z;qMNw!kM%1@%!4}f4c0oNAZ@|1u1h;jJ`EA*O-uqE>YBYQ*j6W?=DZ+HB>z}9Fp?8 zYkiY-Vea{;%)piqUA~a=j$?P8365M^+78)u|Apf=4nOO)2ql`{m_gk`x*Td7{)=+Jw81A(qxvbrq_D-~?uKY97b z!#}Vu>3!+^;6Q<)vK`dhIytEG`T*A)AlO&eu_oaMN_Nt90yRFq@I-lg??TO6PPMuJ zmXk2hj<8|fe=cQIfjhntRa-}uxH*6mhcm>9gQGtk9UUDWeQ|Vj0Gq4JP=VFcCWjhD zS0sZ6r}n+6u94VveC`s~(yG7VjdaSFixwJvybT8qR(!EwD`pqw0adG3Wtc zK z0RDuR;2Z%ImmX9U5`X1AYmeJTlHcc7@H8+;!V(<^n_XZwO3sPL7vmh;@MCj#UW2Bn zmWDeN$>U>Ylpz28s;VFC7pZa9`{@M4(U9HM)z#J2^=$3h`Vge)Zs>=WrD;$cn!4?S zY}3`{(6f~PeRd|Em-T*MRD1bn-N|p=)zBBE`s>(fU-P=!6@RMFuSK&fN_Muxk+((H zW5+JRf92@;RaWg;+SWCUOzoPYNzxluZR=JxYOeQb%es1KbJi_`uDElWCQX)KXNYjp zvi}{5mK|8tcM`&z@!4Eg!cU==RdrS5Sy}wb(keT!xt=$y?TWgRegDS){EQw=)^;q& zI{qcSnFPR^Z+{;DCAn?0rhzuH`)hjqQ(a&Gn3W}Kbz&A(&)O~@OfT!Js^_d!^^g=Pxc_KKc1_8MH%H0e|(S?n9( zP;VJt=hW`OZ1)sC*|6V?Lo%L65 znU`>UL*(_L$<(+N(By`tUGJqC?{SrNS4@%ZC;Dr;wb;tCc>%Pm`V^i{cR3VYZmvpt z$gWw+S$||(v`gUC>lDzwO4%K3ZP=F^;O(K|FJar1X*XlZRJh@);RPnV-t+PXQg(ZoEm~U zus+*neKy^#WBt(dbzOFR{<8Pm%XjZzzkBuS#eduM?N85to(9mf1JOlxdY%qm;t`}TF|DKZ4Nas7(Gc*KzC7;zK$#cx zEJ{iErD=S2c9xe}*U8PT3Dv0H;3kPLXn_`s1^xdGYd~z19PVl$^A%FQzXDc2WXE8` z0)MrN0Z0lM9+wecU1c};a#yzp5)cF}+tdRIua*UU9qd@2UjZ~0w5-f-vZ@a>$sc6Z zHpt4Z4&X@YGZ+YGR^$P|Bxqu2ju8vGtk~-P6EzXexoihVXHgY>nnoQfcS~#xY!1`v zQY1GVOLRWrGOu6O74q%2=(A19*3SSD#(#O&_@G!4ZHER}kgeaf149zD*TB{MmD{a= z0~;D|1zcbb5~2bUU)DU!uhTSu{2L85mDJCKM9BL)a6z$3XM z%2hdwhyofD#6%R;AIXH05tzz(Jkkx`j(^yVB%0Jn{-GKbJB{XuV^#Nr=Y=t4f`6qo zT!Su?pa@DT;4l0V$p@ed(cfe1I99OWAUO#cM>i)SnE+nOuV-e9R9i7*?KpXtbQcJd6tUmz{$i-r;O z0#I{ZesdVv&(7gHCk*)Z!er-=`=h=|r{J?>u;S1*l!s<+dXkXOinFoU?7Q8BlfvTzuoCdhDYK zLJb_e$jX*w+hYLowkVO8FHDR&5ZB$VfMa=coWbXdpo6wXS>$lI+!io<(0|qeYO9?o zTMgueBU*Uhl=`}uGCU}=7EUQT@TI0|(VxzBr4j)c<6w`jLDO0<0Q(iSS;X21?>oQ{ zjC4$KW>Rgl91!P$@mKf;NX*DV4QJ>?_< zJc{dWVoj#lGT86>Y;2;y;eW)}geh4jP{G5TA7NXI()=j^<6kszpb{ei2x_*&Vqh+}E8ikQ2|8buKU-W=^F1C+hl1E%Sm4;Pt`}QPcI4|`W_wMR^<0XgKL!sxnz|(~0qc~nh_MpfQULiP z3b2YWjEBs%znJ@!*vh_w5J|)VenvVjCz@=VNJm4q}J!@ z<)|poHvHDL0Dr#=op~C{z_gOYCjc56M_+dmL=GI~Gm4$zMl<5Vrk`fCSWU^BnBZ|x z?bH6)ur79KY*;H60Hd)>u2bC;{D;rgS@o$2X;h2Ey2nU44^l1bhqekjoj2j6@Gz%n z8Gieq6YAFmz#VPa2kmz_M&#NODVHb?(fpj1!0R)kheM`}*4@ktrt7Md$ zFY8`F8Lc36LUcWzA^?lz)(XdX&+$SiB;!ch^_rokdmuD*St$?Nu+Mka?63p3|M`(5 z#Ul6IkbgnA1a$HYU(lc9Ax&*ynpt_99XmQmdQw`;^0?&M;kMZAK%WG}#Bea>iU!~= zAPH()-&S1ebD@GQa9QqvJnaq0O+M!V0krjPup>es%-~RThpY$0x=~g>8(LJ$4hfoL&y47JAYx&^8@$>hZ-hS2!*yU4*HnV|0MR& zxU9mDF>U*D22AjOskWAaJq263qQ@}dHAzRb!avNFHpj0~HP=jU!&J8sbcRDmU8Guw z?S|XX5hrS#e_PKTDBKg6Y}sbmN8x+YCG>TpZHBTTT#jJGz9ti|+6zStwF7?E<32>s zIDZ;M9V)ZB(!`aKe}~h%VQqg@0s<#7bAK?Gx-y@yWPy>(evPSTi<}W%@+~mt`T=d%>BY)l- zT^8sHCj_}}eB^LUWyC@PRxJv{r7OKo`mqG*V3^2RKpjFNk&k{0Y4q@dWAS_J^fP>O zHmY+@SAh(f9TU6&QkEobDlG5Qn+qv;UBSt>+Sm0~o{%WOBwLa#AmC|x4eUBp19A{8 zxM-`DkZdaf0t1kLmGBH$V6Ky6Vt-t;_itXH9ZDO}y9344H+5Y`y1RkSfRGOYJLR|E zV~vgZW5K_DJ5Y2DgF>vQaD$gF8FgDxV6tT`m*?n$2d)K9IUEHkR&>Gv;;T*8Y5Is% zF>2JGM#5_I`bp?K7545{D_}a%HV+%NMa`qAL}W)Z?(x`P5{F{jNqq(Olz*IOsX$>m4m8M-o>fL($s3c4Se97lIOBgrwKOWtM_bR(M-c5Xe2L20SNQ^^|J zm`qQ;z9YjFeG(kD-w+wQtL*Eq|3q8|Z4@w&RP`;V389D~o+7`J)@n6u_Y7uMgSZER z-)8MLASTYreGT*Zg=vsTJAZujh7M!3MthnO2)7$B_!V7fU9<(eKxfp!;-HJ*7eNnL zYI-#?LlB+A%+^Vg#9}OCAN%!84i@O)M3YM?Ch$@Nux*Qxu%5!PP$dzW;g{FWJwaVg_q=iNDZ6za{NEG;8$Q( zKfIsiZaVRWKv(X1H*h<8^0kBAHC@cm0>wd3Y66oz@6RFUqygym@=cKechdN%-;RNh z3z7}EN4OuHS%8EBD}S+8-rnE{+qbLHCCZ~B02FZ^AzOf60efMFk&3HvM=}|w@E8Oy z3%N_ca3=H4WSHLJxquUy2)$T+-om}_PcyLw5}SY2MHOj@UY1=n!P=f9=jZx{`6H!x==k{Lkzs+GCM_DP zRwRif`@}CZ;^m~!m=qU7g^8)RwATYE0?>limf6|JBq5}MMB;_VjmO0y)lNlu?HL=k zL_tOv#aVJ5ssts7lSG$FLewC*-V9WaTCp5{-Ya&W{C^ofIs0_crMq*u=xt^kAq$XK))KX;EUzK~Her2B4*}nDM=sLGNL8IFSPE`DienX%xdNa;9|;YpsHQH-FDwq+$lbWg|+6m!-la9Ged zVJra4nY{0K_CTcRB4>)p@=)T^#?U+#dA6{PM1MT9w(in9`Vj2LYG@)0ib|f)8mLvJ zbb++ki7aXvY3LXwKvQzGWyckm*;-BHIf+1)h?sVmv8i&Mv@;9OONS5Wpklozcw1YE zXIAyhOoa9Z*R)4g|NK$a$8N1P97b7&`{qy5Dm*OZtx{q2u z<25ofS&uL4{uzd*@3Akuutd$#kAi+C7&&uV#M7(mpSse^^*7Ga8?wt?WN2ZRcti$v z9`}vHz+n!fr_+y;UZSa*ArKwDkd*v*>r*ULCvd&DiYGsdUr>gj9xaQAdTwGLgA>+)HV`b5$+CGz8h`rYWi6F# z)QOP_BuS{Ho>R=hY6g*}@oSV>1|j{KG{?}$Abx%9uj=Y+ELVnwPE!@^0ttz!=2el` zThp0c+$FF7`)eYK5iH=N@hCyh?s|$5SaMrKSbj}FV8Rd)icvToX_t_rmYxGEM6rgk zk{`VD6ur%A(l1Q)rXi^JA%D7=EBh}Zy})Ol@*~pX+aIF4=sSvMPwlS9PJRKcc)GQj zJB)*BemR~YovUg=w3}+slTe`JQO*5}LDqBqiFH(w*z-Ick%m345-*5FNWRQ$t&#)Q zECC&Y5(SEUD6@8H_%XEvWHq!*e;h=0iLzo;rh`g4*KB+YFw+!d&VM){RD|r0xQ^Vr-m(N5+}GJq^^}HeboqQ(J@!Zq@Oe&IdHIyDjD0 zU$$lRFf@Ps$U26l%>G{nvQR)n$b~vpT|obzqnTDXA-{T>+Z6@&H3B~AAzEub4Ba_> zKcVLM1yI|V@$tC6(SJ8wsShN71`)F6#e*(Zu6x>Gqqj126(y66G`(lS!f}`W3u7tM z`0s}*Wqewwnogdv)IYM1JW_aI$*m%GSwNtUGQAV#b)@+LIpqTiXm-c)fedXpR8~3q z+z9MPuRB2MWUdXM;64Pv3#z|CeR7rW_6rl1a*=W@#*V>UNcJ(&U92ys|ZE2l2i&^>u$W0A<`jx8oKC)D}szq zLwh81D#XL44}aB@oMB!y;Wx4kzIkY4$jj5%o$~1xEw%B zO1G@b*Pw-=rZvh2#lPl(g^HIv3+D1-jEiIVn#!v!J}iWDXz?*#%FAgyzKgnn^;xXf zi+eDXY-=@EUS88d>2zN#IPZO!cJ_?ezXX}Q_~@r;-G59h$piu1)*nr-^`$dRguLfY z203&p@(i5ogzP2alXP>4{QXpxI;Qg*V@;;?qoIomw3l3e;6M%B7$ZS~jkq0h5PlLZ z-cQ`FL*#hSCBd`eE;xcPodR%dF$Zgp!@f?e4iF~KHNf+&n1ICqG6MSqyoV2Tr zK;BdhgMSt7^Xj6fj{}rq%1Q3(SNQSoU(xZOISBCZL^^aF4#rz3!vrAD2LxPfbWqlL zMz1kfj8115pj(P#yC5gZZB}0MG5yY1ieVO1N^p~R34Eo2{EY>+qCE~a-3~w4BH@wQ z$b0_b=RA1cV?6^4YAT=#FbfsU#!sKH|EEuABY&fR_AvC6+A{$q;~}lvD=dI22qf-U z0$R|8Wr0v#z&_oe4eN&!y=5%8>iedHeC&jRvb{S9!=0*pQt})SSbkEPgW7>6OQ?1bRKf84J zk$>D@PDQNeI??FL)g7G@m#KA*v$1z)}?4cPsbnWi^6-ut)E0_Cxy0e|tWTu&Bc>S1~ z)rYS%mNrs@4JcE3m(-->uRRTumU2=Ic2GUZBsLucLS0f;{@7Tf zkBK$jy7RN7mIS#BTnH3l7v_<|rzr~z7AOP}fQdm2Tw>FFnr`MEnVgm#h<_YI-fM-X z*+$NPEx$NHLtJ$3{}j1;sVI-1s!=`RER|Qrt}Wv>6fZRIiI#6Qmg&-lmOyy2fv1(% z!8vI=hHq4T=>zm`551m;BL|ywX}VA4eV$*+1^ZS@3Z#2&Mx0b7ol2L}BQai_J-3sL z$%FTtjDPMb(2Tk6n;IQoGJobbGIK{usIr?zgOj`Cu<&)nN60y>;H-M9tiZZIBeQN& z#MqOSn9lE1((7pS3(~0H&d#~_X37;EYHL&!iWNF;iQ$Ow1>KuOS-5zesrE($&zOd{ zd7l0UtH3@g;Y{z^T=h_t<7FBuv3HE;k5DeSXt|i&j;9mq?{gWYFMr)!TQcwAq9LO( zjY_xEFHakJL|&XGn+f)ik44SoOg0I>piVYiN3oI5qA{1)krWPc{YqQZ#_C4Iu|wm^ z3WuKln1P82U2h4;s`)g=n1B;Y&0{hGUZaYVI)8Z&8P*c7Rs#O&ie*%qEw0C{zc+e+IY+wRUyC0rAT-&I0!5Q= zKPMa|KOZObSwC0!rxgmeM2nZ0X3Lr`oP}&J?efgq_REG5Vm-~K^k0WK=Evc_=NB*9 z+rHkQ@nYwN>EQcJX6YVP|pUW6QwGDR>1`Pvt7w6Mt1Hg4M<@q@kkYVKEg3 zok)$cGW@6OmeftWzLzsmYMy8X8XT&u>mWqCCA9bHTYmE)T@xu>6QKFa>oM!**1W07r}#eF?r3KzJPqh*o$T+7C>(* z+BD)xB!C%ZQGeo{i3D`iat>s7V{rHOBH~w9Xlbw#-e$U{13!LexDJKg;jMwwP+SON z-M(6SJdWY}3IHbtsem49F4sGF_%(4sO^s!KJ-Br5&7 zbp`4*7`RQ}$?F|kS=(bXo(nm4ZUIpD7A+L53$RdbXtlTlZ0uhY71XN86bXNxHYEgSd-B zDAc1%Jb%!9SI81P$xB=ujEf{MbLu8;kkQ41U3oNBb3}ugR^a08bIO3@+F6l6Z2onYhV7$?`PQZI7QdTbKRvsSLY+OPaIX;13<5m z##*oR*PRudM z`Yd>)wS_Z?k;z2>xGE?B@RKAmu+p3u@|$qc;Qv0LlTx&V@gHA&^tA#yQl-4^WdgnG zQRvWcEc2FE@;y^xHylu2 zf2#KTEZT^3rOG-uyHuHV4V)^7u=Q&%o`de4xJr_)4W&j29B%QxqN^XH+qghQBih9D zGcoWji#PaVB%!Ag#c;D22tvQGKqdVa|9{!wKUwJ3pN*IUtqV^m$5|~i$rC@~M+r1Q zw;n*2XbhiHxh#psa5*y(*Lhy6c#_fZ1Wp?dPFvVPl)f$0EB>oIGhjUv@fs-M4*(4( zH#DN|+v_DG9Hy7>bbB=cPh(H6hE@%(kF*>Kaf*tWhl<>w1r>Pp*w{ZN>zMsuLw^I! z#Sfn)|5G#=^m1uwVoAKL`cM`0vlma^T|RXuPnUrK*gyYi?c^Anb94*RF{{VUeDlpz|KzqUFeuqZ9N3adg?zM?t8E05{nW+ivTO|-Yr3X?I=U{eu<$k* zfln--Z1DN(CwtB>Ag7wv*uQqMEf$iz1SQhCEXnYczRhkZigM!EupPP+et%rsUCRp) z$Ff9ceiLPiGu4O=2w!#LbP=NC#kC#)E7?!9tCi_qz7KB1%b#Or_{x+k%#~I1L|o2Q zD9#!=qd%LMU0Mzi71*Pf{KwkNRNg6n2JgUaIsQ9>#il5W{urqr#`F2t6;0+VK~*!o z9&Ie%w8$}4?MZlke(9zBn15Vl7Mq@~3-zQVO!`bc3#gu*2bYw>LngVrT0)rKRQVyiu0_!j;*BG6P%mX7pEe zr(bY3_N)0#t0FTUy$VcbBho}OoG4G---8gU^r_V2Oo~oUL0q-pk$>HlOmFsykj>xS zpSY4Ssr+%3b4 zdg+I&Bai1q%oAVhzn-bjyXe3Mo9a7a>0Z-`AAcA_>!tm$wtq-7UQ2_J8m9Gi+(RqPy^l%2)I8uV75=Sj3hI&x4#~$8npY>ug3WIq)B@b-%pd z43$%t7k*Ddm5^Fik}+s-x58=}%vWLJC-xJcClXu!vHMhaBI9zK!Rv|EJC4c*+pegK zN81?J+=5IFvdM)P_IUXBD&zyJnW3JCk7F|h*U(p9Gb3LoY0VF4;;Lr7P*T zDvv9$JF-37hGue>JURV$()vcg9wA>U!z&P5OcNls{LFh8gW&(8bC&n>mZ< zV-^>xU^k~NpKTt~p1QY-O00;o(NhVEEomFU_ z2mkWlNYi~odb7f!M3jB zbZpzUZKGq`w)MrfZQHifaniAE+qd^QW88gyL#?VY*L?A~Sy&Y~eQFscIdoUmph!dc zy)I+g9{4RfW7b2USeH+OBB%B z6##gR-%9FjhrA3_Jz6fmlPnWVgkG9-==(S*aRV`Pvc_1WHZb^^IY3Luiimg2vo!z6 za}>%E6c0a8qbz<#2~}|1CRt#|#`6a%D6Qh*ktVxe=`O+iK5KbD=~J$3HJho##CpF? zPh4xIonJSu`rA_e=v>oWUY}V&D%9%GNeMuU?6d_DLshtt#h9h!oElDk#E4zLbsyYj z1$#?Upj#h*`HJHeuEAqDF6qsu!>o&&0PY~mGtr_V%sO*=%~v+y<0Z+(00T-5!3@lX|K#GjDAfa z;+UhXzR$uhH?A=o5%6CKey-vg3@CIZ$rQgY2HjQB@_+^d!{NZoK3?A9BY74?bVk=N zcNeh&1RO)T-?M*l!$7hTm&NkPWC1MXN{v$xJ{N?oBX0dm@(~1E@)7l$e zRkDT78GeudX~IqwW1d9MO?a2CqMmyk2g)% zjdToyjf02YXaO0_II*Q(PO3+{mRfk6pHyH%A`K6fB1>&C!DUQ}M7P2-@SIlth)$VC zK#bWG9??mH1j@6f58OiiDhn7W>__}7Y>{}p3V43q9Fsb*R@f}t27h$t50LiuWf)8` z|8t^T0~b0jP7N34dc@1$--MpiZG+oSS;VLDHJ*S1;lfS@H|g%f%Q27EGOIWA^ru#8 z+H1=aN_{Jnvv<-m0qQN;>a3)sI7<=M$I{nh)2n`#vj(SHINW{+2n`@R&><};mb-r+ z{x6qH(M&)Ps6CP}2P;u=8kdKm1zlCoPjIXtqY-_W!1a!06I8;hm(i0bAx%+wW0sOd ztHzo5GCfPMMnXtznMz72Tkt#65cy^`O2?X)cnrbWa!58gl!w!XAau@VaM;|je1UT= zg8|OihxcO#Fl}Gggalad5%tv}H-1L-#P_A~p4=vC&w<*`du%0Q`kT%0hOE}46sXo? zh>|E5UHO}~p)@)m=+SZ(rKt1%E^ze1+J71m)@sdS;gFs0N3|_J zvm15J(GjN}zbISZ{BGFT1MvV)E~$Ha&}m9HNq`(#={bO+;SFHVa)lH=u(FY<7oKF0 zyu4K0%>RMy(9en2jvCrwa2oqJ(9--Ic{=LI*IZ}tQz3r!2|}x=U5g{I)7I&pW8M7a z3`~MV{*%_${e}EF8=A`!jReqpJp5&-o-90{9W>@ysV?cR3LB(@70mfkjXQBkI^8<#3@`W&xj#yLSz?O7jIowrD-sOEN2 z(5;^_?L-^~@ogd+Hx2JYg`1@E6>_q!wUdr)`zgYm#SCyrEWf;wluyp+byeV(D)AV{ zJ>sRfB>ioi;=WiN)pQjA=OufRrx^P4dVM3%v!$4V?lV8svogExlGriF{9T0*`Gvk~ z>-VQkVQwmO=%x?vrOczjxL-DEB0KP_^9Ql1sW(YYXl9J<2_GpHR|{)gIjLa^B*22z za~30cl?b3{(%aP9^SZXSo2i|*6YzfKzM*R9w8T=|(G0mN20~fhd1PH?XMZ1cVKWh< zO#R2gR!{nMtJ*S-Di$(`I;NG-F{FfX{h%cr9($#-qryxntTZBnl6#Vag7*b4gnBV} ztFMD4iJa{ieB-!@xcBnyiv96?@UiFS(eE2BvLBEy`AcB-f+u~suq1j|q`lRo4H4!= z7b52PnSacSha_LQA4P7IG_+7ntkyRxr!;10o$ju$;wNmy;fj-}2a7O$!;N zlxM+SeXNfAa76wQlb|o7ro+cvz|FJ21ps(AcTy6mns~}ByL$YyG^v1Ea=ElpyCuok z*ORWn~?_|~~L*v;mxjc2k{qW#GT0#UnV&puK+(1^V?8X0Vkx#YMce0TwCA=d1 zw-x$7ol67rakd=)SgyiQ|KG>^D~%BW1R9W{HevSdtQ_s7imx&;^1U{d?k{dPANPn+3T@HmaWCSqWPu4T2k(~+#A zC*qhdD%(lLJpOa9Le(=^^-}4UP4NcoHFT36O^;pMsFP~ ztz$fS<(dr zVkgR!_i9RozgZ=A3k$AiW!o9j1s`A}%S_on^qEGBJGH8IW`nQo(R(ZLD@eoGoVSIL zkMv|aI{y=I;5F=p0$%2fBcRC`+ykP@Drb1bwL5w(*J>X2{l$RXRBV zg>Ei5#UHZJl=Z=l9l&jglug@z!8F-B759+JaD9#89%p>%`aD22BLe7mjBNRbC{2R* z-V@0*r}c~3Im8C;(FzF)`{QT#%4*0tK{*FnQ{Ph82%8dX;=PDUZDHLE@7m@gk1 z{Hc|#IUCcB_P^I{NFV%T8VDnyH&6Z>;yN_L!#6)ogoZoNb#g-sTqitg_tF0olo2TydN9gvn zSV*m9y!EPqra0qe@9V|h@AdW}(l+WU;DnP#9k&j14oNV1dunlUkQuD1^bim;wRiTJ zY)sZ__IV#TaH8utyQ9iRs}=r%Mngm7+=HShWtSU{%b{0?xpVW-X?5+q`p0nO5{7uW z`KzJ4s?YhW^+e9`(8x7mrit{eVRG`%`8CGthuo4gkT{^XyoshV=`@0P%KOUGT0+PqQA+0I}?n28gt)ON9LTnmO|h1@Z%E zbN2%~m&B7)&Khb6%*QoSRW{^KIN{TFVX#?N%cp&C;eK$T5GVV z#KTy~fQF?!ioFm>+Sj^bznGy2%Vij4ATObMD!y~56uOvG>4Wp>ux?iCYuRSxc@m?z zh3n~`_qv@d+=)W-egoWp9~uZb0Bx{+QluTABS!jXk-UPpTAP_+ukE#$iV+A8e*&BR z>#&+6gO{VIn?|Q5%LLS-Ex0hk24HKDo51jAO6Rv&XOD=gt2;&L`|1?P8?M%NbZGtDxfw;H zxCPM532^`m%lcR$x#dY!=zAR$Jz(zr0e<0&&AoC=FztIN`$Rhxfpl!m)@Z!kkMUC}s=53(F|i zQMUbUcbP%#1HTgwg255@Ha?8%`hy5Xr26RxC;&y?qU95<+AE&{D@FFK{J(#jg@JIy zcgy}&5tCg&yrr~>`6qZI4E$7U2s@XX5QpoJ`-0ch6xw9O;Gp0_B!AB&ueiIp3DT?@ zkfObyfxRqXN;M4R*B~ke&7u{Flrof6){ag6LMv`z=@pAy<~+S4^9B{Z8~}9?Nfi~d z=>SB%v5U#hYGw?Lr@+YUP%zAK(Swvl8&zZm2r$!y*)%75!Y^V_1({-CiHEx`U9N-E z#~svxz$o1dcjL4HuaEgi?d?pcIhe;9&PCzQqG-cjb#y%#&ucoF4NEIZK20fljB;I2 zsD1X~QV+yBxd{~TPvhn!hf1ce{UQ74pMZ>qDq<$9%-ARRkcq&et^_QJ z&QQWx*9VJ_h)>O>{P`Z>*QCx(PXuZpoe{Ckr5+|sAd$k36@c}c>%!p2cr&)g`(plzFMY)|Jc%siT z1A0cYvE)!-#_(KI1bIGd`blnlw+3j91Bm+NE?8>RsWi6LN)pVz|A7+W1Pk+1B5XDhf=u;S8m=fuppnRiS zia<3UiM=FKh%_d1~QsqMqTKQNa=lRjSi++6Du=wW^b~yC)L3*t;{seUZ&*>=qCT&W`xka z(;QeO;7jq51YPs&@9oZ!xwwTlBpYgJMQuYD2C>Uu_+*q#38;S<&OqESWMmNPGw zEWpCkf+K|w^$AGXyx5 zF*R~d3%@UMcTtN&isgl()vgXK(Eu93uQt0>ifipfI;h+D5~GZS2g`HF*g8 zLoSzCntYanLXp|#+C$a)LfTHKaiLyZepO)coKL-bRA2=Otj&YozkO_j9LVZC%R;XH zaE}nZyaO1zqr#5i+8&z?H9ky2;$RpC3}T7I*W=bb@Pz8SnnZ<3ph6oZYhXEp%^`dC zye599t{uV-R7iDv*O^SeT8JZ?R|%(;?FITD#@ zsspmbxJ}94BNBjiWkil2c(HhK{l0UOf&9u7PnV}$vx0exPi20IAOlc7f^5HS5}C`WVEo+&m0ByayTudQOzhVtq=jfJ(KBRK*Xp`Gwo+S#h7fPa2l`vZSmY2V05fbcLFx7gx;(5mxj)3Dr)pP2!B65%|yFkNW8^vBfJi->-OygSp zbNFO>&*Dv zhM$&um?-WrJ`bCs=#8g7E02xuXv)zy9^n)x7wB4O)*K!;MzbOElZ_FGf%48Q)oFCU z`FZKv(Li0_0(z!X&wk;Bk`G4cG-T@A(D9Jsex(Gi*zjqf}|3()E6>%~QbFKUiyd$WdGk~l= zX~i0%Q;p{E(cVR)mkgoLx2iVvC&ed>ffI2ZWvMQN#bax#?VI^-_WknO%ITZ<4hCBb z`la`>{c$p~eU=d^dSrt{#NF}yc(UEyo0GRK7b9R}bXURm;7}+4MGt6YKMfcG!HK!d zzMc}sCz_bjBQt2&+ZF-yRa7$9_7=A3V2do{_RLcgvW=cik6zI@pQy0fjX_(bQ`kDvh+_db(huWtFF zDx~xSaI6YJ!Nk}5i%>|^g0#*PDiaB`Sh!5=mkfnA9Y zSCu+$HVV4r0~;drKiIay1}LjFW$2EwRkQ`M?R*4OlH_=1@wehx z?95nZ!gp**{sP>0E#jv_wXi6Lb6*RP*xlvqodXRM@CO>$Myyeyn;*p9O#<1ew#K;@ z6&@H&zOYMl93`JzHR=ogf>|%Aym=6zBhF71vLr-Wy>&`iFemF}itYDAc*rSK5={30 zqWwF9eK9yg`p%Qe0G7j-b{Q7x3-qgvg6T?LgvHB$QwVTM?!K1Q>JtW}=ksgs3OM#c z_KD8eUVXzD5_s>AO}w47Of1lb!^ekqSaRou13kk0N39%_;L}}(644VW^da~PCz|gW zBJ*dv$Gl!VNMsaVS(YT!$??T*w{5W0k4R^TyNXZ7=R1v_Y_Ie}IrkPnbroaT*SO-c zECU2NB|ZR1RU``hZ~Jw+&U#w9s@=Zj5m_`vh;kFIjNcW&7Fn!_=jTo@LbDHB-zUlU z5d|(rk^&fR5{C(B@uybn_JkE@8niu6>uWz>UH>ttz7ALir>A#$N+1!TLnJ34?GlKy zoU3Jav4xKlsuSPx6^f#rmU0;xKw-A640J+h6I5|S-{trqUtZKwFA0E&P z7%?;RuGJKp+qAM$0aLI2;&So{7l|6LV2uOEA2?WcS)?S4>n=^Ic^59zuWR}lh*EcI zZg@yt#Kai8v4rUJZ&yZ$6%vx)J2=Y)+5nvG-|4q6{FV)_cYiPK0^&V@u|g?DzsOaN z3t+ddkIOd2@9N_CV}13NV`XDuD*(E^DfLa(yXV=M^UH>GBQE9`;|J`&OXE?4KH0P> zY7idy|7^Cbm;)%+p@D$%Nz&%!|J6Y3M1er0G0=d(0<7&fxRJlE^#@cj>UBAtvL3Nm zH9c~g+3fUi+NOKj=~c7}ZMVk@Yb8gX>D>SyGq7Yb_atsz2nGRc_XDZpo{q;;L|9{v zR(a$~Ec)Pq)9q%VJ5k{=$ZV!4#zwxIc5x*c#Ud-}i*92a_d<_w9EH;dobeH6ywIyE z;7+7s00oxFGZpO8h2RlOWE#3=ZD&Eah{tY4s|8UH{G>$`R7}*1%0m8H3u_J-n$(j^eK)!U;kP+-?7ok)fClsJHd`n0w z7Xq?}lOhRxkK)*k%5(JX`m^fyBk>^&kCIEfuA5!Fal`HC18yasHY6b7lp7PeM-RmS z2yGahH7CFf4lgUPq^H=D(n!oG_1robFlUrO*e-BA9XbOl&2t=r#DK2Gr!9dShrU>F zO_m|rQAMREOc*sTn71b<@$y*{=rRhpZ;3&wHVr4vKp!2qs9w`ZXtsH6v+Hwr+tbx? z=fTiBIX!!+q48>B zL~($KAF3s+2w0!5kB5kqM1#Tt{PFJpC+ma%mRUeu&0+)}I7s*Xr6MlNR-KAiZ%5Qk zStzaooa>SrY&C54W`KT2i-Ym ziYAOLR5~P3qK1rITLRb=K*El?io04yTEZBlUQ9xB6-h=`J-bEs4%VDWbvoV&FAfYU z$~eFw9Tl8Wafshi#w0g>G=|05W9z=^4YRD_YBkDwq|KFUmNQvvG{MhhpI ziS!NT(y4q#AzhU~)Jt9%q|!E29qjY-RHe?a-EF)1v~@C@NxyOj_-rPIyAqvk$+L>7 z2bZB}kxv+|QI3;N$2Y}4`u)#DPfUf$N@QY+Lpjlk&<}?w$CS1%NZSw|(NJzdI>wVO zw}hJ}DXRUu{}Xw|F!&BCJ|d^|6Uh+h1Fk?2MlMJvIlkUBcG$1iFh(+i7bVjI{%36Dx;{rFlMdzBDvZeBPtT_m}Q?kaoB z1WE}v|GpTAmXU}=fa_|Yduu!l|B9K13fP04YVeM0roYb%7wtkO^)PQeW zO1v7!LJpGAdm^8C_;pi{c;6r^9G;qQAMS*OQlXJx&*_&QVUzp}Aa9I`uvmvWqqg4; zW3(Z|TJ_2WT-TgI^2oltpZnen`SF=8E%2?&gp%{Hqj)-h1;E!U-XFB9iPt55T)dio zjlivR#^0>T^Gz^{Co3}|8RvpEFQthm1IaIPp$KW?2 zcpvKTawl&Q`WIvG`t7oBsb&g~c5R4*1cB05`5&84fpORZnMl`aaQ`%}WR%8{!uAuf z*`x{r8t)7#8%gLfn-xu#DpmELf#Q7;E<0D!(pJ=uP`VlkrC(5}QC;}F^(S>lxm!iu3vuKo-&$69DdzE#d+_6Lo0-PEPh215`6wTOrTF;${W%%0^p8j8iq?)Wg zbU|}81AvTB>15s*E=kQ!uRg}WEOKGz@d$LzS5t+%Od(q{)zHjC{rz{t9e!fdyrt z#2VHn^nE_hJ~8S(-kzU7&y!v{0Djs4%y>@U-C`CC&7jHb0{F&aOc&*FTa#X(1rcf3 znG?ryPWZ0!7j04!`?-9HGwhNN`a7~ba8*zX3 z**v`7`d;&){%Jy3UFf;_f{mY7AxxYr9Lk-p(5>v0Y#Y;$7W37=;+i7@hUQl2LX*%I zStS(dcYk9jI||mxKZOLX@qULcFcMHE(LXc&PUT5As8c>asN7Ho}B;zfxJ$S%v#qYINK2!O4oMMOlPNX*~kSfk?cd257@sTy=3 z(8OX4PTxM+YGdw11UrX+(GQVTb7i^)zjSqEGoX9Nl-7YR26Bf(+(q6hJSAwwjHv81 zTm;fr-}T@^YxGIs1-eZ!G69}kS3&h?p{(C*O^dkt>#RQ<`XssOnOLp_NOqH{G63kM zYtwJ0UhV!Hb<4(iVtO=#gNqyJyGAE%Pdl44W^RaBN_{H`FKD0Q-D2|}_~#JXhvzzM zUt*{9NRrqS!4V;IgsS#qx%;-J?0VmV5(7q!f%1b04X95jXZ8Gvf4*!`%qBdlLoeO% zc6QM+WVBcBTga#BuCiPJYK9*+k+FK++}zWF^EgZa1)@bZd6$n}J@^rQpU!OvG3d>7 z_6}zRkjPxANG^#}F3=J!C<~!P7%;u8=cH(B=+HH3_w9-CC8Xp9q#~?NiehA@SS#bQ z^=pC|D@GXo)(h!=)mz6_J*`Mz6#pHMjn!D>NJdYCAsYYDfqoODC9s2#{No&J|Dyt- z`Q_;gMI%XqjNX$?kh|`IoQ-PACg4FffZAWMp~i|%*DuF|NO|)1T-x7ob)PafHd*de zLTc|HZO*#Gb1j}d{$Vwhn##mhx@|O(Mxp#xG*+(Ga0E@#K;40TP20zIci+Q|pP3 zT+z|kO!veolB81SD?tcyleA?F*6Fim#+&D5&7bJY-ZJ;x z;fV-oQn50G6n4Y&Lj@RLj(%0APgq$kYYxHa6v!#wnX2v7(N1K&?SCCjr{omisNMfj z8r2Q0fWv71!}q8Q z!(^jGu#JULLJHufxSPcCOyRtFL<4tPsdS{TXWHF_kS@lI7>IJS4TWK*!%1m^s$#`~ z*euPBKCo&=%4w=tynE%?zsPZvns^qz^hZs!BrX=pA(ZJ+0%$(VeZx?#9#Y9fV>nA} zUA?B->U(d{Tl&?}RIWqSCl#z(Cz>QwjOS2j-HfL;(U0nqFAhwZ&7h?bn@X1EcBko_PURUw zL~)=_ne1!Y+`Q+J$sw7cp;nucw-P~0yF){ylj0u7^uBw3jm^$WT8vFo9$AT0ZY)HA zRUv)Lq|U^lr4B0>Kmrzh4|gjZt|DIdw4+*x9f(qw35{p=lQwtBf)l?x(&|LiE(|efyC358&9z-S32Y z8UViqZQ~bO=_rWwL=~+2x&2WNRMn^^+_yL*)?_cW>(4>XUZJ%nbFPN7V|AT?9gu5* zkPwV#1_TB(`3`8jo}DvPparoDHUu)x|BmsL;v8;4O(4=k+f`&yy)whR)~>|G`}MD$ zV5X*UW<#b_MC-A*g3u6XvcS>7GYBkuoE?xlbq+bvq`E1HFGRZ5gVJl4R;Xn z8!{upwdyyKjgrr?@2+%EOg_Da+SR>ny{vTY3cv!z_C(wG_3Fwi3~0cDWg#58#@6*V zT;pG?Wf%VF#fj(P`h4uoCzO4s*0UFa&h;XhVTAyGhg$`~XNC{5+N6fjklif-Vhx*Q zh%p;+3K-)!CHX}TuT7asO-S~TYKiM)kv_+pwk(DUVW*W{dz?;;Ly9vq;9(do={9`P7pLZL+`3g zOdZ`qm!(o+q$Cbn66kbX?^JL9W%_Rnc^}Q!l*GXsOGF-+%#Z91(Jm8~&sRCo*oPEw ziQS54q_)A8*-Mbi&h9U`nEFK*sETc&C%}}Naz5!hy$H68SjQ=vM0M8OV1RJKH7A{> zykjU1W=n>`owuyEwL%{baT-mzxP|8KF>zVFzmiixP>|2xmu`F&%^|CD1o}an(Z3qb zx-*^t;Xqro_eMbx%ML?9AbF(Nz^bWOA}|}|zn!BFsc@NK3(>+frVj)|IchVJ=m6N_ zWuFNeJGX*yiAuUN*pX0`8h?&9AiPeHaTiYYwa84<8Miq@ecwyJGSM; zUMUNUJEcYgLX_h4VP)LKsX|F>3ZOw~f2P?2Z(yl>)lGkF2PdJEX0nM*xWr%19*Ge#JaoynV}4`UP&{lfp#+Vb6YB|F#HmU*K@f7ug0@a&E|*?X2;ecge^ zQCHHxuuX8T4-}lLh7E}+i4zQRx`UJQL5{5P z7236Nz8+FKfa9lxt^&{?_cB!wKkNPs^a~;5SAJJwu-(~=wR0&Yqzhr1daYU_j=yIW z>w6@`mCd3-4k(%elU6aPc0kgy%EoZYZs94jwvJ!>=j+`)`MGBWEr3w5SiXP(b$OrV zvvZ2SuTRJ4ljbe$1DfX_5wn4y=g=(;5t^Jn3QV4obDch@qdPHkFZ<#bqYBe|w`;el zm!apw^@CCG>sd4=d<+6m=?K^ToJt_o`P`!bm$1mqJIfb+e8@ zGxzAT#rjqOusKCm9l!&9yAQ&&51t*N#xTZE^D?VQ=5K6`tJ`ght+I7xz0n#oJEK5> z%v*mb*76SDWv&fl_gql=8%f8WgMnC5un3l9jI79?-2zxsf_Uk7f2`zxYhj`G^tCSk zwK?2#o}lBu`v1I)PQDH8nfmmNRSX3DQ-F^4%x1~w$0fy00RTTwLN4J#2Dc<4C-IWt z1z^|p;`r9X_R6de5%%5X;BZC++q;@*s-e#hdXD~*_HDX!(7qLBY^YdK?pmga=TAhp z6?ACqu(d$tZL!fBq>eT_%`Zosx(byl68I~09?z%aur^RXdF*4*rPASEe_-Cr;vR=N z%m~NF4aH;)E&yo4z~#Imftr`k;KkL%nyx_fAm{2CQ2Nn}%gB0BO_#HaLq`EmnosM# zN{aP-zGCreClBRqe551X)9qW3$0E2#UAj zX>mRYiXe2|tTOMSW~*ZlkFWDHS|Pqh@}{1~dLlS|A0Q@sb$)9F>%5ugYtN>AuEz{P z<&5*4^XK6ss_KGLDjS|G*L<*sFMw^+TH0OEHi!a_hVR!eSMo7p`?|V(0$O-obC$EM zrNFZvE?1<0mnQ9=K)v2!^?!;fQ>NUHt!-b3nx0*Ys(^c%QO9sHdB?_eCV(vDBl{J{ zp!;*+5`aMbGGquXS|-IQ{b62@9oMX=cQ>vJbN-x-17+caoX58p$~7uL!4kz+rVH<@ zbRU4xdQpnTIora2?KBeRp6`$LHfrg0Slch3SDjoz6R5a~5rbrq_o&cbJJs^x@Fc}> zR6j7L$M=ursdNC4D0i<33o6^`x?{z9Qq8^V0FWF4@sywYr2@-IaJ(qio#DwnBQaqj z60Bqr31>je65Jg`Un1KGpk=!U50HSHJ*Q$2-WVg#)R|1bTG{UF-Y_da-jHr3M1T?b zw3q&d-dk!#_5fd`V3mC4KK@}KQ#7J?RyGw7BG>zZ^R6;fW@<06#Ogd(KOR(>mDBoG z0tj$ioiA9hj}bU*>a70?cKYxhYR4I%(5fpcLx@&u{A&e4Jsrq+_Vjr#QAP!JF>yAj z{_oN(3Wx-obMDvW(q9SywKNF%)UWOcLHtQoBN1#nz~Ykc1r!m?^2{}*V!fWPZa=|= z%8!ba1!ehGTXnp{V<2RD+Vs>wMR8)W8a^3M#*DyTdHrBL-S60+XFdbAeY8kuz@(># zLD6w!b!Zc#qG&iV^LpK+VaWmApRY$J;PQQZ_(231O zXf?SQ{lpjz!!XoqL2pAGSsr8>6kgTFmPS;)jM1YtFn??7Ru$BX-Jle)f%s7`8+U*> zBtsPIOrxD%Rwsm>z~x?3@M0x9gIi-o^t863A96Rxj?{%geVAQ{>%B{U9(|-8f#fd< z(|YvSrzB9HB@auSf`{D{w+?~kOZTw*mBlY*$FJw(_u2iuo35^nE&)MbK4#wxBz~kP z+`US!sWab6WGFcop_n&X`m+~(z&n6zvQY`<Ei_0SOY?7)=GS z(*dXH=CP1$D?^-_J9<)vJ+cSmu>fJkUZA(sUCO#MWT+*kv{Aa&GMsfw`b3oO1dP6s z9sO`cngqNxT||6*v^axITUPnbUIJzRmYNDu!nZgDy>rCzyQu4prPJ4|H3T5AGtC`y zY!1}KnTUOv>}-f;%*;m=BW~`t50ya%P9YUC62lC-kW7v;P-;VFzz<;?625ibzsQ5T3Ky36zT zXXnpse15iXr6ax-DxO!usvLmFm*JG$l>mhnuFzrXvc1Y4ry~jv_L#Q{*aN9KuN!fY zE234*S(ASq=!Hb7W*XX*``lxh;x&rPC%2Cw`HM;iAq|Y1-Ak8Y=g4l6seNL+(R=1t@g>UeSaD#dklY|3?%|$Sj7c zslqmiUV!WzT0!*yz#8CoN>a(S^b@224_VSO$}KNp@a53G8!HZ^EuuQRC$vb^jP#bV z^?dwmWE90=Dgk9f8(#^fl?E3Qb8?@~ZZ{ahkXYeIbMN=oS%F? z6e}9;0xn)|S$iGs{szsv`N#;?`I)iFl?%$5?##R`@8Y+ZZ1M!>20);7pCCh7D6 zxeC3Hu>~zx7c{9y6psY`Pt(DsY4DLJ*kne{B@E?~VTuz_a0(x`Xy3zxg+N2`L{`>E zSk^_=*v5-{8Y`ecU3clx)-r$YHDq0+2LxRgiPs_0`=TjG|7V)Q^WL0WBlF2EakmIP za7otX!1sb4BTDN{PUEO#jecE(27Uam81EIjEP>MR0|$2byNO^8RVHT$EMrqT8#Mj0 zYTQEZVp#Yl{@eyNqd@iw17g5zOb|&^qHoAikF&2C+@`b))}OkmvnKV!Xg!9mlo3pG0|Nm8gQYRW zfMBP^s-eOFVv-cC|D{64cAltW9|x9GGsy!KKs+teVuhANUA>)TcLuq28W( z)?%7cF-s{l-?zSg+$knSYGQ(9PtrBXyBJDX3T{75-*fmhNAdOidIyn>Aesm184HKD z@^*f|82`dn--Pt>x$H@<)Yl!n%?H5;2P3gxF|$%P&L($=q+ zr#G~D`h2~=8hd!zszZAkGDtoXp+gI;fT9eje!erxu(?WO?A^jII;271G^QN`5j}W} zC6y$f3PJIiKaUkJ8bfa4K#b4D)vBLSz@}_2AaMefUo4Lvn5sZIJhcF=745H7HnGj6 zC{UpWP$KMY(H8M_t{ViPX65b0b4KAN`-sf3sS!cy4jdm!>rRi$W=%zvy)$03394;R zTA!>jX!_R?H_Bt0$1S7~iQU5NrU|X2SArXhY0)K!-so~toY+pmRnKdVubaKTLtE0S zdKG(_h{Yf+cdb^lFTPc~pVfUjo|LF9gjm)CYC!NAN+%%Oa-(n1lfY7CB!jYmL{o+Y zKx1g3lTr#G1(xR947o57uVU=1aPD7g85j}SlbCl!_&T=3X$13j1;}OO3INL_kLRLA zItbl;E;HXC|2_8qNV=sNQpmOcjy>sLDv0P`-@k*U1B1S$or|fHouN${p(F@oTCOw* zJV0sSUpxr5=YyvGc@A|vItTKV)n=8^fX}5rHh_AufnAf8veNF`FS(i(P6r=0!|Nu& zr!dRR2sko^CvSaie3cb+5v(a|BM2rCH`+dllR#T0i8y~hjxtP^lXQhcZt(!fP4vTF zZUH&o{mtX212{(em8m~)PPrWgbDAYE05Fm*XmJz}{fiUUV&tr(5(F;O1<8y&is_n# zRHX&{raP>U3OXHgG1#kO+7g^jx7ll~Qq0E+W&{qAQax5Y*uB_^gB#SUAZy(iUR(-y zmxIDa+R4nvEt%NmHVPzllbJg%zAOk~i)Np=u%$AmW()&^thZ$!x9zqBw)T{`1dv33 zIm}z}ya;7uG)fpx?Bp$`b7cL{<$cQi>O$A^M_|Sx=Z@R?v2HV~1&; zx^Z8x17zJ)BW`EmfUL&Y*Z+y6{O5Axf6;0{fdc_`!=%N@f{+4k>^ImEzpnfC^Q-HF z*Q~CpHL~dNmRWJ2!Nlg>PQz>wEzW2g5+q}a&tE6MpZSy$0c2YcHsZS)fA6keueT0r zV(cgQP1)> zH7He0aR<3OIxzu=dRFSrWhBA>e^F{wUrbu(^b7rGjMQBL2)8;0HcAsc#ehk+ux>cat$kGzy6AD){F5L)_FRvh+iJ!$=x>Hl zX>-<|LvHhwTs0@?d8#qowjWaYO)$G}b!Tdd2=LC^K#Xf+=FJFpqqps|QfeJ_TCL6v z7;1{%U;qG*A)t73e8PaH4=+duXdtKEg1T?Jf;tg{3CVDp{<~dGGtg+W-E2&cP|h~l zd1ha1x!zzAt5q+s7s+EyJ*cD>!%5&S!@Kw(POJs%HW{zz8|Oc+i_jG6jj48&LxL_5 zT3Qq;Gj{E8Hg9co+LGuF{L7bBhb zY6JmIF$y#8+C;YW|BtJ4U=FN{+HBM@JGN~*>DcaA9oy!O(J?x<(XnmYw%xIl$@|Sz zP0jp;Tea^wXYc*21urUO1Em021S6Y)kanbBPq`G2bKRnsW9e<2UD2Q}x*5A6mg_q1<1`w=-5zL_E zZ@P?*ga|(LB&dizNzErAc@XYtg{9ZCwOZ{_^+(4CF)%7LpLn<>j$aF8S8P4*-UI=C zeKwE3uKGViJ}7Z+wkx>Rwx<{M<$v7m5~4iC$l=WARRn{FraRy5rdN~)_aLyHmI?A- zat_9W4QXnId%164uSCC6>w1j_;!JRy_XPXr7zNoQ>B~-52OdvV<)l>3TBiES+-4N@ zl`!J~q1vNMCwiU^@v?!T?l`*&W^6!kjD_R*1E0@}V6)HVhT*fxlK$nS^L9HQpO`M1 z;_vIpy9i%$-vQe2((R-4CB`b~%=QdM45=rS#*hR6wY+Y5f;8jiv+RM>%~%ZK2r-i7w=c$^5)k2a;9G!(PZ0yez;myBMn~ zXfy34h}C;Akh}a~v>LWT7gn3C^_DpwN)U?SeoGo7CvtY)gCEjI_42DxD7S|K9K(@o zGp_Q^ZLMwN&n1t&UF=&=!kgjV8BB26kx=jxT9U^NR1iyQg@VFOAWU|OO zClDXIVhXIYH;R_4v7z&__lIK8MrK!VZrZIy&Wy7H%W%)Y!u~Y1BCy2VlASEl?$B1K zNh!~Eh_h>cP))41j+YmI)WXj0R6W2E*dBD^^22Tb(t@3T;TdpqS)YFnQ&3rXGm^`J zbjkdDD!*xf7Hc>*(@UKItBgbvwi0S$$f&c88%GMa4V)Dy|HJ4xBmdh)?`OpdNeZXE zx|9x$wQfGO@_IFcd{&T12*)M{O!6A z2{t@eU~xRQ4I^1SZ}~Dv8@$X4`9<0S{Xz5QcBL4JQ{4^o`C#ROJfnA9eRt#a$_xgy z9i!n6q9{MRhj>8s!lC2>QK;(S@5@uljP~L8Ak99N*OB!yd4wt2>rbYY4P&AU(fz1u?=8xcOy>*h^SAwtjAn@AfwsHK< zd1Z=ZE|DAjcrJXR()J>PVc^><|Ftf_6PSrA*XKyhPIIwnT>c87y~3=+jS?KTSy zP@Z0H!({Ymq5I>paDlLHw$9IkD5yQKF1 z04qDU=>A7qP1JBzDh0WhlH6`o5OFg(&6T?9EP)7cU$-czLiY`5&(EMBU5`P_u#?kr>y|CvAZbJ{JB<(NvQ9Bq%RV>F!%o zHp5--6_h4YNwJqgYFwN1a*6`OU_ZnO<(~Q`#1=I;UcrF^M@4!Y_NR81sL&V#@Xb zuQU+Z0*jUrNd5`SpNKD#5(PWkXZQ={i8Y;;Xi14>tiMA@^IcO4tLY>YW+6>Yo6;tz zvlF^YBlL#)GMEG6A{^QNF`if_0}92Wo1&T;^vp`U&AWGz&t8I)b8)-pAe6LL_jREH zi?VBs3(?mxGZUdC^Y_TQ^uK`wE#nQf>WCAUejjswQ$w29>I7E0G#9i0lpdrwdD!`P zv+|4rUt+KhSe?_F-N~AdNEgEfAVx8J_#p9|CWu z9FFC%B_H0mxLM?yRI1jtH*0J!ppCSUyb6~s;D_>NWSj6+|E7dtZIwsS0Iq8`>^|-KzQ?Sl)O|y-^sQAfVFcF2W~Gq|8<31^xBQ)H8by2|~5i#;T#gfpW zT9dShJ%PTT@>u#Dy!m&gRctm_*s;`enTXyI-GNg_-R7mn-G#JKDLM6imYkr(tJS%t)COXy@3)`h zBEeh~H_ZlP2p-0A;GI`!-@K@LgTpd6FNw4R=ztPb8LL{Btg9%d0?SfmA_5 zNfwmUl#C=dUwjh=aH+8(<=?Usko!l0vGo6xQeP}#X^FO|er(XzrO>SYb)0TStDWRI z^8xt&aYGFyhI3-|oJlW6W0M^kgZ6M*)Fh!0iTA(UJ#|A_MDQ2L#vjPz@D0^i9E02Z zR>E!X#o1=JFUPtyNo1G$z4dMHgztPefr5;fF?3~kn0A(lDmVozE;!? z+DXOwjQp$5zkubme`g~#RZuUovZ zTg9n?s7=oL6y0^5^(3?8VK` zr6aa7GyxdI@PCzp{7Dn%Lo8MJrz?k21zKUZG9!+bl9%dmhrei}l=~QI_&bS8`PS6wRB$M}59UY-rCvUp0T$O-t z_?uhL%MLuGQ<> zWAq6&=st#&^E5Q@xS0DxDzt!s;5~Iz% z+KTQ&$WP2>kPDGtAg&(;R4wE5mdj=a5}BB~U*VZCSVR-U`}}r^lpq$_KRPF2iXDy8 z1~I9IzJ8)e`^i8v@*0s1yr(qhE*tr!eY!^WMQ!Bs*-5yMXAmAdfpT>c?r>$x*%cp| zC1+7*E%}>!-tX}A9{?D6agxN&hG3vjs7p>cnBDl0fq%O1AuEU397yyo-NB&_l9zLG zo}ryO9d^fOOrkz%5`=Gqshw-sn*_98&I7nRME9V(P0cQy8L&h7G9^@XS^3_CtB}AD zAzYUsFvqUn283`hQ`;*~`m8#w(u{R}{iFb4PvMGygc=s`vjT*!A&bKTL2HQN>jszi zdU3&@Aktt)Yu!Y>ZbOioi$|qd%B+9Bw=#S9aYg3p2D$PztxWMZUtW}4gE~mtaoB$j zLKZ~o9W#DcJi02jt)@}DQFr@PY7JSlxrrvTNA-PtX;>}qtvKMPp*iq_U7}ksyIo@M znsw&jnGQNt8U&UZDLSvBwh#=pnOdf#xOr#-S_Ei9ye(Ey>t72SGijpELvB<-=oOzS zYV#V+sZUVXg@1@!j46VqVqf?KHf)>}q#?W*%k0<0;~}Mi!;1Vdo$^>CB$g6LH1LBk zM6^TYAD!AbI$HJyz7bq^>zQ=@di;kOh;sH9^6n;megimQ{p0<|!FL@|?smg&z7ZM8 z=^XnK7o_h4H0Ow*|B;l>7aB}EB~+wL@tcy^qz`&@_{B6UA(&}mj|2|*>33(gB!?2| z*S4)>QjC|mPg2We|BrN{r{~+q*T%gM)FZhro_I~C6o{g@XZBvjxuR8Yc0HkwiYW(_ zRHyzNzjo!Zjefo`jh|k(inh-n@{juqJrn5J9+>}LYxV;0?QdTRj5ut8B~K)sFyE&S zN3GEOX2K?shU~hLt^a$#Yex#mjf*#pwUB{;OgkrREBsIV0xCJ%=!@R7&QW{l_6{3a z-#O8!op>Ni;l-}>eJJke)SBX<=6qzFtCOt_cVmJ%{rsO;ZTtkVcK=ZSz%&|QFOI2u7m>_DhrmM+LleuKF$-xtM1qF5ZoJWWAUNchH z;*(ciMs<-q?lU?jmUadNlDgzCP;@NPsJifOC5>?`l}R>vmQr}M=$Q?8=Gk(r80OoK za_EQ;v_?Ju3B z%zWWT%L3Gm=hqBlUkh`rwzkTRa8au8thU0OEA1SKQBOYuC0@=Y;sk~Ncf49r&Sw!q z92xCTr?$EK5P`Y%F=2iW@0Wq=J;rE-t`zJvQxGzMGhJJeRU6Z!P)Ol2%2wD)oP^*P zrW>?I*^FCZbn`2a>d$#DUf;;C_i-_D{OYc)XC;yOce!B#|6;dsH2ey$VYX~BrHN1e zsZC)$lB|(-V`fzs|8uF5*B;_0NK=E=K*fM^+w;APzW~FXAszC?d-RjBhg( z77>M&@n?T6wG3Z(J&R5wU8fjyy(O1gv;4!$A*M{rtp1<@Cbg4e9%)lpt8&5eGMQE{ zX6b5#B}iPBu1xrSFnroW5sosl_<8qx2S{5TPuG?q@6x!Mlya%_2otJvkW@)OOhYDm zgI=pEnY%$RIJ8PxA-nTU3WHxRZ1T^>Fo_;jRc3-1_3@6|7xSZZBLc~YTjLeE)$J%3 z8cXZ5#^;TJ)P**_4!LUdYae-0OSci0atdL{TTZDnBzJ`hR_M&lHC0WUxe)UgIFSiU zl1RG!3<|y=afH*e0C8O>uW5Dz2Q@aAD(aY&eI8vy8|=h1>scOeG-ql*Ir-)ki*Jmy z2>zkG2wKlo6GHO5MfRAe(0>AXqfTGH$Lg_$W&5ca9!`OsCK_jQREEs#Q8oC zV8p|K^k>F|lOFv~fz{(Z#@WG-^mO1v^`Arf_sA~&PCSrY)ooMG^bD zSEkbI*tFwr=d-9g$$N@t$$N3nf&dtKq(O|}ZX}RUdqhd)F${L?gfQq4-9*9SH+Qu2 z{96KFC=#Isa&Q9_YDE*(y~3=fGjp(Q@g8kJ*Co@m9Y358pF!eOEN+Wtwd?f2rjGdA zo#xvLDWM$QH02Jq;tA@E@wVHxNA)~ypro>z)F0D^=$!PE2H>LM!_f|?`W*x`4p&Eb4NGFofHAN|NSD$N=nZRvB zhe(&qDv-9T-9~_El*L< z)R<{=8qv=N&PLN{#z^^vhCHH)WWz@%exG=(n9NE8({)hAuqslEvyhl45i7^q%-ELJ zOi);dExoLr+K{EDo+Khx_S_T@SzHoVCj)8Cf{evhDog?eu`lH~kgrn`K{L0 zA<-_v*I2P}$qNQ$#9>&;xcd8Vct|T)E7%=)-(fxBcFS;MK};;Q);n$+>$R%m^Xcx1 z8-5JFf%R@aq%61wrM1rsu1^gybe!Tk*z@(m!C6EpRIs%ag}bIn!TcPcW00Am1@BfI z&hzG5Oxu{FtIu|4EID)q)wgjl2D#;X9$qhKVo$}CVNp;ymr)XN5m(0EK@SfVhisG$ z`SH~dq|+|N;FOV(yTLe%OzNeFc=1q%g4_xqQ!pls9a}eGYxqUP8|mMVCsQkxnO#o# zVQSV4ZzQGdMja4IMsy4Ov)MSVU^wR9!IfJX&P%1wDIfe{uL2ct{HM{wNdk~Xe>e9p zFM`B16rcZNF2uVRmu_F-HV3+x;4Uop?|`10&3Ec#g;zhQW{du8Y2}qfV7Oi|I~MJe z=>+4(qmiPpu$r_w4f(1}X9h84EPJ5aCV*KZh;HoQA))fNThJBL%#{>ZupvZpmB z3@tJ1iQW{VGALjT!jEBmF!Zeh`OPS+1WjF3!1dEAtuANs{kR=hPePDMTu3Ge&{eX@ z_sU#e{mW@8 za3!5>zK`BMUS-Iko3UU@XO@2ZN7C}PbCA9SZbFEoH1k7U&X?*yBjC;iVJlTbfl>8N z(7U9-F8zdXVXC4M^gx!sgz~fpBq`PU-#Vr@3#TC_!L%}9S0DV2)u**CHpj(iCn*HU z5o3k;>bkXhIlOEwUi98nTfqZ86KFXK0Yas`xg4fJAc54xWM;_%F}SZ7XCoR3oqa-R zBEH*eKj@64`kxvXNxD z#r>D^FU9FWTWHmt%b?b2@j*W8YH}pD?EGfYnP*o}NiM%&m+H)tnSPPo=WV$gQrCy& z%RQjVdxaPP0(EHb&D}sl%w-qx4?%h()?Z9OGc4E(l-EQcwfB$C1!SV$g<;BHvX{sK zHjDIy>rdxPUOkEkIc@LQTzkCN2!W~5r?!YAg)Q%|smQ~`?Ga{GeEC?HzO&4AlkAbq z&C6ZD13rpdDo1ICZBgW>LzWLw*;EgB896YHIyp=hUpB=`n})vn1KsC;m1#- zE&Dpf`H9kdsK@;zr9D&A=s*!^pzRsMfWgwxQ5e$i{cTPGKY0$$9QqRMifnhOhcu*) zWYUQ0ROS=(hny5&q`T+M&~zjYPBOHieyxr0KeN;Mgd_n5H`fAJy(tuG3y#EbrWBG-E&Kr=T9m67M#|@8W(($^^@y_HY->!ZgI<}4Nq;q;#<{p};&h#hcF?)A2 zyDd)(WT2q4Zo#AMd~2r*o{j{98JhZ`wyIh5h;cmjZxl?P7yJRWP?1vG52#0C5&EIH zlR>y>BLpzVr-R(-ib8;E{q~3b>PdV-plcEZ;W%_W-W5>i8HHND8jY zgkd^3b;fw7$wkZXhH>nN-ZOgJF=vI$KhXn9^R z?xf?2;(WZEyhdzSGR)2`LDBo{s#Xh;qNi)H(tzB=&?|n>AR0?ETQe=)NixP-MP#-3 zSv`rpw6`4Af0gVdnZ0hM5&MIoq_F<_I!Yv}cEWj_(kk&?U#-j^WwK z^~fG6dwA&{GmkvjZRruQ*72TFVcT0DQ^Dm_bF{k%8P};9uPH!R^!;Ojuy(^EcGE#W z=C8*7g>su%iJ$}7lHT+l_QqC3YUdf#gaAes!6fZd?K6AFf$8yDHQ=Y%$8wKVDy3 z3)j}@b7(0`ZMZ@e@I;6GE(@p$sAg@ywb7GJ;appQiE$d@8L_(H=N;f{&qQ;Uf`3EXB@mfxkcrkgt6^6)!UmQEbi+&I3WigFmc{>o}y>MfVs9-lIRd8c_fH%G0 z08PfsJrYjNOSq@L8?(5HECk-RICDZC!baOtX~Q@c$9{Lh);sFgLxDI&PXJ#E4edk- zS7!8z0|u}qZs^E`X6V@y@98vPW?jX|MWr7k6}Nsp@^c&gpvG9(7iS-N*bH*GqVkiQ ziog?pveAg_J3HeT(y=*Ybz{s*-chINj3BZLwS>Y(vfFg;1fbr<=o!$9$1l?oW-X6zkC~3`E3hp1)#*fu zlD%D`SXaZhP|}2p?H(y|YPeE&)xMYIi*}^qiA|Q_gC~sj&k;)lMtbM1FFXVcP11B2Q15X=7aHJNEfKf>=!a=#I% z6bAs~IA<8r56$%s7PG8p_qgvs74= z)jPJL5$grtDC@kbM$>K6OS3@!dU1pvAxA=M7W+<=`%~KKKb2Aa*!mm9Oqt*svD}^I=>UH0Eq5*1|_ z+w4q#8fD7WI^f$_WEc(zY(yl>Ex$5(J1OzHrn zd(G|cT`T1v$%Hyp<1fvG!wB{zm5-KGS1wJ%!s8v{5`>T3yNM}fOC<=AP#VWr*T*#C zpnl+hU@E6bm}oJdtck;s#1e6GxJ=+`({ot(Z!9lrc&Eo4$XzzCFLcY-cNWYtjEUio z0*s$^bDHk{XEeO_Q;Z^1GHJ^gi>$_dp|m+iHvAfVbVA!Cvl+R#MmNf`B-i-k zqwc;*MZSUHn}cJ)4)*@99dWq;KDqk^_0v0~d><~%1l|B`aF_t7kHh=mK}!Yu#01K6 zR16AAI>}A~nK-8X=`S7n8pV&T@o!_$*T9uXT^2@InzfIWgfg5?PL5xEuo zr*YxNPf?Vh`Zy!HL_Ys|%-=FB-|R$V#uz)Fgz+C;3SYKZ7@eAVG@O%!Y%3~+>p0ED z(N=#1JMf)#74%{uThst?kVf{U+?=0wWj!CfB}@r8QRFyqG?f6e@--06(cHf$B}Ixs zv4G9bS=pbNAEa&~PP}tETkHpW^%g1g@?^n<&|8WaaB(T)=)`|WQL&94a^ja@=Dn4e z(g=!#UftF7OL7utH}dWeG1Co!8Di-rvO5n;OlSbq!$wPo81CaaGKQ@PFGN$oa0Ki4 z&B1fRlhZDiZl72c`vt&w23p`WS*#%Fh@9{MNxB4GWh2-l?18H&%z>3o$7k|9`GH^? zbTW9}ZJty7p4F9qf+{_jE)P*RxpI5?CEgXM+FNP=7lN$?JIqap?OsB29vt*phAlcM zvITuwNWX3b=@OKn(~BZg1k{z9RXib|u3caSb%a12XU1y!)dTyYIifc)Izrg1XyPnw z)`p!B_YTa6ACkI%w9gC6EZw|g)~OK3dfLi#8sR1;?+KulI_4s*|2X(1)x)nqQq&o* zZ?{;bzXAy|4lDG^^;L3>9IShRTD`xQEVAgiS3H3Bp|x>*r`qqhSFF)bR5H=H`EFS8 zB<6;7Mb_BR%79lg%ZvWY;`%HsqrKec=jw-`uJ)UUSKAe=2d4E~7enYg*~>=Cn^KCk zFJkGZ8H+K-!6gPN&CzGr_LOuovzcj?fs7E`{_jV_4C(Vr%U9ms0qHX%qp$qo01$`ia5vS0(BWnA`F9S48dmmzH>b11~b)x;>!y^&YQr3d8 zi=lw)v3u(@?<+1o=lWzcfx#EY23loi=PWhfF>|x=q1Nk)VrXdZ9!u&^+BGTTNNDIdln~tZJhL zVwL#KTZTCnoSseDct0(pX7%8q4TtbD{A`W?H$~6}sSbQUgV08j1zj8M>0H11uEgo{ zf&QnrgDDGB7eVK8(V2DbskIy;mqlo+l_A=80Fa?VHQ_)hZg2makt9`RpB%fF!sJ%y z!u7cZt;s`C;d8ldj!n~#c)F{rDu8B zkNn1RFzZJw_|8MShC^Yj8b5kCtR$B77ifXV7CykR5E?u#6is@rM=w<;@9B+4v4CfL zcSuf`G4M|B$(X_8&TwE28A^C`WJ|16lbpS=KhVe;GAk0qtO$d`lQfmmn(iF8$*E26 z+@_IO;U0PzYh;;*5dO;$iyHn#kU}t>x)*3PgiG1u6NpStO}6NyA1R}@Hw!$A2C(h1 z%|Jw0%EA;3IPq47Ff!7?O!f;fU&MP89$0{~X2rf%I(nk`E_SIdLC2m-bXeE-ou})B zJxT?5unb9)okB}77Ciiwx!X(MM%H!m=U^?4Q?kE?gRdYJ2Leb zwB}3ssD)+Ci$lWin>h5Mk!)~$dgCSy8Z6U5A+k_E2a&Kk@4ZS?^gaXqxu-%CKK8Rb| zcdX2Chfj#gJ1!&Idk_YaY#9d{!#i*^ZNS~Tw;g!J(CKqqTq-5QoP%$;X)Gz8IKTqV zM(6W4&rTcFIaGrwEc~+R`r4;jSz8vOGjs$ko>$S3Qj!=d!@9VERD=&qx?~~fXP-ON%!^$^Fn{x3 z>(jBL`5(3PIzBE3(wE*SXeYhK(X{A8JPrt%la4=Gx80*7cTiptyA2`n@yOS`yxog~ zy{KH0hfDtOmh46%0gK3?tUbbCJMhoAbfToVZ+FafQ?eI-?J=Wt{Y}md^0OXCQN)ul z6c=K5%+ckbj=HfRt3tFX+DXq4f`Hx8c?oD7=Y(3`kT$;E3SO*L#mu|oZ@4VRh5!;a zzT85x0W)vXveC=~Z8^GoMx<<+iTHXplF?NUgXoz;co)l1ik6J_kmX4nf9{o(+65BC9`Q}Y>!nEl|{2798r@Ke={|3`AmpM znb4Ko;Q=AUnQ!Z4hZXMH3$m5CHPEXQhh?gJq6r`hEk=>p#WE!#V~r&I_;P9UFL9aJ zSFx6djUNk2vdYtg!5GCwqtS&`PWH;=tJ30oPU|V8$L*V)RDtX5xl5XC=0}! z@CK(!&^<$05608-AAf*^auf8t(DkkUI(6EnI@=!Z9O8b&KMW1Cn?0cF?L%)T+^C-F zXda9DL-0`Pn(2&(X1{ar3|Hnj(kjb9zE1R~b<$G;fZc0w4iK!3Eu%VKP~AGc$PoGp z+JwHKli5RJW}V)jfrkNx@>|=S{PpyNtNS)myvaQ1x=G<@eRx9)v<3F~moBrOr-c)k zH4SZ8S_OM9vQ`beJ~z*(@-#w!M}BsytR?Cc3NNXQM0|V2EM|3pvZwkPS4zt9;HKpl zKNAxGFiW4x!?MiEO@jBMCW$#wbg?KEq{p+-1#15*wBkeU1@nT7%SrKM2{`AeIHc06 zT`magKPk(OdmS10A*+^63+ec4Tsaj7_oj$pczm8Tl*$#tRcvPeI}QQ~Yj*or5||zI z9&eb}_6M%9oGmo$P3HIe;oxH-;D@X%Ud_<3ifD%b+UtH0R{^SI91#n6 zXR--vmf(=F{jC`8)bb&PieTR^OfT0+JNZ%Cp7mvdf#avL$D@3bxk9dG*G5kd31#Gh zQ$SBko}+%%nvkH{$zEi`GN5F?lBxe($I=05J@lO+8FI;|(N2c~He>H-9yYrR&pYo?@&{eB30Hp5z+5eR8w+H8 z@42sSH1l)4l|JTYH6wbHx2Keobh5O?-<4-t7s5l5-~>ZCOTUErZg?B#%n;r-ir1Qc zx}IlE0va1>nKb{g9KeFSzii`M?#bS%u$<0^BB6HfB2a#E2~Fkn`xm0Voe*vja4&-7 zAA0CLwqVx;8|kV;{IL7D@>XE$76y{Jj1aQ=>o9(ZRb>(zQ>d@bUWDFBKtvcTyphU? zNksq#(by`wD>Il6>-GGgCp)^CPMPoI(g4bK+?VfdMu&}D5Ua-?Vf`OvjQLeE zS5b;jkl1I)`SPdv^W4{Uj_+aK~m9 z?OI>+aM~&?J6Tg?3#M?@<4bPo`{N>BcvD9>wHoaT+RkX_A`ZE_@+oRN-lN$=qr2@q4ym+4bl8CLGPMky zOk$~46JtSH?=n?rdBvRu7`3hhDEgdHpsr=ZxrdSpyrQ+wSCP^AiObL}Yq0CbCHP$E zqFoN4U(i=ne)o?GO+JjrC)6rhGNB0WeuEqCz0+OEF~hSGViWsZH$_)R{%+eflfai8 zQRH|ZEFyr6N#(qpXriZWbZIuP1zXA8b(%BqW<<3y-)gnLi54mYjCp`@NOwCqa88k> z`E}4P)UlswAciK1CX|U$;ej$CrC>*Z|KJfTJh!&$6{EZ4`}yMZthA|nQZ)C_#}0iO zAURXmcoT|lJN2~N!kK|qNs7a>JjLO8Ep)k*n#XQA(bZ6A$A+hp97WA3T4n8hRYaOY z&pIP}TKOwwD9u|2m@ZU>#{FWeUnAtJhqYd)N#Hfu>cqJpqkEtR)rSXXm3m6h?yd9+ zHtD*}cYH_+EIjW~Cnt1`Hrg=w3%YY(EWR23Xp16PJeHb-md@q(9u{0N79V;|ySib- zS>OBpR)o&-L5dc5nI&I5hZvFzY8p-dQGWgEus|TI@HsgSd`v+U^N8zW)V}(ji37aM z$iuJ87yn3=ubP<{1aC{nCujEqUSd(9?}s)jR!xzPJ(Vao)%xv{L=_#LzQ7kttepoZ z`iq&VV7^8tP@6s7>FQhQ-6#54y3cDHNzykg=;vW(gHfBiuHRajF)p>B8u6J)^-^Fx zy~%PAr9Sxp9=!Q~{wXPMFKe7#AFiTKT%Y$%QgqlPj}z6rNeAIC;{T?oT=<_kyMl6& zG_n)|cj4!$OSD$rf5_(II!=&27fVRFUUEHAEmc@M_yk{iJHdgsP9QylQ-w4a`R%2$ zbelQeizOiy|0F|6nlqRk+{aa~Q076z1A$UdRw9D{Odz_^50@;2YtcBP;F?5+Ni*}? znY*;e18}gFi&&ccS(g57S+zV53>wk6kaqdcAHoTd8I$1pGQ`?Cr$Fv&F>&d|wn5=XLB{%Iw>E)rFT zVp(7XWUvLZUH_6w8ux8=Hq!{ft7KG%`ax+N-_)ifky2eD;5mqfEn{{23Zp948N-xl zb&5zFDp-t0oHAzOj`2<0ab!EpPsR{ep26R@VuiQyCxT_7;MLK zP~COa1b-0F?qx|7UW(99*UgeUJHxWq)ojz+;ePgOSh7I;1VZU(W`ImrZ6j@}oJO~8 zoNBKjTA_q~J#l=v2i^OQ#Y(Oh6DD}xk`i?-Nv0DN1T=a2Q#RhYf9g8W+k91OJb88t zSS}denI~*G7a;sT89Cul6Fc&`gGPn*$csOUKxV;*t36&|iIVvM7O;yxdUa63g-A|w zNJ{N;RMw{CVvfw0@h!&pJ&KS=mF4X^@+3#3YN}7DxQ_BrYk`-tU}O~cdd;<|?JmeK z%h+Y(^kx5Ur0cV7y^p4lY9OydceH#OAl*3zyDqLMXsTEOwfk0%F8VZXclT}T@=b~~ zL6Ll(?e9_jot|~83&|N@4T>N@@BSqS!JC-hxqh%8L=$knPz+w!aq?U|7?yPJ{!|*! zYdk%hod$iHBN%1>p3p6UheWN!-z}rY^;$~gMFL`={-}sA-9MNfiD{fp@J6VJAOjA8 z_7z@){vUN~Q%}Sf_7icOjYV#oBRi|;Ya<#Krmdot5V_cZ94rf%T7OB11C9@VP;-$=O zfX4W})bV;%>a#B*Oxx4^P;E&bgJZ-wyuw+S@QR=kcz$}iKd48wUJ9>89dRY`lA^{d z6)0(v{WEKtnW&f)A1_m9IMr)V>e5an>btrP>`lC1yb{`NekSU5d9_N}0ltP-7@420 z9(sCNM+!%RdYPZzE+0=-<~16MzCk^&97-_Go3CaLX*7By?=o~_u(tGGXaf)Y9`DDo zHyU=GVdL~w81O*LG8l`pRB}9xFXXno%Ys%t0ShS z%#aVm&NbxIDMowqVYf^cm?&R(5Z@Y;XoCKVAdpJB5{t+?)fhos>;7pIsmMUyiG6+$ zxnYBQl`W2a~KH_lgrI8k<#Lp3eT2>tjt#6sV=;0g||JnnLkGT|`8#QJbNj$sZ0We=?b zYgczF8^JXEC6%hp_!WoTz{rPG1vZIGphh@4l&R_V+*7eZL!mqbt{0nZ?3+{F5bHHj zwwHS(e?s;|{B;$*GCF2nlzA2g&b1^RV>J1!SDazI%-ZqIP4e1RJ+`^}Ux%h~t!Q%EL| z6j1{vgb@cx+0$UZsAzE;;M|H}sdR4jbrEWl#2dU47q#(4BNBSJk)Kp%Go%kDJfX984DgCM{`O6N^PnbbTNQ0-q6|sW-1w_x?vh z1p-K+p-6%7&b+-rJnXmPWYY%O*&B^+c4ZQc-tWB17nD&*1Ud;JkO;m<3sq-6G@#&eA@6qkFhk@tL@h}_m&MID{L<$R$K*I@I0$$f(t zyLl4W{l1ND!jo3EJmqwxph10HDsif7PRB{7WLrkwsyH2Hx+hxIG0bh=KQs98f{7(e z{nYvjq5PA8!uNjO8>|q}u?hnG=%k2G@c+C1{2!};3MA~*>Wfnl@qg^4|3lz8*Z2}E z{!#6*-Q)PrUJ8i_Cgs;BV+ZO8-I^{|ZGl5(>qP|{OdDlQ@!!F&{pk~$Xs!|uUce)n z^mG_^YkJtSSQeaD;tH(ucW9+1O7^i#n*1$m3E(_JuOhma>$P!6XC3x zqXc{i-|(Kz+aInv6tPOkx^OlHUI@tiGCN6VmKw=EcG9!qES!Cx029MayjsU6+Lj9~ zEcs?x7s9_09M9Ymi_x$z=eO5I?wa)D5I*c)jV+|1HxX1HW{&+$(RuwczMouSWE}#1 z8RH`GGYLI-pZ+A7QcBqX;Q(>WZFK)iPmxE=t(up-ZpF(t6GXRsVN?)sWd?{Wt9gS! zQ5?aDb2*{un+_(cx+a_T6qKv`=lDtg{KRqJI3~~swMP->@1nN(iK-K*=x3fL3&XY!^h{Lf;K2d7nnBDAXD;Fq&g75Z-k8 z2_h$2BO0M^mP}|9zjw@!8V$+?taA!I8En@k7M{z&q&BpVMJ`xzCR_KTF=Pr>0WY*u zw`9^LgHpk-OvN?DrE3uw^i|CV*m5EGugUY1K`65t3^I4LXD38;jKJMR*5po>*4uGr zBe!Y|59~Pu=7{ThhN~3t+}iT)*!I;Jc>CE}Ei3#KJJOSfOz4M@c?Ewv_h_g77~|Ge zluaQZ7THf>S=@uWET|*n7-D^2B5&PrYI1fuhOpZSE=x-vF1lzLcz&275j<> zGtar4aiyk!zUieK20%rj8lz;AU*b^|eK1*9T~V@F`L{9`T0@Ixu$FQ%3JR3cUw)a+ zhd@YOfq-q)@_wg)=Feoy@TbGvUO$h1IDGayh1?dmI^~Xc_m#+*Spt(CY4TwTD7=Ow zqa5t~*L3G$R+am2T$7^7&iACBLyZ)H9(}VfUE%kd%XFEyIlxr(3r}`X4F1_b*t>;6 z%X;^a9DlA3f7GIs;f(P>5+5yH?8;eSpYAh^#^jr5MldomOwtq{cP)k84>=KV=KCVn zI^grEw#CQ&=>-o-Fjas}I1hJz;11Jvz#Ey{cAsecSvz?GL*XdXZ?~s_`t$$8OC(38 zg1sRgd?lx~jQ2vjze%FZv8krw3BkWpTv!#qQ%kjsTn#E)%1w;|o&-D# z2H<}aT$SW?k2@ZQC|Gwr$%s-y|J%Y^P(}wr$(Cz56@ZW6d8>XEmzosT&t|%k34e zC*CiJMkTQ;x>kgwT|k$^*$P(IHtLAc{a-?2)cTVO8;agjD!ky~f{4Qzcun^c1&h1- z9_XV=aLdc$}+U0;(o;l@hSl8 zs&f4k`y6?36Y2yV8U;s)1_PS+U(uzk&Fi)4oa;ySqQ_=X^Z`go9?|=@*B}#zunl7S zw-BHWRO24|MruWy+_YSyAwr+>UUF22LeTA*C}i8__DI9O3G2v$xw$(PXUzk2$!IUA zo0fE`Rha1ARlnBHHCHwQifPH8eGpn?edb3BnyO*Sr57DMCD?K)`2QLrpE^c)lE zUh`&)RUwR2u>cBA#d#fS!~DHB_`gWMyudC<@E%d;YSIGwPQ^#a$CYQRF?#xR?6T=P z0%a;quj%Z*E#V&W#ZkE*>cczcVW{l7QlseZoDSzvtjvp4(pzo4RWew{KIhSX4%_yI z6Py$0uH)aELZ)UIYi{oo0bgb+ZqqL`7mk^tS47|nSx49j)Oqsl7>mHNH zw|A@G8LW0t3vs&rdU0B2HDDkq(>Aj^_!-sUn2A!#3&mn#T-pD7ZPEgkzQ9Pi*Ykgu zF?1}vTuW^pNInR{f3c+Nz6@j|Bp@Iy_Ef_{5JJF|j-AU!bINzML7)2l^c%}OS*jGo*3qViaMn(StHBVD8CVw>(OrE;Wps#*2t z?@mBxN8(WSPg(O7F8zveePK~@C#~moYS%w?>-`vC9aU!gkS9JwUcGbFS!rf#_D{CP z7>zuEXnb;0PUYdjbVqCXM29vNI-@7ABZtwe?|{&Q^N`K{+^6S1rtl79ph`*BBD?eI^i+;jhNED;d+ zmX8x=S#P6|S><)0S39SqpYWb?%Rh85{sHT%3Ud2?TZk1PPu(%l`zH1J_&z>ILAOeop=%iq}Lleal$G`~sQOKR+&j)cu6OMJuwA5g0 z^&)MjQ+~~0{_2XoG|rcl88`>0PPEbU_ z9Kj(Ehw^dr@$#G6?XF9Qlc5^7H|k)1Uj!kpv~0P2>!x!-K^ZWar&g+zE;L=XOiGs&Yxy=hbW4xSoIIlfiTzR8riMoteNi6t$s3pG_vzmZe7EC%DVTvGs|ClKhsKw4|Ey-U1qEh6m=Uu@Z+a-zFM-3wqAisi8F;AXB} zJvbdc9Y>LPhur4io zi19?7#2xN;3)cNaLbKFhEfQI$`bkPzLz+mF zDU4fH=D9kss}O_{eJ?z3R(sg?KA;PL>{jH@$`_=r}rH z;Oo?r=b&`rwfzV$T+p>}Ep01{a)?J2v|PB=cFLR;3l{>{d132vAgr{>!ft9YA5UcP zFyW&aiDc+>HECkNI@t|w+i!?J%jC5x7p`lmM4>d}*ADQGGb>oPvm-K!$gB^Tz#gHv zM4A0?f+ZZ{pc-BmlpV<9(j$?S#MgNty*P=)`wJU8%_`zDR3VM_5P-#vQ8{Y%%#Ez8 za{qETDjkQo3jw1vdT3}2_YMgU~p7{(xkJPdv6uF#~KIeS}YNa~={Xf3o}v z>J9N{Q5QghS`XkN?Y<7mBn+pIqLtCs@}O{+tRWSXwHRbL#yP-lS#6Ow4~trU&nObp ztYbwhV56k2prqPE*qEYLC%Ly%pA9bkU|wu1FQ8JDsV2h8IoaUWtg|A4;_jI-@m+>? zeyk>h8^UozxoiuM1Q*TMA`Jjij^uOhBD^r+nu1tjue=BM!Jg~c1Dkl#K0$xDDddPti5&h;$BB60(? zRiQzl#CC9ljmpkMSjH~+RD1(X0ek)!nKZ90DS@)ptWeA=?Q^VctsJ5?1I-LU=L0r| ziCv%1kDoJ?xC=qNA(Au3*K(`}FPmM-bu`_O+6I+`Uwx;Pn24<*3h{LO=!oo``eBSJ zqC4g#?Dyw*EKEataVN5iK(v!^!2?M^wML!u}L+oFs@`~E2VfJzB`ZKdd zvT0+dHx6pu(%IXf>WWfxc*RP+hQ^DVE#$@dm2c34DS1hNSby>xRyBHyZUEA^FGmwv zyhP_y4SyFhBIdg3%YBh2q1X0pa17xWS(Kdyi`U|C@{S!J_y|bM{W|$*UF!Fj%cET2 zPw(h1pbJ_wM!@iy?w?2wPWot3tigY^gw5=jO8c8mkxI#>VhB z8?+QZ_6k|ZH~#R|2*gXX3ukwJo>zj}HCyALei0=9B6srr4AgPmCI*OgD8TZFR9-m8c6+?#9z0o8;>YnemOI4Z#}(n;ap!NIO@B$v4_bsh z=51ZEA^f=V^UR06T23_n#H{#o(7pz{?GlTB@>G+*381ol_|3Q700?4=a**jka}`E^ zF&CXlDjCK0C!Muw&I0(FOfIb0K)5z}YiBto4_sldv|Ei}cNuir>jxGg_C8O`K)NSz zx*`@ZIQ7yM20zmbGlkIi$<0Gs4M1s_lt`RiO>t=jUfi$LuP@Td^+%^&#OP6z)W4WR z6X&dABImT8^^moTe}Od0lJ?362xd_q?936Nqc$x(gF=aR5Tv5SlDb_j51qABf{lY0A#s5oDJnBm1q%TLSf zI$;|8#*|Lxvn#@dSs5kDgw#A@wx@*{i%EqD5obwD{l1ho^{JSu+Ai73v6+|<4XMGj z(9>h<#y(n#7OjQNQ>+`85^riyJl9_X&gq|B9sFn=H2@oZB9z5pe_P(!r6N|9KrOy+ zsW1!|iOKLcq5JPZF$3_cCQuDUcL*~CXS^bHmv0QA3{LHi2RE`Dn4=h89BNm+W21sC z)n)k&hBx&m%c89hG3h_#F z#rOGaJWriY&{E1vI64bHa3>_0lM_x(*QfUiigw%);^~)9n{AEARWsbb;vR|Rt`dRY zoB(#_RGrM>@Y#Muty=`Yg`ElUn9oTcS}Twu6Q(A$0VFN*K#}$4VNHz!#x~4<6jA0( z1h36e*_wCzc+L6h703j+(@a;Yz*&cRL5I{n;(awa#}$hPIX&yWnK(=xmjX$(U+_Eu zuz^?-@$T0L&VtdyFfQ+E{Nd|N76*QRnE}#P%@y|3v?BALF%#E|soQMmYGj0%Wc7wG zA4L}wU54tDd4u{~5lX$M@LMY`Bb8b7&ib3IVlDWx31ciS3D)5406EHAK5G!XZC2w) zB*&Eu6I|n<_E0!G1Jn|=YfV}U&Fp9fabyl2t_{0cTmI4>o|EwWxzO)T^9s`uVSqsF zo8ucnAE^9G-RfNd=sse9Z$~?Fu;-eOn1^WGM}v8nC2~rJNZe4}B}iM3QvPaXK*gyY zn}u*momidpLP$aRFc@KgR(f$3P6%4sS|!~jABEv&Pu9P#nZ4labx~79bT8{_YbSR` zQMXAK?etca<9hn7_jXLfzXFnOz5p*fAO4I3Ed)v~hSU)RA1ARv7{_d4_B0s7|nKC2zuSQ7iT@hfAdQj5w z>;x?y)lcQc&81RR-#=2d-wrj-(sD-qLm*ZN2XQfq#Y{AEzEzYa$QvkYn=?+Bj-tyc z2G0-~IpRk%!l%!|MC5b+K!D4uOQhJv&!tJ-^sU>f`%g41#X@x*e;Bf^Bo8?|5>*{9 z_x$s6R{Pq^?fc6ehUZ0#zZa3rs@Le;$~|rm!=xq-)-`FYxR)A_TcP>!`7ittvMMo)37M};@9=tWuw(Gwj8V)i$2=2U(ae2~4=lNUvN#`%|MyjqhC(SP zr`|N&g$xALBan(5{|{Rm-UNaQ*ld1!`Jm;340WB*(pm=wjpDJnD72~NpigKVh{KMM z-+ya86%8r$?S^>UdD$kVRx+@lykP3P-I6*y`1mHuk(Zb6o+-~i%rG+>^Y8K<+Q+SK zj6f8eQUNTH7&$9-d{c(2})Taiem%0Y5&a#27WAWBe zEDxKfP6vrm+^)4EeXM%{Kv&@{;4%RAzOnQicL?F|Zql4)v_xQM8e@Dr5CD8zc)xu$ zO!Sm60=(|_-y(Z}9XL^2W}rEP*28X956y@CNyZzThx9q!#;|>QY2NsGEq1=%6kgQO z_o7F+^2GP{5}xX36{|IaE@}7Ic1|{$GrmQO8H_l8IsDB$dJ9q%4;h@XQ2V>oPR;t; zI!fBN*ye9!^l17%XHessBn6EfkXW1qb)b-sQ8Qfy0$1Q}>xu085=zIoOQ%ktVEQIg z1A2y5JLNATZA845SIk^dE(I*z_WSl0HG*;T3{TLbbops?w`Xi+Oh*hPl&| zm{t+h-$pgX{9Jn>x+vL7l3IVK_u(2^gy=-FscButrg74l270)U=OjSDV$?teHpf_j zt7HHwl}gCViDc`ll`W)j70dd*g@{$b#Z@06X5c10%7sP3#!j3biKn;bx)&>FFc2V ziy6XIL;!uI7ppE3)<2VU=Z#(W{dwsClS*z%k;S)FyOGu7WzcLr<08ST!z zflr8NH}Uptz%0m75N>d!1Y7PZvW^t15EJl!zVRse-aRdoe;VA#2a?aXuoBToEWXBLYtYW-Wp};g=Gign_v^16a$0R5BZLx|&SFse*-=#`x)k&SseHsh z1s2&X^t0At^D%$j+R`F{%}HlYc8y*mAO#%&_4Ru^`qTZvg9umV2*D@(SOy`6K;&aLvf$Js4>&HuX5?Aue*N8HIcW}JO`P~)AKcR$tj&+AS$%`=kV z2!ia1G4lgi)?69aEXspS8Dkh4U?{zJRo%0U`=N*u7=Yn~G{FXnoapNCg#P5U!>!H& ze4d9DxTgl*GN1eZSbgDy)$UAbm@^#T-iGvLal$@F1M5Ay@mI3`gAr1oQs zc9B@4s5~qfjDF#I?oIP>7}CL;vke;qYELEWE(B+#t5KK934q1tNGsO~u-~8v1VA=M zcgBWAC!{8+s1B(is(d1WXI)fK!rJ8djPJlGi<2LzA*XLd!IMWZPJb<-At@SF<;N5w z8hVL)s#eM)j&NflBjB_nE?!Fk^RA)n#^9jrg8PvbZT_C36If!Q5D8(8k&+t#u(X)m zRgQZJwX?YtVqYa88F5+>48)Pz-;RRo5HQ%nqaI2Nfh<)#zDp&UP#;!^cEUq?;ggu> z{9sBoot7mLd=WV0_lu^4GNnNQ19;&+bbM6Fh7c?bnFpLgj_bM%t^JcDUY7#K`!Iw6 z-od-XEj;g~S;uU>srmb1Ti)O*MM3Z6r!}D?gpycuiJUhwj#oBxT~v zO(Mg|w=Z@|gc()1^x4AP|oN%vdhzk zpRmngN7fQ$sGX^n z`Y$Ad`l<&0eE}O?b0I;eWBba2UKu$*7Y4Xm7`k#2!Z;nq6sVR&S3GXiaC{Nacf>xo z=EAhry37c-I>s16D!ko*TOH@f7ipZobDA2j-W0~t0UonaLc6a`yX)Z*L`_7zkU6(t ztI7nq&+8gRlQ0<#$mEbN;z`7uL?WokTTp^ZfNHB;#@Ztz7>-PHc*j9-rS=YI2CvZl zoHBWQq|b>7LXxfN5kCTSQx)GEf`7{bPdRjhwv+`)$!@~^v@`+BgM}z7y(`WEQMjn< zY2@d=I4&QxX6#3Pz1P}z(XH@`UeQW$-|p#xPH*%v8dL3Zs4|#dWSdI)z3_Zi4U}Yc ziCz*kU}Z4)1cRlxX^OSD@yM$UtcEGk4Wsi7tWnlJWiU5rAeM0?ztFaQyL$7cg6%6GdCv!h(A_FJDBrts3 z!uil?kD)agV&5Cwi=UPbb3b6I-r2Qqezb3m2 z_~SB=BiOArFpYF2H2V=+F%YrG@Mj7p=n7RW;bGv&8`=c$$YfoiQSth<7{57KqsblT z5iY^~Hbz_KsJ2-y9z7#?BBKhTQPUp;&5Nzz(^ZrWGmD<}gswT47-kS?j+;JlKlWB2 zVbC{8Sy5J|N`IDlzW2{(Bz}!RRW9LpG8Y@>aQ+V5)7_oxKcfBkVGvZBZ za?OhS;P?(OE|7$a(y1Gn;Ee4sUXlSlN>et*KD-uD;JM8UH2rBOwrm&mJE*+^OcQ%EyPM49w49n2zGEN`2zK#@#2 zT^vX24DZw(5!(^Lsj(1~m-9095t7Q6Ncll<UihQB5mirK(31>>sata#y0d(vf_9&2pRp3P9%IOIl$hz(gkZC49c$^^Lp5)! zh?lhp|3IJ&YeIg4HWl*Ke}e;spEy<=CN~5)wrmif_BuvJ+Nhk0y^*Gq?c1>S3sW(< zPD1xC)0YZW8y@bCZX|l}>k-J;e_dbV(I)wRaDV!WvFbF|L3w>(5O?~?@RBI29*%8y zgVTF|JbMCv^bl8UpZXNlx64(tco{Rva1s&WFT zh^DEcQ3G~N&0^2{+>b;B*B!WvE+vzxLLr+mI7oYWa zCP=Yg>bXv1)yX3!UccfH3yySS5)=Vsh%O?sJ74l4SJx4clLL{*?*5*`rSD@se7EOA zt}A_pKKh@HWR`ZPYM6~wrJf^|jb_Ve3ES!_nbo0DwF5o{Um#uK*g;qnAm8WNdQpG( z(X;1;mdnhm4PsaV?Lu|ZV4!mkiTRf%(i`Ac0+eLdD;0>qQt_0##_EiCbI1WM-gwGv z-c0=D&>d0~n~}-BR9)Z4*I)&;q1nf%cM-k}+5)u~s)T&kZH#4}Pg-0842lzHLM9kZ zyL!28vFy9-{4tLjqh+T{yhG2kaaQSTqRYS%g)dJUeQ-8uw`1G1S zOiObT^J~x6$s}&}U;PSK8hQZf3Al_@PaaKuq{&pvGSX7&bQm&|%6a+WFEUC8C*D$5 zRkrG7`{D1uz`r+CHsmy`x4i;>9iJ{NXXl)&JLlm#`kAILy_kZq&X?>&K0NsH4%2(` z8%n_*V?mN^rUDadB>nPGf)gQ#!xim{cbNmxX8YWbzK4Hop=B^B~0p*Q6KGL z(GAPyso(iLvp(wK?>-OfL)Zn6thYq^LRbwTk@bCk9j)|pRaMI`={%gC1J)Q>W`fFD z^yWiu@efn{HR#LNi)Un93V!W=wTD`|X$7~_Z~G7aeV&A79Qvr%amaksWcR!%b~F0i z;O~LJXQ)7)ah4*jzvB!z)r4sGBau(gazD2cON;p(PhYwYWZA}cKTkZUo`ib5J#r@OuJ?{4OMnPywOALp!8Q??hZ1iW%WiLc<%Huy=S4dNsGt zC+>N=v4Tqkk5d+jS9fWS&kmdE?mU1|9_;?w-%r@iZgH9Tb)Xzz0-LIqb?_%9KJYgl z;l0;$3goe&(c#Uyg`-D2Tld4$z8>SZAC$6F+~7!!z^h$yY@^*ba3}4uU|}xd41eoE z`QkOH9he58KuhPtpU)Bwt-O9g6ft;J3H1HHT%JJ!*zrP2TWTBX9M?=M7^?*57MKI& zWuG#P-LVcDmAA=&Sif>PVqBLyZFZ!G2R|bnbczR3r0l0C?xZ11Wcpu;(rru1j&N_t z;qIx+O@plz(C};aLrZfAe~RlFhiCWleNM&%9!H9_fdmkk>}%@Vk0Zk>9!rG7d*J$tK#vSy+IahhN#6KvUa1?dm`X)U9o6LFLx-icgKmHYP4qH;3 z@u)#J3C_*n-D`Hzq@8lcVxOs-C!V$Ax9ut);Jb`n{@X>ZldgSJ@P?BCf15V0i@MUMKvyywkxTvMi51X!e+!Nx)YsuZ%uNpezUSuj{kG#3h)F3`JkHgA zsYKOG(V;(Fd(m!|C*~6u`(Uq)Ad;J^(@U$-&|Y8IO?b_t@@g0A>8dQuQ_DQWIs5pFk6%!4Ob)cz_0;y~lp9mp z0wI$~NO#gKEYT}ZAvk-6w|JF7w>I$rT+_-F^ zQ?ae8r@3(|nt_jeR%-wLAKU1E_7nuF8e5Ei@FO(@ARyfTkGM+Z9R(o=bjh{|Dj6yf zt~c_5^MP40h6*{7j~i={peNju_VBYNQ7JV?RWhWEdig(0#W6(NLz$SJ@Q`AW)>}0> z1@~y`dC1p(^Gbz2Y2UmkUk#KrODX4vs5d9!2h%j>ssFVsKydAzMJ(rd3*P+$M%uP;+*t?_6Lbma*DPC-sLGn# zMQBa{3q%XG1<7}1+@$PDVJ`LrZPFx{N?6&{zK8r7ZW}ueRiEJpNF{-@o=tEjB4}mS zijRnqYEOwP4XEiq;d0afLBme)nZJ7K*!(;wa<2^EaQJHKMAsaV9T-@o5S-V7K)(Tr zK}RJ@^9-}lo;ycJt$r3HYbL&IUebSd0{Hef;tFFMZGf`~BG`qx(DA2UdGya?%5O$f zrG@$E=F0g|$wi3)Fv`{<>kSo+Bt2iUfTAAJ`*1H4PCBP# ztk*Lsb8>gEy)Ou|K%hMv;>yHvTs(Tlb+KC~U(YI{KkBuCz&5P!6Kyyo6!Y=AxR)dE zcn3A~L)Va_|K2M)l4BzKkiCtWQ5_Ozx6UfmyO-ewGWEt+uJ1PKfiVMw0WS z{v&jieXd1~-u&1lzP4CSDS37#Hu=(PD(l5&Y!x#fQ)N*yK^*dA>lR zv97Kb&2yj3YQ_$uZlt#yhd~j60XFr8Z#0E%v~Cdq(X(Az*lcR7!2-TltL#Y2Jj`+n z0TNq#=J34PThJMl9xU5iXC`9xisKW@_P0sYQZ*Y}vQep6+izfh|hsEw7-!D}J2-efSepi#HrVRmu^J0%03@mv55ms_{{JIG;!2UMEiRC=^-t`btf zBSx@QRqX73g;tBO2){wS4U~!PveuvbX(IMI5~os=!0H3^4?dgdZ$bvBy_jeyMcomH zsL@0gzhLf<#`W*Uj^K~w98`rGH@t=SaXmJNz7sXkNxjD0vZ4x1eJ9RTo)+_=TcrspOPLCo7ctNp<~bh-G$b&wchNAhb1o2ph~ zatB|bpN}axsXyM8SNs@4bV>tzj@zt<(iQX*^=c}d+NRiv8`<;h2QmfY#Te;+0zA$K zMcOrHP0uysg}nL>pA{Gq611YNi5+Ym=xTXvK!==olz^fZVcasBp5Yi9QY_AAVi$uE zsHo2*`=u%-tAYt-28o9&NAa83oa&(w@iZR6UGaXt(Q=ITeKQ*VBV!Fvzu}pmznC*i z?h_TpFx_QlR`a@cfdc-adpdOqMO<(_$rLZMA#5E9J7%N1*cArUSj$RI5BC?J@UCzrPhj$+|pwxMLO9jjAQGbr^PUw zgt3kJGP&~L`x+mC3=Znga(#>?kmkk6yt`s#_V}lxe!29jQ=)^QDTKI*_XuHL##~NG zX8U%?%y17@!(A*em$ecbsVwx@Pw-bEIF;|zd9-0PG7pQaYKw9Oj9SQ+GyPjV7>eXQ z8Q?K_w%5No^$9}FXpd>`J@O3?W1UUr@Wa=m<-i3fUB;wW^w`3}AP0p_Qf)C^2g(Dp z%lnJp=kA?eIU=^F)9WMW@@pe9aufw7XkSjtLbpaJ*&$vo6>~;kRN|YKi&SfjXTq3t zdO(2MByH ze~WCTX;LP>x-U+w{L$M!M{%QbfM=|VA~)^CV(0TBr=&zGQlUC-Q0!w{%4e8HDU~LN z*`|M2_i+pEb!LSOr5>3j0*fGl0HW7AzHoOCPMRu4@>B{y9t7?#rEd;_<|)Dx3b@dt zmzP!=dQD3yUUtTmc%YK1mUy78lPLXbza92-My9$GmOu0ZT9;3cggkawi3V4E$gTMl zhFHoXXe4=MIqeCCQJ>|CKoJwR>G6RJO@vK)K+6tO=avR`3QdSovx*#N`iOm^7T9!F1T^@_#USUYIb*hBV_x57#CVaF%y1 zX)mka3|)DpaV8`+j9n}BGd~w*e|nSA$C+algG|f7f!kP@t9|eFY$xAZ0HABjB7XBU z-OE(V^9~@_o)gO|p?Tu$!sf>*bwsv11{Ho(HEBCIL zBM(I)UGT_BUeS6)a|aTd2&foZSs7EL_4dljVN+$EqJ?WO)X6=;^FkRtdVOv6^S7BJ zX}A|ppRuA3KJwhKX#;eX0)P#O!WeN z1gL8F!4Q4!*1 z=@<6Ox87Sqw{1GMsnrTt@_}Z@Ew@}Bd%)I|rlQ#F?>Dkf22|hH%Y#a4dNETNt#=ZO z{Zq*kFcbfvs>ys*YiGRNBMVkjI4a4awxaxw z5NA#P{lIw!rR<_w6jRM*P2&iZOSXI5l@uNd{_z>|%_kk`q`>EzLR2-SD2-Z7arg+dW>l{MWehlP1R_s7Kbeu*O_b2{9BRNiIOO8_CX5yg|J6- zvulg4`r9M}cE^6F^*BQN8v><~fuQMZ>!^V>l^NcY#YJB%5dzdjUGrn>Kpg}Jv-Z|< z&Z@;I60m4!e=fZe*AfW%q;GQgmv_YX5mI!WftM)gU8tAW+5j&jk%!$G9(og|ay35U z&n1xolq<0yn)*5;8ge8Cgl;fPzOagTiRd33E@>qC!iH1mG$kEi2za14d*w$cCgNZJ z&=bzmEI~wxp|bU3B0XITh)%B!(M5~#Y%yyii~v)i(%Qlc2}%sVKlGSTNK+VPc5aL1 z8s5L2uYu+XFDKAffa7XW>iiAUZZ~JHR%j=GtZx2+xSv6rTQGZzbewBwl?M2MU^)$` zU7&!3qB;c<+afGk$ms}4>&@tNMbOKWs~{lFPPop=ftP0Tnl&T+P2I~#uo`OuX6=m# zMFBxn5Z%_MqS?UN5{!)70zH#dkO-tl2T^9H58_!8sgUBv$;^pj6#N{Wm)v}fr5~tt zk_AjVXKIXr-mLvry5yd;zQ^~RWMbh^_;?iHx#MB1Bqc>)JE+&F&;FojcRJ){>C39g zqankl&@B#+5L9kZILQ|C-SOKD- zeGYi9m-0KRou354cz~E;Pqo`Id6aT&nYrXmgF*e?-0$F2PWF6qShP_~+cP ztb4I??J@THK@7GsGhX*=Jqo5GU4UH44^|Js2o&tCruZ)-#xi1?#Nw=bG=K+%Ij)xL zuOl9;u3uZYDyygRt35N2b~C4RUmSe+6kZCOL7HI3Thoz2?R{9Lwc}k4QY;jQFP!K8}y>Wrtd^N(D0?XtxkN4untd5f1bAvu4K zk(u2;aH}JGG=M>Un#P|_ssL!{5Y4U*1xw^nKYky-6{4=v126Lb(1i74tU@z)8Kf!W z8kftkkKXah2yg=j$v0|>lm)=kS-ca@KUN@`zWydS0^PbOt1Ka%;CsqY7D9!Mc$&1U z3xQYAQdjk!^U(4N=;lzV7VWMuFoWO3&g5awCNl(US`6B0EO@SE%mSRniW>f@Xt)S~ zCQ}Z$dASSo+X&QOJr89m7CZGRb#m%(B&*Y!Y6=$=g}%1brg%0+#?(2UcQ^HuD~I;1AmDiBj%I`{eFRGueZ3Q zm`iZgAVYjC&f@Rb71z27hZD~N$R%ezT9;qA!u%oyzo6w|YIuSXDP;dhmkhGv%NFBq z_2J;b0{h6J{j?V#zKrb^6WQpums>vrEwJgire!qdjrHTe( zDCr)v=}4eYw5M%mnq%9BbKT00l!lX~80RrNXiAAO-)$qpMK3FEc9_PcuQoL^XS(KJ zD#Q#mtc#KLm1Y2_2Mzs_zU8lSXc7#~edA3GvPsu1+Wb!Ql53Z{u38ofp~{stdD=^t zk8^y^?~w!wgw%kB*-6&3tw2bTn$qdcxJzNEnH@wQAuN zzR_wlTZ#aX6ICpl4}1r5y}w6;X}|G@p|Azd87uDOxa|Y%*b6%BB9ST~m$vWDt0UvJ zTs_E~;!U~2P%^N$LMPolpMChd3E0a}3NAcR!CJ)vgHOAIE*KM;<5dul5p4Eq3Aoct z;FV(_h1qGEM7SfCQ)&mumx=al|A=gB1=+=fyetAPQMpneRPWUr&8!ed@@$g`dJ23x zJ97Pn+-wvpWh1!5eoS5XrM*$C*pK9A7!* zr3jhN@;adVimAKZ+zlDwT{R9V5zk@jY?tqxwu{+AfH)hHpY<^hnH3)d%gEWxUghB+ zS#Sj2@qIknn>~(^D0`0T2Qz0z0y|6GcM<4ghztXhYslT16k!tz{x`M$-w<6kV4 z4<;N7pE@W1&waMB1%eDvm-)vMM(V!MK!N}n)0D8R0ru4_)Ono6jLXLyAZkS+cM^%$ zPN+vk`?|@_6OC-lwr$=x|L0bDn(}2eHE~s-vJ>aTk*7xf%8e$yELd`O&63~I;+QD1 z*U4MIEwf8uKQ%%UkwVm6T2E5{mE6Veh?}LR&7O~+R<}9$F3b(EM@uxTij}rjhx{Gb z7Q-VaL0VH5D=(?@+^^o3i{T!3nV!EF`gj??AYxXwmm^{1Ig{+Om3r_cXk!%ABe44c zSzDRKF|#t+>ofb6h)dhpzA}zY&k5#lhQ0g;w;mpxR_EIPxjsmF$eZekXQE!3#b%6g zQ?&qD7Ne}@NlzTGE97>Y7k=Z&(me{&-wC&PzFDh1C(JdVfvBcKUzs~Q^-;Mn&9m~)_D?)qEtM-ge zN$_0;0PO;h_%6DkTq<7TdGE7}cAMr(-&V(of$Ic1D3!z%D~cqh02qAGCJKML2aFx( z4|b%l_s(zV6piGW+rPhO&6o*Vd<=;#t^6$m@=v9F_qo6BB=|dD6O1@r9QxLnx~#dY zyVTXi$W*hSAH3N3q{k>=l@~F#44Ff@g;-Q}52X&Mjnc4r>&5ZE0q^k<3LZ*7Njgq6 zvf`?Uq)LBcC!f%ZHwp4r0n+4<=0yLs^kPy1S#6wZ=sfw=E4R~#oUo%OJArp$8GImC z*e1HGfKG@mo3dOLBMNO&1L{7$Y2?S?NK@-z;!+*On{f$y`KXkqG9e_p2CDTT8Xi7WX=}@fxJX zIl698C&XtcD92@kkPijy!*nuq>LTw}_e}s4W_?Ax46}Os<#{m>$)WMLzQGB;zmM-H z1Ew3=V&1h z5}O}!_^b#Xnqe>99iLI24JMrzNB+`~Uqk)+&&Mq2+s&>_@2Ix>j<{m~i0HfaaSA2cjD8tpd&5W1*98+H-iCJ(#elb$Yn5mKX)nWO&KEYZ; z200_#$0k$d7JsTn2?fHN5`Tre35BH)F zLC`=zpZGvPg#RfZsa(+@@ToC6XvlyjEjx$Jf4x}M212V$WZ53cSYmU-;VzcH@sNmC z5LceHd$(a42e+20$gbm)R=!{SLeZYO`CG)If#OT|CLQ&2_Uw}@H8bpS7pUTkD@$XP zv4;u&xm-z=UkJdiys14p^0(hK%Dxg&glft4NA}YS#q5I1z0y@#FpK2J^Z5au%R9H7 zqU&ivRM|iZx{Gb4auG`pI_1I^fB9jszVC$zWxf*#+SY0`hY(5p#$C$?Yvl4o#qe;| zs?*A&P>hEJ_0p0!&2tix8ZnBK)@Z_0gM$)NpBoh0xFZ=uZk>p0^j97ykzt8$5pZZ&MLekUYpP4b&(VEQWoj@aFvLm&rXk#D$ z*b3&45mxbbDEvPFUO=J0R;L7u?SFac&-pQ-2#7+b7vXpHpG> zgVc-$2d2Mbi^7ml@+IQA&_+iKmhpd=gMeYV6uJ&kW{QI#C9LBaJkKOZ7_XUSNEK+# z2XQ1adxG_PD^(`gws=OIn0=vF>=8^(Tr*jhuza4294D|xze#>ST>eyv`%f993yAPpLLJj(_(9FSQs% z?pBy=k2-Z~LyrPyH4BeX5I?1DS+p5H(zN{$#fy7Q>t-w5W5}PG2c&6n(lumAk<%PmS^S%2Ef!cI~h*l90n z#@Uf)2fh<*k3zF1ZdBB%i+w-ibP$w?5SsiVi#i&LO)MUX@GZW-UEgeCprR9c?YIg7 zSBbfTj_qp}vJ`jLPYIsqEZTktQ+q`&k!d&a{rgQYq4|rf#W)%~>Ugy!cF#XKHe{uW zKNnR~G0(up35Sulz<(v0HHZ_uvt98d`rf$6^b%?ramx&FAJ`Cr(~xsCQUWcu(QJc= z%GC4BeK3kvf(R7Y3Pssz1J9zvop^aT*Vd)6FCC3Z~2xpk8#)XsFU8nt#Bf5IWt``F;1ck?Br9 z+=;T=l85n9{!N;H&w8=_w+V%A*OWOs(aBUj&zCN3r-$pBYY7i}K$KD}654H1kv&Bm zOtqy|N(S%5xqgnKm4hM~z6-6^nm-8}w@Tu~_%_MS))ehN1X2H%Xv3AEHnDeV{f_}* zPVA&nJd2Y+2cd+`RD87C+Ue{!1`n;D0(A*!%Tbpk&VKZB)+NtEat=`U1x9{HJE1>%@o<06qk(E_SPM{j_ia};N z+8Jr!{C`P`hE8-iNmEK|H^p9us0+gi&^OSjYQ44WrNm_H^Z~VEK9&YD#j{bo!*iRF z!tK5ZeCjt`69Vi5Hta=>_;{(m#mCcyy`r00*!0_GA#xrYT(Yk<@nFmcfSYg@x^YZRfGj=mmAQvKIsx&=y#ciEVaIjoKf^PM!n; zKz}zcSM+!B*w@IJw*iG^Wd#Pk& zW$!Utr?QRNV1a)a2E)@tv^;7Ge+*+b>F9p@i0;E1>2BW7a=%rjgaM<9A0us)8^|y# z3m^u^!%b)p^~3Y~?4bseaUABNw1fyK{38P)m>5u(&sv;hp|ANZzZ=6(1fOj`h<~mq zzyGj_UB=nThP0)^0!QXC`@}w2TtrlK=`b7~EjpfA;N$ntRXOdlz&{y9;^b02(SoaN zZ{4yug4lfvqb)B0=YQs9BW&bH;h%Y4+PZ-q29<(1-m)tdvMV;{?u=uZCp#sZV{{YK zdTZ7G4i&KGtl_F|t219k<{SJDkbl@3iS%{Hn_F)>_Zzh^#V=&Sj0Ohv1Jm%LXR-R- zhXhFNmD`#eHMr1RE|;_G%eRzFXW*sZDZI_r%@Tfh|emv3k8yw3fc7?I{J;Gc>aj7fz~-4A zMWY?+rgH78&1#L#MiZtjM>4|!wpG+7T@VD&72R@&V~%E`IQTbEO9KQH0000809K6^ zO{>5lC?5s@0F)8{02crNm&{uf7=Nu-U2oeq6n)pPAe4vMovXAPx&ZXzAKwLx~zm#r2B*_nk{hwq-kA6)X>lP4a&5+;h)m(lkw4)n@rUHKnmaIkCc@ z_)RryQBsS~)D()GFe`z>!W+?A!Wl0bqLPor;f$TPnR<60yuwMh-mg7mAoh5w(OcxBR$jEF^c^)q;>}0 z5CArS%87faJL2mA1aCXa#GkypQCj1>TCd6CAh0M)<#Ao9qcu>5BiI$Pb0h-nPH1&U zB6aFh+PjqZQt1e$3(zOmH?RKs?fUJ_wRkCBBOl`Hz1j*Q-IeULUkGi?9hdX$0#JWC zszw0dnwCm7fj+MZJd;R~Vc#fM1;}9P88cE=z?XPe5$V_kCzZo_sY(WJl%0;*Fs`_OMo&-xXcc0Xc1L*`5Q)Zk^dZ3MDTVfuT!v8B4FY(1M@{G+ zc&WT^-PPsgTKTG5W`(IQvD=`ZEh+!crKP_+a^79Goz|B>y!h$o44uE)g`LF=`NH$7 zMBr!G$$1ShrJtXD$v!{-l9wdz0xCoKY#!|CQ$ej4Z-RpxYmMFe9R)cGw9n{UqWo7R z{<#qEAakJQ$Id}kz=*~}(?9{U8OXmvvqG>!nOo@`$YG%fZ&sI)?gAGjZf|>^2YQR1 z1@EDox3@>$I54Oa1lOSH%f0>HCKG?Cra+t1cbCoX0zC&r7QO?x+b5S1?*beFdzUWn z0xvTCs53sG-3~YRZ2mBEu#^t`u1J}u>W-!CR zuBh&(OYbgraF6H?kYpepe|vw$Ok;h__}6aoeS{#*c3~GHeZmpb`CNRzvrUe(j?&QM zJF4R0JkCb5WtJAQs0g5WYY^ag(`ZcpTAplh6~K+N>(-nsSH9LS&Yj0RxMLhoHuwp4 ze`XDB0l|29C+n;}7w7l@5VY$Ee?$$Zx6RK03 zxkhWv8oOsUw%*jI<*|ejd@kGJvGL$W7PCE*!^w#ru^+$vWR`2V?t)<^x<2~oX%_h_b;z-SDvc>kC!YRO?Z*=OITBlF(fAvnweG025WYLRlhUI z!nNSk6aYG}rVy8pKdz~R<@77{W{zOf)F+v(}KH%x1h!0zns?Ck99>^vR>(|k0aB*E-v78hljo%d!p zYY)~Q1Uvccrby2(svsP8f{pd{r`?V9{?|e9E}l<<<6iK8X87GaEfOmHE-9vIS*Cdw zq-AiC6v^35a9+e&m5icbTqH@5kAvYwT%0FSP~}0K-2}6wD4{}rR>f%sEd!i57(%mH zwz>d7Wj?O1<066LqaZHJe3-@nF&O2;`83I@xWX34=_DzGu)2W01g#@cr`4f`MoByg z(hT4wfqWHzT&LAVKCglzDXStKB9sUU4JY#v_d^z#q|;Qif&d5~C4!xoFb?c%ga}N> z_&1@!&E{v5w7iG_$|yzfXY&dkm-u*?WLOVI^CT~VGMP*eMhd;B5$hgO8E6N9%n-Ge zKo+%qeUVS?@c^pE^CE+0lMxL%2h>rUza+zo;b4V-aXy*k*DyqAHXEflu5yzm@EG34 zXZck^gW`G5@(Oy)J;B+S=}8u^%8M9=aE5qi>_PK@>)04qfxRdzpoA1AVwM-ws5{;s zcjEiq;OOA>@lV@_yTRU3@b2*7Z+owHUj?o0Blz8lf}i$|zd!i#IDis|+i#Em9vr+5 zw%`7LJ@{eo?JLCi?$7TIcaM&OgTr9&&Aa`*-B(et_jYIh$5(rAzYAVM&9?`~!T#Qx zy<-4-d_YYKV0*hz?==8&)4356v-ruL@wts{%98w>5 z4&MF!aPPbCkAv?I_FwJ7!Y=5^)^$q~eAr%xo z{OS8$dIT+Q!~b@U_YU47Zgvjd9v{L_#Le-+;jyax)85f;6l@>v9U)>~A09vhh*+q9 zb3kCA=G$F{gGk4o0}M4gPzcBJce!5CN>Q0M0bIL3Z)(2Ie~Jt*w2ZFfWS(XaY-OeQZ1lTHgb+ z1eW$wUQ9+`w1NCv#@qFQVXiJR0GklH|n~tvlEm z&gSW)3g$EDCDz`*1;C@b2)^upr!c|s=|+=U65#2HTS%^Hz=kj2xa6q~hPu0SBrf#2Hny#0^1 zqKdM|UE04T`Z-L>`J^g=YIvV6k_vWlpaYs^QAiP)fwl#PAfbpS!=vC&^L?RSs5wJHE zd;n>@x|yXz5D9LAtK>ust z2gM7u1GN9te!dI4vccX<-r1&S$X3N3Z}tqBUk;O3pg4^$KLmNkeNd+u<{iA?V7n}M z5sdImf`p-e24^qzGN}aRyoKs_2oYHOh?gL+)7cmfXSydKp~Ifg9U?!Sq?b7SQ9_5B zWV8>wK;jE}cQDq_sONw!1cs{s0NJAx6Q^i$z@_eZP_$NgI#JXE*$?(NtV;4$mjN<8+$v8#rDbC9{Cend|GD&%OzMJl?^QuusB&K)4W{KgHoQcs{G9!}Gt+k$v<^ zK;tk0sy|P9SyH`#rp2bnD`Jf(`Z|d(i)1YKOZ*Bf@*1DX;&=v9Rc}i96;3J{aS2sb z6)KVe5r2&QLP42K65_M!(Tw&*`3o4`Fgc5dm+HaI45);9IRX-?05P(g^7q@T)~hSxQ>SVKyH~&btPjgz4&Y>tL`BW z0Dix;;2V&|pxhgfaB(76FXbESqG8g($|sc=w?Km;AVg542mVqpAk?6Lx? z0Owo__t;ecW4$Ke_%RCu{lA5^y0-SYi_3_@dFM(%3t1RY$suy50O0&?@QcxZ z{yxCo&D2-gr1^*F&stmaczp3Tr{Daw+Rms+wP)~;$<0AF+r_uKUp%G7h38UVn zd4sq3j-Coey_e1`CiYG=%(U4&Hs@M^ozB4~aD_6XNef zIFQ2hUM1hLz-zT~n4Bjcu+-6IIy)wRS(4zzA4tUsThH0q>XiDt3D^ z5ld^Lm%+qb2KXb(5!f`oOmLupCu$IX|7`w*MS+yRUG3x(_2gZVT&4NEM2f9FG}aiO zF=VN1KAF5q&gSRaLrJA_Qc2o>pf9s+6o>dLOI84Pn2Zv!c4)gq9!|KJ&9k8-fEn!* zE-HR?$i7IXa9E&uD)~2@;D(7c*=zDC>QlH-2~)H$uv(r^+{IKDadyrx^)gu#KNQ+& zcc+D^F)+{4VLnPUsQJt$0Tc(f<-rSqf;g5SDZZS*CQXPc((@F!(J>rYz)N{!d z(`=l60G<|ei*2YC8@GH`_lC_TCS5@BB@WAT zaZqMuQ!Iow1jSXii}RPFB5sD|d>RFlB#S`qF6fE_Rzrf~dnAt7gc^9A;Bh;>rsNL2OAAI6U9jf`*CSKHcpgK5zqmz_Aq<%!A5d)8ecj^YVyr!O8Vjk1jp17p~G32roqt#Orz;4B= zBRCQPvM*xfmjzOpEP~|Yz{J6k3ik|z^h;84CLdCk>aeFhUq>Z8-CH3~)+fas!!D4a zz$~=w0tec&W{nHdia$>(fqaSk5XRH~FrDDhAI?&O3fmoj3#fh%uu1L+i}s%$ydORO zwy`80dJR4rPU7j=C=RO4p#A>+yd6A-gYSnB7EM?IgE`sQ?DkJP9r%0N@nOpV3@kb; zQDrRjkx-&@9}bdF61?NY0^-~v7~Lmvms5HrP7Z^CXm2p!qYEtPF`lyV6y5?xgnUS_ zA;pEb+r)!^kOdJL;iVk#A7nqRUOAhjRcMfXjl63;>%l1sm_!H@kD9^I=vYJ@>U3Q4 zQyZCw^x(7%b?1roaBXm&WGn|9!%-Nw82A&0H#BUzEFe}G_B+_x8Zkqd&p}cSV<-rR zsGplg7u73D5!bF z+)*7O2j$K5ET7=Cwg2?udFy?<&4nxhwMDEEoZZ3V6M{>Ia1Uw-xHufJ)n z2|<_N(6`4yYy0KStKHY}*$}3;wWf{(SVVN=F_m2#oRuhUb8Qd?!f!S@Yg%N)##+5! z@-z#Fgv}vhQS?z2!(CyB7uv>4t#a;2^wf`ke4+ZLNsctQiG0pFFlriCpFEQnaJE3r zjw)BmO^OUDkRRa&1?v~JO`E}WVklPQ;L#+n9tm|jS`(CcaG4}C+KU7fRXpeYW{S-t zIgjI#6c9jdWh&Jtw2DAkq??W?m_dDzW%A+HI!G+#`4*}jBDx2ouYo~uSfdAj zMFHRNuesYoMZ8(T3J!O{D)@GbTB^UBu|#KV-dbSt0D*rSVOS0D3-h!LC2&-B3E=az zaupf~31V;fD@`lkP-_Iz5>rze4sm_X5?eykxXI`ic>)uHlXN5QyXi6jwaMxDM&BqS zx{(jkHe)Fh0$cGEXM9!A4dSaj9hCup${YYdPA;;0qxJ{sM03uZ7r-A+Qd_uAvDmrajC?PYJw)H!^+q6rA0VQW>w3 z?CI|Ye6WQtrrd}Rkv*Ixg}jr}3leXe93aDd;y@UZvgtlBs7+5daFb)(rbRG+Y!NjS zsDX1*iwD>W{PHQk4b}RK46--&;)#X{94>6Z@bFrUN7?E$0EgH2fh>EwsISZ6xhuSg zQ{bnz7!gu~7IBrDu*~K~)2)YP5XO8Z6+9e)lp11hHXn}Af@=bQJE#qPZ?%k{P;r>Z z?Kz`f{1EigF?xiT%?rB3rv!X|sVhz6;&LyW%`1(nh#n@zkvsvnUVQPqkKkQaW~VZEI8N(d>SJRa%iL zCUsbIzjej@`po}4p~Wg#%SS8 zI*ietA7u4s9eo_?I}L9450B84XmSJqLQ9k_Gle zfau!V4N`sZ_Dwo}GGp?A0bD2=@x^hDzWS=X z&+cm_S)S-`%m*$8S_Zh`T#zD}b-vTs&?545%9%9|f>Ho~f#xMn@md5hwhsrrjx`yy zi$g&o8oZXkv%IWVD=6l7pU#UKrd+a(7nQ!_c8#ULUgcWM09H~op14D)!Zi6C=JUx2 zF#-p!0+%DKszSCdvEn@&8~40;tyen>n+1;X76?zFPNjRuuZ<|#3?7y!y80VciXHP3 z8Sl6b#$(uj(`+q|HBK7ltRKxb+>urD86Au1oqfDZ@t#N2P3xnO)lbsXx}5Bnm+)n% z>aCyZ2BG_65VhvaZW?u=jI}8Ubl6CclYT_&8IH*#u~LOi7CDp%>*rt!Pf}E{PLr4& z8rb4eT8s*FE>y9p-gVg+leDwp&g~@0LIJvS*U^Q4fQqRI-u->Rf}#+PL-ysQe|o3P z7>$Zba5L)lo)_9?3^pJ(v0GwVCQev&SxHJ2TZWKiDj%hA9*Tkv;IMU*#2`e0(A$2} z)*1}=^Eha#KLz>V;!^;O;+vKsNIeLWU*{?C32|XIHMpBOAOX%9z+?T~?wIj{8eB7= z8Umz$l4N6xGR3`@u_o{_>vj3?VF{uAZ@&5FNq^(X)4tgdt`)Qi3W0RT*%mISj!z23 zBXakJ;3ix+OaLKa+36UFB2Xq+`^HOQ(Ziv@8*tZU*HNz5vnEqS|?F| z!rWM3S-~RW#nm%9)^Q5;&|wMpLnv(_TWwC2x*z_}QQO}axsid-E&bKOIqjnoA08dN zfhwEkj1sIRWa~xGYhY%qi*G6bo9le~mQ1F%;8^S}LSw{RBKqPhLLXpPD~y2O7wbugkY8k+cjcCu+hMg6K5u6;|oN(;o%#Lte?h^ut<0yq(0 zPkmU0cOy1V#Xq630l@%R@m$gk8=Xs#pz-0Ri$W|x6VuoqO#~+h;S^e2Uoa6^CIa5> z!H^(FR>YD*Id~v_Nv`9YQZ944CFVmvp2*nJi0%@l)?#?GfZXwqZqh&VzA zHD&oE=%^!Hf(4Cc0hNr}?dasR;~Al!b~IQ|75o@euD+l8fb$~r1M#0dOAM;% zZ92RNm_4-A4?EF%#|zF+-1ln8IxWbB3TKg~CNjHDzRDr*(h)!)IM&_(O8T z7FozH_}d;HE$Hj2Ga>g<@2O9JY(Hu9W*wvvod}{5-Qb&Uoov1%&x(F@A$)aj@A8NG zplU53uYwj%y8TlZf&RG>5G;x~39eA!LymA|bVP#>PVK8I7iE`GaJAYlY#{S0Y9QB+ zcXyV(xjdD3F6tTDafO!=?GGJ1xtv@%EPj3lm99(-x%<*(WK3*h4`@PvsRviS1{O^8 z$Bd$BIbXrL^$xHB)9`i?--6es@Ip>R;$F{~bTk5Ab)BROkU70UTdys&_zK-E+U7>k zqGv5xMM&I4YkfSXlByY-T(Fy_7$U>Bm(oIf9;`R)1;OJj?s>f;P9(NUupjq3P6uID z1GeBEv6kGnNLBBIe8Z-HVUNv6%9p}nKRO$&^xzKHNoPLQ{xbC74(tEI$2RJgABR{97)3}L-UyEY6gmL!4uT|`Pf-|5 zLZb@{n7UDlmr~CJ(qM#t9@Xb%9hD{!m|a6} zs%~c+R|nTR%kzoSIm${Q?IierZ%x?B^X#8Vk&`o&gkc`Ts-*Dr1s^Z$jI`KXvF^zx z8n>Ddu+(L8Q`XhTuq-d)l590?6h=Wy)@m)=h9&iK8w+hUj9%OIOPgp1?XOQ?m!iPa9(MRuwj=71pLmT2G#@ywU+{Z@GZ{2ENS)tKdn~lP-^oS6%-2s zb;EG7V7GdqpP}lZbhPZDgYe|0qm5AUBQA8dOtgJWTLR9K)(CU5G5Yb5=#?~LJwmT_tLIfUD=ACvlj%0k6z!KNa*%P{(?-@;UL zAIyf7?M%tHHoe+%lbvni56ikMC*t?)u;^Q-e)zM7(7=UOKzO%43e*|$On?6I2*Jc) z(XeOusRiI2rFbmiNz?Zhx(g9s_6uWHiUh|I2~xb8MWX}rMmPw_rG?ENCV76zrqXP^ z!@3o+c}4Gk1&&~&qa#q90c(h2c(^my_8)7GaFDZnCgqMtXzL4q9$jAJw+4gVLlVz8 zHkBMW;x2%$lTn;7LZAyf;TW^Eb32L4>aL^hQye^w;i7KlOm39JMaS(H4O{`z2vFT3D+`cW%Na(k%g%YF zOPgm+90o0zR1$0hPz-pd+{FZ~Fc{TapjX`sX$cnvWD*q9;^V&d#GGiZRlg*agvMh1 zfV@V3LPnrRHW!#hxQ<$h@8^_jdZ@2l9V@i;puh1nc)HPVbx@T__dDx+uk)1dbT-UO zon@fo(a7|;GDopOyH=A{o0Iq~nK*H#>`sBaisv~j7q<4dU+(VHg{rrkp5b79$2@QQ zrS77*{_40#VGN!_v+B3c;qlwNI)uZ5;9Wj{;$)4t(~LZ@66MnBqIhK#;f>V`O$0=k zSc!ln(wfv)T(pMthAAgtpMq$sR_UyelQvXZNTl6>daxNl!L@tTb=*GjV29k@ZeDnK zpaxJq=c6|1@_0k=pWOlGB^tfA1xsny=S2FD;9s)bxLW1rg{{YwqBd+XS)Stn(9|z~ zk;a{u9REVIulB>TjraGL9dqR7O@rzQ>Tz(-XjBs58Jc!O9AkfBQ2|sQqg*`Ej<_XD zxdMsM_Qy`%?vL`(SyDhj#*L*Lg&)F2vHr$LVv?Tbg9}XDX?^4 zF$)!3kqpq%t0ZHfD7Ddza3MH`u>lQ#IS`w0EH>?(831fXMwjja5*M&zcTDjLlv@x3 z>q?Qu*u;*~X^KH6f!~RJ4l#iHoGh_qzguV+L|FZ7wloINHD^XwHZ?o4pKx zdn84rG}pKo@lSb#zB~RUut!x&vRxICGlN*0+6ty1>}UN#W}W6N@}#>z(X$mKvCk|; zIlDTUVb^2^?wvLTG>6ZzEsLC8#|>*iAqLc>00uSy5Lt--M8PsqKp_|Ktb|7h*{V@tbEm@rS}!uejVLOgjk zEWYj0NJcA=YY(UqDl7LEh z`A|9ZR3^VJB&p=rxm3ugXvm+9u=v#HpiP_)J=*?dgu-Lyko|nYB58#LF&*!fEV?lY z76F;SvV)UZQX>^CG0^Xq(u=^Zyxa*-u^G49?Aj=rYC3^AH05;E zA*@MxIr=3iN0ZB6#=+!&vNVJfdc|+>#i+cTjDNYDjLKg|m*u4GB@5?zm}w{q7G0O4 zO7ZcQq_+hki9^H!p`xBa$3qNp?$uRl@fVAbu2s=3Yw=7Sk+-Jj7Tqw>bG8)j$zrE> z*XO-v>0=6QWO$=d#I`)rl*e1mQTSR1VB!94ce-wZhs8eCriMCy{=1shuuanG3fGbH zB7`S|qO{A&;8+Rv9ijF~Mzb>O4UjF>SaVvyL#WY2y0{I%F+FRVgPf!TVdG)bp3MWG z8C{kGBE_4sI-2J_Uni^t@ne2yH&b2c>nNu~QaGwtAbCqvI>DRNM&Smv4629l69X~@ zbzbLwaJ~WV6%7}E=iTV1qJ^uv9jc+Uu{-LwB=wmgiODgItZ)!3*eqhXCL$+HS#-@!9c!DUSuklDl-X#7L~qG-mUtzT@z$1WQF`jg=vhr%&s}--h5bO>F~v7RR~Bo3Z5ettk&|ORlo#pqbZ!OZfUW{U;6|#9w_Ru48T^(X{TjfabiCZoWixzp4GMcjQ{DkU*( z*7=2yya^a9{&jGzE_v7Ey$9U`V!D@MH76(f*l>Y=HfPx*{F14>aM6-JkwTVz&TgJM zh-uG?qKv008UTgHEyWjpvhYlbcSK^IJ4S8-%n3vT2rSmE(K!(I^g_KSK`b5=RZ=74 zU-t0u(TaodT$7&wVAU08ox!Wf%UF05E?kWY@5jbkz!=}FuLV|=H?Ih-tlRzbH(`}~CT$xCQJ?j_>as^lG>IKF(!!w=g$je^@YjG(;U3VV$&nX@cgCBGtb!Z zG2N4v&J-IC{z|mjq` z=^{i8boG=bPYnXT4hQU~WdFdN+9#shR~>zl0f_fFAfvmf`^shOHp#~r>e}1zs#pqE!tm1Qj!y9*m(^6uH{Vnp8eDWN010Au@88ZH)BMy!HlLobxc5%(hU5OFcTp`EuU8CvqR-e>wr z?U10yES*D184z7|>Sulb70pte!J?0?GtjWIa4d|Owta!oF|h)s{p72sE^Fer1OxVR9dylO|iG#WXegNbI>W$sC9?|Ao(fhch> zJOLESbqBlL^HwD5z^@mrz_{Okr890M1YUgw=$xn*?LswKy1{)4;Ag-R}P+XU_kO08aVWP$Ue8%eJa(-rTHX(9K7mQVHFRmgCA})7pFQY_fU7+`?g`)PQ zI|5FbCVPG^;(0pOiba!ue!`T5go6UbW<(1V9aEJOaH1-lB0-jT^9$=$A6(M$I3W?$ z48uC5JnI~W6|<$H3|FN?%JrKzpnZR|8sO2a5^rN0Y_w& z)n(?du>GLjk(q(9L6LB{-ZsVn9f*tsA?0ohYk)gs?xvo#I?cv^roROYLkP7n7}Qw%K$;#l}-*T|;Xabg&t0Y`Am*4~_mc&Og=dzid(hG)ji{{jha* zq96j+Va?TA7w&0)F05S+!1G375#IGICbg3FwZSl~o`&*1R#-&GjzLinI5)PWxoRwn zJ4fhomF+42vJR%Q>62M?xE^);ZY%)N(?&qTvu=eea+^Dn-M+TH>-LJrNm<@_8j=rdD*2@+lI3^kH**h_MkvhP zy3>a5WiB#XAzv0rT}0*`naf#IYi25z%h@C*Z3f>AQp%M74|L2{D7d9A8jF<4R#6ct zPKAKe&qcgABZeG57ct{Dyrfi9CcNFpG&}FJwpm17)-hQ;)}i&)^@e$QhbMO+VgKQF zfgVtrJ#eCbr7*-sE<5PcVJg_P#?$8^>S*E`#L zSDyJ;4$1&Sw-PQC+8W~Q#&oi|a{VM&~7%G~&8i`*78OcxSFwo-AXK zt@jy{%gMvh=_Y>_Aweyw37KpiL>z8Iw+{(%C+BJ?eN2Cyu6$u@ebDcZSvLHOhCMODo10hfvUZ*1v z!=9}#-LnCF+tDAKv}=!o_F3)G2_OZwcjy-UIcZaFUP>tp9mLCHKvPZA*zV&yzrBG) z6ZXDbUpgxP9vYnUMJ%tBba**QF!Xkn5A%tkgn;7^Fg%cfnu3VC_e>tGifgPTg9`e8 z7?O1$sfD$4jw`qd8+D4co2Nyk*l;*-L&=##kLZUR3Ehn0Nd-)sTsJO|?f{Iy_?2ec zzFr!A>nQO3nt^mvFy>!pn@h87BN(bOdrM*=HdluPh&0%PmA2l;p#VqMycRrF5S&6Mi79vjjLr!dX3k#p&I?0)+`xZvxPFL_F#ybL(qCqL=vj&c) zOmc2I>Hu}D8HCu!CAj_^ntD!ustz^{E>GYAy0&cb*^F()P?6gW%3c8?2T5(MC}3Aa zL4zW9-Et~4lS+LKQlz(k5aRz7Lev?q&wDi6Oib%|Re-FpugNLoJe^oHsMC|m6NV$e zJ0AlrNUa}FTY=GCjQ6v1C>D>G`mq!$?Q|)lkSc*!WL)TlWpr<#-4gO4YZ60?i7N69ef;AH5CTclGu3UO{^EW`{4NeS0~XI!M!jbt$}lOTPy z*JNHQtUaI-A;Q4im>&=mTTgXrGScp4oaWihU#?dL6qK>h*m0_iCQ-FXRYPGV1ZC)S zry|V51InPbO?@;I9f%HI7pS8stmzT26~YK)q~Vx_t}jwJ;`AM7mw)-Af%6c=$&#Bq zA>eM#dtcYBbQX1gq!f;?m`Yz}7^C{Cr(=n-Ejc%M0MbqSH9XibQoj!*!+X3H^nGtF z;{e@%F%d|_bR&R1xD*PCih1W}!Qy39>1a zcN7!)vbPQ$BS-)Rd{i3J)FcIw4bbrx1BwfsEd6ASzh}U@AcP-QRaTkGTVd@)N3}SKbh;#xJEI{I= zeY>=y2eff{wIg+@c%6u3xoHMR5{58KvUpNqt~F7A7rg>>U-$Rk?han=|s_w9e0DWXq#!~WN>`K_??L7lD>wXGD^c{jl*9g)5YHW?AH zGM^V>Mb9D^Y06fEoPe~rZb0wSj;i!UMp#wjSCW+j0u`J0=f_8XP z-2%@ML{B?enPim5OUUaik@E%)Riw*7>$%C9Ua)*_O`};_1e*}@Mw>N|g8{Izh4`+2 zRUaf6xR`BR*=M+HH^bunaxPiDK#Ip9G%-|C6OKFND3xs zfXRHgP!W#^j5^c2+I_wKoE7M*-=4IPDgzGAtMke!=#2ReUzYrru}g7isXzwCcBa)SiOG?!Lgy6OJ<5HTo@ePe9mbi>k83GQ8_*AvTRB&0pK+jn{;Mv# zZ+@aPrqxeTX@)4+r-<5<@<%)zgm!*Ivq?-<%}a)pJI_mT!3)yLWKI$;98ZKz)IehnKc(KHG7Y#X7=fh+?ntDK(^i6fUTZk~u8a6UtU#%>*ud6nQwPB3q2B22=-Ln0GVJi4N^Z7j7> z2uHhB*z%|4x$V-&-N6fgVd;Th>kS;aFKvHJ+#xxYDcYr>l?3MfpxXyBIvCEU^9gJ& zS4j}kMZ2dF z9CBim)}(3;*ddW_9oQ?a@F!iDNh`Qx-@M&_^#bX@ffG#p0B2kK zZJ4sSMuIe^DsgqITR!yeDl%!u1?{FuDfNVTk)EeytwjKZ#QI4=mQfBeqW}thA>LeU z1{7rhzM+#q#|P>Mz0(NG7dNV)1y8_w)L-9thC7e)32FV%^1^@f@$fy3yjf%x?MB~J zBm7NwMtyZ8zb^o4K$X9Le+c^P>%mvg)_({#zWnM5#C#Va9!42s81LNGsuC;lln@c8*qXfBiC3|ANSs%Ne# z^S!eXyL+=49uZ61Ox)$`W@%}H?cIuObRgi5-0j3^6Ch~zQ3{8ee})i^mU9D33AQ7c z_UDQyPN;d+hG#Clg#hC&<8vrLp(5`gc^fO;&baV$M~P}i%#dA~BH*XZaJ|3rwAbr( zf)Mjm0K$UxPK296mTdOv!gbS0yJ)i&LQPAMUF)9hOJ227+qDq3zT~;iHmX``iKuQp ztF)5=FKVf|aP!_Ve_Z*t$KZ{|Tne&7>j9n)wUB3066bE-o=o_%xvYz~i|DIJXzv+v zR6Q#mm=z%jN0^??D?M_t*C^Gv6&pg+-P?oX-AyKAmCY%5glq6oZM$+eOcC$nTLp~3 zpa+g}$4P+FQ&PvonG~^O)Y_y&x$i}s=zua=>3L(iiA0=Me?~$=(ZXOA!4T3JT7ynv z4DOAF8^$&*;#DYEf6wRCJm5XYiE;!fZD}2!ofXMdN-;7}PZ@vErjCL$x3EqNId;aa z8_e9H0adhX#(iXyp8;z`2Y1iqw-+lU6Vk^*xvkaOw2q05T0eD6tkt)VlOF+qj-9pS zI*GjlHje9ae|bw;F-nqa+Qs~FU4(N+i2tZrw;{XiM^v;p&`UV-Tr!_K!>_L=s&`i)gKP)1<0zs zf@ioY2BbmuM6VGOX!g5iFQmF;_r`IE665I&B!_-yp~7sTzSRxn$xJ{|CA^Ve>@>1e zHEQ|Ve{~m6y*=ZXx93YYT2ts18||ZUW;hWn*z#^;O&^a|d${eq>$q2TT@ z7-^wH2D#&mG$ZNwhK+IrXu69GKh~qb0(ae=BRbzkjEz7858Z`LKwVa=}n2WENx44YFp7 zvuM;GsWJOh{5%MB(nwhWn95|t_qADmO@oOzSQ-=NM{<4>Lh&qH(z{`9HY!Az$#F}``R zrv+ytrmV~fY`=hbu@5P`+Ivihg1gGh&<0>x?~+kLjCQU7@5hW{`|h}K409PRScr7T zlzPq_|DC&u%W(<`@(JEb%6(uce{0=;gBO}ZjQ1h6DB@~HzA>)<#TLOX1zP=R!W+jG zw29Inhy#4?VL67(*a#i3v50n1pm_87OzoQKbP6*G6FIs0mZPVjfK!9ATW|f}cfWyZ zgh498dz$wT-cmh_uzmV;v}oQ~M|Hoz`c{j)B&4S@LMo{QZ|H!XqSd&8f2iKwYX`YU ze#^RIc4=?#uc>8CsmW6WZZLo}Qa_L&n%Q<`^Z~UB49uX>A$qtmD1AU0wFnK&0XdM6Cy5Qk(_?+?m}doX2_x2*ZIj;PZVESiX4j)=+vj+}sO4zHKd zEoSk53rC05^;%g^$h{WOe`Ygsaemekm^?Cz69wIk1DG<9p_q)|c;@i2Ed=8`BkNs( zG{|(F!k!j_Et-Igvog6@B}LJ>tDSoTKKgF?&bm%1KHaL5EkQCyAv`~>@pxKQ$#h1# zcUU`2=MFFtGEa;91|S-pzg8hD>3gH52`^$XejgD93F+8;!HQ0D6Nk54%r4+# zkBvN2Xt0w^f0=|BYejdP+leePaX|_0r!DywiDWj9v@m3Hipae7_s*2bb6>^=OjIaC zJ+E_Yv&(mcb?Rf2?9d{mjRs#JUrBR>#uP?kX``Ug+-lR3vl<*5LgPoYWqbN~FP{FV zt_X=n+sqULSuw~L&i3^G)$;M;`V)qwU^(^me(BpOf32FZO&-h2=ABchE|A=-{79sN z+j2~}Beu)ks^9BdRtGh09};({Mo`|WG@?i!qOVpou85L{_`}St@L5i0@^k+U3qNYp zs_j`we>Kp23*C2Ze2#T-&o%LTtcTCB7XDk- z!AiWgfl0cjhh!wr58W57NTFGW{#oHj&|mRL&~GMXbw02u$9p_f1@tKq*#2sV_(iGb z{fY|n{3py<&0vxym$5ZXPCLuQ35ftph+yoie_;;ej3B(l@b{jPE*dDoR(P_jxuXf~ zeny6{zNv3?vpZyUa$}4;K%F?^*qUl&)=5IvmCVYnInWaM)6q9j<2c43QPrR z4rCGMCpQ&3R+}PGiooq<;tC(eSO^elpP^V}f%gC{O`s8LEIqKP`Uw=FOzl{x4vNg^ ze|^YM0D4@c&Uovvu=qeFd1xFgmhcUY5PeQjDNyfU_Sl>aBSM7m*d$`BO6jjsE~r9d z@>QZ2jnxJ?IUSCoU7m8mwcxWPd&N{VEJNiY4|lOW&M={RqoT!~?edZD58pT2qj zXo6L9j<%0Rw|(VSA#P*NS0``@d_^Kxe|@$I-B(QLEEV+yF9?GRMD|7DK2*bSN}6FV zg3!4qazBC{{*c@(I4H^whmdohE?u#@Q*zb%VJusz_*t@A@$(TYR#m&-s#VqQzj9U8 zd#_%5>-mpdrp{i4A6N&2aY~7pF!5$0tUpG{uk$24ITii+e{4m|K`&p_YR#%TfA|BP ztTCE8a%TS$R;9&7Ga~4-tk8vx{jrQ|RqwrwALukkyln7@D%{iYj-*ItoYt3psL6c& zOhmA`Wc%5I(wqw?{44Vwn(xlg?7E1nfnJuu1MSQOC}Pu)vm4>SF?z=p!p^s<7~Pah z$1i}MRLo{NWbTa4@u)1WH#Y#Ge;Xsk9qz+lK~Hu843dIp-IMhwSU;6Wp>~BqJ*EIq zc$nNsV|roAY$1be@0Gi@GAanV0_=4{M&gVKj5cQ$BKd6yCRBi5G+oHY z7zj*Wm&+_yF&VvRl&cdAAF)2$ZQJ*I$5HTR?+9bepi{DX!3ogt4$j+%e+krRQj;&C z%=WOY&!GP-vY?h#o-OXT46e+buAR8KAj~|MG}(5Ye=O=V5!DHzt0B-=qx2;EY8;d0 zo#|>`Joi-3%^G%t2Lj7xR0G3iB%*nf>DE+K#04C^RA`T&(VmI}7CwSsWY)Q=YK_L! z7>2IiT1Ysh$btN=e=6+sf0~-)U7^0U`deL22(Wk>=)lRTge^weqHduHn1AP&NgbNU z%q&hhOj$IxC~%a?b#=cM48FFBFGtkoDRJV{;1TV~ODpKX(5qeEKP+<`|6q8hksFPG z2%^z|Lk#vezP63i7;+i3L`yAcw}gIBDLNRBMz~>2bKW*Fy076_e=^C>)1hUgb}08% zq2p$IuTlmQrTs&O)spsNAvbkFLY8Hhl8>u|)XG!z^1*<^ljK8iUc?wqwd~NQV;EQ| zmmpp(Bc>5cL5eh)#3QlmBp+aRuZ(csPoPFRiYpF3GD4fMH)`-`rZj92h-S z(;2C0A2Jf{l5&WSkCvzbB%L-y>AogNkn@EoHv?cC1Fn_*6F z$SquVc;3unsY)atviu(m5YJB8iDg++Z9lIgh4e|dny{TFNtHnW;6>#FNlv2eH- ze66T)2hdrJ5*8YKj|~Ar87K<3f!g_lFFq%e#o;*? zzs}Plf6)<3pv|`~?L;7?}&n><*y}t+jbt zcC!&I`@4=Y5cam+vD{v9kxtTKT8X1?$q`9l??zu+WE^?j-BzB^3 z4olOUSpj@*{d{p}IpPaHFy8S@*H|6U25A&pwW0}V7r4kxORnSW)FxBIG@EK8rImVi zf6VRy0Rl}TNlL$O%8Z|U__( zyBy)ZP-Aqo2poSebQTVFVM$8&FAn%2!-yz|PJlL%i_8h~fZRYn!817?^Af4Cru{z` z9>EIk&aED$X10{v3q+(D;fJDD@Ij!RwPn94rT}Gf1b$7@I}O?6_Q>p0*KzjKR(ol5#qzy&_&3&1jL%r zDB+MKOT({~uxC-^0nN;E~}LYRvZ@s7cX=to`OXKN8qZS1Uo6RW~M@KXojRj2;rANA7mBO3I+b0I7##64b8=zbv8hmo-8 z82quD`^RnDAGdFFW(Tn=V=mlnflAeR4cgyeC$ zBZNce?ZQAgB8p9~N~=lY`ZIV0RsiRYsYMaWctF>*CQ!G5>YPzpqRI~yYSVa>1m}~y zNb@-yFXq!JTMyC2Q#q%IkvDm9*)t>Tzw<@de+#Ycl@#sbeqDkYp--`Z?LuR zWNSy<+RGbOFdso{Q04E~ns=e$D&Imkd-(uUXzW^Y!ULow%<6%XMRBEqUQ&p_k{4r| zak`LshB{`XD2X^#T<$2O49gAZD0UfF$t8Y|)ANf87HV~k>TG8g*bqrE1bw!#M@?h>h~%3gi#Q0Oy8i$^a@(w8itbw8(yVc za~gIm7d-hHEeHD%`=5c5s@@w(Q}&Kw)N!!rq_7k;nzQL2DeU11N;uwBt*ut?mpsil zZX8PN(O^75-j;<>&$OxeV|y+E*6`vU+NH*rgBis@f5U{Bi#G0(?rO$2Qk@>tWs=-y z#D+~88@+JNgwuSN=H9h^E=3X{W0@vt)vf9QS+C5}igHJf0*Y=&ng*eNflYdjIUk3d z#1S{&2-=uT@@vlJ`_H7vRS-vfY8JJ_zCc3*YQWkZdjuaXqs4Cmvck?M!SyWqXkkhj zlw-1Bf3KiyAL{ph5|7N^-{o*-+2i1VyJ*E;;02v8Ha_XU=F_mlmzHTp7gjQqA5MM( zQjW675t;iqWw_=4=>|vEqe1Y$iwI%aSL$gm2#!K0fW@-!gDDzKh z!r`9U2#xQ`N!-J7rB03_??4S`wecDk-Sr6Gkw_^mdu>X7_9;+D^cF3skf4m8S{9f( ze+16Q4-qDMt65TjLw`IQP*iZvv{6@Eh2oE9IPJ-?%#_1sdpvH2V#k= zERmcS3Hke&=V$0{E5hVa?!zzaE1Zi2QsJWGcBx6q%DA5riO!mg1ILyq1E z;Q7bQ|6ViCLw@XrFddZhGkdyMp6#xh?WoQl#nm*03&ZfMf6VajKEpVNFu{QS-hiCj zj{xsv;zKQ4i@Y}Lt1t5IAB+4ymIQdn-P$6b&L?uZ@3+Pu8EZU7jYdfqe<~_lAQX6N zWf3%#H1z&)VEjSnf?e&jOU@yb&TyK@Y=|kVOyXdpE5pW1h}C?CN!Lm^q)gc6dFS?a znr0D5qrh+!05}Q)cC(M z!}9A+Qu6D}?Ud1ta2;PaHoA^Q@7YZzsO(=fT`MqMW`eNV9L5JrOYko^>%wtg{=lO% zRnaF%_lknw(}Hc_-=UO8LY=6+(>dAPs2vxnAi8QcI=m>D>tZuI={q+Mp5CF$Dvp^H z8nRY%8)iqg;PAXKf6Rj>_Rt?f!GYEgcU?f!S-}0kns0Or!Qhc<@A2a9d8g7sR_$f~ z)I&Y^Sw=zinKa6Dx6Jx0s0Dd_V+ab8elUduZPj99xCz?UrrhRGrR|3$oJ8TDj!-<8 zaN5*#1i9tEf1$5wL({gD1DkA?oU{2V zd8oE5Ny(gv71}BjOozf-v~YMOXT&pfkx3}*2HN-iI*%vF&Ds0XC~Y@x4iuJ$MLD&# z_YnhM$Ibw^SnsrK42MQjo{&PA6elBBz$cv9X{QcIX6eZ2@Yh2cU9Q6JT2R)7MW$L`o zGS`0`^#8-=pNITg?V$hRQ^{fEgFbWLBN)e>E-U zw|TXl-89Up>L8YpO`6?7(;!8DSv*a)NC(&8Wqgqr)o{*cWMmGSREIjx0-A)1pdV-} zvptzee@hWI`tg`H?4d>(n=t0c{*+sK`C>s7!- zn&TMpgx2GC{t!ZTAM$BhRj6L&n3|;#@M53yUf(VCu6>|_Z6-~(0hn-P6j!lhz|pfY z8n&=st&X(l!1Te7TisT@T$vBcWSHeng5HK^e;VPMfJ`_+6URU}&6z&TgQ(MEthi8z zW>ghvjuqKr&R@LFS-gghL@D8)lg}$u-seK4?nL9d`xbFEo|9sVd>Eu*l{6+)aEFsQ zn(UHE-b}mwFnqsXh8WC|({DYZNfKWrI!)x_fxY68W;`s+FG4qm;@5H9bHdBS)f^@qD+mM^;0cWKS*28|(@6=1;xl5H5Jay=>^9GPl0pv3qWG&6G zibtnwhZrFlcKYC1CkjH0471s%WZ0Wudiqyy_RrAl*DH+#P`BDh`hCRC#wUygDm#Pe zKV4}w{V%cUuRf*eFKbPIWf0o2K2ntz`E|yA^f86o9L5Y2^#NIo3e6* zY&%BfMlDUL(Ue=Oe-~_{`C^uf=(WN)ldwgK8A4Bq!7`x(7xQVHb{fyZ0((m)o)L{mLfY&?m}l!LEgIN<_?8CW#LzocjrnN*=#p6Opbp$hpE9W#21swf0axcclAa4^um2NSSo7C zt$2k4-CzK+rcak>YEKZgmc}`mEvmy|u}Yn@hc`dPCevg&gI1DIP*B8AqYFAk8`c-e0@V3T{ys(@&#jZwCP8Hf+f|AW!(^BU zl5+{bIOanRe>h9s6r?@IEMtk0m589EPGsSlOzDpF#JU{d08StmDNzf)quB=j%_wX4 zXNYVq!YQ-v6(J)Fk}X(Kkz@7P3bYu6M)rnSfZ%*=nu}CA7Bv+>O)H!tP|;eDZ#FWD z;Uq7$DnO_Z{OGF(072Y{C@Pe~*uhl~n=xW*2v6qie+uNHGeC|f5uoswO|r0#_*T*C zpmum%KWNo@;x@f7SFI_mS&;N(|KW~pva{sZCZ`7P0o}rYKj|$oI3!RyVAIksO6G`Y z_C>#Hr{?=<1I!s0K`E9W#AT&9hJmogL7ARATU#|3pDbxYjsS-012#b166Uzp^$?ti zF6tS2e??t<8KxtCYhP+MPl}0S*`!tV)4D8?$qcgs>>s&F04T(@pHXuDI^yZS&Qqkr zgtL_pXCnw8o}HuW5pP!Ut<-A<-{qnvMMX*UaVpIwq>W35MUFMdkD{EPSvw4$e=%sr zNL(yTFdmqQhF#~#OwHWP-#mYv#$ZqYEe4a!dl z8aH0)m|-ezh32-Hb1YvPw*ScMKbVudka@(m-r~JpQBfhadRqN;^Dw(`uc$FvmU%SZ zItIDaxvoKrmY~zfjlIj*7Vj*)Q2wiVc8pjvD7kcqSZR&7+7H?h1;~FjpU%WPI>n0{ ze>d?6lNN&LLU0#GqgW;|V6cfIWse|Z5nz;PIFI0rC$T|KSR~TGbVepNTqw+ju#Xrh z`Tx-Rqhm%~-UQe2jTvVQu%qJgnQ<`G(!{%AT4zLEvVZqpMtD#)fN`*b#2GWMAXK)~ zLKoH&4r+eq#pN3p9ksox3o|`9*y-2xE z#wYa1fhzFsmrA+WMYQLmJ3D~>>+QXLf94#mWPj@F*q_xx>fMWy>r}k3Pq#$^M{ePY z+=SfVx4> zdv@|QdA5?(Xg@7yF-A2I#uus$+5jV=}A_sBafsEiGZ8Cq`-F3?lmSse>6kX@|mSk3Bp3h z7KsQH-xW%sqBxz2^G>gzUtxzMuFAvoxz` zmTZLRDK0|zw%=!Me-6&8te0ToPJI}6(1ssxehGw&NiQgnNLXMC5&lyjhms{~hxuyh z;a!YDVu?ZZ@H`OWkz`ArOFZ7Udcx&5IUVM1?=0neCPW{{6|mc_pcTH}KHlE%v>ZC0 zB|?q)8Vl<5-9l(+)c`_uL?RKS-}TnO23_*Zk{;(NYsgt{f0W0RJ3s&vS*PlB`yI~M z1OL)k?&AdPKxUxJz!{ZVyhC6RJk;sTl9ea1aRTw9$ZeMRCU>#o-PgtL?$0~B?~eBl z-s;Xm#n0SZr7M>oOeANVZM`nwlKhuXkY`^oB51PeFK)7bP&mGUMrS#t7 zbgS!YxNDqhfB6_=PKQ1nzucy_&rqrxRyCVvRLK&Mh}bt@;NeYol}|w$QkK-VrKAKa zojX#mYX__BsdKEV?-^y|s|0sImE~qljD?f)Q6+Z_S%8)fHymO+V#kMgavk54+|T>> zjT&?N=GchQ%^$EOD(l>2PU9QaM9@p`6)+Up!)&K?f77P!x8-Qx=42J&AFs%%L4pen zHcPIO;$z1unp$zRqV(q)uT>-|ifM^={jDD}8Vu>oXs|8k9vD4>>M`AkNsn@2uTV3? z;|nu8KT_z_HafyTGzCf_$u}p*JR@ie9#dviHnfS2dtuY!oBpY5b7Twcvq^m6CMe}+ zDzz#7e>`2i>Nw9o4MKZSBGeXEYU#0I;&Tk>-Uak3=LN|$A~MO@zukcX6X0Po@N3Vm zf0^8n4VL0HAxDj(hi7nbxRmEU+yOYOePtwm5i&2|x^s&^Fh~kirrVcKm#v+MK_Aup z|9ByZVJullOc+}xC{KZXm1E5)x8Tm4YElFle_EdC1!1>gh7A_Gv|f%2{R%V8G%QX; z!iNmQ_3~iJPe>(B6_yXJ#kRRC`xA1?7pM#LIIW?n%pruFQZh%<1H6qYs_rl?hI5RhUh=IjFe{Y2^Ri6IY?v0) zRi2KNRT(FCK!pec`d9GRS&^eT#%Ey47-2{UtImfM{L4qqPDbk>v{uX3RzDDCb;M?M zpN(>uE4$Niod<+Kh1tz4kdd(-KXnfof9&g1_S#YxVWX_rdjyO6w7rJ|;|sPLsepZ$ zz)NU&2wnI7Wm?!l1k{eA(pIA8@{z_!pYkG z^S7 zb(2LFDny@}g$h)LD4_mWjmG;eiO-&QSpQFoDq_UHo2cTILp)o@zf}OSe~L&VLl;`{ z)ubQ!%rj5&m4_5$0;XnC(?4ou*^ACBTqaehAGmhEA1hi|gQ#hqLqqhS^sY4-AUKs> zS7M2Ul1@!5p-)H|W1S?)T^q6?t(?@_)y-NSjT%1-+Qo2?F7$4HIYdv~#(RlI-XMV= zC)?3jK3cx>Li^+yxz|iAf0~HjZ2~@4zkzkh(*R9G9OKp@DO&40kuWDw#d;sH$%w%T zo$OyrykH%2!Y9=y@Gwb%r!1GS!=u28yFu2q4ONfuNYjf5a$wdvIJU%aH`| z##p$A*5x=a3{~I0;9Tf znhfp-X`ekJTIbVrHO@$CYG}_sXSgcC!JhNQCX&)vIWA6e+OCpT8mD8xBy0>ED4~DXnZ;e=3!|5o{*dxz!!J3o3G< zow>&5UCP7=B?hGkdec?rL=-7TY=>s)4{t<^81}3StLIkQ75DEto)i;PRh$(bd`ukX z^Q>YOnVt;Z%negs^4yB$?JGveVzYbNm8G4pxowj%7S(ct|7f)>DcSG|@@=)#n;5YM zsLhDUQ6Mkbf3uQi!faijP}n;gqrOgL#$Vk8$Rg)yhE&ky0Ab>{4N4}i9SV(~_M@@K zrjbYSwoP+U zH~Nh(`7@Pd)*PO+t>>7z_O`9Z(B2GAPQE#Xr)`NPe|*%onr)xnEo=B^w_)GSngcZm zX}!&7I17DaQadXe9zHM;y9#EG8!&U+gqc+kV|0hOjFgk*Lg4Xj7~@-gzBwzWs%WZe zR-6Yh%%2w$z_Tb=nFhR@v#~c1BxkpK-mmY?YSgRU*PGBix;we77Z)_TL?w;iOGVO$ zg+;Lse@7xQ(Vp~Q}%{g|A6I~Lh&yQ`=go3KmUQ`aIC?+Lz z8G+#l{+Z4!<xq~pCz^$w zE~O)@p1~5ariWYWDpLGa{#cr3KG87er^Pp;iW*54g0dxvFBDt>J(-0FsISe-L?+OF ze&04g*lXc>W;Qv6f*}1yLLEe+FqL|Oxray+0CGOBE_y8IO05~^E8@t;0E5J~K8P3$ zhk=Sh&*6oz-KKlW&bOBSjS7_#RQ%yCf8b!5)HvU?q9nNvn_m(WQnFkL?M^3=bO49M zn0sjWC&$UBd4Ngw`Qmm}9WE%463NW&4eK;LzaZBJl7^8%5hN|n?%d+k2!PVJQ^&>? zu_a?RN@8kaqfd%SOTfe(79s%8+h`1bott!G1q3o=-Tm9Lh_iDJ<|Ep)j4?&fe<+Iv z)Va(mDe&V45Go@PN{ZUiJ}z`#sb`Dyt`TvjWN$-c0eG^b_*XgIxXD)Q%Fv-ym?;e< zrI<833j*3`gsrzacfH^+nI?3I6Il%z@La|;md7e_EwAT?45`}BSPz;#1!WOBDV%ODdRhJM8lI(azqUpuYab*WHaTf4{^7E*!2i z3OimwAMx*eI*I4>B&mkd-3FV%xYVK%v`)EaLn6E64eTg4)3bbnF8e5Fm%}2Rp|{Q` zjo~YRi}9V?wp!;nM4$oeffN0hdeCW7BtDRw!`zU_rOmjY^@Lc&Q=F9wl-J67f8*)1 zFTeWp*Wa|rNrs*>4}q6me|YM#Cs%zCk>;hX%rKs%6?#7*f&Mcoa)d}3L2=6}P{XFL zf4J;`;8-yvrJ5`X#BZt`cB~`dMP63ywN5$(!)8T<(3gFpS7OO@wa1*SZ#NwoCK^!M zJ9OZ4nBA0Q(g~7~bYFv&$FW8tqQ)5+`LG$zH2q*3>lguE37qIfe{1h=Kkx6ndgF6F zdq6xxTmCdrP8pfoM?2DE9+p=F-hV}Nni{E&+6T83Q1{><7Xi5EEP*k+0elLy5 z=QdIwPGcj+kZNj%BXvhgS_U{*t-HBCQP_0!>P@LGS;#=MMJcWd84^ISEs#nLN$aQ6 z!8VZ5bwxqqW+{556)cLkYMo9qHh+RI?$I5)@4+3s5mn+3f6MT!$`0Oa|2)`xd%R|^ z6_gK_v_geE?`6mNy;pZ+hCa03-`j?1nXX2$5;Uum->tE>;Xmu5#avL2Jw!=)Y>{(q z_31luudQ_vs1rHZ)_OgLxR1EEJPkI46E6~V$=f=4Se`yc{nj8UVRwX+`FZl;5O-oW zV5kH2q#RZ{eS>bK$OZ7s)sYCHA z(#`7zIUpcu!(}DP>Sh@i3dw9(m+909)zj*t$gj1Zvb!xI^MyKH(fjA-uIYqrZ~BYL;C_O~$M6+Q!MWU_5^A&sQQPlgpYxdVJ z@pz{%z_kWqTQUOh&_(zNQ%jSt!Be|U~MU%32%p8BqH%%Q^;|I=ppu#6sx zJ3?#7p8dM^-rjxP-K|;5aC<<_FK)a>YbGFdM?o@zbxBbyxTTPKI@VDOttrQ(u4`qR zuPVe5C>5EfJPKV3N{23r7_2)#&(eSDR0U~Skt_78~)|pbIK!tQR(kGkqGlA@)ZU%VOmM43aKdu$96X2?x@i; z4`VZBbIdQo7%y5UkGrRTc|UsmzW09g$k4@L40K(rjlH@_;^M{o(e1OlP8WYqVL%t~ z;Qiar4-V83PYPR|0e+l`BI#Ka*~QuH#$7RUT|IL(m6IIqo7?s1*Msr}g5Bs@f$E9t z6SC`yER&a;5o#nV8Y3|YkyR9|fAgl5{G6y$_w{mG=;2h?8^~ltTeW0tstDl>1HI#4 z8^r3T6SJ|%fa{3|c|a zi5JuQNuS$9T~bKRImQ~6qYn;uMW%(Cp6=hS(eejG`3$Gzd!2^=Z+lR50R{#3bof58d3YhREE(Cv3-;x$M~zPXBfMt1P`jxWf<&rxa#XiNZb z>m1Ecy6{iv003VAU!|HlaYqH|$+Usmyj(zltBN-=Sb!zWjiME^P;!~9nEj~^wF z;;!5UmNe|oSX%rSfb^`r2~bfmbE%*rt`~e*|4XimP2?;ee2- zrbf-8EnsJPM?tox3>Z0q^mtq!4c#v%c;k!Q2bgpYWIL0ws&SZvaW6q7sv^QDa;F1@ zN}hr6N5MZ#8)W;e;)$z5+((R8eTFjcyT2Y(a}bhBDphI=aj}ut>u@X|53+P5W0_x^ zWn`$pT_wX9jFoA#f1`3_>SAPW(Zqa2wQWG~1??0};qx;c)Ifph7UPLa(vG@+{pk6i zl=>k1U4mQth9 z(EYhr6$}`+)124*l!Lb5)Px7=Asn4~EpQ5LHbrB4 zu*SI_UBIy%FK00!#^pt7BSP7oW5<5y7`kymDl!EYhLo@%)wS{opD)>eg}F#2ab^2* z(VnF)F3sYuduVjHT~Hu!N{C)A5V5@~@@IiIf_tChn6LmjLi>w)pZRF?o&#pwp6TCFWlbgAjJu_9rPMn}{C zJmN^J2WOQ;yS~kXLz?xSC@vsYy#`ugpyX2Uj_GE>Ba_qFt$w(-3qLE9 z5`c$2O#Ba7hvS)-4LQT)sW+32q~5Gitm#@Ye>aC~Wv4jD5_(RFesJ8Z(s5H0O4qLW zFpE1yDab|(h7KAUd0swNl1^PJTa!#J#-$pOTinj&!C;|Dw zf4hCABrtvSZ0M=eh_5N57G|x2=(SZ3i9^SQTV$c+1~^ISjR|9;QX>S8+=apv_5X;X z{v(=Z$jaoL@a^|S-X5kC=;T!?>z?9CKiZ1$pYq*tzJPy#@f3&HG+N7soND+hb?vC(N94)K135}NI>ZPU# z%!Kp#NnE~HBxpN#y4~EZpf%QPCDa0w+e0g`ftJ(8siYUMa|Q_MtE0P6SO?GEzq;O9 zY5I(Vw+h?IDvtX(9-zce>lZE*87mMisP88E>(zMna`f>&qC&y=@(Nh@4I56dfAIr4 z-Nk6VK=5>mAfeBLvRVZy0I5v?-4e-tl!JLp$M5@H%C`<+$V3Cd*Wqub;{erG_D#jK zlfHLrUhokmXxdNoKg>t8-0{kIZldF2TGz=;yLCpGVvt#>UhhRa+j(8nDJ_y9{lw7)X4owj0irr~d3b`4ECM%88+=mKc@tbZq2 z%rMu*ASbT1_5$;1WykC5jl5v3%Hc+%RbP7OQSBA5 z;`PO=FUVLG?J3O(Uqe76U#I?R)~{b!^H+B+E|$4eKn`T}L22uqx*oRy;;4cvewmG; zfpJi$L%fMk9Dyq5=&33U+{vYId4E5hrm&x*KR-M4a|2j|1+y-v3(v;iCSob@TQ`b+B|18q9UV=Njz*OmXlZYd zk5za)6UKuDtVBsii6b7_JOnD@h`I%bu2SYjvYI^LU!U+p$#HP?th$XEAYRq zsIvX;&Hk=1AgmnCD){(t@2UHEM2`<%xKF3_bpNgUv`0^0IAw2&atZVFi+l%2Gy?*S zDkY*x(a{*Yv`Qu(DhU0)@NPyx>b3$4t8jr{1y5iqOY~#eMfwAKjW_{h|IKd)S^7S+ z?UV%Zigm+OvSEg+1w7itM1Qna+(?&Y=vpnHtcCcWB=LN*FtNy&ON`2$Y=fpZs|XdJ z;D@!UG*RY^<#qlKBtEEpto=sC*5pKrazk4svz}Xhg@AoK^vz_vf^Yb=-M;lwE)ko# zSKp5h$NS^Kd^qwjEQ?{DcHgJUh)u-q=@1Cij@TID-^wsWv-E`AO@F4@WDMh(cc$s2 zuQT8+I)?&eINle?Y4Kh{N~lj4*Z@VW?rBC7Cb+o0#f=h(!R%5cjAR4aGCM$+p&i4aRPC{GZ*PyY)D8OLdVdR_a%^M&4Zk~?Gv(>M zycc_FsYTI+ZD${=6w_ z+z@UORc!}F0C)S=Awl(+050Kup`?|`j^R-J(v{^)3Wi~lt*9GQSVEnwt5V30M3iIy4tlLB3LP3MC#6<1-@5*$Y2GrvpM?JK$4gRA$hc)Fi8Pz9y&Ix(IWcyRFc%73l)YjJKIl-uy_CF{%xticuLBx(L# ztuQ1(V12>k($&RXU3FbKlKfq+sO9_Hs_SVL+lSzqGkv?W6}L=Rr3H9+tHMLc&`*n3 z=|`+lKNse&xJuPBRq*uujh%y-pEm0R8pB(Me15{UVQ`!Z9LT*h9-b%@EFd5(=2?9* z9e-oCC_9BgIt6x+FIR=)+QOjJ>HCc0*Q?o6l*+uG_;XhSaL3x(+Ukbdr`ZV8bBw2l z82H5-2r7iL2W^<>M`_Fx4bU3!`oMU!6vUQy25zgc=PYdQBe@mGs1|wBRiM?ESQ(?a ztk41ZevMVN%4r+MSNpwdyFB0_({#eOz<(+RyT2;Z!5|hWVJlAL7n&saRB0ZA(_JGv zOegVD%BX1)@|{@F-=c6?9-hU4qsPIcELlU~tO?}l4vaT{^W5st>Hf_$0!*u#{q9Ug2l-^6{hKYBk#D}g}Ou@mJbwYllYwAAd^ZfK*G zcPl%HDi1KvX~W3_nSBci=U$ zBe#`}W1oM-A%5e|j3}Hbp3FXDs=>D4EWMW%=7NGKdd8LmS9QAC$-F%DrsnBfmbDR|=#+pVT_-=wTgh3bQGn>1&75VO^MAKlXHKcmJnh0%B~Z3PPO%A3Fu0d;8A83AFj`i+y+Y_hj(^L#wCZ{lg!Bm?wQUU&>lan4 zi)x9=*G-DFT+6l?v40Hp6z61WrEvG%pF%mM%uAAA=zzK-GTn>BO42)CmBX=UDX4L! z->uXV117HES9oIHr>F4qSjqzw#w$znK8OStQ*^Pxh^||HGfoS@5(;g=Gq)8pALxrR z>m#P~ZZ@98#JR*w4k!&Dq|;M4bv<}+eu3Y7Ee1_`=zhaO^?#KwK7^udsSJH(PAl`S zcrv<$wy2Q1R-^0V=v7^2J&a0@%zqqMzbhC&IC7P=rCz2-bt}5B7pfKRDoDT@oh6h; zF3lsDTo@dYGS#=aF(e5E3xFe<(hn$@*}P~i+e}-ECNUbFzooP0RW}}S(*MHiX(Xmgm(r#J-Zb9dQtw_zi zyop$-!>5+Z@+E)j=#fu>0iZOrN=px0-g$Nz42K}r+xm{ELF^EDtgLHV(O`{K6QT+qPgmg;d zY;Gqa>`mbQs8kSFd(kIL-^*t>)mU|wE9$H~)0t{3&30SVo$>Cd2v8!%raw$Vj%N+3 z5T{+?gG6&#VF43e#rCE$8k_s-bbw*E(pmp~M#?ps1r=k9DtDa^p> zdlUnIx;sHock_=X;cE%jUjO}Ok}PY05Ri`c#ZoLjp~gslr3$M_uh+MgUM&%{6nni$ zid~B?XwM-eQ3;O9C)qi@su#+=*Pm1F1sp*r?GL_)>btJE%l{N)Ua4oB&sgIO^DFBh zpOS|S8m(f-R_hCNI-pX&ZO5Kw7=O92(6i4d$lD3>UxEHs0{zFy?tEkRQBsb$2$PR* zC;a?ZYX4ZNU9b@{U^xX*j2+ETizNAoiuRKz`N^nMZL}k;*XTlRw)yVOrhxo66w9poTo59tA^Ok;XQBW$=e9TV;z{xltnJV~$ zYJ5)t&y8`w2eK8YCRJ%Ma0%j9OjQIpBAkIozX%|Gi}`^hO#c^wF#MpxrU`sfadr{P z*9y}wig{4=NJcQODnS@+oCvcI6AB&1#FUakdrYLzekUWcshsk(?SCd}22kL0K!RTC z_;NnMF~|>Y6_)yc7G(Xijh$+VQ~c#e4VsuHSZ8WdFG?g*3+M_~prlPmUj-yVQ7MJM?uKEq;6+Aca@aC&ZHi z9lj2bfl-#vRmTNo6dGdMMP}Yb?!=4Snb#6Mr|J%EHmL)ae1960OP@{K&BtN-5aa-X zyqZ3NHVXuL93YTJsz4%D{dULMuz?fu)8EL#$+uD}24_QjPz0bIDZj(hs|hpaG!PI4 zf$cXrjRocAjr(2bD)t7>Mqytb-+V`NdM{xQ0#=SeWU+TEP@ZWyz}jS3Wnc=!gL@nK z@C4x>2MIy%$ba%3abKrq0~!ZRbS6vRs*C^3reijv^gC&R>wWsx!_#mlvD6O6V#Du?XHf_en}*pboICBtf*W;0?|$fv@J8)OTLGB^a~ zw{xmMgHw)%uw+aHKp4q|@Zfz3IHlNP!qjvu89jOdyE1Pg3P)H4F4(_epPkI%-3vO$LkQ& zY~tQ1m^StFSAe8HUmviy={@uLFt*ha9zyjxZhy%fgVGdH0{ML_ss8+5C6ybkg4=vP zI-?1F>xdOfXQiv$e5RlkR?sfGR!K)8r#BxJwPKOdmx}A&uM$W>hUsyJiTzKOE00Nv zUO{QTGC&n&f&u%XnivTFXbNu*jg}|_Hwm+xrTXCEbY0BP)&i9T3MJg?p5DR1#e z`mr!R+5KZRtDs7Swl`_T?_KLGjfoK+;*u~F(#yqnGF**Nw)!791cl2*`6g{?7>d>C zQ>4?~#H6@2%B!P$YgEI|!z)H%2<>1_K!1hXb-*GY1QJB`_5zK<1*e){EVRlM?DyIC zoLxu6RrjkapJeI1_p!p$Z3(u5B&8{K_rBM+MfSFi*vp0VRf4C4#jVc}K*c85U4bB< z8d_y(WECYqzfge^pI(N@;YrU2rnMy@I;mcnZ4XnLKBLdmlwxH4(jej$f zGSsBeP!V`ZvevO4MG$gMr=fT0J_kx6Xz#OWzt`6misT~7**LOp0UhIMph~Lfk_1P$ z>Z2T`gNyVsS2TpG(P%yxu-s3kiwkTG@fy>DGIkvpnlU}e1}54|f5xVhB4lM$-LiLS zuqM(rMgr6q!pi5|6ku>WqTsq5Sbu0l~^a`VMPGZ=W8K9}AL0)DUs4zk{?0#(_7u-w^)z=<0}vJoVx z_R5f+A#i+T!LMpYSls_C)kAkJD zA32{H&&6|j#msHt^9$u29!IZU9}>F^1H!pJs?MT|bVLq4lj(Spo>CZIHZROqSy=As zFadR5P>_@P2!U&jP7+nt{eKPht`Dkkb{^64dId*g*EsNQE1bwlBDVOpZGI&i^yFKC_Td@Ko4wQ)u;f>2jE5r(?E#M+At%d2<2~U7Jt*hkBM5a#sy7xaqhjA*WuRayjHFuEAe2VFFJ1rSpV6gD(I zYEw%P0nfHyvk%K;#^2AmbJ0oDvL8%eXiTE@InqBmItNP|>3Qk#6rtNwC$eUCwZni_ z%J{NMd8PqpT7Q@L9Om8#vEr_>@0xcmWqdquJQ9U@9vK^Fj^L`%BrE9m<9?SAz}drX z6a!@8WI&{TD-FPHDZA#n`UQ{ip(A_fcyD!)g18-8G&-)J4XtO2SVW@-QQS;wi|{pE z==UjCmy6YnMq@R}+S3f4@NW&&`aTHh=!3xN(&ChkZ;b1MB_Z%B-cE zmCo~vk2J!LF>snOb@`u_R9DVo`^4P03pMuwb#)T6EtNG<(B-czviueDZVFnK>uslks?u1AU-qN^2X76yZCw5_c{UyWx! zD3iDyiGN#7ONQFDX1S8mu%__6g=9pZg9&M)z1TPx!9%j(Q@(NBealjGIoX`aY()_k zN<_A`=*M?ttCV7Ti*5!7wh^60qbK!l|Fl1ge(6u(v@n?Gwvor`)xYNH0Cl6*m<0-l z-29Qdq@CH$6A}{iFjVV~l+&z%|(^_Bf5e_AkLd_zW(aVCw1o$;9hd|u%s7m4=9wu<0n-| z`U~_SfIn8%58e8qZUnjz{bYW=*n4@fg-)1-q?9NOQTDXxNiD&20>Fowe(MyHc|Itd^(Ri-1(|wK|uBeo`8#AR_ z?sj_jafqXsPhbRtN*as22=2d7x3J?`=>~8(E^0I^fL5@{V@*g2=oac3gIo}wd&_}X z0EMvaQs?nU6Dd}cC*Ga+Cx_z|wrAScNq+=K)!KyiXS_Q@w{qC+RFDK>M{|(12ee0O zb9r}*l-pzZEa@u``&%2J4(GXzjt#0?3Wa zokJZJ8^bJ?c>GjG#PWne2MTV9JB&snMF{N1tb~RXFAX>A%HM$Q3~LR8C+RkW2Y;YB zTQDmpg6NbDnQ}nla?(ehatR{AnA2Bt&NoCxVA~lF$-|+hWTF1)*-U5Eih9I{OoY;L zm=+pMRB)G^(-eBPjt)mf>2YRJs_Z6sm;`!ih)f0pOV@n%EshcAH#o_9W2J}>4wVXA zAOK@gp4^%-rYiPRiC6~5zws3JB!6Gzc|D)ueGe&cUgkNvbiC!V^{5&BKM>wFVSm5p z^Od#eI(nDk?KUPKiJoP7XWHl3CyPJVQS=Nin_o{dH;zdiKkIe#5nq>nWLXzekWVn= z6`+ap3BJA@(GeRpF0&}V%xBp!>P*x8EQG24eCc)no5vJKD~Gk+?;s^6*?(Yw6r?cc zm=Wnru590NQ-)0sZP5c>6ak1 zqf0fYxd8h3D_=&m40usUhj-84zzeH=yB2y=RtBoshQTcRFt@a70jI#_j1DyOiQtW- zbOfjZis1zAk_L%ttdS65QoKctfw z$}ooFtOAqkJez4vsg09??h{!XMv&rV;MfIahX|b+ZPRfj&)(m%27gjwc@=|L7gjb% zXxXR|GQdK@&(6t|TJ+2fy~b18zp=p+4pwb+=fg><#Z?s+I|V3Es~x|WE_ZzSWmWpw z8|1gddau)D*eYimqNEuXjL*;%FM#e_h6f3Jzj;jPDn0_=D@z$k1tUT{F2h^!6pi>& zh~W-=^SFS&LQ~-X)qgjLKd~&*kFUzGC|1E&Wt|W_%yeQ^$l=a>^^M;d!g=Z8QTYd` zU7XJ~W~rlWkSM8veiToVibEtymKI0JU=~w*8x5I)g3xLVMF}W zEtBdatXtnT5aGTrun-|oO0HVPPK1jtjWlQ=@)s9#nYCN(QGYCCA@}(_HdR25>8yB( zzBIG9??>o9V#8h7xxBa$ zyV(Kh3p8Xq4E1Vz$IvvWFbEQ3p;O8lXOAFBoGDVY)h^R6gj$OopZ%g8o&IpniqM;2 zzd~cMq+i-{b$^29KT7Tr=a)i_QiB)#l*TQfmwMdFP%RQA2&*)|PI=QsGCDtkXba;N zA1}Ga6|XPqwSw{cebrV}s@uZP8pfnlk%;v;AqmmNj1Vd+ahS&IJCUnBE{jmFC0jgi zDg#xrU@dB%MD~<0z_nEoXR?JJ&u8{_!+&WRSBk49`Z#-1A?u&a`-3hX zIh6K?qY;<_JR_NGmY*R`%pi4JEzP^P;J;(1BrEZJwV;L(5N~ayAG^N>^s7K3<-58t z20^lH>IodzF(>^jY|~_mS%;hHMLO-SpcPXkVS9v{(^TK5rw*HBrH59L4N@|kpz5UE z=~231<$tMWG(3RU9L?KN4RxBGz#T*PSir64Ph{C8~ZPpYhhj<;u|D}O_M(NtE21MrA&Gsj_ZvguuPX(!#@ zhN{=m3H-;invS?|+?|uE42B`YbwD92Q+YIsC4`y-f)YKST#^egcJ_o+Y@G;KGu!aM z`3y-YBg8hM=q1q}IzSq@E@j7qnSD8)6Id9pLBG?VVK82_@FCi(kRdSPvnfSf9~Fiy z+<)uXbeq?}{&)oBpQ*u_b9@pc-;NzyV*sTDd$+plbL;r?h0qSYDEb=X4d7PfS{1Fq#DAHe zoWOA7&V{TSWCV73P5Dl~8c*-#efyHtln#}XvYEMzAJtKBzJU%oIUQv^c zekW=xe*J39q!Ll{{By|a;{$YH=86sYstZ}LBnrH!UcnZuxiJNs8e9gJj_g!{Ah#MJ zyuCFjh{yXJ{{;h&P;`;m)i0sv40o)Ofs|s z$B6J~WG52A&-$nH@jQSjp~tTH|?i_sJmPtiJ8#bgNHbP%^3c)^JP z5-?&4q^n>1du}%y=wdRkudcaXu&}GBD3TUpJI#40a6^c_vBD6?Ni-aH)4>iO_VDZ5 zLNHEEd|`%15}!h(%zxKV(W+$-K3*^kRxrS#ddp&Grqwqr1w|T@sjZ5&L^uX@)Ni2d z%9=E+AhtBx`VX$GJHpKk^%WmlUyU2NTuXP9ewUY3(9;eWY}j-J@5NE0N|mp%oRu-> zqmFqc?6hH`^oOuOyEMuOpuoDZsvDf8H;U5aBx!DJU_Lg@zkhq=g_Yu;6WTsDHstQ% zVZh_F5RXqnq~&Asu~A$I(Pdn_C_j0Y!5_KKc@@~V$9j4{!@%^np53YOJ#tg}nJLcu z2T2z64CCM908KAdY92J!(YA#sQ)xkLn)P6F1_@aPBViYJ4qnnPD3755*o-1r{|x&_ zyS8TO$sGNhlz*vQ-kGKoj+>%%&NWi#39UIqhTeYqT($&nA3#fUknhXrJ2STA>{Wn>446)k+P%eAir+QpI!3 z)v0Oli=C(VOHEbc*)&<@-tp0{zoHF#5ojfl-^JDv@BHN^Ubz{5>~nAVnKxd+D~0ct zPZR3imVZw`-G?pH2c6UgA1U&%Pbl7~4B6g*SRh5abFWx#=rX0FLs_fYbaJVc6Ew?K z(@+%mPMkBp$<~RRNI!vBxbI{j2;oIkW~JMrn+qiz7@t$}fsLa2juZ_eUv&+83`^my zje^=&T*#Kq&r3K^j$ zYRc5U*om6RIb+dt^VaP=5y`x>Cz(ZIQ&yskZ7nmN%$u+pX$9CwRyUp}5sNe@v;LDEg4PSUk9(M72= zc+qVm`k1=u0wqBa1c5UoUUdCUTvu^+dv3nwCduv1(BfU6f2P8pMIAP~^QqPuQ#22F z^E2u|S)!I&!Spgp0UTS3)Y(@+E0f?5fPYC-u*#6`Wt8oZA|8thevdZ;J+@L}LQ-OB z-#5d3H|1RUAvLMfPRzHC`PLO`L3y(4$d@s0cXS{*xN^>uHvyI2C!NTI-@n$@mEJJ0 z!p8(K8eG0crsDY2YrOt8O=+jc=`Q^z@`Pd=j`I0brGKI1lo)>kHDfq@qt2pDntyvZ z%w}if?mpD;FNYBd=?j5r01<}m6rG7;QK49#ZgcG=GPj2>bbEO+NMMx?Pe$Q(^GQ;q=&b`LO0I=eSgGt9BAkU1Dj9yI-_gA(z%3BR{K|#-CaBYWW+FD zUh(+VQG&Z+Z|#>?Dt>93*JB%>-Xu_#nrp+hTGef8z;OmvvcLW$opPI);^aaCAbOM>NH6MS|0zP$k5HJ|M3S-Xn#&|4q%e1 zc6W}3Qy@3CJ7k8!bO@^|t9OdU&Aq_M zgY)jsd6W;j_#gb~0#|}RKldtS%y)O!%$bs&)7*hWMk#Dy!y8Eyw^R{2kqo-(AO080 zs(+z49LBD0#Nl>(TN}NFF@K1F95cY6+xz)^kPGEYOFweedp(bn_3Q%wC4MkT_ok&P3;VXK+Khx!H)0a7% z2D;gF+Q8UUuvt~aXx%p>b00~5AGpK)Y3*o4(cv|$gv?|HNnRs9x_>A{Bj3yS41ug@ z=LNh+l>$8Tu0x8r+F`v9LzvlHxBGbkO?X@L;uO;QUPKEQK24DT0pNKc0zMiN6sYiv z9h1UTP(;|%`YSSdvsEYBBtyaf<=(xudu!3@V0@AeqO)uOJ9`d~a1OfKZW9>;9`00< zN}|$DW$s14p4)#RP=CT#JGJomo?_f{9Hi@tAu9<}U$B!*2;x=v;++7QtaWtOu_7vJ zTqy$`UBtf6Ms85+1j`dt?G(;>WqA{iM!VB~w+mYdYywC;zKGXd$4xza36F4J_H5A` z+#P{=vT-og^K1w7MNYv_UKt?JdxEP)KohB4bXt3mf6G^U7k~XcTiy;qwKqs8bW@>l z6Iz&Du&KFINA7N31pPEkPEL{z`i!c3k(A|T7Mwdmq7J}3%RbQElAe}T%#AF^#%pbF zZ|mvPt^NJ2XV12tKeuhV&pj^P9ngiKR)3I!biER_v~L(SjZgFgRf3~fDfX+7D#+d1 zOo8=H&Jl+D1b@$16&2Cmi>Snm5%UW7JgcAv!I>kG0$f`J`X1X|%`w3E-gKH?>h%w6 z32lZP6XXSJUV#X$cwQrixZ0TSs9HH4mdTDrAOA40ki2(Pp6P_W`2*yp5*K8ELEJ&b znbhTH*_|wconW#b+~&3ogz(ihkrtMu(Ew3g1%vL*AF&jd4(b_ z^9mjIpWGJmGm6wlaj_EV#Tpgp;imQpU;`UF z7N#Nt+J7IDV$9r5S2vo~g77*>hbP@Mg8dkU)EO$8qD>+1l@iA;1GhDgXw8i!RFjK` zdZB!IU86&@6knj)TXw)dyrS#qOsWtqP;`nI(GJO%J$s{W+`{>D{9sh8;aNsqD50%; zG2f^P280@8?s+jDkA5L9{YxpX30@0vF$+n3lYfRI`jO^X73$*wh7fSxr(K6sK?1VB z-ZN5N9ZoNK%aGzxY;ai@w6yH98iQP2i>fB-kPbLh1#VPTY_#1QAUhky2WqHTf>k6X ztsze3gEDW6eiFD002tb|-@xySaSQ4>bw1j@(@8Q`MMR0;y_sh3`{Q};q^w-V=SKxr z)PK)u?M|}}y7XvouikXb)*ckPhPkHZvVFYypQzRayhH;eMu;v{xglH{Rnb-;omG{R zwOGADZfW{%NxBQs?R?NgCC@;X!*h9%B2>{9rZQ^2GEB5(u25od1jCzBUz?YrdZD@1 ztlY4)iOME=vRSzSRG(&@l--m1xrs!Ss(%x)>YH++NrZu=HLBE{R=0v=1u z+~uluW0>|?B!6d*Ba4P(l z8Mx&5)j7e*rI`}OmX-iINuZYUfo~1jrTB{?mGuXu4kR4R4OOYAIZcUAQ~Ga@VVhNcgZ!f%}D3)wc-FT7=L)ac`MFBggVrr4i_$NS_!aJ$Uhs71$oBx3NRH- z_4`$r2Cy@y$`?BlvjBT5N!Pn!ZU@AImkcA=gAmJzeru-F&hkz=$=<>_;ltZ>bgH~7 zwIX!w-+&yIV8T)OuY4=|scyw7ii|L=9Ko}SxE{efn+CKqKqK)^(mu%tX@7pUu3UuO z*OjADC7I&i@Y@-^omHGZD2FR0_JMHxx)-Ceh6tT!16XJ}PQ*Ot9y(_DMV9)ndB1aR zSSIR%GCD>J-|9&1G&!%;VS1k75tH*Rba|-`#z4n>R#&Eu@KxF=PU$3uXZ2BUfVMEu zpHo`@?9hPs!;={s;#&pJB5fU2g;Xt0{-;fR-TMn_jaa{SRX@d&SLX()QATqvZ$ zLm(-gwlT`=u>VWSrwU@pr`d??c>r6gFBUW3t2!z=zskO(r>YReeSgv@>baz}h)ybZ z)HPwZ=n@_ZQ`0xhIC9>b72l|p>jZ`q46Q{j*ffbN+wgT4TFRcg~ElUL6T6IXc(aGIM@w70jj`6zn2 zy|cFm-*=mvr58@ER)6&=p44~9ID3;#^Y-@4qs>SBhzf1fBX}!H?dpo|K_5p*ji8Wp z^9*B|qoHf04#{b9vK6HbGOLS8-aRotq|A|%lZ9K&lx$GEk{mbQ*uawYC&GPDd$8^+ z^b}_aozTnBB{Ww+PolL99gPMv;>+R5cp%~vyJuzMw!!#fwtpg)Y2*`F^IEVN1b{>@ zu~m>vf-nZ;ZZgwXoi24iX2H9Lyn$ch%1ag8Je{7-$s`@4f#A9#gGBc0(u{8!^;NT# zM67E5yt^FD(hq-Q=xF2&lGGr3pAB|4Ynm2hyufG{)WWaEoM}+4{66$!L#a$Lm{UL6 zro)x0UaO1qRextr5f%7Nt8Wii$moAg*p0}sVl-vfn_I_4OU78wp;*O|fEH?g6bbyG zd7Opy^Ln#rAXg0QL?asW?27@i_LKU^2Gr{Y2O^34iRX3YQppWl5k|6j^6PW7COM8~ z|H6%3Z$q{gh(c_zz!SDo->oE3%m|h5MxyADgk}omH12U58Wc*lXdr%blN22165}~Xx^obFg%U|!PGI6+ z=nYBE4Zc>w*7XHfhi+;(F1r$Tv1N?yj#sT{Vt+RuVZ0_1ED10OoG8!ZzsAbWUMVGo z08JD}93xXmY`@U&hWyZ9=HFVQw#Nr;O%CojX*p2EAPvV5)y= zyU??Q{(b4?{o23MV{v0oI%EcrE0TzS*h_9S<7 z?=;NnVnoj}+rb3GByvm{Q~*j+bF4|CDb>YB6OTKfZ$kJC`zcxlA_!VWr`M| z6@68RTEl4jWH$n7t{ZLlcac2X4}bf+(e^`lI>P;7z%&yWHAj zH8e>m*#@emop;a*hl0P+I6;NGk|BKuB>jp%YUm7S;h}W zVqGBQC6y^2SK6AUZDL&&V;#2cz?B8zdBx}*^o+Cw10rD5sY90SY|pS?d2812THKOP z0Q7M{v4Z=602{u6X>FlfSqqz(j3;r`Yo}V z_==uoDkQHLag7=CQ;so=0!Uxp#So`8d&&OQ_Tk>s-5Z+?M{gSGrP&aWC%F5oi77-a zqxa=udIH<+>dq?q4RU(EeeRE(iNH=HQWZb=Iq&wGn~w(PdH3g^`P=!=KQ}iwH~rm# zSvA2emCiR%)JBjXeSba?5_PNfHNN3S;9b*w+2ps-FudD*bX?%on0Nzx=|_X@8U8CHhV+v3K^DEG`O} zDhyv&@!*>xQ2d@!CwAYkCksu|NZs)!cpKb0u0Lq}Y5k|~;@ZEXiq7@A87&@KWN)n| za5xSBFRV+2CRmXOkdHRLYkm0paciUgOp1zEK(ipMz&fP6j{Kh5CmNIMh;+5D#Nj|hwtbb|@5vHa3N~NPzM=Pqus}r@Y zz#VaFT4xbHVm=*Dr{jxUU2&lw~fJ#Y8yP+eq6OI*}ipLdeOJP4n6O{l$mNU&1y2)W*7tYyPRN zQfB%&Ab;pQgE8nwB&Czl7xXhXMn_gSP&N9wK5V5JL7u?c^lx}HLd}*A6dw%TX;hxM z(=LL=wrRgS$&6@VV3=min~}0Z=?WA`d`XS*6&}!u0Y$M+U$B35RKLMvKYTg9sRf{& zWgp5R?q5}pK2&d_7^;8RY{FUk;;fIGE?Z$#zkjF-5uhg0n_z{F4{K{TCY2}ZjL8p_ zjWqyOw6#*!T(ka3f6$*@Y7h>F;|?Y3UWDU@!g1sAG8`?Xd18|i+^acw;DLT^y+BJE$RSaGK&ER<*+;XXA%89L!_u-B|Nl`hh`iZco4 z_4S#;3-4!?ktu#d$SxCgBOKHk$lA1(SJ{P?$Zl^eK`|`A-fVw7h(}?`o;|sh54pNS zaa_n*Q8Uf{HSbS_M;fJaRQ@jPRjOj9Ie%h4DWRNZDRg=^?e{JbDOlx{5@m!Db#m8= z7~sY93JcZH%+9-<3wzxgh!w{bi1VkK$Zq$$c&#~dL_mWU(@zJ+jQFP>H{aWiD=M7Vl8-Luc&)$%Wcyx@kNVi7wsr5FnxoNbF3hv zXIH6r)12+uK~`#ed5X19aB1RPD4#@l!ZLyhC;nx9mx)%S=8jIME<7qZ93vW;0T_3! zMal|M`Jbi~Skxp0LMN}Qg?~I&rZZA~b3<@AU0k7$1!#@wd~}%Qvpn__dv9z+&1ST@ z8Kr6T;zhKPMjPFznL1^lPT=yIE&v08N*CrXrb+@q+eZVgR*vlOGCBu(bzzb7wcXiR zX3#LWmTRsSA~);L23ZifKnxUfqh5~g$S(T}XW4hnvWK|ycGUtYg`_guONe->i2h!MZc>42wL>+4?h+F`BH4+!>q4fY*_ zeR|1i<97fSs{8}M`hOt+DBWw}xXX5S9LfKpq(?+{-;n)1#GF-Ohk}nQoh6@SD@5%N}U)Zy4*dvB~8+M_vRBcQZx=P zW)WG}Y85oHW{i*T0afE?8RoLX6J0GR`EYU$X2>QN2OAn-gMW?40zew~()VMUMh92s zo}|qJbVH(eQ=t>h_+qp&+LU?klhEeeeYZv1Me;^ZMfQ=wTT*>P3Oh#2u`2SKe%D8SK9S0du170q6q;1r>*(B zbrfi0pi~+is~fRJ>G-a*of*J^0sGgjM+**#G*5zf{aRz`yM26cZewJI#7Km9yDwvi0zx*?)i=7ya`-Hx6uMSlKmiwjZXu5x#{@ z|1{fv2w<(4zvhtISlESv_2kA7y@bvxl+b2Y5xyrMcbS+of3%5Bld>R6&AQ zFn^ZO#VA4(i5h7JIFSbjcc;X`xodXrw89nvh*iV%1*G3PI@{4xY@_5zWXGbu8!Z|3 zkW{^6aHdTcEqupLCbpA_F|j7LZQHi)*tTtFV%xUuOl;?y_j^v&sq^EiTD5m||G28F zwRW$CI2@r9kD)0|uhX^s_0^WLzN4mXfo883pBuRl;YC>_@75)La2-g)*$@!Y0YXCA z<4^!XuY&5$SaKkLw+k{2zX>~WCZNHdZ$@1WECaga{Rz=}Z2DC<)HWH>zR5OS2Y=zN4~*dan0D?zp5<~ETV&a6mvDVI2(`4@kC4g z0AuEYFHSV)da_m{==i=i@x8HR=?ZVDEi9iOXO<=y_}~Ny#TLq1L+2qxj@H96hvJb7 zJQL~SZI7EE|GP32wfiP}nPuWqnbJVb5%=f4v@m-dZEA>ybuYHcr;s^$JyQu-hU|H> zJ8Zlys|@-Wzk=$dk}hgTZ)QgFMVAde+uVd(KM^>5+!t60n;mF?x*bZoiG}!biY_MJ z&pdp0Jgjd{vS1MC(mX~|W7Uo&_HTCvWN*Qu?PapJg6Ue{G&~J2@#lilFG2>IFRrG4 zB1AiTeIoVus!>p=8HmZVuZCIk$OTk|NUo;ko9$DcBuTs#UC?@r9sINDeV2j)J)N5@ z{Mr)!mCtdkr6YN6TVH)fBml)iF@}91Dz`jP-~RZAUauT0O+&=#j(Ryk7{aJH=h!0OL0UPW%cj1_DsVrOi zX=~Dg{X2%Oz_hXcvkuTtl_fi!=X^)G9`v0d(NOe3Z}Df^z7|($OTKNNlsV)jK07c0 z<^wYcY1d;2;e?MVoCC&XRc3k>s6k7vJ=i;Ey=&5!6i3&53&RQ0#X!)!naw||c&c*S zlA;RFL)u7WyApq{BC~PGVF(MtF)>fyL5S;K(-@FQY_36B5ozTRI%;KDE9+7qr#VzO zVX_D(GGF)Qnh^#llX+C7FdkcvQ?QD&OsOl0-uQv3r@3w!Mw76tijhPI3^O*>*n;C> zlDn{U9E4)AhJ5W86zVVJMan&oN~nSDPm%|f0Bfi_8u!!fu^u`Z^HSaK$BYmOwu^yl z*XLXGlymUrIUq0R47CD4v{>q>RK(+=+{)XUW6g`i( zcNKa=8xc?anP9$*A+;Q}4&`2|pqT9znt+d3kMJ_6nT&n#wJ>SLO>v)`-TS2Yg(};t zQ2LIPWBaLFyCY!qjf(zb@?z0g?r2niBUD}St?HemspoFkTyn<}X!dch|3vrka({NA z)g^_JH`6T>ks#H=o`Vyta~a#%RoxEap!VHyz1zcr9N(6A_2ye63uz8!I{4-*_dz7Y z??M|NHOfuH*ZRk=g=E0q)_Q)x>tIYbCw8v8tJ(wnrCm~#+aA3j2R-ol>r&FeaV%mthbRrn?FufxKwYBfB3@6%WOj}EF1w;41 z{1YBL4CCBn^&_jrN=mH}B!LWpd(xA|8v|j;l$KF~j=6kpqa-hm7CFbol zPFr!r9YL-H7>;b6ti&?bHCPE0sZA~zItz!@3$|KfAqB3?Nx$DCj!>!=dGr`Lf><^E zg+}bQ`m55(1%4XJ4fJLn+_-yTfQkXCGH5!+pCOwC?n>aIF%HdN0*eK zLm!d{VpYD72keoNfHYy(wmSn(VqLD+dmLNarq}5;zGVjX>3>G0V~Y4x42xT+hz!tM zEtd=7F-5GQcYvKX3zPCqnk%Du5g@%YvlP6jzO#(uILfZQfOta6OffB$1bP_mYZR(t z#9-hV%OoIkAa?w8FPIA4E^|d4;$?S|(qKmbZX)Y68+{Or381rMjm?PkiklHO{V0tj zzLRZ2Gmhp@3Hz|3PKaD%k8|yH{=59-2pfo`jiFu~!=BIDx4>Jx>2xoyl{gWw1}lm) z-o8$`un6EEw=a|jd*aexw>QnuEMLr7L1w0tZwHMO-PZ(jBQ9n95N8_>9q3V7f| z$k0aVy_hw4cx%^r(F^;D25KH*m(Qcr0L2 zKsP}t{cIlG@TE9S|6#@PS0O5$Awjdc>2b9k?ZCFMDt1?%pYK*WkG+oo;l-p8fg6hu z`syUu&^7pMpPPHGFkpMswkjzk^eHtyfn>D9q(S<((D{#X7z{P{ff5-MsagNl@PPdSK9!db`y)#1Ev2&xfE{+L=K%Z=-9HojRr`lCgLvHv81>1qfrdF}Sh z#JXhBv*^ssTWpAXPqgCnu++aWE)mkd7r=240?WtlGd{8#v3+p9R$;z@6HH*wFwVrz z&}ZSJB5d6z^5FGw3$~i%qs`s`oFiA6Ba`%vc&UYMpDoqL8}FB7AxYNt_V$j>tgFA- zV~t?9!lQ$wtPILId7X zLc}~7CDe$uEqpY#;2}((!nU|->HzzCe$TL+3V}>a$wQ7R~78R z01}Yd;-}7qSDsn0SU**PGz#qtx5fnx8xO}=6v*rN#^(8bIWRSIZFMOs`Fs`0FCEp( za><2ra}TGdFF3v`)T|#Tr(xUP9Nk|;VDXEVO;Ahgo=u8$;Ia;&M9w2lJSXu6RdP zw+2D84JZc}*^(s?8n?N$ifi)0GRk1S%HLGfsA7{F<%8%ZjPN^FNeiiX#gtuUC~HKf z-1)9*h@ia)sB#Viw%}2OFe#&KxL`341UHe5X2tXVi{r_I)MWZwECvHAbx4`L66eZ! zO_}R0HD7#X3QGvU^3h-yqs}%xe=Ba7Lp@)j`E26OO(&@d0G5JM#6KMFUhWBSiAHr?T*P>Ez(kAH(%C zmVz6Ers`*5PfaUIR+2OgpR1!>T#Up~_x{|Zs}Hf$P{Bn;RgtFDZW<1v$c74!xaAgB zOD~?_aAU8-^UC8n#2*WGBfhTS>5Tu*M zN8e<2_0nCuIX-x8Ol-0cqtDoUpyGA(+Po~F=6;iptch?x<7p(kvg+GgNqxXZ# zXfZngK4FV9vuw=V*wx`XhZeP@?UlDHM1Osl(ML<<$a3%N)4W*@K(^PQ-x3UTa#D?4cC;W{A6EGCc%O4_S=Tg`Q8ALdtafH|lS@*TBogYh)K8 z5D9Su_&zZ)aB}(CbJ69Kdio>6NwDR4(?5r8yHKzr?m?5*wr!lE z7^>CI)5KEQe_Yvur?Mu+z`YR3#SG0FJAA5o8Uf_4M6@5jlwo zRKr+&3vx?IQva{(GKXVhz`NQN4;9jlxc}^?5`0Z**9)eY^+uvAWszID0Sl)Dm#mUp?s#+Ss_q3$JOzct0cqYcOlk-3Mg7>D9i?_f)~lBYg(9v05}I7wKy@SaOPg`vIWCHXQX&Og zFNo+X6x>GZsf3cPV8$%e734 zpYPBF;=9m$Is65FM+>FIEK1{3AwVt~Vt71p18D@J)!$4OkuEM3K@f3Bzy6H+O|lDa z4*2M?Dfu)PQH-Vw`n>u9>DA6c`UtSoMZQx73FESEQz=ueZKNcCrm9_RxmU3c5K2|Y!uCvyoHr8;u4D`rOPM1O(f-tJ9j!#ZK|T9$ zX`f&-7WGJq;}%@A6)tj6ZKI^9pFtG-q0sBOx|Xb!#B&|55-`E4#C-`d;i=Kipm+A{ z%dDw{CgUB6GjjdeuMUen?{gt+Ms0la4iPlg?^|xVo(o36g&FRyqRc|`ns(CapWq_D zY?2CkE5SmKxYp#XpD<)Cv^g^jI4HA=RLnBGU(eU>)lO5;E2C)Zn3Ie%9VlX2Z>yPp zxWwNazuvdRr|uU6hUpbRL_uB@3LByQ2%Ho?N7N7re0-)+(y2nmiG)s$W;bpt!Sqn; zp6o1em3c;hFGuM3E2Q~AeZ_yTd7uYG{K)`UzNhA1a1VUQaJF6Qs(M^yNo?-V`6pRU z^Cr@lv#nw*@Zl4J2P+glNeaqru@=QHjkoy?3ZXq)47W2YFHNC(ULQ?v@Rgtq$f1@c zGPF+f0~vY-XSH?dTE1-kiwjtf>oBte= zeVn;zms7KLu{&9n@LX7;jUO96PRJOv&Ssc|G69~7 z3q6MmSfQxwx4uGbvMaxqD@uLU(~AET$lkV^YubRN^L*omz%2D>wuHB^8h3VLA*!H# zC%uC&b}_`6Ygnn&DO9cGeNBy5uw%9$6--zh{xg?}G6eyWWmVlCtN4213xF?q#pz}S z^0y#V3~BV=z0@tM@B2RS+VZYAk2|GI`V&YwaKc{zxlDVGKe!M-%ZZRT3@2Lj;h*u= z(e`h$KpU-=woj3+ZLaayZG66$8r_}b0|_#{bx6=W)jT$~z;Z*qXZ!33Rh-#a!xV-M zG}VGaKIH)kCnon$xbCp4fl%WJXO?!`PiGb`(KmHUB*Gg0gwP=CDB^JgOck5uANSM7 zz&k21XM7Ly31lrjJq}Z9*}VSS-SKp)Wk8?RE@b@|_Hk-x^Gdu|vYUCCShzc&@jXFb zT72YKU@lwNibHt$t#!$CSCgvgtb%W<0Vd-PTGPv6$0kcry5*ndk$A74kb(=VOZ)F* z)LuzvVSj*{;^5!dxdXL?i21*jK4A;2z``pYsnFH7)q}7zsZ+h+SKBw)lLzAK4Scy< zBKdz$ZVf;gBpQUZaxRpqsWVf}mn_N^qYghzGpJ^y%87zOEccCZ4G+bIJR=(751iOf zLQ)IE;zIJAvBnALP7W^So?WUEa@ce;L>_y66Cm~-2g>e;9;EUh zvQ6jQKSAK=BzJnH7`kW8tF010vu-V}<;C13qrPr=96+csOu19|6{|O1oa9U64Wk-BQK&-zNT$iR0zWj zL#wiT?qwW8wYe_1$5-j;-bl+)&8PD0V2`#%i>?Wy=ApG+GTU-$U1}avPdh$c|82cM zEwV-Nd`_Xdt~p+%1IR@S8SJ1aHqia2m7!TeFwQ#u_@jD5xj~Y}VkO36Q7Yc_uJ9IH zqKodQ`^}kA9BL^x$`MRz7Wye3K$yKe)ujfd3_B^s*w$#$el5xHgp8ZHZ5l&A)TU&s zYJspMu=u6TLAnYyZ(XyN5a_n3@t8Ct&trp1B}qIu0wO_%DOe}yAqpltRCsBob1@~r}DqwY@^uDdlQ#FSZsiY)b>oab}L_=jN5>(eoW2~dUzJD783*BtzL!mP)=dc~SGPgK1t$<$b-orgDF7Y4yI{U~cty>Q z4*njy0UxeanAbYXhs2_ff-TizZH>hgLW@;&+AHs{OEjPaaKE9X;mKA*Uam_@Oa(F* zbx`;LcGa`koS#pJzB`kEE$ix6mbJ)e?C?N#x3xRdkJ(J$J_n&E?(oRHtx%8A8ClN5#}f}1BRxP z!0IE=!hb&CAT~1gF~l5noy|qha-+NS0EJNjMTJNhV3@EX9qp;GYV<)|RNHsrf4sJ7 zsH>VleonE`Oxbn6Ldv#3ipiW+Xv%Z$l^)5n4`;w+H6@-ZG`Qm7X=Wf_n_X^~>2C)U zQsh^EQ3?h2Ll08MQ*c%zVqH84Pxrqa+xuSvoMt|QRJtclSg;AGs~rO|2Q zg=WS!=XisC+w~S|)u34_*QAiGdnXCYb?<%e4h;_v*LDQ>CKi*5sYImhbggwy&YxW= zV6xTXSX;VygB!7P2bziL+?QqQ0`I^$qB)tmx_5*}O(`&D{#k zP+yXg;GR=3$gHglG&EH2*~5W%@O+&-diod{!5y#5ARyH0b5NE1GJ-hZ0A3(L`rJn{ zwE}weCP9|7Nz*1Hr=gf_8Z>g5{}gF+th+?)84J+?b=5ztNc9M@25p zO~$y85@8!u2*{uR%8U%00!g^@S@J)!be>Xf7g4FS{`)0G=sSWrT6SGNbVX~X>IvaOMK zjAX}e>Gwj{jz7i9&A>IHf3nN$A23SXLt-Ab$IPknq#={jXowgiDC;o6LbT~}=~86p z`s={?WUl||nHO+uX;bZ9rwJ!R4)qtBj85Pb-V@OTisBba^tS|CPLmCndWeAb z*J;CwMA3=V-2DMrBFtzn;dWai1WRvMnkQ5ecMW}wJCAOc0S;_kZRsJgq!=2OvGSaw zm^EZ$8t4DT_|3YkGb!vODYPB@$uZxIKQ2I+Egw&%Xx_Cav3#i*)tc{6Jz_s>In;rr zMT0!{y23dB8+JX4l)J5PbP0ckQX*n3L%+g4wGgVaxaWPOV|eHLb_Vz*q#NkA=&WY( z(*Rp_`!}C^HxQ_9;DNXe)=Y7V3Q?(0ix1{EagG7)iE{aSD^=z+%?;L$>DG9+YKw$h z0Ycp5v+1S{%FAnPp>*u4`+U@7`*eE2-$*r2=gGqy7Lagif#UI)c=`j*PLksj*{i*G9{Sl7@BCOALCay3M z1%EV{s7e}h7HM?4ztQv}N?X$xA#&8b%sEjF0sOtG)^JWUAeOeN9@qVAy%f8E?w6nw zV@EU${NDRFh`baSI2r%|fCijI@XD0-OM$~8p8iAB3Dd;=H%+n>lGwF@Z1EG zjuKJu*)4Mxoao`eDfWG`D7JdH7RjMr?1+Ju>uq1S@6Xg1qCmcjCd@FJ^l=WD!0pU! zT=79G28m9_AG#!}OevAkt&zY>qU0-aS|civRf#OT8 z^H2T+b&27^X)+UrODCT`eLRM4jt~h-NvpB zory~WJ2K>IYln{T!ltHcr%jbcvvsnve0Z~UK1g^0$3sWa9GSrE8C$=LDRPzau&I(2 z@hfjGzE|+EvCy@(i{oeHxHpcDHvV=(h7&`QnxFTXYhx!3W7^t2IeI#}a{j?eMBcwT zUN}NMOHLLdGk-0@c^JOYkPSYTj;&#RBJ3?ICceudNKlh7e8LYHa>`9 zZA+BE9-UQsu?8)jl)Kd;>Ff&GgMqz9*43l(7ZY3-3;d_BnY(_eBsOu`pX`u&S&Ga~ z$}M50vq##AX}?%3OKyzMj4@O`dgbLAY5?UtIW5j}mW3|w*=h1gi3JYC1Ez7@ zxY-t>e8po`?4_f@#%^E_YV~z2b))uKHnRq=~U;W}Ve)T~rkFgi4_>jsApUjcUSQ zTEfpcMbpIM5P9|#Ra2-ShL%vP?hf}+r>SoCq?f6b&fy@!r_Ru8B$aF!71T%nWdJwbc5?^hNA7BWo>(xIwwL{*m9oObav()pHEhf%qtb4PDV!lDyeMcS?+&^j!3Y6o z2|;WO?(GtcZ@-`iw;h$WE!AexX7>Tmws$g9U655{Bk>)!ror$N!3NR3fbOYXwfcTUZU2;<)l`X>LQP{s9zIoTQy_{RUdRy>;u9U(kJ!`7qa1Sn%`rDIf3WzJdi@Ur&k(=w*b zQr&pWbA^E-vXsT4dpP>qbeGS{9N4<^{!W%fkpraV_3ag9Ku3F}MRb99Or*;j zCLmGqay9@$H@Fe_4L1)Sh&9ssnkhVwY~6^;6v_FADOT*@8MHOY++qi4M(ZmBsY0se zn&4GR*Ckqm8>4N%1z#*Izo~qdG}6h%q`?L>)r~rV&Y@CAli*blUombDsYn8pm0p?3qON_6<|8m`yxxtyF~cbd#`37=CfWlT2?<-vAU5zkk`-11{;i9*4OrE1DSJ)Lx5k|4Ws+%Rx%bL1^O1N+KE zQ$-S5Hq%Kjj9Tm9e}nqwJ0fqY!lDjgifcKxqJG#ImJ1Wu(0bbjIAL1-rPm(-%)G$y z8BGE$L0dMhySCNOs8iU|11;O(|JC{@mmp8Z?sZXo*BP1qK;^(8_8&SZaEA*H3igjh zKP-Z9xzuv+Orh4E%zJ>$O5`!i3T#B7dfQ)^dRcKrPYU z$g!*bZI5;H0;fP}<;}~T>q~h=G@Itv{38Geb5tW}p*l^X2;UsM%moG!l2U5odGcso zpy6kij~gTaXK^#OUX~iytn4S|YtqkNj7K8QFB2qxmuqWVQ)BYcOD#W>Un9e@CVX(1 zs)3!KQXk#V+SY55RnlqWoJBL!cEY*f9`#ZVvo|Ac3Vz@7Fbj?{L8;0W6C2Gaak>ed zV4-p^eQ@C}44L{>B^SCSaXm&VREPVx3S!!pa~W#PCwEVw!lr7XbLx&+PIQZ`=)wdk zjafbz?lAA%l%ZSMsH!Ma1HK{=_fW7K^H?;k2U8QNe;$ADIKYR4@5Eg{?**#HhXa?O zqt1vr|GOZF`%ls$OT^?f0it$EKEWMu8-WWQn&W0*RU_2nX+O9u!+gF3!h5ygFAiV%ea zLcWA!d$uuV{q!G1`U899lHda+3F_g=&7YcbR(vsd0}%W0tOE8069|eg5+)h%mmk)? zE{f955%Ry5w)Ts;SI}d1cSB-fE<-(}W{_WRg^uWvbo0-_9_9>k*-Ov4e*#yuezMYo z$hGaHcq-epT|Q10j^oIzO}P~gAA^7yJ!nAK zlXBLYtPW@~c%K{JDDbHdZB<+9){czuj2z)tXDmO4cA0jUDKjq<;)GT?7xahH$Q!2% z+2+zQbN!wjQ9J^P665bugy^u#n2XStW&gFfyK0Lz*~D7~JO4SCzQ&gbOx=BZCjx_~ zEi!z!l{@4UWLQOA3IfvG2JCO6vcu^rI$>PsxOK-SX+3VuRgKOhoE(_;;H*Z-9~2Wm3cq87u|xY%yVy`u+2b9IWaUXPJh-YbG9&#jS=tN-@nnV z9D85Gi3JBuf6H%R=i*-l{_T>+&Cm3C^uEBdyY@iR3VpZn$hgiD9(VFRfnV8$Kx=TO zFum{G8dIw^vE62ZvU7+Gb-~o;+@IoYOs_oZSi&cIep%WCac!2m0+?K0A$sTJ%1jV^ z7?d*G5-+D-~f1cL@_FpV+n0Dt>w){K% zJ~Y$r+jwR&EM|yXFKws?cu3BxEoh6>R&`K2xm`kZGA0N#fSyxp&IlOT?7w56#L;ne z27~8Bw=xj>h3>7kg#xzAzO-&Y&gBhXmE*_8K1{+f8*m0(Ooik6G zGAXL-p6`m$ZA;m=hPRwP&o;wt9?NL@w~v*qZYtEW6W97`WeXVHhwu$$>drNsuC8iW z!<2T8&E>6tDq@kcpfv}f;oANbjSL{(gdgOsmjo{U+iVz`#!Y|q^&ftVfsxu_Bhtb1 z0(s1j{$l+wv9KdVhVAAhW68fXD&Q#h>M}6M`briPRj7O4O(R8VM;`jD$VSB1LaPZ3 z#&@a7tIJ(Sf7!}d={svkp1C-3{jAJgw^iwLlxs``Zj^*oUzZ0!W)IHG7S~y2h}Mdb z#b2KG5;MjBh3J+JzLq{!!+|Z!wi_n>;h@_o6q>-MOJcrWs+^BKJF|f-cMVOPlQH5t zNNf6g_z0wj+0m8|y5qD=2PUZlBiy-jzH&R~#giWkiqwJsau{j}-q*O~v@H*4|1ND} zr*?x6OwLF`&m3_1eZ%R@*&T?lPnpizt*1m;tXex9=moBj5-?iMMX3##p-<*Va-!a| zq`Z*nDwy}u;ws`VU*6v;r*i}V3`3z#3zLZ8DAx7+W2 z5tXkL6G{qwRs9ppz^LJ#PEdHF{$Q-(QwX07jGDNCnP`n8nj;@K96O?pFJuPqt{)h> zQKonDI3e3}%>K7=eBJARLJyN9624W{XoK0#Ajs4Nh`g*W1DLlK19;|^gA_%ja3@)0 z*V=ejufVpc>u)l+Atei*3v%ak&cEPJe;0mxtS0?})YW8%)a4Ro3N%0h`kA9o9QM@% zeRgzbai`wu3w;p+>?l@fnggc*-1sep)x7PH&m0U#nzD8a+xL|tAi+>1T=Ly9LcUTH zi%OqdS{StbwDxrPM<#hp=kR5qSJt5=Y>^I2++HKplyjWq4)nCNRRJqazd~RI4_+j? z*k}zOH0Jy-IkM`E`kk5L8yLXraM0Hs!%gB5qA|-8uHmVj~o*D z1#?L$al#N$L`UQm%24XKQlV*09u;dT5C265)32ULfQH|+4Ex$linqr@&SuB$XZ=>AzV+QJU3jazheRESvH z6&uoCd6}2i!Y2IOeCZD;IbOpC>9zXlybv%&LaBF17WM-CoCz8D{dRo+2#{{;*=9G` za8mlWLl2$)Rnu6WN+GPR(^xa03zQLVSG|>)d6=1tIO2Vj?3ln0iWUdW-8%KGzc3ny z-4HLqcr8)u{2^0EaaFFJ*ayEA5)m63gA*(_*fa;rEv!4t5&eGShr=v~>vm@IJ}%y$ z0!^0fxGT!E3Wo9wzNCh|>uqL7yrlYCt|vvbmcs25y3v>u(<+&QaEOaVzc)F z4?pad9C(CB@%0vF^1c^BzwD#nEL9Ti3W&#vcQeidb@Je^v|MUA?T=8m)|mGIkOJ7C zd8`25Ol?o%;s>oi(8w_^5fQvZCG-j~uCc$Mm9uhsr88u|C#?x}4lN11=Fj`xsTz+v zv~CaT-OaQ+OgA}2u+k=g+^@<%SeX8ezCutb`4iXks-nBY2?bi$D)Um$H*~M{D$S%@ zQE!+7FK*KrFw)Nw*WGnq4s}Bi>Nr2Mru70x>e*u=>=C9r8!^QFK;YNCKG_WvL5Op5 zqCRaphig#_gCpHhXoaSs>KtUTTc8LSl);7I*GfxE3DvZUecdQ9g>1g6bm!uQelPq-t}>FcpxQ5U8Q1{<^bY0Jxy>#b zW^?PxOOwaOWqny7=$!;t3bJP0v;BkDF_8~A<0X*RqQNvy)KU^R+*u*IQF((PfSNPR zz)GDN|9~+%DvkRmHErC@Td**ge|{Eci9)+MG@Vq3L{yN16>O(KJ0&VR|NTcXroLY) zlg^Yb!2-G6x!{TF1)+p%?}o@MRV$u2Eqdn6osby$xPmpX#4o8hp-{_6{K1gj(>kR5 zHYLNbK{&M@mJ-ql;c7zB^QLCgU1l$>Z$zrgw0t~w&E}e0MR(TUIT?QXR9X81`b|sx z#2CGBShv6#k_hnwoz{S>(SVUow;2s*TQDdat+lALiimtww=ew7m+mM2rwmRJ#SAM`y2sBG8Ii@!PgYaRa@`F*QI-} z8!YD}ebvjaV%nt(zF@j;K?+ka!!0ay;U27b{-Y}Q-iocw81yC(*5CVsO@h7KILZ(V zD!Z76WzP#%#+~D<#uz6Bxo$jYL;*|TgOulfXj&4e$UZr*=*$AJTgJ`M9M9Ci^3p@p z=57jQy^k4Qb+7#4FDg3u7y`Wu-TxQxQv=kU)D&+VzHMaHp!Ff&1P0RngrYo~A93xp z_<&joEU=I~%7BbbxO^#%IEeZ^!kc@T3CAkuAxOFY>@7B?4n-(DE}Qq{I77+Ey!@7H zAoKWN*~N!Mf^TNotyt|P{IXbtU^)nZ@r|3ovk`35^~zpdi^Mr}faZg+4glTPcE5^;FEPJ@k|JJOQXuV-5XoorQ6*G<^o&bN5gsj~YClxM z`q9R}8yTO`o`x%0H5aVehcm{x#|Wf~7n&)P>XO zLJJ^2;IDqE#$j;^G)Sktvt|3UzfZ({i|--PwEnjrJdNJqibVdiC9K%Tj%j_G49jr` zE(%Eq{_Pw7?Z|(a9R(hG?mB`?BTiT`I>}FPK)xWv@;%f z1&7UFJM1cnB6oftw30V!Z0eW(N1Fq;3~M;_k6*MwrPm{A8=+W*VdTk-5$iq1L|Qd- zJ!f>l)K!*fs&7hFMFagY2oLrsXcBfs?KnKlFV?K}RD4mCNoEkl$xFqfjhGif0Fpo! z``L|>kF??HMMgJW(6g_)J8f(|J~>veB{oyCI6eZ3s+mZF0SKBvSHladH&j;Mv?jcb#XOz@DC;~T4Hn#onwU= z1l!m$kq;GG?5}?w(PrY+yB1sF4%KH#_I`4+TZc&KZftj%l4-TmsAI|XA~6}jch~bs z)L)@2OFP-n4*A%xuKc-(um0L45Z#wVJZkG@y!tvTPrsK19hT9mvv?8o8n3#&{m5~A zEoHJzEA8yc?b7CasMgJ;7@^q-u8)uncI2Cy1LGACrpu$s(G$d@Cp6o8Zcp#${y@g$ zp58oRC8rps2*hw(JIaLr)Pq6>a_S2_n^nZjU{NQF%>KY-aA#3l)!kSfWVNLC!GOT! zSf(4__>BTpK1j#?LGt4WFKSSq1Lgb8?d(fl!sv8N9uuXQCOZxZPU04kjh?&2~#cInWCUlL?BXJ=}>C<~|JsW$24Y3Fc zN@`{UasTevK(Ai32)>Aq=r3*AZH_PLd;_;eX!C~qx<(VnJZdie>sHU=(y`c2^k>i{ z(sw5@2IvvQILg+^(NYQ>1-nZfy z(nrBe>^%>OZs1`I2S#_7ZY!I}(3il-@N_vq%JP>-T=9h6_j_JZn{WiLz8i{RW3h6D zovcArF3(%@n`w5&ruzo!F?_u}r6)P?CJ?#I^yTBL!!1Z)G$=_AV`z5^?^zqq=ez60gPzJdiJO=KTq{I3 zWnB(JARZ3JF`8^!3UB$cfFAcmucZ#fVq`jkP3d(bHN#>k^94JUj5_?i65q?2`!re} zQ@}vE-(04%G^ExlulNzP9g>bc0G%O1s8^4|XbII7(5MPD_XhoQ%pcZ?)IBr9E*%N| ze6E$tB;WU4%#9IfB_9-~O*(J!@kW*KGZDXr+;1Jm+4pLKv~ZD+7P+Zr6s#Z>1C#t^ z9_pTVOr3zt1A%w)`eh9$CJlo4UT!5jrW|={>1?#hvDgffq=S?wJ03OyPYNu%^ z6GT(d*z*2bFhf;Aga57{62~_!6Fx$38O^nOrxhY)r{Q=e6>Xr9DSW}Ad(A+v>yB2p zstkGY)cGTX+U_o9mXBmCZ6}O4QZc@;*DZ6nOEDPRNYU6WP7i_b>5K6HrHoS#ox#tM z|3@B6W_px@f&u_Y5C8yC>a8<4e#?goI0`7@|B~()*%)E}65lAPy@lX}E!^(lSrFj= z%d~9xfZKrl2c?1Fvi}F>_<;{2{TDTl1Lp?+50)l@U;m$G85!VMF#koH3&F|$YnHlQ z1n&J`P`4Od9r8ceUI|_cf+|%YETigH?DhK}-Ocy!BLo0aXARNNQ@;(+;8L@y!7*8u z6h>zx!l9VkTK5ko6eA;;@9*~y(5=yvqTu1_9^h#oqNI~r0sr?0{EsP5-K_?<{{K7o zuQZK=rUC^NfPn)D{_7kAXkcXG=uB^KVl&yLk(fEz{?l`&*4}yN0`XDTkN~ZoAuX6J zjz6lMvyb*C@vpGGm0V#Jlhn`T)Rh+3T#m~dd0D1JZ~@+dcT?E6+?}N6%LCK<=#?)i z`oFylGa8=nri(7m(PlmPe3;ug-)nC>G0VU%!r-ry7AL|(htuNH9K|*vsF`fYaOn^OO~6qG z`p@MTC(4TUjTa45krbXa#aAh$DvA)9JkOSB$_@(0rpke1U%xoX>imI!&<8>HcKiCG zT%V!F>Y~Ky>|oF0L1haWVi8N^t}3q=)+n2-%cYvlv9&3RQ5&GUYanU&3yP<~&Fex` z97TaWzSU_>4%t1S0Mk<)7DstzFK-7_Q!IXNY*oxN;yFP#*;pE2;wZ3$Du|<+vje0G zoDT{oPzVarSK(5oO5w-t_Cxosdb8RR*m={r%c$OL+D zwX15dgOI)|9mF9z2Pgw8qQ(T^)o}u zCj+mdY98lk9y?{fBDKsT{bs7zi~qbs;{=~4vJK5GyRA)lud1+}TWcJP&Z@;(A%zJ2 z$Wz$*Sf1&-#NaY!YbJkm3vH&0?Hxj#CU5J4wDSTF29M6kS zGFf7sPrDsnc0m|_$)st>TO$WQLG8^tUih zDN{qN9h?K_O+qTwODj02ZInZ%Tb-!C`D_%`6dq$EUMebbq z#!Y8)ec&4|;7Z|~#uCA3G{j_5O|6>Ax-;v75Ke5Wf+tyj&h;ETQY4!&&^+}jwkW1? zAGL8l1SP+JKhDsUBUdxhWIj+=11aPlVg+>5JR9?N)u{rnSKc$rJc=SY-G1I={t4rA zs2@T}wn`!uA&l0NQnT#IFu0p)M3JN0Lc-YUagy^jtx?lNcyNF|o^$e)Z_MGkQ!cwE zEfc@ZK9!HTWQkwk7ajA^a)h71#?d&azryJy|V zgEUY@XscSuUE!Y6S=eFer0`eFxs-0U7W3Wye7WQ7fBo0nlqPDzUnex^cc}Ff+yJ2Y z0+IfI^P7SG9=HDW4t|eZuNuFFFOo)Snji@pL5Z*6ive>#zM-fM6)zA$fGHm!OR~Y> zO%QEx08H>EOcpeVU{Lrad{M+EhBtn&;0FSrh1ehfyQl>!V1Q--QIbs*Z6a_6`h`XS z3-JvKP8I(KzCwRNs^~QU3V*c+IRh`d*lGs(NOJ?FaIV(RYOT1z^&{nLC5VrV4J$+a+Ap{ZE(hesDPkQ1O>z z;C`Kz@An0IzcC!RF#>?56DxoUdd-8MId&hMb}YF%RCHZgHb3s$m13U*p3&CVtw4&+ z=>R?PC>d`n8K#uM)dHqTBnmsaxVQ6vcEwddVCfXEux=INS!>l->ih`yXa5pE_Oa?* zWg3d>L-VZXdrMBvPLJL5y?Aib3f|u0b(XFW_BI4%lS{o>w@=MG_i=Yg;)BlBm&7f~ z2h^EmoC#+8+@>nO%fw)xYiH`5Ci+O236CGb_BwTT>tNWm<}0yIZe}Uo4m){&ZzzX3 zf_TQg%%|I9H`Gl?Y~`ELx0Cv;@x1^a2>xIu{h(c+sO&x@0G^X)92IxBPK)7gl=$6; z=Etf*lK8><_w*Uf7nfnChr^m~%5sy{kSEf7aD#efYm%SR6JOyp&kiEX`bX|2@ElZ` zZ^US;(=Rvz4-@zlyg^v#iUFH{3o>!61?U5Su$hhC>f)l5>Q=QbgUL4F`qLfmmHyU%L!o{iP;Cl$;s(7xZS(T99V()XcxGDO zgM+I~hYC~@*yMHAvnt90>!jc{!PCgSj6*!gwG3fp1y>oCU|c01@}I$f@iR77o@8Ff zu`Y4nppM+W7xlvfms@BDubm-CLmkUzVb{=PHqb#O2By{CnF}p#&jHsTD}j}FQuip7 zf~xK++RIUu%TC zlPN}CMMJ`?nm0xen>>XexIGOSA&gvF@lW!ew%avDcD- zt@Wd{4o1Jz*A!%OIlQ(Hm%OS*k`qr@oqMYh*)e1jmm!_T>Mj+3ySCJo@v+_#{88iz z@fpWyESrb)Z(yShAn1ineCfCCH|*P~56Ue3c51Q;Fw1Xz+;mxzg?^XSw{L9UUF#<6 zCIDeF2Eg#6`Tzc=+`@k>fcU*bv+3LJn-+KAWh&PH5&o}l2*WVnerfTa-=w#_lMIPc3{IgK0;2?uQWQz@u_1{Ur3jaDKpm)HL!sbu{zMK$c>%jY z;YFPflJv5xXCmt(w=cx&xQ`k4SDD5EnWie+y{fkZ#J`C>SsZq@HH)swS@JvD9_`AW zeEWs*ts<6xy*J_G_I+Ajw5?QLN+_(#ckDK%$khO&0JG{gdWKay9&;A|sH~o^`Top~ zN3$Rl=~8~QgAP2m3o5l=XoyiUlOjt>0A2)Ehf6#yD2L8B&fAa<|_YeB-+`!kT z@ZY(C%l(7iZs5z}eNwI^@VfsQ%a-&S-0Y1oljsby1g%3!Wp)L6TEp*M&`XQda4 zjxJ(x1nTb4a0+_4hlFLx(MaYrEs<^iWo1giVBRw9EWGJrRwwGx+_PKZWZ9T}|uW@NcMp z8AIqKov!x+j`E9(MXY_Goh})zL_>G;sWWdbjk_$86O3w|?!^1TX2GvGG6qi0dJmKQNoFnv>g^byEHS1*AI_=hYe^nz(@p)+N z;X^)^a?9b27S*_S^}O=~tGZHZu?LfXk;7KsX67oc>9c&@)%~ffDnqvnd+LF(yh9Q$ zHcp=G+^m7eet&hPb8s(pc3unP5XPR$)s%J(f*PeBYagA4u6eRWXlAW2wzJ$p<~UzX zVtNY06fsz;p(h=&Yr*eO*v$zzP95{QZf&W5AWg5|NwZ)M*CTPD!5tIzzd=ub#9Oz( z^FMBJ_gnb<4;04f{{=w)b7g?=!!Z0K{!z5%Pv`$`fP$G2em*2Kv_zWqlD z9*VC0R%U+ikN@?90(|c8uvCeoUs%cig~R(GBcG3+nz+jP>f5XPa~$?fypWA&-2CFB zGdKy842r{Faf>)!3~}t`d}HW;Vm|;BkI7982nVrAsKrSS@C}B)#QoRC1F={V8<<>- zcR)x0t61D~V&lgPr2u^Z^pB~9oB-ShzX9R{E&{s5kl%0%GFn&;I3u6}3(EK)B24U4d7BFfIz2+)4~fWm$8Ydx(DZ^j+ERAuhD#yvpsRCjII zmzl|T4MO45NfmT_Z+@o?lbY+JHd}*cN^fSp$zsr}P!JK-+yTxY!$2MlV*2jR51sVW z^$QZK3i#U%9QEZ6VbG!ad1wb%(=CL4on4Uur$Cu0{$W|!l9x_<#vV`E{cQM{lKn8UeKoI zZm|WsW#DozM?7E68T&-8SRC0QRty;B`qjC)8fUq*dlynm?s*C`@{-Q^`heo+P(m}S zxU56IetK1Ynbz`+8b{gT@k3m+(}hDXx8A}Z431Q`3AyHf?A#8A(_TLj2hz~n&QRvm znryFO+R9Lc{_Js>8zjt%;3Ye~n(Te$cFJ9@WE`kxXj@;R_*UD`m}c{BS%-hB02c6I`l&)r4^%Q4U>6qXkA-jceT@hHF zHe~kMWxHN~&vG@Xt~<7HdYApmh!kFIPv`?ENBlrNMrP%XWb8*;$%Gg1m{Htyy;reO z_VAT+$xKq`+Ut&Ps_=H2%r!n%2?ie4v4$+#XVdG^TQvZSOPHZUqGzs_Q7Vc`g#3Mh3osn>FMJTCm z4vUj{L@k<%Xy*9{%F<|r&bSFrn+TwOP3IJvUZ!zx?vOz^I5c>eNmPE!vGYuf$0NPn zp9GPH1_6ku+h6y?Bj)&EciP(>wSodqKk!Po%HzhZ_^nK@LOMP(@lBId$-}M`uVC}; zF7QNu5~e#|Ytc9e;8c<9;PhOJ4U|ZvANA#>P;EM$E#qQ~|2pB|{Ibic8UQ3e1#$Cc z4!nH(oJ6RvP#WMHkpB$6h-e1D8nvKe1R(Vl zhh|<{8^A7rU>`s?{v}ESbd2Iff=BQo*-3JLG3N(o4so zzr+bB{5L3#fYZIq2Opq3xd{K@6@Ng`mwf;Tfd4WF{N=>SD~=vu8wA-P%qAii%VNQ8 zV(}pGV8dX`i4$z8NrDpxe~xZ1x~p7$M`<=?+5Ri`zl4n6MeDm}-9d&ao>h+hfbE@s zUP&#O&O0!Tm#U!-qW%#kz6-IlE5q^)u~Z=R6!uO1g158eJ!gc0Tm-t)N_DKvF7D2H z!;80AgUaEqU@nr{TEYUjCU}D?)h;BM3i4K{%$iv&g@cp71>Zkn?`O*z#hlf@2PmxF zHP`}Rc9;pem_I@R0N(aLom~(!Fu8qygb6O6FAu;x;Q@^f*>3>*7K9i6hKSv(Vn6L0 zs1gvDb8<=SC81l^9K9Ooe+$kb+V28)Khulh7 zbq`NkAIykD3LcRPuaZy5-8rQNJ2Gyd$no;&JSk5BQ6sZg$!mD z*gRd>wl}eII&0=>q>GA|LXIeZ?$6L8sbkb%^LtZbMy^swEeqQrRuJ^Lo?<93;m7q6 zX@xf2J|5GP{8I|Gfxw=lS( zvfcu5;3HGtG9C>0^agJL1XEG|?2bVn_Slle!0NmtNa&G}8N(M9sn$?`%ACUT${ra8 zHJL*c4mhdn((38&&lMV*3<@#V!c?eK=bxo_*Nkg;fJM)#&)GGx`394o0!Jf#q3%3X z*2Q%@@3qxY^)S&|cbJooP+rXEc93AIArLo>6#2#s>+up^RgSm@skC-itBWD$0?qQ> z>3Y`YLPY#xjIY_c<{KD)67M&xh5-$k$C$aGaTjKB!c)q9M*vQ39D)QH0;lyo3Mq)| z3Y(w8bel*@rjp50t}|4$hYTNmt;!Ytf#V()7rGb|E6wlqX2yqd+vw_y-Y)tYSu14h zwanJw2hI)Js51{|$Y2!w&2mU#2>J6fb3z$zf-U>}r!iD)po_{{(@fCvOgh+|8CB)xzS=nvo$$t*nqB??fC z2$n-jP#jdCf2TWtfqYDsL@c0sF#w0?(ovFZ5_l1j0A!J5Lr2S*qBocP6zlj5yW zh81`>m)x!M8`43apl;Dniwv5N0O|nJ{aQ8z^Up|U!PW>#0(<@rb@1n5O1ygZh8_D6 zK}WtE4FrZ`*%F(YKr%)^BKq?$F!<@d815AYaM^p#@Cv;zCWyOPe zOU?4xL0f8nYy}!cR@o7qJ2DW>qkHE|HMty!!Xcvk8QRh0plF*@sDFw`)AL8EB2k*igf;%@29JlC-Z%M^_>-k zzy}xdVY3)XtPdHZz$Gjfk-`O z4HDrqHl3f5J^*@F$%OCRJ!O=!`+PjvH~Yeb@Ew7DjL*8V>oh(XovGhGDQZ zHl&x=(-$ejnJY}5%WL*~$IxGUeq2M+7*(16IrXpvK>f41@p>|$_eYb{bFor+{ez@M zzk330$>}<%42zDkDM2O8{wy?7Wzqu9{2!Pta9kQ98Xscci%_) zB@0o{AkwIaol)N^^QFuw!HcNA)tzw*d5UJVr(!zA3C(1lIpVBy4;X)~B&T>=?UYNC znQXYf<_=AFgfVJ+r(?#I*%QOs7zl_Q2HrCCE^lB5SGS3Ab8ovn)-vKAzFxFJlw

    cQ7j+dxDY zxsg$(IH|3ODqY19{XCoA<086Hh^K4&+KxvqgF}7g&tZDJ)p#$jWVKRGhwZ!_4RMya zt+tCQ_B5_DM#8z~(BD*(C48v56(@y%t$XA`@1AlE?noTH8_RJM-@^E1C!;V-e*3AbuYKhyr%Ib=Pd$qHhdY%_&d7*KL8?tGmB(SnBPzf>XpI`I0GOLc(NqGh2+8_{Afvu z1MCEjm!mPYr0fCtO@#~7h+i}V2yM`IaplP+O%TX+G+4Acpd1vqqIiRcf20=0k_wJh z-^H@wbh`Z;OS=_*#%9R2)ltfSS?dFv1?#&z`#r+D_`ctRw%ea=Zs>>4t){*U{y0Pq zD8>N(T)|{ke7CxREWLnZK-wnn$-2v|=|FGR?Ls5GPuA^_o-Oxp@aFSew)$+w#zL!Co`6?XJfc*slY*RJ7L1I6D5CHjMZ@&lm zRUq#nZFnayGlxZ3*k67&mY+JpnTlM_-|cNMI&X2Lc`l339MJpD61ld)LF?yudiL`E zCskn4PuBnUPi9FCds&$alq;qmSmqq`uJgg9B@j{A(c4PXsMH~AmlvWtt$@sR? zF&BSv5sD|ryMchvr#Na}4Nm^JN@O!%Dv}Vra!<|^$+@PKcm?7QCX(-^(d%-qPV&aVM}Dl(O{eVfp!ae{jO6}3&X)8%W>==TwBG?L-4}X@F8abe>>}6CGtS;R)vXw2>gHyYP#5W|8UvN&1E|1i0tQm_q-v>S@qW5X_`E)u(_6zXbZn< z@W35oRk-UoWu&7q4@z;?LMv`3uGx{7-iLswFxMEjaz{x!8~rTVJ8H5`|4E>BgZ4hU zqwaKU2zji37>4jzHxw%9H|?B}59&VMP7vehAzxs|bN^^>Q=_jjW{uvkM;pV#E|f(y zH_r~133fk)TB}z0b&Fo$A}Suex>`NgP~4N!`4Q>qiNCqx!#b3-RGH&hj|HuhPbbzo zk~ifP<|s?i$OG=SeUGNSe%!jx)Icf-enxI6`15mr4MaUAmRGwq*H>cgG&=pSC*sHT zn*s2a6aT*c>!a`s-tjLr_?~G0m&!j80UXDvFG)Z`Eg5otutc|k8V7nFj~6hfs8@1* zvVn;W_DVU{bj0Ro#F&X;*|qVgAvgMI@Jw|)R}AN7hntz#To65=Pak{NVH`aJ)RM=+5lP>K& zjp^kKG*e}&7)=VYyWN{W(nE;b-{laou{Lkv634BT9h&&itxGo7o?}I{{qYW_ZT1k` zY+f1sK&_5EWo&iFX9{=)1p~d^`gFU0t(o)~A4siK&0}Q5yX+a9{M34yhel@A+DeU) z@Z0$mi+DeT=vCf_aa=o)dNPuMf7YS%ELI=kSwtNy^XFw-U$5FSSt!0=>)g9hkHIbk zPGTN6r0ms3HUENDCi_)g=)Ll9^Tf1Rz5BiObnWwTZ}ZlTD17O7KE?b!EBDHO4Z0AN zK9Bdmloy@5skPY$PTZ?IOh%1JP@|@Cp9E_glAr>=`%h-vXCE zwD}9Ze6IgT_Zlcjl34PPXfQjYiy*^Zxk^Cfy{+60UZGmb-@rf^(qEzr&~oT2Z5ksM zO$g?807;DhO3kL1genF=gTLSng)dGtLM+-f2J`>#B&H89+1*UAtaT=_#ghgYLoka( zP5ea)xDt6zX!!J#E?@DNZQeeM;Of>K?yLGpCd>oM|`)pYQkSl9OE-3aOL|K(*10s#9($ znI@#?$5i9s*l>e?$fRpeTTPPW)))RX+aoa#^rPs-eRU>s#5?(g;|s$xI*VR1U9o#C zT_K5zD>6yrD(dFosqgDdYN_t=xL$Tuv%Zi%e(?KDQ8ayh(w`!-s+vB@+Hw|ZgOJfD z6jD2M>jU+AyWZr7PHZLda6x=wZC)cGq$2vzHsy64$Mf!gyf#p()BS6kN%1}MZGXES zpz1<}hMuknM%f9bV__b5w1~v*^iou0-I0J0FeO#v1z{gX69`OU7Sap+j&J&Xl%2aZB9Y|+nN1ikzcwHHR)~%r1weQA} znX&VDk{y>x2#pna>P#PD`j+AKsVXX!wyBSm*xn4@o=-kI^x0_tDTu8-sKeti2!~AB zl@jdAumID7mtzf}b@aO-uX|uV@Y#P_`HOYm*H4fR{e0OJKqAHlIhu{EFXRYBG>SxcZaO)&RSby+Gw4iPm)%3*a z`-T-A+*Q<|NuFGxg0y#_qBi3D1kuzh>+$w7vP8l-ZFM3@~91af%V#G{* zzp?&R>o7aJoM|-HJ4lf5UBG5;vR9d8cUqrF(Yn(s#EqW;I?iI$t&~1MB<^Ab&2yCf zVtSsBr(=_@&q@ERpkOziQs+)y_7ipL+}nhC{pf?o+@5rSek!MR1LTve$>^$oAZp56 zol7NaiFut3|6Q_#{#$hEt5*M%FnvS+NSQEv$u|q=*8+BOQLRk8nAw1hgy@p<1xo0} zk6+T|FD;J#A5++*;6<6vf1*s=e}^)?mchSMCikCGro~u)6Xig7&kJ?3K8f<;=d%3A zXg;q1`;#dDax~EA;d~wqphUmhXN7;;XGK}|S>Yj8=Vx0waFa<*Xf%y~7I>leaXb#N zRTEKSP@yZGN%;|NJGX)BYOUpn`-plu>R>^n5y+X90~?hQ*S@aq z&di$1kI(24&908tSmR!=4>b(qJ|6;TuU#5j^&busX9upm%zK4@XYSqQX-3VpvAeWs zJhCmF=e|Il6TFg>Qz!8Ly_j>{1gHZkX`q)YP&d5TxFR-tMI~2HgHmjfeU=J7w@4NH zIh@)-1}o~$K%~Hun-dDBzH3q#G_5ZsgU(}_r2KK-IcZ*!4h26mqhHs7S+B8`mTR;? zJKWI$3W6lnwaE8>LX}E0dNDfa%Cfi1V;(}0-RbvzXA-LB>7}vLvNNLhmKW@|ZI7+1 z++AO7b5B`@&~Pm+Rh@E9>kt4{niMT~7Fc&pw<&n=&W}epUCR6LbdDT@2PDNYW5R8B zp=z1}CD9!&AVt9+Dmb2S=+GgTrmLywi)k3)^} zAFc&D=|V1qi-fo( z^}4NAcAP$cN_#u4Lqrm{;*)Hp9B;MolCQNvCkHftbR0cvTO9)Is2@4Q$NKbwo0L57 z^*b?<;v@BjczdzJDf1jNPgxepV0gzUmsNi$mj2v4)+x2F*sw z;hI$y+3Z9pbaOl!0i`$R`z})V zJ^T!~{qB^Aw{U-du!wTK!F+u|go#G#1Y_u&=|}{$=_UAawR_XPQM}<~mD$4ooNGUgcx3i%mpJ|puMUotu!Bz@)wV_4!15GN< zd01$-BHFlIs~Q^ZU3;7OCu5J{9QEW`zg>BM&K4s5L)c)rC)Ov%zDC@kv+n5)y)eQS z4gK5cz>2rK?hub=rjx>&SzJ09&~a3Nh~cl+b{;1^dDUCo+pyW{xG?{zk+ z_fD)_jC?x9>~G0n+VbP7Nfie!1O0$Rrm@P-|N2%5S?hm``MRp&CX7FFA#LT%zV;J; zSdJ>US7PImjsVEcvcxU}HQBbU!|YZ1>#hd>XS)2p0l{Cp`)OYRf+0|ZhAE0fX@bT` z7^h(rry1}ULcjz;5)||0mU)1VA;^o70Xjo3KG3p??=4&LWf4(;0R^u;_2LbTe!b@q zyevjw0Cgibbhxx$VkQ17|Npf%0Y#U8EDI)CaxgG-*%&B>7o&^(U5I3%aQ?!rKvjZR zVmGkA?0P^)%VLEf*u?Q-uqDWnJi)x8B+P4HBHw?7d*H>8Baqj+#b~KUVavIfos$qS znm>j}>LmrUeta-8UBo@aG~hM&Ja8+=l8_4ZbTq z`R}O>m0gvycjk7%%~-Y-Al??0EkO!tS&g?u<*ihAwK+hw`+N4nxD{Cc`<8mhz{O=5Z z89nrQ`2YHTd;HU82xnW7R|u_t__5@ZgT%Dk6V6K}orPT|zyZ8IRZ)IL>7C*VkM?Mu zwp;XZ*yV7eCAQLDwj5jFB2?ZbsufN{YZyn-St0tK4h-MkQy7Uhr+vCb(zRGz(vyN- z@hx_;XMEm1yDjb4b~!{gba^<);Y@j{R898*#f*NqdTSbakQP5r4Q!r&z)N{CqN|A3 zbj6?00WVKGW)8!Zg~81OLK$W{D)U@6*eFr+xz9VvY5g11dTutz(VDC3eXRnrdRNv3 zzN+`FEXSouG3?YtX#sS^`Mo*{vOAcmtEu<<3^35x|KF`(K@fn zOxmlgJh$?8(U7gXy(r?3>$6etww%B{R| zBRL&92vC#xrmpkG2ZTYPDie{P(*2OSCvPkKonQ>hvY%4(;t$Yj0ki>Zs-t?b0lr>P z|2La{0N?wurSbytRa8F-m*b#utZj(uh+B# zumDW~4gx#_fCxY?A{T!mVwRu^iN8z>Wcf|LAP|%Q7>$=~fZqUHL@hyjAAY4HL<_j0 z)DkuVv+Vr3VHBi4`*jCTQ0Q!ii^XzaouwA+2rG*)%c|hFzvOO;e$)7e?1@n7kdd^q{ z*sf5GdVu8j!~ubmgaAdJ7nyz~-G5qkeSPTAux_b?Bxn##QV(aZul+Vv36;sN@c&}hKQr(J1(Q&lXY>EcN6#Z^+%k$MlkmLUc% zF&FiBqgjNwVc1%z)LtrP0>kxHE`7Tv>0sz6(*>yUeEAojR@*D)n>GXUrV7c6syhFi zZg)9zCip+EK7hxmn5F>PWB$k|w*z zQffzk)q5Y}Iza;SsCGUhmPb!$P+esnIXxzLD2Bs0nSC=#J_Xym`pmZ)+2&e`caNQ& zsF`y*#So^hpDFHV`OY}q(0r0#AmD(3q^;nN&S|u>fJiVJ*UZ325+HU$&YwgJu_Go9vLzp?&YN_&5{GqmP zEL;qzIaV>VP02i@PpAcE4R&e{1bt*93do3ZN1w5z*&3QmWQak#5-0#AK#V%N-IjOGf&=aar=K(*5f=$&2y7-=IHwZlU{3WLisyT75%%nr>NsB*! z=sSh)%YtYs&f>M;r<&qTzii)^zr8O^?wyyP;U~1b z96xVEVE=fCCL#~3VbC5dTnl?ym9KELWy!U&Bq2Ri%tiL`&bWbb~fRX*) zw~G@(Ygte|VY?%>U&SKks8h z6EI4W4D%J{11w!Owk4P4>=e3W`T;EpW6R&nE5kl{?FmD^_QFMfvqC<8tw4Njxl6#W z1?kwr5>B7s#z~n1wkiz~LUVs5$aEI*2 zJ~quo&%WT=0Qc9w;64wTrg%}g@I(FSmTN!lN-CE8{ZFv{(+(@2Gs>agr<9Am%70Ji zC_i`nFLvoj<9Lp74<}Cb z9pt_&Nl?$$04X0i`{Ve1DZxKoNpQx8!^e`z$u^)*J^yPR{F0Rj{j;>hCn_VQeI)Jm zOwv_&I9{7X^thr7Oyj8{z{5H4E9E(ky@MPcOu&yWN$%@AQebV0o$n($dsJ5Lujg8pPNhY3C;y_y z2X79~2qUxusHR(g=bQ@r6p~ibcnR_7l5epn6))2k7Mz1`pAEDUv!EW+5yg*MHLdQ^ zJqvmw9FwOL-`I0_tlPTp01+4 z^7Vdr_vdkiw*YU3*a9C;x~J?1Z%L5dg1aw*C++2g@XOMFlLeAzmb+$B9c_&voEP{8 zh>Nj(2p(@JdOhFT^HN>r<+HxLVfkbG17_6&X&2MBOJ?e*C&2#TLD}Pf6{)3jR53Md=PfjG53r zC}cSvh@*cSO5Au%t97C(a{rNan)=?5`bYMo!LRk9r9th<;$4xse`jWbKBlIBcV>b< zrl!9;Go`6cb|t?EsV~2A;kU`OS*KfFLc!I2f0Ltg0VOxZ%bBuHB&EQd=y`M-@loOo zUS@-T>GIxH-q!L;yUQ$fT)~lEi`1It_2d~Gj?6isA&O_r$4#Ty8G(b|b8dZK9@_KT z&LVw}?#XA-h9}7mbptM*wUQbL2Ie<{l&U;QEX07q?bY3yYP{C>mm524d}^OYsz2Vh zE_trdF;(!L-Bh7m2`e|;x^Xucu_icfC}W6!4^L2~t7O)W)()Ug>b9m*%A`?E*PftA zP9Ar=+xZ0FPR%Uv8PVS_N}b^4+B&Y|MlBw?1C5g6k=gdxCfn+&Y|H*p$@|kz0J`yf z^M@Gq^OCO~w}j-k`*1yF7G_bZn-RB0*RtatI^T43^>=n%{FPe0vOIpJYX6+^{kF}2 z@95hvc_AqMC3hoU`vg+KvQ#snm;Hj4#0zxsMEr2!TA&0DUzm(eUD;fU_aYLbj-IlTg3mZZxr&HPLIw!iahW7NUh$ zzO5YrBo2Xq-y>~wY1ll8t8yl zDcHy6z@XVj*^7RuqV;_~gZ>uP`g!HZs}A(b-1N87LRg*mAz8g2N)~1hJ}vBjy=D;b ztQ7DBLl1Crj&VwDwJZO%Qb}k(D;!8`7!@KVnJF+(t~^wtag@Re zJVr-W)Uq~}^+O%)!=!6V=knx`T{PYXow#~RHbbXQuGjmMzYPSVJ!=*Q8)y(C9IDEb z(p=1~MkCv3x<*qy5=jEU<_ok2_ImT64-Fw`{OU*X_>a|vq;)l+CtS5J?rQ92jX#A$o*vAK*OZI6~* zD{4|1XgZxP5}V-s;l}iNjKIu!%E01~*pCv3rl`@5SRj!sz zjywV|)HN_h(GFLC_9IpaR<_AMS^TkzYiGT=M(1N9x%YqC(OqI)Bo~l`@%or zG4)s@8NfEr{@xvv(`-)x=v#(=5%lfDHgmqlM~)O6QEZe>igB}fkxQJ?E9m5Tb9I^V zWPR;`{7~u#CdH73)=zD^6c;owE-%!Ur8YZR3V$6J`%oZ%?3}O$?rR{(amt`O)def1 z?Q;uc$3v&wFQ_(fzO7%;*zu6MJYqEN;NX;xN}se&#iB!%U>Yo6T@^d{KDmT$1#ioaPW9`Qlmk>S`JR0aqLG6Jzi&zB}-gF2#utR%nASnb` z2pnwvcC7+`L&Pj{ZZ6RFHdXK$EEp^@o=(x{t4RA*3Ox<~;1Yp$z)9hOu6I}N*BB^H zk20cp4A*>|xSH}sI}-%#5RuOX%Efsw*@QJDXS?7;Z@YLUNUrPdwYr}Qr@vkdz_R54 zy%ezPgcTSTN}81uf3J;RTF~$bLD0!>{VETOdBuo-3-p9=_Q2x8O-cgLlU*KYBL?I6 z!{ALd%z~EUx44%P$+gK+Vo|2Hy21C2|^qpm1|IuwO4WI4gu}o=>@>Tvn9ogsx-ZF z*7-AkJR{8UZeW9TlPnoghr|(^gZvOqE#+`0hH=>8ij&aeNsr)p4FM`WzepN1D)@Ti z7LQemPOuB+7$hzyobQ|#L(l&{EJOc`uF9&i3(G7<)&5MAY7Iqu*n%TUZtDq>{b*6}`=_(DzX6 z7WI+%-khWGUx`jq@4j2S^KG}l3x9`<;rkKOXur7gOUV77IJx)ZwjHA6fADaxykW^s zBO$-&ghlVFAiPIrd$SMTe}&?|3(LgL;y6}z{|w7w|NoD$Z2c)Ldxv8Bk71d`AUbb< z{I7>)+P?_PcnxqM*>#k)ZS{*~r6fqkX?9&3HHa?#vCko7hJ)I(F7-VZt}4Wtt9YMe z#0d2~=Zl^Nuwo#sB1y3RhF&O ze~t_DNKO{e1~WmnV;GWWecS@OPE$8zcudE;n1=jAj0l|W4pmBO^Dy9LrP$g;9*&vv z6lE(bQXm?$;3#5&hP2%oGnJY$EXOz(wpTFVsZ#nalYKS{m*bdCULDhI8h5}ms1x$Cz;alXM%9T@T_l1 z$&Y}`2%e@~2C<*=7`X)DpxUNQKzI9ge5qQgU1o)J^D-tvnLpZvt9iwFpl)b@>A7wh-vl8qKO%}Lizfr%}^@u=MwX{%Za%+s|)vbI)#_nIh5-beZsH%f1#ln z04q=Ocrt2>4vEap!JAlXF!>bYxLKb(MRulhLMECa{;USF%|6o?2=BTb@JZp0#lDn{ za#ofCO_tp4{}!9qdu>i&BHU+~?fVkja~^0S@KHLPWo`@jM6nn7tBd2Z$q%)+oh`bBV%L=< z$&&80!G}Hli7ngHYT_58zeJvmP7__`?-uuVTN~?N#!vroqvHozf$!G~;-DFMKfg3N~*6Np|zYh_Roa=o0Nj6zTFP+#>99vt^N zIlQCDukGtXl_2v<`^DyMvsuXPRL%}B87qvla#(^UK=7G18p1Jo0aon5MlKOpn)7^> z{4lW8`x+Obg`e+8OW%4gOmtwxG49@J%%b-d16DXuG?1Tj_Oi(Ne>9k#8@XI~CxXM`(*X*v2T4s153)i;EHrcX znj2}%^|73k7c7D*z+GVIs+gi#WuXMu&rOBJ)T&-~5H86JC(mP9kVPt4U_gjD$f6~tS=(p^oyMpOl*GPUu z4eCm+mZ`OwrvjMi6dI`nBB(s!HSxwA8HBO_hh@g||1kybtbMUx`{s%A_9odo!#juh z*?nvO?y)Gxz~6_q|K081qTIh(_){nObH$jq2g(-W65$>nZee7E?-Z@eZ*2dT4(;x&v0D9;HTJ1w9DDugP*rVSf7oYu{cnfr#fBW-f}q^_&eTIQ z<5~Hpv;M-Zz}4Y*f7fJplGq3&F8&UCj5ePwZPxhf?h1l`VKx7F4REW^ zxAsqW2K;JkzuMW)gk|7w7|ZM9fFB?Pd6BPxatK?Cyih$s&qHt-HL}0Y)Y4D@ogJR) zlOKp^e~1E34cnG_oXcRauWq1>t0RfS>op9tG@wZ)u3{x7omr7s95I1H)C$0>p))~G zjlT>|%TGSRsfCFOSQ;)~-L`A#k+&_O5nI-D3tB1k`)gF-Fm*tZnU4_-Xb-SPe3Fyt zRKHy=zOvnjOAJPzd}34}vRMMYCq&A0n#JO@f4P{CK3x-_Bo=OPJLtgGLFESo-5fi- zOLU)NHA5p5Og{sa>G&++m7wmDc{`}h6N*UbF)++y$kO(sIo&u(0bX}$T&T0->%xUn z#~IWQC(9!r@N~N)5qxkiYD0J%xFrFiaK-wKuzXn=dasQEe-_8gJcimJ)R&`+cvZXP zf0KiQv_{U7$^SJF`PQBVe$rF>WwR?3xZ!r1Y72(($LzvKQqKi&5`nrwb12bohv^Bn z2y%GM&ggFFC|x)d=?$N0FNDcPlSSAk8oK#Z1*ReaOCfSOb3%3p?25)ZmDcZ5qa@W(kn3x^f6R}y2iLR>im;NDdRx zT`iBt#&|r)l6>~=T9pUJr|EDk0+F#+WEx%8?v(5cj-O+V%dp&5rFw}>8C=< z->v(AmG9R4fqVuh$fsSc5Pgfa;QN7(q;Hk4Y#(jGsQo;~(*Hnjf6eWm#CHAjt`}!dgOS8apR$k{{HH@(G%eu*><8=DQ(Lrm@_?rl-xV@=;l)}Je}Xr0E96(? zRm7;ad?yL>0`>vtx20uOLtn|lub-}M`0-=m#;EHT|Nh3m%O}0XHe2%5I*b2Z+OVYr z*Ka%e<|(O_UnOAvu_L#_cxL4$%f#r-BN4#DM-M_tPaepeEStn!um=L7Jut7AUWwFV z&<-1_SBupIm{)GX_3(Goz>|=SnIAjJSBhJtpu;3FHGnt=6&nJ>5=}t5zME zNU`14PcGSt6V|MDy@j*yWP+oz)9t6T8|sLo%aGUey)vZ8F&kILni z*v6d|nLKtT#_eGMD4c9)ye~+E)IM5?Of~o6EeF_4;b< znkHB^V~n+0o9T$XmN9})i*(0Q?82)85p(I#T}Y*4*@*{^fBGH6p}MXUCJCpZIH&X- zUyd-FXTEU17P7>0u`h)erAMY)5b^HtXbaFt4;@ZIDgjtEk*-_1*63?s1h147wup%! zAul#x!nmquB7b&<5wf0(l6q2M_Z}X%H?~fzunSfM2=2CjXKt;-`H)7-(VQ3uvAUf( zqFNU?eL)(`AeSamt`Mm!^e<`+{NE?u3z_U$>Zya z|2OX2p8({4_nE#y(2vi;{MBItB4LQ4A&P=f0*7&kCTN7FAQ-_A6eYJmGmO#r=gv~_ ze)MBsbU4Bt3HE7FXwNU`WQVTgow4l3(&2v+_;a!Be>b90#DBgF&FmD{w*>bFOJ5wK zQE1PoGIY;_@HaU(eXFPa(px%C_na$v!`;rrrT1;@!rR$b^h-~YyFYc1aj$~B4 zBNpNf~n3?H!fNB*k1`4-*$d&|Oa+8-}%!^oXG3+Oxp zz4NKnp5GUFd(~F~-?BmWpS(Qa?_S?Od3nI!f4#nc^74T1U*Er&BJ~xPppTJB04SAe zgP9^{W*jIoIN!MWDI0KX=v3i(Se0DxG`kz>NQ9$AkU3jKWeZP1fEstt=PrO6AfiaO zF&`9TQZT)HHkyY-tF6>#n5Mn5p1F_yxsNK*~05^>Llw)5!wL?7YNGEitHQ9nL>`jDuTIrYwd@ChB#3}X(waAO^~#Uay7Da zl81gli^rsD>l9q9^aP?kSd?oQ)3NFhueyD8cbcIDPQE>uR~!TvBLoyv)pc%J=r&J; z7PZO(vyq2+8J==gBo4tx@C`e6+jk=+f3L;Z-AZpXe62WWl9K6830$W8@-k8DkQmLk zq%041?~QpD<_{(-r@yWo%lIkFuskCOAAk#dL0s{dCLTXjinZXcLS$LN z&->*y0=EETvx*wloU_mas?^hE}vO(*u*Ctp@b=`}LBstd~@=#wb5#!tCs;Fke@ z2O}~6*Bdy!{aGHO}pEv22IvFy7%kc^hxQ^jqI6-Ak!i`tIBBo|L}@ z@ON7EEPq$FtUeKJD1dKss2f1}&fY{5l1UbfA`lIH`+12_Xa3XKe?gc}->BG2Aw>%- z>^<`OT__ZfYrHVaZ@JkYv#kEIrJpFU|L`S0)jlqMy*B&nU-9?PG1J}>kH(fIn(TWk zUw0zKEe*$i+GV^nj`}vU(;Ent8{)AJHthYHHRr&dy#C%6;xEp(-||}h>#S=2C9&0s z1O^9B6xzZCC(naQf04M8$pN&c;I%@5Tdoc&=3bYQWH2g($1%Xg@qK?TCS*Ek5KkYN z=2|)|?>~CUo+X<$(Swvw8knk&kRk0nTP1 zZbphqsEk-Q-@72LUyqMl)F9=duX2vY54aCGSUR1~qgMjLe@(VdNqN4*lz9mmnZ1^X zr#j7|S6Jl=ws=%<+l{UiVnT{U1~HsVMxmK7-uBhrVXRcW%Qf6OfS_MH1F zv)}OZdf?j)y_?p7_4ya(@4hd*11}-z z!?58))M!r5Z%O&tAD_12o#6@c6y@YOd9IE!+6+}xB34XZ088sv8O-BSy(J}dd>$Wl zj{9x8T2mNb60kM>{CK=JHw0gcG>qf`QX^SD-!2u$U-~N`wTnw)vHoJ{q9o8~zC0aJ zCd@*Te{o{rZ#jtYYmhv-(|Whc5Q#TnhYo>uD1#T)3I>n}_k;7gNj&Pvrw46>Mw&B) zQZ!qbd_Bom>r4uFmgR?=n{uP;_(QL+SjoLCS;M(!1{kTYcS{*RqWb1G>8Q`(BzcEu z3aEeH8yv%XR;Eqzhn2=f*EfA$rjI`n^UvS^e=89Fzxl8qMc=>P^Lr@XP#1gacSmoD z2I8$pxtlYmZ{l0{c6>^9`Wr_4Y6dlYD?`BXK1C2gJ6@*Qj<>{nnsr0O4S4suExJn{ zrRbjjZs-`{|DnQP5$3R6t2_(eY&mpq0dDy^N$gibVjoEj>AkE=rMukHmT#xnyG8jX zf7pfLj>%h^9V72o^fuMlRm-DYn<65%B>uNh%*G$oz^y^`@QCtf!Q{vw>T z?&ad|u2r9J{oBrg|90!&?g9So*0=L6fB$t0^7>A9<*(^3sy!-@@Whst-H~UHHA>++ zN#(pK$A>qT&q%@hU6EELkZR#HV zkqNZ4Lj3r=b34H8Xp84-6Ff&W1C!uY-vY%jY+{Kd3Z(+rV&{qgXQR9y?&)J7f0H!3 z<)+lr7G8!n1bFnw*S?HwkWD?J63-_jK3CXv;irjhoi-gFfykqW*byj=!?US^(U?>c zwq1D{4nsi2?6xkJj=5jz%ZyB%)N)VWr-@;;^yo~5@f}_jv_H6}e#DqHYH-yHIz{SJ zs59;i0K1r_n|g}kV|GaoE{#SUe^C)+%0Th8P428-VemLi6x+Up&X(S{YwCw*Dd^QL(b9ZZIw7U)KYl-as55gV@g@|JR^U zv6$*xP$(UBXhTwE`_MR#fMe|~z3roxendzz1fKTc6{c0p{H>CsIy=wnf8!n=_^0vg zuizQ@oaDcKIvF>)U}XZub?AiRBg`(Vo7^JCk3$Pihu*6db(~P(M9S%^CFyo@^93P# zBviwfE*7s&QBD}{KbfJsfXj-S$5x^m8|+Tn#eOk}EKUhd@IZQhmal^i9WgQxY#usr z^UX4x!+r1di8 z`Sm*X)Wsr`6YhH6fYVu>6sa~g5edh^ZmR`lZO*9M=WhTUQ}G$@a>HH4@4RgJO| zy|PEKEohu?)dP=b4~(O-BmPhADbHKNI;HonO}oE0V*C+&|M^Ydpw$Y?Iqd!rjUN#e zLm&i&NN86wgeYm+Q`-%~Q)*X)-X*WIeKZikcD?I;&D%3-*Dg$Vs}AbjXvN>&PUJgLPOvve{>_x% z_J_Wy>e26|AL5<31OKUGDB*D6j`1|-fiU=t9Hx3of2w21e;j_+F|?gkm^BXjCU?{s z2#xH~D&JrpDE7(wXFR+FB;tdgXj2;Us zx@{+Cf34%j6knsd0825SQ(tmNk1aVycv>}eh7EDLe}#vpy&vLLPDbTvDGqTWo2k<< zi?%B9rDeltam@Gtj)$>ZG)@Kt4M|HT#O#6Wfww=Fz8lRWGu{y z8E^Ts0*}EhM1aaQz|mxHo%LkLo@N+vJ7xV4TSX5%I+uafB-eYv0zCJVf)8RA3VIU4 zc2Rh-e`!rGpm|`Imf#;fIwaF*-xB-Oq%_ftx7(zu%cE9jY^0rDHv35={-9q>`rMo#gWfi(2$x)?4~yfyq8vd@td3#Cg>g+0?cbAG0}mkce=s51+zzQ+(}ZA1TI@JPpKo|a5J%^9R; ztIz?j2L;KE^q0%I<53A&zdbkJ&7T8-YRvN%0~z?JHPmeP#kV4RxQC@*rvibm##!2W ze?Dlc%hhL6G{`Iomm}8$f?C-uhF0ny*DxjBo7B2*6jV3y#^M$L(A=Zf`oz z6#af!NNnzO>K1S^dx(iovs_#bjhQ15y`(dLA~ox#0=8@adcsfO7<1~|CB{=thcCr; zyto(l`M|U_RShCx;{dRpjX6eL&UHq4e`_l>Ravd=v4^~nPFTqGL>oPX-LHtUWFt#y zXjOpDT2WQ1T)ceAfZIBm2h{Zz!m5I~I^Z$mj&{ywX@_$Y72)nMOlV%*G_{k7R=lBs zOE8#57nekBLlp>w?aNz~Qq7pzwNX)vnm_|OB6@l_Fp`fLmKwe4@aUy-{b0$;e^f%> zfl}M?`pY#s3V?FCu!mx}Pgq6IVHDN~o96Z{kd>Dl6fMk1jm?w!;{-jan*&F_1ZoB0 zZAY7So5q|33Y&2b1%U+C;b_tWIC?#-hT1b7id?>3pv+9pr}PFT{JKTx*Oh-U#>8qY z{It&y3BrJII~9g`VOFMi`cbOff3QoXuw?69vrbwVa7D5$qMYZ*OirPQpVVgNINpjt zDXN3*(*krnSZWVNefff~8LWHjt?6{VAD%3YLU*unRkpR1zQ*3h1Z@; z0}Q_Z$S&7^E-}rQdAWy0f4jc(^PVPu$o$73-uchpe#Zq!wrlZr?GwVm|M>P7fgo+dw+m)?b<(Y;=={TE91LB!-e%lD&vFp?y@;N37Oto5gwuk`@!cRFdGwJ@s|MMDF0CAmj{vZ@I!wZ8e8ar?{3juT%y4U zAH>p}q5EMTe-~uHb4VtxdK_SYh2pREM(O4#3fD=(z+Y@|tR z4NIR!#GrT1aXrHK-l63ib^sWAi|We)UrthpA7k$&VKIN_p!ycL4-#1#5V;Kp4t<6B zp)sQCfe>9{E;3O{E_;Xq{An8Ysg2ifeLw-0HI4+Ke@?V=I^~rx+WxZ}7BQg^ROZ*e zcvk;qE%4pqU$VLToS;zfG*V}MiP52MP6sq@BVT(O9FVx`vjC?BPP){&pR-lNZ1q&@ z4Z_Aky~T;TM(0p-bd?wmjazSkgZt{*yD%1A?pqm<%{A4WLrf{>e6o;Ll{?fsP$f2` zf&?}Ve~D!|N*y~h+P$-6MSVV6(ksEtqV5zKw}9@#S$P!^(|Kmh)s1c|)XedMWYp;u zVUY;7Mo(bE*qldhJlr&Cgv%|`xdvqNn6k?YkdTL_=dqiu$rf^qV>$_@(Q-Vz#KKfh z=Y}NtU>SNL0U3Or*WgZBykR^kl*;@UlLBB5e?^K5KPtjS{j2zbZd+7lu&*ve%lXjp zts|o99LsA-w)RQwziP1Prp$JW&8+2kghGN8Lph?nu{XL}j?m6_99zw&tH^0H&mj7ef-j&DRJh}~u ze~`~>89NSA`)JX2EAiGG`XW0Nz0orvc0M@4n`|7?3t^*b?^hb2gFc457*@!xCk3WyNsCG$-B zVOt6rLx42zYKbf)j|fqA$I_3X{(q%HiB(e}cw6G3T2>FIH(OON9GYI2P;JQKe{^n| z2Mcf}uQ9>7vnmd?4+;MgYsSIRvNBIeF$WAI3(ESyqMSTrt2Mri=gAEo@$rHB-La=h zpeqO`O9|9eH5nPhDa~h`ZJmSJK-t7**o`Egs-8d@I$*8S9=H4@-evtKh-8T4Faj9L z9g-KfCu>NN?57m#Yqtg#b zkpWnzv8B{YDZVDYA!QnJ>{*(>_8ZuIKK9JV;?LIpx`3}eW1Sde;U%l!2n(G+n~#f? z-E#|0y;|;@Z_anBfhfvWaGT!<_h#Vwa>BNuXUw#wuU%LddOz-^U$ zcVm{3L1HVCaSC@Dg>|OxsLd>>7^(KIUKG^OukJJ(8k0j$#l5kpu=qTOvxsG>Kp&3Xv#=k`%oCiu#n- zo?vfthjdqg!Q*`te|CpI^i593cTK(+-w}1g$1N+RKA+~r->vWT&8|by9eQzkN3t;4 zsdf8I@0&5VJ?fT2!W-DaJESG?26ew`3SjR7KE6xO#OTgh-%@0Z*i%yS?Nzy@%iE)* zZ@xVCRxCuLJsb$%>eb16PAeqdL_cyL(jwCR={E$2sa=BSe|JFo+6&+}2Gv3dIIcd8IC?YhA#3Y^;aqH16CmCt_H zxDQ!~@`v|efB*R-8~vio0T_<|5g7bD9QL=fVOpf&-lYXV+9Yuk8ns)L;l6NKVyH2r z;H5q;PQx2rza@5$BRvc?_j;YurJ^~1P#e~@?iQ+8E^yID=&Ty*DnLy>CFPb#W;!ej|dQ<~@+LG_g5qI7QHae-~Gh*}$kf(h-$`De^7C41h?)kLd@~l3nSTE1T3iS1{r`{$b&-SI zmz_n5WIMyuHoZ-+d`W8N>QJIeq4z*=-LszEf6{~C!rjz?^Mi{K) zaS}ChaAlFkmD3(QeorrY`>GjibXqSuJb$O|xERVsCq`5*s!qpKdO!}-{!dx@_ zYB^_RVEF4oQlUsNG^h<}xr!&BDV5W87QLg2zAm-e>Vo6plsR=X0{Cl58>(@@IseW* ze@rjDqC<5)F~Tv$7Rfhj$6HLX^Czz7+?f_&j(H&mlZd$>sYNaYCgI_6CI~GroDa2H zQYgvvF4;|vnqC-Ysyl({L1yC?x#*;j-V`(GdOlkjS)m<09RToLKLtWZ36@s>G0J{p zgkA1s8{U^M2)IMq&^#YMq37?`es~>yf4%g_UvK!a8oT`uLLdslaC!qqY&ZGC2#VZY z|F-m!#AzIQ*FOJRj-~d=DC)}q7PZ?9pz+=x&&a)+3ZZ-9Gfdw$NyzS8{HfdDmu@(= zx57ze$I>l>q>=ZWGyV25qISz97}^uU7@)!c0v8SXeueMkZS)_<9=_bz$& z(Iqz+*`>|H#Ydj{Ko6F;9fXa+X`d>*0hgaAg&X-Le06i(5rzBG5uYQ;S%1<}dsAJ3 zH<#wfE};t-aaVs-R?k*F>nnq5e^xx}*4N7FmurYtZOMdX<8H;!KSQ!;SAy~NtlA-2 zej};GJ`zv+QCF`1LMH=uKA9~kL*yQpoq_wWAW45+fo5b(koQbZDu}UB=7W29u4HX2 zFpOg9I%K)2!;jY#L%Qdy^UBrMgMq0y=S%|+O9OBUm7_uCPV3L7ZxV_if5Z3abX%D_ z>gW$g)|X339edQSG*5V*3|~ON6C@be!S|Hwasuj@iCXU&I5{$rqe>ZYR;6}B>T=yF zvXwrzUAO`XS|c4!wK(3H>L@bg1T~juq;m-%EpoVanRTw7DN@#v8DA<5EZzc zBDg^llMCusZ^i`R|CC|>A@RddZA7WZS!LD~jn4JbwODnZdQGlpe_{I*`*I*NeuM$n z?eF;^CdEj83~6qQW#Ru=RQ3FSIBd=eqXNLw7tu`H1%vbHT@seqK>MgZwc(#YeQm zuZDbc3kq1WBS#^xf5XcgD9I7!=O}O4Ym%TPY*?da1!7m9o)-(pA4(fWc@s=$aZCN882?%@E-+I%li z)n$QN8Fkd#UK4rJJ*~JkS=rD%DtKNlPu)X=>+T|2!Bt)`86U8tWyd~jM8hKq5kYrJ zpdrDsx*PUC&lpYXBaQRWubJGqd(xJ97mm++`bCWC53c`ze@+bl-K`(_-w(I_;O_$? zG)-<9ABm$Ve@$=yLGdl$+bw?xoPtnt%lB~nQ^P-a2e1v;w%lt&lnv5wXom{;&2QcZ zmeL(ph_^g@jDK$a^ERFRGK7S`OPIUiPxe+mMc-`ax0NhH?4lR@BvbeviHiRN|Ekpp zy)kUNVcXk=jUlt>bLeS@$u{LzgnDX5JRiTJEFjFdV8ee>!>%Ul zYrnDB`ySu6BMF>{Ah~j~?v2{346^W=KUZmsH}9G@M5NyFS)4Glk=rH6_Zk`~>Qg(& zc5B@Q>!rfhhDOs_f9RfY6LU&Wv;?`GplLpfT7NFHzPB|E zGWxS{1J0)g=PHS|PY4qvAZoj3emSeMpAIMAmmYTe#QUdm63a3()pN@0y;4<}cPhw4 z*69d%l{fXa5Ol1fNAA@(wPY+WZ@k@B%hlxWfV;Vs!q?NHhfnf&i|YcTgVR}ijo@Li ze~&XjvcUqI(c^ry@himy(1%ri?Fo z$OB<|y|%CVHkOTtfi~UZhnZ=hZz&h2ZNT-58s_Vs0s)Vw zTJjDr*2xRMzJ5a<;1lSn#Bzy_GaKIwfAXn{K6<``{A;C8^W5f*$tD=x1cokyyhYGJ zSwHiHJ)8wujT5#{vLO%A_+go(mK$f&AmWwELN5xR9*9q9ZjA`a@HaRX+KGC4cYv8B zgXtf^f?o-*t^|?AebJ#(rn%4jMSSfQFxL-H(X%yZKT^Sa(`v*JxD;6quV4iXf9i2x zm3G#l>Vm<+iH@lYFUd?}s))Vy}w$P;rl}h64&O9{XF) zxfLs634CSAnd1V6ArPbTm4`dYl_ESNGYiBMXhBQmx)9+lF9(fougLF#b3{3TvC4Fp zx?z6PlX=?SRqK#UEn7kJ&JP{6Bw)yS>PtzhK0l z<(mHCJs(p%pRWHQp+d1;i44aHn1Tp;gCOctj`4ORZ|ClI81KzBcuz*qXeWm3S=Bq$ z*-q<>+C?k21cXLEM;K}^I&SDey+xbQFAx>IYk1h6yX+ieeD9N?Z>*x)v+&g5y z@JdJa1PqGyzFb7_N`+9kgC3f`eP*ehz=Fp+&Y*9q%m!P#D0a9{`t0L8)O)fB+fi)) z8Q!OLcW+sI=j_nG)xthLcZ4B65Jq86BO?hH*sH<$v%v2YC2C#%skvn(NVCT9jxyL5 z!NxD?Ycu2Bw`z1W-0~J1e`z`(Dp@H)-m@{R%t86~>HL$I!ppG6Z-~Qd@E2anPuD8; z_;dEeoBWRjO&d*y7}eisBMV1KGrksl-Z@-g0pD-cKm)>pC~lz6!pNuem5u-vG?e@VG3k9&#+U(3b5 zjmUulNaA#zS&CDH-fDWP59!r(kyPgunv=nl*78^)e>d;J!YDj}-O3f2-cytS@-|GhF|Z{-nD&Tkdi* z8rvhVb9P};F-Qsi-ce`lFa61V@n>s+eX)^$Ro~{R`C>67n>TskU0L@kyahT=74!JP zDbMipZ+5%D300a{q}MIV+&=U5Gyd}ZU-$3-yV!4jK4JVOF>@&aV7Nh1A<3Xc*5XO! z(2hChe+QFX9qgDwV3xSybU7DpHocaV&w0cgOL69K@Z98E#(V~B|1R15@rl_3D01}R zMm`e{!?n6Y}6VAewKa@F*p7i4D-e#uu&~ zx^c{ub~F)_P$|O_4H~*P@3!ezbN;+3R zjNSFMu^?0ai*U^>n<>5j+kowNcl|YF`|*zNgEpLmAe2HO9ED*Lr)iw{wBo%Rfe`-* z;XSV>lRe4ae#qiI)sCUP!c5|CY8AE9l;F=}wkh_Pg^z(>&@wngFISB{AHwAy<>dke-;a<9W< z#Jf!l?IGM=C(qv0uxu|=K<`2FG}$+?g^ycIxy5hE?_;)UukaEd{w1>Yn(Py7k|*f# zxsS~`uAM=rNPe5_Ac z4U(v0qX$JAw8}0agCeXlJpx_CI1PUa{VOb4F3a5qMIvN9w2#$L_D|dkr5FtwRa%4Y z2~~AY`X~YA#C@i_>J>`>!B{GZ^sj=pm~m?D*c-dxR3f!Ka4BLxe>Jh!=zxDVX|$~V z>4AhtmAr(D2|C9j4MreUG~qNXTx5mAi$B&97V_M3hxF@!Esl4&Myy0wT-HW-abrT^ zX%>XHR)I*=*hAJ2Kuk&e8Om>YP8BU#X*b^E3--xBRstLpXJD+G!brJ*#2wTc?cM3{ zsKk8y7>KpN%?hCPe{BB1FN}KkeGZ4g%I+3H7!F|Kh^JR;_FE{Y+!nIp*OtG(B$j@y zc6OWtj*`L1kO0YIAI7;Kbj&qFF{JXf0@JmALNGr|hcWd};V?{ncg@5|luirn8<6>E zy4TTsnxd5fm419aShQd%v*qq-|w!l(4E$E;^9gC3+VhLiD9k!4f-6t{i0E%d(e-^6Xg z-^FbZ2;BaYxD8^Jqg-Tc2cO|1zH>+Xa^Z4>y`K=~97L@gwRIpU)(&Y8t7D8yLW@<( zrd5XVMEWL#?lGLbg-;k2QgaF3CI=mi?wZTxMX68q{OAvf*49GP;<>%$rtL%Tk}E$w zk=KDZe_lgKy=UUXdgx0=v8C)&F{3`k_@YQLaCUDloZ4K=4uS8a^xVZ!tqIEc8fc+k zjZ!4YXBvvEX88m%n`ZR4Q&!imN4bbQI8<6!eiaB|bmUkP;k2VJ%eZgeP#-~JrIwlj zPc8JcB!NhHwXesFp@b5z&DL$^Oe>hDCn70-fAi=QagkqF%AnxpvAaaa)2^)LNTG_^ zcT&@WQg*m*i@UJh>z;>q8~grv_){Xij(c65CCAX!A*wd~BY@TDnP%q6dW@5_;mGk4 z?8Gf(XqS`7qKw9Gl}i?Ky?%XgK^FCUtBFB%KyAr~ZV=PCbmMwfY(L72v;_;>8y3GvIxw@@W?z zUeF+GE?flH5Pu0wLR~rL97QE{C)g{sujd=@v&4MAoKc?mb9*^C>)*OCUkL@j6si5X zDG<*25Xk)phxsaQ_lJl0f&Pb542_~Be?cHiAjOavhT<54(J+Z)Bts+1o6Fyy1%FF~ zgs#EU+mIJbgL)eXsxS~jrSO-CaCs#o{}q33UWct52?PP{BP3p#67(v1gRTZ4E3*Me zr>CGTvz(Aw&#**+%&&;_%iAfj?n8oFAcC%}ix>o;Kp77KU7>7cX)vp62e#_nf95n8 zpvxF=9oZ_tp2Z+EL>O>E>FNZs+|eJndE}tI(b`{ILh}BFL{H>0lr9;duP6GviT&r( zXTfLuKVRd__i~wTq2BYo8S_zRZVA15==%-6CmsB~&fGWdJfv0059Ik(w%rL{+Uyd# z(?pt7{6wDDtYDPbxAGz+j))Taf6RN=>Z2f;00hatd*58HUJ)%p%qZuqz#{r46{Q8hwpR=Nfe=)f19#kw8 zs$L?ws5(&@i7The&2*VA$#%BEQ+urtaEEt7iLghh8P&==oz>gam{$Rz#wi&^7@{&p zPBQMsUJE2?AEy?Li`O&}C#HzF1xu~*(00CX)-MT%(Ku2Mn@vckLyFW?MPNQubH4i& zRan$SViSwqv7`KRcarYce~k~5hpgS$!L!3kGLVO%-O|WNMYv#(f_1@&jiy4a!33Mj zOC09tIS!jU{4`Cj<0jqwLYRlu(G-3$M8aO~j2>&5EJ7ucntmF#Et~|bZSR^_f?PtEmMX|yK4KTTvkh}M zZXWz(w!!6k87#`-T(z`vG`go_X1nyULiXGI`szvW$-^=8AAXS=#ZfJhi1g||=fDqTG!EHUkom?@O@Djin=IUq@bguYT{u6_ z_vMxC|CRjTf1xl;{`JF-|MQpB-~Ni;z-rFYzaIDOufA(u9{}_J;AOl6?&p{AJ-m_( zfilPfqYMgT;9r;fDFs)5t9}?TcSXTS+p^t)^2u@;YxRU;K&@oKR*VE?7iJxSi&1by zX6>0V6xbkM6>FD^U(TB2Yo81UojN)OY(nO@^m=hMHyOXl#_J;Gc`w1EvT4WgTSI5= zxA<4G@mJ?(39lb28;aEjrxXtDuX=I4#s}~G^c?y`7tUFr6Rqsq)<3F5zY=%BSl z*S%lnckub$4EA@E8B~3REFlb#A9+^-Q3pf6{iM=xTyJJ))y@hkUr~ZLh|*?0uG#9hTFhc?ext zG2)wJww@C|Nyp?lzL9=$YTba9aycr@0vt)h0yCmfRTR^10jy1CaWl}kK zM%B5Osw)K_e;Ok9N|5-j-Xju4-DX>DS^eQXQjEIMu6IA&i1UlIsS9V6=aRv1FFiFz zcdC^ESc{)Y$ga2hh)vQZSlmy8`>d0RPEKkvC0s|&2j&&-l19Hu(|73{ zv*K9jS9{oDcwy+AW(f z>X|)3(=qYM#0ipTrzY5(OJ~}ndjRsET;mT_01U<`62}peB1jr0Xoi9j z5)9bm%L^2Vzz9x!O4~_dpnadMQ+Ff$8?v>~XKXNiFbAYbB@3g|>De+Ljr@h@I*>F>i77?2>T$G0kg zezUrB$dHF&uX>d}%XjMYarz}pd3|F4@{RbpKyni{3&ySem9LuL--t5@NSs1{f#8?3 zE(IBX>H?^e>Su1<4|?12OAvGhU7PTkoVoH{12+T8FJBC_<8~r6*B#CG1b?1<=)1GO zOODT~#34aDU4qxoS^vkRA9~OF-&jZPcQFl%e~f89hBV;${XB>G4;~mxlFFqPzok+!TCwciMvy?G$K z@mz(f>+QCu>6R4J*@Mp{f4yGn{akI&gcoNMG{BE}+cO&u$?p_=jKfy-f`loA$O*7# zRg9>r9zD|`;coAHwzPY=w`zLi~^3l(c(Uzl0T zw(Ovmvw?2>#h&o3$BA8C`MPozrb_{Y=_vS?*ITKHaHC5d%cQw3*=R1WP|cBG=7*r| zX9V6tx|;dt2jP&s>wPuoiPf=)=)a}qzPF2@_kL0Qy$8HGih;xBy@wY5%!QhijDMaL z?7*B;h`K=by4Cn47noTE;tKaB6dErVrdw@Jj@(E0Dj;qny~o`0tty`1W^Vay_QAvs*UB4?rY#!x$T4H^tB+iXtD zCuQc#hA!kQ&s`Mk*%A3}7x8jk2x+~EeVi72Du9S0vP|wwY_uf=W(My1;C)r=^pJD$ zB57Ufx)=B6-HCB37Ie5_hev&$8WFA~lJlEAPS8+?)>%ao{abu=YN|_4DG9T zzM(SKket+OgQ(5fHaheB7Vec1K1{}`lg~j2;kjwW6OT0c4AfL#C{3oWhxfyUlwjof zyqplpRQAR&63cHZrnK2pllYwO@TVAhv<{VBlvv6QZM+#hIjX9WmOGTiHj?I-SzjeX zvV{|)^oQgAE~ZgW`TF(G*&ips7ccuVPO`eRe*Z#$yY#m;i16$7D7OnkY1Kv}_8Tl7`3AWuMpB3}*pi1c67Zv~2l2Pl?Y`EN>iN8UKG zg@1_$T+YAEgBVgcCs6&UkZ-B{XMQ`LT;KIX|J2O7RYTbMfx%mrgSU8GmaZm1mq2Ez=s) z_{rmsZIxYcnY`4M+)XI+?8(c5hInJZ7kRJ^2rjgg-7tgTCyB=-@-4ZkOpY5jG-zzr z_IU)Y9%U@>;?}aBg?l<4)KejcagM698uifV)05dw_OY!F^i(fl{zH+ah~3>C6VtdS z#*oE$5&d2^EgQCJ<$oD>oA#K6*9pBSas^RBJ~I~IAfu;c z4$kAf+nh*k>?UmUR5LjwGD&*W+4TT92Mp}y)xfTRcER_+sJ~*K_~KsY!EYa+Hv>Bt zu|74hgT6V~{p9ELt+^oxg9G16U%1#w^FS_Fy^;43$x3G4rFc0KB>@-(O*=HBNj+bOL1rmSHXl5;;d~DzfHmLAc zKWxoocwppE<{G=DD|H{df-xeV7KEvT@_5Ju;vdZZD!}3B;d@_;;?eOpTB!BJbX<@IlUy~Btw7E1oNpd&w^R`Y61t)1_uPj1s<3579l})y}%=Ynh5CdgSnW`74EPI zKpeGlFc;_oG6V1``i}#b*9DF6H(l1%i#EYQs-CY?HOQ}6nLzUZUI%D!u-%f9FZc$G zbz;!%Umz8Qfp~w4fXPy9)%9Nm2EZ*K2_TsQASFTbez||O1zMLYOIIw8mb?4?tmbnC z!*7lGC6_v1jLJRtjm~gKl|EM2%jb>x{eKRI-}K`aRFl47mHnN;>JN2$&~vY0ty1wd z$E|A6m@^LT%GW|z!rv>hhRi2tZC%kFt{mP+JR&yGeZIoo4-u_3ifRVrcjtmr&>IcJ|{ z?h&+=lp)e$Grn5%PM06%{p`E4_P~z>vb~(U6I?%8h;<5eZ+P>@5?IsqpfT5uC*C9-FI)`SqR9(VCKAmMNBmh|7_Eg=0&WGQ zyllmEb02v9Oc>j}%LviQLPPj@Yq5qXLU@v+#i-!r2b|P!59h9`m-`21dkP(ev#~4hf7ni5M zYjF0ygj6`f)^T(Er9=Bi;T~B1P9A4@w@zQ7FTvqSEgT;xx0OwTSxr)j<~x5#&_Rz@OR}+tr%Yk23o%1|bO!j2t0LqyY>Uj@%5(%F-;)pwoYN_nq#SefJFh zzKZ^*+&R!Cg+=~w#tv0&Ju%2l#Moo)04Ce*m__@O^H4U_L!Aq(I?S}(Jo)q9^|AjiIm_` zHMFuLtKANJ6;l*k%aDJDOychORQAw!$_A0uRu-e^xOsA$TsFPUMiy_=od(M|8 z4$~DP=tJ=ai%voqP`CHg+u`0a?_#sKY%Cw5!;ejE^WYo)VX8+@CoT5s@E0{E6ur6l z(8r4K-wzOQyEjrEErK??CXfYm+_Pj^m3^vMqj9F60FGDMzR%P#s+VsRerEmDSt9e( zcLn;Mh`DV1ivNG6&3?R`vvwQAWSS5Ic77-)HGu5YPzcdjV!iF|`t@e>< zA(QTmKx#E+Scl>uIz>9gG=DT?QN3~`$KTl}r1A`RCX~b$eVR_3g8q(y zbzQPiniHBJ(*91}tNWqij7IR`9mgCpxr^vR#i4oU+4YuNV(m6j;eQ?e z7ypr<{$DxZJFfrX!F~XEgj|wd23ay;lmT+@%bx}FDS{v|nxqjFr>W(Im%lv)Apu{P z;XMT^6R&Jz2>{hgP_X31%W;=9mWtNvmmWR^9Dh$1qu|PbwOs@@SS|(N{qL#j1kjea zlV1VeqwjM}?-J<|DpHwOwIKEQ=jGw^XBqJiF4a!!!ReB6Mla5Z(Fs|pVVzbuJfR(G z?Ewt0#>2b5`z!t0TUDiHEmFL7-AO*+_L84|^s;ONN`F3{C8@bkCg$YmvwyJ1#zAil)XMtBX8q0K zNzcQhJ^6lzhg18gQQ5b+lat)o?Nh!mlvr-7#JF8M@#dlp=gu~AKXekr6*uuNo)FVR z9%t91j?TTUme`X>4^|$l7IGW{?Yxf)txLA%e8~}9XlR^bIa}FbEDl`*;&FeaXn!jy z1(#{%b-H<_tElRb|%v2!mS8ghj`XzO?4w_hx7U&R)hHUyjX3kIy>c}W_PcZ%d1&hCa zAKc~jbPei=`A4p$_rrJLcUpkdt$%)Y1CrlzvLA*eMk)OpN9^5{FcKOfb1Mu_8ImoL zW@Wo5u3S%ts$xBq7g{zFI;uglmN4BjjC1&CvWM75`V=6jyk*6lwOS`n0gjaf| z^)|gpRDV0(HuR$o#MkIWe6c*S*FR0AMV|l9)9HVHkPj*K-yGlv z(^!O{Xp~+MmV)U8fYAkP!Jrt5tRyjt!DyKIlo9zYqsl_r^0I4glO>QvjFQDnYm$Z%K~{cpVobK_!~bR(~j85&D-sS!89T zF(|;=1-g;dfObLCC2x*Wz_LeIGkDP1T?ftLmB|jy7XdT)X!S~4t^-}i$QB4sV{lDN zz7KY%eh0ez8D!PPH+M1x&Yss+WfO^W9ahd-)Cl(#yXT5x0o}?tf+E?>bEWfv)bvj? z>NjixhllPkV;@uA#(VfQ`-EI8-PEiMkd$cRx`lGcMl0?Z8oV0WoVpr46^G37O zl<1u7560D@@5o9&epE-j2S$2qC9>40$JzCTW$fiO;8nh*JXvDv{pKpPP;OT8veGm1 zzMP+Sybst{I+rg)1r2}2y39_a?I@YE3nyEYUgee%JGb-+$wJ1uTPjrz7HO;4nnsx* zhB>9Tbb1ha-(yz%L6sLemsQQwW#4Lj^Sf7nkuv1sn{2 zVi+_fmqWrprR7(b8AJs;f8VOV2sBvWhxY3NZ#u|p+FCaSmxMf5?7igV?XRf6=jvze z6;XKmJ_4Exhon0f^$y{w{%&Qw1GVvIqBJiE7QS6TD7e-bLBgL0`OPI|@8 zx?sIc5zk*=BXmasCDe}%Odt*Tt@67p*2>p2I^We+C(SldX3S2zONf@R%9qvNW?u`c zAeya?DjNvU8-=$y+Me!OHYdlJ_Xy?psxSDNc_pYqBI zu9W-CyX#{)75cuOfBJ$qGrPMp`hXFz+gziG+bNql*i#32BkZ}oYk1DC57n3GSt(V$ zxXFS%@A0TN1-5++H!^ju&+{$4O5zPcV8syG*Ctq2?R$m>CrwY=NW-`X9FY4wCp1Sp%H@uEhTGTVop*8p z;UcZv`Etp;i@1SpkZN9>N*a0|2mQ`-gGmjArd&D=nWZ*W@PpIX$@ZaL zFG+J!4k6ExH>aAb!jW^9jH&U6U(V7gf=b;pSt>r4d!yB_y=4?iDT`0vlF#!oZ=6)M zXX_%#e@($-#d3LgrkVKgI1{h)kqyH$Bvm+zPp?Mr#h|YzJH4}3k5cXOlq&y*qb}`k z(qJP;b`!XipFGe_e$w24(%~l_Ry$~WpmM%|{~XBItfuH9AedgB+gCrFe=-gEe3S3J zLcrTUlpkr(S%guB!cmyPNED$yRZ5T6e%yj5e?+_zMbXt%V|7DL=@oX!f1xx;gz|KO znom&?6eTk-S-U_fP5>l}aM1k&^Cu`MF22c^5pUAC_-fUWt~%<}FHmtwUE*~z7uZB* ztJ!4+nw~Tc5}qX&0=l^a5 zJ0g0?$8tKze*L6_*sm+x9?lGdo%Qp^;;2TQN9vx%!JU|`L&6qKKfe@t>RwP`CP!n( zhVZ0p%A50oJv>t`v0litVa&2KJog2>Z#}U?oAy54UaIAvE8{}ERL`B_5t_ODf9@gM zOJ7_AegUczF+DM{s!H?j`PYc-$VtV=_QhBRf ztHaUIq(f+bTf43_wXE(G)VyxX9+fk4dt`;}zCrY>mq|(m8GoMp z;qoMB!00?Eulc@F+h-Km#1>Ih26Kc`sV7zr#v`(P9E+KwTB%E*Jc$T_Z?xVq&Lok&|j|lK?qrnV1J0CV~;pMidt>ZV>8<12o12=j(p7C5O?gVr>CF$ zkULt5^4uN|hkOekQN`pGPqYon*4XkInf)P$z0H9$_S+>g@Lvioh9dl|m1jnvr!?Q3 znuPa#etUhu@#(Q~!oxo@V9p-HJt?!loUF;}zWpj^0fan%dXtqwZs`0E_0VZc8{)~O641-a;QB%nLB3PvpeiopOG=>$+k7sPy*q54@fbk%xV@ReAH zM3Yq{l*(6n={k|R95H&6&wq$O#tL4~fV3z{0iqA^S&rA@AiOeu)~uFV$3Lj$fWIHr z=)k~e|J8q)+kNh}JblQTmP3gNq;dUwiOaEM4@nihisU6{lf8TB56{?MRXX!8B_NPR z`5uqBp+7Z%Ckm<3*Qtpn?$&x*wJbmHNnrGggMM`$0VY@9+iHRNjepg1`8!)J;;quR zyjJ~u8xXjU|Kv6xa3BB4Z9r>DaJh|tFerKBNe#i(`$am4E>uP|EgB{f&t7U@DWKe} zH*N>Vs9nh|*IxDwtM*Qa>`zU$(~O9fhlh(K#+`B=`;v!DeS7Sw>#~YmZJ8XCcIegp z%k4G`%v)QfAYT*NZhu{e9k`9I%zRgktRFoQw3rdC8gI}|5+dY&%nHKUU)fiv6}W0k zVH`c55$=@%>o$2(i?n10T-Bh%^>%g!4b4b0@1rwfL%Mz^DP%(2^cK^zLQtI?Xm`t% zTvOYGgGWVJF0<#N$D_TS5e^s7p`)KNUuk2w?GwnnJ|!f|kAD%n@d-mJTO}-CJBda> z5^#~sawDhwBN`e;O{eO@yr?;1XUD6WJIDCF0u57y#`R_Uy;8&np3F32b^LgG4l?D% z`P2^*I_~eUN2<;25&Fc$OZu#7$9?t%TOe_j4{KyAyg5xxytU{!(v-Akl|X%%n>Msq^L3Y&}vFH;)dzX!h%2^z5-ZKKKiw?Q$coSiysg+l|8XQ`|Wb5a8wzJKS*Q+KbDsNcGCm6Xq>sqo`o zIt!A6NTyq!ID+AEIen$bVcOv5XSac-_!j67TcC`z87QXmpSpa*Wmjh`uF``FDXAml z7qKN9Xa9EXbgwOm6DzeNUU@|8LVSyohOhPIt6Koje$a&!c@c#f4`B%K;VJiZC zU%@oKdw*k^Z5Jyv> zXGAiq(eO&($RaTDx4f9Iqk{|9WuH$Y5;+hq$OwRu@#=g+(E!JmR1XkRDNxnKS8v9I z1Ym>4fTfDz%m4mL6M+PCh-nV!CQDwKF>9fA)qm&)R8t0!MuFE!1b}scwKM{lw!mwg zfth{{as8z`eKmv<7;2f zzJIpP{*$wVlSAv-{{azmqn+ueWtm}l+|s&EKooy`4bx4j`qLzKMk`0Xi4w2nimWJ| z2`l$v6ypsPF_7Fph?tXlJE5hJsLy@4pKWMI$LH-F<*n=&B23Bq){c>owdcu{8R1zW z{CPvN6n=#XwUJSyaYXZEpyxx3c}9!AAb;gB6r&g(*xcLQIzm1V99%`B#@?yN*2sSZC81b3@@Uu?VNj%m&cOcDsxDm5AABs(k(hK77jQfPO?H8|9U|p50$} zReZ@_waaF5c$79WdNaFyCt?}`=ziLTc4bGXJQH7un85K`I}>B-@9vSW4L{6Itb>M3 zm4bhjRmy7Rct9VWj-^AOW+Ot*`+u=;)X>)&>Uc#->2TsspVd~NFT)i+HTG36Sw<7) zyN%jKO9JHfBik?>?Ods>D!uYDR{Vf+{{E01cXJ>`8%3)i|GJ=Heq_|@ZopOm}u@$1s1n) zPMEk;Z|URsSRxe`CR6#$l^a~dD2bx^+P@*2;WbUdKL`n1C(YJINHxDy z#<+_RDc&PQODwRtHOm9bBADzyoR^hOvFbx5UN!y;zhfNB(Blq}{Vg&5r8Lf$p@>gy zD4_5C!`^KuaN9jnJrnG@Ues#Y>~;7%|6h_g|B+?MD`9;_R8fu}+3*b+Kd%B#Wb9dD_v zvZMB>wLdq`9Fcyu<@a2TGa)~~r)RTuP$ta~yL5S9K?7eLil>Huogg9X9Su2JLEex^ zn&Nk&pP7-D=MvEy;rzTB6Yie){fXlR*H$pmf#I^D8e2n8MW7;(!*%yC4{wv{msFiN z$W1GEglY0aT^rPOV{y8y37gYVuTBVhdl++7?HT(d-0FCNvmKPr$#ru|@fmRjACA%< zXN}rDa!51e(&3taUwXKBydA&t>&O-OXlCs8RZ#TkWZl?~< z3%Z{b`qe;%9u z*fDpeB#*%rZ35=LyG-=iti>!Q+Wm3Ji6hLBSXDIX_uqoF%H~Ea|Qt6o_v^nra4I*qsPj zI&znC4#Zzgk1Ss_J~jjwsk!6D+dXobgC5TYRe1y1p&X3Jf7ei#h&wAC!*088@3yH} za(|t!zL9Z<-eQ_Sp0w+!YvXS0uOS&U&~XeeUUwAE?Glr`TF%2v`E{AEd!xX^S8$_K zA337Fvk}6y>QUX~c}31{&mGM&gHRu#-D&7u#qv6K3UjY#%+PGyqAIM{=xJ8xJ;&6W zZg+bKbNGZCf6}8&{pQ-wBKd9?4l za)X6q$R|{cRnd~Q2h8Rs>n#Zpk7iFc{9Zt1M|r4&f1IgfBlz~oBvFo}!$M`0T9OWj z8cWOUVDpW-mxvoJ-1W7d0bug>4aXBV%%`nRA@n_*CnjhQnJKQy{yOwGiXEt zBLbg1f8&*Pyj;*(ur}xn$rt2&>(M1Yurti7&5^`Xyv8amJt>q?z3xZSR?1*6Kj)C% z7Ts`fH%e^X!yUI}3`c}~Cc$pCYG9EW#n?;rG}n(G5*hInZro`7BD{76cJ7?k5I9~` zLmYb*b!YlpbeheL0F}DAQPmS>SMaSn!dJd%DRi<|a4{VJu&81DzsV9%*{ZCAknHQv zmSH%5@$8S`+;6sgkJUcD^+T7rSOq~GVU{2Xs2t^B`ZQn1R;dIWa*30eUroLO#|8!* zmljzCEo_d4XP|G614ppmRw@h-f}OuMt7Vl9B&lQh&l}bE4;{W{choHLjV`$wu9g*u znq0V1oJtHeE_ttBn*nGUOZv`&@xrZ{qqjs@kok2O6*R5QNuPm6@*9zAm4^84wU1{9 zCx`x%vjZ6<=uelgSp^(_sW+8-Q^V4fFNKGeZYiR4)R;V%Z}XPuueSzPmM@dASGLd1 z>q%z0qTF)Ugxr^Hp3!)BRnNB@a;;dS-8|~};bS^=;4;4Oi1T4D@?mT+lYM9NyF;_H zeiAb5ytxx8WTgQ`oEi^nZZn+Li47UT6Do*4J)NrC4%u3Fo==A`#`aE>CzF{j$@gKS+;6a-MO|IGuPtK_XJbKX4eKV2lZrAwy$!idM$j;Wzyw7y3`!Fu z@G@d(9Ht2rW*CZ~X@X!r^;?Ju08SVVU@T$4)Fr-u_N8$ev~Yo_;7SNiaWDV^e=Y*C zU>uXJj*;~08BT$*O$^8r0cZj&;uy?@rsygjhyuLDlNBPZ z697v0>z;skoq%@q0*gcjdejSUEY0$8i4s#%69m5$%&I*8Qr(>!wYNyqC(GNASWY zV?nrgRx_l1qxa&f_|wM4VP*HKMesGPzceAwAqnahF-qK_%n{Kq0ydxnJp5CCBxtQ` zy!lqnUs?zFa=>vdWqfTNXqe_Kfb6KV?$n5X;q{jL zIFrG1KW+Rcwh>DR0YmR|Er;))w#2=FRBY1KzZ>Bxpyeqm+WfOT;xEGjeLkPsU7$Gn z$pAu*o5%A|;;#-7ZzHn9gt zX!nn_@fUp0HpjZ=+!+marjG8UJ{|POj_kT-xM|dpx@db*+Hy-$TP?v0Q@ClKg*;R~ zj0SNN{@)4<%wU9m$p1Bqc=crI6k4k2(+!=axDoKJrqIL3uz(-m!UAZC3x>&mIv%~A zqq6SIbR>Rnv;2t;8~0Q+m&+!7MCyx4ZiI3*$&+|1_q6XgMoKrj?r_lTk{r#_;>6pt zzKi9{wI4CGEE6Uts@~sGBatNvW z(ctjry7yu%c{-^SPMGe8r|YCYJE%%=rgl1sQy3-pY{~c(F}ukE#QG&uxpLWX6}R(d znm&>O+o!Z(V#h;KCU(v0$H$8cvYee;{Bu(F0wRw^4H zKvO`*5Til=JjVe;df5`DS1l;`t2xt8;2y262@9rw6EH|`mt;I5SJ_46i_zhN?|}QA zgFkc(oRpA!rDJ2@97{Ap3 z6rN^(Ls()1r}$psN&H0L!qYhIouH%}dxiG-!Hd;b`> zK)(uHmbj(Xc=bJQiQk{m_qYvOGSDhr{O+s0EQul;C;*@53I?mbw8uq}c#>B8bi+lO4lComd^iaVb@Q zd@^tOyTLF4zi(z&m+_kR)DVOA+7;YRHe>;QKXOf?PFuEd_~&*T^bQry<8lzq)|=y; zxXdBxPKB>b?yMrZjU)X8okDDXyTQ)>e^d8n&8ni$m+(EGqAuSKqg&>oBKm@P5Kurs zjJ{z;21StZ(>IT2KDAFxzm9+RTM@N?j~fwztxvAZT)CEOnHn-Y2=o?`8!4ao}pkn9s!#2mf2w+^R_YstkfWX+e^T~ zQU(-0!RQTWIlo)c80b$U6j-By+ss??hm5wv|7xH$de=_h$te6DV%_r5>^)kWy(I#} z^i4Hp-u2bD_7KnxBEip3t?2FTw=fcY>PAN(M+Bp+Z@qc^FJ*$n14seq!`CPgu=3>v zhj+4b;O2GJ^?hpXew6}tA9>k-{1;p9<^MXwd=(P>TOnrs6k@h$0vqqx_Q^&U`Z@tC z{2(GY{GAX3&Kmj}V!jQm>f-!InKo4d9dGcvx2mGuCQZG*<=cK0o3_02m$B*l&;NQ z^!>68Mz2KK*9q2*XVWhef6{ePNeFXKL&0^u#guxhZAp-&z4$7aOT<1TpVw8hn#k;M zu~$4CZ-+!=3lokn#=)v9e#iB02 zT(`qcj2SN~FFk*C4y-tTTXGbjj>ACAtqUk#(k|MFrbE5=&fc!xVrWGe_k}o6$2!<2tr$sa_g5cQrsH$kZ+me#aMF8^y^V}Xk4^w(z zu}&aY`k+gy4?XyoFgU(-!uZx$yqCSjf#Z^$p1sjp#h4x8l{Hp7vVz+_TwZmzlw&_$ zgl7{SQzROo7hURqS6b2T+#}dPo8VZdIbaEEbt8$!5`v)u4;RX4-o7UfcG@S)6-FJ` zK}#i+3o3>Vu57F2+_qHD)7>@JrlZEN(X-jvOFkS6K2}FuW-Sv|Ts2LB8jIw|Cv1Vj|EaM&49(pg;Up+5kEq z@5$o7))wYFfGNsv+QQp94Lj_E#Yd{sgbjxalo0-ZEG@HTp3R4u=RYVZgNicrxulH! zo02l9C`12ANf}g>q4Z12_Nki?vEwqZzIwFvZM?mKeVN#|GK37 z6&C&5k}`lxkWq3d(1hofr|cLw114BGXW%%Ny|Jjua-2VtCs>f&Q{5d0#hj%Z#T*2) z))?D=i*?9(Ae1NcWK`20+jCai)3uIa2S+azS2p6qO;j`OfuiiVgPln71#vp?m-XVI z<)DW(^wRWK#4j1iAi^zFX$QX9%63HUwf6&_WYoVXvqB%$S%0Kid70@YwwLvF|Ad7w zo475f-ihADGuVd=@%*Q22Rgkh8ncFM@rLYw_jXM)7HOtT0g`g(8eSvoWgLJ#t9l>wkSkm6oHaB4r2&~lJv)9Yx?b?3M^C*kO1Nd z5JB3qMLK?$E8hZ42oBiTpvuU6YzjkyaIj^p7y(!{Td<%|Fk!nLZ2K7!pftH{#6Af$ zQNTz(db`lP$wwc>A@nV0zr_#aT}0g*4zXpjC;=GN+lc|0-4FyGU}Td4$`DY&rNLE~ z;AjOMe}I`JQvN2^#C778m$zh16ohW9#G;dwKaj0I=eFZV*6IHhKCN5Y_Ah-}zvY2j zF3S91a_U7*jc&iM-zhu&J-YYL3GXlRUFL&)_W~K5`z7H$dX2Y)-rH*OOFH_U$$Nj6 zzPq7cW_=-5B)WcH&yQiLUMlt{xLt0c7=)g*~JzaG_9f|$Xp zifBu!vhg)W_i%M#_GRR+n7kz8X3yV zPj~S4@fP*wLKX;riS5^E^6Bp7hYz+czYTva+oy8;Vvqyv@i2S ziaS|DxtC!*(AK%M7oqDobO&*>G9k&B5WzYj=fjlmt{42V+mBEAIj(T>e@ZNze5KPx zXis6eJ5BO+OQ5?J4K1Hh6&tE;>zKu;XPS4X#JDxT3~|<>L68(uLENl49c04@kZ~{U zC&X8CcpSN_D#zIYZ?q!@Q3lEfnTQkB?$YpWSpE~){{O(y9sd^qhWd}O)&GO%`3Io& zFV69M)J0+lj)8G+oJI(Ye}GAnBrpVFXo7%|4TX_73=_yls0$0h9M}e}(s#j~{30W~ zJ;>faH}r$NlW7!)Z+(cmwr7&}6j}0CCWcW^IM@Ii{k8>S5`eMd3^Xjz1lR$@3{dGJ zK~MV^sEcGkqdIv{qXXFVRxFF(A}R<5`XBLIpA57tV({Mho6WZ2e=0y(V?Y@re#<6r z&r$@aJfQCZzU?G{V#;4z@fD!&JUzdnE*%$kDn1?6oKdf{`ly1m??1@?|1TQ5FaM7k zyIY?XmSZ5dg8X2C@PWYc^0^xW{UW4rLa{PzES3P$py zPX60((*GJ@gg{>5{eR6_*#B&=IZa;U_7k~(_R)F2@Q}UUA@cmeZq+SJwvAY|9r(l6 z`+xhRjnDt(v-!>g=wF=4k7aoR$5Eiff{@6E#IKlmJI7LQQD^KO_TFe`BRE;GieyI{>F(jvZkD838c1k+&Nl z10r{Pz^u*D61>2V)`bf;i^QQ+)>fzMfH%5dShxRHj`VILMc7cpk!Hp=u@ zzRK<1x1r<@@A}oLU^Yr|i>2;#6x8{Xl@Qnl1Y`*M1$MZ>Nb7RYpswY#nuBl@VzDvbK zva>?GkNrXkFaENlWZRc^aw9R<=Kjo7xFs93%};cM2aKo8D8y;6Zs&3dE1VU*t&w}` zt1Q`?JND#Q_lT8&XW-$cKi~}pt*rBX#~w(WL7z3w#J|IyTTku1+VkjOfAaOjQLDR0 z4ajA70zw48ZrdMTd#afH=XIi8i_a%cRJky{5)IAWB)fp3Q6}UAa_BOWv-qQ{?_Ws9 z(+>w#t2|J3##d%VCh_20c6rv`9_LpWypHZQJ{LrT^3aZ_>sVI{t(O+p-Wj@a6f46F zOR76Dhoo-PA%L@9>Z>ave>vte!oAW^g$cRh*}-0UDB4ce_fX4Uhlg+$P9uiw*HKP# z3e)Tc&)cys+~`s0*syDDuY4qqSM23<$c`Glq7pRdWi)m^amenWxvhE5)e;Kvd>>(B zUNK+S5(RFXGg6IV$E7_(hOTZldbqOJ%zO+ebSY*0Fuqdeu4FbJf2Q*>FssNKlB>_U zeybaYa0;ICnZAy}+S_GvX0A5%Pi*O5VfgwjNxLmE-hS5MJxT9B6S61Uhz|Kvbl zZR`K?AU`_ug8$wu=#NZ-LISi4fP-BG`qxzQp6!JJt!>LOiFdw?qaaSwAGgQ15D56u zC}>VF2%x$F4Qu=@e{4npTZi~PeZ1wkAV5YSbSLku8Tpk|8fb3BZ~F)Qt@Qb}7oy%u zFk67#()lgkZjb?c+w!F(IMprmCvOX)4RJ)+oBD^n9s45Cu>f|!2;kvS$d>j0r3TCb z+T+w$%ALq+H^2OYXaZ@A>J4*uN|r(yed zFr0omd=@VgcmWpkmr4M|fy88Ifq^{-LJe0AR@2Hv2Ch`Ds+n^b+ zZ9D_AwJ`%NHUB3f;JKP+rDWqTNI~*UIPfJ{mF+FS-?og>x3^SuE~3V+qf+b)zWNgA zZ+~`4fR+dSe@OiX)7-xrT~a@dF6Cf!X}j5mcO}pbw>?Wjzw18UX}C_D?$_n{N=nKl zL{-0Zh>{<7BJ0TA2^~b)n&s=WuxjxM-$<5wS+vta!_m!d?(07Kl1l9{2bX!3h^ipq zOCec?S1+VblOZbKX=QI`>qC}fndzbgE^x2$IMrj^|?Vrkzba zmeX7sK7K}M^aam~2IJ{be~3?}^n(#1pWDK96V5kPD`-x=y}H#x!gJptj;c8p-J<9m z->UtoPMZwzH#io_+j$z6G~2c+9-!1D4r}f2mE>}LA<;-H(VoW|q@ytE={L6BCXbx6 ze^4bd_ruZz=F`o04=oSMV?~)E32|gH%rWh@+tpX)ImojMt$673!cpi0hNNw2Y29UC>N?7ISk-YJI-Z1|q8E2l9e*-$t zx7bJAQr@4-MnI{nE071P$lJNI{k;@e57xbm)>LMD=S*Fv(2c0XcIAELIIx1R?S*D2 zNWC^$eWi(G6~xi$Zl=UytO5 zms|2vUGiJ-x;Si>hSUyGSYK*=e*qO-VvlG^Vo&~To8Ag%M&f&p^P;BykX3ve=+KVD zc>Lyz{R^wc3vrFKaiY!gzKk32T#MZ;qKw^IU4k>SpzG5{WtWp}^yMDx3xA(=Xw>F8 zURueu8);Q3#wHWEwzm&q$Q&g~YPJ6GOr<26UGz>|aY-W1hrZtBj(s!De`D1^k(j5? z=H_sz%*V(x!q_C@WrW$#gQ+HWTH^WVR9&*uE@t~$sirZPhD#Ne!g;;dV+EPWt8-p- z@8K=$mm!H=ybT2>e7yZ7F$pgohvQ+=_&79Mi>O@7#%}0&TRNB6z_6XfLjlEY8JYV^ z@n<|vm*>@US7xoO*~y>kf8`O~daK%ZXUo_g}Upp9P9)wIT=^Gpxe6r3hM)S8r@rKv72Mi71 zTO5ONx%gx32C6aP@7s}37&J6s2Gl(e;_a}A1EL3-0R)HPK!P?x!3;zMfZ+Dv7uYR( z^B*_VhGCzVUU>yNf3Ny|JiGf?+SdNLgdp}a^dptA7^5cXB9yqR5;ua{%9aeKU-$?T z{D zGoL=Ya46uu*XoN(?lZ&03j7CGRg4B_yQe?xE+Li@$4e;pV zn9Y&8)kdwTf5r1zJg>w)Y0rGyESQxE-oger@v;njG^n$TSf$|z8ZDj+sbZk}-Gg7R zoWGP$EA2Vnyz6~fVKGHpEH)c~htN%GlsP|3Vgopb<%!ZR|>h+=NJz&f0ro)p~n0G*JdT);AO*-5ZjDb|DOyF zI%zy~>AUF-)^eUjz~ZlkZFv9f42$-9dR(bAum!*W{+>3sAcBk5RquMa`n$iceXV^`yulLb21 zM)umW3hUvY)FB?^@!;{1D!p9$n2=&VhWF*1w+!SSFod%Z=?q`zy_0|M+E`?8?_G0`zYF@3>K}f>YlcMP|)t~_TvEB57lXZUzlg=P!}(Ygh#1t zp8Sr_u9p{szqxqOAIN`rpP74qAnyIbo)KaXd~xKijs8r0WszfUd?Zv<-R5)NpdxXi z4(2{h2w4qfCBbQh*Pcsj_@l5M0v?+i=n#cb=4^SDd+g3U-bMFz>gM2xPg=i&^+whZ z36(auAdCsIQ(!&sV^f-YU+kz-EiC9lxbe6{JGJxb9{0(6zQcdJ)FWlQwT=bK2+>S= z5~~mHVe~>a$U~%V(%p{Gmi?^y9b`qC8!=P8rU;HdaHF(p4f9RPZyKMy$&b;~uH*$q z7P@ej`;Obc>JHw=TXu5EcE^l>+EcsKxP2DFi)9proz#^ZvHOmac5JD5LQWs0=ENBH z8*CCvDpW9u)Ol8_AGl*wa*YXDPNG>yDkW~FcubZ;eT5{uSO0#9GH!AA=+pSO^uIgn z79Jko+@oNa*}}}%9e{TEPl4$lzxYcy`tuk55Sefo!6^i#C=y`^ipFv3!3}NLcRR@L%f(t?r#F5-yZvU=pFi13LEoL8#@c}u`a~1KT&-VB62z2fAs)%Mh=&^I zU?4E)V*%>-#&G2PNl!p!IdU zqlYZF#_ea z$pv?zOl3E)BPf=i;t!Q8yu*LBKNtJ_Zs7_UH>9!4c9Y~jboRiu^BuXrX3w3Dmvl_x2%8P;MwG4kw@?f>#Cf`p3 z0_{5Yv)0#<%LQ)t%V_tZ5hVNuZl6s`&bmNHnN^*PQ#>FJe=OwtvpIA<913jqsU~cQ zvcUTJcl$yg>>Pc{7e!Ipa>v}}+NimX*7nJZKYy|Gra*pGwgqRW!4{F~uZz)R({9;M z%zlC&_0Swcm6JFYAUY|r#yerSndt+bcFdJ2~ut} zv*ROM4tq%|b}rMIisIo86OvR6p{E9wQElQ^7+qX_F+QJ*oN=!TEnc7FP<;a zdK)vWJU>V{Ot!O~&R4pei5H|8CSpHvgbO3|BESVzN7E9hH~rGOPfQRpN2~KY@BjS) z@VCR&J25-{@QZ)@{cqozxi6L>4C#NjKlFCE?VXZ$brDTLq=%{B zKee-gz-I`wvNucs>_ZYj(B3uzpXR?-u)YAf#wz`T*OuxPXa4Yqr5%txrn9ic3J(A5 zwKW?T8=c3Xk^1j5zPC#v59e-a%;L)0U&@1g_1Wo4GC>5wzkAa7;mPf}&s3{wGFA~c z&fig%%TIsXpsyQC&M+KyQof3wBuXSRx4@sj%kaLodY$dXXJCT+#V+jd!zGlTp8TB9 z{`B0BArJb~m}g9N(sBfM&u`LrVRI@Jm)kAfTOKOL{_CdbG-T(RFjI%a-Lf;y=m%#f z<#`nq?z1;?H<=<6so-=(^n-EAOV~J&8`y# zFuc0g=Uc|T;@uMWjc*|<)(I-<1jl^7$P_Z@aBk;I)ojVi>DnImk-qRZo4BHfz>Bd? zv0O|!=f{Cq^o5Lf3{Q=Fmtl`v(AeGh14*3Q^5Mt$nn0F?=f|FhTT*HJYG>)CmXltl z50-!9gmPIQ`D>m;hb-CeZ0WcgRPj!CF6%j_$Q!rjhdEM|n%=!`SwVIQTO!{LP<4OKYF4;xAIwlbu<^PyW0U9&$@1vXvfY`< zlv%)^`xs3QIh}|pR^}Z_^wDIrP+1y;9UqT`USFa^M~iLLyL9j(c)K62cDZA=kFuQj zr^gXrSGSnx`myh+aH@~bRpSp3nQ@8zSUl{~1_$mjDhXw>Lc*0hM2wQ;e9)2|jmCeX zQd};#Hr$dK!q7lK7}Of2Ti1kb_sCKpB^K7d z@v8J2OQIx(!zBGvl=@GO^CejQ>tp;dJp|(vO5rF&p+JEQqv;O^v?=T@LW#d!qhio? z3bEgrw{Tee_LBrc&h*=g82A%^EK&KUA7v4sDR29xZ|ley2l*WS=0Jh)@-}~s+%i8H zeupLs(2}xWjS9gypi9vpbb@0c8F;Yel3UE8GjO2oK|+I`8uM1p1{xwLP@~+U=@x~z z^S~l7SB}BpF$06g)VmIf!@sA0$%K+6uM2#|7 zO@T#^!q-d?d8b)|u>~~mlU0KtF3=W`zHT%m@u%9ScQ#ygve?i3E1?D=8DI{%3Vc9r za`PYL&jR#as+Gfw_S(|LB|@+DTl#DZVq09+>>J0KrHUG>HJN2T<+*=)gMMLU%zv^n zR)LlA7TAPC-3&)^EGarv5nN#mbPxphl`zn&5LC7%S8M6SGx}VXVonZPi;H&K`d&J| z9F8Z{{zSaCj3z%i`rfq(S-%)}5l1b{fa0)c+zWo<7^dXBwH*n2oScTA^mFJ&0(a7f zmkGD=GD^CcCa%PDS?Z1qrbe2-oD zCgd+_TMJCs7&>z`e0gq8{eVVLLpK&^h!tu{O2k(XSLunN;1ysPLv zIUZhybiY*UBi_=a$cYz?U!d#W3Z&K`_hJ^nmz!_cJMu8i+2z{20=y12oG`G6eVA9eIBo!qffMl_4ZX{YAeviMZG@Ltk#FwmW8YdP-y@?1y4u!gbI%{-tl> zXuqJLeV3H6(z9VwB1YMtp@T}#zBis1>(IO;{SdVoWznvxHM;|&kIa3!J%z-R=-D8Z zq-0Z-;jZhH*0M9C((0*y*z)qxjU}4iD(4(dhC3~Kl&BZ zcpJQ$Lk-8ca$s++S3pPSq{y&SN~s&~G<6!j^fGZ}G*qQGIQ4sEpc-rdkO3&^|Du5W zgO#UUuj$a4HqM^zl$RK6{8CIsDB4P2d9M9@fP8zC)KKMU`#<1v8_=mh5$j~|^mn7- zDkt5{A8da<_2$|_U{(2PQTgKaImIg%|G>d2IZLT<)@8YZRSfoOaU;a?EPG|S8vGl9 zC$@jBoEupgX9J5HSea&%{L^-mWwFoCZwFA>VB%_sl_xfuz>Xpdm|q*bWet{{St0&K z;e1s!|uGQhP+W0w7^V_)BP=DObfj9HSTpWF5zkgOX zg;Yj2qFUhGG+0LT(J9@=Z66x7- zPB(u-Bv0Y#jME5oTKx5x%;llwI#t?>ZlN9PWqNiRdcmr4d7x1=y$(VhUYnM{YhhRE z1|ija-3h2?IS>}^g>#N)T8*2Sel#i5=VFs`wl9Z7qw|q*XKh34_MTC7%?0!RvN%_V zF=x*wSRpFNNzV&L>V5C7?4iK!FI}o1y+eP~*Ajl-StXzx94%kQu3~S7)Z6XINsZXWt#Fs-3af$<<8 z{JD%h1G>i2lt($f7mc|e1Hly2r91UEuJ2RKP83CAnjta5$LnGDp+l?my&50cez<=+ z=uU!j$a&crK_QP6y)2SVImc)9B9o%i4$H+CZKd<7fOe#MyDvvm<{#EcSx<+vaNv)| z{uZy01@pPIt{qtpQ~V6e!ENhc)G)y%9P)aM_Deu4l%v zIH=T(8!5hMFAkI4({KmWm!gI^iFbeeaMIAf>B71}MRiT@ZTdfeXX^2Ps#noGiN87j zgZ;Vp@F%-{0gT^v`5pl>2t|+>OcFQ)V>E-}2*D5pMv^qiFbEEBxbVYv_y+wV_-%0Y zb{9=T&?6vVz=qneA;thag=PR}k<{@RoTu#j!WH9ypNUKs6WnYjQjd%G1nOA90J-dCcEFHy3JOEPG!^=6jQU zsM*8fKO3YyCfdO6QuBRLR)V+#kvq24B@AboGhp>JVjw!rw-(OK}DD z{-dDcpGL1gZxiyxTvfy`S^Vc7$3K4OFK-NicLvbzZz4Ml#=3(rlYNUv52^8$2 zeb(kWx$i`2G`d|{rzs`&@ZC#PkxF6|mMSd`uij5+?iNsbWI#6?W@Bwv$DW9B>Q0uABu&={xw zxSpljmD=on;ZM9E1yO%%+a#M;+Oep_aXsI+waIfr*m4^y;*qlruVZfs(87E4bP=NC z-qLi>x;uwy#AByF^`%}_^Z9s=OUg93UCL^Oo%JZ@bS3RmEh+= zJ^ANRC?DfPkUOi7BQwyqfWR|-DD1{mwP`t-0--nVW0S4y;LTWJ*o<+pf zsq;FkkDWv)Ztv@LKKLwmu!QV^?$P`1CJ@Opvk84pK|Y{?i>U*#I!4z>h7QAZ0Wfdd9xW_R_)+&Ej?8L-oK zz!@@l&JTY-rG16&CPj?db$EIFZEqLokD`Nce6`32eecA3apx}(|P7MZNlX0R=It6g{9Vf2_*V!Hbl%_-xUs(u93p><)mf(pq?rROUHm}^ zZlr!cv7>iW2v=W7gc_8Ry)|)Iu??i{GsQ{4!u_ zCmeqs)Xv0j*d_j)6Im!e!zT`8j_cPtn5a&+LTqXs<<(TlzyIJYPfUpH(u> z91}+D_O^&}S+!?{=eO^p9EjH9amfDIhEk8)$c`FaHGc&ey@#y3A=To^E6e%Fo*&oN zX5{ldvo5L6sW(~KZyO5pcJ7kv!-8)Mx_hnKF|{+qsa_9u2i-%1J}dgRv^qIrOt^nW zQy$lnH^;oUcbep5Av`zbnAJC>^rP57TM?sA$kp$T*F~;-$XWu<^v&E0D&cs)1Vhzb zz0-cc9zvieB93_Yizf=^)U45-54R7+KcGhPMc71X*Z=m&e&ZialXh|XsR#AnKS?EEdokV}~G_c#R_i@zuwlHlz&pqafzhBvU6WWaC$d!G{gE@W=77DoZr#7Tc}wh0Zm zo`Bz(f@&h3g0|R(R=17YTLMaG0t%wruQB{rC{a1DJkOoeZ#8~Lm$`g z1o^*WH18}4hWM#v#LWhI_N5Ax=TyE}ufCfHn771@HzYh)TxEN?UN*QVOE9D=?~$o8 z@R2%hK2;MxE4O{!@o*L$pnre+KDcdY))}BhYcvpQ6TUy#7nFE7 zv-dA;HdQnq+delS;s~iS(`*~Y==~zI{?aPbKT9Hh8{T}&1T98cA>WjTfnxu+ja$6M ze=c2mhHFgLr!!QZ)ipP+@-nLz|z9A!ZTz z-g0f~CGy43HIT3SwT7)ukoc)EDv49gZO|Gs1!FmGa9dv4>zBTxSV_Wmncp8QcNc=w zOR?QTYy73#ms@DD?X(^JZsZXfY`-%v@S*^9KaVM}uTPFd`B!ue{WZMiN7i^v<}$E; z^&lhV=4PR}my11WCO&@yp>%KBin`OfgXMN@d0dJhBK}q zbep@N#RI9QyM3LVwI}2q*hTj4I|UyvC!d!K#~$(R4kRm{*QHy8l%b**cDSBWv8qqL z(DByo(Uk=b%P@snkT4vs4||Y>*E8h1UJpE0c1JnQu&7_Ay`_KT*r_?QjAGc5DBXJG zb$TGX%X79wC1I{MMC9gv3w!n1FOVT^=zE1<aw5H$ zsb*1!%khPYd8R{GQBvae*ty23<1g3BG*#k-1vYOXs2w|PS0c}j@|df$b2nJmUzBCc zh65^_cdLPk5ORN#U3<+(<79w=|1?(8)3L0NJ1!w|0Uc}k)$j40SS-$+qtjlwOKQZr zwtZ6i8llfM&@DG5*UWmLv+ZK@Iqf5flSe< z_j@O_$sXDvXggoa_9eZ7w8NQ4Wsw1LclqU#%J7aMEIEH&6SYOI^hLJXahw(lp6U!u zj|VfJ3COSDt4SQN*^pn|-X=8dxvw14D|B~^G_ET=;syYpDr-a&nwJ7U0^*6r$Nv>m6Fk=O_f<4ONOzpT1qC*S1l6`U6Bp)U?EPmJUrS{w;e9UcHG}SS z$dDs!Uxg=WcQ8sbGK^Hy;WQ9PLxAQnnmdzTXtUwu!HLH#WTlf}>v|(G$*t_;Tdk&U zEN)+Np~JF6cppv4jNqO96md(2UZu*<(qT|vdfeY6UVgPK&EGYOeHa(uGTzTByvB!> zQxCU$vwfJ%edvy`$#YD5S}$dMtum>Q9M84h z-?uMq!q3l9zITGu5JBqkZdmnWl63#h&Ks zIyC-)*w*-qX`slCVcnaZLq|CljdVHDxGrN|?a^yLS6&yttlaA^LCxm~f2BXNn{Wu^ zkq@lsoFfWKu7f7og$^Ls`D{j_k)GJb{o5e%@@wxi$}K-IURq2`}_YN;{NYg;AiCvy^iMuD3mvh(rl;qJ!y}Je?PIng|7}}Z+8)+ zG-mUg2PS5$;tYM+`2CIfC-(*V=*Ik$`vQG*WB$o~fj+u1e|}$nREUB8Tp~uuyw|BZ zwlCCQs6`+V_m^!QFIl(~r6h>Z;$l=^yjHLVIqQY+ccnh)KK+t=KDQrm2 zOeIGT1c6B*e-gaufqBrPp~>W97OXQiaXjJEnxowdh*gDSA(}}=s79D)>2XE_^%eHh z`4T-yw%%h0Bq^{IiqfjT-e#vTIjQRLm`L4KNhZZbobvflsiura%tZ6+@!nt&I_zaf zQqIeLv7)p%F&#w8eRwkbTMz5hZK`&csc>dg7ZKK*e@EJ`h|{gecll0ihlldA(6htL z%maQfk7Fw`S^-U0nR2#utAu64f!8Rs^}VY(v8tNac!$uBOrQ4&hB=8T_!}Mx=m&F3 zUBs*Jt0$o$#Xog6+BQlKN*2#q+U3iVdx| z(3NK&G3wQ-Y$EYptE0P>Z@Iv>@_1{!aK*ORY=}Sp2=9(yKj_nr)hxc1e!k;y{{r`+e~b5jUedndeU(=;Oh~I+dF8IQyeGKJGZRN_ewg9DrG;YF zG^M(uV)%@f`U<&^ViJcgIc0w2BKC;;{O!p$1a*8}Gb2FgWD3Ykx)b4!v{P2Y`c@QZ zfAu2VQ`^2gR_KE4d|kfjlbfCzt!Jj=sxyhtR}Tw;BOE^Ghbagco6EOIp#&XlbMsNhKbfr9a{9RglOx2PYE^F=wf!s z&+V1fy%h>kBWFrU;)UwSDBR9cxbVbqf1UNL|2K7S*5oFdbqn9~EBc=AH1pIE?*#}D zGeS%fcgzSOkQl`9>kr_eY*)JM>h3pAd=XXYv{DRG%Fo(sKWncApX~h2J`f~+x=QI5 z<}1{=%Y8^Be{k^&yE{*T7)+4GaBI((!W`}=h96$9m*k_T<_;?D%dqjd zF4`jq6NI?3S@I$Zz`3J*-6KJD$hsU(eJsmYcYI5S zJZt)~3>=UnUt|ElOg=7?ZaC9LDYUt^4;Zc=3=9iewf1VGL^1O99 z$_+uYo)Gu@<$m)IK1`DN$7H4SgMh(if959I_|OaCKRne}0`Qxs`IZWNXuGpk(pdO8 zhkh;hQ*w`8O16eN7HxATYf+Ew@xaVBZSry5zsLK9(Kb|qewqoTx1EEv-rm$A_`gVW z@4WAFjTqg{{*&!ebo8^7e_~>fkBYWSZvn~CMk8W+w?o9Yk(zB1W>=0d$R;|*c87;; zA0XW*3K4F!A>GX%m_3;|j5kwdgxO>!$uH}Ee%e$aFZ2(Sgb(c!4_vG>HJgP2T6de+_m2)XV-FzbA~^ z7x((PkfNCrHb_eC?<0eN&o1@VcL7V^`z#Xs$jtX4ftbE|`KCAq@%SZKa1x~mK5wNu@u_V8 zY7#MRy2o8@%}#oAe@5y2^ZW2&hE!nxIS5eyJbUwFYwF|K8;zN+c{zdA9cHGta#T-P zE>u_2R(U`mBT*J~&cvOGXgsB!vlr7?k@GshD0a9`i_CSF3vw_uFsJ89L++!zt{6uz zXz_-X0BEh%k}FHNmv;p^KAH&Rv%Jawp`vKN)?%!X4e z>RgXAz-Kxe+}5(&uX>{y&qpnDx?;+Ez9iXZF<}NdatyAXhCa#kf(9wJbxGU4KB}`~ zc?EF1+gy2=pB8Z~F>)mHpfT0hjbCY%NNt$bC99e-HQi*MvJp(zhgrPd^~zusUm1^Q zpy&HhEt#Q9e{b=P6`7iG2oy2;tAawBnOt8~k)7X*IdL6-V(Zp+#5i=r1s6We-T>?` zLJxnHc?gL7D=e(o3g#P1K_SDr;vnls7tNvc=d(A507Vc2$sQNL_hbH=iJ&=Nr^H4J zStd@wHH8^6jNeB2)EGYU2kMl_)6(Eqyxb8St`)IBS@rr?vEF+ zjR$o)ws(!K^Hbf_Nc%Jhuq6zp>u~o{J6NCy3~_fZ{$+GpAeYVdk;{F5=3!LfB~CI} z>LOQ-`p77SY(q{BJUToHWurVbM1ZWTXVAxp;MJ0H$_7A>&Z0@U3$fa(rZI>^^9wqw zmU%$Pe=-qW+ONyYa#GV0p$@}I%@CR(()A^D9(v?YCZL_zx1(ZMmu99zmcj#mx?JZ$ zS>nn(D92EZU)I-@GQH(@cU|EH41J;l{J5U0xqit2J}APwS}?L$kiX+H+-A4+qxKtE z_s4UcG%o6Ex*F4BpUE_V=}(i1qaRze4~jTdl=d?xaeQQ z0k`JOmu8RZ{c+5eSN~BY-*3Y!@FTwd0k8CL!7K11zWxbbZFiK%FYr2T&db|oRTUkr z+&g+D5FUy5mYlM_oOF2<}e|ON2a0~njZ+`{1z$d)L`q4VkOaswuE53b# zkffm%B&$s#|!H%d_QlF0Apj2)7q z0x8sQoGvOJ#LZsfLVSD4sc$c|uRPD3eRBhk(Fz2R%m5-pd$6Ixi>vr>%<@a@f7PvY z%cW$6YFi_^{$$^~lW{k&hdr9p@lr!Y)QuAgP)(sc?8SZ@%|@s2#*XPaS12UY;^V zI^iOH29Lwb_LlP_aL&zOl>S(uf4vvnaJPp6DTrL9w`5MNtp|&nL{HHpIA-^g@ZGHI zzn?KIjk;cdHR^ECBq2?Ms!bDQR7)!l~UP_ub1N zGZl8e*M`BkTOc5AK=H@$XneC?yBo7+#BqqLhEVBLg2f8wE3Twb{m zeC;+9lamOq4H$rz2_&}-+l&O|zWa7q-U5tOXQx9g<`_%IIH%8bW3U%Y^v$Fv8g~?l z=00(J&YiLxplir|}0zCBRwXES6_2hyWbqJ$Ar%EUxLGBLOa`#?#OS$r37Jd!?8*ux@MelzLcmI3m z|1$vp?zw-7#0a(R8*L)AY}*am0_WpBd>-Gx4~sW?nC^Kv>t93ke?uf*QFf)0bhZ)V z&GjhR##d8#Ps-T?e8_OyGTWRP=$&!W+hD}zVVnH~i3xH$*IE#)6+pO;;L_B_TSI*F z`CsvP#b5^BN`yGuzDCHF{%|Nog&h^du+l=`4+$aoJH#_SEy3~z{@Ss9K^Cp^;v_RTI(7AxZPr&T* zQ|2sKh+Xk3b4Rc0ExJ@An``phzd&dK-75=^>hRp#k0)Qmf9dI}S%?`yk!&Xq6riW4 z-`)l^;hc7Xx(7bJNGZ4uVcB0Rxstp$T{Vg^y7(z9B+DJqH06#tiQxq67l;Zt9mC(9 zckT68Hr9Kas(Yp_+xpE*#5s!&SDkizOKx+0gwG5}U{9`!EbXKz$H#NXQlK~&N_Gs) zW_k9n=rR}wf0E=a6W19=A}O&g?Mv{WNe*_sqy7xWg24~`z2b`~=whnB1LQ;GTD^8X z1C%s6zIC@quaU|P6^MS{n)f8SapH2hh`R^Rd1%?_{@_OOZ!%(0nKIS@UjUoLqq^MW zrY(B=xy(Xv%BH`xK3t52II7Epx_2(!xD|OzS2Xk1az4J(wq6!lY9&M(NDm6W}KBr_8-3&_qdiOhGd9K7tM6Ij{SHfaCMIq+lpQ zDAf+BmoMIo`G#tCiwbgZpD%|RfL|!4UO0j*m+(6K8RXwE-JC`c^VJ?j@_>@lS*xF@ zTD;k&uXz`Kc$gH*r-ietg8_8*jr@H#ifmJJe|(Ch{VdpC0c;a{{PBYyjVFHZkgpyS zA3puNlsgipF@j(yiXm}i^N;vY2Tp(T%ndiGM!MVk(cy+{;cnwc>}Itz{#n8ieXIjt zpR#h((}81O1m(MpVf^Vf zf8ZU?@$KLh)ZtG#I_WO+-m#z9T`4ef!{>0verE4+Z^nx7?u3+WcN0>-gimK%DogvT zfkcAE$F=rtp+!{5kFRZ{7*;h@B-q=`Hp z!}QhLC~+B4b$o%Mak(*pPjPF+9`v+Y(k1mW1#LwR^r(8#*A|FEe^{hX zt#_cokjOaeDRf>b3^slkeqy(2YUC~8ZqVLNiZ%~k{dO}fH3I{QVo5%Ch>HcE7C@QS$YzvtFD}v ziJ=aEIHd8&9shmSo~~4kqyF#{f1;e7OU0S#Hp6(N^yB+Yz-2lphgS=DqkdCaL`g0n zrW#M=jZ-DY5`_L2ezIpv)!NYqW9JG@E90mJVShRi2fe)kI#9PO( zmbt{N0gWw#XpMiFA54ng0$-@@o`W&xLf7kheFQG<=~&!wFs9^3=7P>Ee~JY4`D*1L zcDsbsVRBH!ZT{PEChz$0`OoLjaQTDNx(1hj3=t~p5Zn+#zN61HInk!({; z>*?0ZtRT19DG?h}TyHqq8-Jzno@EZF+bq(0NCxk@AHO!+`w?O?ffmg3;y!Hn+5Xl@rj)oApAB^_Vrg9?3x>SKgeZ$BXqPLjVqo=2_uA?_y zdda0^oL{Z2k`GH5BLAYjZ|8?+pEbY|?CHp4#n@a}tYD#2isEbeJjuu@exv>+Vrs&Y zjz$)t9-@jx>+t?}f48etcNoF%|jsEme)tBlD;L;U28t zL&>(~%MX=f+;d=p2*yJ?;dOFcF$zN&Mdge)78xgT&fdB%wkRzA1;lU@WD~>^jt}w% zSeiYi6>GVYBg`87A3@Al&vjO=E?p6jFI{7h{t-PE=TK|bEPo1U{WPHN{YpVlI7N3S zGl8C$2Um1M!zEA)6LN|$FsJZFt;zWDjP#g3APQrx1%qh2%Ts{slRR;q7Frnr#b6&(4UbPYM(#FvTYO=qqc1Bm3_c_ zyw!T28-KVEn^*$`_%)uJ{|QwbcKJkH ztUplY(_>%n0{DGY`S>n?apUC8p`r-+j8h<|d}Lp*YUoj5H6ULFKm36?McsNzuA z;m(9V+T}`14B7Dd3zOm8C-FW4QwMc|F?^J#vO1Q9*VmlNT7Yt75>?i?3dyea;qLUq z5xl!tR#=mBRGL&#l~V~FZiV&Mm_r4@uk)3<1;!k{nv`e*04&S&EXE#@-SpY0WITs` zWq*RxSvEx_O37E{aSN;8>=`|mE2P~*<}raaq=I+4HCh|!=u;6YvjR#D>-7}u1zrbI z&pYO;8a8fgVt-o>Vfdhi*R?V9o()J{&!2A)J~}~40FrJ^D&u8uQMW~64!pT~B&bm6 zRy-)~BRQV5fu8%R)O^yk5+#9_xAs&m?tcpR8kSH11)Gquq9l5%mgl_8u$T?1fIluc zXoc+kJ)Fvz8}7rSB+gGpxJ~SKBkZn+tK?$^hmlPapL8(qJD;=$v_wUz!P_m_G{D0ZA zrT5TJI;&)qsJOLGL5&3`M>xL);)A6gHDv?D0ORB^a#A_T-u=G*0!EBgNSW`r1^1Z; zc~K;t$1TF@_&InU*yAEr5>ZTYn`O8h0tciPd`H1LYRW_JN}WT!MJ|=Tni6jt%Ap8XoCxp**aUGF$a zsLN~M=C^)3$sJsUZZM&MDkH?JN{%9PLELwUoy}Z6YxK1+WG&Y*QFz0wXMcG`0ZVaj z+v!PnuJfrM>l=etjlS})o}hX3?%Y%lF`l{n?4qpIsnRz>?9`Ja4R)|)+-`a1;inn$ zp4k#K{W;}W{L*Fw2hgTJ$M2_*m&SoSAXf$n^=k=|R(ptfaRRl6`?!e4%J~&Md#$yR zjT!@onoVbqkk4CyuC5f4J%8U`vC|s~K~^Aanj&dygfTwDM;ws}BTNW5<%QgNL`@=s ztfcir@q1ehjxhk2)p8KC^kIdtPrw#8NC#HE;gZlC4#m0{x{?awBO+hWgLzV)o+1QB zV7igtkW-{tz<@uFckmX?7EL~}7v5wXetx&KF+B(N?P6Hj=u(t}JmKC6qlkKodBZCOJcWviISCRN?Ps`(B!ebD;zU|P&c)86aq{vyW|dM*C? z$q#AZsD{W(B;g#L+JDgHotjyu5v|%G75hWxOs|SV5A~Bti?r~9;P7w+1@qZ+X}M!I zgeGwAkBMlsk_cL2)hvRdxzRFNQg`R^h9J129R>I}`19e#8YdK@#<0Y^QY;)8EFm%l z)bxN3Y}Fjk>`AJ5MBo1(xkOOZd^=GRgr`K}<^DiPpIDIyCVZ!P;g-K6vE zq?h-}*v37|^EOWhZ-vq}Pxs|9U2yj;O5poFO6$|$y?6Umcj7sxl$sCuvZEjhtoEtZmwG3UvBQbz^09Hl9 zh+^`jDCAtY@#1SseF$Q1!7A_cDv@rq$+zWRz?*ptySH{PA1zn#sk&GOZ8AXD!5wkW zZpR@g2Y((OG^`XH<_+`Yxp72q4hc7LisDdRO5IrIGyd!=b$*na5AzSvBzD-&6*+PO zV%Wi1XL&w+6D$%^{)uN#-wr5o4$E&iwgpoHKPFRhC986I{`s}9I5!$K%X4?OWG{!z zlx`vyw)FZ2wTyIuybcJPD4z}qOz?$+j2?7coPTn5ze#WRK!4g%BQ~0c?~59R z?>bU+(`rV0!xDivD!Z+Tdz=;?ZmT4XZGV?Zb_dTbpoH3lnk)NVUnZUYveh_jVvv{l zW$oiR!C^m~YL^VdVu;Y`9qd`|f0}mFgo)sR zO}CKv@JIQP-)b19m7?We#2`m^*LrNL)Mq|-^zO1iREdZD4x1f}d8lb?> zLML&kXBtc;$2YHta)yMXXyQJ>a+glK1rdMxxL#8<%E2RCvMcc{FQJzfN4`qJ$C;RN zF=+X5vde;obH}#lvXMoa;z&&goXaVqN#Zmik>|fs|CY7O3oTt44+4dz6@{9+s8)H2 z=VlB%+{i>L63GqT_A5;%&jmQ{eX*8D@7bk@7cYv@`FmRyicU{x5zxdrQSbFzUVnco z;hAam8RT~tu=8t5=;5f z(Ht{wL5a!X`0c~idKG|;PaReWy@LB7;u0vpBtdSM;*`)8=z{~w6P?)n+MvZYUCTyAPyQDqtdTht4Wbwv{UXFHHkro2?3wfF9s8NWp40^0+-wNl` zuPfj+#uA(M@z~3g6*ceo4R-uGcsoO3<`xe5qkd~R6%4BUYUMU{;iWG{k?H4m-kGy}Y+0uP>?!hCVx~WB9KCb+!UmPUsaN^P5aoUqGXC8ka zR2_dswjcC~-vQSOdk!o6tnq&~2z3AFb2ilvsQDk9<_j$T@)W-eN#5Ky=xyU_t-mv7 zQ%gj9B=SlRR%AiaO)9Ys^zGIj6!Rf6u0XWehfte9GQswuKi;~UD7k;t^D8v12)2G* zEBO%K^&89%m)O5>`sX3Z$$nQUvH>5mZwH3yrgPk^KccPrUr7r=ZW>QG-N1b_j7ByB z6EWMZZnF&OrY<3N-R73FMeWpN%hvoQGNv0cKFnW*BxgUMhwCkZ4SccVIOL<^38Lb` zqN%y-0{(}xU*p;2YXX0kZto6EpIE{{bO8@GxUXSUe~pe`z;1Vo*7rt1K-Sr9gyf&*caHi$R|)-EA~_r)AMibBKNIHtgTGStxo3R9+V_N#V%T=fJ2`g6M0F>Co>(I z8)|c0Z;h7$KNWAq%WX|V)Tj+BpNu7F{qtHZ2Q<&p3vkZHz+1XD0?!hoR3cPh6R4!+ zje{{soKLuPtsZ|Bk2j(NofQt18F`*Mv*lWd1}SI(+6!u5b0ty}9cc(Nw9s>Yi8NAw zuh^?HhIMR-2|T@J2x(`~J>8bvpz@Z6a`0NOzkUGoCp*XUBQicj=3L z!%m@C{P+O@`W;|9zf7@vlnJT%Z{?I$Hh(;q<$?Df!{>iG1^DhC%wDGm?8)%3Q_^O) z=q2%N;f6QPy0_$LIVhn#Z2oYA8cRQ1)I)jzbfH!55c49)E1Tif;n82ugm*GEdYRGu zB0z&;P5kSa#Y>nKtYQ)}qE_Y%4PDD6RR>(s$f6kI6+CfIl|7P_WwzzW`ruc-)fO@bp4u{JRFi?kQbkg9Ht8{qTUeEIWl!S^fm`sfj-q%z%yu zcgZNDg%Hs=G;uv&3;32V^JU8J0dQR@Q($Wscv*jr#Fd;~dQz5l9HF{1b%Lj;M0W3I zT55m0d1d~OEgVe!6QBBrJ+Gwd(f#9K{`3FS9DZkJb{Y>m25ljie>yh9KM48oKE=l9gwD>|sUh8B=t; zVc>rXG8^l{_NEiPHJajGyol_RS|23g4gNl1F-Csofao44x$?enZ;HXYja5ee63dbe%PQ~}l7BAw z0UT797b-wM=wGN%?7|-Jz+VW8mAhEA@vnb=Wq7l zH+%yQJF2Xt?VGtdciscAcy=+p<^u4J{Nsb;<%dR`U9sN{8c3ocS}mEH!4=NmzmRz95%ezYw>eR*A5GA=)Lh0@fOn$hVsM@P;g0czQbEu@}r3 z&SH*rZjeMVFJNb^#`V|o7Q_fAy;pw_Mp*E4UllpTWg9-9iQBXN;n5*tez$wj>n?Qc5!)Vta5R6c(S~WU zM+D;#he_7`bbCu=U*hYMR9sNdmMq~s5qE%j5>$#`PJab>e{K){QK|qx2+`f1wG(v&v+oKAq<3ln|+>4EdNcFC3 z)xcuQY;?3szWVxn6dv=LDjknfUS|Tf!8#=NvSr=r4gD;O&A62 z*tUVO-zH*GT2<)^6aQe>&qMlHzX|K)ALq17!!|DdA=h1h>xT_Py3Zi;4-`g_6|(-$ zksG!8=TCc||F7=h3ub@*o7ev(n6B8ii6vLM6m2-S5-5t9k zQn=01Q^>EtRM59c_UZ8#VCwGkbJY(Bbw=a~IP=`$3q+Z4QANk8+7Lz-#PaH&xBZt= zK8nLOZysD$G}_el+gMm_z$+>tzz&+V{)uKCe&{E`e0c(84A*l}iN&d0P>m2y3y@qNhMPLP!Kms@ zKnSUgZOk=ryLs6}pU8*>-pyMj7*Q@Uk38{W7)~yXCa7x_`91_KG`Rp=g? ztfsJ3F1*E*Pf-~0?A|JqETQI$IUdz(C$9JsQ3E}5XRCVg07aN&c)m>6Cz?H+$DxT5 zSZm(yWc8E=@$#W>nACcO_i3(FNm=f$89o`&D6W4t@w(V2KoochGsw>J&t1qBo%IjwOw@77ig~UN!Nnc9^%J8#ynEuX$2_+NAi|V- zeIkGN^@-M(CklT&(Xxh5&-?SX3h;S$KBKT|{WsPRCrZ_eGCA0HJT@lM2-+3!tEEIgt&i3(W#~hQn zCt;Sp&^#Y4LuA2?EOHufUYt`$GFh8LRV#mj-`~*#&W@t3Rvi;B_)H*5e_{{M3>jGv zRprnh1Uyj2#aP~Jr2`~#cRAaEE_{3rWQ2wrP+nm}QOq<++Q{6}Z{s`~iLvwW8ajZz4W;}nJB==v2VVERL9%xvy% zaIz;i?>$*0+8Av1sfoG|wnw{mBinyMqCZCSo$#)7cpF(KxA_Q^-sKkIPL{EKPcq&2 zL!*twuB3Pi^;?noXZFr3Lub&9?b5r3gCV!AQ*y`dZ6ff?WXO6_INGve$o;2TwB2^J z&kKg(-dxVMSGS&R`R?fZsp%-Ri+1e#v5>*Av;v9GTw9i(8+Pb70^BMrNLz(?2I(h zc;k_khul;iFOl#R1^2`K$@+*#%aL4P06d&&Syv}qHqN)lW_`9&;TdAj5?S(teO|nB zz)o*Tx_c64r^JChX3v|DFs{&R@WKG9isiQ#eCx%aDx1J934>P?oH&2iw^Bct^ zyfaqK)nL`c>FIbun<;-^-?gg+5NpNp;-9D@fSep(N`BPvJ8_m|?F}L<<%C+DOwvop z2gC8CI$3Kmo6gfnYeV`ppdt{ZbR}f!<#<;L27X;gd6)z?BZKR4UYY-iSr+JcdLL=; zrTM9RXr;l11>ALzN@VgW1ym6nNuCiG8hk%ch$;*N^Pk?kRcwEu9!Po=UMKr`!p{fk zrn_F@3b=)uI+6)v&>Of2yh;67(>G*EtqhssBY$~$iRc<3*RC}}e+v|(#}z*x2}|-u z*dVY3lQ0X-&CZvCN3MfzNGMx|pm_(f z_$^fzsX<=`J;fTHD6(+G!|r)d97_v3=suwfG`M=lA~kk}qQSSK*WsbOR9w@jGoa!Z z=82Z_kPB_+Pp}jfOO<9rPsbI_ayqLiV4n|~bULxFf>%Sz%2*jZpe3!~sCR+juqX=U zY4?Acs31n~@u)K25_q@lqh(#vhq;!T^ zONHqiw*0b)MIxTWm(5+EF;CI%3ZKeqvd*o}yvO6!p_ITAV$hJ*Yk8pqX!Yq8+zNa- z!|t0roV1z5wT7BSxz)+Yqd{~|c=b|L`R{*kdF&e$Yf+`$9=ANI&KG>xH z8^?Uzk^l2gzb)4=5+*PbhcSx47zW00493^ejiG6VA_x+r5SSpak19B9cPdEtJ$W+P zOn(r3+iE9?ZHoihT?SEjn>;0{pUHPWWg}zs?yQUL_1{+QZBBnQxwTYKbPvtjTPJ@R zv9*3SD?@m#4u4X?tz}oV4=XXut{*10d!YBoXA;|nt>S$jW-~sdx846wMn!AsxcMB# zn^G4>Kj(O?_pz0i>F&3*A4Mg<+}sGZ3hw@ObHh4LVBg<(LNRnSgffY~&bj~b=Dql1 ze6wVg!d2(4Up72WpOsi!6{Ckf^4x#KX5UN~X@D>ppVYNmZ6pMi`-dgb=faHLoP{>& z?yNi3XLAPmlbqMt;xU#hvX9RG*e-(Q>Bz6#@^iO{M?MLP!;79f$Epu6=PKZZ7|^-q z%U+A~&Fvmt@ehL_>nDwjt&aixsga?3R!ZQMk?`3hFGl%%_YKXWkL-LPUon4}%lhg0 zN`iuZSZCJ&0oHsSQ@i2c4vamn)uRV})oVhhJ{DTY+WMW)52up1jitF=ulKlc38rNH zce-5A>{dv?&5>fhuI>_1+dkET8G3-)^j)9${2AV$>TdNO1Ws??aQitS^q@YTcq10j zJbOq*SpskSet4al821JuCkubh*2XZtV)b=!`)+t=nGQuSq*e7y)aAD>3Q&3gF9yMD z)Wx0_7J$z#eTT(6oQ9x0#Wz;2QVAWZ_DI$?zVr>IJzCT-H2h+VydP?JQYTCGy3*m| zZdDv$woZXV8cFMSwYf{lE7kc4&pmTm+~d=^)aW@79`Kh^z*+C%yMcdL;G2oqY;RiF zy0HEJbIvBgTBy=%f3a-0DDr+HDdo;LT@fsQG&q2*!!f*{lX7`z9xPPy^{U0`Fb6ED z$$tEEL77BcAqYl*wH%C(0+@D(fi9cTh2}X&?@2U*Ag6`2NY-cBhjh@%GbxJw;ybc^xAYs{ zscsuySRw3AIDl~S3|bW5CF5KORu|Fzkq4g-%VJKncdMQ`Z1AX*J_91je7`txS^W|{ zlOlPEiUR@25C>_%!-|mti28F&Z>T*>EK!&{FX;F0e#rd#AVP_0{?QOj@d?%vw&C>{{J8^0FL` zv1$nh5TyP3p*Aj6+sn&U_;7@5wy)?n?Sd~qVeS9J&=^8u82V$&;cp-O z1*?8?;CGVh4~>5t$X#`e{_9hJf92!k9u~VYbb{Gk7NTvx9LKkB(2utUaArdXYIo>M zcJbKySA0)vCFsq)XGNxXACg@$E++Q~T6EJjGt5t*hzYm$#rh1C*m@Auo-!3N+dvD0 z?$~sQAFsW@fg5Itdk(&T}6A8o{=xqwIT|cm55}bc-!z;-C0&)76%>;j2X5r%> zTLXWhwfjE1`2*^h&LSl1I^KOzVYycA5%E#n(nvUWh6$6`rNH)NRS-ST7WF3LUeDGWMyipk|U;s3E3I>y$KJhWX4_| zK{o1){Gq|@=u$1?L{o239WZ?ivXcjBxQS-Nsb+ryvb~;ahYnCXk=whZgq@G`&pxxJ zf;7&Mo`8)Hnl6^P6)k!?A%n*Qg8+z%9_@JWTEsd=Mt&4K=S>9BauJ5a-$hc$+JH6fcDIqm=W_k!hwwjV= zSva;452KFry5-BI8|doJ0bv^(!}=l1nhrlM<>OGL!70THQavF&7bQ1vgv;mnl33Og zaiqx^Wvr)MUe02J#8nHp9VVO`DDJb<)x&@Elng9_(;x>c%d{6yU3i{vS!bUJt{>Y> zy@A;q6CdYC7%++(YBxYU7d3Z(LWn;jPNXmRQED#{^?b1Oj7*4jIuIf2spmtcWn_b0 zxjR?B3h54YI#w5F8#qDEZ8<5$ospOTeP7(yN>9|DwMgz_cm__3C;aMe2}98(B6@$_ zWRbExs&AtiZt>U{0Ap{1+E0V5W!_HS(q%$!S2|;`KqbHF`9p?C-rs!b5D6@5wa#hJtk=OkoIq&FQpOEM#)AB8_d|R_7;yB*^6=d%{!KpLy|Oj;{&p z0kay$${++B7UZUrIw^@5hl>0&!@38$eax*#B^bd;2+2=WsGC7Jo`{gMd?pHC>3IWy zS$B(*ikGq01r~o>5x2>k>^%8?*902sTeWtYxw!`!1*maAT@ENQqaoUpMI=;5v9~Jl zS{Ebqs$N&^n(*~qhvN37$lN>JeorlGGHKdgNk_M z`j$$$lIN(cUr3V^5NP&!EmO!h(=z3otY+Bl0ExC`mn45MzJG*C=dYy*S`PiC(_a+( zdMy}ySwCcqCE@oHlN)k;D$HwX$hmv)a5HNbAcKSJ*Uu+rfsiGpU5Hc`8kzy_Q($R{ zgfi@`BZtZF^L4{=j-$$R2_OkOaWjgF?9TKmf_RTs^vi48~fl)NgS(Snze@l z&65L!#9=%hVdcqq%KbGv_wX1pntDGiz!gD4-<03@gxz0BWF7iL`est@kV(okUyWAD zeecEoyTuarpA<{Kaq!2*68780(pq(_v>Vx@X*Pck;k{By=}k4UvfpiMBi-#ts7?Eq z#vgl;?7{aLwS6VY&$}fsxiMt~-}H>pzT2{%V5RFT2ak3Wt?g1j^CC%;?R0BtwLKNx z^n_@*H3slx`$|Qd)Ju4Hy1r|g9$k@1QVK`CewXgp1sQ*v zb-j-_jluC#66G)R9&1LA3+clQMZt@^Y|-)T-iWYvF}VvjHzN~c0$^Zq>+YZz7 zV3ihB_DJ4^C@EFvJk&lBo7ZSe)1`lQFVIc7qHpT0a#;T^(9;EgdF6#vNXMU!OH|gk za1jR6Vr$XB@zETEpt;(lg3MxJ+}$pH8q>n$CEpiZo-isA0}#eKtT{}KV~{ozcp&Q= zHu@NuNNNC;_PGZ}x@GkS<} z$940gqdDjik|-JjnS&GtEk)h)>76o-ntD)}J#Myh1r~XPBU3Il=58NvN5Tul_kj?J zqc!)IoNKYEkZ?|2L*Yi{g-!@!`9u$mG!#EgZa0Mb>M##3^~$@tHjLAVLX80lcuG16^L5oVa`7>&C?D zQ$Js9Kt8q|bdWh!2akV)%%-n+JU^Xf7F$EAv&GI2k}xxz6br{?7tmytZkkQq;K$zgraaq

    l{5hS*S^Drqasm4vp;!6s}%0rfE9(ujk+xtY=H(s|NVTzw*_+lpz zJl%M*^QsNOXCQyO>zBM?+6FC9>A`B%?2FKYyq*PZ46mghTF=^ObYgSb(h~=Wd^C63 zuQ~f7Z@AX*K$FOp&hRIEVmQ$vxdx-PGsIKg*-D0r5ibFQ6&R!pKeVP$c`jMFYO+=Z6<%J5NEs`uctWB+se3AY4Sup zM7&jB95549o9h=bFDT`@J~__d^8C8VWCLm9gtM38#`x1P5p&oDbG3sKn7VQGc!JIi zl&2?vo=ak;Rvm(!x0?|6=W~j2N1B;o-CnC+v;A3`qx2v2D*g{AZ*x0O|MkT){0nXQ z%3-ei+uwg0Hu!G(u!AxG!-GM*C(>uh|y|8Kq0_w|+ka+SYqc1+_> zE(bg^Rp`e%iGq*v73kw|PUc4=e~Nx;MR$(&d&SYif(bwD#*t6)>mk6Feq>6KqoeU~ z83&K_6P10fUxA>1=g7g!GU!jZSdkqIA3Mj(kdJ@W5_%Nr6rY6^s5c#q0vtO9_$dew6FWJZceCKz6y@s-UWB}&>((L%v?C=-TWAW|^ zTsFG@#(Lz|oPKBu5t7bo(~fz^f!@l((GGvO6nHz)$)<1zLusS4uL>rkCj5NxcbVy< zbR>TYG_-~)@zkR%K-ITyzwNuh2OJ$LC zP(1^OJDx_V`2Q$Cn;L(ondz<0Ek z@Mig3rI2De80=SDKNa{i%Ig&zTtT@{>pDPzcg7i_B01~qmn*(~<1fH}BQU?M#rUb4 z(uM%~oWWOEWaH}c6a{0T-=h0E6W4$DpAndy-*`9Vwa5Mx++E**ui|rafkOo=PIMwJ zZporfZYFYICdJ6j!M%AZF_l6U5`$f*kXYKIax5XG6>(=F0wB>AZ0!D0Of!GGaoO-8y1hVHE@E37p{Jt<$DX{R9+iVEN+H;*IDS<^l&Ur^n$j~ zl~I|Zelw?xb3b`~$g${Kvvi z`v9k7k7>+zl)BerlaI|j{(__bYiIg~lYeoRpP&+g5f~+55+`sN1Yrsy35bGm6oE*R zM5+BhjKqKI5`iKg$u06|xFE8ljS>Bz(GF=OdbD=zAe1LZ4d=cC{(FBwO{oKplTU5K z4z474obp%$LJnCmf;iTiVC*EmLQ zNjs$PFZ#r9w|EEB81XjEE*Ir{#)J|q`)AvuqkZFO4%rd;9odWxd{63F!byhfEXDDZX{iP2Y|GF1-`-+cr5 zJYNOyQ<4l4tC!Ljek`y2|m01>k1^@ z)RMP)T`uyQfG_X(%2Y1N!)ZY+%6~T<;Wk4#p6_tN~$$rM>@!0AF}f zTYS4eigkI(xSdjS&?8GV+z^IxYbjxKs(X82>G=zV1h9V*TTM(w21a7^V4gETo33PC zDb8KHE2ovtoWskoqI}L4mZ}KLay`RyMe?^(kJMbipHKbu5l*@RYl)@lJOHsC{2p>0 zTCq!Xcl1E>)AA&-tX#(gkKafKO;x=erC3nEfoK^XwwURsJOcQ?WxwV>>MVdi3N2nRrqTMdYNZK;g2x%3W$Zk?m9C6tgm+FP*j^2$&Ff%;}eb%LZ)FwzR$} zBb0xaR4MyFO^53Aj8vJuxyTJx2PYL=#5pD7n>5#K4PKqFG0#5C2_!4GEqz(g&1vgruWvS?|5%~8}n)@G)<=W1_eu_v!Qz(?)S zy6^CbJCAtu7hL|Q$9_ZN|9;%hy&MP*{AOr1i;F#M#^Fyf$49dcLqEa=*r%rhKNc!-^e|wg^5c;F5CA%q8RE~zmYK=N62ppUdYbJRB+_Q6-@qv5$f9vvC(a^*BgcdA3f^Zn~K;CI9N zC!+#>H>}@}>YsEn>eshDQn+=Zp!)-&{&`Lp&|L=Q($S+jzMlo6T3IQ4WRG`lY; z5vV;tdEeH0?oEb>^oQfy#?_W?mMF6h(+lF&u7;P(QGH;wXDc-%I;1S%Z5w}&^ofHn zAykT0RV7t?T_XDO_5zKguAn$WlJ4~vB3d_wmCWY=YCPf6?>ZV+anyiTczUhgoA;M= z?(ONW#g1~laD`-@P}U~4{#14DbM~YYBN|iPEMy1g$`F!ox! zhw!Z{s3G!yqF>4~;Ft2kf{`UvlOa~o^a z;LF{n-mx}gDbBe;#~o;Up6)7+ynMOI+_&~M2XSoE-aFgbH!z1%(+_Cnrd2374f{*<_ya)%{c*HmxO@~#HrwAfO8EQK&Jxq>|n zv;b8acIrU*Ji#>48OBA*l|0t#TNf3rDRQ=6OD9mZQGx0~;DMZ7gkVGZxxQj}92MJo zKm1@;yrIQzYDZ3|!7hfa5t|#lI1vV|;aLpamLRk7b#)dzk|<=eJgf zX*J@g;xLz_aacvag>QUor;QNzxIjd#P6&uN)!+qvlYk-n_jq~Sxtw+GB0Cpj*tBS0 z1({nz#0_W}#GgY2d?IKN1bw@%#c~lE@dRm)VGN7qmy8*cT0h zk8RcdB>8>AC50a)|2r%n8DH$<9|a!r2|IQc@xQZ=NYEaa?h$N}A03Z}Gz0ZfujECi#DHnVm2c$Z_67od`Vw=%Zl( zJ}wSb<$?)~F|Uj{@H z2dNSa_H?aaY=h=Ce&OKghUMcm=2wJ!HCRR6q^nPk!K(_`>0&1&AeH7xx^N*!PId_^ zB=MM>He!1ZSD&F7geMo_m2*E2If6lugv9s{$Zea;(KJ#1t(9v1>ekI#^Y2Hbj_+6c z=qZ1F%40y%*Y5W#)hvUU-;vwfk=x#pTYAVMzyD*Zjv6CTSb%Fyz9O-GN4^dwh=Qs2 zZ}4Z%$=w50P`?^~+-R+K`%>w00P#`%0;Gu69toSz29Q6VzdtDLg`ejdM`J2aQWpD7 zuKs}i&+R;#JF)|oL*0I|o(_~YyHj7aj&kWyyJ3;t*X7tbHzmvdUq+GMxvmj(C6cs>~U!voXZVUBHU^?aF45bTgjG^Okj3Yh*mk z)FGoH(K7%p-tu}q1ZEDmGu}ZZ(-S(hA&&agyw~M+S7z_EP;ZoeOV4giR#mW}zpp+| z|BI`~y8HsB7JQ)Y=XLx)$N%}OhWuab`&|kCm;HXqWP=z1BN&K-FhU^+Lc#*jZLa@T_#WfPu`nHfa@JJ#aY!Z)#Ru>&tuTc602}CgO`bw4mwon~ zmwFU#zXxggI}!q4bm4VXv$Tc(lD?MsrDxN-0Pa)49xg=H5AR*}_xOE#AHA7>O6|0H zNB3qCmTz+C3}@QRw;jH$dkXSbkwAW*oYM7rhy^o7Om^p2;Ey*S`HHBJ}(L()`!=zY5>FH~D}C z`Om~{*)NG?`A8%m-bnR>G-)<}i-o|3Cc#M91-a&co+_&s;LHi1MEA-u1>d6BbHaRX zi_gfCc2phEU3rQ@p2uC0dX?I^Pm-@lw}&9sCBX3Q1o!KB9hbx)o~Q9Kf^?0Cp4E{z z@$?L+UfUXwlVc+UZ?@z0iR#b`E!@^Z91$5<;Q($xk-ztS$h5U5wg;9AcWBx}e^uG5*0!+rsI3FoHKQ9uB5I|r=krE5VeCiVUip$of5VT6!T^4|BY7*OWf6b})+GU;3 zzL$GcP6N*qV|TBHdmJ_F16!r3bX^Xp&r#>+H-@Q13Q12i-B7J5RjCDW^8FMRW$*@}#7M9}(`1{G<2{3p(Ock$%>Re!4TJV8E zG<4sZxU3gODbk+16$!1+e})4A!_#9uWP$l`C4$l9x^Tt1-$>v8&QIkaHNY?RcRxun zO;Lvq1nW|{Rzl@-+8WI7_h8IlS%62y_ZkP%_k zp88NI__{RsB?eA;e`~9cspOw8lJXg!SedjY&7GROIUhE!Z^9>`=FAk_I^QgPCk(Ga z)49}%&jOUhE#L^#`p(PsHJ2#U)Rj1^PjK3Q6kZvhQTkeT!F?hdDWQqidAqH5N#ZAj zyb2lJ#ye{PI{P&-MI>7IHZ2C{UQg;s^ik3<`c-N}94EL}e>=>+yoxy4T*XYZy*FDy z$O=O9BqKn%RnCa(VxW-_R<23Fi>uwRc4EFkW_#&Oap& z{sfWS0Ek#=q&sVT!M%yQ-QOW)+EwGtWoW%QdT6lc`LjP6`*`5}jV}8(6<* zas^cMJ@NzcGT9q>@$+J=bR()A-d($1svD0uMbjveQ*=hQgqa}gX|#4#^u3;{e_w%$ zWj%|QqeB?-czzVa85j9@`m4g!f8F!Dg4DOYeo9x6e=v!GJ1;^Bl*B2V1b-|2xQF~Z zlQ`NG@*|PIa|@6^M@9krSf(E0%IUG%kE1&i`}6+JLvIp1`atuKJ3;oLI7xnRD~LLJ7j~+(^PY_O zn1+A4e=cD7;CVX%f^rbTBP`x^u9`>R9B|VbBjb)kSd+tIG#w*e{`nkW- zzcuDIZ-0pE1N5>ermJ&at1!0rSbq`MH*K(GOi=eV6I|HunFQB zk=^C$Xo$9DN4{eF>J;{Uo5ss4f1^#{TV{lHe}z4yh-}ksnOObFIqw}jVBmfG$92mxuT4cLlFo-g6RU~VJE!~ts}5N`PIrCsNOXVQng ze-zoIml{HX@L4(OPndhCwiWshK!oduk>5Z|d{d89RcQj(j7p;`ox0c>cazKEfjfC8 z^6!;3!JF5SypuIS#nkOv?`fcwjA1LWz@V?pwFfT`FXQ5P4U*t)=2st@xL5e%-}>bu zb`Lzq=>}~<`#BRa%E?1D05VN37s2+5e-k%vWqDlro~ESMcDAf5kJV9ry0WrF52P@}k93JqQoQo?lN0@U z=N>w>49_d4GmFM#JsAp3TL&Zts}^-xORrG>YQS_ zaE7j4ctZ9;@?<_htgZ`IQj8~O zj-qs$-05QXF^~p*6Hhxxi<-Vqe`pF7f<+@YZ{b{RCULX<{wju9Qf21w%>4+id1}QM zvxUk&&U>Q;W_Jus`m|0%2O-TlMb+zgUH9liwk{@&N3urusX5TmH^#Hy&hI02Ii^ct zhBEMd$=~Gp)L~v4|3fXoM*k+^A>2YFoTET{MfY|DB420{znxX^kUFjUf9y_e>W_;e zzV%Aq)I0QBJoNQjcH`#|Q9z9$KNkYNUWutH{ri;?Sl?0>t3p_Z)w{R-Twmze72({F zE$td8fB|oQGMJNSHwHbwoIhc6%$FS3&i6u%iD^N!mEgA5$L&@~CsL`RhGtK=qxiB-$(zILd2VOxs zFX{3)L1Z3}%f8?K$n!K{F8i5;a6cpcI5tEJ)6ybJhs$w7{>Ll2f5&5ZoLD63gl1l} zn9=}Y?pN5alz+~s?N```ybnD#nfo!4{ebEiS!{CKapL_%!ZCvA80o&>{t>>s5r2lx z(<=StM7GI@pO0YDAkBreM$;?J@w9HzFwML4#iTzU@%RWPEojG?+pkx69B0mGW}&$U ztuFM7mQp%f7=&igf3M$>MrY-Ig3p(@(aR4NE&E>}Y+}g*KMREWt((37xS>>dZ6mnd z5>dDvHCF+=2k!gMlO}wrtC1G#y8jjy`^m@;J{B$U=cT*Ptz2X6erw-je{J{Md;(%0 zeVK>UvDm^1qP@Z&iq#@<|6L$T6$kxi6q-jhQ6SG>a(};%e>H+Hw=&Q3+|F>#^>d&p ze*XpjS&_~T>q@%P{kc24dS~ybhp~5waF<6kv4)=YdYELF7K9-f<4VRxuWQ$tWS{i_ zM}WLV-A^##_Hh4-hUYzkGL6&}1KK~=<4ni8WjGh1_ehOe>l!bS6I+C=4JHIxx`6U# z`-peW>J&lGfBUM3`^{*(x*JkMy{Y{jb16P=Us3$v2U93d(FUa1X;2jC)$tgUVurgtT5m$GwBp#ORcXgAe=})i6&2)SRz=s|M_}skse{Z# zE)7QNgy#HeP__?4#FX8EHB_cr@?L^si!$w zsW=#<5MD0An|KuWV1?%?3`Au*-pf^0y9q#q(ZUnCX>PM*$(&l(Mhf96~ErETViYU01^RQ7id{K=c_=YxJyLWA+& z_DdHZop>TY>@D-dJo8XyA&{>v$`p8T`NO=kIJ#S?KUp|UkF+RC9wEh{aE5-|g^?rL zf7qYrx&p)EPG#^5JAjDL;-^M6ChU*={%eZcSUy7MfjqQ6zB zb$<~O^MrH-_>Y(G*Tkl0?Ey%}I5l)sfBgPI|5r`=p%OU#CMbT|9r@U=eJINh zCBt6>ksA$bw{+2OGOBI*kAcXlJ1z!%DuD(57Z*`$pReSF|7Ie(wC*011g48lCdjYH z?ETG~1z@1B24njh5=Y11bFq*W9D?l@yuQM_Fn%{81NonV6W}kRlZDA%GLCM1fAV-# z1d8dM#9t&xSqL9yJEaf+2wbn0+o>jhf%uy>im3wjoKRHeB_NJcwAQdY`F)*;3WMJ- zFMeIF(df*Vg_oMi-T;tR3)hIe0S>S46C;HzIcT>Aa&M1Ed9Day48vJeee3O8+l!9) z2A;xm;24NkTne@VG-i1|l=?0tf5?2c8koFZEE7HB?+=r5A)+*xI{Vt-a+&?_h=abX_u@obD@ZSq9`^e=giLIXf6ymor{xg7!2#t&1&ayxrt6qUn1G^RV;O#c89c z@ePkj#MVF?tJjTsve=S>VwChVD?Tp)e!r^t_2NFNsB4Omyh5yBUSV%8{! zOx+n9!)?XP*jHRX^*4X*nwyp_YGD(KD!v{TlwA!_wBvUc}y5n$xKUr-3h&OuZ%CW53Vm-f#H3 z`Lz4z*a2$Q>t%A{e<6v^2e&w#-Djqqxc8h|0?YCj_}=y@BI~c4b86*zT2>T-@C!$r zTy({K0g&*QpMD0;Jv{w8%qYDhvNw802ST@QO*!SSnu25e3M<3gpsDgg?xDFgfLJ*DK7eo5 zjoDYul0deK`?y5sXwLh(mI4>yqvLH*q~mHuPbh5W0_YNm{(m$p4f7K17cA!tvc>y zPwCZsoY&KYY|jv%Ol@mK(+Npd(DUQ^Zwog@x)}be^3GL zk1ikL?^Nb>q*8x)<5%|c_YV2adw#q7m1PDWf31%H;r#u{UqYYkCWar&)-e8+ z!KCn^)$+B)8T&W-do>vpIXF*pu%{y>dI-_rNBwsS9X(KZd^ANL>U$qgSOoploD)Z? z7x}Z)>|t3)9Yy6uek6$t@~8zTh~tbfa^#HTkA2Mz;R^++ka*>CK~q80xnJUK*dk~QD%Z2EetTl8C7j5cBl+CmkRD4()uE?0X2t9Mgg;cVyX*3L! ze-IHoA}-R^mK>Y?f_LVZwNxw@^#}J1s*KdY9 z(J>{`5|yErN%H}86Oe~YtS8`n3o626h^NEqVx}p#d({OANw#a{%_l}Nopr2 zQDYXA;D#fvL+u*8W*F=UkdQW!%mxwue}Y|uD=mzby~n3I$`L8ztkOdrp?bcAu{@u! zgnAQ`iuXBa6U93eFU=jursZL;bSdfjS?JP<@J}=a-iiIMO$7c;g0u<}ZYRZmybu8_ zT*r{?I%rOg1BXvh%7JS|*e3zyP)$-Kd2?y?aJB=j62klTU-w8xk+G&b;1`D_=-!Nf8|2(z5EI%^BlW6$z=)YODcBKy_#BhBMbjiu#~%sNC)f zWx|WeR7uXfBtJ)neP4skNlkX(sE_C)AF1>=sW!mdz4FHs%9K?%@&=> zGa!V^JU(rl6UHdN(XYS__5FMGM7)ov9!d-cYrbF6vIhg?QU}vxP`u-;HO)e=&7i9~-cuzW>X~o9@v*ZaWVLiRe@XRr&!^8T`hR|Q%Rer_ z-!AmEb-jtl_kJNQADVotf9;n|1_m5|@0eWju|Yga{g9);KFJP-M0`|S$oTLr+&LN& zA2f}icEb1jmOkiMSU(&P$%7N_^a;<8L=*L?)5p?}ig9)n6Yf0fXw3UG&|^E3`!f;c zV(*$0B?B=`xHz1TFr@*g#bmaUoOvGb<}k)tCf zxlh%>EbaSJ#y$e%(|51$CmW)m?|*G- zS3L^?qR()CYL5DN5C7!!_@xSRJNoYRPc>u%eo-ovH{jEhzkT2M(--u2z8~PfeL;Wc z`vLyj7xZ_&AK<@zL4W7_`A4Qw=*vAfi)Tp>ul58CXU}d3Fz9tIo)k%cQT8Rqy_>n+ zG5cI_>)lq2$ecZyv9C@e+2AXy%nYu`_gTd}ZIj^6NLC5puxdHUZ$awpYjXz^Qx_vH znV@8>`xqPOiW6V&#!&ZZ9K?6}8!uu4nb?KB^hwj%0$@^CdU%SmkK-HO5~|Smh^5sP z)mo2j!j1Ml<332UoM;Ari|RXDF0DMATsf(Gff4@zp3te}TX{*>`}KC(nGmjWGdL`G zMS9OG+HMz1JTYTU5Zcuw9;2e(1Xb8v$*8hOML3{=&_}cM1*S>Y~h(5!?3gY!9hL|Ohz@|=$w^QmlW2*a|YLjciy*CW93*6{W7iIN} zpmRgVxe4&~ZEsyAwAFJu6D#7L)U5*sp--nBlLH~RdWl)5-juLs&Ok0q6>Esf*tX4WA5(Slh;&k0J!9gL?w22j2o7@ZxdU8m1PCpKR1T-n?;>`UPEXq z1}6-XJ5*+W>id3=$A^Vym@WwWpF+{ukYCmFjMMYk#kA^ty9SqM2#8Bi(tLE;Bj8p; z$30{LQII;f#@wAwP?v?FWq_^i^Dyrij}sjyxMLA6WKv2zZ%_&lgw9$dNO+bej&zrt zeFMHe%FErSPH2iIF5L4wOS4#MCVl8qpUn`t@=SGq1E2n^&?Nc@*csfhY1Te96XNFEjd?rS`D_=3`1Fe?i5Hg7WgHM{zw_yvnm{_!@g-`(SocVd4m-K8STVso>ps*wUK| zmrJTusc%x;IJI@Wsw#G5w^#5nC@@kw+=?ol4;uijkSsh(xPRZdFt@^D8xH5H^&>!N@m%x-LCbwD8n_bHE!lL9)K__#FW+^O=c}Bt9WHQ8}CK zl8XN7q{_-9N`_ONM*?Dly-x1odH;)9Y(Zv#uAWaamLlM-!wqx4WeF#_;@2U8mTcmNs z$dARxpE`p;hko_WL<#bvYC#@-w1=J)afmzZFOTKr>?kV5K5nMuM^rJ*js_qUJCepoZ+EEMq{s86Ul5W@)yQVLIS$W?Y%JBYOd}#;(m@QQ-~_UTG?A+H z^5@}BFICL~!o$I%ftJ_Syp_45&u(+38fwBu)b#a0rUE4+$PDtEIPXk(BTc3~K_zVOCA1CxBvagjQb_kkJ#qHWAz0HxF zgUj*j3Ea9%Y2Z$-39nbxK+o2jIO|fHg0;1@R|t1Qx-)fcJ!?*wAnoqD*EhS0o`02S z4oMsSI=OIusxJ>T6#R{Z ziSG0q8mmDEye9=0*{0`J?+g1%HFn>h%BqdQ6TMUU+Mroreyx>!3b*@z#^CW5)j1CG zGHQiUt|k|B=oC*w!d5R{`hyAUd)?RBirpS{F$ym!@)khmA4h`ud0u@QONJnysw4{* zA+KAhXxN8l>B#2N#3Tq(UZWNYrWVpecTj$Lo|xc32?ftWll$6w^$B5I(bDJNHhIcr zuTI9cSc2-72{+niO6~4{bVIK#@f5W2&GJ*2F?E3I9+F3mWCe3$Dfwb1UbfrAqT`!pI!+P|LWYm!yWmNsz5$vOvf_b zM@jg=YVuG$F3;S#?^hdh{XQ*Ml7UT9G>r|gij=}M{#w_34B|I}Y zN}#_^_150O?YGi@f`5V@UggX|@_rEN?Pc^Y ztq1h|$0=Tx({t)jC#FwglVdMsD9Ak+Gn(R&_X(@WC`4Tv?JTQQk_zvz&MEx<8ZdOw z0FT2>S3A*=5)ioRvk>D5(>`k}UXhF*2ah7t_(9)q%N0o$`1HPEuS`;(&l~+r;mZlI zBca;C@x+yX+LMAGB|^&{=b>Kw+HU12LTdyytpC3GQ7I{8nzZ#)Ws)$OX9>~6#spA> z7`>QBzdOIBgPwaB_i?$yrN=@q3uPyAiAGURfF@F>bbpSox$h?LaDV2 zm7TZkqq@(PA207Bg?ZB0_5k*bH3q=-!jM@>B^O($jF~jyiQ!AiS`0(wM4ogd@2?~l z!6kny)L`rE<+j`&oqL~i5i`ZF$We88RUH~8*4OJDaZ5dZ$pteKfE}9 ztHyXL^Lg?yOGJvJfCKqRAskLa=tt7;BQ~_hI!JcJKymV0{MsX; z9Xj&(&^w^;qs{J!_dbgN`^JPkN?u8S=-7C~T3-}+KQ4^;pVgEcaTtEAgJhp(Ljpgf z1or@NzrcPa3jRptV@Fxaq0XBe_C$xmA$2S??EfFm!q`zOgM6^>&?!QXC5(Mc2Ppp~ zehJ}GGXd7$@XO7Gs!*TcD7vqkzNC=OXpbpM+$j3bm5HOFV6nNM5y5Q0A7li79u6-E zPy$6&^f3=!55Ze7^34wnee2e91n-BP{-|v&HJg#N?R)j@4oUL5hb)NBSqHv>z^@xM zzWhbDNYQ_gT)6NnV`V<&hyEA8W8e?NV|1TFzv(h~KkoG1J4xpF(%Q6tRB>CrTH3tL z-8k>_``cMH)VCc!QaLJYdPQeToH}Ni$wmhHL6oVvOv>V$Er?&}<}xNm<;% zo6+-F;p@5VpCZA5+})EI@aE^hpbv{nws%9fN4k{a{Sy;US`i1_Own_-`BIEfC2n#_ zux#XppVCOf((69`K6PRLxd1pB6!U_oiwsLBTB4O-;KrB_D0592s}47R%z(z|0-jmJ z*{Fb5z^?3W?}WYVQ=t8*0MuBpXKTbouw!}IIxhhf80}QqkCU1`Wc^Xx>~*yeAERLg z6%(UOaJR*7YaG(&XV3#~HQ7@nV`-@=;Q;U05zYMswo9qskwW7^m#dw}EK=gREpfW5 z1e9M2-+VbVwO&sTAWjy4^p4w2I|(&>?`S%T=Qn9t`t_kbUu1RLzaG2YnlO5H;M_cO z8L|xL;So@D6HpaNv?iho=B}wVP*J~W+~Au+L%oR0UMd@S+#YZfF(Oc;e&!ts5g%_t zZi7xu@yiu(8n8J*M8l}qTg1aob=&wJ3_(CQ<%FEv**&kEwdOT1Cwx+LO*ZF=VLcIa z5%2VM0yg&c>fK_0bCg|?hO43SG8jlX%{kA4 z(bqa68jtvPt*I#O4CCx50<{e*vC#~RPF79z(WoW2Gcg*IacNZwW@}dmp25gUm(ILG zq`JsFZun01!qdqaAbr)#ey!yY)ci3mFRXz-@W&qYwwsi(qQPaBjR7HBPCk4qg=c#& zYu%#q$$>e4G09JNq;p?G%_PRj1JSx^mfHzg@wEf9^|6XP)Oq6n$=rKwJBlt_gZDhe zx!34lcvE*+VFU;(;12H*0wm1S|Ddd_U6qwt_U!InV~u5y_y7q-%!rsVV}1h>>|yYR zj8eL!)XloCEz`J~umm?7>z_KKZvGZ$Y@G^}KKN>XfmEhkrA08v$eJ_{7$A!qIGkvC zf%#{2%knP7iK2cyqLp|}VyD&IjT?~&r!r>jjEiyVaf9lYbpx|-Ud}b3S&U6K_Kt%u zT%TV{+1}T;rOE4b!)YLPQBle|iP*(A5-607jTd)_WOMH%lJ8Hg0)kwj--d(hU>XxN z-P*T*yW~WthlG$mL(o^kAKS;>wtZ(9Jo%iCIMvaFnjv>63GYP@JRuY(#AS~#Vxn;H zRESzoaL!!g^*%&4BYs~oa&0PaFh-IEDZ=d=RB0kZm8I4fCZH?Gi&D+jB#pNgmugZ8 zHK-eMiwNqb)!jmsmCc-AvJ`K=?s5MdRl)y%3|0Mjw;!S^_#0G(P#}ciAaM*nps*cP z5h#j(QUKHrv-a&f+yY^ogi!*kn%{L?%{M#py&ADL_-C=@6gtw;8TM05{)FH^LRHyEf;l>W z@YpeRGCT+!2StQ9^b)|&wC(6K+vpfbNgSE({n-1u`+;|mm?Q^%7fcUg3Hs@n+A&vz z9=Hr5_iOyysLB*#P!?WH8H^A);;6DsQNKoWV&(r|psMoss7mJ?Ox@()qN=YO|I4UK z`rD|g7|Q!fn^o+h`PqEEvEg(bBt$HK+es*bQpkYklkA+-eO;Ewxq6T>3L5hEa@^PD zdJhlDqJQ5n4}3Z=q?=K9S1hhqtgv`S6*Fy6??8tR)tbEg9ZdP^5|OW^!t4JYBKZiCSAA#x8~*`kcUWD~6_3sld}i+RlA{J~mG2 zbwVz>E0IIFu~zz-E6{8Sy%?wCJAzu_cmj0di9#sNoN#Zr6F0$Y>8Bd9Z|#)ldVhMT z<-EU(bpm3z?nR5*>V$A<3xW{z7B>wDcu;38mv`5B8)NErIa@=8L;kW@W1I~c#ILz@CCuzT|EInHt7u-Ct0k5Io7NDA$G4ZpEi?+=FO;snAgs!ZtBW zOX2n6Bq=k&wKiR4M?W_dNekeuIpzh~@#I|PhVka`Wxra*2;fi|hLhAejX%(j$0)Ei z_68;Py++dVIOkDSP|k`p01=d1bKfECxrQk1BrSIusz-(l&829}$iOM|I&3J<^KNq& zXmkLp^&a_mvYNG;zFvTTm_?bvo?YmF3sn(m@=luP+1D5OPKHfFOsmjcqJ;zh09DCi zmU9%xde}0*vtdNb8|q%xHwQr{t4P-C8nnoiJYV~3Zwv^2z1kfGb*hKs038nE9YeweiRq+c@vd?HaVFrFg(i2fC?;o z5=!r?+S7*Sw?zkjXpZ`A;nbJNnCCM}+;~%}lzXRM;XB;k)0I{Y@Dc*|a}ZqoDs}xF zaf}J|=tuehuhfFU5=U}tN=vmX>+jM}rPX=TVmcU6g%#H-Bs2r&7Mbhr|FO5|on>*oU5m>l6CW}UoZQpoH%{F)ich#= z_waB}fBA255km*1$0EQ7&Ez7fp`MG2d(K%}>AapFP_@4+q6@@hxMY`xn9mMu#!C@3 znA)grI=ph-d%VsRiR47ML*?!Ea+&JH5yU%tn1gZB=2n}35+I2r?QW!kV5u1N7PF`2 z-=Mk@N8B$dTSe~uep<*2zcB9mO!-bAX)>7ios^6>?XKm3!d|N}xO1C-ZxM^UVQ^wa z!}u<|4YImhx7Y;zw)h>qoylp|WV(4vavGH`S3#+ts(|R~>k%|DRV7|;6*`KFCZ{gq zybVs|%hnNpPLjkiFY+OC&kgnpeFxmD$k;PkwvP}6?$!XC8yJ)<@+i_vN=S|r4#KFZ zbwcp@pd-~3jFz6>TMp??>OV(S$Uj3>Ki=(!s0#T8RqcQYq(B0PAOhUs)RCIP5o*U* z7z|+q0uwL_LkIzq6pT<9`CWp+0eh08+!7{7u^#__Qkj4bI7EIXM}Wvr6mf`me%Pzu z?|&i>)b)kby2GoG{M2qf^x2g72?0M-Fg|Il^wT>YXP>sEbU*TsP!)NMX*^~;riVi3 z{?z^G2Oz?ZzxR{L$RnFZzy~MyNRnm8;i2p!sQr=i1V3}B4xLWwDElPjku$@oqXi26 z(}7ceze82m_dTM^vV)P~426163?TPVNh>UVZwUWiKvnDSP}MOc0R9$L{j%}DjH=YX zjjFbFMvVX^o`RfqYWYyyDmaJyCXO(PON(U!=cPIK@pB{w4eq?5FPGO4Zen!GC)-xe zLT~oiP3qM%zGZTP>98-YENG|e^il^!djZ0KLnZpwysD3m5DFj7UK58-8fcAj$#$xO zIPKf?tJkg! zaehJ^mum<4scv|8XW$aiIB<`SX-a$xK^%n`C(u1>2f0*?&JJO)UdgYGTM_s2N^*A< z&cbZ8x`{S<9Lxx;DKTo^W*}W(%YFlY^fSnmS9_AeWUg*}HKcQcJ?}{Pj4nqVz+%jiTe7Ua-fjMuwdDAyuzy~}eN5@X_TCjYpJ zQ!$;CTL7LLf?HHyVtT;c@|1R8nwwT4LUL-ds-We$B-Q68z9K2%@GpUO*zClAog{sP zu;nsJBj()_LRK%J0nn(Yk=aQV29FslT#7Etx#mwUb@r#h;4x;l@x*7SH`o|NdX^V) zj&YPZ!9-*r=IsQmi5^3Q;ywR{TIV04s-?(`w^BXn`nF!?Fz~FGAziy8W$_27iZct? z4I%!KxOM_pnk`&jxFN>FlKJ<4>!Z)ctF{BzX}IA^0G;Xgy?A;Nm}2d&_gLAi z=}gC%+ifs5GD&X8*B*}U~nWIF3uH3;!Ju)N#&2yXyLSLc`LJJCcm@@XB? zt82d^|BSO720qKv{)ke4pes+FyXA2yBdNd{dH>ikvarmwp8<%%*)KQjP%NJ^R8J6e z9y(6Z)!v?IdoGop;^vazTCNs#@lAR;!|r#)Dt9ec+@b~`Rl(#(`YPr|#R*npvy{9z zgE_TW&fVW+h`t2*Vj-o053-X)HRRM1I3F)(j<1PcAF$3 zK3OWS7uoKa;jXYf?d*0^M~ND6YaYFJt*JuAmmo2NIuP!OB{B&{ zVChT9yF{NDrUEm4N^6v|ty1bwJ6O8a@MRFDGqCQr>;2C8_siX_9NVN2>Ll-wV|Z{7 z1FrC`Ulv!cdFu>+`KO=)|N3~6GB1x-p#P!wZ9|&;kHmd}J(n-KT2_-}ZmvNBixtl7G9{FQZF-ywGo$n;1f32ueaYNTT2lxhRChQ3ON~9NxhfN`V*( zQQt#f2VnY)>OAlaa-@Pt_$b01EkMLEPAvVjfbT$v%zmPOlJBCg9ju`rZJr(Y?8xYl z7!8k%5(*yjI%sx4vK0K_F7OZurI16}97}#evLB$Y9T0+_`JfU0=~71yB_1+9XgB+w z#{sCLv3-BSer{QKR2{KTS2~0qRl^8AN`ol%`Nob$rZ74{<}nL=zYy$CnJ&#Cbl2g( zjQeCUHP$D89}7-;2^U`#ob5I|R+`41c zuW-Hc}r%ZI5+wGJ7suQ+Jp!+X+yMu4&m6C)ZFw{9)*4gX8~y1D&K z<+RmV|4=!PHg)>v*7bZogm!+}Rx!=DT${gr+P^-3Yv7-p_SdsMC^o=fu0;bK4mn2TiU<}yAmv0~qgvSzk19i#l5ayL<@4~C9gp4g^TmM} zrl;w*v1t4a6{j?gfvA*S^?vu>iRys`R+7~F840Xdj zSebHvGNUVx@|4&Ed|uJ?m5!A?YEBRuZgE0S{VdKqu4O%QcJJ-`0higEg5fl}t(`~r zZe|T<%q>W=p@C>Y%y+Nvp;i8TVemO_`g?4TXXth_**E$i@Y@Rx+BZ$0Kd|An<^uwFm$=`AbZewrBQx=X0A*8kh0=}Q)V?Ht`~*Qe`N`b`3i zJJ!p10`VzH7FF;Dd*qUGc@hR;S-15|zpPPa*iISV_gg$wR!dZ$@TQf^8bSjl0bnJ6 zx3fRc=<@soox7E@2VwCXp%G)s)`P+#A*~)hB;6?!qwwAA{ zX5wbs>{v{=fseV^tlm!q6mBn>P-KRGt2cEOlKrMfx#tL~)uRpC`!?S=_6_J7^?ob* zNwMheiP&d;l~JTmEZ4-j$u)BNguiBuqgo|De6z7m&x-3kP2;!RI;V~ zN00rT5!gR=Kgj>4Q~ZmI{kc;_e(Mxb>`*1ANC*T;3_}P6qF@psQ3~5}Cx*g*I6-}P z1~&2Gd+uHkfj$+VFUg4HDDEKXF=smcg#BUiY0mvVeI~<>hJx@j4D6UgLLPm+@yE~Z z8$s|8N77zj26%X950=Lp(eSaAXMnsY5)@8u&L3@i=SX zpE*QzPCjCP@e}y+s!9x#J40?5w3KTlO&bA5tfP7Hrfs+F_uESw-LyAzh53 zMk1dezmYQ_=+F#H=E(Hw>!t=a+rye?T=!V4OX+5S8|$H0cA=DYcX_Kmr_)L1CjE)M z6J-Vw24GtB?e6&ow8xGli=^6H9u>R&%T5CLo|o92#1*{4JsRYK6AGG!D_k1mnrIDm z@y!hd(6iR~wvJe-v$-F`lZcV&vnn~TfVZ!PMSjx+C;0`UfEL^AS zjSt9GKtZVi7FErv;tV@yddBW@rT1MqJyoLJY+RfkM%@W%ZR#Bony-4CSLp2&!5F^* zybr3db%nZjnCb8ImHlG3el4N-ufmIeve56W=x-PKwFO0C3L(&c-BN-eic`dHK|fIj zL17>QgD{Nk4}CYMo1%v$BEzF_jiCpr9fOZqM=1WOQYS~=^vKzMDD)`$T?3kY;)X+7 ziuwo`;0ODjz&|_T$B1JBInY0dA9TVv{tQvhj%Xo7e_%j&)48v>|2&xY;9=ZT>f)n2&704mn?2rfJ$j zgk-yhGCNtFcQ%Jd!RDn#nT@k%FA0Fp`ircda&0d-_8c#l_I(>zDL6HNC(K_u>Ab#PErS&jnn71bZ7h5SFsQly@z+2KAb~HQX7Hk4zP-Yi##bU{lZEC|z37ithkLXEs>JG_K zwJ*L&TLOPIZ&`ekwzNyxk(km2u$T72@-u!KYKt&@uiEPG<}E)XG%rl2$mW}?iwfVw z1aD)1AK1MibyM$Gt2_7aX&eOVG<%4KD3xUEzR(#Dqatg!)6!LXpUc~L;Z;qsUJ}3V zPWz1lS}MSBa%zp?Et+(B$+iHLg&~Y+(7D@pimbb2D$epaL!wf_!IhZe7vVXQehEBC zy8uEmJ=!z3shV?AQ$;IeqAI5$Y$_DuaW^A>Z_Vt8jA)pGcX0^1!qLkjJGQWrk-R%F zfE+G*8wzip5STc_C1osbJj=MyS#`|R%gvkpEHG!SXX5055q_1CbGa&*Mb)wy+9}Xq z_n1ioqs&#Zs%f}Vy3}16xe<;eTKJHv=wBxXFP=(&;QMxeXBU3@*LJs?eY&L&B0YH!!uFqsz)*UeGXj4` zBqB%g^k9sIN6m9TVem5>=!kZxpZ4eo{&WJQ*+DYfS5E$vCC1*4-m&=pi|=Dx_x`@g zY0o*(j2ky7oP@agUGPx+w}OYi?)Q#5C-86l-r@Fuf8+NKw+H+UzqhHPe`s)ji-$ej zD)5jE761k1d770tKc{&l%z_vCMA`Fr%~sJOulOlGtD9#&NlhQprGJs2?7^hE87$Ek zcSyJZS&vTL3D^C3_6RzesrbZSYj%g#`PsOG#E|Hjk0k%mb@WBp0r`+NupgBaf0D1e7p3ba0Q@20RQanSSDx@Zf~(hu_1LpP3<_xQL>DBFR7Hfz$^N1S$Vx zH-j;9FZRTYRq1xry+dMT1`h8{|KcFx*0n zxS)o%aJ$i4UbW6dgFA*^WWvMPb?aJ)7ABnUjJ;SKBxS(Tqi*lvrw(sCp=sRsNj++W zW5=O~+IzpLy>0UR{sK%Vf0mq69_tJu^2G9L%n?y?F0fj3;;;3zy_VD-OZ&tMMZ4Jp z69*|FjNw~<%Nq%g8qZ{-*SAEMNtRNyE|g}jQ0f53z7QLaXV{HiYd0k*j>tAdG+G)j zEA_O!Y1J!~3#b0#8#056aTeHZa7`eoS&|s=@)v-bqWX}MrC7~7CEcR^kfP!n8SPOe=A>PeBYBgi? zLDdu~^raa3Nd*O-Bf|ySdZE`#q|TNAUrcS=*$PsRDK=x(@QNG)Q!KqlDTL-~)4I!3 z-}4u1I?b{Lf~_#&f7>ls66(s(oC;*->dxpHks@W~qm;?Ot$`ap@KOSVPWf9y&xIJtjd?d z2(xtBeGjV0eFtHe`rR_%1W-xaj|I|P{wY28+lY+NvMQhC#k-p-vSQusl;W*|#vDj~ z8<460A(C9D0`}lOx}x49^U;i7N?Jmy;F90mkwS)!!_Gmkv{5Ig!fqObbBz^7@8%;6 zST4l-CwA&&f8P&^vEpn9!|%`lH8u)X8)Ja%OLRHNd9Q{}y!`gw3=4Vbo|m$gsWkyk zR{Bz4d3+G24S>1qFNMzq*AQPSn z^pwyx)6nv4YGAoL_}qR~@+9V-q|J=65*rg-pF|#KfASr>JiQ2$jVK7UP<)2KSouzx zN2`3TW!~jH_Ig1}@5xKBz$)pz+CnKelFaNbc7T^*Q7*P;Gwtf|!g8}I4TxF&!tq0# zCs$SNEuJ%SxmlLmtYd>D8Z-E!F^ypb$#fW2FI;uP7AvVA0>o(8fN22e-A7Oz2qP-E zJ{;_Me|C9$o#FO$#nJkXN{}`(E!DXmb(x&`9F;|wT9MT&McGhN3ZO4YDTz5cJBh+2 zR2OvkdIv>AKiQyuHuiU@d(VwQJ0YtmW2dL;=Hic-zg%zn0Jah^oOP>>!VPQr8~AW& z45CAfdAXh07O!AkT7sv=*V*7eijCA-dFvQ=f2#VWj|)wHIuLO7o8&FIrD$KR2Rk`L z(0g<8#(9+tCUjCRD9KD^>N=+qF7HtEzEsZsk+?dcd_QGu3*-uS7YCi>X39>i_K6o7 zf@!##TbGGh7?BTQ@n&RZ5^XmU4o-g=w6VIXbNc_77X1fWw?99LrGG%y{l|-Zg=&Ak zf52}_WgtX>)DF@xguqA`q!8qwjX(&FU@%G^g);>DjB))PY=fc$W<{TZ(hhr&k3z~J ztA!s_k7I(tM`9~WeoFW4twj_A7i;!?Ns1!&2F&X`MWXz)^Id zyJHM(yu-sE!8Z8Q=nfr6-X+_!sowdc z83q*JOnfpyX}N54@Fo1qZN5&{;4T~zU%7o3c2rh0hoDJZeHs1)e0DshKf%Hnf3(yZ zaC~?uSNsg3Oar7e8#Hep^6am;zh9NRfFsD1YVBq_)NU9U%K`b^_|*)*{r4g4$|Roo zh!D9?#QJBLM<0+50}ed*4bDRk;jpi|VSjdsz@J^?pIsvGXV>^=mk50C8vn*{Tob?r z%L4QMK8CXvNe+)&~HdJ z(q=)tNwXm{u&7YwRAKQcxV4%%1j6Orbyr<@NHU&0sioGk@oXS?ciC`+U|E1-%+o0% z_`alW8P=SqZ0YupmEvgbUZ&G<)oxRT<*}elCoI)oXRUl-vQ)#hHuyu~e*))pVBVJ% zF3+l71w-A!OW$S%YH^GJg-F5Ki{RhpwQ2b7eaX1B#NqJNUluaXA6GsDf&`P;>$A3> z-I{|wQt0o;wtrd-IML(s8F^Poy{x6;u`)3!`@5VT!wPO3>jZja;{kB$9S`p2%>{X~ za>a=yf_PY$>M~K@%AH8ue?|Bfr-U|Ds(WdHuV-_=#nk)xrsVsTn1Sc*489bk*Um5e zbu+H|yL%X*l$J@!ugh(Lqjyo>S+rt{`@k4UM-N?`zHi(FQqLeP0PDJ&Li_}AmaNXq zg&_o=peDUUn-?GE(28+{&uEYW_e=5tIOYfS)DSxa* zk?pt5j4RJ8dwH59`snCDNQM)8VN(zaad3sWHaweZ(eX1LMj0SHq8z?aG?Kjy<58R+ zn~GnXIW^1+7SZ{j~RWO@xv-oJUWknoA9N}tf`Rh@pMAp4(k zFz}mt@OOaW2N%-A0y!Z+;h6b?*VT4-hn6+9Q{N3R3-;~7-gWxjQKKShl*RftMx6#B zEJrOk@xisf4$t)3_v;vefq7X9EmXpZ@vYE(ssNhAr=A%ef7kg24lSSX%=ql3312c) z=wG`_8mm+H#BU1mpxUhRl~2J!RuTECVX2$8E(C<7e7)^i4sR#E-8L7>M-GM3RJdg(4xXjA zA6F9*$Oh61f8KQ%>iktKuj29K=lf_r1Au)M_Ep|b(5U^ySemE!zDh(K&Sfdg%lizn zQ%T?^!3GyUKxc=Jp$F6UmE<|xZnzX6dWe@IQ~I7oI!bYBo=>@TM8L{x{Lu&_Y8QA=8_>1k20E2~&E7_A)k+ zNIeUP$k6a4=ICm^-vp0RPzJ77zygEnoYSBoa?DJ$1ri1`np?+|wmz4|XCN;)YDwI4 zUox7p#)emMUu%n=9F~Ol2r%?wk6_cp8ag^zFWMQ+R%BRJV#%@ztgm1uzf^h*xf+8B zQzWUhf4Pqxd|qHssnN9oK$V5X2*vH*Dj^sfSyEB5+ao7QyT)Qrd#W$99t5&TS4h}> z0r$9eTTDpTFfg-KWB|?81*Yzk4u^@$4x9cmFm$Z_@sC35AHzDkNdM>aT+^}a|IyNE zehl?D`0(GZ^%W-mrFDMW@r7bLJS1?GAR!PVe+iPnD2ODWeLIe01iAnDBb=C}NB`4~ z?si}p5eLRYkYkJi0e@gu_K|DF4!jm&Ka$iVvjf0=p(gJ@Z3lxP{8IuRco2^da&Sf* z)Z_G{IGcn&_mz=9DvPAV!A6d$1Hi)B(WDiI2Ol8)h!G*5=~m=N=5~Jq`N5?)dQ@Bp zfAl9RKFTxXXG;VfTkzz7lQD8|1L9~0w10{dk%JOI{)!TiL6dr0tF^g2F2quEmBU?s zgcHkeTD)9WUHFYQzk(>X#+qbhl)#g>z^fO5I}{*~$6}iW`-7#cHL1mLpAiKAX|z)K z#dX4qle?}aIE`uTza5F+7Za0r+>Xn&f1<}-?k31peqc{|a6Neg=#*-#VU_6C6C38>lQE=S9~~( z8`S5!B-8Tkb$uji?E{l6I(}X$n>uPXKv1vexij@JPKN5j+Q?{&oOUkMC!yBcWTvv)l_!*P->3>+>f2>LZ?Y8( zDvTgeo#DW~Qj_I)6AXNxaSHE4cX^=^riP69V(KG^fJlFu61|-vPn#HMf4PQFr@kUo zNtbzR1O5Ytf{|=W73N=8{@io*4K|b%Uu3oMwk@3Ry;p?Xb}c&emD^psMERtt;|Yq+ z6tRCA@ww7hkbZBjo6wC6^NoM$PL}ox%sMAFxdUU{OvyD}IC)~vhD*^;$K)xw>s&NV z0f(VHSIJLj&#bP5U<5|jf8KfNWh}iq-RQ=II-Fr}8`=Sa)v(Ms;ivSPk-_2>tDEwG zm{S$>YRcCXWUfU#J=K5gw`QY9xvt>dYRhrVY^3JAy@^;)EcXpw{7r$*LE7{E`53H` za&letTar!4LE?gO{2^WhzRMr{5ndEFC!>)YH4BsxGz}--1i1EL{kj~{E^-9t6Ge|hC&AolmNL(T|5+odDO?v8Id!dJSNsEk&n zu%Y)%{jh1KawDY^e_5GkNczIvGWeX@6qXRs($vpFH3H<#6walx;p<5Ur$+D%k7?l3 zBk7b|iO%pqkQx(XOO=Lgv`}N;3FVShMvh1-d5=w?G}f30msQhFB;<+NvlA0EYQ~D2 zE${AyZ#TB4J;Xboywtw?rn5(s!)x}Y9dFkDmI78rB${_Ae+4UbM3pMgH6$Wj>tstv zunA1q6?+XQfJ_4A=%5=KU_f?PPP}$a5@*@vsYxas@_yA z!|!6`&l__>f9dOF1_e1;M&LauKJ$pyWB}J&wY#CX$X!Y1p?lrS0xXn!G+~^`(OE|M zHJotQyP{s^k$&eLzj2}#ktp0kCKxin6<63NrB$ZL@l{4nD)F2uWHn^!|}t2mAqIM6-iokAufrX!HSr_y=fa$EjwYwmAqsXr<_9Qr8z9OXTw?`k|;s z$pJF=z4qte;Zayl;6uqdJhGa9N~Ea{B2DohB8?}#g2jD0OCm4sL};bYsq*iLG+$5@ z@NdxKfuewagBA}I1$+ae1Ort6dS-D4i+`F~fBZ904E!6kcw8p%576RoE))3Cb$;df z|A6Kn4uTmzv*rOvrv!&A^X-s9xPy&hneH%{23s5wNvHX$pCQphs<{{KIE0YtL<64D z^0IC3%qhDr2Og+)x(1oy$M(`Db5q~-A=?hu$dwDuZ{1BlUz^1q-P4xY^0}<+D)oM* zfB7@u7eD=lx^Lj9(Ow{x4CX$76TX2ForacHtJ>(&yD{kJa+Ksn-|Eo;S=Hcr zr4__VkQEC={rDE$0aFWJl&|BFTT-&tf7~s7crS{4$^GJ~*OB=QCT+coA?QM0Smb}5 z>iC6IXq9=l8`NL_E8C|VZWi86Sf5K=OJC2_Q3F(UsN5=~G0kwMi|XWsbAE$l_$=eZ|#cu!uxdXPIF{LN!uMh>pK{XCeB zADgNQ4-epM^+R*iZF*B}W7eR@=hXh{nE^jKwZD31fGX5SpTMu_i(g-;e?8oYIU}d} zml|LoN{zCCXVjqxVa*CdRCiY%_$BEz)P3u>^v&b`*l*untY(P ztJ04P%RVobic%k22<#XaB=;-7 zM-mSqk3`?mR|$WHM18+xeb5upqo|C4M>#q~52AFM9a>SlImiR!OkStSCB$CBEuoG9@**wQ zn8B4B8urk-P2=iepy%9ggPFh(_ZV3*unk2-h6LZ{?GfJ-J2c-$;Gh{%p*{K&eQxYRQ4Ob*DdvXOMX8Y@==)lqeWUG1s^w~gX+(H z0ep{jP3vyYkIf4v{pFQ63>swU=?sTx2U=?ik%4x*GS>a-PHhfg5SG~ai|d35Rzg~q zOX2C~(i|rWR6*NQKMDIye|di-fkdprMp-(kC9Lvbb@{b8oenJXO7^hOlUYol)^I&p z?=9$Ql27eqvha5DeY{81j9cy@Wgre+wQR%_A6esO@3Y z5yl?SY_~rj(c&09Y}X;&@}cV-eIn@|7yqa)CH{oO;8Cc-K4T>!|rqEF<`bfAO#xYBdHkBR6?Pl@ljL#0z(Qby1Ou?rQ9{zKFb#f4Op!KWO<7v4p z_3!s!hTo8rb-@1Be}E%4pIrwr3*R&H;Nq@FWO)3JF2Za7{Zg%QR(>`e94p(&MJRyX z@YElMOY82x<uoj=$wEKqcPG{y~xZ{z3*-4Ll(?WCok3^&!P>~$2*8#l)B%~jKq zE*|iOq=r~YH%ac8H5EgV$2;VH2c+5;Mjf6O=#?rH9-q14(u5f#z_E|5l+4mgyqzLd z(;@T(u?un;e^*kuo~CN63E}Ah%SNU#ozD+#6Gj+%gOa@R;oHjZMUWRMlFD*^8n^U@ z+CydMTTSNancdk9M`@`D?L&oQqFyUicktc{-bK;fx8t<~)4B39o@ z?TWkQ=1l;zb>WkN@NNrJexTLBR1D$H1#->se<&2>y~#OYwNXYg>-Rc^2`niR=Nz2J zbQKeO0z9YPp7-GzJPaFh*BsHP*CCb=d!FRNr#FWr(bvgS-xE9l{`%lT(;2cstef<; zR`>W?TnX&jCxE1_j{7}bsn3{mo>t{HVeG5q2w>b2kM>g#`EPvL$DGDqr0@-b}7zvKMFfBW#=UYPw;RS-A#B0lT|l*TK`e;_9s*^T149hjJ7XWYknv|M^14-EM=AtyU# zxk@&7Oy%bTHfQuZhg_$Ao0CnG3VWw>a$7uc>q?Dkt{J6Is+`Y$0i5qNHB?s`eBoOE z=DJCeNp{?Ef!ETf8>Uj*oxk{xAPbo`kNTqASkVqJ+e}}n25woLdyL0h$zBd8LZOhWL?T$cGi^?uhluGi2 z%InZ#3wOF3(Po&+^yCS`yb2}4SDHUoNrf;ssA0e}UALk9U>D)V;gzIcEqREZ3j(zFcj(BhXd*5l7u}cO+f3{E`;!XTvyBtl=$#GiPpB6EM_=CF2U!$&j z^?lUk|4Y}A)asXwvsx9QDtxPM zjH$ma9dL~MIr7&71K%8ZQEa;VI;T<+{sYf`htBq()h!td_$qyT1n$!Bbku$pf4Im$ z0vGH@;9_?kD4CqftgfwXuz)>ShOU=xMCi6gq02+IChSG$6e?fvLh>#}Xe-!QzZ~3_ zWrm>Kd$4%cCis_}pQw%noYF^2#lGtx+s-3+-h$E|A;Y=LfeX3Zsd&P*k5F-O4t1sNaxclr2hcU`3oQcPjFmsp~q|vkGn^Y?NvTiGl}+9mgpRA2X!ls|e|qxJf-?od z*}}APe0r8%1XP&x8pTod&O-IHGpt42-e&VwP6n4O>jG^WCsYDY-1a~`V1puyIxg@@r(;Fq z`35~8&h^_nc&S)}+1=141ga2dw3Tr!L{eberky%qLdv>}bQ1my#kilI^z%~qPxf6) zA^^Q5H1BR<0lk}>rl~?IF zeu|O_@>7Z&5DKM^hOYf5MtwTTevs$NKKh91LDWD$A}i>psEA=dk?7I6kAG%=9g@fC zXY@mS6he{kCm8!tLt1iFA@_gdQqeK4EBP=)$moDrN0Ai#r2NyP_&|KdhhgCHjYP)* zh)+#nKiIzG4!!o1I2zc%BYBr%2L&cf|L!~qgUtmtr}r<%saD>Cjz8(|39@pG@;w~^ zYmaolHe1Qo4pE}UToX?NRcm+UUsL1@CLbsa_%d?a$PIW8VD9ef!_9xM1WP{CMt^2` z7zd#PR_z^JRnqo_CzikQxKd$QbO$F(3cpBI{i#H)!b`HGb&P>jzg|Joj`bd)O0$% zZXgE%k^A7!F$%7w9Ve_BdG`LkGzd>y9;|90>jmc=a#Cv2$LN0%O|q4g|ChP}E~cN#Qc-EE#; z50^{cXB4+z+y#G_{S2?xq2fv%xq|VA#Wh1A9eyV+x%GOV>a7)6FcD&zJhAYr8N$t! zv~AT>=X^IR6>x@{J}s1=`2)F_H_r0Gv$bF-VV(-UePw=0UUVZc)BC2JtqMBTQ&&1` z3{9GT^#c`1OmmY+Sb(Ra%T)ti6LmV9rKQ871_jsVnL%|i8qLDxaXULglm7p zb)b}-S89J10fC>uBXw@BDw`C&3_7&0mm5 zJyNFZ2fm4Qss^Xdm1^dzrqs9k0TX!7T_u|ltNBvmCmU9^u~}q*=u4vYN2AeGF4yUT zGdSyI>|cq2WT`5((+it*munf5<&6zAZ1bVhaH)UDMLWHzX&HfwIcuc)35t8#`*d#n{#C7CqrKP z@d7bg0aZ`oc~|fTdEW%Aw7o2yP6a%8ifEcO^soSCnFlZKH`2Y(W*pBh{q}o>*}><_ z0}IW5O#2^>@Zb{N;uE;pHlLQ}#>PnS)z^R4q)U@!UZI^w<3+RtF_AwV59sPeq_~SGmC&!HJPik8G+mBijd_b8UtI^a)&kp-^ z60<`H>X6>X4*-OGOz014RdSd)WIuE4+5yo4qdslKLvZ^uMS&2`}79@3yWgvg4?kWby`~*b&5Mh69P(b|~ zgr)yOgw-$VmnGIJ{vKi3vQtJ<_<*3Ag}!ic0rD(AW*)9p7M$(M^TNp zDki==-E|3nzPcRJsJ!2<`~J*5;)#NFbh1qm0DbGCm)xEiB4LEU%3XhwRZFKWD5USR zaL=AA{mRkHocMgmRyzWVtI($ceGA{M7NaJBR)j3@Q89%kK_aX%472)ZqFg6VFP+u! zbDHD9bobL|e{aw4An5(mE0dOezm|A(UI4)!&|Wadl$!cVmLWKDO?}uFG4@|*BX~oQ zXf}_$8>gXI4;q!kX6AoI?D_^LAI-J`^m=*M3}PX~L$KXQ%RHYakY}$}dC;J~9%7H; z6m1CEMRd%~iE3>aSKyIRtQV)G9YA`o#pUJ6;uK-eYQ67~5Mg2oE*{94Uk0oZt)3Xy z^mcbCdyPgo9PsDhFqU|K4KFJIkgW3JafoLLp#uk;OWuA4B{+Z4FTJ7otDc<;Hnjbl z@qRx}j|qk(@wvs13u3Q^xnBuzLs53Pddk-#lXsB(L=}%=!mF9C7p&6gjP3(-$FuQp z%akEnozY4>+*wH%&S)s-0T)C?^~odgdKCnAVDW#5w1A%t;9#hncVpQZV;9AN_-f9# z*FxM(QPqBjw19tqN#O3gk&qFn@mz#Jz+N_-&?o!az($bQrR*r{GdOp?I}-{MJN_eR z-wJG0z=-sTB4!Qao>`IB&IsyVqULTS85VY!pe`fo(MxBzsN&!(b`C3OqgE-z3+ME5 zWC!3)e$4C(Q=Ler%`3-9f|xJGN7S}c z(h9227IOATLG(KG*Xwy=-)}LFQq808=v5qB0_=!04X48TGOH=vUX&<_ur6AQ3$#UJ zu;=I6wse0}!sqNJ=7P$3OwbDNZ2uA`Q5`-N*^P^IdmGwYH$^N}FF9dxT88l%;OZ1L zm8pyM3>2kTA3}`oB@`!BPU3gz6z8lIdC4Q*yfQz6T*PnrC3ySpyH_!-=y2c^H8{$G zIEd)nG~4$i^2gI9lf+^9{U;iM9KCZ56485sA3a^iU< ztSUZwkcIw^o~(P;-1k`~!xS3e!hJ*Cmc7qCXNhl0LNTk(NVxZ=w^J~H6dK6`Y%a!@ z#i97PZKs(FWGfw6FQ7%!mP#sy@#O8Cxhrz#5_=uNCkB>8#Zfk&%>ZSmaON!odwus^ zWS)ObmWSech=XfJ;q7FgZbOF|#5hkEeO|30Qt?`itWp?H~o`@w&A=?FGy9yb3qrmuDY|Bv|p`~`s^`j_9I`Cq?e zJFW`9U4BcGU#21brSF>c4@mC+Z)^KPihqB5UBBmYVLKwEQ5^XZD#W6rO&HT3hcDuA zPl4hCKtbsTk)g-5*fD1x9__{m`5`K#K4&20$0FckZi0pfVk3wT-z)jFP}75AwWG8s zIn2x zfVeLROAqk5!@wP^!k^i;eND&k?IDutUP2DgBN zyChbO{pH!p+s>4HgH(eeG?Tw#@BL!!mw2!Y>rHU~RRq(;A>bSR2%iGam?O#AxA|pE zj`pah9fPvy*NGZeRO+2sHJ-s0;a`6@0e-#9G2PWhsFLsLE)+`i8hVc=;8-|D>^ws7 zAw5QN`ESUOd20`Izx#3Xqu2U{^qROc_wdqGzGprn1j~)@7c+5%gZ^b%#@CC!G3X9O zS3tLH=vx_(IaHR9gYf5A_2&onqvr+ulLz*r=LP(e2lk`q1^kl-_M_(o{JVb#cDSYe zm023_%`J^1ic7E}IHrXsH6Sd8eW1}(dzFr1zRpN1US0We1Lu%SBYN`A;ikt#5&vueJ7KNj|9Y z13z<1O9Luth7d_Ds;vCXDi%%frN^r+@u2iH^CjF&+Pr~4W!10crqUM5Y0o?O6e;84 zoJm{4Ltoq0{^hDABZq%4*KH=YfKTsBBUC{-3!_;eOCJDcooxh|REy1shU(o%@D8_C z2tNG+DH+pYxhXDCD%7|4=@Qx@qTkQn@T6ZnJRlM>18}Azdul|Md|r0$YPEww&zKSg z)~V%TJ_7jYYlA(R{!(Csu! z*Ki#?PS!fP$|zE3as_|+G%5FkHBWpqVA@S;|x}8FA({EZ*l(+iR=seEfm3F9Q*KlD40ee z0;6FVgJA+jkD`Co54(cI$AcmHP`#(Wq;{& z%AF3XV*g#HQfJiglHTi2smj(l^JM**NIq}hf-dmyqVC@by1>7Sy8k}t3hNPc{}|f; z4ocbflfQ!Q6Zm&g_oqSE*4|$%BtWy2_mvl5t+F@0>Gy*g`gLqaDaWxTkEkDbLimfw z9E_U}%LsoKqwZT7?efhNV$$yUa?ZbW&1oxe?L66W%BB7OaHpu^ZLVvgH}2wWrI-_$4)Jw-{^Kzb&E6+=51J*w zAPU1OhP5Uf5!oV%wVOe}P8Q@!c)poY={7P(R$P|JD>JxRe+wemA0){SZuXlU0d_UI zKIAdjjsxF*)9XX)h|bVRGB`~VapdZ7fJsyF ztGNau8O*Yb7V}%OA>*nf>0K|wyP7~z8oBb!%pN%=pa#|?2tK>^u_%j+cOFn!u{3&v z0;WS(LQngY%ESZ1TJBmzrBOQH<=+{w@@WX~W0t)i+x+ad862>3B59)uz zPRfqAQRvUcLgJ5H+{Y^d`^2ZiYYsn5^Y-OI*spd!hXK&X2=7R#KVH{+N(#px?UVG- zMTR~ctbI+#EH3^@pAUZ2Up6hOBLJY^)kFkIcxgZM<>guT58VJBuqt8EIP7Z>w=Pc& z$p@?Y4QSQA7k?eB{=CG$S|RXPOZ=-90>={nzA7;9dG4$WJe9Fd=dd<}0)s&gEjL|7 z6D4YB@bXf8?^}syyXGPeXD76gtLP%xye!c&aaBP3+DoI#*ONva?r{Mu-HRtn zG96H%S<)uCrF*JJ+)%aJ&dM8pKHvK<4$2#;?%S0{IUB0XvU~N2bB6<9aIGDM)$Gx{ zKUe&W;=DeIr_+rlinWGvnDhFAYpju!6d42wJ7f)l13FN1%8w(h0r$I}q3?#=A?T zl=oyD#rjnVqb7u_3i8LLDbW%?u~d!$Z_jxXT1}zDRsd>3Tgv>$^{D{ZzZ#vmb#_rPSQDiCB}Omkp1O);}-y zBueC!!8=yu-7(cO7QB*Wj5Fp^no3jCz1rT-dD!YXV0FIK3Iv@KP~s|mQzRETFtM>3 zqHG+ZBExz?G3`fkV@`kFnM-(%e3um-K6jiT519kp)Z5rlTB_fA>}2FujA9cNyO~b= zI*-r7w%0xJZ(};|Xb8H^#h5$!+JLCtAiweBrrg$FVT@p4PM`*@p57M$gB z-SBjg@NI+9dZO(Tf#$(0uaO0$6*$`On}L<|GmQsES*upAb~xm>!qNpdoe#%=x?K$; zRNh%OA?y=_^AUfvZzt=ye`G*)-A23R)&~HBaoRXKmt_i%qtq8{;=HVH|sr zee^U30NzD2#9hfN(clAZb83v7d)&X>E3dQa3zNi{riUDmi3+5$ec@QR*WF z{7HXg_q?3=2<<|Lso@WS7yZFAQFOR%h4`Vi5kg0^V8NgZkWp7rC| zk-P8k5&5v)sgEwlL5=?#zFtRP0DXP|FP4A#dz^F0t^^CvSmA31L;Y1%Y>E*05pRO0 zvG$kV#r4AoFBwSNH2iAi_zsocvc*KecO$`Hp-#|*T(jc$ zRs5v58}NsNf8v~*jq)4Swcg_D-`(g9h#TX4<@Nl>JW#A=AKU*X>~>&3z=9IN+#7I=xBfbj_erp zsX_GHytv~c*IRkzKr+1M;^iI#T*Rmt!tG$OXiE)_C@&VVi?c<8NSk}CxUXruS+)wM zj-G}6vtK*eZF7Ox!COt3C9n)$OADZM3aGI1&u7VhsjjUN1Ou&0W@^Hs&(YHdYwvbh zJAD>P?m`Y6m+Je@JDktJ@B$KPj>%9QMb~J-=2d#VCUWCqf-WV z%YWZ^jg8De-J<-NV|NK?!6t_adaR9`<*Si%3tmZrGqfJwGae>kyEY$F%n_(Y(0U}Z^Sfe{Whs?J@E5U!w>aGwp>Sd;jfzu z)?C}$zDZ~c!BGk^>Tl(FzlU-G0mz?W-A~_){9va7z6k1B1=~n@-Z!NDbcKy>dcCyu zs)gaypHAlGq+Xq zE#jR`hUXKjoL7XtyNkXS4d-zBT?Y!xcVyhI5!IaAfvCG+9HG}4Vf#pO@=7F@F4PAl zav|yD-(OXH4Y7a6Tq5pprK!e6NRXYj^`YE8&(g6E z$a;l|xo9H{8t`Qnn+8Dj3mMff`8|b94`QTQ8+omWvS(qs#N zzr}M^?v{V>i>usIHC=yi9?gD3QeQvYVbr%bi~ZCk-)dPxm-MgUPhMaD%P#r_)BfUu zze8*|NfH#k17euKDGGxz3_)O=Mo5Y#2oi@#oWzMAP63A>Yt|id9pH^RaM+HZ4rVy@ z8MMF;P((uq%EI9tQ~eOvLD^Bx!k~{&Ds`~54oQE;@FT2C9UYDxFz#2P(@)_mIjVEv zr|OmdYzmn8Nb>IBEv1e&$T6Wz9$l39qsT_!$5isMLgIfA_-Fy8pGFWC9`DIMB|SX- z*uBD^&J6q+{v|&uMEgPFuW%hd9&qG=e4heNUP5kn)>8P1G=O;}%@Mc!aQ=fG|2PHA z-}!%knO*HzPj;Zj3hc2-Euqvn<_qTq)_&X(>>My#8jf1?OI=pnU(bi0ZNLk?#`#~3 zkL>G&?-#s(^SuUsYkX~#|DwU`9~!*y)(;up?flLA+WI;s?8n4Vlb|>7dm6m1Xy&gK z^-rH8@$Qb^+z|)Y?#iMtU;T~dwja06J1c(y5$a5V^wmi?UejxgIQ4HDBKtk*uM@ss z@XH4q_!o;S;eMsavp=QC8y|{1`=QA1!4zRr6p)3!R(F&-#II7GNBVj_`E;buYn;yrjun?ydvp-}F#&qGA!&e9ujCliOO9V47XYdbfhCy%#Rw1NfHU+#Z+ z5fwyaB3x!sGj7(Dwru&UreKE7O zONiL1vEX1<%0;iz>zqsWW13d_1!#!r*982SF)AXlv-19$fQ5y{+L+6)6R_W=U;RJx zjDR0azv>34=&hb&&)aaa##W4R)1IzoTS15N-dSCImSrSPf7>kZZLXI2NwI%uzp=n- zCoElCUox@>Dh?N>-TZ=7H&u^bc>%;u>182?iYj%&!8F7=6p4c}VATho$Yq5=O>yh4 zniW|2$&-b#@UJ$SXYf;%FN=Z$`MsuIZ`W5W{-mB6rqbnN1s~~pLoq?{$-XPN+DstF zc%`QN8$O-jiPlF$Sr=!m3}wUz9Bh_o%fsWxSPieWfKq7*@5C`ytzP9Zdb&_5iA zgy9bh20l0`hrQ6pCFn4%gbxXSJ~I6fXVQ<3Ub=_LpLLuLE6ebpq@dZavM$I+e?Cf% z0Jlfp3_U{L9u)T&w+F9-|D63#@-xSyLr4@o2s`LUJs%Da#Xp=l0wGR*A~1Sr*2D2p zLD_>d`YF)t>!-2fmiR|_^bpZc4}vm;9aiQ^dc^JcnC$$^02v>JkLG)S;lsZ5kAywF z9jLlEdKUhcF!t$H(f?kuMarNEDoFGDe_a3Ex)HKk? z5V|@61TOxF(4cf>fWUI2YFHf>`+ z0r2bK*D*~L{?O=Wwcmt)EtO~K3lO*B^Roh>A^cW2qAhVyW75`{_Lzt6%e5}GFdcYW z%)h!$wB^>Kba#{-uxt9}dI$&J9tDmOs`nnfLzLdl538$#f zB-nDMj1y!o zImdMigWKeEgRHH8j64twp>mI?8;DTGlL!acJ)>zLcDY@iL*hK+J!?&v{B^(MV|#~u zSw!5iLso^+m$FRxBGAol=0)7MR&uRn9q^={S@{L4nsWYkns7gpgaiJp31>{=vr(ms zciC>vzVmC92NnrVY|HuszzBQ||Bc=aW9WC_zF~w2wP%WdGyPDbj0T;a?MvR{qtSsx z>$Wj2VG>MPs)9Y3U^#qdSRq|N6NA9G&+sdV)X_Rx%#{bPQS)RM@+F%a(s!z{VhSzz z>IHgDnfjy(yuC_5=hXoTrX@YXRYny#x=QAp6^rHx7L}mz1es`ZY1)+lKmy_X!!NR;O^aI^LY^ccw{bp=YbEx1I*sv5t?vDu#Itd!xO%-mh!d#m z%6kg5?Vbad*?n*uXnU!AE6!jk#pkRX{al{(ZCw6;!SLTv8lT!Pb`s-klFG6_?Y&fk)Qbnd|U#u&q!Vp z9v33XV+?OUllb`mWyH}T*fYcA6M)fA>YHK5FG3(kZW)C~#(2npWJfb&kMjF96X?hu zp}+QwhK|TcevgcXl0?RiARC^lR~=lRUZLuL#Gi_9&^Ir@od0uF+_Rqis{k)KdwB64 zO(IdbBRN$l;q#vHb)oBQM=%7AXn5ZCko7gC_pM?NM|YP0w-a90H;rxJ*W5DtG$dqa zRK#z?X2(34)jCju&}+DUG;P=Y1fSoOZF={+S(9)YLj_KLHYO6c|{^OZKI z-&gu;7X!Ufcnv%g-ILez>l>$4`6ph{^vSC*d~_Lr zm+nbXOl}~>pi=c|Vu*Y0H^u?Boj37+{dxv+JK2{;5vB-vjN}wF2@*`qolXUV8#(|w zm4tQ~PMrDd?#JK-#MH|plOHD{I;W?e%Q>%bp3g2>9&4(=>}gyq`{gc??oO)60@w3w zo;DGzPHcun0?1>Sdv|${?IHgZ_N|}}Pl)Et0D~g)h0B_5Pw^;=KK<%^v=M-RtRAbg z(n^=g09E^aFV|~OrT(!tKJd^M*SGL%LRE%mKkublK|XjFauxL zjG)^TJLeUt2CwApKM`sjukW=k=(iNZSm3vX=$!6GUaO=rMvI^FY`?)R(8DMsT?u9N zAQA*2L`H)*iVE1@5^ zn}fOmojoO~O|XGHxnO0*bDG?p$=z_zAz?@|+2oys>DA%wD-J4G7q|uv87XXNz4i4y zCba53gsD+$b#z!WuXC_e^RXG0Dq7FH?s@U8l8-hNwzHnGDHTWz*+0Od+*AkDLOd?-<@?Ds-HV?^<_?5Oes$~ca-D|uRNl_x zi(}_nVIH??{}q_&O`j!ta<55-uG^(E3V7Dog3TvPgGU(e0JP4A)~?aO*1(;`nw)q>KGlXYoJ&9t zdIA$aHO_rZaq*t6biZ-%iB8!QkEuNnks%Q&I-gL8S{G^2H6tcgu!vRqil$<_K00fS z?G`lPo)yAr9NVb6V8Q&7C93Euz+*1zMK9)io&~Grg@){{Z#51g9Or~{0pkz%;$OCL z|L%F^Ksv2|_;#E8CX!t&=^1zf@GAxih&&;5KNcCUzaGdcF^#z3Y7rM1Ws+get=s#p z<9x^zPj8!-q`i?F;}4G^DgplG;&XYw{cSiYr%jV~W&8^hhe_J*FTyVQ#Y~4Ze8t5t zN;izg?$ESqoXAe|Jbz(`Z&Zu#8Hg-*L#IAjhTSZ+D6h>gqvX$qs=# z{KHRwJ(N+>qm+Y$$7Icph~wla9qs?1hcCikp-+iBwEMy9zXno%LQ;MFanb`;-T?p6 zEdS=A$JRSYl$D@#-gxle1O%&~sh(pB2>{aE#{=K=io zf&3@W1NiL&`A?n)@Y@ISpF9uXw-4mE&*Sex**#?Q+)1rL3G1jEzX+a%82W3EdRPiUlQ(7Nl^i0{{UYfn}6-&7zl0Jc`cs}$L-07KA&?(QP-JlQTD-W61# z^0@#>xA8Q*PCN9GhW88PE)bhd6l^9)6vZgH7XZnT=PVKuq#g< ztouTs)3M22l6D?-b?bGH;a@zEXSuiH3gRVFg~)b<`9nu^55>q}Q8L2uj5pWCV`VgQ zv)s|{cqD0e5qcZ%tg5tt0DL^Ss1|!I1iX|SjM^Tl@$e{?z|s7qOlS1&`nNzuvIz_* zM>MlL)UHw!_$fDpulxzK?dciXMv66C)h-{k$9eQ$Wj2s7y*YbJuaA(K3Ru3srDja5q~- zsKfUOavbs5RzbMN0K0(CkY2J&9;~Di?)j22A}}RhPS(QETC1H>W*K0At~X2#}BooCNUfOy=`ke&&J3bn%wKOI_TWS5K_^YScM->j_FA7fW8jT}=Y!KmH{%P4~hme;@xyzQcquK;ivHB+VZ?Fl$xgP=g0-kBx zj(uEtsq)3ZtoFvNhTH8~*;5a3xo#O`ZG z`iju+HdY(GKbRM6=6$SeUQ)-N&XQ!M5XEbyt($k_)x1n8e9`KE4wFNmqNG6@oQ^^$ z2$~<8k8QK~;`)c+KTp@;PRc4og83`!-}gnC1m{-Iw@G)N`nw&Ht^ho`+$yn#-0=Rg zkd>6*Rg{FYzv36Y;fsRLV@ZZaNw^8l+#{mLkE)7^I8U074r&abfl!ohf@C>6&plt` zC8Rpj_g8G<&(kn}km5P52!`y!lNn64Z^1HGDIgbV@Ow3!XOaQY)(f)+W2G@&`Snyi z>r*Mc6w0z;8bA6M-vqA<{C#yhzN|qAxQg5w=CBg#Tg_N|P zApa0OpTnM^&`~Mow{;yuge*$U$u!g^cwG@2x@OH!qlgD6Aj2sov6h4qGlpIsZJD@%Ehmiv) zrazgp&JGQK6cRpWwds#tHvREkC6l8nOOwatqxb-xJ4Pm`18+v*fpUqT!CLGa0UG~U zULX3%2cr!S4{enlhr{?$ls)ub;-k@cSRKX(zK!Tl!!tY(Hh~|N)(Ae{eE1y3N748A zU8w&-(Z6IkF9)oxpTC8*zh^Y>5bpT{NXviITlmj^A?<2-G7$-+f@VqWZ9pJEcg53E1=oNVtiF!w^0e)_i*%a{gq{X zM63gU7d~DWQG1Y*oh@+1)kpID?&8~iVF*Y*C0%?wh{(qJZ93?%EIVk?`oAG2e|X7f zH3y8exa2!hz~=ld1g#VZ*!g@vCB~gnUzKx9&hBcv=Bsk&_J(o}#W;dV1nX5~k;XXh zVeEqnj^6Fnoper zerA5~x4aK7MhS438k`y7+Fjcn3T}g<9zPtSGf&2Fr^n$l`RSaceQxRqoyeIE{2JCsnnPbp@ z;ZDG{xK>>f<6__`g-8vhVGx>t=UCgAV@tit?AmiKr<#9XZS`(S-$oq0k2q>Krmrp? z4*}Haqag8pkCk5i^!TIR>OVgFyW;9^&ivh6C5ccJK_e7F&?F6EBmof^K|%iCWlxlmK+3_L(3jI1~jlAmnZhEHA+5H8uZ~D z3w?$vQTQk$z{y9ff;i?X<4*yEPClMK^yk7q8)dX{s>OA4)jf;)cGd&@M{(heA~m5 zHA0=`w{&1(d7o|gEFW9#VT9;@S6Hh}lTioN|nVfCSL@mGX7 z_AqD<6cezgp1F-URpNaj#qTzMIukw5iO0M}i?P0<2QM_1UB_R;oIara6P}EU_GkG9 ziF~%TIQDYZJO&Dqj7OTnYUMrMu7TIf6`I6q3C_+lntjGvs|amNDH871_!2A7H0~iu zWzf{W+f_UPkfl*mUBRf=Wdm7(!YmYRJ+oyWyhHoZ2JL#ws`oMz&_l_8qYc;iHdo2= zj-AlfBW!@dLCeGws}QBC^>on}#T;R(VyIJpn$YA? z?O@#nEK0o!_ITQsxd%xHz0CJDg8S#Y+}{^P5={tm zWPlzO`(&CrL2y|oU)Pt|q~RF`<1swHjeu1xJh+WeOW&=t5GG-N54{-~3X3*!JK)-g zQ&CN6=Bb^KJD8h7C)>*%Zn@s7gqhh$Ii*k^-%(8z=1n3d))3G)U!(VJ?W_){3X0ty z)dGv-TYnkyH0-EBd@CcSkgXcfzVa;lwdJU)hhLfK_AAzEJ10zBnaxrKz;AN97;t#}o zggV6Y^6Bfn)$Eo9>C&C{j}BK;3&@rk*6<;BBSD z=?qGbK`STFgHP?;m+W;05f6OU_n{oj_*#Lg3h3hKBe#WJojX45`D)qcTWK$2!LJ;8 zB3x&2iOXewM&FlAwyKGnD_K!GeXB>A%T)sht|qf7*jc-sPtwr1z8qnXqF>4uC(Cdf zy=#A7tUYahW8H^@HX(RiIo$W9e%E{tuc^lsHLsT7= zd}1d8y=$;e<0h;}iCYYD!bPWmId4u3^lOQ-7}{0V)xg(lc7nM$b>9*k8P0$QQ?@_G zX2))J34w4k7pJA-iW^ox)$18~zMlYQ=FcH4c;A^VnO?}si`Gk8>PbR*8nVzfIFc(Q zW+1(PmXIW1SP)__5xMAe0>jpg0a{aM!5_BRNLE=B0D@u|7f#_o@l^39BdWn)Au3ZV+878CzA)U zW=De2=OTw5{U^t#Kk}#9Uz;uF2XsQFFX(jhf~&4cF|slTCnd29sg{3afu`}pANd@I zaFy^a5jo~rnL@H^*uFSt-m-*1V}AvIF3VyVwwBwqcm~{({mq*`)3nR=NHnW@PrmHW zbk8wNtMSbHlYkza<%9UV-~A5>=s&;vadY5bZ~7Jq9=#WTRfb!g z?SQDa+*gwcGV9CQWNuX4~;FJ6f@W&>PVjK`bvibjLAFS(Vq zZ?%UyQ(?Pl)|iJRxg9!_Gip2yC5^)XKOdd#%-T5WR=h=EWO*+X_M}nZ2^@{Rbn-71 z;zT#S4efD)=KzzXrJwM}YIRyYpVwG;&DbsAHF)X9@?uFj0 zmCM$_IM+`Q<}xe|3UOn8RrN z^fYp7wm40obep{#S8K+9Z+!y65z8J~@__)seH|Q(rfDX%VNBqf2B}!6a}F`>lR0<$ zwhupFEN%>A9~;%fzd(2xlhBLOT|-Mpz21uf;k?Vi=ZC1b-o* z+}D=e|8vOz_}evuTSC7xR3OfMlpyzxHj#Y0oMga1KSquJhOHET#y~aRUbMv*_7n3R zOntoLIc|^`!xq_n!x0O(Ph@ksmehRc*8!LI7`8K}pvA|8!<%@e>sZpa%fGR`W^qfWr$O*PvVedkxKckbDuZz|$G0HPHL(M!CEz7@Sd{Q3j3(`9?5YkBRe zv+q3-&WtpY=p=oAbIdu%9OEGfRgKSivjNL2Ij<*gJRedi?~J8j0*dzuFRFzD&6pR0 zRN9=l1>jh#R#3hikYZuLye`%8lE2OrI2dkK)dpC_FY~kUEy|^Zo4sr zl${Khy57lFCrX_%6M!V;waWP0NL3rED6)pILoh3Fh@9cBP!?UsF({RFVO8f(0iWkq5}PYO7bJM-fFlMqx0?29PAE?w#5dF zpGG5$Gz-vWzFkdtajx~ipPmlMoNK)9=BW@Zqhz~h(c9r9bZ6M3dKPg|0p7wdlc2Z49Dngy&o)N-(b*s?$xr zJ%MR|qUH!R9jwp!+Rd3R(^bcAFV^L*j{V;lf@13X+B|-+_xZBvr#jWYdfqo&_0w~H zs7hfdvKOQ%8YT!Fr*MKIseQ-^Mo^eUPzb^?9HmfVTcWT}HQv!Tu_gJ(J>F|UNxai# zkmOC2c}t)W)K0NZ!hI?zCO+4AkKXF(^j_G1-@#V=F8;rDPN8Hk{uA-8pPIbAq{DEp zTRo zUAiyXi&SB-cR99e*)H%4sfYOMk)|&aB=rZtvf28TtayDWm#wFZ3uLmejXY~q=(e~Mgv9zRdlJ`7<46*P^6^eLLvm@At zQ8#oD)l%g#hgE<^h45NG4n*s4uQfmQ6@vxzlT^nSWE6VYSU376X=dk_zESvV8)I*C`h50?0G zlmQ37XdG7*HFv$pgpH%QWGAwt^bT>4?4IM0PKhO-HY3X*O{iDldGabHxSc46hMrHL zIZTP6xTEIUlrdf;Goy+=DleAA-I1${g^} zBxsCB;}0U%;hufj@?Oh$K1KY$8&Htn3@FHN1Qg_xfI=Y@h0_Fz<1htND7J+ch`=ct z!69f1H{0JRf_|E@?_mPpyUk&|C)Qg^y=BxZcO#I!TAm0yB!7lW=cQEi>yDLogA^;X_Vc{161rFZscF4PF9qxe&gWmlM zWZ%n{z;E#`d3V3J0Ja4V0@Yx6pSzaC(nB^jn*3OXly`&eRP4dJ^az zP+mU<6sWzySxcRNj-V&Tmu&l{Pp9*rF!TJM4=Ar+2b8^S{KK~YbU-QoPR|1I9xo)c z%H;&4*UGHp*Xf0fsblJt?Lp!}W#l4)d|vD&C7oeJW1q6TrK74CWX9#_(c_8G3apd@ zAMl_Ug6l=M+y`f@b3JewQNkcnqEk?Y+C#TZn7d)$4^c?6w-BPe?o47$3e z034laYrD`h_&6mU9##%4*9Ev;UpwZ?)jzA5C6>A|sPw=FH4>{y2k8cJVHNxKq)!0# zn835)wR~Y06kNyYQ!IMbYqY~Yp>6hS^Jar*Y1c&)_4abIiF-nRI9%7T!wuoqI`D(zzgokdKggK=r(BG}_aCp0TSY9nOeS3D3a z>pX;Qa9CUho)ZuUX%l=tEGKq3h*0FTQm~7gNzd(L(zLIjVf_Of5&(F0UJZmNqz*N= zu{wu;2USbWC?!L*N6*t^%jZF+M_(?JIfuX)IcvVUe0PIfJ9E5H2A~O^lA1a|Il_8Y zRljfsuS`CUxCBJw=`Ux8fzO7AnN<8~cG#Ma7gp0QhTt)Ze6TN-)6r_CpKHMR6Y8A5 zCDvV+GaGEd8j#Cj4XtTEBXqD~7?QglTb=TMx&i@Id3j|-y&NQZJ$UCOK6#QCQZr^i z#*m%w!A*tl)17$`jKCp9X(CVQK7z>M8ot8GxdCAMfEq;`uF*-0ZZ6{c+ohs4s#)iv zzvf5o<~NzvAHa~R>sHwk6Ifm1C~KEQrHIl3O8nfnVEWv^8h;b=d1Vw+6egkY6#qtl z-pBDw+`(6XGF-x3T?dVnhvG!#t-n%xS`%cm-zTidBT+t=u7= zXQTx^FdaDYMf0eN8xJo?o{D-~AEXL@n0k{ER91fld=d#1Mpsf-ADW@bB&V~Whgf<` zPbzw7pp3@{-rWdPhuYn~M|O1t5J;T)l1K_3SC8|xZ1i54+FCl}iE2ZuT4U_|dTrnY zTM$rgeC|P?di;rm1kE8X^87T$V@JeW8p0d(P3?O8jy&jTzV=0Fl@t~j+ljua!%?JcR$X)&i6iiAWq zj}n;Z#J0RYSn9gKLt+EiWl(N^;{4xEtkK`ZLFjMbAoMdFwEfT!4Uq(a&=|RaA9PEn zx8xe4w!_(Q_{yB+J}la46|X1gxrBjM7`O1_>P12RQuhB*xh#FExY}ECMDWo zP898s1r5LY@NWNbY9A9Ju>GZ9W?YbX-|IfBg6=I5;#XQB@A;Q~_&IrhYhoqv+YIgP zI})Qihzh8k!4bdn{#_dt-lv^+C9vRa+;-ooeK5Wcq-^I8p*znc_yU5^4GsMj4r0eW z{=3r;I0(L4*K>V4=<{?(;yjMh%gZW$CiOA+XO_CZje&Lu1bl~q*1wB^{$!BycQMco zfq*v#TG{PM+7AS^55m@emdZ&CBr_~mUt7v&6N)+4V9JVcAX3$7TXk~e#ZQH$jtTJ! zueYv-k`UXz&3M-9*LiJ2SI?Sl-A1z9bR*gn(r8$d%AbqgABh6^JCYWkM5P`W$LE!8 zF|LV0%#jtDoZr$&&uW$!Et0Ya*v_+md$zmXMd1ZbVg_A? zFc!Jmz#qb-8JuizAu}D8N_nl-^U*JPkB#{X>Mi34W2^zUmnlnUYEB}z(f^L5!%ts$ z>^Bz=>^Bww&!4P`fm7n+cP0{%>)YD+ny1zXE)n-n0Om=L*Y&)-tw|-b=m(2 z_Tm`)&bWx}`~0iLV_PBcXeWeWZ-JwIVSsk(*{;O*Rt7|=y==GVPW1j8d*^{$-W9%w z=8|Bq(Cq{=WS?f+*TuKr(sm)_Tg2h777uD)Jg)hViw7ltk~}}R2Iy{|uVHwxJ$w9l z@mT-EiwE@o-QsaR{sp`BeCqQe+CY$YJ`Cb1hNdQleDy}MIY8%7fXvw0c*I$h@p zNgb={8aH$s)@;|E16j$0s~H4`I5mP;4>4V*ub7!rC|d#=aa0wKo~I_yP8|z_vN+w+ zfZx^_Jjm;RS$a0p_4Mm174T`N>gOue`7$hPTLr_KA&>jreNG{T`J)SZEbwRBos`i; zhtrOoDkmbHWa0?v^sUMd9)ZJPDMS5=`0o5#i_@u^0j>;n>KOU_lNxK^XzaYboE>QO zQh8zY7G`*iT#lW?x02%V_eeI+uNKS0d@?m_oIC)3KE2dCGAewft$mb~&)lX)qebA8 zNAb+xSdG+ac?+`qpy#<4Y`#74i8|VEzvyF~`uqhyIIq$4wqT(Yg5V^I!SCJyy)Rc3 zN)j8!fnf;U{(~SGMdQe)itsypfZt3FXs0>clO6JG;DUzt$$|~$+}~pHc)a_Xk)M09 z!SUOFSeDppEYRB{mU=G_yS68?Q$VoyFfKvtQwPu&!UVk!=6)#5|JjNMdmHa0d+i3H z_hkoq`?q}|jO-O3dhZRu#7<*H-ZneiAKPyT+0SzWIMJIH62F&7;%(-$fjIgNh@!vr zViVqz3dA?C<8Tk6Mxl{^jBTgLUX1st3oZVCVIuj@h0)BP#u#kD`QDdpTWJ%(v!$ ztX<>;caR3<4)SIDTMy{DJ_V=%}AyjpvFc`4<@AH7kpzr9%gQcR=wwrJ=iyxtU;B|H z9qPiniTteXzOh$+cmUV7qy!kbq*rRaI0yT(JcsM?Fkkou4xXnP_R+g)LxBLsdrr?#wr1#^gP zMQ+oUbjwDxj4R^fq2jYM2dyh_iuT35XzS&2cE5#t%YCh=y^sJ59Xv} zezX&$0Iv9WQ11&a&N!#}QPEzeEopYPM=e9+h%IYo$Fa4Br#$K~dZZSAJJ)^gn%Q=3 ztV1mUnUH<6luhsHoZg*Z^l`on-bfb1>l<#-j^P&TCl)x(`-FBgt4F5Wz)jDlyucbE z$C$VHE}2j$X@vTsU;dSShDZeksDi8Y_Vt&(eEos_KfmD6{;U*#5V;Hiom5ay;zU_P za3U2O0Qr#`e$sC}ENK&eJu8{DURnR-d+{~BoI|E2s`lxU_GLa+YVUQFRG-M=n)(Qo6)u}<_65J&-qYc#f1jg)n~#KyN`A2!|AcQbH_-1$Y%*@ zOU>f=#HnkqNP07@1v;{&?Nch@?damn+H`@f1BEcbyt`iV6g$Iz-GZhG_Ihwu91gfc z(d@IS0*}-*R2ALZvkDpUDZ}72lA4QdCnwWD)rfM{JXp_N2>e0MXFWb*y_8`=b|Y!a z#YHZpl>0So);?q8$-jZ+NGk`QMr8=cL!j&Gvf&(uZJ&dUVk3uAQIzm2qNDmGx#Ojp z@S25|qZ{0enVQRgK<4i>>^)nLalIG>5DhsZW-+NLD60M`4%y3qR+3_%Dc3rv47vxt zbTd(SMEB^_GEXK>wC%m87x{|Dmjj^iOcd9>X)o!iYnh0Em>4Da*i>YrexA-)B&cRf zHl}mB5~b%;;I?uaDnWJrNjdc~u=bA=XoGfesEcXps!LmckB5XN>%^_dC+nZYT657*k?Q3*uDozNTDoqZv6(qH|X+lK)WnBgSM}Jy*+1 zXVSUve;e1?4lCQt>5tRBp8l}3KP*fA-!(4{Uy_X_S%ml=+6K9TcHf zxn3^{?=>z0+u6BsxL41%v^?JR>i2>e`mXP7s1b^G3744KcNRtaL{#{zUL^K*tPIh; z#P-F1VKRD8#$sxFj+W6hC+`%xhm+IpCj#xK5yB%hi947XWux&qk zIdBKFe+5hV+YU>i=`W0mI2QT|eY%3Y0RNQN4ecWoRkuf5?e0AmLKipB9qzWUXMZ1Q zHSS98>yA{oZ?W9nTUsEvo~sRlBHISX_r@uI*nr@@u6mglUbpK$JgSU0i&dkm0tZ)T zH!yNsM^Ri}P&Eshw?Oz+WBz5THxGvQ@vg6CkNvg-d{5SGZ$GL_+}~!kW471xXU_;N2Q}8#9{UYGcF51OJ+&r$|*Q*A|IrF!hr8)9! zFkhwi*UH)MNq@gq6(I9U8;I2yBJLndekBWLbw}R%kKNrHQsb&*`*d90HyprzyesGJ$F{lsa)uvwjFjmX1X%n19`6LFzai+~qg%Q{bR=-6bzfy= zG~4y#@tA=S@^QdNqp}I3a(xb7DoSarbNOso$!;!KZD1qzq6oRb^Ow~FYIlKu&!EW^ zSz5)nGc2voLvSjDr3$c7M^5HR?*o3Nr05uuNKUVy)vZs~r3o2=<#P|5(K(!-1k8ZT zb?sl!7+yz)q3!dlJ<~j;rH4sesV7+Q1f3n~NB$D752;TWBvw=fxdOL)XiUNu5@&2w z)(k>7;Ea@*g+Y)jr>czUN9ss_ASalr97mhUBh`4RY#WXn9E-|70J$ZvDtH&T9;rHZ zK+y3Lsv<-#i%xr%HsF(2(sZhlac3C3wZWUoh9izStG*aBSOPH0S;S(p1>@x+{3x38 z1J3j9gOoRccsWCqE6gx>>_;bEB*3N8zvZv|3sAUWTdp}^3I8fOGOLAuMZFGmFV&3# z<)@Y(qS!^@)vYZilR6t`YMj@Qx*%3jXCzZ3)I5{4o96c&KYa>x<@Gs8+_Vlm`_ZZr0!l zC69A9DLH%)=1>`$m2@;N*dR7e31!e z99#Os#6LWpMTa?ye;oDg*LS=4V}F)z%J%IKPXDj}N41YX*Q@>`JN!TgpYQB@7(hc1 zP0=)gLnH>l2n2s_9ZjG+M>L{$0DxlqY!Lp|z`)VHJ{`Zk0!e5Wq=1v1-t!Bmn|&h5!3q-2x8ygcFf(D5c`!}ak3Yy55DW<0f*~`1)Td5P2&dY=L zT#J7tLO(#Sd0Umlt6hjq7f!qz6KUq<51AeZr8;p>wa>3?0oaenh8HHfsgQ*#dG16Y zt=?UR*yx8X$Q6eeWG*KNs+X?MIiGa96PIO&{(P%{kI9xR11ATg$C@1aL7EkOny`aC zkOY39u^Sye`o2v@-|mvWy3M(MePpVUUsm;HPP~K)8eafisE>8&@&l<}RSgwSv10Hi zJbYm%U06~i@sm1Ny4ki3h2~zkSKqpUje|#qBM+yo0nL$;%i$@o6BUdP>~0nT>WdnQ zt>sOB2BSx0+HT~=)|o`Wdp6Y0MMjkLZY)=Z^+gx~{7Ezs1e0b_WYk`sRBV}BnkO%+ zZsH<=EXQ%C>X%i`kF$wFxA~%zkM!W>1SXADa{<oq(Dn8ji)y3@iqAC4ViC_H}ElBIN}47P!JTF1O12xwJQ`U z8kL8lBXn}qUe&9Y*qdJiM>C=Y)(K#L{YguBk6hcR9hatRnQkp@IyrYQl@#LUGR173 zWmo;?LSm^(gge+*?0^HDUR#lj!X|y{bvhtp(bvxp6eoPOWzQsSc^4{31}F5-4;6|| z|l-KR1HCA$%8GP*~8s9o^$w4ws>-)(rnps*w=0!k{DP3Zi<`#Eo(J(l{ z(Oob)hdm0E+yF>OTRHrcZ?wsOT{>os%iBcHO=?yqcrU4ix(T51FfjkBJ;=eQCYijp zc7Lr;Vpy=O3qbU!l00Wn13bC3k{=(-wIszy5F$}Z4jm49h>i-kK0!@0Sng$v+k$tn zO{0Q?zB7QUiSg^2BvO~v!)>i)v40-;Opla|>tEGVt$PVXQPVH@e3fs1Oj6&EM_z@V zwq?yr-vKt&f?)}%q5P^Xb*dZF-UXNW+O(!Fo$ULaX%(ldUax1A*EdOcq^^td0eNwy z?4rk8WQqv*N|k+VQHKQ8g67g3PdRFMvxEi^m9^m$O8-Xd@Qs1ErvD-*7WX>^;eWkr zH6IUHuVIYq-74abDE`BL{4e!w81e1le_BSwzm!+|KX#CB#hy|RiB72z+=6x#*v4pO^~#a|YBv>nea-}n*= zbM69Cl2(Rf{7=WjWwHFIQve^H42Jz3PlB06M--+l!Ot|)nE5XnUeb{njhlyOfybu? z^2I>{*exW!wg!WLueJ)u0F_e*t=33%$MD74YR;Da28z^jo-`}m4)>+Db7XM`2p{em z@#kll|L9k-z2FClwU3VHyWv@VMO+B|0>1PXzc@|r9uBJgq2+U%wYO}~1`Z1zd3QXE zasz_eqS@g~Teocm#{%u2EI9b@m>a3aR=Y--Fy3r_gP~u4E|;BW_2VAxnD%{&%8|)G zK(Pq_^Au&_jPG_6!Q0OQOMTHvogCLbd@X>l#i`k;vgR-N1Ak)W9q4pErdHe zmgN|7n@50uIjZc-$93_A4acHb#oTSAlYeL9Tbx7rp;mn8Qa?^a;9{+Dr(lDPIir6m zXlorf)CGpPgL04GVnt&k#N*;jkfx{|{+Je!k!+$Q;Nj$-CMU2+2#ycKL2n9wg%p11 z;I@tdS|Pz%!a02k)yloxMrc(L-AL%o83=!Vp7bxsX?a3xORd~u1+lebJH z!npu{!?INM=tjESAXPyZ{@QtYK>80K0hwEJ^Pr0xddG2Ly)eB=ZK5w?stGd#2QYI(;q0Ge zpY3=_+rB)f__`3?RFJB3ijB@@?$9WZtZgY(e!D}2VTwNp;Zkc9SN=zI{P^UhOdaoO4o>}9fD+3 zs)h*oA`6!}8Nq0L+F5+Q4UdS3ig5r`mu#Og5tlz6r3O9=XHXXp`+?4KCxY3%;0Qi#({AyG~&)rV*)^QF1 zfWc=G4yNTlWO2iNdPaFe1pHaaKrfm6d&l0G{^!pZ1mHa%WyW)r%?ml!mynrMGHZey z*R%q++nx*^u}Tk#a!ZK!1y@F-*DBY(m?bNaGsAYxu|w5amgjY!#pp-$)v+Dux9u|u z6JgD&9jq!Z%zF2B`$RjSP#=F$8&W}#;;q?Bdqo@JB!U}I}T<^sL;9UKvHcUF5Kiqd*j>RN6d zs!E_w86>V^Rc$E7FB)@4^WGVS$>7pkZPsF);etnzP?Q598o0$ci7M} zZmK`%u;!fnR4g>F1;1Gi?CoR#ssa*N{zYE6pijy2O-C|{yK(fP1bmGYVuLU3z_Q7d zq=fu*jv3^?DX7C-tW*0ITQ(NcG1d=BuSkK8y@4+VJ#~q>?irGxTf=;-VsDkelwGIg8W)Qh4G$E*e zJfnbVI=(5E5Qx}IKEli1CP&f6#r)f6(++~dB zOWN6UX~n`15OdGNJ}W8!z=qQ*K**bkpHvpUOP`@6*!z+ltWw=pM;@(X1h=8`8X&R} z#)qSW8+K_&6aGTK<}DXQp!q7!F)a+13)SR_c+7K z+waCt|K-4E@)@NV)jvj8=5Bt{_2du3NI*s^)$>0_LqJp7Fl^}oct*Pjt}H;jQNNB4 z+&T8_;UA;FTp%+_@aK&c(yo(Yx#t!hJ8du#UMFhT=lbsop z%5eQIlDz5jC$meF5rmOx9G2`uwf+#>N`x}3-%uJKkFzRL;z_17J!!Y@t9zS>Ieoj}j zi^P*^SHPBq0#ty2=!kXF# z7jHN1>Z$l4DTNY4)1lcqQYHpWokIvVGYIOS_IHG`2;Lk&xN|mU1`0!~l(eoR``Fb* z;&&7_0``b4fG~}@M|ktu*b_q^f@;`jy_A7R;Mv7@P>L)ruuvsr_-_+!6M4KZUJeHx z?8qtdk|<;cAn_P%*g2x-4Zah$(6-lE`a>kE^c3rr@J33kBsf!O& zq34tQL5h066gIR_5*leBo~iNe(2Do3F`OlUL!M|S9tXGGJ~OBrRj_S*tMd)A3VFl%lc02Kt7wdmw*eL-;q5G} z1;h#DVu}2jmaKIG4eUxHSD#)h9ycx8S0udWDuE048g8eC3Sw@3kZSNLTo7lIa1#*9 z9SQ&iOwX-9qIF-{y9xCxciv_0xf23!$i{pUr;B&jIHZa^Pb4IDrWPGuNh;P4m4Tpd z4f{}CEF>sD0}Lc2)v=#4pz^+}42)4B}%@WPHXlzhMtb*Ipa^~Tq{(TtxXtIp$XM+|ZU)&iy6zaTi%6${n zN5dxP{Ns_Pj;B5$_@k9f5ljb+Tw!);Z<>y{OOibh3s2xedZ$LM@KO*;3GpbENNfQD z&=K=XmhL1X$o|*^@m)Qmu>$eaoJsYGW61!v3k`UIJTHA}#ezd+{BHz1;h#dVg$$$m zK@MI>SDzAOW*XnbC2B65A#(~j7j;6x;bq6e+h^c3A1GP`8HFz%}Z2<<%V_=f6*6KO=lJTbk#x+$x zlegj0U%xjPNCN84ZZq&iAb!W;uY<%dJhsOC+&`4$iHoRWns#gHYcSP;eqx zPGEpXDpf|!;;ZCfMw(tCMs|s02Y$xwVHv?K5t4+q0hv(t0#rvapK~XwqGhm9@9e0D zSFjCqI|433(M{?(GR}I|h+t6`;6ezX>_C$seX=#OX#ul}$}tY7yUe4wNvR6KGh}yR zp7PDTm5D4JLtU_?97%l{ZT)9G^g^+G)>)dqpSfG|T?l%~v*U`2UYqUx=%DvEUiI_# z39m-VtDb=pAlv(6!}A?+!LV7sv%#$eYmM#W?Izdosi&zhmgA#?`-Lw6poA8ViWM~5 zVMqWYg!D-1l}7wXFhziupWT_*%Z>W<`HAUkK^yFKV~Sa{e)P@rN)!Lp3dx-a=^1+a z+>Pob?pUMPr^OMx72*2S)rThh)w;l42vz8oGt)fzA&7&xJtjQpQ=|0b#+DL!&`XcX z7q=$#8iDHf6WFFLnZ)@NfQo6W+|rq#iVoif^08mw??T826Zp~O0L{h8vD@A9@4kY! z0bWH=+g!e;CyRe?vFY_P>Ql^}L_J%B5bX{?=|k5!cU{8xeEvze0m=kxGUN8XA@`Ci zeJaY`Z&z}TL743EHnw%i3I4tF@&Q>07n0A)(#IFX|G~xYY6R$=Jl07=-g+N3_^)2< zlFm4+=bu+nZ=6zc0Oxa>+CDu^8i7Ozey3SQO_0hDvRbHkXFaC-7>Js{p005Yd%?)E zPy0tI@Q#ud6}Qp>DR;rii<7@uR_xu_C!*KlHpjl;?dOzo#5sCro^A6&BRt|%v#(2G z5y}GCc%~jloyghnHe6cw{eNYHC(_zgCapN6-0{;|?>6N3CufjN3&4kwrDNH6601)?$01$nx{Y@KTUtQ2xYy4yCcO%}}Tpb>at@5Z$q(0BDQ;yA+s_7>$zT)WS~`wYrzbzX>AK6cCDDkMz+b z-STmNS6eO4vyrEfX0RP(^|aQ?SSqY*66u(iZZ6-r{eXRO`-*r-8p<>r5EU)*<;SmI zQo`tvnvX;{`(&Vx+Lsmj{FuJUZy)2&u~V&<0dtmB&A#F>rna)MH$eDo6p72I^j|o}T<%y)&qfIR1H!uqt8bmoc7;zc8+OsQuV{ENp9AX*Zav**h8*hw>)Jlus=!O1;FV(D z`X!-ZqS{7jrW9Ipi#_jnSR~AQ>dKHsly(xtU9TlvYdn^O=U1LXjQ(J1SV~q_U8DP1 zZKCmB{!Mto{Gz3A?e^;#Q# z@_RH%o$G_Z08n7XJ)+V`r{2YD0D^+`nt{I%XuM<1zqo7d#e#e7`ue-TntZE?LA?{> zcQ?zNV!bo1MhgovXc2y^R3~A2{)m8E;!v3pnjns-AJ%Y9DyO;)Xw5>9q64w72|hvo>xHYe|YA=ZPqCwhXw0G zfr*Zq&3l4`e`cP0Rtt#;g#=DDr6!LYqI zCY7BOJ+5o~t{A9^l$O*L>*Pu5CAV+njP`;$~dqB{s`1 zZ|p`aS?hDLVdhiNCD{G*Q42@zl8W8Svzr_K8x2~NkMudr?Uz9$@Z!2TqdWEVx!}-X zw{4=`J~7BvsrRMbmiTqb+^+=Qqu4Da5wGvla2ecMPEG6VUVRhebX2wKq1@4q<;)Pmi6U$_e4K>L?l)U|5E?Raha*3egWvL&y!w3bx|I7o zi+&<;ZSl%HCUBLk4tx5hu0~^CZ@IrW-vC0--m)h^KbIaprVoI>PG5bGZvFJ&QGD3M zlq-ErjuXs6N6vn$5i9a@3j`)K_>>)!5}7ZFnt{>QS9ZKAY3f{Yd3QOB1?~@#e2%LJ z^P(BJvSKxm*C3Xxq@;k&?oXIFh}Tu-dwNL!6=07IoeLj~7F!L<8mM5IoLJj}dI3;T z94iTB8*ak?X91q+9N+tOs~!bXqhW4<+{;%)}Gxd-G_^DnqHiq94m@;wkI(>F6MPA_tw z-Vl@|SflgC1XNedq*73aT*n|hW2HH+#-8Q=TmI!)7!90Q#42Oe=RE=Oya`aL)VL)G z)Sgl^F^EHFengm+O>i0xb-vP*+Uk=Em8fE zOA~bmZ$f(q#D!v*6-7H-#0sF=Q_76EicamOlx&e4AJ8hK(f3P8>Lf}*|LK0EUc!6N z7nH>{dhw!znCfzgFknE1fcF*07mKj7u9yB9V=PtrGxwGCS;mJ8>q5X;uh)7&nbs3} zvfY+oDE3`*c3)h*r}bz8AJlw*n&Qb^gsA5N?c5Flzm9-Gzi7OvRuOQo-$p@vVwS)2 zj13oXnd0WkXtE|Oc2+up$|A?!K6-+8s%+|IX2jn%x4&*Oh6{XEQehMRi?sC4zMg(&A4SUi#{5beCWvZ){#QVV4$1_jpcTCujqrpb z8N9O9rqG&12kA+4WIte^>W3j0z8no|`ZOnJQeh!5>1H_MyTi}XXOBN7+7`5X)x)7l z-Odj9^DSICNh?0c?V1VXlLZs`Jrtp?JFyjX>eTj71&1z|Lm-D`yPWA19ekE}Q^VN4 z=sRWFvgi=QfeTij@$ku#E%Ug{#~ZVP{SDnQ0xEMV&e{^wt|b7h+>1a??P>#-64x{Q zvh=}Aw9;F2(5ze+;3D9h7D>Y6A{yR%~hN3a;-QdE7gql`c=rn>ux@%9%1)L#*}sK$f|^|4dF zuHyVr3j)d0Ez$tql=B98K{(F{7MzDp;K@*Vq|m}Yg{HQ3$ePPd4$OaA+w0<}mDnXZ zD&eN^H9z6Zl3gPgO!p?SJ$6vCZMT2*7I~je2=I)ASZ7C23bUvufKKZeB z3XLGGCGK7H0C&0BvHec9&O>@dV>jHTTMQWR^2G1s-Ujs$62n>t))7BnguRzRTg67Z z&TN)GeV4qa?mzLp;Ywx?x_nq`-+>IPK!94sQEm z&uLNNc)1n00uS1!M*rGgIO~{Te@M0PZEAt5zr?jwZsWR7(Kq%vnz8tN<&QtKTYWmy z%0T>Lo?`z_2f6w2$vxP-$d&P3Z>iUYeuX0-72yL8VwHQoxU+i4{`6QnF`OAiL za3%)ZGTq(z%);X5F)NhVMp!NM6)z+@e^L>94TaBHhf}aZ*dGw_q=g14Fh8nR8H{e} znnS$SHp9>)kE8T^(M&Fcb4wxo?rZNPs{mXtq47m)Z~|`yb~T`aD3Uw)Mn^fe0}?J_ zXBGf1?ZfgUu4laXKEH(H&Q1U=u0N$>h&8UK)h6+AQ9JY}4}n1H!hKLTR(>K8`K$N% z3Z$2pS5}{1VrTLc6U$RDD)DXPinWTdGtByLV@JJ9Kk?q??2T=W52*U!?aYT45OqJ9 z0nr28s-Ml;zfKse@QgdZmv|f-21p1=l?n>(c`2$w|GcpG^-yxQ7hmixJ;d z+mXPh{U)0%OIBX(ie3>X)Xp;gWbO_l(q|FsbX(cx3En8dPL`G2}bC` zGuErK>zS?$Y!<>BJPR_tFZce@nf?9UeB0akLr(gpM*elsU z_fsvH-vQR9yQ>26Ahe7I34h6}cDeB?alB=0rfuf5J-f?26l7sPbiI-hSP$Zx!cu|8 z6YW;6qJ|QgIH&z}%Q#f`b_&^xd5}*dsu&}yYYXJb6+f|Oqo3;~r?52lsC#0+SMLy6 zB1QnJ9S_dMP5IJGCw3`tTBu~s#ltG1cafh&hioNBD{{m*8M(b=h&iJ{kd`6z8MWI5KH!*OwGLTECBGRH5Th)=Kp zk769FrMsH3YU4Q^G6F*~{$gZ~B_Uq%H9p6Oil37(Vk0XE&_`gL0cno_dFL14%?I-~ z&gdZ`3Y9Eli~Qx%Pfk?cJ{;iZJR~$YVa>jExyTjzI<7WQgPb^*}JHHugs_4NTO%*82NE`iRb}58Rf1C?e5o6 z4&umB4@H$R=|C00GwDcE_yqdLI!Fq0`PQkFQGR-cj&=7Bz=zm?X^GZ1w&ENFZJ$mL z(c@T-YO^gx3O7RYz!Uu(JKpudz87! z5M^zSo1W@>X!5s{{I@WaPIuQL1Yb>GXM~SOz=Vp=seeQH3c3oi?yVNg)Z8^YEk@2w z`RZ^V%|JCOAV2>C_O?wi5AI$heuKC;$x+F>vHTGq;r7*vifoTvm!F5G>)RQ>BedN< zHWZwfu@bd8AJUJD7Mlp2!QdD^PKJFZCz9n1E*V)(5JK$yn=LBF;o zq7aj=rD0bw1k6p+!(uUvEfqjb3k=G^=lW=2c#t=brgAn2NTLm@d`K4&*+AzQyO2Rg ze8wujm|C4W*H}Vv%;QL5roQ!{^6R^?=ng>mSdxi|%gh3Eot!8lc0af%B{Pk2a*?Kl zL$$ola^5M-+R&M8MYMBkLllA-r12vB^{)SToR7x~UAarF<0^ViD52T$Y7=8rUa%n$ zkaU)Aq0rF)h?G#RO@O7{?FNdD+bB)0G+mKEgV;Da>h!t3yVK5RNfdu0Us>p=2)uOU zggH2|k9o+6NKNBmVoiB)Lr7+S|vzJDt&3p?b*DTAL)_Z?` z83>7K1oRxKdOtYa)SaCD4V-jznQzp|cn6#Nw2SOESl6R@Ch;C%2pg1#BS*p#l)xh~ zh+5&{%5#Alkp~$@#``MvBT&>L81fWQvS3%-psja2nbk@6OooZE;UZ{rjUwTHM%HtA$k(2J;?)UDw%qo|_ax(A>OrO-KF++K%Gs;XFxxq$^#ur2uw&)%e5&eZlRJluN_n;N5$?}wZ>=hmrZ!xf+d&McDlBg z=`HK#y1>~?+(6HzPJ&pjf%#`1Ko;Syj^RToR?I*sg8)5wyfdrhRl@ipGb1U=|5LZXv`66eF^7`Sdfx=#k^AOJLblWs%#0E9pyBLGbQ4& zOv%FYHdK?QZpHPTl!Cf>3xTSTk8~+DZ%J!z#D!igE{-V?uZfoLgz{3LIACZ%KtNDH z#}Rxo(5Ql9<-kBd!k|DvxIjRuvxaDR0GEWim~{rY5I0`%Gh9PV%+d>IsJP-|P-l+3 z!aQ~7NmUGZiJ17}8Qt+ZAB(vK;s9d)kJq76#8AeNf%JFa5A+bN)0GPH6~KnjK+5|8 zl#%5VJ!he^0$O=r-0xz~*0Sw&#nYxjDBktCA7Ii(*T{;Y0(@lqSrUT;cRhsk2!ojAXJ92qiqWTa%pXlBNKc03Rmpo>3qTA}=x;0GC)*9qk@Fvcd#2z_g z!XdGYN?84kHpJT98l5dTy2xy`5*39^5QE9Yrm8jGepzv3>zBINjaqea)1eCRB}=&!e*%3w^gn+defzWJ^&SEr z6zqQ@?lS}h*FRB=3DOM|`Tt6HG$?p^p@Dz~NP&RJQx*6jaZ_=P(GXi+SRuur5&o}6 zxCUvMBN!0S1VSpZI22B*wJ{ociw{4fH`qU2A3~5HkpIL_Daa%6f8vP(q#wvX(MB1v z=)YS)SBHH3uM|-W(hmH89rVHI7ob4^0U=PP5~_dqpJ$2&*;1_!NdWP${j4dZ>3>?e ztRXY8{*|r+J#qs^6uXY|Jk8E532sZLD?5U;lcmY5LXAa4f#KlMtsWU z1%LZ&4gTK^#I-^F{?A=J-B4QpX~`Ubs{gO4!W@*}zY3{KOHeoe)0aBF3?=YSGr}LJ z?eDbg_tRii*u2{C9WJiFFQQbUD=4f~B6~DgfJ}5<1jsKW;k%az2+%|qd3GiS4mHH& z0b}rid<`udTUSlbwT|^3H<94T2+zer2>G!lB|bg4=7d?gH2rAHc&@Y<^5RgDt{_Kc zkxr9ugH?7R+1r*AI}{!FdifuaW3IIXuLe_rbO=kUi#T0~!XA4e%gi>W$e z>fx0daqpKjhk`1_4Z@0CL)FH3c71Jaf{O>x7c5!vCL-(ABD!ME@VOfxtV)}%^XOKw zzG;+b*LaNcU2BsYPRPc}ZN;p9Qwcpjnx|X~LZ=MIizh>+p#*0wMqD|uC;Gke6Ki4eTd6;iDsxvHGyuUy9 z>(kqucRi2o_5G1D%c9JM>5VEHu51X{&FqM;n+T@6P3m3NcBpcC$vk5t zqk-FJSvEMPj;8^R>(>UOp|Y|0{p>bMlyxMGhkhdXmkI=h3An1+GkWgVj0VCJ5~isw zEtzYsMRw;%!5R7T0h!bw1XILd z*>D#rNVKmXHdt7&w}N_we0badhta~>x)es02f|;}5G2WWO{hG7ChvYgXQ2@A4Ivfw zXa>6GdLLN%X;pBeLmu>~M7fE^E)nJgF}P#^+{z39%ZronC3ZXZYtPvr`~}-GO9{lbMN+7exouUz72%OK4f<41 zKcrXp4rEx5BA=Z9RybVr*QQI^RVmZ909gwMdQ@~!+(tTg{81s2GiLV9+F;^ni1Q2 zb+3!7*@c)<9z!Dl@*;-A9o0&%j(EVI(ZnKyli_;!VmPTq8%m|3Xg4oF6V67dAUKhg z#@USTN$f-00j;PQ`@ua&EhSFa2&ivy0l+$aZ#jR3cfB?e-rYc43&)_;U}IqVcsuob zfb=xP*G<@@T9Vc(IJDdpJvyioS}Mok^1n zgE=c3`ChCd*BA`U*+jAbx5!jH9xfqwjk8$Oydp0 zw74w>L&-P*ctjLV-P-*$(n`GYiCY{=y%=?h;FO7#_8T;L>g&n&2MP#ykxus~2s&ho z$>IhjeJwKuAO$bL$rQ;a@hT)KKeY#796;w)ilFJBO+r9naFk z9|Q^GfSo}t32yBM&(~pR)CSSA=J2N65^XSr;Su%##>%PM9)B{h>;=}*Ea9n6Ln5t) zpqpwm^q0f8aS(56)}Es54qNUz>^)svhP@*h$?ODUywVgH^t~LMUKT>RN95D1l-oG# z;UO5e^n7uET0gz-EIe7E^fTTS;5LwA=&MT_ViEciT*D7cXF3V$d(wNhZQ$uctpV-n zGc|4it%b86Z#8!n6*EsAz>{yg$32sw0bfjn^`9&s7QR00oACO$a0ZjzvXF{?cA=G5 z{MuXaU_jXKTs-dbK=^k*BB@DPd=%fK0a%dowMu(+#X-rNzbAuDYHw;wnGkoCApZ_>{2X3Y9JpzmWNvo(#JRyA;WO^bQ) z=h&VI_pO2;;x(seajbl4^c>GN@#wH-PQPlG@~PW!$eQUi@G>)~{ZU;jD6To*sJmAx zA_zx!;4=6x6lR;8qKmLbj#(fn)2gq5GGxo2s??3NZo%IBufXy>PPHmU5q?!e#O<+qZ)dKFvzO)u8=Nw zKTTU9pPJy4_vfVv=o`yr`s{BTxOi{*sJ)ode@?z9>Wg2#1$qo!sMbzVjJvS~L9;wx z8JZt_9mV3-tpDESj_@f3x9Emt=}PMYphGt-<>XFjwcuG^J}{N%N{$$Z3|*rkW5RNd{4kiwsFZ!Sd^LA4-=-#s=z;I#7L%Ajn%C zPZ@A_7%L9l``?A#nEgxy2uA8++V2`m_sa0 zh>Bp;!anParn2ZWw}M;_qzTS-hT>}Tuvd0NTEoWmcqm{ROzPtNrM7brQBt)*2YF51R7`?EycO^<^nTi;F_KN^>;5Fv(vD~lz|;Rl z7+0-tfMb>R@LNfo!MZf)Me>J|b{?0_tG%pc*0|@7%v=$pB{Pq;Tm8~g;#^9?ky36` z#1;tX3T1y(vt*N_A1HX0fnWd6%Fbtbg+3Sr2*?NW|CT!cn}|a@pux8UoJ0A8;98@9 z0{{P~w??rXb4K7mKuoE4S5RaCJ-bYCB*0Utdhsc?C)m#uEoTpLyra`ZE45)2O%-&_ z0i@P}%BGIRo9xSuZJJ1fI{(FTS*nOihP%w3$;s(%Vv^?7o4=GPe-Tp@uot2_3$;sX zNz^b??Q|TEHWOQp3X={4I+pzXteh!)1odG3ZuB^B)<1Jy|PtYw-363qo58}2)_ zS4V`Ye?zkLbjwq33>7-H;UN;Psv*I0jk^rA69g{Vh+ri1g?p~r7L11|w`H*5{V|DH zP)aB*t!im#5BbPeKb$Sy%7hGT5OP3Q#0@tk#}ZZO3?@1E5z^6G_lCM{*D~wiU?LzL z2bua5)%zPNS%^rB&s4+#W4K@KqJ=!0q}^aYw2_bJ=10YoJvsD0nV1@NLuIdWc}Z)+m*P}n6;DnZ+j6sq&q_(`hwMt`ka+Z+%NbBM zz*mo!bn2&mSir;sc#1X|DOX?P+U12xxZ?`#3sGb0jCu7(6L%QIbFe{Ch zdcDlz+q!LJZ|c3p?-J}e8dEAiHY*YqOm3P)(u~YVrmcJ3zPZ6qT3xH~Fm-!@>pOTN z{N(Dxnz+}1eI-_5f0=)SP|%TwE%9QX55#rAwUF-E^5v!gcHQJA23EM^x-4a*+8IS~ zZd^{jwstaP{^07MuGJh5K1U!gBmeQ=`|Kr1V4*!YY}@$j7<7aHPkOzcvf?>QU(U_g ze+zbgF&`+McCZ!1F4Z|RhT5>CcDT8dn)Kmb_qC19-DQ^oO_vq>v5@E22-_W(a1uIK z*rM&s(!M+kIJ3~6bT9tMmF&>9t;rnmD=r&;&HJ;3fu$(5(z7OBr;FuPP+WzhB}$|U z{W{w)yo#>+_ZN_0+Xi!Erc_w-(Q)vC;_$hqUfX6RmQI;p~m6zhv))ckO{7)7v2ah-0_-Regg-MOWPUfdEsk9(Cv&O2Os>!Hx4PY95*KF8C@C>h z2u>DMzoUe@FvnERY*So()ELKD&W0pSI2G^{^UFnuHWE!~#C;i2lg&}c?t1@80m6eW zWk|LGKo8gPS-agB{1~Z?LycW$a)@o1nxQS*0~Niun5;vlj5@XV4g#c%w93rPjQ#Jm zD{WYlQ_h8^EIEeY7e%V*^U>dVMxzn8^~ogF`AJcdcROh7B^f7*Fer`ztIOdH$#T9O z^R80RanVYQ&yZ^c(&OhE_TNgIl)3`GRPm?f0D~fDU}8N`3`jjC=XB$t#x z8m_;ywBK+TY7h;2_u0I`=Muy24e?16N~IW<0ztaIG!OeATjN5tQ8xwfX-Db~##$M= z`}N)zb{@n(jYoE18$`_D*s-vc!ui!VpF>jyoJ=@qV1EDBJIfTH{jtLFU_aVnbJt+j z0-o#0-SGZm-Uudj z{KgFF`>+O)8E~MRe_T@KPU9x0Ro~Dv%CxK}%cvp!l*X}832U^ zz6^M-5NyIr04(%GP86-eKnx z_veM+`aI!l-bqYJjp)axz(Q%ph7_6HN_1+KAhOq48X4UEq?*=f^CsV_K;{S(E7B7A?&jglgFqI+QQlA z;j&rqmQ^z35RU*kM_WIoT66$0P>T9}jooUAqyJ3bHaxAyXin3JDR_+3AUsR@lrmol zx9F9!p7mD@Q6Y-WiIR;D^6Ea#K~faSFQ|^u5+&m5)o-wyf#*lZ=iTNxO+bzmWdcJY z>4Qp%uq?=i)LBljXw&Xk5^TWoQ~`1Gby*xNpNRFY)KWY~R0b7?mHm`oWExZ)-Y8F@ zzp}hq`V}A`sEl;bJDtryg6OZ{_0Li4u~=0rE6&qlycWa(hQw1mHLYa!c82}DOF~Bq+{-1N`s-(n!Tv)(AgTso&i%8-6(L09*Kb&_> zix0W#DD&cDFNaBOl9?n}2bJ?Nu-c!d7lGr6m{2DyoEI%T=}K3KL{t_BZY&b z)W#HT43ENHzV($pD%@1XBjS=?*gydNr(2t3d_ zt&bG42~L>*_dK+CsxCpeKA;)S$9!-hkPtrC({ZxP$FVHE%G}K6S2J zU41$S!6te)CE5TMDvonQM*59CKgCHf7ZNK_>u2_{fYNYj4nPAZL#1r%%O{^uIJ)i7 zgf5vP-DhpRY`S)w_)H7o)MiX7K@1S|^Z*#WrM3P=B7?ZZ`PSg+Db2{y8RTtk?=R}$ zn0Q+o_w83O`rDIbt)9C-7w8#wsj~&qDamBv#fow(0IdfQ$rYKN%o=WB{W(6T`BFL4Bd`r2*0RZj{w?{?fgts6@@W-kMSs#(% zT4~|w^~FuYn7gLJjx7t=BF~460OBSAI&r^W$hGtiG9+>M9922!y+D? z;YOws5M@SuT2Qd~u9dXlA^wh(y#V3rj}6*3*0k{?`1Z&AC8Z)#=We zD~j7AQE_R51V=eOcpYfYIJg%XWKldO4XUpIfeN~c)vez?(_gCWzWt{Atb>U{Yg@n< zrc#+cl|Oj)CR*4Eu5O2oPrnY8caxqd;=^eOYG2naAaQF1r>t6I{(rM`$nU&*PE?## z>eMR~4>*I$UVTg|!W$ITH@B?NqIfis<5aq|0+V|@V#CRRHSszgU(}LW*h8rWNPd;f zH{L(o3UDfvof%zr@XEn^A@uGLzD>z06d5pz`H5Njxc&368jFtN&UZ6yXYc0$0NPnu zA^>+Re#h-Iq8Td!!W=211;4Y<&Lo_eAnjVADQefyKm+Fh_?;oM;S6lnBvzI$_g<^IyTc&!SyP1{RRn&DTE;9l-ei9mI7j>Cs3V4?H%QKH6E>S_ z6A#ZCo&X+@Ga^!ePd~)loNNMXvE_w(^SU0{9~YTW3$W zwtp1Prs3=A@=&152C8!*X6KK08_PgmgfrKlMEW9aP@y|-SBPC`2%*IPc5{*GM!01K zC-mmsr32J!)OLC@gAeC^eLhv8Ca1?A+YA<<0j#UC5O_qt1;}%~%AcbE+`N8-meT9x zbWId`W%qD@`*iaz>+^LRu$|lWW&gxv8Qm1l$1V?2|A*pRwxG z3q`pM(!uq@&FH2+$TZiw<~jA!4x(U*Xrz8vvz-e6e*k1ao4>V`!`W@{^8$Zbltoo` z0tU%SB!+q}rpVHOiIrVeH|+}OW1BU#$d*l;37B8zZ~Zh19LJsF3IHL0`!DxrTtnpN zD^UXrgQE=3z6Dk$4)k*7l_=VwwLHTHS${2YI01-#k4P+gL{`~%S;@=IV41zxG3hA} zI1c9>e=;!jVzHo!PiV&y(|>=uSY(B>r8sN795dS!;48(7TAq;X@%zAV@wJspYRky4 z8(_AzS=EU{`}*f|-Qy!H48Mf!2wi|}SZlGV`Vn=x5x@e^KaQtB%A#J-k7Iond16x=+L7*Sn4UB)=UzeRh$6Z-fAPJfqVjalFT3BOSODx1kmLGSYVLf*OfWg0@ zXaT!I-G(+@Doja=SBt>Cb!lAkAhpscg9;za)WUIs&;r+;XaT5!2G+L&uOT!0QzaS3 zvBwh1aFe>YtcdeOX2XgSJTqF;D3?bSMHe9(4+K7U;Q8EEZeD+6WD80cg)+%*i)v$^ zr1<=)6+`nMDaC3OPIM9(cI=4`e!5eDbi{H?P>x$Tx<2m>Bn3l_O9Zoj`niRtZ7Hh7 z%%Sq3$^9Q}ZfgN>nx4R+ngaL{{gUJqHkiZg2a(kR5DJ_EW;egVGjb>LTLF_6u(=J; ziq_4uqC(XaIQf62m>0kY;KW(5sPW6P-rVCU>cy(dMq+w3QW~Mg)U$0alU?X}hY*`UXzS-vR;s~s@FT^pJvc`hV4frJe*E|F4=!C%2bGQ!L|aV2sL(5Rj2g}GyqB3Jh<3MT3kg7>FO&BsAA zd)DpL;9Jxo$mFagpa^?KkwGI*L51ky#dirxy){NyzI82Cmz1FRiL-uAlqon(ybfoU-`Qqmi zSinuRg#hI!-B<5*v;}Ua<%Iwi38<*AMm(cw(anIFiDESxk5TILm)(d3Oeh;{3v;?%VM#QaQu)^A37d;9+00OIyOJ|su zQY(K+N4GQ#ZC*N!SvQPtum^$kkPr&chaMGHCxM;>;({6|Q5scVB3ll?%T8GXWb#b1 zsK+TmE;a&?0N94~Tcx>>zkCD37rhDxA)M$Y_?or_CBR;6A^{-k@oz-6zyPkBg(g;< z6`o3%UW=k&G_Se|Ifg)|W|v}ucF`z2!iIlGL=Q)@^-)F!oB$2CBZ34b43BU!p!Sl> zp=^yBB_+_Y=;p;5+5j;CD=nvD3Q)J%#YKLcUtEAL2|(u>W-HcJF}LW9*gZ6!VPjV8 z;6(7*Lf;aQ7CbdxGiZgAmX9q}4<}D<9ehM0n2c`xro6=UW_1Z%#%%J5UNQAJLDhfF ztQuV==n|?IMZ0jlDFpv=E0=@r@EDoV2a(ZkfF(4j64l3`!>(b0o0VwGxs4ve1Pln! zs!$KoABkAY?(Vm1A?M$bdpx#2iG#r;y( zjkwsvS_eUn1YHIY%&{Jz=&l92z!85*3Y{ykRLk`cvf#r#am@=+cY4i)WqRmiQe(Et5Hwc#MQLCeU+!G(YJ2zADX zjE5ff7D#AipHzukJ!5FHV-7IwfH3x(Ov+^xNKW=B{6<2NH5JE`8cHyR=;O}1)U!NSUxM6^!ivf_RXTtY0AYxSD$96AN# z;sTunAkN??9uJ+V0l^Ow`DBoy155*A)UZ+f$yJ_`|02r0s^(7E4z0iYsZe(lH)5Ne z@+9IEq~{*oMW~N!uYTIu!u3k?-acCKY3V8XO^LIAJpasfC=3{7kuiViWbHq$ZXS*; z@Y57l6FP?$;fDP#xyNIsY0O$}Z+}r0hBzpr;!-r8v+Pss^cs zREIOJqH4vYFq)dYt&x8c957kV3Eh_3JE$GWNClV!C`hQnlLpQAi};m*!o1#|y*>W& ztFM7??4@@ODpEFmzyR}W^0hiF2M&S`?O;rW9@W0xhNN%c*_Rws`SU1$+-0N3-8j!4 zXCv2Ea_vW{gZ>3Klj24qr>wy1aX)}%l$SM-Kq=2`V{O~xb^?F@hoSd$qXZLleAo^* z4K+ZIm6Ct|8cs)nhXwfa3Z>zPwzw_Pw~mf?0ebqEUuAcNeS3<`XVHkR&U+8ub#W^g znp7uyc{7AUWr*G=|FwSIKMexcCfk6ZhSGf25GRd7Pz zBi##-+g5f-_>g~Ryen&r+o6lVSTN6M9rs27Dinn#ZwainJlL?@Q=f?X82fyx(>9n5 zk%n9hpRW<&B%$Da(li}a5Iqij`C`kUR#ag2-|~}$5PHV~uD3433w^gko{YHLO}gBo zCv4=p-=&%o-&N)msGM%r#7stc-GmN>1#kzJ2*{pX_)>pH6Aj~3)a)4{E)ra{ap06# z%+Rr0icVq=#l%&EmkK!0kO-I9Bg3A>m;#weka%h^xS{RK`KBsb4Lp!z`U!_7sBgF< zohaJ*wZ4MFm;}Ew%NmfSCP;xrwwecd2S^e!g_6Tbsn)TzJ)DuYij&BIG@sMyCE*QP zcodKkwda4TQFx)G^~;ph3mO7Zq)(hYZLIS>z(I<5xh2>;>^3vVZ8U}_71f4e8W}ea z91ar{NaRAYqIg<%=iz16y&{dXl3LvrTT=X1o33ZEMAyvv!UVn&QRE#FvHTM+yQLoz zX8`ICOkp$U&|EcH`r~p_f~C@zz~UDIW0pic-|By8E_+??1%;HM=azijIL=Mo+)?<| zrC?$$7~nAi%q)N-^qmqI+8_T6 zQAvLW72~O1T_hq)P4Z!(i#{(=P?!nbJl{~D zc2zScN1Laa)3Zf+CAz>*K##l#Y6d0x68M<}*%bQ;tz@Z)8 z0V+p(14M`RWJ{WyJ2NkcqkmH&M4IHJa0MVku2iHPsYIac zLbR*#v+v)%q>Z7#x7~zdhfwK#F|&||!CD+ebEwCJq(8$EyhArWN6Z7gRwXPcvBG~q zV;xxM(+ndL0ho@pGWPnqDz=@ub3vt0TW&S#1h8k99=tr(K_nnNsw!yM& z*L)I;WMK1)Y2Sdzg7a%n^A|d~FfXztR|{)0;bH2b!8BL{0hwgXsZK4fwRe1j3an7v zYMi9ac2ldt1NwBrCWBe#cGo;P03z*EM{xS4hhY8Z6UT5nrw0MWr2o`0oW6hQAr|8H zQ%A77+Oe^0|8{n3b3{_1BgGa^sT&b30cE4*rUK=w>c(WEYN&z!0?$}=u^OS4Nq}rV zMXoq%4GbydUq)9|bC{4_z`A5ASoEDW=nB>&;}PYV%8uDBg7c|3#--`(s7^ZWcdUo6 zLD^zQZGWxsVCHFDEH;V}xrTp7M&g(~IZ8j89)ai3@*2ASLX4Eu!x{k6JD5l@^F41r z{`jMm$;Yc^A=pZ+DLhgXi=?YovP}@_HO9Z?^JY_V^bU1XQuc8R=-zZHD~N22;Yck9 zd-#$1C;UDId0qm?^{*z92x2eAfd@&sg-~rp4EWmVfpzZWRfREK@S}g7aU7v5#iA$5 zKFJej{8+zBdDWt^s8MgTo_)*@7PJmsZx5j(S~8p!pJn;iHZwRW>vlN3OSyD16kZ$9 z%3GCCQ}8{A$DSrpDC)M#=%Ld?@@!v&L4LlQGfB;n*$YI#_7&^pe+7R+ryAa z_2_Z;ry&h#A|cx0elvg29F$c_mTih-3!yo-qd%6c`F5oFq9RF90$xqO#&fdROyj`7 zY4(A<1i*1%OW>hxT)7`Ll6PZfJRo{n$o{3TGyzL75>$iD)bufz& zqgc7N=qHaxd6T0YA*2x9&}=#SrWrBH7)h+zwS-kC3ll^AEW3Y8cQwBSYG`;sF{66; zfIb7Vz^fE&$==nwLK$63RUl6+k_sATr~(aISP01=3S)`PFUp8;ezaGlJbTIP;ZY=L zQ%!=dSS7)DZa?Dza_M-aTuUnJUB(k}fVS@e!#SHP#9eNqiOj-79e(KI`k`*5r}Yjm zk~Epwm&E&*mePNY)yXKNdu^R}OQ-x26I@C?(-hUhM+S)&6JFgb{H z=^65L^h^$fVuPdxwI_KHWK8)~6QA~0x=yHM8X-lg%cp;^diO3zpUz3fq|Bs0M91Hu zOZr-Jl4i-Saqi4YqjPaXt%~ZZX+a)gIPcQTPTjeLmpaCeO0>nkZkpP{53b~5_)N5eTt;YYXv<`v$OjGVNv)fU(;Lh8W$INcU^p* zUtA=Cag%>9zW53o$!}l&k-x!z@Y&bjsAsFi*D_vt7~I#Ne}NIb94DsO8PKJ5&Bcd~ zAEnQixr3MIbVrD!It(dzD#usFub8PVFd}7D)@-?53XS4P_Uif9JK%A)E`uWyR0J0& z9UYT{BHmt-*py>{2))%Q!_>(%svRLa#R4(9@BzuOB~GLx=g-Lr??ftkdP?!b6k^K`vmgzg7kAp$K~RNsEI`5bnrcp-DsBf*w07W) zZnnpbfdNB<)9sF)&f8Qoc1!O-C0Hg zhImtOn#E$|Zo9`3+1HH@+zJFkHyZDD3Tls9bnno&{1_uU;SYAMg~LZZZOX!NW&m)L z6LmIH4;8%uxaH7oxr zra&^i%;r@O!Xu6?vlZ0}v~*^g2^nT8^353Blt@y{L9q>?(RprKmf#$&4x(tpj)szo zvsc%tViBSdo1b~ev*_Y#Zu?nVKD)7>6kf$R-p3)3{ub@Xe z9?B?gwY;)}1&+L+TX$13T}p|1=)}h-`2@jqA`v8Q_jI_fgUU%3-w=QNs5}oD=P-(` zdYo|7b}HxEE!(KMkBs}=<9dY)25}Yz(uNM3-8-}d!yhng3bdU@k37*;01E}v38XEk zTZk9SDS1Y{&al#horCGbxe1CG1k+?wR3R`quH;vo`gfxjKh#xJkv zNZB@VB_IX6DV{mn>6U+YS`Th+u~1vV(pmael}mLBijK^kaq{_o?XFhQnEAisuKqvS z!e6h->Iu3#%F<*P6*whUrGYBHCFp_buF69f>?-eElrl77NKZF+_*D8xS`(()--E~` z3D1zve$=vzk_KXAfGmu5+yegdyQp^TZk0yU(#wBvGbL1T&hCGtk=JiNoSpEs!_&7f zILhT3rL0!AsNAx3#4WZDvazYq51Yt0FM_C8`So1d39nFGpD5LC5 zl=DfAy~E}t9k~~+bC+nYe}i?YD-<&T-Sd$@c;E_Uw|1$D>;3~3OzA30YG0(MNi0wB zu)wUPwps7d9Y24_?9@J;o_d>^+!~enV@5QHB5g~}^WO=7ahLmnZAX}WCzRTG!aXAu05$mnMsI-3@y4}v&O+8prmV`{_V-A6; zYdmw2+hI)sTsHb8wTE|_J*|xiNnQ!;=0T%dC#>v)7b&<|xQ<@b7H*}dUtQ&3xoLG5 z#C~V^<&I^d%`8%J(CXg6b+1U&*tHNTbYL&jjLd`$d3-f^{A~)G0V0CRn(>1qbZu_9 zbC4FADiD7g7i*z)EF<}_$ta)WJprPg>zf&fZZaVgg|FTcD{y>MinVe1_mK^cisRDH zVJ!ybb*8O}R$VZL9-x{Hy-ap=s>7|fb1Y;7|2E0;Zim^TA?tCy>DlDO!_Eg$J1LI8 z{KGfV-V`pwWi?Kf!J3CmY@pni?DLqInpzm_96o=Dl=5_N%T7A>_h~=fI?b=$*(wsD zoBQQjdhw$5GHFs4i6Z$C%10qV4_qn7KR$3t|EWTmuJH|GKwq0o=%|DXU_zVnKh539 zVz!J8ZFM_cDL06i7oQr*g?dDs(~yLxrtJVvF*CqEtNv1~r?C|Ut8v=rIkAO^F`*k- zMTURT>+ld^`Hb8Y>`By@?wxitc1o$!^=~a6ZWqtxI5FvMP|dNd5{!L|KE`)i*p6hW z(rqSI>wY^{HiLmxb~5a2nw_D*)m38YQc^zUZt6l^%5b{OWND+p$rVU!vWpyXitEdf zdwDu;YE>PmLvIx_4_8F?;0`#n1`6VM9IY+oojKj1rlad51hf!3FL>aplcs75K z-?1o5x_J|;q7yQa^lZV4j7+OD-u6IH4unSY`|WkV*D=kT+oFGE`e4 z62R$y(xNyGR-%V)V**huC2>5O#lw&d=y#`kVG2L#T_o=2o?UBHPIjav=nn}LifM_i*k&CavXq11VOKHu# z{hBOe`V+mTIh}}{GBB~sq!l|wl_8oIOsaKL6Zh9O)k5D2iIT$dg)ObxgMpWw9o2nt zLy{ByG9Y0#bx&0~Nf$;sA)z4UriO)y>>1_Jn_T>ia`?Hl{cVXsIrQqGV>Ew90cTem zN*^0fvlq1k3-e)=5VTN`(YsM-(sz{XLsC@v?_6`r5e4LeX_}skj4F64DPI=J4=x-W zgma}US`RhVnZ9_BIG+nNBPY_=Q;FN6?wz}h(#}gM7N+(pzY58TH+FC1I1FlkU$Z3f zm^jk%)qVw&b&fq&Z$XOP&hvkJ(Wb<7tft6&atvGGm%*Lp^fI_4Goq__>jK}sptoC6 zG)u`PZ|QjmjOatz7Uc7AxNl7O$hvtJl?|28v)|U^zo>^_)bRkbi$R_PoR9hq9_HDA z`#s9VwBKZJe~Hi09DvKpQm6zM(PXO)!#&q3izYR-}Se$_TXkU&V&UWqE;r;A9L?rwt9>f7} zhfQsGLvJllSr)RwfqA!IEM_xZn~z{{omeA`km^s;-f{brKW;fJ ziUW!Z^)i8}zjwQ1Q6om-UID4$;=ZRSIpl1BP`Y*`7$!6|YJY#yw%Cz!p07VNN241P z#y@oGy=%njfM1aZYcLqv@<|vrLuE8fhN^OQM{mfeP9|TD6_{M{B)_;gmbKx9+;;n} zY%m8a8M009EOYg-|B(g*Ok9S7mtD}$F0h!9Q!5Qf-x;Q3$&nD#0178z$|fGJLR>gG zWSp?W$aG5w45xoK9I^+?WQqoBmO1hG+9>Ido3I-Y>+<+VorzM$3uS*g%|7$<>#59^ zKgj=b8u>3vm^hJ1tVGEn&X2!133$8TpUii4n*9Esf84uRXmqb~mnGqq9a0GKyh~9v zra~*nXT~{JZY%pfn~KC&T0-GaS_CjQWfWhE@PhhZgb{!Hj4q|7#4b1;uJ_yCZ?dWB zTwmI`cDhm}8e%ZhUb;YKD2ZaII)5|H4vf3CRaN!zWvAWd(th#du3J;r+O$`_zn9av zE4|3WeJ)s;Ss;IqjJ#=O3JaQ=m0}^3MfQ*MZrXPcX3ZgJz94orp25-sl2k|5D{`nw z>K!@J+aP}{%T(p4TQttE9>4DU^~sYbV6nim=|$z!roDOsI#^RgtRn`y^ED&ZRQB#;#nZ^Py6z2%LIZ?gLY*v>C*AQ4^JdUM{V$ z9m4N5DcUOTr7-iExZtVIzvUVsa5Til#oPb*?ihdH>jBGAS`uA$D7`3J?UCv+&}PzG zP&p+W3_>gw0GPtUlfXCdh7}H+kX086if@8iweXS&T9J$_@;Ji54Qt6wvU-x;dWWG? zg$`@)XRdBoTU8AoP}Gn?n5u@i-pf=iLGM2BGp()T{os@>{hEtC(zbNlRO%MbFossA zkb!>`;(irJt4dMenX%?$*sl7~R{YiHFncX@iZ6P8FU1n8-s3|2Nbz4YWuL$9n*&74 zbTMmkf%L>EJ1N479*~=)^G-CjqE?Wq5ffG`<%Pm@? zJ&RPD$}hGT&{X+sC8I);ONaMC_IvF2^s&#Bgcx$gvJacOkGu)Yoec@Q;eNYHNZVyy{mRIHnvSsk*)@_ zLC;j;t~IKXu!G=fjD}nH_Az8_3}e6yp=&4*agv zPh=6vBPSW^Ft$JG=-_8y$N_&QlRD(ZV1hn=lI&>*XNpuJOgK4dV&p*;wRC3a%|T}c zewpm4`&>23%jubE6d21GjvISu5d{UXsl8d#A-(*QV@aCzF`+C|l?BinV&ic_B8hKf z>}jYo7QM9M=gO(6N-U6(=SBL-W)Z?PL141Y?l>@W?sWi0>R?OlQTBgu!5J`?Iua6s zX(s=Q8$n*(2HDp4|7pK~<(Jt}#UWzj{*%^l`0uFb|No+*;}Q8mz=$S_W7?dZrB&>d zmw2MfB%8ti9uyfZhf)so!6;_@3|Y+kM>Bgw^{|NMM6BpoT8W2a_syjOzB47{@~ z^cdF1QeO1({+%N75+z#Xpz8-`0;*4vUus0qo#h=W)=PeCTia}|I9_H6M)E#*kXFvX zRAkhvX0#K@JwO!7Q#TI$Z%z+~jJb3nU6SoAG?9uhnCLK;!2s7^$Dwujfzf5HFocJN zA6RTYc`LhD^nrf~;8GZ%0N5k-jpC;+E>QSknOT~#F6AnxJ3w=NThtxK|I*C4q6#de za>ItE*&9uFgTY~7^xa9#h`gmK^gC~N*K4KFDzi-aqP~a-+%FR2AFf$-H|1L1K>rJ{ zd3jSraq!b8i2!(OS?-$${Ldikk{k#DrHA>g#Eu+ry>EXciq}um-%baF3}G2;H=N?- zLc%ru>R_0NvHMRM3R8u9>j84&P#gLR$CyXqMB$qD&U8$ zJG+aEdz4jXy|5#|97WePExpd*23@};&*tKyMG${j;|^M%-+#oK@K0-A8VMN>c7fPx z0u;lOOM01WQA>vjH{~7eGSz~ssMlMk?w@lHh+9pCe8@Af^|t=vLUzO@nxd0(J~~N8 z)4~uPI5))9;|{kUcqxIi-^z$H=J(Kgq^oG(Vk}l1lV3^NrCBe>jLXNF&4@fUr5Nqd zDfEA}IsNzYy z?*AZ{22vk_7~x76_Iiepd~Q$tW2A<+L;nMf5A7X@HFWj^&yU=P`$@KytS0i(4BU$% zdESohX-XlgHv6O@~^{0PShJKO}LUIjVMCgx66M% z?lf*F#wm^7C^xtBU)`=&BCG?&2phVa!A{oBMlNaSmV_>1=#340OG1B!w zyw%tmfR%cuCE8>R+}s9+=7WTXNK=2W5FAM)&>43+@B(!}75(Y9H;k+PDi`~wI*-mv-1qd-W$1SP`N_xd1tmInk~>&*&^NP1 zqv#6$hvp?>7EIBa?rKia5_btgmW(U1=Wjl!z1IwaEC8uvXx)mOJ4Z{KRiJ@(8fWBMHHnlSX*ed81{hvf;n&~bbj4hZwW z*i9KeY7YUosQ=Gx1Z`qZvG3CEgYdP zah|3CZ51oggH^q;-x%%J&&Yq`Q9cHDEwSUHpQ>{~N5H+qh@5vEFM1<}BkO}3KeRS> z@<(_jeEg@3{yk^S3;+K36DFk%3K5$@nzuTJ;$3~x9*F2{eyV*gYz7$zVF3ZQX&-QF z>>tP3pZxqpJ+|V>E>Zn0U>CXrqxm#@^xW$3DBb?@YTi^0XB#i5S+IZ2#81mQ8zvhE zU5F%&qezgMmHC~R*MB*Wyq_%|w}#nYm2<3U1V?)4e)6qo(UXfejiy(Iz0@VTG@Mii ztNJ#%7bf!ZA8VcnezhF-G)Alq7~d&IA;%$Y>F8OT=S{Rzq7#7SMSO%kfvM^?HD`ay znZRH3V#7Xaeivj2ZeD-3{8B&Hq^GyMW)gk#?Y!Dms@=A`vRB0o#xQi(q&{c!X1!G? z*WAplR9=MkGnHhRWVa7ugaqgOhDwQ?TN%25Q4m`wh5WQZ^y}TRD*+J*D_S+TLKnkn zH*OwMkF^J=MG$msPZ*~$D(rcVVLC}(d7Fq!QiCbBd=q!^E`WansFnM2fufZZoLJ!L z5B!GpN-XKn^G=LPa{Ba`zcXf9_ozU9!mI^+@jGEim-lfu9Z7+hXqQA^k=|kaSi5{a z0^_V5GvAuvt9fb!0p~;6WqR>m7K&pLyaMfpudkS*`C>CIc+QgKSeSV&sEWKbAa&RvKyjOZEI$*qJ^e)F4e;M&Vyjg#Y%G2OlVeC3zk%^Nx1)aH6 zRtAq1;)ufUMml(q=s-I1)h&w*JiFYK)xt7D=sv&1C{Q5MJ7!o;{;sFC*cm-6c7}|U|tk$EDnof+UV5*M7UG=1A1ekX*u85I#uj1jI>02J=YhY)Z+e_Uu?Nl3Ku18 z`?p3B63}rpbE?~?yDEx$+-AqJP&>ccxUROllL~)>rQt{BP{T9naEKP&Orndm_<;DK zp=?3f*oYNB``YcK;%H;H@$YG=zo&kb$OV*{rp@oFj~gVuhb%rih-JwIKR; z6r@MnpNG%}H3Kq-?Ba=84I1|v-0Fuo@RZi-UvVS-^Gb!b- z=6QeV*+}6|?W91btQzIoA)eeR$!Z#Cdx?9~^2EDa#zghirJ&dwH9o%$7j3vZA*-VD3sa=DQW96z3{sk^&wLXJ zBcTq1oI~Y?sp;%Y7|EqBh^vm6?@HSH`j>xJJ25_my}MMpUt>AMUf(PlR4a&Bg4;Xl zu27E(B9*D=u8BtiXTdmg9+QnYgl1Kjz|;u%Wx8(cz#f>6c4fIjrQ6IY^ENh{kAYW> zTC435k!T$nTj{yb*r11I^w}6!CoM+WYrZlR>j?!B^!#!hR0v=uTrL%_qcMK2k%4~^ z`rR&T>jX)mxcCPgAT<NaR?F?mP??>IWKo0Z@2@YosxDh~1UvzBok z@hOETh}z2y0;t0$2pekzsWfQY5TuJDPfI>Jx&h7Vs`CPyo?;9h>~u-VEm&2xS#XR_ zaYJuNW7=VA_!;x>3RXza*pR@d4#Z(@vsz)S%4x;}654Y4D+V>c#aCBeHZ=1QY-O00;o* ziat%Big-~r6#xKHQUCxPm*IL07q=%^2}l(V=ZZc}cy)B$ATs~}$;p@hpa~k6A9EB7 zf9-w!ciT3$;P3t`SbMUhTA4}QkDc+<>C2?)H1D)&Hc97okK@XeNXZ;aq)JkD)JgyM zyen3v%mfL`iGaV@FkQxILKG)vTB0Gulf35UX`mLF9Uh^w{4Tv&wfxvfBspQ zh5EcK7Ypd9`dZfN)4Htlx9g<2QZK6PpsBW}2LU|ts=2DN1jp$hdppb4P4JA~Kdq{= zIt_xOU|l7PRdN~>C3Ns6tIW#jX0_T*G>9On4R})K*JVCE;NHZl-q(5E!0V^fA`GGY zJS$g#ttu34s^ve+ych@YVVzWUe@34+Mf>>#J69wt_@+Lc!0R#L*m-{0WE&{?%cg9w zdXd$$WDTEcn6+XtX}0UE9tYD+zDy_OIxDiO2hg{#U%z;nrFoUjnr~q;mpJ`(@VBJS zoY&)^$=)^ux(C+F4A82ZF#)Af9|u3a{Ej}2WL$vGk|_W;hmQyihHh+qe|rI=Fb-D9 zbv8-iwbWl_O@c5~{qN=bSbus}+$769rByI9v*0 zOkk8JK$A5M#H*}=&o8R-e=Q(bl+_Bl^eY!sBPnH7zYv2OdWP8i2(4-~C3 zB6=8-s0x3M-rRmNI*ZPe)8=WATfXV1$be;YCXIXpZ(;04fZsv>|&fmtb_O2Kte-WI`h3p_K(fzQ5;snRLX zK(ay>a2mV@?hGp?DCfke%~BP?J`ElRO8|`}uo;HgZ7jC%%I63kCOJT)PcD1*9OY1#K_ zd=kF}e3u!3bw=w5r=iNix~+3S^6jpd%T%Iv@!5 zlj#hWWCKm+%Q~25vt)xDvkB^CTN5(8(t|LR`Y^TAai@$uq!-Pu%SI;Cvo-+CL!AVqS%Q-I9 zU&g_Fe?3NJ1(?vPUW}!a^{Ab2P$6*KYND(`7}xqOfR$=$t@f%d_L?)7H1LzA zhIW;z5i!V-*@`L_3n85WOAPHkX#7QYiC}(F4ov17V2bcE8jS-Nw1B@#>ZEC^NV*PV zSY_*FGRr3X#vM+4q-<=Lj9}FK&1B0u>xDvt4Y+efmqB@WNxUyf`&FO8M=gQ_s%tg$ ze-P=zeDSIK;(xj?P85fv#ZgvKIYqUj!wiXEaY>}?C6}&)V_51S(vgoO4ZqGT3F5HB zy4+MS9Ux&rE5e@vp(u=-q>2~6;_{%6(_c^2XZj0jKYv$croVa4e&Ge`E;8CV}38>?Az^RQcPhe0CL(+EWMHaueJp zAl*PrtdeGS6_eBju9g7T5m=x>0@njjxCXfx@RnqeOtE4tsl_|K*n=9t8o1#FI zfdMfWCDz|*I4Gff#cjb70riJ*oDghadWo7e#pI#!q?lz0A!&QN0Zs{wbiKVneYW40l6J%$Z8^3mNet~Y_?w7CP1MV>ye2YVl{MOiGt^&1Si{)D zKyUjNZjrHNjH(pPppx;z8sR5se+sDtcyhhYX8AnN>ON=)V738)2JOFi`r;T+DOaHW z1N|z1$0Um{FT-WFNM_sc^0E(D&Qzl?6r~;(1WY{=wzX=JVqR=tJd3>pjI$9>$o7G` z{MT>x4@wFMiiVg~BMpQGx=^k4DA7=_n0r#==6hh_4NS+X9viT3GwM0ee^G#1E8C?( zmC!N(Zd3&S+`#N@YU~@ZZ7dMmh)SI^%e0MLU2!xrT75P*t+Qx^qICw!5sWF>L(BnD zm?7f4)+ClYqtr#Hu1g zr_%~2M_-}eNGjm+B#%J+f4}hG$XJfpbuL2-vS;}z!==~;0+4yfRdNIKH6wyf{e)Fz zHLPnu;Jj6Cpfa$;qHIhY<7~BVw$W&}N@Lj+>LKbhph3r?Z@^g3MxCOJQVgabth>l5 zAg&=3)Kf&P+amhF@?w)&KbZBJq`sb{FeTB*7!DdqMxmXC85kPXe;yO@1j}{jVU=uo zE~Xi1_hg;-Ovh31pSXr#bcjX;3VP|9tBM)iDoAdVtxZM-nT%YliD|e<8~h}uVrIQb z>x^*g$@p+};Wll(+O9Wd;n-+5&Qu@g;9mxuw{MO1MHZjoFp{>k|UouR=Z zzkxZBO62*0m!NAPe-j492IgwLCI{jTSZ^pswH(6bZF;y`gDPY%IF*0{Ny%YE)h0zHB>1yAXPxwg(jy%IRrXSJqNX% z6qwtbZBqpec~lRpNU-ShvU%2ah8$B-_<{`awwKE2R{abef0pL)$?U=206_%W>zg6} zcwQ^D;@{qjKQQGXA=TFUKp1JM2N7K?V`3~Mv~{1+Yl3V65m_c%prR57cI_Wb&~Qx6 zL?`>(r+&T+hSB7NH>j`_c&osywWPgoT zS!CLhQrNU|yme?gdTb%fk)m3*NyEa_@~ubYaF0}re<9Ri6&S)Pt5YS_8Kwkq;W2KyOo! z83ArO0?DO$3gU^~6RD3op&1KgR<{mHq!neKp$pvRV< z^r{9wU*^p=h=8D4DNH3sqPt}*Nu)*MXgl8>JeqV&+MB|m<|2zM*t3Ik=wcEzB z2S39AC<_4F;G9pIQnQdrUd+pu9qiRTvW9WR;)X-cT7qx@kthnf-jYakr=x~9#x%4m zf83r24mhJ-4zh~sS(U7{?pp-7X9#xrA{*H%GK_2v>(A1h03RM9s87>>oo(yj5W90Y z4i05#4_lscsD|#4rr;1p;qb4mK0Ic}p#j!EEkrrEooXru4_OsF8M!(NO`*LR%oRo` z8azLoj1Ibd!S*4Dc_ea!LJw%~I$6~ie_oJPpytm(6YCY>FsJx?yex0g^AdwTSv4Yf zv&G^p+{56v7vsJ9RMR)8k)%aq6UduSX<_#H%L0oK8Sxg=74*T_vSu?VvdchkR`#$b z%SAZ`T3LYo1OQg?qAE9QQ`hS<7^e=7_}CuzvdR}Y)~NVkP>az%y+)$K59h}Ze=kVx z-w$^WqXF>z6e_wUMb*Dl>`vI;F zXg+?P-vwZ;J;F5h@xvap1x|lMdd>Z-pJL$&u@#tK1A*c4vO07X6*e+lOR+3nO|$>u zda&G~N*k^eMK0G+)O_d7F^AEFf8l7f0~ywMkJ}NT%_7>L+}Zef7)w#yJBe=2PfjmJ zBN8Y@BsHXtvyy52LPS!ssm zJxs`Eoq!*e?QYlOqfL58n-bZ%59h#{YxX0OzPXV-L>wGx^1dtz?>w2$Fn6>ROaOz+ z0eal@vs0l&lZj(^jLBPVx$LNkzGqL?iH~BRyIC2PZdu1(Y?JC3taCr6Nwxlsj1!+b zGf#YuLW#)2I8J1rHCoU^e=1eray<9JWrjp@H+ohNPxQIV*wOz*P`v;;Q8Pj=s5YVU z<@4^HgJL;hoh%IQQ88?U-|RB)ChT;^qGI=;3DoCj6UQv6f8vTajE(7*wyVig+pwh} zyQa8fs-c94p+eX&VO~n8SQ4BZ)82m&nfm64G;)l58`DB(e|+$Sf4v;bcHakazTCo{f6T$G<;m={ZSCKya+%hIBA9@d2W_#;lA_%Z(xR85LCn^{CHZOhuyQOs&q?Ab<4v?u&r3fp3NmC`D%8yy=y zV3`R#9aSDV(oVuvjG&0ozKzjaZS(05t@B^l2T_u)#UXY?f50R!E}W%y9&)uhyf}y7 zJsb;7)-;yr90d1~1@F|s-z+KE87^Myciv0zvQqc~FpBG}k-(m)9m1@MMx!`MQ`=EM z<0Ct3(z4rEHNP^(?E;mJOdXV`W9rd8t)h6(I2@p72Q6nesudt)Igiy&JI8uqQQG1# zaMaBj+*ksWe~ce7MBCgjHF!HH5@i`g590@;5SQROtFDrDZ!8f#T;gWQ0Vk8 z$bIX2#EjVXQ`#pzy)-u~FZC`ZDooHPls%W1tak?We`a>oZP%LFnc75G{kVf@tH>&F zj&elCXN#Lvci6$CZDjZK5L;bIz=ohjRre~CmEM+h?1K|`(P3duI8pmaBERKDRK?zQ zY#T%hqqz}8_v%qNRshE+o3cp0jpFvqh=Qayrq9~=6J;w@v28oSxS~O(s*Hk1!3m5n z3@~ybf71DcN3t@7ga*_J_M~mI98rWCo?xiQEdp3t3~#G+y<|~wZcCe+*|Kg&PI+D? zM7ABP^%}*RYRPM#UbD(X>=YCx#p`>FBX2|!K3>jB%#b;ZKarY#8G z7SXeO{XX_3`TI1R!WE6+aa;khIIkz|ufrxHf6b7J^6EilH#*%;*Vj46QJ5?)90XuJ zO3}e}0nDF_@oPP5vEMP^x{>xbrd%%)#UgNPw4qfS8(O<&4#OC6oeYeutVSw=OYvcM zXw}lG=>!@V9plek*G{aXb zw5wlg%YU+S`lE`ow@sCJR<%SQ^3SNd%14hLrCnJQ;$$r*6y2z}!oPkS(RW9~vh`X! zsF!9T?EqBlg_{t8X*ndd!PO+)2kCa)(DJ*M4iNLQdOK>$VXMvh}&O@+%Mir`tg*~W%0K6@$w6^M~mw&*X&o6o^)|=G|Jws+adFQkxo(|KHiWHcR z@a^I8#k}N|SD!!V%Fh-l)1%;XWtcd{`+7#KN4$hDos|+6Obt&1K}ksihnIA zVyj#t(&w9k{gxQXM(`+xL7mV=841)4!jX>mytmA2rHRp@_Yfy$h6f(?Ka8O0k1r?R zfDZ1KgGepB@ZTpr?32LOV2;t7e;<>$pnrlgl5l);JNO;*6xv>^1;l5#=uemYh1p~I z7?ZI?BQOQm7q=?{(%nKO-B+BX zcM&A%-93MYh^LBK+oZIBu8cvsW?<;sri>9C38bYep=E{DY zzMspt9o^0Dds+P+SR4W4xTTXJ9B{1Ey3Vj_Y!F5*1FT8|?!eYpppSYDKYvZoX9jr> zd#o6@WQl8d8>FWFrk?U{3sb771t_1qMcM@@pSq=d1Yf!ouS@Q$jKLp`lB)USiHY+;>m%YJ04LIjU@tz2(zz z99yBb)5Xz)-e7@;d+x>T3e$4r#r0U9wyx=yhIvpH99~t~{4mIJ;(z7&YL%sV(qz!` z8h0?$EERaA{VSsi9l~T&!6C5q!xk#%yJ#EX{1b8nOyGfzwM;7I&PvM->YJq6VWJA? ztp3XWd-dg5dIDl3#Y2Yz4hLbG6$^kRyP?@z9RBva!UTI7SV_Hb^dmt14J8G`tYBZA z9!6ii_!8bde02Wv;eW-)qr-Qhyg7k4A-oCS$%{|n#UrTprhvC2`0&Z-s{?GM0}oGm z*zoYghXoH_*zgV_gxG`KXC3T5cd`4zf(DpDZ#mgn@DBgH;y*tztxqVIi=8$NDtw8r z0S)REXHGj04==uops~Y87oUt=p#5n&IA>k|(Luj^vCVq&V}FsOR!)njrFS{H#J)x| z1;-49Hrg)($tslQZN^x*Rvdlr`Uh8eTpgnHZNP{o}@u59+AAFVt zACW0TQJZYzQhe>sfJ;yFBj2eUlGK*Nl{Z}VsbyT`@qZk%8o{&}wCuz;sl90?TZ|=( z!qDv@5_ZJ;{=@JBSvY?=F~59DUwr-J-#;@8e{O#HB6Ms|UP^4iwGASdHNSl7D7J$> zht9l7X~~4zomYcl=rs%$@ibZ{t7)159|*#G_wJp%MK1=}(2-jC4@RTjKq%6zc+&y; zZKa+0uYZj8KP7(x2N7PCw6BaoH5Gku;*mOWG)HQ~1$brAc&LVVSQUKSVwLVRr$KZ6 z-~#bNsM(qA(f4akuV~-um8{QUZ{cI@D&+OfI#k{2P_?;ky z$LV)#$vc3f@a+B%f5o6F;$|p+@El=-+D481D1TU#C2K_Rd7ZCA)CFmK1Eari+gmb$ zmDM$wyrhODpn8@Yz$~e+G&1m_cF(cLz#wI+aw8G@pT9H!J@{|y>Cqn_5)9ERtQ;z=*|9pc|2e%PH(LIxd z%70M`x;}f!3>XD)VhhHUfBdai8L&3d`0!e>Sxs=*pciKkAH4T&r25_6jI7GCad#xU zVnS*OW?WOgjG0k_=8VFrPx>Zt*;h7pu`{xPr zjNSxglNyisx?+-lYRUS48Hy&g%NTPE1&nV_ zQ^57Ev7ah`c>EGZ^*S=egOMEUv(Ha4HJZxuHYItH^X~SoI{2@cEsz4TAp;WfF@I@l z%=u%9HNjGl%m(p%1I!+n5y~Vm^TLMKSc|Fw3>YV!kERtkD?twC1t(F&tZlRhgu(2J zl#dBFQuSu26uO9EEEf=HCVABjG8Es!x_78r=H$Q_(vV*ZUX);h5#qQD8b>pkjZOl` zIc!+fh4LEIltMgkG$c1K+09!5O@9#}V1wr?;Qs&}W(}7ifFqU%D>{hs*x+|WpQK1< zQx=Y+0n11A)Q&zR{}Bb~B*jAFI}H+a5A#}s%Ht9>uz<6MeX6`>Y^A0_KhoDpwknIr z))(YgJlpMLxv?--F=LH6f42!RkbNdE17k)RG=}ika}z|a z1XUtI(3-;b9HSZ&j{&NA8hOnq(>S;DULYGj^xEN@CY80*_4{rday*o=*gd_~0G)(K zx`1`G@GR&!`giV5_U=r!qkn+{MrX3?{@hBZp+XL)a@LP8NY{>UB+125o1w?(Fy_vr zkA2EH6o5}B7rR~6TDH#CA1pd!=K8D(e5DeBPSOlH14nFGj*~ZFg5|~L?QxX9N&o!C zySIP-V)Dgj?~-bTR|ve@FYvYsZ=rvmp1eCwR_Pa?joz)2Sy{h5{(tIC`pM|c)b_v- znPZ@F2e+Lmw7$k1nTbyAgKpa8)H%`yO@*X$ z7zngXnH!=J;Hc(~By@h7==z}~FvA5|j$OE9K<6)xA8D2$XBExfbx%^x_N&@646!cX6ad);(xEioObN{OsF;=bma4o z42NR-(Mw9+O8fLBX2s8En`P4RiW*YX$g ztBAr=K=9$n4d}#68%o;6rZi5Ja|mtDCB6;2IzkT)emtxSR?;5lc!#n6^|3Nuy9SR_ zETQjiER$Jan>%y2v5GWgn(&E!aZt&gv`Pa`cg@IsTz@Lp0LV!E}vTq}`_ z%(ec!IxPnj_a$0c=uF$2~tF4b=WY zGQAcXhSuHU-B2k<7?TS;xhbJbz!esCaC*GcLVxsSv&Tn-v3Eru*|Ypgd1R1+anCbv z(03Sz-NrdDhi1W=73{KU{%&$uNnZhcd5o!~>Kr4@RsP4kI9_F|5=;^{+gq0T(@#GI zuYdUZ2Qo2E)jbT7f4ac^vevdBV;_&cQ_wri`eudRAuvlcI12g3V1?Tf%@ULWps)Z} zm46(txH~_mbH|*rR=aXl6a}tc4Xwy<`HEk$+89YWcn4r2)q5O>M=Cq*8pbznvL)R= zvMKUri#GTDud|yc7*bx{f11?WXNbabc_gQRj_Ja=V-PWS*I+kJQb;3bF>X_ZB-YBB zQaZjCxnz=r?bBRihma0kcT(_g~qPBaX8U&-VCPwZi{sfC%XA! zQIRnD8ACUWFjx2ZAnnYbn?SlsaCBewHpebs(<^n%84r1H=$;#>%h1|x;MaZf=~me< zfS%j{$`-9$dv*4&@bL_};&CRsqnLIor^_~*ZTMT4H}r~1y93{3`iOI%vrNX$dwodusg_-top4kJSP8z(s06hHkbCV$k8%y-aG zf0yR*aovtPhF!}tvWB{%$mrGkDBizIw|aH*wi}LKq3I?d`vb4h$mOQN2%7~ZXV7Iq zhZ8BGjvIv%$s(@jjZsx?ZdBVL|rT={*x)7ET(k0RUHb!*A0ZFIy6%(wqGOIe zp@4>ReY}LlzHCRM9~@mZh$EDxWAAjx){5%GnT#AKTGa1DH<1Gee7V%NN356RM^^S* zGOh8ildM@*rfuX=kq=FWriV+V^=+Z@o{y0^ zb4uqMYOr7Md`#lK$bVwsE}O4{$8~T^kuIEMutmgPDRMCrsDgOuY>*oXA8XvMy#WkT ztW<6mSL~sw`NWTT1*v_h&0uB{g~+~_Ahqn|_l+3AF+}Ep32pJ}XvB*+8_?Blvb>J0 z*>)H(Im^lIP1U@TP7t)-_RaOI zJR>J)g1HM18r~z>Ge03WO9`U=I_RA?s&`z8;LF#mp8l<3|1Plr)y{3r*t$*ZmFM@5 zsr>wZg6HRtO7IkZ_kIL#=!1Nsmor5C{uIvI(fj0hp-`M;$yYXD^oP!|M4L)&x)Hfv znlB{FdG`a?1b+}_PG`~d!HgzQ+t;%#VpuLWDrP8U0WXl z@0U(zrLsHxzBut_Kf@ zc7=3)?4&C<^UO%z`!=7<9{f={de%(<^FCKlgfEuKEW_;c(sP|nW*=1cNboU`ZoMtC zfBvx}-hcMvs}9`ES?U2g4AtEPl9z*79s!nLJXvV)vC~IHbOFNHsp;!wY_T>;norYX zi9(FoE>gEN=_&Z20bi~x` zg`oScJzfyf9xz>Jd$;X;vkX*pDxfGwG2v&Gb$|TvVo_xaI`1M#T<%O%hE0Ev2gUV) zD1d$G&~d2Rl;}QZO81DDGsJrs{OEwGFziz`6tx|7v2hG>RZxh@HpX|0DB*b)sMrw4nAe*bhJpas>KCTm9ToGkRSs9(WAg@5^h%;Ta6mSjODP~sXZ_geFFsj`~i44fT)aq zr&5+Eb|IzXIk4xkiR*jXB)`1};%Q3^)-4iUHx&wre*Xy3U5_(_95QOx&dtrw_*%|Zt*_9z6jm{wGI~DeFH=btPfV2_Dp8)C@C7C zaq>`J3t7(&*YIp|_jbTKN&fK9#DC;b5TL5S9GgO0_^3+;=7hR?t_K=faq4sy3q26^ z4PIEE@n)7fyM}kEQ215eO@PR-61A6FGZJy|4PE7#ppRqBw}HERQ9YpK3^r$1)0Zeo z^t#orVBQNv-K2B^Rk1%I2)8vr&NxjKz_&_%-u?N;It#s;}+Ke%~NGVIO1l`Stxz)&S>FXtj5YR~ly!6WMwL05XcKvT2 zykG>#Ng{iZv2`dfm)iqjk{gV2!!!0hfQY&B{apSO9GVNu9S=J%fo7_H?<=5H_3r5v zyOiAFGq8F+*za-8&feWHA79%8>>xmpc6p)$^HPmr@c++kq3owFc%$3|>N{JL@O0CO zgk^o-q zN%P7Ne?4(GhCE8>HJ98}XKrLYQx539&mVvPbn=gij5}$vVb{KQ&Dt|uH?!nmWN9Iy)Q9QOy1l$^pU(U7IkcKLg|KRjI-`aKR=`$2XDE zZC9^d-iaze+H-%Z&kj}>U#C@@Vj5HH?kttc9-U0rMzT)riK{2mEiuA#{HNnAZp)p^ z?JcIiYSbxDSC^|z!B~xf%{r~?Sp#(yBgNx^Myp~7qO~`fuyh~it_c}{ z@HS})Ihi|}toJ57#`(gXiM0=GVTT(%WG!Z(g>fO|$uVl7& z?vHO+0^^z9!6GIU{MVADbN1#T8;R;)VA( z$FroybC@;8SvL8NdC#FgbY2#&%Pd;%Kj)@6wt+d3HTTwaAZq^1;>;7e%%k_j5W9WO zoNH$lH|~13h8MahdFv@mFVI?I`4jetD_-b9o6k)EH%h zBBQ&uYNIc>3@H|f=tTd*N4*o-dB}}ukp%5{ptC|I*>goa9n^r;eM_lK^<00p zxX?ne5zV|lKF1qrd70D&#vGFQ3#gR@zLlAqf_Yo&bwyDKO4Ys4ctAGPUX9IWpsG(= zukCU-jTbSu+KQ0SzuDD}B(0@pJMFyzszIx~qDnS-Y|`nly#ap+Frr`aYO^NNh>aY* zb?-z+M;0;c>VZsa*CeBgy{Qg8WI%uY7?^OQHK=VGkL^Gi24wBAJUf00zr^yVSL%^i zsHwI3nOdr2ig}#yZPk+Z+qkKn-Skk#Qf5%)M@s)~k$cUQ?qwqAd&#!gY@-zc)Z zk%n>PW|Zgslb-j=)#Uk|I61#>ZN8RQh(2Jx0j6VK#)SI=90ydS4d_Qm1Gs;Z&vLw>Opg1ceZX0vHx_gWg(r__Hni#{(8K2D-jUP|{c?UGpq5G!qOSyv%&8nm_ocr(JneUR;W z9#bqDpS$r!y+Nt?>^`tA`zCzm)j)X2^~iN3HH|Y+|6>&e_{aPZ0onX{*V?`Y={#kCB5c(2w2B8}O- z$L^`Ik(qd>hV`9*?bsRQmeVyoQ3lHUs;JEI$$H#eDxHQZvrp!&=cUmShp-@az^1^U z@O#pN!FUxoFYQF=i6z29%Ua)I;5||5|?_Mmu9&mhX%x)G0yFfSIjQ z-WHYp*wo>BN#<@t(Y=Rb0Fj;9gJc4q@U8(XUE9Hl6O2uh-&F9hp1S31oUzGrz%GEKaT*YF+KnFYlxx@XJybhf-D zvtLu%An$(?RimfF-TU-pK~npwJNSsm^mRPIeD5m3)zjl>u{B#2bRIi>Yj5Bn56O2B$Z127e~wqr5h1{{rSho&NA4*?qrfMdRjcA%!x zB14~|?1!=|jpaSbeod8+Da)#X0tTqYyJ(&o@24bjyFH4j#WcAr@;pkmcvYyM?a&|m zA5cpJ1QY-O00;o*iat%Z^`Hr*5CrFnK25itu?af{4(EzKO{U0b5UnHt05Y7H|DXvQ ze`R!GWMOn+E^vA6J!^N{$gSV~E7-U>q_UD~YqPz#Zr#>RlwIFVoE+Qxs@G*`acr}e zNR_1QxZC{q3t-+4QnIr>?d`cf?Zzf&Fc=I517HAfI~qM3MYAd|%B#I-)n1PN8=q`# zZ*4~}s^xuMTwS+O@?sE8c6KMx={1Yqf8Dp&RT-UBm+f6vv*=Z|D)X!@s&WjSP8f?` zAHJ9#olM8=hc?Q}JbLl===AvTPv4xrJwCyQ&~EF=lP8CZ<(w^8*;41Ix{O)?|Aw_0 zfXkxGs+MCdv)N5{#hU2d^j$OF+B#V+msQ<1Q8u4P3!}p#gNMoPcxM>xj(71tf0H4h zFd6Se?8B1P1r0bKj1hya%eq=bX?nS8S2au1s8}G}XjK+K5|+-3metw3+1e5>@ae4K z-Pj^4=Ca3vH4R{x;+yocm^0bquT53T-{;lU70_A!S+lJz4r(mHyeyh_UR+E+%-9l% zG6dvqS>3>|X)4;zs>L#EWsj4#e+H0;Z--GszoqT{k~PDqWglAlUG!RH^$h@$-HH-s zwyaqzUawj`7wB1Mvo^iBPjA@$FuG!GO3%c^#{whS9^W^!Ygo!5F3|JmJL$L6S$k1e+=zk)3YQ^%WMI39{?d{^Q>vq>c1(P2HH;Rx~dbGe=38$tq6W# z0S|zPe_Itb%QYJmO|;;>afMyLFRJo#Ud-CHklU6mmTlBlFhrI|z>Ie_u!F&F1)Jv$ z@GL9_?t__tyvpX|(8%AEHJepeW$|~Gf6FPj4vBBdo3gqq^_Y_KfkVkccgVLU(zVK0z}jgF`wn)?esmVgVdG&Gzx(>j z^zi7_+jM&L;_b`Bqc5$8?~bRhrpL$Amy$c;a~x(`a_JMT8dyc#^e6?O*9dz>xR;tO z4>F7$leCHn)tX(h8o59aXdHc2E!pL2KEIFd3J?+(us+vWdBt*Qe-3L3f+4EP8AFDR zK7alNPQT$&1)wkhbANZuV25_2k0^kU0R+<5heuOtaQJ)5o{y;*Ld`9p0y|u3jhuc`$bEkVZN9|tRt%eDS(M8Yrt;dL=%Wy4?^ zTj}S!&wuWDhy@$zM*ou8LCY7o2@8-3)bAzi+If}bqi>F1hC98`;6t0f zK9CT-O|l^N&nLhBf1dk4#d8F>xXoIo7s-PpQO!qxBBGzLcC{RNoQOcn4iF0aDXN=_ zS!`B!@bG#Ke_d33E?tWnj{L>14K_8I_A@}k;HVL(l+dpoor1O<4`o*q>HgLSuV3qd z8rCKQ^VxW{gx$dsLk$SO*T-wednM|_@AVAB?=?LD>FM{U#|NO^+losa$1zz7KQ_03MT zo?1^ZUsiP)8I++{Z0_~i4fN9V>gqKK^-@&ydleAk#gewp0!(n9=Zj>+4DBDpvq~zVlJg#f$0u5 zHa@|=Xs?`a$&tyl6{b%q<}n5XZ_y+Mj<_JQO>%Y)3;WH{*GF%^JAySns!BGn5ds^q zElL9u9Cw^8k!nbX0mo)pfylp@Gf96!jhK7Lf4OzY*^mAa?6f1f>YT&a2ApeH8jy1_ zSfTYjnl%k$h_WzF(Woh_HdV&E(c?6C(2g#vjJ--f7B>$=&maDIN*G06+irjiL0Wcp}qktkf9Bp2-ElelN z`K~bfpcu&V96iG|D1$7+dlbGhFbH~4qmtdpRUoOwnHO8AKPTp&6Z4u@$izej>D()UO+e|`jef>SNvW8rP_`UT%}e+z$RbaPrSrFUh|bH~KW zd7hfBLY^7fo_lBZ3`Y%rlUoOJz;_ehNQcdy>Ad0ZuB!!0$$_(Hd2{&NjC*wUv~S0J zo^p51UeMnYFSL_qFW?3X>s5#x#wxG%S)+SGU<@o z3wo*S)@CDj#^z)_s#ydxdZM3AlHGE<$rj|9GPhmWX{JWX(~Em^e=x&cg>Dq#i`w&j zW_snw+hQ%9aDr`p1n~d@>*e8#gVU+$Z}r?>zT?;CgTa=RcPBwOakfZ80(o6fNs|y@H!H2I7 zUr$dCUO6tn`0OtSqd#Y(zweBGGd}-Jd-^a+fNuNYa94gOd@z*8zz{tV6g+{C_sM&s zT~f#V;7Zr?1fKgeImJVto^$K*;3bmbbl+BmdS-D!U8nhGW6^~;B&g?qFKno1Z zzyN}p!O=MbJh<`}VF&}LUGXR$N6|r^7dYPxue4zp15C4oUU++NdUixONOZwqWtcTE zVZ9%z1spf4e~Sc08PXeV&L~f0sHr5jKst#dWSnt47+8AB(`E#wQuH*kms$sWyk=L~ z>|W|83Fj}p>KJe|rzYBPs?fnzvpLHeCKg)-1S#V{#sJasplX}I8DEWZa%{4EFpf}X zpJiN|1>>~M%C-Pu&9!mDjn+Xs%|QLn>Z=t75H(Q(f2&z)2jD1r23r61vmtfIUrEI_ zqebRSw#46IqR*nM0khau?0P(m6kLX`uyqJmv5uIn$ZMl8e$j<0YNef*C#r7v(>ysqkl_#eAA*V+B8iX zHoqJae+l-{LpqGabj4o+DF4fIi3t4mV=+c-`(n=!tb(Y3orCyUf#F6T+30uC#L?r) zbi)f5VXj$FXlin*xDVNf*?iT&(iol)oYXiK-fmE}KiY4UhC<;g+R?1La?d#{X9c}S zOzjq8VfFQCUS;bXCRH5JBysqG{$J8+a z$%bB_A4^lXQ4ezvJoWHSL2V0?u%3ZOI6~8e3t*#v6X@@wW`b!17}?5%ma};uHbjh6 ze;f~-ZXkGoko@FM?Bk)W?`Ofht?_#jYn`MS8| z%iszHdDE)y%LYMgLXmb{gZU8y2gLqRoC)gYdN4r{_J+^ew(jCki#OED1&77{XZGgd z`{SVH+As5V$+kGk->J||@px;SV`!a0U_>r~lkXGK&CQp?2nCPz$e1Ly#?VS*e+SU9 zmtERQJN`UEamSy-O9k@5io3aTL8F5R%UxdQLr!L8rJn1#7&9&!>!5Jf6b3dfq4g4z z+JynNT9pHh$wYHgQENyGN2*vjE?|oneV9IWJS`9Oc%*UY)hFG)w`R3^fO_eJ<`&w1pkHcQ?1vLHjsZhyHP&*oLb zOqE1;H+6(ZOq8qU)>IeG70lJk91uEKSoiEuc>vUza{P{@2kKmJsO{*xYgW>9fOr(s z&#wn`3sJp0)7e5+JqOmQ^?HMzwJSg^p})t?5|phZ9)d|s#8h!4 zy!p8YN~v#zl{j1)8*l%R;v^Ej0whY9CW1)_v_G^CbJ26vB%ph8d5(uk5X4=hZr`zr z+zPZPC}yR#a(MXNDyjWje=hi5^MNbownzd%H^nj)m$;$h={w5mu(q$v?5Gr&jYZVm zBSe(6L`X*22tPt%8PF`V2BgnJh@lfOD61+W!jMa&OPsA;Bf{8{Dt`1IKaG7E=O}n; z$0^Gxu*Xq*H0EncY|Mo8~d>;cyP7&FWR^v9oo)z3H1*Py@x{oM*zB(+)^m_pHapM z;UlDh+3VOL{_UOYw|FEExh9G5%5Ygw!Pc&YBktL=o4c&OYHSH`VoGCEk3pe;{z_PR zOp3(#hW7;SJ#8!wf6Gwe|HRrDBp@c#)K-s z>3yOjLkHMIyfo+bHAa(C;$L22BmxM?*|qKMMXsS-wyfofe+!I*hu*zdW|)rxmxCb& z6C0cBpkJa{i6^UpRxp^&HYv5V>);~<888GekjrKwF$BsMBAX3wn?FQKlF|Tk=F=3u z8fJT4mas&&ZxI$B4d#Tv4C!*eafJy*sNw{v(HNT~0eQp8B)I(S=Dg3gCy+2v1+^R8 ztxX8d>D|!8e@^g1iMzlG&u6cL4;TXT2I`75_L6iam)*t>u`JCAB}v%BqkKPjQmEU_ z0dkf#DITfAuTW+}`yECJp6A1eG~&U)XIa08nZO*Nn^a@ZZpYYinFzV6B&MNp+Zt~8 z{7~@DZH7!jZZLPw|AJZLFAtoTxynKXFPdqI;w*nvf7OZ1$o}r&_~`KHOJ{f)@?h|i zbeq_Rm%6&pnc#_Wr{QU3iojlcf;KsNjV^oL!>R#Zud>+~1Hx^{WHS3@( z$R^kU7>JPa^q;^1*Fn<&*`&iwDya`3V3>}4kNUI>lH}*1h_ssijVWR21(FC>q=_f^ z)Irj3a!BFD53ayPfvcHV&N1?qOH06VSX-y7f4B|VmvJrjLHp&Wo~`bzg;i!^>XAoY zsl)0?tbF3gMsjTXR>x;j;l>rs9=d4uQkWDD4Z=w-AKKfa%N*Ts1k*Vc-bw!L6MyR5 z#N&@Jw0aH?XW7=z!5|{^KAEg5L|j_ zf4|kSC_Vm)&DZ6@>Ws-PhQ7Atybp}5b~7F8Vn5?(vo_?(dO?SOacO(@3Jj%Lz_3}_ zj?o0=0Ps28-H>w4Z`q1Vz2U0})gIJ`zm2Plu;$9X)aaWi? z7!u51Qh|)*OYC5u5Q4@OX2aW}L;3972E}hfV%fs0>q9v=(Ni8~M$Q${)M0!pO~Wc9 z1S1T(=o8BO_qF#=C5F&Raej&=DK-uHp=69ZojFH{`c*sDdD7(`B@exwuuR0@f4j+J z7vuO`r@C8y2;h28ZEJ#x$~q1GXVJ5*G~d7r$_cg>oJ*7;IVZrFp7X@wB=IbfVR){C zjWnmk)sZ*qwN5pD;Mkuuv<%Y>tg3Q|hBO)cu}+UGeI-P}c_Bs!-#p)HEr^Y#gb~7_+gGdxNm|aijB0MEs?@l(A>qx{05UGz{b;In15#f6OFV3C4SC zfa-+M=y-M++U~W{*+N$B7q4CBRD$Vhk*b0(RtAyRdaescsR~(c8#52ejmdZ0-WVlp zRQ$i!YH4IBXn&sDN@pOs1*Lox&159EdX3TAJVx-$vjS*UF$N?2km^Awrt*zRJUWd1 z7fHFKdUqRJ5(&B+kZvtAe^POy^VTmAf=)YMt!Rb5A75BTZnB6CVsYn* z`8UeYc?MeDvxqX|C@EbI+jxXkDyCEOFqrul&>hD2{Je6XXk62Idb_t`fT4K zlT6`%qf=zW6H23@e;jorH(eh;17)*DmxG~8(jBIg+aT7A{NN9Xjj;ldaX=A$?9^Hk zm&C+jp)1sTqM4P{!|zNw@H|tu?;YR`rwzXi?SR9twiUF&dT=SQ@iH(?8Fc=;r%gov z`#q&+@J*GHW|O94S$3F@IVPv@Ix~q{8rf@arl$ul4^9s#e>Lvt;0>lh#>;y=`NmlD zIo|s2tLgN08f+)`glOrO@b$9b=-*S*k!9t;!K;EQJDcUS!FXt>K11?9CvT6q^itia zwyi3EK%Ouv6eS)EVZEZeI$NUEVrS?P9O?7}IK}K5_IjCP+7sF;uv8;%csX^s$7(Y4 zi=vA(SKl0*f4=x?dh8aI`^%5{XUUIa`0wD^FJxv6t zf6$u7L-GEjNSQr)IsIM^!c8!Beta>RbNy#%G%+N*)y<^pL5!^*o5}n= zphSHPe^AED+oG;YIz{9(PJTE#J@`KT_Tcp)t+cbqfr=hU*Zvv8qMNHO8N}Q&Lz4qK zIL8MY?qYD2vqeH(1f!*CGp~RaDJ@tkTSajyONn!bRBWGY|MB^yBGWmP9-0cndGo~4 zZBd?onP2=C|3hvZtnAMc%cs0HxzmeU)<}`Je-Mja2p}@~a~Op}KfK9^)>b2tAh@oc zWfw+@gid0)WD5tu{a!rf^pd_vve3c^(jp)Di1M^@3>=qvEf*M7)kIy2Djz^3`3B+; z1fzxh9N1H2t_J$!)w8%53tz2bJ-nhVfDnzWOi)&s2amPU+6sM^pyo0^n#Nk_pMnz$ ze+f3~<_fp4b{1bTu;H_o3i?n#b*}myK00Iz*}bYnmAceKYDO#}?Fpx_6=2WZ$Bq*0G)NXB(KJWqWHkW0Y5nq(=vo zq6B>tR7wgY)`Lb#ffwJI|JjocI9%Nne;23x9xe#jaAw;8P=_|g$I=)^c(bB9ur^)6 zW?d6%R$TWc5UESJWVqYWR2ZR~nvBuJQbjx3 zSQ=(W8?NROZeATB7cKtXmM%zi14T7tI)@_FRlY@%8*g#_VHKPM7wi34*KB-?0nOwa%^f>{ef8R%`P|l5+YP~jp)J_bK*RqnczAB3}?&uU7 zTf{gLIKQs%ZSZw$X>P(r!r$8xe13z<>kWN(iN7b;ihK5(vL$#P&TqO^1N;I0Y&8uT(bGix^QD)P3(ep2U(;?z9!3?&CQR{0Bmb^n)GxDdQ zE88_4>0YRlc3(<}1wse3mOQ<5SE%M30e+1(HdeNSs`7`FY&EDU&w9try&-eh-^ILZ z-kZ(8V^)3Kq36+e+Y?4vfAaiVlyS#wfOd!@9y-*|Po3gY_Q3Ce36Aa_ML`cly&BSk zi+wjFOLXlQ`c~0zb(Izt)!ow4f#TOU>6A2HL?&-*oR7-xFl)+aIx7R)`AUL5wrEh# z^W~(V0A*NR4yDh8e<~r|GkCxy!aD*|&kSpmE2O~&Liw;n3Lk$=e{pF^2LlP_Uv!9b zDE>Zp316r6U{QM#p&j|}txl!?Y*mUF1q^QWT~x;Tq}S7RHorOd1QGtY!szE!W!5P&TB69S>JWw< zwJbJPSe(NIxKX%ue=RLz82$9IQ_v~${v}~b57`woLQm3R02akDKf11g zpTM$K)L7Etft#;u+fu_n%40ith{x#Of!V}PZ$EtYf7NA6E_r+v4}v#6>q^WnkiAz?+#Us0m>F0uT=C z8DB7&b;Fw0tVJQAl(zt)WAetA+!(H-_!@j@H8$I)e?+xS_M;;l1xfaeZT<@cN?;UO$vb?&lwgwNDEO^U+I7>S z2f^;cg>H5@xkj3)M!;6{dvj^^%Wj8EKf?V;+W>OqA;PbJas$oUjLv*T&-K%!W;qr^ z&oHS%f9>+2NVYO&+zCrCxW>|0_imSk`hsD<&qC9n0HIJXL7XSNAIZ0%`r12taZr#N zoF|~ds_TSvpYMg`lkkfVv;=Z?0A)a$zl;CiWkpE6M?~Yjr_COoY8WvXK#%G53!}*2 z$xn}UcxJXiZq;nIsxe>!OoI7*NZ%zYT6qr$&2Pp8(jCCC)X)W^N{IYJ zX6o{0lrK-RmK9qwFKjKHLO{KH6}{V-Zpay_zKCuY*a?B2C%IQ%A&qri^EcZlXq& zT+bkZ!u~ocDr02@ivaOL)tB3pu|w(WmhYOU_YVLjT z&VT+fKM@xYZ8#dB9TaFcj#sk7DOuh`j`Q*XW(ak@@m}#|JS)jt4fvhiXo-Gv$Di@z zMSs7_Ql_Z#9^!u%$4==8>Ti8|fX32}LLBqvPLIbUgpxoyrWGm_%oYoM=x*qR3=M3# zTY>m2Z^9ojhly2k)o3Fib*h_lpS%_g&wqY0zjP=1eDsN6Ia!F4%a{&yBX z8nUddIwYC!rOjA_Vf}55dY<^#`yhq1AY5NCatF7Rc*lUPg`ycnv}GLo&B|M&QGc&( zT8sEPW?F?_E5wY-V^H%>p96|*99xQT!msb@94Il)@;s>@;}lm$c-)z4LAGZ<5;i13 z;Qi>y)8+{(T=bw9e0jUZoZrmqxA8zPF_BSxF%3o;ir4)i5$oeRtbqXT2FnxwRw$iG zt+41SGWECCC@Eu|@B9O1*6Ggol7D}`JAtiwsB&T7^I4L$#Coqc$^fusQKtdGWpNog zCWYLrNXSA96t@~#%u9B+JPmB68-1p0W~+yW9X#m*;v^;sFlJDxR}E+!@~}wR?*xX@ z2|ypKOoDDu+0D&;RlVw6zi}uq*6cFTU3hZro~RfsDx)+jES=0haR(Y`V}A?~R4vUa z|D8!doX2=s7N_bxDQ-PUKX$IqFRTyH6Ix_$=^*kXo_+wl=lAkUf%LUDWO?)3YmDVA zck_J$=_ME^5K!^gUi$Ipsi&@54a0K6@2U?x&-@B!v?vhb<7j~|FND8pumM)q=MiLH z)&`)1SIGTD)D#Fiu)4AB5Pwi&)Xw}IN;t?@i)E4sjs2tX4&knL`=crrtiQP&dvGm?eHODR z=R5C%Ei=M*3TN}X?B4qfB>s>(2uA|><4q_X7gB+{C*GZ3OTN6bQB7gFzE>je-LS>NW~K6$0nDXikzJ|<62!gw#zflde8Q$C=!zBp-3(P zjz+Gl`|a1=07!tOG?Q#-mo1V&qtWkfG)HXu?UY4%oMfAGR>}4B2YfOZ4MyxmUL49~ zvz5$$F=kI6KY2EVf4*bCC0Tf2SK*hW2w>Q&B;uLiF_SryTh87df8;jL*j2uk`>^Ef zWnN`*C=+-FKX}PPSTB=hvZ`bbcbk&)9nU1fy5gL@TD-V?eRUbgJITTJFO!t(c_kNlRYqKxsp|wctKU{KNzDr% zXT2$S8N&7_Y{LQQ9linBvOG+XI=38d0gvruz`B>3!lO!ttCUYzk}Yp}b~_#naOXhb zxgkLSLtoJ|f4R)U9bYbC)bf|hmly9}T`zyVc)fUed36mFe>~3{{P@$|E@iN`0A|gH zPlCroX7)QDzQ2As{b2}{1Ez#&p7Htcz{T*V=Yt4x8 zE{V!qfG|vfwCADN1-DOzY!_z9nhW`xz1Z^st3fSdphhAO4m$W}IABGY1EED;UX;-` zLAF#SVDsUJfA8TX?s7gn6Yx_W3i!ECvS&|+v*!bV{>^mC6y)`Rgf%RRG>MdS3ZQ6- zOP2g!RZ@~rihxb0h!@CD#FcAMYua>%OWBEo&ohwCsE9Jj=NoE-r>f3ugK)z|~GW`@Mif#(4zLQ?o3 z6e9+kiEdc3HX57=7KLdFnhiHdtaVZf(5@uoY@f(2JcA)1yCD0>qQT3>yQ}NvtHtZf z<-1FesgjdA0aE_T`=8M_!M6oL-v9LR@$^4~&)@nV*(doq_;&o$U%c_)>czXo+w0}^ z<*#pFe_dP?0Kjl`#6kg{Mx@ysZ@ItA;|i5$ zU1ibuyjHX2Qq5d0^@wr(3hn_XfEcJZ;-mWib3LL6ODSLs!VCmRmh`>AYaqbdRVrZs zsAVW+iAzk>tf0sX|M9pPy9V1>fNHDP=Z+odf51@>0F=EJXho)ns{Mm?Y2e^K!g6!_ z@$qNHDp9Tc((|Vx0*R2Hg5t3M>3=^3U}%s%6R;2yd(wE&pbFas7&U3VGebLp^Ui#t zv9JjdX)5_+He#>An7~dYFF}+*l36I&V;alvB3?*#N&lga!W(|hU{0Qaxe--?yaLHE ze=_@g&YlL}JDU^|>~IEArBn@51gL^rsX~X-1gfX zT%UOZ8*lIjf}_MDG~aVp@y4zg!?OvqC<;ul!6^MZ&b)@s_GF9|vRvBF98`ww z<&}V0i+g8+q2~bcV16691_chr_q>e|uKdRrHmf#IX@b^a>*-(+rC`6=6)EYje;`n$ zpRc}v3)E{2hl*hrObvvfEP^evN=Ac$BQQgA{?Y zf||3G9OMz<&RNTV4+fo$lBR1(7F)gwvyHH9^D@a2w7i0+>xsr~38Fb+Ku(N$=yw>$ z%QOVz0m3Ne*JZ_fqNKPyEXyjJf4@Xm305AQP+rV&eTx~mPS7la*1f)Q2Q}-%pytLM z5J9f3Qr#j9ew) z<@@Mbybr-Yy>V;cQt=I)h57+#+TpXW*=#u@H7^m%3>~DsrA&IX%|Q#Uebe%!20va2EGgRRi5?=>qo;$(OU9-lQJjr~uawpob zEtTFbI#e_eAn`lLEE2WHr#DFi2V#J&NYf61TV~Z5CUgA)u|&DUXcf>vAFHhy1Q@or z6_AiBTjtF6F-e7p5?_zLp{RF!ayciuG8g&Oyx^J56pUilMR%}8f5>$KTnc0V>6k=t z^o`eI48=wMo2$#R#4K|0hJN%o8kG_TkcwvzC;8sXFiBOij%cwn4AG7WjD?W0MJ{93 z$=y-~38&Ox-0_vQj4QSt9g5e8{Ua}L!V-%JKM&xuzFEe+vF6xFQg!o^MMaQ7I3;r>%sixIs&KC;8WM!5RpL8;~>>a8)H~ zywv`?$LxX4mrE7TTYIqe>qyD;0Oz~PQc!npm#!(i9lkDI_$>n6Q%5? zx^>GN*J*H8XhMJm+fj><-9cppC&qY!OX(_^PG~4l!j-Y0Rl}yMYP049r4D<9PD=HZ@vX7-U(CPe~ZKW*EXS4l&A0*kdN_RobXaBbg z1r-El=&bWf%=9K^qm*YGx$TjD1S9~`b^{sm*979oATKvF{d*c=eJf07=*nj@DQ3Gc z+V+YEdP(hu>cg3sY#zf{)1_f*sn)fyhT zwnHzlRGY@iTFaI{q9?Y@51-lcy~^(%#?EsZXB% z$7#a({tB}x)Ep;s9X}xY^IOaPIPXDXY(-~C3I~BBg^d;Q=#lNHAK7*V?p7Wo@+Ua% zz|vZ4f6uVSJc2<(NcM3xj}7lzmks~&cnJUeZFmwM)>Ipr?y1Mr;bhB{)+J_Z;rR-K zWF0%U^B7&6XlsFSwSCnHnr4T0t&y!n-N2_XfS!%O0*VSWl&XMx&~Ubb8%RyCd{JWg z!eWljkn4JS0N!84oXVT{?b3janp^Mo$1Yr5fBp9F2_-vFop`oE3>U-azNeF7Z`@mi zuP+@tD}U+2Q9qYpL4EJ?!=;_xki7mI2zO9AzVgqD*S{>@^=zZYT;c8?2l3nGyQ{^U z*Y}a)BpQkUV_Q14INv9g$5XDpWXm-+|4#OC1e^Y_w=agq(q_2}Q>>U#ID_7&9i#Q~ ze>j7AIO7P|g-U239w}Lz#F-~`a&rKq?ZhOB1dDt?)yy~^9)#rqq67<61SBnWX|YBG zaS(Pvkol;-6VFE-IH?`=eR)(zSe?_BkT*}p@{0J zDd8_W+oHn^xecWq&0&ZbbAUkTP*A0ge-wg#c37dhTG;n!xMyQ()oT}Jo~ghMjCTrj z7vWk}CV566*Chls!W6D;+WDOjAxaZfjqs))&R^2R+D%)Y!69}%yh_vKQyw7qj?Y6M z${Hj(ajnq|H!(Pt5?G|uL2eP2D9K7cDH_HqwMol0pXmG%L{KKFO?-*&fs%B6e@1k7 zcL)2)ZxW7Sal`s;NTAV4ZSAU>b*cp%45`vIA))C)1V(2_&Xo-SPZlJ2y%h)6!J=2W zBXZ5UjpSkN)q+4f8L1&@6O|z#VXA}#04DBXJ|$_^^e!XDli!y+^$Em( zs6%{vwU!mL&_z77oIa|TdE^ZFouM)n)}%UfIP~PzZ3>WVnuoq8+okW`4Er7+?fSWp z;K;z4n+7G{eNFL|ZX@#5*a<@*SX}zL?k@jzt&Xu_tY0@g1h8FK7Ti_7CdD!iWr#S_ z8W@@1q9tje)8bFP*GIjqGGJ>E7(!Bi$p&H#l0z5&yprlfrImQOr)x^cJIB3_P(8?C zLI7s3MF%5jfixQ3IycIXlOZ5odrGkGUb4>n=ACyYsE!M|tsiy<_xcm!g?0L+c)naE z83gb2%;ELbUFMhV{lonfCCT0OuG*k@Ro ztUFIMy{*%nK-Dni0}`%!&yM}jm6@882&)gBmh2iUSEFWk7WC7nt-Mz^Nl_rL2_*hN znNsJ4M~x_6c>IxMRaavF9BDPQHw_IBu%E)IAJQ!Uqh9WF>xkS0Q2`!*v1M`NFPg{< z+b`U}OgHXY5!jJJt({e4Qr+m$v1%B2Ms&tb(?HWIS1$2AaOC6Xj?ct5UE*kXo<866 zKu^gJoERO zQNq{iy)r`A4NvVxG`l%pBW%&|p+RmZN$fx}2PRFkm}AO~Y0Ef&HV~NY8e`=W-}UVX z0tto|{Y)^wDyA}@LL|?}bsFIs0+p{eW%UueNcZ7Es0I?%7>*^gRV9rh#fYaW@neV# zJMpG?x=r0@)2UOE2_*wa6Sn6bxMLs>3!|tiG4Wq>9`(8hPcaTRGEz?K2O`GHV{_-m|WarD9D73v>l1RD{ZqODaRo*_yh4@W$`hbzHw0 z{II~H?cC4AIWix6pCH!X74o3GyDzlY2U)l;#3LH0L!R9Zgp(TP{PBeK3K7wzB}jPf zLK)#Pwe#&jKu`TU!e-Xr_o*mYI6TB2?Iy?RXh>+!htyWVugnbn1c@G z=IH@c2>TiYaz^i?|<~n)QBNgP9fM`hi4wXV`!nWamO&C?h z+Wp}zct9)~RyVlzwHQCJtN1k2N9?l6yX$J4J~|AnVXvA(ZmADrOe@wZk*g}Y;gUMB zZt=^_K;V~~Gu?(`;LcjTolap>QRgPf;+|$s`jRq;!ZZ@eSBS^osxHYN&Iz~g|2hR6 zI*g`Pb)drce{D6k_6o2W{p_iKJGx1fn^K#PXijK~D{T;Y#Fb zCGqGxx(PR≻!$nii0_=_%8=W`)4 zA6T=qu~G^W-UG^f1~XP&r^b}^fLk5z1EqbVTGxDXljaJ+anL4`sROVJI{Sj(*tC&1 z=@~Vc0^1O%Mqk&>0B15O!5M^7EF1IQfHYeE9Iu5nDS{rf@!jFw` zDss;|pD_Cl2U;B>mv;OKA7h&D%}`eS3wE#q&te3DE%to%%!+%}=l4>7F<@oce!I zO9KQH000080Og84O}F^`3E;8><%&K{x7@D^=)w=@iat#_us$g5J^%n_=m3}BdJGwt zesvTFf6aY+f7>>)=>Pr{ti3s;5}9_A)3fJztF)=>ZhV^BzP8idb7fbhB-&<8kqSxq z(Z_!FI}ZTFi;|q~{?65}btDoP3Oj1nrXLq+TefJ@hbGU)>Pdaa zRj>1MEbCrh44l2;d_h*ZD^JFiGc4a7a%Ms;aE^f?z9{SIPA(*$aviI&zm*R1L}pgW#wv zTEL6(yecPYtDet~7L-bT&7CKQ#AMGT(6UYHq4DnPM-Wf}I?M#ccLCQXr7D zEj-ykHcK~nEMi&jo26w- zJQC%*o2>@ACc{xuD`toy`!Izt+nFCh+;9-_m z^9g?SL#v@!!>GJFKR%-}L8iaoEf3x|wFqZw`s)i{6)1m{^qWHKd8}1rG>1}Kv3#S!ulHld| zI&I$5vuHFbl36+$L8&d6o~JOOvMQYcssYx<@x;b(Q0D;Ra#n2cp{dZ%@BFIQ7=TYQ5j0H~3et`CC@}R+P;} z{UR#_lw%jevbq@a%eP10IB#L}DkHK{R6vDba5s-cLoCQ=&z&we|H~_zH^EV zFKQ&lufIpV=P$PQ{?gz1^0R;Z^wpo9{rGQ#-@bTrF}%1$G69&4jcIyC1C@?uNp%YY z%Kwab+VpsqZ*FeVzb9BQNCGYsa2XQ8RoX170$xoslCVkjNb(ezl8VSG>BGDN*+asd zK%&Ig>fC2}E-MDN>0=#if0pyjez2L})SJ}OW`*Cb$_ivjvE8KAEGv>6Bzi&c8i3a} z5?oiw44Uo-r9`)mgSQfM(NH>t+5xdWzyaw~2IG_^6s!mp0BfKKaBvd9lufH77XbQ% zQ6j+s4|IV{2;5y#Wyv^CK`JdKHwdw;Y5w$LgU&c8VjQ4K1oMgMe<+3nKU+bXL0_wY z#6otJrQAsqK~;PPOw!Jtc$PGi8x5{1mqEjOhF}0nF7gJd&*JNHw ziQ@Zk7N^BD>g}~<(;UDfkyIh8sU!pTI(q~PK9JOk!bJgt35zz+6QBj}f#j z)CBXQ%d%0(#4AZlzp~Uc``TYI{=6e?{@uPS|ap>e`QQQ)rlppDzkI3v|5;ds< z0jQ-@G8hbkk8V5o8N-5o>%5^6w;_}rAgG^lGM^*glplNEe?se#jN7&uLw;~F=mNBR zI#{$ozM1)95^gTzr1%f=niv2vJy&p#mmJ>b= zn$k-|Fs#BTBV$=p0dlQt6yA|^QG%tH(C5sjLJWq5`utG_SdkShkJk) zEFJI!z7k=>ioV0&-~AH^Nah?cHwkCc`$@Dm$7X#}A1_h${x>My(GQo?^tQ3 zS=~@MpUho{+tP=oN@~GfG>hT;U0T)T;u{2uDwEzXf%u9=d#J6bnci@Gl|j4VB{1bn z!&u6KFM{1QtQc(xCajk%zO}XBW|!J<`G}GQe=h?6x-984ytG6{?TQL#*z0vgg{Q-_ zBnJz9X7|c>`)H6aS752uHps?gyFc|v)jK6MpYVoC#gD>P7^zTN6rLsOic zf0Pjv?pbs|(-%Z9{GZkJ0z@wgK)Jnu^Z&!?d+DU?2Q}EiH|YFH>&7N1l5?DaIZ-X9 zX-s<%<9WILYWLNjU-tRy>(6&Tk0tPFnbt*UgGuuH$junODf^ zE@Q!ffvfR#+Ki;=j^NA4ryj|VToLt;T7Pp`R&XsX=c)9cGu)tA%yV?dT>&i~kuhBJ z7p6J-(x!dFljdW*R`WPrT931sFJ?cSI@(gDCcgf0opGL;L)YfO56k)UYSG~Xf5Fch z=8o3jNFQqB_Y(6*evmw_7k@o6Y2;YpfWglakt3)kd3nud@18;=8Wp*sMQFI)^_GDC zgH#n1F~NXXFySm&@br)0Bwi2I&Q(PJe99EDdiv>O4{A5y2hB8382*;NG_Ku^ubRn1 z&z8mdX5$;S;C9B&_9p3VnueAke@8pI=Xd@26yBbx@MpKTFi%mby<; zi{)o4cuNKx%KRh;b40Eaw2v%yD*Lc(=jA<=lW&W~Y%GjB6Iv3F;|Xers)MlDu#Naw zl*QwWmh68FM8RmBPLc&s3e^q|IMh0@X`yu{Ri5z%s>de_1LDlA+Ou%tJ*VZHkN#OZ(AA0u`?r3E_iESAb%jFkZ4*z1LwIw|Y|1k)0>A2i@f;E7G;xD$_ zxf_?AdigEbB=JPN#nDyb@zoU(<>ys^hvOP!Qg#*A3m!E+(;Jf2k5He z9gAW6eu9Do<~#nIwW9x0r~_g}P|l(VK@D1%Y!VLmpT5RM^*~KvKR+^|2ijnOku(6s zy{`}XpsJ-K3`Ibdazsl#nu7gjTJ*McrD0q8M4k$&T(#<--#)m8S;r*grJ zie4L5m*cbG@9>nzfjXBb4Z4NMKR8W)s{5=6Nuoxf2mg@kuKd8X2KEEuXH{7cLF^&W z-VePkU2-KJS+~B~Z7yIAj!|4r23$5KFv5{p-`K6l>I@c89H>a{gsM4ev*;#QfHo;5)Q?xGON*2E-bUv$|Rmx&k>(wQdBX#6<3 zO&=qedl*RAiYkp4@I^n+LxeSEpzy;1{S#BLZqzdwP+Pj8P#_`}4Fz31pZbD9hVT-F z@RYvzI1GD(fzYVOm7sQDFmsyB+O8nSe+zXGIOD2Bo%zimcx`A^z@8$e5mYJU`hdZ- zyhT3&6ONY0=w56!MeVw|+Wyb5CmY^ikms#+@e^@ z)9YmNh|~d-kToAr%aNrBR*X#uiYf$T0Ct2$`JDkfFy|4oRFf>8y?{g@zaa%r&ypxr)Ca^;K9A z18GNKO^?tuM2O>v9{DV5p`QwEr>4p8bwdf{hPTLeRNPiyH90FH`BixRp2aVq zgrv98Za>)VwQ4?bE5DB>^L}73f2?3ysVd<6kSd@$5?ZvH%wzS=8D&@V62-6Ps_X_o zCbn)v;$sf2r;U9n(hL^s=z&fW1K#&pjT=a3e6r*n%^N=VVABhO(Nax{3SO3{Dq>I* zFbbh%{kE=uYAi!{m81fC)#5NrzZSP|(d!uPX_Po=e&w`<69JJi=YnsIzptQoN(PI6E#CfD3S(-&Lm02c;D&%= z^j!f3V*U7=V^C33kl$1qtBIWx9IjUBhVf3Oz;?_)(XDA|ijgUTmo9<}7k|40SfAB< zg4^`keWO)Jo8gyNd2;PhVvY_t$dlVj9|3WNm!a z9zu)7*I7~|U`P-r;)$$jR!M?3Q<5KiN-Lh-PVu`>s6A$BK851U4R~N8*WU6;sJNN| z8fnx_dn@sn+#nWHfyU&1%9q4~3m1QGgongR(2jvG%VJs&UVbhSgb6ngr4UJ>`pWVi zd_~#XDJx*F)r(FbfDiU+l7lScQ)N?BZ08`?9;0&nGt4W2IreS@(j;p}qX@+q=viPc zY7+_{#`p}a7Wk)~&*YSWg%+nGT7G;`3%PbQnw8T-LVAaq!AN_k|EP#5ONBgSNj&sCF2bYVl|!u!i=j zWmP|{})%Yp|l!zh#zgtu_AmQ@@CN94c=qiRR*e& z45|<=i+V8!lz0d0Ljj_`ZXVH}hPd4%=%u5TP!J1U`0U!q%Sn>+)Wv^S1uipC5I8yw z?xB1FcIN~gN%>>ITWIM_;-gV02u^XsfETVGaBxU7Lki*HF~n#)t8W4>PLUznh={{8 z?C}js-ttRf@^c_j64Wq%Z_F4?-!4$99!)?gX*A3Oj`Qv@Jxw<}M@{!&w+6$4YBOTff` z0JDL;X8>k~LI;2Pz>Zy5I4MAk;3`ldw;Ix!x(-mXjEoNSU~+|nh4sfJ%p$65R>k;4 z>(V!SP@ zf(4YF6d>B99j5SEWp@)Kl%wW*KC)?$oV1pUww<_M3q^-b2}Kq>w8h~OQLxf95%6rK{AEMR`pz7;5&{DrK#0XA&T98AOkE7=vFBf(IZhBnZv z$8D5Z$b1g4=uTi&MdQXlMw%EKp_kx>3m1PG*~PG&IOsdH*5#@d$zEUkVzAIzjTG=i zJzc4h%j!HUZWX#6Q7_a0nt~Ze_RO#nnuMaBQ;W{PTHGPqAOh>$lhrhePr?CJnJT?r zn8FUBC+aZLtwb>{PNaR97zjOSw^*|C| zK2$lAp@myZvNZqHm^v*cC6|bY3m<>mH3DFjrwB8UM2afm{n#2Fzo$fpAbd?WpirZ+ z{9=MOjOGq@0PQI<=wW+v@#7fJ4w{btbZus0|J^vl3=_JP#G&q!8`f5zmaqh=C{Gwo zQizGL+#C%LT6cn??HbdH*j)ywtgJ&Q`=VhHegs4eH`s1IIyM%3McsjC5TXGq*QZ*v;h}yJA z6aeHsCFK$ONeB*X`h4006Vw6$+~1n7?Lh?d^Z~kbF#3W^c~`UU!I2+bgl$qp0!kXB z9v+)`R&N5$o)id*H3vjKQd57fSVO_5zY!UF!N1X1d=fS!QcJ|CPfz_}F61zT*O4kk z#cCsrV9&b*S01nihWw)82asY&rV@ zMzdRN%3HtFT2#pDcB#)`96y2#l$nrp30Q(LFw1^P*+lQNQY(M(_JFNLOvRWwS-*sA zqtOyzJM@FE0iA6|$I@_xTz2?lrDnj|IA$}#QfwgWz`Qbn93#|8{|ugH$+hUMf8V%s z?stSn>fu#O8dJfNG8BK&N_?XdMTWztXf1Y`pbAX3V^ex zK6{;}ovx166W1^`)Fkkj0Az-AjHckPX*yn9N8u?VMFyL4-Qpfj00z5av(D5Qt5*th zW2h6@(s?V&$jDG<8h1z4yE9&R{#-;lPP90-T?bLAH8iQnmV18!`%@*dxz-&hjt}qS z;`0Xwr>wi_ApkvjU<{AkijgtBcLpkI?qpnmVko^6M@1-@eoA%)b4G*OiC$Z4wi(c& zcrwAHmqLKR@4tGqsYZdzP+)ge0CnP}J9KDDu3oI*vF~yYz5(jsH;;lTs7wWysuu#(Ai%It!h66Yw-QI(tdO4LEh8WMQB+HreiftOyrJOB-IqNb9J`vmR91Supfdi)_ zO@^VTt}TB-()kfIXL_Vj8XkzKY4K{P)e}vKua@ky*s%$JabKuC>?zul;o4583C<5w$ zV#`+T?C}W6_#t^Tha-I~H;PDQQI`ChXf?rwT zA_{SeJ+S3sO8{a!4V}K;yb-)nrSnSkzt^3+S%V≈0stv3`4`=)B=rDM_BbPLPh{ zYfC;F#(j-I2KMR4Hu40w@7+a03;(7PeVrkk4I8g|;wpryV5ITFfKlLIpyqdU*kBS_ zNBn@R77xnW2{Et;8uu!7Lh}B;7qT${}e2L$lFR2?{3`K3~ z%^N5m4Y1OeQ6FBkKLHB6Z;y-o

    5wvnX)Cx;gW-i7e(mL?%=xe+Ehv+6QNV(-7aE=uS!RD= zrzJ3jw*b;NN$pPP7UE}v;APjQ**}%Ot7yEmLvoqbsUnvTAS!*;C`xJZ54*fAYkqguKHQd(Xj zP7pT+L<}h%?WF)Yq8%yWOlS5~)^UGu$dNFuPY44a2%HLj=;M*tOa*Mj!G~G|WH3{K zdU2Pb{fO}KIkl=F^4hH(FGI&>7z;!~apX3`Fc$?%gq0i@!QZlCTHb?A3dP;J`jZ;c2WzSiSx4H2E-V2JBnYTO*{@c1!1jrqWJkw zKQV{=^pg|#*cHvMfL-W|FXUS}BbR_OwQq@uTCyE~h6Bzdv zL*EL8xnGcb0@~2yjObv}i6LLriW%g)Rba%QM-Q(=Bl#K@zw!`QHy|JR=|K#njB>TfGfa)^F}1R#AtFT$*)Ub zfSVZ>!Ei~D+HWg11U=^4`{^f8PJa4Hilk|U;q1UfBDaB(FX8s~b|}RQz(${wOjw6poO83ujdgY7MxTxy8#|_iVdQ_^(ruk3rqVlAnHr$4 z{eZf{W$Bon>?VS*JD%jeH79q_ zTd9o{$S^nP4iRAW$Vd-~VooURnDqFbBZ~DLrQug3pt+Xj1`^s3KS!qseUVDlS56vT zpqAVf_w7^ah?svq6j!yAW&1kLT&vZQRr`Vv*0NfH6EOCpY-*LWWpdM0X>irP(#VI(!i*_nY5;IqfDqG33$R$XHh&GFHF=-p`2 z^m^c@-MJ7ByxX-neKux8YbJn>~8Z0(Mt}nd zzM|ryDBl()3b)+}Tvlfr+1@~2_@#Q*Yh@T6ahHIS3mkvkn{gOHB+Rbt%AhkTh!`-S znhf3q96-<(>QUl9)y#~?S!OVf(|VH3Q>R81UW~(jVD`oB4}J>j59N*X&zrV8#bpa} zSa3!{F?6zjttxM-%|!2x$s>BR4zl+BO)vs|_5F2EN5-1Dpd(Z2Ls<7FeB6tMKq|7Z z5Q`KKQ__D4^XxVaHqYWtDDj5Z*FLpz9)34#MHZeW31pTRzKSoFd`s1H9i1 zf4r!BSh4q~u&1wTbaoHeMP@gQ=GOdt8(?rl);tEY6sF{qH5kx<@c4*gHfx@WZ2vqj zzr|;1d>zA!6Si{eZFG9DGhUS1!=rSwV7><}suO?n3FXBI!mF|jqL=Y*k9)nxL$F7> zm4gEv5u_x>rt(6mx=l(82AOwy9Q_WO@G#G}MMi0Cen&PfFZHdmb zFfMY~w!=^t1saw_ipseW3#zO4Leo;nc19T~i)8^C^CV9yJE6Y>>BK>(wp8kruILO& zQ5TfgDO>#$v9EmMTc^A!5b=J?16-QXF9v@yBcTKyco>*&FGNv-_gd0ElwfGoD)SMR zixyRGv$063VHn0+@=DQQM)%`N?*PVhEb!vm0wh$GvW;eDf!xwXv&ckGneT(Gm#_ch zzy2c*zRezZNXYUmwP1oRVR?dux2PKsYqE*phVLbfb#6yvMxaUkQtxgk{RyY+t>=Fn z1=+rxV5db9Jcf@4C}7BoX8RnpP}7}HcPTao!zXx_m@VcVOaNr_zZr4$q0I}5xB#Wt zl*MF4azYB9#iUurbesw)Se6|L8?YijL~<7{DRLdfBBz+FXVz#l7s=#CwRI4{V4gMw z61QPws8JFf*9@&cf<$R6@V^EAYL|aK$+DcA2FdlT7DR$^?gy#YhA}yvT-qZjjvha} z4Y%Ig*}1>J2O>Q)x%Wi)BDL-PXQvw8>q6NO@81DRC@ zGnFmCx~KJ}Rg1WyxSu!bz?J&fGpA?AB<`}}2zfeZnYPF)ecjs&F1`J%UeSM%7Ro2~ zh>-2-kBp1hM~{OU5z*>OTqK);@`28HAuF(kmHL%kmMQa8PClOYT)sGI&#a1yQ+-2X z8I+JJp}bk3`QWw$wT3A>Dd?89FRhJ|Qh6$QmvP|SM4nV5O>X?i``aRv29xn&i-^ko zO`7K7d8T!;}uUuAkAy-0Ig8|5CkiA<~|By!r@thmLjxh zEOvPG^B;PUqN3g!Fk0qEBurs-6EO=3EjFUBw~H#_xWjM-VnQu?}g zO&bEwj%ypK`jyB8r|O}q%#$F!qaE6|XkR$mJ!j6<_qS8JJX_V_G|~kFbA>29)=cB_ zN-J!YZGmzHtr4+ZJVh-&Lh~8}PH_7Gcb8!{EOS3lV<=$+ZNYzBahm3S?*)Im;fy;t z&*>3zE6h^*+Bi5RMOVWl&*_+PTY&;%<=(tS0^@8xRFQ$%`atR;m^&p8r9m0%ycs+h zQW;8CikfpYY(ZTv)1B*&6xpZ%*w&n&mDBV3qnsISL+hOQQ1$Zksxj&+o)to%gKaxF z^^|jp|8Fs?loo&gsv&kV0E9=Sh6S1c6>6shrf0M)23E>eFUe8w)S&6K@1!?h=7r%N zoP$R(yDp8)A?O|f?mijLy#HmwSh~_u>P3gRWWEaSiF$^Lz>>jau;)p24GQS<=ePIx zt)tf`Tou@i5pFL*(5^M(l#1dxtGSsL)34*Wj42gK1ipW+7y~@HD27O|hXWrjQ2i$r z9Jk73!Y%?Ay4TpaI9bgwLAasY^pW=KKCP9GcFZ9ark$n7XcJDJgtB?o=2rZ86%~~! zPF0RNnBa+OgKN9DR{nHBx6AXO(ulI3#B(Wt#LqeCDcxTzcdZw}b;UZ=H_eT;0jX{uP7;d%~}iw1=VFN{O>xOjgcboV&boB@l|R7^n}p7HiYLan8B zjrJ?uM%vtf7^B<4h!o5Fq9#yf@4PUnl`f`(`j=tPs-a*7LdiS;3?}DX=J12BZh%sR zk6S6l!-ZnNc+BHdx)<-6#YmLdx+j#7S|@+y8R|GWDv`Cz_^I)sxGl>2Lh8m`X{oBw zl+)6DQm38_j95%L227}YE*cA1VjO8O;F^4Z&bG8#D)|m}Z;>&^h0yDoup88yUV{jnR5^ikUwzY9K*x0u1WMfaVv2EMf z*c;onxp6k;+k5v`y;rYlYU-=5bGm!#%#WFKzW&18qVi1OQ2i!SGaD zrvx zq9KUMFpcYR>z8@Z6Myj=zr#rNloK7`p5z$2kjr0l;`%1TdI^@OBB1!+D{SiFQLyWZ zpZzXIXT#G2^DRh>hb8MO&U76VOQ}+3*-H3l(}^Qk)%pG6kVW3KOlllao4FM3vzBYT zHy;W(E3p#jHTvYd^_hj! z#WF-tBBP6fFAIgttHTM;JE%3WK|_%Iq9$~HZggR;hI*G{-}Rujw>JMGIzyJh^+^RG zgMQ0CEh5hgKTKwlrKkUO-C^g-K(csQwl*iVJKG)-*$~WX?Nz;e`yOetgPTohev6P~i0^GH;S0trTklQT8R*7S z)j)HweWBMcD7`R4lL>r%_G!5C`evNNd9Q83pWufvw1s~hMF-~&03kDNM6HzY^KKVD zFktz4nc2@M6Ljp6*Mk&wdEzG;@zNbOHF}ki)gFo(Fp9#q#BfFnt@LYE513)!4Oxn&LtwnC+xDF?#d<+^o@|NlFDd;9I~c*?Ez9eaEf1k+MuQMa#oW(|I2R2 zrcLKF)S>M*7)2QM6@9S^lvK*{2{I~TX9V#IJG+cUE8pO$$$bw4RB=Y1uByZI12Qse zI=;vtR@z-rsNJ{DeiP-8wZ`| z;4%bC&{`e{ z?@qqTjSap>rbJ~LbDbu*B21%?){7}F`zCDj>dnvtV>~PIQ7_i<$8IawEoSl(&*jPt zF_a-I4FX(UnXPD>yinQhpl@O&I1;j&ySL(3*4`0$0|x#3yg1aDbWy}HNYh#p1DMx* zZ+`?no^4i;r*}US>!Nc7P+cdxhJ!U#h30&?UoKCc93+e^ifC8r+@-#*3@#iZKV2MN z)^wZ!y;nuzKctgAZp}$Z8oQZQXLi#$uzE0%dEqEeUW|o~@aGPc_YZ2lQjbPEOWZq- zB594OkmD*YnOH~zH&#G(FA=ypa*WWve;AXDJ;_iY^TM`LEX6y>1+^Yy@#Ekm;o^?K zy`kgE1kHLnWDrF1gV>E0Sk1y`ZgG-WW>O6TMFliAuJ?mQPNzW%-$xk7Y&c5ff9?F% zuJGYCI9-QauIvNhUc%{~*-dg*Ad>fWJZLjSri^MvV^nLL`g$S8Q{#%5T)%3(6n_)5 zj-oQ%7oiCSU1pXX!?}a4|C*%B7k;l=;5)q;ETS9A;u&a>vSqVBtH$+oE7MRjDetZb zz~P0t2ObOat*l!=-2KQFQqlmnW_KEv=XX}wRo$*qJbB{is`#QyJpP~$<+CJ?ys$F;RCs$ZfmDAYoMKH9p^t3%t})PGikB+er(4beO4cZEY2Prpz`^o(3f3+gH#h zAni7|drx<7d%HowgLJi(=%lG)d*@^WiDn=9fqz=g8j_{SaQ(oqWYHyyw=nkxRnNFr zEm(46K7Rlw?cfXEF5i#m^6Zdj5GEefZ-0tfuWv9}TKFdf_F%Z&hd8_m;2D@yarjLv zUp6A$(J?2Q-}~(D@vT{}rQG#J}l^u z=sdd%#Y+VOu+i3f^6BMy^S1X4I6Q?Czxl0#J$+oCzqTCD9IW=X>AesCov;7(*VB7T zq(S+iV7V&B>X#k)%Pv$un`k&!I!xkN*V-~!IDt}`UxCNdQedCjQ<ODL=XxIf-?Dj()$iZRKB`-s-0xcGaT;QLI#1%jV)_gvE*wc*K**rx7`cYvQ9MFvJ z%8{pLRQshq<hWWAPd1u} zZiuscy3N{YmTD!-Hb^DFGxG%`QGjklZAgF}bG|y@v`4qtd_QLxs9*#Zv65$`t7d;X z?imS_GM!+}QKAgCa33Ea{U+MJmp0JV9HexPqwm`fcbrhg2GyfG;m=55UdhswM2V>h-)x++DuC9h?&q=SyslFH2?ro}QV5 zK4ovGwQ+K1l8Wd;{*&gMQ-3Y&`2!v=U|mC)Yj0_&qp`0l+Lgtsa*=NVhd(QY-35DZ zEHrNwFanKW(WC~ZhkoAcl8;f~$|+Ah$wzcX*^H_VbWhMpdK~ zCW3?{FD2tzxgGI(bncXrZ&#l6(}*gws(M`_^^WMz7B*rSv2%PBhJ9-rgquTfwWu`4kWo(9j3A&Mg9V8oYhjTPsfkQR8AB??=#;lgwY)FSGXa zYZ^PiZ(=t2tb5%P-1usb6KukEd{n2Mm!Ub^+{2+*L@v&0t@QEAUUcxqh|;)nloP>8 zMIG&Ii8Or?rn*guzr1@L=cjyI@-)YwY5$h=ABlN-kLv?Od2XsWaj!W1DUmZSjkCgH zg?Px|mnkXa8>CmxTL&SxKTWLfOy?M2@LXqraE-sZa?}*1{M%V`VHv0`6a&5Mcu#oq zKNre6V&^j<5bWuq1Kyy7dJr40ATN)@Jv!DK3nvS<_djt^`R`(C;EenA-gg7LrJCp{q(NlhIl^^|0QC zYI`tsQb|d5D1#>jol1=_gU94zn;YC4rVqdG!W0(#ZeE=oj4-hvs_E#*?W+JbFD+H9 z#JFIKi8T?6ff_IWJO!)ysw`Wqma3P!S@w57`Q@k0;K_p17p<;AAkdkYW$d`Sc9z@b z2d?=`E7egTs8kJz($*@q8$!VyX|LQF9=nWRF2;K3;KQ?AJ0pl+u3Twn;rlgB9~TT- z2y8K=SbALa%hl&c#_hHW7&(6^OCT6alBF+dx;5za=JVr~SrP0pfHurSLe^ncGqdfhawqr(cnvI;HB_Pc+o&*jDPgYGMXcPZ(qu59w7p+ zJ`l0de$?(*iik|o`U;(%e%Q$Rw;{7MKo+hi#0eCr2m}OVGE`vl6E@2%>W`22$$dOt zZ9C-VoJaa7+O8%10!h|{i-m)-A6VF`lyQo%42BZEs~~<0J<*Zj=RG(BJ|Q;_gdf0{TxS`rg`+)toLf+J=xdKzmCWA$j$Ere9p&Cvxu9 zN2+e$O&DED0W5mD%xHZZg!7XX3Z;Gq!UPwFm|fSrh3GC2s@;kr zwivx8n^%7J%}pB*Vgix(^DJj1rVJ9gGWEqwF65(dnm3*vOjVgU5qCNjzGQKt8LB^B z)}pZ+YF{AynFC5yKR%hE?0cBxQhjrzm=}>~s!nWREYw+DJL`*xDcZg!Q11|(9Rpy^ zSEA~N-mLf0r)^*NM_vkyimg1~%)cure?@G6vkQNg7JKW23W#MKp%a3>osMwn(9pEPQ>0WI>6Py`ylccdP}3k( zwQj)7efRH{pq@ql4OBH^lvDLvWmvFJ>|_;6> zUTR}<6`d(xdjvzYlm`Stj|oHa-#;9nVAVefr=?kHwD>!EctEi9X9u|{1$7z9uwf{q zZ{Nq=U`+3KgjaP6w=2E~XR=KnW?MAJRkM~p%kmB7h53xN0aK7|9cHZ(K7}%&poyPD zr2^MBl%FB>or$z_T(nyV=kq-LP~6r{?N|v9%{Wz+VPi)f&K=IEu?Nboj4Oos+Z7)4 z5T?1`6ZtzErvRm5&PN|#YClmtjv`*~eTZ#*4I_)Q1}WinUpL`=q_WhXIaYq7t=yp{ z1C(lP2PIvlz*t+4VxTP{{9bFG+He5Q4ol$yR@zzf8A9A+ip@Fgrc<;*BhPh9M7>Z= z7C239`vT7NlgZ8X7LhY=J=t&;P{nto+uoVVRD8P?0jXzESJ9Kn_zj5&KS zHPYbXyXWjF@l-V;+IJ_xXb!4Om@~lhyG8bfwewQw~4cSK*}j;(;WlK5Vze zkb^=tK<}X-A0qo^aS}H;LT@c4cOE4s&R{D@Db^uVk4kHyIZ`g@R_YQsgTi_JmJXV_ zGuMZ+rGNXupNQ*MWAe)DiyGKCF_suhy+L%BGg(`9+}0{)D=&^7xq!Y(Mb$rjRp;*& zi+a%n$^W3~`s!56v7@*Z#Z(KyE+@lCv4P49lW8d^Tn2aAh03-ZBk(B9j_4U@y(^;W@ zO5`BDXqm08XgYA1l#0#1+w#?=<;?>go+b_pMrX8a{cg5Y$x_7BGVmuMS*$qBS&%KY zNVmN7ei79(g?{qf*IOTgXMyRA5EC4e8V#gNSRZw|K&f$BHfr8Dx_F z9OU1$L+B_NvCs-I>V%W@n(XPM>qK}Jykl?|`T4(zS_n(eft*3{&cxs8p0x|Z0cv@a z+47?)H@x*~i(~R+I=`<9@wE@%(<;&8&MS_e5L(~*p zWh@+0>r!ju{fU8?AC^P&yKq&ZgK7tE(8d$%7O{DU6)gTGsWt*|$hAvaok2_2WBF(WqGSSd{6n-U`& z>z>4Z>w{x)s-2!2r4V+o4f^z;aPbf0&3c0;Cbf4a&Nv*2TgnJ(H=2ku^@)M5V&NPJ zYG~@-eMs>&0SFv4IoHBFcz7A@W!$1#LU{`O>Bf~hCn3JcPXKzFPuAl6=n0zhIxu}-nWwF|+Jsf9r+fva{qhe*)(@nP~5w>!uw&@-N~ zizcJCLXEUwL?*>kT@^$yAV179UbO%S!#*@50n!GFpDx2+Ld;5vU!Z)^)#@=`yp`1} z>9mqaKgQ+4&9WF&>1C8sZi>UMQ!R5CTqY}9JGCj$?=e5hVspnB)N-*`4=D|Gd?#Hb zZmVR!9)EW&*2lne@)Yw`+U9JRr%Y*E4Q7S~4(&rL#+6*iBhX4nBE+|xaYz7{KPP`w z54aiY&pC8N_VqWRCg%9t2s{C~TWk>LgGrel{2hCUNxzx`>%{$WQ_ztV7LZidJ#Aqg z`EfdZh5>~2BHY?_od~+2+lq7gXWxS^UN7&bx9ba|yS=Bw*|UBP3G%B_;@B8{@oHiU z8qpXqbVGyf1C~!AJ#vaKI9>oIslLQkL&IY!85CJjtRSW&^)+jbe)w#UjiAb#8P=f~ z6iDUdNC$?RC^I?15ljh9j@TZ1vu=zfr@0hs(q;m;hJbfA=D0_^4{F2XTmOi6YDy&m zuy7Rj?2)lft2X^i0)+&;jULzUv4e%t-JG!^;egnQ*}1?3UA4NEy(D_@W}Ux+;n zgrvOjKSCRWqJS!=G4EL;6~Y;%fP$VCwZpwB+{ktEbt>RP^Iw7Zr8A)c8Z@x?6&SBE z+a=fQJMXhrE)SQGzks<$!a0|@;S(w*ux%lkjLG^jVzS%0s#|N2SAC1pD)l$-!>+l< z%h?fG)7&e;Zk(()NH}y6uI|U4G9Le}KMF%ERbYYr^A>`ASDb|fKWQMK`s+}x&FH{@ z^ZqD_?i;Ek2avh>eSM#-t^l+s2!@DroDc1JfywagSfepmXaE6C=JdfO9(8hPCaoep z%^S69_&{9rh60uX#mC7OTqxTlJ3hc4UN300r0|M5^W=GU-d*qsN*0kT>W^+wLr<=- zyBpZ!{LMOXVdAe&UZ3aN$p*i)aXlju?Cq|veh){_N-l11%j7^<&}R|y-57`-%*wm+ z^kct*Rsxi&BVaiZ5Ude?5&Z1NqUgiHEARs@I8P4b$wKj|TM*{s&q3_z?dzZ1VQl1( zKvuslsb8Ng-u@1k$k3o&8922epQD4flaItp$UCmrqzB0TuV{S~y}1Xetv$@TFfu+c z%Nmi}hlt9NgZYqztA1o-&*Za-qS1E6xcdHBHkiUIll<%WH(TA*v{YVLM5Rzd;U z;B&^>Mfr(%?A6;K`|~aTDNcVQG+bFMx4+r-ZBA|f*#9?#LGI_<{a|42=g01Ouj5m` z4@%Hu=r4AXthd99SO@)Y_u;=DF>9%Q-RvtY)!O8)_^F2!kA!FY?X&BtX^H-Tx@5d@ zVvFpu-3G>^C{LO4G}r?PNQHWa4BNxT=e!}=h-{06IiD#?7H2fqdu|fwB7P_{91Rup z){>q_(scLgLsoxt23|wo`Cw>on?kUs%^|E0c0*$DcSpdrARrWXYRnwKk1K{Cd#cVF zGZ8d+#)1MsTP}r2Q+h7(eOcD3=}ArOT*)RH_<@;47sj2{t^1LVn}h{_Lw2yVDVsOF zN9SLZKX+c11al1x7B+LJPZ_k$8x}?GeY>?8aDbI;a17EYBO#LtA%)Cf8jVP4q(<=o zs$z8>+v3q*Ps8n%kqnn7)(W47k%x5I0#!0ul^NIqdYt$@@4tv|#IpQnyk(t;q#S$7 z=K+s;lrjv`%QLOwHuGMg*zrv>lB~Em)^(wBQ@jNgb%lDONO(ycF&H6?JhCrTu*6OM zbT~#zM|r$I{jV)o28Kn-MvR+}mXzuSR4$+^b$r~ZQouv=O9aETEV2hq=&os==}e(v0;YzH#FJ78jvLDS)!Yp~n5-@M|4YkJK8-4gk>J zdYQg?bdm;xH_M-u`t)B-OBr|70T84=C>k+_F1Y~u5{)~PEc=XK0STh?XCUr0aSlX!CXD(T0*BAGS@p_HPeY_X{t`{Sq-?@%Exl*7seZj12MNtMwACQI)4^ zd2}r)ll5K7itr#pY^QDqvBtTMryic>ad<3dszs*g0jS;+dvck_LHP>c`9BaqP-3&I|J9{ zP46>X(8g9avFmT8WB;z#sWrmbTCawyO?pe66W}acG^7K# zXcCi*pr-slJYXhlu#%5=b}NJaMR(|?yu)0=HQ3ZjaI%7(zqQWWKHez{Chu0>gAijg z5Udwi@s`R)fa`=q-b{;}dHz}zWxPX0opC8DU ziF}WxHUEZn=E_X@}=~EQH&q3Qx+&2sJo&DCMj1Yq2 zEBGUA=0V{2y5{wlHIA#sGIbEg!%+<h?HGO7I+pp z*orQrsP|S{)lWs8fQ8^?$Tj~uh7M*$Te^`H#CE6`JA{g2O47*(;cA-KV8H>`TQhs| zBrzkq*wjeyXtf9CULdt?5^kAGafQkGGVxj<<;XUXw%G+vw1_l7qmrQAJEur34j~*R zOnr$9n=yT?;#q>WgD)(+@%j(aalriSPNjQv_8?=%Mms2enGQ2m56cS=9mI-g$7aP! z>vB*Alr#IXA7zQ9m@A1w@kMrY3FheWIDb%aA{1kos7PX42jE-rRieVs36aX#9e?RM z`79KIedY;iNuVjAt!iZx+=r@;yGDl+0@iLTcOYcJg)5Apahz%}Uv*`XAu{-Ce^6TT z&;T~5k<;)S%De}pn02Z~TV&J;b7DQk@HtqLX@GQ1Bf$>mU<2#{tL@J}B~pVwle9eF zjq7^=DC`bQU*M&&Cd22#El6r$Wt3ItfY!HzW{{&cW7E}s z^pMeHlk;**SdyiTHj0z3c7Q^jnG(~;&P1`yc~RY|+(`*nh0d-_^G6lqI7%16L()id zYdTGiMuFl*Av(fimT#GBFXYtje)pu=V<$RJD2@Hh5Ks?Fy6Y5t14Y72#*k2g-Y9U$ zVyVP|{V||{<%%ZNy6YHUJ*&BR1X(XMkc=QJN&k+NIfjM8=q)-vNutEGdu|*Dl9hBI zc&!KR~p52r$EV$~k>rcP)r)MeAi9+1gdWFUli@yI_QC)+3x^^WCPXC?!T?E@k zid!@2f$9Vym~F%ozmWXiXUy)SZZ8jgcjdgp7T^(=gc5$(8#Ge~snnx;jVctF)M-nd zxbP1!h^U7n8003R)y0ft%ZaqS-9(Syqr!9yH_|k0l|?f3+5snsXor1k&7zXh;aPmg zZF;)LBiAhe`;9&3Fk~QoFAOzg7#c;J6g&e70|R%kOjYnzMMEQKw~VijFP6!> z_%e7e@{w2#{sf$e+tGfH)OmwZ|cAB<1iZDjk;5wjvE0b|y2Jwbn z)gQ#UPTOax-r_K&7$6>14ZAb$yA2F{7L*caLsp8iww;$fXMi9Y>A|M7M7gS?1o0U= zh@^cMlJY@6kkd$!!{H{gw-rSRaZ<*(*ZQFvt^Rp;vYI)6oXRDENXRxrLS2t5W?(qU zwYjcmxEZeGaMGqivym)%y_?3dBc8ZumKq{~NC~9O<(ogB zX6Qus+m2zbD2@>cVXQl`${oShxvYX{YiLly2i?c6*hU*5b3?8E=^1teEAyW~-S4{IcjV^qtvabn zMnV29f(Y%7OG=_!=j@`$DM|sw8f!!y-uM_>ILDL~T!ejnefoX)Y7RZ@yG_^E$95UD zpKD90@{)*rz?A2Y=$vgOUuvFp#qHfn73XcKNq1*~tr%ca@(RNEc-V{)cg-8xe)hqltO$_E8V{@=dQ(QAv0_7#gW);1f2!uXC-Ba}=uyO*`EL;@Isu8$o)%nV0E@iFVD>C=7H z&~KBbgR9no$x>gbEzR)JrNW7J-wFES2HFLs7%zMJ43(-QjYt6)X@N=2g;#}N9|@i2 zsfUmaTowd{uX8ha#+z4;S9-m(!68Q}YXkMkV^hx}x~0}Fh)J9fIA8sIA0Dm`#|u^7 zoF4XfPf@#4pguVFI$9bt_OjO3!kgNClCDNw+@j2s~E6F;bD7_7WZbOkiZ>Hb-`r^G!qb4orB-jS@*M`cny>2kP%$%OFV&(|GjJS-z%yN z?uK9+&Wwj^2ZtL1E=m!EoWaXMxRN+tNL(N;BnogS3J|#zWRd@Nnsh87;dP>X3~p>P zo4bj6=gjDD`CtpyZwIR(M>*$ch@egLqeB?^>%L8{@yw$jFLIq92UwHJiIW@=v7k8` zZcRX9G=h~$goG)*L_e`$LD<_(p`BWV*r_o(CVdh`_{q2DuA^kppV#cnkj-@0GJ%B^ zHD7?S^5r^a=Yf}-iNufa>ifptc6-lIoVx0V z-5L@W_U1lT(U=-dz6E){tzpde1{+mK;g0gicjq6YV3of$pqYB3p5SXKputXjXKFa> zy}l4|=q&ZyO4@z(3}1!$UDv-JB4mfWHK+n?SJ2z_W4mozV<&&7iVd+=4i_HD7B(8= z8Xmq3L_2l$WJyABhDXxxol|`+sz=8ptly4GQq?tKKVbYP8Ib{8o(6OE4}3*f(ZEE~ z1K^^;h3$R-!K(nqc24VDbd=QvwIxEh;mIrSNp?PJ+E!R z%zf<}zf`4Qj$<^|4PAC$R6-Rca$;{|x;l3awR3f6(jj6%(g7C*iYA{rWeUNVt(t7` z2G^k`!C>opy(Ycn;@=(pvNsVCoGRTNjHmccZNekW8PEfH$)*kHzy0D$>SU$ievmtLE`De5@xfBQXW@-* zS{arQ@I5Faz`8;2!L-tX3~x~w|3Wc3-U2$2Tb$XZ zUw0PfwPW#%9@+?VCX3HO(JAd&27C2~B7(m@vbcPr(8UEgBd!Z>=*`c4fDGfw*NN<) zmFj9&y*oJV`c%(I3U`$7cMp8lW=(OVAAlw>W^iN-bIx@(l-J-IU2ZQbhB2vRxJHr0 zionuI)(y%baCzCWv63lGBU2CY)Hn5r;qpTCn$8cSMJB)cYVthL*S)CdfN1&ZW~oT7 z@@IW7<(x8@$do2BH#j5%xZ}meO+UvBz9+b7rB_K%CWF&JJp<`A{i>(zAEN@#Tq8n9pf zk(uC2{@uKB-0NE=K5mES?t8y~-w01o7Vli*2SE+u52`Eo?R?Ts0$mK&^&>tFjP-ec zqEepoj&FskkyPEuk_jzs9v9|y$w2CVB_PBsu{U+4ww5W*bczZN(os(c84Pb|OkHrt zCW^Ja51i$2X(=IzHs+Gs3y*e2{7HzSX%rH6w(2;{jNNc9mgBw7ZEq(x|6q*Sxdk7| zr?7)A8{RVelU53)01V++@Lt;8?EBeAAzPa=1y(LBw8vg59U7!dRZh9UKs-&%ESMo> zx!+ZDoX@aX*dceX3Z6@rBknvo%!I=8P$>42qgakkZ zB8<*OA2PAV`-0F=7yQ`F7c9_PFaEJVFBj{bb4LPy$oO4>6tFCX^aPm|k9Vm1iK3E% zN0p@I&hZjw+S z1Gi)_emqBWbmBnP9#qb~3_Re8V`4a~Es~9oLv}_FEeUa_=MQl(GN1g@_4QV739W?1 z;4>HT#P*VjF@Qm9%b|qiP>D9b?}mc%RmYto(mAYi{b2jD5JPXmr_A2K{}~5;zK)%X znEnkt%_^M{VoicsW3<^9C)efyNsL$bnn+|_jIJQbhQD*Oi1bT|GqE1otiU1;UXH~& zv^COGiT&%_3mFAv$9a8WTTVh~7qhQDmyv#$Cz$nx9H3cqbZrGKru5Z6BGa+kGC0uo zst^1mFiIpI#SMyu?-#7vQ1_*FOQJ@nW8q6Sw z1FUo?`?fGx+a}xg?CA23pNpr&{jU7uBj3LwY|c&Ms~bZiz-Ow$6Y z-`_2Tkb%YVoMu3c?)B>L$$&tluDt}2+}>~M)a)6`^a|s6Mp;y@N}j9jkJ)HC!?Ab6 zIGe}7Jf?L*unnxpzi4VFz-x_8H-ilWnDgy9V?8)MSFl=Fu#TcqdgBbyZt*l#WI zJyQ^&u?X+I0yzf>z7N6n+gEbB_>7k^7CwHkHRb5OPekRt7f5F@BM!kKbde=UHs|xP zS-aZ8TeC|!64W6AF%oX>5;+D1qQnFxG?mgC8){klaAP?A&sueP9ihgv#C5xLWrgg# zuYlX--wpbspYWAM!>fB{GnSr^a2pJLrdAx~0Z~ORFOQ4hm84fC11YH1@MEioD?G{d zg}iUEBEiyT3N#XU!W7dl*e#rYT#(eL-DoeYZ0$a?Q$f;VF~CLbFp|HqMXT081kzQA zK*@8<_BM7Qob%EOxsCYwcuQ(BREofueFNB#cElU`Y-cEhM{P2+teLP^DfF++a9$`c zXI$Qc{zTDNw$MUa=Y^*3>98|*k0#&_C-sHoc*XWlznW^t1t56G5`Xo&omtvD{TdIY zQdheR6GDDV_R0~$`o4qQG9UDvwg35}CAx>jwFOEK2~Dvc?7f2mO*|}mNIT|TFcmPW ziLpIt<|KH3zL>R<_3<_jIoT%rk}V%#bnvy+tf)ZcS6kDpb18$FI;Xpg&3F6^ib=<> zi$@hs%SKost^Fd(-(u-RTFF&>D%(byzT#jRDD|Uw3jobYI)N9c0(o#_&>kKWRXfeq zyR^KgAjRkkZW*r^PE%2vIv1p4Iv#*+DRav#;I}}~BwHRHZ5!W|H!a3rZJMOhQn6B* zgDyU!8I~%4Q^w-X-hxbANVzHAWaH}Ut5zmxXv^paQZ~*%W7cxQ=i_$`|BOtlmfmOb zi#A|mLr)L(QbiZpZ!;hMiyLCu_Hy7wrh--r@fi!ZmOP^UfnA}VkEyY@>u(@bD!pX9 zrr}FlUb1E#`JlG4xDUDpo7P zQ-I(?CtJt3;NvOAcVDHDgcjUn$-i@SNJgl4*<$RaU4m{ghd1pk`mB(M{mH*3xJ4m% znXp9sz>_rRmpZTCaCa4&`4!Nqpp$+<6PNr3jYWswX{Kdt%<;fv2!>hpcXAJIq&TVl z>WgTSShoEmU(eOKnn0)yFXSZi{$2)k6k1_r#;;aEyo=kHmRGcMONi})2=?WiTRG(fXFg^M02IdH_s zuG)^!xgu(Kp8Q9s^LGVP!H~4j8h@;QsK=x{V;B!}pH}hx+6$vbB9vv6JG3?{o8P%4 zwU@{trr_nOts+z5c>7+d0JN?pzUKLj{0;}?hS`G|^TGMq>Vb^#2c~KYko)@b*j5Yl zwbcq-U1T0R+|6ng0G~k@MxV8@BAZ7~LsJr5mmanzspR;Z?Mr$w)h-^8IMnu+mN zoeU3RLd7mIE?ZQJZZ?s_HjW%e9K2WtJZXXkG`jcWzx11N0^c00d$k4Z``MlkQi{;7 zU|_6PBv+DD`Pnh_`J<)2zL@^5-j|cKQU5}Pd}d{+js=@e<3CUR9W0c#fRgDq#L;Wf z7lX*?Y<6L)MI3hMgc`zjGGu9I1k_`~^rTf|HP$o3evnj7$eaRJ-VZQ>!ifeK@zjOU zJIWPZGM5h+Y2aQIyvB^>i(?cR1BBQ&$xkixK)PtLQzb+E;sTuA*%9q_44X{~gXAEm zYOi1oCXlW$-d47Qb1afIT{Cv+DWyuVxyztvk@q6YN3mms@Y7Zc^&Nhi&($zvCMSS&GSlT!jLITvg( z9j1*l)hbA#yr3h&vB!ke))K6?(obb|iqsSF3Y$EG@$4^!!XqicQ0{Nih?U~IVGV0> zuqE;CqEiUqMk4gz|Csw(lBp%1N+*z_r^w94i0)X1mwPqBubPWDUDKeiH2o0e;iA7z za45oRNCdk575F|W+=?d=&amV^?)sme?jyO9nxr`Q!B*krkwh^qk82x;tFH`t;h;_L z)grXMVI8?p(sh8QG@?$k*L-(Kw$0N+9j<|nbSN|Z332l~GOepc$I-TVE8sUx>6`nO zNtjCn&nKU#^e&};yfPy3;wZ!FJm3QFLNA_-KwjR^fJ;L&osQ=n#iJ65AS zhFH%~^01JQx2o@JawL0Obnf3Kiin~ND#?5FhS@0&Tz}ppa`F2n9WF9b4_L9x-{g`}w=%>m@OKd1V8})4d6~;qbVyq#ZAAzGKi*e=(#^ zOh^D)SP)i&CX%Y#Srbr@pAQLJ!%yl4y=2HW2|##o^|ANh&`v#=|?sr0iPMaVeFSc;c_M zuNlF#3zM;n;3Rcn6zOw}=mb@$8rPE?PQ_`pdMw50T_-1n)tnFW1jZGG#DYWBQgF?! zG1!JHIz98SrgcDyk}2yU3Uu~_|59!vIHK~N(XiyuZwM=Wr}?rbSz5L2e?4GUuFZ6{H^v2ZnPN>%NW zT}+Lea9k}SRN#fO@znOLZJM$*0ubH@$h!_)XAv7WNr3+GSHHzWTZ%A1Q>;sRreAC=qmpHLAB;}pQ;$<{8| zvx*^v>zweV^Gxc{R$=_xa3__zg^-$5RPm6rJff2A$o?Lc@?ltf)Ql#c z5p#l>yqmJ0L+*0_cN?@xC)lQllC zQiv(iOTBQ4WBz$8aZ3_$lahcO6Ab#e)#C3+T}ROqE`tF~5)&zC1B>rJ1Q+*D^CUih&j&bxKzzI9q*2 z`R)mmW-U=%h&Eio!g#;j}|9>z;B;3a1jIreEr<*IOzbW`TE|Qky$_> zgjyiOAzS{oM2WL((Axl`@Y$pLBJDxK*VrVDt~>I*q3a&AeZb@6m!M<1N0@h<1LzAy zuUnmxr=RA#L`7vJ4y<&kvdUh&DBkwt2rBh{`UuW?8}6U_`H3DQraaP^St`+A7oN5C z^~y&(v@G4WYGp9qjPayEs?cowrL4wE+;RiCOc|?|VC zjwP&6G@M6AOX}cMUvpHJ$ug5|$3XS~5;5M*sFNxHarQ~d{VQ&Idfk~0kLvmorVpPx zZpXMS>c^g$lADL}4~DDVY*ezFSzDn!h&rPs;fb=gC%d7mWBgB`1*Z+N#biP^_aIzZ z^*7Z-ui^FiWMyK1%dmn0k(dKAz`aji+^qVeZ>-?itA{L#Fqn1|<>d!YI7T*@Os0&f zFq|l>!zTIWf&aF1KBLdc<3gJh@@3(HPLwWZUEmu}`wU&}J zDKZAb)U|Ad!BaMrnFjmVO)t?c*OOoJYy2Nyv~l?2o`L_LOtof!2n7o9UtZOLAtEB! zKX`A97)J1qVif=&^8L@+6M)D_{BOWb9%7Le#L0i?Sm`f_0N6iB@Q!GR@elf=B4rW( zgCwj-uLS=fu{@GA)IVsaiWDRH4}NALNsIo2a=S?PDF212;!Y!cXmCL54{Er2Lz< zpg#swOC=4m{QsuE(;;U-{&Skig3N>b53UFz6TKS*MTybbl= zP^64&BG}L%ARL7MPbm37444)U3uK!ArEX}C%>BQBS&qnz{|h+jid^@Mgafs z8mGns$X5SW`vX9h`=3!E5V;@eKd;NQ?qCH5{9jrfQz}UiGBJQ>@An662`Ys{BOfLSWD~Ks|PzuUQtylp3lvsj=tfLvFl~)f+R=n@& zQ%EF`kSc9xjRa`63~^Q%3Mr)3;RT1H@^QVEw03Zqr8-AwU<;vfw7rl=9Zy`bBK*bT zj%F z8-hu5OQ$8_Yo!@bx^XL>`Vtn9?d+JM>x;@tZ0w|xM&MCt3LDuMwqX6DATuROR*XAlu$@%O5YiFeWtf{9bj-3nYBb~~8B7FZJ@Glz*pc@Rb~u=$TL00+DYNJi zR+F@3Wg7M{3KygUjfc`x7~Q3GC4A+_Gsl=y55OvPTPjj)zVud~I_Iy#K?B|^S!2R= z``KCRZy|O&GW(c@m=GNlo|sc=;o&6(YV26*O`PjTm>aF&_r8fAP-x4Nn}0{D+8UQn zLN!Wf@HhZ2G*cg9^d;mYrX*212JX#@7Kh#s!c$KVHn)XK%jm5M;j-x~6YbLh6w`|Obu-B7rqOvRng(=hIL7hkj=t%-T14MtwY9ay&hP-A?j&Rj~B{Ee=M zX;j-DD8_kSeVwXZ7Wpt7GtdZ4d!d-ue>~$61>%UYY}|WT|ZzDSt>K#F#y-$?DeD?)&3!jN?kE=DWDZ4i0cJ> z>Ch2vxNefxGR>X6OwFD!D_58*}P`3?AfR((1d52tFgU3fwg%d0i?@b!PWdUOdxn5=!>6@4%Z=zW!!gVJ{ zxR;8YmceF!jE>D~+Eoy!h|9W8l6(!QBHGD1sXq&OGr*n5x&@6xjrGvJg*TQgzcx|C zpz@_(GAf2gOw`J8vqnv|s&87?*L|587M`x$Xn13uL_U&?@yBwKe2HtQs+PS9n!0*w zjYZza)K+2tHLQH4j#Q0IuTJXAD{H$6eUgTQDqI4kGKz8ygW7id?N3E2t7 zb7SJ;I{^e*8*_C7IQnRyU)SRAUy!cZ$4Z$yhu$0?srKW|k6g1Z{UPJnrT^GteK$BW z@LDVdV?}tf$ceQ$5{2N`uhs=%UEXBoF+u3S5XvQcTg9%Hw5PJESYgLDYQxemls>tV zc|?->2S*D|ZaJ^)I0NL2@%S}OOLRLI37z!$`pGKc&eVsjnuDH?4<2#In+7HX#9CCf zf}RSH%}pvY-tlmDHl`Iesg*Qpwz(L*iRwGy?5+EXcQ>+nbt{)r#tc0H8enE&`<-Sp zr@Y6BX}G71Nz@89FMY0dUfnE~3eoce-&$0xPfVX}HNUp{UX(dXZSx6LGq~o(lyL5h zaJ!kE46PLos*)$&C_jvuJJK%^N8K_O~=;ak=9hmBwpg zneUQ5i(|Z9zC|8evf>_K2SifJaSzOA7B111b4kz76M_l)OtY?~a^&|3Bu4Pqr?$PK zo80bD1-BYbcWJUklylLY?GOSvVGbi)#?pDwo%YwUXrH6d-fbDG6R$X2l&6YFrA#(x zzj!sJ^veH{!x-D|&kIVKi7#=z>r=R_5}MZ}4hM#n+%D5e-)kTkJ_BTOnb%3Ka?y81 zA-x7JiBaF7RJb?~q;}NPh2{peneVRPhGm+cb zusUI8^`;tL-F+J}&?4paJEe`Rp5+BwpK zoVj5+dzIRy*cR1Vi>kRXbE-8byw0>gyYgP6>^owOe%khiRQhc+(@N_7iHiBYdn_^r zCs`#)e3y-rJdBPj#Pq^vun=Eqj@XztuP*$v>_XRIJd<@#70~SPx~sy5iMRFJg36`d z&)_yT6-rY&S1X^^ORG2MS!7Vx&N?`w3%9GW{klWUvWW4YWE#{@)&j*uKa!7(TDusD zUJ-ot)xR|4oKiDb4YdCC>g9`wD|#K$MssaC1F^Pm{4~<~rhkGgP2i0tzIJs=1;i7E zB1U;#L5uU|!X3cPjxQ0+CDEfu&3kLAdGdEItcW^#jbz2FIJe?m!w2}g61KhZX6^60 z3KeP&8K@2gA}=dT9<5KC2#7dH*t3seveIOqhIymYbfMHpr}O-f-21>DxZEq5_>ic_ z_HiGoF9ddOgX08$@$Tr6;eyM{sJ5x|$4g64%aLpUnXB^5CDOPa!-uZww`=%IjQI^Gh~mRKIXG z3r-x)lmrHT{HRr;2s>?$XsQrNx}#_nUf@OzJJyrOD!s09h4OzD$Hz0WF&B7&GwQwa zJS3R)-CURj@I}y`Zp3G~JW6R#I#C?0^7ki$lv9zfR9m2}FdOPIBCm-u*8macR~kTG zeX^sAZJ<@J4Ne24CUS=+p%2TO&o^Mh)Be9#LYCf3aD;ZTtb*H&Tv+`0RZADlwPu%>b61x?hW-BAz_`qn5hRdD9VSnAGcN zazpsYj+sh;*kyJ78%`-i8!yrSeKm`U&9N-=V-ysh4Dj=KA{IbngtgHFwr%(zJJO0V zel1HRK{){L2uAEd+<=RL^W*TF z%Wv^#e+(Di9s|(rYleB?d@0Lq{^k!PuW6hA43N9riaNZxwg3>XlR@WyAUFHl&^u6t zMet3XA8@rJdus;8g$Lf^v))oAlJ=(dVI5f=1^1pZdB!oav)L!$Cv*4a^r5fzt@`w? zMLRDgP$m<#JFQ%1?|cRnr(Ns=Gox~4#)Lt6@beo$_M~&N#|5@4G-iewEC^dU*9I{h zUUNXTE`q-*y5(n$N^LydAoXs$UE1bTtZH)8dcLnJdro|X60GuhgwpKb`C_wjuBtpF zb$g*{I2h18-y7U_Rr^!EUb5&r;MqQ>Ywc&^MkVkdos^&@U!jWgdefo(7WHey-6gAO>~cc536eGgEX6XE69oX7 z{|QRVocP*PE%3qBZP0abuz(q1C62y>b9R*&5$qy*CqByRZXsudeQhY^a^SGyE`a|P z^y+D&*xc0`=3>i81s%;k$~JZD=nY0roPq@RcXBkE0T-!{AND*2+nS!bX&8e%&n$tP zxVi=4)MBCS?%?)2KlJiq)}l%)cJDMR_%N?6s3Ii3a;0+Jbd$253; z84IIL0|=}&aRF%PCBdLu(-#^B;Mhdghb}%4>6&;MH|S;qVm_wfRuj5chXxhxDDXzK zmn6B$lOyvYyPg;e`5Ck0k7&Ohj1;8IE$Z^p^Z$q^Y?R*FKVk`&{3@-Qx?XxjtDjrc z@1+;;k!wU7ZeLC9C*_Cj$L>ezcS+@pcp#R$@bh@qA4D^oeV@vJXhz(uK{S7<5x12~ z7innRdgCF2dZg-qM%#5YvNXp|gH?jip9tz>CooSk5hKtj49&UR9o)AJrbk8~?CoPD zDjx|y4XBnSnpp3=lD@d4Lm&v({0@$#(ib{M_E#@+2KQIj{e+;&RN2Xcr&f@fi+1sm z#UWvTVO8;=UuVB%p?V&~)V40sf=@w^?G@|Eh zbwT*YCg}@Z{TBY9X=|PxL5j0S_(2~cWqx+iTT{J-cN*HwnqygHxCBwXwQbmqbP3Af z>FdiBHuhrE@T_HFM@DPUC$jqxnrrtDoso5J%d}1|JLTrGK=~rAhoBJ&TZT#`#f)55nUdZHrz_mre`{2*u{aIS%ohJ&%0`H!AWh*Or_prFGK#D9Y7CooWrl_1CEU z!@rRC-6Pyf(lT;6bf4B>AN71e3vScNdi0t_IZro&oBB+T9w6_%{52A>xh^ zfxRS$bEg2VNhP90B?I@R60w3&(}>8y=xIa`Q7ORWX+*5R!`s*ci-qF zc@J0zN16fRH1idTuGW-$$NZyoE~5F0K;l}G7)H2E8Fm3@XUb@*K#BnQ)o+VAMWe3_ zfCl{W<2AO@j}@gr;WIFknJ#XOci-SC*Rvp>EBq=b&Q)w_#HWbzNe=Z=^*4b8V;0`5 z4{nmbK#i{OQ&n{XL{g(T1%z3>SvdrBEgMqgHQG&ftt|iZHWN}3QeURLOdU zgr!4WN><$vUZBT|+zUA0YKJPQ+;ap60}GmanV?FJ%x>0>hBwj$JBovZ0zn$xn-J3M7&!ewK5n zDCp=)adG%@eON-1NfD?=Hb-a~W97`h%dIUvF*3GUG{r91DA`sV-aimf)Js$*f6Vno zIht7CN}KgPS4}C&XNf~H_Gbb$7^Ey5wtTp{JouZ|RR5$mgP6hKxkUYF5N=`w}wdfYXD6%*@Laso798u_RCvG$Q6AO4(u^74>xSj`N9=l`%^? zctO4tYe})#ur51UERgBG4al_J!mPzf@dEyfd6M($hBQ(dnziq`X5Hu z0F8&p$Z3eKS7*!5l~Y*^ypu&lC3&gw_2-k`@IF!-z6aqYtJAti2Px7)>h!ru_F8@4 zb&qy91N_xsds+;EpUJe3GI^19jN@OV|Eq!P5PH z!K>=BV76>z2dLL(4iX9o9q2Z##1sNon5|p9H-%%Zp$juCE=BfIsx{$A;iC>KTG~JE zFuu@!;g8xZ)Equ2NFAg2v`7vAou{k0P}h%oc8egfgl2c2y8Q8 zjv1#f7lHZ-!pGHTp%uX)^+e9Q=;gtdP7Id2=qA@FPP7dFxGIk>VafAR5aKv|hoyfo zng8Vc(2*Q`kxfJgOwuf!s+@0e4r+UNMQ04P zM&0XbDmbeV*h8B`h$v+z5MM?_7==QFTqVBO2qnds7_{4V^G7xnqdl2N|8#*Px0UQmX$MRZGVRDHiO z;|&%Gx}v*U&tc8&0IC-Yi8uRiI)c_$QzzGxtXKQLT2Z;(1!vhR$V3%iEbma#-{CDdiILR8@K?R=*ur$|mMvC?>7} z_LR*1m?m<1w>5vXkOsh_jr^FZq#kZ-uKKWB!J=FDl**+NCv)EWu=7dApf>%#I{2fX z4>i@$Dw}^~vP$X|RBH{rwwuGzXNux_7;Cutl9fp>n)a(w1XuLa)QFd?9;HddUs(wC zNfd$99|h`)rAZQcYB>5NQCzqM>dP-#AM2^ner5Te-v8e^!+!jL0MWR7+RI}x^B*x^ zTW4B6C#4w^F^_tW!KRv!af!Ni*UPNBF;ms}c=}hBFrh^st>&uNPEYDI!{BB5ylL-@ zeUnm#i}SmjZqcZuqGuJBbvg$E&43^-io?;r;Hjh;x zGB4~hCG7In${<{BN`leJ9YMV>Beo+WHvhsI7EYV~AY|wLH_%!^P2FhzLR?#z*ppr| zYB8Q)ao~-!Cm-HV4m5;B7=H0Z$Bj~WSKsOXP=E)`*N2S(Hs5w48b<2!dKqT?x#u2(;D+f~>7^8=t?`DE;ig zV~gYbL4Pbi^JhVff@qvINw_0**=HpB%hA_&7Ks_WKyq2;;f^zl7EeW81YC`5R^nX$ z@dHHT2y#2mH=Pfj=+)IZ`j*;3*^=Wiq{{4~9DNOj2>>0PU(A1I_mJ}h`jx)W~ zJe?0=h!hiS{(^}>$U$04z#!-8%*UyE8V!KhExhHhzQ7=dyxA{dx_$$v_sQ(k$KJ9! zCT5}5C)}P0j@F!B4`Ll-x5{|Cbl3v zvo6Sx@{R!y77#rG*sh-Uq-Hsnu{r;-iR{oWn6!yZ_m7edV0P~^crlTTE0gh-dcnB~ zC#a1yNIm&Hm@Rj&FPGCi&OEu%navJ#G(SkYn6&U)v$Z&iZ|O? zl@?mhwV4+-Gg70dBEX-`i9HvkJQJndcjDV|LjK@niac0DT!0dh)~$(9{M=#ny{0;= z$td`MWc!t~7R64VRmCfTh}d0RvHZ&JYiIm3o0==eQCQ_iYftQqrXN(0$)O0v{m(rk*WwBEjw%qQ87 zTOyd`Tbr#cE0=W~k^#&&oSaFgR_ELso;eZQFiTjIbeTo#8xeP04Ks#3g}fv#$p zdYT<}?r^grJ=GIXuMbwG@ahxv$;4JhAdQyNAHEPw)WTxBjI)=(azmo}8oLi$iE$55 zB)#H})lG6+Hf}RrQ*}8XNu0@`3xW0QOBTBOTbY?FLJxyL3$Zuzs;}~GR_I20$$K0O zFx8AbmutV*?Z?=>q1aG+*slKb6n_AkO|xTAi5`%~=S}b z#P)K9ZpRgxu*)&s_a5XsFuBh@(&6*#J7KeruPoghjkrJDZ>n~o0{3PLxnGVdJl=5a zla0*BI>DWHHtTJ0&6wQh@mdd_aa}#2^S-?CV9v%6jMt*1ZP~b#4!UwhoIMAL4D}*>vB&G% zs^qJCMAX5631HlETreM~b~1!o$X?bk{eyOZkr?E~-8=bs4`~cBKwl<}a4(82tyvc- z0ZZ0Ja8g`qh=rpV1#*rB>g66fRL_Oy!de6ICsHe!=Wxsb3&c5RM0HW@X>Gd*{vDSZ zYT+n;PtF@vmuY;xhsHgWhz{0Mnlcn9nR_`Jq83zvhS2G%!8?e}v8X;S18{E95XuLX zi(ns@*TKk@l~(q)jbTtUD4Bmb9ztg+R0a&gyTwB+8zNQx1H(n|g{?mF=0Kv0ZedVV zfD}P+(Vb_!uHWGbZzniUC33L*-qYvz+?U}zRh?u9Lvk9|a|+M1mi*gwLKd!O_}mY- zA8fx|F_Bp*5p)+2U~#{LA9TCb!SAuW)v@o{+S{)V1d9w| z017mvy&M%ml2?g}czQszNGbRBAO4OQfqqf4nAahPd4~atE}6i%<-B-k&l_DgfmA7x z(PhL~7khTv4_hZR=)^qF;^cA`CgN3aU5EuR;6`!abTfno;_Wc*s3MoZzo^HsM}@x4 zbbL&2(YOc=wOEezL5Kc`-^RK%Iaom6)J5RslFo2lHT2u3TzlBXC-B7||Lda_t<<*Q z9#v3$lfJJCEbd}MHBaFBcS%37+3-DA8W)O#d#7fG; zD~|ymS5wt?!OJI>w(1od(${j33dOv9VG9n(f$#vZua&*Q8rfN78Pup=m4AE{_B$5V zzb^$^fS+^JrkuP(_QX*Ldd$3}zQx4;YLm;GvRArzMKx7$TZ`>FH($@&0`9_Q2LMzx1HN6dT!;MFfok42AfKRrGUZZzLOJ>fXP2>jpFPOC-ZbqD`uizF&? z-x1u4L=N{B17Un%zc>;mhYnC6F1+1_|3Oq2b&De%d6)p! zEt7=S+Zw=RsVt<53tF{UhKJn7QO(Y~@*kwXR2Ejn^;Z8tKe7t1o#ph2;Xf^4)n@&_ z+QZ+kf7YT~#{$Nk8fs1J>eVy4k=A)*$$g9RgX=^XQNC&c`)J*$#pIX&`lI25^@RD3 z1ld~-GfJS-yQ>$-<91MC*rRBEVdOxS2w!~gR~zOyin!qcbCwa&Ju1bSsaTA<;jxm# z-?4vqZEPvWdiVM~)B>zkMnnykEhAzBYLTCc-?yG@aXmO4CO!%o#oo}}XlkEYLX$H6 zK}b2Z#N^x5K}cEi9n-f-uhTeG6_M=e*dB-u-jQ76^kDVGpyEgs-N_!XJ zAjD7LDctGM;Se?!GN$B;)ts>?{;$>!U3p?wIp&eWH`%NJKvO{{B{49ScUAhJc;qCO z8ZJzQXKOIt6{WB3`ps@KG+_`rWUH$~B=Xz5n20po)g`?Smu7Iv=5M^Vr)SOUNsx4i zy9uztvamxa2MYJ9mUS%}?Wa}6BN*zKCOeOvOu<&Z$Q4Wdr=hxKMLW*&_qMB27*|{9 zFv2$qSdc=tOvgd)wlKcQ&Q|YX8WBDDy|mMHeftU4%1w6A0`CAS<_}0J-ZxMm9MAEdQRN0g8+V4cAI`78>4)_PoxL!6)MSg|9?bjXrQoP{ zhd{OW;`0=@C!+$EfnPpmX*8p0{sw&$3a=9G50_rgN)Qn6S)4P~kP%zze`N4yrm zxQVszyDs{Zg*_+DF=w4%mQYkLUI19iyWP%x@&Cr8R9+9!*TV%Tnc|X_NPC+sEoX$sl~cK8*>-zS9;9g)7TXdVXoZgKNAs#8X7yU%ii;5SCts7o`k5!RaH*bLvI!l zWZYCD+-@FNUUpXe5#s(aLJOSQ`9RNjg2PXTh`s{Rz5N4G7_~y_$ENO!N(T%tfxaD4 zlAo7qVDA;}z988>T()g=M0t?;Ch5tCu@XOS$@JkZZ3f94xE z81=EVwA}2-==^dVO4bVN7smstKV2~%FRhf7YSs37WUn^}nzs`jToKEs{gM10G{nYd zFDr!tNmb8#KxyCT=_;e6T&GrPs#3Y(dP((GYO_7oTUa^+){lDqjB@DJWb(CFkym5V zMl0^|gZEdhgu^3^M(;kPw7wlkJiV0NUR-hJqB6R`?|b!Df9X$G)w&!vz)mW@HMY5{ zBQc@<>~|Z6+?4SYZ;84K+O5@l{uynl=29JHdO;FNkw;jZ#v~Jnh~g)!fpOJ1QKcD z)gTs|Otyx{66PyO=PmwCRfDc;%tK27yW6M4Hz$XZg?HG0|NF;9&OXLL`8(yhqlSnM z9p@f`LOQ9z@NYyi^umVg%V_^?n)dxPVpspXnz3XQlrjvkd_9o_K>tE(t#9x>DE->= zdOrRAUOV-B^KUP7eD~&1`nzb*7@b2gmSpfSE6^^(z z@~61F`Yn0IXWG}`4CHe6wh8kfm-BUv+r#E{3yY({V}9ATPq%l)azQJp;I#HbM6!m( z+e1T*+~6yCiG|74Phd=o_p+}lt@W^j&^w~;yF}j0eGQA?dMu4wk4>#DhJdwt zL-SWhz|G2ChS=Tb_C=)Yd^~_SF0lx@ximDtJ&Xq<-T-~)MeWcpch@)jGN&iVZPO7~ zV=ynSNWj^+EzSSID_;Lw( zeT&@U%w%o9;SyqfJ3P41d{~wTO^$@7b|AuKmua?)$ z6z#0wj89^cFcbEU_svXL8twHa3;v0!8M2+t)rU;~_k{HKf1}fc{)&+@Cb2UA@7I z4Q~bRwY)ls-fPNx2iAM48%bHzO#u_IcNGu<6F-`UJuzpP%S_Acw}v^SkeS?q_aiAp zxBe80Rn&|BFCuJ`FdJ6MTRmUp&}LC5gvq;o^UA=Am%AqI6vWFNpO&gR&|hQ=|5bbR z#yH?xx%8_Bta@hx$7$;ETG3Klrns0bGvO%YB$`p5Ir!>@T?Ly{ zRO96?9-5Pk@j;jK58-WHp>5q-Y@sV`3ZuLveg9~Mkh!b0Idx7Vmsf+!qo37A7`ush z*>NgnN=SJc(FQ9}yzmYf72XUoQD6(!vW`?dIwlrVI!`0|tQ5(3xkoI^at82iH$fiz z``^)}MQtqI$nX#qg6_=Hu#KTm>qf3|g&~Xl)wE&IUQe7`l7Yt;13XcS4waY~ za(zewZ-4=(-T%>*&>3&V0_VN>@%@*0aaPc3(2S)_aD&A@b5<~OR><+Wd@y_kn7%Ru zbG8t%1F5O1w(y6im;(sQW)$x9QvOG9Y;?5ph{ATuc!meK)rB!vVVocVrjCA|E&QJs zo$9Ct{@NDR--!(Ht93qHh2es#4MNE6$0^JA!%xw&O__Uricr`maXeux9etu+|7$v}{%exq zl3(q&e7s4{qa?@zn9{GYFg!hC$CT(}S2!BEGvN7Si(AC<{`N8tFC>2i&pk|&apM>* zJ3o1p8gN$&@hQ|Mpe;Yf>1)6DyCi&4v(G?ijZ>=y-1WAB86STN+s{AS!e z0T=m7q(!rmpjRK6rLP{hIY!E7x~ud)b$Nn3LDA5ogiq>`=->3kzfy~Tr5=CNG`{eE zrKykV87Bo%H7j|0eN01=o$x)$_cv=lXd~08)!%X2_`%ud7#P4oL6bfh`0%Q;0t9fl z*2CuOgpm!aa}V#FMw{;BmL#V+G-r{(M?1wYM64aac{ zZ#G__R$^{PQ0&YUDLt@G`({6gJU+P#$~IrT60s0^&`snWc2Gq}LhN{eRAc>krSw^*-8dVE~V02ikVKqz%l+8D|` zVeW`DeO3oC?SdH_-?hPaWlPlfj2c0xZv-x{V&yIDcF~i0<@{J zfAo+b_c%1ydxv*Z(_{snM;hU>X$gby%R-^?oA_>*rU(l?#mePMvo-#&imY$9CeawF zJtq08DD@RY7}TN)!tPQYeGQBFv1-=E|CO;|04+O$>)Er`a1B&Ig`DM+n;k0|Go`;z zGm6Qv)hb#QAx^a@zY5>MRsst5{G;ZMGG;XAq1Z(H))t+RRHqN7i+}#0m77{4J!Q9A zg+d%o@GPysydM&ITU*RSlBH`S4aM=?lT;fHw%AZLk9sN0VN4xr^wV8sCde--GWU*lDTUm8FncaS7VTL8}i$KU#P`j+K>p(-BTG^ z=<9#HWw<)}$dNbKgX~6_DE&`Ap|BewZ|Ng0(u?b0s|nd>u)LjU6MV>1>ubo4F_k8! zGO<@gho&xl6GD6*+&g2oO=$_Br#&);#HZon)UT2rzI-+xT&sfeL~Qw1$Iw_{WIt1O zPM>0RuQK}Ds~PgB8RF!G+0-942NU&h<@2LlFQ}DfhZEOspf6o%6-&Rr66I7~I4lfd z+;jqC<}*?1XIXa_jjF01T9&|Ad*{q7xKV_xC#5%= zxZbD0N^~%#3c7*=U&&WzX(>PM9S9CoK`CD=M|ppn9m05}rF;TB8wn0nKvCistw8@} zK|+icsl|_vL!A)dfqN8~r-_FXb8!+AlK)<7x=1}?9>Pb+gMZb;_eZ3TR3({*WBDos zY1}oeNdr;iMsc^+S_d0lF%q)nv#pKGV8) z4lD%&ARYW>#eDk72VZwk&$(Cr3#wI828e`2o9oSU;W50WwG7tuH@?9Tl*SWGuffWF zvPA^{XRsLqxg~lF2G!SXH~eZ;v#|W7D|*z*$fr&2!Br?FCQ5jd$nlGpR!DF1Z<~F$ zb@jK+zBH4&Z?nj3zm1w6=!ZS{;{!Obn!e-u@-n)+Our4Gig_5b*`(%#TWjiwqtCCp zXII18>uEM=--KzRUox4c(7#+@md5=h%;`4AoZ99}%41FcfCyS7td%&^QllVGyc-vX z7WT$Xy5CsX&ha!R<9GX_f~#|qJr>>E6c6LZ;!g_Hg3k;78uBl@<0{Y;BcVXe3;EIB zxLvd`71teN;9W-(Wy9XR0V5sUu1Pa6dIG6SkI<8kwjh`E)Mne&bN^K z_>rHO7{PCSRpdu|?Ct+T&3m~17b@IC%D+(U9)j(;R#5r{w z#M5v?FnK9a@V6*Yt{)L20~s=qAOi(5JVd!RdW>>bql2z4UC3|Y?U;5 z$kcTH^6W*;w}v1??|QeG=z18Wuq;^Dxomfyyw2KH zJ$)4L*pHDtd*N^+RY{od6|9>XEWXLATy^#N+c}*f_GnH!CqY}*Zc-sbu@YP%lEl?t!C<}2FV79-PCBu>o>Q_ zxRD5DyuQvthex)RHBoEQcUI>)dJF4gtw{h0c{o~GYcwZ^L25N=2Wc3RW?4&Wf@K?N zO5&~t+A&JQydK{o%hGxm=SWmdnjE9YhyF!OBZ+NKF-}jh#vi|0vR}kx-&^?XlbP(j zG-xXZra$!}UBtKkin{%-R`p)V;*=6mC?-FzOReNNH|Ej=FErr_*Q4Fz<Wx_1-y}OxB zY|)YB@#2*!OI-7_JSaEg53{`3jvDjB<6tz!i__*_x&aC~IYvgM*LkrQ$&5QA$UeGr zYP}HidCC>yeF$-KFdxwWENnwgj*T(GE-zM7z-;T76ircO%S)SJ&Fw8n9pyxj4dqIL z7v<^^B}#DiLu4RF22x}|>ZZiVK!yw?$UuP-{2V7lmJL&$!4N~9!C8;SNci&F7A;H` z#P7nLrg__Lf$WC%u`w`$5ulg%u$Zn}5$Ina!mqxj6`c$0QyH6X8E_F3_`Y&{b4BIK z{zYZ>CL*i#mwR;4yII_?OTXpgDzAAP`3kjL7Cf(YMYyIJ)x~VLn@1e#MqFAbrU~*g z6K9Dl$i2_tol^D~m=!SN*Dn*!Cz-J@HCpQW85?^{UYB%Hys1 zX<2Pk{kyHP29q)+o^z;j_^&@v@v2Cu-NA+IKf+zTag^Hgm_k_p_Uw zJR8xoOghJhVSdeU@!j7pw`*5XbUcym5VrwXFe#c;h?{Xbs%yOf_MGi&O859k%tZ)A zT8JudIf@qbhR81ungyRZuHPTC5WpXg==F~a*2Be#QW*<(Lv~J2nu9c5>$Gy_b`91Y zRoKr>2By8WO196wZO`D;jrr`))gM}wZ2K;HNv3NqiG6>1ySf)D<45$qu)69u41NFA zMnfxi{s}t!5Zu+RSaUOF&sSwj?@U!_vS{dP$4hAPdhn|Ji+v?GSlM7RV;e}ftSbXsK1opIKpFWd#L$-JKJn^x6d(cK$a0mgRP@}4Q+SJ#K=0B*$RxkLx zvI1vt?2433yW$>7E_sYrOI4 zkNfY!SZVKZ*^XV}O)+5Tm2VI*Fc^1cJM3qN6j#Xb;N|e3OHYR6!oLZ8F9-Hsb?vP^ zQYL(kJlch~Th=8OGJJC0nqFj(??JLP2L2H)c6;#4!E5KkE49hZI<2s|(%RJ*%&CF1Cpf7k@ADz+8x#&+*5xvROlMziZ{yj5-2w%N+Yk zP*V=o(O_HrY`&PEEXN285H*`cS#y0Z=yzzcr-I|P9`5;%P_DrFeh%ai^_#g>YzI1- zo$~*lI-3vp)0|)Fr2v!V?z&HU4Qh~y*?L&Zu#Y$CY{u@B$zMMB;CoH?+yoiJ#Ei_q zpEkvuMR&xqxlGSXw@no%n1 zmbclXQ6IJ`pV#t}J_Rkq7?A%I*B=lQiJX=n8jaNjW`CWzymK;qxl44#HD@ZyuQ{_h zDf#p`vU4bgHSz6BBJ0MwrX7}c%G}TNC9b)$gUJc5ca^`h>Eqc`0+DsGT@{Jkrn<%w z5RPm!GFR)%!j<`H)_y$k^^#tfqp$9yZ}7k`xlFq%Hd@X-PMbGgE$Dc=G-;D*TDU$< z@A`AuwTq#fqB&eCONkWMyT!uVechJPMw|W1*{FUCZltYU zMXC1~`oJJoOmP;ak=43JKrkQJ?MKtDtAAeO_keXxkZ0%QXf)|@?ovFhD8usbM zP9M}KAEgfaYlt_Od&g;SE_c?t?+?D6FD~-qccC=mm}4FVT(I|^w|KtLh%_emV>iI} zxOTG6KH9UngK@88wgh+Snh|=*v=y8dHFNd178a5W@vA==5;Z2u6~_-!hWIc=(Bc&S4iq#A*YaCXsaEN z{jD$Zys|yWHokf8)UfQsva}_?A31?n_P)8KBNFkJw2G(4q+RD6n<;zc%zxdk^hnk% z>uS)_&O2t%&T}#@lpXA7^IOYjD*M_}+VQ6cAUCF@KE2#MyAoh^bF>6AK`&c0W>sQ$ zZfPJm;xT6LX}T+ksJdOFKD0ce#>eFh+$W}%I@hDT1Up`UJte<#_{#j|@I_TOTg`)a z#dG*x^DEU1JW{REph9l^Q6Ok|={A@XXf>%cseDTbJ2`6Uy(@J3Tr`E*qrG#k_S|$5 z_`>H2O;_5ZOzxE%D1NZTWT>5-Ci;uxPzsfO@1TssBYg4K_wJ!U^3Oe*6>`O;=pvsv z(4SOrU{f1n;F|#|+Nhs`Rv|UtIZkg&Hm{<55*LPMS=ov{Q|i`vs{A^FPI=1gmcm0T3SF@iUW~hPE4DguNfrx|Gyy+mo8zKxI1dxDvi2!^@ayH8b0-ixnE+$qV*B zAEkn8`8=`44v)5)K3b38CxYKgSJ0zA61hLABqg_f0)C#kpL=aR;dhCB*~@%vkR8yN z*WCR{du=%6gV2J2eY;0*>*Rn?N$y~*$T5M}UYTX?lhajMrv4l8HS<3K@K%jI!qAwO zXyH27W#5G0^t;J21TLLf`7a<r;|7S;2+^vJn|86U zPx9)>t+C2rmHJy{{O1-~j{QKV&A`cR;Xm4;#`_xNiys=%)w_6N^Elj3+dGhpB{*^L z0$-u}#?kAOoE(>j<>#)GMckepYWlU|%lepjqK*}BPvWadDKpV$pI`8ft-`OWIbCG_6;IO9s<5fa zpOrc&chdUH92a%4TznA*+&CRkT=d6xwA&Jj#$H8Ce|r@x@Ys3lL#D{*@XY`U%(bu^ zQ`9Rq`!nt?yMU5Z%f?m@)+s(M>KHVdwBB|H(av{<%0#aCQE_$LFEE z43%`+BwQWi(*rSKCvw^}KlY+0KXNM^EzTtr=I3dBAX^mfNs(9hisk&Epk$Iv!UCRY z;IKpN@qz#>C7!2`MgW+-BoR4@7E_oKRwPQ{^k3`OW}WH?C?=t8uT{rAlCuBC$COu& z{ex^uOHpjQQtjnv6*Z0@a^nl5-{M<2@DKOb@@vNf-W@+4_P% zKz=E#Qr#N3)fK`74B|{^X_-CJS=FNMBtaUPV-T;Ijg)14UIWEUz&s9xj+U8G#hZs2 z`M)6528nV$7z1BQ_{t4eiM*pZ_Tyq&TbcWVl9~AT-yh8v_6|rDwl;Dd9ew23-~Go_ z^4CPKzY3?*o_FI$nmFBL6npYWOn#;`<`%9H#qe79n-KjzwC_$6gjd*aUaVLRq#sSJ zcms&&8r$aq+tE*4H+{^M0=5gD-0DpUeQrH9rCY${CG8J-o(T3+42VY-s>!imhrAwX z|8*2jZPuCvESXa(up(`cFC;z>SA&t9TzZ3&h1XVLi+|oF zSIvCjJp!a%rt@3>bYGJ?4q(A6_~sdOOlpJfOOPvRaDF+zwS1#pZySDOK)J6~#!HjZ zh|FU7|1kE~aaBFh-zct<64EWLq;yGpfJ1k8N|&^Nhb?fVyBnlCq+385q`L&^l$QQ& z{CuD1xxf3muh+eQ%$oOJv(}o}bM~2;HG7YJzt1|Dz0Ze=|0Jqv&0`-Wddmmt{@F0p z;{_NU-Hz{X=fBB#mV{nP%_b-e=z&JN>+DoPqp-`0fAO78-G8c))hv4djAz@=Wj~fj z+C|cdR`XE?Y7@( zI|PT_0F$rJSMHM*a2qfFF=gsspB$+rP6Ev`8ISED1FG6kGgXysJqkLQjWnU2wB_C} zDBy+5+8y${f$4gT#PQ_+@|genFOOz|0F}9~kC}DZ%h~lep2aeUuxEaMD_sAlkQMFO z$2+&z_cvTV?IOAb-GHp?q>KN^HEW2pLAhv0-4FwfTjM?U0;gHLdg9*ZvZQ$rQxWTo z{UAyFP@leP;-33v*g%+uDk!{GH>CY~YNP3nKZg_S{u@m!0*`eyC{L}TjOPa%Wu{E4 zC=_gzMu&=@O+hD`iF=XYx$*xbO7)3UmUo@+8i59LMbDB!w;Oj!tS#Y(o!!A*=VrrY zgT9+@P5K^oG6smAMw*EW=O>3^%ZXrS-QUN$Jf~L-%2@07Ho{|p0#;BtG-!|JQDLz> z(SzuutrX08JZQl0F~^JR(*KIkJn~-=rbVZqarFU14jiUncee%l_Alj zr}CRgbIjzW!%P(&T80E zfMdOk6#I*a5I-t#DOGWRN()$G^`Tvv`*tv_7$TPI_QGe&)4HB&0(O(l# zFQyPH!;g}P)!{p-c#-<8a0TH@+One_dL@iKe`YFc0wz(~ijz|Z=6n}=UWV+?yiD1j zm(?Yn+N**=Q{w3k^?Y=y2cU7a<3%u$i+9AZ=CQBx$Q`yP*Y3iXpLUBbhwN`W}^i$a!c;+_F($N)_KF&tK#>GNm=-+#r514!b zT0DQ3ZLA#PE!BDcw%Hi_yq5T~L!uUod#molYSDc=l{;@3o0(hJD>VHN<=6Fo`VSS> z^|t(nitDy4S48wfFaFr@i`CFMxW7#->fiYqZInak6rGaBKq{>N)q=GrE;d$nQ2?!6 z9Ef$1q-}pz#@dM!ZX4fVCpLwKn>Zn5yS9g4t%WzZzWp2tr^xBw7RUZ!{dZma&Z=%E>TrD)Mh zw_Fu#epUWua?23CXaq*6nt8(lOg!h*IS8^6$*iJ@RvQqc$e z(yy4JO<*3@m*honr5n80U$XC>(_PWAG47H~a?V_4T#(43S$@G$)B(`cSK}aWAJjfC z5Ers$Q!6ET>90;6$0w}5-*-#!6nEd^oq=+{-*Zg?bRgu!oI!y4Ku`!sEXBQ zmAQvtE<=BjNH0^BXb#Y~H+Yqd^qj=ofl_}(<2)*A@ZA*jdE2q;oszXpVe@y3oV{$i zLw>ynwRz4-gJ0&gQH@@Ig@Fr8Sv%E6R#S6Q)%URjPDZ407neXqE_u-XwwS}NQia)J zRr;TXim?;i8ZlQgqe*Bh_>s2iG1=uBxtP7|Nh5P|nZ-aEQ5b+G)(sf?F0q!gqG`O+ zzpRU-de7fu3b-lfi*`+Ia}nn=&<^OWu5V}=O(|bvn`&?(d5_Ale|kTZ7!Za* zAlO?sH}Qy(fAEl~yYeLQ*s^_b!D0*nLzT{u3z85N4({QU0@5=3)h#%T9*bSs3 zBg?#|K(@}Ka9`(3Me`r#6&l+3S=U+K66O0vX!?5;iM^+GzayIMg^gMz!S~YuW9BEJ zeuSA1jWJnb2$f`?J+<+EWD!Q26mHs-6EpHrS?woon(zlfAUgBdJl+^BNk^*<#R!|}@U6buU2{}QB zg2JXghkXO0D`JfFDv_;`#ZB-?#$o2(=mj(8h_OE_dQLU>1vTv8FDLsmvC8*W0{UG* zELKE(38{R_tKq>C$cBdMYc!QCN<_cy$gRE^)O(hB$KB({ zTQ`@YU7F@_y|m7DNi;vCUNpa_^k{xp`DlLUy!eQF_DrZf3#!=i^<`AE_EJw%Iz_$X|xG@i6_xY|eu7A=D425`$SnS#=On}d-cbfNw1Bts+7Pc__tTOpfWA2I| z*!$?nka9Ls#L$oZRN6lVkvnJ%IZz3Yiy@;k?WBmXRtxO2^Cs|uEW~+x&k`A8B+7?+ zef|)Zu|aG_Q4~aR;kEMjF^>#}#OPB8F-pX!6U7 z1ZT{!TltPPLD2g4Zz3?srw9aEAb3@jKqxGUH%@cHqvF?_p|>`3c_FP(03?-W#}hFB zuK7k7P7zN~@(9W(;%m2~f60VWJkO}vjy9C%=!G&fYYteOcL%fU>Qw0}GBdyMoE``v zaM9HnER-_uF6J*QO~TIs4Q3$mI@a{TIzNY8v2f6${8^_!AEBO!exx{pNQk$6Ek&TAn!=d~(0=jZt}ySA}3yMS#q2tsLg_gJ8l zGn!!F1%o>nUVuRn46I-%1ZC=J_+oSRwrbs$#t@w9W$X`C)}8$ga(m0kHT-y9SWdA} ziMt=*L>pIZJw-boc4(<4<3qPklS5u?IxwWpTf&6 z4TKt~?Lk1S8?;~#94Fxp zCBd?vO9vPDr=Pxf7fcm3FJ+i!lzup>5pbzrP#c;cJWSW5KXmsF@%-7@I*vT|qhdsFlI2Gw7@bt8d15dSw8ZLvAHIbSB*t?=j(<)AU z1uZ;D9(q!bSs@=g>=lAWr++QklM{G=^EZF@dN=jOVMa&$cvx>~s@n2y&!ZAiW1aVJ zaE3Fj0#00o%kLK+Ekc(6V>uCB)&5T^DENOM;Q7Ds|5hUKh*oOmE5FyPkBBiY+B!yc zs?U<0>~3Dl+odU%FlbpY0PoZPC&rDP^#4*_b9kJ_c{IyCR;lS@eY3g&T-sHi7EsAV z*-6;u3CmPo&nI+cZVMI=tv^yVSm%^5sHa!e|G_G*{&y!4y5BR8R*&a#`-g#{b>Py1 zB10rwi@KrBLla;1FF(c?L4+z+XIWMOhYQH+mb0i3ZI}Lr04>%?`e?}_>Biqx>ld3$ z4{tnh_4cu(3PW$J7gr0wMc0H(eZa7RR&|f&p|n$UkR>Th4iwS9CK1jPY-DAH;cJ;H zJPgSkH|5Q!2SWo-wU#y4ZM?qNt?>~hFot}7!5HHElTr5bvKqerKHoPsw{S6(L$bNH zI!T2ro)F!4M+`Oy2CDd8Llgd+nErd|6!R4fC<4U{4Zn6)eV|CAdLgn@!0Gp_KRY;g ztncv(q<%7?U8fj+EtcSQ@|seFLX0L#*#5Dqp(+Sgf!TDUNRLe0L}nX=164#=nQ$rU zwQfO-6eyprsREjqsQ{l3Wh*79*Yk}UIA^tT^5tS+VucOK+>agD^+_L{;*odU>v;B} zEo$WRCFLDJWQq(oV&dinlb`HmB(tAvq@yxoe8#A3ApG~4Oc|>5Tg6P>3REWH^KzQP zvp7#GbpdxV9CZQSe2`aR;X4;Ru{DKfY_oRe38Nxpm(Og^MrCUKsEc#vrUD}%&zP= z#IMalv(U}ds41DiW!`L$yEV9N?r8Ja33%DRsbYe z`Y2iyXTA!|grIMze;9nA#@bYBKjk#jM@s;P(m1i;ZLXiIJI5pEHg+4U{+PLU<3L%c z%Cfc3IGWeKWxt3@;V1kwR6gkyv_VnL%#+b+8aWp)sSGiyE{R|S@23G@Vd1lwQn4@8 z33Cebu4WV``}zMW$mggQ_XMzZ38_k$8`kyap!9UFPC>AEHPV(BkLk}+?buob-p2Cc zA6bL@7c$@j{Dplm`(Msx@!GJW{%XNtgVC9VV%f0Hp|Ec8X1sgBoz~rTZVa!eX z5sFblLIloglp2K&jE%W28wu?j4sZ3>ksPUWIlFw7w`T4`Ekb8J4!|<@b&4{~)g)yS^Pg0ce&v@$B#^~i5=1^`p?GIz++#puc1)C6n_zrav7HEqs2W+xXfYD2Qd59aZW!)zQPd)jAVP7aZph+!JT z2PzxJlzxqOHkQQIDS}x&@K)5#7dFG4vr~)IFmXF6_JV4shLyFnpU+nvLR|#7e7#wI zh8KOTV(CbG0d>mkZmcHdHnH_|h-Sz1x(A=q>gKQ`^NO1KFmK!XgxZjp znVdRWFMa0?K3%BM=uMivec@I!OXK7dDBu(VI9LpkG-7LT0gR?;c9Sx zxLf`bj24aM9qzw@J+gVkNb{z1cJbCcT$BAb%*QkxEUxP{#~#c_tl6J9C^d6bsb}c& zO2(~{I4U)BQnJ{1TsP0xxABU3H;BCzb|2y?E~p=SHZNX|?Ea>N6|Lf$4{iUiN@wfH zAt0xoc-D9-6Dwk&^9n_mmQDbLfO_zoyL2=;yY#iHplt)|$;vjePmBoP>MPF%{?W`_ z_jaK98|&N)bN5-$7QwF1L&(it3B2iRSZ>7{=I=`sLZiTi)AjK6)#Z05!O?=10>O*x zop8Zuc}!L{I5{OsB6H`fj#b)_O3V{upq<9fPw108PTe~Sk#f{#(HAcmI+r8;{X;4r zHh)FY*xkSVB#Xld*h z&kcvZNobs@Yb1AzgW`NC3Ef4eHnen+kBB=6c&F*$wWSCJd63`e?>E{Svn)RUOF9En z+^eTwz29)HQw(<&8qH#jlI-mpP&iT>lme9!>$JAHwaS?a9@DD(+$}I zzK1#VoR4_+^`ezAlnkMt?^xDdGJ!4qb2%y(G@^1TdMUox^F7j~j3k~7x z2q0KH2lBA)dLMa}=A(}n&EbD54{q^*w{Crpmqa7PsIdE+&p1YiU_`2hM*|wE*Pav0 z1ZHi!QDFCg$wHfGi(00@3vhw(`k``o=?;{BOq(ZqZ?#-b?JgNn~NvH zgo|t`9&uoU36AOs?=mM!!tC(2Pg4iI!IT0%Qgpejk)7WtV9hN(=6l65SLBlf;AR9F zNo0JOiej*Gp3SHW71W-Ws`Fd$B09!1em>Kf@FR#39v2)EOoFX& z(=+th>KUH}vV>X{2NzX}V|ePmjuIBL>4@%L?t3v!rrl(duvB5LFb*#26v?pU=VRQa zL-IlSIA#`N+~LGrc-huJh?AoPiq-HZHF{nBqMjGg3V`E5H=zQC?UIO1d?eUiY9huV z79Zddha5lUv_vU6+zPP;W}RfC4XopS^!ab=#*&(p1z*Jd=579^`#TziLwJMOGfF^H z4c_yvy38r{&bIdbI>hx(DtxrP?QL<8xYr*pHcwsq@Wi9e+bw?&TW| z#=gKwjwG6O@fS7*QX=o&Pd%YY+pKc*HgJ`zjX(lwN=~cyL7)0`YnfS*$+TF^62@-@ z=Vy%*RLPwfJ3Ha42O;cE*MAM6Lq=t)@LK(p;1I6)L|&DoJZ{+iXYjGt3WN|<$K}uH zYr?5d@$|q)Y45NjSc|LmXPoMKJ#X?Fo$M<)DWMm~ko2sJ@yl>o@1aknkcL zwNX>R<_CVf*6E=t5O7eQM+2{ohyMY7Ziw$=SJr}{ArAG2~ zS*GvJ-L71f+7@tk9~(0N&Mc&|0@i-5x-a;l{h>7brSyWx zzUYT`BR$LgdCzvEbgm2Ph85AGpje+}Jop{zAyy$u&tdu{3O8bJ8{#EOP0kl`A&%y4 zYQHw*8s9F~43I_8B?3m=5#5T9QD=wYBNHoNN$3d6iW1|-bD45<8J`!>Y7ni2g5&Hg zoEN-04We1AuFqkZ`;OP z8*)8vXbOcDv1m;u&O1Y4)(qMzMmC!S=We>ugZcEZHIySPyB1M)lYQ!)(6f{rx9+Bu zcBzWsb0FpT20<{)OyL^0)uL0HeJ3YpQHyNWf9ouB+?Ld9xWNfUhVpI`Y_7mP+p}k0 zBjUAN#jx$p!P3dWd1oCM1Y8xu^TIUPjs8;KT1fQXs{_svkQ;e;zTHVgK8D`p-0|*? zA3+iF#n7e2C&*i)X~_(IhPX=ItD~Xn;+3fe!0%*)M=gW@9F`>r^9|z3y+6MTZFwKJ zExzjr4m4%X`FrDeG0OHv{6^LHRVEC1E4NIB>)kkQ8kvVBJP4eYHTu`ca9^_%+F0c^R*&`RlpbKN*|PG$YeBldLmufgk=` zB^DFXjvmg6W*)v*&!@weRy^Oj^;p|fRJD&sp;JtLKlg&DvAwlva+8@KNADqe`3rJc zS4!*%%y1^z3OI*9=NlgyJ;GT0gj3Q>L57}dAWn4bW=%cwX8t0-l;Vakcx-&YAWO-r zGT`M$;^bYVQfes*0gcNj?F#4D!rlltf+muv%OFR;u=E|N;#((^0R)~%A)n?1*s3hPN7cC{M z74FAm#`ZO9a8{0ify*7Y6V-A56`W&v%g~^h!RnMz+>a^oUS4MOw^Bk|K7-Y9d?xdA zrcdWGuOWa^Yi=$kE_0`^I@{|IzqJfLwus}f(BE9lybRq@t98F89LrS(bQ)2H*_HgB zE+^aXS-h88PBDG6n@&4{x7Q9N&zc}#;9^{p5||8Knv46Lh@`Wl_WF?F)?9Yd(zJ$T zSh7y>q1?6o!Gqb29?1nD-ig?vMv&=UXJ==v5WPf4^EoGZ4e4Mb8~;*>(aEujH^PKw z1M82<8YhY~=KkAg#QZ$uQwPmUQ45vP^=d*SjW!b%1j@X%F5^FP0pD=}%;zay9Z{gW zaMFtd`}P|(zu`}+m-gnUKQVY;S?wT+f3T@^q9R808PCq5movSMfv~^*9mS4(n+t^~ zByb&4%HwJGMYvWK%6RUYy*yeC1P5y1!DLuWB7WKjPH12wftg>`;Ja3#%86g zJOh@r1*6DosSAO)!j=y)rQdtDFup^No0<4^7rRnp5j}G-x z&IWK)i3L`SU6C8+*AR}8A{pbimyKHSh}}XD-(s>7i42v;Ck{*ihRZK}aN}2(&{hC4OxidZwzk|9xY%&cswX>Qz)vm<=%_m9!_CteO-L+dwR@6r z6P*6{CGdFdD}y+HN>zC6o-A*Y$r8)>Caxc!@MOpZ#dE*WU+8KPLgC{;9RQ=H7sI%f zR16@#4i|WFLgk9W!MH4gitxQE7CYdx89g<|vtC6pV&sT)I6L-B@8{HsYp?OoNW7na z#X5Wq@Bd>cmV|W#a;{1*WXDCCIXPLJn;QYe-TKWV^*n>n z1?_|;%-ibC&ZIB;Qxfif7Y+sq=2)C|vx&8^7`~B#yDk~aDOBHkBo~FIG>%ohcY^FwDpJZ`C+8?$QKQQy91@1l8y^VEWOCe7Nc>hss#1KX*z(sXEAasTcWSZaA+R z#D(F41r@A*h#rN3z=y4~DQMI$@KnIVw6-Qx+{LdHo#_)=L=Zp0N%01k>s^}3+5c2^ zs=-z5z<=^_^nCYJuzWAh$^qY)#twvGaej{d6rn|FLEMW3&8c!U5dWH{56M+Dyad zDCv+R2;LnoXEO5txM%kNS-fQUr&>%gC*|-j|J`WV`n2gf@BiZD{690+QdU*Y`xMxY zG>t||maZn;R8X{xRNqHVm4`a(3xDmSu+SzlAvx1I?_=?aX#yA1d2Kmdm&#bj1It+g z%9|-0rJqN5Q7~z&9N3cNEG+FpVXh0NuFc?Vu`tp>kNEi3{gM=Fm`%Lfl0VgYAeKdl zFuJt6{prcP>60cs@^q|sdSOH!C3`2wrlH4c4sHe_hISl=i)H15y`d~WLRStoXEy3K z%R-fp+)MVHr9>^u!f@4RHX?k=Lm41$28Y{QO+oRpZae=Nj{n0r(VR&vyT(EV$dz%K zwrUMz{U$3&Ia>a?~dVSi$mWW`L+@p#z6aD1|Po{Ga)C}sxI)v!oo znrOf7(dICg-S-;UcSsY9nO*ykI zyBBy_9F!|WPD6iU)}lXz9=;p{N)6_6OsgY~D%?oj#haV@lI;sNRLjU8F4D^%y32tC z;6`z^t?KtQsd+MR^Tw%vX=qSHZpqsm6VT{t)tdfr0Ig%cF4k(yiLWkoK8kNHTieTq zmOKA^b>tG$NBdCPC(7);lGGcjZ+=Nz9D2)k?Ul*ZIko&TqCa_sLa+irW!)=`VUPNA zaLk9qb63IFt@;WdJh4PM!R2AW?Whl-@!_CJIHXc;q{)N8Br(Iy`yai*f5bQcFv>s7 z^x+U_K8&K-AFn>F{6~Wxsp9#MJI5JvHTWObB`4^tlH1aA=Dn>*EDn^N5oCwBvA%zt(ptFwvI+=LJ z?Tpx`wwK80*EY=tu2q#CJrc@C=K>|TUR6f<=zX9B2lQo>;7V72V>=HhSn-%*ln1&b z+QIdIpw=fGoQ&N)`X8^|!1b#0n4x~IU0Z+9mzYDdD<|wG2?O`S!N9$6Fnh3Yt$9J$ z^Tl8Q3q4;BhOb~K0t3h=1q*%v%E?4BjTEujw>$63EmWjkk6$nswAI`V{6DgQ{|{o$ zE@a@NDP(p9EdNdh2Sq%k8 z7&>+QofQqkKTQ8>@T7{Eh>tC?`C;%?k-5`pN)^WzUR}HXr-0N1*ekf(tpD&?bM{ca zb1)+idCJ3#=gU5-F6~Rb)|F2J?nY$%1*p9>1KJ+pALRGqsUh0dqV)&D(6=rhE?+}O z7nadOKJ;ilc!BV%5A8bKAGLYR zh?5NqbPIw09|3^35WEv6A|#d)4uY(xa*JDR+w^9`*JpE>A(eW|-cke|KkLdh;9SC& zN8plVnPCxX^G3Lx8pv4j)WdN%;>vguI%er^uK{1e94Th1dIEDlhtupQ(4()|!k1>s zF_=3YJiE3COfGAuit$SsGv{&%o}dp{MmVU#&7!n`LZ&LePwra~=xE|gB7NGljwXe6 z^xrKm3sYAn)_)hTVnaS`{$h2j(Z&%078j9j1S(jOO1@jJ803HjInbi~62DTtwX6bP zI+?a5=vFEsIgxl4ad3(YOE{j>rbS}=4JTc!O3FQ)y$yHhYJW_^3KjY1R zFg`fnCn-}QR?2A2Vv9VVKIJs1k{q4cO1b|JT;m_(28dc2(wF zg*Y-pCqJh5+s>RDDUON0m-`?iw6cO{UcmU1m-~@9GzhPvFxf24>pG-IMVt9<7|EWQ z!%oZ!h`u4SE7CERImjtg|@&2lcDQ z+>9rni9yn1Frihp>%%KqOLv>mADG`FZL9skg5}P0(ep;mR{vzP! z5OtT&TL5Cy3L1EnxUM%?c-REh_Ffh;5okJN=12@IW22@W@Je=z?gazrfm_Jc43^lr zz(#dswe^T1dw(>k{h922>LbaV2tWW8%t^Va z0TqE}MQ;kQOb+Ui=^RMe34UOuoOxWpa%ow0OJ=+J6j+#o%}P1d#0kW_gKLx%g0 zM7Hb2=VDy2X-rN7{sangAA+qYc>yiMd9mIMp8p8LBqr%>Q%vE5!_vojO;73n0-CF<&8&n@5nIB zvxt})=gP4e)Mgbvt*aX}$bZMZ{M~OSSq|)59Ky{VEy(+}p-f1&`IeVfq(y_QDRoBL zJi?Bh8gEjk#W`)@7q;EBB(k7`&p7Maq0qH?8dh4CVVF4(`j2v-SJWXtrOsAZdAJHG5#$wJd;0t5&dmd4kZc=-;pE_S> zTz0modB;*3m$CA76$@;nNNeFAOgmR{DStXicaoPjSsR8Myc5lav8u!#nRxkHjFB(GR+xs*D&q>*#|{SOq$|w14=Xhm5X;+2nOL%zOWVY@_a7nopG(Uf|@gpoc z@_smE6qA&*qN^rKLXAYS*g{f~Sq!5NYEMY3!9~hxPF$2S_jRB{dTOY7UeY+%X0udN zfWiy#f{@dL!gNEn-~BO*FgR3sn%4?xK2~CG`o7fRUisoMD&nRF>Mm6fyrk8r77(TV zEj{J)e1tPX{XokxIGRZqS}sX^^)`zxC>lKAK$nkQmB(9qPXx3X`9=#)xRu+8&Jtnq zmorR#*iac_l52C3eZ{hEt7^+8S-hD5SetiAPc8O2L8Y4qu3$W!v)z)x(p(r)!v|_G zlead9pLfx_R9t$`n%Q6Sc*q+efET|>ON_ykuxSQR%m5r7G*V9ZfU<@!l1gx%mDR7P z!QJ=C!xuq~>f6%ntT@p_y)wekW6-O&R+l7aE}O zBbG@a8NCjS&P}EU9&=71QFr+v9b+HmIk`J37-B4(U$!Y7lb^&zQQKq~?+40ZHse#j zpDkS5kRB&=vwkVVxkSisqp?IU8Drsopbn4faDBlZ!|kFEdnFk&r0pCK{VH~Q=#ewm zf_&zta}z-<^Nj-)luopc3Xgt8mSOzL+Pz+KoE%WRP`m7o&efRr{4O1H@XQqC|IWFh z#x1xITF!4HQ|Yz{FXWizZq`|Ng26lNpvD)_kw0he$SkIAB2eP+vu5UpV1&JDBd`eW1zk->hvht439V-U!+&eUXg=##~Fw@HZ z06>D+E=8|oGomBE@m#kWG{RR*7X)5BZep+lH!(~h`z!G3b{bDC;$XgIpM8I`2eKzh zjRHF8$b2@0x0uZz#fr-ikyGtP!Ll{t>CS;-{=6@E6}CP4jbnL{UfPjPPhv+`zw>e;_2#lIt0^w6k?oHmT^&gr4yLXbV} ztk<8eAow`iy<7GV;ksQAf7UNXLJ_@LSfGk&0Q%x{oVP=I$^b1N_}%q6GkuOqOHZO8WKC zy|W@W{Yt9mG}I#=aq3eQL`Hd-C^ZhT5mu!m6E#mH7>}3?tCEw6nkCAS^=oN+oBL{V zjxB=06HqpfMLJ1D^Gm&2`$IGszw!QVpvkyBv(kf5cDVI5+*U(1I#_fhTBmFd&dFex zW3D`xngFp*ed9mRtB2feUxiWZJ;>?k2!52TYS?hu#GDVKcmXE~F<)3oy2vrm-D6%# zyt(;Jb*kbdRC(LMyK$*DYam+jZjIc9|D?!hAE+8SY%(H(z`##xDzAtPlHRL~&Oi0$ zmp{xhS6-nW6fi{@$ZDfa*eEq1ig(kQSW(kdE(nOn4>YL}_#G4_-^!K$YIZ7pP}c9w zk-iFU+jWV#Z0F5V^r2P6%U|R$$M^e(g>g|vH#V6ue*}$W)>r1PIJm&sl;rD=wla4g1V2|OGIcbE zGk1_#EkW4sn5THX){Lyn#0vh}mI-eE^(kY)X(}?ZR*)z-v3(xcn08}pzeXewNNUuO z^RDSfVxu8|=h|yMLQ*Wr?yS}o$621?+Dlqy^v?`) z{JRs<7bc`5Yh}%F6N$ zz#Eu1z7Q6CzbVYcd71%!F3$5un`PoqizUQj8INZt2sRQTzk*k-Y?FT!96xVF!E+RR z#Q;X_fr=W#Lq~beDVyp@kVZ{!RAwzOg~wHcGBe;V^a0Ld~6fzh{12#~lBx}rQ17H(uYPhkYf0~iJ! zf`h|HUzxSJcz9gFaan#q`LA@JQ`T*?<(>NW87i*!nO9uxL}wnB@5q2Y)@wMATJl#V zZLZS{lH_Qe7w(qII*CJ{j35?m6|cBfQ0_2O9N!UDT3lmpKbw|sf9hg$h>>zBVFYqA zw$Z1-)|mh~bC-58$(MG~$(Qi^fPHWGz9DZ5uu;FZo7`j=fGvxZ?5VWvINN3k%|Gf_ zT&?s}lCNsyG6j}n4SH}+y_4R9chQ?M`AT@(G5)TVE_nb6&)z2AxkElxu;l-kTNPDW z;?KjlcNyZ`cFZ%!I=f`As9*n?B1lG{`PmjzKPlprT;I|Jv0=HB_=EqK=f5OR>lBcS zjUpIrqtZ2du$Qb5xLj;_OG_2=3dO8d@) z^)S?jy-f*~hR=kfw?FuDY#vX7mBsVa9}P|F=eR1DzF>aoj6NxmEc zuQtJYuR`tDM@{j~j{J#gah`0Ru|JFY-mrzkt3h717VL4J2LvCUt$E zrSBinFIs*K^%>x4OS=C}y248)djlI+PFeBKA?MX7X2HzUEPCY0^Ty@N*5-ZXUZKa# z^P${)%D)vJ{LT#_cjdF4-tZY2J3$|hViLMK*ImF1GTBp1a^AQLvTaiZgoUr6JeYQY ztkc|;5m9oJECGNk->co9gJ z%%xUpCJfxq4w|#>s>!Y7v7E`Rh8~GLwzK_P3)Ct3JM?_iMn%re{|f;cFUVcs`j$k$ znais~b;LkoEmnTe%l$QFr`~L`$IXgEp${baYFzd==b&D z!v18|v9R(dm>hOpyUaM4zUi+`&2!}-93i+AYA9?oNRd9ZYS3Q5NEnw$x%p*k&*e*9 zo{|irk=YwgfYW8g%-LxJ40%a~CXxLcaT-Uv;Se4z`{F{6+K$f)>E^6oKAZ3H)bb-@ z^i56D;Z%OS8$6{`-uSTOiC1WP<+b!7`DXt8rij&XOe-5L*X2ej$)-qz)$9%0G=__j zjK!hlL22UM=iWxL7QmtZ{m=QE6p-`WbqHq9=|WkioNnC#>E+s$ zM}HxZp<=1~VRTH}{gE^8#C-iqnFr%q(3Tj5d_;%vye81kKca^MG;UaPnJ0Yk^;g#K z*WO0e1;Y3$C6A=}krX_V>4`@%UGHB(*|jJU4F3aw|Bc91xG%d~4yG{xI&tN*~-8pn#3$mUJ)@=72M^b$s_QiJo(7YDj9KmiUgdih*iN^XoL2mqzB{BDuxbc1D74kN4$ZVtxOK>C1uY&IOt zIvLgRb~K+`Kr>tc6LUY7y2PbiXYIpJeywxe@lidQy2!ATyJO4vS|Yfj>vJX-2Ys0=pQP&-H752`JU|6< zO)`g`NBrzC&$pjinexTFc~3rH>GUDLpWM6Rh2yL@|J>Nh;7)|16ldRR=FoB=09ZCu zR{s>@Jb>t;5xM_V%hziqT1oJ^^v(_8AxupW-g z8#|CvpT3vL7Mv#}t7&I0pP1efQX@~UA2|2GJP^59UaNA{uz~S9cI!t@IBJdWM(lnM z%99^%S~;MLyjfg{W`+urtlS28~ucM zZwNtmJWI&t9o2-AUw%83*eRCRx6+^qc5)HHL=?+pChe$16f(;sJCoL z2U5QP=IwVFoAF#(EFsQW0A@(jJ2C=-cP04o?@9P`Db zuY}>LZUF<5ZbjiLlN2fbu@age%{>&NEz-7LFCG#?L6AE(h)dSWQnkubH8%K*^y{i{rwB2iG2LUo ziyc+r$CMVEZ8>s+_ofcwIO(Ilz_(UEFlEDkW(G>-q}!OE~2Bk(#6 zj~-r~SwpZcl;`tW|2hv|gh>5b@J2QXSFJNy4jiwO9(@Q24iMxFmI!`@IQgF0LOgs- zlaos^ygFvi5&TI0LUXQuk{UHEsCWcvM8n8R;6Wbp=Way{``MPL7WVA}*la03AHa9? zo<7JxP_6E-*nl|1hX=Ud=;!-)kPmlY^IN@pP=)-t2J)yTquVvHvyDMTE8wt|lcd-M2OARZC`p;Q7BKFUHydndpb05cx7!O!tT zZh zNH+!fO8=R;Q7&gXFc-IGBa`)>Q=T6T7&iomQs2JTBx2^Z+A;k9C6Tt;6^;!C{J%w7 zFLK0Q{C?2Dmfr@LQR&Ve7*T=i29I~oCeWmi7AJ-snTP1cu(SJr%#lLn)5jkCyBQycwi=-8?I_vMZgx?epHtVCd zUq+QnebMN46NBP#}Wk@x(^W6FPC}v74YZ_ z&fCNDqp0~dNpgWm7D z`6oJ^c2fo_?odmy0G^9j&nbLcIOKN&=iN}=^&-lO znqOG0_yef{yd~wxv_(e&@_`P#CGyC0EjsFyZ3!~fwI`aOFBQk;YY};A_zb%>DOlkkT&gm&^ILBx zg0@UAPPE*$LJ#W++Gu%K3V3#k^m&1>euWudY5Vm1&FM5BZMEbNqnHI1WPV~b;bQKd* zC28ecEji`NTXrUU4+JFoYK^?Sq8T&-vq>a?zB(Wu6r2Rf^*3SNzY|#5lJ8>-cpkcCSeo2Nvg&lB8=tW=0u{kK6U(l>wvmOe78a|^wWPeM zEz4vE*8L81zC8}#jsEyJdnFZUWgoT`cVVSAFE3Vntgc_C+1=Z#!?&SK{;{@#@&b4} zt8Mz^*|ivxp7j6;2a5j*0HC zVQr&1Jtk@FHb^5LgS2xEZ4w2ev>l7bHxZxZKR!b({_fF7JJ+;hrClumnEw1!@;r_G zq~*;TAjm<~^zmdRfsJ;H?&3t%svH3D{LaNJE85x5E7YHqvnV?z>^;F%o;)s46={!R zSdy2>-&22Te6-q*|mEIbhFL!jS zo_`{Wq(SIhe@2bpDg1!4oZ7PBv}pR)!?0oTAf+s*Kq0E&r8XYDMu7^i{76qfMom%m zui`;92G47J39aNXGQstmtcoy~gh8p+TdS{vCtYc;_@Gn(ca9qhTCdlrI&Q>qmZ%(c zzuN&<5b;>kQ;3z=RxBQ9W->rGggw6_Sx0aE#Ds-5U?B}CEMFOxPXIHgVCE>y%%mTu zs+sJ(N<%IQt^buK-Y|DF?|hnu)*F!7Awzw!c&Cr>X=SqpH{xEPLkfTy9x%fh3K~F? z)c25Uc?52pO=sK)Z!RDcrs-iCY(OmCoCbPo5s(5i`H9Gdj*Gk#}J7?|Qa9i5TebZCf1e6Du9Lr**U9OqgN3GL32p-h^Oy6EH_d*7^s0nr*h0(ZX~nC%+nb={JgRRi_ntcw{y~0wWF3z;A9AVg z*<8%KBrSflJh^ItpUF2zKEU{ONPX0Ldq|LX>zcJIfQ=WSyVOq*BsBAyoEBQz9Mc0? zpM0@_8uZouhmZ<22Vg2tg4SC++|P~hX6G}vEH#IzKrDWQYFZ5bUx{>oCCbBWjlXPO znBB8fVZprfL`*dge@qx5+biekc;uE?kcQY8{&w#v0tlRVAmG6O=AeU619M10AVPIt zzkZGJn=SBHOAK%!aTt1s?B9g%>X{ZcQ~Jy$L5lHLBdWVhKqd&P5D^-4hH0x79(<^)G31%YXw8s8ruo(j_L^E;-+n~Yci-tYy<8z0h1d%IpnECo^XGC#c97ZETwf=g z-EAq+j!nU;RjoR5ljaY%=+OMk*SEaa4^0*vgSL)5-+_K5x(=ufKE8oZ0ESC%V`B7F02&*vn6w2| zR}uspDkg6cwrY>y2pNOUQw!|{`!nX)qPedND}v*|4IBqqjNmBs28XK|H3;%BpanpB z0V5g^^kD!S%CHe!0~@%=AUHQ$Slpqa_U!Wm%-UDa!pktDdEtY&(NUwdKiukC!hUx! z?7=9jR_cQrB=lR^t2=t|rVj6s+Y_Kzeotvg=^k|6u42?rJiJ%fX_xB2L^$oC<~qk| zUC8hS=I)B;A4W3|PQ$+0JyOUW`0MAHvzVjCv8+TyUJRd{`ak#-pr5S-C_A)|nL8K; z6~Kq!J4t!!OLfX@j#Ty>Nygw>7a*UfA5aG0Rg9wg%Fo|wzuDEzYujX3U+=_Y z6?ov_L#yXhwmv*83A!j2IG1^en3K)!fA~EWXg9P|-MBX;J0e|hG<$5AYt8RWZ6C5w z1(fZF7oH(3Os=$n=5zzRX7|NCL8E^z=RW_V@XdqH;zf1io>Pr?i(t#4?zsPl#`-#c z;9ITwsxT=q=$P5*#@8-lLk7&fzF!%xpYw~GJjhLbdoYY3Hd41hMtchPxKJD;NDrJL zuFS>J9tz(i~0@+NT(iP_^mvUDeg!}0=J0fNIN)p_+RdWB-_s}J)D~l zRmC2{KYCls5pGvjY;DO9YJIEtCaJ$Q0vDEKi=rAM5Aa3(l>yU`qlOy|G1n zNx_l`KzM+HWl#_hKt}}z$RI?)03C!O82o?k;#Fd&`~d@J%^>3TM}4JR$CQ>!`x6|*lYqEo99gkl(!M<5$B>B;ehi^$7aGwFiB zA}OcH)hDrn;aEe`$8ppZX0M!T` zcJ(SfReaW&$zGKPzEA(HOk$duqywXoV6;F_^)CrOGil5-)JXit-v}*}LA$#|Il0z8 zF|hWU@Yqv|LEEQT8Qdx!xK+8Gl>SF;y%##gdZHP6%qa}|D#gkvI`*I@eT+BsRku$D zZ>l|KrmIq@oHA*rQ_Kfu#ei9V$!HzYn8&1?i;T2LW+*F!DQ1E=?JF~sMK?yDwD6OP zHQ#DJRIwUN0`uWbgv?rwBk9HYtGR#nd|? z1NNg9dMPv5f9PP>{!=2Lm)032A5wz@2Txi(UrtMx33r-61;Sq}vT3gZChCB7dSG2j z_kWeZ|0%q~3XT-8;znhS&mU~09UMsJU_&+FKr#de(*He7!W1@z3GOE{Sd9o)2k8in zNHJ%<%p=g?1s}ry4g>!+9{=y7`(MMpoHwf^QN)(sV^n1~D`i@k)gydLZx^$)ya?Mw znW8>X#E#u#++;VeVOrX;JY-e}rFw=$Lsyl*KGngFeP-OGBELaT*0DT%RtM|vh53Izb2o3fZ>35UOQ_OJQ`9p%?W8mpNs^P3-k;!nNnsLRKVjq|AYR2$#Sr`0xV`pnJED`{6CTk z3%EIXXQCRZN^h$6`DMJpt#h(|{%Buu)St>`s4gX65 z|4IM1(hV$r4i+1NQLwH5k;DLNWy-6*Xt7kXgB$+O68OJ{Rl%qZSgZ#YgB$LWzXAWL z^nkyq*@9d%Dzjh7QC(#=L;bvDw1`4*$RHllS4YWt9OzU6XuI7=aH%Ezi90XKmxYK>>J&wW67Jgo`S^!ZDjx*YB!SNb}v}wDam!?)47ZncPbl=_v zfppkG42KyN4n9ob1~+^8i>YW4)x=FfJdSU?qVvF*?Q_(-!ngsn-Su-x-m@4B8gBnC zS*x4i$lfy~qR1T#0lX<9Ke`f5Vr2^d?68u6VYyp-3SF1X^fe1X?w&4ZDnw5oIwII3r8oPY5CwMs8;YP05{&`0!Yec&W>+V18!+V@|MG3oNz* z#yVYSZ(gnn;rjE|W<|7NINTH0N7CG{fPBYrrm#dt(io9Iu z5rrf|YGP?Nz+xF&?tx5?Gq0c`MEIr!Nj zXq(hPVG1TnVH63r1|ctb70XK@Fa7T>T$Sl-s|MUX_!PQFAX*rKz4pl}Jmf_mCdwF? zTLR`jXMHI&Z}8pas2WUoek=z6K;TAz$+F2Lr1xFBwk*AHRhwI}tH>%gSoQY^zCv8I zg&sFzXZbo;h<+a$4zd~HWzB>(cbXPAlo*H}rLC;{w#)We zjKIfmRMx6YJ=a4yulF79s9flKlb$=TOGWF$j5f3T6GD;q=-KjNqXo3d@}r6R9VjLD z^=XtmPzpfSWLJ*$dQ5J5>Zl^}F;#zYY(%DVLQ{vqi6q zdsoETcCdDPA%?=4JW=%a;vBpzxO&e)JV9j2RlwP7A!iQew66w(j}FQDCK#jtY~OJL z(UfbQ$;7l*yS_Q1(4V=}*3JXBuyYrDuBQO-k(3T+G9vr<2N@7?!&P&jpGvVb|B&)Y z`XQx=LCgN{7t5P~Th|7|f67{P`WYk{efVCub`KimO6SgQ#d;-GO38l(7sZTRpqsP5uU za(OH%h`Vn|Z_ugYg&==HCc>dg<(;1YNDd5pEDxaGWWZ>-u%56k`q#_-;wJy%Tb23lT%du|Nw;PP7&qFE|?M`CS>YTW6D%PERrkqiH3MXiB0 zO&qk7s8@}1BHjKuG-ZX0rHl{{n_KtXyjX|a9QazE9rG^mc)~_U{tq+-!Gktp<&fo{k9&ds;Hr=x- zUY1!BLeWDzm)VG$bJ6{QX6gV5g_Uhi>0P5zy+1%3|JSw>H|E(Ug1zTa9vpolX;#^) zpGJ%2wsZ>Im?xT&y=o@xYIf*U-0|o|BJr~2l&NJRM=3k{?S0it)z_=9_C#j<)Dg22 z9Nu0ZYB<-}zby{>QVQN2q-;M!vwTyx;@SqG$%!u^njsPGEPF!kWMzETY>JON=%YXe zLy!j`|C&!-Ew3_$(jewiD>i;PXL5|m*zoYW7a!EEtJ;8Kl~pC=phgPFq> zr<-%l4!^=CVc5sL=QRs%+4xPPksttW*`!Toty@0FIeWhbJx+d!c%O6%rR*`&%nc^} z(?QP`3)9G1(nq(Z9BN>PNOevaAwbbk^ z&7B=M`dsq2-DWKNs~@(Pc$!Zw0%Inog6&W}!JMKcNYPmdk?+df8TbWA*uYhZA@Tuh z8*|0Zxp;ZU4puAwb6<8BbHcAR=s)MYB-Nb?I4kr|iphKdb*($BC}Nd%X>QpaK_<&@ zejz&He+0jA0m=R$Y_ivaOx9&r$iFdDR`P;r#;)vYy!YZ5ZVEW|fxe)_0C}UiLX?Nt zPajor?lL}o)Wq={Gny+$3FtAJt3-Lo`SkG_&K;t)X$R#MyS3>6<&|Q8bB_3tX0(T? z?`kf|p6C1_F`4^3PP9J71!wdO#YIgtKgGpUOYYvoOCVbM?xB;o_mHulIzW;a`S|v! zHM9e;#$3OIIgg`YNRl|@>i)wgr`9DAuZPm=5F*q==6@~^nG7WLs6 zA~Nk68qqDlPK&-+uas9CQ)f3_GiNW!=CD#9QRY8ITX3QNK4L+To%SCF@L!yN z8tM?qx7Xq{|GD6w;eWO8mjTYWu?yy7jN@QRdl0HTg>DC|Q|?-wZN%Nhm?l5SHLWea zREJ~?rQ z^9B2L{Ua_pVykjG<1in0x<=u~S!t&S>2imh(WPg2T`B6GP`k$!u_eWDqxtccNDfX~ z4c;ubf9n@HBjns?jBM{Z8r6&jE+>A=cZ=-)A#aj58pxjLV-5AlqN0>kH&VO-)nKkvPWb?J&qTJfuvfFfDOj!+*M($w6E;Yjyg`Xy>&q! zw;a$f#3w=pg~$k4uup`7#tJVAt6eI`50$>lslhYo@?2)bTo+UoMw6J?CisoW2JO$B z&aIUrrpN{TMiF@cwyASNFnx3sI@{-b7IlMffKZ6Et7(K0{p3p2ZI$F4qY5Q_AQu+( zIwrA%b`&PFwkOT>a)mUi_D*z*o6+@iB{h21haMkBWQ&?*pByS3#jb^PdKP&NjOM33 zQ1sjH9D6@v@A(Zhs6J49n2JrByBBrcs(Fs;_YUyv{usHoRovsrM;1sZkmawG&S~5` z`#~d{zA9ix^OoBjO9^3jAYg*(vi<%Sc>4CrT>fynoUEIMi;w91o zk&x27+38@GV$iK$NW&oFUjEO<+l-&cV06V0a=!7G(p6v85 z2dEl5Kb4oDR{e^S5{v2vmaU*)ombm9KQmW!`twu$c}3)5*3nyhjvd%vJXZO&!~Dal z^O7TI-HWYz)z4WSws*CQJTx9OfFH9iz2VfecX<+m`fa4{7IU3o+aEJH<4#kf6J5x9(M`-SulE1j`H2%S0|CH}c|~ zF8)V8aY&AWX{$@36zbX;eK&RJ)Lm$;ou7Xc7pTQyIy1COdiva25G@qYf8>6k4t3e& zvNT0)+}sh()|Y%kW^muLF%{bNam4t|z9pIkfsfI-b9RRmvE0!wZgAHJ&_dvHim1CP z0Ix(loXUr_^1@JQIL+faSvXBxOP3k&Ua)A#qT-6+d&il6H#L%`^H<`kn|G!5&@lbS zqch*`Rh!Fo3M(eI6;Ggq5*Ilr9lS(0#40rcdH8a0{oeW3$+nMSrMm9Y8+G;%=h+gp z>c>E+bnU1Pwe%I)Ng&$f$`RX$6!inv)=Sh7i;<-_-18EcV-vq1WbfAQc)O{8jONl~ zChm8OS#mu$Gol4?9k-i0mdM^UnEvsIwh!K>V@;lx1r_K~1^BdsPXwQTRU+=)=IO(! z?^r{ir;Px5Sd(9Y?bnETaR1EuK29B)nM7|w*D2k$Ho_Y!9qn|o5<<*AS&xL|5-w;r z8;ma0BTpK*X0+mxa02hJis`Hieq-4_SnW-!oR2x`68T6Cafwv$V+!ScUIN#hAZb{- z*h3vSoXq9|TsVJ~Atvbg@UvNk1ho{7vGL;)Jyhnaf+-^5n{dyMxX3iEvXyvck-X1a z)QCe}{8PB*ea)X%7%$uWF%6k+QIy4tnCtO9LXPSj<(kccz$EDfjD#{f;mI&K?!Ut{?TuqT;ViRi|OdTp-k@J>X~twJFm!DwPN<~T0hD0 zaWf5$Xh2 zjtoLw+rURiG!-RVgZ;xOyhVLzP*3#J<((e;{s}%T9ha;(?$H-emmF~QKuHeRky8}j zh2zH*l9(L!B=k>UvdgWiZERn8bW;Z~GPSJfZEVx^QN;4cYPdb4R(4(~r0yE*pI{~p zTeAZrSm`cb-neHdy!A5g-NwY~){?j7Q-u%Z5lLFax!$1(wzcOAQV}UMPDIU19^J-N zr`J-o-NRP@q@`xdH;@~GItom{Va>QJY%w)!Y1r~9Vz`u*)-`Ahn=qB}HcPqE>P?fF zu8wtSR;OW457bkmgzB?Axv_1Qm|?9VTfc1yOH%-@(RSxYzSdYo zW2aVyZM~E%62Tq``?wF*(0TO7sd!{0Uxhhkr@%z47RQXIwQlR4TVlX;!s{cY9n2$Hh$6?&bOs6&uaNgM zE%nHu4w6aFG?mMOf+drR&95|NplynwBP)~m8T9!TW7}x^;XwY!F}sjVbkz?7cr%nOm()*z?Dl<{0gu#68F#`sA}47^Mu8pB8J61@jMot8<4o{G&s z?owL%Uy=7=x3*Rra-xPDeb;shHgDur%t!2SvOVCogqFDV5{eZIY8Hj-`aE-H((c?^ z6z)(XCU7wcIE$9Tpellw>|zoZR-~5O>3-TxPPoqy6mOjt8M(Typ1QI`>k>$fgzncm zI5drm09Y!YK44jz5;WrAU3Pt2Y*MI$5PK)3^zi)*Ntz4RL=AO+ChQv4Ng(}T@~shx zRADV^WfZ|fINe)xE>hoO^Yv*h*2`sV5?!Qp??qic!oUxW{t@B(1c)9NB0=#^jdlm{ zg3eoCSY-%SH}~1Nk!_=~r?wrrG|~*wLeXA_EfzI{m{R3QzKZf#MpuvkE7bn*pf0n?Rn zwm)@MEqW{QA=WuCXQL-Z?J~>{K3T_mp3WyLVRbvDc750-E2C~1=bdMZ-qHz>Dd#Qv zV@kD-eO`P=8C^c+;K#<( z*jcgF$NknV&i!>UiEsXhZ_KhwCm?qngTStL6fJS!2D2626_^g*gcZv#zT}Yn5~b9h z10Kc2H#LWfyz`g_+yi)WDq%HZxns5w-c`8RI4!nu_*PZb@8ls~Aqs)yuS?19lz$H9 zeqe+WPVm<6BI3vI*CD8N9%EK(c0$NI3cV@RI`@T1$-5xrxp^ZrUV$6<)1|8be5~d; z0cMy&IHTQt&;|7e45axG>q9qa4}Lub;+~6N;!BHqY{SC|a>(r36&?FdmoRzmI!dUV znEDQ6bnOar|FIM1j7h_d9U;DjCm+MZ0aM1BK0CpKVZKk$S6$rMqpY1z$j2s4P+xT& zvn3F{?$TdoNES++3#-Fr9L@aAZ)oA~h{AWB*=`O$}j2cMWFD2|{}? z>eUf!T|VE0U&L8pIhj+-1o40M54vEpz|t^SnRps3C}b?E=7`0G(#WaR5hN_sF7u3u z3uVBNsn-HKwgyVrMNV!`lY;%d>sY^^I^59y5wg7M6_g5`u42X3EHPkC9*OKLcao8F zju#;>uU?5A=*)yuU@W@vR){xk` z21!w{#k!91VrW*;V$1weaCt@h^~v@<+C&qR-5bolB>PAH|+s;M5ISug5;8UK@h*5V{6jmPQk1yahj;$ zH$nk21V|e$tc=nxQKh26ckxpGMX|=z0L3ujBM$8Jik-&1t`rmM;fXh|% z7Z$LRV_XY!bIm3@CBPkL&eo0!9;-MxjFOfVL%$xiyj&VSHSUISi3+>Y65#+=}miD_( z$pX+L)-sK|sl%PYe_ne8?=a&XJUMlb+Nf4%+qPAsfcqHV>Ni6x4a1p| z4|lo_9ghcFhYu%@_rJ%0yJOD|;UlE$&+9uBS2JnA-OPjJ)63jXw`0Bcw!05gUmxoa zBzZ4$n{LN~GrC3!z?<#VMwmR&o}zVlCKvO*%mbI7v*4m{x;_0iW`Rie*2=+LZU23_ zKX(IX3Cs>%NYest@vzw%IP)*)|JJv74(2lZs^$L74V=Xn#oxso%vJukoR*N?=l#c` zr(F79EW2MfEus3a#cbbWB}DcW7ZSw2>Pq5t%J40HOtp_s^58s0Uc51qiv!1+FaeXAaQpw z;gI0*LOY)PYUD9|CVsg{$`phQa$k6V%vS|@CN7BLZQ4&}15a(}abGbS+Z87ZFmMB% zsz^KKDR_8EQ8VhuG#W`4r^tn+`=_rzc!Y=yeUm7x#@0~&^|no$Cd%a2u z5)~9}6Lr+eR!?L$Y}{{`YYcKd%BdC*C#S;>NnTMA@HI&-vS!VR<-RYU^v@POz3ILs zL9e0b2$QV(M&ivs2{mWaF)Mt2^8I697-9GM!|vuYpC!8P7iDXB5-$u7{~9O%8YV$+ zQ-_GbUV=w}gQH11%!ZNx=H~WJ_U`8994_AK@sf_cT$p{H0Q#H8dZ^6Kaz5b1L~i=g zow@I8&duzXy~gsRw$&W`vj!e-+gTi7?<>;w+}A{ihGX;i{QBrEAW}tC(q~Pp{Z_qG zNc%#@ue>#gSR_hUN_ty63#W-6Q5WL)jy7z<WZU;Y#=1z;=NZcp z%aer5@Jt++1PQO7{v=7m<*v5xM0 zK6ax$oAJzgmp?yoRSI4rt$j(L(edRcTzw8GyI}N?1J1u|o! z$(TzVD!lsLT*-xH&cs00YSLZOG#%K^T6=k$X{(0lTVU0C>*9a=2Jl7Se$O5bbm~9j ziQo&j5$-iUyMg9o^=wC=iCEQh@K?lH!dc%$mMZlJQuISfjwFx-xj)>@jsGYdiL@s! zJZFQfxN7KS6WeR3lxvy`)(#(T8ewqHUal?v_MG3hczRIz*ixf6I=P0}wiJvL$Fv}h z`l3=w!wT)L=SWOvh?cy8Hf=i>SoT%ZQ#bj%TlS7|7=>5qM|DrK!FBPPdRKL2uhl1} zOAor_CziND2%N7zWnGW3_J78fnB1@_>?NvT*Uifz?@50 zavIvktEk^HJr31tbB7H#i2t#_6PpCk+`#^hLV|;%`@6qs6QQDj`?eNmf4lD}=hmFt z{FBL`c=WC@;}Jrp4+U@2rK@@CrH~Nv*(r!8I4D_jZtQ1@`;NkAl?y|Jf6_N{yJR=m zYi6cNFa}{+wKSPXaL#7-9ZM}87+aTB?h_hSMJL((>6*jumvICV6- z#^;}TLV{>)(2sWnWb;-q*er>Js~x;}$`(GPqE0!^%r6r{t^ZTl$bqJzNY?J{VY-ex z6=YR0ygThuhRr%(mfjC8wx>W+ucu1Uwp6Lh^bM|ku%&MOd&Sbcf~QYHjwwD_-=wg< zvqd$FSsfr)Uo570lWjHsvUj|QF}mU2>W^A|j$Yn<>z0w`Z(-^aX`Xq&Kng$}D#>eTF zRi3WMbus?OXB(3zNeB)d4vvEQU$3s&B=FU>D0H!8-c^Bsh{Kvp4x);KOe}2)VeskMeYue$zZe>UMkxWQ`^sL@k zzJjN;ArHxZFW8l~FOOObo`ROtm;^KqD6# z&{U+yoC5v{CFMz>mTS&$sPg4l+&L1)`iQjnM!JXBRB$MeJG%TxPi z`xnFZ8HuiQTpY@8*^OpYGIlT134Xth4DKshd%+H$KT3}-!cAP2FNSEa)KaUdo}z5g zUU#@|rpC8Y@+$Exbrxwu*=@xp&&S_dUQ_6uVe?(;lmbip?tO67mqc0ynP6hUG#=Tt zv*FJiW>Oa`$#uK|Lqf#2R9Ow`Y5_0qI5yaWxF-yw0 zPe|iVff4}fXj`v?IQCW4V)quSSl&Cm;Q3HwZ=mlYS$7`lbTBEqsy^Pj%}ES=JVUd+V8<~d2ZaRJIABB{S4 zG&rrQmT<`xk4KA&T98LmJ7pA{65yWW3grfCYiq6rE+}M6Gv~%zT68i(X!!r&7=>ia z5u9`S%&zh#jyo5_jW#f0IIIU3tdsY&YvmeA%f7u2+r&$+d>xPX(bYJOM_pFBQoV|w zzk7`e_{d;#-?Z$m-KC0E64K2a8cr%M^ykx4BCPK3maVHxJrmYfM;C-Z^fC$>aj+PiRT}) zv8T>vV#sy!E^|wGv83)Tc6XPO#2gU}>SvK=@k#o9nF_gQ@O~nfWcOJ}*z7q6XIBs9^yajYok)-3i;i-Qr@C_@ zU-vVXx-myWTx8AXL-++wEcO?mZ}q%!+{n8puO%lK zu1No8OqCFApG3wY+azMr!*LhKb!5uU$q@&PNfc9QjxDu_=Z=}$p06zXIv=(+8ZIva z{$e=l6gR)z-yAQV(2C0*d}Ld}Mdmdqr$D!ch@BseG2_5%vi>;!YLayq3;&(Ht=ppF zo3G=P1*x~v7#ZnC!;8zcKY!$Q5P4*^U-#LHxx8qS3VW@0ukrjX#q{ykZ|1=A1#WjP zU?qO}m9x+E`)~4o8g^gf^*PT5uh*@vl`$xgwS(o+OJzbQes%wdx?>-9zOHeb9?)yF zWE@yOC1F{uI9)2UCVsolisu~h@`-ooO50P8HbD(b3Q}ud8Qr8|{DhZMR&AN7MTFWUPw2&e<`1R~@4(0I6e556StnN0#n zaM3ze3GkA-+j@r%VM$W=HLP>wlfs`nh8@bXI#Oe3N=da?Zjh(nM#^!;peZ5s_>dJ) zYTK8TR1wle*MfI%J#_3giJWn<8WSY{^kj&j9J{HY!8qodpT_dKm8U^eH}qNGv$>y8 z&&ycPGpS<-4TYbhNfnIxv;6Kt(B5}IZiMS5}8J5r~!RJ1Hv_#IT zD%rjg#gn!fc~r!&)`)!1BM~+>H%#ow_K7Z2#~sqnQucBL_O_2GCZY2y3uwXH6+FU+e2zV<^ z8Jic+1gftby`CEt{5oJyBDUkfx5!a&Pb z5HrYb6Q)^IYKalaK#;bYOgcae?}u|c%S4Ic$r89qow%6Kq=CAZ8E8s8|0Kf7e2il> zfC=##gUC$Fu~}Ndr;p}4V!jEPL0n#(acG;R(?=bj%H_b0Fq`X0gv7At0yyn$c9m4i zACs!=?My@8@tqR7h3pJl(LOZI5r4M~$;4R4*G2upNDSqL=~NQE;om`NvJxnrAGmnC z;J8y|Q`rD0e!h|TUcu6<0t^zouXtI3m4ijeu+%bztJFyLQudu0!jw8yY+m1eH+Axw zuCb@4ux;GZFQqk>>6#ZYUFbx3ywA$F*{fegYv0xca>*rBWn7?}rz=>`Zz>eTOBQqZRz)Qje^9P32V`i zlSkB6icaC9m-gh#m~-SVZ9LdZdpubOS4U5$WKjC3R$|;pb6@S_AH(+-c?H2${?K$p znINMbjS&4asTH@RH|GaXdcPHLX1QM$YzxMDJWKv*!yNtDn!VB~7r)`1McO~U= z%x44oCx6F1#tfnow4Jf`Xc6c|!UdF1Q@msq{Iu^7OEJS^5*Y*{J^1PCk|4ddj@?uW7Qr3M);!<86p%&8L zGccBVr=T8u+(Urav2}HgrbA}=(;oV@KDPoR%KW2#`5*reyMdC3<~s@i7$qdK2A^K zaAO%B|Lu=**o1?>g;-<*G8~*CZrY!0C_Av|x+nnk-!jZQ2^qxgc_Xr;rcl1e#gpVv z@Qhg)JXHYY2@MIeJQv)yYSNuA5u9>RVq%F;tuouipY=ahp5DQmf_i!UBdEcT_L02F z6NH0E%Gw`FL!Wxf#?$$+LZ9uW)poL83GyxaorSwd8y{rl<%aN5t%=PnntkWk6Nd*f za0`gug#_^B$ftBYuX)p7)P;;A#GIa&c#P8dj5pTc)iWD8ykxvcdjI1PEAE*k{RM7bk^J} z$5EK&Owq^QgmbRfK8j?7ER657i2!EQLj|jHsB>=XsV+aBV3%5w$HaVFnyQmCdp4aL zt&pE^^?Hzv6ze8wt!UDBHZ?p2e{6Ah^vvOBu6fvL(CifBp_oc=>=q_R;j!P5YaW7l zJH)bQoaom<;%oy{jJj<31!ACUO1Bf@WCPyH>&27Knm0mGQm+|ZM1_~}j#vR7!ML8( zZ*M-X!&hxDuAfZxncMvkKmUnc#Le`)PZrwTDMi$!05=D%vk^*XHo&wPrs{E>i(pCO zMVbt4S^TLpC!-6QmPWbN!WVk78hpwSWhSU%I%U;?v|{*^zzNNqVt2C8(qX>k_zTs6;9~_?|X;R+HzLE z9IcV7C;agmedKBLYK1r&oQqq1Pi&?n<}D^;GY^b;pK~+H)<}G^e2vHPcVz#rMfBZ%svo8AhhE?* z0?)D5?I6DqF9OEj&Hdh71vD!6{v6~Vezt8y9e=ImXaW}@Teq}?3cnFM(A>4A9w7;1}CtAv`TO`{U5L76N5DI48gQgCi~ z|0ic^1&cn#oKwS}o2SNurkU9p37t+gL4{!rHnNr#b`9ok0!PLyk3c9XD_v0vlcAu) zS1k|nMb_Kb)y{TgeQg+TC+Mqjs_+_Hst z5XZTr1{{*nc>fWyRv0i{=UkwqWO4I4e<$Ht3q0Rag4);{hvV7k1)^>Cz@FY=6-3>U z7eoWt>4<_X*5Bbi{@K5psUZqaORlo4FhEPC`$+v`p)oF#n4>auT;t@OS!HOC)6Bc} z1V_bM($@t8zuFRvvp@VX)@pKj#Z@(#R5k&H=cN+K9Sc}Dmvr|5wof-|vZa2bq#j5Q z2)jE-2S-=?+;Bc0D^;aRuwWHn*XK{49*ZiMs`L3@T%A*NCQ-MwW7|&0wr$(CZR3q? z+qUg=Y}`dRn_3;ZTw4>aYX5p1XJlTzQqBmR9oo- zx1E2}Q9rlLpJF~Y4^XsQCj)2w*llNz*OK2PVtf`}(KU`y0|$#HLSKBo)KvXIrR0ZDG1;a$EYfR~2oJTq8p&NSD>3&F#*vCBZjN z2^~%cb3T0k1w74wdubE}v#fXm^M*uHX%py~mpj!Ocv`a8r~`c4eKRwb5NFnRa`vbm zwTv?s0GGTs?Cl<5mSW2(Z#v;(2@!@AyT74yP{N6lrhTKqv*s50$A2rc1`F8dAISeT zLH@J55zap{#9;vedD{U2k^FDViLn$35n$tj%aOGAOf$Nyo|$sNwb5=cYcc7Ba+g-+ zEKe;@=0--N?Fg0Fj5F&9DWVi}^7(RQ&s!EasF-r7>)vdXO6LS&$%^wO%rVa`+oy9( z-8l`LIWV`OjV6_7(WL5}Rx_1ZlWb0uEWRp}`a=Xhd6qW4Kcd;O&GBWhN!2(R1Q~QuB4xRGT?FId$5vw)S*LKAcolWsAzHsny_m752v`Yx(Dr7$2Fcotc5+ zPu2*DBI?FZe@ow0RVls*A*j3%0G1yF<8$qYINp zN`>+jfCcuXHRqL)6$DL8L$#^3*g-UAoFYWvv7V)I@RSctASb8YsQG@aEjBsAk~kn0 zFN;{lPtb;FUvuCl8g3oq05IdRyvImyqeDN#2Z7T-%GCBEC($^yqnb)#9POL5B(HOT z?8zjFCqBwx6kP{ctAJ|KB0nL|qkT;DCigIGZ2K@ztGl!VG1j@ajo!3DsHLm?()b0D zy#-o#Pyb8XhbN~nt)?hqAxUA0EUP|cczb5Cf&gl zO)$qS40KfmKIta>p%YtG*TY{jk)u=$z*D-guXtd+q`xc|;cN#m*swG4JpU@n4%!bo z(&e>gU^qMI_M>V@PA~qX5<()Vo3d~?sRqo7sNbN~%c!Gkt(vutH->zC9U_|#}w$C$-2{=9dWXTF(-}?#|Q}#mFEY5BoG<7 zExFPi2g(EH=W&C>7S^Y&1VHpf)?evl?)$M97QL`T?vTZq?>P?Iw_=7vcL<9T?Y@}rA$B}tC z-;-8d!{G11Wjt1YE8@#sHaL$ArMfSjxmi)=OmyI$0QxX(PQS$Z^sVS-v|70dof5~X zwJaWnDm1S4&K_$v>t$1@d;9-o&S0Ib>1Upy(HXOkLk7kH*TB; zPvj}v5D?94*GplSsxqq^s3&sH|MBL6P)qg-v`c)1`L3YcUCY?gz#B;dxh-7>OjKs* z5MPUVsLkvMvJ=`hu?l~~`R}ED@bSqrfZ*3-qCEK=-(ViM}9+iCzJJiVXAqKZHS>o z@{plZeBU#u2>%mldvUPJhaKzkp&()|&IkBbmK}XG_V~zeq(T1j1eISm7H4#^b?hBZ zSbzqIU`+mMSFkDWm`$nAI{m45f*Bz~y1@{TKuDDF7Ir4#YASO6U(0T5Z9dY^|#l$a_sN0`3GN z0Ay;Gq`~qcqKb6<4?btHAmc@cuRHhVT!IVIuZ@ig(ed&%cEerO8ug|eH+TR~GY8kZ zw{{L&^Iz5QKRW1zvNGu*|JqtMO$_QUM$L8YlLhBnDC26cfwdwCL|JCCpYXGtQGUE{ zNzap*D$Eesc%04%vONjL;)*%*FV?<4cAKz6`h%vA7C6%HxK-q&EXwG%!&>mTAF^Oh z=nzrIpQpBCws>-Q1HZ?`%h%)sQ-Je_rSpfgvk%C>y}TH0eZTs+9)5^=RK%NR!m)o} z`mwX|j0C`kwD=Oyriw_X!RqE)wDGy7G0l#-PqUG>>>ZE*0~*@i7^DM9HW!46|Oi8dND4UgZMKv)H7RNg3FL|inV zP_R6bd5-#CAn^wm`4A@8k6+mi0{{N*WFKSn=X^iktnKx^A3k?;6l+q}j~FonNAnf{ zy%&&e?<4a;EOegtcuUp8Km$Hxo))^`M@&jBlA6!+UQ-?SZ zw0xVAn)&9hV2akb>BDyGXgobP6jDG}rwz|-AAb5ofV^!82<$$EjHGk6-@_VAYu`NE zUDJ%u8@9>nPRUpD5QuQ8s+pRFu%T_LJofu|VgZAvXxV!a(|P)g5bLI6wOw24Hb8|K zEv-Xt)KPVJUKI)n2>`+{8JJV$kJ}7YF~?w(D^ zS-GS=xqO70W9neO_zV_1|#&}euBjKY^-r!e6;3p@`e?{@BElf>diz(S|iB&IOKrsOXqT_a7) z=q3RTfP_mo1qFgkg4|+@-!;@VWAI5`Yp|YbW&~5wW3y|`OjkOKtpDZ=(1;wplM8T& zM#^!#ptTbt0tP*+Ybu%DixSRX4D1ruV^CO(9P%n%MM(hP50$>&Kn%jq$^G-Ge>R^N zr}r>;Qf(v&(EU=JEu8;a`R(Q^T065#0>S5-lF{qyK!|g8G4k=$6HPaW*1oiL-8O44 z)~G#zxe=iQ6!EXlrSsx8>Mlr9=0NpY#}P%`-45O$z`ii+%9g>A+br5`8`{Jl=r}Ea zZX|U%z8XC*00sF5H(BX%dm0hx!D7>ShsekW5`9mA3snKoWLqKBNkIbUu}-r0))~w1 zm)|EqOm-eo-eyK(KMz#u@h~#%n#SLfzElWnBN)>T+O$I|84?zUH1puKyB=T!mK7^Z z#Wm&&(9*5{yrxMl8A}jt_&dWoh3eowaSw?b7idS81%PW90Er|eru#?WP4W3Da8U>~ z-5u%^?z(3Xpdai~?y^~1NG2hoEL`Ssch*gNWGM(LwCd% zv+(7q562~l>lo~0Yzn>HMefqDgS%ZrO{jy2x+-4=;G_dk#w(Qbeoq{x38*AAvQ_Yg zyfL6Iv96=oDk(gcVLY$Kd-$(nmRyX+Xd7Q6CvnO4S>__A`!GRcZ$BTe6#)St{nD%e z`duRL6sQmC6sX&Iuz4|asR$yUyk2?yV-9domaVA1ymt)A`YHbNl>x+TdCOc*R83 zTdk5Z>e$IwXMS9=i!kT*9kx5Ff7lBu?d4iFnR;{cA&e zJ<;V;k?Lo1O$tUTy~?yW=5juu%teEDQuBE7^Xj3_lR%(nxr|&q zM6wHiX1iPw9Zr^@8_hHPeBvw>Dq}HLm&|9e4K% z7Ic&CN+csDEtD?`mK9J0J0j=ntYKahBt-D3Ks>V;^+xf+ubNR<7zj_;EXC@4X2EmQ zP`s^kA}{2`Nf_R#CNpdSzI!trt%eH2shMiZ`L|3=$O`Elk4pGUwS`7yVjZy3jcjP4 zRfj*$gj@1laqeVpH;z9aG#&GJq3;$Rw;u%LN5Ec|e!_ATw4FPVq;I#;Gv(4M5}fA* zn!ZCl&kQ2R{E^oY1778+cKjaKP0F68^P2~9Y6gk?e|(kvdgloM&o1@u(Nw>h5;o9< z)s$~h=;kXqMg06biVO8HsKqiV#;~{;+-EankPSG|3ERMF_=`2CjQ~z=o#V;wAJ+gYe=U=e6XeJH1to=jr%ngbM)VxZc zs+Rh>$<~YGKP2g26A+zD&iQ;0tJX2OafODdw~1F^aTWh{@Nsx_#dumKD9F)(_xgoS zM?o-IX4|o$^xD9sZ3?PA;5D!e#Tg%c+xbmDF0PBjZr%B>BxnBwH@vu7+x3N!m?)BAVb`b zx`MBU`MR(RfWx>^x-0MH`?@}y|L871K;RjXaeYp(lxweVO!s>W`1mQ;PK&4>Mnh10 zd_bF=&^3B+X)E}#Y1dy;SoZmN7Y_2#x~>p>RE1u)iJiQ+1VYt<{HSRpN)O0i& z%+|~8v;(N&`3Q!E*{nT1V2RI`WyXFb)>>SN%G4*45A(o>vMVE8YzsG4)|51Qa)u$9 zCf72+$)4iw$sDt~9a$cqY1WNK_q&f{VX$tasuACtlVwxh@If^udm<0>+&8OZdFod~ zUVW2I<*Hb*1L2{EDj55jv4+koZi#QHof-?zq(J`UHs}l`vUcTnIv45U{cdPD(p4Ynu%%O6o2*a$2L^Gw8;891?#%k`9>emU#SwWz0++>5sHDjZSkdjat~|_D zO&wQ5E@~y?&#;ezj~-_>Al*`g=T00F&BQN}?jR^z+Si!W{rzJ7*!G-5>~`s2ixVgyihyX{G)*;PL*w-hBCta)rlxlR z!ArZ4sQK3haYUUke$08v+`fx|jjT+D)QzSXE{7iSH}z&Hk-Z=HtPJsK-6iUDbn$6v zcVxWZb8KlP&bu%LAWzHsCX*lNfp(+A_9kU*T%1qQNXQ`{@DzS|pDzms$25~9)=Go{ zOv>KYM-uigV8-`6vBo_G1s_hrN38?avOc8-Xl`8t)WX?2%H8@O7{$2RWnftotGtC5- zTeUw=r{>YfuAt!sNAE$3=dB*mMirsT*gmiD3$Ndt^S$DnegqV1fOL^2| z-LFkDLK5y;5gcJDX&2S&WgeLiRaN?4jW=J2wjJxBlbjnNjDVkMN-vW^N|QPd&v<@| z7R1kkh+*OJtlS;Io`_ZdUD=2@J6CWbHGr^GNE=-bn6=_0A}3ie3o$s2-cTqfr+S?o z8vQ~i<1s`MtWg~`_&lLV>Ld{$=l-EE$&s-8=#x=bgmzV1XMYu7kIUqp+b1q7J<|L4 zeJo;dv)Rf(`VsGoD#mm5VriOTqmmh~xMFMl(Sz#(NK4Zr>of4iUy z@HU{=Y!rF_>MgteokFgmg*}$6CisvF!D9Y6iw>&+5X@G0MfM8TQoPP1brlGbvNqEl~$egCG6UpbrSF?xQi`5Y`&Jlt`O!f;2}T z)d>`#b`Lx;kIqypn<(HP61?z?j+*UfcLhjVA0}T zZ@#(2%SE%_wDF4ybfzN21pV`x)0w?pg^407e(&G*#)i_-N8raEm)aLXyz)u9nI)T> z4+Rjklljq7<`=b}>J2s@GRd5Q)a3KRp@#1qKEQV*DWU}hoMAI zzhY@dr7X;+oQ4xQbLx0cN~PvW<#JJ1LQ#^pQk3zifIi(37+@ExA@S{(TV<4Q14*8k z4+-)aRq&VRLvwKC@5q$Td%(<9e%x*zo>mx_z>=5}_GW_Ml$lah)qHya2ThA))ChBO zDq3ZYacb&d8(x6 z1IDCcX;S{GT@o-^>SBp2h%IRHuI&xeEaorx=hJ^46;UI5_f){c>r;t&I98JAhY zt0%##HOMP0?5u?RcfSHC7E9-^CT(+O_J@*(sBc=fe?hG@f3wl0a=_1ug`oT^bD+}z zo@P*CkYPed_j@MZV*nct4Gm^Y4Cw)3>ilL%OK6!BVQN7u>4(PVI5xYN)-|UjRB9OF=978qx^;w3ze+VpR+GvB}m|@Fd@`RYKzAX8$vUzhuF>>#*#=^1k zZkSw8O_L^x(!94vB0Ry(iRKg$Xsjp(Lzxw=v>|?kGB0MRf|@^aRXAPK!yJRqOM{&I zw^)ha0?~(oBWa4lA2D8a0kJS*!=_rr%aCyz4>`EV8z+ zE~Tdq5PyLyJ;aIYvXHv$P;ox=N~oCmWd~aWt)a;#@>w-$WTjR9&H(fCZUD$TL;8Ho z^}WC3|NHyuvDdEX0hHbp_x_X3kPeZ;ulk+m0J2LRIT;oqPPo8qI()aCkoTeXN)3!apgAw5n4UcXx)6`K!czwr6% z7Em6F|0i2Cvt+46QizqqDM~y0PoE&MFyT{`N`^4Za?1uCQhk7_BW-7A8dAJ=Lk5lJ zJH@jF<)0VgrFOkxa^YF?Wn^6`B&|B?B@4ErukobrK1C!*F_Q_#c?x;Km?lS<%0ZzS zDXn>>D^{Aa_J~PKmJSBz7R3*ZzN3KR`tmV z9=$dOP3}1JLz{RokDD_%dS_Z*RbCpge6-mJTi*rje4hTO%OyH9+e%{}+u}V$@%MF4 z_we7gqAQf9L+wkWa}CDpBt|@-`h`Qd16QN1u~uC)O=Z#0O;uxjo5Ig+kp@*I2mnw1 zBlIF9O@>r8w42uFjcd%8IL{Leu6LJb>-R#FCIW8uPIAklWy6F$VJW?IGd)T#KZYR9 z#8>}Tz3g;xlU@to$3Hd+Ug-^6(r5*ZorG(aW0TU8#iQHh7`a?^V6JH>AW9X#X~a4mi~^ zwemxMQF8p&nB=l^jK|o19Km?O*A5`m@!svqi=(huc$c}$EESm0hdb)N0O&cFC-cOO zdZ5ML-Cxe0E;06SG;VL$eRcgwEmX|eHYmrh+Z4^0Z@6AZ&N=>wYh<|6!!13!_1k1M z3-vpn!y66mns0s>K)8&zj24yG-Kee!J6}K$q~jyF0|!{~AU( z!s@8wQi?nryE54Q{(E~~uAv%?b91`~xQ#$$#VC3RB~F`4Wq(RTYfjii%1o0cE?xCJ zf8(Ue7LQhomd3VWRn2`_NehZuv>rDB$Ec-B!?oZxLinxXnx$|h4p>@n`2CLWq>Qe; z*;8wEsap`j#N2IpjWJEss^h@%g6B=_T*4ay9YzaaT^q6HY9U!*Bt7}7@2E%hBHq_E zx`!yYOO!=@ELu?Edq3VGWn(GhvOHsSt|GF}-9jcoPJ`y@rm(%SN?;Y2Clsy8pt>7o zEfXO5hZC7o*iRb*6+mJnw_b5J)2uKa{_CFd59g|{GB*NKenNnV7#-+Wh1k7iW~Y}+ zDBs<;*r~2>!Ba6+LghfGb-r}fZ#hg=44m5Ko|AodTT>l)1#SmO(X#Um5JNv_T&N!N zD;wIawpYfBwl&+*xX4?!PVez)>#5Hgr7w=Ov+?ROBxFt7B|tkb7n+a%{A1K25C~u8 zk7NCP;bteyc!~lYe1R}@QmYUbRnwlbfl;m7lYi$ZZ)hqqzO>{tikL&rzwM$SmSMcb za|n|CXSDA{o-Q`l>0_+~qF`j7k#cpui4e}sGgB`JZKGpMTWnXkdUB(8yxUm554i8{D;@>}N z2m#BnU5m+G%-IUx%jk=IwwSxvwS1PGyX0*`=k_ShM}UjyQi+w{TSO|yTsGgVL(=JV zX%nUr>zsBOuWl)Fsr3BG^#b$Aj8;f5(Ez&*($SxIY$GDi;u{(i^retwanJK~;`%>E z8k#LBq}tSE{w>-{$1>%onLN+wZpd5&-%-wHt5^vX`J;*2voCNtncvZ4Hq5 zUN`6M=7)$+PmR&PYo&2+7rRz{%DHY(PVDqYIE*Qay+~h*d;j>ayDdOc%9dNt%vvc+ zhXiB611=O)TphhJ?-cV>!Z^@b>yNH^oFY%&)DVRpoW z0{~`xh}aN71*~CiY=Y-2d_|Mw_uqeKskb{kPWXK(4PWgavFMb|s!k>I-8%%?wdY!P z#snU=3^}sHbt3!Ovv1IE(6(FsT5KeGmPx1q;zd?cZ@BN{tt}Rg%T?Ur4WAM-KnDee z@(9_kpC+fQX}VWvgE@31iJVk|r&I+CF92r5BKslPGELTF0&htz z4~GBP%O*B*ajQHms$W_AdfL^S$Vm*{*rg_Wp~}3}jRnS%vJI(g_Gl!S!Q~N>d8F7O zTevL0%*kIXb5#6J(OyS-rM0RHH30dI)g`z(SF*VE?D8rDb9X~jH@*gDhF5iM=_Mp? z_9EGyGS=Fwc&woNZ>5K@qCe#Z({MMj!x>b@euq@5LDyaDU#o!F0l z=lX?k*Pyk7Tj|JK{QDmEbaD9Z=E=%$P72rOcw1%s9k0;=Y2_p%c!c7wxKnmt9* zwfsk|zhxBaU#5JHEFQ$kMs&xfU{mMuK@lJA7~)Eo1Nl1#bZEP}?f0cJ(BFIBZ#Po} z@m$R>#o5K&$A})t%kX!#N`>-B1yn0=L1yn_X=0*i2($OXpAQeMI3^x5fn6-g9seE? z8apWL1^)y7??wdo8Wyq2PefiBD7|1G2|GP51`RgdVirk(Q27i5=)dn(^nN%eg#-c` z`t!LXH>X}ugR}_0$+jr|2!W~$^87E4xf*o zPOwCe$*IBSo+Ss33w9dZ#vhB87cj{llmy3tJ8$)L4-b2hJL8JZPsyQXGpJRrOjJ}- zHmkYiCS0jpy5ayT^WrB3YggbhRLstKQCtUFL?!I~Hx>AjUTkLlmgGsyW`Ve9lhUy0 z=#Bbb8w?=G8YKgS`s(W1)@s&y>I%5%VDS<0nY6Lgzio)T3d2b;aq_OaM2f%;aEj8y zvq(Y6No7oC)~0K3YUxEG2*8Dg(n7MZR4|XefeuK)fH(oCNUErs$P`<)f)R>I=%z6` zrtB?C4K!H?)8j$;XoXlP+@!|eBfJ6JG(bd^ou|Zi;l+-IB|<=_+Vd~H;538jspwbi z-*lm*oWcvFO2~N;bO2>MquC=5Il44u_*%;I)S&I&*mY_#TSX1B* zaOezCf2PM97LOiua~61PbrPeP*k0+DIVRkE|BTBo@HC&(u7tn$c<(3ywWJU znS&@DORWId2_Qdl7AR?yD^J*CYY=4|>cj+G6&t_{h(Vx#`ZLaBa*ZT*8jWlhS&CRl z_%sJQrXf03TcdUOZ_|B^xbfbeJ_A)s@ij`e8lhU}{Vw$I63`R%)9tTz^xZGp4h7BN z{iW)O=d3IArJO&U<&*M-Xh2;=_r!5M)&Ux|8>mKnC} zQ3_&LNMe{Z>eu{b&iQtFdw;yn27UeNbU$QlF|$&v1UYGPCj&(+>Yz+esHKKJ((xS5 zc;-HhN{l>!U)|fSJYWB-oZ@Bt3Ziq@$@&Gr>R2Xpon%^t4Z_XCFpG(U+$wHQzkk4 zOw_jUp?8*QlSPMvJT19x3u2QjwFUxCjrDVALi!C_hV5$Im2Kv4RHMZ;p&N~M2lX8I zd{F|$IW4)=H!Kq{_d^Eov#Cvi+XZz95D%n+>4j{k2}kymc-?de8i%E z^zpB<@r3Olf0{*pT;FHgN<=`Ad5ptr_(HI-?;U%s&8rUs7YxniTHo;}fS%Lb=id#u zMdG27tU;PqTjfXHrAF*YWq>G9Sam98VYrcvVZYrPqfkz8L7*jPbwAV>lZIJfF0{-p zI$V-@__IkMeyur*h$^+Y4tacqmP8`GiFs$&xu$T&T=@2AmvuCgu?=8KAhIF2cgJmK zsn>k`t2&?x0N-sG;Qy%(mkn7Ay%c8&HdyU(r@ypR+@5S;WU?ksvz<;>D0hBehjV$t z9rp64xArvL-ZrHfOWwYn&BL_{ew*d^-CNL~c#jQ+1g@FpyurIXhRphIYhbs)y0P*q zt#{=@C0hml;`F*X(*sbdJ_-UnCJS$qu0r@2t*g7)f|oc}B|)%8ZtbCahEiT7kfHwA zT=25i;|s?0K|nV|5_bIrM@73opO%5t;|2`kIoCSAC1i2vSK)z;l#&3?vf1g8Jl z{DJz&I2^Gf^<8N+P=icV(6G`)fl&FbLr8U>x53W?@s$J)NVd$x%2tt{{O(@=w~NjH z)KJQr?S~h2Zk(8d?f*FAC~l57R&JxdjUsJLX3#u@L@n(s60H-~&m$abl)dTLNGzU| z9i~BM#frc%OF#ZPCXmpY(#{=y$Qk!mmIecmtx%IoH8;|oSbS zg|eW%RT}Ziaa(PxblJ=7W75ryuQ*>81rGLQZ99{UheeUPRa)vYt#dmJ*+LF6BSPFH z#E@@0pr$Qo%=HIpRIKt~yNtZ}ql=R0qyiV_ZqhpGJJ~DY&#p;{@3)~}4N2St#~YU^1?4QkJosb*IVytwn{_bk zf95ohX50U`>83*QPa8dgo}@UIq;RqE-TQ#lvqK}T{)Kn|)NDvOmW!EQWuyRj@D{ih zDNrGz_ee;}CmD_3JO}oWiKq~`wkn_Rbggs`=C=Ad1=}sla%G#}8iEkgl6Y!wiC&(? zQk|I!c!W86FYb~Q97zJF7EDy1fOucs?-w!|6qoI>C z>YyA6*!H%&Be8Wu!mt%IM-2x6WkL4tv4nzYa@Wo%CI7>Q-@9P0bNTnzpTG%z52e6L z;t%B8a4t>qXc?cDGjO@z9dBoRfUI4NG3`h*){WNSGM{afhs|i!S=k$4Bdh4>qm$~} zA-f3ve#{|?-hp5X4L?F*8Ljru&*g4)C7Fl#oWFheH758UOZd%vKYt;9(CL^>IO@;x z?*;Db&%>(2|5k!d$TW68yfJU#goRy+U6NX+u)j%OM@rJMj5^26?i44)Q%skCC$#C? zeZ<=MFfmoJ{iuyY>wr=E!tdt>BMk$DN*m0_BpjH&c1(nermZU(XL8mw@Md#U5%6*8 zRuc8n0!8YK-UdUnYNKdKU&vqC!E|-H3x9D|3nt0e_yD?FAh89$sUZ`2x*f9@(Ok*? zr4(DC`>CNE$e?SUi@VQL^|ls!<|d7i22pgiZ+)$vO_Bs*lK>1KN27mLCJC;)g!waV z;b#vREoHY{+nD$m*CL(Ycs)O%LW&MA*iWaeKy$VYzCMVGS0K zYOl*GccE#z5?~;c9Jg({Ypl~;rT?1&YFe0-sTP(B&eqHGuWu?yFcuG^1IHMA%g9-8 zMhBYAmop}g>Y`RXT5I4%vIY&pJ{4;hE0`2L20I(X6pVi!<4h`r-R_1XCDPWIqPuH*c4*-muqltR!;>aCmCVbh}5+kz3@sIn0#S;;2Zr7zH+``E~JL#eU>k{ z!9T|i^ZP}eM}58c1We`yYcXU)XpdM^V8aKzWac^4aw8U3j4#;#{u3`C($*MTyjxgQYUn*UOt1z8Gu?;qos&&+Mhw^9IrFa7Aqz6dW z0NZG0Oj+`69uwS8tUgaD#rQPnNXeL<;kz0;$Z75&8=I-Y_jmK=$V?I(nqF>1`s~Mv zH*eP5_+26`i|=19_HdTp24t*V?;YUk#OWb?#KSpuf>wq!GfuPAhg}OnMZ1v2%-u#= zB+}F|D~F9uK7m!4h5dG*aOlbN__Id5fV-jm;djs7@VTQ81rNm6h-WX(Z20omqXoQM zb4NdpUhKX2yRtVo*x?JzHyhsG3(zsf1NP6#<==!-Ffc>})YDwxnH=E~+D;*|6R3%i zU|&hqQMH^k%N})Pkrl^XNMQ(zzk1Qcl%b|*{YVxQRVrAv6|H29b%_MOtlG+!0FB-} z=Ro{Mj6!D4OVE(~?!hFrsW0mOICX|qq<5~$d4ofm+e!?wYDtY+34LzMu(0Q#Hx63% z9eb43N)ew~*wgU%M49WL&j+gW>n|;5v{{+!@oV!>*XL{T;c@WoYF12&N)8U*?OwJc zQ94@aN^452I|QG=m>-6Akhg9l0FPuMUXs_Lfjb78OeT9l5?DGu(emVDP6X7}u4nMT zE6NYCI$mJ>0I>nRE9y#!ds>J-J(Rmy(Yj6V*GWyxm>+{U$_; zd*ozM0_=jE@}r9}VBcTa47_tIr{k8a**h~3_j$7BynI>xc}57jh!m!W0CEHF+mn(+@Qb8l=^$e=au#ydh-kfu{6sH4qF*sh;IHi;&Vh_wtgk zT_74E(Y$}Al~U#UTH+oxj$oZ}@j4r*`63sx5_@%d3$_w9s!mr_+2m2?W?|i~#nRIP znxKq0unaWm0a19Zd0OKB!ahzafUB9+{5nz{%SsQN&tM*9dfjFHhF2!&dP75CBajyzs|B9Axxn^+z3g z5_1&hyTUWGxEY&T=PLD}pwJU0R0Y`Idi1yjoMCr;He@!mp}hD70RE$?olizNF7Q=4 zSRsU`bDjFCAQ>B+fwrQ!MF#!^OS-9hduwR9v2VOe9RB`mb9V_*-QBv_XBT0ds%YcF zMVJrlRWVx~EG@YA_oG$r%&8jZFP-t==abdC)K4Un13>v}$-s%ft?-9Z(v6RnpzTdeqH%#Ei^+!lr9kb+$2U)j z+Ume_k9s{j7tTjtj~?Bq>yd+f$@_kI`Qtx#77+--F9<~%zkD3>{vaU9^Vr$@%vS3W zhi-EMHOg+0t88(#AU4+<1g1(w%&8a{C|fWX4KyWSv})Y3t>fG_!n z7})KzsWfC@&`fRcCXUPnsM~y9`X#dLk>x_HsxVu7TJv^1CejB^({;tcaoKz2#@T`+ zN@HenZNerCa_#mF`QN)pyY3khB{2Mdd_HEl|4RFQT4t2#iRVbH02Nms z$QBK-amXYxFU&7!hsk_!R8;rv$Vk7C5 zmWenr1*ITswkJrlNJMJn_cVdkmUvkSu^JEeeAnHFn3b)M@{}})mAY5rqawqm#1_+$ ze8A_sctkmsw23pLAkThL+o;GBHa|00R1xoPGbIip1l5*sN+f4&6sYw#fJWv?GE$kG zR=N`}9}!4^LHAA&jg}DlBr#~WKIjae8#58@hmB))!^0Ta2}u{FCI1 zB@esn>HIv6dArQ_enu_Jwg@6;K76ZbSBls0)4t@3&IFmttVMgXwv+wgG4vdg7UYlf z;g7E@+`AoP%ZLg_u!eU3cD#=ySbXjJJh zXGzh?Ujdj@tig1nXrt-Th11FSj^OP=P}mBZamV_#k?&s!WksBl-yKVg(xdlF;fR1A z<#ae65a>7t1^(=1p2O=w=M<3u$Nt|ZMq!0!SBnsKOPP=pwqpQc5qeB+0@qnoqR~r~lB#@0TDiR+s z6$w)(CF!ErBuP^jmU)lSPCDAXhnbKtnmLJoi@{X1%hEqmXH3w*6fe z#olwFi4}}_loh4~pl^zDcQ;^C?JY8}gkhYJA6cJilTOklIY`IqM72#XbeL`+dU{3~ zvHn7kkcoM&EenG%(<%tsuB`=)MPT6RI?~&kchiBhLYq@Q0t&2Sb*5t0p*7x&qD5s$ zxnvA4$+1;E>jf=qh~PNP#1^R@nD`$6a6pg0g+>c1&FG|xHVEvN+L?aZ|BwR5KJfYq-T1IxT!)_~D<6V2ELV$Pf-C{=Lk(~Z{9o_|);E*c%!su&kaV3cmiMdR<4p)Ri`kWri8BgtETPm1ey4w7u$Wsg^w@MU4_CP8 zqV=n=0r(WGeHSLHU`>v?UM)}vIU6|^1`7G+eiw_5qkn2hNbh%Rzt!u?pUe<(O%PpT zugZK>FEF9cMb4@PQ*t6qA3BOKPi0%Yi5ZLYvbYFk$;NHXpiM8bn}}hbx-ghcn6x;@ zoK~_eo1;RqEq{N#a0*i=&#JnBiTcbLH+)ztJ)UpH$O)TVUM2fZMn8u?DaUPPj0b(W zDt=~>6^;eda#H;rIm=0SgS_O8@hPqYCa(NF-g}Iuc@Lq1u$3uN*l+9^GCR3;fNz0H zHdTALsMf}SJrl!vEfjx^DxWxSV6diB6>b`mQ6Jxh=U9KLi{BeQ`Zyb`an5<`7q`D% zWU+pq*1Z2*`Ac`FiAw4bFkBjtob&3Vc)4bxd$7z!1jsQA!5_X z@`P$8&#|PNs*4)XxRTgeg?hKDjclfey6LmN#M*46^lhosJCVDl9pFyaYO~IKHw*NRUVj1JGttGVb&#^^4LO?C-Py_v0_86tn{2W3Wj&uhEZ(AZ64m(y| zo_D!ZoL7#mJ%>e6_0Gs!&|r$cRm)*#*2;g3kP-)eW7uROc_KBpWp3slJ3YQ|yyLRW zPvw(N8fYhNumdyoG^#&rVo)9F`8J-82`=FGKkQ&$&Eals0d9TaKL*2NP7LXe|HSCU zjD@rJ(EKa$W{NleJ7Ac$dg6=MP1?13<4&Icjbv9*Lp@JT65)UzbtCx5=JA(=^aNIz zLQ)Cn;=O+h(8$jHG5>M(d|_7ph5M6N9RCd$s8Rj&1;TEE=1`;U|L@QL%KfP#_&;}l z?2UN$7K{h~1W-!@1QY-O00;o*iat&2z=#MJ1^@t>6PKXi5E+-9juZ=jMKA4ayQ!UjEQ1AGFDs)9u(n%q1I0Ekcv*Ji56yB8cGXIj&<@>g1vSk= zZ`Nbp;p($lE>%v(b6Xf$IkpHe;s$2ipp5gJjOKZgq%3MDA)>50M9FOS%Y*{~D~|-t z#L4-L;o}4vZ_va^XflV;N6$e*DR7i;SV@JO8}tS~GP83AAa(+O*DOkojC@qKu4qdj z-c?|@lUl{EZwsjCtyz0Mpa0GeYzfS8X+f|h{-|Xsax0{DOd{G1uq7|Hpahdj$bvht z*vhdN>EbGK8JcOAy@cx74?n%pdixTAf{FF=6BMpr?>XBWULhjJjjqusXI9sy08#*s z)aJmPCP)OtvAslpjc|7P`jVmH7D_hr_QK2@XR>ql0g-w|;dDYhHJf@ta;cKU!`b+-KQ5MqWd2FFvr31`q!*#Pp zGVm&n%m$lVv{4cFjmdcQ$P`W({hoDT*5Gmjf7M8e%~#rgqk)@Sf=N6np zrtIRaRxrSZTe}dToLn7{?qZ9&wyZHJ7@7=A6Um%;yR&ZYdvLW;7CTCkmtG;J3h{v| z4xVDUB7vbmZOR~9XZ^DDT+O{b_Va>0&CZ_9Q#MDGb>*}!?fkl5=fg%?CNu(58g;6Q zvKG*S+#z^>+pY$r>XR;{=fdHn0GSkpoYkd=O(}+UNUdb`hL>oyJTOWQf^AU$WS93o z>T*>!WU_k?%LG^Y1eTMHIJ(bYQOZ7#_=zU2i_WLc?1q0ydQDUYDsCX(f#ZTZeupl) z?r}stpq0yD99{l>Mmgn)R4a`#DFp_S5AN2k*N!89&$Z4t77p=E6q679JM5A4!T@F^ z(O4Z!yJ+&)D3o!_QUQt3yUAnl%ZB@H)25o^&Ln-L+|rYJJC>Gz ze@ItU-N1SdzOL|HQ+st}Jcnm@p>$98hD$58@rH+EiUnUKa&&}EnoB-+ulNw%m@kJV~GEAw5IO!?;j=fXt^58aq zTCuYfMNeYy1pZOULSvMmlxqweOjWYjP)04Zp=~9o6Gz++>@_PPw^7Y{q3uN*l>Rkq7i&>q@sF7S1>*>)leows*_Yst;Wov zo&-q#{*4S!p++{=2&to)jX-flCD%gIixLZ&J=hF4ZZX&8bV|E=dd(J?(#9EYdigrO zk!7ARh$9ax>WdhZ79MMCHq_Nsgx68Ljpi>tUi|hdfARd~udm;}ims3DfbE=raNun} zLJ*-&j1h#7AlcqX2l*$fRs1;$lE&x=FJIE;gNVZ;L?l&JyNpIglkhrzB-IhOI2(vR zIN*I94oasI#TZ_v;rNRD1GiArjxS4$yvcW)QB*o{eJ8kLFBX$qcS`Io@ZSWfzpE@- zk}xBRz|nvYUAvx;WHcK!MFuiEEFN)G_aAAZ%GIoXK(MhZ&bBeku92wYE~?=^J-B7 zgix*E&GjYxX9exr68!h@S~ zg>S)ta5(g)yaVH`S{TdACWGeLrY*Ck&8bDRETKWw)NKYmUl(vc9OU^5o2z@?p8RM!=)P_dE3m@zHH_>A=lpd3Ls1- zf9IR^W>romS#?dX6=!X;*sRM5f8X1a-(iyaXXE~=8vScsU6=az%Kf$8E=$)K=7G~N zU!@EA;kH=SutTnWyDr?b^Gyv{*(}_{<<-SzT`k;@2nU*#dkhG04m+gZXU$>(sESD9 zn^f(3QJv}c^17%NfKjWqbYRNWs`gVXf3JfHtjmw<+f}i2i?J?O!5FK$#q+@{Ed$nN z#(m*Gp|`#DYWr+2gO5DLM|e~o)JUzI;>;0C=e>-GI!xGq*#415n-1A#7P3qXCK$45jx;pgf+8-6~{9*?qr zLn^GppH%gE13%%j-;Q|6S49N}=-sBq<3U?7+;_y{w|Lp(#fVpFCL^8ikEjPcs>gqO zs)+yLvH?J68#tnHEAbA~4O_r5ZEC>(d3jDOe+4|&9_ZcUa&=v`I6$QxwBz{bO|yRf zQu&MEDbRp<2@?n4ZF5~_7YjIL3%Ss4tHlB?Z`UJFVcoz>Es(zUe9JroTbD?Mq;wf=M)wVf;*n0a?BII9#Kyu$G0b{>>O z@%3kzOUpC^#|bM>9ELt5jta22oB*AeFVc^cA#%ICN4Sk_%Wr@C_&dJthk~v0RS+3D z6#Vxa)xWaLJYg@Ue`CpqMA$ddjS5byeMW{10Dzj zvP3Y@f|mQIpJn(HIXnD#2#=9+0Au~&>Q?3=2WmLVH_JITf+zIAfYe9xYPQaif6iW& z+ZGy*Gl4i7X@?VFU--qzPi$d^TNeKs$$2gT~5eWu4Bd&3umn=0oM<WN1BN&I54nDt&0>!CkKUNbLOlQh^Z^`pxHnq57lALFZ)WiDY#WUx%l^1o zlX#om0?{h!H50ViWjVu(DP-Z1!U6oNy1B(65-dmIIzubzK7O#;)JQuYpse12K)HaI zH!aGt&AAgx=@p?-z+BF%e>JTJ-<3sHm$yJS6J3q5n`;m_SyBx~HruR#$zI#na9!WN zmpyrX&igoP>Up)M7BhIKr2|;h+pIyd?zTB5>2Nx$bxV+36TSvPuqMDH7h==)Qn!gV zWez(5tZ%bIoyubC3BJNYk^mTj9FE08dXAShu&hlh#P>aQ39QH#)Mb=B5Hx zL%&;~gE0d@b%*7Bv@QPxvSs)K^2z#Yhi%da5t~JW3pu#pCuO2KuM5`|G-k#s_=#9N zcv%+pRee*fni|E1VnO=4RkL8odbc~a3gH-@7QgoJvpP6rf8K(Hq_HG8QT(~X0ig4MugR%?(bVTa1__ew2&9xhH6Ru1Aik-Q zsaq#Wz7D#PMN z7Uzr}?u&cqch23UxW(=Ybw3m2ZB+s>1Uaf?1VI%9px8`MhJjHBr7p(0F-HN87c;pN zmTK{r5`Neq*PuV?LKwwqG;O$2Q6uRz(FlgG@9M`=V(?U<*p18fm+(e8FY8&kkB11@ zlzOe`_vb%PUcP?+0fGJT^_%DK{^q{EfBVh57q8sc7k_#6;;(PN`QUzd`RdzOU%fq+ z@7nYJu~4f0j0DefIGS)Pg-1a2zpL^B$4NhzJ^~RLe;-jVr;T+#j$u9gZ!pn|i{R_^ za=o=MO8mi)S%&gvvsl-kw^q(Y)~J3>x1St9is*q2fY@3K!3HQPKH%ep6J70#3urkVNjC zI*B!+e$ASS{y{_oE&i!j1e|B(a@q7eO36`PsMp(x`Ca8vAu&lZN z6HOkkwx5v`^IZV&j2{Brp96gtgZXzj0n2hFI&<6wgtBV~aEVVIpZ2{D@b7&4$?2YH zkNCTD%XOwXQs`nmeDHwmV!#59JRDr#333cTlL^|`O?7g%HK297@$>rJHex2WJ|xmG zf7US+ma9j=EOVd+#=&{P{cegygmQVZTi}?H0X1ER{Hd9}`yCe!w%RQsp#9JQ7?0w$ z>mAeZL3m2~8%E#b^AevgUKr$rmuob>f@A`u2hEn(B~Yj_;Ww%uSv(Rp+u!Q^z85ch z56h0D5U;;~_AncOQ0h;EuH4Uq9jL60f9^!-r=Ccrn5cfz^W4x8%bS9P%p%n}zMq`y za39UJ1Ao2;J0N8H0g5qBBGEB4p|d_KQvLqCKl(MNeJ8EpUhYjXcEG@q#&G1Ig;PqN zwE<#Vu|$Ocu_uFgEOWS?=F_T1XbUa9- z(bPvn2K{yg3`|F*2?Og4O9sWRGjkakE~2?0bck@OtCnsCkZ^2IW6Ljfe@~9l7Uam9 z2ZJfBdMbPT5cmnl(C80zCIB=Zw+hl(6}wI zfLM791JZ?hxj;ovvdIL*qa_@HVPezA0(vA6otE6{;8+22baE<-E%cUu_ES{`>d2`t z(QJ<(hHh!`1JW>D_9(Ove>!|!%#Kkks#t9w zy=YeD`*L+tfn+MrgiXllok0KwIuTcdoE26>YBUNvla`l7ORKIcTowId88$ z#xtkhj}-gp=g^~{r+)Da%ct!Y<~DzyN?Ef?#Zmze~PJqi=%Py!xQ+S^F|U; z!)BjgUcd#0O+{k}ve#^uLgNxhm$<3C*ct2n#Dqic9Z3HoSnJDGv$?p;#7|RH&yj*H zB!p=jM%R=BTd*o~)D2aOa=6m99ezK5IQl-Pe-4NFgAr^6k9g_ zuQnxaZdrx)x(W|I-m!STr8751vP}ZyVv&0)@`g@+sFov3XiNjxGPtR$k6WMxWgF50 z7>mvc2SMgH&&UM7xpqfK?zzX?gRCrC7(&sOG22AGe}SS~baq#wl4zqT)Up9E@#zke zq1z!HI=|uvfkV6lhR$NNXNFERm>6YzTQsD9h^0V*9-mdE;)<5>uF&P6wqx=H%g##p zv5epVSGie|-)r_b|K~h=4#zoquQ(@O~u^$WYpzPXuSTt{mY9zXl#;OY`BRN4cyD42nwR)7oHm-Ks#BKH|lf@C4JjmfDu_l1N^-6t-Z z4BhPZx*f6F!I|ra$n8xK#yI0&$SUFQpsyOV#Dsdese5V4X0Z+VcVtroVJhI1(ATX< zg6O$)jv7_i-28kZ{(oHDhP@f<_GF;Ok-@3F9r#U!E$|ii)2d_rv`{|F&3w%e#{dVJ z?}PY8S1)`uE+M1fAQ*1lE(-P7)f70-nqUE0+riE=R^%t&N1}XbRRIDSlZ!96B8^6C z5Npm7q_w(`nVCn|3o)&A5MY5?B!GjLQU{h*(ODG+c{G23@qdat^DBxuD%EBl41#zN z3kVo$-?Jbz{vewXJCevy=;V#F5TRvfri`T4y`?$Nrt}JHmjYHvGTYb?{>a{%bOcQllu)f90~#KjuL%v?yo2CSUtrw)_G60Iq#EIXF?XHGYLS+wMxPq9>H>@xnBP02Tca6TYo z2PaoT@T{g!fc+sb1>-1pbn~I}y79z9KG0KvBuIAdNC5sDx_;~eO**FLoFuukMNwbT zUqJVW{t#Gq8+}z4bCUbevjD-3UE_#B&?h*`5fJvm_ z!E}nlASA6;Fcv?M*=2!-cevgtIN`cl19`}UHE{DMzpKRjU$=>^f%SAwD1XSZ;i9_2 zkUG_pF|5&aI!gB?u3(AYzLLds9dUr7;D-;vG(9S?PItX`lzL8tUBCKR&L|AX&6eNN z&e1h@QGbUpZEz@M`B>sc9D7Q|VN2~c{d>^b;p14V5p zdZW-_4+#S-9sEB#S`5heq|u5dQRo}~iC84+Rev%9{ewr0gjgXCcZ@Km$O#gxZ-*o} z^wHeaML;w>vHT@OBlaKN)vZ#GFzWi#sD~V4?}cgX@;+9UY3e?xHGN%cn@sF97p_GKsZ{946>?(5r`flh?DM=mU>* z9DgJ0XhODPZF-cQoOYjVCm7!116JI_GkTJEFcTY%K(ykVb|q@3P-64r(6Rb=@klej zg<*EwFnpVR0p`LH4(Y$@mOz`xLEV12S%-LCppADpTeRUKyT6ZD7+B920XMcQpZ4Fm z#YxN-R|A_z6jr1Gcv$v=pNn+-5kqKp?1MW7^!dS=``-@&l}u z@l_uh6&*QsBH~pnMYbIrfpaRNu2pr-=Y*;h77J5SdZ6~KaQXp7(5GQXLU6V$NF!F{ zNz&m5l^`CnK@^G9EVrb~Kt`-HAbu7stg)Dz4Yz6EG6Vp_51Oq zf??Y(c#=*vj*^2X$GFn>9ixnlFun3OI&lu1X$S}7?4DCQk}=?ObeC5U5hs5|CDM;_ zTfj>(pM|CZyrqb0pn5E1TS$!=`$+Q{T3OGnK*6dg+ljan{51-=ge<`Ns6fj~GO*m5 zs&94pJ&j~b*dWo=3QIoDD7p!0?ZUz(xyh+-iQzG($?)D0GHY0*G22ycae*i+2K3ar zQ8_SY4eGF@6Y_WDvEeO3!vcTo7z$J2mHjJJp``IaRyuS5p;?8zxS^DRQ@uWPj0Vx1 zlqNT)`y_T{K_xz3Hpa}(MwlZ8nLEP@enx3+m5o(sQ)VQYb;^_^st|tHTa$KKlJIjM zYZA5VwJ0%^z^cSQ^;wqiV?C$U8=$@0!la7^5;Pv7j$^btCn1{R+Ms`SbiQG)ZbuVS z80?P>3R{GXjCp#e$(I@xxHF05!CVQ0P#(W6jbi|DM#?|kDOI**S%=~_-&*-wk2Q-voMNt7oMjm^dN~F^iIe@C(7z3*g3snQ%&Q5S3r%6vqe8G*d zOgJ3q5}ZKGQ}P2(wcvl9F&6+e4>)eatO#>+#FP(MnR2y0LY@T=9C@1^G27E&$%Ubj zRCkWdfwbAoDwDd8dESuVIzBkt)b36nf;<@_27Hto>B4_;ctqg)P@A!FAejvu z7vgd*&^}4vf%e7$2q9rpRvs69Q!h|EKGiM54V(r{2=z!q8k3ylRa6=wU?cE=S>K!? znK>&_6POwO0e&>k(u@L+dLy_Pn?gLM>w_Om8i^E_RV{+R!DXrC>!CZgf zwUbj>jF{`o4XNo;K$@TkR8GRU3&hhdjHmrTIMj#GaZ;DJRuiH+Zq%^^7eDD{5Jzr2 zv7*Sg6@Tv#Ls|BT2ByOKV_G)OD2^wkStgA+GJfGjiC%xme3;=<#OviTJ)#5fbIZVh9Vzf{wg^0TZCJyzC z97TCK01>6_&bZJ}XO{`K_8cQ0G+`NIf@E)Tn1$P=={T4}hnQ6LO>?D0i0r&p@*`{D ztf+AsXQY3EMdhE-T66=G?clz^8Oy4&{ z0pg6`7BaG{Ew^$>^!z|&UjR*-Gp9k)?xTD@cFTW|+)1tx18r?@Og@Ja!ll+5x}xa; zCHO2^AE$Ry8!F`e<)aEPHY8y3BvplR)LyW{*Tpu&^a>eUzOJ{Z0sg}1=<$uCY#$!b z-}|t+%+_*}Cojwq=EC&}3<2^y`3`Kwaj7 z~ejkeaZN&W|QQcE;ozKIxUyT?G44WO#L! zNsvEe0K^M-Oe<60nGv^NeJn8Glhc_#d)8$Q9E`D~)gs8&p%w2RiXl zsLQwOc|X;Hh~r}Y_JR(jd+&191sMyi(RI*f``oK{L)^FWxBiO8eIBG@RisDQIba7) zhf2sb)A;m5ujL3vowJtO^(atU=05eXB#sd@V#7ZrCvMk4o@UyAr#TW(^W1-)0hqAtgG&vQJw04+ zfSx?dhSOlprf68eV?^O0(-H2LHEBhyySk0o28Vi{n5ro-N#49F=>Q|9jsb-m@9w6F zk$X-ZUv);Jc1y`6m#pAMI!8Y-9=LbuM*_99?A@l;F=g&32ZLycXIIUaCm!>XObg-y z?v*Z7=YfV!xu1Vgl>waphLGPU03a1=sJc^TE>__sJTz1{n%0rX7C0-Y=tBI?coKX- zr^=acoM&~hSY8%q<(fofz}7z4c`NCug6VUqjz9|%E-L4d(r1A5N~HQsBKH@{u-v6Z-|}SgvY0owQcfexO&N$Y$XK%0z1e@PyoYpc0JyfaA9z*zXM9tV z#oH|BIS2GRhKp0c1Y7W|YqV7#2tS<@3*^gP3xfOJ+^2MT?RQI}_LQo9;Sc+u=*xLln?)!hmIvS{V1Pje``NXBitHs{C%&8fBVizW@ zfj3|p%Z{5aIXiC_=frPD5f5JwVP2Js@}{Wc#Vl6VPBdF=$iF~cmdXE_m>2b9@I6*? z{O*7B`H_(yscRHd!?f4FM~3JkP_oXzcKG^su~IlFhl1WQf{{>pV$@ax05t|i@n2*^ z%ce8W1ta3bR@cZ$#=@JrI3|;GX-0Qu&7O+Vnj8z!4F^_!vFP>9aIC!gAvlMSR3wVO z(u1a|5Yrzzo)0>xoiJnH!?3Z!j(r4-_dtKr^%|kxcapt**djRTT%%oGh%#3v&rZi3 zzY(tGGY(7x@>>^>8!doxPs1#z;qU+lCs&iRi4EOx&NbNoIO9IYnGI2sm-bS#$c{2U zpKc2m8)s%0wsJvo!EAdF3N2-J(i(keOnmchn&q#HWx`>g2@J_}5tP>j1zA*as&Idb z#gp27hDkH~C)D#DK;%!MAbwhtWy>LCkWwmS-6LG~k*J&-l%sLk5O?g=waG z=A4RtI2vI}ZrKsEagjdIa6lagaj}08$`~>(1vE4x_8A$BjN`E5eTm8HNJ4GvV%c6c z3A=AY!O7H;{4CNTsR@-Qze8mvM6;<$bB_8-SA~asN!1XKG%0Y1UGH_keSSIdxIF?r z@5DhlXOgKI^wh^DdCy3l2u0Ol1+alj>EZ7 z2-_8LQ6%6A_v3QnDKJhXuseCBW9&@PFx0SwK2&!(t7nyse;JI*t&_t^e-M87%kpp=lkqj)QcqFz$a2&ZF?qxZ1&3z(kAFaFH?}$=fGXnW?7Lv9>{9k_R8o;@U=e z6Lv?n;`<4&pp=;FWE_0Q$q<2=I-Sdftt^M@<`9*4?K(6s2k}Ky3(lBpzd=V?Oeu&S zyI32O0wcrLd`4GQi#9P}@;0=Q1#2lh$#Evd7`N5R;ad=+07!oUyDfST8^pK3tlBsx zNg!2G6py(&<48+a^_WE*JNTS{4Ld|AIPETq*8<`g0=GfCt``%B1L${)mPWmiD3)D= zTS<1ndsr1QXBbIE$lQ<1B$zQU>et>Z>9(q`C%yu$>DO}F3mjg<)igV$h8ME$v-cv?2H0JuQ zn?rB-LBi!BxZ%m`Fi=x+*rL#Cd=-MdK z!#8XUMOP6-NiH7Qe~m3U5#(UBE1q-Wf*~$`J&x=^6R$+7)5Ye7n4~DU0(8xCCWan= z{V}KIU=2ZwNzWTEtso|-P+`VN@ontM&vLo9CwVl9g8+6jeI1*YI3;$__tA zNbj2`TJpRTI2DtpkOsZwxQ@P*5Y`4V6)E(lD%^;T(maIJ$eBPuWgDpH5>O~4A~;=C zATjnqB6ZI=2=!#~QjV^nKW@&}I6xI9G+;73R_cGRCjK`;s`ocqsz6QxEhrGEJoFzS zgUlsHmaq>7R@lb#dS*-9;s;p|ad2S|4$1@5=oWG{gy>$toa$s>#iwW1(Nd#j&3ua0 z#fDh%Zd9hY^W1d=(#!V=(dIa$Oe|0MxtL!Rbm0QK`q>JR)vgz2zvl^!lH9W0 zt~+*%QbpCltsF-widRy4ztB}U;i_UZyP|*SWzB8qbk1oqZWL9=sa3}g9+G!{N7Y^4 zQl{`k{SVC+o-RKd`uBK!cvyUT_-<3LtLrkZtte$?oyS$Cg}#aYXyQoT0@OvFH%QUw z>6*t-atxY3%cSp6RQ0X}&Jj#}Xe6g+py_gnD&?UBWl>I@2nqwC)C`lrmlomB#o;^s zBiSA!pnWBC2GOjli>fXb6IzG>Ou~0f;!w%^(L*8wI?P{}H7EycGL*V?=kKXOu_8~Z zVkmA#)z_C5BN5MkKh0te^nNA^X!wik9E?s(Lb>RVqg z7w|4dmEEp@U!Rv4RyMQ?iyvkT1-K5EIK+z!9!2Qf81f(y@51rZAWutD&IoJ(NF*k) zF1p@24!%Fha{b&LNBpkgI8YJisvvS?Y8SF!wSd;k0^A~@46@atc z^-Zy=G+_Z}-(&uo2Uf9YC!K_qxd0JH`GTrD7$rGuDDtxr?~1sTs0SUqmMhB`#XaMr z0GksmBen^D*+4A4$ouZe0Le7)G|Y+b!3lXns|}n{TU_C2I7(kYXXK`h!5y4F2xSM} z8Zw<&P$nH<8|Zv7JBSnja`8atMkPr0bey`&+9bhBoYxA`%F92-L_lm0dN72e@D{wa zGTM5n+p6`9D6>VwiHzZh3|XmydSVI1i9I)b`yZ=+B?A48ahPHEQp&pkq}_!mTn8LrqH9%*H05KAoNneA_Cpzr%Uo{Nh?Ygu#Mrk>a#>5HP^Ty`uD zGnM~zYCU;=(FSrl7#vBmr&bpS|SA4^hI{Bp(Y?L}FmHAKsH z@Ws)8$Wg^yh4p5cVg2>h4sWs9`j=b{3SwQX=q_alTJC@f$6M&(Ny;8(gF~PLgK_qN zM!qAl{N!wlPJ9#2;XZNaVrY8qsG(nZ@zlbKC&<^bx#w6}0MdFr+0<=uUQVLr2qqQ3 zXl1h#GrTapp9bdo=aSqVoj2pdl#6``x zK;ki`#qvkrBW=5ZLl0>92sV$LrkZ7m#@Qvib)k#grq(Kwcyp{Vf*eKv#>`(6sOhLM zn6Xk1BC;qI8(4%@^&_UwEw-po&a>|dsT2j`x|i(H29;ga&8;7|A;2A9wD+aS98hL| z2cQ4T?`W(PKrt`Z=!Dtp5dhe&=}rgrdf;mZBg&iF!3`!$r)%|OaErl_tHEic(mTLZ zhu^`o2Gcbx%N1pb7cYD{*9%Gmgkxo68PFct&IlBz_b#uOHqe$M24Qr_T+pq4rs0LS zfS7r;iQ({3|Gt1Sp4&m>`H@q76Mh&035t0U_q# zl3d#;N9AiL54uSRq6(W`lGQLec|#uK2EP z6AqdNo}_V_D!|z2U9}v9OVw>Jfqf}a;isi191AdS>hgJ|H>XWzx&AqJSEmdp;nCZ}D%T_W&39yis3D#k@TiGFynjktDn`Hn-M zD;!PiavVgakyBrS4V8==Der>ZWg{4f9#f2f)cV8(E9FRCB; z*6D`bu#Ii4<{}i1HH_)oXt2CrqKoP_e_aDtRn6rsKL!^9D5J919^ zyc+Aq8?bv0lJmN1e|$<4l26tRDX#VX!?K+fOD1~PepO%(;sx+_q;M%Hk3HTd||arV2%zYnM-1NcHawTYexOy&A=L1aE@ zcHV!eG|V^{p*z0cJxK* zMV(D6emjHZ7ISJq{{s|RH;Y}HBt0A%LM5T^`PcEbnWc>*$$My?f)bkdwFJBed%cP$ zJ}iAG_#0sGe^g>}JM@9Qtlj(#tB)ka6rR-}kCZ~KTFD@oArr~dr zzRUf_@9p;28q0#mep~KcU=7gOZph8>JWu%91SwVMgh+34!`Q+CyaG|K1UNi61Z*%E zjY9iopV!fywZDUSr*kRwVn!Cf+0$*{>vP{ut0w>Be|BBAuip+e2f=-dm+u&d_qh4A z$s=ob?`1Ik2kvhPpP9b?;JshmpPmEhZ$~!{-PshB?pPZMq-b$>cP6nP0i2|tx{(f8 z_jJ^|@SX8Qpy>U4Ue201T%Mct`Qh&eBNElCkNNT6J||yiZk3+O1aF#l=jxFkx@ngO zOA)VAf6~42UTEN7_*6u2ld*k%8Y-kZ??;9nPp^AT)4uYHCmQzKMZ~+2aMxh&!nzYv zo~={&Fs$~6s*NQU#WI%#H2|a^@L%ntLH5wTmON46VW-BUl=>-3C794bz32XaVj#a+ z{Y;&>yr%AEEwGJU4rto7TqXQ`!mKHyXyOxMe^igM?opCid1m`~}0qUrwUYoF>h@ ze+xfj;y}mQ<8iR1?Q&7AhqRTQ3HD%_+3k3tJm61REd#7?(LAH5S8B&T#HaI3vwp1{ zZ8=YzP|*-C#nMV*1P4T`rDIc@3V_0MuD8q5A5A-+(8>P4!-!(%;QtO|I@b_PwD1D0#624pI#7LGYF$^`k-eX2JGme_YBCb=IjO?vKO*BYOZ6lZq9H=^(xw%&o_b zb8R{d{j2_ATOcwRX+N;&k{jD_Gzhj~Pq#|NB;2SWJNAzQ>CmJPySUIFhd~P`KqKbYanGB@JXYDTi#NUa8}iZZM1TT`n&9o5RGmX~CV;Z7W81cE z+qP}n{$ty=ZL{N!ZM);7W8FUI4(@xiTB{~Ctg5y5{#-m^F_tFoe8!w?rN`ivJ0G(n z--Z^diZNJqxy(5(C_4hcG+yhWl{bk(gcT)OLczeTt=QelcmeR19kjLrs%DJPH~9j%Z% z26&PFl*L+^4uu`1QL_FPsH&zu1;d)B^1p^0B;KfyowTY=5y_?^tpcXX~CTct((P$Px{nMfopufDr%^*VKd6}?+ zf{4XFG0U+cB1_SUE?Z3BhPT*%b7%EU+71(=)w<%|My2tm8EhwJ`@nAD#y*)Bz=X_A zTR9^x5hgs3?-3`U$~3y>MQC-gOEjLwPU<@+vHjJqhmo2=MG9zf;ZD{Ibm=n=4%w#z zAKI5gOWz{*!K&1C+B8w1Cod+67&EcwaZEynz#qtY+4mIO<$kPyf=5xQ7* zTq${sL46e)Wn5wW^4xkHD!k7L_{}p=1Clb;#iFZf!$uzvS_<5PLK@9w_to9&FdxP@ zsPjQS%SU(Z?u}2=QS{GWAwl`85{HT#9!UfqvK<>m%af^|*=^4NgX`U3K=_3-*-QqT z&IrbX&+-<5S*S})xI=pwmE;Y&&M_Hn*BuZCxiKAVFt`Gg4CWqYiq`kThLe5ab^aFB3WKAAS!1$~s!ev+fM@sX+ zO)+-pyf=>NY4F1gEEo+R@IdTiExmIY9zbB6i^_v>uKmxu2dwH>h`p#sJO}2^dEib3 z{7~gM*)7Ua_1#p^7pq?)n2y|}Gd%I+ zxn4!JD3Q91%r+1J`s9*w#aVlzw~@!sy}|zKs^OvWiXX;?6uzF?0Xz6zLacGm8WrDi z``pH+qrOl2Aa9|AA;hpFZ0FAv@On#8fSYlWr#>iFoxK`I;xwMy%{dsJaK|Z7q_tb^ zfKR}CS`w8|z5a&YPD;UG;LE0HZ#!lDJHY$vS~{jVC(Yj#Qo#W!yxb%muxLv5L9zbu2i8U zf{d`<$~-!3k!~Z0PsS#(99gC}jZ938s<^4h&HG00UkKmf7MI(RR5Q|oK=&B&wnfWW zqG)uF2>Yn`L7Oca6ANWBI&8fipBey%(p;8 zctZO~le^lnjd`M~4_1)!536D3Cx5{dr|V>KXl&wJKh0&*^WX6k+hL|~>*}&qT6~pm z`9p^BASCY@gB-~GfCv;JiJ{}K7RyEBbno%RkLOoR#pIoTPw!Fj+mHJDCO5mbD#Xb@N?4I4&oNc~;{RS-)+RlV6 z7=B~mF|FJzEa0oH^qtUCSmfkwkX18D%F7X+H6_H#5#jw-el^Hw;zXv_C_pV$8Asv@ zCjX53b$^`dV!7+ChZZp=g-1lj%F2(zB<(FskR>WBXVvPF*F!^7+gRLT^8TpTlGgu6 zg?M_9a2amV9D&P{J8Eb2U_@9li+OO22Iwn;i3=GI(5IXc9gs9kgQI)P_wBOfw zzr-$mY3bRdzl2-N`~+qG@<#8}8toq8?HvHNmiQs5|V}-$+>{S?_dRldqw|N(f z-e%2QJ?^)Itz7GR5o>{YJnyjvnL|em9J&1=SkYY??blu)RR05pxE2RW-eQ^wJdPWd!jq1g!WLo!1Pi7arFiRVv`Gaa{+_mQshTu-(qSZV ztJq0f!e{Y*i8pl8Yn@F+Wfjj&y*y7T!GJl9;CoHI`&o0Lom|*s3lKEJ#j{W=KR)U= zc8?ma%HHP9V=B*hsvV;9mPF|#a&O%#@n@dDsn8+{F~z@$NI*Y91I^bhRPy%qufaVB zkRwi~m+xYtr;9XkfJ)cBvHf5&`;wXnOigd0!lj7KrT*Ohd;uUVfbt+LLv97r&-MU( z!#{J7&Q1|KowHkG{``7OlMdZKDZ1|k!+M~#vEx2w%lO{E0FMWX5d(-%bGZ%Glmq7T z%_-qkkhDL>z*Hh<@x~7Er((0L&@yL$2?XmoMg}{U2m%n##6CL5-{LK$jeKlj*%4z~ zvq*f;a=sw}kXF3EAOiFk$Q^#ovNcgi7R9M7vu9R;U|a5ZGGPcj$r_J{X z@_75<3*Qvm*?bho;X#OpbJSK_^;SZdto;P5~H_U^q}uz|Udt3N$}hdP)-rvL8H zo1+>(&7&=2A}y=`*vMGtK_&rS%J|?xW&j4ypy5T9fKJMRV2(SYyKm3%=0zp|FjAE= z1*=q}!|Uz>>a3FBK_kHwI~S9Von;Xc7Z;6!u@vUqv}?zYK_mSN1$oq3R9KnMsq`0O znfJJ~Jf{h~s-w!)MOsDLn4G)dC=yYW*1TwN0%CsqWae|voRt!q8n{1K9KFLYR$fb}Rg^tbfm z@UpYoD+~hW*D|R&W`h?l@?41_9x*9Tw-6xZb?uE0l1egK{gCJd`OApTF|syk+@Qnq z_94;&@92*eB!+LaHE%z=h|7KGtv$ElY?`=dzyJZf=H;smvLmH6JwgfvK;^sNefOkl zAuS6$R#S|B)UcstL1-J4Ng_Km%C^9B9MM_ObXDHmBH51l4OtM5!^Oy!S>=3Djo(qW zk(hspat+z2?$PD73a9%VIMq&GA>Mp>DmS&%z2Ir$$&5su7!e!^2aF6!AH5_?QZ7kYd8$7!#HjUP z=XM<(2@NTJRo9~M7XX=q34lY#auJ4I(g~UHhzl* zg;C>jA+W1=JnFOq2CvDfY$TgWBRV`sR_2c+kFgVI57fB^HKhZUf)BDxqOp4*nTh>}vP>s2S%8&p8{;UK-0=2kuRH zi>l+xajZs{ZmiT(#RvBiLA59M^g>h6dG-|)oRQ@K|BO}bV%m^R%?W5QMeteH{Wfn| zQLTx3Mh6+2Py>;^#9!P~vG;MpVE6Km&4>Sd-9XvlaR5Y5xLb{BZ%#MIds~W5f^~~_` z`fw=hVy3k1_cvK`xpo!00IG+j-tTAse?SJ|=l5a<4Ldltr}Lc=F95w7O=M zE=EU?DMQV&7syH^KI)P~pivb5X`AAD(RW$^;OX=_BBNn12_9}h0C0b};`?$vv!&@M zFw#G2m4Z=7BrF+6X);9tr&gz5b`=spEs2M7B$=D2d zuGR^6jg}eyyN~H9^UeBep2IT z=>PQW_3-fYfoLj;>|9~vrd`@;&Cy3b0qk0yiISn2h|`>I2zOy{R(%_~0c>)~K&~(Z zg6Kskne_7di2Ri@?*8gFUb9X+!-xqikP$14Obv{f(JqXvh?zY3`cM4FG`YDM*LpoNkN@$P1wB=8lcbEsAxi&Dwpl zvOQ%$VIuiN?nlD*Q1KTn!_nX<4YP8PEX>FW*Axew))ULxJUa2iXvD4cA&W*qy=CiF zhGMP@(AI$75!H$)MUErY&ifGR>nrUd_x$wykYBN(JyovlqDr=&Qx7k(TRsSyDmh~|s{gVr{5=0HhGq5}`7Yis7Ka$-3o1OnNa5fh0=y)?~e8A88 zuGy5g*R0c2#e&qpyfmnx4oY7s;~GguhuLDVM4_rX<1Z%8MNMe`%ayKL_ei`-Ka>jt z(HgQcZW1~Yvze5k1SYz`LP$+{Voadi2_^&{D|Cy{ z6$1Rp$zom54s4Axs@R7$@RfB)+{i{3@>Gk=Q827oq(S5%uCu8>VhTV5cruWRCUy># zTbo}xbG<_)qF#Wf;w?KMzb!Wu6WVO46 zaTy1z`Nr9dulN*((5ckpNR8+k?V5PjN#F?ja~95=3rN2@>V@3|lw(CGt+)$poW44> zDKN&fZM}GugYamj|NR8vS1v|3-n$Ur_T!X{$-9cCHCU;!;sHK= zuH92ubVdG?u3mr662H>qFzg5ks zNYXg7@!MC21`1h+(F!1{Iz(YN&Qm^XW5jiHyzGDYq1%pm@H)_N4#c#z{vM|}zhzUe zI1_vinz0iusuf%{ukgBfpi6!CYJj}=jc-JAwPXn9)uR<=pn+u#)JVf3=<`L2M-|x7 zw>EpfHeCQX1f)!meoe80kutzQv_VSb(^bs~Sm`s4_I3R1069EMi7ZlfzN=b??xIT@ z7%;K>Z4t_0NRnRe`rBMi8|nGNZ;2=KQWoxxvGUt*l{|2fyo1}>9TltO4Y0a~#3pK1 zyy^r}2C<=h`)7pz0hZ@8-)_5`iE)ZO``t#SZV=t)g6rT!uXg#*824fF$&J+;ibKY^ zEjvrdx!3;ZVvwC&<_!J`e@}|!&;oz_A-tyrDq)V*ucVGv+nW~xb~r_5lva{oQ*0R} zS#pu>Fl5S&-LOg#nsw{PIDl4@FFB{e>|b4qv}LF;hfAxpN5R+|;{*qWPJgJJV(raK zH8NOIQ$_wpz~h+KN_J&5BE4qj0>8qms!lZSo>S=Ll=yphkfW2sS#Tk9r?5l~lc&Ha3b2KL_ww8y@bQq- zV1P_K(e^ND^YgJ4F?{R#dV4-3c%9&)uo>iTyT|v#V>4|j>S^>EaRd-$dwuwKndS@N zWi7cxCOG_7e}U%Lcev*UuPD>y!peOAGxceFJo+5bcdqyb3Bi$mlmqzqvqQMo4@mpM z4DkLs<8<8X^SS^00@U2+&(4Ph75zEIng?7vJ<@N{Xq0KuRhhZNtH4nV)G8JH>cGje zdL`LJhqYjLC=M8QT_J#%R0&T05pyj(X#>wfit{=PhmdIgl|s$b&&ZCc9wLW58LTYk zJS4&ivZsn$Nj^8z(TFV%-L{Yll+`cJf2XF8`i;|;WF_K34tTtTe%*726j91_e3WXj z?e>o4B}H7?@4O$g{2^8vw$yT+S`gc7hYhw&3{J}PTg^u>k_%}HLsis%lj2n$={8ua z@K2~aO!(Na33YWW+m_{NVk?ILf{wv+7~cpnaR(lG7z(M;{jAY!kh=9Eo+TH5FvTJ@ z)Z`=Zb zgF>PF%T6jpLrkT5(B#kS6O$auhlxJ4L3LHYxaeg&Fo|G~j?vZQ!czaV3tE~2K1DI{ z$t2Tm4nnn)X?Dg8U9q6J6{-VO0|dD)8SO2~OQOFDK#7+w6+|-zNuV!lmc-mm=iV9@ zRY}c-z}TAY6I!+;j@6)eT$x0)2d5f$+~)6bdq2%tP8O{@4@X2t&H+yq$Ppc83tFF9 zP%Jb>K9Lp1D$B9_fvDOlr(~@QNxdoXqC~KcuFP2`P?=p7v!ANr%8dP2G>xn51=+RN zF%20yAV_dVfKjxt_`|geBZs?B)-Ou1#bdbZlLId?IyvlIN%SdKa0LrI#d0qVPfc>g zY=1NNA!Z5gu|Ti!G+}RWtJxmJDjDmlU0Z)a6^llp+dQrq?f~PuUudnlLr2di_J}hu z*U*qJkGUYBi*VFDQ7BMv71|))g6Xy2 z-{`>s4$m+{@N<~T$0OBhs^V@c<<`;F=;RP$ZXePvOj2Vj_B#=1IOXHvBjt1GrDFLI zPyj)Le;_#dhu9BVoAPOL2vR6;SH796o#q%Td9v_Mu$cTe!W?X=&+vq z@$;#L3ckik`h15L>>m3ouBAdLNBv&x`R_#);3=eJ5-jlH-K$?-Z6Z|D^_g_+yJE>w z46|L7fC%$f@sXnV^F6YM>6YUvYve9v!t?# zh9nP>`XrJb^d^eGNpwU;{Q(_q)u{!fh--T*{LncyX&)~Wr1iiEN1sxtgP$HgR>y&Rh0MI-Rs0T(!t)c$UwcMzrsw{~$~ixrk*Q1wKuUIBgSKFl z%BTC{wt)Vq2i1p^%-WS>$|vDpIP#s6U)C9=2v~8Y_bP+%hNyF`Pn)56}41jG^i*T&hPxtGp2VrFq0zXIb3G)|8lODPqt?c+l zVj^D?`Ks&*M;EbId+~g%N#I(g^1*mwtZ`y=IK!A!7&<>Uld8(1Vc|ip)pAx$l=JQjU0z8l)PiW_91_~=g+?JsxpCaUU$CgE^T~5D zii{+b=oFZ+VuvePuQkp9HO8R~#cYL4Nf83$Oik&3wk3$rvZm}qnb`L8cEx88AviU5 zBKy;*UR=p+O|yAwM#pSI=WtHeMd^9sJ8gC{oq^c4)yAf}-KqgSxeqt2$_~0px%9!G zJS7TX{;%j!aYPZmFc&aJM*prAn)s2xkrtF~t?p!0Ce32!ND>@|=)Q{7_9-pNx;!L; zdm*aKml#Vm|#Ub>ek;rJbnnB9lf!{yk*K>$1Nh+v#+ zf!Msq1JqxVuLiM6w5~_@&OjEtEmVsDBnubDJEJbe8>aw(OI=cOBh7+zZHl}gWro3q zZj{CGI-rJAX&0`JI+R}~qC$&oxoyMSA1<U|%h^;G{cE#L$Hn`Q2itbz&}XiuCS~Nex8X z&SrLuL{C zEk;hFWKQ%WriN&;nktt5>)MgfH$8Z66a)c)xeD1WVmi91qqm)ub%1OP&-ocvj8mQ7 z_U#___`9BYJVd06Zq)6fz@8T&1NtTY)TPf{d&XNk*indLNw zh5eZW4~1@D%G}J*H+HRxFsFI zVhy;sWP~)azjBBo$;Q1pAe8?1g!XLiP1;j2>Wb+1Kw^Hci`~J4d|Qs;Om7pB4DvHEw-F zb}+$#8*NAV9pL@+V@>aR309f#KxH@IF8LC%Om8Err9xuIN>F!kq@$H@PXs!FXRENYwC^jvo*jm zqU@aH#hNtugs7?%HF+Vfr850ylr1A*Kif_GJ^ET^(P!evjh6lXD=n>3bp*$SH`~)H z9A81ia;^qxg{XyAa+B$u#Z3^`z1$yubrDQC>uK1Dj+!nU-^0l#z`nEh4oJ++Bw&Yq zu#(-b&;Ub+IxZ=Gzysgh+^!YmTpoa{6M!<3_4V9ii>1)RYknF?-*u?I-USyl9(fN1 zKX<1og0`o9hK>p4OGW^(ZbowG>Z{=aqA^{?J>S=8zf@SU7PWoTmbI4pLt)F=B1_D6W)2Xpq7=~O z)>PSyzJb2JG4G0vf!Nj7k_vmwdwQ=`?o!sw%_Y5=f?tMu#p!X!9N19Bz5?u}8cQJqLI-hQV;FBZ>0@5(#? zZ#Qr0jt~T`Pl!)xxEfA`Mpm0GanpwQY851xJQ067cA*+<1Lyjjbyb7k zEQePcPqx7xb%LH)^{%jZ{2dn%`$;c!_KVctH7~)E?J=?K&<|+_jsS>RylV5ZjFdu- zc7H?v{&Lsv_QgBk9a)(o$sS6KC_G&bI%bM}+w2cTC&-_2K>fD!u=_C^Ces4&?If(> zV2*cRQC=gICO;pcydQMDyu8%wnv>8W88_dF}M722qlz zuk$sEDISu}yvS3*C;_%b&w?9s_U*k`V0q;eJ$=w$M<67}&H3#(iQM2x+nD(;Q?FwzAq#jn<&!*e*p+#l&N>EhDgxY3>z&k@vwS!Pk>n`A z4|C-;*T<1D^FiHz1wzkST#mNyLDHIY$XXeTVqKWV4d90YsQc2`kKd82wJ2#*ogmp@ z%`_p@DW&4gyeC#7{pvZB{cU38J#1V^z^5y0U6O(3g^8kvinTq?O`;STo5QTW*tlk7R|~w8Bhr~2@_)*y3IVtdYD+OGRyu-)})gF0`HuOX2 z9+*Wkn*yfg^Y&-r)`GG1@QY5#8BQz_|r=)L)Nl*|ya>;QkQCI49R&k)%e%E7LLNM~G{B zZRCjco%F_RV|Q(w*B!?Z?QQ{Ee70)#s7ec(qb^YfCqz~2(`b)o8p*^b!f;fL_xL$jB&Kg2sG zM$(9A4EdEoAuJ2nH8 zzA0MNz+Jl9rGz>{LW>(|Emt$y?|#S-gcp*{A|!EG3>WEt+N(+=+?&-SL-eX1p{XWd())J-3s!-1oeL>8Q`I5VLM-*P(QN0Y912lV+>p{ z(8qD58}dypw;b_T)46c*{D#;aCS@tcb7F@@AZYmWP;Ro*;0!G+6tStCGrGdY^Dhgk zr<4z|g*|GCDY%rlT(i%{^=h`8I?gB6-YW_yN`qCU`X8?$S1Hp+CN9QIYA@q6K_Vk3 zY~DCp+6Sdw#;OFh`^ZcV=`2n|XjnMW3$M<^Lhv3}51zWu4dvOpke|&upmbbyaajqa zQCc#ODulOT0|Tcbr#b`+u@tV|Ob+muyTSg*$?&#M$-al0UD1oA4D4)HLNRLVm($-h z71#9M0s&j@2MiqU7lQ6dlq~YA6A6)4x=kz#RNCMpH{=_r68H1|Sz3)Mf|ySK5gNVJ zFGri!F%(~gaWle7LYl$R9SU*}iXDZdQyiXFpb?}ddX-A$=3gfqC&LR4vzq|-w%x=K zZ1dAS5OLZ+u)3e;kUn~`etEKummqpeLeT!uE3&0ez>NJ=m(VJKEnu<=Sa ze^zlqxkbe*UC;K;{a(f43~{NRuwzO4Yzt%~J5dm=r9beTVjHA26TDd%wTFX$cvLD4 zXtj>3LZ>FkrMo-5^b0sO=I{VidEnpty|2SOnGAwd6}*|I2SQ@t)0yiapm~PJTKeu? z&{fMPcw$^{~@$Oci1nH|RtZ zoYO8!?w(bMQ%5+KiVu{E594pWz22X97iWq;ZFDl1;noC-$M;m22^WAy6LRje19z8G z#S|}uhw^N@#>Z0(3|OdT_WHCP(0s>65Rd0k^q#WhwjTWqx=87!1XyVTlzIeYfu4X} z`5e~p`blcN9qAI7a{dd`+Tpu~$JF7=IpHn*vy-hd1T~~8PeQ&m=pDhxgzOKYe&U1yjXF$GSVJZG_%Kb~p z(n0{EyHbOt8BQ(;6TX??oRrkuA(Pmz=sW~B7{300pJaV`{Koht(NNeZ{xyOH|I2?_ z@U_MICv2Fp3}v@gy6`d8w*&!uIM1C7|Bw(gxz6o-QBPg6kWhe9KWJ+hX(Z~9WHvb- z^!1EK0!32R*8-`Oyu93RJMzqR{(tX*Yd`KN(7|RDld@ux=rsC*$*`UPruHeM0qBJN zWNd_yi6w%=NrJ@Pi(|Ik2Exr90ewzN|0p7lO zmC9n;Hj|T91!2xQ-_V%x{^=$et!WL6A9UV3u`dDXT0ek9LC&ZHvkqyguq0<|c)4NM zCac*%a>WxR!F?c*{sPVGY}Qp^476+#ScE6g!G6d_HrG_jnVQn=_Ga_)6M$SE)9)el zQM*PA2uG3Lg{l@}c;D0lMYGoRd+|sRzLp4{Hhh=Z8Z#US_)IrH5L#c9WB$Ko_Hm;b z^-vs9@BIKe%be%_1vV7zMCRn=mwO2cC@C6D2fHfEEgVX!5}kXi==xdOwwC1$v>~Z} zn(wU>poQr!vk2PegXW^-^R40Tkz*p#0_)IAyP2q&{*ppoe06L0m-k)W z%@6phNzI&-?*`Q-F@e-QiLf7UcKBLcj? z1U^n@raBn=-`-bp5E~3E2FZR-uBR9yaoqE`BnCDno10P7yk|a?CXrA>V!Ar=yJUH& zLHTG}=Ap9jM?zSVML2_3$X#NOg)V9ETh3CEU{$5AQA!hv^v4CAE@g}4FX ziz0`y((89sU5^=W-WCr&Fy*cf@HXKX0~P;qze*Mi`!I&%UT9YX@s4xer_P}|*{-6F zrie&RgQk3VI$(T{E#{5*!iyyc<3UHOJ`XrbTv~@*Pw~QY8kJ(USy+a~yB6>W_1nsY z7@ZDeDR<+~#1&aIg||&c9_H1L2!j61Myfoas{f9+i?Tbo+J0CKcqiyYt3(i@hOjHg zu+^j%nat%-ra^?EB#w~S185!LFL;HI>{0U@!78o5$*=eGFdT4M*Ov5p&3_4R}0|2fwD{B&o9pyc3a66bbR}_Z3GzeK6 z2;V9@%UOq~eyg>hsHE%NzZmb=;YMTT63x~DXn$Pj^j<;d*1`=GKNK|Ts4^NM z1EL>MZ*RF^(4E#P5TuZc4cgS}a#d^AG?e|3zl_EgGYlz?V4O=>w+G)*pDr}k1kT#B z5CG~vYAN^{k3wyckP{^G9BTVREnwsUgsOH<{@<*OD9X+QK2t$%pNHDs_3dd^aAoxuHb!K4 z6@xhm(@Dq`fAT1HK@L$9c$U~k29Y^3H2@Hb{)f3k&|+6oVWpB$BS##%@UOY_9Ac|^ z8<0iPb^T12*iTRN^?7x4`PjN{A`6r$LI%s8>+kM6ea(FQMBvvI*up2tA(dEjubX#1 zqwnL}(dtb0t{Utl{z*Ygx?gs@DaCcCCwILKcaz@T=iy`EBAh=C`%>u5-6EuhPco+5 zy<9Ffntj;2!wx`WkGEM2Y}uJHu%#Q1F3Ndn(lmCTej|V7w+NIs5d6Mu zzr_*0M<>(;reFDEvEx9w)GEgj#$w+4BQfaXyYM<_5VwzHuNkMcW)9|TS1r9MO z2R*}B%2jsq4xL6tg(G-9xnM`BUeC=he6{cm~N4@;l2MTg&;d!;^DQ z-KM8)AoqtDUi;O3FpN?yBY^~a_nbmr`On)GLC%x%L_N>lD zO=-_JOn)e=prAgXv|aO^Rm}*y92h-CqdfgmvgLt$)^|h64x-qe%nDqdk!Oj_L=kXN)9~wG z=vWUu+p<2GOyI(BEJJwT58?lz@BRZV>fp6Pjs*t$58$?A${P6|?0?Ha2V_w2|1HN| zk@Z3Ux1{n!<^uaK47bSi6Pz3r2&f=q-W3_IBgz+<8}z>o_@jMsAs`?iy^Og4Wb%yM zIxrMIsL8n*XL_37jE6FyQ|M$E=oJ`4X08vYs&0d3%xe9;R4rh{1uFkk@SqeiT|oag z-+zY6&;TGmp#EplF|p%RAXp%vTUsC>JRqP9;$$?m497rZ1ONw0|D~o;8)Pyo8a+4l zxQ6*^T8L`Z=4RhWmsYBFD%32~p{Te}^Em6{UI#7_bRZbDcT0u(25F>~-`5xcjrn9!x#UTlJY^%zA_k4=hLwe1mjxNRb%L8uDcH6%9?1<86luG)E&OvlT>-6 zMt}Fx`2;TbDIdgvlD!&L`qAs@1&-s1OyZ++EaylnObPvyGzq&_&QU5iSdWIR;&@gG z^;nYzML;}yNN4I^O&yBVFwg2rJ_|*aIt*d^8Z-qtFI7|Op?vp+MH??vG(|U9@cEJmI1usY zn#LZ%EI+t#lq)W>e*)~r2p*ohkqgi127y>C0$MZs8>K(lW5vl-u3r>3H*73 zN>u_H7tg9U`s&lPi6C!Q{x9&FXr+gQ^ObB4t797WGmw+q@wG?z;TqyDf&i=18Wala zBr)Vrl|lPs$5z=321ioPSO9co5G)aQ4tY@NL(-LtS zvOaOPe*6VX7BcTwZk7}1nM|Vccro@oh-T%69KCcz7cT0OiR~#mMWUJHGFpU~3@FioOAx_xinsq+-l@F&^$7c609H_>| zi3_!DKxAuYAITz{8t7lTKUJ)1sv+pga9J1RUCbz#BeU`?8v+T~wlSmbXPZzQsMrZ4 z84G-2{81WW#i&o4m{1_fC)o)k+JK}k+Jf3%15E~5MX^6mt$KwW_StAXUVuP$03dRZ z^aE7Kw}u2IC~U$WVfPgrBbg@Vt1&Ygq#wt|}bkfNN z>hkF{)PYnQXqOb8Twr`UNgPdUlR7=NCr{lTuiA;GPA`QaiI)x~^*QoBW**bc^zg|Jo^Fn^JGP5xW z!kAUVc?GPI){EK82n%i=4uB!vdfe)uVkcPiyqHU)7b@(RR^XFp*j5^cF4=J*%oJT| zkx4Q$@!JmdNDF_bN`6GBcQs;3=-L1wEC@cr<5$_Q8meaD(M9E|8&{ZS)ocqxU0w)x7yvJew}o*jPTZe( zI*s<$4Z5)-loVYO)Oqoj%|;`(5GBDhz34MeBeNoDNQB69ObAtB3(&g@X`- zV&Xl4AOA;gx(-g`jWz-Ph%!%57+6(&^IwjX;VF>~a3=qR%?2rp3s;zNJ=Z9yp z+`JYFh0cGu$0}^2!~g^OY<7+=D;K-jCT`3Kzj&`dT>bk;p+&FwCVRAY{l7G52+9$> zf$MuR&3(sgb07-NjIkIpro=lx4=9UdM+mC3B`a83<_orGT<#eRN(blyb_Bj&4-W!+ zX>KLYf0)kqWZuVMKwT_bXl(@$g>#tv(j1c7OAQ}tOSvqh2m$Hmz;0C!!WDF6(g+(! zb2K@pc@9xGfmxF-hyXutAg!kU3+c?ZD3up$&0V{Ij{o zu8OmR6`1cIBGhKBvQ%6jq{kUcNJwD*Z@>=OeHV_2DW4-2@7z9XYZjO`8x_4JqI32J z>0HRhD*#+ZSAPGrqbh3J>oid<&)EL*s+wlJx+3enf1>}8YX>Cxkl~01t%)#+2_yII zwKr$ZzU9V*AW_xH%whWMF=pweheaMSfa`JO8V#-Ja4!=1d#`2A92bg0N8$XMe#=S) zIv~n-sECfr3z^Wl@9$PXCPdCtPF)wVefals3&1Yv`Vt1Qf(g7k+UB>`b>_+R*nxe* zFu&5FP5rwuwxQ2)c(1ldR-I>GivF0>H$3TIQmqSAyNm5rGvIG&t65Xe3s6L{9JF_u z+_C`N2PlZAdxI0sg3l?+0aKbw9@Om|Pa^x_>xBEVfL}(Og*mVLv|xMT%uB&WEWp|* z0swTL>tuEmPST*_n`_c>&uRS(R4%V*U89v#rMfTS_K&A*G@Xe9s5*0~mHgj@9*V7^ zLo6;t*_9aigz{Lpq=rs9R%xsO@8)S<7FCs7iXHbjf1&Q``Eqpv?ACffxt4{m{zm8@ zu~Z%(>ejQ;C5lpkH?@^gdOuyDdec&=5dhe~QXJkrO1SSvm;J|`R38=%4!WV-|yb}bYwWh)}!b_^aj{-lvhWKne)&^c4?wPVHb zVnotLot{tzTK4X*X$FW0^1B^)GCDWjm;CgpaK|` zD?>>)^q}}Y{-&>Wro(Pu*cA>S6q!bD*X4%0*z5)ugv_%a^v(jAM2VOEl_Gznomp*h4>4g*cuSPUr(x= z+ezbUo5x0LXqQU<%^+uGzs-!kBnOz{#^-k9>c~<*!yCT-m0+~5VKYyCNthyi!&)O+ zP=Z{b?9WKZzK14s*mHwoXE9baowh~$hDRK+KNk1Zp5KS;J#;2uhJhvtiWN8L3$9+N zESj7%weqn z8v$Pz@D5y@$@zl(|5xZ{7V{8qa3G*Fg#Tx8-j7Fy0chGg9&x~Z-xwCPLD}t*D`a27 z&}qHcN5HRN2kJ8$$%2SBok(cv!jNs)EBzfvNd3gA=(B%IoJWxtAR|oB9PxuF;(U^91w{Vjp6nk|d$nl$-j zBJ1Ed35ZCO+)t5pR&;>I91~bYFcQZ-@izF)lAJy&4C(TMZWrA08ifCJEqOO9Vo91( zCXCDSZi0sSG7x|u(i7y^jj3Gr<3r0WK1!ru+*a&sL6e;UXXj-w?IwaK7xHEaApJzY z4-+K+mME&M?G#4tSLUF?rM*$w)@BxE7QF{41Hk^2A=GgY+Q#tCy9@p1(Q~{G;ZQU7 zf}I-$YcTh&dJ(RRC6sGX|3Fxrr(bI)@!|R(uD+=|vuN8kwr$(CS+Q-~PAd80RBYR} zZQHhOr;=0qo`=)+eVBh>%+}Uevy&+v!rLxc{Wq@nc1v_t;_J}__udMobgWMftLJz8 zk!;i6U7}&Y%I{6cI3Z->mT7ZR4r>z*UN|41;_#x-9~{{!@;)o&UU_dvErgsRfOHTU zm}X?@@xf0A6=mclWv;BXO*T!@LCd)Ku531S8G--f-?Pdi5}-_C0sS{h^kb_`CL!5j zW~7BUvV)A10=ht?73DGP8si=Fdc-FchRDCFtM-zz=Ozo$E_Fa*h%u!c!pjNc`}%^6 z`YnD(svu;Au=!r&@dWZRmI40$07aUyC=V%tK>2i)1YrZsepX^169jMe+)|eL`F+b5 zWijRL+0@6Z+kXjZUW-Tt-P8}0FVMZpDY!V;R+a=dDZk>anLf10qRt)+bzqFS@KQO0 zZ4zjp-DFCKuJ)<(1Fx`#+{Ua1lpA$87~dBPsAp$o!Mb_QDh30ignVc~xx& z4*jTnMNehpybWEUwTPUN;!wRBksi19A}o-^4F`1?4Ap9*;5F?)86s7}?Bu-Ek50|L zh0-U5?%+wQa2=2@ygyy=mN~?8Z>H$Hmut@3hQM=PI$8|n*zOp%r+qrY;9Vhp7vPpB zcDmJ=6TsKGSdX*PQs}xsfXlkzF&AkfY(8?2T*1E*w)zY>JnBY2Q8w-ygLLj?ZPxyq z5=_DRVeS;@orOlb0xGpS_U)Tc{5mX?by^xqRwzm7=gryPkHKMWFv01Gncyd@G|SW< zdN3z6`mLWG5Hm<@CyDMF=GXub#P8j2+;WKsEQhaGGZa`@07O z?d|S&a|Fg@>S^&`E1iVJbRJR;-ex{vX1t=p3&PDt-ExvL>(FMHuW^G$Ddx-~k3<9Y zM1{)nRLg|-wU+Er2h>|RlhTx#JIK#_><{?PX3o$(`9;EFq178cH6sTa9>L8gNm5ad zc3g@;qAZlk+m}{-z-^3&b+(DHQ%qy!oW84Ua)D&s!BasH-_tLI{eo|3RxM-4gF$>c zpQSC1?Z0Wk+tFdx`_vY=qb4XD!q-auXgF^+KJ|7+TsGlLkNBZKfs3Fnme+13*PR^b z9Q$0b!Vg+FYt2xrflN)JS}JHBC7+*qHR~o@$>q4^FRG)60Q9PLZ!dgxaRMeYe19V$ zHI>rmLHDeAVV%Qp=+X5vAofFL!%C>v{Xw)}s_bYya@Srvo5H0HyKJ*TIiXd=ZC-s;Hc)yGu*FR zSCe{RmoB7{fZr)9P7cNYk_Sz_{oH(AtcE|9*B?HImk|kTYIh4ZEfEF3j~`*tl#;w+ z&Th!41DYLsms9K*F7HRJ_(8Zl3SZJTd94xmrRwh%QQ#I|2^FAsF78s#E{@p&i}OHF za$tjn%j!DJU$0Q5m82qEUGR8>c^@-5CRc{cE)l?QN=ZNMNw$5*^0Kom79a8dw$GH0I`k%Z0htj+^pj1mHk#{QLQ z^=DVgCFiU_2M+1^HN#JsGdsyVq5SQ3(K62zOIhXho7wg ziGl563M%$#V{CQ}Idn-=`DoW@&SyuQ!ymC5ou`wH~tn%+dIQ$Ga%{ z8$@oCyXsT4`UM2~WY5v4#KA?s13o+-z*X28k+a&zg3Cc~LABMj*H|7TbVRtU5G*6% zQEehc+`>NsiQUd2Wo>#8>Jxp~LJ$W5NxKMwAbg>(y5Zv6EJnp>qCw&T?8#=H6LMKH zMwTkzV*q+)e6bm~rSUP6O6GC9uRoyQHuTK!g}Y~C$K{$rBazpJqG|F*d{(Tklw|7K zctQKfBS-w6R>W6Pn~yvGi&~TG7Ud*;#;u53a_XJ_T6Q5{6BKtJ>y}UcS=D_2bIPc# z4f{{GK~(Qu?OOQ~rh-FceDS+3ErM5tA|*3WLOaE3Wm@hXQ3?7o6Hwq>@*nts>ZOa~ zsj%_;(I3#j6?(X%G=h0%68}hK{*B1K`y541BPRq+&EL?&J)x?4IGgj6YWPnEEfWy@ z7k1j$PiX>HEm0M#>8%RjBiYaZJ5WYYIJS++r9mcFqP7;GTf0<#HR+0G^kKPTm<9DA z{leLO(35E=Fa?1caNkqm*wEXCCR*n9a?rqANkNg|*3e)zoKH83TV*eeIpXG3FxJof z4UWQcJ+N>3j^64JcX_AxGajOss3tQM-P_3-gcryR;%J@SgEpH#zQ(@*d=veV6bf-` zLio>yuh@0ii+R;bkjZYd7Pfc3!NIBzC6Fg_JM}x!oM(#KKM*_ll0g`|xd=oXg*Qf7 z276t}CSwvHjB9*{cD>lvZ9QBzdeQ%)@_yxmH$2&MOc~a|q|8sOMb7W<=<9M?VAk$z z>!PC3o4)d_S0`R)CbR$pHi@Ofy(;Uf$Vc+rR;1j~Xd-6$m{*9geeU~SU!xILXKfL; zN(gcBb{r8+d_b=!U**RYUK9NEa@pNmU^<7~&1NlqNq8;FglkPhhIvOj&^)mz_=iUCXQE$q!-U_mLq*>xU#JoC>y5CGB0$3zvW`g2&qc)2m$a?ea;MSG*t{ z#~9gLq8TU2W6GnmG+A#;BN?Y$8Qc+sX9O!N@L}>4Mg~>>sb>=0naetCcqqMlX}bw7 zUt(h|7VMkbuHj6NPz+8{{mh)tI{I*uo7K0;PW%3=5 zkJfCf9e}KF{y-Z*tL6GiE-Svxqx0^F{hjH#?ekXrMQ)L`Tm=X81EhEj>V% zA@$`&yPjnFt`me8t1}tI=OX0l53CmYx#4!rX8tBD=W8gy4&l4dUN-kzx`QSMwd+VV2fIj7^r{MKd^O@J;xa6$-Zwvf*@Bgi%vw!Od zUfCnC83Y&zsOjG!O=a3g#!AIXL_+|W#ZFrfG9d-u`bC7`Ek&Y9@sm-bX?sIIp-6kf zuGKV#i`%X*D_BJk_9UQlCK07tJX(WDG6MJR?4O2^P3Um}GNHT){^FjZBoSO8fH=rZMe@_Rg7VJS>hRLr5YkVxVN> z%HEalEO=yXtWz<$kC7`M&Vro5z)>M$$Jpz0Gg%=K7bRJF@zJO>xk-HSs(OZW@&-=k`!%S2WKLHN(qe$RQ^0MPyoP31pJ95=Nm z5e*h_&1d7V`72@fnfBufF~QudCK31sV}Q#4@E^wFVw-z?1(FG$ma^91Ef>!tP~{2X z()+ifg7AtWGa}3MrOt(ts9wxnLu0kGB9hNkau>f|JZJ36Z{ot*>xr_91q%-k4-V$u zpqZ+Y()Kr3w@_lh7qm&!?JMyyXBGh%9YdJWZ<4N68s=k%O|A_-$Cfxo0 zE=#1=^9Ite3zhSmdfLH(5vOZ9_LLq_b7UZ=%1X)vPI3)5&x!et)3mw;Hdcg&%5iE4 zTLBUkNAPFBHXv#z>#yg-%>jb|f4D(!=WiD$41?UQzidVas95RZ=s$FvxbZ`lSQF#^ z-~z7&5#l9RSqm@diU_tS+CcRI*(1ls!W^K}1kcB96NkMn(8a)5mQ4GLY|FJR%G4-IN+Iek5}=fEbZbAPM?Vqy`Ak$ypkDMTgHZsx>OIq z;t-%f9K|6%Aqf1^#HYv`?-GuHTKS*D6pRJ)-+5)$EIqscANS`Q1bf|+JyJ+Okod%8LN~-Y zx01eF((Dhy)p90~h8JWH=4~VIrT??yLt!YL6CJD8@IBO#+j$&N3#d>w_^*Q0!!da* zP9Y&bR1hX39!>vwHR3mKiOrlkX{imk`P@25rLp71tC})#nFEXhrXWQZ|DmTzVYs^9 zkYj12U%=*~WIS<(5kSZQ7z;gr3am^MdpNp(ZnQ(2po=8p@)EK6^HGi^LTyZaUsIO= zV;~=hH2OH}MHP+-DSR&;bAT2!R1i#*>tnW^t|#@+w>DWtdNvkIoNtYmLJ}^=Oo=ND`cF) zR5tUcFn~6IM6FvYq%rKmiZp|Mj;9R{-sVtroyZBUHa1PnFCM`}C)R{7P$MPjf8$qLwcf4cod^bXvl z=Tjl#kNmAtG-QiyVOEj!k$DXoO1sRlQW|{XT6m5_n1ks6swe@NDCO=V#>Pg}mo4bt z(Kr-+5q~e~0(Otw+9CyP51#ko`Uog5N8p2WyPYaBzsxVH zaNsr6n$y4UV@20|-#lX`{cp($y>j{JZD04C`Fr4BFvB}*dn14M~0z{W1WyQl&UyG2*05t1m-QPnx zCIzY( zid4R6OvC{O2ozy)zbyt~=s3Zh_I$ho-GDis(s)&!nmZBNuE0G=dqnBc58!Q(j{7(Tgk0KQb;3)Bo15DUBl%c zHyYNFqw0p_L7dwQGlU4qMeL~E+OTwe2D;32K-QW0)AmsBP2D>oZUMe9_K;J~4#zK;vo00 zfX;bQhdlmuAz}kczo`^fJ^<3^HN0}dk>XRr@ri)otR`*U4tXQkHO>jZ&%fcAqwL|SR zriI$uK( zxzA}eK)H2*9nW0~Mn1?Luae1dREmqO8G^u^tTzw#1<*9r?KLK^>@VH2{|mD+0G%tW zA1|gWx(nMsLK{LH`540_$4YWKON||ML(#DYyV=F>jIZOOSlL?32u(f^Y|BHdg3M?Dfk*N0Y=A0cC7FuK%jA76 zB(mjm20#PeyxKQ^N8A;)2~w~B?&%7GR^sRV=Ii8Yn&}sKqm33t!&nOC9hu)4eqmJ3>wwVU7Lp>Uoid9`Q2fs~h-BitS`}cz zQYS|X_t#Dia|qx29-uzXjaczvDTI4G#&9`Ny+r~4pJZIY7SCvtdNC8cPW~;2u8#Jn zi^BV9H1)Nu@o=9dA^bExPD!@-KN_B&awG|gqXUhd=&}{1GeWfavq9|89kfZff=ARF zb^tW@(3wvjI4B-hSaWk+)-9Gd;+N4PmmW_cU8O>$73K$RAaJ!`uE5KHW${qc`ij2%Y{(_<&JBiE697!iUNJqhf zA;WLg@CGw$Iy|iWncX{`B&eft%U`}DgL>G8SpG6CiD0T4w&_->q{D9Vdf5^3WdSwB z={+|YL>}3I)C!ojCiLWY?Pea(BcMUqFhry6?te|qG)mV;X6BYA%<=cre0I#?Z-Bqu z$|blFVa`~+aiQnG`p7uA*LOq_2HChLWL%4iH(Yvo*z9-ObNvS<+8D@j$yp*U+|T$7VgO7`1$ zIn|}ja2G^}(eSA^?&oP3D|b8xZUKMs@O4E`U{-;d>n>poP#RpK_}4Q^u}J?Mxy*+Y z=iW@`%>ehWEKHz@Hq|{hbdKvC6VXUPx<|8^+K72q71qnGLw#Sf7=&HHG>bTmyzoIu zSkb>@5E>nUVGzklHX#xUB1|Tn5xDWE_MWg_W9uZwV1_AG-`W$vBP`cSArmPxxvlnz+ND6H3 z$ejacHnjCV9yTGVReZ*hlHN#HtXE_C-f1F1*4h|r8sKXqkz7|l)7|3^bEvl6Gg6bS zRE>(p@gu**Y4WHG7gcPSCTmLjd*0*nAh#ppv3I*Qw-r~$>v?A0oKi!pkkJ7K=2JWh$hi4VWu zSa{S^aCOk>$=23j#QkpA*k=GX50~Yd6+5n1Qgo&TVfhW07C%u4I+pgUmzXqnKiDck zAs&1A`vyca?4`X>Z9XqHtYl=dUY3Sz2)yzaA58-%x!v3r@4nn&4tG?Fjh2fHcZg7h zO4w|9F^X8b#a~s%%vUG*suuJVg<6k3?LvxiUX_iuF*yo+MyJ0LdyW7|f9PnUM#oqy zPIRx4VQX~Myh4$IEY#p5gbqv`6DKK3+B>@Vc)M+W(|b(;jJ28sq&58DT9evsU&>fV z^th24_^71ivWKiJe0JVDZQQ11chfG!cMz%l`FMb-yodoMCfUR}pDhFexX-yYf|n+B zx7s$*^Q~T*7eBeNAKL&y!r=@^t*gP^2vIwn-j+!^8RrZXb7Xx?ZUfWpJamgp0<(8Dt&#BI&<1I$Y0GvtFqg^aY%-D1u z8Mc%1&idhs8G^EzfS&mTqZ~@tA^BkdQr&*}!rwyJ_-&0!;t4=Hw$0@xznWDfVYw=; zO=~P}C*d^avm$U_39;+Q`6bhUFMbd+94q1!+|Q#6^55Wx-1;oT+z!O7U;-M(&J%@> z7W1X(auas%D_J7{GFD6m6At&hNhgeBgBU>c8aw~&paem|;WuaxC~GE_6&s;CYJXB7We1Q`6hM4fo+&C1~KRMG2+=uBT%SdZNO z2EBkb+dKQ~3$C zpW^7qw35wgQ)vHG7=ZRW1^yMEp%;4VWzGbzaukvhPXwV6>BMlw9jhtEe=uU3at7um zwlCxy5$h!BVjsH7clPpFIgT}y4I99Ei5~~2Zgz|1y5fGBm(xNz!cbVu z!=^Qg>VcHNbIW_ao8-mpY`mSUndgw^!3#z` z+z7x57rd6Xx{r&geY`=S8F!+%kS9{cqA^@gk5R<(ct$F65Lt0T-ROVim!sE+f<~HzvUf|9O}mb&EhoP)|l~%Q7062Eg4nvT>LkM zECb&WLTIIuQ$vMG@G`3kG5Er;t~WNO@DMxhF0^rf%Ni5;{Bc= zYcN5J{HqEr2IA|K`3iZDf2j2tqQ@Tyz-=3b*zKq%;7S}t7fv}N^D&aE(O7E~<0LH? zh*{27>}|ZBdN+>0Gea2i>fAI-9g5#J%9DTAYew(3oVJjt9#%y^QFhYw1N`4GC4p(2 z7tKF{(G3d-2={*hUDpO=3V>x~M9K^Yu9T}3O%AUu;Pd8}ba)n#%scN`O?Ru@x+)BM06Y*2xDqqz|Na1Phtq0Vp-J$vT6NP zecu939c-|M5$07cAtFyUm)c}=%40}$e(HAD9mlinbsW{M?d6F_$(Hb_2e5=|zE z`HE4zqc0l@jwB0@FiL)uG>uyBgiRz=eQXOZD=0f%9UN{Aw3yzGNupxGl_wj{0%_|O z-BiL1S(PW&(B{&a{Augy5MeG%5y3KSSxuTCl7%#mrI7Z|qAnIHB{7~S0mBOlOhoI5 zOujfU0YAdejM9uqIG|GQ57^QZe~G)J3okeN;BaLk9K=m(3h=e1zTa;B~-SDn~ z?@h9R9qAM9PvMgYJ31+cv}e*=;~^~8^h0+BM&{rNKUUP{MSx0jb#`>vZ(j%1^#?aX z{g_#KXjz%~$yj6Q2z~=pjblOfW}*1}Z#HmNt_<0k{V_(HsVcJaZ{a)Da+&bfer_$u zn{}CdPSQ6%%b90ieM+fTG;sGr8}*iM;z8X6P^kwWn{bowShDj^p6Y+G*-7A|Y?Dzr zwDDeyZ;529p8zOUbn;5kzL;L|Ssy+9{V1^+D6ct%1gM@~4=J#1)#Q|;?|6pxKn`W(9H|52bLFl;m{*Zb-ESu!4n zMjnSSvEUO-a6?;p?qxj=oGjDx(ZZ@G+X)ktqoWlRg$5nDo=g~$7uj_c40MTX|4Q?b zL+wMe*m|TE*B3*ElE04{G9{h0sB*%fg5Olam*F7rmGFX$Coxz!|4qD<7tG-=ngv}!l3Goceil)2R8racm6mY7a-O&B;L#kb zcpRe1z+K!lRiS!p8#cZdM0J*cyh86CPQk6yN(7Kxa*VS|``9D3FQ^QW#Z+Akl>lW_ zt9BkVJH)7EB4U5yiol_Eg_o5di7RMvrcg0rR=lRYL_h@(UwDlzu8ZWLO9sNb8f>Cr zt-YAo>wbT(PoPH=r&S-%zNd`GJ)-FQwq}#TA*i|R5I8YaLSjGi>Is#tmbUjxYyRX7 zX$3$FA^fiA?|rXpr%-Wbu$PS>n|6Zv~HGOD?{qw*cG4i zbqOE_j?P|Ic6+x$;cDtLvn3jIPsQ?KN=z}w@DdOE`1m}ZsX4UW2iy1Guq*RNyOk5H zt%fvDdU750meWB>&xW})ZTksX;svkr&H{3}w<}B89X_eMG*J`X46YygSIHNsjzdTT zhlHXBRi6%%k10fN=B#Sq%w_-epAP|1)+9~&lU?ydE1i=k@GPO!HcKo5N7uVhdN|9g z@eCV;xXY!HS*a=o)iYRC?YrkJD#6#dz-Ay>1?n}%%k1Q};Y3kR;BP&@@nC&M>H~5& z_1bVb8(y+jULmikJzhuZIyVVC2UTUIZrUOJ{I~ek$aioe+0DH1AdC(w&FlH!zX>H) zIdvRFOqsL5ZOEd%)Ou?b3l$QO2(p{ibqn4vh8GuVJS+_7%zI#;J8-YFCW3Sl7(;|S zR0MR%_Vp;3&VKA!uN!T=J-T1FhyZQDjy%3*DTD?Wq9UD{wF$(#e17~%won#-Tg4>z zW)?bGr^~-oGg2pl5k?w~&kVjcUL9!LnH@ z$Nnts$`&fjUb}oT{`c{=sD%mdLCX)@7_R|N{0{E@2#&vmy-QjT(IQMD2r_AKe(P-U?c78$5(k83Sd zfe0{OJat&Hgf~R^Y@- z+UOO9=X4AXAD(eZ_d@9pWk$Fs6#da2S>cOGXG7n548~v@2ku96Hk>iOyec{Pu_c-4 zODm8i7DC46#cso*X?Ma|GN%yM4xFyJ0W0Y?MeQ4J(5(N>k*eK=j4C|R;9mnPDp_1t zf=VVzT&3KUiTZhbeC%Vw8XVh=68%J}y$G%90*duiWoQ_HHBy%obmtb>9;d(?aTj>0 z9baviTGNHh%;3C^Y=ggD>-B{5>4FlWU#C}KLM#qsYAkev$y|<~xAk1AL`mJK-bITG_|J( zSqTI~iXO=SYhM_Kd@D-?Iji~1nOIxP9< zj7-1nF~C4SuCO#r;h(LC5|$~n?4cYP{6)c5s{@rLHJ}$c9N0Y-whvheI4M=H51E_f zi}_SkRR7G?qkgOTp6SQkrn1t8t7bnL!nR<`v{W{`aW%EA4>=aq!Rn-U%D^Zm z)4p7Y7su)l{1fEJn8>9v{_X87abE@VPIu~HKe7sxt`xgY5IM_KFxiUC<6|2f9;4&lid}>7P2`PhDN;9aD zErDJKfEJ@vbEz&*tY?!!jB@w^`J6l4u6@Da<8}c4Zz&`jeN|}dCCO?aeF`A)B9~Xq-GvjShlET;MlAD;4`e5`k*U=r~@f@r5 z%qh~MO?;pq6V(x#)APY!D2NKssu>Wj%8^`qx1s_=Xm=xavBU^piZ)L=2DC!VPN>W{ zje0#2-c;zs*UgzA@pQ%w98{S~-;+59gif%K`t_z-0MFDumNq+s&1qAblx&rHAGY^eimJff2>vFg3eQBaY8x7 zhLU5pGsmOc*|r|OA43}O(I*i_72TfrYmfMiFO#RQIA4?9vo?ryK~LB1Tb>Z9SP5oQ zNU~h;<5YyYURm|0xGv?6Y$%SddM5O4Uiegw5Y}GYi<0B4Jsl!Awjbr@byf-ld_+;{^3s(D(Af`wi!eQ81) zd)_|bpKRL$NJ0ZBy4~#T09^E4@V1BaG!x4=jj5}9$6$YY2l!3l0I^s8{B_-vR<|Pu zL6OzS%jC5dSv7-G$z>`>l#4?r&A&X51Nau`3oy1Ml1qzyYMvC7={cP#>7c{`Dcdo3=k zD#_IE-~a3T_${~l-KvUP?-1&s)Qld-e^J&cvf`H_V)N`>`QePp_hpl|;KL(>|_(cGHcEyvlnUSRvNA8WP-@xtrEl zt&JN_MuxeNH{)78fxs?2X+(WvSjdy6 zf->H*n<7^#4v37c@(ypPJm-u>=y0{H)9n&4P;sRz2Rie*ns| zw?GX~Ykr=ld_MmqGldIh!(_8!^93{6Fqx9j-%iAI*J*xwuD7nKZGub7E60TWz2FWHV= z_=|@~KuqR7IZC|nm+1;==eLXR-;?Gg9LEU&o-~c2M&?aRm;nYQx_EsrW7zJWTIp?| z16$$5e#YlK!?UWWRM8Ikawr31(joA;l1Ll``Kw7$|8|g~R{dFgq8>>@wpIc>KN|l?7>~J#S{CvgUT|kF8YOjqk|w%*jKIB zF%NtM;P3Jf%589j>|w#R3XCG8*bXcNmC*kAZ+SSpYlcJ{{6l8 zSo%lObu&Mhb`6UuhW^_ULF&$T3&%`=vMpuJ2wOYg*A3x9aF7_VZbud7YyNeYkN3bL z?rZoR{lHdxHXUTFR|H$erR8Awm@^_Y#V)4g2E+BK7EmB461FjVMK2i0fKb$wjc6z- zCLohZjIo+2whcLxuX*U1$m*WMcVYYpF`_Nz6p)k)P^Yv3R0cN5VX1nI>;M(OeBR$saRx{QC?K4z3UoQI}OD+8mN)J zgSmL#Q46Gy^{;Kb70YSvA2K5>E)o9}B!q&_eE~4ux-$==PvOt4#}h+{0ZdRcu~>av z-EJ8{tIdEEj)A?lgXvCd^0yekFpAn^XO|9I{GT#(P@0R;PsFDvR5@*6s)WOVOi--s zaeL^SzoY2%tn#oxoT4S%6OKrX*qDJFkzI=y(xWj8uwsgj z{p3>|SdD^Uz+jKZHvs525Z1D(U$QlXzhdzm(h{)L_(lgz<8B)j$s58KS_Myd)7**7 zqT02lOs9$bR&mFo()}?+HX_~dlnQuUKNANu!Mp5|l#F)HW)apOGC*{N;tV(=6VY8{ zR8*bJb{f?Ijbx2%&@maneP7_|TFDV*Th%bE?UdfNb$q z$q(8h2pe$zUVXU~;j?03Tv<)a`dbE}r?1vlJ&7I1uHO%ZWdZz}t>11Fi>I~eeT@yS zNRISQH2sxD9%j-&y~seSo(jLecwi5=KfI@=n`WJU{E^U5F%Q^-IjCsmrFS#Ade0=F zCr=NY^bfxMACy?YNsmG>wCH7PU7E}RtQGwfi}p1d=uvCoam#4ca=eQ=?8jws~ zLHEsv8$ZZeMW3P@0fa6_0pn%b!RybssN%akR3`qtPDvtwzOc%ZTEFM_S|MNTb2Kq1Bu`PMtdp8S8i)*=aiugd)O>L7K%eOA@~+c76;nK01UidQ zgD)x_tVgKKJK+}1sjG9XHj=n3C${!=DFHF5h)ndn0(y2sl#$3I-~gUxo?!u|2+~k| zmReRP^)h@w%na?W=@WAqoe2~mE==l}e1Ug$oQg29|Br~=G0;A&JKU;x&I&=NmNA3F z*BOi0mp{4lNBPZFnjpXQs z*|}oCqH~TK1!<&EYMrm$!BZ60EF<=&)>GsSzijnN6}uvL?>aE=l>}f8(kp!i@)))MwVsWD;F9d znaY~;PuXjV>rx9<1QwI998gJ1nrj80JF=;5$dW-YxVCn2*O+#%7E}8w{AZALj%tj2 z;!rZ=)JW4z4BXYicwBgHKFU3K%M+*ZEz3tqEVy0O5<0EPy~LP{SLydduYQn(2^LSw z4wZXYH>UX}WpY88kgIPkku0T6F^CZ0sH4sts$(O>iw=2k8SOxAG($I8`vVubrAfT- zn6e6(EvP&)ZOwmN|98#X;RW(6wIH3y`33g5JmNkoai_3g{GWP(jf3}#{#<57IRr6l z*cA?CO)Xw;vPaT}mBxk~)U0XO!6+^iRr<}+CB+u!xPE46gGt)xn7j8;^OqgK9>wFs zy6uS!A}k%=%@exp`|EMhSZ+YM)~fy7MN zUA33Hz`wZaTnBjtk>9;T*4m zuzMufeDLGu$w}hE%=%kCn%tXQ<|SH#vM&_#=*-QsnjTz;aLe@7nnGgIpkf-|xDv6K zk>vquynL4rLqgzzi`gLoY#y@Uv3owlUNmEe?pIL4HE&=wiAM8&L$tbQG%t7qydEvD z4n<3Cz8i#Np3P0+`*wm5dAkT{K^>CL`%PpKgz^y+`Np17ohGS>IW$tE-@v$d-tvva zEd`-pn;R4nTMam-542Nd3igt5sW;Nq?>vFsMUJjKUvPyQH3ezp^D*V zwtsE3;~RGP%sAQpqSi2y`;$m7)m4F}=so-*$^z<~MMqX1dsnsT?a`?B!I*m$u}s@f z3o|6=Vr!}TwFl$pAldKTX|4!{Kc=s3GP+K%P_xd*x7UEK{G1yO=#cpXONd$5X|o=7 z>5&qzlbz~xcn*Zb*m2<&VhQ;j_oj8c?Vrgw^EAJ1q}@q4T~+!?3{g^po7=BIBMXWJ z`O`vL)19;vtH3=T$5OR8taYiGD|I3jje%1d!fQSKMN3BHg+?xKaZFIV*HY9x!^H9$ z=>)(`dOM&K*t{k&Gx-kv55lcwN2Oh`%-ysAY;uqDYHP|#a9)043%tD99QJgp(dx|Y z-*gXtU23k$KUll(1CfaMBS3DBx6j8x?GmA{U3Vop6m^iaG{fA-o?T~;M+_wiI1VX# zN-GyKMMAi>Ub=s$G`hyl6Mz3^)O|&lndBd`!HWW@_+FLHk4elXs8CT;E*t!W6HP~P0zbNchI0;{KmN464~0&W*V$s_M}+n0DuJP_9ODItg&S1U*e_Xg#DdUJKO2 zrs=kdwv&}`4tsU$Xz#G^=B_aTtbitYt4fqoJF>fex=1-BbIo-i;8|~iD z8@dwL!%*3M6o5-+=a*o=5X7GHcn5O_b zH$%_c90DuEPC_Vcr17#Vby24;f#D!xwmGP;#^o8iLT)Roar*Kf3?=e(_nsqK8}Tc2 zB@FXla(ryDw0H1>YwOy9wj`8)pO=_7`rquK2~^ApV>-r{@+F=3EaI`a{-l{v)(?de z^KN}XbcWqo8Yeaz?=V1J*+fnLRe z3>;Zb5cdu|(gU$I4qCqjMlnw|khtK4M9yT#ygaXX$wg|#!JDHQ|GJO`F#4cxXJjC7(}2?oK8v)C6zsmYN=ft*c z>%@3tJ2|m!+qP}nHs+guYO1E@zVEwtKYOhQ)wU0<@}tC)k1$CS@aTI_R34|Q`v}3> zd^h*BCPQ{F2mG4yr%uHReh3=zIa(-RF697xD(kdEi&TgQlqKl>y?J$5ckMyQm3BG% zFXNwfbr~w5a)TAuJoJFO!$DsXO+s&K#<~8zzd?sPiyIaMjnHebSJo+szN;Pu3S>?I zbC&(LwRUI;X2Qbj>g8k?jJ)}h49m-K7ssq;wj?DU@~t0;d>0}~ zBizC17LWWRzc7qGIy^{IM&dyLBe8|8{fH3)sz)Zsk+}G&t;LD?RM$(`U>x=P?*I3d z*WPC9#0v%lG`MDm}F&e6(|(ZJ2jzO`=)*#PW+C@rVAKl*n69Z^I0-)R;ZK*#1# z9L;aFmg^bCG^jExxdrJ?CiSn>*#^b>wG6dL%E$}ZLNpJnGzrG#5JF-@GZy`&3j3S-eXL%LLVCf600P5j!T#OHoxs+JqKMx@w{fbRSx ztnu|-02N#bf&YG#IuSY|qu@U|qs*^$xavZ#cmm3`9M~H+2&KGnK{okWiHp#r%|H|J z5j|ydAg_xbEf^+7d7(cz9XIKTV~9jtTyKa(yQR&rJ4xkhwIF3N8OCq~z{O`@X$(_L zNw_8cKuwA!&}i8xeTEKVud0+3`4`<{GmI z;Kd8vXova~{9U0d$wTfTfIO(LHP&H}%GYF$^qmz?|UlAXpxvYn^0nS$;VZ zjG@vCq49CxY%GWU>>RXmqU=E~rt*NheZ2A5s{Y=gQm#k6%jn#SDixYqV9rMKr;rU z*CI06D|0>q#&L(MfiZ&(2ixWS7Aomf&9hrj*Ueq5R|RT81oFq6pv$6X{MY?I3#=GO z0_b=RIw+x|X@hLEaWZgmE7(a{uZcIQNN!Z2zHB=W`k=z1VWB@dO z+1nvhL2+HIkQ+;SgV!*Awx2 zqQTUbip$aw(0eMu7mZ?!RIgu8Dt&R_(EFIxXtNQ8~YAo6)#M88_Dj;!tc+P>dO0*H_NGikCXg+ZN-*_EXK+bcc zaKh_9(DpaA?iiUIpww?2B!tv`s{uDI3?Feya-=wxuUIyBf)TiWRwgr5v#qD%eBSEr zww%_4Kex=;!|9OYqDikFUnw$16EKrfNg2k(kvW|EAQ^LNlGo{7HI^O`b*vWww!`-7CW z?N~;WPToKlpkaO|yu%3^BXam7b1O|X-mF4dhjIj^9l$+Z#7&0QS)46Ic zP@3w0icE`Bf*pZDoM{uODm4+?+4$PJ`w0T&UnE$Q-JUvpicAI9vh1odddafv+5Mk* z^!*eW1{~Nd73>;05I8e6>>8O97`3(c8u`C~AwB?DN}Mp4s-e;L>I{dz65_3P<7j+g z6skj{^onp8)a|s7Mx@^a&D2DexUpf&{0hELz5q$04Kh|Qq!9U%sj%N05$0p46vhOh zPb!ivj5IO>J@F{GYJhoDPoFYE=FLRof}H=lV7BX*2&eg~OIG?yl9#jM3R z;307r<>6lh8W1?e=|&Ft8((%t;qTYG%b^noFv}@CA4s`5Xu?Tw?9bcBUobedLA%A# zxcl73s_@B+ulsiUs!0W+A?K^A7bF6fXXrg&KYIkvNuB^+$xXo5EgKjrso8xNU=H`kermUCPsRLUn@ps@x)Zfla3V9A2 zx%_vaE-pP^`xUHTsqzSn`;2wwWp{)0t?cJ3E14NmDHg+I#*woqKuH?rXazB`a_YRY zsB9HWa(E8QaYs5iy(&Tv5_v-`mFE#z8X&C|{@mlSR%BDsM1$)^x}Mar!+{p;0~AxY zVGPomydT&B24nF}4m={Q&IBne)z7s!sJ%hx8UPKG2cx{CW`ULY*V0Wf>W^o)d?dZN z>Tg^T)oX7nnQO<&%^YP$toG4B&0$8g4(wwP*yD0(X;_$hq*)mDRm24>l^|<|HJ}Z( zqMU5uxu>nVKo^T%Y2I%&OneP+&MYuhCb+3IG)tk2)!Ac=AnszL(o$GOC6|{ zY%STeG@$v!Uq;<>X&ht5u18v~BNHKbzRT=le*lgkI?{(SqkLZvsv{2Myzm;qsE4!o z=d|ubHOM{|5|i#YQovSv>JGTX08juP&_iwvKPH3taFzJ{YuLvvkhz)Dkf#s*Tw6wq zLv<9AU+&yMP*+)HU7ndm_V&fsSzwq{ui%3TKM9pju5V}>?B;+wC6T8}pg$}`+b?B$ z!2Vrr+Mn>nI|tKBYyIuQUTBiXT);|FUh*{*%D-mLW1BW`#?}H%WVkbQ3+UevLm6-n zSC-dPVK1@Zj?~H&eT#+TKJ(C1PsMVP{3Ab3Wu@SO_^bg|6yhS$DPV4?Ggi|Q>M9rZv*(e%Y4UXt?selxPl=m z#tH_l){85d<0|GQy+Msj%U`g zbv>+Nol;`=LOET}P{;oz6$y|srbT@nkm$qD_^5RF4^xS*5808p0Qh`eTt^8YlC{?e zI(LwCBf6u7UD{VjU6OE^rJr}Vpl?gv*7yT9&ie#rlo>R=L~ zs*Z*nRFywr$9jVgnSp$8tHgUl^<-pZNt>e38fZZg>zt~|R*g;D{6j#7;803LABpS6 zjpAG9p{+#M!?iagpQ09tmN(2Z{!pSTi>C;iTmoC1S^Q5&3J_wIHZiVIa!zl^;UaCv zj$jK3$IEE*ygx1D`jlz0+h>0g+W@|XEhljn&>xbo7JC((5=IU-&qcvrBQ8fya#_sj zzu;Qh6gD|L8-ePTq6cEze*qhbvdji5EBSY<7q^CJsa~B!X^I-@BG^lwOAh%do`&0? z(3i`m@yzp*9`Ma{c~;W%pZTgWB|NMtVt2kLHtC}41yt)OrR4m*n_W1&+){%G$?41I zjc}P!#c*efvOZm)-mA7U%2cH?(-{_pC_pXz`0a6@v3C>y6{Hkk@-###x3vHEcj^cX zJOZ(cgK?C9K^X*z4x!!`(zuIUpu*C3Xn*>`P1p)L4zTBxKQnF`CZ%uVnjNl(_yWW7 z+(H*Zs_!Z)EEeGp4a;iAjG)P9&nT}?K&XP_-axjU@yxTAb?hp~OyM@t*}jy9p^%qq z7IHqy1`TL2cXx)?t>2cyR>pgOKqL}^#<98jz5pwI@?_Ftfqt=;v6EB zadyFAo&fibA?tKY0Nj=GAcu{9Q2#^=(!A|GYFH;`3Uu&8=WE-3uB7EkjJ*=LPsh>W z@x(U65yE?Pye$LMay3xPP;xS*1y7uWQ81?X-}OberrmL7U!=blxcY&L7O=oAyIlOx z(;@cZ*rx;Rwv-;gvqM%<_C@n!gM!^JrIdPp>;RR*-8d1UyW}MlNC@Y4VW_?lfY<@N zj%U<6=!kIow6ZucN-BSWYnb#+s<8d>h26PjsG3QGvit2j{Q|l#luM3%z~m%BppAQ= zARiC|Y`k9?#U;UyC(s{c@oyrz8vgH3pgi#=_z=+PPlDnV_1jw zmVjBS`mD{9DgH0jpE==xb*dJHum&#}Bwe;xg5}@$GKx&ixt#%+#`KSeM7XRL4b9^H zWN|S&F{P*Rx%PaS64Dn~@Qblir#*Bl*V0&EV?H+9U@XDuZa5^9Aa{JJ>iQj(08CFE zBNQ|~StV__Pa$Sb@sWfwJRHM{bYmaQCvKF~QJ7Zq3x$eU&gTJbjUJgpZ0kFF8n4uH<3 zKl*`?lCYA((mM47_gVCsigJ}SB$a3~*^~|*WF6XTMQLG1-|)FxcR46mq7w-O{jI(q zYrd}6Ip9y(2=bptrt>X=GDFuwFjtk7vpA=xgjMakL)FLoE0W#GbHfp%@~j8W9@Y%BZmP-JWrNRY}cC|En7q9AQ^PTvF?^jXMBXr zn*_T#Q?UY|Oz>Rl&0B#nijFX@xK~K%-NvONsqGQo={_t)qe0Yx=EB9og#ZaemViQK zuW9UHej>60V;KHHi0%%)pXX7{a0p~*rPR)hZC*c0@8_FfnSWs{-&U?xE!tLp_K&#jVF^+4NPu;VtovPb?yf;~^FU?DK*vaC$ddUDx33bTM({t*q;f|E zTWI`K4~`*mLOPc0BuE)fLILdqSm|%9TsB~?ch4>PeJsYTyDNPqe2t>wW+=Bxse0?| zi5Cw+x8=`J#VIQJc+Byimiz*1DpL#o{Jcy`fIvQN=YQUl=$&;hONeO}9zqeJf4Z{l zG)G_m*ep%Q5QJHqwBlS5&?a|P`boQjLi)OvbZ6gCaf@8u5}+sF7yxpcu5CDV>*qj+ zldKI8YHDi{sgxE|Zi-2BKLW=HK~0nkwxPpa6}lx=SkHjrBh##wTtx`rRP;mwIH<` zPFb7`A}05&k<}FmBmk&5XoCFCDee?~mq?hz*-HM3D_nSFT~0(c#?J_irZucxr2E>S ztH*Q!1W0}MywS!L!BT&Z=LCn^$5szR8-s~#<)__i4Z3h*pfmN~kc+(05IAla4cApD z{R0hO4HLplukYGW8nh_D!|W1k($-1&*@}t$k@##oW7U#}?*M=-t|{zx&>7Dyey`Sj z%fDO~3zQ)X=`?miz8pB)vk1fzYPt9#>fn@updDWF%$h3(IDf4Vj3~<)xR?4iD?9FW zr6c^$jqwjL63^D!Lxsi*?G%Cyw*H)au0d0UxwK6y47ZUEr$R%=p@UvA%5NTC zJ(3A(4(yMh<^bsbi~lkvo4Pw~3w&|%29=~RWyuVHqtbvz*?AJ8T=2&hq`PA9P7#TH zxAxQ&{%BSaRy)(n%Yy8}CLR-Q=dVP1ty+~OgEd{OOD((j@x;WGudpdFgFQ4Qv z1!R`}c3WoRhG7cED_a{ERjD})@6NslT5>RuA==h6!2z}u+d>9G)A>T|ruQM+Z7I}i zThNM|75WOmGue3=De!vld{Iq7B(I%{XYEc%q87*`miI>-!w7&d zN;CRbi(85@`ee>U;M|!JXXc}qqYfaBX0>7%VQNn8=v_76jgf7M_Yza2vQRx>>kx#x z77PjYjsXmtAZR>0gL>kAw8$~F(6D4@4LHozOby(c#y44ZNracS@zal&QD!rp)GH^x z8t)gk`+8!_=JMP%=%@dY>wY_|g0p4?Z$7-2kHlL!;0I9XS7aaYi@l@wlHAee?veIQ{GLg+2ZJIx(z%7^As*FM&!S7 zPq#nFa}q_iDX3+fYvdN~7K@6Nr}e?d)F87^cm@hd^qA+U=;kXK8&CiO60F5Jv-MX) zHLzBuYiu-{Gyl|*2UFjEk=dZ=uY99^7rL$gv7v|o6tDdnC=|AhjpEvvv*|trac5}L zL9|5UvN56i_^;V|aK7|zk1?~+v# zM+ra#R@knG3#4nTQVujI@O|qI6^M#s`!`wJRjco4aPV6ktuJnYAi!ssAQbq}=`DNI zA=V>>r4nbTu{*mB7A-)>U3cAj$C)~DTuo7V+}u66rnf`xH%f$)Ba;fa1pRf5ptns$ z%T1j?|Kj^MQKRuY8mx6%-K25@qfijTI<@z0;b5EPI2!@^>X;aV_>b^kUeT(QO-=S1 z!`E(rruqY;5CUN4QcFOVPVQXrVK+8_r#8`HZ(Fe1`Ixi@@!nJNZDZb>hs^fD*j8~E z^}v%egOU4FVTq9;t(DcV^}$Fp*9l}g0-=aYc^puFB^QWUFpttNbmdEdi<@_FLINm4 zm;1%Is^d$>(u&5Ucu`m6)@!v*pTX6z$kgnTf`WA_OaKmM*fDzbDtS>A)^O5;I8pC-_?v^&=Wk0k-^KL1YM;rtnBiAu`YSvSi95oNV$|i{Fwx1n z5s_XRu7IFcm|Vc+9oNjv0ll;=Uc{AIFHqiszRJ`$w`d~kI=|G0l>hlEkr$eP)k6DG zkbLPX-vG6|ZJ!h$$5ZrxTu*9HFkx4dpF(BPx;X)c4Pg{&2gee;xXML2D&Z`Q{Q_Z2 zZMPQBcUM(`TuT?(r*g1}_Jo{D-gq9|);T2S1%L=cRp@u7Ef2JhMX4PUy)$EiqgQc2 zX@bwu!YtjrKOh5dr=5AYT@Di=3p|IB*-&`>2L@eu_jnG4>X>cG?xdi5r+Lt(aidNG z7M2M0^b_Kz*qA8^M9XM`Ea%=Vhxnh1G}X2mB}!REbZ&t!I#_HLo%wE{>;2dbrtPR8^1g>u%p}v_};tf^YZAWdx&sn9S zcga_pR>6!@RX*5HQUUcR!E!(0fw*1k4DoSchE!3a^z0^sp~we!sj*|Kwkg}78>>xI zB?UVs+LIe*u*5EW>RDEZ^f&OXUnTgxCp)wKHiq%(1NvTvD(zQag&a2BAaV3T0idmR zr0cjN&sT~T^rJH}8YCkjI8RSU20ckrJ(!IrD?VHzQ%)a3$B5FU&`)3|gaH8?mWKac z5qgqp>-bkQvi{+-1stB&$^w>#f}^iiL@547~-N1@I%QA$3_$+>*+6*LH(%RU;(D}}k*dHqd`m`Yo zAtP1;IDiB!t42hG$qm@`mR%ipdnMjdIaIo;yx9#hZA{)%aw)wII zJz9i5Tr_S$-HUwK?7|?y_9N~5K$`NQoD9(jxi-l zub(~c&ujPR%Ue)?QKj1AhfAgQmQtI9Kke}B%W-Bq&)e_t7-MdK7I3!(+4E_`OnmlZ zTgU%b@46EZBMzLrBKE*@YRYy|;Eedt7(ij+!GOM(QluAnbt&F< zIa+h)-%jTxrAY0f;bh>_QWWYthq|&px&hn+A$DnX(S=z{G^6NZ+HgMK#q|(^a#N1J z-wXXWswY$N-e#7*I+?{c4PV*la21XY*gz;KQGuf1yIP?2lh^%UexNieZ|CW9YO}8W zQUyo_fkjUJP{3=}&NLW}-#K+c)2C?nfn58!F6j>Ee!lOpU;#Cmbq9IFnGBwVQ2=B2 zBjD7}NzjVJRI6QF=9J|R0@8aAqUm|nnLESA3o528jC9#>e&Qa>zCFmd?|+u@(Zr*{ z79stVIe+)iT_=HF!IPTf;OiiNX zZ=_63i&iyBJriv22^<24+oRkV^)&o3JuVh(7jLWEVhlsB-#Oysu(=J;ysO?%e&^~?3Lg(Ic&9SL;qUUy!rfA6v5KLeje zy8msQjWwzqDmuhz4Jb$ZMa)zDwwsRJZRCcjdaT}vgEsbyhW;eFLQG%_h)=wROz2x^ zyG>98G-hkIskMsmP$x9*i!q!mRNPQ(MZ6-k@Mg44A|-$u8`X@9t@U;xEFja2x<^@# ztU#W8B%4iApr%SGmj?_EA4R_O-u$XTqyZ}2Rrhm_IKYP}ij=0A{tfouOMLMv`%0Hp zZyP8I2^>3#)nIdKStY(uw|XF5`7!Jh7jemV4acwO@F?74m2b?$`^|Wov$) zA8qR#G#mInKCRw`fBQ>h=_wx0u(A%3pm<>We|mhJ?5+R72g-!t;pOte8C(~WCkB8q zL<|_h``I83WCbUlRsdx@yBW7r!GN;az~gGqZ74D^++hHmBO?oSG`)f7iF@%I-<|k| zqQ401pOLXHByQ@lIfx*-?NSytasC#R?i-XkTbSG^vL<1*o))zJ=E2HDUf@%%D}vv} zy>;rfjiNbd(U5}mguowHM6piy!UJ;hbAqXe1F?X@iq%}(A%x}JxdnN-Cf`zBQe#{3 zG|`n0)znYW=r4X_s`)d|D2x`_WRwbdP3Fp2EW0#oDI6MQ0fd@&KR{eh8c)9>*d^WW z>1u5uDO~vW>_uDix752RQ3r%s)z)^kt9b|%BKO05C4e&JX$MCa zN%>y%J!axiG*uS!tHARg?WXR-!da9qG#Mt@{?T3;-@%bn@>y)vN96MNYf@RQTNL*n z=nlV>9{lqI-RT8rxmQ~-7ngRd4b%Je@aI4#h50#hJ^XkGojJBlZmF*K4sn9RT~hQ9 z2JY*oUq5KBpfk9EU0wUEWPnkJ{s5WA1aeW*a4B(@i;1UFimsGD^P27egO(YK#qmqy zTAk$&!3DW0k}T=wf%0TlV+Wtd%hlyB9^d{Fr-v9Nv%irCCLDUUW%Uj~(ObfRkpHo@ zF*RW0NEgx~NF(xK7qo4=x^A<0+sny}5bhSpNPf)0LJ#+|_2P1H5U|Iy9Pi&!DADXS zPEA^%&sQPm110!sJ}Q??T-}1U=G>_F2*~Ro0(8Jr(dLR0_TXkO?`l1*!3mlof zv)G{))EV>-+Z$cY+Zn0wXLEZXK{QjgqDTM!e`5dEIe3&};Qv`X!SlzZj3od9YPS79 zdf*&H6hy!#SK{tBtz%L~Vsg@Xmo?`lPVs~jA8*ej8TaOTXSJ<#fu!U?8VNU;l>{&Q z>t-z>5R`xN_0-O_-g33IHA#XH=$ZW!?Die0)7zUOnOO${SoOE`Hl*K{Gg1Z}e|d{uc! z>_399QkGq0yd=OV-&Z+RdVPP0i+b`>wxT?I)0|bT&tUJAtU$|bv!V)DiRMx6`f8P8 zb0SDh&t43N69oW$Do683A+Yy~9LT|VI;m+kjz>7HrgDiP)n0ut(zMTgyzWfH!d~k( zTM9Vv&7ROMacC$?k8GI%&@=}2s5(_2seWN;pwrC-7K&ke9D)K9`n{>>&eqTKkt;sP zsEkUnuJWJAafe~3IOQY%m7e_tC$ux`PAS>{69@Jb-;OW&nh}ZE92_yeB;eul@;yG< zs__`r$a#usQL6FSdMcP>U`2%MZ)H^Ej1Fk^WGxL-Nic_DO0qp`wHKU?6kid`n%$(h z6c201bV}Nm{9_vyT{qplHSLh+kh4E@<;Vg7N4qWICuO<}qyx^?MKeiwXzWhBSOsAp z^q!3gL@UFX6tgv=;?!XkWs{zRK6Ps0st0l*FO%jt-<2@47_pC#W}C@ow>^K!rVe=M zQfyGfW`K;a=c10G)$Fi)A6#AzL-liGYSPVNclKT%^VG3WsZW{K#o*M^!*H3t{;G?Y zn~vs2w^nKKF&_5vA>!a@Lorba0E9nHa&~jR&*-LHG!TRRn@*q<; zgTG3?Mf%nvR;dTR5f^%pQKR|B)d579W$EsYxYBq;nNHHpW^6OPV()Zx@wD@d8u`O( zG(ZTTN$FFps`!WY32SfJH<*GN7%mnl2J|10S=p?Ozj0vL^mzwtb|-9}5$Wu&mQ5T& zSTLBgG6#|i0yuamve=$)G@-B@R&Db>AJ2vb7hS$o%@JHOg3=Ov!i89>|I^*jJF_&K zrJz#6-`zCWkugIH^G99sB{f@eIL*U5?E*a=0?m*!V!=cKwMY z^1~X$g~qCQpc}7ZlaL0M&j8eLM*7%V;h2W}NU_EZy-N>)&2R|82VVNGI(26nKW4X0 zKj_ktlY$YY^gZ^)7pSdS%vXCGrFaP$#LM}R?E~HVPsY+WTSMz?Gpsc=eg~a;e?lHQ z{z@FM+i8NSCdah0F{jM)pl~+KsCPzSBk07?+j>FS1Xt^jId74+sRLM0haP+6`CFK? z%Lb2(!VQOX$foeraUoIovW`tzfQYSWRTsK@`uFBE4(~Wwi#%|c~^PQVvP zQ7o#s+Q(@s(YvD@Cg{+e5TfIvj10#D5r`LBC?-TQv2yR_8GtUb{HKRXZ8q>skTf|_ zO%Dv&=UgjCP|5aU_5ty;VBnp=NLMDnZd8y)*!~}2@B)N*Tu*nq-iZNh4a4axvk>3v zdb{+f0{&P;{R%|?G*b+5v~1vBYayth42N7u7ZHDGO+g%xBV^KtsuPJudC&V@g!aEC zp_;6~H*{iShf8OB7kX~qMCfd=MJHw4seoZ{lD&GOu1XMIngARsSi2xh*WKYllF^+` zlw5HNxvvkr&*yfZJ4icGkO=#7l?q!q!M$;bb+ia)QNn4=0Kcgo)8RCD2cmo6$F)e= zVC~j)PN$efbrysCK#hN-pg`l8LduH3RAG!y10-*ui^CQW(Qh73v2U7mNUTvI#E7?b zoYh0yVYu*gLI9@XKkXnDJ8oIv7m!+zBg{xnCWSYU^ZF%Z5BUB>UrAiE!f%5+vu1Fe zonYq_8x^MilvmbyKw(v}tdVXvMyBmjBq0f&5}C2^D)eZwl;{7_HX@DmK^f}Gla!KL z(<2Awont>>%e*&&1tC%nr_SI=oXBb ziki2m{U&wV2;5g@BjRwhwo5305+?4j%9wZy213#$Hxz1O38_Ez74jFX+iy6aP7Aan zJ!+Y_fCEs`lXWCX8ZFnX4l$Fxv@;*zp`9`SsgF`Iq~Ww;k1->)hf$`Mo}QAd50&AM zDKm~qbD~Cq5S_*}3q4-p>;nTE4u;2R?Dj5Y8HQP=_YVKKqPj&Qi05oU5&*c)g;#*`@aNaaeE@!*UJWOXlYp~k zyXUc5NB43!S@fn6w`=q|e_G&IRQ@XhtqHGT>Z#040{#2TD%l6|G~o8)n^hvizrv1v45B6;XiQvn_`7joJ|5pEUc5-%9wfvu#xtVS*7^ocT zh#dfrCM|W?EwREjJPSceT*e$fu&S&MB9~^9`0uU)45HPpzc#2OJl|3>BMHx)KRy#~ z2(B&o-YaUr&Ri6=%#7rXIbup?6W)hut>tdUB2ju20j@z(_6v{PtQl7U0Yv;;GBi6~ z5ZVY}ma;`0)p$1l-9ls}*23V33vrNrDg?*@i&$@X03r^ClGW8J0#;8$%@#IadRtsP zoc*Dh^S-*re3s?17a~Cl-?SGN2)Kn<5dKGXff^4fvz1xqTI7&q191Mj3m;O|_3s4N zoxP9Xcd0nsglduEF&E}tbuo=aI0H2%N*!Js9{AI>;L{w_`#00cu#OA#8Wlo!q!7TW znfeF&rMhskFyYM&=whj&9($2uF922?F9B}__=H@FBAUAnHj=TTVX9C-tv?Fl<|g1P zz_lSABv5o4DDV$eG;%GmqooeCx%VP6)sf_m!*?l;uE5fof$<=c=<|XTwy<=b6_CQ$)0wd&0))~U$&(Hmh2ylunJn>H2O(-n z)yJwv5cF%^G36!n1wGa!7!qIvL1r>HemU4QPrpKS{wNUTOGt?YCfW|kn+u?#E}_f>kA(nbq|Ch9B#BgNFSCudLB9^N`#|sKp>EQ)kJ8E z<$DR<6Xh{@NX413s_wKudjddxAm2^DbSt$`o-)Y+%In`9>jWjoD@ojs{0>vs3&GbS z!$-%(68h(rTm_~FkKgy-dTbg*8>5gG#sv z=9kn0^rLpemBL2^_7BE$dZ=0G9L6QO$g$RXboC=dn|DK{xTjR?rmacdgG@g&F9t7Q zY@>y0K&Y#UU8tNTT^nHgB+K5-t6g0=$ydC_|87a7z;Pc#Cmyq=6kG%T@1Hm@O=xVp z*C%7f=An=?RCNF0;s!5NCoF`Wr?;USW#t*yYNFILY}aD9Jcp#7(L>*ORE(dW7aMHiSA(dXW8KUIhv)4=*4?gPg$Q-!MqJO@Bbx zy(x0Nd(;lQ9Xa8iTvjUzTSNhB6L_xJ@T4w-Enco3>q5vGT#y*Z-Fi=S)LcFl4^*v@ z@&=3BUt+Fh8?Zy%nEVh+!#t)=1Le2NQbo#eOBj&Qdbh8qAyRuzQdOZN_%ZR)5QTAp z5FAw~w3!pLJsQCLtK={Ym3z1m3_kjW)s_9W=uQwn`4zK_1IlfGWliJXHC$My??->4 zYi^Pr(4Aa@ZV5xslz}`-Q@41LRR_h?JUDEhd{FqWSw~b<-??7|&V_u)AB#3w)TJKv_JbTYfSPc)l!k$Lf3NDZIh^d+Oj5+JG^SAg0+8NR1Z`CRX#9Wz?WqfYt`f~7&z6%q8@W>>e0HT- zpj&mrJrjV(1mSlI!mV&xIUIN%ej_fdV@;NSH156AP9ZyRzMmyF0w#pP7t- zzC`me{vKzl?~#5>q4 z*#~diQJXWs0e91C_k{x^xwUh9I<()l$)t}!9nXaX7vbrKMyJ(BHd=s>##k}3nM06{ zD;qE?3LKi*Hlqk!Df!4spcnS_b$>t))Y<>2g2#Gi59P)osC%;1MT* z(uyr!@9=Kx1Iv)Z{cQea%qc)b82}4A5-?f^ii+xmnI>geu<}Gr^ryX(JpqeeyoG4k53O)j~Lhj+@lO-feL* zIkcVM&mf*181B;liOV6Wv-m*l(cylSgBhHJ$g^004Or}VC#?$+PwMf(PqXv)t^=Ur zX4_gyKv{%tSo^!YUeYPxAwK^Nc4mwO+W8w}>?a-Izu6$qF5dmrQ{Nb>z;{23k9`}> z42RG+YUC#i7PQ?#-&xnuj(Bqu0&+&w>b6DLOF5+n^9u(~92P)RX_H*e4q zGwT-EVB7pE(c+!ge^N2e82+0~)WsoL`)Y+K;Zf`Esg zd_VtlnBP>uV0JY`V6pi}o&azeL=9p{IZyU!f-|}lF@<*kOi)ZRf;Z_{g$411GaUL> zcF@e%GV@cZQ7da)4~@g+kSsu*r{dNa8?ouX9I~VQHp@b5DcJ9VTmCbHw;81{o5T11 z6$uG2aOr@@ulBS0D=d0F8{<(d2!3Vt53FTy)*&mJ0w|6r*Q6#cV-~<1(zoDM6v6^= z)La{DpagcxNlF0&bT>t<)a z*6+R@_43hE-E`VV9>n(`*p&c33YA3)v610=XL^08E|+85kdvVpKEgyj74{^J>(e7& z3&Tm;K%c%X>ScTO~CKxX3q!RFtmi(08V?FyDx}+QS z{tCjRf#XuTwC;oK2v4ndikvKW)PpI^YjiYH(;Cg&^b-bR=q+}135{EW!T<@iU|h*1 zKY$EUFMtj#$ib)w+f~|AIk1Jr{5`Dlh<`_7j{JJ}25FqE&C(W3(W4a<4TkH(pJ6vr zF#nCIiytn491bAVN9s@DPd4l5h{gjaiNjP>#0Y(A$;T0FUF^I)3?AG~&BQRGMBa+( z+*#{bDmT0a!*&-af$E>U+z(g&*@yAL{F7+6SxvQZt-PX7k;J`Rnt+#?5bcy+k>fMo zXcxMSoWea&l@U@0u3(z9Hy`d22thQqGdH$>h+62`1_7YNVYth<5Wxiq%;thg-W_om znkY1hBG%yj5!s1rx*STpkBPgSaO9Bdkpv#>;2t^7P444y=qL%LILg;6j{{ zp=5Swx4^HLqPaCwR(=>ROT^P_dUmrWQK%@MKm6P8-a)^NxTW)al2odlt^_~s>$sCW zaRg2xHv#z8*A<5+T(@biX;*atkdDN!hi%Kw9KR-OQD-YwVgI7kMNc3u$CUeJwm-+q zqXnfyM}@Af^%sGy`O5#>@@VLNHZ&Rah}W!K)6?UdH8J{K^ zl&AP9i?BddeGi{y#x{p)Z1MktT26xD|2ik!o@*bSct>)As7@3qUZIE=;aAbI4@I zhWaSeksEcQfUJ!ROfFnpR$C9M3&6)7 zItSeD_v z<(FWMa)jv4PbhwY<2yDgb{HbUS5Al3;>kJ;>==gk&ZxiMzv6}!;QNhMU_>Ev%m*OLbcqt^(qr_D z_(LbQBKEnaaFEZad19A#*GsW?h?=aG!*UoAn^mC-8-mDiPK>F`G5})Byrr{kaz?D;+L!_WDuR=9OsUMBOD{aHa zg&~%mUAwSscK^Vcn;5Z2d$J<$o;$z{!S45IfodmjqgdkMg=Re0T|^l=45#Ww#42Me zOnKKM5|lw2X{C57EY!*FjskdILvBIn^IW7~f*-w>Ox5;dd^`6$F@XNGY!7T5LPU`) zKC}p(JUYjN7R%)qjlCr`d1AuC;M0HLhN35NK530mss>YHW2QZqA7Uog#3#gUESc3@ zu{jin9!(dU2-IoU?&x>jGYNjK5fPnOKJV zyqq9*tZ(5Qp9{5j{t)2oU%V?~5+8r@+^86ag(`?K4yY=~KeCNH#^?Lw25hkwM~|CU zEdW<~<~GYd1o?CT>$E$N+7!x#i9voOkc+FI=aGAbK~J2V_=iMLB#s-wk;2~9US>Zn zXn{B^hpxz;6Qp;?y8K79T=pRk8MPCP?ywcP=s(vOWzMB{o&KVi+o5*Dj?lwlsa zg6Cd1KyTX0t0MqcM&1Bd=y>Txh_SpuVWxGH`yismN{wUhk^c{&4a{ZO(EBH3>HXEF zfvG!~(oSZRiV)Iy5$OwY>qqiw4Z)6$UVj^dvzgcQ)jLsFm|69R=f5J^C@~QB58Lq8I>$l%MYR`nO?k zug5jQ^7&hYsQ`E?@v}9aps&RnliW{_lfz%el=ohty*SY)d=eV{;dk6|FK5?}K|!cb zcM3X^Z=)hPGluah-?ABBmzS5Ti>u#=75pIvlRX4{X?=h9NZxR@7*%gvb4O)1#q>MH zFdR@Zy_L}M?Bo9yI{6?NqlPbeso28Mn{<pnZpwY1U@8;zUk6}r|eZ4Z9 ze=aoRdR_}p+u+w2I0|RS-_p01`^n%tpatCB=73=`?OZGl8I0zqpB}yzT=*idDmIbI z>CH%7>Q%DHJpO5dim%6-N!S)(@T>cg{j42qx7_oL1nEPBLhoSF7Km7pL5qiW74HAI zX1)xZ>;b6KqOyL2xpk6r1qr^}Z6hAcj7t8i*ozeJHd$-An24N$XQ1uKW@=N3nlYaG zH~n$I+!Hzn1ZS&um&%TQ=NIDL4V{Tx!mFfRX`Wy6Z@m6d{%DK+Tj@dEv9@@5oSdg( zWm-efEmHWo(8=-a!UX>IIv*++Ymv&JfnJP-@)LmaeO^L1v*><%j=zhIdVYlZwDfqe zCTg(L=2$ZU!Pq@{7+HfdWc9HKV`2B1ApnYs9@Z6ZudKAXp&yCxfV8-`EZh5dVupC$ z;*_9fR|DJ1hfr}Ypn0n9cq%mTDvy)_T8Wy$cYli`fa>El0>iQ{5(=C z(zoAOj&ztT5(HCJ;g=9EswNNr%O6W=1qp}%g9GkTZ-m;f1lW0A57`q{+kE5iS5Zzt zjlDq|Qg`u;kCo!xqOb$CI$h*?EPaS`gM}`zmLVbBWIxutlIFM-xyh}TI?gXtn8FxV zt!#y@ZbN9d&3hJvbY~z{o{yp;0+MA=@kBiv@p?WPGE~fdqG6s!5e;ki+{ENH>HvJ0 zx<5nYHmP!2*_pg)x1G2WjAFSO;2tZK3g2V)7En9LOzvzZ z{;Q(9$X;&krZq7f+tn1l5V>bOa|0M=Y_^9n1YM#BqWCLrcY)tm6=&6WJ4;<+hLGmp zHyCHe2ulM@$b#`@R<>pKo z0DN9guCbAdtGtmq6rlFeO8ysB=h$2c7qsix6WbHpwr$(lvCSQ0Vw;nRZQHhO+dNO5 z_rp2w`U$JLs;j&1zOK_}LMg>TTWd2uyZ5yh0{Sof8hcK!)Xp=2yfm;UZOuFQI$|hb zXT)|vI8Kc6^@IOZ1apNP)_jC7reskhgYw#vG+LF_ioT}|0-LI#>|IsUexQ76$}OHO}} zvtr!Da!A+j$Pl^K=_2>vN6h2ZEQ^8|CCC_k)FiqjGHSgx9^16^;YZn-!-C>=qLV*S zWNKCNYkYs`7wk8hw3J0^Jlze|3!R+ z^noN?g`7w3uVOu_btBxOt8fpPnALeq`xTM;}oe>*R5%T&UUT| zFKaadDDrJAklNf+>Cw(D2IKARj0w4HuHn3Y;Q#-NW&!zP4$lRj|6~)y$RHqO|HD&N zN<&9VV_-tn1pcv@$;BXQPTblIP-)M?18C%#A8FIC$jFXB*od$6u{AdrL!#N)uq_lq zZmnxQZ-pcEFr9?no19jag)!9Oag&~6=zZ3iRZtg4Udm$%3LL7cOo0SWC=TsEKB4Vqq!qGu zYvt+-Se>tT2DLpbEEIY==ty7JSG6WpUg6d7IAVLi>&~+4;`EsNtw{R>9Sm;{SdeF% zdCc?N5;WH{7zHy+^vh6Wf>c;s>aPCtMW)B*ClnE2ZQT8m z@xHG=Gdn;E+18SAnLTs>%!h@C{J=};yyR#It9M8!ZLJ!yq=7;zP(x_qW%iOn*wTV&Bylc{IAofPj=_93 zAaW%S{*aP^m*eqinl-m0c%*5<7p@}xV1SIRFf9H`S+j)jP;@b7a_aKtSmwZDVFw`5QKXe_;KkU^DCki5@FAdqn$cwnli#Rp~ z0(X!-W8RjTm*DvAVSgby0xeP=t-@vOw z^z6cC^;FdpfWM~GnEzKCuUy_XWlETn4<3NH!0A!AP z4zXIA3}Rbk3hvs2AoYm!7vVkx5a&wIEDCfPt}7wk6q?!HM!d~592uQIl7QYc^GFo> zMCx+LLQGHM7%Z9Q!yRJ9<(maWiKA-alu5pEMjUi4G;Lc*)x^zy^rRGj_=Xe~I7dVjB6 zcSV#!Ic^u*L?{C-WydK7%a|+7WrBshNWaN6?@WAH?Cv#Jcb{OJ-iFVhZk>@G{o)kn zDT;9%7!=smq9!L$cXOY;8W%L930iF9a>KP*8QkgIJ860A~9C+?Y z$_Wy-u@LCf*V}EB{ux#Z1Z~UEjB$ca!5I7KYMc!^KJ-&K{56%*I6LJO4#NOWLg&Hd zZ(dzfM)Yo@^_hLjpG}5gpDMJjjgyNu5Po3{{%fIY)x6wuZJoDu+^gAxri~4s(x|^M zXE5b2u8rq~--v02JhU%yk`c!WMTgd;M?X!$K+G<}inD1x>%Ddq&`II2CLm|oM%}nJ zCwzkIpxMRb45RVnr5x(sPOTznUQMqVN~E$I61Vbp;CYl!FRqo~@Qo z!)1$CmMpn&bw`y|GdmgxfcvS}b809CAa4(nh1$VBb{A5wp0wD>gU9a2^!0=K?HAje z?$kKeWofsGB!gV0(&4P5p3g!$MrR;5G&Gl_@@H5I<-m!oz^T65m;vE6v(#AA+z+#8 zAA7i);BTaog@H5V6=TRFra?i_59T!?BJA$ok@U}f!~fk{TG}{J>;4Di6I@J32P6jp znRH95JNi$zp2Ukv1zaCzKtPp+#e`u3DUEWO-|;_g?qvW`QJCSrdBEqllLPB$`0u%F ztnD?gd)590cx9VmnKqRl^D5qsEiW4}t;RKeK^q`Y0qXg;-+ zYfWW3c>H&7%9#20a zKQhKtA8SGcg8l-j4ydk(9(5~&=T})!C-*xE-;!G#QL1QXf zVl{0ZNnA$gW7ClkFB_OB*9o&y>3>hAIkb3X?_5-_jM~oqP7UhG)AWM0tof7d-3M_^ zqaPbTPWsdwFwNtiF-c>YD7^u%4~n!!F&izko7Uk7^lphBPb98l0jH&5KM+vi8iCgj zS=vI~qcm^r^jU>OKELFlzPBxC7$+R}`}S+p16wrauls~sUyKqr6qFE;s2RYXO$(dk ztthnm08`={m&r+iO?)?B(Ab%NOneCyt^0e)Ba`%c`T8{K`yE@#r&1Hp)eWuj6UpsR zG+i$O+#%D(mskC=Bitdt6gNOb55G;e$IK*m0ci}>@v;d^{t3RQ@K2iDs5DDhe|TW&OukW5-mCx*x7?1u@r zNQCT$w@9-GL+(Tiv}>iX@n`*B6$>ggc0|t5hff-s2CQykR}rfW@gf8J7UvjJOkGW& z=Ie3oJag)ys1Om;;E)b!JRecr4@VasK<-bU*Zs@a*V`#8Pj_cezVlr@Ps+E>ps5<* zj$hv7pUx16n~=>LgUUZ(*zb}C5gw8()hyuPM60#UOGvE{;W+nbwQn>rOKKGd1A?KH zKT5iO` z+D4rvRsvD;7P+(7MFLO7C9MT*9e?W6b7!1)7o0OJ>bi(GtTD~KQiX`@i56>s>lcT< zNaN&|f;%7UCO3BZqcM~4RPKL`%a<-u&Cud)t`%aA^*MqI!XW=aX3}qnse;H>DG6l0 zy^N-}-Gjv~L-+osZ?~(&;Gx%8_nHx%6%0h)A%X}_pnZ>&vxtAH@UPXU-_7n08 zhIZRoGf&pHbW1o^RWEc(oe}^ChB{zJ3t0sQ&WLAegd$qP`i8KQ$VA`n&DF}r3z)cS zw^oUYx!vyn;4ks_IrG_r#9HndeMK@($dW!`hs6d1fSp3m)Lsb0F)%k#r6T$`oLPf) zg+8V!=!a`ju3pntnisf>(G+Y z_=KtP&a&@tueCuzcWV!L6jtp8LbUQIhD9>bC69^3`J3x=u4OrONiq@IVwaYFO&O%3 zFv78&0blRu zW6`OeXA%SOw&~j|b{-~$<&7COdD&_>OZ0-5ivj{#&;6u}X zuF$lYdn|WQlqvkcise41NYnsIRo?e=<62IY{_FtF%)(asN0J_>#g#oswV|@q=}n=n zM_ogD#j*v!YR4IEPBET`LEP&o_~p`8V7Hdz?qHXBi|yvVLm{meS3o~%>Mu%-V|XLS z9CT(!(WXNFsOft+I*dmN1~-icNqF4#mR)ZNEAQ}PdTV@Oe9s_39fO5@AISW;guWTZSE>ojYPil!yc)-40u2j(z%r}JWv(Ko54?>uC^#AZ;MHA2(q z_zZ*Q8bnnpmGIoqQXJC~@f5b>8o0qPBwaN9m(1Mht>ZuS0&vt=O$$k7-R}2L{Oo+UHaYVXJ-Az;aE->2b7u#y zexO%vCpcs#q?c1&R`QVy(dCt(f06$VIIK^~>=l^Wwe=t4Iek*lEF_4(n_Iy9(>q)b ziwgRt%(ft7gLk1N!e$Q*q)b;_Ib#=tHGv=C1GRH#EZl1AB^(AegYXzq)J}vY0vlVe z&yXqJ9SJCz+$B~9&=M)y#I-D)QZuTIVLVe8)QOo-3(sHbSQt5g5|rm_02jSh7B@+vxP^dmdKKFs%f^GCz-8gCp_&D+<*Q);%I<+H+0+JE`({L{TQxO|5 zGl7%2(OP-u+*SapZaBf0k;X#WB$RY?B^$&KEQ2nbPEPO-Ockf7R-q8^eZ@h;96LWA zggbeXMCrwR;x4Jo@uho<%$|AuPcJW4?VQJ$Z0lImb!q|B@9Nr~l>o>|>67xW>PJl2 zb6Hu?TYs~5!p@saWqRhO?Q9;F$|yvjh!`}MrBPD4IvIPKWm6h?_@>iGLN1F2S9ygp z{Bg{4FV9zNe{V0wEzLp>#2pQ|X(I%i@fbilR72BC+#X@VgRu2di>vwe2G(^~*T8Ev zed5U2Jy2nR{M78V1>G@>Lj&KtC^uL*Dd4PNAFRETOL_u;R_mM^inLPKnf1%vv z8KB=(wquC>?w8T~V~|<%LKuxe_v3u`S!NaZ7-xhtj6E;nzNkNItyB$+2usRc+-8kANXw}jRu%bQUI!0cq$GV1 zVeX_U_CORdS8v~cH~lt`WbuWr_ePOsJTc6uX)nFraLS#l(7>>SKJIatFc&GLDCB5Qz=4x#0iVxvr3J@HH}uZkA`YRK zsBD`q6KCUj_<3DnZ8Wt&Iw?{h`4S1El29+(%Mmg>RhTw-LxoSkk4S4YPMV=0mT|FU zU>US&hm|fOD+2*=Li=>9Rj0a5x=UibBpFsZFa6j{h8s!L2Q6`HPHEu9=$});nmvcT zXHr=34Wj#K$KYS1EaNL!R!z7Cjkh1cRQ`G$PTMicL@Gv@yBN8(VR!z9rX5>|hFE!j zwD_s$PrOtHM;zq9AH&1W?K*i11y)Q&^ZuV_LU?UoSh)^hl|g}O8_0;YTZZ0I2WNZh zdyyvAc+J8r-HH)5a+Zg4_Ik7e1MDw#8XmM>>#eO!pMxJK)N~Q zVd45Uniwff;%Mz|EivAIVGbzvkYUnqoW7aq)_jAsfk)c32IB>M!-q+>snr4f$-Edh zOtL9~Dl=O^$?PfNFJ?9(^40`PGi&&;Ys3~!cc10m$3k?{KSFegTu@sji-vC)3}vvp z!5+zsB#%P>kpiHJHn>c~;4pAM=Rx!)DiUMPm;rFHf=p+!c2qxsR|fk8I`$Hv6md=u zrAkriI^@{DD-t0|z*#Jy!g^S=HPb`VckAe3vi9470(1Q2@QGZ-+l1-pU|)YpG!C@k zijQBx6W@a)FgAzvr*F$YWh_Y9k>OAq11~RJ{G(X<{I4Q`z|0Dq%uY*6=GJ5EwLT$n ztXfObXqUwaVu&csD06w*Bs;4RFz2P95&RWy#>qz#={5^umJk>g_mOQngMi9fkXq6i z?QLTqGSmtzPH`6P=_P5yRl(C6_GjBzh~Uj-+*uT-rMVLFX5<(Kdi?Le$Fh@e?9cuJ z@?GSX07NYlYvx9B$ewQpI9MLE9z&^sey}@1R0Ca!T~xoY-BLfp)uxs9d{XQpIv+Wbt`;;CTrr6~Gx6!76KfeNLsQ**n}i;7$Hr;~{6 z75GjpyrUuhXI`unp)VIF4np{6Knrk^!zsM@VRsIr&1SlbU#}B2KgUpy6i>|D?zYfC zH?n$+Y_yVj@7Tf#VmjTK4;V_=`wXv z)Sr&MC&Z)hpM@HHnQRJVv>1X2S4D}pD^g{=QHf0sW#Cm0(cfjFs`c#o zipS@(89}AQ>?0h-mQWR>OQ?J28Sbq8TPL4>pHKnBD3;9y5j+OS>&fg7 zJ%2|aHI?691qCxvE7#LBacM_XFzXcqag*s-C0zlbTTD#Y`^k$S2-5F%IUj^t*1*X~ zwjMqLog+kQYOEra?qxh~K@mC>WR5CwFL5|zi@{=d;_`?(mga)S-b}s{ zP=S%TSR!iPu}eRtSm&=q3YtAuOYBVy%9FP6+lcG--Y0Y~ z5VCb=mM{_5A#gl=Blz_4gEp$qk+&z~#5aa^uoNWN75(ddRqftP07-pL3;lg*syIww zJ*jU%Mmrb#s8wX3v?BMnHiM9@J z5%*}9(W!Qu6(jTFP>Dcd;(th!OsYe8d5=;iOhZpaVJmT9U$8^b(4p_`w9ij3 zQuikyf+(*GdM|Lz`zR!_7#Q!&*SS?-x3&u2WA-3vA69H_V_2P7ONe(m>eFd8a(*k=HUa8Sf!jr2?p;J+ zaxz(XS1-uGg!R}wQS2lsQ%B4Bos4XHl7N_I97_+im1!YVe%E3?%A;HWS` zZ4W?6cV-@5Ge#%2-WA`?L8Le6VuL9!{J(PUtqvDbxP=BL2~*w_Y=OFRz2Yj+;%xTv z5VgExm$x0B0(iJu^ID+4RY0o*!4sQMPXg3y;1^mZn-d#{$Yo^#X)3EdpK@(KTW4oT ze;7#;dEmXVd+;~-Hc8)nqG30*PjBs}HpvOU-*U%jhCOn9aIHNykarClXgQ={KeSnk zC=(|yOy7X-Z0JOJEAmr`NSz+Rfsk+u8L-pC+@6w@4j%snBhQg|KXTh%0!ohZU#Q2Z z4)N5O;Kv;9sk_ShH<4vWbCigN{ARIPs1_UK=l%slj4=f74`jrizVl9 zvmubjDC>dIo72fa=Uy5+btuW$v`3QFg*c#6SSHOFQU+(D7ZhwbMJ_)k4zlp*u(#9= zHy?DMUb;UgGM0R|l?aY6tz&m~&+ym)iy)JPF0R4h` z{Zoje_qz|TAr}elbc%y+c#EG_X`*}#$_=OqA+filGR?N>cpw_WNQVXzA1LWIqR_sN z!ziWL?ralwEL9jt*5GHZCCyO324g1yD0=@_lsDRQS}o08GM;^yva z79QstUCRGCkTfz-)xbFtP8mKTNZ5^_h^QF&EOf1CBo$N$NcI1|ib@Nw`F`A*%S$6t zK}7~$-TXupv#x$%rHzeLxF#G;F|m&BuG*ail3yT$X8HHs(@GevE)`C5)WLrO6ZS) zidl21)Q&xhC(DRvH9veF4$YzXbUR-XKxYA8cnBfWl8JM$55C}K8^|N90&)Dlzaz|; z+-hgG7}o|X#~%*A-nL)!QCfSqRu7yb3eqFoH9EvSA77e!-(A-CZd`vK zNnHtE&rG$bVDb=i(dL&~>>(XKv^U|<-bBsgl`<}xU&O-6S%e)rdR6ll{e~hz%2op| z928!0W?X6T1;c4X~QdohSK=s9JgZ|#zlx|-xA0O+}|FbHq!p7=ZU zBwXZ2Yzr#s+arGJzB(BFZ{7x=4P$}sBZi9IZwGH5z^2TDvh0n&J;4KiH)Ir)w6@f$ z2kX`B7WU8w)-{M4eC*~hPY$IWE4=^e3S|mYF}7@1Ez77{0Aq@9=Q=3~bhw?{*BGBe zfQjDt*xi_?*X0X#o#>s>s8;5P&PL{ErGr6(;nnE^%u7&e(Jst5goCzR`D4KMe}%~X zbnl3bQIK}phfI-~vai@s_?87nbp5K--4`NR;qy8{>}s@$9HDg2*c{3`U=6ED2oArD zsCE=nN#&+m>Swd%!JP4IW;Ty#+gAYALcPyi?}4$Dv-|n1kpHoebNVHZUquCGap0@T zAxWsR1B~Op1o0t0;_@Iq`UHSBVEWvOFYZW$ZO+311)_a3p$#n~@!9+lWm?k|a;Z}I zoj?({2rvb&$F4CO2Qu~QAPC~{T}pGICS!ds2tpIh-INeDRNodAfIM0`&0WUqL1(|K z=9#!PgfUY1biUZtOb8X13h>D%I1bGK9c+3i(h{N6NI{_csh{>YT{;N!{qXr$xJQJn?dC`bhCh_3h*Q zO!etj=!z=$BzC=p+8B+o;(inhj@2)Zz^ilKEtxIwtFhA`ef${J0V$XLadpx=*7urD zAACC1bzbfT_n&+MUI*}1GKPL^)G>816qKQ2Q{+`rp7Y{ND%GQV6RWoxz>GE-j@VW? z;-*ICX~)^>P&1Xn%Y;2w5&Z)1y!8!LBJzxK9f=tYn8~^EU=*!lZGNwK!$$Nie^%C= zJF)0x{m~dJcavQYel@_l`%bymw_E9N56AglO@4o-L;FUsZfEldp%+&FzBC!Im4lJ@0vDcq}W#ArOWD1B<1wG*+VLoq~qn?b>02RQvcRh`M4 zn)IAW&yXg4|2-u-2gH;i70;T7;OjX0!&$WNnghh*(15LXxdL(zP_IJH@l3n@i7tin zmdr7vZtV6A2vk&^A#2{)$QtQ_mL^25^3g+$zt!o}nU^9N9kZf9wSt21vL=a`^bO%F z@qUHTn2Z3Jj{GA0bb|*gxpG6j&?O)x5+*epq;1Lcsw;NnaAjU|y=aQj2p9&xGz;iY z>3w$6cYqB1=i}yPQX5x?{-IX8nV-d}A=IwqFAT;pL;8(+~H5#e`u8dJn?kd#!Pii%MEG*`X907}eTCGM-*0q%vr)!#rvjxcq`% zu#>-wC|X&uG-g$K5$fx4YudbxgA-~BDEu<&tp--0IGec~B{J}5y+e7Dq?m*WwsI27 zzgCy2=?N1OFO>MtRT=eyBcn;%f`Y)_%qjyM;<}~Xhv*cPeGNPR2wEw2(cd1ib6l$w zLS9Zp-v2j)!&bP^<}QxZci}IHAVFy9?ML`F7{I1OMQQ}QRd|fo|4HKX5;S%Hy;Irb zNCK?sW*BrqGrzE|$^U5AlVK`arqJ7imV~?3XHCe;PL07Zyo;z&KS$IcqJ_7tpun0g z)MaxZo5glWh0&c_%wef(atQH?_C&y@Ot<6K*Vo(JL*LFV?fEU=DiVsGLJx^s`w!ih z3x*J_X>`M4^EM1t1&Y=i;+%fi4RVgtdjf534m4e?`kvh{Tx~ynZ3oIHgwNKTO z>wgw_LqOY(d($iK4dzd(w95%wuQFe(^S%b4m!TfM1;xlcBuqm(moq2BtJD_AhQ~@| z%GuJYTMj_QWSguu$Iu0M?UXjVc>s~83JcA(UQE~|r)3%YE67P^GQMga2?%hOnRG!G z)AF(1J(ziRge@DZRUg14J9~Kdh75N&Ti38Ca8*MYTFo$@W8oLAf-BB!6~T23a##5E z7)NNHOf_HG<{0_oG^{X8=8BMgk1GpVaFRd`Y1f%Yrh?skR9W~gY&we*{{TTW)M6q* zc3eD-6r{VUJbI}3pF$Jsi8Z=Djp40a$~!0o)PD?wRTKD6X@|Ch#T8k9(f}zlMk>7j zEycE5<3g6LT3&p^Ogv7M5H0WenO6IK(GPvF@)F7Yp^2$WVRz3IG%xRrUIHz;JQFN% z3=s#?P6w|7#C@v%P1S@csQ_E^9AX0c+i5n^7S7$+Udo2#`-Um5%E@iY5)W-W1vM1g zI5dzUI$V$^)o-237<2u8smW13?%K%MW+Mne8=UI<@?uLJ6ByOm6YRZKkw z0s#NuBQ{V}`ayEX$~?A(NI0&ijHid3*LnZ_eqEN;m7DXFUnXTMR0XcLA3sX*d!Dy3 zQ+!@fIW8knd?93Vo@GsAl=+YV37Af8*oztHkHo(Ag?WvzUTfqweBPsBSU;EOub0R7 z8=YkY4@O(Fn$|Wy-lxJxs#wec9O=+&9j-T=jFqB^JRe{^jW@9i@Ah^ToV0R-y$7E) zSEyW}sTV=SXH5TKu7E1FR54{^7^woO#0?rtzO<9baN8JdTN@8W0owYA(U%HI9bh@! zp}hHUp7mz%6%DqCZ_P1hwZpl+A zaYMJ?$5(_Kc^M%`m29^+yE50)!`XbbMEZwW_R3{)AR_^nM4-+leAzjC9k>jUK42S;tORhqDMeu+?v)~IYhl&C8CP9iy zw~^|ll@w@IUC*$tfxh>Ler)C$Eu|{*4hgKC3CPxoZ&{iMp%sC3Ae7Q4&F5}ZZ(Q=A ziYdv-m@OV0Fp%N1t+o3ajGRcbIr(V&;+&?b2Rz;812vlQkD_gw#e~pZs2Zs{&Ql0}2+ zLxp1ZPnIQrBV(`eo`eD%q~~FYyA~q9En);`D4VkEUK6EJTxGwvsB=Xh!%%OF&*3^^ zJNRK=`g#WabwLo1)-iD5sev;amFpREDKDEU$=s}80I+EMrK{rxqBe`oGjh|d%j~>p z7J=Ad>V-e#feE>jQ1-}=;XkIS9@#S-gi#?cg=FQDLz#|7k2QjB;MhazV@2zG_kR19 zb=xs;!iW?%@L#%s;G6#Q`KBcNTE3y|Wya%1VR}#Szf|Vh2Q;wfV+Qz*$aHq$>+HSR z_D@0|zJl}tJf~c%XDX=J(lBMN=&Kz!63 z4;G!#6;H}A-w#nHjvoR43JsA*&Awg#ZHF`B0iLcLtpj8+2iGY?0yp@HI)-d-5x5(cn|P+c9&*LqGv4dYmgcU9EwN zisKCnHiC`QkMra{ge+cb2SEaCSwB#< zvL!}0AO<+;K+-t=!tqr_m*~#DgD6xetdG(2#2SOA$TjKs(s!BbEERg1@P^W4kTCbL z5c$391)!0bDJ=p{svow|OY***=yEt1deDM3*zkD= z{$Ty@@YXVS0kPYE>NRqB5D=m?b`KP!wD>1fm^8k0ba-HjhOWZ~$Nx34IUZv)MAjXr+J_@?*=Ei5WSz}H8k3@iE&B{)?YgR9=dtI7dwtkP9!kb@t zaK{z9ADOJJHo*+6U4d^Jp3JmER33wo2SBW7@Jx0P!4;6SP1)4 z3=^p*jS0v`1phssu;gY%=OmZbokcpE0lY|2W9PIbt(8ksyyv`8VUhBcKcOBWPJl7N>5Ly)Tiq7P?ZLVg;TR*9;SL>W}|aqy$0=57=M4CwbTF+CvRyPF7eUz ziCe=QVl`(9Uzm)^`;-3VtZm0&4O}CWID;Dg;!yA$p{sX1FiED%wnA2rMbn$72b#n@ z0ZI8VK813CD+#%WSFwkM2YJ`4? zl8eHNJA}01!qLM?!Wd`JeCM;(HSz&%|9R8achl%JNWIhblePqVT@gE^{`tO@t~t4{ zarO-WJ0hwDJsi>HCJ7so^PsY8y2Bb<{EG2@)tG<(>#V{Ob@^Y&6bBsQ|B1igcbviy zeu02!(|~}GrUgEsVx{?+qoRn|IBarYeq9?1ufh~rS%mOm!Wi}T0k!~mj~HasfBJ2r zxlu;|RS9YdnUYu^J1=^PiBi&pyjwX)k$fbKHy^n^+-Y;>s3gED#R)#FvQ+Z|)NYv# zdBOYg#G$L~uT{(L@z9SCu}f8DtLN>?_vY#e@62UWR}qRweR|KZn+-c6Al1T0*#I`L zDUoyaig}lIsZ5bG{esK0>X{|gaEsotYx3{BV?Aow>0HS?xyk}cWlLqov^vx`@8zB% z#ZY<5fg_)?t#cqZxP`1=X^7wYeP`d_YA+fMzOK9?fEdRm(WAb0ZQ9sHO!<-wS8{% zs^|CZ25m%(-aTLVihgay>0haWtcdZX`{uY@FKjk19l9aB#JSety@AkFEaJx2*ki2S zEwo>OmMXJ8E(s?mUbp7GqLa&jl$K5=Jc-uzsQ6nf(QTSh+pY|w^~iA{XrB9k4E{I? z9;$4mWDZcX^BC{A`o8$~d!8HamnkPN)p?H0Rcm<`Lm7yYbfO&o)KyXGW(j8>gYL4{8b)*VJ;1=@KK+ zf(D-0SYOC?H(JwOWoy@*c{#^gsFFuyl>!sVq|*PXIHwTNp;RPvsbxNzp9w3X#Kr{0 z43LJm2c(z`RO}r|(=Zn)KwWkjHV_=8S4K3NqM%?obCrV6h%KO$1b`KoS;%S^^l&x(7AL<~3#LzDh_UX~y5uijP%bjYxlO8bw8nB6vppeOc|5SD;p=+7(aUl3yDVRaL4Bc>wmw zYZi+CSJ2XjIhp;c7mNu<2>Xr}yb;}JUTihR_MaY#|8$eDDbMMML# z@#XRLjhkn}&%45B@-9gzDU+i;Biec=)6?hiyoZTcoo4)#qQ;#~#xQ~ADL4r-pJ$aJ zG9c%hu(wB`#~;%+NKHw?OaXE}@>42%Y$uaFCT>DKH%Lv?!498Ogr@waBG}-W-(1pL zw2S1V;3rAl6J5qrYeT^Vsi7c`>j2)2H0ROYl{VmM-)j8wC37^1P(U0s4yEQ#Sh)TAr2V%Pq^J18zpR>shmN zyZrm8CCmvsgbUl~lzls4K!t9^{>|5Dcn#bQgikG;+_>4@LMs{Kb{<@Jh_HQfc%yfQ zNf7ac>xmySH*UQYNL>G5W4L%qQPleWCS0sBO-48RWfrqH$bI+tu-Bs5mtDP*Cu*c5 z1yhyyEMMCwT7edI#p`p48iVb=(uYu)W>s(gnztUr`s@-Ya(Ww1?GPY*N*y?iRBVPQ zoE_X_-QR@<-3Nrubz!=VeAeTC5&82@!}x2DHWti(uDq8NReX-K`Bz7##R_Y)=RmW| zXcy=oWBXg16FUl~Y!O>dy%jLx&e8Vgjhm<)JnU`2ms_MYqQt3#Z1DOOdk3TzRW{aD zY1F#`zTAZwrix(-xj;>>Gd&ckg2(`?H7vsY1lhWe^)+xsPozwnbiF`PeS&_Eq$1W# z3w{QBE@g3$)VJ^s=8o2BE6`GV$|$e9LV6ylPBXD6Dy^oZEMvnl@%~AzRh@1 z{BSjLlQhLtM0B}2=30@f4CzKe(bU%3P#y+Hlj7z9>U?NS#PzGXcO(+f(U1(N~8-67BldN!8Xmprb7nt%o`cKXH=1| zd8+tJs})JFJ2O9~F7KCY1s$T*2eCK~dW&F$?}VW?y$_HIC5Ho01AmzddDcm>#SZv* z#n>gb22^D7G|rsTggb4y#)P?^aPYTs-hr#qfCOpZU~p*S$K=_WGtzK!fbUbO>w*QM zYIltoZ>mqC(6^Xdn7CptIpR8&FqlJgHSf$ZzP?>LMd%#(_-#4pdK8=y@` zA>l0Ue)LyxiJ9o48mrH|Gx;16VKmE4W3_V|3$1Z=Hv`W`6QdDyQN$x63R{=Nyq(3* z5?Y+XrP+~(K@0TUzqk0+v8@j+WZ#}!Al?g-HqU08;dED&5shbsYWdX&HDGH9-=@iJ64f=icgG`XFE5W zRM?|eKifg3pFCM-2g0dI={XxCJPJoo!>u{X>|QB7N5#A9JGvkjT%FZPf4{*Eutu#)pTCY(pTn`7#RWiFSJ+Z`!G$zyZQb4B22KMKJ=Isol+l#gJ5UN3Zjol zt{F0`wa18e88t^&e8ihAmCo1$yUSrB*IpIUrb|g=7)Y+Ob^5s#N#;!)< z(}lpp)o#(APSd)L;bC%B3o~Xk)hn(3U{vegaNS1#J;dLQ01VV5!FTK~HJV}MR5U)` zKP<3F!$v%w%RfCdQtqT!E~(MS{F7!<5hOs1b#-t8@;PjP&>r+{2H4|Y_#e}frs`m4A6;_T<^(Uz}E^?as&&+?YVnnuThW)UJ9T|LG8EcNIV;~zjQ{`Z3%stx%`Uss!> z{0LKf^NR5+3!?5gp_I-r*yD!2b7E$Cn6)Q4JLYB!w$2{~sD|+Il+rFW{8! zp7Ta4%6CnP&_NrDn?FUCCInBNE0KD0rM25?l0ACIDwPJE1H?Ee6OK!3mPsCkZGeTMW!UA65C z)nMrDqA~}bQc(ed@dkpefjjM|j#)RT0Kn%JW8u?-q;O3z6qMu2PXB z*U)YHY-;nTm={Eh9kE>e98KAquTNf#Mpe0=V%vq-7HP&4wo9uGySuyk(}=;xOh9IT z^z|>1W!C~( z2E+r10_kg!^AUZIvq(yZvxi@r8BM0t4L=3+9JO=0-B%l!@tNvy1T4s!i5og_9wofIOyg=a0t5ns&^Q#Vd36Pky!65l)e(lk3&(}aeJJA%2ffYM zzeuVvy6Y?Gjn_tYY7vbgkV(v3U0JK;z zWc1=RXVp%yJ&#Js#EOhNuFDdk0YTFTYEhnmLjY)Uu*7Nurv4JhsM$}n?J`?48;>5t_Vby_u-Kydxj(({| zGp{0&$Lv(eIbrA5moOCYfn&c{$0x6xenz~>$YwcfqCkKT9**?cOP`&c;KC|LyR5g{ zed{5fAnVs&_UzfS_Y&X_beHf7+5st65g}qb(Lk&9U59rB?Qaq-A2?P{aATZ%FLd%p@S;rOV6{#%2D45j#-%r_p9p^+T5plf*YmG<` z@NY_Lp5AMZ4q8@)5LriYx6pKN(-(Ca^AHdpfJ7=j74cDTn0~{+_8ecaC)6Nv5TM`i z>69%ncHqBt4n~{MaD(%~%YePD@U6(RJ&OuhVBO_3cts0w7CbpxAUFzz0(c{(iIhyY zqcTv$I*0Yl_J{<3Y9O#%kwfbdJW&qX$er+2RA-f1&P)JkfjEe4_xG;)0^Kw0O2l@X zG~Spclq^YQw9GK$GCZ!Mb;ifQB3p|RfN0A+$${nK;x@d#xtw2}{~e9!#RTNnz+;;Y zs%yysz7p_3u>7aJrS~_WI<6qeM@ZU>8o*9&kRZ=N5RPnr*!P?l>^w^m5Oa$1L|KP; zqXfSpi)6OxdQ*`@Pp2(I{QM@(u&>xhXB2)sy)1V(SK-~w#rN}t&zh$2`}zF#{OaxB z0J~pId}r`atpqov5)bfi7v%)+O6S~}3|sC=cr*rtiEV-IpGt_TJXi-ltnkO5?(Zi- zgFYk6AVP|NWHaUlrjIHhX{2uCFEMb}qyp0!7@GONy}f;Rv$zRiZ5jnw=794D z*&Km7+MTh_BGyO@@e;IDsua&MGRPp%Ka}xdssgi#+dM^0B9)=;mw*6oqD=BeYp_E} z^Rx;>Fz#&SvoE7^E#c3X4?8P!0~5vM{Pyo>PD<*3to6e#C`93n6#|ZZN`5D;0l=`5 zA4|jm2gA^`V~8G*%d$=Mi1AhH@O&?=lha6&?id|Y3 z8L$t3oRV}|Au$M1m;>!FE1?9C{Gmg|vI7vMUT@HjP>rw-IQmOURK9E!E8)KcUqrG) zX+WXD@Z!3*#_Dz8Ptd&x@FCOH7~k{(B)6%UA-KgMZCD^-#`FxL<7%zY z_6rc2x(|D(W3YF1!Aq4Cfzt>^_&;QPsbvm-ufA&K>X=RN31?G${|xg6p4GnbPjqVP zZn>jLy72QYuP_^hlw>0)t0_5U(3rJCij`tagB+xy#2A8jo)9uLfT4Cgl#{*r>*ci- zq~7Li&2wHxnUDKg8&@D+ihNv|@JYmMW`>PxwW~VI_QyZhQKqmc5!(nfr*>DEMO2%A zT2iFnYxQqwgx&9lU<9XnXeA;Diy=jqK%~JFI#R|QHkzI zF$z7DKNXlllTKrfQMflxa!_NdmhQe2I}WsbSItzFaPpQhUtWmr_ zKo?honGg?kq3QHwLEvZDBE-M(ttyrKr5s4hg#J$!~9BCnCVHHLqj-!i5-)5S`91D)f#|0sliHLAdF&7Bp<*? zHgA?XG9k%cTo4q~kz6DkHkkN~fJNI96sI9IRVz5f+Eky;u-vr24Ig$`6#2zTK>FdM z71|#8u^ViE!dhj2^k{&(9nlU`ccP+2-EMEGV?EL#g(`qSmL_zms%`Oq2DTE;g6dd| zxG>Srx=M{<(Fkh=WnGYT>epCW=B{i2TYwV-HN(C{%DbLf$sIWN7m}*w34?I~^Yn~N z1%38~oIGP+9GILnFWrA~XaaLnrymr*UkW`a{To%}ao{b&6w_LsDa;C_W_G@&u?ag_ zK2?;wfPAd=E1!B;-ql!tiZ%c%X(9xvYT%l6Km;~^5@RnWp%69O>cScG9@EI8fnYOz z{(Q3zRIfmk>*uk0eqQp&=O?RgUMQ@^Bs{uW9$%rxw+f0Ketvl_%|TY7$+5)b6X~Xi#+GF0pG0WCSf? z9rwa`Q|FL|X&tIe)W@&_TOX0^XQ)M=ZK$>^XC0l|pn0A_6w4uP#FY}dpt9Y<+%>C) zxQfUaf~6D2k)KL`kF-#X=dnmsH9-}LBLsNPmKiL}pcGnA(2ZLX_sk10o90oi3C@Xe z*jEGCTN->wi!h?XVc3Ws?Y0?)eA>T%&g>&j`vMR5&h zK*rfn5DaoAcfpfdL8dF6H=XjJZJF4_S-Q;hFq?AX{j-% zjfY|INy6iW89q0|!TYt%j5|&MR;FosZZUzZ%`$-wOMtz64M-eT`+}oAVGTvK>ZY$C zWI)>z^51e#ZN3Wyz$BHpw~6wYd&tl4((PyvKP1FLgBxUI;v}z{MI3(LF)JhPZWxb7vjmxOE7Bt^VIoG?k`mY8_WP=h_1$M3w&_ zHI4iad>^hLKha-fb%lVu0_g9N>@%D%L&HKd= z6_8jTmTFSEsM&7PKUthf=z_r(-Ti!`%vIvu`)l z8=V_;qsEBVVyG=l($a1oz(;KEU+UkR0RJ24$$ue5W7#QnI68*DNJft5ktsLRWLAzc$|8fot@F1ls z_k>P09%kSWbMnB}5LYc~HC8^69$vqQmJtTwomD5}?TMv2mYKHrh^M#i-gi&riD*tn zccFnqU7JA4S|3Pkw*hDYyTMstEo!BIFG47Cc2O+t%()L;*uxksW_j&G^|LM8+{YL5 zcZ=}d{IBodzMEf;-EvWO06B+K-Y)6x$bilv_u&>Yum3_gv{^ULZkLYvL&r|bV0YJl z`;8qjTG(hFarY@?P(;-x;7Lj18|7AsP2uZ5tgSeOBd1(sT}CXx+}PXfFL995n*iGe(?cNz6i zT6e@gKo(;Xn3}G_IDDJcDh2M-313pD1Y6d?D+%$v!k7Q6M7SZX8$L6CDR!a$aC&TQ zj5>4acCo_}bpKVB|92U9lk_?9XRr??Zrvc$$>-@DyiF0CE6@kCe*Je~!_|+Ku9@}U zdyP`@I#0oQN!hWk9-*tv7G*uOlj?j9@NZX-lA9qD_?`Mu0Odv3H`jCaV~>}qCYu;% zwmVovn*o}}MHkbmLGh5(|SLCEsHKGF@#JYwYU1UcT zK@9JZLl{|H-RUFQy{|(}lvAl(QC#B9iJS-Qj&2vx1o3)bS=MBF-xbc~=^9L+TV>YHEAPXR#n-ejQC_-nBPKV$2EvOkqeAYiZ!g< zvbp!!3i1P-5?)`Xi^ZfN92N}(6rz8x4mOAY^~@nFPyuNLD2tbp=>jQ|RX2L*_S81| z2lQQ*VkhY~Gg#081_>`pj^fj}cW*A(>FXD-b#;d7E|4s(A(GU~0AzVCH_<=E?zuLs z=PA~2rXQoOvWY#npK?~@Xx_tYxH`$>)iQ$hKCF84|@(CI2Z{! z8w~drq`T~calirrvpHg->>%av9>LlmIrR^!mJZHF5rLT9h_4LSId%VyBdNbWXYT%J zrE}PviFLsHC(DlcC#ixu;;t`6fesBjJXQ`mMq-c0_u~P7F;#8DQjd9RwJ`U)y{9HaY|$;!dam$q|-> zfc3;ECo}WQtRJEWs@ID`l~^m4KP!BDpFa+lz4SSw)k6LIy$+PkM!bm<{V|@6aWAe00;o+iat%Ap(x>%!4nzqaGE8SFmrxyJ8kvvvyTQ}y9 zs@ZJHdSm|7du@Myz0KPi-sq#FHGXYg+2cv1TTxXZ`_#FS7W?i{eP2aiaANYZV zP7jX+;!J&Bsa;n#wKibKM;ZLQtQxI~cTH0E-2X@2~Xz zMXl8e4(Yx6Td#EY6Ynv<`%&G#Z0cIAa7NN+B3re~SD*5Y(lf2A#WwF&*NbadQJrs< z*}Ipj?aFlt3*wbTJxw!ReokPPpJ&_V#{6_C7awGR^*yYvuOX>`u$OX(lL}`$l!wO`&ZY zy#q|M+l7GN%QJ(JeOFck3oiA-JzNxRv)ie{?-Gr#Rkv7|m0Ii?U1FcGZ8(oyYdE;Y zHR0`I$A}wt07P_4gFpPY=E})?bK$%eeOsBg8<>9>qRlk>*jCf*$G7j_ym)=_?=SxH z`h0Qu@`v*`=a+s@LIczHb-8Z-mGI)|=yQt~DVt{&b7uVL=m_WuJQu1mg8^T|uc{p{ z7Kp2h#pLK{@k*`pzUrV|bM?PqSI6-1=p@6NEKl^&s)CKl95&#~F~6Lg5oR18AJe~x z5*dFtUn5Pbs?0mW9rV-FO!up6*lOx#iZaQk<9^y}%m$2ZJ za*dCFY^ZsrcWOm9YIZz1vVC#D8NHupi*kQ=^EIKum}fvQc`cK$$6|+sZy_D=pIO!1 z!ih%h2ubF&6o0k4Yh|(C+5n~dw$4V6Gz~w0)XE+_YA2)YQ8w=OJH?%5263jrCfxaB zS2}f5oA{Gbb*Bzb3!et9KYIrTJZpioJGcyVK|frVz#??k<)2iY5uv#5y4~67>Gfu|+XJ<&XHB~~UGeXyNCQv5$@8oH zn`cke)#|I$*X7kI3jxsnq(gsI4*#4+93dhgAFf*mN7g-Nd3-#!5qi|Xt0n5f}wwYzeu-d%B&c~A}Z7uXE>#nh&4E4dSt;&C^h)ONP zSs-e=S-itLc+V`5%-|uyj+B7DfOLq9fBMSK#!(=c)tAi%E_=E1=JPU#$!MU^#buXw zy?$NRg!xyBsaSzj4v|mO>#V}}tGpg{*aUf@Hyscv^9*KO7PP3-r?amzSmo2%Q@{J~ z*;D+P&5-P>vw-Hlt*d=@+q8e50R8Li9btF&Y{nOYmac%H;I5XNx@l>2)9iV;MZ&Kg zcovkc=v*TG0W2(-o2eZ5R#_M2OA08n(7xsjOMsJp_3Iw(vQN2qJGRWsrYOiBjag>9Z|t zg9WyRgL$%nBd?hVbuDuG8`v@+)CS&f>>@dj*5TVtq;p2&?lOq>`|)u-}Bf3a{BLdjreF z7j^a&X8{k_edXPtYzu#aPT3KKfwhA;*c01^gBc?CxayS3*RC^EoHoNobyYelquKe|!j?$P9fy`YJ>oq);7d_J^2Os8&W zM!eMJQg#j|J~TC=KzZkGE*e<|(gd`}TlfL?EbCR(!%A*p zqQuzc{(ywr*Oh+)X4t^ywFU-lEZ#{+Bh+UgfUB~r_Ti|gWt7Srl{5`p!n)k_Ep3Ha z@zoyX4-(;NB4!eZ?{ptomhi!|6zOp)y1p4b%|5<=4U*b*(^rK-U_zmyY+?JV{gmhs zED7Z~l@N7v;oWxA_@uDE$!kz?+vV}VY!=B*zkneLK;D1ud1*XBX?XV}y<6`l`#UE2 z*S|h~jI9@+ZoL^61!`JEpJi7(Hfz(+6y8tPd?Mf6#}tq7ic3 z5nFX^KUR*y35ZRFbz|4SY3TU=eg$eOGRU0CXsR;^qnQh1n7umx?#0K~9~K`j-kiVv z_+e@;@BDx1lqt_aNP-kHtlS^|D{ageCv8LYJJiLVz9-#>a_#KkUQE1e>`T5$51vA- zCGsAkBu>A$x1yAm+8q2?_H$}150g+?HNwW+yq}@kuplAD^qmCoWh0S#ckfSkNL;dI^6+pe^&L2n>;qxt#XEJA(kWjeP(D z&;R}p2ks>M4jCb`MK;OwyG%DMj}#3s5H#$JCmC9-I*(~0^#Z!*+Q4#^2t~$C(*lv-(gLst;KCGXXnxax zmVx$Bkb%~1zS#o1CKfo0K>kGf3f_rNb#rUf8KA`^vSxXKvV>ulVnT0NyPx72-rD}H z+EqErYta~0iMnTUK(h83$Z0abc*G+tWQ2dwH2e7%-|$hZTiW-#j0R$*$RiGtXiP(W z2M_n3=Gjx*qG~oXLXYt=sDv${49tp^5KpEXKPo0?*&}`SNFNVbeuhSx4jO*&G9CZv zE8h}^ear<9xDs2VJSfChEU1T=pbUTU36Wu;3qvd)07uxEM~3W~93z9vG$f_<_(8Os~*VPAm4?p@Dx2xAg5b zkpHTh!v9C;v|zzKCwk~1IbH&v{a&n{(F4^=4eSB6N!MkX!FquG!|nl!Z-BWJrIy#e zeUHr?wA4Wt*BBo~vVljyK{i(%QE+MRO#x~5u}6?637#efa+wmKY!2v0V^6bD-ggb~ zGgSjKdpgPHAPl5v**ZvRKBbRN&8H&o z`jEnBS2^Md8hV`%ASR^PJlu27p3HVNYfN1AZHvfArViXX@o`!@9dCd88K|(=KnLy0 zmbh5^)G)DS$X0y%npbGD0V%Y{yCjA~k3%roG5(HK-WJ{+xKb;$QKKA&v`7_92ap7i zg)Y9*76LLOAX{~y`4hh~)*rDI0MY=iv}~9|wQ;E8~>xHf}>q;Swkw#q(&k2b!mhL>Z1^;Qmed zoPoB?VoIGddrL$eF(3~K5V!|YgqOgi0IAw?b8V%e+?wTK3$}ltl1{VSTIEd~kTw?R zyPSr0Ry$B{;Qp|lJ3OlszzoJU*o~qgk`k!}o*o&&M>-+mOepV$%g%mK)s7Yd96?+L zjPA%f?)Gr_t3wgbIBaxg0vZxqh4CgkMW6!YABP5yhZ|D_Vhqf@R&bN!%kmL5QSpfN znq4~GDVblKl^lO}8W9n$28hP1X1fDj_o}SQZawc&fG8fzqYpF~RfhG`y zuf@keVB`2NnLf?@7+=z4iVSxl8@J{G%H5CjJIVj{Lv(roE(P?Ha91R4)C_nwMEqVB+O#ULw2TP_FY$E{Niq?YVYm z8laA4omYP|H22hs?d(OvVz`kYnzc{LBrXEvWbH>rlv?-d=~vIbdFF5M$S!(B{$Jkf z3F7LgDB0bBx3W^8AJDE$f`+7^S+Dfhf46<7JG{+5DPybi2>UeKlF2!|%X332QAO$N zPpUX*UZ zL#fGG4#1KqveE0046Q2S5%50gxz3j$P#B7(8mmp>qvfqxj=7d|8bU z4g0tyPgfExaHs7g;H%TY(19RiAQpRE_`n|b*~SjsZIiV2WHLxPSy>Pp5W<*F0%^js zt$}|IGmSP(qd9x5m}IlW4MANZTVP;V2RZ|XMe$(jbJt3^3;SMgebVEWIxOl(QXolM zv4lMicw87-J3&gB2ovx2&zPQQCVdo<6GY@fljo*MNqV0S(0Ra&9SH$I&*qAV#yk}Q z=Kj7;Qaa~vCN(v5X+rS?+N$@D&6}xV078GR0Eayo24U@uyFjT?Hv$bwAI7*L#a!Kx z|Ha*mPJO=k=zPcnS>mLV*QP31Oq*B#=HLdl0r6O|!^~&5)fK^gOdshD`HV<`LP6Y`lLg zr&2WBEh^nWN+NI=|G-W2!s%#q;JXG1YwLn=_Jmp>l9wQ<2}z5;P% zy;d!rGT@&C2QqA(%-0bW8J%6SxFhD#*utBmJto>1W3uh~kL@+=x^kJ&i)F2 zWc1%(kNMx@AY)?K@jRr{1U%WF>@>mF83#2FK}nics@`Cm?_FXn7qSu)Hp8 z&LcF&4wEU)j*~RXdff;S@&p)?1LB?V6x;wJbE91jyPf2Xe8l&J5c2>z?g=U&XmbLI zxmth!{0~iP;jhhyCk1Z8T z)RH+MJO^@N;?b?X&W<%!zyfvCvost$W&q79tH$8g@#u6kY+)wHiLaQxef9PXV^1Y^ zDX%i!@5r@>qM{RnaCTRF%1R|kl7gEJ9REJ>EnpJOdxg8?#(aNJo|-qqk6PK#W*cv1 zCrBpkw$!Lba|}8Mt%RY`?jE$A`2V{o!G;drCAzu%S36-h%E@#@$LJJ|y|E55Xq;EYw<=>C2q1K& zZdApo4TzSaOj(O1MFfH#iqRm(*2A21k5t~#N|g8WTR6K8Sfw7!Uh;Q=l2p)((9{%6 z-(m3M4g-+d5<^ZTte+MP7Xnn+m9>XJtDCY2ZE&FN+7y4;Fur(cGi{9vUzRqUV&wx} z`UksYtsUnJnkS2V8ZS6Su)s|XdhVcW10p4w20{I1JXrd^eUq<&7Mq83#T_q}msV0P%^Lc-p%8J3Jak}Ot?FN5dO41DrZnaHH zGlA(@}WlDB~=bxJ@9EP|7kI#W)8GP4%r< zAaZLXm~p3jrs4`4%xE4Y;c8jS5`jYN9zDvu&`Orl)P*-DTRO4l6f!_EL> zNWh3!%A5@iTU#JZNXo1IEPGMu#%4^>wixsX%bK7?*YIhbV7PtdEK4R1X(;3tcfum` z1I~MD@*Iuls2jQ)JcF}%??kBRffN9pVyA!hHSAU8W)0e+Bn7XU0=D(}S5K$#zh~h( zpMUinpMHb?`_p8WonyAGUHGa2L>Dgy&t3E$+)R@?;)A0NGCG$5g9!yqy0};*N)~Ct zfu{@>ITw(*R?<-Mgh)niyf`wKhZoKZ6KN$#6fKbqkZrJWSsY2yl*7R*?k5=I4|0E0 zJ0cmMnPYLf3){3|`J4hpytNi?$OuG!{$ zKQDUh{Hc@Q#8Z}$;YgumYx(UZA84%tzTqgam(tkFsvr420PGB3rU%!66&bC|ZV>*~@7!1R{!g z4A-2*$Z=+~V>+A&K&%L4B_z>|;sQGq7lm=UAEgC!HZAKKg}3)x5(s5b^s648;a z>%__bB2dAuqeu^9kUGhoV&Tdka-_{{Lc0DxVcNWHq8hC72sxI^cIF?+cmjWD(bVCB zppoU}6ixOe8}CU?B?nLN)#T`b=mNn=PSGOub`JvI?kayx5KzGNvQ`r( zI|$F4`-!V@zO1|Ohpe|=i+T3YOBux0k)aY9xj%F)!&svk%{H)vhBi=|)u8<02d1UV z9n6!!xEUl=fPW;EFWG>An5a#$87T}Q3X|8Bi6GqWQ<0KSTddEgi8y@R6^!Drtv7jF z5^uy)S7`MHm2?`Ub)A1?FbXI`ktGAAua4{w*KN~p&}hJc1buA_x#U<<0!=e(51QX7 z<7rWTsuz)H3Gbl!e<1@$NMIRHwS+WRA;hkh_Lgw1+_EBJ{p$Awa!sYH}ST_oz zY6*)u0lSk!M)wRq$2d`+=_BT?E3syw5WPo}G)m{h{&)Kze8@BAqH&jtDjXtKW{n6X z@^710Jt6iuO+|kXF8!MxuJk9Rc9Apt3iKl47&%M~33jL4^}w1%sAD94zZ15UfL5<1 zlKEpzkg$>+OQ>E}N!t$G^M9ea&}9dVH}@Tn0Ztze6f3oEeq*D zkllmIw*q1yG(E`OnJt`(O~G_GG6a`S3rkOq@#WMuxywgR-3&8T?+E>E)6_M|d z^fF8`Zi-<7=Jwu3oB{0;)yFt}he!T&`}4?zpE8`$FEA7SH90FTJ1ZzX(w?%9(hK@y zP?WiCG5N2R>o7R3xdmQzp+GxG!eD+2>SgS#oPR;~dHmy$WF8#WZvraWNSaDm&}~8yw6a?Aq7%@-x>=> ztv+{NaS)D-pB+9jmUjHtQM%kT8;5I6Ryco2IU-(4(_)0M z-%k#xIn@^Xaw@cdg{?lJV6EnQuV*G!Zan$<*)K_MI88%WAd8O^dJszJE=AMj5+HwL zlhD5q=~(3VsDoj@G49c+SqvR227zi^*^#?G`-GA?dg$COW>-;xs)`M_wW)mr;7C_C zxq#kf%t2*0WfxspMQAP+0=p&+$~}>wy%5yY=44qt3I=66E8?|v{tUna9cCv|21&4D zv~{*}ThFSJ=!CLM=j96pRPo|ag${p4f>Z+!DZ3n1(s1as-X$^;ufdpZtT#R>?Jxig z&Y^5s1@wxcDcMUe32vi0M;^JH<^Z^);*bzhOFz?{6j|St{MoZC@{>g+A6Fp0E71V#*_MUk^-o%RD<|3) zy-pZe6zPwaz2{#&Pvpryc`9FX6-PgfRoV+q{ z7)V9K!~!?l!dv}-KQ_3SCfv(-C<0LTPWiALw*asU63q^*Fev)Pr-{4zNM}#JWmY2S z6rue6{Nw<#55S7q%^|Fx-{DS6`XqtL_cNs5!+?Gt!#TuYPFx}G1;Lm?n{Y}fC`2wG4w-kA@fNO(Icpdm5L`j~-wb2(ksy%-O0qD1P!eS^0 z>keawwR|Qh4k)5XPlS)og#~A~QOI1s+q7`q30y?tOj$exm)BHf%C7@*;L8a5@TU>H zV}J0+4^oOAd=24CK7Npb^1p`gU;gm}gD@t;%V3QEH==*cq5cMm%ts*{vK;CWp}2HR zZ`eH}B9hufGsF*0GPCUma%K)5s`;3OJve(n53}t`x#z?{BWDnw#lwKQRRvZpv*Bz# zG{-X>kmg>)HF$ac{=?$^`M-X=cz^!N({70q8#I81=GU-+MGQ1vn%@VS$Y}QWsEL{U z+^%D=0Um#@YlDA<%{(+ir=$BTY!;y!G>x7NHurGQ_3$1JRNGuVs08RcZcP+zxpXuQ z$m-hF;=PkNT3A#S5Jcsxs?^MCxsWoVh>f=3uTS|?@iEEsw6JP)fEh+A1eZ=hvn=e( z*wT*xjqbv5M`A+6y0;IJp%ByV>|-cXfO!w-L6mTt)#T0D__a4ySr+o+TaiF?) zbQPl85ethhZttPhVtoWYcL>MG=I3zB^x;#W?$JlU zhoZi%=l}R6eeBb7!t?q*zJG16EHV)kr|*CK3d1q0aVC~;IL3nu1)EP9+bxLSOT7iV zFTo8N3>%DU?WDtSXhAU8p#iC-`-(FD_#unIcJudYyzxXC@ZkQVeX}N}{9$Nh>@xjF zs%Wlz;0xmcD+XVo$#Bt4k1KrFv@5GKGGlV7+&$$g7zlCDV0<6%DvB7E&Dzp7(3gM2 zF>EkfQhB*$aGFE(&>M_imwIs{a#&QShn>@!ywu}?a!wy>(@`$BcN7#9PX{u~Mrl_} z48mM4XH!W`4S;7&y}{z&#Z5_(0+&ji4FNOR1}<$VFJPOCW~FCkbE@i7OlZ>GDL_K$ zvv|_$e4}R9-L@J4cLL(f6SMfyB)xwh7qvzkr;?!RpSUT0wwj7N*~6vMY^GclUKm@I z#9-g|R2e9@Suw|w!Idoi2C`*^kcPKv$;>adbDTEPzqisiCfCU!NfFk=eX z5HyML!FmsJ(M;)x2hA`1L?}Sw}=xUEurW&%*)551oIhGH@z8u`x<`@T2i4X z1djPd-Q0SdGGz)Q~bRybQz`D(mNj!&tv} zN;}r7;H8{@&au>lUpM93Z@=|JcVdJZNg47@(`<&A(MkF-B;pAfml42Sf z9DG3WCT!*vN1{^uhe{kx@r!@sY#v=_QD%$wQd0m2#hJ{$ylWdOfp+ok=4(W!7XPS9z@xm4QJytsUMabYe65pBO%+t2dR z1$v?CLLUF(*KiY=lbT3$+j#Wo*&p#nKN?L)D%%05Uq@6aWAK2mt7cK25iqsuH^h1n7!BO}ARJ z5@QDh=!!l~x52s+w*wLAiat%+d{v!d6953UK>z?Emoa7&7=LeXY;9p~VP|D>E^v9Z zTYGQYMz;T7pJL#kkd#%JCMkA%4X8lYn{JCXX%VM)aghzE5jC==rbsP^w5=}oyYG3- zlca3tZr4B@iJUnza~{9*nB#3z??s+(yS8goo(sJ{)J-eo+SFy&s+_-1?Bk*?OI5VG zu8e!M?W&@!>wnTeDC?^$U0qEkTO^(3(Huwpy((1Imd9U=+FaCCD|MwBJHDu^iiaP7 zs+;lMhYvqr_%}bpn*}|)OdsA$1Apb~V{VF_+ABL$-4*JPZ0^Upkoe$#W!b4WO;a}u z@mAiwS8a2&Uw>}uyW=I1`K7w9>f6dvJILZ%UMZ6qeG!-K>l^sgHD#&S@TM`!EdkG$ zuD=o;YQV_88ZQX2yY_7UJ zsF)G$PNLd&?yR_|5ag*UkCZCOkD@PS{3(WoCFT-@w{&v_uo%>q_steKtWz{Q;gXW8avCP0prv1e_&8131rQqqZW4U$QG(dR5iU zUY4LM&5U#vkGBxkJvhajf1eY_&d$#0|BFV+Rz;vAz~oW7(oGb0B8dieCmR4Jn)|va z04x#OfPL@3y%4Yd=j%T%KtAn`4$piMvf2ogAfPI+QyTRQ%tBR0xB5n9L878}?Q9)L;xCLUOgeO4J$%_5EJ4GhG--=`1iCb-Ue$OfvC^E!79@lWfRoF)4SD{$*Yyy12KBFLRP~UQsPwCXov0bphUF8K5=`5p4Nne zypHtXS*fo9+t$B=f8IJzNzs_I9MT&ShnGXVi~b^P{X7DkP1jUlYq7=h8X#L>3)!uN zGxklCT_+R4b!cQsSc^T*<68?y9<$+=079vvPqE0jj>r)bc_KeXC*M|hj z7*JwiP{%E`Fw~$COq)}G-|+)n#f8lTKcHKl6AMV9 zm+Qq6ISr^gKkb|YsFh3O(yCFHF~$-Y5(Lo7SdYBSmM`bYa2#l-xI)mETgDPBf4qJ< z@peKVICYJonR1^T0^2rRonv<Ojx z5HqBQ`eN5PM6BZiHfnJdom8j3U4MH{%&=<8gNC@YyEAC?Kgg}b?J(f9un}l931Prt z{jC@kL>*<}O1?#aOflz7Yv-ur^dbT7ACerNLxGPtonrh7kb336Y9#Zm?Y-uVg|A?R`v{ z*w@ucZN(sN);`P@(OQ*aWciIc7qf&*@ zV0RhWV^x(I+Jb^eFgw+%;|}pEa_UH|-9)cd2ayF@f~w;ucZI^ zZ_ew+d~j&;Lz>fgjGI(?6j`W+&9-(IA44a;JG3I$U4+%9x1%Q;4BX$PvhPeo0m{*S zg2~a$Pcwi;LwNYJW;7;osR^oZfGv?^fl|Vza(LKgfF89FeB-G$JOh(;(iWZE{7RE; zMV%YK)+eG7>9Y1@dL&N2>O6R^U8H%06-Ks2r3{|F-5l}pV44?CK(AxHziCDchjy4; z+JU$lyMSO9av7kiQSOaYpx9+BNGx3=el8dntp{GWhPkbtpRtAzsV3~*dqoE@fZ&6_6f&j^suC*DtmP@i-nd}W>hYx) zEQgNl;Ku7;hKIdQXb)8-)ZqAOv6M+#iOSq%K6ktu=HA`Z6v@{PAn~skqj{5%eygr4|5{tl|aLxv%>|-(1n}>V&WEs}o+=*KMv17LW&^ zyl@Fjk!F9WpYRdUsNyh?9x? z&mC0ZiuQabiX&TAS^CUxoQ8DJxsWjqUG41n9JDBRgiIaWF{r%5fq!Fff|SxeK@WVs zz)8FqhBlax*?~AT|90Pb7}3y}P4N!+^lwM>5JqNPBxvK3aQVUrmySTg*OVQ+LG2#V z5LXxRVF10KyFAB$T1ZQdkm{@WkB@wDhm7+ASE&J@(I&S{{tqIXQGfC%0~i>uc7J0 zHg^{nyOBqW5DigOCX056Wc?r1VIg6qWcN~u4T~h(xX`gthduQQzNnJ5-SG7yNnOBB zP2|wjSE0oPRJ#Ojf@<&Q2^t;xM z?)2Q&M}$@LSP(^dBRdVWG3K_YUaL{!zHUx=BUqWlnQDj--6l-yxO3g?&i;q8PO!l{ zP1MmlZG;^0&C2!X{%^YmdeS-FvTLXz!GBB3g*o%PZ5;3%1iGt0>2Hew+z|+!6aJLG zR}`8*ObvDHUfw*KlOnoiY&bLy+d}cfmlxwDLb$_kbfVlRLcQikPxvZ>*tT2V-C#hv%0*9ydX$TMPrk+H)Xc5M+_SLlLMCL zgWfI>X(%Izk=~N>NxVP+E;zl)#q9ONa|Hhim(E_(XGlmzvbFgIoJ zbhm;eH)8O`#rPe7ag+>gPfKZJv{TI%vnR6$th3Xg1uBBW14!YIF7hdNm7~BrQ}=w1 zCdHEBRKEMEPr?l<&dl{s-`iPR;ZIs%7=9uue&f7@JiT782Bfss{>QPas;jDIFuOQ} z4Tml4;wG>H8DSQ>_`9F5=j=FQ8v6e>&57!y^P5W-=g3#*;#cgSj zvnZr`U5ohWSf?84qEGa0mF=yuYtL>c2FH57cMr#tnVXtW>aIF; zf8bXsu-NTn zbJE6VQ3L>&yAeO-rWiYbS1&sxTS) z2wb+i``4qe9^ZGk7zi_?ersG)R%TW-+TiD|pEtWD);wHqaZZ0kGwTSlcLKwS3HVl! zSUX45d))F9P6_KiUtfUXS@J~AZtXE5eU*1YG&+>z`Ku-h{xo zYJZT#oX5YTiJBpzw^ z2u51;+j)*ez5D*#+0Q|=ooTo~hNg{m7Ace;`Y%Al-A<7Qp>MZ9B)?zkL~P4xajour zCM5rG%FK_0@F+a-a`L(J!y*|07J^4-1pvAOg>!mmF-M`5-!05N$*Q1~Q;SB&kKiI) zT&!^o;id1E&OOU}BDO3#al|XP!Jx70XvR4K>NE>s9i%wHD-}ag!Se%`^xM9M9cW3R zXt$f%+KTs3*p|8q$RaU5+x}KE?sy)<6&9ZO0_|)>nhM4^~Ug zOuipq|5%wBCHVU55GFCO`Q`hga?=bJ{tJpd1!~zk9{I&drPBZkxHEKT$EA<}l44+O?Vhpc zk6X-GC_q7NKwqeQK)y67m>G3!{7tG~?s_v-N&aB}-+d+6DF@?xNFX4aHpWGid=NnY zmDvZA(+$c9Z6M-8On3N=`|DIz*DGP6d{YEsB%G$a(Bz7hRuoT^wi?E5L96B;v>q8P zHp~FS^y^3Iu#?BoFsmd;HDj?_Q^7Ft;e%kJdqrklTGt?1U8kM$Qkf3E?#AD*FGv0? zmKQ{~hKiU|ZBz-?w7am^$?aw;`C@>&77Z_N*AuiN4=y3+&~fCWZtrWwgN@708&{BR ziJ6stqpL)Pt(@$v7u%hkqm(_pk-Q~BqSrjSBp#L(3%_pLoo(^6Atm7-&&wP(9y!sZ zNsvvi>-GR7Ts=~I$~5*>>oMk4WQPhwg3eTKF!mpgMAte5O)DGGWE5*9;YR>iGAshU zCon8-q^3$}=$S5~36yP8J?>Czw}@>0nBog{InLT5Yqk}_Agm=HW;I(fYq^tx(ko{W zy(%((hy_f9rW9MDNV`J1{`$@GJs@i z8Zx&IoQp!9N3H)UnWk%t!=cZi#qaiZuh|`mJcs6_<;_ZRT!&vO`8M%HBK_!VVeN~( zB$46%Zm3CyAb=TAlzKmjyw2hmp+ZdeVJlJCjI)KLI5DBEd_R*>|-9X z6J)K@f z`_kL@pH0W$=J7E#W{r2m>jlv{<+gSQ(6pDp*1LNj`>B2F4t(FI!nS&u#089~oE~KC zh_SSRPm2HRCSYYga|~D^cD~M#tq6PvZe&m$LF_pE_m4TQ(WX4FAb`@)eL3c4fh^~g z0{Uh>XQMC_A9;VFaZ~8)<$WeXkr*d;)AEXK8mr*5-d0`v+?JTabe*0sQm~+mUO%%u zG{&Pws&@iWcWIL4z??IaNMTv0%hp5?K1>O^ORU2eWm66doF7mRZ$O~!?Jn?8Fq~2F z^dFU(9;fND;TJds^Ba05yLVvUbMJBxOt5CAh@;#0&{J4862fhUezy-+;VBi26&`0c zShxOe$W>YSLl=b3>==ZptEZ!<@gkc^976YB0U;PlpvAlNdSAt-$LaFM>{*ha#D^vF zgdJLiVksK4ely^J3unwRnV303G+rhmIT!WO#scbow2ib2fIcH<(2wHT-_OYlmvzMz zhz-LgU)H2dN#?K_^u9A_V}fn)r6us*6p1$x$RFO;r+RomwpT(j^hOG~=w_d7703GO zl+0})K3tO%QS)uAwlPP%12fP-h0UIX6To~|@28-ZmkxM_pJRjnyY~bS4jLy-fSYw> z60pneV-GwpR^=N5GVkm}+}x!+;W(^CyaMf35sK=EEA zkC*&7!UV9u{KDwY;phy=4!!ns#a8d|oBl0}Zmaz9sLBt>+>`2)}%XrB+I0hNbKRPW1DLRLL8)a z?cL~?xNcW<1;e6!ntiKX%B%t}B2HBA1SoeDH-g5q2Ma)F;efXAtX@kJ1tSNaF)JJ&4s>$dlE*!GMmdg*sKUFT{xB8Z%3Ot>q@>xTh@S&+A z)yt03L>3jr%L^*<`@#%Fv3VS~h|~q~LGj3%fPL>Xb6jc1Scd&LZ+4J!x-QWjT5x-_ z%W~EsuS;&JLK*1VR-8@im=5R`Sv*LyW2|_Xz>(nN0?9za)M747soot@*My@;qTTi9 zK!}TtJ+;(H?Y}d{QBQo=gL~MJ_djy*5vkT2Cm(l6BwsOMrZnvgh7{6$W67jVDy*hZ zZ3sKKiPG|l!*oO+LXAoYDp&&(3&x<_To5{>1^G+99UO{*ARwfp8Uhe9CX0uI%@7)7 zo(i`5%NVaZ1fj$d3=)i`<)2tG{t$V?#$JPbH;}NmX)Ib_Bsfv%BoIUx;_-3DgNSGV*}wY^VTEbU4fo+M~BulC^PgEIs?4h zBgO8wQJDlZ0tOE}o>DpHa1UNg><& zIXhZr%f4JAp22!sBzu#Eo5JoWY}?x;#5Zd&cuNt8OU#%UkzK`FsO52=R`6m(GES{P zTwp}H{*fTVWBqsctP^Em(0BU_F45{*kp797$mJGAk};J#*Qks zbf$s+(eY{Mm>kuZZXE_m{MhUWATLJ}e+J7)m5N<~wL-B^TuC75Zi*yMCx}DO3#>4M z!53ood^$n4c2IbE!ZEOU@hLn6^QtEb8Sm|-i9KTny#v3ft9z^$U$u?~==B%8doXp&e2g#)qqvy{!H z5iEibc7*l$7LZ6tJ7@}phIL2rzy%$OCL7q!lFx!{4}vrfa&R|_apLp+Q{M#%IEtQ? zI{=)m^BjY}EavK<1vFqp@ENR$^{WUXY-&WD zRoqG|Gbg=&c*5h?I~=pWJ8I)6s6P=STfp@7pQTL0wD62o=u>g^bmT%2@PxL8>I-b8 zJiu+Sun#$Zo29WiqdS4sQ@iOr%Ce=b0WU<_JoT*XW$Uf)Y@kvPi&uIm!wD5V0t99U z8L8$ri|aKTW8G=0D5ncP*W7z7D!I8i z1Y8R8a%YvH!Xthh@~N=E$*-`#GR<-EoG|biWV?Vw>u-nML<^I?hVsK%N5b-&-yGd7 z3trv@rRqfq#=MQd%jm0D{t>muN>sM*)aJX*AT4PGW%{AOn$Ij^h!vSM zoa%e_(bO!UXcL_fUhw&(GE)k}22Gj$37dafgNUzp!YOeaf}Kv6^vKfM8yA| zme^6ii-5HTc|$tcy8elrWDhpWh|-ktWZ%YU1#Y|6fuiFjj+B-Z0{oQJ29}s#^0jOhfYHm4f#E)aT7`}J0 z>T(}e(DPtz1;!kTFP@Kap0t27X~v15NausAlM3sKtucB>Xx%mY9a!3hOeQpgDX<37 zE8S#ScOJBzida!-H=sHk^ti0@&K-?>N{QU4j8seFV_N(BP_P(zI#iuk5ZN zbmJ?RmkMSG0l=mEQ`T@jj_sHecmiQS84ZA@g@{!YGMGJ&J)&{g4h7STfOuu4wf4^2 zFYCc(VNY$hfN~sGWaya$qJAi_u`?JYSIbw}XVe$y=^cs)p6veWi3-ywa7-NxIlCzq zJ!#EfRk_#Mme80w0_D+&{`pGcPqHcXMhn+$)bIy>0)UBV;J4W`jM&fW=YmvscwqNL z&yvPUkbcdLDK@0iPUDffV&z(ohrL@WGWo%j<}U2kugKN3iS1m{VEyBFD=(=Dq{KK; zn@u9;lFQ<%L5b&Ks8=j}0^gqz5UkkOp;h3@H)o7QK98a%f6$5>SvwfyS4Xyk^bodmTY7RX1rV2vY`x|<3)Nsr1Ut{5Raus||JJZjzP!RAZZ`f^ys3$Y_%EH^Wr@|ZyGk8) zcX>UR-X2=M0XCVtuZd)gInH?$)3V5_lDwp+mWFK@?c%2|q!JV873s!C_-wH8f*4ht zs$KK%XHt3wx`lSal6(_^Fq=@W62+q#0fP!!6IypS(Ve{P?yl7n0=JDKxlo8$q*_U^ zA5h?#EbKo5o0<4_3a@!yb-mqv^Kyt$y$P>;f^A@fsVvV~0{BcJj_26}XnK@apwG4Nl zfvLb&#@``t<*NNB{AT>uQl-e@Mcds1zFi|>Q~Pu1)q*r0P|u9-EeN?5ezr$xWalj0ARow26u+M zsH~%}5i*#y3$@81%9OZ`hkJUz&s|jw?RpYQ0Pc-3w4b1-q(-c3^#+K(cyvss^;^)| zK&;z=jaerO<*P&9K!_92Ey~WqWX@9BCX|fUg{jOjLbv(gRbzRZc zHe03WwX7?`I;Ixv|J&C_D=yg3dSE(Y_QQZ4jU`R z>!c@gGzt9igY=?J>1J>O&~>KJ;}zD?Rh*>HY?-k^2!>y>v1fd9_BE}17yPv$tj zpL1k8=%=KmHtI{ztUe0ecRjth3-#WA4Xf8y1+F&8O81ysz{7l+&y0xZGbKwV3beRMO*6uNU53^k6Ae+Mn^UOl${Nb4fOvY8{+EJ;ryt6;H}9H z_VFtjz{Ka;Dtr=H{M)UB$QlcEGEm=R)ZZ2;E-M=`#$bz~FkGxhpVU!XNE{CAQ16Of z@0+*))_ur2!{sMZ(>l9=ruiXbov(zXwrg&27IYZ$;Cd)qa>3mVmru>< z_<(7`isxjIB%3%2j#5$hT7W}`aM&a}TjJZLGaMxvs1up><)y60K1w14+43*BojHeV zT(&HApqRQ4;Lnl9a%-?)ck#Z7GAuR0N`g^9d)|K-Sn=l!^`$Qitd-Zj(cFokX%;C; zC$;>J&0x*Yqk(KF6iGyj64(HbjcqB-HIr+9y1VuK{DI-8<$||6w{pJ;$&q6>L_8uY zwuc%Mv3w=AWOHp{L*xj4~luzge=@LkR#z`Sz=M~A9Bh5c8x|& zOg0NX;DdtBn_$FsF|IY!g(SkWS76(2&=Ze_Y9^PQDb4N>o) zzov-|fdClh5C{v>_)OxrPd8jyd09~PUgBenwKmnWfm3nQiVvgia>c5SW`ojVihRkC zH1qW*^^auAmVp9FrljSnA(mL$kU$P*y@>HDppIMT*-H8i=2z@ud@s0dVFK8|F_Lz3 z2u-}WZ($UR(}X&%r=gni)g5RXm(hhP#P{Wv)X~q&jUFO=`mL(Y?71=;OD!3*s;)nw z;$(yU?Du|)7|ss}Pu;ud6o}iB;E;0kM}Sx<8ebKay9#n3z=(=%eS#4Y7!<7XdK7r@ zzuFy43YW7$OkS$Bx0!%L!N(#xQ7tFQi2<_g$_5-RDO7`wVp7$Fp|NpTgq66HQx%IA zA%E&l!*R}Zz=%ot55cr$Aen5XFBxCK!5%O~HFC7FBXFjIsg#wmxbmL7OW0YWVM35O zb(=I#VEw`>lQj5gyCiAgQaYxF_%iS;VD1`YyxFS-VVL=;1l5{twiIHx(iJP@&vJ}U zE8X=K}ep4a^ePh(bu%wQ!3XYV6uwM%Tx)hkY_~@Nu>?!fEKzz zRi5L*8OB->)N&!ySezh3s6b<0uG!j$SU+eQydC!_6*8d)G-Z=odJ2JTn*j^A5+l7U zqkI}`W@pn4G`)CPzPbU!hQVEr0`P!)$!*Avi&ZYB=pm6Ais1I5mYy}&i0}$fx}nf> z{!8Dd-*{WXM8-OVa>Xapo)P6Iz=;TNL5ki71uhI}3O|_|eD+PCnw<1z57!bXu{nqp zLCXvSAGegZeEo6_H)*MCeUv%TIzl1XN@0|55#*1AIlvi42YIHJBMBt| ziP42UQt^}_Hm7F>jl!+~{^&k!IHecz?OnwUTM8r1!m&1yr6c?YgbY9xqXS`hQgLZf z4Qql?)mYq6Biy5YV#=Fcy$Dt>K=|ef0MB_nmjDJa!(WMu8Mmpta)v>stu)JPJhH@yFnjDy_O?4gdtfA7_gIwIQ9IAAJ03a zn9B0^ez19p3xOH)9}vcf<&?19Z@67nB$~sOUI()aOUsK^aThNKB|jXXzBPxi)v=c^ zUELtt!N+KgrTR2a?xwb+dHEt6KLb8i!_VrL6>V}K9L;Mn*|&_XS04ta56Uf~4gh%? zqDm}d8Mneq%-T%?puM)c-a<#B-we@b>hj#G2HyuC>RgD)akDI|s01tRbL1lX(=2Y}My}cYDcBy0=$^Monfyjpk zb@rzLmtz8Z?Do}B=vW>eK2WcT2LmR67u?)w;rDUE9sPALj38vNb|5v13qyoBGeb(ge;x%q7U>*!bvRA#vIcpZIGZ&*l) znf6|;I|sc0u%mt1=gz68U*X=d(0jN+*du%dl@e-Lrh}OCf6L&E#Wu4Oo4K4BeEual z<;ga{_EpsSu1;`0c{1J=9)5lN;dE77)&j4+Z!PIlq4_GB95nyl3yASx`#N|UGb3)k z2-W_h*x-*FUCo&B_m0jCKy;#L@FuXFoKlCO!VnyKzJb~k zS|Pb2!p@YNs!Nh$@&3H8JAtq>-~dn>mF8rU)QNI0804~+_`qe;qfI{(R&w{8@SL35 zdbJOkT%V|(I3TS?`h!S7Rl0*x@wICIZ*dBJ%Fs(YBk?8uCkGX;DT{&C2zM?DqaJ|1 zpdYaWm?Kg0%#}F5_4VJ0=hH?4$Zlq-i)c!8X?HK&%uxn-xU~qIrwC`eVsHjq;r;Yw z9;ionxSg)cx}Mf-qicjHXtELAj11?4;e+`Fpv$+`?jOgi#fTYY)+Kf{p|kUuo==z1 zn?31o;#7y&Py1CyFNINo{=LQHN4Zw#h<0rQ@C7Q0X21O7#XUL$56TD@zO9Ex5~?G# zLZ}3z6KN(1O4hx66u_H5ELVeQEp&}EYm+l*XqFu)XaD+o0Q+`}!tSG!&yltTORi?) z;aTpkp1AoDnNZ*VZVm#yMnng=s(^f4e^(-u-g-&evs)BPmmN+_7Ater&du(e(-C|C zj^E8lF*Vw+{$sw*8oP{3@&|7eu#2)KhgIJg1c+KQSa#@sWCAZB*8I7NJzw`9$VB+A z?#Ozc6rhDnQnGI#2@7R8-)*;lH^KG?|V1 z$7SG*K@BvHXU3$-4)ksw3U{Yxlep3e@G1~AG~xvUtA0Uo2h=*tH>3wQyS46(e7fCi z=aK);%R#arE}wpN6rq#_t$4g4gUj5u7+_WKp5Bh^H8uFDBjoCMy})?p(wHZRov9|y zADW=u-a%Pr7!YWxBNPFPTf898`K907MGjIz8F~<#ZFgDodToCUdpcAhyt}Ib6cIvB zyyjGg^6FG$VmgFMR^G*8v|AvFwf6RU&nnY$m`f(RN7tSb6w{JZiA%io8LrcSoX$?s zBjo-(y5X<_(Or&g-eewgVKO@XYkED+xp8Um3&|ja7#2v{Ap!xb>|S>l0q#lV&(8kF zYT0F9MrUdvjeL(x9WFNA_uMrLisD}m!i1PoAstD60 zUQrMLm(E*kD8I9PAZ0S*E@Guir&(vqxa^8b@{e~LQe5mk2%-t`!I(+6qeSHhJdBNx{p}=*2RXCepYhZV^Ou zVVL&VTObFjx=ErfGc;T$0~brzUF<5w+)mqJ5J>W*k&QDeo`hDoVIr)g<|0{iAm^@+=#_#@t0rqvM! zvI%wiiQUzjq~q}8pL!AAi3G*vB1v^cawtQ23Mz|%ik=!%=oVuk z4(Zzp4u&YoqwdRe5uq4Q@nyB6> z2{LEZ8>aD5UVz}(NE7Zm<&XE22*@d*u2IA3)E}25U8RhLYE1)-IuX|YAwWgO{}ec} zMi4mh2206CLl~jj779w?xFVT_r030OO+iYd=2-k9^=yTW5y~Wm5W|17j`RU>HIcPq z9{!k_4rP`>U6`SET$tW1XIrsOkiI98nSS=4nXq!gEpRou*hxUKXHqLUreq4BFp85( zqh(}I2^E{GU*I8>JfHcY@e2ujul<4CAh%Q|Qf~e?GrXa`p5zj=K(&#+9|%XSA4X%Z zVvdZ8gS5+p|BlP6062@?lbUcpkwG+Y7Xc}Nqpdv;^wl|w`w-YY*@?^`6EZvm-s@gH z7~!<3vW=rro7obqX9Vs}&?5@aYaYDDI>QbbQ43Gwk9~n4mXfMhBd~rRpFCn^>XZ^a zX+?OOL;2+LG534HW5b_!Xz8eIf17^|A)v&FV} z2PPz_1*rh~aSC50r3JnC4<8)0oH1Z}#If5FJe@UGc2IUT8@(pK;e+6O41CLusryNN zbfzqRfMOheM$;33Iu?%s_=T<>lo5D(43~8^|;fgS3YacCtnY zA0gLxdR_DJksC%H4Si}3%_w(1K`jdMAv3HW*AqLN?d{5Zx@{??hgB!{y8`i@jZPvI=POsVJdIPpJ+ z7@%iD!iQmM1a5+TvA~~tfN-Pk7e&Wpoq*appUzL>E-;1lT9i?2^u=S|_`uYN zny5CuBr})G|0fM7pa~p7q8f)Ytv?PUTQst%YS%ZkO*R2kF9{{7B)jr${P7Hsq-+eAQ9=()ZD|gh^sk3##*wUNX`U$sZ%{F< zf8emUj_}d&wy6tFr#yY{GvTDqxcc*-m_t84(Jtw)*!MVq8Gr4kGi|Tj^>DvNcty*! zt99{kp*pD`8499fKq7x-EbHWX4AFfPc5eYR37!}f!V-is8=j}I3v}s8!6h(NfWq@D zegXdYy?as=FDx4)3wr}t#d7Ej>xm^$lA`Q%i;wC74hgrc8TlRJC~!7S0mNLchs^CK z93Hl~Y10;PKE7}rI$hH)6-4^4f6LklO2A5wZQ+=YlH4j@rw`Y3%>{Uldhdi-hH-3}y3_3L=GMbUg5=Oa(^lQJ8^`9BL z{aJ%vr*y8Eta>uEg)P^DAR&7uYt6J&ShWlriq5Nz|ppmu*)iLJ6^D8h453Dpx~1IMz8FNo?>Q45RK9<`jk!Dc+K zm+%}wc84QA6BA659s#0TSI@B0R$zf*7at6Yk$|G~jv|8KlE@8TrRlPVbAN#eWc>pWUIku-rosm+-ZR3FmvnTb(34kZ2Rj z_qa#hHrwLfv-V#MoE_wA@ArNJ#quxKGIey74Sm9K5_}CeAtKM!d}uLW6P!q3MAoc# zn)^_am|8g?@4ZTV>S_V(u=e)52={ZAp{_*+)1B{)`<%bS)t!7jjg{Hqg? zSSVP@H;O@ht->f4S-i1Gg+Yn+E6hdN)B_|>*YdW+4pi!X;g-2k0&@|mk4_G{{OK4~hU z{(Tuoe^Y+m!!UZLJLdBL>{{!g10LUvv6;qjL?+~sUP zsQ+g+7m7yy2NRDdd|q$&^oG3aj_wez6W+YG#m(Oy=SM@I9LtgCTV*Qo z5YGJ*V6jPjYgqKA3woe9WbWb@ai*?d8ugJ0h*BcP9UK8%FHVVn7;@x*?Af|_H!rqv zAub8lA$qY<5;wMO508BZl9yPQ$vze=d?+LOa|d>t7rNlQ!RMrWlc=knWR`5uig!he zZvqWoY^5<{{n$bI@*>^If6!rDy19IDI0T}+L!)%oD^xFARp3C-uync5_IJ%e^VFu; zW(mdU)xjR}h7cgiwc5l0?Qmdr8%iJzo4T9S&Xvi-1mT!43jh9g(#)<((M?$_#sd}Q zJlupDw2QF)BudJj1#uM@c`2SLJ{YsfW z22{d<8$;Td_nqUS92xMR@J*CT22k9m^gGCppKPDl+_4+1iKgX8c7pzYIrq7#u6~w# zkzpYPdPZTVW%M^pRI-4%ejr!3=jLloVVm^fukO@P2da5NQt|IV&Q8F28JzB5lG^C# z=S?9N)qM)88c#U^SliOQIdK^jp_ud~6Bb3GE|RJhSPGS4Oy&IP-#OKbJ@-u;j<|q^ z)n9g99-HZ&Kl=IIGOI;pjMThYO;~4Mg$KzD_>J1B>9@*hg-Z6h>U(k0|%+8DH zM2=6rc`ir!VWGR6nxBpxO(TtX&e_I(oW!9bZcHofIImv;e$>2ttaiR zIC!}_H@)4xd<>EFem?;>W$+lA@GQ0k?V9#K{r#acB&l-zX~#nPW$n@4_S4%Qbtl~W zFQM0|D+6d1!L~R1^(Wi)JwiRcZ_j2vQas4XGOQ8otGU3xj~n6Z%bQ(}S;@FsT-J~H zM*QEKdGsZYF~#6OKz_(+e$OZ*X+NN-bb#^2jZ=~+97)mZ(C^zWQgZ3WZ5N3!L%#+; zyxZQ-n;TMBCnx4kJ)Isy$BMRi>)heYGh8*Ogm+rxj#M92D~XK@7SM@XR0%<9x+5Rf zPL)cq7aQi643PB3n$?k~D_UeKFkE6bY_N#+9CY)NY35!p&r!<&E@{Crp3jJ~1Aqw+ zmmruml^bp3Y6(5L2=Y;vki^Vk3JNwv+|~E^rm0aAad^uD#1lFnu;tz<*Vf;<^G-c9 zu$iH?sFAKL=Y+F(3;GB5bPHpp;R)YvV06kKs`UuS?!x3kvLlHZOuT3@Qjy_7jBs30 z&+Z`}9-lOm2Bm1qn=zNT{ku}qPyoMC@DGE#CWm5lZZzgPt&BC8SSIWO9>t$5c34mN@e9_uKo9iZ}{{ml%?-Z0DFB^{-T6CYw&^GRsdnawPzXte_wsOZjJ;lHl?2CYuC}(=ISNRo_#>j8}_^AZjy)Zl;e(49Y50SwfuLDgkmSN4NMbea3>e z_F&ot&3iO`?3>=}LNYj!c)#y!2SX)GFPYBb#ve2S_eQDrkPa`S65=M9@gs1gP!qq5 zne%^@M8_&CD>3okfy%%|-WHAp5_F_Uu8M^(%y0iyCe5?BfqG6ltwYV!FkcH$B`*qk z(K$)YUN>B%dl7A1EdwOn<0S<0k$Gcl&oJ#V)0#$jyjc1=GIXbRZk{}L8-)7WbeF*L z67Bms9=-lSx`uVkj`$orNuM=YCk!QoEUy;m#vaQ17(@DRv8{o)PYWB7L_V}Ofz;xt%cKzTmqBSwQcR31K9hpP6N+4;XRs>aw8>gy3@xjuxN4wxakua4`=2 zWD33j=2MB^FXg}wX_S4R@dIVUS92Sf4g2Z}{8iG$^`C77-5(~Ho`QJ1Y$t>$V{5Nn zG{mtc41zcED0Y>KEdsJ4^7f?)EvZ@kx!T&(HO!i1IKVn5<*D2PuzkK{6Jpfb&25t%rr=Bf|2P1|wJ2%DxpmDnai+qjXxoQiqlhdMoI+jI69ytGM;` z(B_gALVa%9W(i-jOlR`NIm0^POKul3&honx2S)N@9g;`~V(Dg)3xNxX1@j8d)rF&3 zP6F8NY^k^#*x%8F6|(OZ`^wNzU|{*xT%42K8uCBfR+PStK|>@SMScGt?xgfnG==j& znu!Nb+AK6GBj7*j*J#V$J&oJ(1dh-(qCXN|c%}`O=#q1I5R!s7(2mo_LHd*gkHPThUlt+(wIOlO= z_?jaY8lJy0>{$xs8j}@` zH4tTZAr>?Y3X$k8DzYGoc>TC#JkX`dY*Nb^N0e+fYHW7725OvtwyB^8;Wl!QCo&my z+-U4$BEaP@g#w6bMWqN1SvYW2$YT5h9m)*#k zs?}czD3V7Wi6?e3AHw@O$ASoVX5Mi(0v|FU_F{yH@eSA{h{$#ydCT_D!5A>gD@Kd? zMt)#3mV?3y#REK*7<6ttF+{S_1fTYnF(9O72CzZp$tNR|4S3Y6fYfO3u@a~;sUXADic&Lf$9 z-zhV6|DazY(;xZYG))2)yRI9i4YTYQNbZ}1F1W5BRchA)Wt3hR+0lGt;Da+`J#sH# z0bmEZ9oeHzYZvZ1?{~x0NNC~zsU7NeyllQ);y*nMSL04L^Owg27oCX*3$;l+QdpHR9|i)QjeuM#%OL;H#7!g zj?mEYU-AE&4g|I^zG3SjWoB{}L#2628{hpRS3k&NN=iwK7843847s!iHaWlooC$1f z=7|?jP`B1kj%s}uz@tIlj^^{Za_Ds9Ut^Yd#z{RGsX09}V48Z?*7T~ZVETW^I;X}; zfNkBb*tXTNZQHhOn=7{2vE8xlq+{E*I_&WF+5737`&Pf8=B%3Y8v|sg9{3nh|1JkL zKupi{Cs1njUZ2{Vw)40-*8=$`%pv?WG2?*IpQNPhl!stU4V~Nh`OWi@^@zzZB=q;w zrfkne-ES8TL%Iy)XEXRKC*sM6pZVqYKkcJQC&%gx?w2-4UYtjZx$Z){eZv&%PV_|l z?(2f-Uo5Rl=o2*}Q0>(k-hk-1s4+;Su(CKYHPw{|qZ(QN?JQ;_{%4!&x1PVHAc$k-z|7{1bw4i&8yIDjszm=L28Lq*O;F*9-BK ztDb2#?AP6N#DoBvGZ1S3?+l-bo_!%Z*PmBeh!)O9h*cKn&PcSed;dt&Jq)yG>p3)k zC^C*cLs*!oxv{6^_u2RdP%!f04*mMs%Exj3)9v-Gu{N~UL~_ZWFT!Q7E40iq+iJ(~ z;kg~tN;z-wJTk#DpbPH1XH2Gtd&OI%(U)((&X`-7kJ#Qu$Wc@N=!ay@sUAQ7-hL)8sYTJ;f^HMo?eydLO zFvt?3j3jbZ1L&qgGBg_l4L=E0-10n3(chZ>aDF}5*V&uJ!TIj&!`t;5B@mlczsec2 z{+sdy$J211Ll~G6=0g6|r(qr^cf4IwCRs z?ZvAr_esQ1H~Y<#|LG6=p8xeV{j$p)pLm~}Fh5+^Lqx>?X$1nvbETppF2cqxnXESC zjRylk6u4kI-M&9S4RASs3y3xkMl$17TC3mDQI-bY8I-*E0pSZFd{EK6Dp)H-W|_@b zpy3!7f!;n~>dS9szz22Sp+#gKQKDcpsW{>{DX1daqws9l*7R5u8MJA#T}#*Rlk&^# zbBrqKvE`Ek0ci5#-Z_1kb5Yps%avsGmBMQNMFe@nRg)iXf!_k+FXIKK%uuEG&}K20 za8&L2$g!Zx$=-5fG6Gt>2fKnrt9xbzYk{I_KpMiMGD?1h0%?xihQSbdIu5NlQGi6k z9UX_tl}l^0O%(YIQ^C%Ts%lbnQ8-7JDCn`0mKc`>z!qZ6V1s z{!4-?Nla-sd+%LJ|IAr6T|G=xy`s`xh|G(GJo#-hl3+l#Pv=VX>b~-b7gu?Jb(jVP z2wVbDhGc#;$NavT?=Q17@+r5^IkkZ-@MUb4VmA%?vjcXn#?=Lk$8?#UfLD@ON`ZM6 zaz(ZaR_#4p;9W5I7|g29@haa{o`Kf@Rf|9{D{dZ{voX?ij;^RgI-M%F5ZZ^6OBXqz z&N5*gE9695lZWlsIUdrXq#&q3h{OB>TFj|D2^3mx!|UP>Box4r9$fw~y#KOm0G2LE zmmn0<&c-a{kb0-h>-pJv6Nn)ts)1Z{#MGXw5jT2ELp*7NvYW^>k@z6=X3o(mAow3) zrePTqhhWi2Vil|jN%%~(X-@22Au6fSx30vL%N=g5_)`cAkhEFD+!e~1;%@+e0hOJ= zNF?6Z;KSm>$iudZl|SnrejH$p1;Y1hk_K_eFt~$|CZy<)xkBWJPN1w9@-$0R5R_;| zMehjlGgfOx$l)?>uZv2r$WT{92M4ddC!~imS2S8D{j1YoA)t?pfeYN%z;ua+S4)MI z?jpil5;cQEJdR?FWAnW+&5t!;bj!fqEE4FIQ$)&CoRk+~;Ahg$M1g4?Q5a5@f@gjX zuo)ScdDyH$*z9EfF_O^&qi-r#WYhZ5eUh28HPom-=*pAK6X@k)Y!s2dt!TuQpu|Zw zV3Qpv><2<3$#Mbx*u=vQJqBecoFs5rN{YTXY8bXbhoCRhk-1u1T6$g+Yg@wFzY_Y0sMxYV zKWc|yEDG^S!5$kR)FT~$queE=cYzvGf8jcO6F06c`2}$bEr?8-9r$G}I$*i(^u+P) zF>BEMLsAg+P;B}x@!}5YoOA~hFc<+uyj_{cX0TlBkFkkzlN!t*0|cO@ad*FyvFy2w zF`8F{*%wu*{4T^9Q`LvQVF?}jAFPS1PI@xcz#K~)hKbV}{6bQID(2b%}Ogw`E3)a$6!2EPfFS9S>I=i)vfcw-L!ol72&p49ksjd}-I3^PIKhH9wnvb~DWa^S8 z-vUqb$(PBw);N005ujRfGt%J=g@WWD3!@?G{q!@IKSYOs=hvW_!L8XmJXO>KNAXED zp)(RLG3f7JQkF1hFe*9CoH1o&i?J$YTGb*dnU`eCaqfGIB3Kp0;J(1^wZwT-|Eke4 zsejq?Y|iwDw+6JM0p!k^(mr){WWv0y9C4I9Eh?4l7J2Aev8`!`SkFSnLrV4I0*fI) zwSDM@3DyNrG*eHBkm;DxKEL{~r+;t$lK+znsVJ02;Q866w#ZF zNnavPO}Kde{9?MAl$@#=psOoOMgJrBx#BExBV5BNLPoPxy=jH*6?{(g#DoZ@`jC>3 zv_>3qo@iT@hyhJTE?hl)gygJTM*9Y^7Iv_&q^u9D#vo&mW*;3aFL*71tU=F#b&|gR zhq$#lKJ_ug*dkrs@bwsK{u2bAIO(|KY7r|{v+TSr^UQ7L>t1k&Qsg;G<_@`6h0~R3 z1rM318$T__U3OMa=4HK0Q^D(X#-gIY;UTx?{*>?nHu@{8=Us{Vn9B6GVQtp0L0Tpq zzeE|J`x?EnLP#rVV)dQ^M847w7(0L=v5fh<-7StxZk5qh9T-c7uu0M?~nuq$CTdOxG!$~#M>#5bZ8u7JEFkL#&7+dpk8Alv0C&=W^Qj; zD7$WMgw*jiO56sC7HC2_?bC&H<~69$6^TB}Uws~83=x&W=QoFW$CBu2hj&(>Ez^Qjlh;ZbqEe}1bMt-End-AXsE%-cX6 zBXyuDBuhrf2<@E#{ST*JI3!U70mLu0fi>U zRw3{2OrMR#MFgKZUsUs4D@RRk48jJ|ojr>p?;E$MX^P(IhQ_@Zz2e`{VFe75@?Of9 zf;?|OqTosady3bZoAJesKY;u6l;26cf9z_%Z267@r8VLcSC6O_=M)o86>Zak+NzMP zB1nmNvbpZ>WilmV5v`2XJ^$AKv0|COZ{vVTU*D5p*teG{Gb|^%=W3L!gu(#Io@VrE zH|bv^@-lf*(kRG&q5oA3jq<4$uxxQdKoC!Uyevi*PkeP7G{Vx8kzW}TWXXYP#XKbH zQB$Y2M-zHgWKVAhyVG59rTFNerp5CU;nmj5Y@eqYFsP4N-`!E1_qgkx>LnhWt|{!! zk{+0Zs<>AF#%_aE**vPEQdb53;~So;2LjE?XX{@yGIev8IM8=)(aP}s28$41gGAn> zIQX^dH5LGE{rk8c>l7pjtZYZE?B8U;914Kt!y(L<4yT=9 z-F|c`R~3blWfrS)zl@W3A7|>qi;Z0`SBls7>8PQn+bvIOsMu)(S_V69)O0O&ERl9O zu7ugU`sR6Y3F5u~vTHU~h!mCyu{%7SjKu^=n7qSQi18RF1Bv z1j4JypzY$3m69JRMaYFx8#e5>_gsap)zf|-TP$JquM3@<7G@j3er`K@G#)bdQG&-h z@C$7V(~EmccT|-t+8MU2v2bDw+BgwGW#ut*#v+trW8JX}+pNo!uyA7J${-hvc+t>m zUULDS5s(9<9iw-(Tgeb%xJ4zT{BOG+JJ*e!zsPOjL=d~N^H7ZA{-k>O*+FZGk)zQL zy8d<=C%wHMj{SwefOR*v&5{~Vak%QvMn|^l{Hy`)nR6nF5)#j+7nB{)=ebzxjSZSF zHspBN<+=;DH38S_sRFN_M-sNzIHOM-P3^xJVk`-?N~HfDht<(W|9i}cH%CkU&$5}sK$+zoEC6sy3INdk z51W`6=;&f*?qY6cXl8Bd_CIuD9ec-3F4V6)Lt!>5J4STM^X=BPz3%pH`)D|iHtG!n zXDBiztEg7*bTNAB^(Xr0zTK(B)QYxd?Y%!FNx%1d*?s z|LBY!yNw>C;tfp@FlN@e45`iRpV-2V%sHrFIfw8nH375>{UU zRbsR-2lWEpFODZ~zg)aEE*7V8Lh|D@aF`Z@Lw@08TGCFW$%z@TIIL9#@S^3LDyLq> zS2(n2@E9ejX?y7S6BN(f(Due-XpPpqY3EE)Qpcmb4=>8JpLVI3J#x`Vfb??l@;3Ft ze`fdBWtL{{1*&ncQl2^_McL6egGk~43!USs^>|6%T%Sb|S$PWw@?k_3=nlh-eUX#X zq6wsiJIKDE70#8gbO?lO=ZFvhhwC;N1F|$O@5t5NNA=vj#{B^G--zI$+L0jXFwl+Q z!BTLv2M~gTO_X2C4vaUGZvGji5G<^{J+= z-ikyRqHho6qa=$ey0h)v?G=zxP`x%Wg5d{;s`F zmzJ!ebJAyoRb4P(?>Z6MA!%}v3rhzW&$#MeLotL)11#Z{Dc4bf-}W<;uzFPTt1;}= zB#shx`e|oHWOrfMYZ_LhcnBSXtN>^b(I_b!0b7)Z38iMKZGJo|z^W}!+a~pjZmBpR z-K>JzhR<}j=~6-$HAU9w>s}3-r++c(RWA~|2i%fH)#&U}VlL8Nc;a+Cl;6>7#wLLM z=PMCbxlUyxp=ZIpsJ0Ev3NnZTJe?`r$rl~b+T5%+nlpF5y)LI#N4IzX$SXGU`+LpA z$k1H4S03ioi{K2;AqOu|Zc`X-H2vP|U=WTEUt1{p_jjIA5aUCj06c$MD61+?!(!~G zeZy;Br5QC5X8CC8=~allq!YG_vsruS2;en!!zyxS+L>}6+8!f59la7+*UN?KX!6|Wx90QQqA+}DHoJsL0|3UEQ|UGN5#lPthj5foPT39&z0eux;6n(Sf;0m2B?Nkp zQs3=!CQn~Sl(im?(C!S=mAsoY^-eHmLs+QmV_?gTrBr>Zr*mV`t!X=$r-_HTQ_2+V zz|SA5;2-xYWiY+}Gm!Hx(@)pf9!-oI@FBq?36Ymhu?OkOO+oJtaI8^WaZXLzB9%dU zRRIh}X<>&*!?pvnXgnOfN~XH)*~;Zi;~)Wvm$2;wr0+jtW>;?LPp9D2l>17^USQ(9or)?Y zF!OYV&Bd$CrPM~aR)x&^BF@}p(oDC__hdks;_B}R2~A*-1oP5_j}!(kvnkdt8nLL3 zzhZ-oIV$AO26pO14xJ~KsZof^2rMk)GhJ>Im8t^McDysjW#+3QRPh@{G2s#En<}K; z3n9J{HCsbHwt)ow8RUvNF7eJ=lnSC?BlYnTTC!v}#Wb)ukQG7&krNNQ&`;FNH4$)S z*y(E_nm|d=&cf>}G24G7kzjjWW#xUA5KAaQyD5*1xqxZ_1ThX<70UDeKGK_d(qjs5 z?+@^Iz)XqhJA!V`5?(En{b*y^S;gni>+7QmY zV!CDE(R;A<5Ah!yj-y4Lc&fAULanxQ49h$^d;_;|PJo@yv8P>YKNTd{KBRFGpCzyl z6tCN3)8>rANZrRo62x@Q99vcR4btB@yQNCzS*|c4Z@Ky$qaCtEb#f_2e03!NVjSg2 zT8kns;hI``{mXuZk(@vRRk_c>4&ZMry>Xr-hY%4c>U{c=X_TtiTc08btGHXQE5kK| znANL-kzF>XO$@nwTBv!}+A-JM#|#WoehF-Y17$p1b)$wK2ve#eN56>&twUo%T)`y; zp9BM%o@!g@-H!L!d=dri!s?VdRdZtD8I&Fm*5S}ZmA{*(@*#T=k{W_#iwt{_WF~sr zIm=bTlL%_y4z??K2QMVGJ|KVpE^Kw&sGyNN8hR-++F46M)6T#jT1bb!X9H3klDj1K z@{Va?&#kEUUIQ8+Wh5T26XBzC`FjPU!eiT`K5r3ZcN7VZG z8WWN=Jgd)TNEfuN`nUj&Elo2T3Q^lUGJsYTu znCyX`^u(Zkq(ePJluU7LkC0hlvh0YmwjhAUUkpO%GGwdV7V2X|Y6D?Wm!c<_LRGFW z7QBB&tM2XjFefz&NkjakPYCg&OqKd+v;_fUgQy%+A>( zpG!Y+u=2*2;>??jaL(yAbHaAT_AUOT7r4}Kz%9eaD_7!qvsox@C%lrQc&R&mN=A|` zXlj4Zz=slmUe9*22?bVMd?~pO!XMyb-s?i75d@T(srqVO8ifd~B!QF7+UmmpKmQ&F`xs;Mw3y9NUzQSBlreWyGhFo`oire42f8)A_fBvu$ zi^sSwT;J7aYSmoX9cM8>ciX+j*(+xlGvT9srv0b(o`NL9vjs}Q{u}`%s@Ztn;SEHk zW3qQXf%LIx&iLX73tyQYscP-D2Z zo&56b_{D836-+k3unUL0)yOvh+gwE{@d-pxi2nbSA3rS6!U+D;RcF+Mpeg*Pl~&Qj z?@$E&r}_A|%*67aRyu<&6pf8uN8RXmN&63u#@w>*$IVM!kw7~_;^+U-cKGFJG6nF5 z*G#p)vIk8Z9VYzCxW$E{DFZnjt?1(`-t=sl(!fL=($up`Q6GQCGT6A!}jj6&NB=3Jg7+f8iwwo%Bq+ zg5X{!BaLgb%nD0^;ZFCr@P=+KF$TQ$T3-inJX+G76OObmzu?i* zU`crDO4}Bt4eId*djjRtR>b?+xyW)Zaz&_PeNi3u?FD~M9zEE7o&TL&w0YyppC!~t zh`DXD4Q9J$5nBbPrnH1?Z-lB5D;R)pZU|1tosikIiv@o?0tqWq860aq^^w!#8t%XbhZsSN`y8HjFpU&J)Y z4h8(*U2^Gp3PW#EEu*8^HQ5P5;Pg--IA&T<4AT}`cmo@c;yz5c@Q~UhPB(GQ2J~ta z-S95ShT;wJhGWVWQKnpZlMvG`*K4CzF3FcL%NB}zHC^ix7~T|itT*w9Rhve~jA?k% zW|84XAbv=l5luq%I%7kP!kT&Eq0qhyPAD}z+$`$A*!KSE8ir@M*Z;Q*Q^M3 zOVpt3NHPlx#ybCV`jBwDyRiNj113S#+{x^>HmX{Yz#cj;*Qr9I5;U=2y>^uycSZ3Q zj8iK*P{WL{+{ndx-z-&xW>^oi!AU~pj^O0fV9#?+!B(@mSrTD`z@7T9;*E*cp$Q`{ zDKkWxXQP(fPbd&yrRtG1L7_u0|Ds(pS z3Hww-ielcLHck=AdV4uS2Tz38ZDfM7+{JHA;7=ZxxsRF;jhsE1j;zVKOKgs!7y!Yo zI`iekUoA$4*T`UzYEj&1kx!^q*P$@#AH#BwO-Q z?r1Wxc$nl+tP0V2UF&upeVV4xZ1iFj%GSV50%4Fb+>wTHvgVP!Us{$OwaaGC#A_`Q zz@%aW^~kuj;f2xjd9}0i+rR_37Ly#Io6H{DVo5e}{&E(G1iq1V%#?Qa2(RoJgF2(^1+FJSbA!GHd zr#Lh1JT6g~4|yDWB)^`&^SjobH@A@C#xL&?2F($->kzGBYGw`t_jbz+2F_b| zP;23+XgE~?!_44wESc<&c=~Cj9Wl225wIq>On=F8$wx0Yvo@Ir$5n){|HbTqwyf$v z9I!$xtIAO~OmR3XHcf)ZPhi1$IT#>~x5?M+?s&P|V^~vgv)2nq)1YtFJLbRsQ>g#X zoZVqo!|jV5{K}7_ZfxC);JM!^3ryLT$~TZr=(YaK;>12aOWmPMyCrYxX4os>MIfaU z!IRa%(5^$Qh!uY7l&NSHzvoVk+S+k#vM}t2-{6iR2D?p!(rysGPr}E734MpFEp>|P z97Y_0Iv{kZsXbO5-x5YClE9_@U}?+iFBnUC?Uf5}N)!@c---77$Usks9hm8Qi}x&% zxnud8&i&sSPvZAj0U|2NO6G7V0H?UX46AV_2NU*;S1dlIzO(zV`Ga*l#UTe za?^OnvqtPd8j%2`9y}9`Px9U%od}PhTxJ-z2>evHla_n3iy_xavKP~(H=#dm@?Y9p z;Vy}?0Xa>px|B==-R&T%JisCwOQYqWcltPHKwS)9Y_Au4xJ}GP97>Ae#Rhc%r4dc= zTs)h@Zk#}==ses?Kt#hBAyuM0aCpmbIPS`dZfOe^jwi#}$I8qJ&&IiJ#a)Rr0YH72TZrYWTg}k+N@|t^zi3Rt|OiF4SsZ zMAukX1z%&6pHIp2E)M&;zrCGeM9`80x6Y*b^!99&MCI}1HTXw z0BA!704Or%+tBbcybIA0fVrBoj(D8Ny_cHsS0NhVjULG>)ZniL6fU-G4RKlyNdLG- z9@J3?EqaN1)E9NP@I>#4X@D9;ohba7hwOwV+M3ox^XiS2EK8h7`_g8JRyLWHbjz=A zVmiDu;J!zFk?46I4BqkWGSL;&7^AUcT7ZiQYfTyO*O84;i2i#t zUwEje(GL`xL2W=E2&Uq<&s0;T-GNC?RBU@TZ6F0Bce6ea=<(0D;XGNg9|NIvoGR_0 zkFShjH|Mz?Bm3}?D63pMV55Qin4h6R2pB2kux1ojqiPRgZ=2G&X5kGdsX-julS|0K zx0sD8%5Zpcd#1FPlCKgWzFBIh@>Tbdx4&TusQM;B2SHT@p5hrnrb9um6PAumRQ5Ye zUx@0KJYWHcr|qbjci-cLTJUPQ?YJpmLJ5ixW+o$}O!4@=D9}MPue8rnCUM0H8H%Z6}Y4C#!J1E1~ z5qph)Z({bN2;(n_Cvl;JT2O@h2IpVg`q|1u!oAK2Bq9pP3z!m^awwlAI$i&`S-jf! z7I0A6`Nmei%&`>SL=bj||1@hKng79|24EKVL5bJrvVduEE98do59oL0HGnlZ>5gK8 z;HqRWzB@^)p}l$?Azi03?fDj~Egms>^!EiMNa@z%wx1RoEl{^ZuXh5*Jhxn~|NaIa zgn5qyM%S7sqjtL_Y?4cAnQqf-Ai2L6MNAZ2cVVPfnL-zuT)^^XVTlDAjOkR7o50FW z+F0XNpM|NOiHZ&r6Ub3%r$D%9CjP^rE3!h4BWiE0_nc`iZc@C^+u2@0{P2eqsIh?% zs1qnxz+$$fw2F;ZlK(Xfsz7WN&%M^j$UIFCWaD>~mnHr*v*H5p#5gnQ9xO{;Xh%a* zGz0DN{1$PdckCjniILhJ@G8;VkZoYt$m*%jHhVpFT3RS#4L}QPu5kLUGu~sYagH&% zuE`m41`iKCP%k|Bv&VN? z30k>y_2{s`EDzdYt{?CqmjtPBF17|T%|#XCmn6X7{Y~$i11 ztsYHmLd_k69Oe(-Dd;&7YX7D0eV}s-9KD2wnEXo0VZt!6VU)E)+gghX-bl(KE71Q# zkP$?O>o*3UaoJo>F%+VmPd=o-ZphcDFigZlz}uuY|Jo+y`zN?rTELxdf9c0QHxI`m zWw7H};f=yuaxs>)f+!;D&|7v;fOJ_LiyR~gox%{{9_rS2?>(WsSsmvNQ9I|P!^nKl#o8$i8d0vhh`G~}2itWn*`|#ejkL=78g(x04 z(r{;mYQu{RQ3)3EQL;)93h+6wa0xP;Pf+FG-r8iOs19DlKPo33lVz-!HdMFAwJIpl zUbu`$8++vN?FIVe^t`AliypfHrFjuE(Tx93gFex2Z2 zX;rg(dkSWcm3;B|Puvg!`y86w4gz1C=YndnqS?2YQle};ud!?8H^*12nL0^g!e|@e zQC=Bj5)Aop8Db=y=%=~~u8Q-W`*?RaElHv6?|vX1-sa8!?5+tNHW{4+9&gAKNG)1R zF6X)*mR&-1MxG~MM1+p|lm}%z(gcBx>baw1uyNZvCp(TB2^uM}AS;ahJ(CD=n74u!#ubj| z(EWu-nX<~Y^a1z3%iANJFVn}r8QncdMnNeWQO0y3I&|Ao78)eTe}{29*=Pa~|EYeD z-1zxxU;qH+KN!T1|5iWyB6K)ljfTAAAqR5LyC!^ch2>Yo+1mH%*N=I2NLD$vF)FYs@U6zwBNhu_=QSlOFf|ImKn!E?6P!2< zn=Uqq>~S*{WrRV@mhy%4s?41a{#nZY{Os)PyU&KgKg)xKB&&%ap*3qM!8%f%DF^j?`rQ=nVV6uq7mHS5?Jm$~FU`kuw;7y{we-igCWKOZaKO6Vs>+xh^5@v83 z_A$dY5DHtYt~p6};J_L1&pI(ng}9G^8Gi)#n0*;zv4_8rgDXtI%LPbMb-2-^-?eRT zDi;ddR%@*1;?7!+=p?D4CiR0f@HInnpIAb0%s1gR7#U~#QtY*Xo@_wQ>dq&Wk1CAM zwkdenoBMpKE-wp@hls(rAB_3Y_?ZOdt}52uq$4Ip>C+STWEHX`bJ%iKWr}*Cdj-*7=cKJz1$(>htg@Cs`x~jv3`4)!Q%ds@aqaZ z>5wH_Z+OXJ0jg6#pSkesF^u@P@OM`rxmezZy+8l6nOLq^T9>KpP^CLAdgkpCC1P&* zWTz!Od+Qv|IOUBb>yIu%LeYf0@H^FDtF@CHcX#7+T|&TCddQy63e^uS%p8}TAF_`^ zg_}Dwy&O=*nRn_HG|Nz)y_4FCCB_kSOVJ$L9(Xqrw0`-(s_3Vw&I3Bx{n6quM&rUJ zrqD)2b!q=gtUCqu6VY&GUq-#(R6W#9P5kY}{0zpJ^~Z2ue{WnT-p z9y#*Is_I$BX^#iq;ntx=wHBK>^})x6y@$)Sx+E(be6UzI1o!{x^pp$5!w_+NSV*ue zz$g6u^T~OD`2)Gfau5l%ekFYZxw3;O<8<5OOa1|TRx^N%r=FEHI$@%PmxG+WeLHp{ z14|0|g28j6XYKF3&AL{r@mYfPJ?T)w(eSqUTj=WJLq*SXwO_-q>g4MjgkK$K12yb? zt=B3IOy^s*d|v7TEEZa#1~TaZ0Twd>v9+@zyseQ7T9C}sj-VA>8r+8d{ zBS+^Ho-bMCljIk1+hIb2CzY^Z|E04F(Sn%14tM`5?TwpkP8Qj%yIWn(?<@%}TUc$w z_^+=bsP=q4{u!R|%=IltMgO4k6yX0!)xb9WRJup`cVF-V03`nz?PpY!qA{Z!%i$`l zsimK5sq#KcO_k)bWn7e^r2!H8x=`J{Z~1&QG2KD*coJ&C6+2z)#M}eZLLbgp`u4T6 zx`XdQ3B$7Lzzq9Nb&cDr7P^Xy$>!j)t*^y&mHWaIir^2h*-^(xV!ekA?y{Py7_!-E z^6aBge+Z-&p?V`cX!W4kG1}zqwVQx3elJE=)$Tz^9;?Y~G_hIY3t)$o%+IIc-_g`u z6m>%({`v|@`gUQn5G2aLEJv#Y8piEoC|W4q11o>7YZhjMIT{WIQ;n6I_YTly1pU7_2v3wjR;MIrDL!MGQn2`*!&YOtwtZV)*7_ zh%7h=eD)yU2glz^|8N388u7}*{8~H)8mpR}UrgQeC!MON{~BjiR+nS|_p%*#R zW``p<2D zDA!?j`eBH`K+ZMLugYFotp|zFvA3iHE^?eP#=acnv94~ zaV?yzZtnq`NdX;!L_AY}g=~vyvj|{M5ll7$izV#x+OanDjOLwI+xVWM-?=^R4|@ww z-%DW=I!b}%3AM&$gr8&wVcke-@hYEGG-8x3Vx$~EN*gU&=Z8iO+=4uSV@YUTD=}BM zJzdW&yo)eQ6}Q&Dd)(trmu=M4J8D?pun}1eogmU8>!op6&pUm2L)Zg6TS^$nN|_~- z{BAl%bd4bhg#yjQrBDWY1<{udJ@-ev7?lbRJv#JPEyz1XR zhM1yJh1V9srJU3TN?j;n+V*#MEu7loIn&-d0g?6H3umw9F)Rr446F)N#3UtU1S@Dt z$$Bfr&nwUVrJ+?OKw=Lx$1Z>G`vxGr1=T2n)GH2KfTh0^XuX#_qAKv?&eci5?JW+R zyhrvZyi{%*=IWD_W1CzfxHyCpn{fHIXmvLQq#saQP-E`_L29CmEK?SlKYXJ5X6{y3 zf7Lte+5I^clpy;quc0FUD}SZ~(vCmSg-m8g{n8aNtR$jhgSZf{>y+@%OPIH6`_uY2 zUB(}K_;9@#coo*6KSck;zh%_0l0ZFy4 zqVZ&bzQ+#(!*XO(e66EYJ!)|oowPsf73}b|^%1{&(D%CG3A~`A+~Ry$*1%fO2ixWS zVB(sUNgB+56aippDFE^LUIFTiDK!Co%Q{p#28$$d8}{mdw@)XJwqtxOyXo*sT=1y*N?DW1Quz7mMfGfLz~qsd+Vh|)761)SSx9O+Vif|Z7d<%ra*C1oz3zKth|9DJl2u6dsJs`i+z&6-IZ{si;+y2Rk{}4B1 z3t>%6sY`0F>LJJ-_U(U#YL9nKP zi3cphW_-fJsrjWDj0Su1h7OlpHtdqzfKi@;R)F}(A`XNoXMw3@GZYnpGd96NaX!-W zruboy8WkZ=8IFGGt~zLv^o!wl)E=7?M?D2C#vA+@mVCND1;n*UPso;|oB`#Ia@y|= zIbk)E=8^Ms8=M;j)xN31>}iC{Y@JZ)>(UJUF(PCO+u~Sn&Q6gLLW!>je75 zsXbyhh~!#)nq&`H!tII1Rr*hu?Ew#hDMn}>To-sQr|s4`|^N{ zC$Hz%T_eYvM78&a2NxeE0&n80w2*GsjE`67fA%dE`*51-C@g)dPVQ~K4*u8#G(;vv z{atqd_+aPy&Cpi-068d^`6Uy^G&E35%~R>Ndlk1j9IH+{8e0|MT_HR?wk zKTuf_qoA^T>miPFiUo(M8PFJhibv8-;lq> zGAA3g_oT`9fT0;P9mdZMJRW8o#9A|y<@e8`A%bj=~m1CSasX@hvE9b zny{ZrjZV;$ymjE6FgAA*C45Y&q-@M&GDZ6q--KlfJ|SvZXRG6lP>j%r10MpmKS2K+ z-bQ|7-LwkHyq5e5)d*&@4XPgTN(jug1XGQL(NX-^=T*(*9H>t%Y@|PDl98?vW!w}C z50n)PH_$mviqSphBoqt);^`D9$q73T46Fu0p`9DkEqx-C_Qc0{9{ac%b6$wY36>wG`!HY3T6X{|2rJ@nLRh%0UIgoK zg-TwN_Ce%mKQ>p%{T1^G0(wR>z3{f<#vVOY)~LmM=pNb;N|Cf-!}AK1DB1Oh>zpp$ zBxf4(OLbSx83BLOMi#-s;Y-NTutppWd8A9G?hxU>%$j}47>T*v?#l~Ej;iLlw2>J+Dro|b7DVX)Doc&cj4Iz?s9Cafts{XA^E ztF~2cv^IIOL%7G_@H|Q-}$fv^PlQP_7ZtjdDI2aWTjd_Te+V;}z0G{aNOj zc>hVWf8{W76Pv-Bs~R^j>o7*s6S7Z}1YXMsy+0Oq0I1s)L0kvMj6|t7wr2l|nD!Z> zU*;qnx(#wSb1!Zg6__TURZ!u5&VZv2?XL{vbptJo)|^3uQZn*{2VD-T10hX1AsccDe}gv*Zn z!Q)0LRHTCn+ASLM8G%0e@3PjQ9DCWnRQy9+v>|_u-_l1_fcbaLw>w zNdZ~4D?_1ZJ-Q@!lE=^aQ|kylQ-B@-` z;|~w?0^u~^OQlTpq?}$0n;4wvK92cCuG`P>cvBb$bnu#z=; z%A_dK8j!is0Ibev%;^i~0#xWP?OzbWP;kyVBhR?Nz}N&>+`A44Xn%VMT8B21&=%Ib z^u#tbgqCmb>*q_fyEQA!ZrJ37w0H&8?5u6;nwaqmn^bG3ztNB6ZmimSZd;x>b>x(U zw*lFqKVX+_eBYkEq=Twv>wTnK{E!FLhUrs})52RdG)&->)Ua@vvgIykQCZKna3AY1 z!|4lw%YRcIqsX<$JN>qjzf34sZfU`>EOnW*Z`@65lFS%#>rVoYzr^sx@)D`=;5^ik z4K3wC$<%kXZt?uFZ!&T~Z43t>dP4lLmB+ZCVT`PI1baDoTB0Qg1mk_key#PBooC^a zV*VbB1mzsAxYX|zV5D8u=W~AlIZC+Ou*b~~?2XyF5I0~B_Sen`qhH*d$y05k-#2}9yKpFkW!uu9s;b6{BKjS;H*@lJ{HMg$;-|#etDgN&`3}6Y-gvL`}1Yzfd zg{NX_cm>p~Kgbik)9~DVzEqt%Tja$HM^_i_!RFhZM55g*L@{+?PzZzaTg(- zQMoodnI&O2-WA>QsKo|#N0RLQpKH72@|#snJHTjmG|R#ndM#E6u;gBnK08+)&Q%@h zg#P-srNvWs(YLi8(QrXENmeW^x9?m{o($pU^R34em6Y@rg@))QuEr_BY#fjNjAZB+ZBkl0RaFkPMk<7$1_x%(-G) z99=fUL%5@UupL49+0%Gzu1;|4`q7P_WsGvu_-jz_pW;&-yUyxQyq&$=j<3PmX}r!M zew#lp-p<(xIw|{UnqyZhqZTzlR)#a7!KwC(oo1b?PJ8*Zwh8-Jecs8{=nKb;Plc|| zMG_|O>c`EwmP|+KtX;C66uXznIPa^#IkSK^^H*MxSE5qf>B)KnE3pKX*uz9mExStc z8)BNX`FPN`#Be*)Cz6>Zs)L!P(j72&;xtN$=KshaU%r4tT5TX)m7I^DhrX zCz=^p_a7G**XpZ0{^^c}U+xrM2A9GqI%!q&1dE6dexD8j&VN-{3C0Q4?(R^dezt%^ z^P&mZn{4_#^UNC_Sg-T|57EzxF^Bz|1l8*r;6|LTLaDY7nPZIJ+wmeSkedH_hMlT$ zwywc=HO?GEFM1=esNnOHGE~}-h>tqDV}d};fweYstUj2Czi)1G<;$}@&P)7QNQP@Q z0xQqXVrX3j%hNn8j51wXK*ME&Z=hb4VU z&O)-0`X7{`?8zEupi=Ps++rUGWMKtxb^V?G1SafL`60jeUrjy7A7_TVE&f5GGz?zR z=v{V0%V3Y#@AO-+3 z7TeJ1fR^h2M$aORR=%#?6)N!bV^xjhxm5X+EiF)p1BG17&`bcT=ykgQ-@H6dcp;^o zn#l;&4!Yp8^YhH}jPfqYNj}{sDjkPOdxoOO@h6H&+0j$+bURs;^V9ghI!E4F>k$OA zs+j`l&)zL34WD{u|BtJ83=SmP!bM|qVtZmuG_h?@Y}-!9wrxyo+qP{x6Jv7c-1Fm} z_kQfERn@DytGd?iwR`UmcN~hYT+)X8snm>y)bxLn0e7iGN1|FAOFqkX3`Vu^EUo&- zec9d!450WgKk#R{7GC%cJyMpsp|Q4c;cR4rXXf5dr#LvQE@dMqb%IV0m{WqX_Vjs_ z#DwI_tf6Z`jP1FD-gC#eFIzbCJ0O>qzEi1(cg-#?_+!8m-3t+WFMO< zfvEHaOq?AZ{@FVE+v6vm`phv`QoH^^CLwr% z0&Lt5R!f)2+#OLbQ>>8wqeVUcY9pxMHk@)26rT7Lt1Xz6KY3R|&nN9dQ;^8I@#)5p zVOT0@%kPX*2R%3wx}lr6W#1VS3SyIVQnW_n;xl(bPIz?BMU)ua?%YvFS3pUDpriB$ zz8E-ozxkbT?gXOKy2+)C)p_at$xqWkvEzJ8Pe+E z{WV{EcUw2Y>ebfN=hWe`5kyGr$-r_Quq?;)1+5#m^;uR(pQ1wzXHw?L&(TR0)mhbP zYs*}hLw8FU@?_xn=j`d)k*lk{jgM=Dnebq&Y2J*?8uL?-P%{i~!#+*qdr_McG|nMfmQXK(lU@D(Ghd^AadR%fb5-ddapVFL4Bna##w@3D`hcIGd zJwm0Iv1e3|^kJAc60XV&-(YxDGx)iSa`UCD74zs|?lqyd@JVqtbv^ivf}ln_c3i}W z=&&QDVX_EnF$&)a(rE0zB=P&dQ1gh5O5Czm9o!31c4QlD2!+{3F)ACffTYBtJ(||t zozD^K$RjA-Mr;>3CjDMDlQwFx(o*hM*^rCNn;(+yX-CMV%KHoxynKhTq_HKAB&1Bg zW7n^Q(j35M@cQMmN&P-C$~Cj5_u`>4v&gCi^OVyW29;ZBRwQj+EOR65_B6BZ@tt8| z)Oqw^BGv`NYu;4Y zn=emBREg{=Lg2|Nc;(9=`$ym;{kS7L&|3A0a8f!) zua&>qu9ZKK%r62svS~Q0m=yGNiM@lf-BNExa{0H#6Du~5Q{9wT_1zW`zcR)ep9_^< z8RX8E>;=Ao*T*de0%xIjx5zcJVXQZlM8hv`zU-}CuP={Fx0i^D1_Id;t({z7fk*pY zrD&evEAGng*OOFPb5nG;`!`Tjze`nbs#JOyoyoaDaE zK&T?GCrF1*1d8{ijtn%4!h0Pg96&g194t&68*hIabx(e!S2zs2MYStWsEn#r2 z%trmQfx5{4Z=rne2ar?P3Gu>pr1u(^v6UPMZ*&tqkqH7L(^}~d7Y-Etsr69>x+DoE z0>3&Y_vykX<3hl{7tGEJtbX^1ehKnn$Rab1>LTh6!&84ow`SMFk>9>q@=p zwQ(H;Lc`;Q08y(fvfvw1SOR@3gYm*&`V%%vP6Bc1gAv4+d*%o_<0AM3pR$*^K6(W8 zo_gG&Ah1)xDx-^M9^aeh9zwff@f+M37>fH_5*XN}?cuc=<0b{Rrr0xPXzV1Npkq1`;FxHhSFZ+D%AL3&(9Wn3;Y_fPz)I3un)=9HspxU zQh3n&!@DqA5R9b(d#Q~GS)nqx{%7|xC63B?7QoInQwbe+;Ni|vh3^nv0`rNdkQh2; z6@Kc5{FuLPhBJ%*tzi#i*99`EVayx{xYEokD`gb$97T!?=|uK5?;;Bcu3@@TLMUAc zHWj^ym#eY0x3~L%w}kd5`&c&Md@U0!;qUBK>Riy#7dti67Y$c&D*f>evPz2V;nZXl z0-EBCtgLSv!L1c+3acvx6+23~t{7!=T{m-mpc{htJ9!@5x!@}_>gx;!9{b&(LEk@b z9zB+36ik+PGXGxLrFUhBr#^!$oHC`%Qp69iF4T*cqA}fMn)<}*hf19gk$?Efm(kh@ zr7~GCqQUA(B1oF92A2JaX6HGvdMt2M1rj3=49oU44R{n!WABeEpn9HzdUp#{NXuNa)*p zc<4)4$}Dr#{jFKhlNb>u)q>7-yInIIg8Z`-7hKkMzlz{!3FiVOuLMd55dJ}f2Y_gg z2bcB4tj?JAI167LS%Tr}+xK_F5S)sXOA-25lkEP;XvhY!AU1 z!e!2*47vIqLB+cI7rGFapf$Q5z{hzi7QMsHN8_cPz87A1+-G;wu=a0vbWZ5Cz-b|r zYk@Sjes0+^dPJx$9c2t*XaVnOlS{Zu(2XkN&iZqC3{^0u^y(Ia))PwnB2FFn*3{sb zgYk@b!hU``G-Y9+)Cm(KS{x-V*0gETuw<;dGIe+PdvQMo3YcL6HaVIskmr~tvjU@I zCy-3Trb1-k$~H1ND%gwQI`!g>BtWX#x}5k_k}hP~Xn4i+Z0+jyx|3UT&9F0toeY9n zWl^7=u+ruDW1=4Zl8pQjaWzVR8DTt5ysVbnv-+JyUY99C%kD-i1|c3qgXCtUc?>lNPGrQQdyCP%sQWg~55Zb3~7t~usY zeje2_z#iJ9^*cA0wj?dUkHCC4I`wlOWLR>)Qzd_cXuK?LO8GeekbyJs5_=->C}GOP z8N5B|s!D)(+>|~E#b5KV=nCDJx|3`XF>f`*&sf3}bA4<`KL*u>QbrtDVH9?SbkB!E zUgg%AR>7dR{FaW17R(#Lt8&nioDG@@=P2cjZjV7@3?h?YjT^a6aQ;hAILDGQ62k*D zzP!F{&(3F+6fe3QK(AZFfVF|Er#IPuydvcwb@j1)PjKgN!>4ro8g25b1GoDjXu-4uk#o5fF1;GhG;g$Ct?+Fy0P>Tn=p zHX>7u4eVH>&9QT_`81HyCI2`GPJl;J#?55RmYuYie8rfEt?>e(PIEUkS-}C;sxPu? zvWbas(v&9u2c%oWswhS+L8%5tgAPL0QV9o*f-D~!Y#7?Q!Yo~Xg^AG5sjZ9ZX;VQX zOZoiU`X>`vK=52^zLLdfuC8f20Tf*dWa<+<&s&dNl`lWLXvAD-j%$aeke4p>5(F9{ zC$DjsZnL)FdhfSJbyI%n4}lu;YidS898C}5JACZijD*zoLw)wNTXz9DG=-pXs`0Xt zbm&EulV5r>ibB6+?<0GkR#lyyA->a&-$si!WaG1$wEZF z6bJbutF2!d{DBPVT-ceLIzH{jFw0r@hK@$d?7G2bjJ$lju%lF~W4D+5?;~cz7F8&wMpyJsco zR`yahVbJf7GIqm4EC-aVOjf&usx=M-h{%a-0AUaGoHc5-E_L-vtQK@Lu@LeqzzDd-IVSOdn8LGGfw0c=U~)Jt5JH=NqMn6sa)B8-+TS%Ok_bq$;tRn9X2w+%C62v zm6j^UsxT|8GwHN1p{V@l=M6_snN%5;XC-U+9Sp0p1XF4$7+-yL&tE%k^!%Lpfn|&I z9o5HKHUkIuDod4)uwz)SLlB*offF@I4==lYF;!g2B|ub%U%wevgAsYLB1IR~ubKcU zG$T*{CVx^P?0Jn{=hVW5Fi=G16(ep_W(hvlAL>q%Osc(smdHbBy;BygeNdd^ovP6S z5O3*%eK~aOrWbW;3VE;5xMIQwXu8rPeNq@KCx#5d6=s|r@=FmIYwQ?mZhAJ*u|5Z) zm3P95FnoU(x-5Y%O*_|Gu)I+Lm@ zto{UF&uyF44IFVup>+=4YV+d9>Gt@<)QGBHUB%<0Os342u3P-9v<)*%=Ng@-UGX=a zWx;SVk2BamR<$vW+B@?dc^-9dDaYQUFND+za#i-~O3|q`t4>NJG)8U1%b5cGY;QNH z9+>#6+lJz_o;f@CnZBk4*txHh@ry*uCas`1&`|I?vE*^ft%bh7Zqj`3{XeeFTX_X54A?)>Cpr3hMobV$s^?-D{{e80|!hE}kNPYYoW zUcPg7bSW-}{rTYm?30i(8aN}Bdz@)wN!RU*l#BJnmRPa+66xsZZGRa<^0zM8!EC$o zqSEKa*@4(%b#c|SxUxs=FN(N6%zzZ1hj8gZRo-(wbqPYd(&T^9T>z)og|BGz;P|*J zX^Xi5KfhnwAzjAKDRH^zS-EU~GX8%-cFp5xwebJN(={%kiNYfNhi;{lf1W=K4FaN# zkviRiMg+JSSo}xFV(FJw>_#hw?{kelFY;Xxq1n2=B5`zw#6KM8B|928n{OoB8oHPMQVDq^8zZl3b_}uRm4t#-qi@}NS7FSt z5W7hp3-0@Yt8AS8DsrWHJ(f(1{&#tW^u6_6WYuIEbT-`wElaQotyhrnAod(lgUZp$ zTd~V9&Alo**IyZtY#0f}6A4`RlN$8xn1B*yl14PwE=DiKuD)vv3UI??wZiJjcqfaj9jNcyZ|1oEL}>`UFmoA3;93>LgGUvxJ_77ZF#ZlG+a zCfbvng9ssXOG^YoWTe^@T!v|^TRH6*bkiU1n;=@#X5T>`RcSgblbU3)2FrRTqM#)= z@^p)8=9TQilGTe9H4UUs${}2Zrd?$u-#jj)L4NaSu|nT*vL^&#E+%?-B3cWbl~q}R zk&Qs(OgXh|ECF8-v^{R3pqV~Y6kwGw9f|DK1F3H@T8FA-MW`~iy`r_&Yz#UwNedvF zU3l;Ar=z*?6M4@>#o#5Sf(A0aS2<3rd{MLdjk;${yx#%_^_ zk-uMeBi|*{Ta$2Kp!WF8N3U|e`*-dD*JZ`Vl#zg3qY_fjyq7% zeMeJuz}4NAfc~pqUKaJTp){#GJ%mghsS^$idw+A`iT!IhrUe-b%68Eg{z&MnFedjd z5bRaAFZ-_A`{=61Oy57{%qRE<*^A3heTuF|_SdEN6M^G*D+*>J5BtckYXsG!)Vbh) za&3~56kR|UdJA*_e3TA|F;Hu?{!J93Tktn`GW+~Y$?WBW=c-fOEy9pOw|+POu@jQn zvsO%-*G4umLh%EhP*iIEj(omr@TvQlrulOgw_apwB#|RNo%w2lTI&8xWDh<`F)6RK z`$*A>cJdjuoBBQuebH9yj%^Q5;0fs?S%agTlz$-F%CH?Y!D~O zZ2zj``I#t}kO-YTxsZ}p{))w%Gu_9dc6Dmi&@5c+`u=TkYC3So7v9X{Qe!7@%+}Kt z?;G}8c+6~ty@V)aO$ZcK$^?$yall65k^HE@?~r_!apbcsirj=%&<=bnnQwF>$o{72 zpOwCMbyjISu8Iro!hnz)Jx2LD(GMPIIvS~;x!L?gGtboZ)^!xd!VjK${Z7DrCF$$w zL#;s{Mgeu8--^cpZ0=`pw)#Gc8%6P+5HX2?Q^WEvS(ki&(i3}RtacrFwr?ft_W7jD^Wk*j%3$c|MO%+-M<8`dYVL(%$RAjzN2);2&Cn&6 zaS%<=n<&p~EcJ6(DJGSS|83-JnB_R<){HG$kMh0?bn=DJ)^;l)lN!i`S;3eIvu7OZ${ z^sX+Of4Hadr*C`F#pPjg$T(sc;rb*av>X*((c5P>zh#yvWlj&1POp(R+fc=EueZ!& z;lIPuPXafixN0GCKahTJN?P4BvSX4V+ZvX-EpB)(-Nj@vcJ@TWw+VV2%(WUq^1K|)h$9#4B@z0}h%sFvjvEk6SSlhOZ8inWC<}{Sq6AY6*Xrv6-X7i5q=(9|> zQrI3T7o)7(GCgn}-DjL>xsdO9#Uq+NXioJsx(z>|8%zGtvsVa4&vg9y8eyOb}QuJi|?Aew9M<{nKD>c3(A3t9l!f5V^eXb+J84VggE z&mi#qHAQ93K$?~P|FQXnAV5F}|9dZb=AR7AsT@$~lz?hS`XIU$NesU7Ff)0GJDdZ0 zW}WYQ7uM;zoRCoS&dp8WAYx4+Z!_rixtF`QyZhVy%k34cvz2}=IO}oC*`~f2vfDPc zK3-Qsc~&StC{i=av!Y7copD!7HS|S3Tj5$yzeDAleg-xYS-~dgc{6V8_mJJZb3K1- z)ZM52dZ6nnRuPg-Gk9LYM?8frUd*HHLk8dU6Hz}#v-%;ER-G@^&Q*Y)MtHaZO7<3aetB{S%2)ZQVk zSDqcq5bpH*^c#B&uJq!&Q?ImqYSS5PFlTo=D$sexWmtRaHU4&On<1ENo+mU=RUr91 z-@b4{{%dZJ=ZVT9gSvWP{QHnz3DTg@0rZN?b-X!zUZVE9*m`glt&M@&k`9={b z5CXaHSVn?ol^?GnP27iuYlLAWMlEOcY|3oaY&E$HuW1tQ78X}-ik;V=}n?4 ziz`l$kar;!k|PhBcufv250S^~L*=rQ`g=`rL?>LG&`T70GNr$8BuEu5U`Eo@Eg7-dCO1Vsc@1hds-|9OX^bRDQ$e-E8>m-z>qY97F0 zb2x0CBX?k}TOgze(~dV63;-1Ph&ns9~&ZpkGS|y}J4$;LV3vMX$@&*Yuq6L zGikezj`N1=KNZT5NCnIPi7{Yq9 z!(Y7Bq_A&X`8E?2%LJLyw$$Y`!80v4w)}rxCQ1_U$d8d8^PqTzJ0b@ukm0d( z1Ms4rHFFHpIAlY$iW6lnJ;)k5E^2VTM{@?G+B~}PBv6P6mt}N0latc1J@G(2vv&B_Q@!@-SmK6bnUSk)I7po zXgWY>xpv_csih{!TV_&i+PI?Q`d|W{@Q%zYEQ|h@w#`JdY#gNKPaqY7Kj@c@L@3~3ky50BSHnNK5g$1rnpQe=#}s3E z3>{0SaI{JO_I4AQYFxFfQaosdqkdPR%JH{NIs`RVT1#?<|M%-Ny8Cc9MRzDr?O+5Y zT)2!A7F=u60XI;WDNVE_sO5u}`(lVA?=|Z|c6^tc5R{^;MKO~b%wo)i`#E*H#(BP` z{1EI*Amy_N9auhP`o~@bZ6zjNQ(VJup}_cmHD>p=W{eP}_Wz?;gZyh}|ACMEM?3Pr z{mc&uoeKER1N-(YvI_r!OL}cUKydyi<9|LVN}|H@N+L~NBPj=?^WR%<%t-8nBSjhW zUTJdswYl?ZQ(PMQ@j^Ne|MU*lO*jnzRFT{ zu((koK6CFo<H$%jTpIdg|SJ8<^mu`~M}?z64KL4tt97rdeqcZXXral>Y(OAWUO<7?Llxfri* z6mKtmnaIMl-kO9ytLon;qJv0ed2X;>dNWrF<)S3`9dk^h%!(Kb_SQQwf=eXu`r#` z_(`1WZg|(Wj$|nAje!Q(Alt-&Yw+i#XHiYJ~;2sH)^#q9Fow&Hm` zcv&ijX)`IPj$?>NpJ(Ky_|x=unL^I#g*rxcc|r3R0rNu*f~ONCgg4#hw@ldOat9gw z0t#2A0JIx-k0Z_-Qlzu8WNA17nM~R!c24kOe>M&FHRqC$Wa*7M{_sk!<#D7y|7XOS zKwSUX?QmUYMopgFrE1{^=a>{N)|C*#-n?DyPA|plBQ4L;E$hj7mkmPwjas+aV%rMV z+c&I9pq8&NuK%CU$+XyCl(P|tL{_go_2gYtbm&&@sKFLR9!qX?l3tEc_S152Z?>sz z(($s;T(h1NC6+JyN1=avky=MG6sBeL_e+}gP%e?b><-o`5;xRAFye_xNt-Muyn=6P1h6iraQxeDxp zW|Zls+(WY+TGp2e^lln}++B;vTd$mfd4V%#-7lrrgE$G1x7AdsdeqKRp4S=ESr{|( z0RT!j-<-0KKIv?F7lEWv)Ko+HBJD1ZO(0_5t8Hn}IGa>dsgcJ0}$+;u&3SL1Ivz`YDz zyB3hQN(}hjmj*!bei0rhYx5JZosFmP`CE;MLDX5b+&r@~l|kdpCB0o=3824YssdN) z&tsd|(V7PvGTYyp><$-PiULY_O3WRRk+W8)Sjtb9d6V^fHw01Mu1$fw7S>%8pr%z? zA5H~FwYo?yn<%UoY|0jkx3uC)Ei_v{1!{1%sABU|t>2(?0iV~>| z26r@AF{#HeN3_uEZT@4=-^d!!*6B8mC(9IgSH3O0HP0Mi_j)C-L@FHDT;!V*7w=^5J?TWi%Gu=E@yLzPMF=>Mfx+(JJwQLO z)7M}1JC|DV8&W;*WavC%H!25R3@V3q8%@pR*=fihsc505;F}(pt zKzq4XXe;gLXyd4WIYXp8G(k2|2(QhHGdu}~H)!2~JrD}?MO^ey@;M_`3Li8{4w{Eh ztkvM~X8e4|Q6Gi+g(iaqFi$+)Ti2=o+ei)OcWW2_%3+K3v+B8gU#@v{kedd71Uj9m zy4{v~YzSKYm{=23>v_Tv5nLgsGx*dGXiMqe!yU>FRz>^x zChXyo+q`+~w^Mjxcln%UiP$o0n*27Zt^T(Bs0Fv8LSwHaYo>6UMgNqYMC z+{FrfOPf`^n90r#K<=asiX=DJHQWj=PN?kb9Q8l;;|cTN#`k!R>G2;Zr_b_*e>2%p zt2wv-r7rO6l$j1G_sP>UzUig$2j|gP3L~?)@K3Y`E1V(!^#GPzTSs7^r$I^?;>N=p z8L_^#?E7wnt!RE5_)-~!qySo3!f6a&s;2Xk%yO>apCWHW;29sPybyG2qo3mW!h}d6 zM|QOVhQ%u&tEe*tR(Kn$P0iXm;{)@$g6oAA2H50*FypL}gY{?6>heL2d?!p!)1L+7 zrJYSwl6H#>H8NVIn(L74BJHlk^+wHAb>^7M{GgpH!o(48s-jd7kHeQQhaZ` zHFBVehim!G5Fs81Q}@EPE0QDHi|MX7pt`emJHrwh06pwTu(NHpEY2*K^43K@!`LjsEI@io;3<(z#_MgsLi(hB_fV`!9zi+JV71;Ub*&qZ7t%3=RQ(sCw zxS9MifM9BhN1&rBAZ&H238u9MNqoa_kJkp@O^$+8k#$Of6JFvpfYOTGnlOE;!8F}c zkrrE@b(m@Q_|P5<2jeyK(Ifc2d{@ud=!8Msk8XQ`~ zHW3flNf^|s~k-{xUv1V8%FeI z1=}#-C2_hOWeOOD3eB3cGmY-)M!+;Sk1$8@2FLbcC_t3sl8m-`j}yziF<;MYw&ouN z?=o^{3U;}28aax5Yu7>dS{D0|w3xd92&B+kb4*RkFi#2z8=Aie_($OvU24TwZC9s_ zVLwtfM!pvuZ*0>+tDyd&qkVZIb{ix^PmS)g)&$x9+-IDnwE9$HZc=KFRl2Ob38L~; z;0b@fQ({-&vk&|2S$F7lcsn}@GoG05eR2H}oT0AxpxV@ksjU&Su*b#^W@d~7FsC4? zUpfW}-z$#A22V-jQdMffSQkZnRQi*i>0;=+65`E|89;Tc^E`_kMzZ6k5=v>U6n7|3 zz;SWl=sdyHg-iX-^Y6L8ufQ-bF*$YM!sYYI$Cpe=&$u!xhd}h=Ul&QwokwjGID2RW zJIv3M9+!|k`;oJ-!1*W8|uWDl%>rs$wv<(Y*kUZQayp& zc0n?q$hN!*9A?{~lzT41evT%)mqYNn{jiCUS;~VBjvm%j_DQSZhIw5+c!zh7Y!lv6 zUkZ7s*m?~>ZuMC87?Nz?2oJ8;<&XrG-YDPDYh~q0Xh%5T%{IE3HT|{&l>h13<#79b zMStBn>~b2nbuS65*7^JAuMHFn4k>_aF%36JZ6NEYKJ?LF*wwBg%gr%9s+&}Ht!X8# z6h)26o&U`tVq(bu%}~e{sg@+p&uWCNVMu79<@&BR^byQOUc(#2&HUOG+Hhczkd|e4 zH8HB?aiD4z%gC$Ed1xX|auE_-JMai1v**u@ z2`Y3F)64HF`u7UiatJbGd#66YUT{?$be=cLc3i4qi-n__@t7%;9l<|20!jZl(n(+~ zX})+15i(yy8t!Im&rMUjr+5w6_P1pyrt@TRF?EyPX01S^Z!;j>&YlN$+aO8)b zkbJ;yAYNlPZmldb)!$P*%%hJM3?Fc*7Y{J&qlo3EzT{*r(5-S%_FBS*Z0uqGXWtywVtd zwx~Z-j)5y|Vhbt_(U0$RyFxHH+e?)b)bHi%?Ix_>eX;|mx{yKB@tKh5@J)`#ytpfP z6(}hR1T&A+yki($*b@|m??!F$^a%p_jA4)WmsdV65+?qY;mO$3bw6n9F>|60KQR+r z(iw#u>Fg$toGkQXZ?(>qHilm~r0I*$&8B$Iy%JYQ{11Sl^Z}oP>A^I?T2(SbGAFPs<0OE0ryr6ybjnE??xf0Foil zDdo?rA}z(-jS=)@TPh{;XqgO3*BP*crn~hq@_J#rYm|Mru`k&7&oFodUgHE6Ato>T zJE=2Ndo)cJ7l8?sg-I67cxbFVnWw+xL0_Z~9Odb-rHXT(gcp}1i>&Nx5~9*-;5_N$ z8f^egL%HXIMK?-B%fMe*0^lnLm>b22eL7C6#B~;v_jGQ=s6a&0U!&C;CB^wgfMkDk zW492&bHM+~$bNqqqTCT2%m^Qa?!<%U*p1ZeqBoD{o+ho39|sQ%`Js6RcoY^R@tFv% zBMI#RiXQmZ4$T*6H`0@ww*e50862@{^*{&)>}WkCG1i6<5!4@SWYwMJmnLv7yHJpx zi7feBo!hAWvDAocWNjp|{!=CT=kRl9He5r}<3+S#R*W8TBOQ-Z9nV7Zt1_=cvxl3A zv;Gv;;P*~(#sv#V$i^=H^)}K13G_NtLY)}drhy`(h31+br@`2g7iRbyvOQ;3aez|a z|1v8dE(QXxf}Qlv{R)S!?`4)gBrF%KdL4BY(AjJ2d+OLjGqS3ry?G_Uiiko}-POn6 zv|hzd?w?>da9S&*ttREL`#NNzaJ{*KYtdWT&WQK9`${ryX$3M{TdQ1bF(!uMNpiGeKL8Tr4OQLU z7;UO*$fA zBBA`y&`j*)H%IQ}{c+#M3qTa{HXN*Nr!9%C#S!^mG&}aZ7>UgUyk9mhTKdh{Twe!P zRZ5i;3X^j0BCdtzXANIrtGN=#>=VTUpMS}JgmZT;J>IHpAtG=!d#e(pnu@ATQ7r`0 zE+M&YNPIu!R@vA6&PeG>4i><_Z#N{fs3!b*1<#a90HZAP(05B12Asqh9)hVybt=S- z^AlRf*)~BNCa&SE_5Hm2gJn(Y4bG1{MDAeIz9 z4EiWZhz#xxdm>&=z8=4z+89(JPIB$|6_?D0UpnUMn=u+!$!@+Mo%=TgX*}Ou)?7tN zrdyhe;8a?Cf-|cc%sJ*}Kf3!hEm<KwUhamB=be5Z!rltRSc5hj#3pPCe0J{te)^lAb)WAI+OmsN z?4{B}@z81UJ@`Y`yqJ>;>xy{?wNGbgo%9bG?JN^Oih!Z^$8FCv7_?bn9+ZCQl8(eYUpO;*etLCGq?dcjr3Zw<5)yI3F1o|>XQQmXp3$_lo z%JOWbXDW$)%g+sN2s)ePf=4vR67il}cr=aw{fz$Rv>T>v9@%QAB#lgZQ?g5iMZtoB z) zXd9e~7%;I^%cRm8BF)E3_GGpa1KxtzT`?GlXax)&IB0mFB|4916q_epUR%cD*mE=} zGK2OOO${uF!MywtE0KIIiK}BMLM?z6AT3a8J1ft_54bIeO(x*hpJQOZPk-m8d*iEbW}Z(&rnUoPN0qcF(|gH9pPdeHV*3$ME-DQ(g+fD?lF zSR=}nc9+gP^w{sJAH!nU#ojtMc9hQ%uWy zmvO+dwPyS+{gu)xT--&dwHAoC9qxxlp1jm;<_K=wuk6Q{xV}Sw?kuMR`uE~=SPxGc(ikmdH`UAbuIr9Ixork6Xx(ItJu%+443r@^8~03fG69c#FG_m zF5k>CrHLTQFPFeN@P^N+1-s+a#Daa+mAl#~lcKMQR2UaAmL46(>5|L3!{qk`(b&ylL>g5wpeokD2a0V)MHq z^$)8>nd^p05{^=#IHjoeO-zSh55|6Hfl&25b#r;Mch@f}~-!VKymi8Sn)sX}j+o(dg4QWcs!YBd%u&o6WaCA&5mX=lC&8(z<@!rLZp~1 z>q)#HD@udxwmG%x1zKf3eGY>Y2fg4Ugz%AfPh2+)!qhxFiKCfuYAhP}tQxRTH2J34 z9gcwqlF{P@j>^uE49#c)uiM(!mT6F71tvrf-AH?6IP3{sP?h$k#v!vCKjtx?b{E;Z zO}-yCfc|Cbl4@(}^@_i|X6Z_Napbbs$lV*z)G`|`s~{oCVHR1S=~f^6I`V<*OQfm6=q!3%!D`wKj%JS$oaPn-xP7^ zeH?%A+HipG*|!`8Fh7UutGT}ogw3qVv+;E3Z&?`}!%oSb>wt0nX|*>wRt%hv7?EdJ zo~m|t7Uhmw9~xIW<+Ov}&&}U~6oW)g74%4)vXNzfY6;3?wAv1YSt+meFdmuJl^wA- zvJNFhc_OnUYOG8ItUAuE!muYf`f?E@$ZWKnC}?k$ z6y7>v{e5VUz-^D~EvxjE__%+@^4d$4KmH{Adk+JA zVEi|n07BKX$rC8oEtx(nGzur5lE$Qo0Hq|89&7Y-z?n61aHIG{moqJgD`MwK^v-B@ z3#ZDL32v?xp+;3~bc|}B?gYkGR9INzaj0)I`zEx^4d>Ne0w|?lJ|{*naF#zh_{!kG{jGmHrthzx;V7+n|DYLR zp#7^as*GW7^>C7Uk%6wF8L~uw5hBb|EiH-Rpc5DrDBnoP3H6(m0^`b}Ub?!J_;4Kee;5wUFK2y)}46 zKyIdOLrH=?wft?+E*&vsY$k=W9PPt8_B}qaK-!P9`r*UpubV^w~l7ZFh!D8v70O z!RGu~j%$Qk5L>oc=Ssgl=v20Ud*FHm_)I|jEoFVEcCtkO!?fp3HTP=Cm4LCL;>jp= z-3DQ!Co8xLmjsRP-roSximj@4PUu*(>DC&S9u`-A`k#yHb}NACj=4NCV!3TgKBKMKtdvY|HwIX5A+O6FI`F>u3x~Dx_e=5?I7T%@7=GzXSrKlvGCGl zpMEp@E!|}U`|aJXW0w1BL*h3!u;Ttc+vR*fgVvV?@Aw1kQA~;J%RU+$=MGtln#2a^ zp`?vyz$JMmqr6!Z6kBL67viRZjw^AtyQ1!fmaub!s z5j+sE7_dozT}i@z^n<$tL@Q&CsB&lRf6D*j1mlJP0Tf36Pg~akPv!TQ}sz0~#lzn_oa{dLaw zdCqg5^Q?33ec!j@pzGzu^oOYrDklS8UA=Gj@v%G8Lf~NsvHHe0J59qmfAA+$Z0wEN z(EmtcHZE#${!vx0BO9MqLk?5^)+YMN-P57Be`^Fk9yiTAR>gM5xxJZl=;Gy*tRH$s zMudK9UVd9KXfPgsyN#ypaj-S+?8{LN14_xWaz|-52c>(mvp$=yJDXm9eYgKl@z%+z zo}r8=jva!>Y7^sM1|8bP;&Yw$*aer4&W9r!g(` zzo)MHI3&_?kzaM8^BLv2N{JVy=eHU~K$dbDdai^-^{`c_N+Y*Z9 zHMU*YstvDBsKzy1Wsa3EyUi2m+0<|~QFZ!3`k$$H`{o`{ducwqxfCM$`A$IMyQZ@o z8)%;Riea*?1{2K`__Mo1y?L)tnEeQ6G@dg`3T8dIh^RlS3iuwBD))#Fn`?Alp97~T z;OW?3xaE>?oWY1$-N0kR;!{zkS3U*~v(7by;Nq5pGCH2UpWMeWw-kGceXz~#g6XBo zqq4DVrFTl(F`*)eFshVPBXwMOSvcFFW?~)`?|4iPRtN()&$5waqf0Q{?b4 zc;1m?ALB5!vvhEb13z1PeBsGmA)e!l2yRn}a<|vj;0JPX!VR@IjtJdTXwDIuRn3yw z%r$wzshagyw!B1loOW5$#D;D>Yht8>vw=m!`#@VE_2ZN_9LXD;W2)b%$cHX@T@J=2 zwr*J}pnqX*b;nA)UGrK8^CMhkk6hATt?nlk_Ix@q(>b5txyTE16`FMgf98(Fq`Z8H zYdu}uT6%M*o3&QcWn?+iz3$p;l?sb(QQH!)zL6c3caKe$Jf_Iu$j|F8Y)~c6&7^Lg zHfZ6JILWIM?RRF3vi?Li?oIm}-Zu)RPU-Te-q`zGQZ#{=%TkEnx+3)Xu@?K)3k@zm z!t(y?Nm;(xl8cz|IbLd|)IvB+ezJcY@3X`;ImRWW>=*kKD7{P5$9V94zjqVc&-cM2 zuh^r1b=F(n7mJc9!5|}$(T~eXG_hkQat6xD zdWCcCGb~5;I0n70p=QHfbkWaz$&n*q-JtzuyJCEKDy@jX0(Z^Q{S*1P;$t6}riE@v zXXB3C+Hv#f$o-jvCycvaTzgwIY)m;bn8)+Wzvs(NuIAvMccq&$ODC0z9^07m&s{QQVMW4GkQeZRqRM}c8 zj_Ki3F|(fuY75@+zn3Nry%>JU);WHUe5ilC`pWP5ckcIXrYLkg<#y%uWY#l0{WVwg zv|hPs>M*WOTk3fHfs`93vOq!-5$WJ3jwr+hj z-~Ja37xuQ)N9_O5r#)`7*WOPsPkr2*la|Fx1-ns`4mVfsSvuvC==$6Gb=I5D8Xt>~ zPIajkSaip!yPAil2KcC79mqR^A%ipS5>bPw$^$VyBi|UJajcS*nVoNWYW>J@Pp&wH8 z?Jt#K5BEHcTZ*@tDc`T-7~1=U`bYTPy%R65TH`#-rBzLj3Rtu(<;A+)m#9!nd(2Ha zR`7^V=;vIQQtrd(jNhFZ-tQY(YYV<99=~f~&o-(bB#8;+MleVoMQ=1o7=ZQp&pZ~ zm-$=ES2Dou>kzJz_Spv?j*IJDV*FZW10OXoMtv>FFv6US(y8EBrkY8m|B&i*`O#Ln zs#x7SA2dXs-GG-nUoU#0#J550^XU>Pjl#e%)jzXw{YrB>-!vXtwP`=Y_EV={?Gsm+ z4V_tL(W$Ugq}q2#{8#Luq`swZtP^d&OZqgY4Zg(cp&Ix>%> z>d(v?8_OQDHPdhY%ultcK=5+KtTwm0_kxQ9b>Di0{$GjvOfhu)#EOCO9h6PCA@ zvv&GzB{3i!{nP8pAUsb##C?fFqyKTc{W_z}LzyR}WNa8F9=CWD^vp(AA7@h>*1c{K z%sS2XYb4j~UXIyGbzDrFq^7cD%|=?|?bI(>D)#n$p60WAIuhr1+i6M3`u9N=+ubh< zlW%mXPzk>}dC%)%x%s9JEm5WSTqAX~iRJBC6jx7%eLu=xwdq9x=ZoI3=0e8s+*5*8 ze086zS!eP$22kz3Qs%oeJ3jkew!`7sbbhV+>xZuJ^8V1{;(0gZ+ky+#{&P2MCNx0p z=bP*MyRJ{p3Exjp|4g6kmYaIXL72%lGv0YJJ=k3? zY4qOK`r-VB8eWy0YZv_&QEqfu)x4zLakk=W^ptz0?k~3!u@YXL+$JahC7Y zFx3IwKvCW1-qbG5aeKkgedi+2KG0}aPNccH?~6KX^JSlg2j5?&|G6lTi>n>oTiyHY zy4uEsu{}W#d();g2dB!l&RpvYv_ITd5|CA@$YS2sNb!76Soh_qGl}o^>}B5Nv6=r? z^px@+s)hc0XD=CMPMTRBb|_!xzw>m4zqC=5dPlbTh0O6F=FLBtB0@XYwb^DAF?(Pi zYi`)YnArBD`1z+O{o-u;YrF3>is0%JUYCidY&kBTP~%^>^GhJ3W~_!|g@^Rim!-QO z98_P6#Ldp`t#PSy6VMB}m`WoNrg!&iWIaEFrANzQ#sCS5xWd%;?;maT92e{JPvv}N zm?_woEM+kE%lgU`%d~h&Mw#ELs|jNl;o^=zTO)f(fD`b%mIhoGn=Ij zCs0mNY>e12upHIAApibwR^pVAP0_ZL&Pm<7*!c7Nk8-wi zk)AG*Pb#>17E8QzUTrtdys}d|#3!~hE95Kn>$?_JiQepKCogV-hdkPi-@iI)Bt3B# zSCcytoo>hDl)-9a=!oS}nX~M)>9N1}`6|VeqahlfVqH&nj`(QzFt2-m-w7AfFSjFM zM9oFgN6gdSWHLEL!_^CWRc|P*VaC0nx7sSpQ@(u1!(01i<0>7LG99NlG{VCx4PE7v zxM-9UZ|?Chn)0Ve?EcVKGS{B(v$=KX@D7}J8tuGR=a{s$?^~LLlq{Esx{pmC?sDpt zZDLl>cp3G8`_}`(GN0rA}ZG#LRgmo*@(%LV- zW_mestYw$`%~_px)=y7$Pw{u!zo%}kV_$E};uYLz?Ye)O89#6gB2tLuLTtZ&n?U}{ zfV^O(!u*bl0 zW2vzkz8hsfuM3YDI$sx&A|&GbXNDzUsb}v&TI7TAhLGA_G`vP^f=ZO7Njv%PDrOpm zdk-maX%03<)FsYj4gP5mnD6T9mFjO(==u5KYa=eGf6&ddIIc^zc}(_Qh#&l5_(IZg z)@>E9%s2*V_Z1>D4xFYMKW+Eigr5d)*UO&FbXfPjM<;X4Ks3h2C72;kU&Hp+y*-se zrzdR1npD;?R&D)g@KvqNrrT~#5;OGUNvy8|?!=vG!w!L*!0D%jdf&wlmPr}ZnGQ=^Za*?g}KDUqzSDba*4Vv=XyCtuH6u` zBj!V1xy^gqTPb*oAb!{Wjh%@lOe*Rdo3l3QEh_%(U5MlUP_1b-(;)n4Zdcy%T;s>L z6a=LNPCquZnl77C+@QixJ@@_L;~i~AY!w$7SoC54Kkav4;Mf=Z#E%TkQikYH;bQ!A z&mQE>w9j36bv8Pxu4kI}XYU?aKWl8stATIQdOQHe77yzQ^=w7;hu+PFmxiifj~Zyx5cwFpeG;2dS%spy+#{kmImbGOsOJ%7H{g>^5) z|In=F$A1~X-Ca+6R#a?jieqv%RZ9Bt$1UbM{JQ(TAgs`flA-2JG@+^77&#b?}l z0SeoM^_)s`e^OshExcA+T_t+?lWJv<*vXl@UWSXTA_H(6M`VG$Rh>sdt|P17_*kTundsxMeJNiS-f5;>|?#{Yb!t;@%FI@chvN%`S`JQBd zqV)D%3{zghjmqMj4<@ zFYL-VXBtDgjU)$d?pKN8EL&gMc8B5G{xcR_0-muojYq1M%xD6YorV+qKKi-)%D?Qe z8ZzeO$c{ZRR`hY<@nXpM{rT@6!_*XGpT?7nPQ*XfdM=-QMqh^MSu^EK6dV1lQGRPq zlEOrnJ>>_{#U|_a4V3alCb}n-^?8(^M-(Gml4CsS;+G_(&*27RF4;=ee`;oa6!WUt z_D0@JYmZQrLR|M6bHy)nC?G4IIWuFs!a z_sURiomZ*&HIjUtrRy}!F|YL9w&l8AZ?2Y-Q;->(-j;Ufwae|6crlpR|#) z>jkNI27PM@vCwna7KLL<*C>yZ{m z-3i&7r#YW^1N;4V=* zcZ56hhFp1dg1XC9jIqYIIZ2h>c>l79jyAiluPM z?#1;|_uAt!Ij<|3V`|iUEe_w@cEmYnpKmj>*1$UVfp1@mdo(V5ap0cDsy#TEJ}`f? zqoaK6JykUwR&@ja?oR(%T)1=7t^;{XKaNnGVqLy|Np||gSkg}8ZgpJ>N0YwXgfzu( zCvT5r-qUTR&xn-c`&2g7Q2lf(i))Ox^QhO&9_NXLece?-Qd0)8++~#G`c}>78UnWT zHB*f%Q{SK(z_%BPJ+wX-D0Jm!#sSr@QKr9hIcuYyEY~0T<*l?s5@-J!hx4Z2o$d8F zqNOsW-;^>TY@z;>RvnGsCa-JU@>B1eFH}kOE#E(qv{Y{=U$I%0<*D4Q`Yva!1a+@8 ziI?INmUNjXe^=*wHkhS$YuaMBFuf7j+3-Vt|9I5R?WM50n zrj@)+Tf^4wc_7H?vPZX3=0`DH+Q{k18C{LuM?#CGzv8w}duz@G?D$lo@_7#XbVqR@ zJztyKsqsQKt#$CHk`ifgKsa-o&BB<3^$k77}KM>sL?0D1XD&6m3EcJEmH(!GC zep*Hz*tNm9EK54|t04E~h`KX+(K9bJ2kV>MmJ=?&`ExkG@mXxuEx3PQ@-D7rBBzAE znVOc{sr~TQ^Rx0i-`E;jr%iRTCO>@(+)cUgRd;#3taYOCQ|-HyDr)PUPnz~WR*edD zOTPYwLn)#2SisY3IZiv%+2c35UzL~%R-W6{(vv&IzO0>8m}OWX*P&VSb!sY7c z>~88|VWEQD3{{7#=8j6jzhk0HU*l@!K3Z&uPrR-suB4GWm~kLFGS47Hzv!aR@Xg|d zhU?0|9147jR0Z2+-mVA{&&VjQ7h4u!3i_g+ijASI`(2GFPq$V zk=7|J|4Mn2S!}1&=vFId(O%X+ayNaiMu*=W)I9pM$ZN6EYK|GYtvoHuWEc}qH-+$=x<7g7aWr96Mo+xUQreN&MCFO zJh5XYY>Z>}YYNT#0^^%Q6FxD#HVRZR8UYbO^KrOoeV-UOaGyL~LT_J-6f z?cJFjq3`RM^JnJr{FwX)T(`%Xmv^*p!@U}`kfVz2*}*Lvko8=$veUduFFsbYt<|y3 zWFd0XkJtkpY4YqdvviCau|EPsO5cF zHqL;db{z!|hE(y`PtiA8ejPE`t3Nhx`Axw2g~}F&qkCj;h`uj;I~QBKG~MIrYG})f zyMD&MOnGzZh;n|qsL$k&qge*}TetNw?g|lVIC1k4>#(Dr_*kn;>UM>cewrdVqXxMY?LnZAvYq5oI!bV^2k0lS6mOe~2vG(M-?-OW$qBH&kTUj$v zu<=u+uOX9j*_Q#$;IA>V^Z8+FZ(l52>Er&1>+`PB{Y^awIlL8|EJV+FmdrpcZxx zZsVbbulRot4di`f3|+n!>&Ty{E+^+6snFo}d{S7mB|WM-&9Y;wn1!r+(hk4vj(xw{ zC${2#ddvP{{O-kK-`4Xd%cMo_%p2LUk3O^7wLc?6lbw4T#T1=Q{6{C;^{umnt7FD5 zXrFiJ7Qro->qMl^vdk8a)uu<8pXgZ5(mtWe+lQOKw=8;ZfbQGD8|R0fZa6-DUw;H| z>Gq!Sf-pUGT7H*7r09}q`JY84&Z$a&P?CGP~6%k@xhf5QKjGcFwSI@ zQAPH!@qPjGGDF|@6Vg?2e+np~n;tL=H8eWS9zybJw78jB1`XmNnUwfId9$I zfregPrMKsA*Bum?HG8_n{Z5j-)w3Uov!e@45ln6zyYD!-_-@wo)eiI5;5)eaVpyGm zu7&aQTUHHBL2i@HXVPaZmUfIq;O!Hf=u)p;<8sI4ANa+_=2Xcyo9r%>-f1pXx9+kN zAB)ZHJsKB23j}s{_fO)M;LYC@lvpY(+%rdqnLns)B+)6gj~o8QiE!v(x7t}Ia~d64 zHW|^Sz+imgmU0&8TDgkwd*OfKW;{7ZM{g&0A4f-cRL#Hqyfws)aIK|%T<}(TCAha8 zy)$p+D#BMIg*sRXq0xPtjS8uadzs)4zgl=kG~WsWK8x@)$VVNlr0_X*aU%@Vm3?R6 zRpjM>;35O*Ga+)iSTSLPi+hbYUxb{r04Zw}iTA#*0E_TUTp6>x!ibC!cD*qD873oh z0oI`jxYZsTyH>J-O-Q{iR-C|3KR}qh5M+O}k$9`}Uw)1H$T~fc4IOnur-in>I0iGC zuvWGlOTKF#GQBts7?A?#wQXoRI1!}2g=F!oYwM|_@u z^r9nP0_}-{uT-r z#1SD4`u@}o`+jhdRCVpp#sJRcT?DiBcn>+`(iVek&Pr5Q>XHhP%^`HK6mMXi$qn>G6p8I*Aq72h%^bU41T`dz^GqC;@DA?g9c$O`Wg>~- zhdGu@7!|?c5#N?L(DfEj9JvM#XCspPvC<-9AcB7I!N&z4!eI!9N#5W0(G*D}Ujfdert4-)f&f|iU7m3?5Hv)d_{<)7ngt%Sb{B_mpiS-!>5 z0+9F+XrFumM!Jd2j~&3W6DHX3`i%DuSl-=`Y=p_ys%Dr7-O57AfHWT8gf%nVkP1=EFtWn!iP9^zJ5)C!B7C4T=>nLL}-d7Br;U&lI(r#*8!RV zY7|+K89s~f+qj9)0)0v*WZV*@Kv{2ClCh?TNd5q%AYUC3ULsz~3WCC@LaSlTMpxb> zkl+A7$tUQ#fe3XlhY3bmkya-ndj3-x#2W<4267Ebi4yVkR$$q-r!|b8>r}Pg6T@KI zj;*a7*rZ8PyHJuFAUfH41$sVdm@GR;MJ^GQDUs}eHDpCJbq{VYEGPkC7$6&ytI*wy z2raZGsZauw_}LTGm-HViG(1Rzezk^>ifWJR;&=TT&@LAUL7uvP*%6_Y*_0fJ(Lq!t zph6qhk%Wi9dIuO5xfH+bN%$Nv!W_U;qqQDVdJuyCcPCzQxgu;fPy(V}ZDe`pX)V0pv|e+qcD4o~);3sa0xxEX3NN(KwE+Kz#ISl5;UyA~ zOEy?Z5p+Z$N|P7{h@fKfYYVcF)07Y$D0#R1Tauw9S0A~V9)yKC!?bq!t8yuk=lzsI zWB~;w`SE@4x>(TqA}l7kdJNAa(QwK^aGbJ-!V*Fdi8I0T(UO1VD#A0CBCWRAO~Rkx z!Bg)Y*KOMch!MxN6`^A#!fJ;V6G0zbNzYin&IXcDS21iIRv5u&5&mr>C1PQR-AH&y z6%t_wnc>hUO5~g!@JA!PM9S`=&2J%t9it*VD`bVZ2#?)_^xI)Ki=dCc5{Y=g@Cs)1 z6UHEy)o+#xd2K+=gQ(eqaiFqDZR(qS1v9@A3KqS>jv&i1O5~_LR+uQtX?rkpY*zYck=M9YcD zy1+>2q*dyVvregi8-%ZwRyL7@)tp_&Nan#PUF(?J5j7aG9~4HOOKciRbe;;dOvs!! z6f-En;6Vv>b+GnF5X#BJVaF2!fdnGuy0TO|T|ro@SA=$6#LpEgNSs6(+RoZeYHxCd z1dj5yTiBsj1a`Cz;*=!W%CYqkuv`e&;T0d*c^G&s4w2fK&1vb7FULtj*6z-cKMJ$b zgls^bcVj+~2&xZbc?pB=rM~v;A(RbKpaJsiC^5bcNjpT#h0q;Y@iL(!FzCiFgmxa} zz>yW7@kZOvP7~S%|D$B#9go|jU|z*AFLH54W5x93xAF!WGMvHA%Y;i8u;- z7?gc<*`G7pfqf6K7bTn4RMZNbTtwrGaR;AIdrWM;>Atdrt!OjfJ7V*aJ641sck?&PT*~!e z89EpY)cdPf5gtE6gdXs~3KO7zYAPf>z%x=If0Da+Jg^&x zq6v9Ia|k32Z;&`Kkd6~M>H(PpRp3UJH=5s}q~McTyU)&GCgQJnVg(4$I|`3nn*r(| zz1BsWc!|(?PplAeL_seYv0aSVY~qFGCpP<_&DW%f&F8(a8wiZc-?Ci^fJN*Bx7xg_ z3N(Vh*h+*BoQDGfG*%Gs?lVIyqoBN#E^DikxNStdp7)CSoxEYhOIm0%FH&`b?w`dy z^~dCVJX9GyP-T!0dtx7oC#ILqG&codaI!jZGV(}fVvM4=5j7tu=}=t;#ptU00kbDy zG31MSeLqpI`bTtFq`+q-j$QWw;ar`FeSO#AZ2PD0ETo8SA^564-cNy4!sVSWLs8F#N4tMR;m2Q!t{6>(9`uJT1v+*}gqz4PK+_?pkr#ZgSbY&%TJ%zSMw;2R^+bp&9s1Ytvij`a&GVldC1tsUdk zA_*%LxUxVy1F`&+a`dQ}oQM}R6Ik4>N<2cf4weKec=Fv->Mj!YULZ*~CCx`!%OU3~ z+{koho}vN{IG*iVJ7{4DJ;L^hUI-}# zEcGa?9daLKbSjC&=<6{ohX~q!m!>GqUh7FIS?OO3-cA-!iqF_ToVDSt#L}HF$$j=0M zrGi0TZkR4X(RR>IP_*}kz4H6P_RVwFuItuj61F&ar7W&RdDKpdi~ z!!N-&Tfw)1)#_D*Z<-`v6$nEOJFBQ#h)H%(%BDFlKZLEHx+Fbh{E zL_QQNCFgR)?ceO0@BzGwRcmT|xx%H~y8Xu!S1f)Xhc-QPPD*tE-{Ey9S<1ttcv z3Ir`s6|M>Nqh56i!l*DAqsT-igyI)7H&Q>(MDi>`MavcjT39|s>eLQfsdNva?Jk9+ z_7XN`=Kl=#SjU5_9#kL(`}U1wgHhEJ=y;GZ;78b;^@N=cWCs_hfUN_$3sClv#@HSX zD?^aUI2^_{9VWDMA^33EEfCuCp`CJA3Ned>sMrSoAU02;&0Bqm%_0#HwFzjA2xyj! zL7N4UkO(*tK%0-Aes6(?<-G{YOCBOQ@I+{91Vl6xDrS*?wFIC!piJ<{)vE~K5le&$ z{$i#l+xeno1|~i)1z`=)!)@VJB6KlpkE3L=1mJXWoGj88WhJJlp{3?Gqi&O9!izfs|fF$_781TG?W?yzIoBWH|^X% zeZ34Udfpfn33az18-Yh?^@jjme-VEbi2E#pB^g+JsR1c>VJi35=;sSy7d*vWvnOoTZS`&!UGSIAqW zK01W{IF^$T%`v)mxsc;AuzgyyIXuS1f}F>(2>w&Yc^wBnLrlmkphohKgGHb*JQAPf zcLvBI^{x44Re=qKN)S-5?4Fcj;n3AwcJ1NY90A3N$i!pW2r}uo{?HH=!C->2*UGd< zkOeV212RR#gJq$EBT4ZPGS6!e+BuM#cv3Qpj%naS&#Iu-!3e|O%2kAK&|*QRZ?lN} z#{zvq3vay5z+lR#sn(QyT)UB7C$Q4Q0ew%vfMT62NLvD=bxQM~yS9WQ3i6EQA919Ybh?OCb3wE$3 zfGc3oA0?1is2>+tkf$rK;WCzeE@0roV4|>6t5*?TWswDG@@3sf_(E6&J;bz=@uk&- z10U6twJdv=SP*xAR$;OPi=Io?SgGip1omwZz91f~Uf{*NtjM=~R&HeRH0ydYI@B8Q z!C5UlKt};|7O?PTqm&V+CHmiA;t-DFSvg z*%VO{p|&4#DX`NB_g-rtl$mmejw3XHyrh!^yU^wzRWT!rfZm^b>4p~kj z*=Cb@!|hy%q%{ym$>%|9L?YO8nzSR_*~PPQKgbWeiZ#p!ZIH0jSQ$1{1k>>E<6;ov zo4~+C5Z?r-PCmY5=z;Hm}*Xq{qT6+Wu2f z`5i?{l1YZFr_mJq9mENNIYX(odKKYieOVFDF;+o@HH9?pVgBXfIuJ|(#wFK{jUS?x zf|VhR`{iLG9XE`d1A7Z{)PYbW5m1CBwWX%^ruKznqq7uimh^HoE24jtjUSm#ftZ1= zCBk?H{BLrC&@O?P!mksEG3F539zDg1IHf|2nRaI*p8gU$ucMuTKZ%`+&Q1Yq(g&)e z+<;d>Vqn;_piOc&4xb}&{Tj$dUPhyI9Olo#Mh3Nafu`-?k6c4x)QE68Bn_6dm2fGQ1{{8onr+h{aiSV|y7xmS2F9L( zf`xq5zR(ak_{OloH_vILmAk2MI4%t4I0n@SIerrx5kHv1Mqa6+A*oj)`>Wz*|J(28-&rxwV|R$gj!_6MiLbO@yZ1KkLVJc3p1e{LKVYVoOx;prtlKH zfqVrG_Yt9=GfBt!+995wbHNo#b=R7TyCD(U*38C$?1EpL5JxmU3nOYBBKE!LV`D;6 z(O;sV()iErb?^qQq2J$;3;w{Bh<|&QR9c1gTxto2WmpC&$q!~++=)=ZEK+SJ$-MkV zb~F4+E`IG~csvoaEZAwIQ%3MvAXjV}k@$8NN$mnL{NgE~f;(PoS4cX82rXb?XGECL zUm&4VDA^wRHUgGO7)**hMf|=&#G4{3I|5$>M!a23Y#!Lo&V*E~u!$>?k-=@kV4er9 zot}Fw5&s>5^BHu+PL&J7L7=ov|M6AP5jJFqih~nTJ4f1uGQRgeu^xi?LD*T48*s-M z2^)2oorRdRQRb0CymANNeEO{N+Dy9f7lD8W=|2Zq48;~)kQmAbJtv-8o5k+XvZI0! zu(XI`_KNZ8XF~`(D@*9)MCwaH1BBm?q1@trH8RV9`R#z3h)|pv!|Vm(W3Fi~W<)FPEaBm=Gt6DR<-95v@GzHUg|< zLHn!IvygO5AE*tq;?q%4m!j; ze}yOt?UZO*;b_6ZhAe7xfWx3a8bZmd4kkreK?*;&7m8Ifabw7+WD7_(92;nm90&xl zau^JJ5x9C4;kR`C9R@U5up&cc0m$(CBcYQM87{yI6Gql)C~=#H3TJ(T^g$DJw#85fc5$LaY=4YHlTP&jhe{U^&U57fH}hE6@e+mQhWJhm`jCUGtf0)nN_yz)stOC&~Kio`&zPLaN z)>=-fT@*0gFh~L9np_Y^p~MvXQ$?Wg9k{tTxH);0Ro{Z51QFkhr2NEi>zwH~a0OH= zb{!k`5ecUY(N_@EKrVBhC8BkS zB=e&U-fZhZUMo2CC9kPWorw&~FOd@X-&c^X9Xs2T2%U$qi6t0Y5iCxAARi=$Tr zi-Q($P33e+G_W`vAkRiJjkDp1(3~RDm#d~Yd7-^vHN2p8a$Q=+6QRAc9E@b!WOM{K zWxvb!faDTPhg`3H2`HHyL5|*ai=D-goZfOmm?Ek%9XNBlCMe#pG|4f(o ZvK>l_30|SJ5HI3qS^2lAX+C=>T9>m;v)*N!t8!g7i#*HTU6uMmFqW+Ru!6>||FJG^%JyK>WLL%e5+PJ; zcyn_F|5-!3wuFC+jSM84P9ILE{|Q0L%^RfQFS_l(4=qlD35bR5i54u3#Sd!9nj7 zVKwJvTV3Mn!5g>D`kDt{H|rZ&;C9z;${T&Z9UtW7t;~<>e-u z6|fo0R^ZakEUTM}R;bufM}G(TkJXCbAz0M;Y};;{o9y((Y4-V}&tSQVdAWw^!y0Do zcC~8O8=Bm7dRcBJ^I}sBN7L!SO}V*h<~bqP!D0;%CX>Z>vt5^yNmkv^YsE#|EVr9- z!ru=L@?XcB|4ghI!yL%vb3`ez+~xHGk}oYu|1P_iVAP z0V|uOd$_v3+-|C+8xr9_vv!XG0T!@B`hC_cmw>8>B)&=2ZkE-BelKr|Y6%#%Zc7KI zT(4_C#quVYz^44Lxm_14w-}pp9gMN6TRb27wca4Qy6&5{`anO>M#y}07jWD7PZ-R> zX1#lIkikcu;-iD|!+)$?ZL*j2(~I@GS#z7C>~sg)TxXx>pTWFuppWXJT2`B#1p)tL zMaz&p{6E3;UVMOcX$heA@e0n5=^<*Bon)`ya(g$Ii5{XhhgB-qwe|~>?r)UC)BL7+ z52!B9x9cTr(HKtkYK(_~mg5M{%?hy=aU2K%oXd+Hp6jfI6Mu5id;l!sP8tu05Y$aH zdU|sWbZ-oZiutGb>1#O3Yd{1&h2w0s zZZ3+8H_Eht}dJ;yjWx zO`DtE1Nix5f~z~3^e$iGC0LnPO|1))Yj>;N=Z_h+@5Z=dwSom|?{3KS8*yhMXKykY z4w884n&xn0wLnz{qmOwB$wIZL;MI?NZ(aVdh5PxYtbaEj`Q}ZrzUJ-@;5E1hirEql z43Pa3BGT}4waA8_kF!Uk>|c=B>&zxqy=dSkeD>QBZ`8V|;Ml#{)_ACB1BZu>==>IW z3cP>u#?EBO^TQGKfCv2aub=60d3V(Spo=XWY`FXwFX$pK;BYrJoSJ#LAkGCIYY+79 zX}P|sT7Mj%(jdYUeDtc>JbkWgOz;#a$Gn7z1Ms%FDYMHZoXw@&o43_+2|R-9k*Ba} z;H4HwXuH@kYXY1DtW16&GgH`jgTqQs+H#{m74!L|fJ^5+aVHbJZ%ROFeeAYt(r(se zaihP_mSs_ISAIL=7bbwuo!>$jFp3Ev!MdP3Z+}AcB7TDiM+y$IN%Aw^X%j%V^=`6i zVCLPi;H*+`@TSD`-g!{c&7nWTTw10yI8Io3Vr29oF>ZjxwN8d45F%)c-uY$l&DAJ+j z4u98-*fl~<;LD)v-1TvA09cg~Z!r--!}l@qEaD6Ltkpndx<=fR9 z8^IHLU_k1lc{SVQNR+S3T?-AznLr$kw12}1utEIdWGFq*R~{902!Fax`DTX=x&~NC zF>J4Z$v3S+agffg&k@4eVA3MXHOM~A-k%RI;b(>>%SLV8s9HZN`d25vcP!MhI|}N$ zm9EWrVFc$xco&BP5c)?$r zKlX+%2oF}yCn^pM{kea`!v%S`b<)D11xE8jb+f&3j5CPOdQuMPRiszQsRJIve{<}| zLl>zK?yYr+UAJ^)+*CEe6hJ)JMSu2nF$2aq`**p1n(cCq_mAF~$ap;fIrl+^w|U*t zy$Iaod^>}O7rSUQS@y^6hNS517Km0+ZskzhFr*BM$# z_wj@Ewnp0d0967F$gN9wdE27M+$@~*ORorx0+w`EZD=+4t}L>;yal?M=znUA-Q0j& z%K~vQve|YGtog>ihU@zJt?bFm1@Ggmspr*(TFl^`mJVQ1@3IETy4&WMq{Hc~HZ4JN zP52rF`JDih_=!#1E8QmAlsW7KFwD&wRX59>C-@2rNdjO9ayS+X={a83!00xu5Z|}d zC9rCn+0_u+ax>tXZg9Ksu75!UCoKRnXl|@0C)we=Sl?Flp(iZCwPJ=dpe{cgf6~JL z2H7XsaF7r3zrp1`obV&Mp@yTgC!d{ zI0(3yEw#Ww5laf#M9k=!aE5;@+G^%iF)Ee7)GfpCkXVz9SQC6O1Ap03B$!wEep;(eyaNR5!vfk~EtwK14r^T;5{HzWR znYUmeX)Fm&6o2k8xqk|UcB5Pr+vR3512M4l!#`bDAjj-bUR#n7MB~Va+bbEZ24;%b z&38P5w>*J2(%IKV4W!Bq{CTkX*vyGp`1J+u<0)f+TS+IXFbIUaBmi_C@HIKr&zgDx zWRM`)jzCKJQv+e)eMy~}-u76o7U?Gs`E8*g!BfLFc z7(ga<$(St-WXrMss^TqfWU*lMa9`X*zjN*;#VvMMsQZ~9@2V1rA;?iBBM2%k0L5m4 zG7OA5D0MM5jX4T%yqL+IuvCk`l<>nAxd#177sBXgqiMsHii%IC@J29veOEu0f~N|_ zZd`V_f;Y-}S%1&ULp(&lrqmlnzd!$Z^8Dr7cL?l{FJC=<^H=xv?dxyeJbU53KKsjy zXaDy4n|JPq=P$l}@zv{7`K~=5o(iQp%t-KDz|n+TDLewAW?q+ z0x0(Db3XU>r~jx{rx6gICJJqlkOT-LX{?38aXXX6i1$1#+tmhF&hUyNPAY4~BMMbCX>HDHu7I221hlKUu+{w8S z?HM}S0$mZmN@uodK=ejh~kb+lX1;`j`mHSjSLU zS$_Zlv!sH08wckZ_q#2Y5z6JsZh_B6w$*eUa_KI1bSFxG=6{J~iuLLzJx>iCu^cVP)hviD@cramhlglO z9{BS;*aIOu3{Z@55{ZtX37z#>lfwAt!_luf?R#kj_i}HFu?Gf@G=?JwEu2#FtPK#` ziWRC6=vE!XW5FAeW!Dhe=bXP3OQECk|KM+&>m#0>l_<>2bmS7(+<}?ozh&0)XG=_s-D>1Gc!rlVaJ0sdQg2d zWYDkIz`%4Ap)jz{uw+o|*E5%q;Uby~LWc;ax@zfW0J+HaG`9Rw_v9EILw}A8eK1JV z*AOX*eKtZGhJXT1myD5-oxika=CyNCO_BoZ-^yL2zA`3N+t){e=dEGg9~#mH77#0s zVL-Z2n-?hdNurs6P_=?1FidRvSU`^iqSLKg%^j;vPR`C{v4!69&wi@PK%F?HC%OnA zh@o3r{D2G%mpuwCgbrU9vwu_6Y+G{fK%HcRL9BIz^Nec8hi^#=fB02(u`brThtHaI z`Lok`29qNP<=4<8Z%i}@*mO}yg9$*gL< zp*7)mbN8n7n0y;L9h{PCej}3@pjJ5mn(jB=3G>2P3{tLJ!c*GJ9DnXckm80a>X0f0 z^|_-Et*9|w`2n^R>)F*%TrEN)&QF8W=C)j)J{vsA2CLN!?^*g~0^5(SbM2Kr`58?h z3I!c?7@Q$LvGV&a6O3r75ZUzCV==kT0$!@+_4xOH|M%<}TL_jrh9)$>Mf)@GThr-Y zs|`9KqD)q?-J&kbd4J0e0#|_be9e4S)!Pqr9jIPAq|oGD0z?5t((2N>aXDAC1I9CF z6o||L=pE6c)u(>(4CBKbNGzN`6s?A;%(qzGQT%)K3Kjf8BiT1-1m|pv^d6|dZ_kmZ zSr$Oh53|E@b~rf<-x72=RGY#)|73prNqdN9h3?6$H;So%i+`hW@WW&Hq4P!(QNv~* zVU)lHhD}8i3bNO1%tDhCNSC;&yx19Q3&rq5P9aGDB3PTNb+f&^%EXCO6xNYiE+m9$ z%SYD$1Y58!bJPu0%W}BZwHz4p5|&IZ-zVB*s~hDNtT zI&^-;4+4jH2MnFX=)eq}XfQF#__pX({}4-o0zE#fO2ri|<6WW4K`qYYKbBpT@M9Ul z0j_epBB$K!QT~s4_7skD^j@(bKQFq3$c~6-J_3X8=EMh=x4a4;#4Eh;nh(2P&zY2* zWQh~nS${M8vY-yX-{lzQo|Yr=^i9P``*_slPiVaUy~9u1Tqrc}w0m`&1wVY2fCa;w z8)omH=r9BwdiQDjTMwmR*W#ULB5sPmHQsGO#!D9_%3lFi3x7ttWzBwbl0_?>UYqd6&$};vK1ymy zI>Q(4$I%<04LpAK=E2n^TBx)KXi+c&MXdlAvM=fP7)9}m>}KTfcKtnFZz8!PgY$0Sj{w5kAsjL9*WTaiYi zHHbB53DR0!$T-cT>xG!sItZ{pEfT=NOMj^Y%c|(C3WNNh-@$mr3Hk*EM3ri34+cRz zhy?@;weMLF8h?<@h}}lD*0vMIg78YaT>DRCn-cH@JuyCWk> z<3ipUl^u^kBj+SzhkZgCkFNYz21ACIc&t2b$Ga`IaCvh>XmY>dhC?BM-BF_F&VM~t z7sudzK`g$@NI&KErvWSH`LV;Ku|#XiD$9=j{)y8~UllF+^i!ah8M}=Cc~kO@Ae;}# z*ulw__&}@a6JUP`Ou;zHJ>9(Pyl(urkPq}!APJIPLK1-giVh?DK$DKCS&$@mu`KFq z`U~hD(H{cqZlkZtVoq`&ns(t3EPu&!`>NWo0{~v0IL_4yIwPUJgo~bFu#*Kt6JQd? zcr=~jFbGMjHH^g%WOh}c;T^6w3Te2hHb5ToU=7^-$y+Ni|CeoIYhXQ{>&hRpY`Cnh zG2TzLWDILGosQCdi33@px36R|T}K=}Dfr>zLrsqgtkYfZ9i{#jVb?D{lz%e{IdZe* zx3qI~=v`Lj+`pfpGc(|DvEH#EM9xaA$sTr2k1_VSyNmSiaxJv#a|j}S92wenaJb{K zH@smVv$1<=(p_qIp^^w2gpvYY5oHP9o_d~YD)6W5GkZ}+mIZNfV*->OD*GFL+(1zq ziry$R*ki%~O9%gJM~h(`AAdDk(Ig6e!#@#=M7>Hzpuh8okq|4y;hqu36gfeH_3e-Z zhn}7Lx(JAdCzij2XvAKp`?^)?5r%|+9QBYx?0q+lUET-sk_`{NQA0+)Ma2;*Qt=E8 zi5qRJn`&9C>7EFuHkqJ1keGGH#9dTnYxxxE`59n7P$scfk;4St4u5*}P;c^jHWYo} ziH>7r9ZkqqtW8g{v-9qg-2{VTe3*-SctKAR4`yPc5r|ft)2>AA6iRG<96DD2E*@#- zw=g)58-{PQFTh+l!Xf=v-4bXMIpW+eH|r2@3bgSKXUjHRWcT;!8l(RCBH+e$<XK}(kiw)s&I*UM}PUpN4!te_qCl&Vr_CKMpZvYlof#lDY!5$LG~llJ&6y56Bu@2 z{b*8h@@;Fyc6La$qB}d_;6lJU_Rs3JRnLc^ol93W9=hQqMR!=hTy_Z;D{u>rpvUsP z&Su}vcVR+@qkLSLID2x=YbAa4;U=P@@6r?f$QSV`t_st1jM&4j zr&EQE<^(jO-p~;%Ij%P7C zI+@)&F@K1OvPaax30{dti%L$o!jOr#D`OqonCl=zKfa#Bml102SzD!JBkvvOea9#xBTTRSjZT~cr+-1h!8p6;)Q)5f_#EBfOgl)EH_wx6 zRyQBJW~#XI9Aqm?XZx_2A}ZAwQvfz0ie*LlWJIxy^rPGs@KVfYp{W3GDWV#v9t+tP zQe(zG(tL*2)^jURuqw)S;`9W6jRGzq3$Q*a(6W*YEVriWTOEE+BiRx*NHn#=l8-Zr ziGM;`yR>jgZgT2dVt9;cGQ4+$%o-MH%yyMqTp-G&0X?;DR1VBVgE}nfg!~% zumC%T!c=%={~A>&X?&2C4jn*fRv|BLC}rSOuMZugK{O|&$<66LiCtMxiI10!F|)G~ z=7d4!&ai@?QCeGNV-?zz8A)cHG9`&Bgn!@l)}(!wB>ddRnndk-ElLa}uqyFSeU>Hs zSkGzo259fLFzKR!1dWHN;~4GENrgDx~%XK4S%Ir zQ&d2ak;fhLe)UGvojpXdD2r7UvMKV6AlNu1ZU9loczF3EqG_l z1whRMj@vLR!rYuNab|&{{2m-@WMqW)F-$2-!r= zrp7A)DI7DetSopx9ouzRi`&>_J|RPh(L$jVBJL8H)zmX`6y@arM1PdFJL5t_on4yR z+H;J2(1c}-36j0VVHR$ersH4^9b!_|@0)8SLS*N)k{?+EXGM+ExF8iQD*ueuq8pfO z2loZeSXRwNtxl)b0|Xa;ZB#`pc^UftO-N(|ydr`-W&sGT>v7zt%cf`c(+@q;P7}A! zA&KI5OAHh(f#&jM4Sy6sCI%E{;5E{?2Wyn5H4*_XNtHcl4-jYkwvdrsZMl_8z2^ri z`vPdvTsRGqb{}N{vRj7aPBN4jXd8QD@;Q_cF16m!6-^H)nP|!SIK7+NP$BOxA60;{ zApuh^sVa=4_JS3@DRvnqWysj_b+bba@E1l$k8hl0hwy;@K7WMGWww@6LwRA2Fc+>* zUWGCc3m$0acOAhi=`a`9!}T-K-sZN5yi8mLx*Rw#Y>WRo#t&d*CDQK)?1&~ zDY}o13KyA=?TWdE4cz@{fG4yOL;Kt4?8%ek$LA5KhTJRBEKf$wgmuL~4w&{MVs($d z4DY6kk~9~l-G8Rh3^!$DNJ9<1pvXx!0SZb{ohW;nPQHfg2MJNL2q{UUqYo)w7+PIz zzA&Hwix%4@acmq{if}0xXK{h%3YYsJkJpr<=1*+O<6H`5q0tHs zA!C6bXgi4*3=#-cyGdkGD1F3dn4Ra#i}O4VW00MJy37U1!HP6@K`c{8Zx;c_{fztT zZhx-bhN$&984_`lqUvGAbqa*sgdGUH&$3A2T-}XLyRSL%4eKJ(jxyJxN+3!Z^XAgj zV0>s#oUE4HOP~`WHDMv0A5DPljLA2A(krLC2=da^F7eAVa!3T!-EJDVaIt<5tc0kfQJv~9a#+Q{63(hs0>WwwR3eI~iIVtc zw-RtSWx?r9&?jWQGya=~`3PJyRJGEg;sjmjBb7~SW${oWfd0C`Tw%zPd*GDDDCLq+ zez9|DsNa8<9O`*us;0ms<@36v1B{qD1{7|*yPKv{?m2aQ)ftJ}Eq^7~gR+7f z=^XvUc;Mcp9|_dTvUl5B$CSCF91Nl%o?SIxo_NelGA)P;xL3MRbqE?dWsF8u25|mc zLVlkBfK;fV>Q0%tScRAH&`{lIT1O&V;H;pc3-LSSN$?S!DrdfNp4G*2byZxH8xoNL zTl-+=t)!<4rq2aF0xd|msDGSCN}mDJE0O9miQHc(!?vHEn48=Wts|l_T-W!f_AO5) zuZnqdD@8cM+?0VhgN!9>-J9*&dq~#?fNM+pfmfw}#y2Hdyv=ehIH2D#T$}#|&Bm(4z*9~EuaiAC@2vKL$3W+&qM@e|(C$s!#V zMBmnKDQaqro@aOykblk!Yfhn$G3xT{O=?#o2``#`OqXb`J^X4ootW|&Z?Kq0C!Di} zK}kPGGRK2J1`LDO)P29$L<9AXV4-=A{B%X^ncv5V$Kgz5!ym4iwyiFJp{&V)Z{$pT z<|3y8j$?6Q+-dw%WOb|Oeove}pSbjRwb*-?IW=QX?82lq@P7tOW7%=jC1>aDazXrN z6!Gu{5$1KdEZ-M(yqLw>+KFb%E%_Iy%QE>t6Z4{e48F%oj^CX=KQi(Yb&XvW)U__kQ>KZx8Sa?$x z$7FIY&FIdo*?&_}T9acTy5YdeFPFW(8IF}#KLqCxl8Qv}S9;J?6=M2B$MZo4wHIdW zdl)uW*s+g*@g7LJUL(}|PO`TTTRJD5YqYBiQReFG$@#eBH^LQw#(`--e(M5qqXkgz zX_y5y93J4{ z3}{>ve1994e;A$AAH*z|Yf*>cPXn$5@r2*}Ib>kSSD0q1XU?hUhocdu^;QSm=YN+IkJ}^A(@q?eb0(RZK~H^blJ|^s zi|COhe8;HUB1a~pcp|@F)}p2LW?^gACRt^aF4vi z`;%8X#?F))Lk&ylLv@$4s;1&`Ib3ljw8=6LuPKe@0~2r@VcC)gf)R+M*ygazFLPMB z!GGuZKMtnTk@ry8GnTOO0)GD5Y{~z{lmtT&-K_Z#sLMn2o0q|lI4q4lqL3u*nymu| zWaf&~L9en0K)fHsj65FVzv1$3sK98n!hs4%^FX?^fiMV}yqkwPBjGJV(Oo!-Za}t4 zp4dSTZor+K$e9cuqM~PL4uQFX;mIU)sDJJR{s;a8;v>uz062F;Bl+&k+51DNpAQ4I za3x8I39y|mgjKLqhL{@Tmk*(m5}RSyloDUm*_1nnvwAs1yDR=^wVUt;ckU9q&Z4Ud zo(mTUO|+KLeVd(}Sm6D)i60v-Rx(*8gO;!35P1RzRV<9%yX$Z0v2M0A1DIv*MSouJ zyPHcV5lo`c)3ghnJ zJPZ$wt2m4WOtd%+mp1c}ynRBInQB@cYa8?>dGO&Zu5FYzVSiLBzMt?4N{P8n#=&=- z3=x>A)45#O%5uDEj!}8nZbI{N5Px4Zwcw1o_8WAR#gu~Rv5OToDKIi@&1ZC7wP+Iq zCT~j{S+JJElN@JKjB#779KHoH3V;-_+oJcdL3~Ths*Pik1X2}6@tCVKj^I0%q3H%E=L`;d2*e;iegfOSoCuS0g7Hf|SU*ia+;z;`k<{WrU7SupCOU zY1TRBp@#*>Y$pSl!qx0%HK0VRI2R6@G3(yvJ!M2gW3KPIIrN4fBwQYX8=kxl12rXw zEefqhF2Zy?wY-8@kz27kQ-2URI`TMctc&2c5ZEP_WX-}*+p6n+VN(!rD08l<2auyA zUn5WXQ}#FVJ_kNpp-2AXYEJY0gxX5yN8s6*U@G~Du8kr+e8a|2bQM9AS2*VvL1 zK@LW{;yEWS7~yoJbG^exF1*VFZ;uO9>yW0Q<}^0v<9E z_@2zY6ZodbDoW>R*%__2O1c21K#MV~$>z;18Pp%jek3oB^uBqbCC@v7Q!#l8Y0ztq z>*z}fVQnB&kwV{Bg?}5dQJRO48aWdPsB8oETmlM(Lcb>bBKzjK; zBHA2>w5=;(^CLeAq4quQS9ZX0B(-BH$Oby|3kBdr_0ZV{yknF z9+s>gzS-8B>ZXiqD@vJJ=W&&3d2pgXnmCfT0CiD|27f6UJ>BpaN{&JEXPNXJimKkV zz&V164~^vX3^ZLXQKdYTpe)L%6G34hl$v1@_|hUAx;VUlB->*Iw6A~8Aewb`S=GgI zLJJXqN%*cw94dJ~dPrnIhxzNW2IYWFhElig{5>@&R^&-l48_f;X1nq~Cr+;L))_*KWCMtEjL;=9PPnz{4U?J|4Lp4fqN^t*>NJtapd{1{c%J*b&?ajja zi>J_&qqX*yb)T*Emrf`eYjo+Fp&2D+ccLz>@h_h1-MNmve5GK1>73IUnUf;*eHTEI zCI9;A@6Vw8U$h1?`d_;On1K1$u0VH&adP;-$3$##q`zvmnw0n#PnXg<#ObCJr`^XQ z{MrMqL;koUZs!Rze3Ip4s8H2Ks);r zgD;Lojw#wi(c#F+8zvOCA5SwC6cPT^AatBm6-a-#gQucpoHaG@4Fc@bK zXykhm%TF$L=)^bS9PSf$E{3M(jvD%f7f&s$c!GQ_n|qFx1t6{0lWpA=i*gbzM=+`Q zMJt<~nc;=${WLJwKbPe0==@pD;_UAG21A2LyD`2L?{O)gYEV!O+Rb~IKBpu@T-1yU zBpzd0EPwPp(zaVT^nibc4`K7jX{uS3Xq;WKTNk>>ZELL}i8sdvBgj$oZ_NBPftrpA zgBdIJAR>!Wv4urgS3hF<++v3cbv>6!UU}PMEzO0f60_?sQOZ2EKMMqP(dc++ebFx>kSB2Dca-xgMNHD!n62 zb@&}TYcO5Is$5f+c=5uQbG@WAKsZ)5mI3XN?TkQidhhaPWdm(FVh~1$%mv-*7aCrO z3y7Iln-~rsHBLGOtBoZ!6RKqQ(+w7zr9+RX%h;HsofUq!>qhPV2gaao^0$+h-@ShK zmyFgt{Q1vsPQ!mix@j*vjz_dDpHOZnJ2A>y`;ew5ffw5)uA!!1B0S6vyP(K#D)GBd zQHjdE1Jb|TS3Mp?GC z&GC;REbth8H`d?r&qjEGYh)wo2!s_v1Yu>88R+IUv`{)p#H0xr$8wI=?f)UfS?ro5z-0^lkqZ|y9#chm2+KCuK zhA30@S1fwb)z|jK>qZn7FsAx2h{@*H#kCf4aau_%Z5G(x@gu}(I8^eatKvx1DErUs zQS-as{cZ$Q=uz`e@ChKmi?b_eIP{oLuNn8f?kRtEYK{12ek|%3D}rvBYthRChuH_mS|8ax)tJu&UOW!J35Xvv#qNX z?{0s02TyPLQTNt>?wjcK=gw!U^*3!-`!R%`HdOYYhEr(DFPU>UM>3%BS~e# z5JCo1$)UwHS_+$Err2Q4bvS>#ZoN1t#07&$`7~81kk7=v$r11DV#g#=W)g|W zLT*cBhu2FO8EA?H-}_FX7dbV%UL!908O0#4J9Q%Kic>%`cXP;U;o}#Vm+fI545t$_ z>cu|t1Rlgg9C*@!U9DEoYn$UJMDK_u2Kbq3qYO;P@}ibkCRG60-NItZ&)9zxnkKQn zs5W$ONJtW6nI-`Wd??6#K`<~jV7=u80$53cvY*s&mx2WPF!u#_`I;0tey(}$1cwL5 zgXB7`%N*{~;o$6lKRy1B;`ql$$N!w4e>xcB3t^FKnxA?k%fAsS+<&U-lFAPQAc3ms z2xbfy_p@QNJVS#Lug-X}kfu=O8(+tH!4^A^Bv}km6e3KQ7x@v0|ck<5!bEH6t{)_#A_o z@fll#PhXs7zkBrifLbzuFSJve=!w8ot}hov=96aU{fA1!jDr!{v+;HZZ2AY2mNivl zmR{7^w&J%lSnV*U2J}Bbk#)P=w@K2&i6K-H`ksFsZ<|@#IFh`F<|!zld0$Jwd$8B* zc;ds-hl0NX22Uj>w?psP%i7J~u=+?sT!D4E(;Y#>ef<2lp*PBun= zw2)FSW@Pc3J>3SrKKJdkYVtqsHf8(r^-yyV+_!l7o^g1On~$43vUc}g2Gf7w{+95W z>FW>P`^Ej~IgtMLbmP#SO+o37wUI!I7I%MV68jOrN&2Z9>40@lC%p^b8BYX?-p}Xd zteL~*x!o*|e?J(Js9t@@PyhNk`8sodtMpVRc+<3dSC9PAO}ji;ig=xp?v3|C1OLLu zB7&QY?epVMA=P<5GW2+Q-D{fmm0vv3u-`5s-i?I&26GqIotg4%ow|o%wLesCtgtAS zxh$vwApL;TcG50^8W- zfTmr`Rl?6F%$hQaCO#oX^(5;aC7G3HhQD8bU*jbQ|Luk1zuEWt-ZC6#-a-Iww0GL(s0)m0bk5lBfhH$%lp_G+ctB$m4NjA^?M%7EL`5-U$++H~}PogHm6S>h_4wUobrUPXMB{?`yhDoe{^jm#^H2{*oE@$|=IltPJd?8wrBjK=9G6B{&MQz`&F%yxM zMf*7~;;HC?M zh5!9mjum@Zd|V%*4AQUSeZ>Zwwp&}Mgdy#mQ2_!kNtRBKX$JA)8sU>0=h`&F!M__PB&tv{LSXGfH@4wu5O6~W$}y?7 z68WVe$JdR6i_v89yu8#Ohd~Rc$JJlF$54^IuhyGwu{6GI=_H;#+Sc%nPBxBMHeyC5 zfCj)X4DHT;1`nd(ts_j(L|LrLjNE0o)Wvq~MP&44xxmCTE$7HacTt$%A=+kD2e#hJ80II-@N0VH_Lf!IpIhvdhs_D zD$_~C0FuH4h2Rux7%Zkyr7MZXttC}+h{B!MMB5&JaJ#JW8NB%OpO0U@`qS&dp4Zn+ zvr+e!xDhA2x4-ZzbQ*Ji*xj1QE(tX>_KJ=tXNc|n zB4a2Vh&Cb0Xt`Iy3juJ;`2GFzn1i6rqSt@D?w{2j_f-Z0s;n;t_ae?@btUM6WB4N4 zrFfWsX~Im8RO!M(6`?~cQz@++&X%^6flyBNXgbLTZ)xa%f}Q`0o}gZee?!MK`?~|7 z!9s{O7F;-9c`~CU&}t!KmCUlbnA{YY3aCV1Le_2&Ehp2{D4KVI=6m4dY{p5OqtlT4 z1u&NZmixT#bs*(?IeQndCgi@YS@tnT7ig+~x8H>pGH;w??8l*3kGQX7nQLVl%>S}?DkV>KcW3|Eq zMh&uyZMD?OMQ+8CXiF`Jw6A-l|36}@u$C0a&(*S6tH=-Ci~7&Ggt@m#{fG5H*iLMJ zE;6dmg;6ORbX|rizQp^084T+zO4Vai0S18>myz2ya{mhntDxtYXDB#J0jtVHVYOSK zqo1CSgT=$D+;p4$h(AY{D5gP8syWl;Ttml?hd>%+Lg|XG)FX0>6#dP_ zu+y-6ds=eBAn+R%f7w?E(WO3{Z74&3sn#Gw(tyPQ5JeoeeqG))7|9i2t^E=g0Fd^& zybhJy(1}5RMqmD@C^z};5kd_IwiyywcQ9@+gO0r{aP+?0Cfd;D;5<0TbDH%Y>X$M1(Jjbgha+t*ncL4_xo{oH&QItJSi?>r$Vht^ z59Bsl%lJ;9;l!a9JW1l|=>CF-8REU<4(uOf3tcx6_=KGY!Isav=^yDTobHM7+gP*_ zrXG3M$Uu;yLq0@jX~qgnaRfhqk1*UA{rmK+wcCq;DL&FfrLLZKg1Vb1cNBm)vNekZ z6CNuTnxjARHKz*@vS#sCTP9Z~$(g~m+@hX$-{olMWJ4*D1-d$a7Zf^5PY@`1 z-RB0-sx7zk=6KPD!jRjn098MAgSp3YJE2Tb`F;zpuVHzS$4|~h`iimS@4FYS&v-Nb z6}Yh#bg^?=BZsi3fDlV60cFYEwGtun-^(>C_N+eE!_YLoz8KyO|l4e@Z>a4@1ia>Lzg z?-K=IIe|NJ(!zyD)5NycmWgigCz(DWUtDTzwsvqp(ucJ9bAUQ_(?px5kQ6{yc_AsP_z&C3OolI*7^KcW++4dog+Y z&FSguH}6tp?&WJHZG*!GjmtPHHWA?WZN04O>qD0t!4tJXa&7rDaOFis>NI*ta;1(| zrdTS?lD)~J+(Ky@p~PEBLPUfj8XHQN3+Jgfkr0ES8%L6Vg^2diH4fo6+dO?^bSBZ( zbZpzUZQGvM$;7sw*tYFtV%s(*wr%U1_ujj{f3>>L+TG_@*Xdom3SQz{^_BHp*{()e zv|VNs_e~IL9nbAZK`1r}OIbIp8^P$`2~l))+t=zr{uEj>vBv&ax7}hp&C(WJbkI;%TaFgV9g}WgmW?h==C?kBbo&j7 zG_e1?;2PqQQLIzP<7}>UnAS1B==H{d0iX0t=uLZ;?`c3&_F-cn30@rLMP>C#Uw;U- z<6V(OHzT=9rck(Jzfod%QHtsmMc+kzn_#!>$a*EJA|xN z&ZT8@Zh=JZv_2?0c7FEN-Ij6)z8Mz>t-lOvvLA#pddT=CdBIv0hBPpaHc*>>&JAQf)WFe zof9_5-nH(alr+burH)DOIiCMvzRJlvOE&JbLdd)K7dMu&Y|8z??$dt=U2GqSI3wdM z!e4p<_I?ac+gPNi`C{{zvTqT4H~L~;Sti@3cp8imady5-9)oiq_oVbC1H#D-Z@oT$ zJ&cf`RkwZ_3>-8a898NPsL~`$6D1)akxh%@iMm@una|*77zlB;?W|p$#dx>7?rxD? z`obJA?Y)Rw$ovFmGj7Gjb3+oo!EFKaQ|g8VcplsPGmSrOEQx}+l(4|(+NFw{TVKdQ zFY%OK%S#&R%8)aE8HBff{ce~7IwM`h7R3=fUPOmy0P2sIjzOTIdAl}$zDq=}VLxiuA z#Zy>5+&&9t?yfe6e{af@g4;{iI(t4;f@=z+#u(ex4ExwK5wGA6IKco=m8avM>uh;g zdm6T|J@u5=p+z=hONCy{-UCn?IZ2L_rn>n1ZNN`6?ti{^eps16PubeAe0~aaeSY>p zegp}Jm{Z*jc7tzhvIBnfUyj1q?f4OluCY z$7RMd%ooC(TQK}*N1^OyaE_(1e5?p=Nx3zXDmcqb$Bm&(=Bji2tH5qd7`}$c%lGN! zyeAN-ek-_Zx#Iak>I0u+_gj(EzGAM{u)WpeD(%T#gJczTF)K-X=ID(ul)=?)?~$2A zMa_*abqF@K>(=ZDsZ*2vJ9p?mFOG6iM!VAOT>s@A(9$dCs#2sF0GE{sqaQ5$g( z&j@NYCbaSCxT2u-HO?sQJt-%=G0v#gzU{>e@%U6}gqiBIZTNXzV&0!r3o~=NZNP%% zT>WHvq=Ax@5m-sIc_#niZAqax2OJR!-=2(Qq5?a&&;&wQ0(&<3UFB-@I3&`W5WuC} zrHMjpLAhi7mr0Lf-Des9ty-p9l&j-X%i%3?Njz?q=}fl5AQf+=5PdsHnW}t*x*ye? z!=)7>#mh6DrWBe2>L1ew)R3BbNkFxb2P=iMbG+AF3K5+9QgTV(LXs+^aV4m0m4tpB z>eo5%L1Vv(=m!Km+-X0I4tbd+6ij!OJ{&OyYctye_FBe)E1Xy)SmQS5K6*Z&qKBzR z0l|AYa(o9f^AT_|2t{@dv=M6OoVq=RJUi(%6N?-4`E11v)i$zGg>ot}05GN?5KcEw zc=_8a3Y|)g%4)9blHIDJli*kmj$uQA3|U3K>p}WAvL`cYVH;ylUrhi~tUTaBBq#$% zBYx9aClmgxonhV&NauH2l=*bsZ^Sk)D<^HTPCLdXnJ!#k%8(I5q)1U=p-`c4RmkvJ zS(0KAvyvO|TFdDhgi;FdH$cH73yw8_m`x|Sp$y`62H)0Mxqu`^vP^4(F45S;Sjhzc zk};e0GhCLCc;y?Kl30_2(ye48%$cT*Qi4Z)H6T>{R6fp$e7n>CJ)HN8pE}O0UGAx7 z-TwdDRNxXxqw9N6W}I3aiL4RGtfYp0&*T>sGi z*20OIo*d&hTCRa<<*2OWGF)hROE~@qI?>_#75Q50@xc5sE2zPpVd?xbm*@-0LFi=5 zvBx#wZZvK$XO@xR!uu{Mj?frI1f=2d?Ls0f^?no(#_YxA9-}r-JFdYX} z0+tSOtIx5#Vx(H50RXPgC~T>Pg3moJC#emOZ?}{fu$;nu(0>V2<+U*cKbqcm2)E6D zQ|>#{aVE;#Y#_}MnxLun@8jVgnoG7R#@^xb3-O3eFRc@`k;S9ycJ>}@x(+yI&h+`^ zSmAnima1-%c`|3f2Z8I}kO7g_duoclwX~H%AE1LgoiLZd0U&hjhb-oH-GF5AJlSuM zU2xub6lW+c9Jd|f+9fW@65PxF!_hTU0~V$u>%k}sp7>74nR_0|yU&%%xxSWppD&Ae z*c9`fBUGUsVNAZo`X{#w^|GpNN_HmKm{c37)V+BZW+ICny(<2i4px*WUA%uddn$9D zcY^%^rM&>N8Ibmw5ag0cbIfSdln}&q7quoD;KEWAG}Feb#OGDO`h`CQ5x~q|;@Log zvt@nFLv&Q|h=0Ym4}fDFE_)Ne4{5EJHM25EDgOA*R`Cznu=7pRWM8`7MNP9yd(LWi z^iW^w+>@`zSx_BaieWXpaABohso%Sk2q-_gqZgWl2ISb5k#mNZ`lkKWD5MQs*BFBY zQv{!3-EH=i71bR3!?=^S1eFu)MI7RsihY0^1hrpv>^Zzg=>)`vP4h!=oi6LKzrDXA zXG6+CtW#>uf@h(H_lr1}yk;JH;0l7ytxHi?VR+W32wLg>ebi}7j>6*+EO~jc0A}dy z3*q$aPs}gar9~uRV(8r zc3wn;rN=pqX97M9YKL8}fX0C7Me{)zh~V@^?M|r*G2w4U#tXCQ79rIXm%R&|_$vpx zeuPq&V)O~$1ZK_e4w`OWp^#l^O!QI8)Kf!sRDdh~g27vqM(qwi;4M_n@b&4e(VTI+ z!~S3A#p8*=jb6Po3A(a49|$JAmrDFM1^J$Rl-@Jh#8ZPC^OQqB{7;nk zf%(s=?2F4o7 z62Rh1{I9-7m4kwEKnuYGh&LkEB|O@o?}+1KZp~;nHNkbV%U6A2|JXkXu2_01cop32 zMAH9k2^Pm6((HF)@WqF6D(6iS21?iNQ;8s_GK`JA^o6a)Wc=!jyi=-rP$?k8V>**L z!6)hVeDT1y4`wMJ6$vy3m+@y024bql3KU?Cj{-5wLsZjP6Cz=puohq63t< z^4SBn%EshqG%Zk_*pGXJ3twTnYEJVd%&uoy5W~!TQOSHPT>Ii0- zD&?;Rve(a5MlZ&Mk_Rwt5jf-=pdol3C>^oOPvk;6$Bg#sjH3KeV=}ji(ty__xfZ6r zgGb6hPKWc9WNb1I#us~6uS?dRw#y{cdda%8qwC|uJTl9QGoY9ljvNT;B>6IAY#UQU zf?zY5H-Jg0G#m}v0v#<4uSWCVF$J`8cV#g%^#KWq7L5?K1X$6qy8{simQv0_Q5BeTxu1amSo@n^6#6705!Bs40RrRWHMdAaGbJ2y(WDi7c-q zu>Qg%K2`3vI+IQyFYVX2Y-BDGtc&cHuIuG3NxceV@kew&64v{Q0{~ct(joF9X2pO> z=ppfXX1(|rjVG3sxfBpQ?x;t8dfk!JMc3%muX|6`Si=vEWHxzx(}uUy$Xq=B(70Zb zoS!MUuSv@HWr=~3BpU)0#n2gz>*HwnLz^hm?E0wllz+}8+i$z>{hg>PLU(DYn_Qsf zAZj@7{-yre*g)a<;Q(^mZ+3p4u%5Ua1is=;{GdK;{HqJp=bM;#X>N8StEWO{S3;~@ z_J}%FJcMD-VdY=Aq3?$d*{(cFwG*+-P2POQs^y$LkMSa0gJ?m}qHW+H zeA>Oc^*n~|Hp(d5{y$`n6Mud>iq$Yz$IN**SS@}vMb=A>2?HQy8f%uGB!ntH61ri# z5JL5D@?p@84=P!PLuGFw?4rsAGR4HIv)HZkeX2@1+C8e8HTu0CBA%h+mcS3`3WCso zHM$ltWyDBPXh7}LOlKxG?SFNe`RY}V^8@!2d|fw6y5!+~UEiIY9a428!z@_Z@w&o` z*Klabs4`*rV*s-D@+&bp@Zrn`$tD56IxDVZqiiM?m0=EzD@wt%)zkKnU?r(-IELLCJ7))x*m1%g~d&yGN4Dh!3Z%TeLO>Kx>bVYM!X7~GXhP=D{??O)vg4MD0i z8o+~PQz%aLLF@H`bhDatc2`vU(=h~B1jzchYvES#_WcAuQZH`ux7 zvI972<@(^wtL)-j*Ib}ibB~jHWQ6c6$$0HX-M!hhoM;8Wg)Du+3Okukq+z}L7!KyL zMYTP8Ll`XZnVLMyyPmf~ypMwj2CW~dy!BM2V>LR8B9h%QoHwqBa_yy?^{U7 z&!^xl59Oly;dA4$ZS{1w(G(4h8;^a-MER|)YS^GbR?aS38GracF6WDOiZb}UB>+gH z5zn*z@j-P^0X{9KzvKA5 zu>}rc(!Bipk2tZHnc&^J>Ozq52Z~n}?^vmDG z1cxkE4X4O)q(&K(6zs0GKk&p?D;%Ak&#m48~5=e5iQBi%%!Fbg6l zwPEeFtcQ1Ujm%W;J=!P)CsNk%*o`Gd{IS2m5?jjH-MpU3&szsn5-#=-ul0ZkAbigk zsOgoRBHjaPi3LX&oqO?dWDAOF{gN@Net%gSpjvIM6?ThZ(;OsRwkx+h8f8kfAvC+c zBla9DRsuu4{!U7Dgt%Pe7$oRj)K?dXI!*a&R6vXvq_@nT4!5|)H!T^HQ+$hG1^|H5PVl`)^sf3H z5D;_pdc4!)@i4k#Z(#ZpVW9v0wtT_Kn9J|`VeFI7>QdlcZqEz;xWl#SGYwJdN^NE~ zBvef+I2v4nPSc-`PTYy(jQFwtQk|*hQtDB&p0p=b>Hd&sG1v@}NQ7F5e6u;%*H%?I zU65R*-Yob#0agNe*a-l;1%(%C>yX38xietKM$Sg8v|#m)@zkg4D*tM|Btasy_A^^c zxeHhcgB3Q4T|%7>KR;%^j^>loI~>8y`%(v zKHFnr;&Y>dsO&aFLJHv^R!GMBo26P-E{bOK5DQEtF8J4eFJGVo_zRjmN#DPN42O&Ay}SbS zhB6~d8jI8sA0!7xGgW(RloO>J@DUHuc)J0EyQ3}nXSTk9Rp#|`jkatsaL@LFxo-wA zbrq0nZn#+rR(B(OxP6M)QwJYCEnh){xETW46^Wa>cVK| z2$2C7KUPN3DXa8bTS-(RYO0ra1}buH$}rsoBXMqw8)s{juFY70&{;5Yk|+k~tQyq^ zf7GR@HkOBDHL={zNyeXcR#JlR?9DbaKQZ{4I8v4ia4rn*1!Dp%w-$S~~cYsa}`yhe6WuCFbbWamz2&qm3t$X%3;8rG?eu;I|%@k0hgo zKVAyEHQG{N!G}|WPH2-%_H`8^*v301W(|Ug!_m?%jI4Xd>ry!1dl#!Pq<+FSMyO^W zSvhc=W1!aL!N1-FKx?Q%q!JvY^|vSdDFMvY3mAbba^jLbj@&wScudY?=5qL@Oh$T} zqiyMg(PD8GaQyK1R|@NK_w&i=m-PDs{KtFl4i&K``XLViwv5Oti3f4@G3?vb!8B)( z#9Hn-hHfTD;|qBvsVz4=bFL1_XVYM)G>K^ZJ*{x!e|`n;Yw)iGYFNcnE_i9^oB^`G zai6qmHZ2E-M=2uFTd?7JbnC;_9Vu=EtgG?Ao#Pv6Oe3x)@H&2>hbMet8Rm_nE@5Y~ zG0n6oZ*_-xAkQN-(0<|EiX62m+Z)bA3p{nezmfs#&W-&BJVWyP559MkF=jrk>5XHPEQ z50ZqSiA!!`smH_WuczSo5<%5LPo?l89NVr;87S}>3D&AK1U7sK&Q$lBq@allsH(v+ z8opX|x6TKY8)hpv(>^L&Fzwa`GS2KIL>yd+#xO2~@PD-mDpIk=Ow(n|iMu_*nS?2k zOmyTse&ZBp73F~-u^8E24kRin{P4WJpZ)lJnO#Q8lWlX1ttPOa6fcHe#mGBMuve&R4u?A7NNiI7I|npihd`A_1Ubv^QQ9z%B|x z#=S?SJf(1V(yUjlO;?^wGjJb%tUhrmusKjN-`#d>hV)XbCG392srY)p1SQ+XTNQes zvO~e}?_YZVfqHc)*ZOu$2-Ha1b`p2@R7|z?WdFdlE7<{+IvN$`IfHb4a}0WSLM)EM zT}tzY`1L&pD+Aiv-3Jh%Z(>>qhPpRhh{*Ro>ly}8570GUD^P7%4cN4M z8nlgR9$Jfw*<|!&Udph~tJ7;Z(r#N9V<1ae_h-DFpZg5wI;+9WW_9lEN#-U&v`@A-dEbzJ^)B(f+&V)&a-8uVssGNgzaS)HXn|E_t}BI7 zgavwN#{uCB006T4m7llJ(;O0~AVW#Fk{hc!GLdO8GomH(!k#fTfRleIW8r;n>);PM+Zn-Bey~#D}h+khR4&Dz>uD< zv=T^{6Pc_dQ!uevXqhR8N%C%0x^E{X^nzv478tz%ur_H^f5Q1SNIsm{ye0|#c#0`A zVv-}sB*R!3CgCG8zTi+0cV;Cw-Cx#Dr=DUTLD(HT1Hq9s6?*J*gOfR`>1sw@lArvl zGSjJcFaX%<8bQPw4gezugrw9qO1>50F%-m4+8PUH1FvCTbJ%ww#?^;jAf&$7pUe$k*ulhPnjI<$$j8H?QN>5u$EVjTFG3UQb#Z@h#7;gubV@0mU^^6VyTR0b#ms zQ2O-J6TJ|}$?ZrASHd9l+Pr9{skUD`lZva+4@;3UWUp=zL1ES&E)A2wKU`tTz5@cQ zITU_rQiOJkdEsuQX0bXtMjeRXT69t|kjvRr+#P<<(!Fd7uZ~=!3&uN*_!f(Ky8y6< z{Vfx|k9*NIK%y)LgF6I%lh;_va^&pYV`1sJ&KweSgPgj{$Rn68I5Kg^j2AoAWtu^4 zZ8jjzf?bFsBEWhI`GYV1`_wClU~|H4tAfYYf?m*)I!Wmo{xVP>j?bWpqEhB+v)Hkt%R-)J=O zv8_psL3eSxek@7T{4_HPOKz{{ILNUOB3jvWa+wZWFSe9XD616y9>xJ9N#cOUrS1NP zYB@wCQoV`ukwt02)y>G&_iXYW9G6cjIO#cUO^r(+n8X%D0W8U2gGEu>g%{BOuj3x3 zgZXOOiZCR>z|)%hA;Ko6MvlKAj=eefo}671w+E=odDROm>%2RQ;I)F?UE-bnMek6? zp$0EoqlXnvNF{mjC$+xF{+ao`6)fgJ^zxv^CFWzZp?RZ5c+Fpwg!Qu+AKQ2#$XM?O z?C87WdW&D-4uAjrH?q9&xF|r$`CKSbX~f6YU<4U)wuBM}z`^V0(efLmS}>Pz#5yL* zWa}l#Eljz*uf&pzpWF|6{@XL+{wdVttd$+6HjO<5p|%Bc(n_KhX;z`jZo48MErG^{ zK(mnYF5&ot0u7uBqR?4*RsNQPFC!#}VvM&N#>Y6Q=%4|+MF*)PGy$-VwKI#ZO{V=# z+5MN8=P*xdZ|gOT)RjjakzRaRN+U(HmcVZLWS}8aGG+{4O2ddhEu|I&Ysr~ecR~g8 zmf@p}RNVCE@h<)2PwsZ*-!v37!LPgAB1g`xsxR+^FC+vs8CiA#Xa35_4B8X=U)EdcoQ#b&pFQ{MDN$4_dpqbze zv_X}qWReYhhgM<&D>~AIErS%^?A!?;#|P}((m! z<^xTFQ5&Fmpb=&bI_XgCYgEm$!ICeMrU#ewmfX_{z7rM-xEwkA;bp3w^6Jg#`_P>* z3uIP#%n3eYct3y}a!e=P_SRRF_uW1xj^+xi=)ANjq-az#5)`*+dU`VXJ7vou&+g7) z8^QydZBrF}syLx8DKuHiKAY772hWxz!@umYYaG-|TeqD77F}v;dMv+W66wT_=fb^NFUSDz$;(^_5y0S@>BL zQ=efKFWR_?W6(ZjH%u;UCW>>!*K#cKXvK+PH-a6jvdinGaq)gPv2X z!$mLsWHqPjI_Tg(uQ~Tg^bA@NaF#Q{?c4VE(JD+msLZpHJt*)A{7zr$C+}4MZe*dr zs|@l?*iivg4+r=t*`kW+7@%@6`g~^yKh9VP-{(=hh?X^?@Qc3U8xq^L@~XmIq5{bI zmD*lQAP^>yl5C5L-}v}g?bk6IkVmdVF84#P)3)02+8@OeQ+?&u*pQ&%p(29@gHSPQ zp@DrL&Z{u(cPjs6QV)P*+!eUkg)h#`qK9EC?JNQO;HM*_JtB~VnLSBBxOMos6>sE? zOTZ5Oekb@@00T>#ugo-XTAvTIzzHnG6+emLFze3KFWah0#+;j0AwhPwxz|E(0&YKI zgYj>QhKd&;2aj8>x)xk>G%fue-N1RLIY(?Oo(xw+JY?ylSU*TacL>~CSt%!lJIOht zuk`>aOQI`d%V)WUUP_yYhOA6?7AnwNWt9DjX->tMkl^YPn_jLneDL2XTv8gt_8qda zq_Ibsvn)@S9&t2Lc(Do%0WY`V(NvPUvB5#3RUJMC_17zH!9@8cSLM_DPEO zreQLEXdUvVdFU-i7K(6G0B!yr(HLHwI&)**D|}68vOW*AH?jqy`~>0IT{atg^04iK zGUdcB2K$D{!IG*g(m_CS|KHCDfv9y3gqNpn*yWZD71VCZ1zCrC=f~tWdN@e{DLWu& z{NpSsmDIi*koah5l1}bY;sB ze5Izsp5SR98OM$4lVk-l20Q5^fgpeq@-I2us=$X5HG#^4~gt_ueGEh=gon? zI%L|Sbq9(kC)1t^>%ESJ&ggD$_J#>DSX`m?xwrbWSss9OVMphyZZ12J4H4)n5*C^x>)x3OdR7M!b0%^1`9jsetQ~yb9egSaFzyJxKQ_(^ew;K={lP8u-6(WE0%;%rlQL-YXj^uw&KVXj=J%KW`{Q*9ukSk`7B_mpbm5qrIS_vExy zcQcJ=5D8dagT9Sq)S^LW z)$2$kBysfJTwvbh3IN`(sTWHze=df9A{*P`XL|@^XPF;HZa+M~{SyIhaI+&jaWj%( z-AlsVxe1mIFnuoZUwov*{858Q(6rAybJVx53hQNV>>-;x3W&%IWY4BnioYj6EUu?Uq7F)AljA{O zO?x0vBxQZglS<0T$@u};kf*QmUr~9V`EW;o_H_^$mlV>Zr~Cm-q^$TcwM-)QLdWeU zVj~QVEfO4z6U1+yUGi<$60Uy<=#iT6p-|SiftcJP$X$@^&5)7~{q3#*X0i=!L%GMj zr`IU!+f&S*Fue^Pf18CCz!JO!0|WY0nlH(sB2n5ToW!y1pC1E|D*W~v1kUcjfg_r5 zzVTtd(R@=ivtBoGnw4Sn&2o}7Rg{aVLs&05z-r|wtFv{%xXQx4nV{mG;aOzz^MuSP zR~FN<8jrBd3wG50hSvD@O*BqxN?}C$B=g*gM)XV7{D~LjjMy`6m6i%gaI{5}8+2~B zVeltcB<~m82Lb`~w&Ceb55q5t}5PaY4~0GlqFZdInj?k zY*U8;VK34(U(rYm@14v@!J>Wn$|44wyH>{2%DI5i^`t z1H}>X-a}`e_1rVhhN2bEpP2Y^CqV%vMZ;)kQ(?Y=LrDdo-TNjNb#E?Tno%)V1tWc{ ze6>#l6>B_A#IG3(tqQeTzlps-NeYVgF@utk-=P!vKA_41j%qjJIM^!6%seNhzFnSQjmnENvnW`IZ8!7q5O<@y&?B-Wi~p>gac>5CVkhY1U542 zFj7JCaXbys5Wbxy;>Dr5g_`tPUTmaHz6OpPLo&buPn!!|3AbLG({XD!u!$Y4=Ad(^ z>qs&|oFhyH+5nzM6j*$E*%_tDFw`B*%b`?lB6~`IJT6PT7%1+Wi^D5!%`$sRd~O)z z^!9NRd>}VgN>cSGMwpxX2+*{dl~3B`0>^fq#zh5;Y>o9_xIUjhbzZJ5*7i(ne;pld zTxMy^8VG(IUtrd5cYEXlCw-=^%=QvlExGPveVH*%PAI4yv)_o4i^{<<9B+FaGn^H} z-IgnG&~v|;7E2=^m9V)JB&6A1shCg!&`nRSri=D6N3<9^dRXv6a0FIyV`c1>3z-fN z0-*tkxbm@^jYvqJmHJ%SD>&UA$w5dm8a1<`yUH9!`(5}+Of9zi;G!M>{Hya-wSagW zKlg|R%yZl8w#09$8uNl}xx_o`T$803}Ji7 zTG#Y=a77RV(+jeYzxEBC{Pe11xrj>PsO80p93&2$h@gSDIKnuBCwsXaJGUes#fq>4 ziM(loph>oGos;>8ed5c7lLPt61$yY+(9A^wGSGOXE5yTN5+fxAq8qiak`}ELjj%fN zALBn{e$y<$>2&#`9`}U0jJn=iM`$E?2wKKKL)-RfajL})-EmGk`N{F*%H@Z2VeFOz zp+qG%$+YDz+@w>=W&aLJR=d|cL0%F*lHt-EE^Dtl`m-jDCV#)gpo5kaWNiolnwyy- z>Y<0W$217DYX10S9u)_z?`0?u=1o>Nf#9^PdE&ZL(7RNM&e&u=Z*^E;%tRdB#Bn8= zITK($Na$w}tGe0l@_8}7f6iK5T(OVd2;&OsF;h2jfO_a?hoA~8NMq*_MgCIWh`=Cl zWMxetv7x-94Qv6^;)=j^Vz0z( z>V@{jg--1fbo|%5LGeLBql+k^5z;665%u(x3k2P2sscd@I$MKHzA9C_=y2L z2{(d(o5)av0Kg{rCa&T#UJ_K<&!e8)v_PnQwH6*gZM7H!v`jm#8{8muJV*#HLg zJ40&VOy~0|k2@*XQ(F2fzEC7Jrp_oKVuOOlJy&mtML34A}Hk`c?C(yy$iyS77 z{M0b{!lh?>HG|CY_*)^kKn0&&)XS02(4+iDuBmp|q4l>o!uQddA&D)-NwSy!_pv$m z%Ft8cPW+AV(P(jf+gsSS^0|C4W_i;EnJCGbAo>M+he^HRm|EO?GA))w^%LL>2evUe zkrYG+G6kQCRbU^Jvd=w)rBv1Hi5Fmt`9V9t!x5IxVOc*6vslYmDDLJJm#EYXf3F$cCexye zS>Bh+(2W4g74&H6lYU6g`fTWk?o{LWi;6lT!Yg9kE%#yRn5f;M&PzPP%cz_kAL4_7 z2YOoQ`Xu-7hF740MwSQHb%3svRE#|{koF?xufE|cym;Jr|M@`T|@56qeLssRZ(W+9h5Etw)eb5 z!L8KEBTYsNJWD)Z=B7OYQVDwX4sK(iWd&V@044}ZB5JiA*bzH7@$%u^>E|!HsH`aN zm0r(H!V zW)RKf%SsB46+=}#*>}B#xU0}4^~!H`-F$e{>w_zb;ncM1%2$Ea@gs`Z>5| zi`N#Vs`VD1KeVB2H>|`NjdZAN3CWR5bi!zSK>t5B5d1&6fsH>7e!yV=mmHWB;KYyo ze<1Y1Xh|6b2*}qE2#6@H-U}Ez?YaO8rt#iM2jxF28kfwl4@3MH#>N5v#riL_CoQ=xuV&U@j)YQrN5*Xc3aGtJ&fAd2PfE^~j?UFr zDo1oyfu~wnN1=nyc^0+yUJSyX08K;lxa)kQ`9HutY}0?v-wRW|w)<`W1?Nrr0^Qb@ zG+FHd-509ZmdQv%qPaI%yEMY??o|0%Xbr58&h_F&kG3L{Y0SB=9IEd?ezyL6JCREj zP1l?%{%ME<>>f%wR}~)4p>e41Q*BrTLE{vY4eFDRQXsk%BI^1lLX>$Sm>ERWrd);@ zW>SY*{ZbXj*r~{a#P7SW^J1G8&cTQ(YR=|yFgvo(0|+EP#s0Q+R`{@u<+{UIWBHmFQ|_*>DV z#73+H;Ps0|z1GGa*{eA<>%FP30z60Cf2FMx-hy$cw-f>&Jo^VVDdfbiYMiO#5IMLX7EsU_O)?!8>$nmAap zjzT^U-VwANmZOOJ#L|)X4DPxnfUT z$r%C01s6=xYu7-p63kA9z0)Hc_cSNoEwHtQH?-_OX}FAT&TDSI4Div7R6C);6zuu{ zT$r~AF4LeUvl>8cJy<3XKzW9Nk{gI45$0I(${$zAQ(KRS8(DaH<|&FjteftUwf%T1 z$ybb}I@^QjA-;0GIs-(yMH}#WXbFUeD_wQ_JzmkbmC<$J>05fxa zp;Mp5DidJt++$GQavz#U!=pjs?TqI2&&~GPV6ZMBiz1CwY2?*E+4_d9eU*xYA1vvj zt24qeL%L%{NNU`^EK1>F}$4Sg0JtP0kj0?A#o;NN5VItJe)@-Oq98%D))356cuO(Aal~hxe`8zXEyEN6mLO868?OI2nm$70lBD=nfh;A5*)*a-Pn*$pfU@ez4P^5n?pr8xwR6+2u2v zM+HFGIDTs-DLp3tn7SlM)HlN7E%i8~(bc0$IBid)jS=szB*4WdXvn5O7^^os%7nXk9R8GfL$fNek764xiKjNsV-gzIrO-O#8e z8B!z(Wgt3)>w8D4swm2hI41a|=@@J8jyY8k^Pt&~rV89w+Z=OplGI(%zHt-*%9T$k z@jR|%kNI-)%|cE{!by_83IXCQ_+FzT-YJ5^}@33ly0tc#o5 z4nsp(yJ;Xn?aGlSN4qfquVs?Xx{G5%0T)|Xli_26Xk^kd_#+!vS5XJ%&IJQ{CMOAG ztL%Dyr=^U{JA2u)0WM`X;PW|#qB+J_8^{2Bn=Dd6uV@VpzoJ%=A0?(L*bBEJ;o5bv zkm#XUVqNG-Injbs*D=R+6MLmmzg+abt%59V_2hOyl_%p{MOzPmoWuUjvZMTjrl!1E zuju>mjA-B^aG}1qmbEfv&(UR`?rk@fve*#B$I44nwsp32-6ew{3ZW3SKbEAu4GTF8KYeXbdWW_Cn1T z56Ip@pOWToyblI+V8j8DoKE=JP%jM1Z1U(VpkgARP)PRkth-Dd&20y`Ee=gLSsW{X zYY3jx9KTE9X{UN7^svL9vdZb(xt~tK87QnKSPto%{|cDuSndq8wySg(QVj{B-((M? zZHApiHkp|v;1A|(g~@#AuW;kd(ia}@a`j~IZqLwpu)hZgB>}6Dj0|*l{X)YWI3P&4 zoinHT)vj;A84e1!a2k~nY5zg+k~KV(H%rH9ZdvcZLuYY*$o!7uv07RM3V;WaavzVs zQ8R#p|46D_V0A&{m#8<80>!UQzWc0W&XxWs(IK;5P_l(xyMidIY<|TdZLd|qQxO<0 zWfQ8_Bys_iaE5h4s+`cyiDA&`$(|_Q`yv(~*oFizT#^jX<3&Z7^JzCcwfVXC>gUUk-%r=x!^qnkxgSmC|=Im$spePTQZ&XeTLH9d=v0 zC!Dc(TA?}?LtBcXzgM82AuI_BG!r%+MNg3Cm67CBA>#dB^K|Xow+PF?hRJO+JI`Li zcs3t$K zQB*0arR$M9sNdPsBB~k|-paaty@|gw#4R_eeR6b|pJA|>uW``KfeW;VPL50ytmw-N zuF8Fk?LIA?w(Ah*K0#W2h>7@*!y%C4MkGY8TEwia)(K}_+QCW0j#+NLgT6r9{cQuZ zDWoG4kqsD`uIS2lLI}D|QD*+y<$UBUhIVqit%smmK!rE#l|c8G^v`@1Ek*}pOru!!AMH3k-%8__8v$PD3zhj}4OJ0c5n4Z>T0>rHKac_3mihYo-F3gJMSR_zKkZ`M zh+`-4j&?lo`n~u6v*Z7e<22AA;L-mw%b6kI1IYg{OH_dyM~{EZ(vmo>cM6ygfW2Y2 z+4iJo(4WI6H4wW@)(s2{w=@nR)v~oD)uo9RTi{U4%DO34D5FB482RlzOYB;}z>47Z zpfp%Ves{ZBduY|%VZ2gXyOx*tl@c-GzkUywo*)-wX+`?GAZS;+zdJsLA=cV$Rdkrk znvIGAUEp^Eoo7m;h+2~}1|3ZwAUN}P7gahFRKq$=L|c^)IwZOf0=F{Nn|Yr&_>Y|s zE=4PWyf&vDKj`l^q09{A2JOZ_YQTKA4Gf0UZb||B5^B7`bityeG`8^^lpay~R8$2l zUei+qnxk;MW2IxDA1lnA4RB;n3H^3ykyf-CWCypNNu&{IzktAN)G%@w0f4{`tCWmE z3_%N1TFec4s^VE0ChrVhjGW4dyC5cS#mC_8lW+}ivsv0nOyDQJYNWitsd##cg;Rd$ zdlD!t@6@_~Lw@ct4aHj&6|w4#ZA?COkK7j_n~@+$;}5~z^wt$nadXwlo~l614AANJ z0n3tTWljxCFt?0Rrs7Pe0CJKIQk2iT=*$A4W-+@Mq59aSA-9mt+rTYn^4C(Kkb(i$ z;iufI_K5?qgimIp+A+RhTvziFJDLlGj%8;BF`eZiWWP1%L4WfPg7_m8$0%`+X9fyb`qdz?jC7IMS7TNqK@J>-DQq^Nr(PjKGOsy40Jp`D)1vl#XHwak2Q9qj|d96@u(5ji^nU5sHW^M2Q2P0zFm*Tju zqJ+Ex6oY(&bxw(YGB=6(cSD%^vw9EDmM;;Oc?!8MOBo*dHS$jQ*$N`vPEBXQGNC{7 z6!~#$9w6VV6DXXP+I_L+qii{JK1B07-fwTsDk>rF!tv<30PB`6f^M-{kFR)Pd5FO= zVqFX2)Kb$Swiq_F4faKLQ)618GmH`PBI7JL+Va&s^3&6Ae-^5GODMo0xmhCp9VY+2 z4%1rCFFXuH-&pA3kWkeHPhODD1N&5J4W4zxZcOqkQVgP=!Nhq-Rp&#B379;ZcDt8P zf^(1ypP%hcz^1N*27%40ro=n{DOF88TO{IHLLZ*uILYsdA%tcDq^aUSPQ!u(t)Ouq#8myzTl)+2_q;4HB}Z>E&M#$Q)wf0}lz5mogU+bZKDV=dbG#A1N63cL2Qjzpw)s|NEn!96OM1^m4J5L z)g;hH0Rg=QtRN+9%Bk_Nc0|k5r56TZr{QIZm#TtlWuhmZ1?)ckrqe-1k~f8k z!ix*n5nf1}-@`S#y^E)QG(q5TO@89Ca904AxnGY4gR`>On&GQss)%4HFX+}>?e1w; z`*{1}*&X|T9_x2EQiSySapZgxgtx1S5>|JoQ=LuEe)dXS@{h-0mOBzeHC1YBS~O@C zY&AVmktq6MjLcUZ`~H$a;#bj$t$g6YPy-unp|p*g&XlOlW!TLk;V3t~!_mPeB6a{f zODMoGl*vZ5o#imoY``1<-1y|@s8>=E2o7dcr%D`u3ARFMV@D~BK-6|AzPNIR^J804 z=_hs3o?3qxSoPK^IoNe$nXIA$>NOFK!)Vo$|&U`#%z*!a>HH?<_u#c+Y3|YV7u*XPX zH>!boZ)g#bm2Xd#=ozv2jEv**9ojzo!s>~C`iTi-g#F||K*!X;J*5V2Mt}g%_eM*6 zT7=KKYQHG?NQI+bXi><8ee1`xg`MeKV>CR7s(~?U*tAfqy`Yw7Be)G_%Flt9@4M5u zF4A22payoZz^H66n_~0!Y{J7dccX;eNGc+=Jr)J_)6XAn@V!1x&ez%lHznmzF3`w- zORD~E$z8|3=?)ZK*V2_KfM#?-`6OfZ1&Lgro5xu z*~A?#x>{@Nlj3-w>tKZ}cvn>Q;(;hOmnyKt-O6)nS%`6Zm$a%8+LWY}7p8v3C zg5CT%n@ESlmRFczu_Jc}}-XiJ;)P<(e326bH>+-hm z*eH?jpdV1EGDsXn`gN&_NUhgL`Zi8+)%}?;fZ^ z?#}oE} z--9!W5<5CIq?6RWH{V;H$;Z8z$2Xe&qFD~`G#iiduZPB-$W^@@lLXvtxTvqJ&h)S#jh!M0Q_$rs|p_YKc0MuMC_Rei#Ku|0JcAKmSw_D%=8D@}Vpx0mv> zbAT}6{uGn&?UmZ1+?r*i!ionht}rz~=D(rCJD9^JrAu^A=k;uHglP;%Fs zAz5@g=p(WB3~K5^46GJ^V1jJsB}~hqyR;ul4AZ)4@1gDeBe7LeZqjCgj^d}i53?%a zTe?o|4MJf;dh^dzeGj>Papx*Z>Kyh7CPO-h6(vd8Ce0vydG+e=uiyQEpz|X@^rv$} zzun`uC+FZ!A#qoJk0Y^g!DCadkLWSj;KaT;$c#syrB12tGHcKuX@9#l((1Up#limo zP)h>@6aWAK2mpkVMNajGdTD-_j^YCrx3JU!l8gj|l0{CpMqvUpnFNHAMNYSV`U0wq ze}s}nPN@~AGh7q^0Lf1P02BZK0CQz@b#QcVZ)|ffV{dL|X=g5QdF4E5kK;ym-}_h8 zdN3e0&~iPQ{SYYWz|PLtUaXISFRm=XJG z7@Mj+^7ekH_8K}rX`5T~j{lUqem%AFf(NY|HBMvGszMG!KUg@g&GYZ}h~FE0f4Ou| zzi3)X&lrl5WY0;zpL(G@5OsLD1cx9e=YB-`tVnNxWwHkc?^hZ9?Uc~ z4gjni4|}PW;_csFU0ht0Q;o zz8ben_|~nf74G&?AxlA zDzS8moFNXdNH?|zJ<=|xx3q*M+DQT>HvtA+KOz=`1Vw!>*CLn2T_M(!M40lSmOR~p z16XaQ4Lb;hkjq(RU@nlAmqay zpvtw``+!2YA|4xYp}(<&f1}>{x;8Yo(?}Xo`ac<}kqMCTUKRMQ0276ObMtD!BbyD8 z#*AtdzITIGc6US7z}Dva?9>E5*`Ma}{alH44@AUu?)v-eOy%gz3kR8JMa_mvmkpH;)7@|9jHtD%>%Lp ztI{H_m%@iIvu%b#OWu6l?{*b#RBKZ(E@|pg4;MxXyQ*zHR#*nkxUFZf84S%zIrb%L zM{c&X&?dVC;n3^me`7V!uiKxN;+;G=(@TH9B-2|79wlHDtV(v5r{k0*8OCv28S6+I z$l|n>;Z#ulhV9XI=%+g{4LG^{0AM}}a538+AP-KBtByEqJJ!_*M68giU?*=6+Fe>PKH>;l5ZWuYIbZS6YddEpzB03M zn3Ls6O(>Vlo0N7e94Htps_&+24;3YLGXb>z`&hnreWl?kQ3uT2mG9BdC zU^!px%_N_BfBb3@%=Hkyatl!)S?&k9X&$bxc-}RvKr1B_lICk}pEN4#z(2({<*bnD ztsGGBf$QsagX5}})`XZ2U3(}zz304JS4l!_Ct5g<;s%}wN*=Bo&BYJUYiv5> zDB?}%Kqi2$$sU1TiY!|cs4@FIE3!ojoVxM>U3-A7y0{rYv=kd)QtELy(J>Xv1NKKa z$m5^+8V|5O9L7MRK(9YTb1A_rT8Uy=QzTFxg+c0!g%Zd*LBs@W&f_`OL)G3v5`h&H ze`8w7m{6VuV*lsezLh)hC~}=j)F3O{q1I}Z6@^Ad7%VYKqurFHu9(0##H1`2zEZ$u z5lO2Tnz}5MZ)c;UGFO#CoZood17u%!So2f_>z!UK}A z$ZI+|1c1i00MtCd();11P$o$+fmbS0e-6Ot&3Pa|$3iGzeDtVLp_prbkq2f~8lf0k z2;!Oeyu~UO#1GxJx^2)Ci+_99u!w}Kk;CzH21aRtg?*B_vhTFaX%cE7iAlKdapW-} zazRFJK8CP7A!k_$%?Sq_;*E(r=0HN+e;6h?8)7Zp5z8I;ed`B3WyB83RhH*$)YBvr6aI(24PGPJ+@z_PBE9r&&Vopw(HCR=LHz_ z<#lUfR&-7n2}7oTnJu%>)O|0(4=507r3IogF?!+9`m50%1yRmu(r@tE7O=>59;Ubi z3K81^l5iZ;Hl3|C;zvj2kq(*Cf2skv5?@ov4SlD#OudCK5atd}rDmb7-kHzL1~M1$ zt{u2PO%fcvSfSohM#oA}Vzkpw5W&=yk_jR6lQRuE`;RW;+Um?E7!9Mp1<{U(k)M)` z#H8Hr-xC#$&{e$!lcpW`f@4Q~Vo@Ty<&U|3T!1K&c#CXMl6HJa%fBKkJj?tGQ zyUe`JDv&J~vEm1}isYo2yH$lR{4v`2p(+zBK$`+kIG4*cls>%ru+vG~dUy{m3p7gU%unCS^mkw7cKW-78JjvQC8Bg<5l81r)`COqSD&SS3p zB+lamS#@W#9>*tHAIg2(f8SGaE82#Z=uYI>%M6V92o4AT9;C`n8bf70AV!AXrVM6(48 z)JiH5KQcc+6w)w= zA(lM`fGzK$5X36x+56}rlk9P2qGrz1%qVYj3DGrZ018LbAstCf{4J{ z@5?l>Fw@QBW+VO39)Uvx>XCu@#6@&$ff3=%&SFqg{M0v5tBTw#_3BBqxpNk9+FQe- z7Tb!Pz<}03o?B8|g&|?Qh#5o(lKMnpe>7az*nOb<*wnEm2FoNGtD1S{jn6-?0UC4e z3I0BtX(ZU>f6kgArL>!mT9HS#e#uM@8sI*i+`u%}kZnGqgZ(teLn25y7bfO*l__W_41B#nq?RXjzU9#?LeHxu_>KQgacOyss3Q zyJpjP5rdYzd-$*FMvUzEaK{WBgEH8AD_;d@UC$jd_Ba2Hq7&UE7M_cne;j}ex^gQ8OTfkhd_~6Na!A}4<6r%GT ze-*Vvk+sZAEg>+M*PXMFI{6WnvkIYMWQhF}YD`Aqyi!sC$}rmg#_DEU?QYj3q$~WN zQ(+VUsx0Lt5p+S}b-0Ig2aqFtn0p(F^I`Pqb{3nTZpydfHR@;nNhU zkaOu<(*d;Td{QL)6S$`<({N0vo^DQ`V~qY{I-hc$}78ucqwWH1_d>Rs!ocgKX)%hG|@SG>^&oXnQ$mhB~^2&WNl- zx$o7;P3>$}x$)Pbdbnx!7UoD2_WL17n$dR-TsKyHkm>%kb~D;?I_H-Zg5~V#e>3sA zAC)Iwg3pj*eP=Ws$~7CRHMlW3s2a$xiW#Il3lxd*4>z{3p*O_EOAK+d#T+H>9~~oZ zxZh+?2|quhj*KTyAk2W>`sZGZbnEq3;_A67o~vuzT^f`jb`c*B@R_+-oWagKHbY*! zdW|7Ljm$A;YV|=DZNV^nSc;vxe_NWn7~K61)sK(B*ihrXfoKpfQUL#{c|+Dqj@VA8 z6Qw8?ZsnPogXLECJ=p}VzsBPNj8^)D4IT&M=k9nG`ZzojhTL4oP!R1^5GTP<#D0&Z zINCtcCVWO$MRJ_ze1kjrX$kqF8tyP=d-3ibzeSeT+;A!IOP(NfvMK;;f6m~}LX!}W z=mb@K<|{Z?Wvtfh2u@}WSY@-5OLp~a+wUYu;GN7?BAbRbbIO^iX}5y_1>dZtsv%3p z1^f|&BqkOE4sySgKM2%+#7Z#^G2hJqeS`>gucl~U22Ffm;g1p=4loy3{SIAGGm5tF z@%9QcUmqE65B9JXW~Pl!f23~qx5Eup!EWe))r~!OrOzS4Qav7~RN}^v>n8H)zv4lv zx#c@m`2p)>nH`D1lFZGbu;`=^Iclm-eU6_^WFe!26c*($tN))oE9Cl>=6r|O!i+{y za1o9QZWg(|Z8RzfgHv5FJ3jStrsN+2j(Ezj^0pJQErSsEz8}^nf5+%^P$$O>^6yhK z&=|(}xHn0sUJ0PY#2>a8nK5wZJkU+M6(Id@B^V#nH1WwC26YkIwzP0Ch8w01BT57# zAqwg02G4@dF?j8q&yQ@4qX;AG@rom0b&^27^)fU{CG}2zmL9Np$+oFwr_ib2DGJBfBvJWxNKOA=lZDZvvsVxbneaUVTn7=Y3yG10Bl5&w-I zcoTH&&u)GzzY-nfr25k3T*GHags|DFNB{0JdFsT%(%X?V`zqB;{Y!`m05zX4hP$r0Dqb*yk2Fn4k@0lT6=Kx(VCc;F_D89 zHo7WtW(cc8ne2aSWPy(${oOTn-x6)i4Yqh*aE$PuycUx?ITWoHob@>!p*#|2{AaT- zRke}Upd;wW@PmaaAwYh0YK-ZnTW!GH;>37QYmWGme_&~_*bnS{kNRjk)H&71rhuV* zk3DRfw(e_)0>+aQ*r%QxB4JlUiMN)fp*|f|*x=;=Z@YIV$5I&vh-N8#a&#Os1!J8| z#=FB~Cr_M1Br|i)o8oQ2msayQre`+}hjI_5X^dwi;+g$Hw}p<8XC9%LbsrB=%*dY^ zqZ~a(e@j=ey}N6d;wr;uD=do9OUwOL<{F9M2X;G%(4%v$@i|3s3gJk5lRH>7**uRe z)huR0AaofdLgq3C?{`4;t@Dn<7ewdn-(LNKb086kyz?M*Ex{G?fMstF;}-t>vv^g! z%Djy{6ZDT+SmO^V^R%N58{c#Wi2?KEmzax?e}7!O3GNe=u8PNkQi;$m8z33=d`0py1e^Mc&jm3noM#3xez-6*C2Y(8(ogTZH;4K7S9*w-R z)zFYW{D|zCy*8Jb*2laj$-<+Q`L$4W z9K@3<1~(R^7oiy8h}5A2Jd*-5@pbTaEn7R{MK(X{5tAWl!Oo+`+-ju8&Cc?tRoA!G#jdZKIzK-;sy5rE z?X#*ezjgc0{Mwf0w|~YyyDi!pz}vs;-R7cf?Vn2k53twWY~5VO4;PJtsh)0@@k9LW zXw^0w^{i~$rtLCm`_w%Dev6}dhA+b&_+XobESmMYTz?>n7WHMhDt7CBSuJFY z<)(0mZpyAJF3UN-nXjsKd32Z%w*7t%14byLwyni>q=OwOuszs=9RaXuERG&vq^0 zEaTeM6|DbqPP5{;tq1;_mo8Np%XwRN&8}UPz<;arIX|Dz$9YU)I|Z|DTP~_q z1#_EE?%hfF19}`C0rO{bZ@A;dx|^I37aRF9!(Yaur%hHjeYOArmi1Rvm#ua+Eu|5& za6D@h0@DI6z(4U<}^H}1;yO3>KcfV6~0Mc=pde46E9`+SNB@w62!Pn^BJtowPt-wXipV(IA8a_wp&On~jJ^WX;h!fHf@q!O|AhRrJJQqQ9s7pYW?Y_T)@wB`c zIztr=V{-REzL~N8y3J_}JuY&DpG?v}e}tF7czGju{hZ#)MWVeI97GUXJTxqvw#mfiSwuGkkTf zxqn?=o@V(EFaG@E`yXHAKA~ik$QDPzGwK>*u!dEhM4)2~X1J6=JWw06B13#SMCk1N z<1pzMm7!_#CmU&DCB(6j5a$yI0`Y@xnyxuM%T*f(-D~Egr){Z3N!YsEZ8k-_m(~xm z+cGQK5_w?_@-ZuRuwL7&sn`3NgC|b|P=EYXe^<$sQ%5=lLL^8M&@sJBgR}j7ps+ea zSXa%aJl+EHYC!91QPy2VV0oN7A)T9re+;1Wtg4ZTPW(lxWkU$j>&^)H(jWza#-xx9 zltJ_j_v)kP+>R4$i`%AMb^~KHuR}<-+XOWIy6VUI)Ieo6qIV zb}NUK%#YZFl+4RN|MB?wi*LWraDSc)uq#pF^i7~=Oh5Y92{ghnX?8iDMKk{8-@kMu zaVRo(0&`ATI0q^l5tvcS@#tZ9l0EExsz=$wjC;_x+5R<<7|0|w55Ley2lxpq8wC|@$ymoQ`tqEABB$9 zg41LR`}tfez_|5yR@Gr!r}z%Fbg)B3se36K6ILe6&1r@e4A8xL{oOKvLP$?}KY6a+vH%U=PJ;aYtUWcJ)BV>jZ!BuFm3 zr^+svI;ip$rO`oW&;HR=wS#Y7Dw3K<0|WfCF$AWzWxT+DpWeuwcz+COOan`1M9A6^ z<3OtVR5n({)Iu3lopbI^k+TZ(ktlr8}57j2Kwf{48HqgO89C72OT&_MtY`Y&9JX0 z6gAZH_!+hYx=|0bEIJ?>m^HZVftka}#(5Y2!Q!f1T#J9MxB%-8-L))=eS4;F_wMWE z7JzxK!P&DKTD$~t($C2AIL_al=GkWg!}f$_QDQ^@^g_9v@qegzt-f27+ddm3p~e0D zSL`akKj}FlVgDvL#)Yl8sVyql79>2^{v?kcw%KL}+l7lVbE5|p+AMeL@&v~ZavH-R zup1s<0=f^|$;bl%Hk>At*0e-g9_pN7@LC%pE?B}K8>`hGOlYu~**ya4voIK7Z}du` zE;VMeHzPvVTz^D51J8bSD*lrHFog>lz)Hr`Ig;KcmWFn9H@7b}jqaE;)y>%mfEun>_0IF`BC8{e8AwDU9lAMm97D%It=*HfG-w^9 z%gC6mYBabqW?^z-+A$)YqwKR7N<=J}6r2;l&1>xD1%FmIi~!~Gb_$bIt(QPSXg+J< zO<$2+lF!s`7ihqJvZ7v^Uy&+9M8h91M#z5t82KNcyn6Bc#UEi)MGov`32L{6t!#lS z$Bf60aGC+JaCk8wF;!2%ekfrx4CHKEu+BJ|K(ZJn0+i4QSpbI3g9r$u*_8#`eL0p} z8|{X1sedgldib`-wBCXz-n3D~S=Se^-QJGp>ihCdW22fa&c}#>PgwT3Kbl+#0Ssm0 zHly8Vw^vP98ow(pPk&ZMMos|V;z&C!JA~PhL_{BBOg}aTX8=nu*&yG!z|?FMi5gA3 zv5*ito3Il*kBRSLKYUHzO=>k$oPUyAWiO40>wi66S=EI1oEwb!pL>yd^qjk9Wqnh% zO-*Cs{wKJ=<#$GbSj7J_2L%;Dx-ktf&{-G&|7d0PrriN~zQqXYH2ZvtQ}=~oU7!ZR z4D^y4a=+Q){&MslzxS*5gW?+OSQg@MXT|ZJeurjCB@Yt~Vb9ndMXKghjp@{RVBG5U z=znuhGJx>yF@wVT=16_>WNCObE5j@L&gnAvnqENJs-usCiN|lJ*%((EvT8p`Y8bor z$DHPK?_wTQwQ#?suD%h5fA#smc}WgA5E8OVmj?23US>s&AMU=`oF>eI{o zciDSF?So$KpUg7^>XiN;@QnT9Cm4A=9)B|q3n|GZsTlk0wfPlBFjjVyOk1*#ND|xi z7nsDmW-J=vzioC(+?~v~xIMYQR#tsbC*xevg2bIddTtKxh~}uDRBh-TnETA=g? z2m5m{S$F7S9vYh1p|PYuZ@O5!wEpj>h1?e-CK&m+i4`_SPxdFQ3}rDiE8nEUpnt;U zy18KcKq;DdkO(DkH(dh;XxVudk}oP_nq89%K4^wN7j0Qwdrv*Sun@sq8{bU4=fVY6 zu-*kc&MM$=^wHrda~nnU_bFP8z~{H=rF8f_cq-d653NJ#P%BWJoTb|z0_rk{>Icy5V#U%9RN zt4xy4I3Q3Kz(!>^&2VwUKfGDv(ctQ3m)jfK5y8@|K|WsLs&Hbx!N9qfn}6wHo73uM z(YIP*vg1t&1TB`5p0aAt<5*9@%)3pGf#25ACl!J3jWz z3+o0`CI%~_J#jo+6LxZBP#udT#BZtTXU)9ZtFku6U%8y(l=EOvIaz2sjIdtpv)oq^ z0tLn~L(-P8FRIpS@<|zpZhztK`UXH&nC70zkk8>@6obZ&=UUr>F2YrKyHojO$k_y&Q-JzrV@CuFNanLlG+Rw z7*;&lBslQ%7S5vB78ljJ>i3kv39~}q8?n2l>KPD<-iwmg5$FViB2KxQAV!mTI#>*d z9LIFHK+k{$pL09nDI`=$`mZi6BQg=E1eyFr-G8>Jml{lZCcAizla?#X zB_M0~%827Ud-P~2`K#sf(W5~IljUR-wp&mtL$SK`>XKdmQP2>LQVtH5y*G z!06;Y?DnvJH-CWlGxM>P9ze6Hz#?&+!I_RI0FW3kU7HPjfpEd@NIw?I^x=z&D60nz zO*=aABHf{BBk=pSEN2#wP+exNyJ~jpC2|HEB9e{+tETRG zyEHZCqFHh{|9iKTc*8{>&5!eJys7FP2#&70to0o8QnC90KrT zG$4-umJ`9`&t})dlPT&Z7*h@}t4_%w9;RU_nJ+-=$Ey+^w3s0z`QMf>P0h4OvQn14E;+d=H!CP(vkSGx z29K+_b$`H$AE;!PvfC_?deDR@$k@twCk2?dyP9CqxA0YN&~`kdg&DN(Ol;L!nglbS zde%WCa{Q%ca9V17Odt3NTPG%^tLhwE7mkj%hI@Ci>_Or0YFvn52yXYeHvcq6FnxXF(C4yp*%$3EdEX)8rpINvI%wpo?J3f zIh^gfsgDgWbi0dXg@K@^MeT%NBP0v59%$s7$$P<9-D&~-kU)e9sb~nzA%5LD^?|E?0;gGFTptD zFP={(GZbL$*m(|RI(!hY>aTGkU=n8+d(7s;BrZ%e_QFNfS0CO&CiSuuO!oCSH+0Su z4z`&(=aLwUJuv5n<4(NzK2Xj{3s{ZL_F7h(18Y@yf>1HnX>e@ps<1)|Sck9+-K@zVL&V^}N7tCBlgK(+=mA70lk=55pThAgvfvmKAj z(@}U7ODLR_DlAU|bj{{*&t4_(GkN$HY~r)?00NC=t`1bF{{Fk5H-F{oQQ}V!+wU>^ zT8EpIPn03L(=+}I-xO`f=S#7n?0UxKc9uG|<~ez1!SZkS*7d^yhA{*QGTI!o8&Z z4t8y58^}(+aXGu3Wq;d?cA~%(7hov-j(5wb`gW^ z_|)u1?@OU{YzYC1N5H@_G=jNAH9enCQ&K=CNxVJSm!QOrn4$O#Cbv1`PUp#{aRe(4 zG-;5AJ13-3ge2I-KXimYojNmMM>)0hl!&Mnl`7=slSUNC)PGczn7yEX1L8i&UL(_N z%Lbh?u)m{hEu3RCKt@JuF%0y-;%2W$s~FmxBve!QeI#i(AoI>2NxJ*s!H8tk@P-nN zqGR$ilTAN>MhJ%Osp?;#Vf|s;lx^I45cgl5CLpER&p)Q0Y=S?d7Xl9@MUKZKFu()< zQf}yAx53$&9)Ii-BR||eCd=^CAx4S67r5d%u_m5g$JVg{OrM%2OC7mTHfa1- zRf8Z5Mh>&rpq}1Z1cCz$Z)u>b>Rlp{^{?{CAnCii^nhj8A`k|yAADxL4(K^BA8>fa}{GN4Qb6Nwf}n;0Nj)4e1h{AuD8Q zL~0g+V3L?LQ#osWl26V)kJUI3o|>hFaWJX=&VL3dj?IA)ug6@*Kli7Da}mSUgC3cA zz_8R(GF|=EbO`c+b@dH*^FwO5Qi3I60}UX6ZGY#t9CaO?WM`v`qP-~o_0Qez-S4vZ zjNpgS`CILcljbM(wcig~rxzZ|R~#22)5S$%(hDNkGBQc~&2}D#Yh7iiF}j8QU5P}@ z#n$&wNgJaNGO3`08;UJ^lns<_7K?@iQfJcqJX+LkyhTc7wI)_}w_Blr6nQh}Kk48^ z!hc@53$g4ofpx#{{Xx8)q?$#jyv_|%6|^j!&52V}9E4n=VRC?s zXr)TfkPuM-()=VqVddjEdO~R?souEm-JfiO=eb&EcdyC=tL-~y2LSIFg7i=@F7`pv#LOXzM6S9yqk!)NhEWs9scdGhj(mB6$PEaLD7i_A3?+p% zg!^Ta`yWLUb-YBQ;bFQ0^(eFn^)$Y-m)^IdMG89an?J##xVK!0P%74ll zjY7h%Ny!McuFR^^V#4d6&YkhTgL$H71a0EbBK%pS;%NpZ!p-D-5=l(sr5Qpua@=@I z)c_aP8J1mttiT8X>GjH&UKCYH7^RX3Lu_0PiYY6GPLm~*pn<|wSEysBqpB@J!NSnP zt3UQ+S!{8`5!Pu8(++3xXZ-9a34cvxws49KZksxC1*M?ilUh|e$U#-%o8CN{aZc^RMz#Jt38R+vT47eR$nzT%h| z;ENtG&_=MK$Gm;G-&$h+q1S` zBe1rEM^|OB#NvVn0C9+{)4eDI0Czz&%$zK-a&c__jA3CFDQt$x7WgkZt#fDN#4fU! zSm$bI6ut!J_!pM2=*Rvm--qOK0iwcz#9{WeSW1*+>8&as9u+T5NXDYBn;rVxMt3Y9 zupdVXr10*k$F^hNCN)UnB7d?72dCN5aZok02E^{zv_YC*~J0Vy}MX zc(qMBwGx9LAVNm9^$_^OE<1bJoga2bIgBk*7~R24g>{+V*OSx|U&C;K5N|+MJpca3 z78Owo<8hEr%`Y*4G0($9CqcMLm)n13BXY8UQ!S{loP zv2=WUl6Fqhvqn_f7cV%l5E^_=~H#y3;d`^+o`JB_$@TtT&{B@UxgFjsT zMl^D}#{=Sq(imd3TP^@JNzb*68KA)bXA%G(=f@~k<^%kp>4e_45eKGjxjeNVA$`<6s$EPU*%Ro2pkpI8NgocyO^tE#`6tpIcK((n!*i zjZ8I$H&dWYyI|T*hPs{^*yrgDHU5CjP*{;%mzM<|cR&EdFn`D=QJ19mUq(aVhWWGe z>oQ^EsoBzVJ?k-zC<%ZHsmh9?I+7O+tL!Ckdb_Lh$q7<^cX{=zdm=!Dyx*r&L8b#h ziRU9IsgrbGHADRq9FkI%u(3erVXuH$`-n!`EdAb=(fe|mZFY+*^g~(mG($@Uv-)at zGDVKSUzDUVR)5Yi#ge}{G|IE_#lA1QiOtiH`psDn3Swpw2stn(*;SZ;p&XK2)Q%G1 z2$ajtbD=xYC{qcH(rQ-=>c^{nvi*N&e<&9PB|*BQdnUgaHe%JH>J=u-k}V}H6RQ$-l*2PW_{dYw3xw=Fv7 zq*vcm-Xkh7=LrqrV*B*sA0`G$^8L_O2SW)YltuWWu*wynoVOXd0*42R{!nzBY8Y;J z3KHO3I`>qr#jiu@$SMtW?17tTw`gH%M0Ap!Yr?hANzlqCYBGIX-ND0eBq7*z=c5|l zcO_Qp_J82JEie@xv;v-!ts3-Q;xR-CimNejZduhCs#`E)CRj?idzg=(ESvl7GE-AN zNzSHeB(;7OZKN)td#!ytE6pwGt$=PYU{-19AG<9ef!w>pCc=mqu@$fCH&}m8ajrtEK zfcApXZ4l#T*zlttvUSC)Ww}HOVi+#-eeNQ{{4y?g;B|iYIKYCLv-zqq(RR(JVBw&? z|8R6S66iu?t$BK%qwJ~upG%xE-zEWM01xd9*$(k!xAZqzH3@TT7jg(uX6<3&=HXNE zFn>IK&rh3#$OMdp6?^AbgQ8vTQ$u#$0qbjUDU7J31Ck3X=$d0BBzQ2Ty@o9T8CpzL zN*x)5_0S0)EvPIFlBe_UVOieGs^p~UdwD&l{@!%Xx4E2Bc^%(Opgmq^Q`7ligq+1d z;dfKCRkQ1|HEjRZ>Zk&q#A)zu0I#P~et%v>Q&Myz+#S~Tx6n7_UqT|IO{w0)5;;ka z)WeTT>M$5GB6u_@5e|FVHj5I^d)Y&VtG;ZhFG{1-89CoC-l5HW8YFEFecCf~b;52c zoM8uN8Y!E>dfoB!I*)~$&T(0D$~jF*P)GqrU}Ehnbxx6wL8$YtX5CqXBMr8r0dSMy|;Pw#Qm?0@+Do^Jh7+>S;z`(8+C%FQH>^F7l1;_2C(`s&AK z2hy`;K(>_4a3O2}V9G!o=97e$-Of;gk0&86fmV)FvP|yHmwofqeAz6h=0`d+>p}Ln zzx|C;ucec5!Lch3>rmYCmcPYv9*rbslRtw_-~|3f5&VhoCu2(uF0}q?R)1V{`0qI3 z)~5a)Thi(LyZU@m4T z;rx1;$StNl-D=T|J#fJkLDS7OqTo03+5{Jk&8{lC=3reO>V(08O*!x1@u3jev3eu% zdSm_SXHTAf_iP4T@(_U@O@Fkq9w(qe$6E>W#4BVa_b233e8xpRZP8OCph?GTT^$nG zw&xKr^OIlfb$JkUjp0J$@;97^il?!+>)qusd}H=g{ZpNA(+}c?B)5B3$4%RiV{2S`10`S9CXr0%x&H*EnMTeQhQ^D-4L z8{dgmH_5mkl7BojQCaudx+k@70jK?-&Jvb($y@E{3vy(X&UK)aVuL$eK&F`)WxROk zz&R$YNK179J$ACy3!IJ9EYHRgEtXH47GW3ydl`c7?~gA89VT|SfVOn=h;3kHOo6~U6_>cL`M6R=_v z;Ig57vU)j&fuv4+okgEU8RicxNceXPND?|UN2Ph?Mkt|*6xw%VRP15ry6|qotRPxjN2{ zB26IKHGkyE&tA#qTLEFJZf*)ljQt=A{@^hW>4zZ|i*M%+^B-C{iKP=Zmn(sWlI&y2 z^M#k@@dmeqpueb?Ad<8ti@IwhgJiWjzStj|K(d`cGGG)KOjyC0x#WWWa+|fOd$HULx<;Pn4CrzqZ;~1f`5KK@i&^rM@ZJLA4m=ym9Sm8B*Lqr zoH2w+5KLd#K&)(lH%n@mjGTKd&ZMhKb1b*9Ywe)h#ngAn-JlYF8~_`vo=~kaMT*Lt*m+&lb>SM}_w9Ta&AfH^Owti$vdp0E~5(YR(RNF6U2S+T{hk_xm zc+g)clUY|P1gXtOFwLJi>f;=r?dt2gxqqz_A(6{_Bd?G)dOD_Mh%l8cRn%)%UMOcN zHH|#8C~(8a8V_&J{X8fKB>MwTsq(eogL{RK2?QJ4m@euuT3>2E(cyDf$Wnamww$pa z2@XPo0jh%r&|QX)niZLiM~}k#SF+(`yAu6#QBBptP7BC}sO+_yA+Pot2_9o>jDNTL zxzs^px4|TrYFbz|Eq|BmEUrX>x7_v5T|93}H945nd^HGqaCKH$=^cpshKsbW_fzkD z4b|`!_p@HoC}dSenIVM*CxsYWzP+w<#jVlPNEHf~ORto5v)pk0{BNd!o!ge_Du1U@byNE(shlY!FjWubh&t}Wyy@U@5vCXN$W&21 ztU}tD={Ap7O>_Dl423tD`V$*I`hQ>V!qM1i7|9d>jK(&CPL*Xx0hn_QhkcqY-h zg=0JEbexWD+qP}n#vj|ZZQHhOc5M6hdCnQ#8ttbBHLU$%t#<*MB#aTE=LcXh63QvN z4yIpNRa%isYjkc#x>5u50}4NX!5rjk25aNbEm0LU5$ljGp-ycsb7?`AfPow}a-(dV zO)hn*jgxP(LKUQsQ0z{j$0}nmOUvG;*#5cTGCpI_KVN+1R;80&D6(&+y9uqf`R)y+ z!^_7PRqyWpJyHSiK`~)PO>|ef9^#1;!;7xL;T|jUw(s7aPtWH*vRfQCPcji|Za-xo z&-OkK2NHv5C~QV3(5_k%^^Q~x^$({PL?LEuaOXeuRTVA6M5nQ^2@XkZ9ZdTkGL%bY z&>0s|iIu>Vz~pmi$frc^9|LKGZ&?RbyB!-w<2$4kmyQH5wYTqQXBM!PFCdcilPZDT zj(+_z(PMRywa~3o4PLCjDEy${HEGNzDcfXk>sIM#OC`%e0P!jq}Q5s&8nqLJ?rk|0Wk8qqY^9l>mw<6WD zwkNl4v0x3zy_ilb-MDT?$YQyNzS!gIM*7A-{$W2O9~K5?3H$iA)1=Oa9`(<5w-Dz| z>1Ee9K5G&ThhuJL)j zSeU=(ZuoF^j&Ay7jOI3cGzrA(>A#$n+^25&WTaVleK5D-Z}>=N3TK>j#_srdmRQz( zWIxWEIbNkae503reaC&f`~tW)9>J@?E20j~mW+ZSNuh8j&Wtnb z@^}K`ry-U2$#>e09|76tv3=ez`keN*OiR3+($}7zrB!I(C_S{hHqeEhvyi>X#;j{O zC_NqKc}+N+q-m30$smxCPCDn}`OMH!u-x2sGd)tUzloM;Qja+;{R$J#BTW1$g2BuM z+(PF6NTjg!)qP7ikN>``Svlsq0f+xMf`tPZ&Ph?^lS3YTX}>V{UtVD43Y)QCkGpzq z3}rmqHPipT@|V4I#qMYXb7|Gi#a1iQwI&WLGnr5657VWp}CH&2MdF{wWu=~E;5^?>T=cMF{@jlqFVr#IPqE&>$>3x&i zS#kLgzP02iq{6@nE&nenPAA8xDD9srzW@$aCABb->UpkSc^n)t^GB&jRpmZFD5osi z|6NIT6qmedpSfuiRS{Tp^_)ID7nCPxHIIXH*?UC#Bw;^G`KcyqpSYrJiUItYT@I~s zpXpC{T>96H>ALnOQFFvTL(SqNw1JzWEB*W}KU-pR)evy@`4kHd#^MJes0$Z>ytrh@ z5?Q7cVG$u!Na3-Mwp6%p-}IGe+~D}QUsXGujFJ=od+6zEdUhX$*czG#II+#;ZhYRV zqg-y_I_qRfegH-DxDX6`E<_V!Kk{*PiND}Q%7*}~8Y>M`33*I4=a08W3yq4lW8Wy& zMKp`PUH2rQc}79lUrP0zcx^E>zj-&iH~aP;ac~c!pP|mpXW}LY zc$$J*6ZDT*YCp>p19l@|T|5uBP=|Fw zaMRV>+gqikb#!GZzB1?1<bYN@1juA<&_l_BnN% zYxsE_g0kdqP{*6!j3Obuakye`XY~^uAz3(<{8NU6% zy+hVaqdT`(_&eUPh1J+;(>-+QU(>jN8Nk^D25HDah67C1ZdeYWT}IMF>Mvz01AYOP zd#lRVa;l@=g`7(a_mzbVV+NgTrOLW!+3St+NSjRprN-$E77lY)iGc%4&aL;{&@Ful z#E*sFH1O=_Y&H*Q=>5zp@NF!{?jDAYNi`Rwhx3pYXZv}i1A`%D4ll!r3qaO$q$UAd4P&>C2ny}I<{%iS2Y1Drt-%Gf3N{d>j{0zx_-8pVZ`v)wu~%m3hOX zLdQPwPWeQ&y>r4U#}x@iXOuKKDNh)xOzsl96M0fbglYinhOP)z`CW115q>u0#SsL{Am0Jbi*nBmSVEw$uH4 zwHY)0j^+T+k}MnF?qg*;>K>;XgW~-~V-n?5k473jNLMhAM0(1v7?uXA9O&*|UNx}d zsP(jghWWs7M_cV`^1&Rf_493`1&_K7j<66Bdk#-9m|o9L?tu@9Vnh>hye?`T2Zu)GGSjHXJ;bv1`m(ieSaM-v|!TfRWk zSYRv6oD@R6K(OO6)#kE0et5z>?GHiU{pAH=sm=XH<%9{gYrgHV+bds0kwU&31=qZq z=B2hunV{bohI9#t4by)y^eH@QI!Im`RcvwxgMEuHfx1CQBewV`JJ;rdp4DLcg_1n+ zN*xY>e59iF%_FU>2WA`4l%r5`Y%1E!8XP6ABaFbYO0(%e5T#A)=H8`1=88tk=Y3e963$m3a>@NcXR#-T%S^$3NAC5 zI6WX#5n5)lKu|Dg*Y-%;RD7A*Pu7kYiyr`_H#>M}m+-?lWa@0jJCd+${bFO^Cr7Z> zSE%h~hpA4G4!MqFeI4~Kc`AS(BLq>eftrNd^1e}1*7Ne>9$Ai@ zcXnproaHEKzt9#XgA(k2COi@ORb}L6^wg&~qJ*oj(lXsr4ddnUg~~;rp?4?)u`&dh zocHXi9*Pj+454%MW3GYa3spL_`ih{YUMu^hA4dB=G*D}iVHe4B(=jF^tr)Eu4y~2R z&q{8tKrc+*Fj$AI@2r)%N0W2QyTBwy@`3T^*136u>`q^G5cP5j%(4MG!$r_&UfH#i zE;ASz@VCN333>V!^^NWF*wH%@2k{9Y5z02VhM9;^B}##AGKcs8#eCpyjuR>@>0y!BxR@B8pH1+0iH zae4E^R9}(wwi2#k*^#W&uBh*85lH0EPByI8T zFUQSt%_ZkkU{{B$-z(-aYz`_7MNO3vLkch`y)Jz==-_fHXaR0eeq6XqthfjYji0&p zLu(rY+h{M5#x%aYlg=GRCw~X*Kk3jAsKjew_=@vO3a}^Zl@L^SwSG%+z>~XyzWYk` zm_=}AHm!z%`~`RWdHh5~rcusFY(mpeF&U6Xd{ojdbULD7t<$Q0F4of0_S|5m`WU8` zhIA%~eckfHx!S{sv0JcQ+_kCv;c~F2Q}=W(jnS=PU`#Ie4zK7JJH`Z*a;xhEy#4Ct zIsF?&(Mod%N@sihgV2HT^-q=Gay+>>My%*zsvK5fJx&)!RxHfSd|Rb&Q!FgsbT}tq zm~BipW9jr_I!Nj)(~gC{v4S~ljS}$hy645r>s)8$(Fr)=I1`$AwgALA=|w;~`*{!v z;NUVy(^G`J3@U|O3i<&`M~*X&WDKEwd@tsSnv((-=&7)qV16swKPv+Nt2)%e10`D! z`gzpr6hkQstCj&&o!tu3=*091<>CW|{;fWp%2KhTW73D7)ykUGw;V3#qHhJA&urwB zK1QHPgC89WS!c&02-6iDl0$-Xxgyy`+-u~Y2{J9iIhG^co_v7v^>3^7hG3nxjhf5@ zEIPTNkFvHscbQbCv8!KqTNmNwm(`uWp*z3uvk=8sw+2j&CZ8fId1sV_*nWE=>x((6 z(AI=|Jlb?NnX&XB{CHDd%9p_8C_@yDpIB7~tHzR4R9!a-%)^*!ifP>q{pHx<>hx*E zeWR|&q6|=D@6HBjqPl|GRHlzT4%3>#mbDGd?+ZlspoY zxT*H=8dD=FB63Z*GVPEh@)A5x491|A3DRP<-EWc#U_xRqD4k$oKthu!0zWe2RKeh# z22dzO{@|1Kx9Q7xPBQx1xCz`%hDTp|3;nUTG-d)j>NBTZTzIOtK<9R7u_vT7JY-WE znLrcmsHrg!ESQ~%!~cf-f1aZ8MNk;f{{oU$S3ncN|9iCE0{#6z41M?k==c9%N|AP8 z9sh$VNkD^t{O_%J3V8SbTuIPr;B_GX{X%yJxF_U)k6Z=dI)DCq%o+gi0Ym){g9$vc z`>BN%2q+;32nZVpDD|fj3J0+4W97CfnsDm&1q0WN=f?`I(U6#~B2DHyhMMbOsK>{c zp3H(K%q$Vb?+463?ws&-r4{Q70xvl}we3VVD0wb zoXXJ8o}x_*hFZAq7@H)Xju_UbUz=3DXs`_M)T*p4{#J$la&Nb20BHZH%+QJyes_pl z-W>})tumIUdbs9)Phlyrn50{!txBl$%{}dOQL6QOD@~m`I*axV@tSiMfDL!ha; ztz(lS7ZTJJ6;;lGC+9DypBl7I^^zIuiYyitMP&~~$k{5|cCp{gRBHUB%dP|&76~Vd z#o~%-O{JrOkhZZh1m_wJ*C4&RF!7bDfI+_J=aR)_^8}5Yr6*@B=>St$+?O~-x*guP zNjI|H-cWoh0P-Oc|6v)-4*`0lgfpiv<9Ds`=iB!yU+G;pU)DDEw;21@$Me;Aq^j4N z(WK-Q--;XA?XCqo`v)iIml(S{4nMv-`@jlasF&UM_uu2k&J(@1Z3~~uTLqLqapOQ8 z2+#G0Mz7CMJ=~n)cmQhNl^0&oIr8`Sw($&YX$UB2K6mV!r-rVa+SzY_wCY9ef;GW81Su4g)W}0)E`7v3%(79YsVpY8BS z8z|%U-%KhqzPwmpoZJYEbk0HoCmZmR+UTGV?W+Bu48V(-C)OOyBrIeJm?kK(G*hlY%Sl+j#sFFCr~@kdV3 zd?hvlyEJ+#e)TFUeVS`AEm*vqe(@V!zK@H4334B)yV-qzLy!@B{q!=IImMFTxo|(N z>sOSo#?BsB_oiDkQijt=X8UI^uAGxU8>@VA0hc!XJJP^c1;FZHOgV+t=7h`UAOY+t zb+WPeS<%!GIcc^03Ej$5pgBe+&!5cY=nCEFjr$CfA(oSR=3n`I;tEp2LtuVf@=SLY zq$@JFLJ4+YHu{xr3Cjh|-9%q#e1SKUq~aj@vB*FHA%9Lm(PRqq{=sG^fgrgNu9XA# z0J8jru_0IqTx@1vgxX{rOlw?r9{=jiym?Qman_;!f}2Ufs9V4wkT_1&WXBAxBeGus z5^#XPv6$cey{2*<-m8%`KsXA{A70<2Mqa8)Kwp3=!0Id4z}N`_HIlHpw$T(bm|dQo z`RIYg--3tTl1*7iDoHkWH1uUQs}v;}5Z4j<9zXVk!D3xB@^3`GGf;wo@4Jo_URpYW z^>gO_d29WfQtw+;dFw1DQRV%3P)qvF;D#OUKy~qNiQ~E0%TIGT{!?v0bi$Ug&fj=z z_;aI-Uk{4m6;R)aVb#c9K;sF4FQ#ySThd|IrK%hna1D?G!#!hVexg3qBdj!70H2L; zGq_ZNBsvv3E12hOMiQ6k-C~Kga8O*)96aK{{@LrTb=hmC7%VBh5o;*WPjDFQe2}pz zqqchm+|(^Q)N>#{;FIC?!_>8XmGJy(gpcts^ur*IK_?bhe}?-G65Ie^^~-)u2W?rK z_TS|HPj){kSmhs?3}Zn;VX3TMfEl5j1GK^jJtoMeGVDYoAfR3cavCMgD48ZjA0IZ3 zA3IN;FqlXZkM3S~C9i~hz#gZ_FWOFb1_dWI-qa7qC33Shh}BhjNx3kC)jD4WWb@ge z8n=8zNGolg$W3Tn-BYEilJ<6RNL2o=fRgRv)ZW|_NE*H-Qe1=q6?JqA;JVk;;$k(h zEwUo4q?hJs&G%CY8ymNfN6jqWyur`-lvqfD4$JIrZBdpX;hJ)AvX5y?hT{OgMKUJc z0c_7+l#LnlG}A9?n&;EUvS{O7!81hMRLG_~Mzq z8$`Q#gUY&1^t5F#0Ro2vutYa|O4E$L6Cg@Qes$Ld~+;{bh1|11hBiqhzXs(EJvz%Vxaqi2J2vki{k zPkxVcNg&9}N|+Z4qhXplrMrndq-CsNB-3H4i#9&LdvxRM+QI&y{A&G*qS9|Imhfr}C^&h-)QdCm8dq6XBD7wTPPQWh7MH)S*Am~dv zzjsu-PpQZM&2?TCz<_&Y}ScJeGl&6vG@d^bd%hyY% z5#$*@swxsOuATAMNaM!QkQ;=#BSQuf(^%R=kBRa9L+*S8D$pbCC7I=pRLU96VNoee zHxT3B{!Pu^P5$F0Tqm!D44o#Gabv+KI7=Efr9MWnqK}dl4Utxkg17|G0b>X#a~{#h zfXu`4Tc`H~FeOHqf1w=EE#!77phHD85~f|pwb)KNr0tRTBERn5aN(6L35L=)tX zpPi80IyO^);IfSB$=oWT*efikgGTiugw0#Rru^kFDWV!rRc<748?YO6 zpS}BTdXKZ6VqfA#vQ#8;g#wFXtO#OWs*?&x+BD6# z)=f+bP|q)|10li!O$m#~i3QI7=Y`N}l`iI~hJ*G^MuSDhjR8?MU|vJAiHkvWZ1gdS zR8RBzoMlWzl8aq68=Q%?N>iFdV+vUJb{T4X+c+;Lb{=)*kFLk>>I-8GeF-Rhl@rjM zu~a0^Bm`B>g29mn0>51&YVYe?Enefqdia$9NX~>LEHzh`Y0C#hqcm43Dh&5)xd&l` zxEj=8AFzTS!w?Ng#x#i`{%}`y2N>?8r{(z3y?+AW}jD z^|yW3&|VwSqv7KA5f_PN&cynldnjdtEr_hzP4UxZxqlsD`lzA?+JXd33+#o3{gLSh zxYK2TT~3}kqmf&-Sd+7O6B{68mrmK;BagB^bl_vMgm4X!NW+&L-~*RRY=WPFv^j6f zNADlkJxmST&6*ZcMfI#8dCD}sR(W7MsX z+No|8sJ~m#Rh-$%(fbD6Zgh1I*{tG= zI9C6%f-Ro0Y&FvGLt~HKKOd>Q2p=mrzsHW6x$&(ek9Cq!nZ1NOy1%Y*>aCLzk&N|o z3XBL}1ymU4_`nQNrY{@NSF&1kz|&UTqr7(Qfc*Htq^ujJ8(~16LauoqRv}dbFmYG! z&WsY|fWJ+q=hIlor5e5I@-Xufs^mmyq(_XwlT!2y zAOkbU{D#M4nH=3Mz_iG8CNNh5%Kb4wi9*z=Qelra zRfA;)Hn$O7%O?`!?r#EkYBz@YqHSDd01IgUsq(|7UrOm|2G=#SW_I|JDb z>JkV=U5$G%q6&*yhEP*{v^NAi2O&{F-FqXrlAbyxKDhgtu5gJUZz`kd2LqS&RHL(K ze*8_T#TA$dh4BT;R#YwkK!ISuqP}<3anzl#b!||3&7{bLcx?_To=(6cv}tAhqUwaC zSy=9Dcf?NKu>2%u!nB2_MByQfbRDG&U^G!Zz7J3gM6+)W-O>mE{~ugjo*@9CQzf+w1){yl!G|iVh3-CBR2Cc9j%5Hi5y&I)b`-HC0Cf`{0@4r{_sS zD;~e>t!PBiwSm0r+1NZ~lSKwBvI8MhVzKgc*Wd5iIdcGL(8O87l$OWw6V*v^QIadT zwPm;DFl#jStfyGe9?QeT2wwN*s=n|JaQsCrXoS&#L~qf#4=C^^7o@# z-<}>yHg?@RwO3Q&pI-uI00oEGfI!hY6rz8&wz_8pW*5uZB;^>AK(nVf(wc0sD zuc$E6HGKw=`4pS#|tb z&|H7dVm$*>0yrxD7oO|j%vgCvrCiIi(*?!n4IHVQYa|PfAal8Pd}RqUu?UI}aUNo^ z*T_u`uq4UR70!1w_vqDN439KV$8()<#%+M_;{8IP3!>&sk)lJrhH&6-XWCfaRR{Z0 zyt)d&PNT(88K~Lj(P-~gbHhtdBG!= z%Z~?sih#{Hj)f~#;qN+94U|QCTwD#O zQD)1O)bD;l%OI&{n|+4=Nd0tba@{JVC2KJQ=AFI&n?7rZx&l4+rNg7Jup3(wT{rCOLp#OvDOJa6Jwt z6PNr6cwA+f0Od`<#2B!GpznPgmD0TX_p`|3esG60mb@K*t7-FxA6Ecs%S39b?C!U0 zXt>snjC|lgcZXY6ZW|y#z;rw~LMkLhyy4@1R+zv{+tXlZuIX6m2zPnz!tjTx?pMDd zzx3($QN~ZW?jnCDesmq5KfI6q0hxDwjcgV-H-g+29SAA`NOR*b?;gSN(=_zB>}e@Fi>MeHT!PVPxdX>dX9tlNUW*KOumM2O6VOtirC+G z70!#@X8l_O^<*=!(B#QcQ;b?Ol+icepui;YW&c_zNHrc1-clIr=Ii4Hwo zR32vmL3Po3c!2R6q8u?_vpEYYw!PXCG=I>m!QlG20)=D=L)er$-_QSt(kymZ>i0h= zpm?iw8RJV%&Y^$Q6gp*07Qk5tU+!Nz`RibEht~PcRCEAA$)=;5U7TQWB zY3bbDOLuNhm9scEF-CP@!^PrIH0M=PYNTtTG??)FNxh3&io@_V&Qmrzk#hyi)F`)& z{bg@K*oZ95tM}SUB2JdqHLQU^VVze)9iOiEI$Qvq!bKNV%PeOGz*N(9&E(U4c?$<- z6E-%BaWpn8aNUM%=Mv9O2t&>N7R%b`sLckI)n(^?_^A1i#!F>(f2keA+Ow8T$iLN{ zgq>4v6K>A0g`dz4|1i^0z8hTqbD0?&KQOzSkG&XS@B>6dymu`^-?orkxObu#S}Lwq zdsEJ<_@Kdti464!XaN8(b=f+7Fe0GJuX}{U1SMFM$4U_28@*96zhc0vdb>%fz2kg$o9&>6Tc7*;Fi_j=mIq(<(&N=6I<*twGUEkf}Z%N8XZ{cT6>HD1TU|C#`nK&@k%~4eH-dta+ z(^Bzb+m5!oV@=|+NCsHtVV^dCx6)1R0-e5U;HaBr7jlG>7R5I%IHG9(y#3N~s19qs zuqk~U^aKk%;GfTf?RPtd(jQbB?IwC_*UD(y3l!0d*5^BK!*;}_Mx%Y zr+>0}oX5JL$$FY?E8MSqBn6{WBQ~G%rOqWCzkZ%h)KlMT;(h2dH@m!L6<3V8#(eDv zo6%bjf8us=`kOrB?TU8Dv0%e#j`xpf^G!FY?`iiR`05^+9K$MPi5U&>K77I7@jy~V zNxCUh0K|D1bncYvETBvZXot1z1(4?7Gb~NT6MsIgT$M1u=j&|DZx&Y)G&X|LoQP^s z+*492tP_=&+7y;QU8^D{6OO@2DO^2}XC?a0r=1km*K@IO{(2R7+CnbjBDjegD~Y!g zuAMZAL^jSmt5sKr=s4(acb!Jh_}NQKDP$7)0uYwi7fovm!JBvVbMkzAc?kOk)fZ;v zI3j0~z?p_Yog}Q%(U}@*SePGNCW3w>)3&`Hz;fnxmbhFXLKIOEU>Z;XHP7x z3UT(QW8F~fZziYJ#xxpmP@AWLQ*iDpmS}%vFS>bD3Hxs0$l0Fe5su#lnP9`Azg7(; zqv}MAH;$;fC(v4{PEZX23Ceyt=Mk=I0r2xwopSEv-J9fYwhUuxX^2MWg+112F6@Mu7T7udde@jE$W!0IVsH z62J3bV-?5zW`K45Z)*oFNfzM7676UbJ1XnlFtr^CbxeZDwIh+*a%~a&Xs1L#uuSKso&_5-?04iy9Xws9;nkL67eVIx@%0PVk#&OjdhKVyK%q_oU%J zF6th8w039C6Vriyo2t*{EQ3Hc0|cZw^x|nUxZ$K$-{T1_n{gB(8q`;#OjCx%kf`2b z;5^q&4%gD7O8^&xa*lzIq8XB80CS5IbV#~;L$M^QL{qSsG?#-Y;n0*R)Fz$@!cFf>VD zO(Jwse(k7%j-qOx69XO9-g0ifaST@ghdOorwIFY?ketFFk;>i#qKhpI&fME>;gkZ$ z?r`*1PzC<3*WgL3)8=PP1bil)>2RU?br`6Kc7bvjs5U6m-0Y2)xpS~78496>+ACtq z>{v679zs@@Wp^c1thxS^VZ^1u-1My_M_dl>RVSfNK_+dPH&GiQ7;m99lIZ$M9nL^0 zLxp>3IYS?s&j;iL5UQB>C6)i9mr1I|(lv}KcA(32Y1 zAv8;{HF+Y9zm@N7zaeXPwQ3>$SO^DOY&EJVX-))8!uwc$l3=qJoi@=Yq(+5vXY=CV zB%K>pyw^d>45|l<;4riirLC#O7IR^85a=<_<4-%y>4X_ddT|uwPVaq*OQuF_w89Zl zW%H9#sR#FIGv+?t13t-LPfBc^r~R+b0`AYOp(hVN;FzpSE=1iglA5zcl4%VOG-oWd zj;i*_p_13+El6A|+)JHCldalo;ar2T3`xh54z~Q`yV7WX9Q%s&V~&nJHFYamn(Wps zExmr~`gId$rJkEe=FeqT=8k!ok^g4mpp%Y*bGF`cwK`XS0i5avND?_$yGL(e9GVkx z)77DvK~c3mAL-dyU2Mti@ur-*ID$o$nG)1sqUBrB;vS3E;8OnW@;^9)u2}0>lJr?Q zbr)G1_*#o9BY;oCq^B2}MVPB`v>lCEZV($~qneV|Si_K9s%bOqYtVSNZwdvWSDo*$ zzu4fd6pm1^OxFMI_h)+73>X2xAlUmgBJV#qlInHidzpskqu&?t|#uk zFsL`XpsOlD?8PolenxR;m^I1&f^PGA40Il1uc`NdT#FeMX zEq}S!+=kW`oG*pDshvIGlavK5QHdQ4`VGwbSCCCP>jfY%BzwvP?J)F*-qxz3Jacu&$NlQ1|y%UdqB3c>fB zT{D;e$ByV1?%ubLiedE3+%vmH07mAZ_8kO@Gi6Kn3@LQ$=6t%#-9;vhI-__VJ-imO zlVZ+nG$iU^wgz*E0AQ(NtbSzC8a1Wv#V3*%7)o{J@`S_nsE8DOHbK^x!(r0AW__mk zQi;llyJcx|Fx)oB(rG?N;|s?g2jg>1*ah0rl|-*`m@5iN z09H?lg>VjAdq~R~HKgL1qETXw&1yrJPpM&RW3AVv$-RniVfN?e(e!4bncPk;_YaI+ zhQwz7A*MPywy4xR&@X6BMmoturvnSxIx(!Wg#e8l7A?$$xaL~&M$+L4p)qRruYMRu z^^pt{=ZOb>D$%))QHeJDqj6uu0!Xwhz+EPXqts)&5*zhwSs`^5d{bjxZXxuBYz{+6 zoK6%r^}~xxUhN^GmYXF&s#`I+kd{iUzlO`@7$TFC-%^d-^I}kgP;6^QT&(7 z(%y_cU2cxcf+j~Ou1)cv5$*IM0x?M7X+$%tqbhX&_XG3l*cxKbpf_AP45_;qfTka^ zv+uSIyHK$ijGlR}y{!-;$n4rZEq79Cc^Qj>p&;?D0;5JtNYQ6Q*?`~zYP!$rOFBW`8x;9emC705i;Zt_dP5{AN zBQ()g(%3=EL2vG*V-j5|O6m&%@S$_<)8j?oJ`_D4%8Zpv-6@LmbJ*Yy8DGbXfW_yA@IP*US!B`J=E*RHE%5QN`)8NhL|k$ClAn1w)25BN-{@ zW3qnhp85+@XTFiup@&7W2o=YShhY{h2gYM|qh3)rV@WE1ktKYTKZP6vP||{*OIWlZ z^$Y}B2*x?x_b&ub#d}v=Jw>>+h13^SAgQ!_Mj^R!F;Vkm*}ost6+uRD7LDI^y51BO zid>z&3G}fX^1)qxw!(V5j5Aujpe@^V#FH#n(IX6Nv7D?w7xCv|jM6VJI;VDX{s59xcIf} zhQG9-*Q~nR9G{Lm5^5s|zx1TD=O@yLv*(%=_6l<8Y?Lnbx6(Wd&<;bR6gN@}m6S7E ze-ei|Cs3qi*B^e=n@6Lqp7XC$EL6DEvhg<`)R3D@s7>BnNh758uEY$3 z9Vp{iB?NtE48bz$bzod~6=} zrdp|IV_wQ~t)*K71m*(bE6y9agg!w|ozC>+sXS`PY-UQamSIzuX7`kg!g^3yZfPo$ zYfDTjM1W$2UB==Tdy<;!DC-S=;YeO!q*_ryDvh(jR(VgVbCqp$*HtMNbkV|vDum_Z zuCF7{H1HS%=$GatrNob~?7tJGupV3C#<#ETcjZz0YRC%${xeKAztC=$oKz5%#27oL zFWpNQmT2Cyti1&nSyYLF-ZsPapo4Ct!q;ZapGw_4()Cag5GUkaBE&Or`FpddM;5EwkVzvtWI$h5>kG zlg^dB^t}Nbbu$V3&OzEkzj|57qfR(4Ga~HJC3i4eXyoIgXrd6A(%ONFv|kh7E^Y_0 zl7#>3I$-o3A`#Miy}9mMQJ#N*LmFzKTN_B&m85&L#g}Cq0%`S!4yZy@$ILbg7G;xc zi+kG@va)O2;vb#$-u&@fkO$aH3=6hTEODM-=;Q&+9w5)u&p;nU2%&#VWAX1wE!rmQ zmezFQIKG<;guWT@z>~5q{%8dAb z*gU0swgKx;Omb zJLDBN*|s8HVzv|QLV=Zbk1?Ox&roEnif!rUmO{CiR3@qJ6elB(Xoo&U2SNo?%fA56 zUv9O^6YbtFTYuVCD_Rd^jb2ohZfsJDV|Ko7yBUCtZA2%WhTZb?MLjq%!14PEKCoYy z%IwNe$l48_t=?sC5;rQrdXW8ekqW9II*OcvDHL5CEs6S#5u&&!OS z0_yDqJ?ckOdm@Spv2H&fy?%-H%Mk%6saNUZHb25H*a*;iEClMUVABIZgC_*WhW})c z^kfYht*N)kJ7%N$>+OYiYfRkQ6dD~VG!IBfT?~7x&3rhEri4Tl6>tY<2=9xX9F`lzajyo+6gK@ zw#WyIZdebxz^7St;XWbQw^=CB^Epf-so7P$GK!|qte2wRoz9&gY-_6do8=0Fgb%dK z&I7dsUdJqbk4KE7)Nk-}dUVuGyhC)iTd!0E@^oh`Px&rNYRg=iv#j*%$qA@WHOg(j zYwu*6cP}pq@tLx?zazYiPpm>J0<3JZxI^geG*nlaMz~jG4q``w?_5h=r$yD=)FR`u9|o3 zk+-OF&-qckTF>jUP_wr-@-u=v2|+41v>N0q$#u*&fii%L>px?r4c`GVqkJ}u^UetL zQ?&J|Sf%rsqy`4B(%tgFFAY<)Hp4K~)&-b&1z>xl;L`w- zZA}u7_Ba;M%MHSgUKK!oaVuBz-81ROLc2kGm5&5QO&*sfWBZI7@X2y8tmQQYwRZ9q3nx?4#ts(OCS= zz0+3q7>jVhr@wyeyz;|5r+YuX-Wd49`sAaLv-z9H7Z7@rNzyr=3>wwF1$?xma*(kf z9}muUEGfXg*nI#51!9ir2+^5>s4&uq9vrzG)^$n0v6!RY#6ddZVu`92EDgJVPWpu( z2-*Z(j|$BK@#DB>K{YESe$Dmit*UG0#Gj7pZkD;E&)e>+NsCJ!jjiw?mg1T|ONCL7 zTJ;l58rZ5|G?>{N`#+jdKSN#i(_Km#a-C0;K=@JkLx_MXPE@#r4kFAs)$C)f3Ky>ocPYfUSEn4mqL zYj2-Yf*|y^m+6{{&WRrJ=D?&<73`sskaV*t^xH(Yvjw7V@fh+0cv}S_a0a~u%I?~| z-1S;>X(|Dyx8HF!_Dy7k2IJ6ipnG#T__7xp4a<)YtuhXkcuqXOCsjjcz6zLaVqV0;DbR=nK0Tg9irLF zDk1S$mDgPSk~f{*}92mTiml_-I9Aic5*G^Iw3lY*xn zzFF*4v^Isjz2?Bq3h)9@10^%{}!n<{mtjdH}3#&5s4K?+0&^zC3UiAL+9f)Zed ztpX8TNn}NBY?EG8|L5(-NMC5tRG6N*)}xKHaUmuIVE?&pLo}U12MDZPxn)XzEp{s3;mx{-deVhA850SyCg3FY27AbBbL6ycvh+Y~^j};kdTxGlWISd%e&G65o@Ox$7D)ZIA-<5T zn*^kQ((rO4tk^9?ZJ%JA0;CT5?7 ztV{p&kvSmHM)@hC^mX=<6}vq^mP)C@ytin=eJLtE^ZOA4L?fbl%__Fvy*URPcwf{x$$W_Ka$Nj-veZmQRy%s)o z_tEj`CS&rWYT8ipsYQ8hrecQekOmU@H!rzB_Wb0UD;6z1nf_2(S}bMT`Ex~aS9J)W z7L(|q7V$t!e3FoJ5`3=SoHIkl4Zh4PLNY$Kq^Vqk%)jC2(K^ggtL`S_Nj!l!@r~#aZH$} zE;dV9m21QS1Yk=Q$;GAUA55~Ji#>)Pso+DSnw5c7gcH{grxS9$9^yHt?n`8p%R3@v z-dGdI`Pn{5dJw?Re!JlFsh<{+58jXTtDw_6EFM9dzZ8{(xUk?poRIY6xExP^Ta<>` zhbcT6M{K~a6!ikNOx*2WJ{XAFAI{sd9o36?toQw|P$FtYL}~dlx2S!uiznF8A_trM zeP7qb^}eVfc4is6qXlLtEFogT{zyfaX9{1j`Kr`fB5x{Y>u_SZf}XCuxe<+%QVk-w zm;bNVj{v#eRzUy)vPnIE0{;Wh^m5u{MfuUo1tF6QISMMF=}mB-aXaL+tw?8nW}ac; zSuGSKCMGBmPeI)5knZ`oq6I?nUX$=FWetY{iQL|$eFnFwuS}+16C4RBZr7d&8odjl zxp$ssOvjCFS*xIKJa9KNqnK1-K^$=IPPAd{0j+iW>%h6|(ax?ejqnB_0JvauhasGV zCQ6XEA=L^uxiP1AvBQwjk=5#6UZZ)4SDG?Xh#+uX8544?aZ$fDKs8L8bK~_QhmUzs zV8{`==KgKH#A`80JxPTlZD@4PzEhkrp`L{A9B`>K7rvY^jjX70WXNP_pIPWK_SP+O zP>D$Q#EX7(Cys2OG|>ity|!xV#HJ5BbTB_Orlm$Q>t&v3r`Zjc)b)f|G{iksc;%2W zYM@8>rj67?Nu`rMA^i3rc0}$@A*d5g1iAC;OM?#frl*^lV@!FlXU-@d9*jEKw}h~- zL*0XVO7KVD-f{>$*_ry{vHT7J9>tCpjaRQLCO3xy- zl)iO;a*={&3=gPvLdvvYU1ZFJxME*D^3cYxLx5bl^cD+XcB^3O3;m4xEaLKgeHFT?L916+N7uEUb@FqaDSXCXty;lc&w|dHuI5?5qUD z!2gl;PSKS{OSEuo+qP|^V|9$~*tWA{+qP}nw(X?jj-5aEocB(@t3CF^x5r+y zYSo-m;7FT1JJ-PU`e>r-O4F{xO80vEc|5V50=&)*minAn@|V)0#5$mkftV3VLQB=BN6~)x%&XqjB!L06?!M>djN4iE3mDb`N?G5 zD(biF3qm0xwj1T-OVqH(4XR&Jh(t~hO9KobHWY}#g#tf2`2GfUQM@MZ8haTW6eI;gIeH& z+#D9D&}?8c>UGc#Nh0GdL$-Z!UaQ0K{)zl!U@;TZm%^?r*G2dchaYhc?VM(q&VL(~ z_(>MFIRrrR+olueh$M*rjf=N&`L6|GX^94e2`{fWcmqZ{tiSV)JquhtFV`UIqzOI}D~4e2a^=sGLc_$4j{v~??Q#Et7H&P`UDX7t`Qbpw+l`aI z!_8a3Q}E;IMSWHHWVsZEbJIKZf?=1nv)Y9Oa%Y@xeV7yyPB0b>BBkfjo#3sD6Shja z#}-s5_$NCM6>La?&8Ook>kl2Ltil|`Z3Vp}{_(JNxY^%5`kd>7oe)oRs=6+ir>ThmA7@W~%uxtI@4as0$oGdg% zJQ4O8>U4KKU!L5#sy9?D=x%4~?!~_)!KqUqY>F1M)EL3V2}g+v)k+G3Q5~}MxlJXY z(2TGJ=R>$0Sy+zdIF#t=gENy*>)W@+he1_R3BSKu9cQHE_VDBd6B{Q#fUuBdQJn#X zhFd`@?I-z!nu}fghhd(WvHuou=n24+8n%7imO=xJ8aUSIV838gH8=<~v10!Ui9yv> zzP*coT&Fe`V`v&{KP(&;56i-K4+;3ZL)|a`$*QGUmoy>?6GO3SEW=cdR6R&Ad61YsYYTDY#dXe z-pJX@zJY*?>Z}YS54`eFs~|^1zzjKtVi^4qF)RR&lPCpjh?Zin!kN+n zYtj^#VB5jJV!GYqMz8Tim22Er0Jf~mOk7&hO3W`fY666jwBSKprP<14b{mu>g%3Mv z!1-G)_9PZ{+r}3x+6;`x)$+&tR1rH2kB*@?@4dXOAIZV1H_9;39wN1Fsw$R!;?B{Z05d=rc z3_`%dI1oV5QU}+E9Ktsub-me_e@N+bRf#R|qpmt~5O>VZ6_)`VgKU8{+xiws*hd

    Navigation

  1. - 3.8.0a0 Documentation » + 3.8.0a1 Documentation »
  2. @@ -202,19 +202,20 @@

    Lno~!wp%avI2isi~>%sVT1SloGW8CBgGvO>gHv(>l`3s;H zTD2&v4kS8}gC_XEc^QDj8VKgOBT<#_8&IrTBxXt}54r0!`%n?`Om1mZCPV9ibhJ+W z;0qoePl*|68YTg7tTajBC;FQ|12EKHcVnDn=$+Q7lg(q+5GD-)g8ElRDeupuMnt4v z7$TGks3M#cfiL1o=ja~o}Pra^e4)){}VcSUjWY`(^I7U>HJo{3$K>YO5!w0v3;S%R=WI# zBu)qoC{YT)FDr^|8-PM`8?tv5BQ)liX-~&9c~d8choTC_ahw!mc$!tJ(?f85U101x zw#nwu`#EYa6zxUqNMxkZmJ+*ZkeWA&s^81b4CC%aKJE5VUi{`ilviX4`_Ohzs6554YLXZEY()G;fmV^H?ocU&;pE(-wliR3d`B zgt+wB6t@v2a%t|hwaZ-ww!E4X|N6R|V$vxBlgpPaoqXQeDgcX8%XW-t zY3Dx1pMA?sPBrU~%dNy?@Hjn~lyYSQ&TLmVT#L?GEZpZ=x0aU$rfc3dOH!1Ne{OVk zPpkD*fMn_Cs{1VOXCy+~$jloL2~FG7iwwyTe(|VagSX3{WRGwe+|UplskS#AtfAz6 z&06>Qvm;gP7JIx=r1*(RhRvb$cP7c9wPoY&IC+Cy2Drk`J1H~qvi>y{Ts_YQSVml# zey{CVZ0T+#_%!omXz=MsQBgUhuog_CS2q!VH)C+be*_41A$( zH;)FM{1ht3F3JTnnku9_w)u2eugj!t#bt`LDu5qgfi^~`k!<81Xa?JB5gic7P=7{k z6{Lk8L(p{O#pWa6ufI%qG;?tQ>{{`xA6V@niYDt}SFr{nK~Ihi@X?1`8)8M(oi#D6 zT~JQWonrDPn%rA}T)(y9o48?Bkbh~@?Yo!2_f^3 z1`dn>@rn2!?sp0(0mRyWqg?`s^#Ag~eF!1KLI1-CpH57u9;*f2YpNb3!bLMO!$WB`06xB78Z)y75hE|>Ulhe^owt!mQc z$ZgwLL-QtjOiUKM*htTdBeO5Qwm*O4+zv-;@JN6-9{O*N`XfR}_22SI?LJBHa=r)A zGVg>N{C)lW+`4C{t9oMrjqAm}ufks&%`h$G2rMpnlL|P@K9RZM#Re@MpurTJ%wTyCi6t z|1-*{6(>=sNhv?lpnO6n^;@w7I~|Da7zrST{?)a=K5N%Z-V-n0N6(@s?#sTOQ8j08 zuJ@*C>;@FO-QD4JbiwLH2qyy8%LF20_EXYuPTV(uvdJ)?NNLn#@dVD)7V-KWhMPxB zw<-8ZzSe-^7llljT%X!I(I##*{0g=VVXUO`ZjRF$-ul&y<7rrkC1O};&S!8_#4_Nn zOU?ok!?9xH^K7h_LDsSOVcO^(c7pba-3FY>&uNzF!scYn*h@aXa+d2*9^V)|kWC?o zVvWo)&Xig?t(yzB6?Fc~50sH1YC8jWgq z+CgS_NQ#3rRzMrOj3yuN(nf#n6j|>0%VwnzKB+_gbGYziBSRwkcGprY!hsN#aS;#G zFIG?(nU}vCYOk>!8GIRD7Dv{RKnv`+>Eq?!np$M5-`-~NpQ}x}>Wm|YQOf{y$`R9( zot|eGk<|h;Y@&RmTxyaNJ%ID|U z&XYrGR>T)NfK!rC2TZLPuCZJWJo+Z_c>pVNFtrdwP6BP%5&~bo>{L6tz1AYURW#Sk>gH5o3 zh=agjRN)op+7ERhyUmN_rj;FlKKr@(=0pY-3)<1x9S%fi`v zMOR@8+yw}UO)j`E9>D|A`L>dc<_~qw2|6I!vh3kF6O$BKjpl9+dj6Eyf|MM%6OkVR zzPFi}Cd^u?m8+H2ZcEkd@ydVSb${9*Ygr0y zjP~aP4y1{RmtDCqI99J)F5fK-W%dNECJYx&(tY9s~t|?L`yT(=|vt+2b3U z!qdU~>YyP>N>PqCf`>Wnp>9=-!6XP05i!670nv4x|!HEIL?VVWvvw?FgJx#RY!@!4~C~p9}+wcP$h*<6%=$c zyJ{aSFLf^0%JKSuk5eb`KrJ{(6a^DFuV;gI8P^pI6N9B8VFV}*Tcs-Qv+5CbhK~uT zvS3+4_S-?o6E;9Pu~W^3Kw+$K73mH-Xj+Cimo?ZHbp-*gxey-a1125Kbdk|IqoD3E z*c1%~%cI>07pki1`T=?yq_eJUfmng?y~Z{+zF0)4;M<{E?zHv$Rt54P6>%cxyCPrsV>vmki08n=5*9ONiuH8XsYEvGt=ZNbuafi~~aE zj+jCN98v(XjJ1l?YxUZyLWt}d;I+k`<{+#cD5LqtJ#N{bfO?M)ZoQA!J7=`R z&QObTESi%BZ-gdg0Rr}q4OH=HmuA6nvX!CP6hc5CtoFSShgZI9SWaxIbth9*D^!<( zaUlC~DYqEj2yc@F6(7~d7x4$`1A3YzbZ*s)L9hTBd@E9_gj6Y7-K33ufWBpn+piE3 z#fd}3%9=L#Bh@(ky^nzN)TeEKX9h;TZlZR1>l0yub8@3UR1~KNl`Jyap_<)z1uYu( zn)(2>6N)0Ntc_(Jze(G8G6!Qb$2AN+Y*RB_Y`&~(Z3B1Xs|l<9D`(Gx+?ahJlCtOFAQ)_32ZZj z_F~C%2i1S~=XDs$d(D9WgE1!V&yqc?81C;H8TKRqixQC{yX~0ZqAL55JzmXl!s!?4 zu;ANda2cFB)OMbY9a36rYRD|YLp%!k@wia($536#;%kp83?FDV%`X1hUG*gMYrz4W zoSe*19%kWx{N2ZHR4`TRBxKB-O z>Ke-$J;1>kKM|Q^#-UU=t7xw+xh@cDxe?UH&+<&JW4b6vW)oVrUHr!;41c3JU04@h z;<_@xq{=}4ymVP8!sP4hR_M*qILu!Z1p^R-?6@EwHd^+r9fC@ zg+MmXuZdTkbov|hINv4+STT1%V`w9kdEIE^8 z^Nh5T<4pvSnvl*Hwg}n)CTd2z!M?Vg=YrweD9lD92UY>GH9_BjulCZf1ckt^k`ztw zUvB$@W>qacW@b;l0$q2ZYAqrFW^pyURzugWckCJkGHXKY%RFKdF|I?z7iCuKy234; z1WCKfz)OWxEwhxc8|___?xeCV)RX|vdatQwp1+qyJM?j(E>b`Txi zn29&2*^30&wW*cj`hL;d1Vf&`o!%`ca7Zbh1IlbOd+wL_pPU$}xMsTn37!4kA|{Ol z@G5o6jQ0sDLFF}=?R0o8d}J(!eCKeDhqkC;z=KqE*gD(s2(mjny1Jegw(;nbyqO%kx1Umn2d+0s zM%!}*WJ6#boTWM|_DJslQ1}RPI&Un6@M@`rcQBXR+oaIsz>$i1Cu*AXauWT^E3SEK zvU^$3CZ$=Iujm*^6rUF4buFdYQWr7XIh&xLT8?3NAic}8j5xz=hkvZ`z^|BI&j7Ti zf(W0O|BL7KD4=slL4bfR!2YAj1mtM!SgxvMS|4bmZY*J7!Ua%fHAP(If@?464v@xv)Rvr5HrvdR9l&$ zdm7m=ev4LE_rQkvZz0@I-2kmyj@XRUI!zKAB0iF~-%u0ZmWMz^ePzpwg<+Fm6*Gp7 z4nPqCdE!Sfu(XF%?s|X6pJ}zSUUURjpVy1ox0x!4i^-rh3+{qq!m|DZv$fRM7V=mQ z0}^;nY00Q1iE50cMaBw&sw^Oe#x~-dE443dIz6`43&?HlT!7-@lW$8x9#&2r-@OOE zjWRD)jac7xJsuka_%H7Uyl|!ko5ft8DgvSijz4YM1Vchxfnyp^s+s>T4tDvuA9+j% zaiC#tMzL4Juv4V{dZ9Or#u_yJ^6sGHW-B{EONK6@1PDR3uhCvYZD80uv1_I5#SK-y zBMJisP!nMK2ERc5_ve&i%LI`K|9`~38j@KLN}+*(vQv8`TYDMZYBQ#Z!8 zSIZnBoL!ZbsoDc}3O!B`3hfjS#T)3Q>rRDit5K;{w#H?ho~2KlnH#10kz-M7rHW9- zs$$DaX+c*G?ClZvRXe2`GVa?;tEE~HIAto@Y3dv42*iFCdD_Df-rI4h1HQTtm%>QW z1-(8bvVK=UXH{-rFVLLqe-FOPtuGa?$W{>(U)$&lS0ez@6+;GbWS)5om9k0FD9r}1 zv%WR1y{4meCW0TjHK>zkvch#$*2;>A)~w$CYy1+08ck1xlD z(>-q3$Um^=Gvu@r+xTOC&nr3FJzhW;X5@eEgZRsbYTU=|T#oPfA=M#E+#sG4e!hOh zoQGa3XI%m?VA0-3D(=+J!9Kk_KV7nPbbfb2s`?W>x6a<)WHKcTrcy}t>mA+@?Y99H zNFLCD3!v+Z%t)co4|-GJOff*Y(;L&{^G6ER7f9fU0*B^DRAlCgK;kuIGlfD9&kQ9u zp${vS8YLeFMQT>F35W$F_jXm-f}`qn1Z)e}0*e3`$li>Q1(<&|C}8|io+KjBV35uO zU*PSV%@uJl3OU@REi4psH}E3LG7Q!fjj1dpT6+Ga<$|Iqd{eLvkLNoLDm;H=BJ0bejX%*~qFl?BYoDO-XXufXUk>F3yODdbrMsRx zJcF2QztE6Fo|94$&OAf5F#EEfgN*&cXmdWJikTH26B~5SZZ?~BNjp^s)tl)3;Kh3`WLEz zQ%G($xT>NiP!fr*q*~Is3}BSRv}>lD8+_Qea71Hs<-tkS=TUeV64MOOMe16}KdVdB z^^j~lnhym)Ary%%L{*fer(2Hu<Q;}dy++blnn`XdV_2)oSe_9y*A+{*78&EQm=Lq{6W zLOgf6{%_z&ilH>QU08$yN^W17tN3`|;Pt~hu?M1O!eGIm2;0+)i?=c|36c^?W!UjJ z2{x4(+%iu!R5Ji3GIL06_G;k_i78ch$gCBvAn(hqL}{?w2-pYS!x`?o0J}drNzNIq#p})v!QG=(s9pJ-&oCK3bm}T3Y z>|Z+FF9Nkc{>Y^*p^sLY&j|+;&2<{{q#Z;ztw<&C%Wf44fv{^~FdgHO2Pz7@Hn(15 zh7VeW3k}$3L-KiEj|zqS%6j_!)#HR4=tu8_k8NB3XTW{p{D+FZuKPvoh7zY# zlwX&1ahi9;ScIb_sG|W4z#8VMk_S_N_Uv*k2jon&_AxzuOBlZb$%(huoId3}{1Y_( z9{*KdauedOkoyKTv_Yg3f|(6$zOXT%33Y9%w7#`F@Uo+VfAe5hPwfCVz;2T84lH$l zZ4D9>8E#la=8QIX-+3B&YM1sCZt~IK=&#S-fcI3+(f;F_P|q9`AY666?mYCQ7<+MXud=%*Pt%)11`kQBlxZ**Cp!@ADg8n} zOTxr*opCuE!A<9M_Cq3sIC?_m=dvabew6&lHPoV1H;!XFi2F`ks{sA&xBNqKTP1rX zy5%I%s+&2Y*dDG10Ob(=8FBxJfuL8k8}E^g{O-U zUeUQr>L_Qep051SN6PS2*!cj*p0Z?KwnR8bPo>?+Bjibo`28*%Bh!wQ*$s3=?3!K` znGQX4y(HkW=&>3O(i&$lF|F#!991iMIDQkjUyplK4@Hw3KqGW0NP2bu%H1GlD!nqO2O$Wo5Koe(vk+W&NBmOVEYdPhCsQB;1KP80^g6F>z z{Utt#CjL z-T!20FMdESVEs2cpbM$^uNG4uG9UiG*)AJM$$wdBJ4lCrnzrBFYc=|R3z)+oUH^Ss zWdx+szgplZNZx;43D(YF3@S_Ofj?sg$)-;N~mvYgefq1DmgsT8aa5 zV#vy49_M0`DM8N%SJMaa$O@Yg6tO{a)59 zPUhSs>Y<|W#0FSGc&I2W^%c=~hYeK5*0dcAk!})dLZ*SMWaEowpZ&%Se4 znHUR(ie#|+rqRK$F*qQ)@Vmw7;~l_JL5DuMRR)1ND8N$0?gOLAG{y9qQ*I59Vd(+Hv!?(k$u4;wp&y~m1vB2lj=Lyky>f#P;>fx5d__C$cfny$Ab^>7n(wb zky!Ig=7HEYBAk&!;18D6!XW|6OP_qs*(M>~;OgIcQH+@eX>)$q#&?cf+xnt^M|G_Ew6rDR!(o3>l6nWD5Kg z)Fy{O9@#(LVeOC4H8^5?l(#u%VQAsD&eZ#?RiV>h{8N}; z${y|fld;>lKMbkxT&?XRZtm4!gg%a|`szlYj)zD`)<|mln5y3Sx4k{t{=-qZq2m?UVw<$t5xXQ~mV%y*-6W zD)%;e_LoXG+9I;k!3S+*`o)Q=gye&umTjl+)Ri%P7BjgJx^s*!O)fB+IFvQ(>w|Kc zIjkw^M;_X|7p%{)Ti>yBr>Wvi-&3FoosDP2)j=e@7I+UiZfx$@}@~q`1>OSe*g+l0&AGtx($RH4RJ|1S&^@3DO7m6@H7&j5Sv}?OJrJAOo zYZ6WD@^O>IbMgwXi!eS$973>>neNWt;8vS)d7QGERu;9iL_$Aj28iR#;Pvm zFb5CkI@el_=Onfu77-?;p=j(;b&e@Up2)|z6d<+O`6Z{6Fi9D1Ia;gyJ2%#z)D@Jg zn#1i0L{B~ZigEzZ3cCT5mj^Q6jWC2Z{xMI2L~r&I0apCl1$32iXRMk~5ovb2C1pa9 z&(ID)bx09g*j8DegGkXcvqcI|b@5Z7y`s7I>Hb8JB3Z;0cMwHdF;lH9;0Ga0Ih=$5 zT^=&gV-?P}xUsO9Bn6{E=0CrM?t8HRg#@$b!9Nl1?VPwf!Y8-iV)Sv1z!^A3m08&# zVlFAplofsnVi;`hReO5VCzum*rIdpowUs;AOU zcHaEu=-Gv7A;yhUj_OubnD1FQCb!a=_f{9d4@{l3?l9jdasAnkpqSL%+wqLuVza&P z&;Mi$gLshSk`lscH~t>0ok|a%qc=;TVmrfH=~AU==u8(6g(*KBnWR0bDlzHgeI1@;TIi%t%HJ+c{L(t zWKcGXlwz8~FcSvo*6>IuL=)w|8f;W{-!9-9Exf`=(Df2y@BS7cqV>j4_i?ak3`{P| zIh(fvw0}f6xkPOL=wIDH*unQ*vNWja6{ADqDxa_ZmHvZDrlU&lN~%1M{eIRSep<+`fCN0r(kPCiEL>s7W=LU|2m1Nd%|4Aat2|?cCO@h)C8J0vA=YX-Tj7T5c+5z?! z;{7l$vhr$dWjS3|6EUtkMs)#|-9r%Zr^URaF)bY~xe|f#T(0evW&)K0kt4=>_hK$C!)Xmcat~z|1pgg63Sb=>7(74`NnSLGSct0mh zCAo(NU8&Q*6w)xPQ;~v_pxAr#2kuv$Mpm2LkrIvz=!+Tac>PJ=zAQ*V37-bI z&Ik=o9b2>S;e`$@b`C>+?zjZJAr*~HBE9jg<8PbIn43D1kfL((DyPN-Y=ADt1-O1$ z^d9;!r|nPW9)a%wUPnNLr=ryvb#*^h+Rj{zuW|1^>$-(^XZJ%P2%8E;bTxQce_CcU zv~n@Icp4~P)I5pn1O@N_9E%XmM;`0WeFCP#x{!5JUhoCS3sYLHq2CbvPV=8xR)W?c zz`m}Wd9korYV`5ve@?uhK$-mnR3Y)%$!oeR1VQN4YADVDXbn^jLZ9?E5x!YsUO%q5 zW6NkjRY1ojY?Libu)2B3?^Eg82cbX~c1SI;W%F`T^>L8 z#)a?;Mp-N&c_p+}3umpssv6pVfv&qP237w>xfw&$^?KVs8&bz4nNK)#6?>`2_$8`! z5qMYq=ipEmAOIY&EBYdz0(qW+d#u*_3is~Ip?ciW_CP-GQdG)%aUq2`!K6QpcXyq9 zAZmfjhx3+Emv}Ek7dqn3z%gt>)4s$2Yuj=Mhbfb0gW+ConK}l;BYq9BN?~ol8)})? z^wp15%jV9qb&7+8crswHfGHqaw9nBD@3wKqo_1XUNbxwwJAl{yAgf_X1VV%vv>Wpd z(ET&d;zbDFHPIs^fVU#;&?`fs(uC_*ykWN9Tr#za5oCkjoa(-UEnbY{>X&s7wgpMjj8ug z;~d$DUY%C2bU73l(3aU+Yg{ie$H7}XL(p&KE<^9}N@mQFmLlHmMHg%e24~+SA$f?i z0SNTi>9Fm6;V@vY+rd2XqVhH&Cd(Fc7;{K`)Jv}PH+{xzq(B$sN zZg;9=?-wW!J2%?8x-X=@#|t>)h=0ErzzOCa`Lht~U$3Tq%+KJN!Hpt3F88>;tu7Ur zIut8KGzM;dE)|?r^IL!4!z0D>$+p&n&w0Lf$?55hXY0>D_f@Q(z*jw+b*)cMJJ5+9>Ofy}3 z2^#qts?NAZ5jVw;RcHfgWgy1@;Q#$ckJ@MwOoIRdl0iw?tANB#ZiRwunPGw|{@3Tb zb3$4E>)lUzpnm^r&83B)`u}B-#Gu^&9SBk4P-FiJv}Bj}cpiR6KUnM9Kfaay`1_!}sc8~u_ZfqpCNQTu`o(95-_Lit19e(=#?^#$d zt$Ztnda76z6x-D=pP86MqqCu{$SV87owsw*;#rFs2XiY!WAoI_6=`j?@=MLPCP0dj zMbC+9HkQX=tG@I^wrtu}2KT*g(OI`~dHw!cvV)_GTC6mwm9lmbfCzIYsG4W#hd>LN zly|EKd=Y!ghs@8cTRsIxrJLf$AdEBmw`IGqUcoWh# zk%&rs@QdR`6O`AdCzsi-`o=CHLJ7jbf6w$>>(^Np7SVpiHB9L*11L+G?NpX9uHisF zidvYXcc-$o9r3GHqsj-*%s%tIkMJIe9fyjKiixG@T)ZunZga%VMOl|Q7yh~oUAv;jCSKp|pcA*|^d)`KJ zzK7l)jq)pBfHv)&O`m5sN13qD(QYx^bDwq7FUK5-CtyUSe40IzL&EpR+b62OYhiPl zGP=7n$rqWWnjQ~}s_kV4q~j!1KVRAV?i%q4?8%xpRMdjPllkLf&6{WRg9^4`WUTvS zUMfa=#!p761y!*0o*Z5&@0_4(EP?&T$*|};4l$if0GkdjJV=EbF*$-Ct=-Pd+R-W| zym52SyDz^7tG@2JO>@#==o|E_mP}?BXJdaNDr0#n2yeZZ?JKz|_^(JoIq{_P1CY!$ zbn;YfP@b7xrgG!8D}JTN#|E6WQi>&cwdo>6mYj6$S^x3a&zs_I!Si7HBZ-%U`$^e; zJ4=vhR1mG-HO1lI%NPeS~c#dtw>D|2S z9SwIUulP|lsAFK^D+F!XSwk**IGLZ-+CiNZWlds#qYNCDJKOPUfJzU~z zc}P9p(jYAihdfq}*Z;sx=1fn1?+qr~1-O;qZTC$>OahycA`J#EQ+i zoz03OzD&fbmRV~S40Koa>LliJ)>5vCZJx9L5e<2XNEiHfr)Kqt#Y}_KOP65{aisyz z4f?A)%TC89>L4DX_2A~KzpSoo1aOZK4ni==t}v@bJgZ=d8JRX0{pY~9n({^>!;Wj7 z1n0m%(5e!be!gq`dnLZ)wK&cgAqxPs!&7gjp(|?kgHjmDwUK~``}6`>s1whjzcEz)X$Kjs;KY6BGSZ@QcV2QcH`l@jh1 zCSqihHLINUPeta5hcvu$B1IV%z@1h{I8yEQr=A(ZBjPQ53oZnhef8@WHMdeqaQex>xZev_PQM5IIQqb7!O@o=(?PKN6LjyW1ull z@~q&a%EA|g5DnheEp7K6KEM*YM8ZfGEB5vx=S z5D-7TSv}JgLX*bA6%GvT5{LVKdpM?qNk}jk2Cii-sYT{5=z1HUKFkKFe0Hw;NRq?; ztsI1P-enS)VxlMYh9cGFp!kSg$Zl@l6yB2w5wJ=vz7t_fJBnf5J&2gk7ktK_Pq6*l9tpn zRl^AtJ!ComZ1<>&H=q}-ZxR`-{>h=Ep%-K}_YRhXjE{*m1AIaiUGs5}_MC6lh51ms!dt#jO#VyXL_wR z@#@RcM1@iB>h)a3ABt4Et!-yr)qB#hpb6K*MlogIS%A&JOcGhUYqW<6eX!EQ`QIRy zt%F0BlAv0&j#j;6;bnG^Zav0K_`A};%@kGAANKJZ;a6De6dcuw9ONTLWJ)GN_^(n& ziX#cQjgR;%%ZeGpbKK*~?hAjm7AG`2Oll-Tx}C=^XF^Fe6vt&%O#ERL>jmdM52~Em zZ03IiDgyLniCeg|4jGVuI8DCoqD)Ar7a3xl5bX!)GYLjB+k`m*>ID|AlK(O<=YpqpEl5vbbN<6-mNO|caToOX^Q%ZcvJ|bM)0=j@%Ao)%e zBpJAb{k1jsoOtH8{HANxz49$YAOD|`1e7)u&OfwDp$`QO`yYU*wPqgx@qJH}fs;}z z3x%DcW(B1ONaEqqlBpwQR=rr_Hh)Ykc9%BB8LFAq%nnUt*P~W%U*uE9U_s63lTQuZ zLWtH5tse!GgH{!j6aY~J-#Ve!e8>6;la?sb47RiOAfsdBi@so-7bJ8lF=a$R^NDpe z2&$}4%^J&-crg=Cz2!j8s#MEIfOyp zax-bddgplubniYcIlkODsdYJQB}2%?R1A(>SIkFgw%HY1#tpfX$fr1#RvoGl;F9v~ zXD0(+g=VKAnXEW9@0*w_pK@RgMG3r}0&4?B&3x1HX@WXN{7w?OLwva%J%(GgRy~VK zfD->k-)`7%{L?{h6?95ETowi9MjOIG8Y(Wu*anIaMMWG?EA3DDeD?nc?RO8bmy-ScoR;d`Xr>odcunhmR?cqjJ;QL&#?*07BK-o9 z5AT~E%^WDcg96`jQ3sKV6je+uF)&-{H~{=Pe8HdLtNdKG9{l#{MO92A%%S<#=^W{-6Q= z4PVPo`IVAaJT;)r0vvz`jN_}&ps0OjkP0~}{Mq3_;ic)65=+8gtL;P6lHC8VuV5w&!m(wOY|2(P*(st(R%R+Qdt`f!kWJ!{6|y(4Ju;G&y|P0jdqlSX;Z5If{l3@r zKiBnMhx>e<`}sWgb3gZeuJb(SIrVwyE{qREdrGcRvJA9UY7Q&f`MOo*T`er*8?2rh z?QGibTX23JUX$+{K%3YSRL*I1pd2+TG7v-{LXMR~7S{jJ~0e zMIpb~5JiP+9k#f9xvT*Er8F=-vh=UYmZ@Tr`AtEU6`}UQdg)tnYVMRd9T0!Uv_L-W%(U*Wt64O2>g4&TswaD$}puZW-z+SA;!ZbjH}w@X1P1^gbH zZ|3jafayQ-!yeYpw~Rl$7D1-slr5gA z7Mgh+%ze;tKV6gd{UPaVkND`kiby{T@*B` zpVp_mztyctQ6Br&)B(7tUrP28<(!_l6KwjTQyH)OnTrW9KdXS(yPt&H;8RpG@4sHd zHClIiD`+Ij2XDL-e0${sWzwWmUu#b&R_D`NDZ*C=#aHX)0(IWR)JvHO1z5dCr6Peo zyO{lL?fzHS&TK(kn}v?8=4@LGgO9MxkQ<)J(jL0!xh zKIX;b@S(wz)Qnp@lggCvqliZyLBe#j4@q%M;tG<3_gz_4shd)&QVHtXj{Ua?J*M=pxxYoZ$0Ure%tn|M*CXIh zs1pDBwx+@p=b(2JtGUYyQ;zDd3SwAHX^J;jb?Pd+UG1+&-ot<=GpFTH_`#LuYdg42@0OU19t0;cnr)cC@`%c_~gUT%D+j!v7+a3yGl&@56rcACDG z&8KQ{Z93bASJx}zyGATyfP{U3*K{|9Q5R)k>QxO(b)`mCFv2uASl~;r*?ifCO1m1n zteUVrK|8;gyl0xKEN(1=2J{UoWl6S^W`uciS!IPXtNI5mE3PSBk6nA#{M_S956H*e zYFg4HX^}Ta@=CS~e1#jT=4>S8VSV7ltJIYpkw15mN zyLgS0jhdX`V3|&n5GPZ_8@8wH-PWPL0*OQ)gVR`EK5@cF;rX09D|m^;TAk$4pF_K zH_00=Bl&l2KeopzM<-58t2?i_6Bayf)o=3e^Oq0{pWRLVFQoU58u7@p=gSGA>+0yV@r+Sn6ctKkkoX113xK{_uT;7EdPa! z(Qh?4`InmbSJsDQ%e|O?V)w-&bjsU0x2+l!^yloNin7bgak>0R^2XpW>yI(j3b$~= zBA*Hgxm-M^#@D~$rQw-~`RW3`R+*30yNjgN#bnuL0SWW#h4oTGKT>EO$Ryp>Ka#ht zf7;UIbH$=WC&$1UQ~CvcW}joLLy)Q=O`oDcMCpY8*t@{_xRrqUN|@(o`M6YVUY9#l zCk*|i)t&QIO1(yLV~c!M8!ey zqf+)vul&?o>TT&A>8Iuj%oFy@PbzXkg6i%V*Y+JqDmnONCEhlbaD|_sop?OD{GL3j z`#5ZE^n$?MBxyuk+X0ghSB>;t-K78l^zWhzKmA=J6BgUDqi)VWyW~Nd%N#$Df2deh z#>yh9B(a}C#H$7dD19gLrC>zO5O5P-i%u-V@;))BPQE*{olOVk@#}D3x&NMH!{Wz$ zhw)^VmQA%nSOq--^TK=husM!3qbXRBhW)6oG=5He$ivd&sa}uMiY5JVZl#+xR$}PH zYz7uer@ih|9x1(N9LAT|fP0QcmYfe8x%E6ON!)Pq63o-zk0W}n>MIO=J|nL8o}b~)un6&u|2p4DLcMk`{TSlA)}H+ZNs`duUc#jvAQ zOa#N@18oZFcw0T6L{ug6_m%;V4wPP&#}|dvtWTM|l zU*_j5>P`M4HCJz@t3sZ9SAyulmJSd5dnJea3%lyc7gTpbUZ9L4Ytac*X=FgD1#d z3($g}gMhb4xm)nBpqda2w4x$qreVLZfnmU%3xTJx_w%`EFAShN3%!vMJML{P}6nHtYE}$!m znpK*T-zchu=YiYm`?b}Z9_3CC2e&=$ANF!cg8RU|!)~}iOYf5~-mUyNmrnV6mgjBhhG-V!uC8? z!h&l)Kwp=%s%ChTh}nSpR{zmadZnSoPxC0wz%_Sb+3&;pGNZMWx3@CW#Wn)nQEuxg;e@}v9@TzBzj zvZcx&j-UX6l0wHgPGF~!rk|XZ>rY#-cTyqcsbIDEDOyH$-8+ zbo&|tmWMn)Bk#_2j(R8)6wK>wg^R}C4&#v-^b56!kmQl~#K>JrbQg|g9?UEB^6EQ+ zg|`;q9&^BFgKpPuEcjQ9ya&x-{=M(XHkc{6 zV_PISQ*Wz0@)CFV-KWv}@k)TkIR&$NtA>i$ken=m7bbfsLDRdvLb%hk6L*ExPiJ$S z2B)@-!>!+jW%xd`c#!u*gYixp>hP71a#ucocn13j|H7TMC#(3q-1!GlIvQ=UId|w% z>Oy3oDJ{z7$G0xE5Atg{noTr(rYcl1TYKgyUHJaF^CdCA+>rLn#iY6T5*^vxG;9%K zmmm1LKf>6uEVI@eZ1C=WP$N-c$?GmHK%?02@H~qn;lQx;30z0%O(&z9h4ppOz*G7$m&!_GjfplCi{dyv=(rqu!)9 zVy*BL+r42TB|Sv?{nX^@T@USAvWjY1pK@`U0A*HJ_X6E8RR`~mSBi+)7vHd_j5EYz z*c?ar;J*4K+haVPA6pNs$BC~cT@_x(o~z4pQweQ|Rb(|?2?;`-ux=vYL~N7HKF?}L zll;QB8I0?fTj6XtaL_I3_{whw#kp1$2UGCAeB#c_G$tp}{6L+%w74!`s-_k|+brnunv=T|dX=?Dviqi5@$KkliL~@;8b#;cQzd%|an!wE0TB`ZG&i!)9lB z6I8PsVV)$5*m&qHi3hv3MV z6y4#iqv?JkqA=YX_cHWhC;@go>ua}U!wEYd$qiSD1LHjvE>>=IE*8ZvquCE%77yI~ z@or%)>@yx_X%xzO7{>0WeYxqy2M;NvQ(iq?=YcEDMTjP%vOmdT7UB*=j7Y3XiI|B{ zM3oo)bb_&5+>ZrG9ukTdCqyaZo%=?Kl^!3JX zcB-elNH`A_?>rylxim68*!lEnT~Zg;$be5KJfzNoDdpOhsPAOnC$(cuudApY^jyH6 z;mpkrQvv*H>R}r^%WjPjK~#6gyS^=mv5c%J=wq`xG$G9vyerRs)aqv7dYE$x;Bc@y zxBj4vXL*_GGl0szh}acz;L`dmN>#G9HTDJ5eI{AoX_Rn0C=LNWlKpCM@B8$4q2%S3 zE%?<{X5tXH&sl1%V*X>f*!|p56abm9>7@#Hv_J8tG%T%MY~@Wf`pk^KYL+rsSy-dW^TqZQi*~A%#;ynCOd95tbv*rUUs=6dEZD{-lohSZ^6*{0 zkLYSRP4w_N94trPsZHXDPLONjGnQ@&t_`~VNlJ0mH3B=uocwE}!#9CNYuMFbk1T8% zc$Dw$4ye|t2kt;rSEsjF{6a(+78I^S2(Qo!aw6ko5%aWM+32=JQ?7s4b zfQjBR{uTHBjRQH~4wvVgJ31@t+BjbNZ{M$cUH99I%SW|ph5uw)zc(`FLa>X20zaTw z7dx@iN3Cl)N#w0Bzg{;9`%u(oIw|#5c7wnuovBKJ6SZ4#d&Nec>mKcG=LFxven)LM zyX5z^z4t<}9~93e-vv#St46l7r=&&Y=KGkWKRqsCe(l;MGqIT9Sj?AV1E2LP&iA|wu4$}~+rH4m$GX_la^oHBg3P2D zl^chm-s>A0g>u1xvoec_&3ore{KZYriW#L%~_W;%Vdd;1gTe?hkMa z*&sjP15O`02lac4UT#d0ZN3rD<=nIh>#IXN?_!}`*w>pop{6LSJ#a3;wjVXtCUoqk zl52T<<+-SXZ+kY;zFhG*+bXwNVrbtg3JS%oT8D9h^|E{7Hmotck*hYwYb}kDh!z;Br5}__0uf{Qz5QqNrKW>Oj{fh3$_I%cHl) zj0R_uceI^-r?jUfLOZf6JXV*)BA(f}Do_kwP%=rdzidOaK&_g}yy$0wC3xJa1s}hI zu`pbGbVb1BL^v%h(3GKadSK8Ch*lQb7A1U|kz)9qW&bsfxGUS{9~ zGpN!`UOD2L;2&#z!De8-Ev+KrN!L@pJACLlZ5v9@Kl%y(85eHfo_)DG$(=5afIOe9$6v?ec|7ZfX=Y>`VFSL&H2)c%MuZ-t%+oLip9~M9S^BlZFC)VAegt=;=R4%PbD^UR{?xwC@lpUYIg-HEg9;oM zH_PI=p4<%M+Z50COV2zS+k!g@{cO?UYTXj}ro!Ab*T8kdPMd@-(cO&7_ulwY-9Yz4 zF_a7FP4E3&%0=8NU+M4`vEu8Qur7Xh5^tfzXP7%q$cr{u^4%*{{@R@v)?=D-KcWto zx~b=>FOyDNhmJJ03oLU*8kvD9A4ey+=1dNT5svis-)KY@W_ere7QHFpKQOm3f3)}? zG=$yR;Z~d9osB(t_yT+rW9@2BX8K~WNaVXmaU9`SuQbF5`RHNFEZf(7 z#MfC$o+!?LGpl`)sGJI~xW59A0`oKy3TVkGMj{58X}d-Xz%iI{OiMR|216>fYez+E`}B!-i@cIL@~ zQ?#et(6((X#WG3DdVGv@P+)>{E!%P1@XI2?fc=V}g($qlu%pT5XG5L|v?nzTyi$w- z1}PYiEbU#3-dqr0v$NH_q%kW!M1QTvz$(x7qA2V*+I&6UXc_i}_5?#&0R@!=jRbnQ z0KiVyU+XAU$(lm{f$497YiHA+uTz~Zacp6*(zoE;TR@oZ6ctqe>XtkT48{d*DFQ9l z{(T_4KHGxg$pGuwgJtkpGC+l@We?tWMxg+ck^yq0xaw3K_e;E*43M4aG$MFWq&onE zIR>JgJ?uDFitu9dKh;19ilqSLXV6&9yIOLWVX#*YFc|eY4mu;eTC_o%RDc2uP63F{ zpf^}GKL$WddmyG9e?aA(Poaz;H8&;>xSRsuBFP=5K;)=hk=K@aFtI_mA^`VH*SzVS z*$zmT4jK%`_J=Naw^O_jQbS%Uq#@h`so`=lKzUY}XP0;!6I!MyME7@LCC^hR19E=ny#p>G#dW7*;|QdG2YIc#1R$e7?boe@&4y5@b&b$;H^lSzf$);5L;)SkQRx4%MsNMp zA~Dn;JE#Z9ej`si0k0OkmJTqTH5)&d=uQxHbrkxYKEgUb5MHV+phG&qb5?Jfzv2A? zOc<;l+8>hY90HvYUbL+!;KT=%OB{bYDzW&QjT2P8DLo8E@kbGi9uO}BV8J?V(6*n8 zsR!7b1(2d5M!^Re03)*bE*Vhs4UNI*-;!ELf|dY714lCe+B51|q#3+A(8y?0g27G) z$oYZrQV0PlGXVyqDv3-;)krd^o%yTD+N_*r&}f2nLRKL?F9e+tUYV(2QYOIo=#-hI zzscJsUP$}_1|#|dHI{?+uSpi})7cd+Yv;e)Uzr`TIs!R$1GM0l{EzZoQy@bYz>H+4 zkOi?Dp8<`t0D7b(_*7!I0A^+ZbV$jkQ%UG5xR7;j9)fI067CAJX9J99wjkU)WbF<< ztp?>Uw)aRu%WQz|4E1!+BQ6Z`Kw`*+{g%*=s~sHWn560Nc=lW zJ?RIJa{$&e-~0XD4QNRJNk;`016S-%ItC@Ul6yY(j-b+L8^jo32qq+V&I54IbOb+m^Q4;qatOh{{YH`u10=-9 zAOmY4?5{q{gBVD&fD3s5+ga&MUPPT4)IWjH@6X{#dj$hrqro5t@8qAC)`GTRMXQD6 zA+!*Ka7cdEGk@*WdfMG*2jubWU`;-7<*cT^_mcVtH70-oW^rLqgLDPwHSrWcH3gR{F~Fh{fCS_zJkK)Xh#R6LmqA=G*m zsP!~|pxhn7`v}N>Uo3yM{tU0Y%eW~9jSCkjsr-4f(B^cC|8=wAfq-~PxFIzZAOPf+ z0AR4obC!$$R!kX80^Kx zzq4CI6cYcY^jEfyIox!|fj-7#a2*DNT=e&W@Pfr5p$nzIoI&!I^f)oJy|Ekf-{z3Z zLPB%iLgtVx`^Dn-wgZsfKb;yxAo2S-&|OCmghzH*Tp45mjXLDDPi4QVMX9QKE3q=vBcX2Pm;_+Q+h5iG^J3lKH0>^f(-ly!L9g23fS=E4{_`@&-!xr>&+wN%XBf^Yp27u?_PbOGF?)RPOaWLZ3*eoF z+%wlas_V}?b!D>uab<2*u(uK*13eS~?EgtDlB4qp2Vj}D7!X*1$I@P zyUJu0RAY@9@)|)kKzyd=p9PG6t7&sULN%%Zbv2{`3yu`WIso`!LG`)z_s}&o z)BphVfCDth=ytYf1iJ>HBK;H${Ohje*U}JBxCWr%{jXId=Y5Ot3JLqKf`K&vE%1BJ zwWtOlBMp81U%>GifEqcadU#5MBkI3E(1a{I5~NiNfe54j3k1#1UXu8Csz0rsM+YV1 zG{mz&Kh|^7&>7)%6!Tw7W@`Z^Hyj^tNcB|dtLzorRYBk2G;?U S_)lR^VQo<4K+T5S5B7h5&mHps delta 90805 zcmV(*K;FOMk0Z1FA`VbX0|XQR000O8noVs@kq(j$noVs@12{!VBya!#5Sfv#AAilg z>v|ih3PthUA8-N71Bs-bO$U|ooNy%uBEpbb-JsFxCXaY^LL!cW*1EOG$AMJeS zkoPSjdV|meJ z&^+6=W!AJgwP;o)G^m=o&7kLHQCF+&0)V+;9ni3{ixSosM$)!0fU1VJ*cHqpKRD=} zBCO`TY^y6=J$U1`S>N#B>t?-_1#Wlkrd;a#?f4)sudevXI4kOTwyp6QK=2P>Dz7%# ztbol}v;voQW>GCGTA^Y`9e*9@?XcB|4ghI!yL%vb3`ez+~xHGk}oYu|1P_v~_8 z16DQ*_i%M{wcS(;HzdM=X6+sW0$jol>GxT)SOBUblK3W7yIE8h`n_Bh)dDbT-Ifka zxn9?Pisdqxz^44Txm_14w-}pp9gMN6TRb1U(lTIOX51J46M8$?tancjGWf_-d~{HL zoRzCh_KJRbxn4JGZhv!>o$g>C>+FmCbC}o?4ncKMEvn7Vf`EUrqGd=P{-0p{FF(S> zTLP$kyoLi}dWc$OC)t~K+}_P)qNk+IVHwJGt^Kyu$Nok+Jk6KQ2f$@%zFjY155{n8 zS7XF-T8<+)7%N0eL}EDUaPTg6cyO~8j=)9p5zvG?X*?jpKz}#U=;`tX2-_Gi6G_1s z4&Zt-Z(qHCIeGW(>FJxd?_s9z*V}T>(${cS*Ra!i%*NSj-CPtGiyZ)kLzw;f z*~=u{KfyUK58_b+-qyHHO*_Fq^)VAR-N}~5-U7mIx~Rhcz#8VuVg|&$1kzo!{^yDN zS!PhoU_XGCY=1WE>H-crt}YxEyg6hgX&&=(QS6XV$^w?NYoM&{vdvBJ0sMS2!PT8i zdY3Qp60FSYrq+eYwY$~sizkfQcVk?!TEPOfcQ<4Ljkq(Bvp1Ox2T442O>?-CS|A&P z(WktG=f1kE;MGriZ(aVlg$sCD)|*d!b6Ko!xVr;*4SxuIFr}aO~c0Ydlo6fx|;bbbgCW175IrC1*0^`QeCq zzyp5zm(TUMyuWS$(8U%GHr#HE7j#n>aJZWqPR+c$B-R8TYY+79X}MljEe=p=5a9_v zdfjZEy?;cZMo5(iurs}z^(Fu*pCTbC?z1ZK6cwRX*cV#SnBVyMOoC_mEX?z zg$dwu=eH0BjA8;vurBCQn-IN--yp(~f`fdJ{C|v>)&$UPy_>8Wn0a?BII9#KybAHW zcOH~2?)Va~iF9bO!!;v*jF1x;FX%dV zeSaJr09IwhJWK@8@PmxOQEWO{CEROu)}b%?ckV4}Dvm58*LV4q(t9+}z4s?QjBY5WhGXN)PmvM}I{f!k?~FzS&`eZU7ci4BIPU^0HMZ4$|4p zIYKxaOj=~Q2HC^x!};(Eer9O0Y}D3`s`aCye|7SE$3iW;qoA%^>Dr7JMsPlacX22H zp?@?qZd^;)kcHA`ZU;Z)vu3p$x&@`4s4*-$NO!q!ITD|>3?IJAUU8$K%YWwL zuVr7S;l>4>%WHkzCl;3w5__!SaKjQa9Qm>+mKXCPdr+*e+NXN_u{V4{c(8IlQGS2u z&;45-E(pA>69)z@Fq$8$<#y>9XONHeq#V$zNUxAn2Rw%V=Gc#iE@B_tTk8_LZt2Qc zRyDyCKs?vW?3-c+jC1xMa{V;h#eW>{AH6Y=@p=G)?1Kz%^SY&b5xB|ub_NeGcF}0E z?2p?GiOJb55Urx#FhQGLmovPWLQw!I9KgS+n_C-y%M?8&Q3-p5%}&#Mi!n87mjz~X23Nq zal7!YK?El;9~m?^){~R$aDQH`Z>##y6PDmwF~b>9mmiNmYvF%`?6Yh*$Orjf;c_2N z_z~Su!_nE(&(B97dF5B@X1f}GF&a5=a{GK&EVfoI)Xx!(RW~*q1YFFPTHv6FB?W9E zX7o%r!#@^nHS@X_l}cdhmSK2AtVu?!2|k#C>?o4VKyYp_hCjFUq<@{QtJMa-(UDy@ zA1Yuq^t%N*7&8D=n^@jQ+wxB!k%m7YpRBKT*d~1tu~{^@kb?_;QYNbNx^P`VV`i*^ zpNPeSmt|33)*q^MQ=|M)EJ*LSZWat#?{>#lAsoZg;@2L2RtJa7TdqU%!yg}^(F4(DPw?JNhhi>2!y;K0CXPkH96JKoB9&SAVIPnft2#624ra+ z#J4q)y!s_B74_=YOdx94->V*sUJIC9vsA!BAkkOC#YabYdw;wzfK2L=Fc!Vg>I8uTY!2%~_FrVUprYBrrl8^Q4PUHw!Fo+=c(aoOPt-YDl~Ju46K z5CNM~ZxsFh{D0@ki&yX7Bd|Zddj0I}U)@18De=ua0p?|#IE*7>GK(Sw6@VU1?{b#j0 zjezhpfxxn~$OKP*>IjU%Q&xmeP{{B^>myL1t}v;zU6ruC=kMl9m#}?NB4*I?cMhaJ zE9Z|cpo`mLJ&!mtRCmY(;ksHD6`i_gABt*Gz!`cG64rxrC+9}AXXt2?XLg@mv_ws^ zi=r)wD}S1oD`a2l*^Vw*ejgRu&AKIt72jlW2UyuPa^vOVa?}wh@mJv5MVsVwd?3u= zYxGi%%=yR-H=>KfX!wz2{tPW3a4*hx#}%Hm#R6C^W!z>0qh*c`c|s&(WxMf>ghhPk z7&lW4vspWssJj%GWUZK@$rud8h-&6ETJC$Oq0h8@fYOZd=~&b9%cg&W< zmHTC|2bHzaohbdeCz2`FtDp2dGjzmqw0|I1vmkbf?TFZZSxdtl&5V>oiq!YL)s+5oYwSfLt$Zq-3N7Q7)@ zb`7D8{{EzFf>YUl4N6!35L=$UAK8K%XWo=;J=m~^L;=hu@xa+-S)jr5P*opS)qjVw zCVvW6FFQ_a0t_N>vsJ08+ta^HzIpaP-@HXK<*hnrPro=nP-Yb#eQ{v8Rrvn-fnitS z`;&u!Uxi;DA6SMJemH(2s<#xoH8g*dP1Fu{XSH(tZZ?hEOxb(mrgU$!dS_}NPkFn7 zpGeaMD~4ZCdCxlo%UC%7i0O3M%zw9w61W$6b26PWe~4!>F%)v5aY`YikYn{6DY6F) z?Lo%6&au&VkXd0m?Qq@GDb0mQt&An0>WS?=Gm}Iec05R<2h~SI2K{CY3`|E63Ipp5 zO9sV`J98NsE~2?0bck@OtCnsCkc(_jW6LjfPma+s)QMAiqKg267`mm!56IAP*`v@x z=telo^t@S@@5=Ru3Ir#4CTv1Z z?+gMk(22M`3-v#FfW|NAmzFxJf+Rd;cf&eZm6OTsZvm%JAVq%iW<|EA7D$d zo?Q>c)gmuv*RVo~2(Vu>I&8*Iw(BU(f`iP|#6_!5Q)sE5GkD z!HAX$kxhR+7L)5N;H6q#kN^0O|Hz)RghiW;ppT;zR?TOpE`nUsHP_`j0fU)SDa1dm)^NdXJn`?J+ z;+}iFJ<7_Wg&`De8M95~hbX#5XRReFiI$y0?I8dYpMUN#G`bzqq4O(#5IDp;VCXDH z2WIF*gNaebw?(h|hgb>}=hSwr zj$!U;Ie!vQ-&BmWPext-gvRUNJN&H8g+lXAyI03q@WbZ`STMY~VfOxs4nxqvSJ1KFxo9^_M4L|TIuxKgnuu7(S7lYQBq6N8NP5oj@|%m;PJCJ z53VlJLZv-Gi-H*_Y6ZBEeMP^=C~}_>B}f)h+nAhsBVkC$)al}?$Pe(Er3EYX^>%Ccj>f9iD8*F{S{{S?V%#xCQ3(Ug262vY$9N2$L>*!9bg<%~j(+-&(R?HnC?7k^bb_wQ%u z%nUeOtaoe(k+TwOvWK11V~l<7?jrrWTnnxG9D;}+hkmvl9PW7R4VUa=Hg+#fx=ZaY zR1#r>SW&<$qAbDNQ_oXP1^$$MW-rRfvLG&QOn}luWq-p@8z^c+(Hn&ZdrTN$>EQp_ z(P9|KCyiD#i9+A-PsAcouYZye=CVzKgRP}R2X%9${f(zpcWIr<9llVY5fnf*Mk0vE2-?mn4XNOcP zy0ZfgE(EM&|Ez9X^?VrGxpY77f=kyhJrATX#gUCe@*sVk8G`bvRgxDM6;hOD6b$|G+`Wsq0V&1ygWn_TS zfIqw!$Tuwu8aiw|JGV|?KjP0_hwGtRfIv{i#0JRRCMIjiHKLR z6xnug1kS05x>nUSpA)K5FfB|;>4Dm_!s!PTL7#>l3BlR1AdOg&CrO7NRDyWO22uP{ zv)Yj^0~xW-fPeIdv#000R?=4=ZXzoBE@?%LUn)me2%1Op}s zat8EI53vsis94+YHALnLuZ(T#S?MMaj7A-v0@$82P~9NU$rC&@>;&)Rqa+oGZrmIw zi_ihxBzu1C&8@a~L0fx5^cdc;^XaQp6cN&p6r6z-*q zm1wl6i6SI1%tg^$R(X>93_Wb zj&Y^$J4P89VS43nbmAO1&k+vB**&LrBxAtm=zj)h+CiGUd7fOey7|;KQ^l3%AX`~F z+lR#zQK`n50hOCS$(FD|qNx>@e4J5C6w=y-g-ddiQ{NK9 zV}DGO;k_ed*04xpwyWIY0#Pmv=&5z1a$qhR)L}^{LNvv-LG9>#%U<1%CZ;gh9~l(32pJjk^iGp6H7amt63K%Z76zd_ep?#H z0OE|4f4WnuY|F9^#cjSbfhiQcO|!SeK0za)YZ0H(WrdGuD8-th0*Z`0_Ba7ar++DO z09Cy;238#wss_59o#8;vlb(|Jf*WC(a5&HCv0BRm^+=f{Z=H`Sc zAFwjzdUJw23m!P~HalUqr^Av9LnDdy9GL@Yvzb*UaUk=&A;EQgaJH@8oj%6<-wA$# z6TmE@|3Bg@^Pk+U$B#Fds;CkXlz$vYVB0oiAu!zpcvhm7`_iJE!LZGs4SC)nGvBub zc``%{_$W8hh2!vu!1tjxW8*;bAvi9?Won>(lE4G)jRO!u!ltY|F8a1!pmuz!TZS7r z4VVz>k%lxTImxT2G(x~e-~qF~y+AT^QKBX=Gx`JkXm+L<1s?TAa4|N8cz;aS2S1oJ z5-B2U?f7h+h5S3}DA0EO>N8ZwQ6Gvmu7xP^K26BLCZF$rE9fnJ+eNX_JRE9ZPWWlYedoapZ$1RuuWR=IUmGhE7;%mkSD1&CcFAWZE5t<@s<-J338_Q2?akWJ)lYP=GV!ZGv8%7PEm zv0ZnyxQ$Kb6EcJtEfh*2;x2({OFbh;QC)`H?knR@69+3sS+N^3P~3x`D}da9`q#Wz}5N>U3&7 zKydNbMpeX;m!a?9hD0{ND;yUY)rG;#YJk|=(+#6Zy!XtG|` zKmlZ8Kw$=6BaM5oMt_M~BN5<|RM~^}0CC1|3mMtfmRq^hdw!s@FMuY^h0`Eu_fZxg zyJbl3BtwaTwy`%RpF;`ZQtJ&}(e!|liI%L7)4Qn+74rV_Q3V(q5-{bGs=_#GFIeGa zvCA+iL&lb`6wj6p9iGV+FG=2Ynzz+lhq$s?Z+%{;=sq?oTx34BE9M$D zaQCMHp3p`N?Qf&Ar%#WcoJXJop`39~ZBt*?+NJ$zUeMs@b(CTXQr2z$4bh%v+$HsA` z2$ynk78hu)aJdiicugs4{>0`q&V}$&<~JCL88cwmB1G?)FOU`W86!}lxpH5RuYKFX>kmUtJE8CrbKJJSBvZ!5v35ZBBGjIQwO>>VUYf z60T=VxVFPc5hpoiIyX;G1l_H&y2+=+Mt|sEf_tx({UF4Xz#wLs`*f%ty$2lGe#l3d z64aaaN`K!4XIW>40}nNl%@0jAzXKdzxR={CIXWlOmYC(e1CYgyPh1=;C!{{KgWk5% z+uk7knIIUl{m@~KzfCy6p|>kKXSc24rn`)^Z`);j62B$i?+w+wAA-4L0-l^9Wz}P4 z!*`RflVUoVc7onExeDS}%_U^znKV)9Q=H@HD1Up?tXfX-afn-Un6*uIS#(gaF!_MG zq(vT~GuDscV&L|lcV4(lC!YstVFK`@ki5d}vu&?k=uN;hG+Lq|WGwIlZ6^_fK?0#_ zH;F6?rH}Xwv-5m;ah}Iv46-v&m$@K0Sdr!~h-K>N?IPf~pK*WP&9&PQwLT|9B2H3N zJ%6mYPJxh{umgejSr#drtGlsj_cbTJVO>PpQRZ4y2}CJl-dvg*j1TRJlhtB-1#}{$ zCM=}$qY03mG5Lm1dgXK%!G01MUY%tU+=B&biHc3A@l zV=Sq)&`BXmc#xhVfj6{U`kzuUzL6zkfU< zheSZ#?WTbX7Yp>jN{C7t)v5j>hgA$L;jCIEAgs1PC8CI$D2Z=&D*?AG3r=r>J|XL! z@!vGeN8p;Fs+ATMC+I>Sscc#+i-#Hk^w$OE3PYCM1E(}bDVK!ui=9hT#ht6>&MS>| z_vF=ScDX1}cAAsHsl~j=#D{?p%zr!S)gl|r1w>4pfX$l4+$SuS#4&qA zp`ItEY6?tJKCeqUz=)}1K;g!_yJRwHosp>BQgXp3E4Y!)(NByA?tfkSkwC31 zd$+B1Oqn~%!5|vq*;Vu9iO0Mo(}K8wd!-9ihoGTT#%NS!0O!9Y+7=F6Pax6yXSSQwHJ; zGM21$Z?$F~hf=iTNVhhYzg4ko*Q`^g!9Q!;)SernW(F3!bKdVe#d*B{coVm%e0 z27LB94m}R6!%dne@|ho!4G|%Q()SBY`P|74LoDX@8PK-K$PGqGWBT z1#L9fjrv;Ml;tYBYW4~JsA#)MEP8L3z1ZqDI}z89pYWDW7U{4c`nGmUQBz~|Jj0uS zbXHh%3Vn=GmuGKMyMG!Lln z?)$|i8mM;!3(a%nrz>L5{60oJ4rd}8{&3Z_ZFK<*WlauzBWL0>7dcgE9E%I%PUD{< zt6M$yd*bx@#HGip#ooKjsTq4>7bdNNH((mej+-tyJ8u`4#D8x_5f5JyVP2Pu@#A}|U-hqM;JK>L6afLdE4G)fO z%AuQ=9gzF=tx2b%Vl6_uCfhRiK{v%^Q5jEEsk%T0e`D`A`Cih*fW|e!w{iK0(MkPL z%yPLFb$=NCJm5+YPx;MXLI#F>g=waG=A4RtI2vI}ZrKsEagjdIa6lagaj_7}7&0y( zG&Cdj85xX>l2u0Ol1(L!!?{oh+ZAz9B;X16<8tCDFis?}KY68N>`bXK)Ubp; zRChV6YAPO=!xd*jn=JG2n$l=KFagIAmMwW87=cKNZ4S%)Du<;Te3Ad-U^*Rn4~0Er z34bdu;O8&Rmi%8#NiY=A&6*E^x;#R^c^UkO!_wFz3Q5wg**b7QX0ACM^eTG*#QQLd2HeSsoXPMZ zDtdQ3N);6ETf!dwA>bALB9lJCx(y+4Hd`7lrmSCWL70Nd$8SOrUE zh^aAt`4B28u^DzvDe*;}O}TS8tCvHxyW)>ly9sY_=Pt49EV`=Txp0BdL~9w{x7o>w z1>S#~__5()C6i?`X!$x0ktc9a#lqOVyZ)9Q>t;JMfLZ2Vp=lkqj)QcqFzyb{qwvtUio;mIM2pjK zX)_gs7m@zQw*?-3`U}hby zoE)JVK6hajZklnpgqx*(HFBaMNQtbg_;bG}j&DL*M(F4S%b^sTW}RamdRTDGb~1n| zT+f!P0VP_+xp2^oS@%BgDI*#hbA8v%p*Q>>;qnmN@Z@zEs3|#YQD`-C5vJp*iy=Z%+E5EE3WFn{Bu_%`+)izK%^xoDw_bM1mmj`y|2%BdF|IO88&}*k^_j@Q{hX_hjy!z&AZsQ94h{ z&S$Hg9gpp#DhqBYAP8_stV6dEN<}ipf(*gWhmlM_)<^YXg~z6#Ahm z+=z|RJcQK9nLt2g8-J+h5>O~4A~;=CATjnqB6ZI=2=!#~QjV^nKW@&}I6xI9G+;73 zR_d=N{x?CY_t#pgKu!WJC=jST^dBLE%r!=qunz{-<;L@RVGHBp2U!nsaA6M)$^+Br z7IHO&=w85_>SSNVrx(`IQln+fe2VqemRRv_RHnG|+;s%f%YXL?(dIa$ZCwGIANffL zweNAivICAIsU1r}HqcS${L$&`o=p63U^F}nW`GHZl=G#Hh%GnA61+LrYUY>m#!z~M zq-YnWLMHIN`HS)6m~I@2nqwC)C`lrmlomB#o_%U*&ZXHef@I=(X6YhsxB52T8IEl!go#LP|5qz zLm~q@%wLx^C&I9Q`OCBwD;V?i=e zspBOI0Dta%(yS)|3vr(us!@tlg8PR=LYg4wd%D9>z9)lgZx+^HJ%yeet+ltT`)sYh zc0$ouqf6He%_uRu6Lo2gfAw7N&UNhND+Tjw=bX;SoD`|=y8x0b`EQ^8{tU|hht@zw z|F^CHCSd+sSD-t?I63^^W41WbziGCbl=xRqmpIZo#ObCJr`^XQ{H+IEhx}g z=7Ci#+DRv2WiCL3QNEz+4n|218;bmF#JeIcCF(&3ujR@zMsd&hD8S|f%ZP14HV{iM z^1gdAKr#(H4Rhjqa6+EYY6EA~7FReKj?x#<1-WTsa0h><4?@|2w}wn77L-W`*akXZ z%nl+2fLuJ#rBMlzJsqd+vNlPu66du-wDR(gF%b~kgB}dwD7*!4ql~s*>b7b)*k+$8! zp$C67d<2_EPE*aQMC0s=-MY|4Zd+>=NxV5W7(tGre`Dsa3Dk5{7|d9y2N7A6iY+X{ zy7~#z=N3CuDCgPtg;a_HaotPyXoJdb>gLvu+YsQ6FWS4(WDY2^qc8sHcQjTCpqQ5% zbi(ZQ2mtKXbf<%QGw`*85#>$o;0BYW)3twkHn_#$$o1enQt2IGs>AQ$S%c{sR^^(q z#ETccoa+Up0m8Aeu?%RBY-a?D(|ec8l?}Azh(Q<~G8c5KUubwCE+A%JZDKfl)HvxB ztTvX^OsJCGPfIK|ONSm&m$5NNJ1hKd*Nxi!4~#+G>s zY1v+N9FJ&QKBL@Fc4CyZ_7P1_0xz};TtiL2M0l7Tc0rNfRN{A^rYb4&=Gk-DETsPE z#f!)zxR(Is&=C^^F-)|f$ER6~u_YkH99)uX8|A2c?L?x7jIwNNo8uotSl}`GZmhrO zpN;SW*T_cF5eO@U2*zxXE<#9pfX{yw-?d%BLDRsKG)_|m7#qE-mVX6&cp*@HK)zy6C9 zxRt;xjGr`F^{nOqU(yg@<>$n3?v;N%*5B4G ztS0kS_t7CfY1YMhHwt()1S6(t-P<5bx#R78MmZQHi`y85v=cFe3{j@)uUPb=tFP^e z*NrGFU`+LK5R=VsiW@ED;4{7$mZ6O+v>JR!N;Y`3!hR@^ki0CUum+2L2@ zv4>p{BLJgd)S>d~~vvQJ*1mwANj zLM)PWZB1U_AeZ;f9GQN>BBzsuyT4yBE`>Ymh_Vcpyy4vG(fEHQz7!YMamHLk!CN~g z8dHiIO@M=GP|U3>Xf}`XhhA=LUcgY>Mj5jKLFiJPVfJr8znKU)jn6IXfO&R2(gxhB zzg9xLD*WN~=g-XwxE)Hr^B=~Jd!UXT2O6lKnNL3C5IN* zXen%tnPP)E*WrKgy7l6q5El$0<LSS5cl&tY^kl{k*gN{qh{#DiS z*oCDt$!e@$gE|r~dQYsmFV0K`tQ*!kW#a!zj>F_i=bZWH_eQQ`UWds*qJBrtiJw zw?psQ%i7J~u=+?sT!D4E(;Y#>ef;9_=ahX7#^jU_<<-@bS~f<1bSb4?%*f(5d%6vL zeeT<7)#QKNZOZo5o1x|)xNq_DJ>&2mH=j0nWbN*~45t6U{Vm}$)7Kxo_pAHUb0Gcg z>BgZun}X6EYa@XaE$;r#B=#eKlk`(J(gEw9PI?!-c z9@^KECn`Mb)OeIqKSiko6FR7O-2cxEtAw9Vm^Eb- zO?*O(>Pgl;N-`_Y4F9nHp~g!N{@V-1f3xrPy=6GgzAcwgxHsJvp81RS-1n>y?WXAs zu3p+<%Q%LF)oCYWXz#SmQ5P81=$x_L15HlkC`SOs@qorC$d$7}_%8l5L;waiEt+~B zyb~lsaRNwx2Bp3t)$I|VzhHRy%ULv<^Q4(~;b%-7=s0^k4z{#iEvn6swz4z99xOAv z9WRsz{3)wtfb}h!XB72H?bwI-biQsjuau)L=ZO<48se2$T1kxHfM~UJY->{iPf+5dMKQS2Q2-(gIb8iI-Tp8k8Rx(pwGB`=o1L5kr$2;Nepel+ObEZE+R zOBtfhI#tB|kyv144?tp4u>vt2#FvA)^|*1aO^2a>)!%IkL|upTkbc9f?Zhk_kO zQg2s(lhwMstUeAc#sv=|ukjJ*qA7l*50cn1i&rh_xE1}4uUp|UjN&b4$N=eR|)}CSzioB_aV-t?j`7d zf@An1D#Uo0X~Im8l-r{g|4Qf(JBuo<9L^Rthq6#kHl>1S@s5W6C)oL~=?OB#{2N-t z?e7kRdMP8?Sa9KZ<;je)PpWE)dBH_>FmXpqF6wNz9^F8o!HsfrO z(P_y20+`DH>x|v^I*_`7oHhg`AMzW2)AYU=90WAgD-J`|oYx96_G2}}Ybt8ED3%xV zBJ=q0R5jCg zE+t1jBDY9kXG{z`4ZF9eB_|Aj0>4q#`F$0bT+Wr*hEk(x@gpP+n3Wh `|<<+4E+ z@&Ie?mpJpVwAbZzsN9Cu6a5*T2%~DCC&~V~V3!WtLbaa2g!wm6WatHPgvW2dj2zTbg8 zPyphPnk*Jfc&u3AhW^Oc9H%H`&El=LOs-6lGlOfn^S%uQu?wCSy7`^6g|eHjv5((n zq5Bz?kWQ;^B_e_%{&XqvZu_jIge=_0IM{xhsM~Kf#m&hcQ^Wp$U5<86Hk2Z0(Z{Nw zm=$`0K*`-NH-J`cxt%x1mu)Bvxy=et^`RTgJ(k-EWs1u8TX=m9^O`?-dM?sej3s~H zy>NZToAIx}jjf=Io!c5YgguoDSW*cnOYW|f2$BC@HsRQ$mr#1$Pg_K*)*Z%(-7Q_} zbvozR6KA1DAq;U+8~#lIat20;0x$W@~rL`Sr4WcsnmZj@;3I z=f;(o`Vd~l!SO#n%!ZH2l5qUQ;>(kN{{3S(rI+Z3uRPP->ZmZ7qprHoFTp}ZDX98S9YX&@<-ALGPn7B_-sX9^&Z5eyg~U)ZfPz9j4K zh8t+kv=8-v>5Sis>z?Xj1u+Ss`*(_Z$9^z4ew(l&T>IcWhDfOQ4Anz(3p6^2$=vsE zU%h`hdH3z<>6^FjQ)KSd8zyaoLl_%JM;#JBh~KyMqN;BWT~MYcYJ=q3@@L@cnu*kD z^pNDk6|GFMP?{xslSfGn(lkPew~~a22t_nDlrArSor}Okd>e;u97z@;+DF$ogxhR4 z7;;E)SExr>-k^qZmAE(Ze-N}e?8=>h949fNxDIdmcq$#gikT1i z)$q}lCu$++{7?eOD44u|_Dnj=GVd93-yZ+!Npc!q&)w`p52WQJpA{5Z zaeTS1%6h(#lGaJI-j|CZO(4X$;4n$V(aI@*<`ej2bscYg1tl%V?0!+2#0bKz8C7{I}Cgzf;o?W zGG_hLrF&H@I6DuAYk0NcpeCVtf|cd-&BqOD4Wqv4=LD(LF$9ia34fw+JUOM@nRgu* z#i2102MEc`Oiu(%QeKcp=Fk!o8m(RDu8ImPtm&2rMLjB`2bWP|Gs3KYM!o&f>`&jwQt} zBPsE`@c6^dYboruisnEB`gr&~UtEBh$Y|XyX zs0c=ykL}8%QNa0;{7;Ur=vq-=+L89u>D$tn<&5|#>DA*M(#-XIsb{ePf;joy=(^b| z*=oZdtHz@+>p|Tmfod0I@v=KWI?+j!ZMvDj!-yeiZ1K=B93ggpo>bj<7hR=RaUZ0q z8B6<;NxfG!22#i3&BQrEMwj;}11G(f`9wqpvD}2~)3_om_@gkskJQ`Gs}sfeygr8? zzX=YmnM&!=VS%A*#9(>m7EcaiY1(sDKdmPPau=a%(`J$|(;R-O24N7u81E)54(%8f zG*>%c!PDEf66cKU*Hmih4hCAPP(3@SWc9n}x4hAd*pN?VMk@s-c|4! zjOoaMhdER$d~ACj;kz}KYqk%({A(zjH&@ZLHfWy3p-kKmb}7YGgHjliY}eg>jkh)D z__yDCF=2S>La*OvSNEPkpn9ztpXKrw3oA%Gj@|D?P6zV2n#1<=)=z6Rr}quwl~lzn z?U|zl0#N$bcfH4EVqEOEI#eN8RIb~zBP32u_8(j$pdLxZq6~n=?kGQ8-8oDlMUzl% z=mlfZ7H``{wk=48wl-y3d&%OU{+f{plZ^8{<$(wfphL{99)|?5J4`(n^Wm8VNEE^m zSVW1jK2UWaZt#A1EL4STg92(qVR^rA(V!E&+OfDT)^JN)^N7~!-7piy4Dw9b^;RNk zAaTDIEu6%hdJll~AHh+2RUAJ-q7bBHrD}_{hkY8+C>u-xQjdX@SkgFcC;#MB2$UfQ zuhL5+7IFfCBhat;g3Of62to1lNVDkok^T{#pUS~ zMQep~X-Os494q?N2jhTHWA!J>_Ez(Lp+bjD3$m=dvN}KnpV4{Iar)G>;0%fSUrOrD z>qkT5>B@3YrsaSRRT74^2*2l?`}Mv00^cAAh$n-P>cmA>u#g>9hET+)46V%f=&PxF zZU|!0K+Rj6dziUil{G|tim-00;iFsWY4)y1Loj4le_P>JE@}It@P8wr=A$u!e%{@f zU^<7_uFwD%5<@1GI6|4bA@9rGf~nYKkVIuZt{Ls}>M_nG5E{|M@F2@f$1WsmQT=IA zOZzAX25JHyY^%MlIfK%XlFFB@R5M|(8tEp2KDG7Z15Fm2bx``v)NJ(enoU?b`Af0g zi0xs4VgY;@VrDQA+$KsnhKO{SjMN^CuF_>Oo-#mY@=@5rq(#+N$eayVRqjO*k9*6s zY)GaGe$Gi$y+&kAgm6qsU9Z#39Z8LEu|lfU?6ovIf`#&nikYSLDpRl1-QSE;k8FS3 z(MStNWk?T8Phz+dy`$KYkv0b3T?Xhri=!=8R%HSh4#waPMd(lA!xSfB;kk@#2OP}9 zcAwuGutPfyj%-IqScALI-b1)YxBJ`>?$JghkEB=)w-w zq#hGUVWOm5YU4(7eih?3dUj}pmDiO`WDGH+{D^&4kJ7Lq#pqr*A@Agw<5o!$Gp<2h z-L=uoIKMp1?VN==>E3~M9--7CC1t|b6Gh{@gSwkvAY@Mx3k{Mo^$cLBhT@91p#MI( zYQNL#@tkU7@b}IcM6qyPSebMeRUbM)OE2 zM^Er_BJ20z_#4-n54m(a!j>DQ160~O|5ry;&p7_PIet%_FnNG`S7i6Xr_(;mAHrX^ z$xBNr4&?N~gFRa@%xX~3C-BgDZS0PjyOYSyb;=nOYt#9^e&TQVj|vl`=wr&IcUdJS zuQiL068e$!Lv>~|7cSjK2r2!4$jCz`5Sowdd$HXZUL09#{IkjwjaU@Mf+z|uHMVtt zn?%2@+P%;&G(`YvfoU=$c_u9(!1#aok-7quYm2W4`@P!%m5auC&%?*vnc;$gwhZnZ ztJLdM%Ce9aHqGa(66-eHF=PJ}j~)qix^I4H+%kvqg=pZHnMPnIwALd)p6MgUrli)! zCSE$?KiCYf82xnM4bPpbxRth6=GLqmNymfqrck`Ldw(tbP-eR=iqo`! zi|Ikofxi`KDF^(Cj{BA%*r|dT8h|j#23oyV+nOmU9P%y^5ZSyy~HN{-iN5f z>%J=CW0m+!8s1YEstNc4;(Cd5K&RpGrYJs^LkHT)=}IEZ6umtpc(J_n+p}0&;v1O~ z9Y^RZ)Ir8+yibF6!Ef8xSpb&faV-AS0ws=+7BGOZ3}FAY0F8x{-MPWnv(L5jKH-UN zCaA9Y`M%$Vkh@SB$;v3DY7E#(j+y(KNl@Oy`wH3GxW|j;W%9pt_w9H8C26;+g6%`3 zO`-1lk}y=}Z776r*_b|df>KNw%mF&Yz4;IDxMk2zeZrTr$4!Xh*3uL5vyOpYd zhiYv0R0p$Mt83M|9iKwq0g`86F6lD^(Pf)2N*ODX#BsF1H>t)_(rS;N9?e};>j!y( zI`Q7WpG?~n;=SGvqTD=E_ThmpnVWLD!U=#%-|jyy2p|Gc(+&#DY3u}WYCR;20M*X& z>&j; zgB4?medw;3o6XiLNTj5LV~aUEoT&j#G6Tf2z2>gt%DCW%?Mva9^a1_`` zH0KiT^eO@=eGl2VfGDhYpt7Z9FAPrS!QAyZ06b1sSst8UL>FkX zX$$=a9m7|sXZoD3{q*YjKlT7ALfW0YB-hTzF3p;{Hm>aI4!#xBMKS~L%-IiWB*)@} zt2eye>t&Pi>NixNl4qjun~`h^x+~z$Xkll3%l$9(j(pd?xs!s24R?&2j5sg2TE(hC zx#2ck$P%w0nAy5zB!lisxn``X_UF7;`vCV=0> z9>5}$#egKe$aTzIN^7uAGgHQyab06aqf|IE6)!e3w6?fMl`+3EyxiacgObHYK#XgV-jw+vWXCunstlBly9ezFKz<>g` zUZO(9KsD#aHEksn+)oi>M%A1_Uv4-+Ht~FclO)043zcAgqI~*HRdKC!byn0-Kw5?` z5Ger_ao@_MW&_13@YH%I->U+dQ`A1NooMNVjUKV8tmK|eN&!3`1avl&cErjQA1xKE z3F^H7tAjZqXf#mZIUQaK-7%Ck`fYSKn~-juOrdoeFb`E_j=*PT5m~{TD8r2AJQccZ zk^CD4zLhMfxqL3%%J*$4^}*Cp%djAHQW@4t%R>1}rk0 z2CCK4TxGKuHpxN6VZC+BqgJFq1w*r28L?+)w)#EL>+ht{M1aFNj!xVxOm%x1r`?pl z&IrVSPIAZO>2QZreA`k!Ij)$Kj5e3J8Xbn_>_JIEMwe8h3;{p~N96K)O@M2I-yqT? zR7DiUS*uD6DpHw%XU}edE)5*Hg1|ebn12V8-nt0@INVKVVeI;SB|-_-99yk~@o)Xc z{f-|5i2wTDcSv?FMWbc^{8;BuH2#g#0XoQ^{S8~#uWtVH_w93kEIZZM2TWc16`D`? z`i@H!wN#rEQv#sfJ3$~;69(W6|4s%N7#MT)yt^~(e&0`brmX|^)6@ZeUnkd-r?WfV zxCCc#x>xuYn{vQk90(k{bpe*Tkr^2m(W``BMk5O_DF#!K@wzeXVZOjVYO>Va%Dn2= z;|`>*!te4;`&z(~@zC?(?sgUiq?1k=6?b7ul*-Hhekn$eDT+Ep=R)Fu*)s3?u;l}r zHJ>~eETCC=uDt{*zs$B@tB3;)Z2H6Bo9q9hOF$16BB>-6I+Q#z0=$?RM@AEtj_baMlH9LS1r!@s%G_6 z+!$c|8vuzIH7@Oy%}2SSEy^^~6r0wiOHRWd$^^sG{J2=gZaLjbSRWl2 znJV1-#t=uS)6ZDiEsTL6AH`-vsVY=jT$MhJn?G~kG^6m91d0=-m8>%=I*!um?}Qgm zy3K&m$(!(b`*b4p=+eqijAEeJdur&m3EH2x4WMQ8_&R#*S@KU-^XHZiZk$Lm?2^Z8 z+8<#R&%zc1L@H2j>F8liq)M87pxsdLpcQ!OmqFCv5&^u7b0p^}$qth^$n(oee)n&< zy`ikM;Fx!b#1+XTyRj{`)mNM2y4TU4Ze~=f@~}g;XBG064<50SHKJadL}W%#ke{R5^ew;gKP*1!R3d28Feg_+4D(Cv@JE@SSfCkdIOfbl? z$QU>eS7`fz+RwB==S!M#B!8b#!J$!X0~(|>LLH()z4IN{ajFr1kKE%3%(Qby@s=3v zp~4Wl)-<_;Qq+rZ!x7UEHiGJoVLw#Uq3cYcz6+q{c=AoPf6kW_4Jw{X+AS{W(^!pJ zB)q$iVhJK;V!=622_a*1i5LA%2UnjuHNFvd#41K2%yA8@Ey9BHvmi(xq5>T~1RVeR zVT{bpA>DYO`nS8SY|KcC+)jC>iO8G1>6mCHNS-gNJ+iPH+;hC zhpT*-=*}*DqOP13#Fv9O`{~gkAIXcvQuU>O2tO~dT9*%S8cZ4mgm>;Q08jo=#Mj+V zpX1YpI#B+=F_*7bx;%)uIzK)A1}wkElA{1gO&xi1)&nEzO|K*2{>_uiL&nRN3p(V< zapJ$`;x*V$xVj3Qwk(WomOv-%CoW~|DY)yCk0@(Bce#x|D zGS@v}_QK7?*wC3`JwwxYbet0waD>J!4r|Bu+%?@->Zon;6rJq|>GbzOH^1LPr@~)M zK%W>sP{TuflE}PNQve1O5PlQ?SbImbrQ!mjZL99h$W$cxVa7Wy!5VRBGX0an$-sJ$2M=v_)dA_*&<8&aoFyJfRZ$8tFIzu6V5>ZT3u zjw3~zB9%Q~HI1+D^!>9{iKK1RPv)vC1fs7-f&R+m=FiL>1vrkxT-@*tMTNV?>+atY z4$omP^W}V57s0c_5QOkV!Ky^<@|zOnXU!sq$bDm4%AVrd$ zUb)Zv6#hztCruqu(;-qoi@j3$DGcf@Z$996+S-+^DC!--tf|n#V&AaG-3I?$Kfb0( zE;S+Mg}VPmh^4>A`tq}z4T$%@Ilm=O0R`GIwS|^hH{tr(K0=noO_!AmVgr+O=|5hL z^`SHMut2o1*s8&ZO3KtErw`%3qj{$Wh>IV*q5TfOTieXbrV-GGK z({Z8>F2I64(>``C3ldK}RX~Dj3_YND=t^ zGZL&-VF+ya2%NF*BZ)~12QXQKZ8&_r_-dUGC^N`bY^Qlrv|!w;4P=qi;<`sEwW`Gb=XZISeTz6W2G)u#M@V)ZFrNC}WO84+k zz8TO@x{`4C7BBzJ8zMNtF2SbQ6@d+wg75g!tp?`9xy1U@CedFBYu{ej*+ntk(v|rI z+q!TIT>P*|nDZ3W@zEsc+YGtz2mYdxFNhj&1zr-csb>HvK-a>u6aw>PJ{OtmcG@ul zt`wlJznY`6yb`eE_`qTLs4En+lA`b~RoQLlt{8GNU_H3_Vsi*gJn#rY!mA(=V=8{L z998Z+qAiiFKDFU|mIM0NRR>EucQD^FVsvmNK8m|wM4@QnnF?RoH8q+IT7W|V*B6Ng zkHrNBO{56u5&V^TvFwOh_O47{(Hcyg{VZR}56pl$yp+?kd_&fT{nm>YN+}_W{2bB! z9L-zo7y&}c&KNbn=YZVfg2^LeQO>X!`X#@?d`9WctBTA+g6NofC+ev><>pKB^TBh9 zYWyhUE6d=E;b=)n#K;=G%tB8Zp%@M9#DNpk)5{N-*`xgXooUS}c>+3^U^lVusyhvp z5+x&6G%Nf!iUxS1f)Wnl``VtsJ2h~27z6n7a3oF^I#ee;-+)q)=Y%lD%$h3PBrY8C%-(lEX8&e~z!975RVxPb2a%CU| z9KsCyD2K>*rQ5vAM*R-(U_D<6_j2LLlUb`Puh5pF$5i79TutDD4lMZ!(ed9P8V`X0 z74SXEs*-NHO5sd|V`ccKYi8#jXRm%;CHJ1UP02wVF^?^}hSq&Lf`yXqzd; z&+$L!sT&7>X=oJxgo^^bvfj?Y@ni?jbb%;Si)vkV1T7_9hDf>@04p~X4e9Ks)DEEhd!7}K-*@6 z`?H2=GxUGUK8F=3bj9MuJY*Eb`Ptv|{ z`8%7@<6)sofB9o2`&gnX-ofyo7mt>dIPGV?#ERw)aSN~N3>(0_vJph1uo*-XYuA{K zpE3(^7-YZ_rIvuO0w7}oX#iL;w}XG#a| ziBK(39Ej6DM^-!+DmI}3J5tEpTOEBAovwuJPRs4jTk3^Gh1BQq^b>pdD}Rn$eBpky zuZM2AdADQa<+l{If&T1x)>sAbG#6NDI9(42dr;z8GPM;GU{3D;9mCRHSt6Xfz!(lo>SdRhrcjLCD(G`O7~VPdURJ% zxp*{pYpAezg?P9fxIW53mxQYrKK3E=MZ~f0auiSsFd^o^4%h{@?vK-6u?p^-tL~xT z;NqoC*KG&Ru|+QdM&A5t=7{GXde52>=81kpU~WhFamyF$y)39I#5yX5yq+B@e`BOB z^ID1A2z0=}c2xOb_2uVB?JJ>o_`9$3<53a+{S!C3W&ix7*4&ev|8^etiW}1zAwJDw zo(S6)GQ#4V(waJc)e9bJ!_5YF=rYm4o;Y+zIP?l?R+eQ8K=1S;s7hX^EeJs~6{+IT zOJV7emXrH{7ATDJJz49dJxmGKr0oHbvT?C;U1Hu2eqtPRd&x;l zw+o^oF55MiNRnK+Yj(|LwQ!0nYKf#W-w}}qBInOuK$^~&Wn`Qb$;{<8o!MVZ^GEWe2O&?e1Jgn+ZeX)PgpkR`5{Skc$Eg;{ zf}7A?c#*@BiSNjoeDI3^Uv`e*M0f6z0)tR8$yUfP>l$d@$E6Dc-hIBb;)qmIoJ6b3 ziIL`e0A&1eM@JxgU##kM$HvtftKkX1O!w=qLqsP-yfV}%%57WvKz&w;iO^On!?IW_ z#2Z2n>%cTLweP_1x;U)SS)8U;6H#2FSM33-&}CE0J@;NDjB}7q*SWG4T8}|Aj6V`& zgTh>!#X~ITcXz_Qak{a24LkJGtP=2-l$`}KfCSjb>^a)RhBiVMEudE}z}25gpEGgm zvj7!+-5bp7u;i4X>u(*tVr@9u^MHY61~vzU&~zIdvgyR`h4_T&;y6|5m&cfMlel?s^{vV|; z0BZ|1lOgF~sK{{?q_Opjb5AdOWEwKUSDL6NVOS^$?oP+lZcSx<`hh)?F9|LAVx&Q| zZKZ8?*QGMK78u96DDT(IzAwn$TZy&%-*Ph4zKk|@n=>@Js}U(D;`Zuwi$2C%sal9` zbiu7dfvk-TEKk>l?mW&7xJ}wlgJ(Oc07*WV7@eFO=u*hxFCcbMlsNK~IbSd2PZuh2 zFGmFf)1hkh)2YQh{fHnJ-Otj_Ce{NDzk6Ec+1S^zhOzxKQXG$8abw|5L&p-F9$gia zztArIVx<3RPOrpn(9(x3wCil39s8u)N@Ry3k-{@|U#Mo0dalUYFBRDgN`px>0WuSm z@a!^|g9nzBt#n9*KYB>-SUa|8gAtTv7Lw{zg>Z7_@FdfkRt zZQ7Pc?4X>JalUhTNo}Er7U@gP0}LMgKB|t#v@MRdywAv`O)~1zaG>WKER54-tDs^R zMcYWCR|@`e*J_k_(H^`YRXQjl^j6PfOJ8x}B?;&Il>uS6XC<#?xbTQ(TA$5zldE?o{}S))w%}MclSVL8(K3WYtuCuIVDVSlV!z}nL5YacR%)Lm1gMChEsj*| z`IP639dKm{3Q(zFNad5!a|*R*X0|0XjDlSXnC7c%1e2V)Jy1Y_rmrAyD)(9CGV9$KHj7WBUx} zw^JLS2189JL0CYis1icF!NbQP&A9diIzf7QYaCxl0S}~r?Agg*aRh$f!>2zw=q0X$ ztZ@_%9?4OoE*ehB*^hVJ?RS49c_BTOWx01fonfQE!K@;zO<(;_0XS9uIlhjAcI775 zb{u4|MoQJkQi)-~mBPWZHF@rfC&{%qPB7~33uR!o@*kL&jGwKZ6aU69@~`6_AFh=k zsl%5#f8|~V-w+ImPx}(?az3UI8?v}XQ93O^y!k#pd^KXs?(iFLJUsxqKlL5iTld$0 z4c>E^?O=X0&Jrjr0Alyo-@@kK&+5{+%T`&K;pKqS5gPK$NsG-LF^LU_^&q*y@pmQv zF4dIAYmc524TKEkTF0IBG}BgqS6ZxcO@kLnpYv>}p_x5cMTPFRhVs=&|EzYwm}l2` z8u{KV0E1BJ3&~+;fg~_fN)8q)2l#T`-m@|X{baDNudlx|{Cl~J*j|inP@hRl;smOK zC03)Z2-IBv_@m=_EpFTicb|0!MW3-R5Y2ndlzRnyo-;FZ`1Mi0eY?oUJVN4lU`4?Q zaog8Kk9@<+EM&8tg$=Z57EVLdOSJ3c3WNJSRW1V|pOO8OxEFLkC?^2a_X|z8BZ3%Y z_^Z5X9vwG^7jU3*B8{-Ov}^#RnCpF7={Y))$E>}GpX9CPb-tO*L+ov273?~Pk2l)3 z%oSo=)M&B0<)JRN?zoZ>dOyi?CK5wDp(HIQ^OrSx@j<@r;dT+Vv$)zPVDHcPrJ2uN z)X+!RXS*aEMW?I~b#%0KkpXsYrKmG7ttU0~HxeY`9pJ0Wjw8Dsp)P+8Rnwu20O*C! zza*oG*HVw{xFv;-rFz!{rdtuAhSDsknb8B~AVw|+-g2$z(}}ofIJQ;@buWW&sr)*@ zSchtZ(W0;T5Jh7>i4d}|R@R2L$3?VGa_QBSYqRM!rZizJ@G2p>D~^L%P(aDk(O8;q zbA?k-69E0nfYnhsDRoWj$}Y;7SR47{#wEZSMZdluY13v^R{C|*M$g1GHfA20zw|V1 zItIWsWieplfcv9UT}Ia3(Ereq&1>lDI#xfBH1;;ncsP*!CNnYUFL&7?M zE!sowIAS}{Vt-1_x#G+^WUPdT#jUzIS_6FwBkOY$cnX?z`5OFHFGY^IdVhL4j!GxV zN8bIe;G~<5iusWc^klbKr8lqV_GT70dt=@s0%zp}6SoA6?ZuB6b=_`>jQfYsxW?0X z0MLfR<-~`%M4$;qm2U z-a+<|7DHDbD^>`e;0j*6q?J+;^TDwn3@{!;E`Fm41?8v8fIDLyqsKcT2vtI}dP;Oh znZ@Y16Dx_i$$lS5wCxe=I9E;!l*9S$fVj^xtFv}f_`19~EJPj5Bb&o87j3L*i994<{JUm(mZ0WdFuBk!$!{Vu?^n5MPC07o8`PrJzqH zGN*Wnct}ign1oLTBX47ciFQD^O8<%%?t+|w#e7d^?$)&KxDH#0@pLkDe- zp&w?|{PzHQR1~znm#RRJCt1xHg2U48iSu4g_evo;V~gp+-C=;0@&UoDXR}5;(D=6Z6GX-pYF5ddB8m`r0FH3Li2KU5( zN$=!wYR%a||AvN19a2IgWQhMM=;9^s53t)%1rG0jx+0r!TP$zNkb-wN`cSWXGD{oh z2+XpKe!aVs@#9KkjccnS3rgNWEe=)XnWHV}cM4COPUdo~^2Z3*A63cD!9UKxh$!PW z?miUY_Pa0aQc2phQvs!r=SpI>X9rB;&@#43optYV=lGK!c?;I3%V+IKpHm{+{f2QbHiZ=DQ`QSDBKB^t=NM~!W#7f{B?~RZ2sAEei ztUfuuYp8{qFzq-C9RU~O_yJh$Nr*Od2$ASND|2;mJ6frCW9{_Y0gXJ~X3(={rbp2f zum7_K(oLR9dK88AQS#hECzyB-KhJ968*f4w=lG1m{j6;47ukTDp?U`Tnx1v4iMSN~ zmp6hY;v|h7AAfZhEoDJ5C|IsahKeizs8_6AMveO8%khh-)ET2SE&+>d=w?)8;$STZ z)I17iK0^$0{EG~tC znwR;nkLVT5We8rIzwCe6Ve z`Q2D{S5v&XHb;aV;*W&{FTJ6I=Ck=Kg6nL}0BZ(a z)D6gD$&}Krq*vTY4`7_naj}z`Dr!W8`D@}QAd`j+=qiH)_>o9|Q}>?p=YNtv&s%h8 zN4x|NB@WM`3gBNcnXKv;rjbA^+zy;zf|>paZ5Dj!F}gL<2+_URwA`92(lVUr{G3?I z|6!G=l_p_=^#UC9N6VU{Gm$x4=MDhk8Wg{z?5 z)mOJFYp)VYd>bu9TLz~4qm!oT7{DIi9wvkxe$JY&u~<$N2qzpkZV1vlP*IASy zH(WT+?5%&l|EW+wRL*J>LBadO|9{-!fMpv`ocw^n{>LCL$-;&2|AEGGmnh`_5NBA% z(*HxP%i6$xc>h6lPvF`Aj|BdSU153mF7p;l}9)|c2 zx+VaxVEzZ?D}a^%cW-GWa0&eXM%#hMKmq@AD;gULv@9qfAV&-!AoPExcFv|Qt`08t z_BPH8`udi3mM;4G^bVdm8n$s;ElA%zy@8y7c$YOO%Z0)|ELe`ZL)J4`xIco5V4+hf zWx8f$ibUm|o1Y)QS&Db;Ug-tV>*R^eLmxk;6gW6Ic7J;&MH;x5yZE!70iVKD7j!k5t zs$Oc0OAY0a+?(?+3S&)nc!tj=q&G5J{`E+ca?oyZy0iOgOYL>lC(d_MXjH=fG%|EVktU9iv$8{Sl`ab6CytB6yC`Xrn z+0=>hQy&z#MZk;8U`tl`9Qf5wrhh4JI_lbL`II|+_i#iD}M5NKiqBQzCLL?xU`> zHFIDwU5R}Pmh-mDX9}ZK)V{$HdE51?|q*wrN9)Lxl-|Svd-dIA$gy9!Q zmXJK4B&>39(&(*vflahtIFR*dBFJVwjd@O4oLLg@w@Rvb6QbiSIc5X&j*j%KrismO@#EnVbKzA&aJUdQ$S&8@7=5U(S0XF@YuY#ntu_}JqU5^z=k zi%WUtUCbl{wQQvtW(MV{cu(DHaB32FNNlbJ1VEYc&`Xn_Kaz6bq^DW(Fi+M-U=C~p z`IwlG=9q+uOXn%gbyGPwuRs>!rT{OMzh>HfIVJVhTxQdV&Dq29`74*SdBSB&x*OXe z$(mEzU&kd^T+i$+M*^tc_}6>w8TI)2l37humxgEuV=2TdnR75Qr%l- znJlwd&%)j6Pf z2pmYPq$0y+`kZ>)9iDl+%wQh6(01qk?YPp&X8y#!RMYw5-YkTN4047`P;!>VNAXxq z%cWe`3ZRCS4+V!=*=Jyz3aF-#hLyE7D-K1H6P-Lhb13^2nB1u0ask$3G3FnhryM#sT<3|h+u=Hp-J?%w64uW=q!w{Ox<{u1n!O}I-P#pPmNELk96sQhWG8KGE zLF4mc9}TtI7E{e-942o1dhUldRHxGa7(3;a!DrA^=k?LFh@TnH9pSD#0ot7+MvEq) z7zeK-%})aMlu1R>tIpy-ga^kNLFX&JZszR?FQE zjL#*yQ836zXHKsg=^FV7jk?*UXO7Q6+KXY0h#~I5{5sn7p7RB|5D2 zQ!bn*mT0u@$rT2pT&JMs{7t+Hs_Pakm!8UBLI${H-wHJ`4<`Y4s-Dwn3e6`mUo zPmj9h)n-;T((9$$ z$KP84OSlyjiO58{26D%SSek)0iex?FSw>*rsE^xn4IR-dMnJMnE`1w-z@tMHriG)g z`_qS5syz?oEMdDwzxMZPy-zPXX(%47T=tL;2hy7}wK#{?@#yTniwRZ@yv;~D&(rC=Sz`q8{({iOy&OTQ zHVMA~#qWWpW`byokw1w}&-1KCJdV&8Rr*9(XNc%KWj1Xq$y35V?35<<$%)kOzdFvQ zjiLE0V-X8&gq1ZE%piy~9#d?ixJewqCItq^2lR zC77|V_67EJ`?9l1w{f;Et_ugF)XX`8i0zTwl)qP@iJiHRDafSB+|Hgg4XDs)!EzNY z!Xdcw9Z^aY!`9^hA3RVN6`IQPirc!0*{5<=#Q3yT(XSiW3Zk6LaTytdqir}^2Y zHR6N>S2}CRYt5Ia49pO5z9dos*OR%&Hr|YTk}O#%y>5lcXvNW&njC631)uri`kRfM zV9DtYVLQ3A7~Bz=iOk~NtQ&^f@6&1SR~M1pbs?c((6&(kHFcrDB;W=p#s@C%l4t)^ zs7#YCDXj8f-HcTHvO$HV@(2sRxqii6@H)^ZsU28ccQdFrm_N>E;if`bM$g2v`_%(qlqtQcow;_?zxm)ollXltdf=SROk9-u;ipIj zuqVKMvN#(60stMF?IE17gk8P&ijbx8AA})J^c*!G7ynVk$x|K0crsDJXHtdPTO{@? zJsniK)WgE?Yq=QdGcY?uU1Q*B4O;KBgXnoOS+SWJnj;=wl~Wjxlwyy1&+MVr){B=^ zxnUQ_Ay++iCE-M`HGzzLLB0lQ9S!jvk4U#eR^u3eh`t3(;Hx(sKCH}{))lgQ0p;8t zSLvWt3bS)_;M&*ikKFu;N089lTsmn_n*+&wNRum`YpDEps zd3DhNb%bOiP|ET?g|!O*+`0k-eP4#rf_Sfj0#=0w=8g+(3y{-+LhxIR#h_h&Gu(|= zUU+V;9Z0ZE?d*M$xXRhnNt~Z!q#B|LgRpw#!OF58F5W7++z6OymYnCTo^Kts#-1$C zaw-C_;XsPM+3#xX4m?xyWtu03-OoKyuBu)E0Ly{mcV|#%W?PvO4(&=jEf@OPtE@6v z)~CH;@X~GYn5j3`mvdvoa_I)q0g*#EgN*4W%E$BovJrP4A0(eYp@cEy5JxXr8%AAv zz@NeKWLp@0we`YknNkACn}$~d*wO;O${cpm-!GD}Khs+Jckvy`7ap;^r35D*9z2Wy z+%GG{9C5{YoJoAAxY-)12!#PkE}&ENeO$?6wJ3IN+5cp%N%%#2D&z7f#Iieq10XWi z$D{iF*GIJ8)7WN@F|oM3DJ*5qt~rPe_`g0Td3s~*2iip+(M5$CO0{xS+(+xv$0bVkDLL-ytupok+?=cBp z?*IO+j@>|FfoJ{otMWi94rtS-^1Ne()we|poM7g+EhDGZ15|c%E)=#l`XNdFTUm|@ z48h~c9PN7Zbuv6RaSWw`1@5cSo@XY(aI{6)As!L_wdPsG<2Uv zJwI?X+VEpv9ppDVDf&^9y){PUwuv=ao|R|nl?18W;WlDkI_o_yWbN>|h)Zmnh zHelX!7+VR~i&R-VnmK!U>DA}^kd-QmxE{olV|05ftEs7RS7+-!@5~u{oaT(~o^n>a zebEK*haaf9PIHcB-=-PaTsBmi>?{RcMTzNJ^mVYP=lGT)Tny;!V)$yey1#6j*-RE( z0`)_f(|49894ok2Gb^h*DMwE$EFbqVx`hXXP{^YI36q`qjjvH>F;AQv#p*OGhQ2u`a zVL+b0-xhbU_UxVP6<{!kzm|7JdH5?oT;gh!JcdNo4`!GedO(&BhrLuw@#b%@E-o(e zd?$yZYzn17c58tz;W4mK^s=b(vTHZ>-Pjkng7iY@-v(&k7sGZ5S8bJd!xo5He-2`m zOHtpo9e=1oN2|`6C;V=)A`BmW^wIZ#T-?>~WGjLx2(u{K3Z@5z0--V*C0HJySV|NE zWt&|PvK1`9*x};-ORJcrZYAEpzhdZS=CDhFw|8;~rU^0M0z3U>uEdX9iB~vO$)Yc} zV$=14-p{R#L8eq$AY$|ap1q!qk?~1#tO;JiUGxZ!hLmFU`c4!V7(oUzB zw1g>|Q35A70R?S0AQim?LwzSJk;?2Y6V)gYr+g?S54Y%m)~fE&*4_a!H3A}#1+H+l z6vZ&~@J9}1w#e*|uQr0@?x7P!FU7v^_QhQ>z^s5mKI{RjtjyYbRKgX>*r*HrjWrzY z&VRSHzP=p?vWVQjWvoUgK*u|k;Z+7M3je0&)q)}G4Y9^R)e7G`pp{)+U(~R)sXaS0 z!C&&(RKK4qQFXvXoJT$Yf-DiwMMOtA_C3foXQp@kfk_8tE$^#zK`?M%ZUG=Q)WUUJ z>^yQcvY|gX!ijO~fM=^bg0($%0sdRuhJl`YvE&<_%_3#B`?10cDn)> zs;w!2n{{<_4;MxY+oEYaQCI;^q^(D=8w}k_K6E)+M{1U|&@MX%<!rV6kn1f3LkWO_S;_D6a2&EE$2e>Y;~mKYS)H~r915mivp?GQ-FOGC0SD*r z0nG;iA!geF=H8ic(UQwRkxK1WnnMLtr&&N>#4_-1X5_#C~4 z%fM3n$7nx9Nlgkm1WT3kJQzk<)!h3`S*4C#2gNm*&R2Ug$QK^JS_ES~f`6~vM3hM8 z`(AG9hwCdIcMUVpOfv>aGK1Br1&6)?_D`98^IqvsO4T7lW_82Nd?$hAV?13fUcCEBl#}Cnl7>NN_+Ca!P z58GN#T85JoZD8#$EVkjnmD{E_1mWHCK3q={%`w!;LcSf)H9e?BfoCw)Lf>htu zu$MlFdkDO47s0$$nYaX<2S@#{L-&&6`ux_pIC^|vR1aHppoa>=!?_d*w6%*rH$(hhT4S&@BtKGhlJBTQGTi~8rK3?(|}6v#@j-fO^Qjp z<}&2~jb5CG0)K2Q!~)JoLxl##Qu~uUu&CwkYFsFfsU;lihpVM5}99l7}##`1uabtQBsoN$OslXpy! zgtY(Ak8%QHJ>3z{Fhy!b5-{JJYIT~Qr#4p!dWYu<&3`M<9*n~QA2k+G8GIGas2IKnh_Yio`8(^+|BL#DK9 z5U#}6RDW{A*y&AEZs7vb+}@egB-Pa`^MzT%&IO`t3*k?*1fdrzv|HNIu@U5$?Q|n# zFlC|SjFS1AGmSd=dz)}=b>b6@h0))Pct^}gPie-?pwzD4Qx#3nRk;P1rUUqbb4Pq) zNg}`H!(2bEK(v{53UrRfc*TJeLXNlev8bG&*MA~eC*EQe=$6Y^@rO%Ac2dsWsLWUX zm~8w}l?f)GMFA=t%jFu{K6^a&N0BGki{Gq0)tor2s5i?b)J7_*v11df#;SRNRV| zp?@{H6>0J^0cSoyz`?%pBSlJazlIj8@KECSoPXGBi{-;r`zrUck|$Y?z=V_Ftfq}L3@BrAC_LmK|!|Y zZFNn#p0-ldugLZXZ-&c<0u#}hIygAkuYW$f{Pxe6GjG1X{PguVmsyX6>Ce9W^xH2k zzy9uvY*&H(^yTjmCL11xiO7Lh$HWe==6y49Q|6XCX!t}#5_nmv>rb4x-(_6PB?UA7 z8Zl|#>b6@GGS0%L_Odh@d)3Hx4vlM5m|g>JO47J5L^s-a*^5&<12i2c(P03C_kYAB zF#cpeb#>HLAdg6GRZ@Cxas-n0=CGv2t}i7tU{A0m$*BU)m@u?svKOMHl786A3gKYwcj${7JTF74O zE`!ZpYu_)0Y|9RP%Q_i{&2RsZEPtptIID}B3@1p>@OqT0`stuo6kAi?dxjt6QwXk+ z@~DrYTBeyQ!@Co&89PJ$0$v62gf4}qOCI$D;lQ(;01i>PZuc@mQ)vmY`IVN1v1q^I zLg0GG?67A0E(qw%D%+~cwDG$EizA@^9hh%o3TmFC1%~7H*7dG~2C!zFr++<@l9r?5 z>f>wlEJuOy2YY7NQmcXbKrrQfp~&6U8!V-wgTmgQ*1UW8uV@F%j<^p$LC2^J_1?@^ z0a@3RftUoMSN0G<>|+7_4$_O4i^&jJD>{4{xe)&@Ue51gCk!RrBruP=OQry5n@%*9 zBg4L&E@Qfvm`C6(Gu-VrxPP5Vo+dV2pPz?JL?ni&(W7xFIU%-Y~6D) z^NxLH%gP@91-pEPSFvN~7F=A%qzc{{Re(1*4xej~{k}P1R?59%J%6Qucp{1omQIS6 z4s1-f1_6yzuMXkA!R^tkYqy2l**zY;slq0zl?W)KJ{>?BK1;&{5ksVWAC852*VvOqRrunF4J`=RHZ1gzcx)2~--kf6-xA(UOoC;AZzM$?Eik4-m zH3Y`;yi*ZU(>0=UQh&@bf()sDLOH+~oVV)_P#Hnndn`mX#qPEuC0*e^&V*3`s0fhe z#Lxw$*WnuGn>C!_!`SP1#x$5=YQC;nuP4%F`e@o&Va^;@)We=C51*&Vg_Nt5nh#(_ z=d)tAl#FY-GQFW0)6;ciQ(&JnH%P7_u>48Nz3#;8qXezIH-FWUT|t@(du-Yf*E^Gh zI-f9Y()8srb9w|@vydcB_&Y_eYv4Z0`BtJ1Gum^y;5VxT%gNJc;&nGDPrU>m z_rn7WLtnIwB7ZKEqpBc`$zGMfew9ryrAc5&OnIsT~69B2=Q>BCa&)ZNk?o99MlXnuTJ!KNDbHGgD-c;+4CPjzjYS?skx|;G0US z61L4afe%4M;!dMSAa|#HAn*qRo@GN2b8P_h@eee{lG1+}G+;rLKT3!|AY>5vTZ~Qh zAeyejFArD=^l{JTU=PaRR<+hUtDF68e?w)l8-F?+b7RlU=rd$6Rfh-Rl(;eMx`~4P zFL(%M>IzSlg1}u_VMi*kB>%I>EID(89Q9qNe#g(1v64{}+>#t_^ZzH$dAMGa>CJoX zrwEF&jSwpMD#Z2NA}BuaX~49pz7P27sr1StDr9~Fnd^PmS0`cgNtBZ?z5K@rTYZFK zI)9G`iDNj3^FM4czhYc21Yodr2w@Z7NbneF9^xbMFHQc5!+6f6h1o2(r z39zPv=x`>i{^HBh&w%>rR7>y(eh$9c@qY#N)WLo5+*N=|JFS`4n@-YiG~i9p4?VlJ zsQlt_u#ME8v`uYrasUGoK?D7p^=wby;?h^PN2-1an|VV-Dw z!l-Sbm_h@NwSN4hBu{4K>S(ad1b>Klslty}4AmjW=L^jq9(`~jW@gOfAj^ynqMw;$ z>SQDN-x~Yz5$srZb=ft<8}ofoJT5q-^>1ER$eqiGW(!VI{Hz?}KkI$2ij9jqh&poo z;GuFzVPBnsG3{?_4Ve9(fcLECNGu7a29N!~arS69wxF=DBT^n80*>+>wtt;zSk;vf z@Q0HFIHsNik+7;h$8SQ$zC4{k*gWL`Z`-#gVX1NgOtTz52_2_L0j$%>cy)M&pot$IrnPwSxfzSuhpabte zEJArQ_o8!M;aBVCgY}R%mJFzjBNPerO@(UWxHQGd?-QlvTw;^7iQ8>`Zb zP>m2`?wkM~BY~0lI(S>j#zMSErpGg4Hq3gk^SCkfUpW_ne;qwxxd!?9btH<2{A2y0 z$Tl9Png5e)WM=%Y%Y(TYPxIoGQ$E3%p)YK1{4|#MBY#!LVfM05-kTa$`jk$X__W|Q zG4Ux+Q5yRH#U}Cue!5Zrx16w}n>afci?!?1QTY1ezX4E70|XQR000O8noVs@x96b) z%K-$MO>IrLwxa_t2o9P}ZB4smJ#cX@004uom-DLwBY!niss&^K@*_#5=)>HrYsrZ! zv89M%=A1!QnpW0r|xByEfSdNnd#~G^z=N)W{+ms zqFvU_#c{S9RRo|BvRe|3Wt9o4tAU9ssb!}&%jgK<;d1}7> zZi{0*!zNSr>C1IFtlDl9e*U@|c3b}NXcCTt|9>~5bgRW5zxbl4`bD{|!iLv?Rv6T@ zeGNOb7=GXnW%fM|M2MMJ?*K=(abLf?qs6vdT$LBFlLy+(0mOXMURM?+n{qqN0Cn)K z`FB;WdxOcjou~!%wAyynqD0jF$Yc}Gds%I(W@!g`RsC~UcU9QTe0@_l%l4)(`rQ`) zj(?zS+UBa-o7NZAQ0$s*IV>)#Wz=@jHmmx=;iK!Tf+p+Z9=as$dO3T{~x<2**U-H&;{trqpFhKQuVfmVYY;rps2qllKA&cJ*gl_TFWRO8kl3SMVJDa&e#SuLW9$y% zrnxAVz)4+Ayo$&ls%9vL{kF>5j$3WJ_PT~v1t731dk4nO$z!u|{>A+Bd}3QwYkwGy zraK4W(hTrl)#02Fhd3`7$OD;WLE}QC(rsM=v~2goC9J1o&gczRG>pmJ3;BHhMS39y zB^F0!Ap1dk-nZ*&pihFS%K8@TvhSH@Z7<-{X5E&{V%M$jH9sHGeRZEcpXEXw4%Gn> zL9fmAk)~PvlW4T7V0Osd$e@C4{C`zuI~t8%L5m*vqRI@|?7Cd<023qyN@||9=l=j* zG>7&~+WiF%8Y-MIf##VIhtlwXv-NV^lpDQ=GzP-xFHZ5RGfnOCVk_PxZJ;uADg3DG(w-l7MFPT^gM2=K}@q3}Icin`*WN;?;oG^`dI} z2*L7k?u2x17=H$!^Q>-=h<}cKCe^Ybgy?nW3HZ_=1%cM2CL1V&Xbkt&NAI~^Cm0$x zZMWbJ-`ag+fIrAyK6{yc`T6g% z8A`Ms2^J>Q6QO3+JLrZB0Xb||cz`j}qB~fm?xORX~bXZL7Co;9%TQg?5ic9FndW_I{R||`%ExJI_9PW-{p2C^CLDPCG+yH zf1W*m@y&M`?lV}Hq;Q5d&@-kV{p$o8%`s_qIhsYA{^j4la42z8WaZLkWq%Jd?m=T0RRdn8fy6*2seSm329*(xcy$_J{;kmyKUhl=jPtP| zL?-3+c!7#y>X3+vW1MQJAey!o&xz)*MQ*6(O3Ea={Kbl2)d|ELHZ~h+w*9}7W}d^M z2lxpq8wC|@~XX&mSwS|#qsDrKD9+l zBQ+W9I7x8B-$X~N4HUI)w$2E9tyK>Y(Nm+Izkl^N1JN_}j|`eXn4-KQ4Gm~A0@i%i z&jISDA0MLDmw((;#>w)B{S*X14(zXh$a1Z|2Q+&zm9blKU=k!*@2Rp2rVgr%qBJ__ z?D;?1x^eK$mkOokqXP^4t1$$owq?xVe@Z)Y#~wi%)4-w`CuHr2aUfNFEE}t0YM~rd zodx$KRg0n-xJGqP4Xo{&MDMSik)nl*GiodZYrNbF?|+qZku5Z%@6Em(T!}F?^h)Hj zyZU}-%?{PsnhR%?SY-c&BlF~_`%|`T3ktdt~>|p4r8}0ihX-#==N^(Y74-;kmCGV11(;H zI2q;?I2`BiPV($ifnj?BTT~cv2fa{j=e#QB)pv_(J7i--w8Wx+z^?N9lYs-1_HTk? z;@OIty0QkhAQ8s)H+l51%Qic37tX89tsYcpyMNrRt7BY0$Z3p*f;T+AfayN$CL<37 z*l-$6TGJA0d8q}%U|u_fT(E>eHrA^>n9yJ|b9e;QXK7}Dy)i0-i`=fa}ntb zJp1HC;wArK441Nim8_?CD7_PnOrcG`y)X9A?CrND5Il#L!P&vk2K1%mFg4^?^_>^lMN&r?bC8HeI`jo}97D%It=$u~v}hfx&&Zgq8#K5wCSeL< z+BM=lN7<(_ln7a{DYz#vH?OhV7vOGK0m|j=6gH<`F9CzleBQw~Lrr!`K3Co@;DGyN zWwSKDB32F|4S&2dIF9qjlmGF_s~68-{C^poDhgmPD^R-~xUwa3j#-ag;WPte;qqcY zVyYg4{ZN534Cw4Su+I22fn+gk1Sp{qk^n557ZD&xlPe3h`%)~oHrfpjskX@UFt$gu z9>WuD+B3y@Ka}8ZZ^wliU&b^xs&R2XMhyG{w$J_5x^)__-$Or)hfow?Zt{6DN=bFs}F20lN(`^1#_MWEpL9_cWrWpct zLjMnF#*X+4j67bCS%-y`q>|Jb`~0=}6;?1-c9d*evX4j-+x0it#JhGZTH(KKcPjKw ziY>Y)_t(m*59(yxD`H6W6o1ltbE`*Gpni@w$MF&Ez_h!GKt{JDu0R$wIi7jTBM7}}L@(&3@P#kxIb`#>q0c##Mt2sd59 z4A8RkEF@o4#yGp85PZ-Kf6lwAyz)Nv=)yt-b8UP*@je$Su!8k2;D2#e0Ut*n-M(ec zQN)Pvr(i22%`#(pMwqrnm}At@4cPvRvO}AGz*L@|ze^IpVXmX#-_-@3e47o49H_3E zZ!ke;+~q&td^-Ml4*#D#!hj$5ocv1ffi#}cD{Adu8INEG|Is01!h4v{z$Praa;TO8 z;(XUZ<{G&Th3Cqh1b+!he&XR=x5dsBY4j4e#&=|KO*3ym$AjK9ZtCGOlN2>RF{nzQ zGwhDs5C5=JT zudG_MNsv67>c$>fn7}hwE*CpCv4CDV(QG`)kL7$K4-K?Dn}5wb`@_b`lnug~YELY| z=7!xpSyaz53+K1g__KE4&1KaX>#$l*ktTRCsJ$$-9Uj4+@3Y+3Ap!-~F-O!^;5gOm zH3h80$moDJ-2Ao=HcJzBO4V&OlXd^Z0Q1ltI|sbE&4Gj$vYTM4u{REIbOQEe6r1S_F#5*#?Zg|jHP z<$1lXhkre#c*3sGcq5MI)B^)T*?e9xAA!;^Q^YM-8^qHjnhux&r-!6#KJSH^gnJ09 z7SJ;w!ROqLXbKTkk%DY0ONflbDM6-yQon7Rr3RDU$v)5(LIf7MO8zH3;S!bdN(FU|l2 zGlQ-40@_UtCX1sCPK87PfXIOD+H7D1nhSPE{IN);fzNBgtX?!U?Hx{yR9k@QMmF+# zsDFX!{2n|gPP#|iN8k@#Rn09R!Mf~Pf7$NVOQa08R3u*qxTYD{pPCwb(y$!v|K70@ zdt@|dKFhQ5rfzm1IQsgc(R<9Bm)ta`|LRgmn{b7~u`+uIz-MSc%znxVVe)6Y8{m^E z>LyrI4qw*2l0&>qLsGI|Fs&aiEBK(p6n`Q?2kA0HM0;~>V(Kybjr793Ae!ZX21-*z zL)V&QakC40AyYlGWd-yInBu{(so56EX3DbH6=y%?hJ!M;%TQ}<@V!fNbw9h?!TKsDt^{|3I>=L1EL7zIY*^z77i)DrXpk>3!aAbrVRz%s} zDD)cJE80#qqf1cfc1$;xm@GRGmVaHAk4C`W*sF(U15L~s=aQK+Q%D{z zq5FV*IMkbJE;iV6w_RdF;)a9gWHNQ8EC5+jmFvDG%Ia~~!6Lzy8xW!GvbTOZaA&>U z!3<>YJcX9`7Eh>4l)N`E9a_%cUEtmL9q;4?Fp(LJawE-on`Ocv}67LMu{{RHR< zm@57Q*$m#nGsdfv(hG5Eea#l14m}V^}3Abg&SntG^L<$ zDr{|tYN5+ll@(W>X=FIWYA+nW3QZK39!tLzPoKYj^ZlFWe|ueg|9|53_b*?5_v+2F zr^UC=-aL8w$=^F`?$(5q{FpKboNUi^G8=qL=LX)lI{gG1fDYmBKgir9Oi|!6 zy(D%F0nwMmrtXp1DT5gGpUNK8@x}+)H{}(ecneI@RkYm{%QraVOk&(&RwNB78|D+x z0(Sctlu1KoC*kI@UVmI>n;HoUec63Qp|A5@y&llE9!$^zz*POEfE-PnZ|WjlNj z!1Y(S5wMB#^F5~fVU`zWB75ga)K}l`LL&9j7)*NhI5&9C6Mqr7xw;6GSc|<;=a%EH z#P~r{PFf2{jV{+(QY(P8YP@2oi0dS{S9V!mS6)OKp!j)eBmM1Y5^i+_;5eRU0RR05 zFZ7D(CYCbPcX%1YxpW@+h-+BHU;Cqr=}Fq43l2T{Grx)YN==c|WC7_M zM)dmu^U`hF8GrDKimK$!77*89?!)W5MbWkGV9+w(w%hT@d^!s6Y6*suQibJ7FkRz3 z?m4RD4U>o8f=zsS7C@l26zax>>hFIS^rmD!$_xq){|8LZ*5^?wCdv@q^%{SNugk9I z3#iyoyqJup4O08W^pvCPH~yNR6VN!nUwnT*Wl z_a(>EYy&&a}UkjT;mKrKDuSl;EXIe zW_&lo?}c}jBQ1(QAna>A)g@wufqQd`WTWyJG@$^B5q1*8ZH;Ohnt%DvoK$D{(U12a}g(QuWnnxfQB_ru%13x7K}Sux}ujK~xL!BR^}h4s1VHpsW| z)z{q3KT<*zQ;9i5lmdHJt@?so6K%HHz?Ka9@a>S&xaKek`{ z{h)Q4@ld|vx^OamTtz0$5P{3cD1RL`+af-$b#lO{EevHV1?( z`M8dOrZksaaO8XUC)?n8uK4V3uDpfYzQrJG#A>lpvbiK2_*YuZf|Akh&|S)LTh^2@ zzyZ}T{kp-J_YFC1csN^QBpT1>d%zEPp9;(+D9kmxnGqP&rDRcHp{#ZFjv+`71><}l zBu&iSL=nk#U+@(0`+#8727hv{o7t-)UtZwk4hW1Wxk-r(C51JF`=y)v1FNu{TMYu^ zQfgywl~XsI>n3RQ`%wwDdvqoqjvPMrKVb`Q&gyJj1Ra#7V z{nNQK-Z+>@dP>kHZdx>d)~I;hfst@MIh#Zh(?n?wO*abMcuLg(7k|<@EW7?(gAoGK z>ylB}r&4fN?jn7XKHkI-2m1$co}F2ISZ3Jw?)TmKde^i`(LnbcKd!@Wei$C0=$d$dz8@-mHM#sV^#lRO*ON zEQz6vy@gxm$^U*gbn6$Ha5;@So5RE)uyZ}jEv*4)_=07E-re<<9u!2o8&8y z`)fQQ?W!54J!#1w>;tyslb8P1V`5tP1^HU3s2>T|>fl~`vki7zOxPS}*Fxkq4 zMY*`FfG@g`_PsBmvsnn$HGn@ByAHm9y_lnf^Y57>wV3u)4Xz)1;DRlJrkg9Ag5St% z6IAP+U)EF}Y+c>f3Cp={s$zJ@XQfir(OZev8|%J2d-C+#XLIP1hZ7hsK~+@EH~|$p z-sE)ua(@+b$V%#t<#Z>*Br5G)u>eG%iBfegJs(`5JOXBZ^7FmUng^ODM&nx{9G=A_ z#qD}`F@rJYKQ})&d4l#1%?(k~oAh;>UyB;*8ZFIRW(8unq6;`?5qFRLm-YrzolJTm z<|N=?%L*&raJbOU%K!@nytj)7_3$B6`x|UV34iYw7n0viOi3N_E}hcBaph-D`_#7~ zOzNZl%z2@lHNpCT3ltT__1DXe_4iJw6Lj z;$61k8gPlTWCInyJ=I;#PCq{bla&7OrE1g??+|mc1Xd)&&-{=Cy7MgT?H2ngLd6d@ zSZ+k`xxcA$%Mgh9q zur7f48I!v@Gwv$mcWTprGyH<_@_(s}GfBrU7!Xoc1WVY}gT-@Az=}#9LzBgvA~H(k?Lb0`cG3md}x{hLRjz}f7-OEqvzWh_pt=d9EyYo93-mkNIJj~i}gc?A+LDRpDUADU*H9) z&6!E&&m8q}j-TzCtAD1wX%a^w7x$jLnzYf=F)qUi(`|l*y>{gts=uvnrOdL+OD=|J7l^Q7Rwt#Gis=>G&@_()*lHf76#(29go4H3SfFqj3T2BEvQH9;-$;v;?1C>Io%%fOPkiGG;39eiB0#p;!`GIiG!FXy*r zyUoX|wmo@|d3vK``2W8~AC#v}V}XXE^IG(7xT{?f^c@F%r*gqiipMy9?k|P&VLI`70E}hpzDQwOMnGmnsSC>+_yq-mc!+>k$aQ>y?d7S^74ej7C|u zbY%_1C?D|LN~fL(aA+VqTI(RX7@Ts%w`g@3mHMNPgJX3^d?<^ zp^HYz6aoBke?`}`TB?rji(@}DCHH&$vfICIMK6HDcA$<<#YG zwE-=j_x^hH6R(1CddxP3*$B|0I3B8dAO{R%VW}ZeDUXGw4w92mfhC_ieI> zETIX<2RkuqNIsU&9I&#pJ28al{4}F;me2&e&E*r*kG($osQACn?~`K^bp5=_BKLOw zZ0R{wJF3UiT)*O3WG>iBI28Fu|3h3OX@8Kb(oxQIxYI)BGDiT>`1~L1cTzw0JE>OQ zZ|Qhe7EuKIS9_lZr~fJM)7d?q_h~-6d+Q`#ib zJl}n^_vx9cf%jPi{MP%Xy_Q0;D0gi38>n3Ca^Bwpwc{VszwROoJ4@bD)gm=Q{C{kE zOaQScfiF5vrt!)&iEO?#1%%EUx19d3Q~eQ`A0A8}oZAewk3J@MJ@vPV7E}HP2jv#-j8L~+R_mw% zu1YQ)S0$zt5}*Z@(xpX`EN_8eKY#HVkMjll%XRh6`+}Bz{5c+C(3f(vnBYz`Ki55t zF#C0bpG0>!?n!of+r*moi@llp)1VXk-G)l}q3)JvC*ndai;Wy2>K*h?7o)ROl?HCR zQ!cpl;-UM(j&{qf`H*1DV5d1HU{b2wNZ*UWC#M({-o~v2ueYYiizk1oc7Ma%GbBE= zLV%F4S>kwyt|YifN15gCq49C{9-1D5^84^1r}r_iR3D&UWVIm;CsM!=mP%#=A5bX+%GH!KQcSMTQ-%fK;*xu2TzMJ; zOQ!C%GsqOG)#Xtx!sTgW!2Xoeab5DhcOlGaXpbhOO3^eMleodBc1_~vfgVC@&>Vwm zK4GSF$#75VW>>{^*`EI+#ec={G4g4;3Jd52 ztt?WBhPQMxS<6Zsz-X`r4F}fr{=*~H0@iZu&UsEPB`l#;K1z@QIn+W3pC7DY z<<*_kKTBOFjkpGO27k+3o$;%Wkz8D=bIAiS)>tn79gB~V9J|X8bI*ckz#hNLb12b? z0^j8JQLv|hp|#(g$4*4~55wRF!8NdVLn`i`0^*nCg2q!eT@wV&Q31K(uxhz<$vsSa zxkCeu=TZEIwBe?jS6~)UU|XJX4Kqm;9Q^0>c=m_01TtK9Cx4#>pxJ?x077f;sYg?z zte_{qzX=N~8_BnIT(ukVAeO1=F17yPOU zkPoiLCKKHw<$vq`IM)W^>tTseRJ?Kr;^j3}x_pISlGNL zuv2I_e*@(A{JS4Jy!szrCi@K+@{}@@ZeW;<2d8A1VKw_BRpR0_0?E2vv}hd7GxPql z0z1!9ilu4sDkC)<_aSE*8h(2>pN_9i#Dz~w3(SJfo-_4g_$TJ2% zH@SI*+2gU|e79OvT{IQ{JC!kRn_#kiKv#aOKtaRmWsA%4g!h9shLv9;j{qf_+7od)I=V+fl-tM>M zV|Rn^F*kqw`#=8aZ9(K^-&3IY3QA~#Rc5OlrGK88!hcLhPpI&CHQe z!`lu*q3_wGqBsUaKz(Arv5r`dLVHkGo;SkBwQcr%U*RBpdEb|?z z_kWwZk4Nxpz1i`&43lVIJf$i90vPJe6jS;XPheJRQVrivv>?r(uIkYsp=+};6I(>L zm2QzazcsgOycJZ|R!WsGy_6h@7kUxcGWGr<6onuxhTb#NYDDyxvSJmNwZ7vu>S zH52bG7fZ_?jywNZ8e5 z6S;Z0#$8AaZ)V(c!vi$Og~adi0v;H{bTA`*+!Xj3G=7nYPL}k8L8hjDg75G#5T2{| z43$)s!w5FC__o|LP!r95|DuCJ2{wxm5k5sMNPln- z4&z+HF^t_D!cJc44%?CYlVSi8X@7Cj0AI;Dc#W!rt zWiGDFOMTK~VMe=S(t*_|okf}Hhj|443wi6d<=~@ad-&!i5stMTf=6@GRXd}%F`VDB z=`Z59&OOuE^*dm$J5xP)3Ef!kgxveP27mbdJoPTRU(6fkJ*6Y(r++d%80bfCK^J!x zS5(gKz`Qd>Z= zqWJj||9kC8oMfq6GStk>oNCzfuYLn(*Pgg#`Auy3f)l$q9X?TUqHwWz#DcXb#cBy} z4=3JWi68{aPCeV=!+&(8B%`*$Wce9$+gsIj!plgfcR&h4WCHC>W2Oo+_;{yJV+$1H z@Vd@vh*hMP)T8T?o^>L>Oha6G-}+z5Z9plR?Z+*-{3>-eX|E9m%op7Km*;<&HzYA* zk+c+9RaL@F5A;*w1#(ZZ;Vaul!RAvhJ#Cs*!(tw$1G*!R_ZhIKD}%O@HTB z|F6Wwy@2)T`8Cb1@nmXK`4UxwKb2>k@?dod=2r~%qMI|OoLk}_ytuvpJLqDJ8v~NN zj%x~&Nu=`3s1Q}vQCv_x+}my|uFr{nzYDj;Z^*erVx43s!D>^IzGV}-pZQD*dwr$(S?!Er+V6C$n>jR6RB4HOcaC z?D;*5G`XqZ8yiA@5tD+uF`^53@jE8Bm6={3Z3cqbxRkSuYk##SY~YHU3WJcQN08BB zyh6puHa}WMO|sRj$Q1t#NK>sP(5CsI-4Rwk!v)~>Z8rPPEYAF%^@tC3UD72tCdLwk zHA+ZAI9-L zB@U@SP%o`S(HHW%*bYGO>K;d$1 zdga;0&N1W`nNyC?$;UPW+&+swD=cDlXsT;u&~2)tCjdS?B%74~)8PL_YPD|efWm{PD>a8kgB*9J$!>CHE7+r6|j zISM|n)e9b{OlD}~RI62D=E(0C9{mgq;&7V?HR+YTI_a2T0 zC^(3~{w^jg1c*S+OisqYrpW-h+P_Wkzs??6vLlHqYbFY08oRO(Ap*O-+bhmFEIFdz zwa@IEXJauhI2Zws21}1BP3N_dO~^ZZY5@9qbLB(K^O-Jm7ajHB5RdF-a=5L_sdH=W z$>pOY0?2d6?3xUI-_erLr+WJ1gYDLU%1aXm|%bOuuO=&891wbc}YY z4P~b4aV-IZVi(eLLkWNvuy@Xv!~NwlMAI(HK|7+J#nf^QRJl`HmSIFx|* zM7)20niT=6Ez}9--2*q9V0V4REA$c8*L>mPdK%5YZ*{+X0|Y0`7*efx^~xyhvQy;a zTMAkuDyQZMOP5eai`J*bGmFII>BKVni}?8o`0Bi>Was1-)CpgoM8ZUx-)X<=TT{to z=Smhx>@vupDTF)yW4xrwG3|3d&qfk+w+CaJ!yExnd5&tK0L+IsG9G+E?4KLw&$sW_ z-h|g}!s%=HA5y&QuiNLt;01!`)dGyh*r_e(Pd6Nd>7Gc19|8md$XQ5&n7XHlz3t52 zZjbcO*H4>H-fDY%0U1y*7HpxFegRi+xE+H2R7uFQgV>{yhf!oL#+M3NgUB!iIy3dz-hptcNk<(lglW>|APfqsN`|c?x z76QS75|CBf%idMxA%5LYEG0(^aomyqq#F0fljY;aEmzV*WH|7%g0C;&exWn97T^iV z59ye>eD~=j^rP=BP{1hs$!*Zz`gS6`Sp|sbiVkU$8wG6>DrHN&g_r%uoTm`z$0EK; zt&lcX&+bbZ$+h&N#C#=dpB6r4vm3>wn3P4rsKn8X{Fqw~2(@6E?_8Pr_P!VJ__-fJ zUEO5b-&?u0>C{CJ`!k{d*^5(^T!x=c)(dXWaaBMwLg#_tt7n&B_8wdDZCBR{;Q>el zS~r8OgEHq6U7MAtm;(cIq%+DU5ahzehT}Wy0g--YVTN^&acMnCY|4?Gl93A?p~F3g z2joA6eiMnqBO{{%T?zs(!-xR;&}j`|(QvLE!}C zAu6#&2UH-y(ShRKanbuRda1;KB1FKTAd(4zX)0`#2R(OVnZJ;kS-?2_lG{b->p}d%tD$P{ z03q=+SaNjZRqfLo;%NIqdv&C_wa{`G{qY-0@bt<&`~-yCf{i&cY9i+Z=K#rqSrfLp zcx{`cJ8RHPWAE2!Ruo0WX!h@eyVt!n2DP3y6}8K=m<6-vsX-mNx4mUYtfA_XDfy$t z*y|q~Rl)Th7z&v`iBIX04eVvHWQ-QcDC)?cl*l^7&p-*}kT+9U-@Eb=S7lnPdQc5u zVpDx%WquNVl%woSn7&$(o&eAkvFzzoI$Nm69A;{-sQXlxr3ffu>3m#*puvT^y)~sf z&R7gN!(m$l;BP17)B^aiNz=AlHSDxKN2E(g!Jkj3+t#PYKQqMVSHptm!-y|~L>3(c zI(=0h`-m_D0#)yOb-h#-?Yc;kE=1Y=6kwG^vK!7KBx15zy+;M34ghH7VJ2*l1vS`; zNPu7c7T6U?no0T$rXeA0oRCeP5=}6v3<2Z4{&HRk)qn$DkzcsIvb-u@YP`80j7#7K zXAp<0+M-&atKF(dCRoYUpf;~cbZ7}vq2zN2OZ{VorjFijXn1tqzK345#@t?ACNL9w z8v_aIk(wNx(?-C7Ex^WN;7fd2Ow}OmkFDTOC2VY5LmmygRP(wJ%Tr=8`LPq5yPQ>7 zhO}$S{>dKpZ%RBz@J;ejxej0luA*%0n5XG}i7lZIKZ|;3snqJdIdK64jf)Z;-hvn# zfvk)ig(!*VD=Hqojo|C2f;MQqmK{pl4$1TOze(g+M2mFOnSh`zkj3}-K@w{U3*HlR zr^<|Vv6;DL2$x_uAzJ|>w8`Ad;dzz#D>{oBoy^puCJZV%4Hx|-4_Me>5Ul0q@a+62 z3S|a;2S%>T-K&zW!bst4a-XAMbDGNd9Qk8CC~)#oTy3;X`EB;L;;d7w%E1{VR20>T zi(i%-4aTwIAAp{1&5bq~CO@Tp9yZ}1FB>rdD6EDnwv_HBs*sk^f^1HcbPpdAQLotM zg`I=lA=Qn>4OQ!t7*>}Z>ap1QG^z=`cn`6n2ud+ML!(l|#p9<`sZlni+2p9CGSA>< zig0}SIjn%~vWzr3C~@eAbP+&oyI-j{=)+Y(wK3272;dR{>!S{HFW-j-J0au7h3qqt zN<6!TL<%;_s6S3)AiiH-Y06KZV}wNH(${Z?JSP5W8h!kv?JlivSGmO)+nKh#d>Q!P zyQ|qs-L?d__qiG2{1+iU^yH+?m|L5b2|P}knvToe?N(ODUtoN#4GbMYA@?;fBV*I< zXC4lF2%yR=-|rIwA)9ZU&Lk>Syr5$hIBHl5+Rh>`)RGrOyzhYrH(zDjM@~fe#Uv1Q zgDBB27cVkou<9utgW}I5Iv*BMV1`KC zm1FCZOLouuz90=l7At0j7~}$40-6k&%Pd!;1ALgGuvM~`MdX0kFIoqZXUrIxi9_Jg zpFtbLbw<##g|U}u2MJ9Vlmn4USmuQZG=$=4CaP)%B&9?(6UO0$xEKrK!kMhT9Z^uN z2pxM@c=hdIQVqs~c??P+RaQ@s^rHQhFw&4#WiJj30CGYV|Fcb^r!CZJWn}B#5g@PJ z0;r2A%QT8k3G-;qVYGyUmRIO4^Gm&O!9FeH{$2+cBnLi0k7n<~y7a@UW;V3SQI+UO z@V4UDBN}lEEhENF_on#dhuBOT+}WwHZ-cUl@)h4e%-^vpB!|( zhET@*9Egdfe0;0#fcC>YT45y`VXAlB7ZKjq52geZ%Rdhb=dBkJUCeAitkv#81b~SM zVGqK6U!hX2k5`^BR0gu=pg>Bs#L=yQgs-{`{xx*KrvUq=lPQR3s&OE{gcZb zg%3Ule5Tbk0AYc0#^1`&g9~c;CRE;E5O;1I2>Uy(NJ~NxMB!H5kwy+zYl7or)Oo+0 zXy&vr1Irl|$rb`cQVfh5_@LWX6;Q{RXo^N<&BKv|Bapxpx~zK4`4(o9Dc*>W%^t!( zL@ozkvQG$HD!l=I0@C)lr4+q)RQEDDY(HaKNE_9|flLtN@(bkaV}(aAUwg!aH3_H- zGv03gH;iy2#GMo}RFZL@_CG}VfT4D6qb;iL;u86-MOmj50dR}*e+QEpaDoT(k4}QEISw09>4d5yfh!C?{7Iq(2ml!_ub=}u2i(7P zlbV3$Jm(l9<>V^m#9W!A@6coZ4ToKpw`F>K-@sR+oNaK1Uweo%3>YmL}B$R&1RTdC)>OtOE%A-22caUlR-4g{o7#*ib5QOfwk9p48U= zw3@(`u!|E(nP95F2LT13?zqn|*v7Vs)AQv-JSwcF(rYs*=uMPCqe5|*taYrywFWqc zYN7`x;B2B7pqY7Zu`;<^(88gq|EAl2hZ)qBUDrvEK6=u*OWrnrK5kEc9LO_8pw&OQ z#qK5DCWpH|-56W9hEEzUv=$S9JZxAMv}mY$cw)7S3Ku`&000nauRDfR$`-h$Zcwdu zA`~*>C6{bt50D9_oEi}+9Wtr{d{?G>0=F+vUIHsgrt)LFm~1-cm#S3&hQv;{M^IY) z$!D8ZQRq+54?aHs5P;y5^2_NTZ|8MpB~R z6-jgPN*Gvx)t8HrchCV!pbekL3bp!#rU*)MCiL5q6d`*`#^Eqs*rL_>1bkyA{Pu7- zI`Ucc8$xjd6!%NstKOA#cZ3qC|{qbB1ZFmTB{ zc|@IG5McQyEsqN*x}z+kC0%T9%i)mAVu7t)GgXV&bQUgZz`I2{qa-a)7d*0#6;2Dv z*_4d}pBJS6^ypGInyE_YYL8X=($4ZB4&aCc?ra)ed5 ze$g)0?3T>v{v|h%r>q8-GW$4peonko?nF*{9}p0c%FT|E)gptWESGe4YrqKt4JWux zyFR!5jyf@Se%rCF`VprtiyGcP*B(NX>j3f%^CQaHoP}& z#Tq0YVo0WKSV{^hk}8M=d(3}Kx%;s3Q-SvA^aGI2IDXVwAgadp@YBUpbmbYS=y}#{ z2c)o<%js5~%t z<%y3B!|NeuVSw2YW&<>9Ole?z)r_-Ud#N(f5OJ^B>ZsgsqJ(=I1HS8`!+>b&0sDv{ zj%acn_&a7!vqWx}*oG)#f?`KTS>I~mmp%CC1)>-gX-Jmt3fj>pySkzCIyfc~)W?(| zqDOkX(~f-fG<63d-uf#Esgf3m|1MA5haqtHt|u(xe7FPX#Pt72d(FGvx4*&T+RKdK zS0(sO80>G8IO$78-fQc8@T2ak0NTOggmHBl2luwxnsjyI0T*bh-|IZCt?j^>;`A^U z#(uA%FE=|%5&0HwH;|NBf4ZcYEA;&ngHr5aRa&f;`)KkgAMWdRlv@U?=&e}<;Ho)% z=FDCiezE08(Q0b=;;C%s6V{M1gCiI9)+iI)#!u#vcA5KKr(WHmP;Lhj0+K8UZv5n+ z1-N(6IhlyHV1V3E16rCnHRUCiv+e$Q0!Q#-^Ve}SxQ2*D6|(S*7Z3NoLPrE-v_Mh$ zNK2MARcqYMCBgv5RHQi;fDW=HMGS=} z>|LcFSygi6H}i;9tB}*e_P~*7A$vcWR7}AG%bz-8M|aFsY|MDX7!n)IH9a0(v`qqT za<{&=*YwJ>vi!sxP6=m`Tph8lnp%Z;zojgDWUEDao3`k< zgqUNpDO<)gd>q-Huj%N}(}l$|b`aF)$~O;iA>(8dwo4A@fq5?8Rk0Lh){*&lHdayrF<`Cgj( zW&r<$EDy9B*JY4-2ot#!xRD=fttgXnt zD5U6?6}Os&H?)ED^in1`QZB~iqE8PGJbLS(g`_;_9>s}0uCBZ%L+W?T8g43q;dLF; z`?_4QvZc=+zy-nQ?1U8O5-oiS|7dbl=B6L_8IZt7i%KkHfahp^(c_B1<*|1=dDD5# z>R~&-yVc8L@88HR9Wvk*gPB+E5N<7MfSc5g@-p*YwjWw6oW==D8l2lJDp-O(_zf%} z)xQ;K=uk{6*?89xF|D zZ}LXV_L{xi;xZ_+0NFZt!_(Sm(RRR-qHk3P)ZqcTBw@`>j_{BE(V%q@&Y9!?kc6B3 zahMN8V52|1m0g9eNHnaT<7j9+F)fahvd~6|_j=lVQKR%)qbLQ| zwUPMGS%CHK-VDvVfeZZ3Ns)sNGec7roAJQUg#2<>a++=KT?&1dk*SUI6La60b1wP; zUnugPLkw=&m3UDF775XlUC59-*q#!%6oCRsqor$Qpto<6?o%8LgP)#XHncIS+@5#G)Myg+;NT-0P_}l#=U)0N_#}21 zAgt_++!1yNH+;7Kh(da>0!wu0P!~*Y8{^_!>-ZQdA{Lz=yY*PCa-;GB4Dm9lkoVD? z5JXwD)9wFDXU#}xCg=|}2mjy+c)}sc->$$2=gMOOBFqT(i_;s}IgXo@&&<1TT5X>T zl0i+O&)hDSj>{Y070q*Xj0jPgm^y{5M0kxdY+J~Jkk(aJfX0w~tffUG3 z9Vp{m8^muC)i5S3&?FM9DNkuw2xk!Xa{IzIT=nSE2UJ~Dr9C`cGof7z^XVbeli+qB4E)CCcl(<&rN_CFMCv`;TaAfNC zFa&{S9z;=-qu(%QhDMirt~8C$#(5yoS*!7vJ~0Fm%zh~-di(Y(5cix107jd@i%-+C zZ=*#<4NhjBH5f%IRq4S7fE$vw6~X3_Vo+cSCQ}btG58zrVZp;kbE=D$B)X{plosRU4PBOMH4G#~ zBknbayltW(izg=00JD#UQW}@$_pWHqtfGjEifxP7&&$2q*4SjfJZn)l2{^ zMwj0pU3@VZza!i>GWbw!PshO}w7_3Sw$A&5jzAL94@)PP0nHa6N}N^WVQxf}lQJpR zhxmNh=(XlsNvpF%#8r#K4E7w^dv}4#iwgSE>bAU5ty6JnFgJZ^$q|!-yU|IglaNW9 zt5#aWc%y9$rLbL}DSx|>%aBlBI8G5pi_<#fGe>qSeixR1gmP>+iTO(g*MBG6gUf08 zM7!yQ5@h&d1ICZkv@C?#vupCrT1u8!rH&QRZ%zQW@7+(aip=j9{688zr@ue%Ffq^P|WEF^BvushynnNgoyaC}G=k<@2q?Ct|6z_!|7#&W^ z6iun5@9ntWyb1Hg1+ImiTfQ~$G9@T;SSAjve z%(D*UZ633l#bd@Y#rUcA| zBLj>yxXJheZStjJYuS&KYKoPQQ26HzZ~cZ+`0(YbhZKgJ{BR~6%sM7;hS_%io%Vd2 zsoX$v07Lp>`!m0 zT4w*fGqJItMcEcaONh#(#E8v$_9Y|SS%onW56MEEvrAY>a-e)n*WTA$H7Y4Rc?&d& zm|kThMHX$a;>$;w(g3^Or^JsuXr_i;!$x z->o~^ihhJwj)RunoZlCBPA+Nf9bQvT-6JpYSk@jLjUL1k+EpAi(_!REL2K7xw)CY z0lZ2!Wy%Rl2%qm$TqJBR8Fo5O1ed(VwpKjP1^OY}zUhI8>1%IaXn;(vlSG=F=zK=G zrnW!e;8!4%xb63p<@=C?4HS-|GpDY$_1Qh@5bsHxs|^KC!gWTpad6Mf@z}OO{j=SP z%o4dMm*muPRUl38&eaE@)fTpFWjwovcm>-IToRJlI+?o`w+O(<+;F~wKyl`r>7F5l zFR6aF;Ant{KlJZxw&0Et02~Rdm5+av)i&ANQ5iJldh+d=95INU3KA9H^}toNkSGlA zU%nHrv=Z`CZgNpsSg#$?jCdczh{lme!Gx@nb~qi`Ef3p%4uMbabMzq3))h(B!?@c{ zx5UwQde}ou#4V|_>mbW4LhmcspZ7!1;&z0O5DkD$>k0~-t^AJ~_E$F)PhMnKsf2#T zWCYJqRfSdg6?Gpg9#s|chWMEd5ONtrZ88`7m5;mBi41U1JYy!T=a0E6kVO^La=T^?Tdmt!A^ zCp&F@*4jq)f%v=H@%C=^G=F+`K^v6 z&yW$1r2jfmzj;shg{?Qo%HddlRwTv9HSKAf0?UVfpVMqo+(l=HAyR6C66;T=%+#^& z>m3m%&A0{%7lm@l1|C`)u73BWFwj8O(ae4)4yK&*Tp^@hqo9bBtpN#P@h{}mXw;H z1V+f(GR8x-=E(M}lGA#(T|dF+XQY~X?iThwrckczPXNxClg|9V!-aCUgY*}i0DH)( zmon&11J0YZb_ovHt&|!d5)S-IRvNYt1@~8fep8HNGs_>QWN+5K@z$tz;id0jvt*Pb z7bC7H5jeZC=^TfYD`-@(Og|NEF})Uq6+-4FYJ-cg4ln#=*zx^Ta`HnT_m7B{>10*y z7#5WQp>LgO!|T6YJWMRYteX zg6me-!0TYI(Yv$pix=fhHt~I+fS+vt&O|_nQb}cs`# zg(8UHm%OD)LRuWaxAd01_cZQpq7}6_sqP1nDak{Abu499j`{5mu{!5pgnxFW$XYCI zl3c4u1zzQj38;g#i16p!O2ea?o(92jZJXb-V z&oDvqJ%$m90UR=EOeATPjw~`pE|MH~?a27VhJD=q^MXr24sSZH{`0=!jmI49Yp2V& z{olmDFX;Ni-Qf(cyU|Qs^?7J{>foJoE=eII5uogzS9^1ch5ec^b@L769-qGzwzR?>o9=B%0EJfS~T&|Gv4*XShX=zc9;o{l&+oxbe zrBw&2k!>0Yki%9LX4Yac{s=M~qu_URTh`9fPI*)GN_!o~RY+<)< zy|M1Bp1}ioJ#o%zw+G=z&GpjPqGM9 zz6GWOboBn|MR;OY-zVdo^p@W_^HK3??&AcRg%xR95=wQhVG^&9W{hSl(l%{-60L+o z1X&iJu)}w$(r0@1p<;Y~o!6*$R)fvS^{w5fdNmUZK5BtAbt82Aq6iw`q^EMVBXV-c zQ{skd#}e!8OLcOG!v)10FFXv<3X5FSK zZEuHQr0Z98cZBTK=Zn0o#@4)-q2q%cFpKPhLRSHW)%>`qTcDzIB;5iOi-ve%ej^Mm zZpbnm1yP;be^cr6*TAUy!2O4(D-+cJmgOi&}7_Tilz3h1drn>NykCok1k8v zPUjDAu|PT>hrc_}f7iGF@y&0IzZ@zCY?GbdctB#82~cN5AlR3rrOonEZx0*7F|JGN zG5LphU2E626I~}OM(4G6>qKM4L?}34DNpt3A^R^~(`$`VE3IsB_?Zh))AyP*I{SNL+ihctTo zBMUoI4D5WD;JcMjkTLNNY@Ut0wNtj-(9GL>_e`Pl7_!}sL-|Tl`=SdOzGK&4+b`A& z64_9q+NBf%(!15yWl>Nfw@wudKrVe_ppl(-P>s0@ehUBTD;&b&ruuL zZL3Nu8hQ%QSNlytyJe9w&uF>7=nth+;bwxvUa@}tRZP=($<1%X85lAN=!6UQ@Fm~H zbxv48BoOqq4Jh2%=PDtGS<(U9e-%Q1&m;5uxHIxb3!KB75e#)rz0vj-SLN}z|Nqrf zvH)GV90UUUo0)~~B~AR>4WO1VlCiaFOH=ysFw26|iTb0WsZ4gI^{$)CUS= zQPfZ1DWdon_$J*JO>}j?noOMoLVujFexzUSo3Fp-z3;0H;9dBH-ss&3_>^musiy9kKHf@=J3c)Dj(01FJ90md`wx%8 zuIzf>wbG-FfZ*B=GPYNoTHkhZb&`CyfD+B&C=l_ypj#Yy=)vZ50(j#fw+LwT$6j=n zU94?bk?5JN!HI!R)9Ia!MftKXE7TG&X+LluC|!5@lZR6-#IYWIfE{ z`vX0<8VP~;I%5fd5DU*w{251@-aiG>>wacvgBD~zzSNSNN@{_;yZfe*$gkpF^eBd* zo#kDX+2r%48mFjrEcVl8HDaY% z>9t#hqCWV{1K#)?v}^+d;6}%hYk9tZ+RI$^Bf4Bk)%Q@WhM1j_mCpy<_YJf|3gA{X zYEN+sD=M7t529hW^F>vAUh1E=!{?@AygJ!>s{++-)OhAcfuNf-uen3_ZcaXv9OXXO zy_+5rNqAd8#9F!6{^HiGRtFEFF{jxi{ zgaMq|FqV9aPfvt1z|?i{47)>5;p1x&JK-@nzxpFHMPRO-wA?yQ+@~9BozaT97!zBqM;lK`YGa25>sM7tO(>&_YL9jG zuvI{yC(mq@@h2jfT#(Q>6tX4yFNs{KcP^bm>ZbL$;FkU#&@J#}aq4pQO4#@SZ zcJy%xQZBN0>iHu#I-I(rfL?h_tc)SzPntsD%1uCSc~*NH3iY;c_v+|6`3KrE=?E@m zggVmOIVWK`SYQK9vTA53KB#y2VHNaq?DYd+-FP+k*a+`cC)_M5OmK?!Pd{N`62WM> zOX%3^v&tW1rLsg;6NKAhWdN@nLv{PLc?=I>3&__{KB_7xf{7by2Q~idsJSRNMn=Hv zEON>2^#Ls8-M*`ZRoav4T_Gsw9%^9wY|~$dD7m=)N7va>l?OO~YqxquNe!<*DAoOd zg(iQqK2rZ4&OF>sVnERc0><)}TJWxpgr0)TxlV)t()eu?sMW$v_;&cFcLUt?tU*B8vEuKGt+<|nz zX%4ED$gKnlH~70?Ad*UqrERw-s-ijoD~Gvz^wZNSTmk=#GRb@ivL0lq_hBpdmX&-N z)yAnGnWUbzOnK7erd>&tWUrY_WWk92JKS^u=)@(3W zTk)dTZ1wMtl!o5K>`L`{9U2D-OOcKd=1T{Zk#7U#CL$7ZFW%<4#ixL`N5L3N{xdzczdb-ZH`JBoH zZTum=j_RWAMhrsFYKe{X@YooW97z-?bae*RV2J|p# zhYN>&szbpIm8Nkzv1j+n+}B5;;qChjXe`Jd?byXx#2Z08qkLDx0F`bF*qyB!gAVfO zaR$mu4c=l{Ihv^6`9~3ke>Qk#HX@ZSy2ZoXeK)kf9&bDYlA@Ai9tlfk3B8ex({n5m zSl3^O|Cd-E?q9UzvQ&hXHnGEwM@eye@;; zz=8W9hDV2a`eclxj;(r%mSb0AW71JY2BcBP_815Dj{gep16TGZ089}y(F2I%*Cw9bM zjO33#%y44ZR_PmkXQ;{A(HnVS^d+61MOTs&_QapT8YBci39)P2ma=gg%tq|Q3%V)U z;S+HjjpDTOlR2qc$p)%Qm0@u|04?Cua|&qWZ2ofQ-w}S^+b+k+s0TfB;2o!AOk`Q< zg-_A6fe!7PDcS@%g+=}xmEm6Mki?T-lqi}5d>fLUVd>&N2l9ku@i@ z5<4s~8%Vq?6|U*@I0l#R#r*n4`GJ#;Yul17Vkm%KoLe<$`r7?^fbhnBXcwS*jQa#G z*bbyj0k7H*gk^_;m_I7R(akmUz-G~9xSv)}&p{s{Q&&B99T|vI9xvr*uz7dFcmVWw zTvo$f;GL$<2!7pY_B$r%>NSBN5T{HgY|@b|@Q+HbTj^UNf@jkjgXV zwwWkW7^>ZnR{yqPQg3&`0s)ZrWbR6N57H74&7d-3LzZBNggLrC#v)ly01Dv;7v%#c zKK9Tc6zP(!_!)yZ2w3L>nNira!;-atl36arFh2Du+p%#h$4u$FMNYq%s3aw&_mhyr zK|(mg>R(0CNRY7NevUFsY_bLFXW*eBRS=GWCtaqFLG_j~+pqCB#sHXIw~p4j9C+qf zu-bCK)!Fttdr01G@V1zE&}wS=i(!=osRtXf7{x<5p&)Bg&}sx!n{TP?!zqO1IsQr37$~(AH^3bb^kcup38)rtmmw|SLqTd2_Ov9tVN?L5 zvGC;!*$6?P5|jL+D+|Z1-DUwds;h*d;1|gd>5rz(98d^t-2vKeoLvsV7u$g23@w}Z ztb~gQTh$QO=)#7&v^x%12ZF(*_@cRIU`i?eTKr@6&=`$^SVmXBg+zNT7YZD3^GK#0 zbC23xHfFHNib`nyp3n+!Ow``5Ze!qGF5pN1YZ;dD08#|4Mx)%>_lKSzv6y;UJxU#{ zn^NpL-P{&Ys|&E{-kcPPHhnpS%8aC!BoGE)8{=?tzCLDCt0jTFBnHZ3ag|hMPDD30T z$=~VjBj6?Y_41}M+P}M827|cilXl6l%L=Cf86Rj*PGEO{3^|C1=HGv0@0By+dvhgH zIe)VOLL^#_155=AsmS@meThv<(;+->5kIpmP$`Gehf~~Q_r6TyG!V6Ey}@DZgLD79 z>1V1`-w8ml9lV?!-UL@eYWHiPLaRZ|L!H8_)mmGo1@(|I%F{+BbW%l@!8bNVkPMSai`n)*l&|`XLF)ScPOZ-s~GCQ`z+!qior9x?Aq~C2m`j zVrlSl?`ZDww68uQSRWYc4$n_}Nu<*VdR@$NUL8O&B~C}g#es~1Nxc4RKqQr6b*9t; z^F~l)sLk8!Ze!-;rp8>Ow6}}9S0wHu8BT)&aZ|LIrPdTKUAS6Qq)tf~g6fc^-+L+% zg=d5Afv6e3R_j)y7PSpz+#!335G96vZ|%m|!S zEDeAkf6N+WLiJsCU46nwTGXpDE>mtuT>U1%W3foEK?~O|B^Urs>lZDV0ypYTL>jcZ z?DJjl?Ix$C+E`Ul{ciO~bwZA{=dXb8C)DfmS#}-Ix|AtNxERXsrgBX6D7}M3^QS2U zC=zBYfA)>ZUSTF3TR?1o26HQ&Vk)-*s|G+ckN=OWvyj&|$?qF1NYpCLV)ZBtf{kM; z)G&ERxf2kGK;4&NH= z1?bZO_DG#e5Gb{v4>5For)=*sh1JAsE5rPSm$(?gKtbm z^ElDH%T%W>Q`sM}10DH}UEQI?Kmb^e4vd&)^Fj`;%%EL@=a^o_m8!$y5?aGl4^aV< zRf8geq%_hMw>*(oX4i8$hh^J2X3m|F;swf2s!C&qyjn z6fj!hlyOMHU^fD1UN(YF)u!>xENPWuc1KJYVTF>;$04xfGj)!Ds)oLD00A^X{S6F; z&mb_Bk=pHQbJ?DKj0)ddyNSA0Et?neMrc> ze>AS|q^`a-tA+q=#gjw`a&&_AO(Oq1+rMjX z6!8f1TpEWD+_2)2fleRnh8+~mNU*_G7S3sUik5Oi>|cxqW}o<&lcBwLI3VWEB1lf= z5E8>gH{c`IR0ETM@9d@&v)LcX%WfF5t1KK3QPPw$fqvxyg6TgAJ`8})+5wV|9cNBJ zp34bQdedBW7{X5E2oMJDl9hFwteGu8P8)R03SbAyL6A_s*NH=v51PvxF7=tgeTgEG zJFw1f+Kja%g-i8-anlvLs*qjhL&fIO;^w7(l5jGIgk47KUu*?>L%5 zu*#%uk4QLQATu$ER0y!vf+C=xW1k=RMYtcIQy#3)In46F%(X@Qk{ECNi6GydFg?+9e|JYCsdw07^qL@uowApN>dxJF94FHnmW7Tk>+^4GAp*d zKAvAfW?c|^=g41HOc!gQZwpZz{Kja*H(h}R^Rku=XNo>0T$(;4(ARe=D>=xmM=Tcs z2WsI%Y||zSM(I5nEm}*;dOK|tSGk6a*MW%#+o&qt1}|>sM}A+sd?KPEHwrsF z6}TOb^UCbWgn5#w=^p2!+&}9ndM!JWYE}r}FtQkR24GMdEsr8Z;YJtdYldw$nW>5T zmUHhnvcG5nFpk6O1ArgvM4{Tay}qhMf7{pv-Wmp0J#RstolTnyNbIl5RB9wR7{_QC zg*MxhgPVgvZ+;_BrE_C}$ds~%EFmzEOe|#{qJ3btw59Vv3 zS9CGnn&HY^V(RDi21jUz66?(kGUo5o_1!gmfnO-Zgn)4{%WyR#P#Kefg-aGg#a|JD zJT60ar8z{6Jo-m%VI6vdo9!luQeeD&XHb?LT)-{WA9^g-&HFV11V#Fuvl9@aIgw!9 zC{2d^GIFWTs7=&5j#6nIO}Fy8&1w1N&nc*SY+2{ZC=6L^za=y4${2_9FOFx#jieUG zjs?1&^LdEJU7sOOc z?10XUY5v4U3vvFuMu(TZOW)3qn5+mqm`t(LOWh+aB0LRD_nEaKuTCRTCmL{1Cuk9& z$62Nw<40s&_~K#RxE+h#M4+qYc5B7WDGOO_M9Wa$0T6tp{UmLlYr&uAB*U^GD?}|D z*hOWPttub0b&jZZY#o$5Q8#;t$b<5?5P*+&Y9~YfFEaiGCp-LuPtRE&Pi`}Ysi}(( z+owUAS!@bVbPM_p>2#zPvaMfmizs7SO7u<-XStpF4c*_5fd( zmx@Z!ADz>wJw(UtyRANVOATA0_XyNT7gd{vVVwQ5S^TFZ2B<%EFvDd5j*8&1kw27O zzvH22iv3hrWrU%nGN`pCk3Nr@Ot=-5I1RDZBydB_P{wK05-e3iOrR5X5a>T__4n*| zzpKd5cul9SjBni^N9z^W3%S>TcL2`LLu&&DA$0vL+5$l&D4L0(9@=Od!%R3POLYuu zmy}g=r}PX-!akcW zq&ix@e^mCCa1s~PMK*`R)Bpl{$IQ3zg4usytMTi2}18b=d~gVMAd)g z4=RK#2q5EMPcU`{>^CS7kSr_^5Ec*+kdv9Si-WVhy{!|Yg9j^ziM^eJku!sXNA@q- z*aHr@o)ZlRR?SslJi?Apkicm(LVC|tS4KO;K!4(mCQ`K&IO%D*_Y2wao1w&7qV%a`z5a3ZyEaaP+Y zrFfBDZCC(ShX8h=X<$N^=8TapxMBg^B!cJ;;tw2>3T6dueb6Te`L6<1f~XKiOhCau z7w=i@8N;a$TV6CIT`?p;gi0>lRPJV8n2@IjZPj!5dR@g`_XCcKz#um>$|SuI33%zCbrFqC&|RN?WE&mV%rnj$;7s8 z+cw_0@9TQ&d!Og4>OX$9Yxn6>)m^LiUTdGVXWWmSdKILc?2scbQumOAA1Q`i6J814 zHLZ+1h$i6*sj(x1IUm6&RZ{aSw{dpJCjnrSB~uB^mB>JY*+oMNz3mCn=TS)U^@zig z09X6Os2Zf}7R^H{+X&!BsGFI&g3!^O=J*FTtP9h)@J}SmPyt;=0@pE3 zxlGVqx;dcfg`;kf2Uxu2})T~X%PG0U4_YVEOGKE8?_29=L z=yNl_Ym0mZp$#Eht!Mk!#>&SL?5pqMlu3c@&3!hwi3!~&7W%*XqB%g1QA-CA!^w7~ zY+uVu8&bwyd3e@;?6$q$AM$>L^7-Z*oki^8<@(=pQhy}g7Aq2jz(j|}4=$_?t4Zz7 zFK%NcAfUK%j)NuwhK6G1ll*gteN*5~I`Pa(iOl!&g+<~eTLZLzs@BD_K|@x4F}(}j z%*DH2y_qqa93X!3Hj!6j8Q>_gQNWiWx_JF`)1C^S5Z(&Ed7JuW#@M~6w*)$u}ZL@^OmLs)&#>AI8}Iw)))Z6UpqDfv6+?^|Bm z488GN=$X&i_7{$76Wb)(33Ik3OL6#SmjftjV2$>7%YJa3QZHL6b>*`<^m-T#O)V1- znwAE%I>UvaadDXMV8y4laTc~Jm3Oum?C^<=7&5w+mG?o~0_qdDuKH|so=!ZZ*A{>G z$D#m-JxoTdICqbMd@$p2thZ{?0=OnPbYtHFw}>{@pRuY2yvg==7cMT^GJeWpQY`Jk z;7kR7tIIU0#|^a?OO4!MRjNz-%5t))4__(7QQ%`$br^Bs`02^_%7*I#QM1+4(_=nr zBT#wSKc8$GUVqKW`^Y=3t)&2R>zeQ^J}!=!%$!}o;c1x+l)V!$7>AUWNvdZ-ZW7b{ zySEOd^4XHDV+DKc=NzYDQQD?#_4YSTPP_C*`V}k>qVGmf?^+}F?9~3a<>E;N^D2ck z(zq)u9H8doWMP({UK3G;H`bEAc?J83I5nibxCG-I$6U=d9~Dh}V8i-bHl3D_IGr&P z%wYQ1{uJD&lx<|Gjnr83Um6M_nLFnjI~{r?k}<~-lh-{kYU77v)}@h2)&ozy z9S6&fS+(zozu+N1HF738FFyG~{oPw!bHbi+Y?oWiSp}C19Q2vpS_!HI2>t|nj6|-a z%laCaTyzy>fndZ&YleJWfVBloNvlZ(ihj;ZlaLfZ0%_SsM4K>8;#hT3>l4Cwi9d*1 zKuF;XJgS`iw<<`N7#WA>5{7^oLdXx#o-$p(6(lZXAZ|{aPk)zhyUHi&%BHxg%0KW8 z6^0rd)av2b;1En2PQN^t62KgNGo~W*WfOCxANj6^yE$Snwdp_LzEi1ZbFMr>HDpRg z@5L2W0+bPGrkfrN!nf!&L}tl?#$a)8CY*D?g(=KZ@hZYI722T|^j(uCa(YUjD$e2Y z(8B9>?h83AOXk2K64&xW<(VaVJ3Ko(h;8R6I^4hBUwNA9;-@&*{RIZ{cQik|gj-!< zDkhlR*zdzt7 zS11!_2hgHfhU#VE(HV(@6eY(tOtwULM8#z02vld&&*f&7Y3)v8!~n>@G3obS+YFt| za7BWC6Si?gJ3-miPAnXbXy)vHLFOjj>h4T}DwdwZ)-Kv5w$h2yuG|(QH>-K^EaNE> z1ukFKDhn}!lm+dbkyDtNReEt4-AsD5Bl#|}f}X@=PKUj^!mK);1g*EXdVU>3dU(0O ziK8N`$93KSdU16pslssF5Su%KY66Pa zVntTs@mTejNSisMcS7o5WkN`CfbX0i_j3Er?U4mR_c51kn67D&MEf^4TolOfS{XJ9 zNJ#gpXaaeG7{HN8a9yh!xGghDMP|JTcO?*LJ}_bscz0iXYo7gw&a_mrv{-d1Ag`Ng z;WJVVH98dkk?h+-CHDcP8HNHbMse*a0@3LeY+fT&gB<=h&AG9~eTeUDe^Qaxp)^J}5T1S=ud>gMyzq0VYQ0vf?<>}?&V`l^Xg4%0k{eg*snxjD<(($&$^&D_#1 zQgU=u0)&+^qT;d@>)^~(Gor$$>X6J-|6OkqFlje}f=U<%fv9z@O;RHS+8xP+_86SE zQlx|QXJ@d{*|~>4NFxe9p3UYWQd7{9Lm&Vm==1*hWyI-cC&%PMRwV-pK2SgU4=r;p zCK}iQtH%eT4dBzTmrcTg+BtXgj%6^zS!S#3wcAAd(tlJVo_l_gojOfh`r1_A6a;~~ z=1j0Q{HlC?VN>03M*XiZravxr0Yb_}YZ(*wH3`yw9Id=5bXJ@w4p&JTeBWoci)8MV zF+4Ni?CWl}6VlL67S)5y5_k}8N4ZbvCIQlS+i6V9qS&H{=;4e!4&IYX>N4(XSn6h6 zTvJ(ks1nu2WqP6*h_JwvsIQMeB_T?yVM~nb=%?rJKYPI77jhOSb@K@2BGNtdVA>5( zote|NBYc3Glgpc#YxsHdnC5oenth=*LGp6F)8`r&EwD3lR7W@e4al7zp#7X~@_jUV zqYTQkq{q^aeM1^8Z6!qrk-lvJ?*1!bA!Ca0j5DYDckVumMTv4rrh+T?yxNQVbdy~S z8~5_+XRhM;k&hkw!p^-L7{REQ{DtexTvD+G(?Hh`DO@B_@M$-|C~JXo8YnU(hqh-j(`eOu5N%*FSymmwAk(k!`K3 zi7O$3U-u_eYITy)OT(ShcF))z(QlST^zyo=QafS?1@J2j(XxTDix!F|K zG2*L`b_ZPyd}F|TVYYA(kbdDAmbqE9>KPVSRhmx!?3?jA%hf1PTjD8WpUua66S3Z` zovmDk0r{~@<`2#2m$gtRj;!^mAF5+xOZ4u;vLTnVZ;ePlss+akRA_2vLK6dt@HqpHjEqzR@p zo4FGZF?P0g{(75prKhLYX&*Pj&j!ynZM2Y;=LQ*_1Ing(@+vnQbiNqYHL%&~xapy9 zncPS}uSrSbz0vN8MCEaF_CV+~)2enyh#!8g z2a5c5ZqCd3D7!<5{HIf36o%D$3r1B>>f#*^n9Ou?GU53F_=;zii(5*IX zVkr1&{RvOP8vmu7w;`%IeO^0TPrBj@EbvxsI3NQTtYIl3Qh5J2@oMhj#v$#L zcOvG}=Tl8iK>PZtN5(TSsQYP>PoCx?8+Srqli3+_(Zt6ai;j-!7s+>ij1w{pM)pUr zYBGl-{r6WHoyX{ox-Ub^`QoMwH_XJ%iV=G)ofD{Y*}LghN_0T&SZcGwWScV2az z!GGK;Z|>WI#dx|3ZQMGbbh|JwFUS@TH7J5NwscpnwL`u-{4^Z>^w@T;tSa0_6Nvdl zS~}ao6@t{un>hx2p9xJzODGKQxF8O(i#FiQf0RE3Q!BT%T!%e^reH4`~ z)JpTp$PjWI6edped{Old4nVPUL$oL<=03iWL1>hkGPT_3$gq@3+9 zWc<7mN+Jdbd~4w2qZlV=E|QLC!VXqOzLE7)DsX5B2tzgynUY4O@83{k1EzP7?l&ej zI^Q#yk3^b)gDRUqVDN0GJ_HH#G5JzDE~;S%=f$s)(;1Jm6yA`qM1owp_>iT7 ztP$KJieMnKkgP~XT*sZH`!q-q8A082vnavRr*6W8Kw-p_@sdO9kwj38qV0j7;IqoI zc^ZpDu8i2t)g=tW1`sXS0=Ge&p^(XY3aO?0q6_*?6k`pdRd_M^|7xDi;GQ|B`KP}Q zW&r5UnSQv9MszC>kbZ?b;j6JWL;1oh!-_n=9#u)z}E87T;BmsBZAf|4*X5nTacMyz%j;xX2p|~fx(%=?2G=eat?FD zP5F!}=GOR3Y%n?7*=#n&t<-JQZ$BTdf(>5V(JdA@-k&6l;YqfPA8Z;uskE4xU=lfw z*^K=Vfz0UcNXwH7DEmaJq7omMCx!;(lgz)%!R|DEv0RDcFy-%p%U?v89eX!QV+e;5 zXxd@gm-l=__xkbE5O^+|hAC6?WU&HU#%7?X!Z{tt;u-H+$JHhL95hN^?c@Hhi#3c1z0}zV!1F1y#d1_6 z6cj1n9Tr+S6UrWSQUoE9Q6(S>_0|%+!_hMMXLwn)1HSnZc>S8l)$u`7Qmk-m{pgG0 z%cKy@iX%HVI2WS!#v9Wuf|~FZjHoQaEq4;Aax@>N0eX5pN(8kj9r#Cc4M|i zM{CbJp!G(_e7ve`fft^dJ_{LII<8$i&LJC?p3vL;$H854ZnhSPrb6evgTN3unZRc_om}nJPItJFtkb$2b z!7%bIaoFFYf9F0W(?TYLi(QCrK7RKC57}cy&>EE;e`|oD|869G31Z-mZ%p&60w06; zb_>PL^CM9spVj0%Wdvu^-`-ZO=C??Y7&l?~tVJ@K043Y>^#i_tOk7;O1E?-6G4F33 z==(EsB}`Xhz8N+zrmxY$sglkY$ZFuy6+>s6yW38+&d@evmm9xeHjSk-O!~5HW|sm% zM6g$d=1d(gdzsl_5|F8b8z*$o^4$eqfbQ!)WO2(f%a_ezC1SH+(;F7tjC?CTl@O`E zaxUVGm%o0SFiq0;%zNJK*6~llciGc%%(T@W`R>(y4!WNLC(zKLJejmaY8AktdJVV4 z68c2J%A#ghOptR!;Q*z(d&V8_0NnvcQ-MLd!|3z*eqOqyhf0f7fxfhM=m?^7e%wW2 zCm2^vgm*qeK^SMAHGDQXM~5ZK8jzmPX@CadGNMR5`W*co%9!Ra&P7sH=;nSVGpwhM zl^$EB4n2smg!R70CT{CM9ByDG_bTk_lnd9DPO+(V$z-BhrcBIicDXa*FnFr`+3>f{ ztC_juIlQZn_CU#Ilt7dNfs^Se6yG)nfsEc=M0IPTeQB-U*r#A@|8}l`ybg^RYzO{d>Zgjke>h9;`soRR7~x} zOGxj|nmgp$s)6weIkg@yZ=|pH16{VZ7$1ZU=c~lIp&bZX6Bw~#0ZT^T-um=QgHT`H ztr4k^JTEGO` zBxv4$9i$O6pv4gX`&mK~BI{^>^#N~+lpS>dPP0cTG&LN;f0TpMrkhXizcsLTN>u|i zFX4A8R=L)M&89t1u2{fI7)=1E(AenG5x%w*NP%^83UnhhIS}GVSkoaTQ$<#WMAFah zI(f&1gDS=VVMt(Xp)F7eA{DZKJ)VqmmRQ5LBK6U>9pf|7Si^o9z0R&aeGo`!jt zAVMtGo0qsN-W$Ti*EpR+WiH-XgwT8pXyhLcnv=!#_up0}vh2qMZ=nURCY5(Gsb^|5 zVd^OjV6QPvAE;K|D&R-lmQ1UOCGkW^JDTlHpKh>S)P;7S$qZb`)e^!2>(yV67;dV$Zt8kiiNQUrd;QUXP@mH>>V4G%`bR@^T3} zRsw{Hq~qdv=uboy7hB4%%JW*rMWe9^YlVe!Ix4QK)jHYdc$S38L_!3Tr)-q-3PvK94oiY1o!Wyw@^+`1intS76=-S+s}P*9M5k z`p+OPg*5Eu&n!=l2*6eOtR2U89; zm`f}Zwh8>Vg=9-44M=bV#q>P|>ny2(Cm+l;!vcb?t zy3S2QNjkDgU}(#LVNi@gcBXcMV{#->LrwLH<(6XPH+bqjG`3MJOu_WquLLJG)@mM< zloAN~*P2KQngD&62HX{$Z>rqodN(-YM|i6yHM+tpg)N&j-MuTDNYhFxxq849+UOrK z>7&faM5&`4*C(17VT8D9NHx9U5-`Pm2i#5u`iBY&LtoxDhFJIcnq%G-YICb8J%);3 z!V%T=v+{?(Fc?RWyc~_WlF%Ufwx%0}(d2Lqn$b4XuG@7fQnywTxm##M`B5pM=&QE7 zf>*Tb^hqC_beag<*XBQH==gy-6F=dMc!!()(7EAyV1X(IAm z$qny(RUV%rhR<5hX0g))(^npME8ep7I*%sWk zub{3Pd#fB^a5Br-R0VhvV1?tRkid~RJBi;CDxwe|jDBZHz7XC9+mTb z#IRBgesAf-n{-~5Y(l^>zP?!#C7zoJzW~#|qST`*@3_KtHRH=;s30UW&?NhMy}yyO z0y;Wr=8h#ew+m;*Yg@#sH+ap2_SeYH4ZL_z!!0-yf3%}xYa|=V?FMX7j*|=sfQ`Q%mh&?bI&XR>djlpe} z1ClF)d*lkL`uvZAAzPr~(_89HT5OZ*GSr7;_Q8gkB?>d$Pk6^ssxhIWm zP6dvi#jrTwjV@uuE%e*fqD&;y+*I_4mWh-v6`}RVOl~(QOTNLzC4?~fFd@ZV#_z1p z;pB}uNe1I~m*pG&KjuDav%$9ZL7TIE`a1~QxB*&1rj^~1WQZIEi?w@6vs6+oWtx{V z(KFPGvc$mden*9r&ESl#Q?t(D`uzR7&wP`tyn*R38lv| zH0IV%GSci73oD7<3l#m4A@+-DN(s8qAhYKLU0+`%e`1y{$f1>)`p*TLe~F1y1$kUz z{k1%Q1NQDE)T!R%g(RHL*->dFcX21BNR9zVryo$ul%>;{75FtjP5ATVxWfoTH#V&@ zo#^#(ACl$C`cZjonn}K}Y0peJWs-?#BKG+A*)R#WgDj;pRdAj7L_5-H-k(1|Mat@$ zKCXAbHCk&TF6Zhxx|7E8Z0nvDe%hvpId`*gRF;&1_c&r@hPAH{kA?})5LT4xol#9u z^m~bhXmQ{ITjk0fBCF31+-sMBy7=#ChOK7-C@bWfF1SK7g#m>JLR6Z+hDRXw0WStt zY+t8t|C57kHtB>O`nOV}rn`EQj5KNw}vg$DvMVDwLwRzLud#stRjj~Xt=yTQey()z~de@g92ce6ZRr{#dZ6DTFXN%{}LU7o9!E32vXN)*!6ejNupUx}SONv4_@v~y* z97gx6BQWI8bEN>dV6I%!i!FoeuLd2OQ+Qsl**+H8RMw&Qv%P1vRVan7Pt$J{9iVW# z4!S{6wP~l8jbpuQ7kqsK%0(IC*{3Wfbpi4^ZJ0%I zipPz*>VK<$oJRVmEeR?O>1~4QG5df_I(WOfLVxFV{T}o9V`s`qPVb?V-_i1Z@~l6Y z6~=Bq4_xF*$zGx;1;b(wS~{{&d434aM1P}0dOFN#`*HcM)LlWnw!Ftj++jf{Fa6jT^Ljcy95q1&nrw??LS(u%{6wIW{=Pxi%wk?@l7vu@4sR~VxF(yclEz2gLR`PxT3 z#})cfuHGYh;_k+Zadh!pGKQE*)6m|yUG=8J$E~+Ls6-FEgsXrvCa(CoD$#-9;!b;$ zjWW0ZDOo~kk8|i{#tlYbT9!|*@*0TJwe$Vjl?GZ~*Vx|eYC^dJ0uMd-yF3zN5|nFt zJ29~b_dJi&{e^K0TMR>d{T+vI29U?6eDc#G|0)OpB$dbS#!){@u_wMyBX)!7rxSDn^wW+%VF^Eb>0q_Xi;YS`p* z5lyv}G&XqnQCb~OyGRD1qZ22a)QVKvPzig;E>xIVQDqBNAP=4-f3vh>JYBrC) zuc~cYC0%&c`0^psSr?Xy7FQWvs2isL=j;l$_712Coi*l>|7qbF%6 z8@JaP&ZXAE6UlPndhe#BG^k_^@Qt6ZQ=`l4YmY|*_;qCKTFJ?}T4G@-sWlXR7z{}$+ZO8XD-w}~XVYWyXu`c7%{tddrk$OmnG^{t2FC=v$La$x4=2p<8KDg}w67NY*j zjox$`(4lYTR4CR~(5Lfd>2-0)np-*T(pcu2q^=_p@9V^A)b>`I$vvCb4RM06!$ak*6tez#xNxEUV;4TQ z!W3^`#wQP5h7-2{TN1}N4KDB$AQg?Wvd|jzzUMcqu;Mg*px;1Ngm*3^Y5EY$DiiU4e}Bp zz-F{4fv?5GJWv^0zqzjLuCzigW!oi)iQx`P{W|Hq(NG8Or@HF^lAc+h`h1DZ6Dspq zZ^GVdcSg=JbZydMYC?+3Q`84w-6kat1CB4%6~|Z8uc@D~?^jNIKE4nV$Ett9Wek&T z^}|$t$-(p-terg6LJD7a{*o{59v3M;(D$1s%+P0dC(|j7MuRH>^Bs3m_gCYW2#6WH zyHfTRZuEwnx>lsrwy#-JU8kHGe_>3PLz&5?Ta@H@P>74aL-x7YE0axT8^OFy)Ffgg z0NKRGUz<%#Ytm2rCg!S2&{utHGp{hkxSHC_F#UNtbHPFrZ>(;0I+kd;+YA2+*tq4! zR9}0jZ}FQVOxj5CRe|?cPA}nfMv0tt@HG~xP@t}aD|uuq&UAuFJH~UdCI3ma$JI%P83mL zMesl^i6VI9$s61f>z&uP7OWr(cxU&sGlk&=QZUpYaa1HcRCIV5@d|cjxK}UPh8!%T z+$^n<`j(JwCU&souO}%aeD1lx2w+1)YgYajN|B=6o2WVyML%8uS~WWitOYIsvm<=N zRz3D0u-Oo6Ot;VT+NZ;KOK-w)o8tY=wb$W>JsJ+oehTF?_=nMtm=gkYAS7R^Rkp6x z1J*~uZBMGdYi^95Gq^C<>U~cf)Qmghwy}{aUfQ{fTA)GXX@({Sj`L^F>teik-z#pF zsWU2s!*@JP@-CiGNMc>YKX@&}XDk$2d200=yxk;9ydA|bI6UDjusz`Zif{~|PxZ_dXo(8-d}fR2Cl*K`yXpys?szc* ziCCJ_G{-vh_J%-<953bzJt#Vl;(~>m%p|ri3(iH?jmwI5z0P@dpk%^O7AvUTDcZw0 z@bzk7oGBB({blI^o_x4>5@ESDUR_8JlMM&kEmWq;!WAJH!*eVrh-PmfZpBU%EHG*z z6$N9ms-e!-w+E^1Slr6~7)N|Kw2ha5t$6fAWTt@go2o-+rYFy;dGXFQY&#s4eD zZA@vI*Ezw2^5oGd0vS&&ht_E zEiB_l_;=ugU)c=ilhl_ZyUobl^tfO}^%CdR<>J)|Ze2#`aGdE<&SmO&;+r0h!>>O% z(yOS^ZpsZDjg(X8Vw~ozeKku zo3|3P0q3rrO2aNYinDPdK1xDvo=2ZAZyeK>MB31Kd5s>0RWZOi^{d+v?zCY3RF7&# z?-n#sY%sIQS^Ln~z=9f+E4d17JSB|gg;Q~wPw*OK7IH-W{*hRWSTxsGno{pNp&Ntf zW0kO$h4S^kw4)6Bv7voPkmh=00NTH0->4-3<{u%Y$1U*==5M7|nzHQz@U&HJ(=t}6 z4qhi9s4QHLOQn50&1B1vnd2*DiQ4^n^i4r*6t^akPRBBv1}^Q_gg%vQzb*6-y_kk^ zKv57aDLD~ndBEje@;6_2n&7`Wi&ntZ`6~qjXLtBX-Lwet{clqiBn%+D+pd3UO(Kpt zNlK3^fLc%*s>nj+;CFWKt4}8%>GilN>z&sf$iBy@)aYWvxaPs2^>-q!>q1DB+9EzG z^RtfFQf}z2L_Wolw5l-mK*tmsH^6srD__D5HK{o)mrHSC3N2hB^ka))#@di6GK8Q*o~hHe#$V0S`+3&Tc~4#$(co6X-z`@| zZZM_69q;wWq|YI)8nQJoc;{@Ul0|HUfyYD2O2L=SEB z@W!n=Z0(d>52Ow6;%Oxk5<$Y+nAYv>zzcOO5wQ%xtgDR}Rs>`ULyZm|XoNZp01vBG z2S4CzNltBx51tKP{Tq1p5$5R0tx8TGn4g!5=ywBoAQ8a5B&t5P%s5{#%R95;qk>z; zlqGv24ljE>Ah=&GiEd8W1R-qXUaxuBc{fW2DLtPKY2T985@}X_I zS}25HBo!GvkU-!*&S*Ck(|*qRjk)R70BJ0vJ-`d@Po-`3ui<*waIs$4P&cQG zuZ`=;Q_cV+%CvuEvUE|+t&duG7<%D9>vmrh^_mjft3QOeId65^QcGKlvPUHh03;L3AIrQ zeLW5fTO=t|GrwaIK)SEtTT(eZUdCNbhUu2)pAr)6YVxrx2Myd=yCX`VqR(KTj$lR} zn@1D7P^uVaPpMo>^z3++oU%C&yhOgFNL{{an-mrzTSLC%z< z6(HiN_Yds1i{_muU)A?*Vca8F!kwD|{_1^m@=-W-8C2MuUH6CHh8vgNc^zAbN)R+m z5S-Sy;2OQOAu$s5AYdQNMo2F@y0d&LR?c}O9U5)tQ99;+WKETT+_k=MIvLsSlbnd; zso^a8+5yfK3HPwA`rlg?WVKXQDE6&c>!bF=mg1M$M8T>}*mY&5X2f*B@bi}e17>6T z>XNcvUl6RSIE8ViDJ)x|BvY6Kc!;+1VNZX+K}uZIoscEx+0urk6bjcgim96qmL-&| zpf6^;Q91DFh71N;1voT}wY6omfquEuxM?MY6k>3DeZC``US&(0k1O4Z2(f;DM`PEE zUu}NJm7A7g7Brq=fO;*rS!%!lz75Y}7t>A<&Lrv+lnKv!ChmzZuZnRkSjBjL)fnmKiGoNx{4UrLn4Hq@FDUpvEAvW7rou)a5M|GDx~3;~iC>g1$rC!58||wXer2z;9e5hZwMM^f=k%`5;))ugyADRmRmuTyM~$rD)HJ67IS8? zu{8V;Vf|@`9JJs04VEdMG=-AVJ{nhk7q8F{3bKSI{Pe^N{YAI_6hRdK^|rmxvI@_& zflJ0fUX+gr%4V#1Eb1jDRo?6e>p1vmEBkiQS#DO57(d!<>nrenet0v3X0KWhb=-~_ zdY`P^5Y*<5JrRXw%y3x%702QW>VL7}9v4*z$~;eSln(z7u!{LN)Bws3N$x3D#}W0VtD5f&3x5zbQ6 z`nk@5?7LK*Do{Yqy-W$0SBXZo0cOKZ5@ed^A=~g+@w2B%C8|B*%SW>5DP7M0)~|h5 zyYtVKmorO(JQVOZMPWHM6mSR5f#!Rp|MbG3g-)z`Cm})5(2h{#X|A~6e{9-g9T#MjR1r4<9pw~I^=VX5M2m(O9DDS$(7N9tq*7>Yo-T(^oG^W zLpZ=Ql7K*EER;fH-2nSqx)D0>Mh%h-26ac!)o47Mbg_q=0-K%!i=UZzLi3o_rc#rD zU4mV@e0DY7`XuMrkFO;pp(aCPnyhTPjBAbZlj_`PqqD5q!?e{MNV_KRFILy;uh+$r zj`#w}0(_oqLt~Oo_=4$1bC*^&DyKvep1X&$yAp%_0xd>#l|T{Agu86kVxiaQToa*C zj;yk@pu#t*qh||yB|dHeb>a^ zo7s%7PSZJ|J5CPaiJB(uA=_eanQlEUMlD4In}3cOYW8)7d6JUPIR5hey=K5A6yH+%u~N;fEuKId9bV+5(W#Hi=KDE}-&G z%oun;@Ay&h7lsIAbUr2+$CM&MdrhsX{h96EeGCGKDi&VFltYz{@)eZ!l3IBoaY|!M zEM}lhID&%ICU8hL8{Q{&zKIuExt>+Jq~t$PHV;Zzc>`zEO}QoP%r)Le^GW_RF1D>3jh9DrTvt z8i|hyPe8%zE2zaAFQu3JujeW`{keM@v9+}J?*V(Qbo2d<+2%iDI|F^)T9#Hy2^sOE zjcwPi%k?RCY%WHp3al~=>mKfZ18JFmxTHNNGAM4q?2k zjeyAmg;|@96z!eBu1Iv0wXI&{-Jm<%dkFWYXOr&`89igi)+S??S-Fdk$H{mt*DF=S)pN*vZC}q_g?&>p6CC1Joj5C%8s}V-=+93(IrF07mF>V9UJ{=4YO1;{9~p2($@z~LbLeu)Xya8lSkxo z3C-WY3`q&XfLE~{k4yt6rw(6BwsQ29*(^DV2F&7pMAJzsJGLF z5B)Jnsd{0;FQzB<{dTiz<@RD0vlf~5Hk8W-%4SV0 zQ)_ZqVUo44q&nxnWx1D!= z7Eh1xQng54J!vhOyGmw>-a0s+>B&^^n=kW5idax_Z*L67>eOsDM_+irT|u6MdF?mUDN%eh6Y*%XNwNiYk{$RQc(WaJ=Z1aB^;4bRC0+y&4Bc z(O{T)p-E`C+Pvm!newk7Ia|u-Q&Y-!kC67vGzll9wf4k{PZ_J88*cO06L%plU)WQz zrgGt;V7U)F#rn*W#awEsD@>mp<4|~vA8i&;#&Rp5s>J--Mb0RC@0L8m<%uXc7i+_y zum_m*+xwRk-}E{!l)f}qYi%S?YQ6SeBy*o~JSwku?rlUj315e@Lt=VkO299c!O;<& zkwk~GCzh$5^JQgjksoyOiRU~sybRdFT=?N?&(1uhA}IwkW$u25hMTd|#TVGlJ*-4q z$DI@nT(gO}Zt}_F*jzx2MjEY)ue*8U6gL}TkQWWBS{X& z)`BDH;us6ATjof~6>trIUdag}AClB()`Hmj-=DP7I+>?d&811;BR9H{VC76_-jVpU z&;6lOV`*Ib;pOY~ux8%rjFjxL5>x-E6R#uPO1}!F&$9>C8P1dvzcR0FQ9crO(3I*C z+8;ypU`6#DvqGZI6zcZH$KeYD-}+)M+wh$rtC#I6wRTsZi{f#%WXpbT_JN_dtGu(E zUWj&fdO)!K#XzGDj=y#Q_PaQ3WlPq%@~f zt;I4Zak94WI((W5E?qNRzBw9Z#?XRF6dK{2*v921O*|f)6!1TKXDNqW^ ztA2S#gQ=nrQVPClTElmOVem{MpOK#K9gK9n3rE`6G4+6Zi5GoEDOsw@WL_0AeM$Uq zHfjn{8i=#oc;Yw2S3E=~nQ=Rb5 z_ow!dnN%l9-(ZYs&_1ZZFL|ZRj8MjP673_)_Acf|-j^wcJ<^Dt;p0Ph-3`3Y{(M+o z*8~Ub6Ucn8xpF+iY-|Jhr8fA*82`ctnwM%!Y+Q^rYNtG(3gRb}Hh>-t%Hnokx4Cw@TPWkmXh_QU90N_c$`~osg_i;`bB`gz9GbMnswO`!IGk%Yw2U8a0(2HglexfDD?)2#D$gTH!RtQvc^{cZ_rhjqdZNY@0 zn!?Qcr%{M?iOip-HJ#S=Q-!=iIyT?s3Mj8v)j7RAxynFdX+1QBNC@@U$P6v^F}#r8 zz6SNpteiK+B){a*VzD}uP4Q-UgFKpqRS9!aW)I=BS$pWGU-oEK}^%TkkpYCO}x5>TVArTEZyX?EOb zIYCfK*iq)-&_1yc4TRK{xiqy5EHyn&^_zmdOET)XGoiMI4-bfZ|WcpU?cFiSohOJukXNVViz5J`pZ%~u= zpnKTwL*~AAX71GjkV)i)1VW#nnH(Knz6wM^)lkkw{zQO7b#jAXNbqm^8?j!v2`KP^{90{v3sVR@J=u;v`^~wMQeS#&z+?u+5E*`DX^1tL4w-diVb<!~B1Rax`PN?&>PTorcm8~bEn^BbP3?vm1sJR2B1Q!zD>NUy#h@_r#* zrLlIU>c%qT=bU?`56Km#PB4(vHrIYZ5j}LIC=wuItE`Vb_l;X!w}kEM~GLK(bnR%R9y=6h&+qfh43)aCF@*Qbp+S2XvZ@e_%@ z;%gA#HXDHMLK{-2EGG?U=rP+|G!a1yQ#vLS-L5o~e*)`KoefgWdvWJ_;@ykFCs8LN;{eTI`C-4~;0x_%epy7L#91nmluqjt%Uy=5VODH#?yRqGKqZhOm z_4lu{#gq)XDbJNoxW&5;$k_zS9=+Z^EP5z>a7DVaL)`U^*xd=} zv_Z3~Fw^5T`S9o@k5nExb%(wa7HriMXvTQr4Cg$X=qm3CKVe4tOYuIPFHiz(JssY?W;SjqXHCrfVpyLiDqoD|yvIM?*BI(B#I(jzCi_Zpy>+XWTV=Hgz)Ecd9@k)n_>b_LIN zo#R2nZ|HyJaL*LB4oOA3GrYEpXHzplS2WzoR8b0%6P)R$V<;=BdM93P^WOFSyV?eu zh>uaV&#j}UxD1@{<{Tmr797+IQJ6fFTIj%ZZvJ_Ku%vO>t)&G%@MJB#I?gDY-C!p4 z{NnJhiSdnIy6We8viW8&$u0+9cqkw7NSl-;O!09-;Y!+4fw73dFVA+1Pj2mY>x$?~ z7qv$oGt?Rqb1!|ImzzHux)|QR?J}ybh`JK4-9Jjn+=&VGm=o&xoMMT(@OCBa{rPSo z+54g9qy;WDh9dhy62}ak9dV$JP^I7#{O*4n&o zr%wNqG5pAIrXhtVyov4W2@LOAdiug0cp+N*7z3fJ_iRxfsz;9L99pg%lG|X?R7Dcd z64HWq5fB2q%MGTvuIfn)jkhm#48KQ1IqND;G5CeNa*11e*Eto<8HSKv+!)-WFtLZ+KGG+ zc>OXYZ1@bx0axd5nk{6_M;8wv5Dxnh2>Klc@m9j=`4Bgr`xTaZsSyb~v?96SJq25F zVkrRabxlZE`Z<#6FZ)=JE#AmRArQVmIJN@o)`juTdF0ceS32jgJOXeUgR#5JnY~kfHK04SgIdC1v-MUwjg(zbb^%lkN1zF=FXNP zW-eyC^T_mvXM7k4&pr^Iok5g}hB+}1CkIxGpVoAWCm4o9phtK1<~mFa3#Ab=!k(C| z#0bTJp309ShCgHw)4_Gy?VX^VKsW`S!EE_VRRWNq4a9KGYhp&>-KMETJI1PjXh%QV zeKXQ*C5FA;5HrJJB@hM9!0qp+0YiMJfp3*;`&ZfOZ0V6dVGO|ExK@l^+=IT2hifdtyfg;@wUMUx+j5 zphO^=j_yvx?|XJgaWu9yy=LbEs^w^^!ZW21{`@n%hBbGIg#^CJOTzM(&rc3vYOH`^ zf#7%NVCZIrjmkC$!&5<@BbPuvY=8l=GcxvUa9SC}iyI8Ps-JGT3x?kYCk(zXfe(lJ zuV&NkP7D@-#ml#56vJ{5O=B_GwR|)CcUKA85|8ozAqH2MLmW8io9D_AZJ-ZXwjkgW zZs?F-}GipSEy zIRJ~(6njZc|141Pz!_KT^$)BuHSARZ(ZNOsP$clLXIuHPrvi91B7&uHz|%)jWVne6 zC(HX*bQ=T6JS4E1e_ImP>H;w={s`Xc3ao^^64(}YxXK+#`o|5=g%X9uzk6=Dh%unlIvrxZrE%+aB-{v`{Gx%U88&Xl_`icLy9bSh z79I+YzWn|0xw$11F$DbEseMf!&(>iIwEx`JPSFIkGZ^D(GEJK~zP)+#z-}=-)>x<@ zzJC${GtvUKYl4_zc{J#{p{6abW&w%N7!AQ}0T3(hUT_Gz?5o+EgYp6aJpwkt>>Qp# zKF}Xi@#dl|Y~Bp9;uv@DoY{&j#(T#1UyS9=5F50;(EOnpqNke){1=d{1!Bf8CJVMe z2j~KW{sjW7&}^_v3q*mlrAsn2G!;0JhpjNaWe6^bY=i&B4Hm4KVgC{WR=BwjVHdX}NqQwfeu1Y-{2rn$UW|9!KN&4rAvS%i#@$Qc+l)xc h@PBChV=EGVL0nUn7z}y@!VLUSf*XJ6W02yA{{eYcLPY=o diff --git a/kbe/src/lib/python/Lib/enum.py b/kbe/src/lib/python/Lib/enum.py index e5a80cd609..5e97a9e8d8 100644 --- a/kbe/src/lib/python/Lib/enum.py +++ b/kbe/src/lib/python/Lib/enum.py @@ -25,18 +25,19 @@ def _is_descriptor(obj): def _is_dunder(name): """Returns True if a __dunder__ name, False otherwise.""" - return (name[:2] == name[-2:] == '__' and - name[2:3] != '_' and - name[-3:-2] != '_' and - len(name) > 4) + return (len(name) > 4 and + name[:2] == name[-2:] == '__' and + name[2] != '_' and + name[-3] != '_') def _is_sunder(name): """Returns True if a _sunder_ name, False otherwise.""" - return (name[0] == name[-1] == '_' and + return (len(name) > 2 and + name[0] == name[-1] == '_' and name[1:2] != '_' and - name[-2:-1] != '_' and - len(name) > 2) + name[-2:-1] != '_') + def _make_class_unpicklable(cls): """Make the given class un-picklable.""" @@ -156,7 +157,7 @@ def __new__(metacls, cls, bases, classdict): _order_ = classdict.pop('_order_', None) # check for illegal enum names (any others?) - invalid_names = set(enum_members) & {'mro', } + invalid_names = set(enum_members) & {'mro', ''} if invalid_names: raise ValueError('Invalid enum member name: {0}'.format( ','.join(invalid_names))) @@ -427,7 +428,7 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s if module is None: try: module = sys._getframe(2).f_globals['__name__'] - except (AttributeError, ValueError) as exc: + except (AttributeError, ValueError, KeyError) as exc: pass if module is None: _make_class_unpicklable(enum_class) @@ -532,8 +533,10 @@ def __new__(cls, value): # by-value search for a matching enum member # see if it's in the reverse mapping (for hashable values) try: - if value in cls._value2member_map_: - return cls._value2member_map_[value] + return cls._value2member_map_[value] + except KeyError: + # Not found, no need to do long O(n) search + pass except TypeError: # not there, now do long search -- O(n) behavior for member in cls._member_map_.values(): diff --git a/kbe/src/lib/python/Lib/functools.py b/kbe/src/lib/python/Lib/functools.py index 24b011dc04..b734899b56 100644 --- a/kbe/src/lib/python/Lib/functools.py +++ b/kbe/src/lib/python/Lib/functools.py @@ -413,7 +413,7 @@ def __hash__(self): def _make_key(args, kwds, typed, kwd_mark = (object(),), - fasttypes = {int, str, frozenset, type(None)}, + fasttypes = {int, str}, tuple=tuple, type=type, len=len): """Make a cache key from optionally typed positional and keyword arguments @@ -469,8 +469,11 @@ def lru_cache(maxsize=128, typed=False): # Early detection of an erroneous call to @lru_cache without any arguments # resulting in the inner function being passed to maxsize instead of an - # integer or None. - if maxsize is not None and not isinstance(maxsize, int): + # integer or None. Negative maxsize is treated as 0. + if isinstance(maxsize, int): + if maxsize < 0: + maxsize = 0 + elif maxsize is not None: raise TypeError('Expected maxsize to be an integer or None') def decorating_function(user_function): @@ -497,10 +500,10 @@ def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): if maxsize == 0: def wrapper(*args, **kwds): - # No caching -- just a statistics update after a successful call + # No caching -- just a statistics update nonlocal misses - result = user_function(*args, **kwds) misses += 1 + result = user_function(*args, **kwds) return result elif maxsize is None: @@ -513,9 +516,9 @@ def wrapper(*args, **kwds): if result is not sentinel: hits += 1 return result + misses += 1 result = user_function(*args, **kwds) cache[key] = result - misses += 1 return result else: @@ -537,6 +540,7 @@ def wrapper(*args, **kwds): link[NEXT] = root hits += 1 return result + misses += 1 result = user_function(*args, **kwds) with lock: if key in cache: @@ -574,7 +578,6 @@ def wrapper(*args, **kwds): # Use the cache_len bound method instead of the len() function # which could potentially be wrapped in an lru_cache itself. full = (cache_len() >= maxsize) - misses += 1 return result def cache_info(): diff --git a/kbe/src/lib/python/Lib/http/cookiejar.py b/kbe/src/lib/python/Lib/http/cookiejar.py index e0f1032b28..d63544a5f5 100644 --- a/kbe/src/lib/python/Lib/http/cookiejar.py +++ b/kbe/src/lib/python/Lib/http/cookiejar.py @@ -990,7 +990,7 @@ def set_ok_path(self, cookie, request): req_path = request_path(request) if ((cookie.version > 0 or (cookie.version == 0 and self.strict_ns_set_path)) and - not req_path.startswith(cookie.path)): + not self.path_return_ok(cookie.path, request)): _debug(" path attribute %s is not a prefix of request " "path %s", cookie.path, req_path) return False @@ -1145,6 +1145,11 @@ def return_ok_domain(self, cookie, request): req_host, erhn = eff_request_host(request) domain = cookie.domain + if domain and not domain.startswith("."): + dotdomain = "." + domain + else: + dotdomain = domain + # strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't if (cookie.version == 0 and (self.strict_ns_domain & self.DomainStrictNonDomain) and @@ -1157,7 +1162,7 @@ def return_ok_domain(self, cookie, request): _debug(" effective request-host name %s does not domain-match " "RFC 2965 cookie domain %s", erhn, domain) return False - if cookie.version == 0 and not ("."+erhn).endswith(domain): + if cookie.version == 0 and not ("."+erhn).endswith(dotdomain): _debug(" request-host %s does not match Netscape cookie domain " "%s", req_host, domain) return False @@ -1171,7 +1176,11 @@ def domain_return_ok(self, domain, request): req_host = "."+req_host if not erhn.startswith("."): erhn = "."+erhn - if not (req_host.endswith(domain) or erhn.endswith(domain)): + if domain and not domain.startswith("."): + dotdomain = "." + domain + else: + dotdomain = domain + if not (req_host.endswith(dotdomain) or erhn.endswith(dotdomain)): #_debug(" request domain %s does not match cookie domain %s", # req_host, domain) return False @@ -1188,11 +1197,15 @@ def domain_return_ok(self, domain, request): def path_return_ok(self, path, request): _debug("- checking cookie path=%s", path) req_path = request_path(request) - if not req_path.startswith(path): - _debug(" %s does not path-match %s", req_path, path) - return False - return True + pathlen = len(path) + if req_path == path: + return True + elif (req_path.startswith(path) and + (path.endswith("/") or req_path[pathlen:pathlen+1] == "/")): + return True + _debug(" %s does not path-match %s", req_path, path) + return False def vals_sorted_by_key(adict): keys = sorted(adict.keys()) diff --git a/kbe/src/lib/python/Lib/idlelib/NEWS.txt b/kbe/src/lib/python/Lib/idlelib/NEWS.txt index b93769e73b..c343538a29 100644 --- a/kbe/src/lib/python/Lib/idlelib/NEWS.txt +++ b/kbe/src/lib/python/Lib/idlelib/NEWS.txt @@ -1,8 +1,66 @@ -What's New in IDLE 3.7.2 -Released on 2018-07-31? +What's New in IDLE 3.7.3 +Released on 2019-??-?? ====================================== +bpo-36176: Fix IDLE autocomplete & calltip popup colors. +Prevent conflicts with Linux dark themes +(and slightly darken calltip background). + +bpo-36152: Remove colorizer.ColorDelegator.close_when_done and the +corresponding argument of .close(). In IDLE, both have always been +None or False since 2007. + +bpo-36096: Make colorizer state variables instance-only. + +bpo-24310: Document settings dialog font tab sample. + +bpo-35689: Add docstrings and tests for colorizer. + +bpo-35833: Revise IDLE doc for control codes sent to Shell. +Add a code example block. + +bpo-35770: IDLE macosx deletes Options => Configure IDLE. +It previously deleted Window => Zoom Height by mistake. +(Zoom Height is now on the Options menu). On Mac, the settings +dialog is accessed via Preferences on the IDLE menu. + +bpo-35769: Change new file name from 'Untitled' to 'untitled'. + +bpo-35660: Fix imports in window module. + +bpo-35641: Properly format calltip for function without docstring. + +bpo-33987: Use ttk Frame for ttk widgets. + +bpo-34055: Fix erroneous 'smart' indents and newlines in IDLE Shell. + +bpo-28097: Add Previous/Next History entries to Shell menu. + +bpo-35591: Find Selection now works when selection not found. + +bpo-35598: Update config_key: use PEP 8 names and ttk widgets, +make some objects global, and add tests. + +bpo-35196: Speed up squeezer line counting. + +bpo-35208: Squeezer now counts wrapped lines before newlines. + +bpo-35555: Gray out Code Context menu entry when it's not applicable. + +bpo-22703: Improve the Code Context and Zoom Height menu labels. +The Code Context menu label now toggles between Show/Hide Code Context. +The Zoom Height menu now toggles between Zoom/Restore Height. +Zoom Height has moved from the Window menu to the Options menu. + +bpo-35521: Document the editor code context feature. +Add some internal references within the IDLE doc. + + +What's New in IDLE 3.7.2 +Released on 2018-12-21? +====================================== + bpo-34864: When starting IDLE on MacOS, warn if the system setting "Prefer tabs when opening documents" is "Always". As previous documented for this issue, running IDLE with this setting causes diff --git a/kbe/src/lib/python/Lib/idlelib/autocomplete_w.py b/kbe/src/lib/python/Lib/idlelib/autocomplete_w.py index 9e0d336523..c249625277 100644 --- a/kbe/src/lib/python/Lib/idlelib/autocomplete_w.py +++ b/kbe/src/lib/python/Lib/idlelib/autocomplete_w.py @@ -4,7 +4,7 @@ import platform from tkinter import * -from tkinter.ttk import Scrollbar +from tkinter.ttk import Frame, Scrollbar from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES from idlelib.multicall import MC_SHIFT @@ -189,7 +189,7 @@ def show_window(self, comp_lists, index, complete, mode, userWantsWin): pass self.scrollbar = scrollbar = Scrollbar(acw, orient=VERTICAL) self.listbox = listbox = Listbox(acw, yscrollcommand=scrollbar.set, - exportselection=False, bg="white") + exportselection=False) for item in self.completions: listbox.insert(END, item) self.origselforeground = listbox.cget("selectforeground") diff --git a/kbe/src/lib/python/Lib/idlelib/calltip.py b/kbe/src/lib/python/Lib/idlelib/calltip.py index 758569a45f..2a9a131ed9 100644 --- a/kbe/src/lib/python/Lib/idlelib/calltip.py +++ b/kbe/src/lib/python/Lib/idlelib/calltip.py @@ -167,7 +167,7 @@ def get_argspec(ob): if len(line) > _MAX_COLS: line = line[: _MAX_COLS - 3] + '...' lines.append(line) - argspec = '\n'.join(lines) + argspec = '\n'.join(lines) if not argspec: argspec = _default_callable_argspec return argspec diff --git a/kbe/src/lib/python/Lib/idlelib/calltip_w.py b/kbe/src/lib/python/Lib/idlelib/calltip_w.py index 7553dfefc5..1e0404aa49 100644 --- a/kbe/src/lib/python/Lib/idlelib/calltip_w.py +++ b/kbe/src/lib/python/Lib/idlelib/calltip_w.py @@ -80,7 +80,8 @@ def showtip(self, text, parenleft, parenright): def showcontents(self): """Create the call-tip widget.""" self.label = Label(self.tipwindow, text=self.text, justify=LEFT, - background="#ffffe0", relief=SOLID, borderwidth=1, + background="#ffffd0", foreground="black", + relief=SOLID, borderwidth=1, font=self.anchor_widget['font']) self.label.pack() diff --git a/kbe/src/lib/python/Lib/idlelib/codecontext.py b/kbe/src/lib/python/Lib/idlelib/codecontext.py index ef8852852d..2aed76de7f 100644 --- a/kbe/src/lib/python/Lib/idlelib/codecontext.py +++ b/kbe/src/lib/python/Lib/idlelib/codecontext.py @@ -122,9 +122,13 @@ def toggle_code_context_event(self, event=None): # thus ensuring that it will appear directly above text_frame. self.context.pack(side=TOP, fill=X, expand=False, before=self.editwin.text_frame) + menu_status = 'Hide' else: self.context.destroy() self.context = None + menu_status = 'Show' + self.editwin.update_menu_label(menu='options', index='* Code Context', + label=f'{menu_status} Code Context') return "break" def get_context(self, new_topvisible, stopline=1, stopindent=0): diff --git a/kbe/src/lib/python/Lib/idlelib/colorizer.py b/kbe/src/lib/python/Lib/idlelib/colorizer.py index d4e592b6eb..facbef8bb1 100644 --- a/kbe/src/lib/python/Lib/idlelib/colorizer.py +++ b/kbe/src/lib/python/Lib/idlelib/colorizer.py @@ -53,14 +53,46 @@ def color_config(text): class ColorDelegator(Delegator): + """Delegator for syntax highlighting (text coloring). + + Instance variables: + delegate: Delegator below this one in the stack, meaning the + one this one delegates to. + + Used to track state: + after_id: Identifier for scheduled after event, which is a + timer for colorizing the text. + allow_colorizing: Boolean toggle for applying colorizing. + colorizing: Boolean flag when colorizing is in process. + stop_colorizing: Boolean flag to end an active colorizing + process. + """ def __init__(self): Delegator.__init__(self) + self.init_state() self.prog = prog self.idprog = idprog self.LoadTagDefs() + def init_state(self): + "Initialize variables that track colorizing state." + self.after_id = None + self.allow_colorizing = True + self.stop_colorizing = False + self.colorizing = False + def setdelegate(self, delegate): + """Set the delegate for this instance. + + A delegate is an instance of a Delegator class and each + delegate points to the next delegator in the stack. This + allows multiple delegators to be chained together for a + widget. The bottom delegate for a colorizer is a Text + widget. + + If there is a delegate, also start the colorizing process. + """ if self.delegate is not None: self.unbind("<>") Delegator.setdelegate(self, delegate) @@ -69,17 +101,18 @@ def setdelegate(self, delegate): self.bind("<>", self.toggle_colorize_event) self.notify_range("1.0", "end") else: - # No delegate - stop any colorizing + # No delegate - stop any colorizing. self.stop_colorizing = True self.allow_colorizing = False def config_colors(self): + "Configure text widget tags with colors from tagdefs." for tag, cnf in self.tagdefs.items(): - if cnf: - self.tag_configure(tag, **cnf) + self.tag_configure(tag, **cnf) self.tag_raise('sel') def LoadTagDefs(self): + "Create dictionary of tag names to text colors." theme = idleConf.CurrentTheme() self.tagdefs = { "COMMENT": idleConf.GetHighlight(theme, "comment"), @@ -97,20 +130,19 @@ def LoadTagDefs(self): if DEBUG: print('tagdefs',self.tagdefs) def insert(self, index, chars, tags=None): + "Insert chars into widget at index and mark for colorizing." index = self.index(index) self.delegate.insert(index, chars, tags) self.notify_range(index, index + "+%dc" % len(chars)) def delete(self, index1, index2=None): + "Delete chars between indexes and mark for colorizing." index1 = self.index(index1) self.delegate.delete(index1, index2) self.notify_range(index1) - after_id = None - allow_colorizing = True - colorizing = False - def notify_range(self, index1, index2=None): + "Mark text changes for processing and restart colorizing, if active." self.tag_add("TODO", index1, index2) if self.after_id: if DEBUG: print("colorizing already scheduled") @@ -121,10 +153,9 @@ def notify_range(self, index1, index2=None): if self.allow_colorizing: if DEBUG: print("schedule colorizing") self.after_id = self.after(1, self.recolorize) + return - close_when_done = None # Window to be closed when done colorizing - - def close(self, close_when_done=None): + def close(self): if self.after_id: after_id = self.after_id self.after_id = None @@ -132,13 +163,15 @@ def close(self, close_when_done=None): self.after_cancel(after_id) self.allow_colorizing = False self.stop_colorizing = True - if close_when_done: - if not self.colorizing: - close_when_done.destroy() - else: - self.close_when_done = close_when_done - def toggle_colorize_event(self, event): + def toggle_colorize_event(self, event=None): + """Toggle colorizing on and off. + + When toggling off, if colorizing is scheduled or is in + process, it will be cancelled and/or stopped. + + When toggling on, colorizing will be scheduled. + """ if self.after_id: after_id = self.after_id self.after_id = None @@ -156,6 +189,15 @@ def toggle_colorize_event(self, event): return "break" def recolorize(self): + """Timer event (every 1ms) to colorize text. + + Colorizing is only attempted when the text widget exists, + when colorizing is toggled on, and when the colorizing + process is not already running. + + After colorizing is complete, some cleanup is done to + make sure that all the text has been colorized. + """ self.after_id = None if not self.delegate: if DEBUG: print("no delegate") @@ -179,12 +221,9 @@ def recolorize(self): if self.allow_colorizing and self.tag_nextrange("TODO", "1.0"): if DEBUG: print("reschedule colorizing") self.after_id = self.after(1, self.recolorize) - if self.close_when_done: - top = self.close_when_done - self.close_when_done = None - top.destroy() def recolorize_main(self): + "Evaluate text and apply colorizing tags." next = "1.0" while True: item = self.tag_nextrange("TODO", next) @@ -250,6 +289,7 @@ def recolorize_main(self): return def removecolors(self): + "Remove all colorizing tags." for tag in self.tagdefs: self.tag_remove(tag, "1.0", "end") @@ -273,7 +313,7 @@ def _color_delegator(parent): # htest # "'x', '''x''', \"x\", \"\"\"x\"\"\"\n" "r'x', u'x', R'x', U'x', f'x', F'x'\n" "fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n" - "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x'.rB'x',Rb'x',RB'x'\n" + "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'\n" "# Invalid combinations of legal characters should be half colored.\n" "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n" ) diff --git a/kbe/src/lib/python/Lib/idlelib/config_key.py b/kbe/src/lib/python/Lib/idlelib/config_key.py index abab74265f..4478323fcc 100644 --- a/kbe/src/lib/python/Lib/idlelib/config_key.py +++ b/kbe/src/lib/python/Lib/idlelib/config_key.py @@ -1,51 +1,85 @@ """ Dialog for building Tkinter accelerator key bindings """ -from tkinter import * -from tkinter.ttk import Scrollbar +from tkinter import Toplevel, Listbox, Text, StringVar, TclError +from tkinter.ttk import Frame, Button, Checkbutton, Entry, Label, Scrollbar from tkinter import messagebox import string import sys +FUNCTION_KEYS = ('F1', 'F2' ,'F3' ,'F4' ,'F5' ,'F6', + 'F7', 'F8' ,'F9' ,'F10' ,'F11' ,'F12') +ALPHANUM_KEYS = tuple(string.ascii_lowercase + string.digits) +PUNCTUATION_KEYS = tuple('~!@#%^&*()_-+={}[]|;:,.<>/?') +WHITESPACE_KEYS = ('Tab', 'Space', 'Return') +EDIT_KEYS = ('BackSpace', 'Delete', 'Insert') +MOVE_KEYS = ('Home', 'End', 'Page Up', 'Page Down', 'Left Arrow', + 'Right Arrow', 'Up Arrow', 'Down Arrow') +AVAILABLE_KEYS = (ALPHANUM_KEYS + PUNCTUATION_KEYS + FUNCTION_KEYS + + WHITESPACE_KEYS + EDIT_KEYS + MOVE_KEYS) + + +def translate_key(key, modifiers): + "Translate from keycap symbol to the Tkinter keysym." + mapping = {'Space':'space', + '~':'asciitilde', '!':'exclam', '@':'at', '#':'numbersign', + '%':'percent', '^':'asciicircum', '&':'ampersand', + '*':'asterisk', '(':'parenleft', ')':'parenright', + '_':'underscore', '-':'minus', '+':'plus', '=':'equal', + '{':'braceleft', '}':'braceright', + '[':'bracketleft', ']':'bracketright', '|':'bar', + ';':'semicolon', ':':'colon', ',':'comma', '.':'period', + '<':'less', '>':'greater', '/':'slash', '?':'question', + 'Page Up':'Prior', 'Page Down':'Next', + 'Left Arrow':'Left', 'Right Arrow':'Right', + 'Up Arrow':'Up', 'Down Arrow': 'Down', 'Tab':'Tab'} + key = mapping.get(key, key) + if 'Shift' in modifiers and key in string.ascii_lowercase: + key = key.upper() + return f'Key-{key}' + + class GetKeysDialog(Toplevel): # Dialog title for invalid key sequence keyerror_title = 'Key Sequence Error' - def __init__(self, parent, title, action, currentKeySequences, + def __init__(self, parent, title, action, current_key_sequences, *, _htest=False, _utest=False): """ + parent - parent of this dialog + title - string which is the title of the popup dialog action - string, the name of the virtual event these keys will be mapped to - currentKeys - list, a list of all key sequence lists currently mapped - to virtual events, for overlap checking - _utest - bool, do not wait when running unittest + current_key_sequences - list, a list of all key sequence lists + currently mapped to virtual events, for overlap checking _htest - bool, change box location when running htest + _utest - bool, do not wait when running unittest """ Toplevel.__init__(self, parent) - self.withdraw() #hide while setting geometry + self.withdraw() # Hide while setting geometry. self.configure(borderwidth=5) - self.resizable(height=FALSE, width=FALSE) + self.resizable(height=False, width=False) self.title(title) self.transient(parent) self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) + self.protocol("WM_DELETE_WINDOW", self.cancel) self.parent = parent - self.action=action - self.currentKeySequences = currentKeySequences + self.action = action + self.current_key_sequences = current_key_sequences self.result = '' - self.keyString = StringVar(self) - self.keyString.set('') - self.SetModifiersForPlatform() # set self.modifiers, self.modifier_label + self.key_string = StringVar(self) + self.key_string.set('') + # Set self.modifiers, self.modifier_label. + self.set_modifiers_for_platform() self.modifier_vars = [] for modifier in self.modifiers: variable = StringVar(self) variable.set('') self.modifier_vars.append(variable) self.advanced = False - self.CreateWidgets() - self.LoadFinalKeyList() + self.create_widgets() self.update_idletasks() self.geometry( "+%d+%d" % ( @@ -54,83 +88,100 @@ def __init__(self, parent, title, action, currentKeySequences, parent.winfo_rooty() + ((parent.winfo_height()/2 - self.winfo_reqheight()/2) if not _htest else 150) - ) ) #centre dialog over parent (or below htest box) + ) ) # Center dialog over parent (or below htest box). if not _utest: - self.deiconify() #geometry set, unhide + self.deiconify() # Geometry set, unhide. self.wait_window() def showerror(self, *args, **kwargs): # Make testing easier. Replace in #30751. messagebox.showerror(*args, **kwargs) - def CreateWidgets(self): - frameMain = Frame(self,borderwidth=2,relief=SUNKEN) - frameMain.pack(side=TOP,expand=TRUE,fill=BOTH) - frameButtons=Frame(self) - frameButtons.pack(side=BOTTOM,fill=X) - self.buttonOK = Button(frameButtons,text='OK', - width=8,command=self.OK) - self.buttonOK.grid(row=0,column=0,padx=5,pady=5) - self.buttonCancel = Button(frameButtons,text='Cancel', - width=8,command=self.Cancel) - self.buttonCancel.grid(row=0,column=1,padx=5,pady=5) - self.frameKeySeqBasic = Frame(frameMain) - self.frameKeySeqAdvanced = Frame(frameMain) - self.frameControlsBasic = Frame(frameMain) - self.frameHelpAdvanced = Frame(frameMain) - self.frameKeySeqAdvanced.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5) - self.frameKeySeqBasic.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5) - self.frameKeySeqBasic.lift() - self.frameHelpAdvanced.grid(row=1,column=0,sticky=NSEW,padx=5) - self.frameControlsBasic.grid(row=1,column=0,sticky=NSEW,padx=5) - self.frameControlsBasic.lift() - self.buttonLevel = Button(frameMain,command=self.ToggleLevel, - text='Advanced Key Binding Entry >>') - self.buttonLevel.grid(row=2,column=0,stick=EW,padx=5,pady=5) - labelTitleBasic = Label(self.frameKeySeqBasic, - text="New keys for '"+self.action+"' :") - labelTitleBasic.pack(anchor=W) - labelKeysBasic = Label(self.frameKeySeqBasic,justify=LEFT, - textvariable=self.keyString,relief=GROOVE,borderwidth=2) - labelKeysBasic.pack(ipadx=5,ipady=5,fill=X) + def create_widgets(self): + self.frame = frame = Frame(self, borderwidth=2, relief='sunken') + frame.pack(side='top', expand=True, fill='both') + + frame_buttons = Frame(self) + frame_buttons.pack(side='bottom', fill='x') + + self.button_ok = Button(frame_buttons, text='OK', + width=8, command=self.ok) + self.button_ok.grid(row=0, column=0, padx=5, pady=5) + self.button_cancel = Button(frame_buttons, text='Cancel', + width=8, command=self.cancel) + self.button_cancel.grid(row=0, column=1, padx=5, pady=5) + + # Basic entry key sequence. + self.frame_keyseq_basic = Frame(frame, name='keyseq_basic') + self.frame_keyseq_basic.grid(row=0, column=0, sticky='nsew', + padx=5, pady=5) + basic_title = Label(self.frame_keyseq_basic, + text=f"New keys for '{self.action}' :") + basic_title.pack(anchor='w') + + basic_keys = Label(self.frame_keyseq_basic, justify='left', + textvariable=self.key_string, relief='groove', + borderwidth=2) + basic_keys.pack(ipadx=5, ipady=5, fill='x') + + # Basic entry controls. + self.frame_controls_basic = Frame(frame) + self.frame_controls_basic.grid(row=1, column=0, sticky='nsew', padx=5) + + # Basic entry modifiers. self.modifier_checkbuttons = {} column = 0 for modifier, variable in zip(self.modifiers, self.modifier_vars): label = self.modifier_label.get(modifier, modifier) - check=Checkbutton(self.frameControlsBasic, - command=self.BuildKeyString, - text=label,variable=variable,onvalue=modifier,offvalue='') - check.grid(row=0,column=column,padx=2,sticky=W) + check = Checkbutton(self.frame_controls_basic, + command=self.build_key_string, text=label, + variable=variable, onvalue=modifier, offvalue='') + check.grid(row=0, column=column, padx=2, sticky='w') self.modifier_checkbuttons[modifier] = check column += 1 - labelFnAdvice=Label(self.frameControlsBasic,justify=LEFT, - text=\ - "Select the desired modifier keys\n"+ - "above, and the final key from the\n"+ - "list on the right.\n\n" + - "Use upper case Symbols when using\n" + - "the Shift modifier. (Letters will be\n" + - "converted automatically.)") - labelFnAdvice.grid(row=1,column=0,columnspan=4,padx=2,sticky=W) - self.listKeysFinal=Listbox(self.frameControlsBasic,width=15,height=10, - selectmode=SINGLE) - self.listKeysFinal.bind('',self.FinalKeySelected) - self.listKeysFinal.grid(row=0,column=4,rowspan=4,sticky=NS) - scrollKeysFinal=Scrollbar(self.frameControlsBasic,orient=VERTICAL, - command=self.listKeysFinal.yview) - self.listKeysFinal.config(yscrollcommand=scrollKeysFinal.set) - scrollKeysFinal.grid(row=0,column=5,rowspan=4,sticky=NS) - self.buttonClear=Button(self.frameControlsBasic, - text='Clear Keys',command=self.ClearKeySeq) - self.buttonClear.grid(row=2,column=0,columnspan=4) - labelTitleAdvanced = Label(self.frameKeySeqAdvanced,justify=LEFT, - text="Enter new binding(s) for '"+self.action+"' :\n"+ - "(These bindings will not be checked for validity!)") - labelTitleAdvanced.pack(anchor=W) - self.entryKeysAdvanced=Entry(self.frameKeySeqAdvanced, - textvariable=self.keyString) - self.entryKeysAdvanced.pack(fill=X) - labelHelpAdvanced=Label(self.frameHelpAdvanced,justify=LEFT, + + # Basic entry help text. + help_basic = Label(self.frame_controls_basic, justify='left', + text="Select the desired modifier keys\n"+ + "above, and the final key from the\n"+ + "list on the right.\n\n" + + "Use upper case Symbols when using\n" + + "the Shift modifier. (Letters will be\n" + + "converted automatically.)") + help_basic.grid(row=1, column=0, columnspan=4, padx=2, sticky='w') + + # Basic entry key list. + self.list_keys_final = Listbox(self.frame_controls_basic, width=15, + height=10, selectmode='single') + self.list_keys_final.insert('end', *AVAILABLE_KEYS) + self.list_keys_final.bind('', self.final_key_selected) + self.list_keys_final.grid(row=0, column=4, rowspan=4, sticky='ns') + scroll_keys_final = Scrollbar(self.frame_controls_basic, + orient='vertical', + command=self.list_keys_final.yview) + self.list_keys_final.config(yscrollcommand=scroll_keys_final.set) + scroll_keys_final.grid(row=0, column=5, rowspan=4, sticky='ns') + self.button_clear = Button(self.frame_controls_basic, + text='Clear Keys', + command=self.clear_key_seq) + self.button_clear.grid(row=2, column=0, columnspan=4) + + # Advanced entry key sequence. + self.frame_keyseq_advanced = Frame(frame, name='keyseq_advanced') + self.frame_keyseq_advanced.grid(row=0, column=0, sticky='nsew', + padx=5, pady=5) + advanced_title = Label(self.frame_keyseq_advanced, justify='left', + text=f"Enter new binding(s) for '{self.action}' :\n" + + "(These bindings will not be checked for validity!)") + advanced_title.pack(anchor='w') + self.advanced_keys = Entry(self.frame_keyseq_advanced, + textvariable=self.key_string) + self.advanced_keys.pack(fill='x') + + # Advanced entry help text. + self.frame_help_advanced = Frame(frame) + self.frame_help_advanced.grid(row=1, column=0, sticky='nsew', padx=5) + help_advanced = Label(self.frame_help_advanced, justify='left', text="Key bindings are specified using Tkinter keysyms as\n"+ "in these samples: , , ,\n" ", , .\n" @@ -140,13 +191,19 @@ def CreateWidgets(self): "is the 'do-nothing' keybinding.\n\n" + "Multiple separate bindings for one action should be\n"+ "separated by a space, eg., ." ) - labelHelpAdvanced.grid(row=0,column=0,sticky=NSEW) + help_advanced.grid(row=0, column=0, sticky='nsew') + + # Switch between basic and advanced. + self.button_level = Button(frame, command=self.toggle_level, + text='<< Basic Key Binding Entry') + self.button_level.grid(row=2, column=0, stick='ew', padx=5, pady=5) + self.toggle_level() - def SetModifiersForPlatform(self): + def set_modifiers_for_platform(self): """Determine list of names of key modifiers for this platform. The names are used to build Tk bindings -- it doesn't matter if the - keyboard has these keys, it matters if Tk understands them. The + keyboard has these keys; it matters if Tk understands them. The order is also important: key binding equality depends on it, so config-keys.def must use the same ordering. """ @@ -154,118 +211,87 @@ def SetModifiersForPlatform(self): self.modifiers = ['Shift', 'Control', 'Option', 'Command'] else: self.modifiers = ['Control', 'Alt', 'Shift'] - self.modifier_label = {'Control': 'Ctrl'} # short name - - def ToggleLevel(self): - if self.buttonLevel.cget('text')[:8]=='Advanced': - self.ClearKeySeq() - self.buttonLevel.config(text='<< Basic Key Binding Entry') - self.frameKeySeqAdvanced.lift() - self.frameHelpAdvanced.lift() - self.entryKeysAdvanced.focus_set() + self.modifier_label = {'Control': 'Ctrl'} # Short name. + + def toggle_level(self): + "Toggle between basic and advanced keys." + if self.button_level.cget('text').startswith('Advanced'): + self.clear_key_seq() + self.button_level.config(text='<< Basic Key Binding Entry') + self.frame_keyseq_advanced.lift() + self.frame_help_advanced.lift() + self.advanced_keys.focus_set() self.advanced = True else: - self.ClearKeySeq() - self.buttonLevel.config(text='Advanced Key Binding Entry >>') - self.frameKeySeqBasic.lift() - self.frameControlsBasic.lift() + self.clear_key_seq() + self.button_level.config(text='Advanced Key Binding Entry >>') + self.frame_keyseq_basic.lift() + self.frame_controls_basic.lift() self.advanced = False - def FinalKeySelected(self,event): - self.BuildKeyString() + def final_key_selected(self, event=None): + "Handler for clicking on key in basic settings list." + self.build_key_string() - def BuildKeyString(self): - keyList = modifiers = self.GetModifiers() - finalKey = self.listKeysFinal.get(ANCHOR) - if finalKey: - finalKey = self.TranslateKey(finalKey, modifiers) - keyList.append(finalKey) - self.keyString.set('<' + '-'.join(keyList) + '>') + def build_key_string(self): + "Create formatted string of modifiers plus the key." + keylist = modifiers = self.get_modifiers() + final_key = self.list_keys_final.get('anchor') + if final_key: + final_key = translate_key(final_key, modifiers) + keylist.append(final_key) + self.key_string.set(f"<{'-'.join(keylist)}>") - def GetModifiers(self): - modList = [variable.get() for variable in self.modifier_vars] - return [mod for mod in modList if mod] + def get_modifiers(self): + "Return ordered list of modifiers that have been selected." + mod_list = [variable.get() for variable in self.modifier_vars] + return [mod for mod in mod_list if mod] - def ClearKeySeq(self): - self.listKeysFinal.select_clear(0,END) - self.listKeysFinal.yview(MOVETO, '0.0') + def clear_key_seq(self): + "Clear modifiers and keys selection." + self.list_keys_final.select_clear(0, 'end') + self.list_keys_final.yview('moveto', '0.0') for variable in self.modifier_vars: variable.set('') - self.keyString.set('') - - def LoadFinalKeyList(self): - #these tuples are also available for use in validity checks - self.functionKeys=('F1','F2','F3','F4','F5','F6','F7','F8','F9', - 'F10','F11','F12') - self.alphanumKeys=tuple(string.ascii_lowercase+string.digits) - self.punctuationKeys=tuple('~!@#%^&*()_-+={}[]|;:,.<>/?') - self.whitespaceKeys=('Tab','Space','Return') - self.editKeys=('BackSpace','Delete','Insert') - self.moveKeys=('Home','End','Page Up','Page Down','Left Arrow', - 'Right Arrow','Up Arrow','Down Arrow') - #make a tuple of most of the useful common 'final' keys - keys=(self.alphanumKeys+self.punctuationKeys+self.functionKeys+ - self.whitespaceKeys+self.editKeys+self.moveKeys) - self.listKeysFinal.insert(END, *keys) - - def TranslateKey(self, key, modifiers): - "Translate from keycap symbol to the Tkinter keysym" - translateDict = {'Space':'space', - '~':'asciitilde','!':'exclam','@':'at','#':'numbersign', - '%':'percent','^':'asciicircum','&':'ampersand','*':'asterisk', - '(':'parenleft',')':'parenright','_':'underscore','-':'minus', - '+':'plus','=':'equal','{':'braceleft','}':'braceright', - '[':'bracketleft',']':'bracketright','|':'bar',';':'semicolon', - ':':'colon',',':'comma','.':'period','<':'less','>':'greater', - '/':'slash','?':'question','Page Up':'Prior','Page Down':'Next', - 'Left Arrow':'Left','Right Arrow':'Right','Up Arrow':'Up', - 'Down Arrow': 'Down', 'Tab':'Tab'} - if key in translateDict: - key = translateDict[key] - if 'Shift' in modifiers and key in string.ascii_lowercase: - key = key.upper() - key = 'Key-' + key - return key - - def OK(self, event=None): - keys = self.keyString.get().strip() + self.key_string.set('') + + def ok(self, event=None): + keys = self.key_string.get().strip() if not keys: self.showerror(title=self.keyerror_title, parent=self, message="No key specified.") return - if (self.advanced or self.KeysOK(keys)) and self.bind_ok(keys): + if (self.advanced or self.keys_ok(keys)) and self.bind_ok(keys): self.result = keys self.grab_release() self.destroy() - def Cancel(self, event=None): - self.result='' + def cancel(self, event=None): + self.result = '' self.grab_release() self.destroy() - def KeysOK(self, keys): - '''Validity check on user's 'basic' keybinding selection. + def keys_ok(self, keys): + """Validity check on user's 'basic' keybinding selection. Doesn't check the string produced by the advanced dialog because 'modifiers' isn't set. - - ''' - finalKey = self.listKeysFinal.get(ANCHOR) - modifiers = self.GetModifiers() - keysOK = False + """ + final_key = self.list_keys_final.get('anchor') + modifiers = self.get_modifiers() title = self.keyerror_title - key_sequences = [key for keylist in self.currentKeySequences + key_sequences = [key for keylist in self.current_key_sequences for key in keylist] if not keys.endswith('>'): self.showerror(title, parent=self, message='Missing the final Key') elif (not modifiers - and finalKey not in self.functionKeys + self.moveKeys): + and final_key not in FUNCTION_KEYS + MOVE_KEYS): self.showerror(title=title, parent=self, message='No modifier key(s) specified.') elif (modifiers == ['Shift']) \ - and (finalKey not in - self.functionKeys + self.moveKeys + ('Tab', 'Space')): + and (final_key not in + FUNCTION_KEYS + MOVE_KEYS + ('Tab', 'Space')): msg = 'The shift modifier by itself may not be used with'\ ' this key symbol.' self.showerror(title=title, parent=self, message=msg) @@ -273,12 +299,11 @@ def KeysOK(self, keys): msg = 'This key combination is already in use.' self.showerror(title=title, parent=self, message=msg) else: - keysOK = True - return keysOK + return True + return False def bind_ok(self, keys): "Return True if Tcl accepts the new keys else show message." - try: binding = self.bind(keys, lambda: None) except TclError as err: diff --git a/kbe/src/lib/python/Lib/idlelib/configdialog.py b/kbe/src/lib/python/Lib/idlelib/configdialog.py index 229dc89874..5fdaf82de4 100644 --- a/kbe/src/lib/python/Lib/idlelib/configdialog.py +++ b/kbe/src/lib/python/Lib/idlelib/configdialog.py @@ -14,7 +14,7 @@ TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE, NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW, HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END) -from tkinter.ttk import (Button, Checkbutton, Entry, Frame, Label, LabelFrame, +from tkinter.ttk import (Frame, LabelFrame, Button, Checkbutton, Entry, Label, OptionMenu, Notebook, Radiobutton, Scrollbar, Style) import tkinter.colorchooser as tkColorChooser import tkinter.font as tkFont diff --git a/kbe/src/lib/python/Lib/idlelib/debugger.py b/kbe/src/lib/python/Lib/idlelib/debugger.py index 09f912c9af..ccd03e46e1 100644 --- a/kbe/src/lib/python/Lib/idlelib/debugger.py +++ b/kbe/src/lib/python/Lib/idlelib/debugger.py @@ -2,7 +2,7 @@ import os from tkinter import * -from tkinter.ttk import Scrollbar +from tkinter.ttk import Frame, Scrollbar from idlelib import macosx from idlelib.scrolledlist import ScrolledList diff --git a/kbe/src/lib/python/Lib/idlelib/editor.py b/kbe/src/lib/python/Lib/idlelib/editor.py index 6689af64c4..8326032964 100644 --- a/kbe/src/lib/python/Lib/idlelib/editor.py +++ b/kbe/src/lib/python/Lib/idlelib/editor.py @@ -317,9 +317,6 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind("<>", self.ZoomHeight(self).zoom_height_event) text.bind("<>", self.CodeContext(self).toggle_code_context_event) - squeezer = self.Squeezer(self) - text.bind("<>", - squeezer.squeeze_current_text_event) def _filename_to_unicode(self, filename): """Return filename as BMP unicode so diplayable in Tk.""" @@ -446,6 +443,16 @@ def postwindowsmenu(self): menu.delete(self.wmenu_end+1, end) window.add_windows_to_menu(menu) + def update_menu_label(self, menu, index, label): + "Update label for menu item at index." + menuitem = self.menudict[menu] + menuitem.entryconfig(index, label=label) + + def update_menu_state(self, menu, index, state): + "Update state for menu item at index." + menuitem = self.menudict[menu] + menuitem.entryconfig(index, state=state) + def handle_yview(self, event, *args): "Handle scrollbar." if event == 'moveto': @@ -936,7 +943,7 @@ def saved_change_hook(self): elif long: title = long else: - title = "Untitled" + title = "untitled" icon = short or long or title if not self.get_saved(): title = "*%s*" % title @@ -958,7 +965,7 @@ def short_title(self): if filename: filename = os.path.basename(filename) else: - filename = "Untitled" + filename = "untitled" # return unicode string to display non-ASCII chars correctly return self._filename_to_unicode(filename) @@ -1026,7 +1033,7 @@ def _close(self): self.io = None self.undo = None if self.color: - self.color.close(False) + self.color.close() self.color = None self.text = None self.tkinter_vars = None diff --git a/kbe/src/lib/python/Lib/idlelib/grep.py b/kbe/src/lib/python/Lib/idlelib/grep.py index 8cc293c380..873233ec15 100644 --- a/kbe/src/lib/python/Lib/idlelib/grep.py +++ b/kbe/src/lib/python/Lib/idlelib/grep.py @@ -8,7 +8,7 @@ import sys from tkinter import StringVar, BooleanVar -from tkinter.ttk import Checkbutton +from tkinter.ttk import Checkbutton # Frame imported in ...Base from idlelib.searchbase import SearchDialogBase from idlelib import searchengine @@ -173,15 +173,18 @@ def findfiles(self, dir, base, rec): def _grep_dialog(parent): # htest # from tkinter import Toplevel, Text, SEL, END - from tkinter.ttk import Button + from tkinter.ttk import Frame, Button from idlelib.pyshell import PyShellFileList + top = Toplevel(parent) top.title("Test GrepDialog") x, y = map(int, parent.geometry().split('+')[1:]) top.geometry(f"+{x}+{y + 175}") flist = PyShellFileList(top) - text = Text(top, height=5) + frame = Frame(top) + frame.pack() + text = Text(frame, height=5) text.pack() def show_grep_dialog(): @@ -189,7 +192,7 @@ def show_grep_dialog(): grep(text, flist=flist) text.tag_remove(SEL, "1.0", END) - button = Button(top, text="Show GrepDialog", command=show_grep_dialog) + button = Button(frame, text="Show GrepDialog", command=show_grep_dialog) button.pack() if __name__ == "__main__": diff --git a/kbe/src/lib/python/Lib/idlelib/help.html b/kbe/src/lib/python/Lib/idlelib/help.html index e2bf773478..b654ab7f2c 100644 --- a/kbe/src/lib/python/Lib/idlelib/help.html +++ b/kbe/src/lib/python/Lib/idlelib/help.html @@ -6,7 +6,7 @@ - IDLE — Python 3.8.0a0 documentation + IDLE — Python 3.8.0a1 documentation @@ -19,7 +19,7 @@ @@ -72,7 +72,7 @@

    Edit menu (Shell and Editor)Completions in the Editing and navigation section below.
    Expand Word
    Expand a prefix you have typed to match a full word in the same window; repeat to get a different expansion.
    Show call tip
    After an unclosed parenthesis for a function, open a small window with -function parameter hints.
    +function parameter hints. See Calltips in the +Editing and navigation section below.
    Show surrounding parens
    Highlight the surrounding parenthesis.
    -

    Format menu (Editor window only)

    +

    Format menu (Editor window only)

    Indent Region
    Shift selected lines right by the indent width (default 4 spaces).
    @@ -272,6 +273,10 @@

    Shell menu (Shell window only)

    Configure IDLE
    -

    Open a configuration dialog and change preferences for the following: +

    Open a configuration dialog and change preferences for the following: fonts, indentation, keybindings, text color themes, startup windows and -size, additional help sources, and extensions (see below). On macOS, -open the configuration dialog by selecting Preferences in the application -menu. To use a new built-in color theme (IDLE Dark) with older IDLEs, -save it as a new custom theme.

    -

    Non-default user settings are saved in a .idlerc directory in the user’s -home directory. Problems caused by bad user configuration files are solved -by editing or deleting one or more of the files in .idlerc.

    -
    -
    Code Context (toggle)(Editor Window only)
    +size, additional help sources, and extensions. On macOS, open the +configuration dialog by selecting Preferences in the application +menu. For more, see +Setting preferences under Help and preferences. +
    Zoom/Restore Height
    +
    Toggles the window between normal size and maximum height. The initial size +defaults to 40 lines by 80 chars unless changed on the General tab of the +Configure IDLE dialog.
    +
    Show/Hide Code Context (Editor Window only)
    Open a pane at the top of the edit window which shows the block context -of the code which has scrolled above the top of the window. Clicking a -line in this pane exposes that line at the top of the editor.
    +of the code which has scrolled above the top of the window. See +Code Context in the Editing and Navigation section below.

    Window menu (Shell and Editor)

    -
    -
    Zoom Height
    -
    Toggles the window between normal size and maximum height. The initial size -defaults to 40 lines by 80 chars unless changed on the General tab of the -Configure IDLE dialog.
    -
    -

    The rest of this menu lists the names of all open windows; select one to bring -it to the foreground (deiconifying it if necessary).

    +

    Lists the names of all open windows; select one to bring it to the foreground +(deiconifying it if necessary).

    Help menu (Shell and Editor)

    @@ -344,8 +343,8 @@

    Help menu (Shell and Editor)Help sources subsection below +for more on Help menu choices.

    Context Menus

    @@ -383,7 +382,7 @@

    Help menu (Shell and Editor) -

    Editing and navigation

    +

    Editing and navigation

    -

    Completions

    +

    Completions

    Completions are supplied for functions, classes, and attributes of classes, both built-in and user-defined. Completions are also provided for filenames.

    @@ -480,7 +480,7 @@

    Completions -

    Calltips

    +

    Calltips

    A calltip is shown when one types ( after the name of an accessible function. A name expression may include dots and subscripts. A calltip remains until it is clicked, the cursor is moved out of the argument area, @@ -502,6 +502,21 @@

    Calltips +

    Code Context

    +

    Within an editor window containing Python code, code context can be toggled +in order to show or hide a pane at the top of the window. When shown, this +pane freezes the opening lines for block code, such as those beginning with +class, def, or if keywords, that would have otherwise scrolled +out of view. The size of the pane will be expanded and contracted as needed +to show the all current levels of context, up to the maximum number of +lines defined in the Configure IDLE dialog (which defaults to 15). If there +are no current context lines and the feature is toggled on, a single blank +line will display. Clicking on a line in the context pane will move that +line to the top of the editor.

    +

    The text and background colors for the context pane can be configured under +the Highlights tab in the Configure IDLE dialog.

    +

    Python Shell window

    With IDLE’s Shell, one enters, edits, and recalls complete statements. @@ -658,14 +673,31 @@

    User output in Shell -

    Text widgets display a subset of Unicode, the Basic Multilingual Plane (BMP). -Which characters get a proper glyph instead of a replacement box depends on -the operating system and installed fonts. Newline characters cause following -text to appear on a new line, but other control characters are either -replaced with a box or deleted. However, repr(), which is used for -interactive echo of expression values, replaces control characters, -some BMP codepoints, and all non-BMP characters with escape codes -before they are output.

    +

    A Tk Text widget, and hence IDLE’s Shell, displays characters (codepoints) +in the the BMP (Basic Multilingual Plane) subset of Unicode. +Which characters are displayed with a proper glyph and which with a +replacement box depends on the operating system and installed fonts. +Tab characters cause the following text to begin after +the next tab stop. (They occur every 8 ‘characters’). +Newline characters cause following text to appear on a new line. +Other control characters are ignored or displayed as a space, box, or +something else, depending on the operating system and font. +(Moving the text cursor through such output with arrow keys may exhibit +some surprising spacing behavior.)

    +
    >>> s = 'a\tb\a<\x02><\r>\bc\nd'
    +>>> len(s)
    +14
    +>>> s  # Display repr(s)
    +'a\tb\x07<\x02><\r>\x08c\nd'
    +>>> print(s, end='')  # Display s as is.
    +# Result varies by OS and font.  Try it.
    +
    +
    +

    The repr function is used for interactive echo of expression +values. It returns an altered version of the input string in which +control codes, some BMP codepoints, and all non-BMP codepoints are +replaced with escape codes. As demonstrated above, it allows one to +identify the characters in a string, regardless of how they are displayed.

    Normal and error output are generally kept separate (on separate lines) from code input and each other. They each get different highlight colors.

    For SyntaxError tracebacks, the normal ‘^’ marking where the error was @@ -733,7 +765,7 @@

    Running without a subprocess

    Help and preferences

    -

    Help sources

    +

    Help sources

    Help menu entry “IDLE Help” displays a formatted html version of the IDLE chapter of the Library Reference. The result, in a read-only tkinter text window, is close to what one sees in a web browser. @@ -750,11 +782,22 @@

    Help sources -

    Setting preferences

    +

    Setting preferences

    The font preferences, highlighting, keys, and general preferences can be -changed via Configure IDLE on the Option menu. Keys can be user defined; -IDLE ships with four built-in key sets. In addition, a user can create a -custom key set in the Configure IDLE dialog under the keys tab.

    +changed via Configure IDLE on the Option menu. +Non-default user settings are saved in a .idlerc directory in the user’s +home directory. Problems caused by bad user configuration files are solved +by editing or deleting one or more of the files in .idlerc.

    +

    On the Font tab, see the text sample for the effect of font face and size +on multiple characters in multiple languages. Edit the sample to add +other characters of personal interest. Use the sample to select +monospaced fonts. If particular characters have problems in Shell or an +editor, add them to the top of the sample and try changing first size +and then font.

    +

    On the Highlights and Keys tab, select a built-in or custom color theme +and key set. To use a newer built-in color theme or key set with older +IDLEs, save it as a new custom theme or key set and it well be accessible +to older IDLEs.

    IDLE on macOS

    @@ -801,6 +844,7 @@

    Table of Contents

  3. Automatic indentation
  4. Completions
  5. Calltips
  6. +
  7. Code Context
  8. Python Shell window
  9. Text colors
  10. @@ -868,7 +912,7 @@

    Navigation

  11. - 3.8.0a0 Documentation » + 3.8.0a1 Documentation »
  12. @@ -891,7 +935,7 @@

    Navigation