From ea63bec03952eb3990f95cb60e05cc28454d88e5 Mon Sep 17 00:00:00 2001 From: Hui Li Date: Tue, 29 Dec 2020 14:18:01 +0800 Subject: [PATCH] [TD-2103] taosdemo function enhancement --- deps/libcurl/include/curl/curl.h | 2415 +++++++++++ deps/libcurl/include/curl/curlbuild.h | 198 + deps/libcurl/include/curl/curlrules.h | 262 ++ deps/libcurl/include/curl/curlver.h | 77 + deps/libcurl/include/curl/easy.h | 102 + deps/libcurl/include/curl/mprintf.h | 74 + deps/libcurl/include/curl/multi.h | 435 ++ deps/libcurl/include/curl/stdcheaders.h | 33 + deps/libcurl/include/curl/typecheck-gcc.h | 622 +++ deps/libcurl/lib/libcurl.a | Bin 0 -> 734534 bytes src/kit/CMakeLists.txt | 1 + src/kit/taosdemox/CMakeLists.txt | 25 + src/kit/taosdemox/insert.json | 53 + src/kit/taosdemox/query.json | 17 + src/kit/taosdemox/subscribe.json | 17 + src/kit/taosdemox/taosdemox.c | 4621 +++++++++++++++++++++ 16 files changed, 8952 insertions(+) create mode 100644 deps/libcurl/include/curl/curl.h create mode 100644 deps/libcurl/include/curl/curlbuild.h create mode 100644 deps/libcurl/include/curl/curlrules.h create mode 100644 deps/libcurl/include/curl/curlver.h create mode 100644 deps/libcurl/include/curl/easy.h create mode 100644 deps/libcurl/include/curl/mprintf.h create mode 100644 deps/libcurl/include/curl/multi.h create mode 100644 deps/libcurl/include/curl/stdcheaders.h create mode 100644 deps/libcurl/include/curl/typecheck-gcc.h create mode 100644 deps/libcurl/lib/libcurl.a create mode 100644 src/kit/taosdemox/CMakeLists.txt create mode 100644 src/kit/taosdemox/insert.json create mode 100644 src/kit/taosdemox/query.json create mode 100644 src/kit/taosdemox/subscribe.json create mode 100644 src/kit/taosdemox/taosdemox.c diff --git a/deps/libcurl/include/curl/curl.h b/deps/libcurl/include/curl/curl.h new file mode 100644 index 0000000000..84229bb698 --- /dev/null +++ b/deps/libcurl/include/curl/curl.h @@ -0,0 +1,2415 @@ +#ifndef __CURL_CURL_H +#define __CURL_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * http://curl.haxx.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * http://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#include "curlver.h" /* libcurl version defines */ +#include "curlbuild.h" /* libcurl build definitions */ +#include "curlrules.h" /* libcurl rules enforcement */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && \ + !defined(WIN32) && !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void CURL; + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist* contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + +/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered + deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in + 7.32.0, it avoids floating point and provides more detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + + + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Content of this structure depends on information which is known and is + achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man + page for callbacks returning this structure -- some fields are mandatory, + some others are optional. The FLAG field has special meaning. */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char * b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an + OpenSSL SSL_CTX */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS +}; + +struct curl_khkey { + const char *key; /* points to a zero-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_STRINGPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + +/* name is uppercase CURLOPT_, + type is one of the defined CURLOPTTYPE_ + number is unique identifier */ +#ifdef CINIT +#undef CINIT +#endif + +#ifdef CURL_ISOCPP +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define STRINGPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif + +/* + * This macro-mania below setups the CURLOPT_[what] enum, to be used with + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] + * word. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(WRITEDATA, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. */ + CINIT(PROXY, STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CINIT(USERPWD, STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CINIT(PROXYUSERPWD, STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CINIT(RANGE, STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(READDATA, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. If this is not used, error messages go to stderr instead: */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CINIT(INFILESIZE, LONG, 14), + + /* POST static input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CINIT(REFERER, STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG, 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CINIT(HTTPHEADER, OBJECTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CINIT(KEYPASSWD, STRINGPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, OBJECTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(HEADERDATA, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, OBJECTPOINT, 39), + + CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */ + + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */ + + CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* HTTP PUT */ + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA + + /* We want the referrer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CINIT(KRBLEVEL, STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CINIT(FILETIME, LONG, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, OBJECTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */ + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */ + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CINIT(PREQUOTE, OBJECTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CINIT(ACCEPT_ENCODING, STRINGPOINT, 102), + + /* Set pointer to private data */ + CINIT(PRIVATE, OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CINIT(HTTP200ALIASES, OBJECTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CINIT(UNRESTRICTED_AUTH, LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CINIT(FTP_USE_EPRT, LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(HTTPAUTH, LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx + in second argument. The function must be matching the + curl_ssl_ctx_callback proto. */ + CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(PROXYAUTH, LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CINIT(IPRESOLVE, LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CINIT(MAXFILESIZE, LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CINIT(INFILESIZE_LARGE, OFF_T, 115), + + /* Sets the continuation offset. There is also a LONG version of this; + * look above for RESUME_FROM. + */ + CINIT(RESUME_FROM_LARGE, OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CINIT(MAXFILESIZE_LARGE, OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CINIT(NETRC_FILE, STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CINIT(USE_SSL, LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CINIT(TCP_NODELAY, LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CINIT(FTPSSLAUTH, LONG, 129), + + CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), + CINIT(IOCTLDATA, OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CINIT(FTP_ACCOUNT, STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CINIT(COOKIELIST, STRINGPOINT, 135), + + /* ignore Content-Length */ + CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CINIT(FTP_SKIP_PASV_IP, LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CINIT(FTP_FILEMETHOD, LONG, 138), + + /* Local port number to bind the socket to */ + CINIT(LOCALPORT, LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CINIT(LOCALPORTRANGE, LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CINIT(CONNECT_ONLY, LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), + CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147), + + /* callback function for setting socket options */ + CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), + CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + + /* allowed SSH authentication methods */ + CINIT(SSH_AUTH_TYPES, LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152), + CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CINIT(FTP_SSL_CCC, LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CINIT(TIMEOUT_MS, LONG, 155), + CINIT(CONNECTTIMEOUT_MS, LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CINIT(HTTP_TRANSFER_DECODING, LONG, 157), + CINIT(HTTP_CONTENT_DECODING, LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CINIT(NEW_FILE_PERMS, LONG, 159), + CINIT(NEW_DIRECTORY_PERMS, LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CINIT(POSTREDIR, LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), + CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CINIT(PROXY_TRANSFER_MODE, LONG, 166), + + /* Callback function for seeking in the input stream */ + CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), + CINIT(SEEKDATA, OBJECTPOINT, 168), + + /* CRL file */ + CINIT(CRLFILE, STRINGPOINT, 169), + + /* Issuer certificate */ + CINIT(ISSUERCERT, STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CINIT(ADDRESS_SCOPE, LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CINIT(CERTINFO, LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CINIT(USERNAME, STRINGPOINT, 173), + CINIT(PASSWORD, STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CINIT(PROXYUSERNAME, STRINGPOINT, 175), + CINIT(PROXYPASSWORD, STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CINIT(NOPROXY, STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CINIT(TFTP_BLKSIZE, LONG, 178), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + + /* set the SSH knownhost file name to use */ + CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CINIT(SSH_KEYDATA, OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CINIT(MAIL_FROM, STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CINIT(MAIL_RCPT, OBJECTPOINT, 187), + + /* FTP: send PRET before PASV */ + CINIT(FTP_USE_PRET, LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CINIT(RTSP_REQUEST, LONG, 189), + + /* The RTSP session identifier */ + CINIT(RTSP_SESSION_ID, STRINGPOINT, 190), + + /* The RTSP stream URI */ + CINIT(RTSP_STREAM_URI, STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CINIT(RTSP_TRANSPORT, STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CINIT(RTSP_CLIENT_CSEQ, LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CINIT(RTSP_SERVER_CSEQ, LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CINIT(WILDCARDMATCH, LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CINIT(CHUNK_DATA, OBJECTPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CINIT(FNMATCH_DATA, OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CINIT(RESOLVE, OBJECTPOINT, 203), + + /* Set a username for authenticated TLS */ + CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CINIT(TLSAUTH_TYPE, STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CINIT(TRANSFER_ENCODING, LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CINIT(GSSAPI_DELEGATION, LONG, 210), + + /* Set the name servers to use for DNS resolution */ + CINIT(DNS_SERVERS, STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of miliseconds. */ + CINIT(ACCEPTTIMEOUT_MS, LONG, 212), + + /* Set TCP keepalive */ + CINIT(TCP_KEEPALIVE, LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CINIT(TCP_KEEPIDLE, LONG, 214), + CINIT(TCP_KEEPINTVL, LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CINIT(SSL_OPTIONS, LONG, 216), + + /* Set the SMTP auth originator */ + CINIT(MAIL_AUTH, STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CINIT(SASL_IR, LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CINIT(XOAUTH2_BEARER, STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_INTERFACE, STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223), + + /* Set authentication options directly */ + CINIT(LOGIN_OPTIONS, STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_NPN, LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_ALPN, LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CINIT(PROXYHEADER, OBJECTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CINIT(HEADEROPT, LONG, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CINIT(SSL_VERIFYSTATUS, LONG, 232), + + /* Set if we should enable TLS false start. */ + CINIT(SSL_FALSESTART, LONG, 233), + + /* Do not squash dot-dot sequences */ + CINIT(PATH_AS_IS, LONG, 234), + + /* Proxy Service Name */ + CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235), + + /* Service Name */ + CINIT(SERVICE_NAME, STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CINIT(PIPEWAIT, LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CINIT(STREAM_WEIGHT, LONG, 239), + + /* Set stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS, OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + libcurl, see lib/README.curlx for details */ +CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2); +CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n); + +/* name is uppercase CURLFORM_ */ +#ifdef CFINIT +#undef CFINIT +#endif + +#ifdef CURL_ISOCPP +#define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif + +typedef enum { + CFINIT(NOTHING), /********* the first one is unused ************/ + + /* */ + CFINIT(COPYNAME), + CFINIT(PTRNAME), + CFINIT(NAMELENGTH), + CFINIT(COPYCONTENTS), + CFINIT(PTRCONTENTS), + CFINIT(CONTENTSLENGTH), + CFINIT(FILECONTENT), + CFINIT(ARRAY), + CFINIT(OBSOLETE), + CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + + CFINIT(CONTENTTYPE), + CFINIT(CONTENTHEADER), + CFINIT(FILENAME), + CFINIT(END), + CFINIT(OBSOLETE2), + + CFINIT(STREAM), + CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +#undef CFINIT /* done */ + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines with be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL builds. Asked + for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_CYASSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_DARWINSSL = 9, + CURLSSLBACKEND_AXTLS = 10, + CURLSSLBACKEND_MBEDTLS = 11 +} curl_sslbackend; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_SLIST + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + /* Fill in new entries below here! */ + + CURLINFO_LASTONE = 44 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + +typedef void CURLSH; + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_FOURTH + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is suported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* __CURL_CURL_H */ diff --git a/deps/libcurl/include/curl/curlbuild.h b/deps/libcurl/include/curl/curlbuild.h new file mode 100644 index 0000000000..bdca52b535 --- /dev/null +++ b/deps/libcurl/include/curl/curlbuild.h @@ -0,0 +1,198 @@ +/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ +#ifndef __CURL_CURLBUILD_H +#define __CURL_CURLBUILD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the libcurl development + * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * This header file shall only export symbols which are 'curl' or 'CURL' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * Right now you might be staring at file include/curl/curlbuild.h.in or + * at file include/curl/curlbuild.h, this is due to the following reason: + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed include/curl/curlbuild.h file with one that + * is suitable and specific to the library being configured and built, which + * is generated from the include/curl/curlbuild.h.in template file. + * + */ + +/* ================================================================ */ +/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +/* ================================================================ */ + +#ifdef CURL_SIZEOF_LONG +#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_OFF_T +#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_T +#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_TU +#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +#endif + +#ifdef CURL_FORMAT_OFF_T +#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_OFF_T +#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_T +#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_TU +#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +#endif + +/* ================================================================ */ +/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ +/* ================================================================ */ + +/* Configure process defines this to 1 when it finds out that system */ +/* header file ws2tcpip.h must be included by the external interface. */ +/* #undef CURL_PULL_WS2TCPIP_H */ +#ifdef CURL_PULL_WS2TCPIP_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# include +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/types.h must be included by the external interface. */ +#define CURL_PULL_SYS_TYPES_H 1 +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file stdint.h must be included by the external interface. */ +/* #undef CURL_PULL_STDINT_H */ +#ifdef CURL_PULL_STDINT_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file inttypes.h must be included by the external interface. */ +/* #undef CURL_PULL_INTTYPES_H */ +#ifdef CURL_PULL_INTTYPES_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/socket.h must be included by the external interface. */ +#define CURL_PULL_SYS_SOCKET_H 1 +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/poll.h must be included by the external interface. */ +/* #undef CURL_PULL_SYS_POLL_H */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* The size of `long', as computed by sizeof. */ +#define CURL_SIZEOF_LONG 8 + +/* Integral data type used for curl_socklen_t. */ +#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t + +/* The size of `curl_socklen_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +/* Data type definition of curl_socklen_t. */ +typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; + +/* Signed integral data type used for curl_off_t. */ +#define CURL_TYPEOF_CURL_OFF_T long + +/* Data type definition of curl_off_t. */ +typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; + +/* curl_off_t formatting string directive without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_T "ld" + +/* unsigned curl_off_t formatting string without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_TU "lu" + +/* curl_off_t formatting string directive with "%" conversion specifier. */ +#define CURL_FORMAT_OFF_T "%ld" + +/* The size of `curl_off_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_OFF_T 8 + +/* curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_T L + +/* unsigned curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_TU UL + +#endif /* __CURL_CURLBUILD_H */ diff --git a/deps/libcurl/include/curl/curlrules.h b/deps/libcurl/include/curl/curlrules.h new file mode 100644 index 0000000000..7c2ede35b6 --- /dev/null +++ b/deps/libcurl/include/curl/curlrules.h @@ -0,0 +1,262 @@ +#ifndef __CURL_CURLRULES_H +#define __CURL_CURLRULES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* COMPILE TIME SANITY CHECKS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * All checks done in this file are intentionally placed in a public + * header file which is pulled by curl/curl.h when an application is + * being built using an already built libcurl library. Additionally + * this file is also included and used when building the library. + * + * If compilation fails on this file it is certainly sure that the + * problem is elsewhere. It could be a problem in the curlbuild.h + * header file, or simply that you are using different compilation + * settings than those used to build the library. + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * Do not deactivate any check, these are done to make sure that the + * library is properly built and used. + * + * You can find further help on the libcurl development mailing list: + * http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * NOTE 2 + * ------ + * + * Some of the following compile time checks are based on the fact + * that the dimension of a constant array can not be a negative one. + * In this way if the compile time verification fails, the compilation + * will fail issuing an error. The error description wording is compiler + * dependent but it will be quite similar to one of the following: + * + * "negative subscript or subscript is too large" + * "array must have at least one element" + * "-1 is an illegal array size" + * "size of array is negative" + * + * If you are building an application which tries to use an already + * built libcurl library and you are getting this kind of errors on + * this file, it is a clear indication that there is a mismatch between + * how the library was built and how you are trying to use it for your + * application. Your already compiled or binary library provider is the + * only one who can give you the details you need to properly use it. + */ + +/* + * Verify that some macros are actually defined. + */ + +#ifndef CURL_SIZEOF_LONG +# error "CURL_SIZEOF_LONG definition is missing!" + Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing +#endif + +#ifndef CURL_TYPEOF_CURL_SOCKLEN_T +# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing +#endif + +#ifndef CURL_SIZEOF_CURL_SOCKLEN_T +# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing +#endif + +#ifndef CURL_TYPEOF_CURL_OFF_T +# error "CURL_TYPEOF_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_FORMAT_CURL_OFF_T +# error "CURL_FORMAT_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_FORMAT_CURL_OFF_TU +# error "CURL_FORMAT_CURL_OFF_TU definition is missing!" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing +#endif + +#ifndef CURL_FORMAT_OFF_T +# error "CURL_FORMAT_OFF_T definition is missing!" + Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing +#endif + +#ifndef CURL_SIZEOF_CURL_OFF_T +# error "CURL_SIZEOF_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_SUFFIX_CURL_OFF_T +# error "CURL_SUFFIX_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_SUFFIX_CURL_OFF_TU +# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing +#endif + +/* + * Macros private to this header file. + */ + +#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1 + +#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1 + +/* + * Verify that the size previously defined and expected for long + * is the same as the one reported by sizeof() at compile time. + */ + +typedef char + __curl_rule_01__ + [CurlchkszEQ(long, CURL_SIZEOF_LONG)]; + +/* + * Verify that the size previously defined and expected for + * curl_off_t is actually the the same as the one reported + * by sizeof() at compile time. + */ + +typedef char + __curl_rule_02__ + [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)]; + +/* + * Verify at compile time that the size of curl_off_t as reported + * by sizeof() is greater or equal than the one reported for long + * for the current compilation. + */ + +typedef char + __curl_rule_03__ + [CurlchkszGE(curl_off_t, long)]; + +/* + * Verify that the size previously defined and expected for + * curl_socklen_t is actually the the same as the one reported + * by sizeof() at compile time. + */ + +typedef char + __curl_rule_04__ + [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)]; + +/* + * Verify at compile time that the size of curl_socklen_t as reported + * by sizeof() is greater or equal than the one reported for int for + * the current compilation. + */ + +typedef char + __curl_rule_05__ + [CurlchkszGE(curl_socklen_t, int)]; + +/* ================================================================ */ +/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */ +/* ================================================================ */ + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define __CURL_OFF_T_C_HLPR2(x) x +# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +/* + * Get rid of macros private to this header file. + */ + +#undef CurlchkszEQ +#undef CurlchkszGE + +/* + * Get rid of macros not intended to exist beyond this point. + */ + +#undef CURL_PULL_WS2TCPIP_H +#undef CURL_PULL_SYS_TYPES_H +#undef CURL_PULL_SYS_SOCKET_H +#undef CURL_PULL_SYS_POLL_H +#undef CURL_PULL_STDINT_H +#undef CURL_PULL_INTTYPES_H + +#undef CURL_TYPEOF_CURL_SOCKLEN_T +#undef CURL_TYPEOF_CURL_OFF_T + +#ifdef CURL_NO_OLDIES +#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */ +#endif + +#endif /* __CURL_CURLRULES_H */ diff --git a/deps/libcurl/include/curl/curlver.h b/deps/libcurl/include/curl/curlver.h new file mode 100644 index 0000000000..17906764c8 --- /dev/null +++ b/deps/libcurl/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef __CURL_CURLVER_H +#define __CURL_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2015 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.47.0" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 47 +#define LIBCURL_VERSION_PATCH 0 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparions by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x072f00 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date should follow this template: + * + * "Mon Feb 12 11:35:33 UTC 2007" + */ +#define LIBCURL_TIMESTAMP "Wed Jan 27 07:32:44 UTC 2016" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* __CURL_CURLVER_H */ diff --git a/deps/libcurl/include/curl/easy.h b/deps/libcurl/include/curl/easy.h new file mode 100644 index 0000000000..c1e3e76096 --- /dev/null +++ b/deps/libcurl/include/curl/easy.h @@ -0,0 +1,102 @@ +#ifndef __CURL_EASY_H +#define __CURL_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/libcurl/include/curl/mprintf.h b/deps/libcurl/include/curl/mprintf.h new file mode 100644 index 0000000000..c6b0d7679a --- /dev/null +++ b/deps/libcurl/include/curl/mprintf.h @@ -0,0 +1,74 @@ +#ifndef __CURL_MPRINTF_H +#define __CURL_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef _MPRINTF_REPLACE +# undef printf +# undef fprintf +# undef sprintf +# undef vsprintf +# undef snprintf +# undef vprintf +# undef vfprintf +# undef vsnprintf +# undef aprintf +# undef vaprintf +# define printf curl_mprintf +# define fprintf curl_mfprintf +# define sprintf curl_msprintf +# define vsprintf curl_mvsprintf +# define snprintf curl_msnprintf +# define vprintf curl_mvprintf +# define vfprintf curl_mvfprintf +# define vsnprintf curl_mvsnprintf +# define aprintf curl_maprintf +# define vaprintf curl_mvaprintf +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __CURL_MPRINTF_H */ diff --git a/deps/libcurl/include/curl/multi.h b/deps/libcurl/include/curl/multi.h new file mode 100644 index 0000000000..36e2e940ec --- /dev/null +++ b/deps/libcurl/include/curl/multi.h @@ -0,0 +1,435 @@ +#ifndef __CURL_MULTI_H +#define __CURL_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void CURLM; + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on invidual transfers even when this + * returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic informations. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a zero-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +#undef CINIT /* re-using the same name as in curl.h */ + +#ifdef CURL_ISOCPP +#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLMOPT_/**/name = type + number +#endif + +typedef enum { + /* This is the socket callback function pointer */ + CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CINIT(SOCKETDATA, OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CINIT(PIPELINING, LONG, 3), + + /* This is the timer callback function pointer */ + CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CINIT(TIMERDATA, OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CINIT(MAXCONNECTS, LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CINIT(MAX_HOST_CONNECTIONS, LONG, 7), + + /* maximum number of requests in a pipeline */ + CINIT(MAX_PIPELINE_LENGTH, LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10), + + /* a list of site names(+port) that are blacklisted from + pipelining */ + CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11), + + /* a list of server types that are blacklisted from + pipelining */ + CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13), + + /* This is the server push callback function pointer */ + CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CINIT(PUSHDATA, OBJECTPOINT, 15), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. + * + * Returns: CURL_PUSH_OK or CURL_PUSH_DENY. + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/deps/libcurl/include/curl/stdcheaders.h b/deps/libcurl/include/curl/stdcheaders.h new file mode 100644 index 0000000000..ad82ef6335 --- /dev/null +++ b/deps/libcurl/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef __STDC_HEADERS_H +#define __STDC_HEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread (void *, size_t, size_t, FILE *); +size_t fwrite (const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* __STDC_HEADERS_H */ diff --git a/deps/libcurl/include/curl/typecheck-gcc.h b/deps/libcurl/include/curl/typecheck-gcc.h new file mode 100644 index 0000000000..2e24db0ff5 --- /dev/null +++ b/deps/libcurl/include/curl/typecheck-gcc.h @@ -0,0 +1,622 @@ +#ifndef __CURL_TYPECHECK_GCC_H +#define __CURL_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(_curl_is_sometype_option(_curl_opt)) + * if(!_curl_is_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define _curl_is_sometype_option, _curl_is_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ +__extension__ ({ \ + __typeof__ (option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(_curl_is_long_option(_curl_opt)) \ + if(!_curl_is_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(_curl_is_off_t_option(_curl_opt)) \ + if(!_curl_is_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(_curl_is_string_option(_curl_opt)) \ + if(!_curl_is_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(_curl_is_write_cb_option(_curl_opt)) \ + if(!_curl_is_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!_curl_is_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!_curl_is_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!_curl_is_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!_curl_is_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!_curl_is_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!_curl_is_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!_curl_is_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(_curl_is_conv_cb_option(_curl_opt)) \ + if(!_curl_is_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!_curl_is_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(_curl_is_cb_data_option(_curl_opt)) \ + if(!_curl_is_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!_curl_is_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!_curl_is_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(_curl_is_postfields_option(_curl_opt)) \ + if(!_curl_is_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!_curl_is_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if(_curl_is_slist_option(_curl_opt)) \ + if(!_curl_is_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!_curl_is_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ +}) + +/* wraps curl_easy_getinfo() with typechecking */ +/* FIXME: don't allow const pointers */ +#define curl_easy_getinfo(handle, info, arg) \ +__extension__ ({ \ + __typeof__ (info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(_curl_is_string_info(_curl_info)) \ + if(!_curl_is_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(_curl_is_long_info(_curl_info)) \ + if(!_curl_is_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(_curl_is_double_info(_curl_info)) \ + if(!_curl_is_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(_curl_is_slist_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ +}) + +/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(), + * for now just make sure that the functions are called with three + * arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define _CURL_WARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +_CURL_WARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string (char* or char[]) argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a FILE* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a void* or char* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a struct curl_httppost* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a struct curl_slist* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +_CURL_WARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to char * for this info") +_CURL_WARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +_CURL_WARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to struct curl_slist * for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define _curl_is_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define _curl_is_off_t_option(option) \ + ((option) > CURLOPTTYPE_OFF_T) + +/* evaluates to true if option takes a char* argument */ +#define _curl_is_string_option(option) \ + ((option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define _curl_is_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define _curl_is_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define _curl_is_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PRIVATE || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define _curl_is_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define _curl_is_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define _curl_is_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) + +/* evaluates to true if info expects a pointer to long argument */ +#define _curl_is_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define _curl_is_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define _curl_is_slist_info(info) \ + (CURLINFO_SLIST < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true iff expr is a pointer */ +#define _curl_is_any_ptr(expr) \ + (sizeof(expr) == sizeof(void*)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define _curl_is_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define _curl_is_ptr(expr, type) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define _curl_is_arr(expr, type) \ + (_curl_is_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define _curl_is_string(expr) \ + (_curl_is_arr((expr), char) || \ + _curl_is_arr((expr), signed char) || \ + _curl_is_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define _curl_is_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define _curl_is_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define _curl_is_error_buffer(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define _curl_is_cb_data(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_ptr((expr), FILE)) +#else /* be less strict */ +#define _curl_is_cb_data(expr) \ + _curl_is_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define _curl_is_FILE(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *)) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define _curl_is_postfields(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_arr((expr), char)) + +/* FIXME: the whole callback checking is messy... + * The idea is to tolerate char vs. void and const vs. not const + * pointers in arguments at least + */ +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define _curl_callback_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func), type*)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define _curl_is_read_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \ + _curl_callback_compatible((expr), _curl_read_callback1) || \ + _curl_callback_compatible((expr), _curl_read_callback2) || \ + _curl_callback_compatible((expr), _curl_read_callback3) || \ + _curl_callback_compatible((expr), _curl_read_callback4) || \ + _curl_callback_compatible((expr), _curl_read_callback5) || \ + _curl_callback_compatible((expr), _curl_read_callback6)) +typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*); +typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*); +typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*); +typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*); +typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*); +typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define _curl_is_write_cb(expr) \ + (_curl_is_read_cb(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \ + _curl_callback_compatible((expr), _curl_write_callback1) || \ + _curl_callback_compatible((expr), _curl_write_callback2) || \ + _curl_callback_compatible((expr), _curl_write_callback3) || \ + _curl_callback_compatible((expr), _curl_write_callback4) || \ + _curl_callback_compatible((expr), _curl_write_callback5) || \ + _curl_callback_compatible((expr), _curl_write_callback6)) +typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*); +typedef size_t (_curl_write_callback2)(const char *, size_t, size_t, + const void*); +typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*); +typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*); +typedef size_t (_curl_write_callback5)(const void *, size_t, size_t, + const void*); +typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define _curl_is_ioctl_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback1) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*); +typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*); +typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*); +typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define _curl_is_sockopt_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback1) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback2)) +typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define _curl_is_opensocket_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\ + _curl_callback_compatible((expr), _curl_opensocket_callback1) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback2) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback3) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define _curl_is_progress_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \ + _curl_callback_compatible((expr), _curl_progress_callback1) || \ + _curl_callback_compatible((expr), _curl_progress_callback2)) +typedef int (_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define _curl_is_debug_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \ + _curl_callback_compatible((expr), _curl_debug_callback1) || \ + _curl_callback_compatible((expr), _curl_debug_callback2) || \ + _curl_callback_compatible((expr), _curl_debug_callback3) || \ + _curl_callback_compatible((expr), _curl_debug_callback4) || \ + _curl_callback_compatible((expr), _curl_debug_callback5) || \ + _curl_callback_compatible((expr), _curl_debug_callback6) || \ + _curl_callback_compatible((expr), _curl_debug_callback7) || \ + _curl_callback_compatible((expr), _curl_debug_callback8)) +typedef int (_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define _curl_is_ssl_ctx_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define _curl_is_conv_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \ + _curl_callback_compatible((expr), _curl_conv_callback1) || \ + _curl_callback_compatible((expr), _curl_conv_callback2) || \ + _curl_callback_compatible((expr), _curl_conv_callback3) || \ + _curl_callback_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define _curl_is_seek_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \ + _curl_callback_compatible((expr), _curl_seek_callback1) || \ + _curl_callback_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* __CURL_TYPECHECK_GCC_H */ diff --git a/deps/libcurl/lib/libcurl.a b/deps/libcurl/lib/libcurl.a new file mode 100644 index 0000000000000000000000000000000000000000..c63ac70946dddefb5b3b5c55cf82d693b731cad6 GIT binary patch literal 734534 zcmdSC3t*g8nLqsI(l))22^XO%mjO~qfwoC$OUgwuG-=;~DMZ>r@>^KCYc)?v)ab^9p>aO?+-3nS$TH4|&mf|AHx>Qi;5Rl5HEhx?R`#tBJnKN%@ z1YLK(|96si-gAEEInTLY-{+ij`bEvXE$ttkGRL2*sx70^+rNH)?feDv6v?V7j#G4t zc4uam=&kILG;Gp3k4?IPdmsea>4ofb#y+Q%&zw)G=YnrIrFB2f|9tdnr}Vu%_rBzm z9y!&SQ1(srRBm%7{H0Iq5oZFQn-~0To_n8iCVc-P^^E+hGr@jFKjBQ^^Y#mwXX3Gs zJMa25-sDWo_gr_>nfP9x$hFSI|Ly11Z#omb&pWp}6ZJF6ce|7KIsXc0lKtGW&zWSN zJ1%f0+0Pd~?o6_u|EJBFWIrRna>~lK-_5**rgc!I}Kj8O~(11AL~O z|INSd`O2NnltRw~pK_-BrO(fva;7}HSUm^VIaA){nOgb<$MYynYN!E&Uq&MEJ!`c>(wX_SJB2olosLbHo)2V}~^i8pju5eFW z2Tfz~?#`Z;waQ7?+NRd-s4((++|n6t?p9!DPjf3n6lw10HQ`><8@(zV4ab(lhv>47 zn=%oC1u^9^0@Jcsb8qYlWS8WJAmLbj&w2!-xph%bygL@w5zuxkB86;>EBcqiPC3bi zS43KyV-{I`4-!)HvaP4L3(2N9(4gX)v1{uMYj8fyZ ztBDOAMv!Xl7S__!v$jL>T5-^3aO~`eYOWe%n0lK#J97vbviy`NQ95fZ_ucVGj`M6W z)kI8aR;yg6Ss&Uu!d{&7ExsFXs$fzr7AyQhpX^M0bPzKJG$F?bfDXsJ36(NQMH{a zuXA{{tg{JPIy=JMX#CoHB288hG;AT{tUWP-Z!=+E5{@li-iTHt($gK)`3y_T3G)R- zO~)b*D^r|0dyETaXj42I?rjaXb##YylzY%xD`#-i6EQ40qB*6qH{8{;F6>JGvbeXW ztFa@3>SanXYGqGbTNCPFQ$$;sva5=A7>ULLtUOv5?p=*g<#+(=SWin&XA^iuGp%lG zPe=EfTqr}Ror6Ge%~*&d50>K>6RW8=d}BO}ZYdhew0+*Xnysdibgey#X$~&~w)Ql2 z_4JxLsQcm84pRj?BI_13AxR^eqNA;;BZ?}97QL;xCEV2AY&wFDwz(a;$VMaKaBH?2 ziV=M%x+H0Uk&IDR3)=veZ9NJ>Lb4wg+i-JqLsJ;t7yMU%(l26%jYoI%Sz2_Z7Im&k z+5jQ#igru4ti}{gUF$sN=3LucV>HJy$IzBzT9-??F4xk~N>ohEiG@46O$|VMgNhQ4 z^|q+&V}eR5i3_As)_?}SlZ}CD0TnsTz2Ws8ritqcqk!gXm`G^XXB12fR&t7Sv@;xz zh}&#XnigGo#T5;UmMbLEi-0zFN6`Rl0R3Vv($>@2X~qb>rV^RrY{DGt-H;2ZvYp{1 z*%ytm5;S+JA^}skGD^ajj#+!d<$M zssW-5E5JqwrLbn*iBY#rS^Eeo4u%bui}5^6-ez4PsH%uq?l9OxQOVLon$bpDW~8xQ zi`eL@RBr3;YQ{KI8!$FtL1H6lQjOyU!LkEewAxKlAUSeq;%F(y!Fbzj!sj|=?e6V0 zx=qcxYhk~|j=)r7TaTtwJ21VNHgfE(0^BJH zY-NT5I?#Xi#+tgreK~Zhd$V1(qHpN!(E(I$TQ~x@Y1kzyb9*xef7zB=j2ORImWVEL z%mN}EW@;hSIsOTvhT4nRLTAlQ>pL*AYvF*WwAkV`@9&2;ou`Al+FhtG3om zT~omNW-}dBX69oHs^}W9lq#uVPO(h;pdhJO*#c_lP-=2q+6{-IVWG{;^um3S4)ofV zR~&ZgHbT-~IU;JB9D$X?rcR_Jik$5}8tqu4M^wsfS97190jt3f`fNQq%G$?zVwfkJ zTHql7jIKP^)EVwxgWSh}t+_L{p(&b~+bKS(9={8b&NmLLq8v4^*3%}%!nO_fVu0bb z@9k;9^oc>hz+{b1sHh!(Rh3K#ynHHBdw zMh9F2!8lm?i#8Z#9BV8XJ}UQN^iSPUOki0Kbb&?s3YZzV=F%c%QHnbv^YX(BRMx?( z?0UocwXLQb=t42qz3G}R)>6fVO+-_dnH09HZ9<=#Y3rne!0d{HVhMHxqa&ruj0Mp- z>hNHmrd#wVwW>3)>=3fmnT!__Rhn0CVA?1`3|%q5Ty*&|9e>g5 zeC=&s-xTYKM^FnC9|G2Ji$;6+h3xCjq31v#H;1e&YYO)%uI=Hu%^gbH5t*9}HP~6E zcy~viWsIu65@EyS7Cp0RXl-2aR0s$v`DQI=L}z_diH@$x1^48heX4dEgf@{ zF&$maI%5nH>4}`D98hP^mkmX_xA{y<&3S@@P>dGQb z>#V6Xsk3u&n3%z+Ejp|Kknn7dGOT3nCp#_#MXP7}42ZMC%<5QQ6FS(QxN11Hp+!p~1F^tHw~-#Enf9tTSXZo zDVuO&wA(fTti}xq#SvL{a%-}2O;4oVR0LTV@JxcRRA4$o<#V(-+KE(Uv&`hj7`j83 zCb3x^$7r`H8Zj#wq~=5gB|$qv`;1vfG}^pIH!I>Umqymf#uMdh?p1g&`)bYjP{4Ig zFJU{w%2vC>A6eD5qABwO&dO!6t_f>0nZ+-0pUnUjhvse}#0WuEO35m*LS5+9-IyXp z3)|6cRtjaT!U#zBY4lu`E;O^5RVd|#<8))$hQ%wX-z4MIPG~*6^~k8XWi6XF z<3+}6_JX-2UiW6~^k+GEh!hV7i5|&vrh?eAc%V#Bq~~LWuvQ+%Te1c71Q7#jBuYM4 z$|mciHQd@0!+%HH2G!n2u+pv9omX$bmzsQNW;u&|Y8GJVYNFTNdfwa|Bfc})wjf@e zOKclKY>X0ii?x_7-eR_xN7*LybhmY^X_9$+W+@+^y~0gdTNP00&b%O2W^_8zW;Jpb zS>rf!yaF4Ryhc9l+y(RI8hMS*j@8nMb~exAa>4ALIa4f%qaY02JgE9Q=KfacVxk9C%ZDCNmJmG{JmQGigPK(~56lrcm)krr$M_xyYvXZD z@x8DV6us)?abcF4yl@O7HGYo75@@f-&a4J`;I+N0=X)RydHG?)151Y|lTL5>LQG>l zYdz$;CHJ7RwBo_IDB*!**5kpzP^QK5@fovGkF`vSJeUMo_2(X&uGV?u5N|q&>+bLx zw1pU1c*yZF1jCY8Pqzn`w7}O9Z^>tA;7Xc@yt%7mO>>VoL0P#`OuW2Ro%aS@p$j~W ziH_$Wp~ghRTd$V+!(CDgYjOZBd=97I?h7)<-ujr<6&Z^Hy&76=*f=9inARL#7T|^;{3(~MNqWy z-OpRRdt*^ArT89eXP4_u()G=~-S~Lzh1)SD@^~jqdShK)=KM~WrvVmnG=nT&9Orwu zse!%+>}c)AI%fBIb3J%&{X&;KE{lXhCJY{@$d6gg(UuNxX0y`F!b*`h;)1KB@^DfS z%2#m2raRWzmCpt7ruC}}TD4%LThOvAy2cwo@r;A^e2%0wT)kmj?PMm%h|ueZtEwF7 zdvG&S^uTJo=K=fXS1)XicGq}d=7={RGhxq{h0(6Oi6rxry!BPMVVu>`>}~$U2J;k8 zkXTYNKJ%b!Vx3;Xb>ks8^ti)<5_->Z>Lo@VXmz_)c?{xv5ER>TV$#d?t2|cJ8KbE*q;z-CW`BUQ|YY?(P!4 z5@TcWX}cFyj6v0mT(@KR0MXG`+I*)CQ1>_I7q~jGBA7fBSiYiW-?CuxPl#oOn>x)M z3RRZ2x~b9`Rq)hJ)>oF*jJT=qt^5>C&xTUpVvHnk?%+u5Mz>{oWogYJH@VwQK5F2H z7^T<@Hx;TZYjw|?CcKh+;~SAe71!MmxIS=0;A1-wwR*>)+gHV5|HGdtMLGtPT@IeI zK(e7CHX(6jEOtU**TkZleWTy;omS^O^g-|*y?5A6-6dffnh!IBRx=`8YW8iL0U(ro z@xWt8$HpF_A>E5q72CGiCOre!Fa-k3gUL4}tKCg6*Gh)Yv0^_^Sp`gUMmPhzN-K-p zd;_OXgmd`zY3jz`Ux8;#T z^^1%A@d^EJ&x#)xOzbQQCBa*Bi$6=R8|n3nAtY$E1VKV7+*x)S-G!k_SNW6SU#;Tr zBFzH6&uw2ixX-tFGioN{=^MBWnx)C%2%n%sKq#51H?YGhdw0`LRs>T`15Ien>H(+D*)|6pkWwtZx-bV*7fAs{jol@F z1ae=8$1roG!MtOc{yv^P<>@%L(OkP$&EV6N3RLZJkn4z zhGv?6g_3XACl9LtF5K-K{1MZ;=ugP4Q1S(VtwbFBE^J*UnwyG|pK6{Y-J`@SwmEg6 z$Rs=R<2n}C!N+c0=&CXnYIzHJ%ocJWwD5>;s2jyEI24=U1ZVDccT1R%mQK0_xGJY$ zhticV!w~YEtV{=xPQ&hQltAI(`xAH!n_y;ACiw!$(({p6I{!jwLWbT)C)xn{~D&AMp+T1MH9{?WiZM@X2k7 zRjwKu?nE6K3XBat_Iq#>$GzK4P1_FI#zy>H&!6^2-D6%=57R~+j!5*12{Vx(a*rP%2J2NzM zuWp9j#0YwHX@b)m-?q{>l-%nce%e?qfmNo4rcS6F@5@O@%=8lRrJw2g(D?-RGtN@J zrPWLC&6wTYBW&~2&q%=Q@`U>XWbh_D7WcuzzCHn(Vd?sj$~$3@?1L10XKVLaF+T_C zey&>iXW-Lra|W6b^<#C?&&6BJd$kSbmwrfx`zi6@?`ab!YVl`QNMs@|@XzRMJ!Xm% zXlV&YVzaPLi!VhN_&G(20#^LJTx7k~SsV;CIHBffY}V2qY>(&&w}M&pT>p&fxvkLn zXUxM3`U^5Y{v}J7gDDjygTt-Z>UF;Iv6)!>9(8z|9ok zV$uZ4D{e0iluu8Tgv$LL<fd94t zey{+3v;ba#@{})q-d_Os7rdfFD-yCDS&^p03I)Z4;H|e6~ON(fPbR^zNG;E z;{y0^3g8C|;D0KBPePNJFTai}fS*$UuPuOo1o*MV+4iI#==6svP1fVg4lSzY&w2cr$DjH9IiEjs`LlpOHBQr#(3O`4LQPjLUc9Vf zdDHU1rJ;r<_4T-=#gaT$!t)}~tUi^CR9|LK1wI#0G>QWv{pne@8#Pgq3DRyY?Q5Gj z%+P{5YCq>9N{3JmBrC6%vw^UwsjZKKP>y_k>U5f#T4Ea@RIs`U3zbf1G#ob4OJ);d z_Iv;Mtx4~;6H)IUgkKpMufiJ?vtM_0Z1e27$Z;)u6=kV6yWK?MpCcrgSB%gT@C>KE zCN1wIdT$Ohk}arWR`f-^YVYbr1O6AG3d z-=;qm^^J;rIPNlhI8mh{ehMCgcUw5e1P1@6#!-zNpM^hQ(Vu4F`z+jV;pJoiMSoAn zWBAXo@G~rYmW7{b;q4Y)Y2mM1_zVj_r33~j`uia~#^0MQ+@}8k38DBp3y-0{*utwU zyw$>IS~wTJsQ6-@89v{z@N+EuUoHGx3*TJ;KSvL3Xg$lKKhMJLbiUQX?fm_@g>%ej z!Z~W;T#qvN>lSW@^B6ruVtA@8`WY5pW8r-kZu9x9h1=!%0SljN@p)R~%zpMGCY&!? z^ygXlTNZBT%M{&3kk7Fe{rfe}c-i#xEqtCu-=T5Ra>?9;XVAhISomi(PJeO4N{0R) zE&g`+w_3Ozp2sYlQ+DI;iv{pwIU#^zyejb+`g#lJ*w)}5vv50q_gVNti~fUp=*oB< zZ{agEPJiuoW1WTD`M$~G!?x6fCuPywe4e!Exd>Vm?WR20ZJ#2;7kjn%$SGt#P?GJHC??j^uyX*<-zxB^C}Nsr_Fx-CU4tc z*Mrw-bE^k8{`PzD{o1_Ki|g<^v!ffjAfJjiM0(`iZgjoaz%@I@ja0Kmu6g!q?5m&M z+arQyAgY;NlWVMnk#2+lI?&FR9Rtp6>{XJ@N3*+o@KJlo6)R@R;72P!*Qljv` zt^DA?sOe@S!>>;3PS@qZSeSe@W|n1^p*jQTw_jF>u>`N%({kYS$CMXS4nCxD-Cb$d zj??V%*I1ZrFlM%`dcn-5=56zt-d4#NW7IuHAdX zze-Q}`#tXc9`ltj=S%-GW(<@m=S+V#mBxRQ{%e3SEY)~ywO{*xwhcmW!foCW3$sb5 zOtVc{y>VxdL1>8Cb(nS)+P&Z7z=WSPRQ-7J#s6*{|2`5yG5(B_ac|eE$KC$cCGO#u-0g2qa%cWneGyM>tgOP<#Eax>zncOb zzoErX#7F;H{S7hsqW(BK`osYS$9#*N`M5jt7q%w{-R(!kgO0HSNM+^EYwl3#NtCT< z^SwIa!p*{8yyp7O-u0UAV-nF=1-QWOF`_?v&9`#<>&D+BJLnx%|G@0P-)ilc5SGPb<{Ggy#ei`BR7A~h$=d5q!Us}Nu3Km508Amn;>UU2YHxL$F zEqMag+)2gq#OBzH1#cw?MV!r?!3POK5oddA@FxjEu_ z+@x!x2OrVqRu68{^{*bQwM1hWn*DDL!5lxr&r<6x(RIM6-cYa1Z$(C@GzG_C%m}De z@~iqk`s3|`3XQ?I7MxFc;d3=lw6Hnqy}CDJFx};4cu;Y}>-E3T7-m=(2-6OeCzaR#IrD0=0~qMuZ45K- zyz>_PrDK=~8!D~pGa-eBvc{=%!K#eGZO5zR5ShZwc<; zD-`Z3^9^nTGsxehuBX6|bb2*ofnAdz5_NJV1x1x~RxsHBp%oW{r0JPKl5dbXgz-^T zj!4rL3Hd42|@_j?|hG5|&kBp>CM-EI(yl~OvUCF&8FBNa!U+UYkFR{OR@}5BA zt)c)zbs_>fg5Z@-jMW2!HK-?jOG}y9zS7|Y_V5BH&7T?e3PIz}+pC(oI5oOeJ=5WGlaGQ}S@&YIq(vG*aRl z3{mIXGKnHMe}Mj?i;>27*Blxx8y?sfJI+PZzYM8m2`TCNVh zQ}{H!QROSVa+45+6aP55sR(RdT_?iyE6LJv{?&}6 zr!t($w~=YZf&Pmwxmcyw;N>VgXh({-vUH>`hUubyX>bYQ0&X8 z7+*8KG?-Wv_+g#>|6=aQafdD6BY6OfbCe>CoLAvZ6;Lnv7Dn7CgVUUE?x^rGL!R@_ zC#RyuniIxJ^6;C81NkAY_t@$JF-YCFVbSN42f73{-f=#OR}{cG2F*v`Q2>t>z!L@V z&jIJ0wV&k^O3EqT{|8S#e;)uYb6h&eu7=L=7=M(z48MAx~&pr5=PBN#H*!F++6llb`0S^_E z!~XuZMo{(bjq@KfH@@4#?e9z9*0`6?QH$Q@a~3Ns6tj(KZTMfPaq>CA!Vg*W_S}A= z&UY{U2Q|)@J?B5W0R7Dt&QAm;Joj0+ojxCAKMut?oE@*rHBM)of3W;hJ)v=i^CUcm zKeq!=dGTus;8Bg!UpxI@*SOc;5?!?oZv6GrQz+tmjM}I*1~>KUw;ueU_V0)XH}&VQ zUgOC99`(Pr+Tlk$Sj4g|vx-=qdO6cPO{BMNDYVvcA3F%BBf9*utW#@R^y##O`Vb!C zx|k3W74rCNaLvvbopYfh&%f5aS?ida;ixpme-ln)ZTvUyI#^I|mnG8n>+pY#221%Z zJ+&?#y050eQm5+-VR^Te@z=aR0!yQ}=`QzXsJ8UdwrTg?@HcArWgZ76|BPSF(6CC> z89=}9VTMDkl3&%d?cTgR!O5HUq+K~lxrpe9ksZsf*MEj7 zpZ|Mk0rhM3%KUo$pR+)3P1P$V@3vM_Q*-`YMe`SY@39I&orFZKmAI*^xr=jfAHI;J zmXx_O_qrEO^8LezZ_5b3kYKNC@-@sg^^^jXn06nadn|ZhF(g*&+cLfXj~B$M2cC(Y zt1OZ)jh1Kj%FylvH&x~)9w|yq`_ksiu%hsRfoI|`Vw!}Vk_Xg|*z8&cn&4xF+OX z1v)U9b2LuJw=$aCy}CoZ3#M*qbcfop$@9P5MJ_w%6KH%Q60G_rhcL`@pf6aglT%qYvvf8%2rYjeTpm#IhC_O3i}* zOsl}y3cOzBYxG;7AN>Z)qwMWY{vy*1V4pjehZ8Sj<>)lMJe*Tp*g6(UeZ&i?|28(< z9=I24FFN&?>v~!<5@Oq_)_C1SgU%7(;9dl<1`Wr#l~TPkErf4yKZBmwIo(=1GHaK4 zG7}AfBqbLKzf70hpbt<72?$&1AX@1Ssw^CrEj=b&^-1hTeT^GZGXa&N_Nb@)vYx); z8(hLADDCZ5=&_3wKPX2zg*|;LK$Typ8Kv0j`lKS}QmX_xQ{R_ibA3OG439)mi}OhR zla-u6^2?Qdu&Q|mi=(^hE6+oAZsg`otes-lD`X8ql~vg4I!_`h3+|iup!!N}?BDur z4k>(tU&k*uXV((0m152LtukHwBKmFLou8#EwP=>@bXWntB9v&MGgz5 za!QfxFnPlT*BX_NChrF7fw5_?(+MR`OfH`XOBEdEfs3I->eG7=TsQT_5x$J?*}!f; zPy*6^^DPsunWSHT-ZhUyh z^}D)_QSH_T@&wn^8x^i>dLTR~RS+K<;7hgl=u@Rb4AE>MX&NdF8 zKmHlccx=GQp`iyVS-L|*t(AT^Sz0-I$uKsfn;pnCBTJJ9L&@hPf$@pRH}D<0OdUUN zhq9Zxt_-YWSGlPRnEqERml$D%on^bqo(NcV8UH*h5IS6&IvcZ)W&l9Lgj@k!<1{Xp=BIB!N`0=!{8%b zY59xbA^$>{Dw&KzJzIzYQ5o~bO|(}Or7KaPO}WieOwvD>y56rGjQ86lkNO(qgXc;& z0Xj)HI`pU+(Fm4I->hO7nMgXKnrK zo1=cnJa>lA_21Ntlek;Q(}N+Y+Heg;YmQ?@n%P<}XZQIRt+*<5W#jUus~VPF8M?Xw z8`NXLwC>Cwcy5pP*ztmRaNd z22}y_xvCyVTX% z#b#~Cbyq5mIXHHtdXqo+1~$a~<9C$Qm-}z$9`wY7V0mNljZX}pa}YuGb^b^kC_wqe zDYD}}FxBCpZ@H%FB2B(X=Z=? zqN%Gq2xK{3@c2*7?~{DL+c(6<;ydzw=5wbyemH0IO?7?=ek9&YunoWXu!^`lmGKT~ z8p+GWnKKD4EBAkVO8NBQ4y4hp^0LdPUSB>P9B@Lxr8{;pod>i#eqW;^ue&wYP9TR@ zhs7&2wchZ$Y{xFfd9QZ&3g6i{XU`nK`2yK92TB=%JVy>(uEasQFlHYvtxU|UkEmXA$vc6++aGbA+X?!@p zp>f+kLf;a6!nl~-uW^$uV#Lpb8o$&4`u&i+CuY*wSpP^g6PyJG(C?k{o|tJLjrC)q zncyrpfPVi>-V>b>4^CsgZ@E7QUXh3Pr2_bo0{Ao(^ka)(8}n;kd-Quc@O=C~Q~<9n zfG;Y5UseDww8#Hr1?W2p;5QY(Q^4gLGTv0uZ{YoZ3eaC+UB{ z|IGq?xR>Al27U$u1@!@q->>DNt!^kd*Nr6hm6 zPAq_*UI0I*0A5=F|8N2PvI6)uz?se?lM!er>0|N!xW*gRFjQnzXwN;_q>pG^`cdG_ zr+oQ%kEY+R>81Y!{r3vc?lgyOooj)*$bwX$VQF$WnFRIf!mgNHw8W56hm35jSg~n zgc0V*9x@^4OF$4`A2*>6nUI4h78VfrP!b*HR!wupL#zkaL*nKxp7bCT`aGA%pB0Ac`_``4RG?V+}4VL7pp4>LO!+*8OTY z3qxHIB*i~x7Y<7gZ;+QgG?MY!1N+9b_jWOQHoa6xaxY46!ezKUEejXoyy%wZZgbVL zxw49l3Dnu@g)w5TOwoLebDVc79wUo#g@tomZ}7V`PCkAM|C+|h=X49-YT;*CxEf!n zaGh!4XQ4l(BA-e;#@`DpoMUE#^UNPA#?R(+yG8#Y*ctloXq@4-66^OgrU<5M340>$ui&zGS;(ZbKQa9dW2U!)BELQT&X{WbhA z@!(j77j=~fH+;+Uf7rrpe@89c=2OLhK=D6NZOt zKqeh3^|+1UxBWfe!q2eiKVsoFebmD3e4nNltLd-b;&YF*^Lezrw_f`u=z=<6)} zdlvnL7XG9~AF%MRl)(T+e{Fo1gGgM(h1XmB zFSqap3m>p>J3PZ0XL#Oc(SOmRue0!fws4!z_bhy-MgP2o+vRH66c9nNKHBZ!wH9u- zpLc1T>0tBudkYW3&ZPhOdc}zGI?=-GHBLU4Tlh5=y)8T1Y|)=((SO3CpKjs97X9TG z{&kDqJ}c{AEP9)N*)%wYVmL#1OuXh2R)v+u=D+5X8(hr!u%-Oxbl8gAZ#wqTdF;Uz_jn;Cr?C9uIy{oBz{`>v7c^ z9^94r&OJO|5Vo(Z5+2Y z!aB-2Q)dYDd#_%Yuhr$A%?$m~-D>9SsSjzqM7uMuV<_^HN9kRdgH%&*TJ58uMGL!+W-Bqvz3XzaepN&sjs$)pzrf3;A{_W+?n@E z*c-h~`j6VZjZyEV?b4Vo)*15qwEO9vgf-zegzeDe%m1<}ML}5`D&{|j9>zWUXsSXo z;CtCPL#Ghvs@;C2yUIQ@%4{C_t7U@H+e9a{6p~Y zfgn%w+5YwvH~Bj_v*bdUVXi241+wX+H3W@{oJAtKjw{Q-U)OZlhyyYGfulwjcZh z#8DnfZdOWjU#SK9 z$p5Y-Wsnq^B$CTkcsGrG73&lbvU=Tj=XdA;a$J{u*}3&r5$L*PqVLWklpmKeju93j z7yGa8TwtIvmQjJYC?iy3I}kU4R%NKhd}qP$w*)cJu_v-O5+23W~7X5yutiaQ7x*dv1G!$>2zu~ozhQ=5Rbh_Aoa;c z)OL6GCnLJjL)(|tZq90lvs%B_CiZ_7wD|d-&4ASFibw9lV=nCHy8#+~nY1A^H5%SsPPM21k_D zo~)JdAG}}TTRk|W8;1l-eO^)Q7C-23#3t4ChtiOR===Uc`u@L=p1GmZ!N~lnbSn`4 z;qmm#kke%>$V}lsN=!F>y%BW7f+SSZ-^Gkz2?f!=RYMQ0iT}UV=9mW$sUp<(zQmq7 zQ2SwPm4w9pAEAg4q|z4F9u2g|S@(XpukyNoc6<@D+?)H$AoIBC7F)U)!x@azH_&SQh(3HLPN6f;pxzXl8IH?r`N#Z-$DFi zcyKQKO|_H7z+^Or$pZnNbaJ+v6i0!>>Ewa!M^2mh$WZB3$(M>oWo77qn~k z0h(~@^!nsp_<&#IMSXG~{Rp)@hnPWjF*r0(+0TS!|B?!oKr(xIiEhTYFKYW%aC2N= z{T^KUM9(ifXW)6hU-MPKxqI>X$pGZeUk4G=Zl9zd67>m_veI6gl-TYj6LoMaJX0wa z%;ZlKzpL;Kei80NsTBL1rGvQRYzI9}rC3~W2OcvJ*Yo-1^)Nr=hOmbProh+}xUuR{ z-{7dwKTyf?0GZKwB6goV;2SK(Pz+L|dw^R~qo%wE7w(a;1bs{QAeR_6J6Ho9=ss#* z8T}_ik4Q^|(tlL4%x=esoZR;%_b?9J$i^*w8XU5IrS57+Xt^nEHIin;O-bmXea23$ z1Y^b&lLAG}U5q(3DaL(lpTu(D1H!c)49)#SrjJaIq3!4HiNkmw+TI`k7`*1CVD$QQ zczZvxQM;-cQCTnbMQ3ASf=!Z5{YXDWs?z7sc0cRDejJd(_@y3Z0f#`a@6KW|e@}7_ zV;Q8(n7ip{#aXb%sX}*tgVxD|fvv6J=zb}9_z3npaYqu}gZL;UTKj)f=NsTMKk|GP za9lRmQ1c4McAw^^hTy`ZAz$cl%^_UCcI!lJSqaU2!9_9tJ91?8#~CmOUV9V6D}eU` zBnbqd|21o0bzmRtvDb(K!@HqPeUF8)?$9p3Z{SNzDpU3(V7d)SyigZPVxt+7R*GWL z6TzZKFi>RVe0SbRXURR=RKySyM2z=8sYpG7G-B~`5s*(XOpwHG#|>N)N`0=fpMi%6a|B5tCCKnd z?5q=WI);@ZWMOQh&c2#4-ciSq`IB&ql$FH8@tRB-oqV`i@788d>fzqB1Y<+Gw;;Bi zEqg%9e?LJ(;CMgZNN7A2xg_IfmzEX22{jAw*K*YO`Zj?96Cp=mQ18RMCyp4WKZ+qLF zU>89piNyLGKmJgHrLH12eYdpawB-Om?ui<#uR2@Xof+rD;LMociJy6$t!p6w-Pt;OMs;WFQUUO5fF%N`-{qojbQa+Y_i9{e z;cs5u(;I_ugkHE{FyEs(`)vPJyl4wogJrJR^0)Q&bjej;{zy+0S7P*Z^ENPH?)T4_ z;a}bZxoXZGp}#8J67E<>8SNSVm2KhPR=+>6F5KI^ChT7pfzSu2mO~1h)aI=<`2O7s zfsiS*`m?H@-?sh!6%qB$cn|*FF}e(e+wd0eObQ&sbmnbi{yZ9@xQ8tJ?@g?O{4Au- zXr-p^({=w7GT6tVJ)+`zkXcK4j+o0ky^6n!6I_=}y#c?ArWSunj&p4mr~)Lb@K9Z) zUd{mCF|FTB9+1Y>_lE@`$9*XTY?XX&VCpp){gSCyW%TtqdRzde>4Q_>lirYX{`n^z zj#+$*T=CkBO!#yi=Q2&hxSX2@tJBzgi_XYk8!Q65c1`y^&PxBhZ19ru{^F90it`Ew z2d9>tR8qdVxW0TC0_k_-eGi`d@Z67QE3lE`Rd6qPWn{2dF>Kj%hWvH}$+k$updqgP zXBC6}KPhue&-2L^b4`mf!A6-f$UzfvzqXQcsEP8)3e)N@k?~dZ`4go?R@$^@`bD`D z9`d8!8pP{N(N2&xxGV};c8%K@^->1G=Nga2d19X6%=F;38n5)={Lanr)X6*hbE#-2 zsJ#bSSl{La)pd^ zB^tYK(M)h|Fo1rmw#3xZtmRFjEz7i5#-?B6Pa8nLZ3J3zuV!K?le zKtBAtz$p`1fu%qy(;og9dXbgXxU`AD7`}Xbep>)Pr1>E0MXBzoh&LIM2V0{FKI;FN`8c!t@4 zK&_Hr{6u>$?g+&CVpMVy~s49+PU6>*kJgMVA&rNG#h8=TWdD$?`&iou^KK>xf&&(9`? zp0f8;UjFBkF%)0N<1zFXY1~V{!J`M**e=b1(utk5OMgMpK`WGzv zlPvnT3ea!V?H=RxA&Y*q#_5c0mI>#-SoCLE_;w4o`OF|=D86j^6$S9Y0{DXk@ZS}{ zeY!oQwH==R9Vudr}imL|yA92EJ_#$)L3(m2!2mQiWd4L@;P_G8q- zPqz5Hsd4h3W8tUcBMlY#@SC6Ucech!Uv1%+TJ*Mz?v(}TFVI6T^5>^H!#|>NFaLfE zud(PqsM~+i&$VzP+e7~BBMtxOH9c{^g}-F+vE#KGG*sk&CLY7*9|%HuaUuqL~Hl7BgW^qx_s+w$>8D<>~%0R_{sDL%Jj8{Pou`!R!|vyK;vdSX7H^VXW5`K z_{$pi3!24$sl!?6!A8(-a~K3Nh>|L87Fmma5GNY@4?M@<-afM!i%=lU0mZY;Zj$0{V!kp zAnESMFQcrRGr{;%r*#KS0oG1?TSibP@)&5U10R8*ZKUf z;GhtSdrxiUF*87rz03YEuwild6ACU9@Qn%u0Jef(WtG{+X ziqCKQSQq&;>LwQdGz7b6RG?aYwM}9_d)64hamGklYZU8(gM+T>Ie4THAD+)__ zYsU_EH?(LPHh&MlNSxSIH*pKiUxzt>n+ew45K7)$5ll_2PqyGtAACG~jFidg!Q`o= zF9#8h0@?{MRMaIt-BC$DtwVW^(8Z>m3|h|T)p`j*I-1JJzJz!+?R;id;giKpI{nA~fRZg1s38)ifRzhcF zcuv(vx($F4f|-gUKPAQ&t(s=!jX@O6uzF#;L#r!J9S920p>4H_^Eb_ zc*9Bh5BOFjT(aMKGUfFh>Ub{LD(HMO@2HH( z`*W53^8Rw=u)OcByhq;OuDoB~4^)oG`v;YK@y;m+RRB;9@U@eZTX*PsobiMM^vbq5 zu#k^~w5t}wvpAitjLj3?)2f*)_$a6jd#rg3pH!3kaqt=s{^`QEEI0K)C7EZwsK=)v zv-bm$8l)1yd>dEg_i_8K5Y(?jzJcc@@i}aVXRqV@!fotUkmD*NS@0^*@MM6YjZTqW zsN<)gcJc^B949E5oKwtLvh-P5nTOeoqY!Sz%PJ`Km3^v|92CYIc`_c4 z|4e?aa##>mySMd=p}w-6rG^F;-+SbJN9BEZqv)(c8E~Y^u>3@FvTHWm#6Fan6O4up#Kn{#uQ)`9Mp>8Q5*VQI=|C?)>L(nv5>S{X{d(|-%j z^gI!VWjSMe3Awu)7!+q$Lz&Zmi(lDI&)Birz|If5T4h(Av8z^gwXj>I>{e#%Rw}zy zXo9->*iC&B#c8x$mpkzo=Z&R$`q2Bp_V;O?mxuG|me!T3CVQ|B*^QJ4B@f0=MdGeX zygkSF$@`F~`08DP^iMoe22p}l?BrOT_^H`VHaO`A!N|nl-L$l>A0ZjX=Xd$}JOd6@ zzQLQpBIBiR9BB%&(`LvBmfB5RSN9ncju0)9rEMR%QtcO)zn5l@m;T ztS&bB5US_k_kp2QC-zTv6GtZF+&V?$f_$Px1y)mFHN`h@C#(+bI5svFJgQ-T6vN&_ zJ4(^hER0pI^bI@?`a?U`E={#f52m`S;veQkJPVPmIIT544V6yS#i0n!M$>w!uEFHu z>Ar!zaLsVhX<*l4e^D^CxZPDpy={viUQ1IS&Xjt1uy`elzaN?iHC515Q&SBMY8ON} zpn(W7&Z&e3Rjt0##ZhrGdhiXbhHs%{AI@c6iXqF%>|b2i#g9YrP*NdGN*)6V76A-3 zz^4D-`-91+(Zh$5%@A7dXb&X=@F`G5+gfO(gTeFFBO@VS!w{GG1{|hK;=?$EbOAG(=cm?6(Lz5T!g-G? z9|k+!e`nR$aA%yBAB3i|R#NUAY!P(W+okHsug%r8eDc`RA{ z4_R1x04e5*K!&&jPfI0jMEP3Lhr7z8vf z%1wEK%#>)1}7Tt?G)Qo znlHteIRC{+<|Ix7nuSe7Q4EUF_~X7T@j>OI&9yZz*TgL=kqWoLjfXE9tC`@tt6^19 z`WRS`%hxXz;Kx?!32PH2q>w*niNncNufEq|&X8kQo$Muz2I^F!B=J_Y)R5k2E^daYRY192Wk zb;#h$EF9s?;1_1`ap8Fkg&}Wv24m<(WxKwPZ~BeHR(VAm{G2C`rpJ=Z_ae#nb|I#e zW9%UhUA1rE2Jqh1fI1KW8R`WDX$#a76rocIVbZC!x;e52fHkaQlm;m!;}!%NUsHnf3ww1`-LuqWo+cp z>3*y(eU{{KJ$ot4MxTkHCtZiB{UJ<2%*+9uct%eK6Jy82eVKB9SaJ*QRsY1olfDjh z1(6+Kaso%t((90II{pYsWBN99Ys$w=h|CVzV1iC2*9GQ*SV8tc)uhr?FP z=3QN#mtx<7ul@i6S91t6xn%ml=2yqYAWDk+HR^TE$Ix-CqMk=P;{;^}C9_ylpWK6S zdMN_EX(z*OO~eA<=f}m-pD^p;S!d-+Jt=c{msU!U5rIaYB)y6Otd;)NO`sw;vD0+m z7$7-%|Bc@>Oo8Nf-yr909KK>Xf?utaC5lQG92y(cl_o^kaSK;>z z@3RNa%(DAdmfh0io4$b-_-@LdIs`j6o(GVzk{0n;Fcn{kTNW_6zc$EKpY_P4vh*IbE}8n|4b91!(AO?A1PQVjeOY`BMkQW-kae1rdl z7FhiIh;Lw@=+~{3Wu1@<}o=BUnJp8d0}T?#*~@Ip09TFbhG}zI)&A)mm~troZd7uCq6rreCr{8 zIuVOZpAVa#kV6@RGH)yL%1JLouuEZG;BgriNv7qP85;6~7DFwhqId_v2buzKW+a;cD zU8CGZAxR3t^keAPviZUFG}YV(lRxKTK2{Xp#72fqFR%1t^neW&(?e(xE36f^fl3!v ztc-^w&Rk;NiS*&M*=nNlEKP9b522NKSy}KKXCU8NVSV;!qVrupVG3LwPAt;-<+nu6@?9ni?wVJX8IE_+_aNP zVRa=ZY7zPo!#nFECucK4DB>hP9DfXsbYyw69v+Efv{ z(~;OltWBg`+>-n!*Y};*hCXr>o8FKm>(-&>m(@HodY(#0@e@lMj$5)43F-vTxuFc> z2=Puj*#;+8Q*$WMS5~wh*GM#?zHszN!I-5JXo!RZN zu1*DrZgwAxc1&niYE}U?qq??_k0x_+qtg}d#37*&hn&;a)7v#mybNdFb5PkxS}19_vilsCl>3*JPrppI zIXEutO@Y|Lo+i5oBj3H&E6Vp575{zSEf|ZZ(jPX)REPQF3Fl?y{bv;aCjyF~BRCS! zRUkV;TBsY}-T!*rF7Od}KmLa6`l-dY$Pm2r9SDKU9SHTvkj1%IAXI^LzjoI{cUNWd&}AOt?g5=9XsBU5jpI0| z7ucg_!<)^M?3wvX%I}|0{DZvV4NMKe`AW?zn47*RJLB#xzp{KdP%<_D<>Cz#DXhSA zpXN6cda8@?{6J$rB7pGfdlHbocko__+b1BrxF-SIpsJ8gnR^oCUUHGo)$Y%v`*%@{ z#{Ug_Z=^2ju;$xiL%CG$$r;f!QV*g3kj4*cTIk!sc5U@)Oj@c8H)DxwJ z>kO0_#>Kr zqX*xk@lSbh8cQ73>Rk0Wj1{?%n0{LTf2jcehXOdubw2(@sMz^%Ujdvls`==-PM;5- zT>zh70AEx9zq|m>J|>^Ply%LAM+@Nn1@KP;xA!bbUxu{&ashgNrgPPBXmT{AQ z419KK+^>ZZrJn-6PvgTHmp%#j^9A^)3*c{PKK(Kc!HfuIsv@-gvR8@?CY0${c#bl0 z5!eSVeGA^FX?%nW2T++lgJV*TTd|i3wgi>3cWM`9Xa*~ZvHOisd6Qy=T zsa;ZPAC$c_sFkLzUYK#HtxLVl-L2|y`z~|*y=)I^=~AbtV}^q% zkfK#b+INM!S|S^i8_s`jj5l{;k5M0P1&HB|SIb%+jNim9Nt*S#%r-2zXlXYmwZqUF zkI->sP1EXTToZt~mU6cMUk3kq0sJ=_Cx2EsLw}C0FJ}Wg$HE`eIKz3ag+EzA8UcfnsoFY|7OcDEoZxd9XA5f1>I6;_{}!pVqiH zoRjr{ht_sDzoT)|pKtLQ)i}e$>5JjNOb@lZ{8yHN2#Wme_?o>=#B1>wK6hw(ufL^} zK?LRH^PtAP{x<2M1aUik)>*h6uZ@fhl$ZYJ1@QCrP}EC*g@xPvdo0{8=LZVlvN2MJ z$EKfd$WojHOEk{%z%jDP$4_Y7n_o$bo?aRH zuNI*Ho`uh`=(iW(bBZ2hc>SGe;dXhuOXJ@1^B;OV;>8!}afcUQtZ}Bp1y(r6EZp9k zS6`m7Wn4pNCiN}QVa*cb_e|Z7?M;4z8Ek3vEaWvy=hyQks z(_cH^e^3B_)Z$~uYoQ)@lmBeX-`fk|FN21P^o*N{FEJ{HhtGc9E|ZSR;FBjQv+kxc zc$vm^cag!DPf_%`naSWwb$_X=MFtOPTqkD+k7)j^n^Yz|*J}^`f@X2Q#w$H|sczp{ z_NWXWbFTfl3eMm^(R`{s_*R`h^E~()x__9;Syar7E8vO4xZt~IK_iEham%;y8<9_`%_ygK( z(%;~Q-lVg^AJX(DJq>Q=pLHJoKh|cGK8Aj;#!WgH{8t)Z>EZLNHv9G4YFvkqVu5)B`-4)EXKBdqoTV>&D6;rHfj8KyxN7XV`;@od~ChY9oS zmYy#8NHx2=Cl;Q)Zmy_YYh4O<5lUz4f8J2Zg_q=X@jYWmg z=r_k6Y+LKJ*}UADO4p~y^>jynOno%P#}uqjd4e*sz@=&%f3^`yle< z9MM+B|5t4gdgH%&*J;e_e!6bp_j=r$_#5}jwR>GGGt>vPd)nKIX>F@3VaS*MBRW7w zv`0*THkHPIlm5-XNa9VuIt~V*R>^Pn$Dh@T?t1*@^M9-EQ2dtvEDB!#W57sKjmK8^ zX#d%_+e)*`QOdNQ=x{OYBoNFlK*Vxx`f<;n|UCyAYq7J2r%8^-o$Wa%i&5=_3Mw}>8~ z&k(T2t_jh)3m;u~OwCAEzGN83p+c|(0wuwjzrTEF-aH|L2+XhCg}+upH2W6yZ=5$a zn{Irc8wuPH_}C8n+-!=drcQHH*oz0LB1rVypnQS=BK9T{I9Y{a;ePCXR zi33ICx1((s(k$^PoK}(YD&w?DJ3ZYvjXyg20VN9xzS!6a>iB)5yOsO%;2uKfW3e+_ z$mc+0FZO1ewqeK$4N`VUB#qMRv6@AbC5yFO%MN2(H1;MaVVl@o zvl+Pm!ZVPTv5!JtHg>K%v=k@*mQM9;so+-7>-#U96F<5C?K$z1UGP|m@!-Joeue{f zv6qcp7`Gr_M{#5=MTo#k7S_YrP!ys@k04v!#4AM-{n5`th7TOc{)ZIbyccp^=NyHv zqn{l{;xEBwW0`@5Qdb(m!jKY*cZX!C97dLBEBlriC2V+b77tS_Y(tQn2_1|_aLMF|F4sv7Qs=%^k5c5B*0VB$o z*y+a|3bTzYAo#^09V)>X-P$&+%I8s(&ziAi*mW;4#O5t#UjRvqJsYE^Qf6`Chhwn6 z0h__jtt>k5DCSC#PD8Rlcr|fbEkb)5B>OJxslM$$P~4SO{CC-co$)_$TcZ0SwUnx!9)dulfAjLn59f&C ztpufsI%Vv17H?aHJhwJBC3pA+{t<0f!vMA^uf%v#)BR{O76$a@s7HMR-vGC5oWf?L zER#C}zAcjmuvKpq`xy}a#O@-6#L6!6#|~aJ8N~`>evP4__}H%c%8TK&lRG+CxauoI z6#T2kP70VL`*t;mC|oiPA3)v+@|PqJAVGL%9a>86$VLEwr&Bdcje?LT$>z{ImZY)mz0)^`FI_DQ|;+G}vInydbMQ_#nwk&KI z7(>8M=H8RU_9BhMrUm-P{IOT?J300u%4FRHeqT{YAq z1@M6Tya(q&+O-CI#g&|^K~DvmY5yr0TM+l2t#wmLtG3%0}j#lqMeyN zHx$NpACgu5v9a5@i+$$fZqask;lclxxp#q&s=E4yXSf*wIZ;ummpW=tP=N$c34&%I zff-E{1r@b4#1J3~Nla!ic#X~sFpfc5Z&+=$^@g=oTNP0h0xIC87He&7Z7XeUWlVjv zH^eLN|G)O$Gb@M8)8~D^@BMw>hRHeSf7V`m?X}mwo_&dUXT1?g&n)e@8aCynVl<7! zRU-oNA)L>Ok{&ZoPd6Z!iE->8SG-YCSabpSegsPO7t?~nveFrwLtMoLgK4~qcE*RT zn0g_nHvSokjAj;NGB@UD?*L;n#}e~Yk*BUP)5;NM@)mewp^g_)XIv{&w66hbQ!p08 z>kwXtP^Ngv!zd%Fgm1dn=XG3lAtIDOR_nM1cS(NcK*3V>&dyp{l!BcTfaGSMq9FHD z{n6&YBvh6Qu8axS%DEO`eKYNw(?BWTtCSC0h)|i#|S<30n$UkEG#gjr_@(o*tMfX}NfwS+u9E)Rt0v+AxXrYOFGL72BC3 zs<91+D`-<6UieKfwGe``hRD{7T9Q-?YN^S*JVR^8CLaHM(7U7SaAf{?5pvqVEmJQF zhC5C_#!F6upAD>)RBno~-rit*=CW99e}LVC{rMGn^k2!Yn$9bN@x!tk5FHzjN&7}S z&&T}xvyi4(a|7ESfWWg@P=nI%>XOqUouepU*~^Jf2YAc3urRBy>Byx}JgR0^V&?XLt8s6-{hmc{ad=Zx+6gRcavhYmLR|z?D{5w08sqtV*Il zXhD)^JrURGOR9xuXo3jQHhx5H(ag{is?JN%s;Z?%5#?g>k_iE&9#)y4*2^`OriQ}L zF@>u$T;?(sN|tSFSXz6xzL-48Yin zu51is(aveX?nCqWrQ@@GBUmlyCHavW$4{V@h7CiqP<{=M2ixK$dA2|{Dj`%-jw&c? zxDn|ZH0S$@E;H8@+v^B>9cHf~d!1mf5qq7%>p#8bz9`DP{i_1Fomz~WV%~&s6XH!N zZc2Gmftw26%)pKK#coAXj%k+LnxZ{%9e5enE+h+>OFc!j`wKTuOKX7C%Hf+xxJK(>b@tMlUp6FL|%T4B=F# z|Ku9@Sh9zmekxH+vGU*f;XlF1RPSgQSp)P^hl4*$JzT8(Xx_j!vUSK`(oaF-W-=C) zV`*si4*ZFFkr!z=*&idyBC?B3_Dsnnd$&VoO8Z2r28a@Y$(!7*+945SO)fq~D`SFG z{43A^%zgzZ-0=l$@L0%~_;eras=#bN3{O}q;14Nw1M}E5*svJtM8eK0DV6N@5|=I| z-x0-swUJp<^t*vyI#OMb!n>`q1*BowHs@E_pD@)-=^;55SurW-G7<-WAR5!+6Wu z*<5E1+oGWZ_cQG3Hd}Stu=12e6;`I(f=`NWY6V_s(h_p4d67 zq_T&lRATQVEwkMMxXCPxxX%UW z^tv?cJn{Eu17u&a;+QH>RRs2)gA{`Qg~hHrKt7@)qdPQQ*6bg@CXPN9T2jspsX1$`rg^0#CA zpeGp|6Yqjt*=AQ5F!l5L<2cTlT*D|wHAY|(095-3`rNr2iz%%}KXw~o;VQ$+9Mimb zPJXRD7wP%=pNhjE|IOo$AV0DdSh7JPdZNxbN)&(JGTNCzVBH_&?5j6^ZFc#eY#=a( zLwhw?`o|tt`lIfVw!K>ZC5AYQ6nW;z*qcB& zCX{nO4LU+^7}2}VG^nv#7+()H?WiMn zc44)w)0-JSOn)Rphl*d1y&b_g^oDoS^6?w_;fX9}qVmBV>vNlU284oc2vAtS#21VCywD?F z7!-RCZ%p~|rwtqngVJ37@RASFo3Z?7`K>;Z{)4<^gX}jkG_=ngBxBUx+WoQN-ic^? z$GncuLh+-OJ)&Xetu3oa?urer==drW`!D>(_zLz{s4DA9qlo!0XZ+cA7JfFPZI|`~ zQ;b2r*e{)4x?i#5)?%M!Xg0ElX(dgO zqrsTx8rzOEBS*L7`hf3;Wlgk18wIajf?ff`*tKN}5+VH-cK2dqW3kE4Rt|;(>n;0G zJjz0FJjz3Na=sq_l=1t=_?=BgUT#Hf?UoGBvdw4L(VG)KVQ1dj%!TZlPKF| z&RV0^%rlResCHmY^wc%`sRj52${YSUoHcvs>Yq|1p6BmBOk3tAx9Hc#pxtY&vZJVyPffmzYZ zs9^j>^eH@y+`R)!&t8jQrCc7Yi+Ij<<%8l%dwfw#!Bj92mGDeC}D%v!-J`xRE#39BQju(qJRs z7HY)NgQ5`Vq@erXSSLNyG6`OJZXnoR96W6BK1HigGnW9j(=g0gVLjG6_nAIqSfwm@ zj)1Px@@U{Szg87%YwcQ9tlv!xnC)AtI(5*cZtZH7EMAs5^s6kd&6by4myI>9iGEAW zA$(Zpi~|6{&Mxqkb+i*e|C;stSk7;RYr4g+JMj;mBXY7|wS*aAb6^C1ZeR3A=@)Uu zd4ugkhGDtw6be~-J|c^=2G1Nc39rXPKXfVn=`FrfWo<6b66~=y_Y8*Bf*+elbgy&V zxVN>)(ATm7;UN(}dI8~XH^aAU_FErZ4(syVOsXAp)gbZH$nUU{p z%i|2o{){@bmnW;cDQqhSX=Dn@1mT)>4PrL`=jh#HoPNx%HCVL zPRCmROCWl5FVQ6zFyOr%&F25++HjWbT%+yW1@`73i_f*sQnuip^X^H%-Qt_=m6zVm zcRT?&>F>2cNZA0a!s0WiH#o`nxX!{)>n`t&cA!x;>+@o-2K7gMj!c? z?^*o&c}VU)u(*^j>fOf{zei!b-6hWh0t4;*qhcoqK|G<+yP@H`y z^aBFJW-sD_Y0B85SH~JR~;J++@zf%DJBXF@#TLHLo z<&y&R`@oKSljpDk_$c7yUt!lENc#qQ;H<3P_?&O)-I@hy*MPpU0DVgV{E7m2z;xEI zqX8Ghn}lAX@{N4Gyr3Be&&2Yuy#KW`_fAT(H<~ zJAeb<%O%B}t2|NzhY$;$B+WS5RYKH~xh)`SG*w$QMUS8XV-g(n}JR@xG zwSadBF4k=KQb59BHHi(Nv1xv@J=zweva9>jHO z=0*+kA&>RW6lgN<_TIh1^5LPo+<3!!X1EEAm7(cq>@#8ua zOe_%R+Fuw$?6G%&D{uYy_d!QTd>np`k7+*{e5}I%je9yjpCeIk^@g+k(Hs7N#VP+u z__=UpH+nq#`Lq6`^T&68i}S+r(D4~#aq>A?;co9SzGfBZ=<5}q0~CI#!tq%oM}N7( zb-0fzoK>Ua&snZ?yy$RQ57F_$s?pKErEpe(4*#9S880sLaQJRTe~7~OM>$SMdXDip z`d=5o-JTWH^F&2Ihz#I}b7HjPbArWr;nee6;-26@Hou_eO=Yujb@=*W&(g%Wc=zFXuN3 z;8zvEKUKJv^I+RiWw<(C;}ovThjT4XeIBahzrf;tIbSWn=VL`*q4*q)3A%LTe;9sF zKV=F(T;UZKXSiX7*DHFRFK$!xS`R-gfcG5;rf`&JKm43L$0}Us_t6&j>tU|Nj|UH} z=LL$7&eyjnT=V}y0X|)dUY92?7r+PEArQt(^FP?)e)&(g`0+mZ>kHtS0{D8xU)%p7 zwn8F*ZEsx`r<_ON=k)(`g=;(cqs9I9@QI@Ty5jSNqSxiX=}c@m^3irON8wZO&dGC) z#VNlo-|klQQx$!eqSx`=&khhV+)71%gvF_cBNcwMqSx}5S=_JB(-f}laJk|iQv7c! z!2fxLS1I~86t4C5j^clmq95Yn0nRVyVG7rBMlDV~==yZE#i=(f&tnSL@@!Q6wfD-6+T|k^GroLe|#q^T!-6cafYk)wnE{@;GL7F)8dpz z+rw(bU&r?Wh3jxPDL&H_|931-c}f(%L(%JSyA^*O?rw$aaF5y_OyQ^>jjyygJD`|Xi{&ZYZ0DsNmlxHk{j?bSIy^e1` zJ1#F)N-A)j*;{dhKl;TZ0*__=Vy z7AO6=3co|qmn-}}g&(KzcP#GL&xeZtOhx~B0s8&zxDn;i^v7GA@{dq_CMfz@3a_`g zU!KbqpBhDvlNrU4zs4U@_((H2+U6&Ul@t_zYrW7tSyLX%_eE;c`W<`L9&C*2ANUkGAu*ieB6KOBQFm zzJZ^!&({^fog&)tx7Mx$7Gc8U%oQR(bcaFvVd|DO# zC`Es@qSxu0QS_q~{Vj@K+w%_;z1G8%ieBsCb%pDE^j-m+QcU#Tvg6c(B!{!`*k`2|nCy7}4&--S-`S7ol@} z+;@se1QhPRJMh3Ojl1s-t9`ip?%>8x9Dn!Sp~#MhINW`AnB~J)Sq0zZ!`=A&i$2_q z!~b913+Vqxd;WZA^P5SPy}wcLHS=7BBXHL-=4OR$53;*KQ*imk*){8O;#SSLGj7!3 z?yl$6no|yB*+!oKr~b>}mps|#($0ndh6Zu(!gtpSi~0Ra=NRuebz3_Ze+RRS`@`ojS8w6BpJ4o_d@udsk10FJY^o#s=!8Q0 z!Q7j_ZqJ?Z<0qVKcHjA*@43_ULn90SR>*Ay#;7o5*Gwj!xnTuB%+b!TdWa2;WDbm^ zZ&(9yu`P~0FKHbM3wbbFl`U3|*#`$ZR;}q1KWa@;e9oFsd?}7uOI=Tn=7gyVY%Ozu znd=XLx?V>mxKpR}o+x-vTlnwZQ~&?n`;dFz{k>HbfI$g;_e!i;I;7*-6$l}ixp4$u z#EY)~lzZl1H=wKw>rPf(|LM2z6x;9mPw&80e8u0l;DH8=9pDli9Hvper_?r)edw zY7a)!ui-c?EW+%#PhPhbN6L3zH#@h4S0=w-CVuK8nVAc@3Q)GoNzcS=@R=Z7b?=Sj zJ992>*WflWwLOU41zI2`Qdm}J?+Gh@Ur5_Nbt1;xix27r;52d+@1%9!`QGE zXIeYA%*i~q1|*T-b_nX-kYOm3ITr-We7xm9;$vsOib(Lo>dX?%+uwLEiQm`>;)pkO zr?tQ6$gi;4L{^2xzHvt9q|#{m$K)DKr-VLz6}&#N0?e=;c_%JZTuXJZzP&oQ11f0Q zB1VdZ5V8rATH}(rwx#<;_1trAyO=ZfO3Lra2h#q#jak zX6ClXk->2cS}cl3?X zOX3dVSO>Hvu>yBUq^foRf%s7umvz}S9avNm*|hWYWS6Cm^XT9h4rj&IR(2aFyM`vU zipieXy(jh{*H_-t#nm-X6V9>48O2<-T>eY%?#=sd@BXRaIr{kaNapzv1i+#QFF7Bd zEG635kIK8-?g*9Fk6Y7$1s(QG*-T~x{8ne45QU^~UI=AGG8s<(z#7m<`esgN@RA8e zHM5}umvH(mED6DKF0S^$5rqALVd>}TT+Sf(va}((bs352G6~V}?!K}1#O{8vnOFu= zncfjU35QO{M|V6gb8F+nJJ$b%B}W`$C_NW-kDeTg=S0 zHbi9`z3fuFvV6k}a>@!j->1OI2ISi@n>#;O4L5 zLY;pjAg1n?by!k5rpK!45wN=q7b5TO6RXDGU~Kf3sb53A$|cPsuu^x@@DY&G zOMM-(Lx&R>Q@w_+3Ol8=*~-RCJ&3Ad%hX}P?q{*z$;UPk?M`CxAIWYeJea0BlR_be zY>4Ga^{h?I9u+yObPIC4wNr;BJ`S#!`ZXLIdMS)EpB}b8i+#&_lCY4S;vLx90{Og? z0aSNBwG(n9xYY~==U__Hj5i^~Dp1q;%;QD5;5P&-SXgsKE>`)O!X|f>O_w^cn;1{^ z#BwVvzs2c}KetizQml+c`)n!-5jr6eektw^g@28yuTamhXpdZ~o6ue*iCxiwX+kFW_Ea_ppu zv9G~M26i9FwO@F`W>Q%8zP2yGzfVFIeFwWCoPagKv9Fs%%mljk!Re@cVQ@|j%mEXwUM>? zEU!#Glu3Y3pmWCEiO=ene9c>X3tMPd`TF&a^=$41)^V^p-p7^yD62XExb_=zZmeW7 zn|@yMQ-P%pj}=emUNzpzzW|eRqvLsL-+9S#z$def=q1%h!? zER>PCg$l^!ZKpAbcXl7CaZqkXI@hm*Vs=(ye+aJnpNkh;64X^NTaA0XU(NR=@;(;w z*51YlGb$%B5YckBFK$iwX#HCJ53p2&8+%=aXY8JjKZyyP7at2&dQB2adszDumXm!ih^sZJ+&hnLi%d)bwH$-87%G>wfH*}(Bq z_ru$k#CE{Jj`dwD@Dy9r@%(oXa3GHM`}%EwP{+qE=vbejna0nGWS;86jpQ|yv!~hU zbsuf)&-6FE)Hk3N`^xfnrY(!?NiRImc|V#$6VVRg4uFWJ+u?TtyV2{+#c znY`2tD!cOu#x9b6BP{I)Ho1p_k~%#F@4N3%`jkB)_fW0j^e$F`Zz4ku!x3()1d;xokjgu`UnU6%9ShUZLB0KPmI`#$bxo9Yu-Vo|n zyDDb{L-F?@VwU-WLEynAgY~<#G)d&R}BDw8(*AgtWB zYZy{s11n(Z%Old*KQ-6CVG2p(&h4?ALf*nz%==ciC){ zYu`jNr&VVf^r_p}yo0ToW!spikh)l6k6lcv(K$p4SEv6tE%W5E?Yza#4ZAAPa6FGS ze5f*w{ljpkw<+FJ*a2xv>?&+hhP`TW{?wRL3-}*fi@^M z6yato-t_I!k#BTtT+KY{r5?p!Y!B-tufdIMqf!&BDUAdNpwmR*&E60kKj}Pa;KxYR z;MV9!yt$EG^JuzeHg4H9$L-u`rluIzg}4^s+7e0sR66kK?-+_}ifhshc=O{9gcU{? z5%CU4VJB<6xrYk^mW^<(rBR{Vmb{jv8%`nNX0Z&!9y?YdUeWa1(6=m*X9LV=gBzP* zmk`9b8fTDzlfKwyBq7CPc8{<}J0F4}~uwx;EPf~Qb`Ws~@ zirN?yigA?A!N*6ieR8CHlecUoeWpHaZ^Gst?Ty&)brkBp@duD5y7eU}Y7fH;r)JLp&sCPV z`$<>MWH2m~MqdL%E5Tn&56x_AB?B&qlgr$8e2rU?q|XAU?r%wcww;Pku<-{D7%JoMj>vJXBaoww%(wQvb2ydh_#yreMIPz&JnybYumv9|gimUAFV~l|<#247Vk_=1px0zOw zi`k4hcd+E#_^H?_l-{I!$nw!`B$h^_FxPjr8~z}4l)LZlIRK_PxceyyPPCFQ&uC8= zjG~&P+luZv+Ji>0^nVFU>{VrU_~u|ub+FqucSD8M&%%j*V>AU_j%$>|lGTlkpV6Hb)^O9cx?ZpB3S1_K4ty zR{xTR4q_Ni*f5b-)nQ3~0sxg|JGQE531Z)3FZmRZoc^#059-M+!76X8^#xT{P>)Xd05o|c|JV$x@ddXr)8SZ$lL|W8d>NoI77NtE|30)7bM{I$gG{z%JLHL2TX+x8dl1PZSdAEgdW<1>`4uGIzZu;gkQ8**oTVUX}2yO1ETof!X4M`IW?XN zZ<)SlBI<=(2CtuC36&umw~ z+#+fuA>8r242EEDm&|uLtdTPb+DG=!=v`W~$-aX7j*V;+!i1j3gYzq<y+LU8L zI@!Q0`#ro6t?2T;>_eJvkD>;4n^}G@WI);-&z%)1_fRP$u-Rs642z(g^m@GdbBrOc zfj?9O_Ysq1D*AY7xeyI>UQXFU!7&Ugf4phN=ui zR!1^}H)Z;j%wQSAKf`9&a{k;(JYggIgGg7M8H|C04SO)ZR)WkVC_5w!aY$!m0%Mc& z&`0x9*j>mC`$_hH-&!HIJwCYbtIx&USRT6Zg50JoJMb!B-sPH{C|MM1j)I6>G9D!h zHf&9s_*;8*23sIL)`eK~NP&eId)#SUj=4m$Zumh?a$lb_JO}?9(S9zAztbTriyD3;bkQKb8H7iG8^RHJCLTn3CW=c zCyBQdB0p^1Dn%^=9r<@(&qCVLPf%6{ToLV@G}s0vZ)TN%KLlV+RY6u0A|qdk1b-eG zxw$%st@$mF#4|F*#bEHZ z*jbrP61Q8I7^MfJ^w!Q8fI+hTJKFbw;r|xOvh7x+13zqG`i0Lb zG~80JBXu!wgp|Q2>yGuNx=ubR5jRR>HqI4OMiJPJ(G*}VA{YYjDtAMX!{Enma0lJQ z4(*r_h#iD{$AxT`7+)W8D9R3ej4g#?qM5To_5~8)ad?lS5s$Ba7-q-mCb(=vhbDGl z$HYKvNOk5G7RfcKUx34QX9d-rM?iWB=PpSUV?8ygcR=+v>H#w-p5X_ETwN?B2t-5x zo6RvTuV5?=9yW77+FEu2_F%vOzt9EYS?8Z)wHL;@EU4Y9OHlPutFy&qp`y9Y#u6{$ z{dxw8(mk`B!+9vL_)J&H-Z8%3gsv!!Jj+%p{=>xY+l=!Raz;u)_Y@n_tqDHSNpc-Y zTXHoUhCq(6rFd*8l8A=ZH!M{*_JD>rVBF&lhVg6Un*8Q;ZUoA5LQ;g_75Zn@4U46x zOr-sdY~qjDe{)yVtNb^1=aZ;PzaO0zu%I=X0-i$$$ryrQ({5OGx|>@V7j>80_VSsq zUugp6Ob`t!;l_sbjRTRP6EC7_JPhCRykrE=JdS`vquuzJ8sE^Xx0#kKlF6~}zNcfo zZSkKa`T8;QLHkQ|Hy%g91cUiL_3b5pf(bvCE9$aJNNpklgAlcQ$%g+(kz&QtBVNdv zc~-(FykdEUsC2pcI^N|a7s8uMv_l{f-(z4tay?qT5N+is2#WF!WlsMC{(#nWx~V9< zb()NfpmiTj-($vfmUDy$iI5M_#z#_FGQ8EWiBRe{NK+ow1f#{yz;}c)eC)!o8pccW zOxUh@(fU}2*-FvGwJcW}p=|8MUy6M_NsF(Le=Dl#oHk;HoDhKiX5tl?gJ~LF_)Yr9 zjFKg#JQ<|L3h8>(hRBkfUz+M#cRZ4$(yMwqQvTL;Q*x=2g}<^c2~8prPCUdN!oC!r zsJ2+f1;bmHS1?84a{VXCow*)NCC?Xmlct$?v0Zg!^6lZR%cUIz7TqthpM*5|7OOlj z`3iU6mR95Q0;FC7fY&$kDVOx7lte8hrE~WCpb@(_Extf@Uwlh2<7`r+BYVk+eJ=BG zS76qNscj%cj^uao%1mN6!pKy#ujvz;AHIG!Gj)7U$NH5l3|tLk+ia#xMpq$%-G;rY zZLU!Es&XGH)2_JlQm=?OmB*K3C0G56T4@`?)-lkO!plU|Gc7d^+=JI zx&dE>5?}W7lJ@}hmN%o^NqpJIyMZ@OaHyszdm#uX;cEk`M;T5)qnfp0`sb`zbGem? zEltK@vemOILqURK2wFu^%%TnTDf@M%ZJEvx%C44#sz9i=ZZ(#PQg8-d!@5z^Zo;0K zutS@Zq_+Jo@~O`YtC3z>ENDrvU4cyCCC|XA0p1F369To^cJj%#2!hH^id)FN@?scS^aN>Eff@R2eB<3*NeegX zmfS6R4X-}{vCLLsuD;j}DlN7mkpC{?@esLMkxd9zsZaB5zD2eb`T;eZa1+@D@=}Mw zfA%1xm&uPXhd_22Qr(OzKwfsCm}^I5e~lvy+<2>N>{X{tBigWJj{_UUljUZJnlC^0 zHU^xq1aWc&gf*|NCblb?0EYlTC^BdNdy)dsZSG+SiEq?l+Ns%EG4>94Lw4)$B|qmU1zUbdcKZN;)63KBl3EQbrLymd42&)Nvt2xw z%QZvV`^JX3LNhi5$;ZS-m3si_Z5Sx8rRJrwL)p8)BDz(qg92qoA*+iCW#dfoUL){r zDK~KH#%;LC9)dr)@h_Cn*z~r!mqxDbrGJ1gk2W==2E=f3FT~-*7ki-d*bx{`!XEWZ z3}dQNqngCCjpjSakYfVAvf+Bc(O%Dwz*-R&@J-@%M0*;?z*%#%coMGY2$>o;xgRtp zh2u1sG>gUL2~tM*WYN_%j`4se+Dbo(WskDVnIQ8szT99OgvuL(Ken@z({-e?)s%9! zW0O5vQiAzVa!673<^O`pH+&`%cSbgLd|GtHf%0uP^5%|*_k~Gg(|_1BaupkqX!m=m zpTjen$%&V-oA3MocoZ`<@WCY9adp41@Ll((O!3(;hm6ykvTsOYpkIWI&!xY=Q zjFWeDcxRia@#(I=*t3Ud#xQms_qI%~NZtj-_RK>vz7Wb@faDOhKy$WHI{}c&)1mA* z0J#?Nao`lqH zs%L`}({FO$=kra?@m7M=9Vn-8U=BywXpSU}_0iotKb1>v8`!G8Y>5a>C$P+Z0)E`j%Wj|*b zxOYN-jYiN8F8>2DQdfh&ZDP;ot*?nagKccKtz9!48*Q6C=VxCe?cnU~$jj(D1dw;U z<(x5ul9oM+Kz0Q)u)h@RnNnL20~c4(3+6f+MaSE0F^*bzD;cFejBMQkEg&bOt6%l+ zJR|GF=r#2n5F-}&NZf=E&eMvsX%T}%7zIo!`7TP0?5Pk%rjuHYW+#$SW@Bzr@mZik zS(47WawO8Za8LGlp#LF~f5fpsJtFBPA7JL^DYrQJWw_6vM2LLsBwEqLi~VU_xATM{ zv1}hf_Cc0>olO%2ci(z)nTER}p^V>y*-3wrnf_9Amr#5#ALMZKIcH=gU*}kfZ0n9jtg?N2)Ot#` zoapONY)3QaW>``;S46V(q8WXfM$Rlh2!IP}}-Na8U=io^+vEgH&{k`RzQ66C?@TC244%noD>0fzC4m)Au zW=dKJroA8DDoo%}h9~-ZskIncdYJ3)@NEM_Ml5I$-3-6Q)O0Qzfr~X$Yoqwm>7_0L zC5AmJwkA0G0*M2122E$bj$l_XLBHY5qx1`*IjkN|-yXn_)%9O;sZ}`r=x$)%J)1B_ z*spy1wfo?;P<3pOsk*VE=roZH^J*49^sBBZmX9Lr( zdr2~9=ue_fPILvs>18{>&3VRDYJ4Z$@EBf#Z3vf0`YYQEe-=q@if*J$@?X%s4QeNF z(<^@o6UOk-1qTX3&r*G0b{^(AqB#TF3TSB0_GspI$`?&P%I7ki1ij%V1{ck&WI|VX zx4o2jsSi*)6^)y{aiYt+5{xyX*P#{|5j{kM%Z7mwE^CC#GBK&G@(uv4i#}x%1ls-a zgKIL6(kyxGVZcibMmfdt2%PT4b~wJ_k2`$$2)wW4p`*d}vP zQ}1Cgwrp2kLAOiPGLJG4=xIx2G9zE0e1sDZa-{UDTnZ_J}Y0X*b}1g`AorEaCi#D>R_ zf*5dE#@DX2{lu08cGX(85igOMlHf|6u9f6A!vN1h+4(%d_?i$8v{vrjd>HFN`)QU1 zW+t%;ih@>R`z9t}z~Fb_;PML3*s~t9f0hBK3Z{dJT=H9#acdWwxoDr|^owGui2d2* zBY2ALt>}44C`Q;47vV`Q3q3tCU(j%lFj?h7f59-2CToX63!$ff=qv z;9ZP-AH=9mJGf#3isVS%;uY%(WM5Hx_F%M#jQ(8x{Q*7c3C|m zRN3S3&X(`FVq`h#6YH64k;#_wiG9UST%JkICuFkq)&Rl^WM>H*Q(oAw*Ir6a8SORK zrM98^b}3Ph)MR~Rs}*|$HI6d&BtY2lT;v^0*}i5tzdS=RwkeIMgg0XLmdS$IF;JI?J8an_X)- zc^haYpQC2YUM1a#gTTufx@ZD|r^?{fSELV$Pk>&WeI<`)r>1xN;wK58XVeEg#54OZ zF%zV_uU_Lv4+)%Yy?gQCnmL^d%{~X1F1t8@^~tg0ge;ONLL2g}U6toxfysby$CoF@ zhp;Q)$l||otw`3GdLn3Fs3x4bJ%S5QsZ7G|9BENc(xf!owk{(n9rzbzV@MK{UwYKb zXt(9%Z-EEcrTuQhB|A1YnCiNJb?3tUIo0(T8;<}ta;O0POF_hFF%KDy*_DIcS}=Vy z-mx^RykM@fIg;aS9FfTt7Rmi}VZo|AyT{l!N@V5;jGw-XcS}vU8;okfb*lqV&r?qY$Bu#_qOysbUT!W;W~q1y*FIzT%*}>uD|fScc%& zn%1VtKDXX!1=)l-)B#p{wr}}Hu^2RAT*i$Vd+?q zO$LqWXXPk|B4hnGoRWtl`yf9{jc2+p*E1`6$-a0|W`}su!L4xS3vHnH*FHo-K+Y9% zwLb^p zOlfPQ`i$ZAtNaP(sb7J|hL8kdX7jQ6oa_SHfo6i2T#LI%=j@;?VGTde9+_*%fD#k^ zyksr7+EOySrC$l&{}yTQ24Gg4SYqq>ja)C9Et2R}vYlhreWn`u1#KoQvq!m%FMqZ` z&NFjnJ^?WUv5Bt@+7Po9W3QIi8XI+4kD23b0!Y7`s3f)}YB9`k?jpi3OAZ~{`{t$k@% zWjI(A`%T#{sde1Ur0A*3Sj)m*Lu8XW3uQS}It&kJ(;3VCKE~60c}JCsu>+8AsCBz2 zcmi&H)CVGFHYZxz*dV(icp#`porph)-SytG1a5TaD!CCEAiR<0oqY&WF#n`K$R3Uq zbGe+gfG$Dz0}EA*xj6hDgI%ha;epE8^T1JtCG8?FQ@CQqY6yA0CbNYORJc|U~ zzqf4@(M^SS>q{oJnIE@$$wf#SBqSE^U-}TCr6RX1`5pOY$>3n>F;F4>@XBGNH_U5I)W_` zGlG-vlFmRFMrCXixyZP3=P>5S=lLdk4dUYDXSP-Hrz%+I-GjCYaJul4=0+S%8d}g; z*Axr2HsDZ;=6X5hb74c>yoT1$2pnY^!r`35=Z!oH^wV-jY#K@&5z^ecR6JbLxFBRa zfe>ep*2QtUXuORFiQ-94D~-2-<8i~=j-#C7W-V+$sF%kZ+IZaOdFNK+DHd;S!h@WB zinC1Tkud7cB*oDgiyG^3YDs8b;{y0H!I*Hdk$V_{HZ;XZfpb_xEv?O$ENWOhI+XJt z!%3r{J;)YMQ zPnRr>HQ@Bq*5<__2#@1RTW|=7bv#TpRJVwNzR#_ zarVqv&S+e`Yyv0^!AmUEJbykch#HUcA+K(ykf!EPJ(KW6#359_sJX2{?%HsM(dbaP ztu4M7=g1Nc@l;uyjElp0A&c`Kpf!Y?bT~|>j&xK-thucX22giJ-O{5#ErN?hhc0PA zWE;qZ64CF8p|)6aj*alHUdreqyWm7&N(7_Ay;H%Mu}*;hLH=o@jwF0o;fbL-9jUtc zG33Zgn&&OG49{v3`x_wYVk5EY*U%AvwvY&V*xgF$R^T$OufS zYiq1GAdX?CiY*0;EF67&r4$|$r7%&C!`mhfZ$rt!GA0j)gd55c*lbmM3yO(}fwIz4 zoN$a{s43pyz>o$(8)WsiK3d#Vrp zD&|Kd`9zaVBxlYETpS43*Eh7pCWek5b36n?LgH5%I5iYF4~icZ#tF`d+_?>~j)vC! zjS+6DoB{>)3XgmcdjW=gZ&?D8Wl{Kv4nf6#PNnv7;_!uWK=b7g>cFWnlt`29Wq7?4 z9~ySWS6f5FWyppoXcy;_!4#%}9v4%zPL}Xo;u!*4=nikQB`%6k8@w1!1#D-p+5|z# z3E-gsqX4dQ4M1?m+nB<{Q0aaHf%=NW9wlKE8Mc+>Q@)Ut0w-ViT3&ncHZ_Ew_j&n3 zc6d9&?o|Q_%U0k>@A?L0@Od!xvVj4SW6bb*qlcrKn`a(F!^h$7+*vbGvzQlnCXYZ( zU3=r=_+oPiIE&vALIP4iFdnX24xkl-{1#gpnAb3W5f3$6 zaAjjlpna5FoHBFP+~f51o>?Mr!37tLQq2e)&u)^9g#*K2<6~l=y4f@_V8*k~EBkP! zUEj0COt6V9jbIxLySgX+_ekg3`_c5nLUL)qCA(r5CY~WOG&aNbfZPlUf! zwxM`ik>HqhH{QyaBj@M8FE3JE>6haBY?0SNyTKw0{r?Z#3>zlm7U}JS_@yjV2C?&{g0kBlNg- z;TOQ!>OIb&zB+f7^cjO@eb)7QIy%m@E{6A{|YjfgEy=TacCF zx83@yrazn!zpM{VA5Zi>V@RmUL?S$-sB#c^fdOtMtbQC&fUD)7{CVJV4tbwQF7DF? zft68-k17O`E;Z1Vm7=hcn1 zI9NT=A9D8jweO7g=%7jrK6f5rI$h>(}sj#Js^OoMh5lS1Zb*)rn~f6W%+UPtBOO- zkd8imUe2Y^v_VXt=Pd0XC_p}Jq@_(Cgx%+IUr6CW$k{!_nc~78jA3oM+xaJNOOO+` zbW`4j8TJHADPSY5_{SD!deIHXkN8{) z2IuNZwmgW7UEsb8Kj->#y9J+{f@ji~GH=64-H0o7E4a=3QsAO4P|ukhi2 zwD>$9{=UVB`|!V6+-}jId;52bUz$VA%_kO@xTi?qBkd+?{RdNBZdbRhDw5efY%|zs-l& zS^P&ne1XNE^x=ywKFpQ_POLVIAL+xFTHKxK>*%kuxGR4gp0aq2kB_u%knSJLdq*7z zaP|b_dxH<>ObX)s{-Yf~7ZI1O*42yqEY1l-+C40I|A0Tfk6HRUXH#t6e7IL@M;wydl&n*7BkI$Qe_YZ9I;lHu;#_saW-nIC2x#sb|SbUKW@3#0Z zAO3fXH~H{SEZ*NI&zBaT;-l{?bo~SO`tW@P9}sxShkF)($A=$e@&EGShgtj^a?Qv0 zD2ux@q}`k2EPkes&nSz3&xen*cwDZIOCV5g@t1x0=@x&`hgZpS|3Jvc|4fT-^Wo=M zKF9j_Twv+_`D>1)KgCCH;y)l@%9XtQjh6lmAAPgM-}m7r{`~_LJ~^+l^!2u#;6k`w zaM1hsEVuMW_~_;9I`YvdA8zvVfB+{fXm_XO^GzRqkHx3@@CO8k9m+M&=@E-B^x;2| z=K+C6AD^c!{v#i5&JssE!H2(K>3`?LU$OW{KHQ|ofWW_f_}fC?Kfv|o+Wo=e6+Zku z%in+Y%m)^~#Yb=Yx%~sHefTa*|DF&3(&C)VrJYHq{(+r7d|!DU5cq))_beXtHHi zxBz}w0sQC!_*mc!x7c!2ePJ-(&f=93bMzgnr(6uqTFlFK0Eu$#@#BA>h5~d5op+;s6Dl zjH%%|#ql{vV6$x%ZZER<++hZH?U&07@V}-2zM=qri{Mg$A1@L|tQ0tBUm;(6m1@JQq;Ozy{x3&QNq5}BU!1wQC z3rXmu!>B0`SQv}7jIIx~G}d3%+|(tae^=fU}S= z-K&A~Tmoi#Pc5eMUfmo`pfvfrL|#xW4n1fHh_sbnEq5tfoe?Qv7y6R~IZ3#kB*-}7aI%DTvJp}^j1!(G3(d(wbBf_Cp`T*@ z8p%zJh5i)bKf!R8x8p>TaU#P>;%l6d#NdLQY&Z*_@xtdMK~6Sr4W)^TNO-bvJ4Nu5 zg?_w|-^9*@W%vlsapLO~^Vhr;`Uyr_3F{OSM-vN?aDwokU?|1!1d(Tga40v3&|{u~ zNp9g+R%!?YD;MSygn7AmFBi6DrRG8Wmz&qtw>*@U$@{WW6F`~qWX-Bfn3kJhL{?{% zrRJ&3%435PQOm4_SrfB1RvMU!>24;2V2V_{rM4ck83MJ_tIwViuC6_M+O(NfvubCB zr&L$f8q)fDnQ|Gxl*{^-r4~b$6vwllz$3}X-)=_`CcM>4l+3#0yMO?*>ITGWfq0Y z(h_-_*UdyuL)q9gzj=P3o?$O;Yien2Y>L?!T~gQ9aPs(CGeOW&)LDYs+O}97%BcE< zmzk1F*w;6=EVX4wEhbK3DpqZ6JtqRyUQ$b)K{53UTdjnPjUHH5RFM`ROg~x z5099JYCOt&RcINMdh@GI=5DOMx6q(eCldz$4bZj_K{B~6 zGtc!hVX79j(xS#Tt0F@aZ^~1(ENE?;*$_KVrsdAWY$D4{GMbyWXs{lnm=DHTRQWgO zwV<-Iz7ZyKiPV1eu+a9}w&qxK{7OU3B*zn~!&YX|#m!5sH!Cp{FE8>mFpB2Vm`~?Q zhB3StObg}*YE_G&F^L?I5rc3sqlLV)9GAqwmF4e;{$}7)m0fu3sxUjBi z-Xa*fBzS&U>v*(JIChPh@Z#L}1$65IH!IxD5%J>*+aDvJRf_&8i~H&SX>nfIrEuYX zuIRs|@B`7mr{in(wH!US-lZddO@A-}I9_hS&(U+k0XoWg8-5O#%|&~`Pepr{j^6lf z($Uu_{0@b4ts@=fJOn>Sf0?4!a&A+&mh)E%U#W7*m3ePB9>tT(;?^X2MEbh0rw=7OM`K{K;|3`%% zsqk)vhZMfc;?%?U6@IYodXWE73Lm5JqZK|?;aZ-V1@L->AEWqOrf`lux_CWdamx7v zh3``M{R%&PARgdI{{ViD50;RKBd+N$usHSnAbyViN=2{Bu{#y6`9GrYhZLU$b|MM+ z>vH1?g+Hw5-?TXOU!w5eTb%Oia^Qz{oQnK4pYPZy4WxfW@mX%ismNdFqgyRbdYykC zR`kOapC=T(&PO{He!rqW$&PE0|Bn@3VR6cHtisPw^qPOYqSyA>qUg2!Z(5xCS*iGc zp>UlpH`+l0%J~yTf49Z`>G)4Yf3uOAf*V9OI?)^(hM1{1+%(^G_>W^I5HMT|OLc2Y~(I zPExp*v(@6%+j00g{a>f(wLDKL`VoqLa{>Cd75zv>|E|KHQus(VR^a^dS14S|pRhRP zr>!{oS1Ece|09b21Vz8D0R8#HKm-N$wE$)~9Jw>nc`zH#&ONIM& zHeTTv-}~@$@eNzt&;J5NulfJN; zI|~Zns|(-{EB@MkwppC|ISD_fpSKhrUH*Ka=ucMk|4{T=Kb1^WIPyOQKgYjX;X1v} zSNH@)|80erEBreO*L)tdxIcaWs^}*wK7Y43(?z%c4`k;7j`E+1pOgP&g-=rWG>bD_ z-M(6&=qD@sB?{N&%p(dvP0{~U;hO#(g)=Hn&W{Ser5suX^S)6H{$2?_JP8?6uw8{n-qTB z(RhHP-YW2Od`2rgtndj6*YYlLos3ELE|^ULoQK2?SLfx{|orJ za7QZqMTM6s{3V5-V{yi7n!@W9{r439nWCSr@ZfMfz>!Y`KPS&5i}wSj`=@b5uhaKx zg+~>igu>5I_^k>*Q{nemoZ)_7;lES#I@~`iT!;IC!Z~-x#p`p0>u?9Ka|`DW_ZW*) zKU!}!3a`OC$A5|9^MJx{wz$6>ctP>e`QlZDYde2W@!z8O?^5)-Ui(VnnokiM6L5@| zuGb#1IQ6g?D_oZwl@_NSbUSL6qSxg^y~58`;a;Y2E$3Ah z_v`c9ihiczbEn1q_WYcppQY%3tMKy_{%!$2AqoOVJ?s29Q{m_1ozwqC7Wd1uO3_bI z^miy+*Dnt%T!;I-!Y@#KUR1c|^LvF?Df;&nuG1^P%n8T%K7*f&*P#kur|`)ZXM8s+ zyiw8XaN8BG!@XJIvlX8^6n?kDzo+mE6~0m77b*M|i~G~%_liEE=s!~Q+Y~;7oozVk z=VJVve&$)6{O?it5{2vhl2Q1}ivD4RzoPJ$EY5H%6#i}j`p*>oHxzw8cK+cgr!L11 zwmA9E!Oz7jRDgb-qW`9%ze>^nK;f$j(C<)qv7-M};o5$RI2Zv(Iko*9W^unAj#u=$ zeX>;HwczFAn^L&WM-M7o^Lb9;a}}R07WeCUkD{+r^!swq1kO)C%HoW#4)=0JuiIDm zDSEB9pDJAI?Q_LvGs19sz^o*347XU}=P3LVg|AS!4)+d)>u_IDxaRX4g=_lHEbdR= zgUUoq(c7y^o=FyGG54Cn7hBvPuiF%#pDFrh6}^_{b%pErzO8Ugzf1AotoVBz41%LP zkK^a`f0V-KD*ObC`|V_$!f#jfixi)Fg~t^Aw-laI^z#({ZH4Rl`f-IfDEg-quJh6B z3ZJj&-?q3vULPs?1&aPlg=_vtj{^}L^{MrLs={@8RViH4HxTDZEAD$1413h0j;`JcYMdobl3fexY!!pTjx$2uFF=;OFGIQsI{? zJZW*i-d~{*^e+~m|A(T#O3{B&fc}IjAcCX(TFx03XMARnbGgFbf*+@!bqfEL!e6y` zA7EE2{B1?A`QI=VL~x{Mk?i>2WO2X#f28QIQS@sI(7&eWuT}KFDnS30!hfykhgISM zj`F;XpOf=Ui&OsV6h2$g>-gTG=sOhsdPV<$!v9hL->vvuujmI>;Q_86e!3i(YH`YW z1Ab2a3lzQ1?`?`cq3DwZ=pR+|C5nEXqSx}gsOXc5{tZR1^|nXRrxbnhG(5mDzFPic zEYA2Y!_UQcd;$993cp{`|3cxq94?v;A~^D2j-TUyfW;|~mj7f$ze3Sh6rlgMqSyK8 zo&xmmDSV^ie?$ZiaFpja_&GU`SNJA{$1Toy-KX$X3jdM9zhiNKyJfwi*ZE?b#r^vE zx1vug{(B109~A`=oL|n#7Wd0D!{QA02lzQX%u)CQ3cpJ6Pbz$cqSxuWu`h_=$p72; zIsSIoL*%5aJfoIwin$2RBFE96q42vDe!jvh6+TDdnoonmb$!RS5FKT?5kD6$%SJll zPvPfqVst_L2IJ?};TI8vBYubIA}cB!7*Z z#GR|KH^lgJ&$E2^$M$)l4|n{T*XSG{w=T9z&^+$;=Mn)GeW|sBNmgFR$E|N);ln$u zJ>2cX@3r_ZeYjh%UPQ(!T(>U0!iVS9rTcKV&)17S+^rAid5M~T*Ff_evhm|<{@gn4 z79Z}`V>^3s^lsfX_Ya_RxLbF<+lPm&L2+Harg!V5Z}s7By>yokck7~ytzH?fvsLn) zq;S5w_aLIMZ6EH|OaIP?yLHaD4lw>)yxcn5!05K6i(_?{;EH7;a$V@|S{oMCjgB?6 z#{#2et<304+S&r6Tbubn^0LubX{R5tXfEexG?wu+UWP61Ehe7u79K`peGe9*jm9SL zi?O^VFdEyUH;kTs)_J33^_TU~u&{Q1YaLb@{lDTu;6jtNYRK`duy=Rb^3%Q0X+Z2S z{FrnV_-VJW-8`+aoEFf{@1R>`rqM87$?7@y%jgT#eeQY zhQjS@#`y1tpY!kZzdta)?&)*b5Bb-$>CBz^>yK-1vXgSg#fE;xP;+HCtoQxlGfjF6 z|7~{C;Z`~i=5a4wk10F3JfvLdUiSt$dHi^JQ$D`@WJ5A{;B{5i)A|JSF$xAw+lxPg zoqd!I9G42Ytq6E%-9$3W+mUV&>?l6CI zMbod%lr76|ejH?x&Phum>9^!;9yzfm65P6zoFkbG-&d#qiUUdIjldU|bE zJ(}2b+LS%BwiT8A0^&!~ecO-b@xVp77Q8*^s^ekp|Lm(JhKm@ zPo|Mf`&<#EY*%IZ6I4ueYrhh_2;e}YElC_gc8^dcW+PUS%q??y8M!%9{z1f>{#G>o zD_}E#)!+co)N>@g{!7|Iq<+gYa`mP`gsw?e&F}7+^+J&-_9bschj4y^-f>8hJK`#m zenbLEKf)lR!4pd;Fj5XlVA3&uog@GfK0GJ<%@^jcie&l<|LXJyIGrexSy6$cT_?e( zUXFN`+aOJ({AUsGERiKI!_s?kd}zP!d+phuk^r!x#>7POW*l2%d8b>~T9=ZN+kHeEXhdo)cM!0lr?4aR!$w%=Q z=T+fMb>3uF{4e(2JwB@H`Wv1kfC!iq6%}uF&_SUpB!CKnnt=(-=%AE<;-w9k3q(Sa zk{Q6(%izoi;~1qswY3*pTDA38ZPjWKMIeY0v8_ez#Y?StX=Mynsx9ITp6_?1=gunhU$Cdv5mLgUnOrpUmf4hh z7#@VPk4mDDGvmd+;+KY3Jk4}p?q-gJOYSSN(p#aO)O4t^=fS+*C296y?o>Q8@tGv% zj&XHv>F0>YSg~v8K<-`~&fFfT##K0Tb0Ca!G?NOt(O<_$lFRDnJ~H zFa^y?-vcc`85HsIuWoVo)Jp|e*@in?xU+3EFfg3?a3kO3L~$I*nkbAt3oF8%sX!$_ zcsk%iDlI;2CoTZy{*O1RwuxD4lFC#wccXpsMoQVb| zM7g746j$NcSYpRUG z4Z`_hoMq4Vo<|DL-CZ-VgE{NT{5IkgrzF?vYPsOA=b-+p-#Vu@lKDK6c_Ey6&iKmY zu7TMnS8fLj)I`yY-A@iRL^!jhy9N;>afieA!E9bOCCt=(lEzSWWH9-~;Mf5C?H4}^ z^sFVSUh7RC;z38Eg__iuH}#KtWa4A2 zFvRt;w!m(8#;{PGL96|GSDf(y;jN5WH;@=U8LlG!q`9FNgaiNctk=v>C9i38DCM3S3!AP!%w0w~Gy z_8M8S&sU9I2sZHV3}@Ou!s+*8BO=*bjj6sTtqv5Z{eKMev%M9u>mn1M!Je^T2F|gQ zK}pW2o?Xh|{y$jKQ-zc>YSEIO8KeFY|F5RiD5Xq=twSUY2@tpnLJcQsankDnB7N(Q z#kuD6OSDKsUJ}_D zSna~2_VVn>FvX``{_ zL*Ps|j6?%H7(13(!CL>XC_W}jazn7SB}*_fcL&Tp_F6Q%*cVJ}n8K0J*x|v%< z2NLRqrDa=7ebG^Gg)=YYMo1>4n10{Z(m@P*H_lexlAhm&lev;eXDm=6B0pDiHBndI97y1~GwOC*SN#zrF1dd+uwBki26o`wtL~g&>Q1_sFr@S&GwGE_vc{~AW*b>o`iCJD&H=a1tjw#O z4ji=#cAy0bx<6r%k=pDW8p&)WpJCxlzd+BB)sczM$7&;^o)4G&CYtRRK)Vu~3oD13 z?!q3p@v30r$$&J7n5n~J+aj5rpxf9FT-`cHo`7BaVcL&%c+$E@iAFbS0&3!+BSs=b zD6=`7xiMS)_B?M=V?JNQz4v^vHeZOJh`W3QHrM3;uVPy>Y`N9i;O8f* z;!9+kI&K%Xv=?A^AmayaxXYmZ`i<`re%Hufj}J6miLcXO1H(m)VAQt6KQlO|w#L5< zyK?p3c5^s{#o=McT@L*tM|>mhAAXJ>r%{Hg@b}Ap-(KD|0L`UlkE3RcV{9z^5YlAkH-)A2m9tEOJ|h(OD`TIJ0xNE zo&ew$KEol?WI}`I+DO^2+3Znb;EQkAq}u zA8hD?U4TG|jd8F`Q8j|Sj31BYVmz=1N^(FHo3oVeJ&?(?!IFN4#qkxM3wr^bU!FLu z^zQsVI@5(VY-um?((W!P{Wwp1!C>l%H3N?a`3F+l{eB92?#wE$Y{EV@0P_3POdCAk zg9Hcr5xmRtnnhlsQ*2dKI@RbMJLAj+{EnqzZ?Mn!E-J5F;Ngz_g)Z5s9z-p2@w59tld+9d9A z;`$-?@fb_*-n-}V7WYcZbt~j^f}9I~&Xvplz7q?OTurt3I1g_8*Z_H7OFx=n=~0FB zI?Rx|XF%Cfl=Cy5(cOrEmQ)u$@KdKeqJq`r!hH_+FeLN}v1> z15P=+(BkAF{uk%ti_ixwz26#;_+ZeFFG4@D2+qAk81Ht=NBl4N%(XZNVR(qo#d)E{ zcUxTiC2;Ny)0f^li{Rh0d{$eBBt8**_|3V#_&ibs=N>JT-<>-a{|G)?i_rhE2=3#j z9Gmb_UVMWW+ok(D@GZTjHh!>j^n?lKv#|1AQTafre6v(OM=GBjl`oCTcS+?#r1tBm z{5a}_BHt8kQeT2JmwkUllb;-{Yj2s~+=}o2)-T03G_k8}Ya2hwDBC34uOEWST;)F% zxC}eW<1>Q#bEW39l=5*v&(}TmcR!c*{_v;ysww7;^ItKgo~%fPuU~>dw!1Y_NQx|t ze4voB>wEi&#QKG8?fN^3^+;~vgR1rRtDwT6*GCoYCqjFD=uxuIewozshokm9_?UH-E2q212yu=$yLe2|mn)omLhztGC*kMPyWdtMAJ&mB zemn_r5NA1d@o@^*^k*wv%j52S;pH>O((}|Sz1D9MXC3Xvd$+~O=R}47LeXnJ3v3nW z<VqjSGcyTpD6sxik{zU=Rr9S z!_VdOn8Ht1_~!~AsqimZzwedvVufq_U!ia<=l2z^<@~9|Dd*uTUJgFl9#MPY;t6}-?!o=m|K91r z-FD(%JhZUYJ0QT+KcqWBJ`Ctmk~%})2W=$f$q)$lB<$Z}8pO35zk9B> zm^b`DR?0XoHK+VvH~nt-i|~Zk*1Ym`?l(Jiznu@g`o9Di!&ma5I?^_NmVbS?@w(@E zc<5ehx(97|jq%z`%YG;^ulx_$@Rgp7b<BjME!GtHr+J-+dGw;Mn1b&~xh>Q#E0t zUma!zl>yAP`RlH!I%C54@do){UsE;k4I>NxR?B5I>deD@oWqd`98Qdev)3=jl(&=O zD#UC$fxlQtatr-=Ge1?ecJUKgq3da?8Nb#CsE< zz5X?M*j=-nA-jbgufo|4t8g+8)4b#XbURKKLcxya5>^IuBEE2<3+; z@-(|Xj7ty^;bFrN<>3mKU*1;j+qzN`QiwaAvhnrYCHdT)pcFiE9hj4{vzp=Tq`a2h zsqU>wVYM~63XY(}BwWIsq~^qEYoCQXH&LCK(!zoX*xgQ&WpAVQ(=R%=*Vt_59J9@+ z94U<5eTS2Y$jw<8p4*Czh*vT?Bzon`U|GHFSg>8WliWM|JLr9eGn;ncZqJl!O7LJe zF5^>!v!k6qqXb5p%)i}vBqKB|#)oA}c0GfZi>7GSMyx|ki@oru zKUrd|fBUHr?;03<9E#i@?tY4=t1y-IJQki{NrSr@rC@_^h(?2)e4}!@(^M^wxtC!< zph-kZfN=H>y0>uW2FVeZg@lJuzGQ;>K`X&lhcny5AHN))xZAn)#{k16kP|b4;mjjU zAXe?k$z@Ym4P)^>V{y{WNRWw%Z3!!20+$esEm!2?8~K$a(4kCN%UZ7dthF1}y7NGu z8wQ5vIVKgo(yR-RKx(wkg$Z91CKe>YvzjE8*ai$P!;1g?)Wr zTFN{V$7)WuK!h@Pp9YN@Q)2hb3ZB`i)3tRaBP>DW;pBV$d+v4DXu5O0$|uvZM5|oX zw+js6lbrN8v70Vu)!Dqrc5)CRn!TU4w>6o9A(mhU-AVlg_gHh9-O!Hb;mp?kFJSfT zH^0q-GPCVqU~3DHp>2RHeu0j}83)Ahd=TZ&}5d+uj>&fd0~hLV2qx`3N5towvl z&d3AjmRG^Bu!bkGo@vROfpy~6Xq}qf)^H1se2}rD;S7|oJnV{<5F_q#Zv7pyo+{^k z_B+P@jhPw8RN(fc;l@#{o`=N$9AHeW_IgnLq;Sp)%8I}g!gYKu%RBqFSNcCs!In~u z((M-PV0VqT7*};&mOCCcjy0;TKAl@1k?O#fXGu@)bwJR1L7%mJGuAF=bw;zS?$BIWMHJ7I7MxNYT;@lV_lH6OdsRCrC(sZVD zhdY;-*x7wqsuRgP?W7I`!;NQy%;k`nbao{3Ozg{IsN6u7D?l=Tg$;*Cy(;O(YFr6n zP4k%uy(s^x3)t)D)2%{WZ*KK6W2O%zpNBteE^9sknSP~eD?8JS%@b+p&2*HA^g zNWl^P?7)#xtP!n5Q;X{DoE->&O&~!LGXD_H$oVwetIlKB1S+GQSUCc@BAxMmA_o@i z2o>W%_-J5c)r)5Byp=hIl_FTOok~NdXm+%_gbDg}QeOw=F3rGl>dq@*8x@FOECfC( z^9qD;Z9d%vk+H&xo;R4CQxVC={n5^bK;`2`+ILNa5Fy|^hFl>Hm&FWo9)qTl(g3n+ z;_lm6~1$7+U)RGjoxqMa)OM~V_a8E8sE zSEcd6nU|Y3KRb}R9*c$LelV~Bp$`O-n=F>R_6sEU)yD@Xu7MK459K4d@5Df?Ha!X0mBpBDypI9lOM(dKYvLwf}9wD8v0OQAQma>P1E<56oUC z?I4#(ApS-qhZ$~h(gy*TvH(+hf?Zu%&2Mryh$Z#08P3`}zKfg-(H6(@Pi6AMlA6rs zrr_pn16dAh(tG0lQZL4j27QT>;#6c4i|fI7;H2172qw3dkXif>>%qyF{q-L}levp+ z2{aUASXO1UhK%)ZP5&2YN=)U%r8t>1sdIavc~gH=k8Dfj-j>XO3-sumc3;TrKJ|DX zf?7MtEfbwq7mV1$?y1}YP&BO;?~{A;Gx&VBNh$3qn+Y>AJF2>BoX5634si`LuJVEx zAA;O*I~RQzV=n>IR0gdW;f6p(ZV!e&sa7Y=Rf^79Q_F-qe-Pl@&=aSD5IOQJ zbooZAD|Q@e#>u1cszL-E*>JMEWYzTjL1%5hK&mVLZYYCVOhn&$kk48B+ZtzW*G7&? z+mhI4^5Da&x;TB>D`{1b<$pP8ZcE)HXao`@S>U!W+;-u}aP~)gVFRl2MPt9JYu&u} zP~y|C;iZ(9C19AZHqGX$ybtJO``OwBt-wHd;+E^sxP;TpdyV*HG@3?YmAV@r`Uf0F zMFaC?Ibm%#vcj&j9JK{2#^W2p-CfAM{XLIbNvoB=&97ia%R0HMGL-!p4K61T1g%GmcFbI4>h-op+Dr--L4);1%hJ0rSl~O)AW+^X{ROxy@ zBrE|!lwd4a{}9aG*hO|k5X?N|#(@>y`(xieAf~O!)hwW)%>7J?_==EQy0U5ZMz<#4 z#1k~YyRecxyMg4=%);8n{oB#28iX~!wa^&sPnJ8HBy}grkD6TfW$@2c;Yy@xQtt$r z9xK|6iS-qfBAh+XNq+|y$@P3idU!bdAiDrjEIW@)HDfxrRpWtaVqWE|+GZM4R*iEn z+nT%&EeF+IXRDc=MAOfWbb~jed5q0=V^N5Gf1I2sD;g+x&Nm=TztmOUrC;m0hwXj0 zy=;R%Jy3eig?Crd`#B;I>u;WCAu3|aym5Iri@z;<|J>&j!vn4TeZ464NB-ZCc@gy3Pe4t#vJaUlL+gkT_UY|XccxLqlq zB$1P9WPNIqSiAIG2Lwn(q063}hm@1=scJwO1fi0l?qFE>XOHznu$TuQPJ!8_6Is?&f z90NIBt-$ut<#SS}F<|B?%UzU=mC~DNGhsA!wRXd3?mDS5CM5mhI-%f5on1{H%}N#^ z`BmHaR^Q*Ft}kP=ERsP23_)@N^6A$I-fdKlm}Yb?D9Npm`l+fbxn6R@`LE5+e|0%) zx6PRNd1eSAehNWQAx1~N>%IXIu7AW>!)=nW^+VwMCPh1kz%Bh9NgDM$-vxCSok!t# zFn}tgkxWUrUSf}C15Y8(oz$;{JK9V`185@++!_0D|9&jwMv@uMNsmFYv&kXIzU1Z- z%A3hD?unbP8C}u^9c1KL_)fe__zY6yW|!#CNo^H%O8WcEg_}^5M>9LZr>4b(*a!Xy z>Ojw=EB86|l7A;jglz)3&DhH&q-kvj6W8?HKL!{Sb)t!`)Kgn4;Wn)OD-Tvf8Y8pAaV;?>#Ps5TZmjH#tRK-&5&mr^Ee9@$I_CnrDU>kM1PJ89`nyWY!5BI!2$LUoe#DQ6!}Z(U5}l;=}Bu+@s8Ze0`hwAa^&VMnv-v z(Sd0d#atm_5uud0{S_pyqFkcibMaKN1^&~H@3ZzDnAntsnZZ+yanh4ukglH_2@pK8 zC!y5hrJzU#FO}l4liG&|k*qNqqYAvpFb`e`FJ3M$iDWj=oLmEljdM0G9{^JnU~+J4 z@<)gbjotgeWpc<#uf`eS)2we0ST$fp47&MX|1`dY_e>8HfwAf~%%H z>^Xz&Nj+J}WA79iI5I3FLs1S4i* z=^V!1gYZQLMdO1^jI>b^E`^Gw;lkYKi|jtUd*zl{F{X7>D@WmnR)Es@JVI}>lmN@?OqBx;?!;+*t( z5Y{Ax`CZVn46s=`8w=ux_*Z0C%1lOA{IaaPb(tA}S*gUj8yP;{lwJ8U1mOGm7i6aO zdz@K{%C6Lx{SL=!lb`O79Urd$B)PdFGjyZ08ee+r;O$77(O*^9M`E|$c@b%aNu}Ad zmUf+8$;Koi5Z*Kn6CU#wECrvI)h-<$&U}Q=B#4@vwTGj@wI?*QWFWdlYimo)<)OGN zHJ1Yt-z@XTD(onBo}Ubtsn=dJ-35COqK58yp3)TR7i(FG^)j#?pW8dPIPK+*v1>ct znv~)BtqFM(H=jB2Lz7AA3Kj<2i{#Hh$vT#A`%Yyr^Ka9ZT(N5|6cx?lW$R6IVFIdE znF@sQh>am*8t5wc!3V=(4+I_s$Nd#qi5?z?A$g#2UlUyM#ourlYhhDZy0y=Qv$qSc ze2Xfx(@9?rd%)NXqj!5Jg?AD$!WTaToZbc}Cv_uetfoSl_u$>&RyZ3jdDrt}q-*0y z+`6?C+_;na1}uvs9o6B^h3MU4cGnb)aOV_!)?i9$xbu9>h-T_~$i*GRjtE`j{(Qkw> z>@yj36ObX}k=9BlH6PEJuNY?9|40{Tf|+MCFDM7-rloggTy|+6`M^S3$cKz%0M_6=v zfC$3^l z@ny5}ay+-?)=6K8o7{O40ww4iFo6>gK4{}olH8m5bTjX(!`TU#dgBv2I=IhJ=jQ}v z%nP>l3EowVGJsZQop;3sPB~xOfP{ zOFS44Imj-8$X25P9UBu)Zj!EMY=mAXVduS6i=v#>X|*r+8A>Spi}A2rbqEiu+9w76 z$>qaJ;+3ez$)44CppOWQ8X<>6_93Y9a%l@#{#-EQ<$qM-iCb9$Vxhd~XFF?u#a5fM z@m97OsuTN4j_ykC7?|t|PTY+4QT7Jb@lSBAYj^c9T>5hS?wh3N0>sx_{=~W!lhUpP+cZMitaNu7v`#CjPl zaMJhU2CsT2*R>#NrQOL&sELPjdskw8h8{7K91qM%vAG8eSoa_;!Hpn$8%^0sy&#w;wmVJg{dm@MbD@1> z`k%1=lkIqfQ6iLFU|W%UAn!jYE!)Ij%`IVHcQs!rH`&D?xe91O^h!EADwn_mNhQKn z?Lo+A-(Y{S+d3ATD3|T!uakq#D~3du{}u5Qy%Xf5w*WPXVrR>AOO5|nO^eOW8kT-B z-sZMrFHWrcA(e%C5Pz`%#+3WQ;vO2)b$FCmCqrCuETZZiV|<8-?RXHG&s4#Fs`lhE zZ;CTd0fvo9Tbd5>3I376%N)Da`F>Pyrm_32-#Y29lJ0PJwU3#M9Le{aTqoqDz6tdj z`oubROOZ!M;4e-HgOgLUy=NP=SIFPs9MdH#teP8!-VsM(SFS*a75kpW-^@$#G0D#k zkDZtN45MoqAj!{;5cy*v3_yK$WNZTR(|(D<_(4@|OFklad^3sAPOv@0Z=s>J`U%!) z78hmMhqt2+Q1z}`UxC3oE{`-+@=dF+VyKt{rKK@=HtLk$?Z9^wP#lb=;CVJOlHN5R zM+Ptz_FFztLxpCXW;FC@>R)uvIVK>(NNkJAFjDN>-cczh^?MH^6nYuRe1*6*W;5XA zq}BpEki#0FTdPYjD)6Swwj4XFMvlaKo1bDH`TPv+&IL%5AMdh8>CWclzuRKh6=JMz z2&!9Im6&;hC$z(cu*EQmrA5|N$pVkla0@-Iwkm}_#pNj3egF!iEg!Dj{ut{n+S1Xl zCEp&H+!CDdBi3lJkIWZ&(PXh4ym{si&c>I-I^gXN31#l3yIXY^12BK3zRrAy;6_>@ zv0PNVN+G>&|0g2fl<54WtY?yscgziCH*#5k>HviTVfKCop!A^cGXXr&;B5#%ILtN0 z4#u}Xx>=RLRM1n1bl32ji-@EhOmH%-0DY1oUEa{mqHNciz?W0AS=IfS_zas};I8tE>rek( zTLtI&IXZ(CScr<;$;bYNgxSbpKeyQMycSg~?0R_+MTDK90pJcDpU94999jDar#j#C0)ZnDgf@5;mWjks5onZ3XVOW)RB-E0AKR&bP6t_Gw zt`d~@kXa^NgC^27mN+LCpI_aVc|$GPHFKp^?~4#$t4pjuj^#IgXs~+#LaF=>XR)pa zNPbG2BS$BIn5%k#E2m-FiKgjpKgAcyX6YC*&!7W})u6X`rQZ)`2E>1E<8xBKKx`r| zA_g}MRtHKPK!~jECm1ytLx$xoe9elVoDWW^6qfxRm&*a$ufj-!* zp9$t6)5or%v#!J=#Dl*Q{+~Tq7V(UHg|T4Ivi7m+#X=5&Vy~(%tKPSx8BXdlz=`!T zqv51x;D&iyS=IG88$2_zx3bY1#PFwWHHI^P#&W|*<~zhgTx^Er5N~)U@R-;c842p7 zKSAA@TuOPxaHeYCv{FsByl-$P<#QLSG_j5T`>8|~Svx8Cb`l-{9vv$RN)L}KLuF$Fw zClxm_%I+1ba3TT4l2(zE=K4H%WA<;5qswqt5R@%o3OfH|SI}jM(RPZgpqXcky;pUi z9=sh*lL5I|6btPiTi3CGgAp2=EOrNBQ0My`)QOt0oM?8Elu~CUKSGdAnxe^=F@@Ie zhH%Mte%Y6PH2e5Mq)FaN;erU7CKerXsh|6$#uf~|;p>a2=_{ZDBpiRQg%G^%WU4hRx?mYPuQ?z3Ktb81q3;fnnN6hlVI-s7PtPY}~I4r#ZN;uTAy;;j zr+bhJtO5*0CfCcN9?ssNpD>b%;7T(meH~2={eVggk4m!~qxfipql172*~o+$_++LC z8_Hs7Z|0fciqF{?ugUz3jd3S+A#PZ6uu`nyGKw$2I+T@h9<0t9?yQ`MYRmSyFf#(* z@vU&lv-@}8A&U4yzmp1}iyKUAl1bh;-pG01xn&{V-^RBnDLn42Ifb3@PBv6;*@>so ziGOo$c>@>Loz2KBSdNvX*4qCjBIny!n2&Ln%pxM0<-^)AuEq*y?yttlNliw%kacs+ z*#Rwp0sPreK?iHetEb@Q`w$LO{G6Rg9P!S|`N`mtgYqYn{|+x%%P+ zCp{c_0y?hManeI^gYjLIFEzZCdlkfXp`i1Qv@o7!@D-mwOUcuJpyUv>?6>laBXL2~ zro>tdL|5u7eIlln6#VS7hK zx}QeE&}lt&pa8?1^gj_+mMxhK!6n6ba+~lOK|aYZj&)KmL&p&IYfNEkH`tMC=`Nw# z53dL-x2gO3`vSfP5P5|#lwwA91KpXEYC<}Joeb?b>A#`@qH5+3f=_a6++=+=ZAQJF z^lPBnzz4Z+gJ-Za6>um2kIKquapz3725&P1$3Gebp7pnJI5$7k$;KwfgW(jn@6DU_ z$2QN=l;cd2RkzXg!;~yrmX(2OzIs|qe)UPRWn~e^lPTGr(ih^B+jz-%JvH= zsWDFgshyQ^bQ8Fw@Qx&BL`f9NuDTD8*w#)R#nBCSI8m&hOIl6l8{sPR!of&EKL~HJo98 z735(<{T``PZO{RN(&0L(D{*6T99p?$DWqfKHdKSsNK@jh>_BL;&%)55rUn&t>TnwU ziqHQda-1)DM%}DtLeN8sb=##Z@r~Kl_WjE|ALD0+k8jIVfSj0V%<}WRH7A8!- ziLqImvqQ9bJ%u}muI`ohFJQdXD2E;*_Y`h1f4k!IPbpUFV~Ljr%OiIWp5ob`aUI{u zaUZne_#Nx~`$jW5e`eMmLW2*aHZJsd{JwF!~=#AQRnPw?#`{Kq)l-A_3;Ov7bZ z-t-~X)4ypo#`q%WRxwSX06vlXVaK4!Coao@d~?U!lTUO~zm=*@)QD6d(!%GzZEoc5 zFi!F#N_|TYi^_j27DuCTWbzG~@Z|>KmWEdPk{H@&=suy)i7`4iu0)y1?F5uBFKz`B z%=@(zhn_G76v^H(FpJ31W4YxIkRp=pypNheVZDXRXXU+t<5)dRe9p3SZsonSJpKw< zLYcqizKO_8fFjssq3fi6t9%~hcPhm>*@Q=b9TRMOkUqG6ww$Z z_^E{cOk#dIIh1(|)8D91j0?}bi=LX&yLmi2|M=P7j}erL6@%NFD(aZXoAn^y!Rm(=S;Q&N4jfG z_-Xf%5oDB`3x@9N>2I*cwQ)c7;VThfKJ2-`3Tz!5lX7ICixDOFZU|sgkEy5qfUU^ zWd7&nGJ^tGWE$?Q#tD)-Wu6of9fk-nCZ!V>eXSSeo@1)M9ad!UF zB-rRUvw34lwRDoKi|70L?|DpyRryJXBG(TLnjF@}R2lZa2(P<3*4S|fnp$|>!rECF z%X1STkdJe& zH9jZuH+<256`rFXbZvh;x!zr;2ic|T5Y3oQP;O8mK8X$PcLU#+mPiXuBNqbQMm9`n zi{JU9*kWZNY$VgR+~qAna}Q&IJUjlqstU7c!L-<5wPn&Eu+4%y(Ezx?mQ5J?O9RMT@y^<6X~N*ik&{o1zni$a#z~#b zR@Z-!%Sks#yUZ2k|3cc0z$o*++#wJcqcw&8zdJq??K~aNn)XgAnH(#s!98vuBwCkWCT@W9=E2HsKXb zZ0nFob`e7wvvLKqa#sEYQAX-RXQG)nAEJdD?x*$e8QQp0cPj;)-fAv zSWO*`hlX?Z2J%nt_=1enZ?RQ-0@|1F%L{vuTln#dLs?9e-&QS5vA#TW8;8%r-PHrB zSe)5WM%RbTKw~sdF(SA#Fdcqw9CE3byprPVBhON7vql38I-^<4d_=POuM^12SNkRI z8YF7nOj4Wj!8ZD}X#F0U_i@q8CO*e$E>2dn43=1K^WappW^KI83S?dw>w%CXSf}iy z_A_Dfa^3H670g~dkh9~HU`{3-xbWo`v2I(9w{aMUUCm)#AeVlipRxmi6U$4GDi+N_ zNPRRb9p~WwBUxfI$?XUlI}cN>ATo*BI1Ieybu!!E>Bg=s6esTs7zWR}B`}CFBSDqp z1wh6Zl(v^-vuih4_maAm-eH!j@;`YWWSH! z5&GD*sI06Pq4urnQ6`<+F;KepE>2ulb!E)wDQIx%*AR<+3F}8}!=aq0%~H5bAa_EJ zkt8Hh)*Si5aIQ@v7aaB|`6eYK{Vtxe@D|J~DD8l3LYs6md7LUd#7qkE<~suO)toW6+&N!LyTtD?*MC<+D@Jj zEV*tW5?YF-o(Wz+a6J8BX9I|>N4<>@C{fC2+WFM5fI8{l$WymAIKUW@7Dl-LHi@rW zqD2V!2k|4k%w2%2DC8Jp|2qa27fC6S9@KTme`&sE|6Ka_x8ky<{8kRtF< zaXYEaP@@!&++UzA^k?$Mi|sh++#;FjaCIhu8A0%Xt_}|>xG>~F-bg;$sANP3H4*qJ zFKrFD0d1??FWFh%Gi_dVY;YtyZDcr;o{0#U@?Bfn~iD!}XwXFdy>J#i{9q>|iw;j)wL`~&7R z-06pczpi?p6OqHRrv>t#N0T16{YsjvIP-e${t8afO2r*JjS;$4;83?a92*qLJ{j0e zi`kBBqE=Xovk_Q-FZ6< z6XpD3fPoY1DK2aq0KN+dpX`cU_{tmtaER*Toew^UuD3g(g|AwGnx3p2u_x9KBcIrL zk>ryyf#JJu{C{pneTdL`W--4ze`Z@Fg-J5|hDR`a?J$fVOL;^EmiN(8tOapkV`1CEnv9nfu%E3o0!go6le2syt$0fJ;ohMw|iC|w( zob8I#{`jQ)dIJ01EvyMyO;b#MvOo5vh`64L@WdBlhmr6y#EI0_L+J<)8}+coT;MU} zdc+J^(n1i=pxTC_j7oil2~G4gdM!5zf(X@5Sj{b=Fr_Fe@>kY0=8c=5KPZ7#{mg9~ zFbgNNbLSnuP?ixp+HF%Fn2WttkZXf+%Q}DvIzG!yFMAZQ2-;@h>|x=F+o^z?17WJ8 zWHWkavGT~I+r`41G)MUJdGR6L1=?4);-ITZy%R6T8nplu;@rwb12eMM50ni1CM3*V2qNRx!l$C-I%)ZupzDlTpiKjj zO+G2!k}qxvX0b)Pj#H{DM!ud#b?xg;N7+IW$!J~@`oD^N@)_$eF+`D*|_fyU-*Y>3s>%eoIVbX~brS%pv z_urrq9Ph=xa=s_9M$Y(t8O=G`6QIBN)CU#DW zO3G&prC(u;F_ePc(5zoD_US){8R*Wf0mW@hch z{`s+3a z9gRztHZJkkx3#u5*2f0nvx>9BluI&TN#j)j5$TmzTSA-onX@i}^!2`}Q>XfBFGX@{ zT4PJD_P5WEE%Y~c_)i(pampY!pI~%N%?q$6p&wES$spfFwPVItR{Clqvupep24~bv zn=#v8g>nF{^=*q6&u=vw86sxv)3eYhe8vT$!h$IiXlPzyMH*2#zF|b=*aLpP>CH>A zf1#AAhPK8IF+x~NN6c5dsJXqJilE9Ear^uw%^hv6P*EGU)@hBM9&K!05L<{CS{mR~ z^7#?(X!Ns0`Wl)$=3m)D7Bw?x&GyGT<}YZ}32$ig&%9{XZ1SUerQq2z>7QR8gJdmN z5As317*uERZ)jWA+R_HI!v=~i4TF5s8)LFlqew5Rpj!}m1{qi2X1mpb)ea3J-cC-$ z8+?~Ew=~qxU(x_Om^pt*2L6i&!wREzyN-CSl9wcfbtm8Sx@f#6x7=8<;u`yS!u(Ba;$mV8A#g(jGQ7jzzNBqwGwKCCr-2nT z<#FD~sMfaD)47*aOFp#W%`nDRwf@D9`_MlPOVcsdzVb=pcPow4{L32sOXjyq$%jQT zyE=wbO}?5XOW=KsO^h5R2HDFK2@(ESebVAw12T#?jw_$+weT^@T8{4j{(I z;ii2_qvE-|85zbS#}IKdAYfSg+j1;SS}+JxDHsw=V4{*ZDfwHFJ+ zNJ~rO0_2@odTV^~m2lS0t-1~~4C%{IiRLRWaqg1hLYX}crSo+9E>zFWuxr?UUVpu- zGuYSit9w;wZaz@SZDcTVM8_y2)d+IQ`^IK?&LvPzOmseW>{+L~E=mNQE>#k1&_az> zk1EX-h>k}ry@O?}!9TXLQe^B^#m&DGhJ=R=@kUD1(bxj#I;Op?rNu8>l)scS{ijD`u8>==Bw2)N?*!Waz&nB^mB}&E~7)d_A(F{TZ2elcpi?N$X zR4GG|5Mr8@=-16(mX$X87vw+0X=+}ATmVJ9bx|uSC-a2uHh)`tjHPk`bkmA`atrwi zSADuwsGId>58<(6E5#)@E^n7+1@#;k^!eBlWVJeE`MKfpDA>&b^*({M< zwdDo`^(~F_L5X~@?#f?}BH!BB;vb1-$tW_%QER-4X+Zj~Zi|yQ2^WazFu0_EEeQz4 zrm7seIe{v4Y{S|4KmO@6X8WS^J7TBLXlrP0G7Zy?(}ap8W5oD|K0>flf6<=v>e>F0bFPfH#^V07MxQad z^7L_WxvRRa>deuV<3}0PO3zn%c$9o&mak-aMai*44jQ-`iJJh7uOIN(#y^FY zjs394cC!EU^2*Y0WAknx`OVI!50*WcIMc}EBK`?+Px;dGxk>zKxQ!9R5vCGrxHmmQ z-&hvr-t?uRvKxF2mxKiHy9YlWvZA7}mwRowe@^)@+y}v!ll8w9Dzo<|FB#Vk zUf{Tee@dq_vM?iq$jN?f5*!=PPusE;f!PJCuo)}MB9LY)8@6+YY>nk3vE6!H5RjsnFjD7x$OCVyQQz?h#Ke**!R4! zFZ=ZJ>az2SZF^pNM|t?7@|pGJ;i=`-V8zLc-In(lT$?@T7c*OYQT&E5J{+sKSiKN0 zHl^?EH>G^!&HY2=l{XFumQP3?bYXd7XxY!p`rL0l#B_|r?+VNBC%9%@H!`1-Wste_ z3X^K&95#Ee#$(P)@Zi1@jQf^S>@eS1Hl^HuGi~k0{z!9j!1VHYrB@G<9o~_F`90{N zxiEtL*7A6cjC6edg_3bICFABGY8V)zo;LWB@{v=^E9VJ*N%^p8#+In3VHjxT!PRBP ze&>ju7|(e7>|D;F6!ZjHt)9YpJwf2IWqs$*^ubpkc*64H2XV=(lj**h=2<9XWdpzg zf))x{&EN(g)5`r*%ZDKljA#1b(pkL=qA5E&EPrYLLnq17g@Z_q@B>4GFOW2`tPi9^ z!Ep}dKrumiy$B@d4-VmPbZ}`@=r0ziG>Fsm!Lu2dx%QoC$R?Y)_Xu)PKEMHwxmgu{XUO->QGCz_&5yy|I ztN(0+bW%U=(*%Qq#m~kpuRoAsp=?MU6G4@VvPs35l!XVwVfm-Iw^If$Ecc`OFb_?A z@wDZ44%1wattRh}3iZYL<%!bL2g+B$ZdaFHf^!hSH~JKI+Th7x=SLam@e=~+uGV%l}11Il6b(bnW(gw9eWj^b;R3Q3S(r>qzv^(?k))^>z zz9m6=KNEsO+M+m*#*cWrZA(a-6WA1sud(S?MNoM)r@dNxyd3T6I@-xdvo%gYVkD|mo^rjoon$OM;StCFX6Hlc!|#%JMI(av5#MM zWxQ+nvI7pOKXAU*;uXgTY}z}xywl<{ZN9i|nfoo?ew?9~HVQ7e?-lv)wz#xSfYWaf z-!a_KOM3v9Z&=)avcaX!#pS0KuRgIi{lTy&k>BF^HiN|zqYS;9u7JgTCmGzO=Vx=t zXP(8SEdi3L7Oy?NDCbz`d;+e2-fCho&2P@z1ziZ}HtMm^j3r znoG!2uoDZ(sm#~6w=44( z{le1E%p>NaRQ%n5yx(>o4-~w=uf_%Jx!mICc<`YXpW(revG^hn?zgyGPTa>Q3qHWN z+Xd|TG>gylWaLgI{d99{QhKyuyP&WbxxX_*#nxJou9q z=Q>V(JS8~n-y{FC7B}Uo5aM~u=VA|^KUjQ%2Y=P#t{-@z`hinDiNpfBQ)ju)psP51&DT!wx<1R#@DW;{u-} zExyV_f1KsdJsk9LqQ&3w;9P`9`FDBn(H56}rD8PR;{84Oc(%pA@bIa&IA6Ng$25z3 z%U4uz_$5!eW?A~-o_NjpOMl-a5B@bve}V^Zu=o@YewB^a=%XNMyQQ!5&@Z+4`5ycl zi+jtpY|;Wh!;hruW0j3}yPOM8Zn5}Y4}QDF@ATl`v-ms@zQ*EnJ@Nk3;;TIP0~Wu} zga1nK{yt-m1vwwL_(^gu;9Zu_YERRs+tM%a!-(~R~9{fYWVTYb3$0ruA_M{6%2uFWu->GPQ0|X!7YxmF}V)1z%{)byW zJsv&C_te4vLJvON@{u>cRK&*42IR-F+()A={j+j*QH=H4cvpD%PqO&K9(;<$w|MY~ z#Sa!e75LAz`1d{Zmk54f`}1p-zS_g5(c-f`xEXWo?>p1Oe~G2%W_J2mZt+(<`1OJh z@Kt#7>qd*;>B+B7i=$}wI&QQ4-LZQ2;dd==+Ji3Y^Zm%;=0nB>{9cQ%^rZIzi{I?Q z9}#?jZ>LB8CoJCO!8cnzi#&Xcef0MkKT(k9_mm#yWdNXbd>qLy$+wR9Q3xUUr++B z0!8pKMR4{P`{Hv^5&X&`c)SRnD1xspg5OmHf4B(#WD$H@5qx_Q{Le-3cZ%S#y6FD!yzQ3P);f?rbv&lJJG zRRsTG5&VH7`1&IFvqkXV7r}P`KeV(kUX-xj@1I5J2VfwlFZ~ZKf*)H1A6W#SPy~+@ z!7nL-w*x<{6yuqrOoH70O{xg}_ln>T6v3Y?g8!}v{#p_I-6HrWMexBGxb92;M-{O$qebvbir|xr;LSzwrA6@7MeqlT;2VqJuNJ}g7QqLjNYH-T?SPuhJHeEW z2HuzcM-{=x7s1aff@AqepZvMNa&*0~X$jsJYhKbJ>n-t$N35}q%P{2@FRR!Uk8-;> z-V$rB6Pm?X&McUHCrqw2ZJw$QZ>`8vtl?}!WF75tXJW#lZxd5K;yS$gu++y_mPSt; zH-3Vmjkna{J&ky~uek%SSxt+z*UFnBnxdnzj*BpD@Uauml!si&-O|_;gCtzpZ5M=@ zWxi9*>nV6?1IxOR_Str6zHeE59hW=THDH0SaKQphu#YckfrK%Wb`htpuqMT`*Tw&m5RBp72rS%ZLvCe(%KvDADAa%=C+H%`^WnKQ-Fj?FXTdXL*9&d|zLmDyM zWvjjQ8*FK5Th<$*ej3{9m{4Kd(AJJuCK`dYx&W5+^3nWwY~kpMXI71~boKwS2rC@M3H>+;J5EB4GxQR6oWwO=!j6|v zkPv|uFn+uGlj#M z66#EOdZzF{Q+S>!9L_ZK!t*Q>N_d_nVb2npvn14666!4BGeIcNGNFXSStgXkH9^8o z5c&zip~_}Yl{~Mq*;FZfCrZc(!exSRoFG&a%~KP;(w+=|2~kxgLQIq(Rn`jdt|5(~ zQsSN{HxqMx3I0M6dhDmnqAxRyEEf+?ZmOvAHT^l2x$ky6Mr2 zrUavP7fqX1TQj?Ec5q6xrp`FDdR7tUvb`NXxV53FaK{QmDg*I-c&_RUyg1WR*Eql9 zYSbA^4=5e$(04+}aqc zYmK$F8v;02yj-WR>*9C=vwo3*%nQ%Hx;ng+fSBv*7rGBz6XY=;E$(QQCr#iAXI;ODk=9YkHodW> zcoE0M;MRrtCwLvjRVUs$yRwjw_618iY8zwbt+!g%6QUof)mRl$FjGZ}c`!#Lo4+2P z-(ph(tv8^)mPcX+@z%zU`uR{bq2+b)Z^ZCg1yd>+Xuu8wP9?v3ylg4?C@h$nc+Vxz zesMmJ@x(;AWd5=`Sz+wNRa*zl1me}z;SJyV zi4*HOAbYE|TU+V#1#XkR#q(_*h~QRvA^UP}L49~V7q2JHvTt4+kyxmt-DO`nGpI2G zWF=m`wsgpmIqhhb6bd6>MrGTfKrkDP9dn0wrtpH2xo+-on<zZ2P9Sd3T4YFV{B{kQJ@t*HObGd9$!~CnwWqnIC-a)Ec zwxk)tO6H-IE6KHO;XOdU0B8bw6xZunivq^jl8!pA`0zf`1(+9LpAmyiR~5A zL=DLJHj#Jn(tN3s046DN+0b}pe1Qo=Ybsosrpu|ezx!pJpTZAc&XD7gBKVdf_@6D# z=>@JocKPg5_(X-f^SB(IBu|%qs+~V0pR*NyzQQLde742Ce6Cjb(~AD57Wbz2pNjq& zMb90mczEf#4u=Qh-HM+p|2Y=tiR&$0e7d6VR``ty*K+b}d_2g18-6aIFDYEpcPsok zMQ`Spxn>A!c@+M#qW_J;4`qZnNPjMVZoI=R&eIl!n|Vn?f1bjxRP>tvGR41I(O;+N zHUGO6eNfT=LeXpfTNM2iMgKcRuk~-{%Z&U}75(la^h0GF-q4>8`hQuwIZNT%KHc?h zWT(@0p`s6|c$+LvdY!HYj05u^{#*RqeEGS>nO`*u=lC`c;?wYR>7P@4v^;|_4#|V` z)A4iZhgsY!|2Rb-R`lm6`fi2SD*A}RIX=vT{55@tqCX$cTzNPS%)_gnH44}E|El7n z_3){p{~h?b{13&r9}n`^_$>;59?x9*Ut661;r9yPuIM$N4;8*$(eGEdraubfU_2<# z3;4P5o}lm-6+TYkn$HY{Yd&)nuKC=daIWcdUD3ay@Fx`hs>1)JaITSZycxT|} z%6XKc*YSSI;$H@>*8h2m{td-vzQVOU%N4HWx!&TGhf6(Od2UwpTArUNT=V&*;-k~G zUeRkl-3r(G{JY}Awdbxp{SUzn4zHabtMDCo?$V#5@HZ9yONHxrcPU(_>m!R(KQk4d zGCP$^d33rQg=_x96|VE8st7(w;aZ+47Wd{?gThaTO!&N;9E%kG6(FvDu2cMVeY9HP zTNV9x6rWiNzemw)Jv^jvt%norl3$8ftN5H@aq9Ceg-=!VOc&R4^EhAOvvKdH>r%x> zr)!bIb-I=)J{)p)`CPB)b-J<&*Xg=P;cqKGuPgi=g@2^*zbSlz9ptAT{;u!~6|VW; zt8ncPA62-PbG^l>#)}pIXB53o?;yJXnex1==!Yp>^B-Yx^1npUk5Tl$QTX`^->LAG z3fKJCC|v8|Glf5=_>4IWH#jJN4nH@4=O|p$*IS(O&sFqSDS9pcO$vWc(SOV0UcWu; za1h}j{(JmfdCs&rRjBjkC+YM&X)% zy~Qc#KNbC}ivD*BA9*Bha8Q1&hp7tJ{2#M8^Y=3RTzNJtdR^{zS)B6d{QXGr(RMQY zC=lWx|I6`n`JZZW%BlHZtnd#NeWT)Yg~Hnuy|(|m6}^u47m8lTyV2radw5mR>vAnG z_d*WRf28C&Z5VEFFuh;J&rNU0;!N+q6h24c|5o@-MflvR=ry0n(Flx#@$SLTjrUT8 ze@)>FE$-F-Hx>OjMgN$>>lEIl_-s-5ONxG;!e3SRB!$0OgiqAI$HjEbSM;?Or~EqJ z`xL$A|6mdNKPvhw75~2|dTl44D*AdwKjc{4;Gmon@pJWmjK#fjPEzy@ihhcs*YTFw z_t3~^ucE&|;h!jcuEIZ6c+%pOvr*wUDSBOwzOU$;6#Y*WK1tz^DLy)1UQ_f76#ZL@ zUZ?kz<3WVOTONO5amv3CKUdG2EKdDsJ})R-`^kSOKFx~HpfBMD2l;%4pUZ!~#l3#- zX+{5MMcFw`%8<@1uoN#BZ}OaE38`cD+D^>)&5 z1ja!=ZTPu-zHD*E`-Q^iD*R1_U#a-CE8Kp*QPQjRnN{>(SM=Xg{IwnaLeVc#^qY#% zzoziF75#q2r$ga~oroJ8Os_6?^DIvNOvlgF&)194pL`OCaF9NRpG$w1#l8GT1xRh^ z<2bwYl@|BXZ&38wZ#-Ru{?rk|UgSAf@gHk(FaO^ve4nEKT=CI*C_CBk_ws4AIQ6hp z@rf6q-=gT3Df;J%(0`!lmn-@`Md%MZ1w=R~&(-+3dOlj=-%xm`!oR8T+bz!YYI}Z3 z(O;wJUsd$o3YU+-;GXj6`tJCV0B{h$7C%=`vn#o=PhB3*vh-d*-)?crsr`0B(d+i- zcNM*E_x?)Zx;?+m;*|3`CFffT*ZRyUT{2^_1UO! zE$0svem&xL_53S~d*fZm2yqbS%gQeOPZZ8MI2V6R;aK*U$N#PHGKF7yDj6I8ujB0U zSzvMMC!z3GMX&AZ5k!;aYF6DLyI1XQ!gqd_Gn5`xX7Mr{e|(ZiZL zr&^r))N;;H^jgklg=;>aDSUw9pBTefO}x+H?B>_23V&MRcU6+w&>y7u45;cGze(Ym z57tM?!Srgp*5XX>P58O;d{xnFecqzzsaltQgQEXL;r~$hUWHF%rx6F`(ezss&Udg~ z{=>!#xzHc1@JSY@{8{{5`q_$J=hrI=*LH;kXL3*;oiDd4{I81tg9_Jt{-kiN=j53M z{@NdQTb%M!pSGLhJMk<-PyA;5+;p93amuOlg%48t z|48v!q4<C*AWiqOYd$>AU$-A;So;^cEHey)DLQ1m+Azjii=aF9NZ zpG&{c;^eSM=Xi^lucQ|3J}yPtku?g#P$y5aD3D zzK@?Pf1nySIK2A5qFP{~{{b#t`fpmC^q(pGIfV~a{^V1O(;kK>{D>d`9K`u8DVP7r z7N?wd;pgIKTAcB|rSPc2%N3s{#pj2Leu<*j`oBxz`xO0SiqDS}zE#m{J})ZzHH!W( zieB5>$BKTQqTi=*ZRZ20fCz`z-cGeR_4Z@@T)my8=(U_v75z^XeOS?JIj>UmcPsiO zivC{;|GC2VDtzcv+~6q1PuGLPE$+3$GZp>`!noJ(Q7@Q8UhgxZ+a(L+?(F%ivDK^=ce~kMX&iM6}{Hy?TTLKL&(|#OtxuO&ocj5tqQ6n`(dk{I=pR({KU28&GY>01I^Q>1+$+!Ti{JyNBQhLJ zmoC2(EKd0!`XA)Ie|!|x^*_8JAQ3PVe^l{TT{S2uLL#8Sp9ut+#YH26qNoH(5HygK zY&0lp;_fD_Ym`=0thS}qR{E({S`|?Q0%(GMtRiZq{-plQG$K?jqSoYjzt6q1Gke+f z`99C{=QFQYvUlEd?m6e4d+xbE=FSZM-1465!~Ob%e0==+T&{6bp9MZXe*4_!fxaBJL;r{;RSs#9|kIx|?PcGjrNIeh#>wBW|JxcT|DE`A_32lkG7^8qhaZ&%AER-T|E(Hlc~|@RwD@p;99Zh( z?~emd`tbLCd7U!>%%|t(Vuk*PH>Pv-zn+J zUE;$J_u;F2_z^z*Gav5fzmf&QLH=9t=kovg;Y1bw4Srp`{YZiLp;xG~4_U4%^5~c% z#=j>uo<|Uei(s+fzXQ-At)xd{qe7b=bY5WQUAFc691AjuV(^VO`yAC+l!1FbI zje)!CiFF2^qv<0C-cRF=2EM<>7aRC*7({V2$$!tEAJTZtz#q~05(EEA<98VNHyU4R z;1P{4Gw>@kzTChs(D;J}-dE!*3_MTc4;%P>+A&uec-j=DH9p+H-_m%Ifxn~i(FVR<)^T|Gb2_*n-1XBsax@NSKl8~84b z+XnuX#={1_TjLc5{=LSh8hEe9ryF=~g{qG$47|U_D-C?0#;Xk6()e5hKUm{627Z{v z>kRxzjYkap7>zd?`0*NFY~Uwqyve{%)_BaoM{0bDfsfMo9R_~7#+MrSnHpba;OA<5 zxq*+@_=5&MQR6EN{Ctf+Y~UAae5HY3tno(;{8EjtGVmE1f6~BbYJ81>U!n2m4E!36 zw;T9%8h_rvYc;;b!0R>svVq^A@vR1alg8gLaCd&Y-N2)o{#^ra)%XqrPip*Q1HVh- zT?T%)#y>ak`!v4Wz#q`~*9N{^5Rylp6R7O>bwxU9-A!-S3lB8uURD;0VfpuiwC`MCO<;|q~_e87ju#m!~cfVs}`WxSm$)kXTI9z)7 zJ2sUD?tZU^-yiYQR~D%Atp@IXujVMNugl;4UXA*`gD2PhUQNuPcm42V19!hmGf1}& zm%sa68r#6#dcVTJ-R}sg_oaLKxZkT;Y0@91%B$Xk?a}WzR^j1(>etoB{Vq+Nfv-4D z(Zvkh{r=1f19!haquxL4$#uVnGn$PVhb!0pF3rOR?tb^?T?2RDTRB|&h0DkNjt$=v z>*w!&$7YLxyY0PD2P~J5`@Nbf19#i?aszk2`&77px?DH@++pBu{CU^F-S;U5M$|8w zkJlsN7jJu#-??sTVRg-{5s~V~NMHot>K7Psb$xwc#KKyhkh~c0-Ag;gd%Pr%BGD&8 z4H%UBA|v=JrJbw!n0AW1p-E@2o;!06KVYs5@c;3D z5cwH0bhW3rmFiTtUZ-*|=w|Jn2989EO`$Y}sKnOg>bGLF`aKvwl%uON)eoJZaovm+ zG5()?X)2kP(BUnG4M&PR|KH{>MqcvN+v<=~M@qhKZ!Yf2cYjN9AyfXMD^!kr?RRc| zxBPDYsX9N~ga0Vi)f+S}xcOaL4(~JBKlnFAv2~#OrTy6?-TZDpJqs9hG3{4*4L}@C z^56Rx^pcWdF*C{Ey(gt=6C()KwzftFsIF%F*u%6KdJww z{+VE(WB+c zX(gjhRY>K4TPK9i>yzV^C0n*c-&W;tz$|9b4FOl!~`w7 zwCs{l;+3*#Wm7|mAEsSwC;nqcKQFQ4FWQNzg$3b6-$ESGumS} zhZ4_QEpIR#J*zMfIea~ral?sS-t|tamEQ=O9RJvgy@Nz}*hk^SCliW$?Y8l~;bA-N z&T`c^+llhR!FGJ76&nOHJG!{AAYjF4WIOp25!ZHe4iyUa9%LsruVD{h$KQ#ZH#xq? zP6D=K$3sUuDQw!U*eCGKRMy5E)=qrTTcB7)pD&qlW!V*FSC(B> zHd8DlWwK&df;>~XTKJ8=$?;w*_G=`+CK_ULyxnd)>U1kU2aGi5*X{V8 z$SX9ftAW-=9M^fKr?+>GTi?1|PeBUAYN0W{8I8uv3n#*bLAxzwu}$G5fQDgq@)SxB zCtmHH7NFtqANq;)e3qND6t!Z-c7fDR{41RJ0;FM7+fd;vj?vNgf`zfgpJFz`HY=<4~LfAmF?Eb5DOcQD+paR{080cO{pc`6cC;JW=%6cOi zT3y`ZO7_y{TCsJY2)9+iYvbFVAs-uBTjl>0cbpvG8M)PNgZE6J`~1^Rbl3=kzx}Sa zH{M>Bc)sBr*LB$QvpSLzfW-CD4$$sGi3t+W4$+tBk#eQLPUPCjNa5frd(>!Av^=q+ zA%ey?RJFU!a1HpMl8nkxvWKK(Z|dHk5g#FPuGD?SBR%bsJbbtWMxWrcmL7(d`c3w{p^<|Uuz`d754*NWc-JoyBd$>g+BPPqyu zr^Ry0#V=7Gx<$ZH>E}l-E3vU-LtDcO;Ag_7gPzCau2R8N<>AdEFtB{0Byyk&h707Eml%5reC$I5PV5tImjYshwZ~>%^7rw{&|(UZGDuu^shD$BHfI^-g_VU)<_mtl`C%y!f`ycxdXhP~yKA+sU7D zB$PP9<&Rbo8DO`S=k_+0jEIc2p?dc~#AiF&o)g>FSYWL#h;3{5H`}C)A7+FTpV@7) zP*~g!(4i?n-+@OhHZAq!GafzjQ(RN+De<2<)~ppH zi`-adtsi}qYeSf!;S<8MLv3drg+#fv`gE&>BLmRw2_-)09<2CtTCMXLpb_hf+kK-f+KF<*=oc_z z+Z1Nk70&sJ{bMc)ZztZ@mWiwmqjwoRdF<}UeoZ&^j%fG;nXO^Pn*0*GoLUHr{G6Ow z9P}vE4rOV$mkNeD+i|_uxr{0$Q3=Z0>?)i;V+5ee>(-asJ(Ps$r#}BJFGOJ^YdFz^ z>cK1`lz20YTFuia1}tu0(;m6S?tFn_U4OBYaNJUKjhHUH({NDtg>D>3&Op!gPUPHh za#UH-gt3hQAmi zj2a|P98Tql_-hwS<||`$Qpm9d$;lwCl&f+?Mmo@o|xx6kesfQs&Ch$ zDw6R~;FcvqnLeu8t3Y0JDKW~?XAnthWN%t4o&`Z}_Q-*_svWN*Dp#A7&FEhSF*9jgq!NMeEy(D*D_e{ zY<0(5cIU)KlG~lFdD{3$vI7?sF|M<9uzS|o8q~?oR<616q_g!&G$5urT0bXdCng59 zyLYtmL+?2qtzWQQovmwh9`Ia()|!VwAg(PZcRkPOoM=;T2(3{1zeW8zTG^cN zbFBJl(Q_0l=J&=z;tJ&0zd?L1IUAB{a*Kp_Zm* zc>bUjE1SB$3;rhE!Uh&w0+JPblfo05JDb>|AA9Hhc1^#5b*tuHdPXL`-hld%A&Z^p zq<`zdFMe@`iJ|U2%31ui487vB(PRad;R|Fg3Y}NxK`5>vxtvKHNUm7|rEqjc+r4nH z-AgXfQJSPkqTGRo0X7zFx?5HMCJH)NNMBv5b$8~0aomNmT6dyintP5D7B z7(wz&h&Wh5Z0_O9bFBF6V=+S=5dC(f)w&%On%H9Jjw^_6%u5VFlPKOv7lBmg6tGqO zYP9EPR_t5hGZt5(J!e_51F#pazrDFcxu+B3aN!w5P&~ zeT=(2R!h8qr&F!ilch{dv*K?ZlhUL=isIKKS`x7Ci9QI1#XFtf!MiXHZtlq$N-@L5 zD10N272Q3A1$#$|8iiX}t?!G0UJ+!KARj}I=AMm$^oW6u%O|oy%rPAOp*Ba`Y3WKN zy-={0vkmfF9v7tWWFpTVK;%h5hQngbJ)4=1Kk5m+bC_W(u8VrLS07q>f_du|ZqUN~HHPb1UuC5NR7 z8$==ej-p+*f`z?N$&L1$Y{iP8pVi9GK1X|gV#RvIb3TMUqdoapRv*QyABjiiTJgUg zmE!*gw6YBRcZ0RV2MMHHA4-jU0J~eQ3&gv&39_IJNXv6l(!UGx$Ot0a2Cyt|3vv=f zH~0LL={Vo=sVnhKqY_mEXh)cV5B(O@UVqx$^MzPwH&&~#FeuW#7UV0DHe95ABgh;e z%{@J0#ed*tj+VwIm{v-kr|0=RooOCc>>3nvA5XuUU?NH?1dizQ1&J;Rzi!;9wqi4+ zVlR?$LG&(;z&n&(jiu{AkY@D>jX>wdG%s5bZg`ihU>E*95WJ zzaB(XNh`Kuyd?*W&lJX`tPjy`qjYNLNNueX4Iexx#c1KajJC;Advx!B8?Z_SOM~{1 z+Y)#4(b%&?)c^EC# z&&}UrmP5MhFHG~WVq=inr^OTzOhicqEndVe3;N5wBA?GPS*?E-?`RSEjh?+9M^~Or z{&aA2Wq-3Aiq8%@;Ip`6A@y2r#g3H9;Af|!J!f0-b?EoC z3+KR0eoLr&y-n5Y4PepSGhO1(b3>@d7yVhDlZnK?!?pp<~Cyy+1wMS*Y^ z4=V_r(JG{&7cF&+sOI|1XTl#Jngst##D6~){=fHH@aJfV>HJj-roFa(tL@b$c7Kx5 zs&$04v!vLaZy(oszG3#qCB-|tKopphh?bC99L(Hy#kV@*o~Q8pgV_I7vHv8mgZZOr ze_z}SpryKg#54~K&LCwUKblK05hWF@lS3U+>mSWMLq(5y!&t6Ai$9$pdYt0<^Uu+4 z)9mBZgR?JJ51EOH9-p8p_R)iW13gFuJr?a{dy4iPXT_o-{6H8X+H<58|D$Ko7vbi9 z$;y8&N7n)lr-MVZX9NQ2kyQRz@QwBix8iRekgAabPRo@4E~UXY-}LtCn)}%BQ-8$R z>T9t~^RQxkq1Zkp?7=0JkW|p`KJahu*(u~F(!X22K)Shy?+dkJha+BDEiXvT|3r}A z5@~%2akaVU5UB%>*R+Ob7?$vBSn1P{X&#YkL%T>7G~-oh_QM|652HO-Tk-3?rnc5} zIm}EedhO=#dN>$r9eRWmuoMPVehg--6tkF!U5Ba&IKN8qZ|-pbSgmhM%VT4(qFqwL zkC={g!Pgw=fDaYQu_cBbbl{3K;P^ z5m<_ve^TT%cu~MYbj@Iw71VRIr{_zOFXZXTVRl+RU#l(fMGvNxo+C5qd6L#sMUTy2 z(=gQY4=h@IFzQv;-@i7x*figgAy+SC-$emlW6>@7i}*6 zsiC*37p_t{qz9Q?CKRl7j_Z!J~vsWK4o{*l;ZO<&*V#!v{daRZDzs&Qa8Z#EFdbFkf z-F(rW30C|D&;EA}Nf)N<(yR)XFS(kaAmrT#H?`vb#uaUsB}UaDvT|qJaTqA+JHqZw zAKtqBEqo&byel(21k-G3e!H~u85B{Dg2(NHQ15EQk{KJsLQ<~Qi7dWtjFj6u8iMUd z%QSl^f8BjMR9q(6%ISCa(iCwE%Q(7d#f9nll*2i@r9DZpUHpGWr~TiFwwAz6M!mEseGgS3v`9+>7~#csopW}kYvnP4JH zD(H8p$arzHL)lGXTe9DX{08h$*Go@G@Hf!)5IobydNs;*1W z5S)WVwOhoP$9P#fj3%w^-w1im2cNPue}!Bt{yBPkU7F*Ku%WYX%YgH!WI0ic{fw98 zLI7z7P>ONasj~=KqCG`cJmJv~ACgY58gyJWXj?K|YsIH~8J1^^GQUz84ilxeic*DM zp5dk+`P@7Yrgz<(X&zSWFpR7Aar1)+;(ijSP%VG@gf@FvJYbEtt~4HNlNk(9LIX4+ zOSES;=CB_9LnoxuD+4^L$}>@9+(DJ%Q@uP9bG+cil(Sf!1(I!~nBizI+dt7@(o`$L z)>12WGDc=_&Om>6mk!73cMpI!Vg(T(%DUlWDn8MQzlvU8JIC(burJkoGvtr(r!qFcBpcY&=C| zog}hmda?$Z7Vya`MNoESF|A}x$s}vCl0_=W`t+YP#Zw~dD|F}D6eEIZ)($6wd`2dI z4>GyRCnby*?@Wu|;lx9X-`+}+6Bhx0mg@Y4Ctydq0C#IkI~&3j$?_)3V8v&8Sw1#~ zF)C23fCHc$Kb1VYr5q=Fc_x`{)MvBpKASPk!;1YBV<@+Xss5bRrxhxzw$P%^w1Y z_MC?K9|i)tny=c&gH<>9bGTJxqsmSX^H$0q1Q%3JDN!77y4!)M#ebeH=5;l*LeSg_ z(!pAPXO>)&Gj&&2F+gRM(i6w|FINIdUFJN%IbJSDImkw*-5ZHe(eYi{Dy1=PCm2C|vZvIx!g<334Vhkwg$0z`z`miqfhw zunQOf59e?Sgd}wb-WkACz2t7ioz_GVYn}ZC7vTY2ajIKdVJgDfp~rw z586CSTf3%BGp6fhiCr8FILrP)EhV?gX(t@-0j%!lbpxAkj>UaFa{xxCuW&Ob(>$zL z48tN%miUqtyOkh@>7at~28--*2ue1B(xg1+a4rrdeZYFm4AOueSXWfK;gk%+%c1PC zHf=ZZJd5tY&!l^6b`DG7cTSVZq2}+IIs7bx4l;8(2ON};(ln9+xG1V0&-`MMx0S)E zAiAZ1<8Q)Fe`Jg9K*i|uZ{9NGu1hP&9ofrKNlUCTvO8bBZt(jNOAMtYt~WWn{ieym zuaPrKf}5`b|0UxyA21WsrnD?iV1S#w9PB5Y-G=#{E@|x^SGPt-_>HXwOEDN3uJ)M8 zVjt7KnxVcFi(e}i*MfzjIms_Z&(&lJaH1ilJH5VMPb>J*m(z5!R?p|NhWm+}e7crLFr|CXV5StHF)4kFZcC8FB zd{uIv*8BzV%qD)7Pdw8~{G?3cCn)ixLUq3XhFcdi(s=6yw>o%DWK>7ghFy3k|8bYx zYTb&;%#>v=vNZfnWub({$l|Yz?%(;(oG~b_a)wNCXgj_341)LxAGSk!pd&sGT6`jjm zDOT(MnqrHpVQ@ z6Cm*y%{d;6ZfU@Yrt3bKc3BObeV)BSnKmu5t4Og~4U$SzT4jn9E2-7dhE`^zP$IIn z+o9m$cDYO|n;wXP)jpmvh#+o!Db;@eno;;4j2^aIwcCu{tIbYjw#nf?9Jly7?QYC` zJZm|Rn_+Gy?5~P9-Ct+Qf>9M~d$zhX<4l^^$&lww2s)x1NO%L&Z&Yn#Lc)&9H;VwJ+QXl-jUfkY2NbQ&Y z_L#($$S~V_Xj7Y=Q@`6z+#P^RqV<(g0}O?5#skPmAZng9#MJIKzjn?SFqTsAXupEA z&9dl5Wt$IQH43;Rjm1gdyDWzLS*Qv6!)&*|H5fQKrVqTPbf_>HD6_*0+=&z%tAb8( z0a&U$nLNG=gHh*XLu&V9ezkSLxgkTN`im-d_bWdpVkNcM0+KYQM)#{U%o=V7`x+I~ zJgnGrG6a&iWIq z6fGECC<9~|B~_||wEoSI^MlcNyYZB}uWg@d4i67C24>Duqt>0#X7t_99BdzoeE?}v z@{O*_xd}HE(Lzi|#boZaqiu)@w1kW_8$tgBxRuSA}OXG2o=^s}cLBOe& z-o$6rzsdO2w}v!Ptn35!|H6>+qRC^0JKDEe<0yK%*~DJc8KQcy!lo=cHH~Db{r~y) ztJFv4_n@k0LgPOh2((Qnm<`KET>wIO#FQXc~rVXQJiDB02h|_T?7+RQlXn#0-<7ctM%+3;a}q8&$QydEEE5`6n|2I|4_5dor}w=nlp`}ZF<7j zThgn`StGLp&n?|ibS4f>2y4z?O%AX2q_g}n4h3kSPMyi&LAg`o*CDN*o|dH#@3ONF z5>+`D`72EgdFT=_&OiuJG_(CQ{ylI(pW&HShCfoGft-3B)S(2icTpMs@lK<}F~7du zzx1Cu-d&^1a|LNE~}6)g8! zhoR12jP9WOzO({iJ_xVTsRSlkVSg}Mud9!{#Cam^iZ>%bZyrvFGp|nBN-XC? zjhUG9n$c99A28xjtz>jsD{*%eM0fPZu#Am%?ej*JU1c_c7t?BV2`=mUS_x&+xWmh^ zKa=688eBD1he4%U^8*s;owH5p^ZwUWJj3v7qZ)qYnVAkXnxZlM8e+D?DW?4vm_w&} z++|EF_FHD-9_@BA8K;1C@C&EXlzWiT%^Op|ZgW_<3tFgJJS*MK>(ElvrpCLz-vmwZ zEUb!-J9*|GdTuwnfsJXGro&0OPeXY(F@FtR>=WG2JcxGv_^X4sjmn zm9~{>+JYDCx|}1axduyTp;^OMAEPcgAeo`39cpz7LG=BfSqclo!h+N8-L#atnO$3v?#7$vN`3FQu#>H%vy=C6 z`OZ#G8EofP3~rd-bSqwIH-+!c!CNWiy{n+4_IpZi>>DZbX>2D>hRXUKd(cUGby1S9 zZ{za?c=sP(tr$ZBuE)15Lcin&K0felFOK3D6Mq+aya4YJ=8-pCx%S43=ejN>RXZtsBeph8jD$P8sQRRC7aq_tAL1$WC65<-t98?bw+=ZTPZy zo5-9H-`Q{rsFh`fx}f_Qk)MVB-YU<}eTrZLttMC1vO&e}UCFV5rh0eJ!MzVDU>H+s{B7?3Uh4-aJu8QvM z-|#6adnxebU3%mTNAqV zsTmujW$GES6g3`ZQT}2l`!}sw-WS{=EpQ+HkidupwLN7;P*HMCQS5-Pd!e z@@Tq-Pu+Tub}ind-Wk2MY3)72Y5%6RNhTV~v13Bp22T{WM-Ep$*}E0#!FbJd_pjim zC{Onb{LDFSRvl1K(t(_5d-(0|9GE z3S>$^X&)+jc=m%mLW!^O>dTP`QxYFt&)3@TDP3G(#Xlj}=sMmX#QP}w7Gj0^S5n$i zcTom!4FrINk>pdP(yw!qx3=*D53v?3few$572_kLc%kGoIF373 z;TOFzV^QSh_4H;}%k|XAJyGwn#ytyg#~b!Opr-2Goo*~pDx@(~uWE%|n!qVAL-ME| zf&Q=Fcl(~NJ=ITF0w7hz7gXoU?zK93>EJ&?bmnM@vYMRm0J^b7?zFy0dr?(75?e? zuudAio%j>ETk$8s&Q7*%k)LV)(TP$Pvb%$5|7r}Q#yjZttoSuBHEV7re(|o}L7`5J z4arO14yv5NXy@r3f)@x6qM!M^O!`Bgj9jQ4Z(nl~_@ZcC&R0Kp)_}Wyp#J$OD2A#EtSeh0N#h9`7$SI-d zh6)*l9`BkEWe98tl&Z!2cF^;>75fN0(0Rp{yB|Y6OmbdiY?dS{Gf30?igc3q*#YR$eLTGdjmjv%1Kq*#1q!k;6N8oYNj*||tnJAJfFI>0L z&7JyIMIu(%1hRc_d`zbi-u{BMY?B>*PH1pXzCCZ#5`108imyhEN*lNb3BGY(n{9IP z4=e~@p1%TYt@Zs;*JJTkGb?r-wp2#<9$>|;Mglv`yAPB8ORin$UOSK1usUn4?}HiP zN8z?dg-@z$!N)q1ZqO94L)O&*x}LVSa;4TfQb}oM|oih zUTR)bSZXI;U0=$~h!I7q5-}#ii_44f9x~XJpYvINE(qjWDDeWmSAutv4Ddb)z>UN( zug=_7k;8A26k$_xsBLjyJ>bFi_#&M0V?1gjEA<{(hM{JlOx6L>Zu%CUbuM0}kHAsZ zw4RUVqE=6a1`}cs_%2Q%NGYMbltOI{Y-q=IC?}^)i%~dHsR16pxUf`EDHFcIkdrHy zT<2@MxsPrRFF=a4fz=Z1sIuEvlS>iz_}eH}I0qX?m9a59_kq?hxj7+cIHbx7GEA+msM88naA&YX)!hI06-GC!bVg z=s-vF6Ag%^4}cS6DkC2%@f&4Qh8~#h&Hb4Pji&ct`V<=4lS&>KoTR=1k)GjU$)H*m z^E_JE#PT5<%WWs0bLHbLn1~yhSj-}e#IA5+XYavo24@6_IZn{QA3dAX`>n74v{ig6 zTgTwbC?Z)Yn<*(kac}Rz7?fTX!7SvcLVQVwbGpOa-nx?+IVq3v7no;YpTQwsXNg=On5W6n-t(7jILfR5Z+3eFhLU71Q}fb0@Nof7$(8A+1y zfY&8AFq+etC_wSfGPQSpFh&WWYlJF1G}=doQ{@l=S{jd@r&6@PaBD}R>D(DsZ0G^V zmuxA8Ph)P;AAP|}Tv~rT{<#ejT~Oqx4h9$LKIEF~Ady^L(4WfScN&Vq$sx#!?t2$M z^Cmz`fU&RlnAdy?}JqI?+P!eMz)d9GRT-u3uU`UC@nP6Gdf6s`VAnK#R zy7LU|3)_@4E;;D8OD2)(I8rrqrJDc#spda9spY0M@3KARg^NoWCHhM+wUcYuRiqgS zEP~LG{$_U6OX%0JbD&{a(*}-BFm|=kQqkjZU?g@sJs){he}{U}G3|LPR)_ivC0FkT z9p*@QUKzLcFtp(wLGZj5XCyz^Z8G?kxdVPh5PoGP0S?xV91J1!mQ<%CMZj9LzHY^u zpqKZhKYpMi*|Hn@!%3{z_s{}HD@cg&oj9|eZio7M&==_^{TT`=I^g{!%!shJ3iLdX zT%%I(sYe9{@o#96$k|}bEro$+%J8qD0H=IbJLm8hqyOv|-B|8s(63ThkFEs)!VRRL zu0)Nv1=C|!)Cucpf?7HYs{w7QyG1)k2CKXSI^0Pe8ukk%usQI{Q1WRyA7>$D(=OHi zR)KML@-$WD(dUCQZbSXd{V!`(cOyPOO8kNT>h=%H58WXt9zRpj%I(FHGE|jHXYbaC z*NlTL$hX48fyl{hD?6+D(+J7e-;;Vv5Q8Mipd_gchfqnpQ4xr|-w#Ji_~p__&N%ke2L zV5rRNQ0`n&ZiB=!D^`p%z8E8d1w+x$9TXy8lQ6VM-zJNRp*C5qyKQB8P&E^#U^DBs&#kh)5yWZ6&xdB%)KIK5#)IJb<<-yJC4R#)aePzM%aoxGwB zQzD*~DgTVWxCmcrxsR@AJw2rkbECbu$Tc%Ni73D-5tj`m?&@Mu5_hp-g2!IIANtPCmSB0x0<5o`QV+EXG@r zLVjE6=A4n3l7wK+;#p+Pm>HLaUbVr4DIk~N-Fo$0O<9Op)^cX0k zvVnbeZ!f&CbvM22%twVlIt9Gnq^n_Cz zgg}|y+=Z~A9iexdV4=jFbPN12=;H}WC!zG_Hx$(erlNZCgmbGJ}QYhAJ$3OZZIF9;oZ(WJPdBL zi}!&LnwC;g9R68I*TG9tGlXRjhjK0jAGRF1vqbuE@=?jl`C{I-KNqFooCtrN2%d>>$~K4{OT5AZd* z??yHZ(oTKnZ@?{8&%Vi^YbuU#^~kMtD@qNM?Z6M*+KPRN(Ez6=8(7gfR?7ex9i#?p zdXU!2;EyuP+83NF$BK=Et9m1<(L7UQx*X?3X|Sc}`0k?-(f_fA7|DNkms{bn`{3Qq zt6w4(E_K_NOyyO;`Bc1Brt{8>-Mamw6KaRvXk8q`=n~7=Ppt+ zMqwErzKSq~kk8Ez`Vm-E4W?_axS3;r60XQf8IoBtIU|vW^S>tLTvuB0g;3tcSM*S1 zj?i+}U&%ZP8OsVg2#g%q)R=Qd2P?V~_6j45f6Uq{_H)Oqi)b=0_*?{HFFvjx0`4wb zgeq}3eE${3(?)oPGd3>8%GB+vKUnv*9~EGzIEqc3fyvGd7uso|5lb{&ov9GUY-ZwQ zpsk?mUTMYd5hqo{VVLPzylx=nlu}@LC_c%!5pYU7D^`Z8W}&tBCN_o>UHlI5e!!F1 z8P(pm?cUy=o}O?1e(aacA2#8LbS3^yMK*p>@Xe;CCWPtozhf<-PvSKWf&;H9{qdb7 zt~unQjN!K7=#$*m!8H`sNl8hh0ExR+LMi8gf3xCH$FKHoa|U8(c{ov3SmYF;t0=>C z4t-txWQ>8>ZS+YoOz-e?r`Z=|PKSitQi%XXO(p0{zkrFPFLgT*);p)BsOc>zFix#l z1INs27227Hv{F+qZK~cJ57?(IcGe`#Ka6)Qx^ zLeUp;$Txtmh`#O@uEY+Z8PzUzfAHh9&)EZGd(*?nA#NA;mpfD!_5o@}H$!2j8z@!> zZ>L~AD@6ZT)OCx_G9Rw2yEk{vH97IQoy2EOPc4n@iQqd{H7H}^3a&oBXdv=?)t5wX$$(&Mlxb=hZpR8)zhM zY(*$V3{YWQMl|55hZ792&Z8JcWmD{#&!vn?pR+M;!@#W{+MZgl!=OSf`{|zF$-$*m zZD{i08OhljIYV&?J)T<0x&Wedx8m1EL_4?BNjb1nao_m~MrG)$%GR+2sOAHax#_zh zc(*)?ud_=ehBm$!yo^P+R!>0loR)*29GeC5P_hW07*+G{vu5I!z*)Cg%Qo)+Qk(sH z)3-U+y&LmhY8W)uEnX8=uLB90-34B247cJ zg-!Hs20iRc<+Kl-G!HVU6Baw;Jip1>7bxb9sNmd-}nn0LP?&o@vf=%KE= zb8qKXFO#<%hnJ{}&O)oIUbU?FA0W}M2b!C1XtF|eKit@9rZ00{B>EzLU+TS<`;UrW zEKj_G8KQ8TemQ2BuIo52N&Fc@^<+B7&(*4k%;r<#gs~{*w&oJ>mZ0hE#hl>Bto{{y z+q4;y8bEx(C)V_!BfVinDs`hk&VX|tCQ+j7vrVEH$Io)^{vu3Duz3^eId@7ohOQbt ztQEh4y1_@#`8Y|AH4<++Hm5dPE~~<8kPSb;u`){G@2ytx#5+$SIC;wC6#;= zN30AdcJlTTx-f5f;p?1wSx@^z*eY*N4>U4xb=AP#sK~KpQO@J;YzHqUF=(8ilMr`} zh{MW+baUav4>H_C0b#5U&@+gq$vrZrrrWsNSQ@}5o?$Vfu*n|0)Q!6!X;zSwb`}1e zopHk(A>1M1sz@jqlL4fioQ@ryR}Ge1WFIgpVC1`k4W9eGPNOisMe$Bdu-R`X&%uf+ zEQ=*(S%k}zG)ntqAuY|luAN;}l(DZ0!8fcn@K78HCM4~}$-2em#jlh$eVP+Fpe$L} z7_Y-(V+ohC_H4|F9EN+wvBEmI)10!gEnA@~-f_l@*6LUx=OiU@{>RI|07C1AK^)#; zS55ps(vF{ML{`!HChE3Ft;2PS!Ivy#PTD!aHUSM z!5#2l1CS!c+siTFtYXlZYsFgumo@#f3E%61pERlMGKlvyq0E}%jLWp9EJQ~JH?5N% zHDVEyq!s@jmf|T(gbEx*p0E_>XJh01Z^e%x#8}JEj|)5g}HqE z>&HUk`TIj+hLHFUo*)40)nP<{)%gClRlX6?U}*R9Y(;QH2crmY05rTQ#6>=LS*8Ko zGM}Q4xxSXXUbz-O{zXacG)QtCe^SQU$Q};H+6!>3Y}~TqkFgI@ZmTMiOA%#FKj4cW ze?tnN)V5;JGXY27eoiaa%(JnZt=k%zaEJMC`%HHkc!rZzy!-oo2tzuKIi*LNCT&r* z9ydVXp8v5StOTUD(^9n4aajJ`h)qWlb2o5)&ta;a!_~CKdU}T&M4<$35?ZU}Rx5(u zl2{?T@JJ>7x{h^@RTs1|qT_kkQW=>i`d~HSW>N}&Q3uY*$@*=SK zG!%^0S-b}*LkkaAG$-=jjoTl+N82g8dYGB3;RlD%h+qNcb(Kj+NW`GYWmlEY%kJQWegV2!C^$vxJiucGn!$82gnJZr0 zvIZA;T8C4~PYq~LpzT)tC!(9&H=NA9Mc?6yo?fgU3?gp>n9cfTu@IXFqqTw19ouma z1^0s533QbIMHSiZnpt#Q0d|N@Eu8Lb{|tlm#f3xFfPk-AK?ppTRg&J*hd8=~1h9(? zLUWAt51onS>+4Tqj~WEE+^OL61lYD_pEtbq1U0i3@3_Gl`rzTAK+p!_}#OL z9++%fBc()n*j1H=(N(#_SESe-m4?S|x#gkBiLOv$WA_7-!FbAKat-Uw*cr|a&^I+y zS}TBKlW)|P0)c7hdm9-7`xfdw2F}4B@SKJ>nRGuR+r)mdSH)PyU*Upy9}fU@W@7T^ z_c#$JB#hHbQ7K&W8El_v=UFW$$~;uYc0^%wyU1!e5a>RFog!Et>&>t>H2(6>YLaK; zVWe-i>Tf|_cl{BmY~P`fypuy;P^D-1!3nlHZ1XS4I?qV|`J_ZWbQg>Zl7WH#7nmlo zD`9BBHU6ZoU5{(Je{y!B&~u{eIJ|)8U4bjkRzOO};%&|}En^3+bK7yhrgH)fH-=`b zjwsbxwW&pR8N_X3!(wMH0&%3wRqv>24w4E1l>g$f32DqzqqaoZ?;ta;+6?*`b94`$5h^Vt0RmlO26D32R zd41d@uX7w(`Un&nW;U$76hXy+vkt2~sWUy15b(!_T92`G8HQSQ+v%XURC*6x(H6g_ zh?E+*JE!!xAFvRkSgFFsqnU|o(qP?TIBQT74FfRik|5hK*^^S-o|1E<$dUW!{u!z$ zfl01fevh2!_EHRT&LeO6Rd&Vko1tlBO(4UnueW}#H!{n!3diV2KEg?Ck}bt!S?!S{ z@cdc`^C>=M7u|b$B#5WP^0*10;R41Icb7RIo{O<|uB`f?|humrlU_VgezEpfc z!|?5Mcc0&|)vBDkX}&bbQe4Ze+91%&V$i5SbTQ6etUa0~b%Y_~O8MVdxT=G9i3nS$W{% z>c}bMYiqBYSA9lcd`)fryam?;XV)%RP(3>`uXaIjNKMs%z_j}6g{PEV13qU2htwZ1 zATVcMO?6;Sq%JTwf`4_jb)y3H^N|WoE~^NH%ki%~G=6GeWZ=rcjKJ(!3xaj?>Z)tz zEvS~0`3*IZd380_jREkTH>;**Q2>j#Sje4QTOSDwDIPQ9ssU$QdB(_*Ly#DG?v?zx zGLUw1R>Q)YbAt0{)y%0~IKR3oaNg945h8Phh#w)Ej0jvjnRvy86{AK3rc__uFs~*O zoHivKjMTCq0|G-%9TNyGxPDg6ysBWR;`-Bqv#P2VR@c`D$#zx*1oc#-J}|#}e(l0V z!TPzi3nR0xsSYft<$5zzzTm={6;m#pewkQ8Vc`9ts9*IndY1lG zKY=qNi|VS+9x~gNI;0-rhs4{4%t*ooFU+qU`IF1Wp@<0@#3ZpR|7&*{T>Sx zdaqA%!(3pvRhoQ)^z4NX)6vP@)`w^Iai#mPR2KJLIqCvl%){&QL>0Tmd!m#Q`AJ7~ z7Jl(qU-y8HRwl7;XY-8Bd(LajjZ~oFes3plO$*Qv99_Ex>SIA9dG{(Lq91sLJ*(cB(ORaf!ikb1aQ{ji{v22mq8^mzP-r={o^PG--V zJ=f=vvvt6U0IaR4s)k$DE}+ZF;nRb>C`CLEqH3z=M1u1cL}txKBdw^Zo<&QcVOK8@ zV+|R?0u4d)hI?062dA7jK6qNm>7x~Ax5Y20j@(eY@H+CTUN~pg>}m#uGx4Y8S7=ua z9yg@^IG8Qs8Vn__T^OvISI-7gh5W&qc~{RyNK$&EDXEa6YF4#a5UI9NA6dv4OJiv{ zGlrZrdd!TX;!{VB9&_61C1Yn@J-e!UPT9Ee5WU`+Fk zKxr1v4l**I8ElX+4koh@YTe=l&Z})ezN_)CrkWAXWr1SX1!oMYzf$XSarMIM;T=`A z)%Em4*F`04pV9zJFRF%<-Y{z(Y|rEWmVPKQps*50QeDAtXo7eKtIn#wPJGC9EJc^< zC9)El{xMI~t*xtG06(a0xMr@~k``7&>j8nuZodO*vppZ5L$gq}vJbLXNhdf9zg1{a zVk%(~1Qc{zRYj;`!lh-Qsf@4n)ij05@8b-og`MU_<|1mQRo~BfzHmGWKFrzJ1;_3K|+%3Gz2|URl|jlBy%rz&>?Uo?qE#4=g@@AB#^IxHw}? zOc)rjA%jl?^4P?xgRu(Rc6YTb@6(rJtQ&6y2}SgUYBW zZx!DgiY&t!Y;fd~kLN!j_|N+}`Gd#9d-C%pDZiPnX}_T?n{}J}SzKCNO1H1dh4 zFjPsjZ%Z!jTF|F!biVtUZ)U3fP09~mpFj9Kv0i9%2lM2%^tr+{Xdu8C#cvGpU|b56 z=NFt0D-v(l_;}(~`308%4{HEO8+xuq}jHd8aZvK+oarsMg%kr1!+W9MTFCcwy0nkZ6FT!sb5Qwqy zSHgh?ju-h4a&pWfLHfDa%B{i3D=FtcZsU@@$u0iHNcIg#HD>AE#m{7 zFIPrq`b7VnfM4OGeX&%lM*k#Us_RwyYMm!Hph11kpKT*C*Ep1J{M}gF^4|@n6af;5nfTM{dd+yo*Dmo^_>raNs1t^L&U(j@0yK z&5zc&nS(Ez;S7L&>9c=LVrN)(Ay-X_v&kN+afka>WgQkDV;Pa@)TRaw$`m4s582B2E z-)`V?V+DGuU+?1cLZ27dZG^s;G_LgZ=(lSAGd)OBf7kdgjB>rJ@t@1Dm+3<}&kJlf z@GecyFS7WLFEq}0;6J|Bc$FVS`a6xED8IgoqF-L1(ZKf;ykCHC9QPl*b;kOwFz|yk zUTNUG|3-RuPQo)DKNUPrw=;$Df1#$o-{5nS#&>w6k}A@C)US8(G)>Pq>Oc5y6YA6K z2az79akGAHjn6amxj^GP4ScG`W!&$Rak<798uXPKzuCa&XuQ?HYc&47k2jMGHO@J@ z|7g_sN`ucW8h_ltRXgvO8t1yaWM>=fc83e--=)GQFHk4H-o<-0UYhG+Og*UO${fsh z>315x!G|%qQse#Q*Sq*~F~3qv?+|=>My6 zcRb-r=p*_21-PNxf8=R=p&vv#UvR`pga08KA1uFKrXw`I)WCxp-(v7NLGXTo0}OrC z9K2s(zQ(qFKb~!gLzMh58jx6}+nop%3ipv@m9QB(l z^tl*J_7JN?@ygw#Dne;p)3w~@Cd{h>k zuhPlHe`Xduk_Ep#3w}=){Eu1i4O#G4v)~_P!M_8}dfa-sRHIt6L~;NYGBTC-=q&iD zS@6kO@R`6Vw?fa;$1CxHn>D^dFW2~Pjh~?LdW{G5gv!NRHD00d z4VwN}z%%K&O4AoqD#9{NzeVGf8kaRtT-%<7&!<`N@3PtEckO-@E5Y+ zuV=wO$b#?6g6CoZER+2Y$%3Dh1;?$yjC?Ay;5TK#muA6#odtg^3%)iB{%RKdvn+To zaK?wqU#Rx@qWTH+$I@yhyZsb6>5J}Ggi%e;*I{O&KPwAfkp;gx3m(aWw`9SWXTkp` z3;tXdJb)cjBW4F`YOs4{W>utiVL-OL&8(@tX5NCCRn-w}L9E9f(FnFo)z(F3VtdTO zx*Mtj+>A1F&cf|MOi4-HK+Bz%3+f}tUN@q6bYT3&mrfmTj~I1oNnkcNhGN&4W-)W#929a^RbV{q zFmo>U7S&WQoLSW{f4=O8m0gncff3>HMf`Uv|Bd3m(fl`t|4!$>68;;@f5k$0nk0oB zx)GLKP=#s9SFC6xd$GzdSx3p$(Mo_~CV5X2cFQbGQY6}e-C z{xqeyNF1f|3g^*Eme7nAe2mH^^rs2^X!$=zu8vaN)SGvj7Q-#mz!eNw186`-G^PWJ| zh?q$$ZD~vEsDlQJkRVD>Y-b>WJ2HF-!Qxi~=EG1UWMKlaq7KbO7>C%nWw&f=TXwZw z+PYhJwTOxu6aibS)Y=uRt!TB)G+ME>ieKdY|IdBS%#)K$tKDsX@B9Atz~tWZKhJs2 zbDr~@k9+R9=NS4b6Ix|BRGGL{CRUY^xyr~k#sBN)!q7}Md?uN=Q~bYviY6CROz32T zPcrvYe5uUe%0S($_`K=Sc-_32GZ)s>*40L*$7|{Ws4w-+D}B4F$0F&L74_mVwFZls z>szlRRZHV?34o`etu;_rw+d@2FR!a_zPzpp)z1%=8j1yMD_30ULu6EkHK?o)P0KD5 zE;N6C0a$>`A?vPK+KR=Fi6%dI+480pa?AB^Tn}EyWo}r%4bICclZl1ZoLAPhEpJ>^ zzqGZ{kGgW{nmR0@TPgz4yWICPMtfai_3{;KeA4EntD2dMm5I7#SYw6-dugP8jM}iQNyIX14y7uxK2KlSxb$*Ay03$kSO>mZ7*Yjjfc#)6kN3VbtFXkm z?F)VYlugCXpgOqRRU$XGw=P?WiZZYqGgs7aAkasW$gB1?6_a|{r>8D7=FHx*q@mdmiV3k6~ZR5e7O&b$*@21gZ#RO z+KVpCGNr+KrgNFOa>W(W9}26>P;5<2b;x6#t&ur(E^i=I*PJW*m5ueQ9mqzigL+q^ zG8=0#nR7z&1|*$dV}pDmVW=0*n=yOg8NS5kUQ~qQy%beO;`rg{SWVYh2jQ7tA8lBH zE`A`CBb4YMa5$Jq4(6uSex>d5eL`atvYeOAjBQ>}$QX(+wlKVG<*M3cSBRq9TDg*# zp=<;ny0`<{1pU6ELd=e5h1c zhvpC;{jdu2yC~8D!I0Hv<5H6WBRCARartT~1%AX~mgZZjX(kB_SywgLk^-;gNE9uc z?X&TH#t^-0E`wOR--r(>Bn8`*u0m5?cWDc{Z?>3d(T$q&YB57utPaL7Q(~g=1SKi* zR+)g!^6Ltpqzy~DC-I{wX%~@e)eD=?f$A88J%>pySMSkW`yUwjcz&pWK|ulylo*#a zYm_d;z(;532hCD>KU%|zIxbcBJ=T2q;h9Oy0*S^JsCXdOu&mxe%tvbj;|=1p3?r6- ze9Xsf17evk-3B0+t!QmV*;UK)8m8d`SK)`RWQ~*Q9<0?Gh~F;sr{c#v!<`@KT>6~_=&^XnIG4}4g1h-@P`H-=bTWW* z)3xg>8GJ2%RzDjsZ%*gZ-&_Fy5axv~eG)g8<g(J+A$+_%y+p?mC6vsQ764XJCGi zj`Ux|&+<910KP%te8#u*w z<(w`!^Q-BvD}eVZJfrx;G2cPw>Uq7wHzM4o`*nqPDSWHKZ%}wZ-Yb&-mlS@o!ZrN@ zg=;;pS9rJLvq|AMD*REwPX(s!{~Pi?)5Q-eJgNAMllPXCf0M$i6#fqiZ&NsrZMAy4 zPT_pVYVl19=h_F0|Et1vJ?#TaF79o!h2)Fd>P9e2lUKGLNX~C(_ z>lMCP(NhFVzoh{E_Z2-wu=IBppx>?N$13_q3(&u+@b4)4e!*ETNriu;93D8gyqXoR z+n=op*Y@y;!js@<^W}{r_rd&I6rM!5rC&lp;9Pl93Qr>3(wBXT)Pw0KD?EvCOW!u0 z)Pw2&N#RL^Tl#lTBlTeV6DH*GByKHz)5JWk^>el0Z1+x9^fxN{q{3eioc8uzg|DlC z2hP>cw-la4cut;5QV*uTUg1fETlzkQYx$c`Czru|HYz-caLWgi=*Ch0?PY={|mw`pV8+Sa-$zT9+;zW&A&n6x*z|# z;4DY|T)AD*Yd(7wo>cNwf7+Lad~QBH;dKiCy28JsaLwmVh2N&=cPU)+*(W&b zBb!F6w`Udoe<=K*!u7cE)X#tjj`{je{4Aeph2O65WeV5ww+c>q*pym6S1Wq`Jn~J2 z-=XMlRk+UY?Si}YcRBCQFs#J zmj0AEq#jIv{oJAPR|??4d3pLIZY}@M2u?fH{eDK#U#;lBuW-$$PvM$AI3JPW+;VR? zFOO^b4GK?!#L78+!O-+g3fJ`KF7)Y{FI`{0rtq&L%<{im;hO$;3jcwkKczO$U-P+M z;ky4?wAiP2?fgoGCl&ug7v}kIS9r-qdHgPgj~ATn0Eb96UuP=%>l9w2@VgbhP~qzp z{!7K5d9eKZ6ustuNYUS^=*usL2ae@(4}O-<)e65+;jb3JPq+j`aO9)uKcn#b5N7$G zr||m~zEbS->f6*r~4yZEk0%m(ZTg}^%4UcIUmKXrN2dR*B zoau6CY3Y9~IP=@7@IwmUsPHjM;ejK)PIp`Ze1^gwLmZp#Y{4ndLkgd-=ykf^RQNtc ze^BwcSK)66?&{%|OF;xj`L+FjqTax!TsXwGa-JeM>9rktieB5{4;4N^@p+;EpI$|; z`NSK1d6@3wiqED3`113$JEn{I0Xe2w5P|KpaEi_b^r zYkUFxY{4nd$MCc1&Jvvbf1&VJ#pim3KdksnQusba->L9Eh5u6F=dFMTj(X7Yw+K#o zlK5FUZ!Ulz+X^B$=IeC)Ed40K$^U7EPf+-?3g4^vOjh`livEDYf34_sd-bxy&rtNk z{tg~E%E>7cD`%O)rzm`?!mAWsEjaU~^}I=NS8uxu;I9|JD^`LroXe-a0KT~ZzGGFM z&vUr7`F&8~&ntX%!l!4xex>k`;MCg)g?~@soZ7Mc?@@gIL*W%|@W7GJS@>D{h~P|D z(=Sx?XDj-P6#exIze?fSo;NF8x2ylEaNR!tyWo^lr~6aESuVPrsay>Jj`Hht>lFS1 z!fbx8Q}~MtzeVA{R`|UN|Bb>A3r;zItnj)u@W2tDhM!IMGQlZlufo?T`g0WCrRXyX z|4)VM{8qGs2+pJ}bDZ=Z{@!k~R9*dY&aX)BQAlRu8p`UiVWM z3GT{Y{DnM!Z9gAUxVE3Ef-~LEsB~v2`ll7XO3_CYo>cT&|6fw{QAPilqSxheGCgpv z-aaij<(!V6)z7txKCAHWD|~~(cPX5=md}2L|5o8u9DKl09<9%q!nHor3fJ_T6|U*` zC|t{PP~m+@+sgTd!e3JOVZo`N8453D<%gsE+I~JHIO(hLv;2=QK>sO4U!&;HR`j|( ztW)^Qihir&qtpFQMX%+2OVQ6%eEJpr?-ah8gFiUtSC1d=Qn;pnRpGB7j@83aEIc^3 zeoYme{B`-BtMF$KX8BwyIQ2YB;VTur*4s6T-c$4&6us8Z9fDKNUnu&=6rY&FpHX~t zJ$+lzpR4GPNx}oi{AxKzCy5TO7pEr;Z0Pkkd6vSNR8Bt%*Ys(@skhmR{>zG9>tU~= zpRVYm>)?SSpE!Ot-PwXOUs?|rD*8E!ex<_aD*W04e7>RR=PCM|6}`5@2NeB$MgO$m zt{pzF=+9I1Zzz0$!uthhey>+}=@;RFqkcH0YV~uR;H1}bo~-C=75%3Q&@WZ^K}Ek@ z@%gF3zo2k!|7pcXm;0THev#s{Q_<`4-KXf!SMSkYgh=(YTRQ26f^eQ^pNILfmTKPyjI;a^htbcO#x;q8J`o)P$c z6F<7^75!`QTmIiv_#YMil;U%N!Vf6?LWTcc;TI{qU-8%F{sJFn;9NQHBoSOOetP_Q z;d%obT-*P@2~Iv2<7e}Ar=r*C{!r0hqUfJc^t!x$rRYDW=s&?h2^{6r^3)c<*B8KF z6rA$c;b-Oly`tChhuFx%xqADY;FO0ZX8HU*g@YshI(`;EmYIYj{zd#O{_z5MyWmWB ziK4$&;Y$^sQTU|_|0l&?=j*$QUbiRzsc_n}mGifX&l?Iqj+F=QRQ$e$pQS%XaOU@r z!qW=Z_PZ11RzEcb=vONGW<}qr z==FGJo5J5z^p6+7XRt8fDCb-FS$Wz7r<}_a-l^zyy5Ci}=JSN&^LfSR1x2s&evBJuK9dN@%cN&=MF`$`Sd7yPH|azeprD1 zc}2fU(Z5oFe%RlG2#)&Xl$GT_QgByqpH%dm3bOPQ70xLci%(U2biQg7{TfC8kfJ}V z@DG0(9yrSLD1MgzHw)lb9!=`O^*wr09^Z;v%jdK+^7y|ge8*XN{NEM+3l8$&D9<+h zET84cuANGURc?xHk-3L3VaMIr_5pGgA>Fqw)cAr`+ z=N3uC-(S_w6T|F2*c<49v-EZ!?ClP2_s6sQN?LlmKVHRfhfmP=U+my^AGxH9ALrBG z=HPbUwkjGdoK4s68`kRJc3*BD;jHQHzTCSU-0lPRjDy>Kz{X2?+H~zcT@eSj`)<`b zxZQWl9F?ZzxBG6bb?EKBTip(B_uab1!R@|V`y9M%iOGK8kb^G~e6rZ1&6nL5YqNvf z{jYX8xZSsE+EIQwmXF;(XM=;=eR2X5R$X~TV(F#0;_F>=ZMJtS8(Wr6NMP58zyy4O zy)-c4Qhe?|VdV;XNM1PsJ89&ICg9`yWtTVNK*9ke*tElsA*3cUA_1LXKI$Kg2YCLT z*=1q^j<{-^Fl+9j)6CWyLfY7j9c=J{v7gib-ro?Sv+9aEbIc-gcf0hDHo&$s*8g$b z&{QK9kZbdg{F|gSRIE-+$F|e9{XJQ5sb+p8{QZNIt__f8#(K?~C-VGD<5wasc}~i4 z^lxnXx6qK3v+3Jw4Z?Wu>hCN6=ttt%Ry!NdViDX7rN7>OpQ2j`sXwOS>aP|UdAjm% z{t7_2GO2IAFCX8^QI7!LJJ}5M+~mg?ZzIYz&|-{;5Q z$3j!iO@HE~NoRzVs~B|eBWF&YY(mbMa>gW|WXXtYYvMD973Db=;SFitmru0)gZcZ2 zxs5=V#|9QH#8KotxwtDHE^fg2>to9i%CqE4?2)9MIQ06v27Jh?uMQV`U26kHay}`} zGUf574<eV}jeJfLGfO5$F~D9Q&Kw<51JDAjR~4 zFLQCYq`^CVjFGnOIR6x7oL>ydALx6m^69>x_cGO{?&xQu=ig2HlS7(ugmK49$!l9-T$AJ5sL6R5~?`qG5;b?gqH!&O$qDgGH z-}VWS3g<1SpY_ALOuK3lizcrrvWIiWgVhJ-boL`r$Qw<5M&XCNOd?!D2E{nZ-ip5! zbeXl(z=t4aAeP=aCw(ZMeh$Y>iw#86yQBng6m@@DP3H^26i-3PY3f;PEFHVbtJ4QA zx+HpW^pfc3qILF6X+INlbtd9nW0_pM>l|JNWhpx!n@@D>2!lula>yQ!2tt21>!Z~$ z%C3`@!iJSNVK4ap`zGRAQ~83Q3=4b$7zVe^he3EnsmBu^_R@QkZ=KbKLJ4^tJw?H7 zWvR#8URJ7O;r!0T@9crjf}Kx8&E{-wSY3&?=K(P6kKV<w}O znB9@1?=lbbgYvQV-FzO|7wbGOQDIIVQ!juqXpM#148|Z~ifvT9tJ$|*d(b#6BbZ|E z8}Dk(*`+bGc=`<+-OJR5OTUsE?At7+l|2&FCj=%0 zc30}Lj{=gphFX#QFL$>D(+@mS5=T6?Z8jruS1AL|u@cr<><^g6-ejRWmbmXj3A*{tun;Sq@fX$Pez9 z{F6Ux4JU98dmwlC7|vSbc*`RV+|e9Z$>yIF!Saqv0De`LVL7aIHsbH1aFLK|ehWayX+ zxAy7B4C9mA7isI$+SfpaYEx@!Oog>&kBDEu1*@b47B?=FD7$z_gzGzYVbs=n$Kk4!vWk+8`8@Jh{zK)efZW zk!06Tf8$59qnE#n-@xtJ>@H(wM=`&C`p;WzPwm|J*`l^nas7nCzpHS@we&w1ob{G< z+TtH!LkP$E$;Tdx+c{p+hZOFgf#=I}g2FEnKBU(;hPlSM_*V+x|0X!)ITk-F&z*|? zM1|j{=t~v;n8G=YYx(>};jCX44@v{Y3!hIdexl%%pKYSW#|uvVYduF5A3nla`q_$4 zSmFNJTE6~ue*H7Fd|b=lsrYO8{WG-uaye1)zfsX^{oJf@o$kL0&iraV_FQBJYd$@S zkCt@vVwJq;Q^rL`V9M;AiP~6`=pAqGw-Z=?@g3|D(cBQ1l;U zhTwS7xIJIl#peq><<$1DRN=bZn*`_OMEtCr_Utn9(f06*8`_@dGyCzx|Fty)xkY z0KQik;yu9MYSur5d|6%DEb8NI9G%(pt^O|qMp-PKkO#I%`s@d_vvS*O zD+2Akru(79*BI|z+D^e(&$Qbo@waFY_f~!jCvh`W{Hhz|X^IqOMNPCwHp zeeZMDHZROqgn#h&SiFI$?BPsr(}dvhDT7997kTM-7h>uTvuv0i{>_l{*quG?RbFOH z*z0_{?byDtoGZ?J9G*nP%Up#yQ9Ey!=p|Kj2Xma8YUSJ&=9@>E`DRRTwvEA*a~Y>O zA8hI-JrkFC*}k9jQYD`MKrr(XFAE`-W`70TJuVZ(yi4*TK)9Yq(*-P(?)&CK*h<3u5vSe3aLe!9sT{U*q|Ja-n`wSxwuC}hR zy|HbMc|D4`p^d|$rK7JKUR@gMD4vDMq{~N?hJav(X*y1@KgN6;(SUe#=8WO|d{Rwr zJ_(aY*Bu!xt?D=`UV2;6u+5lH!W5G;pJaDv^?A8}X>oteIV7f6c&XywL*cNnA#t`Q zl;<{F>FjyZY>S8D^G^kEY`#8eSt}+VFwIcm@5a5Xb@iEbI5@|i2ZHU{m#xC_5!mg% zX=#0<*{i+4Tmp7uU)IDe%vU*km~$t88#44Pf{`PD(=ift*r2`DkAFpOTY5Y8U_YkE z#EaplBhIq3V{tnsA{aRNXUHcNuH_Gj{N%%*b(7`B;?`!G9sD*M;lDek{~Ha~Ly(uM zaEDeAV02H5o_ycnx>9JYZudd2lK32Y@RnsmXU9q>x7Ucoudos28WQ>c+*mgz@tx>_bKhhBKPT~B^7#Vf>`@Z1 z`nTz^ePtbsSU|2lVi2DA?Ks!Qx8+x8tXm>oPP4<;>dnIRyRw@wF^B^afscM8@N?5I zG}b-9Ou=pSFS);N`V%Le=`Xx^uVdXw6*3%t?_*v2yh{XN0xZPgo>(`95qt42nz8i&^yuQt^YuL^)n;8<~IuD16m=jAv zi4`kCt8moHgistu9)%K^)((wrX$W0#gcveVux@xnII+!$(Ex+-Bv%n3XV z?`vRb#4B(t&i}F+jMs4P8jDJX4T?>v*vS%bER^x1(%j8HOeRP}u5+~3g8D-O?$42WF zuE%6QP`DnG{Z!$a&x?YyJw?6Ejmch7^wh5%tAzw7J%82}8teS`)-q#a^8b=C&AT?E za&>L4(3qw|`jl>o_kPDT=eV7Z@NwZn^N;T}exWfC(3r-K@t0Uaxmx)xTyRVy8CWRZW%QjJf=|`Marh`Y!a|$283<(-9*_BycpJBHrhkASWw1 zFWJBUzH%t7^VtG}l_6Z=`4TB;9jB#XDIfd)R2w+xQ;tIIo#y)&-m{IOjtV`uxolN& znV=ISzN?vt8&Ujj{8NCl-uZP*YPdNxFSZF z2-Z842E6Sp%P!?In2CGL<1rUN?)D#)y|lS*pMY|0^6x!=Df5GBj$06&KYi~ns0_4M zomqG0+I3I+Uomny9bquNozPbxy~PV~KN^+a6s zbClKnM8P9ISzZF3FpL8~(Jk4#sxxpdxjkG~CY2@3pCJ|xrl)b#t2q0-#`Y|)Re#M2 zNi6Qa8?fs@^SFJUux+-bx0>R3l+NOoeufVloU|6V@n}c7X4*L?i`%e>@F6}z?)Ame zv(Kb+`G*XefA+NWV+D899VfVrXX$PID3@@Hv#+AF;TGrTCUjN)#q?*)(`UpVaqw#K zdk#KZ{2{qg&-_{EKF>vLz<+m+df-Bn0$-cjuTTpOhWzC!f6H%9t^TYU%Iu9?3qAjp zN#*DkIzE%LEUi6RJ2_c!w?*3^@!Sh}Xjka@Z;KG^)x@|DIsQV=e_MoZzC&-*x7Qkk z^WK%;fWTXw_#ww1fuE}4Rl6;sKdXQ0kFBq(zYBp4m3~qLT&$VmKIHfp!9P^`y^{Vx zp=bI`+fDxpU`(n4KkfEQ`nH|3VFH^t#8%^HF-ybiFkLBCfJ>V}7%`W;M1Y8j%UdhI zg|EZSQ2F2QkI{1ZV*c6o+xXUg3yqCSq^tY~n~+>x`G=C7q@Kv1ln7=A&4tEpoWHhn*yg*4>e8|$BT7r+$IL9XdZsk4 zqYnR?V>YHY)cOG*w>>$1c{kLUjs3eGBiV01J`9}p*%%!M_zb+ysy@tQjS?SDPi@He!z+H|Fgnfgar?U;u0(Xs8|NYUaU z+|$vVlu7-`d4}AU5Cis&_}lfblsAMQZAO{|-1#mdS6eRP9i;0*eQZROP$3biL#AVG z*S1k73-0z&Yb2g~ArI{e^|9|YzU^bJoR+tZ&vMqzrf;tt``LR<_s`m+?p@k>5`Tcr z0NW~Ys#ILwTK!r0T-*%RN3;qK2tStIlUU$&&A=DXr;$%A{Y*{e%QgJExH?>h zHGKG@e|m7+$nvh}Pp6%?<}<-W z5PBVN7X>?y#2qr4oo%9~$SyD^{Z?Pb@G+W#Kv)skUzQzjXd;31@4fWl%Kq#o^T9RV ztBbzza(&UlYOKwqYCB%?1}x32GH=wq^vG}=N-b%_>umWNdMFw3+5d-OQnBXshAvX`jS%V?LofSPq<@dZjfJd)#c++Uv7`Rb*s)_PCM~7}|LguIH1Iz( zAL&6BJEpyu4S9Zz?)2Om-TXJ-)ul^@T{Gk--?NS}_8=rmX;`psKci5A-5dZud z;Mt|gqT#3Uqw>LvfTQfMLijx*{I28`tBpH`&B02M^GB4HMN3O&`*Iu<8h^b-z*2BpcdydL`-TL2cqj}4ydIDa}6 zKBEABUIBbb0sOK8_)6fEa|sIw&f3{ExF_B!xUn^0UHA7oX{tQ-rDCYf_Dp^E9u5n^-EhD?V1|%;AB3K_VGWpie}(P(<>X7wqO>~ zUCWFotd_>*^0>v7(LRB2H>+{*GOD4menmrLpsubyab;^`-KBNpgs6!XZ7n83dtF-# zJoO+kyWQ2*H(y@Ir8&ZG>8dO1>?h?m!WR-NRxR_x2Lxe*JcuFg1i5m|e=L6X+3p;{ zInL#ClEqn0bfnkoeV#O^KQ5+jE&WS^b8N*rU~#+eCvn=3#XlhS<;pW#;T*qP`tJ(v z^7(SttKYy*h*E}cj*5V1lZ3|`bt%BS7ZgJbUu#D&|o-{tc-Pd?Z zaQm!f={E>&`$CIv6g(tXi+77Z?BJWkU+&2WySNs<{_#@(9;^6zl-{9a@ zKg|wq_0!_uRzIx{en9*Q2eDfku#FBAM02OlN)RtL9hFK%`4F+zWvgNFpa!@=!-7~36u zvC!{ua669aad10+*yZ32!e_68R|)=zgSQC2&%q;tKjGljg70^5Pw;0PJTCYF2cIvv zwMW}7)e3Iy(c)G=)*dZx^<(YP;#NP_9xZP5W9`x6cFmf#M~hqi1Vk>2+i_a4gD1pq z?a|V=3vTVv;%f!B_Gs~>;MN{3o)UbtTrIvq{MH^VzESXyL*Fg_u!C(&eV z;?uP&J05n+-HwO<)Y`zI=j?~t>)Gz+{I{FW4?!_8_-_8~cTct*v%IbR*58Diq4K|hgM7Gd|6-o4Xi_%5wI4n^xMj~M zqet;CKAQ3`xxa2+>33x(ajR5_EfUCQHTyn-;Wm9fs|}TYnLHrBNn+*P^e3J^MczOA zZzS}~YyaN=YxfAQoI0t>U;O#r*K%&2l@}mlZvA%=US?*QH+5#ost+cC4G2>Tyw#|&w|noH#l2VVLQe9esrnEh=#N2X8j4}q=h89Y33fwyNy84+Af zc~w3h*)YD$>zGkegft%FTknf5c@T52=Y!GeGLPE@PknXe&$-2}edX}FVV5}8!$j{- z>dU;$!jitb_RKK$WCZKmK2YihyBA?{`H%kRbN(v^O!a0e`i`@6(Ot!9uj9d@uK4tQ z!TXL2ZhPSM>X}6)ZM~H}oew9DNWK+DYQAXxTs4Wk`kh|-622~>$ox_-|Nh=v_tJjk zGKD=+F=x(K2a!1Lyu_5?xa#oy;JA2rNpM_kxHUNLrf?FJ!Ev{QY0$xOw}!Wv>mA|S z%ymb&2UmCQ+v`e&4*>VLXD{Z*`C=ior#MXG!+d!$E4_K+(2E<)$>UW^ZpVkV5^vou ziua%iG~XEFT}Zr(Es5DRIhOt-c8Px3OaCadL_PfEyySCm)c5%?s(H=TFnELq#aaVP8a6S9) zOo>-N@&>Qy)&A$q{uddqIF8o=WzqEBn#?iLbq6A-ywP=scnPLHf)?fVosnRwk!Z)8 z6NBqd2NdTUh3fRf(T<%ZvElQ|YSO{%RjB-UH?qgnY*pSJJt4}|S&w?bw-2L(+s>BP za$fr4@M3HhA}{7pRH-n}^DxCj&$U!33UPEK)t{(|B>TsNN& z!@SJo@cm<{88VIb|E%Lsf8vAOGh}fTukw&6c(m<6{kg*w1_=cN#4aanX+uDmLRxouTvd0u2Gg~$5{G&WX2OC@Pg3Xk~uW@5a z;!9r9n=FYy@=D|;^(ZpX0i(q(%Sg)9j%w~w%_>smrFT;q6}=uNa#d*j0NK_LBBPX^3E%`4ZN=`>Y9Hb`PPMNDude|kJXR5 zF<$h;{^$MuP-uG~>gWwkyD+%^XK1JKb~ILBoQxOs^dIPsb-Yv*@4CqtU)TJ5u)B)4 z^Vdhji+-7W>-6CI4)lON%df_3eBMql3@3U+=2LPk3t z4Z*y#e20lW%F}ycgdyJuc}X1o`pyt65rX&z_@8Aoz*=R1=fVI-WZwcsQ#Xn;`A8AC z7gqg_nNpZgzvY#-=K|?$JQVe#uJ}#?lYuRhZpx-h-wP#Yh*Sbi3r;C~NrQ z-ra9;=jp{}t7eo`Q7l;f49f-?+3)Qm?%556^po1Kgy9yqlBMtM*ip>-e^hWi zYXFj?FW&VD%8b(Lh!^eeKR`WqJc{jY-pq23bJL!6Jj%u-`D9&YH2UB4 z`DKZTbGk0YF5=I}(@iDb&gW4De!gcI2QYi4gD=Z(dWl?Nuu#CdU$cx8XB&>Ooi7~W zb^NyI-1MffDOGTY75y~2XE<3z_slRnVlo!M)$m}Mz{Ea{-Gm?n?z6vvs**1b3#Lv) z7vAgAeaYBEPfI}V`}`uCA6jh*a!qL82_eUvBp z+X#gS?W|(-W8X&(g6lU8pht5ttN8c9vZCJyKM)z6y#P`69EsKgW%Ov^WBA_wD40SX z2@DHl{|Gbkk?e2HEgvyR9w-iE_veu8k8`&suq2SZ#~>`u>}}@OCIl$^jR6R1U3TLD z1m%(afISi6+|izy1)0 z4Gzr9-{tFm8k!fZ?nRHmH3uDsv6A8xBxxf52-eB+$MADQKMB+OWsLw&&d3&dZ@dxQ zR{J3?=G<^zQQL1xJK7t!H#TmMH*R-L>hWM|BE|{W{vde6B=Cxjdjo45ypF!2-7|_R zysqNYL5#@Pz7*@4b+{(=LOfV=s5;#L@IF>8ff(tEfpohEZD|7L@iC88hy98#&9Mjv7l3AveCI zxBVjfq%l&{?8Y;IQYO0(q%MOH~dr6DKiA)GLfh zbQQW5e5)aE6$OZP94Izq!PIov1XWdmtb1MaA=f3~YSyl#dV;C>@NjL5mqtB}b&VP2 zrGMdN#)SJ$Kz|8N=;ni|(>W*r5n@$``x)&7Ai-^iumnjm_S5X)*HMRG?}-FE*TA4~ zhd%fU+|f!P51trO#!`Zv%aCSux*}T&Cfs*}Mgkpqdob?A5Y3FVaNjJCjKOiKa4YWH zM)9zXFw1!7b1=M(BWZZjr3F(vn3msx#nCmg<%1B#!PMgjh&z1~ygdqd(a@x3R}>vcX%%0TpP?!w$YP1acPs0RZ6GAlfD#KRR- ze7Wh-*i>TZ1kBsavMG-h?TU?iU{2@5?I-6M#M2MQ)Bjc3laFU;z0IJe8rhE&CCXyh z32qo=Xu?trOh9fyiO`gq6lp^gV?q8mnqsr%jR|K3EC1V|#XTSQboGvvIXUv;4qcl-*9O`}wysUz94+;Am4rXW9P6&vedDocr{e?3s-Du~Qs2}wKAq>e!U zNaa+R2In-W!j@DiC~2q_EGjgoiMe^Y3Ptzp-wRz$S5pzSfnFe(+Kj{v%f*WH>i{jw zVe8i7K?6WAwa3t60iBru=(>)*L%i$T4D_Zx7+lXmm1(~yK)G$eKHy=AWv&V1lXr02 z)u6L2)`4sslA*gmFA=<<7gmye7=LQg4@7sqH9Xq!yb%`a4t9Qz77NMIpu?tvsn_U- zStBPk=_i7zkD+MMp`lyzyEuPkX!he^Hz)m$JjSE9DBoTVG1$DqROY0A6HC8@8InFM zl6wdhs|K}VcM)6HKQi08b^T>_%d3?2X;Wu8uo)ffeC!ZJ{xGeZO^X?5`PFJ0T4K{v z)%9QdiR@PR?EH!Dp1OgX5(q&isYJiXRv{g#(J$}zTo4|zVWTzaUuQoI3d@fj_!ica zj>E;lFa0C#SkqW(5D{g>raXWyjpdR(i|Xj?hmoQloeUM$q~D08e+j$ogJr&ivf?t! zcfhj46gWD#ydAauq9%Pf`_+S#8SG=}XLJ48xBrM*#XU6v&=vObbSuZN!~hEs70>nHfJ$_BCk9)Sf)_93aS-y$E74@xy3^C>9iQ z?Qwml$heTzg(wb;a`f{>d%h6XFU7&uB3eMoFT%NC;acp5=S=gA1kP6VNT zFj!OVJQURPp{FW)_$Ap=l}|`(CJpg)__7THEi=A>tp^xbI^82~+M zSdGg~g3ZQ5#WC5{5PuMDb{*QV!RWb$7V{Xf%(;@(^pb2N(57xZe}og-(rj0|&PZly zA=ARx)wl4{-`RaMIk3gkRie~8yB5!8nUUedCwJo!49{hp?eu59+R*y$Du2*#Cw52s z1AQ{W(EABvV)GExp2Fd7Z&419lR5J_#c8IemT)xHoH&P*x0tfs7*2vXIBrw8+gxu7 zZ!yKB^ZlE68Y}98rZ6ZQr!yOKtxzf(<@s!!i!!fL?|6&Ihw2g z^1{oU0oejDk`i9@I}BTJnX2A}Q~~XIV7B(>vL)kz{QH-`NmlS_$#ar{e2$P6DIfJZ z=I?*~XENZ=PxE}v^iOC2#^AcnIQ2!uqaF0l7Y?R`J9drc&gfP{tZ1)VK{8d@FlhaG zFvH7Nakdm_02?U=Ch*Vyy8qR{|7zfWHSk_EP`-Rw%ea95_fOGRR8Bg5@)>7NshS#{ zJ_9FO&hldC&W_KSJ8%AZ3l`QcI{&kaFW`0#1zkS=(o5@chUaC?%RYa3%N5I4wEo@7 zRf)FMYuc~;!u#1&PUi3aNLEK@NASrwYH3nY0 z&Tl?xW|by~4Icq+4E5v2CGI}>5jQey9YXQ#68Sbu*iRWYtMp*eu-zsP3`=QiKK3vhd5=U}0 z;UhKkjaeN|-Qe!xEAffgij|F*wly{3zQHG|t6tI4vUKIb1fpD)1DjT?ykcph3CBsV zX$au(^I+DqgL|NA%d zNn5@B8gAehZRYE`{5c=KcXjUEk3rwInJ?g4_|2Q-4PU)cJbqE7XK0KfeurM=BzA>+x~;}v>l7vZ`(-EHk^Gj-ADp(7B}y(;6Kj6!S|9*vQ{?8WRKT_Ijm;bW`@YT{TQ~r~c{5LB6 z6oqdS+~q$-+GUr|8o^!q+ZDa$-=lCX&r=0(h-Mu1%wIbeQ_wLzI*YFroKsVD7EcO3 z(uZ^SGbDhseYK_EAoOBZIr?fzP>LmodxG13%<}0GJ|UAzUY_|vA9nC+X$SahLudKe z{EqkG9B%Vl;ovsElO5dVx5~k7ey2IOl_%ohw!N!%aGPJx!RJf9YoVjLf_!vqXchu@X>;|IQSUBTOB+kc*4QMg10-km4B^+ zj}-c(gPRowz)}uw<=^1oR{o6+K27*{JGhm9lY?9NH#@lfR^=uKA20m3IJlMn76+d! z^jjUgO7L49+{%BOgGYq^4hOFme7l1;3%|Zg!NU&zgy7{4zF%-V=VRr3M(_%U{(#_<9sC8ss~o&naQEBJmjsVE^alm6cJS8( z_Z<9?;C4>R%Kwhw_IcOh=0iD@YpuhlSjNYEZl$yIc5l;*9ekwFFLCfP!5bWWl;F({ zK3eb=2OlGNtAktl6AsR$h;;1^UM~1r2OlqZ(!s6#DF>e{^cx(!O7M*iK27j$2agE8 z$-%Asn;qN}`kNd)F8CG)pD*|=4qhwxRtH}!_^l3pvEa8k_!7bIaPS7fw>!9%e}{wj z2z`%(KT_hC<1Po^C-`0m-ywV+aq#^@zt6#+5&Q`UKOp#i2Y*5EXB@m&@B7B=-`_L?{@H;1mEP~TLj)=la{)mI`7krcVz zgBOqR+wpfCyhL#Ofj)!zn=JiHv6^=!ZuhJxaqv;XXQYFV7QD>C#|S>k!9#-c3|BfU zPgw9V4qh&J$ic@89(M4%MW5vkzE0@JJNS15uW<0M2|n4u|3mO92mgWK(;WOR!6OcS zui$q6#_D0G;C6n<;tvTPclbOkxSb!e^gkB7)}jB2;ENsnXM$hs;7fkpCew%}TPw+b& zyi(-Z?%)}r-{Ig>g}%qZ&k=l=gPRRxq5r)OZWeR^f5gG9eeQGcUXkYs2R~8L-S6Ow z1b@cCFA)5IgMU@*{{;tMD)hY${z1WCa`0t>A9V051b@xJD+E8};O0|h=;s{=e_815 zM89nxwu^p>ixCOV;``*iREdK>KGLTf>EIuhehMG28fW=@OmO=?%Hn16o-E{(=h78# zV6uZ(h<}NL_lQ5?;C3ExtAj`6xoDSz+vl!P&U2Gpzfj@e?)n0oFS}l##i6(B1>E@r zyI#P3ez))c-REWd{@;CWweSDk=Sutj|NqxLxt^EzTvD95_fOW(V47sa0&?A7?%&w= zM>IzknN(-9wu=-e3og}(kZ~uDv3CQnQtUZ!JnqQzFO6S`xa2trKkaP#QhjqlHhp`o zK?v_@pV~!4{%=WrwP7K9Bi9J7L+P*lG@qb*w11`kIOKBmHwPHgxAhmd#=RKwuc!K# z++QoVy`GN{d!Hl1P4EQm%ip`Smm`RnoBuM2Z|6@e2P?nzH{oWe{BNgX;hH5u=AUI@ zl# zIOl<&e20rCfZ_|9bqadp8lP$Hted9Y5;94oiYJYeDr@yiCc#W1p3*?kXE&6oB@Q!My0#y_D0yH<2wMpoGJ36}v|K2;;H$WJ-* zb1hiw{QRrU&nC%F_EX45cdTnucq@WLEEda~aZx{uC6!@r9I@G88%eX(;9>M|4?Cgk z8Su)tI+^QRAzscHy3E>|``Aud_BPK}N)KOvT`^QyW&Z`ApWAOTp_`P=!7_X@Z1?bZ zUG_=xEeHD)1XJfCm?c;OdOCAI%D>N^hCnNU5#D4drc|Fzg2bTen?_Tgihj@f6ifG; z+KUhEGR0%d!IxhN@!PkqmhhN3{*=YL8p0=g>B;!)(R|B@?;oe)YoB212c+&O4j0`6 zg+RZ>;o!DN|Fr%M)!~!dj>g|p?qO?=-LLwpjDDk;JNJQfcGsxMUizu{xL4<-dvO>J zKeHL0GTF`8M=D0ibw`u*>^)2~3lG27XkHsLO0GKWu6p{+IF z*ggd?&s*WgWz$T4+CIcD?v#l&@f*RXO*C5`Y+qzA7Ne6#xGUdJW%mg${q7v-;V|2{ zj>Fj0!qk0ilC!U}2YEA$@JaTt)#GOdw`Lb|IEC_BJKJAn>%Ot(vw!Qdn@rT}Bpjx*9f4tz$JA+^3rt~)L^eb}43}YVO z7RP}-#liJwC#t-x`*#si}L~N&a31(@qJdN|4=Yqk}0n!#qbQY9<)X>|@;5 zT=2TjnhF=e=li2@6wm80HmR&p?&1-j+KbIQRz9DtFl1;ChDx>Xdi9O2&sg#4ID85= zA`^wK{z$azx=~=(ap<_<`foxoTe6u^4-8Uiw4?u&;0;f))VkK&Sl4m02qCTJr);(W z21U=Fl&{aptGK5aEBK%sKsCdI*Ud#x^ged`=J8zi0_ZCjyBx$k+BMTx&+cHy2bm5O z$US|IgLEjf#G`{^^gY6F@VXWblaT4Vt4}(NI&S69{)o-eowJ7r?_7wD>3q{>Xw%M} zB~3dYC<)&AaPZE@jge=+X_~NzRfOV_K**mc513Z=$$a}K>Ez3c;dc%SujV&~IYArp zdbP#3IWI73%mY#{nrv=%KyW}=t*I!6!ju8tk1`?-BP#uiQKj_vRT@651I3f|el(L=oJc7jbiABI-< zmc*y-_PV}&w+XoU9$a>J&~tnoalv9khS=&$!T4U>1h@ToLxw3Jnoz{kJ6AV&U77oU zZZJgN)JMH^hOt-A#)tFRD`S`ChAqQP07zC(^bqFx$?Pt|7pu9D4-E)8C?UyvH?ygY zaTnE054gwECYNoOMl<)aX}&8ELHkS_MpZU;fVuJ;Z&V1`P@kn_CU*t%c_MHZ*mcR4xLV;aB+}2uLee*<)Hc z6P^oGCUBW)Q3C7UdK+=D(_t|6&$wCl);su{n7Zz*cX17-zHYF?`0M!_k0!>N@10Fb zcd_x7bnG|ULKf{fbjr1#661{3_n=3706A;JSIhWX+QiO9Oo9u#g+t`l_N;V1dAeA- zCr8Tq#;2A*-#2pYg73dU{K@-G86`fl?k)05d?foZWHfKTR-aw#q&-_RHeZD@BOl18 zn@cpw1PkFDI7HK?lYBexU9UMzOK3 zMMs*F@zTG;hwC8cesRGKiy&++_t^Ce1rh6-Q|xsu8fK~?_VMcd3HBw)o@uI41OqM8 zBA_K>+jieHFanJ?Zl~9=b6D@UK`QFWKF_vyLcYF8hWOOz52`<}M6T?K-o>Y0KP$+9 zFJk6ve4e=AbN+)E^?}U@SPaqo*+RwB4dHU^B*gKnzYPKJLVZD=m*+qAq;4i%=2Ox8 zshK(Bu%m^~drnuPxM*%y?btwU-QhR!rftn5X8$05&mYQFT~KqUPX8#s&K|RiN#bVn z=<8>q^5K5$3CV3>v9spkc=}1^1cE|BlVJKa$;m|}bH=@a^v(z@zR*05v0=*VXHNQU zZ0N!*9?N50b?CZ31RlsBj?sgQ*#li{5n-(udV$Gr4$1j9hyQ6R`C$>GLfVp1r~J`RE)M72m^2 zspviLK>2=oW{-eQOiWXsS(P~|e;beeTR~dwKTE_j69-h}%?Lt8_U9FLA6axi)nAR8 zJo>(UsFr4b?qKS2);T;6n!+Iks+O1jBAW%TtDDBWC%G5obbFGcO8m!d+~L8?C+}t@ z-;?B1nGb9zLD-&T3RRInEYoSYnJ1KK*l(z_Cz{?9>|Bk&>hvAqBxq_fKUl&lXO>`L z3!+=XDWce$G4)&E*rb7+@NhInuEh=T)9RDB&guHrZAe`P)qIAk0&4bSiI^KCZT7Ed zXFaIkUJJ11;tZbS@OrJmVz@@dGjDSRDZ+}sqt0XH3M!()aq zjdrpQrmly4clUpW`Rv+yy=;@mf`2*M{|{RLc=h|db!>^SDQs=HJuw+R@GrZUSxKDi zb-Wb_-oUj|W{mc1<;%U7VaqIENvQ^Kr@XO_d(CTke_vkP{83hJ=ZDiogPr4GB-r!m zrIP4fxWl951H6158R@BfxH^p?(X+i28TBl)F-+^oO+r+s4+T3tye2{GyA=TgTHhpq z!0Rca1w0GAgZ9hRYi{6k7c-8XXTjTK$0X2k=sXs1%0u#%FH^=(Qy#Ph?QC3c;KPhp zghImR<d(7P)lcU(#oz#ACBevSiKfplfC`WJ-S=5UhrdG3!_n-6c=WKDd5rFv3#L5?} zKN8&ZQ1*D^OM(zabT5r4ugs?Ot>KLbz?|0xTu>7rh^Yy3E#~XG?5p@#iFSf=qLCIE z2Eo)rXjL$c#+b%NVPYmj-1ZiVYtLR|nw3p*U1p;|O)tM6RKbBgHoC**rt|7_i4T8sK zbP|;>;&MWD73)5)d0YS%G*!HypH=U2S{p+4+2@52OJ>B^zkj~!C zfi=eoPoZb&TW`m!+%gWk&pnj9%Z#joo!>=|jRrWn=O{$O-QP2*bGt@Qw^_UzSKprYthcRmwj0{5NxdA+L%~k&RgM;G33gO|4smR~%KDFx5mW91 z<@urCAq*jpWc_F=j#UmS2Rn56qb1=! z&i46-Eo^LH3!88DjK0fZEZCgTc*Oswgvghjs=;tx6w=|mxEAU ztkisu(76}Ewuy-DG2w^}`y!tC2SblGb~fp0tDA+MMo0QGQiHw>Sj<_g*)M&s}#%|D@8XHm_0`L7&2yyBTJL+ ztC(8y`2bOTvilKW^^NrXMl^MnP5&;&^Lwwnyr#Xh5-{=OnD`AK_1p1|yZmmnGm66W zQ>EQzXQBBu<7<&G@i`;gqMU4`%I7gV&Bzu}df5&Fqn8tMaj19|=TT!~DS!r+HYEEh z_FnDw>TAPG#_dCm$vzCpy1l8jVQ+Qmz$&WRhwMeDH7FNdPgEO$*48w$y|-X9&g?`( zn>6YA-CcGq67{R!g=lS+BI+4{eu%``^XZW;%35BqGXj+7s65;IZR`Y@t%Nu8AI3ah z4|Xm^T7I65UKhX%ox?O>F*Ug`!~INnGk2MCMK}L3KMz-N~=B%03(LA=n}A+K@SWz7lW z3xr||10e`gjk~!s=S^HtGe3SoAT&2RrzQ|OaqOxS10kdy2%Q5_>I0#%6DGA|0mj0{ z^$VHdLI7cTC;fG{5YjE|3}!n2LG-hG}gbP z9>%URpt&VlFaK8Yn)6E8jK5?&3km9}A4>vrQy+*e4=r3Yect@q*u1%+)|D&j8&|D@ zq~k+I>$S_SXgrO(h1Ax>=hi^Dc{2kG7cHD0h)$okfZhctm;iPY3sldEE|?vdj$aI+ z^8(Qe5IiGL6A#Ra1{O{aKuGw#c__{KU@?FGf|`X3L$l_EqFzn3I$-p-u$Ge^f!f%d z*xXqm!*IcjTJVp~i}TNX{+Y3W)bqUBh5p6(X3jL1^L_CATH}iYtXW)(vI<2P&WObV z@p-f6EvgMnzo51T+-EF+#%n^gH4BhjG)|$a7a7@b34w4vXj#%B7%yHO&zlP^ESM8A zMooC$%+P|G8S@}dZFEL-#=_8|SaraUXM{&4SOsYMr%#$v0peLPSjpnkL-S3JQ4b8m zh4X7_ssr(v@p+#O#A9=7=FF?E3CxREpN7g3TYzMvi)uZXe@vvPnLA^_1@miJpK>Iu ziwmz@o>k zayhey-zGAHJDT0)Q2g@y1Xh=}4tsV)X;rkeB3fELy)-nvbTnd2FD;pIjNx^FjNm@N zK0VKCs67YI$1Z@kf)}K9cwt|_21FlEdEkD`>+I698-^jZuHmyvLmP_`mt_gdE#$l5`$s zVsOMb=|Q*5zXYmqHIu=(ev=sT)j&XO||A8}_v!mHdC$dlT>|tFwK4vLGQ~-nbT*)V&_Db=F3h%5j5 zKIb_zCx>}k?RS0suIqpO4ou$n+~+yZdCqgz_pIlRyrOK)5w&G&kEkhIcf{6GuRL#_uU zpGFeEs4|D=Y4{O0dp%Uy0X9qU0p@=gRSxiExh)8c2n0o>kUTFFJccLDdi57)-r-69 zyHtl=$^bC7iz-}35XR)$Rd^>J6UCc+`w7AK3a;`lu&)cgR=!qLz67>O@J9LQQ~3fI zO;La&7zZ2wvl@lDUSJNRz}pX%Vx z2yW_B({SO_SXFHPrSjm6J`8dIUYyf$V5nK%hTW+TaeuBeig5Vs8 zvCS00Z?HkUPZvDp;O7W#+9u;%EBIXokmvb=bGemmE)-nHJLhtV;9To#n=1uZ^Lmy; zv*3q1^h*WbY0>hvOYo07cvSFL930EhV1@<$;ovI;?|1Okg6nk1Ira-aPd#(^Cj~cq zYK+Tg1lM{sDB3u|uXgzSx8PhYX`62dzSzOPE4ZoejGqSt=UJe(QL{YI11Do`^O(?U zedJuW3x1nJ&!KPX^K%aVE5X0w;J*|6`wsq`;HK?2A^%zMXC3;N1b@WA>90tg0%u zt6cNxbGr}DJ@EPH|KNka$kp3@xiC~;2|IU5FdQ558mX1_X0o6Y=}e- zjhS4kN4{_bu6}7~>FR6^G`F`lU)vyv9=+-f^kO{8U>s8lsFPYTyfv}AsV6eAN;nvD z?Yntdi}slv2Gia&mG(K=hIBBUtxLKhOPe?vH*sliPt(LHfh+?JOw9=#m{>n2cbe`L zTBq{Q8T>Pif2Q-#nf!AW|5Wl%mGV-h-_<$1Rf=q~LZ&D-lQmoAbBdywte93Q*D4iC zm10??!kMi9Dn3&*AI(A0OxB?&Zj&{C%|Y>;qTX>%Fl3vmD5ogOsfxoC#dE6Wsp%EZ zsXDsK?^K0P)xNZ==BE6fq4=Cp8OVRwusV#lw_|B;z$#6 z8_pnZAf5KHyk}{oRlj!Q;AQ=`w6m?NO=S?AU5p{8&aQ@zu4a`>%<;u@qCFiA&CS-C z$=yqOdN1xqh81?bt&wPVL!_svvzNy^D-SqUxkUm4^}^Oj4F-ifx|&+%bYVOIRMbvi zL*#l47H8jEmbSG8+Ayrz*)_!P#oe|~El|hO*3L+S6{+^7&Xx|G60J)~AP|)D$j^;= z_+gGg8GeV*oQmHC_!<1~1YuBJ1vpk^@B(SC$Y;KVA0{~IM_c$Y7X1PXSL>o+C;c%N zZocKo-=?2w@juq0pX0+{_uKS-!V4|>k6ZK?S-9>uXnBsaaC4TkE6>xGJRFZP`gz{s zZ_96=DaCITLtjJ%z>xn!{0v@h;dXkleWfA2Eq_{YJ}}3g<+IMBx6_MPJ<{-T0)8gk zA6oRbJY3C2!$%N5L;t!(zsSOeqdlOZoVNZKTKL6qGknq(ZpZhF7S8>thQ5xBVfeTN zKZD<7;fpQ&2NrJg*(x}rF~*{Q+QLt?@Vyp(l7+u(@#h$Vk!OZ{(vg3Kg`a2PM*=tB z5gisj)}p^&a0X-Zzulrg*`haRM>5<~Ec{U)J}+5(##!{Q`_P{%pRnXV-lDG++?BK0 zqGw%W^s~%|K5o&UX3_Wi(0|UNxAl3ygRcNDnk^R2F#sdab|3zKvFImQ^soESziZJ? zwCK%Qa;|>H%8&{5Imx1*B)Cg|zC~YY(O+)iRTkdr!>8Y(pKQ_J4`qwOauEa3u@{SMv5i$@&y`5>%e^78&Z&NJ#vn=|vedrfj^c>qY@-+I; z_geJKhbF(Ruy8wGxBBq;q7VLki;tbpe`w)0|7|{eMwUW280v>(izZ%Y`{37E_~jP; zO@dSZ(=GhtKJ=gUq5q0SZ?`+Yx9DeB{LNW240oo57s>b~arSLYyvi-y*4xPzezrwl zW8ojR@Cz*b91Cx@@Q{V~T6ndEZ?JGXpA1^~Y>WOG3!h`*Q)TGXO~*NcQxA5#cAZ6U zr{j$ly`7E;i{4I`w1wO4>9vO5}e`Md>*!NTb}1EKId9|_FD9If2r655e&nfi=PSiG{N0)ueRvJ7X6Jr^dGly zJHEfOa9jR@axjHqxOO_03QjrgbUf0cx6^Tqh1+~i_2DzsqPO{6ZsB%*xKr>`AZi+Ro#5niB7TOCIXlV4cl*$fJWlg>=?C~x z1mof*{5XN3Ja)eNs!zZ4HlKFn?-p+NpC?GYO8z#!*a!cq5B^6VoU+p}Ui=O4V;Y9x z(HQ(GNe^kRv-r59HJwzqS^Td;FU2d1R|0zh7{H0|j_t*Lyc#V2plfrLG$VFnTaJ zX=!5WuU>;lK7SKFYaE>8@ic4oBO9)nzhCFz?+X2T2QQ>hF!$<5md`N3?{jdD_tR|D zk1V|>_<)0(yP~!^_|ZbY!@-Xce5ZqRK7nSJ`kT{FQ1IOjev;sO9sFd$_d9q<^rIpK zH(IHGGvB24MOe6*4=NXbhThC)nfW?{kC$+R4t))H(u{NP2|{1#;FATP=HO=vZsI{_ z${!Xy?9k5>e1U^665Py>89t4IH#+pKg10;PHG+3Lc$eUP4t~AhF$e#c;A`^G{H4wMh$hgLD3e#*7mhobx|4qa8jo1P?m+ zIf8RukjC&iPw+|yUm*B22R})B4}={2QlU5H!0>Mse1StB5qzPX8B#S7vo$@f9ZeH^6ebqs3>fG{&USPJCN_61TZZ|Bz(g!KZ=E>z zf{Q2gatcK}w6&O5T?-)EU3`jAAS?(OMmr|4mWd05W^pVpBsJz7{jl`&o=AFYTKzch{%wr!#=pToA(#`*zz*@h*KsiN8~^=y$ru0K^_pU@5HkK8QZfFG{`tA> z>YiS9&g0)e;BNiM{&nT2-4RjI4vf=Y%v}Ktha$P*Gfnb^zfKCoYRAzHf6~;dGlG_> zJm_5`XHK1}T&7l?b*3hH?`LM3^OG5)5dYxsq1XV!GivnlG{54p7O&x0i#14#A%|J? z0pMX4hlH`ozXaQu)pr$+6Nnrdn-=gsHQ;R+z?P*W!`veN1!z(>Acj*v-_4M?+dUY@ zPUv93OK`F+jPupHd9q&!%#@OGIM2iY{v3f56AqAmw6_5q^_dj$y#+YM52sx56clX9 z9j%T&)U3G+Zxm9IxByer+=7}s5cxptoIvF8 zx^ykiw~36P&XSxXhAh|@c8wy0V$Hc#*tA!B%z^6He^VX*b768|BZH~&YIp7VB=^ec z9mAll-U1f-_yZ^**-JKAN2Qzx=`%S1zt0WfDH{c2bcPlt1|rqiP&N)nL=A^^QXq1p z#Jw*4v4a&+m#Pg!u2Bh=c^4Z~WpDY=ppyes6Jqy!P&i^S$=*iLN|EGKklB#sqxhO! zk@-CE>W4VV&-4xIB*y_7%#qds8oRtCcU0m44dz|z01cy36%=ySxJ-Rc9+QEPNAzJ^ za=w*0lPVh{IYy>Ft?ILI>IvkD>H|ks;Cxvx!Q{#2yT56kIK_ckUeV}mpB%yc)M{Z} zW~OgSc{MnoKz$V`fst_gQ$R9z!L#PvU(bRQ!ATJ)Leo-P!>J!V$huRxA_4DaF`E{M z+$kwYwKY~h#2$vq#f)q6NC=Sm0aY9S$$`u_@uHc}$0n$rKyXB9U|Cah`%-p~AfD@y%5LikJI`W#)f#Ek48ZUvtmi!@;H~+oI&$*rsqzr>cx{ za6k|34?Adex*nPxcF?Lz-9`>GL&;fAdZ==ky4yPo;^jnT85S60gLpqha0ga>N6P8; zG1w<0uAezyx=TAOFeL|N-}3EAm^#`+rx!mx_r zbc4Y+5riSm;bepFAP7S~ERzP`Nf3tg9IiI_k&;ze9$5Aa{y_`paIeA5+Ao*C83T0r z-ywX6b9%z?F>ATWhoAKZf5eC0j2V%h!~TZej2XH7&6uhiFEbWO+>Y1zWDLW{DEtin zg@U{Mmss@d;~RQ2*5}fH+v3C4&Cow@;kJIv8ZSDt4mI@V-YfEF`(toV`s}3V=eNO+ zws6)n2LGUi^E<)dW{ivcS?3yjqR_kg3|o9kEP69$MLu@Ez0sn#)BP5~UA=wX!tFJ7 z+bo>J21d@`3GSxva59GBBZ!}&=Q|DcCP|^}|Kl;B|Im0&5Yn>9_>JY5_D4tR;I@W& zkva((0(p+s4SJwY^vN>EaG1t4x}EmFKjeJTx2DehmExTRPRAR0N-$acz4~W+O`h&p zj`2Su%Td3W@Xa#>nD3R^Ir}#$@-rXV#`rVOIyjnlo9;XBG5(yFrvD*%5BB@Sf4j{T z??(Ryz7#Jc4H-b5W{lIM6Vs1=jemo)?7O-ri+foK!nonPam^Sy6U)(Tl-JAEdBMD%q|q8#!S^VbCNXrd zs3H``mtMFYpN$LZ@wRv)3y_!KmPa*Of=}Xdwl`{Qgh-|O#7ynQH|gHM*(`7vdqK+I zd?_sDupA4oc*U4YvV>fCW(>J7r-svu%hma{FT=7D^FKkHdNs~l{Vd(|F|Xm~;_rnE zb{yE18#@8F5V(CxG04YlJ-NMmJgE}DDTMs1zKg#r-#t+w+)lLe-P7G7`z-Px=aGn}3R5)H;sNf~P0fsnDxbbp1ryKGu2t+@W zFQ$=_mG7Po*T_tz*gf|}P{s0{t{O1*B9|) ze34$g3(b=eFgXzRYH*??IXKx7usw8TPGEj)d)%mdBVHR1Z z-Co6j2-Gkw%kDV>&8v%3hW`#tF)mB7MFW*t;M>~E+gSA5w5szVi}G;JotX zA{65IyC3paFQ#9o7{2P2tIDrx;8pLig3MlYxCpV1BY-geAP_4uq`2zy=<)C7Lx^vJgIEIWK7w4d70I6j7e}Ddep@F?y-p8<_im~6=B3nE& zw)lHehRe$1g@wN?L!T%J>oj68SF?cNESh*Bj(#axSWv1?p_w~UIp+C;Ruz54SMuh% zBGn5$*i%v7-WmIB>~$V&{KpdAFBI)J-&i7Diqxn;KK=(sPa~?f7~+Bbk6e#)h!gnB z2aW~vJJlY$Q@RIs5`LPOMU2wWOmJ~#)NxSevy zXqnopxU_Sra`D+Gs`oSI2D^lh9_;Gv?P$0f<5k=MstDoQ+|}9H+N@b>&s|;DE^Te# zR?~yWw^WM+nNP*f9-BxpL&Bh4R^P9vHkElxaON<3Y+@}5VGR9xWeWtpEI8>8$ItMo zl7Q)4YT-vo)^+K>X5su+F?@DeILoZTbpw@?r$*#%lB~#ZnKupnN*^2~%8;JF&xza; ztip&d+E*$UkQE0!G9}wpMie`m=WcBcz;4ugPqu>b#H)Aqu9Q-Arzs>yN z&=Z1lc!Y*l{!F;Vh2UoH$M7-bdbC5|F7Yz^r49Y%f(IRXp5RVnpEp21 zrd*G6=rbaZIfuaTe@Sq6eds*lKh@#$522st;BN>%%fa6fJmlb}T$}csWc-;qjj%&M zNxHW64jvSIfrB3=_#y`{6nwFRzbyTRD;)f3!5bZXQ1BK9|DNFO4sObIhl87P-ROXf{npB!~x9BE?aI_#2Y9*^Wbb zmO{Vy&8fA^r)yC3&3RqEmWcn+@;q5^spbR?1a5J{H4ehgSbf(=zgPc$b85!F8=kS7 zXRXL@=NSr@5cwZBgd(wY$Hb=fOe~Z|^vjx2`nirDb1>8&S-Se;GFk?~Z$aCHh0xF& zH)A)?%iuu&m4-l`3xt5*v9>YMG0$c=ns=M-MiYPy=ArEq%++5^{4aL=yKH;mo=<;4 zna48mqW+jAjenE>{N@A~i2qxh@ZGr5?#fOtJ0+m~;(=oUTsz^0?>8s7L(+X6nOVjS zf6~-5&eC&y`tQG5pFFv8>SVoA`Ms}C4%g=d2&vZ)^5aNcVEKW>laWgwq)fOk`d6XZ^l#P-y-zH8Qi=VR(}EpNlT z04S%&-UvpHh`n)6^qJbK7dM^*Y4<$MyEtkSFGfz|4Obh-VoH5*PGMym781h~7!)P8 zN4E|ZsRgT$BF1PB7J>S)f<0e0cUH+XKR|nLUFzN367J@g zG0QkEoIYX5MC0hHf!L-mQi zJv_EaeHxf+X1$u-^|f+Ub9a4j+v7LB@hP{l&AYv3?n9#0^BFvrCA*QWB1TgSsrmJsyl8Gw40pbUQ;M#*J5v z5ZTC8Nld#0ZP1O-8Fxd!k+ovxVhrFZIS!&zd@^UiU9mO%u!x_xnWj$|TzwbojQE!+ z@;l-9rXZ~mk2&b^lFP4@In($i?j|dW?8X(T+&{+^>ZesbS+x&}-w6AG9RPkTp;NEV z%4+D1)nK>h`|uVMZ|CFUzFl}XcO@OzVZ1$Id*q_&h2hj& z(WAoCU%hFZnL{>r6a!qbM?~CnSgw8$D5rBu2#3^uin`PRT^{$T)M&3s zf2SQ?z^$wKmu5)OT#OXyKNq)SVt2z9h^@Cjq*pQBQjf-;KMEJ}M2AUl2LmC7vm920x)VH6VJw9W_pY)1 z3FF?N>D#>ikB}Zy+NnppZ` zZTb$5!SHIuS0WS$XVg(dvBf`9zR%@`iD)s6?HCer5yhwZ_R0#QDt6S zfa@o#(?hPx<;m*|BZib*!37Xrml9tgZw zJ?>hsGy};-F!67D2y&>}0~;)MgF@X0dn*{=CQ-(;pf0_cwQ(3%rmngU-7VY}MVuzX zyI|Ya-i!MoS>UVVe=Nj(opkXM_W-DiZ)O}|%P7r!o?o%tgS0^1d|U$YaNpin`$(Ez z#ZUUW)T(uOpau7m{cx_1Zw|p;SeO1Zzc{_bQ4kkVqC~HUu&}Q<5Gje@*jG^P-TAoU zyqTFES~Gitc&{w-^?dlQZ$`*<@pr(c3cS7Bzk{9|f|{55HU;yNS3ot@vCXOhWl7zv znociK0~`YGUjylp!LZszRVrHovFsKP<>)20AS+fqx#vTwT&^kM=C1go1$EPZZ7r(zeLgeK1z1OL26JWv9u)B51xf|*)vPYsp!FO8=$(> zr+45XddIb)=al3!A$Jiihv3x@o(h^UmIf`(E)A+lZS#_q__{$;*FL00S7i%TmXvqY zaP!UH87~<`fkxC+4wL$!48?s7_#=T{MKYsSn2)pxL9?bFP~~W+B1ycA=m~>)$(QQW z;r7T8^RTXn$tM-<7m?V>mm(#mXzdI2RYnev?CQqu(AeX#vnB7z*1yr7L9PK9Ozn&dWlaes!y+nU1ec&-?*1d!G*z(MjD3G-3!9$ z1&dX>N&fDFyGYFHl;sTyxC7dS?l!RwO{2Y2i+Vn$Y&!VqJG{g)WxqYl+*R;Mc>0gL z1oJ%#uNtJnErhVKtj3Xpm?e)-gUcdJt>eI)}V4eoP6 zR3MCTP9a7c@vo|$U*?xX^ih|7U_U(7r=By>N38Go1PYc)4<1#bTA0iilt5Cud$$)d zj67{6$M|(ynRpiSvKihjs^T}Kjz6d|llt6Cjzut;Vii^ltOBX6BmRa=0swiDC6T2F zWyniB3HB&eUh+E(=W+Z|;S}k%B&FKGOsV2j!z`v+3VbT^dhMqGzdpAwFd(rLEqKYZ zQFg+qU#NWas%m;nM$WY?USgaIOv#4|JaY$%x#@3bJ161P&oV#3ErQbjuS;K0Y09|T z7yDIJoIafGKmG{aJ}mT{royXBAEJBB>Apq^ju43I%P&fYe z#V8z^v*9C`|50+*L#@bpBcKDxy}EJDybf_uFjcoAa&mS2=3sH;go88EgQ{44R^NSz zs-Pw{szS6>lOBay>jpSU1vEufOWvJ<%r%-`Qc>DR{T+$CuS#>|6ojtxaFS=JO3>AV ztJ!rZKv0sG(a3hQMnGlNg={}s6`WRd3i$0(5WU>=dZHKBr`|%18J;<(Pj``oC3XF* zl3B@z5EyKM{y2JfFi?;kFQ~2Bp81Z-L?_ozREMW7^#|$J zm}K5Udh7ghP)&lh*eaMi79;;1h@iu(nN=T9z503SJJ!G*8k>iYHjcdLjqLNrf1CA5 zwtC6--6`}{4VfRmhP=1dq*Z1+GBLi|GP7_MD>}jGgFJ_~YH5W;XH=Vx5Bh6Rzy>NA zEW)X{N{`eh2Mk5#Y$#MDHGxz=$f1#)UkckJ4&DWs@bZF8UXWw<0TTvmL{b#%T*p#HNd>o zel_Zt3j-gf8LrT+PrYn(t0SElK%!5S8biVw28ne;< z;>fI&9>o)`C;$l8RG<$|Lo719YF(Ujfn~PaXwCW1#<{6Foc7WmXJwMw z5#MzbPGyLk376+jjlWqKtJcL82 zp9#Ny03zO8y^*=Yj6Y)x0HimMHqJMkST%q!vv<;y2^kb*8T38#L->z{r|`@PYj~@JKVbdVr;O zaCIPs$JW)e;Fo4_^-codwhmADgN|t1sBG%97<+oS-{L^I9_K8^_8i)2yu<+hV*HZF zgP{V_U$mRl&Uy^(n*Kt3Qwh8L5sZ^RtFi|)eKFoK?uTFsbdE8^=9&KfZZb{oi=Gos zf1l^y@EwCqaV6=P_kbiABNtmRi{ zOXzk^*YQ$PHi9I;0ZIhJzd8T8^I!hK^ItGf{MRssCr7C*HmZYKwLSi35e9^cy(IOH zVbpTQC#{kv9Dh>{-aP8v{t0v-I2I6lSgn^EOfu05!l@*aF>+Dt;r&eJ$cbiXH~sKl z0Nibr2>9eeAX&6BjF zm$(KxK9~gl6p3+BlPULrYhC>Dg4kOVz2pK|z^xWF<(^px@<#BPH8FZs?4yN~qKk1H z&Yr`OVzG}FOpG3_uyWja&RL-9{<#IQnG+)~&P%=+J#xC{m8+_s<$WYf@x1B#8{Kj?Jn-d6{)iq-1dTr1QZQx!{@IUqWc%^arU#1bW~I zq}72VFmhUqk^I{f_%Mqm=1`7Ad_@FOmTzRMufBDx37geW8-{nnLxy)kVEwn<+g@OU z&{yC@Bl3U}|K;7IZAr31BtDAjYcR=D9f&==n^_WdZ(3)ZBdjc@kijG=kY;a&CC{ak z?BAa~5jo3CoPob*Pg1W>g3;L%@EYmeT*`nPd4KxHg^SH&T3eA=(;mHKVvMIU1^i(mP?v zmVv)XO|ezcgG)edU|Y*9nz#}l^yy#DEh9z@8LSX(iSsDcvQ5gj^a~b}uRT;dl z|H{J5v5>TFZ8qJMhm9<)neVDN=>B6kwKKy|%=bL>UpSHez2tA%D?-66$}Gd1nb%7W zKoef#AwW=c=6*bNQPA_Zs6l>>uNz%Zk-qN1D= zT!S(7ajLjtCPZ&Qi<}(ae^z7+OF?ehGJ39_vb5VvndLVKns{3uoHQCSj{|1WI z>|Q>K;_Q8U$&cf2Y>QgthAt&7n^aD~yy>PEup1fasZ0Gmn;>j#vh5{~#!7Ew6+N`f z7FR?r2&a<_dN8T9GMMBklLZ(yE#l-&oFnn!cwc28a@6IB?v>S7WZrmQeH82TMY9Tw zlbzbG>XJQsvUbzxmBimg?Q|u=Ur`Z^l!luJ)AuKLfO&QNjRUD4uuB#hIj?#9x#`>b z2`9GKr26@Jye9o6ijZ2^SD%W<5Npg$a||_lB4!!~<2&&hxOu5j#lo~=Rg+eJ5oTn# zo>az!-5UoYQ)8P#Y-A(&6jiZS@jO)G8Sm>WjC>fIlMx_74rrf+L*{eCm>(Cd#x_y1 zK=d{VJQCmY)LQMExJq<%EBFb9?n9-D#k1kmC#UgE%@Jon78pBrY~|!WZ1^~|G=Q^R zdel{7!KSObdLpeY!K-fwHsc~OZfFUN?Za76y{#SC$ufx-k_CHkjaW}7sBjNiS5KgB zNoQBj(#|EpNP8>Xdb_(ids`=5-PLkKY2aMkY6e2y{zVFPci!0E;L^@ub9=P&+SZl{ zt)0zXEpQ85)Vh3WC*Oi&Z;V2KNNaCt;DWB;#TV5FadFw0K)ANLCNQ^lQDAJ<8JAym z&dHNzTsdRXq_H@#YEod~@}-gH_F!92*RtS(`3n~XBV9p|mIi8;_BLJJ(b}uf(}PR8 z@Cw@Y;8<|SJyp2f$rw|~WHw3S5>WH>#y582-YjgaEDlRy-B|w!e?P`v6|{mXlpN1xuvT)%F|SXOM6u` zJ6o3raiv>yNjr5z^UvwKI*T<}1lb;%oETWRbXl|m_w7M&#cE3BRJy4mF$NK=Z*7Zofq8GRsSTIw=~93^PaS15 zJ@nwGN1?Ix*t_(`Rw|&Q<@DgPraluT15xkIyvol2oht7t-6@qbncu(Oqo)VoU%)y? zEr(`QT6D6iXi~);*8!sHKo-P*6m+Uu9T$ZVB3<2pI#CeBNPPklbNlr&v!ObE&BJt&k*uUC2N-{GfAjKu^x zFn2d<4WWdqs>}*;SraxfvM%mY`ZapX>kk6sh%H^`s!YM^8Qz2k{myIZLyle+9EVtq zhf@nmQgeg_w4Uw*lP(6x5J92doZpK6nLm^bcq6(i8JY{U}DcN+qsC7cL z7kV{2BvHs&%zA?@$P}oikquDvQ5_+j=xL7Zqy$~d(pFHQD($&}5p6=H-`d-5IDz=R zpIR6Q94QKN&n+wm&H-4OX8lm>g)8O#n|#hLE5EIytweX(z4OmXFR*C zB#b2lfiQlJ_|cTGVF&#kg|o{>-(FN(7VIycT{iBvVY#yp=aw}VO~>ZsY1L(w)n(&m zmjyuzFJO1>$Z_zl!o+hVn|Xw@iebl#YRZC5I^gQE67Fga!ddlC@a(`Za0&N5Uj)a; z)DG!hY>>VJ@Y{5Q+0TWn|6I13vh@W;Hx0`xT+PU$;t^%{7F z!_jc^+=>&FnMdETf}(HbKWnm<=|`OhnQkx~3$t{7L0PDwRns~m=e*5tl_$>x7^5Bn(a zFARvX@ovfp1<`e}Se6Hr{f{$=K zR0)2ngX{Ax4^e4lJIxe&>cci6WkDC*F|~p>I{0~l#~ggV;OiZHk>J}L{4&A!I(Vbt z!CaClq)q)DrtWoAukxouJrBvAuVvhN1n)M5P8|9SF8SEd-=toK1^5wZ8~xRGNMLud zjRpd@D(f(HAC&E~R#^@S>~iG)wBQ_Vv(4Rt?|0<ETZRRG=Fk@^xrYV5=inuRKj7eH zf~z{!aywGthXjI7xI7(;`ss6Uo$n6`-0R?^E>d#?e9M`W!KXZD&A!d@!OsWIvn)*c zQtdr_HTclC`QU8t@`c;ygY#?%hFdB5O7#s8?q_`Hxz{cq|F8St_X+=yw|yA2j?Ei zeDXZ*gFoYg@A1Lk@WDqQ-{cGTC?EV(A3Ow{`S8A@by11wM_`fQ=I*yug0~1hz>Wco z>HA$T_%6X!{}1k~f#;L+6FxY%1mvUVGR1uOb|3tCADm}dFun_pQR1Tx(dH186XK16 zt9~e)xTri|xF`7FlYH+h#O44-h%o%qfbko?Hh15kUU68pI-)vvinThnS{-0LC3~K=eSkHO zyw+ZnpDK0qb(Nx>qTVMf4wLn}#?{{{g;yzFRnyg}+3N2U#clFbg(%m_D)=gmsB^QY zX!&%A%5}1qLAxr-Df(UUoT^->D*7opGAi_`N~$R;l&Ly?Q+ zP#Z=f`01|4KLX2ImqCxBS$zyq8%AK;4nAy1`KC`jRH$irDpFej-_uPkfi@0ZYIs>I zPW^7+KnO=XFlN%#sU1kjp0IJm-7v8ZHLvjt4 z$L3{fG)H^w?ZP2Sk%s2>R*XF}&V3D$>pQ!a=NMnyje!aYvpo{&Zpg~f&<=?(x+a{u zTU%Q+pKNq2Sl$H5WQpL#YIMm&&q&*{w5?6Eq0%}q z<|jGqPU9CYGBjS(bQ;@hFdUTBs}$yk)g(L(NIc=9fih*sKm*( zjFGO-ilkmcGm71-xwEQ{797=GV1|Wnwdnb6i0MRSeq-U>(`)cQTR8U{8~kk_{_F?Q zFx*-A8G3VWJMptE{KG!P>MZ;b!5Qv(7XB;2$!D~MKWow3dU(ac&$sB0 zDuo4x{Oj>E@|c+d;`1zg77Hy5ahuO=7H;$TnuT8gKZgIYEX**JpItnIpCUN<+wwP9 zILC4f{bwwEfrWqD!fiQEV`TxuaF4~$@HsVCJbs4HF@n4DUt;05ej*khelr+8H(B(y{?}P} zy+!{wi_eEFyg)kXt~|2^r~K>!n{exW=)Y*u*I4x5v+$sW|Hg;UZLBn5D9=LtOt|KI zn>fb;4gQWrZ|9$xtTbULe+WNA-zzxzTx{WYSoC8o{3{l{o$ilV_(v@IB38aIF8@-& zDbI=c8F@Zv(c9^GwuN70(O+WmImyDWx9Dv-zhdE+SoFWNa9eNxu<*qeeE}N@7|LIP zpOJrr;Eb;=|3r&^tVKWDqPOK#jRfe($ByrDY&>8X?#cL>aK{QxdYezm!tL_@c?-YP z;`0NG|0x!})uOlg|JuSYw&?$0@fl~~FIn`qeu`z>fbw5v(T^0I@f~mBqb+)ywY z+a#l(sTRF0f5@Ug&7wcgqPO{XS-9Olx!&S)y2U4E(c64xvhjnVj1Bl1IadfyJv3VQ z?H1l-;a{}yt1bL%7T#>(-?i`-3;(-?FShVv8ONYJHa=5urppA2ezrw#$M;u)yYYS9 z!k1Wl#<7uuA^(Z^8U0Kaobt3=_-w(+-{y0b#b=U5-)8YyYT>t8_%#;(9SgtK!na$v zO@A&MOBl*&(=V}byMNv%IOVUy&&2n$7QNli|Aj?w=byKH@N?Mc!nph|w{V+JT5#&W z5~i#L3twQ-KV#u`J}j02Kk~8lcBBt}wcwPe%HrQ)(cAJoWYJHy=pVE2 zDHi@C3!iG?&-?H{=0hNYapj*QIORM8KclzvEPA_K{I`YM^~nz`K4)5dp0nuf_`YS~ z%PjhHPk;r6a(3cpzN?@(oi1$jA0tl7`$6s11<72xS5Z+&%w=n$?qLJM1g4v^uzEm^Bj#XF7-S2 z{?HhDGv2K>#9Fu+@4nliH{;y{4sOPmpK@?BzFffoE&lgOJ}~p4MjkV6dz(Yw7*yU- z$@bo`EYfr}o{=8?Y&UP}xWPzkA1+;2>o+G}-P?=%)~(CiF{)`>|APk+QhciB5Q&C) zgyiLxF$U4k@}XAsO~WJ)Ir!cg8ZdXX^RtZM$Y=1syw~edCtSmxJZ!_h0(lnMAl~1r zf7XTM$vVz9#(%LBps|`~2%hr!-*%$r_Dg5J)WqNTpD+F^HF@^$=f>$*)(f^V{>+nQ z-Mrg$Pl$gTEC{yrr_2}8m2#oB8>mh1Y!8O z<)$6+9jx47mg`6MuPc8(*-5Q2xA)@5CQ6;;GdyP~Rf!Ij8){xI$SH`iD(NdL7_!}CZ) zdZ)mGig}lFfW}CZrN)um`j9j%%lYt`z{w|wCyn95qLPoE!}b`OZ|cBYA7@6?EC%g9 z^IITqZo;bCW!+iwPUWABI*n6ql^3%%i-+l3@VlCZIOA;aAl_+M71-6mG==8ypxEDk zTlgP6c30`2sp;3|Nzpg4IVf%TiIA_(;~EDVraujJ%W&K}hvN>!tzr#ZAaK3j z&ZwNC+YtTtU$r^Y|BW`MZ%j^rka`WF92^=5CH6(mmCb13l&UNLU0eLm#Sv`bQarY* z4E5S$Yq?8*Avd4>0~_Djz{R$FmuVgO5O#1W1*aZO@t{&}u%0Yiytpq`?=F;mlf*Yt zZQ1iYH?lwQSa#o|*$ZY9>V1|3Aj{*_ zup2!b_2)peTRg_?J@sWx=IuYs`4bC-k93jtr3|PWFiw&fEHYs;(SAJ9_m$F&m zul(yyc)~eO*lLNpI&qj2FZT@ba?fz&EN?sx6!FH_S2TL#7gcn7Un>~ed_s8#Q>f|V#M8~$pb3EBNM~@iHcpI2&bOMv4`b&!>O6YtoihgZXDMc zRJ%@@ z0NwG(0bdNKBiQq9_M#$7-%*opEZ6&CagcD<1$%FK{ir@0p(eGyO*hq~ z-q-^6fsKsiFaHd%v^MoOZ{B_t*UTgk=jwy%hgjaU%Obd}H9}X%-!6(=t(`M7l%E(V z1L|y1#b0^CE^=%xk4z7zYTGljQT7m2<|p>PXcd{veg&aiR6oRCQRWXhJ9`V6ov;hT z1Cf!cP-;E0poXk-Cy=XfUZYh$nVXT|jjFsz7Iw0($wEW-Ko3I#EY>;KD*tL<@8;d< zKtM&3HS7U3rJ!T#C6dtX7S_fV9A968GMLzpnBbt0dto7gl?9l?o(7suED%1AC(C+y!+4iVicqi3&m7%))00D!qx}0H-re7FXecC7dlh^(<)3As?DGDumyO zFSKFUh0hkuNx!$MUShi843`DBX2VdtXr}>No{L0d*y?BhC%GUw+`oyfV;CoxZH*J4 z!Rt;DFC72#ew_Xn9{Nmn9xG3MflzdQefpkV;KUO(=7iIC?8bZgfxY;P!%J~C4&9VM>6`VzoH!T) zRpltHQ`BsuP_vE6wMX$6D&uceMh?{{OUbzdD01<~%hd*X$XAzoO7};84AFu-LjY$I zL@J8iV!AtovyYIKk9S&;8DJJv%#e>zr51B9eR(|!b%`8efKw-PN8v^XRI3|K9kFM_ zZbk*Za`OHYd3fX^8@Pj7!`=7b^ehO5a{-2&l5kB{upEC!zSLiGA}V3DZ0vj;gM!M9Res!J`CiKyv&$XZ9l3FlJ2tW1 zRSidz`UjII>h6HTC=W`+hb%g00_}2o-O}L>eS` zGzZyl!H*Ih(iA#BCFwbIW!W6n-17)g!~O{#D#UY(sPV8*_UB zvC(qXA=PEm;=_3{Y%u@c%kW6bYQBjM7oL>M++%eyv6`~R!t+(oYTuw4H@u& zJo(1J*oz^3BMD$se#Y}O{0h|9I8pswuHXKhvA0s=b;z?weMt|2)ZAKbBrE4OOT7+L zV{tv4K|HNnp#>KbZ1!!U^W0LE}DWzw`k$CJr7%MX3`saEPpuM z1jp~V%yav7$QOI8Y}P~6q(if0Yf#D=LZc3^u{4J?qb%73RF<4ZknX~74kyWAg+e4J z=xsU7c^c^D&G97ZSlY}jP>PENnY9{_aWo-qWRnX9hol&`id1&ZU{Wr-mx|#u;H#vk zrIiQev{=5on}CZ@diz#$dsla!y-aq1&DU!mYCl=dfd~3%2fd$)< z=m>-AC%~n+20xl04C(nzV{lonrRX^>WN`MgX-H4M250||hWtN(pTW&~3evNWV{p#F z(~zD^7Y!c5I}PcN#n0e#3Br(`eNclhBnU(L1OC(^1)9+yGuj>kW8}mM-O7Bz!A*SGkFn_u{%arndBLfJ3j7THkqi*V4R?az zq-USd&_8YAr&##w7H-pXUo{Q+jK|OLX|QnSErWmB!kOm{ZqBtJAAVyR{P!091PlL% zh1=_LJu-mdV-kLb&!rY_hkK2MS6cLUTR7)=4WDlaPIa(OF!%DzTR6+Iq2FWS z_WI9R(*L5ft>?QeoI^u~&vz}{rvH`Tl+(_Kf3nVTK^NyRIE{;6E;#w0jh~Uf&4>O@AN+e3 zpK~leKeTY0{{agRS@hqM28Qy?w(uVc?#ln1ML)-)ze4(zn&!@}{Z485`4F~+o~#LYK4-ArGdxM@R)8yezfjF5Pc ze_)84Zy(x&`~yS1@n_6bc`H{UhxI^LM%oAJmY1t|C*titcwcxB>Ak@$Dxzgzr|^YL%s`FP2v|MC+wMV}B-|4a%KzR~|xz$i;4ezqwe zscom)Al{AK=DEbeY|6WU+l0iwSubzgjQqyF954CezeeJ3#`_t6 zvNZlp{0{@>>K;&FZ;*d;=OJp_!Sd&mowRG!0-Hc!KnfQ7MhwdhpVdje@E1sBpKu&q z{Y^S!vaI`kk88H3PSu3L_r6ZJ+X^%Ud0E;=u*P_wb6m=6o<0k(*{+Uf&Y+ z5Ct@Ujx*jVcHd5((&Rr|4=iyQl%{wvyd<$oc4D;6B#M$twNsp_J zy>sQf)Sq}G?r1MjjKaZ{S86?GIDNm;1{SeR9XpP)Ciy*u)qm8SwTP{4E$;fj#okrh zYrGB13TnX)cb$#KWfH@2xpwNuyv0WAE&dknqg_Q-tG8|JPe9lSkt+PXJo32sE!Tc$!|z>?3YRi>R1|1GHyu<-m@ph$`c!wOO{iC-XK2EPtSDNVcXz{lSBDZAbL2cTu z$v*;eyj|`kjz_`5+c{YIipQxT@6N$c$*W#sDsU4z#Gzbk7F7(-aM^5jeIL>Yk@%_i zz^L%PCki7YVR?67O~Rkvm92EAR?&%aDc3s` z1$i@rRjfMNuc6Js+ZA526j=`>^%aFG1J|W~>Lnfl-C)fq71^Sy-(|juP}XYlwPc~v zbzjYF^86G46>6bMbEu~xuzWSIkv)MP?-Ebbis{A&ePbVi=erIx5s`=FYrA z+U&h)pu9@wr7@D1qNf8xW}VF(#W-II51OsfomNif9ynt|^0r{SvXXVn$_aIl*0BS1lQv;dx@TRgtVbznhsBW=H>tuwEdUjC-F4VcA zq6intgIP5KKcwyKz#(4ZRfrdgy*tB8UIovwnOD~LHy2Pz@%QV?5#ZK+7LbyE6XRDh%aXX1N|5=Es#Q z`vCB!@9}{S6Fe9+dj(JqX6=**zCJ&EU0yhO7Op5nMmr1fDL}=1Z9(QXAS(ZxQdnIO zQWu z0BmL`HpjSZ3dm+P3-d!N4YAq7B`G9H3rLg$=+0EEX3Pqrlvc;y9)aR90!_d`<{T}~ zv|QjZ1P*bi2N9=Ji$j_~^a54W9gT=)?!f|1P?EP$@`6$z6kL$WKd4B#lAfmS_CRlUQ*&$J>W-$)YXi7e2d5G8CW)T+_n9Z3tq1MxtcOZCpGNapc7${5 z{&1GQ+yRhV_jg{|+M=Qv`4|4p;dea4>A;VM^9%pVFiGD3H>UfgqeIF2%?PJ_>)SY9 zX0L}+ao21>uX@H}%RP#+qXapOWBy#1=6)mSv1J*A&XKFLut?8()HW5$GHl40F`@B- zbB@9`oJ%4f8BWPMagK)g*es%7rm4p;wSLcbQr&#eSJ@!mXA3>&a9opbkL_F#QKzoC z5B~WKEQ9d+W7>mixM|_$f3`aGXXHaV?^9n&27hlJMkq3Xu2j@DceDqaP zR9yZq`ruWPWnKCvAN+N}89awZO}vhh3{IT&g2CrmILnN|ueERv(HT5t;T$V8_{RmO zoc8*J^%lK7?|H8e{R0*~^Qqy##fSc97Ck@74gIfu=>KTZb3Vw>zvM%IrBpqx{@428 z$CiL8j7xu&5B}di_%>vg|_gwpsLH9Naq3Z$4&+j7OWnJC+rOBgv7S zXFOSOx8-}+3D<-#)r7J7&d0o0|7;(~)18ko{&hQ&4K6z#Xygcq|H>SRdYj2g1Lj|i zG1h^`@KPS+kG`GEM)bQ&YvxnzJV{D(abHY(%l>hRW3A78kg3me+T zzY)*G%vQD?+<(Sx*){n7#GdXc94mcIZ>yU?PvP`U?FTN#uDCfWDZ*)tgTf2;k6wP| zfnCbqYmdFZnH9f2H*wSFK96DJ+?2xFvXayBI+b=9u3@qE51}u96?VZqhD}3*|L1pE zQM7!0K#fa7MT=$f^}(4}*{3r`=>nD@ep0NAlX`N_Hy=I+IQc9PYNb28f5eAAz$4qa zs1*IhIb1?&>|73tj$Z!GprRbIIyvi2t^C#QYQeI|VKl+ItrS1gb~cGSak~!`6r4rb zF6+AQo@+ZzJl}uY`5$U5B_50qQ`fJ}yjAGT!%bViHgmryr&2spw+zRv^ZeS(ADIB1 zCwbV0<&iwCYDqc2SO2EXG;$i=#{a1Xkf#aXJeiNpyG{Cc+hV=Dv|NKg%+5Z z)`~)!?7;EvhCk_y>F;Y^uc~r7Zm*?z?`_^rW>PUB^$cOX=BR+0%u9b~*R5!o&`zb# zZO2CFowTLr;dkM<`gGm2aKWP&^cSOzI=X5f4kG~+uJ>vN>r-k011C3A{}U!!ewi6UIH~Yfx;%9LY^VtZ@2)9V+lGYXKkFflbxH z_(w|$qi2QFA6?9y^*DJ$jREgwB;YUdL0r6EWroMlm~IWJ@+}vU*Xgq+p2l`<*Oyt z=cc6RjvBJ>-a7XK>i53$G`b3TF0scnWQ=K4pPp8ozGPJLNiTUKvQc$@^0igbtFg;oNJL>>AB@|Fm*GP=gA~409cn^&|a4g^@aPx1$C)#Uuezgg>~uf z?r{IP2kNGW`g*2F9KtIH*CUp7>ArRzrBb50Ltf$ZiZvt=1ES z$WSXPa4^l3S!(_j=N@>;lfV;Qu5tGKYi`~sesl4NlQ!m#L}65Or9>l)DX%R8{ggWJrLcF)9x=1*=nYM|;Ub0M-?S+NEr$$(OpKxxvBE z0i{0WmfFghm`7tz2NK9WzbjRmEwA1hDuLc9$v8?74>yL46x1;5P^00@=OLBu+cIn~ zaXakHOY}e{VH_3&O$3<=^h8XhMil9m>1LcZ43F=woK@<5f|Fo~M0IL-W)WPa+)32p z`%6^JR^LgkdLAm|ZT^Q*x0gIZ1q3r09SE}V{H_8^j1trQbbBY?XeOYj8CD9g6wn>eMAzH82t30Vws7v*4_9h_2;SN~+Q~SX_vt zY;VWhS8hTr`6jfWbrOH#5Uc}G1#?d^mq2(M@Rfn->j#d!aNl4s`q$W>N+O3FhkZ2{ z7N9=g5q%lcdCB|1#Ym5Q(1%C_GT%ctvQ6m=x?g9>_-FOosgi`0`Zq7AbRI|s~aIuxL*z1 zhrA6hf%5C&f*q_yVx-H;jVes(XHFiu6Q4qNM<;JOKrWn_FY%He0Bz;~RDkq>T*JK8 z!+hjo`l%l%Yh!56unTLk@ z_$b(jj}j!nul5yR2>ss$BFHe&OZ4L{69og4{uE7>S1dKk8(J8|s+49Pv!fIJ425QU zmYGfwoEkpyU8w(HLCUg%6zeyvj(8K3g_-BU+msJ!Dh}1P-Q8fM6Yduv^hq?7u?4%I z`-g687h1JL=5Bamlfjb1^)XCdc60Gm4Hru*E5S@J2ocVqIPj<7B z`7pV=Q6H%#1}9FkYuP`C=w{xbqH_7+=SV;u;)_}t$eb@B!)1O2t4SY2|KaF2Gq*Bg z;(tQ)?hF@oX!c(wXULKHy^4ECCrr7jgwF&YUMyo$9C{?Sr9Gsv@|NA5W@% zEO^!1P#SxqCo&RCV&0g5^(&9;8trX3uORluaxc+~G)iq<$puFMCU~`5;ZzuVqYtaS z;1qkK*Gqg&y)5(++&gy=aS?cXiR1D)6{{dPI&hG$VJe7U!AS)%%LH+2K0b%2AlB#O zGh7Anu{=%}mBijeEI1Drdo$uCxS>Dx<{~d~0)u#D<#rY2HxcDWzQ$K9=1@s;NqPLd z#*)*7km~ZxiYG1mB=MJpWFOV z>e814>r$75>WY|K$`9DpLeSp_{4Ys)m(TB ziZ;#7Xw9+E<(=!xRAn2VcA}T~GzjnwQjWq7c7e>(2$1z=E{I&4cXP0=sIOfrYJ`Fi zqCty$|B=(e@i*UDJ_;IQf`srzFwUfg)zc|vwZhn|5Klpb-cN`pMr^)CHsHo|4;+(bI;0=B5J{n7X=FX$_tJgHN0dksv3^jnzcwlFRmk?VRmig3yfNK6D}){7cNlqE~Mw)C>j<^ znlOHA)f-k{bJ0O=4OPCg)6OqzENaWYgv$SbFxH~~7we?B#=%}EW%gt+y8d%OEVKuk zA~g##6lZ#Iy^?DDgJ$9?e61Lxcp*PGIqJo*sc^M$(|xS9(Sdb4iqPd@ao2z|HEn>>9e z?Bo*@T;*%f@*^T&xD$Qw**^GuADlZ6^6_u+!LRkfSNPz8wg}FG;T6q2IJX58fUq}o z^B^NwBbW)~wBXX-o~DWF=JEfJy?23+syf%kCm~=2%tXaDZLy9v*4Qc}h>|F3hD>A+ z43HL3>ZJj5F_Dm@$qZms49*1D9iz0`YHz2U)64PH+S;4o1qh%7TeXNwekq5~D@x^l@$;lT*s&#grVY zgxDm8KhLsaW__?t?9u4J+Id8fT7cBM$J7HQqIk-74Zc0r>ym1PvB5HSB*Kp*l?6y^ zEiwyB*w?WR#~#5$iPJE`)>3+z(+b$EgK|$C4wyb{qg=G34In~k@8I6KC2|D%VLRuL zpMH)X9eb1P6{6J_cP~LW=0|(q6!SM7aoaA$%YrJLZG+)+(86u{k05{0eF8t$C5B$M ze{0;{?=;_{XPGkeAEe-L@in_m1`leS@*i*E7i*k+xVO>JKW6b^du8zd z)CHCNS%(?ioV&%>+#71}r!+k;wjPexRWJE)THVlpT;pCoU$^M({df;p^Z|>{G)_ps zk-xnkuUg|?{%2EJa7J&X>e08@gNHQ!ZH<#p06!!D9uNIuoqo5mV+%)mTMzvf9>6=p z=k*-8Img)>?qc2adGR}Q;H#Oaa9;ZVv~XL_Cv)H(x*_w%Ylw-Y`JafZiPwjj7;vON z2|t5hXyG>ft{nJB*g=3JpO4{Z_zHmw8M0G5A#)mnCTnzgFYp zJ$zPcyx4>HYJ7qRcQr2S85aLOjZgH@7mQaC;y8!S$oY4j&&~MP;MJPG%tQZ8&HpqH z{_h$$<2l3UyBg<5bauG^rE#;@$Q4b%}FI?%t@6hxC#V(ys^kaH2s^M?ayU{~$^w{IUjeOqvyhqFN{`Y=*?OgHm z2!;JOnzix;5Kl%ycgu9FeZFdacaH8)nis|9MqjyRR)Al%em0jfJ<;*B9xrh$!*FzR zzw37tS9`)We2u!z^J$u=4#vQ~_v*g_KFHJi9fk3)=C{&pg_ci7j#_=sd}X_zY56(t zVLR%|cGY;urau{s;@zND81=_A^6GC6Fa}YMpY6&yNP+u=x}^Ubam@8XyfOD_BHUc8 z{o5Gty|ha;=8gYi?ccPshL4foJU8PeTl@!4Run5WA>+@kwDDh}ajMyy_I$PYon}K2Lz2N8jYLrktT{?JW~-*6 z(wuku-uJXFvNBz@NTt5xP@6B$B{Il=SkQyLmzt6f^~d*qH5at0rTR0 zpLPE~>pPSGF!9h=Z{En&r)bd??PBeZX~EnqH43h#O<>he+*>cd2rQe+lnC`USD)g& z`Zs+FsnVRx81nbtCYv}=jB1hP|L3+Mmv&u#ChGHlG*0^Ov=hlXhUxBYRaII@f{gg* z%_Aq`EirE$Q$500=E3X#6ue@-{b&8Njv`M}7I7=CT3_F-j$zyGm5E-j)c(B}FKwX=+*+{`PPIzh8JEUuH!I_u2$RmT6<9;{KNT(jEt z!2vyuO_#^6_#afxDeV82^?yxSH*>H5Uzc^$4>uXqTh~lJ%h-2)Z)5DKmF4f-9_%i? zu1guJMUZNYd5-c8%#@L*GcZ$XYWRCX%<0pV(Bxyyo;$>?Gd+CK$-GrVYnm6+@Qr6MGmI`Pf^^>^p~nJe+{uaB~6z zOvmPT+Hk~IYKifh`pBS0s9bs6?ezX$<9%i;JyoNA*>eFX#(KmXn1q0gF$?l0mm zJ|BN6*mH37^3V5uYIo1UBbRqkhlB91PJ-vL#rGD&_s-C$LOo@(MeonKj)FN=`}~RT ztMKsOmnxua>iZVa2lVg^aO&l8T(wxK-(e53{@yBn!0*55VFuZ-8{e~u9ofjSh0GLg z&BWACg%bK5sL}aaPu$c5z|WW3YTon1&GkT>q$F$KtUNc#$nPvDKFVnjJ>aNurZ_&Y zHLvo=j(o*$`7%jT#E7Le2-(?p)A@HM!cBbu|E3=mgRl=k@K^IdLUpGOVE}HvYXQbg zo_a~J>ciwiz8PP-ZhUd-Z$f}<`IzIrE~isVc43Ne>-Hw$+>Q{He!&+x#+TY+_`2J0 zAhtf$`gs<@674^t3?P3CUWe{c_Ds2bzSluoZ4w?OcxB|(1!X|WP7gxZ8pprk;?xcV zY5Hsrkqtn-Ev*jTeVO?+vk$s9ZA&tgK0|sI&XAszeIN7%;~4HW_|dIXmw))5 zIqqLSC(26oaF=^dwD53ZAlddolQ7%4$7h~z<-_t-<|_!GspN!vyS_8-ff9uTW>>4tbJ)WhAY@hEH)_hUSd3Y zEL4`OX<_;jPu6jw8BETJ{0Gz1>3zHnuyVArzPlsZ5&JytSaN%=+9Ryarc~!j9=2gu zk)Y}lt4LYxUW#x{jd<6kDlWvCE~+jv=4PouRWI(tEU0jtFE|cAgMU-wtTwpE-Qbt7 zk%1#_@5ga5OuJ+7KOhV`Gv{mYO$tuy z)!^UZ4O~F}E7=KE>v)!W@W1K^sd_I%FQ2o4mh)e9hW|v(r(D5lyjdh(v4Xp*L-%rFU`G8_XTf;(l5QVpV$7q`ltCT zy7lUk{%_7&D9V=x_De8~=>wdQ3PEDXC(%=d3Rg465n-s z?n_&lfZ~^X-9F^sSd-tpZ5NM?3A+WQ5+mBf+p!awp`t&mg%?QXS)IOl`Fgqx7Ra`c zYem2CyTlL+6Y{X_B`%!rJ_(bCl}_?ogAieaHZbL%*n@M`dY@Uf5{4l6;XQ;~b%ay3 z!|~6f!$=R1e}eBW#k+p>ZkJrnbCS!I;>Zb8L~CRL{)oCBMaRH|@Q-fOZoxfBy8)8rXN^@pXz9j&YH-1_uW#m59v` z+7v8|u1+n+NYfeU=Xi7IHkB^xouvN_f5+Ol5tjex)peL2aQfszlp9@uE+(41iJt^G zt`kV!#04kUDf4fYW=ew^WgOBgw3-`r{`xj9QCYO7^Ewn!?Wrqf*eibW<4Dp*0cR!8* zvrcyUcaVs8nD%p@*R0ZKI&E`b!g`0!gPHQ+B$d=CHwBX7{@&9W;nfc?a+b+QW9L)P zD-Z2d^WE<;z@b}>|Gqnz)=uBeRCL6B6-QbPUV%|9kI7n#H%PF!qWCFOGvdDKKe}cm z(Ar}E(eZWkn_L)h+?#L1ZE|6md-Dd|_%|**t=YZ#JAB=DGm~ua7{#=A7P8xWlrr^~ z^g79V^>IIZ2(6Ca!udg25BIWV`QQ>M3n zg>~P-{@xa>MPf6rKhaBwCW26>eF#>?oYe!ngzD1LVw~GmqU69Ka3#Lz zHFJ9Z5G@G16H9yU6Kh1tJ9ZmHy&52)E$&wi@ zsoMAiMXc!A`T~eIPNc<)h|=Cq2yXt5256R1y&A7lrldv0roiV-bm69i@&>rXqH0mF(G$GL9`&0 z{OtJT1;ruv;=*%#K)Yf(jDET^#yfpi!eHw1fV-``_VxmQ?@#a!+HCUQJ!b#5{B^ay z=*8|X|HjCeL(Ohv^r4}Mv`?GJVqnI2UdREw6qBy|oMe&X&MJoa{^T`92T-veb-?NS ze2L?xwE2GL)JOBSi2?ubhLfvrQ_WCxVK{lu2HaQdAKvYbiXRxh7mbW>6MjB_XuFgA zhQtuLc%o`qrlF3ZK17$k9u%w;^|D$bCxE(j7JQJ-JDz zH|yitiea^G{)F13zWQYc!+Wfo59BjE z#JPfrhY?dTYpY9WML+633D%JzA9I~kl@LK;Zw^o4WbZny+KCl=!pY4vkBwFDMZ>$1 zEu!PtNQ^tNc## zr~SAw64fU5!|$TlQStkjQ(?^VZp1w3PA?Vne3E~JUG|0sY}}W0-9vdz2}*qnbtRT@ zf5`5fzjq3G_H5q3s?nb)l7tGCwlHK>h2F~{twaDdCaZJ^yiHb6(bt$D0ze1r&H+1U z=XUT>`a}n&gmKqg7@E|-(224%Mqk&A7GHPe@`cxj`*K?l0~kY_pc4@>)$vTt#T(W% zOn(t0=DjR(n|pD5;n`ry zy1%4i504G*lwJU6LOATUnmsNw^b1M@$sX=f0Qc#zP>Vi+KXI0%=2H>8b(B)hJp=*# zYmdhZX2XEfcYkR$9`4}+RI~rp{s>S<$18-TY48_brzT3vNr%)z26@V|rF#}2=6$|S z-h4aWL+j(GF(}ApusnHOK80kv+C&d zj53ng4D-DEC={&(lBgrdYCA}X&LH$49dnNgCDMZU-RIyj{z_i&EB+gKl%d2;2O9Kmd;(i~uw_B0o8w6D{Me?D zySEwRj%KK^3wE^Ek0?-^(Z$hnXgs);6L7*IRSwIk>yx*X^3yY?FQ&33>Scd|16gLo zpj%LyIuc}=_7TCB=cnV?dpwGz)K7%i2c;mL{*9s1v(sXw4oKcl;4K6CS?NApb(fWO z;-$?YDCukmszIiDlZQ5zgWaV)AVY4o6|`<6B=c`vKx!nrR*f!WJLCU`Op}+I2!SPr zJQ}k^*Fiz|hXt;w0nFAX>GQq`t!_OXVTqp+`YS?D1__m=IA4c1ioPuV&NzSKQA9ER z4vb(vh#R}jhoN$lYq-}Ngpy8yP6`gSTO^58q-Z2i?s6rG`x5JJl`g5=wdj@X zT54%CRf?)kP^MLllC3(qndx&NU)3nRTkw?n39^X}5yFeGxpP7R?547Rpfx-o+JmZ4 zEsL_tvnadVqwMGxoxWS7HiV){k6!s>qHxE3)In|I(RKM@x|VM7yD6KA4eN^0(tylS zIDK^mqI$GyH+>4}kh&NVXNTwZ`NLUdaE^*kh0FKHtUFEUBE-D>=-_%(kl z^hLwz{#mH1yC90vdKvg1x-&jcxmvm;AeyNnSGsM zS1I2~PA}!qr;aW5A{qKnX?2n^82yL_{p-GopqpD>hT};AgX#}$fB6P54>ldgfG?d}wO|0|% ziB%*|-nthLD#Fr)n?4f9%6QAJCw#E$$x>Ozyu3(Q;wAf`PSx&fC(ofk4Ty*iel}hx zIb+i>?hC_WzdqEy2ccyN4h)!v?RXizZ!<4WvY^zxJ>5*qPG0kBi;H}T7Lf-+uz@PO zSIz&ac^EsoI*wMf5OEA0bmV3yL$9`k+}A_ypSZ0wzOoF#p-?#fT2!K8cP%3}xC-SH zxfkcqLmYQU>LzFeMJ1#M!^-pEB2d9P^bUXT4e9qd*Zx{;2V7s1ykF9qN-G)s;Y%p* z=P4ppUZ_IwPF)L-{g9FLt3aRVk6mcR!X(ZC*=&gIo^9wk$5kN1{@NXoG9|A}d1OA; z$$H;J1SKh#+6$S(4Lc*yA?7ZTO~ZW?)+WEe`e9z*)E@=i8#xCMPKE|Br!aG|(|}Al zaJ{K&!hI9hCV$GO_@UwGF(!+l8V00tGu0|VDa~{uyxQJB)a*=1am~X#Y+kI0@!C>g zgbF6_W}wESxu&L4)_;@_opT4k!++xqh`1D0oiJO`Jf&6u6hTydDjT-{rUsrkiYAgg z#j0D_b?+Bq$Ndvaej(1)(S;wC83Ms1Dn=uBD;=U#WWL?UtGEsFFAE0=&R|7 zwKcY%5)EA5+TIw5b_7m2x%(7f1Xc>$0-YUQ(X#_5x5UQ!>wVCRasurgQED+@X_c`?e7a$bvazx2J#)N3 zDG*vFzxng(XV=!&1tZ}LYXeYSb0hRA%S{q_ZR*{IBRHQIzH-xqPqM(>|!Z&WcheKQ1TC^QbQ9sCA0{UfdydGzFsnW;7)M@HsZ+RD`A>M&7M0vM zDw}R+Bg)r<6?Ub2RExADuO7|o61MgkxiY-${p@@5@)u^6Yu32w@cyvobv)w=UVZsU z$Qwo>->oS?=<(4rANkt3^r<-T`@ZrlGhWvxWx0bJ>%ys2C4 zdEs$?w%rbS813Wm%XSaR z!x-O65B;w+zR$z|NsVvt;2hd=*Xk}0{(|76eQV{K`S)jycW0pVUAFH^UcuYqG)3ly z$4X|y`4L+-{Dd5Mc@F&S9C#Qwzjvs{l}_42Tv_jD3zs_}vf-VY4=4HQOk2r`0rKCg zacM8{{;N6od^ZRF;~Y583e6_ZFM!K;E4qqM`P=9FZ4UZB=D_!9J{vS2X?Gz%zBJ4l z?niRq0pOHJma*Vp+G1QQa?sc0z{8qPF~?zW(mvxlHwXQ~9C%|6d_@jCkpsUa2mbXO zIKTAGmR|hwHyeIO4*HEb@JDmtFXX_7fHPgzA0z7YNk0L%@8qEO=a92B2hP>YZ1K7P zIK$od0Tr(FDR6sH4*Dx|;6B|=$EH%=)wg!n^XgmP)YaO2m43<5sU8mTd;}lIM>s*f z)4axLg(H>LPJY)UMsP~SyW$y*_u zA{+&nqR55k6y-@?Rw!l?%oMqwqG*KK6k$B&j2uTc=%IH&{j%=% z&Mpiso7Lx3967Z$HAm&;%KGT?#@6QM^h0~c3Psl0)YXkMD5yTsr+jA>>%_MfO=--U zIIt%N6od5FR^pQbP$NJ?XM0B@zUa8hhw(ON6c{a`Vn~__ymiuLf+x_hq@ks$9%ITT z-1xeh8kQ@s4Q(CW7(+HJZPL7!#oD5+^#V8g}>67 zs&7LayN!Oj+oB!aty;X!cURvQVX9DEvxRdp(coXQaQ0mc{-}jd zws1e%9XeD)@{NI^|ER_pZaIDi|A~c9vG79{eujmAf{fwF$Ck%F-{LI1GyHk*A06qZ z;b-t33%BEYgN0XG^fzmq!TT-zKP>tx3;%;fKh?syoI*!=>~P<)a64St8w^^8%lg>J ze=Hfm@nVO2tA*SAzir_*|L<#@{5iBS{O_^oZT`ltK407XpS0+0{?A(c*;E<+Ll(Ww z|8Ev3qQ}|bA}$;G2HVl{6-76`8;XiL5u!b3!h=(`z_q2zgQ1h8E(j;Z?JGX z+>IKio@*?6a~=ut<1CyfSksZet)DMjcrD%;eSXct?egAl;TKr+DGRsL@oyGxr{mii zr=0A%m~hAGc~Qz~=fe+bob=Te{goEIoex)8_)Lp_gN57lKeKR~{?`_6)2B2}dF=0z z->~RyJ&)GYH;k8K$#b)Xhb?@Y#>v0L!cQ2F2RQPXg`d&e9F3FyLl(ZoqPOMgvv50J z8!X&T$Ga@tPRD+YGhEII8F}_t^me!(I0{5?lz%pUhW<>Alg~#iJY><^d|E8}vn~2H z7G7=P->~>ZEPPrK9^fdC-5%9xobpV>&&YX^ML$9w3qReW@3C-OZ)+|7$6NH@u;}gl zf4fCrZP9PCaBi(La&EWy*m6E>;kKMFS-36devAJJ7XMLfbm6EsoBu?OQ*YJy8F|Vq zJYeCUv-r%h@Sj-tTnpb}@j21LU$p3Ld0w;dc^3WOE!@__v3iijc-eY5LF0@Uy_$GU zw(yfIyvpKZ%hPV*cKQ9H#ph!dpYK`pc7FJYMPF^vKWEX~`uwP#CuO{BeNNUm<7Mk} zo<(oV|5*#S^|{=_>nwTtEdHeyeyc@4$-<}T@iXPAw(tq;Ou$ioyFIGVIO!|!GwE`h zMgM6F|C5E=>07KPR>|jNi~fTeXSlZht1R5^Ctqjr`MAYrjYV(k^FJ-z&W8_KxSd{4 zTDUF$pEXYTPqD)Nt3_{zdnY>waHKE8&*<%E8fScM`afIrr&{!HSoF4j!g@Y}{Hrbc z&uX0f=UezX3twR2w_1G8wD50P^b0L~n}yry@@EUT^Vpzt`{4{@E zk8oa*&fsPqZnpoeGJP62Bx2E3mN~7CNTntBUPi-hdbq}_4O#7fAr&FbB63& zF>h5H0(1SOx+yDCS9aeRjvi)6ACzxcrxDk~V?yHQc)~TfPDb;X(;miq_0O_Mo-Et8 zGycu|ym@EBH`i*s$mV}g%YU3FVkZ8^KifRsm*Z!zke>T}kT+YrV+#(&|QMhN8^oCEFvW35njUL=`&r5Iklc$|IEnvBKvqv$d z(%5i)?>5#QBQ)fxrcn4l9@^xlJ#3eIL%s*Bn#OOR=i*bk3$WkV!4>zt4@GA%kfY8i3SdB^6pd9(JMN-lXMoZ18E%)1_?BD? zON+8kEX23&!iZkM$lb@g^niR51s+5D82@9_>`5&|cJ0XzpE z3(j|tXReOuJQG2l;r$#a^}I0hOgKK67jb8nILR3}5T`#@;kZ+rfeW;DFVNcU(%PM& zv`f1QkO%ptpZdBAN}3Bzu7YZDkNAGlaaRENT=CEV-ly|ZsmTFD>n#1aU4=uBThBUw zrIuhy`~SjTuQF)aRFhKAXZ91#!sf2b9;cb(q`h(^Rj?0;SBGcsES0l&PQzoPes?>s z;iBRj@Yq$p|UXY*J`vp$Q_T?>_p6#EnuBdn}II#`*fyOW9HFJg!=BrSn` zLF4@zm$U@Nj}k~9(2cE$$qzMd`pD@tlT+QXf-385>WFvj(#8JCNjS$nI;lLz!lRHk zWDaasKCPpJ%qi;@-@}fMw}Z0<7;(CgB5Ht@S-mu+0E&n>orNDA`!HkiGh>@?6NDqq zeu2S%PY}+Fzozx*CzyHRsq=hOzS`FHd;VX-Csc_6!a z33~MP?)N83kRa$b`xD$8fKE9+N5c)enEu2&ATjZf;ffxu=wXO^5&DAjilv)5Ftdyd zorXhhEZ}VW^C%fEI54Z>Pdvwvp7GzvoDk}37{=ic_|R&&;u)IAA1Y=%<2&*qRloNq zsJTer^rubK!tN2G=lJxeeX-y4KGQdUIC^&9Y?y%G6X`2`64XBD)L%G#6Q9H$&XO!tbu|6Ny6yPhpV2A?R8);LkSP@25R}vH&7ekMf&8@$ImG0@IF5}?zF#> zR;5mNi-)inL1Ec{G0HTV0z)Io6v-2uhKmCHN*AAK;ajs;hZiy{>nIbzGa=cmG9 z_em+Hf1U3@O&BsmQ!rIU*+(d8{7?{M5~ZJMqMsC^^d9t+Nzfga*ckw$Sr-0PN{C;J z5E#WKPhgcHLhMIMv1-5wyTm6im_EB^CV!spz-HoR9$;n4hc-ILY&2eC^DNXKE|{V23vyD*8*%*l|Ee7@Zf$ zYzoR)VW_GpaNTbYD*`AAQhIeZW;#NW5Yi9vA6K!bVt?u++G)U9s3X&d??#%C0GahX2v8?*-{U zE-H?qQpqP}a$aF5c|jmpwQJP^CwZ3Bur1Oz{y~*<3wAn5dWg;F3+4q+-4(=$+PTef zw})|-%$vW(7p9LndA}YyPUaYr3wElZbn+N_@kgrq-EFZ!i3;=>--aoSiy%tAJFjrZ zdmsFAEJ)}5&WWjI#=c<^;H!`u_^r{JQL{N_U2eYB!7KKs9n!$v&VO@?if`gKCib^4 z_V+4v`B!E8swlW)=fjUY`YYc$u(*wU;2PMNH)Y|6kCN7m2^Lkxj|dl4=l@3dT`=-1 zC7fkTesx9F@gvrZxnXo)!HuJC$`9d7nVQ2syK%oXFj(SczH>T>vb@{3ICc3C zWc{wkQQ!4+k_X%>{sXTYsi(eCIH%$Uev7kaH1rf7lYg=L8Ylh1Rd5_$;=`vjPzUd3 zEn^LN&CJQ`)8GaEX|E1>)mVViyIPkk)*ZE_^hCH zFGoi@?%Ad@<7no&l^UDO7Z(*3FTnf;Y1eC9FPq9-#dkFJ71F+oqk8|9a}|Z)Z_iao z*#P!ojWb>7q#USQj5~BkRX>}{`n;S44PTN2?*`5}1~VX$@&)Yr9Q16& zv+>`M1OF*-^6%7XCS?ZLwjA`ka^TNvJ{$BHN6HJZeHsrG;08|eKCZ*~G2FW}F8LSO z(TJ+dsf@-0oXM*vYP?$GCcjo|oJO1IOrD*q@%0*)e2e$gUpD<*sp-kN1eFKl|>1vHF`)6i))EtqTv=PRw z?X7x#CdnIlSsI%a|9)3$?B;{Y!0_@ep6u5Kr#XT zaSTewu|D&PnUmU15RTc-o~x=tI@6J!OPq$@K5xWt;ZJFL@?m~5^!qJ7cDT>#^5qS8 zP~+ZkKcLGI=~)I0|1&L|dDP$y8u!LGo&$f|;$!Qn#FsUj9GS<$|w2f}fEm zfO|SdPe)Ony>oeWf*!u_z|?o%eFUbSifTO@{-)mP_u!`9;dy{`hThaW)gC;cN%2*V&h^#NF))*Wj9+dCa-L;Jy0KHMeN|vwYajgm137<`&J|s_mEe z#-G9GX-sDy1N)4B+G(+!(VxL);U=5@*RgVgtJDEf|L@g(;kqog_Rf_zxTAA=g~KLTGd(B@_yjm*7wiA+@hj+?{kYAmS-fWmfLF7 z;eO10NaZpdFmr?XRYzd#%5kfVt!d@^*I#|}5Gmeq!fC1eij-Q8*q2@=B=)6wpVk|<&-dUW?= zl4T!5^Q$vsF}7bEZ<(04L$8-xhu6w-yi!2&Tq*~1NKTR)1|c6NPajn8&S}A{)u`(V zubCJ*rzLRB2aIWanF^Ho7s`RzHLRj{Vs;L5t|{@UY$#zb1xyRmAiw1yGZ!--$y7YT z8WW}to%q(p%%uJV=PvQog9{Sl@6k@DPaa^ZX|MuwnND(QDHi-!F2>oVByy5Tj!vB_ zr^KJw008M!4f(O3KrD{KJUQPF-%S28mz*}62v7wv^mU!D;a^B&{c4V~qJOAI&50z5L*RhFcOF>a6yHW% zM1#;P=R(8oqv>o(W8ci!$^R<*0=$X2DokJT0N@i-w?Yyf9<5LwN}KM(1iAZs^rM(1 z$K)EOM8nB?OtXy4e~&oH7&7kuDCT&^z?iN3Ds+dld5>N*=xPgMGL0EdZXpovyYT=o z$-DRAf()Z_i#rM$gh8zlvz#H&4G0^m3b*t^H?#*EHLx9{KY9u_Z1mN=6F+#=iiz<- zSSGKG9~ishXmdP6L&5cOmg)M6epLg6lRY#O;3TW-nA->MW%iG_1H*fje$8`=!9b7R z=U}quY3LoMR->1?WA0%pZeq(4Os;>HIBfKN#c6mezOC4uutjq6<1Ze$d&l}Le0GCA z7~jOxrSk424|mKa^7Gej-vN0m9)eBS%$dVTPbMa6jfL~W+}cD_=Pe^jz@m!&o-IKn zFEW^%#NhOatzXyimf>p&|t12nwuk%f zl;V#1LpKN7$|d)HZI8|kBZipQ#5&K56d}2qhQ$#Re_}hI<10(@{A)JiHd1vG>@G@H zTwSebqS#-C_sfrzclmf1a`!Qw!73O#^xxzlq7nCxR00gs&Z&$K7s7&h{8JD+{%4qb zY=RHytjK@&vA5^1TUhDuy;gW!8=<*Em`6_^1F@Xp#vf=IQQCSS)rb(Wh*pUphy6Fv zMD9>R)jLL7e{VSgW zg-vBE3n3S(%0Vrv^!^!}xOBs|g?$*>kx(1wWXA7*xqtw)jP=)S37}g$j0M%w5?By@4#&i6|1J0?BVcPxF zU&i+yfQfzo^sTIN+^_j{6Yd_4`_uJvAqKb~e zbAtiQ_y^qwQWs(X2=lT~Bvn{_@!tb00^axOqYm`Rdhpg>n2x{f zjA&*mg_ncwF`|TZHkz7NI~=1&I;+oT`b5i^H!D%&OppU1{JrNvcqqXcQRA>YBs&U& zTSP@L3Y*}RAP>+9pq=a4ENz)OW4_{5rdUzPoT@eLgWC?C5Zw0ChiCMS|6u%u^FyaT<~$CQov*Q?D0Yq< zzcW5O96dT%btvSI;7pet*y8*5(XktyO(sGyg(L4V>D zHXAT>4Ew~=n;!hr8_3$IDPelFf8~)*!{adT>yJE*2D=am7=h94a@p$eTXmLJ*jkX^QCZ~RpYppaJJJyMBN2(kg9os!8 z$?X%dyKDL;Osz%#2Yw$ zg@=@t*H%0v=|}mtYWcXgNXfVJ@k8!wMn0Nff_#%9-};dIQ1HG2rUw=w!+qm_;Z_ia zRs7EsjFfxRoaFiJZU0*>y2_uf*kj6BGV&xUqFoik;l6_HE)D}&S%BjLB2O0V-VXI((ObeNz3Oj=A9;9 zF2uw#K7IioSldVEp$xfpIQ1$*!r59#$liyTr2fPwL6JI17^B}j9ZGyusc-7*y$`wP zNh{Fot}37={fVEG`WB&PeWC0VhumLOV94YCh7zG(K(wTMNCauSy_jdqAZl_>hI-eF z(^|Ii9WudF;D>}z#{Xe&dQ5HJpCtWJ#ZXj0g-C|b_A&9jM>GfB+5@#!e~P^*$D9Zq zcEZm?o=Kgd7)8%dtNl$o@5P?kghJ*^twyVf92hNO&a181!_3zUOX05?@(r^^t5p>j>=Pmf={2*&jlS? z&yJUFr`5Dy0!_0SLH4VLpfG8_`p`#CK~fczs<|-KBZLDo%=9OY2K|b8@k1zv^Kt86 z!|urHL&w02Kd}bL>O;rLJ=YiGhmP|1uB8T09YH(j;JRx$@IX7Lpx%AIG zyZr3chpJ+HN(#5L<-SGkCxI%4GYitpW>$j}+gH^-tv+;ug#B@$K2dmb$KL8g6M;u7 zH!+i>-a;`|^zlPuqF1e096vNF_6LjWTE+>CcY{#s3-zvVBeNyuyi|cp{W#6Xyk{oP zyl2-lohIA+oCp__H3kQo%Dl@L~m*dtfRFOg=Oco{27BYP1JqPv|w& zV3rIs(e+6EZX_lrGy>k~fvZ(WKLRZICP#f{`XR9YK0rhMsPt7nW4#uCwP&zlh!~6Y zh`mm_9>i&zk>nMNNAzFID*Abf-Ac?^p+xz6zsTGb-#W;-r5HLITV<9hx+t8yzqAKf zxbGIZqEg|^m6QA?r_dx>Pyi>SmLMkUQCAgm^6Pn(T=A<*e6b;CpjWtp32x2g6%|%y z4aRSRf5=~{x?$$~BzCWL(&J7K0Jk~!{_4&7zyI#nA3$N+=e&vCi2Iyv2hMl49X!H0 zb-UA7FxF|^Gsu1&if^%V>aU&F{qi^}ilO4_L+8)H)Hzs}tU6A<{965&YC%X$*okiz ziJiW0@*1lHAaY0g?quX+=QsO1K#aNCFpeMUVa(h+1JH;6=wAAu9-1BhDpe1L-GtDj z3Z;MIRhePQIfgmbl?z@72N@9=8t25MQKaGuhMUtNgGH@*vxX74RHt}G;rH3YGs;NV0Iw-%Xc zX|Z%HF@ka2%N7eyo)Z?YDani1OvG-w=kSJM{@Fe4rK*k!q=kk%|%|FMn?pZijv@{iUHB zrR{wJYI{SZ!@&>_M#t$EmGuSrs2ggAKzSV?7 zzaf`Q`Z9&yKy|?Wl7uMzA{=k_v|Z$$lOp%DUF7nfG9@lk*zz9LMQznM*`TRQnJ!zb zV^pDvo;tEPsDM!jj%IzvZ%otkzXa4#IhS0PIsp?z(yCO42>Vb6< z`NyR@V3_lG2z*=`e*go6OEUdQJa6JG0wI)B=?!ovr!+Tj?8rQ`@wJ~>k=xIXJi{ZK zvJC&^T4vSsbGm-UT+d9*7I1fObRH(QhmMl)QA4vccrLg0CXs5_mgL2Twx|sD>fm{Q zWZ6c~5;ZQiWB*>_X0o(Az<+Fq(jvE$;|S#J{be))y8QkJ#IwsUb3ICM^l2?B=iJrj z#5}1p*~||={R!G>cdE)m?u$YHEe{6cZx{R5TnjAz(%AUHG5$4Eai7VnPVzpf+t8st z#?0Le#0k-{;~Vp%FKqX8QK4c!d4KeywFwO3o&;I48)rs3eODJtXkXc`61MNYe$y&h z9qWOb5`LVaa?apJRzIu<&~70dhRLqCO#EOobHH@NWmE6|=*d{nan4y(7&|uA2TI+K z8RJwfDvVx-6GbUk>@PTd1Zg-*K61F54BdQrgmSp9a(3a>yX%}iAsW-p+aA3qg3|DX}VrfhxZMw*5iQMidRG(YkBNWd>QL7Ju$E1 z>rX7li{$*0)aAHheCjSNmIX8IpY>vDri9&t;6~1WjqEAQ{K`XYE(2_q%Wy_+l@I^U z=D%}L-EM&Y)%Tc|Ang81<*?rM!2Nfx=IjE`BReP3cQO!Y=OFj(+iAdhw^tUuhB(A@rhmX$4cs)<|NvxkBiR?KcNp~EPv`FMW6U;D9JIDhR zRXZ6>UQ`l4SnOZBj{zRU`BNt#>7=ZZT^ zn!At%{deEo57s7fi1PVJ4wEm89(sA0C}Yf+t@$_}9U2MIgCxw_M~jb|{98ye@>I9V`URaR+gxE&|d=1YxBuh>zcoTz+&Ii&<(>N@wwK z-*v?@J-CH?&NuU)FiWeo3e_^QH#A{XDDUyv2XY2Pd&~q+M8BGe9vX`JU0hl6K%DUx z2uH#Cdnb%l87O|>Xn%qq*KT2bK@I)(d6jN@oO2NG@5C!ikU=3B#D7Bag%K&8s(PKe z=e~XrqcD8?NCe=&Thc!DarE{TKd-+OztBgyhoTTyPP&dqil*cEI}E!-Xx6#A@jx|d z1*#PE`_~)*&Uo}*g*a^f1cIOAURQ?2LL69y?|(2z4-U-aFbTPSg=*#F2l77DAKyEQ ziF1rUaRI{I!YzVOfXs$H`5Y>Z5az*7)A@^9?jCr6ErBEwWTm@k;7Lm=l6B)O-M>oQP4Q{)fnQ!db`eW6v%ty*oi(6RzLujQ< z-{6bCQ|T^6It0#&f2x!9X1YHTPOe}U6Y2CZ$gRkylF5|^e{Us1F!4jWralf1=2=n} z@vF+jFR>39+3-x43Vd%PYDKOPQlr+jT%}6!aLN(-Qv5>xyTKZJY?#GA2e#5YTvvkA z**Iyi1&D;S|5+8+6r1cUd?=;+Ah>Ph;eEpG+t4~@5>d@yUIO>=tz5uIrT2NnR&-X3 zXlk8>A*0IgD!vO!r|D*2B%J0xNJiwF_$7)Z7qA|~mBc+;zbxsQI7#@9j{aZ^!b$6s zdaBgYOQ>H%Q1qulX2sC^ODHGRBN`HxPI6;ESR`-VhyS8X>B78*Y-t_!rP5S(fjmFh z`#f^iHE7>3zCr2QALqPAp2R-!L&pAK;TBww?Ow)flwXes4n-)WXr|W3DqN=7P^F#q zw#4C9^lMYx_S(EY-F$$#w3byoZniSqm&tbV1E1ld#Fr2-YlUqrUC<^utvMM&NqS1b z`y2S8aJ5LcS(UdiI=0X>r>UzY2(Y;E&(L`IoV6{;9{xVAS#04>J_`KEZ>il|t5I}N z{gYsm5B|_12p4?#gd^QWrHB%~rh*?k!={c$uG9Go-%L^5rASRw(5#J(M$&B^T7-%{ zdgmFc!q6bjNi6n73yl)7MA3;@Bf2xOU5WD#!T45o|Hh~(HRhvJSQJFig_ z5V=T24(o;BGjz9I?xK1pfvU9+AgZX;r&CNy-j8QA1gc?)9~`>{CC=wh{E&I~7W|X^ z$@cM1obRjUFwGQ*B zB%i284ed$;5R*YtpT>i3KS2+@r5@1onOc1CV-y40fVgjg+BChAR;lk{Dck79B*v-` zQi+Li?K$b}{@hdP?5^|qMp7WVs}z*%o*FO0oAQMAit8?@I3!E3YFo=O`R!2bX~zYI%o#r1PWHpMEf=CgDvQfM4K1-HKOG^R?qfg`d`- zNS^vPWD%9$(Emui`bIi`lTF3`_&XD;{kN!ZL(`QHDxK6L$VfV$G9R+fmTFd+Q{@LH z;oYb$trjD8O8nrFTTn|w_n$^d8af&6g)}bA{Lwj@H2Rx#qmuX}$SCpLCso;!y1fl+ z?yS~(zbith@DRRVMN&NrptT%rI z>X5XX5ART<0MzDDSXzaCSd@$XiOt|^ia4kS&($HP9*_jAHdXzLCVZ1KB~y|KO5bA8 zO1qjmAI*Zw4|DoDR6o-!q^T;B%OBF!^!H9?Ev6fs=&>l&Y-r+p-;uFWhi)#$`V(=~ z22yiUGv9nXqnWh_kPjH8NfITMJ}m43Rv1u?D%0+Rsm;)Vsb85-@QRVG)67y&A?3|` zB#1PeXW(Tj4$jh}I!6lhbqG+GyjOHVNyU-Enf$j9oKjWD9^jw)*6SHz*WAwxfqGRk z*|;s}Oe4FlM!`tAOatgeg1vta5Uydz4@`?;m*REB>?OL8N+h@eHzs1L@gC0>-6)w! zpJ^FRM|L6yNvqVeIEXg=r0dWWPp6F^7_GX1iPs@;>T2ja)1F|m$uxgY;O!Q64^mHo zu?z)%kDJs!L;{Jf^soANN`}F2JvltQS#>B>tMYZ|Q{@kIdhU{%Uq-o9DpCzQKtxvE zYs7eW#9%j7^qMpu^qBFHeV_~_nNy0N#&NZF^Uj<|MfrO-BI6=ARw5N2KYn1GKT!q6NS0#WxN3Js=(P)U9*}zb7?7oE5RFXw>Q49uL|@mF z{@zEB88caWn0fS%_!mDg-eiS`5SP>eaFez*-PtuQ6$ZBcUVg2~S)gjj#JMLmFy=n+ zSGP<!6ofAsByTIMt0j zMXgkaxU(H8j@I7GYb!+07uo|P?MXwbtqto=P*9? zD};nyQs^=v8>W7NltLHpY>G*7_sx*|3i?HxT?Kf(N9_O>K1cO-;dZ{MvIWepT-Tc_%{3(b1-j3@YxMkvDT-c0ZkwKH}J%E zc(qyVo(R&SL^ed?LzEuzh*`xqVa7%kOE*rCE6M?Od9kg>!R93)N0$$%#&1C=gw z>Z>M8te5n1f2Gz=j1kYn(hG%dA~%|-G^@r6NAFLOCJ=YxaM*ny?Ec!Hpnf?MHqq(3 zZyoMOEN1x=JD7&avfyU4`M%Yg&8)k>HzY4=Iogh%AKX8X5BsCZ^=hmA9xQ)|EfIh3 zk3hzL*8Tx>*SPxxM7lR#7&{{5ZfZdnCqfe`P&_t`K0o*ZR#8|LCKc}w+8)LZ^pKve z7G3-smw}sFY&`ZO_hjO~UWRg9 z`nZz0R3%qJZEyL6R=&S?F5aas6OTRAx(??NW@s#jstO9}%a3MuV`u*Bn4aO*5%-j`XRqv?qfE;Bj1gm^Dg}MRXlVrijwMN z8YzE@{-{WKlqE_v;`!>}fnAn-jQsy#C+0LeJKEaHPHqe|cAthb=mX2TPvuODI5`!* z9mldab#>uV+63Y^?|S^$UUk#DypN1!{(Bi|t(txX{4K+}?LT2g3lKP_-Mj{OUC#G)q}51*EE z-Wf8_A#CKkz!G!5djO}{x3$WVb&WJW0#^ezI0&z`qy4>kn1^!1V{`sbW>dS(D1Ao~lqCD=e3a^V*PNZ_L<` z;!u{3Sh?IOI~oQHX-t21Ep&@C#@-Me{kF*+nk#)R#kEJ@pTld$MsuX7{7Q4)yV!BL zUDI(1kG72tI|m&;@^2E`Na{~Cb0l*CZ8Cm$xD%y}Y>iqny2hPLF70LyE6Lg|o zM!p$-+2oxI`(01wvYADB7i(T7&51=d_5s|}5#w$NI+NEZ$2T-~>qt2=@ygf{3l;U` z<SBY&I{6~I?#uJ*M^;S{kUp*boys)3HcOh#LVlc)heU%lxpa*= zdt3``&p-T#150+J*A(0^st^8Ie#$t#1{dct!@HNC{MWMQ{(ymVzCW{4@Rt@PG@-zjR)mQxt$1J{CR6J`r;( z`Mdgk`eB+zv-_EEhf_N)6As16<*34crOiCn$F|KpQ$MrrCT{XM+YY*u@gpAK1KfCZ zk@H%Km+NOH7u|IHh*$Fg&a@Nwa6#}oLDjjjyuDcC>oqR@0o*Uucr_IQXWIL#aG#fM zRWi0I6Tlg+)JwQugCE@n{PIvK^x#To;>U1EkALE%y~iC49|#`M_3B=E>+^BcFZ8-j z`jf_a83q1c_XYsc@6+_smTRKiwgyd2VQ~`?^L&dxsxT?9xZMv@^4}mkys*j6Bmmxx zvh-td0&Y^zMoG_A^^vYv^sY0u_3Ajm50{g(rmX2qelT86(D-5l=xeFQOXQk)d8)=u zzsS6qr12IH{TUkHWC-<@pP5jeK@Wbe#@BgpK8_M=awA{N0KLgG_8V><&W7i*LD-dp zKAr<#p9BB*9QY4&;1A}&`B7^&`DrvH8~#cTd^iVQjQp65&&P7$RXOlEIdEF4$i}}V z2Yz)9{6^rkN!hO}Lg^zTp*Q59|8WkyKL`Fq4*ZWf@W1B3$DlsS7T@D@;AJ`RbAXEt zPF=y9`gyj-%QbHL@{2WIr*YF>T&?lN8kasj^mYUAY;xYF=}lE5{dUmbo`e3UIdIPF zQvQ895K|L9VfY`dN~!eQam#SB$-};JHhf|Zydnqw=^S_rIOVK6M#-b6TYO*0LC>?| zNxxguOaC8U|4ZZ5$0|P3&&Tb3hF-Rb=srI1M>QVM2`GJh;J*c)Exxa5`c4ie;7t2@ z1e&yL^dAFGIrn}@(O<4EzO!@C^GtZr!-o~2^yP7TvBrzJ;Q(&7y7<~OzF6Z%2KJ@N zr_+Pqsqr2U{)EQYdvKopPCgqnZt~9u(eEUFmj|Dw@qUeWYB?{~c)6Zbk$ySebptmt zYf`yfn*(2;1OI*woZow9qR<3A|}J}U=)Q4YL02Yyu!e02`|i#hN+bKv&? zXSvvShRV${#>4HyIq09ufxo8tlyd?CE~qZPQD{)ezsG}5)c9@>J_UF-J^Pl$+M=y6 z+6n-r-j z=RcfQ8>yMXe`oODH2$mNKb%_|sX3GX&f>qR@9}&xQQ=``qBCZsvly*bM~*dMX=7!5 zba`WIbF;GVe7I$5L(|@|LYs}|YKyPF9vW|0THnyJw7wY&9=3PeezvU5C`;Fhq_G1k zs@E!15Of#qXy|Agi7KUy#2OkbYugfSn%0(eqwc2m#!f8Y)VDM((GZq2mU|$Tan$0D z^0#bhePesKEJ!Fo*jg69u^1z7>ob_rk`jgbsh8EC%zI%m!VEZ9h7^~Pa9c;Wwydpq znzzDL37cWdxU{vlH`T9L(jLW1jl|oI5f`v#bTutm>a+YeH+Ca0*4HC6`$&SOuH{W#7KtSwqf`%dD5+Q0$37qJ=x!Ym zGwOdtq!4IFXVi|SsbWOiO)EQFVJcnjC2Om^e)(0%hh4TW)*yB^yP~b*@+EEcEr@Zw zH#? z@9Jo1>h7ipjbx!T+HJ>QCBO(>H+HmZL07c4H8w2iYP3!YK+V(9++2^sTW>Owjyw~( zt*Ke(GFED)JeYEa1?S}`eLP!0NohDh3w$GaP4b44%8^Cn3%WX%)oB*m+ZA2i3#Gl$ z&s|N?t|jf=&1ibWdnX7MKpgX0*N;+nYRt&g(9+bf6pSUf}?Q*ydHo0=L$OA61FOone#P`ztL z&4+fbfpxmd5*Z$EROT7W%yyYhqxLA%RH=&FV#4Pk-k$c`W_1>FT>|{jT8H%g+HWm^5Hs|p-0zH z9P!gFT+Kr&d*_oZ{3K29m4CLzF}>pB(ADr?ZSkLM;qpxeo=MN4_ci#@eaYfOJRvB~ zi?#Ta12g=evT$4e4{1d+UKJMo5(}SV;n!QZ&F8-?+@|N}dvxT_uDg-vBm!_IUIzaW z#>I4eZKvZ67$?$sadY0J7ymoPM|9Lbck3GdXQTg5M|yVY4bE{8oj1MSvgoVu-q4?k z{y!c0oQuq|32-Fi3f3Tli!Pk68FE8uy0#dyC$d zbK24H3`hR+@H64oS$Lg=FS2l(o}Ylzkbx<-!=gcaKvpnU$F2`hHPV&P--d@<$!tc71@;kG`1ZQ-`w&d~F=|JwpY zRevLZtD(Px4{)SkhM&Qo3*Z5cxUIKC0iueJEl=@@3MYL#eumG7EWE?QPqXk&3qL;x z{#OhCoJC)A(*I%aUErfG&b{&7Tp$Q$W2Kt*(7I@7!J=fjNtD)IvVjc-jSv*8Z3wwQ zG$b+ENUWD)H&K3FS827U^zDtl_O!IM=h&lFywoOufV5T6s+b#Tg3y)j) zx>N81L;fB3H+*(k_!SoZjD@eU@V{EPtaDe8Cy6&FAwLy`8U2fhC{MT70HUK_kGAvn?-IfJu-lWj z3QqpEKA*R6Tb@G}ZqsLf3=Cjg{&NKjWms)rN z?uO4J7T#syQ^^#@mGirTyK>%V;dXqVu<&N^GvPjG;dZ@u9Y2;ZekHdbI5?)CUL z;a-pdf55_Rd46u;wmh#0?#h$JMk)-$wdp$qcj?zz^o)v;^9vd1e`wL$@wzVq{e+p6 zM$5yjWcX*vdN|6t&cat&_@x%!W#OKMf7QZm`FC5m9jDDflRaT-qJals25JS@0$v(ofUf=f3djT`>b+)m?FLLYSa?-sns!G9?@zdGq6Gc0(QJPrR!dB5Gk z*US4K96Zd3zzpa|T28ZGD=O}WzajvwSubnwV76v(mrI|c@tqEC)-M;50gT~e)=Sno zcyO$y>vV9luF$MsGknat!i^5SSy%XigPZk(b0i*yk68~`;o!dGv^?t^+^oyn=HO=i z-D?hR*54I~o=mvA->>;kc5t))uFk>DI=c-HZr0P8ddu*yG~*h%Ivj(Wb#pw)ipJn( z-CWqg&APcN2RG~H%r0@m$E=&X+Mze==FA<)hTg23`?f=G*3CWR;AY+2)KQN7GJetN z;AZ{NHU~HB-wQ?$=VR6xMIGF%GwO73v(D(<-_hJw-&AvYTMJh7)cE9iI<7kposOk9 z8rH8^aHB{`NE;k|SkJSXx6AuZZ*Ga#pT6MSrKhQ-E<#$*wM^L5s-yN_`VGQ2i?*mQ z%_}Un<4V$yvJ?z|^>G-DSvKt8c^tHZ88}`)>5t*$>DPC>+xdJaT=AxO7(1W*E|aGe zOG3&Vt$((4C>QgqZI(;;rrtGfZv5Hi8Y%w17VX2_ZA^d6>Tdi$0gT~G^BOj74oLVP zFn~NsOJkmk#P0epI8%}NxSroOCVT_ez>#)We`>=H@C~+S*n`eHzjq_WfA{5@uu$k3 z|1tPC;TxQNREA%Sf7@)31`+!YwjnKzd9v?f?8-rYwupZlqur&wQ7||CcZ&Z_QXd#T zMt<{t11uxOzfa;Hq$3RDe=Poue-nRxhK|rZ>8`*J%)jbK`q!18@2>15ZjEX$l?)Vy z;d~VTZum@-k;3me9}X~45?IC!f7+bT?4V_ekFaZG_RN{erDWE0p*Z@xwL7gq!%CJg z@)ByScew}NipDT2*}wa}bt7q=x*SQH#N|UbEM(%6L2TSCeyVS-ZQ+_DEMI-Q?@zqG z6JHAbp;^)1p84xxhw)#qv(Bf^GJP{#)>iTioZ?rWLanRb+l!^Py#Z2Z((yp zT&K;Md4^TYgYQ)4XUv>4N7EmDnGYUgLN{%TurD9`@M8Lov?UKRvg!uDL7tq1tLNhd ziM*^>sx#O}pSbM>_mJ)7Eg@_9F8*+~53e2-7u1owkEC+g@m#!M4Cg%+tJ}pkQ_n+J zj3qD3;k`FElOZnL${;Eq6VcPtyH zN+q`BdE<+cd7E(%(BR`e6SEVq$&k$c%JZP zlI;IhGN&jp0HHrmwiH=i-&+b@?e8{j|2Et$59hfyAU@i8O{?V%H@ftn11Fq!#OQq$ zmjYG#I_~6&aiKwVSGkTO&uc8LROc0{yCqJ9A9yXmLldYY?=QzIPZq=FZIw7M3CG9v zPc+beT#h=-<;zg9g8DB24bFSw%>?|2FTwpT@ckw-Q~Z6gM3?61 zbIbItB&%?nNMYJh3sLTWEK=GXEvlplHV<RKV|d?#T&blzEV zLF*FSD;ocZN*V8!(9^i>yxSKKlqbVD#HuGgsyrFP-Qzm%`|f8YIjkI9*t!JD9Ol0} zi|35ZQ%8`EiX|7Py@!YVgH1;BF22L2ZgJ0{nE>Yer#Xi|F`luq3Wrw2#xBPB6hT1J zB=a3+o|H3KmS;V!&tQp+Rr5#7;Y9OY{wySqtcW`KVhzrD*jh;dCq3w}SeR&3Q@e~# zD?u6^8v_Alxm~&1?hT3+-7^`A_U_vf?w3q+AF*u!r_61Mk>$#~@0(wT;fBpU?z=HY zr3GHt4`CbDH5|Jh31?c3gtNag621&L!>z=VMx`;H{HBgX&$-l*a8}JD;TwS~{_^2e z`2*OU8R#DpdMH~Nl}BKELh!JIV{1@NTRj?TYPGF;(VI1@7gU@#FH%u`-u(GX%BrfX zBJ(QBs`Vn zEqfET4{0g&dq=ZEj5^djC5QCPJVBAtlI{zQv+%P7KNU}QMGXBNf-^bTGB$XQWIeWu z0~X$A;Y?pcKSt7%^lVod{NF5`Ll6f4cMG@q|4eXKPIy&@&ipsystk|D;Ilf#sL?>j}_}4$pc-ECpRcrJw(at!Y)gx8q0U=}_XOfuoHvRdJ2<`;qyVnJTk0h(S zWggEuTK}2GvmTJ}jhrSxlaI}N2o_>t1IY6ZiKxjpj6ch*8-FvNRqXiZK71OMFWZ>- zo96;J8oNz*_$c*viTIanKEy&Ix^oCoHY2}*FN9^J_=ja2q*DkPe?rE;(QBr@-DdIM zApXt6jVs@ekR8}gk)P*h(6BBYDSTohscNru*8fb;mT|+MHfQ#`>)XvT13E|Fx7&Ek zkN{z24I@6s_|)Cf$VBLSMb^J1yX zMg{J^cvRQZ@repV*JOWzYKtcx@(1qzln*YW4@Q^ygB>qktj?Bw8TVcH)4x7D{^HFH zjdx(v*U;Ii`fT8X=_?>(vE;O2T}50stOTkm!u2-up~{NXcX|Mv zsqW2;K=P+_!?mv}Iyg-j*AcP^;fz!qV2e&^O22hKU5-wra=?+c1-P+iFHXiqoCnGi z*N_i<2D$>^ytea$zCiaRhG958I#^KdZC%v;bfD{RWQ|^G@gi?8?{)BgyU6Rud90NR ztW@XaR(O{b=?-&65;kwEFskr=H(1d9^s-NOEHq;A4g@(%9_OJ;3PHF7axQ+khr7f@ z40J{(Ly*MWB47MUCGhreAx`MU%}D5@j#qtDZ*QRcdlWITEvBy&mV>RSunkZcl*z0N zW%8p7Wp?tB`XTcHl&RdP#r_|wV|Bwmgy9Q4y?=u_oA-VWRPFcDeW#fB=!0i7MCw~- z6`mrFmq6G3>=#biX`>>xc4(zAX2rlt*(*-Or@GxF2EoqKzxL zL(5m$*3x<9X}(FPpW5!5)E?=GuWD&){ERv(^~|6q!nv-;qDUNdFUqtH+&zoD-O}9LJmCNIV=ecn%L4oUg1tAM4C2(!;1TA&1U=8|i#Cbq3>({B{2M`Ro1l zct&_ABf3T-9Jm%`8<8^IMdmOc;*aXPUHCS=C=%)K!2h|vlzi~DDCytqbd8^ePOgT22YM z?H%%{%z!V?fOF1fBtEwQXSnO}q)~YZ&+p)WB>Ep^z#q(jKbHZ2B?CT?0Uv{UgmT`2 z>X=65Nj`y(B&SbpMXgf>8a+Imir^ffFq7B}vvabw16!tb>3^HfUt7%@9Pe;>M@3*T=G-@j*o9oQh z_;&KE#fDXEW!JI|=cl@dt7}?umUXJqKV7{gr}~{|Od;gGF!i z|4Ih_|7PKA${7CU3>3;^_l?zMAix;zi55N2V54#4)hzjv^lVoe{yaC8h7Y@seTzkJ z^WSLUtaA*X2P~YQNQ1Ln(=gok;osm7XP^&)hK9~UqTZLO-yz)82b&$-l)t~DZ>g45 zq?c3t5A`mCke^8=O=*dZ&leWkFKi_MbL$f7nz{|+-!=vEA=oGRfq92k^L=0*p!o>? ziK9_8%pB_i;wtRYv{PXtPnY~?{fFR}Jl(Yh#y{O{W5PGjFdS(wwuxZ>gb2iPU>oDl zJj>x|>^9vhH$vj*(tcX}JIUlT{&(9`vXgcWg@V~Aj;tH<@$ZIDF-HpD^bO4z7RZ!w!=E;%WX8Lh_bZuU zmIfSs-_Wc}qyS+h#sA}T{j2M6decA8^gin-rhBG3P9=%;URmi;@0yHYK=P&2>Io?w4{Y8(rB&+k13&uy2)tJV= zx@ds&x(6^=@j|k?0G<9mj?|PTPsTt)U)1{*hD2V7B-?Vzk_!tW$xA1cB|kGYlDajg z^V^p`TS9-CxGS{9|3)PBfd4-NSO3*J z(7WrH&`yLr-oI<&?$81M0GvXnZogrH_XvY|5>AEw-3aLs|6w?dIevceCT|Zy3-!V& z=-)o^mCzpl>!}Cc@Bh;Lzj<2_VCXOYSB8SwyJ2nPP%uSyF#mBVnv`JDK_ovjSw$t9 z>I(em;=w_0PpFqcME$*Gsjd?reCiTU0)d)x7*ND}B(x>!-%^&GSB%*Bca^1X^qqX% z`pdinkx}T7;U1Nmp?9 zBxLnJIr@yPBLvA<-f-*_ucc!dJR;Z^$A7ZS1Uu6WHn;z|@1=vyJ0jT81Gl~WmJXI0 zGzwmjdSKeTk~apGq7mz3f0fm;a^zSSe7@q;)DcQX#_HXrV)pzOzx>P49wbLvs6q&Z5T2k=xgT1WgS@LV4+VR83_P7t zviq060=Ll4h__vZb{N_#_~Tce{*w;vk!a|^g4DNXMo*sd8l;+^df@bdtN-^&y*&(h zRMa~V+MT-n{a+qDwG>yLsVvTv$V&%&W1#+m+qa=y0Uhthm0`GV5)nMK=g?!wYGZm; zar%94?YZ^QEcVr+oL6TYnJodV9AV6FIa8xogaxNa*2+zdw?? zeRRpjTi)_^MtXY#hjz1G*mGzPf*2PagYxU|>)i>p?!hoLys{m zRWr>;U3SfDFXKMDbRbdhQB*!TW1dRgb;7wY zm;q+s9=MG;@7hf*sC##gJ+#Mr!#{B7G1h5gdPA=xaETk@^cU1vg@}xQSL%UJj4$=y z29<;Hw~os@_Yf+KhsQjLXtFxjG8FV~5BQ%Pa|pS0%;&CMawznae}}ib_tCM3cKZ*F z!KnR~Fg^=ABgus?^!AMM5BTx5O5J$etiPQ36YnpF9vibI^aga6T)2}#Zt+(Y^`U;f z|FNe|^_4S!rT2qhyd2}P zxEv_QlBmsxpSf?t6;;!*Xl_BlR(t##^EI2pAX}0=A?Ce`tLiFJwS|di&yJsg3(WqGh4C-@lH-zWBC zU_V~$V__dJ_HnSkU+l-ieuCKZVLwsXu?{V7U0EQuLp7vhI}+=uI~c5PO#FEuHs#G! zasys_`?Ft-{eU@Q>-t#ga->OYhiVhz##ldfj`^8Cf&7(J&M}F71BrpWz~|~PR|31& z8|v}4Bzp2ncE-H9C$zoVe~y}n@!>x9fxPyTO-R+RfPs~&-^8m@vs_Vm3~oQJ@P4my zMSmaeB~-T;V%c9>hU2shsq^zZM(hVnQ~S%W2kXyF}f@Z!fE?q7m8tWX>(A8eRb zq*@Ajx9j7`?&aQVy!|jaI(c4>f6H~xg8rnEE#8UVuM>NGz0ZHhzbmotZ12LH_yt~% zigj$tmRRcQ(S@;+#{-{x1hSzJ1QML5JGcePx&(^H$~+|EsDoRw){PEy^VWfi)at@= z|1V=x5ai3EyqEfR@W(WmxZ5o~+6lDEF#z2g*}r zP~EIX5RJnH`=8Z?ofy;C~94 zHZh3I_aZajpPBNHAmtY&#}$|0!q9QWZ7=sfrm|lc7uM$#MWBXAGCK1uO88d)M-bBb za#TV0RE#>@0N`*xZv}Shw{q_-B=(^gZicrQidY|PuC3#j)Jm$&||?>oqioYVIH-1h@qr5#IZzL+P?QS+o& z$9&y32CWLI@+)haksFhf;NV+|%(&#I1+Ya1#}~)ek+G9OHko0=RPsm79mnzuug_L~n$r?T#!{bELR&~$%qdr5 zHka{l5_|^nVRy5wNZ+SLr;!Z3{v+pmnZ)X@CJ9`nIqV!SCB9Y$M@%|$?uhsuf~&Ly zc9P&`9g9jcU^M^8wYeO-N|yl@n*IrAz%#A2tpdH8r)9)pR35>z8vi5lZ^(eRXTZCF zlYcQ6DZ!}xgy$FWKN5eo3P!@e51f3~3Lll%fZZqfM!{8H1NJcfkITx%uQow>{t8dx z=AC(6nbmc(F!s8lrS3}KqUfyZavXN8Eb|+2+O)FC3CSbR<8smzCwe!bJ2CkOv>WSOc)&cW+6|lldrEdt(q3|6CokLRP z94%i^wxp^WsD6(vij=B1-^qD8x;c1oUck)jP0N6vl>v`sz^gLg%QN6j8Su^w_^lc6 zjT!LUGvJ#u;M+3byEEX=WWf6};IC!C)uc7j!%dfQoTwQAFU)`!Wx$Iw;BzzJu?+a{ zrJkUi_Pl(*h1>JRlcZdd{&@VG{5DH))?@a(e7l9)^YZs*z#riRDGd4BYq%ANAAU#p z*){dKs6UOHdfU`FhThckLHMOHxZyKd!)e^`DRyv|4`t!MF?C`wxZ&UF;D*m82RGpk zIQV)=53`TZ@Hh4FGDZl-;HF;X@;Vzg_3Ga-FV8a%tb+_r$AT8rPychr8K`&!@yjS> zn!|cr@|7aSkI4t-J<~k>24-d$bH^~%&2UWqGT*06^Yq8F@*Tm5`qM5`VIxm>4(w?C zn>FCB|Dc2)ONXQ_LFb+G_$*st2Vcv=3A0{5RJ(~^TQ~mYz!)b}E`;2-O2U7qIk?5* z-}p1nFCL}-R*HY-bK7hX|7`o)#>j856|jsH{{k+qf$34dy4}bs)A%>(pJ|?dxA?zY z{F{d(PP%?E?&djJGU_^s7_%||-S8=soA%^!2P!0s#Jw-3A{DIk|AF7PA8+x>5-OTq(krysUhCi)jmh8>fCH|fE^1oNs)2dXK z5%=igeyn(PYrLiTpQe~AS>G$`N9KPj=D%9jC;gL@b*EW-L|rqjWR5v}M-}$>%KAvH zq_-QxW2?|H80Cq#;5M)Ldu83$%t!IUZg8!M5jv_ed%L;iNT8lH}HbzSc=0uK5r0* z-`uATzftqEvZF9Puk_x#8nb>+A2QGQUVeBlKcL!puRLTZ4~ZRqE`_+^+fb5Ju~r2e z2KLXLe-eYaBI25VIr0;MGr6?^Aq6wsbVrHGec7Y{TW? zO;^;DzVpgpGY=9z!i|>%J5F-BYB1gsY*!cM`sP+88C}?mNE&ha(5M`44y8 zf>peutr=8WF|n$uN?`4+xEY;9b@jpannvS#UPnCG(h$U?Z40i0=QX$3OdDKN(+)2+ zwX1NytcsiAU3uQ(svvLUbsZLC%GEe5SyF*;nw#ru<06Bt)sEHm!8+)psRegITMjjh z7NdLSv}rn8710RPT3geMv!8=2aFex9BklDy*p_QTTU67;Ynl4s}8D3ocz;;agPG*|@r6wN^LpRu0y8*5ayK zM02se#}@p_v8n!wdT3p1prQqQgLU=Iji9Siiki>#Iu`-WR{?1-Qp<~zgBLWm;L2#q zrs49Yruvmg!xr3YYvW5L!MGx$T*qxd-q}8c#p~NJn=c_75`8mou%>M# zau7}gH{2z;&8s@4E1d^;7FiI>6WZXT=}N{F`bj6hrZqQ%BOfe@sq%ryu*9Z=P!R}D zs$<*zD1hpV# zsSBbCQ9-!;>rmtvzZ%6tWxC46WmTr;QnJ&d@+XN9oId>w3a+a!tz*U9(4l@nRo>9J z5?W=*imj@(C10c7W&Nr-D6hk^J?qEmK^`N|IOzf)0Vp}r)iJNNZbb19PKL~jMOjl+ zaJbgGwy^=VfGQK_v%@Q~$rIOV*Ee1PN2N-tw6XoNX*I2_O^vm>+)H>%TUjZZWSET1 zgv0LJ;?q{tBi{AFM#K%r-J!m2n4)~h=M5ZDg)~oNtq@cb%{nCB?X3iI!y2m6@J(4+ zpU!u6^-YkIAD9(a>UinTTREEQU~T8T)&BMawH zbwNL(FMdi?T60d`WOY^5;nP5KZpZ2s^(d7MNV+;ir#9XmTm|i~majz3YEUw(66F3((twwe|RVH!$^)W!qHED@F9O`XL>icaHYvTcVNy z!pMgmWoQ*6FuA!UxC)7ms(va8mP&Qzj8f>0<%|u8BR_-CP+fgP4VG&Od!rYKYg$UE z;g9f`)*r8nXYeLF^W(v2DLyQPYgR%3I@hP^RAx+5>X30HkjhSL8sn=}M$(yAg*>Do z#K*LVPw+pkolQz3c4}}XAJ*x)axo+! z3{GyXiLW|a)nWLiw>7R@6>mRVm&c{eh;+-!X0#tr3AU*WsG48+9>)W?J?wAUxO;fc#NW6L&P)!F}F6&zA+g0G2b!#JYIh5@6&1}f&>S>j3RIp+eN#1+>U!j5jrgi^ZMq}3fFH=J$dJUMFYuGHx zAf3spoq~n&TqgFdd}5vaO)#n-=Jo0BYB?=mwvVe0jx^amj(i+xveoG)!*Q;Y^QqH9hvQs3!Bu*F zP7r#T)F@w%gX?p;a(&ll59f1=dd*Fr<6>O(*D2Sx)S;iI2uArfIQ%(hM0w0U2=$7e zvy^3&?+!;r5y8!!REBfiB`G*S6^{sID+$lJ>pxWkM!Dl=8PZf@MIs6|I ze1nrNKNGyw!S@IrbMU7Oe+U1K-~pA&qegZC>u*Y`n3{+ETm)uI2Z;O0Cb^@^W2 zl_l4grS|=Vo(# zFDZY9i_iBl^`7f{#=%2^t7}At$bDxB{vC(@ zg`D`ej6S;@^}Iv>1>y6&MN8|K1%JfBzb^cH96q-R&b{Qe`JUj*9bBK&m+QORCWigT zLOJM^PeKFjs})WOFI z{`7W4tYK!1O`5u|JYC`ahf^QXuUjWXwt!uuU z0p}ewBhm9*$dT|p8F221Q)9|lDrF8)orBvjD@y06169u`q5TY8h>71b)bDKmhNkm( zwxXP^DQ6LxrRmk_t7ptmh_);GGZg(9ihj1DoUJ&|R-9)m&a)Mt*~-^!#bKtVQ5YNurSZRBm8)z!$P z%`H5PR}WKHS9i9qOovt7#(b;}$kl@u?agv*uI}gP_1tXontgAlNI^rfP`xID&#-Xz z4Gmsu;pAy>-A~Z`IjwB)T8lp4!rLv}-Y1u^aF$=g=N1cR-^}2*Svc2|8~jcSKi&#-WgaTvVR!slA}5)1#hh1Xj6 zCoH_(!q2wwgoTGK{1yw3Som!gKF`AMwD3|3-)iAe3xC|g%Pjmk3!iV{uUhy53(uBz z9Q7Qt@Z&AK+`><>@P!sW!@|$8@KOt}u<#`o&aotuUbPl}u7$T-_<0tdu<%L?zs17O zxA5C6e6fY!Y2iyOe5-|5S@`1?zSP2>v+xTn{8bCT(89B&{Y(8Xv+(0BoMUH3Kc`su zCoO!2gtTt7 zH&}dXEqtYgw_Ers3r|?Mt)E*gywRe+TX1H(%PstI3+J4xNtf3wyxqdz&q%_MkBy%r zIQ4lc{tcf`S@dxWhgBKU^FOHGG+$Z`9+mVn-A;qg5!`N<(rv2XrtfCxgMzcoMq}{t zg0rnfWAHq|&0LDX-;#10RMbQC2Lvy2@IMI7wgipgvsZAo0cZ^VbHVxTrZISr;QZ#& z82m25`K_ce_$I;mjiWL6*8~qMbO>KBc+|nW1n0Ma#_;JBoOL*j!J7nU-AiNejiOK1 znKTBk5_;BkGzO0e&N_<5;By6EuFxU;4&h(t;4_7uWrxP_nJjpdhST^2!CM`?Kyc<^ z8pCIsgxjg%G;YR?uXgaa2=+`-TpWrt-_%nj9cktbU-|FDo1mED` zW*qx#4t~4PZ*=ejBLBA?{M$mm$-y@We!GL;DEJ)?j-hyE?sD)hq2KJ_c|!kygI_K5 zJr3R~_%;Wx6MUzGoB5HSJNP9+zuUphIR7slJSy~i9ej@9&p7y0!S^|MQ1CxE_)O75 zpM#tEg%=!robWl|;26wP<~0X@jRgT_KtIy?-^{PQ<>1c94la=!B4%r8uE=&u&~po6yxUgY3)f}43)zVhG9 zQ@H2ZR0w^s!zV2GOb4GS_#6kHEcjdppCEYH!3zYBI(UxYF$W)z_X-DpLEbAJe4o5m zIruN-eVK#rly{yRN<%UD|A4$Ncknypz0SeEE$^!we1p6eb7<&EY^UV~C!Ogrt%)w2(E^+XU!vF6$=V|!;OKsLG zhI9YV-2ChF1ra~0&_qk3>kEseR@&JHFEAE)attsB|6zGIk2#aHt&*J-7>=3}% zIKb?4n7iRm3l$GLc~Po2iT!Nbizk#F6vCY-tL z3)A8MWXDbU-Ye_>n6h3Zh3fxwS(j#EI)9E(*3Xz}3Ob(eRMw}@o-tjMAN?6LJFO2% zSV^Mql8YsNx)=3aR^UrLI7T4s!)E`8_ZluRIE*_Ce##mUw-_vsrJ9OzaMMYVYRXu5 zJ4B0?;qn9T`98Aj?zy%&>ir(qSj4=SlwSq&=J;i}reU1ErlAv;9xPY)Dloi;z{|K8 zg5gjrp@U`Je+W#$9S||x3o)LyAb*NGPQo2IxF{l3MJG8%0C)G~?f;fJ1E8s>LJmoI zkP3$&lenf4Cw+KaR&qYU=t_>jLA>@ zwwmwjK02to2yj_}+(mF+KJJ@8{}}83g0ivf3)hhrhI6B?pX&7e1q;SrWUf6RT?WHc z`{&z>kvF2WBdsCS-{IUN=&A1`TVI-Nq`e;Rhm*Y)(WKGIf@^+g+iMoS*?1aEAoZxo zfM1XSug!q3$$(#<0sk^^%6|Y)8kINj+=Ty;z>2(NvvUR}znVDPUJTeV&#@FEY5QHJlHl@LL6NF*S#kQWopCt%G`uE}A;4ct_ zA$~mm4L(Xf2IOA;HOqdCuTL*lEaz|HiPq(-_>O82jH}V^p<$+}?Yyf$hxxbjaGyPfKjenE=nfjY% z4;$-a+qm-c-Ibm6s{}N2Dy$IFLXX3|95I99uWUk;@>=6`A3qSw0S}plqdU)4BHJqQ#;YD@u?>>%ediB z3x#GL`Q6Z?ks8;(v*pwA-aQzWGGQIDou~#tn&U04|12#(l&1RDC@J|&Ah}Jp<*FF`u5`56Ne-SD{C0zZ27*(g%O@UT!p)ouX|w~ z90GTrG;H3XlcW1r7X>jXF&CFs58@e?XOz#brvqJEa&ZXX1AHs@4u@XsBmbyZS5&~C zapm3)KJ)l9fj@=dq1us)yw}Q;C+;7QTg}T8+x)oFdqNTUJ&M!_+>`UkO?mM@AKZpZ zzjpyRxGgWxbsBV+xVk7h80dNyp9d9EEEO+`sY8;t-pA^A2ZQ(V{%Ssx$45$@h-XK= zk99xRanZd%*2Yrf^J3TaLfp^BN_MS@rmw)p1WL@?9`klqOxcG}#vzn(2qlK=G8uG}eBh{DyB8P&( zjvwHWH`wuQ;g<_)Oty^2xy}C({~@P=$n(0xmm$}A@uGsyo{+k}3HH>#?#6H8@Pa_a z7R=uignAT%a_{GuUIH+FsQs^Wns~_H^>lnp;%}n@-AUe8&QL3AkrIJhdm@Rq1_QTl z8M7NG^~zQAT|I&BQxP;`Q;>Ka;D_)M>bdUqA0gbpO()L`wjG|B9P~g zCZUzc{U>$rKYvl}!%^?`z&CoP^m;oZ-Y)NFkwg0Fc4?d*LstM`rE$dtz-hn|ai z0}=nPPy0`Z726O?jqB-sesm;t>-$b&;HjLQvD(M*Sc|(JWX@_~?fB2*ZDA@JBtaN? zVMh%2y!Y%HcCHfY^To+@OkaN);a<>)JgrO-7yikCyP0`Yc>Ei7ni!Es8S}pLOsZ=n9bu1TqS>&tDM{2 z)6s}DnE(NnBb>6(iz?j$U0mA$E3#*IH`rC^X|w%>oad9X%F7em$Ca0C4|LU$z&mK> z@{qHB6S-`D-dyC8af|#f^gp8n4ExHx-$as2Q4Al-Nquhc@ZrOU9-Fv((ps4KpS>-; z&lh}e?OG&#bW3?^X_nVp5r{tT>n%_GCcAvfZ?urzpGK@Dc!^kf;&0g^T`VyFfRQb* z0A=iVWub#!Q_+M9R0ufV{2|l@Ce|mhGAK{HH9F9BJ_`QAWc-hq6x5TEh`{fY@TMx0 ziX{B@&qBDEMC?Ktqm~Xz;QK#BeLxXlb$DE$YnRFrC}HF{^MJ+h=_m?UUjK_ASg(s; zpld1y{1LAL=y)Qm{cG@}^qUySL20QdsVfSG17F-R@r~;acY)RkDX&GynbXFrL@FAHguJ)8@vDT29rX~rZRJp z&eVsAfh@=bcPKd*RZNr$>3;%3mhadGO%876=P6xb>na>{b4iD1Sf1M7wf{P{{8grpWQ5KzttjALzksdtqYV$F?rQ5s~<>tGUv*u%_8J zsd#$bndzUQSKs{l6*%s^%@=8H!xO|E&G>KfMLJgE;Lldyd9`uhxh+@tqV=`Ds*d`0 zGQ6<9u36ivR&}%~XntEGU6$}PYh}T?>Uf6_Qsbz~4j)M9?puNoe3NE`E{@DAjh4+{ z5G!AJPQ{{g&#OFt@sg^g7hJgPqEFVWsKuGID_1pMdRf!z=9bpW+uGwDSFGv0@-v@e zvS%ALIX*_I zYwTn8yfC71X2*!&2WXFK{4UsW2EO7k6=9YMPMT7|xv!v9aMCOioa^8h2~L_y!S~TF zIB6~tocl5^5}Y(K!MRT)COBzIMP}j=A)@_UEvAqAS<0go7gFfmq?foezKe$0FH}A> zt^->Kno@}{?TgBmFd2Nb&)4KiZ}UYq;$^~<_6tRcm!R-oC`t^%URtV!qkWJiAQLGVVcfUHl2@5Znz7Ws&4RP zIx3HNGVSK$NyGG7pshZpQB3SimvXT)EzS`;^VJ{gseg{S(NNEvZ=<2EDz(*D z0sHx4FMxfq*nbIKEfM<$*tHfg_67S=!Ku#+#7=#xM8`YzX2w9NPwp3|p?*|?>ev7O z{JxvTJkZK`(Tx8yi+%pi0{_2^8=c4fG)&_O;&wV(iCl+sGtWo8DSKXiFqJbefAWpF zk^JK8M@91IBt|dD@9}3}x_hJ#@V+zmnEf;)_Joy-DeU8RQ*2hR^ zv12v>oON&a|_Qt}AlY+7uhtbwaMsJ%f%k zBb_nJdVu5e#;81o7oM+BU_k2`&wzg}1Aa>e{C{P@zncNSCj-76_;FczzKwX&nDpHP zJ8@%{i{%+SM~c^rz|}kj%NUF*8+g8s|B>i@>i!ZOU(TziSL0mvRn=&>v{%=5;M6P} zb9F`i>9eQf(6#tyd~53KFJqg=oa7~opzx{=<5H(^&C)BDu!@N+Gpv8AuCC=3KGiFD zl$P&^W3_OKR=lN2G3u;tZ;H3HH-e}U7oL=qRJXU+)-*ThiITROHPyICq(+uOtx?jc znH3cgcp7oF)N0xuZsr%{=oiaYT_3;&IUf55`cxHRcMXyGs5 zdq%?t2S*J5wNk!`bN`sZzbrWUa9q;h+bw$X;kTN`KEsB1lhEzA_^|#pd=`^248yh8 zg{BIff{HIh& zjF-J0jYDHJ^k(bxHx~Wza5Ma0%s_vvlq*+nCtA3zhf@V-xNM&r{%2b_%c#L&RfaVg zMKJZHsR0bm?*xr0(*~ca;q=}^gBJ@Pl&8UG%Ddrba8v&ne+D=C&A1ypEPTw<;8DS2 z@-(=4uXJ!-?+?vG8+t>x+@Y6jked>2f+v(s9^1jx=TjYJ6gPZxg^$z}7 zdEe;Z@|wQ4-N<>pINagTe_q}jZv|GBB=AmYe0aa%fJ zU^M5O`0Lknxsz8_r!X&u4Is}RR%S5fOa#`o3@48uOrd^c+#~!2CtM*{JdB-BmV5G) z>Yk7?N9#WXYRWZTdrSWs|KCU>+Co|y^9+mK^9bgI%=;x?$m_-&1HTB~n}Kyq(LPd@dry{o z4|%`df40nVDKv@gNAW+~%{RLiQ%-g_uNgISX~04+UhMU0R5AYvTg5wkOx68A z6FSaadb?%z()$G>g6&U9z5OZXVJ)HR9K%E&CI*1#fp**MO&8J8A)GLXX;~1CQ+SplZ1`S|-y)qudkk8MVajy8+O~!X zy^gDpDV7bJF71MRk}JLa+_DyoAz3H)S7S77Xs%Ob6wbh6KIuua1=S93zk;W1?S49N z^P9uy5yk!2i8i6i{x&E^5l0e_4))jKP3@dJ-OMdnbLEK_Cdax5(>wKOQ8^@jYWKnT zM-pcbcAObYEyzoqi)n>%JNF0lJ@bj4yhP`~V8@4JB|AG_K`bYGPYuPhzX^?Th8TLf z`!Vkc67SuV=(@Kz&!;Aw-m%jC3g86JXrH+&4o1v^-wW;_kSyr`1#=e zuO9uXRFyrBY7CGI05}FHcO*sfgV*zpqy+Cs%DNUeB$cXdeENo@*x0B>O3j@~5mu$_ zD>RW0jJmsJXiO2Kfg_A5uJ>o}8hK2yoc!wW{{Wf6w6Z!G;y2P5Wi)?zRvAVpOOF_# zEFYWoT{s{rBMn_D{v-V`$alY{cBHQ^zs3BTA8E3WXyIy_%wves5w=)ye8C=TQ)vl| z<0kUCwWxi*(=y;C8SsU`kINd8-`Fn7K>w8tIQw*zvj(dZtzBl;C3Bs@q z$u^$B&mjoo@-cmB;%ufF`qdDwX=}gxzW)Ez?nf9ZH7 zeQJyGf2xC<@XeEba$~nik2$i+SI#bNrapUt_zyZBjQ&hm3t<^a|Ldu6n3#U3x{Jdg z#{WC@IroZxelKj}h@;|emk&c*EE#I2cwiZ2*lzfl`kVtYW|L{m#Dp^~G`+Y)FC|yM z#YfmRV%C<2=FE^)=11S>oLp)`Gxaq)mp_cvq7Z>~cM#JZo3pAk!*M$%aF{^f`_ zCdy&sY<_G=ase8-Z^n|716_?E4czn`I42H|il3V}JUYkD0?PlBGo@r4s@-eF^kCO7p&sKEsY|mMe-Dxn%45P|uD96X?GpmDq_# zgSQ|YOWwe^Y-gmkE$q(;+(U;i)4}U)=U#4oKfxA~^p%u?(cJIEt$e3-E zA`-agmxyiPo`*~J1iE-xT|=~FU!bd3u~*6%I`Jdavwxym7nf2a0_jC(MnRhwKoq44 z-FJ`}i#CR-AopFWK;jQgC>0FTI|A#XUZCMSsk7u&g%YIrQc6^c)%x?cAWm4)=~b$3 zpJ+9CRY9^?6PU9}wjgG5Jjv!W5J3M)@GzubN$prtW!HwNR~xqDs?hB!xl57Uw@@}K zxz+nnax2kwa$j|1a$kgiW3>sM&Kj$|r9!37Rddjb%8r%n4t%{QaCc8C>hpWqDgu%d zB!Pw^(SQCh`B6SmED}2=b66wPK5JFqY{?gT7~ zJb+bxG4Gt>J#R$3Jy_NkNxY7%c}`K_=AB@>qqK;HN?p(vxtG?McOdqa*deuuxF>Ma zV}QKUU<`sLkC!-BU^#AbjyXyOX>J7<{sdpi#cW4Aj%eo&9+;k1YKR|)M5;^p` zx1(DxqYRuoz=(KP1p_zDfu8X)J#dq!<^L(itPwLlVqb~etDYuCH=hpj9i>6&&=*nF zn96AD%Tu2(K%4GC{!m~0@7D1EA4PgEfBUatn(8qJXvC!XkTRfy&8(GBeU{h0-v1vM z7LlD284fR@C8nqj zr5;q3O{y{n3+0DO^@;RQt2jgX<=J-?ZG@J}J^fU4{XbH927GVkrzCLq`B~m>{6hBg z!uXbq+0sz5CqA~J`{9nJ28?%hH1Nx$yf!3C!~XuawEuT4UFS9BNi7FNlVt5L;<%p9 z?`G9AKGH)OXF{UKe^zOcS32Rd%|{Vp=tV~(-d5yt#a}B)eHVVh>R-R7KMs_sM=NMO zyfmy2+_S{AAe7sXr~VcYtUv1V#s(wH+r=nUnaUeFh8)u`$4H=VR7I*DY(?rUjd_1t zqHdLqu;s)9xVqW?!oCisw6`^uEJI4JX9tuY!R|jHu*d`K#KjV-S?24Q7{NB19K|G7 zdoayMwb24yPf)sqYPV%3<;O12^?i^gyLZFBy_>U>e#9!~T~@GzC6SG&ud(J+pEU~L zl@>y}freOWpV&`;R6IY!hDFMIQR(%+sK%<1@<(mm_#&1H&iJ=&(KYoH{D z;3u(<@V?|#d5OWV#gDnTpKEW`7SI7U*B^Q;R`RPg?~kRHA?v+_QfYQk;7K*1&7zZ^a`(1 zw5#*i+Mj$O2Mit@g`fDezNOfl(Z7HNQ++T)J^g2@gz!B`s{Ox9%l9Blao^pCKwb!n z_4u%}?p;vip*MB&wFqB0o30N8(w(3{R~)Wr8>8DprQXcyB9{E|dX$h@5@Mg96T@^~ z%v-+!4)MTH5kw0I?#Vk?mO>9BdA*lo*!H8c5N0q{30{QOYuEMoOi0TdpEuQTMv=VK zsAQ4%`!c;zM@b6)qd|Sq=;R-p~E+6WNg&wZ(o{c5L%cIFyK}9kgRBEj#*%vQT zHnwHnrrQ-u>P+puJcyl-{XaqwL-mVPe0B%5|7K8_^0Z??-Z$)Q+zvP7IeaCU=Y0J? zhL$&TU<(P@;N=wcS0K+QsdTw8bAaXEYpmM;hF!CJK`pgbMe+>J-p;YAiLRoZaA&rX zBQlev#hja*!%o_bt6A=Aq514{0PMQ9Gu=vp%8Fwjix$m!kYAI?_M9Tsxw>f)eV`ps zixSBlln-?rpUg&W6A9d!Qxxc`fHSu+p^e0FQN_%ZdDT9A)}c7;My0@}qEWk1QGsLg z<4_p=D2Vu=-Umeuh935wRPo1rGujJaj}O(?E0RA}12||mRA3`i81tWV)`D&5;YD8m zB5#0mw0V)_^~~hu$-CJ^j3louw3=1kmWX#fJFTFK;lYmM8gNg%ksY{cJ}irp|E|0R z?k@A8LFx5kS6!KZ%+A0)I~y>E8S&1=roIjk25#aRsK9aqUDx0pHtch~AGY%3`~vJ~ zM1|su>`=0(CJkgONX=7l(kyJ*VG72X?4>*Ze0qA7h4V^JWwqde8=uYmN0yKj$QxzZgE%IIu z9W0;ndWE+OpS%jJe3;DT54u?KOB1ZX53ns2Sj|uvo3ac1DgtG@&Pi3}WtEpa#aZRT zz~_1>L^_)ST9mpv*I(g(Ub}Z~gu9BKM5w|;kmjt`v`4EgtaCh4w)@{uir$u@>m^XQ z%BL!a>oDf^qDD_wrAWxNo7IOZ(EUR&P_=w+Iu*Q^ln(p92q)>^4(m4R9IpjdHFV@B z?2Tzp_p)B$e!skk+Tj~|7$1rqTUaLWm56$em=Dk=FY5n1X@~j;s(px3s2GW|sQvUu zU`OdV)?xii)BccYvjg2cr84nGPW)u#^+j12h?^ho{e2!jpxz@yvd6sAP|}N$7Lb|H zQ5t7INM_(3`3YM?eHa!Q?0*CG1KKZ4FYHy6Q9C72WXJq*tW%QhubzJzBxv(|GEsm&rna~CmeoM-unB|ak5=) zw_ngrH`eZDIk)MCbGdDZi!B@S<#4*IKzDB*0vERXZ%;g*^B|PSgp1YgqAHYJx(@$1 zYC)TPlUDiJ z#QN`iRpqz7t6t%EspF~g43?f|KfkH7jcxn@>N6UVTIK9nJNft(a|x*O7cp4Ql7c z=9OtqWKo5^9xWa5ASdVP#zU&pAw^2hIXxI$Tpw?1tZxr~9Dz%yoZ62ExlaUs+m$D5 zC5hLA;;dj*OT4BjIH{>_YOoDnucXYYYdW>fFi6J}VGIk@7Sswa-VkrCj(46JT-kU9 zfy}r4wx}g!9h|dfTr^lA( zCa7dJv`RsBQZQbZLe-GN*VudoPdC;&Yj6BaeGu;*^@3_;0C2vVgOZ zGp?jK?aWE-XP%ZpRHc}59>tbc+nK?oL)l9!!8fU0E3XZS;wY`OrMa2PAKnS7|A#ami}?W>Srk{f(0TjIf%R>t<@lP9%L(OOm3V<22`@}#;c`q>0a zI>C&D;L_Gkt+chQR$0dQ35wribfhxSf#)$wVx67;X@5~iYm?{mg=zb5+BaJSR%{E= zEap!nzu@{ToOz$f#u~S*1^I=g`2~^uyaG6(`JjyYAi}mB|H~BO^PPak7}vAiNWXGk zepX%j@cVgVv)1ATyyoTSoijG;inPmuv01h0mxW`qkHG>uq2nSv?jL$U!g!sZ)gk%L zfqZ*4F$4sk*YPr6NgEl0;ksrJ$!F@F)BL`8k&p+jp+@` z3&t*UkjU5wkogu(Ddd_9ws~mV(|mzHLpnJ(KX?t|pwoK6*mKhM^0Ai~SgoCkiT|7E zABOqo62Ul5PM(RZPal(?S3b5Bzhz_Rt6kGf$1b5;L^|Y^6!&M}$b2SiGb{6pFU_Bf zcjO_sBdhqTK>C3AJ0?f_lQo@KGkGJ|bY9PW-HA~Pcss-LW7L{RTRY`rvupkN>-_Wb z*ZZ%+GXgrjzi>R$80Kdj{2FO3CiE@)#TVwU&&vAIh}*^IkIkNtoxdS#VgAOf3-FA9 zRF~1X@c%pmamvP}=^PUsyC`jsjg6bk4=;1@Z|?fNkUWOcYhiwHvG#>L92`|5T zng8C-Fl+rI*MOpW@@4rXBg3xh6g&$BUydh@sY7UgH~ZQrfu8)=(j$zjcktxe65<<0 z=c=v%cDBLUb%Igl5l^1qKzegGvMTSuE*89C3@k8)p8Ib|zg%!tMuA-|_yK8{sd5GE zi-ND0^f2Y+hk^&W01rl$89X_ptoRGA$_TJW1iwRYRR)03jI^fq_rS@gr$CYDybbF? z!PlRtag`@wJuG;T2?V3^nYMzzL{{F-BU`QBG;c%CY_&>o=$*DPDl6os&)74r`GOZ4 zK%U1dd=$bSZVCk-j{1C@*wQ;$hr66C_@?2oPu~MED!q2qI8PP+(+nWbkl^X>ui&$V zKfBGgnJc*Jt5^;Z!F4=_92O{iRQl`^TrW7M zgluz};8)rp?3W9^&cW9RZt}fxzDDpb89<&1!N2O@p5X49wwne2jzj+?g(F|7=aA!9 zgV1^YoSA9(_Y3`G`PLfzWufOnIoteI=uz1W zGj9scb9Y=b(zzgh&`DJ_jQqq5_{kaY(=y<^gL@?YB^mH&27GA-yfy=Vc?P^Y1OCkn zIPXj!Nq(+H9|_-@0q4n@Bhf#d0q4}fNc0CX;D<8c`KZW8;xjP=&b8qq(MK}iOETb> zWWZ}P;Fo5=Ka&B!B?JE54EQ}6@P{+tf6Rctk^%RlZG2qT(D!<+DNP)pIlWd7HPkh> z*Xp4K{f=W)xbee`L+B?@jW;7x8WBI$7(p3Wp0=BVrP+0~Rtp*W_~M}qMxqlXQ~c!wkiLW+=mMA+;f>wxO+Ft_t9NU=0|QY_5y9s4*YC<%oBHHDuUMgkyBn zkf5eyj%liIz&I6e9%yK6YHF*msaw&}&`>WokF~CBYhO|yU)tK#Qd3vj(!l{TO}Enh_|pzNk|*AR0YBrHlu_mwkTlgd`&QSlu5G>2;$lKvg0V$? zcu+mAEUm_HFHZVt6=?N4+<-Q0dlbgruHa}BgXBR%404qvU$b>)kVHD#vZk5QRzfHZ zp_HLmsKL5n8d}<_4mQ&1)6|Hu*6KBFjX3H^Ar3pE#ae6cm*(DDUtgy;bE$U>mDXV> zw3?NHt{6=J>r}kP@Q)cEWqvI62CDO6=h*yAaCX7V@o(sLdsOeUSZLw89jWniEPRW! zBglV(h5uY|m;cii{f8|2XD$507XE_8r^3Q7V1O{>Z_9a02K;*#&c2w5?_Cytu7%$( zI3Kn=J1u%!o_VOpXdRdww>d4Lg+L8UcT zt)mS#C}P4x6Nx$liJZX!qCiUv8e#|r4M`+35EOOnOqA)6mV0X}_tsW=)t0tiueVx? z@9>ad>uo7oORKH;XiJP%ZdJr5-~Ye&+A}+wjD_Cz`+C1$_b-!k&i|~v_S$Pd&pv0b z^`91Q^D*|Fm@fC%7(Q1JKp_7Beg=;U&V$YWIt#b?FPGc(w+KWCOHyu~MM(O)U} z>A<))W%x7d3A`QOD!fpNh#KLX;JR>;eFSYpWw&?Br?ziYiTl60r ziVFnFIR`%@&uJF^84JHsaHebXX|?EWKBI?$5P|%;7G(HeW8qx$H~3l$=YBYY?-iWs zo^Ii9Tew|bc}IZ=f$7@iHAQgpIRih#f0~8c^=-DrCt}fGY0;0d@T)ESObhR{@R1fi zV>m7lDCg(#Gx9WBIM)yjzE*I`Ki0zUw&>?u`27}c>-n)9_#Xu)f397bbU(1@ZT?65 zL4-j1GW-nvR0}V+@Xra({Mvk$SoGs8`gIm=^Z7vzKHDt%@fM$t%R?a3oo3+y3!iS` zXIS_Q3m+#q^J~|W3oLrOo?Iw6>#S$-X|VY4U53%yk{oM=k<*cyy{KBHQ)BTNw+k9TO_>8moyl&B7Zs7+k+~zZwjUR#X zl;LOcb+q8rgUzSZ!WUTd6D&TJ7Cy8!Y;-T6`v1_+1vgUC)1J z;R`ML7cAUvUw^c4yM4VSIQ3(WzoxyhtF3mK9KP|Y3nZdgSKhfbo zOy&~;;|-&>S76?Q8aaupe98RP$YXHx{?VjsaPvO2R1z?_dEZ**;N8Nw!okgZ%%FoW zkZUgoZtk0Oh0GU_6H_h*H+&4fKyGl3#9;8ay7KwD#z@Ly>FKp5#)kb+GRU z8bFS_&(bFyGQVa#reoTvVasQ4;-Y?>>F^^%U;sIi)(&HEL7snUd_E(PC+BE(*eL0L zPwJPsXXH0>1aV`a_?L4L2*G_{YT}vWY|!xBNyhi4bbtZevxDiU4K@=e1L=P*2V;b8 z^A197}Iz47vN$iLR|gN{tIMJ)fxMnfzmGyYQnwxpx&t+iE}soC@`j9 zCUoYoPSWRdkR3?NV2;;W=jw+1`?18gF`k=v2LETlT>bBm_6gYPzd$ozNZ=d~+4iMvnHQHo?7WI9vvbJJ&;43z$M zE_NUs%gkB9O&>OX##IEep)7kE(C7NUvGFsm@|?3Z$)Vf$S!aZX96=?EwkwNo_p!G% zU8pvmaf20%aBy3B@~0pQr*>OrGqI};0XuG|!wQPoqvut26yI>s%3)q*Ti}K%{;nrU zlJ<%`SlUQF#*4}o#Wx)9U;Pzzes#dVI)$@L{BSB%6i#iz4nx?J>?pqehhBOF(ub*` z%4-mB_G6an;yJzFR`KsjPjx*;Zd^p3cN-!duP%k z`o53U0r%ap2a;o}LeScijeJJ0g23F#{HEHw@1=ec4Jk^q>#E{Nsv*FA%so?BvwicB1-)aV8uxobs>Hk=Ra^RgX5>ljPi})!Y7<`n@oC(-<#(QPCUzRu~&d zjqo2G#KA*(pID-|lx*=*h6n2j>e3`^YD?c24S%iY@@IQvD11v_ z=_y5hJFRPMq(^!0i!SmK*TcSUD|eRu!b@Qv%)8tN<6-BdmtH3O`BIxVvSaZopNgTp zxUW{_;7Tn$vSH=GOVwcOsqCD|w2zG}err!YQVkr4ebGw~rYfd-=@}?P4~%g{RYY~j z^Lo@ogxhM*-NO8zfK9p(s$GN<4fK79H5pPB^(EC8s#^}{dvx z9$uUO9zG(*hu{^s2NH!h6|Bxz z>kk~~820gB_S<88C~Vn>5?@EreLlKEzSI=)GV zQ20<6-{nr*vMoOdDGF}NUqq2eI#6I%|CZn6GR?n+T~>}&wp~_LM!;B}su#l14xBp- zgmZn0e1fWblJW!=5xh(WR8>~MxbA7&M^!op=4)?ju3v$VTjZTLE^>VCFtDc{6@4)_ zsVtSx78HPwVlKy)AdBhJ#wD%G8ZTdg4^fsf*|8#bAV6uIMOfD8sM0Si$JeK+|wC zkp6dz{uc-#+aMtm-{?Qr++I(3;L}s$n}al8b2*^wyxAseG_?|8C@`k&rk`tW->t@2 z*xMm9E4b-nZa?90=Jw?i$I0~n(C7C2p3{V&I?;1`ZS;aulehKMMCJJaCJLAuY>Hyy z`)e50@lri|7zvP`KyAm)-NTs*vFV70QU76#4#-D8C*7nM2ub9J3-tT6lK$|NFn$hztF6}iTW zYbBn0aQli}W5uDy&ox$<_@=y#9438p%r#crWg<976VJf8#)|bq5Hy5xH2O2}G@J}H zR&+=uG-Cqwe>h{s8j1gxjuonVM4AD~@ZpXXMUs9HJnZ1=4`apIl?Sc;Xkegqpz`tK z%g3qPhdx%sO(ljPK_yHO_VxI!L6XD3S*UG{^UCSIP8Ww_$$0h9|TMx)0~f!tw>o3Q87WC~7UT5>8`@=5cFv zELpM&Fb&E?N`}>>A6~Tsmo&RU^&rdsRWaV*S8Xg38Cx#ZsTW{<$56)McE}fch%SU+ z(HVA!Z!3v|!Kyn;zJNnDjtLy2(dnK0wjoKJ!xZBrP{VADPU^f5fWh35|0eEF%~-8@ zUM#hQ9%S=SHZ?q&_CQoBQ(kP9dV-qurA-WEiU;=?Xa4iCz}zT38Z%Fo?Ubf~JM+qTwu~0ooGjnwB5wnl?Dn zHCdZeq0^%zH#2230Apju+6-3fV7gIstJ!EBW-`esSnmlaZ?5xb3Pi}<=F~$>mj+?^ z>dull06PESoDK$#dXgncoFQoQbCCvk(}{GoBE}lw?_~MM zA1;YAtNzZ-$dG?SvgAfwRn7A!e}KFGo4EhGYQ8_YmB&kAjTZIFzhQMrC*y3mMQKWO zeC4J7A0z?V5Vn)`ouQXdpB6JC&{v{%@dxm28Nnp^TcJS zD|jT~-ZYHW4OCD2zOCBnMO{_HBB?*AW`}Ah`K5a&Hb_F6hn8lQryGV7RCpZ9legaTC)5L1_~xv=L|J@))HJERRO z8%(A%Rh7ASj52~1Jh;90&ZB9mjIGpMb$9;Z=%+3;x3>^%QEoZ-)gBJJxu5Udfbvsi z%kgJ=L$@A(emQ4WB=r-FI^1bclm6~HROcz_yKmIP3+;2IVD}B)@cNBKTv{&gMpYg; zJ$;I1n)qN4EMNM+y4gGL0F>>&wL7qR)yNWm=TYDo!d)63ltB(XvaV&F-7wSUUo`|I zO5tMW>rsxRkyLN$6&ZDuQNfW&lm@`KM`JyF*1d^j*x3~M9^fqKURXK{)Wvw@L{8W!^Ny-A3n zZ4pbWgy=AlrHn1=ETmVLP#c-4L3L`czwMm}W5d}>yV+Q&~Ro4CQ ztCTpDsFeC{G4Bh~lY~V-NqVnV!%?uGCe=KMnta_h&o~Vlq$at`otk_XX_W87n+h1E z^dwtwi#I*B=KLJI>grMDy)bK7$jECzoP(W_wb zc09)JsssMc<1xq9hRZO39~rN}n6QqJ(MW&Y_TJ8Rh53}pZ|KpCHhN*>Rcz^H@Aub7 zy;5l~C-;!KpW)B=708mxYwsxs-M7;(__OK1pgPQ;FJ4vRdvp*qf*N``JbOe-7QoUW zwTR(7P`xTzvJlr&;fQ0nlo690xL zC$FlWP(OK9WWoYW45W}ksckWTBt5KzvjEiJBofc1<4KS**S(W*599bquPahA7qXc- z5n5Ja_Xp7mj*4^nM(PvtQs|gOMml8#iV9Znn0El)d2IZuHWoHu#grBmb;d z#h7s(#dEVb1S^4f&xWB$<&Ih?!)seM_q^$y-PLU4(bJXvO3G6d;Tuym;;+bmfcv&2 zTBM{x#l3JHYZP*lN~%!6SQCAOeSd0;8f|)OKffHeGqmC_49(M zDNZl&FCbv=qT7%9DggBh4GA?sIr->az?KUAEKGF6!uF6z!+!slZlXd_c?03Z>qDS( zJo_n)dx_0MOyLcURH7gACqGZx9I2mx)N|cC0P~2MGDRskW%?ix(^KAq^Gx^niYlYo z7%5}*TID)=uBX; z81*~LX)@|X*?Z;PlUI!_S9%C1J}ipuR885m+1?Z@YmUT+AaPxKIS6`Tj*<29N|Z`f zVf1KwWbb_vH$#tcd9wF1mfDXZB~6)>bQhtuuxQgJ%jKaE}As~_TR)>T;K|9H-{NN7=2W?CY~E; zX$@reqz9TBmo{c@S-7!&r(+>f6n5^e2t-@KxqhLhZ*%`1>vduuZ+T*7XhgbT4t z8y4`CRO(*f)KTrHDm#JwS&h{ZX1BHmnp=?%bvMwqw6$YJprw9EBKBy4$=UOOHu?8YH4E|veQ)G9$3DV(kyFS+73;OF(T(|CHWL39Msm<+z4Bl{qtsYxNz(!`GYdYD(iu?H>u1#;z+xb&=pK5E>c<} zn?FjZL>Mv*2 zrAf=C*7hhXVSAu;Q2<-{uZT7U&JT>6I59AS&eZ3FNVRcG$=@Z$=BzOiDm58q zJ@MxxV#Un1n{4}<2rH$RpV`s~qnL|z#~^igK)FQpgQHlfAU{w%ti7^3l^f9B= zC0x=NZE9VpWTM+| z_D!&>x}@=}w)*z=<*iF$CAWQXOG6_hfdx|LlH#C6sSc5hq}r**hSak4V(e&LGY(bW zY&}}o+7Md;MIaFolcrSz^-0p*AtD55@XYd-2GeY z|5<{sad7?47xFs^)Cs-W%Vbh$6x{x%hR{`ldu%jTxLTbL_U-1gpB0v?^Fh8#EsUqv z39j>0teNR2{SbexpuNKOOp)1YhOI(<`|8;2_J!_qyQS4n5(4Y`VS$-2O)BMHL_4kf6Sf zkaPR+$s9QM6b?jxehz#_4xBbcDbHR>G%op|&8LC*Uy}px%z>}Yf!~?~zat0EPYMQ- z=f^p4+RPk?{*O6u+PWNwJ|F!B_0uNxS&fa<70rmX<5Mh{ms951v`sf&Dw}QE&|B8N zoHFyKEzl|ZZrTi;y05Ihm1{s-q*ENUojI{Zr!C288f}YCr8iDnty8hY7M->sr#Wcr zahgU6q^;12g*k1nPSKCE?bT^++K!$6uT!tkpPea>7+eym!xF|veSOy7j9fpnYwGJX z#RFe`FK&TVI@tSbxT>z9>8d(D%j=ZXjCX=E^wv>_M*@|yz9ly9w4FG`jnNkAn|f76 zpSR)pQ9Ys1^dN4uBdx`drLwZF9Y*6?`bB{yIXV{6F_o#dIwPO{gpLB5ujy2(dQy(+ zaFMhhb|(|@!)m$;ms|MR7Ouwy{hbrXN<;r!i=J;k49<4V;PSuN!uj2np`R-_s;{#A zZ15(Fev(E1T??x9Epic$Y;-%i?pCh2LY*+xem`Rt6r1<7e{qUpeRxSh%fE+CF8V zekS8*_!#^0#BKU7<)GgpIFlJ~@%c0vAQ1QCXZX(%oCiB!O%}baPcx44wyn>9xA@rl z+-Bjn{O?)#6ic3CWn8D6?01cvCkf7IwwyC9+~#wY#ph^?Pt2mX`Iz|x`Bz)?#ugpr z;din|p8w9lr%lF5(sNF3=$BhKpCt``y@h|w!v9Hd%46&Kn-*@j>-#J|T(~#_Yf*j9y`A$Te#hS zF0gQ${)-kq*^>Xef-_&oTe$jw3fHb4-mvIDVbL2i`fhn0s~_YJ>K{HOxXb@+i~a^87c6>P&JQelyZ+a45`aKH zpT^ImyH9ZD%jPqblK=$Lm*QvWPY~RtZ@1{}bW;{S+T!ysIr!XV(VuS7|1byr&nE!-ZD9bI{d%2+cSXdFiSFR(V4^lpqyPP zdNVhi%bYfJI@qZqc+&oPU^+6)|Ji+>-*XcpGXzn;zQBLB4e~6=Ao}D`1XF&7wh1R}gFyqxv73z^!P5uj^@vj;6Q6Tk2CB&| zJK{y65cAwljKL8{UAwZAZWkw!2y3Kbb68=2?50nd21>u_6x=`?6t3?PG$#82(%z!{k9#9%>semV}%x`k=g?RX)D#oWp42uQy56T~h5FzBBys2V) z?0hfLlZRLyzJ^pWqemyZW81r?-Co`uf9Lq+BNDF!y4r3>++h5}PcY67|1I7A4c$ns z8k-m5`;SMoWxwkCwYv6i@F$;$P3uiULS@H>)`)J#MRivgg3QG)1W9Tk$vdB@_D|Uq zioZuuHdj}4bK@Xo@q39^@+eR8iRcBCsXMk2I}bOqIHKp05qL1ZfAV(RrgXI;-R6qz z8R_C6_mw|kV#c0+V+-~xl8J4%2Rjl4aJrixdj@&5QR{D}Encf{DGcJN@NEm@_|8zN z4>|uc+yC$SaJOgFVh+@|55X<_eVow=`&i=C7lY9Y`zGRR6zcOC-S8QKcu?AKMnCX! zgKhg}&;CI^ZwOdEW_W4)oI%tU<0D6<7?5Adk${op6}pB?!U?)r!8|f zHq|Y{M~aP-(*Nx6=f=DhqIZ*u$-lWi1t%nN$E*jOc!u7EbB%e28b8;VXX5{*W1jW_ zXr#^_UHPZs7BRcdka~|0Hu1s=X3R1W$HYSXf(DRdwnxK=V0kO*wgOxsOA*Sxw-n zjDAB|3e4__8TH9q$glM$JQbh^G=X^X*H*Qv<&C!y`eHO6HfK`lXqorV~3dFQ;Yq{ zc=pDlY_oQ}sR6m)`C8at{rdFI*P?~fQ`eQIFB%c*naVFFd^nC^w8T64q0~(5o?C#o zuA%gB|Bq&u3{QE5AYGKI&0mx%>b($m%3s4S7wli!V{HWFo;D?SBy|9SrCu+8Z4Ws5 z`kv0%woIQyAe_FT_`tEGI@Y4PXVDsMGvQ~JO0^L|FZF`8Q4_mBWIHRjhi~(DejFL_ z(lA%p`K&)V7Z*y^eV<%2J=It`J@vcHo>?zFuT&8|1t}8O7Usv0jcbd2(cdSo9pPWL zTjYO?dKcAh^(TLat8~F*)J_O{QPNWiLny^U*!knJC_QCZh@0SfKa7(Aj_O3USR$oF zNIOgt5Z<7T-T>Q+#jswO=RcbDFTlP3$GK!E-ZWTvs`y?-@%cMXK_M_Z$R2alITqK@ ze-)H)AhryY(M!Uqv$&0?2%9)Zilu_RvCCO*R-t8z><tg(m zHK9kbxdmn4cc*7ca%D+?MfryV$M$t=vV=P5c7@Cg>U{=FoaLN#`q)~+seNcLq15|m zeZL5${_C*{<}C3lQdgBn=|(poSiKYwvMAiczS<;b3ZcaN`O(rydKAvNr!I7WCP|;? zL799UVX~-NY$!drn%kt#011qP7O6-*Q&`Nt)Rch7y=JOYhDlNE51)eO4_laBxRaVv zy65ANKa&!-AVD$NB<0;1vC6x9=RlW^4Gk*hO(+I?5`%`Yi*>%TGj2?HSIFoxmL7{+f^6s3N(Ju0(%H+BqDXWCE)CZpxueZS3?QdV9R zOgQzv=^d@^2Yn+=Ty2R?ezXNr>Apq4$Dt(jFROr?omO6A|5eLQ&FIXitNdB5H)Tzf z^}$p2P1yZlTXG((wvsvQuNEfu7pYr|Qb?q0dVYHiH}qbIyVzm-Xvn`|WXbycRde#A zKS*s3VH4oU57Dt6{bAo7@+_dM5=y)LS!iCHFU2!Nn1*Y+t{dVd{;=Om&B=!i+;ns# zPNPTf_eQ@1LmPS9z0p72w5Nb(I(EI`-KBJv=|4hj)hC3H4BbqShSq)R3xb5K=Asqt0OS8T;o}BrX8s8P)gpYqK z5=YQ-=%4VVF}|*LzBHaPRPkD?IQe`(>CY?sU3NcS1)m-Gv*plGc7-nsFY_GGjO+b^ z9V7g|ls|cRaaRHOuP%f{Hw}VhiNQ062lHnPQ8L03DJbv-HS%0DG{5m+^rE4)0H+Ku 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

w>7VBN-LHvu!|8uCifk-+C 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

<3Z}35sM>}2X|wq+)i%U-lwl$ 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 N<0od0zgoUY`u_?Ma^nC1 literal 0 HcmV?d00001 diff --git a/src/kit/CMakeLists.txt b/src/kit/CMakeLists.txt index 66e8cf7398..bf52784300 100644 --- a/src/kit/CMakeLists.txt +++ b/src/kit/CMakeLists.txt @@ -3,4 +3,5 @@ PROJECT(TDengine) ADD_SUBDIRECTORY(shell) ADD_SUBDIRECTORY(taosdemo) +ADD_SUBDIRECTORY(taosdemox) ADD_SUBDIRECTORY(taosdump) diff --git a/src/kit/taosdemox/CMakeLists.txt b/src/kit/taosdemox/CMakeLists.txt new file mode 100644 index 0000000000..3f5e725aea --- /dev/null +++ b/src/kit/taosdemox/CMakeLists.txt @@ -0,0 +1,25 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/libcurl/include) + +IF (TD_LINUX) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(taosdemox ${SRC}) + + #find_program(HAVE_CURL NAMES curl) + IF ((NOT TD_ARM_64) AND (NOT TD_ARM_32)) + ADD_DEFINITIONS(-DTD_LOWA_CURL) + LINK_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/libcurl/lib) + ADD_LIBRARY(curl STATIC IMPORTED) + SET_PROPERTY(TARGET curl PROPERTY IMPORTED_LOCATION ${TD_COMMUNITY_DIR}/deps/libcurl/lib/libcurl.a) + TARGET_LINK_LIBRARIES(taosdemox curl) + ENDIF () + + IF (TD_SOMODE_STATIC) + TARGET_LINK_LIBRARIES(taosdemox taos_static cJson) + ELSE () + TARGET_LINK_LIBRARIES(taosdemox taos cJson) + ENDIF () +ENDIF () diff --git a/src/kit/taosdemox/insert.json b/src/kit/taosdemox/insert.json new file mode 100644 index 0000000000..88416c13a4 --- /dev/null +++ b/src/kit/taosdemox/insert.json @@ -0,0 +1,53 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 2, + "result_file": "./insert_res.txt", + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "no", + "replica": 1, + "days": 2, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb", + "child_table_exists":"no", + "childtable_count": 1, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rate": 0, + "insert_rows": 100000, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 1, + "rows_per_tbl": 100, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 10, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":10}, {"type": "BINARY", "len": 16, "count":3}, {"type": "BINARY", "len": 32, "count":6}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5}] + }] + }] +} diff --git a/src/kit/taosdemox/query.json b/src/kit/taosdemox/query.json new file mode 100644 index 0000000000..53d0b31921 --- /dev/null +++ b/src/kit/taosdemox/query.json @@ -0,0 +1,17 @@ +{ + "filetype":"query", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "databases": "db01", + "super_table_query": + {"rate":1, "concurrent":1, + "sqls": [{"sql": "select count(*) from stb01", "result": "./query_res0.txt"}] + }, + "sub_table_query": + {"stblname": "stb01", "rate":1, "threads":1, + "sqls": [{"sql": "select count(*) from xxxx", "result": "./query_res1.txt"}] + } +} diff --git a/src/kit/taosdemox/subscribe.json b/src/kit/taosdemox/subscribe.json new file mode 100644 index 0000000000..6dfacdd6ed --- /dev/null +++ b/src/kit/taosdemox/subscribe.json @@ -0,0 +1,17 @@ +{ + "filetype":"subscribe", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "databases": "db01", + "super_table_query": + {"concurrent":1, "mode":"sync", "interval":5000, "restart":"yes", "keepProgress":"yes", + "sqls": [{"sql": "select avg(c1) from stb01 where col1 > 1;", "result": "./subscribe_res0.txt"}] + }, + "sub_table_query": + {"stblname": "stb01", "threads":1, "mode":"sync", "interval":10000, "restart":"yes", "keepProgress":"yes", + "sqls": [{"sql": "select col1 from xxxx where col1 > 10;", "result": "./subscribe_res1.txt"}] + } +} diff --git a/src/kit/taosdemox/taosdemox.c b/src/kit/taosdemox/taosdemox.c new file mode 100644 index 0000000000..8cf6330cf4 --- /dev/null +++ b/src/kit/taosdemox/taosdemox.c @@ -0,0 +1,4621 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +/* + when in some thread query return error, thread don't exit, but return, otherwise coredump in other thread. +*/ + +#define _GNU_SOURCE +#define CURL_STATICLIB + +#ifdef TD_LOWA_CURL +#include "curl/curl.h" +#endif + +#ifdef LINUX + #include "os.h" + #include "cJSON.h" + #include + #include + #include + #ifndef _ALPINE + #include + #endif + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include "os.h" + + #pragma comment ( lib, "libcurl.lib" ) + #pragma comment ( lib, "ws2_32.lib" ) + #pragma comment ( lib, "winmm.lib" ) + #pragma comment ( lib, "wldap32.lib" ) +#endif + +#include "taos.h" +#include "tutil.h" + +extern char configDir[]; + +#define INSERT_JSON_NAME "insert.json" +#define QUERY_JSON_NAME "query.json" +#define SUBSCRIBE_JSON_NAME "subscribe.json" + +#define INSERT_MODE 0 +#define QUERY_MODE 1 +#define SUBSCRIBE_MODE 2 + +#define MAX_SQL_SIZE 65536 +#define BUFFER_SIZE (65536*2) +#define MAX_DB_NAME_SIZE 64 +#define MAX_TB_NAME_SIZE 64 +#define MAX_DATA_SIZE 16000 +#define MAX_NUM_DATATYPE 10 +#define OPT_ABORT 1 /* –abort */ +#define STRING_LEN 60000 +#define MAX_PREPARED_RAND 1000000 +//#define MAX_SQL_SIZE 65536 +#define MAX_FILE_NAME_LEN 256 + +#define MAX_SAMPLES_ONCE_FROM_FILE 10000 +#define MAX_NUM_DATATYPE 10 + +#define MAX_DB_COUNT 8 +#define MAX_SUPER_TABLE_COUNT 8 +#define MAX_COLUMN_COUNT 1024 +#define MAX_TAG_COUNT 128 + +#define MAX_QUERY_SQL_COUNT 10 +#define MAX_QUERY_SQL_LENGTH 256 + + +#define MAX_LINE_COUNT_IN_MEM 10000 + +typedef enum CREATE_SUB_TALBE_MOD_EN { + PRE_CREATE_SUBTBL, + AUTO_CREATE_SUBTBL, + NO_CREATE_SUBTBL +} CREATE_SUB_TALBE_MOD_EN; + +typedef enum TALBE_EXISTS_EN { + TBL_ALREADY_EXISTS, + TBL_NO_EXISTS, + TBL_EXISTS_BUTT +} TALBE_EXISTS_EN; + +enum MODE { + SYNC, + ASYNC, + MODE_BUT +}; + +enum QUERY_TYPE { + NO_INSERT_TYPE, + INSERT_TYPE, + QUERY_TYPE_BUT +} ; + +enum _describe_table_index { + TSDB_DESCRIBE_METRIC_FIELD_INDEX, + TSDB_DESCRIBE_METRIC_TYPE_INDEX, + TSDB_DESCRIBE_METRIC_LENGTH_INDEX, + TSDB_DESCRIBE_METRIC_NOTE_INDEX, + TSDB_MAX_DESCRIBE_METRIC +}; + +typedef struct { + char field[TSDB_COL_NAME_LEN + 1]; + char type[16]; + int length; + char note[128]; +} SColDes; + +/* Used by main to communicate with parse_opt. */ +typedef struct SArguments_S { + char * metaFile; + char * host; + uint16_t port; + char * user; + char * password; + char * database; + int replica; + char * tb_prefix; + char * sqlFile; + bool use_metric; + bool insert_only; + char * output_file; + int mode; + char * datatype[MAX_NUM_DATATYPE + 1]; + int len_of_binary; + int num_of_CPR; + int num_of_threads; + int num_of_RPR; + int num_of_tables; + int num_of_DPT; + int abort; + int disorderRatio; + int disorderRange; + int method_of_delete; + char ** arg_list; +} SArguments; + +typedef struct SColumn_S { + char field[TSDB_COL_NAME_LEN + 1]; + char dataType[MAX_TB_NAME_SIZE]; + int dataLen; + char note[128]; +} StrColumn; + +typedef struct SSuperTable_S { + char sTblName[MAX_TB_NAME_SIZE]; + int childTblCount; + bool superTblExists; // 0: no, 1: yes + bool childTblExists; // 0: no, 1: yes + int8_t autoCreateTable; // 0: create sub table, 1: auto create sub table + char childTblPrefix[MAX_TB_NAME_SIZE]; + char dataSource[MAX_TB_NAME_SIZE]; // rand_gen or sample + char insertMode[MAX_TB_NAME_SIZE]; // taosc, restful + int insertRate; // 0: unlimit > 0 rows/s + + int multiThreadWriteOneTbl; // 0: no, 1: yes + int numberOfTblInOneSql; // 0/1: one table, > 1: number of tbl + int rowsPerTbl; // + int disorderRatio; // 0: no disorder, >0: x% + int disorderRange; // ms or us by database precision + int maxSqlLen; // + + int64_t insertRows; // 0: no limit + int timeStampStep; + char startTimestamp[MAX_TB_NAME_SIZE]; // + char sampleFormat[MAX_TB_NAME_SIZE]; // csv, json + char sampleFile[MAX_FILE_NAME_LEN]; + char tagsFile[MAX_FILE_NAME_LEN]; + + int columnCount; + StrColumn columns[MAX_COLUMN_COUNT]; + int tagCount; + StrColumn tags[MAX_TAG_COUNT]; + + char* childTblName; + char* colsOfCreatChildTable; + int lenOfOneRow; + int lenOfTagOfOneRow; + + char* sampleDataBuf; + int sampleDataBufSize; + //int sampleRowCount; + //int sampleUsePos; + + int tagSource; // 0: rand, 1: tag sample + char* tagDataBuf; + int tagSampleCount; + int tagUsePos; + + // statistics + int64_t totalRowsInserted; + int64_t totalAffectedRows; +} SSuperTable; + +typedef struct SDbCfg_S { +// int maxtablesPerVnode; + int minRows; + int maxRows; + int comp; + int walLevel; + int fsync; + int replica; + int update; + int keep; + int days; + int cache; + int blocks; + int quorum; + char precision[MAX_TB_NAME_SIZE]; +} SDbCfg; + +typedef struct SDataBase_S { + char dbName[MAX_DB_NAME_SIZE]; + int drop; // 0: use exists, 1: if exists, drop then new create + SDbCfg dbCfg; + int superTblCount; + SSuperTable superTbls[MAX_SUPER_TABLE_COUNT]; +} SDataBase; + +typedef struct SDbs_S { + char cfgDir[MAX_FILE_NAME_LEN]; + char host[MAX_DB_NAME_SIZE]; + uint16_t port; + char user[MAX_DB_NAME_SIZE]; + char password[MAX_DB_NAME_SIZE]; + char resultFile[MAX_FILE_NAME_LEN]; + bool use_metric; + bool insert_only; + bool do_aggreFunc; + bool queryMode; + + int threadCount; + int dbCount; + SDataBase db[MAX_DB_COUNT]; + + // statistics + int64_t totalRowsInserted; + int64_t totalAffectedRows; +} SDbs; + +typedef struct SuperQueryInfo_S { + int rate; // 0: unlimit > 0 loop/s + int concurrent; + int sqlCount; + int subscribeMode; // 0: sync, 1: async + int subscribeInterval; // ms + int subscribeRestart; + int subscribeKeepProgress; + char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH]; + char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN]; + TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT]; +} SuperQueryInfo; + +typedef struct SubQueryInfo_S { + char sTblName[MAX_TB_NAME_SIZE]; + int rate; // 0: unlimit > 0 loop/s + int threadCnt; + int subscribeMode; // 0: sync, 1: async + int subscribeInterval; // ms + int subscribeRestart; + int subscribeKeepProgress; + int childTblCount; + char childTblPrefix[MAX_TB_NAME_SIZE]; + int sqlCount; + char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH]; + char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN]; + TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT]; + + char* childTblName; +} SubQueryInfo; + +typedef struct SQueryMetaInfo_S { + char cfgDir[MAX_FILE_NAME_LEN]; + char host[MAX_DB_NAME_SIZE]; + uint16_t port; + char user[MAX_DB_NAME_SIZE]; + char password[MAX_DB_NAME_SIZE]; + char dbName[MAX_DB_NAME_SIZE]; + char queryMode[MAX_TB_NAME_SIZE]; // taosc, restful + + SuperQueryInfo superQueryInfo; + SubQueryInfo subQueryInfo; +} SQueryMetaInfo; + +typedef struct SThreadInfo_S { + TAOS *taos; + #ifdef TD_LOWA_CURL + CURL *curl_handle; + #endif + int threadID; + char db_name[MAX_DB_NAME_SIZE]; + char fp[4096]; + char tb_prefix[MAX_TB_NAME_SIZE]; + int start_table_id; + int end_table_id; + int data_of_rate; + int64_t start_time; + char* cols; + bool use_metric; + SSuperTable* superTblInfo; + + // for async insert + tsem_t lock_sem; + int64_t counter; + int64_t st; + int64_t et; + int64_t lastTs; + int nrecords_per_request; + + // statistics + int64_t totalRowsInserted; + int64_t totalAffectedRows; +} threadInfo; + +typedef struct curlMemInfo_S { + char *buf; + size_t sizeleft; + } curlMemInfo; + + + +#ifdef LINUX + /* The options we understand. */ + static struct argp_option options[] = { + {0, 'f', "meta file", 0, "The meta data to the execution procedure, if use -f, all others options invalid. Default is NULL.", 0}, + #ifdef _TD_POWER_ + {0, 'c', "config_directory", 0, "Configuration directory. Default is '/etc/power/'.", 1}, + {0, 'P', "password", 0, "The password to use when connecting to the server. Default is 'powerdb'.", 2}, + #else + {0, 'c', "config_directory", 0, "Configuration directory. Default is '/etc/taos/'.", 1}, + {0, 'P', "password", 0, "The password to use when connecting to the server. Default is 'taosdata'.", 2}, + #endif + {0, 'h', "host", 0, "The host to connect to TDengine. Default is localhost.", 2}, + {0, 'p', "port", 0, "The TCP/IP port number to use for the connection. Default is 0.", 2}, + {0, 'u', "user", 0, "The TDengine user name to use when connecting to the server. Default is 'root'.", 2}, + {0, 'd', "database", 0, "Destination database. Default is 'test'.", 3}, + {0, 'a', "replica", 0, "Set the replica parameters of the database, Default 1, min: 1, max: 3.", 4}, + {0, 'm', "table_prefix", 0, "Table prefix name. Default is 't'.", 4}, + {0, 's', "sql file", 0, "The select sql file.", 6}, + {0, 'M', 0, 0, "Use metric flag.", 4}, + {0, 'o', "outputfile", 0, "Direct output to the named file. Default is './output.txt'.", 6}, + {0, 'q', "query_mode", 0, "Query mode--0: SYNC, 1: ASYNC. Default is SYNC.", 4}, + {0, 'b', "type_of_cols", 0, "The data_type of columns, default: TINYINT,SMALLINT,INT,BIGINT,FLOAT,DOUBLE,BINARY,NCHAR,BOOL,TIMESTAMP.", 4}, + {0, 'w', "length_of_chartype", 0, "The length of data_type 'BINARY' or 'NCHAR'. Default is 16", 4}, + {0, 'l', "num_of_cols_per_record", 0, "The number of columns per record. Default is 10.", 4}, + {0, 'T', "num_of_threads", 0, "The number of threads. Default is 10.", 4}, + // {0, 'r', "num_of_records_per_req", 0, "The number of records per request. Default is 100.", 4}, + {0, 't', "num_of_tables", 0, "The number of tables. Default is 10000.", 4}, + {0, 'n', "num_of_records_per_table", 0, "The number of records per table. Default is 10000.", 4}, + {0, 'x', 0, 0, "Not insert only flag.", 4}, + {0, 'O', "disorderRatio", 0, "Insert mode--0: In order, > 0: disorder ratio. Default is in order.", 4}, + {0, 'R', "disorderRang", 0, "Out of order data's range, ms, default is 1000.", 4}, + //{0, 'D', "delete database", 0, "if elete database if exists. 0: no, 1: yes, default is 1", 5}, + {0}}; + +/* Parse a single option. */ +static error_t parse_opt(int key, char *arg, struct argp_state *state) { + // Get the input argument from argp_parse, which we know is a pointer to our arguments structure. + SArguments *arguments = state->input; + wordexp_t full_path; + char **sptr; + switch (key) { + case 'f': + arguments->metaFile = arg; + break; + case 'h': + arguments->host = arg; + break; + case 'p': + arguments->port = atoi(arg); + break; + case 'u': + arguments->user = arg; + break; + case 'P': + arguments->password = arg; + break; + case 'o': + arguments->output_file = arg; + break; + case 's': + arguments->sqlFile = arg; + break; + case 'q': + arguments->mode = atoi(arg); + break; + case 'T': + arguments->num_of_threads = atoi(arg); + break; + //case 'r': + // arguments->num_of_RPR = atoi(arg); + // break; + case 't': + arguments->num_of_tables = atoi(arg); + break; + case 'n': + arguments->num_of_DPT = atoi(arg); + break; + case 'd': + arguments->database = arg; + break; + case 'l': + arguments->num_of_CPR = atoi(arg); + break; + case 'b': + sptr = arguments->datatype; + if (strstr(arg, ",") == NULL) { + if (strcasecmp(arg, "INT") != 0 && strcasecmp(arg, "FLOAT") != 0 && + strcasecmp(arg, "TINYINT") != 0 && strcasecmp(arg, "BOOL") != 0 && + strcasecmp(arg, "SMALLINT") != 0 && strcasecmp(arg, "TIMESTAMP") != 0 && + strcasecmp(arg, "BIGINT") != 0 && strcasecmp(arg, "DOUBLE") != 0 && + strcasecmp(arg, "BINARY") != 0 && strcasecmp(arg, "NCHAR") != 0) { + argp_error(state, "Invalid data_type!"); + } + sptr[0] = arg; + } else { + int index = 0; + char *dupstr = strdup(arg); + char *running = dupstr; + char *token = strsep(&running, ","); + while (token != NULL) { + if (strcasecmp(token, "INT") != 0 && strcasecmp(token, "FLOAT") != 0 && + strcasecmp(token, "TINYINT") != 0 && strcasecmp(token, "BOOL") != 0 && + strcasecmp(token, "SMALLINT") != 0 && strcasecmp(token, "TIMESTAMP") != 0 && + strcasecmp(token, "BIGINT") != 0 && strcasecmp(token, "DOUBLE") != 0 && + strcasecmp(token, "BINARY") != 0 && strcasecmp(token, "NCHAR") != 0) { + argp_error(state, "Invalid data_type!"); + } + sptr[index++] = token; + token = strsep(&running, ","); + if (index >= MAX_NUM_DATATYPE) break; + } + } + break; + case 'w': + arguments->len_of_binary = atoi(arg); + break; + case 'm': + arguments->tb_prefix = arg; + break; + case 'M': + arguments->use_metric = true; + break; + case 'x': + arguments->insert_only = false; + break; + case 'c': + if (wordexp(arg, &full_path, 0) != 0) { + fprintf(stderr, "Invalid path %s\n", arg); + return -1; + } + taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]); + wordfree(&full_path); + break; + case 'O': + arguments->disorderRatio = atoi(arg); + if (arguments->disorderRatio < 0 || arguments->disorderRatio > 100) + { + argp_error(state, "Invalid disorder ratio, should 1 ~ 100!"); + } + break; + case 'R': + arguments->disorderRange = atoi(arg); + break; + case 'a': + arguments->replica = atoi(arg); + if (arguments->replica > 3 || arguments->replica < 1) + { + arguments->replica = 1; + } + break; + //case 'D': + // arguments->method_of_delete = atoi(arg); + // break; + case OPT_ABORT: + arguments->abort = 1; + break; + case ARGP_KEY_ARG: + /*arguments->arg_list = &state->argv[state->next-1]; + state->next = state->argc;*/ + argp_usage(state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = {options, parse_opt, 0, 0}; + +void parse_args(int argc, char *argv[], SArguments *arguments) { + argp_parse(&argp, argc, argv, 0, 0, arguments); + if (arguments->abort) { + #ifndef _ALPINE + error(10, 0, "ABORTED"); + #else + abort(); + #endif + } +} + +#else + void printHelp() { + char indent[10] = " "; + printf("%s%s\n", indent, "-f"); + printf("%s%s%s\n", indent, indent, "The meta file to the execution procedure. Default is './meta.json'."); + printf("%s%s\n", indent, "-c"); + printf("%s%s%s\n", indent, indent, "config_directory, Configuration directory. Default is '/etc/taos/'."); + } + + void parse_args(int argc, char *argv[], SArguments *arguments) { + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-f") == 0) { + arguments->metaFile = argv[++i]; + } else if (strcmp(argv[i], "-c") == 0) { + strcpy(configDir, argv[++i]); + } else if (strcmp(argv[i], "--help") == 0) { + printHelp(); + exit(EXIT_FAILURE); + } else { + fprintf(stderr, "wrong options\n"); + printHelp(); + exit(EXIT_FAILURE); + } + } + } +#endif + +static bool getInfoFromJsonFile(char* file); +//static int generateOneRowDataForStb(SSuperTable* stbInfo); +//static int getDataIntoMemForStb(SSuperTable* stbInfo); +static void init_rand_data(); +static int createDatabases(); +static void createChildTables(); +static int queryDbExec(TAOS *taos, char *command, int type); + +/* ************ Global variables ************ */ + +int32_t randint[MAX_PREPARED_RAND]; +int64_t randbigint[MAX_PREPARED_RAND]; +float randfloat[MAX_PREPARED_RAND]; +double randdouble[MAX_PREPARED_RAND]; +char *aggreFunc[] = {"*", "count(*)", "avg(col0)", "sum(col0)", "max(col0)", "min(col0)", "first(col0)", "last(col0)"}; + +SArguments g_args = {NULL, + "127.0.0.1", // host + 6030, // port + "root", // user + #ifdef _TD_POWER_ + "powerdb", // password + #else + "taosdata", // password + #endif + "test", // database + 1, // replica + "t", // tb_prefix + NULL, // sqlFile + false, // use_metric + true, // insert_only + "./output.txt", // output_file + 0, // mode : sync or async + { + "TINYINT", // datatype + "SMALLINT", + "INT", + "BIGINT", + "FLOAT", + "DOUBLE", + "BINARY", + "NCHAR", + "BOOL", + "TIMESTAMP" + }, + 16, // len_of_binary + 10, // num_of_CPR + 10, // num_of_connections/thread + 100, // num_of_RPR + 10000, // num_of_tables + 10000, // num_of_DPT + 0, // abort + 0, // disorderRatio + 1000, // disorderRange + 1, // method_of_delete + NULL // arg_list +}; + + +static int g_jsonType = 0; +static SDbs g_Dbs; +static int g_totalChildTables = 0; +static SQueryMetaInfo g_queryInfo; +static FILE * g_fpOfInsertResult = NULL; + + +void tmfclose(FILE *fp) { + if (NULL != fp) { + fclose(fp); + } +} + +void tmfree(char *buf) { + if (NULL != buf) { + free(buf); + } +} + +static int queryDbExec(TAOS *taos, char *command, int type) { + int i; + TAOS_RES *res = NULL; + int32_t code = -1; + + for (i = 0; i < 5; i++) { + if (NULL != res) { + taos_free_result(res); + res = NULL; + } + + res = taos_query(taos, command); + code = taos_errno(res); + if (0 == code) { + break; + } + } + + if (code != 0) { + fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(res)); + taos_free_result(res); + //taos_close(taos); + return -1; + } + + if (INSERT_TYPE == type) { + int affectedRows = taos_affected_rows(res); + taos_free_result(res); + return affectedRows; + } + + taos_free_result(res); + return 0; +} + +static void getResult(TAOS_RES *res, char* resultFileName) { + TAOS_ROW row = NULL; + int num_rows = 0; + int num_fields = taos_field_count(res); + TAOS_FIELD *fields = taos_fetch_fields(res); + + FILE *fp = NULL; + if (resultFileName[0] != 0) { + fp = fopen(resultFileName, "at"); + if (fp == NULL) { + fprintf(stderr, "failed to open result file: %s, result will not save to file\n", resultFileName); + } + } + + char* databuf = (char*) calloc(1, 100*1024*1024); + if (databuf == NULL) { + fprintf(stderr, "failed to malloc, warning: save result to file slowly!\n"); + return ; + } + + int totalLen = 0; + char temp[16000]; + + // fetch the records row by row + while ((row = taos_fetch_row(res))) { + if (totalLen >= 100*1024*1024 - 32000) { + if (fp) fprintf(fp, "%s", databuf); + totalLen = 0; + memset(databuf, 0, 100*1024*1024); + } + num_rows++; + int len = taos_print_row(temp, row, fields, num_fields); + len += sprintf(temp + len, "\n"); + //printf("query result:%s\n", temp); + memcpy(databuf + totalLen, temp, len); + totalLen += len; + } + + if (fp) fprintf(fp, "%s", databuf); + tmfclose(fp); + free(databuf); +} + +static void selectAndGetResult(TAOS *taos, char *command, char* resultFileName) { + TAOS_RES *res = taos_query(taos, command); + if (res == NULL || taos_errno(res) != 0) { + printf("failed to sql:%s, reason:%s\n", command, taos_errstr(res)); + taos_free_result(res); + return; + } + + getResult(res, resultFileName); + taos_free_result(res); +} + +double getCurrentTime() { + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) { + perror("Failed to get current time in ms"); + return 0.0; + } + + return tv.tv_sec + tv.tv_usec / 1E6; +} + +static int32_t rand_bool(){ + static int cursor; + cursor++; + cursor = cursor % MAX_PREPARED_RAND; + return randint[cursor] % 2; +} + +static int32_t rand_tinyint(){ + static int cursor; + cursor++; + cursor = cursor % MAX_PREPARED_RAND; + return randint[cursor] % 128; +} + +static int32_t rand_smallint(){ + static int cursor; + cursor++; + cursor = cursor % MAX_PREPARED_RAND; + return randint[cursor] % 32767; +} + +static int32_t rand_int(){ + static int cursor; + cursor++; + cursor = cursor % MAX_PREPARED_RAND; + return randint[cursor]; +} + +static int64_t rand_bigint(){ + static int cursor; + cursor++; + cursor = cursor % MAX_PREPARED_RAND; + return randbigint[cursor]; + +} + +static float rand_float(){ + static int cursor; + cursor++; + cursor = cursor % MAX_PREPARED_RAND; + return randfloat[cursor]; +} + +static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; +void rand_string(char *str, int size) { + str[0] = 0; + if (size > 0) { + //--size; + int n; + for (n = 0; n < size; n++) { + int key = rand_tinyint() % (int)(sizeof(charset) - 1); + str[n] = charset[key]; + } + str[n] = 0; + } +} + +static double rand_double() { + static int cursor; + cursor++; + cursor = cursor % MAX_PREPARED_RAND; + return randdouble[cursor]; + +} + +static void init_rand_data() { + for (int i = 0; i < MAX_PREPARED_RAND; i++){ + randint[i] = (int)(rand() % 65535); + randbigint[i] = (int64_t)(rand() % 2147483648); + randfloat[i] = (float)(rand() / 1000.0); + randdouble[i] = (double)(rand() / 1000000.0); + } +} + +static void printfInsertMeta() { + printf("\033[1m\033[40;32m================ insert.json parse result START ================\033[0m\n"); + printf("host: \033[33m%s:%u\033[0m\n", g_Dbs.host, g_Dbs.port); + printf("user: \033[33m%s\033[0m\n", g_Dbs.user); + printf("password: \033[33m%s\033[0m\n", g_Dbs.password); + printf("resultFile: \033[33m%s\033[0m\n", g_Dbs.resultFile); + printf("thread count: \033[33m%d\033[0m\n", g_Dbs.threadCount); + + printf("database count: \033[33m%d\033[0m\n", g_Dbs.dbCount); + for (int i = 0; i < g_Dbs.dbCount; i++) { + printf("database[\033[33m%d\033[0m]:\n", i); + printf(" database name: \033[33m%s\033[0m\n", g_Dbs.db[i].dbName); + if (0 == g_Dbs.db[i].drop) { + printf(" drop: \033[33mno\033[0m\n"); + }else { + printf(" drop: \033[33myes\033[0m\n"); + } + + if (g_Dbs.db[i].dbCfg.blocks > 0) { + printf(" blocks: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.blocks); + } + if (g_Dbs.db[i].dbCfg.cache > 0) { + printf(" cache: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.cache); + } + if (g_Dbs.db[i].dbCfg.days > 0) { + printf(" days: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.days); + } + if (g_Dbs.db[i].dbCfg.keep > 0) { + printf(" keep: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.keep); + } + if (g_Dbs.db[i].dbCfg.replica > 0) { + printf(" replica: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.replica); + } + if (g_Dbs.db[i].dbCfg.update > 0) { + printf(" update: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.update); + } + if (g_Dbs.db[i].dbCfg.minRows > 0) { + printf(" minRows: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.minRows); + } + if (g_Dbs.db[i].dbCfg.maxRows > 0) { + printf(" maxRows: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.maxRows); + } + if (g_Dbs.db[i].dbCfg.comp > 0) { + printf(" comp: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.comp); + } + if (g_Dbs.db[i].dbCfg.walLevel > 0) { + printf(" walLevel: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.walLevel); + } + if (g_Dbs.db[i].dbCfg.fsync > 0) { + printf(" fsync: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.fsync); + } + if (g_Dbs.db[i].dbCfg.quorum > 0) { + printf(" quorum: \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.quorum); + } + if (g_Dbs.db[i].dbCfg.precision[0] != 0) { + if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2)) || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) { + printf(" precision: \033[33m%s\033[0m\n", g_Dbs.db[i].dbCfg.precision); + } else { + printf(" precision error: \033[33m%s\033[0m\n", g_Dbs.db[i].dbCfg.precision); + exit(EXIT_FAILURE); + } + } + + printf(" super table count: \033[33m%d\033[0m\n", g_Dbs.db[i].superTblCount); + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + printf(" super table[\033[33m%d\033[0m]:\n", j); + + printf(" stbName: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].sTblName); + + if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { + printf(" autoCreateTable: \033[33m%s\033[0m\n", "no"); + } else if (AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { + printf(" autoCreateTable: \033[33m%s\033[0m\n", "yes"); + } else { + printf(" autoCreateTable: \033[33m%s\033[0m\n", "error"); + } + + if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { + printf(" childTblExists: \033[33m%s\033[0m\n", "no"); + } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { + printf(" childTblExists: \033[33m%s\033[0m\n", "yes"); + } else { + printf(" childTblExists: \033[33m%s\033[0m\n", "error"); + } + + printf(" childTblCount: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].childTblCount); + printf(" childTblPrefix: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].childTblPrefix); + printf(" dataSource: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].dataSource); + printf(" insertMode: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].insertMode); + printf(" insertRate: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].insertRate); + printf(" insertRows: \033[33m%"PRId64"\033[0m\n", g_Dbs.db[i].superTbls[j].insertRows); + + if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) { + printf(" multiThreadWriteOneTbl: \033[33mno\033[0m\n"); + }else { + printf(" multiThreadWriteOneTbl: \033[33myes\033[0m\n"); + } + printf(" numberOfTblInOneSql: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].numberOfTblInOneSql); + printf(" rowsPerTbl: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].rowsPerTbl); + printf(" disorderRange: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].disorderRange); + printf(" disorderRatio: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].disorderRatio); + printf(" maxSqlLen: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].maxSqlLen); + + printf(" timeStampStep: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].timeStampStep); + printf(" startTimestamp: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].startTimestamp); + printf(" sampleFormat: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].sampleFormat); + printf(" sampleFile: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].sampleFile); + printf(" tagsFile: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].tagsFile); + + printf(" columnCount: \033[33m%d\033[0m\n ", g_Dbs.db[i].superTbls[j].columnCount); + for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) { + //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen); + if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType, "binary", 6)) || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType, "nchar", 5))) { + printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen); + } else { + printf("column[%d]:\033[33m%s\033[0m ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType); + } + } + printf("\n"); + + printf(" tagCount: \033[33m%d\033[0m\n ", g_Dbs.db[i].superTbls[j].tagCount); + for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) { + //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); + if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "binary", 6)) || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "nchar", 5))) { + printf("tag[%d]:\033[33m%s(%d)\033[0m ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); + } else { + printf("tag[%d]:\033[33m%s\033[0m ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType); + } + } + printf("\n"); + } + printf("\n"); + } + printf("\033[1m\033[40;32m================ insert.json parse result END================\033[0m\n"); +} + +static void printfInsertMetaToFile(FILE* fp) { + fprintf(fp, "================ insert.json parse result START================\n"); + fprintf(fp, "host: %s:%u\n", g_Dbs.host, g_Dbs.port); + fprintf(fp, "user: %s\n", g_Dbs.user); + fprintf(fp, "password: %s\n", g_Dbs.password); + fprintf(fp, "resultFile: %s\n", g_Dbs.resultFile); + fprintf(fp, "thread count: %d\n", g_Dbs.threadCount); + + fprintf(fp, "database count: %d\n", g_Dbs.dbCount); + for (int i = 0; i < g_Dbs.dbCount; i++) { + fprintf(fp, "database[%d]:\n", i); + fprintf(fp, " database name: %s\n", g_Dbs.db[i].dbName); + if (0 == g_Dbs.db[i].drop) { + fprintf(fp, " drop: no\n"); + }else { + fprintf(fp, " drop: yes\n"); + } + + if (g_Dbs.db[i].dbCfg.blocks > 0) { + fprintf(fp, " blocks: %d\n", g_Dbs.db[i].dbCfg.blocks); + } + if (g_Dbs.db[i].dbCfg.cache > 0) { + fprintf(fp, " cache: %d\n", g_Dbs.db[i].dbCfg.cache); + } + if (g_Dbs.db[i].dbCfg.days > 0) { + fprintf(fp, " days: %d\n", g_Dbs.db[i].dbCfg.days); + } + if (g_Dbs.db[i].dbCfg.keep > 0) { + fprintf(fp, " keep: %d\n", g_Dbs.db[i].dbCfg.keep); + } + if (g_Dbs.db[i].dbCfg.replica > 0) { + fprintf(fp, " replica: %d\n", g_Dbs.db[i].dbCfg.replica); + } + if (g_Dbs.db[i].dbCfg.update > 0) { + fprintf(fp, " update: %d\n", g_Dbs.db[i].dbCfg.update); + } + if (g_Dbs.db[i].dbCfg.minRows > 0) { + fprintf(fp, " minRows: %d\n", g_Dbs.db[i].dbCfg.minRows); + } + if (g_Dbs.db[i].dbCfg.maxRows > 0) { + fprintf(fp, " maxRows: %d\n", g_Dbs.db[i].dbCfg.maxRows); + } + if (g_Dbs.db[i].dbCfg.comp > 0) { + fprintf(fp, " comp: %d\n", g_Dbs.db[i].dbCfg.comp); + } + if (g_Dbs.db[i].dbCfg.walLevel > 0) { + fprintf(fp, " walLevel: %d\n", g_Dbs.db[i].dbCfg.walLevel); + } + if (g_Dbs.db[i].dbCfg.fsync > 0) { + fprintf(fp, " fsync: %d\n", g_Dbs.db[i].dbCfg.fsync); + } + if (g_Dbs.db[i].dbCfg.quorum > 0) { + fprintf(fp, " quorum: %d\n", g_Dbs.db[i].dbCfg.quorum); + } + if (g_Dbs.db[i].dbCfg.precision[0] != 0) { + if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2)) || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) { + fprintf(fp, " precision: %s\n", g_Dbs.db[i].dbCfg.precision); + } else { + fprintf(fp, " precision error: %s\n", g_Dbs.db[i].dbCfg.precision); + } + } + + fprintf(fp, " super table count: %d\n", g_Dbs.db[i].superTblCount); + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + fprintf(fp, " super table[%d]:\n", j); + + fprintf(fp, " stbName: %s\n", g_Dbs.db[i].superTbls[j].sTblName); + + if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { + fprintf(fp, " autoCreateTable: %s\n", "no"); + } else if (AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { + fprintf(fp, " autoCreateTable: %s\n", "yes"); + } else { + fprintf(fp, " autoCreateTable: %s\n", "error"); + } + + if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { + fprintf(fp, " childTblExists: %s\n", "no"); + } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { + fprintf(fp, " childTblExists: %s\n", "yes"); + } else { + fprintf(fp, " childTblExists: %s\n", "error"); + } + + fprintf(fp, " childTblCount: %d\n", g_Dbs.db[i].superTbls[j].childTblCount); + fprintf(fp, " childTblPrefix: %s\n", g_Dbs.db[i].superTbls[j].childTblPrefix); + fprintf(fp, " dataSource: %s\n", g_Dbs.db[i].superTbls[j].dataSource); + fprintf(fp, " insertMode: %s\n", g_Dbs.db[i].superTbls[j].insertMode); + fprintf(fp, " insertRate: %d\n", g_Dbs.db[i].superTbls[j].insertRate); + fprintf(fp, " insertRows: %"PRId64"\n", g_Dbs.db[i].superTbls[j].insertRows); + + if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) { + fprintf(fp, " multiThreadWriteOneTbl: no\n"); + }else { + fprintf(fp, " multiThreadWriteOneTbl: yes\n"); + } + fprintf(fp, " numberOfTblInOneSql: %d\n", g_Dbs.db[i].superTbls[j].numberOfTblInOneSql); + fprintf(fp, " rowsPerTbl: %d\n", g_Dbs.db[i].superTbls[j].rowsPerTbl); + fprintf(fp, " disorderRange: %d\n", g_Dbs.db[i].superTbls[j].disorderRange); + fprintf(fp, " disorderRatio: %d\n", g_Dbs.db[i].superTbls[j].disorderRatio); + fprintf(fp, " maxSqlLen: %d\n", g_Dbs.db[i].superTbls[j].maxSqlLen); + + fprintf(fp, " timeStampStep: %d\n", g_Dbs.db[i].superTbls[j].timeStampStep); + fprintf(fp, " startTimestamp: %s\n", g_Dbs.db[i].superTbls[j].startTimestamp); + fprintf(fp, " sampleFormat: %s\n", g_Dbs.db[i].superTbls[j].sampleFormat); + fprintf(fp, " sampleFile: %s\n", g_Dbs.db[i].superTbls[j].sampleFile); + fprintf(fp, " tagsFile: %s\n", g_Dbs.db[i].superTbls[j].tagsFile); + + fprintf(fp, " columnCount: %d\n ", g_Dbs.db[i].superTbls[j].columnCount); + for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) { + //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen); + if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType, "binary", 6)) || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType, "nchar", 5))) { + fprintf(fp, "column[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen); + } else { + fprintf(fp, "column[%d]:%s ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType); + } + } + fprintf(fp, "\n"); + + fprintf(fp, " tagCount: %d\n ", g_Dbs.db[i].superTbls[j].tagCount); + for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) { + //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); + if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "binary", 6)) || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "nchar", 5))) { + fprintf(fp, "tag[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); + } else { + fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType); + } + } + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + } + fprintf(fp, "================ insert.json parse result END ================\n\n"); +} + +static void printfQueryMeta() { + printf("\033[1m\033[40;32m================ query.json parse result ================\033[0m\n"); + printf("host: \033[33m%s:%u\033[0m\n", g_queryInfo.host, g_queryInfo.port); + printf("user: \033[33m%s\033[0m\n", g_queryInfo.user); + printf("password: \033[33m%s\033[0m\n", g_queryInfo.password); + printf("database name: \033[33m%s\033[0m\n", g_queryInfo.dbName); + + printf("\n"); + printf("super table query info: \n"); + printf("rate: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.rate); + printf("concurrent: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.concurrent); + printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.sqlCount); + + if (SUBSCRIBE_MODE == g_jsonType) { + printf("mod: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeMode); + printf("interval: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeInterval); + printf("restart: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeRestart); + printf("keepProgress: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeKeepProgress); + } + + + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + printf(" sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.superQueryInfo.sql[i]); + } + printf("\n"); + printf("sub table query info: \n"); + printf("rate: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.rate); + printf("threadCnt: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.threadCnt); + printf("childTblCount: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.childTblCount); + printf("childTblPrefix: \033[33m%s\033[0m\n", g_queryInfo.subQueryInfo.childTblPrefix); + + if (SUBSCRIBE_MODE == g_jsonType) { + printf("mod: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeMode); + printf("interval: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeInterval); + printf("restart: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeRestart); + printf("keepProgress: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeKeepProgress); + } + + printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.sqlCount); + for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { + printf(" sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.subQueryInfo.sql[i]); + } + printf("\n"); + printf("\033[1m\033[40;32m================ query.json parse result ================\033[0m\n"); +} + +#ifdef TD_LOWA_CURL +static size_t responseCallback(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + curlMemInfo* mem = (curlMemInfo*)userp; + + char *ptr = realloc(mem->buf, mem->sizeleft + realsize + 1); + if(ptr == NULL) { + /* out of memory! */ + printf("not enough memory (realloc returned NULL)\n"); + return 0; + } + + mem->buf = ptr; + memcpy(&(mem->buf[mem->sizeleft]), contents, realsize); + mem->sizeleft += realsize; + mem->buf[mem->sizeleft] = 0; + + //printf("result:%s\n\n", mem->buf); + + return realsize; +} + +void curlProceLogin(void) +{ + CURL *curl_handle; + CURLcode res; + + curlMemInfo chunk; + + chunk.buf = malloc(1); /* will be grown as needed by the realloc above */ + chunk.sizeleft = 0; /* no data at this point */ + + //curl_global_init(CURL_GLOBAL_ALL); + + /* init the curl session */ + curl_handle = curl_easy_init(); + + curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,""); + curl_easy_setopt(curl_handle, CURLOPT_POST, 1); + + char dstUrl[128] = {0}; + snprintf(dstUrl, 128, "http://%s:6041/rest/login/root/taosdata", g_Dbs.host); + + /* specify URL to get */ + curl_easy_setopt(curl_handle, CURLOPT_URL, dstUrl); + + /* send all data to this function */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, responseCallback); + + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + + /* do it! */ + res = curl_easy_perform(curl_handle); + + /* check for errors */ + if(res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + } + else { + //printf("response len:%lu, content: %s \n", (unsigned long)chunk.sizeleft, chunk.buf); + ; + } + + /* cleanup curl stuff */ + curl_easy_cleanup(curl_handle); + + free(chunk.buf); + + /* we're done with libcurl, so clean it up */ + //curl_global_cleanup(); + + return; +} + +int curlProceSql(char* host, uint16_t port, char* sqlstr, CURL *curl_handle) +{ + //curlProceLogin(); + + //CURL *curl_handle; + CURLcode res; + + curlMemInfo chunk; + + chunk.buf = malloc(1); /* will be grown as needed by the realloc above */ + chunk.sizeleft = 0; /* no data at this point */ + + + char dstUrl[128] = {0}; + snprintf(dstUrl, 128, "http://%s:%u/rest/sql", host, port+TSDB_PORT_HTTP); + + //curl_global_init(CURL_GLOBAL_ALL); + + /* init the curl session */ + //curl_handle = curl_easy_init(); + + //curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,""); + curl_easy_setopt(curl_handle, CURLOPT_POST, 1L); + + /* specify URL to get */ + curl_easy_setopt(curl_handle, CURLOPT_URL, dstUrl); + + /* enable TCP keep-alive for this transfer */ + curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 1L); + /* keep-alive idle time to 120 seconds */ + curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPIDLE, 120L); + /* interval time between keep-alive probes: 60 seconds */ + curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPINTVL, 60L); + + /* send all data to this function */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, responseCallback); + + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + + struct curl_slist *list = NULL; + list = curl_slist_append(list, "Authorization: Basic cm9vdDp0YW9zZGF0YQ=="); + curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list); + curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list); + + /* Set the expected upload size. */ + curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)strlen(sqlstr)); + curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, sqlstr); + + /* get it! */ + res = curl_easy_perform(curl_handle); + + /* check for errors */ + if(res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + return -1; + } + else { + /* curl_easy_perform() block end and return result */ + //printf("[%32.32s] sql response len:%lu, content: %s \n\n", sqlstr, (unsigned long)chunk.sizeleft, chunk.buf); + ; + } + + curl_slist_free_all(list); /* free the list again */ + + /* cleanup curl stuff */ + //curl_easy_cleanup(curl_handle); + + free(chunk.buf); + + /* we're done with libcurl, so clean it up */ + //curl_global_cleanup(); + + return 0; +} +#endif + +char* getTagValueFromTagSample( SSuperTable* stbInfo, int tagUsePos) { + char* dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1); + if (NULL == dataBuf) { + printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1); + return NULL; + } + + int dataLen = 0; + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos); + + return dataBuf; +} + +char* generateTagVaulesForStb(SSuperTable* stbInfo) { + char* dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1); + if (NULL == dataBuf) { + printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1); + return NULL; + } + + int dataLen = 0; + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "("); + for (int i = 0; i < stbInfo->tagCount; i++) { + if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", 6)) || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", 5))) { + if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) { + printf("binary or nchar length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); + tmfree(dataBuf); + return NULL; + } + + char* buf = (char*)calloc(stbInfo->tags[i].dataLen+1, 1); + if (NULL == buf) { + printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen); + tmfree(dataBuf); + return NULL; + } + rand_string(buf, stbInfo->tags[i].dataLen); + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "\'%s\', ", buf); + tmfree(buf); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "int", 3)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%d, ", rand_int()); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "bigint", 6)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%"PRId64", ", rand_bigint()); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "float", 5)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%f, ", rand_float()); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "double", 6)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%f, ", rand_double()); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "smallint", 8)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%d, ", rand_smallint()); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "tinyint", 7)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%d, ", rand_tinyint()); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "bool", 4)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%d, ", rand_bool()); + } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "timestamp", 4)) { + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%"PRId64", ", rand_bigint()); + } else { + printf("No support data type: %s\n", stbInfo->tags[i].dataType); + tmfree(dataBuf); + return NULL; + } + } + dataLen -= 2; + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")"); + return dataBuf; +} + +static int calcRowLen(SSuperTable* superTbls) { + int colIndex; + int lenOfOneRow = 0; + + for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) { + char* dataType = superTbls->columns[colIndex].dataType; + + if (strcasecmp(dataType, "BINARY") == 0) { + lenOfOneRow += superTbls->columns[colIndex].dataLen + 3; + } else if (strcasecmp(dataType, "NCHAR") == 0) { + lenOfOneRow += superTbls->columns[colIndex].dataLen + 3; + } else if (strcasecmp(dataType, "INT") == 0) { + lenOfOneRow += 11; + } else if (strcasecmp(dataType, "BIGINT") == 0) { + lenOfOneRow += 21; + } else if (strcasecmp(dataType, "SMALLINT") == 0) { + lenOfOneRow += 6; + } else if (strcasecmp(dataType, "TINYINT") == 0) { + lenOfOneRow += 4; + } else if (strcasecmp(dataType, "BOOL") == 0) { + lenOfOneRow += 6; + } else if (strcasecmp(dataType, "FLOAT") == 0) { + lenOfOneRow += 22; + } else if (strcasecmp(dataType, "DOUBLE") == 0) { + lenOfOneRow += 42; + } else if (strcasecmp(dataType, "TIMESTAMP") == 0) { + lenOfOneRow += 21; + } else { + printf("get error data type : %s\n", dataType); + exit(-1); + } + } + + superTbls->lenOfOneRow = lenOfOneRow + 20; // timestamp + + int tagIndex; + int lenOfTagOfOneRow = 0; + for (tagIndex = 0; tagIndex < superTbls->tagCount; tagIndex++) { + char* dataType = superTbls->tags[tagIndex].dataType; + + if (strcasecmp(dataType, "BINARY") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3; + } else if (strcasecmp(dataType, "NCHAR") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3; + } else if (strcasecmp(dataType, "INT") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 11; + } else if (strcasecmp(dataType, "BIGINT") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 21; + } else if (strcasecmp(dataType, "SMALLINT") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6; + } else if (strcasecmp(dataType, "TINYINT") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 4; + } else if (strcasecmp(dataType, "BOOL") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6; + } else if (strcasecmp(dataType, "FLOAT") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 22; + } else if (strcasecmp(dataType, "DOUBLE") == 0) { + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42; + } else { + printf("get error tag type : %s\n", dataType); + exit(-1); + } + } + + superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow; + + return 0; +} + + +static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName, char* sTblName, char** childTblNameOfSuperTbl, int* childTblCountOfSuperTbl) { + char command[BUFFER_SIZE] = "\0"; + TAOS_RES * res; + TAOS_ROW row = NULL; + int count = 0; + + char* childTblName = *childTblNameOfSuperTbl; + + //get all child table name use cmd: select tbname from superTblName; + snprintf(command, BUFFER_SIZE, "select tbname from %s.%s", dbName, sTblName); + res = taos_query(taos, command); + int32_t code = taos_errno(res); + if (code != 0) { + printf("failed to run command %s\n", command); + taos_free_result(res); + taos_close(taos); + exit(-1); + } + + int childTblCount = 10000; + count = 0; + childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN); + char* pTblName = childTblName; + while ((row = taos_fetch_row(res)) != NULL) { + strncpy(pTblName, (char *)row[0], TSDB_TABLE_NAME_LEN); + //printf("==== sub table name: %s\n", pTblName); + count++; + if (count == childTblCount) { + char *tmp = realloc(childTblName, (size_t)count*1.5*TSDB_TABLE_NAME_LEN); + if (tmp != NULL) { + childTblName = tmp; + memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0, (size_t)(count*0.5*TSDB_TABLE_NAME_LEN)); + } else { + // exit, if allocate more memory failed + printf("realloc fail for save child table name of %s.%s\n", dbName, sTblName); + tmfree(childTblName); + taos_free_result(res); + taos_close(taos); + exit(-1); + } + } + pTblName = childTblName + count * TSDB_TABLE_NAME_LEN; + } + + *childTblCountOfSuperTbl = count; + *childTblNameOfSuperTbl = childTblName; + + taos_free_result(res); + return 0; +} + +static int getSuperTableFromServer(TAOS * taos, char* dbName, SSuperTable* superTbls) { + char command[BUFFER_SIZE] = "\0"; + TAOS_RES * res; + TAOS_ROW row = NULL; + int count = 0; + + //get schema use cmd: describe superTblName; + snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName); + res = taos_query(taos, command); + int32_t code = taos_errno(res); + if (code != 0) { + printf("failed to run command %s\n", command); + taos_free_result(res); + return -1; + } + + int tagIndex = 0; + int columnIndex = 0; + TAOS_FIELD *fields = taos_fetch_fields(res); + while ((row = taos_fetch_row(res)) != NULL) { + if (0 == count) { + count++; + continue; + } + + if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) { + strncpy(superTbls->tags[tagIndex].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX], fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes); + strncpy(superTbls->tags[tagIndex].dataType, (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX], fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes); + superTbls->tags[tagIndex].dataLen = *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]); + strncpy(superTbls->tags[tagIndex].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes); + tagIndex++; + } else { + strncpy(superTbls->columns[columnIndex].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX], fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes); + strncpy(superTbls->columns[columnIndex].dataType, (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX], fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes); + superTbls->columns[columnIndex].dataLen = *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]); + strncpy(superTbls->columns[columnIndex].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes); + columnIndex++; + } + count++; + } + + superTbls->columnCount = columnIndex; + superTbls->tagCount = tagIndex; + taos_free_result(res); + + calcRowLen(superTbls); + + if (TBL_ALREADY_EXISTS == superTbls->childTblExists) { + //get all child table name use cmd: select tbname from superTblName; + getAllChildNameOfSuperTable(taos, dbName, superTbls->sTblName, &superTbls->childTblName, &superTbls->childTblCount); + } + return 0; +} + +static int createSuperTable(TAOS * taos, char* dbName, SSuperTable* superTbls, bool use_metric) { + char command[BUFFER_SIZE] = "\0"; + + char cols[STRING_LEN] = "\0"; + int colIndex; + int len = 0; + + int lenOfOneRow = 0; + for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) { + char* dataType = superTbls->columns[colIndex].dataType; + + if (strcasecmp(dataType, "BINARY") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s(%d)", colIndex, "BINARY", superTbls->columns[colIndex].dataLen); + lenOfOneRow += superTbls->columns[colIndex].dataLen + 3; + } else if (strcasecmp(dataType, "NCHAR") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s(%d)", colIndex, "NCHAR", superTbls->columns[colIndex].dataLen); + lenOfOneRow += superTbls->columns[colIndex].dataLen + 3; + } else if (strcasecmp(dataType, "INT") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "INT"); + lenOfOneRow += 11; + } else if (strcasecmp(dataType, "BIGINT") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "BIGINT"); + lenOfOneRow += 21; + } else if (strcasecmp(dataType, "SMALLINT") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "SMALLINT"); + lenOfOneRow += 6; + } else if (strcasecmp(dataType, "TINYINT") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TINYINT"); + lenOfOneRow += 4; + } else if (strcasecmp(dataType, "BOOL") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "BOOL"); + lenOfOneRow += 6; + } else if (strcasecmp(dataType, "FLOAT") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "FLOAT"); + lenOfOneRow += 22; + } else if (strcasecmp(dataType, "DOUBLE") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE"); + lenOfOneRow += 42; + } else if (strcasecmp(dataType, "TIMESTAMP") == 0) { + len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP"); + lenOfOneRow += 21; + } else { + taos_close(taos); + printf("config error data type : %s\n", dataType); + exit(-1); + } + } + + superTbls->lenOfOneRow = lenOfOneRow + 20; // timestamp + //printf("%s.%s column count:%d, column length:%d\n\n", g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName, g_Dbs.db[i].superTbls[j].columnCount, lenOfOneRow); + + // save for creating child table + superTbls->colsOfCreatChildTable = (char*)calloc(len+20, 1); + if (NULL == superTbls->colsOfCreatChildTable) { + printf("Failed when calloc, size:%d", len+1); + taos_close(taos); + exit(-1); + } + snprintf(superTbls->colsOfCreatChildTable, len+20, "(ts timestamp%s)", cols); + + if (use_metric) { + char tags[STRING_LEN] = "\0"; + int tagIndex; + len = 0; + + int lenOfTagOfOneRow = 0; + len += snprintf(tags + len, STRING_LEN - len, "("); + for (tagIndex = 0; tagIndex < superTbls->tagCount; tagIndex++) { + char* dataType = superTbls->tags[tagIndex].dataType; + + if (strcasecmp(dataType, "BINARY") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex, "BINARY", superTbls->tags[tagIndex].dataLen); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3; + } else if (strcasecmp(dataType, "NCHAR") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex, "NCHAR", superTbls->tags[tagIndex].dataLen); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3; + } else if (strcasecmp(dataType, "INT") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "INT"); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 11; + } else if (strcasecmp(dataType, "BIGINT") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "BIGINT"); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 21; + } else if (strcasecmp(dataType, "SMALLINT") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "SMALLINT"); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6; + } else if (strcasecmp(dataType, "TINYINT") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "TINYINT"); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 4; + } else if (strcasecmp(dataType, "BOOL") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "BOOL"); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6; + } else if (strcasecmp(dataType, "FLOAT") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "FLOAT"); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 22; + } else if (strcasecmp(dataType, "DOUBLE") == 0) { + len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "DOUBLE"); + lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42; + } else { + taos_close(taos); + printf("config error tag type : %s\n", dataType); + exit(-1); + } + } + len -= 2; + len += snprintf(tags + len, STRING_LEN - len, ")"); + + superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow; + + snprintf(command, BUFFER_SIZE, "create table if not exists %s.%s (ts timestamp%s) tags %s", dbName, superTbls->sTblName, cols, tags); + if (0 != queryDbExec(taos, command, NO_INSERT_TYPE)) { + return -1; + } + printf("\ncreate supertable %s success!\n\n", superTbls->sTblName); + } + return 0; +} + + +static int createDatabases() { + TAOS * taos = NULL; + int ret = 0; + taos_init(); + taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, NULL, g_Dbs.port); + if (taos == NULL) { + fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + exit(-1); + } + char command[BUFFER_SIZE] = "\0"; + + + for (int i = 0; i < g_Dbs.dbCount; i++) { + if (g_Dbs.db[i].drop) { + sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName); + if (0 != queryDbExec(taos, command, NO_INSERT_TYPE)) { + taos_close(taos); + return -1; + } + } + + int dataLen = 0; + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "create database if not exists %s ", g_Dbs.db[i].dbName); + + if (g_Dbs.db[i].dbCfg.blocks > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "blocks %d ", g_Dbs.db[i].dbCfg.blocks); + } + if (g_Dbs.db[i].dbCfg.cache > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "cache %d ", g_Dbs.db[i].dbCfg.cache); + } + if (g_Dbs.db[i].dbCfg.days > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "days %d ", g_Dbs.db[i].dbCfg.days); + } + if (g_Dbs.db[i].dbCfg.keep > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "keep %d ", g_Dbs.db[i].dbCfg.keep); + } + if (g_Dbs.db[i].dbCfg.replica > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "replica %d ", g_Dbs.db[i].dbCfg.replica); + } + if (g_Dbs.db[i].dbCfg.update > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "update %d ", g_Dbs.db[i].dbCfg.update); + } + //if (g_Dbs.db[i].dbCfg.maxtablesPerVnode > 0) { + // dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "tables %d ", g_Dbs.db[i].dbCfg.maxtablesPerVnode); + //} + if (g_Dbs.db[i].dbCfg.minRows > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "minrows %d ", g_Dbs.db[i].dbCfg.minRows); + } + if (g_Dbs.db[i].dbCfg.maxRows > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "maxrows %d ", g_Dbs.db[i].dbCfg.maxRows); + } + if (g_Dbs.db[i].dbCfg.comp > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "comp %d ", g_Dbs.db[i].dbCfg.comp); + } + if (g_Dbs.db[i].dbCfg.walLevel > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "wal %d ", g_Dbs.db[i].dbCfg.walLevel); + } + if (g_Dbs.db[i].dbCfg.fsync > 0) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "fsync %d ", g_Dbs.db[i].dbCfg.fsync); + } + if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2)) || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) { + dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, "precision \'%s\';", g_Dbs.db[i].dbCfg.precision); + } + + if (0 != queryDbExec(taos, command, NO_INSERT_TYPE)) { + taos_close(taos); + return -1; + } + printf("\ncreate database %s success!\n\n", g_Dbs.db[i].dbName); + + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + // describe super table, if exists + sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName); + if (0 != queryDbExec(taos, command, NO_INSERT_TYPE)) { + g_Dbs.db[i].superTbls[j].superTblExists = TBL_NO_EXISTS; + ret = createSuperTable(taos, g_Dbs.db[i].dbName, &g_Dbs.db[i].superTbls[j], g_Dbs.use_metric); + } else { + g_Dbs.db[i].superTbls[j].superTblExists = TBL_ALREADY_EXISTS; + ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName, &g_Dbs.db[i].superTbls[j]); + } + + if (0 != ret) { + taos_close(taos); + return -1; + } + } + } + + taos_close(taos); + return 0; +} + + +void * createTable(void *sarg) +{ + char command[BUFFER_SIZE] = "\0"; + + threadInfo *winfo = (threadInfo *)sarg; + SSuperTable* superTblInfo = winfo->superTblInfo; + + int64_t lastPrintTime = taosGetTimestampMs(); + + //printf("Creating table from %d to %d\n", winfo->start_table_id, winfo->end_table_id); + for (int i = winfo->start_table_id; i <= winfo->end_table_id; i++) { + if (0 == g_Dbs.use_metric) { + snprintf(command, BUFFER_SIZE, "create table if not exists %s.%s%d %s;", winfo->db_name, superTblInfo->childTblPrefix, i, superTblInfo->colsOfCreatChildTable); + } else { + char* tagsValBuf = NULL; + if (0 == superTblInfo->tagSource) { + tagsValBuf = generateTagVaulesForStb(superTblInfo); + } else { + tagsValBuf = getTagValueFromTagSample(superTblInfo, i % superTblInfo->tagSampleCount); + } + if (NULL == tagsValBuf) { + return NULL; + } + snprintf(command, BUFFER_SIZE, "create table if not exists %s.%s%d using %s.%s tags %s;", winfo->db_name, superTblInfo->childTblPrefix, i, winfo->db_name, superTblInfo->sTblName, tagsValBuf); + free(tagsValBuf); + } + + if (0 != queryDbExec(winfo->taos, command, NO_INSERT_TYPE)){ + return NULL; + } + + int64_t currentPrintTime = taosGetTimestampMs(); + if (currentPrintTime - lastPrintTime > 30*1000) { + printf("thread[%d] already create %d - %d tables\n", winfo->threadID, winfo->start_table_id, i); + lastPrintTime = currentPrintTime; + } + } + + return NULL; +} + +void startMultiThreadCreateChildTable(char* cols, int threads, int ntables, char* db_name, SSuperTable* superTblInfo) { + pthread_t *pids = malloc(threads * sizeof(pthread_t)); + threadInfo *infos = malloc(threads * sizeof(threadInfo)); + + if ((NULL == pids) || (NULL == infos)) { + printf("malloc failed\n"); + exit(-1); + } + + if (threads < 1) { + threads = 1; + } + + int a = ntables / threads; + if (a < 1) { + threads = ntables; + a = 1; + } + + int b = 0; + b = ntables % threads; + + int last = 0; + for (int i = 0; i < threads; i++) { + threadInfo *t_info = infos + i; + t_info->threadID = i; + tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE); + t_info->superTblInfo = superTblInfo; + t_info->taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, db_name, g_Dbs.port); + t_info->start_table_id = last; + t_info->end_table_id = i < b ? last + a : last + a - 1; + last = t_info->end_table_id + 1; + t_info->use_metric = 1; + t_info->cols = cols; + pthread_create(pids + i, NULL, createTable, t_info); + } + + for (int i = 0; i < threads; i++) { + pthread_join(pids[i], NULL); + } + + for (int i = 0; i < threads; i++) { + threadInfo *t_info = infos + i; + taos_close(t_info->taos); + } + + free(pids); + free(infos); +} + + +static void createChildTables() { + for (int i = 0; i < g_Dbs.dbCount; i++) { + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) { + continue; + } + startMultiThreadCreateChildTable(g_Dbs.db[i].superTbls[j].colsOfCreatChildTable, g_Dbs.threadCount, g_Dbs.db[i].superTbls[j].childTblCount, g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j])); + g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount; + } + } +} + +/* + Read 10000 lines at most. If more than 10000 lines, continue to read after using +*/ +int readTagFromCsvFileToMem(SSuperTable * supterTblInfo) { + size_t n = 0; + ssize_t readLen = 0; + char * line = NULL; + + FILE *fp = fopen(supterTblInfo->tagsFile, "r"); + if (fp == NULL) { + printf("Failed to open tags file: %s, reason:%s\n", supterTblInfo->tagsFile, strerror(errno)); + return -1; + } + + if (supterTblInfo->tagDataBuf) { + free(supterTblInfo->tagDataBuf); + supterTblInfo->tagDataBuf = NULL; + } + + supterTblInfo->tagDataBuf = calloc(supterTblInfo->lenOfTagOfOneRow * MAX_LINE_COUNT_IN_MEM, 1); + if (supterTblInfo->tagDataBuf == NULL) { + printf("Failed to calloc, reason:%s\n", strerror(errno)); + fclose(fp); + return -1; + } + + while ((readLen = getline(&line, &n, fp)) != -1) { + if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) { + line[--readLen] = 0; + } + + if (readLen == 0) { + continue; + } + + memcpy(supterTblInfo->tagDataBuf + supterTblInfo->tagSampleCount * supterTblInfo->lenOfTagOfOneRow, line, readLen); + supterTblInfo->tagSampleCount++; + + if (supterTblInfo->tagSampleCount >= MAX_LINE_COUNT_IN_MEM) { + break; + } + } + + free(line); + fclose(fp); + return 0; +} + +int readSampleFromJsonFileToMem(SSuperTable * supterTblInfo) { + // TODO + return 0; +} + + +/* + Read 10000 lines at most. If more than 10000 lines, continue to read after using +*/ +int readSampleFromCsvFileToMem(FILE *fp, SSuperTable* superTblInfo, char* sampleBuf) { + size_t n = 0; + ssize_t readLen = 0; + char * line = NULL; + int getRows = 0; + + memset(sampleBuf, 0, MAX_SAMPLES_ONCE_FROM_FILE* superTblInfo->lenOfOneRow); + while (1) { + readLen = getline(&line, &n, fp); + if (-1 == readLen) { + if(0 != fseek(fp, 0, SEEK_SET)) { + printf("Failed to fseek file: %s, reason:%s\n", superTblInfo->sampleFile, strerror(errno)); + return -1; + } + continue; + } + + if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) { + line[--readLen] = 0; + } + + if (readLen == 0) { + continue; + } + + if (readLen > superTblInfo->lenOfOneRow) { + printf("sample row len[%d] overflow define schema len[%d], so discard this row\n", (int32_t)readLen, superTblInfo->lenOfOneRow); + continue; + } + + memcpy(sampleBuf + getRows * superTblInfo->lenOfOneRow, line, readLen); + getRows++; + + if (getRows == MAX_SAMPLES_ONCE_FROM_FILE) { + break; + } + } + + tmfree(line); + return 0; +} + +/* +void readSampleFromFileToMem(SSuperTable * supterTblInfo) { + int ret; + if (0 == strncasecmp(supterTblInfo->sampleFormat, "csv", 3)) { + ret = readSampleFromCsvFileToMem(supterTblInfo); + } else if (0 == strncasecmp(supterTblInfo->sampleFormat, "json", 4)) { + ret = readSampleFromJsonFileToMem(supterTblInfo); + } + + if (0 != ret) { + exit(-1); + } +} +*/ +static bool getColumnAndTagTypeFromInsertJsonFile(cJSON* stbInfo, SSuperTable* superTbls) { + bool ret = false; + + // columns + cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns"); + if (columns && columns->type != cJSON_Array) { + printf("failed to read json, columns not found\n"); + goto PARSE_OVER; + } else if (NULL == columns) { + superTbls->columnCount = 0; + superTbls->tagCount = 0; + return true; + } + + int columnSize = cJSON_GetArraySize(columns); + if (columnSize > MAX_COLUMN_COUNT) { + printf("failed to read json, column size overflow, max column size is %d\n", MAX_COLUMN_COUNT); + goto PARSE_OVER; + } + + int count = 1; + int index = 0; + StrColumn columnCase = {0}; + + //superTbls->columnCount = columnSize; + for (int k = 0; k < columnSize; ++k) { + cJSON* column = cJSON_GetArrayItem(columns, k); + if (column == NULL) continue; + + count = 1; + cJSON* countObj = cJSON_GetObjectItem(column, "count"); + if (countObj && countObj->type == cJSON_Number) { + count = countObj->valueint; + } else if (countObj && countObj->type != cJSON_Number) { + printf("failed to read json, column count not found"); + goto PARSE_OVER; + } else { + count = 1; + } + + // column info + memset(&columnCase, 0, sizeof(StrColumn)); + cJSON *dataType = cJSON_GetObjectItem(column, "type"); + if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) { + printf("failed to read json, column type not found"); + goto PARSE_OVER; + } + //strncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE); + strncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE); + + cJSON* dataLen = cJSON_GetObjectItem(column, "len"); + if (dataLen && dataLen->type == cJSON_Number) { + columnCase.dataLen = dataLen->valueint; + } else if (dataLen && dataLen->type != cJSON_Number) { + printf("failed to read json, column len not found"); + goto PARSE_OVER; + } else { + columnCase.dataLen = 8; + } + + for (int n = 0; n < count; ++n) { + strncpy(superTbls->columns[index].dataType, columnCase.dataType, MAX_TB_NAME_SIZE); + superTbls->columns[index].dataLen = columnCase.dataLen; + index++; + } + } + superTbls->columnCount = index; + + count = 1; + index = 0; + // tags + cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags"); + if (!tags || tags->type != cJSON_Array) { + printf("failed to read json, tags not found"); + goto PARSE_OVER; + } + + int tagSize = cJSON_GetArraySize(tags); + if (tagSize > MAX_TAG_COUNT) { + printf("failed to read json, tags size overflow, max tag size is %d\n", MAX_TAG_COUNT); + goto PARSE_OVER; + } + + //superTbls->tagCount = tagSize; + for (int k = 0; k < tagSize; ++k) { + cJSON* tag = cJSON_GetArrayItem(tags, k); + if (tag == NULL) continue; + + count = 1; + cJSON* countObj = cJSON_GetObjectItem(tag, "count"); + if (countObj && countObj->type == cJSON_Number) { + count = countObj->valueint; + } else if (countObj && countObj->type != cJSON_Number) { + printf("failed to read json, column count not found"); + goto PARSE_OVER; + } else { + count = 1; + } + + // column info + memset(&columnCase, 0, sizeof(StrColumn)); + cJSON *dataType = cJSON_GetObjectItem(tag, "type"); + if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) { + printf("failed to read json, tag type not found"); + goto PARSE_OVER; + } + strncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE); + + cJSON* dataLen = cJSON_GetObjectItem(tag, "len"); + if (dataLen && dataLen->type == cJSON_Number) { + columnCase.dataLen = dataLen->valueint; + } else if (dataLen && dataLen->type != cJSON_Number) { + printf("failed to read json, column len not found"); + goto PARSE_OVER; + } else { + columnCase.dataLen = 0; + } + + for (int n = 0; n < count; ++n) { + strncpy(superTbls->tags[index].dataType, columnCase.dataType, MAX_TB_NAME_SIZE); + superTbls->tags[index].dataLen = columnCase.dataLen; + index++; + } + } + superTbls->tagCount = index; + + ret = true; + +PARSE_OVER: + //free(content); + //cJSON_Delete(root); + //fclose(fp); + return ret; +} + +static bool getMetaFromInsertJsonFile(cJSON* root) { + bool ret = false; + + cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir"); + if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) { + strncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN); + } + + cJSON* host = cJSON_GetObjectItem(root, "host"); + if (host && host->type == cJSON_String && host->valuestring != NULL) { + strncpy(g_Dbs.host, host->valuestring, MAX_DB_NAME_SIZE); + } else if (!host) { + strncpy(g_Dbs.host, "127.0.0.1", MAX_DB_NAME_SIZE); + } else { + printf("failed to read json, host not found\n"); + goto PARSE_OVER; + } + + cJSON* port = cJSON_GetObjectItem(root, "port"); + if (port && port->type == cJSON_Number) { + g_Dbs.port = port->valueint; + } else if (!port) { + g_Dbs.port = 6030; + } + + cJSON* user = cJSON_GetObjectItem(root, "user"); + if (user && user->type == cJSON_String && user->valuestring != NULL) { + strncpy(g_Dbs.user, user->valuestring, MAX_DB_NAME_SIZE); + } else if (!user) { + strncpy(g_Dbs.user, "root", MAX_DB_NAME_SIZE); + } + + cJSON* password = cJSON_GetObjectItem(root, "password"); + if (password && password->type == cJSON_String && password->valuestring != NULL) { + strncpy(g_Dbs.password, password->valuestring, MAX_DB_NAME_SIZE); + } else if (!password) { + strncpy(g_Dbs.password, "taosdata", MAX_DB_NAME_SIZE); + } + + cJSON* resultfile = cJSON_GetObjectItem(root, "result_file"); + if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) { + strncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN); + } else if (!resultfile) { + strncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN); + } + + cJSON* threads = cJSON_GetObjectItem(root, "thread_count"); + if (threads && threads->type == cJSON_Number) { + g_Dbs.threadCount = threads->valueint; + } else if (!threads) { + g_Dbs.threadCount = 1; + } else { + printf("failed to read json, threads not found"); + goto PARSE_OVER; + } + + cJSON* dbs = cJSON_GetObjectItem(root, "databases"); + if (!dbs || dbs->type != cJSON_Array) { + printf("failed to read json, databases not found\n"); + goto PARSE_OVER; + } + + int dbSize = cJSON_GetArraySize(dbs); + if (dbSize > MAX_DB_COUNT) { + printf("failed to read json, databases size overflow, max database is %d\n", MAX_DB_COUNT); + goto PARSE_OVER; + } + + g_Dbs.dbCount = dbSize; + for (int i = 0; i < dbSize; ++i) { + cJSON* dbinfos = cJSON_GetArrayItem(dbs, i); + if (dbinfos == NULL) continue; + + // dbinfo + cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo"); + if (!dbinfo || dbinfo->type != cJSON_Object) { + printf("failed to read json, dbinfo not found"); + goto PARSE_OVER; + } + + cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name"); + if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) { + printf("failed to read json, db name not found"); + goto PARSE_OVER; + } + strncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE); + + cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop"); + if (drop && drop->type == cJSON_String && drop->valuestring != NULL) { + if (0 == strncasecmp(drop->valuestring, "yes", 3)) { + g_Dbs.db[i].drop = 1; + } else { + g_Dbs.db[i].drop = 0; + } + } else if (!drop) { + g_Dbs.db[i].drop = 0; + } else { + printf("failed to read json, drop not found"); + goto PARSE_OVER; + } + + cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision"); + if (precision && precision->type == cJSON_String && precision->valuestring != NULL) { + strncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring, MAX_DB_NAME_SIZE); + } else if (!precision) { + //strncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE); + memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE); + } else { + printf("failed to read json, precision not found"); + goto PARSE_OVER; + } + + cJSON* update = cJSON_GetObjectItem(dbinfo, "update"); + if (update && update->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.update = update->valueint; + } else if (!update) { + g_Dbs.db[i].dbCfg.update = -1; + } else { + printf("failed to read json, update not found"); + goto PARSE_OVER; + } + + cJSON* replica = cJSON_GetObjectItem(dbinfo, "replica"); + if (replica && replica->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.replica = replica->valueint; + } else if (!replica) { + g_Dbs.db[i].dbCfg.replica = -1; + } else { + printf("failed to read json, replica not found"); + goto PARSE_OVER; + } + + cJSON* keep = cJSON_GetObjectItem(dbinfo, "keep"); + if (keep && keep->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.keep = keep->valueint; + } else if (!keep) { + g_Dbs.db[i].dbCfg.keep = -1; + } else { + printf("failed to read json, keep not found"); + goto PARSE_OVER; + } + + cJSON* days = cJSON_GetObjectItem(dbinfo, "days"); + if (days && days->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.days = days->valueint; + } else if (!days) { + g_Dbs.db[i].dbCfg.days = -1; + } else { + printf("failed to read json, days not found"); + goto PARSE_OVER; + } + + cJSON* cache = cJSON_GetObjectItem(dbinfo, "cache"); + if (cache && cache->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.cache = cache->valueint; + } else if (!cache) { + g_Dbs.db[i].dbCfg.cache = -1; + } else { + printf("failed to read json, cache not found"); + goto PARSE_OVER; + } + + cJSON* blocks= cJSON_GetObjectItem(dbinfo, "blocks"); + if (blocks && blocks->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.blocks = blocks->valueint; + } else if (!blocks) { + g_Dbs.db[i].dbCfg.blocks = -1; + } else { + printf("failed to read json, block not found"); + goto PARSE_OVER; + } + + //cJSON* maxtablesPerVnode= cJSON_GetObjectItem(dbinfo, "maxtablesPerVnode"); + //if (maxtablesPerVnode && maxtablesPerVnode->type == cJSON_Number) { + // g_Dbs.db[i].dbCfg.maxtablesPerVnode = maxtablesPerVnode->valueint; + //} else if (!maxtablesPerVnode) { + // g_Dbs.db[i].dbCfg.maxtablesPerVnode = TSDB_DEFAULT_TABLES; + //} else { + // printf("failed to read json, maxtablesPerVnode not found"); + // goto PARSE_OVER; + //} + + cJSON* minRows= cJSON_GetObjectItem(dbinfo, "minRows"); + if (minRows && minRows->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.minRows = minRows->valueint; + } else if (!minRows) { + g_Dbs.db[i].dbCfg.minRows = -1; + } else { + printf("failed to read json, minRows not found"); + goto PARSE_OVER; + } + + cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows"); + if (maxRows && maxRows->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint; + } else if (!maxRows) { + g_Dbs.db[i].dbCfg.maxRows = -1; + } else { + printf("failed to read json, maxRows not found"); + goto PARSE_OVER; + } + + cJSON* comp= cJSON_GetObjectItem(dbinfo, "comp"); + if (comp && comp->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.comp = comp->valueint; + } else if (!comp) { + g_Dbs.db[i].dbCfg.comp = -1; + } else { + printf("failed to read json, comp not found"); + goto PARSE_OVER; + } + + cJSON* walLevel= cJSON_GetObjectItem(dbinfo, "walLevel"); + if (walLevel && walLevel->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.walLevel = walLevel->valueint; + } else if (!walLevel) { + g_Dbs.db[i].dbCfg.walLevel = -1; + } else { + printf("failed to read json, walLevel not found"); + goto PARSE_OVER; + } + + cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum"); + if (quorum && quorum->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.quorum = quorum->valueint; + } else if (!quorum) { + g_Dbs.db[i].dbCfg.quorum = -1; + } else { + printf("failed to read json, walLevel not found"); + goto PARSE_OVER; + } + + cJSON* fsync= cJSON_GetObjectItem(dbinfo, "fsync"); + if (fsync && fsync->type == cJSON_Number) { + g_Dbs.db[i].dbCfg.fsync = fsync->valueint; + } else if (!fsync) { + g_Dbs.db[i].dbCfg.fsync = -1; + } else { + printf("failed to read json, fsync not found"); + goto PARSE_OVER; + } + + // super_talbes + cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables"); + if (!stables || stables->type != cJSON_Array) { + printf("failed to read json, super_tables not found"); + goto PARSE_OVER; + } + + int stbSize = cJSON_GetArraySize(stables); + if (stbSize > MAX_SUPER_TABLE_COUNT) { + printf("failed to read json, databases size overflow, max database is %d\n", MAX_SUPER_TABLE_COUNT); + goto PARSE_OVER; + } + + g_Dbs.db[i].superTblCount = stbSize; + for (int j = 0; j < stbSize; ++j) { + cJSON* stbInfo = cJSON_GetArrayItem(stables, j); + if (stbInfo == NULL) continue; + + // dbinfo + cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name"); + if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) { + printf("failed to read json, stb name not found"); + goto PARSE_OVER; + } + strncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE); + + cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix"); + if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) { + printf("failed to read json, childtable_prefix not found"); + goto PARSE_OVER; + } + strncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE); + + cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null + if (autoCreateTbl && autoCreateTbl->type == cJSON_String && autoCreateTbl->valuestring != NULL) { + if (0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3)) { + g_Dbs.db[i].superTbls[j].autoCreateTable = AUTO_CREATE_SUBTBL; + } else if (0 == strncasecmp(autoCreateTbl->valuestring, "no", 2)) { + g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; + } else { + g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; + } + } else if (!autoCreateTbl) { + g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; + } else { + printf("failed to read json, auto_create_table not found"); + goto PARSE_OVER; + } + + cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no + if (childTblExists && childTblExists->type == cJSON_String && childTblExists->valuestring != NULL) { + if (0 == strncasecmp(childTblExists->valuestring, "yes", 3)) { + g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS; + } else if (0 == strncasecmp(childTblExists->valuestring, "no", 2)) { + g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS; + } else { + g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS; + } + } else if (!childTblExists) { + g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS; + } else { + printf("failed to read json, child_table_exists not found"); + goto PARSE_OVER; + } + + cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count"); + if (!count || count->type != cJSON_Number || 0 >= count->valueint) { + printf("failed to read json, childtable_count not found"); + goto PARSE_OVER; + } + g_Dbs.db[i].superTbls[j].childTblCount = count->valueint; + + cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source"); + if (dataSource && dataSource->type == cJSON_String && dataSource->valuestring != NULL) { + strncpy(g_Dbs.db[i].superTbls[j].dataSource, dataSource->valuestring, MAX_DB_NAME_SIZE); + } else if (!dataSource) { + strncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE); + } else { + printf("failed to read json, data_source not found"); + goto PARSE_OVER; + } + + cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , restful + if (insertMode && insertMode->type == cJSON_String && insertMode->valuestring != NULL) { + strncpy(g_Dbs.db[i].superTbls[j].insertMode, insertMode->valuestring, MAX_DB_NAME_SIZE); + #ifndef TD_LOWA_CURL + if (0 == strncasecmp(g_Dbs.db[i].superTbls[j].insertMode, "restful", 7)) { + printf("There no libcurl, so no support resetful test! please use taosc mode.\n"); + goto PARSE_OVER; + } + #endif + } else if (!insertMode) { + strncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE); + } else { + printf("failed to read json, insert_mode not found"); + goto PARSE_OVER; + } + + cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp"); + if (ts && ts->type == cJSON_String && ts->valuestring != NULL) { + strncpy(g_Dbs.db[i].superTbls[j].startTimestamp, ts->valuestring, MAX_DB_NAME_SIZE); + } else if (!ts) { + strncpy(g_Dbs.db[i].superTbls[j].startTimestamp, "now", MAX_DB_NAME_SIZE); + } else { + printf("failed to read json, start_timestamp not found"); + goto PARSE_OVER; + } + + cJSON* timestampStep = cJSON_GetObjectItem(stbInfo, "timestamp_step"); + if (timestampStep && timestampStep->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].timeStampStep = timestampStep->valueint; + } else if (!timestampStep) { + g_Dbs.db[i].superTbls[j].timeStampStep = 1000; + } else { + printf("failed to read json, timestamp_step not found"); + goto PARSE_OVER; + } + + cJSON* sampleDataBufSize = cJSON_GetObjectItem(stbInfo, "sample_buf_size"); + if (sampleDataBufSize && sampleDataBufSize->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].sampleDataBufSize = sampleDataBufSize->valueint; + if (g_Dbs.db[i].superTbls[j].sampleDataBufSize < 1024*1024) { + g_Dbs.db[i].superTbls[j].sampleDataBufSize = 1024*1024 + 1024; + } + } else if (!sampleDataBufSize) { + g_Dbs.db[i].superTbls[j].sampleDataBufSize = 1024*1024 + 1024; + } else { + printf("failed to read json, sample_buf_size not found"); + goto PARSE_OVER; + } + + cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format"); + if (sampleFormat && sampleFormat->type == cJSON_String && sampleFormat->valuestring != NULL) { + strncpy(g_Dbs.db[i].superTbls[j].sampleFormat, sampleFormat->valuestring, MAX_DB_NAME_SIZE); + } else if (!sampleFormat) { + strncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", MAX_DB_NAME_SIZE); + } else { + printf("failed to read json, sample_format not found"); + goto PARSE_OVER; + } + + cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file"); + if (sampleFile && sampleFile->type == cJSON_String && sampleFile->valuestring != NULL) { + strncpy(g_Dbs.db[i].superTbls[j].sampleFile, sampleFile->valuestring, MAX_FILE_NAME_LEN); + } else if (!sampleFile) { + memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN); + } else { + printf("failed to read json, sample_file not found"); + goto PARSE_OVER; + } + + cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file"); + if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) { + strncpy(g_Dbs.db[i].superTbls[j].tagsFile, tagsFile->valuestring, MAX_FILE_NAME_LEN); + if (0 == g_Dbs.db[i].superTbls[j].tagsFile[0]) { + g_Dbs.db[i].superTbls[j].tagSource = 0; + } else { + g_Dbs.db[i].superTbls[j].tagSource = 1; + } + } else if (!tagsFile) { + memset(g_Dbs.db[i].superTbls[j].tagsFile, 0, MAX_FILE_NAME_LEN); + g_Dbs.db[i].superTbls[j].tagSource = 0; + } else { + printf("failed to read json, tags_file not found"); + goto PARSE_OVER; + } + + cJSON* maxSqlLen = cJSON_GetObjectItem(stbInfo, "max_sql_len"); + if (maxSqlLen && maxSqlLen->type == cJSON_Number) { + int32_t len = maxSqlLen->valueint; + if (len > TSDB_MAX_ALLOWED_SQL_LEN) { + len = TSDB_MAX_ALLOWED_SQL_LEN; + } else if (len < TSDB_MAX_SQL_LEN) { + len = TSDB_MAX_SQL_LEN; + } + g_Dbs.db[i].superTbls[j].maxSqlLen = len; + } else if (!maxSqlLen) { + g_Dbs.db[i].superTbls[j].maxSqlLen = TSDB_MAX_SQL_LEN; + } else { + printf("failed to read json, maxSqlLen not found"); + goto PARSE_OVER; + } + + cJSON *multiThreadWriteOneTbl = cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes + if (multiThreadWriteOneTbl && multiThreadWriteOneTbl->type == cJSON_String && multiThreadWriteOneTbl->valuestring != NULL) { + if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) { + g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1; + } else { + g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0; + } + } else if (!multiThreadWriteOneTbl) { + g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0; + } else { + printf("failed to read json, multiThreadWriteOneTbl not found"); + goto PARSE_OVER; + } + + cJSON* numberOfTblInOneSql = cJSON_GetObjectItem(stbInfo, "number_of_tbl_in_one_sql"); + if (numberOfTblInOneSql && numberOfTblInOneSql->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].numberOfTblInOneSql = numberOfTblInOneSql->valueint; + } else if (!numberOfTblInOneSql) { + g_Dbs.db[i].superTbls[j].numberOfTblInOneSql = 0; + } else { + printf("failed to read json, numberOfTblInOneSql not found"); + goto PARSE_OVER; + } + + cJSON* rowsPerTbl = cJSON_GetObjectItem(stbInfo, "rows_per_tbl"); + if (rowsPerTbl && rowsPerTbl->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].rowsPerTbl = rowsPerTbl->valueint; + } else if (!rowsPerTbl) { + g_Dbs.db[i].superTbls[j].rowsPerTbl = 1; + } else { + printf("failed to read json, rowsPerTbl not found"); + goto PARSE_OVER; + } + + cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio"); + if (disorderRatio && disorderRatio->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint; + } else if (!disorderRatio) { + g_Dbs.db[i].superTbls[j].disorderRatio = 0; + } else { + printf("failed to read json, disorderRatio not found"); + goto PARSE_OVER; + } + + cJSON* disorderRange = cJSON_GetObjectItem(stbInfo, "disorder_range"); + if (disorderRange && disorderRange->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].disorderRange = disorderRange->valueint; + } else if (!disorderRange) { + g_Dbs.db[i].superTbls[j].disorderRange = 1000; + } else { + printf("failed to read json, disorderRange not found"); + goto PARSE_OVER; + } + + cJSON* insertRate = cJSON_GetObjectItem(stbInfo, "insert_rate"); + if (insertRate && insertRate->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].insertRate = insertRate->valueint; + } else if (!insertRate) { + g_Dbs.db[i].superTbls[j].insertRate = 0; + } else { + printf("failed to read json, insert_rate not found"); + goto PARSE_OVER; + } + + cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows"); + if (insertRows && insertRows->type == cJSON_Number) { + g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint; + if (0 == g_Dbs.db[i].superTbls[j].insertRows) { + g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF; + } + } else if (!insertRows) { + g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF; + } else { + printf("failed to read json, insert_rows not found"); + goto PARSE_OVER; + } + + if (NO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) { + continue; + } + + int retVal = getColumnAndTagTypeFromInsertJsonFile(stbInfo, &g_Dbs.db[i].superTbls[j]); + if (false == retVal) { + goto PARSE_OVER; + } + } + } + + ret = true; + +PARSE_OVER: + //free(content); + //cJSON_Delete(root); + //fclose(fp); + return ret; +} + +static bool getMetaFromQueryJsonFile(cJSON* root) { + bool ret = false; + + cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir"); + if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) { + strncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN); + } + + cJSON* host = cJSON_GetObjectItem(root, "host"); + if (host && host->type == cJSON_String && host->valuestring != NULL) { + strncpy(g_queryInfo.host, host->valuestring, MAX_DB_NAME_SIZE); + } else if (!host) { + strncpy(g_queryInfo.host, "127.0.0.1", MAX_DB_NAME_SIZE); + } else { + printf("failed to read json, host not found\n"); + goto PARSE_OVER; + } + + cJSON* port = cJSON_GetObjectItem(root, "port"); + if (port && port->type == cJSON_Number) { + g_queryInfo.port = port->valueint; + } else if (!port) { + g_queryInfo.port = 6030; + } + + cJSON* user = cJSON_GetObjectItem(root, "user"); + if (user && user->type == cJSON_String && user->valuestring != NULL) { + strncpy(g_queryInfo.user, user->valuestring, MAX_DB_NAME_SIZE); + } else if (!user) { + strncpy(g_queryInfo.user, "root", MAX_DB_NAME_SIZE); ; + } + + cJSON* password = cJSON_GetObjectItem(root, "password"); + if (password && password->type == cJSON_String && password->valuestring != NULL) { + strncpy(g_queryInfo.password, password->valuestring, MAX_DB_NAME_SIZE); + } else if (!password) { + strncpy(g_queryInfo.password, "taosdata", MAX_DB_NAME_SIZE);; + } + + cJSON* dbs = cJSON_GetObjectItem(root, "databases"); + if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) { + strncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE); + } else if (!dbs) { + printf("failed to read json, databases not found\n"); + goto PARSE_OVER; + } + + cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode"); + if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) { + strncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE); + } else if (!queryMode) { + strncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE); + } else { + printf("failed to read json, query_mode not found\n"); + goto PARSE_OVER; + } + + // super_table_query + cJSON *superQuery = cJSON_GetObjectItem(root, "specified_table_query"); + if (!superQuery) { + g_queryInfo.superQueryInfo.concurrent = 0; + g_queryInfo.superQueryInfo.sqlCount = 0; + } else if (superQuery->type != cJSON_Object) { + printf("failed to read json, super_table_query not found"); + goto PARSE_OVER; + } else { + cJSON* rate = cJSON_GetObjectItem(superQuery, "query_interval"); + if (rate && rate->type == cJSON_Number) { + g_queryInfo.superQueryInfo.rate = rate->valueint; + } else if (!rate) { + g_queryInfo.superQueryInfo.rate = 0; + } + + cJSON* concurrent = cJSON_GetObjectItem(superQuery, "concurrent"); + if (concurrent && concurrent->type == cJSON_Number) { + g_queryInfo.superQueryInfo.concurrent = concurrent->valueint; + } else if (!concurrent) { + g_queryInfo.superQueryInfo.concurrent = 1; + } + + cJSON* mode = cJSON_GetObjectItem(superQuery, "mode"); + if (mode && mode->type == cJSON_String && mode->valuestring != NULL) { + if (0 == strcmp("sync", mode->valuestring)) { + g_queryInfo.superQueryInfo.subscribeMode = 0; + } else if (0 == strcmp("async", mode->valuestring)) { + g_queryInfo.superQueryInfo.subscribeMode = 1; + } else { + printf("failed to read json, subscribe mod error\n"); + goto PARSE_OVER; + } + } else { + g_queryInfo.superQueryInfo.subscribeMode = 0; + } + + cJSON* interval = cJSON_GetObjectItem(superQuery, "interval"); + if (interval && interval->type == cJSON_Number) { + g_queryInfo.superQueryInfo.subscribeInterval = interval->valueint; + } else if (!interval) { + //printf("failed to read json, subscribe interval no found\n"); + //goto PARSE_OVER; + g_queryInfo.superQueryInfo.subscribeInterval = 10000; + } + + cJSON* restart = cJSON_GetObjectItem(superQuery, "restart"); + if (restart && restart->type == cJSON_String && restart->valuestring != NULL) { + if (0 == strcmp("yes", restart->valuestring)) { + g_queryInfo.superQueryInfo.subscribeRestart = 1; + } else if (0 == strcmp("no", restart->valuestring)) { + g_queryInfo.superQueryInfo.subscribeRestart = 0; + } else { + printf("failed to read json, subscribe restart error\n"); + goto PARSE_OVER; + } + } else { + g_queryInfo.superQueryInfo.subscribeRestart = 1; + } + + cJSON* keepProgress = cJSON_GetObjectItem(superQuery, "keepProgress"); + if (keepProgress && keepProgress->type == cJSON_String && keepProgress->valuestring != NULL) { + if (0 == strcmp("yes", keepProgress->valuestring)) { + g_queryInfo.superQueryInfo.subscribeKeepProgress = 1; + } else if (0 == strcmp("no", keepProgress->valuestring)) { + g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; + } else { + printf("failed to read json, subscribe keepProgress error\n"); + goto PARSE_OVER; + } + } else { + g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; + } + + // sqls + cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls"); + if (!superSqls) { + g_queryInfo.superQueryInfo.sqlCount = 0; + } else if (superSqls->type != cJSON_Array) { + printf("failed to read json, super sqls not found\n"); + goto PARSE_OVER; + } else { + int superSqlSize = cJSON_GetArraySize(superSqls); + if (superSqlSize > MAX_QUERY_SQL_COUNT) { + printf("failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT); + goto PARSE_OVER; + } + + g_queryInfo.superQueryInfo.sqlCount = superSqlSize; + for (int j = 0; j < superSqlSize; ++j) { + cJSON* sql = cJSON_GetArrayItem(superSqls, j); + if (sql == NULL) continue; + + cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql"); + if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) { + printf("failed to read json, sql not found\n"); + goto PARSE_OVER; + } + strncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH); + + cJSON *result = cJSON_GetObjectItem(sql, "result"); + if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) { + strncpy(g_queryInfo.superQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN); + } else if (NULL == result) { + memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); + } else { + printf("failed to read json, super query result file not found\n"); + goto PARSE_OVER; + } + } + } + } + + // sub_table_query + cJSON *subQuery = cJSON_GetObjectItem(root, "super_table_query"); + if (!subQuery) { + g_queryInfo.subQueryInfo.threadCnt = 0; + g_queryInfo.subQueryInfo.sqlCount = 0; + } else if (subQuery->type != cJSON_Object) { + printf("failed to read json, sub_table_query not found"); + ret = true; + goto PARSE_OVER; + } else { + cJSON* subrate = cJSON_GetObjectItem(subQuery, "query_interval"); + if (subrate && subrate->type == cJSON_Number) { + g_queryInfo.subQueryInfo.rate = subrate->valueint; + } else if (!subrate) { + g_queryInfo.subQueryInfo.rate = 0; + } + + cJSON* threads = cJSON_GetObjectItem(subQuery, "threads"); + if (threads && threads->type == cJSON_Number) { + g_queryInfo.subQueryInfo.threadCnt = threads->valueint; + } else if (!threads) { + g_queryInfo.subQueryInfo.threadCnt = 1; + } + + //cJSON* subTblCnt = cJSON_GetObjectItem(subQuery, "childtable_count"); + //if (subTblCnt && subTblCnt->type == cJSON_Number) { + // g_queryInfo.subQueryInfo.childTblCount = subTblCnt->valueint; + //} else if (!subTblCnt) { + // g_queryInfo.subQueryInfo.childTblCount = 0; + //} + + cJSON* stblname = cJSON_GetObjectItem(subQuery, "stblname"); + if (stblname && stblname->type == cJSON_String && stblname->valuestring != NULL) { + strncpy(g_queryInfo.subQueryInfo.sTblName, stblname->valuestring, MAX_TB_NAME_SIZE); + } else { + printf("failed to read json, super table name not found\n"); + goto PARSE_OVER; + } + + cJSON* submode = cJSON_GetObjectItem(subQuery, "mode"); + if (submode && submode->type == cJSON_String && submode->valuestring != NULL) { + if (0 == strcmp("sync", submode->valuestring)) { + g_queryInfo.subQueryInfo.subscribeMode = 0; + } else if (0 == strcmp("async", submode->valuestring)) { + g_queryInfo.subQueryInfo.subscribeMode = 1; + } else { + printf("failed to read json, subscribe mod error\n"); + goto PARSE_OVER; + } + } else { + g_queryInfo.subQueryInfo.subscribeMode = 0; + } + + cJSON* subinterval = cJSON_GetObjectItem(subQuery, "interval"); + if (subinterval && subinterval->type == cJSON_Number) { + g_queryInfo.subQueryInfo.subscribeInterval = subinterval->valueint; + } else if (!subinterval) { + //printf("failed to read json, subscribe interval no found\n"); + //goto PARSE_OVER; + g_queryInfo.subQueryInfo.subscribeInterval = 10000; + } + + cJSON* subrestart = cJSON_GetObjectItem(subQuery, "restart"); + if (subrestart && subrestart->type == cJSON_String && subrestart->valuestring != NULL) { + if (0 == strcmp("yes", subrestart->valuestring)) { + g_queryInfo.subQueryInfo.subscribeRestart = 1; + } else if (0 == strcmp("no", subrestart->valuestring)) { + g_queryInfo.subQueryInfo.subscribeRestart = 0; + } else { + printf("failed to read json, subscribe restart error\n"); + goto PARSE_OVER; + } + } else { + g_queryInfo.subQueryInfo.subscribeRestart = 1; + } + + cJSON* subkeepProgress = cJSON_GetObjectItem(subQuery, "keepProgress"); + if (subkeepProgress && subkeepProgress->type == cJSON_String && subkeepProgress->valuestring != NULL) { + if (0 == strcmp("yes", subkeepProgress->valuestring)) { + g_queryInfo.subQueryInfo.subscribeKeepProgress = 1; + } else if (0 == strcmp("no", subkeepProgress->valuestring)) { + g_queryInfo.subQueryInfo.subscribeKeepProgress = 0; + } else { + printf("failed to read json, subscribe keepProgress error\n"); + goto PARSE_OVER; + } + } else { + g_queryInfo.subQueryInfo.subscribeKeepProgress = 0; + } + + // sqls + cJSON* subsqls = cJSON_GetObjectItem(subQuery, "sqls"); + if (!subsqls) { + g_queryInfo.subQueryInfo.sqlCount = 0; + } else if (subsqls->type != cJSON_Array) { + printf("failed to read json, super sqls not found\n"); + goto PARSE_OVER; + } else { + int superSqlSize = cJSON_GetArraySize(subsqls); + if (superSqlSize > MAX_QUERY_SQL_COUNT) { + printf("failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT); + goto PARSE_OVER; + } + + g_queryInfo.subQueryInfo.sqlCount = superSqlSize; + for (int j = 0; j < superSqlSize; ++j) { + cJSON* sql = cJSON_GetArrayItem(subsqls, j); + if (sql == NULL) continue; + + cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql"); + if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) { + printf("failed to read json, sql not found\n"); + goto PARSE_OVER; + } + strncpy(g_queryInfo.subQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH); + + cJSON *result = cJSON_GetObjectItem(sql, "result"); + if (result != NULL && result->type == cJSON_String && result->valuestring != NULL){ + strncpy(g_queryInfo.subQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN); + } else if (NULL == result) { + memset(g_queryInfo.subQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); + } else { + printf("failed to read json, sub query result file not found\n"); + goto PARSE_OVER; + } + } + } + } + + ret = true; + +PARSE_OVER: + //free(content); + //cJSON_Delete(root); + //fclose(fp); + return ret; +} + +static bool getInfoFromJsonFile(char* file) { + FILE *fp = fopen(file, "r"); + if (!fp) { + printf("failed to read %s, reason:%s\n", file, strerror(errno)); + return false; + } + + bool ret = false; + int maxLen = 64000; + char *content = calloc(1, maxLen + 1); + int len = fread(content, 1, maxLen, fp); + if (len <= 0) { + free(content); + fclose(fp); + printf("failed to read %s, content is null", file); + return false; + } + + content[len] = 0; + cJSON* root = cJSON_Parse(content); + if (root == NULL) { + printf("failed to cjson parse %s, invalid json format", file); + goto PARSE_OVER; + } + + cJSON* filetype = cJSON_GetObjectItem(root, "filetype"); + if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) { + if (0 == strcasecmp("insert", filetype->valuestring)) { + g_jsonType = INSERT_MODE; + } else if (0 == strcasecmp("query", filetype->valuestring)) { + g_jsonType = QUERY_MODE; + } else if (0 == strcasecmp("subscribe", filetype->valuestring)) { + g_jsonType = SUBSCRIBE_MODE; + } else { + printf("failed to read json, filetype not support\n"); + goto PARSE_OVER; + } + } else if (!filetype) { + g_jsonType = INSERT_MODE; + } else { + printf("failed to read json, filetype not found\n"); + goto PARSE_OVER; + } + + if (INSERT_MODE == g_jsonType) { + ret = getMetaFromInsertJsonFile(root); + } else if (QUERY_MODE == g_jsonType) { + ret = getMetaFromQueryJsonFile(root); + } else if (SUBSCRIBE_MODE == g_jsonType) { + ret = getMetaFromQueryJsonFile(root); + } else { + printf("input json file type error! please input correct file type: insert or query or subscribe\n"); + goto PARSE_OVER; + } + +PARSE_OVER: + free(content); + cJSON_Delete(root); + fclose(fp); + return ret; +} + + +void prePareSampleData() { + for (int i = 0; i < g_Dbs.dbCount; i++) { + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + //if (0 == strncasecmp(g_Dbs.db[i].superTbls[j].dataSource, "sample", 6)) { + // readSampleFromFileToMem(&g_Dbs.db[i].superTbls[j]); + //} + + if (g_Dbs.db[i].superTbls[j].tagsFile[0] != 0) { + (void)readTagFromCsvFileToMem(&g_Dbs.db[i].superTbls[j]); + } + + #ifdef TD_LOWA_CURL + if (0 == strncasecmp(g_Dbs.db[i].superTbls[j].insertMode, "restful", 8)) { + curl_global_init(CURL_GLOBAL_ALL); + } + #endif + } + } +} + +void postFreeResource() { + tmfclose(g_fpOfInsertResult); + for (int i = 0; i < g_Dbs.dbCount; i++) { + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + if (0 != g_Dbs.db[i].superTbls[j].colsOfCreatChildTable) { + free(g_Dbs.db[i].superTbls[j].colsOfCreatChildTable); + g_Dbs.db[i].superTbls[j].colsOfCreatChildTable = NULL; + } + if (0 != g_Dbs.db[i].superTbls[j].sampleDataBuf) { + free(g_Dbs.db[i].superTbls[j].sampleDataBuf); + g_Dbs.db[i].superTbls[j].sampleDataBuf = NULL; + } + if (0 != g_Dbs.db[i].superTbls[j].childTblName) { + free(g_Dbs.db[i].superTbls[j].childTblName); + g_Dbs.db[i].superTbls[j].childTblName = NULL; + } + + #ifdef TD_LOWA_CURL + if (0 == strncasecmp(g_Dbs.db[i].superTbls[j].insertMode, "restful", 8)) { + curl_global_cleanup(); + } + #endif + } + } +} + +int getRowDataFromSample(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* superTblInfo, int* sampleUsePos, FILE *fp, char* sampleBuf) { + if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) { + int ret = readSampleFromCsvFileToMem(fp, superTblInfo, sampleBuf); + if (0 != ret) { + return -1; + } + *sampleUsePos = 0; + } + + int dataLen = 0; + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp); + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%s", sampleBuf + superTblInfo->lenOfOneRow * (*sampleUsePos)); + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")"); + + (*sampleUsePos)++; + + return dataLen; +} + +int generateRowData(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* stbInfo) { + int dataLen = 0; + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp); + for (int i = 0; i < stbInfo->columnCount; i++) { + if ((0 == strncasecmp(stbInfo->columns[i].dataType, "binary", 6)) || (0 == strncasecmp(stbInfo->columns[i].dataType, "nchar", 5))) { + if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) { + printf("binary or nchar length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); + return (-1); + } + + char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1); + if (NULL == buf) { + printf("calloc failed! size:%d\n", stbInfo->columns[i].dataLen); + return (-1); + } + rand_string(buf, stbInfo->columns[i].dataLen); + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "\'%s\', ", buf); + tmfree(buf); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "int", 3)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_int()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "bigint", 6)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "float", 5)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%f, ", rand_float()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "double", 6)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%f, ", rand_double()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "smallint", 8)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_smallint()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "tinyint", 7)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_tinyint()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "bool", 4)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_bool()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "timestamp", 9)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint()); + } else { + printf("No support data type: %s\n", stbInfo->columns[i].dataType); + return (-1); + } + } + dataLen -= 2; + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")"); + + return dataLen; +} + +void syncWriteForNumberOfTblInOneSql(threadInfo *winfo, FILE *fp, char* sampleDataBuf) { + SSuperTable* superTblInfo = winfo->superTblInfo; + + int samplePos = 0; + + //printf("========threadID[%d], table rang: %d - %d \n", winfo->threadID, winfo->start_table_id, winfo->end_table_id); + int64_t totalRowsInserted = 0; + int64_t totalAffectedRows = 0; + int64_t lastPrintTime = taosGetTimestampMs(); + + char* buffer = calloc(superTblInfo->maxSqlLen+1, 1); + if (NULL == buffer) { + printf("========calloc size[ %d ] fail!\n", superTblInfo->maxSqlLen); + return; + } + + int32_t numberOfTblInOneSql = superTblInfo->numberOfTblInOneSql; + int32_t tbls = winfo->end_table_id - winfo->start_table_id + 1; + if (numberOfTblInOneSql > tbls) { + numberOfTblInOneSql = tbls; + } + + int64_t time_counter = winfo->start_time; + int64_t tmp_time; + int sampleUsePos; + + int64_t st = 0; + int64_t et = 0; + for (int i = 0; i < superTblInfo->insertRows;) { + if (superTblInfo->insertRate && (et - st) < 1000) { + taosMsleep(1000 - (et - st)); // ms + //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + } + + if (superTblInfo->insertRate) { + st = taosGetTimestampMs(); + } + + int32_t tbl_id = 0; + for (int tID = winfo->start_table_id; tID <= winfo->end_table_id; ) { + int inserted = i; + + int k = 0; + int batchRowsSql = 0; + while (1) + { + int len = 0; + memset(buffer, 0, superTblInfo->maxSqlLen); + char *pstr = buffer; + + int32_t end_tbl_id = tID + numberOfTblInOneSql; + if (end_tbl_id > winfo->end_table_id) { + end_tbl_id = winfo->end_table_id+1; + } + for (tbl_id = tID; tbl_id < end_tbl_id; tbl_id++) { + sampleUsePos = samplePos; + if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) { + char* tagsValBuf = NULL; + if (0 == superTblInfo->tagSource) { + tagsValBuf = generateTagVaulesForStb(superTblInfo); + } else { + tagsValBuf = getTagValueFromTagSample(superTblInfo, tbl_id % superTblInfo->tagSampleCount); + } + if (NULL == tagsValBuf) { + goto free_and_statistics; + } + + if (0 == len) { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, "insert into %s.%s%d using %s.%s tags %s values ", winfo->db_name, superTblInfo->childTblPrefix, tbl_id, winfo->db_name, superTblInfo->sTblName, tagsValBuf); + } else { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, " %s.%s%d using %s.%s tags %s values ", winfo->db_name, superTblInfo->childTblPrefix, tbl_id, winfo->db_name, superTblInfo->sTblName, tagsValBuf); + } + tmfree(tagsValBuf); + } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) { + if (0 == len) { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, "insert into %s.%s values ", winfo->db_name, superTblInfo->childTblName + tbl_id * TSDB_TABLE_NAME_LEN); + } else { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, " %s.%s values ", winfo->db_name, superTblInfo->childTblName + tbl_id * TSDB_TABLE_NAME_LEN); + } + } else { // pre-create child table + if (0 == len) { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, "insert into %s.%s%d values ", winfo->db_name, superTblInfo->childTblPrefix, tbl_id); + } else { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, " %s.%s%d values ", winfo->db_name, superTblInfo->childTblPrefix, tbl_id); + } + } + + tmp_time = time_counter; + for (k = 0; k < superTblInfo->rowsPerTbl;) { + int retLen = 0; + if (0 == strncasecmp(superTblInfo->dataSource, "sample", 6)) { + retLen = getRowDataFromSample(pstr + len, superTblInfo->maxSqlLen - len, tmp_time += superTblInfo->timeStampStep, superTblInfo, &sampleUsePos, fp, sampleDataBuf); + if (retLen < 0) { + goto free_and_statistics; + } + } else if (0 == strncasecmp(superTblInfo->dataSource, "rand", 8)) { + int rand_num = rand_tinyint() % 100; + if (0 != superTblInfo->disorderRatio && rand_num < superTblInfo->disorderRatio) { + int64_t d = tmp_time - rand() % superTblInfo->disorderRange; + retLen = generateRowData(pstr + len, superTblInfo->maxSqlLen - len, d, superTblInfo); + } else { + retLen = generateRowData(pstr + len, superTblInfo->maxSqlLen - len, tmp_time += superTblInfo->timeStampStep, superTblInfo); + } + if (retLen < 0) { + goto free_and_statistics; + } + } + len += retLen; + //inserted++; + k++; + totalRowsInserted++; + batchRowsSql++; + + if (inserted >= superTblInfo->insertRows || (superTblInfo->maxSqlLen - len) < (superTblInfo->lenOfOneRow + 128) || batchRowsSql >= INT16_MAX - 1) { + tID = tbl_id + 1; + printf("config rowsPerTbl and numberOfTblInOneSql not match with max_sql_lenth, please reconfig![lenOfOneRow:%d]\n", superTblInfo->lenOfOneRow); + goto send_to_server; + } + } + + } + + tID = tbl_id; + inserted += superTblInfo->rowsPerTbl; + + send_to_server: + batchRowsSql = 0; + if (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5)) { + //printf("multi table===== sql: %s \n\n", buffer); + //int64_t t1 = taosGetTimestampMs(); + int affectedRows = queryDbExec(winfo->taos, buffer, INSERT_TYPE); + if (0 > affectedRows) { + goto free_and_statistics; + } + totalAffectedRows += affectedRows; + + int64_t currentPrintTime = taosGetTimestampMs(); + if (currentPrintTime - lastPrintTime > 30*1000) { + printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n", winfo->threadID, totalRowsInserted, totalAffectedRows); + lastPrintTime = currentPrintTime; + } + //int64_t t2 = taosGetTimestampMs(); + //printf("taosc insert sql return, Spent %.4f seconds \n", (double)(t2 - t1)/1000.0); + } else { + #ifdef TD_LOWA_CURL + //int64_t t1 = taosGetTimestampMs(); + int retCode = curlProceSql(g_Dbs.host, g_Dbs.port, buffer, winfo->curl_handle); + //int64_t t2 = taosGetTimestampMs(); + //printf("http insert sql return, Spent %ld ms \n", t2 - t1); + + if (0 != retCode) { + printf("========curl return fail, threadID[%d]\n", winfo->threadID); + goto free_and_statistics; + } + #else + printf("========no use http mode for no curl lib!\n"); + goto free_and_statistics; + #endif + } + + //printf("========tID:%d, k:%d, loop_cnt:%d\n", tID, k, loop_cnt); + break; + } + + if (tID > winfo->end_table_id) { + if (0 == strncasecmp(superTblInfo->dataSource, "sample", 6)) { + samplePos = sampleUsePos; + } + i = inserted; + time_counter = tmp_time; + } + } + + if (superTblInfo->insertRate) { + et = taosGetTimestampMs(); + } + //printf("========loop %d childTables duration:%"PRId64 "========inserted rows:%d\n", winfo->end_table_id - winfo->start_table_id, et - st, i); + } + + free_and_statistics: + tmfree(buffer); + winfo->totalRowsInserted = totalRowsInserted; + winfo->totalAffectedRows = totalAffectedRows; + printf("====thread[%d] completed total inserted rows: %"PRId64 ", affected rows: %"PRId64 "====\n", winfo->threadID, totalRowsInserted, totalAffectedRows); + return; +} + +// sync insertion +/* + 1 thread: 100 tables * 2000 rows/s + 1 thread: 10 tables * 20000 rows/s + 6 thread: 300 tables * 2000 rows/s + + 2 taosinsertdata , 1 thread: 10 tables * 20000 rows/s +*/ +void *syncWrite(void *sarg) { + int64_t totalRowsInserted = 0; + int64_t totalAffectedRows = 0; + int64_t lastPrintTime = taosGetTimestampMs(); + + threadInfo *winfo = (threadInfo *)sarg; + SSuperTable* superTblInfo = winfo->superTblInfo; + + FILE *fp = NULL; + char* sampleDataBuf = NULL; + int samplePos = 0; + + // each thread read sample data from csv file + if (0 == strncasecmp(superTblInfo->dataSource, "sample", 6)) { + sampleDataBuf = calloc(superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1); + if (sampleDataBuf == NULL) { + printf("Failed to calloc %d Bytes, reason:%s\n", superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, strerror(errno)); + return NULL; + } + + fp = fopen(superTblInfo->sampleFile, "r"); + if (fp == NULL) { + printf("Failed to open sample file: %s, reason:%s\n", superTblInfo->sampleFile, strerror(errno)); + tmfree(sampleDataBuf); + return NULL; + } + int ret = readSampleFromCsvFileToMem(fp, superTblInfo, sampleDataBuf); + if (0 != ret) { + tmfree(sampleDataBuf); + tmfclose(fp); + return NULL; + } + } + + if (superTblInfo->numberOfTblInOneSql > 0) { + syncWriteForNumberOfTblInOneSql(winfo, fp, sampleDataBuf); + tmfree(sampleDataBuf); + tmfclose(fp); + return NULL; + } + + //printf("========threadID[%d], table rang: %d - %d \n", winfo->threadID, winfo->start_table_id, winfo->end_table_id); + + char* buffer = calloc(superTblInfo->maxSqlLen, 1); + + int nrecords_per_request = 0; + if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) { + nrecords_per_request = (superTblInfo->maxSqlLen - 1280 - superTblInfo->lenOfTagOfOneRow) / superTblInfo->lenOfOneRow; + } else { + nrecords_per_request = (superTblInfo->maxSqlLen - 1280) / superTblInfo->lenOfOneRow; + } + + int nrecords_no_last_req = nrecords_per_request; + int nrecords_last_req = 0; + int loop_cnt = 0; + if (0 != superTblInfo->insertRate) { + if (nrecords_no_last_req >= superTblInfo->insertRate) { + nrecords_no_last_req = superTblInfo->insertRate; + } else { + nrecords_last_req = superTblInfo->insertRate % nrecords_per_request; + loop_cnt = (superTblInfo->insertRate / nrecords_per_request) + (superTblInfo->insertRate % nrecords_per_request ? 1 : 0) ; + } + } + + if (nrecords_no_last_req <= 0) { + nrecords_no_last_req = 1; + } + + if (nrecords_no_last_req >= INT16_MAX) { + nrecords_no_last_req = INT16_MAX - 1; + } + + if (nrecords_last_req >= INT16_MAX) { + nrecords_last_req = INT16_MAX - 1; + } + + int nrecords_cur_req = nrecords_no_last_req; + int loop_cnt_orig = loop_cnt; + + //printf("========nrecords_per_request:%d, nrecords_no_last_req:%d, nrecords_last_req:%d, loop_cnt:%d\n", nrecords_per_request, nrecords_no_last_req, nrecords_last_req, loop_cnt); + + int64_t time_counter = winfo->start_time; + + int64_t st = 0; + int64_t et = 0; + for (int i = 0; i < superTblInfo->insertRows;) { + if (superTblInfo->insertRate && (et - st) < 1000) { + taosMsleep(1000 - (et - st)); // ms + //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + } + + if (superTblInfo->insertRate) { + st = taosGetTimestampMs(); + } + + for (int tID = winfo->start_table_id; tID <= winfo->end_table_id; tID++) { + int inserted = i; + int64_t tmp_time = time_counter; + + int sampleUsePos = samplePos; + int k = 0; + while (1) + { + int len = 0; + memset(buffer, 0, superTblInfo->maxSqlLen); + char *pstr = buffer; + + if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) { + char* tagsValBuf = NULL; + if (0 == superTblInfo->tagSource) { + tagsValBuf = generateTagVaulesForStb(superTblInfo); + } else { + tagsValBuf = getTagValueFromTagSample(superTblInfo, tID % superTblInfo->tagSampleCount); + } + if (NULL == tagsValBuf) { + goto free_and_statistics_2; + } + + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, "insert into %s.%s%d using %s.%s tags %s values", winfo->db_name, superTblInfo->childTblPrefix, tID, winfo->db_name, superTblInfo->sTblName, tagsValBuf); + tmfree(tagsValBuf); + } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, "insert into %s.%s values", winfo->db_name, superTblInfo->childTblName + tID * TSDB_TABLE_NAME_LEN); + } else { + len += snprintf(pstr + len, superTblInfo->maxSqlLen - len, "insert into %s.%s%d values", winfo->db_name, superTblInfo->childTblPrefix, tID); + } + + for (k = 0; k < nrecords_cur_req;) { + int retLen = 0; + if (0 == strncasecmp(superTblInfo->dataSource, "sample", 6)) { + retLen = getRowDataFromSample(pstr + len, superTblInfo->maxSqlLen - len, tmp_time += superTblInfo->timeStampStep, superTblInfo, &sampleUsePos, fp, sampleDataBuf); + if (retLen < 0) { + goto free_and_statistics_2; + } + } else if (0 == strncasecmp(superTblInfo->dataSource, "rand", 8)) { + int rand_num = rand_tinyint() % 100; + if (0 != superTblInfo->disorderRatio && rand_num < superTblInfo->disorderRatio) { + int64_t d = tmp_time - rand() % superTblInfo->disorderRange; + retLen = generateRowData(pstr + len, superTblInfo->maxSqlLen - len, d, superTblInfo); + //printf("disorder rows, rand_num:%d, last ts:%"PRId64" current ts:%"PRId64"\n", rand_num, tmp_time, d); + } else { + retLen = generateRowData(pstr + len, superTblInfo->maxSqlLen - len, tmp_time += superTblInfo->timeStampStep, superTblInfo); + } + if (retLen < 0) { + goto free_and_statistics_2; + } + } + len += retLen; + inserted++; + k++; + totalRowsInserted++; + + if (inserted >= superTblInfo->insertRows || (superTblInfo->maxSqlLen - len) < (superTblInfo->lenOfOneRow + 128)) break; + } + + if (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5)) { + //printf("===== sql: %s \n\n", buffer); + //int64_t t1 = taosGetTimestampMs(); + int affectedRows = queryDbExec(winfo->taos, buffer, INSERT_TYPE); + if (0 > affectedRows){ + goto free_and_statistics_2; + } + totalAffectedRows += affectedRows; + + int64_t currentPrintTime = taosGetTimestampMs(); + if (currentPrintTime - lastPrintTime > 30*1000) { + printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n", winfo->threadID, totalRowsInserted, totalAffectedRows); + lastPrintTime = currentPrintTime; + } + //int64_t t2 = taosGetTimestampMs(); + //printf("taosc insert sql return, Spent %.4f seconds \n", (double)(t2 - t1)/1000.0); + } else { + #ifdef TD_LOWA_CURL + //int64_t t1 = taosGetTimestampMs(); + int retCode = curlProceSql(g_Dbs.host, g_Dbs.port, buffer, winfo->curl_handle); + //int64_t t2 = taosGetTimestampMs(); + //printf("http insert sql return, Spent %ld ms \n", t2 - t1); + + if (0 != retCode) { + printf("========curl return fail, threadID[%d]\n", winfo->threadID); + goto free_and_statistics_2; + } + #else + printf("========no use http mode for no curl lib!\n"); + goto free_and_statistics_2; + #endif + } + + //printf("========tID:%d, k:%d, loop_cnt:%d\n", tID, k, loop_cnt); + + if (loop_cnt) { + loop_cnt--; + if ((1 == loop_cnt) && (0 != nrecords_last_req)) { + nrecords_cur_req = nrecords_last_req; + } else if (0 == loop_cnt){ + nrecords_cur_req = nrecords_no_last_req; + loop_cnt = loop_cnt_orig; + break; + } + } else { + break; + } + } + + if (tID == winfo->end_table_id) { + if (0 == strncasecmp(superTblInfo->dataSource, "sample", 6)) { + samplePos = sampleUsePos; + } + i = inserted; + time_counter = tmp_time; + } + } + + if (superTblInfo->insertRate) { + et = taosGetTimestampMs(); + } + //printf("========loop %d childTables duration:%"PRId64 "========inserted rows:%d\n", winfo->end_table_id - winfo->start_table_id, et - st, i); + } + + free_and_statistics_2: + tmfree(buffer); + tmfree(sampleDataBuf); + tmfclose(fp); + + winfo->totalRowsInserted = totalRowsInserted; + winfo->totalAffectedRows = totalAffectedRows; + + printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", winfo->threadID, totalRowsInserted, totalAffectedRows); + return NULL; +} + +void callBack(void *param, TAOS_RES *res, int code) { + threadInfo* winfo = (threadInfo*)param; + + if (winfo->superTblInfo->insertRate) { + winfo->et = taosGetTimestampMs(); + if (winfo->et - winfo->st < 1000) { + taosMsleep(1000 - (winfo->et - winfo->st)); // ms + } + } + + char *buffer = calloc(1, winfo->superTblInfo->maxSqlLen); + char *data = calloc(1, MAX_DATA_SIZE); + char *pstr = buffer; + pstr += sprintf(pstr, "insert into %s.%s%d values", winfo->db_name, winfo->tb_prefix, winfo->start_table_id); + if (winfo->counter >= winfo->superTblInfo->insertRows) { + winfo->start_table_id++; + winfo->counter = 0; + } + if (winfo->start_table_id > winfo->end_table_id) { + tsem_post(&winfo->lock_sem); + free(buffer); + free(data); + taos_free_result(res); + return; + } + + for (int i = 0; i < winfo->nrecords_per_request; i++) { + int rand_num = rand() % 100; + if (0 != winfo->superTblInfo->disorderRatio && rand_num < winfo->superTblInfo->disorderRatio) + { + int64_t d = winfo->lastTs - rand() % 1000000 + rand_num; + //generateData(data, datatype, ncols_per_record, d, len_of_binary); + (void)generateRowData(data, MAX_DATA_SIZE, d, winfo->superTblInfo); + } else { + //generateData(data, datatype, ncols_per_record, tmp_time += 1000, len_of_binary); + (void)generateRowData(data, MAX_DATA_SIZE, winfo->lastTs += 1000, winfo->superTblInfo); + } + pstr += sprintf(pstr, "%s", data); + winfo->counter++; + + if (winfo->counter >= winfo->superTblInfo->insertRows) { + break; + } + } + + if (winfo->superTblInfo->insertRate) { + winfo->st = taosGetTimestampMs(); + } + taos_query_a(winfo->taos, buffer, callBack, winfo); + free(buffer); + free(data); + + taos_free_result(res); +} + +void *asyncWrite(void *sarg) { + threadInfo *winfo = (threadInfo *)sarg; + + winfo->nrecords_per_request = 0; + //if (AUTO_CREATE_SUBTBL == winfo->superTblInfo->autoCreateTable) { + winfo->nrecords_per_request = (winfo->superTblInfo->maxSqlLen - 1280 - winfo->superTblInfo->lenOfTagOfOneRow) / winfo->superTblInfo->lenOfOneRow; + //} else { + // winfo->nrecords_per_request = (winfo->superTblInfo->maxSqlLen - 1280) / winfo->superTblInfo->lenOfOneRow; + //} + + if (0 != winfo->superTblInfo->insertRate) { + if (winfo->nrecords_per_request >= winfo->superTblInfo->insertRate) { + winfo->nrecords_per_request = winfo->superTblInfo->insertRate; + } + } + + if (winfo->nrecords_per_request <= 0) { + winfo->nrecords_per_request = 1; + } + + if (winfo->nrecords_per_request >= INT16_MAX) { + winfo->nrecords_per_request = INT16_MAX - 1; + } + + if (winfo->nrecords_per_request >= INT16_MAX) { + winfo->nrecords_per_request = INT16_MAX - 1; + } + + winfo->st = 0; + winfo->et = 0; + winfo->lastTs = winfo->start_time; + + if (winfo->superTblInfo->insertRate) { + winfo->st = taosGetTimestampMs(); + } + taos_query_a(winfo->taos, "show databases", callBack, winfo); + + tsem_wait(&(winfo->lock_sem)); + + return NULL; +} + +void startMultiThreadInsertData(int threads, char* db_name, char* precision, SSuperTable* superTblInfo) { + pthread_t *pids = malloc(threads * sizeof(pthread_t)); + threadInfo *infos = malloc(threads * sizeof(threadInfo)); + memset(pids, 0, threads * sizeof(pthread_t)); + memset(infos, 0, threads * sizeof(threadInfo)); + int ntables = superTblInfo->childTblCount; + + int a = ntables / threads; + if (a < 1) { + threads = ntables; + a = 1; + } + + int b = 0; + if (threads != 0) { + b = ntables % threads; + } + + TAOS* taos; + if (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5)) { + taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, db_name, g_Dbs.port); + if (NULL == taos) { + printf("connect to server fail, reason: %s\n", taos_errstr(NULL)); + exit(-1); + } + } + + int32_t timePrec = TSDB_TIME_PRECISION_MILLI; + if (0 != precision[0]) { + if (0 == strncasecmp(precision, "ms", 2)) { + timePrec = TSDB_TIME_PRECISION_MILLI; + } else if (0 == strncasecmp(precision, "us", 2)) { + timePrec = TSDB_TIME_PRECISION_MICRO; + } else { + printf("No support precision: %s\n", precision); + exit(-1); + } + } + + int64_t start_time; + if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) { + start_time = taosGetTimestamp(timePrec); + } else { + (void)taosParseTime(superTblInfo->startTimestamp, &start_time, strlen(superTblInfo->startTimestamp), timePrec, 0); + } + + double start = getCurrentTime(); + + int last = 0; + for (int i = 0; i < threads; i++) { + threadInfo *t_info = infos + i; + t_info->threadID = i; + tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE); + t_info->superTblInfo = superTblInfo; + + t_info->start_time = start_time; + + if (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5)) { + t_info->taos = taos; + } else { + t_info->taos = NULL; + #ifdef TD_LOWA_CURL + t_info->curl_handle = curl_easy_init(); + #endif + } + + if (0 == superTblInfo->multiThreadWriteOneTbl) { + t_info->start_table_id = last; + t_info->end_table_id = i < b ? last + a : last + a - 1; + last = t_info->end_table_id + 1; + } else { + t_info->start_table_id = 0; + t_info->end_table_id = superTblInfo->childTblCount - 1; + t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint(); + } + + tsem_init(&(t_info->lock_sem), 0, 0); + + if (SYNC == g_Dbs.queryMode) { + pthread_create(pids + i, NULL, syncWrite, t_info); + } else { + pthread_create(pids + i, NULL, asyncWrite, t_info); + } + } + + for (int i = 0; i < threads; i++) { + pthread_join(pids[i], NULL); + } + + for (int i = 0; i < threads; i++) { + threadInfo *t_info = infos + i; + + tsem_destroy(&(t_info->lock_sem)); + + superTblInfo->totalAffectedRows += t_info->totalAffectedRows; + superTblInfo->totalRowsInserted += t_info->totalRowsInserted; + #ifdef TD_LOWA_CURL + if (t_info->curl_handle) { + curl_easy_cleanup(t_info->curl_handle); + } + #endif + } + + double end = getCurrentTime(); + + taos_close(taos); + + free(pids); + free(infos); + + printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s\n\n", + end - start, superTblInfo->totalRowsInserted, superTblInfo->totalAffectedRows, threads, db_name, superTblInfo->sTblName); + fprintf(g_fpOfInsertResult, "Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s\n\n", + end - start, superTblInfo->totalRowsInserted, superTblInfo->totalAffectedRows, threads, db_name, superTblInfo->sTblName); +} + + +void *readTable(void *sarg) { +#if 1 + threadInfo *rinfo = (threadInfo *)sarg; + TAOS *taos = rinfo->taos; + char command[BUFFER_SIZE] = "\0"; + int64_t sTime = rinfo->start_time; + char *tb_prefix = rinfo->tb_prefix; + FILE *fp = fopen(rinfo->fp, "a"); + if (NULL == fp) { + printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno)); + return NULL; + } + + int num_of_DPT = rinfo->superTblInfo->insertRows; // nrecords_per_table; + int num_of_tables = rinfo->end_table_id - rinfo->start_table_id + 1; + int totalData = num_of_DPT * num_of_tables; + bool do_aggreFunc = g_Dbs.do_aggreFunc; + + int n = do_aggreFunc ? (sizeof(aggreFunc) / sizeof(aggreFunc[0])) : 2; + if (!do_aggreFunc) { + printf("\nThe first field is either Binary or Bool. Aggregation functions are not supported.\n"); + } + printf("%d records:\n", totalData); + fprintf(fp, "| QFunctions | QRecords | QSpeed(R/s) | QLatency(ms) |\n"); + + for (int j = 0; j < n; j++) { + double totalT = 0; + int count = 0; + for (int i = 0; i < num_of_tables; i++) { + sprintf(command, "select %s from %s%d where ts>= %" PRId64, aggreFunc[j], tb_prefix, i, sTime); + + double t = getCurrentTime(); + TAOS_RES *pSql = taos_query(taos, command); + int32_t code = taos_errno(pSql); + + if (code != 0) { + fprintf(stderr, "Failed to query:%s\n", taos_errstr(pSql)); + taos_free_result(pSql); + taos_close(taos); + return NULL; + } + + while (taos_fetch_row(pSql) != NULL) { + count++; + } + + t = getCurrentTime() - t; + totalT += t; + + taos_free_result(pSql); + } + + fprintf(fp, "|%10s | %10d | %12.2f | %10.2f |\n", + aggreFunc[j][0] == '*' ? " * " : aggreFunc[j], totalData, + (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000); + printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT); + } + fprintf(fp, "\n"); + fclose(fp); +#endif + return NULL; +} + +void *readMetric(void *sarg) { +#if 1 + threadInfo *rinfo = (threadInfo *)sarg; + TAOS *taos = rinfo->taos; + char command[BUFFER_SIZE] = "\0"; + FILE *fp = fopen(rinfo->fp, "a"); + if (NULL == fp) { + printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno)); + return NULL; + } + + int num_of_DPT = rinfo->superTblInfo->insertRows; + int num_of_tables = rinfo->end_table_id - rinfo->start_table_id + 1; + int totalData = num_of_DPT * num_of_tables; + bool do_aggreFunc = g_Dbs.do_aggreFunc; + + int n = do_aggreFunc ? (sizeof(aggreFunc) / sizeof(aggreFunc[0])) : 2; + if (!do_aggreFunc) { + printf("\nThe first field is either Binary or Bool. Aggregation functions are not supported.\n"); + } + printf("%d records:\n", totalData); + fprintf(fp, "Querying On %d records:\n", totalData); + + for (int j = 0; j < n; j++) { + char condition[BUFFER_SIZE - 30] = "\0"; + char tempS[64] = "\0"; + + int m = 10 < num_of_tables ? 10 : num_of_tables; + + for (int i = 1; i <= m; i++) { + if (i == 1) { + sprintf(tempS, "t1 = %d", i); + } else { + sprintf(tempS, " or t1 = %d ", i); + } + strcat(condition, tempS); + + sprintf(command, "select %s from meters where %s", aggreFunc[j], condition); + + printf("Where condition: %s\n", condition); + fprintf(fp, "%s\n", command); + + double t = getCurrentTime(); + + TAOS_RES *pSql = taos_query(taos, command); + int32_t code = taos_errno(pSql); + + if (code != 0) { + fprintf(stderr, "Failed to query:%s\n", taos_errstr(pSql)); + taos_free_result(pSql); + taos_close(taos); + return NULL; + } + int count = 0; + while (taos_fetch_row(pSql) != NULL) { + count++; + } + t = getCurrentTime() - t; + + fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n", num_of_tables * num_of_DPT / t, t * 1000); + printf("select %10s took %.6f second(s)\n\n", aggreFunc[j], t); + + taos_free_result(pSql); + } + fprintf(fp, "\n"); + } + fclose(fp); +#endif + return NULL; +} + + +int insertTestProcess() { + + g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a"); + if (NULL == g_fpOfInsertResult) { + fprintf(stderr, "Failed to open %s for save result\n", g_Dbs.resultFile); + return 1; + }; + + printfInsertMeta(); + printfInsertMetaToFile(g_fpOfInsertResult); + + printf("Press enter key to continue\n\n"); + (void)getchar(); + + init_rand_data(); + + // create database and super tables + (void)createDatabases(); + + // pretreatement + prePareSampleData(); + + double start; + double end; + + // create child tables + start = getCurrentTime(); + createChildTables(); + end = getCurrentTime(); + if (g_totalChildTables > 0) { + printf("Spent %.4f seconds to create %d tables with %d thread(s)\n\n", end - start, g_totalChildTables, g_Dbs.threadCount); + fprintf(g_fpOfInsertResult, "Spent %.4f seconds to create %d tables with %d thread(s)\n\n", end - start, g_totalChildTables, g_Dbs.threadCount); + } + + usleep(1000*1000); + + // create sub threads for inserting data + //start = getCurrentTime(); + for (int i = 0; i < g_Dbs.dbCount; i++) { + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + SSuperTable* superTblInfo = &g_Dbs.db[i].superTbls[j]; + startMultiThreadInsertData(g_Dbs.threadCount, g_Dbs.db[i].dbName, g_Dbs.db[i].dbCfg.precision, superTblInfo); + } + } + //end = getCurrentTime(); + + //int64_t totalRowsInserted = 0; + //int64_t totalAffectedRows = 0; + //for (int i = 0; i < g_Dbs.dbCount; i++) { + // for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + // totalRowsInserted += g_Dbs.db[i].superTbls[j].totalRowsInserted; + // totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows; + //} + //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalRowsInserted, totalAffectedRows, g_Dbs.threadCount); + if (NULL == g_args.metaFile && false == g_Dbs.insert_only) { + // query data + pthread_t read_id; + threadInfo *rInfo = malloc(sizeof(threadInfo)); + rInfo->start_time = 1500000000000; // 2017-07-14 10:40:00.000 + rInfo->start_table_id = 0; + rInfo->end_table_id = g_Dbs.db[0].superTbls[0].childTblCount - 1; + //rInfo->do_aggreFunc = g_Dbs.do_aggreFunc; + //rInfo->nrecords_per_table = g_Dbs.db[0].superTbls[0].insertRows; + rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0]; + rInfo->taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, g_Dbs.db[0].dbName, g_Dbs.port); + strcpy(rInfo->tb_prefix, g_Dbs.db[0].superTbls[0].childTblPrefix); + strcpy(rInfo->fp, g_Dbs.resultFile); + + if (!g_Dbs.use_metric) { + pthread_create(&read_id, NULL, readTable, rInfo); + } else { + pthread_create(&read_id, NULL, readMetric, rInfo); + } + pthread_join(read_id, NULL); + taos_close(rInfo->taos); + } + + postFreeResource(); + + return 0; +} + +void *superQueryProcess(void *sarg) { + threadInfo *winfo = (threadInfo *)sarg; + + //char sqlStr[MAX_TB_NAME_SIZE*2]; + //sprintf(sqlStr, "use %s", g_queryInfo.dbName); + //queryDB(winfo->taos, sqlStr); + + int64_t st = 0; + int64_t et = 0; + while (1) { + if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) { + taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms + //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + } + + st = taosGetTimestampMs(); + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) { + int64_t t1 = taosGetTimestampUs(); + selectAndGetResult(winfo->taos, g_queryInfo.superQueryInfo.sql[i], g_queryInfo.superQueryInfo.result[i]); + int64_t t2 = taosGetTimestampUs(); + printf("taosc select sql return, Spent %f s\n", (t2 - t1)/1000000.0); + } else { + #ifdef TD_LOWA_CURL + int64_t t1 = taosGetTimestampUs(); + int retCode = curlProceSql(g_queryInfo.host, g_queryInfo.port, g_queryInfo.superQueryInfo.sql[i], winfo->curl_handle); + int64_t t2 = taosGetTimestampUs(); + printf("http select sql return, Spent %f s \n", (t2 - t1)/1000000.0); + + if (0 != retCode) { + printf("========curl return fail, threadID[%d]\n", winfo->threadID); + return NULL; + } + #endif + } + } + et = taosGetTimestampMs(); + printf("========thread[%"PRIu64"] complete all sqls to super table once queries duration:%.6fs\n\n", (uint64_t)pthread_self(), (double)(et - st)/1000.0); + } + return NULL; +} + +void replaceSubTblName(char* inSql, char* outSql, int tblIndex) { + char sourceString[32] = "xxxx"; + char subTblName[MAX_TB_NAME_SIZE*3]; + sprintf(subTblName, "%s.%s", g_queryInfo.dbName, g_queryInfo.subQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN); + + //printf("inSql: %s\n", inSql); + + char* pos = strstr(inSql, sourceString); + if (0 == pos) { + return; + } + + strncpy(outSql, inSql, pos - inSql); + //printf("1: %s\n", outSql); + strcat(outSql, subTblName); + //printf("2: %s\n", outSql); + strcat(outSql, pos+strlen(sourceString)); + //printf("3: %s\n", outSql); +} + +void *subQueryProcess(void *sarg) { + char sqlstr[1024]; + threadInfo *winfo = (threadInfo *)sarg; + int64_t st = 0; + int64_t et = 0; + while (1) { + if (g_queryInfo.subQueryInfo.rate && (et - st) < g_queryInfo.subQueryInfo.rate*1000) { + taosMsleep(g_queryInfo.subQueryInfo.rate*1000 - (et - st)); // ms + //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + } + + st = taosGetTimestampMs(); + for (int i = winfo->start_table_id; i <= winfo->end_table_id; i++) { + for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { + memset(sqlstr,0,sizeof(sqlstr)); + replaceSubTblName(g_queryInfo.subQueryInfo.sql[i], sqlstr, i); + selectAndGetResult(winfo->taos, sqlstr, g_queryInfo.subQueryInfo.result[i]); + } + } + et = taosGetTimestampMs(); + printf("========thread[%"PRIu64"] complete all sqls to allocate all sub-tables once queries duration:%.4fs\n\n", (uint64_t)pthread_self(), (double)(et - st)/1000.0); + } + return NULL; +} + +int queryTestProcess() { + printfQueryMeta(); + + printf("Press enter key to continue\n\n"); + (void)getchar(); + + TAOS * taos = NULL; + taos_init(); + taos = taos_connect(g_queryInfo.host, g_queryInfo.user, g_queryInfo.password, g_queryInfo.dbName, g_queryInfo.port); + if (taos == NULL) { + fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + exit(-1); + } + + if (0 != g_queryInfo.subQueryInfo.sqlCount) { + (void)getAllChildNameOfSuperTable(taos, g_queryInfo.dbName, g_queryInfo.subQueryInfo.sTblName, &g_queryInfo.subQueryInfo.childTblName, &g_queryInfo.subQueryInfo.childTblCount); + } + + pthread_t *pids = NULL; + threadInfo *infos = NULL; + //==== create sub threads for query from super table + if (g_queryInfo.superQueryInfo.sqlCount > 0 && g_queryInfo.superQueryInfo.concurrent > 0) { + + pids = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t)); + infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo)); + if ((NULL == pids) || (NULL == infos)) { + printf("malloc failed for create threads\n"); + taos_close(taos); + exit(-1); + } + + for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + threadInfo *t_info = infos + i; + t_info->threadID = i; + + if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) { + t_info->taos = taos; + + char sqlStr[MAX_TB_NAME_SIZE*2]; + sprintf(sqlStr, "use %s", g_queryInfo.dbName); + (void)queryDbExec(t_info->taos, sqlStr, NO_INSERT_TYPE); + } else { + t_info->taos = NULL; + #ifdef TD_LOWA_CURL + t_info->curl_handle = curl_easy_init(); + #endif + } + + pthread_create(pids + i, NULL, superQueryProcess, t_info); + } + }else { + g_queryInfo.superQueryInfo.concurrent = 0; + } + + pthread_t *pidsOfSub = NULL; + threadInfo *infosOfSub = NULL; + //==== create sub threads for query from sub table + if ((g_queryInfo.subQueryInfo.sqlCount > 0) && (g_queryInfo.subQueryInfo.threadCnt > 0)) { + pidsOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(pthread_t)); + infosOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(threadInfo)); + if ((NULL == pidsOfSub) || (NULL == infosOfSub)) { + printf("malloc failed for create threads\n"); + taos_close(taos); + exit(-1); + } + + int ntables = g_queryInfo.subQueryInfo.childTblCount; + int threads = g_queryInfo.subQueryInfo.threadCnt; + + int a = ntables / threads; + if (a < 1) { + threads = ntables; + a = 1; + } + + int b = 0; + if (threads != 0) { + b = ntables % threads; + } + + int last = 0; + for (int i = 0; i < threads; i++) { + threadInfo *t_info = infosOfSub + i; + t_info->threadID = i; + + t_info->start_table_id = last; + t_info->end_table_id = i < b ? last + a : last + a - 1; + t_info->taos = taos; + pthread_create(pidsOfSub + i, NULL, subQueryProcess, t_info); + } + + g_queryInfo.subQueryInfo.threadCnt = threads; + }else { + g_queryInfo.subQueryInfo.threadCnt = 0; + } + + for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + pthread_join(pids[i], NULL); + } + + tmfree((char*)pids); + tmfree((char*)infos); + + for (int i = 0; i < g_queryInfo.subQueryInfo.threadCnt; i++) { + pthread_join(pidsOfSub[i], NULL); + } + + tmfree((char*)pidsOfSub); + tmfree((char*)infosOfSub); + + taos_close(taos); + return 0; +} + +static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) { + if (res == NULL || taos_errno(res) != 0) { + printf("failed to subscribe result, code:%d, reason:%s\n", code, taos_errstr(res)); + return; + } + + getResult(res, (char*)param); + taos_free_result(res); +} + +static TAOS_SUB* subscribeImpl(TAOS *taos, char *sql, char* topic, char* resultFileName) { + TAOS_SUB* tsub = NULL; + + if (g_queryInfo.superQueryInfo.subscribeMode) { + tsub = taos_subscribe(taos, g_queryInfo.superQueryInfo.subscribeRestart, topic, sql, subscribe_callback, (void*)resultFileName, g_queryInfo.superQueryInfo.subscribeInterval); + } else { + tsub = taos_subscribe(taos, g_queryInfo.superQueryInfo.subscribeRestart, topic, sql, NULL, NULL, 0); + } + + if (tsub == NULL) { + printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql); + return NULL; + } + + return tsub; +} + +void *subSubscribeProcess(void *sarg) { + threadInfo *winfo = (threadInfo *)sarg; + char subSqlstr[1024]; + + char sqlStr[MAX_TB_NAME_SIZE*2]; + sprintf(sqlStr, "use %s", g_queryInfo.dbName); + if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE)){ + return NULL; + } + + //int64_t st = 0; + //int64_t et = 0; + do { + //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) { + // taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms + // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + //} + + //st = taosGetTimestampMs(); + char topic[32] = {0}; + for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { + sprintf(topic, "taosdemo-subscribe-%d", i); + memset(subSqlstr,0,sizeof(subSqlstr)); + replaceSubTblName(g_queryInfo.subQueryInfo.sql[i], subSqlstr, i); + g_queryInfo.subQueryInfo.tsub[i] = subscribeImpl(winfo->taos, subSqlstr, topic, g_queryInfo.subQueryInfo.result[i]); + if (NULL == g_queryInfo.subQueryInfo.tsub[i]) { + return NULL; + } + } + //et = taosGetTimestampMs(); + //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", pthread_self(), (double)(et - st)/1000.0); + } while (0); + + // start loop to consume result + while (1) { + for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { + if (1 == g_queryInfo.subQueryInfo.subscribeMode) { + continue; + } + + TAOS_RES* res = taos_consume(g_queryInfo.subQueryInfo.tsub[i]); + if (res) { + getResult(res, g_queryInfo.subQueryInfo.result[i]); + taos_free_result(res); + } + } + } + + for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { + taos_unsubscribe(g_queryInfo.subQueryInfo.tsub[i], g_queryInfo.subQueryInfo.subscribeKeepProgress); + } + return NULL; +} + +void *superSubscribeProcess(void *sarg) { + threadInfo *winfo = (threadInfo *)sarg; + + char sqlStr[MAX_TB_NAME_SIZE*2]; + sprintf(sqlStr, "use %s", g_queryInfo.dbName); + if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE)) { + return NULL; + } + + //int64_t st = 0; + //int64_t et = 0; + do { + //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) { + // taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms + // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + //} + + //st = taosGetTimestampMs(); + char topic[32] = {0}; + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + sprintf(topic, "taosdemo-subscribe-%d", i); + g_queryInfo.superQueryInfo.tsub[i] = subscribeImpl(winfo->taos, g_queryInfo.superQueryInfo.sql[i], topic, g_queryInfo.superQueryInfo.result[i]); + if (NULL == g_queryInfo.superQueryInfo.tsub[i]) { + return NULL; + } + } + //et = taosGetTimestampMs(); + //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", pthread_self(), (double)(et - st)/1000.0); + } while (0); + + // start loop to consume result + while (1) { + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + if (1 == g_queryInfo.superQueryInfo.subscribeMode) { + continue; + } + + TAOS_RES* res = taos_consume(g_queryInfo.superQueryInfo.tsub[i]); + if (res) { + getResult(res, g_queryInfo.superQueryInfo.result[i]); + taos_free_result(res); + } + } + } + + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + taos_unsubscribe(g_queryInfo.superQueryInfo.tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress); + } + return NULL; +} + +int subscribeTestProcess() { + printfQueryMeta(); + + printf("Press enter key to continue\n\n"); + (void)getchar(); + + TAOS * taos = NULL; + taos_init(); + taos = taos_connect(g_queryInfo.host, g_queryInfo.user, g_queryInfo.password, g_queryInfo.dbName, g_queryInfo.port); + if (taos == NULL) { + fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + exit(-1); + } + + if (0 != g_queryInfo.subQueryInfo.sqlCount) { + (void)getAllChildNameOfSuperTable(taos, g_queryInfo.dbName, g_queryInfo.subQueryInfo.sTblName, &g_queryInfo.subQueryInfo.childTblName, &g_queryInfo.subQueryInfo.childTblCount); + } + + + pthread_t *pids = NULL; + threadInfo *infos = NULL; + //==== create sub threads for query from super table + if (g_queryInfo.superQueryInfo.sqlCount > 0 && g_queryInfo.superQueryInfo.concurrent > 0) { + pids = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t)); + infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo)); + if ((NULL == pids) || (NULL == infos)) { + printf("malloc failed for create threads\n"); + taos_close(taos); + exit(-1); + } + + for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + threadInfo *t_info = infos + i; + t_info->threadID = i; + t_info->taos = taos; + pthread_create(pids + i, NULL, superSubscribeProcess, t_info); + } + } + + //==== create sub threads for query from sub table + pthread_t *pidsOfSub = NULL; + threadInfo *infosOfSub = NULL; + if ((g_queryInfo.subQueryInfo.sqlCount > 0) && (g_queryInfo.subQueryInfo.threadCnt > 0)) { + pidsOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(pthread_t)); + infosOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(threadInfo)); + if ((NULL == pidsOfSub) || (NULL == infosOfSub)) { + printf("malloc failed for create threads\n"); + taos_close(taos); + exit(-1); + } + + int ntables = g_queryInfo.subQueryInfo.childTblCount; + int threads = g_queryInfo.subQueryInfo.threadCnt; + + int a = ntables / threads; + if (a < 1) { + threads = ntables; + a = 1; + } + + int b = 0; + if (threads != 0) { + b = ntables % threads; + } + + int last = 0; + for (int i = 0; i < threads; i++) { + threadInfo *t_info = infosOfSub + i; + t_info->threadID = i; + + t_info->start_table_id = last; + t_info->end_table_id = i < b ? last + a : last + a - 1; + t_info->taos = taos; + pthread_create(pidsOfSub + i, NULL, subSubscribeProcess, t_info); + } + g_queryInfo.subQueryInfo.threadCnt = threads; + } + + for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + pthread_join(pids[i], NULL); + } + + tmfree((char*)pids); + tmfree((char*)infos); + + for (int i = 0; i < g_queryInfo.subQueryInfo.threadCnt; i++) { + pthread_join(pidsOfSub[i], NULL); + } + + tmfree((char*)pidsOfSub); + tmfree((char*)infosOfSub); + taos_close(taos); + return 0; +} + +void initOfInsertMeta() { + memset(&g_Dbs, 0, sizeof(SDbs)); + + // set default values + strncpy(g_Dbs.host, "127.0.0.1", MAX_DB_NAME_SIZE); + g_Dbs.port = 6030; + strncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_DB_NAME_SIZE); + strncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_DB_NAME_SIZE); + g_Dbs.threadCount = 2; + g_Dbs.use_metric = true; +} + +void initOfQueryMeta() { + memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo)); + + // set default values + strncpy(g_queryInfo.host, "127.0.0.1", MAX_DB_NAME_SIZE); + g_queryInfo.port = 6030; + strncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_DB_NAME_SIZE); + strncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_DB_NAME_SIZE); +} + +void setParaFromArg(){ + if (g_args.host) { + strcpy(g_Dbs.host, g_args.host); + } else { + strncpy(g_Dbs.host, "127.0.0.1", MAX_DB_NAME_SIZE); + } + + if (g_args.user) { + strcpy(g_Dbs.user, g_args.user); + } + + if (g_args.password) { + strcpy(g_Dbs.password, g_args.password); + } + + if (g_args.port) { + g_Dbs.port = g_args.port; + } + + g_Dbs.dbCount = 1; + g_Dbs.db[0].drop = 1; + + strncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE); + g_Dbs.db[0].dbCfg.replica = g_args.replica; + strncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE); + + + strncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN); + + g_Dbs.use_metric = g_args.use_metric; + g_Dbs.insert_only = g_args.insert_only; + + g_Dbs.db[0].superTblCount = 1; + strncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", MAX_TB_NAME_SIZE); + g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables; + g_Dbs.threadCount = g_args.num_of_threads; + g_Dbs.queryMode = g_args.mode; + + g_Dbs.db[0].superTbls[0].autoCreateTable = PRE_CREATE_SUBTBL; + g_Dbs.db[0].superTbls[0].superTblExists = TBL_NO_EXISTS; + g_Dbs.db[0].superTbls[0].childTblExists = TBL_NO_EXISTS; + g_Dbs.db[0].superTbls[0].insertRate = 0; + g_Dbs.db[0].superTbls[0].disorderRange = g_args.disorderRange; + g_Dbs.db[0].superTbls[0].disorderRatio = g_args.disorderRatio; + strncpy(g_Dbs.db[0].superTbls[0].childTblPrefix, g_args.tb_prefix, MAX_TB_NAME_SIZE); + strncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", MAX_TB_NAME_SIZE); + strncpy(g_Dbs.db[0].superTbls[0].insertMode, "taosc", MAX_TB_NAME_SIZE); + strncpy(g_Dbs.db[0].superTbls[0].startTimestamp, "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE); + g_Dbs.db[0].superTbls[0].timeStampStep = 10; + + // g_args.num_of_RPR; + g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT; + g_Dbs.db[0].superTbls[0].maxSqlLen = TSDB_PAYLOAD_SIZE; + + g_Dbs.do_aggreFunc = true; + + char dataString[STRING_LEN]; + char **data_type = g_args.datatype; + + memset(dataString, 0, STRING_LEN); + + if (strcasecmp(data_type[0], "BINARY") == 0 || strcasecmp(data_type[0], "BOOL") == 0 || strcasecmp(data_type[0], "NCHAR") == 0 ) { + g_Dbs.do_aggreFunc = false; + } + + g_Dbs.db[0].superTbls[0].columnCount = 0; + for (int i = 0; i < MAX_NUM_DATATYPE; i++) { + if (data_type[i] == NULL) { + break; + } + + strncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType, data_type[i], MAX_TB_NAME_SIZE); + g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary; + g_Dbs.db[0].superTbls[0].columnCount++; + } + + if (g_Dbs.db[0].superTbls[0].columnCount > g_args.num_of_CPR) { + g_Dbs.db[0].superTbls[0].columnCount = g_args.num_of_CPR; + } else { + for (int i = g_Dbs.db[0].superTbls[0].columnCount; i < g_args.num_of_CPR; i++) { + strncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType, "INT", MAX_TB_NAME_SIZE); + g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0; + g_Dbs.db[0].superTbls[0].columnCount++; + } + } + + if (g_Dbs.use_metric) { + strncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE); + g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0; + + strncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE); + g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary; + g_Dbs.db[0].superTbls[0].tagCount = 2; + } else { + g_Dbs.db[0].superTbls[0].tagCount = 0; + } +} + +/* Function to do regular expression check */ +static int regexMatch(const char *s, const char *reg, int cflags) { + regex_t regex; + char msgbuf[100] = {0}; + + /* Compile regular expression */ + if (regcomp(®ex, reg, cflags) != 0) { + printf("Fail to compile regex\n"); + exit(-1); + } + + /* Execute regular expression */ + int reti = regexec(®ex, s, 0, NULL, 0); + if (!reti) { + regfree(®ex); + return 1; + } else if (reti == REG_NOMATCH) { + regfree(®ex); + return 0; + } else { + regerror(reti, ®ex, msgbuf, sizeof(msgbuf)); + printf("Regex match failed: %s\n", msgbuf); + regfree(®ex); + exit(-1); + } + + return 0; +} + +static int isCommentLine(char *line) { + if (line == NULL) return 1; + + return regexMatch(line, "^\\s*#.*", REG_EXTENDED); +} + +void querySqlFile(TAOS* taos, char* sqlFile) +{ + FILE *fp = fopen(sqlFile, "r"); + if (fp == NULL) { + printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno)); + return; + } + + int read_len = 0; + char * cmd = calloc(1, MAX_SQL_SIZE); + size_t cmd_len = 0; + char * line = NULL; + size_t line_len = 0; + + double t = getCurrentTime(); + + while ((read_len = tgetline(&line, &line_len, fp)) != -1) { + if (read_len >= MAX_SQL_SIZE) continue; + line[--read_len] = '\0'; + + if (read_len == 0 || isCommentLine(line)) { // line starts with # + continue; + } + + if (line[read_len - 1] == '\\') { + line[read_len - 1] = ' '; + memcpy(cmd + cmd_len, line, read_len); + cmd_len += read_len; + continue; + } + + memcpy(cmd + cmd_len, line, read_len); + queryDbExec(taos, cmd, NO_INSERT_TYPE); + memset(cmd, 0, MAX_SQL_SIZE); + cmd_len = 0; + } + + t = getCurrentTime() - t; + printf("run %s took %.6f second(s)\n\n", sqlFile, t); + + tmfree(cmd); + tmfree(line); + tmfclose(fp); + return; +} + +int main(int argc, char *argv[]) { + parse_args(argc, argv, &g_args); + + if (g_args.metaFile) { + initOfInsertMeta(); + initOfQueryMeta(); + if (false == getInfoFromJsonFile(g_args.metaFile)) { + printf("Failed to read %s\n", g_args.metaFile); + return 1; + } + } else { + + memset(&g_Dbs, 0, sizeof(SDbs)); + g_jsonType = INSERT_MODE; + setParaFromArg(); + + if (NULL != g_args.sqlFile) { + TAOS* qtaos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, g_Dbs.db[0].dbName, g_Dbs.port); + querySqlFile(qtaos, g_args.sqlFile); + taos_close(qtaos); + return 0; + } + + (void)insertTestProcess(); + if (g_Dbs.insert_only) return 0; + + // select + + //printf("At present, there is no integration of taosdemo, please wait patiently!\n"); + return 0; + } + + if (INSERT_MODE == g_jsonType) { + if (g_Dbs.cfgDir[0]) taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir); + (void)insertTestProcess(); + } else if (QUERY_MODE == g_jsonType) { + if (g_queryInfo.cfgDir[0]) taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir); + (void)queryTestProcess(); + } else if (SUBSCRIBE_MODE == g_jsonType) { + if (g_queryInfo.cfgDir[0]) taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir); + (void)subscribeTestProcess(); + } else { + ; + } + + taos_cleanup(); + return 0; +} + -- GitLab