pax_global_header00006660000000000000000000000064145610622630014517gustar00rootroot0000000000000052 comment=8d000b46b0a66cf4444284f9afe73f5693870fbd QATzip-1.2.0/000077500000000000000000000000001456106226300126675ustar00rootroot00000000000000QATzip-1.2.0/.github/000077500000000000000000000000001456106226300142275ustar00rootroot00000000000000QATzip-1.2.0/.github/CODEOWNERS000066400000000000000000000001341456106226300156200ustar00rootroot00000000000000* chengfei.zhu@intel.com xinghong.chen@intel.com lihui.zhang@intel.com david.qian@intel.com QATzip-1.2.0/.github/dependabot.yml000066400000000000000000000010021456106226300170500ustar00rootroot00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "github-actions" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "monthly" QATzip-1.2.0/.gitignore000066400000000000000000000005341456106226300146610ustar00rootroot00000000000000# automake file autom4te.cache m4 src/.deps src/.libs utils/.deps test/.deps aclocal.m4 Makefile Makefile.in ar-lib compile config.guess config.log config.status config.sub configure depcomp install-sh libtool ltmain.sh missing qatzip.spec # compile obj src/*.lo src/*.o src/*.la utils/*.o test/*.o # app test/bt test/test utils/qzip utils/qzstdQATzip-1.2.0/LICENSE000066400000000000000000000033731456106226300137020ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ QATzip-1.2.0/LICENSE.LZ4000066400000000000000000000024371456106226300143120ustar00rootroot00000000000000LZ4 Library Copyright (c) 2011-2020, Yann Collet All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. QATzip-1.2.0/LICENSE.XXHASH000066400000000000000000000025551456106226300147050ustar00rootroot00000000000000xxHash Library Copyright (c) 2012-2021 Yann Collet All rights reserved. BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. QATzip-1.2.0/LICENSE.ZLIB000066400000000000000000000017521456106226300144400ustar00rootroot00000000000000Copyright notice: (C) 1995-2022 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu QATzip-1.2.0/LICENSE.ZSTD000066400000000000000000000030151456106226300144560ustar00rootroot00000000000000BSD License For Zstandard software Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Facebook, nor Meta, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. QATzip-1.2.0/Makefile.am000066400000000000000000000100521456106226300147210ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ QZIP_DIR = $(top_builddir)/utils TEST_DIR = $(top_builddir)/test QATZIP_LIB_DIR = $(top_builddir)/src QATZIP_LIB = libqatzip.la CODE_FORMATTING_BIN = $(top_builddir)/test/code_format_tests/format.sh DIST_SUBDIRS = src utils test SUBDIRS = src utils test pkgincludedir = $(includedir) pkginclude_HEADERS = include/qatzip.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = qatzip.pc dist_man_MANS = \ man/qzip.1 EXTRA_DIST = \ LICENSE \ README.md \ include/qz_utils.h \ src/xxhash.h \ src/qatzip_internal.h \ src/qatzip_page_table.h \ utils/qzip.h \ utils/qzstd.h \ test/code_format_tests \ test/performance_tests \ docs/QATzip-man.pdf \ config_file/ $(QATZIP_LIB): @make -C $(QATZIP_LIB_DIR) $(QATZIP_LIB) qzip: $(QATZIP_LIB) @make -C $(QZIP_DIR) qzip qzip_obj_without_main: @make -C $(QZIP_DIR) qzip_obj_without_main qatzip-test:$(QATZIP_LIB) @make -C $(TEST_DIR) qatzip-test bt:$(QATZIP_LIB) @make -C $(TEST_DIR) bt qzstd: $(QATZIP_LIB) if QATZIP_LZ4S_POSTPROCESS_AC @make -C $(QZIP_DIR) qzstd else @echo "Error : please enable lz4s postprocessing in configure!" endif AM_CFLAGS=-DENABLE_TESTLOG testlog: clean @make -C $(QATZIP_LIB_DIR) $(QATZIP_LIB) AM_CFLAGS=$(AM_CFLAGS) @make -C $(QZIP_DIR) qzip @make -C $(TEST_DIR) qatzip-test @make -C $(TEST_DIR) bt if QATZIP_LZ4S_POSTPROCESS_AC @make -C $(QZIP_DIR) qzstd endif check_code: @echo -e "\n\nPerforming code formatting tests..." @if ! $(CODE_FORMATTING_BIN); then \ echo "Check code format FAILED!!! :("; \ exit 1; \ fi clean-local: @make -C $(TEST_DIR) clean ######################## # RPM package building # ######################## rpm: clean dist qatzip.spec @mkdir -p rpmbuild/BUILD rpmbuild/RPMS rpmbuild/SOURCES rpmbuild/SPECS rpmbuild/SRPMS @cp $(PACKAGE)-$(VERSION).tar.gz rpmbuild/SOURCES/ @cp qatzip.spec rpmbuild/SPECS/ @rpmbuild --define "_topdir $(abs_srcdir)/rpmbuild" -ba rpmbuild/SPECS/qatzip.spec rpmclean: @rm -fr rpmbuild .PHONY: rpm rpmclean libqatzip qzip qatzip-test check_code \ qzip_obj_without_main bt $(QATZIP_LIB) clean-local \ qzstd QATzip-1.2.0/README.md000066400000000000000000000413621456106226300141540ustar00rootroot00000000000000# Intel® QuickAssist Technology (QAT) QATzip Library ## Table of Contents - [Introduction](#introduction) - [Licensing](#licensing) - [Features](#features) - [Hardware Requirements](#hardware-requirements) - [Software Requirements](#software-requirements) - [Additional Information](#additional-information) - [Limitations](#limitations) - [Installation Instructions](#installation-instructions) - [Build Intel® QuickAssist Technology Driver](#build-intel-quickassist-technology-driver) - [Install QATzip As Root User](#install-qatzip-as-root-user) - [Install QATzip As Non-root User](#install-qatzip-as-non-root-user) - [Enable qzstd](#enable-qzstd) - [Test QATzip](#test-qatzip) - [Performance Test With QATzip](#performance-test-with-qatzip) - [QATzip API manual](#qatzip-api-manual) - [Intended Audience](#intended-audience) - [Open Issues](#open-issues) - [Legal](#legal) ## Introduction QATzip is a user space library which builds on top of the Intel® QuickAssist Technology user space library, to provide extended accelerated compression and decompression services by offloading the actual compression and decompression request(s) to the Intel® Chipset Series. QATzip produces data using the standard gzip\* format (RFC1952) with extended headers or [lz4\* blocks][7] with [lz4\* frame format][8]. The data can be decompressed with a compliant gzip\* or lz4\* implementation. QATzip is designed to take full advantage of the performance provided by Intel® QuickAssist Technology. The currently supported formats include: |Data Format|Algorithm|QAT device|Description| | :---------------: | :---------------: |:---------------: | :------------------------------------------------------------: | | `QZ_DEFLATE_4B` | deflate\* | QAT 1.x and QAT 2.0|Data is in DEFLATE\* with a 4 byte header| | `QZ_DEFLATE_GZIP` | deflate\* | QAT 1.x and QAT 2.0|Data is in DEFLATE\* wrapped by Gzip\* header and footer| | `QZ_DEFLATE_GZIP_EXT` | deflate\* | QAT 1.x and QAT 2.0|Data is in DEFLATE\* wrapped by Intel® QAT Gzip\* extension header and footer| | `QZ_DEFLATE_RAW` | deflate\* | QAT 1.x and QAT 2.0|Data is in raw DEFLATE\* without any additional header. (Only support compression, decompression will fallback to software) | | `QZ_LZ4` | lz4\* | QAT 2.0|Data is in LZ4\* wrapped by lz4\* frame | | `QZ_LZ4S` | lz4s\* | QAT 2.0|Data is in LZ4S\* blocks | ## Licensing The Licensing of the files within this project is split as follows: Intel® Quickassist Technology (QAT) QATzip - BSD License. Please see the `LICENSE` file contained in the top level folder. Further details can be found in the file headers of the relevant files. Example Intel® Quickassist Technology Driver Configuration Files contained within the folder hierarchy `config_file` - Dual BSD/GPLv2 License. Please see the file headers of the configuration files, and the full GPLv2 license contained in the file `LICENSE.GPL` within the `config_file` folder. ## Features * Acceleration of compression and decompression utilizing Intel® QuickAssist Technology, including a utility to compress and decompress files. * Dynamic memory allocation for zero copy, by exposing qzMalloc() and qzFree() allowing working buffers to be pinned, contiguous buffers that can be used for DMA operations to and from the hardware. * Instance over-subscription, allowing a number of threads in the same process to seamlessly share a smaller number of hardware instances. * Memory allocation backed by huge page and kernel memory to provide access to pinned, contiguous memory. Allocating from huge-page when kernel memory contention. * Configurable accelerator device sharing among processes. * Optional software failover for both compression and decompression services. QATzip may switch to software if there is insufficient system resources including acceleration instances or memory. This feature allows for a common software stack between server platforms that have acceleration devices and non-accelerated platforms. * Provide streaming interface of compression and decompression to achieve better compression ratio and throughput for data sets that are submitted piecemeal. * 'qzip' utility supports compression from regular file, pipeline and block device. * For QATzip GZIP\* format, try hardware decompression 1st before switch to software decompression. * Enable adaptive polling mechanism to save CPU usage in stress mode. * 'qzip' utility supports compression files and directories into 7z format. * Support QATzip Gzip\* format, it includes 10 bytes header and 8 bytes footer: `| ID1 (1B) | ID2(0x8B) (1B) | Compression Method (8 = DEFLATE*) (1B) | Flags (1B) | Modification Time (4B) | Extra Flags (1B) | OS (1B) | Deflate Block| CRC32(4B)| ISIZE(4B)|` * Support QATzip Gzip\* extended format. This consists of the standard 10 byte Gzip* header and follows RFC 1952 to extend the header by an additional 14 bytes. The extended headers structure is below: `| Length of ext. header (2B) | SI1('Q') (1B) | SI2('Z') (1B) | Length of subheader (2B) | Intel(R) defined field 'Chunksize' (4B) | Intel(R) defined field 'Blocksize' (4B) | ` * Support Intel® QATzip 4 byte header, the header indicates the length of the compressed block followed by the header. `| Intel(R) defined Header (4B)|deflate\* block|` * Support QATzip lz4* format. This format is structured as follows: `| MagicNb(4B) |FLG(1B)|BD(1B)| CS(8B)|HC(1B)| |lz4\* Block | EndMark(4B)|` ## Hardware Requirements This QATzip library supports compression and decompression offload to the following acceleration devices: * [Intel® C62X Series Chipset][1] * [Intel® Communications Chipset 8925 to 8955 Series][2] * [Intel® Communications Chipset 8960 to 8970 Series][3] * [Intel® C3XXX Series Chipset][4] * [Intel® 4XXX Series][5] ## Software Requirements This release was validated on the following: * QATzip has been tested with the latest Intel® QuickAssist Acceleration Driver. Please download the QAT driver from the link [Intel® QuickAssist Technology][6] * QATzip has been tested by Intel® on CentOS\* 7.8.2003 with kernel 3.10.0-1127.19.1.el7.x86\_64 * Zlib\* library of version 1.2.7 or higher * Suggest GCC\* of version 4.8.5 or higher * lz4\* library of version 1.8.3 or higher * zstd\* library of version 1.5.0 or higher ## Additional Information * For QAT 1.x, the compression level in QATzip could be mapped to standard zlib\* as below: * QATzip level 1 - 4, similar to zlib\* level 1 - 4. * QATzip level 5 - 8, we map them to QATzip level 4. * QATzip level 9, we will use software zlib\* to compress as level 9. * For QAT 2.0, the compression level in QATzip could be mapped to standard zlib\* or lz4\* as below: * Will be updated in future releases. * QATzip Compression Level Mapping: | QATzip Level |QAT Level| QAT 2.0(deflate\*, LZ4\*, LZ4s\*) |QAT1.7/1.8(Deflate\*) | | ---- | --- | ---- | ---- | | 1 | CPA_DC_L1 |2(HW_L1) | DEPTH_1 | | 2 | CPA_DC_L2 |2(HW_L1) | DEPTH_4 | | 3 | CPA_DC_L3 |2(HW_L1) | DEPTH_8 | | 4 | CPA_DC_L4 |2(HW_L1) | DEPTH_16 | | 5 | CPA_DC_L5 |2(HW_L1) | DEPTH_16 | | 6 | CPA_DC_L6 |8(HW_L6) | DEPTH_16 | | 7 | CPA_DC_L7 |8(HW_L6) | DEPTH_16 | | 8 | CPA_DC_L8 |8(HW_L6) | DEPTH_16 | | 9 | CPA_DC_L9 |16(HW_L9) | DEPTH_16 | | 10 | CPA_DC_L10 |16(HW_L9) | Unsupported | | 11 | CPA_DC_L11 |16(HW_L9) | Unsupported | | 12 | CPA_DC_L12 |16(HW_L9) | Unsupported | ## Limitations * The partitioned internal chunk size of 16 KB is disabled, this chunk is used for QAT hardware DMA. * For stream object, user should reset the stream object by calling qzEndStream() before reuse it in the other session. * For stream object, user should clear stream object by calling qzEndStream() before clear session object with qzTeardownSession(). Otherwise, memory leak happens. * For stream object, stream length must be smaller than `strm_buff_sz`, or QATzip would generate multiple deflate block in order and has the last block with BFIN set. * For stream object, we will optimize the performance of the pre-allocation process using a thread-local stream buffer list in a future release. * For 7z format, decompression only supports \*.7z archives compressed by qzip. * For 7z format, decompression only supports software. * For 7z format, the header compression is not supported. * For lz4\* (de)compression, QATzip only supports 32KB history buffer. * For zstd format compression, qzstd only supports `hw_buffer_sz` which is less than 128KB. * Stream APIs only support "DEFLATE_GZIP", "DEFLATE_GZIP_EXT", "DEFLATE_RAW" for compression and "DEFLATE_GZIP", "DEFLATE_GZIP_EXT" for decompression now. ## Installation Instructions ### Build Intel® QuickAssist Technology Driver Please follow the instructions contained in: **For Intel® C62X Series Chipset:** [Intel® QuickAssist Technology Software for Linux\* - Getting Started Guide - HW version 1.7][11] **For Intel® Communications Chipset 89XX Series:** [Intel® Communications Chipset 89xx Series Software for Linux\* - Getting Started Guide][12] **For Intel® 4XXX Series:** [Intel® QuickAssist Technology (Intel® QAT) Software for Linux\* Getting Started Guide – Hardware Version 2.0][13] ### Install QATzip As Root User **Set below environment variable** `ICP_ROOT`: the root directory of your QAT driver source tree `QZ_ROOT`: the root directory of your QATzip source tree **Enable huge page** ```bash echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages rmmod usdm_drv insmod $ICP_ROOT/build/usdm_drv.ko max_huge_pages=1024 max_huge_pages_per_process=48 ``` **Compile and install QATzip** ```bash cd $QZ_ROOT ./autogen.sh ./configure --with-ICP_ROOT=$ICP_ROOT make clean make make install ``` For more configure options, please run "./configure -h" for help **Update configuration files** ___Have to update those file, Otherwise QATzip will be Unavailable.___ QAT's the programmer’s guide which provides information on the architecture of the software and usage guidelines. it allows customization of runtime operation. * [Intel® QAT 1.7 linux Programmer's Guide][9] * [Intel® QAT 2.0 linux Programmer's Guide][10] The Intel® QATzip comes with some tuning example conf files to use. you can replace the old conf file(under /etc/) by them. The detailed info about Configurable options, please refer Programmer's Guide manual. The process section name(in configuration file) is the key change for QATzip. there are two way to change: * QAT Driver default conf file does not contain a [SHIM] section which the Intel® QATzip requires by default. you can follow below step to replace them. * The default section name in the QATzip can be modified if required by setting the environment variable "QAT_SECTION_NAME". To update the configuration file, copy the configure file(s) from directory of `$QZ_ROOT/config_file/$YOUR_PLATFORM/$CONFIG_TYPE/*.conf` to directory of `/etc` `YOUR_PLATFORM`: the QAT hardware platform, c6xx for Intel® C62X Series Chipset, dh895xcc for Intel® Communications Chipset 8925 to 8955 Series `CONFIG_TYPE`: tuned configure file(s) for different usage, `multiple_process_opt` for multiple process optimization, `multiple_thread_opt` for multiple thread optimization. **Restart QAT driver** ```bash service qat_service restart ``` With current configuration, each PCI-e device in C6XX platform could support 32 processes in maximum. ### Install QAT As Non-root User Please refer to [Intel® QuickAssist Technology (Intel® QAT) Software for Linux\* Getting Started Guide][13] section "3.8 Running Applications as Non-Root User". ### Enable qzstd If you want to enable lz4s + postprocessing pipeline, you have to compile qzstd. which is a sample app to support ZSTD format compression/decompression. before enabling qzstd, make sure that you have installed zstd static lib. **Compile qzstd** ```bash cd $QZ_ROOT ./autogen.sh ./configure --enable-lz4s-postprocessing make clean make qzstd ``` **test qzstd** ```bash qzstd -k $your_input_file ``` ### Test QATzip Run the following command to check if the QATzip is setup correctly for compressing or decompressing files: ```bash qzip -k $your_input_file -O gzipext -A deflate ``` #### File compression in 7z: ```bash qzip -O 7z FILE1 FILE2 FILE3... -o result.7z ``` #### Dir compression in 7z: ```bash qzip -O 7z DIR1 DIR2 DIR3... -o result.7z ``` #### Decompression file in 7z: ```bash qzip -d result.7z ``` #### Dir Decompression with -R: If the DIR contains files that are compressed by qzip and using gzip/gzipext format, then it should be add `-R` option to decompress them: ```bash qzip -d -R DIR ``` ### Performance Test With QATzip Please run the QATzip (de)compression performance test with the following command. Please update the drive configuration and process/thread argument in run_perf_test.sh before running the performance test. Note that when number for threads changed, the argument "max_huge_pages_per_process" in run_perf_test.sh should be changed accordingly, at least 6 times of threads number. ```bash cd $QZ_ROOT/test/performance_tests ./run_perf_test.sh ``` ## QATzip API Manual Please refer to file `QATzip-man.pdf` under the `docs` folder ## Open Issues Known issues relating to the QATzip are described in this section. ### QATAPP-26069 | Title | Buffers allocated with qzMalloc() can't be freed after calling qzMemDestory | |----------|:------------- | Reference | QATAPP-26069 | | Description | If the users call qzFree after qzMemDestory, they may encounter free memory error "free(): invalid pointe" | | Implication | User use qzMalloc API to allocate continuous memory | | Resolution | Ensure qzMemDestory is invoked after qzFree, now we use attribute destructor to invoke qzMemDestory| | Affected OS | Linux | ## Intended Audience The target audience is software developers, test and validation engineers, system integrators, end users and consumers for QATzip integrated Intel® Quick Assist Technology ## Legal Intel® disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document contains information on products, services and/or processes in development. All information provided here is subject to change without notice. Contact your Intel® representative to obtain the latest forecast , schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. Copies of documents which have an order number and are referenced in this document may be obtained by calling 1-800-548-4725 or by visiting www.intel.com/design/literature.htm. Intel, the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries. \*Other names and brands may be claimed as the property of others [1]:https://www.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/purley/intel-xeon-scalable-processors.html [2]:https://www.intel.com/content/www/us/en/ethernet-products/gigabit-server-adapters/quickassist-adapter-8950-brief.html [3]:https://www.intel.com/content/www/us/en/ethernet-products/gigabit-server-adapters/quickassist-adapter-8960-8970-brief.html [4]:https://www.intel.com/content/www/us/en/products/docs/processors/atom/c-series/c3000-family-brief.html [5]:https://www.intel.com/content/www/us/en/products/details/processors/xeon/scalable.html [6]:https://www.intel.com/content/www/us/en/developer/topic-technology/open/quick-assist-technology/overview.html [7]:https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md [8]:https://github.com/lz4/lz4/blob/dev/doc/lz4_Frame_format.md [9]:https://www.intel.com/content/www/us/en/content-details/710060/intel-quickassist-technology-software-for-linux-programmer-s-guide-hw-version-1-7.html [10]:https://www.intel.com/content/www/us/en/content-details/743912/intel-quickassist-technology-intel-qat-software-for-linux-programmers-guide-hardware-version-2-0.html [11]:https://www.intel.com/content/www/us/en/content-details/710059/intel-quickassist-technology-software-for-linux-getting-started-guide-customer-enabling-release.html [12]:https://www.intel.com/content/www/us/en/content-details/710089/intel-communications-chipset-89xx-series-software-for-linux-getting-started-guide.html [13]:https://www.intel.com/content/www/us/en/content-details/632506/intel-quickassist-technology-intel-qat-software-for-linux-getting-started-guide-hardware-version-2-0.html QATzip-1.2.0/SECURITY.md000066400000000000000000000003461456106226300144630ustar00rootroot00000000000000# Security Policy ## Reporting a Security Vulnerability Visit https://intel.com/security for information on how to report security vulnerabilities. Do not report any security vulnerability as a regular issue in this repository. QATzip-1.2.0/autogen.sh000077500000000000000000000034411456106226300146720ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ #!/bin/sh mkdir -p m4 autoreconf -vif QATzip-1.2.0/config_file/000077500000000000000000000000001456106226300151335ustar00rootroot00000000000000QATzip-1.2.0/config_file/4xxx/000077500000000000000000000000001456106226300160465ustar00rootroot00000000000000QATzip-1.2.0/config_file/4xxx/multiple_process_opt/000077500000000000000000000000001456106226300223215ustar00rootroot00000000000000QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev0.conf000066400000000000000000000127141456106226300250260ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev1.conf000066400000000000000000000127151456106226300250300ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev2.conf000066400000000000000000000127151456106226300250310ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev3.conf000066400000000000000000000127151456106226300250320ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev4.conf000066400000000000000000000127151456106226300250330ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev5.conf000066400000000000000000000127151456106226300250340ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev6.conf000066400000000000000000000127151456106226300250350ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_process_opt/4xxx_dev7.conf000066400000000000000000000127151456106226300250360ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 64 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/000077500000000000000000000000001456106226300221125ustar00rootroot00000000000000QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev0.conf000066400000000000000000000127141456106226300246170ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev1.conf000066400000000000000000000127141456106226300246200ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev2.conf000066400000000000000000000127141456106226300246210ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev3.conf000066400000000000000000000127141456106226300246220ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev4.conf000066400000000000000000000127141456106226300246230ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev5.conf000066400000000000000000000127141456106226300246240ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev6.conf000066400000000000000000000127141456106226300246250ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/4xxx/multiple_thread_opt/4xxx_dev7.conf000066400000000000000000000127141456106226300246260ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 8 NumProcesses = 4 LimitDevAccess = 0 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/config_file/LICENSE.BSD000066400000000000000000000033731456106226300165550ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ QATzip-1.2.0/config_file/LICENSE.GPL000066400000000000000000000431031456106226300165620ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. QATzip-1.2.0/config_file/c3xxx/000077500000000000000000000000001456106226300162105ustar00rootroot00000000000000QATzip-1.2.0/config_file/c3xxx/multiple_process_opt/000077500000000000000000000000001456106226300224635ustar00rootroot00000000000000QATzip-1.2.0/config_file/c3xxx/multiple_process_opt/c3xxx_dev0.conf000066400000000000000000000114271456106226300253320ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = dc # Set the service profile to determine available features # ===================================================================== # DEFAULT CRYPTO COMPRESSION CUSTOM1 # Asymmetric Crypto * * * # Symmetric Crypto * * * # MGF KeyGen * * # SSL/TLS KeyGen * * * # HKDF * * # Compression * * * # Decompression (stateless) * * * # Decompression (stateful) * * # Service Chaining * # Device Utilization * * # Rate Limiting * * # ===================================================================== ServicesProfile = DEFAULT ConfigVersion = 2 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 32 LimitDevAccess = 0 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 QATzip-1.2.0/config_file/c3xxx/multiple_thread_opt/000077500000000000000000000000001456106226300222545ustar00rootroot00000000000000QATzip-1.2.0/config_file/c3xxx/multiple_thread_opt/c3xxx_dev0.conf000066400000000000000000000122011456106226300251120ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = dc # Set the service profile to determine available features # ===================================================================== # DEFAULT CRYPTO COMPRESSION CUSTOM1 # Asymmetric Crypto * * * # Symmetric Crypto * * * # MGF KeyGen * * # SSL/TLS KeyGen * * * # HKDF * * # Compression * * * # Decompression (stateless) * * * # Decompression (stateful) * * # Service Chaining * # Device Utilization * * # Rate Limiting * * # ===================================================================== ServicesProfile = DEFAULT ConfigVersion = 2 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # # List of core affinities Dc1CoreAffinity = 2 # # # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # # List of core affinities Dc2CoreAffinity = 3 # # # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # # List of core affinities Dc3CoreAffinity = 4 QATzip-1.2.0/config_file/c6xx/000077500000000000000000000000001456106226300160235ustar00rootroot00000000000000QATzip-1.2.0/config_file/c6xx/multiple_process_opt/000077500000000000000000000000001456106226300222765ustar00rootroot00000000000000QATzip-1.2.0/config_file/c6xx/multiple_process_opt/c6xx_dev0.conf000066400000000000000000000103421456106226300247530ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 32 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 QATzip-1.2.0/config_file/c6xx/multiple_process_opt/c6xx_dev1.conf000066400000000000000000000103421456106226300247540ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 32 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 QATzip-1.2.0/config_file/c6xx/multiple_process_opt/c6xx_dev2.conf000066400000000000000000000103421456106226300247550ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 32 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 QATzip-1.2.0/config_file/c6xx/multiple_thread_opt/000077500000000000000000000000001456106226300220675ustar00rootroot00000000000000QATzip-1.2.0/config_file/c6xx/multiple_thread_opt/c6xx_dev0.conf000066400000000000000000000111001456106226300245350ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 4 QATzip-1.2.0/config_file/c6xx/multiple_thread_opt/c6xx_dev1.conf000066400000000000000000000111001456106226300245360ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 4 QATzip-1.2.0/config_file/c6xx/multiple_thread_opt/c6xx_dev2.conf000066400000000000000000000111001456106226300245370ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 4 QATzip-1.2.0/config_file/dh895xcc/000077500000000000000000000000001456106226300164725ustar00rootroot00000000000000QATzip-1.2.0/config_file/dh895xcc/multiple_process_opt/000077500000000000000000000000001456106226300227455ustar00rootroot00000000000000QATzip-1.2.0/config_file/dh895xcc/multiple_process_opt/dh895xcc_dev0.conf000066400000000000000000000100511456106226300260660ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (MCA and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 32 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 QATzip-1.2.0/config_file/dh895xcc/multiple_thread_opt/000077500000000000000000000000001456106226300225365ustar00rootroot00000000000000QATzip-1.2.0/config_file/dh895xcc/multiple_thread_opt/dh895xcc_dev0.conf000066400000000000000000000106121456106226300256620ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features (MCA and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 1 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 2 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 3 QATzip-1.2.0/configure.ac000066400000000000000000000224551456106226300151650ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([qatzip], [1.2.0], []) AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability foreign subdir-objects tar-pax]) AM_SILENT_RULES([yes]) AC_USE_SYSTEM_EXTENSIONS AC_CONFIG_MACRO_DIRS([m4]) AC_SUBST([LIBQATZIP_VERSION], [3:3:0]) # Checks for programs. AC_PROG_AWK AC_PROG_CC AC_PROG_LN_S AC_PROG_MAKE_SET AM_PROG_AR AC_PATH_TOOL(PKGCONFIG, pkg-config) LT_PREREQ([2.4]) LT_INIT # Checks for typedefs, structures, and compiler characteristics. AC_CHECK_HEADER_STDBOOL AC_C_INLINE AC_TYPE_INT64_T AC_TYPE_OFF_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T # Checks for system header files. AC_CHECK_HEADERS([stdio.h stdarg.h fcntl.h limits.h memory.h \ unistd.h stdint.h stdlib.h string.h sys/ioctl.h \ sys/time.h sys/types.h sys/stat.h unistd.h utime.h \ pthread.h]) # Checks for library functions. AC_CHECK_FUNCS([atexit getcwd gettimeofday \ memmove memset mkdir munmap \ realpath strdup strerror strrchr \ strtol strtoul utime fork malloc mmap]) # Checks for pthread. AC_CHECK_LIB([pthread], [pthread_create], , [AC_MSG_ERROR([not found pthread_create in -lpthread])]) #check for zlib. AC_CHECK_HEADER([zlib.h], , [AC_MSG_ERROR([zlib.h not found])]) AC_MSG_CHECKING(zlib version) AC_TRY_COMPILE( [#include ], [#if ZLIB_VERNUM < 0x1270 #error zlib version is too old ... #endif], [AC_MSG_RESULT([ok])], [AC_MSG_ERROR([zlib version must be 1.2.7 or higher.]) ]) AC_CHECK_LIB([z], [deflate], , AC_MSG_ERROR([deflate not found])) #check for lz4 lib AC_CHECK_HEADER([lz4.h], , [AC_MSG_ERROR([lz4.h not found])]) AC_CHECK_HEADER([lz4frame.h], , [AC_MSG_ERROR([lz4frame.h not found])]) AC_CHECK_LIB([lz4], [LZ4F_compressFrame], , AC_MSG_ERROR([LZ4F_compressFrame not found])) ##check for xxhash lib #AC_CHECK_HEADER([xxhash.h],,[AC_MSG_ERROR([not found xxhash.h])]) #AC_CHECK_LIB([xxhash], [XXH32_update], ,AC_MSG_ERROR([not found XXH32_update in -lxxhash])) AC_DEFINE(XXH_NAMESPACE, QATZIP_, "Prefix xxhash API with QATZIP_") #with ICP_ROOT AC_ARG_WITH([ICP_ROOT], AS_HELP_STRING([--with-ICP_ROOT=PATH],[Used to link Cpa library]), AS_IF( [test "$withval" = "yes"], AC_MSG_ERROR([--with-ICP_ROOT=PATH requires a PATH]), [ICP_ROOT="$withval"] ) ) #check for qat header file. ICP_INCLUDE_CFLAGS= AS_IF([test ! -z "${ICP_ROOT}"], [ #check for OOT relative header and lib AC_MSG_CHECKING([qat header files from ${ICP_ROOT}]) AS_IF([test ! -e ${ICP_ROOT}/quickassist/include/cpa.h || test ! -e ${ICP_ROOT}/quickassist/include/dc/cpa_dc.h || test ! -e ${ICP_ROOT}/quickassist/utilities/libusdm_drv/qae_mem.h || test ! -e ${ICP_ROOT}/quickassist/lookaside/access_layer/include/icp_sal_poll.h || test ! -e ${ICP_ROOT}/quickassist/lookaside/access_layer/include/icp_sal_user.h], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([QAT header files not found in $ICP_ROOT, please check \$ICP_ROOT]) ], [ AC_MSG_RESULT([yes]) ICP_INCLUDE_CFLAGS=" -I${ICP_ROOT}/quickassist/include \ -I${ICP_ROOT}/quickassist/include/dc/ \ -I${ICP_ROOT}/quickassist/utilities/libusdm_drv/ \ -I${ICP_ROOT}/quickassist/lookaside/access_layer/include/ " LDFLAGS+=" -Wl,-rpath,${ICP_ROOT}/build/ -L${ICP_ROOT}/build/ " ] ) AC_SUBST(ICP_INCLUDE_CFLAGS) AC_CHECK_LIB(qat_s, cpaDcCompressData2, , [ AC_MSG_ERROR([cpaDcCompressData2 not found cpaDcCompressData2]) ] ) #check for icp_adf_get_numDevices/icp_sal_userIsQatAvailable AC_CHECK_LIB(qat_s, icp_adf_get_numDevices, [ADF_CFLAGS="-DADF_PCI_API" AC_SUBST(ADF_CFLAGS)], [ AC_CHECK_LIB(qat_s, icp_sal_userIsQatAvailable, [SAL_CFLAGS="-DSAL_DEV_API" AC_SUBST(SAL_CFLAGS)], [AC_MSG_ERROR([icp_sal_userIsQatAvailable/icp_adf_get_numDevices not found])] ) ] ) #check for usdm lib AC_CHECK_LIB(usdm_drv_s, qaeMemAllocNUMA, , [AC_MSG_ERROR([qaeMemAllocNUMA not found])]) ], [ #check for qat lib. AC_MSG_CHECKING([qat header files from sys usr]) AC_CHECK_HEADERS( [qat/cpa.h qat/cpa_dc.h qat/qae_mem.h qat/icp_sal_poll.h qat/icp_sal_user.h], [ AC_DEFINE([HAVE_QAT_HEADERS], [], [QAT header files in include/qat subdirectory]) ], [AC_MSG_ERROR([qat header files not found])], [#ifdef HAVE_QAT_CPA_H # include #endif ] ) AC_CHECK_LIB(qat, cpaDcCompressData2, , [ AC_MSG_ERROR([cpaDcCompressData2 not found])], [-lusdm -lcrypto]) #check for icp_adf_get_numDevices/icp_sal_userIsQatAvailable AC_CHECK_LIB(qat, icp_adf_get_numDevices, [ADF_CFLAGS="-DADF_PCI_API" AC_SUBST(ADF_CFLAGS)], [ AC_CHECK_LIB(qat, icp_sal_userIsQatAvailable, [SAL_CFLAGS="-DSAL_DEV_API" AC_SUBST(SAL_CFLAGS)], [AC_MSG_ERROR([icp_sal_userIsQatAvailable/icp_adf_get_numDevices not found])], [-lusdm -lcrypto] ) ] ) #check for usdm lib AC_CHECK_LIB(usdm, qaeMemAllocNUMA,, [AC_MSG_ERROR([qaeMemAllocNUMA not found])]) ]) #check for compile flags AC_MSG_CHECKING([cflags]) CFLAGS+=' -Wall -Werror -std=gnu99 -pedantic \ -fstack-protector-strong -fPIE -fPIC \ -fno-delete-null-pointer-checks -fwrapv' AS_IF([test "x${CC}" = "xgcc"], [CFLAGS+=' -fno-strict-overflow'], []) AC_MSG_RESULT([yes]) #check for compile flags AC_MSG_CHECKING([ldflags]) LDFLAGS+=' -fstack-protector-strong -fPIC -pie -z relro -z now -Wl,-z,noexecstack' AC_MSG_RESULT([yes]) #Enable debug mode AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Enable debug mode]), [ debug=true CFLAGS+=' -g -DQATZIP_DEBUG -O0' ] , [ debug=false CFLAGS+=' -O2' AS_IF([test "x${CC}" = "xgcc"], [CFLAGS+=' -D_FORTIFY_SOURCE=2'], []) ] ) AM_CONDITIONAL([QATZIP_DEBUG_AC], [test x$debug = xtrue]) #Enable qatzip symbol AC_ARG_ENABLE(symbol, AS_HELP_STRING([--enable-symbol], [Enable qatzip symbol]), [ symbol=true CFLAGS+=' -g' ], [ symbol=false ] ) AM_CONDITIONAL([QATZIP_SYMBOL_AC], [test x$symbol = xtrue]) #Enable qatzip pthread_barrier AC_ARG_ENABLE(pthread_barrier, AS_HELP_STRING([--enable-pthread-barrier], [Enable pthread_barrier]), [ pthread_barrier=true CFLAGS+=' -DENABLE_THREAD_BARRIER' ], [ pthread_barrier=false ] ) AM_CONDITIONAL([QATZIP_PTHREAD_BARRIER_AC], [test x$pthread_barrier = xtrue]) #Enable lz4s-postprocessing AC_ARG_ENABLE(lz4s_postprocessing, AS_HELP_STRING([--enable-lz4s-postprocessing], [Enable lz4s and zstd post processing]), [ lz4s_postprocessing=true #check for zstd lib SAVE_CFLAGS=${CFLAGS} CFLAGS= AC_CHECK_HEADER([zstd.h]) AC_CHECK_LIB([zstd], [ZSTD_compressCCtx]) CFLAGS=${SAVE_CFLAGS} ZSTD_LIBADD='-lpthread -Bstatic -lzstd' AC_SUBST(ZSTD_LIBADD) ], [ lz4s_postprocessing=false ] ) AM_CONDITIONAL([QATZIP_LZ4S_POSTPROCESS_AC], [test x$lz4s_postprocessing = xtrue]) AC_CONFIG_FILES([Makefile qatzip.spec src/Makefile test/Makefile utils/Makefile] qatzip.pc) AC_OUTPUT QATzip-1.2.0/docs/000077500000000000000000000000001456106226300136175ustar00rootroot00000000000000QATzip-1.2.0/docs/QATzip-man.pdf000066400000000000000000012566361456106226300162560ustar00rootroot00000000000000%PDF-1.7 %ÐÔÅØ 2 0 obj << /Type /ObjStm /N 100 /First 827 /Length 1453 /Filter /FlateDecode >> stream xÚÍ™[SG…ßõ+æÑ¼À\z.[år•AøCL¸Ä)Š ¦bPqòësz+éÝ•VbF’WÙ³Ëj¦ç;}fga”V^9­‚2&ªJ­¬IÊ8e Rð© Vá9¡‹5Šb5°Vy”õʧ¤lP!bl¥¢Ö4Y r*ùJ9RU…KDt”C\“œ"£Œµz@ˆLV+ò¸bO˜ 4<• Ê;\}Rž€q Ó+k18\S „åxÁ㊠ ‡Ê+ÆLø9Bcª´Š©¬©˜”3É(üsÖºA²â=¤àZE• ÁëJ%HòÞ(„pƒ*‰˜·B¼„xèêâU¢ Äj$N{70"MâtxEÖrÖƒ"Pƒ¸Dš3Ä !H‡ä‘.3ˆ“ËfQ$~‚Ȭ€³A•Cd6ÅX~[89Æx‘ZLã]m-RJì*ìñ€ƒ|¨o"² |”I>QÀ!å«€Qœi­Ù3XÎQyÙ8¥ œ i0œmä 7¤{``Vðšp“`ˆc‹ n""³E‰#ð5¸“0Ô^N:óh=ßÀ7‹Œ¸Ic.؉×,ˆ1Ø»t˜Ä¦òò‚u1 ïbåø‘«ˆ€H_ªáÁ¬á5F*9N/{í0Ô`>,,8˜|´ƒçÏÕÖ‘Úz=>«­¡zvñùüîa4Ù4êÅ‹Á³3þÇ3­µáæL“æë>7cn.¹yäæ 7£v¯·ÜÜJ¯ú³¯3“Þ.®Ç·›fî´›…÷s•ÙÙ)l;ðŽD:¯#I³¤(Û'Êö‹zrî=n®åñÃ|™nvR׎ôJ"­l›ëSèú.š6_ÍÎGå«s(½.¤×ôªõ?ˆW¸ŸêKõ§cØ>³ÆuÇͤYáÒ´ ÚÃ_rsPÛÙÃúø±…›<}ÔEŸ2ö²¿ÿ½¤|"ƒî2sÜå¶yÜvfmœwÆý WÂs+w R¾î±Szsš³¿ü" 㘛SyÙëur†Ssjå´ÿÊÍ.7‡ÜI‡÷ÜüÜîZÿp"Ùþïñ¾DÿIÆæé¶¥ºí¦û­t(ÑíJu»ݧýüÖ~|$¹9ì²¾n÷Ú“L4ŸÕƒÞ䉡R1´XLÈwysûÒ¹ýâ¹ëŒ½“d ÛŸH’‡3CNópC)nÈÀýÐ~²-;"ådæØ…Ç3 ßw_‡ã©#Oh,K…îÊjßµ'}Àst?y e¾£7³žû/9ùFÝbë껞*.÷T™SÓtÉ}a»igô8Å–¢Ìnô‹ÍÉZ@;ݳ»9ã?-AëJi]mßê($£R2ê'ë«P_I 'bsÓ¥Ô—‚ú ×Ý"ùbnÅVÆJC?ãy¯¤i²w+].EF!h,íì¦èžì«$›êŽ€~‘æc·˜þ]VGæÆ“JySb÷{~¹ìY¹ÛB>üÂW¥ÈU?òP4él6ÑO=¿Æ.³ ½ÔÖ®û™2~ý,ä[îè1KóÈZ˜ÈÝMó=K!½]ŠÞ. ËÆP¯Ú?»¸£y_ 4§ª‚5%Æ-¥Ò-P9U°<.m-…FO¡5É>Ï-dZ\™PŠ]±mªÀ›Ì­ížª'¿[I¹$­R@îæ¡ØR»rI–IæJÉܺK²LP*¥5–d™Œ¾”ѯ»$Ë ¥ á›Ô ™´±”6þ gÙî“»ræŠñ3®xŠ‹ÿý`Ÿ»Õúþ­¶)ñ_v—RݰJJë3íÿ­½ÉSbK•Ø~%;]÷­°É•"¹H»)'¤RBZpê,ö¥À~5à'ЏbþPÊVãÿÐýSÓç’w°."¿6Ç~±ØX*vÎ÷ÃîyÿMÞ„TÊšÖźò;Q•¢WëB/y;þ7ä&* endstream endobj 203 0 obj << /Type /ObjStm /N 100 /First 885 /Length 1523 /Filter /FlateDecode >> stream xÚÕšÛn7†ïõ¼Ln”å @ µ› @¤uÐÜøÆ%êXŽmš§ï?‹˜+Jë—Nˆ¹Å%¿™8äjC ©FQã”a\¼"‹«FSt¸jeH®FqµÊzƒkPN£¯ŽÊ;RD¤Bc'D¬¢±øìT W¯´ö¨p£4‘FE+mX*‹­Ò^K% b1*G¥C@ÅÒ‘› µlèHÆ $4íìh¶@%F³•A½T0–YÜ`ƒTpƒcpZ|b¤@‹‘†ˆc8§¸a|r^±B¾AÍäµbWpÙÈðÞ*v vå£bO˜'*6L(°â0rÀÈQË„^™& ó ßP„™ÅÙp0;i±ÊX9TĦ•ñ$t„Š `*0‹jv1L² œÀΊ¸V`b,+:°hÇp-C<Ë6ÁGÖxs•µÐa¶uvChÂí¸Ó)@icƒÛ!žk<0ãÈa@(è„N¦q1)t†ã„¡ ³Nüç”sg(è¼t†‚Î#jÖº€f†‹]BAßD̽&iAÄTf(èYó„¡ 7 ©¼¦øÑ;CAï¢(£•÷h†‚>)Îp–^:GİŒ ƒÖð3 ¹ ‰ `ïÞ†Œ«‚ÅÒ`(¼ÎP0x » `ð°€A‚ Cä0yúT=9QO^,^/Ô“cõhµ9—³‹õ|q=5S=µSÝHq#Å2}»JÅ)æR¬¥x/ÅËÔ¯m;“â2Õº¶_¤ø”ÚNûËêÇeÆë*ãu¿ñ-Îu‚=I`ÝgÉ!°TKý°Ïs°Y%W1q9Si,T°›*vÓÏþ"çìÂÛ„¸‘â*uYUbÛ*l[„}Ò³Bçi%·±}”Dj—¸KóåýÞ¦{ßUêª uå†.gÛöORª‹Á£ž4ÖÙ8KµuÞy“Qa¼¯2Þ?ãÿLmË»Bç·Ô¶ºkB•kB¹kÖy~ÙÜgµÆ*ØØûkråü¤Ñ[> lù/“³®R±Hé¡‚NWÑéºY áçÉwÝ>ýSª]¦è­À¦*l:„=¼ëýÜãò¿¤ø#?r\VÅUFñ72êMÒ§ ÿʃ ™*ËîØüOþ¯ÍŸl¶-Â~H›?¹*C]‘¡›´›˜\Áî«ØïØ»_ç+y™VÍ"mÛ×_Ç”dÄ`*Ë2Öešô<9öÝv‡6¹¾j÷®ý/ޟݬgËiOPg{”ÖÎYnßm‡ã> stream xÚÕ™Mo7†ïú<&…_Cr —( ´@[=¾8’•,Å’ì6¿¾ï5¹ônVÜm]Ç€MQ»äð™gWV!…•^Xƒ á«RB5ø®´0|]‘0žðé„SŸp„ïZŠ`0^¼žYmEÓ4øî…’V¡Ê`†D0Ôh¡´ÇCB1Æ Å÷­iÐñXÎJ¡â:X[9'gÖZÙXÑBr@c-$7rˆYL'-´‚d:ªANhÝp§ÚHvRhKãŒÐ$ÕÌ:+´ãYΣaÖ¡ƒDÇ+tx–‡dà+°ƒb0ï„Ñl!hÁƒn†•³Á ãíÌ+ ‡+^˜¨N‹+À5ÁãJ£ÙØÜ°u-_ql#Hf;G‚$+€†à*KVÏHZPB±Û¤+`6bYp:ü¿Qü‡d‚óÈÀÎï‘qhà>"¸€°53‚ɾåÑ Rð<ã+PÒÉ(ƒÐq|a¡yAÌtæ' 8hˆŽÎ9#x!÷<: ¤‚Éyø‚`tÇ‹pvÌ‚ƒ^)@Áƒ^ƒÞH¬zX~Fð '˜—àAÏ3ô&!xÐ{6,â£dxÐGÉð`‹B·€`…–f-1 ÚÂð`0* [=‚»&§< ®*<<[Î !š ’ƒ§ÙÛ·âÍ™xóÝö×­xóA¼Ú?òßjq¸ÞÞÌinçz®ÔkñîÝìÕ¹ñÿþ\JIÜ̹±©§SO¥æ\ZÉŸ{nîãe¢„Ü\p³àænŽÜì^×QéITºMuŸ®¹9´ù"ÕMçrürÅÍmÒ+~Ýr³æfÙ£@B§!jjÃýÌÍnθY¥åö x›JšÜ¦Þ& ~ŸoR“ç>¨vÖ^ý,){›<³ÈÖøgÔ/‰ì2õnSï&MZõû4[e®NÚeÞ ªÓJ›QáaÔ‡dCê÷¶ ó˜d­Jïçé-»ŸŽS¨5J±®Š‹Òs»¶¿.RÄ}J£nË`Ž‘¹©ÕcAu-hd¼‹½:3Å´Q–É9ÓhÇÂØ6ÌUâ;¦=sÙ¾wë—:.ËUd—ëà»Äsè¢ü©¯ÝEwô}‡5oÙ}¹ ®Sø­Ú“r\¤¨Çè~,ºo£oÒ¾ý³rYîßxîëxÂXžÐæÙ•î[—‘ñéß›«‹×´ñòþýütGs_Ζ“’¶ìT<ùÝøvR´‡:=Ew G9%7E¡•Ðo‡6ÄàQçŸhCüÀÍ﹌zžàO6<^Ãÿcƒ³o$ „áÍ^h§²@8•ÖÉõ¶SšnÊ’êºs/SGí®ê€õXà"W|NÀïËÉußù_GdÆ™éDm#®R5}(Cë& Úáƒj3°Ã·iGÊŠ%ï­ßJ¢¾Lð}ê净çNzÃåo·Ô}d˜G›ñØÙϘÔÞëY¹î6ϵڡ¬N×鯲ü>ñå÷3»úlÕ¦×#èõ‹ÊìÜ(çè~7õ½+*ŸûJ=‰Eײìǰ˜I,føMÔþt¡R íÝØ• ØI ØÎË“Uù."ï_ýoE×e¼®*_D\š„K#í¢ó˜ÚuC~uzÌ©’ÓMâtœ×åë´Cù(±è<žf ‡ò´¾ªTÅORÅW¨ò(p./SÝ}íY¨3Lâ œû2'ß%7t­ý¨¢¬ —f{QËTÑ}Q˜D?u°wIñ|o?XŠœ>Ô©R$× xÎRDÍ+•û&KUq>ª—ZЍªRD*E²í ‹Ç²®ÄГ0tÆ!»Ê7úÈL2ÝŸ*׳“Ö³ý?v}Ë hAQ lËì÷9Em­ÕÝ$×a8ÖªêHV§ŽäíЯ‹•aF÷‡®œ–ç×Cpþ Z'à endstream endobj 776 0 obj << /Length 161 /Filter /FlateDecode >> stream xÚ…±Â0 D÷~…Çdˆ‰Ý$NFP‰ )b5T,!Ê×C•‘ÉÖÝ=Ÿla ]cÿÌUn['@Œ‰ÈC¾KÀxŒ¾…ÜÃA헚تü¾Þõ1ï*cQ| 3Q¢CC+• d´sŒèƒqŒœ\µ»2–‡&«NÏÒkÃÕY¦º¯oºµê5 e¬aB™Ïý¼°ÉÍÀµ4 endstream endobj 782 0 obj << /Length 19 /Filter /FlateDecode >> stream xÚ3PHW0Ppç2ÀAc(á endstream endobj 826 0 obj << /Length 1154 /Filter /FlateDecode >> stream xÚí›]s¢:€ïý¹” Ù„|.­ÕÖ¶Z[èžvwªè8G ‹8»í¯ß €At»3{„›*Z >yò¾o` ¸¨YµOJW Æ0°Æ€jH5tCSÖ<Õ§Ê7ëªÖ¶jßkH| t¨rƀιÊ5†^íé#ñÞ€*68ø±üOŠUJ°x>fí®“¦Wç 'É ïó.&m…!¦ƒ”†¦óz/-fîêy×¹ ¢õŸËëL„p•R.’®ÞÝmöS‡èm6Æâ›sÐ@Le„&V·Úo·ôÔ`ŒÕU¥Aiò@·Žr_ü˜£Ó>52<Ðq[²4Q šè6HVݦ­:­5sæó"®àßqEK]Ùhöf:v1­dùhYð;d¡i§/»ª3-Wè»\IÅ©+ëVóTAÂ*¾ü!eèû•!r2:† Ïõ#'šþAqô߇¤âœ;‘“„›À{ Ýù!°¬rSLͦæjÛGfi²g¢b–"´ƒt PAâ¯7—sN+ˆ»^f&3G?â-t'tãíÉÀ³ÿ?OÍKã[62#'Zä –î©”} Ób’5ØÐu¼¼4Ã*°Á6ö-8%lÛ~ž» ë]×l„µ «é§¼šG‹n¿’Õ¼¶œÓõj1¯H`Ø4wk1o‰$È¡ŠnѰKÖ+{ykO2dVÚ)=+$-‘מÚr ¥¼ä®²B®ÒœU§öŸªNž&Û7¿—bNÊŠT/4êõ#§Q²´ŒŸ0¾õÕònA¡T…¹%½Ï„©šÎÈÆ}&„ªL<,{àÂõÝЉÒ_s>Ç ¨¯i9絟¯q‘°îú»—ø tÝ4d endstream endobj 605 0 obj << /Type /ObjStm /N 100 /First 887 /Length 1941 /Filter /FlateDecode >> stream xÚåš]o7†ïõ+xÙîň߇‚Ž'FíØµ”¦“ WÑ6Ʀ’kËEÚ_¿ï¡iJ“‘¥™‰Ò.°€MRòð9ïáÇŒ4^Z!…—AXƒ, åñQi¡qÁ+# .yå…± 9 gP¯¥pžsÔük+H™×N(aH¡”% ‹† F£@#”¥ˆ‚ʱC•P°R(ØAA  , äÞ:IرÑ`ÇF¡ï«"º;#´ Àr^h«= $´÷h §4±G^ xPàëàÁì|t\PˆÜ& “˜k ÿÆ×@Ç„D°+>HPÍ:"ˆƒ!>Àrd™Ô•’PˆÂ* ž¨QÀÈbÙ4Vô(ðX‘„µ°CðÖ²>$•°ž 1°¤h@Ò  (qÜ  Q8 0B蜄¬£SŽk< ‘k8z& âð%¡`Qpa@ˆ £Ô& ÚÀrD5a<!±Û Š"è#DÐ'Ë–#ͽx¶8îeS<`ôžQADv8x#ÇŠ`^ãJ Tv@B-B‡Kˆ ièLžvøäyà ‰Ø2ÃèLˆ C)b&”¥ˆ™@¬cŒ©‡bsÏ ÀKˆ`HB!¦AÇ0p2£W0"$(7„€^n”é’Q9XEmÔÌŒpG "dÅ€R@9ô‚·‘çÆ“'b8Ãçóñ\ Ä7·w¿ðßt²¸šÏ*W)Ué*~+¾ûnðÍ[CÿôóßqRq¢J’>êRŠœ¼•Vr~ÍÉ”“'ï9¹*MM±,9ŸsrÇÉâÛv|JöLur•ò¦PÞ–Rªû£||¿†iI£·‚èÕñÆœ|¨|Yô9."%šÅªH£U3£rù¦h7YvÉ­ÎËÿ®;· Kê4mz8ùpy½˜ÞT¾éž_â°,†®”ØN äoõáÅÿE1”zÌÝWꨥæ—e&^Æ«B´và¢~²ö{½]U®~(Ý~ÛØã¯Òîºe“a}¥L ø]™'ÓÒ®ÅhÚÆë ¦ËÊ ExZ¨ª“âɤ ‹­Ÿ3ð§RÚ/2Œ{-ïÐU•ÐB•We?:.Pû½ægìŠ7ã=+Êþ/MÍuwÒ-N.ùOøú7ÎMÕï@W›e9,Î% ã–,º‹nÁrZ„Þ_×-M/Ä-çõQ‰÷¸Ð=o d{m9ž‹f¯×‡£ûpí¤\;iIîz‘»^äÝé|/º-G÷cyÛ³éVètÍ-æágn¶ô‡zù³å|~Y0j^ta ½˜BW¦åòjNÛ¥ðãúó¢¥±—±«'eª¤IðcË#ÙëÉHv¥5Ü^™¹­zA«¶Ð/;Üé~–º-KS¸]m`Úô"7ýÉ¿l3ж¯Ý%ï×Ü(´ëåŸÛ¥=7ß‹Ü÷'UÃòQç¬~/·¼[:hÜñ%_Ç-=¤^¶>ǽ²K-ÙC/ö-‡èiý±¢V]ûNé¼,†äîó.{kìE¾åè<«?W핹0jù]œìõeœlAuº~g9«Õµ_¿Éíè«1£zùµåT]>t.¨•¹ÓM÷BÛrÈ~ÕM¤ðoD¯¶ùcÓHÏsóÿ÷cÐ_«Ñº«;õ±N÷·ü2TµñFÆ6¦D?ö_kÏ£ú¯ÒɉO üƒ½çbxxµxÇFž< Ç^OÅðìò×é`¸?Ÿ-¦³Å­ òÜr0<ŸÞÎïn&ÓÛôÛ~ª:™¾¿º|:ÿ$.$*\t¿K¬ªB|7€¥˜@ó˜šçQVGÿéç7‚d<¿K *©­˜Ý}üøî¡í!(³Z~¥ ¤^¸6<»™OFÓ…¸ïÁ¡ާŸ¢t[ïHÐ G‚üG>cØç”óólOe{*ÛSÙžÊöT¶§²=•í©lOe{*ÛÓÙžÎöô½½Ï"–t Gw¿,Òçã«Ùçó›÷Ó›ùnøbx4Ü¿PéÇr‚ðûXñK(.VÑ¡Œ¯ÒK3••möÄcïÜŸÎ;A¶ J58ó ®òV 3Hªµ{—Ú%FVBùŠz¥c…È“v•±q£z×Røˆh€EYYy~+J†Š\Ø(…Þ½žLe…²rž_Uà •0;WÂ!&`RhL x„CšJ˜¯ „‘•ÆúW„…Áo%šP…ÍëÃî\ ¥*Þ#UÔUäç´Æ“îF%ì.•P’*R1íðüjœV[…—[Åúõ±rßlW—ê¨ã;< endstream endobj 873 0 obj << /Length 1165 /Filter /FlateDecode >> stream xÚí›Ër£8†÷~ -í…5º"±L;—ê®IÕ$vM/Ò])”456¤±<¹<ýsƒ­ØJ÷T‹T& ü:çüè€À=@àbða6øíœ3 ¡ïyÌî€@Pz>³Ü ãxôuöip6ü`óoàú0)¡$ „‹ÁÍW"óÙ'€ õ%x\¹ŒSÈ5ÏÁtp5@奋ód÷å ¯ËÁ0±1Œ$˜áaˆªá0ˆ!‰ÃóUê8MŠ­Ó4\-T¢ƒõ®|ÈÕµÀÍ#Άp4æÜ+~ñÆÖοfëpjÌbY2isC)(czŒoP†¸ ûãåd>OÃ@«K¥ƒ(ÐÁÄ‘ùÁmÌoÿÖGuöE%K¶É’T,'ót©lá]P¤+jê†li:]éùÄ·!eÖæ;ÉBkD@¬£P v-oCêL ;WÚ’ÄIž^›äçX¯2×Ù“¶!%½^ÔIy¢âuªÂ=£7Ëîè¡r'Êm¨¯DI"IçxzN"õ·y¾ ‰Ä€(œD‰Ñ6Ń#¥üh!I'¥áÚõœ%Ñë3®Rt5º•Œ¸¶?ç#Ƈ™²; Ìz´…›"7 Ó6î}Î]`Ú9¦ØMµí¹PúTÝ(«¹¶Kù]U+qS+ß ;59)NS,yl’&_"÷ö¤Ä:Æ­©Ho“[z§G˜ƒLåÆ'MT¢'é*Ñöì…ùñ!ró6XìCôçÈØ>•åšû=^Za1ÉŽsܤ£½²3!üŽg`î&¼Ú°|Lbm^.:´áJÜÍÜÚÜ\ùr…¹'POyƒ²›;"µ;ºT‹ó8‰N¢(³¢Æ¬s8Ý–*ùgQ 0Ò4üëZ‘59”–ï‘asâS+ÃÏ™9%ÆÚj7Çï˜$s[ƒ µÅ™fq|‚:6™[©NøY‹ÃØ;ãæV¿oƒÛê¡$g_=ïÜCŒý<›:¬ýÐl„ÍäUA¥¹%zLö°õ|ÒšÖ"Ì’´5Z¦ïH}ËóÍê¾Ø<ùãã>âw¯ñè¿îib¶5¤VW›9ú Œ‰¹w¨œe@žÌƒårocr‘w±÷]X¯Ûh`3"¡G[½Uu_ÕU gß3SæÝN‹S]Ô+«P;®‹¬2•„jÛÈø½ rêë&¬«—Fî}~âãx 8!ÐG~[î¤ü©©Ï㹊ª­eXÖç»z6E}Ìû)µWz7Vý›ÊJêÆÐ0Ë|¿sd:d×x+aÇI¬ã`~û÷ˆða0_mÇj*ûLj´‹r)ã‡tþœ¤ zÇB|Ï׉ïf¨f3eÒ!U¡¾·âÏúŠõ§uÌڜӕv[ÓìA$貸J³]ˆe qOú Ò;-pÝmõR>@x£™!¬/ï^Åߨ­kµÓ¾¶þ…ðý§]¯¼qÅ.o¼U/Ùy嘙HÜìazæ”ë;y¡•ººëÇIÏUžO›§ç{3J3}’öÿ$$- endstream endobj 918 0 obj << /Length 976 /Filter /FlateDecode >> stream xÚí›[s›8†ïý+t ÖJèÈínºélgÚÚW›Í0d›)pÓöׯlDâu ±3G711Ö<<óéÓ„À ðvôçtôÇߌ }Î ˜ÎÃúÄÂ÷ Ç`ƒ['I÷núnôf:ú:Âúƒ` ”œ!%”Q6º½C ÖçÞ‰/Áýæ/3@Œ}œ‚Éèã™/o®SÎÍ?™áP±5Œ$˜Á1Díx$ÐsÇžÎ{•}Ves|Ö¡9*¢U¦ò:¬“"ß ½ýNp;¦¾ï@wÌßyax÷\SDêûÀÁP Æú®sʶðBÜ \Ü•ª*Í1¨4Ï}˜>½RgcŠ NºÓøšäõFWæäaºSröŠÌ<;ï}Iû^Ä;åeY´ýU¦mQ‡iäO•kñp‹Ù6êbu`0!IJîÏzÌ(ÒÛ—Ûˆýñ礙ñ>¸9aébý3«‚IszR뎙³ŠêæŸÔÌ%ÈQ¥Ê#uPc8±mð<è#ßpÚ67ª“TÅí»*j'ËÎŽ «–w|†N.âÔvÏç!ÛÝ=ÓÇî9*²e¦óÂø\/²ƒ.^y™î'n«î†lúí ‡ÆˆI;€¼£¯éžc]‚YvÐv¬ÏÙ¶ã<>›¦#NJu\â#ËúLZ›vz±šÍ²0qÙQ>¸%»&‹{YÌҢϮ‡ 8¨~îÃmï`å= ñ޼¢M–«Zà êEY-Š4¾TªqõÎÊh~6 8Ó¤}©z^dkï³õõÚ¥úDyýK{¥ô-ÏSìŨZÕMžœ«¼DZg8‹Í2®Z—=µ…Ññ—Õò€¯gg¶g¨lÖt÷®.¿aR/Ôu8½Ó‚ÌwÙÑ ó¯"ËŠ|XœÉ»’PÇë—U²6Ò±™Ùóðîdft ¯ÍÌÎuˆk3³ AÞÑ—Ø çÅ„¦6nè˜ôÒ™Ù¸áÙ@wœ5YR•Ê«¤N¾¹zÙ¦‚¬ˆÚ,_`Kó¨žÂ†7/讉ʖEš&ù¼SYáK¶¿Ç6;¯©6»¼³6ˆ™öSÙÆbqþâù>~4»Qÿ!DÂZ KÆ„ç_W‚CûdÜdçÁÛñÇ€Ì>•sÙÚË3û¤Èʰ8Z†ÿù—|Ò‰k®ìdåS|'Cÿ÷C_Ù‰îA_i'ºAx]{Hƒˆà>[HÛ}«z‚ÓõFQs)ªË·~Ùܪ·*W¥îç̶‚Í:ðG{“Öšÿ1׃ԺçûCü¼˜Å endstream endobj 829 0 obj << /Type /ObjStm /N 100 /First 923 /Length 2705 /Filter /FlateDecode >> stream xÚµ[M·½Ï¯à1¹pXEV±l J$€`ëDÐA–‰c×V€óïó^¥ØB$q‘!° öôtW¿.Ö'§M%õQ“4Ž-itŒ–Zm=YFœSžçG’¢%E)IÄ’¤–~Š¢e g Óq:JKÒî,–$ :Š'-MqГâ"i­”3’¶¨)¤$õŠGˆ$í=N!št(®‘šð(^ÓRUÅ#Äî†ñTMxWOÕGªÄ2R ×w+x³ÀM[=…*^—04R³Š‹µá w¼-¾òÌZ“è&€ÉF•dµã«ªÉp ¸Æ ºƒÞüÕ’ ‡@¼›KáW=¹ïŠä­ð®‘Ü 3€»ñˆ&Ƀ…Ž|`r¢ÕÔ§£Aûãį{«¼ØS·€Â&¨K@×=J ÐB¨vh¯lB¸¸Øx^. ÒSÉ9ë=Ü^ìi‚·ž†R«iT³‘Fëì% Ê4: @XAEáN)EÁaEºÂa¥RW0)ÊòŽ#ç=pÔùD§uÑaX¸ÅÒÀ” qŽVgDc„ýѦ0"PØ /£ÁéÄŠ Í P“Æ; “Ž—†D ˆ&.Ú `½J•®=tÝJ=¤žQ!ågÔ‹<£uxFíÊ;ðŒÊwˆQèXrhGåÄ ‡Tªóp»F+…ãIsx ýCZ¯ãôèÑéüìß?ߤó×··w÷§ó÷ï~¸?>ÿùõí¿NçoîÞüxóæyÿ–ç?žÿtþö¹Nçïn^ݧçÐeî0{‹’á;6r‡ÃYD]pÕ×éÑ£tþ>ÿp÷ì.§ß½}÷Ã[Üúúî6·,YŸ¾úê„¿+`©#t`®Ù1ÃUG®09ëš«ú'Ñ|(ËHÍsa˜Ðžiêf–=tÒ-Q;Á82mËp¾Ô¾ ©n€$š;œY‹dØ7â]®£.#j×GÔæ .‰|‘¡ÎŠeä™eH¶RºŠäŽÕbd¬eD¾üi\Ì SacQ¿"¢ð2ò£ªg5¦YËHä+áhƒU78šUHËÌÈ(ò𶨟º#5Ï@¾G’ÊøD˜ªÚ2¤ á¨ËEç ‰ºÁÓ4—!m˜¸ {¶N-•ÌÌò-kõeHâQ…« FHÜ"Q à¼.CÚ*RÊh  u[…³¡n[†´! ¡~ʬ³µõ\PÂUœ¯Ë1²^5"½‡„Ô6Æ%‘ òbO‘ÝbR\’ÒãPËkCšEU k”õ¸46@ê¬*ªIj ‡žk=T– ˜¼æ‚šZQ 2˱HY•²!~+ò›SO†Ž~ -Ê”uHâ·"ËuK…±¢ùRœo–²!€£/û" ê¦…«²PYÏ)Ò®_š¼Î;ÍÉó@3¯…ár¥4ÙNþƵ•£^&¸±:gmGe‚î5רGÐÑ0 ¼-–ãdÛQ™ iÎfG~S”qb,Pê2¢ v-𵂄>§üÌóËa²m±$¸šºÉi—+!(TÚ2¤ … môѱPˆô†ü²ŒhC]om…G‚³yµe<¿)J§ç¡†‡|—ÎýÛßS/™«]½K.ÚÒí»Ÿ~zñþÚ'w·÷ÇžpùMûå®'ÇR^páùé›»Wßßl:?}ü$ŸÝürŸ^üöýŸ¾üÇÍéü-äÝÜÞ¿MpÛù–oïÞ½yuóöXJ;NýåæÇ×/¿¹û%z1Ì…rýª±±Ç+?}ù"`\.?4ûç(!q ô2ÊuŽï¿os´9úûcŽã2¶)¯MymÊkS^›òڔצ¼6åµ)¯My6åÙ”gSžMy6åÙ”gSžMy6åÙ”çSžOy>åù”çSžOy>åù”çSž_佸nÖê6Ø3Ñ=rk¾’µ68v‡qU–8Í¥¬v¶#muEo¨4 ôSè Õë2¤ i«—@$nGñÓò)3ê2¤ yËqiÉõL\oË6ä-ï-fwØ’£îðÀct,CÚ`Þh se{†šQÄ­¾-#Ú·óåζ¬gE€s8œ¬OÛ†vÚÕèØøH–á ‰4·åÊÕv´Ó«½…½ +¸½Ù2¤ í4þ3Ùº*åXtø›>$Pnh§­cæ)+ |'q'r]Ç´ƒ1¦³zDïa$"„Êý´1F±½+i`øœöõŒ²£Ÿ6x $)W°‡&ƒ×ù‚¥là·#ÅM«ÜnÄzp’ üŽ…9V¿«€´ƒ£ÛqL Ÿ=µ`w´žUdCovaµÒÔkj>ñÖ#¦lˆâ n7˜}K= Þ·ke=±ÈØA aî‚RÏìÜ®ûºžtCo…„¨ëÙJÆMÐÛÊzjQÙA!aîF+´Üw‚°ÀqÓZ ~WQ27Uø]èzjѼü®sʹ1¸‰ shVv[ô;ôưó‹žàwV×S‹î`¶”½À‘ѱ tbêÆz×ÌÜ®w´+ÓFE^ávºÅõŠQ<Ðñ²K]+÷ÕÜŒ¹gãóöË ¶ËÐè—~áر›ïÓ$䫾üùþæÍ5[·©‹6S¹vÍøÖŽÝPÕü³º¸êjÄ„QÑ‘#Æ”x;Ö?»èPèõ™’ †ŠL®|(%ü‹[ÂìÊû¯Þc)%£k=¦Hg¥¯â+hv0 AZи/cø-å©ÏÚå cJmÜL ÿѾ i íÏVîâEÕÚð¦cÒÞ¥bÞâÂ+"‰¢æhmÒÞÅ‘'û±e®ò.˜¸±éêAp`ÖèôÀÁ G3³/DŸz}%ý<ƒ¬û²·´Ùjs2$>fN¸úÿcNúdúd úd úd úd &ôè“yˆy_Læ!&ó“yˆ)/¦¼˜òbÊ‹)/¦¼1å)oLycÊSÞ˜òÆ”7¦¼1勼QÊeŽ:Ç:Ç6G›£Ï±Ï1æ8åÉ”'SžLy2åIÛÊ Ì ´H¡ØžÝv{~H à®n0¯"Ka£îIA]ýR. ’ V¹8Ó—!m¡P¸ aÇfþìƒЉ.CÚB¡ ®±ÀEAÃe¯Î­Ò˶P(\Žðc' ƒ)Õº éê)… `=8A°þ,ƒòʆ½>x“# ¹qi©}ÙãÛŽ ع¡FíCü!cò™¥Û_Ñ=\‰:W .›~É•x³%“i›~¡1¹-ðu?¸’e8º‡&a$œŠŒ¼N“\ íXý÷r¸ý¼¢ˆ KÒE–!íXüGã¦#E|GrAd{(’álí®ß@‘\ ù†„{DI(y=”¯Ëˆv,ü#‰y¿ÄÅ.u¹ Š}ô™-ívÐ#«Í&!íXõçê—¶ø“±`GfŒ,Ù-Ø‘õ˜´ƒºmHk…kþ ¹^ôàF>Ùoþ/Lzí꣡h䓹2jbŸgF>`±ëgü:*ºÞÿv¤CÔ:Ž_­Iþ “ë endstream endobj 963 0 obj << /Length 1248 /Filter /FlateDecode >> stream xÚí›ß{š:Çïý+¸„ Ó$$!\¶ÝãN·¶jw¶õìᡘ*ÏQ´€ëÚ¿þ„_RA?Öí¬Æ  >|óæÍ—µµ·“^ã茛1SëÝiœ1Ͳ1`HëõµÝÿf|í½k´zû’»A Í‹q8&š7nÜ|…Z_n{§A`Ú\{HKŽ5BM@‰)—GZ·qÕ€ù©³ã„ƒü€¼2ÄzVD  œkCÕ¡€ÑÄ×GO$rÆ~à;c7ö†iE‹3h7Mn#MJYöCw\Ûs÷_{hIè”æ,ª”åo1À}Žg8ïŸNÝÑèÖõ õ«4mfýI~?bò±¹ ±# êßcÊ­TÜQ:‚˜)¤Z“`q\Õ®A½zêNîâQÝ ÅGƒC]„‘? ÚÁ]xât³‚ÝX‚–¥f^œýÑiŠÀUö&4_§Ò3Ølcý"8ç»ñ,Ú §eÃW&ÚŸ c`C»*r‹îîˆ]$úÅZäeüýi,Å^ã ­×+~Þ‹ñ½ߦÁ9áíÆn¾4ñfcȶ° »e)¦š‰·Ì%RÆ…˜ÝÑ`â jø°yø^V¼…|SÆQ’kœ9´ç:gkã¼9åœguÃ'Q’q8QÚCÖÓ8Äb%ıOd¨•b}tdŽ<ñdGWÁHSÂÜH˜4n¸±Œ±Ž7™q=ÒbÕØ·Ñ)+™úlç2ÇuÜ8vëÆ±¹¢¸B™VIQ¶x§Ÿ5ùoa¡¥ä¹•ÏCÎü‘ø¡éAˆ ¨•LÍvE+O»0?´I0Ì4Àæ ¦Ó‘不‹’©aàÞA4ôÇóµ'j˜óÅ#?ðF³¾8z¶eX½ŠµŠaþö[†¶1Y9•ö½ë…“ÂüBøéú±aU>Û~ÕmndU‘g` ´WÇÂPï}i_:Ç—í%qFõ¨ëÃ%²-Ü© ]çc«Óm_|¨= ¡D¡+ÐåžÓÕçÄâ»>sZN2#ù¢SWç¾ õk¤¹ÐÌÉœæƒ@=×cú}¼,³±âºV¥´äÚ:;ϱ¶j>BTôÜ^´¬„Û·œîÅYïoƒJÑvZÎÉq’æœþu}Y³‘0ûƒ °­g­‡rñá܇Õ?;­O­ÓëÞ’n†™ìÿÍ Bàå5__ž·OWµ3ÂCmYlŲ7á(ÐDÛ¼W¼{ǶI†3Dg©ü‡PÀä!Ó[ôV"tãâ‘ýmÒ•<9yúîÐã@ÖRH‚jÿ¦| endstream endobj 993 0 obj << /Length 894 /Filter /FlateDecode >> stream xÚíšÛRâ0€ïyŠ\Ò bÒæÔK„€¸Òb)Ëî:N‡…ªÌ žpW}úM”À]u¤ÃESˆiòåKþ¤K€@»rèVZ”MÆ à^ŠMHt¸©C†;gÕ_Ú¹{\‘n宂՟!€GP0¸P¨ÜãëÊÙ9õÛ1@Ð0øæ¼„C¥g _9­ øÑQ9÷—qN\ÂS•ÁA*à C´¬ ƒX}L­¦sQ=ýáI«~x"½¾Ýr‡EÕº#½Ãºf jãË V}ùLpVˆT¡V£”Eú&woZXx§šNªŒÅÕÏ£R×fšf‚Ñ«PlëDSÅV¿{ò›l ÜŽmåéT|ü6“L›qÒæ–&TC;'ùFŽÞ«Æï㣹¥¯8ÛNC©5ÌsÆ%Å×m5ŠË•í> stream xÚ3PHW0Ppç2ÀAc(á endstream endobj 1002 0 obj << /Length 383 /Filter /FlateDecode >> stream xÚåTMOÜ0½çWÌÑ9d˜ñÇ8î­…–‚„4·‡mc¶+e74YTø÷MÖfE%$Ä©=ÍØž÷f4Ïz+ 8-(ÇOMqôÅYà]†æ'×ÓÚ•&+Ê¿(ÊAœI}f Î%]Úø½Ô¤îWÏ´þó ÿ ñØRV^TïsSü*8—gƒqÉ0üØ‹‚vz:Bjø½/Ü€u5SÞÁ·âê`V‚Ú‹}æUv²Évp·qXîb›>Äþw<¦ü¤/ ©‡ÇÕl1*nÿuñ ;ˆ endstream endobj 919 0 obj << /Type /ObjStm /N 100 /First 924 /Length 2649 /Filter /FlateDecode >> stream xÚ½[ÛŽ·}Ÿ¯àc’ëÂ"  ØœHÁöCC²¼H„»†´œ¿Ï)µŠei–“ ­ÐsaWŸ.Öýôt·TR÷–HŽ=±+ŽžT)y)©öŽ#¥&GN½3Ž’¨°ã…&¢ßÔDÂ|ðb!ªàÈ4Š“{¢f†ž(D9•ÄE/(1> N,‚5$‰µÅMlêd‰›êÁ k::Õ$\59—$™’Tŵ˜“˜ã,–$] ™5‰ÇÕ¹&%@p¶¤\!‡[Rq?8÷¤Uc î۠Ǚڅ’zÇW©’ÄW’*‡ð¦j\š©µÅbKµá\ôVíàQÝã+OFŠÓµ$cÇéЯ)Þ¹r²¡ehÄZ(ë¬÷X\S+‹-5걸a'¸wÛ´ÅbOÍB-µ¤Öp†WìVŸÉ^8¾’ÔÉpïÐZhÔkM] ª«–ºa¯¼bÿ[…žkÇ&{, ±nlSàf|ïÒa;n@Ùb+ ëºc!tM¥@n°€B=ÀŠÌ ¨h€ƒP1¨Þ±ÝTZXQc¼Š½ó ÇÒñ V‚W°1HuÜ7Q¥8× ƒi86€¨S9xÃ5(nÃqœVÔq fèÁ±uÄÃj:®;‚dèšØà´Ä=n›NìgàBáØ%XyÃÆv\CöëÐ Áøpî>àáºÐ I ‹òð‹®qÿ%¾î¸Å0Òßq¨‚•†Êð’qv…åðäÉáøí¿~ºIÇÏooïîÇoÞ~?ÞÿéÕí?Ç/î^ÿpóú».Ï8þñøåw4ÞŽ_ß¼¼Oß‘x®@%­f–š*½fcƺÏÓ“'éøM:þþîÛ»t|š~óæí÷ñ‡ó_ÝÝæŠ”é·é³Ïø»"¤Úsƒ7r±Ü±¥b=c3—!ñH*¹ÁR¹Ô,±•³ˆ,C’ Ø2KIËZÂv×eHºRÁÆÁY ÚB”%ÏE×!ÕëCB8ÍEYkF¼Dlœû2$Û©aã"›çÈ C]†Ô6@ CÎbÖÜ©!»z¦uD}"åLº,=s˜N­.Cò àpb¡¤–#j³X.¼–¨lÀ‹"йäÞGÅ”QP­cÚ¾É%— òázp¹*d”+Æïö%fÖ•x[QøPÇÎ}*T>`¹¦ë—WG>·’£`u$]$sÇOªæ=–y¥DŽú"ò¬DéëeÍÇlOêG¥•5ÜžUdÔL™lÑõ-§xî°nÈNQ¹Á¿ê§=@i׆âðòÖrªÕ=‚¢_ß~q}ESðÎ|Ãøqãí¿´”¯înïÇ _EÇF«¤¯ñ&º¸F¼ÁÂã³×w/¿¹ÁµÓñÙÓ¯ÒñÛ›ŸïÓó_Þγ¿9¿„¼›Ûû7h%$NÐoîÞ¾~yóf´'ã£?ßüðêÅw?§q›ÕQô¢Qè(TzÏ^¼†ðÓò¡¨7¸x4”)úÉÓ‘æ‘çQæQçñÝz›Ç6}ýt”)O¦<™òdÊ“)O¦<™òdÊ“)O¦<òtÊÓ)O§<òtÊÓ)O§<òtÊ«S^òê”W§¼:åÕ)¯NyuÊ«S^=É{~Ý8ÑP°DŸ5Ê\µyV] }Oèj°¥ŠÝcB³€È¹”¶ iC×Ò¢œC_Ê‘kÌiPÁÈ2$¹vCW— ,†›d…§4BÝIý‘@æ×†ah ¢?r—Ñ4ÄÓÒ«®Z¿Í€jMs¸"k¯ÉÐ 0/T®jÃïà >)1]«P "–Á­jó%8ì×Â¥jtÝÈÂ-Y˜±¬µ“h‡—LfÌÃ’ƒK±¯CÚ¡%@¡áåtcp*ÓºŽiÃpÿÑPòhãP/#¯ãÙ0™¨ íèHp»Ec›¥Ú:¦ £ X6rFµÜàlÕ"Ò:¦ ³‰“¼ŠNIcvÈhmÓ†áDeÈF¹Áx³ã“J¾Àž6Œ'*ún-|ò¹ÐS$²Ö×1]=§)rš¡¤éDL«k ºMirˆÆ@™é!¥á?Ž+9„v¤4EJãþÑNÖÏŒ$ÿ͆X­ˆ‡A‰p´ÜA-Á~Ö¬†ö$4”aÐ:n˜%jäð®Zë:¦Z ,hP¨Ëè7Þå«‘‘öd4ñŽK ³.-Áû3›­cÚ1oo‘Åä4À‰÷p7Ó†¬&ð7¥˜±aÏ`é—7“í`ob^bcÙ½^ÄÞ Lm}ƒ½‹é(‡­Ë o¬÷uL}cÁr[¿Œ¾v Ý]EË%hø/áoN!³\;Ó>ð7ì#ÓžåoÞƒ¹bœ´Ñq-ÙjFU=3v"•-Åä¤ žŠk¸< jÙg³nÙÒ;|­;Tã™øÚZ{B´!¹ÃÕx0Ä=Sk)žAX*_O€úÿ‡-ñ_³%~[#娛¬MvÀ&;`“°ÉØdl² mž×&ÛÐ&ÛÐ&ÛЦ¼6åµ)¯MySÞ¦¼>åõ)¯Oy}ÊëS^Ÿòú”×§¼>åõ)ÏËNCáu<«‡ú«®û’ï`1bl h-ʘ­³3q•4FÍm<.ƒO. 1&¢\Ï;C57¡ó<ÆÇ0í?H|žÓø¤ éÔПÆÓ½C¸j°Êëù”6$TCN'æ1MŒpGëëÙ‚êž[ý°‡90ÂÔ/Ø:ÛÁsD (cœ$Ï¡në˜ÚF¢£Ñx"ˆŽ^×ó*íÃëjøHõh¾‚è¶ â¥ï!;â!m®8Ö>ÈŽjëi…˲Ã3¢3*ld‡_1™vœ-úy>©)f±m=±0ïá:¢hb+p!\‡]1y—·“øEÑQ×jÓ†(þÀv4íÑ9¶ãc6qEû¿Ç _'ïa¾žXxC× Ũ¨ ª8ް nY˜Ü6R h×(†ûñdoYÏ,Üw ñ@h4l%7d– Aš] § Q\cd„ž/ÜŽÐ/i<ÚKë™EÊ>$èaìß A´­gÙñk‘EÈ„¿õù–Îë™E®þÐè»ß¯ŒYÍy äËõahp÷ÑÊ ò› Ö£Š?ãêÏ|Ñ¡œb»âÉÞ³<Ç ½ö°\JÉñ›µŠÂ:~̆œñ»ÍÆ9Lûõ¦þ7s˜y•0œ¿:EZøàòø¬üs Ÿó¿êÓŸQyhø Æ6ª¥øÍšvƒëŸ'ôš3õJ2ÝQ³\a]@Z<ªò_xúÓ 0ÊiLuüË_ÿ–Â^Ñ3÷B£?½}ûãÏ?¹¸•±¸¡ *¬ïÿ2»ú¡ endstream endobj 1007 0 obj << /Length 212 /Filter /FlateDecode >> stream xÚ•1O1 …÷ü ÉPã$¶/·" ¢j¶ª%¡K{DûïI¯\&&?ÙÏOï#ØÁÜÜfsó {Õù :¤ ]P=ä+Ü:/ öŠ1q{—O‡òµ«nºd‡R{<Í}6ïÆ7¿Æ¥„)0¼îÍjMPÚm„±Oð=:÷ÀQ86½ƒ¥y6ô[qš2E¢ÿOäD«:å3- £´ j‹Éæu¨/Ÿµ\à6.=]ôÝÁE²ÇÓÖÍ<Ù:Œ¼SÁÆýêKk endstream endobj 1035 0 obj << /Length 618 /Filter /FlateDecode >> stream xÚí˜KoÔ0€ïù>&1~?8²…¥U”8°T(ÍzR“”$«¶üú:k³lµ)ö¹ÄcÇ3ûË8™A`È·¯“àå[ÎVkA2A%’B&H&`æéMcª(&R…$ºLÎVZ„@ŠiµˆBj¯pÖµ›~ZLL„yx·VÃjŒ¹W³ÏL95qc„ЦóEÝ8]&‚ZêU)‡yߙʸùéw¡™{!k™ºõâ…©»Û]fÍæð²X”…lZLœ°(ìÒ§EašóvÑÌtå -ÌÔõ'¦ÎüÐMÓZ{Õú¾Þð-Tm§> €Ä’‚˜0¨v«ºH›d^™tòeôÈ ÇšÑF1çÂ5|/½½{N¦ÝînAǘi2ùÅ'iÚ×c¨9÷ ¿ ªL°AY|FˆÌ¶qbªtîßD72umCyšRªÁ£Tûù>bö0¯"l¯yÝ•ÈÝ^Ñéà”yÞ—šêžÎ/Óáä0tNŒýÖÑ´1€4í£è·9±?å$~ÊéüÛ&$%îO½yñÃÄ•å5ê:óTOê/’*§Ím›JÚôóc¤Phª–Üi±ÊËm^\È>ÀvÄ&vÇ֤Ͳî:þäÿºçÏgeÒ¼#»&„ô r×LÍÕ¼ÚÂ_ׯ£îI‹¤@$ß$Á×ûé¾`Ì9Dƒ,Æ—Lì­3€ Õ Ü®&æ€q 9£V¾£àb]|HÁ6jÏŒC!ü?ëЦ²9„/Æ^E…÷N>)ÛOëÝý¬­‡¦xäªuñÒ와 endstream endobj 1051 0 obj << /Length 209 /Filter /FlateDecode >> stream xÚ•1o1 …÷ü É€q;—[KÁ†È†h/eC$àß®K'&?ÙÏOï#ØÁT}$5œCÄ:é*ÂTµÃ`!5°ÒlÖiL#syë–£Ýæt2WE=k›l¬èëçÆIý*[lö/-FŒŽá{¯Vk‚¦Üæ@èë—ι¾è,ÕBÑ«a?ÿeŠ yûNdÐU°,ŒR6,Jd6Ím>nιyÂ}GúöÔŸãI_o[3°¤sÛñö ÷šJó endstream endobj 1059 0 obj << /Length 437 /Filter /FlateDecode >> stream xÚÝ”Moœ0†ïüŠ9š³ãoè±IõÒ–Û6ª8YK,KVùøõ…µ‹6êV•ªöÒÓ¼óØã<w@p™PŒ¯Ëdu¡ðua8”·` scÀX‰Ê(X³7›ªÝ>͙̈́L¯Ë«#%JÊÅLdF ±E.|ëBõ‡®q)×ìq¡¸À‚s©i;£ò@IäiƉè„ÿè‡1 ÊBŽ…12’R£¡Øà{·õ~± ¡ñ£ÚÝÆmD³«[×® ùW"Ѻˆ?øqÔÍtì©ï"߸¡ŽúÑïºáÕÜÞâè\!·2¡0<´Yõ}ëëêˆÍ¦à}5â°ñÛ%{ö}*¹ò]Ý·Š[pØÏëÏâó´Éš0›À:³F0L3­uæ\f~_ò§Ù_XìWçθ*ˆ~ÖûÅ‚é/á ­ÿýÏߣoÃ?}€\ËÿÔy«Ï:ÿ®LîËã$ÑIr¨·Éúš ™^]¡,rx8nAi‰ZÉI·ð%ù´L%ƒÂu2”ÔtåM¼ò—®sûj¹½7© öôÛ]*‰=>ÝÍÓ„¹îE«S‹ßù$r endstream endobj 1066 0 obj << /Length 210 /Filter /FlateDecode >> stream xÚ•1O1 …÷ü ÉPã$¶“[´j7D¶ªp¡BjQUjûïI¯ “Ÿìç§÷l`a› CÆN5By‡D˜U!uÕCéamÕmÊ ØŒ>µ·q9ÿØU7 )ÛåÐWçÅž¯6óXÌ—ñÍEàÃrÆÞöf½!èÛm„±Ëp{`‰(›ÞÁ³y2ôSpš2E¢ÿOäĪ’ò••…QÚ†µEŽ\‹:ÔÃ˱ö7¸WÈ^núáÓE²çËÖÍ<Ù:Œ¼SÁÆý ñlJz endstream endobj 1123 0 obj << /Length 1076 /Filter /FlateDecode >> stream xÚÅXmsšJþî¯Ø™ûf*ÝvFMbR ¤í$é0ÖÔ¹¼¤€m“_ÏzÕb"ÖÄ/¾îsžçœ]ÎËbô€0:iáêýÈi}<¦:"¦B-F3AVLÆ3˜‚™ŠœÝJÝïÞcÎS¹­¦¤Ëßœ³¥ªŠ†MU 0j3¬`K+Ã$˜…¼\ßKüYÄãÜ˧I¼ÀU±¡s¬ dVWˆÜ&c©çå^i£›D)Ï2a¡ø¡3,L™ŠÅ¸°¤i ž«½,ã™X·pøã±n,S Ó@mðDÕh »SUº‚A·mJ™”åB¥™ŸWcDP*ÖˆWÅB¡íòÙ.¥ŽeK^*x•‰e®½bxAº!Œ’}+xGBØß8ùŽ>vSŸéÝ$¾ÃX}êטÕ=:›r/ú“rí8¶çÇK3bUôCÏOeKÉÞæ?!ˆù+²;2^çf0vÅãê?÷¯ìÁÅÈ]ÝaçìâjݼÀÝaŠUx!«n¹Ÿ{7m§½¹¸÷â|;~vû‹{Ô‘5,uϯÇ"6GÇ_Øt`aý¯}PÔ½R„®Mrôw3ì|umçJŸÑ‰û©?:qNëô0ý­ãr>è¹ãâHÃÁ–z®}S§C7kŠØj֍Т#3,==ò€O¶ÏúËî䥽² òX”©YôZê;wf“IäŧAêö×2îfØÿ篲ô¢ÇSX& y´­\ˆÕÎ_²¢Û¡Ó”û¢UÚ>¸½ä@’¡O;é)-"•"/o ¾|7Æ2%R†ÓøšW¾½~âeà´wa Rß)Ò à·×Þ]F@¸ “IþK†¶ËK¹èò“F…\±_¶³/ç,U𯹍geæÖ0² ùªL$_ ¦0`i cmCÖ’¶0}ûñüéF·»^Þ{¾hÿ=Ž×4IE)-Ä%?exl’iP£ˆ`³,}]Ò¿®X0ÅUk¸x—Ó•b/ü ˜˜ä'q–—¤³8›>Ä<ß4Éÿ#N µŠBØÔd¾&K}±ƒá*K‘ÃóžjtlFã†<^§Ô\j**fp,ˆbѪñÞä!|ÔÔ&ÌÏòå#²ä|ƒ3UC`¨ŠÁ¬&›'æ¾m4KaÂ×Ì&ºû¿ób¾Ëþìá [ap|µ²Ä–—Q?P×LÓMæq€ï1á5w¥±øCÉ-ö½Úrý›¼bWn¶×¼ Ûcœ_ÈÌg MߥVèÆvù<ä¹@u&÷›”·á U±ùvçbɹºirTŠõõªûNëG‹T¨êN’RkùQëöFüu†°¢Y&úU,ŒN5…ꢄÈn].î7!Ó—®7uª0x+BqÂcžzù<ß‹¢û4¿»,ªáÓƒ¸‘mͲTøÞ endstream endobj 1254 0 obj << /Length 2588 /Filter /FlateDecode >> stream xÚí\KsâH¾ûWèMM½U:ìÁÜͬ±1ÐÝ;Ó=¡Ð€lËÃ1=ÍÆü÷Í Q$£vìãbó(efeæ—ùU©¶-l½¿¸ê_üt-¸¥#%³ú–‘’Ò²Š$±úCëKEUëÿl1Á' . ?lφ˱_­Q[U³ÁrâO/ͦzðE³ñrA`,¶ÈF¤RHQn &_~ÃÖ¾ûÙˆ9ÊúŽœX\0$¸Ö1¶z÷ø¨™’ ÛÙœV ®€%óÐEhI,â§knï\O$²•mÕ(G‡×¥T$®±¾Ô„?’}§§4ŒæÖ Gi'ܯ>,&ÞôÃpî6Ór¨mWþuDÀ¯n£êàÊ/·—íVÝýÐèî Q•¿­]Ž×ÿÞÙëW Å•Ëðo?[î_ɱU#\LÏášÎhÚö'&§¨cN©WIå®Ý¾»uÛÍö«ýÑiÝÞ6Y¢ÊtÁýª1šû—…“£ÕuëwíN·Ùë#3´¼FóÄÓd\ÝU9¤Ö‡.egr©x×U†+³9LZT&^Ó¹  6ä±¶IOªy}á¥éò«³øzWäû_[‚îN‹q›ÿèŸAT÷²*pås¦¤TñÅ{.»n÷ÝÛíõØD¡• Ù‰»F*j6AÊvÎ ´ŽžËl<M¡Iù.T"•fÕiv[wVýòÆíÜÝÜ´nߟ#®ô4>ö~9$³\ÜÔçƒuWøþì»}^­w댞Ã#—›f·@ßÞÝ6|!ïÍ‚oU"*ÞܯÏ&Ï3pÅØÏ).MÉX~tE†‰ÝöÝëV·ý¹*¡{w›hF¤F¦½…¯ÿ™pKDÇ'Tý½Ù½mÞ¸nëÓ:i]B!a‹øZ“tŽ$gFá{±LêX96S¡L,€cnìùŠ9ŽFÉQ Eâ15ƒÞ§Q;éÇì™p‚˜ ‡'â(aœÈý¥&h}]x/;-cH¢ø ôQ æDöJƒšÞÝu?Ž»ÛéV!­îtQûÔj˜ƒ£"Û9ýeÒJ ¦ Z$AD˜¯—ÓA>¦œU€ŒpÑ ºzÌŽËÒÀMƒÃ{€­ZÓQ`ºú+8órV±Ð¤«Ÿš#Ös„T ³²ŒÙÛLÄÌ”9'/@®.ïÖEn9]Œ§þpýnðäÍׯšž|s÷:Šÿ\>ƒ½$Õ ,b9ÖËwqÏ–Ï‘¿Êsµã K¾ã®&û®>V™×t4…@5÷&‹#æhX0žÇœçhC,ÑÓãGúuÑXrbŽ%'²ò²Ò]i®f¸üLAĈR/\ÐʪNP -ÚBG¿ ¡ÊJÅ Êöv÷ᤴ™v&µDNL)6*’S‡;ö§a‚,P:­“lI{bß®bN†þ"0– ŒRdÛyåG34ë_Œ½E`*lÐk´CK*lŽ8RØ`À @zMNÅÈ£u­hYCœÚ¦/û,D`‰¤¹0¸A„V˜ÔbÎ •ÙűֱA` Ëÿ)DGŒgÓGS4%0^™+ó±£Ëê?Ô9Æ% æ[È}Om?ð†^ðñšî38–ŽDõî4£ñÇ0ßâ/1 ÌlüÙŽS Zá®–¬ì¬1ɶy79qHXÏî±U„,‚µ= ™ý•2VlF%ዱéµµ>—Ü5@8F‚æÊ_ø?7]vêƒêûU”îÞÕxöûጭ1 e"h'‘ޏ¾À|u£Âó‹ ½ÔX><¸‹•;ÓVÿQ¥¢âÏaIoFCwÝ’¸xÀuƒ§ùâi6:"˜”T\㇋‹ð²jøƒ z«¿?½…bŒ‚ô–qmÑ6gõ»Ìb¢NÄž©˜p•Ò’ÑÌaåoÛ9uDè[ëØiæšÕO3ÿá䕉cÉ.D"Ù ôU9Oó„8 Gmžö¦yj‹v2QˆCùîpYl9§&µdæ»R´y]§¹c#ÊSœÕ°Ñ³¯Y@¢ç«]:g£­¤æOþzNJàËÒú/8Ø:pM;ÌÔDKõðó K „©]¸“°m'Á‰³‘e#Ç)ÜIØVË6‡¥6×Í9 Áe¬ØR‘%¸£™³sR+ÐAö5d‹ÁËÜÈÝF6ûW\ùd9É'Á2´·¬3â JPja’ŸŠª0¡Wl†C8Ç~øj}7Ï÷æÃÐîoÓ²7Æ)ˆÐÜ+XS¹¥.·çra}<[øåÝH6â'ÕzÄ_º)·Å›§Ü{?è^°\”ç3ÅçªX;:vó%4ý°~¨®ÛyR<”jJr¿`o³ž4ü]¦½å8xMäòܵ¢” œ/÷‡;Vk†DxƒbœoâLаÊI¦8Óg¾~åIšéΰ‘ÎFCÏP´ï%‡AajŠPOí %xYµ½ñx6È Âb´ÒeÁ›ýbõ.µ§ñÒŸ?¬Oì |÷y4:f¢€m^²OÈÇKí/ðc^U$!Oçd”Ù'îÏdí¦c¢¿rã37ý’4͔Μ"*Ôë—o§æó¡˜\W¹¨ÌýL^qú¼”-s­&Æ!‰lÎß<;cO””‘„8ÅößÜmr=š/‡ÃyÖäOÚ®¡˜!fçÚòL8Á 1a—‹“Sxw´ÉÑ æ¾7)qÁ£¼œ“<¡éGȤDÂÉI&£sâ…N30Œ‘Râͳ~»‹Uv€)C¶CKZ-œ`õL0à—½9~›ÓaÉ‘%ÊAœŠ·…n¾ehYSݵ •åSçpÜ„ˆ×ïé³áú`ø§ªÂ®Ãr3ZûÒOˆêŽÜq­éšLö6þ†ó-»½ç‘;Š„WÃÓä5Iwñ¤Î:²ÀÔI’ÿ¾v´`pý±?ɸùüæÅ7+ÆõÙrœFBÌn£Â zà³ù‹J}b[¼y9Ó.[¥ú| y}6…ÉÑÇòÚÇÀÏË9aœ˜Áa3XÃR™óæ™äî ’njP\!ÊÎPè:Ò×mzý؈2Ù¢"’7¢¹\žQ}‹™”Q)Øáˆê/»ëÀõƒ ]ßîË¢ër¶Ù>Ї{ñenT“¸ÝæòèÂSËÝÙÛЗDJ qj#…Õ ÑÔcD‰ÀE‘äs9¦Rx>è”4Hºhöð°ðƒôVŒaOBJäjI=‡6~Œ›†Ûŵé+¼ÇʼnÊ`aÁdqeOÞâÉÔñ?S}ÔǽhrŽ¡I™Ðô9ºßøûÕ¦T~L ¾‹)0>VNV€² +ñXý‡ÁÊôSB ÌHž_òˆÁCçx_Û!8ð Hʨھ÷§úÇ;b¦Z÷=þ‘ð,Ä÷G@ÖÏê¦lü7Nb` endstream endobj 1004 0 obj << /Type /ObjStm /N 100 /First 999 /Length 3385 /Filter /FlateDecode >> stream xÚÍ[]o\·}ׯ¸íËgÈ!‡€ qà6@ ¤±Q´1ã~:Fm+‘d4õ¯ï®Fr"[»ŠïÚ}‘¸w¹ÃÃÙá ç²t¡£B—ÄþçŽ(ZC;¦b é831uq÷¤v9U4(t¥Ú¯‰ºÊöYÇ’NЂÆs´RGQL&a„´û†É±ÉÀÏJÉÖÒŽjlßÖŽC6y:f¶ß2u³}Ëܱc |Á;$œ:Ö`ƒ3àÖ&™sCMÖ*]ähXX»K“W»( †Œ¹áC—Xj{Æ]¬Q0FÌ] ϨKd°ÿsë»ÄÆWÇÅFîR,˜H¬”rQ´Ú3 ’rÃ!©K%›|¼ÚKî$4䘦qR;á6qüÏm¤ÒIl¨³ UZo„¼åõå…-Ovrúýrqöæ|Z.vn¦=ûÛ2¿¾:ûµ{ð@ªô •ÓD½Ö1Þp!]Å‚Z÷«qvË7˵MLõ:¹bx.QnÏ+ÿærúåë×gùtçb Us±W ò{#z#yC¼‘½Q¼¡ÞpÉì’Ù%³Kf—Ì.™]2»dvÉì’Ù%G—]rÜIþ—m¾'§ßŒ—íó·/^ÿûäô«³óy9oŒ…OÿzúÍéçÔ>É–GSo-•Òà R´µî’–>RD§/Ûâ>îNÿrö䬃nüéâòüÍtù÷áòÉOçË0?{öøÏ¶à›€Š}jh´/`†Û§°ÃC|?üòÅÙë^zÚˆ³’SßöSÑž—"}½‹—·ϧœ Óë‹çÇá&g`¢n€‰„÷pÃÛs#±7WœBw{1àÜ©2o/€sZ$õ¦qM ðPݧ2q{ZàŠmÕØJ5\|z/paë‹ã°“¸GrÃPqÚ§4i{vþf€=cwOp7©ÆÃÉyxöêÕ±(bÁø6ØüŠd{Ѝôj†U+X-î%ÞC¾^Ö—Ãår’Ž9¿£G#í!)oOR¾Z°ªÙô¸°ʇ“ôíé8…Ü+½ã ‰Á‚Êæ!áêk6-âÞr>¸æɽz|†bM½Ê;{;!ìßÃnÏro¡!©Ú ÁEîQ¡³õò?4ÿ±œSß¼^ώðÕp£E† ûþŽêöa³ôšb„Oª–Ð÷…öhÑåpùæ8»˜Á©éFu ŽÐ>㢰=/ˆ[>‹Åƒ]Ìnqî\"\~u^§ÖwÔpDd/ÛÇËHÈ{²óì冻ôe—D|ûââò8̤ÒÛ©Ó53´ÏŒè7±rˆc:,¾ÕùêLñzoùßA?õ‚Ðí¤;Õ=@ð9¤Þž‹”ûÌ…B¦['â9¼x/žÃKÞ2gAð§vœ‰0¹v\áðìÈóŽü÷—áò틟ŸéOÇIÃ%ñ½Òð¼eît WM £ôÙÎŽïHyyûìÙ›Ë//ŽÃ’o;î¼I¾,íc$Þr(¢÷p(ïvÞëPÞÓùS;”œoaNÈßY–ÏàQˆã­ÉÓG{”ì}ÙúŠô?è+~„XÜýw?ÅÝOñ#ÄâGˆÅ%—¬.Y]²ºduÉê’Õ%«KV—¬.Y]ruÉÕ%W—\]ruÉÕ%W—\]ruÉõJ²U®ä öFôFò†l郉¼p¶JR/¥UÏzãYBøð™ÉÑOr®Q•ÒW«_Àæ¸óÉR铟»]ãÉ;­'˜$en±¦O!\£ê‹oþJ¶é¯~žÛkL†«èîsÂî•*V®|êd8#¿EL®Pk¸yVle–ŽC«ß¯>ÏÏÏÞüüìŒ`<Ö0ŽëTyiš–©Œkæªã “Žqš€‰ŒÂ]°Jo… X,±©¡ÕqišKÎ%€¯y^Wˆ*±Ža:Z$l…©½m‚aK zZxë(…fVžjšrˆKL:Ó¸2E z´‰á8Te$ª¢ÀT¤Æí’—Bi…ߟ‰eÑ šf‚R,K©|´ #BÆ1÷[S„QåB»ÄE ´ÃŠÉj×Ì2Ò0¹ ƒ€–JÏØ ¡ }úŒ8^B[K–4`Ýu§!ìmMa¡CY—|´!Á1aŸC²Îð©Ç£ÃÀÎ5¬z­Ygf-u,PØ…™°¾ay…àÙžÝ(Ås‚ºRÇ‚¼¦S¥Î:Œ×V6«äac7,wºbèm…˜±Ýí qX¦0¥9,¶Æ€:Êš À›ª­sáìõ$äYÑŒ . xÚœ–!MS®šç–"ØzµÆµÈ<,eÝÒÝ6W°CË)ö5¾ÚTkÀŒWJ3å,Ä…ÖÂeÅþ€ø[ùÜ"07ËDp Ð84)‡YH](Ã.×%NZ†i(i˜Ö@ºÄ°n¨·@W £µ<iÃ}ÐB –E$§±Ô%“®<çu™Ë [ãu8·îÿ8öö‚ÁÖ8„u±Ó$9ÌÓR#dD8(Œ)-æ¶¥Gˆ=2;‡Z˜_¸V3A§‘g%‚—ÍkJ±A&´®e{^-ŠF~jÎLÍp¹¨ÜŠ×E*Æ9¬e¬’t‘Z¦E5N…‡!oI¬`»º[µ·„ð>`ã"k¬:ð°!¬³"N,‹ ~ÏØÕò˜UêÉÞ^ ö¢ <õùÀ0œG‹+ÌŽÁ×,‰×iž£Ê˜WÙ0 çP{{eò-r=„©÷B«Ø²–™`iqçeÂJqå)EĸQç#p‹€6Uh@É}{ǰ À=,®‹)eÈ«& \æ4Oaä ‹ qKGk'¼î l ØŒÚÃÁÎã4gÅ‚'’ȃd c–9Ä8cÙ0šÁÚ·ã6²rNJÍ!${×8ƒáwÜq-&LËPÔòRu”Fj©ä4nͰ½ì‰øÀ  (µW7±·QüLç7±Ð†â U´ÑÞN½Õ-óœ—Ö?3"˜Ê›RìTTó¼u´Ý8´3ŒªmÛ{·—-µýô§Mæ'C|OŽÐD¹Ï-¿9¯K¨IÆ!Íš—"@—±D5ó K:{ɪµÀ¸íœ°Û'úÔgc6ºätƒFB¯í½ì¢¹•81Bº0COÃYþcw\&D#ªÛžºj1=°ZňDðôsŸcã„z¨Úwºuü×5𒤦<˨Jq’adËH‡°%y ?:µW¥%Hv~ŽÝš<†â±|sÄ®2ÈbÌe6B®«Öiû…Æþׄk‚¤Û_’O~6jGöþ‚ƒ±²£ä»ÀÜJz4e9ç—y®œªç5 Ö;Õ8—ßWéêýðƒ*€¿é¼¯ø¾ÎRlã>°oLöÂê‘A¢Ã:'8 ÎM‰‹Ü·hyú(¶ õ£ª~,éVÕ…?¶êGW·*Ú¥’«†zÃ+_~Iü’ù%òK ä—È/)_R ¿¤@~Iü’ù%ÿJü«ì_e4û ÙÍ>höA³š}P/k’—5ÉËšäeMò²&yY“¼¬I^Ö$/k’—5ÉËšäeMò²&yY“¼¬I^Ö$/k’—5ÉËšäeMò²&yY“¼¬I^Ö$/k’—5ÉËšäeMò²&yY“¼¬I^Öd/k²—5ÙËšìeMö²&_•5‰]mØÕ†]mØÕ†]mØÕ†]mØÕ†]mØÕ†]mØÕ†]mØÕ†]mØï¶°ßma¿ÛÂ~·…ýn ûÝö»-ìw[Øï¶°ßma¿ÛÂÑ%G—]rtÉÑ%G—]rtÉÉ%'—œ\rrÉÉ%'—œ\rrÉÉ%'—,.y÷ÚÔ–E猕/ð¾»›ûˆAK¾XõÿìxšÝ#4¸FËʈŠè>h÷æçQ#œqš4éJ²VQš†eóP7<œ‹Á.¯ðõ|"²ó ?µí|ÄŠNØ8/<­±DT]! .e¸Žþÿ” endstream endobj 1262 0 obj << /Type /ObjStm /N 100 /First 1036 /Length 3378 /Filter /FlateDecode >> stream xÚÍ\]‹É•}ׯÈÇõKtÄýˆ þÛ°/Þ1û°ƒñii,kXì_¿çf««´j»TéšÑ©ÊÊ8qãĽçDFv¾l~ !àGb;ç`´iÎvÀ[Šd²•Xì@ñ#%;Š[àl§§ªû§øRŠúG8-û]ÉoöÛjÞˆ³]‡‹I£}ñiJöi •dŸ¢EjÍâæýÎQ6ÖhíFÝ8%k#Æ‹N| ; ó&”÷ëÊ&íÎÉoÉ${k7Ñ&eï@jP D’M9ìÿ§›Jñh#ÅMãŽkæýº¼EïÅŽÊŸ£‘ýY,èjTë~È´ÅXì»™·˜£á˲%Ïö]„.‘Ïh#Ç-q¶þxÒ Ÿíß-[ÊÅÚ(~Ë>Z%l¡´#Ú2ºnG¼eÍvç"[N{üŠn¹ÅªÄ­ø²#m…v,8-"ÖZ)^Œ1Ëo%Ùh‘[)ºÿnå%;"ϸ‡øÈ âC`òQè qcŸm(Èã hr¿ÃN&ݯµÈ0ã–dÄ ‚¶q¸3ÀøBa„„À;µC»Å?íœ5¡µ½µA!7ŠÖC2‚ûðö6.~¾%á#fc ZcÕý|ÄÉxB„Ö¸øýZ|$>Yk„Ö„žo†ïŠ„ýZ´&Z¬Cö]IqLJ֤°ÝÑš‹Y·•öðÚG*{ÃF´_‹sM#FŒÖ´è~-¾÷)µ:¸¼_‹ó¸3œlÁR»™.f‹2 ZCDìZÁö›‰Øt·î]I˜o¾ùæÍÓþþÃÜž~ñîÝûož¾ý±}ÜÏÿóûwyóôË÷ÆüðG¾ð|úíÓïž~õ]ØOÞ<ý×ì·ï€ÎEP"9oãÕ!@ vpʸìÛ7ßlOßnO¿yÿ‡÷ÛÓ¯·ÿøÓ‡÷?þðöí_ëÇÿùþ‡·ªQf•Þ8ïgRLÚ\x%u¦Õ¶ýüçoðï°)8Á`½€EМå›8^ƒöëpkl½çåûX-$ê—o<ÀVï9ЪÇõ‡bpYùÔ&vƧëƒEw }I}®bÓ¶uäñ™dª$:px^¸ä‹Û3C*ŽAù²ËI®#SÉå“”ÊäžSí5Iíˇ<Ù¯Ñfu˜•/`)E§˜h7€ý:ÚŠ¤;ýjKŠ22•˜1,}6?;õ®r©$g™ã¥?â½Ë¨¯÷g’¶”…Ú~´12ŠO¤#>’?®?â£cý¬?É»Iql✖U¾)¾bfì‹®T­§?~rÄ‚~™ø)Á1Ò}B?}WMŽÞ€4Ñ>KX=¶¶Pg}™eЙ©ˆKÐG1Ë>ƒQŽP€]œ×+óì×ÀÖ–Z*y![­ˆÑ·bó#÷6ù¶´c_¼ƒ†8ué\J÷‡Fæ}YJemeZº\Z…gmqé8RU‘ËðL08™cƒ‹r°á7€ý:ÚJiH%¨rŽ=TózQ¼1FšÝ—3­’ƒp;u‡=º#éàþ DHi¡…šxt’^rQj5·øÀÌ­ö\ %Sj«4ÎS>¸?^¸ ئ¬s6§ôÖsÃ`M]óß`9"³ó0ÖpÉΆGØi¸Îq@ÎzM©Æ•áõŒZVáhVÌ|­¼UÊømë yS`Fèþ)X üPæ?¿­ðvÅ‹,(ת¡AZæÑ²ï¼Ž$=r²³=EP l\f';Jºëj kW¤CPLQ“[]™‹/"):rü3r!jÕKL¡ŠTÃŘ¾JŽcM¹Ñª 8&IL£61ù)Ç€Ìö—3Ìî? Ôë!ûÅpèëU¡<‚úÔkΙâê^‘& +Þ9šM ŸÃJàxwÚûqfÕ;œÐ *ŠO7mqÄé…ƒÌ+ ½Aþ–J„ 9ž°>»bKÙ/„…ñø Y?ì8mUž‚)>º„ó˘æ®3Œ´jBÞ—ÁÝê—ú2ëé@º¢d¡6‚JIw‰qØ»g,1³ÕùOã/…]–GJX) p²ãøœ°”/ý2¨"’Z­­¢ì­d çšà—ÔÖS<6aÙªOQ¥ ]oào{ $p<‹™ò¤EÈhÍû:®­‘J¾ŠjÐUMÎYµvFåÒÕ  )5ŸÖ‘5 C¯%žÂÊâ@ÇÞ„ön¸Ÿçç² (­Ò*~ú„ÚuØÉS'¼¾ÂºÁÀº¥… ¡²réÇ–Èi>‹,ar¤–³J¶å‰À–³ÈÙ3HêåºB yj4Y>’ŽÎ¡ä4Ê(ÝÇÎ#™³LBT½„•àóĽÖŸQ€ÁÛòƒ¥°ã Â*Nõ§\ùX¨·(ƒ!U¹ÒBð¾(æ)íȇŒòÖ‚Êê]úJPB§U²Ci.˜U)91N:›³j¡gûNt…&|Àµ![8ä´ïÀ°"v ç—A-T–Gñª1èè(ÝCÔIPàGf,èdª—¨Úê-å›ÀÞ?a,L8ëF¦lƒ€ï5ìÐ/£JEÞë“ ê·èÊaê=¶µ—­#n%3U§°B«¸{p Úûs À èy½­¸@H_\[oŒ t ç+ÙR´Í¥­Qª-PìCgˆfLJ|èz ‚Zò)¨dùæå°÷#øAËXŸÀ²d—|ºl§>§)ðXêuÎ8³ÒìÙGȇ³Õt =³z4?] *;eh¬`@ÓE ¯•@ -Wñµ4ßÃÊq¬‚Т=á8Òiç=ŸÂúŒ2Ü„öî+Ķž‘ø¬[L(ry@ÝB™¢a[Û”.}µýª„¬ 5oa¼os‚GmÅ4¹–q,Jɧ°²ÏŽ,ÑÞ€öþHÁåsÑ¢l›XI¸$q¶ûÝpz{N„ª¥ñ(ÓuËXHªQHFˆeÄ0g‰l;ØRÓÑ"\ØñAo½?/½Ãѹ˜ÂN,ÍÎÞV 1OH;P‰×QU}µB蜻j®l­åê" zïtâìý‰—°š,–‹aýÉM!Ùò«œ ,)ü‹¨5 VÛŽOh/E ÎÚ †3úëTKÊ¥$šÁ¶èU?H{&äÚÚ–Ì5Öñ[[‰^ÏA‰8±˜vk+°Ùlè•›éKÖX #œu)KRî(^£¹¨Ç#÷áØ#-̃STÍèN‰ÕŸ~^AT‹½SôBtÂgy@ 컜ð›æ™=*(¨´éÊ=ãªuzªÞ¥.]ªI°8Aèø¨B§ª~V± ¶¡g0ªYKž×°ì½½K@_U¬B2C®s,ˆÂÌ%/Æi§¶J’xpŲì^ÂʤÍá&´w\s3Év ½ Íä|¼ ­d‰™cD¯ç…¢Ï=.VmY ¹ãcm+–xf¬·­òxŒ ¶C C­¨wQãE ¯9ÌPæDUžú¬ÄkÒi 9rÁE¡±ìÆOaµZ{ Ø;–3äj<ƒ-æZn{¾Â°d>?Ó²W‰¤¤ä+€z‚‚0_úН¡ó"VK§2c§¤^Ý•’œÂj²ÔžÁÜ€öŽ„5fJ9¡eMÎÞ¼¿íý {UÒYi…»Å¤´¢î‹n4<¿co®_€ùeLë¶UàJE4e@ ô}]¡)ÀYcÉ…ý}òç  ÁfÅËhÿöñÃýãïÿñíûõñë‡ùßóÃß¾ÿîwïÖû·o¿=~¼ÍföÔ³ÀåðˆJ³É–þ³éÐW–U“„)Ç ]vÕ7X-˜VÓÙíø…öÀÁQùl‰íx@¿Ì šeÉE{üÐ×yßÖW{N¾°vߥI÷¾å\Uqr`Þ·uÀr+Ã`Û[z· ½cÞ·ÅÛËô)¶0ÅNìonÜ€vƵ> stream xÚÍWKsÛ6¾ëWp¦ê`|€¤nrkG•SËŽÅdR' EBTù¨ãþúî DÒrkeÒi/Òb±Xìãû‚kƒ“ÁÑàÕkê¡5ò}׈VF@¬Ð÷`äX¾mD©ñÑô,{xæ¡yW±’~ʳ]ÁÊ’çB)Îo§ÃÏÑ•áy¡EiÎåÒ*—Ñà÷ :bØû ÂÐ ÏH²ÁÇÏÄHaîÊ –; i™u-ê¹ oùàí€ô‚¶‰Бߎڷ-Ò · !æ«b¾e©Îƒ•IÁwFñ½zí­ Œ¬Ž”›qŠÖà‡šz‰ômXÉ”¸ªE‚¥–;–ðÕ£Tv(²ºÄÌ 5H÷MúÍw¬ÚÄŒ•kØÞ’Ålª@,‡¢ˆ(Hàõr VàQ•ÃËââKÙ]¯ÿû¥„¥”Z>Ts_EGWñ:†B8}SÆO„8‚Šr‘'uÆDJK½çK+}ï{ôö|8"ft?½]@±ï/ïæÓ›Ùböîzq}~us§üÔ¬Q@ì–?ê)[qõö¥·¿ñ$->Jø±ŸÁ@ÊÑõƒÐlÈ;ú“ï†gnèB%~ú¡c¾†Äd…jÎÍêlÉôäð I„¨@¡çØQ0Á™ì°ÃC‡vvˆ µ %‹3Ÿ" y©ì[ÓÒüo·JZ2eÁER°3IXÈÔ¶­Õ™b÷&žë6L ä˜%_ ŽÍNbQ©Éd‹5+Õ Êõ?æ… d¨ÙÄ•ÒäIRK!ì@ñH;̳% 9ÒG¾ê8Ý—ÅX¤Ê(ã¢ÑµÒ>’XÚ«&jÁq 3êP©¸e•uªŠvyŸº’]@‰C! 9'lOß§„plN‡Î 1}/BHO{B¸ßJÕ‡“‡þ B8¾§ ’Å=p€DÿK ¨c„.PÓ"‚ëŽT ¤Ã6¤áªçTEI„^D€Â¸ ý#9þ_‰à6D¸‡sûÃbÝMg“Å/—³Iôó‰à?æAÎøÞ‰h—W|¾ª0•¸x®8e¥P^'U Fºêm¯Ç¨àÓ¶ õ\€Á·+ÚB}> T°- F¬Õa(ÿ%­@h…W*G*œÑë›ï%ï@!¹v˜/ë%¢!%Ò`¥Uûx·|©¾Xp)1AmapBÍìÅ`ð`¸ysr÷aÉþŒ#ßpÆaKçíϳ9|äÔáGîÅËÖÇaså@+e⢡ à…èPŸ ­¶¼Ô|å)4E^Ϭl¡1Þò´3¬›éQËvVe+«ÓR¼>s=Ïœ×I>_ÚWzèëüÍôbq "æùÅb~r—•µVê¼ðŸûå©Ú> stream xÚ­X[s›8~÷¯`f_`f£’¸½m’:]w“8éd{†‚l3ë€Ë¥iúë{„$llânœ}BôëwÎl, l¼…£?.fø(p]j„sÃÃÈw]à rm#L¦­Ïáƒ: 1›Â¹v÷ªH›·Nˆç›¯Š¤¹çy×Y‘‹—Gãpôudûذ;LßG>aFr?úø)<{c`Dßxhß¼7˜C‘ÄŒ•1½a¥'FÄKqQZ{CZ»6ò™RûÆ"ÌŒËøž×¼´lÛ¬ZÍ4ä † žÂõ †1Ê: ÿg a×1< ¦aÿ¼ÍÀ‚.qŒ\B\áŸ"B QäQOz$ˆmDr´Ho+ 6öC‚¾ÐªL¢êÇ€` Ç f=ÁÌAžïöOòuSËüLã:–«ÏõR®Áíõ‹E°ùXóJÞV¼R«¬DB·7Ë8Ou¾Â^Y.«Ý¨ y-Öñ׆køªŽóDÝÁé |*0{ß=±Äæ÷ìg$@x‡!~ÕÏÇøœuƒŽù2f·¼nJáâ›ß,Û1ãUÃÍ[7ÀKj¥\ô¤/‚¬u]†<Ç=*â" ~|ŠBž‡#†ëƒ(]ÈR^Õ¸SÛ;VpŸB¢°¾ä«ø»ÌÓ¤¸_—¸<Ý%TÑÔÍ“ ¢‰¬ʘy·äê©*ò„bÿÚÄ«>­ðïê~©ØTŠ<¥c* o‘ÉÒa‰–…ÛFãHsÞ~ˆÎ§W7·ãÙlü*š}ˆ¦Ñøê&|]L.ǂԔ 6î©)˜¾Ð\/„%­<^~˜¶÷ºH¬×¶B)äOè4 Ô(ÊÖêõͰ-a°˜ Ç«•¬x€"·S.Då-1DBÐÀLbuö‹:ÚÈÖ«‡¬mT—FXT÷!ú'¢YüÛ¬å¶,JŸ¸m$íø™‚¯jù¸IêJîÈ9‹n2Uí·­„n;†µˆ®\ë1mÛM~×FÆ×§g—ãh6½ï,²åv afˆPK„ó"_dó¦äsŸrÂ`èZ/Ç«•vÇP¤žPaz}iÙ·ï£ñ?ãów2Ó”.ÕûÚtÓkW! \êíS ·ä3ÿ›¼›:Mð‡>ÉŸ>BÇv$sÆßkž§z’ÙkËY.Ó\nÞwŸ´»¸Cdñ4Y¼a²xûd\õ¬Ä;ï§»yÒ%&¸‡Mè& 5t 'жgµéi–Ä݇P6﵋3˜D·­+u2Áî¿e‰>+sF·^ö|ªφÊמÆÖýu…“«ñô]øl}uŠ/ã2íÓ­§iuÊÁ`;蹉âÛ¢Š–VÀ†Œ,v"¯ô#¯lf?5)ÂízÄ­ ýô¦Ôè‚ӧ“Kùƶ½p».*¥ôßDºM2xRÌ{*aóòS‡¶&ùò·™ë—Ú%²e«ÝÎ>ôæ8Sû9?xô(Ïe‚¾Ìã%ƒ+r²Uë5Ïy †§Ûßú×SëíÇ…(:&Ïwuü šž endstream endobj 1333 0 obj << /Length 1079 /Filter /FlateDecode >> stream xÚµWQs›8~÷¯Ð#ÌÄŠì·úÜ$séMÓðt¹N‡€ì0gÀbré¯ï®$°!4!}bYV«ow¿]!Fö„‘›Åñâò:dE×aè“xG"FWaH¢µGCNâŒÜ;‚rwéE+çc¢#m«âX˦ɫÒ(6_þt¿ÅŸˆ> "œë¥œ£vq/þ[pP2ÂûV+ºòI‹Åý7F2øö‰0ê¯WäI[DàL ³¹[Ü.Ø5g4 Öá9ìSv†›úî’3ÆœØ ™ó|”™ÜÙXª´-d©…1ÈQYúœ®@wò…yÐÞ¾äågY|ͺ( ]GŒŸ¯ Ì:ÕíÂ2Y¶…·ID½·ùz³ ÷ÚÂ:¾²V&Ü·¬ãõ嵈†qxmàܵÇcU»KÁ%3“‰B¨ò!?F˜]Ín±Mè‡L6)˜òÀɪ¯}ü˜7F’¥Ë™y­ñ™ô[òF)Ï çù?Œy²yu{-6p\¯7½Ý¸ÞâùÑõ‡N×Q°'¨gëxûc[£»4ÛªDTûW‹*&ŠÚ¨ºMÕëeÅ}Ì»|ÿýn^u‡‹fÙyžÓ®_·¡0bjãlm‰ú*Bº²L[ËAùY}Á»ê ¾zp¹#vTI^6Æ<Ó3¥Z`ûro¬Te´“øðCµ3Oõhý6fþX¿6Dwm™âºä«gðÂzgg•Šsºî: äKÚƒ²¬C(ølÅ«íçÍ’¯<óörÒ œ"9E—ô–ñl"úc"vsêÝ4|{¶h>ÅèûêŒ{03É75bÒG™bxÿ6²oòyó}ßrÌ÷½É ƒf 4œ0¸F3? a FÃÐFšz¡òت˪Uð0¤-u—C—h*XÃ4±˜¬Ó÷.¦˜·É²¶²Ï²*¥Ëß1ÉDO <œ¯«€ü†sià~6}ÆfžQ º¨è[ÿ,ÌÑQêj ˜”–X]‰P—cÞæ³uG/&ézK/Fô¡f´¡ô’ f¨ë3”oadžn½æ” |…\P+½²‘¡ z—S´3¡áÆO`D0!‚µ¯& 4ºCezætQ86˜Õ“ÙàxÔAv6ÏF¾ù[‡Ò£L2¤¿„¦ž¨4ñT >ÌÑ[F¦+gã4ß1‘‰»ÿ¯dyú¯íPX7D9»WƒS¯æµÔGÔoó'ïó;uhæ¨ïnÖÉt o¤ÒÇü¼i/x׎ M¶#ômG°µ#hL;‚Ðt÷\‘uZ«Íºž" ¿ø³\0Ë7/> stream xÚ½M“Û¶îî_¡SGž©}P²üzi^’M·“vš·î¥i'Õh[SYr$ªÛÝ__€õemÓôð.6H€Ä7ÈwŽŽï¼]ýw¿zq 'õvI9ûƒ³õ½4Iœí.ô’ÀÙçÎ7׿í¿w¢Xx"ˆàœÙý¡Î»R­7á6u_×YwV•–º¨+$^½Ù¯>­ õ ¿3M½4Nv^}øÍwrÀ}ïø^´KCyvDy±@¥s·z¿ò?+gx¾TxyÉzø¾ï¾ú®;βú.o>îQª7ÛØÙz»­à¾³‰/…kÍiýxQ¹:¬7 VUw6ŠÍ‘UùßÛ•óÁPL®ô$í?;³Ÿœyq#¶#õ@¶P€µX³ý©h×›(ôÝ—?Ý"¸—¦^±ûG‘+FÉ,S-ú&ª®ÊU‰Ýò±¨Ž„Ìêó¥Rt–Ù8tU†®ãÃEE‡ß¿\°ÜÓîI6ù²”Â?o½ÛDS3ÉÚîr©©1¬h̨8_J‘²1J·‹cv…Ï&LcWŸ¤&hªg˜&Sñ‘¤E#h2E;…ÅÔÝËlÂȲ$ >XŽLѨO]Ѩœ¶QÝ5ñîï‰ÝªfùäôúcT”òW%ß„N@µáþÄ•uZ üŒ0Urk¦ìŒ¹vß7s*!÷„ÛíÜ=ˆÓ§FÉܨ +y¹”E&) ÈÑ‘îËñ¶!ÌdÅ7zÁõtSÈŠïT2;ÞØÛðT­³o ß_ jZËÖ¿#ØS/ŽõKÝ\ýêûaEÚ€•T£Šjj:qƒAKD¡p[ Í"+ô㪇û5ìFG….dY<É>=)eÎ(Ý]´„«t(KKÜ(LÀ 0Ä®(Q#·¾×’òNÌóSLbÀºD¤¡{{ ÃúÄLXÞÅôb%€0ðY×ëL«’É„$‡TËÈ ð=„œ{ *FOÄضpA®®PhÕj£ Ú:HQ‰ŠèQð÷#‘>˜ªÌÓàYŽ±Ž éøPh ³8p±’ƒp²+1OcTçhÞ¨–ð‡¦>„gLJLE žé‚Ô…î½B vãd‰lÄ)ÈÀ ˧5%ÁÄ6¸]ßR Œ–X²\Ùfª’TÖ‹ÚÚb¿ÍxÿÞ&À½*M}X'¾»”wãÛèL@ú{ij%£Á%Õ5J›ò±/N³¬µb°K6lÖ±oåf¿$-¯±¿`9zòÅB÷éé‚ÿW?ö¿jñäÀ¦-Šùðñ^f(Âï݈‚o—©;L€;òçÒé¯.’M@'gÛ“4EÔŒOÐÓGSúç}kÎ Þ\põóªý«ÆëàÚélÊk­ÚÿP+w;vyÞé>´Ç@¨ AÛ+âbxh ¥‰!“Ùð/-bñÚio’S:©µ}ÂQbL L"8=¢éÀ®¨þ¶æŒŠä´1¸ »Ÿm °Á aæ7ó?I I+ӹ碂  %*Ô´î4-Š»CÛ«dCMrË(§‹3LkÚ›¤Œ1ÅÛv鲑,šà¾ïZœ$€â¬ÎÔ¢º‹å›‡—Ù Å5 Õ²²YV*0P`Ü=“Õ¦U8.šaŠFÚº²!nö6DêkÒ9´!Bƒ ‘šz{Øf"8·aQ7VŸd£ƒb¦°AY€†s9(C3ÝlØUº(çåq^]©,ôBMäÙ.Ï ;™Dጸ}¤€UèùD¬ ìÜó,?µÝ»”R –ç‹ÑäÇÁoþÔªÊÉØÈæ‰kÄOkÀ·ªŠ>Òƒõµ%|-µ¼ß.5“-L,}ýÜöÏÏ´(áÙi‡`[!oò-É BOˆÔÓÛœ‘|ØÄq†Eƒ+h:OÝw¿v–•vÚé¨ÉÎÛ…ìêðË8\êV÷­=ær¯þlÊ…§;}%è3b±£E±ðZ›áløÒRކ2ŽYkfkù \é_ØJ, u×HÃÇ™Vǧâb?kHóeo6=q¢Øîãêk’,5¿út6Bšh‰w `ìíø[èÝè‘àøÓ%/ {:™ºó·n\ï¾]~q¸ÛƤ§Šyæù·gS6.`Ôƒês®:¬‰,cSàG\&nt¡¶p ImÕî=²ôý:Ž=? ¾äóµýlxá6ø]WÄ‹aGÄ^’p„B‚«F.Êøº6¥ññˆß´Ñd3ÿ$qn§ endstream endobj 1346 0 obj << /Length 2447 /Filter /FlateDecode >> stream xÚ­Z[wÛ8~ϯУ}NÍáU—·d;I§³Ig¶Ó99ª­Ä:«H®.M“_?IÉ’-Û±´O¢H  @Š:u>œýëîì—+%Ÿ®+œ»Ç£Äw]Ç 8q™s·tþšH¦3îù“_Ã24­÷ÙÓ:Š"ÎRÓqqóqú÷Ý‚(Oqý)Ø{vywöýŒA'uXÃÁ÷‰Ï¥³x:ûëoê,aìw‡øÎ³žùäHÄ$KœùÙç3zTj—Ú›âMgŒR:ùþú鋜¿“ä[¸˜r:ùßUвýrå)Ç#G¢ÎL0âqM£|YGËèa:sDœ–_©¢æ+Ÿ·¾R¾ªý•RÑC: ”¹õœŽ8 f† ²ø‘ÅË6ŒIâyGØHÂ…¬çD?Ë(OÃ䡽ÈÒ¢4Í*-âÇ4ZÚU˜÷1kJ—ŸÂ±Èïú8€òzø.¡ž"ý{3‡Ž s„¯% ã-BÒš‰»­I.Q~³˜Y§™”HG83ÆH \33‰Òw'(-,ªà kj³ŒŠò¥½™l3¸ß,£Ÿ¬ Š’'‘½üYÎ˰¬ ^=Yz-¯œqðGáÁS‚«›on¦ŠN2D!†už-0Œ¤æ}ÑòOÓ>‚M<¦°ÓZᣵ,¬çŸÃzðS“x]ê%¸˜Ü­â´ªtQ÷ËÉsœ$¦ÿ[dž(ÚÛ±ýúûkôÞç Kf*`-¹¡²Ö‹Âîö¢ð={0ÏäUZþë¿|I²pYLAJ2IŸN®Zbã§uÍêõi@*³¾§(µ›ØÈI±ÊªdiÚ¸|‚ HøG¼Œô¬ •úbF«BëZaj?D•&vø9.W¦Uj•Y‚e†áð+^aHWIT/B´lEˆÓuUÚÁQ„OeÍ© *§L7k¾h# ¬0Nû_jú-è»Q/¶»p5y -Ô–°y‘Z =#/®d1z—- 2Ù Ž7:gVçз¥s†ê˳êqe†àÐûùun°{3• «šâþnÊ€1³/RK£ˆJÓ³4»/в³>F”á`otÔ—u Ö?¹Ç]èþê7|{g@L»§#¢gÛjm­oÖ¥õ´ÇGPžÂô¸$xOK£CBqŒ3<מ/ N" 3.¼×ûÓ`GM`;3ÁáE˜š†v]x†¶¿*Êì)~EƒhOƾvÒ"Ó(³´ÍŒçU¼Xí! v¨Öu—µ€ú|¡-w×§ïï`løÐZ}„“h3¡ lh]Š·…m/xÖ<¾Äk3µ\Yh‰ZÐ@ÅtU}¿GyHâÇzBk¾PˆÄŠÓå½ íÙŠ¥”DjÀ^ÜÝ<¤b„AºÓQ'8‰]aQW-Ê Ì ÃOìš ¾rƒ¼ÐÒ ‡gôô-ZeÃlŒ™í·ZK›±Ìhuh:0K×ø ´zÓÌú{0 ‰zk `Á X°°xÕl®àœ7×ó»û›Ûë÷—óy_Ò(âJ6,éÙðíWôåííõmYx@|¿I´ˆ±Æ<²±`KmÐÓU›ÛK;¹ˆê€Šû|j3^A[²1…:éI@;2Il–xù³Ü”$[Ûnl,I±AÌŒÃ;›Ây'4pˆ&yàßZô«Pc ÒÌÎÕà‚Ž:À>íPЦõ;¸¤Åðº´ó7L1P€û‡EQ=é¦0ßý™¥–úyQâòA¯4¹;n:30ìM$š¨þß)¯ŽìþyžGaO­6ÿ´ûÆ9ìiQ¸œ‡†ïÖçXìQÂjøø…š×.ÔÐ?aBÔÙ dNan>u¶Ð뫱(¤;ŸP7þŸi`©É=˜pˆu¸""¡¡ «ÖŽçù‚î°d–Ô­-²[03$UØ@ŽmOaPÜJtyîì="xŠ(BÇY™Ï sý®ÿ)ê$¿ëx¦Dho‰:C©³*“®lš7n}:·Ñh^âtC«ÇKöçk‡¶¢®>@»Ð ‚þ(ø¢aáÏ$TÊîá¥0¡Ï<ŽàŸyÄcü øȲ×ÚL (èöC~×~Ì·¹šJ8®l˜Y•/,¦u¯lˆÏ÷£êdw!Ã÷ÆÁj +D‚¦/V­‚c°¢0 >³°z—Uå~h eÛ ­6c<®J¢t?¼rî‡W›ó§(},mÔµáaléÂm&¤œü‘-c¬Êšpk™bÜ« _λDÍÁB5g3)¤,Ñr/ZO_ñÒäÔ£Ð:ކE+ž_‹ço ‚Ât.4eÙ‡ÔS}³¦ÃØö´ÃvODiâ4ÜÔo …§Ë¹ __K0ÇѰàÂÃSH”' ’€Ïpy.<Ü7†Âl{Öf\BÙ0Öý k³î‹…Çv< &=T·%—Í•Ùss®Ö=¹f«\.öƒüd=íH0!Ç| réÏG7¦Ø1+FUoù@¶½ o3Þ8íGù0Þý(oóÞ­€6õÎöy¨>¬Éó,oʬ\N—z/Ï¢FbîtÝócÇž»cA¡(böÞ÷ÝÝ•û“¨˜0©¢ãg|_Ì)8Ä%}ƒ¶g£HŸâ¾$ÒÆÛ“D ¤YcÍ‘äõ¿wã„Qo(ßîñ"TH@§Ëws/¶9c4§^UYƒ¹¨xOñP%ÉË®ˆBz„q×@@‚ûãl<†„µ1òÔÑ4Hìµ° ö8P’Äu7¾šútrññÓ;áÝoå6ﮕ—±5¬9U­-ÜWW4Æ=Q®]»ÀS)6Ê´cHXÓ*È\Æ9¯EPáp—BAÎ7÷ ú éâöâùëaßoÝ6ûõæÊÈœ÷çQsøB™«¨$>dÞÛµ  tœyǰæ•LoOcŽ> stream xÚµ–ßo›0ÇßóWø¤ÅµyÛºµÕ*mJÞºjr‚“  à,Kÿú±!¤YR­OüºûÞù>çÃ-AwƒëhpuË<â‘ï»(š£€àÐ÷Q0r°OQ£G‹zöSt\æaºàW¿ý–ÇëTØC'­/ùl½™ä2É3e<¸‰Ï ¶ÑV3 qèxh¶<>÷{D°; Ѧ¶\!¹˜y*FŠ&ƒ‡1y¶Wì0u«.&ûàXö>¤º:щPY:¡ÅÓ*¯“ë«^ÝzÁžˆã`HaHCL<¦5¾ç™P®½b )#˜ÀÂjSSìâÐRBˆõðòMHsɯÓ|ú+Ò"C„*‚†.Å!3þr[ˆXÌí¡î¿ó$Ö.¡³çÂ솬!ñ“׬KU»\˜²ÿP+ë„aBýÆíXj¯•dèûØ¡ãBãÿɦ±¢—¤Ð]PäI&E©d®¯yÁŸ×¦MV&®û‰5ÓecQÍÀ™2+)ê>ª}¢¥8:©£Þ±<`Ôt´f4jmXyš&ÙÚZ\ŒIdëÕ+Ðcm1öôozmx–ÓI@½bNÖE‘C}`YRÄMÑj-S,PìP8 aRˆYmæˆJ¿Ø,…\¶DIVIžÍÚ6%Öº’úijÞNmG½Ývrú`—]ÛB˜Tò8™ñ´ãr6eJZÌQU°¦‹ñV²\Ïä¿7ê“sávÒ9ìÁ¦3"‡{Dm}WI(,°à‹ GˤjÜõW(Áº4Ⳇ=àÖOüĮ䯋l¹4_÷=$… ¶ç#¦}ÄcÛ…õ–|U½/챎q)òñ^jÿü×,‘ O“¾#XpMæ¢(«÷!¿k²¹ªx³“&vÞðèóÉ:;²ù\nx)>ç«þÆ™ŒlŸX@î$aöÆi}ME:{nw?‹·àJ@mÞ¾•2û ßÂTdõX^ Ýíß!MšI]õ‡};ßë˜zÐÌíAšrÉNq*Ú.ØKn*bÜ)DZ#c˜¸ô’cs õ±‡@UWŽ­ Þx û YWéNd¢Ü­½þ'm›£¬jä?Û…j> stream xÚµXMs£8½ûWpÄUkE_HpÛLâ¤fjóíÓf¦R &µ¼j7óë·…cƒgO!½n½'õk[ [×£/³ÑÙ•Ã-yB0köjIŒ\!,éQ$ˆ5›[Ï6Gd<¡Òµ/ýÜ×oi¼Z‡Y¥‰8¿ÿ:þ1ûfqÎ#€—K‰£FGÓÙèïAl‘:‚ë"—r+ˆGÏ?°5‡oß,Œ˜çZÿ”3c‹;ÆØÒz=Œð`Ö‚ ÜH1DØxB0Æöï§ÜÏ‹ìe¦R:»’Ž%‘'1Që±5a¹€Y.ÍßWá<|O,Ìòuäå>ôÖ ³“Çë‘õ\ΩÁŸÌ<èðüYkþÙ—]AV”IfCçcB±=û­4éY‰Q½¯a£Ž ©ë°Ô¢Z®Wÿ>³@ωVy-Üì-ÚPŽi’ûQbfÌký×áÒÏ£d¡ÿÊSó| »‰¥¯úYeoF“­%+|3l§uìi™Z2ÃŽ8î(Ì ¯C?îUØ9Aáü…7É )¼G` ±M~–GÛþâÒ9s. ©¹~ß(¤êìÒU¨sR7ÒŒ¤ã‰J;ŠpuÅ”v•pÓD--âpí7 lƒJ¦ô¤|‡$Ë ;OFó—èªl•ø÷QrÆ/Óác&EÜšX‡©úT¬VŠ2Ží¼â1c5d¾›{;ÍZj’å kò4ÿUˆe”åú-šqÑwŒi˜õ†×ªîH÷ç˜ÖS›‡”96ÒD ê(.ÔCÑ!·´¡ aj8µ¥â4iÜeLD°è³ J"‚×6ñÉÊR‹9 îöaÀlx¢t©Ö¹’  À¥¸”š‹»››»Û—›éM×) øŸpè§Ä&އÊm?_.ÓŽŒ¹èi2Q… Zi±ã¤tò£ž@.#ȯ+@ð~ˆa™OÂ02C"žÜ vØ^ª]‰@0.áÐ Íôý×ÛÛéå€ÌŸ»–¹¼-óÇ$>:·®<œ ¯bXâã1ö6‹ÔeÈÅ-àu'q±V%/¨L¨×;ø¡Þ¡`ƒY ÷qûÞÂ@å÷WVÄ›~ }0ÆŒ}0FwÚ‡š¡íC½µíC­)›6õ©‡)ó('Õ­B‰‘¬Šü,-rxèÕ_ ñÄÁÊ˶—¨þÏ7ßäüÓ̺x¼`ô·j³DåÞçóehz“ªGšŽÉÁ6Eåä#6EF‚õÖœ]¶ÿpŸ†¡ëQ÷Þóî)CŒï/_@“PI{¦3ýó¥¤}Gñb 8㟘0qJÚ‘uØî©ïV*eWŸGWàØíG–ò$ #%0ËÄ)„š~ƒ0‰¨$µ’ç—L{”<9n-d3pãr&ä‘it5?OÒñ$ £#ñLJw‚‰ØÏ(&¥©h¤fœáöîvÚ#ãg„­„l…MQñè,º„äò4Ǩª}Ëqfä˜ÿ[U-ˆ€Û"nZîG¦I»å5»~r]¦Êÿ}_¨öD9ö–ý€Y•[ endstream endobj 1303 0 obj << /Type /ObjStm /N 100 /First 953 /Length 2396 /Filter /FlateDecode >> stream xÚÍZ]oÝÆ}ׯàcû»;;3; n ´€û¡aüXºFS)•d ͯïêR•¬k_^‹AؾKr¸<;ßgבX›ÐDâÜDÍ>°&ñ|§4Íű1üÅ@šˆ|¤Íï $bœïáŸ(ù,¦àüi xš25 orÌMÂ5« &|K Èø”̯&|B î8$¿ý-5küã9ñî@0”#1—Ë¡q%ªÿÅ+ ¤ Ž#–†¢7Qhˆ`ÂBètJ•|¦øM<ßaŒ,C qšçRŒ²Ï $æ#,›rI>›e^qäç7¤Id®JЭ&h†ðTÓüu<µèr¤P‹‰°ø(óÅÌß–šñ #Å+±à«YLª®tårÅpžµAÎЊ¥†Íµó´‚EqñõG,” Ö_0s)>s‚ªƒkÞ?-šÇ(Cý98v¨=Ç Û ¦÷î)<¦~ ãÐIv3'(A²Í÷¨#Ÿ “‹e·-l*%Î_PŒÖM,vÍÂÔEJÁo™ï`D³^Ý/iÖ?Ö¤·ZRmÃá%Õâ(±45u$eŽø‚p“ɽ;Ag9;_Î2ςˬ6¬É&ó,¥±@>‹Zcf슑ÛWFîpjè:ÙY„j-Ù,…‡ì«†•oMI~K0PöŒ¤&pQSÿdHxtðOB,³ÜÆÐÙ³gg»7ÿù©6»o/..oÎv¯?ö7óõŸ?\üól÷ÝåÕX¯Þwx·ûãîO»çoã|q¶û¾7ÍÛÂmvÛiÅ=–s»‡ÔR‚ԷͳgÍîu³ûÃå›Ëf÷¢ùÝ¿»›_>ütnÿ8ïBÍ%0OÑj'±+ÜÑÉÆÞ¦P~ß|óÍþ<fTmÕ-€jAȵˆ‡ˆâ|uùñ§ósÀýpßwà S¶qè(=ü$Xèã }²AºÂv`áMmr7Ý+•·ðÌ/)õS°TS•Z,ÉÈtˆ~ÍSòÈT&+Ãv`÷`¡Í\îì_BË‘~[öϰ.mA^róC«“‚®ÒhèÙòPCo„T";„4³ ½ #uý¶æ'Äü^¥n}Ï«Ÿ×èSŒÿº!ä–Ð|ßìþö÷-­!ÿYˆmA¸øøãï>+œÃ,œsjêÂ*aÉÔRÝá——7óº^zºBåšßz‰Ä³í/hî–G¨s¸Zžyýð+L¹{uu9¼®Pf³{õâe³{S¾iÞ=´Ï«î}=Û=Ç—ëÅ͵—úy67ÃõåÇ«¡^ß–ÿùÞ_êø¡ûîòçf¶œ˜åÛ8¶V`”WÝ&ñ.&Îò÷tàýËjí>¾Ónô$µNX3rEX9³2„)m)ŒŠœåu<µThÝÔâ Žõˆ0z*älo\´Q>WMͤ-Ó1Hæ­7èO`—•ªF;ÚzkõeaV„1zJp{´ «¦&”©håôÉÞ Å°\y­ñiQDE|zTÄS¢"ž‡„a_¥¸Nz›:ú!áˆÂ’èˆ0SjÑ‚ lÕÄÄÈë\àóVÇÕLâcgùj‡Hé±C¤x’C$Â,?×Èk|¦?kf?û/ÙhyDË#º{¤Ë /ƒÛu¾Û¨ƒ@üаÖ+EDsÞCjѬ*ÌʵãaÐb:4?òj%MYÆ®æiî,fäH8‚=Këº:-h\ Säí“DÊqÊ”§iã_Þ-üCƒ¼„ø ;´è²Z›ç1Ú뛫ÃÍ_y~5(Ã;§ïÏÏ_o‡‰¢µ bÿÃT€Å)í0}ªÁªÓ¨‚_³ŽÒ›Å®Ð“Û=Z·!eX¼“Q~=ÛFßAZb6dɼ®mìÅÒ0åÂpF’: Ó4Œc2éu’qC´V梼 %´!æ“ÐZWû:Ænæ~¬c¦˜&8iu·×-zAÔ…‚âP¦Ì7fÀuÖ±‡ÑjÔ0µÄ ´±GE ®e¤nC¿E„gtGwh‘§2ÂSÐÆI‚ =£e ŽÌœrðçiÊÛë6jlÉwÔŠ¶ó Z‚u´É´FÅê@nj,wC—¹¦V™Â´!Öbmñ¢=VB‹};e5VäþZE”û\ªvƒM4êTÇÚ$d¶íDSÃ!©«”VU×M¬ ôÁÒa›w&(hî}»rÕÔ ×*zLhÇ[ßÁM…@IVj.)êÃPj?¾ñÛÆœ×MMf?jnTã–çýëǪþ\Ïø Kܤ/<@’>¹/ܳúyŸøWèçÐÑ´¾—¿dõœ`Ëu‚¥—2Z×KšºÂC©G£.¥,Öóö9ýë>§¯ÇÚYêêCUëS‰(:µïeâI)÷3Ï)ô,BÏ…6d\‡„ï•(¢…Ö÷Ê× ƒ©ëálrŸÊÁgƒŸo€ýý¿bõq¬1U¬Ý_(Ë V¿/|Ôê„¿zp‹è€pÏö#™ÓÕm~NÇk6ì¤ÜßQ|İïqê¯6¡æÇ&Tyrº”¸O—²ðiYH³,¤YÒ, i–…4ï•1ŸTmšmQ±³¦‘w¡(k·Çê> ¿µ3¥6ûÞŸú"ý⪠ò×±“iª6Jc˜r_„­JÉC5•L]§[ÖkaÏ*BÂ;+´:¥bc‡šÂ4Úˆ¿š ÊÐH¤Ûó|FSÃ~ö¹ïöuM8~‘ç¿®××./6åøKG¿à!×·øE<¼rœj(,}Ç£i–½±ô9Y”D¡òöÚó}pC®"b߉Ó¬BÖh‰£û×õ¶û$ЕºçíQ!K¢ÍÖ/¢úT‡½ŽZS¦‘J …"8½Ã;@ð¾™áyþ.öÆ-“­C›-HÎNÆùgBOµC¬K—6dœ$Ú&?¦Þ£M9·%ÊIhÇ~Õ&äLwÈÎBMÜ«Œ)£wí3?êüTOèî /=@rдR˜bÓ1a…ÄòtϞΘYü´¨Ä#¾×8«t¬š™ÝtL8í%Dk2ïÝWª%ºÕ£ŠFáCÚDºB1¥ ë¦¦äg´rLD0º"öºü‡O£>Ûˆ}u×”>ä§>hØ·=º´Oº´Oº´Oº´Oz¯5ú/¥fH endstream endobj 1382 0 obj << /Length 1928 /Filter /FlateDecode >> stream xÚ­Y_sÛ6 ÷§Ð£|7³¢HŠòÛÚåO»ÛnMã»íÚírŠE'ºÉ’'ÉËÒO? eÉ–8ö‹ ‘ ?‚x^à]>ÌFï®÷b2"æÍž HEžœ†$¢Þ,õ¾ù4ÿ5ûÙc‚NŒ3­¿–é:WãI(cÿ¢œ¯—ªh’&+ Í<ºœþQà <ÚÊŒc‡Ü›/Gßþ ¼ú~ö¦±÷d8—Œ®çȽÛÑÍ(xQψ’À)Ê %œ°ñ„Aàß|¿Hšäª¬–Isw©µzw%…'ÉTT‹¼ £$±f´*ÖK£;*]=Xí¿\¼o“hPb«à»+.;Ú胱V±Û¦RÉ2+p¹Þþ„DV¬Ö ’I‘"Q®›¶q1f_Vð!|˜Ó¸Á‰FÉ?¦ªž~¶2«?aÁÔŸ=f5RªÓÀïTú?iTŠíyV7He)x.û3BeÇ4 ‰ÌEj[ÓX¯W+ÝÆ¿•{?ÿé›1õß)4̾g+;f³ú–‚XêÀDóÄÚu¯ÜPJ¦"ÂE@ÓôÄOÀ&¤Ÿ*0‡±öÍÊh——sý÷÷Ð&£mæ 6=á«•1Òñ<#}ýÕ˜Ô£JRXf #t§nD{Ê:Dà›)¥±ïõz¢Ä—•讌°˜Ö³ÿר¢6ÐИrZö@××’ ´I(4ºõŸ¸ä[§$äà—ÅX% ØÖÝC ™²é¡@À✶àÌ2tÐ^K%âƒ2€¢Š V„‰C½NiH(ìóˆF„Q»7_ï..¯~±Ø¿¼ãvƒ" dz%¦’Põ•¸0h2a¦váÿ{ûE7tp8vLãSÖ<"ÅññçÆXXí˜ÉEHd¿ÁÌ]—ƒŸ›“d l¬vÀNôX°àý€íÍõ×OŸ÷ç,j8àtÕØœ-œôBÒHc\|MÄÙ‹™ã-Üñ·˜F$æ'Aæ$1ÀÀOÜãrJ$Ó¢$ éÀÜ]þ1;š3hâ@ÓSåÜ iO®Ôñ½FGÛ¼‹žyNaaÅD‚’‡ a„ñƒqN OHøßw¾¼×YÀïPtEˆºŠœïÈÚ†cUßu$H‡%¼ †ãeì-…p”tJ ¾)²JÍu]p°GT@}/@(ø§r¹ªTm}ZVÎ…ó^{­šFÝ*‡î/s8uePƒeÔ%¶ÌŽ­2Z°Ì¢¬ÌÀO–k§È¶6õú¦Sá0¹óD°ÐT3}ÉÔV1 çÞÎ æO†²v\°õ‡á…r x_6¯ÌÕ Bñ–\Å‚pØ7‡*a+‡ñ~´Ÿ&cÓÿBžtpM!ç‚s€IA¤œnbß§/w?ýöëç/—··1N9ÁùY SF$`º§Á­ÃfÙynk#ÛºVévŒƒ‡ˆÁ Î%‘Ó·,Ú®ïô¿8Ñÿ'ɰþ®‹eR|L«sÝ oK|]bdÈÌ0 )þ¥>úÿ…|Åv%ó¹9ú5ݔȵ.L-Œù3^¦Bgºa±.ÚT>³»”[“*}ÒS&•ÒÁp©s+µ¥Y7rªÙ‰²å*WKUL†®gí³À$Œä\æ> ¨¾am¡Xjs›Ï\aKæzÊEÓêlg ìIÌæ¢\¸-G¥þYCn—b3LT®«9ÎÝÊ~QZýL±ñïê‰$˼µ’´4 Ö¨úGÍ×ÚÌ7ÓílÑ-ã:µÎ®CvïýwB¹·¹íÝ×> stream xÚ½YISÛH¾ûWè”’«BO·ÔÚf.C€$¤!19d+JÈm¬Š,)–4~ý¼×‹,Ù25Üëë¯ß÷¶Ôº±¨õfôêrôÇk[!‰|ßµ.gV@IèûV9ÄgÖåÔúfsÂÆNÚÇq«ÖQ±(—¢ªÒ"W‡§ã—ï,Î]â.—[Y€££“ËѯƒAj±ö„0$¡Ã­d1úöƒZS˜{gQâF¡u+W.,î0ŽÂ2k2ú8¢]Ô<@í3B ì_÷§yZ§}QÔ1óì—ãסv5v©}{u'cèýlJXÄþ¹vMDÝ”u¹¡Ý/Êx9fÔŽUoŸÑÉà‰Ë¤+ºW™Èuw*ªÚÌ`[M¡6©uÀ‰QΘ{²/Ç Ðˆx9-PÊm¾®Þ꣬¨ÄÚ”†ïp Y2IDª;i{CßvðdzTùJã,½keX05kòÄô|;‰³LLzWD¢†VåE­†Ó þgìxvñ›bªV\cç®#s9ö¨M€ß·/çi¥¦ªMÄI¬] 5ÐTFh]¨™ªI:»b°ž MϺ ªáxyÓ,D^«ž(5Œš!=>dãül³qÏgتÜÙZöÀrÆÌ6ƃ#ÚxääÊ\¡Ï[õ|GªÔÈý`À§VG(éüóÙÙÿo°×U?:ÆÁÒüFS–Yš»DÓE™Ý©ö¦™Uš@CwœÔMœµµöUߨ®TÈ0ÉÛèâÌïÐ…½Ž£cWsÅ׸Â)ª•Æ97\¹aر¨µsX»Þí¯ßέܷbs€êíW{T Ó}¶•ôó¢ÕŸ€Üõ ÚtXSDûtí>jì6­çª…—Q­úW±TUFP}ˆLº%~c31(v*¤¸¸ÉÐóÁC{ëâºÖv*ÃVS«è»°¯ŽÓLÆXføPÈéÄH¥¾DK-W£×"S.6öé -žÎð,nË(ˆ¿=¿Hµ@xö"ÍãZú¬Â›M­:é€Þ9ì‹—ªeœÜ4U‚tk5Öó©ŠÀ.—E¢\J ë€ÐÐE–)Y›«V,Ä)u17tUé«Ë+, ¦9„¢[<<^ ª:ÎÝK2 b’~×ÛªH—{h.x`=_Šxª†6Tˆƒ­ qõ¦ Õ>T!¶V*ÄÕ6kbs]….]÷ö ›ÚÈ×î+§LCæZ%î, WèÃàêÖØäuš­ÇõØ*Ð~§õ@DÔ~|8¦ >¸²³rFì|<”éâRõB±áêËÀ$n™üáOaÆÊ,®W ª×‚Qç7sÕ>ù]‹|ª´ÇÜëq1æà£&¼¹{¥ÖK³ëæ×]éq­— h¨5²ÏU›}úA ÷ö S ɦ\#µÖÌsç¡5& "]L®-ùvày>(LW\3õ{ö•k¶ >©ú"ð&‰í.Î~'”E¥ëíËíõWƪº­*qwSoÝK+Ø„…y€õ5™4DéfB­Q³ÑÕˆæ?„Õ™hG1ÅG²þp‹³›Bçz¾ ¥µxôHÄuµÔ¬`}©·Íl¶ˆµœ·òxµ]5¢67í²g]l£×«ˆ¹Ê•Úc²ÔØE:…Ò8ýN©³Q`õ°tUQß•fq5p‡ö!m8P¥&j(Š€üyÏΠûXƨäjH<ÉǼ@\Ã9]>‡ÀNÄ 5?ðv`" Úð3ËÀDzg9AD>$VsÂ<¦E ¼¿A„ ¢BNà½.•ññëÕñ8¢ö—óÃ÷§GWo?m~ `~HœÈ},€³ƒ„×M¦Íþø.i2`+*T/…¨6á4Â|þx›D>‘ì'ÉÐdûàÓÁŽ›¸Äå[õQ⹊H¶TO”µíäûÉ( Û“JˆGS¼'¢Mr@@<ß½Elý|çЀxAØ~¿#œøz)¥PŽÈ‚¥Û÷ÅT\ Z ²yV: LG6—‘Ð%"o: !àåFþI¦*_‰]ÙF¿5îú…ðPf)‹ÎÓ{‡jÀ- e‚__º9âv. M,×F¿`_ÈÔcò̵è$‡¦ºëÒoL“€ÍÚR˜o S¨e³Þ–ÿœI˜ë>&“Dè ~Iu('.s·ÛÞ“D¨ÐRB™¿3H:®v¤á!÷ÛØrqòéôÃñéÑáÙÕŇ³³Óó7~LñÝ3€@ßñ£ˆóâƒÁ NÜËæ7rˆn,x±O¡ˆ…°ä>\cìÔ)£À, ëdWèvŸ'_vóú 4¯]ûñ¹7† 2@ÛQ­íâs&rlˆò> stream xÚÅY[s›8~÷¯àÑÌÔª.HÀ[Òm“én›¦÷a{±å˜)‡K³É¯ß£ lìÄvgöÁcâ;Gç|:ú$°sç`çrðf®ääròõ…Ï…>& ;#FPV4˜L«¥ŠC~góårà|‰ðÆõמßò¬PÂ`]Ö.áC@1±l°Ìm ˆ:üõ‹æ½³™,¦9Œ”㕎ºî=^Ä…¹’©Kð²’«ÿ¨”3ӞąE.VrǘJûJ¹-›ú*›Û¾[n–‹ÈâÔoeœÞ™Ë–s·r†L°!°#Ÿ‡ÂÆÁ£×ÑV©ã6qU:]i‹[DØH›BÄBÝ?'I6…á”e4‹Êè;æ~dGjwp‚ðÏçã¯ï¯'ç×ï;)¶|ˆUÎD¯UÓ®lï¢ðØÓ#BPؘ{ªß“d·“ñ¯€ kO‚hÈëÉ ie&V¡×ê"LüºÏÒb¿ê™ £æ%¡]wŠøINÊXÆ´ïWaNTß^`Û·\Aäí…öÂ,¬¡“Ûj>ŸO=Ð*¦ë˜oL?à¤ÝYX§Ë0n)—°—A©0 s®U“yj†^6+™`-xu×gÂ[Û§5¼¦Ìxaßš7“BÝ•ÑO—⡚¹ú¶îaW³T`5{U+Ìž8·=âtU•æòVA@8•y™›W"(Ù¹nP ƒ;øvìí,ªzÀ1|XÄÓ…º„ ¤³øW<«¢Ä<Ò!êï§íƒÁ¤~.Íÿj`.‹BÕŽ‘¾ C! æ*2 %ó¢1¼A¨ UðÔU™™'Ó(™V‰É4G©}­“½ry_A¬f}<†–`gÓ,Ðý_U59©+5ǭ̪öb©±¨ifûªA©B¢ë8´Å©i‹ÒúÂa¨W­JÛmâÈžEEQ-55 óÞ¬5¦÷YÏä;K‡i¹ý¼“½Q_„šà—x†žêî,—@A“¶z]»Êì³r‘Ëhv»¯ë‚‡(W5Oýé½Qý)C„1ãÀµKù!‡K œšÙ§JX(TË}ª„yP\ÙZ•üf ¥`¸ÃµÐ„û0 7C¡Ç-„EPCˆÕ‹jÀ¥€$H’WYUnk2B9¢‚m¶]T ¬‘TéŽáz>ô˜(-x¬éN='ºæ]Ó×.Ð5Ó3ŠK¶lÝW²g¾vô§po›!öC<Ï­“0,·„~n( 8yŽ[>ˆ6Öpk¯Ž4ÙË«¶ÑZ^4ëÐrg¿Ÿ\mû7ÍÛÈPÛ5ËÊáîê ŒÜÍ´ƒ}Ýf‰P²æ4¢ayÌç¿…g Ó¼à%<;Òd/ÏÚF•Ö´)´zsÑŽs ŸhmÞjÕ¥w_ÊÕû.«³ô¬¥³î­u–î­%’Ù§™ÿ¶ÈÚẼǶÍ*€àâ4b Ñ• &á=‡ ª7 M´¿È²Ê•–¢Áð—Þé&•|zÀ òߦ¢À{Æw†™y6lžðN›°|…è@Ø=è×ɧ¿zØÏ|$€ÃGÚí²6yê\¨c·{`T¬Q¦Us–QTÓ)x^%Éã¶‹œaÄ ;ÂÅ­ )*NËòi6˾@>ÏJæíL2Ä8€*OŒ[çøÂ ððüý‡=™>Êv¢ÛÆ»‰žÅ6·fóS'ÙlÈvä÷PǶSœú§¥÷$ ›^:CÏ2•BIÞ•_ßGÔ£%PïÕù½v ¬ç_Î?ÞìIñqön-ßMŽÛ¬£:|ðPÍã¨î¡âÕß>¼²RËŠù®ìôÆ/ïz§v£°ó\ï‘å ¹|£Î ¬^žÃÆØÜvåÚCσƒºÍ-;žÆÏÃ1êuï…«)¥ ^j•| ‘Ê@•4°þcqJá]gD„={˜ O:¯î;Y…ÜoNfEù¿yÂj-w••òHãŸÒÄ7Õjð1.ò,Í*Kå_.zçESDëMIÙ| ˜wŠlݺÊ353@9Öð°®…ûvW$¥ÑNQRd¿+Ì}‚‹s½;àRýíH ¨Ñž®;ÜCZ<Ž„°ËÐ¥Le¾þL¢çöcýB«Ç;õQA}XÙðñ?— a` endstream endobj 1414 0 obj << /Length 1414 /Filter /FlateDecode >> stream xÚ½XKsÛ6¾ëWðHÎT0žq³›Ä™¤©ã‡z¨Œ‡¡`‹S‰TH*iüë» @‰°±¤N6EØýö½X<8x;ø}489ã` ßÞ1•ßÛ³€ Æ ±ip3¸àŸ¢Ž Â=ØH  Æ8üúôjZÖúþH Ëâ©°ë·@VŠ@"%11dq0d%Àª¥xu6º}wyïd] î†1pÈ‹&j8VöÅ0ÜÂ,´ø AJÄŽÇÓÕëýÈcrržÐ2!KD§æO3³ûä\ñÞ&…0‰»=5µ{<)CŠ!«š“s.{êALd0¤Œf÷Ž"Bq¨+pÎò"mtmÁ9ÉÕY»cô”ÏíBí<Æ8 v´œ±NǺ΀a>o–n5šäŽæÃ¢ÈVë™Q°ûÒL´[,‹B÷6}Ï›‰¤ý<þŽ=œmtÄpøocä!gûœa½ž¤Ó©ýP”nïm2ø¤Çv-/ìZZtﮬ€‹yãö¯˜¢hȘOÓº^ÌZÔöÜEY8ê§u>ÖoÌsýû—¤›–™yü3ì¤lKX1óâÑ*äïˆp â4xZi]4UD ÜÆ®]”î[3©t:¾I-ßgÇ[ET'56‚úiÔÌa̸Œ(Ó*iÐFD@ž“oÊB)D©Ü•'QH°x™'þg&§ˆ@$à.2ÞEvCÒÄ‘hÓ›mÐØh#a(+8æL²ž! &ˆ z0Ë~è,‘ ÊgÚå‚glE„ÊÕK„%ˆés½éŒIZŒ§ÎLŽœ—m„¸vÎWÎÓ¯ ·)/ê&-2÷§ýœÒ¾Œ¡@-³»'SàŸ˜ ܺ3‰XéûÓðÃÌzC \ Ž¥Õøµn•Ñ MÂo¤žtºÐ/9#Åè.tjW¬Ø ¢áBŽR$r¤ÿ-ihAÅÄ. ]ÝÞücSHƒÈ×h„L{ãñ=÷Š˜Mý6/Ý9ô"ËÀ§Óé ~ 1 N±?Âu –iä£h8#cè¡ÉÛ- CŒoµ±(FŠä²W»½?ž½û°ÃÐñÞlç>sßÎãÜ™Ö6 Áà[Í»/®uË…˜óã¬{ k]®8¢ŠÂR"Ê)2ý¬Xš÷²íæÎ®Ïþ¼Ùnáù3ܫډ=«–ÛsŽTB¼–Û/÷¼øëÃWÚ\©›éÙ—®ì•ö9Om/6{vzø[DM"Ï·»ÏþB¯ÙÞÀê8ÿ9€FW•^Xì8;¡\±»¬44Ôã¼qWŒ±åÊ3ä.±!IæÎ¨m3íÝÕÛŽáAº—Ѱ¬›ƒ‘ð#‘P–t} >Pzú7¹úG‘Mª²(Î[ÔÕªóê\·ÙraëVçUiúop•£¤ˆvx£µílÒi]iðgㄎÀSÖ'°Õ8Á@›(ˆ}' ŽÛžCñ † ¿m˜* ãºP⣀˜¨@‹¢Î Óò˜·l ¯%âÁ²sò8r §Ê6¢!Úm‘øp| F×ëb¸År/TÙýTa@M$ óç=/ÒhSqµŒ±®›Íx¹øš0^¦ŠÝ0<>ŒiZ7ÛfZ?iq¸Ã%»?ZEY/ùµc•…›»T?¿< „Ùg¬Ù3cDeÌûå  v~òVºJ—·„”KÒ¯Ëö"ñãÑä¦PÏ!þy w endstream endobj 1422 0 obj << /Length 2316 /Filter /FlateDecode >> stream xÚÅZ[“œ¶~ß_Á#S•!’¸¼ížÄëÚ;q¼›‡œ$å ݡc.vÖ¿>­#ff\•'@—îV÷§îV ä<9Èy}õŸ‡«ïou"/â<<:!ò¢ pÂØ÷ìÈ‹DJ vzÞjM(rï¤Ì¡[Vâز„ u£Z?r®›xÓj*y³QrîZõ©Ñ¡›—Yž&­é•ßU(F5¦UÙ&ôŒêQÈþý-AN FôaD‚B/øiHý‰Q£¦¦^ùfL£Í*‘Á¯4œs½ÛΡ±3´'mË·»VjqM0@œCe¶•BtÃ[õÒíÔ31íFy¢¯ÉË'õúéë]™ë)I™™Æ{Þv»{5Ç3Æó)l Ù‡ÞB¿®h{z‘\“R©Rñø¿jªÕ3KZ-œ^¨Î÷dªžˆ™Q•º["žÛªÖ-O_óÝÇFàé;½¼F=w\Ï~ûƒzÁ1ó‡«4‹ÌõË0ywE’Z"¼52Eô“ä’m¹îk6«®Ýu­5a¿r[‚øØM“¢KïÛ†¹M«{6Ü@|¶fF·ËÔ^M~(8X{MC¢—.ÚÕ-:=G­]¼}ääJÉtûÑ!Ì&ÙWenVóQ{®åš¼Pxr±Ì¿ó¶ço­J kÂܼ»Ó0HÄägõ±Ùû­T³7vu•ª]h«|/À7i‡†²ý§½5„8ºé)ÉËiÔÑ)swI-4’lµjÌ„–Õ—Ö% ”.¡En_ñ"d–OCl \ø–ʥƅµ+Ð`£Z`™Y—Juø¼< 4X¯h˜ÂÙš!bc>{}Ëé|Ê6_ÅÆãue…)WßzëC‹ :Ìí%—]›<Ý¨Ž½á£JÓ®VCÝX“EÔ†lL ­y V3ò²UÒ-Á¬Ï a¹vB"÷F'Ôä&4i IcâšTY¥e‘^ÜÖD 41§ñoÍv£mÕ©h3éG.öéËüƒÎ-d8“›Kø†û´Ù^ Ú›’ :ÊJ•òBƒô-™j“A[RšoТÊ^º]«Çï™J…2÷:iÀ22»iÔ¼Ÿ•;‡Ñ×MžñWz%i;îøÎõÞúôû CîÀµ>¯kHZµ KíWÖîàºÝ€1³ûDñ=˜.’AäùL$râñ¹ÐN8…š‰‡ Q¼[ù2!½Ù1¨S‘ЉàT^Éñÿ’´òÛ’(sŽ=?ˆOÑ€ÑÔà k2© ™•EÄó}‡>⃌óiì3`åÏfi'W˜`’xÈT&Yc¶°R†¢¹l9!ó‹Øí½ç7+ÌùâOÄЮ2nÆ EÕ.ùÔq³Ã!q-MÑGšAÆ&üÃãÅ1Øë \¾¶1–€ —Áq Gļvõé…áàQìQú8Îd9 G›©pÕÇÑ8ë4m®ïD( B®©ºÚ€ì tÕÅ"Ž$…‹Pµˆ†‚±‡ãðìþ€°~V4<ä‡VßAÊ~ZsÙNAkÀXgëÇá5“ó$¼œßðò©Ý Ó•ØRé$¡T^r8)ûæ„d€ig¶6Që  T:µ;†ÖËWüòß Ÿüð 3ù} „GñÀ€ïíà^Pá]U±»þ&°éRqíô؉+†‘ˆ„ø fH86`l¡‘ÑÐF†‰p|ö´©Æ1ÇÌ‹0èÆ‡t›ô¾]EȽ¹{sÂγXO›Ùâ=´r–gQBZxª2aŒ{©Xc»øBªe¦]BB[V”Öí!2ûÔwˆfêç`Ûw+ ¥›÷7oïO˜wÿÁ¯½}mNüÀ~àõe¢Žÿ#ðq«¿>˜ §‰þÿ—"?ž‹=6=ðÃe蹘„‰G/ s~ ì¡Ë75O«2Ëû¿²zZúy`'<2Ô¢<Õ©‡¼<L=u—·ÖH~DZ"¾[5í¿&‰¬¢Ðò™Ì îà? ç2ÝÔUYu†êG‰zÕdpÛùùÅ´ŽÓ³Ë™9¢æþŒ«”&)šê[©yòÆ•yˆàK’4ó£aè¨t ŒBˆ¤ðô‚@[è5/y´ƒŸžžÍ/†2)x~Z­Á ðòPÆÕ2ˆ= endstream endobj 1428 0 obj << /Length 2638 /Filter /FlateDecode >> stream xÚ½ZÝ“›8Ÿ¿‚G»*VúÞ2—ͤf/ÙËfæn³[S3cêlp $›üõ×RK Æc;u.ƒ>º[Ý¿þ„ï=y¾÷öê÷W/o÷"KɼûG/ôI$¥Æ‘Ô»_zŸfœÐù"£Ù/IàÓër³ÝeU•—6\¸ÿuÿ«Ç9#"d@\O ¨j½zsõåŠB£ïÑ–C‘(à^º¹úô—ï-¡ïWÏ',޼ozäÆãˆqElíÝ]ý~å•ZRâ;bAø|A}ߟ}ùae~½›þ,ýÓ>üP@”l÷dDüø„ IúT1ð½£$¦šöï×÷Ü~x0«nó>-$ðÊ‹z®\¦)6)¶Xz =® JI,¤áôãõüpßcõò& ùDHX$¬Úÿô}¦F¿¼‰¹3(&>•vLd_à ÞJR(…ÀÁiYTfMMQåOE¶Ä·t•ìHOœXÉé3Ä [qvé¨4ÔçDЍ/N_¥î¡2 T†'id—>¬³bTŒ±))h´óø1–YUË ïâÿ¡ %ÂóT!'Åèq英N¬Ò ›Xåº,ž~ЦSpÊ¡4&4pè`ˆxyÃC'à,¨DÈØ[ÂŽµÎŽ!Ñ„ÊÏ*Ú4sæÏ²é*–ø°ËêFµ‰™‰£õ*3öãk|HWYªHü·j6:Äú†§ s¯ÀX)Рb–ok Èҟݯr%‡ˆgM‘víßòõÛÓNZhOðo - ̱/ËAº]7ºóËos`ì2C ©”TgÕ&h/û«ò±ŸÝD޲«v‘(9¿ÎAqI¾N´ÔëLÑ#óãþìVËΊRýKW–¤®°õs–™&¼¡’W+”CÎ؇£C€õ2O“Úöêáß± Í(묨͌ò¡Ã|^,© Ãü"µ0Nb€•«‘âÙ¿ÂrÎÍb\;‡ÖÎОÔu¶ÙjTI ò:“}eÖ%B­Êj|h¶=Wn¦oªÜO?~ùq[äõ¤¿@ª›­ÉZ¤Ydwo1èkÖuKÎ2[:ž³.ýØT>âÿ²­DÌ:Õð¬#S¶D쌲0Ý¥ñÁM¹3-O?òíÇJÁé…Yñé­õà7Æ=i,2æ—Æ#ß5LÔ:`DgÛu’fبd^g-óÚ•W‘¿/˜nËMbè•M½mjg‚ëÇІ&‚‡v˜É»¶Ir#…yp%Š\¹sÈ}ãåré+ßrMeºÝ•Jß_óeÏü݆ŽDã˜R<ѨñÑX‹êŠ€Ë!0Y@gi²^+ÁÔófNA Uýè«|­íŒf»ÄÈ ^L!¡ˆ‡ÌAµc¼Z7f"A=}ÎöÈšéæ³B¡X³‡:¬ÙX>êÌW`Qÿ™ÒØßyÝòwV•cêl­gò·*dÑ+5ù;¾¬º(kìe#X+m]kMU6äER·±b2÷)qLÓS’ŽŒ‹Ùj+ÐH²Ùa“­QðÍè’KÔ%´è`¦”Ìúßë)ÞµráßU'‚5.›Të:óbJo±íôn±ÂW¹H!â^[eëéÙ˜[ýPN‘íJ'‹³¼Ï‚Ì¥&ãw’ë®Už®°£³.¼”iеGdèÆÆ’"rpÖgck ¨[Àd–Ô{™©bÀ¦ßA½zíŒÁ¾G@@®r›¥ …¤²)Þ†=T'´Môic}µé@´)L¼£ybz*µ#©¶ÛX¥S»v-×mK¬^„‡öj…BAGQš±Z`hБe‰mZ$¡â²}5b%×lk3¾cª5*f¯’ L£+½ çý†¹ F¿ª |¾1KIëa/,ÆÔÜfãÿÌ)ÔQ™Qè«”J5:aaâúo&¼ªW`Íå]‚|÷¦ëM+ „Ú·ª?½µv÷îJÏŒPÆP€ó€CUh\‚:{ûÞ±£µ8‡-É G ?™†:vã°waÁ Í ÔÐ'°ûè’ZÄH%Ù6N‡(4û‚³Yº’2J8‹ûLuÉ9d +~t.Û^b¦!ÔÁ‘è³½sKÍ䊵Á“:7Ù–6Ò8©¨Ü&_šÌ:9”ñEšíeš^ýªBB{îÓ[œwo?}mC0qð(v! /¢aD$¤Ñ‘¥0½'>Hæ‹gòL–£€t™V¸Y?€Çó¸ŽãÑåúAåƒ2·!¯Ý)•ÍÎÂlX§ŽÃêd‡‚Æ—Áê"V€~uÌzÌC ·ƒH[T½€Ì²Îä:Š,‡¯©Ö'Àuãqp9ŒßeÅS½ê,À‚’q>{_.sØív§dQé¶.Q§°Å ²)îBõäaHަI‡êE4 T}ŸHØæý„¨6Œ¶H™Œ€g²Å©ËTí8&PzÛq”ºl„Àc›½ƒà:YÎ!0€Á/×E4\:‘Ž,VÍ>Óà b ’óá¹lÇÖcÜn©‚ìLÖ£ 뱋…Çv< ®G¨îT9G‰x¨ Oí~ndƒäÙWA~ºžU$ÂiGA~ rI åOØÔR?ŽŽGÐsYŽÜeª.&À}Ûqp»lÍõywÌ¡÷3,´èî(º£…°{ª°U3±Í?@÷ýéôùd A$@-—ù"ÈLC㉇«xáÏ Öçq…²Ë7ÚÇtÈ.Ó¶Øß„Û‹ç~Å^$ì_ažR+œ¼Ž!p€ŸÞußE4 øü|äÈJXc– ,$á3·LçrEŸÃלH>Lbð<Þã tx÷¾©yówÝG]¯Wò®¿pÎ¥¡b¸5ÕЪÃÌ¿{g.ûœÕáeǰøMÆ.QÖeê+PMØ(lfE{·5¸÷O˥ݞt;²¥YÃ]vý±j¦ÊÒNä^"Yª#þuÕÞ©s¼%諪(IΩ>¬ÉQÌàÆÖ½û#‡ƒÁÉ€z²ØFƒÓiô¿ÑÅF¾^£2´›PûQYPi,ˆf_õåκɎ…SH”<5T¹TÆ+¼ŒÆ;ªuå…çÒ>ЂHU Šì—w<üëŸ#Q"„„Øq&ß~ÔáL™Øã{Ó]ñ´xÇk–¦¶˜¯šTÝŠ>6êl ¢>W”gH84P²^dä‹h#3Fèô'œ˜žùAÇö€h>Ÿ‰ÖÄ7óÈŸ]ß¾›0ôY¼Çíì2ïÛy™/÷ò„¶ñØÙ™5ï©r -„bˆY÷"ƺ4""ä¹0äï€P@éËÖ¼æê¿ë×ïï&,|ÿþ'"ÖÄ®ÏùP¤j¿nÈ«.ëí}A” ZÛöfÃv·ý`mOÀçäEm$Xx!~N§a³Ò€–à]'âÚï»% BÉ ÉÄ,cÅ·Y‘í’º÷µ)š~)uxþþ¤¾ýž™ó,'kþ¿PÞ endstream endobj 1377 0 obj << /Type /ObjStm /N 100 /First 976 /Length 1982 /Filter /FlateDecode >> stream xÚíZ]o\·}ß_ÁÇö…Ë!g†$`Hb8-Ðnä‡$†!ÜO×H*¹Ò Hóë{†»r$k¥½²Vh XÐÜ{‡äð çÌ eJ\p””q2!ºDÙ„äXÛ'všØ„êJ™]ÍЉbtD‚§ ö ?DiE‰v¯)U¼ÐJÙæÎ&U¼Šjk&¨¶D±ÉL…m"ÉÙFfu$Ôæ‡šh\AÂ$Ú;|UiC1Ö¶ÖÏlc ¤’нÃvjióIlÅ\]L±­\äª ‡(LØCaHEÍ: PÛS QÛî1]̶ýˆÅ`„m–!Jf7±U‹¸XC²¡&q1I!UÀ„©\ fL#°Q¸ ¶¡Áœa•â’- I]JÕÜPñU´I¡dΨI¥½KØEeHl[Ä0lÝüÏbÃlÆ ÛñµbB[ pp Sƒ8ˆ …=L¡•!qYv·KÇf-¤êX ÁÁbæ+ÕvËøZÍ]b‚ ÀQÒödH0ˆŽPŒ¶@ds¨N"êX^¢´wš‚a@/,†?Eƒ¹gO²¡³T¶wDN©ù‰Äi,º"8QSj“(¤ÜÔ²SŽæv¸BÙÀƱS1¬FjÛ44‡vl“ÓbÖHÍ:ì\k°#‹£¨u{¼1]­´=è‘bó”ÚÌÕe[_! MðPV‹ NR15›·¸F…”ÃêÅ‹ÕúÍ>NnýõÙÙùfµ>¹ê7íùoÎ~^­¿9¿§‹·óáÝú/ë¿®¿}Kíaµþ~6î-÷ ìrÌž@TÉÃÉ.'ö•+ô¾v/^¸õ‰[wþæÜ­_º?]n.®†Í?~;Ùt›«ËÓÓ“?»¯¾ZáßÌ©ì#N×µ98d>™‡Ìyq~õñôôßÝæ§OßwC¦)Œ™Ò8KiÒ©Hœ†´‹³è­Ý§A|;{;ð”’G@ïbêþõ,à]›s ÞCæ|Ö’T5§i+ˆ£ :'‘¾pMc>žµ5yÐ2K€ÍÆ.°5…Ÿx‘©ÊSÇàµè”…Ø5ÍYÆnÊóplS‘-|ŽF0t.òZã"[c/% s® Ó¢L£pœ‡qD¶èu–ñ¦­/áÉþ î{·þáÇŸÀ¾ ƒ”@¾‚ή~ùåݽÊ94åœ xòeŽÕøŠ¢„H9yN‡l.Òb-á¼Ö²¹~/µ9¯q¡2åâ#²÷Á ¶Â¬KÑ@æö1š¹ÂÖV¹‰g$÷e6ã<+}¶ÁWçg›M¯P®$Ë6ꕉh÷„”š»OV†PhO˜dýúâ|8™µnýúå+·~3ýºqïnÁëîý´Z‹µ¦³Íå¶Åx‹÷Ëó«‹aºÜVcíÝß§ñC÷Íù¯®Q„T8Ñ_ÀýÅÒëî“XY+[ýÆ2—X¿U fV+@wBm»cÓ§Ü ¿Zú˜d9–‰†•Ó8L•æAû~ŽBÏ<Õ1vGçû¬Þ*2p'êTd/5/£û SQ“3Ф) %wC—¹æ@eJa~ºW+Aw¨Ý—°,5 µ—:–®—4w•‡ŽbÊ£›zôB¥ç;t_ètSù ÝïQVN†úe Ø?Úüxk`Ö®[°¬ÔÈtHyG-‚Atpf Á£t‚³¢‡§Þe”VV/SkÑR¤Ñ|øpÐè8ªå0nâepXÞ¡rH™¨åëÙlyGãBè,ïX×ù‡ åº‡–óãh¹æ;´ŒÝ„Ñ·{»¡È^PP¤‹Èbž§2Ô˜Æ0ç¾ — Á9LcŽ]§wÉ¢<†,ÊÝ#Œ6-TŽ3—…Ê8;ûC´ì­É§…ÊD÷ñJ¹H(„¼]Ã<¬ŒåC»µ§’,3#2Jþ´Œ˜P'×…ÊDÑÓÞ¢sϱ?8ü€.(£~,˜øs˜ï ç{øv¤i8s;álw9O çz]\ÕmqÕn ž¡ÊRTúÉ.}®YcYOÝç$çNç‚v7æ‘Ç!ôqêðÒ¥#V.ÆÙ Šlww„,‹%Wæx¯­0ò7YþyÚ¡…®yF9Õ ¡lÁä±/aHs¨G¼¨H„Ðdéj%•‹(5¯¢VÒ²†zJ“Lð‡ŒÜIÇ)ižûlcK>'M»²\Lš·”UXOV¾¯ŸÞ«›ãgPfTnª´L9Åè9/´y÷ë‰õD»Ççë'ôX+ï§*û{@¼ž$ãÖú4â"¾K\ŸJ\vg½ã«¸v›hÖGd°-/|êw¼ðPŸø?å…Lv¹7±.1£|Å9^Æ ã<…ÊÒw<Í2f!é3 ]I1L|l®Eÿ‚®äwL)³%ý?¦$hŸä¦­«­ÇÇ´‘¥GpíMåƒô¹G=¡/ûª½}Ê"vá°L72zH- •#Žl,_ÀrÛCÙñY.Þ½³?\} ËÝD+>ânã–ò'Ÿ+Ë”VÈûÚó}ÊÈL·> stream xÚÕXK“Û¸¾Ï¯àQª²hð>nãì®·¼UÙØ;º$Þ­)X‘H™íÌüúô ¡¡;9¤rPhÝÆ×_RÁc ‚Ÿoþ´½yýV§A–Y–Û}«°È² /ã0‹‚í.ø¸ŠãõÛ_‚D§a%°Ž¤îvãѬ7q^¬~ìêñdZ[Ù¦kqòÍOÛ›O7ÌUA4é,аˆÓ >Ý|üC;û%PaRÁšy R„:EÇàîæÃ?§oklâG¼Ï—¼ÏÀÕ"aGß÷¦îÚ]3ùv­ôõÛ4Ÿéˆã<ØDE¨RÍ*~íZã/õü¸rb#’4dâÄ:‰WÝ`ÿGž@àuâ4XóÿK{|â¯ø3<µõ¡ïÚnXðyë•éÜ º=í¡‘)û±­í4î¤ç¾[Gzõ¹Ù™]øýLáÜewAƒÇ¡û/£|•“5¥’i…:ÔëM¤”Z}zþ¡;{3 w¶7Õéw¥ü"ñ“¡”¬øv£ƒ<,s¡~'…q$;ùðfû·wïïß¼çm#ø¸ÉÀTÓÚ55®m²-ÅjEa †7Q–Zúáù4À¹Üo=k¯ßñÌE‡I¡ü®TÂq*ÓÙ$À}”¹9¨}õmûßdY˜B“Ó“c´­ãЕJ¾Ë/ÛŸ^ñ¤+'"`¾Òwbl‡æ±5»õú—Ú³8Œ²Ü©?Vƒ]Ð'a]Üdd\r¥y¨u xt<×1§Ë®²’‚$Ò gOÙÙî¸Ñ;öÐÔ+™UL½ŽÕêïÃx"RWž‘ÛjX™Øœ9I“\­¶”¼IVÎ’å_šã‘[õäöØ;œßÈLç¶Ðq¿_' ¨BæíyÌ4ö@2hWü9Týî rCÕžüP x¤—1ËN”É¡ÛÛi¡ìu~¦NMÍÔ@‡ö ß ý$B«šcE^C½}áz£U²z‡>«·Ý‚’C%ZŒ‘¬hi†ƒ³¼[2»êPWÖÒô'nC`¸%ÄB­•@°„ D¼Ë,ÎAI‘f/ÓÁÃY–C³4õ\{­kAH0€PÑ¢°°xqœa"Î&0jÖšÓÙ²ØvüŒƳÌrr<šö‘‡?=¿kYB°ÆÆ'à*;ž…°à8Ò"û£'À„­ ©Zy.é9vQzX‹$œ† R\°÷ Ó|&W±;Œ{t\7™%í:¤ŸLÏ}*†ðåcµfàî†?•twÕÙ\&sûðå^²g­ö÷Ã3‹qhâð÷kØ&ìÌW§˜sn§ëûU}˜¼ÿʾ£WÈ›ö<ÚkÚï n΄bìN;€6Ñ"W|矱­Vá!ñ¡fèì0-úîÌ(Q2 Ò±cnC‘&‡qÈ‘ÑMœn.jºI‰[ÅŸUô,8u½,x|nÎ ¤…W0PÀ¾Œ¬úíí܈JÓ`>i¤3N*»LLKª)d$hjl€êh9nÄbqäeC¯ä¯ÀÀƒ¹²èñÊÌÂØJF³7ù õ ‡r0GÄ¿–ăï‡7äÙËtÂ7õéjÃ×`‡¸ÓÁaÇç”P†Â—ãoÄ¢Ü È6Wí-*ô4ÈW!î]®\¤Ø¹E—,Zµ¡²rcDSó ÈÃý%iå圵Ô‰Êfˆ ‘ "°Ë©ì‚”ž ÃK4ÈM•-àGåî¡<<àtaAÅxðìy¤7YÈW34à´o@Ã<•^¢!IÓÿ¯ÊsK¯=*¤ô¨ˆ\º ÌþIùp`m XæRÞ€°c? †µ®Ü(–³•ù£4ˆÝm5åÒ¯£ÿÈhöíÐìÌO²ÇÚ¾÷.›¥³›Žá¯ëž.FâzÛÃëÙrÉmåJö«À­=övwÛ½Z>ÿ«hé¿h­C•DßóW´û«< ã> stream xÚÅYs›8øÝ¿‚Gu­h>øö[1œ}°0rßzªoÎ-—0WK­ÛÁõª1¢L}ªÅðàõñÀ ò]ÃÄÕºvX„s!E1$Ä.kʽzÖ(ü—a„9³<'@˜°]0à6h‰B‹„Yˆ„r%ßA”ZhÇs<-‘$ÛÔ ¡ QNFéµ´@‚\'è"-ÁhzÐ2ŽðÑŒº¬œ§^ëmÛTga§BÇ /ò$S6QoÈ\¯ù"|¨Ì¥$+e˜Eæ?x­?Ê6Ð\€‘MÞu%Gð¶iKx 9ÑO‚aìQ óö°¢ì~Ÿ9ÒiޝòJî0Éã°öZdo)•ê™=ßn–Gaî·Ê6æ[YˆpÞ1Ê­Ös( ›Š˜ù§ÏI0´ñðÀG£»9¡¼×zC. ö³cQöšNi–r«Õ‰µßlÚXëdÌìéÐÁv^‡-qÌñ>åú`žBÅ&_3Ö¸}gN"“¿E¬^ê=¼îåVxÌÀã½ðTl Ó§!av¨`>—z¿²KT4A#BPÀØR¡: ÏLܽL¢"/ó©TpoêX[ïI²8WHžJu2¾\]Ÿ Åöø%Y˜H>_¤b.2JˆÜ;ãõáêÛp‚1ç$—;ÆoVGœˆúŽ–öU¡$N}û±ÖXZ‰ýg°âBƃ]žÃ‡#woxÜS®`€a†»ÏøÚõ×Éç¿z\ÜñO=o×Ç¡PQupïy•ErY\å>?ÕUR4õGEàrÓ*MŸ7Itª²Áán*@Pv¢’O‚a”L)òH°?º[u0(~À·Áo9]©ø|ècûìâãE…»_Ïmä]=ljQm–Ë–ŽAá[Õ{(]›šl7„ýÚ= †Ñ.öáÁI.ìyˆºï E~@–꽪³ÀÙÍÙåí ‡ßÁ­ºd©â6ß1®›à5spQà“¦M®»"¡ÌúéïM'b:“¹˜ß5]J>Õë"„VÛá|í5$OàøqHU Ov˜ÏÁLoê{(ðN3ŸƒA8`Ày&Õ]"ʳ8©Ý®àšuMQ`Û\GÄGØ5µÉ§<ݧ:Öˆк~3Œp¨—ò#„ú¼ Å‘È?gwtKl‚ÕsÍŠ<Ë+c†µŠbÕ%7v+g¥N;°Ù]uE÷˜Ä"F‡3™”r·iý….k´ÌOóÚ¨l‰äÙ$nðÄŽÆØ~xie_9»2T%ô»Ÿu »,?µ3÷Æ+nÞë~G9& ”ƪý †œë³ñ׋«‰¹-ù°¾8àL2È|r}¬HØ‚r‚NA~ýb¦(“qíësŸ¶her|Ö¶Uð ÜÖ%5 áíà÷J_êp=âPºÀg‡ ð˜Ò0PeerŸ©jHýÍ Ö@:ä@ƇÂê7Èñ–äQ/5»ˆC Ó!§Kƒý& ÐÃî$‘"š¤"ë%Ò%ñ]Tl‘H3pƒCȈE)ûi`àyðÿRŠ„D±$£ƒ¡K†jâûÍO_낈Üô1¹;ÉWü”clûcÀˆQ„Ù†O6ný&Íïv;¦A18È1çv¯tH©„lJÇ¡“>™w¥3{šÜUÓé¤|™ä¢( Î÷"1¯ŽC¢f9+ÊYžÆ=Ð×BGãµl0"`e.|¨ ÍÔtM`í¤¿;UsWuŸV¬ ‹Ÿ`2Z"ESÍiÙš,¸š¹@·F3ýµšª´0¤y¤–šJ¯™X/%íÑuM=ê*ªº}¡2,jF/5wš¹?Àé"CîÂäfŽí±ÎÙ,hçlØJÒTïG+©À~¨— ©ÀÅdªÏä¥zÏ\‡#ˆ]±ÕC' ÔüÃájâθVÕd¨ÿ!|®*ìeß¼)\UÌIjIÛ5Í´fjåmZ< ºÔ»wB˜-\JRÎ4Üé3}ÛåÅIÊæ´¾þ¬´6¹š¬eRdÒ¼€ª¶ÑNÛá@ýÌ¡2Á{ºÖpÄ‘Fø²sb˜iëÙkô û¡”b¾¨P&AwßMMšQŸoW‹n¥Øþé¤*“ì^>¼\d‰\s(VÉE%{ýžaíœ1‘Š2Õk~©åPkªÚvÙܸPáp#÷÷"E(;ñÂÔèoózˆô|¯JS[dë$þCŒà endstream endobj 1452 0 obj << /Length 3164 /Filter /FlateDecode >> stream xÚ­[YsÛF~ׯà#YeMæÀYµ»e¯¯(ñ¡Xò¦vã” "!``½Î¯ßî9À0EÀ/$1˜éîéþú˜ƒtö8£³·ÿ¼½øáïÍ"˜Ý>ÌBJ¢ ˜…1'›Ý®f¿Í¹·øýö§™ð=â1ãdëûbUoÒÅ%£ù«bYoÓ¼Jª¬È±óÅëÛ‹?/ô¥3ÖÐŒ"qo¶Ü^üö;­àÝO3JD;ʞۙç â{Èc3»¹øå‚Úrz¡C΀j½]ƒ<‚³ù2ÙlÒ½ú½]0:¯ËJ¿Y§Ë§ó?ÔceFÔ»UR¥+õPî—w›4'‹K/@5+UûÜŸ'›Zùšm6ê×}Ú!—K¦Û{#Dñ Ùy šÒ|îQ’oUªÉƒêäwºtþ¿¬jø[³ÊòGi :»dŒÄ¾¯fþâúJYb›ààoêa )µ6TU¨ïݾX¦e©×úí*-«,WF” RÀúáiâT°-ÉWꊣ›“ ´¥åâX¹eÏŸï’=ª$Ù¦•Ô 4!7T³zÒÊô¥Lh)ÓJý@¡å·!ÖÒ.ÌS#)ž$E„0ñ<ø±o€ò…zT÷ ¬^ñA[ºÏ¥m #, Ûîgë¡Ö«£x´óöI*õ]šÙãÃ’µž¸€AÊÑü9U4dM€ä÷J0{Mì×ã@åu‡o¥+È—›¾©êÚ†‡Í’Ùvp«™>˜à“0©Ú%4ࡹüô}º•ÈPÞÀ›Ä?š< ¿­< Ô{y…YµÌwOˆ÷ÅR/°9Qð Fj:3ì)ý{ßqº§9–’ÏÕÕSÝ8ýÁ‚®ÐÐÔú÷póÏ¡¢¬Ôâ™ùLWÅÜ·!¶ëDˆ/òB÷•1äÚl¥Úd˜ñ1“™çÊL­ÞUºÿ©¬Gýùó¤„Âv‡ìJ5îC‘kêÏKÐÉk—Uÿ}+C\ºLƒK,©‘/˜GåRŸžïSXá*åZÙtˆ~ŽåP²ºIßÎp\S,*`-‹_oa-ÚknÔ³ L%Àõ‚²öÚ·¨S‘Ðka×ÒÖ‰$òÎZZg¸ ÷¡CL¼X Ñ€Þa>Ó$äÊ>ô­Ü ÂùÌ <ÂYc’þ¦ã>áͲU F<·™bðé³å $£gÚ úœ„±Î\ol§\CN7›,_¨Ow…Y§Y‚ c*q—U’/ÓNEPÚD1Ì1ÖŸœÏQsëƒ H@i4 “hh@z¡a|b*‚Pœ¤“ žÈ‘,€´™âj÷8ÇquãÑæzÙa×]YÔ{³#«o7¶Î–³ Ï'Q4 ZSHhd¡‰`B§œ„ûñ)d‰z1ƒ¬gPç k$['ºlÆzÓsaã8»fs~—æÕº½és ^—Âóp úPøZØ´÷m¢Ö~«*ÔÙXÏžri@‚ƒ‘'¡u WJÃï9¬!,Ÿ„#Y:¡j3ÅmÛœŽcëÆ©ÍöH$<µk>϶’ˆNŒ‡“h(„Áª‡ð(ž ÌZ†N ŒF°ŽŸDzu¢ÌfÜœOEÚHÖn¤Ù¬]ñI0 ‹ÕÍ©uêÜ´VzÐkŸVµ>6(qyzéç+«‡R$A£pÒ§ÑÐH#Šð;¬r|A™{:–ŽeéBy‹é&Š¥#Ù:ÞbË{_¨ÍŠz[ìÓ." Žï{»›8RµÑ#tߟOï(ÏÖI„@Â<‰†²G Oø¤€ œ Ù"ƒÓ§†ì‘l`¶ë}¢»¡…ÒHænHÛ̯tHU;^¸;ôùÝ»gê§%˜:ï—”r?± ¯„ n5‰4_™XmÅ^à•©mÍI«#€¸[ÃåÆ)¦Ž›ôa[w,K'°l¦O:T9ºqb¹Ag‹õª)KÚ‡´Ý"åȹŽuœ3€È³…ï£ H°h""'ÑPˆäq@"ñ]Ia‰ï?‘cY:i3m_À9 ½‘üÝгù¿ì¬»—(䱡¾îs\ç‹×’&†»4ÚgsÊhŽ+±Ü‰ô^Ð'¬†°úàD¦nž>§ã^D¢(ž6ÃI4´ûÑ4,‡¬ç< ®‹¶_þs÷ñg„-DzmC˜…„SÑbû¦µ'¡*Gu\WÍÝ—z‰W^j¼ÝxÄg Ø7b¢‰'ÑÐ&æ@ëdñžrÔ¾ALX :Õ„Œ5~³ˆèüÅÕ»3`í¶±ÍºmäU¶ê,·¤ÓÕqÛž'Uß(0> lša'ÑP†e±eÉýÌYñ@Éíƒü8£$ycÛ냠ÿâÓ‹÷7ÇÍ;RA­ÜÛXØà ¥Âq7Ê#ñáòTÙ\[7¥ÏáæŽ}ÿ×—í~ïÓþ‰Ps©l†:ÀÜœO6™¹ª¸Ç3tEçéî¦TSý n¦žo‚Y Ó¡Ó®Óhh8GJ‘i;›Q OiX36{è€æ÷¯ož_-<ø”¿uËÝG\äýëõ§7ï>b¦øuîãt´–„ŸóäpÞþsF±«7I•ºà½ª;³¼¬p·™¥fKik_“{KæšÚ¢Îže @BøÓ¢¦ÑЈ |Åñ´#rÁ#(r( ùR>"”nïn>__ü„ȹ}ýj;ãDqcÇåe÷úÞ×Ìí¸ã¡•&w;DL£©ƒ3½rœÇÂü£a½mÇÓÎfÜ´ÎVB@bb¨š@AÃʇճ?­dæ°ò…Y2/Áp U7¿ÂÇÝCah{7’lö§Ê*Œ-æY’[·Ìô5Nxü£˜ù÷PªwbW7:¶±S•ú»Ó¾¿a{âÈülEô±€w­ýipšBBãI„$`lJ‰‚==³…Õ<ïÃéêÃÍíN{:ï¡Ï¾üqe£„r£Ì–êC἟x(…²M“ ‡+Ÿsì›(xlÚœ4̶Àw æ‚Ôõ>]ù*kþ]ÛÐÒß½]âáŸP"B=Ïè?OOîNø>¡â¬Å‰ùÿp€Ç(ž,Ö}XAC‹ç®¾MótŸT­ý¥oæŸÃr±þí‚§yWÆÿ§"d endstream endobj 1461 0 obj << /Length 2086 /Filter /FlateDecode >> stream xÚ½Z[s›È~÷¯àQªŠ&sÞìÝÄ[Þ“Í:±ÎÃÙì–‹ˆ‘E @É:¿~{˜ ɤöÁ‚™þúòuOÏ`ì=yØûåê§ùÕë[Á½…R2o¾ô|Œ)=?¤Ho{Ÿ&‘éŒúÁäMTFæîçl³ÍUQ$YjÜÜßMÿšÿêqÎð¯¦R¡Ÿ^½_}¹"ð{¤APî-6WŸþÂ^ ï~õ0baà}«Fn<.@×ÂÖÞÃÕ‡+lµn®ˆ }«/Ö¿ÏɘÑè~Êè$+ÊE–ÆI©õ× J~}Ë}G¥Ô˜‘a.Œœ÷YªÚS[Êh2³8¼fA-¡TÁO×ÏÆï6ÅsºXåYší óà딊‰Ê÷Ê–æZ®;d¹Keó¾~ºÍ³)“¯I¬b4À@Š(±Z>(2)(¹.²‘n>`i '0”54EùÓÁO¾|£–¥báX4 ó'ËÆ•)ÂóQèc¢ecoÆ „ÕàÃÍü»ûGKðFuïÓLL’–ÓêÆÅ3O4êDOÄtF  ï&£ç-¤×·uÔ>b¨ìOŒ™ñOÈA!ÂDÖc ûÊ j:“q¸miyQX“vi‘<¥*6¿«(7BZê„INÎPÇoÔɽÚÌ‘A[¶ÚÛ]$EDúy$_<®UÚ«†O Ø)-Žx¼òð5bU”ý:`ºø7<¡UЮèÑ*9fŽ=&RvF@Wú‘ʹ]1ÜTpªÔç)V-—S†¡6Uë¶ͼkPg‘C‹I²µµIÐÉÜÔ,¸sjüú–¬×æ.váwd.€Õ³di®*)Wõ3;âÓÕ/Êuådò9*´ÇõË¢YîàGÖžXdËÒHû&Zs«˜Jc¯6‹>ˆ=«’%ë¨Òz­´<ÑöñäniÆ¥™¾Ê½.úá*²R>+•š÷T+%)VZýzf±ìèÖ¿ETš·Ò¸êÙ¼ǘ(¥JË %¤"ÃÀ¡PR© ÀGBv)×b Ga@Üräh$5\Z×ÙZÿª­ý7c,„–à fEe©6ÛÒ.p™]•}°Û¶—J·mÙIúdn¿|¿K;%Jãúáƒ*w[[˜QeçÚWÕšnwvzÍE;¼_g }ù{9Ž›–Ê’YW{1Y#¤ž¡Ds“›ë&Ëí“§ïɶ±ÐLze-«—yeg¼ýÙÜPж6™¯+èú»4YQç#nå#™«È$$¦Ú±•1ð`¯LFp•y¥õïRå&íwUõø=($cbrÅnS•…ÂÌ{o|£¯ èWÞÚD_”Ý÷-‡ÌZ¹hIÔáSÂAŠuÔuYUæS¢Õµñ}o)v]®rÅ‘Á=˜^­á§z&íg†k:SÊ¡€DÞ˜pg« èë¡ ¡³•—ôÐ?XA*†ØqRŒ†M+Â4ëÂ)$C”‚¤Z¯ Iw÷@¨@TÒÁnY"ÐçqXâZ Uyê‚¥Ca[Õø>’hÃ>¸eihmù¤ÛÈmV¥H»ÀeÛèË®)>PñÓ…:(_­Z§KMÓ·Œîí—ÛÖ%ôp!óÇr” CHäƒI§MaU'tš\†Ï äPÈ>B¶@¡Y=ÎǨ½|l¡ÞO¡lfIz¸ªf»¼¦Y·ë¥Õå*v(¡EÆZ“ai%}„ñ ¦€Õ p^ U[ÌA«½´rAí赆!÷SËE~§Ò§rÕîjNð x¨;Î'¿eq&­[¢š”ëÛ<[8-ØaKæô]+•öõíã‘ÚÀªçŸ¤Åq¦_ì±.Kaœñ2ÓGɰL×ù# ¨ðñÏaú@È^¦» z{‚æÃ`ûiî© Z›$öÔ:·Œ^¬g— ¶SãÈ5J†% *Y? Œr†ü}»ø*Û•'6¶—`.°{ˆr„dàûIæB÷ÕÒ—6¬ îXŽÔÐö¡rOE=¯†^ì©.EA„”ãvEãdš“#ŽÅiSXc_¤9ìÑ0;“æCa{iîÛíøã©~t x?Ñ]p÷|ýíße}²~†yÃç;ËUsú wêÿ}÷Ξ|8Ú›¡[š-›×ÙÂIàv}¾bE¨4®SÀ¡tãY\Ÿ#l"=ù¹}ÂãL×_[*ÌW“ÑlW«z§ç4+U¢×ÇC±*£d]ØÓD,;ÎI³¾ãÉ®Iº—-À&ÇMã«î—¤¾|¿œ0\Õ"(—ïdœùõ‘ ÛYëÑ:‚©ù*öµ:0^ïÔËç<„SÄåÉŽŽJ‚dxÊÂQ2lEƒªHwè‚AÔ8Â( 곯<þþŸžªÂ @mˆÛ®*°lêïÍ-ÜÛV“oønÎweÍùb·Ð;‰ån Ŧ£"qÝË5ìˆú($#ƒÄ·ÓOnîÞô ìþ8»àí8ÇI|°NT1†€ ï¥zu#£ƒ[ƒQÑ%ÃD7 Á;tTÃòL9ô˜C=äMtï§ÚÌ›7¿=ð0øÖ§&À.þùžÜvÐ+àÁǵù\´6G ‘9þß̆ÍlóÙn'ÏÅ6w$ÇËEÔ RG”Ж]t¼Pÿ›‘DÔ—ÜY¹¨ºì*<¿¨TåQÙúhfû¥7YU™ŸŸô?wLTz¸`þ ƒQ endstream endobj 1469 0 obj << /Length 1981 /Filter /FlateDecode >> stream xÚÅZÛnÛ8}ÏWèQj–wIoéö†ÝnÚxvÛ"Pd:êHŽ.MӯߡHÙ¢¥ø`É5g8­j4¦Aè¿É“úNeU\¥y¦;Ÿ½œÝŸè‹=²²†(¤ÜKîξ~ÇÞž}ð0bQè=4=ï<.\c,¼«³ÏgØú¹º"*ô­¾Xïƒ!ï%¸2ãèe¡’<›¦+ß6¾|ÇƒŽ Jx0&!Â\ŸòL¹¯:~l81¶8†‹áåˆQ?/«ÿÍÊÂÖB¥çæÕ¿²Å£™ðØ\ÊÇ,™y–×¥iø9¢ÂWE©Ø4ä3s­æ©í2«³¤Z=o[—E>"Âÿ™NÕ1@Š(±!ºRš•œ\”ù‰aÞHŽN`„© G ŽÆcìßÿ~l»[ª,_#ŠýäþˆuE'Dqk3ãK3"á( 0ÑØ3‚Ba­~5ù÷âòúÕå…3ïëXZšU£æÆ…ML£~Ô“qÀ‚"aýù÷¼Ss=qÀ^¾ iÇC ŠV¾aÌL¤"Þé!LdÛ§³/L'g¬c)‡[Ç ÈÒŽªÎÊô6SSó+™Ç…1⸠$9ÙÃ`åN‘ zC0GR„Öi:»>è€÷]‘"¹^¨lЀ 27({E¢ñè7¦ª¬†}Ày±Í‡çŠ„vá„P,òìöYB‘@Öô= "´cÇdñ†~Œ‰HÈäÃgŽdÞhM¨g³à ”öQ657…ªjÝ&ü¬•M»Â¾þòÚÜ$s•h?Êú®Y–±…5¨çÏL€–¦K+³‚ú#¿pב_øõ.ænÚu~ÇæÒsÚÒ™¹ªÜ+œî@Ìéˆø#Â}à(ñ•5—zÆômi4ÆüÈÝ×Ë|V=èu .ž~ÑºË =8`¼mÖ 8]ÄïP¢€=l °13ý²\_åÚÝ8­•¥2ó¸i­¤å\û¡-–킞ĕy*MÀÍ£föô hZåQiºÀšØˆa `$©Ô$bŒ‡úŒu˜ÆQ’®ªv<’.kÛˆ¬§[ÿj¦[ÇoÌX…Ö†ôÆU¥î–•¥^n×xeꥻö¯æQ?+SÈÃæöþ÷E–Vľ‡¥¥ª—v}Aqm¾XŠÊÈ©pKQh_.âD™FÍÕ…j‚®Ÿ¬Ék^ƒ¦d^g?JÓ;µm6›°Ÿ×Õ²®Lc?!±õ[C¶½V¯B"2jÚòbÕ$y‹j³sm´îbÝÝ~ë½Q½ô7Úf æ[ëþöOEU§–vNF§ªŠÓEið5^:ë…*ËŸò ÍÖÖŒ©s¦Ü\ÿûó Lª^2ƒýô=8ÜD{<Ø3%Âì º­ý‡XÉ›SbÁ‘€.”–†ïU¦ óMd%·í¿Š4óôx«?˜û*Û<¿ü„õ!ø endstream endobj 1477 0 obj << /Length 2274 /Filter /FlateDecode >> stream xÚÕYKsÛ8¾ûWðHUE|ß쌧<›Íر÷°“™rÑd±V">âý6Ð h'¶÷²‡„@ènôãë†Ì½{{¿žüíæä§ó8ò2–'Ièݬ½”³,I¼4, ¼›•÷ÙX°XŠ4óß}£Ÿ›Ý¾•]W55Î./ÝüæEQÈâ4æú¨Hõä—›“/'¹Œ²Œe"òÊÝÉ翸·‚µß<ÎÂ<óôÎÅÀ,R̶ÞõÉÕ '­9±ªÝ!»C°,¢K|’ýÐ*eEæ]±_lÙií ÛY-A…¾Ïh)@L’OZþyŒ'±—†9ãAüØ žŠbfI-³x¥À |”†)ÚåêÛßÿ~ì¤ LY¥¯•9rAžò´#÷|¨Ë~ ¹¹ÿõŸ,‡^®Ú e A¶¶ÛoÇ*†¡³¾BÃc…ŠÁü&äd3.{þ*LÑ“>ÎcЊœÙäâóEÆý³‹Ï8úU²çýl wý¼ªÈµuÓ[>‡?éÞ—êuìàÀÓìmÞ}ònÀY*Ò7¥pš2 `³(ÊG÷^.þýtöëg<ü:ù!÷r/ÇŶr*±á±< L!è Ñá}?þóÃ5-~wrw'iܬñ»/ÚEÀýbwpºªp㯠¡€¼z&|^|écß‹X¼1~^Îã…Å.IU´öe+˦^U:ñìg¾®‚A™]ãQ„,>6µt:z(±$"cQJ™¹…ßtý«5‰ß¨‰ÈÆ»ôò•¯¡ô舣ΧûV—›¶©›"QÇ l§VÈ„n¿1Áºv0ÐP÷m£ú¯ÕJ®ØË/Âr‚J^K‰M±íš7Zù 4Ò"ÎãXȳ|± 8çþ—Ç÷lØ^÷­,vò˜Ã¿€4QiÐÞS>|Ò÷0dyÊ%ƒŒ„…‚|uuvóÇÅå-õ“ã¼ÏË„U5”dV*Ò•ì'äz`ˆ^ËcºöÕã5¶±·7޼ŸÎ3a)§,Ìbfà呵Iõ!‰ xï~ÌË$a Ó×úŽ^Ð¥óðEzõíîn:Pà'ÈI ¬¡îªûZµcÆøÇÜÁ‚$5ì·E×Ïp!˃IMŒƒ \QÊâXÀ g‚jËäej Æ'HEéÔ‘÷uŽÖÔ^´ªÛ‡aìÓ®r#KU1þÝ ;ýP᎘ӕìJ8ùXí1UCù7:…C[)¬èÕv‹£•¥ŸžkýÔ‰ŠöýÔøN©0¬×ºÑmiß×dÕoùÄbS´«ýVi%1(:å Í×<¿ÔÎÆ>kͺšÛZÁeØ„Å&ú¶ð-¦âZm ­õV*~l±Œyè_(Ýëf†É¦ .wRIv=q©º‘¼$Y´»‚*Q½YÕÛ¿á ƒ(%½¬{:@«£ÈéPÂ,aY˜§ÄQo"ÜÞÄR äÕfTé7"ÀmÉ síh{’ST¨QÑ÷r·ïqÒ7øí¤&dþ°§]†nÞÑ0ºª¾Çá—Ç‹º"Øšx ¡½'Ðw„Qa*qõ)}Àü*@@W%;z5}3.”tqâ?h˨t²úŠÊ´Ö`jQVR!´¢Ôªo¨£ƒ¹.‹ðEÇö²Ãé?MWR±Ñ3mÆñæá–ògøëÛîÉ)4"ùå"‚†Ñ´€Ÿ¶œ¦5êåfÔþðÞÒÀ‰)éU½úC ZöŒéÇj:ÞÆݶVö`Ÿ˜ûl”Эij‹5þBö)²ß6ˆm¶²©¥!‚Ú.'6ÍÈÄœP-€Õ‘§þ®i‰rÿXíg$v ÞÑ$útþ3R‚<ïˆ5õõÚ¿!˜çif3¸7Ï›u0o3Ý^ÅÂΘ‘ `´ß¥Ä¡²ÂV¢«`:e õÓÛ*bIAs€?"Rßøðg¬‡v.pÄví×s(!º4 %T5ÒAÝg€t N•C+¨RÆ×&bhÝà­à&·tcj®Æ–m 7± Û:êZñTHgÀ±ØnµSa¼ÓH¡S#K§;àboN ûeU¦2ó?#…2G!õfH¥x€#ôVˆŒî¤#)u‘Ë’ÕìŠ*dŽe*wŒ¿dU=›Êh¼>¢ývŠàB&°ØLE˜iÔÆ‡C96D½a L_ÕÅôÎ8l6œI)@¤û¢ªŸôUå`¤L…¬v€ZÖNäF„¢S“£;‰;tTuEèÛäj®L®6XFÖš´Íj(u‹e$8Ÿ¸8&O&Ð8»ŒðoL]?'H¸íœâ„û*¸eÛà¬Zã·np%P°ëp2i®—6U¹Áý“ 7e©ÛV‹/ù7w¢[b*’-/8°Àlv]R\¨Páµæ34Ô)ÕÔ™înÆàÍÎD“’ƒ§­²¦ºt»)ºvÍ 6;ŽfŒâ®-g£÷{%rÄ“ÔÁ“ÔŘöæÄ„'ºvá p×÷·Uí–Ñ\*áJêâÊL­µ$:¸bIjÊh§¨ë¨ŸqÊFnUüÇ”xð½:Ӛݨbž¥”¾°> stream xÚÅZ[oÛ8~ϯУ Ô’")é-4-2Û´iãÅ`¦30‰Ž…•%G—¦Í¯ßËn¶ìÄö`÷%²Ž¨sýÎ…T°óà`çÃůó‹_Þsæø(ÂuæKÇÃÈÂñŠqæ±ómBýéßóß—3Ĉ ïiêMשœÎ¨çOÞåQ½–YVIž©ÅWó‹Ç k±CZž¾|Êœh}ñíoìÄðì7#7ð'½rí0î"ΔŒÔ¹»ør­žQ®~ª‹ÕÚÓZä3«ö픲IX„kYÉbJȤԚ5,G5ñ.\hèú˜µþÃ<‚;ž Lø!°š!‰ea\Â\B…r‰ï"J¹Ès=ã‘d$6„rD=Y¤×‹q bn0ZʲËÂ'ÊRK½¡Ô;ª°¨á¹ ³¸ê_˜ãMžd šPåæšoÂÇÚ.J²² ³ÈÞÁÛæGÙg‡UÌÈ®mLN=r‚q»`r!eÈ™€<‹‡¤B ÷^0Eÿ%<Ò¿Å㛼®`ò4©£ìË-+{>YïÇåI’ÇaÙ—|W2\P¹>Çê°yà€¹zÎâaÑC0ò°÷O”3£Á+ÊÙ‰"G±Óš†eµ6§IÇM_*1YN]<É‹¦’¹Þ'[¼Öy!»²4,l÷öI”¯7T0«7 ïá{s<¿ý8>Ú)» Ÿ äãy¼rêsêú&R_eUªEPò}Jø$Lkùòä! êp= õ ·ßÂóx˜Ṫ!ž—7xy¾#`".3~ùòçâó¿ÆÇC§‹ÝJÆKo(ö}EUÛ³¥ÂùõGFu%›¶^GàxY§éÏ] ]N¡Ä²TÜ ° äÌ ŸÅÃÙeHxìåÎÂöǪ“O+q¿‹ñû©'o¯?îôI²ÇÝ—= tœØØfyÕ 2D||Ul74Àyü¼ðžÅÆ—bD(;+‡QêP*ц÷vJ(Ä÷ëÛ›»ý>M¼‹{ݾ q_þ_»Jê |ÚìJõnÃÌðöúéß?Ú ß6¸µ\ß7Ó¾4×M[D< ×[oÃŒŸRUÈ“Cð9ÚêÝØp=?gñ°øÁ¹¾8§´ÞtðùtuõnqóùëÕ~ðœ${;}á¯ÁŽíÑ/¥%Ü+ÔöF6ûÁ<úišGêòŸ!‡ð¾”Yu6ÇÚ»qà@sx5Çó8òd†ë«‘n åYœ´§E-3{ÝŠ¥0‡;3â#̸añ)ÏäðÕ[JÌ,*`dÍñK'yYýß4qa˜°*y¬pkÄç F4‹ØŸY´*ò,¯-ué’EwnÑ€¶Z5]ZgCݹ_¿'±ŒÑ ˜âÍaŒ4q˜–ù™nÞ:®lĹA7óA‘EØÛŒñäñùlö*¿'ÕêFV¡ÚÕ\ý¨ÔaP{†c2¢x°©ñõƒÙ‚z(ð0Q²0Hãz4õìíüÏëÛÅÛÛëIη™© d½þq@¼Y ”Ø£Ô0= ÌA·žøòl·óà_ÞC)ë´…zêú¼©m]ý Xo‘: ýÞùÆ,Ø=1ø9ÐÒ¦´ÔY™ÈLaûñ¢möúßp´G>¨ïDfÛ:þÂY†L endstream endobj 1494 0 obj << /Length 2386 /Filter /FlateDecode >> stream xÚÅZÝs£8Ï_Á£]5ÑJBð–Ü&™Í^f’I<·u;»åbl’P‹Áøf“¿þZ_6ŒÌÕ½‚¥î–úןvžì¼?ùÇìä§+ÎB¸ÎìÑñ0ò…p¼€"AœÙÒù2aˆLO©çO.Â2Ôo?g«uEœ¥úÃùÝõôÏÙ¯c.âž ÄÕTȯ'—³“o'>b‡l9ø>ò)s«“/bg ¿ýê`ä¾ó]\9Œ1&‰%ÎÃɧl¤Æˆrù*f ^ÛA>3‹¸›R6 óp•Q>%dR(É,ÉV ½ Ïþ`aÁÏ &¼‹Œ-qbHè-áN[B…ÜßE”:hÇs=½#qÚÔ ¡QA³ô*Z .AÌ êL M“-% ©;x¥¬Ê–RÙ[ëC«ÏaºL"ýþæxÅ©…úPfú™­Ão3(N‹2Læ?˜­_Š*Ñ%Ø#ÍÅqÊ%ÖÖ“ &CFr H@‰ÀäÈR\X®8H â¿Y¶²Ê´ÈxƵU®wSŽ'vuÐÙ&·0û:¥x²y|œºxà<«Þ"6!$¦ã`5ІZ~÷J`Ñ.àæªG¡ã¨ƱTUžªy¥ÀĸWUÆ7QúT>€x°GýÜ‚J4@ DÓS—‘ɇlÿ1–z B$<“‚ë<[€ëÓCƒÉÂävªô„*ÀÎ)!(à\Ëöý92¾òq“.Ê­çÌ£r#/Ÿ¤Åa˜÷ݰ&B‚ðÉ8”¢¡Q.|±îŒàÎS@‘Óã0ʲ ç5¦Ë¨(ƒ| ÛV”רðžRš8 wÈz£ í/g’™*Ž£aÀ%(òÿ>Tx®oÁõ.Û”ȶ`UÆR¥Ýžt ëvUYo]©g<ßfý)«ûÓ F“Vª5êý\hÿjBHp6æ£h˜ËùG–‰.GaÎ) ˆ÷F˜dÛ ó*ãHâçïrÞ•‹dÞô*ókÃ43þôãç››wúµ"˜ú_•JEÒ¦%d‹ŠaRó¨F#J—Þ¸ê‹ ,K¿®B9ü¥ ý_£Æôhiìí!êÇÍVp#RFœåÖ&Ë0NŠ)áÖ¢ãÇÆî¤Y›˜M âtG›Ã +Û'‰ñ$F$H®$ÓÿÄK¹¶ƒ¶Ü M;ØiË£h[Æ€ov¼€ Àu±e¨žÐæCY¶Úq•é Pc}÷+ƺ݊«¬·9QW#ÃÊ׬Þò5A$<6®œGC‹&ÐÐ6öò` eÙ ¬*Óçïs›j̋׹vSp&Qê†À]Ý@±ÚAWëòï5xPëæŠøUÊËnÔJ \ÈÇ_‡¡Ø_êŒ$ ŒƒâoìOsÎQ@MMs/£”Œ ÔÍÂ6†É&:Þ£æ jPÔ¨Ž¢aŒÍ…ú(ðÆ!ßcˆq´<ä“@ï˧ßç·ÿlƒ6ð¥ÞP¾uh(¼°[ç{UK°uLWYþb³üf!!›$y™,“ÿƒ`î-gSM.E~0RÕ£hUƒWq¹4D¸ì°¦E6%7ü«ØiújêãÉùõM‡¾1oWw•y]ÝËx¹—+Uwed½kê(ŒÓï(Z¿,p!­8V'BÀ :²#ޑׯ!Žsw«ß»)Ÿ~þáá°Šòwq%nou\áå¸+¹îÁ¡À§ö¼ROéð•×S&“É»" >îC´újS/úÖana®ŠúlH!`Tü“xùNU§ZZ)ñ¦°ßEºÒN¨‡hU×Âr 4€(I°‘ ±q4 ˜=0ˆ‘™¾@<`ƒdзŠæ—3 ç‹)ƒ¿êÝ|™ßÊlü_—÷W7·2hüÖöa¶z´š„ŸÓP'ZQ½XgëM–Q¼—›½ÁqZlekG¶ÝºŠVôªJ× €DÕþ]Þ±ÿ*›hð`Á#?ÇÑ0ˆâ &°q½NìÃï¾Ã R©·J³ùÃç»»Û{‰œÙåEv†‰ÒŽª(Ûœ½Ò©°mËvX‰”ëµÄ,d›(í&?ÅÚ¥:O™ñdåójëQ[º*{”¨õÞ”&L€ ø8¨¢a æÈgl\RM‰Êcˆƒ\;¨=üæ¿tù¦aüÛñUå,Û’ÇÞ²ÓÊ%Œ$±úKú¶È¶Mmi°dbd=BÙcù]UVy³×fz÷AÕ{'š€‚Õ(T²ÇbLúîJi0ÂÄk@êúãÃlnâ¡ ˆÒxþ¥iƒ„jZUªYë ž]Ž'Û(Ùõ°©;H˜<®|@£ç97 ª“¥{Š9Ät+S­v"ì³Ñ#BÀù”ø3nFõ©59ö„85`Ï=—ÛÆ¦K'YQþß$áŒZ e4ùmš¼ÔNKŠ—tñœgi¶1ñÓ¸¬]ÀµEDùlClýÌÏ~mô[ $·Ô^’‹tÿ)LЬïBY}—÷n•Zn®‡<˼%â‚ËÆO¾½^¦Ë‡2•¼”·½K§ 2–pÿ^÷h=x˜HÚXk)°eæùì÷뻹¹ºÝùr*€‹º4 êìôÉôCGÄ€g-!ùôj.Îg5F?]A·“Ž{Èõ¹­/w5(d(»Aº[P©Aß½mé§B ¯û‚©e‘‹"Ý^r•ùJ©É@]H©wt´Öö€rJ˜‡0fðâA ÇêÐ`BøJ«Û3@c#ŸL yׯh´ºlv¤¸ißœ-£ba‚ÿZÛƒ÷™²ù¶³Fd¸“4Z”ægCY½Ûë¡jZž­ô”íeÏý!¥:“—o/Gå>=¡ö6|ÒßÕÝQ=6‰Â"jËtíÜýZkÛ`l,ÖRšSG¹™Ä¬›BJSñð½xÕy#ü s-ø¦áÃÂ&Wð-Nõ·0µÿ—¶ã°Y—füŽ©> stream xÚÅXKsÛ6¾ëWðH„â ò&w{œÚŽc«‡ÆÉdh²5•H›·î¯ï‚)Q’KÌL/‚»‹Ýow?{öÎF¿NG¿œ î…(’’yÓ™§0 ¥ôTD‘$Þ4õî|†ƒoÓqÂ`_3{™§õBcªBÿ·<©—:«âjžgfñèÃtô<"°{¤“†(¤ÜK–£»oØKáÝG#…ÞßÍÊ¥ÇC‚ ïvôy„QaþšÁY­vY- ¹3û: Ü‹x©+]„øecY+r§… žÁ¸ÇBF"$˜ì,üÉ2ÂRxŠE±O¬æˆâDX—/—Pi\2D©§8CŠ)ë‘ùŽØLôh•j- +$hÔWZê²Ü¡–QDø±ZyO+ #ª¯õ´,6ð|Œ³´…êW,ðS>Ï &š‰*·cþ?×nÑ<+«8KÜì¶Êu¡i\Å ŒlŸE€SÌŽ8Ü6˜àl!ÈÃe¼3ÝdÛ¸´¿ÑU]ßÐÐ ˆðãE­œr2È+²Ï: Y-#öö ‡É°)'•DŠ„¿1D…qN­[>ùþé÷]øWHŒSÛÇ?àÞ”ÕžÚÓ:Kª«:`ØÿÇü褮t ç:Iѳz±xÝbÈP€ÄÁnG$:0ƒd¸KŠ¢ðGGâÍߌp$ “H’(ŒV> B쟜_ì óQºw‡y]y?ÌéÜE6Ë«µC¼ßŒî¡vmG$¨ ‹î .ºN?Ãk-» ñº_1fFí8Ä´\¬é±¶s¹ñê‹ ××\Ÿ[êå}Ûóò™Ÿb FØ—»(À‰_jªø||>ôvìAeñs¸Œ‰¥€N§˜ët×…Nò,wd·æÆPQ NòÆ$D˜ +â*ÏtkÏŽ #ÆNÇ0tì–Q?/«ÿÍÊÂVB¥Uî°ý)ƒÎc9–«W¯YòXäY^;$6ÔÅŠvµÐ­[°Îz5°}*rCB^æ©NѤˆÑrImiM¼(ónÞ¸mµêF˜:§@º  Æcì?ÿ{ZhmhkÇ6-ø‹—7g–û+)LŒXìÜ„ºv2ýr~ýýäú¼g½w7– à%7mCvªì£°¹öAâp>&E¦ÙÒœzÇJ-e(êjÒªnE|m¡Äª]³´ z¶¥”|%ÄyÃÁàfÀ*¦K‰Ó€ ¿9@ƒ¨Å"OâŽì@ù3•(PÃuŒ‹š½vë$Õe¯1ó§˜Þ-"壞\gÓò³²ôË´dAü©®ÀëÀ…ùòäÛ¶}Ãܽ¶ ¼jÔÂÜ<³sqÖ>ÃUÆš^?UnýJ) ™ð'qYÖËæh¥Ý× ²Y=)!I>Ìf–VÛïïM7€³›á¯q{Ìu@̳ë”?ÂAŠK ø.«lÉ%¹r÷­IõXè8½­Þí N÷%ªñ3tI¨úÇ^öIDÍí½ž%@9}»ó “a™ QÐDåϸìHøŽËþ±*w]ö{J—;tR‚„îH}LØOú:/×òÐæiš!j¯÷÷a³b'¦\@튎°r ‚ʸ:\ÆŒ†P`42Îhø> stream xÚÝXKsÛ6¾ëWàHãMâf§‰2NÇõи-Á¶¦i“”Sç×wñ -J²\I™i§eÜo±ß·Ø ºC}ì½öR k¥8Þ¢„àT)”h†EÃ1ºŠ¦qŸ%iô>«3ÿë—böPšªš¹8:;Ž¿ ?!!8– ãîUNíhïð÷Ø£0HmÒ§L Ñ¬wõ 1Ì}Bs¢ïnå Æ„56E—½ó ^·O̤ýia/ɺ½(EʽGg1gQQÕ£"Ojë¿upÙòÁ@$ †ÃàFŸ¦˜é휹é¾ÚqfÉ“~° `š§…Úìþ%Ÿ>û¸>ªç|t_y1¯üÀSÌddÊ‚Š[ÿ¬ï'aÉí<Õí|3úP1•ÑÓdlÆx‡ 2ÌhðòÒ°ÉÀÉiUìæ%•6p’`Âx+S,1åqŸB¢ÇƒÒ˜Ï¦ÎÆ Û?ˆ$ðGƒV‡å]ä…ÛD Ö ¡Ösû­ü{NÞnõa÷áÖíÉŒêÕù›˜‘öoö›].jg’ßùXüSVBFB@󺌩u·öc§E˜«ïK“/3»ôºÓÞ¦¬·aæríÙÊD”•paÂÙ‘ïº* ¨m¦›ª# •¶Uà'Û ˜(‰|×|“ Xͱ†ƒÉ›ðåF" Ñ`Êå#ÇŒ%•³¥dµþQ€â’í ¹˜´”$X2Ý]< – %ì6U»BwÎ *ÌÔÒ~Ïbjá²!”› ´â!{œ›5©Úu% ä´ «ªJ‹ý”µ½Ø“p ºµ SÏËÜ×Ê'[}³éܼ;\ÚèÍÞ Wc^Ýá~6|îp®±Ôú ² Ù@÷.ÐëÉ^Äî’=ž~}ùoˆnzáõônéØ*1`@Ámk/r÷²È¥ S(a{°›@Q°!q%™µìžÅÚ–£‹£Ï—Þ ~=Ëøm=ì\tN;9ÙDê¶Î¬2b{3Æ÷cu{[^Ž™RÀXÊwiþ{1(@ˆô¿pCO˜Tÿã:Ö4ì{ÝÐÅ+a^תH éH·ùÖÓ|™u&J,VØs.ôÑä¦|¹º+Rûû•íç;û9 2ù²‹C!T_ endstream endobj 1522 0 obj << /Length 1376 /Filter /FlateDecode >> stream xÚíXKSÛH¾ûWè(U­‡yÏèK•l%!àËæQ”"¶+F2’œ„üúíyHXØl縰4î¯ßÝÂÑ$ÂÑùàïÑàèLðH£TJn"…‘–2R)E’D£qô9f4ù:z1Á' î¹Õwåx97É*¿*óå­)𬙕…=ܽTчJ¥@Œ§{@]÷ !Õ~¶;~ôxûm¨u‚ Ä!÷:ý]šfYÙ¼B­rˆWÎ "‰I”2º ÏK¹Ü"áA4B$Q Å?k,*Ò'Ý:C©T!†CrùøéúÃ?ܪ¹´Ð÷cÛwg¦†¥Ç÷j™çP}¼³¶µjbš¦K·;¹´²ÝÛ€…tÁ¢ 9HyÁ•B”CJ$ .;ƒ_$ªÝÉåÉ»-†ßýfïò?KlŸÍûùkòd—ò«ïŒuÝb@Bu˜Õw§Ñfž&4.)„Ðï]Tz¡ñ¬!:b]óÛ³† ­F˜‡ÖÆõA½«ÛÚ’a ÙLÉ®7a4.ëfo$ü@$Bµ³§>ó{ïk™ÿ©ï‹|Z•E¹¬W|ÐTu×T—7Á}}à O+ /¼µ«‹ª´¥æ4¡c´‡|†» à•1¾xeóº<ÐÞFÖWPëEo4«£aN+Û,ç’Ÿ–ÌPt²û¨ˆ²Þ}Tìxæ7³ÉŽC£x44nÔ+-^0.ÊöL dÿz™†RBsB[‘m;8¾ÿðqá%àrKú:÷z[Ÿg!·©ž›g)NQÄO(”·½ÕôRMÝEèTO/O%÷yp•¥˜š ‘dÖC&„£·U7ZÆìé™WëvÕ½°Ô ZçÅrž5&lv qÐüÚÏY3õO‘~C?%P›jZ ëdÒ¸ž‡Lñ•ê¡Òñ4«7ÍY[¦›"¿ï÷J0AºÌT~6ƒA³»èkoC–²¢Tuƒzšåÿ÷›‡ûG'žñ·MЉ3²Ë‡½öƒž„ÆRr÷ýIp$`†Û°…/K…©ÀÁCä8ùïÛOŽN¯÷›ÑcS<Æøgÿô‘ endstream endobj 1439 0 obj << /Type /ObjStm /N 100 /First 978 /Length 1903 /Filter /FlateDecode >> stream xÚåZß¹ ~ß¿Bí‹,Q¢HÁw¤-Ї$íAàã4èa7Ýl€kÿú~ÔŽ³ÞعŒwmœƒ¾ìr4Š¢ø}"Ç“ki!…\ áOu¡„’³ 5T-.hh,!“µ z•*~‡ƒ˜ëâI#s¶’” H'¿¬ÕMçn¿…ÌÊ.áñVú]…$#…ŠÆ7¥u5̯ÙÕ欹.RLÁ(wÃÜ ¹•S r'kƒTšú˜âäKa Ôš; S¤îa5¤>%VBV|9 C& S´J"cƒÔšßÕP(»aøX »aÜ(ì¾WI¡4ë†ñ¬7 5ñÕUÉ¡(¹ŸM a i¡&òÐ …š»ÇR6Â# ØN}L¦îV,@·ïˆ@ÂcÙ0¤Ù #”U{ 0?§\1…¦À¼åÀ…Ü0,qµ>Ö7ñ5" ,Ùר ©ùb»Xâ›`N¹«HæjVBK=Pj¡Q€¥ÐŠÇ³" [ãФøñXñ€ïXNõU Á»BXg³ÜÕBž±‚ 9gL5 y<}/¥ÂHRízÈÅjÝîr9¤†°v5dn£®– ‰ù]%ÏÈ$Hã†)<К=² /´@æ\ªžj ‚º‘ÌA0æûµ”©eH¾ŒÄÑž œ,¨2ö‚‘ÍÖ3б]æ¹Iƒß3ÎŒ»e*ÁþxPM<Éܺ‰uÃLá1Ï^ò›VèâÉ“‹ÙËÿ¼Âì§ùÛáböãÕåÍpyóÁá*€úó‹ÙóáÃÕÇëåðáÂ}ìoÃêÝü‡«_ë„6Ž$¾¶Õ^_ÀÖ5Œ`>m|yy£¯n©C·Ô1 µ ¯/¾ûnËŸþÈÅìÅÇÅM¿þë»Ë]Ì~¸º^ ×}ÖôzöçÙ_f?¾ÊýÂ]Þ„WÍ"ˆlŠÅy"[lÈ@¤CÌ õ}xò$Ì^„ÙŸ®^^…ÙÓð‡Ïoþûîýýç›yÄR­ë¬ÃœóÜ긭uµÐ´,ëd ðñ(næ‘'H‡èÄ¢Í)T"³îuóíõÕÇ÷oÞÀÛŸáíÛ9­ÖC²Ê‹y])8q%È´…ÍÀlê |mÅ@²Ñ ì‰i’·àìCkö°Zµ¤Ë¶.Ì /¬dÛÛ§˜òö¤yfÿÇÏÁ÷œ©)G¤t¸üøË/¯¿¨,©+s+QA`Ó”«FùL÷ Ð—õŒi’Û‡ž9”œÆ+œLªo±ßÊã•“o©›{Î55mŒøYèW˜nöÓõÕòÅ€P‡OŸ…ÙËáכϱÐÊ»­å €:~КF\Ö¼èøÅI¼¿(x8‚‚Ï $%zýq PBêã ;S€fµ(8Â(!Ƹ4‰Fyš³Cx0-¼ªsžƒ›¬IV•l­¶ÜÁg­às[y„œHŽ^ÈLRnM;óLR.¬Ñë¬iʵà`xôï£]"¨óöÑÂ6Ø‹LL»DÀéAD°-Îìð¶òZ?ƒÅõ$eÚ‘¶)ûp/º½>溹òâŠ7Š^¯ëÁÛwznyϮأéy\\ïNŽÎÊ 4Ú‰ +3ç(íüH“7U·¬Ì5¡ ᣳrOÖ–€Á¶ò†»²D-uE4KÓ”K‘è]ø$åÜ¢l¿O‰s_G”í"ªÉ£ÕxDTk'hD¼Îñ.ìS#‚:Gë96"¼Õ‰ ÐÑ!JA”îVël8àëDåZ‘ø•‰kë·ŒÙÓ· ?%²éÛeÓ·Ë)úöÊ1™ÜÁ… ]\9C¸Ô[pAIì\wBîí®q'õcþ4»Ò¸K; 1Ø£ÌI@§:M¹ÅÆôZju?ùF·îiúõñM¿nš~Ý4ýz‚¦¿pŠæaÑíšh>?t—b1Û »TTZ_¨ƒtS“XüÝïm×O‚Š£òiº~=¤ë×Cºþ=ÊMSuMS® Ü&*kQˆÏ¡ëÿ­žõÁ,au—%Œc Ó]–°‘lC–ÏYðo«È*þÿüX"xvW€!b:Ûýq´­ ·åT5€•hb[ù«4±G™Çœxš2þÓÖ4e*8¯¾é—ƒþîs*ðŸ5Kf'((¡ûÊwåÊT.rLàûNûÄ“³óžòײs¯rBC-«þóÂDeð$ÎëiÊ”q–Jù¦S9—ÝTÎù±©Ì£[ý÷üÿû7ªcyÐÕ‹Hÿ–b:þ¶•¿òFu¯î—Þ¨îSö¦¾Y›¦\$«{”ÇG}¯t¿Š<Æ»#¦=‡¥Ç#l¬y\Vÿšet#œà@ÿêãø¤Tjv~蓌hb+)ƒÿKñ/—0^'ÁoÑVmH•Êr½"³d”—‹•¶ÊÖVZŽçíXžû§4[ŸÖPjÑÚ6ñÞ7Ð]uŽ„-|¶¿Ü£iOÞ¼'ü÷¯Á´Äš¦}Z3´õ:ÑPÙj[¡$×\–<_×FYçi‡éú‡©ö(·Ü¢*OSf®‘'zAp½2MT†aÿí“òÿk8ð endstream endobj 1530 0 obj << /Length 1646 /Filter /FlateDecode >> stream xÚÅYYsÛ6~ׯà#5S¡¸¾ÙuŽIš&Ž­>4Çxhв9•H…G\÷×wA€)ÊrDf¦/¦®vßÞkìÝyØ{=ùm>ùõ•àžF”Ì›/=…‘–ÒSE’xó…÷ÙçˆLgTiÿEX†öÓE¶ÞäqQ$YjÎ/ßL¿Îßzœ3$æõO3§“—óÉ· Cì‘­­‘¦Ü‹Ö“Ï_±·€wo=ŒX ½‡šríq̸a¶ò®''Øiæ£y¸;¨Cwiî.q9¥Üóp—q>%Ä/jÍ–5ñ žG4dB¡[ 2‚°žbÂDãÔ`%A ‰ð€„J‰fˆROuS‘$íÛ†`… ‹T-+Öò+´§9 Є Ë;b•D2èJ½n»ê}˜.V±ýü ¼É’ÔøD}Pfö™mÂo•#JÒ¢ ÓÈ}ƒ_ÛE›éB˜‘þÝ8ÕrÀÝúÎÄ dÈH‡ÅÃ9$åˆ ýìU¨žsH ¢•²ª<â‘eôȶÔ($¿‰²ô ÆôîˆoSà o¶å_8Éd%ì‡åÖ¥–S†ýÌùåÅÕ…ý ¹}ÞÅi¼û:âw'ëÝ÷jÜRó»Óyü`š—š#­‹æU\V¹jÿû”?\Uñó©^‚a8ùˆv ¤öô Çñ°‘%%…'—w1ðR†—DJ ‹ËÇO7~?àÜL! .:Pn×¹!㚂ޑûªJ£KÇÆ¥ÿ1â¨*ã&‘VQ¹tY­V})À*ä û2ý€äãŒ<Ї32WuFcädâIAe;¿šj쟿ywÄÒĶt[z§Æ>Ô¡WØ/iV6³¬6O[ødÍúÖŒŒ´ð(ÎÂŒ"-ä¨b¥¢œ+°[+Š/§„‚‰¯Îÿ¸>bäaònè­‘Û @¥ª;ú=‡à(ФéùëÏ6Q¹¥íðeôØÿý m{2'âýŸïÞ=íQ'ÃÐ÷`!³xÞ£Nçqâ¤#´ W/ó°Z$uÚm¾æ¹‡5¥f¬Ñsgæ÷YwÚÑcO‰™ãÀ±y¸i‹Q?+ÊÿMÊtጠÿB=²=¿Ë_itŸgiV9ïû>¥Âó]ÞË–nŒ¸otÙ)€Íé&ÏL†üž,âpAÈ»d›wcÛî„«" óÞ. '0”m—H "§3‚1ö¿ýû:.¯³eùæ±Ù §´¼Èª´4³Õv$²‘߹ȸzmçhø&Föf´h2Ýùüӛ˷VØ^Åû<“ ¶iýáˆxK`”¨P·9œ‚‚FH•É]jÚ†i¦-½ í RõÓUÀ[Df²“ MZ­oâU¼¶tKBJÅ,Ø1³àìÙgF”€)AüÐØÒ¦¯…q´(‹Æ½Ü0šš  Zß6ãkã5$u ÎeÔ€ãXTEÓ~ÝN¡ <î1þx^×™ù§dcVÉ­7@3ôTìtt;–³E\Dðä&çôòç6‚N0Àù&ÛT«°ŒÝKw‹]MP‡W膵žõàÄIyo‰¬ÊA ‹)ñs{TÃ4EŽ`  s+/YuEÕ+'È]ºíD=` .|ÔÇ¡ɰ´°é‡i€¸ œ÷áje_ØÞ Înc{Á«Úrp–¤ö,L›ïeœ[¸ªMéèwB(È„Eµ®íSØßÕá_SŸ‘^.—¶E/ûï-2YdÏᑤ®Dÿ5%¸8;Ëc@Û"•–)Êû<ס•¾GRgc¹Ñ€Íalð¾H¨>i#ù“yØî‘0¸•zfb§,ŸY¯™dg˜_oX(¨,é`±Ér8‡ ×Ü ìû•A±(½;—h„P]é×{¡«Ç» `}e—¬ÉPnqX×ìûe ,à›Ë›ÅSù¶I·æü@°@(fQnGa—Ööp3i…’˜õýX(ŒóùÓyü`_Hàq›bŠGåCÈ>y¿Q,ÜÆT 5r­Ã0(" ?³Õ‘ 2PèÞÂòˆV¡ãW:œ ¤Äû[E‰¸>É4¯ôXAÎÀŒœâÄÍ?Ï$‚y“·Ü®'áQ£õÚìiwÞn¶^d5vw¦—öãtß—ÿŒHN endstream endobj 1540 0 obj << /Length 1820 /Filter /FlateDecode >> stream xÚÍZYsÛ6~ׯà#5!8y¼ÙmãÔ©“رšLsŒ‡–(›‰TxÄu~}—LJ”l’éL<p÷Ãî‡Å.`ìÜ8Øy9úm:z~"¸ Ðó˜3]8>Fç9~H‘GœéÜùä2>þ2}å0Á' ¾S­¯³yµŒÇêîÙ¬ZÅi•I–ÊÁ£ÓÑ·±Ø!™A€ÊÙjôé væÐ÷ÊÁˆ…s§F®.\êX:—£‹681¢Bþ”ƒÚoCípû]\Vy ià~áFË*.:+¶%@`ð<€’ùá€oPþ‚2žp|‚ÅýC2`4èáF‚¶¬_³,¡Q°µÏò™¯M{ññêd`÷øôl×ÛÄó!=uó†nŸ!øMÝ'U:S4SÌ›'sý#ÍJý£¨f³8žïââ\ _ô¶ëà–ð¸{É0îU¾yl&˜õ>ÿ !E…( Ã{ß¼½ºüpu<ö±ûþQO÷ƒÑîê:ŽÇ\ýcššÆÈx?[”wj±ç&6­óL¾Oæq®[c†Ý¬þ-—×ÑlL±ûõo:Os×é ûÁ0â ’aˆCÀë,F„J‰qÞ ÎŸöS¥—âv¦ÔwbŠ•¤E ŽMóWé~Eá¦ñÒH‚w Oò} ­Ð¹Ÿ]'¶ëWÀX8Œƒdhnx¡‡Â T|QNA©Æ ˆ)‡ ÒS{;Cêê-CŠÿ›"ªÑF—GÂÑ^:u7ä?Ƨa2 Ÿ&³¶!¡ ,%E¼: øãøÝñëËý|ê£av!zu65´Y˜Ô¹Å<N#6ANÇ»Õê*^Æ+C'C¾7Ÿð}GÈ»^ ò|wsuqÈ<¸¶Õyϲtžlê‡0óÜ24¥ª„ æB‹x“¥qóÓŽ-#cx§žu³¢ì„DBa1ʸ§Þ¦ËûfFtŸÎnó,Í*Ã>¨ŠÍv™-ô³¼µ]4¶SÛZ ]sÔc‚QbP^Ʊ.Ì¢e‘ tøVkÕ Œ0ez(J$ñ!RcŒÝo?^Æå¥ Í–ÏVk”–ïÇBEw˜¢´ÍYR”Ÿ±ÀðG B¹>ò³PÞ©‰B.…BØh¤fìLÔŸÂà»8ž~<=¿:>?mLÐù4ñC’¾ãí£$AèaÊT½L`÷7ÚX™FÔiºÈ®¦ (ÏOZÃO`CÀ‹·C\ÈkƒB„‰gÇDëä*¹ÏôÀ†5&„BÕxMXUZ$7©ÜP­Ô— …@Û GjÃì. (1dDaÚ™[욈e^èy8Ô†›„oU\”…]fÏASTÄ;‹©Ø^MfÈűڧ¦“µn8K®s¹7D$@ñqoëÖkýcf9PH*ª…&©¥i`G󸘙´c­×)£ â8[WË¢´p•ÇÈž(× ÇZì’0e×:'âd3øh®› uLڢʿ …Té4R2ŠRƒ¨fÒHòÓ»¤¼Õ}jú²)V±éÒ¹îlZMv3ωé~XÓ=ÉHÆ}GÇÁø_™â âNu€+Õ´·`Ý¡ÓAh»ŽuÃÌæЖ¤º-Jí{çÆëÒŒPŠ`jL¸GQQT«µM>á;¹Ô裂鋅2k¬¬¸Õ-SNðŽªM'm6JÒm’Æ„ƒCã<ëh·§eëˆò6£ùe¤µo QqâPX—Öfˆ0f7OÉ·œ]Ê F}ô¤b¢;œþd:C%Aˆ˜Ï:W<¢–%Êœ:$ä‡Ü:æYV•-™©¿nIÄÆÏa2 ?=ØÃ|~x*@ªð1v‚çeñ4vöRÚÊͺÚFQ´—›}t·3³®»™&É}HLtáoB¦å°IÅ&ÐÞª4øN¿¬@¼™M\NKmJZ¶¥n’nå[òvvÝçͧW·eG îò’°Àøß]ÆkG™ZzX ºç!*›á fuc Yw8pÀêô‘` =~8!yû×Þƒ‘žj[Új›G±zýèô¦*íòRw4E±¨–P¬îåpg„»þ"æâ!"´‡ŠVò3.áB ñ€<ý®—æV×5÷¾3ŽíŠjÇ'§ny‡¸u{û†xH~Êå›fa=ïÞú€h?.¯¡ø5nÞ _:ϱåÎ ÑöùǃQB Ì:Çþ…KØãêLBè£O."•Å_ÆiœG›©ê¾{ûß*ˆÞßÈã+7N··¶ÿæÊ¶Ò endstream endobj 1549 0 obj << /Length 2081 /Filter /FlateDecode >> stream xÚÍY[sÛ¶~÷¯à#5!ÞúT7M÷$Ž«ÍLÓŽ†¢ ™'©T\ç×w R¤DÛ±=郆àb±7|Ø]PÜY;Üùåä§ÙÉóW¾r"tf+'ä, 'Œ=g¶t>¹Š‰ÉÔ #÷ç¤Ihô¢Ül+]×YYáôâlò×ìWG)ÉüP‚p³TúH=y9;ùr"€ÈÑiˆ"yÊI7'ŸþâÎæ~u8“qä\Σ|¦PXî\ž¼?áÖjÎ<‡ø°>„c>‚EÊ:ñA7» õ"÷ëDøn’ïtm¬kÅŽZ &Hx>ÀÊÿ  Áxà;¡Œ!âá]2€ô(+"ö"+g‰°Í¡ )´ïÿ˜Ÿ¿›¿þx¼Õ"™T¬ŠCɼ(*~µ+Ò¦ƒà2[Ò (üɹWXbb¹²¢n’<×–üyâqWWð⻅έ$x„d_'@…É#¿|O1ï~o+Hî–p?4ž$ÃBÃó™Þç $_ÜŠ0džò@TÌâ8îAãòã}øxœöq€ôÕ·©ÿm„biŸu¹j®MŠ©4Q¶U‰ï_³å]hzpŽ¡"x= NO’Ap â˜ù‘¼Ût7öoO5<`!h Ÿ)µÇÓÅDÀ†œ~8}{y+ ©_rÀxÁP}ý€‰ZÀ§X‰¶æ%Ûlž«‰än9F1ÜÝmæ:׋5‹ÌóßÞ¼9àm!š'ÕÚÂHån}EãÆÊ®›²E€ÖÔà)™3‚žo÷í²‡Êß'bË÷™µt>kå´w)ÔK[ ÇÐúð! EÈH= ­ñÀ."ðáÙŠsQé´,–™©:ýÞ¡}ÃóhžŠˆqewâ¼,ôpéÀŽ#¦V‚âð°­ÌÅDznY7¶D=ÑOF­„F?2 ïŠüÆÂÖï¦H¯ª nτͭû³\Yè_µÇf5hZj/Û.Ù#ôßÖÊK­©eLòº|â†4Ú­:€÷d×i3Ÿ‰N çÜýòíÝ\6I³«ÿä>‡Ÿ°6à ¨Öö(|0®@¦dqÈÊæÎTBïÛþÓÙgsÛ£w¦;Ÿ¦hÉ È4ÁPPé- è­è§Ê”T÷tCÐ2kVGÌÐüñVrfýœå¥AÊMHÚk^UåflŸ/#€sÈ/;Ó(Âh›¬˜84&±^IŽe[G‘¿*AÏ›«J'P3§RJoV¬ç(tÞ“'èaBÏ!p¢n Wƒ€Q+Œ{{›G% q„­¨=j%"¬¦‰éÄaO'rNœÀ}^ÂþÓÛQHGåCâ°(›·¹ ù^_[‘-‘— ëøš–bÔ¿r…Y ƒÍ»ÿááqø óÓ³7.ÎðØ··?˜øÜý½Ïqv~9›Ûã9£ë¦§¯;¦7ïðqþöåÛž°þÅüÐÀÃ^¥©Dû‰;ôö9Ê»‰9ÌœNB”k}î—3[ O·Û<ƒM¤;¼„ëS}UîrÜ:»]®Áijº!“°poYP?í:“ßJÓ‚w%‰‡%çMbÀÉ´„:œ6DíªÚ@V¥¿ì2*@.·`J ³A.œ(%c÷¬9öa1 ¸ýiQJ\…n]n4ÑÚ륭® Utä¡Â‰< M”ñm"•dybÎnÅ”¦ÇQ²jLyþ®™*mRÚæq%pLÖ¦ nUÖ´"K+ÏTÊ¿»9L‚Ž ˆM70âû-ÅÒ\€iK¯zÐ\c‰F±¡OÞXÚP­%ȰÔ[],iL=Dha¥¢Ã­Ëò¬¹±¬++PÆpÍ"©µ•—ö?Ò#!!M‡_¨pj¸l´Çhe1Ll±õQªƒn‹Ò/”¦‡5xmC^Óë5¡Fc!rk´½(¢¸á–¸HÛÅÁsè:t±Î =Ú-&íÀ=Уëù"IQÑçݶûX(“5£N~ð­hØ„ÿ¤×÷™×Ý(á}nbª»{Ü'áò#YôÒx5"MÁKyß+îØß‰‹âï6ð`SGä C1wç1¾Ï¸ùÎÓþ·0/ TòYím«Ð•mL  ]{„ÿv•&sݬñ6ŽÿÀĤ:Å| endstream endobj 1556 0 obj << /Length 2213 /Filter /FlateDecode >> stream xÚÅZmoãÆþî_Áoöd€碹ôÒ˽Änƒ4 ´DˆÊ¤N¤Îu}gö…&%šz!‹~±èåî<3³ÏÎÌî’Ÿüpõ绫o_+Ä$ÑZwË ¢$Ö:ˆN4 îÁo¡Ð³?î~ „’D2ãLëOåb·Îf×<ŠÃ¿”óÝCVÔi—v¾úþîê˃¾4`Ì8&1—Áüáê·?h°€w?”ˆ$Mχ@*A”DŒup{õñŠ:=Ÿe1ÂC¡ÃÂ8‹I¤Ÿ…ý„H¥‚Hi"ù è- §ÊE"…váϾiº#Û…$:: Û,X¶ür8,‰ã D30ÑNU:c*ü:ã4LóõáôpÎI“é á\€ñ8C¸`Dö9†¨ˆHÊ'4jÊö ‘‚Ä"9Ý­ÁpÖ1¤Êê:/>š (#ZL8(0î4íT’(æ/ØðN© Nµ ‡85¤'U r vMÙ°ªiC\7³ˆ†ÿðI² d|0¯Uí@†RÉHÞÁ\²I¶Z+"€WGy7²¡Ý1HÏ» =íÚCÁlçEf®9hpÍ€,ÊÔ%TCAè×JËשQo?„Šxè“/íoQÚßUº]´p ë}Ze®ó¼|Øl³ª²þ§ƒéw5 ëUV4OvÔêñSe%~ªê´Þ9!ùzmŸî]Gð›ZöÙÜlU ÑèHyxcDÀCWmh°ÖÃÃ"Û{Ç<2¼ÜU™}°ÊÂÃÞ$@‹s4¨dÚ“ ^ñïpž¸%N=x‡dÐðL²»º\ò可ïØþL9lõ”Ã7 åðE?å`×f½b$.í8ä„Ò£Ceöœ‹½='ð¥ÕM¼Ä ìb8Ñ6\[ÃÓy¬ú‚ÍvžðéÞu4 Á‡º´¿ý5 ±/ß®ó*wç`Z‰îˆ£ðãÍŒžwÄYŒý:CÃCŠ>}êj³kú¯J”úxÝ7½Ž4ŽÉ¶ÐºqúA¬á{±ÿwÀ¸Õë^KJ‘D†‚8ÂúƒJ›ƒÜÄ«uŽQ_Ú6} :Ðà>³´2a UÈÓü7Hpê–½UÀ8ÛÖ;´X…EŸ_æå"³ƒç©[˜÷®¡Þf°XöŸ´j/. ^Ü–Û™¢v9²ðÕ¼,jãä×¶çQû.wÅܯBV«Ô.|SPÛ6 É@‡õÚ#殿W+ù[°ÌÝmܸ¨×#­ªÝÃáz—ù»²p÷Ò¯ª|‘}¿\âðl^W¶µõÞú·´3aýͿΘ„®û«m–õvÆPÏÚ‹pïêxpq›Zˆ½áXbP¼óÃ{9Ž÷rß¾ŽÚWƒ 8^• aÿ0ã’>dà†XêD¸k¹¾;u™(¼§Èï‚+B¹ì)¦ÁÕ*1^mž}h© _p¾ˆá$)(ÔÜ‘YÞó-ƒâP(~1d§ì†êPA9ÝÅøØ+"¢yt)l·ÚÇ d(¤:°·M­ }øo+pƒ½)Íʰ µã^¹I¿ì\§¼€p^ÌÝ6ùDqXµ….Ò:íߨ d@Â.0îL12bLjp|ÔúÈ)Õ©tRðèxb/Û˜.K¿ÌÇ‹pû騯ý€q¿u>“ÿ'ß8Žù:Â<»à=‡„” í\­IÔȸw¶ˆn,·3Øóí”äánŸô3¦f\€<†¢óÿz—Öͦlðä^ÂÖ®wï7…·Œ(~ñ¥F²š™Ï~$M ÑEƒ;pCjàæ…¸‡¬†Yèà¾nªd«­*lm°3Uáðn>‡°¹Ü­×OóíHJ¨u2œÛ»:lñõ,ó8§C¦I’¨ø™KLHºùùæ§Û—Iu¼ ­œà9ÕÁÿR¨{ü“&µÓN·©ÚW¡ûöåY?[ÛƒC ¼7bÒÏácÚ‰‘RH<–sg›A©¿È›OHYî÷à²þ1¡²]øw†ß×N‚#óiOð°¬ê‹5‘#5á"n°]æ†÷ÅúÉ‚.=óÕ¶,JÏA·I~LåÒeù•§ç²*}ëfköß_a[µ ÈMqofÓbº®Ê©&¼/—*Hâ‚óÕ±ÿ†SiiV³Âû'È&P¿hw¨òCVdÛ´ÉÍ!‘ùÚ¤–'ØO®1+öuü/h ‡ endstream endobj 1563 0 obj << /Length 2524 /Filter /FlateDecode >> stream xÚ½Z[s›H~÷¯àU:}£Ù{ã8ã™ÄvbeS›Ì” £¶E­²€Í:¿~N_@ l ×>¨hõå\¿>çtvì¼?ùçääÍ…Ç…B0grïøB8~H‘ Îdæ|w9"£1õ÷<*"Óz›-Wk™çI–šŽ³›ËÑ_“ßÎò|ÄõRæ«Þ“w““ÇØ!5‡ @åN¼<ùþvf0ö»ƒ 燞¹t¸ĸ"¶pnO>àg¥á†ØÈC$ ÆØ}üy™&ÅŸØÃð#Z,#ÏúÁ öù=õ=ÇG¡‰"‹1#(Všâ§³É·Ë›©ÕµÇù>À I‹‘nN¦­øíà倰Ø A¡',‹Ÿ·Æ¬ÓI‹Ç›‹€6ó|į²òŸ35ûÍEÈ“B„‰¨æä@ö3©¥âXÄ¡i¤ðÌä2Í“‡TÎŒñ[2ÈêómzûujB 7¬‡Þ`snÛœíZ´}8:Ö§ì™T5–:¹è ÖÉǶ¶…üUåïVí¹Æ¡ A ÁÙ@N£/ GþþÛ½çc¸G‘¯i…ˆsQ£ñüË͇˷öLõn2“¡™-LùßãX‹ Õ~ÚàÈôîBd»¨8X®G„G¢b ‹ ¡ ñžQ…!¶'D Œ)8H†PÜh8œ}>ûx»GñoeçMþ;’4f¤yk=nŸW_>|ØíõCEí: (øæôA4¬Ó¹€ÃYð,~©îö:óGkæÀ¹_{ýêj¨«ëéo_÷8ý8þýa É¿:¾v÷t}pH³]é¦u¤¸“uªh]‚É=¹â`­ºÎjäADÃŒëûÁ°\Vñ¹¢%×ÇÇóÏ#»ÿÚ’ãdèÉF† "û²í ¯.]®^™ãä`ź>ž?'ƒhXœÀ±ó!É#1ÈT•t”\^ÝN¦¶¬˜˜t¢êÍ·¿íÍ1"õƒ¦!S­Ûˆþû¸æEÚkaæ@­ºÞ&> –CHX¼`qÿõÇó‰‡2 ÁX†¶1óáZáãëôã»{ rœý iJq•ÙkT™fåÃü—ôÿG¬t@‚lˆÑ0(¢Aå·7 EC–L„À¬þšàÛôËÕí—››ëÏ F“wçÓ‹“Ý@:R^ µ©}_®VYýR¢s‹¤^†ÿe}ÌyÈl+æË˜Î2¯ ™’váäp:>V$<:¬ÌFÃâÎGXøƒpâûˆr ¤8[lU¹‡aå8aú±Ò”æ±òÊ!çp•»0ð<ƒaPDÃB N;?£ ƒ-èîñN\T]BCͳÁ’ºv>ùª Ä¹ü°FÇ Ò£¦ »}Ÿäûr•ùÊF•É›;õ~µ:FUè+Ô÷(°¶Î…?æÕÅ]ßw ¾ê’¾‹?ýJ»Øºäk¿Êd^úŠ]»¤«p¶’æ­hãö¾÷–²G*½ç¢Å¢R¦­J™îIø Ëh¥>~ÑR Ý›ì`@t7àxà&;œFu…ÿÂ7$($Õ嵌³t¦ß¯´Þl¾ÎkCž"à<ÖUt]Ò§²½tßí±¥{˜³úµ6£n–GKÂwHÒ÷RÃóÞÿâgÛ¾Õ7™Q_ðæ;@Œ°÷dïe*×›Ks H[›žgú‚ÿéA}® %í¶ˆ §¶ endstream endobj 1571 0 obj << /Length 1311 /Filter /FlateDecode >> stream xÚÝXMs›H½ëWp„ªe2ßÀÍÞr*’X{ØuR.,Fµ8€œ•~ý6Ì`Dd rÚƒ kh^¿é~Ý ƒ­G [F¿OGï.·|HɬéÜò0ò¥´¼€"I¬idÝÙÌw¾M?ZLpÄ ƒçªÕq­—Êq©çÛïÓÙz¥’",â4)GÓÑ÷[l‘LßG>åÖl5ºû†­î}´0boý¨,W ^úXZ·£Ï#lx¾\å¿åŰ÷ºØKޤ'5ÑIZ¨ŠÓ>Ø»Kî5ž¥g—øs¡½N–½ÃP_òM2[di’®s½ðìPa«,/÷]-¤s}-±1™¯“Yñr¿^}ÊR‡û9ŽT„ÚôZ{ÜÛ kXrŠ(1,oU™ $—yÚs§“4©‚´§†ÚÀCæ*SŽˆbÇ%cûûv.—éì+þˆ!Pæ={4øRíCX ~\¿|'¬ö;á×ãñõäg'iâ6 :Æú[”{úÞdWBP,I·Æ¿ó˜(`&"_T±Îý%ô\N™p¹V¯¿k0î!.‘#ü&Þ‘ 0µ  ŒˆAc߇¡>ƒï:æÕýñÓ§ŽÚ ¼Ñ¾^ÛʼnûAÛí¥S¾ÇËÞ½—JŒŸ÷`x˜€ d`†a˜Ã÷¶'Å éëyˆrȼ_sßÄ:Œ¢Låù‘,÷sÜå¦çé¢~q3Za»·¹Ò}2ÕÃT„Ó}:Ɖ'TDÁ‚ÀŒ’LA³â—Ó³Îoxûüæ´S$ LEý™Æ¨æEo&bùŒþŸì ï8øõvGgŒGÌNzi¬„a”x’—¾¹àHÀ HJsðôA%*Û•vu±©‚«ÃÍcy> stream xÚÅXKoÛ8¾ûWè(÷¨[ÒG‚Øn¾ì¦EÀXt,¬-¥’Ünúëw(R¶d»NlgÑC"™Î7oÎ.oGƒ“sÁ…)Y0š1FJÊ N(’$¥ÁmÈF4Vá{]k÷ö®˜?–¦ª²"w g—‡_GŸÎ1æÍV–ØÕÁ‡ÑàÛ€À"ÈA)¤(ÆóÁíW¤ðíS€KT𣡜\3n™Í‚›ÁÕ?+µ$wÄFQ`ŒÃo?ÿ0óó,OÏÒ!ÁaZ~ÁÃi$t¢•^Æë @ˆE£$ÆÄ"à b)@m˜_þþxyçÕ^JÜF°²¼6/дtK¶1ÈÊ""%B:¶‹¼Êr“:ÒñT—–ôä\ÑŽ(R¢„'­‰¿`ÌQÂ;D ÂD¶4ÚôJ|ÅÄÙáäœÇ³F„ÇcD”ƒ³í»©)ÿqžÿ15õԔ úB|¸™j»íûŠPg3}oÍLc ì¼ëNSS%aöX/ƒìµ‘=êÁ{ôq‘×fÈpø/¸‘ ަ #ÃÉ"{`½šêÙÌ}È O{oÜÂ>YGÚµ,wk:oצtú-kO¿EÈ1žêªZÌý+·ïs‘{î§U–š“‰Ý`Æõæw§cáìµZ6±&œšYþàŒó×pàâMuZ“×¥ÍmÃØ®}.ü·zZÞh‡»¶½ID…Íûhr¨›¥ÖÌ Æœ—CÊC]ê¹k ˜³—KÛŠ†HDi¼«hA€dU4^™‡-0"JBeQ»x5EŠxMÉ‚üKÀTZc(À(A óÖ#›Õ’`‚˜ ‡"v³™à šô1õH¢LȽBlZIÕ‡<ëfhíCëÞGÓx™ãðògC:J¡ 'û ·À“ä¸XÚŸG?Cœ—¶e‚KC•o,vmêEikUPÅ jèÙ¼ [˜B4ÞyÄN !Õ âá³…Â9 Ï#b7ŽåšáO ²ÐSp³Ã{‘›p$àsptØé¶¿PƒÕ!2nº8àÝžwïQ<¼{AJ Ì+¸—$¹?ð¯Ý{àV÷vw»×ðøy_a7}d9‰ø8?ïÏ£­,/,X\rD}{YhgҬ锺Uª}®yƒRNˆàÜÁÜM+ÓÛº«³ˆ<– ®Úî‚Ѱ¨êƒG B•l9Ôæ@ð?óÙSuÍ£zÊÇӲȋ…Ë&M¹šÄŠIÛ·‘ÛéY;ñüXö$ù}dŠöW‚…Jï«cÜÙ¤gUq¤¿×»%œµgo®£¹®Ö)Œ¦oÛv÷zÔC¦;NöŸîVÐ ì®Ïûtû½«· m0> stream xÚÅZ[s›8~÷¯àÏÔª®\^v’Î6ÙvÛ4m҇ݶ“!6Ž=kƒpS÷×ï’0`ùÙ—#ñsô}::`çÉÁÎõàÕýàå•àN€BÏcÎýÔñ1 <ÏñCŠ<âÜOœ/.ÇÃo÷o&8â„ÁsåÝ÷éd½ˆ‡#êîïéx½Œ“"*æi";^ßþè‹Ra (wÆËÁ—oØ™@Û[#ÎsÙsépÁàÒÆÂ¹|ຟܷøé„£CŠÝE:–—Òé4 å`ë þn’«;õÖïChˆkÍm¹ cñòŠúNôSOÒϹ@~(ŒS] ™>#BP(<Õ³˜¥YºÐciÞòU<žŘV$Èáãóä©É’T¸z4™´ˆÜkKsôy¾X˜F0Æâqцˆ`üã8ÿòùè)ß§ï ±%n¢5Þ¡nÚ#å*^|2D’m¬ãÍ¢|v4ª?þ¨ºµ"Ü™_«Ed¦tQÎ×Åžž³ç‡Ò—õtúÿÔO+Í.ÒH‡ŸC¢ÓA¶¤Ù}¤«8ì–I±¶ÎWo¤ý€¸7Ÿß½Sÿ•צáÆÖüˆ)‘ú‘jD€Ýe\D𠏽Дp7Î4úW,°-W¾Ít_ž?ÖFˆ¦Xø‹Dµeq4‘sJG95…™š†°ºÏVŽ·éÑ$í§$ÍÚòÒã|1N“ó‚¸÷³r¤v§~ ÅÜÏgQ J»Bå)yc M%B¥Ly/JÌoðT%ŒõªÐý·F!92&Ü‹(Ï×Ë•4—«çnÒD£_äóIüzZò ia·½1¨#ÛøU©ê¯!ဢçÌEƒbÕˆåÞ¤ºM¦Ãhr)»­ÇåBŽr–—kX„ýz± Ç™!˜ràvH¹eš7é ô"n« „"ˆC5ó|äùÛšàcÈúA8BrïôfˆqPV$¾¨-IC”PˆáFv‹!B¢íj±¾ÂFgaÓfsò%’öõÒâF Á¤£…–„nšn¼j=ÚG3ŸMê}žÍÇ:×òVY„mSž€Â¡¨ò*¬Þk³|?Vkm¤¦~3HÎéøÙ1îJ |º—L{ah™r‚<ÌŽFrqL§ÜCŒŠtÚѤU¨u£ßûµÙÍ´]œuÓ·CȨi™´uš5;ú׬1Æ¿º:Û¿]Q? q\X½0´°¨ÎO€j߯tõ"]´ÕͪUZu»Öà~™uò®²º{UV:ÖÝ¡m_jvvžëÿ®‚Áã=Wá^Z…„#Ò£‘qt&\؉2ìh֪úá=•ô~%vsÄ.ź#¤ØÜΞ*ƳCØU@à°gNì…¡ÔÈÃyL Âá15bޏÇOScW³V5Ö Û·m{ÅØÑ»ë~tcã¸ãD-žÁŽŽ$g^/-öÃÐZ <„ö 2#1ÂäÄÌØÕ¬M‹ Ö#ŸýBìæ„Uˆ ': Ñ~òtX‡g°«!‹ è—;`4wÿŠ[ËÛŵGôôþ$Oíä^Ê"j€ŽŸȱ",8äªËþ{aè™FòƒàhÒ ‚¼„œk4@BB}üûáß‘ûr¡êl¶)òˆòIÃìÕö| «Î£ÔÓº0'»ùz<Žó|º^,6°OÇ6)3À p?wY„ý˜î…¡™& xØï†–«—»<¯"új`÷òÍ»tw²mg»f»Éöd>i×LÇ“CüžëØ.5Xõc·„"—…°ß'¤¹Ðì·ƙҊÜÛ!ÕàòÓåû»ýüv3oç·nÿ}óL×CòÂNÏvf‡‰@íEj? Íj@'x¯ÚØ÷å <ĶMΟï>\=|º¼¹~}€×nX‰mx`?¶µ¿›4´ËÒ­qšªùŸöÕ#• ÎŽb—M€à‡!Ž+â| SAœX˜0ÈÏ¡9’¾ÍâqšLæÕG ˜¾¶x¢êVgûhÌõ‘Nù>¦ñè¡×##À±¼è’“Q7Í‹ÿÍ ƒ©Џ£ñÉb£ß k…n’ñ,K“ê3ˆ²0޳ÚËÐêU«ï´±T™»«,•Úý>Ÿ˜Uê¼a9&ÚË»8VEh´ÈÓ_5ÌÖwXaFÎù¬Å|vãA»â)ôàHÀ.çéÅü:Nâ,*Ÿ’lÌ7e!·yŽ`ÆÇIÛÇÿý3Î endstream endobj 1593 0 obj << /Length 1958 /Filter /FlateDecode >> stream xÚÅZ[s›8~ϯàÑž‰U]—·¤Û¦ÛÝ6MSw:ÛËxˆcfmH 4Mý]°‘-L éìCb[ˆsû¾st$ÀέƒW'ÏÇ'Ï.¸ë(ô<æŒçŽQàyŽRägù~B`;d£!P@]gº:ùò ;3¸ö—ƒ ç^Î\9.a®¶t>œ¼?Á­V{ášÙˆ#ʆ#‚1|ÿõ6.¢¸ð|™M‡þý´NŠø+æþ”¡ÊÂõ­6õú(ò¹ã£ÐÇD(ÂΈ€r©ãýùøó뫉ö~c óeäÊ$-†ò‹©[éUW„v8°ÜM#BPÈ=%½ŒN 1áÙEèÖì€0cVa¾R'i¹:}œ#}»ÒƵ/u#o&cãõA4ä•ú•¾ïTjªÒS U¦cmtì+ÆÌâ}ˆ0ñLç³ù< «œ"Ì¿yò+þ?õÏ—ÑmÞn€÷Û XDù¢´{˜mÅ©T{váúµÏC„1gD]( jî§5ä.ÈdE¦â™úu­‡"×ù&"™IØq6‹ó©–sWlêÕx‘äêÛ¼L§ÛñûÊܦ3IçC†Ì¢|°Š¶7nÇáG±Ð߈:S•5”ßÅÓ‚JãYmÎÃΦUW-R'©¸T®Lçu 4gªip´~ñǼ‹–e\y]·tsÇ|­v̆EAÄáG’•zÒT¯†·fD²ùŽ”Ý{DümØšÞAþ Ä þÄĸµÁÝV3 Á€Cd¤ìpÄ\<˜FeËïDiƒ[òÉáL&é,™F…ž£'“A5&h9uåø\}ÞEÕè[jˆ‹ÑLÏ$ê#JõìJµ6Hš­F•§õúf&™[iU™!§è +Ö™ú%VG¹8·£/‹O ò?þ¹™µc˸w˨âA!9ý³h˜¹¸ŸHSÊù|’ÿª\·<,³Hû—Çia)ÓÝ>*»‹Uª‹ä·rèµ€f\~|óF}“pçQY![Uâj”ŠÐ>¨™¢ÈC ¦¼[Zå˜ÀÂVNNÅå°)ៜ4p¿éº€S.R÷Ò$½µ±m‹ZÝð†ZVd¶Ê~Ÿ,—:«™·i¶ŽgÖEeš¥5VpR­'×+7Œç‹HÊ… i¦çJ\¤ür)ùωª9\¢¤ƒÊëò®Ðó·JÄ…ñÁdP¹’ËZ®î»ÌR-ý,Ofñ˹ä@<-ö¯7“X÷"Ú2ÿ d{•Ogëج]±úRõ¬X¬ãhö!Rzwn—%¢\4•âC6¦õ>^„™A ã|5¤î Zk8ѹєڶ,„Fš‡¶,`ˆºÁf[ñÄ2Ä„;Ì÷Q†‡dÀl†˜«%ÈM 4N!ƒz²É4Á~ƒT€ìo§…MŽG»*¬7a„ ¿CC¥µ×°XpD ßëf…Ñ ˆ>°Æ°â¹¹^k3nªß&õý"™.ŽëÜòEV.gfîo N«*lz+6¦!q÷vŸj ÁïGÖ4U=ØfCηyº¼«^ ¡Ód=ÍÊâa;ªµ2¶®x|3K»©¶Ó´®új•5“Å[w Yµ®GßËmÌ!bmà>/@ã=¹ÕK†f—BûOP!6> Q »i´òª®Óº™jæX'+ì«[ÑH±Cûæ®Ú27pðXöé<Òs-î%CSyˆ¼ÕÒÎA#zà`G•VÖ•6ôÙÍ4ìfˆ‡uC:ñÐÜh?š‰Gû°O#¯{ÉÐT¤y4hqÅ…æ8l£"õ µ¹ŠUZ©XWjßÑ53±›v&ÖíèÄÄÍáËQD<Ú…}—†ýˆØK†&"½§¨‰„"ŒS;ª´±®ÔrÔÌÂnFØYX7¢ í'R-$<Úƒ}a±oéÙ/ÃÜú+p-Oñ(tÔÕÉ}åZìÔ¨ˆQj? ,Uœ²ŽòbtÀÃ~2TšQ—£“ÖŠ!ô4sÞGr ŸL?­ûÖ²}pÄ#÷ÃÚî%CLÄ¿²Ð 0\ö_ 83¾Á÷jH`Q8¿>ûáÄÔÛ!®ëk”éžH<_8„ê±Æì# 5è‡j/U x~¯þØ÷a¡ƒ K³[mD…þ8ž¼»˜\Ÿ_¾zy×nØ­[`?»µ?…®`GvÆs.}ÎÛÔ–lq´ûh‚÷°ˆvF/£ê#ÙžÛ@¦¦¯Öñ4Kg‰,‘õ¦dûâŒä˜л:ýä#ãÖCOHFZ ÑÆ†!£ƒ,/žÜ[cŹtþˆ·¶ª·µ`ï{n-bÉõ4U_Åi¼Ž Û;/2Ùd<ÜŠ¹qºkâ“bñþ endstream endobj 1605 0 obj << /Length 1128 /Filter /FlateDecode >> stream xÚíXKsÚH¾ó+æ(hÏS›½•8•lÅÁ†ËÆI¹d1j±äHÂï¯ßž‡&r܃-èiõ×ïî’BɇÞ£ÞÙ¥’$4ŠMHL!‰"§"FFcrH~}"BILà{–ú¹/æ:ìó8 Þ•ùâQMÖÌÊÂ0÷Þz?z y)aK™I —$ìÝ~§dŒgŸ‘&äËùH¤ ¤Á˜“aïºG½žË'pe>š‡×>Þ¥}$!Š#§èUÙh«Ó¦°³K¯½Ë9 rŸ%@¥r¯~)æ/ÎÂÌ=ê—"ŸVeQ.jGx¹ tU»-¡œ¸g3y–ɢțåyK}ªÊ©ày6Öcèª×±qÃÀ¾×RràÌk9Ô& •œ×å‘–^•…uÒF6´pŠÅȹt ¸ ûŒRüøw¨›wz’-æMý*ŠÌka‚_=ø,¸±Æ(CSf¤SÒ å__Œ¾~Ü] >vŒ ·ýqfEÚ@G2°¯@’ˆDÔ>c*oí5ЍMÌY•=Öw£àÙeÂ×´L" qܦý7J…sT*טR lÉ3n•³|“¥*’•0çªøôYšBDct¿ÄŠam˜—:(>40ް2'”H¯B†ÿ­Y«Íæ `ãt+Õ =ë:¯0”*˜=­²ô7`¡Dؘ—Ö#Êüi$*Œ\¥(º^)H¯§Ù|îŠÒóÞkGÈñHmV8ZV´ß]9“Oç_BØBçY]/­Éµ{Ï–€å>¯±*ßO¬å:o¶ÏïCNƒy™›ÇßýÖJ›a¾éÌŠç¿B†~Ò¾êÏ+mÒ9­ð½*ýY3­t6fwãu› û:ƒq³&„S`r˜ìÖè¡;;9¾«?ËX‚¿§?sÌ_µjÏ¿W)"# ,Ú+¹± )æE¸1 °ÓˆG¶dpŽ’0íÕd{.1Ê@(~4äzÍ2ƒâit­zêðYEt,|§eàv Ñ…M}=•¶(üd*7KµC¾÷ßë¶dõv+زEýÒclÙÎ!eyZ,â‹…ä¢ÔÏ«Ý,ªÂÞgÓïŒ3ßPfÌÌîd¯r˜˜RÊ=ž$ÚHcÀéW‘â*}5éS½!)är£õëÝ—?wä:ú?´›ê"†—’uÔá"Ïq,ù¬Xfp³ìÃ[ƒ¬3»Êò˜cìpe·âd$(Ü£O‰õi2|¬‰ ÿ…)„|5ÖqŒ;GI¸Ì¾ ö d8/n.>ï úQè;ƒÞ¿ ÍØŸÍ» ¬~uwyKÈUu;\8|.N ùá2¼!á ‚û91¨4.HãÙòövÀýAvïÞb(>X»°”us´&êDM8îåÿ_ø®Q§p>vÈ…¿ýA"Ž—x{cR¸R"E*ÛK,ø]è*kì À¬,fiаkþ˃¹žºØÔñ?G†ç- endstream endobj 1614 0 obj << /Length 1585 /Filter /FlateDecode >> stream xÚÍYYsÚH~çWèU-ã¹%½ÙëÄ)g³Žc³›£\Š ,ÉÚ¿~{ dÐ>ìÅ0G÷×Çt÷4Ø»÷°÷fôûttr!¸¢HJæMç^€Q(¥DIâMgÞ§1GÄŸÐ ¿ŠË؎γ‡u®Šb™¥vâìúÒÿ2}ëqηG™ž½žŽ¾Lb4Â…”{ÉÃèÓìÍ`í­‡‹Bï§Ùùàqĸ&¶ònGFøEÔ’ Ü‚¢ÂŸŒñøûÓ­*o-æóܧxœH~ž¥Ÿ1¦÷Ÿ±Àð!­…™ß;¼7o€[ ¼E&šö&Œ FΦ/¯ïœ ”Þ§‰¾Ë´ôÍ  À2Ÿ/ïí¢ð s„âÀBŠ„t<Ÿ¥»i‡éÉEH[HE€X(jk€¨Æ'omŠ&²ÞSÙß~M )‡¡&j`-Ùöƒ $„.Ѥï«7³·HRDd°!híyrÁƒ–«L(Ž 6åà€v/X¦°Ž\.”sñ›sÉí0q^Rå>Áã¸l¼>›oZç™OÄøÇr¦fv¦hß’ŸËraGîU…Êíh¦4‹ts¬ì²XÇ–ùƒ*U^h&È\8ìäpN:SE$a}¹¶@Y(ÇÓŲ°£y•&›ùu¶®Vq©Ü¢‘CœðzØ+¼^˜©2^®ÌIa`êI-®UÅ2½ß"Û!ì\Gezf™Ö’µ«±½Aƒ`+çN.­Ÿ\ú×".:zž©µJg*MVÝ>`à‡OA‚ooëØ Z÷X±ËJÃÉ‹²k g @[*Ÿáñ?Úš‚Ôxnùb¯Vv!ÍÜÞ¯ÊN$°dÜæ–©‹Óú7(Òš»Z—nÿ†©ÖãÓ¸(ªã…=w•¥ŽúiŠ=Ÿë*)w׿j ­²D}›ôY¦ÑÛß>á@Å©þ4W*-­ÁÓ²wG¹ÈU<»-÷­-&r@üÖÁC™øÓúZÙ Æ,ŒkŸòqœÛâPj'øôå Ä ¼ìÉA Bh„£&ýÇ4t¾žXKµ솄&ˆ#aR ¿ÎQ©µ2D)PH†am˜ÝìK0¤ͲJ üŒe—©‰»lA[:ØɶÁ $u¹Þ¶/è"Ng+U_O×™¹'.Vg.¬ãÃ@QÆiâ~Áéž[?ƒâ§):²qBÍ#m×™€D)lC¢á’KÄpø¢(TD/9¤ pE•²ªÜã‘GòìõÈ6×næØã›ÇèõÍ6ÿóçÊö²¼©7ì ®:îUª6'п;÷®Ï 1Èï§Ñ ïÖœ=e=X…,²Ú¼¬œkÒ7$¾xU©—C=BÄäÞçÓ©[ÏK8Œ†½Y<äPÑòaq­@Ó QÀêÁÇ»÷ô87 =’o×¹áq§Ÿl¾jȶ˜¨Ê¦š­’bé¼Z­w!²H aÈ q×BtB2Ðʃh8+Ëq9ÌÊ •À-`[¸1ò…âñÙå»=¦>Žy¿©ÛÜ;Iö§¹{®’³EkS3?o⃡íšHPPñ ¢áL,`–ƒÒU Ê)ŠlÝãkŸ@±}vsöçí+ÇŸáVŠn¬Ü°yˆw<‚£($í.+£r»·C—ÀAv_öÏÜÊѶ*s,®þz÷®aV?Èáí™;¸xµœm½—;Ïåg¼ò`Uîz8敇Ө3Þ/&R‰”¸NÁu®@³¥‰Ýíì¹éÖtÌE)â ~!ÂÜ=üÌ+±stßsmâ(p _5ŸÑqV”G#á‘кH»ÊJu¤Þ§«Çnãà1My–f•óPã›à‡=£þþE=ÛnŽ #¤ˆQoe‹¦xUd ¾Õ}­Ù Œ0eî«lw_«µË ǵ[ÅáíÖ†ã]Vñ¿ï²:`׺áQì‡J¨ƒ_€×ìYª=VÆ@Iü¥+‰À´C´;“—)\pˆÏOÚ¡Uç¾|83 oú´Üj·½Ø¿C(9à/„ú¯‰huH+4 $¥Ë€oôË+nªWÓs7üUf ÜÇ{í×cµñ_ãŽã” endstream endobj 1526 0 obj << /Type /ObjStm /N 100 /First 975 /Length 1845 /Filter /FlateDecode >> stream xÚíZßo7 ~÷_¡ÇíE%‘¢À¶¢Û€ è–bØœ»bCÜ¥Öí¯ßGÙNúÚžK±=$æÉßQù‘¢îLƒ Ž8ª£TM(.J†ÈeüAˆ.1!9ŽI!8q1V'Ô Ù ³ ìJ#¨©®ä6¢®j1*tAÂ%)&älÚìÆh—z£!r»3›¤f\NkÕøg&V› C*M]†µµˆÛbhàlÖ‘±é4-±V3´DXsmбXަFD)f'c¬Ôˆ)7ÔØÆR±Éê”0 $±1Î.1.5§1¤(Í€äRNfÜš$Øä¦†¤6ó Aª6V€Ó¶d).‡X‘£M3 S—) —©ÍZ0– SDeHܦP—9غa{–µbHX­§Ù¢L”›§ñZÌ]á7X%HÍQ¸ 1‚£RȤùÒ1SÓV qƒA›¨ù€F›¿*¤dDWÁHÅŽµ¹šÔâ£ ŽªÉ âhß‚kð…}k¬+ V'Í`Ì#"ƒS¥´EÀORAØ)k2*è¹&#ˆW@ÆYdJ‚ÁŒeB|íGÙ­ÅÕ$ÜjA…Å’¶±äŠñ„ øc¸WáHä*oSDW£¶1¤E¶Ha}®Jj÷WáHlI£-5ØÊdÖ`+°O[x"JÆMDQÁüу£ñãåùÊ=xàÆÁK£op?âá3iseOêú ŽDòm‘H ,a{[¶ÛÂö ¾3¦ÙÕÇ£ñ“‹åì¤[¹S7~òè±?íÞ¬Üó¾2KžþõªÃ“Ýhü¬êÎW¯-‡›¶ÑøÇîõòòbÖÙX¬ë±ï»ùËÉ—Ë7îÔ@§7†×L¾êsÌ7¹€+ üççK(=].3ëÙ`4>¹œ®Úõw/Ï¿\^Ì»‹6Gx>þfüíø«SjfÖ õà=HéÉ\@êL½ õEsñ‰½|ºtãGî³?&«¿_¾:«¿žMBW4ä¼ ÚM˜&š§Ê²¨ói ³´ú¹9ocæ#wÚªosðÏ¿a#Áë5¼OØÐ“/ÜŸ¨¯W—³ÕŸ,«?áÙŸº‹×/—çßž/–gg'{¹™ÉÍ´ÏÝÕg˜4 LÙSF‡ãS¥a`ðÞ„ô)44i†n17O!ÝO¡\J!´'{)„þiB ÒF;È%Ôhìåos©Ø§ÞÃ\bEeFÐ+ã9_}¨¹×ÎËËWgg0÷Ì}1‰óE4ót’çM×9ÈÓ’âº|‰_¼bg J½a«Xàç kgqÖua^(͸뤫»Y 2‰ –½R°eó R° Þfw†q0r8ÏT?é„eÙOXÎ7JØ]o1‡]ðGÛ¥0SòÖ`ãô…bŸ† àÊúš5åhqvã}ã(â´E¡[—]œÖÕ–Óñ«m‰Å“¼­¶%e³{Xm ÁeáªÚ–ˆ&¿Ú6J< ovÁÍ›0S@+3PsN©ycP±;öIöHiR¨'MôÖi"wÐ×Kˆ>ç·}½ V1ñÑϵ%@¸]ðö¨ZÄÛƒ¡a`;e 8£«‰BÃÀIØ•aàÍÇáÛöu¶&ùQžÉ”žÎºÜ¾³–º)ñeÛYùÖúµ™(†>Qº2“fß¿ ‰@ö’‹V³=d÷œi؆ԥŽ;­‰çyÂu)‹i(sœUgûõᆺÔ6¤°Ú­Þ³uýš×Þç^=à(ÑÇÞgY}`œXBÖg«»q¨e¿@T¾u'_åì‚·aªÈ¡œ†³ U† E¥F=¼9·Fy}È9 U¿q`´§9×›s-{•»¦MÁ®ù¿ÜœœýpNÙÔÂBöÀMï¦ê!͹Òœ÷€3zS¡ R!ܤb]¯Q×ë×W, ¼—öžî¶‰¡Û–Fõ“ìË“¬ÁgD7RööònÁç°.a*séBŽi¶˜GÕ ‘fÓyítN*óšÞÍ {m;83®?vŠè¿ïÑÎ=õ½JëG‹± SÂéY˧uŒ°70{9Gñ¶9g¯Ò[ÎÙ›ô·‚nÚb6«ýÿiÒ>M:ÞîŠ4)WÚ^;Y,Bì2k–9Ok¥4ãÉ4r–HuŽ~x3Ø/…¶‡7cÅ{x|#ûÉ–d垀¬½"¾ÚEÈÀñnvJì"»àõW}`´QÐ<Œƒiˆq8†àµï¥oØX`?*»ÿn]y{ endstream endobj 1621 0 obj << /Length 863 /Filter /FlateDecode >> stream xÚ•UKsÓ:ÞçWh)ÏÔB²%ÛÙ0áQ˜2СCîâ^`ÕVˆG –ÜR~ý=Ö#MJ6¬$çw¾#QôQôvñr½xöFpÔeU•h½A5%MU¡zYŠ¡u‡>cγ¯ëw¨œpV‚—~0Ý4¨,/ê¿6í´SÚI×=+/.׋Ÿ º±ƒÏ¦!MÁQ»[|þJQwï%å²A÷^s‡¸(‰àsŒ}ZÜ,èqž¼>“gÅM‰®:eÛ1Ë™ÀýÞ§’E×ÛÞÎ;†7“nåÊ:y›½Ýª¨"ÃÝÍ‹ŒÁÍ:­²ÌH–—Euä¯×³ù]Vl¿7–Öš¶<ô÷¿[9v÷$(G•|@ºUáÞ™¸nÕIè ߊrÆÈRˆP¯Ó¦¢Æ¾˜i³ÉJŠÕhç0sÊe¯6A,ÂÆDı*Þ4w½ë} pn¥m\ô5[³Ûg Ê©.HìÔ¶èf†‡ŒQŠ/@^ù2t }t}Ô8Ý÷)+«b¤isŠr³qÔÎq+­Ï¨ñ _%¬{9BVXîòÙúÙ›¢FK`RQÍLZ6„6,ÑúyÐ8å©ù2)ØÝûo·²Ñþá3…n+]Øù"}&Qà{ +#>÷œQAšå‡qˆÔ}©|×̨’»äæ«#ç-tRuI9Z=aHvsÝ“uéþÀ×x«Tô|Ò q[Î)v Ü»^†ÍÏßWºw$õÂW ¦yKzqM Z'¿PZž™“åcæ.B$ëv˜:Ož’¼†ì¬_½Üç”3†õ„<Þú0S@.ž8 š7ÿ}{ýÏÇ÷W¯âð_qä'o€ƒQ¹iö.°öÐx%·5“ ‡éúÍÜ[hxAXÓœRöг'¥`ñoÆ€€*²~5]]˜e9}§kå¶£’Ý'â>1Ÿÿ¤ô™œû›„ ´dó5¥¯³"E]qÏ`ø H¸ ¸ô…¼UZò0@¾ò‡ôizD R¨Gé§9þeÜM endstream endobj 1627 0 obj << /Length 2081 /Filter /FlateDecode >> stream xÚ½šÝs›FÀßýWðˆfêË}Ó»±“ºõWl¹™&íh°„-¦@q“¿¾{ÜA 9€§/°»·÷»Ý½;aëÑÂÖûƒ_¦oÞ n¹È“’YÓËÁÈ•Òr<Š$±¦ ë³Í™RǵOüÜ×wo“Õ: ²,LbÝp|}6ù{ú›Å9CÂa \*TëÁéôàËFl‘Jƒë"—rk¾:øü7¶ðì7 #æ¹ÖSñæÊâ„q%,²n>`c5FT¨[u1}pºú r¹éÄõ„rÛOýUé„;+,+EvZê\÷XÈF–•…¯,ƒ ,…å0a"öÉ€·a”1"´K„åK¨T.q¢Ôr`tæh„q{l&ˆ :X¥S‚$¨×Tš4j5ت–7ÔrIW6ÕÞÖY]úñ" ôý_XàuÆ Š¢!Oô5Yû_6æ¥0Îr?ž›ÿàk}“Õ….`n€0ÒîŸ gˆOÛ41˜3d$‘£d")G\¾ ‘ÔCÄý"ªì$²®tíC8À¶¿ÚÇå0åÝ\Ö•_O8¨6¨È”iš& ÛIÚäl7Y½ÍkS"èØX×_ÆFréräyRûì&È7©šuÔµ¿Nˆ°ýh¼Í¥#aðIŸ|óÊ2ôÜ‘zûR pÓN]%0˜RJäzTûåçÙÕïmH(HBž¨·Á0eQñ–Þw›xžWq0Päþ«þóM”¡r3ŸÅ›(ú°cMçöq‘ÓÅS1”© ²ûÉCÞ|rïg UÕØ:$yBh;æÛ5IÖ úfjÝiš§ŸkYM— 2à±60 ï¶/C7J†Ž $„ûb„ ÂÛ  ÈQ²8|X0€îäîúüìíñ„PlOO÷8̆kI£°nÃ_3¥v V.) Ñ¢î0É|mAV&ó:¶a–‡ñc&wFè’¤Þ]oS"<EÒ(†$ WìŽËÃR€W<% D«@º.:¾9¾¸ÝCÑ0ýÝÕô÷„È\/ïÎÏ›p¬‚Õ}YK&úZ+1_C½þ:¡*‡…{Qï>·‡žÂÄg” ƒ–€ ˆcG€=ý‰[ásyuûþÌ~ý¸‡ža껓`Mýe²+hT«…ؼ’©HóÔ‘¡îƒ*ö°Þ¸WlDa¶Ü—¡zw§=¨ ‚ˆ‘eÑ( ái¯ŽŠ+à‡+YªLc-2.Nn&Ûìæc |4¬(ð " ðͬá?à%,¢QÕFå'»ÓM/Vúw­5ÎJ„Ät+ãdV®ô…®0ÄøNT”3˜g  H§MÊÙåítfJš©NKjÚ¾ýu:ƒŒê&§nU‰ÁÖ&Äsæ#3þæÑksÓ·_í!w¸²qØŒ’a°‘ q,Fæ Â@–‹(5pfçW ‘³‹Ó‹=” ³¡“º —InÆ5N6KSx„q\.ÁZ‘çD¨w§Ûã"(·'Ã0Ä]H1#R#¢Ü¢”9Ï ©»ËÛ»ëë«…Ñôôdöîbº¤a†tƒT7¤ûÍz­€áØÎ;6¥ÒàËÆ¿¤Ë“ÉòåêgÝ¸ÉªŠ¦AÒNNz÷©=Æ Bìñ2'£dNGûKå1ˆG9IÐD›ª)ƒLé¥fË+ròÚá¦o‡Û0†\o\QØ>ÒÁdUpÝpGU ªÑþÏ—i•«™0f5ü<—Ê­´¼šïc‡²u&jŠ| Á è [T÷æÌ8ЇL~”%#|ëG¥:î@!èU¿²@Q’#ÆØþò}:‘ØüTM×EÑ«§Øœc«Sëê°YωôÑLŽ›÷ú¤Õ%$Ä[Ðñ€AÅÉËà<ýtv=3¿Ø¨:c}>” 7Œ!0Im(_$•RݬTïPkI‚8hnDŸßÍç³iCÝ›w.­Ù(Ä\Qn´>oÆz¼ö’Wœƒàæ/ ¶:Kòy¤´5RPä¸ C›M¼»8ŒaNùQø]y;h úÁì|×­=åáB‰G‹ ››*g­eà:«ÔÝ3» {f0ã`ž›Ç¾¾Tɤø$MVúuó´¹ÕÈŠ¡+w !jã±øQ”@HŒxºŠ2M8ëlÊ ±Ïôj¯²nA=«˜éßqžÖôÞâ§*³ÄÍP¿6oŸÂ(2ïùÿ(»Œ×ב?7y¾ËÁà¯\Ù¨4*HYˆºoU{¶ô ›$ m÷n˜Ã£¢:€¶0Öm~\þŸ©ÂÍ:7ï?+UÕö‘Ÿe›U1Ä™þ®˜ðÅÛGÄ Sãåbh·žë<œè~ØåãjõôçÊ8»¬&ŽRpy®â¼YBåË4ð·¾Ö»õùKgäB Ü/¡–? “¹$o¤N$¥éÇû R¿Z7 à$)úíQ…=;ˆ·Mü‹&ÙD endstream endobj 1633 0 obj << /Length 973 /Filter /FlateDecode >> stream xÚÅWËrÛ6Ýë+°$Bñ¸«;­3Iĉ•M“L‡!!›S‰Tøp«¿Ï Ê¢$+¥˜™l‰Ï}œs/.ºG½˜ý¶˜ýr-28RŠ£Åi‚RHG +Š)ú~^¼B\ ,(‡÷Ú§¯‹´YÙpδ ~/’fmó:®³"w›g,f_göDw˜Æ`ÃJÖ³Ÿ Já¿Wˆ`ôo»s„äX gc…îfïfÄûI0“î«[¼×ú”׊b#¼Û·!A\Æk[Û2¤4¨ZÏzÈ“‚yë9°äjçáÆ ˜(‰40¡òì˜Jê!º”HAJ˜r)13†´àXsÝe$;Á %sÉ.6©÷X DcÉ¢¡ÑÊVÕ ³œa*.µ*V¹Áœê¡Õ;°ê´ØÊó!ÎÓ^ªŸˆ$›"Ë&ÚuÑ­Å&þÚøMY^Õqžø_ðv÷¥ÚMã:0z@§„_ܱ˜ 6C' r<Æÿ,7ÁkBuoë¦t¹a&x © âUc¿_r*ÉkzÎ;U­"þ|„Ó0º’SZaÍ&Êß¹P†b!X—–wýýöÏSú×XŒ/3;Ô?èÞµÕÙë&OêVmÈIðŸû°ISÛ^ÎM’€¢—Íjµ=¡b¨PÄhÙÉ&2< Ã3¬ŽÌ÷Bæ-že8’PI6ÑÁס!ÁÕË›34_dû4ÍûƇ4§™g6/ê=ŠïgÙë×13€  ŸÆî$ Ï®0Xði¬5fP@ Np CQOïmHðûþêõ݆/³ÏÉÞ‘½£xßO„pgö@x£ý,Öž±ÝÉå×7nnü¹æÏ¹µ]éϼbÙ­›#Ä냷aP€ˆCæºxvF>£ƒ>æ Ÿ¨Ÿñ#K 'æþ¤»-mRäi¶vw`~= Š1HšSƒ‰Ä›"·ÃW~81÷‚À²›n9 Šªþiž0nz„ÚŽ5îµý6‡“§›±|¿ÚæÉCYäEã•ØjЖOcW/Ýú¡ërÐû§›²pCÈc–Ú_ ÃŒÊ~–´ÝX¯ªbbšÛÛ…¦Kúž=h=´¿oaÎ)!$HíWˆÍ}ÓÕíË€ 9—X¯Î_S[%Pç|¶yÊËâÁVv˜0Ÿ©jc“l¹íÓjŸlu»ÝØÐ7‘‡ŠíH&G¤Úù —¥ûùq—ÿT'ó{n€”NÇ\*ûK¯ÂL+Ñ6S¸ÚJx" Êçñ…Ím6îmÝmç©í½£)°ùáû ˆNm‚ endstream endobj 1648 0 obj << /Length 1005 /Filter /FlateDecode >> stream xÚÍV[oÛ6~÷¯°ùÁ aXæ´†uX¿¥… Ê´-L–‰Zšüú^¤Ú®ëdذõÅ¢És¾såwˆ£u„£ë ߟ“‹·‚G$A"•$Z¬"…Q"e$•@‚Êh±Œîãù&ßÝNgT%±˜~Xüâ´(E 'Ôjáh&1’4 UÞu^üª)ú­®MnʦU E)!bPµæS¯*™ÎÆ8¾ÉÍbÓê|™Ýy¨;Óö…ñë[½šëV×…a”JÉ*cHáQï?Zñª,¼ú¥1mùqJqÜÝYý1'o¹Ú"©DE3V)âÑÞS*t0ü’¨µìâözÝÏ„±àײ3ÙâÈ ÃQ VlŽW‘dˆ3 'cv"&…¸âƒLÑlw™Ùd`ŸóM±ŒfrEØWîöuW®k½ôI*ks K‘ nÔ6­ý6 îœõ$h¾Ê“ñ¥ß:|£§ ÇŸ²Sþ(…“i©šÂ–öóyñzÞþív©¿±ÒŽýïÅ žì—÷Ø”#F\~‚§^m±Ñ>êå¹­•µÝj3›2°Vg`‹ˆxä›Ç)üËÃéZ×À†à{n†„®Úf;€è}èªj¬êcY¯ý6ô­ô÷‡yY&…or>{ùn<æbè,4zÈ ê6%d3† #XÀÞs¹›2 Ë‹².ª~©/ä—}?2 5>¥èø˜ºÒ&/«­®tW´åîó“ì !±ã¡‡*Ý\N ´ñÂò‰ÓžßÎ%÷Ë"Üî>ÐáÈ«{Ú·®ìÞ#ê§¥u Ofœ$@Ö–ƒ9I8˜ÄÅmƒI¥î¼ø27¹_µºû–e­”iüîIíA³ò_G×Μî:G©n;Äh—«¾.¬^^•æ PpŒî¼ì!0ûÄ0£ïç}e´°®Øoß3àÍüÝåŒ$ÔÿûÍÍoᶺ!‰LIkÔþÍbò0!¡SÂs]„‰ŠíäþŽ–pŽ!”øè·ŠœÁºŠî&7ãÓ_"ª$ß{ùs¤ Œ{mÝç!çèìix×»©ý´¶ ëúØÅ¿…` endstream endobj 1672 0 obj << /Length 929 /Filter /FlateDecode >> stream xÚVÛn›J}÷WŒt^àÁ“a®UJÝ´R¥#5±ßÒÊÂöØFÂÂÐ\¾þlÆßBš—`سö^k߆  "èÛèóltõUpâHJ†fk¤¥D*¢Xh¶Bý_³ïˆÉ‡ŠÁ¹æí$ËÒSz_òeµÓ™‰M’gµíèv6ú= À” `†8¤-w£‡_­àÛwD0‹BôÔXî ^»HÑtt7"a+Énœq L1õÇ!ÄûOïºhã‹M|&Òöi„#vqÐB&Yb’8ÿñ)ñâ´Ò@ ¤à ºÊTIf$Ÿ,àîuR,%ŸäÙ:Ù̧××{Ä74®¡8E´/zí3p]¥¦UÞäö?y&§É±:Ò¨KÎéõ˜§~ ¼—,ßAD˜…ƒ˜\ê­¾ Þ›}C¨*õÊ>5”ó6““û‰äöq§Ë*m‰ý1ã¼+S…Ó¯ä6¸ý|ÝÞ0±¡ª°V•Bÿ$„饙'Ù°l3zV“B¯Ó.ÔIM¸…ºwŽ-“EÒ>äÅÊUõB·Òè½6Õ¹ D¯öù‘ye†UÇ%öX—Êc€ñÚèâ‚ âß+Ñò΋w˜ëøÎ¥øh¯ª6Û¶e±ê¼ã–2Û¤uPx3 rR?Õ!n¿nt’Ù·f‘ïˆîB§i^}J²} ¤©¾nvƒê(X… T'˜pjÃþI©è[=Œ…^üø˜&ˆCYCãß±Áå6Ù¹_~à™×äÑgö<^%Ù2­VúªÅ«WQ±iwÒ}ìYÃæÌ¶çÕn3Dœ±‹• Ð}‡¸1q÷:Õe ±Í§–ïÔ{ï!“ ›.t¶|[P2’JWw +ÚÖÝ?mØÖ’ªŽ%lGÛ²]ÀÿžÀRXñÈXv–ÙW°ŠgøéD7±3ö›âGµ¨¹@*,·cŠdQïÃÊèò@Â^y;»5z.Ùe²É\¥¹«!h¬³™l ¶POó²ÍD ßß;Á!µŠñËQ¼ëÏlW·®Þ! 7 áåÉÊæ‘N¦¨Ä!£.Sõ$<ÔÞ sÅÝ1 ÒÌGáev!G {3"‡Å[eG)º¬T^·'\tìêûë”üµßvä9>uO|äšê®§S%yÓ_‚co`\H€lH}«èÛðlºæÅ]Kë±ùü²©ç‰§û"AŒÿˆIív endstream endobj 1698 0 obj << /Length 922 /Filter /FlateDecode >> stream xÚ­VÛnÛ8}÷Wè‹Ô I‘º‹Ån‘¦@›ÚoÙÂP%Æ& ‹ŠD5m¾~I‘”%WÈ&mŸL™3gfç†À ðnõf»º¸f¤0‹ãlï@‚`Ç ÉŒ1Ø–à6`†k’¤ÁÍã†wõ?a„‚¼ÍÝnc¯6ªí eÏŸø]ˆQÀ[^\ÿ•Ř4 ?o߯ÞnW÷+¬m#€G[i SBAq\Ý~F Ôwï‚Q–‚‡Aò(‹ £‘>W`³ºY¡3ÿ1‚ Ëâi1†èAq¸Æ¡àŠ«\T¼´¾^ñ®hE£tPÆ¿‹kšLÈ@`idíÈsówˆ ¶¢qQ[:ì‡lòûžÛs™«Üž:%[ÃF¾çÆ€$L ¾ü«4h×X༴¶Ñy}{«Ùí[‡^ÈZÇP; g¨‘¢V¼µJÎî–@„:¸Ûiʵ,´|ÌÉÕÞSÍo:á•8^?ðãoþj ÿJý‘kwO ÏÒíŒáp|ªÃÃÎù¶3nYõ„f  êØ×æec­\ÉzoOš{ów·¹¼\?ýéS]‹jLáØ*{÷vÆ–½Jä•x~½L°Ö¡(P½Ë¢¼v¨%/ä±iô2YºTÒlJ–çxý:¯þŸ¥¯R”V*%)œALR-<ý‹P´•A„/3ãsnF䚤S6§sV;§zñy?­&ŸÍ²W(}þšª’–þª|.[‘cKÊáùŸ™XË)´òT}”ÊùÞ´²Ðz¾šOoþT>X*-ÏËi©>3pê—*¯v¢~"æÄêõõr9Í)˜Á-FO-ÜvèF|ÆÁ©¢š^'CÅë½ïRbd`l/+6c@çÒo¥`Ä{ ZéW¢þþàÇϬëÝ™‘-ÛÐN“a,+äîvÏkn§—òït×Ê£áS誒Fõal…ºƒŠ_cßÏk€c˜¤‰fCB‰k5„°¹Ôíš±8È›¦ÅC7L¤û\Áî Žî+ÄÚ/3‹#{§¢.ª¾äÏlíÞ­Ÿ rpÒ9̬ÚYG`†1º–÷•ÆEÙdÒè§–!Ÿq™Îâ'jDõnãð_¹¬$I&’z2ýÈõÞ?°˜h'`ã´1ž!ÑDï[Ø þ9caiAcL€_²Ÿù½,†dÈÎq-£ Æúg0üÎd×)³¾„º6¾ûµÁúíûÞðúÜÅÿÎ$Õ‹ endstream endobj 1705 0 obj << /Length 901 /Filter /FlateDecode >> stream xÚ½WMSÛ0½ûWèhÏ4B²-Ûé©”ÚÎtJN¥ŒGØJ¢©í¤¶\ ¿¾ú²qBa¸`£hwß{«Ý•˜ΜÏSç蔄 ã( Àtb“(ñ؇Ó\¹y×Óï ˆ0Lâ@ÚéÕ“‚67òãÄ,³¶d• ‚/+µ×ù2uþ:XnE÷.“&~²Ò¹ºF —¿}ãÜê%II¨BàÒ¹pг0%&Ôáo£ -ŒEêaw‘×[6æ)ÿŒ°Çä€&¼f™JÆ¡xrk ñTûÑàW ¡‚žzr—µL qK*Æ%M%¦tVŠ×‰dA´UÃçËÍÁàUç퉰ٲ\¥… ü¯x;Ãf ZW.æJ+L\.å{2/é]:Ó¹’( „?Í»jШè·é ÍTåþiWoýYú X7Œ™¤?K›õ{jß[ª-XÏcx[xµj…ª¸fŠEÝ,–EþžÔìošU€80üÛÒ¿õä§\H Z…ô(ÂÆd©é1êÆGèC$2C†ËúA¹&(/:Öd5_u³rkI^œ³›‹c˃0]ó•±¾dM£,õ?ß*.8-øÚL^½¶’&§ -™`µ.]ås0Ù>å €é.«»é‚Ûq®Ï¡üµÍD[3[·K9Þyew趬ßf}_×òZ8¼š›»«1 ¡á»©z¬›ouûÁÊf}Oúnƒ-µÃ>¦ÃªöÚuÖ£Ó˜€Žc„‡ÖÄX?œŸHY«î¥ß.Ö6ç´¦e“^~ü¸Ëõvji8‘Ûkéã(g™}ísA7ú³›dˆ®>†¤?$Y˜Ùõ½p=U{Ùõ>wò›Äz6S‡äŸ'[+Ì6±4Ïñ¡ ËPÀÁ¥`»š÷“¶7’eýø""ÛÀü‡÷óŸ°ßT0ÕK>Ø‚é×L›‘i5og¿ºÂîŠè€­ZÏ;±G´¡fa§Yw)|™h¤í‰Kå͆*†m)ºÊظëよü’o‹î›"‚~… RHBHäJH`Y ÏXÅj™ Û»õT¾ïúNÃý\éë²jãrY’ endstream endobj 1618 0 obj << /Type /ObjStm /N 100 /First 967 /Length 2552 /Filter /FlateDecode >> stream xÚÅZ]o¹ }÷¯˜Çöe®>HQ‚v³H[` l7yh7 F“5šÚ©íÛüúÊžÀŽ{nrݾؚuDR䡿úäÃàŸþp°A ^‡èú4DÍ6ˆÇhÄõ·ò¥Ëè ÞÞŠnÐŽ|ÈiðÎÉì¹»RÍi—Âe µ >2ÙO£ö{x•ˆðª r¿…·8v1‘è‘O„{â Oº¬6EÔ!8{?‘‚Ï’ü¢·­­§8„”í ›''ÓLŒSK!¼ƒ@6Ó»$1&›•ñœée÷{£n,\b]ýÞåÜïa†Ô-Ȱi›!Q`X(¶Qêb˜"{ÌŠ%Å̹ù ¯Uü@ÎÛ ÉgCžx èÍN) DÝÄIJ°tRDŒt`ì)ÖÄ0¦HM‘F Ô0ÜÜ@>f»ESèxŒ+ÂÂ*LÀ"B‰“ïA}_£‡zAEÄ‹yÌÁEðŸ™j8ÇOsw°³ö§°=”eL€ @ì˜Âq‡Èé:£l> ¼j“‹`„ûpÓ‡ô[62ˆˆ ,Á"@ 9ŠÌߥ0˜¥ad#&MÙÂÉÙ‹9›,–H{¶ zP☑¼Å–ik‚ÝF~øHrìkâ!;Ï6JCö=(FèO±›`I)öU4{«ÙænõØbÎ4™íXâ ðÆÑ³gG»g§—ógÃî.ÃËnøbÛ N¹º2Ûò®®ˆÉ­’ðŽÈúHl_ÂP×W˜6†U ö¸÷ˆ»úÝÏçgõe»^»Ÿ|1ì^µß/‡7Gxd¸^ýç}Ãò¶ížc;½¼°dеí~igÎk»¸J9ýÞ_Û|R~8û}xmXy´TÉYß`¾r%HÚ¡¯ý8¼îy¬ƒüû?~…›ÆŒ ‹ ßž~x÷îª/Xë– l§rÕrwÕH‹_³êÝ÷§§gPúú*3¬ž™mðŒ.y´{ùaºì×?œþóh÷ÃÙùÜÎûdîÍîÏ»¿ìž¿öýÂðU¬Ì d‘ °z-ª½Ò¨ õ}·àËa÷§³Wgð‡—Ë'ïóoÇÅ5QG´øÜ û¢4)§%ÏSv5.NÿhV<Lêˆü‹ “a[d-²sÄ]¹æÛó³ïöW }[¼4§ÄS¡9#§Ìž'Afd®F7±^…YÚfw„Åua?:8k“p‚ÁýVÍ(Þ#¹­ÂƈŒ³ek|–n¥•ÛùáÖ&º¹mÊ?_½¥b¼»¥¢ÿæDþ)ü¨‡ïvy”°QsÌyÚ(LqÌŽþWþj/^ÅÄm/RÚË‹‰óÄóubŒz= ·ü:ë`Í¢D뀙N±v$äS5ÂA:2*=ø6a¾7Q]\ž¨—¯~;oeþéäâòøøåáòæŠ8$ÝÀÊ4úÀF>&PÛ˜Âè;Í=¯ƒ”¾Pp>¸ò¶ãŒ[õù©Ovõž ýöŒìž¢{B¯%ŸŠ±GqÎ1o/ÆÝ=ºŸ×}øü=Âɲ]–ÂXϽ±úµ²1\aVìJ¿Q3xÿè[^ˆ þHêi£b‚µEóc˜=’“}D ·bŽ’ÆH©XYÿJé~+j”ðqkhx4d!mV”ż?™èÃØ!ȼ8¾“ìsõ7g„õÜ2¯ç–y=·Ì+ÏÏ+ÏÏ+ÏÏ+ÏÏ+ÏÏ뉨®'¢ºjÖU³®šuլךíûÿõÀ?Á©D…þ1#j”Ø1v ›>æ”K«®ÒìZÊST?ƒ:N/´ç= #³£ªð l@s‘CýŒ’ÁÑå_˜…–)Å*©¡Ápi™çK ²„ªe®?÷•à‘Ìì‡è,ÀÛ%b?åM&¦Z[cN4‰¶Tj^œ–6˼p ËAI/õ v&<€`µcMB{šX&ç…[õhÝj‘Š.Â!tœ–@‡71Ø[°|–¸×EåÒ ›lìp¿:…9ƒµkli!ŠH+ÞѲ²J骓¸Fœ5Ç£ý²‘ÝR‘ˆêTÑihÑ*´ð‚f0d×póÛl†û÷Q¶ÓLT˜negÖ÷{â®Ñô±Îvô‹CõŒäªk2Ñ4¶‘ãlœÆýwNÞ¸bHÿû¦ ×Zlžôò ýæ²ÔºL” À»Å…ðæý û™Ok l?•ÝÞ{±øD-§¦®A¨SetЕçZ#{ÉO`n¾:õèÖ,L’mJ/ûæ6Wn~’eF„c«`%uV?¹¦È/ñ ìrÂö;3O1ÜXß?¼ÕÙ?!A{W9J¨©J™âÔj}ÜÈÑl?%·Uû¡…Ü»*Ò´ 3£IŒ©€b/UQyÑø)`ûÔÏWPÇl°(HÚw,ʨÛ0¬L ž[œ•)»ÒÈ-Ÿ¾Žü”»!{ endstream endobj 1729 0 obj << /Length 981 /Filter /FlateDecode >> stream xÚµVÛnÛ8}÷WðQl–ÔÝ}Ûb7)jd±®]Ø4‰¶…H”CIuâ¯ïð"Çv×Ú‘‘gÏ ‡$h‰º|˜Þ]…Jð8Š|4_ ˜à$ŠP<öpDÑôK4Lä—ü#ŠÉÞ°‡CwD !Ϊ[,*&ÒU.5%ÃE.-©Ïׇ(Æã˜PIÐȧ87mºýh>æ2[CÝŽ"ðð¢“Õèýû#§ï®‚x4xðÐÀòýûY°ªÈŒšµìfmo³Ì`ÅYÎec`´Ø€Ëõ2lÒ{×#@¥ÍÖ¬>·íN4ÅRðÜÕ[,D뾺W@ÞG=»UÈ•K]i“§ç¤¬Ün½)¶. ®>CcªT†uM¿ˆ›–™f]«™“„VÅ…i½Ó“a2Òh2ô½É0‚!õ’É ÷%Œ­„…Xw-l3mWRylVu™ŸQ2|«’ûöÀO zBOì9°’›¥z¨tPmVWkiÜC£”‚•ß‹Œ#~ܳf`gôQ€u´•›ú—lLßø/Jƒï®ª„D.ð¨S,z^ügØ~;¿Ô‘ü±ã%QX^%pï˜x}”"”âqhc¶SÀ¦Îô/—BŽÍ·ÅÚ6EYšž¬»Ö¦’æ§m½{m­mFÖ‹v£h3É/LšÄ&MÅžÒ…JòZ>4¿3Y4ð è™$¹aO…9@•ÙÎ.˜°#Xo‘>:¡Sm«Ü+[!ŽÄÉ: U¾„fv&±Ç”3añD}ÂW!–'½]XËÆVSˆQš‰öÃ=üËŽáŒï*Skê·ÒQ[©„êß/7é5ãËÕp'}Ë ãÁÄW,EÓ/þFˆ'ŽÃöÈZHúvjլīKŦĪݴ²úSw‡Á¾ôö€WgÕÇéXÜÒ‰é` $ïÆŒG¦ 'w¦óÓ-4Mºö:(ºúT V6‡ÕâÔU{Þ´×[ßfé=ËÈC·~«àÙŠÉ××È;Ô3I}_ØÝ«äâe~k»“<ûjKC-Ôe'•æðv©E¿:$ ·1™þŸÎ¾¦ÆµOÐ\{‘rMáêEPоÊ?A0ÆAôsz&ÊU^èÁÛìÔË3 1ñé[žýƒ3Â^{Î ÄQd þ5\²]ÕÔ±¶™T«Dzz^ªØ:ˆG¦» Ó endstream endobj 1743 0 obj << /Length 1029 /Filter /FlateDecode >> stream xÚ½W[o›J~÷¯ØGŽ×Ëeû­mN+Uª”Ô–ÎCZ! kƒÊ-,ÄM~}g/8àø’èT~²awf¾ïÛ™ -"èËäãj2ûL]à¹ç9hµA>Áç!ncÏB«ÝÔ6®¾"dzpà;`'ß~Ê#ÎÍ©íÆMw+ۨͪRìü»š±„+‚¦0÷ÒKWòl[²Äœzà$+[õçîyÉ8~·Q<\.Ãç®?À Îmhkˆÿ¥¬TšÕ 3beÐk†mÚ»á'Dïâv¨‹^ݲHû¨e:þ¦©ŠÞ ºÎóJ˜îö„…‚9[Èî3YöRÄÆþ\ŸâÛ¦ã]÷SJ=#ªë<‹%.zˆZÌÓ¬èŸLËhŸ³ÚtÔüeeœw ›i¢^š­.œï³¡6J›tU–„eã¹eQ‘kÓ«ëcÛÚÕõð’Áò¼DªŠ¢*Ã¥â¿l›½ªßáTAFÖ°N[æõ¨þDÑPìOE¹íÖb;°WæÚ¶ÉÖ¦ iØ2~€zT =æAV¼’÷˜,Rð»ç›¬a±<\]6‘™¦ à(Ê }–@MˆJ/öË=!³î‰S'¨j¯*ê‚æùù°ö{ÂÆiÔ¼!®H¼|[©ÊÉÚ´¸&ó"úªŠ Â/~U ¸ˆ¾ ×Q,2òWW_“~ e!@A›?ÿEêƒËÛÒ¦F!ROøŒáï •u×Bx;ê”×Ò a‚ýa£¾ý¾o‹IA¨ðÿ0œ¹ oM*»ô³oUÂÞz!Ö`¸À*,Àìš'“ñ30m1{4!OÙk ªËìÓ¹7îr6&ÔÙw9lé>÷½L>7Q˜Q441ÒýKu‰Š´¿<ß3CÊ êØÙ·ßÅâX€ss$XÂÉù,a±þ»œ¢ÑMÏsu î{·¢j©ê&u‚$}Ï |Àqïù(»1¹=£\Í2ArõÊϨó3,­!MGÓìÇ€òD†ž§~zî€Ì>+Â(î›TÐCxÓàýyÂûÞ¢ÇzÏçVÿ™åaÛ÷\É¥.¦ðÆ…YÏÓùòEÌØ/óµì*O}‘‰ƒúý´*¬<Äømઘ endstream endobj 1763 0 obj << /Length 921 /Filter /FlateDecode >> stream xÚµVMs›0½ó+t„[•έ_ÉL=é4µ{J3 µeG‚8õ¯¯Ä Çq;ÍÅëÕÛ§·+­š#‚®œcçÝ% Q‚Q ñ Å'Q„â#ŠÆStë2̼¾'îÍjÄ•¥üæÄͪ¬PË¢(e:‡Q]5“æßùÌ£Äå—®MÌO¨ËïnüÅùýÿ‚n‡Ù q¶®ÁÀwõRkÛO£‡'e±¨ *”QL¯|þ“±sKÁztÙÐ_ÔmÔ•ýË|,añEÞæâÉó™É#&¡O]1ëxñCØ ¿u\êVü±áÊ’–W®¹w@™Ü@jŒ$”âc ÉZ[B7ï=ªkm¼ 0,EžÃ¬*›Ú–T˯µuá[ki+³œÕKC;«ø¹ÅuÅ£RÅu%Ô≧E9åoP8ÇCœ*bÏϤ‚éT¨¬=•¹U¢ƒlsjÝ öætÒ.ÏÃxYÃm c+a‘=§3[Vê„|ìßäká7ÐGeäëìYÀ•TÀfÖÇB‹ò`5X´—s Q׆„± ¹Wf“¦Òm£+3]²™õ lx“ƒ§“f '¾ð…Û÷±ÉrµÛº_ëóyìÊ&ý›'j÷4°GáÖÓ4d8Šì}~Å%¯²õuØ2²GðSi¶÷ü{nÒ¬È>Å?¾!r endstream endobj 1782 0 obj << /Length 1042 /Filter /FlateDecode >> stream xÚÕVYoÛ8~÷¯à£Ô )‰:ü¶ÛlRX © hZ´D[Âêp$j³é¯ßá!E>’4íSŸì!93ß|s‰ "èzöçjvqÅã$ }´Ú¢ˆà8 Q”x8¤h•¡;‡î·ÕGä‡Ç‘zúô}É»Î{Qì\6i_‰ZrY4µz;ûk5»ŸQxJMÆ1޽¥ÕìîAÜ}DûIŒôË ÌÇ,P.J´œÝÌÈ«0qb†)¦ÔSBˆÓ¹”9ë O]8ÿô{…ìâ*b(ÂID¨2CÐ܇¨À´¶Ð×]±«EæÎC0æ¼5ÿn¾/E×ApŸxË«î}SUM½^.¶?Ú¢ D°í±E·)¤aë+!ž(3#dB‰uQ¼5¿iS«‹]ߺ”8†X«ÍH'„n¾¬—·kãÛ'(ß^¨|SHŸzC®À”a„ƒ(Þ H”«¼P£pÀúœ& ŽüÍr»gyà…\§µ\˼U)èò¢}#÷E-_¡~êfââ¥ÜæÂ²¸o…ëçߢém KH5œ<i«nyQŠì9xP‘ð!…úºiÐíEZ(îR#×*c}µö¾ÙÚ”ò²´Î6ÂZ°ylÅà~,ÙXíý€9³S¡°`xÎ¥±ÄûÒB6„¡C‹…õëø0t¬rë>;èßÓe>˜éNðÞ§rÊ‹½Ý‰ZØzÖÿ¶mªÁˆ˜š.ËF÷ç°b° =>†¾G4ÄQA¡x8Jl¿z;|u7g,tø~_©ŽA·>¾çwyQYÉ¥€ë{±w}s/Š:-ûL\X{jZµ;;¶>+ËÎý“N~àU·õpB)3½a±öÆÎmS<•±N—*åKÕp>Pµ^ÚÞ—íÈëgÈ+)ZQC¾O;Q5X'¡qô©ß¨ç¿QÿCʶب¹×KÑá>h‘õ´ON>ÇŒæ|V ÂÒÉ»tuJØÄ14¿ç³aü¤Fe¯©y ð|Pœ+òÙO@þÐo·¯?dí³:ŠÎÜh@­ó¬=Ò±EH, ïí€.¹äWcÃ1§âòG‘e\ªº^o+y¦: ŽXV§‡ óÇòÄöü[À ÿÇf5¿ endstream endobj 1718 0 obj << /Type /ObjStm /N 100 /First 958 /Length 2377 /Filter /FlateDecode >> stream xÚÍZÛn¹}×Wð1yé!‹UE0صá$@8k?$kB_ØŽ[ãH2°Ù¯Ï)J­Œã‘§5M §X}ºX÷î …wA‹¸Ù…佋šŒNb1B]òH. »(X(lÞen{²ËÙØ•ÈgÁØK²…ì‚'ˆNñ ²¹B[  $cI] o‚~$n׊ Š­d4–äñ«x‚üh!)fo» n©¶„MˆnÖ³D,á[.&6@læX «”¶»8òQ°¤ ²‡ø*6C„¯ÆÅŽ(Ø’€P["ü½£J 119b¶‹Spt£6ÂZæh°ø ¸ÝìÅ•íÒ ªÍv1@)©Qd¸i;ŽMï@Í¥ŽM(¨ä¸„hJÊN|6É8F¡&½Ö†”¨ FÑ”!=:1ˆÁ3Ž>ÙÙ%'9Ø¥iKê¤øxƸC)lºÇ?)%8ÆÍ¨m)ƒÊ„¥â4P[2*µk§ÔN P”ÚÉ@¶r3X‘JIg tŠ5ûѨŒ;ƒl5U`É(ƒmÂ2µ%Jm 0J0mÀTaÚKFÜl œ<—3hÎìÚ®ˆ£Ã{(šÊ$8èÂŽYJ6ƒŠÒÀBšH»ï’š1%…Wd¶½pŸìCÁL¦fZ\ŽÙäÁ ²4›Â¿œša@+¹4 ÎÑa\¶Ü¢W:5è À=yr¶yõïÕm~¼¸Ø^Ÿm^~®Û÷?¿»øçÙæ§íåT/_{x¸³ùãæO›§¯Cûr¶ù¹Ž×îu`é4´SëÌF)pgî¢ø„›‚ïG÷ä‰Û¼t›?l_mÝæ™ûÝÕõå§ñú¯¿½¬WWï¶/úËþÃÕùùËó~ê'™R?Œ£/c)#ŽÕ>gí}¨ô{÷Ãgø;n)¡³Xkêf®>tA{œÂ4á®E{Ê^æ¾ö„°3Œs©ŽÓé`ké`šĮ¹WÌ]F$€‘½¨ß^n?}­“î•é.Â.Ø*1Š0½ub7(üO¼°f#Üøûññºû"^pøæxA7ˆ[“qKÄ…à……Ð[".»â²+.»â²+.»âÝ®´y!Ê-Áþ”aËr*ôHh+Ð3uVc«ð}ÅBÖoYù§« w e¿DT@-7¡ÒhíS‡èòèëa C‡ï­kGHbkû€¡i}AütûáÃö¢•Å’¦¢^”¦èàúÒ+5Ó\"©öÃüÕ<6ZçoE™ÄØ¡U: ý4@åÃ<æ>VÇŒHÆCgGÔõšO©{ D[fÍ?ÒSé8[Ë2‰ŽO¹– 7£÷†ÖGôÃZy`ŠÓÀcÕÓ«žKF5…®±Û Rñ(y“§z’ʬñá]æeÂuÿðlèû‡g»ÌË„KÑ;ìâê>Ïh\Ó!з&ú•ÙÙѨ»:{Î{@ô¡ÙÙÉ÷ÏÎ>S‡ÀÙ͈îím³3’CÌËXîþáÙÑ÷Ï>};—;Éðìè‘éË‘ý·Çˆe`¥~!–é–.Ó-]¦[º0§…9-s³D1ïäÕ/ó.ñÿyàÅì»xS•›÷ ­FÊ8¦#:=2$ø¨Ý>{©—Nþ(ã[‹n´tÖ¦Ah^¿ v¯ŸÕù}][éZiHqæTd?C¬<ƒªdïSýéUpÈöÖ†ÊÍ@…PÄ–ïì uPdcw –PaÛû_{PÓ [ÏÑOTý4ÅêÅÔOë$ E¸œºIˆ¾_âÝùöì"•ïò] ¨FlÒ³¼·€ìã gþ·DÓ€ÚM󣩡.÷¼e±7š¶Ô˜Ãв]æƒEÙ.óòÄêþ¢lh+Ê‚¬dTPi÷}‡ÿü‡âÜ endstream endobj 1796 0 obj << /Length 978 /Filter /FlateDecode >> stream xÚíWKsÛ6¾ëWàHΔ0ž|ø–&µg2íLéT'£¡(Xâ„/‰¤]ë×wA€IÓvÒé­=°‹ý>ì·Ú!‚n¿®W7R G¾ÏÑꇾ‚ˆaŸ¢ÕÝ9®Ç‚Ðù|ZªºNËâ“ˉã¼þýO±^šÑesl“Æ´¿¨{—GU‘¨®‹ûŽ”î·ÕÇÅo«ÅaAay‚èy¹0Ä!(ÉwßÚÂØGD0BôØÍÌ‘KÁ¡¡åâó‚L P†#JåƒO1 „ŒbŸpEÇ%ö‰o–øÔnôô,MŒù»¦9¦—§mTÝaºÁÀõqÈcX0ξ2&G&†¯ãÎ÷åvî<)ý!¡ñèÓû2ÏËb½š¬;@9ÅŒKêÖLŒIÕqbðŽÂô¨1a ` ˜«ÕÞì°³-“6WE7Œéº×—GóÓìÓڴ꺨tÎL?ºðÛÑ*”AѨ­õs,óÞ‰ºÎ²R›>¦ÅÎt%„eêz„úÌ/g8ˆè [:㪂ì0ÔÚ5>Ä ®÷inÿ\ qÒÊåf šWi‘díV]YÏ7Ê9\löÏwd»^«0£çä _MÞåÿÙ;“½/Åëõ†žæ]þtȇ“¦ü}œe›8Ñ}¿)Þ¶ÔœNC«‰ÍBbÃz#M\&2ÝšåE€ùóqÈYO ‚¿—^,Ñ›C]+n5JKY:EœÍ¯ ‡Œú!mQ§»¢—xZ4/ʧ›D½õåi‘®ó¸Iæ„Dp #,$† õBÂÔJé•o”-Mâ&¶­Q›W ÅáÈáÙeâ9>Ê{ã"Àn:t!‹ >¸Ð4t‹0*¿¾/±Ÿ©Òd¤Ä¥²å@Ú:&h̓M}2Ú¥mi¿¿Øº¼Oa¾DC½m3»][†¹ùô5^ÌS&Èð$Ö”1KÙ¬$ž'ê,¢OÕ§Z„äy…Íóêß_!ÒÆ]•µ¥²:–‰öÖŸ9ÉÁósïT7–4(QÕÑÄñ£<ñYž@pi=Z)¾ÎÐùP@Z\fÑSN ÅÄU„ ú9oÒ¸V£ Æu— !Ǭ¾³7…²Š­Í©ªôÒ²5Ö‡tÛWŠîPzš\Úº7hÊq†Vq]ŠŒäFk®%çÝr6ÑØã¥·» Cóðo^‚úïÜÓ@JL8ý™—Aÿ"ð1 |1x¸îøöºs«)¾Ð;Ì©ewØ=í´ô5®'âß§Ï`õ endstream endobj 1816 0 obj << /Length 1187 /Filter /FlateDecode >> stream xÚÍW[Oä6~Ÿ_©/ÉÃ;‰sAUU »ì®–ma¢ª*‹¢ñLRå¶¹@Ù_ßãÛ\2 ¶}@xûø;ß¹|66–6N'¿D“ƒ·Ô5zžcD ÃÇ(ð<Ãmä#š—&õ¬«èƒáx¾ûÄìq‘t5µýÀ<©Ó¡dUŸôy]ñµ“7ÑäË„ÀRl•É @íi9¹¼Âƾ}00rÂÀ¸+KÃ¥¢.?¢0f“ó Á$6 ¡›8^E¡5%cóüë¬^ô·IË~·(6Ykjv€î}µ°llÖñLBŸõíör|Áá‹Y•2îÆˆlLŠ<ìÉÓ~®ùò"Oåö£¾oókn}èY'hÐøÞºþ†!â!?ð©í!ÒØgÛ¦[[$uíRqxq:1.§”zÚ5î¸w\—M]÷1#‹Ð¼k`Èâh`Ëâ‘Á*”©6÷w {ùTïœòPÐûÀ+¨CÕåËŠÍ%?i–´{Xõ<Úá.”*)U¶ø!²‰¯—_ªcw¹2ÏÿŒÏŽþˆgÑÅûO§ñÇ7ŸN£w#æÕöÄ”¸‚?åyŠw9„`×9 Ch´eòWÝÆ7ël|jµ÷L? K^=Ë‹óÒ$}ÊK)ûŸp#‹8/æqÅa å5k_‰žGEË:ͼ}»5á„0´W5Am‘׎ƒ<p9.4G~Ž2&žoum1µ°è­üÑg¹êï]ÏO§æªSÊ.YÅ£†Í¤×^-ÚºÔFئ風ùÖÛ¼ZÊéÏÛ;Ü&J÷Gè5~ø :“¦,|è¸iô%éQ—å%tA˜pM˜ûš7–#?Ãð ¯Òb˜³ƒûûÇÆžl·—n(ÑTÃu}hMZ‰^KP ½mi°¦ÎZQêpÂú$/4¬Ö¥mÞègÔ¨Or5€'¥ÒÎù‘E »F\¥”L‹ø%{h…`ð펟çü,±F(öEûDŸ[´Õp]€êUˆ¤Oä¨e(°Î¹¾iÿ&°z!ÿkôj¶miÀàú6BÍíã+fÝ fmÅì×6Éë éÎSuÏs¼eq-ž*#„ºú(ô1Ù›u¶y°Md›­/‡‡Êؽ©4ŽýFðŽ…~mñ GÌõ£P…‡YJitD‡¦Ñz¹ G¡Ò ÏÊíêß÷Чa‡<å¯ï²}ÏW ê" 3.Üm> stream xÚ­UËRÛ0Ýû+´´Qd[~„M'¥…†)C!^tÊ0á(±¦~K!%__Ù’ƒó3ì¤+éèžs_Ìׯ×Èè_y„pàû.ˆ¦ @0ô} èÛ š€GÓƒ6²zNš÷«± bÁã±ÚEµH„Z?Щe#“V´H¨õÝŒ]è®üHÁµÕø/†-Øë߆In<>!0‘g7Aw‚es3Ø“`¸ËÀظ7ÐI¾ Q—t cõl„I²YsËöÌeíSÿ*ð@²kz® C Ú¼]œÍ :±z¾|š¤¤R«w1..àòñþO|;ü^ß=Œ¢·ã'…ƒŽƒßÁ’¯öm¼˜ÏK‰‰‘©¥äåT,kïHE•¥Æ—W¤‰‰4ç tƒµÅh‡°« §Ë˜SÎYYļqú4í.é¬,fjÅ ±Ëþú1Òw…fVNuj -ÛAf´bs[ ±M´wؽ´7XcÍ:§y£2ßb’ee"ùæíí ÷ æÍ[à{i+ìa^. ±I\;éJ'ÛXK0"jêí³å¬DÊx»ª(™ôç•ü—ŸŸžVæ…ˆXF-iÜù $<-+qD“]ì#Š\YØ3«2W¬~]Žt$¤8›”ß!Å ™²ÅD’Ô )ýœ ßOOgùˆˆÛ,n#×XåfNU}gm4_´I JmÕõ0Òž|9[¤ #’L¹x¢ ãµú> stream xÚÍWÙnã6}÷Wè‹Ô I‰¤dmS§3ÀšDo™¡ÈŒ-T–-Í$_ßËM^"'&3è“Eùòœ»’GØ[yØû8ù#œ}`‘£„óÐKï][“åAM RdŠS-ºuaÉÚ^æ÷yg^<°Êì¿+YÉF%.ëT*=ê›.ËZm}|ÿŒ1-åL·„«¥G8±Ð¹abÜþL);´º™2Æýl»-‹\ÇÐ*htŸu¨]· ˆß=Û 4ÿÁãYQåe¿”gOu`³²­x¥}c¨÷¬Xu“h!B˜ªÝÔùq‘hh3b[LµB#³ÍâÚÄ «!‹WòN¥M6²ÊåÐm ôå®Û"DZAýɺm,©Ø³„¡0$vî~ÁHD‰30љȎ"Hœá¯Æâ`® ®…<çD93–÷·*(…‰í¼ëšâ6 0diú½t¿Kàþœ*önàGQu'+h íÓ΀¹…*Æ<~Wºï ÝÞ—T+º !Þ+ç(¡CEaŒÂ®¥[ HDn[Q;:ŠàÀøŸ¹«ÒûÞþ¾ZÓ­¬–PTuŠŸJþÞÄ'y\ùrù4oò4 0 [¹H_ߥ‹Ûä‹ìdgH_fLÞÂXÖîòÑO/ ¿‘­4Wð¿e>@|Kä£.–#óA9ŠCú­ó±Íî{9r_a$X¢y¦ äP“D™ØÝWÈÝX²ËŠÒ%ëB¶ySll{®\´âçò\7Tª®NwÛÁÝgåFÖeNNÔF/¬ä˜@ù}©8µà°ÄzW:&Gz§•ò„LQµN9uÙŽ¯’r9(“}…Óî¹WoˆF4Ü{{©Ã#I£6iÉÍ­´¨ñ3Õ{t•¥Ï …€@2]ó¿E‰ª™„¨Q³ÙnŽ^–ŸóµÌñ?moS£Û6+{y"„=`C G!ìÏûy4.×Qú˜z~BÁ@ÅçxNDžŠPï³Ç‘Õ/Ëêɰÿ³Yϯæ<Ó)¶ÎU]ÎÚØ' c‡ä-_4îK†#*x¤5‹ƒ7CœÛÄ|T¢{'¸µÒzt]§züë£ýŽ©Ž}ü·¾ef endstream endobj 1788 0 obj << /Type /ObjStm /N 100 /First 962 /Length 2600 /Filter /FlateDecode >> stream xÚÍZ]· }¿¿bÛ]Q") 0än ¤@û!£Mj4ÞMw×@š_ßCíŽã8×^žÛöe—£áHGEJ—<‡ÉO”2O,ö_¦â'Nq¢Èö¬øSЦzEC¦)RÿÂOQ­‹"èB”ð±Šé&ž²/& Wî-èΗޔ& )˜”'âÞ"ålBÊѺšà}2 #‡c à Ϩ¢uR2¤ÔÕÊ„&BÔÄЉХGoiMAð‡ úîMR¡ÛH{^*¦jš@›¬ %™ mASV˜,Ã"¡˜ñR1û”þ6L1¦n¡8Ea> ÑlºÙëó-¢4±Ö‹Ïò&ÁÒѦšñàl@'¶ÙP|êo#ð”þ6Mð8I¤>}¤ýƒ< {Œð–ņÖæ‰×&az’{:ÖØÛRêmè/5©Ø:II ’±bÝöÕϰŸ”lM2©½)Cê† ž”ÌÅ2æ¦ýC‚'E.fCs e²á÷Y™$˜•ÄA‚u }Á2Šõ¥lMpÕlMè!ňî#^šûaþ“æ>6¦ªþ-‚N‹9xN-ba›ä½µÁ½“ïë7IænÒ”n}+æ)éíeJ·và¤öãgRƒ«|6)MYúhpÿ¬½g€Ê·^…u*¾/ŒÐTB_qL³Ä‡GÇ/¦gØ2„üõtüæïß›Ëð|.Þ1¼ââÕ?|wøä“÷+§âðbPY²ƒkŒézï`‰1eì FQŒ)c»h{»$—±q‡º¶, ýJùñåÅÍôèÑt|Œõ7oî_=¶Mé®ÇXJó©ÛÛ9g´'trüêêryÒn¦gÓñ«/OÇ§í§›éuÿOÿýcËùûv8~ޱÚÅ͵… µïǯÛõå««¥]߆œÞö×¶¾˜?»üizæÑ E`x“Ëå;Œ7_¡èc—výO/..Ñ鳩‡iƒÕÃô » »v!ïB¹ò.ß…·fÑ:Ÿ¼ª7ýùËÿ<?»¼ZÛUÇê¿;þùø—ãçϨ?Øô¦°³Qµd'Ø$pvA±Û\ µOû <™Žº|z9aÿp}sõj¹ùÛÏOÚõõ‹Ë Ìy~yýùåË——ÏŸ?ù£þ,ÐÌ'”,$Á¡1zr lÊØf|ۿ曟_üø<ÿã|0î,$!º(¿XÑy’ÿ©…vh¾8±ž‚‹ˆð¼óOBûþêòÕÏŸÃNßÂNßϵ$„?¢6§ÙSh%oK¦J´,mYj=XCgùgG Náú}hOòËoù Ìø|^Wï¡n#ž}B~ož±O6„¿æYΈ ruHŒ HÑ1‚’øä0Ú`WÚ|È­è&3qÓº-R”V©È¬gÄ΂m²˜Ùñ-©s˜ˆ˜+½ÄÔBM9.öBÎQpiëŠ|>èZœñߌèj4•‘X*Ò,©üŸ¹÷­ÈçAPöh÷p¡'‡ÁhÕSd‘_R¤Y)Ú•TNäÓ7•ïòiJ<¨ Ã&É1å˜XÞ˜.©ccÊ ¿L:س¤èŒÀ)kpT- ë‚„1eÆÚÄ8hf†å"çs*‡UÆÌ ‚vYî3GqVž¢¸qÁ:G`8?é{'q{›áå`Åqþ(R‡ à7¤ÎJ %u…vVváŽæYÍy'è.¤]È»pGê¬f¹hÂ.Äá{É%T7P…ð{éÞÛ!u­Ëªy“ea sö-rUYc*k®‰ÏR#V^¦Ù2Y1ï"ŠEí+ÄChÿ…çº!ÑÖ) „uc¿ÔØâœ¶¦çO¨ˆôÊë`ÑAó¿EWÉʯ’QÚJc…ƒ:¤ü «å|,ïÏ÷7óÍ«ëžä 3J+ØxV¯«ð¶lÅWZÖ5øsr+A(Œûny!E«cKr\ç™ÚB/ðLõ _;½  ÝÈAVkeKsÑA¶pñtzƒùÈ ¨œ×ÖªU$•úŽÅÁ6LÈÞ6òFoêpï[æ²ÌQÛ’ëÖê,µÔÊ9ÃҰáÞ £Ãöëº Æl[y+‹¯²ð&9­[ŠxÔ00H¢÷vH‡ (ƒ3ÃQ­5UìÒºù9”M±I·¼äÕKmYÀ÷3Ò WFV r†£¨y^r•½ä9¬¤^CØ"Z܄ַ ;.~¥|_ápRù]…ÃIåw'ußU8œTÆüRD¡XSN2>?µ<Ÿ-§Œµ ƒԨؤƒ¦˜ÙŸª_N)3˜”ÑÒ1efǃ‘ÑÜ!eÛ~ÔAIÔùÏ©lÌ-@ ˜í*àw/¿.WìÖÊΆ>ª\éׄo•+ì?¨\ysÖL¿#:0ýŽèð¦28’Hê»8žÜò'º†åÉ}ÊTPð‚ (ê=U•žêZŠwrr³½©Rêç‚Ëi¬g;DK÷*’kŠ2¨8EëšÜ£ÁòíÖ+†ÒYÿX׬Äß§ld‹ìèUãX×v0*ù^Kc£Ù*xh éã.}>x‹‰üv‹IüØ» ¼­Ûã^íǽÚ{µÏ¼ ûï_ñþï_ñþ•ìg²ŸH8çÑÀëûF)oÜ·8á;Î[¢€½;¯odß~¢D»á†–ûÊ««6¿ìÌ©-অx›+P¥Ä‹€K¿ ¿ÍpÀŽ0‘¦1‚¤ýV Xؼ`©—èçU¯<!ï·mcYkÓMý9Ë+Dq»†aí× Ø»>䉑ÿŠ”a7ìaÔ°(­x®¨·—êßbö…·Pêùñ¢*ÔþÓég¿œzðÅ[|J-póÛŠ4ë\×mލØà%MçõÕŸmh*àü øÉ…q/k¾¶²Å$–êçºÔuV©(»=-€ÔѨs¶ ‘aÀTҚ௔6ïŒT× ÚØéÃÙï=9 .ð ìk¿ÜÁ4ÊØ±`ž[m+ÍkŽ0j[g¿QÜÂÂQ}Œù¬§EàW嬠9·çûâèÞ“×¶­¨‹bopÚmFÓtiã#‚=€3Ò¿ýlѬï6Ð"°®QÀ5«‡»†êf·‚(W} m¡Š°ž÷^Y"MŒtÔîf‹cÛnøŸ„Fo*çZâÈ¡ÑL² °µ¹¦PsÚΙ­Þ°! '€G£y8>„­Î52Jζ¨.ª üXu¡ª’Ï} [ŒÄm@Ø„æ]":ënû«ˆÑ endstream endobj 1872 0 obj << /Length 589 /Filter /FlateDecode >> stream xÚÅ•]s”0†ïù¹„I“/z§£íØ]¯jg!Ý2³(jûë PXq?Ô©WäÎÉyŸyA` ¸tÞDÎÙ£@ÂóD·@ (9"$c¥àÚecÏ'Bº‹Çe]ªx»ZÚØDMRÛõ'uëaäªRéDy7Ñ 4€Læ [&lww‘sï`³‰N“JBA²u®oHÍ»+€`JðýéË- Ì£m± X: TÀ1Dc ÀÀó1BÈÍtÛÊÙ…`@ÀP Üæ!àJSë)¥ÑU¶Ö*õ|n2’»¸´9’Œr8˜‹^á„‚™Â!D˜÷ß<#¡†I×ÿ{]4ç4®c»*òLת´A¥º÷_=‚ܻދb“%qåÝIPF0E¿0¢£Uõx*&Ó]Le•&JÑTãò€‚Wv§T³R¯=l¢è1+ìFÛg¦Ó¶€²Q’ëªÙ¶í,fÂ…u\ò"¾oÔ0̦}˳tÆ18„˜È##æ3>|ê"!¦¬#ڛƺƒ¹:Þt.©ó²ÒxÝñØÆÚ¬Óý<µï¯äóó5ô±gÀlÖ‡¦~±Ï”þÕ„Ký÷+Ê> stream xÚåVÉnÛ0½ë+x”¢IŠ‹”[·zhbÝ’ÀP$Æ KŽDÕI¾¾C-¶•:mS$@žL‘3oÞ,&AKDЙó1vf§‚£GR(¾CŠàPJ¤"†%Eq†®\I¼›ø’âPà×í~*’¦ñ|¦B÷s•¶k]šÄäUim/±sïP0%ˆî ÇŒ£tí\Ý”ÁÙ9"8ˆB´í,׈‹ n¯(ÐܹpÈoi'2ò˜RÌ0%žO !n­]Ûµû]g–ÖìT ¤p¤µù„¸{[6ù²K_‚sQ•Ëç«‹§¹©u²^ÌON:ð.WÜ—qu uÙÓ€†Ç„k/°¢Ýy°SÕÃGkÚZ÷ë¶ÑÞ#L¯†ãl"öÏPf•iiŒ^¸mjú­_ÉpºÔ%Ðq³£TWëDBEe]·¹UÂn_ }ÒåzL¢«P¨ «hþš11µºò…n²ÙyÚÅÐXh|ŸܬòõøåQ×<å/èÏ`9ËË´h3=ðliÕË¡Æ.-²Ûv>«É­]õP†#J…M‘?rå 3º¯6”N¼‚> stream xÚÅ—[OÛ0Çßû),ñ’<ÔµØI¤iR)- £Ú$.вÖ@¥6…$ƒO¿ãÄë€@£„—&’Ïåçÿ99µ ºBí׈~îµF‡Ûˆº˜{‚¢à9»B áXس,LљѺŽn2™˜u渆0/‚ƒÜ‹1l—)/‚ê‚aÆháЙÍea½·œ¬2΢l¶Œ×ž”aR®=!%õ´§ÀÔ¬SBˆÝÜÌg“Ü/Å·Q†ÓëÙ"{˜ÝèGcOLFŒùj*zåºHüa(/MJ ™Èx" ‡#{‚ M`qLm¯ ؘ*^aÉœG–ÜÂŽç‚Cnøí…Xv Ž6H³d_Ðf$ÛÁ.ˆ¥ ¿¿ Dð°%\x¡Øã|ûpÓYœ½ªæ‚…°žÂqŠ9ÑʵæQšÊTÙ¯;¬Ñ±GŽT`ÇuPÙà®»ëœ1þÄÕ9J>hn¬&™^&ˆ¢DÙ¨—an¨ |ô0’i }20mè›Ä¤Ôˆi8zuê ýç‚VŸš¾µ\,–ñCìÉsB¬(“oqxŸËqxj±@0ª!4©Q]N²o•VXëå¥JygR;WÚǦ«F­Ú¼_š1–Õ©ÞJ&Ân-cèyv4Ö;KdÏRnÌM=ÿ,sXÉÓw£I¢þÄ–[›œ;SõÙ³X¾Ý4)ä NýAØøJ°ãöpä÷{aoÜ »ÍƒþðyxåwN8aðCŸ.¾SÕ-Áù½r8ëëà>ôåýgöôø{Sž†ýŸerØÿ§+~î‡~Kï½½ ãä0´œÄÛI§?lµÃÑI«@A®CsØìŽÊ0ê´ŽŽøMÿ°¬9êìÕîØZMvÕÜ Ûá¦/ ­ŠUE¯ª³‡nÕ¢P¯i¥@(»¶Àï¶ûã T^Aµü^ÐÞ/ï[B*Сל”jA7?ŸvP»­QLß”9ÇÄ¢h²¨]4…¥D°œw¹áÙp5ã¶ïs4ª­oÝ3GØ.Ý6Çùþöe,8¸O‹Kì/Õ;÷ïÔê\õûþJÝ” ?GüÛÞ¯ endstream endobj 1960 0 obj << /Length 1751 /Filter /FlateDecode >> stream xÚÍš[oÛ6€ßó+ ,`fy'5´[ŽÝÚ–+ËIš¦ÒÄ˲µî–&Øúïw(ù"¹¤ã&–Ú‡$ŽDÒß¹òð‚½k{G‡ÉÁ³®àžF”ÌK~÷FZJOIâ%WÞÛ†¤þ»ä¥ÇàãúeO»7f~“*Ýè|º¼ÿ8›ß]ÜÝ|š›¦arðÏ–Ø#«µFšrïòãÁÛwØ»‚w/=1ÐÞ¿YË Îàóorðú/(q‘–«­VH æ)I^âžS*2Še7ïmSÙøéjvŽ1Ï/ Ûíõ2Κi^Ÿ¥£(vb_àÆñæ@T©Æ9˜PøMÊo±×$©@í‘£?š$iË'”4’Ä'$h´|†ížŒÕ6ˆ ÄI: ‡N^#G'- }Ò°ñèœGÔÀ3M¦ãqª$ì¤@Ô&N$Y‹B'@\ ÄäÄx3|]ïÄEÓ$˜ÔËâò­—hî8 wøã ÷"« qm€iü¯'7RËWÆ~Úè ´7Ø%êR“ISÌ[’@“Ô’Æ8Ö8öÁ£"€k‡“IÆùÿñ6UÛ0\¸zÇç™!÷çOÒ( Ð06™ténZ]m4MÒ¨›Æ­0…[h‚Z<Îè,I‹ópuœXï)áoÔ#Lé²84Vm¦­ÁQ÷“Þp’÷(Õn’ˆ²ìbèÌÏÍüÎRa Ø&áЇ±}k±v ¿sÔü܃jçŸo®ç³«¼ô½üãâÖ`êzt:8ãE2´b›z¼·‚žc¦¸ùeQ®‚qQ ög 7´Ó"Øû³ƒ[Ã8šTÀ}6I:6në º;÷™‹Æ‘|ßÜÃþÈlq&ŠÌ¿ä¤ï3²’›g¯—ÀϺTy DåâËŒ¼è¹å«R¼dÕ÷¹"ùm5ð¯¥ç›AŽ9‚U`ÐÞ´ÛM{Ø|^4Àì2ø™pìIbS„!˜Óûͨ5ì·ÍÐ%Æ‚L°´…¾ÈÔéÇa;éG£§ÅA(Q4=̧–žS"©…DrŸåe@Ƙ" ÅÃüÿ'ÈÈ0¢¬$c!é§Ggýqž&.aôªóµ£á8„ÇáÀ%Û¦ T !Wéþ«à‘ðZ‹ªHÍŒ>x‚¨Fx>¶M½E‘ “ *i éd†ã•á¯VÙ Лڇ0Ǥ¢r âàÕ® D@H/û³MLaJ/Z&¬MÚ21Ü~5Ý]±Œº½^ ^Å”`€  ÁÌ09³Auawa>“‹"Œá¼`ëf˜Ù*h²vÊm³oW´rQÓ£ÙœYËr…- L,ò*(ò­âÚô9Ù‡Þ´@œë ª+»›@Ô#Áö¦6ú´0û ¬«–’ŽCZH/´´vƒ%›Í¼ p±V~¼y¥2íkØŒB]’šþp¡ñ”J^7µX*(¨ƒª˜7’xXÊN;NÀéܚÏKe4çºr~w– 0ª’äj žT¹¼Î<e×â˜lñÛÌÿ˰öºh´GgmÊ¢²ªÚ<éÅᤠ:»€t&ئN‹þ@ %ª†€é§Cd@õ ’j c%»Vqøz7B>¾ÞDzÖ%•lOm¶N€ðy½èMבû«éTκ£rS|‰7ôqAvâK`î'i{”|»0Š ÆV3Õ¦S˜˜¨bfÊØA¶Ë‘o6øŒ<ØtÉò¢ÇºQ@3&ê…v»¹¤¨T›¶ Œ¡¥ßÙYUꉸírI“RhÆh%Ûó“Ý= .¼ƒg@¡…™¨Öí°”¾UK”Ζ¼{>U2{!ùñ½Ù9ìû¤‘˜ƒØ¾Ù­u3Õt:lÝ(n‡†±_¦²V ôá\`J¾?j8ÃQëp¦“¨›œ˜kŽùã° ×á3¾ôðâÒœlÿuÿ÷±¹ pqë¹qsñÞ<ý0ËO<8å;µ¶„L!¹>øÓ¢6Ђ\U-/üLžB¹_:SE2^oÖ=¾ã^ªÊ.Ï•÷ÞŠþæt¶†ãà…)ž]ÕÛ— …¶Û  ~9n¼IÃÓ°=u@îhIB¤x´)™©‡L© ¦š9MI’B”M¹1\“†3U–ÙÔŤÃX=jwk´uú“…©Ì}‹µµj · æç6[ †.¤"†çÚ²Â.Ù)@ZÑïq¶k²ÂLœä[nÉ.ïðJD•äY¶7›ƒð&R.Næ ø˜Ý^Ü-ϧ3eYÞß5"ü÷å ³ù&ãÿ€þ endstream endobj 1868 0 obj << /Type /ObjStm /N 100 /First 965 /Length 3036 /Filter /FlateDecode >> stream xÚµZkݶý¾¿BÛ/Z΃ää·R ƒ¢aE:F“Ýtw¦ùõ=£]y8‘’\¶///5<ΜyHd1 aˆ1‡˜h(a  y ‰æÉð{г/(çà?Ø „‰,ƒ¤u¢ âUÌ.‰0Y-É‘!ªÏdÒú.ÊØ7 Öµ¨OÄÁ ûDŠdL”¡˜\aB‹mˆÅ€),$ò)€¤¤>…ÿ8”!¹TŽ~@N¦€EÔ%ù}šßŠJ‚ülEY·.¥ìë²_Oë:|-Ñw€2° óL€˜H10v­”Ä®1Ü. ?°PÆ&¥uWhX×A­Ú²„Ѫ.Ë?éËGæ[3ä%[¯…Þ90¨FÈïÎp+"LأРš]2 JÇ…I6WXÑAÊŠ¯DÖzŽØR™}_hQeUl1?Âu‡š°hPqWуkª"•õWñzm crô%¸u¸öJð“Íë:èËÕ„‘ ‰}âÇ%P,N1úKÉìײ ÉU’pЩ`ÛÄøWü”™;VŒ`3Å!­s#·ßÓÌ~ȉÖ`‚Ù5Zp~¹ø¨Õˆ'€›ã¤ Ë\¥LÎc nÖP늟©+dº1˜nØC`¼êæT4 7é#x˜ùÙå¡”Õ°ÔMšÔU „\¶‡®\¸[mx<÷Ì৆¡¹ý½zォë‡ð4…/:\ÿó_ŸCG£:ük,ÐýÍÛ/¿|yõþûï^œÃº8gtyhqs<(9á+’J–Ì£êÁÅœãX` Ç«ŽNg\ ÚG)çQðyH4ÅpàTXtL8hãÑøGŠ~v{ó0¼÷Þpý W`½ê™ó›ÀÕ¿Á²àO_œ%tÿÌy„¸¬ß òúow·õy{^ ×ûøÙpýYûæaøn·Ïþ÷uÃÓëvuývn7÷Îfì×_]ÚîoßÞÕvÿÈ¿ëÜ_Ûòfúðö›á…OÄG†gìÀÊKì7ÝAˆ¯_ý@™~…Íñ®Í1“Žá'SEé˜èdyï,*#Ž>=HK#Ë.jƒ‹‚‡F‘IÖ"«íHf8?¸^9ˆªÇDKÉcˆtPÂe”bE‡0z>²§´ˆÒÂcJrL4waZsÁpþ îçD/j?uÆßîpå—“Ã]pss ¡/ó#‡µ¦GOƒ´~„g½äêúùÛùaýþÉ››_]x{·´»u×ðòúÏ×¹þè­_hÅ-"Ñ“ûƒÊ¸&4ðæäWÔ‘–}°êòùpý§ÛÏnœÅþ3=|ûæëWöÅ][A< w@x¤(”A¯°wsjáw¢¸¸{[>ûâ®MË'oî^½z~9<›VÖèéŽ!1!×y·Z¾}õêíÛ/酪Gëµ_Ûökxó§‹Û¨9[6ù ŒèÂ@f:–”.V' >¸˜óHvp-ŽìøýáLøyÅ;«Ùj´¿3ø_"Üþi¸÷”ü÷²ÙéØFC%lÚ¼ dè6Ø8«¤m·Á&¹OiII-–34ê¬äZÐ B†Z´ìå…Û¥G.y‘:¥Ú5ÓLRµŸáPNHþ€U!z²…P´‡S5‚ ªjÉmžJGUKSƒmÆî†OÀé„„ ƒŽÉVÊ㟠™ß'ÒÖ2×)XÏSAJ鹨e‘)€¿5:n”æq×çk"u©¥ED))FIæ™J™öNP¨=öÀ(#œ¢f,ŠŠ©qîZ²Ð'Ïé–Æeš!EçZá rX8gµ6k;%²ç…ëOäÙó‚}:c(9…žrð3󜳄ÙLrÃùT ?—ç—UmwË„B F –+MËRe™æ¥ ‹A¦ ×>!ÉH ­¢w9Ñnêj¼ÔejFT‘«.¾’k Ü£ž¿däþÆJÀ± /ÈÈ 4íÆÛPѼ `¦‘yNê ð‚rë„@â Aך?ø"žÈ¤ÝP6ãÏŠÿ´ ÔŒ¿­•˜mZR?#uMÈ­Qþ¡tõ¾‰¿¦ÝŹÆÅT¬÷Þt²Õ*´™RL´ô9ž€ZéÑå3`"CYö‹+%ø½,ÅP¼,îŸóܲE?…pÆ´>gc|òŠÛ?ÓÐl t Ö´”QY- `-€£æ9ê’Nà¦õñ(Â!3,Ñ'E5ïÖ,°ÍZrÒÖSiʵ¡V –ª4ËMOŒZÀjaµ»l/­/ &0‡9 "\"Eí³%bé @ÉFF=Ížr!‡J ²²Ý°”¸-±kœkZ Ë®½Š¢ŠÓÜÛ Å@ qTŽ«J„F &`»qiâ9ÊblN©µ.¬Ë’4ö€´µçœ)"n&¶µGéoE¤²*»q©OÚÀðz×–*òÁ¹*Ã<×@è'™€ž¼å»¾ˆ ¶*»q‰§&¥.­5E娼IQµpëŠlï¯)AtõzO¡bÆ|Ùåû`ð<U_êK™C6muAx ó Ôßáó—-"ƒ¢!F)ìò=‚<Û”;ÃýkнÇ0E—"SªrÁøÉRFU9#‰q€/Œ(Cµ<Ù‘åë©–9–Å&¸UŸŠÖ ÄÔAªmäâÞX ‚œO8ªVSx^ì(”¨Nm ËT¦ ÞHû€d 9¿¿#ý}ÍÞÐâc·“Š5[«riR-Ouʸ‰Èš„>¥¶H†‰Q·§ ¡ÄžKÂ%$g6¯þfã/‡K’± ®Ö´>=v? n§"È…¥¶B½¦yî¨r¬ÚÊÂÓ$HG#þØš{‹w8t‡ÏHõ©^ò~üõÁ¸>ˆGæ5!X£*U]LèRnñÖË{ endstream endobj 2087 0 obj << /Length 2015 /Filter /FlateDecode >> stream xÚÅZ[sÚÈ~÷¯Ð©S•’ª–ÉÜ%Uí>`¶6Ürœ8ÙRê€p@>»É©ýï§GW±`?ØÈfæëî¯{zzz„W—ÁÅÛšà†ƒ\)™Ü6FŽ”†íR$‰ ŒÏ¦DÄ*QÛ1{£a¿— 'ñ }ï%höm8NŸ~ó·Ã¸oQlŽžÑÛü›oÙôÚpeOèÞ"ØŒ¦Q܇aK×”Ìú#øý .¾_Ðd¡ã ‡r£?¾øü6ðÝïFÌuŒ?Ó‘cƒ †gð<2ºï/pn!^µ”Û+–:6’‚¶$ÏMýB©Hµ˜O3>—„æ¿ÑŒiå_*ݦ¹’tcÔ|Výnù²î…ÝV-¸µ6Ë/l5ëáØüz½ÊMà·šRÌ/Xàð²—r÷Ÿ§Ç–ÍÞTqc{_SFAžR4ÚJUzó›’ô¶Æ°á‚éT*Ó9¦HdgVc†³QkÙÈæîrŒÀ$Dí(‚‘+è|Ô¯¿jpJœ0D˜k”Á" \uoÃZ«SñàóÒÂv«ë+j”™©©k•D(@ÐTÞ?õ–ŠÂLƒÜ#1[M¥Æ& ©ŒçÏU¹:E‚gc¹qŒ0]з¦¨Ó(wßi%”!¼$}‡k¸äë®Ñ°± n#×ݦÐs~L§ˆK Î™ÙÑ㸈ØÎ*/Ó(ù%Ë9‘ŰùWNûÙ2R²ÕˆÁlÄ›7ÖÂÛËÑùwÖóÉ´%\ uÑ1ñº‚Àox­›`îŠÍ5ë"¯-ZG§aŒœÁAsí¶D.†”ä˜ÀÝ¥+¬èì•}o\ßÎE뜔œ7WùÞˆÀ•Íèœ ²vGm7-Èâݰf9°áùõ-ÁI˜„¢bm}¬Ó؆qü ÞÚ®ð¶LË$ì3ÄëNê4”PÀ\¾¤uVޤ+‹…tÁˆÞí£m1.8,µcvœåA£ü1ì¿yåAX÷šWÁµ®>\_œ®NyçWöE€”r5ì‚6w:=¸sþ¥Òj´;àô¸ [µÐk´ƒOaͯ{Ú¸·‘c/æ3®Q¢ ÂÊíH ›—â%±ùã1D÷³5¥7%Hd;Ú)‡#ÂC“ /×XAžÆ{Èÿyýt?îåñõ`zk¸{§¥s‚9żs„Òía܈Æ*fT7›ðòоÿYN£~ªÂ¡òpr³YjÊ•é9Tî%*juÍ <À¹‹ sÜK è5•'Ëɯ@~[P'£‘¢?~hLÑá&ÌçÎ'¾‚#*Ó~æD˜|˜âöæ¬W ½;¹¾“?-8¬÷¦Qe2~œÄQœ4%‡Ú…s*—¸Â#QÛ¶¦— (’X,KÌ;gÚ0mQ3}ÿY¿ãÝJo4úš75j±ö ™*£4ù¯Ëf2h4"¬sŸ©´!Ÿ#×Yçy9e«1îTMãJ³?‰gI&ô)ž âh þbfÿ[oªMá AdÑ3(Àƒ¹Àu)ÀºFˆt`—de„£(Þ”³Œ¢X®7g¶™Œ‘<ˆfóúpÅ4øKošM‘mÅŸ›¶U`ä0§¬÷WÒMzÉÓL{˜„Ó fGdˆY’µèžúÉÞ$)"šÍ`‡k[<ííAnégPûš´ÓO˜¥O` ä¬1ìáÝún­:$ŽƒàgQ. c i‰ìªKs˜WñZUÕ׬—DûLňR¹ÃÔ%Ð>k3¤Wñ*¤ò=vJQ{‡™ aÄ9½ Öé‘Úªöh3DÅn»û,Ì0^ÈÂÂyåu2Iªqš˜ (œ?a¥WPß•"íƒêeDSE ß§€}KÅEx¥s”¡¥HB!)Ü9Uhû–MwnA-ye«¶ÂÃá®ZŸvBí¨¡ü±?¦~å6_ú¥%½œê.G“¯Û4/Aå@±ó+dõÆEVH:>؈¥yŸ%íÑäUR~≦Ùð©Ú4Å:3š¶L>â»ìô¶Ör±ù©Ynø•ðºÚÑü–yg¿ìoÕeç¯rú;ØŽû÷Q­º"ýŸ#HqÌJ«!ÔPw[^ãóÑö›M¯º ê¦Å:KÏÛJ‡‡ßYt;O ¯êíB< ã²¥Ê}'úœQ¥o[#7¿Ä_ êÕêùzñB~y®W!¯îüö‘to„ÞÇàP²Ú¾o·"m$_üŒ²Z#›7 Í9V2d‹EÁ°%› ÇvO»Ð6;šˆ°÷¥uñãuüVÕ¯”ëa»U¯«K—Â¥²á¦ûiæyÍŽ.åa)Y]ºt* Ò2=#åjÝëÃÍVÓ{ù,®iqª«˜äJ7V‘6÷¨t †5ƒ°æw·êÒ©ÜÑÞd1‚$]´Ýë…qö¡[´ÄEtYX®‰zçuš^=¬vü™+6e uí¼8@êÐ9’œiÁoºsLê¹6s²®¨@’¬º<ïæB¼%‘XvÁJºË:Nevò^áq»%œ ¶|SIoˆë­!ï˪: TÖ-·}­KÔÓ;ÑKÄ!HhÞ=[ŠÉÞÔËü>¿xVíƒ_Õ;Lj¦Ï°º·…@˜‘"//Î_ËTLK¾òZ&ʼú¾ŠbUxϪé[?²çê$ígÿx€CVKmCÅÿ¥Ø÷q endstream endobj 2012 0 obj << /Type /ObjStm /N 100 /First 1010 /Length 3313 /Filter /FlateDecode >> stream xÚÍ[ko&7þ¾¿b>—‰}.¾HlU@ia+­ª•Ç—²¢MJ6+ ¿žç8™PXH&b+µY¿¿ÇÏå9¿>K^Üâ³âO$kø…Å[ƒõj ^BšdIîsÀsGöµ€~lTàÅ{?û-Õhá¹ÙÐ’9.¢•g_Z<óìƒPŽ&9âX sH˜}˜Cýì곃Ì! LTs„<ÇaŽÈ³sÄ4ûð1‘õ%Ì‘L@N¶N?ûèn 9ñÈÉZ‚–2æHŠVž}a!/s\D+;´ñìËhÙ” $&ëË­0ûh!ñ³sˆÎ>Ì¡ÎæÀGRÁgs1|ª SžªØ•07*.Ø yô%gßðè³% •ñŒV^„0l£D¡+´ü"!Ú7ˆIjßHud߀ÚÕv -]”£)Te>‹FE+-šòün^‚ ö‡9Ø/ÁV‰-AÓ| ŠÁ$xÈ~¶t‰nª˜Ã‰M2ÇÛ6¿‘–¨2ûò£3yâleİÏd‹A‹–äÃ|ÊKb¶ïÊ4SÃKm½XBJÎäI\Òí&CÙÙÏ•c¢Ìsåpƒ,Ñt?ÈaêjÂÎΧØ<ç´ 1ˆó9,Âæ€0ÝÁ¤cŸ¼KjSÚNû[=™ñzšªµÝô2×cþäo¿fåS°µ™9â¯I0—‚eEkêô$›m:UÐÙk^•&²éV¦Êù]Ï$ÖkŽÅ¢ôâ“O^\|þ·ïúrñÓËË«›¯ßo7óó¯Þ^þéÅÅÏ®®[¿þÒ!*¸¯.~qñË‹—_úùáÅÅo{½Y¾Äœ«Y‘g¿f›'¤5{sW¿ŒúéòÉ'ËÅëåâçWŸ_-Ÿ.?úúúêýwoÞü¹Ü|ñö»7_—ÔC^†Ë¾yÒžB R›ï5ö3ýxùÉO^à¿s°ºd[V†‰@‡k2_õèwÿ-`~˜éo <­'.›ÕèÊ5U¬<¦Ž€éy@%øU-`Ü Ž×hæôÐÿ§Zó*μfµèÀ¤«³œÀ+âäcJj£äYK-ÄÑEîD%t-î5¿û0Ðh‘6¹•áð1­¢ñ1˜)dM¡¼m„¦p!(uŒF@D'î}”ÕrÖÌàãŠàöÊÿfã?…Z²ZÒÿírñû?|x¼&D’äàÍH’—ï¿ùæ«ÿ88º9Xñ/ÕÁÁ"«ºpp0‚JtGax‹Eðö#RcX^Hô ºu XÈèä=",Á»Uò±x ¥vØ‹Pî\S,µD)u€ t>ó@ÁÐÙIÂ=Úâü“РzW ²ÅÜC©iP £·Øàk4Êùº•‹J2 ð(Á~åXrhÐl­\«=ûQÆÐë¼ÛDz†¿`®þX³¬Ùó“Àú¡.ÕZòà¶q6 ï ÷ÞÉñ4ÅÎç,œ¥©h¤ŠÌ‡ÀŽÑSÍÄÍ pš®9Öž×H¥„35«+ÿlg@Åó°Üu .·‚ëÜh©A=)E"äµð š ~òE5k4£…§…ƒÑ‹6…¡•´7µ5Nº…¡íDÕº¼Ò|ùs‡6蚑Ϟ‚6!iõæáj\·Ö[qÃó *PÙ¤ö º°D¯ó@‚ÍçÀÉC>v‹ eI,a$AA¾«Û¨tÔÂg†Z€Kî¬8$Síq°m«-$l¸xe*Éu–-hã–³ÅùŒ—pwúgUÌ€ (“Å.ã3¨-ì{‰àµÔs5ùÍ#þöZ·“ù ¡ÔoV ÎqµºB3«ý[´ïn®ß×›ß|ÿº¿{÷öêòU¹.ß¾{óæõ‰ÎiCq‡Š#¢D|Õ: -t”ïðþFà0™<|*!UùÚÙ|Ûtˆ¨ó„ç#¸²˜™Zþ:®Â—Wß~{uyª"ï¡%3F;J„›'T¤TÊDZ}ÚÇ7å¦?¸H+ÛBjï ¬½%‰ÇÁýê y`šW¶ßjoâìN@^…'{ý<Èdàv4³*Ò°º¨Gë¨HÉvžvÇŽªaúáù E·Ñ]ÝŠ´P¡Ô ¡Ò"µëò ÚcÚ¼¿±ÚÉ[UDü°ònÊÍû“ƒ¦W›þ"¶åô šªtBýàZôŒ‚ÁiïÁˆX¯  …PB<ƒêÕîx(Š]a‡Šò‘²WIÆÏíV¢ý"Á®'1x­¤ð°£--V°ªÊØ—"‘£¯Ä#'¯Ù†´¯±3Çùj|_ŽØ‘³ýôèÌåèV8çä×= j(VgŒÂÒ‰ŸÁ”(ÎwèÞ^¡ýlG«úÿÙ«3Ò.¹ùëšù:’å4?ìãh‹½ *>ΡzÔM¤A…€Ý[wùÄ0«¨«­"º[Ž]#O^°€ä …]‰Ü*IÍ)+m%m›çS+×x›±žl'”¬«ÝÊ'×­¦ ›Õuôû4øwŠ“F endstream endobj 2207 0 obj << /Length 2596 /Filter /FlateDecode >> stream xÚí\[oÛ8~ϯУ ¬9¼_;í$è` ´“ L;0\[MŒõ%cËÛN~ýÊ–%Ù¤d*Rìvç%°Ї<ç|çJ G÷Žn®~¾»úéZðH##%‹î¾D #-e¤ E’Dw“ècOòþŸw¿F þŸ„çÒ_¯§³¸? J÷Þ,Ç›y¼HFÉt¹°C¯~¹»úëŠÀH‘ýŒZ#My4ž_}üGøß¯Ìhtô59¸`HpŸgÑíÕ‡+\»JIΖy½YŒí Öé²gºæªð ‘Hi (CZÈ탟(¥g¶ë^Ýï6ðûÍUôq „ì}xÕ'÷îþxû~øêýÛÒC0Ä2cºHv?;æ Jõþzz»˜&®G?a½Ïö><ÝÆë5ìoxw°A†#¤2Ý H0•IéÆÌ?`GF“lÌæíÑû×Vœ›Åzz¿ˆ'Ûoã‡ÑjûiÝg¸÷uøy4îþ³y„õ’ò>"ˆ†ifÎÃßÛ8Ù<î˜ÕŸAt·Ÿ+6 ó¼ïsÜîø;_×,‡`„YÎã~j‡ ±ÛãÝ òØ 1J³%–eù&¶Û%±cg$9É÷ß‚ˆ…AÔð—“ð~5¢fqIk¢Ö`êųü"$ýÛܱ%­4íK˜ÀIÚŽ„a_5²¥ñœÚóe+Râ¢P <¸uìÉ0$Õw _»±:äÄ%kOºR!EHGâåDU{[N$Èöõrþ¸²Œs<Þ’§ÅˆÒ ¥.ho AaÒOW”7ö[ܤs8S‚ ’Óz5.,SÙc¤DDÃ2$Æp/ö4iXö# ÒÀªMÓ…pÇ à:Uš€Lâuâ =;¤H©Ðùw;tÓH?ÌFëÄz2“2´+0PŸ­ ›³1ÇÃ/ßÇ~Aê\´ëÄ$FÓ†?ç*‡GYqY<ˆs›9<¸< â…‡:ÆVy¶¨0 QÈV·¨Û!ŽÔ昲\`B¹.¤éÙøQò¡‹:á a„ËØf~ß’ájìÀFKm: ¨Éø`@޹נfŽZKøšæ{° “ÁÌ.¨ @øæƒ–HJÙÌ Y‚e*n]”‘ÀjÁÞ miì½ø3|€·Ü 9GÌ–‹{—4¥„ÏAmìÄ#ÛL·£˜^VÄôDèc?÷zeËAc·»Ó°!&[ëGƒT‘=eIrÒøq‹†8‚e**ˆqi#þãîB´qAŽ•NU@DdÚó©LAbוOe¸â:OO .EH•°náB6LÜÁ<Ê áv£¹fØo^„+D¤j†pK°LÅëi%ÿß§Ý´2×ÞHöyÍ RQ-~ØQ!*`çö­†§é~Û¾U6v­bïZ/‰TT¹VmH³LÒÎ[¤Âý®UðÐLr;„š|†bz›ö¿ .šãÝ Y$‘Èç8 8•¢‚2޽Xð0Nc¤8é8jþÞ Ý²«¦'ºjˆÍó»'}ÒódÀ¦.6ÖfÀó;³ñïiòð.NF“Q2ÚYŽÃ [1TpÄYÓHœažgÄ%u1¦*#VÆ4ôÓ¸d”ŒOóL‚ò)^h`fLKÙ·¿Òll%M6qÍG¼e4ÊhÓàÛI$ýáØŽ°XõóACÜC›…ÆuÍ þá)ÓõŸgËÏÕ;`Ôzv.ÚùŽFÁ¼0:ÜÙ´‡¯ÃÏÖSo¾|®Ÿ†K»êÿö©èÅ«U_¦“øÀ6åµÃäaµ~XÎ&β6j!×÷YÆjêkŒq°.oâ±§ËcÿßRy œ(6M£~®÷Q?+âÜ~óZ àkõs}@Å|@D¥t³úÚ–F¡¾F¤þº<ÞN ¥-Ðw§ºíd9çcžÇà¹Æ{ [`ÕŠÜv‚oÉDSÐ<í-'¤6ö§½<¸ÇR X¦âM{•8[Ú{Ù!²?Hµ)¡"­©”*dH+§¹Y.`‰:?"D UŽNÒN` ª"Lã’Ú¦vE¢Ê•."©”-8yìJ´n Iò‡BÒ)õ_Ø> ;ìå)A©™l¥cã²ÐJ‘ty©Ê.LZ)íWŠHãSÆ—\* Î/ÿ)µØ`m¼çéÝP˜š‹Vz7`Zî·XVYgÇ`p+mÛxn¡`¤Ê;´¬Ô;åU¶A0Ú°C+U‰ óÛªy¨ûuøXAH<îšV}éÅî¶p¶Oaÿ B{@œ7sæ–`Š÷H„ÒQÓ“‹}ÔQÇ=Hö¶œ¡ÝbmIço¶P ¢T‹ ¦®ŠKH­i´Øáíä³R LUãÒ(ËK£¸T´ÄU•!c—F n{›y*kbU‰n=Á2ÖèÔo*¿Âî¨ww†A&Ax½c °2dšz=–uTN͸Ê:¶?¯Îîº^Y€õËjeM|×éu6ÊTèÒƒãʇ2±ÿf?zO&—KoÎÎX a:GQ™«ÞøvÝç¢·Š½õ¢ PØwò¨°kî<¹*‘j©ëßô½w:RËÝ ™n3Ÿ÷µïâùõt1y5™¬|;?©—G18£°®õÈ…¬{תU±$+'Ý&«x4ï°òÌÁ}‹ŽŠƒvé5ÅA‰„ ;ǜؗZŠÞ¼Ñ«†¶gfäyÕ=ïCv-]Ê2ì¼Ò «> stream xÚÍ[ÛŽ·}߯èÇ䥇¬ Y¶%@‰üØ0„¾:B­#­Ç_ŸSœáŒ°¶Û³Éxwc͡؇‡‡Åb›M!Ç.t̺˜Ù ¥£h(T'¯)±ãPk¨c­5Üq©5Ò‰´Ë^H2Ý ;͵ƺDµMéRBM ¡Ë‘¼»¬µ†: µ†;“Z#Ê´+Œ ©‹!E@gÚw„ØP/á°z R(^B“\9øŸ¢ÑKÖq¤Ú®tLu:–äx†¡& èÃ0Ö\û0líÃ0ÚÈæìr']P2( ®º”Ä cè$»1ÆNŠª—¨ÓHÞ.2 |ƒ’t*ÙQ¢všD¼ý,Ö:X¬ÖAÁXuŠ}¤Ð%)ŽG²V]¡r2ñg‰»BA$ÐÚœˬõ_dߣä.§=Šu \ÛÌEEáÐEoDZ3®–Á˜)­\0T<­"c®¬Ô:LV¨#âÔª#Âä©Ó éŠZòRéJVÿW ])䚢KXFñî`R0‰TkEá„n€ð™¢(fsPq³({¬ÜAqªµ0gŒÄû’‚¢$LŠÉ­)BèZ…Vô‹yǰîèÑ!#Õ¶è4Ô¶èR®mÑ™¸dŠÞ8ÄÚ½q¬` ½1WÛHè KÇÛ&ôƹ‚auA5ôû‚ä|z“˜ëcèM`š^Do²Ÿpè‚ñÔǨ0Ô:Y½£wŒ Àøê¤c©`8ìar1’ož=»Ù}ùŸï—n÷éÛ··w7»WÆ»úû‹7oÿy³ûìöݼ¼û:À/„ovÜýi÷ù×±þ¸Ùýu™îº¯!WŸ°B¡kÏ®€Hïâ“ô3š}Ú={Öí^u»?Ü~yÛížw¿ûöÝí‡ï_¿þ÷p÷Õ›ï_;ŒÙüÃV ”g™§0Ò2„5ëÀëï»O>¹ÁNöy÷5_…¿v»¿ýý«.•Þ …ØõöÃwß}ó‹s¨3çž0}ç5ÆH<¯qŒ½ûų§b=&úÌÆ¦=Lý¼¶™z·ókéázÎl,©×r¦r)X¯çŠ¡I{µ3K5¶3•˜ÃAŸÕ˜ sÂgJÇs‚Ýò¼ÆœúÄgÚ©ö‰îq~qûö®.¦pHwTŸz¹ËØÊö?8TgwøEî)Ðøð«¸ïj‘»/Ý?‡v/ßÝN¯¬èn÷òù‹n÷åòÃ]wì{ï$^ß.7»ÏÁcy{÷Þ7âŠæ¾àýí‡wÓRët_÷çe~3|vûCW݇í »0ÙÔô>[š×)XÊljç¬QÇ̆…Ga‘˱m@ÔS‘“08ÍWh±É“'—}†÷Ø"z_ÕzÏðkyÌŒÒ: £-‹Mˆæ/Ç–8ô$'Y 6»{ÛdzFü†tòÈÖC´DvLsZ‚OëLëŠâ4ζ”9–4_Þ`Cé=–:,lè×c°”™˜‰bÎzAx²Eô M@ÀÊŽd%qo¼MöýÝ»ÓÝ_~|µ¼ÿæö-Èá_ïŸ/ëwÃÝòúõ«‹Ïx*ˆØ£žf<$„°×4ãúñQAA\³Eô gÛ!º(vx?ø=€ïðñŠ’{dJ}ÆÌ7¢¸W‘M¢O¯jŽ}ö×KUÕ˜R¼&Uý‰rõ{‹èÓ« ÏZÒ)­S²(_SÔ—{S9åÈ}B¿EôéUEb¿#yPÞʘ®kpwªîVa«„(¥PÞ$úU£®ˆ¡TЬÃ0qž]ÇÕ„òòzÉÓ“úÚ­ÉÊ‚Ô>ÈÃØ>š ˆ+`©û¬_l [°G„hùL‹]xÑ¥ë,ƒœò Ug¡²Z™.n±âïWãÉb¥hŒ¯Ëb‹!2?æÅÂrBX>oÏ‚'–ee ‰tž8Ës™ËÒÄsºdØâ§¥ªGYɨWx­-YŸÜkIò ëtà#ÙE»®jãéløžO/*#U9Å‚"0ˆ"×´®|Øó n©œ{ƒ¼Eô'éÀ¸Ì6L¹d<ÁK\$ægYiŒ—´€Ø“Ÿ—îU¥²¾¬@öñ- "Uùè Ew¥R®/ÄjD[ˆµEôÉUeC®âåª2<+ôº&U‘TY9åPzF³EôéU…7Î.¹L¼¦+s¿¿šºçÉ䧪e‹çÓkê7ŸôtÈÆˆ9ê•…VÐÔ}ª_ ,ø©{ž1œ·ü§1É̪Z±Äi.iñ•’-2^Рj%»•5ôùWD}—~ű¾‹DÐZ°äÜ{þâ—*Òu&T ÜÓ)`q·¥é o¦8Q¿ï!'[Dï«Z"G¤® Á@ “Ž‘Bé)&]h†K,ˆLü–þAV`ìAdÝa‘yTu2*HfèMÀ·V÷¬ î1ìÑûªÆ2ÀïMV'*ºZ\ MS×µ^-‚Ôz9þ «É¿>xÛÇ·ŒT‹Nç‚dì¯/¯Ðì¿©@ãÿß ú“¼¥è¸¬:Ž”‡1Ršf]b¢¸L¨ŽvÑ·ƒ~ÍŽ²RÖÒƒØ>ž ¸³bwZ¶,ÖçÄv¢iYœ#Ï«]–´˜Ò2YH4]Þb=‘µ,!a+:½`øä_@ˆ ü€¸?Ø úô~S¯r:"µž‚]¡¨ï´üÛ''š7‰þ4Èâhƒ„¡ŒaŠ«¥N@°Iɯ®^ò\sø(+ÿ'>ˆí£_ý#$9œ0<¦átURo5¢ ç‚›Dû6ŸW[úHD¦^éšDlIþ‘å( ÁMÅM¢y?bèŽ&üÂÍU!2ÐäÇx²î?ÒÚàù¨÷½< õo!Žú…Ô›Æëóäðbˆ>üKOøHè6ˆÞ÷s‰¦£›Á0cC—»Á¸¦¼ðPæËzò‚ˆ®ÉÊÜ¿O}ÛG÷äÑÜ&O6à‰S¸ªó=ÿð<¹¾ÙáMžíÈ#Â5 §7¥Ñb3]“#Š}òut ÊÂu=m=Ñÿ§wØ endstream endobj 2248 0 obj << /Length 1533 /Filter /FlateDecode >> stream xÚíY[oÚH~çWXÚ³[&s·½oin¢›¤-¡]©!Ç à-ØÄ6Ê&¿~Ïx°‰a³iUiU©ŒÇs.ß¹ùœ vÆvÎZ¯û­ƒSÁR2§?r<Œ|)/ H§?t>»‘v‡z¾ÎçÓ8 ‹8Mrt(ŸÄ³ruÏíÏAœDmŠÝéb¨웉!?§Ê¬zjÔ&ØU™J"Ø"“+EûkÿMë¤ßºiÐ;d¥ï#Ÿr'šµ>ÅÎÞ½q0bïÜ–'g Î`=u®Zï[Ø"ÄU¤Ü« õ=$sˆ,÷2î#Ê<ëQúc2àê{»“Èì§q'Ùâü¥ št»;¡Íw^¨"†Eøzš–Ú·ž ‡M¼ÊB í’øºìè,ÙÀV£-6÷8(]x½ar«ÔÌž€oŽ&±B¹iàHxÌ/ÍM=äãJ¦slOÉÊ)è3Ö9ÖiðZ‡S‰¨Wÿ^5ÕhíÞ½*tÝBéh”«â•ù ¬LùPŒ/¡½}†œ<¾×ѯL 씆‘Ä{Õ©º4MŽó' cÈcÏ€6 óIÓ§ÎçPå‹e’¿+“ü¦Lú3ÓCŒª‰ãf>ùûç“àOÈ'¿–O^ß9ŸÄÿùôsäS9òèD`ûx 30eÚŸÐH²Õد‚1v/Â(Ó|R£ç±Ò_º$Ö7v'3èŽËË•Œµf„ä/c¤ä½âYÔ“òàd¦€ 57Ô¿ Õ(NäRI\'¬)G>µ…¢?Q¹¾‚`´Di®×Ò8öÍ$Õ¹5ÅD™3ó,ýKE…Ù½§S³º¶¯Kc/â©=P­3çÝË?ÇççVn™ìyQ'_j04ÛñÈüNãä[œŒÍ«ŠpW¼*Ršrœs˜»Åós\€§¼$¼Ö8>tÏ 4&yš~ÒÐôoš~¼¨D¯ØÊdá~šŸÃË´ÆÂ†›ÞÉÔÍ"Ζ<µ¹J‘8–6Ó‹•û´ä07›¹×Ȭ§ñu¦õ¡”Ã(|×ÃBײô1†OzWÝ·—ÿ:–ë 6Õ¨ÆôǶ­§ õûJØÚ»„BKM¸ÓÑò—q°µU ÁàòÃÅàâðÍÛ^ý‹C¨€>9€°@Ô(¿ê )“¾³ÞÕæÁßo a*8b\OºÍªmà꤀U=¦z÷ò¡ê1ÎêdS÷À©lƒòµªYÉ =Çsýñƒ)WîJá[Å'›'§ƒ“^OG§QeŸ†HËíÀ[kµ­àu“|1ÒÉÅPœM©6Y2*o|TföT–¥Ys¬=DÇ×èŽõ‘‰|ýßás`öàäOÅ9_Xxºÿ1+su“›‡(ÍL“¶˜j¸j©¨ =9=7@O¶@@ÓÄ@¸ÂU¿+Ò»Ñ$Ì4V`#`‘¯ï˜Ìïø>ž›Õƺ¥_‹tyj¨/îíõ{YOÙê±Ö(Xs…ÉÿÜLðæašZ9Ëk‰Õtu/ÂŒìss¿ü›„î,%¯üM‚ $¥õÏ™JTK+”î–­ˆŽì¿ïÆÚy®J6Uü\E ê endstream endobj 2254 0 obj << /Length 874 /Filter /FlateDecode >> stream xÚåWÑnÚ0}ÏWXš4%;‰dj€Bņ -aÝÖV( e °®¿›Ø@Ù ]+M›x±ësïõ9>!MA§JÝUª-f";œÈ#‹`›sd9:æ¹#t¥r®Ý¸o‘ “þ|µFVÑ-[=Iüå4ˆÞ"Lâ,TiºÊ7…B$At…hÛØÖMäO•«‚Fðì-DÇFwyä™ÌÀÌ4`¡¾r®G«ä“U™˜ÂkJQÏ? OÚýZ½Óö{-÷RãD­]4‡uÍ€fµñnp–U[mY YرÍ  ªÛ.G}5 Æa ò 9`-º&Œ0Ç,qŽuf¡ ¥Øa\ ëžÿu9{率w gø°‹cFâ šBS:äϲloÏ {},`l½C‰ƒÛ^ãdG2ÈeóR.B%)C™@½UDå, zÓ‰äùâTÙ‚¦0d¬Ø‡×¿”Ç5¬·ÝáY¯ßvÛ½®\ˆó¦ó: íš÷ŠîЊn‚špÿRèðÖó5¨p8ÕqƲEÅ’…sï6›GÁH€oˆ ˜7ɶž¬GôÔëv4àFý8l~h6E?(*@-þ‡âÚCI­ÞE£™)ª$¥C¥s²V„H¡¥$ŽîÅÈO¦³4˜ÏÁÛª£ 4“³ Õ(ˆ-3¿ù¾ª²KªœuÚšæÕm>A:b;lÍWò3þÅ Ùº¬¤áÉâd!³4ñ¡71/c±jÓ›xaŒµŠašj7‘ù% £eìÛ·³î»Ù}~s.cæÍìE®ÏÃkã0Р^lÿ²#Ž ¶ 8.±ºãæèvèßàÊ6ü[ÐM}ímËA¼+—eDÉïut˜)³ýÄt¸'ÿ3¢z 7Þ%™V¦$õ·Ìx! ¬v,"`ÎÔ©´¦(z^§ÞP]+­¥Ù ¯vçp)µ²]«C¯è´ÄóYà‡×„èp1ÄMISè}O¯¥z©ôŒ é ¥;WåïYý<Œ'oäà.\øŸ79'ãÅF™ê¥’õÛÀ÷–s9IÆÅ«)Șÿ&Kù~–‘H#)›Õ®¯Æ01è!ÅG\h‹›Yƒ&31ƒ®—*9 â õAyQ÷ÅgQVñûIF˜Üv?n™U¿ endstream endobj 2228 0 obj << /Type /ObjStm /N 100 /First 996 /Length 2555 /Filter /FlateDecode >> stream xÚÍZ[o·~ׯàcûÂCÎ$`Èn¤€E›À0öšM¥T’Ñ4¿¾ßPZY±y…œ8hv9üv8œ—r‘å¢![qÂSç” µsj0ËN´P©¨)䔨©²E!³¨S²ærJ ´vÄWís-Pâ>Ó(ùRµâBNaˆ2sÃ%û¯ k×ê¿6 œTœb ¤„5šæÖÕÀjìBkàÂâTÜDÅ•œ—3(ë<Èk¹ó ¯içI”:OAI;e ZçA)™û¸ ªúj¹!f,ª8rÎG :*â ’:kˆvÖ]a rÖÐ+åàWcç xEú[ZÐT»JPÒΫSÍ©Ô\§®X-¥ë mBX#Q°Œ×ÅÁ ^§$˜ô7ÂÖbŸ§`¥ú¯œƒ5×8FÉý-±y…SÿUB‘®IÖP k°L5ç•Pšo#aCkV#,T™')Tu"É¡Zé< µŠ¯&ZêRðغ1´ÐØäÄð¦ û2Áò´ "›àåa"øQÅY˜¨˜[É¡p4«E¡òWwÂO0‹”'&P­³4à\_ÎkêïŒmƒí—΄Q'7,pqwsPçªZ0õcb®)0œgŠSNµ€,P“iuʧ§ìò+ù™#§| SöIP˜æ”©¿Äç”}¯:…%!’œ ¦8%åäÉ““Ëÿý°„ç§§g—'‡çoÆËþüÕëÓ>;;Ÿ—óoü@zyøóáËÃçßæþprøz™.÷Mbª³Ö™QaÛ8Ú‘™1êÓðäI8<‡?½8 ‡/Âþ3\þôú‡WõŸ¯†´”–DÖ\—AóÐdljkÇš&^Sûcøä“üýz˜8%Ñpˆ¯q²*ð•{q^\ž¿™.ÿúÓóåââõÙé³á|ø÷ÅWßÈóW¯žئ?ÑèÎqÓðI{DúC,ˆîgÊî¬sT»JµÜ ô»ó³7?¼z¼ßïwCægJælm¶¼,8xuÅäQçÑLæã+•)6„ˆ­ ÁäiU[lAÔC(<_„'í@Eê.­*<ÀºæêCìô ¨†’À×áð÷| y*ÜšrßÛÓ7ßÿò—Ô—ÂÑ[ûj.Ô†ûgä¼(¨w ¶Ö"’´ƒ ç_vÂ0ÀÝ C+j`“ƒÃ;a»K17…}c‘‹5É;'F{•Áù“Ò¾ÁäƒÛNɤ–¿S„cR÷Z¨g¦iç–¢ÛNÍel¶ÒNexu“ùóÁOÏN/û‘~ª*•«YO±¥Ôë‡Þg¢výDÞwÓm ™?]„Èóó³éù?Ͼx/–/ÃËŸ»¦gÃwËÉás¬¼œ^^x­Ïwtqöæ|Z.®n÷—e~=|vöcèNK›F*pÈKª§øÏ†sñ®[ºßýÞÖïR‡Õ¥×D݈«·é]Òk"omo„\´Íâmo³x›ÅÛ,Þf±n„mDÙˆº›dÙ$Ë&Y6ɲI–+É/í‹VÄÑö6Ü#˜Òã‹÷ôêÆEt½è{FJ›çqhƒwõSi‹MT4é#>*}ï¾oj…ø¨•„ö#}v,í-k‰Ù†ö£ç§(&bâ·íè¢KÊ©é£ÑoÉŠÀiÁQ2,6˽8ßUê°Î©-еê”UÔ”- kèY  ÃmZ$JžG܇ö¦y~¶^þŽøo˹7Ñ¿<]Ï~‹öy!£ü¶ËW8yŽú]!†{ÿÉ3Ü˽@ßëói‘¼ˆØ¼äI˜tL#™:x{b´ãk5ÕÞ–¾Ñj.±Êctü©D¿ãDÁg9ß‹ó}¿Ÿê\§ZRcÒ$£L)u†¯ðpD¿_rLí­VÙá¤Bûý>·ÚT+Ô¢dzØÅÖ5Ñ"Ú`²ðõ5ó¤ÃˆŠ×(×!¿-á) ßrnöŠØU[~„ F¥ƒ5¬Ý ô]­r¿ÛÊî×ܲLOeXiǽ3Euý»€kµÂãÄ–öcÚ«wüìFµB[„öãl¥^³lkˆ *j¹}6ljheŠ:Ø;@fá}]ôiÒµÔyi5sN5y²Ño+‡|ÌëÉ~§ßìF©ÂÒª÷(õw¿E1dÓ·òTdÈȰø‘]Nº¨EE-ïàW¾Èåc¥}]¿4J-Ó‚˜J§¿æ¡TÑiTÆãZUÞ´ê t¯R? Ä5”n¬êŸ¬ÅF9póKõ}š]Óˆœ¿ÑŒ5-S×6Í­Ž¨êÈÓ?¨È­¡FåÀÞíEÎÂŽ€Q·ÔÞ3Ý…¶ŽË˜WÍsÁŽHðÕæu¥ª…Û˜¦÷º¿RÐý½=xkŽ"·¦;ûw ÖV‘çè1+IôoÑÔïqïlòÝ!ZJ‰åÎ^ꃹ +Kyç`“xg/üöX”öþÝêÊeŸd2¨ƒ?´+¹xc;d讦»’±ïw7^of‘˜È?³ó«3ûíÚ˜‡§þ-,çüëšš*ï75•~mSÓ¿9¼êj>f-#8y,É¿üeh•¬´/®ÖÅ–’¡)ÏPæRm2™æ Ÿµ –Ñ1CEÿا"zX`Âxôž¼l7Eåø©Ûƒon©€•䃽¡ïŸa{B‹ ±O4RndÃüÁï^ÝQÁÚìï­½v¡‰–ý3eÁ©÷¨w‰?õÖ>¨¯PQG7¸yÛ)Ú9P{ŒâÁ¿À!ä½Zê>ÑÔMïCÚË8É–«x!½O´eYnkïÿ(TÒ¾ endstream endobj 2260 0 obj << /Length 758 /Filter /FlateDecode >> stream xÚ½V[o›0~çWXÚ H«cæ²·¬IÚTM¢6¬‘ÖV‘&E#g]÷ëgc`½%­4!ù†ÏÑù¾óÙ>,'Ú×@ë ˆ <è;Ž‚¸zŽ\ß„A®ubãÈt=®ViRžäYï)‡Å]²,G’UÕu’,4L¤§›ˆuª?wÊ|¤L.Yl`¤³5ËB±„‰ëøºã·Á™Ö´{ ‹èÀ»h<z¦ Â¥v}‹@$þ-ßåÎ%°‰‰m‰q ¦Ú…†ÞDè`ˆåg‰XBúÅ÷ùpôOd@K€ }aiÀ‘… ¾2ü±8ɧiVÎnAÒè±rd»0„#Ó„¾g+GÃŒ³…$e-ùÐþ¨¨ ïXÉçOÙ°H-Ɔ…t*茔ã>¡‘i· Ù5´ó‰A>›÷úÓ`>êGy>iXïÀbòT¢¼}+’l¡€Lg_Ô`œs5`Y¾YT‚Y%Y¶…¼dË\P#p?68Kr±¢²ÿ!yÚÄå_¶Þ›ò”ž×™ñ^f¦MŠýŸHÙ©S#õÃGz·gØ¢•C5Ÿ— \õ/‡+D¸îöºp¥ÜÌšg{ûž‰bß d†,ã/È€¦i.®¤ÖÉØªbÉ8(§¯pCZܸ57ãÉütvxþ•Y}ü‘ì«þ¢k`S¦¦œIïJñœ…ü€ ÀkaŽÅéU)W9—8>=<Ñ;_AÐö5rk¿?‡ü8ߤU>³í œÓ°:¼b†fªO²‚Sù’ìË…ßâbÔ»,õþ.ðÂøªÚüx¾ŸH<ªž„_†Iäö®ü›¨…y:Ù÷$hÑt‡çïRºtr%›ïÝžÀ”…¨#*ÈÔ¨á®Ùý&YW•B‘ÇüÁè©XÝçæ-Ï·yf¯FQ En/é&-ÓR-»2Ṫƒˆ,|Hѱ-6hºŽÝ(6lÑ•ÈOXÆÖõUFSAïå’‡ß ™+qëÿâ_saÊ endstream endobj 2264 0 obj << /Length 715 /Filter /FlateDecode >> stream xÚ­V[oÚ0}ϯ°´—䡩عìhWÐBZ¤µU”%†E‡‚Ó®ûõ³ã„&t£€*$|ýN¾s||` 8×¾„ÚiŸ`à™¾ãØ œšžã×·L0wºãá%°ÅWöö³95N,×Ó»yR,(ã1Ïr&§j½P{Ô˜ Ú zžéY$ íî‚TŒ]è{๜¹˜Ø&Á¶¨ÏÁX»Öà»Y:È„›4M$~2N„P¿þà'ó9í»¸¦ïB$ƒ!8±¡ ‘¯â>¥tš1ÁÅiD•{H ÀR0Ømä `,Ëô=¬`ºÔ°¡þ”%•*ËXƳxžý1Ñiª Z4d&ž -Üb`5Œ'Ñ·¡A >‰½Á1lJ½a%>€ß¡E^óŠÏ:c3UO>« «)Ë‹ÙOU_fŒ ¶e}AùÊ ê/{Ó··èÃèb²ƒ¸·ƒ¸ŠmÒF@;ÈUyÝ1õPµä‡d™RN~Àzã·„¿ã0ê¾åÇÀP?»8rù7€aØ M9ìý̽S޳¼˜§[†ˆ9“ʼ’+ck3±?þ/ i CÞ 3èŽäf¸=Þá¶%õŽhú]™A´ÄîÏž Kœ«#âl qŒo®®†#Cº¯×úƒðHkÔH5JCä|€7Ú[$Ý:#Óœ®·Œ³.–K)¡ð{Õ“Æ> stream xÚ½Yms›8þî_Áô¾Ø71á»÷ ÛŠ­Ž /ÉåÚN†Ø$aÎ6)àär¿þ$&o$¥×ÌÔ’Vûì³»Z„ÀÝp7íŒÜÎñ‰ªp~¨i2ç^sºÀ4Ó‡¯‰œ»æ¾v5^êõ%}Ðýá§ÿ†wümï»û…S™WuÄIÃl´ƒÜÎŽƒ'²~ )ÜjÛùú]àÖðì 'ðòpÀ=ä3·œ¢‚0%¶áœÎiGxS?Mä…RAþ¤a¯/ ‚Ð=ýërÙƒV×°…“©u|¢«œÎuAÌd\_xe@—ÿ¶®Ã]Ðëkt1Y—w¿ ªÐá‘ÈQôŠ. G’yÆr9xד„î}OR»þ&\›Ýù1èÒõ·AÄd(Ü‘ßëýn•†í­ü͆ìq€7ÓuÀ«²^…* ¨–ã^.ílkkŒçÙ¤c9‘UÈ+ˆúvЈT/ w7}”¤´G« I>÷ú²¢</mpå¯2õÿ&#Áníw`º€ÚÓ§æ â8ŠÛK,íåâ²<÷ýÆa K‹¨Íüº ˆ”d§á–ŠöicR Ã3o¹´rª]4¹r&Ä—çxŒLÕöV4^ôºí•¶©¥Lµ¡Ìàáqt÷‡7·i™«<0sp’ è}IdÒÅ&7¤9Žbˆ¨ÜCy2blè£\PBÛAÄ÷Ášod­ ,-è¡¿_·h´ÍÖa’ÆáÕžd† ™¿[“Æ>¡Y7¤O’h¯‚Ú¬«pçǤ}ÅÛ䈴Âô–´²TÈFèÉñ¦Á†m ÛFëð:\å>Eµòcª?œoÛ0MŠŽôûpÍzé-¤mÚ ´Í&zÈOެ»Švë0“›4# íäˆB{¨Ì>7ÚXüO|w…”&¨d8ŠÁ+ÏÆWv>Õ}n­þ}’²8L}æŸYþUt_¬¡‰¨†L“x]SëæúP.ŠÊ(Ž˜V!Å´ ™Ö ]Å£ê%¿K­6>Tb1ÿ ±D¤¼3^ ê¦˜õë‰à)Sdë=#óçÉúÈAõÒÿAUa§&¨´6P:Õ*?ªø1KÉL¤M¨Tƒ8ô7És ±Læ™ä&0ô6`T½o´í Mw7ƒ°´OaÒ¼ºÆóU =·¾–äÂ4i„nØNzW&fâ„‘O÷*(Î~æÞù vk˜éà%Û( Š„7+ÖàMP5Á% íàºmêœD×éCqn²„<º VY}À´‹B%Î*ƒ]¥PH’¦(ýŠW’کܦwDŽuâž6¢LG—¶u†'ˆ¾ˆŒ.ȯ;£ÓÆÖòÂÆÓ}éžYó ²éRܰI¦kã‘çZ¶óJ‰RQ’ÜF­÷Ép–O5 “A.mäÐyìž/–sÌ ƒIlÃt1r艀ÍñÜ›`sJû#v™bZn“LRÚ7Ç ì2]ë¨ÆË (Îò»@öxŒžc÷¢f£ìš…iNÈ=Ü›ØZyS4¨ë¶‹ÇÞÜ ´,={i9`á¨ìŒç^  ÏøatPŠÏIrfÆ|þ¢7Á×ÊÛ£un"ûÐåB„¸bïþÆhŽJýw‚m4v Ϭuǹ@ïü¨6½ lÎq¶# /ŽhØGOà:èÔå`.Eb,Œ)ªÜWÿtœ ÚÉÏGZv½ìÙhQø *Ç9.v=—r6µ¬I-¿8È>ÃcäüA¶œZ`zjFÙ°ˆÃ5j >HLE6:ò\&lºÈ¶½¥‹-³¼Ï™YçrŒh°Lj™Å2K/n€RÚ:êe_Z:‹®<ùQøç3ÓìÃL’§QÄ•‘:vŸ_Ï qÜÈIe±lCÃMçxŠÌ1:TÍÊžc•”6vŠuجå˜sƒÍ«ùz‘D½W/'˃]–ZÉŸÅöõÚå¨Lù jLÎpáˆOÔ‡cÅÁÕC° æñ¬šž]íÉrëW{ò;k†v/Ñ9Y”ù$W(8®)-+2/ŠrÝêÁ´ç¾ªª*AðžªìcªÆKº¦T>¦fŸO4úñnìxçb_§®²ïK¤=‰²1ÿ<ÞdßWমâL´   endstream endobj 2304 0 obj << /Length 1537 /Filter /FlateDecode >> stream xÚÅZ[“¢F}÷WP›MC_h r©bGv\À™ì­(£ÌÄ*ʼnÃÔî&•ÿžæ¦¨(ÍâÖ<̨m÷9ßå|ý5ˆÈ=p"wÓ¹ö;W sŠ ‚8ÿž“EA!„“U(ÀùsîCW{Ÿü×¢_!Lèºtt°X†=ÊJW_ÏžWaOãÅ:J¦v ¿ówЙ"¶ˆŠ"(s³UçÃ'‘›Óï^sQU¸Ïé̇%$HÑ÷KÎë¼íˆe+e‰#‚*#¥l%‚X˜)Š¢”ZÚ)AVè?%nCQöGÜ›÷'¢ØýaqÍÃû^ú!x«ùïÍq0ÌPrvú—)óŽ4f¡‹(lÆÓ¨ £opqça0{\>?%5ì8ÿ>…Mñó·;àðKn¢=1g…ܨòçte÷UÿÕ>uöoÙÛRF¥Æî†Ñ|q_㩎­Ü<¶Ñlù<Ï3ûëS¼YDÂ_¿×Ð+­yæ‹(®çQ+Ý”Ûé7—¯66ƒ[ÃõLÇì‰XÚkÇÍf|¤…?nëä”yrµÂô]Ì3í²y¨Þ<WKR)I2/üí΢«t)T¨r< ÌVÿ˜+"*·ÕKÖO³—Õt¶Yç#Oùk”½Òćá&ûç“âð)N±„Tb(¸Dzµï<T"c@.œ Ú1pž‚³:JÃ'\@@-3ÆŸ’ Wö]³ !Aê¶oíoX}…Gˆ¶Â$iûah´1Öé°©{Çjå¡‚ ¡CK•ÊšR¥oèYD³|Î÷:2í7>/ õRâ)z×<œ-ŸÃY¢žùr¹X=®7q}!«Í·õpyÎýë‰9ÒüW¾¯ÿáFÿÕoðÿ)¬ÝnƒT”—òîœñ@ßáÄÊÖdµþÔ} “óÔá±çô1)z^ΦÇâl.}³›ùöŸáóýýj ç›À¨=%mÍVÄÂìc\$&Àïý­Yf?ênðoYVÄŸ« `=çk~þΨþ; y ÿÀäî/ÕfJ•Ñ ¥u¼ˆ¬pÕ$¡ÅŽu2Þ}DzhC± «y2Uµ|lÚ¶¡ƒAZš,™ÌÝgË!¬®Lð W¦¾Ø„³ä·A! ÓtšÎ±kx^ãdB ³1èÆ Žî \• ÷Úñ‡ç„€±àw!fÔ ¬Ö ’^Z+Óx:XoVÓ¸‰Xa¹1i¾àëæRA ;þ íÍlBÁb3ÔÀøÃgD†ìÈ®vÇJ»O±x`ùÉ‘¼zžÄ*Ú]®Ï«vW¸òî”ä–íxMÏÔуµž‡Mt+1èjl¸¦£›}mŒ½|¸i®_ ´ë‰÷îà AȘèrt÷'‚*‡å—îeýÍ̧øM’,3t²¾ÛG°y^e†¦é#Ã=›Ð]yÉu­ËvlãüÉFamYE$¡T7,½° ¼õ}üyº ûkzI…QÜTji[M4¶ L׺Ó\£Ç UªBxc¸¶1 t×¼5Ü IÕ‰g¸ç—ÉUËvW¥'V)U«Y¼V="Im`M )Y!” N~´Ã$:‚%PÈÔÉ›0 7Ó8ùá&yDåÏ»_‹ÇUzHì~ùú䌓÷l¥6þï¾ø endstream endobj 2359 0 obj << /Length 1796 /Filter /FlateDecode >> stream xÚå[ms¢Hþê>l¼ŠdÞÛ«ºòó²cVÙÍ]rWS¬b¤VÐî&¹ºÿ~ˆ(¾0j²±¼2 ÝOw?ôt”{(g¥ßÍÒÑ)%Š®ŒaÅì*PuÆÍ@*ƒŠÙQʤéVøì Õ^ùoóƒBV©†…˜x’£ÑRÍ,=”  œÈÒuUGDi»¥»¿Òç>(@ņ®|gº ¡B‰„õ•Véc LãÓ¨ÂTCÃú4>U-VTIÖÅDTñ…”Ù‘æYI¹«0~êØ]dzËñ?oùU£u#¾øÅUËäUÓ¬Ÿ—+‰“ *`ñ712E'¾*š@–¡0^Åeã†×kõr…’L=)VŸžßF=ú«Ÿ«—ñØD;•ÐŽ_ÄøOW­O×צY;á§u39™ €LÝÅuCàºÙ8®µZ¼Öl6š‚zB[ "£#ÝšŽõšY=©šUÞø\kž Fˆ[0cÔ%<±5ŸLÞ8åÍêÕYm†ŒÐ(VÏ^€Œ&Ÿp¡\!“ˆ›RB?Ù:Õ?xõò¬Ñ¼0Ïë­©d}/Œ0 *qg°­9yR;½¬šÓAˆ>#/pî=»“Lk÷,?Â"A ¦o èò–”+š^æy'Çx8ÀƒŠñx4°-žÛ–y"‡çVO|~>ËhhmœN×P õ‹«½Ûet!?2Ü:ü›8IäéÇŠ†Žâ Ñç·Éø/3ã8׿Õm¯ãt ¤Ò ¼;q.ç}Ç=r^ „m¿PÔ¯ÿŒ¼Õ±ƒð0üöø(äÁs6.þI=ztŠŒ©Ò AM¥:I+:oy® «¤“s欵îÅÉ̵Ýöð)åÄ·Ó‰É!‚™R*BcÊÿœž*Ô©25<&Ilt|˜Qm"Ž!UcDVZ&@8,'2pžmëó{™‡çy+Ê¡æ}¦¿ {­Ø{sq•. Ë4è`¨›eSnÈ]̳Ašð-O7¢d£K¸;kú¬hT‚ˆœèeD^Ÿº ë±–çz îêxz½K‡IÚã%Âc-ãÃL|ø4´#ÏÈON‰Š-sG¬@3T М'KI÷šÈ‘ô¼sžEÉÑ:¶úý/Vûë©—S8‰ëØ=±#öÏìPlÁAäL’!šol,6Âc?†¶ïYýÃbµ^Îh‘Å_>©c6–Õ>³VŠó*EF1§ãä¨`ˆUáêv]Ë;ïøÜ”ÃÓK®à½ŽŸÏÈïöP„áB'Žo·Ca¤,ŠNzÁJ Z Á ­ÓïZ¡4qﺡ$m=Þǰ^þ~]jM{àyÿ[_ÒãM¬™K¨«Í±ú÷ß {®œQÜí¹Ö#ïü¯¤9dÇc|çQi7JÚÃv;<=aŽHŽ¢À—´ÇØm{Ä*å®gѤWÙQ‹o8Šº1öü 7èw$W0}Çs·o?ð¶Ê™5±Ê»mÕwË 71 o³-Sk6ùÅÕ‡Ú±yÑX½wKŒMòë|ÿï›Iìct¿Ô|à‹XÆTc®†5è[ :ù«QMmÀŽ+âñኣDSÒöºŠ™1]Ø_:Þ×t§¿ïã}±:Ž7ZwÔ·Ât†á Æsü›ß$Û=T)Õdz˜#™-bh¯°eC =AýïòRvQ¿`JÞ5ÆÂÔGÁŽõ?Ç×m‚|D|ëöƒ¼Gµ?tÿj ´}ªý){UûSˆöªö§îYíO¡¾—µ?ExkŠØ>Öþ…kýõ ßw¼ûú cË®öÃäîŠkäpàßIrØB]è|³×1ëµV¿|kµº°/n®(¦oƒ© ½¢øÒ^e)¿FEñFýÕ¸1%o cá0Ù±&ëÄîFÑ]§Ë"Å]–ŒßÒú=:7Œ'.v$AoøÓV†‚¼õÏJ”°MX›X’¶Éc!óµQú,À®ðöò–¬ÅYã‡r–‚MBÙ$& £‹Rk0QücÃTtS¯|0i©žÓ+$ƒÉ^µÜXýLÁJ1óôé§ÅàW&tÇàê?“€»Žçp‘žÛ=ɆÁ oã–ì}ÌÐ̼E/|Qª ×yß+}©(zL7{Ï‹P•‰?±ò3Û³ý¤®‹ÞFûRFàà)9>”18x|º/W ¨ø¼<ÄÿìG«Å endstream endobj 2257 0 obj << /Type /ObjStm /N 100 /First 967 /Length 3021 /Filter /FlateDecode >> stream xÚÍZ]ݶ}ß_¡ÇöEËáÌpHÀ¸-Ðiœ‡4F`H•M½©½ÒüúžÑ^®?²ë«ïmò°{)‰:œž΢Â2„!Fƒ¨ÿ–RA#ÑM†dy`ÂÍRÐH¸‘Ñ“‚ß0¼¢¸‘ èBTÒE*aÐуñ”mHÅ_#% näÁÌ{2Ù`!9±cèP€c! EÅo„¡”rÉò@AÄEã0hé@‘i0(Zòþ2G¿åd~ C EÜ„·¡øgR¨?oAR’ïå­¬ƒ1à]GÈ0Án”ñ6zÁ:¾Ktƒù@1m="äO>nÞäwÑÉ­nøÇÉð9oÂ⟰ßB/1‡dF#„Ut×´M¦(ACs%-æ£YpxÛfn›C`TŠ UcvûD˜Ý‚hñÀ‚é‰>ϘZŸ~Ó³nOÓ !nO1ÏP*@‘àÈVIäOsÄ y‹)É%E”l»Çƒ²ùÐ\5ooè –¶§`Ž“-°„„1FÎàŒ+s’nF¡’mVÃ@`“?->Ÿä£X†}&¢ÏžF ¼2s¥£S.› ¾fLÆýrÜd†³à ` ù4€.9»5x##ÈVDËucTHÌiAˆ’ËvÏIàhbžBŒ>ÃNš >9LàbPóÁH æa'M(œ¼ ^ÝÛk`7ñÍk`"IÞ^34“[—Ï”U/=º¸übx 'axóWÃå7ÿøv€ê#3Ì#AÖ¯øá»‹O>Ù:?¾zq=2¦y{ë1¦Ÿ\Ä›+˜“$ôg˜TbÉýj ép{˜Ý<—_¾¼ªOÚõðt¸üò‹ÇÃå×í§ëávì¯ÿûcÃéûvqù9äh/®_9Yƒ¿qùU{uõúem~Oóͽ¿µåùôÙÕOÃSï¤EGçgsùãM/âýo0ÝX¤¼±H*cr ±€”ïXä-lÍh QŽtFÀÅ<ž„1`6wA§âÐÇ:ÃKFESÌcÉi´–2z´= ¨ÝEGWû äHÇ:G ##Z¤± nîÊccÓ!šUÇvZo„ו|‚§DL¦Ë]ЈcÎÇ-F_$±ŠŒYvRrè±Îˆí#V5x1ìB¿ÂÍOâ¼òKçEdûXçMüç}»óQç}»3IbëýÎ{t*”Ò#£ÄÑWìû÷èû÷h¸‹aͽßy×yß•ZF_ïwß; … ‡ÐQhEíî{ôýî›Þ[ï‚/‘÷ºïÐ÷»ï; ñðóÜ÷hwß‚ìˆÔÊ#Ö€ßÖ{ËÞk¿Ê{/?}ñâ  Ooò\ë½Ñ·—O^Ï×Ûõ_Ÿ¿ø×ÅågW/—ör#|wùçË¿\~þ”¶ «B!÷ðFòèyÅÑÝ,õd¸üÓÕ×Wìü‡ÿL×??ÿñYþçÝ2ïØ??$¬ä‡„•üöJª{&Oeãå.hO#i:Òys°&á7ä6¬Ø¨™t&‚ˆ*9vÚCXӾΘ®QLîêÌøõ¢ì7ñ O½ß÷ ¯>Ö/lƒ¸©À é íÔÖ¹7Ê¡‘CoPotäÜ‘sGÎ9wäÜ‘sGιtäÒ‘KG.¹täÒ‘KG.¹tär@ö2ëРS_ÂvU…GÔnK¨xÉY°’Éñáû—W¯|ö aâ[„‰ï§Zf-Kžfåu*R'Šóªij3£ºžåí0ò‘Ò ‰† cém-Ž[1 éÙi‹;ÕÀËœ9ªHÍ’WÒyÕ©-a™Êt}°˜’—œ´éäTú¨Î4M³ÄÔb]ášÉæ`„›ì„ú ¥fg²¶àyÂ<¡îvý8ïcÓ”yj5TYBKyæBK„.³®²¦hó ¥íÜǚ̷¥ÿ îW¬;"û¤MÒ&©5!G]Bh¦‚ŒµðjºLÍÖz®,0¾Y‡DPÅ¥¥‘ÒN®wJs­y uYg[L4¬aæE~S\ÏÀ}AöIü–>!zî|"}ÈR(VÛ:Sšu^)Vªr”¦bñôÜß6J¾‡šÇL¾µ½˜w±IJ ÒJ²PJà¥ÑjÑÖuðÖOÏ}ñ}¿XGß¹´‚´aŸ°0zƒƒ#[¥qÍ6ÕÉ=×@¹qXÏ@TˆÊûiDš"È&™ÒN¦‘vÂüµ°Î+æ‹=!@µÕ6‡Vc­zu4žpô¸#Ét2}ZÔÙ²ÄÙ—­yY²ù†kÔ%/u±p}Pbl;²ÈŒ]?D};•>©-l+…LMÂ7–$]­$¼Îàɾ'oé#æzîóäZ[SM2[iiBLKZÛb –æÓÆÑîÉ¥¶ïÜ28a” IwI»Àö x Km…Öšæyõ#›Y¤,¿gà Á…aÓžñHä1‡¸+ÇÄfƒÙaò\Ö$!ÁÒ–\ç&XÍÊ|}B†µù64‚~Ô©—Œz.`u˜XçÒ|)k\扲|áê„QŠŸÈñˆ¥×(õTú@SüaÙGNa‹¶ujlK ³¶gHš¸ÄÑO{ÁÀë\>•>H:–jÀO±vð|Y‘­–Y>©ûBÂ*ä· 6g“ìsvZ5À@*qK«æD‘V®«>4q›PÞDBê ®½<Ø•âMëÚr-‘—°Ú\TrSÏçræj0}:W4ŽÛf QÍL<üË>®wZ¬"Ë® MblT#¯%cñ.K>ƒ>"£'pMŒZÙÒ©ÔÑy‚/­H.Er(Ä«äubi‘Ï@}õíM­ìêáw™¸éÊyjÊ õ¾·¬Ñb\bLg ~ cbH[lDµY÷Õ–qVØù –‰Ú•¸Öeá¬sZu9Uèf7éPÞ„§²³;&ím‘)¢œäTi"?—%¦„i@±ÊÔ ~øFÜ.$'RGXŽ–™fšŒ—¥–\4ÎSžgâ3äLòXÑTx;¿,r*u*©Í ªý¬8&*u®yÆTÁiÚ åˆBÙ?Ã!$ÿ@*¢P.¶Ï5òÔPÖ–f®óÒ–)¬Äk¬‚¥†9/§wd„”óÒÏßü:{q°KXTaAͦ´fÑànà™NlÚtâõ ¦E-PÊ›Z 2Ò*ûj¹.)ƒÈa‘»äÐÆ$EñU–ŒüìýC!ÿDjסЮÓÿ,ª}ÜñƒþòXŽõaÇrœèýãÿné°o½‘{£oÓSߦ?h´}­thpoHohotdêÈÔ‘©#ÇŽ;rìȱ#ÇŽ;rìȱ#ÇŽ;2wdîÈÜ‘¹#sGæŽÌ™;2wdîÈÒ‘¥#KG–Ž,Y:²tdéÈÒ‘¥#kGÖŽ¬Y;²vdíÈzÒƒUøŠ¢›Óó¯cDÑd:;™ Þ4¢6Ùè¦|ÈXRPp´ZçSVªj£ùÖ|·¯Aùpý øna_]¿|]¯ÿþó“öêÕó«ðé߯ž={r†Mí¾ßt°ÿ<00ÿX-ßJ{;áö>>›àëœH§¦©äAKä)Ê„u¬LË9ú1“Ÿ(ÛïnCËÂè§¥.­|{$ùiï·²ÍL[¥eÛQLd~‘ó$F/g<Ðè\öïÌJú½Õæ.wio­ iñ÷@+‡µ¦,H¥J™J5Yu%õ£ö†›§ôÁy±Üú1ËöÍ÷¡JÿÐ1Ëýr£¸.Há~!$Ôú¡†f³ÌËéY-ÈÛmü•l#¨øP{·ÆE9kY×Z×YòéÃb<ƒ½÷Ý/öDIZN­Tƒ ºT]U«.µb!·|s'ƒaÞwÅÆDÚRµÑlë†ÇÀФ.…æÐ  ŸÁ܇³¡[¹ILïÖ%š¢Q‡ª(ejª6Í<#¿èrÿ=Úª¥ endstream endobj 2390 0 obj << /Length 1898 /Filter /FlateDecode >> stream xÚå›[s›8Çßý)ØÙ™N²³¦’ÌÎ>8NÜú’’^²†:Äa׆ã¶ÙÛg_aÀØŒh’$ÐïýÏÑÂDÂIãÈh¼ìÈXPD•I0n D…ªH$P0®…«Š?¯‰UI˜°ë–¥gj6U޽ñbf»8ž6mhFãS²–@€«;*Ѝ ,Œg«@¸fu¯vGU¾,[Î,K¢Œ%ö{*èóX§¤²@D•JÊ:%"H0‰´ìˆrxg…ýH|v—Í’ÑIC¸j~¼¶o—þçü½yzÑ阧Ç#óXë´.zƲbYsünÐêwÛaeÔI Çþ4)K!pUˆãîHkÝá ¥ñªÊ<§%re„–Ñ2;ÃQ¿e¤Å•Z§×24óä}÷ÌÔÞ%0¤*L{Ø?3{Ú¥Ö[cQX,é™ÖÒs«w2Ìöœz!aM’JU†³a¯gê=M;ËZJÌW«vÝo½ Eð: Òî~)¨Ú¯þƸˆ\ ÕËf° q7Så îM«k˜í‘6)SEõÍJ¼‰ö —½5a¬–BÛQº•R?ÈJ$ ˆZ’rÐoÅ‘,§ ˜ÊÙ½÷^Ï™tjâ`PëeH%eàp„ºLžÙbH}›#GgC½ný›P‰é@)´ ¶Ókk!Í&â(”|U?mÐ:êi¦>ìoZ#-vXHeYã?w—–ïX§vÂø²ƒÔµó"$)"ÛÈ%gW³¥fÒx3=¸×ì¹Ü¯æF&ýýëZÆ?‘,•h"4®| ªÛÛÃA墳ÕÚ1¯×)U…ÓéQÛŒ)Ò£ºw<×Ô7 ˆªÿʧNìÒ©abI}½Y;;ÜÌωk_oRñÞ D™zîäáW;.§Cn¿˜óØ#óÀ 2N9ø%ß!ÊÂÜ^/™öZ=çÝè³çlŽ@H‰¼ýd'uëa³Ïö]kšOÌ–—¢ŠÕlê^=sÝ|áÖ/®ÂÁðkj:.ç8àïÂoÁ«+eÊTÍ*ç}inqrÂù”é‘ÅÜb¾Ov\‰>î˜Ïo=?x„ùÉ L–$ÇÞÂå ŸÄ!ã[Ëç7inûŸ±Í"Ûá5KúÌšÙ3óÚÿìsšD¿“—̓.*+¬ñíNËÒ‰EUŸI&þ&AɆÙóïMk:õÆÜ¢Á¦à¹‡åbî¸óv1±Í;kbÏ9Í’þ7‹Ó¯Käg>ÒÖtâ™ó/Yk®â÷÷âJ>1#"¢‡gëXÆ¢ÌJ°,vË¥'¶kûVÀT·ü¤ìã!÷Éçe‡8øz?9lBp`»YÆÿ54¦[ endstream endobj 2441 0 obj << /Length 1811 /Filter /FlateDecode >> stream xÚå\]oÚH}çWø1¬–Ù™;ßÚ§6íV­v¥vƒ´R»"à$h ¤à´i¤þ÷½Ø8Øã1¶),fûEÆžûqÆçÜ™¹@ƒë€¯:Ïû_~“"0Ä*ŃþU )1JÚQ,èƒgŠ@·Úœ}F“;rÓýØÁ‰Ô‡‰oÒ|uµó²ßùÔax‘ìi,cˆŒn;>Ò`ŒŸ½ (áÖ_â;o!q0±l\tÞuhÖ?-E¬æ&ëŸb„¦Rª…ìö8¥ôì~2‹”D±7‰‹ëµ?¾êz ïšÌ&Ñd8|NïÃõ­‰Eî×8>ô4ZÝXÐ ª,,«i8Š“YÍáíNÃÏï£zãKÖ(AóEƒ±y7~èÛö1ß=ž/FJœÏgW“ëAëØd¥ðÚT"5F$~˜˜‹ÿÝŒ¾Þ…ãð*gçÁï$ ÿ®t.mø<ŸŒónjK$… Ç@âËOeA ÂŒ67¾{ü#Œ†ãa4|>_–Åß3œ(£Üh¥/ F@EÆŸõß¿~;xööõî9Àé’¸ÌاÇ×øV¹QýM%-usr.—“ùÌMSšp]LtœU™ÉêŸÿ9y¶nT V¯Ál9¹ž…ãÝ3º.œhãëË/ƒËáèŸû; ­Aeš)µ ÷¡joªat·†iOè"Ä Ë\x“—†ðõ¹cùdçíp1¼]æDQSÇÚ]<@8Î8jw~à䜦¨Ã(ÜŽFy3t‚pA8^wR¢ÊS`Šà­]/ød‘œï„!`ý¡™v„Å2íÑ´Äßß‹]ÄI+üÔ)|Ô‰)bšHüÐI…ÝEðÐå‚/ 5iª‰¼›”„ûêõ¢¬=¨]ì Û„&À#Z7[ê`Ô ÜE9KèÝ^9…U sÉüzgu«ôî|~{·Àäì«’AæZe¢¡Ô•Wµ£ùl힉C>Œ"ÃZ¨äb´žºœâeíÎÓ°–Sû)æ ï6CÑ+j†4˜†³†Uè¡°°¸\ç¶Äo™õ{.£”Fp¹oWëš¼DZÛF4¶Qã*¦£Q"Óá2Ê®0×Bç){ÅÉnÄËÇÔµ” _>D»’ÎF¥š-ãN™û¶ªö†ù<‹ „¾l†fÖæVgµ”øª(âI‚$R¸@ðS¢­¬—ª ¦™ræ¦YtÓÔe¶$ÔKáC4XŒ²ÌšªDÞŽô3«ò^6¬•Åèùb´¯z4KÉÛ „ì:#ŠÙ³Û9;Á·…¬Ûã¨ÇÚ¾ Ì?eÖ.{78NT RÿÐ:PK€I7&yÒ´^ •jIX.í˜UÇÑé|v½eNmטQN`J&–ñÇk[Pº£nì^½?…ÛL*’ÝÇ\.,­Ð kZªˆ²Í66@(b´pµÒ²†ó?ÎÉ!ø§æöp^'<;Ä'&Pu7O³:áÙ<Řøiá䪄(Ñ’ ªTÂÊã8êQ‰º3j´yóýJuS7s ú…xa¥“+Ç7†´?¥¦B¤v>Ϫ¯×¹%‹O¬­­R"hëŠÅIë‰qFŠùÊ)£´é;‡ª„3ÆÖíAG‹ £ì81ù”¨6mo£lÖx?ðè(”ÈoIP:ÄâÝ©Äxž´×›÷5D!·ç¿æú¼ é7­ÚÂ×ß±tÈŠg}Êöé'£z;e''Úm¤ìlïCmÊö´=`ž‹&99¤ÕŠ)Ë ‰•¼ Eö8yÐJlÂÜé6b,FÛVæÎbµ ‹µ$¬*îf«~uV8Y¨½•˜)è}5$cüûÆ÷”ó^3¾.CÇhP«qBñ×$ºIœQ7öÕ)šî¥4Ó‘”xó‰«(ý¥hé 3ñ T3a˜8!Íb€†Ì§äý Ð-Õ\EÖL1GEØQâò`•ú×@Dpf.¤ ´ª’CjoGT€åb;Ëðu[ ‚OA)n·*l9‹Ë¤µvÛ×EX¢¯Fåv=Hê çÄX—Ae¢¿|§çæËàòþêj°|Ì?‡‹Åd–dK{Ÿ¡4 ¢›Åòf>oä®ð´÷üL»ÚB_„£=7†f—’?fg¨,ë µDqwÛ LÓÞP}(J¬ÝÕvú R…]ÄÁž©4Uí ƒõva‚=fæ†x¾ç$·æÒäÚ‡)ý}˜„YpÁ†SÞ?Mšñ5Ä‚åm¢º§>Á"Éo¶zŒ¿;Ìv;ﳚPç[Á˜ ï—²¥…Óþš÷x"È¥úáO¹Ô§ÍyëÇ}¿>!“™ÒàÇ'ÒÅ@ÓJd~tBH,7TbÿU8 Ã㲠ôìkòÿ‹y—Ó³‡¯×]\û…3×ÅFï endstream endobj 2362 0 obj << /Type /ObjStm /N 100 /First 1034 /Length 3803 /Filter /FlateDecode >> stream xÚÍ\kod·‘ý®_q?n¾\ñQÅ"#@2†7Àë1»6 Oï ¶äHl6¿~OÝn¶;Ñ´”îHÀ`Ä~«ŠU§ŠìvÞ¦Å,Î;³ØH:°‹Qna¶:ð‹xÖ-Él/ñbMð: ‹u^t$‹%·âbƒ• Œ„}ÎC|JAGiã6røO¶DqØF€ ¬“錉to·7c"HR”>.ž’Ç>)^}•Ìâㆅ°†”¶çÜB–¶çüBºXŒh!ÞÖA¼PˆºF EÙF²°ÙÖAqa+ sPZxäÙ,LQ? Õp ýCQ’ôìN›¦%XÖÙ°˜ â1 KàmÁ,!lÚfY‚8#¦P¶W¡oK:[ E\TÉ¡°= ´½O‰ÛŠ`/Ii{5-ÑʦX³D¿I ˆÅa¼CØ^õKŒ^×!jT«X„—d“Ù%ùÍ"KâÍ ,Mg“´¤¸Ù2ªƈ¾ -Zãˆt%Cè_Ÿõòî „¡l¦ˆê>É(8‚µf{6A‚u›æ¡` u£Zë7€",ð)TØÖ:³%Lá\Ø$` |B'†2¬ êk>©‹ÆÝÇ Á%Ñe'Láíf µpK»¸üúÿ~êËåo®¯oî/.ß,÷Ûã?|¸þÓÅåoon[¿ýÖ Z˜ï.wùûËwßÚíÁÅåW½Þ/ßBú ».DqņÕm¾ý%æ5D÷ýfùì³åòýrùï7_ß,—Ÿ/ÿvwû±ÞÿÇ_ß÷»»7×_æÛüãÝÕÕû«ì¨Œ¡¨É‡ ´Ñšº ütõ}.¡…nÈù:šKÉ$gki±§†­ß¢?!X†ïk0ë–,°â)2Åj¬=^Çïn~üñæš>!4ku[-È›+rÂO„?Ø «!{”"©ÖÞù·Hê!×8\ £7iƒƒù„hŬ.)Z¿’R“VÿO¡}Z“W™¥¥`¸0V`]N9…`3èTÈeœ~¯ÁoWV2`ìÊÈîª{#/Cß T^FÙwãk—¢ÒÇàZ±éB<ƒî=vœfLoVð—m5ð˜¡wØm#D äñ0jà:ìÉV¨öpÝ»¸Š&n몋óx™êw¢Ê ’k©à½°š<È•ìÜTï@”jL·Çb@3^„^²&ïÀ üƒ«äl¤Â%dä˜ÌToÝÝ£M‹ÕØô2ô1õ†øí]q6×ÐáCͰ«B-g@ohlHÙV¯-àï׌&îµCÁ.JY-fµ—K»¿áJâ3ξ¡óÄâukàN“³¦Øøº1jÚÓ ¼RO4Òjœb=§×TÚÞ˜YЫ1¹F»áqMæy¸ÞŸÇšÖ¯YåváÛÈ8F=ÍéùÔŠòBÏÖâqm¼$!е]KZpŸG¶X[k¯à'DáÿhÁcW=ìz íS6¾Ê­lôÂ^JÔ BmhZ̧Œƒ>¬z<•tÛ¸C‹d±¢}ô|°Ãh' Ζ¶6'”Q\ØËéI2vzг“=ÁÇJŒ{òäEs}ôÕÙŽ„cqjwTZôéôÁ*ZøIÜQ>#ºÃòO…„Ï—oQ'DÌöÕrù_ÿýÍ‚ô¦J‰`¼zuýñ‡¾›oþâæú~›é l­Ò¹}ê a=t³ûGz:ìx÷>wùåíM}ß±ˆåòËÏ¿X.¿î¹_¾û[½|™¿ï—ï ¾_ßßiõ¢ÊøJ—wóñ¶ö»ÝñáöÜ{û{ó—eÓ'ý`²kÔ<Œ¥BˆšÚÝû7¥ßaþí VamG°ûÏA˜™ƒ8i?3vÜLÉ2%Ë”,S²LÉ2%Ë”§ä8%Ç)9NÉqJŽSrÜIþî´‡ /nlž6¢ïËqmî‰úïIÍ3Z•Û&-‰LâÐ%—Ü$ã“6… u"9éIº“Êk£^c8¾;¹k”lzóÔ’wB½“:ãY=â—ÒÏÊ=,¡zxFCr×BåÔ[’hûƒbËärê.º„’-&9}ûZwq;µÙ¹èÑ=È ¯Æí”CŽƒ‘nR=9ö®7+Þt†S&íÕ%ûа>¾ñ¸ëòVòµÖƱ˜l3C³’%2‚õù ˜}³Ñ²]5V>Ñlü9‹rmt“^L-á&lõpDuâL§Ó÷ffËk¶àÆ&|â|ÿ>ß¼;m¼Jvu–õÆÓ·;ûb, ê=ÌŒ+ÙsOžAš iÔ‘Œöà¼ý ®IZV<ôó>ùcñ–œm¯vP”"‚‡¡JðÍ…L¡´sàÕbƒÅOáx¼pAù°)C;÷L¶˜^HXFnçØú^)½^„³Z‹oø?ÕÓ|ÀkJ´NFð–’ UBSÆ–¯`Ìdé”§S,Øo=×´©yWu*|¶Gã-É$Ðöab4žÀ„‘@`j(Ì’Ê9ôke+Ûþ{LÓøð!Ecz¤T-gzeô‚|›Šsé Ç Èzv9ýÁê!øñÑZ±c¸—¨¦p¥ÁQÚ‡á FX5Ñ?„×cz߀S 9HÕ(Ãd—FÀþ³aÄ›áÒOX‹#k>¢!þX(Ɔp@#²™ &87 ºlÏpóhß%§íðCÏ>׺­®önšXßî=èÁ<Ø„ì‡Ó÷¤è@L‡{GzÇGøª½÷ÿ‹’ì?û­šß_›ót~5qxÔx¢ùùsE¶{ƒ6R’’£éžJà†ú¬Å"'ä,Î{”ìñÐõ@+>lQ¶Ç™=I`Êe¸ØKÍÓ™Z|÷YÆIïºì=4!¸‡ƒ¹£z=ç6ûÎ#£6Ií Ñyw[½»¹¾?- J«¶D›£ö¡E£Ñó9ˆPO¡øÑaÈäù:rD‰B9WÆý¢}ÓkßÙ_´oȧº}g%ÍæHšÍ‘4›#i6GÒl»¤Ã§fÛ%íÛ.z1|?°sàæÀÏÍÏA˜™ƒ8S²’í”l§d;%Û)ÙNÉvJ¶S²’í”ì¦d7%»)ÙMÉnJvS²›’Ý”ì¦d7%û)ÙOÉ~JöS²Ÿ’ý”ì§d?%ûxÒ¶ÔÜXœVPÞYôKq²ÏÛY Û ¤Ž$yƒ:ºº86”ÒkG¬?C4ͳòбŽ §ÏŒ¾FEÊð>„I´PDZ¯`¬g@M;´_÷š°AàjÊ(^4Úµ\z‘M õWöö¤YêyJà„óìGÈ¡¤ág¡.Ô;jT³=pÔÜ%t'ÆHÍ”òZúâÀûìẴx[•£ˆ@c׉…ÆEï¾VÔ¶ÈÁé]ºSf[d5ƦÙÒ¯„Í|+ /!…ãCÝwî)zЬÌ!%È(FЈé„ßüH 'ˆ©eûv‘k„ŠÅ8å\,Pþ(ãÿ ÄB$0DÃÆžÙæD%1ê•V¢©ÈÊéäFqêÁó¾_¬0…Óé 1*d$Ã\+—< 5xÎ.¤“ÞÞõ¦N÷7(ŸÂzÎÃiaI°èƒ…CDN0oÐÂÀ‰,;K…íq—}³¬(Æè¨zË%ö+²ñ K‡ ›N¥:D$x í9m¬]}›ì×kCàEÏÀsøBÑé=/ ê—§ç‰Ñ;oÇó’¢€ O ©­œ•‚^xCFÝw&P§Õ%Ø¥MÿõF=à±kpáÐÍP`Jüzw¨¦A­~Eõ‘AA[„Þ”AeEvê"oM¬àT±¯aÐ=£ß‘…A•œjN>ù/Ÿí-ÊI¿MÊ‹rÂ_ß\ÆWœáÑ]ö§pþ<åÇÊÝ6z m€Ù×î+>ƒÙôÜÛ ÏÓj ñ Õy(ÁIKm~-ZǨôczdd”úé´õ^gÛÚ°ê/jL zÆëaô€ÝèÕÔfõÛŸô 6 +zy{{Ed‘s´ø)œ¿ø†0˜`ɹdö~è]Aò1‹óaP.UÂl¼×ê´±U6új6ž?Â0m¬?Âàÿ{­áLüïEØzzÖ¯E<ÒÛÿD‰ô endstream endobj 2511 0 obj << /Length 1891 /Filter /FlateDecode >> stream xÚÝ[ÛnÛF}×Wè‹\ÔÛ½_'Ç78;PÔi@(ÒÚ QE%ŽŠþ{—¤h‘Ë•DÊVD÷ÅxÙsfçÌì„Þ½óÖÛnë÷3F= çÄëÞzɹ'yÝ÷©-èÁçî;˜S„rs_rôl8Ò‡XÈöɤ?ë êEÃI_Ú:í¶¾¶¹zèiD)ÄÔë[Ÿ>Co`νó̈Jzß“+Çe0JÌï‘×i]·`ÞJÁ<” 2o%GffBD˜L¦7£J34fæ2Ã;Ï>ôñ¼å}:D CØžÓá] 齋9+ÁÍýû^X¸ÛÈê"€qjݯ ‡ I½åÑžF¿%g1€™“‡Â \"RûA4 " T#–BB6&æåÇ ü‘ž€%T`q¸X£Ip·ÒQÈí©Åá~Øÿ2ôf·8JÎBû0^̇Cl_òciÕõQ÷æâÊ?ººxA‡¥‡¿ÎOt2~õtzöO#®4§}=ï˜+Mû]›§àÍLMÍ™ï1‚Ë”eœr’Y ’… ÉÏF0ŽªI0¶gd'aÍŒà0él– ìiØÏ(` `#jÖ’ õ edqy¨¢|Pc+¡bûAåpTf_&f\"lLüµyÊÖ_·«Ä~`9¸ª«ú˘r{Jdfò8õMæbTE¹ôcäe>Ëzʼn”SælŠÌsºµÊW̆yw¦B6H<¤ •xÊÕHȉü"/óœÀ5ƒ,!eÚ‘ÏÞëbÌVù\ú^¢"ûAåRù’¸V}mž*©¼ÓUì 3µ(‰fÿDE%É-¨áBI‹sp·Šæ¨á3ÊÞ|rª.‰Îü$äIĸ©U¯‹š’È à¨´XjîgSNvg™‹*aÊ¡€`—„ûÁåpVfßf`…ÚW™À$j¢»êÈ¢Û[ø 3µ ‹Õš6¹:ÔYúHòœÑË5¨{êR]šíÀ~¦ê®œ,¯Ã£ûKõ½¨g䨒íö¶òœm®7Ö59qÎÔ¬H_/ά¡å*¢`Ϋôå–ÚlàÊMAÍ-!ÛQ „6fU…” vd"ñ,¹XWeæÕRfd ;B™ J½:_YÊ\pÖSÆ¡f½06¯ŠLTUñÌf0U.ÅV¥O—Ó²h%_Ï3z;š|±aª ããÅ ™1„©¤m Ρ%Ø Mh¾ÿî™ÝÞúÓ¹?ù¦Ãp8ÐË„`K~º³3Ô¬LÐÕ½p0ù,„ü¥ô¿ZNÕSFeȹaŒ7ŠÇãÑdª_ˆ=$`LTÝÜäD‚A‘M•p1ÈÆà¹Ž:Q/šM_ŠE)VõºfkȘ§ÆÙ³W ©”“ûóË ·”–¯ð–Ê2 Ëè~"¿pdiò/}; t*]×7~ç‹ÿêèÄïܤǨ,b±¦>wÊã—WO;ÓxRÿÙzyÕýË?»xš^CèÐVk´åì¢Kòz'ß&ÃbEí)lüÊJè\fØ€ãJ4šôW+cÕb:œkß]­g•ú ¬`6î½Üh·“°¯ý‡a`6)9—gMâk])›UçÅÎ4r›u"ëf¼uÌôQ¯"ÙVS ¸M¨$Û¼H¶z™ÅóùñéßÜŽ¢ù—¼\-ÓR§-ovÖÔ Ã=„ûZ??’Ë“>+ªðuœoõ¹ž)ì|ÓYqب0ЉÜE¥ãgѱ²5¯œïƒc›ÅÒ¥Ÿ ƒÁÑ`>Õí䕆êopö6¼¼iÈwûmx_1¶,úñ Miaóºú†iÎúý7~CÝû×ZûÇ%hÆêšíF²›w“W‚FíEõÆíÚl(“YT ß Ç#çìhÅš2ÿÎä0p-Ä,+@ 8”6nù?Àm]8†Í^¼: ƒ;¿äÓ ã×§ì«U€Ötã¯çÇa¿kÞÊõ+Mè‡}?NççÍ&4FCpE,û‰òÒ—#ϼ{¡žêð›e©MÆ2“mB¿\›s ßnó?yè}­X‡‡œE•åAãéê¿›ŸE'%I×9øÓ×ç¾,-Ùj|í›}‹lví‚Óø+_Ê(`æe€›!ëÏu C³3¤ß9À°ý#ûù€Àö㻣ÒmØ6þÍMá@ endstream endobj 2550 0 obj << /Length 1461 /Filter /FlateDecode >> stream xÚÕYmoÚHþί°Ô/æ¶û¾¶îtR›Ò(U[5ëIM*äà5± ÁæztÿýÆoÁv¶ H܇cvçyfæÙÙñ[ [×ÃÎË·‚[r¥dÖ0°FŽ”–r)’ÄúÖ-ëö¨rlo±˜†c/ çQŒ¼Å÷á,»z Å¿—a4îRlOW¾~ùð8Z%á4F÷¹·áTçW×:èl륎Æp‹p— [‰î×á»NØyèà‡-òÄÇqC¹5žun¾bˇßÞY1×±¾e#g Îàzj :W\õQ K"W1§ê£$—NbŠKáaNOÁÐò6ÁnÆ*§³œ¼®/:ÖMObl_½~¹ü4zõé²—Ã>³Cpþ;Q>S‹[kÛa”ÔŒþÄÃãù|¶Xê8$KíÍêTnì[,ðݰ¯0Ò:Ö'Éq«G¥E¤~É¢Äá>·*·c°p¶!R9¹&Š"ˆ0¾H²œíÆU‡“HûõXâöÔ‹-ù5£Û£VÛÌ;1ÊÊ‘{ÉŠ¬ ©£êêEYt!TžtsΣ+f†UˆW•€:%š²r“¬(ý¹ju,õô#ÿ°²}€ºüddSM“TH¹²‘†irÈA6êУ.þ æAòÍ[êt™G:J>ëeš™÷aœìœÔÂVaâ2 æÍàS‡#QF¿}3ðá(gEüAЍf€Øn¢ŒgiSæ å6ŽE«ÙHOõlÃΡ2i‹1rR%À¤¡óù*jQÏ–LŽ’&á"NÕϦ ú%IHc‹fŒUô»§”¨¼êž/Ç’ŸÏ£ œ¨n×Ô¿UÝ6kž©–¶‰ÂÒMËz…þ3B ÊÙfãÔÆhœ©íÅ…<ꤔ)¿œÒ“Êïà_NÙáòÛ¾|wÉ0§ÆRËó&ìd2üA'žï%Þëé|ü×µö|SvW`ÑQÒÍ&Ý¥CGPÊÎ̶´“”ä]Tõ®™œÙ¬QÃx*ÜÅÝÂØ·tÅ.¢DlnÄræAë¤Ôaˆ7|qÉ!`âðQ·ÐC€So·¡°C Ü{ñ}Uù& £îáÁítuÿç2Lô¾Â¢eeÃSÖ>Â_c¸ÝÂV=‹y6W0£îo¬0!ñ&¤¶šm~e Bö© ߈B÷Gy&|#ñ8PH^ô¨¢Ôî“’kwÖú|¾rÕFãÅt§­vBŠ|¿frg:òÃ`¦2ƒ9ËŽ™ E.ú4 R[µ¬1“tw?ÌsêÃÈéÑ%8”NýØFe'Ã.reÊ$°zå$ÆÃ r/.…ÊÇCk°/<òƒÿùÀß RÜ-ĉï-'Àô¹%®CI9ðw7ÕÉÔ#‚\qpr‹ä~ -ƒ‘]Ý”™ˆqQ°G]87GŽ@ªØ†È1ÄÜcQK™62c"{ÏPgV{ÛÒsâÚU–³ó©C›ÜX>\U扔=*eë7·”Šæ$„L©`m {5NZ¶4X9Ã,ÿÙ¹±GƒÆæ»®°ŠW½ò’  ýf3V¥Óð¨K!Çÿà—i)˜o.ÚÎü…¯o1¦‘6¤‹C–Ö‹ôêËèMÿuZOþ¸È×@¹‹È¡œ6 ¡t×1é€`‰uç†]‰íï »ÇÁÜKr{y­ÔQÊ~5Ë¿ ýë®ÀöçQß@’`Ѝâ¥G¦Û7ZŸ¹^9m+Ý´Ðë½—ûfr`]:Oe MÂHobVÌÙÙ–òV•5Õ.nBÓT”ô+Ó6¸PÌÛÃë¶‹Ôßì„ã> stream xÚå[mo$ÇqþÎ_1ã/ên@0`[PÀ.>}°%‡yéQ„ÈG…Çÿú<5ÜZR²EïÙKr^íìîÓÏV×kO g–! œ9dÕ„ØrÝß*ƒámu(\hC3ÿŒ¤(ù{BqQ—x œå ’“̯½˜ƒ‰Ôؼ‘ÊŽRfÙ¯ùŸÔð'ã U_LðR>¬3_#çAÄ ÖÈ «â ² ¸ä¹ R³¯›ë ­ùº¹ ™ÔßÕ4€·¯ x|ÖßU²eqI†\jq)¹YªƒÒÎYmPIÎJË ¾8¤:¨ÑþÝ6h©¾.~ª6qd£ÁRóïBaÆûj&ƒerΖSõߟe…Ïl°j®+CI®œŒ)LûwÛPd×$ Šî¬ Ūê,UK‘¡¦ä\J*•Œ5°=Uî¿aCÍm· ÕöÕ ºZi—ÚPÛ®ìÃfºDC»·‹ÊCsâf ûµ<4,Œ5@£µA‰öŸ,JÜöOVˆ®ˆ ¢‰[D©î›£ÔŠsÈhß–S"Ùm©Á–_Æb ÆD¦ûU¬F•~ÃjÔŠïOŒ»ˆÕXœŽ&¬†¿naÉÍÖŠ›^c“LV“ó…ˆÕvz« ˯b5QßMXMŠì¸XMšoÌN 4\Å‹@Ì»Øü³0‚I±t%ðS|5üVRü|¿Š%”]©JXB3ïKLÕ•ªxMZÜ¡”ñƒ´º(ƒƒ¥¼_uOdÚEwôÝ‚ ?öê³Ï®®¿üßúpý«÷ïoî®®ß~œïö׿ýîý_]ÿúæví·_'DŠôÍõ¿]ÿûõo¾¦ýÅÕõïúr7|Ýòè{&ÅF…Ô±‚»T-+>ö«á³Ï†ë·Ãõ¿Þ|y3\>üËÿLwþî‡wõ¿ÞM©—–rÞ¨öIijynj[]çšÙRûÅðË_^áß?Γ9à ¢\x,Ø!'Ú”ÿ*Ñw·—»ÿüóÛþáÃw7ïß½{{>>¡7â±úÖ…Þ¨µæ Ò›”qÿHŽ22"\c¤F¯¥7Î4ºÔ†˜2’Êå¨ ^9•ilž¤,{®ªc¶¿ÊòÛÛ›?¼{²_ì·“nS_9ò6M‹”eÒmÞ*’òœÊ–ϸÃ؃ù®R¡<ªòS\Ÿs‰GdW‚™!tµ2Š'ƒÆ#rÕiŠëÒµ·*ºæI§ìå•­(^¶Ú–³›"ìnÌô`‹½#råÅÙ¢ótÏåÔÆ–óΓ©œ¤T­”û:ç-ëº JÕ²¶µ-ÉYÍÎhˆ3$Ze°$äfg[j}­xƒbNòh“a¦–èòò[üæD[z5½Õ6šÖ£Úš(g/Î5ÀÒ Bf½ˆ|‚åO#Ï}­ÓRZA –^2öL¥Ðš7žéü|Ðhì/"dâ¿g{?dξàï†ëßÿá«ÁPy ©‰°smxÿñû￉qóþnÇÿÍQEñºë‹â…1Ñþ Ÿ¼~s{³¼í ;\¿ùü‹áúËþ§»á›ÿþ7Ó·ýêú7ìïï>x9»ß懛·Kÿp_:ï×þ£¯ßM¿¾ùÓ°kFj½ƒ¡±z6x3Ýd`±Æ®ÜXïÖÞ( ¡„PChAS‡ !²²²²²²²²²²²²²²²r äÈ%K —@.\¹r äÈ5k ×@®\¹r äÈ5k ·@nܹr äÈ-[ ·@ndïñ…À!H9 ÁB(!Ü#sÖpXÕ´•c<,‚ºP.¯ÚžQí;O“òZYÄLÆûÖû^mVÒ¨?S¾’ÞdLðù ʵ4üɉÖb¯¦·„ôFô†Ú¾”zAzË:š;å&°3'ªcªúZzÓì‡zÔ›*¶ógJå׬[œgiÅ€óÎ'U.ËlyEPœxCáBËÚlñ­ö<Ÿq“ ´ŠhZ”YéI¶/Ðb"› ÓÈÇ&š€ïÊe6™Hé#û ÞÁ"‘£G®vqé<“'I{5é<µ¦Ô†Zrê+â(MlÂI©BÑ ™vž§éüá:´áú)¶/vPGbSåa“‘M$_à&ƒ'¡ ô"‰eçizÚ&S›ÐÊ/ÜGŒ›n•zãe±yÛ[¦3’m42éQ«,pÑ'Ù¾Ä&ç„M}´É¹Œ9]à&ƒ'ù=­¤ãNûçiþESÜtî›Î3—i&¶eÕîw!ú‚ËTËuCó{x¥²*”Ì;ÛB/¿Ç\¡%ÍG>"°A4=OiïÈçnºûøáYL.ùQî#“Cu¥|A7g„ášèérJ£÷R’É_d‘×»9SïÂ7gQP™^œ«:Oñ›º(ï‰Ûγ1ŸXÉL4×)§©Íi¡­ÚGÍ’ÚlË¢ç,ÉPîÑQ«ð‹q¿wÿÛŸlò›évú㳸ˆXÅÖ>Úê‚Æ¤èåuJATrEî-;ÑV?A{Ÿ÷íûé®?‹•¡´GJÔ6¹¤›™¨ük‘#Ѹ×%–Æ”ét%þö«ü, ƒÂ)pïïòåsÑhå$#ò¤OSàÛgÑ 'hì‘Dóå…lðÜ'`"dÃ2ÉN»ç°6ª:kª+–„^½w¥2oVºLm}†}Ðê1d?ÁöåBvÊØÚÇ£È#”/0dˆC6y×I²¹V(íA‰èÈpýCv=Ž'4ïê^=bûÉ›OœõW‘I.ëDÿ>bшØNTòëlF›Él£ùr'Œã>ÐÝ:͹ÎÜK–Œrv"]Úú4žkÙÎHËŸñ«>îÏ(ÈØ¨ Ú>ÝÙx›§Yr)(h6aš³‚2[h6­g¤›|ò!EàsÕŸ’CÛ5TÏÇ'Îe×lĬH_ׯ–êb›¨Î57YËO'¡ýÓWŸ„¾>þñ$ôýˆò?2 íOÞ´RŒ½RŒ½RŒ½RŒ½R !j9j9j9j9999999%%%%%%%%%%s ç@Μ9Ä5Ä5Äõ0 ~æÙ_%”æÏB­#_Ò‰C‚C,B_î-Ú1yÑ[;í\¦¡Ø!d¹uCÖ@ø­ª'ô”óÖJ>kEYyô'½¬ç‰˜7s²Z^~P™ y¾|â è å=cGóO2m~´8j£? }(² r©œxhBZïS«kâ¥O,[GáSŒ·5—óç{çê£*1Mæd‘f^Þà ’!¢vð‰û"O(ï ÎÓ¶>28JÞQ_Ü)‰óä˜ls’ÐÚiö¶¢v@ÑŽŠXVÔ•SFë™Jë¶0\]Ï?Ù*ɶ§Ø¾Äd[ð‰É¶§¶øù Μ=œ5ïÛÏfpÿ{̸O endstream endobj 2570 0 obj << /Length 2252 /Filter /FlateDecode >> stream xÚÕZ[s£8~ϯ f_ì­XÄÍÛ;[Elb3å@p²Ùî)—cˆ£Z2€“ÉLÍ$0'$Ílõæ!â }ß¹é€ÄskŽç&'çÞÉÙ…,q* ä¼{Nå¦(œ:"pžÏ}é©Jÿgï'â[PRðsyïÚý¨j½q´Úmƒ0]¦( 3ÑÃ;ùåDÀ’<'#jÐD‰[mO¾üÌs>¾÷‡GjÜs.¹å$Y‚¸½áÜ“Ï'ü›(ð ¦ö¾‡‘Ä9$G†8»Ô½ç¨šÊ D¤á<ÿUåÊ3Ü—,+½€Ž›Ý«Á€"âq©F\ÃéË|ïzaÑÊŒP’(3Ñß“¤cìË+Çp]Ó¶S†@•4&û#1O~N†y E&?6^]ÈÒTu2% ð¼À ¨ØxÝèΰ&¦e4jNRÛknzÓ0†€µ?ª/·qD ¡ZQRm «8†dn5 6»pÕ©{>õE¹!¿‰†‚5WÐ@!JÇÁ]_ÄYÏ¢UÖøo“sI@â }åežMÛB͆±Z9Ck¤þnûè=ÄÁÒ7Ãû fÔS…€/cà-˜C i£DaÄØ‡ø^JÀ6€”±—T0î­ÃÀ'¾‡Â”4Ò‡òOIÛÍF…|ïiᑎ¤èH_ƒ¾ ÷¨¤®Q0±€\e2L9~Lz(`7Ì]’ç±+¹$ã "\ úÙ¾÷Ëo‹]Š6 x šÉòw¼¦‰Ü9ðSû¶D4‰(öû@W¿²Bä]Ñ=“A i}åyq“ÓµØPeëQ…SÅdF š§¶r3CK›NnSó:Ë0qDL{¬H—Œ¿w÷WÏ’d.ÇÒ°„*¾µ^«AáÍ3 ŽÛ½þswÜÏ•53G†åµ¹%ð¢Z×½Ô!¹Sn9æ:týŒ_b´~H³ [åñ“y^Å!+Bri†i°!ÍQ?F¤t¤GßÐ[ù@ m8Ÿ´ÒÒ—p¨ïÇñ–™´.¨9’4Fw;’2fËÐ']¢w’h¯‚šÔ —ñ ißGñ69%íg”>V—=Ñ.m¥°a7Aµ|tV¹WQ\˘2x â-JÓ€òxŒ£'䳫ôa™²VÀÈm6Ñ3 ×är…>:¬$Žønè·AúV AÎÞHñú‰AVWUØ“÷îWÝFX¶BÕ½nùŒÿ.IY$¦Kæ¡…±–wÑSñ ME5f .F™¨K(©ÁÄÕ#ÒF)Z§ ¢”6ˆfäö¼¨VÇÜ+jµY"ü–^áSÒ‘ÞI爡^±Ó}=Ú ‡˜¿c¦ü¨©Jjòÿ‹¥ =µa¥tÁªÀT«ü(ð3–’#,H›ÛeÄh¹IšÒa™Ì³‘ÛÐP» ±ïmíÜ]ë61Y*5T(5\nƒªs4×1T:jz¾–äPš´â÷¡uñvf¢Ø(N˜ùièÞÅêÏ<"¿Aècñ º¨c?ÙFiP\àg%’ý WHmx‰|7¼î1šz('Ñ}ú\¬›¬!·ƒUV0ô¨(Uâ¬2÷ …$i냢Ð}Q.Š]T{ÞÔt %×¾ðntÇ ÞK{¯ûÚô=äü–üzS*6²¯ns2õÈåÔž ‡>ª[c&dyŽy>÷l|«E}"Â.˜ý »ŒÊ5@ºEyÿο¹‘ Û¡ò—W3“1ÆqtË3 —®¦5šÍǦ5¡×˜iX¶×ŠœÔ¹™yiz £gŸÖÌr„åyA~/ g4Å7ôssfz·5]˜žU¨æë¦ ·NÞuêyºã™£ùL§f¹š;W¶K ~:6ÝÑL7/1`öaæ &¾6,j!wªÏfG¸ ¿NÞíËpª.W‰âV{ó×ÏgFi…ªÿŽMÇy…gÖ.G8p±yg§­¸©Ý¼¸WÆÈÌæ¤f`WÔÛÓ®ñyŽáaYÊE¿Ô'ÌG³OßiZ7Œšc 'ÆÑÜ1. ïbaåÎÏ]ÏôæµÚĶǵ ãε92ÜOÔÆ¶[ ͹k´3ZGïÄcÝÓkÂüp `YïùÜ5Ë´`Zžá8ó+Ï´­ò{ÎÔ¾ÁAÇ ­c.ãZn±­Ò[°„½(ã ·Ûª¦³øÊÓ¥35°˜SÍ%yxêEd¹8VG^óóLQ8’_sÒòå ]ä”J¼Ð(1&3sbX#£ŠÌÎøÝ˜®QZLwL·xδjIæFg:›×\½È¢óvß&a'%K9{½t9-S>åBEõñµY¸áz¼¬¸æþ"X†òhºŸœZ}؃°ó{ð5C·ŸÐ9(@ ‰pÏg5ÐP‚@`]y9p°; ï…3€þ'ˆrAªì)÷ þ†îC? ¯E‹ÏÿYÌ=sæ.¦‹*Œƒ‰„wO„gAaðî‰Äf¢ðýDÃÕfǾgý3Iýe¼ÿjœ¾Ì!²ô=¦ùnÙ±™Ê‰äog„¢·§Q¾qšmƒ·gQ›­¦±¶<ÆÈV[Þ,§Ë6ô2‡ÜÿÕ‚l¸ïïl²J`AÓÐïÍp†ô{Äþ\þGòß6>§ðô¹ƒ£‡¢tøƒf½ ~ZxŸöEKWSš]]ÿC¥^Q›"QúÓ›VÚ’©89Xpx_©¨ˆíò~jnv,å¯p¬$w«´._Û"¦²dK|†’tá6éõˆ&Y™‡]v^¦ŒÆj™)Wc±§^Övòi4mÂHÕùͪWùï ì*Ú>.ž«h¦GJ¾;ÄIâ°ø=öƒãJ.!ÃïòZ–^O9Än‚ƒrSå-A“ö÷E‚_)Ú€‹Nõ àSe–%›ªB©½#}é}ªt4Z”e€_šÞsf‘UT€¨*R~~M–€Œ{$( =6 Âì˜";”Êza§)ûïýú²ÎÎädèjÿ4á¡} endstream endobj 2583 0 obj << /Length 1485 /Filter /FlateDecode >> stream xÚÝYkoÛ6ýî_!tè`1ˇHJ+Ö!mÜÀ]š´Ž¶Í ÁµhG¨-§’œµ+úßGš”õ°$ÛmŠ®ûH¢./Ï=÷ð’´ 5³ uÚyìu<¥¶å—1byS‹Cà0fq†,/°®º ؽ>æN÷Ý?þ* ç ¸î½öžY¶MåD:Z›q®Z;¯ó®ƒd#´ÐÆ›ãÛÖdѹz ­@¾{fA@\Çú{m¹°l*ÙÊÙܺì¼ìÀ"BN-\Nœ"B†Ì B9[ƒ‚VŸKÓ¼Y£’ƒ*_ÆÊ«¾v¬«>ƒ°›~¸˜C=nk‡$W“´j/ãÕÖò&·}9N½ëXŒÿ²ÔÁ¼þXÚÉPo;%ò}W»< “Ô÷Ên]0q­>v~Òéȱ­Bód¹¸ñÓk.½<\›ô„ÀÆ¤ŠÆÕC™°ä ù_áª4®¢$œE"(³´¯ EM¥uŒE«…o ?¬%Ï= á&ÕÄ/V©xï§½u÷u×ùrò¶Ô9בƒî„úzæuk ö¦ÞÁÿ5ê7àÈ'mä›Î[ôçÝmmø©9 åIUIÁU·Á/­of»«ƒxŸŠ8ú|.o—aPGf…é‰x³šI6þ‚”é:·]é5ÄÏ¿] Ájq£³5Œ¦Ë¯©ó-SšˆØ(óð8¿Ú´•…& ŽêÙr{}D•Ñ¥ˆoålÒ뛺W«âQ}taÖkÍÂHdý„~R=›ä¢úæ¬ÒÑ,ÀM¸¥–<Ú©ZµuA8ö^ _ø'ƒÇ¿Ÿ–)؇ìÖG’ŽÓp²ÿ~ Œæ2î»×ÓËW:¢\K (äª%éç˜\ã2$·lصw/fÓe¼§G: •x³¢É=¤Í*ÿ¦Â×o|\j–ÛñzqÔ¶ãx–4ˆ‰åö2kqª¨RæF×"FžõŸÞÄrúLUÿ$ –«´äá(ÒâÌÉÁˆ(È lu(L$·°ÜUýÉÁÁSBÌѪÑÁNå,SòÞ’d!Û-ã>¯%wát‡WRϘý%Edp~üølà{ƒKïìâtú¥4ša‘ÚÌÅ­˜ä2~3æ1Ï*,ŸBžb·p:Â6·³CYy‘«œ¤ú™q%4vHhkÁ?ž Ö apF÷9}LÄ/ÙÎ0£@??Òé¯f]ZOL}ÿó¦IÄñÃ&#rLgO&ˆŒ‰ðÊüDLE¡ŽL“µ{ÞxfðÞ—…L·U·4y®7£G€R^ЍHfSIiV™B#u/Y» d_À]Ü>¨±© *‹µ) bÃI…¹#– ð2Ú¼ï?ZÿwGuÊ—‘»N+NcR†‰ÔfbéÖ÷O޽ïˆ¾ï Ÿ•Ê ÓU4)<ž ÏåÛ¦ÜHMíVx™M2¹ûd6YªÄ7¦‹»€Âöl“Ê(Ø$Ëü¶¡µ(s”܈‰yJJ3ö£¾@³‚Õ –n£‚Õ68ÄÀ™¨³¢?©Â¢ôäìâÉoþó‹ó ïâ|øÄÿiRðcš4±ŸMïVqK@ÄÞWÄó܇l$¹H m ½õ1)=Ë“‚¡õ©t2Åâ‘Ð(k׎6©€§él;•ë7FíJ1&•¢ˆ²=W-%÷“,ð{ê¸gع×XÓjªô–DŒM%8ÞÃ÷ÿ8öG§—Í3Éè¡í#›ÊÈNµ5Tÿ¶Ó2”  “'£‘. ‹wc,«ÞÒqëNï±Iè~0ü]À^Œ†çÞ·>íØKvC˜´œÁ¶÷:ƒåÓ/:„!Ìîî†0ßï–wpZg†[ÛLàw¥áÁht1úi˜ 6 |ÐïˆÏ’p>ˆ]¯ay89\ĨaÂÚ4Lx}³sE?»Ö}ö£@‚ùê—}dsf¾öÙ0yYC?‘ˆÇ©ôWÉ7= »ôýɲG`÷ý‡™ÚÒwEùÌ'!þ ð$Á endstream endobj 2588 0 obj << /Length 212 /Filter /FlateDecode >> stream xÚ•=o1 †÷ü É€ë$ÎÇ­U [Õlˆr)Bâµ:ü{ÌÑëÒ©“-ûõ#?; X¨ç¢žæ!c£‡ò ‰0Ç©q-”V:e³.Kð²òånœÎ÷‡jf.eýrÜžºÚ›aìïQõZÔ—²’$°¿Äœ1;†m§Vk‚VvKb“á<&;àà1°—þïêMÑÏ—Sýà ÉÛÿ 'áˆ.E¾ s` 2á€Q£Û¢öõ{3Ôö!øaéë$k<éËugf–t}øNŠ÷ G‹Mc endstream endobj 2681 0 obj << /Length 1256 /Filter /FlateDecode >> stream xÚÝ™[s¢H€ßý ;ª"~I´Šì©D³V»þ‡9v)Bˆjƒ°˜`.$ÑXògØ0Iõ˜ ÈZ‚1¯€vTò"þ›5ˆO°+h„ÅgEN‡K‡´Ô¶´LÿNÿOª­XN ,,"%Š2úbzÃŪ·'ô~9íTË-3¤s‚ðïì.ð‘´¿3ðÈTÚsóp4tØã$÷POC iñ0Å›Ý*W&/J ÞºcˆÝ¿;~àbs¯=è™—#Ÿ‚7>¦k èîð«ôµì·Ð´ŽÏh[Ø%)ü„ãÑ`àû4`‡´|K–˜Å²Þ`e@*]O;Š×Ç>ù"QûœáiåôM^ív¨ëÃîˆTøðâ$0\—ƾ'Ù#nË'¼Ú?‡¦çZðÂö™cÙ3À ôqZÀ3ìS­GÍÙÑ7VÂØñÝ‘íZæàd|sm8^iÃà–UÄ ¬Yu3¹â·kƒØ5É~Äúv=†]7Äênˆ+* ¨òÞàÔu¬k#d6àóÂLÓo‡ª(ƧSxVZÌÐqý+'É¢ÐQeNÕEA_7ø½j[htƒ&âŠc• J QuŸF£I i7xã°ö‡óZѰòáp\`=5Å*ò?Xû™%®Îܺ²öX{4fÙHÛ#‰Gv`’Ú΢Š]Ä Œ’>/l4iÎ’zнۤ­5«YHwóŽ j攤D2· ûWkŒúªW7¾pò¸™Ýh5ªÇ+j»D´J*ƒ†œ†å]¦…mU6š’dˆæi5;nµ§ß)R4¬Ô[L«2ŠJDêj‘£¼²ŠyN‹šðø7ä¯^N“J¢x׋HCD“‹Öy(ë%ylÆqɆºZ¬3·›÷t£+TÁ6´Úb>ŠbšˆÆ±Ð›õü“V¿ÚÄoL6•Eš&ùƒWÄ ú JoþÈhÑÍLòd ½™)³Çƒ£*¶"Ñq_¨Ø -í0vþ´ÓX2ÍUç#ZVÏõAÕ 8ËáqÈÖÿ>/jÕPTÆÑú%oè'µÁY)pšUÿ‘³áh–ñv˜ÎWLøctOêáü¡é˜]9üƒ¯;Õo9aë¹%®X«\U€,r“¬u÷ p1~tÉA6tîeùÅŒSTYPß§\кڜk‚ÔÑ”­Ã`E4må®>ÊQ‰Í× -µ{«ïí‚Ô˜×7¬+¶%z'â? ƒ1„ endstream endobj 2560 0 obj << /Type /ObjStm /N 100 /First 1008 /Length 2787 /Filter /FlateDecode >> stream xÚÍ[][·}ß_ÁÇö…âCÎ `Hl¸ nlmc¡+gÑ`åìÊhš_Ÿ3\qã$¶¢Ø×²]Q‡GÃù$¹¹æRÈ5K ).h(Ù\°À&J M|L¡ E]È‘K%Õê*ÉJ ÄBZ ÆìÏ^ûw5áH˜…’Ê@Ïâs1@¹:2ç9¨Xv ƒ­ùw¹†B”07ð­>/K(ÅüSŸHZ† à˜Z ¥e'Pñ¬õŸŠo¡þŒ!µþ Àšú3k-˜¢X­?ƒrŒû8ƒ¤²NÅ)7hŒ²?k8«ë ˜ÉIžkëÏ8°tU Æ)7Ì!§æ( Æw Œ3íÏj¨)÷g ’ôg*udQH˜R ššSdjŸ fcL¡9`:ÀÕ¾ÈþÖáà´ÃwµæÏ”C£ä« :~sËÅÉ«…Vº=hƒ¤PUÃw÷g–‚veàW ‹Ï†E”ÖíÆJéŠ4¢•Õ ©«‹¨Ä}œÍ}± åäª2 Ú§¥´³o ¦©nK-å sƒT‚¥ÖÇq°œú¸¬8û5»-µ$Á’“ËmÉ‚isNDûXxA2ê"܃aÁnäD¤N*'ˆ…|¶ŒÙˆa\³;™4Q¨Ål¤ÜÇb62éc1[²‹˜-gîc1[ÆÚ_Ô¡£lo÷7¯Öûþôt·Ýÿoy3ýkº¹½Ú]y½Ý]^>›1¨Áqj=P%Pk9ÂßH ü Ôï.—iKÌ[Òi •¯¬¶-Tªi]¶ÉæãIU""‘ó,îÅ’£À=œ'Ü뤄2š˜Ûf¢5#\¯Ò*·¶ªK]nëªÍ¯ÔbѣȽR¹ÅVõÓS*x²‡2(ל§µz’Rë&éF׊Å(uÖ¼âuJ+ÝH™–x3§iD¿×jI-’ç†#lï½hºuï™Õs~áC‘àK†)"^"E„ê£|Þ à<Ü]o¯^|o¦\~1ÊæCiç@§iô¿éˆ>8r•wPÎ#OMl˜ãë°ø÷¾ Í¢¢·ÕD½ý¹~õý÷Ïß:XR ë„­”Ó£—DÆÓÓgoéDäœ*úÊzÚ`R„B,Â*¥TÚ|wÉ LYÜò²å@'¡€>­‚ŽïŽÀ1ÀÅö»Ðé®ÕþLll¿÷C”RÔN\¡Ârêàâ9 œ6¸¡¨s{Ó`¤×äiƒ[‰øâàš ºS“W£§­"ñ·1÷-áîµöëØ÷ÎNËïœÒŸ pÕ÷ï\ᬠA‚¦9Ü!°HõE{7F…Éù+®Ã6±ð]*}<%Ÿv&Š˜\};áUŒÕ~cÉÏ¿Z:—"zõb)J5 8ñWdu¶óùyé E¬ûy ÓhÆç‰RÝõŒ©~QÜGÐô¹µJ±ó¤ °$w;ê&Ñ3fñ¿ÔðóÿódN¿Oåý&Ò—ô€,^ÜEÔ5ë™R†xëw‚‹X· s3åUΣ7Ô“~}?¦ÄCñô•Ë™‘KÉ'í÷P> stream xÚÕYÝs¢H÷¯àQªNx4Š.9xî&·5Å)QêŒàî&ý5æLÎÀ(èÖ½XÂ§§GXjI±Ô¨uã´> E’¡.å¸N'á+y¾sgÍlQ]/Ré$&^ü ÝÛLI¾z4ÇPç^3qõšEbù±ò-þCµlÍÐÏÝ+¼Ç7銞±jYé™Ù°j#ÒNQ¨Í>{M‚«Ãq­ÖÓìÞÍXŶ1tf´J-ßôÒµÿûÔ¼ ¾¡i"ô«_ÔþÔ)KbVUèm! t¬ÐÑɧæXë“Æ UyQõ:¡: þìH‰$‘B¯ÜCZBm\ÛÄаúàaVHÓuTel¤é™Áš±tÖ¨”H›Àš¨Es8Ò.Œ´ Á Â3ÉþͰnàϳڒEÓ!”…ØBm¶>7>X™ñ&°ìÈ”Œ°¶ 0uµÐuBÉÕ‰@¢ìÊDÚꤘ˜4Ïd€SÝžš¦a¥"8T 'NÀé¢tðäÚ¨ÆÔÁÆ[=}¤Öμ™§ÆêMìÚÂLRnæ#J_µmòyE©‚v´‰ ¾k㜑e’ãø»©òÃ#Àá¼{âXD»Ÿf?¥¯ÄõéOz·ç‹ü9 Ô•¦éǤ¡kI»Ç½ÁXµ~áŸ7ÇN,׫š=¹ýzÆx¬é£7O{-Š ÛåNy½'Ž^BBúþYF„+‚È T${ä…ÞÖM¼EÞì…çsþ}¥]âçó’î€X/|¯ñmþe­ endstream endobj 2683 0 obj << /Type /ObjStm /N 100 /First 1016 /Length 2838 /Filter /FlateDecode >> stream xÚ½[Mo]·ÝëWpÙlø8œ~F€$†Û-`Ø^´5¼p¡H-é¿ï9|Oð¢Ô†º@ PÖ}Ãs‡3g¾ørÉ=¤‹¦ *\ðGæ"íÎ…Ï• Åjë\”Ðóx¸In\µ ÒÊ V"ù˜A¸9›ñ¦\å U W¤Ùx΂ôFy†E¸»á‘lÜž?´¬„‹bóÇ(Åñ‡Zù+7êB)ŽWHU\ƒJ¥€TJqjF,^‚zRjКøŽxQm&ØÃ;Qù\IÁ$ñ¹"Á†«L+ß­h0Oã9 F%aåÁjÏ•`=qßR#>üÁ¥8ö(:î|®¦à6BÝ uZsðÒ‰0 >J©¼îV=”Ô‰ ¯Pr¦ðª8îuBKzS!j[tž#>Zñ’eè«ÔªeBnªcn8æÒù×Vpà™PZ µ;¡´Zê„Sh9ó8ðkS'|¬Ù°‘žC+ÃHº†Ñ\Yh­Q ,¬§L)xƒ.>ž«°ª6žk¡›Kï¡»§›\¡Ã^ú$¡7IM9ôNû¨Ð¿¤„·ÁÖ”2º&ÇRarX, ÚÃ’F[xžlv™\ÓN¦Âf|sƒ"ç5„ ¤7ˆ£=È„ì5‰„ä%œ¡ “H(.ÍÀ›9ÂÀQHoA H$Öâ’·Â>ËÂCug6vî…D‰c 1:Xe' t¥‰ùŒUx&jIK•¤µYÜŠÀiVа)¶Ç“Ð;[(04(D{( ¶†qØ#Rk­-²vG´€}ö¦¯H{+_‚¤+É#SiÈ-ر ]ÈA„ Oì¨mÕAãÿ8Ô Z`— ÒÖqNB´R“ÈúÝüÉvª°ÔVŠØè  ²î ›æÙCQDV@YJ…,±3Œ#Ziö¶"(†ºƒY–f’‚¢Â5•†YýuX–U+ÀvfvL¢,dÖ:,Y‡ 1Ñ2VŠè{AŒ&#ŠŸ¦2@1ÑZÙ¥¥½DÕltÑ"$ª–yŽ® кƒ²—†šgäRÀ i4#¡o?Æ"˜Ø)ÛÃË ?ÑUØöÍŽ²JT¿l‚*R~ðuf_O ç=J°>öűùàÈ  ÉñUl;“X¦,,¡ƒ¸ÍØŠ€JPŒ‚ .Û«Òé–6\ÆôŒ0Zd¥‰²kc5¹°FQ¤y‚Ø^VŒ½³ki†Ò“íñŠpÁ:¸ *•c˜XWuðVÃd¼¬¤ âR¦RÈó8=ªô= ¨ qChç$SÙ©/l©¶czD°¼ìÒ·a & ^ÇÔV…°íœ>wN9PqIu;x’ uÇ„ïì"#wb#pÍ4æiHð¼sÞ{]‡ï´ ¨yLO‘Ý²ÂÆGI°U:cß$¸/Ã{„;îò&œþñÏÄãVJh¨¤Øõ¹ûúÛoþïÃ5‡Kq0TýöáW÷wÁ+œÛ'ãS¯PT0,Áƒ§×Ÿï?½½ÅÛ„Óë—¯ÂéÝíá÷ z Ø7§Ÿ ïöîá Çœ¿¡¾Üýüévü[=ÿÛßoùõã÷„¡:G]ž+^x#a¼þøB]Q/ç‡ö¿`ÿ1[$¬1Z¼,|.Ê\Ô¹¸>Ü/‹žæBæ"Ï…ÎŔܧä>%÷)¹OÉý"™£ÄËBæ"Ï…Î…Í…ÏE™‹:m.¦d™’eJ–)Y¦d™’eJ–)Y¦d™’eJÎSrž’󔜧ä<%ç)9OÉyJÎSrž’uJÖ)Y§d’uJÖ)Y§d’uJÖ)Ù¦d›’mJ¶)Ù¦d›’mJ¶)Ù¦d›’}Jö)Ù§dŸ’}Jö³ä›¦µGÎÓ«£ gÜBzá0$dÝà¬| af°5‹P( ™¦"¡ª£­ÈrËjê««&DÇÄíª ¤œ} b§&;1 êDª ãÎÂöP(a¾{L蘚(H+8ïšš½EÑEcÂe¿MŒèÁ[›(Õ‘„—ƒlynã…O òÜT  Dô\Va´ï‘cÉ¿Ö1—1z©c$¬¾ÒDÝ ™~÷v"yOÀ©p<«à‰ˆö ¼ÖÄÛ«û¾ó8JÄ °K°3 BÐ~7&þ‹rØÚ~ud”‰9öÅC= Û˜Çz¨#§dM>=ÔY¯øR÷;¨UX†ùÕA …iò~ŒƒNE˜g¢Š0Ô„xŒ&râ5™z.»‚ņŽî-1ø~³ä\¾p5KvkêÄ3˜¥VÎ诇ÁRív”Yž)›E2÷ÉØ ¾j«‹#[»ù0ãå霼ÓÀƒîÏL¾f+Ùë•®3g´K5ôgÀà5bï+°ø²g÷,Ty½ìŠÁtÝ-{ ƒ­1¬Æ dk^¬¾€ÁÖG¸ø…°+3z–Ã1dµäȉח'm ݹbH›=bÞ©9H“«[â}+W³gµºà›/;²ædœê¸ëÈšýÉú×¶Þ¿…ÎkE©y‰«nª>1ß.®ü > stream xÚÍ™[s¢H€ßýý(U¶¹5ðˆÐ&ܸf“êb ›±%!Ìl’_¿ÍEc,`"°/j}Îw.}Nà@0ŒÂÁïcI «"$€ðo CVAÈ*Ï"„·àfh:¾b¾†_€( ¬$ tiyCካ½·Y¯(¬Â‹`¾Ü|…à–Þû +¨ ø·|r D‰  a —¸Í$Ê[L*de•ŠF ×PF”GÌ/+C=]Þgñãã"]U4Ïü­«ˆ²»ÍŸ ÀMù'×÷+àŒSY•—è7Ǫ’Ti¸¼&º¯ |iù¾>‡ ý m F„Cáx8 ËO`ßgè×?Höå/‹{F†ì÷w8ÔÌ[5îK/G-5 Æ6ÌäÚôúÀ‘ã|þ|‘àpÖsÌLŸŒÜb…ç=û†’è®íù8ú'1pŸ,Ûñ ´‘…IàŽÃY‘/šÉHc8Ô/¦^§µfŠëX G³çOº¹°> M×9 SÓPM=ËÔW^ÔžfF¥V;šmêäÜð[Ê’†;­' ú8I£i/RcF¡¦Õ¥Æ®¯S/̺Ôi:!žtéXË-2lFkeÛ'1V>NwÇjm튡o:bag²¯g¢ì{µ! ®½{ŽÁn±ûþÀþ¸öT—^r\rÞB´­ÐthÖ.¨}PÖ¿óŽ ·i/(<ß±Ú`F— ½',v½ïànÍ¥Öî€ÍªÍj^âX$+)+Š QšZOiN—ñÊ>h=í„9iîãþ©L=ŽüBq 4ÈØ»µ¿ Èˆ.Ü‹vΟj³¸Ó¸c:Ð:Ü¥Ù^•ð¾fªÅ¾étì°ˆçZ= ôqúu¿çÒàUÿzétb=ñ_` #Á…i¬#bງŒÜ‚Yײ0ÑP‡#­R¯™a6ó—óòç¸`c®ÍTV`õKš6¦Õä$SLÃTi«w4Qÿð¢%I:òØŽóè¶ðp;îWÁèQ’|‹æEíøç`._‚J¹W4½(c8ú¹|´®Å€ïpHÒÑ$.ó”Ç5V®¢ä ‹º KÒǸßÕ’[ªfêQz6oÇ<<Š#ȳ8Z¶„Â7è¯(³Eþ}½™ñSÞ“Ф¶½Ðð QOWAÈß½»ÄN¶OæbµÈQB~2t/FÉø=™;I ߊ»O“çUº¤?''‹©‰B<ÏÉbõAIhWRú#ÿÔSš}@H£P¶Õ¥¹¦,Õñêù>&øÍ’}/»%‰…wÌ»îõ{wÄò2·Þ»‹‹P©I¼Š3Ú9o+ë¾Ýâ¹úm¤eÏx¾cÎh ˆW»ˆÿ!~þ endstream endobj 2910 0 obj << /Length 1130 /Filter /FlateDecode >> stream xÚÍš]sÚ8†ïùºÄ3[¯lKÂ\¶|¤é$;ia¶¦ƒxjËÄM¯¯üE ÃÚ2¶ÊÞ„ŒWÏÑyu$ Á @pÕ{7ïý=ÅØú Ì—`u›0š:1ÀÜ÷}ÛÔ¾Ï?dÝ@–ø^võúŸñäKúFo2ï=ö qcÿ}ÛÖmEØ»ÿ'Þû n mð”}2[:Îô0ë}ìÁC&48`B}0ÒÄÐa 5v¹«½1v…›˜&‰±üÂÛ»ë¿2°œ(^hŸ®zà>û„‹÷óÁc¨M,^ }ˆq>ÂÇÝ(^Ì5Äý— uæYN}°ŠQ…BJ”tŒ©fÁ~ eÜ]îLÉçÑEbTŒð¸ÓE¡­ÃÄ©:ÄóG i©*‚4„ùìóõ-å®'FжL‘ÃXV+²5öiœŽxã'\QF‘4#wùVÑÂiÉuï·Ëeè²÷^|a3>™«É‹¤_3_Õä•ë n¾¢ÙÈ ‚w¡‰>øÇ”)JŒ\•ß ”h¡¨Tl9N}æ½õ¼XQfl©9Z®Jï‚èAYÏ€¤Vë”|–|¢®§(8CÉ$}{á¿>WÔR (•´; ‹ýRøluyT™Í ¤zßcš‹Ì¢}lŠ–Â™Õ…úu}¿:؀؆ŽP!¿~r’B? ]ÝG³ ¾ŽœÏ8Í÷¼Ì Δ*¸øÚËÀÚP•RwÇg]¨DÛ¦05I½¤Aí)î4$ÚçX3Äß0©ŸhG·xŠ>ÝÒ:n°ŠJY‡5ªVÆ? ~íTRïs–!o©RîIÛɬónÊY{ñ™Bd_Ä©› ='ÙÕi•P>Ûl¹Pqø:NÖQ൓ ÝggY†‰‰ð#i§ÓGgÁxGt /Žèº‹_’Þ¬ÈGÑn7gÊ©ÍwG>osÓÕtTüÿ‹µî5“.”Xÿ°©Ä–ÌÊüÈÚ’Ù¡TË4ó³[°ªåÄJNYâsÿ§& Ž:¡h¬ÚI6·«2•›¼ã뀬©IYÝ›”Õ­IUËeR- aL¿Ah¹œÖ{ªðÒ¬'@]-æ-îüæ+ª¿g\ úßʳÆÒ§ÈƒJœÐg¾º|±nû¸;> stream xÚÍ[ß‹·}ß¿Bí‹>Ý’®À’·…L⇶Æ®³”аì5¤ÿ}ÏÕ7w>'o[2+Œ­ÙÕœ9su%Ý£9æ.%•Ä](‘ˆ78q«Þ$ü¡©â×hÔÔšz£¥>º7z2o·D¥ÍûG"톻@òÀÏàÚØ[œ¨‡WIÔÙATYs­‰Æ˜ýZbâÙ]¸Î~ #6ñðWeÆ3jq¶Î©:Có~ƒ¯âÊüº™#ךDÈïÀ#EÕŸxÑ;ŒÑ¯VëÚ’2+žâ*¸DK’ªùo¼##VÚ'ƒ†;Ìf¿žj¡Ù²TÉ_¡·‘*¢ÕKªJίSªUý=:§Úº£tIÕŠßË:töCàK÷èö–çÜ{j"ÏRÓ>û Pñ·´’šZ”šµŽgàõ{)ÞÏ$u’ÙOSç9nVÆÎ‘ñ ˆ¡Ã‰·šµô‰70ösÜ0+3Vƒ’Ñ <ƒgÂÞoH2ã†Û¬zt;à­³?m´d6cŠ<²1£†dHo4؇Ñ@wH¢EiTÂ{^p4O+’†¿*ZšÆ yr¨·44 b()ÛžªŠ”D¹ZªÖ0TºGÖÙZLüQ@¤2š?‹¯h;²‡ˆ=ïð4OmÃxé˜x5ž·áiÔ=†ˆšæA4d'qñ(’ˆ˜ZÁÓÌç<ÄÓX0áp‰ÛX‹“döåÙo¸óÕÏ!©4; ¯4ÏiŸ}}¾üœÛc¾<€5nž=»9½ú÷·éôåÝÝýÃÍéÛÿx˜×þþî_7§¯îßwûþµ/åÍé§?¾~MóâæôÍí»‡ôZ:eAì´RF¼’˜dÁÊ raF¿/Ó³géôm:ýáþÕ}:=O¿ûñí?osk¿O_|qƒ?¿„’edšÊÈTýߒͯuäÒúý8m.¬rÏ„$ÖBy TpM¼†„ªfŸ›J5³ú¨´ì+¡rEdVE¢÷,È>dXfó”YJ¸.«"Á”3RòÓ‡Eðp®sXXWEÂ,‹o5À$ÔR26 ´(¥f¬¨IZÏØË0 =v•9LÒE¢ <´ù¶š#Ö¬l(¤ÕŒöªœàs$Tr%Ï =G¢ "s-väZUˆêåG®Ø™—”µÓ"U3aó¹aOÕÖ°zƒDfU$|Šbs“ÒsC©çSÔWNA‚ÖUše/[yÔÜPÀ¨•ÜŒL]É¥Îí:{U:3rR’Û*:{q€ýÜ«EE& 2÷‚YDB<ú^%U¬¨ƒdpî^Gbõèºnj°×ôêËäyfxéY;âr-ãÈ8hç ¾tc†Œ†$´".c ÏBTìÐ]’Q¨«ÇÛêQ_4Qo^1‘Õ|»Àúä® !ª]!QŸ€D¯¹ö 2èj)QŸÝe3¦#D¤²"Шþv•_ç0ާ€±¿PÃ2¾–*KS›‹Tó‘ Ÿ/W(Фj:ˆÒ=Pþsiÿm2þðÛèüâþîa‚¾¨ÑÐ|ó® ]ÞÏèxzùþþÝ·· ˜N/Ÿ¿H§W·?=¤7?ç—`rsúx·w\*V¿ß_íÃýÇ÷ïn?œUçüÙ_n¿ûþíW÷?¥Š’QÁêó%èåÛ÷ÁÂhÆ è<›8­yj²5$½s†Ecl^¢AÑäÈ={ ÷@îܹ²²²²²²²²²²òäÈ#G @<yòä±!ûyÈÖ hp4$ ‹F S S S S S S S S S S s óùÍ1³ÑáÄÁdÊ~ÈC£ûQR3îŠÖ¤uÅÎz‚Û…ƒ‹qå5«AáûÒ!/°Bù©— ©sÉëšM*H4kYQщ†ú¥Ó*Ûh4lÕô6­£È¦+úŠÚpÀÞØøÂAQT/f€­±ûùäÆÀ‚ÆZ [ã<Ý(ø Œ-¦€*ÞÆN¡úÑG[å<°“?t¨«9@ï—~áàr_WqØE!A¨bq¨Ú*¼v…RÈ\®²“PÈܺê¸z'¡~Pú ‰YYÒ"[JøáƒŠDJø!Ì(}ÑÆ¹B ïêü¬±ÂåÝ µ£!w.$Äå-æy×Ë'šËÅ\ß ºpÀvUØ<xö òóʱ–»ÂëìOÆš³êDm¹\*)ÆF&¼ŠÃ¶D°pž%60ÿ¤ŠìjI9ž Å2_ö &˵ØÚ¡ y*7v44×±šD+Yéõ½õÅ$¤!üŸPÔ÷}5 bÿ…3~¾˜„¡¾· ‡ayÔUŸÔâjS¾qåÒâkщ}ؤïNÚ·J]LbÓ¾;‰Gµïí$×¾OAbÓ¾;‰Ž¹Qt1‰Müî$Ô ÂtÝ÷¬Î»üÃêÇôï|»ù»‡ú·tY;!€ƒ„+`j²t,BÇ©ýã ø VËPÀ{ @F®Òµã?_„ޤtŒÉ²ò Jèß ׿ýê©L?žÃ&w"£kÊñ6õ»sxTþ–ãs2äoääãò÷ –©¿AâQù{|R†úÁÿ¸Ù¯T2tä"%<9°[¶<917M¦ú…èúuµÏ¡hvkêÎÁ?oÖUÎcâ7ÆÂůj]4‡³öÝ)`»ZSÒñ)¹IßÂcÒ—_¢6é»S€ôít¥Šb>þ{û¦|÷ïíP¾WËI–#í¤(«ùÿ8K ¯§Ü/m¨i¯ 類Vɤ6å·Ÿ÷Õ‘Ü"þ˜üV;ÖD)X@$+ê7QŠf«nbãU$PÅmÚ¿4ß7ÜDÉó `˜¬"Uz¸QÞ‡Á#áÊÏIÕ\®•1‡’Àò¤þ‘Õk”=~¡Ç/•Û9DLPW«{¢_šQüÿ¼|f3Ê8›~fFg‹Âo1£¸ims„;ÃÀáNp'Hø$î’ð=Hø$|¾ d d d d d d d d d d d d äÈ5k ×@®\9¬9V¹r äÈ-ÃÇcáã±ðñXøx,|<> …ÇÂÇcáã±ðñXøx,|<> …ÇÂÇcáã±ðñXøx,|<> …ÇÂÇcáã±ðñXøx,|<> …ÇÂÇcáã±ðñXøx,|<>ž>ž>ž>ž>ž>ž>ž±ùx>·¦þhè 8„fãÀ¨6„ÖÆa÷Ïlމ­•imþWû ×ÏmŸáÏoŸá½äüþþI endstream endobj 2951 0 obj << /Length 714 /Filter /FlateDecode >> stream xÚÝ—]o›0†ïù¾ Ò —[ÛU­¦©]¸˜ÔU– . H°Yšüú™¤I— í¤î†D`?ç=>¶!—ÊgOùøÅBÀÑ\ŒMà=jÆÀv ëÀ ÀÝèêÛùÅõÞ»™še›rjõÁ1Ë·Ê…§Ì]¾„@ßÌwÍ1ðåî‚@~»P3],ª‘ @–„¡6åVÛš½¥É…šíJ4Ö5¸•°$ËÕ± GKB§ÓÌgÁ‡JM-#=ß/p76lgdÙÍ÷ÚŒ|Œu]s-«Ω Ñ‚øY‘Šá¤8傦>#TêG'ñ3PúK‚Úáßùp}œ5¬XjŒÓx ËÓDEÈÈŒ†ŒIë®æÖ.óv5TœxUíírNU+âY–ÌrÆyœ¥õ‹O7W"tÔSDÎhB&].9»´X“G?÷‰i zé’!–36Œ§Cç¾êB¸­ˆlFçÈ(ĉ¼ vdÆÒ ¬þî˜öãœîT’ë`½ºUÃu7F÷˜…ðV«Ñj±n„+OÕ 8b42U·F‹tÒ˜yQè(CZÐu¸Bh2¿lúeÜ®Îr£³,•ƒ°³ §GNž-ËšùצçÄOQΣlümoꦎùŠàˆæª.Ÿ ïî§zkÀÊ'YÚ 7{¹øbµD¸ï&áö¨'.¤Ui0!ª¬õâñQ¶¨6Ûï4¾\•¡]ê—nþ*fÿI mçRDŒNN=Ún›]”{Å{n¡¨Gù?eù[nM‡~÷]H-Kƒ¦~Ì}t}7Æšac´u7F–†q“›K–²œ ¹9T«Ž½¬ÿŸgeƒ{Z†êXF–¥;Ò¥Ä?K± endstream endobj 2912 0 obj << /Type /ObjStm /N 100 /First 1013 /Length 2529 /Filter /FlateDecode >> stream xÚÅ[M·½ï¯à1¹pX,’€`À¶ $@¶Iy1´†,οÏ{œál|p=m@ØaØÅÇb±¾G»Y*I»yjÒ0"Ù¨´TµqÐSÔÁÁHmp²—4”“]’”ÊÙ®I¤·ŒŒ$9ßAÜë|¡&©}¾IšÌ7ZþÁ¨'­s„פðÝ tê„HÖ”#ü©Å±F5¢ ~çI[ðÝ c̶PtRiÉ$æ»=™çh$ó¹±(Éjå!Ébp5L¶®Š5À 0‚DÓ—>çÕäªÜQDr# -¹÷9¯'!ªÉ7Ó[IÞ;ç5Iµ`3Uœ¼jF“róT]H¹ÕT«“W-RFÊ gÑËœ×S>祑^/)´pG]RØä– o†5ÀöˆBTÝS4#*À>yÚ#µR¸Fo©‰q lµiã'î…XÀœV'Ç!-‚T†¦Ö‹`a #°¸—˜GQS—y#ä¨FK=NbR Pðî(%uF’0£s¤iˆ–Œ BǃÅÓ°>çÕ4*em`ƒ#Èñ&ŽÖæw=>)Cšáâ;H]Áùs"µ8ù;p,R¢t,Ù°Uø-dµðŒ0ÄkR i ¤U„¬XYD)}C †Ž`ˆK!ÕøšòVDp.î‹HÄH"ÃÀ8l(aw1çb5•1çb55t±šBª8Äj:y6ÀLѦœ‹Û+S¼1Äj:(ÆÃæ%Tns^q­þðâÅÃé›ÿþø˜NŸ¿ÿôñáôõÏÿú8Ÿÿúýûÿ<œ¾xúðÝã‡7Š¡¼=ýùô—Ó—od><œ¾z|÷1½‘^ó€¼×Qrïqk3ðD‘¬³>O/^¤Ó×éô§§ožÒéeúÃßþûÿ÷ÇôÙgø·#„ˆL»@¨­eÜà߯ q ®yàR- Õ²×- r 22µÀ #WßÀ c >*øûŒ¡Ô¶!VA¡.¼Kn[2iw8 w¡?c¨-w9ƒBíƒY†ÎÛÀ ûc°!¤ê»`(#±…ÁAåŠæ"C•o`ð;`¨ÂòŒ!4K‹ õ´e:m ƒõ¬ÇêI+–éš, âØj«'µAÛì^7Îâ|Ð !Œ+X°jäW^E–«ÕT°Ð-.ÜÁrk^…JÏMüXˆ; øÆÂ ÃáÎl`;( H `âéõ‡§w_?_:½~ù*¾yüåczûë-¿’‡Ó— ÷øþãOìáãÖ¾âÎ~zúùûG~çãüÝß¿ûþÛ/ž~I“uœÝ÷î8t¤×ß~Ò°óüÉÏŸ°þl$¬ÙxøÔ5ˆ5¸Nîk0.-k k k°(뢬‹².ʺ(뢬‹²-ʶ(Û¢l‹²-ʶ(Û¢l‹²-ʶ(û¢ì‹²/ʾ(û¢ì‹²/ʾ(û™òÛj¢¬*€å,HJkPãð» h7 ’uÏÒp¥êôYTö2…ÎÐðfErWmêíY‘ÔÙ·cÂþÛ[É}9‡Ï’¤±£*hÙûÍ’ä¾Z6;—$­²ybd»]‘Ü÷,`IÀ†€þf#¹Àë­dmn;Ã¥_!šS¯ý·· ’ûv,0=ÁÚÌù o[:Ë lÝ‹=ûxTfÃFT˜TþÁ˜­O¨Gî ÏzlÞvJ#Çû¶×¹+a¨¤kE’NW“O©Hî Bjnå¹$)C)E|<ú#öliÂb14<BÀþ.+’EÇA”Ò¿ª³q ²É?+ÜïÛɱïÝ„—Š$¯†ÀûdER6sì{b°sŠdëP×õ‡Ü®Hî F’UQ„#ÌW 3ìNi9Šˆ[aIÒ¦ñ`Wħ”$ÇïÿS©¿ÿO|O Áœ¢…ÀŸ—ý\{aU*ê1Ív ƒAS´ÿÃàUƒ0@3T6ú!,ì~82r®Eù'5oüï°¼q endstream endobj 2968 0 obj << /Length1 1416 /Length2 6052 /Length3 0 /Length 7019 /Filter /FlateDecode >> stream xÚwT“ÛÒ6Ò„ RE:QCHè½÷*¥† ”$$‘Š ½IïU©*½ƒH‘* H¥ƒ)*J/_PϽ÷Üÿ_ëûVÖJÞ™yföÌÞϳ×Λwøí‘v05$ËI•uu5Á $, 89áXWØß~§) #RÿPFà X¼O‚Åu‘ ÖW X“‹K@@!Hòo -TxÀíº@-$†p*#QÞh¸£¿Îß@n(,))~çW:PÑ ††C! .ësï…¸P8 ëýÜ2NX,JJPÐÓÓSâ†@¢åxî=áX' ! C{Àì#õ n°?£ 8ÆNpÌï€Òë AÀx‡+ C`ð)ö04¿:ÐHS¨‚!~ƒu~îÿl,þW¹?Ù…àˆ_É(醂 ¼áG ÜÔWÓÀzaï!û ăÄçC< pWˆð«uPMÑÁOøg>  Ga1¸ëÅŒ‚eðÛ¬Š°WFº¹ÁX à¢?8Åï»·àŸÃuA =>[p„½ÃÅöP‚&¸û˜¦Ê Þø·Ï†Š‚$Ä…%D0w Ì ê$x±€±7 ö+¾pãgðóA!Q@ü0?¸ ÿðÁ@<`@,úÌÏç?ÿ´`0ÐÅí`ŽpàßÕñn˜Ãoþh¸Ð„§ºøüëÉ Ï0{$ÂÕûßð_G,htOí®’)ߟ‘ÿTRBz}ø……€üB¢ $"Ç?øý³Î]üOÿ‘«‰p@/Š]ô‹ß¨¿{öøCî? áþ³˜O]ûßL·‰‚ ø/ðÿ™ï¿Rþ4¿¨ò¿2ý¿;R{àêú+ÎýðÿÄ!npWï??»Úš#»]ÜÄùþ¥ñDŸ–[”OÌR”ؤŠÑÝwY£¨ÚÉåí»8)}ÿªîü˜èÉEW¢&®Ò¢×Ú^Y’¥CÏ"iúå“!¶É®ÏxEt—á¯ÜOn±AKÑ–©z·´eZ žT ½ý}3Ô]¬QZV¾s„b©U¥ûXTD.W˜Î<½ö3·Øc3ƒÆÇNVaÓ¾ûÅ8‘³§;­­J\SîQˆšhÜBÍŒoFÁ“ã-°à›ZhzU´2ÎÓmqß·ÂkÑJ§× YèW†kqýºðúq4R Èžól£-28†A 9âVÙôRWø[)aœ=A‰^Þ‹ãÝ@ú·=Èa€GI`ôñ&ît“0¨@ÕâHžß½.m:Úæ(Öû´›‚PnòÎù¹æTý-7EÐà©¡pýD/]ŸO+ßSúæeIêÅøƒ•aݤe}J'?~ÚiîÇWÑô­'ÄF·(.ì6åFñŒU1½ÒR"H& ùìsÖæ®°#3ÓN–ì5v‹Vös»s¤ÍõïJ,¦óÇ=.×o›ÝbÿÊH¸\Ÿùz²½Ž¼¯†Ñç N*àܲÚnòŒÖ{Y6¦!·§â·÷l:;¾û^òµ–¯µU`çûåAŽ%×HÛÀv­MYZÏ!¾¶­N1Åvy:<ïmA-¸@ÎIß«Í Ä½´iNŒF !O¹HúÑ ÎøG7&¬“ @7³«Ît}g a¸³ÐÆjS¨¨á%Äù¦Ä'›Á$y÷¦g*…=žÇÇÆºäÝ±Ž¶KÈøŽh"ƒP „ˆØ(‘.mÐ’ÐÌœô ƒ·øF¦¨Ç.Q~1««êG!³TN²^DµzÉõ;|Ш9¶`·2VÝïpÎ0ì‹ôä;¡X^¦ßf¤QͺJ,ãÌgPÕ»¹™Ù7MfíëoÖHÛ‹<Í7.¤œ•º³tìAwªË;3!͇¾~Ù<º‚wÕx£À`lÞ³[âÞc'¶ŽÑïi™èyßç¨MùØ¿lq ýô5¯Ì'Bgt“+¼½Ðož-¹Ô_´p|ð­n^N>vj¹Ö8ïcò›¡gÆØ¢ Œ-Ö´Ü&h^ceé` ÷>ùÚxÍ/8/ »:eþ4¨ù–xÀ¶;6xÁáØ¯fu$‰§2T‚ØÈpÌ<ÙûL¦VÈ9Yߺe1¨™Š³ýJ¬IvsÈ‚ÜxŒ`^iÅ3e7äü hˆ³Ôï jú†ýg'z¹HšÈËÖž*Eß`»ö׺ˆ6 pû{#Ö muòd¨+pai–ê@¥î&EVØÉ [ïîÞ¢‘[eÚÐõU`Wî盟ÆÈÙ^ÚÆ7ÇÞ“·Q´¤é&C,¢€ê€lQ¡ûÂR Ù Ì}2÷ÔG|À‡çPSMÆJ"1n´î­Ãlˆ}@@Ðìs½ÍP!+(²¸/²s.»ÅúþÒÃ{ºÂÉš·CC{²Ê×r÷ã½OÚ:&ÝÍ|á;¼u]‘¢~Ï %‹nTæÞƒ´ÔR_ƒÝ[Ïð‹#{&ä§úfcZI?ô2úòô `±X»ÿ@hÛE)!¼çÌõ›œgœù†Ì'{1•=Ä^4¯hý–Õø92oeÚÑÝä®Ã¹¨Úa¥kz¯­;4ve»P,ë1î‹”‘Š¥ïÎ×Ìœ;+òfÚ:ކ<¯ª&ç.ú,=XipÕ„=Xe·öVAú°S™@¶Î¥fÁxú3ä(î¨H~ˆ!Mù5­¥Ùf·<ä2õ¨ƒ>™ÙÜ;Â¥’Ü’G ÙƒøÁ„r® ѽ+oFKŽêÞ$¬âŸ×¹gzÿ¹Ýó‹AЃAgz9Õq—ê€ê›æÝí:q­õ‡OzãMR+÷3—€ºa®ÇÆ,}ˆÑ3ïÌ.˜IOÏùOLˆ"ñLV$2D˜}È׊Xa•¾¼ÊŒk œÕ+çJfJRoV¨ ”$”îѼ´1¬†Kâ(j 0ù(¨MHäúÁAÌË}!•ÜPíéWõHCC°†—óxÚ.Ù%±âç½*o¤×»zçòo©^ùÕF¯Òˆ,½ëx7ä›sL×iÕ3²‘ò±÷1»@Bò,èq3ƒiU4©4yg-e uiè…Çx8[~<+§Jt^^¯ÏMÒfÉÿf4#[ΦV'@ƒ‡m°WÇj ºŸÿИÁNÇOPnHÔ…æ ìçSý3qzÑŸá·™¥’?ÜyjbC¯sW>¾®·ÿ†žrùª‘îþ{øÖû«SrÉר{†ÂW®¬üæýà|Û¬3[eCb-Šc{Ìw;çfƒZä|ÿ`dãÓú”N¢´ÍC€½AŠ–&G}sJç½>î ôn†îk´ùZ þTD’wR^ˆÕ|ºa>Îó÷R¼Ü|Æbt‡D+DF±3¡8Þ=ïíÊýhIçRÓ0öe;Ñ–IÍ·/käíŒ/ÜFyéOâŒé$ã¦U› Íôù§R&:¢)+5ÖQ« × ¤l·È,q§¯©GÇØ‚UMI|²Á;àÁ ãªdSÓQQo3m_\ÀèÎRêwß©zìåg%ûõSÙrܤðT»ñ„–˪EukÝÙ{aÛS¼3drE×Ôìyæ¾ÀgÚ{üصô´õʲj!\öûñÁ…a#1,¸ÎµkÖö¥]Æj$An3æ&ý« Oöýôq•ê5#ìÕB¨è—·Ê‹ QÝ¢T½^:*oÛÓ"ëžvë±¾3$êD}ÍrèñZRáNy4ˆÈ«žšÈš†ÏÄ<y¹Ú9ÙôéX=GVIĶ£jñŒŸ¨ô´áËÞµµ ’@Ü«”•Xt9 åÆÂ(G¡Òs BÁȸÏRJô{À‰¹\êÌ9£Càb +Œm a7Ù7£9‘»Š^$w¾˜{ý»Rõ)?µKË˦œž—ÂÅÝ“—ÚlånQ³ s6Š­~h¿ß<ÖNCv‡ÃFî6®bATÓƒòø^þ=‚‚Ô|&QñTÂM7¹÷9‹Ø¾UOúÖrº?éHBI+j¾e?õz#£²zѵ€D½w¹•»æ}¥Ú—¿‰Qµ+ÎŒ÷ÚÚ.·:K RÞ ¸_p~fRÄÉ{,Ælùq§^iu1q*^¦cån4ŠÈ¹, ½gݳÂ/™ƒ—h=Ïiø9|eRØ=ð³v¯9Û9Äï)Àò5VCyãòVÿ[º @eqø²ŸÜëZº’NT*󤂹ucøÔ÷µ€O*´2Ìõô8?œ»˜~ê¡2Yß··,,“÷ÏP@®TbÊZÕç j1n<ó7æ „IJ±ó†+ðLW§—ËÍSåt©ÉõÏ6Cü/ý\üuF>-}}u@]¶Ëú…ÓÇ —ŠÌ&8¹„ÝXü¡ÆúÆ¡—ú¹@|(å&ƒþAhÆý¨oÎKjtÆ3-ï®Þá€l1NWc’jó >Zº@]ÀÈ*¾Õ‡daƒ«óĪav[Qw”ËÝw:¹BOÍi75ó3{ÆÓˆÑ¯,§ë_?zsþéĆ´õHXlFÛß@É/¯Èrx¯*t|Ç…ôiÐPŸb;÷¤•î2ãjJr*ºý™8ëÀ²‘÷úÉU®³Ãï¼eYvK¬q¢ªÑŒ8޳GЯs £HTì+Åï„NÅh EÈ«p[­·‰g.Q-MƒêªNã\kò׃B€ù´ å̶ÉÙK ’Q7Ó– :‰ãT+C,ÅJ\[Å_L¼&Ò¡üª#L+!‰È—ÆvŸfÛD—+Ú~¾Jj•{ñEÛË]¸³pá ¶˜µ,s=îïˆÙÎpPþ ìªj¼BEs’À–õº¦P*—›UC®¶6uwp¶f\ºâàcï‡'Á~nfYëü?êt‡p[Œ_\Nôäi'¦QÎ&Ó"H˜š³¤ÞL©Ÿ úúEªë·¨9'Ku[»Kû6‰‚Œî¹í>kaÚ ÷ŒÚñ½­¥e’[/Î=Ú¢÷œÏ¨ bäÓrgYÇVEJ0R­V½ÌÒBå!¯ªå]Ûj«¡t4Ëgw voÂÈò§7ø±àÇ™{ãídB“gN]NW|æI×G’™Cy´Á±o{ˆ–¾J¨sRG †ZÞlö4èþK>Fœ¾æ€l2‹Þ|žÓ JŽü4¥r3¥ÞY…|ì¶„ô•‡O¶kÏw0Ĭ¹Ö•²ŽÊߟÆ×ÎÊ­m~À]–ޱ±JlAûãÿj$VDbRt)?Ww|Ü”vô†YŠòHIV’cïòÞMŽLÞ±ø½ã>'4åÞÍ rvX©ôÚÀµ€Q³n{ÿõ3jÚâ9AÁœx¹¾0Æ ^iúÜýJü`cÅ‹¤2ª ÔgǽKžÞVó–Y3!w·ogò9 µë÷¥}ööŒ›DQ…¶ç¾Ž-Ö{º5Nµ@Úê²¹Ðe¿àÕ¡é¤*ÛT^h•`…'´û]mþ¦ùèäk¦Ð,cùí«…aÄégÝä•©€÷ ЧÞM&†. Dqø7’ºþæoÛBƒ}[ÌïŽç™¾êæ^ÇÍl¸ùx¼zÜ©‡åÍü‘¥"PI¯dJ °‘ƺŒÏñgfoˆ°rד¨•m¥3^9œýZÍt‰HQ?—»<óÆ¡Š“{æ5¤2­qKˆ‹$I¡½å_a·´+|SöêŽÁzR*÷¦ŠŒtseWÃñü¤æÊ‘†Žõiýü‰b­c¨zâ[=£ÞHhÐøÏæhÐÙ%ñ÷Ê­••ò£Ö*édgÑq#¶)ÛtY®îeÜBV³méz0ælíµ$P ëùâQ8åà…uLÚö5ºëÔ¶wýÎÙeµgÏåUVµ™33¹jøv"òÑ–B䢽&P­›Ÿî™<)u"©ã%´ÍCŸ(R”%šHôôv#ãxQ˜+,GWU ÷]]Ší|;ƒÒ†ñшœ„!ïáÐ úàÉz?¶—kÚëµMƒn¿`ZŒÎIF©JµzögçŒÐ«Bi(s;K;e5÷Ö#еzm¿¿I2ç1ôÚšKX#êò"˜r*¹MÖ¬¢Á¸‘; ê#„Öùw4Ñk^Y mÜ ,”r'¦ïésòÖž­=S“–¹wžû.ä§§ïö‹†yòqjÚ]cAtÛi{Å–b—ÝFKo~íɲk)§+n”ñÇ|NT¹«¬'¢mY?»½*¯zû‡!bô ùÖÆ¢ËíÙÜÝ£¼c_- žó] KbfR:¿;I£&ò*2<)[V™§ß’_~O(ý4·®þ®—º#‘„ !ØcMSwÑ;Š C‚^DP—Õ·²¡ív®¬­S !I<ö*í„K?ü驌ÝQrVnÓ%ÀR.C8›´ìÕLbõé‡qTâFhWh5G„ËÞò[…%²º¢´(ˆn@øë”t·û«a¾'i»vŸØÒ)®`uÂ$Fª@©ýá¾Ãc­úl<óîïV¨Ô’±ä)ú¹„ù²^Õ…ÍÝ$QSW?Ù¬vËž'Rò¥VŒêK®„*ú 2<±¤Xô¶¦¼#ëeÝñ„äelûü1}²0g¥©% ùùàÏ+*$/câY,ïz«$M¶]v3+²¹`9Oñõä¡Ö´] ,ë„C ¾Ì+~­lcÔ-á>E®Uo…W_é?=$% !lOA îÇbG˜(¼(’wöøéyÅë·4†m dvÀý€¦ ãK5Ó.ïESíÍ1Ç)«‚ì]ÌPâ+îÞ†£2½l‹^²»üYáÄ?Õ‡éü*ï5}ÃAÓÇw+†ùyà„?ÜL'æ¹Ku2R–Ì£ž]:CÉ VQ¶qÕŒýT­~´?™/6âdáÒmôŽÉ¿§\Dnw´ÔXÃG®èy];pð ÈRŸEž¯*¶Ìêj†“!9;Ôí·a²2O÷ÿ+Í£‚õDÞÀà¼ò.§`1éaEš/%T‡Š8x·Ö˜˜:÷οšš0ëœYç˜)T|¼°Lï~û@®RtÕ|dÛ†l#/×` ±ø ÿ‡aq·ÓFzÚ\“_K°_¯g¯î~Õè¤uÒPÔ‘Çò”Û9æÜn…—^ÖÍ|:š¢é¹6lUÖ¾ÅȘ6{”ö‚G“ž°ó²Çª1m§ò—tN×Q?Ä!Eƒú g^ÔØ—Q©>L<éçê¤{ô‘´§¸àð¡N“€<¨v–ÿýÒ”‘­ò‚Gâî0ãŒúb»B  [Ý07Z‰56Ó· eý." ïÅá•àõ™úÇãCóFƼÒG mu:›o š›È]\‘YÐ÷Á¸T/©Y ß6qªvMKÛÏ cbÏÏÏ0îaÆ¥­NÄÐSÛ:‰\Rf÷"»ZÒãKŽÏ êtìå¢#µ/g^U8~oùÍHOJâI>ý_ŽÄëEód&òs<Ëã†vœ#'SÈ膀´5¹H±«K]½þ»v¦ÌXÎHIœò¤'ÀµŸj«gÄÒŸÑï:‡G'2E¥0}Ê1tžìÌ;ðh#o Â~峊½Æ»5¸_ŽË+w: š<´ä*êæ k?_ÿé.PÕÈÚ6û®0ìF×Páf¯k’©—ðžqöó+ûœ:v8&R;#ÜX­ R*î½Ñ+„𠸧ï]Ý÷'Qו™ e™\oáuF«Ã<.ëùølrNñ[D/åð§ñå6Ñ X¦Kœ”aªQ¹®_]ÞÈ’pëq@@äu£†U†¬¤²kˆØ#Œ$™Õ„`§X÷¼ø©cKptzy錔–åø AIBûζt36â ¸|²Eé[ý³ðîÏ>¡vî圱ý5GD-?\TÊu¶¼ Z$™É"ŸÝqr›Úç,ú8jLÄË­„ò®Å…K;J´2pœrÝ·»‡©¸\s~­¥ØË© a~ÅѲ$:©cNLJ”‘–à j³ux™L>¦µ Í‹³âŸyíÍÏ->”‘j©èÅynþ¤À¤c>áyR†ìX PHiød”{ëäG‹ %ŸÅºø¬ÍíQxz õqKʽø®ý¥w‡–ûÇŸÖ;V>|³F‘‘àúÙz`G¤®ÿaž¯…¸¸\³èx®¨æ•Âm‰è®ñËI6.ðrûÂø‘vèõ …kzÃ7ÙŒãÝ(IÉùþÚ(›^ endstream endobj 2970 0 obj << /Length1 1397 /Length2 5932 /Length3 0 /Length 6894 /Filter /FlateDecode >> stream xÚtT”ïö.)ˆ"]2ÄÐ1Cwƒt§ä0 0Ä 14ˆ Ý‚"HwJH‡4"­„„”¤Hóãœóÿ{׺wÍZß|{ïgïwïw?ÏdÔÑ瑳EÚÀ”‘˜$PÐÔT€@¼ ?hG9Ãþº €F0w8!þ¿ î0 íS„ Ð8M$ æé ÀÂâ`qÀ‰ý ˆt(B¼à¶M^€ó * ]}Ýáö(ô1ÿz°C9`11îßé9˜; A4!(˜ úD(Ä „Âa(ß”`—t@¡\Åùø¼½½y!.¼Hw{in€7åЃyÀܽ`¶€_´ .°?“ñp?~}¤Êâ Îp( áÎðDØÂÜèÃúªmWâXã€ð÷n`^ð¿ËýÍþUŽø B‘.®„/a°ƒ;ÃÚʼ(7‚°ý„8{ Ñù/ÜbƒüîP–Ó@ÐþÏêwEyðzÀÈ÷« ú–•¶ HåAð«?E¸; оv_¾?›uB ½þ ;8ÂÖî×¶ž®|†¸›'LUñ/í"øÏ†DEDù07ÌêÀ÷«¼¯+ìwüËž Ðßé °C „ÛÁÐþ/åî ôÿßZ`0ÀEl`öpÁª£Ý0»?6zùîp€Í=0ôë÷ï7 4½l‘gßÿÀï—ÏHWÁ@ߘëÏÄÿŽÉË#}þ<`¿‹€"è—ÀVÑÀÿvúOª* ƒþt‹¾¦uìõ—ìÅÁøg1-$šµ0ûHnAÑðÿ7Õ§üßþ«Êÿ‹äÿݲ§³óï0ûïøÿ†¸À}ÿФõD¡ ‰DËñßPcØÑjÂláž.ÿUEAÐBCØ£ÉÌä þñÃ=”á>0[8 êð‡2ü†¿¤æ GÀtð_ßtô_1´¾ Nè—B´ØP¿×øË†¡åôÏ>”P¤í/Ýñ  îî_ôêÑ–ÀŒ¨-Ìç7³|¼$ @ϰCºüZ³ €…ôv@"þ,'øÇPOwwt¿©nà_öo¡Ã`>0(Áì*êXÚrZ%Gëͳ6*‰»—vjÂÏ3šg‰êUš°ZNÒÏÊœS/Qží+[:¶kÉ»¾ú2}ä¿ZËPç+xÂàüÍžÁ&qêæs2Ùÿ'Óq#FŽqŠüñB÷^ ú˜{·elí{õÄl5Ý3ÉÞ¬dEÊ"ja-ZmUE™tbF;+z¨&›~ƒ5¡c*¶ì—„§_cÍ£Rµ^2©K¶$yWÞ[êì_ é¡ïŒ Vó YÛg G‘(IôÓ) âU-ä]fzm¿¼ïoóT^…Ãl‚#¹(q-£×x'(¢rÐe=nÝóD×Çí’ËL¹Ï¡uôÂÄ®™ÖºÃï×¾×V/¨3Ü RaßjI¨Ø—}õ`'ïP¥DWéÜSJ0\¡“Ò?G€Å_Þžfð3äg,›¬$Xn¢ïÃÌß!^ØcÝ5a´}nVò8¦Û>ùsÕÄY~tªýö£k[J™º@Nª(ùK§Eý@é'ã CаažH¹\MÍ™æ<Ñ[VqdM|bb:¸Yz wœìÞTóÛZ„Ý.»Z,W2쥽ê±§|l÷™!k›óÜñ'YùÙ3Â×Q­›ÙžyÈ~cÇ™hªòö[q}d›ÿf±t‡ÇäLQ^¶Xí—Ÿc©ºlÏ]y–±wÆŠë£ØÊï¯a»½2 ¿=©ñCþ0¬ /~`ìL¾×*Áý>OC²GÇ @1)Eý 2|äìH Ð[ü­ÓD„AG/Oœícé¹äbWT’TJ;‘²ÍÑr™`6~†VŸ¿ê`dF1ø]Ïü® ¥il…êB W5Yá"€,£«ÇŠ,k ²-+1OZ¿è¯ØèáÀ|“Køš{ûî-»V­ÜÃö¼7CbøëØ—6Æ~L—ŽÄ*ûEYêâ½%§aź^ó¢;½ä³JæÇò¿ ˜{R¼;ô¹!*œ„—­Û: )1Bøt·ýÆœCò`ù~t@‰À¡"ޏàŠÑEU·7˼[–N¶´¡ks3+¢0¨TTjO§ðÝßý3½îÔêGùnè¹}Ú„Ô«¤jÙ¯æ÷ãí-7£tJ‚GŨÖù_Îa.2Ê}œ;©ƒ©¦`ˆbz 9Ð qZk-Ò\$J>póŸY}öä°0>x—/%’î>9Nb(Ù õ‹«mÑßÁ­¦¹÷†9×·¹2ú^̉—·†åš‘É`\’d ¸HH.jòÍMÙCžíì"2 ÒŽ†ë˜nÊjˆ9Ór&t[6ã.‹'½ë_æ0š¢b$jñf”uÈ„Uj4ñâ\>2¹Óõ²u»ÞQ0+ìÏ|elÁ”k“ ŽÎ„j]F«^ñy¾¿¢[ĸ&ªmÊ`:yÛÒœi6’|­QxŠ]g:2ÐÁØN¬ÁÛF¤´ ³ÊUxÕï=Rešcrug!jYíŒ`6¾ì¦ˆØ¾:žî­È5â$¥É´äy¤â`‘xv©Ùm;ÆZåm‡|ºZÿ¨ÖÊ'ý­vnýÇÓ‡H£äe |ZÔÏú™d_xK8©þeß¾?»ã¯ºžiìöKrfÏðï/šº¾>/HEè~šzÙ£{ë³Ýþi#û?4çž1m+¿V×…FŠ€ÿÊSS~÷­aWeýŽJ»Â»X?s'Ù‰ +‹„lÃ$ø›Yè(©ºH°ÈÝ(È-?Zc|Â5ªó±âYÁYLu5ïË¿‰‹?û°o'ÜÿÉ©‡ø£RuœñòÜ6Va3xÔgçq†H?À6é{ãE"S•Ÿ/[~ö£y›j_PË;žªeY%Èãó\[=€—¦KM%8’.Ìëø3LŽSrµŸ#ílÿõzÖ»ª`/2l2 \HÁ˜–#765$?øü0rdZ8Ý+ð˜¬@_>Rš«·hbøÈ­ xðø«dy¹Ïˆ õ ²{4ǹ²ý…ތ֭é,JêoõÝ*W\@ž‚äðÔw'FYîD1Å9Æœ¶8ˆbTæ§òåu*EÇ0ð=vFë¶û5Õ|‘‚°º<ñ—¤X³¹ÿE%K¼š~zq¢–Cîòe%á{ÛÙ¾—X©'ý& ÜQ|,¤ ûNT­wÇÄ”…F{€´rkK!_"ÚƒD ›–&ª]‰Öds–K#P7w¸&ã ã£J·}µ$|ÇM™6ÊÊœ†`¬oý‘?dà¦Ú¦ÀÂY-J$rå~Ê0ÔDÓ@!Lf”'Û¨yé’ܦßÒ¨ÃÖØ áå1{4jô:Ú)Ú¯ääYï·ŒmÜn¸„ˆ|>cùRÌzHË‘-jóbÙ¼mŒ’g´Õ$ïnUWŸÆÎa¬Ó›:3ϽÇs"¶M‘!AVŒÙ§K@ìÝ©t¬”\¶ÃžpAÑp§MKÐíˇèH <ž”}!‰P}”nHŠýéTfçá‚-¥ö{ͤ{Ä“šó:Ë8Òh±ÓFXˆæG$óõRBùý®ÕÉÃ-®Ruñ’õP,ÐKCCJìÖ¾0:Þ¦¤è€y9ËfE¦¢öÙPG¨ dÑô}"hSgL=o"¬w‡UA:dÕ0xUU<¿ÚBBßÕ µÛã 5«_Ž'ÞhŒ+Ù=)M,ŽŽÚ0ØäOˆOî…Ï­e’‚kŸ ïUœŠ ëU}”ÉÜùäåæy‡,@®aºÉ¯¹Ok]±ŠLˆœÖ’¬èâdDµ)ëáë—s°*ü§Ö)•ÓicTYïá7Ñ!âùôÇ­ó~ÂØÑBíÏ×c‹ñGJ>4Ha9fOë÷ï‹ï¾KþQs”jÍšQ q§µÍVÑÁŸ|ë}Z`ôóJ÷ëAˆ³îÀÝã~•Ù2¿(i ʱ9’RŠYyâ!ýz4¹ó¤è1”.fuôhg†ùMz̹kµ;µ½@¨ã­ÔlÁd’í)Ys+=É´O_ñŒ› ®‚¦”cÃÚ0ædnåšñ3¼äâѹÃpñcsGc^LyýÁ{ì;£Ïñ?óÚß L‚Ú«8j?páÙóà ÍR ÍVsF¹,²'%Þj3íyfh91 MÀÕ‘¯ö@Ù6™j ØV]J?¼!.ÕÿÍ^I3f£ÚóF7ÉÕ(˜Â•UÄLÌmžD©úýê²Þ('A“ßÒ“pèdÇ`(¿\~rPm7Ë·¢œà^r†ÿœXÏÈëò™åñÎ~Åm̓သbžç®3>w¯ö°K‰ã²ð‚dØð6bìÛýf(œkŠ’#N÷·¸_¯ÑŽÖ27¼l’{« \žžbêò*ÌòÎŽl,/iÁŒÇTsâž4­£ÝÌ´Éë‰ ÷^UyR5o~Ò¥ˆŸðUHh©0ö˜¥øJØ]µÂU¬j@K¢<òDm· 6tDü-Ž•§ÆbôzÌ HYs»gb7ÅË™ù„Mø ãNL­èir ¡Êb›\ÈŒHÆ‹*øt$‰ÌÎghxu-’Ï—ÚÎbŸ`KúÓÍrÍ:é0ø¼¦ ƒdý1[mV ¶õ‘À5Nçæá$ûú*¸tjžáqצߤž£œ÷©gD”¥5Xå–³‡;NT’ÇróË‹§dÏôµ3?h“çnÉ>+o©G»êKBïÞUî-ÆKé~Êm©¬ü$P÷ôƒ,ý  ñâ¸íùWE,'jî`Ð~ygF½*dJ'§”:ú¬’ŽîY¸«Îg]÷z….xYzÿŒ“…›ücÖü§d‘W¯ž›7蛲5 ½ßºè›SÈöËJ€Iî±7}&ïÀ¥ópÊÍû†<À«c =‘!ó O]Qª^¯Ü¬³{%éÕI£š4ëS”|ÈÁm*}èËéècêƒABŠÁk.І)-“›êA`M§÷û3ø:'ø@>g’Ô6ncÚ5´õ‚2(yÙகCÇ¢C5æAœÓajD{ËÂ3ú· õÕ΀ã%‡Õ‰ Ôº—VŸºs7a¯ÊË4é$Æ:8#pRKV!Ä?cÒ'ê~9´i!¼æT¢ÄJÁ~aâz÷Ù|Ÿí-kã¯uϬ7qÌ'bØÞ_oí¶2®(×}O·«•oœ²› ëY(dçÀ¨­LgÒ[ÚŒËRõºq%Yê4Ë}Xõd(é \ ÕÈŽƒëøtN…S-Âd­77i•]"èm~ˆqL—Y€¿í¯¹(Ê ÈY£Ç}º ä)½® Ñ›ú2d5–«ã׫;ì´¶ˆãvkR“Ã% h³Ü ØúIXc‡U‚a¶XÝÎ-¹ï£õBÎHQÇ¡[/W•@b0+: Ù|9ŠOX"O¥4Õ¶f­ÀÕ‹¿—Áï¥uÿ½³ò— C¶ÆU߀õA%Œ7'¤³´—ôÕ¦ÊÈ×Ö]®Ñ„Q/€-Çk~óŠ„m˜yËÒv–ž?Âê0÷¯iÞVäqÕŒo û˜þAî¦_—ÕðnÞj?Å-¾»MŸ$|ó^¼¹ê‡Ñø)k¤ùŸoÄjìÙWhÍe½Ë§¼@àR‘ã´ªS0oµ•žOYµ‹“F=´¬æÀ]Ñ'¹/Úß2øˆ¹¸NΣzK’¦Â|Š2†zÝü kÒ\оWóÉ5V=Uw+z… °þ&¨ïŠFP,Ž¥õS¹ ¾âÈÔ׃}pCâÀL"¥(­©jür’d×[iéàlé“ÑEï‡~µ (¢‘Ÿ½Gxç«Ú< \pVç[¨pTËLÍèuØmZªŠIîÈÀõƒÉ¥s³±U_ú¾ì¹b®ö$\7úÕàÍž«…ñéVTyÔkTFrbA Ó=>T(ŸfprùÔý!ïws?Î`ô"\¶8tÆ sذ õEÊÌB­FsÏ ,æ[>9Hñ䆰_ZõY–Ä2ˆ[ûÈÜÈ·^àMã±æ4cÞZ[8>™¼¾=+¦ÒãfÈxƳ‰N…׫+;ŠkÈo)|?¤#¢:'j{ °ÎÛ¼åˆi$ð5筩˳'sS´†õBƒ6f¡\‰ô1Lœ€~DÎéFkPr÷m±ÖÅ>U³TÛí4–):D”¶•Cun+I6©ìul> »T‘™  [CÛ£žƒk +¾g³…Û2sLžÉM»ao[ó$dcë•£ŸfÖ³£S¢˜l„ÙµâomXá'´Ë4@N P)ÙnÞµ ˜¢!£$¤ÝI”W"¯óÃ÷Æè;t3¾˜JW`ÿFsÑë›ùÛœžLTšÃgÂiÜ«—´Qd½_òu¥íŽõH Ðt~רØí-œ#ª#ôÇ÷ bèÅ*tLÀ`ï\/.M¦|ËÜÜõ†ðR?³FÖúk…àpœPÃö=íIß~£HH–g[¡<·a åL `”íçœçÍr§óKâUú‡ú¹w¼Ø°¢ egíwÀ|â=Æ•\¶—[øÞW>0/úÎÊH$¹ŒbƹÅ||ðSgߵ܆G%Ù*6Øçp¨®íšL4$rŸ›9ÃüðaÅð Xˆ bmAŠ™‡h£"¤›ƒöaîf#¡9¬øôÍÏI«y?šHhƒÇJBÄ‹—×LYãÕäk'¤É×%:¡¼ŽOêÖ‚ý¿_ª¾œÄ»2Ó%C¥á:óÚ8¦)$–®5°Š¼²[ò>u²¾Ü‚£Ìœœ-:¦ü·KV²Ò+úŸŒžø®ØÏH—Ÿ²œš•§Ü7IöWo¢È÷eÔ+¼®ÕCþ×¹ÓÍŽ_2Ó¯7É#˜þ ÛþXGö½%:TMð)‰û9šLV’X¼*Z†Êi3Éc‘==‘/@Zé\|ÎM÷¿êí”»µ™MÔìexXo{÷\î—è*ZPet?–}ÌþœéúÑÄ•a¹PçKu&Ì !Eƒë#xjš';c¸³2·ã¾de •®Â×–&âwŽ2Ÿ¼xç6Ô8{=¾ƒÈ¹—L@»ÕÖØ9”´mï±ÛqcÁ£&nnt 6ëOKy€ŽAÑ4Íý6ûd9Û÷î‘öeß#R¬ÑÛ‰Rðî,¶…Xà›‹܃ ;áü'“¥‰r¤åoò[FÏî>ÈÆAøÉh¤àéJ‡ß}ô4²C_ss¥òýôL´—®—É)Ý^Ac2àãÌSÑXòë„cÎdÌ™[¹xbÉòO4[M‚;‚¶&ÊçªúO¶JÔÍAÖÛEfõoIGæ²?Ðá×hU.~J…9®ð*~ºïYHx‡_[7tB}ìÕO³e.ª;CšYì2uîo&Õw?ÃßÛãÜ¥ «÷n·~OÛÞ½u]¬hÁÎlùº”j©$¾«éb¢/BׇaÈZAGºö¤0{G¸Þaõ´ËîibÔY+¬Ko­'̬ª›( ÄkRi¿)»ÿzã[‘“®Ê„©QËŽîy{,Ä`ÐFsM³±\-ЕÞ5¨ïÞ»m..º|Jø¦þj»¾ã¹¬ØTºùg{²#‘ùTµÈó=é)Ê—Ò´Xá/† Љi{3Õõ“ñ²~38n“üfΪcSÚ'SÅü~:uò[óœ Öºö¡Œû¿˜B|N²R\ëÇXtØî4XeÙ1ÑŒNüØWhº5^N K®‘º¬»£ŽÎݺ”2§vã¦_X?©5èV§ÕáÓ §UJHs×ÍÉðeòi1åç“/†¯H§ºç·gáÄ`Ô¶M4·L [~ûžVMT­£ ÇÀ¾O·ÍéÒ;°êð#Qââü¸øDfÿçSÊŽŠ/ùävâ8ô @ ¸­ìÁÊ¢G”6Ôöƒév ‘\Ç3Ã[Ù•7ä°/Jf%}P2þOsHoÉ~NSÒp«µ³RoÖ4Ûåe& _)WðÒ’¶£¨²½ý×aà!£A£ó½<ã.Eî¤ôÅÅ“2ÉRbon}ÿ¹ÊX4£Wµ\ÆÓÑØdý™NˆÕuÿµ…¹vù#ýVoͳ΄v×í³ìí«‚aXÉD Ìt;1ÓoœdÊ5³¯9Ÿ-äXìŒüð}§ÖÅæo¹ü?¯—\- endstream endobj 2972 0 obj << /Length1 1388 /Length2 5940 /Length3 0 /Length 6894 /Filter /FlateDecode >> stream xÚtTTïú.‚H(R*†ÎJJº»Kjf€ZºK@R@º A)éNAiE¤Eþcœsþ¿sïZ÷®YkÏ~ß÷yëûžg³³èòËÛ£íà*h–"–µµÕÅ0XX "eg7B`‘ð¿nRv¸FIþ/€¢ŠÅù” XN4<‘D€ˆIBîH‚Á€,ñ/ ÚCP‚z!ìm@‚cHÙÑn¾G',®Í¿^.7‘¸Ã÷;w…{ `P  Å:Á]qaP$`ˆ†!àXß”à’vÂbÝ$½½½ ®´‡£ 7àÀ:p Üà nüZкÂÿl&@Ê9!0ü†h¬7ÔàH ŽÂà2àïÙÈ¿ËýÍþUú …ÁЮnP”/å8 p@WEKëƒå (û_@(ƒÆåC½ $Ôø=9P‘× ¸ÿ®‡y ܰ ùkEÁ_ep§¬Œ²WD»ºÂQX é¯ù”pîØ}ÿܬ íòÿk8 Pö¿–°÷t4F!Ü=áêJ!8é|Žp, ¿#,. ÀݸÌIðWy#_7øï ä—·A€¿Ú pÀ-@8Àq¤þ¨ÀzxÂüÿwàŸ)Ø#`XÀîˆ@‘þ§:Î wøcã.ßáÜã¸À¿~ÿ~³ÂÑËBúþþû~Õ´õL-ÌxÿlüÚðçø…DÁwp/ÿ,£EüüŸ\u”Àá‹;§ìõ—\ÕÁ ü³˜G[8Àõ–[‚EÁ0ÜòÿÍõß)ÿ7Šÿªòÿbù¤â‰DþsýŽÿa¨+éû€c­'§m4N¨ÿ†šÂÿ¨Vnðtýï¨:ŠS‚<ÊÇf~ˆˆXäQAøÀíõX˜ÓÎüñÿÒ‚ë¡1ˆ_\ü_1œÀ`.¸GÌ?!(§6ìïküeÃqzúçÊ(Úþ—ð„DŨ‡Ô—wõ8Kð‡àj÷ùMm@P…ÆâRÜ΀ڃô×5‹A䯆8/é?*Ã<=péì&îü<¼ù¸VžÁ›í4áNæ±™ÿ»bkbl—ò˜ÍÒCÃÇ9sš*³kçV÷ãÜÓûþ«u·ë}Eùo«l8Þ¶Kšº8¼4‘âÄÈ:Eþ¯À4]Y²Ì£ O)Ž¢DÖÞ±Ëü>çó·3)Þ7ÊUîhD4ë´´Õ–çhÝb”0ù²l€}e×k´&ú–3oÙ51l%Þ2&C'‹USºå„ô¡w ÅbOï|Šº “ŠÇ¾zôJ’!í“ÛU¼—Ù!iì‰ßÕ?ÓÊØóµeöf,¿’HÎÏà©î²N)ï•מà™`¿4„ˆ,Ó+g$6qŠc¼¹õ½‚Š9fj…N’CyšsJž«,J|®Ü¿F'69°ëÚÑAó ‰Û˜ëwÕrí™Üýí–ån¯P™çá ‚<à‹)ÊĉǷÙxüP“üOß6ÍxðS @¥2:Ó7b0Ñœ_C8ÍÄ÷›˜ð(i¿ÿx_ûüPøuAfÆKÁÖVÛgŠ”IÂw¾› Yûƒç6“Oì+&itàzLršMD&°\ƒpq%'q‰ŠÏg…ùn~+ùYZ;Ù*ƒ¬&W3››]ï1˜ÿ8,Ø8™¬·z›zìÆÚì9™ØN«C¶5Wχf+Jy¤;Ýòü½d®Y26©¶fXonæÈ($tØ¡«Æ¥ Ÿ;âC4a|Õsgð7…ªü÷DñB´!±<Ù ˜Q‘º¡§nGüóàŠÍU1¾w¥æãÐ|#:êÚ9ÎI6?¼LÐxkì½”Ne½úˆKÀ«lQ3éÝO‘)à,-†°ðN’CÊ×vÞX&”†>|u¦'™]f'—‹ï Âã<¦YÙŸw®«b…¯ˆ²pï!h©Óé5$s¾ {³Q|`:-¹Ž‰J[_ßútý~qð÷ÜÑ&+Ø/Ȳu)Xk¾x›x?k<úùØ’Øf®V¹y‰¡á«Ã^x7¹%É&¨_ëÞÖè)ó²õÃò$·'E@ƒÂ¼N—|/ ‹>«>_Ò ÒV躶µ`ê'ÀPè¸Æâœ ™¾àþø°×‰ 8åe÷Ã…n_•{î³äÝøHçÒÍõ2¼”œuÆDnç±G¥dY-CyºÐó ÇO£™„nFë­rÄÚ‚þ÷šì¾jBtLsÏß01œZOc©ƒ•ʘúØÞïI-uÆóñGTm5(˜ë‹ g^ hÓ¿Ó‚1šî‹0A;_Å1×Dߟ~IË7ß ­8÷¤S &7Íúl‚Qz{4uL" Ääß®×-;5ïrÒžð‚BÓ³Ó˜îfyP“¨œÍ°4“g‡pÂßøasbvÏË|ÕÂÈJH»CŒ¨q› xól,\fKÛ€æÚ¥iò·½{î”Oz:ô¶AzÚX‡B™yЬMÁóôüÆWÇ©B“'}¦7Oy¬ÌžÈž‘ɳâiZ¼Œ‹Äs–Óç ƒhÂ.›5½Ùx)=ëúÌÉëÏi.ëþ‡}~ ü¼Ww÷Nu*×… w<¬ 4/RçFÜG˜Åέ •(‡j&¥ûÈò-­$ó“vç#ǪӈÚì²Ûšo¡+9µNl4YëlY‰Fj]üTœÒomTÌü$]WÎZA‰÷ÓI6’Þµ,W>\=¯´ë!"$'ú<[±äM·PÿÀw¿àœ}ä‹¿CE`—7½q€vw¸Øbj…ÛÀøs…ÛŸ»>Ôr¢´kÀÊxÞx4O}ÔØÐ² Ê6N½ƒ‰^îóÙÓ8%R1:— L•â ´¯¹6M9a_ÉhN{Ÿ3,å$¬RúÇwsʼ[ʺÅÒòül—Ÿ'qö-Ä·SèZÞ*?iQPW¼¼T{ß;^|©Î8{¼-¿Ø@€B^@ùå’x±Â°P¡þ"£pÝò®Ÿ ¡t»dVëMtzäW9Ô'… ûg3WæäÊÛˆòèX§¿(>´ Í¡qÌ_ðT ë1}hæ¤ÖûTK`{™ÝæȈ齧˜¥n0HÛ[ßÏ9e6cÿN¬š3ÝzO&?ù0Ù`±ÍÓdÚ´—#ãë÷z*›cñÊÏë+y;q©„I9Ì߉}ó#]NZ.&\|ÔÆîÛÄ}ž‰™|a .°M2f_HŸ«¼›á|ÅGÔÌÔ\)§pƒˆ%úà¥4WÈ |Êé­XBLÑ §Æü†i…†39¢›tQùëBº[}7¹X6i5oðÔÎ×0?8Ï|™Š}Ûoý‰hæúî6« ˜‡¡Ÿô VµîŒ´å‚Y#®aNžtÿáÜmÒו¢šqá‰L;“Tó»{®9DæãOzQ7•Þ#~YîÖÞ²+&©=WÇyJ¼É&¨æÒèÒãÑ9ZkíìæøÚçí€$YIn}ÒËÁkMÝŸÚð€ˆáoGo âoän4³è±´ # `•vì§ÙVqnrÓ'MüNem‚iñ±¥5ìÁÔ@4×¼<}áÛ.åWI2£?doˆ<ÏAØHÜfæð-ŠÆô#å'ú3„y¢—ñå|\øäðïû´­Î æ‡ÏŽŽ÷§OsëNIËGtÐQš}7™4‰¿,‰´rîA¸P’û„¸'å[nžS y§ÃtšOeURÍÛð¡¦C_Õ\Ão<·DæN‘Ü‘=á9S‚+—0ß'qøQ›IÕ뺵%axÔÈõvcñϬo:0»B‚ às§÷ðDùFÅÞI^üœÂ$ÑÅ/=¢DùèÍ·:-éÞTCÖq.9Í’ÔUÉΤ AjÞ^b=¤=DÏ_×(â«ñ;Í ªWwá  ¡ÐÏ|€úí›ÁäŸv5bí„´]Ìç¦Óød¹-všoo欺Tž~ûŠŠxAEzv {²4¸³¾h[7s~Ä|JyÐPæ SÙA„úâ{:pQ^ˆÚWM°I±ýæl+m¬êÔ~×\¹W„ï8q{œ©¿Q^¿yO`)IR€•îixS]‰)c¬‹EË÷g‹3ììxÔ6*nezw+^õ"+É£æC?sÎuÓÙ'Sò~¼WQv^&)µ×5 «ûÚOtýÆ…î7F¶ûšþˆÛ­µ+?­:Qï´êXðJ ìiÛý¥S…ow<˜Ý ûÖò‰ý:©¢á½˜ÝÙJÒg’½¸3¡;3BOYýŒ$î;?ÓhøävËêÔ`îÙ0mªÖ‡gqâ#®)ßlΣäøýæ÷Èçìw¤¤|p’ä–ѳ'NeJ ao]Žôð˜i‘(å]0 ©¼(ÿR:ç/ß'Bwä—ÀKƒ–EjÎì’¯ ø¢ìeËñÐüÓ™„ê¨¾Û¾â¬æî¨)Ö â#ÇÇ J#SiÇMÚú“Î×›£.ºi¤ŸæÊå¤%èûÙÃëš§r[bRi²`àÉ·êU²$aaë-–'skæ†uç‘(‚’ÕÐøõåtÄ›M@¬^Ý'›’`Ðîvð ä€RßÌhø“»Í[œú·¶¿Dˆ§xŒl\‚„>b·jçàµì÷ƒœÕ‹Y}“á³`¾dÑQÓ2²#ýãÁǧ‰9QÒ –×K5E6ºúÔ÷n\2±|h\DXiKs±+ÎÒ~(œÐYÜvTU'¡èÉÞ¨ü¶·KƒÕåÔaép¹ä%&H©M½…nì1zS’¶+HY1Û?nQˆ™T$µ¿yzuâ3žGÿA{d¥%E Lª1…7Äå…oßšnç;òw~W '“ü*#6z‹š%1}Zš€\(›qÇÕW, ¹ÚmG ë׊¯—Ñ,–xr¾~çZqviÍß¼žQ`Ó³¯H›Þ‹É"¾ôK‰Ã ‡ÎÙ|¸jݱ/¾Ü漬ÒÙ®I`Ñc:vt{ñ×tLÿ‡Gãúé§k#r^-=qln,U4†¡âèÓ±4öz!YèGçqþ©%ü@I§ÔGY'!êFÍ"¥OžÁï'˜–‰Òðé cÍ)Éü§s#†Ù[÷|’­Â¼’y¤SáÆŠîr]ñ›+Šgœ(Óâ0ú=Kš30„ÇKÝK÷5ÀÊçG¨—C#7¶ˆ¢£õn£ølAó8ÁÆT.Ô¹ñ¢àB7½¥µß¬lv1ËáOl‡+lj2G™´»_~:˜¿ÈbF—x½=t¹Èû‡ÍW€µRnqu”Új”<_C$?jkÌÃPùÙÐ5^¼j¾Tàô!‰§¥éJ¦?Už³FF)^ É!æ×ïMdÈlЇ¤Òú`½’r+b©ŒëØÈ®Zûtú»nâÕÙF>ˆ=½ Ú±x¿Æ7´{®öÓày~Õð\Ãån²˜àhòjà1{s¸a/l¼Ô¤ZX¸.07¾.õþîÑ×Ô­ZñCŒïçÖÎ} + yŸº~o‹©-gÕ¹ºêÝ‘wbKùE×Ðë‡O>¶>ës‘+eǨ[ÚÚÊ«?SáOSûŒ¿BÍhgûté3*xôTLÕR²Ëþ^ÿU‚µ[öpw§g(Æ*µÎP$[°Žf6ѳU‘h³n_„7îJü C‹`÷on¶£ÕtEßBb‘JÕ‹©cÀ"üÞólà4Ésª™­Ž›c?AÃ~ßÚcùhUµ†´ˆ‰½‰~ŒdiZOéŒ<¸¨°ÛMã^lMÜÐÏD§õ‹>ÿ¾bôøNèúÊÅ@4ϰ¼j¹HÄ#ÉõÁæÙöPÎ]Û‘÷aêÒû<&Uw¹Ä A¼Ç¼k¾w6eQ²#ìJòÁ˜Õª™R¹7—~ŠXó8÷æ¨}>1Ž…ᡘ»3)j½ñël ²:VÈ1@ŸrbÆÕ¼š}H”×ß6ÏYs§½v ½<–8¾Ÿó­œ›í4£®‹‰fÓ«@EáµÖuÕ q/¡ÊVTÔŒôÓpÈ\xîw‰c{>9álK SlnbVÍ”‘ÖeÐ7vÉíÕ[cÙ´3E#f”üV‰þ6'ëz»;~‘• +ú}ô¢\µHé'×® ‘¶)qð[Q×^Ê—z–¬Û•i ¶×’2ü=cK)Uô0KÀN%½$"ØÔÎÏoÏÍÆ>£nÙ°gUhí£ ôÞ4·4 R&hîSx¦‹êÎL R¦hë®èZ_ÎJ^½ÅÕf¬!å)ÉNçWÆšâ âÚPô—XëË}]‡#™Ñq-qÒn;D!¦r¯ªñØ»2r]ðÐ7<"WçÇ‚Âó×*•{ëc_®T‹8£Ö¢õ[±oftU~È€Ä(õŒå/±šÍne¿<‹žT°>iç"HŒO“»ŽbÅŽ‘Ó쨵XØ(N¯Ô79´OyðM­Úã1/%ì γ> ÿ¼ãþæ˜7óCö*ª¸œêM`|ï‰ÒCÊL­øš=¿‡Š³@UNÜÙòÃñ¾åŠÊ?w5>ÎŒøTŽÕdi`޲YÊö6~p0¥MdÊ,Ï9b¬ŽÞ‰3ÙJeS]™¨ºe‚w÷åB¢“ËóˆÇ)‰FDLJfÚTN™vÍÙkí¸=ŒûÁ­:*‘¯µ»×ǯÄ5Ó]…ߟdDtµ2 m=)ÃãÖS ÑMž263uFøÜÖ†„£üÌ(ï€s¾«Ñ:/•oŽ(^ú^stÕüj‚!ü…_ÇÄá7áæcL“[ðÈiÛµ¯çBCj²4@[Di¨W‡¢ƒ&ãt.£·WäAû~_½—Ý—öó‰Üe¼'(þÊÚ’êÎeC‘g³ þï¦J̿ݣ¥y«ûÕ)¼DùÉGD|Þ¦%%•‚O ¾âÔÈ#ГA®À1ÐÝîvúád²ƒ”·Ýf–e½S¾‹úïD7¿TØœ»qˆvÄjLYYïV'=¾§™µ®{NÓÅ>ø@–ópåq!w.Uw*ä)ŸBÙ¯äªáÏt'•zÈ•µw.-ï,ëu#zËöÌéâåŽP™i’<»eëõ±rú²Yia/ô”i•‚ ÷-kâNŸl 3ù«y%µá5Šu´§ûûÚNúú)yc>ÚÔ¼f¬6ã›ò§O«ÇJ+—4*x^-‚æY÷ÇœÞ3DLï"LmD©û¥ÑÓB5‡ŒÊ+è÷Ù¦AQxQ¯·¾!Ýß®š@ ]?¿½‹Ÿ4ì°gº ê¼E¸‰ívæðCF¨/šÉÑa³Cº>¾\lH ¢©å9ÝùúŸSÆÖ£CÐŒ™)‹â… ×6]A¡ÞaP‚±ÛF< ç¬ïX>Í/æËÍt{—¼zK¹xösTï뛎ÁëiwbNoVçÐ=Ï:üBªœâÃcžMEt´SÎ6³ÖѵPÚ¶”0^Xš¿»ÿ5¨"r’*zÑK›c)s³tüЩ´UL°Ìµ•¯r!ê1”u~©¶œ>#ÉkxM©QÒŠW­Ä¨K”æFGœÃÍdK“DIË~ǪpïNõ“e U}ì96€ôm=Zé­ ùæB†w¢ïs§Ò̹øü©èÇ€4äRüv¨!ŸÜN¡¥@û¡Yþ‡…Þ-ÉÍa)ªè¬†¡«@$~Rö²w76=Ìȳ »õ<ó`Îvïv¯Î…°%d^SæƒÅf %ùwW~îá_o„Ðñ bsŒ Ÿ ‹`¶k¯Bƒ!ï\õ«æŽwEZ»Êc ;}´·PjÅ©Gé§÷jŸg;…wWQ?,OÎ0£3ʉæ®FWNGÆ‚ûŠR“´ヲ.¹3GiþŒónFa²c=¬ÝºêU€D`ö*5å^Åóm<3ë‡÷“ÔÊD*ŽãŸÅ_`$ÉΘ„oÜL»ZÎãá® Š¨¢ì’Ú^J³Ÿª>/#Ë)@h¤8TêŸûÀÖ>ÚÌ.›"éù£Ï%¸Y?X@ãñ^Ó\RÞ1I§¦¼ÄpÏó€›ìøÅ^}8„`Ÿôc©ò"Yº³ãzéõë'mÔð½:ºò^ßé¹&z%œI­ 6•=ø„ßÃŒT€±r’æñÔiq›GÛ™áY/W¢®lØú/ÓWTµ«HÜÓxõÍ!+ï]Úò“W*Ï)ZVúÉóñ¤ÚBºÙ¬”îþÕ_[e endstream endobj 2974 0 obj << /Length1 1423 /Length2 6229 /Length3 0 /Length 7207 /Filter /FlateDecode >> stream xÚxTSëÒ6"½J5 ½&Té½÷.%„ ¤W‘Þ« ½H‘ŽR¥7é R”.ˆ _ôxî½çþÿZß·²ÖÎ~gž™wæçÙÉÚì,z†üòöH;¨ æ %ŠÚ†æ …ÙÙ`h8ôo;!» ÔC"$ÿ¡è£16%0ÔF"žpH“‰K! Pâo ÒC ö‚Ù´HEÈ®ˆtóõ€9:¡1ûü} à‚p@â|¿Ãò®PŒhƒÑNPWÌŽ0`ˆ„À hߤàzà„F»I z{{ €]QHGn>€7 í0€¢ ^P{À¯–:`WèŸÖÙFN0Ô_C¤Úì` pŠ@aB<öPfw€¡º@× Šø ¬õ€ðçp пÒý‰þ•†ø †@®n`„/ áp€Á¡]-´šFØÿ‚á($&ì†ÁÁvÀïÒÁy}ÓáŸþP˜%€‚Áõ(ø+ 昕öŠHWW("üUŸÌ Áœ»¯àŸáº Þÿ¿W0„½Ã¯6ì=Ý0wO¨ºÒ ÆDøo›# Jˆ‰‰‚PwÔâ$øk#_7èoço3¦‡@7¤ÀÓ4æÅ|ú£À^PÚÃèÿŸŽ®A €= ‚ØAaÂgǘ¡­1ó÷€ù,úÀ_ŸÝYafDÀ}ÿ ÿ=bA]M3}SÞ?-ÿË© €ôøó Iø%Ä€$þ3ö§ŽÿˆUG8 •‹9§¿Köúî?áü3—Ã\(€ëßDB0Ðÿ™î¿Cþ,ÿ•å%úW¤â ‡ÿösýøü`WÜ÷Ã\O4FÚHŒÿ 5…þ%]m¨=ÌÓõ¿½êh0F òG £ùA"@‘¿ì0” Ìj¯CCœþbÍ_vã_zƒÃP=$ öë ƒ‰ÿˇÄóAa¨ùÛÅhèŸû*# Hû_b€=<À¾„˜YcV¢F•öPŸßd hLÓc ÀéAøk°ÂA0 Ó3 å‚™ƒÓ/ço;(´{üË $DÁ0‡õÇö* žIþ¦ ¦Ä¿×¿õ…ú@!„‹sHˆT¸ó‹ðŽ‹:yoþcx«k]1‰æýÑ¢hŽù§þNZøÙªÓî ¶ö5wF2ô*"§æx>_Œû<|²’®V€ÆRîßP8â/úvòÚÊl¤wœψ٠?LÒg"µµÄµäL1»ŠïÞzþ©øº µe!±p”ž‘±¤3 ŸÈçwía?6ga[C›?$‹§ð°Ìô4R7ž¸Æ~ ‹?W舣ûæ»aŸ5üþý›Üþ áã"ÍÞZ±šHJ:*? –ü‘äA:ê¤\—(,Ñ3ÅŠ´DVº×HŽ[ñ•ï3EíIƒÂžMŽ:Š!·u6{6 Eç¤ó{VŽm6sŒ¾ ßiIŽqâ«Ë`S`¯µÇ:Î<¬†ôâÒ0ðº–jÏ ËÊÏ͵°—šãð… [š¼saû$; $d•& ¿?øá™‚˜œÙmÄÁtéêA€’žROG‡ÅyÍsäŸÀ×gý°*³»)ˆÓí–7Ã=QGH¶ÏLÔÓ!‰fÙ{}»I/ÕEÏÞ’›ð(‹¡ë5ç‘Ý6Ü ù 3Aù¸zí]ªRr “¬ &¤…FäóFZ[X™:·Ì%#äƒgÈH(]>W0=_ª}*Ú"v?øhyò膒þ~YýÆmýžo7­í<Ž…¬5 º,œlËt85Ð"‰°æ½Ä«móé#ñ¹•…ÆA6”å8<ùÿuë´é°ÀL¾!Ú“Ú=´aól”©Ób ž1óÕä~o'gÚ–ZÓåî¥Ý°ªä kx ¼ª9A´MñýuŒ±åX«ã´…À£gÔ¡ùôÈò\Jd3ÄÍz»IçÐí{¥»‚€‚”s!BBx£F;˜C—(Ú$H‰øë} bðdS¨ÐBËÉ¡™p.«¹DS´gÉö¸%–¼áRÕí謗ñ=e[=£ Æ ä§$Tåþw/=áwÍtÅÞøÊ#»ë??ÚÛ²2ugP ÕnÅ‹6Y-;‰l!/2O˜-2ÓS>ÒºÚ°j½]ÓZTKó'ÑúLÓQ írvwxÒ´#‰/Î.Muî2d+§—dµ&Ì`Ÿ~çHÝÈ„ßUùIó0H‹ÛÀ ôœY%ßîKiÍD oœXñ PZ²ÜÃEÎèå0‹ ãu˜¸“«½wp·!ð.ËáY‰fý\cdPýɪÒ5r“ì-¬,\³Rwh:žEývÜ‹™ß·î|5 ÿaƒž1•Êêý’9è)Çu¯Í3ZF9sÛøi®ÀÆ×¯ú`á*åpœ´®“û>¸Õ øÅÓèd5Sùòžšu©–%“•ÉÄŠmÃTa&ȆŒe¯¶üýdÙž†Ô»R©¹õÒ#ïdøÂ6ʪº²V}kN˦28¸ée ˜¶P‚›«¯äDHG2#g×?H3’KÚéBAóÄξ%¯~¡g]Ù彘MYj¯>¤æçÂ9óùžÈ;²o8l¬§Þàà¯9^1†¢ úØ,òÏÊZWHÙ ¼|5°˜ràT<ñ]Y¯³|>ó\Î Â|?¥A/îÎF÷é†fô•ˆ‹®4íÁ*¹9c@rù;8ß{=¤òãÚO.Øo³xHÄ Üq,—XðöÏ/_Ž/lÏÖ ®È¶:Ý–å#Â>8¶CÂS2ÈÄ’~êF{õØ”áìŒ6H$¬qôXôÝÎo½Nd8oõ;ïx-UÒ`‘¾Ý=°éµÀ,áBäKOÓ¤–ìë&E¯44¿Hq¦;åNJ„[U¿Ï±óSU”ee €¾/ñfÙ®O{2Rb ·Íöée«äÏηÜCñÊ÷¶Kì9«{?v3ð·6½Âdè°‰ŒZìfˆ[xGKä:QkqEßW¤ErâÕéâÈÈIÓ’j»:6GK­äm›æ»Ó“æ|î̯øîù¼óËsß´þ±ö’‚œ„”6Ú£q×¶ür ø@ ¼kÎÓ܉úɳ ´aùP1©½ìûz3j\J®0󰈾sÓ&óW* ¶Òw\–{ñW ¸–f'¬…ØÉ€ØòW×û®áíXqã¤;ð×0äÌ›ý :ýmÔ5á…¾y”) K^w)y%0÷¥*7Aâß¾XÄIÖØ›¬9c¢ÙC/Dà\©A³#õw¼t>o±ªŠ•îÆ/È·jÊÓ&¾ŠKå ØªãÚl5™ý²«Z^ Õt`0¥ò[ñ(°9þ®ÊêÏY)2i¦ (åê¾Ó›VyHç'ø®¡yÑoZ«×"< 5Féó€?é·5 ò[s,½…áeˉüàZT5AtÛ5º…ùÍÔÖ×hxWý¸Úu¡%–Qˆj\»ˆ)B/†§ñ)Z‘PêPÚ…åí²u‡ùB Ä-NPžc}2Ù{ÊdZøÒXÕk" 릠ˆñ;Ùº?ÐÐ]"cÿÓÙ×(ûIHo“‰ëà§Œ5:÷²QGÅaº¤“¤Ã…WmÙ7$ün¶4ŠV\ ìC?jKêÏŒ¼Y†dâ9Ȉð˜˜U\ˆt®5>Ð<£ôq.l¸Å‡7vÁkª›{ñ…¨W=®¤u¨o#rÞ¬Ç@žvwr>˜4ï\Ńòïƒ/Hâ ÄCâx”EïeØG})FƧû[)VʰýÀQ¹åçÈ2Íó Ù†5sÓ9ö-¿Î÷ƒ±’±äñý„~Mo}Ç÷OÜry@Ö”$¡s±Ñyã={õDZ&1Nßü¼ºp%¦‚ƒÇ‰­Ø©öXKmÛ+lžë¿„1Ñoº½:ëgÆÇG%c‹ú ˜…%à0N=çþò‰±È¨ð«ô̤YPäRU5ëü>¨ªˆ€ô£­T}δv×=æe¸ÂT‡Ý/|æŽÆ‹Ö³bú¢a´º/°¯ë™î̽˜~Ë”{ÅLaJ÷”߆&»¹ÕªðT•­_Éô:ôбGˆ#n“Oã8H„ñÔ2ì›I~íÚ’ìÈ–ä[ÑbrÀ{BÝ+‘ÌNv–âeò§nFÝâž\’Ovì­ÓäÙ 1ÓìÁ^6iæô[´8•gZâ¾…ø|6q»aÖ¨#•¼7+qYk|•DcïðxÇZ V~mYz$‰z÷®E¨‡å ÕŠqÔe@Vú=¼o¢&á{SƱ»îz!çWÓÒ?ã²1ÿgzDuôzñ¶QÙ_ʘã7?¦ð2ñ:ºÉóÕñ½–p®%W Ïù:K”|˜^Û”±ÀH$°#¨RÎÀ0Ô:,JG䮵Åb °2zC‰œèéºIô‚ŸB7ç\ÝŽ?kD!åêê×ÓC~ÚíÊO —­ëSït+0›œ>b;’P.j£It–&|l% ¨ÚÎó÷¾YkC**|^¢òÙq¦»A$O!k{3g_¾¼Šb­ÓýÅÄÑéÝÕW+S"Mø±ÌQʼn“ŸAÏõî¼½U}Â7gØ_ vºÑq“ñ©Gq™eÒû×^¶ˆ:šê¿?¡=íò9WeûYÀ^²;!XØ:~{4õe9í»‰.•±¬TH]}vR¨ôš×,´7îòŒtV à nyãõÅÜoã’[\|œíG ié”ëÕáPwÍÈÿLÆŒåkô˰Ü8œ†Äô'ë´‰¢ÚöEÞý·.´³I7ø^äêxƒSñwKÊ;ûJ±Ñ:%}Ñp¡d-.òêVQÜ´Ú¤A͆EŸ~š§/"šèCŸàáe%Ìr”óXÇ3 &q^Aä°H×ï\q¼ x°:Þ_œqÞÅêA–ñNˆ„‹Mv™~ÇÒ×MÎR̵ͮ›™2$Øýåc¯œ­)'Âf2…~²‹JÁÒ:7:íÄLOüÝií̹dXïól?îs)÷¾@®Ç^`½ŸÄ¨mô'(y¯·^Xu2$RïÙ?õWN¦.é}ì²H·–E.ÀFm²¶åDÎ=ósasqa³Ù«¥Æ=‚8´^Ö’µ+⚦Ëœ|Î;Ëp» ׯ}š¢ÿ)+×n­œZÐíäFÓÉSF£÷.•©û¸6?fåÉ“»{”úoñ¹jÆûsøI=˜íÎÇ q=Þ°„‰NÐ4îå>ûÂÉCsínltqŒ~À0çr,H [!äJÇ?2ápÚZ{¶¶^tá{k£Ö–}É¿’¬Œ¥CŸ9WÈZõi=uØR¨â­žõx|¨¼zh‰žZrÔÕd|¢ÿŒí’í…4ý‡Ðù\Ù]{9a7™•p%}:Éî,ã,;v c/}ÖNI¾”¢ý³µÌ›Cntu *çërz²îhHŠ v Êy¾®ø0½Í·†û ïG®ÍÝlò"îúY®ÖËœ’¦ÛÚÚm„M áÄî^͵Ã犫…u°šµ,P ÞFzžþI4¨Ž¶‰º ½üǼüy5…Æ3êU¾_è±¶kŽGFòVuL›wAÅ)eU\ig0{†l­F)G|‰×\æêü‰qpÛç_?KÙÎRo}’Ÿ$P“l|þtÍ\ɔҴޮ6èßâ6h`m>•MGÂGø”M¥ümºšÒâ± ½¬Û1¾ïTF+•Þ »Št{hÏà€BÞÙâY¡ªæ‚žSÃ#FË\õa›Ýè`E‚##¿•i‡[[·̤§Æ]…ܰÁü*+ƒæ48;®×Þ³ÙÜÂ# Å_ zXL¾®#äâP>Azjˆ ç‘í6{­ívŸi.›úçjϬËÎ'<©Ð>¶ú&iJ'EEîu71‚,ó¦ÙºÔÍp…»É·bÊÌ(ôÖÔ¥d XŒŠ£·_¢höqÎŒ­6Ÿ‡%KO™Åþ¸},Úø*6Ø#X-ã+]ɳb§ˆÓõÈš¸ÝÏ ïQ_çl¾è/M»:¹ñðô|¡`ˆQ+{/¬P/…C&Å>óTõ“ÒtY:™zÂ,õÒ“›u§AêòaZzWçÈÑÕWÅG ²Ýaí‚É*¬bÆu@™-<ìSÞwšú3á@:Öᙪ)é½/¨•ƒ0¤†ÕÚ|%˨÷•˜î{ÀÇùÁ轑 Qò£"“õ‘ŠÞjò’—Õ5¯®˜ÄcŒQ¡ÙÏç*|·>÷¥àÄ)Š^©z8®ãõ‘‰Ž²%DeÄqÔ%4uÇüà ÝêëÕP.¼’ ¼KzñP;(2Ç%¹M¨—=‹ˆÜ ´ÈaÖŒvŒÂ­èß.î©Ø"¥”‹Ë5ªNÌr‚ÏXÙ4lõ5?½Ù8öTŠÌM‰! <á¾î»/!p=WÖ¾eGï¥á Rîæ•%-æ€KœšµêÉL"Oo©«lIÊö Sñ uÇ!$ÎBŠ®–%ªtÅeB\L/]JŠ*:±GÌj9Ã^|f*¥É%¥îy`\öb^gù¾ÒÞy5O"L%C”uþKúšÓ,ÍžZ‚WY¼þHg Ë>Õqœkkž`Ýí/dùíóñÔ%öô^tͱ#ñÌÓÏ~ÜõFºQžîd±d)÷é剫È"ïLô9ë‘J¬×°æ¼vLQˆÍ‹ï_Ôû*¥`­Ÿ [‘"ü­›Gá¶pC˜'¢‡íåªúÉîÏ]<èÛ·„w3Ù^­Ú†òKPë ö•|Ôn€çË.¼Ú®kºÁL¶ï´‰c[jwÔ}ëz§}·ÊfWèÁÔÅXú/.Ù>š±§²Îr"·>šN£ðG…®\1»v’zèÊ1º´iÁ /,rö!}« ÝÆTï±¶‰ õ0Pôç8¯‹úG!S ‡ôÀŠ—²É‹¾æSatTsÕ϶BçÊÈÒÞÖ²ÆO§Ÿç ‡,©g´b °ãÍ)¨¸¢â.Ô«?Rî±á«%?Äâ«ö8EÕ¢|JÔò¨h’olF-Ü;p*»Ýj!6y'Ë•oeÊÉßÔ‚"g\ãç˺óaéòÍwÞ:óÀðJɶ ]ÑU½Ípï^›Ée`,‹æŠpÌä«õÇ©oŽî?$€õÊ\Rn¬Ò?† ó9.ª¨ƒYÅ‘½Ø[ºß¾ìÙR ”¹%gú·¬–«‹Ñ*¦k^+âz×å¹RáW½6|Ëö\ÿ;ó”¢ÖiÑIR O¦÷­]¥L*-+979ˆ±†o*§ÈŒE4KÙâ’öy}g¿¸»Tkdy™Ã³: …bDzªfÓ;?Y­Â ÷=B{ùÌJzÚë'ÑxZøÚP½0²gM©|fÇ»õZ7Òj^ëóSÌûxCÌì…"Y·’&³.>Ýë(‡.G9o+‡R“¬‘ËÝ G{q •o;ÌÖ¤òÂ^Õ·×us¼¦k›…nxú]~4jY¹.¾§²»w–sÃ2ÇÏw"y–  ª^v™Ͱ7ß·åêóO”¾ék*Ó}½)s™T»å+÷©ÿg«ñÚ%ÁïW ½jRƒÿô£¾ vâpŸ„¶£›rQoÓøí q—;=7wbõŒabÍ :çôü<@Í"³,üØø„¶·ã™õìóÔ;ܳYüþ/uZëtç.…È Ê{I}ÞlïÜÖï'8õVpœLZï¸6¼nÏÏa¯„çØùIµÖgªûÎ>Tž¿ùzd7ÆÍ£ÜE›è¥ž\”ãÕSá´Lxïp ÚðüS;SÈ÷¶ ›ÁàÅÊâ«JÖ;BMž„™ÊÐdÑ Þ¾Å:T™Å1'=U}kÙ×Ì[vÑú/èOê áÎýg€D:z?|/:,²•àõG씚~u¨ c÷®6Îi”wñù6 &BÓäÒÚ´HJn*þ ȠɇbÉizãE¡©™!Pôü›VÒn}Ó¶§aº×_§’Dxtý¾· @ZNœ!©UæW«ï&(öw¥÷Ä)RÍïd5ž]¼9Úå“E «¯ªÄ¦ æÊ^Æf­[Q:<[/ŒÚS‰?Çše¥˜§é?°n»®˜«o<õ¨<ö²¯ãƒîÛärâSZÉË¡ê±)ïÙö"óýÂH¹–iË»³h*‹Äµ— ®zÎØÌ‘õ¦J>O½×Ö…¼þâáëí“C÷9¬¿C´»ïIé ÿÛ)8%NoÞÌK¢ CŠ›tßv’ßÛ¾û>Õá^¸\âåBÙáj$ñ¦Ýˆ($7ã,F8­U§1Þ¨’%qÓh ‚ ”bµþ¸“#ml¥ Z>ªÍH››zª®ôÁõiômÒÁTÛŸïl[l[ Im½ãºážümÍ6Ï®ñÙ~¸ê/2’]å¯öÁUϪwl¢)Ș+°-"T‚À&9Ï–›¤>Z6™Y•šÆroªÕfû̱OðTxú^’SÂCç8è`7’Ê œÕ ¢ ¼7séðJè/“@iË“}Â’8û>F/ŽäìV¢FH³a³‡5nñ ˜_k”fÇ4RÈ"gb¨«»Z¢xÓ³eAÖ¥zÓïí>Q Ç1xðv£JkJ›e^ºø°è‡Ÿ<î]¦u˜¢!XØñ…Ï7 -øó+]Šwð|Tþf)Òá{­òöKu ‘ú´”JFõj€rpr)K2'’b¯»52Î^,ÕOÝÂÕ:›:N×7X¨{)EW0žðaÍtm×µ†ÄJ¶ò‰=ÝEcšÒ›MxC×+²…»)!üožH7Ëô÷É?L>j•ã¡5¼êcy#ÂIÿ>¿½jÚ1?TGõ{l£ß›çYF^¶ª?ËÏcK.'–ÛNÅÏ` døcâËM¹ùK±´“#––Â~"…ûÔ (‡›ï•ÜüíD©¡°ÇÿÃöò endstream endobj 2976 0 obj << /Length1 1399 /Length2 6072 /Length3 0 /Length 7039 /Filter /FlateDecode >> stream xÚtT”ïö.Ý(¤ƒÂ04Hw·t8  1ÃÐÝHIH—Hª4"Ý ¢Ò%Ý‚„ÿ1Î9ÿß¹w­{׬õÍ÷>ûÙûÝû}ŸçccÑÑ瑵AXC•pˆ—O ¯©o"àãàåãã'bc3€¡œ a"6C(Ò †€‹ÿ/‚< F¡10 ÍÓDÀjîN$,çãðóñ‰ý‹ˆ@ŠÀ0€&/@ ‡º±É#\¼‘0;{z›½8 œ˜˜ÈÃßéYg(Ú`”=Ô½#ìÐG@`P”÷?JpHØ£P.â@ §§'/ØÙ´“â|ð„¡ìzP7(Òjø50@ ì ý3/ÀÀæö×GØ¢<ÁH( 8Á P¸:ÃnEЛôU5Ú.Pø²ÆÂCÀß³€xAÿ.÷7ûW!üw2A8»€áÞ0¸Àæh+ið¢¼P`¸Í/"ØÉ Î{€aN`k4áwç`€’¬.Œðïxn$ÌåÆësú5"ðWô)+ÂmäÎÎP8ÊèW 0$‚>voàŸ›u„#<á¾¶0¸í¯!lÜ]€á0Ww¨ªÂ_ "úfE„øÄ„…EPWÔ büUÞÀÛú;ú£'ð÷uA¸lÑC@ýa¶Pô‘¯Ø @!Ý¡þ¾ÿ;ðϰAPk¨ NôŸêhjûg¾|$Ì `ƇÖÀ÷ë÷ï7 ´¼lp'ïÿÐß/ÐTÞXÝD™ûÏÄÿŽÉÉ!¼¾< !˜âG?DDùþÿ,£†ýmƒï?¹ªp[@ìO·ècúWÇÀñל€ÖÒB U püGäæ|B|ôôÿ-õß)ÿ7…ÿªòÿù7¤äîäô;Ìñ;þ„ÁÎ0'ï¿´hÝQhh"Ð6€ÿ7ÕúÇ´šP˜»óGUQ`´dávh1ó€yùÿà07%˜ÔF†‚Øÿ‘Ìüñ/«9ÁàP„ì×·ÅÇ÷_1´¿ Žèï‡Z—¿CP´}þ¹¯"‚°ùå3~!a‰{ñ¡åÄ/$ð¡ iõú­dŽ@¡Sèý¶$ѯkàÑYO'¨-êWè7 ñ€Ö`ˆ£›ØÍþ7ü]!îH$Ú}¿Åné_ëßV‡B½ ¢/ÓÈ£0‡š°æó*YOž¯#x‹Ë­OLz¢„PìŸ^øÚkàg*O¸Ê=±)¿3”¦óùUÄø´×þù¨—yGvðBªJ C±gUî'àâ[‡”ÙAo7&’öt•ü Q—éö3³ÉFÓ?ÃE:6*Ö ¯ZÝ6LÅv΀âïd,© ¨8ÙÜÖ¬ÖeÔ ‰9Y<Ò,ÝÝ@õñØV ,þL®9–îÂ{Õ,>cp~¾?»·'Màø¥zW¥py%•KîPRub¶Zƒ»œÐwùW) ÷芜#ذk¦@ŒŒ¬ñÝt|΀F‡!YXfRû¶ÚX]Sóø0?{¿ËOo¼l’#·š‘)Ú`,p¿¬œ²å]2˜ØºÞzôT¹îëâ§Ñ ° kN´~ß᡽Nù¼ã×C•[ZÚ—ÑK .M’°Q‹»ºB ã¦3ú³5$~ºÂóÐØÂößÖÍåéžQPÜ‘¿çtd¼þ)Sùhg3xZÎ @þŸqÇ( ·ò†â†Ù²¦Õ¥ŠæqÔP—ð+nå²õŒKu½âò¶À܃!KÄœàZÝÖèà ’Xå*ý%¾9ókKàÜ·ÇJ ô/5²@üˆGü ÷RQ"¼ë{rÖ­z±XÕ¾ __)bÖëSuóÖ‰ÑâR Îãð=ß3D)KÐ߯ßÊšMf~n*qðiñq]g~H£Š—RT?2S@ã³]éµ|MˆiÎóCKåm2Íà¸Dš\ž«(†l>ãçt) «n:åáõƒí*÷ôã¬éŽo ÊÄwµ‹“@V—Ýð·ž9äXÔ]}ù û;êÉÞ‘*9Ó!æÞx¼è%µæUâÓÛœ*µç§®à†tévìÎGŸïÆ';¼ÃªyYÎ"ú4ƒ¼³á‡RŠ@)ƒ%'2q•[WÞ,U5ˆÂ}sX1dì!9Ý”3ŒâJ‡4t3“õ­,ãÕµ^¿´¸Xž1æØËvÛúåE£çòùkH ‘,êH¨àëš«ó}mq5¼ù¤œÈnÈ©é‡ÑÀú™VA•fžCC3ºM°Hß‚-4Uc*n¶º‰ßÊËnaYªñÑoÁŠPD²Û Ê_ì~à|g*¤ç#a“Q~-d­®ÓöjÖvYV{.ñ‰¬¿ÏäIÇœð‹¹0/­¹ê¾Ü™áTˆ‡Ù†eÄQ8ïñ=¬‹kŽäëÂýŒ›¬éƒG™`rVË–Ó¿8 Á4¯¥ÓÅ’›!Œ×D%aä¯8ŠãÒŸƒe {zópaûÏ™¦t¶>>ÇÒÑêƒ ÄT_è.Y£L.êÕÀh×ãÁa²¶ç8±ë#Çû¼ß@¶GmgïÃHs’Ô¨äÈ'=¾{,}Eæ¯p Ì`$ ë7•4LKM)^y½*Ò (õõ3{‚v]úW‚´ÇuWŠßš¿ŽŠÀK.H¯UìžÜä¦ÄùVMIsiŠx™2NòÏÊ2õˆÕ!ÅU‡Ú‚y¤}[ß;ã&4~äº%Bàªì~÷ˆø'—œ#‘‡*BT@SXBÖÑir7÷âªE¼†§vG~ª„¿;Ñ#Ö˜ÃÞžG/7.>àIBdPÐm¿Gß‹ûê_QHDcÉa%Ózâ…¥ß*LÚv|‹í9K9hrí|ÑäÁ¡B!ÍÝD:é©•[õBo½"ðܸq8 èF®á{5ÛŠÀg–”CÆîޏP Ã@ YC²Ñ/ÑÎ9‹í¼ fþg«"W¤3Mq x\ "†…nyyMR€êUq±•þA ƒÙ´ß?+Ü~:°—÷}uÆp³Ü÷zg– |«»mx—eÚXLXñÄsÊv§3;ç~¼Z+Ùˆ¾' ‹ÀhÝî^ÙòÈ{Æ7K¹µ£8Ãcµái†Ûj©_]†Æ?.7í ›7ËRûØ¢«NG›Ë¥‘&Z¹^;Y@'ÃW•ÚOýãzfÖ߯¿J©ú‰ÁòWǃÊg©üé9YMŸâz#ËïGßfÎØò²îyj,Cøf ŽðÍš¤é]Ÿyü0†%T‡;²æôSTÁðq%ñÈ?_þ££¸çv;‡@êþz¦æ°±p¹â0 y¢Ê‰Á»„ûœ—Ñ tÀñ>‰¾:JOŒDÇ´TQ5v\6ЧI…ú€3Ò×ûáøZMæ¹[[õbéMIŒY“¥¯&6_„¤obLÆÌÓP–»åáˆÙ#\s’ Á÷W~€©`dŸúX®Sh±Ùˆ ®í÷¹˜¦Yø¯çß`èg|½WF饯y\¬Z±‰œ®ïaÒíb¿µV~ÚD\zº³Z,àÄ>(‡N?"ñx“#y çÏŒ2j“>4¦]NPÚc œ±¹»™U[¦Ä2&³x@ïï_íªHs{„!¥ÌÛº0l´Ä»ôqkUÿÞ+¬äÔ¡½nbì¢Éæ€ö©¿«¾JaJ5Fñø²n 4hxÎØœ4.¸Àn™¤œŸC*¯›Å̬~ 0:œ"¡Ç°‘è"«ˆT(€Ñ¢Ì­"ªŠnBÛ€¯ò¢‡‹ã÷oågòƒ9òð ùg𵄤N4Îmh‡Ü3µDÂqÄØúžù ^Kè?./p²bnª~L[á!FК&9ä°)’&Šÿ‘%£Á*^ccaßͯL O°Í›vºÜ² ý©©—ųõï•Ò‹‰:ãÉweÏñ÷ý.<+®¸ë5æZcÜ ÏrIYW©+óGr_z†ÉêH¹ÆtÜ6Ä϶ ;RZßx;&l¼0~R‚Ó›mÌÔ\SÈ雿jínsȺÁ·¦š Yî ç4•þÀ²cLºfág8èü׺ÌdÎ/y;a³ìM§Khâú72'ÓwÖå’ŠÍw] ï ͱÉWe¶u}¸uDfð U÷Ë•„_°Iƒ=É¿0CÈppÅŠêåËúªŒ‹ÉL}b¹c:•úp­®Ä;Áý¬9iûñ÷¢)y%…¢¯‘·š N˜~QZ>„¹Ó»Ì1Ì<µ]ÓžmRÚOî=艺çr!™GG¹ºÖèíÃòb2“Dª‹qáøÝÑ*;bγð˜"ž/p€úŽ;¹¼pºuJMãòݧáö;à3LÜH—÷t•¤mKiÄL,5ѧéÕÀŸ°FÇm×ÎÇi7ükEcù{ïÚº]ßõSDUÆ(—†d(· ‘áJÈ6žî|R}£å¼`T³òÒ<ôRï“l~Åõº)M™ùOø|?”œ…ý¸“"j§þ)Ûs˜BÓUз˜£¡ïY¾“HÖõ¸ãÛå³1ÙBÁQÒCÓ›ôj&ipÙBli‚gÜBÞìøu±Ë8* ÷¬xŒ>/c.>âŽ<ßïT“ÒKÙT×øõ…rÃ…[orI›ƒ×î ~™)IƒTI£:·?ñZià=½-˜ƒÉEÆ}ͤ)«»¿ÍÇÀí7›ßÄðºÞB•Æx9döÍÆÇ’…l.Âç=V8z‹O Lذ괄V"…w'­v[‹mS°Ë"‘ft.ú* ¹îÑáqBC·Ê7AÝ…ígå›4ºÀo¨KèT÷$Àt.A(ŽÏ´a)äDdÉͯ˜ÓT#45“Db•è‚Ñ[—çsLøŽÖ~ûˆ±´[‹¤<7™ryœ´ËqJ>}ž¹L톱z‹˜dSÃŽqIkDûJsÛœ¿¶9‡ŽpÅŽyˆ["É¿[zÕÁ¯˜àÑJ¶¶Ï]Æö:Ëçö=½+í1E‰#Ÿ›X…ÓE£•줭¨E¿_úžœºÛöb›L\ñ jÃg–›_<Á[–…u8¼›dÓ5빌¾©!©¶Û1ðŠu xæˆR¦šõœŠ¢<æ×~#@xLW´i{'ɘîí[ÍÓÅÅx‰ŠÚ…˜eAäñ¥µÄ‘ ±:³¸ÉoBbT0­=búxxZù~’roŠD¨SVóú~×â¬Êú˜úöËé5Ie˜&Wø£iÁ£¯µ3õA«çc¯5?â05¿0¶º"«Q¯)ÒvÉ,jÏ—’FÈí°õ~+ýQ`±mʲ@ýyæÀã*ðE.9NU°zŒ Ž3¾õÖ¶Ùâ_ÖWæ§9ðŽ•ªp-ãÀ_8£ÄÃ`âplÅ•ûvmـЛø¾·0l ¨f”äŸ'©9ÞÄÞcs$Ô¬]ò¯w ýŒq‡1¬ìcà† Ô³!–Qú‚©ù,ë‹¶ß»šGkÁ­©í}KÞJ³»Û Ãפ‡ZÀO ÇöÅÆ!;NöžÉôšõ+ –ÔL9ƒ–}ߎ¡X*/ÚÓ±61ÁáŸeœßc1ýÜïØ&ÅC#É€ÿBu€RmGO–KG¦Å½íéaýçàl×´Ž4¹àíÕ«Ï«ðô¶„ŠGF?‹eÙבµçÔCŠ$„=â’î4û „몋§|­)ÕÁ?·äïöf¯ùÌôµm¾™;ŒéâóXÕ£7{ÒXÇûól¦‡3Ž»IÜïòÙ+8cp*Š †Á-Þ{ TàNä§Ÿ›ÿÔ¤Ÿödë‹R©Ë×AYÑÒH%æµH0G¡‚æÄ—)CžšJ®ó WªÑj³íè.Ë1Ò¨OQdkÍÀ/Þ´´Ý‰¤³ ’ªaU&¥p å Ó‘zF…°W;Üýª^‘—ŸW““ž¶Ærh,²bÇËF« l˜d½¾ÇÎËÊdâûÝáÐR9.?sÉÞF¿r«$ü½bGµŒ¡YA3ûH§éiÎóŽsá¦ä“ Þ±d CNÎÁf®( íÐØ¸GT F‚íŒ Iq^2¦3vÍ8jª-ìé'xh©Ht\kÌOÞ³ÛÅÌœ4>VYáw~tH•¶ÔŠÿôNÒ ‡mCUßÒÏ+Ýx¹èž¦<¬‡ij•m\C^dR1ØÕ®Rª'I0_“µ¼¼Ù~Ü]®dÚüÊÍs~ðE” ée{l„­'-¢£KÚüUð*ã­n ¡æ…pHaËæ)Œð;¡µS–8Ò+oµèÔ`”ž?+ã'€oõ×O×lqsŽ?‘•Ví’¬'ž>È£ò[jHѺGy@Òà§£Nz{¬AÍõå"5þ+$xcÝ+Ù ,¦wIPá)Øs =½34lYôzèáFÂLÊ:’TœÈyy:ö6;ÅÛkþ“g£ZyäˆÄ±… [ȃló[.Õû/m”Z……:=¦5êŽ?-=±¿CpóËrû ,—_¨ Ùˆl¢O™ŽòbšåêÂ;AA>t¼—1ONå/ó®;5muÅèÈ­ý5Ø¥ Cpýc‚½B-1›kƒ­«ÀñŸ±Ç3øv µUÄc,cÔò;¢IÚDÇ=S# Cv¨$§/Jî’bžuª½öë ë&kø&×íwqùþGfÑs²dÒ®“âÊ4è¶ÚÜF#7mÎH\ˆS‚i¾æÄ·¢™ZYÁƒdl—ªì\ÍÑWõÚ«R»ñƒlw£ðg¹›R[cA_SÚú¸šÒaf=ßO=Œã‚µvKn5`…Î)‰îrÕäS-±Ij–38cE´›•Œä[`‰4¨„„·&ûñÞ0BŸ—S ‰ÉŠ«H,sA”¢Ô'jUþ&ÑùZRÛÏÓß"5ˆÏä“ïÛgyÊ}#¸ÝóÆ&9öÙï¼Î7£ßà«P¾.bž¿u¯u'GZ§dÃõ!,w–—gh¬ì«…SMoÛÀq¹hþ`&5յĨÖrÉx·ŒAÛQóèPÙá©e’+³‚!7=®««›ƒßóFnulÚB¿,t–YO²p–Pðç–é¶ˆÎæ0ëÑÇ|=øÖ¯`#o<‘ET§Ô³­â3òŠªp‰`¤`?2ðÔ6ªšMGM—¼l6”1ùKŸé,æÓ Rz>úŸ9Y+úc@*¡ç7ŒÛôDFä²÷óm¦6ªÍ×,¥ !â]͉ú'SezX[×G8{[±û¬ñ(ÿ# f"ÜK@Tñ(žwƒ‰”-oêaYÒÑ+½¾•ð2ª÷w^ú¿¦æ&KЩ8rPä-*®-™:7~G÷¢lÈNT]™ÊjŸ¯–%xqâSlú“KЫ“i·ûõfG-áÎç£á—gä¦C~ãHú†»Çk)' #Ï"F-ל¯Ê qîü'„×Ï÷o\Í'øt“¨ÖÚJ«Õ3ÍÓû™Ýž½nŒKË]Ï@ƒ‘SÁG®Ô=­:ñ)#Â#˜PèÇ¢]±«‰9ö­29ö¹¡ºÜ>˜ß !îUO;Ôµ?u")ùÜs“\ÌœcVÒÔA÷t3×ÒâOÍÈëVò¦ˆiÉr:[YêFú¬úzÈHmxõÔzB<ž:ëËu¼ïõ¢žðÙ/õhO¥­])Øï=û¥ \:¾ñz²ßæ(ølëK«ºÕJNû…ÏRù¬ã;ßõ ‚GA<;ÝØÅ¯lgÒ‰á£m*é c ¤à:BëÅ3éUf§H¸]ªøQ…±û=ŠG¶Súc†+%ScºØÜYŽ÷ÇÆ|=oÝØeÞÕnõ^Y /‹ß- _Qî: ‘ÝŠ‹&¥¯›Âè©à}yPqFk‰{˜j”yÕ3´wélâ(ã³hAU*6t»‡èÜýÜÌK¶-‘œê€a¨î¾y)N'—¬ÕÓ–—ïú{šŠÑÝݯ‚%VÊžLS"H™£Ö϶ciÆÊô~Lò^êòì¹êKªïT%‹bP|x1Ǭß~ŽA´û"F³Š$«eúLÓÈ!‚¹ý™ü{¬"þ«G¦õìád]{n0¦J7›HM²8Jò-C¬9üó!Am·Åik¸ß÷ÊÜy&.à$냻Íù¬*ßLjcSìdO·^Ò®ƒyLT<”0—IFåùü©×Š[%Ù}> stream xÚuTÓoÿ6-N etÑÝ]Ò:¶ #6ØFƒt " ¢„”tˆHI‹ - ¢´HwúŸñ<Ïÿ÷¼ï9ï{vÎö½¯OÜŸ¸®ï¸ØŒL…T`(G¸& ‰ej¦ÖÒ@0X ‹¸¸ÌX7ø_ÀeGc(¤ìÿrPCÃ!X¦Áâü PH ®—PD (")+"% EÁ`™9¢Ð²@uˆ74uQH8À¥†òðC#œœ±¸kþõä…òEdd¤‡UÜáh‚@°ÎpwÜPˆÐEÀ±~ÿHÁ+ïŒÅzÈ ûøø€ î í¤È'ôA`&p í ‡5 ¼ q‡ÿé àš9#0pSÔ=¬ â7ŽÄà"¼08ˆ»hª£4ô€#ÿ8ëÿqþ P$òït£%B C P”»é‡@:ï!Üà@CM}Ö+„ a¿!n.â A¸Aq¿+‡5UŒ\ƒÛÃ@Ñ,„A¸ýjQøWÜ”505”»;‰Å~Õ§Ž@ḱû ÿÙ¬+åƒ ø{¸‡@Âîýjæå!lŽDxzÁuÔÿºà À0'8(–‘”—Â=p_¨³ð¯ôf~ðßF‘_0®ƒ ”ð® xâ÷À@¼á@,Ú ð¿ ÿ<DD€0 t„;!€ÿdÇÁð{θ壾@[0Ž{"@ð¯Ï¿Ÿìqô‚¡n~ÿqÿ½_amCýÛÖæ:þ·MUå …d$$€""Ò@))`Ð?ÓAËÿ'Vy”ùS-nLÿªØû/xÿŠƒøÏ\·Q8Ö¼ÿ!¹X Å}‰üSýwÈÿῲü¿Hþßiz¹¹ý6óþ¶ÿfˆ;ÂÍ﯎´^Xœ P8 ÿÛÕþG´pÂËý¿­:XN*H'™…DÄA`ñ?8£‰ð…ÃŒX¨óÊüÁÍIÍ „¡0ˆ_ï\ü_6œ¾ ®¸÷ÇËß&8N>ÿ¼W EÁ~éLTBA£!~0ŽN¢¸}ˆà ƒûþf2P„Daq!@\AÀ{(4à×Zŀ ®gÆ·ç_Æß¸X(ìAÿ c¸aýÅþQÔ Æ©ñ7Yp%þëü[úp¸/ ø8‰‚ÊE¸ÔF´W«0û-½'ùòµ-6ɺ'FË=õ,ÀYÿJ–Ö˜§ê]XÅt£éÒ¨ÑÉ@fþÍã!_»ŽœÐ¹4í§X<žÕm¡¼þ“½'ø-ŠÉiX*=vjë‘ñMŠ»¶D¶<-'Ï#¥:ÅV*— /Ú0+62ë@w`Ñ!%[3ö¡JnÛ:Aœ5çWì;k;Êj´m†—™ŽùðA"áHµ%žñÄoÁ6!óÝììۜޞt±Ý|½®*ÉŠ(FZ]¶Üä>FºG9ºµu18¼ŸO Vúî?Ò5}-âñ.Ú¿j}Ëÿް0tFž¼iêX`îy<Åû;ÞKeë¸ùO¢‚kæ¯Bˆ»jü‚:U¨‹Û¢yUIrncýÔ>*>,ìý¿Eäkw:¿ç’`åÞÜé -~@æœ$Ú£(/½)LP!z0öîµö³=µš/ýwXëŽÖ˜ë¢–Š7AïÌûˆ†Åã‘ÙXª„' t‰ëÔ¥¶^ÛÈçyÈ]‹g]ñò ‹(‚LBdîd-Þî–¥r>Û†¹³9(¤Ä+®CëØÃد}úàÑR9½¢}ëüB ­t¸Ÿ—zÇ¶Š±µ*3\Ý?»ÃÝjºaÎj_†¤²䡵€ôçÃwœ“ {Äìåšë|.Ya«­Oܳ$bý‹c\†(™ Åe¿¦0PJ GI€HöT%[éŒ'b‡Î?…ÊŸy~eé |À“pDóÕ=¸6ÄMÊìÄY÷=TNÛü-èÄ­ŸŠŸ+ ,>&-bË£êcM í$Ffïpw‚l(*䩇¶§_xݱQH·«Ó9 ñ#Éè–¬d–ÁϬö+2‘Ôº-XƒÕ¾Ø'€AÎè.:4(7Õ§io鈀‡a»Ý'²óÊc¤ÖÞzBü`ðñç#‰#¤ZÏaVüô˜±(pÏ–1Íhv/|¥ÙBk¡Ÿ:,_÷U¼ÏJèR&‡ßÅ Cd+ýÆn{{즀0ÏØë$à‰nPÙcÒûyÔ埰•¬x¼X‰0(#‘0ï%ˆ§‹è·u 5Wv”€ƒìšæôNðŒ‹M$Ñ×l>?à8ïX÷ï=5ëÚg“æ÷£·WÎ{é{6.±ºÕBèÉiÓöþ˜5ºO:S\R_˜øµÔûªvH–"AGzé"z.‚'ì+¡C«ää°åÀP{*õ¹µû޵‰Òs¿æ,6- Œ+/™ê‡ÞÌãäÏ⃆Z[BmÙ!-¦úû@ûón‚ö`¼ }ƬkûeÐÜÛã ñ+ä6¡…þ#d"¶Grâ‹¡« ··<ÎÊÞ¤f‹!¸ßëyŸ£ÄªG¨ÍKëIÓÃ1ì—§[ˆ"Á7ʪ^fG¢ˆ±94ŽÆç%ßžÝø.Þ9Ok7|;Æf¿ÿ—Ü~—vE@”x(W5|÷gNEy”4‘í,²üË#I#ªõ‡ïé 8*ó¤™2ï[v ëÛßÐ;yÑ{©iÀº†+7ÍxG52NA’‹ëÎWèçÄfËõQ¶O;Àgþ2ÕÓS¶Oo¦ê1þ ŠÂø™HI0ªSèJŸVrmØ9öέ¶|êiÌj<†¯^cóò~I (£Á±¦ÅU~´¶êí(ÐZÁ+p¢rVOâj¨SÑÄK~,ÊþA|³6çZÛI„bfáÔ1©ÉÊ¢<…ÏXËÓ@vï><“ ³aÀåÏt÷Ëæ+ šWÒŸ6½oªÒf>Ÿ<Ê®{H­®þ¹®GéUFqý3oNÖæÂn†ÛâéÅ/ÚcÖ#LvþF?£@ˆÆðdÞÆÔ³°'I–,)Ú«žß¾ˆý<«É{¨Bm6 ¹^åà—.{åg.àóNn”"q¹èZT:Ê,Ìö´9Sœîˆ†åâôÂÛZõ¦•ÜäÛ.¹Þ=®d²‘f 3…×Ò?5¶{8C¾óÉ<\¬j0ßH5¯“¿ ¡Ó×!˜sj"Œ…ðµSQs­ ï-/©_®4lC|µþP±'Í+ïNX‹ä+'Á« MMæ=LB5 OÅ‘îÒîµ—¢2²gÍ€ñšòà}Ÿá-kí¼êùÈúä°¹´¼$1‰fý­«9‡eÂ0”&…®5LÙð'ú)Éçš'UíýB[½ƒ?*ÓuËhÔ+l¤ugÓ?Å­3> ó‰Û9(áÏÞK‹_#?r!åx”ÒìæZj4Lc‰jðÏÉ '|ç>Pî, gï<¼ˆ%£¤Fo˜`¯Ñ:h½æ%Æ”Þ1᳡G%¶Ü ­bÒ  BnÞ´ê–û6—!¦! PÇÐM5ÊUÉ _éP…öó¼ääéÁ@iq‹×]»ú/Æ&yR°Fzœ5Ü5¹<¸‹hž‘Ο•;ŽyÁüÝ#1LEkíùÏOD\Úa,ÅÂÍßÉN]O¢ÍT †>ˆêªN[ÿš«ÂtŸB(ù6±)|Èp Jû$Ì–_9c-¼œo>¨ÞÛ! ë  §³=÷Iã]È¨ï …"n¹žEÐÁeh¡q´•´êq ˆ¢GJÆ (¶]ߦ "&zAç°çÙFåañòœ…@Ýw5¡ï­©ÆÈ>ú éæwST%!Y”D–nÏ>~‰Þ±T\¢ŒŽPo¿Ûy7g¾Yiü%¤n˜ëʱ³Oɵ'á®j£ú˜zš(S. åI·X“úY1Ñ—z"„ —wè\q¤4Ôî«[`J*xeÛ7lº\bó-fIéZ+x®¹«Ô}Î,Ž×–:•+ë´Czœ¤Kµ©P}™õÃ}>Ÿµ`p y³"²?XHò…#l®æŒ»Q’ÓmÛcÈ%±å<Õ>9h²! + "Ÿ±?JŒã‡i”ÍÇ„½­O£ÎQs: `JTrÅ—?šMŽÛ"YÂvì?nùÄ)ùêÓ‘ÍVœj«Œ5bbjOäšþÐu ÷äø›Æ‹¶E¹h¿‰wñö,Œo¬Y£x®J¼¢~ãíaxÅøˆ`ñ{ñih£Ï~õ±jÅ`ºœfì£êÂauÛë;–ä‹;p®ÏÝ(e¯ÙÈ®PmQ5a‡’3d0BÃV>jyäy„3\±Ÿ¸_×ýX›PÖnßG¢Û3™/”þùÖD©É‹í‡®¡®÷éÊÙR„Ù‰×&’ñEb<˜Éâã/öcŸl÷[páïR½œLµÝ1#Y<˜kó«?"ýV¼ÿ$IáÏA‚qá™aã};TÒ¡Ýræ¶ç”PEL=^P­ý$ÕâýþeÈ Þ 1¶çæ»QA›€ÛtŽÉèÛÏ@JØL:$}-Úøç\Ñß–ÍîñÝŒiW3µ¢ä÷Ÿƒº[êò£AÕÐhÎÕÔØ<®·çO&K\.Tºâ³Ì·S›9 Ø”ƒLØC)*Úgé]{#õ»D›ë·t- ,E‰ÉñuUïÞ”-Òé¦V¥ä¿1M¬Õ…!ÎcT›$dµ»Ú •™RVeÛMØ}Éù†…X€ÿd{xßgŸôHßËæMþ˜Î¸`Þ˜z}]Ζ˜ù9@øTvC'qî b̪(od9ºªSØþd~ pʳÑÈŒJ Ê\Ì3øìcOÙÈ@óñšWUù³’zá|€¼r(MùÛÙ Õá-Í÷õƒ,káŠÊP)ýÛïm)2…²Çsä?aseU§8Ñt^XìNm)ûˆB»@c/-ôL™}©¬†Ìk®Žô›út¤ûôB»‘õõaK/ãó†cÁÓ¦ }³u2É+ïÕ^÷ïó®À#û29°©„ï¶×J•xÜóCyàX7b 1ŸžvýŒ8)±p˜~»ž+WÒÞ$Á7:ï&IÒ’ýS}{üzÂW™ûJìA-\ÌÕRüªCˆ8ãè1aÁtXŸÂ™¥Bù¼ãÏ¥S’[ùST'ƒN+93 Üí^O0%Ö:˜˜ÄÎà‡h^ÓMa¨Ù-µ…Š™—¬Ãý ÒøÕ†wbÒ­}Ãǽ$R8‹Éö3^*1ÂçkŠƒ%=•4‚â ?g“{_‡²A±Ø¡·±p霥´×Øgɨ£¨ †H¿±>ízüpôZÑ iZ¢Æ`]ù€ÎÓ½by·æÍ.Ø%~D@)§·U¾ÓÜ»nÙÐ}cä—Ÿ\Üá8K5R0®êÄGÁ’¬7 “ÕYµ7ޝ”ã _ÂŒ±pTWºnû¾ù¬afÊðΧü³Þ/aõËï6ß÷®…~ëÛŒeäçKÞÒ¸{¢Š§Ì)9iy8þ*âå·å´¦œÍ’¬‰UÅ-o˜È‹ü WFQ¤¾oóN°îµkM=}&æŸÍß4¼ñé“UÑMäIب>¾qà`—¼µ?zõ½œ“CovU•À#>¡¨®áQ(–¦mözæòz®çñ”A~…q.#_Õ]Ž^b )ÕHiuÜÈ›†êž]Èt=݇y©SÒ»áßèlÐN…‰ÂëÅv©¼œ]ä¶Pö¹?¬"Ƭš´B‹šÏ×÷Sî£xsÛ.A:¿¸Ð‘ˆJfÛÖ³E÷ž¦™jšÀ/VFÑŽÅ(c_±ð7É}³Ö‡j7óWvÉv$ÍÜ—=ÇÓ ´Ãò|#«wu+\šޝîâ·çV®“¯ÚV”“yí½`¹ï0VȶB‘øE–ü6xÿÒņr[øæÛk`ƒŒ); /¡â%­íüˆÑ i¥fËa‘–­J²a{‘øÞO_NË8 Á¢fÔ±Ó·2%Ê®©+{|šÒâ}†ËŒXiùyŠšI'€Mú¤u%x}3Ç4¥îb>²åx<í»Æ*½ÌÚ¶¿4KŒT±ÐUzk € OjG£¶; mL›< ¥Ô[_Ôwò]ÆÉ’ŽH<%2FPg Éš÷,ìF¡{']¼Ò|Üu-áF¹Ï¿ïÊ–ì%ž‘Î2ëå·ž: )íåÊ, š¾É¶T Ê|D×9j±r“–Ø2¬o¨\Ù}9Á{¾Ä2?Z¹¸â–*«­÷i‰óÃÊ¢’ÄŠ¿Úü½6š^ªqüÛdqÛ&3bÏ’¤H#)€Ãì»\4ðÒÚ‚ÊërÁ–ÅÉ?Û– ¶/ªëÄHË®ê2$p(~HóyöäÓMæ˦‡·6øv{FW¦)ñ¹¿ý¨»K@îôjájù6ÅÍ`ØìnQ· {×éÙSâûTÒ/1ÚœÌq^Ã<óßM¢'Z¯6fõùÍsu}ÐR+*<Ïôÿ€vÉZ¾àU::²ˆ×迈Éåž6s7‡Âcðr>±3^3Üy¯Hùxæ¹_ì¶ÃRdQo}Ê?å™}Í®qY¿ïô ÛEõ*i­Æ„‚yP4Ëuuüïšá}öÄw5¼(Å}ôÎtÖ'îöh:„Ö=툱~sƒÝDùtåg8ý¨”j§ºMaæÂ•nj äz¤:…´¶ …ýÅZKDÙ(=wDºsõZÕ‘îÉþ€ŠçŒçm–|•ƒ8épYS,Ë'=¶ý}\Çת,CóÚÜ­/OžÊØ” g²ñO9/Þ_žK›Éx}ñ$ºOª}ÁAã> stream xÚ¬·ct¦]°-ÛvÞØ¶mÛÎÛ6;Û¶­ŽÕé8Ûv:ÖíïÛçœ}ƾçþ9wÿxÆxVU­Y³jÖZc, e5sGS ¤£ƒ #3/@ÑÚÞÔÝUÁÑAžAhéøk䀣 sš¸Y;:ˆ›¸yZ@s€8Ð ÀÊ `ááᣈ9:y»X[Z¹¨5TµhèèèÿÓòOÀÔûzþîtµ¶tPþýñÚ9:ÙÜþBü_oTnV@€…µ ¦¤¬#£( –RÔH€.&vewS;k3€¼µÐÁH°ptØýÇ`æè`nýOi®Œ±D\&W' ™õßm@/3 Ó?.z€ÐÅÞÚÕõï?ÀÚ`ébâàö·nŽk3;wóüµ[8þKÈÉÅño„ý_ß_0eGW7W3k'7À߬Êâ’ÿÁÓÍÊÄíŸÜ®ÖÝG‹¿‘æŽfîÿ”ô¯ï/Ì_¯›‰µƒ+À èåöO.S ÀÜÚÕÉÎÄûoî¿`N.ÖÿÒpwµv°üOô ¥‰‹¹ÐÕõ/Ì_ìºóŸuþ·êMœœì¼ÿÝíøoÔÿâ`íæ ´³`„caý›ÓÌíonKk8¦EÆÁÂÀÂüvsw§ÿéóºüÛ êf†æ/ sG;o€9ÐŽIÑÑíoJõÿÊŒÿ}"ÿ7Hüß"ð‹¼ÿÿÄý¯ýo‡øÿïyþ¯Ð’îvvŠ&öà?.À߯ øçޱ3qù…›Ø[Ûyÿ6ü×@-àüÿÀ‘q3ùÛ Ë¿‚032ÿ‡ÑÚUÒÚ h®líff°0±ûÛ©íæ@;kà_Eÿm&€…™ù¿øÔ­¬Ílþi=Ǹ€æÿ•ü_‘þ¥Î$®(/%¢E÷_ïÔ£”ÿjï¦îíô—Øÿ(EÁÑü-þÁuôø2ü= ¬l\ο ¹YXüÿÙþ…aùϵ‚‰›‹µ@ïoÉÌ,ÿþ?¾ÿ\ü 3GófEÍÍÄÁüïxý/Ã?n3w—¿ªþ{âÿü?×ÿ:è4ƒ[]r4ã ³ÉÈÎtkÀÎ×ìg w*oV/) ªsì ̈Úá©6~¯gl™æýìô^¼9ˆyà2ºŒGo>‚Á 2»)–™‘j›‘öõ£»=p ÍÒˆH44Cކ3`žü,ÏHeB=wG”n-Æf{»€ Ðë’!´ôJFŸ}H£Aãf'ï±­t3Öø£0eTÙ2¢ÿ½Áœ?E—ÂìRj*œûrA¤ï*yCÄX”`õúh‚u/ŽpwXòÜp°ì§Æx:Ë¥@áÐùþ7 ZÿSüIÌ™Ã:FIu«ËÙY¢~@¾ - ˆŠ9;â@†{Gõ±Q?•Ô;‚ËÎKEÊâ¤e@¹?<>µ^ëQs *g ‘ŒŽb.x RÉpÀŽ™Ê„ÞŸ4›ZA§Ã€†Å¡2ù†ý œ®ó÷a—–pSuŒá=D³NK>8è •Ðxaˆmï5qaƒ¶Rör-‚ƪ/÷³oZ߆œÄ'ÐS 4ÇVw'—°yðÃiœQ6ø“•=´š=fÆf¸Ý0 °_Rø*‡ª$N5‚mƒ]kº fo€ÒV[w!sì³-j,:ƒ}Èm©iÑ›Ç'‡ó”8Ÿ9ßÒy#kÂyÔ;ò|SÄkÅÓêÛÒz‘êÇ7}Dq4û»^ôŒ*"-Ék93ZÅ CJFfº•C½U%™¸È©Žv Wøl¾#y×OÞZv0,§µ…˜²ü&ž¥IbG-«m2lŸ}ŠÀÕ4ùÅ‹ßuæ;!²8¦¦•·'„ŽÊÈ2º½rzÑa…O°¿ìs͖ߢqì÷„Ã@Ü0ÂíØëíõ‡Þ4px$IïPŽrËç¯/³a%[˜^H]"aËxëA”þšó*{áWÅî¡òDèëa³ä×+£à Zâ÷èÃ5K Ö‡œUÑitW\Ÿ=1)rdøÉ)8Å ÂRf#ÿ¼Ü¸Ä?30þNÛS@EÀ†&Å H¥]›sÏjdº¾×k×ÕKVx4%÷‚ xÊñ¶’N`U´u¶h²ntëŒû9sϧ3ô{í¶º,T—´ŠIçùw„ üg² ¤·¨èiÎæYliËá¡M¤¾ eƒôd‰±™žœyZ©kö¤@¿ÔñDR:¤ÆªéàÆÝ…‡FØ,”“_„e²ÃÜtP´¾Älÿé†óQДT,šÕäøÚMq!šÇ‰¹ÌX gMH‡ÜÇyj±?žå'Ö Öï¸w`Û‚™g:àüd¼—i„:â: òíhö+¨fæ¢}4ↄ)|M™-´'¸¡;a1îz.°Yí¯”–(:ÙwMµâ¾|ê_=ÓŽ/«’>lïùŸpk=œÞ­•—ü8„‚(ñžèÝ<Þò.—}Œ@wÔƒñ‹èSÙy [d\øóÃÝD>«¹&“ïÞìv“Ì’>Æ# ļ±àÇ}@:Jú‚·ŒÃ/‡²ý¶ð6'‘ÌY‹}¼Õ5¼ÂÓ4%„ÔÕC[’”Ÿ¾Ê7j+A8m³örTB¾½—ÿíLeRÐQ5hÇ1š²;lÀg-bÉâÆf…*–Yw.z+WØÔEH©»H ÜjÙü‰ž¥4oÙ{/øYw¹i ÕwèÀøÍž7ô)ŸãnQuûË]®Vg[B›‘·"ÀvA‹¢iXÔøH¥î 4"+N~£W_é9:ÓwË’*%0ÿ"[މamU¡P§ùjwU¸'£¾Ü‡ÖW «LáŨ­a–¥æø/h™p½Í×JƒA=75§’}îELÁ“¶ùo± ®øÇûgSðbJoä|_‘W"ƒPAÚ3ƒáÅN•óË3½O_»’ˆ3>‚ü¶Y…q¦Å…Egé9Üz‚ÀÔ÷óɰ@ÙGT>ü^)3§—%…̹Ӗ~m0½‹ qƒÆ¼!í¯\]_¥zaDÙÛÑ®$y©ñóºGHý±¾Á/“s·o¿í½ÍC”ªª»R^\G=·|—á‘Û«¡þfÖOå¤(«ó"ät£AlÆI »gà•Ø»kŒbé t³ð›Ò—5!¦ë|™gecÃpè[w€RÃBä”±³D;Ê\pøb_ø6Á—èêf‰\¼£œ£è<ˆÆÊê ¡ôÕŽdIö¨ÜIJ,La?Å}®x×jáàX뙜tj>A5¬›šïzGÈ·P±‹æ¶®!휎b£ÍçR£qÃ}‘¼‰Üþ,f‰‡WUóxõ™ ½TØ*êÛ ½­ššËÔØ—@éÄ,8PQàhäF°Ô9»Es®:HÖ&fsvó‡äÝ—Œ4ø{çc¿÷a½¬ok‰ºcÞó2Œ+S7~Ë^ ¹ÓN¥½~è<¸X¤}ô‡}sñûD:09¤¼äç•,¨kHøÏzm´á-ŸôƳ5Ìq?:êL$2ð›-e÷W’€g‡å°¤!‚&Œ²TFDè_¹q˜Úy~B23[؆©Iìžíøò°v¦‘†Zöï¼Üê3F® rék Å[×ø;uIà¢&‚JA†k´$AÙ`% B[yI)¼d¦>;Cr†¶Êòç–iÙŽ(J›_¦'tXû  U_ Ùâd7³rÛXç0ís¦×ŸQmi³Ê0u_}s8.´…:{¬"v$ ÍvÌIñ!M0 v”nÔÎjï“IeF¤9±¾ôT5¢)à²ø—zÈÅ{¼÷­ÅF™¶múwû†óÔ帻ãVÇ‹³åºÙCSÏ­Ã…œSe™)ëûÐue½­ö°eV|b‹\üf¼.?ˆ\J_ÂÒI\V̶N,ÐÌŸŸ¼VGJ@Ò6¾P*ùs¿é:DóèѵS›šGz-x×ñïóX(@}Œ•GÖeƒeʰìžÝ’Ÿ,VÐK†ZÄ\ü·¶=ý à7½B³QÊ':úíêI%?'Gí»ªž© JBC—»àŠëQ…p|½”CŸ¬…Š÷{­ÄÅ5µî=OÅ“°/h“b‘®ÉëÓ;)Mi˜°uv ö( z†w*?A4@Åë9|X§X÷¥?ØfYßÁ¾¾EûÉÉésd2ÚUÅ [ب"1fà(¾·æ1¨)ˋƴâfÅ%n$‡ìEf„Öå:ˆ|gäƒäÚ³*áyɈaKåÜ"àòÐŽïhR¥¬ŠaYÂog}2pÆo°¼ÓÒflÄ“ý ³HXI߃m…ˆ$ÿSË¥e*\¬™˜Ô,ýawÕº''”[G°|Ç4Diå¥"&UKw&¸ü±!±ñ‘˹臜ÉsÌ5/$¼y"vùR­(ù™™Ï}œáî& 1„¢H}Û¡¿Ol¨ÐŸ¡úÐâ«4CGÜœò§b|2&( *kaes«(Öw«8˜HÊ…¾¡˜Ç²oC™Ø÷¡ý…B șœØj¤ -Mf`Gô} ègÔ>p­-ꋉ>b=ÿŠMËÀzˆì&üg"ýóKÛgf$›Ä(î¶“€Ú9tN\N˜rãWrëBç÷w<¡¾é$’Ÿß©v4UUýÚ›˜ÊÖËåŒÜ§[+•eñqt 媀´Ÿ²:Q·b=¶ BŸdöäÎ\I««%’;x+ [?/ *îRÄ9ˆ¬^º³€1¼Ì~Þ‡óü©êL£øÅ'p-M¯®±iü–¾áz‘¯µÎ2z¼¯¥ˆ ¢Øë¸ þ'üð,ê'ìpÜlÖ«Èï 3ì½)6\ÏZ•.@/K±å%"bWƒòôÚ10ç¡Ì?EщûÛP˜¢J}0¤¬mÀ Íjœ¥ëÏý*¼ÜTÇÞ³¼UÐÛµF È  ¦™lÝ•ªÌx€0ѺkSFOvŠeq²ui÷ñÄŽ=ªÎ`ÑgK…j’³l¼ Íx2í”¶9dÈ÷ 6,´‡‡ ~™5JÒ"_Ÿkj¨aªz- ß«{‰CÚ:äb Z–˜ê@[›êD½»ÅÔk-{ÿ¢33Ù‰0q mð1MHµò9Wô6¿ãWÒOÔ¸¼àȵ]Eïx.‚Ð:ÚãH¸ˆ²‰ÔÙ~#|Úñ¸z²¬;Éäôo¯y]˜"tù ú½¡ý™Ùø(ÓbG§2Íî•DCÒ— 8µuÒŒ`R«¸-âÂö.p¶Ûá-8øAæ‘LÀãJ¾-̯ óCÍoÛƒ16­áeåt½ÊSG’D›¡5É:ýT°GB¥²Ê¥eÇí–Œöᔦò£ Œ> ¨áÍRg×#5págvÿ6ªðš8§Šc-Q3d¡è{‚®Ž »š@=ŠÉ¦w‘÷Ð$1I)e¢rÕÕ‹ì·?¦st<4Ä2unÔÒ†AÛºÄ8PÍ |kâR–D‘'LÚ¯ÍLï(¨ǰù4þ6–å\Š”(ùîè&qϨ±¿Üèãž2E k.sZPQß/ˆÖßÊá;0²Õ†]~U4Ûrg9;£lÜ¡>}w:~¶î=±ŸN‰¿óÞyÌçŠ#ÚG;dðÁj"âo1[¥«×­ý÷Û¦¨‘vÕ¶Ù¥B>™yIÎ6X”‹ª²¸B_z=†]ë>m=šÃ~¿-´Wb™ë$ÍþXAI&ÝF˜Žß6På[ƒV»_A–á4P† É¿4›HunÂmŽÈÝü$aB^°ªâýî5ë¨ýn»ãÎw›×Ô€± )˜Œ¦…cô\bK/·%”›™>EJQ,8Úû€.RWßyÖÓ~?{¸PÛŠ:`ªÓ˜hK#޼2 ºy2ùç¤Na„—ˆ²ðŒþ«!`MÅПGMú¢ï»9Žciz‚‡Úš‹7-—\O,FŸñûÈ“1ZïòI³ /@5IÇ3µ[½P·ª]´7û@a£×6ÊÅ£*Uåk1N†™X¨$œfE#âv7}3Ú1ñfTþ~!÷y /GË”¾vu¢;ýØô›ù‹­ÖH ]ç72g}½òtPUð=/ŸÒkáæ]¿ž(ÈObnÜ…£  ¨“¸^¥†gÄÃÉ›‘HܶEUgÒ”@ëNë¦et3ƒˆügjoú>úeú>ãÔ€½€–,]!,9Lk­–.Ï9F úMP $J¨ƒÔÝÄè´mizçxç:.»}ª&ÂÅ:/KXÖ~¸ÆÚ¶­–8,ãÑêæåØn]'ç,§[ü¨; Äá`JnYZx‚LÈå+Óˆj[MÈó·0©Ýß.Sk¢ŸSm¾'ŸÀª9$DNVÀ¢Øˆ–¦`sä!$è“÷°Â|.ˆÚÉx…<|lþ ù û’¨“–ý]ÌaÎÅÍ|qýÈæ’\ mèÎÃr¯é|tædvF®ÒaáÔyÐ)=”’@M\‰c³2£pXàÕòõ|Ư͠€š8,$#™‘Xc`—\Q“W\ú#sˆQkꑼɉ‹A[(!Ê«Á§¡ý¼¦dt8yâðÜv}ÒUúŠ7:œˆrôÙž,Bð:üRìýÁ;á¹öJÁ 3e]ÒëøÅ+™12C}:@FCU/÷×IÚƒûJ÷^íjhØ¢bÖh÷Ì:":gœJçs¢Ëb·¶E½è¬cŠçz«C,ßÏ«ïh20—¾¡«x¬kˆíùØÆíœ{«­¹c,´üs°¬ïž„7wTaÞÇXñLŠßA=%¬P›¶èÔ´¯Ù M{zâØX“‘ð?f8ΫHàŒ‚Š“¼G^k©ÁË¥W-T(ÜKcÅ"séç¦AEEéÚ͇ÖòãåÅ!,_B&|ýZ]e /²ƒHC|Û‚SÃ\!RqªƒÁo ½ÒÆë {ÇÉÖ]ÃÔU]}ºtOH„bÌ¥£§§büQ€‚A:¯Z×ea!GVHVmÔ`P:Êš,òT)TäàR'ñн½?еMc[ì>/ï°¸=oZ>¦TRYò0÷‡¥oî8÷b<·ùér»<ö]²Ä&øäù£Óæ\ix£ª9-òè²I%¯ÂèÚ“Üsh_`]5Jëç‹Ô4“Rj|=NlÑÚ£qI`ò‡ß÷Åøú·ÔÞÕáU„ôßíÈ‘]L?x¢nÏÁ"õ©&^Y¯»ïc·Ë}šøã›íñ§QÑúú·‰ñaÍM^Ÿí†ñwúL®Y´q¤[¼>©glØ=‘Ä* aº,hÔuÝy8eÛ´ì¿rÞÖ+gŽÌBLDyˆ1GÄ ­©_"|·bèð¦?­Æ<ß&œœ•¾\†­#æ~iÓÍj»þ9õvaužóÎ~7Xñ4?ÀÿV±Ý ]ý È ]ޱ4.‚ª¤wV2lM%NÄÆ9øæ´B»¯Iu¥‚«å³üÞùipõN–Ug{YwâºNÞxúkò§!|_Â6¨oÒpóäj ¶òV³0&úõààæó1l¶Ü;¼¾Ã…Ö?¯˜ä柱8·–ʰž3Á‹NB2AÍpÀ´+â{ÆÂ,ÖZ7€ÛHĬ]ˆì-™ÿü\©Aå"k„!JúÈÉq5Öm0¸Kv@`¡å?MEWx›A°ÏßnWrƒôþ)‰\ænð„ Fµ–y²º÷n©z{tÎbÈ“µù™Á– £÷BÉ>ÿ 5_àß"üÇhðšu„xx"0ßþu²®/£Žˆ””'rfˆ[óÕÞ«!Fþme &­ß:ÿNºîž•PÀKÔ#J :d÷4C»ˆ+CõÄVŸ?,i#°Õ“0¡.B_詺(¶ÂîÏÏÜ×^ÓÃ’<¨ü Ò²ö€%,äôalO‡áÖ’L´ó{Œå ÅfÑc®Æ^<GƒSÍ/FyóöF.½çÓ ª©¸^²É¢IÆJ:C^ÕÁçó¶õÐ7Éè¹â££¢ò(‹EŠÔ&B5éýÇ·WO£˜(68%ެè¥]¸óžJƒš³–‘G5—bhr¢ ‚ó¿¢äÍ×’“Y8’¬‚šj8öH‡Û m›š9Ì… æa½â„ǘùЇ^Þ'!ìù(ƒÕw°o`¨q·¾é]#`SÜÀtr‰5‡#‚HQÀ‡à?$â¬êTæ|Íl_ôw\4œæÝâ^\ÀÀqˆTC!žˆ‹>¶¼\&?5º=È©æŒ|¡Ê›«ËK§Ý$¦ÔW!]F8Ïkÿaæ@Óôÿd¬3¿©ÎòدÊÎmDĪ’£†ÿd dù•#ÁoÏÑ·L §*È"ÝÛö^0¸h,ÝînXÌUC‡´ÝoÄpˆ“ãšÐ宅ÑNã<4y%¹õ`ò=ž0;/ÔÒéƒ7ͼææèX Ú丅/êãïþDöÉ0Eò…fÒ߇_5r¬<Ž ¹mék¯Á±^»c?¨Ôëïv½áÜòÐ1˜)Z<Ñ$m‰¹p¹üYžQg)°ÀÞ@ 𕝓“ýª\"ЀPø‰K–°VrbèÂ!Ch¹!Ì{ømB%ãº0€‹·;èÈmé¼’†ž ˆ ,‰e/Áº»mýþ ˜r¿>ÎÅPö?\°aO+…çõ×3X.“ôÙhQÒÞÞr 9Y}Ý$¬%qûE„Y@®÷º“¬‘‚¹Åd~ã\^Ý®ër}ËÁs51<£þÿ3ÐÞe¥\tFÙµê)…ݧéÎu,±–ñ"·~1n4\­×høh8Ù±øÈ'âÏ„þ]JáD`–ñù!våG9ýC_m€Ïoì—¾6ÆÉL ëÓºõÓûê׋¥•Ï ›¨Xé§k?õH0»sB§H••o7‡3Ql«Pþ«&Q²‡V0µ0(GËi™Ãˆóaòì7LhùVÒ!SÛ;-¼?B æ â­U¹!ØdH[uäjŸ`78}ß‚Äf–ÜÄ¢èŠ!”`úƒÆ¤1“\‹Õµ0«J^mÛ,+IÕ™ï.…#]0j½Šv3_T©ö r*ºY"5Ñ=xÔÍ"LHãXÄÌñ ëÞTI‹ÛÉ-eÛÞ~°Ktx½d›æ¨î[$oçO@D£Ü/ƒ¡sÖ§!o\y_l^çÍçÂð™ö…(i“Nã}´]Ÿà“ñü¼"ºj>ŒLƒ»t'ç¢.›’dûFYøo¦hj绹ŠÕ6^È1Ôd«­¡²·_SÎ!íh†ŸÉ±ò؉wqáë4R`[¸_3 ܇m%1X_öÏ…[õÛ+ŒeïtºËÅG™1 •+•à„ò¥ðCŽ£µ·‹•oø9â冂â½÷CáþJŠO? Ç:ýh9m—?i¹."MhÞF_Ççµ¼( “»ucpg ñûe¬¸B:ôÔjÌ ÏSú›,ìªë %¢õ² ЗÆLoŒkT¸Ø³3ú]‰L%,:<8,Ë•,oyiØ c§Ð¬ƒQ“;IúXG©óO‘*ýtÉEÁo´Ôæk˺ڰɘÁt¼Öy¢ªåj±šÚ+ôD}ý¥?“tÕ-«æ&Ü‘öOF•™¼Ì<ÁB^qجˆ‡À¤ íZˆõ©zßY+%qí°£ÛR7ÉUм“w´üûO·7ðÒ%'© LƒcË­7s–@{ÈX½ïCjäœaÖ4DݘS¬ˆš¶i#йh2¼ña›¥ FñBËàß…çŽ!Z^k÷'»7>ŠûιºDÖ)´Ì‘éz…dV÷½)@þ>3F÷³öÔ´b‚x•½ð÷^§ö BÔ‹-Êå|˜ô1¢£‚z3놮PÀ&5”±¸®N \Á€#f 7\È}L žóëò%Ößb%„ÏA²Žá†U,Í/íOù»\ê.»·•N¨o©H3=W_™tD?¬¸ê &›8ӡʵHI &ºç^ 7€¼L?ëL#NÐnU/¨‚õF«8ªŠ$~†ŒcÛVýèV1¢"ÅJŠ\“.Å€»7‚-ë íù)ÐòëCšAŒÛþ þǪ:׆.zªy7)ýýjm+NX÷tçT„‚âÅÐÆ+%¾¨ÜwÉÓN/˜î6º³Ý«ûã‰y$4 ¸'`÷…TòŽHY0©‚¸m$áhSr;$tÜ‚lîÑ♎hI¥=íK.~“'T:L™°¡Ã¡Ô•¡!^dB†ÜèSc¹+:\xŒe¾üèP¿HAÚ!@Lßm”~#C~2))ÑäÊrv‚Fir=ùcRñ”ïrw§. Ê#Îáµ º+#¿þѾʌš]Õ—’ NKƒ'¥g|ŒænÁÈ¥‹@Þoh—ˆ¸J?§Û7Ò>áÑàF^ªzáZgqØÁ²Sð²kåfrvÉp3Uxw3WµÂ=`ñéÜm£/ª% ½µÜz‘yêRSæÂÿx 9KÄî4½í©÷f„A¦£ŒÖŽ *ïDåxžUü±CA9‘Ý]¥L(¯4çTÇÛç¤?{Û}—V6Nžûò`XÑ'QÞ¯Oؤ‹‰Ö`ãчçêÁU"]71ã-Üõ^.‹F"XÛõ`³=ÂΉ®W¨“¤Ûm¥[^æî~ìωoúôØÍ¨Œ«’›+âŠfŒŸfþºôŒJ!Õ•Òàj`³eüþcŠ7¨¿:Á-BE-à•!þÞMŠNß·ÔÅì«.0¡Ò{èð~ê›þ™TU4$'½¼ªtüK©t8tO½]åò ߦŽíJ¦ïß8«S¦óõ5ÎÌ¢ËJØçgÛiSeWòjN\fÊFw®ƒi…xÛ:ÉùfcñÙ~L•½ïfx­ Ÿý„io˳+F”Wpõ™åf9*¨Í…|sâ=¯k·¯ilmùç ^Ó’$xtð‚x+Ëe5xÑfAwP˜±=ªz[0Dy~ÚOÕ]VEàï7îj9Õ̶Â*%²©®Ÿñ ]O¦Èâþðc+\8_ª¯ò~¡$¦ï>\˜a/y@É/B±{7ÇQ#Sè¢j͉ÖÚ4Ãoº‚Óç2È ½^8aµsâ žË)šé ”-IÐZ·:¤1Úƒ9Ù]÷2¦ LCàZ†LàiQ¸P>o;nY­Ó/ÕCÞ´àý1ûNvÛx»®Þ D`·XAKØŸd[Ç”'ä*5àéGâñõyÎØœ6¿g}¿T5a2uÈ×/ýNÍ=²½*R&\Ö˜Ìæ|ŸÿåðÕSO‰í¢¸MØÿX5¬qç-ȹˆê9tõ<< ~‡Å‚ÓðÍàmv¹‰)- Fãæç¦ Z£?Œÿš™›Ôcÿ£!v  „‹DuÑz#|´a¨F§­üœvòÃ&…®8t§ËUþq f»àÆ|‹9 j¯D¨–…’ÛZ¬¬¯Aò›±)=—™o[lS—6«àª^#à´"ãGØõpܯ,ÉFrÒMØg‘dÅûç,Q6€S!õñ2oi¤yìur‘W\ÈáT}åq'µl‰403Ÿà…gYÔÜs,Ý8”½×íOSu!ÿÛNµŸY%ZQa|J”HlÇ~_p®øär¦šƒø3ê9sÞìÞ©s¸5±•õ=h´î¬·S2~縩GÛAcïNõ¢kqÎn¿3ý¤léÅ›,W?DZÇxÑμe±+ËíXˆt ?ƒ¹pÑÉúÝùW®Ñ/Z¢¹?µœç“(Ò+ß®0ýE7pq.;5o ²äyÖȇ6º¶¾4³°ãk‘Í>­OÒDKG -A’úkt»Öâ>âRÒWuÖ»Â{¹omÁyuŒ†5Ü­Ò„Ú¹ó[¶îeæœY‡˜Å†ÐzuT' V qyÂSù/Õ¤“G› ÊDv˜¶í–l¶ð)ª D<›.9ÕÉ“ݨä{8<xJ×1BÖÄÌ &Y(ˆ$#²×&7®Ç.|©XϽ ¥&¾¤½Ï‰ð(×gg‡Z5×€ƒÜêYS'–Žƒ¢[$Éçþãð^v“ʈàt [1 ¸ÊþF9dzÉ‹V†ê#L…€ÏL™“†Þ!§É`'ýñ¶®ÞFiÆj†2Q% Œ”Á ¸¨ÚyM³ëVoÄù¤Lvø+o ZòŒªò>ÐaÝ¢ÓãÕïm¥w¤1]•Æ[ð IŽ ¦T¨u¨Ïæž–ÇS1”¢àÀ‚H&§P#î?<™¶‰÷H(Á`Çýʸ¸_JL\ܦÖíÛážÚà8‘ô²ÌfÃän¹#fÞ?â«¼Ò “kø&»Ï¥Šmmµãf/¹í¶4Z… —ª>\¿Ñ¥õIA™„³;Þ¹î¡ØïÃÁk‚•Žì?-Ý£­°xgW€CýÈ¥_dòA¹„U 9ÜêJ¡M¿óý"R%+©Ë‹ ÆÐŒ¬]¨i vë½+R„üj`åð2ƒknôpa¯Ì©û! \Å!‡Éù@×{{®Y•³âàYßHUŠ[ãš­Œ®ïùý$Ž6_%±\T츱 9bEð„†Ç2eóBoÐ R¹!ù˜r™3ÅÄœbŠÔBßÁ€ú §_³1·ä ÞF륲úÇSna(5%iã6Ç1©f:ƒsÔúžé½$fï„x˜ò<ØéФ£=(òt•X ±s3ž'û˜Q¡Án©Â«7(IMhÖ‚6¹Ô8c QÄGC>´ ­žà#“"³÷'ÖKøs»Œ¶ï0XzÕS3¬ÑÆ 4A|Z¿ÇÂ(!æF¬ðë[Œ¾ê—±G&¶ê¦Ý8=ɳç½e´kŸU(DQ‘í´$TY¢ùè(O±Þk¤i' ‘c¹ô‹©µoF‹hÍ0ÿìø¦.”nE¢,n•o¹1h€U£¶T¡å»ÓU6ÿð¸¡Ù$åâ¶l¬ W"àÅ4ãûUŸoÉE¥‚˜q›ûÀ¨hÄô8l'˜×â#(Õnv/‚ê’ ÖˆI/º‘" &*åG3ý†÷ÜUØü«l ­Ã>¡«,èÀ¼¸S¢’aË)ºŸþmRÊ žWÒ>—iÊœÝQ±Ïm¤O€fuI«©ÌM].û¾åwÌ,ª:„)vkµøù7ÇO‚Õ=¹Ém*yŠäv3 b­ŒˆùYSŸi-öœÌ/¼é´ÅåxvZ1eíg*·zKUÞ@Ì>a•ôw.u6z‡â7òg2,áZdˆ8Ùä­Q.¨Ò7=á:¤ãn¯¬4ñÆYó°ioG…]…éÄ–w},ƒÃl9¢Ÿ¥B-ؙϷÈáÉzë›ø¹åUœ7j‹?\M·œé¥ ?y˰IÕ¾9WwNªí Í&b¢ÜËñb£9'®8j?±÷§õjåþÜšq«{¿E)ÿÉE¸ügIãG®þF_ðª×a¤Ë@K™1Ï–/lNı4§¦”Þ÷Ù_«Áw¥ÁÄGMiH)W¢5¶(7=CB©ä\Ð_l¾œí<¹@²˜€z·kàÏP‚f]»¦õaËýQÏ|F•ÁKa÷4+…øC»1ujzn½ä<µàbàLy„´µ„¾l½L/09¾,=Å~"ñ1U¶ Ä)í»V¨²n-ϸNʾj‘yÜmýc½2Ïsµ8¤yýòøÊ³.kÐ3d¼ÜVÕ:DQÙCS[Þ[ÊŒŽiXçÊÜ1iDAÖÎ>r¼ÓiL /¥?ñSý.²išy¦0¬IÍŸÊÎÁoü=’® œÄ»º1Õf)$Ðo7Áº+·Ä”–ÖµGM.£8Ûé(™4 ­$‚‚/Íù¹Úï’·îG¡w@§g[6Aï÷É%Jž~FÝX1°`·çØQ0vH ¡Úm÷*¾ºõRÿ2ç"›Þ¥Å°´¹Ç´ÌW/>Ø6Ú9)ïf÷³eQ¹7Ò¶`ËÙ.QØSl8]g·Æ‚dˆNìGïÑ÷&ΣnÏݵ³ÞZâ9QÀÛhè+ʼniœQub°­“㢷ãÐÇ\ØvÀתdJ†máœ_þ~“bnlvͰ(ß}ˆX€ì*U@,pûýÄ™2à€¨ŒP­í zá€ÖýüRà:)É:éLiø-¯|…¯‡97‰DEŸyp )“1·šq°@.CŸœ¯Ù±§óAéTî7FåW¦/ŠTËK±åW¦@×ÓLGÜ…Ò@5ñr|:̇ʱP¿…ÈhTõ!ÚÏÔâSÔ~ç]NMcÿ _û¼ªŠ!W çunh¡ú&~+Î>NFªù:5Ö¨Ì!žþÀEhè™—ï^RÓÛ¿¾Õµ(}oFm­ªWñV×A»‰Ù¡­Üö‰ÃÆO E  Å€ @B ¥ƒ‘JáÉPŠ0KHh°Gµá‘sS0úÞM Ìlv1ÜKN¶Š!\$ f·O&!˶:}6O_ˆ0oë¬÷…($µ'l€O¯^ÂØ9ÊõSÁ`þ#Ä7ãŸáíÞ@*uÞIFÌZwÙô`º"ÒÀzŸõ)µì¢2©z5UŸ`ñ½¤M×4Ä—¬øè׿ÖýíLíZ\ér왽øß<©û£'§«Yáþ%ó ˆ™`|ãQ:¾ A§·èQS2*"îm/rôRˆgàüi…÷.Ä2™H oÁv% d«„ðzTÌò“ýˆOÌaì¦×œüÛcI]Ô5KH㾨îI‰tæ7ÌS–zפ5H]ø|•Žâª§fr“¨up]¶´ÛÇ\zöÊâÔư\e*µæ·'g³X†ÐM¿Öà÷ìj{<™nfñÀ{Îwc2Ô §¹T«ÊÑWýï¥QD„Fb„ B馨ûýÄ6Öú©qC„Fy»Q49¬ßªCfÛ¸x+ÿÄ0WRŠ_ªÂE×f,÷pˆ¢‹ÓÝE=~“XG8±ÿ©4DìøôÂÛ“êêñ(W›SÆsô•‘¢ðàˆÒN`¥X"ß$ÈOô‡!y? T)wT6$iÀ‚Ht…)<ùDŽ9ˆ÷‰«.Ví ^?íU¹DÏëÉäj| µ]úÞâf\ÍQåQŒpçù³Í„Œ¾|Ìñ®…âè´ÓwZãðòHÀÓ‰htš•óÜ[âo=/ð[Š¢±Çn˜$…t/ˆË©iz_˜»²×ÅïÕ‹€’4Éïô ‡‰:_ºìˆHžd×\üùí(bˆ‹T:Yß»Y)F½­&‰¹¿ÒíDôqŒ…ƒ; µòàÜLÅj1x¨í®kö¼¡$l‹ À¤æ‚4µ™È{ýK±Æ• iQ‹“Pçb»B›¤Ù\ÈHΰ5hçm"RVføUó°‚=-7Û06ÆU+?]dy2äèË´2˜M¹JõÂSXV”N‘IÊ7-B²–E0×Àä/ô?YÛØðÏ÷*–ÂDÊyðŽ[ÁÝ^ñ×?¬¦|}³j Q*Ú?ßÍ>’^¤„ãfÎâeu Q¼6†Åßô1w&UN Û6Óa·¹Ð®¹Ðš ¢t§sòèg³è2C.Σòû MA4䀉›~u±³;äì¤ÙO£Év<ÕzøFB6»[”VÒKœÐ%äq¤=÷Š_Ùºe ’*¬Ã#d ›ýÚ ðBãé½ãlUäÖrXê}‹„þûª ˜±ýVüV˜qïM)ÃFè`ã®{-ÛÍ鮳Œy /«Ú–µQd“ù£ðëµw)Ô!3òül{©þRNÑu w[•Úéú¡š0ÚÒÄqÌv{!oøè36Ìg}7ai­ZOgÏ»ÿɃ¤^Øòº¦üŽüÄCÓ¹¡¨ÞÍkO¥rèûö[­¶X‰ø¬z0÷G.ŸçðmÑ.ó­@vçϹ¨AF¥ =ùÎ%£}.4EüQ•ûÏYe[†ß†˜©ÅY |T‹ h1E*oÁ× ³ƒ8íK¬’ñOÐì.zØ–x®°ƒá#ìÁÂáó¨P•NMÚülx) Ò¬NYüý©®?•ŽÓ€Nøãc×IÓé‘$Æ„.”…N Óz©pò¾«™ýVƘ2žI¥ü)—y…´3aÜCAÈ©Ç`Åvãë§3?µkgAá˜Tn?J 3|}®\IßâúÈËÑ&™°e½ÅêY¤ µ(›Ò=hKÞVšIܳ?86è °NŠqÁã'o æhð å'7a»þĆÙÓû«i®áãZ oö v­¢è±bû+•=‡É5ð2v¿ežÞWT¿—»¹ƒ³å•\ܬ¥)Õš ߎÒô.š{‚Ñ]ëQY1µlî‘ › ÐSöß;¶ˆ$qØ%‹h¸Ÿ·jw÷ó—Ù5·rýî]ó3êíh|ê>~þ&ºÐtÚ+Á÷ïs‘¦äÝnåÓssÕ'8Ö>Ûá¡3þ°„&=A Ži!„èsÕ|ý Ä “ù\§ÏtHñA»ªÿ´ƒ4Ÿ'¾…·ï•b åÎuJžÊpPåÐ)6vØÞwr'¾Ç ±‡3ÿ5 ìEŒpÑR/_¼ª†‰åʉ¢!Þ‰j3¡ÁåÚRœ{XôQg ï?6a)£t˧Ả8XͰ»P”zï·Tm:0öV€e4½2›Ñ´ê·XìÙ4íj_F¿¿ q]Í!dìXeÀã "q.¦5ð•U N¨ÿ2ah˜ÒDRøîャ1KÄ4’µÛp—§_'i\›w ˜b–N¢<ÛO»N¿sàòc+<Ö,&szõÏ„zT`ÞÚ‡£âô®²,á“íFf½uƒíÍX†¿Ü7ùP^X~5’…ЦfZk¥†/íæ;¯"E½=sý¤†~‚¬ÁB©î7}}²¥ìh26`ò–¡êÅB§ƒÜz 8)&\øÊÓ…ìÈ5¿«îhÖV0éëô¼•ÚÖÙä„TbÞ-Aüé€*»ó]\™´Y“„°£Úe)E”ƒƒ\i\ §­cW«Êqõ4X늎p…âo7Ï×ý§vè¦Ank‰´'q?ø„?¯ðíu‚RÜùpW¿xù’@Å@Ò76FÙ/±ÓÅ’Süxàm‰NØ…ÇïÀÿs ][‘Uó¨’Ò uEÝõü1}q0\!íC6 p‡¨žòæZáy`KÑ@^WÒŸ,ÅûT½¹ßûB{þ’na9¢+k}2ÊîF”F+a¸ÃFré3Þ°¢ Í K–¤æ£—î› S0¥~~ÎÓžT zö°›$‚]=÷Z6ç8j²ã’~þ´Õ¦3{Ȭó "í÷¼¹ñ¥†3¾=ù©!øØŸz »&%û¤Gø½ú­œ Ö‡uT,‚ŽÆµà éçµSm J´á™2>çWð! +AºÍ«¦.—ø"—bHj7ÙCa´g úB¡w2N]þÔùõž±D6½¶;6ö¬Ñ­5R+»ßóa¬‘×I›Lškõ&±m}c7ÕÝ.S}£7C\åò!ÀçêÃ˜Ž¨4rYòrøþê²%ûD1w´þ˜”¡yž"èÑàË—ˆËtµyÃê/×?c=gxPð 'g­eVæøUÿŸR ­óàö½¯&o:â·ŸSALvG^[?õ-2é_‚]O¦µâIðw,{G‰ôw;¿iÖô.†8Ô ¢î˜¤©¸]4A /÷–w ér:>³8š9i}?WL޾ù[¿Ìâ=g)v»6o/Ÿf¦¥ ÌÅÒ`2sñÛ1%CÉ1€~FG5Üî…W‡ †’EhRÓCz‡°¬~勇·+N;k¶‡î9 \ÝK.pMûĪ'!UwÌX1€j^_~bîÌ¡(ì Výª?Öâ‰x ÁÔ›-Y¾ú”Xù˰Pg!·¹›3Cü\•7*J]Êì2öÙ6¨û¦×Ò¤k…Xjwuça!gþ²3&iÂöˆ$Kë÷ ”?Sß %Añ¦d]ˆº2ó„v¨ñx-Û ä,õ<6ˆtƒ¢¿Ÿù}‹þOdû©bcÏò¾õKä˜AJ åh±ð»ð"ú Nº–˜Á)…*êüQA@™n&Ën°=¾SŠöó<§ òc_Nž #y€«ÓHVòö§&hÄH>¹C=ÛêJ˜’i‚’ظʳ ßSû„2aÀÌ¡zœ£ ¢èÝùÖÅ(Ÿƒ%cgÄq•E”WQ†M}ŸJäcocy††åŒ­ÏRÆšÖ|`ÑÌzyl+ À,K`Ö»moóûêÎEÐúÈŽ 6»t¿Ô_6AÁÉXof¬æ3LëE…`¯¤¯õ¿7F[»Ýh\í š¦Ìis軇Í Y²·“teõÜŠF7-âH­ìÁ€6ÅýQDÙGOëÒüÝ3›¶”¯´Îý¸±ÊóY"þÌ>kåäãùæÖblÁ«x0á. B¯øÙ #ßÖÓ¥„ÐdÕ Çq“æa8Q#‹zdŒ$¾žªªs MݽOgr[K'å,›“À°—õÊâhdÐ:³6SLâLXV’¯ùŠbþcáA©ˆ8Ox£ûƒúµÔA¿‹Èf¹õº5øE'¥ô:á #C€VÌ,Öc¥Ò æu¯ /*Ýâ(9×S@vå@]kü­–O£IhŒÊá±OVwÐ+i–ò¡–Ö‘i5g¹€ö9©Ýf^Ñg¶çÊŒ£¦¸f·Ösž‹ [\»}¬Ù2«ÂàÔÄâÎps¼À×}‘ ÙY¾Ú¼|GS+K|ZŒü1 Ag•-÷1Z•˜Xʆîq1}¬+ j… 9C9U¹nX²Î-ÂÒëÆ'èÔõàÄsC8ªttúEÌ\^"?ºôU ÷¼à}â°óÛ÷€>fUëæAü‘6çø5ÛìªÛ“ô˜ôç üd@ OÚbLpŽ©ûú`J<[ï>J7D£ÁIîR‚Ó¡{:Bï¸-%ýz?ªÎ^ ƒhŽËÇu=™Œiä*§ ³õßq$þùº}ZáðöžHÇ.“ü.û f!±‘š$£˜nS]@Wkáu ²’õ’XdBûN`g5àb¦ú‚‰ O£ü±Ø…k:¦ˆb"%hãaÔNF/š÷`- µr`г¶¢)Epb øRjÝ&Ô^˜1adþS9ìph ž$a+ž³>_†VÙ3|»=¤6iP4Þª˜„¿9ï”R—WƒñvŒŒšVâZö b(öè›é nžÃ%5]ì$ª$wP»í؃¦ò+/ü$qxþH¢ºõGÍ™©öþ‹M‹5\x!{O¡W.¥6Ò$ûE2 óÄ\ãÆ*™dܦ ÈR³»m®Ä–Š êùuU!põíôé·á gºÖvöñŒAÃyˆSï:àåÑ¡?PÌFv†xÞ°J4PNµáä/Á< PG3±ã€Ñn qZ(ãOé]-$.8n¡uš_cÜ£2æìO¨» ý˜³>½>èN\Ѭ´Iƒ¹Á=ÌrM9Ò‹„ ø{ˆM4?Èá28r:Å ßÎц>Nñ•YÅd³ÐiƒEåÅ)ûnŒ‘ìåX”*ªàÅHßk¨Ýq„ç]ù.raÜfèÿná+•ìÏškYkl/á¥@u?D‚5™î ´(L‘ÃŽóE)y¥›¥º@wãÕôiÌÀ…+Ls&>þêžâtÅuRÅí‘îiÚ¦5ȾµbÔŠù…ýutW|ƒËâøÁ&L¥yä¶t»6ŽÁPü·J½±½j•ÑHÕ‡5oîå\*w} `àËœÈ([ ÒéK¨Ð™„’çææR-Ñ „U/5,€À²Ö­nF Mâûù%LÈ,gT„0µn *ÍE~ ªï%™Dã¼eŽqóvŸb†Øeÿ cØž‚)äæéU÷*Ø´b‡NÈQû4iƒØ/­n Ǥm™ßž4¥.ƒ×$F' +u¯òU(³ vO2š˜°Â»þ¤v•.#ëí k:Ѽ7¶/‰:] § ]£^nûÊ2”‡ÊÑrû¯~±9Š^GùLÁZû{ˆ`]ªÆZÝzéÙê´ ˜Á7$ èJI˜q;oËT¿º»vœù;LkœÏ´$n5T²µJ—+5ƒÈÂagšÖl8"5ÝžAø¸ÌAÊ!ÚpeØ:BbÔ€2{ÝX΄7þ'ÎûÌNÙÈ0»>>X»\Ptbyr‚î~úcˆâ³9T> w[LŠ}Åf/Û¢K‘˨6>DwŒ— Øf—ÐU™ÃÆ€°òëëØ´3¤œƒãe¨¹²„= Âi\í0\¹Òì›Ò<౫«Ý5ÓR}gv 'Á C€"|–¼ŽŒ„ú1âD£¶Ž^&p¡/Á‘ÊN¸ä°¦r0,ÑùãXÀ¶^æÁVÇw*ë7½É¥íC@ó8¹Ðí+|m,ÔA3¥sÂ&ܳۯ$Y­ñù£ñ£³l9ÞbÑ(P¶h!]ë›oIm̈(©¦Qà‚Å¢M Õø¡û}DüµHîÒíXÇ W[öpq‡uÌLç!ÜŸºÉô°åóÕ3Ý›¥dµ@Dí¦+M•ÀÕî8Yowºc)•K7£d1µ2h Z ëÑ«3GP2‘!.†ôåtÓ—…Ö.xVCF%£_a­YfÕΰ$ì~ô¨ÏáNdìl0ÁDìcž †_N†&J(.ÄIÚö3Ÿøí»õ§[Të– XðîK½HŽóWŽniÝס+‡±Jn­ÀƒçC8ÃÕ'«!6x›3òß;ìÌôu5#ÕTÓj+Ä¡b‚‹h–hp7³·À;yÇq—HñÛ½³¾¦<…,¼i3¬´ª+Yqšx\&å±”0ÁHƒìL´6L‹SŒ§Y)I\¤Ÿ¶c`“4Ÿ#È}“y4¸ð#W] Â*¢d¬Ä]Îc6’m‹·Ž:ùÕqòfÄ_FF•àµñ{àÙ: q…˜oª ³[> f ²YïAþJÇÕw“;®×;Áà» z=v“ÈÓrÜlê±3ñÁÚ¼f8Φs¼xN–\.Á7­Ã%Éö}sfaDBÚˆŸ½Dߦãv¹,«Ñå¤au*šÛ@_(+ê,õÿì(Û/ãbì;ßDïm”±¨¥46ý‹§NÜ>?µþà—ÇŽp ®ÆjºAq6yÇ~ˆÜ„µóå8TN(Ïò ¨®ZŸÆð(ï©—Á#ÅA¿auLªcåÚÖdWjH(’œ,Cäd7Øç@UÙýwN샟w ƒIÏåò¤`¤‹iÁÍ£D–q•$!|]ƒ‚­Eé®Ê›ò²E L,êʤšÊÓ¯½4WK áô²AÌΓ(!Ƕ³ôâV Ž75wZ·(“Iî.’шŒžP;áB…3¡›ÜOyC9àâ”­´¢Ô »Nqgu92 ‘ ¡$àm3{¸ìY ~ÆAåÉð»xb®Bš*S{Ú#Õ¦3“-üáCÇ78@€WžŠª‰œu¤rºpO£³mƒ}aÂTÍP}¨²{Ò†Ywu„“‹?`@ö –~\GÿÇ7“0!1ذ \ônÈôÀñbošpÙ΃ÐDS´Y?Ò×݉¸tà탵†|®øMêEQ!µÓ̤ ¹Ëzˆ€m§çI7L¨êÿKàÎÄŽšðEÝöI ¦½}²¾Šói endstream endobj 2982 0 obj << /Length1 1630 /Length2 8314 /Length3 0 /Length 9150 /Filter /FlateDecode >> stream xÚ­TeXœ]’ÅànMp‚Cp'8ÁAh HwãîîÜÝÝ‚ ·à¾$ßÎÌ>ßίÝùÑý¼·NÕ)9u/µª«„¹½)PÆÞÊÊÉÆ!P}0u‚¼µ·SbUZ:©˜Ú‚ÏÀk4::)0Ð ²·{c t€æ€7@3€S@@ eïàYZAŒZê:L¯^±üËòÛ`êöä9²´Ð?8mí>í Ïÿç@ µ,@¶@€”Šªž¼²,€QVY ´‚MlªNÏ­˜”@f@; `aØþu˜ÙÛ™ƒ~·a{æ’€L è9 èjtø ±€à äù‚,Á&vÐç@í ;3['óß<Û-ìÿä¶öøðŒ=“©ÚC 30È xΪúFæ¯:¡V&Ðß¹! g`oñìinoæô»¥?Ø3Í3 5ÙAP +ôw.S Àq°5q{ÎýLæý)à ²³üW,0ÐÒln „@žiž¹Oç_}þG÷&¶n¢íÿxý³´µ`CãäzÎi}Îm ²Ccÿ½,òvöNŽ¿ìæNÿÀœà?bü½3LÏE˜˜ÛÛÙºÌhìÊöÐç”Æÿ›Êlÿ9‘ÿÿGþÈûÿ÷ïýKüÿ½Ï§–q²µU6ùð¼=2€çWÆ øýÎØš€¿ßG'àÿ 3ù²uû7wÔþUìóý–‡š<EÂÎòYVN.6Ž¿Ì ˆ Èh® ‚šY,LlŸgöÇ®egÛ‚ì€ÏÚþësÇß0M+™Ýo^ÿíÌÿ^þ³\ŠgבWTÖÕ}õï^Ø?žªÏ›Õtsþ;Î[{ó~óHJÚ»>?'§×¿Éø‡†ó_ç·&P0È`ÀÁÆÁÁ xþÿÇï_'ÿÑHÛ™Ù›ÿÞ ¨‰ùó²ýÓð6sƒŸ5þsÿŸ›þÇùÏÚ®@3´…9{3¡@ëä´hQVßȃ®Nø¾ ‡‚jÍ/9¾eöí>É¡kÅïï˃ØjÆÝf÷6˜·:mÚGÙä^4L98+ôÍ|¯¶üÙ 0Söu"<Žg”Vôy9´·ÖGÔÔòï‘(Æš¹Á(ÇWL¾4Î9¾ø´—/¼Í’ª¢ Z°k`p+r÷öéãv®.zûûzÛO;7É^eF£Ò ™y'ìQÇCÝރϫÍoù\Ö…Ô°KàÙöã"¼ TÇz½µ}¡þ|9uÖÄt)“j>™=Ð",B®Á¼l_ª9™Z¦±®ŽÓÑ—]×–õ|T' y©Ž‘h„Q…õT2dЉq˜Lô^xÚP‰ñ hê–n‹a†­’O$öd(ÆB±Åžýf§XbÉêsí"Eœ£Çè‰ A¡û*õ.ÞuÔ_~5”µÈgÈæ)­ çƒ;¸·k­D3jΜV–/_´Sý#ÆîL[Ëz·L¼Yï4SÝ£(û–Ä-åg¸²õ¿nŒU O\r‘ÃÖÂß®wt÷ý™¯˜R…Qá·™"Ÿiô¹ò×ÿNy„Pß#V ·R(xi=]•PN¥™€ÀØ®/Sëh”îÖ[oédÐ#¡¢gÓ¬Kzy¯ÞAn=ó«u¦´Ã.< “¾…䣆!¿&[jS½Å7ÇI¿‡Í&Ò”¬¿Á×;…œ_3h¡«­øVãNž* fÀ÷˜}ïsñlõšŽ©¾Æc;~Ú—¨våVÏm«´úBŒŠÛp×-£„90à–èþù_›¾ ó €Ù\Rò8ÓßÁú¡XqŒ*É4ë•÷™3Z— i‹1†ˆYQ Jß$GT[ôuSp¿òS7!š1ËŽ¼òUX\ÃŽÌF1ݶC˽A@~¹É ðüB6 ºnHÀoï Ú½ÞB;ñút ­Hm9®µìZ2.!åÊ-f=NWRÛ=Œh$[ž¢À&0Èe#Ÿ¬ÙRß?<š••h+Bÿš¿vЧ‰Iæ&µ(8ª¨œOÁÏYÉ-µª®0ÆÚ\¸32xrüÝ€ ØQiᨭâfƒŒöJHVa¯çš—qóÓüµ@x‘D{ÕñQ²çRˆeiŸaA²êÌHsªÅŠÇTþAsv’Ö€†ã½À@Ôÿ …îÑ'GÐêƒQÛqÀ\bÇ-CAÖýe·¾èHu„ƒJåK*qºýuÔuS¡-kâ‚ F‹_×`Ä&G&kâ5…ƒ¬æ| ÕvMßôZœËü(ØÊ’µUä{Ü,—C–»a§ïû‡Çœ_ˆÔw7„úZ|ÄdŸNó>õ-f`ŠèoVÕvìuÝ„—ñµUʱ³æ¯–]pih¦Ì’Â…½&™¡±ïŒ9æóys­F)_$À*¥OžÜæèÆ‚ ”;\·•W‡“ª…SXýî9ù©BaîÝ[4yñ<뮼ñ­ÞƒRÂìnu‰‹:žÔÒ41ª‰´hóaSô‡¡ÃÝðiÒ©ê ôÚ~]¿^Yp:¶ªq0"wºÖžï ¿Ï ;˜þ¦”{IwvfÕ&Çð<¼½Œ½ÿ‘GETsÀ çDV8?E3ª“â2Ç1^W›“Kfá‰-"Y;ý.rÍÔ³@3ºÉôÌ„˜Kñû’ѧ »¼Ý[çŠ0?à‡)}××+vÜz…=‹éÚŸ·.Š 4Ã2+ÖâÔÌE!vïÑצÊ o¼P¸ü‚‰·‡ýë'ô·:{©ÞßGžxíx—P:j!ßvæh¼ð³×ð¸#rCss¿0Š¥oÑL:rÎv¡Wèé»)ŽõñB‚„ÄŸX%Kãx•S•ÒHðQÎx}ôÊ ZCÇQB¹áÓ•I¼èQ?î'Y“¤3tCX´¸‚ãøøud}雽 åct+}R¾ZNwò–õRP™¨ œ òÂ…­‡ïA1þm8ƱzO„lT鯭HáÊ!š\NÖ‹È‹â p„×wA£, ý뼂’£hµÚù¯‰s¾ÓÎÂÔûvB£PæúO !Jój޼Ò.Ðó³o’0j§aäâÈ0«¯éVŒá½,fT.D4§J–Æ8:a!²+©.hS9Dò?¢Çu¿5/(ÞÇÉå#”’OšKã2 s6s{)gðO‹Êü¸Êz5ÈêGÞ·X>à+Ù¦[%+È-ú^Œ÷2ìø8t™œC-©T®(«Œ1™©¨»6ƒ Õtÿ|‘w»S°7¬j5÷p&±3â#tOˆ™i2¾Ós%5!«ÆHˆY®™t^gØnéM™âµ×+–2î˜O’}ßÚ$”º-¶O¬#8´Q­yZ.·?ªŽeÚŽÎЈöÏ6¬–ÖrO|¸vÞ„óùÖ^Uû‡à*RœHUÜ×q’7V& z-h¨·pí‡,CdèUI¡‹Q3ñ[vñ)¥¬¹4Á?¿*ɉãÅ&‡€©¯Ñhíø ˜ËÛm²ke>@iÌÎÂVÝø 37½ËÓâ_eSOMïAšjÅ^÷¹v7RÜ|™Ëï®h!»¢B‹é+gÜæŸèÕ9ˆKÚÝËÿ¸ß™+=z-\2õÍø=nõižØ^¼ôå:ãQ½]Õ‚z‚v%KMèòLßL¯–¼wJÂ|oý„áe4W^ {J¢¨zqÚa€Ë×?±vnkZž¤ˆôrƒ˜µÍ•IèÄìn¶®}ɘÆ4Ätápe d0’¦ÿ`Ï©öix£ìq"A=p±"(äjarÖul1|£.ÕšÝ}e?r"µtÍ?·G&}:b¬Xbgc‹t²š3ö¸O,T+}kNVÏU ó™’ŽÖÔ±ôÞ“ßÝ\áþ݈Òv4CË¿%ÿibð6Ülâ' Çé"Ye²È(©¨â[vNô¨¢§óZï1 …‡ñ|øÓÃËs~1—Ä„Á"ÐwݶÁü»Þv¾´&Z’’Hõ´³_OcÜÔl>Îtê Kž#윬iqùü,·H¶>d¯aˆ\îZ#TЭ«‡%ç8c>Ý‘¼aH'›ÏâáxàV6'y‘\ñ(È~Hâiž=Є¦x­å©²üåó—£Þê¡Á”í;U-=vh#ÕüUdÓMÂé7û¨NƾÃ@n«/4œžÖÓ‡'%­ë4§{eïi™”ú4‘¯R„i\ªøf] ,·wÛ~¨CÕú]4gò¯‡‰å‹+¶ì6´›ŽßÃÞ ‘s¥™_l4³»Öƪ!•u'5¤ky:çúìjs¥Õ¦Æ¸Œ7Ëøã“D7¯.‡S™¡_È+Yq^DV®âJA˜ë—û~c ½DÙUÚ+ØP•ˆ”Oøf©¥ãQå1Rê5ïÚ@ö¨âZRØ ˆßɤ$å ¸Ìi…zÞàÛ”¯#TG0É¥>£Ìû§  —?q( ÆáææÊd¾BÂQ¥Û/SÍî׿8‹ZCa$%KgÛ‹ 8c !¡ÆŸÛ}lº-\¦6–nß{' 2¥§û%/¸`Dúêi¢ƒ‰>êè yøé[P'ê>טš©ž9EäW“s‚/áX.ç9œW¶'¨÷ظgbç^X ¼F´þ°KßG2îÀ·Ÿ¯ªÃŽ ׋çû¥ µ2:j*^Þb|ã˜ÎëNéÿÞÐ’2™{Hœ~ÿ"3õƒ›ºØ fìõå«¥šý*á62ªÑžçÜ.ÇZ ¹;“óI[Òü´LãM“×Ôõ˜m!\uK|5FpÔáSZÜ្p] ®'ÇëÒjå^ÀFJq¿o½;íJ(üæVf»céc÷KÖJNXºÐO…$˜BÊÞ(Çcâ©ÖT÷^þŒÎ_ªð}IÈËPÞSGoÝ9˜¹@èáî› ;—šˆQ)µ ºì(ÿÉÀjEJbáÝ > uÞ&U™«+šx¼^{"ïZZLº>.°šÖTÿÛpñ]#|ÅZ™b³|ï–ú¬{À›~€L„ÊdHì°JæÑ>–”Už›)GZê¦)¹Ž&N@~y¾©ðƒt"·’•’”·BuAòNª{`áý̸“‰âö'Çýq„ͽ¤é›\ßn·Ú™ÍHˆŽÐj¾NöJ&ªåWÀáÏÕ@a#mÙ:5®X³X4±h´Ô\³(ðºðñ)áú¿6” PJ<Ž$¿ÛÄž*ÆN &x ¨©*“Q<¸.™ Š«¨¹»’x#Ÿ…u?™Fî„.йxD#ð.[÷Ñ3íf«)„ÂË@%2=œü儨º;Œ“ã™Vî"eûé9Ö„Pzí—SŸ½:”@¡q8¤ó"ÚѸFkä{’"VÏŽ¥xaWn³Š…"Š[­·“„†TþŽ0ï°DÐ(>iÖPá4ÞwE¿oKÈó™ò þIøº¯ÕlTÁ ß„æàöž=ýJˇ\ŸØE…/—d2t¿X¥¹õa7S2KF•«?±º¶ét‹Zó%Yrâ£2ý‚×qÍKAÓ*ß ‹L>­>}ˆ: GDW©Î17Ì' e8w›‡mntØêMÅb¡°)å5F-ì5#îvÑg¨©?"i^DCz£Úëm³08¨ÆÀZßÙû+ZkËšySªÁY*_¦{‰û—¹ukô#]ܘçgßDÈ´ÚýœìTib¸hÉ(ª2Î&§âÛËt ÖnÒ„Ƶ2“6LÖ“òéÓÕiŽEßqWm MtŒÌ¥›€!w+X&ýYGô†Íúˆ¾æx¶$OC—¦)˜JB5±ÚŒþp O&Þ‹¯«´SgKý“ÙMÉ’XáÔl ¤ îêÍÝÝBVí#.O]~tÙW_±15Ï^Ñh)­L;]nf’‰v d Q¿2¤îÇD»Ü\¬|#t!÷ôžÇ)S!l"¾pƒñ*²êói,û6#ºÒãu"¤—^SçÃPÉÌÛ{+&ÇÕTÞ5OœáëÝœ¸§À‰ãŽýP¹´5ÚÈØÖqº|ä·y©šnsW8œIîeãµ<9Ù:nzT¶/IpÖ{ f¿Mxc­¶özÖXeu<…k8›aœçi)kÀpCöD™ì)M_NTB™AÉJ$;R_:‡•$­Õ@c¿6+’L¾œ×О.¤¡MM ¸÷]jÁäfh~Í-ǼÏú¶ÒƒLáÃ%öÞÿ-ÞU¢z%É‘ÀC¤3UéºÛ©ˆÒ>Ü'Ù±ù’A+[ R’S<:è¢)í’ÁhW±/6±>%–Icç%ïG²*˜(§>±«×2WóŠÖ*íå`éo0 ¤4’,Ë ‚a’E¯ËšH:B¥1ñ;¶î¥Û–ybØBª€N)‘KÂì§B¤/·÷“ä®Dw¬ãüˆÏ!mDWמlRLŒû¢Á…’ÃxÈd? U/†68ÆÄàµ|qš5Å%…%w•uzYMK¿I—ÍQöŠ•›©ZùÙjÇÒËÝóu÷î/Ò?ÚðÉf¤­ßËKa/É·ð¨b ´yBdª]U!‡m{lÈј;UÒ„A絛‰NVfÚ“ÍÂÃG—Õò-Q×¼z·Õ>7sSd#‚¬ÝMé’S‹ð&ÉÀ=^ןàr*kæåÀ4åEIä^nIõ-Ùþ ö†‡ý Â'ç–Ý$”Ÿe9—GäÛ×ò,ñàâØL }?F*ý JšÂƒ°çÛîTì|OÃ3¯ý³!}b »<ÍÀSŸ•·`Sã¼Ó_yMDd—›P•6Ÿ·­ˆéLz—#x5uöQKëc£y,iåûë€ã‰zx9–ƒÀHØ©Þ îǦ¥Ü]÷/½å±“ÒÊ4ìƒLx&PxÈB‚Ÿ¼rêÓ}aS´R'âÒFd~P÷¦²Ê¼é?ð5¢*ÁµÔùŽ·ÔV$Å3ž´’è'pš€”¢#Ë¿”q)ܵ;V×)Î;ùu‘»“„X{ï;Údz]ë•©JÁ°8ÉÊÄuB¸¼&Ò(^å¨<¬Ó2ý²é ‡°Š|ìó‘ÕEóëA4,²µº Ò%êǵŸtdî5ÝyUØ»]ø¶…a#_Ô]ú:Aw‘¿²ì’.O'¢M¤¿nDpÿʳé6ϲ<鬒-Ô&……-®Ž^øiyYÆÈš;ÓÿáÇu÷›Ã©Å.Í¡‘QYª03o9· cDB /!“ãÒ“¥=V¢w)Cßü¬"ŒÐ¿‚drˆÂޏ×JìÊÌ”«Î#¹p/ªȲ+šÜ»Y¢«àÈ•è^;p}3Ð#<3š‹3RÁ2;·P¼$¥;ãôôV*¡Òùm&Kú\¶ KŒdËñ›dJàÌŒw$Qkýü0!fÜ„º¨&`ò•³(ŒxJSx¸–—|ï#¢µà²9b07ؘ Y¥€þãV¬SGf¾NƒDCЍ;ê4ÅöŠcƒÃñ«œq&šœ¿¶`Ÿï;RçÇÅZ*ÆjÍ +¿³«§}«e à;Í_ HƒŒ®‚Û?XúO„–ÅíÔ_Éó³À»D[>t/)¶£$ )ƤÔO„¬¢'¶ð[cvÕévé"õ¹˜½Ë[=ë£!Ð[š¼sýIÜùýñq–e1žºX ³þüÚÿ‹P„wÁ¬=Ør€…šbôŽ{êû-?k~ò²mÉá¶)¯QnzŠáF\Ãe‹õGáÖ§]”Eáá½ø4'Æ3².·6ôQzBCÿ._(ƒŠ78ÐŽzäöǦk´«Ý„HûeMK QeÚmCÕŽìíAÛ‹™ÁÛB¤œ‰¦wÄVp” Ëå_U>g”ñ-áz}§=l [XS:^~³#:kZÑ•Î7ŠØƒÎý9CwZ‘é$·°)û!ŒNR¢;‡·Ñdq‰£M Yª”,Ûi;¢CÓàÞ, ’†)þèÀg¸òm½°=EïäºZ/¾Q){•ìñ7KÓ| ‡ÍpW"µŸV6ð» 6Ö£ñ¤5Ÿ¸Vã @ôfa|å­´>¦»ßRë ñö˜ùTÛK 1_½Jlõ•*?n³®ÏϺ`¡ê¼è¡”­¬q}dìO1pj”ß9 Ÿ˜Û» Úi³b5ñþ]¯Fèš[Áôe¬ÚjBL_¥Ùiæàº  Ù ¨c„1n1‰F/S´«á&EÃÉ•!ÆøeÕYÂ÷< M®¯ôó’AUÈn¹,HQÖnß -Öv „|nã­Kí¦ÑŒ";dôŽnÞþÊIøµÜJ@‰‚øe+\®#Z–ÔBéòΧ:¨ùk$zOðRrZÄ_!;§öî½Àvœ±fW‰#2<—"¼}sR ‘k|âÉ›4Zpy¡ïÊGâ"s5dq²Ã—E;BžA¤**‡«ÃeÏK”sŸÊKý‚ÖÆký3[·iŸ¥æ‘ÚŽŒrcáG…úýHÄk.¦uý›+’Pks 2«óapÛ(k%ûöø[1‰  ÇÊ<tHMâÚî–$~ƒêQÅqüTâœÙí*|W²’à|YLZÈøJ!¼‹%ƒ­„§—hGwêI[-<'¼{]ÙUn:qT,4±ëFŠ¢57?Åõ ÍFùô œ¾DµÐ¶EùeûõõA÷íÓ>™k?J­ž JŽ{°~W^^@ã‹wp¹MØ^­^ìVQ©RWGÂ_q;jOŽ D»¸%,;ÄÇÄ™–£ ƒúgøù7ÐÌ$ŽÈ0ÈOfiXf¬y—leØÊI–r®:T¸9®þk3¨wd =£åbÜÒ³_úuB†F|Q†`ñøÂR±y ^ÓúïÓÜN‡ÎÃŒTªK68i]dðg/:ƒu$„¿|54nËoÜ of`ˆÊÔ2Å"öŽÃƒ íø>k™°=‹kÜD.ž/äkltvŽir3hñx7ŽçÙˤ[âp=†@NØ’¢ß`—{hbü–´‚EqrðÓ;U?„‚ Ù¿˜¯ê÷ §ªØ ªoćÁç*«7–~/gŒ²K>#ãײš•Ky³hBg))÷þW‹¹©m%9…͉À•—ÝdzìÅ“ƒI.X¤è-‘HÏU½üƒÅˆ 0<ìb™ÑÅtˆššŠý½€ƒHvžý¶®Áˆõéuö”Ýýc񯮠toM[[?lq¯ͧøÃ–¥’4s%ö¯q ÷wEµ»úHND\–³€“¿Öínä^ûŒ)ÇŠ^™–Ñ÷¨;ðúÐË^¢ë}݃¸¶=ª$”BIˆþ™Qûîmc×-ZÒӦΡÿÇô¥™Ü['-8—Z§} {á’:ˆs¨ŠÝ6êtú^—­áÙ²sq"¾Ñ\Ÿ7?,:ælõˆoŸfèò«ÙøÅ&å R†‹¬õ]|!ãGßc¾{7Ý‚[œ0‰ñ¸DEEüg²YÞéø™^É_Ú —í^»–ñò”¬p+Y¤L¹J$ùâ€õ^Ä» ý˜ià.%`«ÀE‚¤’ÛÍÊDÄRöZŸnQ`ë6ä{”4Ê÷tÎþj1+̶5V‰YÌÊ ú%;ס`ڇ±[sÆÙœà¯ï|¿=Ðu£1q²ILG;¨ïæçآȈ|Bö(>!L¬Jf&?-|:ªíÕž’†€E­)†ߦâÚÓú\Õ<\爄ËÞÉ­ÈâÄ+ÂZIk9öY¶ª×êp "!?t^5Ègꃻƒu‡ÖÌÈke¬2†JˆPˆs^ÞÛÌM‰°nWFøÄf^°ÀƦŽxS}fxæþz?ås@->=??Êa¯Aà—"ZÑöÛYŠ›Ç˜ÎéòrÄîmoÍõ*± šÇ3Z€55«â¶´œê“÷ÑSp=n).SÄ„Eâñ’Ej¨-óà¥KÜ䢿'ÃlRŽD޵¡*ï¨sFa R£XÐ’=,w± @†ŠôžDLÔ—ëûöYEÎ5üî ϹÆ¿N aEAn~ê¹qÎ"~Ñ®)Dº‹xèOpÎNìXÝPÝñ½Ÿ7ô£¦\Ôña—” °á*:ÑcF9Û”ÚÜ åaQbˆ+£Y6ƒºM¦ž‚›=¯».Þ¿o€f/¤ü ´]”—óŠçè´t|mh~|jÊêVñ¦¸³ŠFÂã¥Ú˜Gy¡{4ª²Ç§óä0‰'ÔÖ¦ºˆY¯à°ù÷í’Œ¢ÔŽÒôÆØXEÚ˜¸Z‡ú{µ³·d¤ü=+BG)-Õþo5v[j*L|É7LæXÜç'âýØMŸ¦êŠ¥b(£Û­mŽbBW2M‘Ìftç¯'œðœüÖŽïq§&½ŽÃÆÂ?HQæ²fßVµQ\Ö„as/)¦2‚ÇJj¯ÒÒ†úè»+÷•g_s/º-~ÔP™cG±½‹†‘øªFáå*㇔%ûF5áËïÊÁ{È…Y̧6þþ|nš íþ6DôPr‡;Iž;çÊý<å .û‘†¤CR°Y¦%öMdFü,Û¿F]Yñ"ÉôÃFûáƒOŒçÅãkí^Ë\Ζ¡²j·™[âžµa7~LOu‡›‰,ûU³ÿË‘f=Џj&¾ÜÃ?ÊWl™ž8sƒÁèßæ+ñé:3–fTL™¸Œî3zYËnÎëeô>S0°œÆ+.*þA2Ͷ…FÙÊs#TG¡%õ¡ä¤ž„µõ(ÄQ{ïè ídE¶©A1?·³Ï(Jnù›½³ R@®¸s‰LÎn}²~tØÉ]êÒ`ÛV1S0ÒV`w„³'Èëhò¤Ô—¾«qMô1qÊB×Su >¿Ì“RpߥQ(ߟýÒ%Û¸„Þ˺îíXgFVž…ÚÎL »…R²¼ŒËé,ÑCWj[G'è¨)å-ãÚù’\gY¼›É7穊”+Zt»ØŸÌ>ƒ%åÚi`EËýÙ—‹ÆÝCBw\¶úÚ÷é¯nßEec‚™–K~ôðŸ‡ÕG¦.7L|œ1g£×Þ?À 1.ÌNØq†Lùoj'=Ô¬ ¬ÐIð6¦r¶åa½0¸Ç3_ˆÕô••;^sÊMTj¼›hxÇèûôpŒ\Ã@×oàž½IËàÛÂ!"YSÉÍ o¬Å¬'X£á¸¸½€&‰ü¾†ÖÞÛ„—1z!á²7Ü&Â@.ÂÖÜßm¯€¸&IòǤÁ°œ‰Éh´ÃE2ômH«°Õ­º²8ÌÌéÇ!>I½r¬û)üÝü0¼6²ÃveùÖà‡£êdÞK»Js¹ëáÑ•SQ?é[)ì' zª÷- ƒ -⎼Ò4«»Dô¸ï¸Ú”hï½›¢ óå%ãÕ¬]¨b–S½³cœ£!®éY°ˆûRñôŠ6/™ü}7ßiÓ)Éú}·hÇé¹Ó‚Ñ‘ÚÉ ¶ÌÜqØKW܈)M‚š>ÚµXKh÷i^œžè¸ƒJÛ{*jâËŠËÿq~ endstream endobj 2984 0 obj << /Length1 1608 /Length2 11875 /Length3 0 /Length 12708 /Filter /FlateDecode >> stream xÚ­weT]Û’5Npwî.Á]‚»»œs€ƒkÐàÜ%¸»KÜ îîN‚|Üûºûõx_ÿê~?ö{UÕš5«f­5ö¦&WQg³›¥Á fv6~€’ƒ™+DݤÀ,¶·¼¹‘©©%œ¦.6`¤©   ´HÍv>>>dj€ØÑÓÙÆÊÚ@§©¦MÏÈÈôOË_!3Ïÿô¼í„ØX4o/n@{°£äòñ¿Þ¨\¬K{ @BYEWVI@'£¤ ‚€Î¦öW3{s€‚9Ò,ÁÎû,æ`…Í_¥AXÞ°Ä SÄhnó¶ èatüËÅp:;Ø@ oïÀÊÙäòÖ0Àdnïjñ7»%øoBŽÎà·‡7ߘ â1w¶qt¼eU‘”þOkS—¿rClÞܰå[¤ØÜõ¯’þö½Á¼y]Lm@€ ÐÃå¯\f@€… ÄÑÞÔó-÷˜£³Íß4\!6 «2`8­L-ìÈÌö_Ýùg€ÿV½©££½çß»ÁGýÐÞ’™ã-§¹Ë[n+2ë_ƒ" ²ØÙþa·puüOŸÐùïÑý53ôo$L-À {O€Ð™U ìò–@÷¿S™åß'ò¿Aâ‹Àÿyÿoâþ«Fÿíÿ_Ïó¿BK»ÚÛ+™:¼ À?.ÀÛ (þºcþ¿XS{Ïÿ!ú_µÿ`ø?Ⱥ˜¾µA dõ& Û?Œ6i …Š‹¹5ÀÒÔþ­GÛ5A@g{ðMË¿Û`fçæþŸ†µ¹详óðýí‚,þ•ù›<ófUWVRQgü×Ûôï(•7Õ]4<߈ýGŠ`‹ÿZü…!.öx3³ä0s²}|;llœ>.>ßÿ!ßß@ìÿ\+šº8Ûxôߊfcÿ»ôÿxþ¹2ü)9Øâ¯9Qw1Y¼Öþr›»:;¿)ú÷i+ù?×9è4Gþ56¶MÍHs©!È•Ôïëa‡q,®×(Ìÿ\îöO Ûà+7yªaiçiõœ;r|Þ‘cØêÁ·§íNžå‘úRÒ÷æc­Ò´dÜ d5*FK;ÖŽò>ŸUX‡ÓãaÓÚÝUU3úö„ð~¼ÓùÝù=ýgJ·üϸTwŽè~æ)u±x˜ PØ5GÇ4‰÷w´ýÃ?º/á{wH³c‘¨L ü¾‘'¹xš8ßÔ›?»3Wñg%†Œ‘›÷ !°3Lâ\0oZò›•Ø'>”ã_kèÓÜ9ÌÔ0 Ø6hrW'*/äúSbÆÚø‘<ý>I¤ÁÊÔ!´š„A¦_0ú^<ÜÂvmÖÊ'(Úùuš‹:;É϶Ÿ#“òà …Ô ÉJS§J…è©ÍÛ ïüÁáE1û‚l¨=)‚ÂŒ!™e leòè6«µ°ˆÊ£¬}-éëXÇÖ±"õÕ¹Lti~?Vñ½ŸK¥£„”GF}pV!uÀP7 6'Z»Š$•1ëæ:M:½)•;m…ÊÎóíø”ç·< §ä󣯄ü‘‹GîpóOäC2¥q”š™ ¸Ï_Ò®}>߬ˆâ¿â(9ž£µ&¥‹‘á$.‰pɯ88`$õn>9ÍuàÚ"æÚ†™%Y8»*„á· e=ÿiZ²ã]d_ÖEÂ|©ó¶¦Œ¨¹îkóYÛ¾E˜4V‹ WàÛ+ô;Xî”qá(sj…—‚µ‹êÌ>ý4(œyH®)°)…ÓG^¡nº‡:D Ä có¸{e-̵p8ŽjS¨™âYBÔ)ïjÃ’ýE*Î*M,ž=.Ú< GÀmõ+çwRÜcùwL2JÝ®»+¼:_8"”Žx ™ʸ:š¿ŠýxÚÌG:ÒÃùâ¾´˜$!´ëõƒýƒÐŒÑç„ߎó¸]K•Aâ¯_ÄCg ‘6!™.b/!áùÇBûÀ²‡w#Î÷±?=¶ªvÁOW옕‡¥m%ä ~X­Iý2âÿѵÄ5:)ÁÛ/žD0Þ±{.|§túó‹Í$Ü´ó)…h3Ç'b‡b©¨i [ÕX/bÌöŸjûiךöŸÌ¨âÇÞ˜(¤:|d?r~úŒø’‡5´/{ fóÌ;Ñ÷z糫k¯áû ¢-+'X^ŸÛôg˜Æ·Å“’ Šj$%—¹U·€”W{®Ét#{:g*LðÅœ™Ðhé%ÿ:w.$Oª­l3êðG-Gá(ðÔ=NÖa*IÔaóñ,ßÏo8Zâ[9ó³Ø¿P°ÿ)Ú|±ùÊÀŠÜ«*õc⫤ѷÞ]ü|¾ùsòä“ÍŸ±#¾øI®kRÊ¥CŒÉàr€úÁªMþÑ%à[»E§¦hzCÓ·Cf6#Ñy´(¤›_±‡§Ë\à×$R¬ðª¦› f@€Ü|ûv?üÔ€r&AܪË<·Â·Ž”HàhÓAÇsìr͑ٶ,¦Eš1"‡æÂw)XØÛ|;þß_“Y’xŸ0)s†º”Ûõ]–ŒÑz>j¥^Ù­oíNT.ìYKX”Œ;i+3[©ñíÀÝkPúŽhÉÖ 9éê¿_Ìmb¶ë‘|A™>J•Š­#ŒŒ¨­¶à=´îNÌôÉ^¦3øbS‡0¡³˜¿/‡‡¼qqÁ†Ö[ßqy=ß,0ë¸×'ÄÎN^86q:¤|ö£6\I=8%Íò&ù¥härÙŸGª|¸èðîBË"6R'°ˆ/§º2^ 1OBÞ)¸!\V¢Œ‰C÷ÑžÖ¯“>_·Ôü°ÍÅ„.û§+BÑg*^sliO;›n¥l(Fõ}îí‡ÚY ½͇æóGÚ¢ý}bG’'iÕÿ2ð‡Pd@Þ{W©ÂØY”’ W¯.ž®ßy½2¨ïëf&Ú_W Ó¶ì•X?âm¨âdOl1 ·HÛÄ(±&ôàÒUĩʲ•Š£Ê¶GWpOÛ¡fF·&tþ2^AÖ¿ÚŸl;ïÝîz{ÛGÅozú¶Æ† J.ÇÛo«w(-çôçÍpÚh …ŸÜ¨³©C‘¹e§à µ—ƒÇôp?#·¸ˆ,*_XŒ\· œ!覿¬1jˆÚ¾“—Õõ'½]Ñ´†xÐ é)ÓîJ7s†`é5-3àl¶5ZS•'PÂÑ•"Ü“gšëCtðnµôq~éãdrœÁÈ´) ÎQRk{ÚƒçeÉWöÃûN&tx”‚˜úºîù¡©±Ýr´×Ï ‚ßqá5YÓÖß=î© Û|,ë–`>ß; °±ÞÒ‹×…%ÿVãð’˜T<`ò®Jª.5+N“šý”¹4èð²ÜV«/ƒ7ŠG=íO,ˆÞ‘™ý3NO%÷¦öv‘žÐÔç>Tø ¦§ò‘f»‹4±Ñ‰)iéRÀ˜…a*XOtàÁ€LPÿ ›V\ùvW㸀QsM¿Jâ“È#þ¶væÌû¡ž²3ŒM‘!œ_n{» 1%Ue)´3œÆ¡–Œ3„4첡ùþñ™cZJPD°gè8åÝ©¸cœ¨c~9kâ[„¥ŸäµôP{?{-¡ï?âÿ(ˆ¶XÚô/Û>øD±7 pMþ©Jèµ3I–D\‘ö‰È±|·Â3§¬ß^.uBÁ²ž²î,ñA½œŒGÝÞ6ƒ¹Î÷´$…Ž»Í‚Ej®Øc.S[µE&»š6ù¶¤ Þ>†?h÷;.ǯ»ùš5¯*m…žŠ# Âý!9¸²ëEtÑOw0V+¬ø>òÌg¡f :JõR”öz¥˜?¦C‚š+ÂOÔô0‹ÞcÓ4ß—åöËIµ_Gº" örqV¶'‰ßtƒy¦ÖüðvR%Slã]œ&†ŒÔN®%üÚåÁ1ôŒ¾õ¥GsP­Ü""<>ç«îM^šÙZ¯ìd4á½[É=Ä< œí·òÁfÊ”N&êCIkN· ¡"÷¥©?éi°?ÎrÔ‰³J*ëb„ðÂí}MÎ 7ÎHÏ‹wÊøÕy*Y‰ƒ ñÛYv£T¦à„±h)¨ê­sX|ráßcV)Já¶$F§ô{$Y Iu„ÖÞ9l>SÕ|æÚG–¼ü~Fpµ?¸ù¾ˆÊƒÔË5ï.kW¯RŽ-›ö)â°vœÔWíQyHA÷Ú ¸mŒáLœ%d 0^²ˆ÷®—×O+š ã£`ß´„4ò%Ñzh«ôÖê ˜wYî¨P«bB„þ+äðÇì‚oÚYÁ qØyᲑŤ]çþÖÁ‹‚¹,7蚸¯OT!ûŸ˜–åácLî§î9Ò%#/YþñËõõ?"eâçR“nˆ–öXP‰ßbMn#j'˯Šÿ8&ÁïÚ+GçÈ¥Dv}lY˜ðóV¥P“š „mSâqÅ*ÏIz« ‰¢_‘ŠújÙ••ßIb …9 ö3Â!‡ ô6i­}=× ‘9ô†¢Ðt$c¬Ü Ò¶ŠZZfî‰îõîBÏ#øQór±BAÕP¶Ša$p ¥9Zˆú±N•IrÙâlãXÿé]0ž–ÈcGOCzåvôb™,=œ‘Ò€®‰Ö—\׋ÌzRøôeXÕÇ%›áÓ½ò!°ø¬®€`¢Üôκ 㚥Ŷ¹.ièc¥s7¢9£jâ! $>|`AE o½cžîcQK„-àõÞZ‡ÔÛ6pÖ¨”Úê*Ò. bx¿Yt[J¶¾۾ëÇÁ`F­–mÈÒsóš´j®ÈùZ+^ÍÞÍó¹[¶ÿGÃ%ÛÊ\yÈ‹RÇ=tðÍ_ÃÛëÈÍ—|­ Í›¨ßx9Ë©ô‡FáÙ»jP" x'eúÒ/ºZoŸ `k©5†Iœ`.|Îp,/}Û%15žóðìë-K¢…‰à¾X‹¢=Õ´&\s~ï<ãÉÅàÿéÂWŠ5R¼ìåĆvï„ ÌÆ c±ÔûÌ/FµE# E®6Ê>¦nùœjÖR»[3ŸíNÅç׸6hUë÷Ex… 9ìI¾g\ûÐZ1?´ÝˆÍS)³Ê§hËýÝC¼?a6%]PŽ™‚™z ™®__´oR›àÉ£Dð]“Ym_áÅ¥#öæd.úøgÞè7–öXà[_U…NS³\GÔæ“‘å>IgÙ¿siœ§l%D->©xÎ}éÉBIßžºXx%³{1J I|ù²VsgNIͼ–ÛjÙT×§§V&<éWNÌS78Tê‚vbzø5¿% ýö’K¢CŽ2†%•g>\ ݸ2‘¸²°°g’á ?úi…v²f¸á×èl™Ýîšh§hvµùVÜ‹]~©<ÙüƒØn¬:ª·;G’e¼Q—0÷òý¡f‹Üc¯õÜZC¬¹„,ÒL·OMÞ¡ÿñŒ›q‡v:çÄkë¯ûdо!­ô{´Vu KU-µ?yè„“½µÎä¶Ù9œŠ¶ýNÔ†cªx݉r[ðn÷æÊ\­…zŠƒt!´Ô½&kÃ×ÚƒŸj·ÉŽg½íÛ@N½w;ò»WJ[8þð·T…¶)ÚG9‰‹* ý^ ½ÜÖ½;(ˆæz>½V—³Ÿrüœ_q{Mõz,îö> n$aÎQ[‰±ž¯›YŒÃÖqz±B(ª"[ëU'È‘m4BæßïÓ‹øvÛ\!}¸ÉŠ· p@ 8;ÈH-›'R«€š~ý”-ùƒ¥ mׯ‘2IqꢬOÍ«‹d^Šáå²JŒ]U±4' &\Ú£îkÍD3ol5Ë´‹Cã’m±½ÌÑOwËþº¶}ÔêÚ+xÿçÚtÛØô{øI<ŠôË Lx¦'Dä;í¯¨‚‹(û½è*zÃÍ;ÐIÖ>ŒœÖ/šþè¹Ö=¡Ê…´DwøwLÈeakç·x¼g qh yÊn¼«v-¸¼7óŸ`aÆs¢N¼€ªºˆ¾°j„Ç^ƒDÛÄ7dyŠ˜åi,Œ‰Åé’ ­z—‚–Ö„ÚÞÙnsÔÆ]¤¡¸+ÉÂÒ7ÂP^}ÌŸ]—¦¡ïþ©ÆM¤ÈåªÚn¸Z«ú•9¸Ÿ9«”¾Ìî»­&¹øT1ëqF¨4³‘ÿú ^r}èëvs˜/¥S õ‰¶;+mßÓi«Ã†`ÓöW…ü ™ZŒ?ÇZ9=•‘ëc¢·(Ÿ#+õíÞB'- {8ÙªúªÕgµöÊ­*0[kðrvÞtý?˜èº‹©F¥A´ ÔŸzTÿÀ•5¢ÀÊß²nKg—h·‹CÝq;0S¥Ñ·)0Ÿ2–¹É‰­4O†Vj³ôÆ1ð qï5âºäжȩ²T¹m«Óó2à·èÁÆa-ªY«”˜¤ý˜ÚØå„cåõ-Ÿ”~šÚ qÍXßF`Uê„?jé&u'Øí#Ô]<ìÃ)UǦ6?jòGâ*‰¨ýÙõ|Vþ„‚j|‘·x¼çQÝ]»ê|±"h;ˆe§q8I{qNÏöR¿Ú û/Z€ÑVŸKõsó„õhåX« À!wRÎûn}ïß £N×3™-(PNê½ÇßÝÎßlÌÔIàô:?—Š® ½9QµJÝ|סKÌ ãJ™ÅÞš¬6lºù޶üxÊEb‹<ò³oyUƒôÔÿü”8®,¡ÅÈÄÄ):©ò \9OfáÃ&‡×¶íô8ü\»ÀtÍ6žÓ„î¾i@‹[·ÒÙÁÛ «õÿ±±üš¹<&]}¶q¡ˆøÔQ!äVe¾½wý Ö2Ä4\èT¤¢”ºz³d€ú.iáàtXÓF×q0¯íÎTJÐL‹ Ã5°M.ľ"ršL½Ú?Õ:U)ÖÚ.È€·læ›I–C_¯f–m-]E¾Œ`¢ƒÕgAj =oq« oHø¦ÙÈ,zNÙ824[·džãü5¯tVíõ€@V>,Zá‡D‰?±U•©Õ%)5¨à÷F­¬È‡œÂ®fBgÔÖÏDuÞAwˆžït)Oô°áSçû¹àïÜ)¹\ÞŒá÷‹¼üí”{bûw!QZ*Ä „;÷èÝjW‘ºÂêw‰J‰þý¼ìϘ¬¥6ŽœÎºQ…?“8Ù¨Üò…·§+x/ò›Vz´Ib­€3Eâ¡ç(–`Å–fl*ßÓ&.ÞÖU=çÉÎr£5¦øi€ Gx#ÚˆD!Äß@j‡ïLϼÖ%÷)2ý~4kMa–íÈ*-FŸWÂ@µ°‘‡tߊÈ2u!°ÞÊ‘ø±{Vgø¥ZPZó·y>«VΪ |ÕãLØ=\”bô|@~ò"X{EݾKD¤Ì„å{Š)YpWJÿ˜™Ÿy¯FYšMS´z1‰›ÿkSáæåüýu×érn“¢Ô&#‹/ èRˆðEÚq¹·d»’,ƒNtØcî3“äŽzáæ tý2¡¥k7=rÉRŸQZ¶-Fozaξì„Òh÷¹r®ˆæ’ÎÚ%Â[KD¢èùî·«PZ¨ÞSI왿8BÍýûe´…”ƒ'ßÅ“EÆ+ÊYÒDKj)¾ìOç¼:tvm=ß5ÆÑ{H‚‚µ¡¶ÙŹŸgדw™!â•£‚Wmªä£–Á:fhõ3sVŽD?›‘RyDßù2;¥@™ô9žùLO?lÚ8É.´OH¬˜Ž—»¸åo¼ ÏôÎ"ƒKb®Ñ$¥K¢Ð%Îk?¼° :/Æ?Ð?.Oã}L§LºjäŒmôâ½Èøœ’eŠøËn[ÉoA=”ûˆ5ØO†.ÛFÔ¸è+64ª²…ªÿkás×jj^f[:£•¾l•ÆÃyHøÁ €ˆS©Tøºzò C°Žëe¢@Zh|ÈÎ=¨,Œ;L™ÍJ¡*ÿ¼Ž¨0¸ ÷§‹Ø¥„­Y£¶t~á{¾*)ÚZ#%oÜ̉ÏX’/™ýË¥—ea‡ÙÆjöàúïRÃ/Û3OܬڃèÓ;–aqt˜ˆLÊT÷¢+•AÅv!k:?zï ÖÚg;C-eæó5¦wš¡M2C_;3!P3}4Éœ¶-#‚,ßòÍx¸%.w›î°ÔÐ mÀíëñ,>Ü8 ^†ø Õ“»VZUŒÔàoRá<¹øÓ ¿­'X¾µVHÝVe1«KF6?}ÿnöEý:I’më ë71í¦þ(l©m& ñ+| Fͱ ™šîw»ÇJ–?…héùv¬ÇsÖ#‰ rjûÍñï]Jˆ‘‡¾Š†Ý’›ö4®Ø»O(øÎàÎ$Ã%M)„‘ÕâÁï&0¯Š]qôyûs—ÀÓÑ»sPzz)_Ô«÷Õˆmë{‚žü±Ù뾆Ÿ:w÷•“‡h]ª©±?.«Oõû]X¶u–¸7á©VPãÜe…zrÉ|Î'T£JñN²ÐÜs¡!Fâ8©aùý[­B!ÆßŸ^Êx–¯ßÜ3s·:žTàÜ%>BãÎì ®ÕË,Î;í²kÃÃ:¹¨ ïãoáiºK¤)éhÝ”1$oõ«*YnÍøÊˆu Læ]Œ­C"Ý´\ŽšKëÿ9Uá-­‡CŒƒ–-.¿ñàô$#`’•Xãy‰ãÚ…ÀÊz!>;/½ï¦‹) 1ÕÈ.r„¨ß¢`gZÝ©Ðhn ¬Ò«¾`b¨F~ü}ªW”Ö£?[;»Ã;p¦t0:;!Û7–’ß_¬[k’¾'U´`+EÚiˆ 'TÔ{°*OmÊ/.2@Láߺjº>ÎAxðÅQÛ §åÒØä ®Ùm—{VÂ}Wÿ’OR¾¹¡xedß|G:ò —²lÂS³¹¢<‹y‚\mÇì]û>ÜtÿúiÆ,'HöØþäÊŸ$’Ü!Y[G]÷¥09æ|ŸwµKÓ Mü„Y4¨3`-T'¯æñ< T]¸\ëJ]”÷r탷 y¿ÊW#,l»ÍØ"GU!¢žëº¬0]ºy¬‡0ÛRÍ#ì¼®Þ±ì†i‰Op8\#SýIß™ïø¶1T"`uâ¨;¼°Á;R–ÏH¶UŠQœY'Šbk¸ZãgLáP6ZǶ{ãò•^‰D|xUU(’y³+¡ÍÂm¬±¯áÊï|rú©ÆôéP¢ŒÊ~.Фžï«„””/[)lå?t:nŸ–ÚáGÂÔØ`ÜbtÁ¾1£>Gâß‹ 0_ƒ¿R>'ÈW%žþÓu1P¤qRRó#I§û$Ž7&Ek9ï:ǬÙGˆôÞýÇØ“à±Ä¬ˆÇ=ŒÁãˆd(æÎ–^7"Ëý]«öš 3µ|þ&æÕl‰ÀŸüÑeˆ‡õ86NgýùæâÜ0{Dƒ$ÂÇú¨Óä’ °ÓüÊ[¹ßߨqÞb†~ í? }üUÑ u~U"ß’"`ßÔðü6Wl2{WÕUPNra«AÑn{H¾„ŽB$=jªharåQðÊúIrKC”æ}e~µ<Àý©–G«Œ ·°Fúà®NxG_:ø;¼RÅvÈÿ>:Î2m$ó\ç£ãÔ*€\&O9™sYfAGç&_q¸Î§ª¥·YlWÚYeçåÍõð“)'ŠNVõN¹ø¤ŸK=þû3L{ZB4•ä5øÚ|Vai4’ŦÏͿ̟Ý>Vó+hÊ)H¸OG¿ÆF#wç2 e?P#Ø£ùRbÄaˆÙ…C'Ê)æuæÌWl¹àÕ}sÙe` °Å@±GŠ{Y'¹x,'W?ÐU¼Œ%Ù$ CÄéXÀ¦¨Ö‘òmꉪ©ø‰Gžíà)Sójfb zsœº\錸„“™«ÕáÈ`èLh‡¥WR‘T]¿¥.´PÍNÀ…jYÒ<:$^><ñ±Æ'%z'3Àh[)lì^KMúW<íVÃòXb-Ùº¦¿›ï£ýþö…”[ë)’÷‹4ΩÙ,}z+çÊY"j=\rUá! %2ô¶~Ïõ 6OX{…ñì1œÈXòi!'ï(ã€ôøÒ‘)N¤ˆýÅùä>éy·Wàúåßð€ L^¡tõùòQÙjçÅ«Ä:KC«Ÿm€aÕtí3õE9r«ËsJ™åI8ȉ¯×›ý0´¥g䞆W™(rPê¥ì'¸«&rÅt”žìÅN-Ù¤è>ÞTXØú8o{ Nâd$‹ño‹“ï¹ÖÞŦqqx³úSžãfÁ÷½æ7{ë_QÇ$‰”{´ˆò̶ù¤é D½ =®;LFOÐM¢ª¢Òùiá$$[—ý,ü×ûu¯CÍGv™ËMo ÅÓ?z™ î=$ „q•ÓŠ³Ü”ú -¾Rö'€,sÿÒ ÈùãGQI°Æ8dH¸›öó&NL)=äÂN·›h¬Ê[?Ý®ex©º ~yڑ׸ð%ª*ΊÝÇ_”HØB•j87¨nLg½°Ý•ËBáwƒCmtiözš:п 3ñJC£ó~•á?œ- *­•‰íÞÆ)"ù5H4Ü\€¯›ñ’*A•ÈÍ4u8ãÊH—ŠO ?Œ· €Ä©¼"ð^˜†cýRŽsKƒþùrŸ„8QÕõW«ô\W#¢µ(|„ÖíÞ͵L2R“ç¶èö²HG Y½ð,äŒS(ôÉþæ ‰NZiåÏT³ýÚr¸q<[`(RÏ)јuA­Ø2pý~EÔC} ¼MƒV8¿F¾ðÓ›¯¡˜©«?¡f sžúØgASq`HÂ0¯’6Ř¨È qˆs×'$^d‡æZ‰X–tf­u-'ÙÛòÚã31g^ÇêØ‡Îâzž>gU2p3yàs‚ÅžÄyŸ€kÒÚÅYÈÒ±¸-LÙW—.e=}íµÝGC§–â ÂŒaûsƒå’[ZCCcþ*ŒéèôµEû;è%æVWËÎríÑ`¤.fS`!·”ã‘Q¥¶Û= à+Ù&;ÿO ús•þÌ";Wµ¡ºAÎì¤FAÂäûeßÜ¥ñx¿Œ™øW+ëY¾ýeh¡Ú˜t<«wפ¨ršŸUc¡ùã Æ Kï|Õj\¦•§­ Vd0þöªËÄW½ØJ ß_Á˜¯·H"qËÝÑ™1xÔ×GPcò¡ùÞI'ÉŽ¾ô®òûKúô‹ ÃËEt2šy<é{S´«úâièKêoé.•ý¡™½l>úº_ø|HI˜shps®øÛv³¯aŠu9¹nu-¡Ló¨¢Òý$zœ\’,ØxsÑdš-{-gðÈdÌ dàTìL"³ÐH™äbY~†ÁŽŠeèï á4$ížT<ÿOY²Û½þmÛO !~H# n#"*a˜§D²¦RÑ´Cá§9kµó«S _*?žX¬û§¨õxª­ÏIÒ3F¡ëE†T—•w”ß{0ݾäAÞM®Gó€ÝX›5|Šm­ R!Ué« ù=Þ .è:GVÍ6@”Ðêݽ·^òó͵;ktüضyuðYzþ·´¤&oKž Ž* 8Ä ýëk¿ÿÎ sHYµªì<"‚½>…€èkíÖ.š¦@Ò…¹xÛìèäL©+†¡]pnï6úüv ›¤|¦þ$ÃÚEÝÄ‹ÝYæf4=~£‘Ë.¶Ž~añðÕá6›Fþ·Iq Û49WÎs™§‹tsA’'‰=×¾h@Â%¾'E²Ž´Ýµj ýÖ¸)Cë+\“ð5;äë(Pš;î‹']÷Š2ÄÜb<;­X#äú§вÛ׺JÕÁ¸:Üê…4l[û0ÔЭ$Ë\mõ«(žš{d…©€§õVKÆw»5¤Œ¤¥X3Ö²ð? 4„|I/ÜÅÕ6¹!Œüñ¨&bz ì'F8 ˆ]°¼Ä>¼|§•\éY÷·в2þ-gƒýµè6H–Å.'¶¶N§è¼õ1Üu¾Ÿ€^³üW…Ó‘rzØ”j)DìLƒY}D>?Aûí+©N?Ûo5Ãà^H¿ß%F1ïSµ¸YI¬^²z+^²òèSf"§p«ÛȯÀ—÷‰þiÍ9}peI!4Ï!t¿©ýÌñ¾÷;“„Oµ"0g¼ÃATJ’ìÆdÐ"ç²ÈÁmÉo-¾}gåëG¶c [÷¶gië«?ÔPè߃Fõ%@¦½Nò¨_P [CörVª6YéƒpÁŸìi¸$ŠÆè¤—ldÔu¶åwÚ1TÅyÃ'Ð!Ö"DF êõ5ë’×Å`À °S˜Sçû\x)³”d2©ÓI‘%}FŸ”ù ·áÁ¿4ú “89÷ã6P³À¬ød_ÀŒ÷\e²à–r÷Q%.;÷Û§noˆî°l›F¸ç;œ‰•H܇O©¡ WïÉCÜÆÂR”ÕØ×%Â]9´0Ðñ1Y{¢0ÉTdhùZn‰‰_ÂöB!`±wR€š±¦ñy_­XW‡Ý»Uø©s¥ÙÔÜG÷é챺!tm˳Œ ̵Š´‘DNÅæ^/{Ò¬O¦_tr‹~;·¦`õÚ„!¤L·Mð*¥‚‹ KvÛmtÑiñ¾$­#»°à½ò¼×3»é¡y×Gës€F €ä 9ŠÉÂsÊ-ÂØòsØÉÒà7‚ìjUN¥8–`ö¼|ï7…w"ùQS©щêÏPsŽ¡¼àb­ò&êX잊#~C=¾ËŠæªÄù,r+ÜŸqð§«<©0Ä{ÿaÅ+#{ª&hdŒëK¬v@½Ø2L˜(2%¶,Ybÿ%Á½Òsm{{çR„¿…b²„`Ç@•쳟ð´"orÖïÑãôhåÇ´öOïÔk/saý.é»úÉüæ\à,¦Êºù&?@¦¿“æn¹ãÇäAuø|ËY( ¬³râ9ÑŽØÎk&rˆŽÎn»ùo ŠF‚ß!¢|êï9Ôàšþ|’¯FàðëË‚sRâĶAÿAéßøÎ¸ä,"@qŸÙ]Æ-ªV¡ï ïK¾Š6…²xýÚÈ…8HLÙ6£1Ž©âq|>r\Íà¢áK£vtÄ naÉ~ûðké\y8´Àqˆü¼9üªÚ'êGæ14k+qnÊÝ; fôãyÚ°¢0¥u³†žHïæ8s•.åyßóîINgîjný¶ïK fPW¢ á-SË~”Ém2ùÑhsœeõšžj¢–ä44xÎpõ©êvò¸Í«sÍ6e#/C •’»gÓeB¹12Ì·fáŠuRùˆœÏ ì8 {xüŸªT,Ô3J Qd>˜úeA½òðû+šÅa ܚIJ¥è³æ4ÇTœc„ªp'uYYªÛÚØÇåΠĶÂé,¿WQ%Ƶ£?šIЮ0bRŒZÅì~Š®ès(ÆÖÿ¸Žâêÿú!nœÂÑsZ‹ven',¦ücßM=MÏ9•#îáb{²ÛÀÔš©±ÒbÃdÊœBãìØÕÅ{\—UPñ‹ì!—(Lj›8R›…ÆÎ¯é¸nj‘háiP?aÇ{/Î5 Ìn›Ëó°K²²5ï¶0p¦Þº¡ÅÒò„ÍǦn< Jé‹ È;jãÎCË­…µÕæŽ6 I=²^^eŽMvûúãª}ú‰:aÉÀ^™”X’OÍY‚D'2ž(ÖÿçºÖ¾rSé`Õ@ Ê)¸}@.¸:÷"ç–úÃÅUæ]«ý/혦Â.DÊ•Æ+ ^`~‡fWÆEtŽŠ¤ ìhœÂöøƒzÖNo$l#áô³&}é£Ñ¸ÅöÑõ»üázÐbíƒ$6®%lþÕ¤¾)É~¸\ÕÀ#ni¬ÿ5OM{ZÃ3n3N þ¹Ü\m_qðZߣ¤zºn€E(­Õ°ë<û$}¼4ú>IÛSîVس'5M ƒGÒo]Ûƒ‡ÓÆCoûÿ¡È8 endstream endobj 2986 0 obj << /Length1 1625 /Length2 6602 /Length3 0 /Length 7426 /Filter /FlateDecode >> stream xÚ­WgT“ݲF¥w%t"½‰€ô&½ƒ% 4éÒAz“Þ¤éE‘¢€t”.M:( U¹Ñïžsîúîùuïù‘µÞ=3û™gæ™=k…“UÏ_Š´…©"h~a!) ÜÅÖeFhñ+"¡JHˆuˆqr*¹ÃÀh8¡ F䀦0(PŠˆ…%%%‰8JHWow¸½Ècl` âååû—åwÐÖûìMÜäÂ~xœ‘®.0 ñ¾hƒÑ0 ÜTÒÕ3S×Qò¨éÕ`˜;بçaë ‡µàíî@ç¿@¶JøïÒPX, D¹Â pì5sýíâºÂÜ]à(öGíÝÁ4¶h$Ž€8{@ÀÚí¹º#±.XL‰B£ îpW4›UOYõ/žh0úwnë"í°‘P$ÄãwI|X¬ †#P@4 ƒþË„ÂQ®Î`oln,˜«;ü aÿ/|@w˜=Øê C¡°0XìßÝùWÀÿQ=ØÕÕÙûÏm䟨r€£Q0g;"alN›ÛŽ ü=,ê;$PXè/;ÔÃõ>O˜ûŸñüž–ŠD8{¡0;"A$›ÈóSYà?'ò@âÿˆÀÿyÿâþ]£ÿñˆÿ¿ïùïЪÎÎ:`ìüµd€Ø-ƒjïàïEó›0ôÝ»À½ÿͽ¿šÂþâúîï>u4Û„=V!¡¿Œp”*ƒêÁÑ ØÛ­?vc,wg8†UõOCüÂBBó9À!NˆßíÿËÃ.Ê¿1Ç õ‡· º²¡º"ï¿Û­"õ°3€6òvÅ’ûïZ´‘Ð~ã(*"1@_~aQI ¿¨ðvíJJˆûÿ›”p„ÿuÖ£Ýá ¶n!á?Õÿ÷ï_§'ƒQA@ÐßCcˆ# Ø9û§á·âá÷ÏÓÇVý󟉇Á00Ñçi$D:Ô1-3]s7·oHÙâM·0n_˜kI½Qa~`²+ -bY²Âæª:L aDêW‹÷Ô¶ëÏ5{ëÝ´ÎÜ])°ýåW›ïz° U iúŽi´ïÁ¤Öžù}!“õ/CúVÅW·˜FÚDÝ NAìžù4?\ÉžBRëâî´S4àPÕlïp%mžþàîìï{×õ ¿g À›GÈ) ¾û4y›õÚÛÆý¸ò ÿÂó¾æÑYLp+õEßy¥ÃUÓ ¿ÔBi3m©Üi  zU,ò'KåSXRÿ`…ÑRWš¥°÷F€RW6åù´5è¸3Ÿ¦îŸ +üR y#g28B¸>A(ÃmBç½h_¶·°”yó޵ånž¶fì`/êžõÝÙƒ€~ IÁä]ý ­4f‡Ù9CÍ,§%Á(§"ØçÏÂçH«Zy2¾ý7Äé¦Ó+e×#æÎ¥ù*C!e]þHB©…˜ÙÀ삞lñÂ)¹9Ê56No;Cµ„ÇòBØø¼$#Îq÷U.×ÍŒ³u<ЯÐõKøXáÎ-¼Ãz—AÉö'q5‚ûê|† ‘¢µ€;&E¿s¹ %&CÔ”¦'¶<»>˜YÉêŠ=C•AÎNâBA½–ׯ“øþmwh"”ZÑå¾Ô‹êµcóÐB&®;ÑD´÷އ$ËÉèItl½s‚â» Ù&QKD®r"Ö#l žä¹ æ–2Ú²„;ËÄ캼ÇWøËìï–/!ƒª8OhSN)j2Ý'ãîÚyª7çó¡–LÂHòy~(…÷@åoÄBu#÷ Þú¯éø ´Óçå„ÍöZzmiYå²7pä¿æoQuZÔœÍ{%X´sluh$åç•QIºl†ÿ£É¹êü4s®»Ž×·ï†W™û÷<æŸãz·´¨Òöׇ§Ý·d^D ÎÈ<¤ »«¹‡'¾–yü1uÜ–ÏÏŸ2ÒW>‹M÷§šunŠ*‹‰o8§¥uwŽ%W…­¿yH)YÜT\u«É‚ÙsÝ.Ês¦EíÇúؽcf…xíœîí#ͯ›æȈeåÁ©aɇÇZGmÑð-zíç^Ãzýúgâ?)?M½¹¬ÁpS±ÃÛ$\€/ÚG[¬g[)±Ä€êoOŒgg^vEøštŒÒD‘6ž¨&)Ri”fd¬ðÞÓ»hZú7†©$,V¸d¼LÜŽ2ÛÕ‹@Ežâøu…†.GËÄpQyäF÷ÎRUgúmŽL`úB9;Kk´þÉUµ-­ë©ªm[±¾ƒ.¨70pà‡†óÔÀè¹¢aeüW•'i-Žõ«_‚WÓc)A쯿#¤ô}׿ÆÙæ dÁÕµÉëo(Ü/”Yeh[»3‚:j‚/ôÅ !R§u_ºP[±Â?…XYÉ—Þ}†\ Z‚Ø´*âßÞ« æ#|äPQØ]n5WQ/̘`ã|BŸ!®«Í3o9Å„² ¶©Yóz^êÆ+Àd¿Ašîsåx2ãQR)‹ ¡³£96q›ÌÖ¶­³ùЛó™N!]øgÁî7*źY.íÓÒ¸7Ù}›]Å”ìBjÅ *aPêf'M$dT*º€·×Iè¥ÔY¦ÝCáBï; ü«7ýkxk‘™y®9ø áÙmG]ÙèôPr^@LÈfÔ›Vœuëª,NSu7 kDÀÌ7( ÖIo"Î}VÍÒ$!C²ï¤êæ}ÇV m£nç<2¦Ú««ÚEÑz|ášž‘Ä|Ô’ûþº&£D ¯ã[fßaaq^å±2“Aä9“*¥‚ÀÇÄJCá÷ìÁA½LIáù nïdÓ‹û¢BwâõÇ»®¥ sñ»&¨,2 ’4z\Q)oTQe_ÞåZ¸vðeúÛ^ì€é—מ<Ü0Ðê2as rI»â‰ìíTŃ_sÀÈâöè©9ÕxÓȪê£O&ö:pêì‘;ª>€û(9ž8eÀᮇ5ý3 ô¯º°á`9Eñ=t%ë8¾q à£@uð9u»‹íÊ‚ÒX÷¬¸åcÇol*,¹¡,G­_çã xç«àyô´½LLbŠùwïàܵZBÙªBOMµ ’m+S®f€wÈÄ]»×¤˜àe*ªè££Æ ÅXD×yŸ ~^zFrcs!ÿzuhxæ[Åøö`Ì€¢ì¥œ?_•·T0g› ·ølîÕN<ÐέÏ$ûg2š1n •,j3ö“Æž›æmÄ!)¿–ߊø]ïª{Åó¬[iü‚gDÑMæ—zîu†9PÔçf¨V^åŽf‰‘«gÌ­»7Ì2jt.OË’ön|7,&æ¥ó© JLNyPz'hñ^Dñ;ahƒf}DȉÛ-ᚯ6!!—œô“ýÊÓNRfá€9Y@yëÔâ÷î­AšûŽ;€Çµîüé¡àÛ}Óƒ{Ûú&·ÑøxÏ0‚Ça¥'ŒÎåËk ¬­Y€@ZΨ»MÅï óú÷¸âóÝô£¥¼º]0*ÙâÁãn³|±LF ?­ØÐL¦£ú(ðíB$”ι¯ÕQÂü¸Ófù—%³ ‰×\³ÿ¡÷âí¯ ¶਋~ËîÒV†©ò;³-åÄù ÜUß^Ü}r™C™?TòÝHdx‚vz w0µ‚¦qôÙâ=EãùA_ p¦…²ªæs©·\wîC#ÀÁ‡H3¹‹Î»çl†ã,õì?ÊÙ¨^àí@•fË„aÙÞ½J>y)’Y#\gGÉ9ÚÊá`Ѧ4ÜÆño%Ó|#DK3jUQžÌÌ߇é§ú÷Ø „¢ê‹j¥"qgîéuïjeAö6¯J“†ÎÎi<¾½ýÈü¤¿Ûš‘,/JVb~ãü¼E¾’FÿM‰Þ¡ÿv²3—¦_@VË’m®äK–ê­l…ÔÏ)T$fšzL_ ü2}‡ÿÐR+vR‹ÎO}iðl3þ¾ŠVfîîèñ yãâÔ¹ýOëeª}·v _NCt.c@ˆäŽÒØKy߸ð¡,¹„]œW¿?#3¾µåÛ6PÉÌ2ÄýïgjÂj/:KEÿvþø ŠÂÎý0i‡ñ~›X3ÝÌ? yÑ&ÓþUýóDëˆúÙgŒK,òP6K£S=©i}zƒ$©ïºñ y¡úùTÊÔØ`0¿‡g>özV$ØìþÁ ji‰V½dñ샫³œüö+£6z°@TBiÍ ©µÇثٔ=É´ŽÿÁŸÈkÞÿ¾¶åÚM@Ì'kæç od¼´±Ïê•y"KúØá¾UíJª>û[7©ÑN¼¸œéokð½Ý(6_=cL׆J<~]GÑ®ã<Õ€óY™´yžµVpx§?1”öø”År`À©ßF;ôAë®1N¤Î8Ñ ÞV Ht“µs¨ønרúLCâxðgV™ð“;Ï«_Ñ=‚ÜN‹¾×N¼˜¾E´_—ÒÖº”Ûù%Áócšìþ']^“(jÞYuž´J·Š)?›î¯g~ËèôÉOnÍÒcОþ[YaÚ¤™±±^×H/«‹›i¨BŽÁ¸Øxˬ3ò~Žõ"ú¶±¯Ðظ©ØTæìQã è¡oêÂ…|Lù,z²Æøö-G«kðú¢-´9a@ôVÞ¦ø¯Æ#0\ŽôQ_Ý,Ú¨Ý-x¥f˜?=Ú§ið§™×ž}ôg‘£Ïdæ²é¾s3C!rí‚·uLƒX}q©¬Ö<…¹ Äqêøa5óíŽ@BUìš\Ìm1Ò @0™?hçji(Æ?=h§R­nFFpŒ_]*©ò6Ñz^ýÔ’l¤hÊãH3ÀïA`zlN­Fyªì‹ÙÒÃÉaõ,àŽEL@x±óóSPs·«äãD]ÐzJ‡súKk¶¬y>_9Õ¤I/öËP—ê AšÆÀ8´Æ¨hGš[`ödÜï¯ Ô)7jØÛ”¿(”Á“qIÓf]‘K\Å»`­+âƒ<3Žˆ¼K‘ð½Ÿy{³&íêO–˜·È¢ë¸²š»VX ⥵jÖ»Y´hå³ø €é:K‰Šþ0Ã5³ßŸŠí‘‡N“ëÏl.ªFâX~ÌíçÀ!eÛÑ%ò*ï$ÅùzÐ,!±›v\|ºKÕÜp™y߉"ug«çy–ݹL{lVÑ&¥üSEYՕ͈Ð7ò»ü?$[¯¡¬©@²Ê×ÏõËŽ?‹J3mI"ÛêS•¸ ÎqÆÜI•†™Ùd™¢Qñ P¿‰Û(3ýÏÊ+A㽕ßUÅïÓ‡Ècò2ùBÊö7boæú\ßp{‘ô­&²z´™hGšþ¤ ¤EÛ9Fù°½çùUcJ`¾ð*yëW’õ\9Zò>…ŠwˆAÅ1ž¬ntÒ?ëzqÚµßm忊•5Íœ?¦£4Ïʲ­ãòZVûš|O>ÔÔå 6㮸_щ‡º)æ[ßïЫº~Ï7¸ñ¢s)ñˆŠSÁ%ŸX¤ƒ÷¡cE ‹J£SØŠ¸ö¾¸D§Y!¯´}'õ4»²Ä†°´ùFû0[úš‘ÊõNæ&­Pj-žhØ6R”@ŽèùÜœ‹ÆwéMZ§ôËÏMzòœŽ¦*¹­ëW\,Áˆçzõpö.y€ü2÷VΓo¶ù±ê~ì ÄD¯J¨B–,ž™Èó^ ¦LšöVéš« bÒ’,>av rì©­kg.1Ì¡zz7.g'ÃZ÷†è`®¶GˆÖ/lc`t+ÝÑnYEs•¿iÁagD ÓÝS|¡V”~Psô¢&ÎÌù$æBêÞ¯§Ú±µeæò™÷ +k,²ÉV–8Ö…˜ð¶˜¦9Æç{JMǧU™®”¤ž<À_ÖyÞ/¦®ÏÄÏè³ aŽV–%¡‹:Ìß? J$˜Xnnà•I°Êð·äèÿ²ÏzaÊ}à¸E”¤ÃÄqqVd-L¾ƒ¹â/°AM+‹Y¨j‘ÈÒžœ½ó³ûE³Má î©•fÎ7âfSZ—–ä»í8‰ê¾ùyóèG*9äVuA÷»vt…{CˆGœ¦ÑÃ"É0Òò<ês‰¾tÁŒöÎ5µ¾yMƒ/ £u@¯y¥4Åõ†¹í*îG¬ø‚ <#b¿r3¢"Â#--åùx ó[¢Òü<3÷Tý6y#Ç(dø¿Õ«–Ð.M\„x¦f—/Mï¶ûØkÞPFÚ„nßž+;ÎÑ_FÄù˜è$~ç,kP•_¤ÜgÖ ©— >ñËËä*^2oðQØ5º·’.Æw_p†µJ¿¼E°î]û3²•ôpëy·_ãűZ™›Çܺ_Ù¸¯L¨ò.5^ûIúnÆJniãöT”,¸çÍ–}}ï;ïÂáœâŸÎf¤¾Þ “k5lf^§’Z.Rq¾c¿h"jÝ“×ls]Ó\rQ@¼dµâ^U¶ÓcMT9 ºwr‘QUCį뀄™Â“»Ä™‹ÉŸ/\ÍËЖÕô›s¹)Î÷ÞÎJH¡Ûž3|Sìz¼à æŸxø¬BSËkØÕî?`œXnª‘VUpú¶‘ßXÍ|Ò+LbU˜›·;Žòê˜T˜©¨4n|§sófLì~uº“ªÓŽëæƒï8XÚ.Pøâq6) $]ze,ï[§~‰H@,§¸žLK}Òàa<„àDûÌ}ŧ¡³¤wPëÈŒ Z=Ñ©îƒ\½`ÿ)WŽdÛg²¯Ž~é~’h0fÚv#XÑÔ·èž ð “ˆ:]-oJ6Kd”u†¿.ÈA&ž°¢Ú`¡¼ÐÕupƳC3EêV&ýÖår㦨üFâ¤IØK}•‹”ÝIJ?ÖGI-ðêxZOµ]ßÁ$÷‚·Yg*ÖÆI’w¶˜cÄ^3s®ßí#î /]”cæØ_ëG釵=Y¹ÿ~òâHݲÊ$lU#–£Òâ8àiù%À8Y‹YTj·Ðâ=ykÀj§s ‡%òf:Ç'NæÈ»"ƒiHKÙ$”Wà0溚Èæö?¿ÐôòØ;åÖ¬ýtþrŸoj',Ô%áÍ”¤Ý»Y§üGê^Sc2%›rz«„‡6ÎÒÄ’ïuǘµ/¨À7kDßÚÍÜ‹Ôh¸o©n‡nÃ*]³ƒmHh©îæ1;à ?–”‹b‚HrTdùQ›Xñèažd—fF}¦·£îì™ÄdQjÐè/èq Òrç„pê–LEVi7Ÿñ2¥Z0œJ_ÒuT8‡ÐÔA€Ô’çÛûû~zì§Ï*zCˆä¬6¦‚Yå=röb4Šål!.šÝùìn_rÜR¹zî<˜wÉ"Ìlë;0¹%wƒ3“L¼çüú³ŒÙô^ϼöPr {¯Ÿ´ž$t–2Pµ&¡¼ÂùºØ y¦Oà)Äçl(‹ØAµÞF"X•¨?´Ž ¯]w#µ>eµZ:n*[îôÀ¼.~ì XM£ðBü^"-Ûèæ,}y$Léó;7úŒŽ›{kå’¦1%‹˜$6àHßÃé__õaùllï?vÐ1rŒC­SÏ÷ýPoöm$™&ÇÛÔ@M˜ùÌ÷rZ¸ýô/ßJÜ·R5¸Q`|Ê!^3h1ÝVÙ¦ãIíI+}››pž7«ã“’(–°ã/,ÿâr'qý¸%ñ¥4n™@S¶À¥½ô_Ž4Ž endstream endobj 2988 0 obj << /Length1 1144 /Length2 10998 /Length3 0 /Length 11761 /Filter /FlateDecode >> stream xÚuwSxe]ÚmlÛÙ±mÛ¶Û¬¸b'Ul»b§bWœŠm[§¾¯OwŸ¿û?ϺXsŽñÎñbŽu±(H”ÕDÌM’Žn ,ŒÌ¼Ek{SwW5yU ¥;àÈaGA¡nífü/ú!æ4q³vt7qûë[¹L\¬Ìf^fn^–?kf¶:ºð”]¬í}Ê@7 ‹µÃJÜÑÌÝèà¦æîädg 4Wº:º»˜]y*ûï¬1G'okK+7µ†ª ý¿€©÷?€8ÐÕÚÒ@ùgá´stú+Ó ) ÐåOÑæÅ*[˜H˜[»ýÕ.€ÚÊÍ͉—‰ÉÉÂøctµ`tº1Ñü)TÂÁ\ÌÑþ/W¸¿f&ní4ûÓ”7ÓÎÍÖÁÑÓÁ÷¿` kó¿[2wwbÒp°vvʈÿßà?Ü¿1K €ƒ™•™‡™t½Ì¬˜þJ©îíü›dù 6q0÷÷urtX˜Ø¹ý­-€^p¾®&@€›‹;Ðß÷ÿ%þ玅`nmæ0Zþ¹†«ÿÿØ+˜¸¹X{ô˜™™YÌ=ÿZü¹PsG;ï‡+šØLòZÊêºtÿÙû¿¢DEÿH2°p±X¹9þ8å"Û**›Xÿߊ˜ÿ}XÆÁÂÀóÂÿLìŸÅ{]\ÿ¸@ý·aiÿSIÑÑÍÚ  þ·Iô™9˜ÿøãÏ‹å5ÏÿàÿW ýgIw;»¿û§þGã€?»äõngâò_á&öÖvÞÿËÿ ÔþÃçÿ7;k3K»ÉÚUÒÚ h®líffõcü×p0ÿû‹*;ºZÿõÍX8XþƒS·²6³uººþqßßÐÁü?RJ8˜9š[;XÔÜþøÏÄÅü_À_´™»‹ËŸñü}AÎþsoaý§@ Ð h·²èhÆjÓÚùT'‚ïɰ?Å6À©ñðéNÌkºËÖ¯ˆc[ŽÏžÏš-®Qea5¬ÒÑ" ÖKð…’´Ý^¨ùÑnqf›àð4xÙž³ÏT²ºð?ÎÑ«»ÐŒE9æ¿JÁ¹5\™âë”sñvOö°¾XuÉ wƒöÒGåQÞ2MÀlÒÎ#@á$'®# áàLqÈÛó­˜Áàg. vÍR"p/3ˆ8ŸšÖz’Fmø”çä‘á¸ËCKmí¬=µN°Ž/u-;ZÜZÄ„ct¶>gj.Úc¯ÏŒxˆõwËmïN€Ôë¨8Ö&{8þ8ñ“Q3ê+Ìà”Šog·á)â¿l2F·è®IÈN‚!>É!<œV»4¼1¤„¤W®|ô]ÂÛ}«æäq”/êÜ Îÿ”–ZRtXlª’·Ž\íe Vˆ&òn³3Èqg9T{¾ì⦠jxë‡sxÐ# w(£¼8×w©à×}V- ¥4§#]˜$Ø€ úìdSEδ#¢Ò2Œ-_Ë“–:^؉~zTÛˆhP/]X·æÅD€#P)‚Õ&ã°~ÔöpÚUj¥PÄG ‡â œÓFF ÕgbÊÝ{ Õ±ËÞù”™¦ (N(‚kRÕ'½ov»7>Ú †;ѯ# ª9—ÒZ>À4ôAZUpÚ Q>àÈ5!ÏA­O ËÀHlÃ6´@ŠZ:EaªABŠƒöÖ5 B© Á³É‹l*›y÷ë­C€+=™‰Ü‰¼;dqïÕáµäª]TE§o'=½Á^Ä`iÉoâF€ÖMòdlÇaæÈÆll«ß÷öiòôá¹H²Q¹´kk8ŒfÌ oN; =úPü]ÇÑé ôËFÚ…q¯ä³ãœÎr:£z«Üû `U"¹+ÌŸF`í$bz{ûP†0»GSõH[Cßêt9»³‹ß«¥ÉÉGÞ%ПÈé¾êœ˜Ñ+íÖ Õ©‡7lšÀ 3Š[ÖV÷9­^Q¶%°O½V)O ‰9¯eâ£F‹3€b£ÒRØ>»cD}±R  2šä©ÙœÊ.Kþ¥â<~¤Ìû]A,jQçôî §ìýu$Þ{4­­ýÒtU zú–è$ÛâÆ]¯Âéý}® ”lq"ˆºž­ó‰t÷B‡we Zе'¡™ô˨ԀÐo¬ák6Èp ï Gíw¼=ߎ´Íäzös{’XËÒoþj㯥;ÇIó™I TC•.'Î~ãP93WukìQ)•sP5Ь,ç%Å>{¿É~Tö®˜ÄïøS¢/éâ—8° è÷kʵBZ"o/gã6Á¾Z¾“ ØÍ»ñ·—çèD3Ôx;ur–à·0»|-aM±hÙúÂ^m\‡-s‚Ø´Ëù$3™Ðߟ²qëÛÖ¦¤¥û’%1®ýSûg‡Ô~ož2Jhí麊ÝU' û^åÅrÇÈHê$•°ðæi^ ¤¯§î‚Ï'lå2ê× >¨Í>¼ÿ‚ùª] œg!!é{éSêC!?€ÃÖy:Ÿ{wgòã(ϽSIÂy?¡Ë“ÐSAzE7K¼¤—=-óß‹wBd‰ß9ý륂IF*­ÒDm”°zÈ¿šG2é3†‡{%éZEýØa’’ÿ'5œñu©¤Àó,ÝíÏw|‘[i.cZý Y᜜X"‡¬oÇ&¶õê&ñb‚º*Щlñ¢d`bAœ^%/RÅ—­°Oó-f •ÍÛ\Rg,5®Þ?À…ÕêÙB} ùD‚e=À‚A¥Òd e—|“âÍ:ê„W^QËØbă€:#(¯ß_…"Ÿxa¥¬ÃdøCÖ­ƒmø­Ùð­ÄY¹›—pI1‚¿¤dÕf$gF¦Ã‰…„±îzTwÆ›é7Sq˜S•U± ]=í•ÊÊ(o¥ñ¶ó®¦]øÝq¸„<'~™âŽáðZ{ü„_< ïBeã‹Doù¨¤ß×>„m-–× Îa«o$[snjAã\ ”]S¿ITY¸p»ßæNO´F=";p|×k  i7”?yXCé^çUýÀ¥\÷b®³VG,@¾8£Ì–wûźjq/%ÆÕÞvÃ’«¢xµ•ÇMwN{tVÓƒ›®¤ V ”©µœeïÝ©U®ÚÛV7 þæ¼ÉaV¯FbÞý02.vÒ׆fŒåz^ ?©vXY^ûÔ½‹5µyùæ20ú¨¸t9Ç&‚ŸG”½ µ;áóP.ìS9Es=#pHqm–•ÍÖì2_T_\T´2ÄÃpÕ¢Í^µ7ÑÝã_ÈÉÝe;LžNUd†¿i€ýƒ:ôùƒíYà–a¸:‰Ë˜?ÝI‰yû{‡ÖYu‚¯6G[²ú51ÓêšþŒ¢–¶ÄwýEæ™ËH¡Ÿ;„Ó(ôS·"-E¶(9æ^RÇái´ëMR‡ãÆ`yûp”ú KqöÏÞùTßçé›ý-IŒ.ü¶ášÕÛU´³‘²G7J.o´XýŽËVs+²Ó2þ¬1&b£Núˆ÷ÞœúdK™Iµšc¥Áõ1ôí˜¤í·”e|°äýC}7XVW.‰B ’Ò¡Á‹6AastuRÜ„å¬Û qÝ¢½Ëz‡âP^þû$vò´a:tŒ[7½·Múm“5ÏKÊ&!y˜9¾Ñå• Ôè€;ÜF7¼òèg¸“(AGtnbtðògš:Lx” 96á}ó´]%gA¥B´áWûás7qb˜#i[`ú{4د)çè˜ìÙ,&!’s\¥³±OxOX‹H»„þIˆÍ]SðíÚg—Apo7Äà«á“)·¦Ä¼ÇPe¹®ö8ÐTŸ¥^ê”5þ’+Ï´íQHÞ™Ôk£¥Y¤e§Šùv,DÙ¯öÛ¤Š¥'–÷//øþå0 Ú~¹tf‰jS‰go–"ݬӑÙz¬îIó î¯wn[pÏÆ·Ãh`—dÉs-sEqñ½¸}¿Y{¸g­jˆÁÙÅ7~£2Ȉ`y ëà U× 4DÚD×££›q=ňÔ}\äôÔÕ—ÄìΙ‰_ùpC•S…oyªœÚoÖ©oÙȽƒ)ÝÿÈm½wtZóŒ3fÝ%g÷hu“µ®*î ûh6‘—÷ lôÁ_ÉÓ#Iž?ñ? Ùƒ­Š©©Ï© £F%"Ä¡<€rö{+—ÊXá¸Æ4PJÖâ>_üb™ˆˆæ·bŒô%œw»]qõýÛÓës$E¼¥BMÀ}åÕ°)L*ÒA@„\Æ« ;PhÅZŒ"H¸ÝFº{Á³¢Z¬‹™ÅAõù°“×Ï…C¶ÝØÅ¦0õ!¼Â†8_bc‚üpÅ™XÑÄ?‰—^ÄXO´v­ÐäÌ›×ÙÖýX)"&±TÂQÓ&Dç‹[´!ç«ÆÅ—p»þî–ª¸dû@ÇOÒk¢Ôš)ˆâ"PeÛ7!¡Q”`@M:Ó& „þG)†;Wâ íš^8QNiÿO×|Áqö‡¹Ñ0v޲¡Ó²*™Õ£î»¡¯‰ÐD€}tmñTwY•þi˱h={sP 0¿°íoÞusêiˆƒƒ"{[”‡²P$ß› ¹Ñ~És?Dñïùn L*ÛõW9½­ÇÆgï³êöˆtŸëýá¨Âä<]¡êPÖkí»¿áš¯f-„U$ìEƒÇG, ÍìÇãÓïÌó.×î¸mƒU# qçÈÐo~E‰JK0Nœc§e?„ò}Ø2­«œE1³âUc妷_]8Þpjñ‹Á´Ö¿r£b‚”{cw”ìíøscrT-T…ÞBìÇì½Ç†Ñ=|½ê•vtrl”?¾~/J•$Ø‹‘Z#lýיöÈb&%-‘[²§Ü5úÜê¢*è¡Ââ_v)†7+ÐÞ¡öp‡<Âám\ ¤ñ©Çuÿ6`w¾j3«V4;? ޾y%|Nð–äÛé¯0cÔ?Œ˜ûЮ¤ßàTK½]ý…¥ÚßqÇ­µ%»¤j ”9GÃ’“äÍŸÃ`®ÝþÈeÛ?¢þ-‘4 ^Ý5'àG|MÆàö`Ö‰r9^EÄôô¾¼@OrZR#3ŠÈIx®ìÂúe(×âYñ{Ñxmi!{rPšžãBÉ­WéS"eŽ˜°ÃÁ(¹ Ê@Ï—dQÑ)a¡ focVÜ^ø$f”Eœƒ¶$…i.µ©/¦Ã–tQ|kv«lûkÚõ:°rU›Þ¥æ7Éþí‘/[‹Oˆ{Qôn±û<*øå|‡ô)˜£³Iˆ\ʯ_ÆGÈs÷¿&Ìä~¦·Þ¤˜v xïFlPÂbóÌb§¹<¦ \ÏO§¢òV…«i¿šÄÞ½&@ZcW€•Ô³Œ 縤 || ª#Óô]²à ãÛ;<’šñz*—®Ùk½§pØ—ÝNCÐ7ÍÁG):Íê Ì•1Þuö¡'øvWm¨ÅP¦YiÌÖòuœ¤%T–„j~mÛ °¡1Ŧí›A:ôBjh™„¼o¡ét³÷Ï÷zæ;ê7‡M‡ QÊÇ °:E¥ªIƒÝ`†Û-«ˆÒãíR,›/"xŸbäJiqèûÙªé6O“F¾EàsÓ—ë'ÐÌ/k¡/õ º‡òò½Å€uü޲FÔø±»Á^!¶Ÿ'A­$«9=±fE‡ðÂsNï+®˜ÊVEÚj«#Â;6ù‰?EG`è³2±¬ìë V­(õ°á$ÏÚ#›4—£ðh‚ñíòúÌ«X’ç_®}‚Žç½"ir$=h9>°é3Pb¦©iA Ûß{ ,Û©;ùÉc ¢EXÑ ¯L´h{†’JjîzJ<èÄGøgyg,½DBmæm =ñå=ls>ýÕ6BØHP8É ýà7148ò)Êà#‡eœ|jâuy¿FGÔùÐgc»Êß•“—ÿ=g_¢(ó2òÔAÜhX-ð1pì¨T•lOßbë±s÷Ç_¹5×`oRw© ?M™¤'6÷ÕD‘ŸM&˜wg41ëÈì¬S•ô3 ÀƼ‘+cˆÆà–2Û!ÁX4©|rí1¶sìe¿){8Ç]È=ª\¬xs:l “-åÝt¶ðVJ岚àÇÍs*”­d½Î},}¥m±„9I^)×+,øNú-ö4𩘓!ö¥²sÿ¨o FzFõ ð£3»¯^†—Îóž;ð°½-„’-U©å‚ìš½¹@ \%uìh>4ï^𦨺7d©¡<5–˜G×½÷<öá)­ž†Ñ¸ï¤„qºƒ½šƒ?ûv‚sih@†n"Ýù87 ôÌH܇—ä²fë-xnw´zšA5»ûLýˆ‚u­hÜ6ªUž—Svtö…ɘ º“„ƒÈ‰ù1¯¼ë*I;FÂî.ôíC:®ƒvQž UÊ Œ£^Ù<9í£¤6¦jQ_ßöZ¦x©€?O8ai¾R®áJt®sñyOsœ€)?¹úYbÉ ×DC-l±€óÚw ÈS­¨}$4ˆuÊAYþ¬èN¿.9í ^?õ4þ¦­ Õ±PãÆXüVÕ;•íÿòM\b'n¹+lf‚°CÓ6‘Ǿ rëX4eÇ€öt]è¬ÁÁ]mèè,iJøH&¹2ë–jÅT¢‹ÿ®4¨à]&Éš%k°nP¿À 镌߹%'—tŠÂ3öunçéSŠÄÉW[Þ2ñ™]ÒçݵÄ(pS˜¤H™ßXˆÀî;õE¶èéÀ¹ã2¯XÊ“|C5(6ˆ ï?AGЋ¢¥Ð%5#³ž¨Bâ éÍQ?ðpÍ.V­©ñc³pmCÐ*å»04ÐÀ Þª!™¿8üÓÙä‘rËBÇp^ü§[ò°WŠ£ØÃ¯Á‚1K§®’¸÷þc/æÌn;I·"¢Z.Ð×}¶ÈŽÅþ&{P°Ï+ç&QE!‰@b™û”=»Ï¦úié³%º•'x7Ê4-¨jsŸòž×¹£9n)NŠòOñ›X«=ÎŽ›‚DÌÏ-Æ+A‹ÝPe3¥Mµ;@‚{|ÕÒÛ…ýhF6¦Î¯ËHß‚j°A[å¶÷Üè0‘åzc㌟1@U†@NGÉùØìÊXOHNͲ¦>ü+ƒ˜¡8½Ï¹6/'ŠÞù«¤è WÁ­äY¦TWdòË^Å|ɹ—_jÚkÕBa̬áGíf2¹Í¾»ô9’)n0׋Þ-ÊFA†TE‹$øÜ¹Ä'Õb^<ñËS=÷GG¾‚5a28êi÷ñC®»Q"±ª3Ý©žâÚ–£!¬©”p~Ôbï¿+-(ÛEÐaqQ „ë·EFžB·Ã1Ú<ésF&}ª/{Ë!oÖ­:hj¿Gž-l€gK”²½Ç—kþ¾tIª~²ÔÚâY2R{ÊúP½qP‚ŸmØ&gÀOf^4‚ÝÐ Oè3âDŒ˜U-E€âjÇ´– iï°tÈ–¬~Ùîxo¨Ûr¥å襖ÄáX™Ÿ(¥ë« ßq¦T&±£=IÄXJ9ùÆfÐGߙ‡yð2å/GõOÌÏãC}íé˜açò)ç"Mgåh¼öb- ö¦2ÉÁµ!NúZBªì0rã‘-)QÏ}žÂü–z£È×ü±¸ |‰ùñ’oA-¨+ŒyWó4yùꤔÏí0¨³Ï¨ÒíDæ¶Ÿ.úã´Ë(*]~qiØPÞ¾@àDþ¶>Ÿ!ªk#V¾Ç§þ,áøõ£n$ Káz\,V™‹€‚›|î¸2pU˜Òé·ºS{i8|Uøàq{ÜWÈ‘Ò>|ï¾¥ßÝÜ oxÏ PoÉO•HL¸½©|ýŠP‚îñh!wþ£³âÌ7˜èÃà¿l_LÛ”·rÏ|"Z ;ýNŠ+CÃÙÈŒ (Õ«çÝ .ÒÞUªŒM@®¯a­t¶æîYi ç5ºÝ|Lè`*ïË¡‚”ÊAu¥P’5x°SkÊpOw„¼®A©.Ö’ç¤%äJÔ3ã%ùøHà[Öð—fßÍ©øMø†}=ë¼`C_«ã%8Ωv8Žèö)Täâ8ù§+ïÙ*Õ¬ô;ݳ„øºœÉ¼®€j€·ç`¸V¼ŽÕwƒ~‰ä¹ë…®k,Öè¨UHæD.$á„änPþJ«Ö´€¡i¯39—Ì'©ú7ÍEª~£—#Íïäuá_ˆ Z;>ª†å_Æì&ˆ­x?ª#jˆÑ‚i¼>ìÛ äÊò¶XÚ4høÞu“V¶Ãòö9rbÁÕðGòõ~¿pºj±ô¤>ùð7Ù{ÌRíno¬¼¿V hæIm@óë$dBŒõãa¾=3äÕƒÖ›ÈʓՒgé“IHc2"‘òo“‡¥ê› Ï)¨uƒ-³#pùEÀÌt ï+0Ð{” “^PLàj<пhA×ÄË:lÐq´½Å¤Êt»·FñãY´Ê(ÁéýÊÏ¢xO†ZŠ"Z“m&æºú¤µÐ¢iŽš3ˆÍp #’ )Ô?sr°ã ‚ˆ»} ÈG¾Ï§¡dÇ¡dTy6áçéÊ L,X÷”İUn{’ Oªaúe‚ôéÝjËë@ -W¶q¡?+ôº¬2n3näA‘á óx§kjgƒPoÉtMü*Èp@˜FL¡ø™~Kµ{Îu¤?NQR íØ3ýe s_³È7°x{TUãbü×n³UÃE%#UJbwÐ% ìÝišJxÂî[§Oóø‰ ÔÏa…G_Ó„ ïhÃ7FUÊËhòê ”“x‚­%$ÏŒL7¬L|ã»ü+°îbìå{ât•QhOë/®Cʵ@B4È1†6å†1}˜,]s· ’3­8j+êM¿tÕèAy0ËÆ}¯Y¿ù(6*®‹TÀ`«›ù<0rX)k~YXù|w àýsýÏÿJäi®šŠYÂùï!f¯IÐ^µ’âz•Ôo†ã¾Ð]¢ˆÞ@ów4UNƒ¼¾ǧÐkÉŒá¸-ãæ®¯¿òNËÐA4?„A% ‡-U?Æ»¢-Ç bm)ªÈ°7.»XÜ–¿õÞÙVV‚«–ýž ´§ÂÓË" õÖ~eÐK~ƒh·?€<‡õ”$ñêqüƹÚÿsŽó ÇUÒ‹(‚÷)oJ64ó`Êï;.‘zìÓ“7Œ°‹àÔÛ6'aȧe×–`‡1(T‰ˆ(Y0mˆPÀ)#¼ð“ëÚèã{åƒãw,å›Wš{qË[’‹gQÏK¶k z’‘…NOIyl§úÉÖŒ™3F)=< ÚÍÁ‡œ¼ÔbeÏalXrvé™[ÇäÒÆòw Hê}~€×¬É³:8X7 ”‹Sù\"){¹QÁ»Š v­'l¡”n°R\í½N˜ƒ¤ûtf€žÍ5žÓ‘Ö‹¹DÆ¢I¬2“ìE‹×ô%ÛkÑz!çøSx¼f m°®¶ô…2@¦JüŸQ#›|]†¯±4V.Äó!ÕØ‰ÈÐ’ýkê‘ ¼“þ\*ªbvVašÂÌLÿ–q˜n `º/R¿ïÉß‚ÈݪZF›j‘5»„ßéBYk?É!ܾ zÚU~+‰8oíÕ÷ؾú! ·)’ýÓ»L—æ‡a-òÁꌥ:ðCÎìUðc²“Xä«(Ï¡_Hõ¾³ÌAt|…Y#¦Ñš¶½¦Î˜ÞŠÜÝò›ÅÑè(61EŠ~¶œQºç·Î3B½ø˜˜Ù®DnÐ^\ÓÃ}N 1ÿ×$tC9©In6Ò®´øßÙ»\þHíÕ=Ký×RÉÊ bòäÑÜ„:ðÙB‰ßÑ/bÀHŸû¿.ÛØüÓ»€ wÈ],"Fb@0P1fálg“ ÕÎÀ¬3W^²¤{:SØ£C„ìö¶F”ˆÎCÓî.p$3¹_=º<ÙaFÆáÈ…y¹™Œ;îìévÛ0£#MǕ̀…E§+–üòÕ z¬áÇsqý£ø‰ç:_¾&èÅSÖíéµùcm^>4\ÑçÓZ-aKÈFKãi¹}‡¦Ãÿí©!Ù¢J’ô›Q¢Á·Vןo(ƒÁÆ©©eV& Ü…²¿¡[½|ÒÏtäMðÜñsJ(m_ñÛ“tEîî€ /"µèí|3fqAãÔ[]-Zì\üê\H®´¦œXkèCv£víN~qx%êІ'ãx¢¦:ž±‚àöª2añ"žRçÞm¤JT°tÜ9iõˆ¸•mp§ŸmKo¿ð!ý| _-hÁ¤'h4Á‡æË"ͳ†[©uû¼âmúƦu\™MeˆWC6JœH&¿Å.È»#cÖMô nùJí–ÑpT§k™û–òýÊšõÆÙŠ’šdy<›{Ò=4átßê~_}ÎÜ=zfÀp#9ë‰]3¾GìÀÀ±SÓÆß]` ž–Øü3ÔJÓ‚lXå^©VÔò‚ÝÒÄU@°4?Éö—:mQPÿ­Ë¯ö>«î&h¬YP½ ¢*•d¢àNÙCï}ãr¯Y4¿[Çâ˜ÿz×(™*• ¦5m ç xÍ_ì}¯úÂC;ñ‘Åï_^}Jˆ  èRÍÎZ»é.u}R Ö ÷‰~‰ý„´+Ó´e¿Å¾4?Ñ7ú¡ïs²]Aj˪h܆í·Õø r”Èh6>C…zœQNM{² ` °õÎ2žÂQ7äq"º‹]Üûn7÷àþK1¢—÷Îö0êcºU°*¿ÂèVÖ—‘———ºäþŸiÜ\ Õòo*eFxþì_ib¯~\”½ß»TsØ×í¿>À øÕ=®ðDT~ïht·ec§~…a«ȨˆíõÏ'%?@Z•-ËËs׺ðÞN ŒuPrx÷ 6r÷l>à.cL™`š@Ã'p.Ù™&ÐQpXUFß¼~Áê ÝQÓ! [£ï“¹IZã‹^¢]$KÇ^¿Ûdö³…Ýôˆî¨Ñ*|}©‰H0.B ÃÜ:¶º/gê°€\·¬!ÛhܹN æU§^äOå•ü"ÈØÇÆNtŠS•“a/¸bw‘‹`/¬"Ö¦è1íЗ2LÇ¢›&¬#dgÙŸ|̶w O+IDý½…ʤbêRR Óg¸—&ü…‡Šé¿Q_¸¨[Í Üu½}\ñúÑàå8ÅÂgœÒtÆÑë~Z鞥+,„í±¡‡[5xAúÂ#Ãè•ã”ÓîÞ"Z$ŽíÝ)S€¬ÀZá„aRä‚tfvPTàæ¼k¨Ó¡28&Ãæ5!#rL & ˜Kib{žfÕ€ÍQ¼L0åhM"»%÷‰©Ã2&yÔ±IA{¥W%ãû©M¿»¢Ð®@8b¥opð#ε’N¼Äë7’xop’>ž¢Kã/úëÁÝÏÌw® ѧ ~dœŠOUÃÞÙý°ù-+WI0’5.Õdbìk›ªdiÃ-dè»Ý ÜK)uÛ…¢ ²ykñ¡–­Pu¼Œ õÄôüðzÿîüÛìp€mKclsˆ "É%ë—»õ²hå•a+ ú"ÉŒ¶e„:¢mò²_aòN3’„ϘSÖW=}‹D^Éiî;¤VWq¾‡´8I$§ë÷ÆG”€L0r_ðàK—ÐlbÕà½øÈ,Bö¸‰F¬‘Äœ‡æÊÂ3ɹF ñеd×±Ÿ½½â¨­)¼ ØÖÎ!%s„ò°Ck >®:Z-•¹¤lUûá8÷žø´~ÌÔWÐÃešQ™/A›ÅÀ¾}Øõ(¥©áÉÞ@qü&Î9Žh²Æëï•ÍÊ£•ð]ÊSG:[pox—w°hZ•‰›¹íˆsßB\`Eƒë²™¯d\æö ?º?Àý¨‹§¤°½‹jrØšWŸV-Z†¡T3¨›B¬wL™ÕFmΪ­MZz(²œc6wÏh~ª £Ù¬.ÂX‰/aG7 ÖÍžwú-ÑÃ6$CiA¡ÊüÄj¹ùbÞ-ŸÒ~¼+¢÷N ó»šY±ÉÖÞœjˆàˆ­#é8•mnJðdƒyÖPw3–û] (öýªºãH5'#ݵ÷z–J·ÈIŸ¹+W “ÌŒÑÓþàY¹Ô߀·ôëI3rÝõ·üŽÖˆ„—´xF^é$ðËÃÜõÅ´(Öœ«1™¬Ï—h}_9¬RISÇŒŸÉ*j‰.¹b°úÙv±~7SÁ†•ðuè[žš–>+ëwé~èù»åîWòI8Ѐu·sšÇ —øÊî™J‰|¦Eÿ]+rw„3Xÿ3*ä˯Jºü߸޶Pö8L5RêÃôk{ŤãšÎôPÉÂ,e/ƒÞ¹q(‰”aÓoju*‰R.õŒ½Ý(šü¼C-¬ï»ûl‰"ÃQ¶5YA÷·w€Fõ Oµ¡IÔ9{¬¼‘JZº[ã§D3fððÛÍP-A(ôf޶Ä+PÛÓ=tíÅ3‘òsŸõ¹¸‹h›j&ÏÎíïžWÅ5çL~Ï‹ ãuÿ"âCPI°kl!XNñ*q†2œ[6¦88…ë¶`kÆà·ÓU 7Ô6Œ¦Æ³4òÈ\Y½G©§N·e”ŒuÒ~ó/±yNœúV_—Á¸œvêÅïa€w1Þ\Ådm,íòîBÛ"{ _(žÿ¸$ÄQ&Ö¢þ‚ ‘1eÉ@ÙZˆÖ’þBš‹_ÒàµCªÁ«œ=~ŠÙ]óa5ÃÞo.$Ï3™È–qêl6 Ù©_gNÔ5©ºé-|tî# EÞ-¡ªk°„-ÎIq\ž"vk ë"gânr»÷ ƒ™6#ç­³d–.6ãFçc²Ã÷›çëñä”Juž =þ˜¥&¼Â”=6?^'ztqÓâýƒJfp6d§Ö²zË‚‡‹‡}жÐqOj˜Öæ>Þ&º`QÈ7Äð8Õé|ÞbHø¡ûþûY]ký®nZ_@B&µæínŽÓqåቋ–æ§Ù/VHeÕÆ…>ŠÒ}c•uÉp$"L©Á=ÔáèJýìám;ÑÂÛzQOïm´Dn<øÆ†AýBŸíºC‘¢˜ôWMúŸ¼‘Ïæ_'P+Ô@¢ÀÃI"¯Œdæ‚ßX»FÔíÑ™ª;eÃ6”° îÜ:%€ Tªúxn‹* ï£›Ÿ§ÝZ4#¥ [o‡ŸòQ}Ë Òíc¯×Lö‡e-/°ðº!ëùa~Ã÷TøœÒ¾pÏo„Òs¶xÆdv¢€“º:ßLð¥WX±“1c÷·“{!©ÉŒÕ6˜’祚°ºøŽ+8iZ@‘&6öDUah0XfOà ;ˆý—«lÆ mO°¸a"Ö…‰½NZ0ü¨>½äæÜFHU2Zð÷QQÓäD©=vô×ÜÝçœùðÎ ²YÄfRí´¹”Ì*ô «c~ÿn¾†ß»ä¿ên;d~x/ E)(lÕz `èü„t,‹õÓ’©²~@û½Þ;oCQJ E´žÇ7òjsRöäBýtz¡\+Þ@ÊÍ›£V8޾ÛÍG%uR™¹ÿú’€X‡k’,‡¾“3É?=í9/ÔÈKHbrFœþ…Çk4¢yì fG6¼ú®ÙCtÜ\P©ii>?<Wð„KØÒõŒ.€pyñ\îW¥+k ï? eÍOg ¹£†”ml®Š7Wi³‚IforæÚÈõsøjÐ#û2®b8$/²ÇêtÆ> ’Œ`[ dûŠœ;‹·@ÊŸ'cÏ„þð}˜ÿŽÍˆêphë½ãÈŠ˜ k;Â?$KNüwÚ&-3 Œëøô:h¥qr¶hËn¢~ãNöÕ6ªŠ½=©zǃ:už…#¤›“áà…¡ ×Õ'uŸÏ÷TÀ¡4yÚ|‡“w{fclÑ«îbÉ ýò¬7‡¿/ÊÂâeÝvà—tHÜiôuWáõà4#ÆQ%Î=QnŽóÈ/¹€Ö½Ç¡‰h~zÚ1]Û±…û¨ŠR°ÚË&eû Gи¿§äNy jƒH_VÐ~_¾‹jeaÄÖD'Ç2¡PãÇç)~¦Ú=#Ôˆ£! ¿ª†ZÓl>–ì®2g¨é·Ê ϒ럿ՈɯL> stream xÚmteX]IÚ-ww;ÁÝÝÝ]‚;8ÈÁÝÝÝ!$¸ÜÝ‚»CÁ=ÈGwÏLß™ÛÏþQUk½^«6Õ{U &1 3 ´Ø•‰™•  ²7ssÑ0+2©­Üä\Mío—)"•&ÈÕø&o¤„3ÐÔä–4u}³Ñ´v(™:ØYl¬ü¬¼üœ¬o{VŽ:8óTAöÞU +ÐÙ~£$ÌÝì`W 7GG;ÐBèâàæltáX¾UøÏ™Ž^Î +kW­–º6ãßÀÌëß @貨ß6î@;Ç?²½…‚Îo…[üa«ji*erý£m­µ««#? ‹£¥)ð cv±d]YèÞŠ•[H8ØÿÀñùI‚œæoy±üÓ mÁ`Ÿ¤,A`‹?Û³psdуœÜ€r’ÿrxƒÿƬ€®.VvV>V^Ð ô4·fù#µ¦—#ðO’íØláçãèà°4µsú,o ¢‹©;àêìôóù‰ÿ>!²±,@æ®3 ÕÛ•üý ZþuV2uuyôY™YYÙ¬|ÿÙ¾]®…ØÎëoseS{ €EEYAQ^ƒáŸúÿ¥¸¸Ã[X&6^;/'€í­O>.Žÿªj úWU¬;Ë-|ÿ6µ7àtvyS%€öOÓþ;’²ƒ+È ý[0¬\¬oZy[ØþQHÿÅÿ£œþ7‡´›ÝŸ3 ý«yÀ[÷.EÀýÛ½=‘?f2ÿÿ¼LíAv^ÿà÷¿†ÚÀ¿¤ÿ¯pÿKÿ] le0±±ÿ‚\¤Až@ U«¹õ_*ù ×[üùª. ?ó› ÛÿpšÖ s[0ÐÅåMŠR@°Åÿ$•›;X€ÀV ×71š:[üøƒ6wsv~›ÓŸ7õæûï³%è­D Ðhޏ¼à`.jSÚ~_'FäÁ´?ÉÑÇ­uûêFƉg¹Ëü®Wß¶œˆ³à†7-WRuÌZ¸FJ 2<‘H*ŽÇÖO¼ƒ+ ólá sƒ 2?ò9<íôkaR,~Ƨ^ƒ²gï+ou©„%&05ÂpHîõœT`‰H+‹ªTŽèøpƒOUdíüÕøaçF:%Ym‚#2仚fhäõšNî°ª;0MæúÅQ¸æÂe]ëÏ͈tËyø;'ºØ­;D;!»‹£ói¯XÆ‘^¶FèçañS’HÖ‘Qññ§‚¸í–Íቲç û;fhGy—˜ÄÀ&ÇfµäÑÞåyùønŠp2[;«÷-ãìc‹K–WV†±¡CØ_ô-æ–õ$ˆ N É¥ ÄÏÖª}eæVn0¿DV³ãƒSß°5¦u"\-ɧéÂRÚXgž==‚Aä"ÉID‚©0¶¶Qä(š$„H“¤ZÙR?* ”Íj6gÒÃF²ôÇÑ`·A~‘¨t|b•D²°ycò>™0õe±|wÑDH²B#³Sp,Ž·#º<_›ó?Á&¾¶:계‚SXî›Èï) Ò;(×ød œCIøJd9SÇ„ÆB2‚fâèðˆšP®P.Ê®6e§*«Ø_•kc.ýŽMÚwL}à ©}Õ¤üÜLgSz©• õBI#ve*ß\*ÖxÍ«D¸^¼óAiñÚZp0;1 T®6Ü~õ ‚ü(«žƒsÇ•mlj†gJ%ø(Õ3¥@7ÝÊ0°…gù0è:&„á9XÚ0z—bÚ;Œ®&™ž°-ûRç’Çú‚*(â[àýÉú8,Ãûk;™º%ˆ–¹æ{º )Î!1æ—VèÆµB>„DÐM“ƒn3cò!zô4÷ù3Ïi³Òt]*œ 1lªH=‹ÛÒ7äJ ?åi.óµ|þas` ÉEÖ:^5~d¡—».´·ŠW¾|³j…Râ"3VÂGœQ^h´Æ¬ ?RIÚ¨H`ðx®lÆ¡ëu»qYT¡9}Z)MÿÓr&›ùyÒ]´‘înñ@mÝó™‚õ¤·R‚¾ªth­FJ¶f€‹Ðô{…dSl/ñƱ|4XÉ+2³¾ál¥¼eûH‡‹6¡ú&Èsxd5÷P*IÈl‘[’¥Ý¹“€-³[z²T5£:z6) ïd¼n¿– œÌÈÈ·ÜÌ^’Qõ®Z} ¡¨»,  <ìNË ‰Á“{´‰zjÛÌC'ù-O¼¶kÚéÖè•ýÂN*{4Æ«5·mý(ëõŠU·6µ»5žã“ ´!b'ºŽ`þ ˜ªF£¤çÝ…SBÚ~d;ÂÙxžÈgeÀŒÕ\`¼Öi¶üÚä!½â6òPÊ·Ï»V³žn½×ƒ²³I”të¦÷výD[-±´2ÙüÁœË¬Â«3\Œ²}V~»eÕ1ëa:FÉ_.‹Ù‡Á¸„dH±Š2(Wå"ã “˜Ü:ïØÐÔj òosŠŠ?7€Ín+6)^¯í®ýü/ÉråF…º§à膯l[y_îEÂØ¸³ã»W?fã9[už\göJ'•†B.JqÉE|Bé9vâûMÝ&žC¯”ª¬LwÝšÓ&ÙDëäÔ,`¶´r®(>”Ÿ””øˆµqYàæƒü»£_cšƒ¯\_è|–´Ô¶,@äJÔÚú”´!ðó$% ž„[ûü…ô\ Z«‹rò)SÐ"ü—tÀH…âò`?ó(U÷²˜\Ã¥4¶l¢¢ïÓGb`+þË¥™ª1-ÝpÒåòæ—¸h%r“µ”Å* ¸è@CzëüÅ Á;¨K^Þû \mÁ ïþBš:!¬½!Ê»µZ0«±¬¿U9h}ñmwz÷¶ÎÈ¥ Ûvò;‹^m{wúž¯¨w©.•¼ì 2}ämYKã¾_è|åÃ)0¹¶ÛÞ)†Öoí.àUSª`H”líÒFýOã„{ëG~|•q’'‚Ü•–±.ÏЫ4„»„,>iëæH:ÖWOÝ'1¨Â ¼³ûdß&ÍW kEêÇ¥ÛP«*Á»ýH§Ä=>³'Ù)ò‘öœâ͈@~°9©©&,– i”O墆1RuhV±qK¹vÂ|ë”g”ÿ§B.·0µ×¹aˆê ,>ÏRª`ËY¨ÎøGÖ”—\Aµì˾a,:Hƒ9lxÙ5Êñö9¢Eà>.Ù|Y¦þ —–NÆí¶byöƬ©·UÏíja>ËmùwiïlHA°Ó&ôc㙓“Üçü1p•?‰j¾f­þÒ`‰•`5åÇAúårês-21¼HRÍÛ}&×þÊ~NdnÈdüûWUB´& Cw'ßÈŽ„+cÏA-MeRp‹š}mÌÃùÝrø—9.Gß*mÇ&žè)†w ó°âNQ)ØÏî&F¹†§s(aåcË(‹-ybì;]ûv·ªÂU‘G×kjš‚9ÔýdÌÅGãÆ%ßbæ4úIŽ¢CÅ>ÑTQ—€ñ›èÌ,÷¼Nk×l¢ç`¡t÷wØ+úœ‘õß4—í–¼u­Ú²S¦Ó_·.¿Õb,II‡›W§Rá”(_ºŒúL2â¬uÝ úx•– ! lr¨Ÿ|#¨d”ÍH!<«”ºMöõ*‡(ž \&plá¾%"ö$”4`VWøam3KÈz¦©ÂÀiÛÆaŠ¢Z6)ؼc—Ýþá—ðF[˹ä%©ó$Q ÃDjØdêo7ëºÎí¦óþÞ¼XŸ…G雎Õ5.NöÌǨúßZ*jÕ¥ÓÓ ¡'[´Œª4{Š8‘_P¾µäÁ†§@ÜÉ·r[+Ý|eêñIµ*‰32ŠÄ7 ƒ£æîe8ý¬õšÓUexdÀÈÔ8fWn`‰gPU¶¿ø´wb–¯[âÐÈŒ^Tqwh·ûMâ«£»GBùÁu¢üVgI¯~¹æJSrغ(ªv‘m­®”¨ÍÌ´¬(6m8¡’ 9¼…ÎÌWå/a×±¾ÃmaøOïM¯Kg‘“6ïê§?—‡cBG5wвEp „ÚÑ—©l7‡~"ÚèÌMìL½}˜<Û³»Œ¸Þ…G°Q™wµ!ÃÌ_pÌÁ“i®äYjI™:¶>Îß¼O©e€Î•œÁo| â=·Å•¡n†Í$¼ªckYòæ®ìB§ü&¾¢!WtäÔ: '#^5ËiKl)]æ]O Fô)ÎÎ3 Ø·qn÷‰0S+Gqt§®þÎËÒ¤çzt÷)·ÛüNèÃôXQ¤pcò©åR°‰DP "BpH²¥Ð)JH -K[dòöÕúp]¡:Ømð‘ãÛÃÍ©¨™m3’ZYx03Àý,’2þ[ÞGð+öMë0qxb ¬Rˆ¢ö•³*õàqNMjaRýå|Ÿ²ˆi¦(ûÄУá±wt)°í7ˆ †ù3‚”è{u̵Žh a|Y™ÀL9OÕÌòõ#»³¥-vv¶;„¯X¦gâŒÝþJñ-rò›Í/Ú˜‰êÛ©À bÚ}’ÕÆƒê$)xûâ6û ç­$…Y*žzÌÞNÓ‰3˜qíÁßf‘ý³ å3Ç#u‘¾Aö]múÖW/¬RRÝk6üϾøšíÔ'šÂ–ÂàÈl3qN<€KÖ Ì£‡ªìÃÌxëKšÃnÖÝ¡ÿƒ÷U{e8ôG2"ÂÚP­|ø4 ‹<Úí@ž Òì¤ y p1Âæpþ&3äÑ62Èd”Ä+ÙnœQœ©,!•ÌÙ¤ÂTca•F½Ö‘sã“ Ñ´tGß cÕÎÀ NkXêvHÔõÅŠ× -³Lð§Ô…×%A,Ÿ$ ŒV‚vez¹)|ëI?\͉Ùܹ¤Ê$'ÿº( ,be¤÷¥È9»³ìV2¯Îµ‡¿‚R^ê½Øàsþ¡@q²pˆ²(ò‹¼ûúb ÉË„<ö1TÖö|žÉÖ•©’Ö[в°Š£ùèû ¶‹Þ»lŠÂhæñ¶Dšf¢ %Slv—Ç\º¢ Ò}ðs§ç¿>Âð×G¥ÇJ—$¶üàMì(ú÷g¢ø0íã¾ÙXªlíŠ6ç1¯¥‹1wªž j²tˆ$DáK<·V-ïõ^•CrÍ?w'PŠXdýôWì_¦j? ÚµJd…©ç ~ÎÀØ®mªÂä[:&Ÿ2«Ò¦çHŽ7ò¸1ØÎ-BéT³º~‡ÄBõ®¡FtǼ¨kYÀë×\SD.©É: DQ¼iX©Åwµ^"gôðÝA,…º~J†¾5wëÓoÂ÷;¿Ìù}>‹»÷”ó¹œmÙÜ´¹ :¢ã0Ž?«Ëþt»zó.…Ž•lþrð´VeÌpEPëùý,34@ŠŒxVCqd6V×Fæ¶-\I2}¸ÎT3[«?5W-lHsASf®×Èi—ç‹ói½õ‰VE²ï—Þh Ãv7¬ˆ˜çRÐ5k†ü‡¤DsË©:#3xÜ,“g%£Y\ü´²<uײüÓ*8¨[ŒýXèç8Øý+—›þˆ®É1h×ïHïæûPÔeÔÒ¬¹&§(82.rQcáÑÖ&MØ ëGÀËtXb\µvŒàË–(pì„/¥‘Ä„£ß;‡ç&?¿y®î­~érË‘h™ØÓ=è:ÃLifhðy¤ ›½‡ÕŸÂ~£'=‰pD²Ïíö£ŠÎÓCVà#´nP\VÃL^Vÿ˜Õ|[…¿²Ì$Gs–þõmÌ‚ŒU­E ›ã¼CÇ à»¤_#ì <€7yâ´"ü)‚V›¾âË—[5“®m ùdøHbLi½_¶?âB´mÀ´¢ÐØz™ùÎ6t­0¶G`àÝÆ}ÔåE}:aÿ ‰×ϪÙF®Ž¥K’nìɸš}YîW…-Yxüsiø†ëvŽ®Ò:F)²ÌCË3·Ã„ú*dYsɽ·‹é| Œ¤¸Ÿ– W= ç ’±UFQ¾#øÙ»îƒe¤¬ÇÖɇó€=ûµ°æ{¾ bœ3.»Hs|ƒ¬+ë™§Óôçé]Œ*¹"sõØ©˜ª¯M'·tSS(Íè¦Ð·ôu’kÚ'¯å.(Âmç´`û#Ê>M¢z©}²+sqÓZK%÷Ýý¹YÖ² çhä/aç±´›«]<è«÷[²ŽP“‰k”x³?§±æ?ðã+]©ŸÙ(…3ãò¬ÏS¿è©ma b¡J‰baNn«'|Ú7«Z“e{ánZÑ6¦C€»¨<Öý10ѹ۸‘»d¼üöùÑVÿ#Å-ô6y²rp~Ó½$p¸h|Áþ%f¼s#ÚÜMÄò’j„[kÚ(ZrÇX¾ðF@ÕÄTiþ¦¡:µ,>©ñ¸lì""]Œjb(}òŒØ)#«×-½ÒðpÙž|×TLH¬ÜÇRuû³U5ðàGé¾d¸±bͪöÞ<Þ ¥ ä1÷\qùXÝÅüP8ž}±Pà Ùè%ß ò®¡€»E =Úî†cŠ^Ÿ…÷w›Üw.UJ<šÃ8$çÂ]UsTåþþƒÇ¶M%0´´Õ³ÏøBÒJŸ(š8ž];0q´È§ÆU'‹¾„¼ü Û+"å²ÜÅz(Ùƒ»éùx¼0yÇŸÂéßùUðV[OÓw¬ý®6#ßp9@¡½šàSzÑ -´koÐkýizÆ­ŠòJOY°k5šÏŸx<FÒ´rWoè½zÅõÍצOª"¥j¦¨ù•R´í_áÖãò#¿UÃwžUd_ýŠFõ«~0c8Ïܬ¿aÑP¾}‚Vú6쭚ݽCb.Ï„J[;ÿÍÁØã7CbŸŠÚ.}Yuô_”Êýmõ ³ÞU>I1»@, Å•šO^ó…¯û˜涆E:Ïþ6Ö¯NûAìP -¹¦ÏÞY-ìÓ›Që&íÑ¢¾æ©‰Ó(ºÑ[v4Õý˜H d¿óY7¥3UÚ£Gqê«/Ù>fH­ ®§ê>$h&n]“\¥8 Mö‘=mOaoÏKrþ´¯îQ¸a ¾Rò'<å!žKJhM§} Û¹žFAÐûÜ`ë,ç$ÄEuX‹tsCãìmkHCgKŽ—î+ô¹‚— 2A<”e•x9»é!ZkáV ^䙽$KBãýt"X`›~4wZòò¡Šó3_¬$-~Ǭ“ôân;žØï*j/®Oâ*5h¤G¼%FQ%é^"5Õ‡ÏU yÎ!C]{;õª×!¸ëûý~ÇŒ—pØ®ž3›$ÙjÐf­nÎMÈ㢾ï…ÒÔc˜Rž#Œ&ä"÷Tª½KiMIΉBþ9?>œ¬Ù ;mÆíOµZвßzàã”w\ò;XĨUnú,ÅÖvç0™ý6¹kdcuÁ=UlEnìÞ!.Ñ·×\†ìeÙ&|-ñù& e7÷Ÿê¯N´nœJÐ"ê]÷T$úåº:Õ믻V,ˆ¬>KRž¶b’·€©”ŠÜÜíÓ 4*>Koê[t{¹øp»u¢K2û¤ qWWR{¤iGÜk ”2ƒåÎ’§Y¸œ§¢ùÓW•ëbúJ0iÙŒ5åì}p< ¹p4OûËbßÍÓÍy® 26ÃÏS8Ì¿„ z O.«†ÕŽJˆbW¥x²'Åûõ憭´Nd«v«Q·¸GD£n´³M ]i£üB*›f†ø¦ê n,Þ+ëz;Æ›m1¨ªs§Ž,3Ž&d­wÙ^’)ˆ®~ÀÐE,²Y‘ĘÉËÓs+ûâ;¦—m¿Of[œb»ÉÜ/â"´m§ìþ°’·hºG)Z”““¾µÒyp^+yŒ©+v“å´‘cÞ‰“nùûQL¡à÷Œ`œ¹“~˜ž¶riòã!ðåáù>ìœ#³ÖM·‰Ì9-Dxš3kÉï+ 5ƒÌGü¡ŒÇ…)gœ)’d³}L(BSÅÜÊâ?‚ÚÙ(†é‘ú‰~³~<(¬×ÑßbU ¢ò‰œ‰pã£è½>PSð^À}(ý¶÷$š6Ößy°ÿʆE©<àú# ¸ÂÇ9ŽH‹—ñ¢o{‘Õû¨°WÙ2k[ò  ·ÖùSîºQéZ}ʲAÊÐõìLh-L»¸1Ñ%F@¨¿F;ÒsZw%µ­ûÅ•vàxhæq‘$­}6fû²Ÿ~Ýž4GÒéPå.П^I<³‚+ ñÔ€]€¨¦^™wmïkñ»áE ÕŽÜ â 6‡ôßýd§T%&³;xë˵ünG›wjí*T60[vD8q-ê2¯à|öôؽšÈPÏ= þi².!â› s~„.&"H-¦ÃVÜ·9në·ÏZƒpË?Fl`÷É&£Ö;åNÇgeeF¬:òçO© Aj7åÃFNZ[1|yÈL#3}¾j×âsSNõž§äãöì 7¢J–ˆÃžùöô¬—f:ò:º_å\rÖï¡Ü@þêmÒqÇ‘`&)˜Ül8CØ,¥~§•ûwå$ÊÇêºÞXÑÉŸ>Âl!ƒ~ö>|þ¹qÄî[ÜOèÚ’½ßøÞ=ç~ü[Bj¿ä£mªåk̵ GeNµ°,V‘Û|//âwÙeG=*š^Ifª—Þ9Ѩd6¿nUê4—·ñ>h‹qP­©r>·h˜5ekQæjxgiŒÉP5¥†ñ•¿CØ9LæMî á¶âE~j`O› ე[«,‡D«ê-ý.ÒQ£$S™UCàµB•qœ™l„_l^ ©û¢oÜSÄŸèô„Yö‹‹K%=Âi`dAÙlƒœ¢hÔ4ôðüEÑûTžÜW³è7Æ;ñx÷d9gIeP C»ýjF%ÃH<òˆ6͹:lǃ’ô¬ +ypG»UYEñÞë¦sßßÙKôѧ©¯–c¸k;úñ 7D+éMéæ@+¶&FxThv8%& ìƒgPd/JÛo˜°¶d,ôlù|\Äî¾£[ë ¢‚'¦k”ò¯~}³˜27Dï¸AÅè6ßàu§5½îØ'MÝ2òTêèMn}C;ƒu[ÛFx¬á³i…ër.©Îß7¦Ä3.蘾‡¥xéÀ«D¨$ßÕ33MŠFÑÌzØ]·Àí 3©'Yߣ¬(õZp8wéܾÜà‰(ðlïeΙ"Ú}%(ºû< …“­QEÿ#8üaÿPŒ³wL-é€ViŒ¯n Å2Ÿ¾åG-ó~É„†_@ñTÃ7ö`ƒ‘‹9ÑÀKýVûÒþC.¥Àð9ä+Á «Ü|M Œü΄ÎVÂwËfÊD{“èuœ¸]®®ia£aNN gÝ+Åœïiôzß P¡‡R?d¶çíÕ«<} JLS…質ÒßCäN˜)/º¤ ­ôœ§ 'AFi…oËÎxÄûk;i‰˜Ã½BŽ;#²7&FyìÓ&V¹M­UöÈrEóEZ=´ ñûöå1®¾텑Lš°) QNœS?Ó‘ÅjéòWqXïu6‘ªböp(FdÎ#¢þã†A·7Êb¼¥KYŽìŒNÏÌš{‘${ùÎã ó„|=¾JÊrïpsÎ…X·ki4"Y£&,µ*² ¨Ô!Û=†š!]¡˜£òÄ>UeÀ‚PŠÙE#‡žµª‹ÁvÇ ì¶ç2qTáøÃBp©p=슮{õ=ÍúŒ,&KÔR|ŒŒÏVÞîÏÔLå߈åªaÆÏ*‰ŸòfðO‘:hÈ©ƒNz¤;[ÕPˆé ‘“ÃHeø–f­î¿ÒaGµÑ¨0àø(ŠèÝîú1g5Œ$èbJºÌÙróʇZmy%Ä`&"†á ¯¤fi|ÅA‡ 8ì¿ ŽN!œ¦äSÚ€¯ ¦l€cΑý$°êjn.ñcZ×øÑäºëÁ¶¢[öÜQµ â—ÈîþÚ\׸c¬òA$³ZÛ\aÅ©tl{z<ËÜhŠÙ§ß¡uùN‡T‰úß¿þ´L1†ªÚUý©*›SfËÏÁ¡J„Lø8‰! ûŠ”ÍÛ~¬”_Ûsà¾^fUPš2˜óm{#›¸rüöy/Ë+=ÚPªÉHJ©‘Ç@Ã`ÀHMZ]þ„Ï7w«Å…÷vÉ2ž‹I"ó‘™42OÜë”JÀcT¬ÉiǨòÅ)X™Là.t¿·ç2öE¡*ä³';}1©±ôîéV¼Œ>‹ìTÉ®â«1çd¸°Îk0ùóaˆVA«ø+­ôxP"¢–Z3%R`XI0ÁtPpQJCÂû-Ê,½ÐB•ïa™ƒýňpvl0´ `Ó/\ñA!: r¼Ãk`Èq±wÃØRx„iø.ŽÓmÿ~I»‚ö)>}DÞmÕ¾¼D”¾ÙŒñÖ½d™¿¹ü•jyhDá¹x‹¥” iˆSt|ýPÌf÷޹ §l)X—fÑisf<ÒßIÈ[Q%Ò~WbD9æ1É1qз¬ô}HJ»ËΖÛN‚0ý"E´×«ú¶Ô”‹[¹8g×…-&Ÿ³˜Ä±°¾©P܃à=ý¹ù‡œŠ©ôå+­ŸÞØÑ•…{= ÜÌ\°ÔÑc4‡x,Qèš3}.æŒ×gáèZØKù[pÓ ‹ËÇ/”R[=¦ßYžS»^-ôiÓ[¤ÇÒ^~Ïúä õà=9«®‘OÌãóli)fUƒ ywEŸ ¡'w‰Ù=_ÀŽ7ïOsì8í®rxÿS£P endstream endobj 2992 0 obj << /Length 696 /Filter /FlateDecode >> stream xÚmTMoâ0½çWx•ÚÅ$ !Ù ‘8l[•jµWHL7IP‡þûõ¬V=Mžß̼ñ s÷ëu;ÑU··õÈÙ›=w—¾´“ì÷îÝÝå]yil;<[[Ùj<=?±×¾+·v`÷Ù&ß´õðàÈ›¶<^*;²~&ûQ·‚>ìþÝþ”MS >Ù_êãP·ò{=éÇsæ@öd”ôÇöçºkŸ˜xäœ;`ÝVY×`Œs4½JaÓQÜ¡n«þª‡í¡.’Uu9\ßèY6î>¼ý<¶Ù´‡.Z.ÙôÍž‡þ“4>DÓ—¾²}Ý~°û¯ÒÜÑör:-d0­V¬²WÑÍÿ¼k,›þ8ãóþy²LÒ»ðºÊ®²çÓ®´ý®ý°Ñ’ó[Å*²mõíLrŸ²?ŒÜÔqù¥ã• â5F8@ šˆ=@Šð)&°  È8Ô¹€ÂÅRx u€Dº\j2H—†ª¡ÐVÁ¹0CzL]ø Âb°ct‘I ©g$`htÑ‹0œÆ\F„áŒ0ä†sê‡á jd< —Iê6œ»õñzgóñºË»þê W ¤qÈ’£+—Ÿ#ö•ñÌÇkÄÞ .‰bªsré…¤šáæÄç†bïmŽXú¾„Kß7ǵHß7Géû„û¾nb§>&jÊØµäuœ¯¼ú•ñ1ÜV™÷•âÜãâµÇ‰Ou$ÕŸqWèS/%1{\øxB!€§ÔK(hH©—TЖ枃»J©Ïϯv×ÜëÁ=küÒ2ø¥UðKÏ‚_:~é$ø¥Óà—ÖÁ/¿Œ ~™Eð+7¿èË¢/ ÿlì¡ÛÒ(/}ïö -+ZXukoûìÔE?Z„ãæÅÛKýqíƒÄ endstream endobj 2993 0 obj << /Length 695 /Filter /FlateDecode >> stream xÚmTMoâ0½çWx•ÚÅ$ !Ù ‘8l[•jµWHL7IP‡þûõ¬V=Mžß̼ñ s÷ëu;ÑU··õÈÙ›=w—¾´“ì÷îÝÝå]yil;<[[Ùj<=?±×¾+·v`÷Ù&ß´õðàÈ›¶<^*;²~&ûQ·‚>ìþÝþ”MS§“ý¥>u;áà¾×ÃÑq~:fc_0F)l®»ö‰‰GιÖm•u f8GÓ«6•ê¶ê¯bØÒ"!YU—Ãõžeã.ÉÛÏó`›M{è¢å’MßÜáyè?IáC4}é+Û×í»ÿ¢Ìl/§ÓÑBãÑjÅ*{pÝìϻƲéOÞ(ïŸ'Ë$½ ¯ªì*{>íJÛïÚ-9_±eQ¬"ÛVßÎ$÷)ûÃÈM—ÏñP:^9À ^`„ª‰Ø ¤Ÿbr š€Œ@ ‘{@(\,…RH¤Ë¡&€ti  mœ+3¤ÇÔ…Ï ,;F™$Б€‘zF†F½ÃiÌeDÎ(ó0œAº1a8§ÎyΠFÆÃp™ nù[¯w6¯»ü·ë¯Îpµ@‡ )9ºréñ9b_iaÏ|¼Fì-ÐÐà’(¦:×ù(—nQHªY^`nA|n(öÞæˆ¥ïK¸ô}s\‹ô}sÔ‘¾oA¸ïë&vqêcâ ¦Œ YK^ÇøÊ›!¡_Ãm•y_)Î=^ ^{œøTGRý÷w…¾1õR³Ç…'ÄxJ½„‚†”zImiî9¸«”êðøüj'pͽܳÁ/-ƒ_Z¿ô,ø¥ãà—N‚_: ~iüÒyðËÈà—Y¿2qó‹¾,ú’ðÏÆºíŒòÒ÷nЪ¢5Q·ö¶ÍNÝ Yô£58.]¼½Ñ»á‚ò endstream endobj 2994 0 obj << /Length 695 /Filter /FlateDecode >> stream xÚmTMoâ0½çWx•ÚÅ$ !Ù ‘8l[•jµWHL7IP‡þûõ¬V=Mžß̼ñ s÷ëu;ÑU··õÈÙ›=w—¾´“ì÷îÝÝå]yil;<[[Ùj<=?±×¾+·v`÷Ù&ß´õðàÈ›¶<^*;²~&ûQ·‚>ìþÝþ”MSÏ'ûK}êvÂÁ}¯‡£ãütÌƾ`ŒRþØþ\wíœs¬Û*ëÌpަWl:*;ÔmÕ_Ű=¤EB²ª.‡ë=ËÆ]’·ŸçÁ6›öÐEË%›¾¹ÃóÐ’‡húÒW¶¯ÛvÿE™;Ù^N§£… Æ£ÕŠUöà ºÙŸweÓŸ¼QÞ?O–Iz^UÙUö|Ú•¶ßµ6Zr¾bË¢XE¶­¾IîSö‡‘›:.Ÿã¡t¼r€A¼&ÀT±H>Åä4€"÷€P¸X ¤H— BMéÒ@5Ú*08WfH© ŸAX vŒ.2I ##õŒ .z†Ó˜Ëˆ0œQæa8ƒtcÂpNò0œAŒ‡á2 @݆s·>^ïl>^wùo×_áj4RrtåÒãsľÒ žùxØ[ ¡Á%QLu®óQ.Ý¢T³ ¼ÀÜ‚øÜPì½ÍKß—péûæ¸éûæ¨#}ß‚pß×MìâÔÇÄAM²–¼Ž3ð•7CB¿2>†Û*ó¾Rœ{¼@¼ö8ñ©Ž¤ú3îï }cê¥$f Oˆ#ð”z  )õ’ ÚÒÜspW)Õá9ðùÕNàš{=¸g-‚_Z¿´ ~éYðKÇÁ/¿tüÒ:ø¥óà—‘Á/³~eâæ}Yô%áŸ-tÛå¥ïÝ:¡UEk ¢ním›º²èGkp\ºx{)¢ÿÔÞ‚÷ endstream endobj 2995 0 obj << /Length 900 /Filter /FlateDecode >> stream xÚmUMoÛ:¼ëW°‡éÁ5?$R. ¤d9ôMðð®ŽÄä ˆeC¶ù÷³k›m‘CŒÕp¹;;†wŸ~>Î|¿Ž3óEŠ_ñ¸?O]œ5ß¶‡âî®Ýwç]Oßcìc]=~?§}÷Oâ¾yhÆáô9%?ŒÝ۹׬“B|Æœ‚>âþ)þ;ëvÇw%gÏçáí4Œ3‰ä§áô–’>\ ‚‚6ý§ã°¿ õEJ™€õØ7ûÆ8ó 1¿’{Æ~ºðÏ`W(-ú¡;]¾è·Û%=°ùñýxŠ»‡ñe_,—bþ+-OÓ;qü\ÌL}œ†ñUÜÿI--=ž‡·B«•èãKª˜æÿ¾ÝE1ÿpÆ[ÎÓû! Mߊyuû>Û.NÛñ5K)Wb¹Ù¬Š8ö­iÇ[ž_®¹uÊ•MúÑzQ­Š¥Ò)V†€Ú(TØ€àx¿àÞ¢ žjy‹°°!ÀÐÔ•µZÔÀ2àP="¦ZdÔ0\ÃG©R\¡·”).–2*ÎШa!„U¼Ä,†³ÔÛHð° `+jÐÃ.¸5Nα@èâ°èÐVK-àxŸ%ô˜Ü3š% A°YÓ€z¡ÎšÔ>kP#¬³¦õ™5m0W£oš¦Ã¾žj­®§Üý·.†ÐZ¡ŽT$X/©)n)æ#W—„o(æ“oÀRZÞ $K¢p4’ŽZ¶-bâ\­1¦Ü°Jä æP"Gñ‘XÔQ¬‚i/8ºkÉ^€ÂZqŒ:ZsŒ½š9”d š­Bù Ž)ßsLù-ï7½æx˜ÏJ›¡¾Ò`¯ažÉ½)f¥É$†µ’1™¸ dÑŠcªCZCù<£7Ã3JÊgózÌnøþHȰíáÌYÉšäTœ¯a…Šï¯Æ,_»œ-Ÿ—Oë87Ë}êÛKÔ´Ü—Ll¹oKñšò+Êg­JÌâ.¾GZyóº‹Vðc­48¸’ï¼äØWtù]Í:P~`áŒñ±–rZŽq.nÍ1]Ç ÇàSÿæ/©ßP•ýïuö¿7Ùÿ¾Ìþ÷Uö¿·ÙÿÞeÿû:û?Èìÿ ²ÿƒÎþ&û?”Ùÿ!dÿ‡&û¿1y–¦¼ÍH·œn5þ¹ã)º½ÝyšÒ“Bï½x#†1Þž´Ãþ€]ôGoáõñÅ×Mñ?®Xê endstream endobj 2996 0 obj << /Length 900 /Filter /FlateDecode >> stream xÚmUMoÛ:¼ëW°‡éÁ5?$R. ¤d9ôMðð®ŽÄä ˆeC¶ù÷³k›m‘CŒÕp¹;;†wŸ~>Î|¿Ž3óEŠ_ñ¸?O]œ5ß¶‡âî®Ýwç]Oßcìc]=~?§}÷Oâ¾yhÆáô9%?ŒÝ۹׬“B|Æœ‚>âþ)þ;ëvÇw7{>o§aœIä> §·”óѲH˜ø´åŸ8‡ýøU¨/RʬǾÙï0ñ˜_xˆù•ÙË0öÓ…ŒxµBiÑÝéòE¿Ý.‰ÍïÇSÜ=Œ/ûb¹ó_iñxšÞ‰áçbþcêã4Œ¯âþfiåñ|8¼E°²X­D_RÁ4û÷í.ŠùGÞRžÞQhúV̪Û÷ñxØvqÚŽ¯±XJ¹ËÍfUıÿkM;ÞòürÍ­S®lÒÖ‹jU,•N±2Ô@  "À–,Àû  ð õTË[<€5€ €¦¨¬Õ –€ê1Õ"à†á›×cvÃ÷GÂ@†m¯gÎ üKÖÄ §â| +T|5f©øÚÕàlù¼xZÇ1¸YîëPß^ê ¦å¾dbË}[Š×”_Q>kUbwñ88Òʘ×]´‚k¥ÁÁ•|'à%Ǿ¢ËïjÖò{ g䈵”ÓrŒsqkŽé:n8Ÿú7ÏxIuø†ªì¯³ÿ½Éþ÷eö¿¯²ÿ½Íþ÷.ûß×ÙÿAfÿ•ýtö0Ùÿ¡Ìþ!û?4Ùÿɳ4åmFºåt«ñÏÑíÙèÎÓ”^z­è¥À1Œñö öì¢?z ¯ï.¾~lŠÿP}éL endstream endobj 2997 0 obj << /Length 900 /Filter /FlateDecode >> stream xÚmUMoÛ:¼ëW°‡éÁ5?$R. ¤d9ôMðð®ŽÄä ˆeC¶ù÷³k›m‘CŒÕp¹;;†wŸ~>Î|¿Ž3óEŠ_ñ¸?O]œ5ß¶‡âî®Ýwç]Oßcìc]=~?§}÷Oâ¾yhÆáô9%?ŒÝ۹׬“B|Æœ‚>âþ)þ;ëvÇ÷zö|ÞNÃ8“È}No)ç£e‘0ñ&hË?q:ûñ«P_¤” X}³ßa†c1¿ðó+³—aì§ ñ j…Ò¢ºÓå‹~»]›ß§¸{_öÅr)æ¿Òâñ4½ÃÏÅüÇÔÇi_ÅýÌÒÊãùpx‹`!d±Z‰>¾¤‚iöïÛ]ó¼¥<½¢Ðô­˜U·ïãñ°íâ´_c±”r%–›Íªˆcÿךv¼åùåš[§\Ù¤­ÕªX*be¨-€@E€-X€÷@à-ê©–·xkM PY«…@ ,Õ#bªE†A Ã5rEqIø†b>ù,¥å½A²$ G#é¨eÛ"&ÎÕcÊ «Dž`%r‰EÅ*˜ñ‚s »–ì(¬Ǩ£5ÇØ«™CIªÙ*”¿à˜ò=Ç”ßò^pÓkŽˆù¬¸ê+ öæ™Ü›bVšLbX+“‰«@­8¦:¤•1”Ï3Jp3<£¤|6¯Çì†ï„ Û^Μø—¬‰ANÅùV¨øþjÌRñµ«ÁÙòy9ð´Žcp³Üס¾½ÔAMË}ÉÄ–û¶¯)¿¢|ÖªÄ,îâ+pp¤•70¯»hÿ8ÖJƒƒ+ùNÀKŽ}E—ßÕ¬åöÎÈk)§åçâÖÓuÜp >õožñ’êð UÙÿ^gÿ{“ýïËì_eÿ{›ýï]ö¿¯³ÿƒÌþ*û?èìÿ`²ÿC™ýBöh²ÿ“giÊÛŒtËéVãŸ;¢Û³Ñ§)½(ôZÑK7bãíA;ìØEô^ß]|ýØÿs‰éQ endstream endobj 2998 0 obj << /Length 699 /Filter /FlateDecode >> stream xÚmTÁn£0½óÞC¥öƆ@LE"¤¶­šhµ×œ.Rˆ$‡þýΛ1i·Z)Aãç™yoÆ7?ž·“¬î^Ý$º×êźËP¹Iþsß77EW]Ž®=?:W»zÜ==¨ç¡«¶î¬nóM±i›ó%oÚêýR»1ëÿI+÷Ö´Ÿ)àQ·;÷{ÒWÃ`‡ ý4òvÍùö¿o)Z«ëZqê/7œš®}Pæ^kMÀº­óîݧ`ê¹ÕtTshÚzðÔ+ä&TuSýŠŸÕ‘ @ñöãtvÇM{è‚ÅBM_hót>XÙ]0}j74훺½ª"t{éûwJË¥ªÝšÑ¬û£SÓïC]·w½S!¯¨©ºÚú}å†}ûæ‚…ÖKµ(ËeàÚúÛž‰¥äõ0æ&”«çx˜™Y°F\20/0–b“Ò# “!Ú‡\§)&q)€% 1Ϲ‘NÐÔ"Û‚%”’4¢81`rÈH%ÃDdè‘åÜ#C ýйk Ю%£íºÀÜ"l é%²Ë€ìR„Q ƒF'b=:SýÙäøuX¤ð$”Qúó:ú\C¼–AfpGÇR~m%^!N%ί$†h³³&„ÕšñR 󛣿#Æ¿p'XϾ¬½>ÿ‹A£Iä Â}3N¸h2Ž5ó¯gNÑE'b«£œkýkåØ¿sè ý»¢%Æ|Vâ ¬áž!ü°¡äÀË3™¬?Ðfc91˜ÓŠ—9Ç|u 6ãZÖcW‚Cƒåƒabî ýd1×®eFæ-9žAg깟ú÷Æ3•ZÆ=üI=ú¤ž ç6-Ä7p¥Ìçœã?)pe…øÆgT<ôŸ«?}øpq¹\¯ƒê2 tSð Ä·¾ÿ¦u×KªïzTñŸo·ñþÄê© þ…çr{ endstream endobj 2999 0 obj << /Length 700 /Filter /FlateDecode >> stream xÚmTÁn£0½óÞC¥öƆ@LE"¤¶­šjµ×œ.R’Cÿ~çÍ8M»])AãÇ̼7ÏÆW?·“¬î^Ü$ºÕêÉÝi¨Ü$ÿ¹ëƒ««¢«N×ï«]}~;Þ©Ç¡«¶î¨®óM±i›ã %oÚêíT»sÖÿ“Vîµi/)àQ×Ïî÷¤¯†¡³Ã„~‰ÏÍñ¾½S¨  8ù—ƦkÕZ°në¼;@úL=½šží›¶¼õE UÝTG¿âgu P¼}î°i÷]°X¨é½Ã;k» ¦C톦}U×YoO}ÿæ Aé`¹TµÛS7š÷~wpjúm®÷Ïï½S!¯è©ºÚý®rî}uÁBë¥Z”å2pmýÏ;KÉËþœ›P®žãaffIÀqÉÀ¼ ÀXŠMJ0Lf„hr¦˜dÄ¥–€ÄP<çF:AS‹l –PJÒˆâtÆ€É #• ¡G–s =2ô+æ¬ (@»–Œ´ës‹°5¤—È.W PL²KF1 :;ë³3ÕŸÝ@>€_‡E OB%¡?¯£Ëâµ 2ƒ;:–:ðk+ñ q*q†x%1Dëœ5!¬ÖŒçj˜ßDÝ01þ‰;Ázöiíõ™ø+&‘„ûf.œpÑdkæ_ Μ¢‹NÅ0VG9×úmåØï9t…~ïÀŸh‰1Ÿ•8ƒk¸g?l(9ðÃòL&…ë´ÙXN æ´âeÎ1ŸFAƒÍ¸–õØ•àÐ`ù`˜˜{B?Y̵k™‘yKŽgЙz.ä§~ßø`¦R˸ç‚?©çBŸÔsáܦ…ø®”¹âœsü'®¬ßøŒŠ‡þsõ§.®—û : ]|ñ-€ï¿iÝÇ5Õw=ªøÏ÷ÛùÅê¡ þ‰Rt¦ endstream endobj 3000 0 obj << /Length 700 /Filter /FlateDecode >> stream xÚmTÁnâ0½ç+¼‡Jíb'$8B ‘8l[•jµWHL©$Q€•ú÷;oÆÐ.Z ¢ñó̼7/Žo~<¯GYÝmÝ(º×êźÓP¹QþsÓ77EWö®=>:W»ú¼{xPÏCW­ÝQÝæ«bÕ6Ç;J^µÕÇ©vç¬ÿ'-Ü[Ó~¥€Gݾºß£þýÏÖ#úiä½6ÇÚ¿ÞR´V—µâÔ_n84]û Ì½Öš€e[çݺÁØs«ñYÍ®iëÁ P[È L¨ê¦:ú?«=€âõçáèö«v׳™¿Ðæá8|²²»`ü4ÔnhÚ7u{QEèúÔ÷ ”æsU»5£Y7{§Æ×C]¶_?{§B^QSuµ;ô›Ê ›öÍ3­çjV–óÀµõÕž‰¥d»;ç&”«§x˜‰™°D\20-0–b“Ò# “ !Ú‡\§)&q)€% 1O¹‘NÐÔ"Û‚%”’4¢80`rÈH%ÃDdè‘åÜ#C ýŠ©K Ð.%£í²ÀÜ"l é%²Ë€ìR„Q ƒÎNÄúìLõ¾Èðë°HáI(£$ôçuôµ†x-ƒLàŽŽ¥üÚJ¼@œJœ!^H Ñ:ggM«5ã9¤æ7F7ÌFŒãN°ž|[{}&þƒF“È„ûf*œpÑdkæ_Μ¢‹NÅ0VG9×ú×ʱçÐúwþDKŒù¬Ä4XÃ=CøaCÉ–g2)4X( ÍÆrb0§/sŽù4êlƵ¬Ç.‡ËÃÄÜúÉb®]ÊŒÌ[r<ÎÔs!?õïf*µŒ{.ø“z.ôI=ÎmZˆoàJ™+Î9ÇRàÊ ñϨxè?Wúðáâr¹\Õiè¦àˆo|ÿMë.—Tßõ¨â?ßnçû«§2ø Ý7rX endstream endobj 3001 0 obj << /Length 701 /Filter /FlateDecode >> stream xÚmTÁn£0½óÞC¥öƆ@LE"¤¶­šjµ×œ©D’•ú÷;oÆiÚí@ãç™yoÆW?×£¬î¶nÝjõäÝi¨Ü(ÿ¹éƒ««¢«N{×ï«]}Þ=ܩǡ«ÖóU±j›ã %¯ÚêíT»sÖÿ“î¥i/)àQ×Ïî÷¨ý³µC;²ÃH#ñ¹9¾Q·=E€ºŠ“¹áÐtí2·Zk–mw{H?cO¯ÆgA»¦­¯Am¡(0¡ª›êèWü®öäŠ×ۯÚ]ÌfjüD›‡ãðÎÚn‚ñÃP»¡i_ÔõEÁëSß¿9HP:˜ÏUívÔæ½ßì›ëcÿù½w*äµ=UW»C¿©Ü°i_\0Óz®fe9\[ÿ³gb)Ùîι åê)^fbæ,— L Œ¥Ø¤ô ÃdB@ˆö!×iŠ @F\ ` H ÅSn¤4µÈ¶` ¥$(N' ˜2RÉ0zd9÷ÈÐ#C¿b*À’€´KÉ(@»,0·[Bz‰ìrÁÅ »aà³±>;S½nòü:,RxÊ( =¼Ž.kˆ×2ÈîèXêÀ¯­Ä Ä©Äâ…Ä­svÖ„°Z3žCªa~atÃüaÄø'îëɧµ×gâ¯4šD¾ Ü7Sá„‹&ãX3ÿBpæ]t(†±:ʹÖVŽý7‡®Ð;ð'ZbÌg%ΠÁîÂJü°<“I¡ÁúCm6–ƒ9­x™şQGÐ`3®e=v!84X>&æžÐOsíRfdÞ’ã t¦ž ù©ÿn|0S©eÜsÁŸÔs¡Oê¹pnÓB|WÊ\qÎ9þ—WVˆo|FÅCÿ»úÓ‡×ËÇ}P†® ¾ƒøÀÿß´îãšê»Uüðýv¾D±z(ƒ¿Çt~ endstream endobj 3002 0 obj << /Length 700 /Filter /FlateDecode >> stream xÚmTÁn£0½óÞC¥öƆ@LE"¤¶­šjµ×œ©D’•ú÷;oƤÝj¥Ÿgæ½y_ýxÜN²º{q“èV«'wìÎCå&ùÏ]\]]u>¸ötï\íêq÷x§‡®Úº“ºÎ7ŦmN7”¼i«÷síÆ¬ÿ'­ÜkÓ~¦€G]?»ß“þíÏ`‡ ý4òž›Ó;íßR´V—µâÔ_n86]{§Ì­Öš€u[çݺÁÔs«é¨fß´õà¨È L¨ê¦:ù?«€âíÇñä›vß‹…š>Ñæñ4|°²›`ú0ÔnhÚWu}QEèöÜ÷ï ”–KU»=5£Yïw§¦ß‡ºl?ôN…¼6¢¦êjwìw•ví« Z/Õ¢,—këo{&–’—ý˜›P®žãaffIÀqÉÀ¼ ÀXŠMJ0Lf„hr¦˜dÄ¥–€ÄP<çF:AS‹l –PJÒˆâtÆ€É #• ¡G–s =2ô+æ¬ (@»–Œ´ës‹°5¤—È.W PL²KF1 ˆõèLõ¶Èðë°HáI(£$ôçuô¹†x-ƒÌàŽŽ¥üÚJ¼BœJœ!^I Ñ:ggM«5ã9¤æ7F7ÌFŒáN°ž}Y{}&þƒF“È„ûf.œpÑdkæ_ Μ¢‹NÅ0VG9×ú×ʱçÐúwþDKŒù¬Ä4XÃ=CøaCÉ–g2)4X( ÍÆrb0§/sŽù4êlƵ¬Ç®‡ËÃÄÜúÉb®]ËŒÌ[r<ƒÎÔs!?õïf*µŒ{.ø“z.ôI=ÎmZˆoàJ™+Î9ÇRàÊ ñϨxè?Wúðáâr¹\Õyè¦àˆo|ÿMë.—Tßõ¨â?ßnãý‰ÕCü_er¨ endstream endobj 3003 0 obj << /Length 701 /Filter /FlateDecode >> stream xÚmTÁn›@½óÛC¤äàx ^"Ë#ùÐ&Š£ªWÖ R Û•ò÷7³ÄiSÉF³™yoÞ.{õía;ÉêîÙM¢[­ݱ;•›äßw}puUtÕùàÚÓçjWowêa読;©ë|SlÚætCÉ›¶z;×nÌúÒʽ4í%<êúÉýšô¯¿‡Îúi$>5§7JøòN .€âäŸn86]{§Ì­Öš€u[çÝÒÁÔÓ«é(hß´õà5¨g( L¨ê¦:ù?«y€âíûñä›vß‹…š>ÒËãixgm7Áô~¨Ýд/êú"‹àí¹ïß$(,—ªv{êFóþØœš~™ëãýÓ{ïTÈk#zª®vÇ~W¹a×¾¸`¡õR-Êr¸¶þ牥äy?æ&”«çx˜™Y°F\20/0–b“Ò# “!Ú‡\§)&q)€% 1Ϲ‘NÐÔ"Û‚%”’4¢81`rÈH%ÃDdè‘åÜ#C ýйk Ю%£íºÀÜ"l é%²Ë€ìR„Q ƒF'b=:S½îòü:,RxÊ( ýy]Ö¯eÜѱÔ_[‰WˆS‰3Ä+‰!Zçì¬ aµf<‡TÃü&Âè†ùÈñOÜ Ö³Ok¯ÏÄcÐhÙA¸oæÂ MƱfþ•àÌ)ºè$P cu”s­ßVŽýžCWè÷ü‰–óY‰3h°†{†ðÆ’?,ÏdRh°þP@›åÄ`N+^æóiÔ4ØŒkY]  –†‰¹'ô“Å\»–™·äx©çB~ê÷f*µŒ{.ø“z.ôI=ÎmZˆoàJ™+Î9ÇRàÊ ñϨxè?Wúðáâzù¸ªó0ÐUÁwßøþ›Ö}\S}×£Šÿ|¿—(V÷eðcWtÓ endstream endobj 2954 0 obj << /Type /ObjStm /N 100 /First 1020 /Length 4119 /Filter /FlateDecode >> stream xÚí[ÛnG}×WÌc ³ï7ÀXÀ²ãÄk[V,ÇWä’ÆcŠ”IÊqòõ{ª/ä 9‹’Ö ,{zzzº««NUWU·82(SñJe+¡U\%­¥Š¯TT •QÍ+k UD傧Ь‚TQ•à–Æk] ìj$%QÐ ®m$á*aB¤á+á$1²Þ8j •œúŒ Ž3–j±F„@¬UBcËyÔD¥4'ʘHÓ¨©J MüYMµØf*m ƒ”F âÙºÊXû…ÊJImx´ZsÌá‰Mü9SYp®r`AlI –cZ˜°BxÔÕ ì±—õÉ¢ú … ©¹2¤týh!0sô{PÝ¿_±£Šý4}5­Ø£ê‡ËáY=0êÕ¿þµ‡ÿ·g*€¤œ2'ãÐ(»ëc"Ü!.@(xL­2`=10&gðÌmâî˜(êÀ*(òãYJË4â;©£ Áý@Ój/H?PZ|_$àК{A‚Ûòæ{fp “VÂÖ<­ÉùQéð,äv&ô]¦Äª@´‚KX½æ¾b`ŒÛ΃åÿ ¤8¥V@( žÜw¢0_å)â&„Sß 9°ËúAÌvà 9nø.ou]º»_¡ˆ»p«Š 9@Jò}W¨j€d¹B‘" ¸ês˜ú‘°“!/PF„ õ Œ¨{ðMA”`hŽ—{ûî="2ä°•ç¿“«ñø·Òùñt²ˆD›”‘ÅQ‘OP&FèÈgÓ“£ìUìðÑ㊽ª¿.ªHãƒÇ ‚•|phU†#y Z,ê_7º€žQb; t«fý:%rcøó Mˆ%6<^h2È͉<¦ulØØ¡êõ–Hb*dÊÆFÙà…1ÀWŽš×*jiH»Y6ñÓé²£l*{j%\Æ@ÝÁé‚#BÖ†ž´iDp¢:]<µbÛKÅæ€úR‹Œî¢û½‡K}èRØÂ]º<öžÖºÖ m4Cì›iÓUÆ|ëZö÷zuÅí*ö54]NÊxÅg‘vžôÒ2¤-81b_´Çq¹ßr\®Ó1C¡Mí… º46ñÈ%£tƒáex ~œÇ»ÏJh^Qô¾Œ#·›Çäëoü?»Ò¿ÝGì6®ôÝ9° ¶Sne‘o™@¶û$ 2µ{ëñ=ú–~e\©;§S[n—NEZt×H3t´åLï›wêiÑ8“ûÑÝɰ|W.%BkêD)8:Ü…PÈ“ª|#‡¬rÙ~“o>ȶ¦í¤d  •ÇP^•Kò,Ô9Ý¢R´%wËÔ'±äáyu)#ÑTæ&\ôû,bŠ$ÿHÑHX #ذ¢’Ã* 7t‘>¢'ÏîE)¨´Á†OB>mk(€x2¶„* r„Í1(R’À&ÏE2ê‘·äí(ô÷]eC5á®”Q‘­·™ÕsLZË/¯U ¾ò‡; »ÑXt·.(oëÝ"€i*;»J:‹=­%MÇÒûhŒ±ŒŽ!§2õÈ¡` KÙ`2ÍæÙ%¤—h?ެÑÈddWÙO sbJåbiKÇz!æ7œS)2Oˆ /"£°+ â‘=MÉŒ•&²@YNði*óžh8R/…ÜZ6 Óš s³,è«Q*eÙˆ8z™Ú”(}ÛÔF*¿¤£n¥6%£¸«Ô¦Ði¦6Ä+ý! d4½™ hÄwh¿ifSø^òÑÈ`"n{Á¹™•þ1õËïÊñiŒ‹ü6ñI1ìï$õÿ"IEŸxðïI]ô¯pUÂ,,lV||X×b¼ ìduCÇêùÉlt¹˜ÎÒ±ÇÁðoŽÞ=>Üýχϟ?/ÆÃ³y¥Sýýé×êÃ=%«{ñï?\ÓþkÌOêÉ‚6‰{ìáðòçztv¾ ÔiÑ4ôîž —OÃñèäÁäl\£ G‹úâ5pØcoó(­ˆœgtÂò;›ÕÃE=cãz>ÿGâãñ£%ý™‰W/ÛçLÛ{ýËÃWGo¢`®[.‘ÅNÜ‘X^lk8›Mÿ8ŸN?Íèm[0Çwìçç‡oÞ¿‚ùnÁ¤.’Ñß²îFa~«d›Šrry^<}ûËkRÔÑ»mˆ”øýa‘;4+ ÝÍÒ|»ªæ°¿ÑüÓÅpqÎŽ‡36]ŒÆÃÙšz!ß?|ûôÝOQÈmÖh #ýES¢@F{2†~s×ðäÓ|<œŸ¯‰gw²ÉÏÞýÅÛb“Š“xHé„§„+Ü…xö¶*ÜÉ¡<:xöÓƒ7ÿ<]_ÍŸO'ÏϮ¶(“\¦BŒÁ*ôB4 4MaqMaµk Ë—¢6‹´MQ°}ö=b?²Çì§x¦þoö”=cÏÙ{ÁÙ/ì%;b¯Ø¯ì5{ÃÞ²wì=²áÅe=›'§€êd4ZŒÆ§õ5v1;ž Oêd#T‹Ž+V?Õ‹e3êéÅ ;™Ž§”CvÊjÙeõç«á˜Õ_OÆÃ ö‘}}©ÙÇéÕŒ-]ýÙÕh<®/¦‰ê9;ÿóò¼ž°û}bãè`Ø›°ÉhR³ÉÕÅ1XMØ”MÑpÉ.‡³zÇÆZâòªtMOÙåøjÎ>³ÏWõ|1›Ÿ¯¦‹úôxœ*iÌ„Íë‹Qd^óÑW—[°Åù¬®Ùâ)»bW“Spq2Õì ûƒ}e²¿Ø_õlÚ61¿“kóäéÁÛ·ë&öâx<ê63+’™ÑYÄ-Ì æº44µÕÐöa@C˜ÆICÅ‹*Ï¡-Ò©i •D(Ý¢ ª¿Ö0Ú)\<ßqpx”1:£ýéøtË2tª‚牿ä¡ãñ¦×‘²‰P|\"$Ŷ…(š+Ñ(yû•x¼\9«5CË$¯”qáß—Ç¥ð-û'»ÿœ­ú.ly§ˆ÷äÑË£'ûëzz8lÓ• IWô§àЊñ7TEŠ-ªú*9Œê~¾i¾„î—5ùw ‰ÏÞþúê}Sþžpá(cóñÀ{Y£‹¶ð¢-¼Ú"¼7 Ù¥ºÓ€± ø°Sl8¾‚ß!DlÚþZH¸I4H«¡æ#‚í¿âøwÊ-^<}öï£uc!Ín3OCg±Ü߯`®ßû“iÌvs)-‡Ñš[­±¤«þ0Ñk舧?NN¦§P$ä}üXCç'õ¼ú Óô•M]cw\,m™¬Œ¨Rn™8¬,¾‘"t×2oŠIF²îl°Ùî’!‘8Qp²¤dS›híÑÞ¢å¥EÍ»d1͘ ¥åR’§¥Ac]Þdi7mTkݰZSn)w=$QØÿ¼ò˵Ñp%©,°•Ì“~¼™D…Ýx;!üms5~XBÉûÃy˱q ÑZsé÷ÄdAìñh6_‰WÝž ËÖÛÑéâ|ž~éû¾šþ:N£nÉVúxZ;‹Xgɉu–´i°DK–¬ê`IíÎÒÚ)ÂKª%ÞDÉt°¤wgiý `ƒ'³Î“j°$¸mÂÔœ٧µ}ûKnƒ%ÙäI4q²ºƒ'{Õµ7Û<…ëÃdBKnw–¶î×™ó¦®ZÜ9Ñ,w.¾Š¿ÊßdØïÎpïNkƒéÅ u“iÙòþzL‡Ý™ÞºõÙ`xc¥È­üZ{ ~U:gÞ‘ßÞ-ÀÏKɆÖRòM¦åõ˜»3½5oß`8ô‚L‡o+~Ýõø½AléM×ybÃà×ã¹#øÏê9ÈéEìáyFégü2$x::E†æÒjå’WÀÎϤ{:@¦_¤{R÷o7š$ì*»Ú´ÅʕҢt®¤ŸÞl"Œö™LŠ>ôõOš[H£R…6¸©’d»áTJeÂôQAªè<§²Y*åJŸïM§òY*Í3JZda´¥’¹ÐÊÞb*­Ë ¦NF?Ê—ÅÓé8âÚS™öT!Ë`Š5‘á2E*#C®¨p‹©ŒÎ¬“Udl™ÊñR)}¼½ÍTÙÖéû£\)º²’—JÐ*y‹©è«°DÆe¸lÈ-®LN¦Š¾ÍT®ÀUü„p!#éE©èüʛۘ…/Âø¢P¬!çJ•äIE•”|7]ÙæTRfeñ ¨ä¤--Ùê¥J^ö†S)SÈø<ƒÖÉ$}í–*:¿26Üb*“séÓÀ,žõyW¸ð2Ù‡ ü›S‰íS…o;kÕâÔµcOÈa¡ø~+ŠK-ž´´Öá3ů/³(ž¥P¶%d¸2¼û¦ýаu®øfRu'~£™Ð6ß´¡ ¡â›—Kd‰ÿÚøW‹ñhB$bNQeN9Eü¤3>%ên9r„=Þæ$îý„.UWbå,úpV©¬h'Ëixþ9@nZÃKÿ4ÚYÕ5Z¯F‹¾Ñe‹t@ß|8ëºhñ%­’!uÒ²RµhuñUŽˆ–jÓ’®Å—轂T‡¾ÑÚ591¦ƒ–^á«M/­–T|éÚZôÑR-´uÚz…¶r½´L‹VÚj…¶êE[‰&-Õej…½ìÅ^¶°W]ØËö²û¶E©.ìå {Ù‹½ha/»°—+ìE/ö¢…½ìÂ^¬°½Ø‹ö¾@¬°ç½Øóö¢ {¾Âž÷bÏ[Ø‹.ìù {Þ‡½ -ìyö|‰}δ¶ÒjaÏ;°·Á®h©^ZMìm]´–Ø[߇½õ®E«{ëýЖ饥Z´D-½¢Õ‹½kb_¸\£µÂÞõbïL‹Vön…½ëÅÞµ°w]دB¨µ½ØÛön‰ý¼WØw endstream endobj 3009 0 obj << /Type /ObjStm /N 100 /First 884 /Length 1849 /Filter /FlateDecode >> stream xÚ}YË $G¼÷WÔ,Δ"Æ`|2Æ,û>ÌÁ°ìÂxvñçod×C¥´:ÃTM+CR„TÑS]kÛÒV«n­nµì[.¿Ë&ÒùwÞ4a«h›v†A7Æé¾eœ–­&ÆiÞjÇ«JÛø¹èÖ•çò¾í#&—-'‚Õœ·œ³òTãEÇeËÂÊÞ·¬(;¶Œ¤¼H¼hû«ôʲXSé ÉJcp#Fi nÁÁŒ© ÞYp©²IJ¬´ôM²€àÁJIì¯Ê«°XQí[ƒ‘Ã3Ö/¬(ƒ+?/Âà–, nä£ðFzg=<);Ù)9‘±Ò_%ÕM31 Ô¼× lý /°©ò£‘F!ykÒ¢ŒaƒZ3cØ V6þÑ6>bƒÚE_`Mº³L°A¤”( oõÄlCA°A Á04Ä89DĨ`¨Èω•ú lÔqe¾Êfƒ¬‰wy”›Ç¿¤ÑRaBR“zãÅ蟤;IŽ«#kÔ\û˜“=¿´SÔ1EyÈÀà6â|°9^ì ® nW‡Òcäê *¨¥qP8;$iŒcç0õþRJ^¥ "9^ÊTŒÁºê˜ÜÁ:ƒ úke ’ôÚ8cšÜÙ¥Ž¡ì}¨Çà½ÔeÜB6Ø2Ç\Ø`ãØñ‚ëÂQ øûÖFaƒ ãÀà1Â[}ÌØ-*,l°5ô×÷ß¿¾ûçïßþõ…Åtnß?^ßýÈËr\þúÛ×/ÿþ¶]:î¿~ùß{Aßw¿|ù“Ÿ1õ¸ûá‡ÃÊ+,nù«¶+ÝX¥-±ŠÃÒ‹³vcé+?±Î*',¹±°¯°ÐV °`ÜcÉ=÷%âÆ=–Ü«ã÷0îuɽ:îq¯Æ½.¹WǽFÜ«q/¸?OGl‹±-3Ûge?ýþõoVÊÏ¿ñ®]ö÷ÿü—±S™qy™˜ÏO®Û5õg–«äw–ûîÌ’ç$&Iö’hJýÁãXÿGÎsOïœúì¬úœ˜rf“.{éî$ï”ÃçþJw6±’k8åCø`2±–§å)|ŽV#©a¥ÖøðÀŠê*û~a•½.±à°$Â*†%K¬ôÀºªœ°òÕû «W‡…«7ÃÂKVŠ°Ô°–Ü·'÷W•«÷mÉ}ƒÃЏoÆ}ûÀýqºEl7c»NlWq›QŸëwv¬ü9¬÷ʧ)K5*â,góÕ˜¯iµ½ÙMj.®â«wÅ75gÅÓ“°¨L‰£¥DcWL’"ËÓN  TL ôÜ:„uÁd–XN”‰i…¥n­ƒÛºd[Ý: Z5îuɽ:î5â^{Yr/Ž{¸ã^>pžŽØc[&¶¯¡?W »¡7ôç€]C¿OI²Ékœä(Q"ⳟe¹¥ŽøkÿÏ‚¯ú‚/f>li6}R_¤„·é“LŸÉ¦±;†C4c.“1ûÓpÆ<þcû,˜1c2f8++Y1&+¾Y8¨¾K9¨>K¹¿ΰ7ÕèKª½+ç)åÓ5î»ø‹"̼1™÷”ÒÙ"ó†™7&óFsúD& ³kLv gЈ fИ ú®ü¤§=¹À> ?̹Q—Šd_bõ)"m­ˆÙ8&G~~sGô5fã˜l|:]ž;‚íˆù3&ž±\óa]æÖ˜ÜzÆrs¹5Ì­1¹õ„åÜ‘[ÃÜX²íÜ‘[ÃÜXrïÜ‘[ÃܺäÞ¹5"·†¹5tɽskDn skÈ’{çÖˆÜæÖ%÷λy7Ì»!¸?NKĶ™2òÌ6Ü*_¥«\ýó<ϳk,íZËóÍüÄrv}ß}x|˜]c²k­î‰Ú¢4’.O?_ G’¤ûôºï ¬ñöÕ¥{7¬²ÄrD¦aÁ°ò «?_Ç\UNX÷{ím‰UVðêK{5,]b=¹¿ªœ°Œû¶ä¾5‡¼ÓfÜ·%÷MVÄ}3îÛ’ûê¸o÷͸¯Kî«ã¾EÜWã¾~àþ8]#¶«±]&¶ïÈÇš·çbß…‹–-¦C)q–³ÆˆùbÌ—¼z‰ßl÷ø»xW|SyÒbaè~ûN‰hì`’@—§@ˆ‚ ¤û KÝ:„u©É e‰åDA$Šš(šc¬ã´F  Æ¯ÌüzIÝKš»°CÄëg‰SÄ2%“A4Nr”(ñbÄç}1u⟵Ž`¿ë? –}9uÙôÉ^ÙŸ¿ hŽÙÉyu:¹‚s¤O6}R[b¹TXW2&cž±œ()ÅŒY&cgÅW]î´˜ËdÅ·ˆ‡¤»1=%¹û0ub-{Ž“¼K”È•Å\Y&Wž§Î/îÇ»þwÁ73ñÔ‰™·ô?~Gv-f×2Ûõüs{ùê~!º»9_—¥ˆÙº´YG÷ðê5—ÉÆs}þO_"»3n™Œ{>ý”G̸ÿÝí½. endstream endobj 3010 0 obj << /Type /ObjStm /N 100 /First 912 /Length 4803 /Filter /FlateDecode >> stream xÚµ[M$¹q½Ï¯¨£ö ‹ F0H@lØ0`À Û'‚Ÿ«¼Þõhdþõ~duu&»3³ÜƒÕa¶«Ùd|¼ƋȬ%/7s#ooêo$z³BøénDáFoÎ0~ÊÍlc{cÁ>§7qØçÜÍì£xó? Ä`Ù[pØgõ-öYw‹ûL¼Yã!ÐÈÍZÆNcn–¬¿Ùˆ ðÏùp³8`™ù“ <¬ÂF˜`el„­Ö+6ÎŒóa#¤ãäø;6Ç0‚!žLÏ,L´ LDá“¿ùá >éM |ŧpSÁð *ŒgaAàa¡iuH&ºEö~|BêDzGtZ‚šé£C"¼1fÒ™KC:¼´œÇÇ8B†&7’ÍóæfdÍÐ dyWãFX;„99  mÚ»! ÿ±Nâ”mNeƒ6§ .Ždòú}@?¯´±ò€ÐY±S AròÀ#&è§ßþöÓoþõó×ÿh#×p3ÿùÓoþÝýã?¥/í?¿Î$¿ÿþ¥ý÷¼¼ó·ß·ÿùŠßâüíw¿[dÑ«,‰W²¹½,9%a“%—²Ü"ËÉâM–½’Åq/ëÅÊ7²Ì«,ÖKY²Èr²xÞ/±ç{>ž7ìÝ%önÁž°wöî{·`ÏGØ» {w‰=-Ø»#ì݆=]bO öî{Ú°§KìiÁžŽ°§ {{‰½]°§#ì톽½ÄÞ.ØÓövÃÞ^boìíövÃÞ\boìíöfÃÞÐ¥,³—eް7ö! <|!kPÿ^Öö6ê&‹/eÑ"ËÉr›,s%+„¬‡•«¬_e)‹Yt$K6Yt)kýÃÊ7²6ìõ{õ‹,>¥öz‰½Ò"ë{ݰ×Kìý‚½aï7ìý ö/§ÐöÚ~EÛÑÞÇoÿùËŸ¾nvýcÂoôpçoú3þšô­’- ò& «9rP6à…/O/Àû#àe^Ì•,^€?´‹7àÙ_ÊZ Gaà- L—²–¤ç£¤ç mw‰¶[’ž’ÞmØ»ì_N¡í6´9O®õÂ<’ö%ÓFÎL{õ‘io¶Ð]<§#_i‹ÑÕá%tÚB`Ã…(»DàÐ*»EÀò•¨D: ‡ÝÂaÍ…(³ä¾=Ê}³m®€6KêÛ£Ô7ìæ ö…j6¾õ {¼@}áÙ‡…‹ fãä ÇÚ#ŽÝ(6^à½ðë½nì.°^¨õˆY7b 8/¬zDª§êÈ ¡ñéF§zŒñýäªyêEQY åJ_ºÔ”—ü¨)–Wu¿¾¡×‡†©Î¸¸qëj]Oî õ€oìù†<1²üÈšFß°è*fþ…n ú†@1 }±çFž|êœGĹñ&CýØþtû÷_ýÝOå×ÿò5}ùúê÷„ëö«øÚ~ü+ûÝhÍn…æŠÝ­¸¹B»ž+n·"c%ÎS€IŸüüõÞǾ?¼µm®ûy~¯CçÊ^G˜+|_)L?m_†n]ØuixßÚöлÛõζǟà0é*S0ë¤ù{Æß~Õ¾þTþÿ>×ac —å¾üô矿ÿþ¿Ò×ûüó°ô~±Þüáû’ÑèDm¥@%rñÆ5Ç¡ÚÜÉ:1ŒvÜ;µ3øãß¹ÿNBæ ¥™È FB›4³”,H”G€Ì‰?ÖUÏÄsoõ¶µè]è4KÍÞsýnLöälL˜ JjÒœ§(=Ø©Ÿ»­ÜGÄ!éäl‡k%S héÕ[×|gvj-dï#Í^F¨÷gáeO­ Gî)§%IÏ=0i6Úy꥓³Y‚+]#§¦$C õR« ’}—:õêÛø}ñ+~fª½™È’×àUªBuV0†“iÃí—ü@{sˆR N*'Iìœ×°*Sì!–yÖŸM6‡Ä&ÅlŠíÁ#3;³/Eò„;Ÿ…qä!d“idÆ­$W4µÆ±›8Só$T°¸»jÂÝ0¦×P‘-)Q%ò3T'6—Q9¥œÄ¹ž,ÃÜ”’,å¢~ÚlŸ…ù9âWü4ÌØç½W×jäqO|w"9ptuÞ 9¹U%·.9“¦Œ™½TiÖ#Z˸gÓípv61¾ÛQ ¼ X¶+iïŒÚ0ë÷ƒ’ÞÍ­†T4*î¤kʦ¸ÆVuÖl§Þ“ÛÌ¥´&â9kl>”Ÿê{«Z»xêiê=I1ÅÂÚâB )°Ëy¦E5Æ|wûû$ÌÏÿ¸â§aïl³±µ„7TZ"×Q>Eátåªxfn5s7ž¤7ÞH×Xc1¾ žß³û¤H$n6 ~öhCÀë¿ÊÑówÈNn•Tj(A («˜Â™‹A¬90ûcÏÎIƒ$´ÞÕœ"êId3B^HÅÈÔ{’šÈ˜\µbPêCä{A®æÐZ(ìfÁ×ø,ÌÏÿ¸â§aöÜF†û|5¦©°G±tÅ<Ðgáu'Ňp{xbs€=•¤œJ764gú¼'p«(£H³¯ÍÂR’l2yŸ%…„1;sr›5Ĩ„r]Q¨M%)ç%åέ×y#)ž¤ µÀ¦ ²ËµÕ„»N0 w~= sÈ-£/°UqÙö»Gͧ êõL¬žíçˆ\ñÓ0£ 4ï €u€^/¤‰ˆ‰ Wí^xOàÍ7E91ÑVô-øâ¹TmmMã,¼îî@ ߌ„€ÇƒÆ¬hu¡Ip-¸©×? ósÄ?®øi˜Sp©ÂWMó!c´ª„„ÏÒ¹{tŸÓô“ìN½ÓBEI¿pEÅEœLê6‹Øû­:©ÙWß ƒ^zÅ&Éâv…«¾Þ!“ŽÌŒ¨&Y ¡å« MÁ•Hî^EÎô"G‚ZÛÊ–Ð@ölï•VJžþÊI*¨°ÍTÅ„^_²½[+ÁøD öy–Ÿ…ù9âWü4Ì%f‰hhÐÍ÷„™,YÄJ<ô:•0yîåUÎöŒÐ¢w0ÊÐ ÙR¢† …|h|ï–Onºé®¡SÍÎYL¶§F“‘ìlgœ9¹U©Ÿš¡¨F‰ï"Œt餢šé%ggAE¼Á-Š(>£*‹)‡‘btoÁN*PErAÍŠ¦8£›³š»WÔ‘x ͳ0?Gü㊟†¹æR}ÀìÅ£ŸOÁ`ðΊ”¬÷ê¤hcžÂÜ2™WÄ Ù(ÙŽð#ñ^*ÁI¨0êvC%¢n¡É Ö!¾™S¡3SïI¨ºAl Bšç„» 2J nG™üêNlÆ•éE oDÆä–z_0³ Üi¦ˆžT¯ÞÑñDä%ªFŽÂ¡IÄŒ²(¥tÆäY˜Ÿ#þqÅÏÂü|ôN£(&2¸r¾X¤É(ÏÞcæìH­89æÿC:úDí6fÔͤ®âCÐsÈÙºYøU¾UzÁ0˜kÔ‡–VÛX2rŽ`~¾3±úéÏz¥dÕ›wϽcî–ʀ Â:¥{þVé>Œ{¦T \ì7\4¦ÆÙûè÷ò%Å#éOºcL×LGÓ‘kh°>¸¤eÓ@eNþYÊþ"Ùó—0þyÚ?×ÑP²40¡c7èÝjPr>¢¢ k ÿ­ðû†kÝÁaCLBÞŒ/›†‹GîÒõDú3>H2ŠmÊLh6 H­L¶ãñnšÙp{û­Ò‹LMÌ%pèVzD‹]F«]1»NéæDú36M„ŽMáˆÙRrlãj5 ÉU@5¥Ço•Ñþ„cÜ!­Ò:ØJGÓ§ìl™Án %a¯xXgd¿‰'Ra:O¤âþBÍyÓl]ønÛvl¤ü’ÞîESŒßc')]n­ ¤Ô-»RÊ{ƒe8¯'¡ª_·[')]ŠŠ ó4îh> vYH^¤‚,N çà xC÷ë¶cóüDj¯w¾uKâùT\nHE¿¿*H‘Y’Ñ/н ¾³îµäy>3n|€–dïSˆdŸ‹^ÇÒjJ˜KË®8–tïÖ|{GÇ‘ª»ŽM½¾Ê¿/Ù±´äݘÊÈŽq:pbÞß1l“Øeiø.b­ÓW2Ó32¯UItQ<€’°Ïn si° |ØÛ2{ó0œWÌúÙpFfa hŸÉã¥&E»7x’éýžA‹ÜJµŠœ”ñ\h´7‡> ?$êŸËaߌ‰ÆŽ]ÅcXE£ÕÑä”Ml#3ßqÙK-õ–SÀ\‹é},¦F' £ï¼‡Ç¸¡žbkkÃ,eÜø,1ßô8ŸÅÇ-Ý+‚‘º·b+å²nš‡‡°5ó0Ò<òx9V<SJF†ÊZÆ@ˆéd|©aj£m0Í0wÌ/I,æ>ôÀ¾ z¦¸þò”çÝW?>„é‡Ô]…Ïr®© ?—"=³ËÀ¤j,ÉT N¡>óÎE:&(L°a|{ÆXnƇˆæ¾¨ádô}ø@IŠ}ƒm`÷*,)È`pÖ9³ÄÇÞkã} ¦ãà•Ñ¥cò‘j©Tä-ƆyìñžpwŒl‰*¹LMBoFº)†<Æ€ûÓ¶Ž9ß“f‡ÌÌ“ Ò«Ó›Qu³Œá*|Ï1ýº«ð‘k˜ÑÄfÔ3*VA—×sð–råΘ÷q³³8¸KÝžt-ÐŒi-qGÚ¼}ïã@uÂt¯Èzc@“‘1Øi‹³‹Wú˱€ûŒ)àCëãÅ6ÀijJFÆLò²ï¯a ¥¶†q³"cZòÕŽÔoñý±jÄ5q4"ÕI^Ùl]Á@7Œtæ"|Ï1ýº«ð9ö®£äwqi*¾6'=É|1Üu¶&úÞEçÇ[Ä”aìM\ ÅkPŒ¸‚Lû>±¨14JX®ãk8~<ÿÑÚÆÆÙöÆÇ·C÷ÇB†WU= —¸avï¶ZDfÞ:8V1Éc†ATi…´³MdÒ¬,ïk®K²­.ØØjŒ1´Ò=„gGm¹§æÕí{Žé‡Ô]†/•ÞsuãÝŸR-•%:pXHÝ3®Ò´õý}pʼn3¸3 ¹&Œ¦—*h6ŽâVypÙƒKëÚ¨”2 /zk ;‚ÜˉLxŒQa• sÔ–S‹xƒôÁi³œ9{p ÕÜNâ¢v«Êq<[*É“ï/Þcäƒc½kÎN)€w õµˆŒ7PîÞá¾Nð!L?¤n†ïÿÞÎÓ endstream endobj 3046 0 obj << /Type /ObjStm /N 100 /First 1068 /Length 7532 /Filter /FlateDecode >> stream xÚµ]K$¹q¾ï¯è£Æ€W$ƒÁ è"] †m>È|®Ðî¬fza@¿Þ_D5{º3+³ªgdÚå2IFÄF0™Õd>xüô²—F~°ä-ZllLIZöÁ9bi¹’“=uYZ˜Æ1H‹¼qôZAÖ Ù Nì”çLõ‚yà…Z°ÁYÿÄÚGI8þ!D'ëaZÈÆƒFÑd¢‹B#¤‡H[ù!Y 6RHÒB™ŒÌˆî!§$Êô@ºx“.þpEÄ(NdcÎ.Ô‘Ê„‡Ô:Kå’*¶tï}1RwQ8Ô‡ë°,+ûœªvÓhy J²5bs„ï;çzHðzÎA˜t{­§œâLÔJ˜<½wÃÌ 9³/µÚž¼2¯L›l}åG¡3ö}è9±LˆÑLõu>QßmLßDîL}©ÚX¼íyô”iŽ (m7 +n”5x^´†8’™ ¸4ª‘}†ãcs4%VJjØØKvÓzJ®ŒÞU-<¤\r«0<¨Ç¡Æb®L+>!:Û‚gˆ K®âʃHªÖó&Lj®øx,Àrž1û‰ #6(5ÚÏ4± ¸™©·R ÔžkK>˜i¯­ªÖÓYð¼é›È©/»4fn‰sÞÂ/ r•BÁj¤Ø‹˜ƒ/búnÚÀ½öZ,˜t¹V¦™tÚÞûrœ3&±%d¾¶fൡL„8ìŒs÷›X®½ùf ,ÔM‚T‚m¹VÕt¡¶W_.—êá+ dFv-f×>êÇeã+ÓOg߉–ˆÔ¯Í2a-=€tcpgê»é›Èªoä»ÎŒ€;¶Û)Û|­®%ÈzI&h¯‡â*SOÓ ã©ïž1QÁØFÁ}\*!Â{,êëÈB[ÆN4b¡êr$z¸‘Íìk* jd1âï5ÈMa¡Ô•ɸwÚ‚ÍF]ZµR‰ô¤ÁÔÀäs쪾½i–†j&ÙÚÑtÜä{› ‡úúÙÞwÓ7‘;S_E IÙŒL9¬©Ôœ°åû:'¶[åuLå 6†‰ ’B8]ƒ!]…•ø€Ê¬uZ{eDt(»D{TEaj ’mh%i2Ng껉é›È©¯a)!·<$g$T]—!d÷:MкöÛJƒQÅ€¾G‰"Õôjâ„ô§¤@fïIY-N(ÃÁS÷3N†C™\g½¨oŸçJÂÓ‘yÄæÄÑ¢|+½¡p Z òr {õ!:£ªF24çØ«;’U”S(ºƒíHBÕÆöêëEµÃœ").Ò23)ÂRs7€‹ªïÌûncú&rgêëƒ'*db¨Àýè¨ÜœG„FÒ™Km´0p n*ªâ ;y–°ˆl» JƒKÌÝ«o˜›êÐ<2®Øç@>ÛyS_ªÖ÷;íÈ%yÊ5"IÂÖÇL%a›-Æ€LU½/ìmlTG„-Ób§(¥š ’‰Ñ!à’–¹+Ô:[`0dÍ¢@E)NH[mÝè4w¢¾Û˜¾‰Ü™úàÑ­»d¡†VEi8’ùÖºhìEœžzwé’™TÅË@ÅŠäYÝhså°%vØ ÃÀ&:f1ñ -ö©Ë,~¸ŒÓÐjóÎVÒôìR‰™½¡¬ñ&˜f]¶@PN3hæ!Q»\Ühocª†™Ò¢(®#§Í£¨F¾,G'*ÛYÝwÓ7‘;Qßç¿|j’K¹çMàïïßÿòøá¯Ÿñhšg«~Ñÿ¾Ч†m¶Õ>"Ü€ÜD=-ç}(Ç«39aWƆ‡hÓw`š‘D›6îžœÎôWg¶Š8ˆ2Eq!Ècc›¢Ë­Q“a×fÆÔh,ªÕŠtµ! (Nq žÐ<™ù¤X(½uÙ=ð¯æ—n˜‘¶³©@DžÙ²k¼T¤lÅkU”ùk³bD>DB7,j[š-QV¯Ï¬>ÊÞÂN\g¬qÀÚRx]i:ó*ˆÃ`ÊBØ`-Ó™„;l^¶Uì`ªr¾ª8—²›¢‘…#aÄn-"_íSý9]Ù½–T 'üÕ¦„,¯¡³Ýlùr¼ðJqoDù­DÏÕúìRŸÒ€Ï£=~øøÓ?}~­]•Õ—^I¢çm·Œ†®¶Ý’˜Ä•qé–j!]ÒÍC,žíøå´4_zYÓîHI”M{1äô,-{ýÒ-ùWZ'á_º/eÊN:­'Ü.8¾âéÕðcö¢½åÇi¡³ÃÏY æ[~œÄ# ßv_|Óm»½vÓ!÷îÝëÑ'Ì_ÂÙÖ(ô@”ãŽpÔîÝh€WIþÜKŠËѵãpÌ:¿{5ú˜uÖ•¶‰uÞòµw«#±·ºÓˆæõØï­8U<äúÓ:ôˆëï:çk¿'étôºÓK'Ùm§J|íß³Î߸°ôÂٙɅ—×Ãùf¨v4ÀP°;ÒÂfJÛ^˜9³í…IÐÆÆÑ Hý1ï~^ ?áFáCÞR€QøÄÛÞ$½»±0 Þ¸ç÷Að Îm{!{ätÌyx÷zô!ãA‹aGÀKï²ÇO¿´Çÿ(ÿõ—O£ô÷ïÿ(ÙÅ£§ï‹He r̹Øn‘vßäu¯ñ”¼WW¡“ùS_cÙÔTlät©³e‡ŒÉr/:ßÏG&LÿìÈQXuÏ(üœµ%F& ïàSL¾nÝ=ÎWV‘Ù°g˨›aîÙWƒJ`P´¨"’‘ÇÒõì­õFN: YƒåYFÑá­Ïö2ßÏòr…_Fºc%mò]N{P»„êÅé|~5ÿï¿ûÔ‚ÿÝǟ懖þÓÙˆ÷ÅC8h¼f×åà_ ²bo†AÞ44ˆw¾F¢k¬(¤RõÈaä]:jWÀÕè¢Ç°+þ¿ó¯gâHéû•ädŒ¤Ö¶*ì»MÔâŽ}) ös>ŸCR=Teòôy䚤ÒGuì¢1±ŸKVHè|&œË(ÉX#.Íò°…ÑFÌ]×0¯×øãøüÎñïåSùñóï>þøãÇŸž ÁÛ{F¾/.ضé:¹êàaÀâ:›i‡·¹‘ìGŸï[«;9ÍÆ—˜’¼Ow> |”‰Ê·8-ÙܹVÍ# N…†¡–ä•_srk ý…¯3?æ_ËãXÏÝ5TÜ.Ô4ÍŒd°fl¸H‚’áDf`‡UWIüV3º­±g÷ÙÑË%ƒ¼Ž!ÓÝ0½g6Õ•™[œàQ… w"7\4±Aq¯1• [µÊ=ltÔÔÓ™Æþð'ÿÇ¥.{œ¤väÆ6©0‘´zµlQ¶#>‘–þ澕2Eá?Qsv ?LÈ©b@*ëk×-›Œ»k%lË3µæZ˜ð¯ègF EÀr掕î CoÓÔ·òuŸõ<¯×»1Á&šò0†˜‡ñ1å‰ÚÞôTôÆÐ9bKÙ·‡½/ ©ì9Öœ¡¡Q+rš–*ON—c©³8µˆ™ó1ï±+–‘d£1óœ8Õ#5ÑÈõ=H7WA²”à N*·‹6O8¾Kf SþhÍ]vðÌ¿…¡û à’ÊY{ &/yÂ0°­ŽÌÂù2‘™—ÞT8w "}—ÙhmrHÔ‡ì–y8¾¬n­B%#}È£5dû\äR¸R“)Û©y’·V‰Õ`o’—O±´^"¡>t+yˆÓÌÍÚ›«ŒÞxX)3³3ȶðQÞÉ|Õ+Ñú[«`Ù%Cqqbßk°pnÜ[#F ÕUè.Ó¹S[ßÂÌ̦vÁÚ,µ.Ōܖ‘P›+­zV¾OËFJ[98ë#jjŠ®dV•*Ì@á᛫tÛå1ŠKx£‡|I |5¢òânÆŠŽœ§yÒ­™Ü2ÜŠ“ü©±Cc…½.Ñ*ÉŸÊ%oOHw:§j Š>T°±ÄìI®æ[Ò#•˜ï7„Ûø·LàR7TDÖ®WÍöœjŒ¼ÝçšBprH… Ç`$9PÊ1é»;/w1ÜÍ3®Œ”õ(7Æãù²ÇçJ‚ù› ê ÇäF‡«#Ì_ÀLÇókö&àëÒåö­a/U°ñÈy£Lˆ[³û8ÿ·|ÿ=>É:ÿòÓü¸¶¡»FJñÀ©u¹=³$"=´ÊÕ!pF¹GªÛ¬½ewâÿíÌÂÁЍjK6¡7çÚ°eŽhaY±Ú9j@r¢¯zì}PÉM²!f:ë ŽÊùX|àÌÑÂ=§®åî\«h×wTlw9·Tƒsˆ™ _þ¾µªí€BFOµwËÁI­„·éÕô´‹4GkQŽ#g¡¸•ìlÈi¸gH1»'¾î4­™°I"€6‚¸ír5 —KN×:Þf¾Z£ßÎØ±™=–Ç_ž3½m0Y‘ a}ìf(RµötìT¨&¬Ô©®C§§CµAø«¿­:‰´&£‚›&¡‚ð(Vôs(§2Ç\‹ÂK‡ÊeLPEqmê”Sö’€U„fé—éödzA4ùÆÆ¥`¤ðÔ]@4Ñ$…Øáô9åF– †a¹P‡å"äêœV’´ŸFùq™m_êxùLﵸu){óH.¦äpå‘^Â!ç¯>u>_ezùèrKçÊ}¦=³û‰ç"ê]zr/é…U!z)ÅÇkzLú(ï…‹)÷—ÉéT:•Ò? ¹Ÿ{UÒí0'Œs@bƒÇaÙÌÇaÝœÃÍ^ÚþöqÄãxMú+2,pj‚ñPº\á´öd€^ý<[Ao+æ“rvéèd€Þà» º\/»¾Ä]hÈEªVÁi:a|¦xü‘O„Aäaû48á`» Hztẋ”æPJN–øø¹˜åãçb žŽŸ‹1ø»Œ!½;Zá ¼îNÇîïõÞ'Ÿ*džÇ@ª ñä¹Þçõ'ôÛªt ¹-z}‰;°¸Ü¹|þÌúê¹7lÃɯ÷Oè—1gâÊ á—[ân€Ü&w‹eÎél€‘+ôæd„h%Æ»‰ï׸ÈJ³“=aFœød€(8å“¢à|†ˆh%Ÿa ­„+—kä9Zã>@²Ð ×™qý’1ÇÏ¥Š»ž8\žËG&?—Ï#®oö—ç,ÏÃ]XäwGKÜ„‚ž$¥NèIR ÇÏERoŽŸ‹¤Þ?IýRþ‰¿ào!AqÃßS©> ƒÇú#ë)— Ÿ b×äãZûŸÈ*XFwü\°Œ7­b s°Ä]`ˆVÒ AžûãçQžŸHšä(íDÒ,ϬŽ/'ÞÙ{àwG+ÜB‡‰Um:@X öd€XEàãòÜ<'yžŸ{9Å¡[X,a–¸ ù|‹N°O²ü òq–?‘T>Óò'’fÑÅÁótÞåoo©O’¬pˆð¤²£ý4=1r´×¥Ë|6'óe¿¾i”I=Ø#sò\²p3R<‰r´Ä (žÆ /ñŒù˜0ú“$ÒÉXxHîdË€p2@޳9Çã‹äšÖ´ŠÖ¼J?8ä¼e[aÝú#ëx³ñh½öo ^rórð1ÛúúÖq‚ºí4:tÉ~üÜFný©Ã°î´÷ÐD„™—ƒ¹úôaPz>}XI;7PgÝGùå_Œ}fã_?t £õcúh¸Õ Õð«Á«±+·~ÿ±ýó˧GPùáÓÇ_~~ÿþoåñO~~ÿCAùçç”ßEM î(¿Xå^35—£1æ 3qJ«‘ŸOù‹áýv¹c 6QrêÆµQÍ‘å¼Üìâä»)sŽ$·°º™±föipŽM~†¶EWJØóì\nÁå\Oé:K®ý½å ?Èo'ùYÝìˈŽGGÔ›M>â&ËÌv_œ©D¡Ùbãà» aö4k”ïîõsùaÈF¶gvÁI NZpÒÒ?-öµÂeݸ(ð{¢%<-ái OK©´¸ðæ*…ðúü̈Ùx?m…mÉŠ 3õšL£i®0á—P~ å—P~iÉ/F÷×^ж¾öÒ`ÜxVp·±ÇÜäwÝlÔ_qøª¿ðÌéÂÄ/Lxi†—¼„`ú‡ýþý¿(»8å/àxi˜—†yIsök÷üxêÕ`[œ„…PX……PXj‹Ûpßo¥½þ%¦gJK°$ K°ô7ûDxóÓIÿ¸ïçqÉ—ÜqÉ—–â’!Æÿ׺¿ù[™g¡ÄqAœÄi)<-ÁÏî¿øäø–æ¢špi—pi)?-ÎR¾÷ÞäÉ­¡E9/éò’./éòRk^Üeþº‹:û×ËÏä—˜y‰™—˜OŸ«Óú»2dïxwyô2wóBâ‰üú}XZ·ÅhýÈ þ!ª§FXø•¯ö§WÏôÓZ{ k—°+5²+5²–î>-ºVA.š+±Z7õO_=5âj,¾öO^-ùÂ>PZg¾2+´+ɲn‰¾Ò»Ò»Òœ§_ì<Ê ¿e{\?OIë÷õ¯r]+ƒY×Âõïq}Óöx;JØ•YZ(¬|Ç®|Ç®|ÇRº'Jœ)ò×*Ð/tV*dW*d÷ס_ªëÊš¿Ÿ1LÿÖ&Jïÿ#?œ endstream endobj 3148 0 obj << /Producer (pdfTeX-1.40.25) /Author()/Title(\376\377\000Q\000A\000T\000z\000i\000p)/Subject()/Creator(LaTeX with hyperref)/Keywords() /CreationDate (D:20240202094050-05'00') /ModDate (D:20240202094050-05'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023) kpathsea version 6.3.5) >> endobj 3147 0 obj << /Type /ObjStm /N 1 /First 7 /Length 139 /Filter /FlateDecode >> stream xÚ3641S0ಱáÒ©,HUÐwN,IÌÉOçÒHLO-V0600W0PâÒ÷/-ÉÉ̃Y@„üsA|CS¤Å7?%U?´8¦,蓘”šSlc£ïWš[mdë'ÚÙEvv`†‹]¬Ц‚Ô<Çä’Ìü<ssc°Ñ@aÖ•/³ endstream endobj 3149 0 obj << /Type /XRef /Index [0 3150] /Size 3150 /W [1 3 1] /Root 3146 0 R /Info 3148 0 R /ID [<49391678931F7DADED841C377A7EC2E0> <49391678931F7DADED841C377A7EC2E0>] /Length 7402 /Filter /FlateDecode >> stream xÚ%ÛiŒ#ïv×q—»géÙ÷ž}ß÷}ñLϾïÓ³ïåù“„í ¤±‚KYDn(Y ]@L#¢è”Ì·EX„ÈE¡®œ‚øsî›oû—«]Ïï÷ÛÏyªV«Õþ_½V«×’ZmùèÏXñM½¶øë5¹ê£\¿&wU8ãrÛä®çÁ|¹ír—… `¡Ü!¹)á,’;,wI¸–Ƚ•»(\ ËäÞÉ5„ËaE½6or‰ÜáJX%·Tî¼p5¬‘[.wN¸ÖÉ­”;+œ„õr«åÎ7ÀF¹µr§…›`³Ü¤Ü)áØ*·Uî¤pl—‹18!Ü;åŽÊî‚ÝrÇåŽ ÷À^¹“rG…û`¿Üi¹#ÂpPî¬Üaá!8,w^.Â8ø¨Ü¹ƒÂøGÇåîÊÅ©âMž”{#·_xZ.Æ>ÞF ÎY¹r{…1°çå>ÉÅ%„( ¹Tn·0)=¯¹@..?ÌpYnBn§0ŒtUn‘\ ]˜ðº\h¾]xnÊ…–1ì·à¶Ü¹­Â;pWn·\HvîË”Û,|åÎÉ…Üà±Üu¹Â'ðTî†\XåLËÝ’[/|/äžÊ…Í^Â+¹r넯á\ŒUXô-Œ†}^{¾Üá{ø ·B.ìý>Ém–[%ü ©Ü¹˜Mø"wLn…p4»kÝÑdŸ¨æ‰ ž0·º&{·.¸Lh²wÇåÈ™—]“½;_î¹Ü¡ÉÞ](÷YΜîšìÝErQP ã‰Ñ+æ  qHœt™\\àBa¼!“}°Q.N&û`ŸÜ|¡Ñèšìƒ¸ÀxkF²k²âÚÆ…Tèšìƒ)¹¸, vMöÁ=¹ºú]“}0-CÂ9]“}×Vr]×d¸¶ÙSŽíެ<z±Ü!·wwË1ë,=ºfJw¯œâ1› Ͳî~9Eu––]3´{Pn¿Ü'¡ÙÝ=,§¨ÎòA×dï•;#÷Ah²wË1õ,uMöîI9ã2ûNh²wOË]”ã¿®ÉÞ=+g¬fßMöîy9e–w»&{·!wUî•Ðdï^’»#Ç÷]“½{YNá™}!4Ù»WåîË™3]“½{]î¡Ü´ÐdïÞ”{,g¾uMöîm9lö©ÐdïÞ•£Û¬¹Ú5Ù»÷åøtö±ÐdïŽN?Æ›5Ï»Çr<9ûP'x*§@ÍÆËâŸOË…¾÷…ñÆ_ÈùšýJÎÐì]a Ø9,³ñvc°ßÉù`™½- ¡>Èm‹K ‘?Ém’») ƒ¤r Þl S˜ë‹\xèºpdÌä[£É¾ä'kžØá‰kr Ôå|’Ì^ŽÁ¸\˜æŠpÌ—kÈ].€…r—䦄°Hî²Ü%ábX"¹(\ ËänË5„Ëa…\ä‚p%¬’ ƒœ®†5rasµ°N. rV8 ëå g„`£\ä´pl–SgO ·ÀV¹/r'…Û`»\LöÂ`²ÇäŽ wÉ>œ'wL¸Löa˜ë¨p˜ìÃ5rG„Àd®—;,<&ûP•Ÿ06Ù‡Q< ã™ìCß -w CP“}èSr6.?Ì`²£ì†‘Lö¡B;C&4Ù‡>Xf· o€É>|$Ã~ Löá¹­Â;`²ŸÉ…d÷ÀdÆdß,|#«,x˜È…Üà±\]n£ð <• ÝÂ*Ï`Z. Åzásx!·P.lö^ÉùÖ2»NøÞÈE‹¾…wrñA°Fø>Èù:öþŸä¢P¬~†T. EL&|‘‹B±B8rgýãh²oX_óDT‹år ÔåvÉ-ŽÁ¸œ¯G³K…ó`¾\LÄ%°P.Ä[,œ€Ñõ.ìÄ$^$Œ'–ÈÅkã8é2¹˜Ä …ñ†VÈÅ$ŽÓ¯„Ur1‰ç Wù˜ÄñÖÖÂ:¹×rãÂIX/ççÃl\ÖØ(÷^®.Ü›å>ÊÅl­r>ÙgkÂm°]n4Ä‹[1¦;`§œÐú"Ü£¡[87.×î½rLÓJ…û`¿Ó´> ÀA9¦i}‚Ãr¾ê¶> ÀQ¹er„ÇผoK­÷ÂpRn•Ü;á)8-Ç4­·Â3pVŽiZo„ç༿´^ /@CΧKë•ð"\’óéÒz)œ‚Ër>XZ/„Wયµž ¯Áu9_M[ÓÂpSÎ7™Ö3á-¸-wDî©ðÜ•ó ¯õDxîË{,|å·Ö#a`ôì¢ZŒÁCaœà©\œ/^ÿ|ô®eñÚûÂxãqEq©¯“Úªß ƒ¼rÈ)ˆáŒ}“ÔV/ž =B¨P0¤ Íà ᒰÏÈHcS~mO%à7öÔøe=5üžžZ~EOM€ßÎS‹Á/æ©¥àwòÔrX+a¬†5°ÖÁ$¬‡ °6ÁfØ[a'l÷Nß%µ5·üüoÛ–Ôn‰7¾ vÃØ û`?€ƒpÃ8 Çà8ÄIOÂ)8 gà,œƒópp.Á\†+p®Áu¸7á܆;pîÁ}x`GRÛ±5®í1<§ð ¦á9¼€—ð ^Ãx ïà=|€ð >C Mø|PĪ |PðAÁ|PðAÁ|PðAÁ|PðAÁ|PP¿3[ô9¢¯<ô¤Ï }fè3CŸúÌÐg†>3ô™¡Oýþ¼¤öðf¼ß•§}9ž>× ~ÅH¿:†kaœ‚)_&Æ€iúìÓߙԞÔâ|,Õg¤>#õ©ÏH}ÎéïIjOwÅqpZçœå¾bï™›úG“ÚôÁ8„Ãú|Õç«>_õùªO…>_õùªÏW}¾êóUŸ¯ú|Õg©¾ÒÒç°>KõYªÏR}–ê³TŸ¥ú,Õg©>KõYªÏR}–ê³TŸ¥ú,Õg©>KõYªÏR}–ê³TŸ¥ú,Õ[(ýQ¡ÿÍ$P‡1‡y0ÀB˜€EŽP}ú'’ÚóÇ18ÌÚgÑ>‹öU©¾…¼V,%ZŽ™ŒÅÖXIÝÛ [-®4xtÁ£Åóh—Gç<ŠÅÖ3Ųá[â|§<ºæÑg°7ùÞCNÀkÇÅu,¥° –à X «`5¬µ°&a=l€° 6ÃØ Û`;쀰 vÃØ û`?€ƒpÃ8 Çà8œ€“p NÃ8 çà<\€\„K0—á \…kpnÀM¸·áÜ…{pÀCxá <…g0 ÏἄWðÞÀ[xïá|„OðRhÂø†‚–'°¨89–'çAÔ«4©½þå8Îz⤟ȭøêkÜÖ›V¢›g’Úú Ç5³¹,—7÷Eò&w6­È5w€E÷f¸Órts5°rs­¯ñw¬Ü9n`q´ùbÙÕ™Û›À };V¼,a6-$6À3OXËX`o2pÛ’rÛ:ðÀbzÛ¶=Û¶v=pÒA,˜úoƒ—Iíoü´‹XÜp©Ñ‡X”Ô~ô/ÆhX`jÅwQÓj2¦U´ ö@4 ¼ûÉ IíOWDÓ"¾ÁÇÒ}ô+ Îdtb®Æ˜‚˜âþùäÄ‚ý¨ÿØ/Æ©B€XØ¿“Úߊ',ØOZ¡ŸŒùëÚ&ãÝ?€ÛIígÆq~ù·¢ûp Îä#°¢>ù¬£OÉI£6I€Ikæ“/i(Í9MÎirN3œcü&G_bÚGâÅŠºÁnR¦9)÷MRûkÿ(N`Ä›KaURû^/r†©Iߦh®Oj÷ÿÍ€5-ò6 qó\„ÃIí^ŒCBî(sº(MUªIîf”4Í—VΘ6£¹q N3ú F£y)©ý“¹8Ÿ…”Vœ*:<Ù4LÍh<Ä@ÜOjÿ|~lÔš¬í³©ÐT6›¯’ÚwþCe3º QrMÄæ‡¤öo/ųJnSmFSÀ·cÅß·ÀèÛá¯/‰ÎÀx’ÜØ& Vò•úöJX˜ÔþÛ:–óÛÆ¹¿R¹©­ü·GÃþ¿)±¾Ñb¶9Ø^ ,ߦ[ÛÔmO&ÉüßÓ¨í§M6£·Mç6?··'ɲ_‹ãÌŠ¶¹ÐŽ3³w›ªmcÚÞŸ$ë~'Žãö6AÛ19©Õ6IÚñNO$Éö}qœO«¶O«¶O°¶ùѦe›–í˜ç“äÀç8˜´ms¡}͵±J›Œm ¶o%É©±8ŽªmÅ£Mý6´iÙ6Ú4jGá¡[ûq’œÿÑxY¢Ím"·£DøAò&I¦~o<ŠFPt~šIòWÎDi¡ê€dƒ$Iî#Gäy40gÊ뀴ƒhÈPp N'ɳ(ƒèÊ{}º ¢³bª Ì£Áš$y{0¶pÙŠ’¦T ̣ݛ“¤ù³qUÑJ¡ù (tìJ’þVBТ5 ê€xÊ è68”$$ Þ€ JLÄÝtPkp:I~äT§ (= Ñ€Fƒ(ÿ\I’?ùSq-êÚ j6¡#ÿ|-žò¯ ,W¶Øb`šh90ß´Ðr’ä'þW¼–Òn@Ð-´|ô釼N’ŸþùxDË-#-¿®ñýyz F2þÕ^„Ví§çuùi ìÓ£¹úíg€Åùé X K“äo×âY+ïÓËÁzû´öi_ϧ-¡OO‚…óißÖ§-—Oo‹äÓÑvÉýóÛâT[`DÏkD§kDkÄõhÿħi4–¢km¢x"šWÇ ZV' U~/L߀#I2ó)þot«¢MtÁxÏà¼-—é· Ñ2ý´W¦cì5U¦?ƒVÊt4P¦¿ñ&:&‰ð%ÜL’_xïÀrôLôN(3cˆgVzâU’üÒT¼,º(4š‰>I4F¢­èuD3"º ѾˆžÃú$ù•q‚hKØÃ9c8g 猾ÁŒŸZ3º3†}fU’ü‹?/‹îÈ! ÖÌ0º3FwÆèÎÝ£;ctg çŒáœÙ$ßývœå \€‹0WÀ¯»ƒ=ó öÌ0ö3Æo†3”™±’?}0RÌÄÂIòËñ£pFü'¶f¢F£™hÑh†FCã7\ q¸Œä•‡†sãü2IþÝ÷ãôToH¨!=†ó“äþ³øEJ­!óî0ú3Fwh8‡Iòýùqi‡äšC’ Mˆ!ó·0ŒfQ†ÑÂ!À07F»†ÃhÒD‡c4Øÿå`üz £+c؇ы9ñš Ãè»b* ÍŠ¡NæPKr¨W9ÔÄFÄ`£Eb쇆xhˆ‡†xÈÏÃQqûí˜ÉÃh¯ö¡aöa { ¢©1$íÐÔ~ã'w¨0rûïÜ‹NC z `à Xk`=l„Ͱ*©¯ú¹xí6ØK“zýSäâËÄU¶Ã8[“úøÿCvÂ^Øûá„CpŽÁq8'ᜆ3pb9á<\€\„Kë—á Ä[»×áÜ„[pž@4–žA´“žC4‘^B´ŽÁѤ¾pI\ÖxÖ³;÷à|±¼­¿ÐIá<’‹A bØ_C4 ÞB´ÞC4›>B´˜>C4–ší$úúœYÐK@רg±¦GßÞ<0º=£Û3º½öÇI}ñŸ—éõø §kÔc†Þ"ðÖzK`),ƒåÀ%½•° V¿ôÖûô&}z€‡z›€‘zœÓÛ ŒÔã—¿ô¤· vÃà—Þ>cµ–˜ÑYY úGsšCsºFsZLs+Ash.:5= h=IêûS¡ó>á{lÛ; œØãÄ'ö8±Ç‰=Nìqb{œØãÄ'ö8±Ç‰=Nìqb{œØãÄ'ö8±Ç‰=Nìqb{,Õ» ÷à>pXO{´Ç=MÑÇö8¶oœc{ÛãØÇö8¶Ça=ëqXÃzÖã°‡õ8¬Ça=ëqXÃz#‡-l¦†ö^Ãò†¦^cŒsc ± ÐØôhl*4Â/’úÖÿçK c0TmÌ"7Ýú—Å kÙàƒ†^eƒ-:” rwÞ$õ+óãô;€Ò]@øÆ0%,ÕÐèkí½Æ!`•Æ0MÇ€Í'@Û®q 4ëg@‹®q4æ@;®q4áS õÖ¸nk ÍÖ¸šk[ ¥Ö¸i ¥¡}ÖPAŠLCi<†'ðžÁ4<‡ð^ÁkxoAj¼æo|3 ñÔ«FÔ° tb¦¬C²É:$ë¬C²É:$ë¬-g’u¢ÑL²N´—IÖ‰¦rH­d“¸ äXò¡B‡ *t¨Ð¡B‡ *t¨Ð¡B'Ä[ÔOÿT¼Éh9sg'ÍÜÙ‰ö2wv¢©Ìh%sg'ÈüÒ‰ÊÀ/~éðK'J8¿tø¥32ð‹¯ñ¨ß¡~‡úêw¨ß¡~‡úêw¨ß¡~‡úêw¨ß¡~‡úêwHÖ¡`çPR¿ÿâį8˜–s!Àó¤þ,<Þ‰îæèàù[ñqbüæêIýó±i4µsmRÿòÇ"gpæX~.ºÍû“ú}+žˆ·1‹–³+š‹F³+š‹ö²+š‹¦²+š‹V²+š‹²79mcW4Íb~ž‹1?ÏEc˜Ÿç¢ÌÏsÑŽE~žãç9~žãç9£1ÇÏsqùg’ú¨ÇÛ5VsL=ÇÔsL=ÇÔsL=ÇÔsL=ÇÔsL=ÇÔsL=Ì#SO¨kêЄ:4¡M¨CêЄ:4¡M¨CêЄ:4¡M¨CêЄ:4¡M¨CêЄZ7ÑX k`-¬ƒIX`#l‚Ͱ¶Â6Ø;`'ì‚ݰBÚWIý¿ŒëØË דú_Zá8‡à0£p ŽÃ 8 §à4œ³pÎÃhÀE¸Sp®ÀU¸ ×ad®?÷ëñ^®Á-¸ wà.܃ûðÂ#x Oà)<ƒix/à%¼‚×ðÞÂ;xà#|‚ÏB¾äÞdÎ9ä|óAÎ9ä|óAÎ9ä|óAÎ9ä|‡n$õŸøëqæIýï­G‘sDÎ9Gä‘sDÎ9Gä‘sDÎ9Gä‘sDÎ9Gä‘sDÎù^ØûrÈY gœrÈY gœrÈY gœrÈY gœrÈY gœrÈY gœÜ9 ä7€#rêçÔÏ©ŸS?§~Nýœú9õsêçÔÏ©ŸS?§~Nýœú9áóÑÏ‘o¿1e†œrÈY gœrÈY gœrÈY gü-É$P‡1‡y0ÀB˜€E°–ÀRXËa¬„U°ÖÀZGS÷ç–Åÿ]`#l‚Ͱ¶Â6ØžÔÿõ_ŽWì‚ݰöÂ)8 gàìLêÿx¯Øûá„CpŽÀQ8gá<œLêåÆ8m¦­]„ Iý_^ˆ'0—á \…kpâe7á܆;pîA4†ÀCx±è Ä g`çOí9¼€—ð ^Ãx ïà=|€ð >C Mø,¹˜Œ2ÈX cŒ2ÈX cŒ2ÈX cŒ2ÈX cŒ2ÈX cŒ2šg“°¨ŸQ?£~FýŒúõ3êgÛaìÈX cŒ2"gDΈœ9#rFäŒÈ‘³c@éŒU²pÎ¥¤þÝÏ1'’úþOñˆ²sÀ Ù wÆÙ% |FøŒðá3Âg„ÏŸ>#|FøŒðá3Âg„ÏŸ>#|FøŒðá3Âg±å‹ðá3Âg„ÏŸ>#|FøŒðá3Âg„ÏŸ>#|FøŒð¥K- _¾$|Iø’ð%áK—„/ _¾$|Iø’ð%áK—„/ _¾$|Iø’ð%áK—„/ _Rº áO'õ_ý­xC“úïþ…xÄ% ”,P²@É% ”,P²@É% ”,P²@É% ”,P²@É% ”,P*åIàƒR)Ù¢¤~Iý’ú%õKê—Ô/©_R¿¤~Iý’ú%õKê—Ô/©_R¿¤~Iý’ú%õKê—Ô/©_R¿¤~Iý’ú%õKê—Ô/©_R¿¤~Iý’ú%õKr—Ô/7'õÿúûbü8¢d’J(Y dÒ.ÑÔ~ŸÔÆãÔNãÔ6ñÔVÑÔ&ãÔÑT¿;µ-4u—Aj3hªõ›Úšº£ µ –ÚFœÚî™Ú<œÚä™j©¥ö§6 §ëÀ.ÇT&µ¿3uëLª'œÚ?žÚË™Ú5žÚÁ™Ú+žÚ·™Ú!žÚ­™Ú œÚ£™úê—ºÏ&uóIz¬ä§vk¦îÞKõ‰S÷µ¥vR¦îfKíÇL5®S;$Sw®¥îJIÝeª÷©Fiê”Ô©ûNR{ÏSw›¤îHm;OµGS͵ÔîòÔ=IéMð&µñ8ÕhNm7NíMNíOCøIý|'¸ŸŒ-\l-Nm"Om(NmOÝ Ú0žº/+} ~¥ö§î‰Kí*NÝ —ÚKœºÿ-µƒ8µY&µo8u÷@j·pêž4öÇn/귨ߢ~+6 S¿Ûƒc·Cl ¦~+¶Gã?6S¿Â?LÆÆ7ÎK¢7“ñÿ¾8ÂØÌ-µbïotZÙ¢Å-¶hÅæ×èÎŶ_¶hmJÆVýpœes2vôq<Ú’ŒÝûûñhk2öC›ãѶdìOýb<ÚžŒýl'íHÆ~á÷ģɸÂSñhW2~øçÛŒú±x´'ÿãcñho2þ7ÿ`<Ú—Œg}-ÿîÎþÕ¡þÍéþýè›Òø¯üêß›á×þéߟá×ÿã¿ñ›#üö0N?_©ßŠmÔoÝKæÿL-™·äjܦ÷ìÅ=lüò5nÍóН^ñ5î~Œ;¾lJÿ÷µÙŠþ•}¾rÉW.ùwïqÉ׸,îu‹»÷¸ä+—|å’¯qçdܺ÷KrÉ׸K’K¾Æ½‘qßXÜåÇ%_¹ä+—T£÷¼ízÏ«T¬R±JÅ*«T¬R±JÅ*«T¬R±JÅ*«T¼QñKÅ[TQqDÅGTQqDÅGTQ)•BQ)•BQ)•BQ)•BQ)•BQ)•BQ)V E¥PT E¥PT E¥PT E¥PT E¥PT E¥PT E¥PT E¥PT E¥PT E¥PT E¥PT E¥PT EEøŠðá+ÂW„¯_¾"|EøŠðá+ÂW„¯_¾"|EøŠðá+ÂW„¯_¾"|EøŠðá+ÂW„¯_¾"|Eøj$ü’#á/Œ>oêÅWþNíÿy@ÀÉ endstream endobj startxref 343983 %%EOF QATzip-1.2.0/include/000077500000000000000000000000001456106226300143125ustar00rootroot00000000000000QATzip-1.2.0/include/qatzip.h000077500000000000000000002712541456106226300160110ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ /** ***************************************************************************** * @file qatzip.h * * @defgroup qatZip Data Compression API * * @description * These functions specify the API for data compression operations. * * @remarks * * *****************************************************************************/ #ifndef _QATZIP_H #define _QATZIP_H #ifdef __cplusplus extern"C" { #endif #include #include /** ***************************************************************************** * @ingroup qatZip * QATzip Major Version Number * @description * The QATzip API major version number. This number will be incremented * when significant changes to the API have occurred. * The combination of the major and minor number definitions represent * the complete version number for this interface. * *****************************************************************************/ #define QATZIP_API_VERSION_NUM_MAJOR (2) /** ***************************************************************************** * @ingroup qatZip * QATzip Minor Version Number * @description * The QATzip API minor version number. This number will be incremented * when minor changes to the API have occurred. The combination of the major * and minor number definitions represent the complete version number for * this interface. *****************************************************************************/ #define QATZIP_API_VERSION_NUM_MINOR (3) /* Define a macro as an integer to test */ #define QATZIP_API_VERSION (QATZIP_API_VERSION_NUM_MAJOR * 10000 + \ QATZIP_API_VERSION_NUM_MINOR * 100) /** * These macros define how the project will be built * QATZIP_LINK_DLL must be defined if linking the DLL * QATZIP_BUILD_DLL must be defined when building a DLL * No definition required if building the project as static library */ #if defined QATZIP_LINK_DLL #define QATZIP_API __declspec(dllimport) #elif defined QATZIP_BUILD_DLL #define QATZIP_API __declspec(dllexport) #else #define QATZIP_API #endif /** ***************************************************************************** * * This API provides access to underlying compression functions in QAT * hardware. The API supports an implementation that provides compression * service in software if all of the required resources are not available * to execute the compression service in hardware. * * The API supports threaded applications. * Applications can create threads and each of these threads can invoke the * API defined herein. * * For simplicity, initializations and setup function calls are not * required to obtain compression services. If the initialization and setup * functions are not called before compression or decompression requests, then * they will be called with default arguments from within the compression or * decompression functions. This results in several legal calling scenarios, * described below. * * Scenario 1 - All functions explicitly invoked by caller, with all arguments provided. * * qzInit(&sess, sw_backup); * qzSetupSession(&sess, ¶ms); * qzCompress(&sess, src, &src_len, dest, &dest_len, 1); * qzDecompress(&sess, src, &src_len, dest, &dest_len); * qzTeardownSession(&sess); * qzClose(&sess); * * * Scenario 2 - Initialization function called, setup function not invoked by caller. * This scenario can be used to specify the sw_backup argument to * qzInit. * * qzInit(&sess, sw_backup); * qzCompress(&sess, src, &src_len, dest, &dest_len, 1); * calls qzSetupSession(sess, NULL); * qzTeardownSession(&sess); * qzClose(&sess); * * * Scenario 3 - Calling application simply invokes the actual qzCompress functions. * * qzCompress(&sess, src, &src_len, dest, &dest_len, 0); * calls qzInit(sess, 1); * calls qzSetupSession(sess, NULL); * qzCompress(&sess, src, &src_len, dest, &dest_len, 1); * * Notes: Invoking qzSetupSession with NULL for params sets up a session with * default session attributed, detailed in the function description below. * * If an application terminates without invoking tear down and close * functions, process termination will invoke memory and hardware instance * cleanup. * * If a thread terminates without invoking tear down and close functions, * memory and hardware are not cleaned up until the application exits. * * Additions for QAT 2.0 and beyond platforms though Extending * QzSessionParamsGen3_T, QzDataFormatGen3_T and Using qzSetupSessionGen3 * to setup session. * 1. Addition of LZ4 and LZ4s * 2. Addition of post processing functions for out of LZ4s * 3. Compression level up to 12 for LZ4 and LZ4s * 4. Support for gzip header with additional compression algorithms * *****************************************************************************/ /** ***************************************************************************** * @ingroup qatZip * Supported Huffman Headers * * @description * This enumerated list identifies the Huffman header types * supported by QATzip. * *****************************************************************************/ typedef enum QzHuffmanHdr_E { QZ_DYNAMIC_HDR = 0, /**< Full Dynamic Huffman Trees */ QZ_STATIC_HDR /**< Static Huffman Trees */ } QzHuffmanHdr_T; /** ***************************************************************************** * @ingroup qatZip * Supported memory types * * @description * This enumerated list identifies memory types supported * by QATzip. * *****************************************************************************/ typedef enum PinMem_E { COMMON_MEM = 0, /**< Allocate non-contiguous memory */ PINNED_MEM /**< Allocate contiguous memory */ } PinMem_T; /** ***************************************************************************** * @ingroup qatZip * Compress or decompress setting * * @description * This enumerated list identifies the session directions * supported by QATzip. A session can be compress, decompress * or both. * *****************************************************************************/ typedef enum QzDirection_E { QZ_DIR_COMPRESS = 0, /**< Session will be used for compression */ QZ_DIR_DECOMPRESS, /**< Session will be used for decompression */ QZ_DIR_BOTH /**< Session will be used for both compression and decompression */ } QzDirection_T; /** ***************************************************************************** * @ingroup qatZip * Streaming API input and output format * * @description * This enumerated list identifies the data format supported by * QATzip streaming API. A format can be raw deflate data block, deflate * block wrapped by GZip header and footer, or deflate data block wrapped * by GZip extension header and footer. * *****************************************************************************/ typedef enum QzDataFormat_E { QZ_DEFLATE_4B = 0, /**< Data is in raw deflate format with 4 byte header */ QZ_DEFLATE_GZIP, /**< Data is in deflate wrapped by GZip header and footer */ QZ_DEFLATE_GZIP_EXT, /**< Data is in deflate wrapped by GZip extended header and footer */ QZ_DEFLATE_RAW, /**< Data is in raw deflate format */ QZ_FMT_NUM } QzDataFormat_T; /** ***************************************************************************** * @ingroup qatZip * Supported polling mode * * @description * Specifies whether the instance must be busy polling, * or be periodical polling. * *****************************************************************************/ typedef enum QzPollingMode_E { QZ_PERIODICAL_POLLING = 0, /**< No busy polling */ QZ_BUSY_POLLING, /**< busy polling */ } QzPollingMode_T; /** ***************************************************************************** * @ingroup qatZip * Supported checksum type * * @description * This enumerated list identifies the checksum type for input/output * data. The format can be CRC32, Adler or none. * *****************************************************************************/ typedef enum QzCrcType_E { QZ_CRC32 = 0, /**< CRC32 checksum */ QZ_ADLER, /**< Adler checksum */ NONE /**< No checksum */ } QzCrcType_T; /** ***************************************************************************** * @ingroup qatZip * Software Component type * * @description * This enumerated list specifies the type of software that is being * described. * *****************************************************************************/ typedef enum QzSoftwareComponentType_E { QZ_COMPONENT_FIRMWARE = 0, QZ_COMPONENT_KERNEL_DRIVER, QZ_COMPONENT_USER_DRIVER, QZ_COMPONENT_QATZIP_API, QZ_COMPONENT_SOFTWARE_PROVIDER } QzSoftwareComponentType_T; /** ***************************************************************************** * @ingroup qatZip * QATzip Session Status definitions and function return codes * * @description * This list identifies valid values for session status and function * return codes. * *****************************************************************************/ #define QZ_OK (0) /**< Success */ #define QZ_DUPLICATE (1) /**< Can not process function again. No failure */ #define QZ_FORCE_SW (2) /**< Using SW: Switch to software because of previous block */ #define QZ_PARAMS (-1) /**< Invalid parameter in function call */ #define QZ_FAIL (-2) /**< Unspecified error */ #define QZ_BUF_ERROR (-3) /**< Insufficient buffer error */ #define QZ_DATA_ERROR (-4) /**< Input data was corrupted */ #define QZ_TIMEOUT (-5) /**< Operation timed out */ #define QZ_INTEG (-100) /**< Integrity checked failed */ #define QZ_NO_HW (11) /**< Using SW: No QAT HW detected */ #define QZ_NO_MDRV (12) /**< Using SW: No memory driver detected */ #define QZ_NO_INST_ATTACH (13) /**< Using SW: Could not attach to an instance */ #define QZ_LOW_MEM (14) /**< Using SW: Not enough pinned memory */ #define QZ_LOW_DEST_MEM (15) /**< Using SW: Not enough pinned memory for dest buffer */ #define QZ_UNSUPPORTED_FMT (16) /**< Using SW: QAT device does not support data format */ #define QZ_NONE (100) /**< Device uninitialized */ #define QZ_NOSW_NO_HW (-101) /**< Not using SW: No QAT HW detected */ #define QZ_NOSW_NO_MDRV (-102) /**< Not using SW: No memory driver detected */ #define QZ_NOSW_NO_INST_ATTACH (-103) /**< Not using SW: Could not attach to instance */ #define QZ_NOSW_LOW_MEM (-104) /**< Not using SW: not enough pinned memory */ #define QZ_NO_SW_AVAIL (-105) /**sw_backup that is set to 1. * * Before this function is called, the hardware must have been * successfully started via qzInit. * * If *sess includes an existing hardware or software session, then * QZ_DUPLICATE will be returned without modifying the existing session. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in] params Parameters for session * * * @retval QZ_OK Function executed successfully. A hardware * or software based compression session has been * created * @retval QZ_DUPLICATE *sess includes an existing hardware or * software session * @retval QZ_PARAMS *sess is NULL or member of params is invalid * @retval QZ_NOSW_NO_HW No hardware and no sw session being * established * @retval QZ_NOSW_NO_MDRV No memory driver. No software session * established * @retval QZ_NOSW_NO_INST_ATTACH No instance available * No software session established * @retval QZ_NO_LOW_MEM Not enough pinned memory available * No software session established * @retval QZ_UNSUPPORTED_FMT No support for requested algorithm; * using software * @retval QZ_NOSW_UNSUPPORTED_FMT No support for requested algorithm; * No software session established * @retval QZ_NO_SW_AVAIL No software is available. This may returned * when sw_backup is set to 1 but the session * does not support software backup or software * backup is unavailable to the application. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzSetupSession(QzSession_T *sess, QzSessionParams_T *params); QATZIP_API int qzSetupSessionDeflate(QzSession_T *sess, QzSessionParamsDeflate_T *params); QATZIP_API int qzSetupSessionLZ4(QzSession_T *sess, QzSessionParamsLZ4_T *params); QATZIP_API int qzSetupSessionLZ4S(QzSession_T *sess, QzSessionParamsLZ4S_T *params); /** ***************************************************************************** * @ingroup qatZip * Compress a buffer * * @description * This function will compress a buffer if either a hardware based * session or a software based session is available. If no session has * been established - as indicated by the contents of *sess - then this * function will attempt to set up a session using qzInit and qzSetupSession. * * The resulting compressed block of data will be composed of one or more * gzip blocks, as per RFC 1952. * * This function will place completed compression blocks in the output * buffer. * * The caller must check the updated src_len. This value will be the * number of consumed bytes on exit. The calling API may have to * process the destination buffer and call again. * * The parameter dest_len will be set to the number of bytes produced in * the destination buffer. This value may be zero if no data was produced * which may occur if the consumed data is retained internally. A * possible reason for this may be small amounts of data in the src * buffer. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in] src Point to source buffer * @param[in,out] src_len Length of source buffer. Modified to number * of bytes consumed * @param[in] dest Point to destination buffer * @param[in,out] dest_len Length of destination buffer. Modified * to length of compressed data when * function returns * @param[in] last 1 for 'No more data to be compressed' * 0 for 'More data to be compressed' * @param[in,out] ext_rc qzCompressExt only. * If not NULL, ext_rc point to a location where * extended return codes may be returned. See * extended return code section for details. * if NULL, no extended information will be * provided. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzCompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last); QATZIP_API int qzCompressExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, uint64_t *ext_rc); /** ***************************************************************************** * @ingroup qatZip * Compress a buffer and return the CRC checksum * * @description * This function will compress a buffer if either a hardware based * session or a software based session is available. If no session has been * established - as indicated by the contents of *sess - then this function * will attempt to set up a session using qzInit and qzSetupSession. * * The resulting compressed block of data will be composed of one or more * gzip blocks, as per RFC 1952. * * This function will place completed compression blocks in the output * buffer and put CRC32 or CRC64 checksum for compressed input data in * the user provided buffer *crc. * * The caller must check the updated src_len. This value will be the * number of consumed bytes on exit. The calling API may have to * process the destination buffer and call again. * * The parameter dest_len will be set to the number of bytes produced in * the destination buffer. This value may be zero if no data was produced * which may occur if the consumed data is retained internally. A * possible reason for this may be small amounts of data in the src * buffer. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in] src Point to source buffer * @param[in,out] src_len Length of source buffer. Modified to number * of bytes consumed * @param[in] dest Point to destination buffer * @param[in,out] dest_len Length of destination buffer. Modified * to length of compressed data when * function returns * @param[in] last 1 for 'No more data to be compressed' * 0 for 'More data to be compressed' * @param[in,out] crc Pointer to CRC32 or CRC64 checksum buffer * @param[in,out] ext_rc qzCompressCrcExt or qzCompressCrc64Ext only. * If not NULL, ext_rc point to a location where * extended return codes may be returned. See * extended return code section for details. * if NULL, no extended information will be * provided. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzCompressCrc(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, unsigned long *crc); QATZIP_API int qzCompressCrcExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, unsigned long *crc, uint64_t *ext_rc); QATZIP_API int qzCompressCrc64(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, uint64_t *crc); QATZIP_API int qzCompressCrc64Ext(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, uint64_t *crc, uint64_t *ext_rc); /** ***************************************************************************** * @ingroup qatZip * Compress a buffer and write metadata for each compressed block into * the opaque metadata structure. * * @description * This function will compress a buffer if either a hardware based * session or a software based session is available. If no session has * been established - as indicated by the contents of *sess - then this * function will attempt to set up a session using qzInit and * qzSetupSession. * * This function will place completed compression blocks in the output * buffer. * * The caller must check the updated src_len. This value will be the * number of consumed bytes on exit. The calling API may have to * process the destination buffer and call again. * * The parameter dest_len will be set to the number of bytes produced in * the destination buffer. This value may be zero if no data was produced * which may occur if the consumed data is retained internally. A * possible reason for this may be small amounts of data in the src * buffer. * * The metadata for each compressed block will be written into the opaque * metadata structure specified as function param metadata. * * comp_thrshold specifies compression threshold of a block. * If compressed size of the block is > comp_thrshold, the * compression function shall copy the uncompressed data to the output * buffer and set the size of the block in the metadata to the size of the * uncompressed block. If the compressed size of the block is <= * comp_thrshold, the compressed data will be copied to the output buffer * and the compressed size will be set in the metadata. * * hw_buff_sz_override specifies the data size to be used for the each * compression operation. It overrides the hw_buff_sz parameter specified * at session creation. If 0 is provided for this parameter, then the * hw_buff_sz specified at session creation will be used. Memory for the * opaque metadata structure should be allocated based on the hw_buff_sz * or the hw_buff_sz_override that is used for the compression operation. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and * session data) * @param[in] src Point to source buffer. * @param[in,out] src_len Length of source buffer. Modified to * number of bytes consumed. * @param[in] dest Point to destination buffer. * @param[in,out] dest_len Length of destination buffer. Modified * to length of compressed data when * function returns. * @param[in] last 1 for 'No more data to be compressed' * 0 for 'More data to be compressed' * @param[in,out] ext_rc If not NULL, ext_rc point to a location * where extended return codes may be * returned. See extended return code * section for details. if NULL, no * extended information will be provided. * @param[in,out] metadata Pointer to opaque metadata. * @param[in] hw_buff_sz_override Data size to be used for compression. * @param[in] comp_thrshold Compressed block threshold. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess or metadata is NULL or Member of * params is invalid, hw_buff_sz_override * is invalid data size. * @retval QZ_METADATA_OVERFLOW Unable to populate metadata due to * insufficient memory allocated. * @retval QZ_NOT_SUPPORTED Compression with metadata is not * supported with given algorithm * or format. * @retval QZ_NOSW_NO_HW Function did not find an installed * kernel driver or software provider. * @retval QZ_NOSW_NO_INST_ATTACH No instance available. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzCompressWithMetadataExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, uint64_t *ext_rc, QzMetadataBlob_T *metadata, uint32_t hw_buff_sz_override, uint32_t comp_thrshold); /** ***************************************************************************** * @ingroup qatZip * Decompress a buffer * * @description * This function will decompress a buffer if either a hardware based * session or a software based session is available. If no session has been * established - as indicated by the contents of *sess - then this function * will attempt to set up a session using qzInit and qzSetupSession. * * The input compressed block of data will be composed of one or more * gzip blocks, as per RFC 1952. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in] src Point to source buffer * @param[in] src_len Length of source buffer. Modified to * length of processed compressed data * when function returns * @param[in] dest Point to destination buffer * @param[in,out] dest_len Length of destination buffer. Modified * to length of decompressed data when * function returns * @param[in,out] ext_rc qzDecompressExt only. * If not NULL, ext_rc point to a location where * extended return codes may be returned. See * extended return code section for details. * if NULL, no extended information will be * provided. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzDecompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len); QATZIP_API int qzDecompressExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, uint64_t *ext_rc); /** ***************************************************************************** * @ingroup qatZip * Decompress a buffer and return the CRC checksum * * @description * This function will decompress a buffer if either a hardware based * session or a software based session is available. If no session has been * established - as indicated by the contents of *sess - then this function * will attempt to set up a session using qzInit and qzSetupSession. * * This function will place completed decompression chunks in the output * buffer and put the CRC32 or CRC64 checksum for compressed input data in * the user provided buffer *crc. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in] src Point to source buffer * @param[in] src_len Length of source buffer. Modified to * length of processed compressed data * when function returns * @param[in] dest Point to destination buffer * @param[in,out] dest_len Length of destination buffer. Modified * to length of decompressed data when * function returns * @param[in,out] crc Pointer to CRC32 or CRC64 checksum buffer * @param[in,out] ext_rc qzDecompressCrcExt or qzDecompressCrc64Ext only. * If not NULL, ext_rc point to a location where * extended return codes may be returned. See * extended return code section for details. * if NULL, no extended information will be * provided. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzDecompressCrc(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned long *crc); QATZIP_API int qzDecompressCrcExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned long *crc, uint64_t *ext_rc); QATZIP_API int qzDecompressCrc64(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, uint64_t *crc); QATZIP_API int qzDecompressCrc64Ext(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, uint64_t *crc, uint64_t *ext_rc); /** ***************************************************************************** * @ingroup qatZip * Decompress a buffer with metadata. * * @description * This function will decompress a buffer if either a hardware based * session or a software based session is available. * If no session has been established - as indicated by the content * of *sess - then this function will attempt to set up a session using * qzInit and qzSetupSession. * * The metadata function parameter specifies metadata of compressed file * which can be used for regular or parallel decompression. * * hw_buff_sz_override specifies the data size to be used for the each * decompression operation. It overrides the hw_buff_sz parameter specified * at session creation. If 0 is provided for this parameter, then the * hw_buff_sz specified at session creation will be used. Memory for the * opaque metadata structure should be allocated based on the hw_buff_sz * or the hw_buff_sz_override that is used for the compression operation. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in] src Point to source buffer * @param[in] src_len Length of source buffer. Modified to * length of processed compressed data * when function returns * @param[in] dest Point to destination buffer * @param[in,out] dest_len Length of destination buffer. Modified * to length of decompressed data when * function returns * @param[in,out] ext_rc If not NULL, ext_rc points to a location * where extended return codes may be * returned. See extended return code * section for details. * if NULL, no extended information will be * provided. * @param[in] metadata Pointer to opaque metadata. * @param[in] hw_buff_sz_override Expected size of decompressed block. * * @retval QZ_OK Function executed successfully. * @retval QZ_FAIL Function did not succeed. * @retval QZ_PARAMS *sess or metadata is NULL or Member of * params is invalid, hw_buff_sz_override * is invalid data size. * @retval QZ_METADATA_OVERFLOW Unable to populate metadata due to * insufficient memory allocated. * @retval QZ_NOT_SUPPORTED Decompression with metadata is not * supported with given algorithm * or format. * @retval QZ_NOSW_NO_HW Function did not find an installed * kernel driver or software provider. * @retval QZ_NOSW_NO_INST_ATTACH No instance available. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzDecompressWithMetadataExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, uint64_t *ext_rc, QzMetadataBlob_T *metadata, uint32_t hw_buff_sz_override); /** ***************************************************************************** * @ingroup qatZip * Uninitialize a QATzip session * * @description * This function disconnects a session from a hardware instance and * deallocates buffers. If no session has been initialized, then no * action will take place. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzTeardownSession(QzSession_T *sess); /** ***************************************************************************** * @ingroup qatZip * Terminates a QATzip session * * @description * This function closes the connection with QAT. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzClose(QzSession_T *sess); /** ***************************************************************************** * @ingroup qatZip * Get current QAT status * * @description * This function retrieves the status of QAT in the platform. * The status structure will be filled in as follows: * qat_hw_count Number of discovered QAT devices on PCU bus * qat_service_init 1 if qzInit has been successfully run, 0 otherwise * qat_mem_drvr 1 if the QAT memory driver is installed, 0 otherwise * qat_instance_attach 1 if session has attached to a hardware instance, * 0 otherwise * memory_alloced Amount of memory, in kilobytes, from kernel or huge * pages allocated by this process/thread. * using_huge_pages 1 if memory is being allocated from huge pages, 0 if * memory is being allocated from standard kernel memory * hw_session_status Hw session status: one of: * QZ_OK * QZ_FAIL * QZ_NO_HW * QZ_NO_MDRV * QZ_NO_INST_ATTACH * QZ_LOW_MEM * QZ_NOSW_NO_HW * QZ_NOSW_NO_MDRV * QZ_NOSW_NO_INST_ATTACH * QZ_NOSW_LOW_MEM * QZ_NO_SW_AVAIL * * Applications should verify the elements of the status structure are * correct for the required operations. It should be noted that some * information will be available only after qzInit has been called, either * implicitly or explicitly. The qat_service_init element of the status * structure will indicate if initialization has taken place. * * The hw_session_status will depend on the availability of hardware based * compression and software based compression. The following table indicates * what hw_session_status based on the availability of compression engines * and the sw_backup flag. * * | HW | SW Engine | sw_backup | hw_session_stat | * | avail | avail | setting | | * |-------|-----------|-----------|-------------------| * | N | N | 0 | QZ_NOSW_NO_HW | * | N | N | 1 | QZ_NOSW_NO_HW | * | N | Y | 0 | QZ_FAIL | * | N | Y | 1 | QZ_NO_HW (1) | * | Y | N | 0 | QZ_OK | * | Y | N | 1 | QZ_NO_SW_AVAIL (2)| * | Y | Y | 0 | QZ_OK | * | Y | Y | 1 | QZ_OK | * * Note 1: * If an application indicates software backup is required by setting * sw_backup=1, and a software engine is available and if no hardware based * compression engine is available then the hw_session_status will be set * to QZ_NO_HW. All compression and decompression will use the software * engine. * Note 2: * If an application indicates software backup is required by setting * sw_backup=1, and if no software based compression engine is available * then the hw_session_status will be set to QZ_NO_SW_AVAIL. In this * case, QAT based compression may be used however no software backup * will available. * If the application relies on software backup being avialable, then * this return code can be treated as an error. * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in] status Pointer to QATzip status structure * @retval QZ_OK Function executed successfully. The hardware based * compression session has been created * @retval QZ_PARAMS *status is NULL * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzGetStatus(QzSession_T *sess, QzStatus_T *status); /** ***************************************************************************** * @ingroup qatZip * Get the maximum compressed output length * * @description * Get the maximum compressed output length. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] * src_sz Input data length in bytes * sess Session handle * (pointer to opaque instance and session data) * * @retval dest_sz Max compressed data output length in bytes. * When src_sz is equal to 0, the return value is QZ_COMPRESSED_SZ_OF_EMPTY_FILE(34). * When integer overflow happens, the return value is 0 * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ #define QZ_SKID_PAD_SZ 48 #define QZ_COMPRESSED_SZ_OF_EMPTY_FILE 34 QATZIP_API unsigned int qzMaxCompressedLength(unsigned int src_sz, QzSession_T *sess); /** ***************************************************************************** * @ingroup qatZip * Set default QzSessionParams_T value * * @description * Set default QzSessionParams_T value. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] * defaults The pointer to value to be set as default * * @retval QZ_OK Success on setting default value * @retval QZ_PARAM Fail to set default value * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzSetDefaults(QzSessionParams_T *defaults); QATZIP_API int qzSetDefaultsDeflate(QzSessionParamsDeflate_T *defaults); QATZIP_API int qzSetDefaultsLZ4(QzSessionParamsLZ4_T *defaults); QATZIP_API int qzSetDefaultsLZ4S(QzSessionParamsLZ4S_T *defaults); /** ***************************************************************************** * @ingroup qatZip * Get default QzSessionParams_T value * * @description * Get default QzSessionParams_T value. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] defaults The pointer to default value * * @retval QZ_OK Success on getting default value * @retval QZ_PARAM Fail to get default value * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzGetDefaults(QzSessionParams_T *defaults); QATZIP_API int qzGetDefaultsDeflate(QzSessionParamsDeflate_T *defaults); QATZIP_API int qzGetDefaultsLZ4(QzSessionParamsLZ4_T *defaults); QATZIP_API int qzGetDefaultsLZ4S(QzSessionParamsLZ4S_T *defaults); /** ***************************************************************************** * @ingroup qatZip * Allocate different types of memory * * @description * Allocate different types of memory. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sz Memory size to be allocated * @param[in] numa NUMA node from which to allocate memory * @param[in] force_pinned PINNED_MEM allocate contiguous memory * COMMON_MEM allocate non-contiguous memory * * @retval NULL Fail to allocate memory * @retval address The address of allocated memory * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API void *qzMalloc(size_t sz, int numa, int force_pinned); /** ***************************************************************************** * @ingroup qatZip * Allocate memory for metadata. * * @description * Allocate memory for metadata. The function takes the size of entire * input buffer and the data size at which individual block will be * compressed. These parameters will be used to calculate and allocate * required memory for metadata. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in, out] metadata Pointer to opaque metadata. * @param[in] data_size Size of uncompressed buffer. * @param[in] hw_buff_sz Data size at which individual block * will be compressed. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *metadata is NULL, or data_size is 0, * or data_size is greater than 1GB, or * incorrect hw_buff_sz. * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzAllocateMetadata(QzMetadataBlob_T *metadata, size_t data_size, uint32_t hw_buff_sz); /** ***************************************************************************** * @ingroup qatZip * Free allocated memory * * @description * Free allocated memory. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] m Memory address to be freed * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API void qzFree(void *m); /** ***************************************************************************** * @ingroup qatZip * Free memory allocated for metadata. * * @description * Free memory allocated for metadata. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] metadata Pointer to opaque metadata. * * @retval QZ_OK Function executed successfully. * @retval QZ_FAIL Function did not succeed. * @retval QZ_PARAMS metadata is NULL. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzFreeMetadata(QzMetadataBlob_T metadata); /** ***************************************************************************** * @ingroup qatZip * Check whether the address is available * * @description * Check whether the address is available. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] * a Address to be checked * * @retval 1 The address is available * @retval 0 The address is not available * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzMemFindAddr(unsigned char *a); /** ***************************************************************************** * @ingroup qatZip * QATzip Stream data storage * * @description * This structure contains metadata needed for stream operation. * *****************************************************************************/ typedef struct QzStream_S { unsigned int in_sz; /**< Set by application, reset by QATzip to indicate consumed data */ unsigned int out_sz; /**< Set by application, reset by QATzip to indicate processed data */ unsigned char *in ; /**< Input data pointer set by application */ unsigned char *out ; /**< Output data pointer set by application */ unsigned int pending_in; /**< Unprocessed bytes held in QATzip */ unsigned int pending_out; /**< Processed bytes held in QATzip */ QzCrcType_T crc_type; /**< Checksum type in Adler, CRC32 or none */ unsigned int crc_32; /**< Checksum value */ unsigned long long reserved; /**< Reserved for future use */ void *opaque; /**< Internal storage managed by QATzip */ } QzStream_T; /** ***************************************************************************** * @ingroup qatZip * Compress data in stream and return checksum * * @description * This function will compress data in stream buffer if either a hardware * based session or a software based session is available. If no session * has been established - as indicated by the contents of *sess - then this * function will attempt to set up a session using qzInit and qzSetupSession. * The function will start to compress the data when receiving sufficient * number of bytes - as defined by hw_buff_sz in QzSessionParams_T - or * reaching the end of input data - as indicated by last parameter. * * The resulting compressed block of data will be composed of one or more * gzip blocks, per RFC 1952, or deflate blocks, per RFC 1951. * * This function will place completed compression blocks in the *out * of QzStream_T structure and put checksum for compressed input data * in crc32 of QzStream_T structure. * * The caller must check the updated in_sz of QzStream_T. This value will * be the number of consumed bytes on exit. The calling API may have to * process the destination buffer and call again. * * The parameter out_sz in QzStream_T will be set to the number of bytes * produced in the destination buffer. This value may be zero if no data * was produced which may occur if the consumed data is retained internally. * A possible reason for this may be small amounts of data in the src * buffer. * * The caller must check the updated pending_in of QzStream_T. This value * will be the number of unprocessed bytes held in QATzip. The calling API * may have to feed more input data or indicate reaching the end of input * and call again. * * The caller must check the updated pending_out of QzStream_T. This value * will be the number of processed bytes held in QATzip. The calling API * may have to process the destination buffer and call again. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in,out] strm Stream handle * @param[in] last 1 for 'No more data to be compressed' * 0 for 'More data to be compressed' * (always set to 1 in the Microsoft(R) * Windows(TM) QATzip implementation) * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzCompressStream(QzSession_T *sess, QzStream_T *strm, unsigned int last); /** ***************************************************************************** * @ingroup qatZip * Decompress data in stream and return checksum * * @description * This function will decompress data in stream buffer if either a hardware * based session or a software based session is available. If no session * has been established - as indicated by the contents of *sess - then this * function will attempt to set up a session using qzInit and qzSetupSession. * The function will start to decompress the data when receiving sufficient * number of bytes - as defined by hw_buff_sz in QzSessionParams_T - or * reaching the end of input data - as indicated by last parameter. * * The input compressed block of data will be composed of one or more * gzip blocks, per RFC 1952, or deflate blocks, per RFC 1951. * * This function will place completed decompression blocks in the *out * of QzStream_T structure and put checksum for decompressed data in * crc32 of QzStream_T structure. * * The caller must check the updated in_sz of QzStream_T. This value will * be the number of consumed bytes on exit. The calling API may have to * process the destination buffer and call again. * * The parameter out_sz in QzStream_T will be set to the number of bytes * produced in the destination buffer. This value may be zero if no data * was produced which may occur if the consumed data is retained internally. * A possible reason for this may be small amounts of data in the src * buffer. * * The caller must check the updated pending_in of QzStream_T. This value * will be the number of unprocessed bytes held in QATzip. The calling API * may have to feed more input data or indicate reaching the end of input * and call again. * * The caller must check the updated pending_out of QzStream_T. This value * will be the number of processed bytes held in QATzip. The calling API * may have to process the destination buffer and call again. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[in,out] strm Stream handle * @param[in] last 1 for 'No more data to be compressed' * 0 for 'More data to be compressed' * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * @retval QZ_NEED_MORE *last is set but end of block is absent * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzDecompressStream(QzSession_T *sess, QzStream_T *strm, unsigned int last); /** ***************************************************************************** * @ingroup qatZip * Terminates a QATzip stream * * @description * This function disconnects stream handle from session handle then reset * stream flag and release stream memory. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_PARAMS *sess is NULL or member of params is invalid * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzEndStream(QzSession_T *sess, QzStream_T *strm); /** ***************************************************************************** * @ingroup qatZip * Requests the release versions of the QATZip Library sub components. * * @description * Populate an array of pre-allocated QzSoftwareVersionInfo_T structs * with the names and versions of QATzip sub components. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * Yes * @threadSafe * Yes * * @param[in, out] api_info pointer to a QzSoftwareVersionInfo_T * structure to populate. * @param[in, out] num_elem pointer to an unsigned int expressing * how many elements are in the array * provided in api_info * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_NO_SW_AVAIL Function did not find a software provider for * fallback * @retval QZ_NO_HW Function did not find an installed kernel driver * @retval QZ_NOSW_NO_HW Functions did not find an installed kernel driver or software provider * @retval QZ_PARAMS *api_info or num_elem is NULL or not large * enough to store all QzSoftwareVersionInfo_T * structures * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzGetSoftwareComponentVersionList(QzSoftwareVersionInfo_T *api_info, unsigned int *num_elem); /** ***************************************************************************** * @ingroup qatZip * Requests the number of Software components used by the QATZip library * * @description * This function populates num_elem variable with the number of * software components available to the library. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * Yes * @threadSafe * Yes * * @param[in, out] num_elem pointer to an unsigned int to populate * how many software componets are associated * with QATZip * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Function did not succeed * @retval QZ_NO_SW_AVAIL Function did not find a software provider for * fallback * @retval QZ_NO_HW Function did not find an installed kernel driver * @retval QZ_NOSW_NO_HW Functions did not find an installed kernel driver or software provider * @retval QZ_PARAMS *num_elem is NULL * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzGetSoftwareComponentCount(unsigned int *num_elem); /** ***************************************************************************** * @ingroup qatZip * Requests the CRC64 configuration of the provided session * * @description * This function populates crc64_config with the CRC64 configuration * details of sess. This function has a dependency on invoking a setup * session function first. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * Yes * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[out] crc64_config Configuration for CRC 64 generation. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Session was not setup * @retval QZ_PARAMS *sess or *crc64_config is NULL * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzGetSessionCrc64Config(QzSession_T *sess, QzCrc64Config_T *crc64_config); /** ***************************************************************************** * @ingroup qatZip * Sets the CRC64 configuration of the provided session with a * user defined set of parameters. * * @description * This function populates the CRC64 configuration details of sess * using the paramaters provided in crc64_config. This function has a * dependency on invoking a setup session function first. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * Yes * @threadSafe * Yes * * @param[in] sess Session handle * (pointer to opaque instance and session data) * @param[out] crc64_config Configuration for CRC 64 generation. * * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Session was not setup * @retval QZ_PARAMS *sess or *crc64_config is NULL or contains * invalid paramters. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzSetSessionCrc64Config(QzSession_T *sess, QzCrc64Config_T *crc64_config); /** ***************************************************************************** * @ingroup qatZip * Read metadata parameters. * * @description * This function reads metadata information for the block specified by the * function param block_num. * * block_offset returns offset value in bytes from the previous compressed * block of the compressed data. * * block_size returns the block size in bytes of the compressed block. * Some blocks may be uncompressed if size > threshold as specified during * compression and the size returned will reflect the same. * * block_flags returns the value 1 if the data is compressed and 0 if the * data is not compressed. * * block_hash returns the xxHash value of the plain text of the hw_buff_sz * payload sent for compression operation. * * If NULL is specified for any of the metadata parameters (block_offset, * block_size, block_flags, block_hash) reading the parameter value * will be ignored. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] block_num Block number of which metadata * information should be read. * @param[in] metadata Pointer to opaque metadata. * @param[in, out] block_offset Pointer to the block offset value. * @param[in, out] block_size Pointer to the block size value. * @param[in, out] block_flags Pointer to the block flags value. * @param[in, out] block_hash Pointer to the block xxHash value. * * @retval QZ_OK Function executed successfully. * @retval QZ_FAIL Function did not succeed. * @retval QZ_PARAMS Metadata is NULL. * @retval QZ_OUT_OF_RANGE block_num specified is out of range. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzMetadataBlockRead(uint32_t block_num, QzMetadataBlob_T metadata, uint32_t *block_offset, uint32_t *block_size, uint32_t *block_flags, uint32_t *block_hash); /** ***************************************************************************** * @ingroup qatZip * Write metadata parameters. * * @description * This function writes metadata information for the block specified by the * function param block_num. * * block_offset writes offset value in bytes from the previous compressed * block of the compressed data. * * block_size writes the block size in bytes of the compressed block. * * block_flags causes the metadata to indicate the data is compressed if * passed a value of 1 and indicates uncompressed if value * passed is zero (0). * * block_hash writes the xxHash value of the plain text of the hw_buff_sz * payload sent for compression operation. * * If NULL is specified for any of the metadata parameters (block_offset, * block_size, block_flags, block_hash) writing the parameter value * into metadata will be ignored. * * @context * This function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] block_num Block number into which metadata information * should be written. * @param[in, out] metadata Pointer to opaque metadata. * @param[in] block_offset Pointer to the block offset value. * @param[in] block_size Pointer to the block size value. * @param[in] block_flags Pointer to the block flags value. * @param[in] block_hash Pointer to the block xxHash value. * * @retval QZ_OK Function executed successfully. * @retval QZ_FAIL Function did not succeed. * @retval QZ_PARAMS Metadata is NULL. * @retval QZ_OUT_OF_RANGE block_num specified is out of range. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ QATZIP_API int qzMetadataBlockWrite(uint32_t block_num, QzMetadataBlob_T metadata, uint32_t *block_offset, uint32_t *block_size, uint32_t *block_flags, uint32_t *block_hash); #ifdef __cplusplus } #endif #endif QATzip-1.2.0/include/qz_utils.h000066400000000000000000000102161456106226300163350ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ /** ***************************************************************************** * @file qz_utils.h * * @defgroup qatzip debug API * * @description * These functions specify the API for debug operations. * * @remarks * * *****************************************************************************/ #ifndef _QZ_UTILS_H_ #define _QZ_UTILS_H_ #include #include #include #include typedef enum SERV_E { COMPRESSION = 0, DECOMPRESSION } Serv_T; typedef enum ENGINE_E { HW = 0, SW } Engine_T; typedef struct ThreadList_S { unsigned int thread_id; unsigned int comp_hw_count; unsigned int comp_sw_count; unsigned int decomp_hw_count; unsigned int decomp_sw_count; struct ThreadList_S *next; } ThreadList_T; typedef struct QatThread_S { ThreadList_T *comp_th_list; unsigned int num_comp_th; pthread_mutex_t comp_lock; ThreadList_T *decomp_th_list; unsigned int num_decomp_th; pthread_mutex_t decomp_lock; } QatThread_T; extern void initDebugLock(void); extern void dumpThreadInfo(void); extern void insertThread(unsigned int th_id, Serv_T serv_type, Engine_T engine_type); #ifdef QATZIP_DEBUG static inline void QZ_DEBUG(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stdout, format, args); va_end(args); } #else #define QZ_DEBUG(...) #endif #ifdef ENABLE_TESTLOG #define QZ_TESTLOG(debuglevel, Readable, tag, ...) { \ FILE *fd = debuglevel > 1 ? stdout : stderr; \ fprintf(fd, "Tag: %s; ", tag); \ if (Readable) { \ fprintf(fd, "Time: %s %s; Location: %s->%s->%d; ", \ __DATE__, __TIME__, __FILE__, __func__, __LINE__); \ } else { \ struct timespec ts = { 0 }; \ clock_gettime(CLOCK_MONOTONIC_RAW, &ts); \ fprintf(fd, "Time: %ld.%06lds; ", ts.tv_sec, ts.tv_nsec / 1000); \ } \ fprintf(fd, "%s", "Info: "); \ fprintf(fd, __VA_ARGS__); \ fprintf(fd, " \n"); \ } #endif static inline void QZ_PRINT(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stdout, format, args); va_end(args); } static inline void QZ_ERROR(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); } #endif QATzip-1.2.0/man/000077500000000000000000000000001456106226300134425ustar00rootroot00000000000000QATzip-1.2.0/man/qzip.1000066400000000000000000000057201456106226300145130ustar00rootroot00000000000000.TH QZIP 1 local .SH NAME qzip \- compress or decompress with qat acceleration .SH SYNOPSIS .ll +8 .B qzip .RB [ " \-AdfhHkLCro " ] [ .I "name \&..." ] .ll -8 .br .SH DESCRIPTION QATzip is a user space library which builds on top of the Intel QuickAssist Technology user space library, to provide extended accelerated compression and decompression services by offloading the actual compression and decompression request(s) to the Intel Chipset Series. QATzip produces data using the standard gzip format (RFC1952) with extended headers. The data can be decompressed with a compliant gzip implementation. QATzip is design to take full advantage of the performance provided by Intel® QuickAssist Technology. .SH OPTIONS .TP .B \-A --algorithm set algorithm type, currently only support deflate .TP .B \-d --decompress decompress .TP .B \-f --force force overwrite of output file and compress links .TP .B \-h --help give this help .TP .B \-H --huffmanhdr set huffman header type .TP .B \-k --keep Keep (don't delete) input files during compression or decompression. .TP .B \-L --level set compression level .TP .B \-C --chunksz set chunk size .TP .B \-r set max in-flight request number .TP .B \-o set output file name .SH COPYRIGHT ################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ QATzip-1.2.0/qatzip.pc.in000066400000000000000000000004551456106226300151340ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: qatzip Description: Higher level library provides access to Intel QAT compression URL: https://github.com/intel/QATzip Version: @VERSION@ Libs: -L${libdir} -lqatzip Cflags: -I${includedir} Requires: zlib, liblz4 QATzip-1.2.0/qatzip.spec.in000066400000000000000000000104241456106226300154610ustar00rootroot00000000000000# SPDX-License-Identifier: MIT %global githubname @PACKAGE@ %global libqatzip_soversion 3 Name: @PACKAGE@ Version: @VERSION@ Release: 1%{?dist} Summary: Intel QuickAssist Technology (QAT) QATzip Library License: BSD URL: https://github.com/intel/%{githubname} Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz BuildRequires: gcc >= 4.8.5 BuildRequires: zlib-devel >= 1.2.7 BuildRequires: qatlib-devel >= 22.07.0 BuildRequires: autoconf automake libtool make lz4-devel # The purpose of the package is to support hardware that only exists on x86_64 platforms # https://bugzilla.redhat.com/show_bug.cgi?id=1987280 ExclusiveArch: x86_64 %description QATzip is a user space library which builds on top of the Intel QuickAssist Technology user space library, to provide extended accelerated compression and decompression services by offloading the actual compression and decompression request(s) to the Intel Chipset Series. QATzip produces data using the standard gzip* format (RFC1952) with extended headers. The data can be decompressed with a compliant gzip* implementation. QATzip is designed to take full advantage of the performance provided by Intel QuickAssist Technology. %package libs Summary: Libraries for the qatzip package %description libs This package contains libraries for applications to use the QATzip APIs. %package devel Summary: Development components for the libqatzip package Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description devel This package contains headers and libraries required to build applications that use the QATzip APIs. %prep %autosetup -p0 -n %{githubname}-%{version} %build %set_build_flags autoreconf -vif ./configure \ --bindir=%{_bindir} \ --libdir=%{_libdir} \ --includedir=%{_includedir} \ --mandir=%{_mandir} \ --prefix=%{_prefix} \ --enable-symbol %make_build %install %make_install rm %{buildroot}/%{_libdir}/libqatzip.a rm %{buildroot}/%{_libdir}/libqatzip.la rm -vf %{buildroot}%{_mandir}/*.pdf # Check section is not available for these functional and performance tests require special hardware. %files %license LICENSE* %{_mandir}/man1/qzip.1* %{_bindir}/qzip %{_bindir}/qatzip-test %files libs %license LICENSE* %{_libdir}/libqatzip.so.%{libqatzip_soversion}* %files devel %doc docs/QATzip-man.pdf %{_includedir}/qatzip.h %{_libdir}/libqatzip.so %{_libdir}/pkgconfig/*.pc %changelog * Fri Jan 02 2024 taorong - 1.2.0-1 - Update to qatzip v1.2.0 - Add qatzip-test tool - SW fallback - Fix some bugs * Mon Mar 06 2023 xinghong - 1.1.2-1 - Update to qatzip v1.1.2 - Update README, update driver configure files - Fix some bugs * Fri Jan 20 2023 Fedora Release Engineering - 1.1.1-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild * Wed Jan 11 2023 Vladis Dronov - 1.1.1-1 - Update to qatzip v1.1.1 - Add support for pkgconfig * Thu Nov 24 2022 Vladis Dronov - 1.1.0-1 - Rebuild for qatzip v1.1.0 * Mon Aug 08 2022 Vladis Dronov - 1.0.9-1 - Rebuild for qatzip v1.0.9 - Update to require qatlib-devel >= 22.07.0 due to soversion bump * Fri Jul 22 2022 Fedora Release Engineering - 1.0.7-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild * Wed Feb 09 2022 Vladis Dronov - 1.0.7-1 - Rebuild for qatzip v1.0.7 - Fix snprintf truncation check (bz 2046925) - Add -fstack-protector-strong build option (bz 2044889) * Fri Jan 21 2022 Fedora Release Engineering - 1.0.6-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild * Mon Sep 13 2021 zm627 - 1.0.6-3 - Rebuild for qatzip v1.0.6 * Sun Sep 12 2021 zm627 - 1.0.6-2 - Upload new qatzip source package and rebuild * Sun Sep 12 2021 zm627 - 1.0.6-1 - Update to latest qatlib and qatzip upstream release * Sun Sep 12 2021 zm627 - 1.0.5-3 - Add ExcludeArch ticket number * Sun Sep 12 2021 zm627 - 1.0.5-2 - Rebuilt for qatlib v21.08 * Tue Jul 13 2021 Ma Zheng - 1.0.5-1 - Initial version of RPM Package QATzip-1.2.0/specgen.sh000077500000000000000000000042111456106226300146500ustar00rootroot00000000000000#! /bin/bash ################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ set -o errexit # extract version numbers from qatzip_internal.h VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < src/qatzip_internal.h` # Generate qatzip.spec echo "Generating qatzip.spec" echo "QATzip version: $VER" sed < qatzip.spec.in 's/VERSION/'"$VER"'/g'> qatzip.spec if [ -f qatzip.spec ];then echo "qatzip.spec generated" else echo "Failed to generate qatzip.spec" fi QATzip-1.2.0/src/000077500000000000000000000000001456106226300134565ustar00rootroot00000000000000QATzip-1.2.0/src/Makefile.am000066400000000000000000000051451456106226300155170ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ lib_LTLIBRARIES = libqatzip.la libqatzip_la_SOURCES = \ qatzip.c \ qatzip_counter.c \ qatzip_gzip.c \ qatzip_mem.c \ qatzip_stream.c \ qatzip_sw.c \ qatzip_utils.c \ qatzip_lz4.c \ xxhash.c libqatzip_la_CFLAGS = \ -I./ \ -I../include/ \ $(COMMON_CFLAGS) \ $(SAL_CFLAGS) \ $(ADF_CFLAGS) \ $(ICP_INCLUDE_CFLAGS) \ $(AM_CFLAGS) libqatzip_la_LDFLAGS = \ -version-info $(LIBQATZIP_VERSION) \ $(ICP_LDFLAGS) libqatzip_la_LIBADD= $(QATLIB_FLAGS) \ $(USDMLIB_FLAGS) QATzip-1.2.0/src/qatzip.c000077500000000000000000002742661456106226300151560ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #define XXH_NAMESPACE QATZIP_ #include "xxhash.h" #ifdef HAVE_QAT_HEADERS #include #include #include #include #include #else #include #include #include #include #include #endif #include "qatzip.h" #include "qatzip_internal.h" #include "qz_utils.h" /* * Process address space name described in the config file for this device. */ const char *g_dev_tag = "SHIM"; const unsigned int g_polling_interval[] = { 10, 10, 20, 30, 60, 100, 200, 400, 600, 1000, 2000, 4000, 8000, 16000, 32000, 64000 }; #define INTER_SZ(src_sz) (2 * (src_sz)) #define msleep(x) usleep((x) * 1000) #define POLLING_LIST_NUM (sizeof(g_polling_interval) \ / sizeof(unsigned int)) #define MAX_GRAB_RETRY (10) #define GET_BUFFER_SLEEP_NSEC 10 #define QAT_SECTION_NAME_SIZE 32 #define POLL_EVENT_INTERVAL_TIME 1000 /****************************************************** * If enable new compression algorithm, extend new params * structure in API. please add default here. ******************************************************/ QzSessionParamsInternal_T g_sess_params_internal_default = { .huffman_hdr = QZ_HUFF_HDR_DEFAULT, .direction = QZ_DIRECTION_DEFAULT, .data_fmt = DATA_FORMAT_DEFAULT, .comp_lvl = QZ_COMP_LEVEL_DEFAULT, .comp_algorithm = QZ_COMP_ALGOL_DEFAULT, .max_forks = QZ_MAX_FORK_DEFAULT, .sw_backup = QZ_SW_BACKUP_DEFAULT, .hw_buff_sz = QZ_HW_BUFF_SZ, .strm_buff_sz = QZ_STRM_BUFF_SZ_DEFAULT, .input_sz_thrshold = QZ_COMP_THRESHOLD_DEFAULT, .req_cnt_thrshold = QZ_REQ_THRESHOLD_DEFAULT, .wait_cnt_thrshold = QZ_WAIT_CNT_THRESHOLD_DEFAULT, .polling_mode = QZ_PERIODICAL_POLLING, .lz4s_mini_match = 3, .qzCallback = NULL, .qzCallback_external = NULL }; pthread_mutex_t g_sess_params_lock = PTHREAD_MUTEX_INITIALIZER; processData_T g_process = { .qz_init_status = QZ_NONE, .qat_available = QZ_NONE }; pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; __thread ThreadData_T g_thread = { .ppid = 0, }; static int setInstance(unsigned int dev_id, QzInstanceList_T *new_instance, QzHardware_T *qat_hw) { if (dev_id >= QAT_MAX_DEVICES || NULL == new_instance || NULL == qat_hw || NULL != new_instance->next) { return QZ_PARAMS; } QzInstanceList_T *instances = &qat_hw->devices[dev_id]; /* first instance */ if (NULL == instances->next) { qat_hw->dev_num++; } while (instances->next) { instances = instances->next; } instances->next = new_instance; if (dev_id > qat_hw->max_dev_id) { qat_hw->max_dev_id = dev_id; } return QZ_OK; } static QzInstanceList_T *getInstance(unsigned int dev_id, QzHardware_T *qat_hw) { if (dev_id >= QAT_MAX_DEVICES || NULL == qat_hw) { return NULL; } QzInstanceList_T *instances = &qat_hw->devices[dev_id]; QzInstanceList_T *first_instance = instances->next; int i; /* no instance */ if (NULL == first_instance) { goto exit; } instances->next = first_instance->next; /* last instance */ if (NULL == instances->next && qat_hw->dev_num > 0) { qat_hw->dev_num--; if (qat_hw->max_dev_id > 0 && dev_id == qat_hw->max_dev_id) { for (i = qat_hw->max_dev_id - 1; i >= 0; i--) { if (qat_hw->devices[i].next) { qat_hw->max_dev_id = i; break; } } } } exit: return first_instance; } static void clearDevices(QzHardware_T *qat_hw) { if (NULL == qat_hw || 0 == qat_hw->dev_num) { return; } for (int i = 0; i < qat_hw->max_dev_id; i++) { QzInstanceList_T *inst = getInstance(i, qat_hw); while (inst) { free(inst); inst = getInstance(i, qat_hw); } } } static void dcCallback(void *cbtag, CpaStatus stat) { long tag, i, j; tag = (long)cbtag; j = GET_LOWER_16BITS(tag); i = tag >> 16; if (g_process.qz_inst[i].stream[j].src1 != g_process.qz_inst[i].stream[j].src2) { QZ_ERROR("FLOW ERROR IN CBi src1 != src2\n"); goto print_err; } if (g_process.qz_inst[i].stream[j].sink1 != g_process.qz_inst[i].stream[j].sink2) { QZ_ERROR("FLOW ERROR IN CBi sink1 != sink2\n"); goto print_err; } if (g_process.qz_inst[i].stream[j].src2 != (g_process.qz_inst[i].stream[j].sink1 + 1)) { QZ_ERROR("FLOW ERROR IN CBi src2 != sink1 + 1\n"); goto print_err; } g_process.qz_inst[i].stream[j].sink1++; g_process.qz_inst[i].stream[j].job_status = stat; goto done; print_err: QZ_ERROR("FLOW ERROR IN CBi %ld %ld\n", i, j); done: return; } static void dcEventCallback(const CpaInstanceHandle instanceHandle, void *pCallbackTag, const CpaInstanceEvent instanceEvent) { long i = (long)pCallbackTag; switch (instanceEvent) { case CPA_INSTANCE_EVENT_RESTARTING: QZ_DEBUG("QAT instance %ld detected Event 'restarting'\n", i); break; case CPA_INSTANCE_EVENT_RESTARTED: g_process.qz_inst[i].heartbeat = CPA_STATUS_SUCCESS; QZ_DEBUG("QAT instance %ld detected Event 'restarted'\n", i); break; case CPA_INSTANCE_EVENT_FATAL_ERROR: g_process.qz_inst[i].heartbeat = CPA_STATUS_FAIL; QZ_DEBUG("QAT instance %ld detected Event 'fatal error'\n", i); break; default: QZ_ERROR("QAT instance %ld detected Unknow Event!\n", i); } } static void *PollingHeartBeat(void *arg) { CpaStatus status = CPA_STATUS_SUCCESS; while (true) { status = icp_sal_poll_device_events(); if (CPA_STATUS_SUCCESS != status) { QZ_DEBUG("Polling device heartbeat is failure!\n"); continue; } /* This time may effect the sw fallback times */ usleep(POLL_EVENT_INTERVAL_TIME); } return ((void *)NULL); } /* * Check the capabilities of instance to ensure that it * supports the data format. For LZ4 or LZ4s if * QAT API Version is less than 3.1, will return QZ_FAIL. */ static inline int qzCheckInstCap(CpaDcInstanceCapabilities *inst_cap, const QzSessionParamsInternal_T *params) { assert(inst_cap != NULL); switch (params->data_fmt) { case LZ4_FH: #if CPA_DC_API_VERSION_AT_LEAST(3, 1) if (!inst_cap->statelessLZ4Compression || !inst_cap->statelessLZ4Decompression || !inst_cap->checksumXXHash32) { return QZ_FAIL; } #else QZ_ERROR("QAT driver does not support lz4 algorithm\n"); return QZ_FAIL; #endif break; case LZ4S_BK: #if CPA_DC_API_VERSION_AT_LEAST(3, 1) if (!inst_cap->checksumXXHash32 || !inst_cap->statelessLZ4SCompression) { return QZ_FAIL; } #else QZ_ERROR("QAT driver does not support lz4s algorithm\n"); return QZ_FAIL; #endif break; case DEFLATE_4B: case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: case DEFLATE_RAW: default: if (!inst_cap->statelessDeflateCompression || !inst_cap->statelessDeflateDecompression || !inst_cap->checksumCRC32) { return QZ_FAIL; } /* check if instance support dynamic huffman */ if (!inst_cap->dynamicHuffman && (params->huffman_hdr == QZ_DYNAMIC_HDR)) { return QZ_FAIL; } /* always open the Cnv */ if (!inst_cap->compressAndVerify) { return QZ_FAIL; } /* will extend multi-type checksum check, data format check autoSelect check, Dictionary support, stateful support ..... */ break; } return QZ_OK; } static int qzGrabInstance(int hint, const QzSessionParamsInternal_T *params) { int i, j, rc, f; if (QZ_NONE == g_process.qz_init_status) { return -1; } if (hint >= g_process.num_instances || hint < 0) { hint = 0; } /*otherwise loop through all of them*/ f = 0; for (j = 0; j < MAX_GRAB_RETRY; j++) { for (i = 0; i < g_process.num_instances; i++) { if (f == 0) { i = hint; f = 1; } ; /* Before locking the instance, we need to ensure that * the instance supports the data format. */ if (QZ_OK != qzCheckInstCap(&g_process.qz_inst[i].instance_cap, params)) { continue; } if (CPA_STATUS_SUCCESS != g_process.qz_inst[i].heartbeat) { continue; } rc = __sync_lock_test_and_set(&(g_process.qz_inst[i].lock), 1); if (0 == rc) { return i; } } } return -1; } static int getUnusedBuffer(unsigned long i, int j) { int k; Cpa16U max; max = g_process.qz_inst[i].dest_count; if (j < 0) { j = 0; } else if (j >= max) { j = GET_LOWER_16BITS(max); } for (k = j; k < max; k++) { if ((g_process.qz_inst[i].stream[k].src1 == g_process.qz_inst[i].stream[k].src2) && (g_process.qz_inst[i].stream[k].src1 == g_process.qz_inst[i].stream[k].sink1) && (g_process.qz_inst[i].stream[k].src1 == g_process.qz_inst[i].stream[k].sink2)) { return k; } } for (k = 0; k < max; k++) { if ((g_process.qz_inst[i].stream[k].src1 == g_process.qz_inst[i].stream[k].src2) && (g_process.qz_inst[i].stream[k].src1 == g_process.qz_inst[i].stream[k].sink1) && (g_process.qz_inst[i].stream[k].src1 == g_process.qz_inst[i].stream[k].sink2)) { return k; } } return -1; } static void qzReleaseInstance(int i) { __sync_lock_release(&(g_process.qz_inst[i].lock)); } static void init_timers(void) { int i; for (i = 1; i < MAX_THREAD_TMR; i++) { g_thread.timer[i].tv_sec = 0; g_thread.timer[i].tv_usec = 0; } gettimeofday(&g_thread.timer[0], NULL); } static void stopQat(void) { int i; CpaStatus status = CPA_STATUS_SUCCESS; /* Those all show No HW, stopQAT do nothing */ if (CPA_FALSE == g_process.qat_available || QZ_NONE == g_process.qz_init_status || QZ_NO_HW == g_process.qz_init_status || QZ_NOSW_NO_HW == g_process.qz_init_status) { goto reset; } /* scenario: it's called from inside qzinit, Hw init failed */ if (QZ_NO_INST_ATTACH == g_process.qz_init_status) { if (NULL != g_process.dc_inst_handle) { free(g_process.dc_inst_handle); g_process.dc_inst_handle = NULL; } if (NULL != g_process.qz_inst) { free(g_process.qz_inst); g_process.qz_inst = NULL; } (void)icp_sal_userStop(); goto reset; } QZ_DEBUG("Call stopQat.\n"); /* scenario: qzinit succeed. outside qzinit */ if (QZ_OK == g_process.qz_init_status) { if (NULL != g_process.dc_inst_handle && NULL != g_process.qz_inst) { for (i = 0; i < g_process.num_instances; i++) { status = cpaDcStopInstance(g_process.dc_inst_handle[i]); if (CPA_STATUS_SUCCESS != status) { QZ_ERROR("Stop instance failed, status=%d\n", status); } } free(g_process.dc_inst_handle); g_process.dc_inst_handle = NULL; free(g_process.qz_inst); g_process.qz_inst = NULL; } (void)icp_sal_userStop(); } else { QZ_ERROR("qz init status is invalid, status=%d\n", g_process.qz_init_status); goto reset; } reset: g_process.num_instances = (Cpa16U)0; g_process.qz_init_status = QZ_NONE; g_process.qat_available = QZ_NONE; } static void exitFunc(void) __attribute__((destructor)); static void exitFunc(void) { int i = 0; if (0 != g_process.t_poll_heartbeat) { QZ_DEBUG("cancel the thread!\n"); pthread_cancel(g_process.t_poll_heartbeat); pthread_join(g_process.t_poll_heartbeat, NULL); } for (i = 0; i < g_process.num_instances; i++) { removeSession(i); cleanUpInstMem(i); } streamBufferCleanup(); stopQat(); qzMemDestory(); #ifdef QATZIP_DEBUG dumpThreadInfo(); #endif } static unsigned int getWaitCnt(QzSession_T *sess) { QzSess_T *qz_sess; if (sess->internal != NULL) { qz_sess = (QzSess_T *)sess->internal; return qz_sess->sess_params.wait_cnt_thrshold; } else { return g_sess_params_internal_default.wait_cnt_thrshold; } } #define BACKOUT(hw_status) \ stopQat(); \ if (1 == sw_backup) { \ g_process.qz_init_status = QZ_NO_HW; \ QZ_ERROR("g_process.qz_init_status = QZ_NO_HW\n"); \ rc = QZ_OK; \ } else if (0 == sw_backup) { \ g_process.qz_init_status = QZ_NOSW_NO_HW; \ QZ_ERROR("g_process.qz_init_status = QZ_NOSW_NO_HW\n"); \ rc = hw_status; \ } \ goto done; #define QZ_HW_BACKOUT(hw_status) \ if(qat_hw) { \ clearDevices(qat_hw); \ free(qat_hw); \ } \ BACKOUT(hw_status); const char *getSectionName(void) { static char section_name[QAT_SECTION_NAME_SIZE]; int len; char *pre_section_name; #if __GLIBC_PREREQ(2, 17) pre_section_name = secure_getenv("QAT_SECTION_NAME"); #else pre_section_name = getenv("QAT_SECTION_NAME"); #endif if (!pre_section_name || !(len = strlen(pre_section_name))) { pre_section_name = (char *)g_dev_tag; } else if (len >= QAT_SECTION_NAME_SIZE) { QZ_ERROR("The length of QAT_SECTION_NAME exceeds the limit.\n"); } strncpy(section_name, pre_section_name, QAT_SECTION_NAME_SIZE - 1); section_name[QAT_SECTION_NAME_SIZE - 1] = '\0'; return section_name; } /* Initialize the QAT hardware, get the QAT instance for current * process. * Note: return value doesn't same as qz_init_status, because return * value align limitation. * * After qzInit, there only are three status to qz_init_status * 1. QZ_OK * 2. QZ_NO_HW * 3. QZ_NOSW_NO_HW */ int qzInit(QzSession_T *sess, unsigned char sw_backup) { CpaStatus status; int rc = QZ_NOSW_NO_HW, i; unsigned int dev_id = 0; QzHardware_T *qat_hw = NULL; unsigned int instance_found = 0; static atomic_int waiting = 0; static atomic_int wait_cnt = 0; #ifdef ADF_PCI_API Cpa32U pcie_count = 0; #endif if (unlikely(sess == NULL)) { return QZ_PARAMS; } if (unlikely(sw_backup > 1)) { return QZ_PARAMS; } if (CPA_FALSE == g_process.qat_available || QZ_OK == g_process.qz_init_status) { return QZ_DUPLICATE; } if (unlikely(0 != pthread_mutex_lock(&g_lock))) { return QZ_NOSW_NO_HW; } if (QZ_OK == g_process.qz_init_status) { if (unlikely(0 != pthread_mutex_unlock(&g_lock))) { return QZ_NOSW_NO_HW; } if (g_process.sw_backup != sw_backup) { g_process.sw_backup = sw_backup; } return QZ_DUPLICATE; } g_thread.pid = getpid(); g_thread.ppid = getppid(); init_timers(); g_process.sw_backup = sw_backup; if (waiting && wait_cnt > 0) { wait_cnt--; BACKOUT(QZ_NOSW_NO_HW); } waiting = 0; /* Start HW initialization. it could be first call qzinit or * Before HW init failed, which mean qz_init_status may be * QZ_NOSW_NO_HW or QZ_NO_HW */ #ifdef SAL_DEV_API g_process.qat_available = icp_sal_userIsQatAvailable(); if (CPA_FALSE == g_process.qat_available) { QZ_ERROR("Error no hardware, switch to SW if permitted\n"); BACKOUT(QZ_NOSW_NO_HW); } #else status = icp_adf_get_numDevices(&pcie_count); if (CPA_STATUS_SUCCESS != status) { g_process.qat_available = CPA_FALSE; } if (pcie_count >= 1) { g_process.qat_available = CPA_TRUE; } else { g_process.qat_available = CPA_FALSE; } if (CPA_FALSE == g_process.qat_available) { QZ_ERROR("Error no hardware, switch to SW if permitted status = %d\n", status); BACKOUT(QZ_NOSW_NO_HW); } #endif status = icp_sal_userStartMultiProcess(getSectionName(), CPA_FALSE); if (CPA_STATUS_SUCCESS != status) { QZ_ERROR("Error userStarMultiProcess(%d), switch to SW if permitted\n", status); waiting = 1; wait_cnt = getWaitCnt(sess); BACKOUT(QZ_NOSW_NO_HW); } /* This status only show inside qzinit. And will replace to others when qzinit finished */ g_process.qz_init_status = QZ_NO_INST_ATTACH; status = cpaDcGetNumInstances(&g_process.num_instances); if (CPA_STATUS_SUCCESS != status) { QZ_ERROR("Error in cpaDcGetNumInstances status = %d\n", status); BACKOUT(QZ_NOSW_NO_INST_ATTACH); } QZ_DEBUG("Number of instance: %u\n", g_process.num_instances); g_process.dc_inst_handle = malloc(g_process.num_instances * sizeof(CpaInstanceHandle)); g_process.qz_inst = calloc(g_process.num_instances, sizeof(QzInstance_T)); if (unlikely(NULL == g_process.dc_inst_handle || NULL == g_process.qz_inst)) { QZ_ERROR("malloc failed\n"); BACKOUT(QZ_NOSW_LOW_MEM); } status = cpaDcGetInstances(g_process.num_instances, g_process.dc_inst_handle); if (CPA_STATUS_SUCCESS != status) { QZ_ERROR("Error in cpaDcGetInstances status = %d\n", status); BACKOUT(QZ_NOSW_NO_INST_ATTACH); } qat_hw = calloc(1, sizeof(QzHardware_T)); if (unlikely(NULL == qat_hw)) { QZ_ERROR("malloc failed\n"); BACKOUT(QZ_NOSW_LOW_MEM); } for (i = 0; i < g_process.num_instances; i++) { QzInstanceList_T *new_inst = calloc(1, sizeof(QzInstanceList_T)); if (unlikely(NULL == new_inst)) { QZ_ERROR("malloc failed\n"); QZ_HW_BACKOUT(QZ_NOSW_LOW_MEM); } status = cpaDcInstanceGetInfo2(g_process.dc_inst_handle[i], &new_inst->instance.instance_info); if (CPA_STATUS_SUCCESS != status) { QZ_ERROR("Error in cpaDcInstanceGetInfo2 status = %d\n", status); free(new_inst); QZ_HW_BACKOUT(QZ_NOSW_NO_HW); } status = cpaDcQueryCapabilities(g_process.dc_inst_handle[i], &new_inst->instance.instance_cap); if (CPA_STATUS_SUCCESS != status) { QZ_ERROR("Error in cpaDcQueryCapabilities status = %d\n", status); free(new_inst); QZ_HW_BACKOUT(QZ_NOSW_NO_HW); } new_inst->instance.lock = 0; new_inst->instance.heartbeat = CPA_STATUS_SUCCESS; new_inst->instance.mem_setup = 0; new_inst->instance.cpa_sess_setup = 0; new_inst->instance.num_retries = 0; new_inst->dc_inst_handle = g_process.dc_inst_handle[i]; dev_id = new_inst->instance.instance_info.physInstId.packageId; if (unlikely(QZ_OK != setInstance(dev_id, new_inst, qat_hw))) { QZ_ERROR("Insert instance on device %d failed\n", dev_id); QZ_HW_BACKOUT(QZ_NOSW_NO_INST_ATTACH); } } /* shuffle instance */ for (i = 0; instance_found < g_process.num_instances; i++) { dev_id = i % (qat_hw->max_dev_id + 1); QzInstanceList_T *new_inst = getInstance(dev_id, qat_hw); if (NULL == new_inst) { continue; } QZ_MEMCPY(&g_process.qz_inst[instance_found], &new_inst->instance, sizeof(QzInstance_T), sizeof(QzInstance_T)); g_process.dc_inst_handle[instance_found] = new_inst->dc_inst_handle; free(new_inst); instance_found++; } /* Set EventCallback after instance shuffle */ for (long index = 0; index < instance_found; index++) { status = cpaDcInstanceSetNotificationCb(g_process.dc_inst_handle[index], dcEventCallback, (void *)index); if (CPA_STATUS_SUCCESS != status) { QZ_ERROR("Error in cpaDcInstanceSetNotificationCb status = %d\n", status); QZ_HW_BACKOUT(QZ_NOSW_NO_INST_ATTACH); } } /* Start device heartbeat event detect thread */ if (unlikely(0 != pthread_create(&g_process.t_poll_heartbeat, NULL, PollingHeartBeat, NULL))) { QZ_ERROR("Error Start polling heartbeat events thread failed!\n"); g_process.t_poll_heartbeat = 0; } QZ_DEBUG("the polling event thread id is %d\n", g_process.t_poll_heartbeat); clearDevices(qat_hw); free(qat_hw); rc = g_process.qz_init_status = QZ_OK; done: initDebugLock(); if (unlikely(0 != pthread_mutex_unlock(&g_lock))) { return QZ_NOSW_NO_HW; } return rc; } /* Free up the DMAable memory buffers used by QAT * internally, those buffers are source buffer, * intermediate buffer and destination buffer */ void cleanUpInstMem(int i) { int j; /*intermediate buffers*/ if (NULL != g_process.qz_inst[i].intermediate_buffers) { for (j = 0; j < g_process.qz_inst[i].intermediate_cnt; j++) { if (NULL != g_process.qz_inst[i].intermediate_buffers[j]) { if (NULL != g_process.qz_inst[i].intermediate_buffers[j]->pPrivateMetaData) { qzFree(g_process.qz_inst[i].intermediate_buffers[j]->pPrivateMetaData); g_process.qz_inst[i].intermediate_buffers[j]->pPrivateMetaData = NULL; } if (NULL != g_process.qz_inst[i].intermediate_buffers[j]->pBuffers) { if (NULL != g_process.qz_inst[i].intermediate_buffers[j]->pBuffers->pData) { qzFree(g_process.qz_inst[i].intermediate_buffers[j]->pBuffers->pData); g_process.qz_inst[i].intermediate_buffers[j]->pBuffers->pData = NULL; } qzFree(g_process.qz_inst[i].intermediate_buffers[j]->pBuffers); g_process.qz_inst[i].intermediate_buffers[j]->pBuffers = NULL; } qzFree(g_process.qz_inst[i].intermediate_buffers[j]); g_process.qz_inst[i].intermediate_buffers[j] = NULL; } } free(g_process.qz_inst[i].intermediate_buffers); g_process.qz_inst[i].intermediate_buffers = NULL; } /*src buffers*/ if (NULL != g_process.qz_inst[i].src_buffers) { for (j = 0; j < g_process.qz_inst[i].src_count; j++) { if (NULL != g_process.qz_inst[i].src_buffers[j]) { if (NULL != g_process.qz_inst[i].src_buffers[j]->pPrivateMetaData) { qzFree(g_process.qz_inst[i].src_buffers[j]->pPrivateMetaData); g_process.qz_inst[i].src_buffers[j]->pPrivateMetaData = NULL; } if (NULL != g_process.qz_inst[i].src_buffers[j]->pBuffers) { if (NULL != g_process.qz_inst[i].src_buffers[j]->pBuffers->pData) { qzFree(g_process.qz_inst[i].src_buffers[j]->pBuffers->pData); g_process.qz_inst[i].src_buffers[j]->pBuffers->pData = NULL; } qzFree(g_process.qz_inst[i].src_buffers[j]->pBuffers); g_process.qz_inst[i].src_buffers[j]->pBuffers = NULL; } qzFree(g_process.qz_inst[i].src_buffers[j]); g_process.qz_inst[i].src_buffers[j] = NULL; } } free(g_process.qz_inst[i].src_buffers); g_process.qz_inst[i].src_buffers = NULL; } /*dest buffers*/ if (NULL != g_process.qz_inst[i].dest_buffers) { for (j = 0; j < g_process.qz_inst[i].dest_count; j++) { if (NULL != g_process.qz_inst[i].dest_buffers[j]) { if (NULL != g_process.qz_inst[i].dest_buffers[j]->pPrivateMetaData) { qzFree(g_process.qz_inst[i].dest_buffers[j]->pPrivateMetaData); g_process.qz_inst[i].dest_buffers[j]->pPrivateMetaData = NULL; } if (NULL != g_process.qz_inst[i].dest_buffers[j]->pBuffers) { if (NULL != g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData) { qzFree(g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData); g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = NULL; } qzFree(g_process.qz_inst[i].dest_buffers[j]->pBuffers); g_process.qz_inst[i].dest_buffers[j]->pBuffers = NULL; } qzFree(g_process.qz_inst[i].dest_buffers[j]); g_process.qz_inst[i].dest_buffers[j] = NULL; } } free(g_process.qz_inst[i].dest_buffers); g_process.qz_inst[i].dest_buffers = NULL; } /*stream buffer*/ if (NULL != g_process.qz_inst[i].stream) { free(g_process.qz_inst[i].stream); g_process.qz_inst[i].stream = NULL; } qzFree(g_process.qz_inst[i].cpaSess); g_process.qz_inst[i].mem_setup = 0; } #define QZ_INST_MEM_CHECK(ptr, i) \ if (NULL == (ptr)) { \ cleanUpInstMem((i)); \ rc = sw_backup ? QZ_LOW_MEM : QZ_NOSW_LOW_MEM; \ goto done_inst; \ } #define QZ_INST_MEM_STATUS_CHECK(status, i) \ if (CPA_STATUS_SUCCESS != status) { \ cleanUpInstMem((i)); \ rc = sw_backup ? QZ_NO_INST_ATTACH : QZ_NOSW_NO_INST_ATTACH; \ goto done_inst; \ } /* Allocate the DMAable memory buffers used by QAT * internally, those buffers are source buffer, * intermediate buffer and destination buffer */ static int getInstMem(int i, QzSessionParamsInternal_T *params) { int j; CpaStatus status; CpaStatus rc; unsigned int src_sz; unsigned int inter_sz; unsigned int dest_sz; unsigned char sw_backup; rc = QZ_OK; /* WARN: this will mean the first sess will setup down the inst * buffer size, if it's very small, then we can't make then * any larger in the whole process. please refer test mode 17 */ src_sz = params->hw_buff_sz; inter_sz = INTER_SZ(src_sz); dest_sz = DEST_SZ(src_sz); sw_backup = params->sw_backup; QZ_DEBUG("getInstMem: Setting up memory for inst %d\n", i); status = cpaDcBufferListGetMetaSize(g_process.dc_inst_handle[i], 1, &(g_process.qz_inst[i].buff_meta_size)); QZ_INST_MEM_STATUS_CHECK(status, i); status = cpaDcGetNumIntermediateBuffers(g_process.dc_inst_handle[i], &(g_process.qz_inst[i].intermediate_cnt)); QZ_INST_MEM_STATUS_CHECK(status, i); g_process.qz_inst[i].intermediate_buffers = calloc(1, (size_t)(g_process.qz_inst[i].intermediate_cnt * sizeof( CpaBufferList *))); QZ_INST_MEM_CHECK(g_process.qz_inst[i].intermediate_buffers, i); for (j = 0; j < g_process.qz_inst[i].intermediate_cnt; j++) { g_process.qz_inst[i].intermediate_buffers[j] = (CpaBufferList *) qzMalloc(sizeof(CpaBufferList), NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].intermediate_buffers[j], i); if (0 != g_process.qz_inst[i].buff_meta_size) { g_process.qz_inst[i].intermediate_buffers[j]->pPrivateMetaData = qzMalloc((size_t)(g_process.qz_inst[i].buff_meta_size), NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK( g_process.qz_inst[i].intermediate_buffers[j]->pPrivateMetaData, i); } else { g_process.qz_inst[i].intermediate_buffers[j]->pPrivateMetaData = NULL; } g_process.qz_inst[i].intermediate_buffers[j]->pBuffers = (CpaFlatBuffer *) qzMalloc(sizeof(CpaFlatBuffer), NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].intermediate_buffers[j]->pBuffers, i); g_process.qz_inst[i].intermediate_buffers[j]->pBuffers->pData = (Cpa8U *) qzMalloc(inter_sz, NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].intermediate_buffers[j]->pBuffers->pData, i); g_process.qz_inst[i].intermediate_buffers[j]->numBuffers = (Cpa32U)1; g_process.qz_inst[i].intermediate_buffers[j]->pBuffers->dataLenInBytes = inter_sz; } g_process.qz_inst[i].src_count = NUM_BUFF; g_process.qz_inst[i].dest_count = NUM_BUFF; if (params->hw_buff_sz <= 8 * 1024) { g_process.qz_inst[i].src_count = NUM_BUFF_8K; g_process.qz_inst[i].dest_count = NUM_BUFF_8K; } g_process.qz_inst[i].src_buffers = calloc(1, (size_t)( g_process.qz_inst[i].src_count * sizeof(CpaBufferList *))); QZ_INST_MEM_CHECK(g_process.qz_inst[i].src_buffers, i); g_process.qz_inst[i].dest_buffers = calloc(1, g_process.qz_inst[i].dest_count * sizeof(CpaBufferList *)); QZ_INST_MEM_CHECK(g_process.qz_inst[i].dest_buffers, i); g_process.qz_inst[i].stream = calloc(g_process.qz_inst[i].dest_count, sizeof(QzCpaStream_T)); QZ_INST_MEM_CHECK(g_process.qz_inst[i].stream, i); for (j = 0; j < g_process.qz_inst[i].dest_count; j++) { g_process.qz_inst[i].stream[j].seq = 0; g_process.qz_inst[i].stream[j].src1 = 0; g_process.qz_inst[i].stream[j].src2 = 0; g_process.qz_inst[i].stream[j].sink1 = 0; g_process.qz_inst[i].stream[j].sink2 = 0; g_process.qz_inst[i].src_buffers[j] = (CpaBufferList *) qzMalloc(sizeof(CpaBufferList), NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].src_buffers[j], i); if (0 != g_process.qz_inst[i].buff_meta_size) { g_process.qz_inst[i].src_buffers[j]->pPrivateMetaData = qzMalloc(g_process.qz_inst[i].buff_meta_size, NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].src_buffers[j]->pPrivateMetaData, i); } else { g_process.qz_inst[i].src_buffers[j]->pPrivateMetaData = NULL; } g_process.qz_inst[i].src_buffers[j]->pBuffers = (CpaFlatBuffer *) qzMalloc(sizeof(CpaFlatBuffer), NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].src_buffers, i); g_process.qz_inst[i].src_buffers[j]->pBuffers->pData = (Cpa8U *) qzMalloc(src_sz, NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].src_buffers[j]->pBuffers->pData, i); /* The orig_src points internal pre-allocated pinned buffer. */ g_process.qz_inst[i].stream[j].orig_src = g_process.qz_inst[i].src_buffers[j]->pBuffers->pData; g_process.qz_inst[i].src_buffers[j]->numBuffers = (Cpa32U)1; g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes = src_sz; } for (j = 0; j < g_process.qz_inst[i].dest_count; j++) { g_process.qz_inst[i].dest_buffers[j] = (CpaBufferList *) qzMalloc(sizeof(CpaBufferList), NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].dest_buffers[j], i); if (0 != g_process.qz_inst[i].buff_meta_size) { g_process.qz_inst[i].dest_buffers[j]->pPrivateMetaData = qzMalloc(g_process.qz_inst[i].buff_meta_size, NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].dest_buffers[j]->pPrivateMetaData, i); } else { g_process.qz_inst[i].dest_buffers[j]->pPrivateMetaData = NULL; } g_process.qz_inst[i].dest_buffers[j]->pBuffers = (CpaFlatBuffer *) qzMalloc(sizeof(CpaFlatBuffer), NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].dest_buffers, i); g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = (Cpa8U *) qzMalloc(dest_sz, NODE_0, PINNED_MEM); QZ_INST_MEM_CHECK(g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData, i); /* The orig_dest points internal pre-allocated pinned buffer. */ g_process.qz_inst[i].stream[j].orig_dest = g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData; g_process.qz_inst[i].dest_buffers[j]->numBuffers = (Cpa32U)1; g_process.qz_inst[i].dest_buffers[j]->pBuffers->dataLenInBytes = dest_sz; } status = cpaDcSetAddressTranslation(g_process.dc_inst_handle[i], qaeVirtToPhysNUMA); QZ_INST_MEM_STATUS_CHECK(status, i); g_process.qz_inst[i].inst_start_status = cpaDcStartInstance(g_process.dc_inst_handle[i], g_process.qz_inst[i].intermediate_cnt, g_process.qz_inst[i].intermediate_buffers); QZ_INST_MEM_STATUS_CHECK(g_process.qz_inst[i].inst_start_status, i); g_process.qz_inst[i].mem_setup = 1; done_inst: return rc; } /* Initialize the QAT session parameters associate with current * process's QAT instance, the session parameters include various * configurations for compression/decompression request */ int qzSetupSession(QzSession_T *sess, QzSessionParams_T *params) { int rc = QZ_OK; QzSess_T *qz_sess; QzSessionParams_T temp = {0}; if (unlikely(NULL == sess)) { return QZ_PARAMS; } if (NULL == params) { rc = qzGetDefaults(&temp); params = &temp; } if (qzCheckParams(params) != QZ_OK) { return QZ_PARAMS; } sess->hw_session_stat = QZ_FAIL; if (sess->internal == NULL) { sess->internal = calloc(1, sizeof(QzSess_T)); if (unlikely(NULL == sess->internal)) { sess->hw_session_stat = QZ_NOSW_LOW_MEM; return QZ_NOSW_LOW_MEM; } } else { return QZ_DUPLICATE; } qz_sess = (QzSess_T *)sess->internal; qzSetParams(params, &qz_sess->sess_params); rc = qzSetupSessionInternal(sess); if (rc < 0) { free(sess->internal); sess->internal = NULL; return rc; } return rc; } int qzSetupSessionDeflate(QzSession_T *sess, QzSessionParamsDeflate_T *params) { int rc = QZ_OK; QzSess_T *qz_sess; QzSessionParamsDeflate_T temp = {{0}}; if (unlikely(NULL == sess)) { return QZ_PARAMS; } if (NULL == params) { rc = qzGetDefaultsDeflate(&temp); params = &temp; } if (qzCheckParamsDeflate(params) != QZ_OK) { return QZ_PARAMS; } sess->hw_session_stat = QZ_FAIL; if (sess->internal == NULL) { sess->internal = calloc(1, sizeof(QzSess_T)); if (unlikely(NULL == sess->internal)) { sess->hw_session_stat = QZ_NOSW_LOW_MEM; return QZ_NOSW_LOW_MEM; } } else { return QZ_DUPLICATE; } qz_sess = (QzSess_T *)sess->internal; qzSetParamsDeflate(params, &qz_sess->sess_params); rc = qzSetupSessionInternal(sess); if (rc < 0) { free(sess->internal); sess->internal = NULL; return rc; } return rc; } int qzSetupSessionLZ4(QzSession_T *sess, QzSessionParamsLZ4_T *params) { int rc = QZ_OK; QzSess_T *qz_sess; QzSessionParamsLZ4_T temp = {{0}}; if (unlikely(NULL == sess)) { return QZ_PARAMS; } if (NULL == params) { rc = qzGetDefaultsLZ4(&temp); params = &temp; } if (qzCheckParamsLZ4(params) != QZ_OK) { return QZ_PARAMS; } sess->hw_session_stat = QZ_FAIL; if (sess->internal == NULL) { sess->internal = calloc(1, sizeof(QzSess_T)); if (unlikely(NULL == sess->internal)) { sess->hw_session_stat = QZ_NOSW_LOW_MEM; return QZ_NOSW_LOW_MEM; } } else { return QZ_DUPLICATE; } qz_sess = (QzSess_T *)sess->internal; qzSetParamsLZ4(params, &qz_sess->sess_params); rc = qzSetupSessionInternal(sess); if (rc < 0) { free(sess->internal); sess->internal = NULL; return rc; } return rc; } int qzSetupSessionLZ4S(QzSession_T *sess, QzSessionParamsLZ4S_T *params) { int rc = QZ_OK; QzSess_T *qz_sess; QzSessionParamsLZ4S_T temp = {{0}}; if (unlikely(NULL == sess)) { return QZ_PARAMS; } if (NULL == params) { rc = qzGetDefaultsLZ4S(&temp); params = &temp; } if (qzCheckParamsLZ4S(params) != QZ_OK) { return QZ_PARAMS; } sess->hw_session_stat = QZ_FAIL; if (sess->internal == NULL) { sess->internal = calloc(1, sizeof(QzSess_T)); if (unlikely(NULL == sess->internal)) { sess->hw_session_stat = QZ_NOSW_LOW_MEM; return QZ_NOSW_LOW_MEM; } } else { return QZ_DUPLICATE; } qz_sess = (QzSess_T *)sess->internal; qzSetParamsLZ4S(params, &qz_sess->sess_params); rc = qzSetupSessionInternal(sess); if (rc < 0) { free(sess->internal); sess->internal = NULL; return rc; } return rc; } /* Set up the QAT session associate with current process's * QAT instance */ int qzSetupHW(QzSession_T *sess, int i) { QzSess_T *qz_sess; int rc = QZ_OK; if (g_process.qz_init_status != QZ_OK) { /*hw not present*/ return g_process.qz_init_status; } qz_sess = (QzSess_T *)sess->internal; qz_sess->inst_hint = i; qz_sess->seq = 0; qz_sess->seq_in = 0; if (0 == g_process.qz_inst[i].mem_setup) { rc = getInstMem(i, &(qz_sess->sess_params)); if (QZ_OK != rc) { goto done_sess; } } if (0 == g_process.qz_inst[i].cpa_sess_setup) { /*setup and start DC session*/ QZ_DEBUG("setup and start DC session %d\n", i); qz_sess->sess_status = cpaDcGetSessionSize(g_process.dc_inst_handle[i], &qz_sess->session_setup_data, &qz_sess->session_size, &qz_sess->ctx_size); if (CPA_STATUS_SUCCESS == qz_sess->sess_status) { g_process.qz_inst[i].cpaSess = qzMalloc((size_t)(qz_sess->session_size), NODE_0, PINNED_MEM); if (NULL == g_process.qz_inst[i].cpaSess) { rc = qz_sess->sess_params.sw_backup ? QZ_LOW_MEM : QZ_NOSW_LOW_MEM; goto done_sess; } } else { rc = QZ_FAIL; goto done_sess; } QZ_DEBUG("cpaDcInitSession %d\n", i); qz_sess->sess_status = cpaDcInitSession(g_process.dc_inst_handle[i], g_process.qz_inst[i].cpaSess, &qz_sess->session_setup_data, NULL, dcCallback); if (qz_sess->sess_status != CPA_STATUS_SUCCESS) { rc = QZ_FAIL; } g_process.qz_inst[i].session_setup_data = qz_sess->session_setup_data; } if (rc == QZ_OK) { g_process.qz_inst[i].cpa_sess_setup = 1; } done_sess: return rc; } /* * Update cpa session of instance i, it will remove cpa session first, * and reallocate memory and re-initialize cpa session based on * session setup data. */ int qzUpdateCpaSession(QzSession_T *sess, int i) { QzSess_T *qz_sess; CpaStatus ret = CPA_STATUS_SUCCESS; assert(sess); g_process.qz_inst[i].cpa_sess_setup = 0; qz_sess = (QzSess_T *)sess->internal; assert(qz_sess); /* Remove cpa session */ ret = cpaDcRemoveSession(g_process.dc_inst_handle[i], g_process.qz_inst[i].cpaSess); if (ret != CPA_STATUS_SUCCESS) { QZ_ERROR("qzUpdateCpaSession: remove session failed\n"); return QZ_FAIL; } /* free memory of capSess */ qzFree(g_process.qz_inst[i].cpaSess); /* As the session setup data has been updated, need to get the size of * session again. */ ret = cpaDcGetSessionSize(g_process.dc_inst_handle[i], &qz_sess->session_setup_data, &qz_sess->session_size, &qz_sess->ctx_size); if (ret != CPA_STATUS_SUCCESS) { QZ_ERROR("qzUpdateCpaSession: get session size failed\n"); return QZ_FAIL; } g_process.qz_inst[i].cpaSess = qzMalloc((size_t)(qz_sess->session_size), NODE_0, PINNED_MEM); if (!g_process.qz_inst[i].cpaSess) { QZ_ERROR("qzUpdateCpaSession: allocate session failed\n"); return QZ_FAIL; } ret = cpaDcInitSession(g_process.dc_inst_handle[i], g_process.qz_inst[i].cpaSess, &qz_sess->session_setup_data, NULL, dcCallback); if (ret != CPA_STATUS_SUCCESS) { QZ_ERROR("qzUpdateCpaSession: init session failed\n"); free(g_process.qz_inst[i].cpaSess); g_process.qz_inst[i].cpaSess = NULL; return QZ_FAIL; } g_process.qz_inst[i].session_setup_data = qz_sess->session_setup_data; g_process.qz_inst[i].cpa_sess_setup = 1; return QZ_OK; } /* The internal function to send the compression request * to the QAT hardware. * Note: * Only when request offload success, 'submitted' and 'seq' plus, * And update src_ptr, remaining and send_sz * sess->thd_sess_stat only carry QZ_OK and QZ_FAIL */ static void *doCompressIn(void *in) { unsigned long tag; int i, j; unsigned int done = 0; unsigned int src_send_sz; unsigned int remaining; unsigned char *src_ptr; unsigned int hw_buff_sz; CpaStatus rc; QzSession_T *sess = (QzSession_T *)in; QzSess_T *qz_sess = (QzSess_T *)sess->internal; struct timespec sleep_time; sleep_time.tv_sec = 0; sleep_time.tv_nsec = GET_BUFFER_SLEEP_NSEC; QZ_DEBUG("Always enable CnV\n"); i = qz_sess->inst_hint; j = -1; /* For offlod request, src_ptr, remaining and src_send_sz will update */ hw_buff_sz = qz_sess->sess_params.hw_buff_sz; src_ptr = qz_sess->src + qz_sess->qz_in_len; remaining = *qz_sess->src_sz - qz_sess->qz_in_len; src_send_sz = (remaining < hw_buff_sz) ? remaining : hw_buff_sz; QZ_DEBUG("doCompressIn: Need to g_process %u bytes\n", remaining); while (!done) { if (g_process.qz_inst[i].heartbeat != CPA_STATUS_SUCCESS) { /* Device die, Fallback to sw, don't offload request to HW */ rc = compInSWFallback(i, j, sess, src_ptr, src_send_sz); if (QZ_WAIT_SW_PENDING == rc) { continue; } if (QZ_OK != rc) { goto err_exit; } } else { /* HW offload */ do { j = getUnusedBuffer(i, j); if (unlikely(-1 == j)) { nanosleep(&sleep_time, NULL); } } while (-1 == j); QZ_DEBUG("getUnusedBuffer returned %d\n", j); g_process.qz_inst[i].stream[j].src1++; /*update stream src1*/ compBufferSetup(i, j, qz_sess, src_ptr, remaining, hw_buff_sz, src_send_sz); g_process.qz_inst[i].stream[j].src2++;/*this buffer is in use*/ do { tag = ((unsigned long)i << 16) | (unsigned long)j; QZ_DEBUG("Comp Sending %u bytes ,opData.flushFlag = %d, i = %d j = %d seq = %ld tag = %ld\n", g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes, g_process.qz_inst[i].stream[j].opData.flushFlag, i, j, g_process.qz_inst[i].stream[j].seq, tag); rc = cpaDcCompressData2(g_process.dc_inst_handle[i], g_process.qz_inst[i].cpaSess, g_process.qz_inst[i].src_buffers[j], g_process.qz_inst[i].dest_buffers[j], &g_process.qz_inst[i].stream[j].opData, &g_process.qz_inst[i].stream[j].res, (void *)(tag)); if (unlikely(CPA_STATUS_RETRY == rc)) { g_process.qz_inst[i].num_retries++; usleep(g_polling_interval[qz_sess->polling_idx]); } if (unlikely(g_process.qz_inst[i].num_retries > MAX_NUM_RETRY)) { QZ_ERROR("instance %d retry count:%d exceed the max count: %d\n", i, g_process.qz_inst[i].num_retries, MAX_NUM_RETRY); break; } } while (rc == CPA_STATUS_RETRY); g_process.qz_inst[i].num_retries = 0; if (unlikely(CPA_STATUS_SUCCESS != rc)) { QZ_ERROR("Inst %d, buffer %d, Error in compIn offload: %d\n", i, j, rc); compInBufferCleanUp(i, j); rc = compInSWFallback(i, j, sess, src_ptr, src_send_sz); if (QZ_WAIT_SW_PENDING == rc) { continue; } if (QZ_OK != rc) { goto err_exit; } } } QZ_DEBUG("remaining = %u, src_send_sz = %u, seq = %ld\n", remaining, src_send_sz, qz_sess->seq); /* update the request src info status */ src_ptr += src_send_sz; remaining -= src_send_sz; src_send_sz = (remaining < hw_buff_sz) ? remaining : hw_buff_sz; /* update qz_sess status */ qz_sess->seq++; qz_sess->submitted++; if (unlikely(qz_sess->stop_submitting)) { remaining = 0; } if (0 == remaining) { done = 1; qz_sess->last_submitted = 1; } } return ((void *)NULL); err_exit: /*reset the qz_sess status*/ qz_sess->stop_submitting = 1; qz_sess->last_submitted = 1; sess->thd_sess_stat = QZ_FAIL; return ((void *)NULL); } /* The internal function to g_process the compression response * from the QAT hardware * sess->thd_sess_stat only carry QZ_OK and QZ_FAIL and QZ_BUF_ERROR */ static void *doCompressOut(void *in) { int i = 0, j = 0; int rc = 0; int good = -1; CpaDcRqResults *resl; CpaStatus sts; unsigned int sleep_cnt = 0; QzSession_T *sess = (QzSession_T *) in; QzSess_T *qz_sess = (QzSess_T *) sess->internal; long dest_avail_len = (long)(*qz_sess->dest_sz - qz_sess->qz_out_len); i = qz_sess->inst_hint; DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; QzPollingMode_T polling_mode = qz_sess->sess_params.polling_mode; while ((qz_sess->last_submitted == 0) || (qz_sess->processed < qz_sess->submitted)) { /* Poll for responses */ good = 0; /* For this call, return error, we have to make sure all stream buffer is reset * which is not just for RestoreSrcCpastreamBuffer, but also * make src1, src2, sink1, sink2 equal, and all switch. */ sts = icp_sal_DcPollInstance(g_process.dc_inst_handle[i], 0); if (unlikely(CPA_STATUS_FAIL == sts)) { /* this will cause the in-flight request is not finished */ QZ_ERROR("Error in DcPoll: %d\n", sts); goto err_exit; } /*fake a retrieve*/ for (j = 0; j < g_process.qz_inst[i].dest_count; j++) { if ((g_process.qz_inst[i].stream[j].seq == qz_sess->seq_in) && (g_process.qz_inst[i].stream[j].src1 == g_process.qz_inst[i].stream[j].src2) && (g_process.qz_inst[i].stream[j].sink1 == g_process.qz_inst[i].stream[j].src1) && (g_process.qz_inst[i].stream[j].sink1 == g_process.qz_inst[i].stream[j].sink2 + 1)) { good = 1; QZ_DEBUG("doCompressOut: Processing seqnumber %2.2d " "%2.2d %4.4ld, PID: %d, TID: %lu\n", i, j, g_process.qz_inst[i].stream[j].seq, getpid(), pthread_self()); if (unlikely(QZ_BUF_ERROR == sess->thd_sess_stat)) { compOutSkipErrorRespond(i, j, qz_sess); continue; } /* res.status is passed into QAT by cpaDcCompressData2, and changed in * dcCompression_ProcessCallback, it's type is CpaDcReqStatus. * job_status is from the dccallback, it's type is CpaStatus. * Generally, the res.status should have more detailed info about device error * we assume fallback feature will always call callback func, as well as * cpaDcCompressData2 return success. res.status and job_status should * all return Error status, but with different error number. */ resl = &g_process.qz_inst[i].stream[j].res; if (unlikely(CPA_STATUS_SUCCESS != g_process.qz_inst[i].stream[j].job_status || CPA_DC_OK != resl->status)) { QZ_DEBUG("Error(%d) in callback: %d, %d, ReqStatus: %d\n", g_process.qz_inst[i].stream[j].job_status, i, j, g_process.qz_inst[i].stream[j].res.status); /* polled error/dummy respond , fallback to sw */ rc = compOutSWFallback(i, j, sess, &dest_avail_len); if (QZ_FAIL == rc) { QZ_ERROR("Error in SW CompOut:inst %d, buffer %d, seq %ld\n", i, j, qz_sess->seq_in); goto err_exit; } if (QZ_BUF_ERROR == rc) { continue; } } else { /* polled HW respond */ QZ_DEBUG("\tHW CompOut: consumed = %d, produced = %d, seq_in = %ld\n", resl->consumed, resl->produced, g_process.qz_inst[i].stream[j].seq); unsigned int dest_receive_sz = outputHeaderSz(data_fmt) + resl->produced + outputFooterSz(data_fmt); if (QZ_OK != compOutCheckDestLen(i, j, sess, &dest_avail_len, dest_receive_sz)) { continue; } /* Update qz_sess info and clean dest buffer */ outputHeaderGen(qz_sess->next_dest, resl, data_fmt); qz_sess->next_dest += outputHeaderSz(data_fmt); qz_sess->qz_out_len += outputHeaderSz(data_fmt); compOutValidDestBufferCleanUp(i, j, qz_sess, resl->produced); qz_sess->next_dest += resl->produced; qz_sess->qz_in_len += resl->consumed; if (likely(NULL != qz_sess->crc32 && IS_DEFLATE(data_fmt))) { if (0 == *(qz_sess->crc32)) { *(qz_sess->crc32) = resl->checksum; } else { *(qz_sess->crc32) = crc32_combine(*(qz_sess->crc32), resl->checksum, resl->consumed); } } qz_sess->qz_out_len += resl->produced; outputFooterGen(qz_sess, resl, data_fmt); qz_sess->next_dest += outputFooterSz(data_fmt); qz_sess->qz_out_len += outputFooterSz(data_fmt); } /* process finished! */ compOutProcessedRespond(i, j, qz_sess); break; } } if (QZ_PERIODICAL_POLLING == polling_mode) { if (0 == good) { qz_sess->polling_idx = (qz_sess->polling_idx >= POLLING_LIST_NUM - 1) ? (POLLING_LIST_NUM - 1) : (qz_sess->polling_idx + 1); QZ_DEBUG("comp sleep for %d usec..., for inst %d\n", g_polling_interval[qz_sess->polling_idx], i); usleep(g_polling_interval[qz_sess->polling_idx]); sleep_cnt++; } else { qz_sess->polling_idx = (qz_sess->polling_idx == 0) ? (0) : (qz_sess->polling_idx - 1); } } } QZ_DEBUG("Comp sleep_cnt: %u\n", sleep_cnt); if (qz_sess->stop_submitting || qz_sess->last_submitted) { qz_sess->last_processed = 1; } else { qz_sess->last_processed = 0; } return NULL; err_exit: sess->thd_sess_stat = QZ_FAIL; qz_sess->stop_submitting = 1; qz_sess->last_processed = 1; /*clean stream buffer*/ for (j = 0; j < g_process.qz_inst[i].dest_count; j++) { RestoreSrcCpastreamBuffer(i, j); RestoreDestCpastreamBuffer(i, j); ResetCpastreamSink(i, j); } return NULL; } unsigned char getSwBackup(QzSession_T *sess) { QzSess_T *qz_sess; if (sess->internal != NULL) { qz_sess = (QzSess_T *)sess->internal; return qz_sess->sess_params.sw_backup; } else { return g_sess_params_internal_default.sw_backup; } } static void resetQzsess(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, const unsigned char *dest, unsigned int *dest_len, unsigned int last) { QzSess_T *qz_sess; qz_sess = (QzSess_T *)(sess->internal); sess->thd_sess_stat = QZ_OK; qz_sess->submitted = 0; qz_sess->processed = 0; qz_sess->last_submitted = 0; qz_sess->last_processed = 0; qz_sess->stop_submitting = 0; qz_sess->qz_in_len = 0; qz_sess->qz_out_len = 0; qz_sess->force_sw = 0; qz_sess->single_thread = 0; qz_sess->seq = 0; qz_sess->seq_in = 0; qz_sess->src = (unsigned char *)src; qz_sess->src_sz = src_len; qz_sess->dest_sz = dest_len; qz_sess->next_dest = (unsigned char *)dest; qz_sess->last = last; } static int lz4sPostProcess(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, uint64_t *ext_rc) { QzSess_T *qz_sess; qz_sess = (QzSess_T *)(sess->internal); if (sess->thd_sess_stat == QZ_OK || (sess->thd_sess_stat == QZ_BUF_ERROR && 0 != *src_len)) { int error_code = 0; int callback_status = qz_sess->sess_params.qzCallback( qz_sess->sess_params.qzCallback_external, src, src_len, dest, dest_len, &error_code); if (callback_status == QZ_OK) { qz_sess->qz_out_len = *dest_len; if (!ext_rc) { QZ_ERROR("Invalid ext_rc pointer!\n"); } else { *ext_rc = 0; } } else { QZ_ERROR("Error when call lz4s post-processing callback\n"); if (!ext_rc) { QZ_ERROR("Invalid ext_rc pointer!\n"); } else { *ext_rc = (uint64_t)error_code; } sess->thd_sess_stat = callback_status; return sess->thd_sess_stat; } } else { QZ_ERROR("Error lz4s compresse failed\n"); return QZ_FAIL; } return QZ_OK; } /* The QATzip compression API */ int qzCompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last) { return qzCompressExt(sess, src, src_len, dest, dest_len, last, NULL); } int qzCompressExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, uint64_t *ext_rc) { if (NULL == sess || (last != 0 && last != 1)) { if (NULL != src_len) { *src_len = 0; } if (NULL != dest_len) { *dest_len = 0; } return QZ_PARAMS; } return qzCompressCrcExt(sess, src, src_len, dest, dest_len, last, NULL, ext_rc); } int qzCompressCrc(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, unsigned long *crc) { return qzCompressCrcExt(sess, src, src_len, dest, dest_len, last, crc, NULL); } int qzCompressCrcExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last, unsigned long *crc, uint64_t *ext_rc) { int i, reqcnt; QzSess_T *qz_sess; int rc; if (unlikely(NULL == sess || \ NULL == src || \ NULL == src_len || \ NULL == dest || \ NULL == dest_len || \ (last != 0 && last != 1))) { rc = QZ_PARAMS; goto err_exit; } /*check if init called*/ rc = qzInit(sess, getSwBackup(sess)); if (QZ_INIT_FAIL(rc)) { goto err_exit; } /*check if setupSession called*/ if (NULL == sess->internal || QZ_NONE == sess->hw_session_stat) { if (g_sess_params_internal_default.data_fmt == LZ4_FH) { rc = qzSetupSessionLZ4(sess, NULL); } else if (g_sess_params_internal_default.data_fmt == LZ4S_BK) { rc = qzSetupSessionLZ4S(sess, NULL); } else { rc = qzSetupSessionDeflate(sess, NULL); } if (unlikely(QZ_SETUP_SESSION_FAIL(rc))) { goto err_exit; } } qz_sess = (QzSess_T *)(sess->internal); DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; if (unlikely(data_fmt != DEFLATE_4B && data_fmt != DEFLATE_RAW && data_fmt != DEFLATE_GZIP && data_fmt != DEFLATE_GZIP_EXT && data_fmt != LZ4_FH && data_fmt != LZ4S_BK)) { QZ_ERROR("Unknown data format: %d\n", data_fmt); rc = QZ_UNSUPPORTED_FMT; goto err_exit; } QZ_DEBUG("qzCompressCrc data_fmt: %d, input crc32 is 0x%lX\n", data_fmt, crc ? *crc : 0); qz_sess->crc32 = crc; if (*src_len < qz_sess->sess_params.input_sz_thrshold || g_process.qz_init_status == QZ_NO_HW || sess->hw_session_stat == QZ_NO_HW #if !((CPA_DC_API_VERSION_NUM_MAJOR >= 3) && (CPA_DC_API_VERSION_NUM_MINOR >= 0)) || qz_sess->sess_params.comp_lvl == 9 #endif ) { QZ_DEBUG("compression src_len=%u, sess_params.input_sz_thrshold = %u, " "process.qz_init_status = %d, sess->hw_session_stat = %ld, " " switch to software.\n", *src_len, qz_sess->sess_params.input_sz_thrshold, g_process.qz_init_status, sess->hw_session_stat); goto sw_compression; } else if (sess->hw_session_stat != QZ_OK && sess->hw_session_stat != QZ_NO_INST_ATTACH) { rc = sess->hw_session_stat; goto err_exit; } i = qzGrabInstance(qz_sess->inst_hint, &(qz_sess->sess_params)); if (unlikely(i == -1)) { if (qz_sess->sess_params.sw_backup == 1) { goto sw_compression; } else { sess->hw_session_stat = QZ_NO_INST_ATTACH; rc = QZ_NOSW_NO_INST_ATTACH; goto err_exit; } /*Make this a s/w compression*/ } QZ_DEBUG("qzCompress: inst is %d\n", i); qz_sess->inst_hint = i; if (likely(0 == g_process.qz_inst[i].mem_setup || 0 == g_process.qz_inst[i].cpa_sess_setup)) { QZ_DEBUG("Getting HW resources for inst %d\n", i); rc = qzSetupHW(sess, i); if (unlikely(QZ_OK != rc)) { qzReleaseInstance(i); if (qz_sess->sess_params.sw_backup == 1) { goto sw_compression; } else { goto err_exit; } } } else if (memcmp(&g_process.qz_inst[i].session_setup_data, &qz_sess->session_setup_data, sizeof(CpaDcSessionSetupData))) { /* session_setup_data of qz_sess is not same with instance i, need to update cpa session of instance i. */ rc = qzUpdateCpaSession(sess, i); if (QZ_OK != rc) { qzReleaseInstance(i); if (qz_sess->sess_params.sw_backup == 1) { goto sw_compression; } else { goto err_exit; } } } #ifdef QATZIP_DEBUG insertThread((unsigned int)pthread_self(), COMPRESSION, HW); #endif resetQzsess(sess, src, src_len, dest, dest_len, last); reqcnt = *src_len / qz_sess->sess_params.hw_buff_sz; if (*src_len % qz_sess->sess_params.hw_buff_sz) { reqcnt++; } if (reqcnt > qz_sess->sess_params.req_cnt_thrshold) { pthread_create(&(qz_sess->c_th_i), NULL, doCompressIn, (void *)sess); doCompressOut((void *)sess); pthread_join(qz_sess->c_th_i, NULL); } else { qz_sess->single_thread = 1; doCompressIn((void *)sess); doCompressOut((void *)sess); } qzReleaseInstance(i); rc = sess->thd_sess_stat; if (qz_sess->seq != qz_sess->seq_in) { /* this means the HW get data already error, qz_in_len and qz_out_len can't equal */ QZ_ERROR("The thread : %lu, Compress API failed! fatal error!\n", pthread_self()); goto err_exit; } /* if failure need to fallback to sw */ if (QZ_OK != sess->thd_sess_stat && QZ_BUF_ERROR != rc && qz_sess->sess_params.sw_backup == 1) { const unsigned char *sw_src = src + qz_sess->qz_in_len; unsigned int sw_src_len = *src_len - qz_sess->qz_in_len; unsigned char *sw_dest = qz_sess->next_dest; unsigned int sw_dest_len = *dest_len - (qz_sess->next_dest - dest); QZ_DEBUG("SW Comp Sending %u bytes, the rest comp all fallback to SW", sw_src_len); rc = qzSWCompress(sess, sw_src, &sw_src_len, sw_dest, &sw_dest_len, last); if (QZ_OK == rc) { qz_sess->qz_in_len += sw_src_len; qz_sess->qz_out_len += sw_dest_len; qz_sess->next_dest += sw_dest_len; sess->thd_sess_stat = rc; } else { QZ_ERROR("SW Comp fallback failure! compress fatal ERROR!\n"); } } *dest_len = qz_sess->next_dest - dest; *src_len = GET_LOWER_32BITS(qz_sess->qz_in_len); sess->total_in += qz_sess->qz_in_len; sess->total_out += qz_sess->qz_out_len; QZ_DEBUG("\n********* total_in = %lu total_out = %lu src_len = %u dest_len = %u\n", sess->total_in, sess->total_out, *src_len, *dest_len); assert(*dest_len == qz_sess->qz_out_len); //trigger post-processing if (data_fmt == LZ4S_BK && qz_sess->sess_params.qzCallback) { rc = lz4sPostProcess(sess, src, src_len, dest, dest_len, ext_rc); if (QZ_OK != rc) { goto err_exit; } } return sess->thd_sess_stat; sw_compression: QZ_DEBUG("The thread : %lu, Compress API SW fallback due to HW limitaions!\n", pthread_self()); return qzSWCompress(sess, src, src_len, dest, dest_len, last); err_exit: if (NULL != src_len) { *src_len = 0; } if (NULL != dest_len) { *dest_len = 0; } return rc; } /* The internal function to send the decompression request * to the QAT hardware * sess->thd_sess_stat carry QZ_OK && QZ_DATA_ERROR && QZ_BUF_ERROR && QZ_FAIL */ static void *doDecompressIn(void *in) { unsigned long i, tag; int rc; int j; unsigned int done = 0; unsigned int remaining; unsigned int src_avail_len, dest_avail_len; unsigned int tmp_src_avail_len, tmp_dest_avail_len; unsigned char *src_ptr; unsigned char *dest_ptr; QzGzH_T hdr = {{0}, 0}; QzSession_T *sess = (QzSession_T *)in; QzSess_T *qz_sess = (QzSess_T *)sess->internal; struct timespec sleep_time; sleep_time.tv_sec = 0; sleep_time.tv_nsec = GET_BUFFER_SLEEP_NSEC; i = qz_sess->inst_hint; j = -1; /* For offlod request, src_ptr, dest_ptr, remaining and src_avail_len, dest_avail_len will update */ src_ptr = qz_sess->src + qz_sess->qz_in_len; dest_ptr = qz_sess->next_dest; remaining = *qz_sess->src_sz - qz_sess->qz_in_len; src_avail_len = remaining; dest_avail_len = (long)(*qz_sess->dest_sz - qz_sess->qz_out_len); QZ_DEBUG("doDecompressIn: Need to g_process %d bytes\n", remaining); /* rc will only maintain in this function, thd_sess_stat will return the error status */ while (!done) { QZ_DEBUG("src_avail_len is %u, dest_avail_len is %u\n", src_avail_len, dest_avail_len); rc = checkHeader(qz_sess, src_ptr, src_avail_len, dest_avail_len, &hdr); if (QZ_OK != rc && QZ_FORCE_SW != rc) { sess->thd_sess_stat = rc; goto err_exit; } if (g_process.qz_inst[i].heartbeat != CPA_STATUS_SUCCESS || QZ_FORCE_SW == rc) { tmp_src_avail_len = src_avail_len; tmp_dest_avail_len = dest_avail_len; rc = decompInSWFallback(i, j, sess, src_ptr, dest_ptr, &tmp_src_avail_len, &tmp_dest_avail_len); if (QZ_WAIT_SW_PENDING == rc) { continue; } if (QZ_OK != rc) { goto err_exit; } } else { /*HW decompression*/ do { j = getUnusedBuffer(i, j); if (qz_sess->single_thread) { if (unlikely((-1 == j) || ((0 == qz_sess->seq % qz_sess->sess_params.req_cnt_thrshold) && (qz_sess->seq > qz_sess->seq_in)))) { return ((void *) NULL); } } else { if (unlikely(-1 == j)) { nanosleep(&sleep_time, NULL); } } } while (-1 == j); QZ_DEBUG("getUnusedBuffer returned %d\n", j); g_process.qz_inst[i].stream[j].src1++;/*this buffer is in use*/ decompBufferSetup(i, j, qz_sess, src_ptr, dest_ptr, src_avail_len, &hdr, &tmp_src_avail_len, &tmp_dest_avail_len); g_process.qz_inst[i].stream[j].src2++;/*this buffer is in use*/ do { tag = (i << 16) | j; QZ_DEBUG("Decomp Sending i = %ld j = %d src_ptr = %p dest_ptr = %p seq = %ld tag = %ld\n", i, j, src_ptr, dest_ptr, g_process.qz_inst[i].stream[j].seq, tag); rc = cpaDcDecompressData(g_process.dc_inst_handle[i], g_process.qz_inst[i].cpaSess, g_process.qz_inst[i].src_buffers[j], g_process.qz_inst[i].dest_buffers[j], &g_process.qz_inst[i].stream[j].res, CPA_DC_FLUSH_FINAL, (void *)(tag)); if (unlikely(CPA_STATUS_RETRY == rc)) { g_process.qz_inst[i].num_retries++; usleep(g_polling_interval[qz_sess->polling_idx]); } if (unlikely(g_process.qz_inst[i].num_retries > MAX_NUM_RETRY)) { QZ_ERROR("instance %lu retry count:%d exceed the max count: %d\n", i, g_process.qz_inst[i].num_retries, MAX_NUM_RETRY); break; } } while (rc == CPA_STATUS_RETRY); g_process.qz_inst[i].num_retries = 0; if (unlikely(CPA_STATUS_SUCCESS != rc)) { QZ_ERROR("Inst %ld, buffer %d, Error in decompIn offload: %d\n", i, j, rc); decompInBufferCleanUp(i, j); tmp_src_avail_len = src_avail_len; tmp_dest_avail_len = dest_avail_len; rc = decompInSWFallback(i, j, sess, src_ptr, dest_ptr, &tmp_src_avail_len, &tmp_dest_avail_len); if (QZ_WAIT_SW_PENDING == rc) { continue; } if (QZ_OK != rc) { goto err_exit; } } } /* update the request src info status */ src_ptr += tmp_src_avail_len; dest_ptr += tmp_dest_avail_len; src_avail_len -= tmp_src_avail_len; dest_avail_len -= tmp_dest_avail_len; remaining -= tmp_src_avail_len; /* update qz_sess status */ qz_sess->seq++; qz_sess->submitted++; if (qz_sess->stop_submitting) { remaining = 0; } QZ_DEBUG("src_ptr is %p, remaining is %d\n", src_ptr, remaining); if (0 == remaining) { done = 1; qz_sess->last_submitted = 1; } } return ((void *)NULL); err_exit: /*reset the qz_sess status*/ qz_sess->stop_submitting = 1; qz_sess->last_submitted = 1; return ((void *)NULL); } /* The internal function to g_process the decompression response * from the QAT hardware */ /* A fix for the chunksize test performance. Without the attribute * cold it will lead to a performance drop in the chunksize test. * Will root cause it and fix it in the future version * * sess->thd_sess_stat carry QZ_OK && QZ_DATA_ERROR && QZ_FAIL * QZ_DATA_ERROR it seems have conflict with decompressIn */ static void *__attribute__((cold)) doDecompressOut(void *in) { int i = 0, j = 0, good; int rc = 0; CpaDcRqResults *resl; CpaStatus sts; unsigned int sleep_cnt = 0; unsigned int done = 0; unsigned int src_send_sz; unsigned int dest_avail_len; QzSession_T *sess = (QzSession_T *)in; QzSess_T *qz_sess = (QzSess_T *)sess->internal; DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; QzPollingMode_T polling_mode = qz_sess->sess_params.polling_mode; i = qz_sess->inst_hint; dest_avail_len = *qz_sess->dest_sz - qz_sess->qz_out_len; while (!done) { /* Poll for responses */ good = 0; sts = icp_sal_DcPollInstance(g_process.dc_inst_handle[i], 0); if (unlikely(CPA_STATUS_FAIL == sts)) { /* if this error, we don't know which buffer is swapped */ QZ_ERROR("Error in DcPoll: %d\n", sts); goto err_exit; } /*fake a retrieve*/ for (j = 0; j < g_process.qz_inst[i].dest_count; j++) { if ((g_process.qz_inst[i].stream[j].seq == qz_sess->seq_in) && (g_process.qz_inst[i].stream[j].src1 == g_process.qz_inst[i].stream[j].src2) && (g_process.qz_inst[i].stream[j].sink1 == g_process.qz_inst[i].stream[j].src1) && (g_process.qz_inst[i].stream[j].sink1 == g_process.qz_inst[i].stream[j].sink2 + 1)) { good = 1; QZ_DEBUG("doDecompressOut: Processing seqnumber %2.2d %2.2d %4.4ld\n", i, j, g_process.qz_inst[i].stream[j].seq); if (unlikely(QZ_DATA_ERROR == sess->thd_sess_stat)) { decompOutSkipErrorRespond(i, j, qz_sess); continue; } if (unlikely(CPA_STATUS_SUCCESS != g_process.qz_inst[i].stream[j].job_status)) { QZ_DEBUG("Error(%d) in callback: %d, %d, ReqStatus: %d\n", g_process.qz_inst[i].stream[j].job_status, i, j, g_process.qz_inst[i].stream[j].res.status); /* polled error/dummy respond , fallback to sw */ rc = decompOutSWFallback(i, j, sess, &dest_avail_len); if (QZ_FAIL == rc) { QZ_ERROR("Error in SW deCompOut:inst %d, buffer %d, seq %ld\n", i, j, qz_sess->seq_in); /* Need to swap buffer, even sw fallback failed */ swapDataBuffer(i, j); goto err_exit; } } else { resl = &g_process.qz_inst[i].stream[j].res; QZ_DEBUG("\tHW DecompOut: consumed = %d, produced = %d, seq_in = %ld, src_send_sz = %u\n", resl->consumed, resl->produced, g_process.qz_inst[i].stream[j].seq, g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes); /* update the qz_sess info and clean dest buffer */ decompOutValidDestBufferCleanUp(i, j, qz_sess, resl, dest_avail_len); if (QZ_OK != decompOutCheckSum(i, j, sess, resl)) { continue; } src_send_sz = g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes; qz_sess->next_dest += resl->produced; qz_sess->qz_in_len += (outputHeaderSz(data_fmt) + src_send_sz + outputFooterSz(data_fmt)); qz_sess->qz_out_len += resl->produced; dest_avail_len -= resl->produced; } decompOutProcessedRespond(i, j, qz_sess); break; } } if (qz_sess->single_thread) { done = (qz_sess->processed == qz_sess->submitted); } else { done = (qz_sess->last_submitted) && (qz_sess->processed == qz_sess->submitted); } if (QZ_PERIODICAL_POLLING == polling_mode) { if (0 == good) { qz_sess->polling_idx = (qz_sess->polling_idx >= POLLING_LIST_NUM - 1) ? (POLLING_LIST_NUM - 1) : (qz_sess->polling_idx + 1); QZ_DEBUG("decomp sleep for %d usec..., for inst %d\n", g_polling_interval[qz_sess->polling_idx], i); usleep(g_polling_interval[qz_sess->polling_idx]); sleep_cnt++; } else { qz_sess->polling_idx = (qz_sess->polling_idx == 0) ? (0) : (qz_sess->polling_idx - 1); } } } QZ_DEBUG("Decomp sleep_cnt: %u\n", sleep_cnt); qz_sess->last_processed = qz_sess->last_submitted ? 1 : 0; return NULL; err_exit: qz_sess->stop_submitting = 1; qz_sess->last_processed = 1; sess->thd_sess_stat = QZ_FAIL; /* clean stream buffer */ for (j = 0; j < g_process.qz_inst[i].dest_count; j++) { RestoreSrcCpastreamBuffer(i, j); RestoreDestCpastreamBuffer(i, j); ResetCpastreamSink(i, j); } /* need add flag for buffer swap. swapDataBuffer(i, j); */ return ((void *)NULL); } /* The internal function to process the single thread decompress * in qzDecompress() */ static void *doQzDecompressSingleThread(void *in) { QzSession_T *sess = (QzSession_T *)in; QzSess_T *qz_sess = (QzSess_T *)sess->internal; qz_sess->last_processed = 0; while (!qz_sess->last_processed) { doDecompressIn((void *)sess); doDecompressOut((void *)sess); } return NULL; } /* The QATzip decompression API */ int qzDecompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len) { return qzDecompressExt(sess, src, src_len, dest, dest_len, NULL); } int qzDecompressExt(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, uint64_t *ext_rc) { int rc; int i, reqcnt; QzSess_T *qz_sess; QzGzH_T *hdr = (QzGzH_T *)src; if (unlikely(NULL == sess || \ NULL == src || \ NULL == src_len || \ NULL == dest || \ NULL == dest_len)) { rc = QZ_PARAMS; goto err_exit; } if (0 == *src_len) { *dest_len = 0; return QZ_OK; } /*check if init called*/ rc = qzInit(sess, getSwBackup(sess)); if (QZ_INIT_FAIL(rc)) { goto err_exit; } /*check if setupSession called*/ if (NULL == sess->internal || QZ_NONE == sess->hw_session_stat) { if (g_sess_params_internal_default.data_fmt == LZ4_FH) { rc = qzSetupSessionLZ4(sess, NULL); } else if (g_sess_params_internal_default.data_fmt == LZ4S_BK) { rc = qzSetupSessionLZ4S(sess, NULL); } else { rc = qzSetupSessionDeflate(sess, NULL); } if (unlikely(QZ_SETUP_SESSION_FAIL(rc))) { goto err_exit; } } qz_sess = (QzSess_T *)(sess->internal); DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; if (unlikely(data_fmt != DEFLATE_RAW && data_fmt != DEFLATE_4B && data_fmt != DEFLATE_GZIP && data_fmt != LZ4_FH && data_fmt != DEFLATE_GZIP_EXT)) { QZ_ERROR("Unknown/unsupported data format: %d\n", data_fmt); rc = QZ_UNSUPPORTED_FMT; goto err_exit; } QZ_DEBUG("qzDecompress data_fmt: %d\n", data_fmt); if (data_fmt == DEFLATE_RAW || (data_fmt == DEFLATE_GZIP_EXT && hdr->extra.qz_e.src_sz < qz_sess->sess_params.input_sz_thrshold) || g_process.qz_init_status == QZ_NO_HW || sess->hw_session_stat == QZ_NO_HW || !(isQATProcessable(src, src_len, qz_sess)) || qz_sess->inflate_stat == InflateOK) { QZ_DEBUG("decompression src_len=%u, hdr->extra.qz_e.src_sz = %u, " "g_process.qz_init_status = %d, sess->hw_session_stat = %ld, " "isQATProcessable = %d, switch to software.\n", *src_len, hdr->extra.qz_e.src_sz, g_process.qz_init_status, sess->hw_session_stat, isQATProcessable(src, src_len, qz_sess)); /* If sw_backup is 1, fallback to software compression. */ if (qz_sess->sess_params.sw_backup == 1) { goto sw_decompression; } else { rc = QZ_FAIL; goto err_exit; } } else if (sess->hw_session_stat != QZ_OK && sess->hw_session_stat != QZ_NO_INST_ATTACH) { rc = sess->hw_session_stat; goto err_exit; } i = qzGrabInstance(qz_sess->inst_hint, &(qz_sess->sess_params)); if (unlikely(i == -1)) { if (qz_sess->sess_params.sw_backup == 1) { QZ_DEBUG("Don't grab HW instance, fallback to sw\n"); goto sw_decompression; } else { rc = sess->hw_session_stat = QZ_NO_INST_ATTACH; goto err_exit; } /*Make this a s/w compression*/ } QZ_DEBUG("qzDecompress: inst is %d\n", i); qz_sess->inst_hint = i; if (likely(0 == g_process.qz_inst[i].mem_setup || 0 == g_process.qz_inst[i].cpa_sess_setup)) { QZ_DEBUG("Getting HW resources for inst %d\n", i); rc = qzSetupHW(sess, i); if (unlikely(QZ_OK != rc)) { qzReleaseInstance(i); if (qz_sess->sess_params.sw_backup == 1) { goto sw_decompression; } else { goto err_exit; } } } else if (memcmp(&g_process.qz_inst[i].session_setup_data, &qz_sess->session_setup_data, sizeof(CpaDcSessionSetupData))) { /* session_setup_data of qz_sess is not same with instance i, need to update cpa session of instance i. */ rc = qzUpdateCpaSession(sess, i); if (QZ_OK != rc) { qzReleaseInstance(i); if (qz_sess->sess_params.sw_backup == 1) { goto sw_decompression; } else { goto err_exit; } } } #ifdef QATZIP_DEBUG insertThread((unsigned int)pthread_self(), DECOMPRESSION, HW); #endif resetQzsess(sess, src, src_len, dest, dest_len, 0); reqcnt = *src_len / (qz_sess->sess_params.hw_buff_sz / 2); if (*src_len % (qz_sess->sess_params.hw_buff_sz / 2)) { reqcnt++; } if (reqcnt > qz_sess->sess_params.req_cnt_thrshold) { qz_sess->single_thread = 0; pthread_create(&(qz_sess->c_th_i), NULL, doDecompressIn, (void *)sess); doDecompressOut((void *)sess); pthread_join(qz_sess->c_th_i, NULL); } else { qz_sess->single_thread = 1; doQzDecompressSingleThread((void *)sess); } qzReleaseInstance(i); QZ_DEBUG("PRoduced %lu bytes\n", sess->total_out); rc = sess->thd_sess_stat; if (qz_sess->seq != qz_sess->seq_in) { /* this means the HW get data already error, qz_in_len and qz_out_len can't corresponding */ QZ_ERROR("The thread : %lu, Decompress API failed! error status %d!\n", pthread_self(), rc); goto err_exit; } /* if failure need to fallback to sw */ if (QZ_OK != sess->thd_sess_stat && QZ_BUF_ERROR != sess->thd_sess_stat && QZ_DATA_ERROR != sess->thd_sess_stat && qz_sess->sess_params.sw_backup == 1) { const unsigned char *sw_src = src + qz_sess->qz_in_len; unsigned int sw_src_len = *src_len - qz_sess->qz_in_len; unsigned char *sw_dest = qz_sess->next_dest; unsigned int sw_dest_len = *dest_len - (qz_sess->next_dest - dest); QZ_DEBUG("SW deComp Sending %u bytes, the rest decomp all fallback to SW", sw_src_len); rc = qzSWDecompressMulti(sess, sw_src, &sw_src_len, sw_dest, &sw_dest_len); if (QZ_OK == rc) { qz_sess->qz_in_len += sw_src_len; qz_sess->qz_out_len += sw_dest_len; qz_sess->next_dest += sw_dest_len; sess->thd_sess_stat = rc; } else { QZ_ERROR("SW deComp fallback failure! compress fatal ERROR!\n"); } } *src_len = GET_LOWER_32BITS(qz_sess->qz_in_len); *dest_len = qz_sess->next_dest - dest; assert(*dest_len == qz_sess->qz_out_len); sess->total_in += qz_sess->qz_in_len; sess->total_out += qz_sess->qz_out_len; QZ_DEBUG("total_in=%lu total_out=%lu src_len=%u dest_len=%u rc=%d\n", sess->total_in, sess->total_out, *src_len, *dest_len, rc); return sess->thd_sess_stat; sw_decompression: QZ_DEBUG("The thread : %lu, DeCompress API SW fallback due to HW limitations!\n", pthread_self()); return qzSWDecompressMulti(sess, src, src_len, dest, dest_len); err_exit: if (NULL != src_len) { *src_len = 0; } if (NULL != dest_len) { *dest_len = 0; } return rc; } int qzTeardownSession(QzSession_T *sess) { if (unlikely(sess == NULL)) { return QZ_PARAMS; } if (likely(NULL != sess->internal)) { QzSess_T *qz_sess = (QzSess_T *) sess->internal; if (likely(NULL != qz_sess->inflate_strm)) { inflateEnd(qz_sess->inflate_strm); free(qz_sess->inflate_strm); qz_sess->inflate_strm = NULL; } if (likely(NULL != qz_sess->deflate_strm)) { deflateEnd(qz_sess->deflate_strm); free(qz_sess->deflate_strm); qz_sess->deflate_strm = NULL; } free(sess->internal); sess->internal = NULL; } return QZ_OK; } void removeSession(int i) { CpaStatus status = CPA_STATUS_SUCCESS; if (0 == g_process.qz_inst[i].cpa_sess_setup) { return; } /* Remove session */ if ((NULL != g_process.dc_inst_handle[i]) && (NULL != g_process.qz_inst[i].cpaSess)) { status = cpaDcRemoveSession(g_process.dc_inst_handle[i], g_process.qz_inst[i].cpaSess); if (CPA_STATUS_SUCCESS == status) { /* Deallocate session memory */ qzFree(g_process.qz_inst[i].cpaSess); g_process.qz_inst[i].cpaSess = NULL; g_process.qz_inst[i].cpa_sess_setup = 0; } else { QZ_ERROR("ERROR in Remove Instance %d session\n", i); } } } int qzClose(QzSession_T *sess) { if (unlikely(sess == NULL)) { return QZ_PARAMS; } return QZ_OK; } int qzGetStatus(QzSession_T *sess, QzStatus_T *status) { if (sess == NULL || status == NULL) { return QZ_PARAMS; } return QZ_OK; } int qzSetDefaults(QzSessionParams_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } if (qzCheckParams(defaults) != QZ_OK) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzSetParams(defaults, &g_sess_params_internal_default); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } int qzSetDefaultsDeflate(QzSessionParamsDeflate_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } if (qzCheckParamsDeflate(defaults) != QZ_OK) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzSetParamsDeflate(defaults, &g_sess_params_internal_default); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } int qzSetDefaultsLZ4(QzSessionParamsLZ4_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } if (qzCheckParamsLZ4(defaults) != QZ_OK) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzSetParamsLZ4(defaults, &g_sess_params_internal_default); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } int qzSetDefaultsLZ4S(QzSessionParamsLZ4S_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } if (qzCheckParamsLZ4S(defaults) != QZ_OK) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzSetParamsLZ4S(defaults, &g_sess_params_internal_default); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } int qzGetDefaults(QzSessionParams_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzGetParams(&g_sess_params_internal_default, defaults); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } int qzGetDefaultsDeflate(QzSessionParamsDeflate_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzGetParamsDeflate(&g_sess_params_internal_default, defaults); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } int qzGetDefaultsLZ4(QzSessionParamsLZ4_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzGetParamsLZ4(&g_sess_params_internal_default, defaults); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } int qzGetDefaultsLZ4S(QzSessionParamsLZ4S_T *defaults) { if (defaults == NULL) { return QZ_PARAMS; } pthread_mutex_lock(&g_sess_params_lock); qzGetParamsLZ4S(&g_sess_params_internal_default, defaults); pthread_mutex_unlock(&g_sess_params_lock); return QZ_OK; } static unsigned int qzDeflateBound(unsigned int src_sz, QzSession_T *sess) { unsigned int dest_sz = 0; unsigned int chunk_cnt = 0; unsigned int hw_buffer_sz = 0; QzSess_T *qz_sess = NULL; CpaDcHuffType huffman_type; CpaStatus status = CPA_STATUS_SUCCESS; qz_sess = (QzSess_T *)sess->internal; /* Get the Huffman Tree type. */ if (qz_sess->sess_params.huffman_hdr == QZ_DYNAMIC_HDR) { huffman_type = CPA_DC_HT_FULL_DYNAMIC; } else { huffman_type = CPA_DC_HT_STATIC; } status = cpaDcDeflateCompressBound(NULL, huffman_type, src_sz, &dest_sz); if (status != CPA_STATUS_SUCCESS) { return 0; } hw_buffer_sz = qz_sess->sess_params.hw_buff_sz; /* cpaDcDeflateCompressBound only provides the maximum output size of deflate blocks, * it does not include gzip/gzip-ext header and footer size, so we need to update dest_sz * for header and footer size. */ /* Calculate how many gzip/gzip-ext headers and footers will be generated. */ chunk_cnt = src_sz / hw_buffer_sz + src_sz % hw_buffer_sz ? 1 : 0; dest_sz += chunk_cnt * (qzGzipHeaderSz() + stdGzipFooterSz()); return dest_sz; } static unsigned int qzLZ4SBound(unsigned int src_sz, QzSession_T *sess) { unsigned int dest_sz = 0; CpaStatus status = CPA_STATUS_SUCCESS; #if CPA_DC_API_VERSION_AT_LEAST(3, 1) status = cpaDcLZ4SCompressBound(NULL, src_sz, &dest_sz); if (status != CPA_STATUS_SUCCESS) { return 0; } #else (void)status; return 0; #endif return dest_sz; } static unsigned int qzLZ4Bound(unsigned int src_sz, QzSession_T *sess) { unsigned int dest_sz = 0; unsigned int chunk_cnt = 0; QzSess_T *qz_sess = NULL; CpaStatus status = CPA_STATUS_SUCCESS; assert(sess); assert(sess->internal); #if CPA_DC_API_VERSION_AT_LEAST(3, 1) status = cpaDcLZ4CompressBound(NULL, src_sz, &dest_sz); if (status != CPA_STATUS_SUCCESS) { return 0; } #else (void)status; return 0; #endif /* cpaDcLZ4CompressBound only provides the maximum output size of lz4 blocks, * it does not include lz4 frames header and footer size, so we need to update dest_sz * for header and footer size. */ /* Calculate how many frames header and footer will be generated */ qz_sess = (QzSess_T *)sess->internal; chunk_cnt = src_sz / qz_sess->sess_params.hw_buff_sz + src_sz % qz_sess->sess_params.hw_buff_sz ? 1 : 0; dest_sz += chunk_cnt * outputHeaderSz(qz_sess->sess_params.data_fmt) + chunk_cnt * outputFooterSz(qz_sess->sess_params.data_fmt); return dest_sz; } unsigned int qzMaxCompressedLength(unsigned int src_sz, QzSession_T *sess) { unsigned int dest_sz = 0; unsigned int chunk_cnt = 0; QzSess_T *qz_sess = NULL; if (src_sz == 0) { return QZ_COMPRESSED_SZ_OF_EMPTY_FILE; } if (sess == NULL || sess->internal == NULL || sess->hw_session_stat != QZ_OK) { uint64_t in_sz = src_sz; uint64_t out_sz = 0; out_sz = QZ_CEIL_DIV(9 * in_sz, 8) + QZ_SKID_PAD_SZ; chunk_cnt = in_sz / QZ_HW_BUFF_SZ + in_sz % QZ_HW_BUFF_SZ ? 1 : 0; out_sz += chunk_cnt * (qzGzipHeaderSz() + stdGzipFooterSz()); if (out_sz & 0xffffffff00000000UL) return 0; dest_sz = (unsigned int)out_sz; return dest_sz; } qz_sess = (QzSess_T *)sess->internal; switch (qz_sess->sess_params.data_fmt) { case DEFLATE_RAW: case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: case DEFLATE_4B: dest_sz = qzDeflateBound(src_sz, sess); break; case LZ4_FH: dest_sz = qzLZ4Bound(src_sz, sess); break; case LZ4S_BK: dest_sz = qzLZ4SBound(src_sz, sess); break; default: dest_sz = 0; break; } QZ_DEBUG("src_sz is %u, dest_sz is %u\n", src_sz, dest_sz); return dest_sz; } int qzGetSoftwareComponentCount(unsigned int *num_elem) { QZ_ERROR("qatzip don't support qzGetSoftwareComponentCount API yet!\n"); return QZ_FAIL; } int qzGetSoftwareComponentVersionList(QzSoftwareVersionInfo_T *api_info, unsigned int *num_elem) { QZ_ERROR("qatzip don't support qzGetSoftwareComponentVersionList API yet!\n"); return QZ_FAIL; } QATzip-1.2.0/src/qatzip_counter.c000077500000000000000000000054121456106226300166760ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #include #include #include #include #include #ifdef HAVE_QAT_HEADERS #include #include #else #include #include #endif #include "qatzip.h" #include "qatzip_internal.h" #include "qz_utils.h" extern processData_T g_process; void dumpCounters(QzInstance_T *inst) { int i; if (inst->mem_setup == 0) { QZ_PRINT("\tNot in use\n"); return; } for (i = 0; i < inst->dest_count; i++) { QZ_PRINT("\tbuffer %d\t ses %ld\t %ld %ld %ld %ld\n", i, inst->stream[i].seq, inst->stream[i].src1, inst->stream[i].src2, inst->stream[i].sink1, inst->stream[i].sink2); } } void dumpAllCounters(void) { int i; for (i = 0; i < g_process.num_instances; i++) { QZ_PRINT("Instance %d\n", i); dumpCounters(&g_process.qz_inst[i]); QZ_PRINT("\n"); } } QATzip-1.2.0/src/qatzip_gzip.c000077500000000000000000000175561456106226300162040ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #include #include #include #include #include #ifdef HAVE_QAT_HEADERS #include #include #else #include #include #endif #include "qatzip.h" #include "qatzip_internal.h" #include "qz_utils.h" #pragma pack(push, 1) inline unsigned long qzGzipHeaderSz(void) { return sizeof(QzGzH_T); } inline unsigned long stdGzipHeaderSz(void) { return sizeof(StdGzH_T); } inline unsigned long qz4BHeaderSz(void) { return sizeof(Qz4BH_T); } inline unsigned long stdGzipFooterSz(void) { return sizeof(StdGzF_T); } void qzGzipHeaderExtraFieldGen(unsigned char *ptr, CpaDcRqResults *res) { QzExtraField_T *extra; extra = (QzExtraField_T *)ptr; extra->st1 = 'Q'; extra->st2 = 'Z'; extra->x2_len = (uint16_t)sizeof(extra->qz_e); extra->qz_e.src_sz = res->consumed; extra->qz_e.dest_sz = res->produced; } void qzGzipHeaderGen(unsigned char *ptr, CpaDcRqResults *res) { assert(ptr != NULL); assert(res != NULL); QzGzH_T *hdr; hdr = (QzGzH_T *)ptr; hdr->std_hdr.id1 = 0x1f; hdr->std_hdr.id2 = 0x8b; hdr->std_hdr.cm = QZ_DEFLATE; hdr->std_hdr.flag = 0x04; /*Fextra BIT SET*/ hdr->std_hdr.mtime[0] = (char)0; hdr->std_hdr.mtime[1] = (char)0; hdr->std_hdr.mtime[2] = (char)0; hdr->std_hdr.mtime[3] = (char)0; hdr->std_hdr.xfl = 0; hdr->std_hdr.os = 255; hdr->x_len = (uint16_t)sizeof(hdr->extra); qzGzipHeaderExtraFieldGen((unsigned char *)&hdr->extra, res); } void stdGzipHeaderGen(unsigned char *ptr, CpaDcRqResults *res) { assert(ptr != NULL); assert(res != NULL); StdGzH_T *hdr; hdr = (StdGzH_T *)ptr; hdr->id1 = 0x1f; hdr->id2 = 0x8b; hdr->cm = QZ_DEFLATE; hdr->flag = 0x00; hdr->mtime[0] = (char)0; hdr->mtime[1] = (char)0; hdr->mtime[2] = (char)0; hdr->mtime[3] = (char)0; hdr->xfl = 0; hdr->os = 255; } void qz4BHeaderGen(unsigned char *ptr, CpaDcRqResults *res) { Qz4BH_T *hdr; hdr = (Qz4BH_T *)ptr; hdr->blk_size = res->produced; } int isQATDeflateProcessable(const unsigned char *ptr, const unsigned int *const src_len, QzSess_T *const qz_sess) { QzGzH_T *h = (QzGzH_T *)ptr; Qz4BH_T *h_4B; StdGzF_T *qzFooter = NULL; long buff_sz = (DEST_SZ(qz_sess->sess_params.hw_buff_sz) < *src_len ? DEST_SZ( (long)(qz_sess->sess_params.hw_buff_sz)) : *src_len); if (qz_sess->sess_params.data_fmt == DEFLATE_4B) { h_4B = (Qz4BH_T *)ptr; if (h_4B->blk_size > DEST_SZ(qz_sess->sess_params.hw_buff_sz)) { return 0; } return 1; } /*check if HW can process*/ if (h->std_hdr.id1 == 0x1f && \ h->std_hdr.id2 == 0x8b && \ h->std_hdr.cm == QZ_DEFLATE && \ h->std_hdr.flag == 0x00) { qzFooter = (StdGzF_T *)(findStdGzipFooter((const unsigned char *)h, buff_sz)); if ((unsigned char *)qzFooter - ptr - stdGzipHeaderSz() > DEST_SZ( (unsigned long)(qz_sess->sess_params.hw_buff_sz)) || qzFooter->i_size > qz_sess->sess_params.hw_buff_sz) { return 0; } qz_sess->sess_params.data_fmt = DEFLATE_GZIP; return 1; } /* Besides standard GZIP header, only Gzip header with QZ extension can be processed by QAT */ if (h->std_hdr.id1 != 0x1f || \ h->std_hdr.id2 != 0x8b || \ h->std_hdr.cm != QZ_DEFLATE) { /* There are two possibilities when h is not a gzip header: */ /* 1, wrong data */ /* 2, It is the 2nd, 3rd... part of the file with the standard gzip header. */ return -1; } return (h->extra.st1 == 'Q' && \ h->extra.st2 == 'Z'); } int qzGzipHeaderExt(const unsigned char *const ptr, QzGzH_T *hdr) { QzGzH_T *h; h = (QzGzH_T *)ptr; if (h->std_hdr.id1 != 0x1f || \ h->std_hdr.id2 != 0x8b || \ h->extra.st1 != 'Q' || \ h->extra.st2 != 'Z' || \ h->std_hdr.cm != QZ_DEFLATE || \ h->std_hdr.flag != 0x04 || \ (h->std_hdr.xfl != 0 && h->std_hdr.xfl != 2 && \ h->std_hdr.xfl != 4) || \ h->std_hdr.os != 255 || \ h->x_len != sizeof(h->extra) || \ h->extra.x2_len != sizeof(h->extra.qz_e)) { QZ_DEBUG("id1: %x, id2: %x, st1: %c, st2: %c, cm: %d, flag: %d," "xfl: %d, os: %d, x_len: %d, x2_len: %d\n", h->std_hdr.id1, h->std_hdr.id2, h->extra.st1, h->extra.st2, h->std_hdr.cm, h->std_hdr.flag, h->std_hdr.xfl, h->std_hdr.os, h->x_len, h->extra.x2_len); return QZ_FAIL; } QZ_MEMCPY(hdr, ptr, sizeof(*hdr), sizeof(*hdr)); return QZ_OK; } void qzGzipFooterGen(unsigned char *ptr, CpaDcRqResults *res) { assert(NULL != ptr); assert(NULL != res); StdGzF_T *ftr; ftr = (StdGzF_T *)ptr; ftr->crc32 = res->checksum; ftr->i_size = res->consumed; } void qzGzipFooterExt(const unsigned char *const ptr, StdGzF_T *ftr) { QZ_MEMCPY(ftr, ptr, sizeof(*ftr), sizeof(*ftr)); } unsigned char *findStdGzipFooter(const unsigned char *src_ptr, long src_avail_len) { StdGzH_T *gzHeader = NULL; unsigned int offset = stdGzipHeaderSz() + stdGzipFooterSz(); while (src_avail_len >= offset + stdGzipHeaderSz()) { gzHeader = (StdGzH_T *)(src_ptr + offset); if (gzHeader->id1 == 0x1f && \ gzHeader->id2 == 0x8b && \ gzHeader->cm == QZ_DEFLATE && \ gzHeader->flag == 0x00) { return (void *)((unsigned char *)gzHeader - stdGzipFooterSz()); } offset++; } return (void *)((unsigned char *)src_ptr + src_avail_len - stdGzipFooterSz()); } #pragma pack(pop) QATzip-1.2.0/src/qatzip_internal.h000077500000000000000000000466601456106226300170520ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifndef _QATZIPP_H #define _QATZIPP_H #ifdef __cplusplus extern"C" { #endif #ifdef HAVE_QAT_HEADERS #include #else #include #endif #include #include #include #include /** * define release version */ #define QATZIP_VERSION "1.2.0" #define SUCCESS 1 #define FAILURE 0 #define QZ_WAIT_SW_PENDING 10 #define NODE_0 0 #define NUM_BUFF (32) /** * For less than 8K hardware buffer size, it needs more in-flight buffers * to reach peak performance */ #define NUM_BUFF_8K (128) #define MAX_NUM_RETRY ((int)500) #define MAX_BUFFERS ((int)100) #define MAX_THREAD_TMR ((int)100) #define GET_LOWER_32BITS(v) ((v) & 0xFFFFFFFF) #define GET_LOWER_16BITS(v) ((v) & 0xFFFF) #define GET_LOWER_8BITS(v) ((v) & 0xFF) /*For Sync mode, request counts must less than NUM_BUFF. *If then the request can't get adequate unused buffer and will be hanged * */ #if QZ_REQ_THRESHOLD_MAXIMUM > NUM_BUFF #error QZ_REQ_THRESHOLD_MAXIMUM should not be larger than NUM_BUFF #endif #define QAT_MAX_DEVICES (32 * 32) #define STORED_BLK_MAX_LEN 65535 #define STORED_BLK_HDR_SZ 5 #define QZ_INIT_FAIL(rc) (QZ_OK != rc && \ QZ_DUPLICATE != rc) #define QZ_SETUP_SESSION_FAIL(rc) (QZ_PARAMS == rc || \ QZ_NOSW_NO_HW == rc || \ QZ_NOSW_LOW_MEM == rc) #define likely(x) __builtin_expect (!!(x), 1) #define unlikely(x) __builtin_expect (!!(x), 0) #define DEST_SZ(src_sz) (((9U * (src_sz)) / 8U) + 1024U) /* The minimal supported CAP_DC API version */ #ifndef CPA_DC_API_VERSION_AT_LEAST #define CPA_DC_API_VERSION_AT_LEAST(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR > major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR >= minor)) #endif #define QZ_CEIL_DIV(x, y) (((x) + (y)-1) / (y)) /* macros for lz4 */ #define QZ_LZ4_MAGIC 0x184D2204U #define QZ_LZ4_MAGIC_SKIPPABLE 0x184D2A50U #define QZ_LZ4_VERSION 0x1 #define QZ_LZ4_BLK_INDEP 0x0 #define QZ_LZ4_BLK_CKS_FLAG 0x0 #define QZ_LZ4_DICT_ID_FLAG 0x0 #define QZ_LZ4_CNT_SIZE_FLAG 0x1 #define QZ_LZ4_CNT_CKS_FLAG 0x1 #define QZ_LZ4_ENDMARK 0x0 #define QZ_LZ4_MAX_BLK_SIZE 0x4 #define QZ_LZ4_MAGIC_SIZE 4 //lz4 magic number length #define QZ_LZ4_FD_SIZE 11 //lz4 frame descriptor length #define QZ_LZ4_HEADER_SIZE (QZ_LZ4_MAGIC_SIZE + \ QZ_LZ4_FD_SIZE) //lz4 frame header length #define QZ_LZ4_CHECKSUM_SIZE 4 //lz4 checksum length #define QZ_LZ4_ENDMARK_SIZE 4 //lz4 endmark length #define QZ_LZ4_FOOTER_SIZE (QZ_LZ4_CHECKSUM_SIZE + \ QZ_LZ4_ENDMARK_SIZE) //lz4 frame footer length #define QZ_LZ4_BLK_HEADER_SIZE 4 //lz4 block header length #define QZ_LZ4_STOREDBLOCK_FLAG 0x80000000U #define QZ_LZ4_STORED_HEADER_SIZE 4 #define DATA_FORMAT_DEFAULT DEFLATE_GZIP_EXT #define IS_DEFLATE_RAW(fmt) (DEFLATE_RAW == (fmt)) #define IS_DEFLATE(fmt) \ (DEFLATE_RAW == (fmt) || DEFLATE_GZIP == (fmt) || \ DEFLATE_GZIP_EXT == (fmt) || DEFLATE_4B == (fmt)) typedef struct QzCpaStream_S { signed long seq; signed long src1; signed long src2; signed long sink1; signed long sink2; CpaDcRqResults res; CpaStatus job_status; unsigned char *orig_src; unsigned char *orig_dest; int src_need_reset; int dest_need_reset; unsigned int checksum; unsigned int orgdatalen; CpaDcOpData opData; } QzCpaStream_T; typedef struct QzInstance_S { CpaInstanceInfo2 instance_info; CpaDcInstanceCapabilities instance_cap; CpaBufferList **intermediate_buffers; Cpa32U buff_meta_size; /* Tracks memory where the intermediate buffers reside. */ Cpa16U intermediate_cnt; CpaBufferList **src_buffers; CpaBufferList **dest_buffers; Cpa16U src_count; Cpa16U dest_count; QzCpaStream_T *stream; unsigned int lock; /*heartbeat represent device status, which will be changed by polling events thread*/ CpaStatus heartbeat; unsigned char mem_setup; unsigned char cpa_sess_setup; CpaStatus inst_start_status; unsigned int num_retries; CpaDcSessionHandle cpaSess; CpaDcSessionSetupData session_setup_data; } QzInstance_T; typedef struct QzInstanceList_S { QzInstance_T instance; CpaInstanceHandle dc_inst_handle; struct QzInstanceList_S *next; } QzInstanceList_T; typedef struct QzHardware_S { QzInstanceList_T devices[QAT_MAX_DEVICES]; unsigned int dev_num; unsigned int max_dev_id; } QzHardware_T; typedef struct ProccesData_S { char qz_init_status; unsigned char sw_backup; CpaInstanceHandle *dc_inst_handle; QzInstance_T *qz_inst; Cpa16U num_instances; atomic_char qat_available; /* this thread handler is for keep polling device fatal events.*/ pthread_t t_poll_heartbeat; } processData_T; typedef enum { InflateError = -1, InflateNull = 0, InflateInited, InflateOK, InflateEnd } InflateState_T; typedef enum { DeflateNull = 0, DeflateInited } DeflateState_T; // Include all support data format typedef enum DataFormatInternal_E { DEFLATE_4B = 0, /**< Data is in raw deflate format with 4 byte header */ DEFLATE_GZIP, /**< Data is in deflate wrapped by GZip header and footer */ DEFLATE_GZIP_EXT, /**< Data is in deflate wrapped by GZip extended header and footer */ DEFLATE_RAW, /**< Data is in raw deflate format */ LZ4_FH, /**< Data is in LZ4 format with frame headers */ LZ4S_BK, /**< Data is in LZ4s sequences with block header, it's only for post processed */ } DataFormatInternal_T; // Include all support session parameters typedef struct QzSessionParamsInternal_S { QzHuffmanHdr_T huffman_hdr; /**< Dynamic or Static Huffman headers */ QzDirection_T direction; /**< Compress or decompress */ DataFormatInternal_T data_fmt; /**< Deflate, deflate with GZip or deflate with GZip ext */ unsigned int comp_lvl; /**< Compression level 1 to 12 for QAT CPM2.0. */ /**< If the comp_algorithm is deflate, values > max will be set to max */ unsigned char comp_algorithm; /**< Compress/decompression algorithms */ unsigned int max_forks; /**< Maximum forks permitted in the current thread */ /**< 0 means no forking permitted */ unsigned char sw_backup; /**< bit field defining SW configuration (see QZ_SW_* definitions) */ unsigned int hw_buff_sz; /**< Default buffer size, must be a power of 2k */ /**< 4K,8K,16K,32K,64K,128K */ unsigned int strm_buff_sz; /**< Stream buffer size between [1K .. 2M - 5K] */ /**< Default strm_buf_sz equals to hw_buff_sz */ unsigned int input_sz_thrshold; /**< Default threshold of compression service's input size */ /**< for sw failover, if the size of input request is less */ /**< than the threshold, QATzip will route the request */ /**< to software */ unsigned int req_cnt_thrshold; /**< Set between 1 and NUM_BUFF, default NUM_BUFF */ /**< NUM_BUFF is defined in qatzip_internal.h */ unsigned int wait_cnt_thrshold; /**< When previous try failed, wait for specific number of calls */ /**< before retrying to open device. Default threshold is 8 */ qzLZ4SCallbackFn qzCallback; /**< post processing callback for zstd compression*/ void *qzCallback_external; /**< An opaque pointer provided by the user to be passed */ /**< into qzCallback during post processing*/ QzPollingMode_T polling_mode; /**< 0 means no busy polling, 1 means busy polling */ unsigned int is_sensitive_mode; /**< 0 means disable sensitive mode, 1 means enable sensitive mode*/ unsigned int lz4s_mini_match; /**< Set lz4s dictionary mini match, which would be 3 or 4 */ } QzSessionParamsInternal_T; typedef struct QzSess_S { int inst_hint; /*which instance we last used*/ QzSessionParamsInternal_T sess_params; CpaDcSessionSetupData session_setup_data; Cpa32U session_size; Cpa32U ctx_size; CpaStatus sess_status; int submitted; int processed; int last_submitted; int last_processed; int stop_submitting; signed long seq; signed long seq_in; pthread_t c_th_i; pthread_t c_th_o; unsigned char *src; unsigned int *src_sz; unsigned int *dest_sz; unsigned char *next_dest; int force_sw; InflateState_T inflate_stat; void *strm; z_stream *inflate_strm; unsigned long qz_in_len; unsigned long qz_out_len; unsigned long *crc32; unsigned int last; unsigned int single_thread; unsigned int polling_idx; z_stream *deflate_strm; DeflateState_T deflate_stat; LZ4F_dctx *dctx; } QzSess_T; typedef struct QzStreamBuf_S { unsigned int buf_len; unsigned char *in_buf; unsigned char *out_buf; unsigned int out_offset; unsigned int in_offset; unsigned int flush_more; } QzStreamBuf_T; typedef struct ThreadData_S { pid_t ppid; pid_t pid; struct timeval timer[MAX_THREAD_TMR]; } ThreadData_T; typedef struct QzExtraHeader_S { uint32_t src_sz; uint32_t dest_sz; } QzExtraHeader_T; typedef struct QzExtraField_S { unsigned char st1; unsigned char st2; uint16_t x2_len; QzExtraHeader_T qz_e; } QzExtraField_T; typedef struct StdGzH_S { unsigned char id1; unsigned char id2; unsigned char cm; unsigned char flag; unsigned char mtime[4]; unsigned char xfl; unsigned char os; } StdGzH_T; typedef struct QzGzH_S { StdGzH_T std_hdr; uint16_t x_len; QzExtraField_T extra; } QzGzH_T; typedef struct Qz4BH_S { uint32_t blk_size; } Qz4BH_T; typedef struct StdGzF_S { uint32_t crc32; uint32_t i_size; } StdGzF_T; typedef struct QzMem_S { int flag; unsigned char *addr; int sz; int numa; } QzMem_T; #pragma pack(push, 1) /* lz4 frame header */ typedef struct QzLZ4H_S { uint32_t magic; /* LZ4 magic number */ uint8_t flag_desc; uint8_t block_desc; uint64_t cnt_size; uint8_t hdr_cksum; /* header checksum */ } QzLZ4H_T; /* lz4 frame footer */ typedef struct QzLZ4F_S { uint32_t end_mark; /* LZ4 end mark */ uint32_t cnt_cksum; /* content checksum */ } QzLZ4F_T; #pragma pack(pop) void dumpAllCounters(void); int qzSetupHW(QzSession_T *sess, int i); unsigned long qzGzipHeaderSz(void); unsigned long qz4BHeaderSz(void); unsigned long stdGzipHeaderSz(void); unsigned long stdGzipFooterSz(void); unsigned long outputHeaderSz(DataFormatInternal_T data_fmt); unsigned long outputFooterSz(DataFormatInternal_T data_fmt); void qzGzipHeaderGen(unsigned char *ptr, CpaDcRqResults *res); void qz4BHeaderGen(unsigned char *ptr, CpaDcRqResults *res); void stdGzipHeaderGen(unsigned char *ptr, CpaDcRqResults *res); int qzGzipHeaderExt(const unsigned char *const ptr, QzGzH_T *hdr); void outputHeaderGen(unsigned char *ptr, CpaDcRqResults *res, DataFormatInternal_T data_fmt); void qzGzipFooterGen(unsigned char *ptr, CpaDcRqResults *res); void outputFooterGen(QzSess_T *qz_sess, CpaDcRqResults *res, DataFormatInternal_T data_fmt); void qzGzipFooterExt(const unsigned char *const ptr, StdGzF_T *ftr); int isQATProcessable(const unsigned char *ptr, const unsigned int *const src_len, QzSess_T *const qz_sess); int qzSWCompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last); int qzSWDecompress(QzSession_T *sess, const unsigned char *src, unsigned int *uncompressed_buf_len, unsigned char *dest, unsigned int *compressed_buffer_len); int qzSWDecompressMulti(QzSession_T *sess, const unsigned char *src, unsigned int *uncompressed_buf_len, unsigned char *dest, unsigned int *compressed_buffer_len); unsigned char getSwBackup(QzSession_T *sess); #ifdef ADF_PCI_API extern CpaStatus icp_adf_get_numDevices(Cpa32U *); #endif int initStream(QzSession_T *sess, QzStream_T *strm); void *qzMemSet(void *ptr, unsigned char filler, unsigned int count); unsigned char *findStdGzipFooter(const unsigned char *src_ptr, long src_avail_len); void removeSession(int i); void cleanUpInstMem(int i); void qzMemDestory(void); void streamBufferCleanup(); //lz4 functions unsigned long qzLZ4HeaderSz(void); unsigned long qzLZ4FooterSz(void); void qzLZ4HeaderGen(unsigned char *ptr, CpaDcRqResults *res); void qzLZ4FooterGen(unsigned char *ptr, CpaDcRqResults *res); unsigned char *findLZ4Footer(const unsigned char *src_ptr, long src_avail_len); int qzVerifyLZ4FrameHeader(const unsigned char *const ptr, uint32_t len); int isQATLZ4Processable(const unsigned char *ptr, const unsigned int *const src_len, QzSess_T *const qz_sess); int isQATDeflateProcessable(const unsigned char *ptr, const unsigned int *const src_len, QzSess_T *const qz_sess); unsigned long qzLZ4SBlockHeaderSz(void); void qzLZ4SBlockHeaderGen(unsigned char *ptr, CpaDcRqResults *res); int qzSetupSessionInternal(QzSession_T *sess); int qzCheckParams(QzSessionParams_T *params); int qzCheckParamsDeflate(QzSessionParamsDeflate_T *params); int qzCheckParamsLZ4(QzSessionParamsLZ4_T *params); int qzCheckParamsLZ4S(QzSessionParamsLZ4S_T *params); void qzGetParams(QzSessionParamsInternal_T *internal_params, QzSessionParams_T *params); void qzGetParamsDeflate(QzSessionParamsInternal_T *internal_params, QzSessionParamsDeflate_T *params); void qzGetParamsLZ4(QzSessionParamsInternal_T *internal_params, QzSessionParamsLZ4_T *params); void qzGetParamsLZ4S(QzSessionParamsInternal_T *internal_params, QzSessionParamsLZ4S_T *params); void qzSetParamsLZ4S(QzSessionParamsLZ4S_T *params, QzSessionParamsInternal_T *internal_params); void qzSetParamsLZ4(QzSessionParamsLZ4_T *params, QzSessionParamsInternal_T *internal_params); void qzSetParamsDeflate(QzSessionParamsDeflate_T *params, QzSessionParamsInternal_T *internal_params); void qzSetParams(QzSessionParams_T *params, QzSessionParamsInternal_T *internal_params); /* SW Fallback for HW request offload failed or HW respond in Error status */ int compInSWFallback(int i, int j, QzSession_T *sess, unsigned char *src_ptr, unsigned int src_send_sz); int compOutSWFallback(int i, int j, QzSession_T *sess, long *dest_avail_len); int decompInSWFallback(int i, int j, QzSession_T *sess, unsigned char *src_ptr, unsigned char *dest_ptr, unsigned int *tmp_src_avail_len, unsigned int *tmp_dest_avail_len); int decompOutSWFallback(int i, int j, QzSession_T *sess, unsigned int *dest_avail_len); /* Stream pData may need reset, which is caused by driver API params limitation, when setup buffer, may feed pinned pointer or common pointer to pBuffer. */ void RestoreDestCpastreamBuffer(int i, int j); void RestoreSrcCpastreamBuffer(int i, int j); void ResetCpastreamSink(int i, int j); /* compression stream/src/dest buffer setup, and cleanup */ void compBufferSetup(int i, int j, QzSess_T *qz_sess, unsigned char *src_ptr, unsigned int src_remaining, unsigned int hw_buff_sz, unsigned int src_send_sz); void compInBufferCleanUp(int i, int j); void compOutSrcBufferCleanUp(int i, int j); void compOutErrorDestBufferCleanUp(int i, int j); void compOutValidDestBufferCleanUp(int i, int j, QzSess_T *qz_sess, unsigned int dest_receive_sz); /* docompressOut successful respond process, or error respond process */ void compOutProcessedRespond(int i, int j, QzSess_T *qz_sess); void compOutSkipErrorRespond(int i, int j, QzSess_T *qz_sess); int compOutCheckDestLen(int i, int j, QzSession_T *sess, long *dest_avail_len, long dest_receive_sz); int checkHeader(QzSess_T *qz_sess, unsigned char *src, unsigned int src_avail_len, unsigned int dest_avail_len, QzGzH_T *hdr); /* decompression stream/src/dest buffer setup, and cleanup */ void swapDataBuffer(unsigned long i, int j); void decompBufferSetup(int i, int j, QzSess_T *qz_sess, unsigned char *src_ptr, unsigned char *dest_ptr, unsigned int src_avail_len, QzGzH_T *hdr, unsigned int *tmp_src_avail_len, unsigned int *tmp_dest_avail_len); void decompInBufferCleanUp(int i, int j); void decompOutSrcBufferCleanUp(int i, int j); void decompOutErrorDestBufferCleanUp(int i, int j); void decompOutValidDestBufferCleanUp(int i, int j, QzSess_T *qz_sess, CpaDcRqResults *resl, unsigned int dest_avail_len); /* dodecompressOut successful respond process, or error respond process */ void decompOutProcessedRespond(int i, int j, QzSess_T *qz_sess); void decompOutSkipErrorRespond(int i, int j, QzSess_T *qz_sess); int decompOutCheckSum(int i, int j, QzSession_T *sess, CpaDcRqResults *resl); #endif //_QATZIPP_H QATzip-1.2.0/src/qatzip_lz4.c000066400000000000000000000164651456106226300157370ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #define XXH_NAMESPACE QATZIP_ #include "xxhash.h" #ifdef HAVE_QAT_HEADERS #include #include #else #include #include #endif #include "qatzip.h" #include "qatzip_internal.h" #include "qz_utils.h" inline unsigned long qzLZ4HeaderSz() { return QZ_LZ4_HEADER_SIZE; } inline unsigned long qzLZ4FooterSz() { return QZ_LZ4_FOOTER_SIZE; } int qzVerifyLZ4FrameHeader(const unsigned char *const ptr, uint32_t len) { QzLZ4H_T *hdr = NULL; assert(ptr != NULL); assert(len >= QZ_LZ4_HEADER_SIZE); QZ_DEBUG("qzVerifyLZ4FrameHeader\n"); hdr = (QzLZ4H_T *)ptr; //Skippable frames if ((hdr->magic & 0xFFFFFFF0U) == QZ_LZ4_MAGIC_SKIPPABLE) { /*for skippalbe frames, fallback to software decompression */ QZ_DEBUG("qzVerifyLZ4FrameHeader: skip frames, switch to software.\n"); return QZ_FORCE_SW; } //Unknown magic number if (hdr->magic != QZ_LZ4_MAGIC) { QZ_DEBUG("qzVerifyLZ4FrameHeader: unknown lz4 frame magic number %x.\n", hdr->magic); return QZ_FAIL; } //No support for unknown lz4 version if ((hdr->flag_desc >> 6 & 0x3) != QZ_LZ4_VERSION) { QZ_DEBUG("qzVerifyLZ4FrameHeader: unknown lz4 frame version number.\n"); return QZ_FAIL; } if ((hdr->flag_desc & 0x1) != QZ_LZ4_DICT_ID_FLAG || (hdr->flag_desc >> 4 & 0x1) != QZ_LZ4_BLK_CKS_FLAG || (hdr->flag_desc >> 2 & 0x1) != QZ_LZ4_CNT_CKS_FLAG || (hdr->flag_desc >> 3 & 0x1) != QZ_LZ4_CNT_SIZE_FLAG) { QZ_DEBUG("qzVerifyLZ4FrameHeader: unsupported lz4 frame header \ switch to software.\n"); return QZ_FORCE_SW; } return QZ_OK; } void qzLZ4HeaderGen(unsigned char *ptr, CpaDcRqResults *res) { QzLZ4H_T *hdr = NULL; unsigned char *hc_start = NULL; assert(ptr != NULL); assert(res != NULL); hdr = (QzLZ4H_T *)ptr; hdr->magic = QZ_LZ4_MAGIC; //flag descriptor hdr->flag_desc = (unsigned char)(((QZ_LZ4_VERSION & 0x03) << 6) + ((QZ_LZ4_BLK_INDEP & 0x01) << 5) + ((QZ_LZ4_BLK_CKS_FLAG & 0x01) << 4) + ((QZ_LZ4_CNT_SIZE_FLAG & 0x01) << 3) + ((QZ_LZ4_CNT_CKS_FLAG & 0x01) << 2) + (QZ_LZ4_DICT_ID_FLAG & 0x01)); //block descriptor hdr->block_desc = (unsigned char)((QZ_LZ4_MAX_BLK_SIZE & 0x07) << 4); //content size hdr->cnt_size = res->consumed; //header checksum hc_start = ptr + QZ_LZ4_MAGIC_SIZE; hdr->hdr_cksum = (unsigned char)((XXH32(hc_start, QZ_LZ4_FD_SIZE - 1, 0) >> 8) & 0xff); } void qzLZ4FooterGen(unsigned char *ptr, CpaDcRqResults *res) { QzLZ4F_T *footer = NULL; assert(ptr != NULL); footer = (QzLZ4F_T *)ptr; footer->end_mark = QZ_LZ4_ENDMARK; footer->cnt_cksum = res->checksum; } unsigned char *findLZ4Footer(const unsigned char *src_ptr, long src_avail_len) { const unsigned char *lz4_footer = NULL; unsigned int block_sz = 0; unsigned int frame_sz = 0; assert(src_ptr != NULL); //the src_avail_len should be equal or greater than minimum of frame size if (src_avail_len < (QZ_LZ4_HEADER_SIZE + QZ_LZ4_BLK_HEADER_SIZE + QZ_LZ4_FOOTER_SIZE)) { return NULL; } block_sz = (*(unsigned int *)(src_ptr + QZ_LZ4_HEADER_SIZE)) & 0x7fffffff; frame_sz = block_sz + QZ_LZ4_HEADER_SIZE + QZ_LZ4_BLK_HEADER_SIZE + QZ_LZ4_FOOTER_SIZE; while (src_avail_len >= frame_sz) { lz4_footer = (src_ptr + frame_sz - QZ_LZ4_FOOTER_SIZE); if (*(unsigned int *)lz4_footer == (unsigned int)0x0) { return (unsigned char *)lz4_footer; } block_sz = (*(unsigned int *)lz4_footer) & 0x7fffffff; frame_sz += block_sz + QZ_LZ4_BLK_HEADER_SIZE; } return NULL; } int isQATLZ4Processable(const unsigned char *ptr, const unsigned int *const src_len, QzSess_T *const qz_sess) { QzLZ4H_T *hdr = (QzLZ4H_T *)ptr; QzLZ4F_T *footer = NULL; if (*src_len < QZ_LZ4_HEADER_SIZE) { return 0; } //Skippable frames if ((hdr->magic & 0xFFFFFFF0U) == QZ_LZ4_MAGIC_SKIPPABLE) { /*for skippalbe frames, fallback to software decompression */ return 0; } //Unknown magic number if (hdr->magic != QZ_LZ4_MAGIC) { return 0; } //No support for unknown lz4 version if ((hdr->flag_desc >> 6 & 0x3) != QZ_LZ4_VERSION) { return 0; } if ((hdr->flag_desc & 0x1) != QZ_LZ4_DICT_ID_FLAG || (hdr->flag_desc >> 4 & 0x1) != QZ_LZ4_BLK_CKS_FLAG || (hdr->flag_desc >> 2 & 0x1) != QZ_LZ4_CNT_CKS_FLAG || (hdr->flag_desc >> 3 & 0x1) != QZ_LZ4_CNT_SIZE_FLAG) { return 0; } footer = (QzLZ4F_T *)findLZ4Footer(ptr, *src_len); if (footer == NULL || ((unsigned int)((unsigned char *)footer - ptr - QZ_LZ4_HEADER_SIZE)) > DEST_SZ( qz_sess->sess_params.hw_buff_sz)) { return 0; } return 1; } inline unsigned long qzLZ4SBlockHeaderSz(void) { return QZ_LZ4_BLK_HEADER_SIZE; } void qzLZ4SBlockHeaderGen(unsigned char *ptr, CpaDcRqResults *res) { assert(ptr != NULL); assert(res != NULL); //block header contains block size unsigned int *blk_size = (unsigned int *)(ptr); *blk_size = (unsigned int)res->produced; } QATzip-1.2.0/src/qatzip_mem.c000077500000000000000000000140401456106226300157720ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #include #include #include #include #ifdef HAVE_QAT_HEADERS #include #include #include #else #include #include #include #endif #include "qatzip.h" #include "qz_utils.h" #include "qatzip_internal.h" #include "qatzip_page_table.h" #define __STDC_WANT_LIB_EXT1__ 1 #include static QzPageTable_T g_qz_page_table = {{{0}}}; static pthread_mutex_t g_qz_table_lock = PTHREAD_MUTEX_INITIALIZER; static atomic_int g_table_init = 0; static __thread unsigned char *g_a; extern processData_T g_process; void *doUserMemset(void *const ptr, unsigned char filler, const unsigned int count) { unsigned int lim = 0; volatile unsigned char *volatile dstPtr = ptr; while (lim < count) { dstPtr[lim++] = filler; } return (void *)dstPtr; } /* * * Fills a memory zone with a given constant byte, * * returns pointer to the memory zone. * */ void *qzMemSet(void *ptr, unsigned char filler, unsigned int count) { if (ptr == NULL) { QZ_ERROR("Invalid input memory pointer!"); return NULL; } #ifdef __STDC_LIB_EXT1__ errno_t result = memset_s( ptr, sizeof(ptr), filler, count) /* Supported on C11 standard */ if (result != 0) { QZ_ERROR("memset failed by the reason of %d", result); } return ptr; #else return doUserMemset( ptr, filler, count); /* Platform-independent secure memset */ #endif /* __STDC_LIB_EXT1__ */ } int qzMemFindAddr(unsigned char *a) { int rc = 0; unsigned long al, b; al = (unsigned long)a; b = (al & PAGE_MASK); rc = (PINNED == loadAddr(&g_qz_page_table, (void *)b)) ? PINNED_MEM : COMMON_MEM; if (0 != rc) { QZ_DEBUG("Find 0x%lx in page table\n", b); } return rc; } static void qzMemUnRegAddr(unsigned char *a) { return; } static int qzMemRegAddr(unsigned char *a, size_t sz) { int rc; unsigned long al, b; if (0 != pthread_mutex_lock(&g_qz_table_lock)) { return -1; } /*addr already registered*/ if ((1 == qzMemFindAddr(a)) && (1 == qzMemFindAddr(a + sz - 1))) { pthread_mutex_unlock(&g_qz_table_lock); return 0; } al = (unsigned long)a; b = (al & PAGE_MASK); sz += (al - b); QZ_DEBUG("4 KB page is 0x%lx\n", b); QZ_DEBUG("Inserting 0x%lx size %lx to page table\n", b, sz); rc = storeMmapRange(&g_qz_page_table, (void *)b, PINNED, sz); pthread_mutex_unlock(&g_qz_table_lock); return rc; } void qzMemDestory(void) { if (0 == g_table_init) { return; } if (0 != pthread_mutex_lock(&g_qz_table_lock)) { return; } freePageTable(&g_qz_page_table); g_table_init = 0; if (0 != pthread_mutex_unlock(&g_qz_table_lock)) { return; } } void *qzMalloc(size_t sz, int numa, int pinned) { int status; QzSession_T temp_sess; qzMemSet(&temp_sess, 0, sizeof(QzSession_T)); if (0 == g_table_init) { if (0 != pthread_mutex_lock(&g_qz_table_lock)) { return NULL; } if (0 == g_table_init) { qzMemSet(&g_qz_page_table, 0, sizeof(QzPageTable_T)); g_table_init = 1; } if (0 != pthread_mutex_unlock(&g_qz_table_lock)) { return NULL; } } if (1 == pinned && QZ_NONE == g_process.qz_init_status) { status = qzInit(&temp_sess, 1); if (QZ_INIT_FAIL(status)) { QZ_ERROR("QAT init failed with error: %d\n", status); return NULL; } } g_a = qaeMemAllocNUMA(sz, numa, 64); if (NULL == g_a) { if (0 == pinned) { QZ_DEBUG("regular malloc\n"); g_a = malloc(sz); } } else { if (0 != qzMemRegAddr(g_a, sz)) { qaeMemFreeNUMA((void **)&g_a); return NULL; } } return g_a; } void qzFree(void *m) { if (NULL == m) { return; } QZ_DEBUG("\t\tfreeing 0x%lx\n", (unsigned long)m); if (1 == qzMemFindAddr(m)) { qaeMemFreeNUMA((void **)&m); qzMemUnRegAddr(m); } else { free(m); } m = NULL; } QATzip-1.2.0/src/qatzip_page_table.h000066400000000000000000000122251456106226300173040ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifndef _QATZIP_PAGE_TABLE_H #define _QATZIP_PAGE_TABLE_H #include #include #include #define PAGE_SHIFT (12) #define PAGE_SIZE (0x1000) #define PAGE_MASK (~(PAGE_SIZE - 1)) #define LEVEL_SIZE (PAGE_SIZE / sizeof(uint64_t)) #define PINNED (-1) typedef struct __attribute__((__packed__)) { uint32_t offset : 12; uint32_t idxl0 : 9; uint32_t idxl1 : 9; uint32_t idxl2 : 9; uint32_t idxl3 : 9; } QzPageEntry_T; typedef union { uint64_t addr; QzPageEntry_T pg_entry; } QzPageIndex_T; typedef struct QzPageTable_T { union { uint64_t mt; struct QzPageTable_T *pt; } next[LEVEL_SIZE]; } QzPageTable_T; static inline void *nextLevel(QzPageTable_T *volatile *ptr) { QzPageTable_T *old_ptr = *ptr; QzPageTable_T *new_ptr; if (NULL != old_ptr) return old_ptr; new_ptr = mmap(NULL, sizeof(QzPageTable_T), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if ((void *) - 1 == new_ptr) { QZ_ERROR("nextLevel: mmap error\n"); return NULL; } if (!__sync_bool_compare_and_swap(ptr, NULL, new_ptr)) munmap(new_ptr, sizeof(QzPageTable_T)); return *ptr; } static inline void freePageLevel(QzPageTable_T *const level, const size_t iter) { size_t i = 0; if (0 == iter) return; for (i = 0; i < LEVEL_SIZE; ++i) { QzPageTable_T *pt = level->next[i].pt; if (NULL != pt) { freePageLevel(pt, iter - 1); munmap(pt, sizeof(QzPageTable_T)); } } } static inline void freePageTable(QzPageTable_T *const table) { /* There are 1+3 levels in 48-bit page table for 4KB pages. */ freePageLevel(table, 3); /* Reset global root table. */ qzMemSet(table, 0, sizeof(QzPageTable_T)); } static inline int storeAddr(QzPageTable_T *level, uintptr_t virt, uint64_t type) { QzPageIndex_T id; id.addr = virt; level = nextLevel(&level->next[id.pg_entry.idxl3].pt); if (NULL == level) { return -1; } level = nextLevel(&level->next[id.pg_entry.idxl2].pt); if (NULL == level) { return -1; } level = nextLevel(&level->next[id.pg_entry.idxl1].pt); if (NULL == level) { return -1; } level->next[id.pg_entry.idxl0].mt = type; return 0; } static inline int storeMmapRange(QzPageTable_T *p_level, void *p_virt, uint64_t type, size_t p_size) { size_t offset; size_t page_size = PAGE_SIZE; const uintptr_t virt = (uintptr_t)p_virt; for (offset = 0; offset < p_size; offset += page_size) { if (0 != storeAddr(p_level, virt + offset, type)) { return -1; } } return 0; } static inline uint64_t loadAddr(QzPageTable_T *level, void *virt) { QzPageIndex_T id; id.addr = (uintptr_t)virt; level = level->next[id.pg_entry.idxl3].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl2].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl1].pt; if (NULL == level) return 0; return level->next[id.pg_entry.idxl0].mt; } #endif QATzip-1.2.0/src/qatzip_stream.c000066400000000000000000000562601456106226300165160ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifdef HAVE_QAT_HEADERS #include #include #include #include #include #else #include #include #include #include #include #endif #include #include #include #include #include #define STREAM_BUFF_LIST_SZ 8 typedef struct StreamBuffNode_S { void *buffer; size_t size; int pinned; struct StreamBuffNode_S *next; struct StreamBuffNode_S *prev; } StreamBuffNode_T; typedef struct StreamBuffNodeList_S { StreamBuffNode_T *head; StreamBuffNode_T *tail; unsigned int size; pthread_mutex_t mutex; } StreamBuffNodeList_T; StreamBuffNodeList_T g_strm_buff_list_free = { .head = NULL, .tail = NULL, .size = 0, .mutex = PTHREAD_MUTEX_INITIALIZER }; StreamBuffNodeList_T g_strm_buff_list_used = { .head = NULL, .tail = NULL, .size = 0, .mutex = PTHREAD_MUTEX_INITIALIZER }; static inline int addNodeToList(StreamBuffNode_T *node, StreamBuffNodeList_T *buff_list) { buff_list->size += 1; node->next = NULL; if (NULL == buff_list->tail) { buff_list->head = node; node->prev = NULL; } else { node->prev = buff_list->tail; buff_list->tail->next = node; } buff_list->tail = node; return SUCCESS; } static inline int removeNodeFromList(StreamBuffNode_T *node, StreamBuffNodeList_T *buff_list) { buff_list->size -= 1; if (NULL != node->prev) { node->prev->next = node->next; if (NULL != node->next) { node->next->prev = node->prev; } else { buff_list->tail = node->prev; } } else { if (NULL != node->next) { node->next->prev = NULL; buff_list->head = node->next; } else { buff_list->head = NULL; buff_list->tail = NULL; } } return SUCCESS; } void streamBufferCleanup() { StreamBuffNode_T *node; StreamBuffNode_T *next; if (unlikely(0 != pthread_mutex_lock(&g_strm_buff_list_used.mutex))) { QZ_ERROR("Failed to get Mutex Lock.\n"); return; } node = g_strm_buff_list_used.head; while (node != NULL) { next = node->next; removeNodeFromList(node, &g_strm_buff_list_used); qzFree(node->buffer); free(node); node = next; } if (unlikely(0 != pthread_mutex_unlock(&g_strm_buff_list_used.mutex))) { QZ_ERROR("Failed to release Mutex Lock.\n"); return; } if (unlikely(0 != pthread_mutex_lock(&g_strm_buff_list_free.mutex))) { QZ_ERROR("Failed to get Mutex Lock.\n"); return; } node = g_strm_buff_list_free.head; while (node != NULL) { next = node->next; removeNodeFromList(node, &g_strm_buff_list_free); qzFree(node->buffer); free(node); node = next; } if (unlikely(0 != pthread_mutex_unlock(&g_strm_buff_list_free.mutex))) { QZ_ERROR("Failed to release Mutex Lock.\n"); return; } } static void *getNodeBuffFromFreeList(size_t sz, int pinned) { pthread_mutex_lock(&g_strm_buff_list_free.mutex); pthread_mutex_lock(&g_strm_buff_list_used.mutex); void *retval = NULL; StreamBuffNode_T *node; for (node = g_strm_buff_list_free.head; node != NULL; node = node->next) { if (pinned == node->pinned && sz <= node->size) { if (!removeNodeFromList(node, &g_strm_buff_list_free)) { retval = NULL; goto done; } if (!addNodeToList(node, &g_strm_buff_list_used)) { retval = NULL; goto done; } retval = node->buffer; goto done; } } done: pthread_mutex_unlock(&g_strm_buff_list_used.mutex); pthread_mutex_unlock(&g_strm_buff_list_free.mutex); return retval; } static void allocSomeNodesForFreeList(size_t sz, int numa, int pinned) { StreamBuffNode_T *node; int i; for (i = 0; i < STREAM_BUFF_LIST_SZ; ++i) { node = malloc(sizeof(StreamBuffNode_T)); if (NULL == node) { break; } node->buffer = qzMalloc(sz, numa, pinned); if (NULL == node->buffer) { free(node); break; } node->pinned = pinned; node->size = sz; if (unlikely(0 != pthread_mutex_lock(&g_strm_buff_list_free.mutex))) { QZ_ERROR("Failed to get Mutex Lock.\n"); free(node); return; } if (!addNodeToList(node, &g_strm_buff_list_free)) { free(node); if (unlikely(0 != pthread_mutex_unlock(&g_strm_buff_list_free.mutex))) { QZ_ERROR("Failed to release Mutex Lock.\n"); return; } } if (unlikely(0 != pthread_mutex_unlock(&g_strm_buff_list_free.mutex))) { QZ_ERROR("Failed to release Mutex Lock.\n"); free(node); return; } } } static void *streamBufferAlloc(size_t sz, int numa, int pinned) { StreamBuffNode_T *node = getNodeBuffFromFreeList(sz, pinned); if (NULL == node) { //try to add some nodes to free list allocSomeNodesForFreeList(sz, numa, pinned); node = getNodeBuffFromFreeList(sz, pinned); } return node; } static void streamBufferFree(void *addr) { StreamBuffNode_T *node; pthread_mutex_lock(&g_strm_buff_list_free.mutex); pthread_mutex_lock(&g_strm_buff_list_used.mutex); for (node = g_strm_buff_list_used.head; node != NULL; node = node->next) { if (addr == node->buffer) { if (removeNodeFromList(node, &g_strm_buff_list_used) == FAILURE) { QZ_ERROR("Fail to remove Node for streamBufferFree"); goto done; } if (STREAM_BUFF_LIST_SZ <= g_strm_buff_list_free.size) { qzFree(node->buffer); free(node); } else { addNodeToList(node, &g_strm_buff_list_free); } addr = NULL; goto done; } } done: pthread_mutex_unlock(&g_strm_buff_list_used.mutex); pthread_mutex_unlock(&g_strm_buff_list_free.mutex); } int initStream(QzSession_T *sess, QzStream_T *strm) { int rc = QZ_FAIL; QzSess_T *qz_sess = NULL; QzStreamBuf_T *stream_buf = NULL; if (NULL != strm->opaque) { return QZ_DUPLICATE; } /*check if init called*/ rc = qzInit(sess, getSwBackup(sess)); if (QZ_INIT_FAIL(rc)) { return QZ_FAIL; } /*check if setupSession called*/ if (NULL == sess->internal || QZ_NONE == sess->hw_session_stat) { rc = qzSetupSessionDeflate(sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { return QZ_FAIL; } } qz_sess = (QzSess_T *)(sess->internal); qz_sess->strm = strm; strm->opaque = malloc(sizeof(QzStreamBuf_T)); stream_buf = (QzStreamBuf_T *) strm->opaque; if (NULL == stream_buf) { QZ_ERROR("Fail to allocate memory for QzStreamBuf"); return QZ_FAIL; } stream_buf->out_offset = 0; stream_buf->in_offset = 0; stream_buf->flush_more = 0; stream_buf->buf_len = qz_sess->sess_params.strm_buff_sz; stream_buf->in_buf = streamBufferAlloc(stream_buf->buf_len, NODE_0, PINNED_MEM); stream_buf->out_buf = streamBufferAlloc(stream_buf->buf_len, NODE_0, PINNED_MEM); if (NULL == stream_buf->in_buf) { QZ_DEBUG("stream_buf->in_buf : PINNED_MEM failed, try COMMON_MEM\n"); stream_buf->in_buf = streamBufferAlloc(stream_buf->buf_len, NODE_0, COMMON_MEM); } if (NULL == stream_buf->out_buf) { QZ_DEBUG("stream_buf->out_buf : PINNED_MEM failed, try COMMON_MEM\n"); stream_buf->out_buf = streamBufferAlloc(stream_buf->buf_len, NODE_0, COMMON_MEM); } if (NULL == stream_buf->in_buf || NULL == stream_buf->out_buf) { goto clear; } QZ_DEBUG("Allocate stream buf %u\n", stream_buf->buf_len); strm->pending_in = 0; strm->pending_out = 0; strm->crc_32 = 0; return QZ_OK; clear: if (NULL == stream_buf->in_buf) { QZ_ERROR("Fail to allocate memory for in_buf of QzStreamBuf"); } else { qzFree(stream_buf->in_buf); } if (NULL == stream_buf->out_buf) { QZ_ERROR("Fail to allocate memory for out_buf of QzStreamBuf"); } else { qzFree(stream_buf->out_buf); } free(stream_buf); stream_buf = NULL; strm->opaque = NULL; return QZ_FAIL; } static unsigned int copyStreamInput(QzStream_T *strm, unsigned char *in) { unsigned int cpy_cnt = 0; unsigned int avail_in = 0; QzStreamBuf_T *stream_buf = strm->opaque; avail_in = stream_buf->buf_len - strm->pending_in; cpy_cnt = (strm->in_sz > avail_in) ? avail_in : strm->in_sz; QZ_MEMCPY(stream_buf->in_buf + strm->pending_in, in, cpy_cnt, strm->in_sz); QZ_DEBUG("Copy to input from %p, to %p, count %u\n", in, stream_buf->in_buf + strm->pending_in, cpy_cnt); strm->pending_in += cpy_cnt; strm->in_sz -= cpy_cnt; return cpy_cnt; } static unsigned int copyStreamOutput(QzStream_T *strm, unsigned char *out) { unsigned int cpy_cnt = 0; unsigned int avail_out = 0; QzStreamBuf_T *stream_buf = strm->opaque; avail_out = strm->out_sz; cpy_cnt = (strm->pending_out > avail_out) ? avail_out : strm->pending_out; QZ_MEMCPY(out, stream_buf->out_buf + stream_buf->out_offset, avail_out, cpy_cnt); QZ_DEBUG("copy %u to user output\n", cpy_cnt); strm->out_sz -= cpy_cnt; strm->pending_out -= cpy_cnt; stream_buf->out_offset += cpy_cnt; if (strm->pending_out == 0) { stream_buf->out_offset = 0; } return cpy_cnt; } int qzCompressStream(QzSession_T *sess, QzStream_T *strm, unsigned int last) { int rc = QZ_FAIL; unsigned long *strm_crc = NULL; unsigned int input_len = 0; unsigned int output_len = 0; unsigned int copied_output = 0; unsigned int copied_input = 0; unsigned int copied_input_last = 0; unsigned int copy_more = 1; unsigned int inbuf_offset = 0; unsigned int consumed = 0; unsigned int produced = 0; unsigned int strm_last = 0; QzStreamBuf_T *stream_buf = NULL; QzSess_T *qz_sess = NULL; DataFormatInternal_T data_fmt = DEFLATE_GZIP_EXT; if (NULL == sess || \ NULL == strm || \ (last != 0 && last != 1)) { rc = QZ_PARAMS; if (NULL != strm) { strm->in_sz = 0; strm->out_sz = 0; } goto end; } if (NULL == strm->out) { rc = QZ_PARAMS; strm->in_sz = 0; strm->out_sz = 0; goto end; } if (NULL == strm->in && \ strm->in_sz > 0) { rc = QZ_PARAMS; strm->in_sz = 0; strm->out_sz = 0; goto end; } if (NULL == strm->opaque) { rc = initStream(sess, strm); if (QZ_OK != rc) { goto done; } } switch (strm->crc_type) { case QZ_CRC32: case QZ_ADLER: default: strm_crc = (unsigned long *)&strm->crc_32; break; } /*check if init called*/ rc = qzInit(sess, getSwBackup(sess)); if (QZ_INIT_FAIL(rc)) { return QZ_FAIL; } /*check if setupSession called*/ if (NULL == sess->internal || QZ_NONE == sess->hw_session_stat) { rc = qzSetupSessionDeflate(sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { strm->in_sz = 0; strm->out_sz = 0; return QZ_FAIL; } } qz_sess = (QzSess_T *)(sess->internal); data_fmt = qz_sess->sess_params.data_fmt; if (data_fmt != DEFLATE_RAW && data_fmt != DEFLATE_GZIP_EXT) { QZ_ERROR("Invalid data format: %d\n", data_fmt); strm->in_sz = 0; strm->out_sz = 0; return QZ_PARAMS; } stream_buf = (QzStreamBuf_T *) strm->opaque; while (strm->pending_out > 0) { copied_output = copyStreamOutput(strm, strm->out + produced); produced += copied_output; if (0 == copied_output || (0 == strm->pending_out && 0 == strm->pending_in && 0 == strm->in_sz)) { rc = QZ_OK; /* When pending_out and pending_in are all greater than zero, we * set the flush_more flag to indicate that we should not copy more * input and should do the process(compression or decompression) */ if (strm->pending_in > 0) { stream_buf->flush_more = 1; } goto done; } } while (0 == strm->pending_out) { if (copy_more == 1 && stream_buf->flush_more != 1) { copied_input_last = copied_input; // Note, strm->in == NULL and strm->in_sz == 0, will not cause // copyStreamInput failed, but it's Dangerous behavior. if (NULL != strm->in) { copied_input += copyStreamInput(strm, strm->in + consumed); } if (strm->pending_in < stream_buf->buf_len && last != 1) { rc = QZ_OK; goto done; } else { copy_more = 0; } } input_len = strm->pending_in; output_len = stream_buf->buf_len; if (stream_buf->flush_more == 1) { inbuf_offset = stream_buf->in_offset; stream_buf->flush_more = 0; } strm_last = (0 == strm->in_sz && last) ? 1 : 0; QZ_DEBUG("Before Call qzCompressCrc input_len %u output_len %u " "stream->pending_in %u stream->pending_out %u " "stream->in_sz %d stream->out_sz %d\n", input_len, output_len, strm->pending_in, strm->pending_out, strm->in_sz, strm->out_sz); rc = qzCompressCrc(sess, stream_buf->in_buf + inbuf_offset, &input_len, stream_buf->out_buf, &output_len, strm_last, strm_crc); strm->pending_in -= input_len; strm->pending_out = output_len; copied_output = copyStreamOutput(strm, strm->out + produced); consumed = copied_input; produced += copied_output; inbuf_offset += input_len; stream_buf->in_offset = inbuf_offset; QZ_DEBUG("After Call qzCompressCrc input_len %u output_len %u " "stream->pending_in %u stream->pending_out %u " "stream->in_sz %d stream->out_sz %d\n", input_len, output_len, strm->pending_in, strm->pending_out, strm->in_sz, strm->out_sz); if (QZ_BUF_ERROR == rc) { if (0 == input_len) { QZ_ERROR("ERROR in copy stream output, stream buf size = %u\n", stream_buf->buf_len); copied_input = copied_input_last; rc = QZ_FAIL; goto done; } else { rc = QZ_OK; } } if (QZ_OK != rc) { copied_input = copied_input_last; rc = QZ_FAIL; goto done; } if (0 == strm->pending_in) { copy_more = 1; inbuf_offset = 0; } if (0 == strm->pending_in && 0 == strm->in_sz) { rc = QZ_OK; goto done; } } done: strm->in_sz = copied_input; strm->out_sz = produced; QZ_DEBUG("Exit Compress Stream input_len %u output_len %u " "stream->pending_in %u stream->pending_out %u " "stream->in_sz %d stream->out_sz %d\n", input_len, output_len, strm->pending_in, strm->pending_out, strm->in_sz, strm->out_sz); end: return rc; } int qzDecompressStream(QzSession_T *sess, QzStream_T *strm, unsigned int last) { int rc = QZ_FAIL; unsigned int input_len = 0; unsigned int output_len = 0; unsigned int copied_output = 0; unsigned int copied_input = 0; unsigned int copied_input_last = 0; unsigned int consumed = 0; unsigned int produced = 0; unsigned int copy_more = 1; unsigned int inbuf_offset = 0; QzStreamBuf_T *stream_buf = NULL; if (NULL == sess || \ NULL == strm || \ (last != 0 && last != 1)) { rc = QZ_PARAMS; if (NULL != strm) { strm->in_sz = 0; strm->out_sz = 0; } goto end; } if (NULL == strm->in || \ NULL == strm->out) { rc = QZ_PARAMS; strm->in_sz = 0; strm->out_sz = 0; goto end; } if (NULL == strm->opaque) { rc = initStream(sess, strm); if (QZ_OK != rc) { goto done; } } stream_buf = (QzStreamBuf_T *) strm->opaque; QZ_DEBUG("Decompress Stream Start...\n"); while (strm->pending_out > 0) { copied_output = copyStreamOutput(strm, strm->out + produced); produced += copied_output; if (0 == copied_output) { rc = QZ_OK; if (strm->pending_in > 0) { /* We need to handle all the input that has left pending in the input buffer next time we are called. * Otherwise we'd append additional bits to the pending data, violate the buffer's boundary and * corrupt the memory behind the boundary. */ stream_buf->flush_more = 1; } QZ_DEBUG("No space for pending output...\n"); goto done; } QZ_DEBUG("Copy output %u bytes\n", copied_output); } while (0 == strm->pending_out) { if (1 == copy_more && stream_buf->flush_more != 1) { copied_input_last = copied_input; copied_input += copyStreamInput(strm, strm->in + consumed); if (strm->pending_in < stream_buf->buf_len && last != 1) { rc = QZ_OK; QZ_DEBUG("Batch more input data...\n"); goto done; } else { copy_more = 0; } } if (stream_buf->flush_more == 1) { /* We need to flush all the input that has left pending in the input buffer since the previous call to this function. * Otherwise we'd append additional bits to the pending data, violate the buffer's boundary and * corrupt the memory behind the boundary. */ stream_buf->flush_more = 0; inbuf_offset = stream_buf->in_offset; } input_len = strm->pending_in; output_len = stream_buf->buf_len; QZ_DEBUG("Before Call qzDecompress input_len %u output_len %u " "stream->pending_in %u stream->pending_out %u " "stream->in_sz %d stream->out_sz %d\n", input_len, output_len, strm->pending_in, strm->pending_out, strm->in_sz, strm->out_sz); rc = qzDecompress(sess, stream_buf->in_buf + inbuf_offset, &input_len, stream_buf->out_buf, &output_len); QZ_DEBUG("Return code = %d\n", rc); if (QZ_OK != rc && QZ_BUF_ERROR != rc) { copied_input = copied_input_last; goto done; } inbuf_offset += input_len; stream_buf->in_offset = inbuf_offset; consumed = copied_input; strm->pending_in -= input_len; strm->pending_out = output_len; copied_output = copyStreamOutput(strm, strm->out + produced); produced += copied_output; QZ_DEBUG("Copy output %u bytes\n", copied_output); QZ_DEBUG("After Call qzDecompress input_len %u output_len %u " "stream->pending_in %u stream->pending_out %u " "stream->in_sz %d stream->out_sz %d\n", input_len, output_len, strm->pending_in, strm->pending_out, strm->in_sz, strm->out_sz); if (QZ_BUF_ERROR == rc) { if (0 == input_len) { QZ_ERROR("Error in qzDecompressStream, stream buf size = %u\n", stream_buf->buf_len); copied_input = copied_input_last; rc = QZ_FAIL; goto done; } else { QZ_DEBUG("Recoverable buffer error occurs... \n"); rc = QZ_OK; } } if (0 == strm->pending_in) { copy_more = 1; inbuf_offset = 0; } if (0 == strm->pending_in && 0 == strm->in_sz) { rc = QZ_OK; goto done; } } done: strm->in_sz = copied_input; strm->out_sz = produced; QZ_DEBUG("Exit Decompress Stream input_len %u output_len %u " "stream->pending_in %u stream->pending_out %u " "stream->in_sz %d stream->out_sz %d\n", input_len, output_len, strm->pending_in, strm->pending_out, strm->in_sz, strm->out_sz); end: return rc; } int qzEndStream(QzSession_T *sess, QzStream_T *strm) { int rc = QZ_FAIL; QzStreamBuf_T *stream_buf = NULL; if (NULL == sess || \ NULL == strm) { rc = QZ_PARAMS; goto exit; } if (NULL == strm->opaque) { rc = QZ_OK; goto done; } stream_buf = (QzStreamBuf_T *)strm->opaque; streamBufferFree(stream_buf->out_buf); streamBufferFree(stream_buf->in_buf); free(stream_buf); strm->opaque = NULL; rc = QZ_OK; done: strm->pending_in = 0; strm->pending_out = 0; strm->in_sz = 0; strm->out_sz = 0; exit: return rc; } QATzip-1.2.0/src/qatzip_sw.c000077500000000000000000000700331456106226300156510ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_QAT_HEADERS #include #include #else #include #include #endif #include "qatzip.h" #include "qatzip_internal.h" #include "qz_utils.h" #define GZIP_WRAPPER 16 extern processData_T g_process; static const QzExtraField_T g_extra_field = { .st1 = 'Q', .st2 = 'Z', .x2_len = (uint16_t)sizeof(g_extra_field.qz_e), .qz_e.src_sz = 0, .qz_e.dest_sz = 0, }; static void gen_qatzip_hdr(gz_header *hdr) { qzMemSet(hdr, 0, sizeof(gz_header)); hdr->extra = (Bytef *)&g_extra_field; hdr->extra_len = (uInt)sizeof(g_extra_field); hdr->os = 255; } int qzDeflateSWCompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last) { int ret; z_stream *stream = NULL; int flush_flag; int last_loop_in; int last_loop_out; int current_loop_in; int current_loop_out; gz_header hdr; unsigned int left_input_sz = *src_len; unsigned int left_output_sz = *dest_len; unsigned int send_sz; unsigned int total_in = 0, total_out = 0; QzSess_T *qz_sess = NULL; int windows_bits = 0; int comp_level = Z_DEFAULT_COMPRESSION; DataFormatInternal_T data_fmt = DATA_FORMAT_DEFAULT; unsigned int chunk_sz = QZ_HW_BUFF_SZ; QzGzH_T *qz_hdr = NULL; Qz4BH_T *qz4B_header = NULL; *src_len = 0; *dest_len = 0; assert(sess); assert(sess->internal); qz_sess = (QzSess_T *) sess->internal; qz_sess->force_sw = 1; comp_level = qz_sess->sess_params.comp_lvl; data_fmt = qz_sess->sess_params.data_fmt; chunk_sz = qz_sess->sess_params.hw_buff_sz; stream = qz_sess->deflate_strm; if (DeflateNull == qz_sess->deflate_stat) { if (NULL == stream) { stream = calloc(1, sizeof(z_stream)); if (NULL == stream) { return QZ_FAIL; } qz_sess->deflate_strm = stream; } stream->zalloc = (alloc_func)0; stream->zfree = (free_func)0; stream->opaque = (voidpf)0; stream->total_in = 0; stream->total_out = 0; switch (data_fmt) { case DEFLATE_4B: case DEFLATE_RAW: windows_bits = -MAX_WBITS; break; case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: default: windows_bits = MAX_WBITS + GZIP_WRAPPER; break; } /*Gzip header*/ if (Z_OK != deflateInit2(stream, comp_level, Z_DEFLATED, windows_bits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) { qz_sess->deflate_stat = DeflateNull; return QZ_FAIL; } qz_sess->deflate_stat = DeflateInited; if (DEFLATE_GZIP_EXT == data_fmt) { gen_qatzip_hdr(&hdr); if (Z_OK != deflateSetHeader(stream, &hdr)) { qz_sess->deflate_stat = DeflateNull; stream->total_in = 0; stream->total_out = 0; return QZ_FAIL; } qz_hdr = (QzGzH_T *)dest; } else if (DEFLATE_4B == data_fmt) { /* Need to reserve 4 bytes to fill the compressed length. */ qz4B_header = (Qz4BH_T *)dest; dest = dest + sizeof(Qz4BH_T); } } #ifdef QATZIP_DEBUG insertThread((unsigned int)pthread_self(), COMPRESSION, SW); #endif do { send_sz = left_input_sz > chunk_sz ? chunk_sz : left_input_sz; left_input_sz -= send_sz; if (0 == left_input_sz && 1 == last) { flush_flag = Z_FINISH; } else { flush_flag = Z_FULL_FLUSH; } stream->next_in = (z_const Bytef *)src + total_in; stream->avail_in = send_sz; stream->next_out = (Bytef *)dest + total_out; stream->avail_out = left_output_sz; last_loop_in = GET_LOWER_32BITS(stream->total_in); last_loop_out = GET_LOWER_32BITS(stream->total_out); ret = deflate(stream, flush_flag); if ((Z_STREAM_END != ret && Z_FINISH == flush_flag) || (Z_OK != ret && Z_FULL_FLUSH == flush_flag)) { QZ_ERROR("ERR: deflate failed with return code: %d flush_flag: %d\n", ret, flush_flag); stream->total_in = 0; stream->total_out = 0; qz_sess->deflate_stat = DeflateNull; return QZ_FAIL; } current_loop_in = GET_LOWER_32BITS(stream->total_in) - last_loop_in; current_loop_out = GET_LOWER_32BITS(stream->total_out) - last_loop_out; left_output_sz -= current_loop_out; total_out += current_loop_out; total_in += current_loop_in; *src_len = total_in; *dest_len = total_out; if (NULL != qz_sess->crc32) { if (DEFLATE_RAW == data_fmt) { *qz_sess->crc32 = crc32(*qz_sess->crc32, src + total_in - current_loop_in, current_loop_in); } else { if (0 == *qz_sess->crc32) { *qz_sess->crc32 = stream->adler; } else { *qz_sess->crc32 = crc32_combine(*qz_sess->crc32, stream->adler, *src_len); } } } } while (left_input_sz); if (1 == last) { /* * When data_fmt is DEFLATE_GZIP_EXT, * we should fill src_sz & dest_sz in gzipext header field. */ if (DEFLATE_GZIP_EXT == data_fmt && qz_hdr) { qz_hdr->extra.qz_e.src_sz = stream->total_in; qz_hdr->extra.qz_e.dest_sz = stream->total_out - outputHeaderSz(data_fmt) - outputFooterSz(data_fmt); } else if (DEFLATE_4B == data_fmt && qz4B_header) { qz4B_header->blk_size = stream->total_out; *dest_len = *dest_len + sizeof(Qz4BH_T); } ret = deflateEnd(stream); stream->total_in = 0; stream->total_out = 0; qz_sess->deflate_stat = DeflateNull; if (Z_OK != ret) { return QZ_FAIL; } } return QZ_OK; } int qzDeflateSWDecompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len) { z_stream *stream = NULL; int ret = QZ_OK; int zlib_ret = Z_OK; DataFormatInternal_T data_fmt; int windows_bits = 0; unsigned int total_in; unsigned int total_out; unsigned int qz4B_header_len = 0; QzSess_T *qz_sess = (QzSess_T *) sess->internal; qz_sess->force_sw = 1; stream = qz_sess->inflate_strm; data_fmt = qz_sess->sess_params.data_fmt; if (NULL == stream) { stream = calloc(1, sizeof(z_stream)); if (NULL == stream) { *src_len = 0; *dest_len = 0; return QZ_FAIL; } stream->zalloc = (alloc_func)0; stream->zfree = (free_func)0; stream->opaque = (voidpf)0; stream->total_in = 0; stream->total_out = 0; qz_sess->inflate_strm = stream; } stream->next_in = (z_const Bytef *)src; stream->avail_in = *src_len; stream->next_out = (Bytef *)dest; stream->avail_out = *dest_len; *src_len = 0; *dest_len = 0; QZ_DEBUG("decomp_sw data_fmt: %d\n", data_fmt); switch (data_fmt) { case DEFLATE_4B: case DEFLATE_RAW: windows_bits = -MAX_WBITS; break; case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: default: windows_bits = MAX_WBITS + GZIP_WRAPPER; break; } if (InflateNull == qz_sess->inflate_stat) { if (DEFLATE_4B == data_fmt) { /* For DEFLATE_4B, we need to skip the header. */ stream->next_in = (z_const Bytef *)stream->next_in + sizeof(Qz4BH_T); stream->avail_in = stream->avail_in - sizeof(Qz4BH_T); qz4B_header_len = sizeof(Qz4BH_T); } ret = inflateInit2(stream, windows_bits); if (Z_OK != ret) { ret = QZ_FAIL; goto done; } QZ_DEBUG("\n****** inflate init done with win_bits: %d *****\n", windows_bits); qz_sess->inflate_stat = InflateInited; stream->total_in = 0; total_in = 0; stream->total_out = 0; total_out = 0; } else { total_in = GET_LOWER_32BITS(stream->total_in); total_out = GET_LOWER_32BITS(stream->total_out); } zlib_ret = inflate(stream, Z_SYNC_FLUSH); switch (zlib_ret) { case Z_OK: if (QZ_LOW_DEST_MEM == sess->thd_sess_stat) { QZ_DEBUG("ERR: inflate failed with Z_DATA_ERROR\n"); ret = QZ_DATA_ERROR; qz_sess->inflate_stat = InflateError; goto done; } ret = QZ_OK; qz_sess->inflate_stat = InflateOK; break; case Z_STREAM_END: ret = QZ_OK; qz_sess->inflate_stat = InflateEnd; break; case Z_DATA_ERROR: QZ_DEBUG("ERR: inflate failed with Z_DATA_ERROR\n"); ret = QZ_DATA_ERROR; qz_sess->inflate_stat = InflateError; goto done; default: QZ_DEBUG("ERR: inflate failed with error code %d\n", ret); ret = QZ_FAIL; qz_sess->inflate_stat = InflateError; goto done; } *dest_len = GET_LOWER_32BITS(stream->total_out - total_out); /* for Deflate_4B, we need to add the length of Deflate 4B header. */ *src_len = GET_LOWER_32BITS(stream->total_in - total_in + qz4B_header_len); done: QZ_DEBUG("Exit qzSWDecompress total_in: %lu total_out: %lu " "avail_in: %u avail_out: %u msg: %s " "src_len: %u dest_len: %u\n", stream->total_in, stream->total_out, stream->avail_in, stream->avail_out, stream->msg, *src_len, *dest_len); if (zlib_ret == Z_STREAM_END || QZ_LOW_DEST_MEM == sess->thd_sess_stat) { if (Z_OK != inflateEnd(stream)) { QZ_DEBUG("inflateEnd failed.\n"); ret = QZ_FAIL; } qz_sess->inflate_stat = InflateNull; QZ_DEBUG("\n****** inflate end done *****\n"); } return ret; } int qzSWDecompressMultiGzip(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len) { int ret = QZ_OK; unsigned int total_in = 0; unsigned int total_out = 0; const unsigned int input_len = *src_len; const unsigned int output_len = *dest_len; unsigned int cur_input_len = input_len; unsigned int cur_output_len = output_len; #ifdef QATZIP_DEBUG insertThread((unsigned int)pthread_self(), DECOMPRESSION, SW); #endif QZ_DEBUG("Start qzSWDecompressMultiGzip: src_len %u dest_len %u\n", *src_len, *dest_len); *src_len = 0; *dest_len = 0; while (total_in < input_len && total_out < output_len) { ret = qzDeflateSWDecompress(sess, src + total_in, &cur_input_len, dest + total_out, &cur_output_len); if (ret != QZ_OK) { goto out; } total_in += cur_input_len; total_out += cur_output_len; cur_input_len = input_len - total_in; cur_output_len = output_len - total_out; *src_len = total_in; *dest_len = total_out; } out: QZ_DEBUG("Exit qzSWDecompressMultiGzip: src_len %u dest_len %u\n", *src_len, *dest_len); return ret; } int qzLZ4SWCompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last) { size_t total_out = 0; assert(sess); assert(sess->internal); QzSess_T *qz_sess = (QzSess_T *)sess->internal; LZ4F_preferences_t preferences = {0}; preferences.frameInfo.contentChecksumFlag = 1; preferences.frameInfo.contentSize = *src_len; preferences.autoFlush = 1; preferences.compressionLevel = qz_sess->sess_params.comp_lvl; total_out = LZ4F_compressFrame(dest, *dest_len, src, *src_len, &preferences); if (LZ4F_isError(total_out)) { QZ_ERROR("LZ4F_compressUpdate error: %s\n", LZ4F_getErrorName(total_out)); goto lz4_compress_fail; } *dest_len = total_out; QZ_DEBUG("Exit qzLZ4SWCompress: src_len %u dest_len %u\n", *src_len, *dest_len); return QZ_OK; lz4_compress_fail: *src_len = 0; *dest_len = 0; return QZ_FAIL; } int qzLZ4SWDecompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len) { size_t in_sz = 0; size_t out_sz = 0; size_t ret = QZ_OK; QzSess_T *qz_sess = NULL; QZ_DEBUG("Enter qzLZ4SWDecompress: src_len %u dest_len %u\n", *src_len, *dest_len); qz_sess = (QzSess_T *) sess->internal; if (qz_sess->dctx == NULL) { ret = LZ4F_createDecompressionContext(&(qz_sess->dctx), LZ4F_VERSION); if (LZ4F_isError(ret)) { QZ_ERROR("LZ4F_createDecompressionContext error: %s\n", LZ4F_getErrorName(ret)); goto lz4_decompress_fail; } } in_sz = *src_len; out_sz = *dest_len; ret = LZ4F_decompress(qz_sess->dctx, dest, (size_t *)&out_sz, src, (size_t *)&in_sz, NULL); if (LZ4F_isError(ret)) { QZ_ERROR("LZ4F_decompress error: %s\n", LZ4F_getErrorName(ret)); goto lz4_decompress_fail; } else if (ret == 0) { /* * when ret == 0, it means that a frame be fully decompressed, * we need to free the dctx, not reuse it to decompress another frame. */ LZ4F_freeDecompressionContext(qz_sess->dctx); qz_sess->dctx = NULL; } else { /* * when ret > 0, it means that the compressed data is not a fully frame, * it needs more compressed data to decompress. The remaining compressed data * was stored in dctx. */ QZ_DEBUG("LZ4F_decompress: incomplete compressed data, need more data\n"); } *src_len = in_sz; *dest_len = out_sz; QZ_DEBUG("Exit qzLZ4SWDecompress: src_len %u dest_len %u\n", *src_len, *dest_len); return QZ_OK; lz4_decompress_fail: if (qz_sess->dctx != NULL) { LZ4F_freeDecompressionContext(qz_sess->dctx); qz_sess->dctx = NULL; } *src_len = 0; *dest_len = 0; return QZ_FAIL; } int qzSWDecompressMultiLZ4(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len) { int ret = QZ_OK; unsigned int total_in = 0; unsigned int total_out = 0; const unsigned int input_len = *src_len; const unsigned int output_len = *dest_len; unsigned int cur_input_len = input_len; unsigned int cur_output_len = output_len; #ifdef QATZIP_DEBUG insertThread((unsigned int)pthread_self(), DECOMPRESSION, SW); #endif QZ_DEBUG("Start qzSWDecompressMultiLz4: src_len %u dest_len %u\n", *src_len, *dest_len); *src_len = 0; *dest_len = 0; while (total_in < input_len && total_out < output_len) { ret = qzLZ4SWDecompress(sess, src + total_in, &cur_input_len, dest + total_out, &cur_output_len); if (ret != QZ_OK) { goto out; } total_in += cur_input_len; total_out += cur_output_len; cur_input_len = input_len - total_in; cur_output_len = output_len - total_out; *src_len = total_in; *dest_len = total_out; } out: QZ_DEBUG("Exit qzSWDecompressMultiLz4: src_len %u dest_len %u\n", *src_len, *dest_len); return ret; } /* The software failover function for compression request */ int qzSWCompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, unsigned int last) { #ifdef ENABLE_TESTLOG QZ_TESTLOG(2, 0, "SW_FALLBACK", "sw fallback happend!"); #endif int ret = QZ_FAIL; DataFormatInternal_T data_fmt; QzSess_T *qz_sess = NULL; assert(sess); assert(sess->internal); qz_sess = (QzSess_T *) sess->internal; data_fmt = qz_sess->sess_params.data_fmt; switch (data_fmt) { case DEFLATE_RAW: case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: case DEFLATE_4B: ret = qzDeflateSWCompress(sess, src, src_len, dest, dest_len, last); break; case LZ4_FH: ret = qzLZ4SWCompress(sess, src, src_len, dest, dest_len, last); break; default: QZ_ERROR("Unknown/unsupported data format: %d\n", data_fmt); *src_len = 0; *dest_len = 0; ret = QZ_FAIL; break; } return ret; } /* The software failover function for decompression request */ int qzSWDecompress(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len) { #ifdef ENABLE_TESTLOG QZ_TESTLOG(2, 0, "SW_FALLBACK", "sw fallback happend!"); #endif int ret = QZ_FAIL; DataFormatInternal_T data_fmt; QzSess_T *qz_sess = NULL; assert(sess); assert(sess->internal); qz_sess = (QzSess_T *) sess->internal; data_fmt = qz_sess->sess_params.data_fmt; switch (data_fmt) { case DEFLATE_RAW: case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: case DEFLATE_4B: ret = qzDeflateSWDecompress(sess, src, src_len, dest, dest_len); break; case LZ4_FH: ret = qzLZ4SWDecompress(sess, src, src_len, dest, dest_len); break; default: QZ_ERROR("Unknown/unsupported data format: %d\n", data_fmt); *src_len = 0; *dest_len = 0; ret = QZ_FAIL; break; } return ret; } int qzSWDecompressMulti(QzSession_T *sess, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len) { #ifdef ENABLE_TESTLOG QZ_TESTLOG(2, 0, "SW_FALLBACK", "sw fallback happend!"); #endif int ret = QZ_FAIL; DataFormatInternal_T data_fmt; QzSess_T *qz_sess = NULL; assert(sess); assert(sess->internal); qz_sess = (QzSess_T *) sess->internal; data_fmt = qz_sess->sess_params.data_fmt; switch (data_fmt) { case DEFLATE_RAW: case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: case DEFLATE_4B: ret = qzSWDecompressMultiGzip(sess, src, src_len, dest, dest_len); break; case LZ4_FH: ret = qzSWDecompressMultiLZ4(sess, src, src_len, dest, dest_len); break; default: QZ_ERROR("Unknown/unsupported data format: %d\n", data_fmt); *src_len = 0; *dest_len = 0; ret = QZ_FAIL; break; } return ret; } int compInSWFallback(int i, int j, QzSession_T *sess, unsigned char *src_ptr, unsigned int src_send_sz) { int rc; unsigned int dest_receive_sz = DEST_SZ(src_send_sz); QzSess_T *qz_sess = (QzSess_T *)sess->internal; if (!qz_sess->sess_params.sw_backup) { QZ_DEBUG("The instance %d heartbeat is failure, Don't enable sw fallback, compressIn fatal ERROR!\n", i); return QZ_FAIL; } if (qz_sess->single_thread) { QZ_DEBUG("The instance %d failure, single_thread, compressIn fatal ERROR!\n", i); return QZ_FAIL; } if (qz_sess->stop_submitting) { QZ_DEBUG("compInSWFallback stop submit\n"); return QZ_FAIL; } if (qz_sess->seq != qz_sess->seq_in) { return QZ_WAIT_SW_PENDING; } QZ_DEBUG("SW CompIn Sending %u bytes, seq = %ld, instance = %d\n", src_send_sz, qz_sess->seq, i); /* sw fallback here */ rc = qzSWCompress(sess, src_ptr, &src_send_sz, qz_sess->next_dest, &dest_receive_sz, qz_sess->last); QZ_DEBUG("SW CompIn src_ptr %p, dst_ptr %p, Sending %u bytes, seq = %ld\n", src_ptr, qz_sess->next_dest, src_send_sz, qz_sess->seq); if (unlikely(QZ_OK != rc)) { QZ_ERROR("SW CompIn fallback failure! compress fatal ERROR!\n"); return QZ_FAIL; } /* For SW compress, have to update ComputeOut status first */ qz_sess->next_dest += dest_receive_sz; qz_sess->qz_in_len += src_send_sz; qz_sess->qz_out_len += dest_receive_sz; qz_sess->seq_in++; qz_sess->processed++; return QZ_OK; } int compOutSWFallback(int i, int j, QzSession_T *sess, long *dest_avail_len) { int rc; QzSess_T *qz_sess = (QzSess_T *)sess->internal; unsigned int src_send_sz = g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes; /* sw dest buffer is align with the inst hw buffer size */ unsigned int dest_receive_sz = outputHeaderSz(qz_sess->sess_params.data_fmt) + g_process.qz_inst[i].dest_buffers[j]->pBuffers->dataLenInBytes; unsigned char *src_ptr = g_process.qz_inst[i].src_buffers[j]->pBuffers->pData; unsigned char *dest_ptr = g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData; if (!qz_sess->sess_params.sw_backup) { QZ_DEBUG("The instance %d heartbeat is failure, Don't enable sw fallback, compressOut fatal ERROR!\n", i); return QZ_FAIL; } QZ_DEBUG("The request get dummy emty respond, offload to software!\n"); QZ_DEBUG("SW CompOut src_ptr %p, dst_ptr %p, Sending %u bytes, seq = %ld\n", src_ptr, dest_ptr, src_send_sz, g_process.qz_inst[i].stream[j].seq); rc = qzSWCompress(sess, src_ptr, &src_send_sz, dest_ptr, &dest_receive_sz, qz_sess->last); if (QZ_OK != rc) { QZ_ERROR("SW CompOut fallback failure! compress fatal ERROR!\n"); return QZ_FAIL; } rc = compOutCheckDestLen(i, j, sess, dest_avail_len, dest_receive_sz); if (QZ_OK != rc) { return rc; } /* Update qz_sess info and clean dest buffer */ compOutValidDestBufferCleanUp(i, j, qz_sess, dest_receive_sz); qz_sess->next_dest += dest_receive_sz; qz_sess->qz_in_len += src_send_sz; qz_sess->qz_out_len += dest_receive_sz; return rc; } int decompInSWFallback(int i, int j, QzSession_T *sess, unsigned char *src_ptr, unsigned char *dest_ptr, unsigned int *tmp_src_avail_len, unsigned int *tmp_dest_avail_len) { int rc; QzSess_T *qz_sess = (QzSess_T *)sess->internal; if (!qz_sess->sess_params.sw_backup) { QZ_DEBUG("The instance %d heartbeat is failure, Don't enable sw fallback, decompressIn fatal ERROR!\n", i); sess->thd_sess_stat = QZ_FAIL; return QZ_FAIL; } if (qz_sess->single_thread) { QZ_DEBUG("The instance %d failure, single thread, decompressIn fatal ERROR!\n", i); sess->thd_sess_stat = QZ_FAIL; return QZ_FAIL; } if (qz_sess->stop_submitting) { QZ_DEBUG("decompInSWFallback stop submit\n"); return QZ_FAIL; } if (qz_sess->seq != qz_sess->seq_in) { return QZ_WAIT_SW_PENDING; } QZ_DEBUG("SW DecompIn src_ptr %p, dest_ptr %p, Sending %u bytes, seq = %ld, instance = %d\n", src_ptr, dest_ptr, tmp_src_avail_len, qz_sess->seq, i); rc = qzSWDecompress(sess, src_ptr, tmp_src_avail_len, dest_ptr, tmp_dest_avail_len); if (unlikely(QZ_OK != rc)) { QZ_ERROR("SW deCompIn fallback failure! decompress fatal ERROR!\n"); sess->thd_sess_stat = QZ_FAIL; return QZ_FAIL; } /* For compressIn fallback, need to update seq_in first */ qz_sess->seq_in++; qz_sess->processed++; qz_sess->qz_in_len += *tmp_src_avail_len; qz_sess->qz_out_len += *tmp_dest_avail_len; qz_sess->next_dest += *tmp_dest_avail_len; return QZ_OK; } int decompOutSWFallback(int i, int j, QzSession_T *sess, unsigned int *dest_avail_len) { int rc; QzSess_T *qz_sess = (QzSess_T *)sess->internal; DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; unsigned int src_send_sz = g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes; unsigned int dest_receive_sz = g_process.qz_inst[i].dest_buffers[j]->pBuffers->dataLenInBytes; /* pinned buffer ptr already strip header, need retrieve. * use original src_ptr and consumed len to get src_ptr for this request. */ unsigned char *src_ptr = qz_sess->src + qz_sess->qz_in_len; src_send_sz += (outputHeaderSz(data_fmt) + outputFooterSz(data_fmt)) ; if (!qz_sess->sess_params.sw_backup) { QZ_DEBUG("The instance %d heartbeat is failure, Don't enable sw fallback, decompressOut fatal ERROR!\n", i); return QZ_FAIL; } QZ_DEBUG("The request get dummy empty respond, offload to software!\n"); QZ_DEBUG("SW DecompOut src_ptr %p, dest_ptr %p, Sending %u bytes, receive %u bytes, seq = %ld\n", src_ptr, qz_sess->next_dest, src_send_sz, dest_receive_sz, g_process.qz_inst[i].stream[j].seq); rc = qzSWDecompress(sess, src_ptr, &src_send_sz, qz_sess->next_dest, &dest_receive_sz); if (QZ_OK != rc) { QZ_ERROR("SW deCompOut fallback failure! compress fatal ERROR!\n"); return QZ_FAIL; } /* update qz_sess info, Don't need clean dest buffer */ decompOutErrorDestBufferCleanUp(i, j); qz_sess->next_dest += dest_receive_sz; qz_sess->qz_in_len += src_send_sz; qz_sess->qz_out_len += dest_receive_sz; *dest_avail_len -= dest_receive_sz; return QZ_OK; }QATzip-1.2.0/src/qatzip_utils.c000066400000000000000000001204161456106226300163560ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #include #include #ifdef HAVE_QAT_HEADERS #include #include #else #include #include #endif #include #include "qatzip_internal.h" static QatThread_T g_qat_thread; extern processData_T g_process; #ifdef QATZIP_DEBUG static void doInsertThread(unsigned int th_id, ThreadList_T **thd_list, unsigned int *num_thd, pthread_mutex_t *lock, Serv_T serv_type, Engine_T engine_type) { ThreadList_T *node; ThreadList_T *prev_node; if (0 != pthread_mutex_lock(lock)) { return; } for (prev_node = node = *thd_list; node; node = node->next) { if (node->thread_id == th_id) { break; } prev_node = node; } if (!node) { node = (ThreadList_T *)calloc(1, sizeof(*node)); if (!node) { QZ_ERROR("[ERROR]: alloc memory failed in file(%s) line(%d)\n", __FILE__, __LINE__); goto done; } node->thread_id = th_id; ++*num_thd; if (prev_node) { prev_node->next = node; } else { *thd_list = node; } } if (SW == engine_type) { if (COMPRESSION == serv_type) { ++node->comp_sw_count; } else if (DECOMPRESSION == serv_type) { ++node->decomp_sw_count; } } else if (HW == engine_type) { if (COMPRESSION == serv_type) { ++node->comp_hw_count; } else if (DECOMPRESSION == serv_type) { ++node->decomp_hw_count; } } done: (void)pthread_mutex_unlock(lock); } void insertThread(unsigned int th_id, Serv_T serv_type, Engine_T engine_type) { QatThread_T *th_list = &g_qat_thread; if (COMPRESSION == serv_type) { doInsertThread(th_id, &th_list->comp_th_list, &th_list->num_comp_th, &th_list->comp_lock, serv_type, engine_type); } else if (DECOMPRESSION == serv_type) { doInsertThread(th_id, &th_list->decomp_th_list, &th_list->num_decomp_th, &th_list->decomp_lock, serv_type, engine_type); } } static void doDumpThreadInfo(ThreadList_T *node, unsigned int num_node, Serv_T type) { unsigned int i; char *serv_title; if (num_node > 0) { i = 0; if (COMPRESSION == type) { serv_title = "Compression"; } else { serv_title = "Decompression"; } QZ_PRINT("[INFO]: %s num_th %u\n", serv_title, num_node); while (node) { QZ_PRINT("th_id: %u comp_hw_count: %u comp_sw_count: %u " "decomp_hw_count: %u decomp_sw_count: %u\n", node->thread_id, node->comp_hw_count, node->comp_sw_count, node->decomp_hw_count, node->decomp_sw_count); i++; node = node->next; if (i == num_node) { break; } } if (node) { QZ_ERROR("[ERROR]: there's node left in the list\n"); } QZ_PRINT("\n"); } } void dumpThreadInfo(void) { QatThread_T *th_list = &g_qat_thread; doDumpThreadInfo(th_list->comp_th_list, th_list->num_comp_th, COMPRESSION); doDumpThreadInfo(th_list->decomp_th_list, th_list->num_decomp_th, DECOMPRESSION); } #endif void initDebugLock(void) { pthread_mutex_init(&g_qat_thread.comp_lock, NULL); pthread_mutex_init(&g_qat_thread.decomp_lock, NULL); } static int qzSetupDcSessionData(CpaDcSessionSetupData *session_setup_data, QzSessionParamsInternal_T *params) { assert(session_setup_data); assert(params); session_setup_data->compLevel = params->comp_lvl; switch (params->data_fmt) { case DEFLATE_4B: case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: case DEFLATE_RAW: session_setup_data->compType = CPA_DC_DEFLATE; session_setup_data->checksum = CPA_DC_CRC32; session_setup_data->autoSelectBestHuffmanTree = CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS; if (params->huffman_hdr == QZ_DYNAMIC_HDR) { session_setup_data->huffType = CPA_DC_HT_FULL_DYNAMIC; } else { session_setup_data->huffType = CPA_DC_HT_STATIC; } break; case LZ4_FH: #if CPA_DC_API_VERSION_AT_LEAST(3, 1) session_setup_data->compType = CPA_DC_LZ4; session_setup_data->checksum = CPA_DC_XXHASH32; session_setup_data->lz4BlockChecksum = 0; session_setup_data->lz4BlockMaxSize = CPA_DC_LZ4_MAX_BLOCK_SIZE_64K; break; #else QZ_ERROR("QAT driver does not support lz4 algorithm\n"); return QZ_UNSUPPORTED_FMT; #endif case LZ4S_BK: #if CPA_DC_API_VERSION_AT_LEAST(3, 1) session_setup_data->compType = CPA_DC_LZ4S; session_setup_data->checksum = CPA_DC_XXHASH32; if (params->lz4s_mini_match == 4) { session_setup_data->minMatch = CPA_DC_MIN_4_BYTE_MATCH; } else { session_setup_data->minMatch = CPA_DC_MIN_3_BYTE_MATCH; } break; #else QZ_ERROR("QAT driver does not support lz4s algorithm\n"); return QZ_UNSUPPORTED_FMT; #endif default: return QZ_UNSUPPORTED_FMT; } switch (params->direction) { case QZ_DIR_COMPRESS: session_setup_data->sessDirection = CPA_DC_DIR_COMPRESS; break; case QZ_DIR_DECOMPRESS: session_setup_data->sessDirection = CPA_DC_DIR_DECOMPRESS; break; default: session_setup_data->sessDirection = CPA_DC_DIR_COMBINED; } session_setup_data->sessState = CPA_DC_STATELESS; #if CPA_DC_API_VERSION_AT_LEAST(3, 1) session_setup_data->windowSize = (Cpa32U)7; #else session_setup_data->deflateWindowSize = (Cpa32U)7; session_setup_data->fileType = CPA_DC_FT_ASCII; #endif return QZ_OK; } int qzSetupSessionInternal(QzSession_T *sess) { int rc; QzSess_T *qz_sess; assert(sess); assert(sess->internal); qz_sess = (QzSess_T *)sess->internal; rc = qzSetupDcSessionData(&qz_sess->session_setup_data, &qz_sess->sess_params); if (rc != QZ_OK) { return rc; } qz_sess->inst_hint = -1; qz_sess->seq = 0; qz_sess->seq_in = 0; qz_sess->polling_idx = 0; qz_sess->force_sw = 0; qz_sess->inflate_strm = NULL; qz_sess->inflate_stat = InflateNull; qz_sess->deflate_strm = NULL; qz_sess->deflate_stat = DeflateNull; qz_sess->dctx = NULL; if (g_process.qz_init_status != QZ_OK) { /*hw not present*/ if (qz_sess->sess_params.sw_backup == 1) { sess->hw_session_stat = QZ_NO_HW; rc = QZ_OK; } else { sess->hw_session_stat = QZ_NOSW_NO_HW; rc = QZ_NOSW_NO_HW; } } else { sess->hw_session_stat = QZ_OK; rc = QZ_OK; } return rc; } int qzCheckParams(QzSessionParams_T *params) { assert(params); if (params->huffman_hdr > QZ_STATIC_HDR) { QZ_ERROR("Invalid huffman_hdr value\n"); return QZ_PARAMS; } if ((params->comp_lvl < QZ_DEFLATE_COMP_LVL_MINIMUM) || (params->comp_lvl > QZ_DEFLATE_COMP_LVL_MAXIMUM)) { QZ_ERROR("Invalid comp_lvl value\n"); return QZ_PARAMS; } if (params->direction > QZ_DIR_BOTH) { QZ_ERROR("Invalid direction value\n"); return QZ_PARAMS; } if (params->comp_algorithm != QZ_DEFLATE) { QZ_ERROR("Invalid comp_algorithm value\n"); return QZ_PARAMS; } if (params->sw_backup > 1) { QZ_ERROR("Invalid sw_backup value\n"); return QZ_PARAMS; } if ((params->hw_buff_sz < QZ_HW_BUFF_MIN_SZ) || (params->hw_buff_sz > QZ_HW_BUFF_MAX_SZ)) { QZ_ERROR("Invalid hw_buff_sz value\n"); return QZ_PARAMS; } if ((params->strm_buff_sz < QZ_STRM_BUFF_MIN_SZ) || (params->strm_buff_sz > QZ_STRM_BUFF_MAX_SZ)) { QZ_ERROR("Invalid strm_buff_sz value\n"); return QZ_PARAMS; } if (params->input_sz_thrshold < QZ_COMP_THRESHOLD_MINIMUM) { QZ_ERROR("Invalid input_sz_thrshold value\n"); return QZ_PARAMS; } if ((params->req_cnt_thrshold < QZ_REQ_THRESHOLD_MINIMUM) || (params->req_cnt_thrshold > QZ_REQ_THRESHOLD_MAXIMUM)) { QZ_ERROR("Invalid req_cnt_thrshold value\n"); return QZ_PARAMS; } if (params->hw_buff_sz & (params->hw_buff_sz - 1)) { QZ_ERROR("Invalid hw_buff_sz value, must be a power of 2k\n"); return QZ_PARAMS; } return QZ_OK; } static int qzCheckParamsCommon(QzSessionParamsCommon_T *params) { assert(params); if (params->direction > QZ_DIR_BOTH) { QZ_ERROR("Invalid direction value\n"); return QZ_PARAMS; } if ((params->comp_algorithm != QZ_DEFLATE) && (params->comp_algorithm != QZ_LZ4) && (params->comp_algorithm != QZ_LZ4s) && (params->comp_algorithm != QZ_ZSTD)) { QZ_ERROR("Invalid comp_algorithm value\n"); return QZ_PARAMS; } if (params->sw_backup > 1) { QZ_ERROR("Invalid sw_backup value\n"); return QZ_PARAMS; } if ((params->hw_buff_sz < QZ_HW_BUFF_MIN_SZ) || (params->hw_buff_sz > QZ_HW_BUFF_MAX_SZ)) { QZ_ERROR("Invalid hw_buff_sz value\n"); return QZ_PARAMS; } if ((params->strm_buff_sz < QZ_STRM_BUFF_MIN_SZ) || (params->strm_buff_sz > QZ_STRM_BUFF_MAX_SZ)) { QZ_ERROR("Invalid strm_buff_sz value\n"); return QZ_PARAMS; } if (params->input_sz_thrshold < QZ_COMP_THRESHOLD_MINIMUM) { QZ_ERROR("Invalid input_sz_thrshold value\n"); return QZ_PARAMS; } if ((params->req_cnt_thrshold < QZ_REQ_THRESHOLD_MINIMUM) || (params->req_cnt_thrshold > QZ_REQ_THRESHOLD_MAXIMUM)) { QZ_ERROR("Invalid req_cnt_thrshold value\n"); return QZ_PARAMS; } if (params->hw_buff_sz & (params->hw_buff_sz - 1)) { QZ_ERROR("Invalid hw_buff_sz value, must be a power of 2k\n"); return QZ_PARAMS; } return QZ_OK; } int qzCheckParamsDeflate(QzSessionParamsDeflate_T *params) { assert(params); if (qzCheckParamsCommon(¶ms->common_params) != QZ_OK) { return QZ_PARAMS; } if (params->common_params.comp_algorithm != QZ_DEFLATE) { QZ_ERROR("Invalid comp_algorithm value\n"); return QZ_PARAMS; } if (params->huffman_hdr > QZ_STATIC_HDR) { QZ_ERROR("Invalid huffman_hdr value\n"); return QZ_PARAMS; } if ((params->common_params.comp_lvl < QZ_LZS_COMP_LVL_MINIMUM) || (params->common_params.comp_lvl > QZ_DEFLATE_COMP_LVL_MAXIMUM_Gen3)) { QZ_ERROR("Invalid comp_lvl value\n"); return QZ_PARAMS; } if (params->data_fmt > QZ_DEFLATE_RAW) { QZ_ERROR("Invalid data_fmt value\n"); return QZ_PARAMS; } return QZ_OK; } int qzCheckParamsLZ4(QzSessionParamsLZ4_T *params) { assert(params); if (qzCheckParamsCommon(¶ms->common_params) != QZ_OK) { return QZ_PARAMS; } if (params->common_params.comp_algorithm != QZ_LZ4) { QZ_ERROR("Invalid comp_algorithm value\n"); return QZ_PARAMS; } if ((params->common_params.comp_lvl < QZ_LZS_COMP_LVL_MINIMUM) || (params->common_params.comp_lvl > QZ_LZS_COMP_LVL_MAXIMUM)) { QZ_ERROR("Invalid comp_lvl value\n"); return QZ_PARAMS; } return QZ_OK; } int qzCheckParamsLZ4S(QzSessionParamsLZ4S_T *params) { assert(params); if (qzCheckParamsCommon(¶ms->common_params) != QZ_OK) { return QZ_PARAMS; } if (params->common_params.comp_algorithm != QZ_LZ4s) { QZ_ERROR("Invalid comp_algorithm value\n"); return QZ_PARAMS; } if (params->common_params.direction != QZ_DIR_COMPRESS) { QZ_ERROR("LZ4s only support compression direction\n"); return QZ_PARAMS; } if ((params->common_params.comp_lvl < QZ_LZS_COMP_LVL_MINIMUM) || (params->common_params.comp_lvl > QZ_LZS_COMP_LVL_MAXIMUM)) { QZ_ERROR("Invalid comp_lvl value\n"); return QZ_PARAMS; } if ((params->lz4s_mini_match < 3) || (params->lz4s_mini_match > 4)) { QZ_ERROR("Invalid lz4s_mini_match value\n"); return QZ_PARAMS; } return QZ_OK; } static void qzSetParamsCommon(QzSessionParamsCommon_T *params, QzSessionParamsInternal_T *internal_params) { assert(params); assert(internal_params); internal_params->direction = params->direction; internal_params->comp_lvl = params->comp_lvl; internal_params->comp_algorithm = params->comp_algorithm; internal_params->max_forks = params->max_forks; internal_params->sw_backup = params->sw_backup; internal_params->hw_buff_sz = params->hw_buff_sz; internal_params->strm_buff_sz = params->strm_buff_sz; internal_params->input_sz_thrshold = params->input_sz_thrshold; internal_params->req_cnt_thrshold = params->req_cnt_thrshold; internal_params->wait_cnt_thrshold = params->wait_cnt_thrshold; internal_params->polling_mode = params->polling_mode; internal_params->is_sensitive_mode = params->is_sensitive_mode; } /** * Set session params into internal params */ void qzSetParams(QzSessionParams_T *params, QzSessionParamsInternal_T *internal_params) { assert(params); assert(internal_params); internal_params->direction = params->direction; internal_params->comp_lvl = params->comp_lvl; internal_params->comp_algorithm = params->comp_algorithm; internal_params->max_forks = params->max_forks; internal_params->sw_backup = params->sw_backup; internal_params->hw_buff_sz = params->hw_buff_sz; internal_params->strm_buff_sz = params->strm_buff_sz; internal_params->input_sz_thrshold = params->input_sz_thrshold; internal_params->req_cnt_thrshold = params->req_cnt_thrshold; internal_params->wait_cnt_thrshold = params->wait_cnt_thrshold; if (params->data_fmt == QZ_DEFLATE_4B) { internal_params->data_fmt = DEFLATE_4B; } else if (params->data_fmt == QZ_DEFLATE_GZIP) { internal_params->data_fmt = DEFLATE_GZIP; } else if (params->data_fmt == QZ_DEFLATE_RAW) { internal_params->data_fmt = DEFLATE_RAW; } else { internal_params->data_fmt = DEFLATE_GZIP_EXT; } internal_params->huffman_hdr = params->huffman_hdr; } /** * Set deflate session params into internal params */ void qzSetParamsDeflate(QzSessionParamsDeflate_T *params, QzSessionParamsInternal_T *internal_params) { assert(params); assert(internal_params); qzSetParamsCommon(¶ms->common_params, internal_params); if (params->data_fmt == QZ_DEFLATE_4B) { internal_params->data_fmt = DEFLATE_4B; } else if (params->data_fmt == QZ_DEFLATE_GZIP) { internal_params->data_fmt = DEFLATE_GZIP; } else if (params->data_fmt == QZ_DEFLATE_RAW) { internal_params->data_fmt = DEFLATE_RAW; } else { internal_params->data_fmt = DEFLATE_GZIP_EXT; } internal_params->huffman_hdr = params->huffman_hdr; } void qzSetParamsLZ4(QzSessionParamsLZ4_T *params, QzSessionParamsInternal_T *internal_params) { assert(params); assert(internal_params); qzSetParamsCommon(¶ms->common_params, internal_params); internal_params->data_fmt = LZ4_FH; } /** * Set LZ4S session params into internal params */ void qzSetParamsLZ4S(QzSessionParamsLZ4S_T *params, QzSessionParamsInternal_T *internal_params) { assert(params); assert(internal_params); qzSetParamsCommon(¶ms->common_params, internal_params); internal_params->data_fmt = LZ4S_BK; internal_params->qzCallback = params->qzCallback; internal_params->qzCallback_external = params->qzCallback_external; internal_params->lz4s_mini_match = params->lz4s_mini_match; } /** * Get session params from internal params */ void qzGetParams(QzSessionParamsInternal_T *internal_params, QzSessionParams_T *params) { assert(params); assert(internal_params); params->direction = internal_params->direction; params->comp_lvl = internal_params->comp_lvl; params->comp_algorithm = internal_params->comp_algorithm; params->max_forks = internal_params->max_forks; params->sw_backup = internal_params->sw_backup; params->hw_buff_sz = internal_params->hw_buff_sz; params->strm_buff_sz = internal_params->strm_buff_sz; params->input_sz_thrshold = internal_params->input_sz_thrshold; params->req_cnt_thrshold = internal_params->req_cnt_thrshold; params->wait_cnt_thrshold = internal_params->wait_cnt_thrshold; if (internal_params->data_fmt == DEFLATE_4B) { params->data_fmt = QZ_DEFLATE_4B; } else if (internal_params->data_fmt == DEFLATE_GZIP) { params->data_fmt = QZ_DEFLATE_GZIP; } else if (internal_params->data_fmt == DEFLATE_RAW) { params->data_fmt = QZ_DEFLATE_RAW; } else { params->data_fmt = QZ_DEFLATE_GZIP_EXT; } params->huffman_hdr = internal_params->huffman_hdr; } static void qzGetParamsCommon(QzSessionParamsInternal_T *internal_params, QzSessionParamsCommon_T *params) { assert(params); assert(internal_params); params->direction = internal_params->direction; params->comp_lvl = internal_params->comp_lvl; params->comp_algorithm = internal_params->comp_algorithm; params->max_forks = internal_params->max_forks; params->sw_backup = internal_params->sw_backup; params->hw_buff_sz = internal_params->hw_buff_sz; params->strm_buff_sz = internal_params->strm_buff_sz; params->input_sz_thrshold = internal_params->input_sz_thrshold; params->req_cnt_thrshold = internal_params->req_cnt_thrshold; params->wait_cnt_thrshold = internal_params->wait_cnt_thrshold; params->polling_mode = internal_params->polling_mode; params->is_sensitive_mode = internal_params->is_sensitive_mode; } /** * Get deflate session params from internal params */ void qzGetParamsDeflate(QzSessionParamsInternal_T *internal_params, QzSessionParamsDeflate_T *params) { assert(params); assert(internal_params); qzGetParamsCommon(internal_params, ¶ms->common_params); if (internal_params->data_fmt == DEFLATE_4B) { params->data_fmt = QZ_DEFLATE_4B; } else if (internal_params->data_fmt == DEFLATE_GZIP) { params->data_fmt = QZ_DEFLATE_GZIP; } else if (internal_params->data_fmt == DEFLATE_RAW) { params->data_fmt = QZ_DEFLATE_RAW; } else { params->data_fmt = QZ_DEFLATE_GZIP_EXT; } params->huffman_hdr = internal_params->huffman_hdr; params->common_params.comp_algorithm = QZ_DEFLATE; } /** * Get LZ4 session params from internal params */ void qzGetParamsLZ4(QzSessionParamsInternal_T *internal_params, QzSessionParamsLZ4_T *params) { assert(params); assert(internal_params); qzGetParamsCommon(internal_params, ¶ms->common_params); params->common_params.comp_algorithm = QZ_LZ4; } /** * Get LZ4S session params from internal params */ void qzGetParamsLZ4S(QzSessionParamsInternal_T *internal_params, QzSessionParamsLZ4S_T *params) { assert(params); assert(internal_params); qzGetParamsCommon(internal_params, ¶ms->common_params); params->common_params.comp_algorithm = QZ_LZ4s; /* LZ4s only support compression. */ params->common_params.direction = QZ_DIR_COMPRESS; params->qzCallback = internal_params->qzCallback; params->qzCallback_external = internal_params->qzCallback_external; params->lz4s_mini_match = internal_params->lz4s_mini_match; } inline unsigned long outputFooterSz(DataFormatInternal_T data_fmt) { unsigned long size = 0; switch (data_fmt) { case DEFLATE_4B: /* fall through */ case DEFLATE_RAW: size = 0; break; case LZ4_FH: size = qzLZ4FooterSz(); break; case LZ4S_BK: size = 0; break; case DEFLATE_GZIP_EXT: default: size = stdGzipFooterSz(); break; } return size; } unsigned long outputHeaderSz(DataFormatInternal_T data_fmt) { unsigned long size = 0; switch (data_fmt) { case DEFLATE_4B: size = qz4BHeaderSz(); break; case DEFLATE_RAW: break; case DEFLATE_GZIP: size = stdGzipHeaderSz(); break; case LZ4_FH: size = qzLZ4HeaderSz(); break; case LZ4S_BK: size = qzLZ4SBlockHeaderSz(); break; case DEFLATE_GZIP_EXT: default: size = qzGzipHeaderSz(); break; } return size; } void outputHeaderGen(unsigned char *ptr, CpaDcRqResults *res, DataFormatInternal_T data_fmt) { QZ_DEBUG("Generate header\n"); switch (data_fmt) { case DEFLATE_4B: qz4BHeaderGen(ptr, res); break; case DEFLATE_RAW: break; case DEFLATE_GZIP: stdGzipHeaderGen(ptr, res); break; case LZ4_FH: qzLZ4HeaderGen(ptr, res); break; case LZ4S_BK: qzLZ4SBlockHeaderGen(ptr, res); break; case DEFLATE_GZIP_EXT: default: qzGzipHeaderGen(ptr, res); break; } } inline void outputFooterGen(QzSess_T *qz_sess, CpaDcRqResults *res, DataFormatInternal_T data_fmt) { unsigned char *ptr = qz_sess->next_dest; switch (data_fmt) { case DEFLATE_RAW: break; case LZ4_FH: qzLZ4FooterGen(ptr, res); break; case LZ4S_BK: break; case DEFLATE_GZIP_EXT: default: qzGzipFooterGen(ptr, res); break; } } int isQATProcessable(const unsigned char *ptr, const unsigned int *const src_len, QzSess_T *const qz_sess) { uint32_t rc = 0; DataFormatInternal_T data_fmt; assert(ptr != NULL); assert(src_len != NULL); assert(qz_sess != NULL); data_fmt = qz_sess->sess_params.data_fmt; switch (data_fmt) { case DEFLATE_4B: case DEFLATE_GZIP: case DEFLATE_GZIP_EXT: rc = isQATDeflateProcessable(ptr, src_len, qz_sess); break; case LZ4_FH: rc = isQATLZ4Processable(ptr, src_len, qz_sess); break; default: rc = 0; break; } return rc; } void RestoreDestCpastreamBuffer(int i, int j) { if (g_process.qz_inst[i].stream[j].dest_need_reset) { g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = g_process.qz_inst[i].stream[j].orig_dest; g_process.qz_inst[i].stream[j].dest_need_reset = 0; } } void RestoreSrcCpastreamBuffer(int i, int j) { if (g_process.qz_inst[i].stream[j].src_need_reset) { g_process.qz_inst[i].src_buffers[j]->pBuffers->pData = g_process.qz_inst[i].stream[j].orig_src; g_process.qz_inst[i].stream[j].src_need_reset = 0; } } void ResetCpastreamSink(int i, int j) { g_process.qz_inst[i].stream[j].src1 = 0; g_process.qz_inst[i].stream[j].src2 = 0; g_process.qz_inst[i].stream[j].sink1 = 0; g_process.qz_inst[i].stream[j].sink2 = 0; } /* This setup function will always match with buffer clean up function * during error offload flow. */ void compBufferSetup(int i, int j, QzSess_T *qz_sess, unsigned char *src_ptr, unsigned int src_remaining, unsigned int hw_buff_sz, unsigned int src_send_sz) { unsigned int dest_receive_sz = 0; /* Get the qz_sess status of this request */ CpaDcOpData *opData = NULL; CpaBoolean need_cont_mem = g_process.qz_inst[i].instance_info.requiresPhysicallyContiguousMemory; DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; /* setup stream buffer */ g_process.qz_inst[i].stream[j].seq = qz_sess->seq; /*update stream seq*/ g_process.qz_inst[i].stream[j].res.checksum = 0; /* setup opData */ opData = &g_process.qz_inst[i].stream[j].opData; opData->inputSkipData.skipMode = CPA_DC_SKIP_DISABLED; opData->outputSkipData.skipMode = CPA_DC_SKIP_DISABLED; opData->compressAndVerify = CPA_TRUE; if (IS_DEFLATE_RAW(data_fmt) && (1 != qz_sess->last || src_remaining > hw_buff_sz)) { opData->flushFlag = CPA_DC_FLUSH_FULL; } else { opData->flushFlag = CPA_DC_FLUSH_FINAL; } QZ_DEBUG("sending seq number %d %d %ld, opData.flushFlag %d\n", i, j, qz_sess->seq, opData->flushFlag); /*Get feed src/dest buffer size*/ dest_receive_sz = *qz_sess->dest_sz > DEST_SZ(src_send_sz) ? DEST_SZ(src_send_sz) - outputHeaderSz(data_fmt) : *qz_sess->dest_sz - outputHeaderSz(data_fmt); g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes = src_send_sz; g_process.qz_inst[i].dest_buffers[j]->pBuffers->dataLenInBytes = dest_receive_sz; if (!need_cont_mem) { QZ_DEBUG("Compress SVM Enabled in doCompressIn\n"); } /*Feed src/dest buffer*/ if ((COMMON_MEM == qzMemFindAddr(src_ptr)) && need_cont_mem) { QZ_MEMCPY(g_process.qz_inst[i].src_buffers[j]->pBuffers->pData, src_ptr, src_send_sz, src_remaining); g_process.qz_inst[i].stream[j].src_need_reset = 0; } else { g_process.qz_inst[i].src_buffers[j]->pBuffers->pData = src_ptr; g_process.qz_inst[i].stream[j].src_need_reset = 1; } /*using zerocopy for the first request while dest buffer is pinned*/ if (unlikely((0 == g_process.qz_inst[i].stream[j].seq) && (!need_cont_mem || qzMemFindAddr(qz_sess->next_dest)))) { g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = qz_sess->next_dest + outputHeaderSz(data_fmt); g_process.qz_inst[i].stream[j].dest_need_reset = 1; } } /* when offload request failed after setup the buffer. * use this function to cleanup setup buffer. */ void compInBufferCleanUp(int i, int j) { RestoreDestCpastreamBuffer(i, j); RestoreSrcCpastreamBuffer(i, j); g_process.qz_inst[i].stream[j].src1 -= 1; g_process.qz_inst[i].stream[j].src2 -= 1; } /* when offload request successfully, Using below functions to process * clean up work during compressOut. There are clean up buffer function * in correct process flow or error process flow. */ void compOutSrcBufferCleanUp(int i, int j) { RestoreSrcCpastreamBuffer(i, j); } void compOutErrorDestBufferCleanUp(int i, int j) { RestoreDestCpastreamBuffer(i, j); } void compOutValidDestBufferCleanUp(int i, int j, QzSess_T *qz_sess, unsigned int dest_receive_sz) { CpaBoolean need_cont_mem = g_process.qz_inst[i].instance_info.requiresPhysicallyContiguousMemory; if (!need_cont_mem) { QZ_DEBUG("Compress SVM Enabled in doCompressOut\n"); } if (g_process.qz_inst[i].stream[j].dest_need_reset) { g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = g_process.qz_inst[i].stream[j].orig_dest; g_process.qz_inst[i].stream[j].dest_need_reset = 0; } else { QZ_MEMCPY(qz_sess->next_dest, g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData, *qz_sess->dest_sz - qz_sess->qz_out_len, dest_receive_sz); } } /* Process respond means to reset or update sess status * And clean up buffer. */ void compOutProcessedRespond(int i, int j, QzSess_T *qz_sess) { compOutSrcBufferCleanUp(i, j); /* Update the seq_in and process, clean buffer */ assert(g_process.qz_inst[i].stream[j].seq == qz_sess->seq_in); g_process.qz_inst[i].stream[j].sink2++; qz_sess->processed++; qz_sess->seq_in++; } void compOutSkipErrorRespond(int i, int j, QzSess_T *qz_sess) { compOutErrorDestBufferCleanUp(i, j); compOutProcessedRespond(i, j, qz_sess); } int compOutCheckDestLen(int i, int j, QzSession_T *sess, long *dest_avail_len, long dest_receive_sz) { QzSess_T *qz_sess = (QzSess_T *)sess->internal; *dest_avail_len -= dest_receive_sz; if (unlikely(*dest_avail_len < 0)) { QZ_DEBUG("doCompressOut: inadequate output buffer length: %ld, outlen: %ld\n", (long)(*qz_sess->dest_sz), qz_sess->qz_out_len); compOutSkipErrorRespond(i, j, qz_sess); qz_sess->stop_submitting = 1; sess->thd_sess_stat = QZ_BUF_ERROR; return sess->thd_sess_stat; } return QZ_OK; } /*To handle compression expansion*/ void swapDataBuffer(unsigned long i, int j) { Cpa8U *p_tmp_data; p_tmp_data = g_process.qz_inst[i].src_buffers[j]->pBuffers->pData; g_process.qz_inst[i].src_buffers[j]->pBuffers->pData = g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData; g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = p_tmp_data; p_tmp_data = g_process.qz_inst[i].stream[j].orig_src; g_process.qz_inst[i].stream[j].orig_src = g_process.qz_inst[i].stream[j].orig_dest; g_process.qz_inst[i].stream[j].orig_dest = p_tmp_data; } /* Note: * CheckHeader return value * @retval QZ_OK Function executed successfully * @retval QZ_FAIL Decompress stop, Fatal error * @retval QZ_FORCE_SW Decompress fallback sw * @retval QZ_BUF_ERROR Return to decompress API * @retval QZ_DATA_ERROR Return to decompress API */ int checkHeader(QzSess_T *qz_sess, unsigned char *src, unsigned int src_avail_len, unsigned int dest_avail_len, QzGzH_T *hdr) { unsigned char *src_ptr = src; unsigned int compressed_sz = 0; unsigned int uncompressed_sz = 0; StdGzF_T *qzFooter = NULL; int isEndWithFooter = 0; int ret = 0; QzLZ4H_T *qzLZ4Header = NULL; QzLZ4F_T *lz4Footer = NULL; DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; if ((src_avail_len <= 0) || (dest_avail_len <= 0)) { QZ_DEBUG("checkHeader: insufficient %s buffer length\n", (dest_avail_len <= 0) ? "destation" : "source"); return QZ_BUF_ERROR; } if (src_avail_len < outputHeaderSz(data_fmt)) { QZ_DEBUG("checkHeader: incomplete source buffer\n"); return QZ_DATA_ERROR; } if (1 == qz_sess->force_sw) { return QZ_FORCE_SW; } switch (data_fmt) { case DEFLATE_GZIP: qzFooter = (StdGzF_T *)(findStdGzipFooter(src_ptr, src_avail_len)); compressed_sz = (unsigned char *)qzFooter - src_ptr - stdGzipHeaderSz(); uncompressed_sz = qzFooter->i_size; if ((unsigned char *)qzFooter == src_ptr + src_avail_len - stdGzipFooterSz()) { isEndWithFooter = 1; } break; case DEFLATE_GZIP_EXT: if (QZ_OK != qzGzipHeaderExt(src_ptr, hdr)) { return QZ_FAIL; } compressed_sz = (long)(hdr->extra.qz_e.dest_sz); uncompressed_sz = (long)(hdr->extra.qz_e.src_sz); break; case DEFLATE_4B: compressed_sz = *(int *)src_ptr; uncompressed_sz = (qz_sess->sess_params.hw_buff_sz > dest_avail_len) ? dest_avail_len : qz_sess->sess_params.hw_buff_sz; break; case LZ4_FH: ret = qzVerifyLZ4FrameHeader(src_ptr, src_avail_len); if (ret != QZ_OK) { return ret; } lz4Footer = (QzLZ4F_T *)findLZ4Footer(src_ptr, src_avail_len); if (NULL == lz4Footer) { QZ_DEBUG("checkHeader: incomplete source buffer\n"); return QZ_DATA_ERROR; } qzLZ4Header = (QzLZ4H_T *)src_ptr; compressed_sz = (unsigned char *)lz4Footer - src_ptr - qzLZ4HeaderSz(); uncompressed_sz = qzLZ4Header->cnt_size; break; default: return QZ_FAIL; } if ((compressed_sz > DEST_SZ((long)(qz_sess->sess_params.hw_buff_sz))) || (uncompressed_sz > qz_sess->sess_params.hw_buff_sz)) { if (1 == qz_sess->sess_params.sw_backup) { if (DEFLATE_GZIP == data_fmt && 1 == isEndWithFooter) { return QZ_FORCE_SW; } qz_sess->force_sw = 1; return QZ_FORCE_SW; } else { return QZ_FAIL; } } if (compressed_sz + outputHeaderSz(data_fmt) + outputFooterSz(data_fmt) > src_avail_len) { QZ_DEBUG("checkHeader: incomplete source buffer\n"); return QZ_DATA_ERROR; } else if (uncompressed_sz > dest_avail_len) { QZ_DEBUG("checkHeader: insufficient destination buffer length\n"); return QZ_BUF_ERROR; } hdr->extra.qz_e.dest_sz = compressed_sz; hdr->extra.qz_e.src_sz = uncompressed_sz; return QZ_OK; } /* Below Buffer and respond process function is exact same means with * Compression */ void decompBufferSetup(int i, int j, QzSess_T *qz_sess, unsigned char *src_ptr, unsigned char *dest_ptr, unsigned int src_avail_len, QzGzH_T *hdr, unsigned int *tmp_src_avail_len, unsigned int *tmp_dest_avail_len) { StdGzF_T *qzFooter = NULL; QzLZ4F_T *lz4Footer = NULL; unsigned int src_send_sz = 0; unsigned int dest_receive_sz = 0; int src_mem_type = qzMemFindAddr(src_ptr); int dest_mem_type = qzMemFindAddr(dest_ptr); DataFormatInternal_T data_fmt = qz_sess->sess_params.data_fmt; CpaBoolean need_cont_mem = g_process.qz_inst[i].instance_info.requiresPhysicallyContiguousMemory; if (!need_cont_mem) { QZ_DEBUG("Decompress SVM Enabled in doDecompressIn\n"); } g_process.qz_inst[i].stream[j].seq = qz_sess->seq; g_process.qz_inst[i].stream[j].res.checksum = 0; swapDataBuffer(i, j); src_ptr += outputHeaderSz(data_fmt); src_send_sz = hdr->extra.qz_e.dest_sz; dest_receive_sz = hdr->extra.qz_e.src_sz; g_process.qz_inst[i].src_buffers[j]->pBuffers->dataLenInBytes = src_send_sz; g_process.qz_inst[i].dest_buffers[j]->pBuffers->dataLenInBytes = dest_receive_sz; QZ_DEBUG("doDecompressIn: Sending %u bytes starting at 0x%lx\n", src_send_sz, (unsigned long)src_ptr); QZ_DEBUG("sending seq number %lu %d %ld\n", i, j, qz_sess->seq); if (DEFLATE_GZIP_EXT == data_fmt || DEFLATE_GZIP == data_fmt) { qzFooter = (StdGzF_T *)(src_ptr + src_send_sz); g_process.qz_inst[i].stream[j].checksum = qzFooter->crc32; g_process.qz_inst[i].stream[j].orgdatalen = qzFooter->i_size; } else if (LZ4_FH == data_fmt) { lz4Footer = (QzLZ4F_T *)(src_ptr + src_send_sz); //TODO g_process.qz_inst[i].stream[j].checksum = lz4Footer->cnt_cksum; g_process.qz_inst[i].stream[j].orgdatalen = hdr->extra.qz_e.src_sz; } /*set up src dest buffers*/ if ((COMMON_MEM == src_mem_type) && need_cont_mem) { QZ_DEBUG("memory copy in doDecompressIn\n"); QZ_MEMCPY(g_process.qz_inst[i].src_buffers[j]->pBuffers->pData, src_ptr, src_avail_len, src_send_sz); g_process.qz_inst[i].stream[j].src_need_reset = 0; } else { g_process.qz_inst[i].src_buffers[j]->pBuffers->pData = src_ptr; g_process.qz_inst[i].stream[j].src_need_reset = 1; } if ((COMMON_MEM == dest_mem_type) && need_cont_mem) { g_process.qz_inst[i].stream[j].dest_need_reset = 0; } else { g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = dest_ptr; g_process.qz_inst[i].stream[j].dest_need_reset = 1; } *tmp_src_avail_len = (outputHeaderSz(data_fmt) + src_send_sz + outputFooterSz( data_fmt)); *tmp_dest_avail_len = dest_receive_sz; } void decompInBufferCleanUp(int i, int j) { /*clean stream buffer*/ g_process.qz_inst[i].stream[j].src1 -= 1; g_process.qz_inst[i].stream[j].src2 -= 1; RestoreDestCpastreamBuffer(i, j); RestoreSrcCpastreamBuffer(i, j); swapDataBuffer(i, j); } void decompOutSrcBufferCleanUp(int i, int j) { RestoreSrcCpastreamBuffer(i, j); } void decompOutErrorDestBufferCleanUp(int i, int j) { RestoreDestCpastreamBuffer(i, j); } void decompOutValidDestBufferCleanUp(int i, int j, QzSess_T *qz_sess, CpaDcRqResults *resl, unsigned int dest_avail_len) { if (!g_process.qz_inst[i].stream[j].dest_need_reset) { QZ_DEBUG("memory copy in doDecompressOut\n"); QZ_MEMCPY(qz_sess->next_dest, g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData, dest_avail_len, resl->produced); } else { g_process.qz_inst[i].dest_buffers[j]->pBuffers->pData = g_process.qz_inst[i].stream[j].orig_dest; g_process.qz_inst[i].stream[j].dest_need_reset = 0; } } void decompOutProcessedRespond(int i, int j, QzSess_T *qz_sess) { decompOutSrcBufferCleanUp(i, j); swapDataBuffer(i, j); /*swap pdata back after decompress*/ assert(g_process.qz_inst[i].stream[j].seq == qz_sess->seq_in); g_process.qz_inst[i].stream[j].sink2++; qz_sess->seq_in++; qz_sess->processed++; } void decompOutSkipErrorRespond(int i, int j, QzSess_T *qz_sess) { decompOutErrorDestBufferCleanUp(i, j); decompOutProcessedRespond(i, j, qz_sess); } int decompOutCheckSum(int i, int j, QzSession_T *sess, CpaDcRqResults *resl) { QzSess_T *qz_sess = (QzSess_T *)sess->internal; if ((qz_sess->sess_params.data_fmt != DEFLATE_4B) && unlikely(resl->checksum != g_process.qz_inst[i].stream[j].checksum || resl->produced != g_process.qz_inst[i].stream[j].orgdatalen)) { QZ_ERROR("Error in check footer, inst %d, stream %d\n", i, j); QZ_DEBUG("resp checksum: %x data checksum %x\n", resl->checksum, g_process.qz_inst[i].stream[j].checksum); QZ_DEBUG("resp produced :%d data produced: %d\n", resl->produced, g_process.qz_inst[i].stream[j].orgdatalen); decompOutProcessedRespond(i, j, qz_sess); qz_sess->stop_submitting = 1; sess->thd_sess_stat = QZ_DATA_ERROR; return sess->thd_sess_stat; } return QZ_OK; } QATzip-1.2.0/src/xxhash.c000066400000000000000000001061731456106226300151350ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ /*************************************************************************** * xxHash - Fast Hash algorithm * Copyright (C) 2012-2016, Yann Collet * * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at : * - xxHash homepage: http://www.xxhash.com * - xxHash source repository : https://github.com/Cyan4973/xxHash ***************************************************************************/ /* ************************************* * Tuning parameters ***************************************/ /*!XXH_FORCE_MEMORY_ACCESS : * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. * The below switch allow to select different access method for improved performance. * Method 0 (default) : use `memcpy()`. Safe and portable. * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. * It can generate buggy code on targets which do not support unaligned memory accesses. * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) * See http://stackoverflow.com/a/32095106/646947 for details. * Prefer these methods in priority order (0 > 1 > 2) */ #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ # if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) # define XXH_FORCE_MEMORY_ACCESS 2 # elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \ (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ || defined(__ARM_ARCH_7S__) )) # define XXH_FORCE_MEMORY_ACCESS 1 # endif #endif /*!XXH_ACCEPT_NULL_INPUT_POINTER : * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault. * When this macro is enabled, xxHash actively checks input for null pointer. * It it is, result for null input pointers is the same as a null-length input. */ #ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */ # define XXH_ACCEPT_NULL_INPUT_POINTER 0 #endif /*!XXH_FORCE_NATIVE_FORMAT : * By default, xxHash library provides endian-independent Hash values, based on little-endian convention. * Results are therefore identical for little-endian and big-endian CPU. * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. * Should endian-independence be of no importance for your application, you may set the #define below to 1, * to improve speed for Big-endian CPU. * This option has no impact on Little_Endian CPU. */ #ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ # define XXH_FORCE_NATIVE_FORMAT 0 #endif /*!XXH_FORCE_ALIGN_CHECK : * This is a minor performance trick, only useful with lots of very small keys. * It means : check for aligned/unaligned input. * The check costs one initial branch per hash; * set it to 0 when the input is guaranteed to be aligned, * or when alignment doesn't matter for performance. */ #ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ # if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) # define XXH_FORCE_ALIGN_CHECK 0 # else # define XXH_FORCE_ALIGN_CHECK 1 # endif #endif /* ************************************* * Includes & Memory related functions ***************************************/ /*! Modify the local functions below should you wish to use some other memory routines * for malloc(), free() */ #include static void *XXH_malloc(size_t s) { return malloc(s); } static void XXH_free(void *p) { free(p); } /*! and for memcpy() */ #include static void *XXH_memcpy(void *dest, const void *src, size_t size) { return memcpy(dest, src, size); } #include /* assert */ #define XXH_STATIC_LINKING_ONLY #include "xxhash.h" /* ************************************* * Compiler Specific Options ***************************************/ #ifdef _MSC_VER /* Visual Studio */ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ # define FORCE_INLINE static __forceinline #else # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ # ifdef __GNUC__ # define FORCE_INLINE static inline __attribute__((always_inline)) # else # define FORCE_INLINE static inline # endif # else # define FORCE_INLINE static # endif /* __STDC_VERSION__ */ #endif /* ************************************* * Basic Types ***************************************/ #ifndef MEM_MODULE # if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # include typedef uint8_t BYTE; typedef uint16_t U16; typedef uint32_t U32; # else typedef unsigned char BYTE; typedef unsigned short U16; typedef unsigned int U32; # endif #endif #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ static U32 XXH_read32(const void *memPtr) { return *(const U32 *) memPtr; } #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ /* currently only defined for gcc and icc */ typedef union { U32 u32; } __attribute__((packed)) unalign; static U32 XXH_read32(const void *ptr) { return ((const unalign *)ptr)->u32; } #else /* portable and safe solution. Generally efficient. * see : http://stackoverflow.com/a/32095106/646947 */ static U32 XXH_read32(const void *memPtr) { U32 val; memcpy(&val, memPtr, sizeof(val)); return val; } #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ /* **************************************** * Compiler-specific Functions and Macros ******************************************/ #define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) /* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ #if defined(_MSC_VER) # define XXH_rotl32(x,r) _rotl(x,r) # define XXH_rotl64(x,r) _rotl64(x,r) #else # define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) # define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) #endif #if defined(_MSC_VER) /* Visual Studio */ # define XXH_swap32 _byteswap_ulong #elif XXH_GCC_VERSION >= 403 # define XXH_swap32 __builtin_bswap32 #else static U32 XXH_swap32(U32 x) { return ((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff); } #endif /* ************************************* * Architecture Macros ***************************************/ typedef enum { XXH_bigEndian = 0, XXH_littleEndian = 1 } XXH_endianess; /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ #ifndef XXH_CPU_LITTLE_ENDIAN static int XXH_isLittleEndian(void) { const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ return one.c[0]; } # define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() #endif /* *************************** * Memory reads *****************************/ typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; FORCE_INLINE U32 XXH_readLE32_align(const void *ptr, XXH_endianess endian, XXH_alignment align) { if (align == XXH_unaligned) return endian == XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32( ptr)); else return endian == XXH_littleEndian ? *(const U32 *)ptr : XXH_swap32(* (const U32 *)ptr); } FORCE_INLINE U32 XXH_readLE32(const void *ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); } static U32 XXH_readBE32(const void *ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); } /* ************************************* * Macros ***************************************/ #define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */ XXH_PUBLIC_API unsigned XXH_versionNumber(void) { return XXH_VERSION_NUMBER; } /* ******************************************************************* * 32-bit hash functions *********************************************************************/ static const U32 PRIME32_1 = 2654435761U; static const U32 PRIME32_2 = 2246822519U; static const U32 PRIME32_3 = 3266489917U; static const U32 PRIME32_4 = 668265263U; static const U32 PRIME32_5 = 374761393U; static U32 XXH32_round(U32 seed, U32 input) { seed += input * PRIME32_2; seed = XXH_rotl32(seed, 13); seed *= PRIME32_1; return seed; } /* mix all bits */ static U32 XXH32_avalanche(U32 h32) { h32 ^= h32 >> 15; h32 *= PRIME32_2; h32 ^= h32 >> 13; h32 *= PRIME32_3; h32 ^= h32 >> 16; return (h32); } #define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) static U32 XXH32_finalize(U32 h32, const void *ptr, size_t len, XXH_endianess endian, XXH_alignment align) { const BYTE *p = (const BYTE *)ptr; #define PROCESS1 \ h32 += (*p++) * PRIME32_5; \ h32 = XXH_rotl32(h32, 11) * PRIME32_1 ; #define PROCESS4 \ h32 += XXH_get32bits(p) * PRIME32_3; \ p+=4; \ h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; switch (len & 15) { /* or switch(bEnd - p) */ case 12: PROCESS4; /* fallthrough */ case 8: PROCESS4; /* fallthrough */ case 4: PROCESS4; return XXH32_avalanche(h32); case 13: PROCESS4; /* fallthrough */ case 9: PROCESS4; /* fallthrough */ case 5: PROCESS4; PROCESS1; return XXH32_avalanche(h32); case 14: PROCESS4; /* fallthrough */ case 10: PROCESS4; /* fallthrough */ case 6: PROCESS4; PROCESS1; PROCESS1; return XXH32_avalanche(h32); case 15: PROCESS4; /* fallthrough */ case 11: PROCESS4; /* fallthrough */ case 7: PROCESS4; /* fallthrough */ case 3: PROCESS1; /* fallthrough */ case 2: PROCESS1; /* fallthrough */ case 1: PROCESS1; /* fallthrough */ case 0: return XXH32_avalanche(h32); } assert(0); return h32; /* reaching this point is deemed impossible */ } FORCE_INLINE U32 XXH32_endian_align(const void *input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align) { const BYTE *p = (const BYTE *)input; const BYTE *bEnd = p + len; U32 h32; #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) if (p == NULL) { len = 0; bEnd = p = (const BYTE *)(size_t)16; } #endif if (len >= 16) { const BYTE *const limit = bEnd - 15; U32 v1 = seed + PRIME32_1 + PRIME32_2; U32 v2 = seed + PRIME32_2; U32 v3 = seed + 0; U32 v4 = seed - PRIME32_1; do { v1 = XXH32_round(v1, XXH_get32bits(p)); p += 4; v2 = XXH32_round(v2, XXH_get32bits(p)); p += 4; v3 = XXH32_round(v3, XXH_get32bits(p)); p += 4; v4 = XXH32_round(v4, XXH_get32bits(p)); p += 4; } while (p < limit); h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); } else { h32 = seed + PRIME32_5; } h32 += (U32)len; return XXH32_finalize(h32, p, len & 15, endian, align); } XXH_PUBLIC_API unsigned int XXH32(const void *input, size_t len, unsigned int seed) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; if (XXH_FORCE_ALIGN_CHECK) { if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); else return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); } } if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); else return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); } /*====== Hash streaming ======*/ XXH_PUBLIC_API XXH32_state_t *XXH32_createState(void) { return (XXH32_state_t *)XXH_malloc(sizeof(XXH32_state_t)); } XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t *statePtr) { XXH_free(statePtr); return XXH_OK; } XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t *dstState, const XXH32_state_t *srcState) { memcpy(dstState, srcState, sizeof(*dstState)); } XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t *statePtr, unsigned int seed) { XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ memset(&state, 0, sizeof(state)); state.v1 = seed + PRIME32_1 + PRIME32_2; state.v2 = seed + PRIME32_2; state.v3 = seed + 0; state.v4 = seed - PRIME32_1; /* do not write into reserved, planned to be removed in a future version */ memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); return XXH_OK; } FORCE_INLINE XXH_errorcode XXH32_update_endian(XXH32_state_t *state, const void *input, size_t len, XXH_endianess endian) { if (input == NULL) #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) return XXH_OK; #else return XXH_ERROR; #endif { const BYTE *p = (const BYTE *)input; const BYTE *const bEnd = p + len; state->total_len_32 += (unsigned)len; state->large_len |= (len >= 16) | (state->total_len_32 >= 16); if (state->memsize + len < 16) { /* fill in tmp buffer */ XXH_memcpy((BYTE *)(state->mem32) + state->memsize, input, len); state->memsize += (unsigned)len; return XXH_OK; } if (state->memsize) { /* some data left from previous update */ XXH_memcpy((BYTE *)(state->mem32) + state->memsize, input, 16 - state->memsize); { const U32 *p32 = state->mem32; state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); } p += 16 - state->memsize; state->memsize = 0; } if (p <= bEnd - 16) { const BYTE *const limit = bEnd - 16; U32 v1 = state->v1; U32 v2 = state->v2; U32 v3 = state->v3; U32 v4 = state->v4; do { v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p += 4; v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p += 4; v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p += 4; v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p += 4; } while (p <= limit); state->v1 = v1; state->v2 = v2; state->v3 = v3; state->v4 = v4; } if (p < bEnd) { XXH_memcpy(state->mem32, p, (size_t)(bEnd - p)); state->memsize = (unsigned)(bEnd - p); } } return XXH_OK; } XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t *state_in, const void *input, size_t len) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH32_update_endian(state_in, input, len, XXH_littleEndian); else return XXH32_update_endian(state_in, input, len, XXH_bigEndian); } FORCE_INLINE U32 XXH32_digest_endian(const XXH32_state_t *state, XXH_endianess endian) { U32 h32; if (state->large_len) { h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); } else { h32 = state->v3 /* == seed */ + PRIME32_5; } h32 += state->total_len_32; return XXH32_finalize(h32, state->mem32, state->memsize, endian, XXH_aligned); } XXH_PUBLIC_API unsigned int XXH32_digest(const XXH32_state_t *state_in) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH32_digest_endian(state_in, XXH_littleEndian); else return XXH32_digest_endian(state_in, XXH_bigEndian); } /*====== Canonical representation ======*/ /*! Default XXH result types are basic unsigned 32 and 64 bits. * The canonical representation follows human-readable write convention, aka big-endian (large digits first). * These functions allow transformation of hash result into and from its canonical format. * This way, hash values can be written into a file or buffer, remaining comparable across different systems. */ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t *dst, XXH32_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); memcpy(dst, &hash, sizeof(*dst)); } XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t *src) { return XXH_readBE32(src); } #ifndef XXH_NO_LONG_LONG /* ******************************************************************* * 64-bit hash functions *********************************************************************/ /*====== Memory access ======*/ #ifndef MEM_MODULE # define MEM_MODULE # if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # include typedef uint64_t U64; # else /* if compiler doesn't support unsigned long long, replace by another 64-bit type */ typedef unsigned long long U64; # endif #endif #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ static U64 XXH_read64(const void *memPtr) { return *(const U64 *) memPtr; } #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ /* currently only defined for gcc and icc */ typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64; static U64 XXH_read64(const void *ptr) { return ((const unalign64 *)ptr)->u64; } #else /* portable and safe solution. Generally efficient. * see : http://stackoverflow.com/a/32095106/646947 */ static U64 XXH_read64(const void *memPtr) { U64 val; memcpy(&val, memPtr, sizeof(val)); return val; } #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ #if defined(_MSC_VER) /* Visual Studio */ # define XXH_swap64 _byteswap_uint64 #elif XXH_GCC_VERSION >= 403 # define XXH_swap64 __builtin_bswap64 #else static U64 XXH_swap64(U64 x) { return ((x << 56) & 0xff00000000000000ULL) | ((x << 40) & 0x00ff000000000000ULL) | ((x << 24) & 0x0000ff0000000000ULL) | ((x << 8) & 0x000000ff00000000ULL) | ((x >> 8) & 0x00000000ff000000ULL) | ((x >> 24) & 0x0000000000ff0000ULL) | ((x >> 40) & 0x000000000000ff00ULL) | ((x >> 56) & 0x00000000000000ffULL); } #endif FORCE_INLINE U64 XXH_readLE64_align(const void *ptr, XXH_endianess endian, XXH_alignment align) { if (align == XXH_unaligned) return endian == XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64( ptr)); else return endian == XXH_littleEndian ? *(const U64 *)ptr : XXH_swap64(* (const U64 *)ptr); } FORCE_INLINE U64 XXH_readLE64(const void *ptr, XXH_endianess endian) { return XXH_readLE64_align(ptr, endian, XXH_unaligned); } static U64 XXH_readBE64(const void *ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); } /*====== xxh64 ======*/ static const U64 PRIME64_1 = 11400714785074694791ULL; static const U64 PRIME64_2 = 14029467366897019727ULL; static const U64 PRIME64_3 = 1609587929392839161ULL; static const U64 PRIME64_4 = 9650029242287828579ULL; static const U64 PRIME64_5 = 2870177450012600261ULL; static U64 XXH64_round(U64 acc, U64 input) { acc += input * PRIME64_2; acc = XXH_rotl64(acc, 31); acc *= PRIME64_1; return acc; } static U64 XXH64_mergeRound(U64 acc, U64 val) { val = XXH64_round(0, val); acc ^= val; acc = acc * PRIME64_1 + PRIME64_4; return acc; } static U64 XXH64_avalanche(U64 h64) { h64 ^= h64 >> 33; h64 *= PRIME64_2; h64 ^= h64 >> 29; h64 *= PRIME64_3; h64 ^= h64 >> 32; return h64; } #define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) static U64 XXH64_finalize(U64 h64, const void *ptr, size_t len, XXH_endianess endian, XXH_alignment align) { const BYTE *p = (const BYTE *)ptr; #define PROCESS1_64 \ h64 ^= (*p++) * PRIME64_5; \ h64 = XXH_rotl64(h64, 11) * PRIME64_1; #define PROCESS4_64 \ h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; \ p+=4; \ h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; #define PROCESS8_64 { \ U64 const k1 = XXH64_round(0, XXH_get64bits(p)); \ p+=8; \ h64 ^= k1; \ h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; \ } switch (len & 31) { case 24: PROCESS8_64; /* fallthrough */ case 16: PROCESS8_64; /* fallthrough */ case 8: PROCESS8_64; return XXH64_avalanche(h64); case 28: PROCESS8_64; /* fallthrough */ case 20: PROCESS8_64; /* fallthrough */ case 12: PROCESS8_64; /* fallthrough */ case 4: PROCESS4_64; return XXH64_avalanche(h64); case 25: PROCESS8_64; /* fallthrough */ case 17: PROCESS8_64; /* fallthrough */ case 9: PROCESS8_64; PROCESS1_64; return XXH64_avalanche(h64); case 29: PROCESS8_64; /* fallthrough */ case 21: PROCESS8_64; /* fallthrough */ case 13: PROCESS8_64; /* fallthrough */ case 5: PROCESS4_64; PROCESS1_64; return XXH64_avalanche(h64); case 26: PROCESS8_64; /* fallthrough */ case 18: PROCESS8_64; /* fallthrough */ case 10: PROCESS8_64; PROCESS1_64; PROCESS1_64; return XXH64_avalanche(h64); case 30: PROCESS8_64; /* fallthrough */ case 22: PROCESS8_64; /* fallthrough */ case 14: PROCESS8_64; /* fallthrough */ case 6: PROCESS4_64; PROCESS1_64; PROCESS1_64; return XXH64_avalanche(h64); case 27: PROCESS8_64; /* fallthrough */ case 19: PROCESS8_64; /* fallthrough */ case 11: PROCESS8_64; PROCESS1_64; PROCESS1_64; PROCESS1_64; return XXH64_avalanche(h64); case 31: PROCESS8_64; /* fallthrough */ case 23: PROCESS8_64; /* fallthrough */ case 15: PROCESS8_64; /* fallthrough */ case 7: PROCESS4_64; /* fallthrough */ case 3: PROCESS1_64; /* fallthrough */ case 2: PROCESS1_64; /* fallthrough */ case 1: PROCESS1_64; /* fallthrough */ case 0: return XXH64_avalanche(h64); } /* impossible to reach */ assert(0); return 0; /* unreachable, but some compilers complain without it */ } FORCE_INLINE U64 XXH64_endian_align(const void *input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align) { const BYTE *p = (const BYTE *)input; const BYTE *bEnd = p + len; U64 h64; #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) if (p == NULL) { len = 0; bEnd = p = (const BYTE *)(size_t)32; } #endif if (len >= 32) { const BYTE *const limit = bEnd - 32; U64 v1 = seed + PRIME64_1 + PRIME64_2; U64 v2 = seed + PRIME64_2; U64 v3 = seed + 0; U64 v4 = seed - PRIME64_1; do { v1 = XXH64_round(v1, XXH_get64bits(p)); p += 8; v2 = XXH64_round(v2, XXH_get64bits(p)); p += 8; v3 = XXH64_round(v3, XXH_get64bits(p)); p += 8; v4 = XXH64_round(v4, XXH_get64bits(p)); p += 8; } while (p <= limit); h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); h64 = XXH64_mergeRound(h64, v1); h64 = XXH64_mergeRound(h64, v2); h64 = XXH64_mergeRound(h64, v3); h64 = XXH64_mergeRound(h64, v4); } else { h64 = seed + PRIME64_5; } h64 += (U64) len; return XXH64_finalize(h64, p, len, endian, align); } XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; if (XXH_FORCE_ALIGN_CHECK) { if ((((size_t)input) & 7) == 0) { /* Input is aligned, let's leverage the speed advantage */ if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); else return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); } } if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); else return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); } /*====== Hash Streaming ======*/ XXH_PUBLIC_API XXH64_state_t *XXH64_createState(void) { return (XXH64_state_t *)XXH_malloc(sizeof(XXH64_state_t)); } XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t *statePtr) { XXH_free(statePtr); return XXH_OK; } XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t *dstState, const XXH64_state_t *srcState) { memcpy(dstState, srcState, sizeof(*dstState)); } XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t *statePtr, unsigned long long seed) { XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ memset(&state, 0, sizeof(state)); state.v1 = seed + PRIME64_1 + PRIME64_2; state.v2 = seed + PRIME64_2; state.v3 = seed + 0; state.v4 = seed - PRIME64_1; /* do not write into reserved, planned to be removed in a future version */ memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); return XXH_OK; } FORCE_INLINE XXH_errorcode XXH64_update_endian(XXH64_state_t *state, const void *input, size_t len, XXH_endianess endian) { if (input == NULL) #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) return XXH_OK; #else return XXH_ERROR; #endif { const BYTE *p = (const BYTE *)input; const BYTE *const bEnd = p + len; state->total_len += len; if (state->memsize + len < 32) { /* fill in tmp buffer */ XXH_memcpy(((BYTE *)state->mem64) + state->memsize, input, len); state->memsize += (U32)len; return XXH_OK; } if (state->memsize) { /* tmp buffer is full */ XXH_memcpy(((BYTE *)state->mem64) + state->memsize, input, 32 - state->memsize); state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64 + 0, endian)); state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64 + 1, endian)); state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64 + 2, endian)); state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64 + 3, endian)); p += 32 - state->memsize; state->memsize = 0; } if (p + 32 <= bEnd) { const BYTE *const limit = bEnd - 32; U64 v1 = state->v1; U64 v2 = state->v2; U64 v3 = state->v3; U64 v4 = state->v4; do { v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p += 8; v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p += 8; v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p += 8; v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p += 8; } while (p <= limit); state->v1 = v1; state->v2 = v2; state->v3 = v3; state->v4 = v4; } if (p < bEnd) { XXH_memcpy(state->mem64, p, (size_t)(bEnd - p)); state->memsize = (unsigned)(bEnd - p); } } return XXH_OK; } XXH_PUBLIC_API XXH_errorcode XXH64_update(XXH64_state_t *state_in, const void *input, size_t len) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH64_update_endian(state_in, input, len, XXH_littleEndian); else return XXH64_update_endian(state_in, input, len, XXH_bigEndian); } FORCE_INLINE U64 XXH64_digest_endian(const XXH64_state_t *state, XXH_endianess endian) { U64 h64; if (state->total_len >= 32) { U64 const v1 = state->v1; U64 const v2 = state->v2; U64 const v3 = state->v3; U64 const v4 = state->v4; h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); h64 = XXH64_mergeRound(h64, v1); h64 = XXH64_mergeRound(h64, v2); h64 = XXH64_mergeRound(h64, v3); h64 = XXH64_mergeRound(h64, v4); } else { h64 = state->v3 /*seed*/ + PRIME64_5; } h64 += (U64) state->total_len; return XXH64_finalize(h64, state->mem64, (size_t)state->total_len, endian, XXH_aligned); } XXH_PUBLIC_API unsigned long long XXH64_digest(const XXH64_state_t *state_in) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH64_digest_endian(state_in, XXH_littleEndian); else return XXH64_digest_endian(state_in, XXH_bigEndian); } /*====== Canonical representation ======*/ XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t *dst, XXH64_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); memcpy(dst, &hash, sizeof(*dst)); } XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t *src) { return XXH_readBE64(src); } #endif /* XXH_NO_LONG_LONG */ QATzip-1.2.0/src/xxhash.h000066400000000000000000000342101456106226300151320ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ /*************************************************************************** * xxHash - Fast Hash algorithm * Copyright (C) 2012-2016, Yann Collet * * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at : * - xxHash homepage: http://www.xxhash.com * - xxHash source repository : https://github.com/Cyan4973/xxHash ***************************************************************************/ #ifndef XXHASH_H_5627135585666179 #define XXHASH_H_5627135585666179 1 #if defined (__cplusplus) extern "C" { #endif /* **************************** * Definitions ******************************/ #include /* size_t */ typedef enum { XXH_OK = 0, XXH_ERROR } XXH_errorcode; /* **************************** * API modifier ******************************/ /** XXH_INLINE_ALL (and XXH_PRIVATE_API) * This is useful to include xxhash functions in `static` mode * in order to inline them, and remove their symbol from the public list. * Inlining can offer dramatic performance improvement on small keys. * Methodology : * #define XXH_INLINE_ALL * #include "xxhash.h" * `xxhash.c` is automatically included. * It's not useful to compile and link it as a separate module. */ #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) # ifndef XXH_STATIC_LINKING_ONLY # define XXH_STATIC_LINKING_ONLY # endif # if defined(__GNUC__) # define XXH_PUBLIC_API static __inline __attribute__((unused)) # elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # define XXH_PUBLIC_API static inline # elif defined(_MSC_VER) # define XXH_PUBLIC_API static __inline # else /* this version may generate warnings for unused static functions */ # define XXH_PUBLIC_API static # endif #else # define XXH_PUBLIC_API /* do nothing */ #endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ /*! XXH_NAMESPACE, aka Namespace Emulation : * * If you want to include _and expose_ xxHash functions from within your own library, * but also want to avoid symbol collisions with other libraries which may also include xxHash, * * you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library * with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values). * * Note that no change is required within the calling program as long as it includes `xxhash.h` : * regular symbol name will be automatically translated by this header. */ #ifdef XXH_NAMESPACE # define XXH_CAT(A,B) A##B # define XXH_NAME2(A,B) XXH_CAT(A,B) # define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) # define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) # define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) # define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) # define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) # define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) # define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) # define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) # define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) # define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) # define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) # define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) # define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) # define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) # define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) # define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) # define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) # define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) # define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) #endif /* ************************************* * Version ***************************************/ #define XXH_VERSION_MAJOR 0 #define XXH_VERSION_MINOR 6 #define XXH_VERSION_RELEASE 5 #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) XXH_PUBLIC_API unsigned XXH_versionNumber(void); /*-********************************************************************** * 32-bit hash ************************************************************************/ typedef unsigned int XXH32_hash_t; /*! XXH32() : Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input". The memory between input & input+length must be valid (allocated and read-accessible). "seed" can be used to alter the result predictably. Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */ XXH_PUBLIC_API XXH32_hash_t XXH32(const void *input, size_t length, unsigned int seed); /*====== Streaming ======*/ typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ XXH_PUBLIC_API XXH32_state_t *XXH32_createState(void); XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t *statePtr); XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t *dst_state, const XXH32_state_t *src_state); XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t *statePtr, unsigned int seed); XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t *statePtr, const void *input, size_t length); XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t *statePtr); /* * Streaming functions generate the xxHash of an input provided in multiple segments. * Note that, for small input, they are slower than single-call functions, due to state management. * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. * * XXH state must first be allocated, using XXH*_createState() . * * Start a new hash by initializing state with a seed, using XXH*_reset(). * * Then, feed the hash state by calling XXH*_update() as many times as necessary. * The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. * * Finally, a hash value can be produced anytime, by using XXH*_digest(). * This function returns the nn-bits hash as an int or long long. * * It's still possible to continue inserting input into the hash state after a digest, * and generate some new hashes later on, by calling again XXH*_digest(). * * When done, free XXH state space if it was allocated dynamically. */ /*====== Canonical representation ======*/ typedef struct { unsigned char digest[4]; } XXH32_canonical_t; XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t *dst, XXH32_hash_t hash); XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t *src); /* Default result type for XXH functions are primitive unsigned 32 and 64 bits. * The canonical representation uses human-readable write convention, aka big-endian (large digits first). * These functions allow transformation of hash result into and from its canonical format. * This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. */ #ifndef XXH_NO_LONG_LONG /*-********************************************************************** * 64-bit hash ************************************************************************/ typedef unsigned long long XXH64_hash_t; /*! XXH64() : Calculate the 64-bit hash of sequence of length "len" stored at memory address "input". "seed" can be used to alter the result predictably. This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark). */ XXH_PUBLIC_API XXH64_hash_t XXH64(const void *input, size_t length, unsigned long long seed); /*====== Streaming ======*/ typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ XXH_PUBLIC_API XXH64_state_t *XXH64_createState(void); XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t *statePtr); XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t *dst_state, const XXH64_state_t *src_state); XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t *statePtr, unsigned long long seed); XXH_PUBLIC_API XXH_errorcode XXH64_update(XXH64_state_t *statePtr, const void *input, size_t length); XXH_PUBLIC_API XXH64_hash_t XXH64_digest(const XXH64_state_t *statePtr); /*====== Canonical representation ======*/ typedef struct { unsigned char digest[8]; } XXH64_canonical_t; XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t *dst, XXH64_hash_t hash); XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t *src); #endif /* XXH_NO_LONG_LONG */ #ifdef XXH_STATIC_LINKING_ONLY /* ================================================================================================ This section contains declarations which are not guaranteed to remain stable. They may change in future versions, becoming incompatible with a different version of the library. These declarations should only be used with static linking. Never use them in association with dynamic linking ! =================================================================================================== */ /* These definitions are only present to allow * static allocation of XXH state, on stack or in a struct for example. * Never **ever** use members directly. */ #if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # include struct XXH32_state_s { uint32_t total_len_32; uint32_t large_len; uint32_t v1; uint32_t v2; uint32_t v3; uint32_t v4; uint32_t mem32[4]; uint32_t memsize; uint32_t reserved; /* never read nor write, might be removed in a future version */ }; /* typedef'd to XXH32_state_t */ struct XXH64_state_s { uint64_t total_len; uint64_t v1; uint64_t v2; uint64_t v3; uint64_t v4; uint64_t mem64[4]; uint32_t memsize; uint32_t reserved[2]; /* never read nor write, might be removed in a future version */ }; /* typedef'd to XXH64_state_t */ # else struct XXH32_state_s { unsigned total_len_32; unsigned large_len; unsigned v1; unsigned v2; unsigned v3; unsigned v4; unsigned mem32[4]; unsigned memsize; unsigned reserved; /* never read nor write, might be removed in a future version */ }; /* typedef'd to XXH32_state_t */ # ifndef XXH_NO_LONG_LONG /* remove 64-bit support */ struct XXH64_state_s { unsigned long long total_len; unsigned long long v1; unsigned long long v2; unsigned long long v3; unsigned long long v4; unsigned long long mem64[4]; unsigned memsize; unsigned reserved[2]; /* never read nor write, might be removed in a future version */ }; /* typedef'd to XXH64_state_t */ # endif # endif #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) # include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */ #endif #endif /* XXH_STATIC_LINKING_ONLY */ #if defined (__cplusplus) } #endif #endif /* XXHASH_H_5627135585666179 */ QATzip-1.2.0/test/000077500000000000000000000000001456106226300136465ustar00rootroot00000000000000QATzip-1.2.0/test/Makefile.am000066400000000000000000000051531456106226300157060ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ noinst_PROGRAMS = bt bin_PROGRAMS = qatzip-test qatzip_test_SOURCES = main.c qatzip_test_CFLAGS = \ -I$(abs_top_srcdir)/include/ \ -I$(abs_top_srcdir)/src/ \ -I$(abs_top_srcdir)/utils/ \ $(COMMON_CFLAGS) \ $(ICP_INCLUDE_CFLAGS) qatzip_test_LDADD = \ $(abs_top_srcdir)/src/.libs/libqatzip.a \ $(QATLIB_FLAGS) \ $(USDMLIB_FLAGS) qatzip_test_LDFLAGS = \ $(ICP_LDFLAGS) bt_SOURCES = bt.c bt_CFLAGS = \ -I$(abs_top_srcdir)/include/ \ -I$(abs_top_srcdir)/src/ \ -I$(abs_top_srcdir)/utils/ \ $(COMMON_CFLAGS) \ $(ICP_INCLUDE_CFLAGS) bt_LDADD = \ $(abs_top_srcdir)/src/.libs/libqatzip.a \ $(QATLIB_FLAGS) \ $(USDMLIB_FLAGS) bt_LDFLAGS = \ $(ICP_LDFLAGS) QATzip-1.2.0/test/bt.c000077500000000000000000000136631456106226300144330ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #include #include #include #include #include "qatzip.h" #define DEFAULT_BUF_LEN (256*1024) void usage() { printf("-f fit decompress buffers to size (default full buffers)\n"); printf("-s skip specific number of bytes\n"); printf("-S start test at specific position of source buffer\n"); printf("-E finish test at specific position of source buffer\n"); printf("-c corpus flag for data in source buffer: 0 - iterative, 1 - random, 2 - 'A'\n"); return; } int main(int argc, char *argv[]) { unsigned int i, j, rc, d_len, s_len, s2_len, src_sz, dest_sz; unsigned char *src, *dest, *src2; QzSession_T sess = {0}; int c; int fit = 0; int start = 1; int skip = 1; int end = DEFAULT_BUF_LEN; int corpus = 0; // 0 = iterative, 1 = random srand((time(NULL) & 0xffffffff)); while ((c = getopt(argc, argv, "fS:s:E:c:")) != -1) { switch (c) { case 'f': fit = 1; break; case 's': skip = atoi(optarg); if (skip <= 1) { usage(); return -1; } printf("Will skip by %d\n", skip); break; case 'S': start = atoi(optarg); printf("Will start at %d\n", start); break; case 'E': end = atoi(optarg); printf("Will end at %d\n", end); break; case 'c': corpus = atoi(optarg); printf("corpus = "); if (corpus == 0) { printf("iterative\n"); } else if (corpus == 1) { printf("randon\n"); } if (corpus == 2) { printf("\"A\"\n"); } break; default: usage(); return -1; } } src_sz = DEFAULT_BUF_LEN; dest_sz = (9 * src_sz / 8) + 1024; src = qzMalloc(src_sz, 0, 1); dest = qzMalloc(dest_sz, 0, 1); src2 = qzMalloc(src_sz, 0, 1); if (NULL == src || NULL == dest || NULL == src2) { return -1; } i = DEFAULT_BUF_LEN; if (corpus == 0) { for (j = 0; j < i; j++) { src[j] = (char)(j % 200); } } else if (corpus == 1) { for (j = 0; j < i; j++) { src[j] = (char)rand() % 255; } } else { for (j = 0; j < i; j++) { src[j] = (char)'A'; } } printf("src = 0x%lx, src2 = 0x%lx, dest = 0x%lx\n", (long unsigned int)src, (long unsigned int)src2, (long unsigned int)dest); printf("fit = %d\n", fit); for (i = start; i < end; i += skip) { s_len = i; d_len = dest_sz; rc = qzCompress(&sess, src, &s_len, dest, &d_len, 1); // printf( "rc = %d, src = %d, dest = %d\n", // rc, s_len, d_len ); if (rc == 0) { if (1 == fit) { s2_len = s_len; } else { s2_len = DEFAULT_BUF_LEN; } rc = qzDecompress(&sess, dest, &d_len, src2, &s2_len); // printf( "rc2 = %d, src = %d, dest = %d\n", // rc2, d_len, s2_len ); if (rc == 0) { if (s2_len != s_len) { printf("mismatch orig\t%d\tcomp %d\tdec %d\t %d\n", s_len, d_len, s2_len, (s_len - s2_len)); printf("\t\t%d\t%d\t%d\n", (s_len % (64 * 1024)), (d_len % (64 * 1024)), (s2_len % (64 * 1024))); goto error; } if (memcmp(src, src2, s_len) != 0) { printf("memcmp mismatch - len = %d\t%d\n", s_len, (s_len % (64 * 1024))); goto error; } } else { printf("return from decomress is %d\t len = %d\t%d\n", rc, s_len, (s_len % (64 * 1024))); goto error; } } else { goto error; } } return 0; error: qzTeardownSession(&sess); qzFree(src); qzFree(dest); qzFree(src2); return rc; } QATzip-1.2.0/test/code_format_tests/000077500000000000000000000000001456106226300173525ustar00rootroot00000000000000QATzip-1.2.0/test/code_format_tests/astylerc000066400000000000000000000045661456106226300211360ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ # Bracket Style style=kr --keep-one-line-blocks # K&R brackets # Indentation indent=spaces # 4 white space min-conditional-indent=0 # Padding unpad-paren # Remove all spaces with parens that aren't requested below pad-oper # Put spaces around operators pad-header # Put spaces between if/while/for etc. and the first paren # Pointers align-pointer=name # Align the * next to the variable name # Line wrapping max-code-length=80 # 80 character line limit break-after-logical # For if statements, wrap to the next line after logical operator # Line endings lineend=linux # LF line endings # General options suffix=none formatted QATzip-1.2.0/test/code_format_tests/format.sh000077500000000000000000000047271456106226300212130ustar00rootroot00000000000000#!/usr/bin/bash ################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ # exit on errors set -e : ${QZ_ROOT?} readonly BASEDIR=$(readlink -f $(dirname $0)) declare -i rc=0 rm -f $BASEDIR/astyle.log if hash astyle; then echo -n "Checking coding style..." find $QZ_ROOT -iregex '.*\.[ch]' | \ xargs astyle --options=$BASEDIR/astylerc | \ tee -a $BASEDIR/astyle.log if grep -q "^Formatted" $BASEDIR/astyle.log; then echo -e "ERRORS detected\n" grep --color=auto "^Formatted.*" $BASEDIR/astyle.log echo "Incorrect code style detected in one or more files." echo "The files have been automatically formatted." rc=1 else echo " OK" fi else echo "You do not have astyle installed so your code style is not being checked!" rc=2 fi exit $rc QATzip-1.2.0/test/main.c000077500000000000000000004240051456106226300147460ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #define _POSIX_C_SOURCE 200112L #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include /* QAT headers */ #ifdef HAVE_QAT_HEADERS #include #include #include #else #include #include #include #endif #include #include #include #include #define QZ_FMT_NAME "QZ" #define GZIP_FMT_NAME "GZIP" #define MAX_FMT_NAME 8 #define MAX_NUMA_NODE 8 #define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0])) #define KB (1024) #define MB (KB * KB) /* According to different platforms, * instance total = instance on each device * num of device */ #define G_PROCESS_NUM_INSTANCES_4 4 /* instance=4 * device=1 */ #define G_PROCESS_NUM_INSTANCES_8 8 /* instance=1 * device=8 */ #define G_PROCESS_NUM_INSTANCES_12 12 /* instance=4 * device=3 */ #define G_PROCESS_NUM_INSTANCES_16 16 /* instance=4 * device=4 */ #define G_PROCESS_NUM_INSTANCES_32 32 /* instance=4 * device=8 */ #define G_PROCESS_NUM_INSTANCES_64 64 /* instance=4 * device=16 */ #define MAX_HUGEPAGE_FILE "/sys/module/usdm_drv/parameters/max_huge_pages" #define QZ_INIT_HW_FAIL(rc) (QZ_DUPLICATE != rc && \ (QZ_OK != rc || \ QZ_NO_HW == g_process.qz_init_status)) #if CPA_DC_API_VERSION_AT_LEAST(3, 1) #define COMP_LVL_MAXIMUM QZ_LZS_COMP_LVL_MAXIMUM #else #define COMP_LVL_MAXIMUM QZ_DEFLATE_COMP_LVL_MAXIMUM #endif typedef void *(QzThdOps)(void *); typedef enum { UNKNOWN, QZ, GZIP, FMT_NUM } QzFormatId_T; typedef struct QzFormat_S { char fmt_name[MAX_FMT_NAME]; QzFormatId_T fmt; } QzFormat_T; QzFormat_T g_format_list[] = { {QZ_FMT_NAME, QZ}, {GZIP_FMT_NAME, GZIP} }; typedef struct QzBlock_S { QzFormatId_T fmt; unsigned int size; struct QzBlock_S *next; } QzBlock_T; typedef enum { COMP = 0, DECOMP, BOTH } ServiceType_T; typedef enum { TEST_DEFLATE = 0, TEST_GZIP, TEST_GZIPEXT, TEST_DEFLATE_4B, TEST_LZ4, TEST_LZ4S } TEST_FORMAT_T; typedef struct CPUCore_S { int seq; int used; } CPUCore_T; typedef struct NUMANode_S { int num_cores; CPUCore_T *core; } NUMANode_T; typedef struct { long thd_id; ServiceType_T service; int count; int verify_data; int debug; size_t src_sz; size_t comp_out_sz; size_t decomp_out_sz; int max_forks; unsigned char *src; unsigned char *comp_out; unsigned char *decomp_out; int gen_data; int comp_algorithm; int sw_backup; int hw_buff_sz; int comp_lvl; int req_cnt_thrshold; int huffman_hdr; QzPollingMode_T polling_mode; TEST_FORMAT_T test_format; QzThdOps *ops; QzBlock_T *blks; int init_engine_disabled; int init_sess_disabled; int thread_sleep; int block_size; } TestArg_T; const unsigned int USDM_ALLOC_MAX_SZ = (2 * MB - 5 * KB); const unsigned int DEFAULT_STREAM_BUF_SZ = 256 * KB; const unsigned int QATZIP_MAX_HW_SZ = 512 * KB; const unsigned int MAX_HUGE_PAGE_SZ = 2 * MB; static pthread_mutex_t g_lock_print = PTHREAD_MUTEX_INITIALIZER; #ifndef ENABLE_THREAD_BARRIER static pthread_mutex_t g_cond_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t g_ready_cond = PTHREAD_COND_INITIALIZER; static pthread_cond_t g_start_cond = PTHREAD_COND_INITIALIZER; static int g_ready_to_start; static int g_ready_thread_count; #else static pthread_barrier_t g_bar; #endif char *g_input_file_name = NULL; static bool g_perf_svm = false; static struct timeval g_timers[100][100]; static struct timeval g_timer_start; extern void dumpAllCounters(); static int test_thread_safe_flag = 0; extern processData_T g_process; extern int errno; QzBlock_T *parseFormatOption(char *buf) { char *str = buf, *sub_str = NULL; char *delim = "/", *sub_delim = ":"; char *token, *sub_token; char *saveptr, *sub_saveptr; int i, j, fmt_idx; unsigned int fmt_found = 0; QzBlock_T *blk = NULL; QzBlock_T *head, *prev, *r; unsigned int list_len = sizeof(g_format_list) / sizeof(QzFormat_T); head = malloc(sizeof(QzBlock_T)); assert(NULL != head); head->next = NULL; prev = head; for (i = 1; ; i++, str = NULL) { token = strtok_r(str, delim, &saveptr); if (NULL == token) { break; } QZ_DEBUG("String[%d]: %s\n", i, token); fmt_found = 0; blk = NULL; for (j = 1, sub_str = token; ; j++, sub_str = NULL) { sub_token = strtok_r(sub_str, sub_delim, &sub_saveptr); if (NULL == sub_token) { break; } QZ_DEBUG(" -[%d]-> %s\n", j, sub_token); if (fmt_found) { blk->size = atoi(sub_token); break; } char *tmp = sub_token; while (*tmp) { *tmp = GET_LOWER_8BITS(toupper(*tmp)); tmp++; } for (fmt_idx = 0; fmt_idx < list_len; fmt_idx++) { if (0 == strcmp(sub_token, g_format_list[fmt_idx].fmt_name)) { blk = malloc(sizeof(QzBlock_T)); assert(NULL != blk); blk->fmt = g_format_list[fmt_idx].fmt; blk->next = NULL; prev->next = blk; fmt_found = 1; break; } } } if (NULL != blk) { prev = blk; } } blk = head->next; i = 1; while (blk) { QZ_PRINT("[INFO] Block%d: format -%8s, \tsize - %d\n", i++, g_format_list[blk->fmt - 1].fmt_name, blk->size); blk = blk->next; } if (NULL == head->next) { r = head->next; free(head); } else { r = head; } return r; } static void genRandomData(uint8_t *data, size_t size) { size_t i, j; char c; uint8_t *ptr = data; while (ptr < (data + size)) { j = rand() % 100; c = GET_LOWER_8BITS((rand() % 65 + 90)); for (i = (size_t)0; i < j; i++) { *ptr = c; ptr++; if (ptr >= (data + size)) { break; } } } } static void sigInt(int sig) { dumpAllCounters(); _exit(1); } static void timeCheck(int i, long tid) { gettimeofday(&g_timers[i][tid], NULL); } #ifdef TESTMAIN_DUMP_TIMERS static void dumpTimers(int tid) { int i; unsigned long long start, local, diff; start = (g_timer_start.tv_sec * 1000000) + g_timer_start.tv_usec; if (0 == tid) { QZ_PRINT("[ts]: %lld\n", start); } QZ_PRINT("[%5.5d]", tid); for (i = 0; i < 15; i++) { local = (g_timers[i][tid].tv_sec * 1000000) + g_timers[i][tid].tv_usec; if (local > 0) { diff = local - start; QZ_PRINT(" %lld", diff); } else { QZ_PRINT(" -"); } } QZ_PRINT("\n"); } #endif static void dumpInputData(size_t size, uint8_t *data) { int fd; ssize_t ulen; char temp_file[] = "QATZip_Input_XXXXXX"; if (0 == size || NULL == data) return; fd = mkstemp(temp_file); if (-1 == fd) { QZ_ERROR("Creat dump file Failed\n"); return; } ulen = write(fd, data, size); if (ulen != (ssize_t) size) { QZ_ERROR("Creat dump file Failed\n"); return; } close(fd); } static void dumpOutputData(size_t size, uint8_t *data, char *filename) { int fd = 0; ssize_t ulen; char *output_filename = NULL; char tmp_filename[] = "QATZip_Output_XXXXXX.gz"; const unsigned int suffix_len = 3; if (0 == size || NULL == data) return; if (NULL == filename) { output_filename = tmp_filename; } else { output_filename = filename; } if (NULL == filename) { fd = mkstemps(output_filename, suffix_len); } else { fd = open(output_filename, O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); } if (-1 == fd) { QZ_ERROR("Creat dump file Failed\n"); goto done; } ulen = write(fd, data, size); if (ulen != (ssize_t) size) { QZ_ERROR("Creat dump file Failed\n"); goto done; } done: if (fd >= 0) { close(fd); } } static void dumpDecompressedData(size_t size, uint8_t *data, char *filename) { int fd = 0; ssize_t ulen; char *filename_ptr = NULL; char *output_filename = NULL; unsigned int filename_len = 0; const char *suffix = ".decomp"; const unsigned int suffix_len = strlen(suffix); if (0 == size || NULL == data || NULL == filename) return; filename_len = strlen(filename); filename_ptr = filename; filename_len = (filename_len + suffix_len + 1 + 7) / 8 * 8; output_filename = (char *) calloc(1, filename_len); if (NULL == output_filename) { QZ_ERROR("Creat dump file Failed\n"); goto done; } snprintf(output_filename, filename_len, "%s%s", filename_ptr, suffix); fd = open(output_filename, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IRGRP | S_IROTH); if (-1 == fd) { QZ_ERROR("Creat dump file Failed\n"); goto done; } ulen = write(fd, data, size); if (ulen != (ssize_t) size) { QZ_ERROR("Creat dump file Failed\n"); goto done; } done: free(output_filename); if (fd >= 0) { close(fd); } } int qzSetupDeflate(QzSession_T *sess, TestArg_T *arg) { int status; QzSessionParamsDeflate_T params; status = qzGetDefaultsDeflate(¶ms); if (status < 0) { QZ_ERROR("Get defaults params error with error: %d\n", status); return QZ_FAIL; } switch (arg->test_format) { case TEST_DEFLATE: params.data_fmt = QZ_DEFLATE_RAW; break; case TEST_GZIP: params.data_fmt = QZ_DEFLATE_GZIP; break; case TEST_GZIPEXT: params.data_fmt = QZ_DEFLATE_GZIP_EXT; break; case TEST_DEFLATE_4B: params.data_fmt = QZ_DEFLATE_4B; break; default: QZ_ERROR("Unsupported data format\n"); return QZ_FAIL; } params.huffman_hdr = arg->huffman_hdr; params.common_params.comp_lvl = arg->comp_lvl; params.common_params.comp_algorithm = arg->comp_algorithm; params.common_params.hw_buff_sz = arg->hw_buff_sz; params.common_params.polling_mode = arg->polling_mode; params.common_params.req_cnt_thrshold = arg->req_cnt_thrshold; params.common_params.max_forks = arg->max_forks; params.common_params.sw_backup = arg->sw_backup; status = qzSetupSessionDeflate(sess, ¶ms); if (status < 0) { QZ_ERROR("Session setup failed with error: %d\n", status); return QZ_FAIL; } return QZ_OK; } int qzSetupLZ4(QzSession_T *sess, TestArg_T *arg) { int status; QzSessionParamsLZ4_T params; status = qzGetDefaultsLZ4(¶ms); if (status < 0) { QZ_ERROR("Get defaults params error with error: %d\n", status); return QZ_FAIL; } params.common_params.comp_lvl = arg->comp_lvl; params.common_params.comp_algorithm = arg->comp_algorithm; params.common_params.hw_buff_sz = arg->hw_buff_sz; params.common_params.polling_mode = arg->polling_mode; params.common_params.req_cnt_thrshold = arg->req_cnt_thrshold; params.common_params.max_forks = arg->max_forks; params.common_params.sw_backup = arg->sw_backup; status = qzSetupSessionLZ4(sess, ¶ms); if (status) { QZ_ERROR("Session setup failed with error: %d\n", status); return QZ_FAIL; } return QZ_OK; } int qzSetupLZ4S(QzSession_T *sess, TestArg_T *arg) { int status; QzSessionParamsLZ4S_T params; status = qzGetDefaultsLZ4S(¶ms); if (status < 0) { QZ_ERROR("Get defaults params error with error: %d\n", status); return QZ_FAIL; } params.common_params.comp_lvl = arg->comp_lvl; params.common_params.comp_algorithm = arg->comp_algorithm; params.common_params.hw_buff_sz = arg->hw_buff_sz; params.common_params.polling_mode = arg->polling_mode; params.common_params.req_cnt_thrshold = arg->req_cnt_thrshold; params.common_params.max_forks = arg->max_forks; params.common_params.sw_backup = arg->sw_backup; status = qzSetupSessionLZ4S(sess, ¶ms); if (status) { QZ_ERROR("Session setup failed with error: %d\n", status); return QZ_FAIL; } return QZ_OK; } int qzInitSetupsession(QzSession_T *sess, TestArg_T *arg) { int rc = QZ_OK; if (!((TestArg_T *)arg)->init_engine_disabled) { rc = qzInit(sess, arg->sw_backup); if (QZ_INIT_FAIL(rc)) { return rc; } } if (!((TestArg_T *)arg)->init_sess_disabled) { switch (arg->test_format) { case TEST_DEFLATE: case TEST_GZIP: case TEST_GZIPEXT: rc = qzSetupDeflate(sess, arg); break; case TEST_LZ4: rc = qzSetupLZ4(sess, arg); break; case TEST_LZ4S: rc = qzSetupLZ4S(sess, arg); break; default: QZ_ERROR("Unsupported data format\n"); return QZ_FAIL; } if (QZ_SETUP_SESSION_FAIL(rc)) { return rc; } } return rc; } void *qzDecompressSwQz(void *arg) { int rc, k; unsigned char *src = NULL, *comp_out = NULL; unsigned char *decomp_sw_out = NULL, *decomp_qz_out = NULL; size_t src_sz, comp_out_sz, decomp_sw_out_sz, decomp_qz_out_sz; struct timeval ts, te; unsigned long long ts_m, te_m, el_m; long double sec, rate; const size_t org_src_sz = ((TestArg_T *)arg)->src_sz; const size_t org_comp_out_sz = ((TestArg_T *)arg)->comp_out_sz; const long tid = ((TestArg_T *)arg)->thd_id; const int verify_data = 1; const int count = ((TestArg_T *)arg)->count; QzSession_T sess = {0}; QzSessionParams_T cus_params = {0}; if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } src_sz = org_src_sz; comp_out_sz = org_comp_out_sz; decomp_sw_out_sz = org_src_sz; decomp_qz_out_sz = org_src_sz; QZ_DEBUG("Hello from qzDecompressSwQz tid=%ld, count=%d, service=2, " "verify_data=%d\n", tid, count, verify_data); src = qzMalloc(src_sz, 0, PINNED_MEM); comp_out = qzMalloc(comp_out_sz, 0, PINNED_MEM); decomp_sw_out = qzMalloc(decomp_sw_out_sz, 0, PINNED_MEM); decomp_qz_out = qzMalloc(decomp_qz_out_sz, 0, PINNED_MEM); if (!src || !comp_out || !decomp_sw_out || !decomp_qz_out) { QZ_ERROR("Malloc failed\n"); goto done; } el_m = 0; QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); // Start the testing for (k = 0; k < count; k++) { (void)gettimeofday(&ts, NULL); comp_out_sz = org_src_sz; //Compress 1st { //Set default hwBufferSize to 64KB cus_params.hw_buff_sz = 64 * 1024; if (qzSetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect hw_buff_sz %d.\n", cus_params.hw_buff_sz); goto done; } QZ_DEBUG("thread %ld before Compressed %lu bytes into %lu\n", tid, src_sz, comp_out_sz); unsigned int last = 0; rc = qzCompress(&sess, src, (uint32_t *)(&src_sz), comp_out, (uint32_t *)(&comp_out_sz), last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); goto done; } if (src_sz != org_src_sz) { QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, org_src_sz); goto done; } QZ_DEBUG("thread %ld after Compressed %lu bytes into %lu\n", tid, src_sz, comp_out_sz); qzTeardownSession(&sess); } //Decompress SW { cus_params.hw_buff_sz = 32 * 1024; //32KB if (qzSetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect hw_buff_sz %u.\n", cus_params.hw_buff_sz); goto done; } QZ_DEBUG("thread %ld before Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_sw_out_sz); qzSetupSession(&sess, NULL); unsigned int tmp_comp_out_sz = GET_LOWER_32BITS(comp_out_sz); rc = qzDecompress(&sess, comp_out, (uint32_t *)(&tmp_comp_out_sz), decomp_sw_out, (uint32_t *)(&decomp_sw_out_sz)); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); goto done; } if (decomp_sw_out_sz != org_src_sz) { QZ_ERROR("ERROR: After Decompression decomp_out_sz: %lu != org_src_sz: %lu\n!", decomp_sw_out_sz, org_src_sz); goto done; } QZ_DEBUG("thread %ld after SW Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_sw_out_sz); qzTeardownSession(&sess); } //Decompress QAT { //Reset default hwBufferSize to 64KB cus_params.hw_buff_sz = 64 * 1024; if (qzSetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect hw_buff_sz %u.\n", cus_params.hw_buff_sz); goto done; } QZ_DEBUG("thread %ld before Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_qz_out_sz); qzSetupSession(&sess, NULL); unsigned int tmp_comp_out_sz = GET_LOWER_32BITS(comp_out_sz); rc = qzDecompress(&sess, comp_out, (uint32_t *)&tmp_comp_out_sz, decomp_qz_out, (uint32_t *)(&decomp_qz_out_sz)); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); goto done; } if (decomp_qz_out_sz != org_src_sz) { QZ_ERROR("ERROR: After Decompression decomp_out_sz: %lu != org_src_sz: %lu \n!", decomp_qz_out_sz, org_src_sz); goto done; } QZ_DEBUG("thread %ld after QZ Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_qz_out_sz); qzTeardownSession(&sess); } (void)gettimeofday(&te, NULL); { QZ_DEBUG("verify data..\n"); if (memcmp(src, decomp_sw_out, org_src_sz)) { QZ_ERROR("ERROR: SW Decompression FAILED on thread %ld with size: %lu \n!", tid, src_sz); goto done; } if (memcmp(src, decomp_qz_out, org_src_sz)) { QZ_ERROR("ERROR: QZip Decompression FAILED on thread %ld with size: %lu \n!", tid, src_sz); goto done; } QZ_DEBUG("reset data..\n"); memset(comp_out, 0, comp_out_sz); memset(decomp_sw_out, 0, decomp_sw_out_sz); memset(decomp_qz_out, 0, decomp_qz_out_sz); } ts_m = (ts.tv_sec * 1000000) + ts.tv_usec; te_m = (te.tv_sec * 1000000) + te.tv_usec; el_m += te_m - ts_m; } sec = (long double)(el_m); sec = sec / 1000000.0; rate = org_src_sz * 8;// bits rate *= 2; rate /= 1024; rate *= count; rate /= 1024 * 1024; // gigbits rate /= sec;// Gbps rc = pthread_mutex_lock(&g_lock_print); assert(0 == rc); QZ_PRINT("[INFO] srv=BOTH, tid=%ld, verify=%d, count=%d, msec=%llu, " "bytes=%lu, %Lf Gbps", tid, verify_data, count, el_m, org_src_sz, rate); QZ_PRINT(", input_len=%lu, comp_len=%lu, ratio=%f%%", org_src_sz, comp_out_sz, ((double)comp_out_sz / (double)org_src_sz) * 100); QZ_PRINT(", comp_len=%lu, sw_decomp_len=%lu", comp_out_sz, decomp_sw_out_sz); QZ_PRINT(", comp_len=%lu, qz_decomp_len=%lu", comp_out_sz, decomp_qz_out_sz); QZ_PRINT("\n"); rc = pthread_mutex_unlock(&g_lock_print); assert(0 == rc); done: qzFree(src); qzFree(comp_out); qzFree(decomp_sw_out); qzFree(decomp_qz_out); (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzCompressDecompressWithFormatOption(void *arg) { int rc = 0, k; unsigned char *src, *comp_out, *decomp_out; size_t src_sz, comp_out_sz, decomp_out_sz; struct timeval ts, te; unsigned long long ts_m, te_m, el_m; long double sec, rate; const size_t org_src_sz = ((TestArg_T *)arg)->src_sz; const size_t org_comp_out_sz = ((TestArg_T *)arg)->comp_out_sz; const long tid = ((TestArg_T *)arg)->thd_id; const int verify_data = 1; const int count = ((TestArg_T *)arg)->count; const int gen_data = ((TestArg_T *)arg)->gen_data; QzBlock_T *head, *blk; QzSession_T sess = {0}; if (!org_src_sz) { pthread_exit((void *)"input size is 0"); } head = ((TestArg_T *)arg)->blks; if (head == NULL) { pthread_exit((void *)"No Input -F options or phrase options failed\n"); } blk = head->next; if (blk == NULL) { pthread_exit((void *)"No Input -F options or phrase options failed\n"); } src_sz = org_src_sz; comp_out_sz = org_comp_out_sz; decomp_out_sz = org_src_sz; QZ_DEBUG("Hello from qzCompressDecompressWithFormatOption tid=%ld, count=%d, service=2, " "verify_data=%d\n", tid, count, verify_data); rc = qzInitSetupsession(&sess, (TestArg_T *)arg); if (rc != QZ_OK) { #ifndef ENABLE_THREAD_BARRIER g_ready_thread_count++; pthread_cond_signal(&g_ready_cond); #endif pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInitSetupsession rc = %d\n", rc); if (gen_data) { src = qzMalloc(src_sz, 0, PINNED_MEM); comp_out = qzMalloc(comp_out_sz, 0, PINNED_MEM); decomp_out = qzMalloc(decomp_out_sz, 0, PINNED_MEM); } else { src = ((TestArg_T *)arg)->src; comp_out = ((TestArg_T *)arg)->comp_out; decomp_out = ((TestArg_T *)arg)->decomp_out; } if (!src || !comp_out || !decomp_out) { QZ_ERROR("Malloc failed\n"); goto done; } el_m = 0; if (gen_data) { QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); } // Start the testing for (k = 0; k < count; k++) { (void)gettimeofday(&ts, NULL); //Compress 1st { comp_out_sz = org_comp_out_sz; QZ_DEBUG("thread %ld before Compressed %lu bytes into %lu\n", tid, src_sz, comp_out_sz); unsigned int remaining = GET_LOWER_32BITS(src_sz), tmp_src_sz = 0, last = 0; unsigned int tmp_comp_out_sz = GET_LOWER_32BITS(comp_out_sz); unsigned int comp_available_out = GET_LOWER_32BITS(comp_out_sz); unsigned char *tmp_src = src, *tmp_comp_out = comp_out; comp_out_sz = (size_t)0; while (remaining) { if (remaining > blk->size) { tmp_src_sz = blk->size; last = 0; } else { tmp_src_sz = remaining; last = 1; } tmp_comp_out_sz = comp_available_out; if (QZ == blk->fmt) { rc = qzCompress(&sess, tmp_src, &tmp_src_sz, tmp_comp_out, &tmp_comp_out_sz, last); } else { rc = qzSWCompress(&sess, tmp_src, &tmp_src_sz, tmp_comp_out, &tmp_comp_out_sz, last); } tmp_src += tmp_src_sz; tmp_comp_out += tmp_comp_out_sz; comp_out_sz += tmp_comp_out_sz; comp_available_out -= tmp_comp_out_sz; remaining -= tmp_src_sz; QZ_DEBUG("[Thead%ld] Compress: format is %4s, remaining %u, tmp_src_sz is %u\n", tid, g_format_list[blk->fmt - 1].fmt_name, remaining, tmp_src_sz); blk = (blk->next) ? blk->next : head->next; } if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); goto done; } if (src_sz != org_src_sz) { QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu\n!", src_sz, org_src_sz); goto done; } QZ_DEBUG("thread %ld after Compressed %lu bytes into %lu\n", tid, src_sz, comp_out_sz); } //Decompress { QZ_DEBUG("thread %ld before Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_out_sz); unsigned int remaining = GET_LOWER_32BITS(comp_out_sz); unsigned int decomp_available_out = GET_LOWER_32BITS(decomp_out_sz); unsigned char *tmp_comp_out = comp_out, *tmp_decomp_out = decomp_out; unsigned int tmp_comp_out_sz, tmp_decomp_out_sz, decomp_out_sz = 0; while (remaining) { tmp_comp_out_sz = remaining; tmp_decomp_out_sz = decomp_available_out; rc = qzDecompress(&sess, tmp_comp_out, &tmp_comp_out_sz, tmp_decomp_out, &tmp_decomp_out_sz); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); goto done; } tmp_comp_out += tmp_comp_out_sz; tmp_decomp_out += tmp_decomp_out_sz; decomp_out_sz += tmp_decomp_out_sz; remaining -= tmp_comp_out_sz; decomp_available_out -= tmp_decomp_out_sz; QZ_DEBUG("[Thead%ld] Decompress: remaining %d, tmp_decomp_out_sz is %u\n", tid, remaining, tmp_decomp_out_sz); } if (decomp_out_sz != org_src_sz) { QZ_ERROR("ERROR: After Decompression decomp_out_sz: %u != org_src_sz: %lu \n!", decomp_out_sz, org_src_sz); goto done; } QZ_DEBUG("thread %ld after Decompressed %lu bytes into %u\n", tid, comp_out_sz, decomp_out_sz); } (void)gettimeofday(&te, NULL); QZ_DEBUG("verify data..\n"); if (memcmp(src, decomp_out, org_src_sz)) { QZ_ERROR("ERROR: Decompression FAILED on thread %ld with size: %lu \n!", tid, src_sz); goto done; } QZ_DEBUG("reset data..\n"); memset(comp_out, 0, (size_t)comp_out_sz); memset(decomp_out, 0, (size_t)decomp_out_sz); ts_m = (ts.tv_sec * 1000000) + ts.tv_usec; te_m = (te.tv_sec * 1000000) + te.tv_usec; el_m += te_m - ts_m; } sec = (long double)(el_m); sec = sec / 1000000.0; rate = org_src_sz * 8;// bits rate *= 2; rate /= 1024; rate *= count; rate /= 1024 * 1024; // gigbits rate /= sec;// Gbps rc = pthread_mutex_lock(&g_lock_print); assert(0 == rc); QZ_PRINT("[INFO] srv=BOTH, tid=%ld, verify=%d, count=%d, msec=%llu, " "bytes=%lu, %Lf Gbps", tid, verify_data, count, el_m, org_src_sz, rate); QZ_PRINT(", input_len=%lu, comp_len=%lu, ratio=%f%%", org_src_sz, comp_out_sz, ((double)comp_out_sz / (double)org_src_sz) * 100); QZ_PRINT(", comp_len=%lu, decomp_len=%lu", comp_out_sz, decomp_out_sz); QZ_PRINT("\n"); rc = pthread_mutex_unlock(&g_lock_print); assert(0 == rc); done: if (gen_data) { qzFree(src); qzFree(comp_out); qzFree(decomp_out); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzSetupParamFuncTest(void *arg) { QzSessionParams_T def_params = {0}; QzSessionParams_T new_params = {0}; QzSessionParams_T cus_params = {0}; unsigned char *src, *dest; size_t src_sz, dest_sz, test_dest_sz;; int rc; QzSession_T sess = {0}; src_sz = 256 * 1024; test_dest_sz = dest_sz = 256 * 1024 * 2; src = qzMalloc(src_sz, 0, COMMON_MEM); dest = qzMalloc(dest_sz, 0, COMMON_MEM); if (!src || !dest) { QZ_ERROR("Malloc failed\n"); return NULL; } if (qzGetDefaults(&def_params) != QZ_OK || qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } rc = qzInit(&sess, 0); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("Err: fail to init HW with ret: %d.\n", rc); goto end; } rc = qzSetupSession(&sess, &def_params); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("Err: fail to setup session with ret: %d\n", rc); goto end; } rc = qzCompress(&sess, src, (uint32_t *)(&src_sz), dest, (uint32_t *)(&test_dest_sz), 1); if (rc != QZ_OK) { QZ_ERROR("Err: fail to compress data with ret: %d\n", rc); goto end; } QZ_PRINT("With default params, input_len:%lu, output_len:%lu.\n", src_sz, test_dest_sz); test_dest_sz = dest_sz; // Negative Test cus_params.huffman_hdr = QZ_STATIC_HDR + 1; if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect huffman: %d.\n", cus_params.huffman_hdr); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } cus_params.direction = QZ_DIR_BOTH + 1; if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect direction: %d.\n", cus_params.direction); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } cus_params.comp_lvl = 0; if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect comp_level: %d.\n", cus_params.comp_lvl); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } cus_params.comp_lvl = (COMP_LVL_MAXIMUM + 1); if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect comp_level: %d.\n", cus_params.comp_lvl); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } cus_params.sw_backup = 2; if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect sw_backup: %d.\n", cus_params.sw_backup); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } cus_params.hw_buff_sz = 0; if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect hw_buff_sz %d.\n", cus_params.hw_buff_sz); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } cus_params.hw_buff_sz = 1025; if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect hw_buff_sz %d.\n", cus_params.hw_buff_sz); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } cus_params.hw_buff_sz = 2 * 1024 * 1024; //2M if (qzSetDefaults(&cus_params) != QZ_PARAMS) { QZ_ERROR("FAILED: set params should fail with incorrect hw_buff_sz %d.\n", cus_params.hw_buff_sz); goto end; } if (qzGetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } // Positive Test cus_params.huffman_hdr = (QZ_HUFF_HDR_DEFAULT == QZ_DYNAMIC_HDR) ? QZ_STATIC_HDR : QZ_DYNAMIC_HDR; if (qzSetDefaults(&cus_params) != QZ_OK) { QZ_ERROR("Err: fail to set default params.\n"); goto end; } if (qzGetDefaults(&new_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto end; } if (memcmp(&def_params, &new_params, sizeof(QzSessionParams_T)) == 0) { QZ_ERROR("Err: set default params fail.\n"); goto end; } if (memcmp(&cus_params, &new_params, sizeof(QzSessionParams_T)) != 0) { QZ_ERROR("Err: set default params fail with incorrect value.\n"); QZ_ERROR(" cus_params.huff(%d) != new_params.huff(%d).\n", cus_params.huffman_hdr, new_params.huffman_hdr); goto end; } rc = qzSetupSession(&sess, &new_params); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("Err: fail to setup session with ret: %d\n", rc); goto end; } rc = qzCompress(&sess, src, (uint32_t *)(&src_sz), dest, (uint32_t *)(&test_dest_sz), 1); if (rc != QZ_OK) { QZ_ERROR("Err: fail to compress data with ret: %d\n", rc); goto end; } QZ_ERROR("With custom params, input_len:%lu, output_len:%lu.\n", src_sz, test_dest_sz); end: qzFree(src); qzFree(dest); (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzCompressAndDecompress(void *arg) { int rc = -1, k; unsigned char *src, *comp_out, *decomp_out; int *compressed_blocks_sz = NULL; size_t src_sz, comp_out_sz, decomp_out_sz; size_t block_size, in_sz, out_sz, consumed, produced; size_t num_blocks; struct timeval ts, te; unsigned long long ts_m, te_m, el_m; long double sec, rate; const size_t org_src_sz = ((TestArg_T *)arg)->src_sz; const size_t org_comp_out_sz = ((TestArg_T *)arg)->comp_out_sz; const long tid = ((TestArg_T *)arg)->thd_id; const ServiceType_T service = ((TestArg_T *)arg)->service; const int verify_data = ((TestArg_T *)arg)->verify_data; const int count = ((TestArg_T *)arg)->count; const int gen_data = ((TestArg_T *)arg)->gen_data; int thread_sleep = ((TestArg_T *)arg)->thread_sleep; QzSession_T sess = {0}; if (!org_src_sz) { pthread_exit((void *)"input size is 0\n"); } src_sz = org_src_sz; comp_out_sz = org_comp_out_sz; decomp_out_sz = org_src_sz; QZ_DEBUG("Hello from qzCompressAndDecompress tid=%ld, count=%d, service=%d, " "verify_data=%d\n", tid, count, service, verify_data); rc = qzInitSetupsession(&sess, (TestArg_T *)arg); if (rc != QZ_OK && rc != QZ_DUPLICATE) { #ifndef ENABLE_THREAD_BARRIER g_ready_thread_count++; pthread_cond_signal(&g_ready_cond); #endif pthread_exit((void *)"qzInit failed"); } //timeCheck(3, tid); /* The sleep is for enabling the sw fallback in test. sw fallback simulate hang will happen when detect process generate the 'fatal events'. but detect will happen every seconds. The sleep will guarantee that test capture the 'fatal events' and fallback */ if (thread_sleep > 0) { usleep(thread_sleep); } QZ_DEBUG("qzInitSetupsession rc = %d\n", rc); if (gen_data && !g_perf_svm) { src = qzMalloc(src_sz, 0, PINNED_MEM); comp_out = qzMalloc(comp_out_sz, 0, PINNED_MEM); decomp_out = qzMalloc(decomp_out_sz, 0, PINNED_MEM); } else { src = g_perf_svm ? malloc(src_sz) : ((TestArg_T *)arg)->src; comp_out = g_perf_svm ? malloc(comp_out_sz) : ((TestArg_T *)arg)->comp_out; decomp_out = g_perf_svm ? malloc(decomp_out_sz) : ((TestArg_T *) arg)->decomp_out; } if (!src || !comp_out || !decomp_out) { QZ_ERROR("Malloc failed\n"); goto done; } if (g_perf_svm && g_input_file_name) { memcpy(src, ((TestArg_T *)arg)->src, src_sz); } el_m = 0; if (gen_data) { QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); } //timeCheck(4, tid); block_size = ((TestArg_T *)arg)->block_size; if (-1 == block_size) { block_size = src_sz; } num_blocks = src_sz / block_size + (src_sz % block_size ? 1 : 0); compressed_blocks_sz = malloc(sizeof(int) * num_blocks); if (NULL == compressed_blocks_sz) { QZ_ERROR("Malloc failed\n"); goto done; } memset(compressed_blocks_sz, 0, sizeof(int) * num_blocks); // Compress the data for testing if (DECOMP == service) { consumed = 0; produced = 0; for (int i = 0; i < num_blocks; i ++) { in_sz = block_size < (org_src_sz - consumed) ? block_size : (org_src_sz - consumed); out_sz = comp_out_sz - produced; rc = qzCompress(&sess, src + consumed, (uint32_t *)(&in_sz), comp_out + produced, (uint32_t *)(&out_sz), 1); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); dumpInputData(in_sz, src + consumed); goto done; } consumed = consumed + in_sz; produced = produced + out_sz; compressed_blocks_sz[i] = out_sz; } src_sz = consumed; comp_out_sz = produced; if (src_sz != org_src_sz) { QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, org_src_sz); dumpInputData(src_sz, src); goto done; } } #ifdef ENABLE_THREAD_BARRIER pthread_barrier_wait(&g_bar); #else /* mutex lock for thread count */ rc = pthread_mutex_lock(&g_cond_mutex); if (rc != 0) { QZ_ERROR("Failure to release Mutex Lock, status = %d\n", rc); goto done; } g_ready_thread_count++; rc = pthread_cond_signal(&g_ready_cond); if (rc != 0) { QZ_ERROR("Failure to pthread_cond_signal, status = %d\n", rc); goto done; } while (!g_ready_to_start) { rc = pthread_cond_wait(&g_start_cond, &g_cond_mutex); if (rc != 0) { QZ_ERROR("Failure to pthread_cond_wait, status = %d\n", rc); goto done; } } rc = pthread_mutex_unlock(&g_cond_mutex); if (rc != 0) { QZ_ERROR("Failure to release Mutex Lock, status = %d\n", rc); goto done; } #endif // Start the testing for (k = 0; k < count; k++) { (void)gettimeofday(&ts, NULL); if (DECOMP != service) { comp_out_sz = org_comp_out_sz; QZ_DEBUG("thread %ld before Compressed %lu bytes into %lu\n", tid, src_sz, comp_out_sz); consumed = 0; produced = 0; for (int i = 0; i < num_blocks; i ++) { in_sz = block_size < (org_src_sz - consumed) ? block_size : (org_src_sz - consumed); out_sz = comp_out_sz - produced; rc = qzCompress(&sess, src + consumed, (uint32_t *)(&in_sz), comp_out + produced, (uint32_t *)(&out_sz), 1); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); dumpInputData(in_sz, src + consumed); goto done; } consumed = consumed + in_sz; produced = produced + out_sz; compressed_blocks_sz[i] = out_sz; } src_sz = consumed; comp_out_sz = produced; if (src_sz != org_src_sz) { QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, org_src_sz); dumpInputData(src_sz, src); goto done; } QZ_DEBUG("thread %ld after Compressed %lu bytes into %lu\n", tid, src_sz, comp_out_sz); } if (COMP != service) { QZ_DEBUG("thread %ld before Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_out_sz); consumed = 0; produced = 0; for (int i = 0; i < num_blocks; i ++) { in_sz = compressed_blocks_sz[i]; out_sz = decomp_out_sz - produced; rc = qzDecompress(&sess, comp_out + consumed, (uint32_t *)(&in_sz), decomp_out + produced, (uint32_t *)(&out_sz)); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); dumpInputData(src_sz, src); goto done; } consumed += in_sz; produced += out_sz; } decomp_out_sz = produced; if (decomp_out_sz != org_src_sz) { QZ_ERROR("ERROR: After Decompression decomp_out_sz: %lu != org_src_sz: %lu \n!", decomp_out_sz, org_src_sz); dumpInputData(src_sz, src); goto done; } QZ_DEBUG("thread %ld after Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_out_sz); } (void)gettimeofday(&te, NULL); if (verify_data && COMP != service) { QZ_DEBUG("verify data..\n"); if (memcmp(src, decomp_out, org_src_sz)) { QZ_ERROR("ERROR: Decompression FAILED on thread %ld with size: %lu \n!", tid, src_sz); dumpInputData(src_sz, src); goto done; } if (BOTH == service) { QZ_DEBUG("reset data..\n"); memset(comp_out, 0, comp_out_sz); memset(decomp_out, 0, decomp_out_sz); } } ts_m = (ts.tv_sec * 1000000) + ts.tv_usec; te_m = (te.tv_sec * 1000000) + te.tv_usec; el_m += te_m - ts_m; } /* Verify the last compress is enough decompress data for verify */ if (verify_data && COMP == service) { QZ_DEBUG("verify compress thread %ld, before Decompressed %lu bytes into %lu\n", tid, comp_out_sz, decomp_out_sz); consumed = 0; produced = 0; for (int i = 0; i < num_blocks; i ++) { in_sz = compressed_blocks_sz[i]; out_sz = decomp_out_sz - produced; rc = qzDecompress(&sess, comp_out + consumed, (uint32_t *)(&in_sz), decomp_out + produced, (uint32_t *)(&out_sz)); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); dumpInputData(src_sz, src); goto done; } consumed += in_sz; produced += out_sz; } QZ_DEBUG("verify compressed data..\n"); decomp_out_sz = produced; if (decomp_out_sz != org_src_sz || memcmp(src, decomp_out, org_src_sz)) { QZ_ERROR("ERROR: After Decompression decomp_out_sz: %lu != org_src_sz: %lu \n!", decomp_out_sz, org_src_sz); dumpInputData(src_sz, src); goto done; } } //timeCheck(5, tid); sec = (long double)(el_m); sec = sec / 1000000.0; rate = org_src_sz; rate /= 1024; rate *= 8;// Kbits if (BOTH == service) { rate *= 2; } rate *= count; rate /= 1024 * 1024; // gigbits rate /= sec;// Gbps if (0 != pthread_mutex_lock(&g_lock_print)) { goto done; } QZ_PRINT("[INFO] srv="); if (COMP == service) { QZ_PRINT("COMP"); } else if (DECOMP == service) { QZ_PRINT("DECOMP"); } else if (BOTH == service) { QZ_PRINT("BOTH"); } else { QZ_ERROR("UNKNOWN\n"); pthread_mutex_unlock(&g_lock_print); goto done; } QZ_PRINT(", tid=%ld, verify=%d, count=%d, msec=%llu, " "bytes=%lu, %Lf Gbps", tid, verify_data, count, el_m, org_src_sz, rate); if (DECOMP != service) { QZ_PRINT(", input_len=%lu, comp_len=%lu, ratio=%f%%", org_src_sz, comp_out_sz, ((double)comp_out_sz / (double)org_src_sz) * 100); } if (COMP != service) { QZ_PRINT(", comp_len=%lu, decomp_len=%lu", comp_out_sz, decomp_out_sz); } QZ_PRINT("\n"); if (test_thread_safe_flag == 1) { if (thread_sleep == 0) { srand(time(NULL)); thread_sleep = (rand() % 500 + 1) * 1000; } usleep(thread_sleep); } pthread_mutex_unlock(&g_lock_print); done: if (gen_data && !g_perf_svm) { qzFree(src); qzFree(comp_out); qzFree(decomp_out); } else if (g_perf_svm) { free(src); free(comp_out); free(decomp_out); } if (compressed_blocks_sz != NULL) { free(compressed_blocks_sz); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzMemFuncTest(void *test_arg) { int i; unsigned char *ptr[1000]; unsigned char *ptr2[1000]; unsigned success = 0; const long tid = ((TestArg_T *)test_arg)->thd_id; QZ_DEBUG("Hello from test2 thread id %ld\n", tid); for (i = 0; i < 1000; i++) { ptr[i] = qzMalloc(100000, 0, PINNED_MEM); ptr2[i] = qzMalloc(100000, 0, COMMON_MEM); if (ptr[i] == NULL || ptr2[i] == NULL) { QZ_ERROR("[Test2 %ld]\tptr[%d]=0x%lx\t0x%lx\n", tid, i, (unsigned long)ptr[i], (unsigned long)ptr2[i]); if (ptr[i]) { qzFree(ptr[i]); } if (ptr2[i]) { qzFree(ptr2[i]); } break; } success++; } for (i = 0; i < success; i++) { qzFree(ptr[i]); qzFree(ptr2[i]); } for (i = 0; i < success; i++) { if (1 == qzMemFindAddr(ptr[i])) { QZ_DEBUG("[Test2 %ld]\tptr[%d]=0x%lx\tstill as pinned memory after qzFree.\n", tid, i, (unsigned long)ptr[i]); break; } } pthread_exit((void *)NULL); } int qzCompressDecompressWithParams(const TestArg_T *arg, QzSessionParams_T *comp_params, QzSessionParams_T *decomp_params) { int rc = -1; QzSession_T comp_sess = {0}, decomp_sess = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, src_sz, comp_sz, decomp_sz; orig_sz = comp_sz = decomp_sz = arg->src_sz; orig_src = qzMalloc(orig_sz, 0, PINNED_MEM); comp_src = qzMalloc(comp_sz, 0, PINNED_MEM); decomp_src = qzMalloc(orig_sz, 0, PINNED_MEM); if (orig_src == NULL || comp_src == NULL || decomp_src == NULL) { QZ_ERROR("Malloc Memory for testing %s error\n", __func__); return -1; } genRandomData(orig_src, orig_sz); /*do compress Data*/ src_sz = orig_sz; if (qzSetDefaults(comp_params) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } rc = qzCompress(&comp_sess, orig_src, (uint32_t *)(&src_sz), comp_src, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK || src_sz != orig_sz) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, orig_sz); goto done; } /*do decompress Data*/ if (qzSetDefaults(decomp_params) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } rc = qzDecompress(&decomp_sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); goto done; } rc = 0; done: qzFree(orig_src); qzFree(comp_src); qzFree(decomp_src); (void)qzTeardownSession(&comp_sess); (void)qzTeardownSession(&decomp_sess); qzClose(&comp_sess); qzClose(&decomp_sess); return rc; } void *qzCompressStreamAndDecompress(void *arg) { int rc = -1; QzSession_T comp_sess = {0}, decomp_sess = {0}; QzStream_T comp_strm = {0}; QzSessionParams_T comp_params = {0}, decomp_params = {0}; uint8_t *orig_src = NULL, *comp_src = NULL, *decomp_src = NULL; size_t orig_sz, comp_sz, decomp_sz; unsigned int slice_sz = 0, done = 0; unsigned int consumed = 0, produced = 0; unsigned int input_left = 0, last = 0; unsigned int decomp_out_sz = 0; int org_in_sz; int offset = 0; TestArg_T *test_arg = (TestArg_T *) arg; orig_sz = comp_sz = decomp_sz = test_arg->src_sz; orig_src = malloc(orig_sz); if (NULL == orig_src) { QZ_ERROR("Err: fail to malloc memory\n"); goto exit; } comp_src = malloc(comp_sz); if (NULL == comp_src) { QZ_ERROR("Err: fail to malloc memory\n"); goto exit; } decomp_src = calloc(orig_sz, 1); if (NULL == decomp_src) { QZ_ERROR("Err: fail to malloc memory\n"); goto exit; } if (qzGetDefaults(&comp_params) != QZ_OK) { QZ_ERROR("Err: get params fail with incorrect compress params.\n"); goto exit; } if (qzGetDefaults(&decomp_params) != QZ_OK) { QZ_ERROR("Err: get params fail with incorrect decompress params.\n"); goto exit; } slice_sz = comp_params.hw_buff_sz / 4; rc = qzInit(&comp_sess, 0); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("Err: fail to init HW with ret: %d.\n", rc); goto exit; } switch (test_arg->test_format) { case TEST_DEFLATE: comp_params.data_fmt = QZ_DEFLATE_RAW; decomp_params.data_fmt = QZ_DEFLATE_RAW; break; case TEST_GZIPEXT: comp_params.data_fmt = QZ_DEFLATE_GZIP_EXT; decomp_params.data_fmt = QZ_DEFLATE_GZIP_EXT; break; default: QZ_ERROR("Unsupported data format in Stream API\n"); goto exit; } QZ_DEBUG("*** Data Format: %d ***\n", comp_params.data_fmt); rc = qzSetupSession(&comp_sess, &comp_params); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("Err: fail to setup session with ret: %d\n", rc); goto exit; } rc = qzSetupSession(&decomp_sess, &decomp_params); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("Err: fail to setup session with ret: %d\n", rc); goto exit; } genRandomData(orig_src, orig_sz); while (!done) { input_left = orig_sz - consumed; comp_strm.in = orig_src + consumed; comp_strm.out = comp_src + produced; comp_strm.in_sz = (input_left > slice_sz) ? slice_sz : input_left; comp_strm.out_sz = comp_sz - produced; last = (((consumed + comp_strm.in_sz) == orig_sz) ? 1 : 0); rc = qzCompressStream(&comp_sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); goto exit; } consumed += comp_strm.in_sz; produced += comp_strm.out_sz; QZ_DEBUG("consumed is %u, in_sz is %d\n", consumed, comp_strm.in_sz); if (1 == last && 0 == comp_strm.pending_in && 0 == comp_strm.pending_out) { done = 1; } } decomp_out_sz = produced; qzEndStream(&comp_sess, &comp_strm); QZ_DEBUG("qzCompressStream consumed: %d produced: %d\n", consumed, produced); comp_sz = produced; rc = qzDecompress(&decomp_sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); dumpInputData(produced, comp_src); dumpOutputData(decomp_sz, decomp_src, "decomp_out"); goto exit; } if (memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Decompression FAILED with size: %lu \n!", orig_sz); dumpInputData(orig_sz, orig_src); dumpOutputData(comp_sz, comp_src, "comp_out"); dumpOutputData(decomp_sz, decomp_src, "decomp_out"); goto exit; } QZ_DEBUG("qzDecompress Test PASS\n"); QZ_DEBUG("*** Decompress Stream Test 1 ***\n"); comp_sz = produced; done = 0; consumed = 0; produced = 0; memset(decomp_src, 0, orig_sz); while (!done) { input_left = comp_sz - consumed; comp_strm.in = comp_src + consumed; comp_strm.out = decomp_src + produced; comp_strm.in_sz = (input_left > slice_sz) ? slice_sz : input_left; comp_strm.out_sz = decomp_sz - produced; last = (comp_sz == (consumed + comp_strm.in_sz)) ? 1 : 0; org_in_sz = comp_strm.in_sz; rc = qzDecompressStream(&decomp_sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); dumpOutputData(comp_sz, comp_src, "decomp_stream__input"); goto exit; } consumed += comp_strm.in_sz; produced += comp_strm.out_sz; QZ_DEBUG("consumed: %d produced: %d input_left: %d last: %d, pending_in: %d, pending_out: %d\n", consumed, produced, input_left, last, comp_strm.pending_in, comp_strm.pending_out); if (1 == last && 0 == comp_strm.pending_in && 0 == comp_strm.pending_out && org_in_sz == comp_strm.in_sz) { done = 1; } } QZ_DEBUG("Total consumed: %u produced: %u\n", consumed, produced); QZ_DEBUG("verify data of size %lu ...\n", orig_sz); if (produced != orig_sz || consumed != decomp_out_sz || memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Memory compare FAILED with size: %lu \n!", orig_sz); dumpInputData(orig_sz, orig_src); dumpInputData(orig_sz, decomp_src); goto exit; } QZ_DEBUG("*** Decompress Stream Test 1 PASS ***\n"); if (comp_params.data_fmt != QZ_DEFLATE_GZIP_EXT) { goto test_2_end; } QZ_DEBUG("*** Decompress Stream Test 2 ***\n"); done = 0; consumed = 0; produced = 0; memset(decomp_src, 0, orig_sz); QzGzH_T hdr; while (!done) { if (QZ_OK != qzGzipHeaderExt(comp_src + offset, &hdr)) { QZ_ERROR("ERROR: extracting header failed\n"); goto exit; } input_left = comp_sz - consumed; comp_strm.in = comp_src + consumed; comp_strm.out = decomp_src + produced; comp_strm.in_sz = sizeof(QzGzH_T) + hdr.extra.qz_e.dest_sz + sizeof(StdGzF_T); comp_strm.out_sz = decomp_sz - produced; last = 1; offset += comp_strm.in_sz; rc = qzDecompressStream(&decomp_sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Memcmp with return value: %d\n", rc); goto exit; } consumed += comp_strm.in_sz; produced += comp_strm.out_sz; if (offset == comp_sz) { done = 1; } } QZ_DEBUG("Total consumed: %u produced: %u\n", consumed, produced); QZ_DEBUG("verify data of size %lu ...\n", orig_sz); if (produced != orig_sz || consumed != decomp_out_sz || memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Decompression FAILED with size: %lu \n!", orig_sz); dumpInputData(orig_sz, orig_src); dumpInputData(orig_sz, decomp_src); goto exit; } QZ_DEBUG("*** Decompress Stream Test 2 PASS ***\n"); test_2_end: if (comp_params.data_fmt == QZ_DEFLATE_GZIP_EXT) { goto test_3_end; } QZ_DEBUG("*** Decompress Stream Test 3 ***\n"); done = 0; consumed = 0; produced = 0; memset(decomp_src, 0, orig_sz); while (!done) { input_left = comp_sz - consumed; comp_strm.in = comp_src + consumed; comp_strm.out = decomp_src + produced; comp_strm.in_sz = (input_left > 256) ? 256 : input_left; comp_strm.out_sz = decomp_sz - produced; last = 1; org_in_sz = comp_strm.in_sz; rc = qzDecompressStream(&decomp_sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); goto exit; } consumed += comp_strm.in_sz; produced += comp_strm.out_sz; QZ_DEBUG("consumed: %u produced: %u input_left: %u last: %u, pending_in: %u, pending_out: %u " "org_in_sz: %d in_sz: %u\n", consumed, produced, input_left, last, comp_strm.pending_in, comp_strm.pending_out, org_in_sz, comp_strm.in_sz); if (1 == last && 0 == comp_strm.pending_in && 0 == comp_strm.pending_out && org_in_sz == comp_strm.in_sz && produced == orig_sz && comp_sz - consumed == 0) { done = 1; } } QZ_DEBUG("Total consumed: %u produced: %u\n", consumed, produced); QZ_DEBUG("verify data of size %lu ...\n", orig_sz); if (produced != orig_sz || consumed != decomp_out_sz || memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Memory compare FAILED with size: %lu \n!", orig_sz); dumpInputData(orig_sz, orig_src); dumpInputData(orig_sz, decomp_src); goto exit; } QZ_DEBUG("*** Decompress Stream Test 3 PASS***\n"); test_3_end: QZ_DEBUG("*** Decompress Stream Test 4 ***\n"); done = 0; consumed = 0; produced = 0; memset(decomp_src, 0, orig_sz); while (!done) { input_left = comp_sz - consumed; comp_strm.in = comp_src + consumed; comp_strm.out = decomp_src + produced; comp_strm.in_sz = (input_left > slice_sz) ? slice_sz : input_left; comp_strm.out_sz = decomp_sz - produced; last = (comp_sz == (consumed + comp_strm.in_sz)) ? 1 : 0; org_in_sz = comp_strm.in_sz; rc = qzDecompressStream(&decomp_sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); goto exit; } consumed += comp_strm.in_sz; produced += comp_strm.out_sz; QZ_DEBUG("consumed: %u produced: %u input_left: %u last: %u, pending_in: %u, pending_out: %u " "org_in_sz: %d in_sz: %u\n", consumed, produced, input_left, last, comp_strm.pending_in, comp_strm.pending_out, org_in_sz, comp_strm.in_sz); if (1 == last && 0 == comp_strm.pending_in && 0 == comp_strm.pending_out && org_in_sz == comp_strm.in_sz && produced == orig_sz && comp_sz - consumed == 0) { done = 1; } } QZ_DEBUG("Total consumed: %u produced: %u\n", consumed, produced); QZ_DEBUG("verify data of size %lu ...\n", orig_sz); if (produced != orig_sz || consumed != decomp_out_sz || memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Memory compare FAILED with size: %lu \n!", orig_sz); dumpInputData(orig_sz, orig_src); dumpInputData(orig_sz, decomp_src); goto exit; } QZ_DEBUG("*** Decompress Stream Test 4 PASS***\n"); QZ_PRINT("Compress Stream and Decompress function test: PASS\n"); exit: if (NULL != orig_src) { free(orig_src); orig_src = NULL; } if (NULL != comp_src) { free(comp_src); comp_src = NULL; } if (NULL != decomp_src) { free(decomp_src); decomp_src = NULL; } qzEndStream(&comp_sess, &comp_strm); (void)qzTeardownSession(&comp_sess); (void)qzTeardownSession(&decomp_sess); return NULL; } void *qzCompressStreamOnCommonMem(void *thd_arg) { int rc, k; unsigned char *src = NULL, *dest = NULL; size_t src_sz, dest_sz, avail_dest_sz; struct timeval ts, te; unsigned long long ts_m, te_m, el_m; long double sec, rate; QzStream_T comp_strm = {0}; QzSessionParams_T params = {0}; unsigned int last = 0; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; const long tid = test_arg->thd_id; QzSession_T sess = {0}; QZ_DEBUG("Hello from qzCompressStreamOnCommonMem id %ld\n", tid); timeCheck(0, tid); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_HW_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInit rc = %d\n", rc); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = DEFAULT_STREAM_BUF_SZ; if (qzSetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } timeCheck(1, tid); //set by default configurations rc = qzSetupSession(&sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { pthread_exit((void *)"qzSetupSession failed"); } timeCheck(2, tid); QZ_DEBUG("qzSetupSession rc = %d\n", rc); src_sz = QATZIP_MAX_HW_SZ; avail_dest_sz = dest_sz = QATZIP_MAX_HW_SZ; if (gen_data) { src_sz = QATZIP_MAX_HW_SZ; dest_sz = QATZIP_MAX_HW_SZ; src = qzMalloc(src_sz, 0, COMMON_MEM); dest = qzMalloc(dest_sz, 0, COMMON_MEM); } else { src = test_arg->src; src_sz = test_arg->src_sz; dest = test_arg->comp_out; dest_sz = test_arg->comp_out_sz; } if (!src || !dest) { QZ_ERROR("Malloc failed\n"); goto done; } el_m = 0; if (gen_data) { QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); } timeCheck(3, tid); for (k = 0; k < test_arg->count; k++) { dest_sz = avail_dest_sz; (void)gettimeofday(&ts, NULL); comp_strm.in = src; comp_strm.out = dest; comp_strm.in_sz = src_sz; comp_strm.out_sz = dest_sz; last = 1; rc = qzCompressStream(&sess, &comp_strm, last); qzEndStream(&sess, &comp_strm); if (rc != QZ_OK) { QZ_ERROR("qzCompressStream FAILED, return: %d", rc); goto done; } (void)gettimeofday(&te, NULL); QZ_DEBUG("Compressed %lu bytes into %lu\n", src_sz, dest_sz); ts_m = (ts.tv_sec * 1000000) + ts.tv_usec; te_m = (te.tv_sec * 1000000) + te.tv_usec; el_m += te_m - ts_m; } timeCheck(4, tid); sec = (long double)(el_m); sec = sec / 1000000.0; rate = src_sz * test_arg->count * 8; // bits rate = rate / 1000000000.0; // gigbits rate = rate / sec;// Gbps QZ_PRINT("[%ld] elapsed microsec = %llu bytes = %lu rate = %Lf Gbps\n", tid, el_m, src_sz, rate); done: timeCheck(5, tid); if (gen_data) { qzFree(src); qzFree(dest); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzCompressStreamOutput(void *thd_arg) { int rc; unsigned char *src = NULL, *dest = NULL; size_t src_sz, dest_sz; QzStream_T comp_strm = {0}; QzSessionParams_T params = {0}; unsigned int last = 0; char *filename = NULL; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; QzSession_T sess = {0}; QZ_DEBUG("Hello from qzCompressStreamOutput\n"); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInit rc = %d\n", rc); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = DEFAULT_STREAM_BUF_SZ; switch (test_arg->test_format) { case TEST_DEFLATE: params.data_fmt = QZ_DEFLATE_RAW; break; case TEST_GZIPEXT: params.data_fmt = QZ_DEFLATE_GZIP_EXT; break; default: break; } rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { pthread_exit((void *)"qzSetupSession failed"); } QZ_DEBUG("qzSetupSession rc = %d\n", rc); if (gen_data) { src_sz = QATZIP_MAX_HW_SZ; dest_sz = QATZIP_MAX_HW_SZ; src = qzMalloc(src_sz, 0, COMMON_MEM); dest = qzMalloc(dest_sz, 0, COMMON_MEM); } else { src = test_arg->src; src_sz = test_arg->src_sz; dest = test_arg->comp_out; dest_sz = test_arg->comp_out_sz; filename = (char *) calloc(1, strlen(g_input_file_name) + 4); if (NULL != filename) { snprintf(filename, strlen(g_input_file_name) + 4, "%s.%s", g_input_file_name, "gz"); } else { QZ_ERROR("Calloc failed\n"); goto done; } } if (!src || !dest) { QZ_ERROR("Malloc failed\n"); goto done; } if (gen_data) { QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); } { // Add header and tailer for DEFLATE_RAW data, this is simulate from // nginx qatzip module, and it's convenient for us to valid correctness. if (params.data_fmt == QZ_DEFLATE_RAW) { static u_char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 }; memcpy(dest, gzheader, 10); comp_strm.out = dest + 10; } else { comp_strm.out = dest; } comp_strm.in = src; comp_strm.in_sz = src_sz; comp_strm.out_sz = dest_sz; last = 1; rc = qzCompressStream(&sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("qzCompressStream FAILED, return: %d", rc); goto done; } QZ_DEBUG("Compressed %lu bytes into %lu\n", src_sz, dest_sz); // Add tailer for Deflate raw data. if (params.data_fmt == QZ_DEFLATE_RAW) { StdGzF_T *tailer = (StdGzF_T *)(comp_strm.out + comp_strm.out_sz); tailer->crc32 = comp_strm.crc_32; tailer->i_size = comp_strm.in_sz; comp_strm.out_sz += 18; comp_strm.out = dest; } dumpOutputData(comp_strm.out_sz, comp_strm.out, filename); qzEndStream(&sess, &comp_strm); } done: if (gen_data) { qzFree(src); qzFree(dest); } else { free(filename); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzDecompressStreamInput(void *thd_arg) { int rc; unsigned char *src = NULL, *dest = NULL; size_t src_sz, dest_sz; unsigned int consumed, done; QzStream_T decomp_strm = {0}; QzSessionParams_T params = {0}; unsigned int last = 0; char *filename = NULL; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; QzSession_T sess = {0}; QZ_DEBUG("Hello from qzDecompressStreamInput\n"); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInit rc = %d\n", rc); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = 1024 * 1024; if (qzSetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } //set by default configurations rc = qzSetupSession(&sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { pthread_exit((void *)"qzSetupSession failed"); } QZ_DEBUG("qzSetupSession rc = %d\n", rc); if (gen_data) { QZ_ERROR("Err: No input file.\n"); goto done; } src = test_arg->src; src_sz = test_arg->src_sz; dest = test_arg->decomp_out; dest_sz = test_arg->decomp_out_sz; consumed = 0; done = 0; filename = g_input_file_name; if (!src || !dest) { QZ_ERROR("Malloc failed\n"); goto done; } { while (!done) { decomp_strm.in = src + consumed; decomp_strm.in_sz = src_sz - consumed; decomp_strm.out = dest; decomp_strm.out_sz = dest_sz; last = 1; rc = qzDecompressStream(&sess, &decomp_strm, last); if (rc != QZ_OK) { QZ_ERROR("qzDecompressStream FAILED, return: %d\n", rc); goto done; } QZ_DEBUG("Decompressed %lu bytes into %lu\n", src_sz, dest_sz); dumpDecompressedData(decomp_strm.out_sz, decomp_strm.out, filename); consumed += decomp_strm.in_sz; if (src_sz == consumed && decomp_strm.pending_out == 0) { done = 1; } } qzEndStream(&sess, &decomp_strm); } done: if (gen_data) { qzFree(src); qzFree(dest); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzCompressStreamInvalidChunkSize(void *thd_arg) { int rc; unsigned char *src = NULL, *dest = NULL; QzSessionParams_T params = {0}; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; const long tid = test_arg->thd_id; QzSession_T sess = {0}; QZ_PRINT("Hello from qzCompressStreamInvalidChunkSize id %ld\n", tid); timeCheck(0, tid); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_HW_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInit rc = %d\n", rc); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = DEFAULT_STREAM_BUF_SZ; if (qzSetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } params.hw_buff_sz = 525312; /*513k*/ rc = qzSetupSession(&sess, ¶ms); if (rc != QZ_PARAMS) { pthread_exit((void *) "qzCompressStreamInvalidChunkSize input param check FAILED"); } params.hw_buff_sz = 100; rc = qzSetupSession(&sess, ¶ms); if (rc != QZ_PARAMS) { pthread_exit((void *) "qzCompressStreamInvalidChunkSize input param check FAILED"); } QZ_PRINT("qzCompressStreamInvalidChunkSize : PASS\n"); done: timeCheck(5, tid); if (gen_data) { qzFree(src); qzFree(dest); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzCompressStreamInvalidQzStreamParam(void *thd_arg) { int rc; unsigned char *src = NULL, *dest = NULL; size_t src_sz, dest_sz; QzStream_T comp_strm = {0}; QzSessionParams_T params = {0}; unsigned int last = 0; char *filename = NULL; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; const long tid = test_arg->thd_id; QzSession_T sess = {0}; QZ_PRINT("Hello from qzCompressStreamInvalidQzStreamParam id %ld\n", tid); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_HW_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInit rc = %d\n", rc); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = DEFAULT_STREAM_BUF_SZ; if (qzSetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } rc = qzSetupSession(&sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { pthread_exit((void *)"qzSetupSession failed"); } QZ_DEBUG("qzSetupSession rc = %d\n", rc); if (gen_data) { src_sz = QATZIP_MAX_HW_SZ; dest_sz = QATZIP_MAX_HW_SZ; src = qzMalloc(src_sz, 0, COMMON_MEM); dest = qzMalloc(dest_sz, 0, COMMON_MEM); } else { src = test_arg->src; src_sz = test_arg->src_sz; dest = test_arg->comp_out; dest_sz = test_arg->comp_out_sz; filename = (char *) calloc(1, strlen(g_input_file_name) + 4); if (NULL != filename) { snprintf(filename, strlen(g_input_file_name) + 4, "%s.%s", g_input_file_name, "gz"); } else { QZ_ERROR("Calloc failed\n"); goto done; } } if (!src || !dest) { QZ_ERROR("Malloc failed\n"); goto done; } if (gen_data) { QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); } { /*case 1: set strm all params to zero*/ last = 1; memset(&comp_strm, 0, sizeof(QzStream_T)); rc = qzCompressStream(&sess, &comp_strm, last); if (rc != QZ_PARAMS) { QZ_ERROR("qzCompressStream FAILED, return: %d\n", rc); goto done; } QZ_DEBUG("Compressed %lu bytes into %lu\n", src_sz, dest_sz); /*case 2: set strm in, our ptr to NULL, but in_sz, out_sz not zero*/ memset(&comp_strm, 0, sizeof(QzStream_T)); comp_strm.in_sz = src_sz; comp_strm.out_sz = dest_sz; rc = qzCompressStream(&sess, &comp_strm, last); if (rc != QZ_PARAMS) { QZ_ERROR("qzCompressStream FAILED, return: %d\n", rc); goto done; } dumpOutputData(comp_strm.out_sz, comp_strm.out, filename); qzEndStream(&sess, &comp_strm); } QZ_PRINT("qzCompressStreamInvalidQzStreamParam : PASS\n"); done: if (gen_data) { qzFree(src); qzFree(dest); } else { free(filename); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *testqzDecompressStreamInvalidParam(void *arg, int test_no) { int rc = -1; QzSession_T comp_sess = {0}, decomp_sess = {0}; QzStream_T comp_strm = {0}; QzSessionParams_T comp_params = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, comp_sz, decomp_sz; unsigned int slice_sz = 0, done = 0; unsigned int consumed = 0, produced = 0; unsigned int input_left = 0, last = 0; QzSession_T *test_sess = NULL; QzStream_T *test_strm = NULL; TestArg_T *test_arg = (TestArg_T *) arg; orig_sz = comp_sz = decomp_sz = test_arg->src_sz; orig_src = malloc(orig_sz); comp_src = malloc(comp_sz); decomp_src = calloc(orig_sz, 1); if (qzGetDefaults(&comp_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); return NULL; } slice_sz = comp_params.hw_buff_sz / 4; if (NULL == orig_src || NULL == comp_src || NULL == decomp_src) { free(orig_src); free(comp_src); free(decomp_src); QZ_ERROR("Malloc Memory for testing %s error\n", __func__); return NULL; } switch (test_arg->test_format) { case TEST_DEFLATE: comp_params.data_fmt = QZ_DEFLATE_RAW; break; case TEST_GZIPEXT: comp_params.data_fmt = QZ_DEFLATE_GZIP_EXT; break; default: QZ_ERROR("Unsupported data format in Stream API\n"); free(orig_src); free(comp_src); free(decomp_src); return NULL; } QZ_DEBUG("*** Data Format: %d ***\n", comp_params.data_fmt); genRandomData(orig_src, orig_sz); while (!done) { input_left = orig_sz - consumed; comp_strm.in = orig_src + consumed; comp_strm.out = comp_src + produced; comp_strm.in_sz = (input_left > slice_sz) ? slice_sz : input_left; comp_strm.out_sz = comp_sz - produced; last = (((consumed + comp_strm.in_sz) == orig_sz) ? 1 : 0); rc = qzCompressStream(&comp_sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); goto exit; } consumed += comp_strm.in_sz; produced += comp_strm.out_sz; QZ_DEBUG("consumed is %u, in_sz is %d\n", consumed, comp_strm.in_sz); if (1 == last && 0 == comp_strm.pending_in && 0 == comp_strm.pending_out) { done = 1; } } qzEndStream(&comp_sess, &comp_strm); QZ_DEBUG("qzCompressStream consumed: %d produced: %d\n", consumed, produced); comp_sz = produced; rc = qzDecompress(&decomp_sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_OK) { QZ_ERROR("ERROR: Decompression FAILED with return value: %d\n", rc); dumpInputData(produced, comp_src); dumpOutputData(decomp_sz, decomp_src, "decomp_out"); goto exit; } if (memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Decompression FAILED with size: %lu \n!", orig_sz); dumpInputData(orig_sz, orig_src); dumpOutputData(comp_sz, comp_src, "comp_out"); dumpOutputData(decomp_sz, decomp_src, "decomp_out"); goto exit; } QZ_DEBUG("qzDecompress Test PASS\n"); QZ_DEBUG("*** Decompress Stream Test ***\n"); comp_sz = produced; done = 0; consumed = 0; produced = 0; memset(decomp_src, 0, orig_sz); input_left = comp_sz - consumed; comp_strm.in = comp_src + consumed; comp_strm.out = decomp_src + produced; comp_strm.in_sz = (input_left > slice_sz) ? slice_sz : input_left; comp_strm.out_sz = decomp_sz - produced; last = (comp_sz == (consumed + comp_strm.in_sz)) ? 1 : 0; if (1 == test_no) { QZ_DEBUG("T#############T DecompressStream Session is null Test ***\n"); test_strm = &comp_strm; } else if (2 == test_no) { QZ_DEBUG("T#############T DecompressStream Neg parameter for last is -1 Test ***\n"); last = -1; test_sess = &comp_sess; test_strm = &comp_strm; } else if (3 == test_no) { QZ_DEBUG("T#############T DecompressStream Neg parameter for last is 2 Test ***\n"); last = 2; test_sess = &comp_sess; test_strm = &comp_strm; } else if (4 == test_no) { QZ_DEBUG("T#############T DecompressStream Neg parameter for strm null Test ***\n"); test_sess = &comp_sess; } else { //nothing to do goto exit; } rc = qzDecompressStream(test_sess, test_strm, last); if (rc == QZ_OK) { QZ_ERROR("T#############T ERROR: qzDecompressStream negative test FAILED: %d*** \n", rc); dumpOutputData(comp_sz, comp_src, "decomp_stream__input"); goto exit; } QZ_DEBUG("T#############T: qzDecompressStream return value: %d*** \n", rc); exit: qzFree(orig_src); qzFree(comp_src); qzFree(decomp_src); qzEndStream(&comp_sess, &comp_strm); (void)qzTeardownSession(&comp_sess); (void)qzTeardownSession(&decomp_sess); qzClose(&comp_sess); qzClose(&decomp_sess); return NULL; } void *qzDecompressStreamNegParam(void *arg) { int test_no = 0; for (test_no = 1; test_no <= 5; test_no++) { QZ_DEBUG("*** qzDecompressStreamNegParam test_no: %d ***\n", test_no); testqzDecompressStreamInvalidParam(arg, test_no); } return NULL; } void *testqzEndStreamInvalidParam(void *arg, int test_no) { int rc = -1; QzSession_T comp_sess = {0}, decomp_sess = {0}; QzStream_T comp_strm = {0}; QzSessionParams_T comp_params = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, comp_sz, decomp_sz; unsigned int slice_sz = 0, done = 0; unsigned int consumed = 0, produced = 0; unsigned int input_left = 0, last = 0; QzSession_T *test_sess = NULL; QzStream_T *test_strm = NULL; TestArg_T *test_arg = (TestArg_T *) arg; orig_sz = comp_sz = decomp_sz = test_arg->src_sz; orig_src = malloc(orig_sz); comp_src = malloc(comp_sz); decomp_src = calloc(orig_sz, 1); if (qzGetDefaults(&comp_params) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); return NULL; } slice_sz = comp_params.hw_buff_sz / 4; if (NULL == orig_src || NULL == comp_src || NULL == decomp_src) { free(orig_src); free(comp_src); free(decomp_src); QZ_ERROR("Malloc Memory for testing %s error\n", __func__); return NULL; } switch (test_arg->test_format) { case TEST_DEFLATE: comp_params.data_fmt = QZ_DEFLATE_RAW; break; case TEST_GZIPEXT: comp_params.data_fmt = QZ_DEFLATE_GZIP_EXT; break; default: QZ_ERROR("Unsupported data format in Stream API\n"); free(orig_src); free(comp_src); free(decomp_src); return NULL; } QZ_DEBUG("*** Data Format: %d ***\n", comp_params.data_fmt); genRandomData(orig_src, orig_sz); while (!done) { input_left = orig_sz - consumed; comp_strm.in = orig_src + consumed; comp_strm.out = comp_src + produced; comp_strm.in_sz = (input_left > slice_sz) ? slice_sz : input_left; comp_strm.out_sz = comp_sz - produced; last = (((consumed + comp_strm.in_sz) == orig_sz) ? 1 : 0); rc = qzCompressStream(&comp_sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); goto exit; } consumed += comp_strm.in_sz; produced += comp_strm.out_sz; QZ_DEBUG("consumed is %u, in_sz is %d\n", consumed, comp_strm.in_sz); if (1 == last && 0 == comp_strm.pending_in && 0 == comp_strm.pending_out) { done = 1; } } if (1 == test_no) { QZ_DEBUG("T#############T qzEndStream Session is null Test ***\n"); test_strm = &comp_strm; } else if (2 == test_no) { QZ_DEBUG("T#############T qzEndStream stream is null Test ***\n"); test_sess = &comp_sess; } else { goto exit; } rc = qzEndStream(test_sess, test_strm); if (rc == QZ_OK) { QZ_ERROR("\nT#############T ERROR: qzEndStream negative test FAILED,return: %d*** \n", rc); goto exit; } QZ_DEBUG("T#############T: qzEndStream return value: %d*** \n", rc); exit: qzFree(orig_src); qzFree(comp_src); qzFree(decomp_src); qzEndStream(&comp_sess, &comp_strm); (void)qzTeardownSession(&comp_sess); (void)qzTeardownSession(&decomp_sess); qzClose(&comp_sess); qzClose(&decomp_sess); return NULL; } void *qzEndStreamNegParam(void *arg) { int test_no = 0; for (test_no = 1; test_no <= 3; test_no++) { QZ_DEBUG("*** qzEndStreamNegParam test_no: %d ***\n", test_no); testqzEndStreamInvalidParam(arg, test_no); } return NULL; } void *qzInitPcieCountCheck(void *thd_arg) { int rc; unsigned char *src = NULL, *dest = NULL; size_t src_sz, dest_sz; unsigned int consumed, done; QzStream_T decomp_strm = {0}; QzSessionParams_T params = {0}; unsigned int last = 0; char *filename = NULL; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; QzSession_T sess = {0}; QZ_DEBUG("Start qzInitPcieCountCheck test\n"); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit1 error. rc = %d\n", rc); } QZ_DEBUG("qzInit1 done. rc = %d, g_process.qat_available = %d\n", rc, g_process.qat_available); qzClose(&sess); QZ_DEBUG("qzClose done. g_process.qat_available = %d\n", g_process.qat_available); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit2 error. rc = %d\n", rc); } QZ_DEBUG("qzInit2 done. rc = %d, g_process.qat_available = %d\n", rc, g_process.qat_available); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = 1024 * 1024; if (qzSetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } //set by default configurations rc = qzSetupSession(&sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { pthread_exit((void *)"qzSetupSession failed"); } QZ_DEBUG("qzSetupSession rc = %d\n", rc); if (gen_data) { QZ_ERROR("Err: No input file.\n"); goto done; } src = test_arg->src; src_sz = test_arg->src_sz; dest = test_arg->decomp_out; dest_sz = test_arg->decomp_out_sz; consumed = 0; done = 0; filename = g_input_file_name; if (!src || !dest) { QZ_ERROR("Malloc failed\n"); goto done; } { while (!done) { decomp_strm.in = src + consumed; decomp_strm.in_sz = src_sz - consumed; decomp_strm.out = dest; decomp_strm.out_sz = dest_sz; last = 1; rc = qzDecompressStream(&sess, &decomp_strm, last); if (rc != QZ_OK) { QZ_ERROR("qzDecompressStream FAILED, return: %d\n", rc); goto done; } QZ_DEBUG("Decompressed %lu bytes into %lu\n", src_sz, dest_sz); dumpDecompressedData(decomp_strm.out_sz, decomp_strm.out, filename); consumed += decomp_strm.in_sz; if (src_sz == consumed && decomp_strm.pending_out == 0) { done = 1; } } qzEndStream(&sess, &decomp_strm); } done: if (gen_data) { qzFree(src); qzFree(dest); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *qzCompressDecompressSwQZMixed(void *arg) { enum TestType_E { SW_SW, SW_QZ, QZ_SW, QZ_QZ, NUM_OF_TEST }; struct TestParams_T { enum TestType_E type; char *name; QzSessionParams_T *comp_params; QzSessionParams_T *decomp_params; }; QzSessionParams_T sw_comp_params = {0}, qz_comp_params = {0}, sw_decomp_params = {0}, qz_decomp_params = {0}; int i = 0; if ((qzGetDefaults(&sw_comp_params) != QZ_OK) || (qzGetDefaults(&qz_comp_params) != QZ_OK) || (qzGetDefaults(&sw_decomp_params) != QZ_OK) || (qzGetDefaults(&qz_decomp_params) != QZ_OK)) { QZ_ERROR("Err: fail to get default params.\n"); return NULL; } sw_comp_params.input_sz_thrshold = 512 * 1024; qz_comp_params.input_sz_thrshold = 1024; sw_decomp_params.input_sz_thrshold = 512 * 1024; qz_decomp_params.input_sz_thrshold = 1024; struct TestParams_T test_params[NUM_OF_TEST] = { (struct TestParams_T){SW_SW, "SW compress SW decompress", &sw_comp_params, &sw_decomp_params}, (struct TestParams_T){SW_QZ, "SW compress QZ decompress", &sw_comp_params, &qz_decomp_params}, (struct TestParams_T){QZ_SW, "QZ compress SW decompress", &qz_comp_params, &sw_decomp_params}, (struct TestParams_T){QZ_QZ, "QZ compress QZ decompress", &qz_comp_params, &qz_decomp_params}, }; ((TestArg_T *) arg)->src_sz = 128 * 1024; //128KB for (i = 0; i < NUM_OF_TEST; i++) { if (qzCompressDecompressWithParams(arg, test_params[i].comp_params, test_params[i].decomp_params) < 0) { QZ_ERROR("ERROR: HW/SW mixed function test in: %s \n", test_params[i].name); return NULL; } } QZ_PRINT("HW/SW mixed function test: PASS\n"); return NULL; } int qzDecompressFailedAtUnknownGzipHeader(void) { int rc; QzGzH_T *hdr = NULL; QzSession_T sess = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, src_sz, comp_sz, decomp_sz; QzSessionParams_T params = {0}; orig_sz = comp_sz = decomp_sz = 64 * 1024; /*64K*/ orig_src = qzMalloc(orig_sz, 0, PINNED_MEM); comp_src = qzMalloc(comp_sz, 0, PINNED_MEM); decomp_src = qzMalloc(orig_sz, 0, PINNED_MEM); if (orig_src == NULL || comp_src == NULL || decomp_src == NULL) { QZ_ERROR("Malloc Memory for testing %s error\n", __func__); return -1; } rc = qzInit(&sess, 1); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit for testing %s error, return: %d\n", __func__, rc); goto done; } assert(!qzGetDefaults(¶ms)); params.sw_backup = 0; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } genRandomData(orig_src, orig_sz); /*do compress Data*/ src_sz = orig_sz; rc = qzCompress(&sess, orig_src, (uint32_t *)(&src_sz), comp_src, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK || src_sz != orig_sz) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, orig_sz); goto done; } /*wrap bad block*/ hdr = (QzGzH_T *)comp_src; hdr->std_hdr.id1 = 0; /* id1 !=0x1f */ /*do decompress Data*/ rc = qzDecompress(&sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_FAIL) { QZ_ERROR("FAILED: Decompression success with Error GipHeader\n"); goto done; } rc = 0; done: qzFree(orig_src); qzFree(comp_src); qzFree(decomp_src); (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int qzDecompressSWFailedAtUnknownGzipBlock(void) { int rc = 0; QzGzH_T *hdr = NULL; QzSession_T sess = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, src_sz, comp_sz, decomp_sz; QzSessionParams_T params = {0}; unsigned int produce; orig_sz = comp_sz = decomp_sz = USDM_ALLOC_MAX_SZ; orig_src = qzMalloc(orig_sz, 0, PINNED_MEM); comp_src = qzMalloc(comp_sz, 0, PINNED_MEM); decomp_src = qzMalloc(orig_sz, 0, PINNED_MEM); if (orig_src == NULL || comp_src == NULL || decomp_src == NULL) { QZ_ERROR("Malloc Memory for testing %s error\n", __func__); goto done; } rc = qzInit(&sess, 1); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit for testing %s error, return: %d\n", __func__, rc); goto done; } if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.hw_buff_sz = QZ_HW_BUFF_MAX_SZ; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } /*compress Data*/ src_sz = orig_sz; genRandomData(orig_src, orig_sz); rc = qzCompress(&sess, orig_src, (uint32_t *)(&src_sz), comp_src, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK || src_sz != orig_sz) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, orig_sz); goto done; } hdr = (QzGzH_T *)comp_src; produce = hdr->extra.qz_e.dest_sz; /*wrap unknown block*/ memset(hdr + qzGzipHeaderSz(), 0, (size_t)produce); /*Scenario1: produce > DEST_SZ(params.hw_buff_sz)*/ /*set minimum hw size 16K*/ params.hw_buff_sz = 16 * 1024; while (produce < DEST_SZ(params.hw_buff_sz)) { params.hw_buff_sz *= 2; } QZ_DEBUG("produce: %u, DEST_SZ(hw_sz): %d\n", produce, DEST_SZ(params.hw_buff_sz)); rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("ERROR: qzSetupSession FAILED with return value: %d\n", rc); goto done; } rc = qzDecompress(&sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_FAIL && rc != QZ_DATA_ERROR) { QZ_ERROR("FAILED: Decompression success with Error Unknown Gzip block\n"); goto done; } rc = 0; done: qzFree(orig_src); qzFree(comp_src); qzFree(decomp_src); (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int qzDecompressHWFailedAtUnknownGzipBlock(void) { int rc = 0; QzGzH_T *hdr = NULL; QzSession_T sess = {0}; QzSessionParams_T params = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, src_sz, comp_sz, decomp_sz; uint32_t produce; orig_sz = comp_sz = decomp_sz = USDM_ALLOC_MAX_SZ; orig_src = qzMalloc(orig_sz, 0, PINNED_MEM); comp_src = qzMalloc(comp_sz, 0, PINNED_MEM); decomp_src = qzMalloc(orig_sz, 0, PINNED_MEM); if (orig_src == NULL || comp_src == NULL || decomp_src == NULL) { QZ_ERROR("Malloc Memory for testing %s error\n", __func__); goto done; } rc = qzInit(&sess, 0); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit for testing %s error, return: %d\n", __func__, rc); goto done; } assert(!qzGetDefaults(¶ms)); params.sw_backup = 0; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } /*compress Data*/ src_sz = orig_sz; genRandomData(orig_src, orig_sz); rc = qzCompress(&sess, orig_src, (uint32_t *)(&src_sz), comp_src, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK || src_sz != orig_sz) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, orig_sz); goto done; } hdr = (QzGzH_T *)comp_src; produce = hdr->extra.qz_e.dest_sz; /*wrap unknown block*/ memset(hdr + qzGzipHeaderSz(), 'Q', (size_t)produce); /*do Decompress Data*/ rc = qzDecompress(&sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_FAIL && rc != QZ_DATA_ERROR) { QZ_ERROR("FAILED: Decompression success with Error Unknown Gzip block\n"); goto done; } rc = 0; done: qzFree(orig_src); qzFree(comp_src); qzFree(decomp_src); (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int qzDecompressForceSW(void) { int rc = 0; QzGzH_T *hdr = NULL; QzSession_T sess = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, src_sz, comp_sz, decomp_sz; QzSessionParams_T params = {0}; uint32_t consume, produce; orig_sz = comp_sz = decomp_sz = USDM_ALLOC_MAX_SZ; orig_src = qzMalloc(orig_sz, 0, PINNED_MEM); comp_src = qzMalloc(comp_sz, 0, PINNED_MEM); decomp_src = qzMalloc(orig_sz, 0, PINNED_MEM); if (orig_src == NULL || comp_src == NULL || decomp_src == NULL) { QZ_ERROR("Malloc Memory for testing %s error\n", __func__); goto done; } rc = qzInit(&sess, 1); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit for testing %s error, return: %d\n", __func__, rc); goto done; } assert(!qzGetDefaults(¶ms)); params.hw_buff_sz = QZ_HW_BUFF_MAX_SZ; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } /*compress Data*/ src_sz = orig_sz; genRandomData(orig_src, orig_sz); rc = qzCompress(&sess, orig_src, (uint32_t *)(&src_sz), comp_src, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK || src_sz != orig_sz) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, orig_sz); goto done; } hdr = (QzGzH_T *)comp_src; consume = hdr->extra.qz_e.src_sz; produce = hdr->extra.qz_e.dest_sz; qzTeardownSession(&sess); /*Scenario1: produce > DEST_SZ(params.hw_buff_sz)*/ /*set minimum hw size 2K*/ params.hw_buff_sz = 2 * 1024; while (produce < DEST_SZ(params.hw_buff_sz)) { params.hw_buff_sz *= 2; } QZ_DEBUG("produce: %d, DEST_SZ(hw_sz): %d\n", produce, DEST_SZ(params.hw_buff_sz)); rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("ERROR: qzSetupSession FAILED with return value: %d\n", rc); goto done; } rc = qzDecompress(&sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_OK || decomp_sz != orig_sz || memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Decompression success with Error GipHeader\n"); goto done; } (void)qzTeardownSession(&sess); /*Scenario2: consume > qzSess->sess_params.hw_buff_sz*/ /*set maximum hw size 1M*/ params.hw_buff_sz = QATZIP_MAX_HW_SZ; while (consume < params.hw_buff_sz) { params.hw_buff_sz /= 2; } QZ_DEBUG("consume: %d, hw_sz: %d\n", consume, params.hw_buff_sz); rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("ERROR: qzSetupSession FAILED with return value: %d\n", rc); goto done; } rc = qzDecompress(&sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_OK || decomp_sz != orig_sz || memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Decompression success with Error GipHeader\n"); goto done; } done: (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int qzDecompressStandalone(void) { int rc = 0; QzSession_T sess = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, src_sz, comp_sz, decomp_sz; QzSessionParams_T params = {0}; orig_sz = src_sz = comp_sz = decomp_sz = 4 * KB; orig_src = calloc(1, orig_sz); comp_src = calloc(1, comp_sz); decomp_src = calloc(1, decomp_sz); if (orig_src == NULL || comp_src == NULL || decomp_src == NULL) { QZ_ERROR("Malloc Memory for testing %s error\n", __func__); goto done; } rc = qzInit(&sess, 1); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit for testing %s error, return: %d\n", __func__, rc); goto done; } assert(!qzGetDefaults(¶ms)); params.hw_buff_sz = 1 * KB; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } genRandomData(orig_src, orig_sz); rc = qzCompress(&sess, orig_src, (uint32_t *)(&src_sz), comp_src, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK || src_sz != orig_sz) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, orig_sz); goto done; } rc = qzDecompress(&sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_OK || decomp_sz != orig_sz || memcmp(orig_src, decomp_src, orig_sz)) { QZ_ERROR("ERROR: Decompression failed, orig_sc:%lu != decomp_src:%lu\n", orig_sz, decomp_sz); goto done; } rc = 0; done: free(orig_src); free(comp_src); free(decomp_src); (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int qzCompressFailedAtBufferOverflow(void) { int rc = QZ_BUF_ERROR; QzSession_T sess = {0}; QzSessionParams_T params = {0}; uint8_t *src, *low_comp, *comp, *low_decomp; size_t orig_sz = 64 * KB, low_comp_sz = 1 * KB, comp_sz = orig_sz, low_decomp_sz = 1 * KB; src = calloc(1, orig_sz); low_comp = calloc(1, low_comp_sz); comp = calloc(1, comp_sz); low_decomp = calloc(1, low_decomp_sz); if (NULL == src || NULL == low_comp || NULL == comp || NULL == low_decomp) { goto done; } rc = qzInit(&sess, 1); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit for testing %s error, return: %d\n", __func__, rc); goto done; } assert(!qzGetDefaults(¶ms)); params.hw_buff_sz = 1 * KB; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } genRandomData(src, orig_sz); rc = qzCompress(&sess, src, (uint32_t *)(&orig_sz), comp, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression fail with overflow buffer length:rc = %d\n", rc); goto done; } rc = 0; rc = qzDecompress(&sess, comp, (uint32_t *)(&comp_sz), low_decomp, (uint32_t *)(&low_decomp_sz)); if (rc != QZ_BUF_ERROR) { QZ_ERROR("FAILED: Decompression success with overflow buffer length:rc = %d\n", rc); goto done; } rc = 0; orig_sz = 64 * KB; rc = qzCompress(&sess, src, (uint32_t *)(&orig_sz), low_comp, (uint32_t *)(&low_comp_sz), 1); if (rc != QZ_BUF_ERROR) { QZ_ERROR("FAILED: Compression success with overflow buffer length:rc = %d\n", rc); goto done; } rc = 0; done: free(src); free(comp); free(low_comp); free(low_decomp); (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int doQzCompressCrcCheck(size_t orig_sz) { int rc = QZ_BUF_ERROR; QzSession_T sess = {0}; uint8_t *src, *comp; size_t comp_sz = orig_sz; unsigned long crc_sw = 0, crc_qz = 0; src = calloc(1, orig_sz); comp = calloc(1, comp_sz); if (NULL == src || NULL == comp) { goto done; } genRandomData(src, orig_sz); crc_sw = crc32(crc_sw, src, GET_LOWER_32BITS(orig_sz)); rc = qzCompressCrc(&sess, src, (uint32_t *)(&orig_sz), comp, (uint32_t *)(&comp_sz), 1, &crc_qz); if (rc != QZ_OK) { QZ_ERROR("ERROR: Compression fail with overflow buffer length:rc = %d\n", rc); goto done; } if (crc_sw != crc_qz) { QZ_ERROR("ERROR: Compression fail on CRC check: SW CRC %lu, QATzip CRC %lu\n", crc_sw, crc_qz); rc = QZ_FAIL; } done: free(src); free(comp); (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int qzCompressCrcCheck(void) { size_t test_sz_qz = (64 * KB), test_sz_sw = (QZ_COMP_THRESHOLD_DEFAULT - 1); size_t test_sz[] = {test_sz_qz, test_sz_sw}; int i, rc = 0; for (i = 0; i < ARRAY_LEN(test_sz); i++) { rc = doQzCompressCrcCheck(test_sz[i]); if (QZ_OK != rc) { goto done; } } done: return rc; } int qzCompressSWL9DecompressHW(void) { int rc = 0; QzSession_T sess = {0}; uint8_t *orig_src, *comp_src, *decomp_src; size_t orig_sz, src_sz, comp_sz, decomp_sz; QzSessionParams_T params = {0}; orig_sz = comp_sz = decomp_sz = 4 * MB; orig_src = qzMalloc(orig_sz, 0, COMMON_MEM); comp_src = qzMalloc(comp_sz, 0, COMMON_MEM); decomp_src = qzMalloc(orig_sz, 0, COMMON_MEM); if (orig_src == NULL || comp_src == NULL || decomp_src == NULL) { QZ_ERROR("Malloc Memory for testing %s error\n", __func__); goto done; } rc = qzInit(&sess, 1); if (QZ_INIT_HW_FAIL(rc)) { QZ_ERROR("qzInit for testing %s error, return: %d\n", __func__, rc); goto done; } assert(!qzGetDefaults(¶ms)); params.input_sz_thrshold = orig_sz + 1; params.comp_lvl = QZ_DEFLATE_COMP_LVL_MAXIMUM; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } /*compress data by software*/ src_sz = orig_sz; genRandomData(orig_src, orig_sz); rc = qzCompress(&sess, orig_src, (uint32_t *)(&src_sz), comp_src, (uint32_t *)(&comp_sz), 1); if (rc != QZ_OK || src_sz != orig_sz) { QZ_ERROR("ERROR: Compression FAILED with return value: %d\n", rc); QZ_ERROR("ERROR: After Compression src_sz: %lu != org_src_sz: %lu \n!", src_sz, orig_sz); goto done; } /*decompress data by hardware*/ params.input_sz_thrshold = QZ_COMP_THRESHOLD_DEFAULT; rc = qzSetupSession(&sess, ¶ms); if (QZ_SETUP_SESSION_FAIL(rc)) { QZ_ERROR("qzSetupSession for testing %s error, return: %d\n", __func__, rc); goto done; } rc = qzDecompress(&sess, comp_src, (uint32_t *)(&comp_sz), decomp_src, (uint32_t *)(&decomp_sz)); if (rc != QZ_OK || decomp_sz != orig_sz || memcmp(orig_src, decomp_src, (size_t)orig_sz)) { QZ_ERROR("ERROR: Decompression success with Error GipHeader\n"); goto done; } done: qzFree(orig_src); qzFree(comp_src); qzFree(decomp_src); (void)qzTeardownSession(&sess); qzClose(&sess); return rc; } int qzFuncTests(void) { int i = 0; int (*sw_failover_func_tests[])(void) = { qzDecompressFailedAtUnknownGzipHeader, qzDecompressSWFailedAtUnknownGzipBlock, qzDecompressHWFailedAtUnknownGzipBlock, qzDecompressStandalone, qzDecompressForceSW, qzCompressSWL9DecompressHW, }; for (i = 0; i < ARRAY_LEN(sw_failover_func_tests); i++) { if (sw_failover_func_tests[i]()) { QZ_ERROR("SWFailOverFunc[%d] : failed\n", i); return -1; } } QZ_PRINT("SWFailOverFunc test : Passed\n"); int (*qz_compress_negative_tests[])(void) = { qzCompressFailedAtBufferOverflow, }; for (i = 0; i < ARRAY_LEN(qz_compress_negative_tests); i++) { if (qz_compress_negative_tests[i]()) { QZ_ERROR("qzCompressNegative[%d] : failed\n", i); return -1; } } QZ_PRINT("qzCompressNegative test : Passed\n"); int (*qz_compress_crc_positive[])(void) = { qzCompressCrcCheck, }; for (i = 0; i < ARRAY_LEN(qz_compress_crc_positive); i++) { if (qz_compress_crc_positive[i]()) { QZ_ERROR("qz_compress_crc_positive[%d] : failed\n", i); return -1; } } QZ_PRINT("qz_compress_crc_positive test : Passed\n"); return 0; } void *qzCompressStreamWithPendingOut(void *thd_arg) { int rc; unsigned char *src = NULL, *dest = NULL; size_t src_sz, dest_sz; QzStream_T comp_strm = {0}; QzSessionParams_T params = {0}; unsigned int last = 0; char *filename = NULL; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; unsigned char *out; unsigned int out_sz = 0; QzSession_T sess = {0}; QZ_DEBUG("Hello from qzCompressStreamWithPendingOut\n"); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInit rc = %d\n", rc); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = DEFAULT_STREAM_BUF_SZ; if (qzSetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } //set by default configurations rc = qzSetupSession(&sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { pthread_exit((void *)"qzSetupSession failed"); } QZ_DEBUG("qzSetupSession rc = %d\n", rc); if (gen_data) { src_sz = QATZIP_MAX_HW_SZ; dest_sz = QATZIP_MAX_HW_SZ; src = qzMalloc(src_sz, 0, COMMON_MEM); dest = qzMalloc(dest_sz, 0, COMMON_MEM); } else { src = test_arg->src; src_sz = test_arg->src_sz; dest = test_arg->comp_out; dest_sz = test_arg->comp_out_sz; filename = (char *) calloc(1, strlen(g_input_file_name) + 4); if (NULL != filename) { snprintf(filename, strlen(g_input_file_name) + 4, "%s.%s", g_input_file_name, "gz"); } else { QZ_ERROR("Calloc failed\n"); goto done; } } if (!src || !dest) { QZ_ERROR("Malloc failed\n"); goto done; } if (gen_data) { QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); } out = dest; comp_strm.in = src; comp_strm.out = dest; comp_strm.in_sz = src_sz; comp_strm.out_sz = 8192; last = 1; if (comp_strm.in_sz) { rc = qzCompressStream(&sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("qzCompressStream FAILED, return: %d", rc); goto done; } out_sz += comp_strm.out_sz; QZ_DEBUG("qzCompressStream in: in:%p out:%p in_sz:%ud out_sz:%ud last:%d", comp_strm.in, comp_strm.out, comp_strm.in_sz, comp_strm.out_sz, last); } while (comp_strm.pending_out > 0) { comp_strm.in = src; comp_strm.out += comp_strm.out_sz; comp_strm.in_sz = 0; comp_strm.out_sz = 8192; last = 1; rc = qzCompressStream(&sess, &comp_strm, last); if (rc != QZ_OK) { QZ_ERROR("qzCompressStream FAILED, return: %d", rc); goto done; } out_sz += comp_strm.out_sz; QZ_DEBUG("qzCompressStream in: in:%p out:%p in_sz:%ud out_sz:%ud last:%d", comp_strm.in, comp_strm.out, comp_strm.in_sz, comp_strm.out_sz, last); } dumpOutputData(out_sz, out, filename); qzEndStream(&sess, &comp_strm); done: if (gen_data) { qzFree(src); qzFree(dest); } else { free(filename); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } void *forkResourceCheck(void *arg) { int rc = -1; pid_t pid; int status; char max_hp_str[10] = {0}; int hp_params_fd; size_t number_huge_pages; char *stop = NULL; QzSession_T sess = {0}; QZ_DEBUG("Hello from forkResourceCheck\n"); QZ_PRINT("This is parent process, my pid = %d\n", getpid()); QZ_PRINT("Before qzInit, qz_init_status in parent process is %d\n", g_process.qz_init_status); if (!((TestArg_T *)arg)->init_engine_disabled) { rc = qzInit(&sess, ((TestArg_T *)arg)->sw_backup); if (QZ_INIT_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } } pid = fork(); if (pid > 0) { QZ_PRINT("After qzInit, qz_init_status in parent process is %d\n", g_process.qz_init_status); QZ_PRINT("instID in parent process is %s\n", g_process.qz_inst[0].instance_info.instID); hp_params_fd = open(MAX_HUGEPAGE_FILE, O_RDONLY); if (hp_params_fd < 0) { QZ_ERROR("Open %s failed\n", MAX_HUGEPAGE_FILE); goto done; } if (read(hp_params_fd, max_hp_str, sizeof(max_hp_str)) < 0) { QZ_ERROR("Read max_huge_pages from %s failed\n", MAX_HUGEPAGE_FILE); close(hp_params_fd); goto done; } number_huge_pages = strtoul(max_hp_str, &stop, 0); if (*stop != '\n') { QZ_ERROR("convert from %s to size_t failed\n", max_hp_str); close(hp_params_fd); goto done; } QZ_PRINT("After qzInit, number_huge_pages in parent process is %d\n", (int)number_huge_pages); close(hp_params_fd); wait(&status); } else if (pid == 0) { sleep(2); QZ_PRINT("This is child process, my pid = %d\n", getpid()); QZ_PRINT("This is child process, my ppid = %d\n", getppid()); g_process.qz_init_status = QZ_NONE; QZ_PRINT("Before qzInit, qz_init_status in child process is %d\n", g_process.qz_init_status); if (!((TestArg_T *)arg)->init_engine_disabled) { rc = qzInit(&sess, ((TestArg_T *)arg)->sw_backup); if (QZ_INIT_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_PRINT("After qzInit, qz_init_status in child process is %d\n", g_process.qz_init_status); QZ_PRINT("instID in child process is %s\n", g_process.qz_inst[0].instance_info.instID); } hp_params_fd = open(MAX_HUGEPAGE_FILE, O_RDONLY); if (hp_params_fd < 0) { QZ_ERROR("Open %s failed\n", MAX_HUGEPAGE_FILE); goto done; } if (read(hp_params_fd, max_hp_str, sizeof(max_hp_str)) < 0) { QZ_ERROR("Read max_huge_pages from %s failed\n", MAX_HUGEPAGE_FILE); close(hp_params_fd); goto done; } number_huge_pages = strtoul(max_hp_str, &stop, 0); if (*stop != '\n') { QZ_ERROR("convert from %s to size_t failed\n", max_hp_str); close(hp_params_fd); goto done; } QZ_PRINT("After qzInit, number_huge_pages in child process is %d\n", (int)number_huge_pages); close(hp_params_fd); exit(0); } else { perror("fork"); } done: pthread_exit((void *)NULL); } void *qzDecompressStreamWithBufferError(void *thd_arg) { int rc; unsigned char *src = NULL, *dest = NULL; size_t src_sz, dest_sz; QzStream_T decomp_strm = {0}; QzSessionParams_T params = {0}; unsigned int last = 1; TestArg_T *test_arg = (TestArg_T *)thd_arg; const int gen_data = test_arg->gen_data; QzSession_T sess = {0}; QZ_DEBUG("Hello from qzDecompressStreamWithBufferError\n"); rc = qzInit(&sess, test_arg->sw_backup); if (QZ_INIT_FAIL(rc)) { pthread_exit((void *)"qzInit failed"); } QZ_DEBUG("qzInit rc = %d\n", rc); if (qzGetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: fail to get default params.\n"); goto done; } params.strm_buff_sz = QZ_STRM_BUFF_SZ_DEFAULT - 1; params.sw_backup = 0; if (qzSetDefaults(¶ms) != QZ_OK) { QZ_ERROR("Err: set params fail with incorrect compress params.\n"); goto done; } //set by default configurations rc = qzSetupSession(&sess, NULL); if (QZ_SETUP_SESSION_FAIL(rc)) { pthread_exit((void *)"qzSetupSession failed"); } QZ_DEBUG("qzSetupSession rc = %d\n", rc); if (gen_data) { src_sz = QATZIP_MAX_HW_SZ; dest_sz = QATZIP_MAX_HW_SZ; src = qzMalloc(src_sz, 0, COMMON_MEM); dest = qzMalloc(dest_sz, 0, COMMON_MEM); } else { src = test_arg->src; src_sz = test_arg->src_sz; dest = test_arg->comp_out; dest_sz = test_arg->comp_out_sz; } if (!src || !dest) { QZ_ERROR("Malloc failed\n"); goto done; } if (gen_data) { QZ_DEBUG("Gen Data...\n"); genRandomData(src, src_sz); } /*dest_recv_sz > dest_avail_len*/ decomp_strm.in = src; decomp_strm.out = dest; decomp_strm.in_sz = src_sz; decomp_strm.out_sz = dest_sz; rc = qzDecompressStream(&sess, &decomp_strm, last); assert(QZ_FAIL == rc); rc = qzEndStream(&sess, &decomp_strm); done: if (gen_data) { qzFree(src); qzFree(dest); } (void)qzTeardownSession(&sess); pthread_exit((void *)NULL); } #define STR_INTER(N) #N #define STR(N) STR_INTER(N) #define USAGE_STRING(MAX_LVL) \ "Usage: %s [options]\n" \ "\n" \ "Required options:\n" \ "\n" \ " -m testMode 1 test memcpy feature\n" \ " 2 test Memory\n" \ " 3 test comp/decomp by default parameters\n" \ " 4 test comp/decomp by configurable parameters\n" \ " 5 test comp/decomp by format parameters\n" \ " 6 test set default configurable parameters\n" \ "\n" \ "Optional options can be:\n" \ "\n" \ " -i inputfile input source file\n" \ " default by random generate data \n" \ " -t thread_count maximum forks permitted in the current thread\n" \ " 0 means no forking permitted. \n" \ " -l loop count default is 2\n" \ " -v verify, disabled by default\n" \ " -e init engine enable | disable. enabled by default\n" \ " -s init session enable | disable. enabled by default\n" \ " -A comp_algorithm deflate | lz4 | lz4s\n" \ " -B swBack 0 means disable sw\n" \ " 1 means enable sw\n" \ " -C hw_buff_sz default 64K\n" \ " -b block_size If set this option, the test will split test\n" \ " data into pieces. qzCompress/qzDecompress will\n"\ " de/compress block_size bytes every time.\n" \ " It must be the power of 2. The minimum is 4k,\n" \ " and maximum is 1M. Default is -1, don't split \n" \ " the test data.\n" \ " -D direction comp | decomp | both\n" \ " -F format [comp format]:[orig data size]/...\n" \ " -L comp_lvl 1 - " STR(MAX_LVL) "\n" \ " -O data_fmt deflate | gzip | gzipext | deflate_4B | lz4 | lz4s\n"\ " -T huffmanType static | dynamic\n" \ " -r req_cnt_thrshold max in-flight request num, default is 16\n" \ " -S thread_sleep the unit is milliseconds, default is a random time\n" \ " -P polling set polling mode, default is periodical polling\n" \ " -M svm set perf mode with file input, default is non\n" \ " svm mode. When set to svm, all memory will\n" \ " be allocated with malloc instead of qzMalloc\n" \ " This option is only applied to test case 4\n" \ " -p compress_buf_type pinned | common, default is common\n" \ " This option is only applied to file compression test in case 4\n" \ " If set common, memory of compress buffer will be allocated through malloc\n" \ " If set pinned, memory of compress buffer will be allocated in huge page, the\n" \ " allocation limit is 2M\n" \ " -h Print this help message\n" void qzPrintUsageAndExit(char *progName) { QZ_ERROR(USAGE_STRING(COMP_LVL_MAXIMUM), progName); exit(-1); } static int qz_do_g_process_Check(void) { if (g_process.qz_init_status == QZ_OK && g_process.sw_backup == 1 && (g_process.num_instances == G_PROCESS_NUM_INSTANCES_12 || g_process.num_instances == G_PROCESS_NUM_INSTANCES_4 || g_process.num_instances == G_PROCESS_NUM_INSTANCES_16 || g_process.num_instances == G_PROCESS_NUM_INSTANCES_32 || g_process.num_instances == G_PROCESS_NUM_INSTANCES_8 || g_process.num_instances == G_PROCESS_NUM_INSTANCES_64) && g_process.qat_available == CPA_TRUE) { return QZ_OK; } else { return QZ_FAIL; } } int main(int argc, char *argv[]) { int rc = 0, ret = 0, rc_check = 0; int i = 0; void *p_rc; int thread_count = 1, test = 0; ServiceType_T service = COMP; pthread_t threads[100] = {0}; TestArg_T test_arg[100] = {0}; struct sigaction s1; int block_size = -1; PinMem_T compress_buf_type = COMMON_MEM; TestArg_T args = {0}; unsigned char *input_buf = NULL; unsigned int input_buf_len = QATZIP_MAX_HW_SZ; int thread_sleep = 0; s1.sa_handler = sigInt; sigemptyset(&s1.sa_mask); s1.sa_flags = 0; sigaction(SIGINT, &s1, NULL); const char *optstring = "m:t:A:C:D:F:L:T:i:l:e:s:r:B:O:S:P:M:b:p:vh"; int opt = 0, loop_cnt = 2, verify = 0; int disable_init_engine = 0, disable_init_session = 0; char *stop = NULL; QzThdOps *qzThdOps = NULL; QzBlock_T *qzBlocks = NULL; errno = 0; QzSessionParamsDeflate_T default_params = {{0}}; rc = qzGetDefaultsDeflate(&default_params); if (rc != QZ_OK) { QZ_ERROR("Get default params error\n"); return -1; } args.test_format = TEST_GZIPEXT; args.comp_algorithm = default_params.common_params.comp_algorithm; args.sw_backup = default_params.common_params.sw_backup; args.hw_buff_sz = default_params.common_params.hw_buff_sz; args.comp_lvl = default_params.common_params.comp_lvl; args.huffman_hdr = default_params.huffman_hdr; args.polling_mode = default_params.common_params.polling_mode; args.req_cnt_thrshold = default_params.common_params.req_cnt_thrshold; args.max_forks = default_params.common_params.max_forks; while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { case 'm': // test case test = GET_LOWER_32BITS(strtol(optarg, &stop, 0)); if (*stop != '\0' || errno) { QZ_ERROR("Error input: %s\n", optarg); return -1; } break; case 't': thread_count = GET_LOWER_32BITS(strtol(optarg, &stop, 0)); args.max_forks = thread_count; if (*stop != '\0' || errno || thread_count > 100) { QZ_ERROR("Error thread count arg: %s\n", optarg); return -1; } break; case 'A': if (strcmp(optarg, "deflate") == 0) { args.comp_algorithm = QZ_DEFLATE; } else if (strcmp(optarg, "lz4") == 0) { args.comp_algorithm = QZ_LZ4; } else if (strcmp(optarg, "lz4s") == 0) { args.comp_algorithm = QZ_LZ4s; } else { QZ_ERROR("Error service arg: %s\n", optarg); return -1; } break; case 'O': if (strcmp(optarg, "deflate") == 0) { args.test_format = TEST_DEFLATE; } else if (strcmp(optarg, "gzip") == 0) { args.test_format = TEST_GZIP; } else if (strcmp(optarg, "gzipext") == 0) { args.test_format = TEST_GZIPEXT; } else if (strcmp(optarg, "deflate_4B") == 0) { args.test_format = TEST_DEFLATE_4B; } else if (strcmp(optarg, "lz4") == 0) { args.test_format = TEST_LZ4; } else if (strcmp(optarg, "lz4s") == 0) { args.test_format = TEST_LZ4S; } else { QZ_ERROR("Error service arg: %s\n", optarg); return -1; } break; case 'B': args.sw_backup = GET_LOWER_32BITS(strtol(optarg, &stop, 0)); if (*stop != '\0' || errno || (args.sw_backup != 0 && args.sw_backup != 1)) { QZ_ERROR("Error input: %s\n", optarg); return -1; } break; case 'C': args.hw_buff_sz = GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); if (*stop != '\0' || errno || args.hw_buff_sz > USDM_ALLOC_MAX_SZ / 2) { QZ_ERROR("Error chunkSize arg: %s\n", optarg); return -1; } break; case 'D': if (strcmp(optarg, "comp") == 0) { service = COMP; } else if (strcmp(optarg, "decomp") == 0) { service = DECOMP; } else if (strcmp(optarg, "both") == 0) { service = BOTH; } else { QZ_ERROR("Error service arg: %s\n", optarg); return -1; } break; case 'F': qzBlocks = parseFormatOption(optarg); if (NULL == qzBlocks) { QZ_ERROR("Error format arg: %s\n", optarg); return -1; } break; case 'L': args.comp_lvl = GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); if (*stop != '\0' || errno || \ args.comp_lvl > COMP_LVL_MAXIMUM || args.comp_lvl <= 0) { QZ_ERROR("Error compLevel arg: %s\n", optarg); return -1; } break; case 'T': if (strcmp(optarg, "static") == 0) { args.huffman_hdr = QZ_STATIC_HDR; } else if (strcmp(optarg, "dynamic") == 0) { args.huffman_hdr = QZ_DYNAMIC_HDR; } else { QZ_ERROR("Error huffman arg: %s\n", optarg); return -1; } break; case 'l': loop_cnt = GET_LOWER_32BITS(strtol(optarg, &stop, 0)); if (*stop != '\0' || errno) { QZ_ERROR("Error loop count arg: %s\n", optarg); return -1; } break; case 'v': verify = 1; break; case 'i': g_input_file_name = optarg; break; case 'e': if (strcmp(optarg, "enable") == 0) { disable_init_engine = 0; } else if (strcmp(optarg, "disable") == 0) { disable_init_engine = 1; } else { QZ_ERROR("Error init qat engine arg: %s\n", optarg); return -1; } break; case 's': if (strcmp(optarg, "enable") == 0) { disable_init_session = 0; } else if (strcmp(optarg, "disable") == 0) { disable_init_session = 1; } else { QZ_ERROR("Error init qat session arg: %s\n", optarg); return -1; } break; case 'r': args.req_cnt_thrshold = GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); if (*stop != '\0' || errno) { QZ_ERROR("Error req_cnt_thrshold arg: %s\n", optarg); return -1; } break; case 'S': thread_sleep = GET_LOWER_32BITS(strtol(optarg, &stop, 0)); if (*stop != '\0' || errno) { QZ_ERROR("Error thread_sleep arg: %s\n", optarg); return -1; } thread_sleep *= 1000; break; case 'P': if (strcmp(optarg, "busy") == 0) { args.polling_mode = QZ_BUSY_POLLING; } else { QZ_ERROR("Error set polling mode: %s\n", optarg); return -1; } break; case 'M': if (strcmp(optarg, "svm") == 0) { g_perf_svm = true; } else { QZ_ERROR("Error set perf mode: %s\n", optarg); return -1; } break; case 'b': block_size = GET_LOWER_32BITS(strtol(optarg, &stop, 0)); if (*stop != '\0' || errno || ((block_size & (block_size - 1)) != 0) || block_size < 4096 || block_size > 1024 * 1024) { QZ_ERROR("Error block size arg: %s, please set it to the power of 2 in range of 4k to 1M.\n", optarg); return -1; } break; case 'p': if (strcmp(optarg, "pinned") == 0) { compress_buf_type = PINNED_MEM; } else if (strcmp(optarg, "common") == 0) { compress_buf_type = COMMON_MEM; } else { QZ_ERROR("Error compress_buf_type arg: %s\n", optarg); return -1; } break; default: qzPrintUsageAndExit(argv[0]); } } if (test == 0) { qzPrintUsageAndExit(argv[0]); } switch (test) { case 1: QZ_ERROR("Test mode 1 has been removed\n"); return 0; case 2: qzThdOps = qzMemFuncTest; break; case 3: QZ_ERROR("Test mode 3 has been removed\n"); return 0; case 4: qzThdOps = qzCompressAndDecompress; break; case 5: qzThdOps = qzCompressDecompressWithFormatOption; break; case 6: qzThdOps = qzSetupParamFuncTest; break; case 7: qzThdOps = qzDecompressSwQz; break; case 8: qzThdOps = qzCompressDecompressSwQZMixed; break; case 9: qzThdOps = qzCompressStreamAndDecompress; break; case 10: qzThdOps = qzCompressStreamOnCommonMem; break; case 11: qzThdOps = qzCompressStreamOutput; break; case 12: qzThdOps = qzDecompressStreamInput; break; case 13: qzThdOps = qzCompressStreamInvalidChunkSize; break; case 14: qzThdOps = qzCompressStreamInvalidQzStreamParam; break; case 15: qzThdOps = qzDecompressStreamNegParam; break; case 16: qzThdOps = qzEndStreamNegParam; break; case 17: return qzFuncTests(); break; case 18: test_thread_safe_flag = 1; qzThdOps = qzCompressAndDecompress; break; case 19: qzThdOps = qzInitPcieCountCheck; break; case 20: qzThdOps = qzCompressStreamWithPendingOut; break; case 21: qzThdOps = forkResourceCheck; break; case 22: qzThdOps = qzDecompressStreamWithBufferError; break; default: goto done; } if (g_input_file_name != NULL) { FILE *file; struct stat file_state; if (stat(g_input_file_name, &file_state)) { QZ_ERROR("ERROR: fail to get stat of file %s\n", g_input_file_name); return -1; } input_buf_len = GET_LOWER_32BITS((file_state.st_size > QATZIP_MAX_HW_SZ ? QATZIP_MAX_HW_SZ : file_state.st_size)); if (test == 4 || test == 10 || test == 11 || test == 12) { input_buf_len = GET_LOWER_32BITS(file_state.st_size); } if (compress_buf_type == PINNED_MEM) { if (input_buf_len > MAX_HUGE_PAGE_SZ) { QZ_ERROR("ERROR: only can allocate 2M memory in huge page\n"); return -1; } input_buf = qzMalloc(input_buf_len, 0, PINNED_MEM); } else { input_buf = malloc(input_buf_len); } if (!input_buf) { QZ_ERROR("ERROR: fail to alloc %d bytes of memory with qzMalloc\n", input_buf_len); return -1; } file = fopen(g_input_file_name, "rb"); if (!file) { QZ_ERROR("ERROR: fail to read file %s\n", g_input_file_name); goto done; } if (fread(input_buf, 1, input_buf_len, file) != input_buf_len) { QZ_ERROR("ERROR: fail to read file %s\n", g_input_file_name); fclose(file); goto done; } else { QZ_DEBUG("Read %d bytes from file %s\n", input_buf_len, g_input_file_name); } fclose(file); } for (i = 0; i < thread_count; i++) { test_arg[i] = args; test_arg[i].thd_id = i; test_arg[i].service = service; test_arg[i].verify_data = verify; test_arg[i].debug = 0; test_arg[i].count = loop_cnt; test_arg[i].src_sz = GET_LOWER_32BITS(input_buf_len); if (compress_buf_type == PINNED_MEM) { test_arg[i].comp_out_sz = test_arg[i].src_sz; test_arg[i].src = input_buf; test_arg[i].comp_out = qzMalloc(test_arg[i].comp_out_sz, 0, PINNED_MEM); test_arg[i].decomp_out_sz = test_arg[i].src_sz; test_arg[i].decomp_out = qzMalloc(test_arg[i].decomp_out_sz, 0, PINNED_MEM); } else { test_arg[i].comp_out_sz = test_arg[i].src_sz * 2; test_arg[i].src = input_buf; test_arg[i].comp_out = malloc(test_arg[i].comp_out_sz); test_arg[i].decomp_out_sz = test_arg[i].src_sz * 5; test_arg[i].decomp_out = malloc(test_arg[i].decomp_out_sz); } test_arg[i].gen_data = g_input_file_name ? 0 : 1; test_arg[i].init_engine_disabled = disable_init_engine; test_arg[i].init_sess_disabled = disable_init_session; test_arg[i].ops = qzThdOps; test_arg[i].blks = qzBlocks; test_arg[i].thread_sleep = thread_sleep; test_arg[i].block_size = block_size; if (!test_arg[i].comp_out || !test_arg[i].decomp_out) { QZ_ERROR("ERROR: fail to create memory for thread %d\n", i); goto done; } } srand((uint32_t)getpid()); (void)gettimeofday(&g_timer_start, NULL); #ifdef ENABLE_THREAD_BARRIER pthread_barrier_init(&g_bar, NULL, thread_count); #endif for (i = 0; i < thread_count; i++) { rc = pthread_create(&threads[i], NULL, test_arg[i].ops, (void *)&test_arg[i]); if (0 != rc) { QZ_ERROR("Error from pthread_create %d\n", rc); goto done; } } #ifndef ENABLE_THREAD_BARRIER /*for qzCompressAndDecompress test*/ if (test == 4 || test == 18) { ret = pthread_mutex_lock(&g_cond_mutex); if (ret != 0) { QZ_ERROR("Failure to get Mutex Lock, status = %d\n", ret); goto done; } while (g_ready_thread_count < thread_count) { ret = pthread_cond_wait(&g_ready_cond, &g_cond_mutex); if (ret != 0) { pthread_mutex_unlock(&g_cond_mutex); QZ_ERROR("Failure calling pthread_cond_wait, status = %d\n", ret); goto done; } } g_ready_to_start = 1; ret = pthread_cond_broadcast(&g_start_cond); if (ret != 0) { pthread_mutex_unlock(&g_cond_mutex); QZ_ERROR("Failure calling pthread_cond_broadcast, status = %d\n", ret); goto done; } ret = pthread_mutex_unlock(&g_cond_mutex); if (ret != 0) { QZ_ERROR("Failure to release Mutex Lock, status = %d\n", ret); goto done; } } #endif for (i = 0; i < thread_count; i++) { timeCheck(10, i); rc = pthread_join(threads[i], (void *)&p_rc); if (0 != rc) { QZ_ERROR("Error from pthread_join %d\n", rc); break; } if (NULL != p_rc) { QZ_ERROR("Error from pthread_exit %s\n", (char *)p_rc); ret = -1; } } #ifdef ENABLE_THREAD_BARRIER pthread_barrier_destroy(&g_bar); #endif if (test == 18) { rc_check = qz_do_g_process_Check(); if (QZ_OK == rc_check) { QZ_PRINT("Check g_process PASSED\n"); } else { ret = -1; QZ_PRINT("Check g_process FAILED\n"); } } done: if (NULL != qzBlocks) { QzBlock_T *tmp, *blk = qzBlocks; while (blk) { tmp = blk; blk = blk->next; free(tmp); } } /* free memory */ if (NULL != input_buf) { if (compress_buf_type == PINNED_MEM) { qzFree(input_buf); } else { free(input_buf); } } for (i = 0; i < thread_count; i++) { if (NULL != test_arg[i].comp_out) { if (compress_buf_type == PINNED_MEM) { qzFree(test_arg[i].comp_out); } else { free(test_arg[i].comp_out); } } if (NULL != test_arg[i].decomp_out) { if (compress_buf_type == PINNED_MEM) { qzFree(test_arg[i].decomp_out); } else { free(test_arg[i].decomp_out); } } } return (ret != 0) ? ret : rc; } QATzip-1.2.0/test/performance_tests/000077500000000000000000000000001456106226300173715ustar00rootroot00000000000000QATzip-1.2.0/test/performance_tests/config_file/000077500000000000000000000000001456106226300216355ustar00rootroot00000000000000QATzip-1.2.0/test/performance_tests/config_file/4xxx/000077500000000000000000000000001456106226300225505ustar00rootroot00000000000000QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev0.conf000066400000000000000000000127141456106226300252550ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev1.conf000066400000000000000000000127141456106226300252560ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev2.conf000066400000000000000000000127141456106226300252570ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev3.conf000066400000000000000000000127141456106226300252600ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev4.conf000066400000000000000000000127141456106226300252610ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev5.conf000066400000000000000000000127141456106226300252620ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev6.conf000066400000000000000000000127141456106226300252630ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/4xxx/4xxx_dev7.conf000066400000000000000000000127141456106226300252640ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ################################################################ [GENERAL] ServicesEnabled = dc ConfigVersion = 2 #Default value for FW Auth loading FirmwareAuthEnabled = 1 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable SSF features (CNV and BnP) StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # Default value for power management idle interrupt delay PmIdleInterruptDelay = 0 # This flag is to enable power management idle support PmIdleSupport = 1 # This flag is to enable key protection technology KptEnabled = 1 # Define the maximum SWK count per function can have # Default value is 1, the maximum value is 128 KptMaxSWKPerFn = 1 # Define the maximum SWK count per pasid can have # Default value is 1, the maximum value is 128 KptMaxSWKPerPASID = 1 # Define the maximum SWK lifetime in second # Default value is 0 (eternal of life) # The maximum value is 31536000 (one year) KptMaxSWKLifetime = 31536000 # Flag to define whether to allow SWK to be shared among processes # Default value is 0 (shared mode is off) KptSWKShared = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 # Data Compression - Kernel instance #0 Dc0Name = "IPComp0" Dc0IsPolled = 0 Dc0CoreAffinity = 0 ############################################## # ADI Section for Scalable IOV ############################################## [SIOV] NumberAdis = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 6 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 1 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 1 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity =2 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity =3 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity =4 QATzip-1.2.0/test/performance_tests/config_file/c3xxx/000077500000000000000000000000001456106226300227125ustar00rootroot00000000000000QATzip-1.2.0/test/performance_tests/config_file/c3xxx/c3xxx_dev0.conf000066400000000000000000000132361456106226300255610ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################ [GENERAL] ServicesEnabled = dc # Set the service profile to determine available features # ===================================================================== # DEFAULT CRYPTO COMPRESSION CUSTOM1 # Asymmetric Crypto * * * # Symmetric Crypto * * * # Hash * * * * # Cipher * * * # MGF KeyGen * * # SSL/TLS KeyGen * * * # HKDF * * # Compression * * * # Decompression (stateless) * * * # Decompression (stateful) * * # Service Chaining * # Device Utilization * * * # Rate Limiting * * * # ===================================================================== ServicesProfile = DEFAULT ConfigVersion = 2 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 1 NumProcesses = 4 LimitDevAccess = 1 # Crypto - User instance #0 Cy0Name = "SSL0" Cy0IsPolled = 1 # List of core affinities Cy0CoreAffinity = 0 # Crypto - User instance #1 Cy1Name = "SSL1" Cy1IsPolled = 1 # List of core affinities Cy1CoreAffinity = 1 # Crypto - User instance #2 Cy2Name = "SSL2" Cy2IsPolled = 1 # List of core affinities Cy2CoreAffinity = 2 # Crypto - User instance #3 Cy3Name = "SSL3" Cy3IsPolled = 1 # List of core affinities Cy3CoreAffinity = 3 # Crypto - User instance #4 Cy4Name = "SSL4" Cy4IsPolled = 1 # List of core affinities Cy4CoreAffinity = 4 # Crypto - User instance #5 Cy5Name = "SSL5" Cy5IsPolled = 1 # List of core affinities Cy5CoreAffinity = 5 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 0 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 1 QATzip-1.2.0/test/performance_tests/config_file/c6xx/000077500000000000000000000000001456106226300225255ustar00rootroot00000000000000QATzip-1.2.0/test/performance_tests/config_file/c6xx/c6xx_dev0.conf000066400000000000000000000112671456106226300252110ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # version: QAT1.7.L.4.5.0-00034 ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 0 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 0 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 0 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 0 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 0 QATzip-1.2.0/test/performance_tests/config_file/c6xx/c6xx_dev1.conf000066400000000000000000000112671456106226300252120ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # version: QAT1.7.L.4.5.0-00034 ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 0 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 0 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 0 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 0 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 0 QATzip-1.2.0/test/performance_tests/config_file/c6xx/c6xx_dev2.conf000066400000000000000000000112671456106226300252130ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # version: QAT1.7.L.4.5.0-00034 ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 KptEnabled = 0 # This flag is to enable SSF features StorageEnabled = 0 # Disable public key crypto and prime number # services by specifying a value of 1 (default is 0) PkeServiceDisabled = 0 # Specify size of intermediate buffers for which to # allocate on-chip buffers. Legal values are 32 and # 64 (default is 64). Specify 32 to optimize for # compressing buffers <=32KB in size. DcIntermediateBufferSizeInKB = 64 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 0 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 0 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 0 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 0 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 0 QATzip-1.2.0/test/performance_tests/config_file/dh895xcc/000077500000000000000000000000001456106226300231745ustar00rootroot00000000000000QATzip-1.2.0/test/performance_tests/config_file/dh895xcc/dh895xcc_dev0.conf000066400000000000000000000105131456106226300263200ustar00rootroot00000000000000################################################################ # This file is provided under a dual BSD/GPLv2 license. When using or # redistributing this file, you may do so under either license. # # GPL LICENSE SUMMARY # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License 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. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. # The full GNU General Public License is included in this distribution # in the file called LICENSE.GPL. # # Contact Information: # Intel Corporation # # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # version: QAT1.7.L.4.5.0-00034 ################################################################ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 #Statistics, valid values: 1,0 statsGeneral = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsDc = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # This flag is to enable device auto reset on heartbeat error AutoResetOnError = 0 # This flag is to enable SSF features StorageEnabled = 0 ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 # Crypto - Kernel instance #0 Cy0Name = "IPSec0" Cy0IsPolled = 0 Cy0CoreAffinity = 0 ############################################## # User Process Instance Section ############################################## [SHIM] NumberCyInstances = 0 NumberDcInstances = 4 NumProcesses = 8 LimitDevAccess = 1 # Crypto - User instance #0 #Cy0Name = "SSL0" #Cy0IsPolled = 1 ## List of core affinities #Cy0CoreAffinity = 0 # Data Compression - User instance #0 Dc0Name = "Dc0" Dc0IsPolled = 1 # List of core affinities Dc0CoreAffinity = 0 # Data Compression - User instance #1 Dc1Name = "Dc1" Dc1IsPolled = 1 # List of core affinities Dc1CoreAffinity = 0 # Data Compression - User instance #2 Dc2Name = "Dc2" Dc2IsPolled = 1 # List of core affinities Dc2CoreAffinity = 0 # Data Compression - User instance #3 Dc3Name = "Dc3" Dc3IsPolled = 1 # List of core affinities Dc3CoreAffinity = 0 QATzip-1.2.0/test/performance_tests/run_perf_test.sh000077500000000000000000000106631456106226300226150ustar00rootroot00000000000000#! /bin/bash ################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ set -e echo "***QZ_ROOT run_perf_test.sh start" rm -f result_comp_stderr rm -f result_decomp_stderr CURRENT_PATH=`dirname $(readlink -f "$0")` #check whether qatzip-test exists if [ ! -f "$QZ_ROOT/test/qatzip-test" ]; then echo "$QZ_ROOT/test/qatzip-test: No such file. Compile first!" exit 1 fi #get the type of QAT hardware platform=`lspci | grep Co-processor | awk '{print $6}' | head -1` if [[ $platform != "37c8" && $platform != "4940" ]] then platform=`lspci | grep Co-processor | awk '{print $5}' | head -1` if [[ $platform != "DH895XCC" && $platform != "C62x" ]] then platform=`lspci | grep Co-processor | awk '{print $7}' | head -1` if [ $platform != "C3000" ] then echo "Unsupported Platform: `lspci | grep Co-processor` " exit 1 fi fi fi echo "platform=$platform" #Replace the driver configuration files and configure hugepages echo "Replace the driver configuration files and configure hugepages." if [[ $platform = "37c8" || $platform = "C62x" ]] then process=24 \cp $CURRENT_PATH/config_file/c6xx/c6xx_dev0.conf /etc \cp $CURRENT_PATH/config_file/c6xx/c6xx_dev1.conf /etc \cp $CURRENT_PATH/config_file/c6xx/c6xx_dev2.conf /etc elif [ $platform = "DH895XCC" ] then process=8 \cp $CURRENT_PATH/config_file/dh895xcc/dh895xcc_dev0.conf /etc elif [ $platform = "4940" ] then process=48 \cp $CURRENT_PATH/config_file/4xxx/4xxx*.conf /etc elif [ $platform = "C3000" ] then process=4 \cp $CURRENT_PATH/config_file/c3xxx/c3xxx_dev0.conf /etc fi service qat_service restart echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages rmmod usdm_drv insmod $ICP_ROOT/build/usdm_drv.ko max_huge_pages=1024 max_huge_pages_per_process=24 sleep 5 #Perform performance test echo "Perform performance test" thread=4 if [ $platform = "4940" ] then thread=1 fi echo > result_comp cpu_list=0 for((numProc_comp = 0; numProc_comp < $process; numProc_comp ++)) do taskset -c $cpu_list $QZ_ROOT/test/qatzip-test -m 4 -l 1000 -t $thread -D comp >> result_comp 2>> result_comp_stderr & cpu_list=$(($cpu_list + 1)) done wait compthroughput=`awk '{sum+=$8} END{print sum}' result_comp` echo "compthroughput=$compthroughput Gbps" echo > result_decomp cpu_list=0 for((numProc_decomp = 0; numProc_decomp < $process; numProc_decomp ++)) do taskset -c $cpu_list $QZ_ROOT/test/qatzip-test -m 4 -l 1000 -t $thread -D decomp >> result_decomp 2>> result_decomp_stderr & cpu_list=$(($cpu_list + 1)) done wait decompthroughput=`awk '{sum+=$8} END{print sum}' result_decomp` echo "decompthroughput=$decompthroughput Gbps" rm -f result_comp rm -f result_decomp echo "***QZ_ROOT run_perf_test.sh end" QATzip-1.2.0/utils/000077500000000000000000000000001456106226300140275ustar00rootroot00000000000000QATzip-1.2.0/utils/Makefile.am000066400000000000000000000061641456106226300160720ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2024 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ bin_PROGRAMS = qzip qzip_SOURCES = \ qzip_7z.c \ qzip_main.c \ qzip.c qzip_CFLAGS = \ -I$(abs_top_srcdir)/include/ \ -I$(abs_top_srcdir)/src/ \ -I$(abs_top_srcdir)/utils/ \ $(COMMON_CFLAGS) \ $(ICP_INCLUDE_CFLAGS) qzip_LDADD = \ $(abs_top_srcdir)/src/.libs/libqatzip.a \ $(QATLIB_FLAGS) \ $(USDMLIB_FLAGS) qzip_LDFLAGS = \ $(ICP_LDFLAGS) qzip_obj_CFLAGS = \ -I$(abs_top_srcdir)/include/ \ -I$(abs_top_srcdir)/src/ \ -I$(abs_top_srcdir)/utils/ \ $(COMMON_CFLAGS) \ $(ICP_INCLUDE_CFLAGS) if QATZIP_LZ4S_POSTPROCESS_AC noinst_PROGRAMS = qzstd qzstd_SOURCES = \ qzstd.c \ qzstd_main.c qzstd_CFLAGS = \ -I$(abs_top_srcdir)/include/ \ -I$(abs_top_srcdir)/src/ \ -I$(abs_top_srcdir)/utils/ \ $(COMMON_CFLAGS) \ $(ICP_INCLUDE_CFLAGS) qzstd_LDADD = \ $(abs_top_srcdir)/src/.libs/libqatzip.a \ $(QATLIB_FLAGS) \ $(USDMLIB_FLAGS) \ $(ZSTD_LIBADD) qzstd_LDFLAGS = \ $(ICP_LDFLAGS) endif qzip_obj_without_main: qzip.c qzip_7z.c $(CC) $^ -c $(qzip_obj_CFLAGS) QATzip-1.2.0/utils/qzip.c000066400000000000000000000704741456106226300151720ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include "qzip.h" char const *const g_license_msg[] = { "Copyright (C) 2021 Intel Corporation.", 0 }; char *g_program_name = NULL; /* program name */ int g_decompress = 0; /* g_decompress (-d) */ int g_keep = 0; /* keep (don't delete) input files */ QzSession_T g_sess; QzipParams_T g_params_th = { .huffman_hdr = QZ_HUFF_HDR_DEFAULT, .direction = QZ_DIRECTION_DEFAULT, .data_fmt = QZIP_DEFLATE_GZIP_EXT, .comp_lvl = QZ_COMP_LEVEL_DEFAULT, .comp_algorithm = QZ_COMP_ALGOL_DEFAULT, .hw_buff_sz = QZ_HW_BUFF_SZ, .polling_mode = QZ_PERIODICAL_POLLING, .req_cnt_thrshold = 32 }; /* Estimate maximum data expansion after decompression */ const unsigned int g_bufsz_expansion_ratio[] = {5, 20, 50, 100}; /* Command line options*/ char const g_short_opts[] = "A:H:L:C:r:o:O:P:dfhkVR"; const struct option g_long_opts[] = { /* { name has_arg *flag val } */ {"decompress", 0, 0, 'd'}, /* decompress */ {"uncompress", 0, 0, 'd'}, /* decompress */ {"force", 0, 0, 'f'}, /* force overwrite of output file */ {"help", 0, 0, 'h'}, /* give help */ {"keep", 0, 0, 'k'}, /* keep (don't delete) input files */ {"version", 0, 0, 'V'}, /* display version number */ {"algorithm", 1, 0, 'A'}, /* set algorithm type */ {"huffmanhdr", 1, 0, 'H'}, /* set huffman header type */ {"level", 1, 0, 'L'}, /* set compression level */ {"chunksz", 1, 0, 'C'}, /* set chunk size */ {"output", 1, 0, 'O'}, /* set output header format(gzip, gzipext, 7z, deflate_4B, lz4, lz4s) */ {"recursive", 0, 0, 'R'}, /* set recursive mode when compressing a directory */ {"polling", 1, 0, 'P'}, /* set polling mode when compressing and decompressing */ { 0, 0, 0, 0 } }; const unsigned int USDM_ALLOC_MAX_SZ = (2 * 1024 * 1024 - 5 * 1024); void tryHelp(void) { QZ_PRINT("Try `%s --help' for more information.\n", g_program_name); exit(ERROR); } void help(void) { static char const *const help_msg[] = { "Compress or uncompress FILEs (by default, compress FILES in-place).", "", "Mandatory arguments to long options are mandatory for short options " "too.", "", " -A, --algorithm set algorithm type", " -d, --decompress decompress", " -f, --force force overwrite of output file and compress links", " -h, --help give this help", " -H, --huffmanhdr set huffman header type", " -k, --keep keep (don't delete) input files", " -V, --version display version number", " -L, --level set compression level", " -C, --chunksz set chunk size", " -O, --output set output header format(gzip|gzipext|7z|deflate_4B|lz4|lz4s)", " -r, set max in-flight request number", " -R, set Recursive mode for a directory", " -o, set output file name", " -P, --polling set polling mode, only supports busy polling settings", "", "With no FILE, read standard input.", 0 }; char const *const *p = help_msg; QZ_PRINT("Usage: %s [OPTION]... [FILE]...\n", g_program_name); while (*p) { QZ_PRINT("%s\n", *p++); } } void freeTimeList(RunTimeList_T *time_list) { RunTimeList_T *time_node = time_list; RunTimeList_T *pre_time_node = NULL; while (time_node) { pre_time_node = time_node; time_node = time_node->next; free(pre_time_node); } } void displayStats(RunTimeList_T *time_list, off_t insize, off_t outsize, int is_compress) { /* Calculate time taken (from begin to end) in micro seconds */ unsigned long us_begin = 0; unsigned long us_end = 0; double us_diff = 0; RunTimeList_T *time_node = time_list; while (time_node) { us_begin = time_node->time_s.tv_sec * 1000000 + time_node->time_s.tv_usec; us_end = time_node->time_e.tv_sec * 1000000 + time_node->time_e.tv_usec; us_diff += (us_end - us_begin); time_node = time_node->next; } if (insize) { assert(0 != us_diff); double size = (is_compress) ? insize : outsize; double throughput = (size * CHAR_BIT) / us_diff; /* in MB (megabytes) */ double compressionRatio = ((double)insize) / ((double)outsize); double spaceSavings = 1 - ((double)outsize) / ((double)insize); QZ_PRINT("Time taken: %9.3lf ms\n", us_diff / 1000); QZ_PRINT("Throughput: %9.3lf Mbit/s\n", throughput); if (is_compress) { QZ_PRINT("Space Savings: %9.3lf %%\n", spaceSavings * 100.0); QZ_PRINT("Compression ratio: %.3lf : 1\n", compressionRatio); } } } int doProcessBuffer(QzSession_T *sess, unsigned char *src, unsigned int *src_len, unsigned char *dst, unsigned int dst_len, RunTimeList_T *time_list, FILE *dst_file, off_t *dst_file_size, int is_compress) { int ret = QZ_FAIL; unsigned int done = 0; unsigned int buf_processed = 0; unsigned int buf_remaining = *src_len; unsigned int bytes_written = 0; unsigned int valid_dst_buf_len = dst_len; RunTimeList_T *time_node = time_list; while (time_node->next) { time_node = time_node->next; } while (!done) { RunTimeList_T *run_time = calloc(1, sizeof(RunTimeList_T)); assert(NULL != run_time); run_time->next = NULL; time_node->next = run_time; time_node = run_time; gettimeofday(&run_time->time_s, NULL); /* Do actual work */ if (is_compress) { ret = qzCompress(sess, src, src_len, dst, &dst_len, 1); if (QZ_BUF_ERROR == ret && 0 == *src_len) { done = 1; } } else { ret = qzDecompress(sess, src, src_len, dst, &dst_len); if (QZ_DATA_ERROR == ret || (QZ_BUF_ERROR == ret && 0 == *src_len)) { done = 1; } } if (ret != QZ_OK && ret != QZ_BUF_ERROR && ret != QZ_DATA_ERROR) { const char *op = (is_compress) ? "Compression" : "Decompression"; QZ_ERROR("doProcessBuffer:%s failed with error: %d\n", op, ret); break; } gettimeofday(&run_time->time_e, NULL); bytes_written = fwrite(dst, 1, dst_len, dst_file); assert(bytes_written == dst_len); *dst_file_size += bytes_written; buf_processed += *src_len; buf_remaining -= *src_len; if (0 == buf_remaining) { done = 1; } src += *src_len; QZ_DEBUG("src_len is %u ,buf_remaining is %u\n", *src_len, buf_remaining); *src_len = buf_remaining; dst_len = valid_dst_buf_len; bytes_written = 0; } *src_len = buf_processed; return ret; } void doProcessFile(QzSession_T *sess, const char *src_file_name, const char *dst_file_name, int is_compress) { int ret = OK; struct stat src_file_stat; unsigned int src_buffer_size = 0; unsigned int dst_buffer_size = 0; off_t src_file_size = 0, dst_file_size = 0, file_remaining = 0; unsigned char *src_buffer = NULL; unsigned char *dst_buffer = NULL; FILE *src_file = NULL; FILE *dst_file = NULL; unsigned int bytes_read = 0; unsigned long bytes_processed = 0; unsigned int ratio_idx = 0; const unsigned int ratio_limit = sizeof(g_bufsz_expansion_ratio) / sizeof(unsigned int); unsigned int read_more = 0; int src_fd = 0; RunTimeList_T *time_list_head = malloc(sizeof(RunTimeList_T)); assert(NULL != time_list_head); gettimeofday(&time_list_head->time_s, NULL); time_list_head->time_e = time_list_head->time_s; time_list_head->next = NULL; //open file src_fd = open(src_file_name, O_RDONLY); if (src_fd < 0) { QZ_PRINT("Open input file %s failed\n", src_file_name); exit(ERROR); } ret = fstat(src_fd, &src_file_stat); assert(!ret); if (S_ISBLK(src_file_stat.st_mode)) { /* ioctl return device size / 512, so device size = src_file_size * 512 */ if (ioctl(src_fd, BLKGETSIZE, &src_file_size) < 0) { close(src_fd); perror(src_file_name); exit(ERROR); } src_file_size *= 512; } else { src_file_size = src_file_stat.st_size; } src_buffer_size = (src_file_size > SRC_BUFF_LEN) ? SRC_BUFF_LEN : src_file_size; if (is_compress) { dst_buffer_size = qzMaxCompressedLength(src_buffer_size, sess); if (0 == dst_buffer_size) { perror("During SW compression, src file size is less than HW size!\n"); exit(ERROR); } } else { /* decompress */ dst_buffer_size = src_buffer_size * g_bufsz_expansion_ratio[ratio_idx++]; } if (0 == src_file_size && is_compress) { dst_buffer_size = 1024; } src_buffer = malloc(src_buffer_size); assert(src_buffer != NULL); dst_buffer = malloc(dst_buffer_size); assert(dst_buffer != NULL); src_file = fdopen(src_fd, "r"); assert(src_file != NULL); dst_file = fopen(dst_file_name, "w"); assert(dst_file != NULL); file_remaining = src_file_size; read_more = 1; do { if (read_more) { bytes_read = fread(src_buffer, 1, src_buffer_size, src_file); QZ_PRINT("Reading input file %s (%u Bytes)\n", src_file_name, bytes_read); } else { bytes_read = file_remaining; } puts((is_compress) ? "Compressing..." : "Decompressing..."); ret = doProcessBuffer(sess, src_buffer, &bytes_read, dst_buffer, dst_buffer_size, time_list_head, dst_file, &dst_file_size, is_compress); if (QZ_DATA_ERROR == ret || QZ_BUF_ERROR == ret) { bytes_processed += bytes_read; if (0 != bytes_read) { if (-1 == fseek(src_file, bytes_processed, SEEK_SET)) { ret = ERROR; goto exit; } read_more = 1; } else if (QZ_BUF_ERROR == ret) { //dest buffer not long enough if (ratio_limit == ratio_idx) { QZ_ERROR("Could not expand more destination buffer\n"); ret = ERROR; goto exit; } free(dst_buffer); dst_buffer_size = src_buffer_size * g_bufsz_expansion_ratio[ratio_idx++]; dst_buffer = malloc(dst_buffer_size); if (NULL == dst_buffer) { QZ_ERROR("Fail to allocate destination buffer with size " "%u\n", dst_buffer_size); ret = ERROR; goto exit; } read_more = 0; } else { // corrupt data ret = ERROR; goto exit; } } else if (QZ_OK != ret) { QZ_ERROR("Process file error: %d\n", ret); ret = ERROR; goto exit; } else { read_more = 1; } file_remaining -= bytes_read; } while (file_remaining > 0); displayStats(time_list_head, src_file_size, dst_file_size, is_compress); exit: freeTimeList(time_list_head); fclose(src_file); fclose(dst_file); close(src_fd); free(src_buffer); free(dst_buffer); if (!g_keep && OK == ret) { unlink(src_file_name); } if (ret) { exit(ret); } } int qzipSetupSessionDeflate(QzSession_T *sess, QzipParams_T *params) { int status; QzSessionParamsDeflate_T deflate_params; status = qzGetDefaultsDeflate(&deflate_params); if (status < 0) { QZ_ERROR("Session setup failed with error: %d\n", status); return ERROR; } switch (params->data_fmt) { case QZIP_DEFLATE_4B: deflate_params.data_fmt = QZ_DEFLATE_4B; break; case QZIP_DEFLATE_GZIP: deflate_params.data_fmt = QZ_DEFLATE_GZIP; break; case QZIP_DEFLATE_GZIP_EXT: deflate_params.data_fmt = QZ_DEFLATE_GZIP_EXT; break; case QZIP_DEFLATE_RAW: deflate_params.data_fmt = QZ_DEFLATE_RAW; break; default: QZ_ERROR("Unsupported data format\n"); return ERROR; } deflate_params.huffman_hdr = params->huffman_hdr; deflate_params.common_params.direction = params->direction; deflate_params.common_params.comp_lvl = params->comp_lvl; deflate_params.common_params.comp_algorithm = params->comp_algorithm; deflate_params.common_params.hw_buff_sz = params->hw_buff_sz; deflate_params.common_params.polling_mode = params->polling_mode; deflate_params.common_params.req_cnt_thrshold = params->req_cnt_thrshold; status = qzSetupSessionDeflate(sess, &deflate_params); if (status < 0) { QZ_ERROR("Session setup failed with error: %d\n", status); return ERROR; } return OK; } int qzipSetupSessionLZ4(QzSession_T *sess, QzipParams_T *params) { int status; QzSessionParamsLZ4_T lz4_params; status = qzGetDefaultsLZ4(&lz4_params); if (status < 0) { QZ_ERROR("Session setup failed with error: %d\n", status); return ERROR; } lz4_params.common_params.direction = params->direction; lz4_params.common_params.comp_lvl = params->comp_lvl; lz4_params.common_params.comp_algorithm = params->comp_algorithm; lz4_params.common_params.hw_buff_sz = params->hw_buff_sz; lz4_params.common_params.polling_mode = params->polling_mode; lz4_params.common_params.req_cnt_thrshold = params->req_cnt_thrshold; status = qzSetupSessionLZ4(sess, &lz4_params); if (status < 0) { QZ_ERROR("Session setup failed with error: %d\n", status); return ERROR; } return OK; } int qzipSetupSessionLZ4S(QzSession_T *sess, QzipParams_T *params) { int status; QzSessionParamsLZ4S_T lz4s_params; status = qzGetDefaultsLZ4S(&lz4s_params); if (status < 0) { QZ_ERROR("Session setup failed with error: %d\n", status); return ERROR; } lz4s_params.common_params.direction = params->direction; lz4s_params.common_params.comp_lvl = params->comp_lvl; lz4s_params.common_params.comp_algorithm = params->comp_algorithm; lz4s_params.common_params.hw_buff_sz = params->hw_buff_sz; lz4s_params.common_params.polling_mode = params->polling_mode; lz4s_params.common_params.req_cnt_thrshold = params->req_cnt_thrshold; status = qzSetupSessionLZ4S(sess, &lz4s_params); if (status < 0) { QZ_ERROR("Session setup failed with error: %d\n", status); return ERROR; } return OK; } int qatzipSetup(QzSession_T *sess, QzipParams_T *params) { int status; QZ_DEBUG("mw>>> sess=%p\n", sess); status = qzInit(sess, 1); if (status != QZ_OK && status != QZ_DUPLICATE) { QZ_ERROR("QAT init failed with error: %d\n", status); return ERROR; } QZ_DEBUG("QAT init OK with error: %d\n", status); switch (params->data_fmt) { case QZIP_DEFLATE_4B: case QZIP_DEFLATE_GZIP: case QZIP_DEFLATE_GZIP_EXT: case QZIP_DEFLATE_RAW: status = qzipSetupSessionDeflate(sess, params); if (status != OK) { QZ_ERROR("qzipSetupSessionDeflate fail with error: %d\n", status); } break; case QZIP_LZ4_FH: status = qzipSetupSessionLZ4(sess, params); if (status != OK) { QZ_ERROR("qzipSetupSessionLZ4 fail with error: %d\n", status); } break; case QZIP_LZ4S_BK: status = qzipSetupSessionLZ4S(sess, params); if (status != OK) { QZ_ERROR("qzipSetupSessionLZ4S fail with error: %d\n", status); } break; default: QZ_ERROR("Unsupported data format\n"); return ERROR; } QZ_DEBUG("Session setup OK with error: %d\n", status); return 0; } int qatzipClose(QzSession_T *sess) { qzTeardownSession(sess); qzClose(sess); return 0; } QzSuffix_T getSuffix(const char *filename) { QzSuffix_T s = E_SUFFIX_UNKNOWN; size_t len = strlen(filename); if (len >= strlen(SUFFIX_GZ) && !strcmp(filename + (len - strlen(SUFFIX_GZ)), SUFFIX_GZ)) { s = E_SUFFIX_GZ; } else if (len >= strlen(SUFFIX_7Z) && !strcmp(filename + (len - strlen(SUFFIX_7Z)), SUFFIX_7Z)) { s = E_SUFFIX_7Z; } else if (len >= strlen(SUFFIX_LZ4) && !strcmp(filename + (len - strlen(SUFFIX_LZ4)), SUFFIX_LZ4)) { s = E_SUFFIX_LZ4; } else if (len >= strlen(SUFFIX_LZ4S) && !strcmp(filename + (len - strlen(SUFFIX_LZ4S)), SUFFIX_LZ4S)) { s = E_SUFFIX_LZ4S; } return s; } bool hasSuffix(const char *fname) { size_t len = strlen(fname); switch (g_params_th.data_fmt) { case QZIP_LZ4_FH: if (len >= strlen(SUFFIX_LZ4) && !strcmp(fname + (len - strlen(SUFFIX_LZ4)), SUFFIX_LZ4)) { return 1; } break; case QZIP_LZ4S_BK: if (len >= strlen(SUFFIX_LZ4S) && !strcmp(fname + (len - strlen(SUFFIX_LZ4S)), SUFFIX_LZ4S)) { return 1; } break; case QZIP_DEFLATE_RAW: case QZIP_DEFLATE_GZIP_EXT: case QZIP_DEFLATE_GZIP: case QZIP_DEFLATE_4B: default: if (len >= strlen(SUFFIX_GZ) && !strcmp(fname + (len - strlen(SUFFIX_GZ)), SUFFIX_GZ)) { return 1; } else if (len >= strlen(SUFFIX_7Z) && !strcmp(fname + (len - strlen(SUFFIX_7Z)), SUFFIX_7Z)) { return 1; } break; } return 0; } QzSuffixCheckStatus_T checkSuffix(QzSuffix_T suffix, int is_format_set) { if (E_SUFFIX_GZ == suffix) { if (!is_format_set) { // format is not specified, reassign data format by suffix instead of default value g_params_th.data_fmt = QZIP_DEFLATE_GZIP_EXT; return E_CHECK_SUFFIX_OK; } if (QZIP_DEFLATE_GZIP_EXT != g_params_th.data_fmt && QZIP_DEFLATE_GZIP != g_params_th.data_fmt && QZIP_DEFLATE_4B != g_params_th.data_fmt) { return E_CHECK_SUFFIX_FORMAT_UNMATCH; } else { return E_CHECK_SUFFIX_OK; } } else if (E_SUFFIX_7Z == suffix) { if (!is_format_set) { g_params_th.data_fmt = QZIP_DEFLATE_RAW; return E_CHECK_SUFFIX_OK; } if (QZIP_DEFLATE_RAW != g_params_th.data_fmt) { return E_CHECK_SUFFIX_FORMAT_UNMATCH; } else { return E_CHECK_SUFFIX_OK; } } else if (E_SUFFIX_LZ4 == suffix) { if (!is_format_set) { g_params_th.data_fmt = QZIP_LZ4_FH; return E_CHECK_SUFFIX_OK; } if (QZIP_LZ4_FH != g_params_th.data_fmt) { return E_CHECK_SUFFIX_FORMAT_UNMATCH; } else { return E_CHECK_SUFFIX_OK; } } else { //unsupported suffix return E_CHECK_SUFFIX_UNSUPPORT; } } int makeOutName(const char *in_name, const char *out_name, char *oname, int is_compress) { if (is_compress) { if (hasSuffix(in_name)) { QZ_ERROR("Warning: %s already has suffix -- unchanged\n", in_name); return -1; } /* add suffix */ if (g_params_th.data_fmt == QZIP_LZ4_FH) { snprintf(oname, MAX_PATH_LEN, "%s%s", out_name ? out_name : in_name, SUFFIX_LZ4); } else if (g_params_th.data_fmt == QZIP_LZ4S_BK) { snprintf(oname, MAX_PATH_LEN, "%s%s", out_name ? out_name : in_name, SUFFIX_LZ4S); } else if (g_params_th.data_fmt == QZIP_DEFLATE_RAW) { snprintf(oname, MAX_PATH_LEN, "%s%s", out_name ? out_name : in_name, SUFFIX_7Z); } else { snprintf(oname, MAX_PATH_LEN, "%s%s", out_name ? out_name : in_name, SUFFIX_GZ); } } else { if (!hasSuffix(in_name)) { QZ_ERROR("%s: Wrong suffix. Supported suffix: 7z/gz/lz4\n", in_name); return -1; } /* remove suffix */ snprintf(oname, MAX_PATH_LEN, "%s", out_name ? out_name : in_name); if (NULL == out_name) { if (g_params_th.data_fmt == QZIP_LZ4_FH) { oname[strlen(in_name) - strlen(SUFFIX_LZ4)] = '\0'; } else { oname[strlen(in_name) - strlen(SUFFIX_GZ)] = '\0'; } } } return 0; } /* Makes a complete file system path by adding a file name to the path of its * parent directory. */ void mkPath(char *path, const char *dirpath, char *file) { const int nprinted = snprintf(path, MAX_PATH_LEN, "%s/%s", dirpath, file); if (nprinted >= MAX_PATH_LEN || nprinted < 0) { /* truncated, or output error */ assert(0); } } void processDir(QzSession_T *sess, const char *in_name, const char *out_name, int is_compress) { DIR *dir; struct dirent *entry; char inpath[MAX_PATH_LEN]; dir = opendir(in_name); assert(dir); while ((entry = readdir(dir))) { /* Ignore anything starting with ".", which includes the special * files ".", "..", as well as hidden files. */ if (entry->d_name[0] == '.') { continue; } /* Qualify the file with its parent directory to obtain a complete * path. */ mkPath(inpath, in_name, entry->d_name); processFile(sess, inpath, out_name, is_compress); } closedir(dir); } void processFile(QzSession_T *sess, const char *in_name, const char *out_name, int is_compress) { int ret; struct stat fstat; struct timespec timebuf[2]; ret = stat(in_name, &fstat); if (ret) { perror(in_name); exit(-1); } if (S_ISDIR(fstat.st_mode)) { processDir(sess, in_name, out_name, is_compress); } else { char oname[MAX_PATH_LEN]; memset(oname, 0, MAX_PATH_LEN); if (makeOutName(in_name, out_name, oname, is_compress)) { return; } doProcessFile(sess, in_name, oname, is_compress); if (access(oname, F_OK) == 0) { //update src file stat to dst file memset(timebuf, 0, sizeof(timebuf)); timebuf[0].tv_nsec = UTIME_NOW; timebuf[1].tv_sec = fstat.st_mtime; utimensat(AT_FDCWD, oname, timebuf, 0); } } } void version() { char const *const *p = g_license_msg; QZ_PRINT("%s v%s\n", g_program_name, QZIP_VERSION); while (*p) { QZ_PRINT("%s\n", *p++); } } char *qzipBaseName(char *fname) { char *p; if ((p = strrchr(fname, '/')) != NULL) { fname = p + 1; } return fname; } void processStream(QzSession_T *sess, FILE *src_file, FILE *dst_file, int is_compress) { int ret = OK; unsigned int src_buffer_size = 0; unsigned int dst_buffer_size = 0; off_t dst_file_size = 0; unsigned char *src_buffer = NULL; unsigned char *dst_buffer = NULL; unsigned int bytes_read = 0; unsigned int ratio_idx = 0; const unsigned int ratio_limit = sizeof(g_bufsz_expansion_ratio) / sizeof(unsigned int); unsigned int read_more = 0; RunTimeList_T *time_list_head = malloc(sizeof(RunTimeList_T)); assert(NULL != time_list_head); gettimeofday(&time_list_head->time_s, NULL); time_list_head->time_e = time_list_head->time_s; time_list_head->next = NULL; int pending_in = 0; int bytes_input = 0; src_buffer_size = SRC_BUFF_LEN; if (is_compress) { dst_buffer_size = qzMaxCompressedLength(src_buffer_size, sess); if (0 == dst_buffer_size) { perror("During SW compression, src file size is less than HW size!\n"); exit(ERROR); } } else { /* decompress */ dst_buffer_size = src_buffer_size * g_bufsz_expansion_ratio[ratio_idx++]; } src_buffer = malloc(src_buffer_size); assert(src_buffer != NULL); dst_buffer = malloc(dst_buffer_size); assert(dst_buffer != NULL); read_more = 1; while (!feof(stdin)) { if (read_more) { bytes_read = fread(src_buffer + pending_in, 1, src_buffer_size - pending_in, src_file); if (0 == is_compress) { bytes_read += pending_in; bytes_input = bytes_read; pending_in = 0; } } ret = doProcessBuffer(sess, src_buffer, &bytes_read, dst_buffer, dst_buffer_size, time_list_head, dst_file, &dst_file_size, is_compress); if (QZ_DATA_ERROR == ret || QZ_BUF_ERROR == ret) { if (!is_compress) { pending_in = bytes_input - bytes_read; } if (0 != bytes_read) { if (!is_compress && pending_in > 0) { memmove(src_buffer, src_buffer + bytes_read, src_buffer_size - bytes_read); } read_more = 1; } else if (QZ_BUF_ERROR == ret) { // dest buffer not long enough if (ratio_limit == ratio_idx) { QZ_ERROR("Could not expand more destination buffer\n"); ret = ERROR; goto exit; } free(dst_buffer); dst_buffer_size = src_buffer_size * g_bufsz_expansion_ratio[ratio_idx++]; dst_buffer = malloc(dst_buffer_size); if (NULL == dst_buffer) { QZ_ERROR("Fail to allocate destination buffer with size " "%u\n", dst_buffer_size); ret = ERROR; goto exit; } read_more = 0; } else { // corrupt data ret = ERROR; goto exit; } } else if (QZ_OK != ret) { QZ_ERROR("Process file error: %d\n", ret); ret = ERROR; goto exit; } else { read_more = 1; } } exit: freeTimeList(time_list_head); free(src_buffer); free(dst_buffer); if (ret) { exit(ret); } } QATzip-1.2.0/utils/qzip.h000066400000000000000000000667661456106226300152100ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifndef _UTILS_QZIP_H #define _UTILS_QZIP_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* new QATzip interface */ #ifdef HAVE_QAT_HEADERS #include #else #include #endif #include #include #include /* qzip version */ #define QZIP_VERSION "1.2.0" /* field offset in signature header */ #define SIGNATUREHEADER_OFFSET_BASE 8 #define SIGNATUREHEADER_OFFSET_NEXTHEADER_OFFSET 4 #define SIGNATUREHEADER_OFFSET_NEXTHEADER_SIZE 12 #define SIGNATUREHEADER_OFFSET_NEXTHEADER_CRC 20 /* resolving status */ #define RESOLVE_STATUS_IN_HEADER 0x0001 #define RESOLVE_STATUS_IN_ARCHIVE_PROPERTIES 0x0002 #define RESOLVE_STATUS_IN_STREAMSINFO 0x0004 #define RESOLVE_STATUS_IN_FILESINFO 0x0008 #define RESOLVE_STATUS_IN_PACKINFO 0x0010 #define RESOLVE_STATUS_IN_CODERSINFO 0x0020 #define RESOLVE_STATUS_IN_SUBSTREAMSINFO 0x0040 /* definitions of 7z archive tags */ #define PROPERTY_ID_END 0x00 #define PROPERTY_ID_HEADER 0x01 #define PROPERTY_ID_ARCHIVE_PROPERTIES 0x02 #define PROPERTY_ID_ADDITIONAL_STREAMSINFO 0x03 #define PROPERTY_ID_MAIN_STREAMSINFO 0x04 #define PROPERTY_ID_FILESINFO 0x05 #define PROPERTY_ID_PACKINFO 0x06 #define PROPERTY_ID_UNPACKINFO 0x07 #define PROPERTY_ID_SUBSTREAMSINFO 0x08 #define PROPERTY_ID_SIZE 0x09 #define PROPERTY_ID_CRC 0x0a #define PROPERTY_ID_FOLDER 0x0b #define PROPERTY_ID_CODERS_UNPACK_SIZE 0x0c #define PROPERTY_ID_NUM_UNPACK_STREAM 0x0d #define PROPERTY_ID_EMPTY_STREAM 0x0e #define PROPERTY_ID_EMPTY_FILE 0x0f #define PROPERTY_ID_ANTI 0x10 #define PROPERTY_ID_NAME 0x11 #define PROPERTY_ID_CTIME 0x12 #define PROPERTY_ID_ATIME 0x13 #define PROPERTY_ID_MTIME 0x14 /* Support windows(low 16 bit) and unix(high 16 bit) */ #define PROPERTY_ID_ATTRIBUTES 0x15 #define PROPERTY_ID_COMMENT 0x16 #define PROPERTY_ID_ENCODED_HEADER 0x17 #define PROPERTY_ID_STARTPOS 0x18 #define PROPERTY_ID_DUMMY 0x19 #define PROPERTY_CONTENT_DUMMY 0x00 #define FLAG_ATTR_DEFINED_SET 0x01 #define FLAG_ATTR_DEFINED_UNSET 0x00 #define FLAG_ATTR_EXTERNAL_UNSET 0x00 /* 7z format version */ #define G_7ZHEADER_MAJOR_VERSION 0x00 #define G_7ZHEADER_MINOR_VERSION 0x04 /* default size for allocating memory for one node */ #define QZ_DIRLIST_DEFAULT_NUM_PER_NODE 100 #define QZ_FILELIST_DEFAULT_NUM_PER_NODE 1000 /* archiveproperties develop ID */ #define QZ7Z_DEVELOP_PREFIX 0x3ful #define QZ7Z_DEVELOP_ID ('Q'*1ul<<32|'A'<<24|'T'<<16|'7'<<8|'z') #define QZ7Z_DEVELOP_SUBID 0x0a01ul /* return codes from qzip */ #define OK 0 #define ERROR 1 /* internal return codes for functions that implement 7z format */ #define QZ7Z_OK OK #define QZ7Z_ERR_INVALID_SIZE -200 #define QZ7Z_ERR_OPEN -201 #define QZ7Z_ERR_OOM -202 #define QZ7Z_ERR_CONCAT_FILE -203 #define QZ7Z_ERR_STAT -204 #define QZ7Z_ERR_IOCTL -205 #define QZ7Z_ERR_END_HEADER -206 #define QZ7Z_ERR_NULL_INPUT_LIST -207 #define QZ7Z_ERR_REMOVE -208 #define QZ7Z_ERR_RESOLVE_END_HEADER -209 #define QZ7Z_ERR_NOT_EXPECTED_CHAR -210 #define QZ7Z_ERR_GETCWD -211 #define QZ7Z_ERR_READ_EOF -212 #define QZ7Z_ERR_READ_LESS -213 #define QZ7Z_ERR_WRITE_EOF -214 #define QZ7Z_ERR_WRITE_LESS -215 #define QZ7Z_ERR_MKDIR -216 #define QZ7Z_ERR_CHDIR -217 #define QZ7Z_ERR_CREATE_TEMP -218 #define QZ7Z_ERR_HEADER_CRC -219 #define QZ7Z_ERR_TIMES -220 #define QZ7Z_ERR_SIG_HEADER_BROKEN -221 #define QZ7Z_ERR_READLINK -222 #define QZ7Z_ERR_SIG_HEADER -223 #define QZ7Z_ERR_RESOLVE_SUBSTREAMS -224 #define QZ7Z_ERR_UNEXPECTED -225 #define MAX_PATH_LEN 1024 /* max pathname length */ #define SUFFIX_GZ ".gz" #define SUFFIX_7Z ".7z" #define SUFFIX_LZ4 ".lz4" #define SUFFIX_LZ4S ".lz4s" #define QZIP_GET_LOWER_32BITS(v) ((v) & 0xFFFFFFFF) typedef enum QzSuffix_E { E_SUFFIX_GZ, E_SUFFIX_7Z, E_SUFFIX_LZ4, E_SUFFIX_LZ4S, E_SUFFIX_UNKNOWN = 999 } QzSuffix_T; typedef enum QzSuffixCheckStatus_E { E_CHECK_SUFFIX_OK, E_CHECK_SUFFIX_UNSUPPORT, E_CHECK_SUFFIX_FORMAT_UNMATCH } QzSuffixCheckStatus_T; #define SRC_BUFF_LEN (512 * 1024 * 1024) typedef enum QzipDataFormat_E { QZIP_DEFLATE_4B = 0, /**< Data is in raw deflate format with 4 byte header */ QZIP_DEFLATE_GZIP, /**< Data is in deflate wrapped by GZip header and footer */ QZIP_DEFLATE_GZIP_EXT, /**< Data is in deflate wrapped by GZip extended header and footer */ QZIP_DEFLATE_RAW, /**< Data is in raw deflate format */ QZIP_LZ4_FH, /**< Data is in LZ4 format with frame headers */ QZIP_LZ4S_BK, /**< Data is in LZ4s format with block headers */ } QzipDataFormat_T; typedef struct QzipParams_S { QzHuffmanHdr_T huffman_hdr; QzDirection_T direction; QzipDataFormat_T data_fmt; unsigned int comp_lvl; unsigned char comp_algorithm; unsigned char force; unsigned char keep; unsigned int hw_buff_sz; unsigned int polling_mode; unsigned int recursive_mode; unsigned int req_cnt_thrshold; char *output_filename; } QzipParams_T; #define QZ7Z_PROPERTY_ID_INTEL7Z_1001 ((QZ7Z_DEVELOP_PREFIX << 56) | \ (QZ7Z_DEVELOP_ID << 16) | \ (QZ7Z_DEVELOP_SUBID)) /* check allocated memory */ #define CHECK_ALLOC_RETURN_VALUE(p) \ if (NULL == p) {\ printf("%s:%d oom\n", __FILE__, __LINE__); \ exit(-QZ7Z_ERR_OOM);\ } /* check fread return */ #define CHECK_FREAD_RETURN(ret, n) if((ret) != (n)) { \ if (feof(fp)) { \ fprintf(stderr, "fread reach EOF.\n"); \ exit(-QZ7Z_ERR_READ_EOF); \ } else { \ fprintf(stderr, "fread errors.\n"); \ exit(-QZ7Z_ERR_READ_LESS); \ } \ } /* check fwrite return */ #define CHECK_FWRITE_RETURN(ret, n) CHECK_FWRITE_RETURN_FP(fp, ret, n) #define CHECK_FWRITE_RETURN_FP(fp, ret, n) if((ret) != (n)) { \ if (feof((fp))) { \ fprintf(stderr, "fwrite reach EOF.\n"); \ exit(-QZ7Z_ERR_WRITE_EOF); \ } else { \ fprintf(stderr, "fwrite errors.\n"); \ exit(-QZ7Z_ERR_WRITE_LESS); \ } \ } typedef struct RunTimeList_S { struct timeval time_s; struct timeval time_e; struct RunTimeList_S *next; } RunTimeList_T; /* Windows FILETIME structure * contains a 64-bit value representing the number of 100-nanosecond intervals * since January 1, 1601 (UTC). */ /* 1601 to 1970 is 369 years plus 89 leap days */ #define NUM_DAYS (134774UL) /* time in seconds from 1601 Jan 1 to 1970 Jan 1 */ #define DELTA_TIME (NUM_DAYS * (24 * 60 * 60UL)) #define NANO_SEC 1000000000UL #define TICKS_PER_SEC 10000000UL typedef struct FILETIME { uint32_t low; uint32_t high; } FILETIME_T; /** ****************************************************************************** * @ingroup qatZip * Qatzip linked list node structure * * @description * Qatzip linked list node structure * ******************************************************************************/ typedef struct QzListNode_S { uint32_t num; // number of allocated region per node uint32_t used; // used space of element void **items; struct QzListNode_S *next; } QzListNode_T; /** ****************************************************************************** * @ingroup qatZip * Qatzip linked list head structure * * @description * Qatzip linked list head structure * ******************************************************************************/ typedef struct QzListHead_S { uint32_t total; // total elements uint32_t num; // number of allocated region per node QzListNode_T *next; } QzListHead_T; /** ****************************************************************************** * @ingroup qatZip * A file or a directory compressed by qatzip * * @description * This structure contains a file or directory and it's attributes * ******************************************************************************/ typedef struct Qz7zFileItem_S { char *fileName; /* dynamic allocated memory for filename(pathname) */ unsigned char isDir; /* 1byte */ unsigned char isEmpty; /* 1byte */ /* is empty file */ unsigned char isSymLink; /* 1byte */ /* is symbol link */ unsigned char isAnti; /* 1byte */ /* is anti file(on windows) */ uint32_t baseNameLength; /* base pathname length */ uint32_t nameLength; /* memory allocated length */ size_t size; /* for file it's file's length*/ uint32_t crc; uint32_t attribute; uint64_t atime; uint32_t atime_nano; uint64_t mtime; uint32_t mtime_nano; } Qz7zFileItem_T; /** ****************************************************************************** * @ingroup qatZip * 7z signature header * * @description * This structure contains a 7z signature header * ******************************************************************************/ typedef struct Qz7zSignatureHeader_S { unsigned char signature[6]; /* {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}*/ unsigned char majorVersion; /* 0x00 */ unsigned char minorVersion; /* 0x04 */ uint32_t startHeaderCRC; uint64_t nextHeaderOffset; uint64_t nextHeaderSize; uint32_t nextHeaderCRC; } Qz7zSignatureHeader_T; /** ****************************************************************************** * @ingroup qatZip * 7z Coder Info * * @description * This structure presents Coder info * ******************************************************************************/ typedef struct Qz7zDigest_S { unsigned char allAreDefined; uint64_t numStreams; uint64_t numDefined; uint32_t *crc; /* array: CRC[NumDefined] */ } Qz7zDigest_T; /** ****************************************************************************** * @ingroup qatZip * 7z Pack Info structure * * @description * This structure presents a 7z pack info * ******************************************************************************/ typedef struct Qz7zPackInfo_S { uint64_t PackPos; uint64_t NumPackStreams; uint64_t *PackSize; /* PackSize[NumPackStreams] */ Qz7zDigest_T *PackStreamDigests; /* not used */ } Qz7zPackInfo_T; /** ****************************************************************************** * @ingroup qatZip * First byte of 7z Coder Info structure * * @description * This structure contains some attributes of a coder * ******************************************************************************/ typedef union Qz7zCoderFirstByte_S { struct { unsigned CodecIdSize : 4; unsigned IsComplexCoder : 1; unsigned HasAttributes : 1; unsigned Reserved : 1; unsigned MoreAlterMethods: 1; /* not used: 0 for ever */ } st; unsigned char uc; } Qz7zCoderFirstByte_T; /** ****************************************************************************** * @ingroup qatZip * 7z Coder Info list * * @description * This structure is Coder info list node * ******************************************************************************/ typedef struct Qz7zCoder_S { Qz7zCoderFirstByte_T coderFirstByte; unsigned char *codecID ; /* CodecID[CodecIdSize] */ uint64_t numInStreams; /* if it is complex coder */ uint64_t numOutStreams; /* if it is complex coder */ uint64_t propertySize; /* if there are attributes */ unsigned char *properties; /* array: Properties[PropertiSize] if there are attributes */ struct Qz7zCoder_S *next; } Qz7zCoder_T; /** ****************************************************************************** * @ingroup qatZip * 7z Folder Info * * @description * This structure is Folder info * ******************************************************************************/ typedef struct Qz7zFolderInfo_S { uint64_t numCoders; Qz7zCoder_T *coder_list; QzListHead_T *items; /* fileitems list */ uint64_t numBindPairs; uint64_t *inIndex; /* array: InIndex[NumBindPairs] */ uint64_t *outIndex; /* array: InIndex[NumBindPairs] */ uint64_t numPackedStreams; uint64_t *index; /* array: Index[NumPackedStreams] */ } Qz7zFolderInfo_T; typedef struct Qz7zFolderLoc_S { QzListNode_T *node; unsigned int index; size_t pos; } Qz7zFolderLoc_T; typedef struct Qz7zFolderHandle_S { Qz7zFolderInfo_T *folder; Qz7zFolderLoc_T *loc; } Qz7zFolderHandle_T; /** ****************************************************************************** * @ingroup qatZip * 7z Coder Info * * @description * This structure presents Coder info * The folders points to an array of all the folders * This part contains all the folders info here, in one struct variable. * ******************************************************************************/ typedef struct Qz7zCodersInfo_S { uint64_t numFolders; Qz7zFolderInfo_T *folders; /* array folders[numFolders] */ uint64_t dataStreamIndex; uint64_t *unPackSize; /* array: unPackSize[numFolders] */ Qz7zDigest_T *unPackDigests; /* not used */ } Qz7zCodersInfo_T ; /** ****************************************************************************** * @ingroup qatZip * 7z Substreams Info * * @description * This structure presents Substreams info * ******************************************************************************/ typedef struct Qz7zSubstreamsInfo_S { uint64_t numFolders; uint64_t *numUnPackStreams; /* NumUnPackStreams[numFolders] */ uint64_t *unPackSize; /* unPackSize[AllNumFiles - 1], AllNumFiles is sum of the array NumUnPackStreamsInFolders */ Qz7zDigest_T *digests; /* points to digests structure with all non-empty files num*/ } Qz7zSubstreamsInfo_T; /** ****************************************************************************** * @ingroup qatZip * 7z Streams Info structure * * @description * This structure presents a 7z streams info * ******************************************************************************/ typedef struct Qz7zStreamsInfo_S { Qz7zPackInfo_T *packInfo; Qz7zCodersInfo_T *codersInfo; Qz7zSubstreamsInfo_T *substreamsInfo; } Qz7zStreamsInfo_T; /** ****************************************************************************** * @ingroup qatZip * 7z Files Info structure * * @description * This structure presents a 7z files info. It is used for compressing * ******************************************************************************/ typedef struct Qz7zFilesInfo_S { uint64_t num; QzListHead_T *head[2]; } Qz7zFilesInfo_T; /** ****************************************************************************** * @ingroup qatZip * 7z Files Info structure * * @description * This structure presents a 7z files info. It is used for decompressing * ******************************************************************************/ typedef struct Qz7zFilesInfo_DEC_S { uint64_t dir_num; uint64_t file_num; Qz7zFileItem_T *items; } Qz7zFilesInfo_Dec_T; /** ****************************************************************************** * @ingroup qatZip * 7z Files ArchiveProperties structure * * @description * This structure presents a 7z Archive Properties Info, if there are more * than one properties, the `next` points to the next property * ******************************************************************************/ typedef struct Qz7zArchiveProperty_S { uint64_t id; uint64_t size; unsigned char *data; struct Qz7zArchiveProperty_S *next; } Qz7zArchiveProperty_T; /** ****************************************************************************** * @ingroup qatZip * 7z End header structure * * @description * This structure contains a 7z end header * ******************************************************************************/ typedef struct Qz7zEndHeader_S { Qz7zArchiveProperty_T *propertyInfo; Qz7zStreamsInfo_T *streamsInfo; Qz7zFilesInfo_T *filesInfo; Qz7zFilesInfo_Dec_T *filesInfo_Dec; } Qz7zEndHeader_T; /** ****************************************************************************** * @ingroup qatZip * 7z Category * * @description * This structure presents a 7z category * ******************************************************************************/ typedef struct QzCatagory_S { unsigned char cat_id; const char *cat_name; QzListHead_T *cat_files; } QzCatagory_T; /** ****************************************************************************** * @ingroup qatZip * 7z Category table * * @description * This structure presents all categories * ******************************************************************************/ typedef struct QzCatagoryTable_S { unsigned int cat_num; QzCatagory_T *catas; /* array: catas[cat_num] */ } QzCatagoryTable_T; /** ****************************************************************************** * @ingroup qatZip * Qatzip items list structure * * @description * the structure is used for hold input arguments * items[0] is the list of all directory and empty file * items[1] is the list of all non-empty file * ******************************************************************************/ typedef struct Qz7zItemList_S { QzListHead_T *items[2]; QzCatagoryTable_T *table; } Qz7zItemList_T; /* create a list return list head */ QzListHead_T *qzListCreate(int num_per_node); /* Add one element's address to the list */ void qzListAdd(QzListHead_T *head, void **node); /* Get an element's address from a list */ void *qzListGet(QzListHead_T *head, int index); /* Free all allocated memory pointed by head */ void qzListDestroy(QzListHead_T *head); /* create the file items list */ Qz7zFileItem_T *fileItemCreate(char *pfilename); /* destroy the items list */ void itemListDestroy(Qz7zItemList_T *p); /* process the cmdline inputs */ Qz7zItemList_T *itemListCreate(int n, char **files); /* * resolve functions */ Qz7zSignatureHeader_T *resolveSignatureHeader(FILE *fp); Qz7zArchiveProperty_T *resolveArchiveProperties(FILE *fp); Qz7zPackInfo_T *resolvePackInfo(FILE *fp); Qz7zCodersInfo_T *resolveCodersInfo(FILE *fp); Qz7zSubstreamsInfo_T *resolveSubstreamsInfo(int n_folder, FILE *fp); Qz7zFilesInfo_Dec_T *resolveFilesInfo(FILE *fp); Qz7zStreamsInfo_T *resolveMainStreamsInfo(FILE *fp); Qz7zEndHeader_T *resolveEndHeader(FILE *fp, Qz7zSignatureHeader_T *sheader); /* create category list */ QzCatagoryTable_T *createCatagoryList(); int scanFilesIntoCatagory(Qz7zItemList_T *the_list); /* * generate functions */ Qz7zSignatureHeader_T *generateSignatureHeader(void); Qz7zArchiveProperty_T *generatePropertyInfo(void); Qz7zPackInfo_T *generatePackInfo(Qz7zItemList_T *the_list, size_t compressed_size); Qz7zFolderInfo_T *generateFolderInfo(Qz7zItemList_T *the_list, int n_folders); Qz7zCodersInfo_T *generateCodersInfo(Qz7zItemList_T *the_list); Qz7zDigest_T *generateDigestInfo(QzListHead_T *head); Qz7zSubstreamsInfo_T *generateSubstreamsInfo(Qz7zItemList_T *the_list); Qz7zFilesInfo_T *generateFilesInfo(Qz7zItemList_T *the_list); Qz7zEndHeader_T *generateEndHeader(Qz7zItemList_T *the_list, size_t compressed_size); /* * write function */ int writeSignatureHeader(Qz7zSignatureHeader_T *header, FILE *fp); size_t writeArchiveProperties(Qz7zArchiveProperty_T *property, FILE *fp, uint32_t *crc); size_t writePackInfo(Qz7zPackInfo_T *pack, FILE *fp, uint32_t *crc); size_t writeFolder(Qz7zFolderInfo_T *folder, FILE *fp, uint32_t *crc); size_t writeCodersInfo(Qz7zCodersInfo_T *coders, FILE *fp, uint32_t *crc); size_t writeDigestInfo(Qz7zDigest_T *digest, FILE *fp, uint32_t *crc); size_t writeStreamsInfo(Qz7zStreamsInfo_T *streams, FILE *fp, uint32_t *crc); size_t writeFilesInfo(Qz7zFilesInfo_T *files, FILE *fp, uint32_t *crc); size_t writeSubstreamsInfo(Qz7zSubstreamsInfo_T *substreams, FILE *fp, uint32_t *crc); size_t writeEndHeader(Qz7zEndHeader_T *header, FILE *fp, uint32_t *crc); /* * free functions */ void freePropertyInfo(Qz7zArchiveProperty_T *info); void freePackInfo(Qz7zPackInfo_T *info); void freeCodersInfo(Qz7zCodersInfo_T *info); void freeSubstreamsInfo(Qz7zSubstreamsInfo_T *info); void freeStreamsInfo(Qz7zStreamsInfo_T *info); void freeFilesInfo(Qz7zFilesInfo_T *info); void freeFilesDecInfo(Qz7zFilesInfo_Dec_T *info); void freeEndHeader(Qz7zEndHeader_T *eheader, int is_compress); /* the main API for compress into 7z format */ int qz7zCompress(QzSession_T *sess, Qz7zItemList_T *the_list, const char *out_name); /* the main API for decompress a 7z file */ int qz7zDecompress(QzSession_T *sess, const char *archive); /* * UINT64 conversion functions */ /* conversion from real uint64_t to UINT64 */ int getExtraByteNum(uint64_t n); int getUint64Bytes(uint64_t n, unsigned char *u64); /* conversion from UINT64 to uint64_t */ int getExtraByteNum2(uint8_t first); uint64_t getU64FromBytes(FILE *fp); #ifdef QZ7Z_DEBUG void printSignatureHeader(Qz7zSignatureHeader_T *sheader); void printEndHeader(Qz7zEndHeader_T *eheader); #endif /* create the directory in path of newdir */ int createDir(const char *newdir, int back); /* delete source files represented by the list */ int deleteSourceFile(Qz7zItemList_T *the_list); /* check whether the file is 7z archive */ int check7zArchive(const char *archive); /* check whether the filename is directory */ int checkDirectory(const char *filename); void freeTimeList(RunTimeList_T *time_list); void displayStats(RunTimeList_T *time_list, off_t insize, off_t outsize, int is_compress); void tryHelp(void); void help(void); void version(); char *qzipBaseName(char *fname); QzSuffix_T getSuffix(const char *filename); bool hasSuffix(const char *fname); QzSuffixCheckStatus_T checkSuffix(QzSuffix_T suffix, int is_format_set); int makeOutName(const char *in_name, const char *out_name, char *oname, int is_compress); /* Makes a complete file system path by adding a file name to the path of its * parent directory. */ void mkPath(char *path, const char *dirpath, char *file); /* * internal api functions */ int qatzipSetup(QzSession_T *sess, QzipParams_T *params); int qatzipClose(QzSession_T *sess); void processFile(QzSession_T *sess, const char *in_name, const char *out_name, int is_compress); int doProcessBuffer(QzSession_T *sess, unsigned char *src, unsigned int *src_len, unsigned char *dst, unsigned int dst_len, RunTimeList_T *time_list, FILE *dst_file, off_t *dst_file_size, int is_compress); void doProcessFile(QzSession_T *sess, const char *src_file_name, const char *dst_file_name, int is_compress); void processDir(QzSession_T *sess, const char *in_name, const char *out_name, int is_compress); void processStream(QzSession_T *sess, FILE *src_file, FILE *dst_file, int is_compress); int doCompressFile(QzSession_T *sess, Qz7zItemList_T *list, const char *dst_file_name); int doDecompressFile(QzSession_T *sess, const char *src_file_name); /* * extern declaration */ extern char const *const g_license_msg[2]; extern char *g_program_name; extern int g_decompress; /* g_decompress (-d) */ extern int g_keep; /* keep (don't delete) input files */ extern QzSession_T g_sess; extern QzipParams_T g_params_th; /* Estimate maximum data expansion after decompression */ extern const unsigned int g_bufsz_expansion_ratio[4]; /* Command line options*/ extern char const g_short_opts[]; extern const struct option g_long_opts[]; extern const unsigned int USDM_ALLOC_MAX_SZ; extern int errno; #endif QATzip-1.2.0/utils/qzip_7z.c000066400000000000000000003024451456106226300156060ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include "qzip.h" #define OK 0 #define ERROR 1 static const unsigned char g_header_signature[] = { '7', 'z', 0xBC, 0xAF, 0x27, 0x1C }; static const char g_deflate_codecId[] = { 0x04, 0x01, 0x08 }; static const char g_property_data[] = { 'Q', 'A', 'T' }; static uint64_t const extra_byte_boundary[] = { 0x0, 0x7f, 0x3fff, 0x1fffff, 0xfffffff, 0x7ffffffff, 0x3ffffffffff, 0x1ffffffffffff, 0xffffffffffffff }; static uint8_t const first_byte_table[] = { 0, 0x80/* 1000 0000 */, 0xc0/* 1100 0000 */, 0xe0/* 1110 0000 */, 0xf0/* 1111 0000 */, 0xf8/* 1111 1000 */, 0xfc/* 1111 1100 */, 0xfe/* 1111 1110 */, 0xff/* 1111 1111 */ }; FILETIME_T unixtimeToFiletime(unsigned long t, uint32_t nsec) { FILETIME_T ft; unsigned long long secs = t * TICKS_PER_SEC + DELTA_TIME * TICKS_PER_SEC + nsec / 100; ft.low = (uint32_t)secs; ft.high = (uint32_t)(secs >> 32); return ft; } time_t filetimeToUnixtime(FILETIME_T ft) { time_t t; uint64_t ti; ti = (uint64_t)ft.high << 32; ti += ft.low; t = ti / TICKS_PER_SEC - DELTA_TIME; return t; } #define writeByte(b, fp, crc) writeTag(b, fp, crc) static size_t writeTag(unsigned char tag, FILE *fp, uint32_t *crc) { size_t n; n = fwrite(&tag, sizeof(unsigned char), 1, fp); CHECK_FWRITE_RETURN(n, 1) *crc = crc32(*crc, &tag, 1); return n; } static size_t writeTime(unsigned int t, FILE *fp, uint32_t *crc) { size_t n; n = fwrite(&t, sizeof(unsigned int), 1, fp); CHECK_FWRITE_RETURN(n, 1) *crc = crc32(*crc, (unsigned char *)&t, 4); return 4; } static size_t writeNumber(uint64_t u64, FILE *fp, uint32_t *crc) { uint64_t size; int n; unsigned char u64_bytes[9]; n = getUint64Bytes(u64, u64_bytes); size = fwrite(u64_bytes, sizeof(unsigned char), n, fp); CHECK_FWRITE_RETURN(size, n) *crc = crc32(*crc, u64_bytes, n); return size; } static unsigned char readByte(FILE *fp) { unsigned char c; int n; n = fread(&c, 1, 1, fp); CHECK_FREAD_RETURN(n, 1) return c; } static void skipNByte(int n, FILE *fp) { fseek(fp, n, SEEK_CUR); } static uint32_t readCRC(FILE *fp) { uint32_t crc; int n; n = fread(&crc, sizeof(uint32_t), 1, fp); CHECK_FREAD_RETURN(n, 1) return crc; } int getExtraByteNum2(uint8_t first) { int i; if (first == 0xff) return 8; for (i = 0; i < sizeof(first_byte_table) - 1; ++i) { if (first >= first_byte_table[i] && first < first_byte_table[i + 1]) break; } return i; } int getExtraByteNum(uint64_t n) { int i; int boundary_len = sizeof(extra_byte_boundary) / sizeof(extra_byte_boundary[0]); if (n == 0) return 0; for (i = 0; i < boundary_len; ++i) { if (n > extra_byte_boundary[i]) continue; break; } return i ? i - 1 : i; } /* * from UINT64 to uint64_t */ uint64_t getU64FromBytes(FILE *fp) { int i; int k; int extra; uint64_t ret; unsigned char c; uint8_t p = 0; unsigned char buf[8] = {0}; c = readByte(fp); extra = getExtraByteNum2(c); for (i = 0, k = 7; i < extra; ++i, --k) { p += 1 << k; } for (i = 0; i < extra; ++i) { buf[i] = readByte(fp); } if (extra != 7 && extra != 8) { buf[i] = c & ~p; } memcpy(&ret, buf, sizeof(buf)); return ret; } /** * get the number n's UINT64 form * n: the number * p: the bytes * return: total bytes */ int getUint64Bytes(uint64_t n, unsigned char *p) { int i; int extra = getExtraByteNum(n); uint64_t number = n; unsigned char first_byte; for (i = 0; i < extra; ++i) { number /= 0x100; } first_byte = number | first_byte_table[extra]; number = n; p[0] = first_byte; for (i = 0; i < extra; ++i) { p[i + 1] = number % 0x100; number /= 0x100; } return extra + 1; } /** * this means no category, every files are in one folder * the folder number/packed streams number is equal to * the number of category names * default is the last one, DO NOT delete it, add new * category names in front of it */ static const char *g_category_names[] = { "default" }; #ifdef QZ7Z_DEBUG void printSignatureHeader(Qz7zSignatureHeader_T *sheader) { QZ_DEBUG("-----signature header start-----\n"); QZ_DEBUG("signature: %c %c %x %x %x %x\n", sheader->signature[0], sheader->signature[1], sheader->signature[2], sheader->signature[3], sheader->signature[4], sheader->signature[5]); QZ_DEBUG("major version: %d minor version: %d\n", sheader->majorVersion, sheader->minorVersion); QZ_DEBUG("nextheaderoffset: %lu\n", sheader->nextHeaderOffset); QZ_DEBUG("nextHeaderSize: %lu\n", sheader->nextHeaderSize); QZ_DEBUG("nextHeaderCRC: %u\n", sheader->nextHeaderCRC); QZ_DEBUG("startHeaderCRC: %u\n", sheader->startHeaderCRC); QZ_DEBUG("-----end of signature header-----\n"); } void printEndHeader(Qz7zEndHeader_T *eheader) { int i; int j; QZ_DEBUG("-----print end header-------\n"); if (eheader->propertyInfo) { QZ_DEBUG(" ----------ArchiveProperties-------------\n"); QZ_DEBUG("Develop ID: %lx \n", eheader->propertyInfo->id); } if (eheader->streamsInfo) { QZ_DEBUG(" ----------StreamsInfo ------------------\n"); QZ_DEBUG(" NumPackStreams: %lu\n", eheader->streamsInfo->packInfo->NumPackStreams); QZ_DEBUG(" PackSize: "); for (i = 0; i < eheader->streamsInfo->packInfo->NumPackStreams; ++i) { QZ_DEBUG("%lu ", eheader->streamsInfo->packInfo->PackSize[i]); } QZ_DEBUG("\n ----------CodersInfo -------------------\n"); QZ_DEBUG(" NumFolders: %lu\n", eheader->streamsInfo->codersInfo->numFolders); for (i = 0; i < eheader->streamsInfo->codersInfo->numFolders; ++i) { QZ_DEBUG(" %lu ", eheader->streamsInfo->codersInfo->unPackSize[i]); } QZ_DEBUG("\n ----------SubstreamsInfo-------------------\n"); QZ_DEBUG(" NumUnpackSubstreamsInFolders: \n"); for (i = 0; i < eheader->streamsInfo->codersInfo->numFolders; ++i) { if (eheader->streamsInfo->substreamsInfo->numUnPackStreams) { QZ_DEBUG(" %lu ", eheader->streamsInfo->substreamsInfo-> numUnPackStreams[i]); QZ_DEBUG("\n unpacksize: \n"); for (j = 0; j < eheader->streamsInfo->substreamsInfo-> numUnPackStreams[i]; ++j) { QZ_DEBUG(" %lu ", eheader->streamsInfo->substreamsInfo-> unPackSize[j]); } } } } if (eheader->filesInfo) { QZ_DEBUG("\n --------------FilesInfo -------------\n"); } } #endif static int doCompressBuffer(QzSession_T *sess, unsigned char *src, unsigned int *src_len, unsigned char *dst, unsigned int *dst_len, RunTimeList_T *time_list, FILE *dst_file, off_t *dst_file_size, int last) { int ret = QZ_FAIL; unsigned int done = 0; unsigned int buf_processed = 0; unsigned int buf_remaining = *src_len; unsigned int bytes_written; unsigned int output_len = 0; RunTimeList_T *time_node = time_list; while (time_node->next) { time_node = time_node->next; } while (!done) { RunTimeList_T *run_time = calloc(1, sizeof(RunTimeList_T)); CHECK_ALLOC_RETURN_VALUE(run_time) run_time->next = NULL; time_node->next = run_time; time_node = run_time; gettimeofday(&run_time->time_s, NULL); /* do actual work */ ret = qzCompress(sess, src, src_len, dst, dst_len, last); if (QZ_BUF_ERROR == ret && 0 == *src_len) { done = 1; } QZ_DEBUG("qzCompress returned: src_len=%u dst_len=%u\n", *src_len, *dst_len); if (ret != QZ_OK && ret != QZ_BUF_ERROR && ret != QZ_DATA_ERROR) { QZ_ERROR("doCompressBuffer in qzip_7z.c :failed with error: %d\n", ret); break; } gettimeofday(&run_time->time_e, NULL); bytes_written = fwrite(dst, 1, *dst_len, dst_file); CHECK_FWRITE_RETURN_FP(dst_file, bytes_written, *dst_len) *dst_file_size += bytes_written; buf_processed += *src_len; buf_remaining -= *src_len; output_len += *dst_len; if (0 == buf_remaining) { done = 1; } src += *src_len; QZ_DEBUG("src_len is %u ,buf_remaining is %u\n", *src_len, buf_remaining); *src_len = buf_remaining; } *src_len = buf_processed; *dst_len = output_len; return ret; } static int doDecompressBuffer(QzSession_T *sess, unsigned char *src, unsigned int *src_len, unsigned char *dst, unsigned int *dst_len, RunTimeList_T *time_list, int last) { int ret = QZ_FAIL; unsigned int done = 0; unsigned int buf_processed = 0; unsigned int src_remain = *src_len; unsigned int output_len = 0; RunTimeList_T *time_node = time_list; unsigned int src_remain_output = *dst_len; unsigned int total = *dst_len; while (time_node->next) { time_node = time_node->next; } while (!done) { RunTimeList_T *run_time = calloc(1, sizeof(RunTimeList_T)); CHECK_ALLOC_RETURN_VALUE(run_time) run_time->next = NULL; time_node->next = run_time; time_node = run_time; gettimeofday(&run_time->time_s, NULL); /* do actual work */ ret = qzDecompress(sess, src, src_len, dst, &src_remain_output); if (QZ_DATA_ERROR == ret || (QZ_BUF_ERROR == ret && 0 == *src_len)) { done = 1; } if (ret != QZ_OK && ret != QZ_BUF_ERROR && ret != QZ_DATA_ERROR) { QZ_ERROR("doDecompressBuffer in qzip_7z.c :failed with error: %d\n", ret); break; } gettimeofday(&run_time->time_e, NULL); *dst_len = src_remain_output; buf_processed += *src_len; src_remain -= *src_len; output_len += *dst_len; src_remain_output = total - output_len; if (0 == src_remain) { done = 1; } if (0 == src_remain_output) { done = 1; } src += *src_len; QZ_DEBUG("src_len is %u ,src_remain is %u\n", *src_len, src_remain); *src_len = src_remain; } *src_len = buf_processed; *dst_len = output_len; return ret; } int doCompressFile(QzSession_T *sess, Qz7zItemList_T *list, const char *dst_file_name) { int ret = OK; struct stat src_file_stat; unsigned int src_buffer_size = 0; unsigned int dst_buffer_size = 0, dst_buffer_max_size = 0; off_t src_file_size = 0, dst_file_size = 0, file_remaining = 0; const char *src_file_name = NULL; unsigned char *src_buffer = NULL; unsigned char *dst_buffer = NULL; FILE *src_file = NULL; FILE *dst_file = NULL; Qz7zEndHeader_T *eheader = NULL; unsigned int bytes_read = 0; unsigned long bytes_processed = 0; unsigned int ratio_idx = 0; const unsigned int ratio_limit = sizeof(g_bufsz_expansion_ratio) / sizeof(unsigned int); unsigned int read_more = 0; int src_fd = -1; uint64_t eheader_size; uint32_t crc = 0; uint32_t start_crc = 0; uint64_t non_empty_number = 0; RunTimeList_T *time_list_head = malloc(sizeof(RunTimeList_T)); Qz7zSignatureHeader_T *sheader = NULL; size_t total_compressed_size = 0; int is_last; int n_part; // how much parts can the src file be splited int n_part_i; if (!time_list_head) { QZ_DEBUG("malloc time_list_head error\n"); ret = QZ7Z_ERR_OOM; goto exit; } gettimeofday(&time_list_head->time_s, NULL); time_list_head->time_e = time_list_head->time_s; time_list_head->next = NULL; dst_file = fopen(dst_file_name, "w+"); if (!dst_file) { QZ_ERROR("Cannot open file: %s\n", dst_file_name); ret = QZ7Z_ERR_OPEN; goto exit; } sheader = generateSignatureHeader(); if (!sheader) { QZ_ERROR("Cannot generate signature header, out of memory"); ret = QZ7Z_ERR_OOM; goto exit; } src_buffer = malloc(SRC_BUFF_LEN); if (!src_buffer) { QZ_DEBUG("malloc error\n"); ret = QZ7Z_ERR_OOM; goto exit; } dst_buffer_max_size = qzMaxCompressedLength(SRC_BUFF_LEN, sess); dst_buffer = malloc(dst_buffer_max_size); if (!dst_buffer) { QZ_DEBUG("malloc error\n"); ret = QZ7Z_ERR_OOM; goto exit; } writeSignatureHeader(sheader, dst_file); non_empty_number = list->items[1]->total; if (non_empty_number) { for (int i = 0; i < non_empty_number; ++i) { Qz7zFileItem_T *cur_file = qzListGet(list->items[1], i); src_file_name = cur_file->fileName; if (!cur_file->isSymLink) { src_fd = open(src_file_name, O_RDONLY); if (src_fd < 0) { ret = QZ7Z_ERR_OPEN; goto exit; } ret = fstat(src_fd, &src_file_stat); if (ret) { QZ_ERROR("stat(): failed\n"); ret = QZ7Z_ERR_STAT; goto exit; } src_file = fdopen(src_fd, "r"); if (!src_file) { QZ_ERROR("create %s error\n", src_file_name); ret = QZ7Z_ERR_OPEN; goto exit; } } else { ret = lstat(src_file_name, &src_file_stat); if (ret) { QZ_ERROR("lstat(): failed\n"); ret = QZ7Z_ERR_STAT; goto exit; } } if (S_ISBLK(src_file_stat.st_mode)) { if (ioctl(src_fd, BLKGETSIZE, &src_file_size) < 0) { perror(src_file_name); ret = QZ7Z_ERR_IOCTL; goto exit; } src_file_size *= 512; } else { src_file_size = src_file_stat.st_size; } src_buffer_size = (src_file_size > SRC_BUFF_LEN) ? SRC_BUFF_LEN : src_file_size; dst_buffer_size = qzMaxCompressedLength(src_buffer_size, sess); file_remaining = src_file_size; read_more = 1; n_part = src_file_size / SRC_BUFF_LEN; n_part = (src_file_size % SRC_BUFF_LEN) ? n_part + 1 : n_part; is_last = 0; n_part_i = 1; do { is_last = (i == non_empty_number - 1) && (n_part_i++ == n_part); if (read_more) { if (cur_file->isSymLink) { int size; size = readlink(cur_file->fileName, (char *)src_buffer, src_buffer_size); bytes_read = size; } else { bytes_read = fread(src_buffer, 1, src_buffer_size, src_file); QZ_PRINT("Reading input file %s (%u Bytes)\n", src_file_name, bytes_read); } } else { bytes_read = file_remaining; } puts("Compressing..."); unsigned int dest_len = dst_buffer_size; ret = doCompressBuffer(sess, src_buffer, &bytes_read, dst_buffer, &dest_len, time_list_head, dst_file, &dst_file_size, is_last); if (QZ_DATA_ERROR == ret || QZ_BUF_ERROR == ret) { bytes_processed += bytes_read; if (0 != bytes_read) { if (-1 == fseek(src_file, bytes_processed, SEEK_SET)) { ret = ERROR; goto exit; } read_more = 1; } else if (QZ_BUF_ERROR == ret) { // dest buffer not long enough if (ratio_limit == ratio_idx) { QZ_ERROR("Could not expand more destination " "buffer\n"); ret = ERROR; goto exit; } free(dst_buffer); dst_buffer_size = src_buffer_size * g_bufsz_expansion_ratio[ratio_idx++]; dst_buffer = malloc(dst_buffer_size); if (NULL == dst_buffer) { QZ_ERROR("Fail to allocate destination buffer " "with size %u\n", dst_buffer_size); ret = ERROR; goto exit; } read_more = 0; } else { // corrupt data ret = ERROR; goto exit; } } else if (QZ_OK != ret) { QZ_ERROR("Process file error: %d\n", ret); ret = ERROR; goto exit; } else { if (cur_file->isSymLink) { read_more = 0; } else { read_more = 1; } } file_remaining -= bytes_read; total_compressed_size = dst_file_size; } while (file_remaining > 0); if (!cur_file->isSymLink) { fclose(src_file); src_file = NULL; if (src_fd >= 0) { close(src_fd); src_fd = -1; } } }// end for } else { QZ_PRINT("Compressing...\n"); } eheader = generateEndHeader(list, total_compressed_size); if (!eheader) { QZ_ERROR("cannot allocate for end header\n"); ret = QZ7Z_ERR_OOM; goto exit; } eheader_size = writeEndHeader(eheader, dst_file, &crc); if (eheader_size == 0) { QZ_ERROR("Cannot write 7z end header\n"); ret = QZ7Z_ERR_END_HEADER; goto exit; } QZ_DEBUG("total compressed: %lu\n" "eheader_size: %lu\n" "crc: %x\n", total_compressed_size, eheader_size, crc); unsigned char start_header[24]; memcpy(start_header + SIGNATUREHEADER_OFFSET_NEXTHEADER_OFFSET, &total_compressed_size, sizeof(total_compressed_size)); memcpy(start_header + SIGNATUREHEADER_OFFSET_NEXTHEADER_SIZE, &eheader_size, sizeof(eheader_size)); memcpy(start_header + SIGNATUREHEADER_OFFSET_NEXTHEADER_CRC, &crc, sizeof(crc)); start_crc = crc32(start_crc, start_header + SIGNATUREHEADER_OFFSET_NEXTHEADER_OFFSET, 20); memcpy(start_header, &start_crc, sizeof(start_crc)); fseek(dst_file, SIGNATUREHEADER_OFFSET_BASE, SEEK_SET); fwrite(start_header, 1, sizeof(start_header), dst_file); displayStats(time_list_head, src_file_size, dst_file_size, 1/* is_compress */); exit: if (eheader) { freeEndHeader(eheader, 1); } if (src_file) { fclose(src_file); } if (dst_buffer) { free(dst_buffer); } if (src_buffer) { free(src_buffer); } if (sheader) { qzFree(sheader); } if (dst_file) { fclose(dst_file); } if (src_fd >= 0) { close(src_fd); } freeTimeList(time_list_head); if (!g_keep && OK == ret) { int re = deleteSourceFile(list); if (re != QZ7Z_OK) { QZ_ERROR("deleteSourceFile error: %d\n", re); return re; } } return ret; } int qz7zCompress(QzSession_T *sess, Qz7zItemList_T *list, const char *out_name) { char oname[MAX_PATH_LEN]; memset(oname, 0, MAX_PATH_LEN); //add 7z suffix if (makeOutName(out_name, out_name, oname, 1) == 0) { out_name = oname; } return doCompressFile(sess, list, out_name); } int deleteSourceFile(Qz7zItemList_T *list) { if (list == NULL) { QZ_ERROR("the input is NULL\n"); return QZ7Z_ERR_NULL_INPUT_LIST; } QzListHead_T *head; QzListNode_T *ptr; for (int i = 1; i >= 0; i--) { head = list->items[i]; if (head->total == 0) { continue; } int n_node = (head->total + (head->num - 1)) / head->num; for (int node = n_node - 1; node >= 0; node--) { ptr = head->next; int end = 0; while (end < node) { ptr = ptr->next; end++; } for (int j = ptr->used - 1; j >= 0; j--) { Qz7zFileItem_T *item = (Qz7zFileItem_T *)(*(ptr->items + j)); int re = remove(item->fileName); if (re != 0) { QZ_ERROR("Remove error\n"); return QZ7Z_ERR_REMOVE; } } } } return QZ7Z_OK; } Qz7zSignatureHeader_T *resolveSignatureHeader(FILE *fp) { int n; Qz7zSignatureHeader_T *sheader = qzMalloc(sizeof(Qz7zSignatureHeader_T), 0, PINNED_MEM); if (sheader) { n = fread(&sheader->signature, sizeof(unsigned char), 6, fp); CHECK_FREAD_RETURN(n, 6); n = fread(&sheader->majorVersion, sizeof(unsigned char), 1, fp); CHECK_FREAD_RETURN(n, 1); n = fread(&sheader->minorVersion, sizeof(unsigned char), 1, fp); CHECK_FREAD_RETURN(n, 1); n = fread(&sheader->startHeaderCRC, sizeof(uint32_t), 1, fp); CHECK_FREAD_RETURN(n, 1); n = fread(&sheader->nextHeaderOffset, sizeof(uint64_t), 1, fp); CHECK_FREAD_RETURN(n, 1); n = fread(&sheader->nextHeaderSize, sizeof(uint64_t), 1, fp); CHECK_FREAD_RETURN(n, 1); n = fread(&sheader->nextHeaderCRC, sizeof(uint32_t), 1, fp); CHECK_FREAD_RETURN(n, 1); } else { QZ_ERROR("malloc error\n"); } return sheader; } #define QZ7Z_DEVELOP_ID_PREFIX_SHIFT 56 #define QZ7Z_DEVELOP_ID_SHIFT 16 Qz7zArchiveProperty_T *resolveArchiveProperties(FILE *fp) { Qz7zArchiveProperty_T *property = qzMalloc(sizeof(Qz7zArchiveProperty_T), 0, PINNED_MEM); if (!property) { QZ_ERROR("malloc property error\n"); return NULL; } uint64_t size; uint64_t id = getU64FromBytes(fp); if ((id >> QZ7Z_DEVELOP_ID_PREFIX_SHIFT) != 0x3f /* 7z dev id prefix */) { QZ_ERROR("7z file ArchiveProperties develop ID error.\n" "develop ID should starts with 0x3f\n"); goto error; } QZ_DEBUG("id = %lu\n", id); if (((id >> QZ7Z_DEVELOP_ID_SHIFT) & 0xffffffffff) != QZ7Z_DEVELOP_ID) { QZ_ERROR("7z file ArchiveProperties develop ID(%lu) error.\n" , id >> 16 & 0xffffffffff); goto error; } if ((id & 0xffff) != QZ7Z_DEVELOP_SUBID) { QZ_ERROR("7z file ArchiveProperties develop subID(%lu) error.\n" , id & 0xffff); goto error; } property->id = id; size = getU64FromBytes(fp); skipNByte(size, fp); if (readByte(fp) != PROPERTY_ID_END) { QZ_ERROR("Resolve PackInfo: kEnd (0x00) expected\n"); goto error; } return property; error: if (property) { qzFree(property); } return NULL; } Qz7zPackInfo_T *resolvePackInfo(FILE *fp) { Qz7zPackInfo_T *pack = qzMalloc(sizeof(Qz7zPackInfo_T), 0, PINNED_MEM); if (!pack) { QZ_ERROR("malloc pack error\n"); return NULL; } pack->PackPos = getU64FromBytes(fp); pack->NumPackStreams = getU64FromBytes(fp); pack->PackSize = qzMalloc(pack->NumPackStreams * sizeof(uint64_t), 0, PINNED_MEM); if (!pack->PackSize) { goto error; } if (readByte(fp) != PROPERTY_ID_SIZE) { QZ_ERROR("Resolve PackInfo: kSize (0x09) expected\n"); goto error; } for (int i = 0; i < pack->NumPackStreams; ++i) { pack->PackSize[i] = getU64FromBytes(fp); } if (readByte(fp) != PROPERTY_ID_END) { QZ_ERROR("Resolve PackInfo: kEnd (0x00) expected\n"); goto error; } return pack; error: if (pack) { qzFree(pack->PackSize); qzFree(pack); } return NULL; } Qz7zCodersInfo_T *resolveCodersInfo(FILE *fp) { unsigned char c; int i_folder = 0; Qz7zCodersInfo_T *coders = qzMalloc(sizeof(Qz7zCodersInfo_T), 0, PINNED_MEM); if (!coders) { QZ_ERROR("malloc coders\n"); return NULL; } if ((c = readByte(fp)) != PROPERTY_ID_FOLDER) { QZ_ERROR("Resolve CodersInfo: kFolders(0x0b) expected: %02x\n", c); goto error; } coders->numFolders = getU64FromBytes(fp); coders->folders = qzMalloc(coders->numFolders * sizeof(Qz7zFolderInfo_T), 0, PINNED_MEM); if (!coders->folders) { QZ_ERROR("malloc folders error\n"); goto error; } if ((c = readByte(fp)) == 0) { for (i_folder = 0; i_folder < coders->numFolders; ++i_folder) { Qz7zFolderInfo_T *p = &coders->folders[i_folder]; size_t n; unsigned int id_size; p->numCoders = readByte(fp); p->coder_list = qzMalloc(sizeof(Qz7zCoder_T), 0, PINNED_MEM); if (!p->coder_list) { goto error; } p->coder_list->coderFirstByte.uc = readByte(fp); id_size = p->coder_list->coderFirstByte.st.CodecIdSize; p->coder_list->codecID = qzMalloc(id_size, 0, PINNED_MEM); if (!p->coder_list->codecID) { QZ_ERROR("malloc error\n"); goto error; } n = fread(p->coder_list->codecID, 1, id_size, fp); CHECK_FREAD_RETURN(n, id_size) QZ_DEBUG("codec id: %0x %0x %0x \n", p->coder_list->codecID[0], p->coder_list->codecID[1], p->coder_list->codecID[2]); } } else if (c == 1) { coders->dataStreamIndex = getU64FromBytes(fp); } else { QZ_ERROR("Folders(0x00) or DataStreamIndex(0x01) expected\n"); goto error; } if ((c = readByte(fp)) != PROPERTY_ID_CODERS_UNPACK_SIZE) { QZ_ERROR("Resolve CodersInfo: kCoderUnpackSize(0x0c) expected: %02x\n", c); goto error; } coders->unPackSize = qzMalloc(coders->numFolders * sizeof(uint64_t), 0, PINNED_MEM); if (!coders->unPackSize) { QZ_ERROR("malloc error\n"); goto error; } for (int i = 0; i < coders->numFolders; ++i) { coders->unPackSize[i] = getU64FromBytes(fp); } if (readByte(fp) != PROPERTY_ID_END) { QZ_ERROR("Resolve CodersInfo: kEnd (0x00) expected\n"); goto error; } QZ_DEBUG("Resolve CodersInfo: finished\n"); return coders; error: freeCodersInfo(coders); return NULL; } Qz7zSubstreamsInfo_T *resolveSubstreamsInfo(int n_folder, FILE *fp) { unsigned char c; int total = 1; int end = 0; int unpackstreams_resolved = 0; int unpacksize_resolved = 0; int digests_resolved = 0; Qz7zSubstreamsInfo_T *substreams = qzMalloc(sizeof(Qz7zSubstreamsInfo_T), 0, PINNED_MEM); if (!substreams) { QZ_ERROR("malloc error\n"); return NULL; } memset(substreams, 0, sizeof(Qz7zSubstreamsInfo_T)); while (!end) { c = readByte(fp); switch (c) { case PROPERTY_ID_NUM_UNPACK_STREAM: if (unpackstreams_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } total = 0; QZ_DEBUG("Resolve SubstreamsInfo: number folders: %d\n", n_folder); substreams->numUnPackStreams = qzMalloc(n_folder * sizeof(uint64_t), 0, PINNED_MEM); if (!substreams->numUnPackStreams) { QZ_ERROR("malloc error\n"); goto error; } for (int i = 0; i < n_folder; ++i) { substreams->numUnPackStreams[i] = getU64FromBytes(fp); QZ_DEBUG(" numUnPackStreams[i] = %lu\n", substreams->numUnPackStreams[i]); total += substreams->numUnPackStreams[i]; } QZ_DEBUG("resolve numUnpackStreams(0x0d) done\n"); unpackstreams_resolved = 1; break; case PROPERTY_ID_SIZE: if (unpacksize_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } if (total - n_folder == 0) { QZ_DEBUG("every folder has one file. No unpacksize part. \n"); } else { substreams->unPackSize = qzMalloc((total - n_folder) * sizeof(uint64_t), 0, PINNED_MEM); if (!substreams->unPackSize) { QZ_DEBUG("malloc error\n"); goto error; } for (int i = 0; i < total - n_folder; ++i) { substreams->unPackSize[i] = getU64FromBytes(fp); QZ_DEBUG("unpacksize: %lu total:%d folder:%d\n", substreams->unPackSize[i], total, n_folder); } } QZ_DEBUG("resolve kSize(0x09) done \n"); unpacksize_resolved = 1; break; case PROPERTY_ID_CRC: if (digests_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } substreams->digests = qzMalloc(sizeof(Qz7zDigest_T), 0, PINNED_MEM); if (!substreams->digests) { QZ_ERROR("malloc error\n"); goto error; } if ((c = readByte(fp)) != 1) { QZ_DEBUG("Resolve Substreams Info: not allaredefined ERROR. " "c = %02x\n", c); goto error; } substreams->digests->allAreDefined = 1; QZ_DEBUG(" read allaredefined : 111 total: %d\n", total); substreams->digests->numDefined = total; substreams->digests->crc = qzMalloc(total * sizeof(uint32_t), 0, PINNED_MEM); if (!substreams->digests->crc) { QZ_ERROR("malloc error\n"); goto error; } for (int i = 0; i < total; ++i) { readCRC(fp); } QZ_DEBUG("resolve CRC(0x0a) done of substreams\n"); digests_resolved = 1; break; case PROPERTY_ID_END: end = 1; break; default: QZ_ERROR("resolve unexpected byte\n"); goto error; } } QZ_DEBUG("Resolve SubstreamsInfo: finished\n"); return substreams; error: freeSubstreamsInfo(substreams); return NULL; } static int readNames(Qz7zFileItem_T *p, uint64_t num, FILE *fp) { unsigned char c; uint64_t u64; int i, j; char path[PATH_MAX]; /* wc is used to store a wchar_t for ASCII, it is stored at wc[0] and wc[1] is '\0' */ char wc[2]; size_t n; u64 = getU64FromBytes(fp); // size QZ_DEBUG("u64 = %lu\n", u64); (void)u64; c = readByte(fp); if (c != 0) { QZ_ERROR("0x11 label external is not 0. Exit. c = %d\n", c); return QZ7Z_ERR_NOT_EXPECTED_CHAR; } for (i = 0; i < num; ++i) { memset(path, 0, sizeof(path)); j = 0; while (1) { n = fread(wc, 1, sizeof(wc), fp); CHECK_FREAD_RETURN(n, sizeof(wc)) if (!wc[0] && !wc[1]) // two-zero byte means the end break; path[j++] = wc[0]; } path[j] = 0; QZ_DEBUG("path: %s length: %d\n", path, j); (p + i)->nameLength = j + 1; // not include terminal null byte (p + i)->fileName = malloc(j + 1); CHECK_ALLOC_RETURN_VALUE((p + i)->fileName) strncpy((p + i)->fileName, path, j + 1); } return QZ7Z_OK; } static int readTimes(Qz7zFileItem_T *p, uint64_t num, FILE *fp) { uint64_t section_size; size_t nr; FILETIME_T ft; section_size = getU64FromBytes(fp); (void)section_size; if (readByte(fp) != 1) { QZ_ERROR("Resolve Times: AllAreDefined must be 1\n"); return QZ7Z_ERR_TIMES; } if (readByte(fp) != 0) { QZ_ERROR("Resolve Times: External must be 0\n"); return QZ7Z_ERR_TIMES; } for (int i = 0; i < num; ++i) { nr = fread(&ft.low, sizeof(uint32_t), 1, fp); if (nr < 1) { QZ_ERROR("readTimes: fread error\n"); return QZ7Z_ERR_READ_LESS; } nr = fread(&ft.high, sizeof(uint32_t), 1, fp); if (nr < 1) { QZ_ERROR("readTimes: fread error\n"); return QZ7Z_ERR_READ_LESS; } (p + i)->mtime = filetimeToUnixtime(ft); (p + i)->atime = filetimeToUnixtime(ft); } return QZ7Z_OK; } static int readAttributes(Qz7zFileItem_T *p, uint64_t num, FILE *fp) { unsigned char c; uint64_t u64; uint32_t attr; size_t nr; u64 = getU64FromBytes(fp); // size (void)u64; c = readByte(fp); // AllAreDefined if (c != 1) { QZ_ERROR("Resolve Attributes: AllAreDefined is not 1. Exit. " "c = %d\n", c); return QZ7Z_ERR_NOT_EXPECTED_CHAR; } c = readByte(fp); // External if (c != 0) { QZ_ERROR("Resolve Attributes: External is not 0. Exit. c = %d\n", c); return QZ7Z_ERR_NOT_EXPECTED_CHAR; } for (int i = 0; i < num; ++i) { nr = fread(&attr, sizeof(uint32_t), 1, fp); if (nr < 1) { QZ_ERROR("readAttributes: fread error\n"); return QZ7Z_ERR_READ_LESS; } (p + i)->attribute = attr; } return QZ7Z_OK; } Qz7zFilesInfo_Dec_T *resolveFilesInfo(FILE *fp) { int n; int i; int j; int end; int file_index; unsigned char c; uint64_t u64; uint64_t total_num; uint64_t dir_num; uint64_t file_num; Qz7zFilesInfo_Dec_T *files = qzMalloc(sizeof(Qz7zFilesInfo_Dec_T), 0, PINNED_MEM); if (!files) { QZ_ERROR("malloc error\n"); return NULL; } memset(files, 0, sizeof(Qz7zFilesInfo_Dec_T)); total_num = getU64FromBytes(fp); Qz7zFileItem_T *p = qzMalloc(total_num * sizeof( Qz7zFileItem_T), 0, PINNED_MEM); if (!p) { QZ_ERROR("malloc error\n"); goto error; } memset(p, 0, total_num * sizeof(*p)); end = 0; while (!end) { switch ((c = readByte(fp))) { case PROPERTY_ID_END: end = 1; break; case PROPERTY_ID_EMPTY_STREAM: file_index = 0; dir_num = 0; /* n bytes to hold this information */ n = (total_num % 8) ? (total_num / 8 + 1) : (total_num / 8); u64 = getU64FromBytes(fp); /* property size */ file_index = 0; for (i = 0; i < n; ++i) { // read n bytes property c = readByte(fp); for (j = 7; j >= 0; --j) { int is_dir = !!(c & 1 << j); p[file_index++].isDir = is_dir; if (is_dir) { dir_num++; } if (total_num == file_index) { break; } } } file_num = total_num - dir_num; files->file_num = file_num; files->dir_num = dir_num; break; case PROPERTY_ID_EMPTY_FILE: file_index = 0; u64 = getU64FromBytes(fp); // property size for (i = 0; i < u64; ++i) { c = readByte(fp); for (j = 7; j >= 0; --j) { p[file_index].isEmpty = !!(c & 1 << j); if (p[file_index].isEmpty) { p[file_index].isDir = 0; } file_index++; if (total_num == file_index) break; } } break; case PROPERTY_ID_NAME: if (readNames(p, total_num, fp) < 0) { goto error; } break; case PROPERTY_ID_CTIME: case PROPERTY_ID_ATIME: case PROPERTY_ID_MTIME: if (readTimes(p, total_num, fp) < 0) { goto error; } break; case PROPERTY_ID_ATTRIBUTES: if (readAttributes(p, total_num, fp) < 0) { goto error; } break; case PROPERTY_ID_DUMMY: c = readByte(fp); if (c) { skipNByte(c, fp); } break; default: QZ_ERROR("Not expected attribute\n"); goto error; } } files->items = p; return files; error: if (p) { qzFree(p); } if (files) { qzFree(files); } return NULL; } Qz7zStreamsInfo_T *resolveMainStreamsInfo(FILE *fp) { unsigned char c; int end = 0; int pack_info_resolved = 0; int coders_info_allocated = 0; int coders_info_resolved = 0; int substreams_info_resolved = 0; Qz7zStreamsInfo_T *streamsInfo = malloc(sizeof(Qz7zStreamsInfo_T)); if (!streamsInfo) { QZ_ERROR("malloc error\n"); return NULL; } memset(streamsInfo, 0, sizeof(Qz7zStreamsInfo_T)); while (!end) { switch (c = readByte(fp)) { case PROPERTY_ID_PACKINFO: if (pack_info_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } streamsInfo->packInfo = resolvePackInfo(fp); if (!streamsInfo->packInfo) { QZ_ERROR("Resolve Pack Info error\n"); goto error; } pack_info_resolved = 1; break; case PROPERTY_ID_UNPACKINFO: if (coders_info_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } streamsInfo->codersInfo = resolveCodersInfo(fp); if (!streamsInfo->codersInfo) { QZ_ERROR("Resolve Coders Info error\n"); goto error; } coders_info_allocated = 1; coders_info_resolved = 1; break; case PROPERTY_ID_SUBSTREAMSINFO: if (substreams_info_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } if (!coders_info_allocated) { QZ_ERROR("No coders info\n"); goto error; } streamsInfo->substreamsInfo = resolveSubstreamsInfo(streamsInfo ->codersInfo->numFolders, fp); if (!streamsInfo->substreamsInfo) { QZ_ERROR("Resolve Substreams Info error\n"); goto error; } substreams_info_resolved = 1; break; case PROPERTY_ID_END: end = 1; break; default: QZ_ERROR("Resolve Mainstreams Info Error\n"); goto error; } } return streamsInfo; error: freeStreamsInfo(streamsInfo); return NULL; } Qz7zEndHeader_T *resolveEndHeader(FILE *fp, Qz7zSignatureHeader_T *sheader) { Qz7zEndHeader_T *eheader = malloc(sizeof(Qz7zEndHeader_T)); if (!eheader) { QZ_ERROR("malloc error\n"); return NULL; } memset(eheader, 0, sizeof(Qz7zEndHeader_T)); unsigned int status = 0; unsigned char c; int end = 0; int has_archive_property = 0; int archive_property_resolved = 0; int streams_info_resolved = 0; int files_info_resolved = 0; fseek(fp, sheader->nextHeaderOffset + 0x20, SEEK_CUR); while (!end) { switch (c = readByte(fp)) { case PROPERTY_ID_HEADER: status = RESOLVE_STATUS_IN_HEADER; break; case PROPERTY_ID_ARCHIVE_PROPERTIES: if (archive_property_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } has_archive_property = 1; status = RESOLVE_STATUS_IN_ARCHIVE_PROPERTIES; eheader->propertyInfo = resolveArchiveProperties(fp); if (!eheader->propertyInfo) { QZ_ERROR("Resolve Archive property error\n"); goto error; } archive_property_resolved = 1; break; case PROPERTY_ID_MAIN_STREAMSINFO: if (streams_info_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } status = RESOLVE_STATUS_IN_STREAMSINFO; eheader->streamsInfo = resolveMainStreamsInfo(fp); if (!eheader->streamsInfo) { QZ_ERROR("malloc error\n"); goto error; } streams_info_resolved = 1; break; case PROPERTY_ID_FILESINFO: if (files_info_resolved) { QZ_ERROR("Resolve substreams info: duplicated tag\n"); goto error; } status = RESOLVE_STATUS_IN_FILESINFO; eheader->filesInfo_Dec = resolveFilesInfo(fp); if (!eheader->filesInfo_Dec) { QZ_ERROR("Resolve Files Info error\n"); goto error; } files_info_resolved = 1; break; case PROPERTY_ID_END: QZ_DEBUG("read kEnd: %d\n\n\n", status); if (status == RESOLVE_STATUS_IN_FILESINFO) end = 1; break; default: QZ_ERROR("Resolve End Header Error\n"); goto error; } } if (!has_archive_property) { QZ_ERROR("ERROR: property 'QAT7z' not found\n"); QZ_ERROR("This archive is not compressed by QAT,"); QZ_ERROR("QAT only support 7z archive compressed by QAT\n"); goto error; } return eheader; error: freeEndHeader(eheader, 0); return NULL; } static int createEmptyFile(const char *filename) { FILE *fp = fopen(filename, "w"); if (!fp) { QZ_ERROR("create %s error\n", filename); return -1; } fclose(fp); return 0; } /** * create `newdir` at current directory * back: 1 return to original dir, 0 otherwise */ int createDir(const char *newdir, int back) { int ret; char *dirc, *basec; char pwd[PATH_MAX]; char dir_name[PATH_MAX + 1] = {0}; char base_name[PATH_MAX + 1] = {0}; if (!getcwd(pwd, sizeof(pwd))) { return QZ7Z_ERR_GETCWD; } QZ_DEBUG("working directory: %s\n", pwd); strncpy(dir_name, newdir, PATH_MAX); strncpy(base_name, newdir, PATH_MAX); dirc = dirname(dir_name); basec = basename(base_name); if (!strcmp(dirc, ".")) { if (mkdir(newdir, 0755) < 0) { if (errno != EEXIST) { perror("create dir failed\n"); return QZ7Z_ERR_MKDIR; } } if (chdir(newdir) < 0) { perror("cannot change working dir\n"); return QZ7Z_ERR_CHDIR; } if (back) { if (chdir(pwd) < 0) { perror("cannot change working dir\n"); return QZ7Z_ERR_CHDIR; } } return QZ7Z_OK; } if ((ret = createDir(dirc, 0)) < 0) return ret; if ((ret = createDir(basec, 0)) < 0) return ret; if (back) { if (chdir(pwd) < 0) { perror("cannot change working dir\n"); return QZ7Z_ERR_CHDIR; } } return QZ7Z_OK; } void decompressEmptyfilesAndDirectories(Qz7zFilesInfo_Dec_T *info) { uint64_t num = info->dir_num; Qz7zFileItem_T *p = info->items; for (int i = 0; i < num; ++i) { if (p[i].isDir) { createDir(p[i].fileName, 1); } else { createEmptyFile(p[i].fileName); } } } int checkHeaderCRC(Qz7zSignatureHeader_T *sh, FILE *fp) { uint32_t crc = 0; crc = crc32(crc, (unsigned char *)&sh->nextHeaderOffset, sizeof(uint64_t)); crc = crc32(crc, (unsigned char *)&sh->nextHeaderSize, sizeof(uint64_t)); crc = crc32(crc, (unsigned char *)&sh->nextHeaderCRC, sizeof(uint32_t)); if (crc != sh->startHeaderCRC) { QZ_ERROR("Signature CRC failed\n"); return -1; } size_t n; unsigned char buf[4096]; crc = 0; fseek(fp, sh->nextHeaderOffset + 0x20, SEEK_SET); while ((n = fread(buf, 1, sizeof(buf), fp))) { crc = crc32(crc, buf, n); } if (crc != sh->nextHeaderCRC) { QZ_ERROR("End header CRC failed\n"); return -1; } fseek(fp, 0, SEEK_SET); return 0; } void freePropertyInfo(Qz7zArchiveProperty_T *info) { Qz7zArchiveProperty_T *cur = info; while (cur) { free(cur->data); cur = cur->next; } qzFree(info); } void freePackInfo(Qz7zPackInfo_T *info) { if (info) { qzFree(info->PackSize); qzFree(info); } } void freeCodersInfo(Qz7zCodersInfo_T *info) { if (info) { if (info->folders) { for (int i = 0; i < info->numFolders; ++i) { Qz7zCoder_T *cur = info->folders[i].coder_list; while (cur) { qzFree(cur->codecID); cur = cur->next; } qzFree(info->folders[i].coder_list); } qzFree(info->folders); } qzFree(info->unPackSize); qzFree(info); } } void freeSubstreamsInfo(Qz7zSubstreamsInfo_T *info) { if (info) { qzFree(info->numUnPackStreams); qzFree(info->unPackSize); if (info->digests) { qzFree(info->digests->crc); qzFree(info->digests); } qzFree(info); } } void freeStreamsInfo(Qz7zStreamsInfo_T *info) { if (info) { freePackInfo(info->packInfo); freeCodersInfo(info->codersInfo); freeSubstreamsInfo(info->substreamsInfo); free(info); } } void freeFilesInfo(Qz7zFilesInfo_T *info) { qzFree(info); } void freeFilesDecInfo(Qz7zFilesInfo_Dec_T *info) { if (info) { qzFree(info->items); qzFree(info); } } void freeEndHeader(Qz7zEndHeader_T *h, int is_compress) { freePropertyInfo(h->propertyInfo); freeStreamsInfo(h->streamsInfo); if (is_compress) { freeFilesInfo(h->filesInfo); } else { freeFilesDecInfo(h->filesInfo_Dec); } free(h); } static int convertToSymlink(const char *name) { char resolved_path[PATH_MAX + 1]; FILE *file = fopen(name, "rb"); if (file) { char buf[1000 + 1]; char *ret = fgets(buf, sizeof(buf) - 1, file); fclose(file); /* To avoid CWE-22: Improper Limitation of a Pathname to a Restricted Directory * ('Path Traversal') attacks. * http://cwe.mitre.org/data/definitions/22.htm */ if (!realpath(name, resolved_path)) { return -1; } if (ret) { int ir = unlink(name); if (ir == 0) { ir = symlink(buf, name); } return ir; } } return -1; } int doDecompressFile(QzSession_T *sess, const char *src_file_name) { int ret = OK; struct stat src_file_stat; unsigned int src_buffer_size = 0; unsigned int dst_buffer_size = 0; unsigned int saved_dst_buffer_size = 0; off_t src_file_size = 0, dst_file_size = 0, file_remaining = 0; unsigned char *src_buffer = NULL; unsigned char *src_buffer_orig = NULL; unsigned char *dst_buffer = NULL; FILE *src_file = NULL; FILE *dst_file = NULL; unsigned int bytes_read = 0; unsigned int ratio_idx = 0; const unsigned int ratio_limit = sizeof(g_bufsz_expansion_ratio) / sizeof(unsigned int); unsigned int read_more = 0; int src_fd = -1; Qz7zFileItem_T *p = NULL; uint64_t dir_num = 0; uint64_t fil_num = 0; uint64_t file_index = 0; int is_last; int n_part; // how much parts can the src file be splitted int n_part_i; Qz7zSignatureHeader_T *sheader = NULL; Qz7zEndHeader_T *eheader = NULL; RunTimeList_T *run_time = NULL; \ RunTimeList_T *time_node = NULL; RunTimeList_T *time_list_head = malloc(sizeof(RunTimeList_T)); if (!time_list_head) { QZ_DEBUG("malloc RunTimeList_T error\n"); ret = QZ7Z_ERR_OOM; goto exit; } gettimeofday(&time_list_head->time_s, NULL); time_list_head->time_e = time_list_head->time_s; time_list_head->next = NULL; time_node = time_list_head; run_time = calloc(1, sizeof(RunTimeList_T)); if (!run_time) { QZ_DEBUG("malloc RunTimeList_T error\n"); ret = QZ7Z_ERR_OOM; goto exit; } run_time->next = NULL; time_node->next = run_time; time_node = run_time; gettimeofday(&run_time->time_s, NULL); src_file = fopen(src_file_name, "r"); if (src_file == NULL) { QZ_ERROR("cannot open file %s: %d\n", src_file_name, errno); ret = QZ7Z_ERR_OPEN; goto exit; } sheader = resolveSignatureHeader(src_file); if (!sheader) { QZ_ERROR("Resolve signature header\n"); ret = QZ7Z_ERR_SIG_HEADER; goto exit; } #ifdef QZ7Z_DEBUG print_signature_header(sheader); #endif if (checkHeaderCRC(sheader, src_file) < 0) { QZ_ERROR("Header error: CRC check failed\n"); ret = QZ7Z_ERR_HEADER_CRC; goto exit; } eheader = resolveEndHeader(src_file, sheader); if (!eheader) { QZ_ERROR("Cannot resolve end header\n"); ret = QZ7Z_ERR_RESOLVE_END_HEADER; goto exit; } fclose(src_file); src_file = NULL; // decode the dir p = eheader->filesInfo_Dec->items; dir_num = eheader->filesInfo_Dec->dir_num; fil_num = eheader->filesInfo_Dec->file_num; decompressEmptyfilesAndDirectories(eheader->filesInfo_Dec); // decode the content if (eheader->streamsInfo) { uint64_t folder_num = eheader->streamsInfo->codersInfo->numFolders; Qz7zFileItem_T *file_items = eheader->filesInfo_Dec->items + eheader->filesInfo_Dec->dir_num; for (int i = 0; i < folder_num; ++i) { uint64_t num_files_in_folder = eheader->streamsInfo->substreamsInfo->numUnPackStreams[i]; uint64_t total_unPack_size = eheader->streamsInfo->codersInfo->unPackSize[i]; for (int j = 0; j < num_files_in_folder - 1; ++file_index, ++j) { (file_items + file_index)->size = eheader->streamsInfo->substreamsInfo->unPackSize[j]; total_unPack_size -= (file_items + file_index)->size; } (file_items + file_index)->size = total_unPack_size; } src_fd = open(src_file_name, O_RDONLY); if (src_fd < 0) { QZ_PRINT("Open input file %s failed\n", src_file_name); ret = QZ7Z_ERR_OPEN; goto exit; } ret = fstat(src_fd, &src_file_stat); assert(!ret); if (S_ISBLK(src_file_stat.st_mode)) { if (ioctl(src_fd, BLKGETSIZE, &src_file_size) < 0) { perror(src_file_name); ret = QZ7Z_ERR_IOCTL; goto exit; } src_file_size *= 512; } else { src_file_size = src_file_stat.st_size; } src_file_size -= sheader->nextHeaderSize; src_file_size -= 32; src_buffer_size = (src_file_size > SRC_BUFF_LEN) ? SRC_BUFF_LEN : src_file_size; dst_buffer_size = src_buffer_size * g_bufsz_expansion_ratio[ratio_idx++]; saved_dst_buffer_size = dst_buffer_size; src_buffer = malloc(src_buffer_size); if (!src_buffer) { QZ_ERROR("malloc error\n"); goto exit; } src_buffer_orig = src_buffer; dst_buffer = malloc(dst_buffer_size); if (!dst_buffer) { QZ_ERROR("malloc error\n"); goto exit; } src_file = fopen(src_file_name, "r"); if (!src_file) { QZ_ERROR("file open error: %s\n", src_file_name); ret = QZ7Z_ERR_OPEN; goto exit; } // skip the signature header fseek(src_file, 32, SEEK_SET); int i = 0; // file index file_remaining = src_file_size; read_more = 1; n_part = src_file_size / SRC_BUFF_LEN; n_part = (src_file_size % SRC_BUFF_LEN) ? n_part + 1 : n_part; is_last = 0; n_part_i = 1; off_t cur_offset; cur_offset = 0; off_t file_read_processed_size = 0; int need_check_file_with_same_name = 1; do { is_last = (n_part_i++ == n_part); if (read_more) { src_buffer = src_buffer_orig; bytes_read = fread(src_buffer, 1, src_buffer_size, src_file); QZ_PRINT("Reading input file %s (%u Bytes)\n", src_file_name, bytes_read); } else { bytes_read = file_remaining; } puts("Decompressing..."); if (n_part > 1 && is_last) bytes_read -= sheader->nextHeaderSize; int buffer_remaining = bytes_read; do { unsigned int bytes_processed = buffer_remaining; ret = doDecompressBuffer(sess, src_buffer, &bytes_processed, dst_buffer, &dst_buffer_size, time_list_head, is_last); file_read_processed_size += bytes_processed; src_buffer += bytes_processed; buffer_remaining -= bytes_processed; if (QZ_DATA_ERROR == ret || QZ_BUF_ERROR == ret) { if (0 != bytes_processed) { if (-1 == fseek(src_file, file_read_processed_size, SEEK_SET)) { ret = ERROR; goto exit; } read_more = 1; } else if (QZ_BUF_ERROR == ret) { //dest buffer not long enough if (ratio_limit == ratio_idx) { QZ_ERROR("Could not expand more" "destination buffer\n"); ret = ERROR; goto exit; } free(dst_buffer); dst_buffer_size = src_buffer_size * g_bufsz_expansion_ratio[ratio_idx++]; dst_buffer = malloc(dst_buffer_size); if (NULL == dst_buffer) { QZ_ERROR("Fail to allocate destination buffer " "with size %u\n", dst_buffer_size); ret = ERROR; goto exit; } read_more = 0; } else { // corrupt data ret = ERROR; goto exit; } } else if (QZ_OK != ret) { QZ_ERROR("Process file error: %d\n", ret); ret = ERROR; goto exit; } else { read_more = 1; unsigned int dst_left; unsigned char *dst_write; size_t n_written; unsigned int st_mode; Qz7zFileItem_T *cur_file; dst_write = dst_buffer; dst_left = dst_buffer_size; dst_file_size += dst_buffer_size; while (dst_left) { cur_file = p + dir_num + i; st_mode = (cur_file->attribute) >> 16; if (need_check_file_with_same_name) { dst_file = fopen(cur_file->fileName, "w+"); } else { dst_file = fopen(cur_file->fileName, "a"); } if (NULL == dst_file) { if (S_ISLNK(st_mode)) { QZ_DEBUG("open an broken soft-link file, " "need to delete it\n"); if (!remove(cur_file->fileName)) { QZ_DEBUG("remove file %s error\n", cur_file->fileName); ret = ERROR; goto exit; } dst_file = fopen(cur_file->fileName, "a"); if (NULL == dst_file) { QZ_DEBUG("open file %s error\n", cur_file->fileName); ret = ERROR; goto exit; } } else { QZ_DEBUG("open file error\n"); ret = ERROR; goto exit; } } if (cur_file->size - cur_offset <= dst_left) { n_written = fwrite(dst_write, 1, cur_file->size - cur_offset, dst_file); if (n_written == cur_file->size - cur_offset) { ++i; need_check_file_with_same_name = 1; cur_offset = 0; } else { need_check_file_with_same_name = 0; cur_offset += n_written; } dst_left -= n_written; dst_write += n_written; } else { n_written = fwrite(dst_write, 1, dst_left, dst_file); dst_write = dst_buffer; cur_offset += dst_left; dst_left = 0; need_check_file_with_same_name = 0; } fclose(dst_file); dst_file = NULL; if (need_check_file_with_same_name) { if (S_ISLNK(st_mode)) { convertToSymlink(cur_file->fileName); } } }// end while dst_buffer_size = saved_dst_buffer_size; } } while (buffer_remaining); file_remaining -= bytes_read; } while (file_remaining > 0); } else { QZ_PRINT("Decompressing...\n"); } gettimeofday(&run_time->time_e, NULL); // restore the time struct utimbuf tb; for (int i = 0; i < dir_num + fil_num; ++i) { tb.actime = p[i].atime; tb.modtime = p[i].mtime; utime(p[i].fileName, &tb); } // restore the attribute for (int i = 0; i < dir_num + fil_num; ++i) { __mode_t mode = p[i].attribute >> 16; /* * If the file is a symbolic link, don't change it mode and skip it. * Otherwise, it will change the mode of linked file. */ if (S_ISLNK(mode)) continue; chmod(p[i].fileName, p[i].attribute >> 16); } displayStats(time_list_head, src_file_size, dst_file_size, 0/* is_compress */); exit: if (dst_file) { fclose(dst_file); } if (src_file) { fclose(src_file); } if (dst_buffer) { free(dst_buffer); } if (src_buffer_orig) { free(src_buffer_orig); } if (eheader) { freeEndHeader(eheader, 0); } if (sheader) { qzFree(sheader); } if (src_fd >= 0) { close(src_fd); } freeTimeList(time_list_head); if (!g_keep && OK == ret) { int re = remove(src_file_name); if (re != 0) { QZ_ERROR("deleteSourceFile error: %d\n", re); return re; } } return ret; } /* * the main decompress API for 7z file */ int qz7zDecompress(QzSession_T *sess, const char *archive) { return doDecompressFile(sess, archive); } /* * calculate a file's crc */ static int64_t calculateCRC(char *filename, size_t n) { FILE *fp; uint32_t crc = 0; size_t ret; size_t remaining = n; size_t len; unsigned char *buf; buf = malloc(SRC_BUFF_LEN); if (!buf) { QZ_ERROR("oom\n"); return QZ7Z_ERR_OOM; } fp = fopen(filename, "r"); if (!fp) { QZ_ERROR("filename open error\n"); free(buf); return QZ7Z_ERR_OPEN; } while (remaining > 0) { if (remaining > SRC_BUFF_LEN) len = SRC_BUFF_LEN; else len = remaining; ret = fread(buf, 1, len, fp); CHECK_FREAD_RETURN(ret, len) crc = crc32(crc, buf, len); remaining -= len; } free(buf); fclose(fp); QZ_DEBUG("%s crc: %08x\n", filename, crc); return crc; } void qzListDestroy(QzListHead_T *head) { Qz7zFileItem_T *fi; QzListNode_T *node, *tmp_node; node = head->next; do { for (int j = 0; j < node->used; ++j) { fi = node->items[j]; if (fi) { if (fi->fileName) { free(fi->fileName); fi->fileName = NULL; } free(fi); fi = NULL; } } free(node->items); tmp_node = node; node = node->next; free(tmp_node); } while (node); free(head); } void itemListDestroy(Qz7zItemList_T *p) { QzListHead_T *h; for (int i = 0; i < 2; ++i) { h = p->items[i]; qzListDestroy(h); } QzCatagoryTable_T *table = p->table; QzCatagory_T cat; if (table) { for (int i = 0; i < table->cat_num; ++i) { cat = table->catas[i]; free(cat.cat_files->next->items); free(cat.cat_files->next); free(cat.cat_files); } free(table->catas); free(table); } free(p); } static uint32_t calculateSymCRC(char *filename, size_t n) { uint32_t crc = 0; char *buf; buf = malloc(PATH_MAX + 1); if (!buf) { QZ_ERROR("oom\n"); return 0; } ssize_t size = readlink(filename, buf, PATH_MAX); if ((unsigned int)size != (unsigned int)n) { QZ_ERROR("readlink error\n"); free(buf); return 0; } crc = crc32(crc, (unsigned char *)buf, n); free(buf); return crc; } Qz7zFileItem_T *fileItemCreate(char *f) { Qz7zFileItem_T *p = malloc(sizeof(Qz7zFileItem_T)); if (p) { memset(p, 0, sizeof(Qz7zFileItem_T)); p->nameLength = strlen(f) + 1; p->fileName = (char *)malloc(p->nameLength); if (!p->fileName) { QZ_ERROR("oom\n"); free(p); return NULL; } memset(p->fileName, 0, p->nameLength); strcpy(p->fileName, f); struct stat buf; if (lstat(p->fileName, &buf) < 0) { QZ_ERROR("stat func error\n"); free(p->fileName); free(p); return NULL; } if (S_ISLNK(buf.st_mode)) { p->isSymLink = 1; p->crc = calculateSymCRC(p->fileName, buf.st_size); p->size = buf.st_size; } else if (S_ISDIR(buf.st_mode)) { p->isDir = 1; } else { p->size = buf.st_size; p->isEmpty = buf.st_size ? 0 : 1; p->crc = calculateCRC(p->fileName, p->size); } p->mtime = buf.st_mtime; p->mtime_nano = buf.st_mtim.tv_nsec; p->atime = buf.st_atime; p->atime_nano = buf.st_atim.tv_nsec; //p-7zip use 0x80000 as a unix file flag p->attribute = buf.st_mode << 16 | (0x8000); } return p; } #define QZ7Z_LIST_DEFAULT_NUM_PER_NODE 1000 void qzListAdd(QzListHead_T *head, void **fi) { // let cur points to the first node QzListNode_T *cur = head->next; QzListNode_T *last = cur; while (cur && cur->used == cur->num) { last = cur; cur = cur->next; } if (cur) { // this node is not full #ifdef QZ7Z_DEBUG QZ_DEBUG("Before Add : head num: %d total: %d last->used: %d\n", head->num, head->total, cur->used); #endif cur->items[cur->used++] = *fi; head->total++; } else { cur = (QzListNode_T *)malloc(head->num * sizeof(QzListNode_T)); CHECK_ALLOC_RETURN_VALUE(cur); cur->num = head->num; cur->used = 0; cur->next = NULL; #ifdef QZ7Z_DEBUG QZ_DEBUG("applying a new node\n"); #endif cur->items = (void **)malloc(head->num * sizeof(void *)); CHECK_ALLOC_RETURN_VALUE(cur->items) last->next = cur; #ifdef QZ7Z_DEBUG QZ_DEBUG("Before Add : head num: %d total: %d cur->used: %d\n", head->num, head->total, cur->used); #endif cur->items[cur->used++] = *fi; head->total++; } #ifdef QZ7Z_DEBUG QZ_DEBUG(" add %s to list %p : total: %u\n", ((Qz7zFileItem_T *)(*fi))->fileName, (void *)head, head->total); QZ_DEBUG("After Add : head num: %d total: %d last->used: %d\n", head->num, head->total, cur->used); #endif } void *qzListGet(QzListHead_T *head, int index) { int i; if (index >= head->total) { QZ_ERROR("qzListGet: index out of total\n"); return NULL; } QzListNode_T *cur = head->next; int steps = index / head->num; for (i = 0; i < steps; ++i) { cur = cur->next; } return cur->items[index % head->num]; } QzListHead_T *qzListCreate(int num_per_node) { QzListNode_T *node; if (num_per_node <= 0) { num_per_node = QZ7Z_LIST_DEFAULT_NUM_PER_NODE; } QzListHead_T *p = (QzListHead_T *)malloc(sizeof(QzListHead_T)); CHECK_ALLOC_RETURN_VALUE(p) node = (QzListNode_T *)malloc(sizeof(QzListNode_T)); CHECK_ALLOC_RETURN_VALUE(node) node->items = (void **)malloc(num_per_node * sizeof(void *)); CHECK_ALLOC_RETURN_VALUE(node->items) node->num = num_per_node; node->used = 0; node->next = NULL; p->next = node; p->num = num_per_node; p->total = 0; return p; } Qz7zSignatureHeader_T *generateSignatureHeader() { Qz7zSignatureHeader_T *header = qzMalloc(sizeof(Qz7zSignatureHeader_T), 0, PINNED_MEM); if (!header) { QZ_ERROR("malloc error\n"); return NULL; } for (int i = 0; i < 6; ++i) { header->signature[i] = g_header_signature[i]; } header->majorVersion = G_7ZHEADER_MAJOR_VERSION; header->minorVersion = G_7ZHEADER_MINOR_VERSION; return header; } Qz7zPackInfo_T *generatePackInfo(Qz7zItemList_T *the_list, size_t compressed_size) { Qz7zPackInfo_T *pack = qzMalloc(sizeof(Qz7zPackInfo_T), 0, PINNED_MEM); if (!pack) { QZ_ERROR("malloc error\n"); return NULL; } memset(pack, 0, sizeof(Qz7zPackInfo_T)); pack->PackPos = 0; pack->NumPackStreams = the_list->table->cat_num; pack->PackSize = qzMalloc(pack->NumPackStreams * sizeof(uint64_t), 0, PINNED_MEM); if (!pack->PackSize) { qzFree(pack); return NULL; } pack->PackSize[0] = compressed_size; pack->PackStreamDigests = NULL; return pack; } static Qz7zCoder_T *generateCoder() { Qz7zCoder_T *coder = qzMalloc(sizeof(Qz7zCoder_T), 0, PINNED_MEM); if (!coder) { QZ_ERROR("malloc error\n"); return NULL; } coder->coderFirstByte.uc = 0x03; /* 0000 0011 */ coder->codecID = qzMalloc(3 * sizeof(unsigned char), 0, PINNED_MEM); if (!coder->codecID) { QZ_ERROR("malloc error\n"); return NULL; } memcpy((char *)coder->codecID, g_deflate_codecId, 3); coder->numInStreams = 0; coder->numOutStreams = 0; coder->propertySize = 0; coder->properties = NULL; coder->next = NULL; return coder; } Qz7zFolderInfo_T *generateFolderInfo(Qz7zItemList_T *the_list, int n_folders) { if (n_folders <= 0) { n_folders = 1; } Qz7zFolderInfo_T *folders = qzMalloc(n_folders * sizeof(Qz7zFolderInfo_T), 0, PINNED_MEM); if (!folders) { QZ_ERROR("malloc error\n"); return NULL; } folders->items = the_list->items[1]; folders->numCoders = 1; folders->coder_list = generateCoder(); folders->numBindPairs = 0; folders->inIndex = NULL; folders->outIndex = NULL; folders->numPackedStreams = 0; folders->index = NULL; return folders; } Qz7zCodersInfo_T *generateCodersInfo(Qz7zItemList_T *the_list) { Qz7zCodersInfo_T *coders = qzMalloc(sizeof(Qz7zCodersInfo_T), 0, PINNED_MEM); if (!coders) { QZ_ERROR("malloc error\n"); return NULL; } coders->numFolders = the_list->table->cat_num; coders->folders = generateFolderInfo(the_list, coders->numFolders); if (!coders->folders) { QZ_ERROR("malloc error\n"); qzFree(coders); return NULL; } coders->unPackSize = qzMalloc(coders->numFolders * sizeof(uint64_t), 0, PINNED_MEM); if (!coders->unPackSize) { QZ_ERROR("malloc error\n"); qzFree(coders->folders); qzFree(coders); return NULL; } for (int i = 0; i < coders->numFolders; ++i) { QzCatagory_T *cat = &(the_list->table->catas[i]); coders->unPackSize[i] = 0; for (int j = 0; j < cat->cat_files->total; ++j) { Qz7zFileItem_T *p = (Qz7zFileItem_T *)qzListGet(cat->cat_files, j); coders->unPackSize[i] += p->size; } } coders->unPackDigests = NULL; /* not used */ return coders; } Qz7zDigest_T *generateDigestInfo(QzListHead_T *head) { Qz7zDigest_T *digests = qzMalloc(sizeof(Qz7zDigest_T), 0, PINNED_MEM); if (!digests) { QZ_ERROR("malloc error\n"); return NULL; } digests->allAreDefined = 1; digests->numStreams = head->total; digests->numDefined = head->total; digests->crc = qzMalloc(digests->numDefined * sizeof(uint32_t), 0, PINNED_MEM); if (!digests->crc) { QZ_ERROR("malloc error\n"); qzFree(digests); return NULL; } for (int i = 0; i < digests->numDefined; ++i) { Qz7zFileItem_T *p = (Qz7zFileItem_T *)qzListGet(head, i); (digests->crc)[i] = p->crc; } return digests; } Qz7zSubstreamsInfo_T *generateSubstreamsInfo(Qz7zItemList_T *the_list) { int index_of_file = 0; // index of all files in the list Qz7zFileItem_T *fi; Qz7zSubstreamsInfo_T *substreamsInfo = qzMalloc(sizeof(Qz7zSubstreamsInfo_T), 0, PINNED_MEM); if (!substreamsInfo) { QZ_ERROR("malloc error\n"); return NULL; } memset(substreamsInfo, 0, sizeof(Qz7zSubstreamsInfo_T)); QzListHead_T *h = the_list->items[1]; uint64_t total_files = h->total; if (!total_files) { qzFree(substreamsInfo); return NULL; } substreamsInfo->numFolders = the_list->table->cat_num; substreamsInfo->numUnPackStreams = qzMalloc(substreamsInfo->numFolders * sizeof(uint64_t), 0, PINNED_MEM); if (!substreamsInfo->numUnPackStreams) { QZ_ERROR("malloc error\n"); qzFree(substreamsInfo); return NULL; } // n_files - n_folder if (total_files != 1) { substreamsInfo->unPackSize = qzMalloc((total_files - 1) * sizeof(uint64_t), 0, PINNED_MEM); if (!substreamsInfo->unPackSize) { QZ_ERROR("malloc error\n"); qzFree(substreamsInfo->numUnPackStreams); qzFree(substreamsInfo); return NULL; } } for (int i = 0; i < substreamsInfo->numFolders; ++i) { h = the_list->table->catas[i].cat_files; substreamsInfo->numUnPackStreams[i] = h->total; if (h->total == 1 || total_files == 1) continue; // folder has one file, don't need the unpacksize for (int j = 0; j < h->total - 1; ++j) { fi = qzListGet(h, j); substreamsInfo->unPackSize[index_of_file++] = fi->size; } } substreamsInfo->digests = generateDigestInfo(h); if (!substreamsInfo->digests) { QZ_ERROR("malloc error\n"); if (substreamsInfo->unPackSize) { qzFree(substreamsInfo->unPackSize); } qzFree(substreamsInfo->numUnPackStreams); qzFree(substreamsInfo); return NULL; } return substreamsInfo; } Qz7zFilesInfo_T *generateFilesInfo(Qz7zItemList_T *the_list) { Qz7zFilesInfo_T *filesInfo = qzMalloc(sizeof(Qz7zFilesInfo_T), 0, PINNED_MEM); if (!filesInfo) { QZ_ERROR("malloc error\n"); return NULL; } memset(filesInfo, 0, sizeof(Qz7zFilesInfo_T)); filesInfo->num = the_list->items[0]->total + the_list->items[1]->total; filesInfo->head[0] = the_list->items[0]; filesInfo->head[1] = the_list->items[1]; return filesInfo; } Qz7zStreamsInfo_T *generateStreamsInfo(Qz7zItemList_T *the_list, size_t compressed_size) { uint64_t n = the_list->items[1]->total; if (!n) return NULL; Qz7zStreamsInfo_T *streams = malloc(sizeof(Qz7zStreamsInfo_T)); CHECK_ALLOC_RETURN_VALUE(streams) streams->packInfo = generatePackInfo(the_list, compressed_size); streams->codersInfo = generateCodersInfo(the_list); streams->substreamsInfo = generateSubstreamsInfo(the_list); return streams; } Qz7zArchiveProperty_T *generatePropertyInfo() { Qz7zArchiveProperty_T *property = qzMalloc(sizeof(Qz7zArchiveProperty_T), 0, PINNED_MEM); if (!property) { QZ_ERROR("malloc error\n"); return NULL; } property->id = QZ7Z_PROPERTY_ID_INTEL7Z_1001; property->size = sizeof(g_property_data); property->data = malloc(property->size * sizeof(unsigned char)); CHECK_ALLOC_RETURN_VALUE(property->data) memcpy(property->data, g_property_data, property->size); property->next = NULL; return property; } Qz7zEndHeader_T *generateEndHeader(Qz7zItemList_T *the_list, size_t compressed_size) { Qz7zEndHeader_T *header = malloc(sizeof(Qz7zEndHeader_T)); CHECK_ALLOC_RETURN_VALUE(header) header->propertyInfo = generatePropertyInfo(); header->streamsInfo = generateStreamsInfo(the_list, compressed_size); header->filesInfo = generateFilesInfo(the_list); return header; } QzCatagoryTable_T *createCatagoryList() { QzCatagoryTable_T *cat_tbl; cat_tbl = malloc(sizeof(QzCatagoryTable_T)); CHECK_ALLOC_RETURN_VALUE(cat_tbl) cat_tbl->cat_num = sizeof(g_category_names) / sizeof(g_category_names[0]); cat_tbl->catas = malloc(cat_tbl->cat_num * sizeof(QzCatagory_T)); CHECK_ALLOC_RETURN_VALUE(cat_tbl->catas) // the last one for all other files for (int i = 0; i < cat_tbl->cat_num; ++i) { cat_tbl->catas[i].cat_id = i; cat_tbl->catas[i].cat_name = g_category_names[i]; cat_tbl->catas[i].cat_files = qzListCreate(1000); } return cat_tbl; } int getCatagory(QzCatagoryTable_T *tbl, Qz7zFileItem_T *p) { return 0; } /* * return 0 success * -1 failed */ int scanFilesIntoCatagory(Qz7zItemList_T *the_list) { int cat_index; QzListHead_T *files = the_list->items[1]; QzCatagory_T *cat = the_list->table->catas; for (int i = 0; i < files->total; ++i) { Qz7zFileItem_T *p = qzListGet(files, i); // decide the category for the fileitem cat_index = getCatagory(the_list->table, p); // add to the category list qzListAdd(cat[cat_index].cat_files, (void **)&p); } return 0; } int writeSignatureHeader(Qz7zSignatureHeader_T *header, FILE *fp) { size_t n; n = fwrite(header->signature, 1, sizeof(header->signature), fp); CHECK_FWRITE_RETURN(n, sizeof(header->signature)) n = fwrite(&header->majorVersion, 1, sizeof(header->majorVersion), fp); CHECK_FWRITE_RETURN(n, sizeof(header->majorVersion)) n = fwrite(&header->minorVersion, 1, sizeof(header->minorVersion), fp); CHECK_FWRITE_RETURN(n, sizeof(header->minorVersion)) n = fwrite(&header->startHeaderCRC, 1, sizeof(header->startHeaderCRC), fp); CHECK_FWRITE_RETURN(n, sizeof(header->startHeaderCRC)) n = fwrite(&header->nextHeaderOffset, 1, sizeof(header->nextHeaderOffset), fp); CHECK_FWRITE_RETURN(n, sizeof(header->nextHeaderOffset)) n = fwrite(&header->nextHeaderSize, 1, sizeof(header->nextHeaderSize), fp); CHECK_FWRITE_RETURN(n, sizeof(header->nextHeaderSize)) n = fwrite(&header->nextHeaderCRC, 1, sizeof(header->nextHeaderCRC), fp); CHECK_FWRITE_RETURN(n, sizeof(header->nextHeaderCRC)) return QZ7Z_OK; } /* * write property structure to file * if crc is not null, return the crc of the bytes that have written * return the bytes of written */ size_t writeArchiveProperties(Qz7zArchiveProperty_T *property, FILE *fp, uint32_t *crc) { size_t size; size_t total_size = 0; total_size += writeTag(PROPERTY_ID_ARCHIVE_PROPERTIES, fp, crc); total_size += writeNumber(property->id, fp, crc); total_size += writeNumber(property->size, fp, crc); size = fwrite(property->data, 1, property->size, fp); CHECK_FWRITE_RETURN(size, property->size) *crc = crc32(*crc, property->data, property->size); total_size += size; total_size += writeTag(PROPERTY_ID_END, fp, crc); return total_size; } size_t writePackInfo(Qz7zPackInfo_T *pack, FILE *fp, uint32_t *crc) { int i; size_t total_size = 0; total_size += writeTag(PROPERTY_ID_PACKINFO, fp, crc); total_size += writeNumber(pack->PackPos, fp, crc); total_size += writeNumber(pack->NumPackStreams, fp, crc); total_size += writeTag(PROPERTY_ID_SIZE, fp, crc); for (i = 0; i < pack->NumPackStreams; ++i) { total_size += writeNumber(pack->PackSize[i], fp, crc); } total_size += writeTag(PROPERTY_ID_END, fp, crc); return total_size; } size_t writeFolder(Qz7zFolderInfo_T *folder, FILE *fp, uint32_t *crc) { int i; size_t size; size_t total_size = 0; Qz7zCoder_T *coder = folder->coder_list; total_size += writeNumber(folder->numCoders, fp, crc); for (i = 0; i < folder->numCoders; ++i) { total_size += writeByte(coder->coderFirstByte.uc, fp, crc); size = fwrite(coder->codecID, sizeof(unsigned char), coder->coderFirstByte.st.CodecIdSize, fp); CHECK_FWRITE_RETURN(size, coder->coderFirstByte.st.CodecIdSize) total_size += size; *crc = crc32(*crc, coder->codecID, coder->coderFirstByte.st.CodecIdSize); } return total_size; } size_t writeCodersInfo(Qz7zCodersInfo_T *coders, FILE *fp, uint32_t *crc) { int i; size_t total_size = 0; total_size += writeTag(PROPERTY_ID_UNPACKINFO, fp, crc); total_size += writeTag(PROPERTY_ID_FOLDER, fp, crc); total_size += writeNumber(coders->numFolders, fp, crc); total_size += writeByte(0, fp, crc); // external = 0 for (i = 0; i < coders->numFolders; ++i) { total_size += writeFolder(&coders->folders[i], fp, crc); } total_size += writeTag(PROPERTY_ID_CODERS_UNPACK_SIZE, fp, crc); for (i = 0; i < coders->numFolders; ++i) { total_size += writeNumber(coders->unPackSize[i], fp, crc); } total_size += writeTag(PROPERTY_ID_END, fp, crc); return total_size; } size_t writeDigestInfo(Qz7zDigest_T *digest, FILE *fp, uint32_t *crc) { int i; size_t size; size_t total_size = 0; total_size += writeByte(digest->allAreDefined, fp, crc); for (i = 0; i < digest->numStreams; ++i) { size = fwrite(&digest->crc[i], sizeof(digest->crc[i]), 1, fp); CHECK_FWRITE_RETURN(size, 1) total_size += size * sizeof(digest->crc[i]); *crc = crc32(*crc, (unsigned char *)&digest->crc[i], sizeof(digest->crc[i])); } return total_size; } size_t writeSubstreamsInfo(Qz7zSubstreamsInfo_T *substreams, FILE *fp, uint32_t *crc) { int i, j; int total_index = 0; size_t total_size = 0; if (!substreams) return 0; total_size += writeTag(PROPERTY_ID_SUBSTREAMSINFO, fp, crc); total_size += writeTag(PROPERTY_ID_NUM_UNPACK_STREAM, fp, crc); for (i = 0; i < substreams->numFolders; ++i) { total_size += writeNumber(substreams->numUnPackStreams[i], fp, crc); } total_size += writeTag(PROPERTY_ID_SIZE, fp, crc); for (i = 0; i < substreams->numFolders; ++i) { for (j = 0; j < substreams->numUnPackStreams[i] - 1; ++j) { total_size += writeNumber(substreams->unPackSize[total_index++], fp, crc); } } total_size += writeTag(PROPERTY_ID_CRC, fp, crc); total_size += writeDigestInfo(substreams->digests, fp, crc); total_size += writeTag(PROPERTY_ID_END, fp, crc); return total_size; } size_t writeStreamsInfo(Qz7zStreamsInfo_T *streams, FILE *fp, uint32_t *crc) { size_t total_size = 0; if (!streams) return 0; total_size += writeTag(PROPERTY_ID_MAIN_STREAMSINFO, fp, crc); total_size += writePackInfo(streams->packInfo, fp, crc); total_size += writeCodersInfo(streams->codersInfo, fp, crc); total_size += writeSubstreamsInfo(streams->substreamsInfo, fp, crc); total_size += writeTag(PROPERTY_ID_END, fp, crc); return total_size; } static unsigned char *calculateEmptyStreamProperty(int m, int n, uint64_t *size) { unsigned char *res; unsigned char sum = 0; *size = (!((m + n) % 8)) ? (m + n) / 8 : (m + n) / 8 + 1; res = malloc(*size); CHECK_ALLOC_RETURN_VALUE(res) memset(res, 0, *size); int i, j = 0, k; for (i = 0; i < m / 8; ++i) { res[j++] = 0xff; } for (i = 0, k = 7; i < m % 8; ++i, --k) { sum += 1 << k; } res[j++] = sum; return res; } static unsigned char *calculateEmptyFileProperty(Qz7zFilesInfo_T *files, int m, uint64_t *size) { int i, j; *size = (!((m) % 8)) ? (m) / 8 : ((m) / 8 + 1); unsigned char *res = malloc(*size); CHECK_ALLOC_RETURN_VALUE(res) memset(res, 0, *size); int total_index = 0; for (i = 0; i < *size; ++i) { for (j = 7; j >= 0; --j) { Qz7zFileItem_T *p = qzListGet(files->head[0], total_index++); if (!p) { QZ_ERROR("Cannot get the file from list\n"); free(res); return NULL; } if (p->isEmpty) { QZ_DEBUG("%s is empty stream: i=%d j=%d\n", p->fileName, i, j); res[i] += 1 << j; } if (total_index == m) break; } } return res; } static unsigned char *genNamesPart(QzListHead_T *head_dir, QzListHead_T *head_file, uint64_t *size) { int i; int j; // for buf index int k; uint64_t n_dir = head_dir->total; uint64_t n_file = head_file->total; Qz7zFileItem_T *p; unsigned char *buf; int buf_len = 0; for (i = 0; i < n_dir; ++i) { p = (Qz7zFileItem_T *)qzListGet(head_dir, i); buf_len += 2 * (p->nameLength - p->baseNameLength); } for (i = 0; i < n_file; ++i) { p = (Qz7zFileItem_T *)qzListGet(head_file, i); buf_len += 2 * (p->nameLength - p->baseNameLength); } buf = malloc(buf_len + 1); CHECK_ALLOC_RETURN_VALUE(buf) k = 0; buf[k++] = 0; for (i = 0; i < n_dir; ++i) { p = (Qz7zFileItem_T *)qzListGet(head_dir, i); for (j = p->baseNameLength; j < p->nameLength; ++j) { buf[k++] = p->fileName[j]; buf[k++] = 0; } } for (i = 0; i < n_file; ++i) { p = (Qz7zFileItem_T *)qzListGet(head_file, i); for (j = p->baseNameLength; j < p->nameLength; ++j) { buf[k++] = p->fileName[j]; buf[k++] = 0; } } *size = k; return buf; } static uint32_t *genAttributes(QzListHead_T *head_dir, QzListHead_T *head_file) { int i; int k; uint64_t n_dir = head_dir->total; uint64_t n_file = head_file->total; Qz7zFileItem_T *p; uint32_t *buf; buf = malloc(sizeof(((Qz7zFileItem_T *)0)->attribute) * (n_dir + n_file)); CHECK_ALLOC_RETURN_VALUE(buf) k = 0; for (i = 0; i < n_dir; ++i) { p = (Qz7zFileItem_T *)qzListGet(head_dir, i); buf[k++] = p->attribute; } for (i = 0; i < n_file; ++i) { p = (Qz7zFileItem_T *)qzListGet(head_file, i); buf[k++] = p->attribute; } return buf; } static int checkZerobyteFiles(Qz7zFilesInfo_T *files) { Qz7zFileItem_T *pfile; int i; int n = files->head[0]->total; for (i = 0; i < n; ++i) { pfile = qzListGet(files->head[0], i); if (!pfile) { QZ_ERROR("Cannot get file from list\n"); exit(ERROR); } if (pfile->isEmpty) return 1; } return 0; } size_t writeFilesInfo(Qz7zFilesInfo_T *files, FILE *fp, uint32_t *crc) { int n_emptystream = files->head[0]->total; int n_file = files->head[1]->total; uint64_t size = 0; size_t ret_size; unsigned char *p; uint64_t total_size = 0; unsigned char *buf; uint32_t *attributes; int has_zerobyte_file = 0; total_size += writeTag(PROPERTY_ID_FILESINFO, fp, crc); total_size += writeNumber(files->num, fp, crc); total_size += writeTag(PROPERTY_ID_EMPTY_STREAM, fp, crc); p = calculateEmptyStreamProperty(n_emptystream, n_file, &size); total_size += writeNumber(size, fp, crc); ret_size = fwrite(p, 1, size, fp); CHECK_FWRITE_RETURN(size, ret_size) total_size += ret_size; *crc = crc32(*crc, p, size); free(p); p = NULL; has_zerobyte_file = checkZerobyteFiles(files); if (n_emptystream && has_zerobyte_file) { total_size += writeTag(PROPERTY_ID_EMPTY_FILE, fp, crc); p = calculateEmptyFileProperty(files, n_emptystream, &size); if (!p) { QZ_ERROR("Cannot calculate emptyfile property\n"); exit(ERROR); } total_size += writeNumber(size, fp, crc); ret_size = fwrite(p, 1, size, fp); CHECK_FWRITE_RETURN(size, ret_size) total_size += ret_size; *crc = crc32(*crc, p, size); free(p); p = NULL; } total_size += writeTag(PROPERTY_ID_DUMMY, fp, crc); total_size += writeNumber(2, fp, crc); total_size += writeByte(PROPERTY_CONTENT_DUMMY, fp, crc); total_size += writeByte(PROPERTY_CONTENT_DUMMY, fp, crc); total_size += writeTag(PROPERTY_ID_NAME, fp, crc); buf = genNamesPart(files->head[0], files->head[1], &size); total_size += writeNumber(size, fp, crc); ret_size = fwrite(buf, 1, size, fp); CHECK_FWRITE_RETURN(ret_size, size) total_size += ret_size; *crc = crc32(*crc, buf, size); free(buf); int i; Qz7zFileItem_T *pfile; FILETIME_T win_time; total_size += writeTag(PROPERTY_ID_MTIME, fp, crc); total_size += writeNumber((n_emptystream + n_file) * 8 + 2, fp, crc); total_size += writeTag(1, fp, crc); total_size += writeTag(0, fp, crc); for (i = 0; i < n_emptystream; ++i) { pfile = (Qz7zFileItem_T *)qzListGet(files->head[0], i); win_time = unixtimeToFiletime(pfile->mtime, pfile->mtime_nano); total_size += writeTime(win_time.low, fp, crc); total_size += writeTime(win_time.high, fp, crc); } for (i = 0; i < n_file; ++i) { pfile = (Qz7zFileItem_T *)qzListGet(files->head[1], i); win_time = unixtimeToFiletime(pfile->mtime, pfile->mtime_nano); total_size += writeTime(win_time.low, fp, crc); total_size += writeTime(win_time.high, fp, crc); } total_size += writeTag(PROPERTY_ID_ATTRIBUTES, fp, crc); attributes = genAttributes(files->head[0], files->head[1]); size = 2 + 4 * (n_emptystream + n_file); total_size += writeNumber(size, fp, crc); total_size += writeByte(FLAG_ATTR_DEFINED_SET, fp, crc); total_size += writeByte(FLAG_ATTR_EXTERNAL_UNSET, fp, crc); for (i = 0; i < n_emptystream + n_file; ++i) { total_size += writeTime(attributes[i], fp, crc); } free(attributes); total_size += writeTag(PROPERTY_ID_END, fp, crc); return total_size; } /** * return total size that has written */ size_t writeEndHeader(Qz7zEndHeader_T *header, FILE *fp, uint32_t *crc) { size_t total_size = 0; if (!crc) { QZ_ERROR("bad crc param\n"); return 0; } total_size += writeTag(PROPERTY_ID_HEADER, fp, crc); total_size += writeArchiveProperties(header->propertyInfo, fp, crc); total_size += writeStreamsInfo(header->streamsInfo, fp, crc); total_size += writeFilesInfo(header->filesInfo, fp, crc); total_size += writeTag(PROPERTY_ID_END, fp, crc); return total_size; } Qz7zItemList_T *itemListCreate(int n, char **files) { int i; uint32_t dir_index = 0; // the index of next processing directory in the dir list Qz7zFileItem_T *fi = NULL; DIR *dirp = NULL; char *dirc = NULL; char *absolute_path; char dir_name[PATH_MAX + 1] = {0}; char path[PATH_MAX]; Qz7zItemList_T *res = calloc(1, sizeof(Qz7zItemList_T)); if (!res) { QZ_ERROR("malloc error\n"); return NULL; } res->items[0] = qzListCreate(QZ_DIRLIST_DEFAULT_NUM_PER_NODE); res->items[1] = qzListCreate(QZ_FILELIST_DEFAULT_NUM_PER_NODE); QzListHead_T *dirs_head = res->items[0]; QZ_DEBUG("dirs_head : %p\n", (void *)dirs_head); QzListHead_T *files_head = res->items[1]; QZ_DEBUG("files_head : %p\n", (void *)files_head); for (i = 0; i < n; ++i) { #ifdef QZ7Z_DEBUG QZ_DEBUG("process %dth parameter: %s\n", i + 1, files[optind]); #endif absolute_path = realpath(files[optind], path); if (NULL == absolute_path) { goto error; } strncpy(dir_name, absolute_path, PATH_MAX); dirc = dirname(dir_name); fi = fileItemCreate(absolute_path); if (!fi) { QZ_ERROR("Cannot create file\n"); goto error; } if (strcmp(dirc, "/")) { fi->baseNameLength = strlen(dirc) + 1; } else { fi->baseNameLength = strlen(dirc); } if (fi->isDir || fi->isEmpty) { qzListAdd(dirs_head, (void **)&fi); // add it to directory list while (dir_index < dirs_head->total) { Qz7zFileItem_T *processing = (Qz7zFileItem_T *)qzListGet(dirs_head, dir_index); if (processing == NULL) { QZ_DEBUG("qzListGet got NULL!\n"); goto error; } QZ_DEBUG("processing: %s\n", processing->fileName); if (processing->isDir) { struct dirent *dentry; dirp = opendir(processing->fileName); if (!dirp) { QZ_ERROR("errors ocurs: %s \n", strerror(errno)); goto error; } while ((dentry = readdir(dirp))) { char file_path[PATH_MAX + 1]; memset(file_path, 0, PATH_MAX + 1); if (!strcmp(dentry->d_name, ".")) continue; if (!strcmp(dentry->d_name, "..")) continue; snprintf(file_path, sizeof file_path, "%s/%s", processing->fileName, dentry->d_name); QZ_DEBUG(" file_path: %s\n", file_path); Qz7zFileItem_T *anotherfile = fileItemCreate(file_path); if (!anotherfile) { QZ_ERROR("Cannot create file\n"); closedir(dirp); goto error; } if (strcmp(dirc, "/")) { anotherfile->baseNameLength = strlen(dirc) + 1; } else { anotherfile->baseNameLength = strlen(dirc); } if (anotherfile->isDir || anotherfile->isEmpty) { qzListAdd(dirs_head, (void **)&anotherfile); } else { qzListAdd(files_head, (void **)&anotherfile); } } closedir(dirp); } dir_index++; } } else { qzListAdd(files_head, (void **)&fi); } optind++; }// end for /* now the res->items has been resolved successfully */ res->table = createCatagoryList(); scanFilesIntoCatagory(res); return res; error: if (res) { itemListDestroy(res); } return NULL; } /** * return 1 if 7z archive is good, others if not */ int check7zArchive(const char *archive) { int sig_wrong; size_t n; unsigned char buf[8]; FILE *fp = fopen(archive, "r"); if (!fp) { perror(archive); return QZ7Z_ERR_OPEN; } n = fread(buf, 1, sizeof(buf), fp); if (n < sizeof(buf)) { fclose(fp); return -1; } if ((sig_wrong = memcmp(buf, g_header_signature, sizeof(g_header_signature)))) { QZ_ERROR("The archive signature header is broken\n"); fclose(fp); return QZ7Z_ERR_SIG_HEADER_BROKEN; } if (buf[6] != 0 || buf[7] != 4) { QZ_DEBUG("Warning: The 7z archive version is not 0.4\n"); QZ_DEBUG("Warning: Maybe has some issues for other version\n"); } fclose(fp); return 1; } /* * 1 if filename is dir, 0 if not */ int checkDirectory(const char *filename) { struct stat buf; stat(filename, &buf); if (S_ISDIR(buf.st_mode)) { return 1; } else { return 0; } } QATzip-1.2.0/utils/qzip_main.c000066400000000000000000000272611456106226300161720ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include "qzip.h" int main(int argc, char **argv) { int ret = QZ_OK; int arg_count; /* number of files or directories to process */ g_program_name = qzipBaseName(argv[0]); char *out_name = NULL; FILE *stream_out = NULL; int option_f = 0; Qz7zItemList_T *the_list; int is_good_7z = 0; int is_dir = 0; int recursive_mode = 0; errno = 0; int is_format_set = 0; char resolved_path[PATH_MAX]; while (true) { int optc; int long_idx = -1; char *stop = NULL; optc = getopt_long(argc, argv, g_short_opts, g_long_opts, &long_idx); if (optc < 0) { break; } switch (optc) { case 'd': g_decompress = 1; break; case 'h': help(); exit(OK); break; case 'k': g_keep = 1; break; case 'V': version(); exit(OK); break; case 'R': recursive_mode = 1; break; case 'A': if (strcmp(optarg, "deflate") == 0) { g_params_th.comp_algorithm = QZ_DEFLATE; } else if (strcmp(optarg, "lz4") == 0) { g_params_th.comp_algorithm = QZ_LZ4; } else if (strcmp(optarg, "lz4s") == 0) { g_params_th.comp_algorithm = QZ_LZ4s; } else if (strcmp(optarg, "zstd") == 0) { g_params_th.comp_algorithm = QZ_ZSTD; } else { QZ_ERROR("Error service arg: %s\n", optarg); return -1; } break; case 'H': if (strcmp(optarg, "static") == 0) { g_params_th.huffman_hdr = QZ_STATIC_HDR; } else if (strcmp(optarg, "dynamic") == 0) { g_params_th.huffman_hdr = QZ_DYNAMIC_HDR; } else { QZ_ERROR("Error huffman arg: %s\n", optarg); return -1; } break; case 'O': if (strcmp(optarg, "gzip") == 0) { g_params_th.data_fmt = QZIP_DEFLATE_GZIP; } else if (strcmp(optarg, "gzipext") == 0) { g_params_th.data_fmt = QZIP_DEFLATE_GZIP_EXT; } else if (strcmp(optarg, "7z") == 0) { g_params_th.data_fmt = QZIP_DEFLATE_RAW; } else if (strcmp(optarg, "deflate_4B") == 0) { g_params_th.data_fmt = QZIP_DEFLATE_4B; } else if (strcmp(optarg, "lz4") == 0) { g_params_th.data_fmt = QZIP_LZ4_FH; } else if (strcmp(optarg, "lz4s") == 0) { g_params_th.data_fmt = QZIP_LZ4S_BK; } else { QZ_ERROR("Error gzip header format arg: %s\n", optarg); return -1; } is_format_set = 1; break; case 'o': out_name = optarg; break; case 'L': g_params_th.comp_lvl = QZIP_GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); if (*stop != '\0' || ERANGE == errno || g_params_th.comp_lvl > QZ_DEFLATE_COMP_LVL_MAXIMUM || g_params_th.comp_lvl <= 0) { QZ_ERROR("Error compLevel arg: %s\n", optarg); return -1; } break; case 'C': g_params_th.hw_buff_sz = QZIP_GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); if (*stop != '\0' || ERANGE == errno || g_params_th.hw_buff_sz > USDM_ALLOC_MAX_SZ / 2) { printf("Error chunk size arg: %s\n", optarg); return -1; } break; case 'r': g_params_th.req_cnt_thrshold = QZIP_GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); if (*stop != '\0' || errno) { printf("Error request count threshold: %s\n", optarg); return -1; } break; case 'f': option_f = 1; break; case 'P': if (strcmp(optarg, "busy") == 0) { g_params_th.polling_mode = QZ_BUSY_POLLING; } else { printf("Error set polling mode: %s\n", optarg); return -1; } break; default: tryHelp(); } } arg_count = argc - optind; if (0 == arg_count && isatty(fileno((FILE *)stdin))) { help(); exit(OK); } if (g_decompress) { if (g_params_th.data_fmt == QZIP_LZ4S_BK) { QZ_ERROR("Don't support lz4s decompression.\n"); exit(ERROR); } g_params_th.direction = QZ_DIR_DECOMPRESS; } else { g_params_th.direction = QZ_DIR_COMPRESS; } if (0 == arg_count) { if (isatty(fileno((FILE *)stdout)) && 0 == option_f && 0 == g_decompress) { printf("qzip: compressed data not written to a terminal. " "Use -f to force compression.\n"); printf("For help, type: qzip -h\n"); } else { if (qatzipSetup(&g_sess, &g_params_th)) { fprintf(stderr, "qatzipSetup session failed\n"); exit(ERROR); } stream_out = stdout; stdout = freopen(NULL, "w", stdout); processStream(&g_sess, stdin, stream_out, g_decompress == 0); } } else if (g_params_th.data_fmt == QZIP_DEFLATE_RAW && !g_decompress) { //compress into 7z QZ_DEBUG("going to compress files into 7z archive ...\n"); if (!out_name) { QZ_ERROR("Should use '-o' to specify an output name\n"); help(); exit(ERROR); } if (qatzipSetup(&g_sess, &g_params_th)) { fprintf(stderr, "qatzipSetup session failed\n"); exit(ERROR); } for (int i = 0, j = optind; i < arg_count; ++i, ++j) { if (access(argv[j], F_OK)) { QZ_ERROR("%s: No such file or directory\n", argv[j]); exit(ERROR); } } the_list = itemListCreate(arg_count, argv); if (!the_list) { exit(ERROR); } ret = qz7zCompress(&g_sess, the_list, out_name); itemListDestroy(the_list); } else { // decompress from 7z; compress into gz; decompress from gz while (optind < argc) { /* To avoid CWE-22: Improper Limitation of a Pathname to a Restricted Directory * ('Path Traversal') attacks. * http://cwe.mitre.org/data/definitions/22.html */ if (!realpath(argv[optind], resolved_path)) { QZ_ERROR("%s: No such file or directory\n", argv[optind]); exit(ERROR); } QzSuffix_T suffix = getSuffix(argv[optind]); is_dir = checkDirectory(argv[optind]); if (g_decompress && !is_dir) { QzSuffixCheckStatus_T check_res = checkSuffix(suffix, is_format_set); if (E_CHECK_SUFFIX_UNSUPPORT == check_res) { QZ_ERROR("Error: %s: Wrong suffix. Supported suffix: 7z/gz/lz4.\n", argv[optind]); exit(ERROR); } if (E_CHECK_SUFFIX_FORMAT_UNMATCH == check_res) { QZ_ERROR("Error: %s: Suffix is not matched with format\n", argv[optind]); exit(ERROR); } } if (qatzipSetup(&g_sess, &g_params_th)) { fprintf(stderr, "qatzipSetup session failed\n"); exit(ERROR); } if (g_decompress) { if (!recursive_mode) { if (suffix == E_SUFFIX_7Z) { is_good_7z = check7zArchive(argv[optind]); if (is_good_7z < 0) { exit(ERROR); } if (arg_count > 1) { fprintf(stderr, "only support decompressing ONE 7z " "archive for ONE command!\n"); exit(ERROR); } QZ_DEBUG(" this is a 7z archive, " "going to decompress ... \n"); g_params_th.data_fmt = QZIP_DEFLATE_RAW; if (qatzipSetup(&g_sess, &g_params_th)) { fprintf(stderr, "qatzipSetup session failed\n"); exit(ERROR); } ret = qz7zDecompress(&g_sess, argv[optind++]); } else if (suffix == E_SUFFIX_GZ) { processFile(&g_sess, argv[optind++], out_name, g_decompress == 0); } else if (suffix == E_SUFFIX_LZ4) { if (g_params_th.data_fmt != QZIP_LZ4_FH) { QZ_ERROR("Error: Suffix(.lz4) doesn't match the data format," "please confirm the data format\n"); exit(ERROR); } processFile(&g_sess, argv[optind++], out_name, g_decompress == 0); } else { QZ_ERROR("Error: %s: Wrong suffix. Supported suffix: " "7z/gz/lz4.\n", argv[optind]); exit(ERROR); } } else { processFile(&g_sess, argv[optind++], out_name, g_decompress == 0); } } else { // compress processFile(&g_sess, argv[optind++], out_name, g_decompress == 0); } } } if (qatzipClose(&g_sess)) { exit(ERROR); } return ret; } QATzip-1.2.0/utils/qzstd.c000066400000000000000000000433561456106226300153530ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2021-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include "qzstd.h" QzSession_T qzstd_g_sess; QzSessionParamsLZ4S_T g_sess_params = {{0}}; QzSessionParamsLZ4S_T sess_params_zstd_default = { .common_params.direction = QZ_DIR_COMPRESS, .common_params.comp_lvl = QZ_COMP_LEVEL_DEFAULT, .common_params.comp_algorithm = QZ_LZ4s, .common_params.max_forks = QZ_MAX_FORK_DEFAULT, .common_params.sw_backup = QZ_SW_BACKUP_DEFAULT, .common_params.hw_buff_sz = QZ_HW_BUFF_SZ, .common_params.strm_buff_sz = QZ_STRM_BUFF_SZ_DEFAULT, .common_params.input_sz_thrshold = QZ_COMP_THRESHOLD_DEFAULT, .common_params.req_cnt_thrshold = 32, .common_params.wait_cnt_thrshold = QZ_WAIT_CNT_THRESHOLD_DEFAULT, .common_params.polling_mode = QZ_PERIODICAL_POLLING, .lz4s_mini_match = 3, .qzCallback = zstdCallBack, .qzCallback_external = NULL }; static unsigned int LZ4MINMATCH = 2; void qzstd_help() { static char const *const help_msg[] = { "Compress or uncompress a file with zstandard format.", "", " -d, decompress", " -h, show help information", " -L, set compression level of QAT", " -o, set output file name", " -C, set zstd block size && QAT hw buffer size", " -r, set max in-flight request number", " -P, set polling mode, only supports busy polling settings", " -m, set the mini match size for the lz4s search algorithm, \ only support mini_match 3 and 4", "", "Only support one input file.", 0 }; char const *const *p = help_msg; while (*p) { printf("%s\n", *p++); } } static double get_time_diff(struct timeval time_e, struct timeval time_s) { unsigned long us_begin = time_s.tv_sec * 1000000 + time_s.tv_usec; unsigned long us_end = time_e.tv_sec * 1000000 + time_e.tv_usec; return us_end - us_begin; } unsigned qzstd_isLittleEndian(void) { const union { U32 u; BYTE c[4]; } one = {1}; /* don't use static : performance detrimental */ return one.c[0]; } static U16 qzstd_read16(const void *memPtr) { U16 val; memcpy(&val, memPtr, sizeof(val)); return val; } U16 qzstd_readLE16(const void *memPtr) { if (qzstd_isLittleEndian()) { return qzstd_read16(memPtr); } else { const BYTE *p = (const BYTE *)memPtr; return (U16)((U16)p[0] + (p[1] << 8)); } } void decLz4Block(unsigned char *lz4s, int lz4sSize, ZSTD_Sequence *zstdSeqs, unsigned int *seq_offset) { unsigned char *ip = lz4s; unsigned char *endip = lz4s + lz4sSize; while (ip < endip && lz4sSize > 0) { size_t length = 0; size_t offset = 0; unsigned int literalLen = 0, matchlen = 0; /* get literal length */ unsigned const token = *ip++; if ((length = (token >> ML_BITS)) == RUN_MASK) { unsigned s; do { s = *ip++; length += s; } while (s == 255); } literalLen = (unsigned short)length; ip += length; if (ip == endip) { // Meet the end of the LZ4 sequence /* update ZSTD_Sequence */ zstdSeqs[*seq_offset].litLength += literalLen; continue; } /* get matchPos */ offset = qzstd_readLE16(ip); ip += 2; /* get match length */ length = token & ML_MASK; if (length == ML_MASK) { unsigned s; do { s = *ip++; length += s; } while (s == 255); } if (length != 0) { length += LZ4MINMATCH; matchlen = (unsigned short)length; /* update ZSTD_Sequence */ zstdSeqs[*seq_offset].offset = offset; zstdSeqs[*seq_offset].litLength += literalLen; zstdSeqs[*seq_offset].matchLength = matchlen; ++(*seq_offset); assert(*seq_offset <= ZSTD_SEQUENCES_SIZE); } else { if (literalLen > 0) { /* When match length is 0, the literalLen needs to be temporarily stored and processed together with the next data block. If also ip == endip, need to convert sequences to seqStore.*/ zstdSeqs[*seq_offset].litLength += literalLen; } } } assert(ip == endip); } inline int getLz4FrameHeaderSz() { return QZ_LZ4_HEADER_SIZE; } inline int getLz4BlkHeaderSz() { return QZ_LZ4_BLK_HEADER_SIZE; } inline int getLZ4FooterSz() { return QZ_LZ4_FOOTER_SIZE; } int getContentSize(unsigned char *const ptr) { QzLZ4H_T *hdr = NULL; hdr = (QzLZ4H_T *)ptr; assert(hdr->magic == QZ_LZ4_MAGIC); return hdr->cnt_size; } unsigned int getBlockSize(unsigned char *const ptr) { unsigned int blk_sz = *(unsigned int *)ptr; return blk_sz; } int zstdCallBack(void *external, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, int *ExtStatus) { int ret = QZ_OK; //copied data is used to decode //original data will be overwrote by ZSTD_compressSequences unsigned char *dest_data = (unsigned char *)malloc(*dest_len); assert(dest_data != NULL); memcpy(dest_data, dest, *dest_len); unsigned char *cur = dest_data; unsigned char *end = dest_data + *dest_len; ZSTD_Sequence *zstd_seqs = (ZSTD_Sequence *)calloc(ZSTD_SEQUENCES_SIZE, sizeof(ZSTD_Sequence)); assert(zstd_seqs != NULL); ZSTD_CCtx *zc = (ZSTD_CCtx *)external; unsigned int produced = 0; unsigned int consumed = 0; unsigned int cnt_sz = 0, blk_sz = 0; //content size and block size unsigned int dec_offset = 0; while (cur < end && *dest_len > 0) { //decode block header and get block size blk_sz = getBlockSize(cur); cur += getLz4BlkHeaderSz(); //decode lz4s sequences into zstd sequences decLz4Block(cur, blk_sz, zstd_seqs, &dec_offset); cur += blk_sz; cnt_sz = 0; for (unsigned int i = 0; i < dec_offset + 1 ; i++) { cnt_sz += (zstd_seqs[i].litLength + zstd_seqs[i].matchLength) ; } assert(cnt_sz <= MAX_BLOCK_SIZE); // compress sequence to zstd frame int compressed_sz = ZSTD_compressSequences(zc, dest + produced, ZSTD_compressBound(cnt_sz), zstd_seqs, dec_offset + 1, src + consumed, cnt_sz); if (compressed_sz < 0) { ret = QZ_POST_PROCESS_ERROR; *ExtStatus = compressed_sz; QZ_ERROR("%s : ZSTD API ZSTD_compressSequences failed with error code, %d, %s\n", ZSTD_ERROR_TYPE, *ExtStatus, DECODE_ZSTD_ERROR_CODE(*ExtStatus)); goto done; } //reuse zstd_seqs memset(zstd_seqs, 0, ZSTD_SEQUENCES_SIZE * sizeof(ZSTD_Sequence)); dec_offset = 0; produced += compressed_sz; consumed += cnt_sz; } *dest_len = produced; done: free(dest_data); free(zstd_seqs); return ret; } int qzZstdGetDefaults(QzSessionParamsLZ4S_T *defaults) { if (defaults == NULL) { QZ_ERROR("%s : QzSessionParams ptr is empty\n", QZSTD_ERROR_TYPE); return QZSTD_ERROR; } QZ_MEMCPY(defaults, &sess_params_zstd_default, sizeof(QzSessionParamsLZ4S_T), sizeof(QzSessionParamsLZ4S_T)); return QZSTD_OK; } int compressFile(int in_file, int out_file) { long input_file_size = 0; long output_file_size = 0; unsigned int src_buffer_size = 0; unsigned int dst_buffer_size = 0; unsigned int max_dst_buffer_size = 0; unsigned char *src_buffer = NULL; unsigned char *dst_buffer = NULL; unsigned int block_size = ZSRC_BUFF_LEN; long file_remaining = 0; unsigned int bytes_read = 0; int rc = QZSTD_OK; int is_compress = 1; uint64_t callback_error_code = 0; //initial zstd context ZSTD_CCtx *zc = ZSTD_createCCtx(); if (zc == NULL) { QZ_ERROR("%s : ZSTD_createCCtx failed\n", QZSTD_ERROR_TYPE); return QZSTD_ERROR; } ZSTD_CCtx_setParameter(zc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters); g_sess_params.qzCallback_external = (void *)zc; /* Different mini_match would use different LZ4MINMATCH to decode * lz4s sequence. note that when it is mini_match is 4, the LZ4MINMATCH * should be 3. if mini match is 3, then LZ4MINMATCH should be 2*/ LZ4MINMATCH = g_sess_params.lz4s_mini_match == 4 ? 3 : 2; /* Align zstd minmatch to the QAT minmatch */ ZSTD_CCtx_setParameter( zc, ZSTD_c_minMatch, g_sess_params.lz4s_mini_match >= 4 ? 4 : 3 ); //setup session int ret = qzInit(&qzstd_g_sess, g_sess_params.common_params.sw_backup); if (ret != QZ_OK && ret != QZ_DUPLICATE) { QZ_ERROR("%s : qzInit failed with error code %d\n", QZ_ERROR_TYPE, ret); return QZSTD_ERROR; } ret = qzSetupSessionLZ4S(&qzstd_g_sess, &g_sess_params); if (ret != QZ_OK) { QZ_ERROR("%s : qzSetupSession failed with error code %d\n", QZ_ERROR_TYPE, ret); return QZSTD_ERROR; } //get input file size input_file_size = lseek(in_file, 0, SEEK_END); lseek(in_file, 0, SEEK_SET); src_buffer_size = (input_file_size > block_size) ? block_size : input_file_size; int max_zstd_sz = ZSTD_compressBound(src_buffer_size); int max_lz4_sz = LZ4_compressBound(src_buffer_size); max_dst_buffer_size = (max_zstd_sz > max_lz4_sz) ? max_zstd_sz * 2 : max_lz4_sz * 2; src_buffer = malloc(src_buffer_size); assert(src_buffer != NULL); dst_buffer = malloc(max_dst_buffer_size); assert(dst_buffer != NULL); file_remaining = input_file_size; struct timeval time_s; struct timeval time_e; double time = 0.0f; do { bytes_read = read(in_file, src_buffer, src_buffer_size); QZ_PRINT("Reading input file (%u Bytes)\n", bytes_read); puts("compressing..."); dst_buffer_size = max_dst_buffer_size; gettimeofday(&time_s, NULL); if (bytes_read < g_sess_params.common_params.input_sz_thrshold) { //goto sw compress dst_buffer_size = ZSTD_compressCCtx(zc, dst_buffer, dst_buffer_size, src_buffer, bytes_read, 1); if ((int)dst_buffer_size <= 0) { QZ_ERROR("%s : ZSTD API ZSTD_compressCCtx failed with error code, %d, %s\n", ZSTD_ERROR_TYPE, dst_buffer_size, DECODE_ZSTD_ERROR_CODE(dst_buffer_size)); rc = QZSTD_ERROR; goto done; } } else { //compress by qat int ret = qzCompressExt(&qzstd_g_sess, src_buffer, (unsigned int *)(&bytes_read), dst_buffer, &dst_buffer_size, 1, &callback_error_code); if (QZ_BUF_ERROR == ret && 0 != bytes_read) { if (-1 == lseek(in_file, bytes_read - src_buffer_size, SEEK_CUR)) { QZ_ERROR("%s : failed to re-seek input file\n", QZSTD_ERROR_TYPE); rc = QZSTD_ERROR; goto done; } } else if (QZ_POST_PROCESS_ERROR == ret) { QZ_ERROR("%s : ZSTD API ZSTD_compressSequences failed with error code, %d, %s\n", ZSTD_ERROR_TYPE, ret, DECODE_ZSTD_ERROR_CODE((size_t)callback_error_code)); rc = QZSTD_ERROR; goto done; } else if (QZ_OK != ret) { QZ_ERROR("%s : qzCompress failed with error code %d\n", QZ_ERROR_TYPE, ret); rc = QZSTD_ERROR; goto done; } } gettimeofday(&time_e, NULL); time += get_time_diff(time_e, time_s); size_t write_size = write(out_file, dst_buffer, dst_buffer_size); if (write_size != dst_buffer_size) { QZ_ERROR("%s : failed to write output data into file\n", QZSTD_ERROR_TYPE); rc = QZSTD_ERROR; goto done; } output_file_size += write_size; file_remaining -= bytes_read; src_buffer_size = (src_buffer_size < file_remaining) ? src_buffer_size : file_remaining; } while (file_remaining > 0); QzstdDisplayStats(time, input_file_size, output_file_size, is_compress); done: //release resource if (zc != NULL) { ZSTD_freeCCtx(zc); } free(src_buffer); free(dst_buffer); qzTeardownSession(&qzstd_g_sess); qzClose(&qzstd_g_sess); return rc; } int decompressFile(int in_file, int out_file) { long input_file_size = 0; long output_file_size = 0; size_t src_buffer_size = ZSTD_DStreamInSize(); size_t dst_buffer_size = ZSTD_DStreamOutSize(); unsigned char *src_buffer = NULL; unsigned char *dst_buffer = NULL; int rc = QZSTD_OK; int is_compress = 0; struct timeval time_s; struct timeval time_e; double time = 0.0f; //get input file size input_file_size = lseek(in_file, 0, SEEK_END); lseek(in_file, 0, SEEK_SET); src_buffer = malloc(src_buffer_size); assert(src_buffer != NULL); dst_buffer = malloc(dst_buffer_size); assert(dst_buffer != NULL); ZSTD_DCtx *zstd_dctx = ZSTD_createDCtx(); assert(zstd_dctx != NULL); size_t bytes_read = 0; size_t bytes_write = 0; long file_remaining = 0; file_remaining = input_file_size; int ret = 0; do { bytes_read = read(in_file, src_buffer, src_buffer_size); QZ_PRINT("Reading input file (%lu Bytes)\n", bytes_read); puts("Decompressing..."); ZSTD_inBuffer input = { src_buffer, bytes_read, 0 }; while (input.pos < input.size) { ZSTD_outBuffer output = { dst_buffer, dst_buffer_size, 0 }; gettimeofday(&time_s, NULL); ret = ZSTD_decompressStream(zstd_dctx, &output, &input); if (ret < 0) { QZ_ERROR("%s : ZSTD API ZSTD_decompressStream failed with error code, %d, %s\n", ZSTD_ERROR_TYPE, ret, DECODE_ZSTD_ERROR_CODE(ret)); rc = QZSTD_ERROR; goto done; } gettimeofday(&time_e, NULL); time += get_time_diff(time_e, time_s); bytes_write = write(out_file, dst_buffer, output.pos); output_file_size += bytes_write; } file_remaining -= bytes_read; src_buffer_size = (src_buffer_size < file_remaining) ? src_buffer_size : file_remaining; } while (file_remaining > 0); if (ret != 0) { QZ_ERROR("%s : ZSTD API ZSTD_decompressStream failed with error code, %d, %s\n", ZSTD_ERROR_TYPE, ret, DECODE_ZSTD_ERROR_CODE(ret)); rc = QZSTD_ERROR; goto done; } QzstdDisplayStats(time, input_file_size, output_file_size, is_compress); done: ZSTD_freeDCtx(zstd_dctx); free(src_buffer); free(dst_buffer); return rc; } void QzstdDisplayStats(double time, off_t insize, off_t outsize, int is_compress) { if (insize && outsize) { assert(0 != time); double size = (is_compress) ? insize : outsize; double throughput = (size * CHAR_BIT) / time; /* in MB (megabytes) */ double compressionRatio = ((double)insize) / ((double)outsize); double spaceSavings = 1 - ((double)outsize) / ((double)insize); QZ_PRINT("Time taken: %9.3lf ms\n", time / 1000); QZ_PRINT("Throughput: %9.3lf Mbit/s\n", throughput); if (is_compress) { QZ_PRINT("Space Savings: %9.3lf %%\n", spaceSavings * 100.0); QZ_PRINT("Compression ratio: %.3lf : 1\n", compressionRatio); } } } QATzip-1.2.0/utils/qzstd.h000066400000000000000000000107241456106226300153510ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2021-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifndef _UTILS_QZSTD_H #define _UTILS_QZSTD_H #define ZSTD_STATIC_LINKING_ONLY #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_QAT_HEADERS #include #else #include #endif #include /* For qzstd app, there are three types of return errors. * 1. The errors are from top layer software stack * e.g read/write file and app input parameter error. * 2. The errors are from qatzip lib. * e.g QZ_DUPLICATE or QZ_NOSW_NO_HW, error code defined * in qatzip.h * 3. The errors come from zstd lib. * e.g ZSTD_ErrorCode list. error code defined in zstd_error.h * * Note: * Because different type of error may have the same error code * value, To avoid app return value confusion in shell. Use * QZ_ERROR function to print error type and error code. */ // app return status #define QZSTD_OK 0 #define QZSTD_ERROR 1 // Error type for log capture. #define QZSTD_ERROR_TYPE "[QZSTD_ERROR]" #define QZ_ERROR_TYPE "[QZ_LIB_ERROR]" #define ZSTD_ERROR_TYPE "[ZSTD_LIB_ERROR]" #define KB (1024) #define MB (KB * KB) #define ZSTD_SEQUENCES_SIZE (1024 * 32) #define ML_BITS 4 #define ML_MASK ((1U << ML_BITS) - 1) #define RUN_BITS (8 - ML_BITS) #define RUN_MASK ((1U << RUN_BITS) - 1) typedef uint8_t BYTE; typedef uint16_t U16; typedef int16_t S16; typedef uint32_t U32; typedef int32_t S32; typedef uint64_t U64; typedef int64_t S64; #define QATZIP_MAX_HW_SZ (512 * KB) #define ZSRC_BUFF_LEN (512 * MB) #define MAX_BLOCK_SIZE (128 * KB) #define DECODE_ZSTD_ERROR_CODE(error_code) \ ZSTD_getErrorString(ZSTD_getErrorCode((size_t)error_code)) void QzstdDisplayStats(double time, off_t insize, off_t outsize, int is_compress); void qzstd_help(); void decLz4Block(unsigned char *lz4s, int lz4sSize, ZSTD_Sequence *zstdSeqs, unsigned int *seq_offset); int qzZstdGetDefaults(QzSessionParamsLZ4S_T *defaults); int compressFile(int in_file, int out_file); int decompressFile(int in_file, int out_file); int zstdCallBack(void *external, const unsigned char *src, unsigned int *src_len, unsigned char *dest, unsigned int *dest_len, int *ExtStatus); int getLz4FrameHeaderSz(); int getLz4BlkHeaderSz(); int getLZ4FooterSz(); int getContentSize(unsigned char *const ptr); unsigned int getBlockSize(unsigned char *const ptr); #endif QATzip-1.2.0/utils/qzstd_main.c000066400000000000000000000157271456106226300163600ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2021-2024 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ /* sample zstd-qat application */ #include #include #include #include #include #include #include "qzstd.h" extern QzSessionParamsLZ4S_T g_sess_params; int main(int argc, char **argv) { int decompress = 0; struct stat in_file_state; char out_path [PATH_MAX] = {0}; char in_path[PATH_MAX] = {0}; char *out_filename = NULL; char *in_filename = NULL; int in_file = -1; int out_file = -1; char *tmp = NULL; char *suffix = NULL; if (qzZstdGetDefaults(&g_sess_params) != QZ_OK) { return QZSTD_ERROR; } const char *optPatten = "dhC:L:o:r:P:m:"; char *stop = NULL; int ch; while ((ch = getopt(argc, argv, optPatten)) >= 0) { switch (ch) { case 'd': decompress = 1; break; case 'C': g_sess_params.common_params.hw_buff_sz = GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); // make sure chunk size smaller than 128kB to fit zstd block size limitation. if (g_sess_params.common_params.hw_buff_sz > 128 * KB) { QZ_ERROR("%s : block size can't bigger than 128 KB\n", QZSTD_ERROR_TYPE); return QZSTD_ERROR; } break; case 'h': qzstd_help(); return QZSTD_OK; case 'L': g_sess_params.common_params.comp_lvl = GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); break; case 'o': out_filename = optarg; break; case 'r': g_sess_params.common_params.req_cnt_thrshold = GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); break; case 'P': if (strcmp(optarg, "busy") == 0) { g_sess_params.common_params.polling_mode = QZ_BUSY_POLLING; } else { QZ_ERROR("%s : set wrong polling mode: %s\n", QZSTD_ERROR_TYPE, optarg); return QZSTD_ERROR; } break; case 'm': g_sess_params.lz4s_mini_match = GET_LOWER_32BITS(strtoul(optarg, &stop, 0)); if (g_sess_params.lz4s_mini_match != 3 && g_sess_params.lz4s_mini_match != 4) { QZ_ERROR("%s : mini_match can only set 3 or 4!\n", QZSTD_ERROR_TYPE); return QZSTD_ERROR; } break; default: qzstd_help(); return QZSTD_OK; } } int arg_count = argc - optind; if (arg_count == 0 || arg_count > 1) { QZ_ERROR("%s : only support one file as input\n", QZSTD_ERROR_TYPE); return QZSTD_ERROR; } /* argv[optind] is the input file name, need to check the input filename */ in_filename = argv[optind]; in_filename = realpath(in_filename, in_path); if (!in_filename) { QZ_ERROR("Please check input file name %s\n", in_filename); return QZSTD_ERROR; } /* * For compression, if the output file name is not be specified * we need to suffix the input filename with .zst as the output filename */ if (!decompress && !out_filename) { tmp = strrchr(in_filename, '/'); assert(tmp); strncpy(out_path, tmp + 1, PATH_MAX - 1); strcat(out_path, ".zst"); out_filename = &out_path[0]; } /* check the input filename suffix for decompression, * if output file name is not specified, we need to unsuffix the * input filename as the output filename */ if (decompress) { suffix = strrchr(in_filename, '.'); if (suffix == NULL) { QZ_ERROR("%s : unsupported file format\n", QZSTD_ERROR_TYPE); return QZSTD_ERROR; } if (strcmp(suffix, ".zst")) { QZ_ERROR("%s : unsupported file format\n", QZSTD_ERROR_TYPE); return QZSTD_ERROR; } if (!out_filename) { tmp = strrchr(in_filename, '/'); assert(tmp); strncpy(out_path, tmp + 1, PATH_MAX - 1); suffix = strrchr(out_path, '.'); assert(suffix); suffix[0] = '\0'; out_filename = &out_path[0]; } } in_file = open(in_filename, O_RDONLY); if (in_file < 0) { perror("Cannot open input file"); return QZSTD_ERROR; } if (fstat(in_file, &in_file_state)) { perror("Cannot get file stat"); close(in_file); return QZSTD_ERROR; } out_file = open(out_filename, O_CREAT | O_WRONLY, in_file_state.st_mode); if (out_file == -1) { perror("Cannot open output file"); close(in_file); return QZSTD_ERROR; } if (!decompress) { int rc = compressFile(in_file, out_file); if (rc != QZSTD_OK) { close(in_file); close(out_file); return QZSTD_ERROR; } } else { int rc = decompressFile(in_file, out_file); if (rc != QZSTD_OK) { close(in_file); close(out_file); return QZSTD_ERROR; } } close(in_file); close(out_file); return QZSTD_OK; }